EmulateInstructionARM.cpp revision 269024
1312303Sngie//===-- EmulateInstructionARM.cpp -------------------------------*- C++ -*-===// 2312303Sngie// 3312303Sngie// The LLVM Compiler Infrastructure 4312303Sngie// 5312303Sngie// This file is distributed under the University of Illinois Open Source 6312303Sngie// License. See LICENSE.TXT for details. 7312303Sngie// 8312303Sngie//===----------------------------------------------------------------------===// 9312303Sngie 10312303Sngie#include <stdlib.h> 11312303Sngie 12312303Sngie#include "EmulateInstructionARM.h" 13312303Sngie#include "EmulationStateARM.h" 14312303Sngie#include "lldb/Core/ArchSpec.h" 15312303Sngie#include "lldb/Core/Address.h" 16312303Sngie#include "lldb/Core/ConstString.h" 17312303Sngie#include "lldb/Core/PluginManager.h" 18312303Sngie#include "lldb/Core/Stream.h" 19312303Sngie#include "lldb/Interpreter/OptionValueArray.h" 20312303Sngie#include "lldb/Interpreter/OptionValueDictionary.h" 21312303Sngie#include "lldb/Symbol/UnwindPlan.h" 22312303Sngie 23312303Sngie#include "Plugins/Process/Utility/ARMDefines.h" 24312303Sngie#include "Plugins/Process/Utility/ARMUtils.h" 25312303Sngie#include "Utility/ARM_DWARF_Registers.h" 26312303Sngie 27312303Sngie#include "llvm/Support/MathExtras.h" // for SignExtend32 template function 28312303Sngie // and countTrailingZeros function 29312303Sngie 30312303Sngieusing namespace lldb; 31312303Sngieusing namespace lldb_private; 32312303Sngie 33312303Sngie// Convenient macro definitions. 34312303Sngie#define APSR_C Bit32(m_opcode_cpsr, CPSR_C_POS) 35312303Sngie#define APSR_V Bit32(m_opcode_cpsr, CPSR_V_POS) 36313404Sngie 37#define AlignPC(pc_val) (pc_val & 0xFFFFFFFC) 38 39//---------------------------------------------------------------------- 40// 41// ITSession implementation 42// 43//---------------------------------------------------------------------- 44 45// A8.6.50 46// Valid return values are {1, 2, 3, 4}, with 0 signifying an error condition. 47static uint32_t 48CountITSize (uint32_t ITMask) { 49 // First count the trailing zeros of the IT mask. 50 uint32_t TZ = llvm::countTrailingZeros(ITMask); 51 if (TZ > 3) 52 { 53#ifdef LLDB_CONFIGURATION_DEBUG 54 printf("Encoding error: IT Mask '0000'\n"); 55#endif 56 return 0; 57 } 58 return (4 - TZ); 59} 60 61// Init ITState. Note that at least one bit is always 1 in mask. 62bool ITSession::InitIT(uint32_t bits7_0) 63{ 64 ITCounter = CountITSize(Bits32(bits7_0, 3, 0)); 65 if (ITCounter == 0) 66 return false; 67 68 // A8.6.50 IT 69 unsigned short FirstCond = Bits32(bits7_0, 7, 4); 70 if (FirstCond == 0xF) 71 { 72#ifdef LLDB_CONFIGURATION_DEBUG 73 printf("Encoding error: IT FirstCond '1111'\n"); 74#endif 75 return false; 76 } 77 if (FirstCond == 0xE && ITCounter != 1) 78 { 79#ifdef LLDB_CONFIGURATION_DEBUG 80 printf("Encoding error: IT FirstCond '1110' && Mask != '1000'\n"); 81#endif 82 return false; 83 } 84 85 ITState = bits7_0; 86 return true; 87} 88 89// Update ITState if necessary. 90void ITSession::ITAdvance() 91{ 92 //assert(ITCounter); 93 --ITCounter; 94 if (ITCounter == 0) 95 ITState = 0; 96 else 97 { 98 unsigned short NewITState4_0 = Bits32(ITState, 4, 0) << 1; 99 SetBits32(ITState, 4, 0, NewITState4_0); 100 } 101} 102 103// Return true if we're inside an IT Block. 104bool ITSession::InITBlock() 105{ 106 return ITCounter != 0; 107} 108 109// Return true if we're the last instruction inside an IT Block. 110bool ITSession::LastInITBlock() 111{ 112 return ITCounter == 1; 113} 114 115// Get condition bits for the current thumb instruction. 116uint32_t ITSession::GetCond() 117{ 118 if (InITBlock()) 119 return Bits32(ITState, 7, 4); 120 else 121 return COND_AL; 122} 123 124// ARM constants used during decoding 125#define REG_RD 0 126#define LDM_REGLIST 1 127#define SP_REG 13 128#define LR_REG 14 129#define PC_REG 15 130#define PC_REGLIST_BIT 0x8000 131 132#define ARMv4 (1u << 0) 133#define ARMv4T (1u << 1) 134#define ARMv5T (1u << 2) 135#define ARMv5TE (1u << 3) 136#define ARMv5TEJ (1u << 4) 137#define ARMv6 (1u << 5) 138#define ARMv6K (1u << 6) 139#define ARMv6T2 (1u << 7) 140#define ARMv7 (1u << 8) 141#define ARMv7S (1u << 9) 142#define ARMv8 (1u << 10) 143#define ARMvAll (0xffffffffu) 144 145#define ARMV4T_ABOVE (ARMv4T|ARMv5T|ARMv5TE|ARMv5TEJ|ARMv6|ARMv6K|ARMv6T2|ARMv7|ARMv7S|ARMv8) 146#define ARMV5_ABOVE (ARMv5T|ARMv5TE|ARMv5TEJ|ARMv6|ARMv6K|ARMv6T2|ARMv7|ARMv7S|ARMv8) 147#define ARMV5TE_ABOVE (ARMv5TE|ARMv5TEJ|ARMv6|ARMv6K|ARMv6T2|ARMv7|ARMv7S|ARMv8) 148#define ARMV5J_ABOVE (ARMv5TEJ|ARMv6|ARMv6K|ARMv6T2|ARMv7|ARMv7S|ARMv8) 149#define ARMV6_ABOVE (ARMv6|ARMv6K|ARMv6T2|ARMv7|ARMv7S|ARMv8) 150#define ARMV6T2_ABOVE (ARMv6T2|ARMv7|ARMv7S|ARMv8) 151#define ARMV7_ABOVE (ARMv7|ARMv7S|ARMv8) 152 153#define No_VFP 0 154#define VFPv1 (1u << 1) 155#define VFPv2 (1u << 2) 156#define VFPv3 (1u << 3) 157#define AdvancedSIMD (1u << 4) 158 159#define VFPv1_ABOVE (VFPv1 | VFPv2 | VFPv3 | AdvancedSIMD) 160#define VFPv2_ABOVE (VFPv2 | VFPv3 | AdvancedSIMD) 161#define VFPv2v3 (VFPv2 | VFPv3) 162 163//---------------------------------------------------------------------- 164// 165// EmulateInstructionARM implementation 166// 167//---------------------------------------------------------------------- 168 169void 170EmulateInstructionARM::Initialize () 171{ 172 PluginManager::RegisterPlugin (GetPluginNameStatic (), 173 GetPluginDescriptionStatic (), 174 CreateInstance); 175} 176 177void 178EmulateInstructionARM::Terminate () 179{ 180 PluginManager::UnregisterPlugin (CreateInstance); 181} 182 183ConstString 184EmulateInstructionARM::GetPluginNameStatic () 185{ 186 static ConstString g_name("arm"); 187 return g_name; 188} 189 190const char * 191EmulateInstructionARM::GetPluginDescriptionStatic () 192{ 193 return "Emulate instructions for the ARM architecture."; 194} 195 196EmulateInstruction * 197EmulateInstructionARM::CreateInstance (const ArchSpec &arch, InstructionType inst_type) 198{ 199 if (EmulateInstructionARM::SupportsEmulatingInstructionsOfTypeStatic(inst_type)) 200 { 201 if (arch.GetTriple().getArch() == llvm::Triple::arm) 202 { 203 std::unique_ptr<EmulateInstructionARM> emulate_insn_ap (new EmulateInstructionARM (arch)); 204 205 if (emulate_insn_ap.get()) 206 return emulate_insn_ap.release(); 207 } 208 else if (arch.GetTriple().getArch() == llvm::Triple::thumb) 209 { 210 std::unique_ptr<EmulateInstructionARM> emulate_insn_ap (new EmulateInstructionARM (arch)); 211 212 if (emulate_insn_ap.get()) 213 return emulate_insn_ap.release(); 214 } 215 } 216 217 return NULL; 218} 219 220bool 221EmulateInstructionARM::SetTargetTriple (const ArchSpec &arch) 222{ 223 if (arch.GetTriple().getArch () == llvm::Triple::arm) 224 return true; 225 else if (arch.GetTriple().getArch () == llvm::Triple::thumb) 226 return true; 227 228 return false; 229} 230 231// Write "bits (32) UNKNOWN" to memory address "address". Helper function for many ARM instructions. 232bool 233EmulateInstructionARM::WriteBits32UnknownToMemory (addr_t address) 234{ 235 EmulateInstruction::Context context; 236 context.type = EmulateInstruction::eContextWriteMemoryRandomBits; 237 context.SetNoArgs (); 238 239 uint32_t random_data = rand (); 240 const uint32_t addr_byte_size = GetAddressByteSize(); 241 242 if (!MemAWrite (context, address, random_data, addr_byte_size)) 243 return false; 244 245 return true; 246} 247 248// Write "bits (32) UNKNOWN" to register n. Helper function for many ARM instructions. 249bool 250EmulateInstructionARM::WriteBits32Unknown (int n) 251{ 252 EmulateInstruction::Context context; 253 context.type = EmulateInstruction::eContextWriteRegisterRandomBits; 254 context.SetNoArgs (); 255 256 bool success; 257 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success); 258 259 if (!success) 260 return false; 261 262 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, data)) 263 return false; 264 265 return true; 266} 267 268bool 269EmulateInstructionARM::GetRegisterInfo (uint32_t reg_kind, uint32_t reg_num, RegisterInfo ®_info) 270{ 271 if (reg_kind == eRegisterKindGeneric) 272 { 273 switch (reg_num) 274 { 275 case LLDB_REGNUM_GENERIC_PC: reg_kind = eRegisterKindDWARF; reg_num = dwarf_pc; break; 276 case LLDB_REGNUM_GENERIC_SP: reg_kind = eRegisterKindDWARF; reg_num = dwarf_sp; break; 277 case LLDB_REGNUM_GENERIC_FP: reg_kind = eRegisterKindDWARF; reg_num = dwarf_r7; break; 278 case LLDB_REGNUM_GENERIC_RA: reg_kind = eRegisterKindDWARF; reg_num = dwarf_lr; break; 279 case LLDB_REGNUM_GENERIC_FLAGS: reg_kind = eRegisterKindDWARF; reg_num = dwarf_cpsr; break; 280 default: return false; 281 } 282 } 283 284 if (reg_kind == eRegisterKindDWARF) 285 return GetARMDWARFRegisterInfo(reg_num, reg_info); 286 return false; 287} 288 289uint32_t 290EmulateInstructionARM::GetFramePointerRegisterNumber () const 291{ 292 bool is_apple = false; 293 if (m_arch.GetTriple().getVendor() == llvm::Triple::Apple) 294 is_apple = true; 295 switch (m_arch.GetTriple().getOS()) 296 { 297 case llvm::Triple::Darwin: 298 case llvm::Triple::MacOSX: 299 case llvm::Triple::IOS: 300 is_apple = true; 301 break; 302 default: 303 break; 304 } 305 306 /* On Apple iOS et al, the frame pointer register is always r7. 307 * Typically on other ARM systems, thumb code uses r7; arm code uses r11. 308 */ 309 310 uint32_t fp_regnum = 11; 311 312 if (is_apple) 313 fp_regnum = 7; 314 315 if (m_opcode_mode == eModeThumb) 316 fp_regnum = 7; 317 318 return fp_regnum; 319} 320 321uint32_t 322EmulateInstructionARM::GetFramePointerDWARFRegisterNumber () const 323{ 324 bool is_apple = false; 325 if (m_arch.GetTriple().getVendor() == llvm::Triple::Apple) 326 is_apple = true; 327 switch (m_arch.GetTriple().getOS()) 328 { 329 case llvm::Triple::Darwin: 330 case llvm::Triple::MacOSX: 331 case llvm::Triple::IOS: 332 is_apple = true; 333 break; 334 default: 335 break; 336 } 337 338 /* On Apple iOS et al, the frame pointer register is always r7. 339 * Typically on other ARM systems, thumb code uses r7; arm code uses r11. 340 */ 341 342 uint32_t fp_regnum = dwarf_r11; 343 344 if (is_apple) 345 fp_regnum = dwarf_r7; 346 347 if (m_opcode_mode == eModeThumb) 348 fp_regnum = dwarf_r7; 349 350 return fp_regnum; 351} 352 353// Push Multiple Registers stores multiple registers to the stack, storing to 354// consecutive memory locations ending just below the address in SP, and updates 355// SP to point to the start of the stored data. 356bool 357EmulateInstructionARM::EmulatePUSH (const uint32_t opcode, const ARMEncoding encoding) 358{ 359#if 0 360 // ARM pseudo code... 361 if (ConditionPassed()) 362 { 363 EncodingSpecificOperations(); 364 NullCheckIfThumbEE(13); 365 address = SP - 4*BitCount(registers); 366 367 for (i = 0 to 14) 368 { 369 if (registers<i> == '1') 370 { 371 if i == 13 && i != LowestSetBit(registers) // Only possible for encoding A1 372 MemA[address,4] = bits(32) UNKNOWN; 373 else 374 MemA[address,4] = R[i]; 375 address = address + 4; 376 } 377 } 378 379 if (registers<15> == '1') // Only possible for encoding A1 or A2 380 MemA[address,4] = PCStoreValue(); 381 382 SP = SP - 4*BitCount(registers); 383 } 384#endif 385 386 bool conditional = false; 387 bool success = false; 388 if (ConditionPassed(opcode, &conditional)) 389 { 390 const uint32_t addr_byte_size = GetAddressByteSize(); 391 const addr_t sp = ReadCoreReg (SP_REG, &success); 392 if (!success) 393 return false; 394 uint32_t registers = 0; 395 uint32_t Rt; // the source register 396 switch (encoding) { 397 case eEncodingT1: 398 registers = Bits32(opcode, 7, 0); 399 // The M bit represents LR. 400 if (Bit32(opcode, 8)) 401 registers |= (1u << 14); 402 // if BitCount(registers) < 1 then UNPREDICTABLE; 403 if (BitCount(registers) < 1) 404 return false; 405 break; 406 case eEncodingT2: 407 // Ignore bits 15 & 13. 408 registers = Bits32(opcode, 15, 0) & ~0xa000; 409 // if BitCount(registers) < 2 then UNPREDICTABLE; 410 if (BitCount(registers) < 2) 411 return false; 412 break; 413 case eEncodingT3: 414 Rt = Bits32(opcode, 15, 12); 415 // if BadReg(t) then UNPREDICTABLE; 416 if (BadReg(Rt)) 417 return false; 418 registers = (1u << Rt); 419 break; 420 case eEncodingA1: 421 registers = Bits32(opcode, 15, 0); 422 // Instead of return false, let's handle the following case as well, 423 // which amounts to pushing one reg onto the full descending stacks. 424 // if BitCount(register_list) < 2 then SEE STMDB / STMFD; 425 break; 426 case eEncodingA2: 427 Rt = Bits32(opcode, 15, 12); 428 // if t == 13 then UNPREDICTABLE; 429 if (Rt == dwarf_sp) 430 return false; 431 registers = (1u << Rt); 432 break; 433 default: 434 return false; 435 } 436 addr_t sp_offset = addr_byte_size * BitCount (registers); 437 addr_t addr = sp - sp_offset; 438 uint32_t i; 439 440 EmulateInstruction::Context context; 441 if (conditional) 442 context.type = EmulateInstruction::eContextRegisterStore; 443 else 444 context.type = EmulateInstruction::eContextPushRegisterOnStack; 445 RegisterInfo reg_info; 446 RegisterInfo sp_reg; 447 GetRegisterInfo (eRegisterKindDWARF, dwarf_sp, sp_reg); 448 for (i=0; i<15; ++i) 449 { 450 if (BitIsSet (registers, i)) 451 { 452 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + i, reg_info); 453 context.SetRegisterToRegisterPlusOffset (reg_info, sp_reg, addr - sp); 454 uint32_t reg_value = ReadCoreReg(i, &success); 455 if (!success) 456 return false; 457 if (!MemAWrite (context, addr, reg_value, addr_byte_size)) 458 return false; 459 addr += addr_byte_size; 460 } 461 } 462 463 if (BitIsSet (registers, 15)) 464 { 465 GetRegisterInfo (eRegisterKindDWARF, dwarf_pc, reg_info); 466 context.SetRegisterToRegisterPlusOffset (reg_info, sp_reg, addr - sp); 467 const uint32_t pc = ReadCoreReg(PC_REG, &success); 468 if (!success) 469 return false; 470 if (!MemAWrite (context, addr, pc, addr_byte_size)) 471 return false; 472 } 473 474 context.type = EmulateInstruction::eContextAdjustStackPointer; 475 context.SetImmediateSigned (-sp_offset); 476 477 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, sp - sp_offset)) 478 return false; 479 } 480 return true; 481} 482 483// Pop Multiple Registers loads multiple registers from the stack, loading from 484// consecutive memory locations staring at the address in SP, and updates 485// SP to point just above the loaded data. 486bool 487EmulateInstructionARM::EmulatePOP (const uint32_t opcode, const ARMEncoding encoding) 488{ 489#if 0 490 // ARM pseudo code... 491 if (ConditionPassed()) 492 { 493 EncodingSpecificOperations(); NullCheckIfThumbEE(13); 494 address = SP; 495 for i = 0 to 14 496 if registers<i> == '1' then 497 R[i] = if UnalignedAllowed then MemU[address,4] else MemA[address,4]; address = address + 4; 498 if registers<15> == '1' then 499 if UnalignedAllowed then 500 LoadWritePC(MemU[address,4]); 501 else 502 LoadWritePC(MemA[address,4]); 503 if registers<13> == '0' then SP = SP + 4*BitCount(registers); 504 if registers<13> == '1' then SP = bits(32) UNKNOWN; 505 } 506#endif 507 508 bool success = false; 509 510 bool conditional = false; 511 if (ConditionPassed(opcode, &conditional)) 512 { 513 const uint32_t addr_byte_size = GetAddressByteSize(); 514 const addr_t sp = ReadCoreReg (SP_REG, &success); 515 if (!success) 516 return false; 517 uint32_t registers = 0; 518 uint32_t Rt; // the destination register 519 switch (encoding) { 520 case eEncodingT1: 521 registers = Bits32(opcode, 7, 0); 522 // The P bit represents PC. 523 if (Bit32(opcode, 8)) 524 registers |= (1u << 15); 525 // if BitCount(registers) < 1 then UNPREDICTABLE; 526 if (BitCount(registers) < 1) 527 return false; 528 break; 529 case eEncodingT2: 530 // Ignore bit 13. 531 registers = Bits32(opcode, 15, 0) & ~0x2000; 532 // if BitCount(registers) < 2 || (P == '1' && M == '1') then UNPREDICTABLE; 533 if (BitCount(registers) < 2 || (Bit32(opcode, 15) && Bit32(opcode, 14))) 534 return false; 535 // if registers<15> == '1' && InITBlock() && !LastInITBlock() then UNPREDICTABLE; 536 if (BitIsSet(registers, 15) && InITBlock() && !LastInITBlock()) 537 return false; 538 break; 539 case eEncodingT3: 540 Rt = Bits32(opcode, 15, 12); 541 // if t == 13 || (t == 15 && InITBlock() && !LastInITBlock()) then UNPREDICTABLE; 542 if (Rt == 13) 543 return false; 544 if (Rt == 15 && InITBlock() && !LastInITBlock()) 545 return false; 546 registers = (1u << Rt); 547 break; 548 case eEncodingA1: 549 registers = Bits32(opcode, 15, 0); 550 // Instead of return false, let's handle the following case as well, 551 // which amounts to popping one reg from the full descending stacks. 552 // if BitCount(register_list) < 2 then SEE LDM / LDMIA / LDMFD; 553 554 // if registers<13> == '1' && ArchVersion() >= 7 then UNPREDICTABLE; 555 if (BitIsSet(opcode, 13) && ArchVersion() >= ARMv7) 556 return false; 557 break; 558 case eEncodingA2: 559 Rt = Bits32(opcode, 15, 12); 560 // if t == 13 then UNPREDICTABLE; 561 if (Rt == dwarf_sp) 562 return false; 563 registers = (1u << Rt); 564 break; 565 default: 566 return false; 567 } 568 addr_t sp_offset = addr_byte_size * BitCount (registers); 569 addr_t addr = sp; 570 uint32_t i, data; 571 572 EmulateInstruction::Context context; 573 if (conditional) 574 context.type = EmulateInstruction::eContextRegisterLoad; 575 else 576 context.type = EmulateInstruction::eContextPopRegisterOffStack; 577 578 RegisterInfo sp_reg; 579 GetRegisterInfo (eRegisterKindDWARF, dwarf_sp, sp_reg); 580 581 for (i=0; i<15; ++i) 582 { 583 if (BitIsSet (registers, i)) 584 { 585 context.SetRegisterPlusOffset (sp_reg, addr - sp); 586 data = MemARead(context, addr, 4, 0, &success); 587 if (!success) 588 return false; 589 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + i, data)) 590 return false; 591 addr += addr_byte_size; 592 } 593 } 594 595 if (BitIsSet (registers, 15)) 596 { 597 context.SetRegisterPlusOffset (sp_reg, addr - sp); 598 data = MemARead(context, addr, 4, 0, &success); 599 if (!success) 600 return false; 601 // In ARMv5T and above, this is an interworking branch. 602 if (!LoadWritePC(context, data)) 603 return false; 604 //addr += addr_byte_size; 605 } 606 607 context.type = EmulateInstruction::eContextAdjustStackPointer; 608 context.SetImmediateSigned (sp_offset); 609 610 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, sp + sp_offset)) 611 return false; 612 } 613 return true; 614} 615 616// Set r7 or ip to point to saved value residing within the stack. 617// ADD (SP plus immediate) 618bool 619EmulateInstructionARM::EmulateADDRdSPImm (const uint32_t opcode, const ARMEncoding encoding) 620{ 621#if 0 622 // ARM pseudo code... 623 if (ConditionPassed()) 624 { 625 EncodingSpecificOperations(); 626 (result, carry, overflow) = AddWithCarry(SP, imm32, '0'); 627 if d == 15 then 628 ALUWritePC(result); // setflags is always FALSE here 629 else 630 R[d] = result; 631 if setflags then 632 APSR.N = result<31>; 633 APSR.Z = IsZeroBit(result); 634 APSR.C = carry; 635 APSR.V = overflow; 636 } 637#endif 638 639 bool success = false; 640 641 if (ConditionPassed(opcode)) 642 { 643 const addr_t sp = ReadCoreReg (SP_REG, &success); 644 if (!success) 645 return false; 646 uint32_t Rd; // the destination register 647 uint32_t imm32; 648 switch (encoding) { 649 case eEncodingT1: 650 Rd = 7; 651 imm32 = Bits32(opcode, 7, 0) << 2; // imm32 = ZeroExtend(imm8:'00', 32) 652 break; 653 case eEncodingA1: 654 Rd = Bits32(opcode, 15, 12); 655 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12) 656 break; 657 default: 658 return false; 659 } 660 addr_t sp_offset = imm32; 661 addr_t addr = sp + sp_offset; // a pointer to the stack area 662 663 EmulateInstruction::Context context; 664 context.type = eContextSetFramePointer; 665 RegisterInfo sp_reg; 666 GetRegisterInfo (eRegisterKindDWARF, dwarf_sp, sp_reg); 667 context.SetRegisterPlusOffset (sp_reg, sp_offset); 668 669 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + Rd, addr)) 670 return false; 671 } 672 return true; 673} 674 675// Set r7 or ip to the current stack pointer. 676// MOV (register) 677bool 678EmulateInstructionARM::EmulateMOVRdSP (const uint32_t opcode, const ARMEncoding encoding) 679{ 680#if 0 681 // ARM pseudo code... 682 if (ConditionPassed()) 683 { 684 EncodingSpecificOperations(); 685 result = R[m]; 686 if d == 15 then 687 ALUWritePC(result); // setflags is always FALSE here 688 else 689 R[d] = result; 690 if setflags then 691 APSR.N = result<31>; 692 APSR.Z = IsZeroBit(result); 693 // APSR.C unchanged 694 // APSR.V unchanged 695 } 696#endif 697 698 bool success = false; 699 700 if (ConditionPassed(opcode)) 701 { 702 const addr_t sp = ReadCoreReg (SP_REG, &success); 703 if (!success) 704 return false; 705 uint32_t Rd; // the destination register 706 switch (encoding) { 707 case eEncodingT1: 708 Rd = 7; 709 break; 710 case eEncodingA1: 711 Rd = 12; 712 break; 713 default: 714 return false; 715 } 716 717 EmulateInstruction::Context context; 718 if (Rd == GetFramePointerRegisterNumber()) 719 context.type = EmulateInstruction::eContextSetFramePointer; 720 else 721 context.type = EmulateInstruction::eContextRegisterPlusOffset; 722 RegisterInfo sp_reg; 723 GetRegisterInfo (eRegisterKindDWARF, dwarf_sp, sp_reg); 724 context.SetRegisterPlusOffset (sp_reg, 0); 725 726 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + Rd, sp)) 727 return false; 728 } 729 return true; 730} 731 732// Move from high register (r8-r15) to low register (r0-r7). 733// MOV (register) 734bool 735EmulateInstructionARM::EmulateMOVLowHigh (const uint32_t opcode, const ARMEncoding encoding) 736{ 737 return EmulateMOVRdRm (opcode, encoding); 738} 739 740// Move from register to register. 741// MOV (register) 742bool 743EmulateInstructionARM::EmulateMOVRdRm (const uint32_t opcode, const ARMEncoding encoding) 744{ 745#if 0 746 // ARM pseudo code... 747 if (ConditionPassed()) 748 { 749 EncodingSpecificOperations(); 750 result = R[m]; 751 if d == 15 then 752 ALUWritePC(result); // setflags is always FALSE here 753 else 754 R[d] = result; 755 if setflags then 756 APSR.N = result<31>; 757 APSR.Z = IsZeroBit(result); 758 // APSR.C unchanged 759 // APSR.V unchanged 760 } 761#endif 762 763 bool success = false; 764 765 if (ConditionPassed(opcode)) 766 { 767 uint32_t Rm; // the source register 768 uint32_t Rd; // the destination register 769 bool setflags; 770 switch (encoding) { 771 case eEncodingT1: 772 Rd = Bit32(opcode, 7) << 3 | Bits32(opcode, 2, 0); 773 Rm = Bits32(opcode, 6, 3); 774 setflags = false; 775 if (Rd == 15 && InITBlock() && !LastInITBlock()) 776 return false; 777 break; 778 case eEncodingT2: 779 Rd = Bits32(opcode, 2, 0); 780 Rm = Bits32(opcode, 5, 3); 781 setflags = true; 782 if (InITBlock()) 783 return false; 784 break; 785 case eEncodingT3: 786 Rd = Bits32(opcode, 11, 8); 787 Rm = Bits32(opcode, 3, 0); 788 setflags = BitIsSet(opcode, 20); 789 // if setflags && (BadReg(d) || BadReg(m)) then UNPREDICTABLE; 790 if (setflags && (BadReg(Rd) || BadReg(Rm))) 791 return false; 792 // if !setflags && (d == 15 || m == 15 || (d == 13 && m == 13)) then UNPREDICTABLE; 793 if (!setflags && (Rd == 15 || Rm == 15 || (Rd == 13 && Rm == 13))) 794 return false; 795 break; 796 case eEncodingA1: 797 Rd = Bits32(opcode, 15, 12); 798 Rm = Bits32(opcode, 3, 0); 799 setflags = BitIsSet(opcode, 20); 800 801 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions; 802 if (Rd == 15 && setflags) 803 return EmulateSUBSPcLrEtc (opcode, encoding); 804 break; 805 default: 806 return false; 807 } 808 uint32_t result = ReadCoreReg(Rm, &success); 809 if (!success) 810 return false; 811 812 // The context specifies that Rm is to be moved into Rd. 813 EmulateInstruction::Context context; 814 context.type = EmulateInstruction::eContextRegisterLoad; 815 RegisterInfo dwarf_reg; 816 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + Rm, dwarf_reg); 817 context.SetRegister (dwarf_reg); 818 819 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags)) 820 return false; 821 } 822 return true; 823} 824 825// Move (immediate) writes an immediate value to the destination register. It 826// can optionally update the condition flags based on the value. 827// MOV (immediate) 828bool 829EmulateInstructionARM::EmulateMOVRdImm (const uint32_t opcode, const ARMEncoding encoding) 830{ 831#if 0 832 // ARM pseudo code... 833 if (ConditionPassed()) 834 { 835 EncodingSpecificOperations(); 836 result = imm32; 837 if d == 15 then // Can only occur for ARM encoding 838 ALUWritePC(result); // setflags is always FALSE here 839 else 840 R[d] = result; 841 if setflags then 842 APSR.N = result<31>; 843 APSR.Z = IsZeroBit(result); 844 APSR.C = carry; 845 // APSR.V unchanged 846 } 847#endif 848 849 if (ConditionPassed(opcode)) 850 { 851 uint32_t Rd; // the destination register 852 uint32_t imm32; // the immediate value to be written to Rd 853 uint32_t carry = 0; // the carry bit after ThumbExpandImm_C or ARMExpandImm_C. 854 // for setflags == false, this value is a don't care 855 // initialized to 0 to silence the static analyzer 856 bool setflags; 857 switch (encoding) { 858 case eEncodingT1: 859 Rd = Bits32(opcode, 10, 8); 860 setflags = !InITBlock(); 861 imm32 = Bits32(opcode, 7, 0); // imm32 = ZeroExtend(imm8, 32) 862 carry = APSR_C; 863 864 break; 865 866 case eEncodingT2: 867 Rd = Bits32(opcode, 11, 8); 868 setflags = BitIsSet(opcode, 20); 869 imm32 = ThumbExpandImm_C(opcode, APSR_C, carry); 870 if (BadReg(Rd)) 871 return false; 872 873 break; 874 875 case eEncodingT3: 876 { 877 // d = UInt(Rd); setflags = FALSE; imm32 = ZeroExtend(imm4:i:imm3:imm8, 32); 878 Rd = Bits32 (opcode, 11, 8); 879 setflags = false; 880 uint32_t imm4 = Bits32 (opcode, 19, 16); 881 uint32_t imm3 = Bits32 (opcode, 14, 12); 882 uint32_t i = Bit32 (opcode, 26); 883 uint32_t imm8 = Bits32 (opcode, 7, 0); 884 imm32 = (imm4 << 12) | (i << 11) | (imm3 << 8) | imm8; 885 886 // if BadReg(d) then UNPREDICTABLE; 887 if (BadReg (Rd)) 888 return false; 889 } 890 break; 891 892 case eEncodingA1: 893 // d = UInt(Rd); setflags = (S == �1�); (imm32, carry) = ARMExpandImm_C(imm12, APSR.C); 894 Rd = Bits32 (opcode, 15, 12); 895 setflags = BitIsSet (opcode, 20); 896 imm32 = ARMExpandImm_C (opcode, APSR_C, carry); 897 898 // if Rd == �1111� && S == �1� then SEE SUBS PC, LR and related instructions; 899 if ((Rd == 15) && setflags) 900 return EmulateSUBSPcLrEtc (opcode, encoding); 901 902 break; 903 904 case eEncodingA2: 905 { 906 // d = UInt(Rd); setflags = FALSE; imm32 = ZeroExtend(imm4:imm12, 32); 907 Rd = Bits32 (opcode, 15, 12); 908 setflags = false; 909 uint32_t imm4 = Bits32 (opcode, 19, 16); 910 uint32_t imm12 = Bits32 (opcode, 11, 0); 911 imm32 = (imm4 << 12) | imm12; 912 913 // if d == 15 then UNPREDICTABLE; 914 if (Rd == 15) 915 return false; 916 } 917 break; 918 919 default: 920 return false; 921 } 922 uint32_t result = imm32; 923 924 // The context specifies that an immediate is to be moved into Rd. 925 EmulateInstruction::Context context; 926 context.type = EmulateInstruction::eContextImmediate; 927 context.SetNoArgs (); 928 929 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry)) 930 return false; 931 } 932 return true; 933} 934 935// MUL multiplies two register values. The least significant 32 bits of the result are written to the destination 936// register. These 32 bits do not depend on whether the source register values are considered to be signed values or 937// unsigned values. 938// 939// Optionally, it can update the condition flags based on the result. In the Thumb instruction set, this option is 940// limited to only a few forms of the instruction. 941bool 942EmulateInstructionARM::EmulateMUL (const uint32_t opcode, const ARMEncoding encoding) 943{ 944#if 0 945 if ConditionPassed() then 946 EncodingSpecificOperations(); 947 operand1 = SInt(R[n]); // operand1 = UInt(R[n]) produces the same final results 948 operand2 = SInt(R[m]); // operand2 = UInt(R[m]) produces the same final results 949 result = operand1 * operand2; 950 R[d] = result<31:0>; 951 if setflags then 952 APSR.N = result<31>; 953 APSR.Z = IsZeroBit(result); 954 if ArchVersion() == 4 then 955 APSR.C = bit UNKNOWN; 956 // else APSR.C unchanged 957 // APSR.V always unchanged 958#endif 959 960 if (ConditionPassed(opcode)) 961 { 962 uint32_t d; 963 uint32_t n; 964 uint32_t m; 965 bool setflags; 966 967 // EncodingSpecificOperations(); 968 switch (encoding) 969 { 970 case eEncodingT1: 971 // d = UInt(Rdm); n = UInt(Rn); m = UInt(Rdm); setflags = !InITBlock(); 972 d = Bits32 (opcode, 2, 0); 973 n = Bits32 (opcode, 5, 3); 974 m = Bits32 (opcode, 2, 0); 975 setflags = !InITBlock(); 976 977 // if ArchVersion() < 6 && d == n then UNPREDICTABLE; 978 if ((ArchVersion() < ARMv6) && (d == n)) 979 return false; 980 981 break; 982 983 case eEncodingT2: 984 // d = UInt(Rd); n = UInt(Rn); m = UInt(Rm); setflags = FALSE; 985 d = Bits32 (opcode, 11, 8); 986 n = Bits32 (opcode, 19, 16); 987 m = Bits32 (opcode, 3, 0); 988 setflags = false; 989 990 // if BadReg(d) || BadReg(n) || BadReg(m) then UNPREDICTABLE; 991 if (BadReg (d) || BadReg (n) || BadReg (m)) 992 return false; 993 994 break; 995 996 case eEncodingA1: 997 // d = UInt(Rd); n = UInt(Rn); m = UInt(Rm); setflags = (S == '1'); 998 d = Bits32 (opcode, 19, 16); 999 n = Bits32 (opcode, 3, 0); 1000 m = Bits32 (opcode, 11, 8); 1001 setflags = BitIsSet (opcode, 20); 1002 1003 // if d == 15 || n == 15 || m == 15 then UNPREDICTABLE; 1004 if ((d == 15) || (n == 15) || (m == 15)) 1005 return false; 1006 1007 // if ArchVersion() < 6 && d == n then UNPREDICTABLE; 1008 if ((ArchVersion() < ARMv6) && (d == n)) 1009 return false; 1010 1011 break; 1012 1013 default: 1014 return false; 1015 } 1016 1017 bool success = false; 1018 1019 // operand1 = SInt(R[n]); // operand1 = UInt(R[n]) produces the same final results 1020 uint64_t operand1 = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success); 1021 if (!success) 1022 return false; 1023 1024 // operand2 = SInt(R[m]); // operand2 = UInt(R[m]) produces the same final results 1025 uint64_t operand2 = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success); 1026 if (!success) 1027 return false; 1028 1029 // result = operand1 * operand2; 1030 uint64_t result = operand1 * operand2; 1031 1032 // R[d] = result<31:0>; 1033 RegisterInfo op1_reg; 1034 RegisterInfo op2_reg; 1035 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, op1_reg); 1036 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + m, op2_reg); 1037 1038 EmulateInstruction::Context context; 1039 context.type = eContextArithmetic; 1040 context.SetRegisterRegisterOperands (op1_reg, op2_reg); 1041 1042 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + d, (0x0000ffff & result))) 1043 return false; 1044 1045 // if setflags then 1046 if (setflags) 1047 { 1048 // APSR.N = result<31>; 1049 // APSR.Z = IsZeroBit(result); 1050 m_new_inst_cpsr = m_opcode_cpsr; 1051 SetBit32 (m_new_inst_cpsr, CPSR_N_POS, Bit32 (result, 31)); 1052 SetBit32 (m_new_inst_cpsr, CPSR_Z_POS, result == 0 ? 1 : 0); 1053 if (m_new_inst_cpsr != m_opcode_cpsr) 1054 { 1055 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS, m_new_inst_cpsr)) 1056 return false; 1057 } 1058 1059 // if ArchVersion() == 4 then 1060 // APSR.C = bit UNKNOWN; 1061 } 1062 } 1063 return true; 1064} 1065 1066// Bitwise NOT (immediate) writes the bitwise inverse of an immediate value to the destination register. 1067// It can optionally update the condition flags based on the value. 1068bool 1069EmulateInstructionARM::EmulateMVNImm (const uint32_t opcode, const ARMEncoding encoding) 1070{ 1071#if 0 1072 // ARM pseudo code... 1073 if (ConditionPassed()) 1074 { 1075 EncodingSpecificOperations(); 1076 result = NOT(imm32); 1077 if d == 15 then // Can only occur for ARM encoding 1078 ALUWritePC(result); // setflags is always FALSE here 1079 else 1080 R[d] = result; 1081 if setflags then 1082 APSR.N = result<31>; 1083 APSR.Z = IsZeroBit(result); 1084 APSR.C = carry; 1085 // APSR.V unchanged 1086 } 1087#endif 1088 1089 if (ConditionPassed(opcode)) 1090 { 1091 uint32_t Rd; // the destination register 1092 uint32_t imm32; // the output after ThumbExpandImm_C or ARMExpandImm_C 1093 uint32_t carry; // the carry bit after ThumbExpandImm_C or ARMExpandImm_C 1094 bool setflags; 1095 switch (encoding) { 1096 case eEncodingT1: 1097 Rd = Bits32(opcode, 11, 8); 1098 setflags = BitIsSet(opcode, 20); 1099 imm32 = ThumbExpandImm_C(opcode, APSR_C, carry); 1100 break; 1101 case eEncodingA1: 1102 Rd = Bits32(opcode, 15, 12); 1103 setflags = BitIsSet(opcode, 20); 1104 imm32 = ARMExpandImm_C(opcode, APSR_C, carry); 1105 1106 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions; 1107 if (Rd == 15 && setflags) 1108 return EmulateSUBSPcLrEtc (opcode, encoding); 1109 break; 1110 default: 1111 return false; 1112 } 1113 uint32_t result = ~imm32; 1114 1115 // The context specifies that an immediate is to be moved into Rd. 1116 EmulateInstruction::Context context; 1117 context.type = EmulateInstruction::eContextImmediate; 1118 context.SetNoArgs (); 1119 1120 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry)) 1121 return false; 1122 } 1123 return true; 1124} 1125 1126// Bitwise NOT (register) writes the bitwise inverse of a register value to the destination register. 1127// It can optionally update the condition flags based on the result. 1128bool 1129EmulateInstructionARM::EmulateMVNReg (const uint32_t opcode, const ARMEncoding encoding) 1130{ 1131#if 0 1132 // ARM pseudo code... 1133 if (ConditionPassed()) 1134 { 1135 EncodingSpecificOperations(); 1136 (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C); 1137 result = NOT(shifted); 1138 if d == 15 then // Can only occur for ARM encoding 1139 ALUWritePC(result); // setflags is always FALSE here 1140 else 1141 R[d] = result; 1142 if setflags then 1143 APSR.N = result<31>; 1144 APSR.Z = IsZeroBit(result); 1145 APSR.C = carry; 1146 // APSR.V unchanged 1147 } 1148#endif 1149 1150 if (ConditionPassed(opcode)) 1151 { 1152 uint32_t Rm; // the source register 1153 uint32_t Rd; // the destination register 1154 ARM_ShifterType shift_t; 1155 uint32_t shift_n; // the shift applied to the value read from Rm 1156 bool setflags; 1157 uint32_t carry; // the carry bit after the shift operation 1158 switch (encoding) { 1159 case eEncodingT1: 1160 Rd = Bits32(opcode, 2, 0); 1161 Rm = Bits32(opcode, 5, 3); 1162 setflags = !InITBlock(); 1163 shift_t = SRType_LSL; 1164 shift_n = 0; 1165 if (InITBlock()) 1166 return false; 1167 break; 1168 case eEncodingT2: 1169 Rd = Bits32(opcode, 11, 8); 1170 Rm = Bits32(opcode, 3, 0); 1171 setflags = BitIsSet(opcode, 20); 1172 shift_n = DecodeImmShiftThumb(opcode, shift_t); 1173 // if (BadReg(d) || BadReg(m)) then UNPREDICTABLE; 1174 if (BadReg(Rd) || BadReg(Rm)) 1175 return false; 1176 break; 1177 case eEncodingA1: 1178 Rd = Bits32(opcode, 15, 12); 1179 Rm = Bits32(opcode, 3, 0); 1180 setflags = BitIsSet(opcode, 20); 1181 shift_n = DecodeImmShiftARM(opcode, shift_t); 1182 break; 1183 default: 1184 return false; 1185 } 1186 bool success = false; 1187 uint32_t value = ReadCoreReg(Rm, &success); 1188 if (!success) 1189 return false; 1190 1191 uint32_t shifted = Shift_C(value, shift_t, shift_n, APSR_C, carry, &success); 1192 if (!success) 1193 return false; 1194 uint32_t result = ~shifted; 1195 1196 // The context specifies that an immediate is to be moved into Rd. 1197 EmulateInstruction::Context context; 1198 context.type = EmulateInstruction::eContextImmediate; 1199 context.SetNoArgs (); 1200 1201 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry)) 1202 return false; 1203 } 1204 return true; 1205} 1206 1207// PC relative immediate load into register, possibly followed by ADD (SP plus register). 1208// LDR (literal) 1209bool 1210EmulateInstructionARM::EmulateLDRRtPCRelative (const uint32_t opcode, const ARMEncoding encoding) 1211{ 1212#if 0 1213 // ARM pseudo code... 1214 if (ConditionPassed()) 1215 { 1216 EncodingSpecificOperations(); NullCheckIfThumbEE(15); 1217 base = Align(PC,4); 1218 address = if add then (base + imm32) else (base - imm32); 1219 data = MemU[address,4]; 1220 if t == 15 then 1221 if address<1:0> == '00' then LoadWritePC(data); else UNPREDICTABLE; 1222 elsif UnalignedSupport() || address<1:0> = '00' then 1223 R[t] = data; 1224 else // Can only apply before ARMv7 1225 if CurrentInstrSet() == InstrSet_ARM then 1226 R[t] = ROR(data, 8*UInt(address<1:0>)); 1227 else 1228 R[t] = bits(32) UNKNOWN; 1229 } 1230#endif 1231 1232 if (ConditionPassed(opcode)) 1233 { 1234 bool success = false; 1235 const uint32_t pc = ReadCoreReg(PC_REG, &success); 1236 if (!success) 1237 return false; 1238 1239 // PC relative immediate load context 1240 EmulateInstruction::Context context; 1241 context.type = EmulateInstruction::eContextRegisterPlusOffset; 1242 RegisterInfo pc_reg; 1243 GetRegisterInfo (eRegisterKindDWARF, dwarf_pc, pc_reg); 1244 context.SetRegisterPlusOffset (pc_reg, 0); 1245 1246 uint32_t Rt; // the destination register 1247 uint32_t imm32; // immediate offset from the PC 1248 bool add; // +imm32 or -imm32? 1249 addr_t base; // the base address 1250 addr_t address; // the PC relative address 1251 uint32_t data; // the literal data value from the PC relative load 1252 switch (encoding) { 1253 case eEncodingT1: 1254 Rt = Bits32(opcode, 10, 8); 1255 imm32 = Bits32(opcode, 7, 0) << 2; // imm32 = ZeroExtend(imm8:'00', 32); 1256 add = true; 1257 break; 1258 case eEncodingT2: 1259 Rt = Bits32(opcode, 15, 12); 1260 imm32 = Bits32(opcode, 11, 0) << 2; // imm32 = ZeroExtend(imm12, 32); 1261 add = BitIsSet(opcode, 23); 1262 if (Rt == 15 && InITBlock() && !LastInITBlock()) 1263 return false; 1264 break; 1265 default: 1266 return false; 1267 } 1268 1269 base = Align(pc, 4); 1270 if (add) 1271 address = base + imm32; 1272 else 1273 address = base - imm32; 1274 1275 context.SetRegisterPlusOffset(pc_reg, address - base); 1276 data = MemURead(context, address, 4, 0, &success); 1277 if (!success) 1278 return false; 1279 1280 if (Rt == 15) 1281 { 1282 if (Bits32(address, 1, 0) == 0) 1283 { 1284 // In ARMv5T and above, this is an interworking branch. 1285 if (!LoadWritePC(context, data)) 1286 return false; 1287 } 1288 else 1289 return false; 1290 } 1291 else if (UnalignedSupport() || Bits32(address, 1, 0) == 0) 1292 { 1293 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + Rt, data)) 1294 return false; 1295 } 1296 else // We don't handle ARM for now. 1297 return false; 1298 1299 } 1300 return true; 1301} 1302 1303// An add operation to adjust the SP. 1304// ADD (SP plus immediate) 1305bool 1306EmulateInstructionARM::EmulateADDSPImm (const uint32_t opcode, const ARMEncoding encoding) 1307{ 1308#if 0 1309 // ARM pseudo code... 1310 if (ConditionPassed()) 1311 { 1312 EncodingSpecificOperations(); 1313 (result, carry, overflow) = AddWithCarry(SP, imm32, '0'); 1314 if d == 15 then // Can only occur for ARM encoding 1315 ALUWritePC(result); // setflags is always FALSE here 1316 else 1317 R[d] = result; 1318 if setflags then 1319 APSR.N = result<31>; 1320 APSR.Z = IsZeroBit(result); 1321 APSR.C = carry; 1322 APSR.V = overflow; 1323 } 1324#endif 1325 1326 bool success = false; 1327 1328 if (ConditionPassed(opcode)) 1329 { 1330 const addr_t sp = ReadCoreReg (SP_REG, &success); 1331 if (!success) 1332 return false; 1333 uint32_t imm32; // the immediate operand 1334 uint32_t d; 1335 //bool setflags = false; // Add this back if/when support eEncodingT3 eEncodingA1 1336 switch (encoding) 1337 { 1338 case eEncodingT1: 1339 // d = UInt(Rd); setflags = FALSE; imm32 = ZeroExtend(imm8:'00', 32); 1340 d = Bits32 (opcode, 10, 8); 1341 imm32 = (Bits32 (opcode, 7, 0) << 2); 1342 1343 break; 1344 1345 case eEncodingT2: 1346 // d = 13; setflags = FALSE; imm32 = ZeroExtend(imm7:'00', 32); 1347 d = 13; 1348 imm32 = ThumbImm7Scaled(opcode); // imm32 = ZeroExtend(imm7:'00', 32) 1349 1350 break; 1351 1352 default: 1353 return false; 1354 } 1355 addr_t sp_offset = imm32; 1356 addr_t addr = sp + sp_offset; // the adjusted stack pointer value 1357 1358 EmulateInstruction::Context context; 1359 context.type = EmulateInstruction::eContextAdjustStackPointer; 1360 RegisterInfo sp_reg; 1361 GetRegisterInfo (eRegisterKindDWARF, dwarf_sp, sp_reg); 1362 context.SetRegisterPlusOffset (sp_reg, sp_offset); 1363 1364 if (d == 15) 1365 { 1366 if (!ALUWritePC (context, addr)) 1367 return false; 1368 } 1369 else 1370 { 1371 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + d, addr)) 1372 return false; 1373 1374 // Add this back if/when support eEncodingT3 eEncodingA1 1375 //if (setflags) 1376 //{ 1377 // APSR.N = result<31>; 1378 // APSR.Z = IsZeroBit(result); 1379 // APSR.C = carry; 1380 // APSR.V = overflow; 1381 //} 1382 } 1383 } 1384 return true; 1385} 1386 1387// An add operation to adjust the SP. 1388// ADD (SP plus register) 1389bool 1390EmulateInstructionARM::EmulateADDSPRm (const uint32_t opcode, const ARMEncoding encoding) 1391{ 1392#if 0 1393 // ARM pseudo code... 1394 if (ConditionPassed()) 1395 { 1396 EncodingSpecificOperations(); 1397 shifted = Shift(R[m], shift_t, shift_n, APSR.C); 1398 (result, carry, overflow) = AddWithCarry(SP, shifted, '0'); 1399 if d == 15 then 1400 ALUWritePC(result); // setflags is always FALSE here 1401 else 1402 R[d] = result; 1403 if setflags then 1404 APSR.N = result<31>; 1405 APSR.Z = IsZeroBit(result); 1406 APSR.C = carry; 1407 APSR.V = overflow; 1408 } 1409#endif 1410 1411 bool success = false; 1412 1413 if (ConditionPassed(opcode)) 1414 { 1415 const addr_t sp = ReadCoreReg (SP_REG, &success); 1416 if (!success) 1417 return false; 1418 uint32_t Rm; // the second operand 1419 switch (encoding) { 1420 case eEncodingT2: 1421 Rm = Bits32(opcode, 6, 3); 1422 break; 1423 default: 1424 return false; 1425 } 1426 int32_t reg_value = ReadCoreReg(Rm, &success); 1427 if (!success) 1428 return false; 1429 1430 addr_t addr = (int32_t)sp + reg_value; // the adjusted stack pointer value 1431 1432 EmulateInstruction::Context context; 1433 context.type = eContextArithmetic; 1434 RegisterInfo sp_reg; 1435 GetRegisterInfo (eRegisterKindDWARF, dwarf_sp, sp_reg); 1436 1437 RegisterInfo other_reg; 1438 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + Rm, other_reg); 1439 context.SetRegisterRegisterOperands (sp_reg, other_reg); 1440 1441 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, addr)) 1442 return false; 1443 } 1444 return true; 1445} 1446 1447// Branch with Link and Exchange Instruction Sets (immediate) calls a subroutine 1448// at a PC-relative address, and changes instruction set from ARM to Thumb, or 1449// from Thumb to ARM. 1450// BLX (immediate) 1451bool 1452EmulateInstructionARM::EmulateBLXImmediate (const uint32_t opcode, const ARMEncoding encoding) 1453{ 1454#if 0 1455 // ARM pseudo code... 1456 if (ConditionPassed()) 1457 { 1458 EncodingSpecificOperations(); 1459 if CurrentInstrSet() == InstrSet_ARM then 1460 LR = PC - 4; 1461 else 1462 LR = PC<31:1> : '1'; 1463 if targetInstrSet == InstrSet_ARM then 1464 targetAddress = Align(PC,4) + imm32; 1465 else 1466 targetAddress = PC + imm32; 1467 SelectInstrSet(targetInstrSet); 1468 BranchWritePC(targetAddress); 1469 } 1470#endif 1471 1472 bool success = true; 1473 1474 if (ConditionPassed(opcode)) 1475 { 1476 EmulateInstruction::Context context; 1477 context.type = EmulateInstruction::eContextRelativeBranchImmediate; 1478 const uint32_t pc = ReadCoreReg(PC_REG, &success); 1479 if (!success) 1480 return false; 1481 addr_t lr; // next instruction address 1482 addr_t target; // target address 1483 int32_t imm32; // PC-relative offset 1484 switch (encoding) { 1485 case eEncodingT1: 1486 { 1487 lr = pc | 1u; // return address 1488 uint32_t S = Bit32(opcode, 26); 1489 uint32_t imm10 = Bits32(opcode, 25, 16); 1490 uint32_t J1 = Bit32(opcode, 13); 1491 uint32_t J2 = Bit32(opcode, 11); 1492 uint32_t imm11 = Bits32(opcode, 10, 0); 1493 uint32_t I1 = !(J1 ^ S); 1494 uint32_t I2 = !(J2 ^ S); 1495 uint32_t imm25 = (S << 24) | (I1 << 23) | (I2 << 22) | (imm10 << 12) | (imm11 << 1); 1496 imm32 = llvm::SignExtend32<25>(imm25); 1497 target = pc + imm32; 1498 context.SetISAAndImmediateSigned (eModeThumb, 4 + imm32); 1499 if (InITBlock() && !LastInITBlock()) 1500 return false; 1501 break; 1502 } 1503 case eEncodingT2: 1504 { 1505 lr = pc | 1u; // return address 1506 uint32_t S = Bit32(opcode, 26); 1507 uint32_t imm10H = Bits32(opcode, 25, 16); 1508 uint32_t J1 = Bit32(opcode, 13); 1509 uint32_t J2 = Bit32(opcode, 11); 1510 uint32_t imm10L = Bits32(opcode, 10, 1); 1511 uint32_t I1 = !(J1 ^ S); 1512 uint32_t I2 = !(J2 ^ S); 1513 uint32_t imm25 = (S << 24) | (I1 << 23) | (I2 << 22) | (imm10H << 12) | (imm10L << 2); 1514 imm32 = llvm::SignExtend32<25>(imm25); 1515 target = Align(pc, 4) + imm32; 1516 context.SetISAAndImmediateSigned (eModeARM, 4 + imm32); 1517 if (InITBlock() && !LastInITBlock()) 1518 return false; 1519 break; 1520 } 1521 case eEncodingA1: 1522 lr = pc - 4; // return address 1523 imm32 = llvm::SignExtend32<26>(Bits32(opcode, 23, 0) << 2); 1524 target = Align(pc, 4) + imm32; 1525 context.SetISAAndImmediateSigned (eModeARM, 8 + imm32); 1526 break; 1527 case eEncodingA2: 1528 lr = pc - 4; // return address 1529 imm32 = llvm::SignExtend32<26>(Bits32(opcode, 23, 0) << 2 | Bits32(opcode, 24, 24) << 1); 1530 target = pc + imm32; 1531 context.SetISAAndImmediateSigned (eModeThumb, 8 + imm32); 1532 break; 1533 default: 1534 return false; 1535 } 1536 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_RA, lr)) 1537 return false; 1538 if (!BranchWritePC(context, target)) 1539 return false; 1540 } 1541 return true; 1542} 1543 1544// Branch with Link and Exchange (register) calls a subroutine at an address and 1545// instruction set specified by a register. 1546// BLX (register) 1547bool 1548EmulateInstructionARM::EmulateBLXRm (const uint32_t opcode, const ARMEncoding encoding) 1549{ 1550#if 0 1551 // ARM pseudo code... 1552 if (ConditionPassed()) 1553 { 1554 EncodingSpecificOperations(); 1555 target = R[m]; 1556 if CurrentInstrSet() == InstrSet_ARM then 1557 next_instr_addr = PC - 4; 1558 LR = next_instr_addr; 1559 else 1560 next_instr_addr = PC - 2; 1561 LR = next_instr_addr<31:1> : '1'; 1562 BXWritePC(target); 1563 } 1564#endif 1565 1566 bool success = false; 1567 1568 if (ConditionPassed(opcode)) 1569 { 1570 EmulateInstruction::Context context; 1571 context.type = EmulateInstruction::eContextAbsoluteBranchRegister; 1572 const uint32_t pc = ReadCoreReg(PC_REG, &success); 1573 addr_t lr; // next instruction address 1574 if (!success) 1575 return false; 1576 uint32_t Rm; // the register with the target address 1577 switch (encoding) { 1578 case eEncodingT1: 1579 lr = (pc - 2) | 1u; // return address 1580 Rm = Bits32(opcode, 6, 3); 1581 // if m == 15 then UNPREDICTABLE; 1582 if (Rm == 15) 1583 return false; 1584 if (InITBlock() && !LastInITBlock()) 1585 return false; 1586 break; 1587 case eEncodingA1: 1588 lr = pc - 4; // return address 1589 Rm = Bits32(opcode, 3, 0); 1590 // if m == 15 then UNPREDICTABLE; 1591 if (Rm == 15) 1592 return false; 1593 break; 1594 default: 1595 return false; 1596 } 1597 addr_t target = ReadCoreReg (Rm, &success); 1598 if (!success) 1599 return false; 1600 RegisterInfo dwarf_reg; 1601 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + Rm, dwarf_reg); 1602 context.SetRegister (dwarf_reg); 1603 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_RA, lr)) 1604 return false; 1605 if (!BXWritePC(context, target)) 1606 return false; 1607 } 1608 return true; 1609} 1610 1611// Branch and Exchange causes a branch to an address and instruction set specified by a register. 1612bool 1613EmulateInstructionARM::EmulateBXRm (const uint32_t opcode, const ARMEncoding encoding) 1614{ 1615#if 0 1616 // ARM pseudo code... 1617 if (ConditionPassed()) 1618 { 1619 EncodingSpecificOperations(); 1620 BXWritePC(R[m]); 1621 } 1622#endif 1623 1624 if (ConditionPassed(opcode)) 1625 { 1626 EmulateInstruction::Context context; 1627 context.type = EmulateInstruction::eContextAbsoluteBranchRegister; 1628 uint32_t Rm; // the register with the target address 1629 switch (encoding) { 1630 case eEncodingT1: 1631 Rm = Bits32(opcode, 6, 3); 1632 if (InITBlock() && !LastInITBlock()) 1633 return false; 1634 break; 1635 case eEncodingA1: 1636 Rm = Bits32(opcode, 3, 0); 1637 break; 1638 default: 1639 return false; 1640 } 1641 bool success = false; 1642 addr_t target = ReadCoreReg (Rm, &success); 1643 if (!success) 1644 return false; 1645 1646 RegisterInfo dwarf_reg; 1647 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + Rm, dwarf_reg); 1648 context.SetRegister (dwarf_reg); 1649 if (!BXWritePC(context, target)) 1650 return false; 1651 } 1652 return true; 1653} 1654 1655// Branch and Exchange Jazelle attempts to change to Jazelle state. If the attempt fails, it branches to an 1656// address and instruction set specified by a register as though it were a BX instruction. 1657// 1658// TODO: Emulate Jazelle architecture? 1659// We currently assume that switching to Jazelle state fails, thus treating BXJ as a BX operation. 1660bool 1661EmulateInstructionARM::EmulateBXJRm (const uint32_t opcode, const ARMEncoding encoding) 1662{ 1663#if 0 1664 // ARM pseudo code... 1665 if (ConditionPassed()) 1666 { 1667 EncodingSpecificOperations(); 1668 if JMCR.JE == '0' || CurrentInstrSet() == InstrSet_ThumbEE then 1669 BXWritePC(R[m]); 1670 else 1671 if JazelleAcceptsExecution() then 1672 SwitchToJazelleExecution(); 1673 else 1674 SUBARCHITECTURE_DEFINED handler call; 1675 } 1676#endif 1677 1678 if (ConditionPassed(opcode)) 1679 { 1680 EmulateInstruction::Context context; 1681 context.type = EmulateInstruction::eContextAbsoluteBranchRegister; 1682 uint32_t Rm; // the register with the target address 1683 switch (encoding) { 1684 case eEncodingT1: 1685 Rm = Bits32(opcode, 19, 16); 1686 if (BadReg(Rm)) 1687 return false; 1688 if (InITBlock() && !LastInITBlock()) 1689 return false; 1690 break; 1691 case eEncodingA1: 1692 Rm = Bits32(opcode, 3, 0); 1693 if (Rm == 15) 1694 return false; 1695 break; 1696 default: 1697 return false; 1698 } 1699 bool success = false; 1700 addr_t target = ReadCoreReg (Rm, &success); 1701 if (!success) 1702 return false; 1703 1704 RegisterInfo dwarf_reg; 1705 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + Rm, dwarf_reg); 1706 context.SetRegister (dwarf_reg); 1707 if (!BXWritePC(context, target)) 1708 return false; 1709 } 1710 return true; 1711} 1712 1713// Set r7 to point to some ip offset. 1714// SUB (immediate) 1715bool 1716EmulateInstructionARM::EmulateSUBR7IPImm (const uint32_t opcode, const ARMEncoding encoding) 1717{ 1718#if 0 1719 // ARM pseudo code... 1720 if (ConditionPassed()) 1721 { 1722 EncodingSpecificOperations(); 1723 (result, carry, overflow) = AddWithCarry(SP, NOT(imm32), '1'); 1724 if d == 15 then // Can only occur for ARM encoding 1725 ALUWritePC(result); // setflags is always FALSE here 1726 else 1727 R[d] = result; 1728 if setflags then 1729 APSR.N = result<31>; 1730 APSR.Z = IsZeroBit(result); 1731 APSR.C = carry; 1732 APSR.V = overflow; 1733 } 1734#endif 1735 1736 if (ConditionPassed(opcode)) 1737 { 1738 bool success = false; 1739 const addr_t ip = ReadCoreReg (12, &success); 1740 if (!success) 1741 return false; 1742 uint32_t imm32; 1743 switch (encoding) { 1744 case eEncodingA1: 1745 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12) 1746 break; 1747 default: 1748 return false; 1749 } 1750 addr_t ip_offset = imm32; 1751 addr_t addr = ip - ip_offset; // the adjusted ip value 1752 1753 EmulateInstruction::Context context; 1754 context.type = EmulateInstruction::eContextRegisterPlusOffset; 1755 RegisterInfo dwarf_reg; 1756 GetRegisterInfo (eRegisterKindDWARF, dwarf_r12, dwarf_reg); 1757 context.SetRegisterPlusOffset (dwarf_reg, -ip_offset); 1758 1759 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r7, addr)) 1760 return false; 1761 } 1762 return true; 1763} 1764 1765// Set ip to point to some stack offset. 1766// SUB (SP minus immediate) 1767bool 1768EmulateInstructionARM::EmulateSUBIPSPImm (const uint32_t opcode, const ARMEncoding encoding) 1769{ 1770#if 0 1771 // ARM pseudo code... 1772 if (ConditionPassed()) 1773 { 1774 EncodingSpecificOperations(); 1775 (result, carry, overflow) = AddWithCarry(SP, NOT(imm32), '1'); 1776 if d == 15 then // Can only occur for ARM encoding 1777 ALUWritePC(result); // setflags is always FALSE here 1778 else 1779 R[d] = result; 1780 if setflags then 1781 APSR.N = result<31>; 1782 APSR.Z = IsZeroBit(result); 1783 APSR.C = carry; 1784 APSR.V = overflow; 1785 } 1786#endif 1787 1788 if (ConditionPassed(opcode)) 1789 { 1790 bool success = false; 1791 const addr_t sp = ReadCoreReg (SP_REG, &success); 1792 if (!success) 1793 return false; 1794 uint32_t imm32; 1795 switch (encoding) { 1796 case eEncodingA1: 1797 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12) 1798 break; 1799 default: 1800 return false; 1801 } 1802 addr_t sp_offset = imm32; 1803 addr_t addr = sp - sp_offset; // the adjusted stack pointer value 1804 1805 EmulateInstruction::Context context; 1806 context.type = EmulateInstruction::eContextRegisterPlusOffset; 1807 RegisterInfo dwarf_reg; 1808 GetRegisterInfo (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, dwarf_reg); 1809 context.SetRegisterPlusOffset (dwarf_reg, -sp_offset); 1810 1811 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r12, addr)) 1812 return false; 1813 } 1814 return true; 1815} 1816 1817// This instruction subtracts an immediate value from the SP value, and writes 1818// the result to the destination register. 1819// 1820// If Rd == 13 => A sub operation to adjust the SP -- allocate space for local storage. 1821bool 1822EmulateInstructionARM::EmulateSUBSPImm (const uint32_t opcode, const ARMEncoding encoding) 1823{ 1824#if 0 1825 // ARM pseudo code... 1826 if (ConditionPassed()) 1827 { 1828 EncodingSpecificOperations(); 1829 (result, carry, overflow) = AddWithCarry(SP, NOT(imm32), '1'); 1830 if d == 15 then // Can only occur for ARM encoding 1831 ALUWritePC(result); // setflags is always FALSE here 1832 else 1833 R[d] = result; 1834 if setflags then 1835 APSR.N = result<31>; 1836 APSR.Z = IsZeroBit(result); 1837 APSR.C = carry; 1838 APSR.V = overflow; 1839 } 1840#endif 1841 1842 bool success = false; 1843 if (ConditionPassed(opcode)) 1844 { 1845 const addr_t sp = ReadCoreReg (SP_REG, &success); 1846 if (!success) 1847 return false; 1848 1849 uint32_t Rd; 1850 bool setflags; 1851 uint32_t imm32; 1852 switch (encoding) { 1853 case eEncodingT1: 1854 Rd = 13; 1855 setflags = false; 1856 imm32 = ThumbImm7Scaled(opcode); // imm32 = ZeroExtend(imm7:'00', 32) 1857 break; 1858 case eEncodingT2: 1859 Rd = Bits32(opcode, 11, 8); 1860 setflags = BitIsSet(opcode, 20); 1861 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8) 1862 if (Rd == 15 && setflags) 1863 return EmulateCMPImm(opcode, eEncodingT2); 1864 if (Rd == 15 && !setflags) 1865 return false; 1866 break; 1867 case eEncodingT3: 1868 Rd = Bits32(opcode, 11, 8); 1869 setflags = false; 1870 imm32 = ThumbImm12(opcode); // imm32 = ZeroExtend(i:imm3:imm8, 32) 1871 if (Rd == 15) 1872 return false; 1873 break; 1874 case eEncodingA1: 1875 Rd = Bits32(opcode, 15, 12); 1876 setflags = BitIsSet(opcode, 20); 1877 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12) 1878 1879 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions; 1880 if (Rd == 15 && setflags) 1881 return EmulateSUBSPcLrEtc (opcode, encoding); 1882 break; 1883 default: 1884 return false; 1885 } 1886 AddWithCarryResult res = AddWithCarry(sp, ~imm32, 1); 1887 1888 EmulateInstruction::Context context; 1889 if (Rd == 13) 1890 { 1891 uint64_t imm64 = imm32; // Need to expand it to 64 bits before attempting to negate it, or the wrong 1892 // value gets passed down to context.SetImmediateSigned. 1893 context.type = EmulateInstruction::eContextAdjustStackPointer; 1894 context.SetImmediateSigned (-imm64); // the stack pointer offset 1895 } 1896 else 1897 { 1898 context.type = EmulateInstruction::eContextImmediate; 1899 context.SetNoArgs (); 1900 } 1901 1902 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow)) 1903 return false; 1904 } 1905 return true; 1906} 1907 1908// A store operation to the stack that also updates the SP. 1909bool 1910EmulateInstructionARM::EmulateSTRRtSP (const uint32_t opcode, const ARMEncoding encoding) 1911{ 1912#if 0 1913 // ARM pseudo code... 1914 if (ConditionPassed()) 1915 { 1916 EncodingSpecificOperations(); 1917 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32); 1918 address = if index then offset_addr else R[n]; 1919 MemU[address,4] = if t == 15 then PCStoreValue() else R[t]; 1920 if wback then R[n] = offset_addr; 1921 } 1922#endif 1923 1924 bool conditional = false; 1925 bool success = false; 1926 if (ConditionPassed(opcode, &conditional)) 1927 { 1928 const uint32_t addr_byte_size = GetAddressByteSize(); 1929 const addr_t sp = ReadCoreReg (SP_REG, &success); 1930 if (!success) 1931 return false; 1932 uint32_t Rt; // the source register 1933 uint32_t imm12; 1934 uint32_t Rn; // This function assumes Rn is the SP, but we should verify that. 1935 1936 bool index; 1937 bool add; 1938 bool wback; 1939 switch (encoding) { 1940 case eEncodingA1: 1941 Rt = Bits32(opcode, 15, 12); 1942 imm12 = Bits32(opcode, 11, 0); 1943 Rn = Bits32 (opcode, 19, 16); 1944 1945 if (Rn != 13) // 13 is the SP reg on ARM. Verify that Rn == SP. 1946 return false; 1947 1948 index = BitIsSet (opcode, 24); 1949 add = BitIsSet (opcode, 23); 1950 wback = (BitIsClear (opcode, 24) || BitIsSet (opcode, 21)); 1951 1952 if (wback && ((Rn == 15) || (Rn == Rt))) 1953 return false; 1954 break; 1955 default: 1956 return false; 1957 } 1958 addr_t offset_addr; 1959 if (add) 1960 offset_addr = sp + imm12; 1961 else 1962 offset_addr = sp - imm12; 1963 1964 addr_t addr; 1965 if (index) 1966 addr = offset_addr; 1967 else 1968 addr = sp; 1969 1970 EmulateInstruction::Context context; 1971 if (conditional) 1972 context.type = EmulateInstruction::eContextRegisterStore; 1973 else 1974 context.type = EmulateInstruction::eContextPushRegisterOnStack; 1975 RegisterInfo sp_reg; 1976 RegisterInfo dwarf_reg; 1977 1978 GetRegisterInfo (eRegisterKindDWARF, dwarf_sp, sp_reg); 1979 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + Rt, dwarf_reg); 1980 context.SetRegisterToRegisterPlusOffset ( dwarf_reg, sp_reg, addr - sp); 1981 if (Rt != 15) 1982 { 1983 uint32_t reg_value = ReadCoreReg(Rt, &success); 1984 if (!success) 1985 return false; 1986 if (!MemUWrite (context, addr, reg_value, addr_byte_size)) 1987 return false; 1988 } 1989 else 1990 { 1991 const uint32_t pc = ReadCoreReg(PC_REG, &success); 1992 if (!success) 1993 return false; 1994 if (!MemUWrite (context, addr, pc, addr_byte_size)) 1995 return false; 1996 } 1997 1998 1999 if (wback) 2000 { 2001 context.type = EmulateInstruction::eContextAdjustStackPointer; 2002 context.SetImmediateSigned (addr - sp); 2003 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, offset_addr)) 2004 return false; 2005 } 2006 } 2007 return true; 2008} 2009 2010// Vector Push stores multiple extension registers to the stack. 2011// It also updates SP to point to the start of the stored data. 2012bool 2013EmulateInstructionARM::EmulateVPUSH (const uint32_t opcode, const ARMEncoding encoding) 2014{ 2015#if 0 2016 // ARM pseudo code... 2017 if (ConditionPassed()) 2018 { 2019 EncodingSpecificOperations(); CheckVFPEnabled(TRUE); NullCheckIfThumbEE(13); 2020 address = SP - imm32; 2021 SP = SP - imm32; 2022 if single_regs then 2023 for r = 0 to regs-1 2024 MemA[address,4] = S[d+r]; address = address+4; 2025 else 2026 for r = 0 to regs-1 2027 // Store as two word-aligned words in the correct order for current endianness. 2028 MemA[address,4] = if BigEndian() then D[d+r]<63:32> else D[d+r]<31:0>; 2029 MemA[address+4,4] = if BigEndian() then D[d+r]<31:0> else D[d+r]<63:32>; 2030 address = address+8; 2031 } 2032#endif 2033 2034 bool success = false; 2035 bool conditional = false; 2036 if (ConditionPassed(opcode, &conditional)) 2037 { 2038 const uint32_t addr_byte_size = GetAddressByteSize(); 2039 const addr_t sp = ReadCoreReg (SP_REG, &success); 2040 if (!success) 2041 return false; 2042 bool single_regs; 2043 uint32_t d; // UInt(D:Vd) or UInt(Vd:D) starting register 2044 uint32_t imm32; // stack offset 2045 uint32_t regs; // number of registers 2046 switch (encoding) { 2047 case eEncodingT1: 2048 case eEncodingA1: 2049 single_regs = false; 2050 d = Bit32(opcode, 22) << 4 | Bits32(opcode, 15, 12); 2051 imm32 = Bits32(opcode, 7, 0) * addr_byte_size; 2052 // If UInt(imm8) is odd, see "FSTMX". 2053 regs = Bits32(opcode, 7, 0) / 2; 2054 // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE; 2055 if (regs == 0 || regs > 16 || (d + regs) > 32) 2056 return false; 2057 break; 2058 case eEncodingT2: 2059 case eEncodingA2: 2060 single_regs = true; 2061 d = Bits32(opcode, 15, 12) << 1 | Bit32(opcode, 22); 2062 imm32 = Bits32(opcode, 7, 0) * addr_byte_size; 2063 regs = Bits32(opcode, 7, 0); 2064 // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE; 2065 if (regs == 0 || regs > 16 || (d + regs) > 32) 2066 return false; 2067 break; 2068 default: 2069 return false; 2070 } 2071 uint32_t start_reg = single_regs ? dwarf_s0 : dwarf_d0; 2072 uint32_t reg_byte_size = single_regs ? addr_byte_size : addr_byte_size * 2; 2073 addr_t sp_offset = imm32; 2074 addr_t addr = sp - sp_offset; 2075 uint32_t i; 2076 2077 EmulateInstruction::Context context; 2078 if (conditional) 2079 context.type = EmulateInstruction::eContextRegisterStore; 2080 else 2081 context.type = EmulateInstruction::eContextPushRegisterOnStack; 2082 RegisterInfo dwarf_reg; 2083 RegisterInfo sp_reg; 2084 GetRegisterInfo (eRegisterKindDWARF, dwarf_sp, sp_reg); 2085 for (i=0; i<regs; ++i) 2086 { 2087 GetRegisterInfo (eRegisterKindDWARF, start_reg + d + i, dwarf_reg); 2088 context.SetRegisterToRegisterPlusOffset ( dwarf_reg, sp_reg, addr - sp); 2089 // uint64_t to accommodate 64-bit registers. 2090 uint64_t reg_value = ReadRegisterUnsigned (&dwarf_reg, 0, &success); 2091 if (!success) 2092 return false; 2093 if (!MemAWrite (context, addr, reg_value, reg_byte_size)) 2094 return false; 2095 addr += reg_byte_size; 2096 } 2097 2098 context.type = EmulateInstruction::eContextAdjustStackPointer; 2099 context.SetImmediateSigned (-sp_offset); 2100 2101 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, sp - sp_offset)) 2102 return false; 2103 } 2104 return true; 2105} 2106 2107// Vector Pop loads multiple extension registers from the stack. 2108// It also updates SP to point just above the loaded data. 2109bool 2110EmulateInstructionARM::EmulateVPOP (const uint32_t opcode, const ARMEncoding encoding) 2111{ 2112#if 0 2113 // ARM pseudo code... 2114 if (ConditionPassed()) 2115 { 2116 EncodingSpecificOperations(); CheckVFPEnabled(TRUE); NullCheckIfThumbEE(13); 2117 address = SP; 2118 SP = SP + imm32; 2119 if single_regs then 2120 for r = 0 to regs-1 2121 S[d+r] = MemA[address,4]; address = address+4; 2122 else 2123 for r = 0 to regs-1 2124 word1 = MemA[address,4]; word2 = MemA[address+4,4]; address = address+8; 2125 // Combine the word-aligned words in the correct order for current endianness. 2126 D[d+r] = if BigEndian() then word1:word2 else word2:word1; 2127 } 2128#endif 2129 2130 bool success = false; 2131 bool conditional = false; 2132 if (ConditionPassed(opcode, &conditional)) 2133 { 2134 const uint32_t addr_byte_size = GetAddressByteSize(); 2135 const addr_t sp = ReadCoreReg (SP_REG, &success); 2136 if (!success) 2137 return false; 2138 bool single_regs; 2139 uint32_t d; // UInt(D:Vd) or UInt(Vd:D) starting register 2140 uint32_t imm32; // stack offset 2141 uint32_t regs; // number of registers 2142 switch (encoding) { 2143 case eEncodingT1: 2144 case eEncodingA1: 2145 single_regs = false; 2146 d = Bit32(opcode, 22) << 4 | Bits32(opcode, 15, 12); 2147 imm32 = Bits32(opcode, 7, 0) * addr_byte_size; 2148 // If UInt(imm8) is odd, see "FLDMX". 2149 regs = Bits32(opcode, 7, 0) / 2; 2150 // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE; 2151 if (regs == 0 || regs > 16 || (d + regs) > 32) 2152 return false; 2153 break; 2154 case eEncodingT2: 2155 case eEncodingA2: 2156 single_regs = true; 2157 d = Bits32(opcode, 15, 12) << 1 | Bit32(opcode, 22); 2158 imm32 = Bits32(opcode, 7, 0) * addr_byte_size; 2159 regs = Bits32(opcode, 7, 0); 2160 // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE; 2161 if (regs == 0 || regs > 16 || (d + regs) > 32) 2162 return false; 2163 break; 2164 default: 2165 return false; 2166 } 2167 uint32_t start_reg = single_regs ? dwarf_s0 : dwarf_d0; 2168 uint32_t reg_byte_size = single_regs ? addr_byte_size : addr_byte_size * 2; 2169 addr_t sp_offset = imm32; 2170 addr_t addr = sp; 2171 uint32_t i; 2172 uint64_t data; // uint64_t to accomodate 64-bit registers. 2173 2174 EmulateInstruction::Context context; 2175 if (conditional) 2176 context.type = EmulateInstruction::eContextRegisterLoad; 2177 else 2178 context.type = EmulateInstruction::eContextPopRegisterOffStack; 2179 RegisterInfo dwarf_reg; 2180 RegisterInfo sp_reg; 2181 GetRegisterInfo (eRegisterKindDWARF, dwarf_sp, sp_reg); 2182 for (i=0; i<regs; ++i) 2183 { 2184 GetRegisterInfo (eRegisterKindDWARF, start_reg + d + i, dwarf_reg); 2185 context.SetRegisterPlusOffset (sp_reg, addr - sp); 2186 data = MemARead(context, addr, reg_byte_size, 0, &success); 2187 if (!success) 2188 return false; 2189 if (!WriteRegisterUnsigned(context, &dwarf_reg, data)) 2190 return false; 2191 addr += reg_byte_size; 2192 } 2193 2194 context.type = EmulateInstruction::eContextAdjustStackPointer; 2195 context.SetImmediateSigned (sp_offset); 2196 2197 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, sp + sp_offset)) 2198 return false; 2199 } 2200 return true; 2201} 2202 2203// SVC (previously SWI) 2204bool 2205EmulateInstructionARM::EmulateSVC (const uint32_t opcode, const ARMEncoding encoding) 2206{ 2207#if 0 2208 // ARM pseudo code... 2209 if (ConditionPassed()) 2210 { 2211 EncodingSpecificOperations(); 2212 CallSupervisor(); 2213 } 2214#endif 2215 2216 bool success = false; 2217 2218 if (ConditionPassed(opcode)) 2219 { 2220 const uint32_t pc = ReadCoreReg(PC_REG, &success); 2221 addr_t lr; // next instruction address 2222 if (!success) 2223 return false; 2224 uint32_t imm32; // the immediate constant 2225 uint32_t mode; // ARM or Thumb mode 2226 switch (encoding) { 2227 case eEncodingT1: 2228 lr = (pc + 2) | 1u; // return address 2229 imm32 = Bits32(opcode, 7, 0); 2230 mode = eModeThumb; 2231 break; 2232 case eEncodingA1: 2233 lr = pc + 4; // return address 2234 imm32 = Bits32(opcode, 23, 0); 2235 mode = eModeARM; 2236 break; 2237 default: 2238 return false; 2239 } 2240 2241 EmulateInstruction::Context context; 2242 context.type = EmulateInstruction::eContextSupervisorCall; 2243 context.SetISAAndImmediate (mode, imm32); 2244 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_RA, lr)) 2245 return false; 2246 } 2247 return true; 2248} 2249 2250// If Then makes up to four following instructions (the IT block) conditional. 2251bool 2252EmulateInstructionARM::EmulateIT (const uint32_t opcode, const ARMEncoding encoding) 2253{ 2254#if 0 2255 // ARM pseudo code... 2256 EncodingSpecificOperations(); 2257 ITSTATE.IT<7:0> = firstcond:mask; 2258#endif 2259 2260 m_it_session.InitIT(Bits32(opcode, 7, 0)); 2261 return true; 2262} 2263 2264bool 2265EmulateInstructionARM::EmulateNop (const uint32_t opcode, const ARMEncoding encoding) 2266{ 2267 // NOP, nothing to do... 2268 return true; 2269} 2270 2271// Branch causes a branch to a target address. 2272bool 2273EmulateInstructionARM::EmulateB (const uint32_t opcode, const ARMEncoding encoding) 2274{ 2275#if 0 2276 // ARM pseudo code... 2277 if (ConditionPassed()) 2278 { 2279 EncodingSpecificOperations(); 2280 BranchWritePC(PC + imm32); 2281 } 2282#endif 2283 2284 bool success = false; 2285 2286 if (ConditionPassed(opcode)) 2287 { 2288 EmulateInstruction::Context context; 2289 context.type = EmulateInstruction::eContextRelativeBranchImmediate; 2290 const uint32_t pc = ReadCoreReg(PC_REG, &success); 2291 if (!success) 2292 return false; 2293 addr_t target; // target address 2294 int32_t imm32; // PC-relative offset 2295 switch (encoding) { 2296 case eEncodingT1: 2297 // The 'cond' field is handled in EmulateInstructionARM::CurrentCond(). 2298 imm32 = llvm::SignExtend32<9>(Bits32(opcode, 7, 0) << 1); 2299 target = pc + imm32; 2300 context.SetISAAndImmediateSigned (eModeThumb, 4 + imm32); 2301 break; 2302 case eEncodingT2: 2303 imm32 = llvm::SignExtend32<12>(Bits32(opcode, 10, 0)); 2304 target = pc + imm32; 2305 context.SetISAAndImmediateSigned (eModeThumb, 4 + imm32); 2306 break; 2307 case eEncodingT3: 2308 // The 'cond' field is handled in EmulateInstructionARM::CurrentCond(). 2309 { 2310 uint32_t S = Bit32(opcode, 26); 2311 uint32_t imm6 = Bits32(opcode, 21, 16); 2312 uint32_t J1 = Bit32(opcode, 13); 2313 uint32_t J2 = Bit32(opcode, 11); 2314 uint32_t imm11 = Bits32(opcode, 10, 0); 2315 uint32_t imm21 = (S << 20) | (J2 << 19) | (J1 << 18) | (imm6 << 12) | (imm11 << 1); 2316 imm32 = llvm::SignExtend32<21>(imm21); 2317 target = pc + imm32; 2318 context.SetISAAndImmediateSigned (eModeThumb, 4 + imm32); 2319 break; 2320 } 2321 case eEncodingT4: 2322 { 2323 uint32_t S = Bit32(opcode, 26); 2324 uint32_t imm10 = Bits32(opcode, 25, 16); 2325 uint32_t J1 = Bit32(opcode, 13); 2326 uint32_t J2 = Bit32(opcode, 11); 2327 uint32_t imm11 = Bits32(opcode, 10, 0); 2328 uint32_t I1 = !(J1 ^ S); 2329 uint32_t I2 = !(J2 ^ S); 2330 uint32_t imm25 = (S << 24) | (I1 << 23) | (I2 << 22) | (imm10 << 12) | (imm11 << 1); 2331 imm32 = llvm::SignExtend32<25>(imm25); 2332 target = pc + imm32; 2333 context.SetISAAndImmediateSigned (eModeThumb, 4 + imm32); 2334 break; 2335 } 2336 case eEncodingA1: 2337 imm32 = llvm::SignExtend32<26>(Bits32(opcode, 23, 0) << 2); 2338 target = pc + imm32; 2339 context.SetISAAndImmediateSigned (eModeARM, 8 + imm32); 2340 break; 2341 default: 2342 return false; 2343 } 2344 if (!BranchWritePC(context, target)) 2345 return false; 2346 } 2347 return true; 2348} 2349 2350// Compare and Branch on Nonzero and Compare and Branch on Zero compare the value in a register with 2351// zero and conditionally branch forward a constant value. They do not affect the condition flags. 2352// CBNZ, CBZ 2353bool 2354EmulateInstructionARM::EmulateCB (const uint32_t opcode, const ARMEncoding encoding) 2355{ 2356#if 0 2357 // ARM pseudo code... 2358 EncodingSpecificOperations(); 2359 if nonzero ^ IsZero(R[n]) then 2360 BranchWritePC(PC + imm32); 2361#endif 2362 2363 bool success = false; 2364 2365 // Read the register value from the operand register Rn. 2366 uint32_t reg_val = ReadCoreReg(Bits32(opcode, 2, 0), &success); 2367 if (!success) 2368 return false; 2369 2370 EmulateInstruction::Context context; 2371 context.type = EmulateInstruction::eContextRelativeBranchImmediate; 2372 const uint32_t pc = ReadCoreReg(PC_REG, &success); 2373 if (!success) 2374 return false; 2375 2376 addr_t target; // target address 2377 uint32_t imm32; // PC-relative offset to branch forward 2378 bool nonzero; 2379 switch (encoding) { 2380 case eEncodingT1: 2381 imm32 = Bit32(opcode, 9) << 6 | Bits32(opcode, 7, 3) << 1; 2382 nonzero = BitIsSet(opcode, 11); 2383 target = pc + imm32; 2384 context.SetISAAndImmediateSigned (eModeThumb, 4 + imm32); 2385 break; 2386 default: 2387 return false; 2388 } 2389 if (nonzero ^ (reg_val == 0)) 2390 if (!BranchWritePC(context, target)) 2391 return false; 2392 2393 return true; 2394} 2395 2396// Table Branch Byte causes a PC-relative forward branch using a table of single byte offsets. 2397// A base register provides a pointer to the table, and a second register supplies an index into the table. 2398// The branch length is twice the value of the byte returned from the table. 2399// 2400// Table Branch Halfword causes a PC-relative forward branch using a table of single halfword offsets. 2401// A base register provides a pointer to the table, and a second register supplies an index into the table. 2402// The branch length is twice the value of the halfword returned from the table. 2403// TBB, TBH 2404bool 2405EmulateInstructionARM::EmulateTB (const uint32_t opcode, const ARMEncoding encoding) 2406{ 2407#if 0 2408 // ARM pseudo code... 2409 EncodingSpecificOperations(); NullCheckIfThumbEE(n); 2410 if is_tbh then 2411 halfwords = UInt(MemU[R[n]+LSL(R[m],1), 2]); 2412 else 2413 halfwords = UInt(MemU[R[n]+R[m], 1]); 2414 BranchWritePC(PC + 2*halfwords); 2415#endif 2416 2417 bool success = false; 2418 2419 uint32_t Rn; // the base register which contains the address of the table of branch lengths 2420 uint32_t Rm; // the index register which contains an integer pointing to a byte/halfword in the table 2421 bool is_tbh; // true if table branch halfword 2422 switch (encoding) { 2423 case eEncodingT1: 2424 Rn = Bits32(opcode, 19, 16); 2425 Rm = Bits32(opcode, 3, 0); 2426 is_tbh = BitIsSet(opcode, 4); 2427 if (Rn == 13 || BadReg(Rm)) 2428 return false; 2429 if (InITBlock() && !LastInITBlock()) 2430 return false; 2431 break; 2432 default: 2433 return false; 2434 } 2435 2436 // Read the address of the table from the operand register Rn. 2437 // The PC can be used, in which case the table immediately follows this instruction. 2438 uint32_t base = ReadCoreReg(Rm, &success); 2439 if (!success) 2440 return false; 2441 2442 // the table index 2443 uint32_t index = ReadCoreReg(Rm, &success); 2444 if (!success) 2445 return false; 2446 2447 // the offsetted table address 2448 addr_t addr = base + (is_tbh ? index*2 : index); 2449 2450 // PC-relative offset to branch forward 2451 EmulateInstruction::Context context; 2452 context.type = EmulateInstruction::eContextTableBranchReadMemory; 2453 uint32_t offset = MemURead(context, addr, is_tbh ? 2 : 1, 0, &success) * 2; 2454 if (!success) 2455 return false; 2456 2457 const uint32_t pc = ReadCoreReg(PC_REG, &success); 2458 if (!success) 2459 return false; 2460 2461 // target address 2462 addr_t target = pc + offset; 2463 context.type = EmulateInstruction::eContextRelativeBranchImmediate; 2464 context.SetISAAndImmediateSigned (eModeThumb, 4 + offset); 2465 2466 if (!BranchWritePC(context, target)) 2467 return false; 2468 2469 return true; 2470} 2471 2472// This instruction adds an immediate value to a register value, and writes the result to the destination register. 2473// It can optionally update the condition flags based on the result. 2474bool 2475EmulateInstructionARM::EmulateADDImmThumb (const uint32_t opcode, const ARMEncoding encoding) 2476{ 2477#if 0 2478 if ConditionPassed() then 2479 EncodingSpecificOperations(); 2480 (result, carry, overflow) = AddWithCarry(R[n], imm32, '0'); 2481 R[d] = result; 2482 if setflags then 2483 APSR.N = result<31>; 2484 APSR.Z = IsZeroBit(result); 2485 APSR.C = carry; 2486 APSR.V = overflow; 2487#endif 2488 2489 bool success = false; 2490 2491 if (ConditionPassed(opcode)) 2492 { 2493 uint32_t d; 2494 uint32_t n; 2495 bool setflags; 2496 uint32_t imm32; 2497 uint32_t carry_out; 2498 2499 //EncodingSpecificOperations(); 2500 switch (encoding) 2501 { 2502 case eEncodingT1: 2503 // d = UInt(Rd); n = UInt(Rn); setflags = !InITBlock(); imm32 = ZeroExtend(imm3, 32); 2504 d = Bits32 (opcode, 2, 0); 2505 n = Bits32 (opcode, 5, 3); 2506 setflags = !InITBlock(); 2507 imm32 = Bits32 (opcode, 8,6); 2508 2509 break; 2510 2511 case eEncodingT2: 2512 // d = UInt(Rdn); n = UInt(Rdn); setflags = !InITBlock(); imm32 = ZeroExtend(imm8, 32); 2513 d = Bits32 (opcode, 10, 8); 2514 n = Bits32 (opcode, 10, 8); 2515 setflags = !InITBlock(); 2516 imm32 = Bits32 (opcode, 7, 0); 2517 2518 break; 2519 2520 case eEncodingT3: 2521 // if Rd == '1111' && S == '1' then SEE CMN (immediate); 2522 // if Rn == '1101' then SEE ADD (SP plus immediate); 2523 // d = UInt(Rd); n = UInt(Rn); setflags = (S == '1'); imm32 = ThumbExpandImm(i:imm3:imm8); 2524 d = Bits32 (opcode, 11, 8); 2525 n = Bits32 (opcode, 19, 16); 2526 setflags = BitIsSet (opcode, 20); 2527 imm32 = ThumbExpandImm_C (opcode, APSR_C, carry_out); 2528 2529 // if BadReg(d) || n == 15 then UNPREDICTABLE; 2530 if (BadReg (d) || (n == 15)) 2531 return false; 2532 2533 break; 2534 2535 case eEncodingT4: 2536 { 2537 // if Rn == '1111' then SEE ADR; 2538 // if Rn == '1101' then SEE ADD (SP plus immediate); 2539 // d = UInt(Rd); n = UInt(Rn); setflags = FALSE; imm32 = ZeroExtend(i:imm3:imm8, 32); 2540 d = Bits32 (opcode, 11, 8); 2541 n = Bits32 (opcode, 19, 16); 2542 setflags = false; 2543 uint32_t i = Bit32 (opcode, 26); 2544 uint32_t imm3 = Bits32 (opcode, 14, 12); 2545 uint32_t imm8 = Bits32 (opcode, 7, 0); 2546 imm32 = (i << 11) | (imm3 << 8) | imm8; 2547 2548 // if BadReg(d) then UNPREDICTABLE; 2549 if (BadReg (d)) 2550 return false; 2551 2552 break; 2553 } 2554 default: 2555 return false; 2556 } 2557 2558 uint64_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success); 2559 if (!success) 2560 return false; 2561 2562 //(result, carry, overflow) = AddWithCarry(R[n], imm32, '0'); 2563 AddWithCarryResult res = AddWithCarry (Rn, imm32, 0); 2564 2565 RegisterInfo reg_n; 2566 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, reg_n); 2567 2568 EmulateInstruction::Context context; 2569 context.type = eContextArithmetic; 2570 context.SetRegisterPlusOffset (reg_n, imm32); 2571 2572 //R[d] = result; 2573 //if setflags then 2574 //APSR.N = result<31>; 2575 //APSR.Z = IsZeroBit(result); 2576 //APSR.C = carry; 2577 //APSR.V = overflow; 2578 if (!WriteCoreRegOptionalFlags (context, res.result, d, setflags, res.carry_out, res.overflow)) 2579 return false; 2580 2581 } 2582 return true; 2583} 2584 2585// This instruction adds an immediate value to a register value, and writes the result to the destination 2586// register. It can optionally update the condition flags based on the result. 2587bool 2588EmulateInstructionARM::EmulateADDImmARM (const uint32_t opcode, const ARMEncoding encoding) 2589{ 2590#if 0 2591 // ARM pseudo code... 2592 if ConditionPassed() then 2593 EncodingSpecificOperations(); 2594 (result, carry, overflow) = AddWithCarry(R[n], imm32, '0'); 2595 if d == 15 then 2596 ALUWritePC(result); // setflags is always FALSE here 2597 else 2598 R[d] = result; 2599 if setflags then 2600 APSR.N = result<31>; 2601 APSR.Z = IsZeroBit(result); 2602 APSR.C = carry; 2603 APSR.V = overflow; 2604#endif 2605 2606 bool success = false; 2607 2608 if (ConditionPassed(opcode)) 2609 { 2610 uint32_t Rd, Rn; 2611 uint32_t imm32; // the immediate value to be added to the value obtained from Rn 2612 bool setflags; 2613 switch (encoding) 2614 { 2615 case eEncodingA1: 2616 Rd = Bits32(opcode, 15, 12); 2617 Rn = Bits32(opcode, 19, 16); 2618 setflags = BitIsSet(opcode, 20); 2619 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12) 2620 break; 2621 default: 2622 return false; 2623 } 2624 2625 // Read the first operand. 2626 uint32_t val1 = ReadCoreReg(Rn, &success); 2627 if (!success) 2628 return false; 2629 2630 AddWithCarryResult res = AddWithCarry(val1, imm32, 0); 2631 2632 EmulateInstruction::Context context; 2633 context.type = eContextArithmetic; 2634 RegisterInfo dwarf_reg; 2635 GetRegisterInfo (eRegisterKindDWARF, Rn, dwarf_reg); 2636 context.SetRegisterPlusOffset (dwarf_reg, imm32); 2637 2638 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow)) 2639 return false; 2640 } 2641 return true; 2642} 2643 2644// This instruction adds a register value and an optionally-shifted register value, and writes the result 2645// to the destination register. It can optionally update the condition flags based on the result. 2646bool 2647EmulateInstructionARM::EmulateADDReg (const uint32_t opcode, const ARMEncoding encoding) 2648{ 2649#if 0 2650 // ARM pseudo code... 2651 if ConditionPassed() then 2652 EncodingSpecificOperations(); 2653 shifted = Shift(R[m], shift_t, shift_n, APSR.C); 2654 (result, carry, overflow) = AddWithCarry(R[n], shifted, '0'); 2655 if d == 15 then 2656 ALUWritePC(result); // setflags is always FALSE here 2657 else 2658 R[d] = result; 2659 if setflags then 2660 APSR.N = result<31>; 2661 APSR.Z = IsZeroBit(result); 2662 APSR.C = carry; 2663 APSR.V = overflow; 2664#endif 2665 2666 bool success = false; 2667 2668 if (ConditionPassed(opcode)) 2669 { 2670 uint32_t Rd, Rn, Rm; 2671 ARM_ShifterType shift_t; 2672 uint32_t shift_n; // the shift applied to the value read from Rm 2673 bool setflags; 2674 switch (encoding) 2675 { 2676 case eEncodingT1: 2677 Rd = Bits32(opcode, 2, 0); 2678 Rn = Bits32(opcode, 5, 3); 2679 Rm = Bits32(opcode, 8, 6); 2680 setflags = !InITBlock(); 2681 shift_t = SRType_LSL; 2682 shift_n = 0; 2683 break; 2684 case eEncodingT2: 2685 Rd = Rn = Bit32(opcode, 7) << 3 | Bits32(opcode, 2, 0); 2686 Rm = Bits32(opcode, 6, 3); 2687 setflags = false; 2688 shift_t = SRType_LSL; 2689 shift_n = 0; 2690 if (Rn == 15 && Rm == 15) 2691 return false; 2692 if (Rd == 15 && InITBlock() && !LastInITBlock()) 2693 return false; 2694 break; 2695 case eEncodingA1: 2696 Rd = Bits32(opcode, 15, 12); 2697 Rn = Bits32(opcode, 19, 16); 2698 Rm = Bits32(opcode, 3, 0); 2699 setflags = BitIsSet(opcode, 20); 2700 shift_n = DecodeImmShiftARM(opcode, shift_t); 2701 break; 2702 default: 2703 return false; 2704 } 2705 2706 // Read the first operand. 2707 uint32_t val1 = ReadCoreReg(Rn, &success); 2708 if (!success) 2709 return false; 2710 2711 // Read the second operand. 2712 uint32_t val2 = ReadCoreReg(Rm, &success); 2713 if (!success) 2714 return false; 2715 2716 uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C, &success); 2717 if (!success) 2718 return false; 2719 AddWithCarryResult res = AddWithCarry(val1, shifted, 0); 2720 2721 EmulateInstruction::Context context; 2722 context.type = eContextArithmetic; 2723 RegisterInfo op1_reg; 2724 RegisterInfo op2_reg; 2725 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + Rn, op1_reg); 2726 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + Rm, op2_reg); 2727 context.SetRegisterRegisterOperands (op1_reg, op2_reg); 2728 2729 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow)) 2730 return false; 2731 } 2732 return true; 2733} 2734 2735// Compare Negative (immediate) adds a register value and an immediate value. 2736// It updates the condition flags based on the result, and discards the result. 2737bool 2738EmulateInstructionARM::EmulateCMNImm (const uint32_t opcode, const ARMEncoding encoding) 2739{ 2740#if 0 2741 // ARM pseudo code... 2742 if ConditionPassed() then 2743 EncodingSpecificOperations(); 2744 (result, carry, overflow) = AddWithCarry(R[n], imm32, '0'); 2745 APSR.N = result<31>; 2746 APSR.Z = IsZeroBit(result); 2747 APSR.C = carry; 2748 APSR.V = overflow; 2749#endif 2750 2751 bool success = false; 2752 2753 uint32_t Rn; // the first operand 2754 uint32_t imm32; // the immediate value to be compared with 2755 switch (encoding) { 2756 case eEncodingT1: 2757 Rn = Bits32(opcode, 19, 16); 2758 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8) 2759 if (Rn == 15) 2760 return false; 2761 break; 2762 case eEncodingA1: 2763 Rn = Bits32(opcode, 19, 16); 2764 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12) 2765 break; 2766 default: 2767 return false; 2768 } 2769 // Read the register value from the operand register Rn. 2770 uint32_t reg_val = ReadCoreReg(Rn, &success); 2771 if (!success) 2772 return false; 2773 2774 AddWithCarryResult res = AddWithCarry(reg_val, imm32, 0); 2775 2776 EmulateInstruction::Context context; 2777 context.type = EmulateInstruction::eContextImmediate; 2778 context.SetNoArgs (); 2779 if (!WriteFlags(context, res.result, res.carry_out, res.overflow)) 2780 return false; 2781 2782 return true; 2783} 2784 2785// Compare Negative (register) adds a register value and an optionally-shifted register value. 2786// It updates the condition flags based on the result, and discards the result. 2787bool 2788EmulateInstructionARM::EmulateCMNReg (const uint32_t opcode, const ARMEncoding encoding) 2789{ 2790#if 0 2791 // ARM pseudo code... 2792 if ConditionPassed() then 2793 EncodingSpecificOperations(); 2794 shifted = Shift(R[m], shift_t, shift_n, APSR.C); 2795 (result, carry, overflow) = AddWithCarry(R[n], shifted, '0'); 2796 APSR.N = result<31>; 2797 APSR.Z = IsZeroBit(result); 2798 APSR.C = carry; 2799 APSR.V = overflow; 2800#endif 2801 2802 bool success = false; 2803 2804 uint32_t Rn; // the first operand 2805 uint32_t Rm; // the second operand 2806 ARM_ShifterType shift_t; 2807 uint32_t shift_n; // the shift applied to the value read from Rm 2808 switch (encoding) { 2809 case eEncodingT1: 2810 Rn = Bits32(opcode, 2, 0); 2811 Rm = Bits32(opcode, 5, 3); 2812 shift_t = SRType_LSL; 2813 shift_n = 0; 2814 break; 2815 case eEncodingT2: 2816 Rn = Bits32(opcode, 19, 16); 2817 Rm = Bits32(opcode, 3, 0); 2818 shift_n = DecodeImmShiftThumb(opcode, shift_t); 2819 // if n == 15 || BadReg(m) then UNPREDICTABLE; 2820 if (Rn == 15 || BadReg(Rm)) 2821 return false; 2822 break; 2823 case eEncodingA1: 2824 Rn = Bits32(opcode, 19, 16); 2825 Rm = Bits32(opcode, 3, 0); 2826 shift_n = DecodeImmShiftARM(opcode, shift_t); 2827 break; 2828 default: 2829 return false; 2830 } 2831 // Read the register value from register Rn. 2832 uint32_t val1 = ReadCoreReg(Rn, &success); 2833 if (!success) 2834 return false; 2835 2836 // Read the register value from register Rm. 2837 uint32_t val2 = ReadCoreReg(Rm, &success); 2838 if (!success) 2839 return false; 2840 2841 uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C, &success); 2842 if (!success) 2843 return false; 2844 AddWithCarryResult res = AddWithCarry(val1, shifted, 0); 2845 2846 EmulateInstruction::Context context; 2847 context.type = EmulateInstruction::eContextImmediate; 2848 context.SetNoArgs(); 2849 if (!WriteFlags(context, res.result, res.carry_out, res.overflow)) 2850 return false; 2851 2852 return true; 2853} 2854 2855// Compare (immediate) subtracts an immediate value from a register value. 2856// It updates the condition flags based on the result, and discards the result. 2857bool 2858EmulateInstructionARM::EmulateCMPImm (const uint32_t opcode, const ARMEncoding encoding) 2859{ 2860#if 0 2861 // ARM pseudo code... 2862 if ConditionPassed() then 2863 EncodingSpecificOperations(); 2864 (result, carry, overflow) = AddWithCarry(R[n], NOT(imm32), '1'); 2865 APSR.N = result<31>; 2866 APSR.Z = IsZeroBit(result); 2867 APSR.C = carry; 2868 APSR.V = overflow; 2869#endif 2870 2871 bool success = false; 2872 2873 uint32_t Rn; // the first operand 2874 uint32_t imm32; // the immediate value to be compared with 2875 switch (encoding) { 2876 case eEncodingT1: 2877 Rn = Bits32(opcode, 10, 8); 2878 imm32 = Bits32(opcode, 7, 0); 2879 break; 2880 case eEncodingT2: 2881 Rn = Bits32(opcode, 19, 16); 2882 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8) 2883 if (Rn == 15) 2884 return false; 2885 break; 2886 case eEncodingA1: 2887 Rn = Bits32(opcode, 19, 16); 2888 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12) 2889 break; 2890 default: 2891 return false; 2892 } 2893 // Read the register value from the operand register Rn. 2894 uint32_t reg_val = ReadCoreReg(Rn, &success); 2895 if (!success) 2896 return false; 2897 2898 AddWithCarryResult res = AddWithCarry(reg_val, ~imm32, 1); 2899 2900 EmulateInstruction::Context context; 2901 context.type = EmulateInstruction::eContextImmediate; 2902 context.SetNoArgs (); 2903 if (!WriteFlags(context, res.result, res.carry_out, res.overflow)) 2904 return false; 2905 2906 return true; 2907} 2908 2909// Compare (register) subtracts an optionally-shifted register value from a register value. 2910// It updates the condition flags based on the result, and discards the result. 2911bool 2912EmulateInstructionARM::EmulateCMPReg (const uint32_t opcode, const ARMEncoding encoding) 2913{ 2914#if 0 2915 // ARM pseudo code... 2916 if ConditionPassed() then 2917 EncodingSpecificOperations(); 2918 shifted = Shift(R[m], shift_t, shift_n, APSR.C); 2919 (result, carry, overflow) = AddWithCarry(R[n], NOT(shifted), '1'); 2920 APSR.N = result<31>; 2921 APSR.Z = IsZeroBit(result); 2922 APSR.C = carry; 2923 APSR.V = overflow; 2924#endif 2925 2926 bool success = false; 2927 2928 uint32_t Rn; // the first operand 2929 uint32_t Rm; // the second operand 2930 ARM_ShifterType shift_t; 2931 uint32_t shift_n; // the shift applied to the value read from Rm 2932 switch (encoding) { 2933 case eEncodingT1: 2934 Rn = Bits32(opcode, 2, 0); 2935 Rm = Bits32(opcode, 5, 3); 2936 shift_t = SRType_LSL; 2937 shift_n = 0; 2938 break; 2939 case eEncodingT2: 2940 Rn = Bit32(opcode, 7) << 3 | Bits32(opcode, 2, 0); 2941 Rm = Bits32(opcode, 6, 3); 2942 shift_t = SRType_LSL; 2943 shift_n = 0; 2944 if (Rn < 8 && Rm < 8) 2945 return false; 2946 if (Rn == 15 || Rm == 15) 2947 return false; 2948 break; 2949 case eEncodingA1: 2950 Rn = Bits32(opcode, 19, 16); 2951 Rm = Bits32(opcode, 3, 0); 2952 shift_n = DecodeImmShiftARM(opcode, shift_t); 2953 break; 2954 default: 2955 return false; 2956 } 2957 // Read the register value from register Rn. 2958 uint32_t val1 = ReadCoreReg(Rn, &success); 2959 if (!success) 2960 return false; 2961 2962 // Read the register value from register Rm. 2963 uint32_t val2 = ReadCoreReg(Rm, &success); 2964 if (!success) 2965 return false; 2966 2967 uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C, &success); 2968 if (!success) 2969 return false; 2970 AddWithCarryResult res = AddWithCarry(val1, ~shifted, 1); 2971 2972 EmulateInstruction::Context context; 2973 context.type = EmulateInstruction::eContextImmediate; 2974 context.SetNoArgs(); 2975 if (!WriteFlags(context, res.result, res.carry_out, res.overflow)) 2976 return false; 2977 2978 return true; 2979} 2980 2981// Arithmetic Shift Right (immediate) shifts a register value right by an immediate number of bits, 2982// shifting in copies of its sign bit, and writes the result to the destination register. It can 2983// optionally update the condition flags based on the result. 2984bool 2985EmulateInstructionARM::EmulateASRImm (const uint32_t opcode, const ARMEncoding encoding) 2986{ 2987#if 0 2988 // ARM pseudo code... 2989 if ConditionPassed() then 2990 EncodingSpecificOperations(); 2991 (result, carry) = Shift_C(R[m], SRType_ASR, shift_n, APSR.C); 2992 if d == 15 then // Can only occur for ARM encoding 2993 ALUWritePC(result); // setflags is always FALSE here 2994 else 2995 R[d] = result; 2996 if setflags then 2997 APSR.N = result<31>; 2998 APSR.Z = IsZeroBit(result); 2999 APSR.C = carry; 3000 // APSR.V unchanged 3001#endif 3002 3003 return EmulateShiftImm (opcode, encoding, SRType_ASR); 3004} 3005 3006// Arithmetic Shift Right (register) shifts a register value right by a variable number of bits, 3007// shifting in copies of its sign bit, and writes the result to the destination register. 3008// The variable number of bits is read from the bottom byte of a register. It can optionally update 3009// the condition flags based on the result. 3010bool 3011EmulateInstructionARM::EmulateASRReg (const uint32_t opcode, const ARMEncoding encoding) 3012{ 3013#if 0 3014 // ARM pseudo code... 3015 if ConditionPassed() then 3016 EncodingSpecificOperations(); 3017 shift_n = UInt(R[m]<7:0>); 3018 (result, carry) = Shift_C(R[m], SRType_ASR, shift_n, APSR.C); 3019 R[d] = result; 3020 if setflags then 3021 APSR.N = result<31>; 3022 APSR.Z = IsZeroBit(result); 3023 APSR.C = carry; 3024 // APSR.V unchanged 3025#endif 3026 3027 return EmulateShiftReg (opcode, encoding, SRType_ASR); 3028} 3029 3030// Logical Shift Left (immediate) shifts a register value left by an immediate number of bits, 3031// shifting in zeros, and writes the result to the destination register. It can optionally 3032// update the condition flags based on the result. 3033bool 3034EmulateInstructionARM::EmulateLSLImm (const uint32_t opcode, const ARMEncoding encoding) 3035{ 3036#if 0 3037 // ARM pseudo code... 3038 if ConditionPassed() then 3039 EncodingSpecificOperations(); 3040 (result, carry) = Shift_C(R[m], SRType_LSL, shift_n, APSR.C); 3041 if d == 15 then // Can only occur for ARM encoding 3042 ALUWritePC(result); // setflags is always FALSE here 3043 else 3044 R[d] = result; 3045 if setflags then 3046 APSR.N = result<31>; 3047 APSR.Z = IsZeroBit(result); 3048 APSR.C = carry; 3049 // APSR.V unchanged 3050#endif 3051 3052 return EmulateShiftImm (opcode, encoding, SRType_LSL); 3053} 3054 3055// Logical Shift Left (register) shifts a register value left by a variable number of bits, 3056// shifting in zeros, and writes the result to the destination register. The variable number 3057// of bits is read from the bottom byte of a register. It can optionally update the condition 3058// flags based on the result. 3059bool 3060EmulateInstructionARM::EmulateLSLReg (const uint32_t opcode, const ARMEncoding encoding) 3061{ 3062#if 0 3063 // ARM pseudo code... 3064 if ConditionPassed() then 3065 EncodingSpecificOperations(); 3066 shift_n = UInt(R[m]<7:0>); 3067 (result, carry) = Shift_C(R[m], SRType_LSL, shift_n, APSR.C); 3068 R[d] = result; 3069 if setflags then 3070 APSR.N = result<31>; 3071 APSR.Z = IsZeroBit(result); 3072 APSR.C = carry; 3073 // APSR.V unchanged 3074#endif 3075 3076 return EmulateShiftReg (opcode, encoding, SRType_LSL); 3077} 3078 3079// Logical Shift Right (immediate) shifts a register value right by an immediate number of bits, 3080// shifting in zeros, and writes the result to the destination register. It can optionally 3081// update the condition flags based on the result. 3082bool 3083EmulateInstructionARM::EmulateLSRImm (const uint32_t opcode, const ARMEncoding encoding) 3084{ 3085#if 0 3086 // ARM pseudo code... 3087 if ConditionPassed() then 3088 EncodingSpecificOperations(); 3089 (result, carry) = Shift_C(R[m], SRType_LSR, shift_n, APSR.C); 3090 if d == 15 then // Can only occur for ARM encoding 3091 ALUWritePC(result); // setflags is always FALSE here 3092 else 3093 R[d] = result; 3094 if setflags then 3095 APSR.N = result<31>; 3096 APSR.Z = IsZeroBit(result); 3097 APSR.C = carry; 3098 // APSR.V unchanged 3099#endif 3100 3101 return EmulateShiftImm (opcode, encoding, SRType_LSR); 3102} 3103 3104// Logical Shift Right (register) shifts a register value right by a variable number of bits, 3105// shifting in zeros, and writes the result to the destination register. The variable number 3106// of bits is read from the bottom byte of a register. It can optionally update the condition 3107// flags based on the result. 3108bool 3109EmulateInstructionARM::EmulateLSRReg (const uint32_t opcode, const ARMEncoding encoding) 3110{ 3111#if 0 3112 // ARM pseudo code... 3113 if ConditionPassed() then 3114 EncodingSpecificOperations(); 3115 shift_n = UInt(R[m]<7:0>); 3116 (result, carry) = Shift_C(R[m], SRType_LSR, shift_n, APSR.C); 3117 R[d] = result; 3118 if setflags then 3119 APSR.N = result<31>; 3120 APSR.Z = IsZeroBit(result); 3121 APSR.C = carry; 3122 // APSR.V unchanged 3123#endif 3124 3125 return EmulateShiftReg (opcode, encoding, SRType_LSR); 3126} 3127 3128// Rotate Right (immediate) provides the value of the contents of a register rotated by a constant value. 3129// The bits that are rotated off the right end are inserted into the vacated bit positions on the left. 3130// It can optionally update the condition flags based on the result. 3131bool 3132EmulateInstructionARM::EmulateRORImm (const uint32_t opcode, const ARMEncoding encoding) 3133{ 3134#if 0 3135 // ARM pseudo code... 3136 if ConditionPassed() then 3137 EncodingSpecificOperations(); 3138 (result, carry) = Shift_C(R[m], SRType_ROR, shift_n, APSR.C); 3139 if d == 15 then // Can only occur for ARM encoding 3140 ALUWritePC(result); // setflags is always FALSE here 3141 else 3142 R[d] = result; 3143 if setflags then 3144 APSR.N = result<31>; 3145 APSR.Z = IsZeroBit(result); 3146 APSR.C = carry; 3147 // APSR.V unchanged 3148#endif 3149 3150 return EmulateShiftImm (opcode, encoding, SRType_ROR); 3151} 3152 3153// Rotate Right (register) provides the value of the contents of a register rotated by a variable number of bits. 3154// The bits that are rotated off the right end are inserted into the vacated bit positions on the left. 3155// The variable number of bits is read from the bottom byte of a register. It can optionally update the condition 3156// flags based on the result. 3157bool 3158EmulateInstructionARM::EmulateRORReg (const uint32_t opcode, const ARMEncoding encoding) 3159{ 3160#if 0 3161 // ARM pseudo code... 3162 if ConditionPassed() then 3163 EncodingSpecificOperations(); 3164 shift_n = UInt(R[m]<7:0>); 3165 (result, carry) = Shift_C(R[m], SRType_ROR, shift_n, APSR.C); 3166 R[d] = result; 3167 if setflags then 3168 APSR.N = result<31>; 3169 APSR.Z = IsZeroBit(result); 3170 APSR.C = carry; 3171 // APSR.V unchanged 3172#endif 3173 3174 return EmulateShiftReg (opcode, encoding, SRType_ROR); 3175} 3176 3177// Rotate Right with Extend provides the value of the contents of a register shifted right by one place, 3178// with the carry flag shifted into bit [31]. 3179// 3180// RRX can optionally update the condition flags based on the result. 3181// In that case, bit [0] is shifted into the carry flag. 3182bool 3183EmulateInstructionARM::EmulateRRX (const uint32_t opcode, const ARMEncoding encoding) 3184{ 3185#if 0 3186 // ARM pseudo code... 3187 if ConditionPassed() then 3188 EncodingSpecificOperations(); 3189 (result, carry) = Shift_C(R[m], SRType_RRX, 1, APSR.C); 3190 if d == 15 then // Can only occur for ARM encoding 3191 ALUWritePC(result); // setflags is always FALSE here 3192 else 3193 R[d] = result; 3194 if setflags then 3195 APSR.N = result<31>; 3196 APSR.Z = IsZeroBit(result); 3197 APSR.C = carry; 3198 // APSR.V unchanged 3199#endif 3200 3201 return EmulateShiftImm (opcode, encoding, SRType_RRX); 3202} 3203 3204bool 3205EmulateInstructionARM::EmulateShiftImm (const uint32_t opcode, const ARMEncoding encoding, ARM_ShifterType shift_type) 3206{ 3207// assert(shift_type == SRType_ASR 3208// || shift_type == SRType_LSL 3209// || shift_type == SRType_LSR 3210// || shift_type == SRType_ROR 3211// || shift_type == SRType_RRX); 3212 3213 bool success = false; 3214 3215 if (ConditionPassed(opcode)) 3216 { 3217 uint32_t Rd; // the destination register 3218 uint32_t Rm; // the first operand register 3219 uint32_t imm5; // encoding for the shift amount 3220 uint32_t carry; // the carry bit after the shift operation 3221 bool setflags; 3222 3223 // Special case handling! 3224 // A8.6.139 ROR (immediate) -- Encoding T1 3225 ARMEncoding use_encoding = encoding; 3226 if (shift_type == SRType_ROR && use_encoding == eEncodingT1) 3227 { 3228 // Morph the T1 encoding from the ARM Architecture Manual into T2 encoding to 3229 // have the same decoding of bit fields as the other Thumb2 shift operations. 3230 use_encoding = eEncodingT2; 3231 } 3232 3233 switch (use_encoding) { 3234 case eEncodingT1: 3235 // Due to the above special case handling! 3236 if (shift_type == SRType_ROR) 3237 return false; 3238 3239 Rd = Bits32(opcode, 2, 0); 3240 Rm = Bits32(opcode, 5, 3); 3241 setflags = !InITBlock(); 3242 imm5 = Bits32(opcode, 10, 6); 3243 break; 3244 case eEncodingT2: 3245 // A8.6.141 RRX 3246 // There's no imm form of RRX instructions. 3247 if (shift_type == SRType_RRX) 3248 return false; 3249 3250 Rd = Bits32(opcode, 11, 8); 3251 Rm = Bits32(opcode, 3, 0); 3252 setflags = BitIsSet(opcode, 20); 3253 imm5 = Bits32(opcode, 14, 12) << 2 | Bits32(opcode, 7, 6); 3254 if (BadReg(Rd) || BadReg(Rm)) 3255 return false; 3256 break; 3257 case eEncodingA1: 3258 Rd = Bits32(opcode, 15, 12); 3259 Rm = Bits32(opcode, 3, 0); 3260 setflags = BitIsSet(opcode, 20); 3261 imm5 = Bits32(opcode, 11, 7); 3262 break; 3263 default: 3264 return false; 3265 } 3266 3267 // A8.6.139 ROR (immediate) 3268 if (shift_type == SRType_ROR && imm5 == 0) 3269 shift_type = SRType_RRX; 3270 3271 // Get the first operand. 3272 uint32_t value = ReadCoreReg (Rm, &success); 3273 if (!success) 3274 return false; 3275 3276 // Decode the shift amount if not RRX. 3277 uint32_t amt = (shift_type == SRType_RRX ? 1 : DecodeImmShift(shift_type, imm5)); 3278 3279 uint32_t result = Shift_C(value, shift_type, amt, APSR_C, carry, &success); 3280 if (!success) 3281 return false; 3282 3283 // The context specifies that an immediate is to be moved into Rd. 3284 EmulateInstruction::Context context; 3285 context.type = EmulateInstruction::eContextImmediate; 3286 context.SetNoArgs (); 3287 3288 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry)) 3289 return false; 3290 } 3291 return true; 3292} 3293 3294bool 3295EmulateInstructionARM::EmulateShiftReg (const uint32_t opcode, const ARMEncoding encoding, ARM_ShifterType shift_type) 3296{ 3297 // assert(shift_type == SRType_ASR 3298 // || shift_type == SRType_LSL 3299 // || shift_type == SRType_LSR 3300 // || shift_type == SRType_ROR); 3301 3302 bool success = false; 3303 3304 if (ConditionPassed(opcode)) 3305 { 3306 uint32_t Rd; // the destination register 3307 uint32_t Rn; // the first operand register 3308 uint32_t Rm; // the register whose bottom byte contains the amount to shift by 3309 uint32_t carry; // the carry bit after the shift operation 3310 bool setflags; 3311 switch (encoding) { 3312 case eEncodingT1: 3313 Rd = Bits32(opcode, 2, 0); 3314 Rn = Rd; 3315 Rm = Bits32(opcode, 5, 3); 3316 setflags = !InITBlock(); 3317 break; 3318 case eEncodingT2: 3319 Rd = Bits32(opcode, 11, 8); 3320 Rn = Bits32(opcode, 19, 16); 3321 Rm = Bits32(opcode, 3, 0); 3322 setflags = BitIsSet(opcode, 20); 3323 if (BadReg(Rd) || BadReg(Rn) || BadReg(Rm)) 3324 return false; 3325 break; 3326 case eEncodingA1: 3327 Rd = Bits32(opcode, 15, 12); 3328 Rn = Bits32(opcode, 3, 0); 3329 Rm = Bits32(opcode, 11, 8); 3330 setflags = BitIsSet(opcode, 20); 3331 if (Rd == 15 || Rn == 15 || Rm == 15) 3332 return false; 3333 break; 3334 default: 3335 return false; 3336 } 3337 3338 // Get the first operand. 3339 uint32_t value = ReadCoreReg (Rn, &success); 3340 if (!success) 3341 return false; 3342 // Get the Rm register content. 3343 uint32_t val = ReadCoreReg (Rm, &success); 3344 if (!success) 3345 return false; 3346 3347 // Get the shift amount. 3348 uint32_t amt = Bits32(val, 7, 0); 3349 3350 uint32_t result = Shift_C(value, shift_type, amt, APSR_C, carry, &success); 3351 if (!success) 3352 return false; 3353 3354 // The context specifies that an immediate is to be moved into Rd. 3355 EmulateInstruction::Context context; 3356 context.type = EmulateInstruction::eContextImmediate; 3357 context.SetNoArgs (); 3358 3359 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry)) 3360 return false; 3361 } 3362 return true; 3363} 3364 3365// LDM loads multiple registers from consecutive memory locations, using an 3366// address from a base register. Optionally the address just above the highest of those locations 3367// can be written back to the base register. 3368bool 3369EmulateInstructionARM::EmulateLDM (const uint32_t opcode, const ARMEncoding encoding) 3370{ 3371#if 0 3372 // ARM pseudo code... 3373 if ConditionPassed() 3374 EncodingSpecificOperations(); NullCheckIfThumbEE (n); 3375 address = R[n]; 3376 3377 for i = 0 to 14 3378 if registers<i> == '1' then 3379 R[i] = MemA[address, 4]; address = address + 4; 3380 if registers<15> == '1' then 3381 LoadWritePC (MemA[address, 4]); 3382 3383 if wback && registers<n> == '0' then R[n] = R[n] + 4 * BitCount (registers); 3384 if wback && registers<n> == '1' then R[n] = bits(32) UNKNOWN; // Only possible for encoding A1 3385 3386#endif 3387 3388 bool success = false; 3389 bool conditional = false; 3390 if (ConditionPassed(opcode, &conditional)) 3391 { 3392 uint32_t n; 3393 uint32_t registers = 0; 3394 bool wback; 3395 const uint32_t addr_byte_size = GetAddressByteSize(); 3396 switch (encoding) 3397 { 3398 case eEncodingT1: 3399 // n = UInt(Rn); registers = '00000000':register_list; wback = (registers<n> == '0'); 3400 n = Bits32 (opcode, 10, 8); 3401 registers = Bits32 (opcode, 7, 0); 3402 registers = registers & 0x00ff; // Make sure the top 8 bits are zeros. 3403 wback = BitIsClear (registers, n); 3404 // if BitCount(registers) < 1 then UNPREDICTABLE; 3405 if (BitCount(registers) < 1) 3406 return false; 3407 break; 3408 case eEncodingT2: 3409 // if W == '1' && Rn == '1101' then SEE POP; 3410 // n = UInt(Rn); registers = P:M:'0':register_list; wback = (W == '1'); 3411 n = Bits32 (opcode, 19, 16); 3412 registers = Bits32 (opcode, 15, 0); 3413 registers = registers & 0xdfff; // Make sure bit 13 is zero. 3414 wback = BitIsSet (opcode, 21); 3415 3416 // if n == 15 || BitCount(registers) < 2 || (P == '1' && M == '1') then UNPREDICTABLE; 3417 if ((n == 15) 3418 || (BitCount (registers) < 2) 3419 || (BitIsSet (opcode, 14) && BitIsSet (opcode, 15))) 3420 return false; 3421 3422 // if registers<15> == '1' && InITBlock() && !LastInITBlock() then UNPREDICTABLE; 3423 if (BitIsSet (registers, 15) && InITBlock() && !LastInITBlock()) 3424 return false; 3425 3426 // if wback && registers<n> == '1' then UNPREDICTABLE; 3427 if (wback 3428 && BitIsSet (registers, n)) 3429 return false; 3430 break; 3431 3432 case eEncodingA1: 3433 n = Bits32 (opcode, 19, 16); 3434 registers = Bits32 (opcode, 15, 0); 3435 wback = BitIsSet (opcode, 21); 3436 if ((n == 15) 3437 || (BitCount (registers) < 1)) 3438 return false; 3439 break; 3440 default: 3441 return false; 3442 } 3443 3444 int32_t offset = 0; 3445 const addr_t base_address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success); 3446 if (!success) 3447 return false; 3448 3449 EmulateInstruction::Context context; 3450 context.type = EmulateInstruction::eContextRegisterPlusOffset; 3451 RegisterInfo dwarf_reg; 3452 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, dwarf_reg); 3453 context.SetRegisterPlusOffset (dwarf_reg, offset); 3454 3455 for (int i = 0; i < 14; ++i) 3456 { 3457 if (BitIsSet (registers, i)) 3458 { 3459 context.type = EmulateInstruction::eContextRegisterPlusOffset; 3460 context.SetRegisterPlusOffset (dwarf_reg, offset); 3461 if (wback && (n == 13)) // Pop Instruction 3462 { 3463 if (conditional) 3464 context.type = EmulateInstruction::eContextRegisterLoad; 3465 else 3466 context.type = EmulateInstruction::eContextPopRegisterOffStack; 3467 } 3468 3469 // R[i] = MemA [address, 4]; address = address + 4; 3470 uint32_t data = MemARead (context, base_address + offset, addr_byte_size, 0, &success); 3471 if (!success) 3472 return false; 3473 3474 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + i, data)) 3475 return false; 3476 3477 offset += addr_byte_size; 3478 } 3479 } 3480 3481 if (BitIsSet (registers, 15)) 3482 { 3483 //LoadWritePC (MemA [address, 4]); 3484 context.type = EmulateInstruction::eContextRegisterPlusOffset; 3485 context.SetRegisterPlusOffset (dwarf_reg, offset); 3486 uint32_t data = MemARead (context, base_address + offset, addr_byte_size, 0, &success); 3487 if (!success) 3488 return false; 3489 // In ARMv5T and above, this is an interworking branch. 3490 if (!LoadWritePC(context, data)) 3491 return false; 3492 } 3493 3494 if (wback && BitIsClear (registers, n)) 3495 { 3496 // R[n] = R[n] + 4 * BitCount (registers) 3497 int32_t offset = addr_byte_size * BitCount (registers); 3498 context.type = EmulateInstruction::eContextAdjustBaseRegister; 3499 context.SetRegisterPlusOffset (dwarf_reg, offset); 3500 3501 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, base_address + offset)) 3502 return false; 3503 } 3504 if (wback && BitIsSet (registers, n)) 3505 // R[n] bits(32) UNKNOWN; 3506 return WriteBits32Unknown (n); 3507 } 3508 return true; 3509} 3510 3511// LDMDA loads multiple registers from consecutive memory locations using an address from a base register. 3512// The consecutive memory locations end at this address and the address just below the lowest of those locations 3513// can optionally be written back to the base register. 3514bool 3515EmulateInstructionARM::EmulateLDMDA (const uint32_t opcode, const ARMEncoding encoding) 3516{ 3517#if 0 3518 // ARM pseudo code... 3519 if ConditionPassed() then 3520 EncodingSpecificOperations(); 3521 address = R[n] - 4*BitCount(registers) + 4; 3522 3523 for i = 0 to 14 3524 if registers<i> == '1' then 3525 R[i] = MemA[address,4]; address = address + 4; 3526 3527 if registers<15> == '1' then 3528 LoadWritePC(MemA[address,4]); 3529 3530 if wback && registers<n> == '0' then R[n] = R[n] - 4*BitCount(registers); 3531 if wback && registers<n> == '1' then R[n] = bits(32) UNKNOWN; 3532#endif 3533 3534 bool success = false; 3535 3536 if (ConditionPassed(opcode)) 3537 { 3538 uint32_t n; 3539 uint32_t registers = 0; 3540 bool wback; 3541 const uint32_t addr_byte_size = GetAddressByteSize(); 3542 3543 // EncodingSpecificOperations(); 3544 switch (encoding) 3545 { 3546 case eEncodingA1: 3547 // n = UInt(Rn); registers = register_list; wback = (W == '1'); 3548 n = Bits32 (opcode, 19, 16); 3549 registers = Bits32 (opcode, 15, 0); 3550 wback = BitIsSet (opcode, 21); 3551 3552 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE; 3553 if ((n == 15) || (BitCount (registers) < 1)) 3554 return false; 3555 3556 break; 3557 3558 default: 3559 return false; 3560 } 3561 // address = R[n] - 4*BitCount(registers) + 4; 3562 3563 int32_t offset = 0; 3564 addr_t Rn = ReadCoreReg (n, &success); 3565 3566 if (!success) 3567 return false; 3568 3569 addr_t address = Rn - (addr_byte_size * BitCount (registers)) + addr_byte_size; 3570 3571 EmulateInstruction::Context context; 3572 context.type = EmulateInstruction::eContextRegisterPlusOffset; 3573 RegisterInfo dwarf_reg; 3574 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, dwarf_reg); 3575 context.SetRegisterPlusOffset (dwarf_reg, offset); 3576 3577 // for i = 0 to 14 3578 for (int i = 0; i < 14; ++i) 3579 { 3580 // if registers<i> == '1' then 3581 if (BitIsSet (registers, i)) 3582 { 3583 // R[i] = MemA[address,4]; address = address + 4; 3584 context.SetRegisterPlusOffset (dwarf_reg, Rn - (address + offset)); 3585 uint32_t data = MemARead (context, address + offset, addr_byte_size, 0, &success); 3586 if (!success) 3587 return false; 3588 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + i, data)) 3589 return false; 3590 offset += addr_byte_size; 3591 } 3592 } 3593 3594 // if registers<15> == '1' then 3595 // LoadWritePC(MemA[address,4]); 3596 if (BitIsSet (registers, 15)) 3597 { 3598 context.SetRegisterPlusOffset (dwarf_reg, offset); 3599 uint32_t data = MemARead (context, address + offset, addr_byte_size, 0, &success); 3600 if (!success) 3601 return false; 3602 // In ARMv5T and above, this is an interworking branch. 3603 if (!LoadWritePC(context, data)) 3604 return false; 3605 } 3606 3607 // if wback && registers<n> == '0' then R[n] = R[n] - 4*BitCount(registers); 3608 if (wback && BitIsClear (registers, n)) 3609 { 3610 if (!success) 3611 return false; 3612 3613 offset = (addr_byte_size * BitCount (registers)) * -1; 3614 context.type = EmulateInstruction::eContextAdjustBaseRegister; 3615 context.SetImmediateSigned (offset); 3616 addr_t addr = Rn + offset; 3617 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, addr)) 3618 return false; 3619 } 3620 3621 // if wback && registers<n> == '1' then R[n] = bits(32) UNKNOWN; 3622 if (wback && BitIsSet (registers, n)) 3623 return WriteBits32Unknown (n); 3624 } 3625 return true; 3626} 3627 3628// LDMDB loads multiple registers from consecutive memory locations using an address from a base register. The 3629// consecutive memory lcoations end just below this address, and the address of the lowest of those locations can 3630// be optionally written back to the base register. 3631bool 3632EmulateInstructionARM::EmulateLDMDB (const uint32_t opcode, const ARMEncoding encoding) 3633{ 3634#if 0 3635 // ARM pseudo code... 3636 if ConditionPassed() then 3637 EncodingSpecificOperations(); NullCheckIfThumbEE(n); 3638 address = R[n] - 4*BitCount(registers); 3639 3640 for i = 0 to 14 3641 if registers<i> == '1' then 3642 R[i] = MemA[address,4]; address = address + 4; 3643 if registers<15> == '1' then 3644 LoadWritePC(MemA[address,4]); 3645 3646 if wback && registers<n> == '0' then R[n] = R[n] - 4*BitCount(registers); 3647 if wback && registers<n> == '1' then R[n] = bits(32) UNKNOWN; // Only possible for encoding A1 3648#endif 3649 3650 bool success = false; 3651 3652 if (ConditionPassed(opcode)) 3653 { 3654 uint32_t n; 3655 uint32_t registers = 0; 3656 bool wback; 3657 const uint32_t addr_byte_size = GetAddressByteSize(); 3658 switch (encoding) 3659 { 3660 case eEncodingT1: 3661 // n = UInt(Rn); registers = P:M:'0':register_list; wback = (W == '1'); 3662 n = Bits32 (opcode, 19, 16); 3663 registers = Bits32 (opcode, 15, 0); 3664 registers = registers & 0xdfff; // Make sure bit 13 is a zero. 3665 wback = BitIsSet (opcode, 21); 3666 3667 // if n == 15 || BitCount(registers) < 2 || (P == '1' && M == '1') then UNPREDICTABLE; 3668 if ((n == 15) 3669 || (BitCount (registers) < 2) 3670 || (BitIsSet (opcode, 14) && BitIsSet (opcode, 15))) 3671 return false; 3672 3673 // if registers<15> == '1' && InITBlock() && !LastInITBlock() then UNPREDICTABLE; 3674 if (BitIsSet (registers, 15) && InITBlock() && !LastInITBlock()) 3675 return false; 3676 3677 // if wback && registers<n> == '1' then UNPREDICTABLE; 3678 if (wback && BitIsSet (registers, n)) 3679 return false; 3680 3681 break; 3682 3683 case eEncodingA1: 3684 // n = UInt(Rn); registers = register_list; wback = (W == '1'); 3685 n = Bits32 (opcode, 19, 16); 3686 registers = Bits32 (opcode, 15, 0); 3687 wback = BitIsSet (opcode, 21); 3688 3689 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE; 3690 if ((n == 15) || (BitCount (registers) < 1)) 3691 return false; 3692 3693 break; 3694 3695 default: 3696 return false; 3697 } 3698 3699 // address = R[n] - 4*BitCount(registers); 3700 3701 int32_t offset = 0; 3702 addr_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success); 3703 3704 if (!success) 3705 return false; 3706 3707 addr_t address = Rn - (addr_byte_size * BitCount (registers)); 3708 EmulateInstruction::Context context; 3709 context.type = EmulateInstruction::eContextRegisterPlusOffset; 3710 RegisterInfo dwarf_reg; 3711 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, dwarf_reg); 3712 context.SetRegisterPlusOffset (dwarf_reg, Rn - address); 3713 3714 for (int i = 0; i < 14; ++i) 3715 { 3716 if (BitIsSet (registers, i)) 3717 { 3718 // R[i] = MemA[address,4]; address = address + 4; 3719 context.SetRegisterPlusOffset (dwarf_reg, Rn - (address + offset)); 3720 uint32_t data = MemARead (context, address + offset, addr_byte_size, 0, &success); 3721 if (!success) 3722 return false; 3723 3724 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + i, data)) 3725 return false; 3726 3727 offset += addr_byte_size; 3728 } 3729 } 3730 3731 // if registers<15> == '1' then 3732 // LoadWritePC(MemA[address,4]); 3733 if (BitIsSet (registers, 15)) 3734 { 3735 context.SetRegisterPlusOffset (dwarf_reg, offset); 3736 uint32_t data = MemARead (context, address + offset, addr_byte_size, 0, &success); 3737 if (!success) 3738 return false; 3739 // In ARMv5T and above, this is an interworking branch. 3740 if (!LoadWritePC(context, data)) 3741 return false; 3742 } 3743 3744 // if wback && registers<n> == '0' then R[n] = R[n] - 4*BitCount(registers); 3745 if (wback && BitIsClear (registers, n)) 3746 { 3747 if (!success) 3748 return false; 3749 3750 offset = (addr_byte_size * BitCount (registers)) * -1; 3751 context.type = EmulateInstruction::eContextAdjustBaseRegister; 3752 context.SetImmediateSigned (offset); 3753 addr_t addr = Rn + offset; 3754 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, addr)) 3755 return false; 3756 } 3757 3758 // if wback && registers<n> == '1' then R[n] = bits(32) UNKNOWN; // Only possible for encoding A1 3759 if (wback && BitIsSet (registers, n)) 3760 return WriteBits32Unknown (n); 3761 } 3762 return true; 3763} 3764 3765// LDMIB loads multiple registers from consecutive memory locations using an address from a base register. The 3766// consecutive memory locations start just above this address, and thea ddress of the last of those locations can 3767// optinoally be written back to the base register. 3768bool 3769EmulateInstructionARM::EmulateLDMIB (const uint32_t opcode, const ARMEncoding encoding) 3770{ 3771#if 0 3772 if ConditionPassed() then 3773 EncodingSpecificOperations(); 3774 address = R[n] + 4; 3775 3776 for i = 0 to 14 3777 if registers<i> == '1' then 3778 R[i] = MemA[address,4]; address = address + 4; 3779 if registers<15> == '1' then 3780 LoadWritePC(MemA[address,4]); 3781 3782 if wback && registers<n> == '0' then R[n] = R[n] + 4*BitCount(registers); 3783 if wback && registers<n> == '1' then R[n] = bits(32) UNKNOWN; 3784#endif 3785 3786 bool success = false; 3787 3788 if (ConditionPassed(opcode)) 3789 { 3790 uint32_t n; 3791 uint32_t registers = 0; 3792 bool wback; 3793 const uint32_t addr_byte_size = GetAddressByteSize(); 3794 switch (encoding) 3795 { 3796 case eEncodingA1: 3797 // n = UInt(Rn); registers = register_list; wback = (W == '1'); 3798 n = Bits32 (opcode, 19, 16); 3799 registers = Bits32 (opcode, 15, 0); 3800 wback = BitIsSet (opcode, 21); 3801 3802 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE; 3803 if ((n == 15) || (BitCount (registers) < 1)) 3804 return false; 3805 3806 break; 3807 default: 3808 return false; 3809 } 3810 // address = R[n] + 4; 3811 3812 int32_t offset = 0; 3813 addr_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success); 3814 3815 if (!success) 3816 return false; 3817 3818 addr_t address = Rn + addr_byte_size; 3819 3820 EmulateInstruction::Context context; 3821 context.type = EmulateInstruction::eContextRegisterPlusOffset; 3822 RegisterInfo dwarf_reg; 3823 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, dwarf_reg); 3824 context.SetRegisterPlusOffset (dwarf_reg, offset); 3825 3826 for (int i = 0; i < 14; ++i) 3827 { 3828 if (BitIsSet (registers, i)) 3829 { 3830 // R[i] = MemA[address,4]; address = address + 4; 3831 3832 context.SetRegisterPlusOffset (dwarf_reg, offset + addr_byte_size); 3833 uint32_t data = MemARead (context, address + offset, addr_byte_size, 0, &success); 3834 if (!success) 3835 return false; 3836 3837 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + i, data)) 3838 return false; 3839 3840 offset += addr_byte_size; 3841 } 3842 } 3843 3844 // if registers<15> == '1' then 3845 // LoadWritePC(MemA[address,4]); 3846 if (BitIsSet (registers, 15)) 3847 { 3848 context.SetRegisterPlusOffset (dwarf_reg, offset); 3849 uint32_t data = MemARead (context, address + offset, addr_byte_size, 0, &success); 3850 if (!success) 3851 return false; 3852 // In ARMv5T and above, this is an interworking branch. 3853 if (!LoadWritePC(context, data)) 3854 return false; 3855 } 3856 3857 // if wback && registers<n> == '0' then R[n] = R[n] + 4*BitCount(registers); 3858 if (wback && BitIsClear (registers, n)) 3859 { 3860 if (!success) 3861 return false; 3862 3863 offset = addr_byte_size * BitCount (registers); 3864 context.type = EmulateInstruction::eContextAdjustBaseRegister; 3865 context.SetImmediateSigned (offset); 3866 addr_t addr = Rn + offset; 3867 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, addr)) 3868 return false; 3869 } 3870 3871 // if wback && registers<n> == '1' then R[n] = bits(32) UNKNOWN; // Only possible for encoding A1 3872 if (wback && BitIsSet (registers, n)) 3873 return WriteBits32Unknown (n); 3874 } 3875 return true; 3876} 3877 3878// Load Register (immediate) calculates an address from a base register value and 3879// an immediate offset, loads a word from memory, and writes to a register. 3880// LDR (immediate, Thumb) 3881bool 3882EmulateInstructionARM::EmulateLDRRtRnImm (const uint32_t opcode, const ARMEncoding encoding) 3883{ 3884#if 0 3885 // ARM pseudo code... 3886 if (ConditionPassed()) 3887 { 3888 EncodingSpecificOperations(); NullCheckIfThumbEE(15); 3889 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32); 3890 address = if index then offset_addr else R[n]; 3891 data = MemU[address,4]; 3892 if wback then R[n] = offset_addr; 3893 if t == 15 then 3894 if address<1:0> == '00' then LoadWritePC(data); else UNPREDICTABLE; 3895 elsif UnalignedSupport() || address<1:0> = '00' then 3896 R[t] = data; 3897 else R[t] = bits(32) UNKNOWN; // Can only apply before ARMv7 3898 } 3899#endif 3900 3901 bool success = false; 3902 3903 if (ConditionPassed(opcode)) 3904 { 3905 uint32_t Rt; // the destination register 3906 uint32_t Rn; // the base register 3907 uint32_t imm32; // the immediate offset used to form the address 3908 addr_t offset_addr; // the offset address 3909 addr_t address; // the calculated address 3910 uint32_t data; // the literal data value from memory load 3911 bool add, index, wback; 3912 switch (encoding) { 3913 case eEncodingT1: 3914 Rt = Bits32(opcode, 2, 0); 3915 Rn = Bits32(opcode, 5, 3); 3916 imm32 = Bits32(opcode, 10, 6) << 2; // imm32 = ZeroExtend(imm5:'00', 32); 3917 // index = TRUE; add = TRUE; wback = FALSE 3918 add = true; 3919 index = true; 3920 wback = false; 3921 3922 break; 3923 3924 case eEncodingT2: 3925 // t = UInt(Rt); n = 13; imm32 = ZeroExtend(imm8:'00', 32); 3926 Rt = Bits32 (opcode, 10, 8); 3927 Rn = 13; 3928 imm32 = Bits32 (opcode, 7, 0) << 2; 3929 3930 // index = TRUE; add = TRUE; wback = FALSE; 3931 index = true; 3932 add = true; 3933 wback = false; 3934 3935 break; 3936 3937 case eEncodingT3: 3938 // if Rn == '1111' then SEE LDR (literal); 3939 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32); 3940 Rt = Bits32 (opcode, 15, 12); 3941 Rn = Bits32 (opcode, 19, 16); 3942 imm32 = Bits32 (opcode, 11, 0); 3943 3944 // index = TRUE; add = TRUE; wback = FALSE; 3945 index = true; 3946 add = true; 3947 wback = false; 3948 3949 // if t == 15 && InITBlock() && !LastInITBlock() then UNPREDICTABLE; 3950 if ((Rt == 15) && InITBlock() && !LastInITBlock()) 3951 return false; 3952 3953 break; 3954 3955 case eEncodingT4: 3956 // if Rn == '1111' then SEE LDR (literal); 3957 // if P == '1' && U == '1' && W == '0' then SEE LDRT; 3958 // if Rn == '1101' && P == '0' && U == '1' && W == '1' && imm8 == '00000100' then SEE POP; 3959 // if P == '0' && W == '0' then UNDEFINED; 3960 if (BitIsClear (opcode, 10) && BitIsClear (opcode, 8)) 3961 return false; 3962 3963 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32); 3964 Rt = Bits32 (opcode, 15, 12); 3965 Rn = Bits32 (opcode, 19, 16); 3966 imm32 = Bits32 (opcode, 7, 0); 3967 3968 // index = (P == '1'); add = (U == '1'); wback = (W == '1'); 3969 index = BitIsSet (opcode, 10); 3970 add = BitIsSet (opcode, 9); 3971 wback = BitIsSet (opcode, 8); 3972 3973 // if (wback && n == t) || (t == 15 && InITBlock() && !LastInITBlock()) then UNPREDICTABLE; 3974 if ((wback && (Rn == Rt)) || ((Rt == 15) && InITBlock() && !LastInITBlock())) 3975 return false; 3976 3977 break; 3978 3979 default: 3980 return false; 3981 } 3982 uint32_t base = ReadCoreReg (Rn, &success); 3983 if (!success) 3984 return false; 3985 if (add) 3986 offset_addr = base + imm32; 3987 else 3988 offset_addr = base - imm32; 3989 3990 address = (index ? offset_addr : base); 3991 3992 RegisterInfo base_reg; 3993 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + Rn, base_reg); 3994 if (wback) 3995 { 3996 EmulateInstruction::Context ctx; 3997 ctx.type = EmulateInstruction::eContextAdjustBaseRegister; 3998 ctx.SetRegisterPlusOffset (base_reg, (int32_t) (offset_addr - base)); 3999 4000 if (!WriteRegisterUnsigned (ctx, eRegisterKindDWARF, dwarf_r0 + Rn, offset_addr)) 4001 return false; 4002 } 4003 4004 // Prepare to write to the Rt register. 4005 EmulateInstruction::Context context; 4006 context.type = EmulateInstruction::eContextRegisterLoad; 4007 context.SetRegisterPlusOffset (base_reg, (int32_t) (offset_addr - base)); 4008 4009 // Read memory from the address. 4010 data = MemURead(context, address, 4, 0, &success); 4011 if (!success) 4012 return false; 4013 4014 if (Rt == 15) 4015 { 4016 if (Bits32(address, 1, 0) == 0) 4017 { 4018 if (!LoadWritePC(context, data)) 4019 return false; 4020 } 4021 else 4022 return false; 4023 } 4024 else if (UnalignedSupport() || Bits32(address, 1, 0) == 0) 4025 { 4026 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + Rt, data)) 4027 return false; 4028 } 4029 else 4030 WriteBits32Unknown (Rt); 4031 } 4032 return true; 4033} 4034 4035// STM (Store Multiple Increment After) stores multiple registers to consecutive memory locations using an address 4036// from a base register. The consecutive memory locations start at this address, and teh address just above the last 4037// of those locations can optionally be written back to the base register. 4038bool 4039EmulateInstructionARM::EmulateSTM (const uint32_t opcode, const ARMEncoding encoding) 4040{ 4041#if 0 4042 if ConditionPassed() then 4043 EncodingSpecificOperations(); NullCheckIfThumbEE(n); 4044 address = R[n]; 4045 4046 for i = 0 to 14 4047 if registers<i> == '1' then 4048 if i == n && wback && i != LowestSetBit(registers) then 4049 MemA[address,4] = bits(32) UNKNOWN; // Only possible for encodings T1 and A1 4050 else 4051 MemA[address,4] = R[i]; 4052 address = address + 4; 4053 4054 if registers<15> == '1' then // Only possible for encoding A1 4055 MemA[address,4] = PCStoreValue(); 4056 if wback then R[n] = R[n] + 4*BitCount(registers); 4057#endif 4058 4059 bool success = false; 4060 4061 if (ConditionPassed(opcode)) 4062 { 4063 uint32_t n; 4064 uint32_t registers = 0; 4065 bool wback; 4066 const uint32_t addr_byte_size = GetAddressByteSize(); 4067 4068 // EncodingSpecificOperations(); NullCheckIfThumbEE(n); 4069 switch (encoding) 4070 { 4071 case eEncodingT1: 4072 // n = UInt(Rn); registers = '00000000':register_list; wback = TRUE; 4073 n = Bits32 (opcode, 10, 8); 4074 registers = Bits32 (opcode, 7, 0); 4075 registers = registers & 0x00ff; // Make sure the top 8 bits are zeros. 4076 wback = true; 4077 4078 // if BitCount(registers) < 1 then UNPREDICTABLE; 4079 if (BitCount (registers) < 1) 4080 return false; 4081 4082 break; 4083 4084 case eEncodingT2: 4085 // n = UInt(Rn); registers = '0':M:'0':register_list; wback = (W == '1'); 4086 n = Bits32 (opcode, 19, 16); 4087 registers = Bits32 (opcode, 15, 0); 4088 registers = registers & 0x5fff; // Make sure bits 15 & 13 are zeros. 4089 wback = BitIsSet (opcode, 21); 4090 4091 // if n == 15 || BitCount(registers) < 2 then UNPREDICTABLE; 4092 if ((n == 15) || (BitCount (registers) < 2)) 4093 return false; 4094 4095 // if wback && registers<n> == '1' then UNPREDICTABLE; 4096 if (wback && BitIsSet (registers, n)) 4097 return false; 4098 4099 break; 4100 4101 case eEncodingA1: 4102 // n = UInt(Rn); registers = register_list; wback = (W == '1'); 4103 n = Bits32 (opcode, 19, 16); 4104 registers = Bits32 (opcode, 15, 0); 4105 wback = BitIsSet (opcode, 21); 4106 4107 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE; 4108 if ((n == 15) || (BitCount (registers) < 1)) 4109 return false; 4110 4111 break; 4112 4113 default: 4114 return false; 4115 } 4116 4117 // address = R[n]; 4118 int32_t offset = 0; 4119 const addr_t address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success); 4120 if (!success) 4121 return false; 4122 4123 EmulateInstruction::Context context; 4124 context.type = EmulateInstruction::eContextRegisterStore; 4125 RegisterInfo base_reg; 4126 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg); 4127 4128 // for i = 0 to 14 4129 uint32_t lowest_set_bit = 14; 4130 for (uint32_t i = 0; i < 14; ++i) 4131 { 4132 // if registers<i> == '1' then 4133 if (BitIsSet (registers, i)) 4134 { 4135 if (i < lowest_set_bit) 4136 lowest_set_bit = i; 4137 // if i == n && wback && i != LowestSetBit(registers) then 4138 if ((i == n) && wback && (i != lowest_set_bit)) 4139 // MemA[address,4] = bits(32) UNKNOWN; // Only possible for encodings T1 and A1 4140 WriteBits32UnknownToMemory (address + offset); 4141 else 4142 { 4143 // MemA[address,4] = R[i]; 4144 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + i, 0, &success); 4145 if (!success) 4146 return false; 4147 4148 RegisterInfo data_reg; 4149 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + i, data_reg); 4150 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, offset); 4151 if (!MemAWrite (context, address + offset, data, addr_byte_size)) 4152 return false; 4153 } 4154 4155 // address = address + 4; 4156 offset += addr_byte_size; 4157 } 4158 } 4159 4160 // if registers<15> == '1' then // Only possible for encoding A1 4161 // MemA[address,4] = PCStoreValue(); 4162 if (BitIsSet (registers, 15)) 4163 { 4164 RegisterInfo pc_reg; 4165 GetRegisterInfo (eRegisterKindDWARF, dwarf_pc, pc_reg); 4166 context.SetRegisterPlusOffset (pc_reg, 8); 4167 const uint32_t pc = ReadCoreReg (PC_REG, &success); 4168 if (!success) 4169 return false; 4170 4171 if (!MemAWrite (context, address + offset, pc, addr_byte_size)) 4172 return false; 4173 } 4174 4175 // if wback then R[n] = R[n] + 4*BitCount(registers); 4176 if (wback) 4177 { 4178 offset = addr_byte_size * BitCount (registers); 4179 context.type = EmulateInstruction::eContextAdjustBaseRegister; 4180 context.SetImmediateSigned (offset); 4181 addr_t data = address + offset; 4182 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, data)) 4183 return false; 4184 } 4185 } 4186 return true; 4187} 4188 4189// STMDA (Store Multiple Decrement After) stores multiple registers to consecutive memory locations using an address 4190// from a base register. The consecutive memory locations end at this address, and the address just below the lowest 4191// of those locations can optionally be written back to the base register. 4192bool 4193EmulateInstructionARM::EmulateSTMDA (const uint32_t opcode, const ARMEncoding encoding) 4194{ 4195#if 0 4196 if ConditionPassed() then 4197 EncodingSpecificOperations(); 4198 address = R[n] - 4*BitCount(registers) + 4; 4199 4200 for i = 0 to 14 4201 if registers<i> == '1' then 4202 if i == n && wback && i != LowestSetBit(registers) then 4203 MemA[address,4] = bits(32) UNKNOWN; 4204 else 4205 MemA[address,4] = R[i]; 4206 address = address + 4; 4207 4208 if registers<15> == '1' then 4209 MemA[address,4] = PCStoreValue(); 4210 4211 if wback then R[n] = R[n] - 4*BitCount(registers); 4212#endif 4213 4214 bool success = false; 4215 4216 if (ConditionPassed(opcode)) 4217 { 4218 uint32_t n; 4219 uint32_t registers = 0; 4220 bool wback; 4221 const uint32_t addr_byte_size = GetAddressByteSize(); 4222 4223 // EncodingSpecificOperations(); 4224 switch (encoding) 4225 { 4226 case eEncodingA1: 4227 // n = UInt(Rn); registers = register_list; wback = (W == '1'); 4228 n = Bits32 (opcode, 19, 16); 4229 registers = Bits32 (opcode, 15, 0); 4230 wback = BitIsSet (opcode, 21); 4231 4232 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE; 4233 if ((n == 15) || (BitCount (registers) < 1)) 4234 return false; 4235 break; 4236 default: 4237 return false; 4238 } 4239 4240 // address = R[n] - 4*BitCount(registers) + 4; 4241 int32_t offset = 0; 4242 addr_t Rn = ReadCoreReg (n, &success); 4243 if (!success) 4244 return false; 4245 4246 addr_t address = Rn - (addr_byte_size * BitCount (registers)) + 4; 4247 4248 EmulateInstruction::Context context; 4249 context.type = EmulateInstruction::eContextRegisterStore; 4250 RegisterInfo base_reg; 4251 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg); 4252 4253 // for i = 0 to 14 4254 uint32_t lowest_bit_set = 14; 4255 for (uint32_t i = 0; i < 14; ++i) 4256 { 4257 // if registers<i> == '1' then 4258 if (BitIsSet (registers, i)) 4259 { 4260 if (i < lowest_bit_set) 4261 lowest_bit_set = i; 4262 //if i == n && wback && i != LowestSetBit(registers) then 4263 if ((i == n) && wback && (i != lowest_bit_set)) 4264 // MemA[address,4] = bits(32) UNKNOWN; 4265 WriteBits32UnknownToMemory (address + offset); 4266 else 4267 { 4268 // MemA[address,4] = R[i]; 4269 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + i, 0, &success); 4270 if (!success) 4271 return false; 4272 4273 RegisterInfo data_reg; 4274 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + i, data_reg); 4275 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, Rn - (address + offset)); 4276 if (!MemAWrite (context, address + offset, data, addr_byte_size)) 4277 return false; 4278 } 4279 4280 // address = address + 4; 4281 offset += addr_byte_size; 4282 } 4283 } 4284 4285 // if registers<15> == '1' then 4286 // MemA[address,4] = PCStoreValue(); 4287 if (BitIsSet (registers, 15)) 4288 { 4289 RegisterInfo pc_reg; 4290 GetRegisterInfo (eRegisterKindDWARF, dwarf_pc, pc_reg); 4291 context.SetRegisterPlusOffset (pc_reg, 8); 4292 const uint32_t pc = ReadCoreReg (PC_REG, &success); 4293 if (!success) 4294 return false; 4295 4296 if (!MemAWrite (context, address + offset, pc, addr_byte_size)) 4297 return false; 4298 } 4299 4300 // if wback then R[n] = R[n] - 4*BitCount(registers); 4301 if (wback) 4302 { 4303 offset = (addr_byte_size * BitCount (registers)) * -1; 4304 context.type = EmulateInstruction::eContextAdjustBaseRegister; 4305 context.SetImmediateSigned (offset); 4306 addr_t data = Rn + offset; 4307 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, data)) 4308 return false; 4309 } 4310 } 4311 return true; 4312} 4313 4314// STMDB (Store Multiple Decrement Before) stores multiple registers to consecutive memory locations using an address 4315// from a base register. The consecutive memory locations end just below this address, and the address of the first of 4316// those locations can optionally be written back to the base register. 4317bool 4318EmulateInstructionARM::EmulateSTMDB (const uint32_t opcode, const ARMEncoding encoding) 4319{ 4320#if 0 4321 if ConditionPassed() then 4322 EncodingSpecificOperations(); NullCheckIfThumbEE(n); 4323 address = R[n] - 4*BitCount(registers); 4324 4325 for i = 0 to 14 4326 if registers<i> == '1' then 4327 if i == n && wback && i != LowestSetBit(registers) then 4328 MemA[address,4] = bits(32) UNKNOWN; // Only possible for encoding A1 4329 else 4330 MemA[address,4] = R[i]; 4331 address = address + 4; 4332 4333 if registers<15> == '1' then // Only possible for encoding A1 4334 MemA[address,4] = PCStoreValue(); 4335 4336 if wback then R[n] = R[n] - 4*BitCount(registers); 4337#endif 4338 4339 4340 bool success = false; 4341 4342 if (ConditionPassed(opcode)) 4343 { 4344 uint32_t n; 4345 uint32_t registers = 0; 4346 bool wback; 4347 const uint32_t addr_byte_size = GetAddressByteSize(); 4348 4349 // EncodingSpecificOperations(); NullCheckIfThumbEE(n); 4350 switch (encoding) 4351 { 4352 case eEncodingT1: 4353 // if W == '1' && Rn == '1101' then SEE PUSH; 4354 if ((BitIsSet (opcode, 21)) && (Bits32 (opcode, 19, 16) == 13)) 4355 { 4356 // See PUSH 4357 } 4358 // n = UInt(Rn); registers = '0':M:'0':register_list; wback = (W == '1'); 4359 n = Bits32 (opcode, 19, 16); 4360 registers = Bits32 (opcode, 15, 0); 4361 registers = registers & 0x5fff; // Make sure bits 15 & 13 are zeros. 4362 wback = BitIsSet (opcode, 21); 4363 // if n == 15 || BitCount(registers) < 2 then UNPREDICTABLE; 4364 if ((n == 15) || BitCount (registers) < 2) 4365 return false; 4366 // if wback && registers<n> == '1' then UNPREDICTABLE; 4367 if (wback && BitIsSet (registers, n)) 4368 return false; 4369 break; 4370 4371 case eEncodingA1: 4372 // if W == '1' && Rn == '1101� && BitCount(register_list) >= 2 then SEE PUSH; 4373 if (BitIsSet (opcode, 21) && (Bits32 (opcode, 19, 16) == 13) && BitCount (Bits32 (opcode, 15, 0)) >= 2) 4374 { 4375 // See Push 4376 } 4377 // n = UInt(Rn); registers = register_list; wback = (W == '1'); 4378 n = Bits32 (opcode, 19, 16); 4379 registers = Bits32 (opcode, 15, 0); 4380 wback = BitIsSet (opcode, 21); 4381 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE; 4382 if ((n == 15) || BitCount (registers) < 1) 4383 return false; 4384 break; 4385 4386 default: 4387 return false; 4388 } 4389 4390 // address = R[n] - 4*BitCount(registers); 4391 4392 int32_t offset = 0; 4393 addr_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success); 4394 if (!success) 4395 return false; 4396 4397 addr_t address = Rn - (addr_byte_size * BitCount (registers)); 4398 4399 EmulateInstruction::Context context; 4400 context.type = EmulateInstruction::eContextRegisterStore; 4401 RegisterInfo base_reg; 4402 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg); 4403 4404 // for i = 0 to 14 4405 uint32_t lowest_set_bit = 14; 4406 for (uint32_t i = 0; i < 14; ++i) 4407 { 4408 // if registers<i> == '1' then 4409 if (BitIsSet (registers, i)) 4410 { 4411 if (i < lowest_set_bit) 4412 lowest_set_bit = i; 4413 // if i == n && wback && i != LowestSetBit(registers) then 4414 if ((i == n) && wback && (i != lowest_set_bit)) 4415 // MemA[address,4] = bits(32) UNKNOWN; // Only possible for encoding A1 4416 WriteBits32UnknownToMemory (address + offset); 4417 else 4418 { 4419 // MemA[address,4] = R[i]; 4420 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + i, 0, &success); 4421 if (!success) 4422 return false; 4423 4424 RegisterInfo data_reg; 4425 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + i, data_reg); 4426 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, Rn - (address + offset)); 4427 if (!MemAWrite (context, address + offset, data, addr_byte_size)) 4428 return false; 4429 } 4430 4431 // address = address + 4; 4432 offset += addr_byte_size; 4433 } 4434 } 4435 4436 // if registers<15> == '1' then // Only possible for encoding A1 4437 // MemA[address,4] = PCStoreValue(); 4438 if (BitIsSet (registers, 15)) 4439 { 4440 RegisterInfo pc_reg; 4441 GetRegisterInfo (eRegisterKindDWARF, dwarf_pc, pc_reg); 4442 context.SetRegisterPlusOffset (pc_reg, 8); 4443 const uint32_t pc = ReadCoreReg (PC_REG, &success); 4444 if (!success) 4445 return false; 4446 4447 if (!MemAWrite (context, address + offset, pc, addr_byte_size)) 4448 return false; 4449 } 4450 4451 // if wback then R[n] = R[n] - 4*BitCount(registers); 4452 if (wback) 4453 { 4454 offset = (addr_byte_size * BitCount (registers)) * -1; 4455 context.type = EmulateInstruction::eContextAdjustBaseRegister; 4456 context.SetImmediateSigned (offset); 4457 addr_t data = Rn + offset; 4458 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, data)) 4459 return false; 4460 } 4461 } 4462 return true; 4463} 4464 4465// STMIB (Store Multiple Increment Before) stores multiple registers to consecutive memory locations using an address 4466// from a base register. The consecutive memory locations start just above this address, and the address of the last 4467// of those locations can optionally be written back to the base register. 4468bool 4469EmulateInstructionARM::EmulateSTMIB (const uint32_t opcode, const ARMEncoding encoding) 4470{ 4471#if 0 4472 if ConditionPassed() then 4473 EncodingSpecificOperations(); 4474 address = R[n] + 4; 4475 4476 for i = 0 to 14 4477 if registers<i> == '1' then 4478 if i == n && wback && i != LowestSetBit(registers) then 4479 MemA[address,4] = bits(32) UNKNOWN; 4480 else 4481 MemA[address,4] = R[i]; 4482 address = address + 4; 4483 4484 if registers<15> == '1' then 4485 MemA[address,4] = PCStoreValue(); 4486 4487 if wback then R[n] = R[n] + 4*BitCount(registers); 4488#endif 4489 4490 bool success = false; 4491 4492 if (ConditionPassed(opcode)) 4493 { 4494 uint32_t n; 4495 uint32_t registers = 0; 4496 bool wback; 4497 const uint32_t addr_byte_size = GetAddressByteSize(); 4498 4499 // EncodingSpecificOperations(); 4500 switch (encoding) 4501 { 4502 case eEncodingA1: 4503 // n = UInt(Rn); registers = register_list; wback = (W == '1'); 4504 n = Bits32 (opcode, 19, 16); 4505 registers = Bits32 (opcode, 15, 0); 4506 wback = BitIsSet (opcode, 21); 4507 4508 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE; 4509 if ((n == 15) && (BitCount (registers) < 1)) 4510 return false; 4511 break; 4512 default: 4513 return false; 4514 } 4515 // address = R[n] + 4; 4516 4517 int32_t offset = 0; 4518 addr_t Rn = ReadCoreReg (n, &success); 4519 if (!success) 4520 return false; 4521 4522 addr_t address = Rn + addr_byte_size; 4523 4524 EmulateInstruction::Context context; 4525 context.type = EmulateInstruction::eContextRegisterStore; 4526 RegisterInfo base_reg; 4527 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg); 4528 4529 uint32_t lowest_set_bit = 14; 4530 // for i = 0 to 14 4531 for (uint32_t i = 0; i < 14; ++i) 4532 { 4533 // if registers<i> == '1' then 4534 if (BitIsSet (registers, i)) 4535 { 4536 if (i < lowest_set_bit) 4537 lowest_set_bit = i; 4538 // if i == n && wback && i != LowestSetBit(registers) then 4539 if ((i == n) && wback && (i != lowest_set_bit)) 4540 // MemA[address,4] = bits(32) UNKNOWN; 4541 WriteBits32UnknownToMemory (address + offset); 4542 // else 4543 else 4544 { 4545 // MemA[address,4] = R[i]; 4546 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + i, 0, &success); 4547 if (!success) 4548 return false; 4549 4550 RegisterInfo data_reg; 4551 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + i, data_reg); 4552 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, offset + addr_byte_size); 4553 if (!MemAWrite (context, address + offset, data, addr_byte_size)) 4554 return false; 4555 } 4556 4557 // address = address + 4; 4558 offset += addr_byte_size; 4559 } 4560 } 4561 4562 // if registers<15> == '1' then 4563 // MemA[address,4] = PCStoreValue(); 4564 if (BitIsSet (registers, 15)) 4565 { 4566 RegisterInfo pc_reg; 4567 GetRegisterInfo (eRegisterKindDWARF, dwarf_pc, pc_reg); 4568 context.SetRegisterPlusOffset (pc_reg, 8); 4569 const uint32_t pc = ReadCoreReg (PC_REG, &success); 4570 if (!success) 4571 return false; 4572 4573 if (!MemAWrite (context, address + offset, pc, addr_byte_size)) 4574 return false; 4575 } 4576 4577 // if wback then R[n] = R[n] + 4*BitCount(registers); 4578 if (wback) 4579 { 4580 offset = addr_byte_size * BitCount (registers); 4581 context.type = EmulateInstruction::eContextAdjustBaseRegister; 4582 context.SetImmediateSigned (offset); 4583 addr_t data = Rn + offset; 4584 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, data)) 4585 return false; 4586 } 4587 } 4588 return true; 4589} 4590 4591// STR (store immediate) calcualtes an address from a base register value and an immediate offset, and stores a word 4592// from a register to memory. It can use offset, post-indexed, or pre-indexed addressing. 4593bool 4594EmulateInstructionARM::EmulateSTRThumb (const uint32_t opcode, const ARMEncoding encoding) 4595{ 4596#if 0 4597 if ConditionPassed() then 4598 EncodingSpecificOperations(); NullCheckIfThumbEE(n); 4599 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32); 4600 address = if index then offset_addr else R[n]; 4601 if UnalignedSupport() || address<1:0> == '00' then 4602 MemU[address,4] = R[t]; 4603 else // Can only occur before ARMv7 4604 MemU[address,4] = bits(32) UNKNOWN; 4605 if wback then R[n] = offset_addr; 4606#endif 4607 4608 bool success = false; 4609 4610 if (ConditionPassed(opcode)) 4611 { 4612 const uint32_t addr_byte_size = GetAddressByteSize(); 4613 4614 uint32_t t; 4615 uint32_t n; 4616 uint32_t imm32; 4617 bool index; 4618 bool add; 4619 bool wback; 4620 // EncodingSpecificOperations (); NullCheckIfThumbEE(n); 4621 switch (encoding) 4622 { 4623 case eEncodingT1: 4624 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm5:'00', 32); 4625 t = Bits32 (opcode, 2, 0); 4626 n = Bits32 (opcode, 5, 3); 4627 imm32 = Bits32 (opcode, 10, 6) << 2; 4628 4629 // index = TRUE; add = TRUE; wback = FALSE; 4630 index = true; 4631 add = false; 4632 wback = false; 4633 break; 4634 4635 case eEncodingT2: 4636 // t = UInt(Rt); n = 13; imm32 = ZeroExtend(imm8:'00', 32); 4637 t = Bits32 (opcode, 10, 8); 4638 n = 13; 4639 imm32 = Bits32 (opcode, 7, 0) << 2; 4640 4641 // index = TRUE; add = TRUE; wback = FALSE; 4642 index = true; 4643 add = true; 4644 wback = false; 4645 break; 4646 4647 case eEncodingT3: 4648 // if Rn == '1111' then UNDEFINED; 4649 if (Bits32 (opcode, 19, 16) == 15) 4650 return false; 4651 4652 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32); 4653 t = Bits32 (opcode, 15, 12); 4654 n = Bits32 (opcode, 19, 16); 4655 imm32 = Bits32 (opcode, 11, 0); 4656 4657 // index = TRUE; add = TRUE; wback = FALSE; 4658 index = true; 4659 add = true; 4660 wback = false; 4661 4662 // if t == 15 then UNPREDICTABLE; 4663 if (t == 15) 4664 return false; 4665 break; 4666 4667 case eEncodingT4: 4668 // if P == '1' && U == '1' && W == '0' then SEE STRT; 4669 // if Rn == '1101' && P == '1' && U == '0' && W == '1' && imm8 == '00000100' then SEE PUSH; 4670 // if Rn == '1111' || (P == '0' && W == '0') then UNDEFINED; 4671 if ((Bits32 (opcode, 19, 16) == 15) 4672 || (BitIsClear (opcode, 10) && BitIsClear (opcode, 8))) 4673 return false; 4674 4675 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32); 4676 t = Bits32 (opcode, 15, 12); 4677 n = Bits32 (opcode, 19, 16); 4678 imm32 = Bits32 (opcode, 7, 0); 4679 4680 // index = (P == '1'); add = (U == '1'); wback = (W == '1'); 4681 index = BitIsSet (opcode, 10); 4682 add = BitIsSet (opcode, 9); 4683 wback = BitIsSet (opcode, 8); 4684 4685 // if t == 15 || (wback && n == t) then UNPREDICTABLE; 4686 if ((t == 15) || (wback && (n == t))) 4687 return false; 4688 break; 4689 4690 default: 4691 return false; 4692 } 4693 4694 addr_t offset_addr; 4695 addr_t address; 4696 4697 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32); 4698 uint32_t base_address = ReadCoreReg (n, &success); 4699 if (!success) 4700 return false; 4701 4702 if (add) 4703 offset_addr = base_address + imm32; 4704 else 4705 offset_addr = base_address - imm32; 4706 4707 // address = if index then offset_addr else R[n]; 4708 if (index) 4709 address = offset_addr; 4710 else 4711 address = base_address; 4712 4713 EmulateInstruction::Context context; 4714 context.type = eContextRegisterStore; 4715 RegisterInfo base_reg; 4716 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg); 4717 4718 // if UnalignedSupport() || address<1:0> == '00' then 4719 if (UnalignedSupport () || (BitIsClear (address, 1) && BitIsClear (address, 0))) 4720 { 4721 // MemU[address,4] = R[t]; 4722 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + t, 0, &success); 4723 if (!success) 4724 return false; 4725 4726 RegisterInfo data_reg; 4727 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + t, data_reg); 4728 int32_t offset = address - base_address; 4729 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, offset); 4730 if (!MemUWrite (context, address, data, addr_byte_size)) 4731 return false; 4732 } 4733 else 4734 { 4735 // MemU[address,4] = bits(32) UNKNOWN; 4736 WriteBits32UnknownToMemory (address); 4737 } 4738 4739 // if wback then R[n] = offset_addr; 4740 if (wback) 4741 { 4742 context.type = eContextRegisterLoad; 4743 context.SetAddress (offset_addr); 4744 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr)) 4745 return false; 4746 } 4747 } 4748 return true; 4749} 4750 4751// STR (Store Register) calculates an address from a base register value and an offset register value, stores a 4752// word from a register to memory. The offset register value can optionally be shifted. 4753bool 4754EmulateInstructionARM::EmulateSTRRegister (const uint32_t opcode, const ARMEncoding encoding) 4755{ 4756#if 0 4757 if ConditionPassed() then 4758 EncodingSpecificOperations(); NullCheckIfThumbEE(n); 4759 offset = Shift(R[m], shift_t, shift_n, APSR.C); 4760 offset_addr = if add then (R[n] + offset) else (R[n] - offset); 4761 address = if index then offset_addr else R[n]; 4762 if t == 15 then // Only possible for encoding A1 4763 data = PCStoreValue(); 4764 else 4765 data = R[t]; 4766 if UnalignedSupport() || address<1:0> == '00' || CurrentInstrSet() == InstrSet_ARM then 4767 MemU[address,4] = data; 4768 else // Can only occur before ARMv7 4769 MemU[address,4] = bits(32) UNKNOWN; 4770 if wback then R[n] = offset_addr; 4771#endif 4772 4773 bool success = false; 4774 4775 if (ConditionPassed(opcode)) 4776 { 4777 const uint32_t addr_byte_size = GetAddressByteSize(); 4778 4779 uint32_t t; 4780 uint32_t n; 4781 uint32_t m; 4782 ARM_ShifterType shift_t; 4783 uint32_t shift_n; 4784 bool index; 4785 bool add; 4786 bool wback; 4787 4788 // EncodingSpecificOperations (); NullCheckIfThumbEE(n); 4789 switch (encoding) 4790 { 4791 case eEncodingT1: 4792 // if CurrentInstrSet() == InstrSet_ThumbEE then SEE "Modified operation in ThumbEE"; 4793 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm); 4794 t = Bits32 (opcode, 2, 0); 4795 n = Bits32 (opcode, 5, 3); 4796 m = Bits32 (opcode, 8, 6); 4797 4798 // index = TRUE; add = TRUE; wback = FALSE; 4799 index = true; 4800 add = true; 4801 wback = false; 4802 4803 // (shift_t, shift_n) = (SRType_LSL, 0); 4804 shift_t = SRType_LSL; 4805 shift_n = 0; 4806 break; 4807 4808 case eEncodingT2: 4809 // if Rn == '1111' then UNDEFINED; 4810 if (Bits32 (opcode, 19, 16) == 15) 4811 return false; 4812 4813 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm); 4814 t = Bits32 (opcode, 15, 12); 4815 n = Bits32 (opcode, 19, 16); 4816 m = Bits32 (opcode, 3, 0); 4817 4818 // index = TRUE; add = TRUE; wback = FALSE; 4819 index = true; 4820 add = true; 4821 wback = false; 4822 4823 // (shift_t, shift_n) = (SRType_LSL, UInt(imm2)); 4824 shift_t = SRType_LSL; 4825 shift_n = Bits32 (opcode, 5, 4); 4826 4827 // if t == 15 || BadReg(m) then UNPREDICTABLE; 4828 if ((t == 15) || (BadReg (m))) 4829 return false; 4830 break; 4831 4832 case eEncodingA1: 4833 { 4834 // if P == '0' && W == '1' then SEE STRT; 4835 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm); 4836 t = Bits32 (opcode, 15, 12); 4837 n = Bits32 (opcode, 19, 16); 4838 m = Bits32 (opcode, 3, 0); 4839 4840 // index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1'); 4841 index = BitIsSet (opcode, 24); 4842 add = BitIsSet (opcode, 23); 4843 wback = (BitIsClear (opcode, 24) || BitIsSet (opcode, 21)); 4844 4845 // (shift_t, shift_n) = DecodeImmShift(type, imm5); 4846 uint32_t typ = Bits32 (opcode, 6, 5); 4847 uint32_t imm5 = Bits32 (opcode, 11, 7); 4848 shift_n = DecodeImmShift(typ, imm5, shift_t); 4849 4850 // if m == 15 then UNPREDICTABLE; 4851 if (m == 15) 4852 return false; 4853 4854 // if wback && (n == 15 || n == t) then UNPREDICTABLE; 4855 if (wback && ((n == 15) || (n == t))) 4856 return false; 4857 4858 break; 4859 } 4860 default: 4861 return false; 4862 } 4863 4864 addr_t offset_addr; 4865 addr_t address; 4866 int32_t offset = 0; 4867 4868 addr_t base_address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success); 4869 if (!success) 4870 return false; 4871 4872 uint32_t Rm_data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success); 4873 if (!success) 4874 return false; 4875 4876 // offset = Shift(R[m], shift_t, shift_n, APSR.C); 4877 offset = Shift (Rm_data, shift_t, shift_n, APSR_C, &success); 4878 if (!success) 4879 return false; 4880 4881 // offset_addr = if add then (R[n] + offset) else (R[n] - offset); 4882 if (add) 4883 offset_addr = base_address + offset; 4884 else 4885 offset_addr = base_address - offset; 4886 4887 // address = if index then offset_addr else R[n]; 4888 if (index) 4889 address = offset_addr; 4890 else 4891 address = base_address; 4892 4893 uint32_t data; 4894 // if t == 15 then // Only possible for encoding A1 4895 if (t == 15) 4896 // data = PCStoreValue(); 4897 data = ReadCoreReg (PC_REG, &success); 4898 else 4899 // data = R[t]; 4900 data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + t, 0, &success); 4901 4902 if (!success) 4903 return false; 4904 4905 EmulateInstruction::Context context; 4906 context.type = eContextRegisterStore; 4907 4908 // if UnalignedSupport() || address<1:0> == '00' || CurrentInstrSet() == InstrSet_ARM then 4909 if (UnalignedSupport () 4910 || (BitIsClear (address, 1) && BitIsClear (address, 0)) 4911 || CurrentInstrSet() == eModeARM) 4912 { 4913 // MemU[address,4] = data; 4914 4915 RegisterInfo base_reg; 4916 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg); 4917 4918 RegisterInfo data_reg; 4919 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + t, data_reg); 4920 4921 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, address - base_address); 4922 if (!MemUWrite (context, address, data, addr_byte_size)) 4923 return false; 4924 4925 } 4926 else 4927 // MemU[address,4] = bits(32) UNKNOWN; 4928 WriteBits32UnknownToMemory (address); 4929 4930 // if wback then R[n] = offset_addr; 4931 if (wback) 4932 { 4933 context.type = eContextRegisterLoad; 4934 context.SetAddress (offset_addr); 4935 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr)) 4936 return false; 4937 } 4938 4939 } 4940 return true; 4941} 4942 4943bool 4944EmulateInstructionARM::EmulateSTRBThumb (const uint32_t opcode, const ARMEncoding encoding) 4945{ 4946#if 0 4947 if ConditionPassed() then 4948 EncodingSpecificOperations(); NullCheckIfThumbEE(n); 4949 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32); 4950 address = if index then offset_addr else R[n]; 4951 MemU[address,1] = R[t]<7:0>; 4952 if wback then R[n] = offset_addr; 4953#endif 4954 4955 4956 bool success = false; 4957 4958 if (ConditionPassed(opcode)) 4959 { 4960 uint32_t t; 4961 uint32_t n; 4962 uint32_t imm32; 4963 bool index; 4964 bool add; 4965 bool wback; 4966 // EncodingSpecificOperations(); NullCheckIfThumbEE(n); 4967 switch (encoding) 4968 { 4969 case eEncodingT1: 4970 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm5, 32); 4971 t = Bits32 (opcode, 2, 0); 4972 n = Bits32 (opcode, 5, 3); 4973 imm32 = Bits32 (opcode, 10, 6); 4974 4975 // index = TRUE; add = TRUE; wback = FALSE; 4976 index = true; 4977 add = true; 4978 wback = false; 4979 break; 4980 4981 case eEncodingT2: 4982 // if Rn == '1111' then UNDEFINED; 4983 if (Bits32 (opcode, 19, 16) == 15) 4984 return false; 4985 4986 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32); 4987 t = Bits32 (opcode, 15, 12); 4988 n = Bits32 (opcode, 19, 16); 4989 imm32 = Bits32 (opcode, 11, 0); 4990 4991 // index = TRUE; add = TRUE; wback = FALSE; 4992 index = true; 4993 add = true; 4994 wback = false; 4995 4996 // if BadReg(t) then UNPREDICTABLE; 4997 if (BadReg (t)) 4998 return false; 4999 break; 5000 5001 case eEncodingT3: 5002 // if P == '1' && U == '1' && W == '0' then SEE STRBT; 5003 // if Rn == '1111' || (P == '0' && W == '0') then UNDEFINED; 5004 if (Bits32 (opcode, 19, 16) == 15) 5005 return false; 5006 5007 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32); 5008 t = Bits32 (opcode, 15, 12); 5009 n = Bits32 (opcode, 19, 16); 5010 imm32 = Bits32 (opcode, 7, 0); 5011 5012 // index = (P == '1'); add = (U == '1'); wback = (W == '1'); 5013 index = BitIsSet (opcode, 10); 5014 add = BitIsSet (opcode, 9); 5015 wback = BitIsSet (opcode, 8); 5016 5017 // if BadReg(t) || (wback && n == t) then UNPREDICTABLE 5018 if ((BadReg (t)) || (wback && (n == t))) 5019 return false; 5020 break; 5021 5022 default: 5023 return false; 5024 } 5025 5026 addr_t offset_addr; 5027 addr_t address; 5028 addr_t base_address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success); 5029 if (!success) 5030 return false; 5031 5032 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32); 5033 if (add) 5034 offset_addr = base_address + imm32; 5035 else 5036 offset_addr = base_address - imm32; 5037 5038 // address = if index then offset_addr else R[n]; 5039 if (index) 5040 address = offset_addr; 5041 else 5042 address = base_address; 5043 5044 // MemU[address,1] = R[t]<7:0> 5045 RegisterInfo base_reg; 5046 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg); 5047 5048 RegisterInfo data_reg; 5049 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + t, data_reg); 5050 5051 EmulateInstruction::Context context; 5052 context.type = eContextRegisterStore; 5053 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, address - base_address); 5054 5055 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + t, 0, &success); 5056 if (!success) 5057 return false; 5058 5059 data = Bits32 (data, 7, 0); 5060 5061 if (!MemUWrite (context, address, data, 1)) 5062 return false; 5063 5064 // if wback then R[n] = offset_addr; 5065 if (wback) 5066 { 5067 context.type = eContextRegisterLoad; 5068 context.SetAddress (offset_addr); 5069 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr)) 5070 return false; 5071 } 5072 5073 } 5074 5075 return true; 5076} 5077 5078// STRH (register) calculates an address from a base register value and an offset register value, and stores a 5079// halfword from a register to memory. The offset register alue can be shifted left by 0, 1, 2, or 3 bits. 5080bool 5081EmulateInstructionARM::EmulateSTRHRegister (const uint32_t opcode, const ARMEncoding encoding) 5082{ 5083#if 0 5084 if ConditionPassed() then 5085 EncodingSpecificOperations(); NullCheckIfThumbEE(n); 5086 offset = Shift(R[m], shift_t, shift_n, APSR.C); 5087 offset_addr = if add then (R[n] + offset) else (R[n] - offset); 5088 address = if index then offset_addr else R[n]; 5089 if UnalignedSupport() || address<0> == '0' then 5090 MemU[address,2] = R[t]<15:0>; 5091 else // Can only occur before ARMv7 5092 MemU[address,2] = bits(16) UNKNOWN; 5093 if wback then R[n] = offset_addr; 5094#endif 5095 5096 bool success = false; 5097 5098 if (ConditionPassed(opcode)) 5099 { 5100 uint32_t t; 5101 uint32_t n; 5102 uint32_t m; 5103 bool index; 5104 bool add; 5105 bool wback; 5106 ARM_ShifterType shift_t; 5107 uint32_t shift_n; 5108 5109 // EncodingSpecificOperations(); NullCheckIfThumbEE(n); 5110 switch (encoding) 5111 { 5112 case eEncodingT1: 5113 // if CurrentInstrSet() == InstrSet_ThumbEE then SEE "Modified operation in ThumbEE"; 5114 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm); 5115 t = Bits32 (opcode, 2, 0); 5116 n = Bits32 (opcode, 5, 3); 5117 m = Bits32 (opcode, 8, 6); 5118 5119 // index = TRUE; add = TRUE; wback = FALSE; 5120 index = true; 5121 add = true; 5122 wback = false; 5123 5124 // (shift_t, shift_n) = (SRType_LSL, 0); 5125 shift_t = SRType_LSL; 5126 shift_n = 0; 5127 5128 break; 5129 5130 case eEncodingT2: 5131 // if Rn == '1111' then UNDEFINED; 5132 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm); 5133 t = Bits32 (opcode, 15, 12); 5134 n = Bits32 (opcode, 19, 16); 5135 m = Bits32 (opcode, 3, 0); 5136 if (n == 15) 5137 return false; 5138 5139 // index = TRUE; add = TRUE; wback = FALSE; 5140 index = true; 5141 add = true; 5142 wback = false; 5143 5144 // (shift_t, shift_n) = (SRType_LSL, UInt(imm2)); 5145 shift_t = SRType_LSL; 5146 shift_n = Bits32 (opcode, 5, 4); 5147 5148 // if BadReg(t) || BadReg(m) then UNPREDICTABLE; 5149 if (BadReg (t) || BadReg (m)) 5150 return false; 5151 5152 break; 5153 5154 case eEncodingA1: 5155 // if P == '0' && W == '1' then SEE STRHT; 5156 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm); 5157 t = Bits32 (opcode, 15, 12); 5158 n = Bits32 (opcode, 19, 16); 5159 m = Bits32 (opcode, 3, 0); 5160 5161 // index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1'); 5162 index = BitIsSet (opcode, 24); 5163 add = BitIsSet (opcode, 23); 5164 wback = (BitIsClear (opcode, 24) || BitIsSet (opcode, 21)); 5165 5166 // (shift_t, shift_n) = (SRType_LSL, 0); 5167 shift_t = SRType_LSL; 5168 shift_n = 0; 5169 5170 // if t == 15 || m == 15 then UNPREDICTABLE; 5171 if ((t == 15) || (m == 15)) 5172 return false; 5173 5174 // if wback && (n == 15 || n == t) then UNPREDICTABLE; 5175 if (wback && ((n == 15) || (n == t))) 5176 return false; 5177 5178 break; 5179 5180 default: 5181 return false; 5182 } 5183 5184 uint32_t Rm = ReadCoreReg (m, &success); 5185 if (!success) 5186 return false; 5187 5188 uint32_t Rn = ReadCoreReg (n, &success); 5189 if (!success) 5190 return false; 5191 5192 // offset = Shift(R[m], shift_t, shift_n, APSR.C); 5193 uint32_t offset = Shift (Rm, shift_t, shift_n, APSR_C, &success); 5194 if (!success) 5195 return false; 5196 5197 // offset_addr = if add then (R[n] + offset) else (R[n] - offset); 5198 addr_t offset_addr; 5199 if (add) 5200 offset_addr = Rn + offset; 5201 else 5202 offset_addr = Rn - offset; 5203 5204 // address = if index then offset_addr else R[n]; 5205 addr_t address; 5206 if (index) 5207 address = offset_addr; 5208 else 5209 address = Rn; 5210 5211 EmulateInstruction::Context context; 5212 context.type = eContextRegisterStore; 5213 RegisterInfo base_reg; 5214 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg); 5215 RegisterInfo offset_reg; 5216 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + m, offset_reg); 5217 5218 // if UnalignedSupport() || address<0> == '0' then 5219 if (UnalignedSupport() || BitIsClear (address, 0)) 5220 { 5221 // MemU[address,2] = R[t]<15:0>; 5222 uint32_t Rt = ReadCoreReg (t, &success); 5223 if (!success) 5224 return false; 5225 5226 EmulateInstruction::Context context; 5227 context.type = eContextRegisterStore; 5228 RegisterInfo base_reg; 5229 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg); 5230 RegisterInfo offset_reg; 5231 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + m, offset_reg); 5232 RegisterInfo data_reg; 5233 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + t, data_reg); 5234 context.SetRegisterToRegisterPlusIndirectOffset (base_reg, offset_reg, data_reg); 5235 5236 if (!MemUWrite (context, address, Bits32 (Rt, 15, 0), 2)) 5237 return false; 5238 } 5239 else // Can only occur before ARMv7 5240 { 5241 // MemU[address,2] = bits(16) UNKNOWN; 5242 } 5243 5244 // if wback then R[n] = offset_addr; 5245 if (wback) 5246 { 5247 context.type = eContextAdjustBaseRegister; 5248 context.SetAddress (offset_addr); 5249 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr)) 5250 return false; 5251 } 5252 } 5253 5254 return true; 5255} 5256 5257// Add with Carry (immediate) adds an immediate value and the carry flag value to a register value, 5258// and writes the result to the destination register. It can optionally update the condition flags 5259// based on the result. 5260bool 5261EmulateInstructionARM::EmulateADCImm (const uint32_t opcode, const ARMEncoding encoding) 5262{ 5263#if 0 5264 // ARM pseudo code... 5265 if ConditionPassed() then 5266 EncodingSpecificOperations(); 5267 (result, carry, overflow) = AddWithCarry(R[n], imm32, APSR.C); 5268 if d == 15 then // Can only occur for ARM encoding 5269 ALUWritePC(result); // setflags is always FALSE here 5270 else 5271 R[d] = result; 5272 if setflags then 5273 APSR.N = result<31>; 5274 APSR.Z = IsZeroBit(result); 5275 APSR.C = carry; 5276 APSR.V = overflow; 5277#endif 5278 5279 bool success = false; 5280 5281 if (ConditionPassed(opcode)) 5282 { 5283 uint32_t Rd, Rn; 5284 uint32_t imm32; // the immediate value to be added to the value obtained from Rn 5285 bool setflags; 5286 switch (encoding) 5287 { 5288 case eEncodingT1: 5289 Rd = Bits32(opcode, 11, 8); 5290 Rn = Bits32(opcode, 19, 16); 5291 setflags = BitIsSet(opcode, 20); 5292 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8) 5293 if (BadReg(Rd) || BadReg(Rn)) 5294 return false; 5295 break; 5296 case eEncodingA1: 5297 Rd = Bits32(opcode, 15, 12); 5298 Rn = Bits32(opcode, 19, 16); 5299 setflags = BitIsSet(opcode, 20); 5300 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12) 5301 5302 if (Rd == 15 && setflags) 5303 return EmulateSUBSPcLrEtc (opcode, encoding); 5304 break; 5305 default: 5306 return false; 5307 } 5308 5309 // Read the first operand. 5310 int32_t val1 = ReadCoreReg(Rn, &success); 5311 if (!success) 5312 return false; 5313 5314 AddWithCarryResult res = AddWithCarry(val1, imm32, APSR_C); 5315 5316 EmulateInstruction::Context context; 5317 context.type = EmulateInstruction::eContextImmediate; 5318 context.SetNoArgs (); 5319 5320 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow)) 5321 return false; 5322 } 5323 return true; 5324} 5325 5326// Add with Carry (register) adds a register value, the carry flag value, and an optionally-shifted 5327// register value, and writes the result to the destination register. It can optionally update the 5328// condition flags based on the result. 5329bool 5330EmulateInstructionARM::EmulateADCReg (const uint32_t opcode, const ARMEncoding encoding) 5331{ 5332#if 0 5333 // ARM pseudo code... 5334 if ConditionPassed() then 5335 EncodingSpecificOperations(); 5336 shifted = Shift(R[m], shift_t, shift_n, APSR.C); 5337 (result, carry, overflow) = AddWithCarry(R[n], shifted, APSR.C); 5338 if d == 15 then // Can only occur for ARM encoding 5339 ALUWritePC(result); // setflags is always FALSE here 5340 else 5341 R[d] = result; 5342 if setflags then 5343 APSR.N = result<31>; 5344 APSR.Z = IsZeroBit(result); 5345 APSR.C = carry; 5346 APSR.V = overflow; 5347#endif 5348 5349 bool success = false; 5350 5351 if (ConditionPassed(opcode)) 5352 { 5353 uint32_t Rd, Rn, Rm; 5354 ARM_ShifterType shift_t; 5355 uint32_t shift_n; // the shift applied to the value read from Rm 5356 bool setflags; 5357 switch (encoding) 5358 { 5359 case eEncodingT1: 5360 Rd = Rn = Bits32(opcode, 2, 0); 5361 Rm = Bits32(opcode, 5, 3); 5362 setflags = !InITBlock(); 5363 shift_t = SRType_LSL; 5364 shift_n = 0; 5365 break; 5366 case eEncodingT2: 5367 Rd = Bits32(opcode, 11, 8); 5368 Rn = Bits32(opcode, 19, 16); 5369 Rm = Bits32(opcode, 3, 0); 5370 setflags = BitIsSet(opcode, 20); 5371 shift_n = DecodeImmShiftThumb(opcode, shift_t); 5372 if (BadReg(Rd) || BadReg(Rn) || BadReg(Rm)) 5373 return false; 5374 break; 5375 case eEncodingA1: 5376 Rd = Bits32(opcode, 15, 12); 5377 Rn = Bits32(opcode, 19, 16); 5378 Rm = Bits32(opcode, 3, 0); 5379 setflags = BitIsSet(opcode, 20); 5380 shift_n = DecodeImmShiftARM(opcode, shift_t); 5381 5382 if (Rd == 15 && setflags) 5383 return EmulateSUBSPcLrEtc (opcode, encoding); 5384 break; 5385 default: 5386 return false; 5387 } 5388 5389 // Read the first operand. 5390 int32_t val1 = ReadCoreReg(Rn, &success); 5391 if (!success) 5392 return false; 5393 5394 // Read the second operand. 5395 int32_t val2 = ReadCoreReg(Rm, &success); 5396 if (!success) 5397 return false; 5398 5399 uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C, &success); 5400 if (!success) 5401 return false; 5402 AddWithCarryResult res = AddWithCarry(val1, shifted, APSR_C); 5403 5404 EmulateInstruction::Context context; 5405 context.type = EmulateInstruction::eContextImmediate; 5406 context.SetNoArgs (); 5407 5408 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow)) 5409 return false; 5410 } 5411 return true; 5412} 5413 5414// This instruction adds an immediate value to the PC value to form a PC-relative address, 5415// and writes the result to the destination register. 5416bool 5417EmulateInstructionARM::EmulateADR (const uint32_t opcode, const ARMEncoding encoding) 5418{ 5419#if 0 5420 // ARM pseudo code... 5421 if ConditionPassed() then 5422 EncodingSpecificOperations(); 5423 result = if add then (Align(PC,4) + imm32) else (Align(PC,4) - imm32); 5424 if d == 15 then // Can only occur for ARM encodings 5425 ALUWritePC(result); 5426 else 5427 R[d] = result; 5428#endif 5429 5430 bool success = false; 5431 5432 if (ConditionPassed(opcode)) 5433 { 5434 uint32_t Rd; 5435 uint32_t imm32; // the immediate value to be added/subtracted to/from the PC 5436 bool add; 5437 switch (encoding) 5438 { 5439 case eEncodingT1: 5440 Rd = Bits32(opcode, 10, 8); 5441 imm32 = ThumbImm8Scaled(opcode); // imm32 = ZeroExtend(imm8:'00', 32) 5442 add = true; 5443 break; 5444 case eEncodingT2: 5445 case eEncodingT3: 5446 Rd = Bits32(opcode, 11, 8); 5447 imm32 = ThumbImm12(opcode); // imm32 = ZeroExtend(i:imm3:imm8, 32) 5448 add = (Bits32(opcode, 24, 21) == 0); // 0b0000 => ADD; 0b0101 => SUB 5449 if (BadReg(Rd)) 5450 return false; 5451 break; 5452 case eEncodingA1: 5453 case eEncodingA2: 5454 Rd = Bits32(opcode, 15, 12); 5455 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12) 5456 add = (Bits32(opcode, 24, 21) == 0x4); // 0b0100 => ADD; 0b0010 => SUB 5457 break; 5458 default: 5459 return false; 5460 } 5461 5462 // Read the PC value. 5463 uint32_t pc = ReadCoreReg(PC_REG, &success); 5464 if (!success) 5465 return false; 5466 5467 uint32_t result = (add ? Align(pc, 4) + imm32 : Align(pc, 4) - imm32); 5468 5469 EmulateInstruction::Context context; 5470 context.type = EmulateInstruction::eContextImmediate; 5471 context.SetNoArgs (); 5472 5473 if (!WriteCoreReg(context, result, Rd)) 5474 return false; 5475 } 5476 return true; 5477} 5478 5479// This instruction performs a bitwise AND of a register value and an immediate value, and writes the result 5480// to the destination register. It can optionally update the condition flags based on the result. 5481bool 5482EmulateInstructionARM::EmulateANDImm (const uint32_t opcode, const ARMEncoding encoding) 5483{ 5484#if 0 5485 // ARM pseudo code... 5486 if ConditionPassed() then 5487 EncodingSpecificOperations(); 5488 result = R[n] AND imm32; 5489 if d == 15 then // Can only occur for ARM encoding 5490 ALUWritePC(result); // setflags is always FALSE here 5491 else 5492 R[d] = result; 5493 if setflags then 5494 APSR.N = result<31>; 5495 APSR.Z = IsZeroBit(result); 5496 APSR.C = carry; 5497 // APSR.V unchanged 5498#endif 5499 5500 bool success = false; 5501 5502 if (ConditionPassed(opcode)) 5503 { 5504 uint32_t Rd, Rn; 5505 uint32_t imm32; // the immediate value to be ANDed to the value obtained from Rn 5506 bool setflags; 5507 uint32_t carry; // the carry bit after ARM/Thumb Expand operation 5508 switch (encoding) 5509 { 5510 case eEncodingT1: 5511 Rd = Bits32(opcode, 11, 8); 5512 Rn = Bits32(opcode, 19, 16); 5513 setflags = BitIsSet(opcode, 20); 5514 imm32 = ThumbExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C) 5515 // if Rd == '1111' && S == '1' then SEE TST (immediate); 5516 if (Rd == 15 && setflags) 5517 return EmulateTSTImm(opcode, eEncodingT1); 5518 if (Rd == 13 || (Rd == 15 && !setflags) || BadReg(Rn)) 5519 return false; 5520 break; 5521 case eEncodingA1: 5522 Rd = Bits32(opcode, 15, 12); 5523 Rn = Bits32(opcode, 19, 16); 5524 setflags = BitIsSet(opcode, 20); 5525 imm32 = ARMExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ARMExpandImm(imm12, APSR.C) 5526 5527 if (Rd == 15 && setflags) 5528 return EmulateSUBSPcLrEtc (opcode, encoding); 5529 break; 5530 default: 5531 return false; 5532 } 5533 5534 // Read the first operand. 5535 uint32_t val1 = ReadCoreReg(Rn, &success); 5536 if (!success) 5537 return false; 5538 5539 uint32_t result = val1 & imm32; 5540 5541 EmulateInstruction::Context context; 5542 context.type = EmulateInstruction::eContextImmediate; 5543 context.SetNoArgs (); 5544 5545 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry)) 5546 return false; 5547 } 5548 return true; 5549} 5550 5551// This instruction performs a bitwise AND of a register value and an optionally-shifted register value, 5552// and writes the result to the destination register. It can optionally update the condition flags 5553// based on the result. 5554bool 5555EmulateInstructionARM::EmulateANDReg (const uint32_t opcode, const ARMEncoding encoding) 5556{ 5557#if 0 5558 // ARM pseudo code... 5559 if ConditionPassed() then 5560 EncodingSpecificOperations(); 5561 (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C); 5562 result = R[n] AND shifted; 5563 if d == 15 then // Can only occur for ARM encoding 5564 ALUWritePC(result); // setflags is always FALSE here 5565 else 5566 R[d] = result; 5567 if setflags then 5568 APSR.N = result<31>; 5569 APSR.Z = IsZeroBit(result); 5570 APSR.C = carry; 5571 // APSR.V unchanged 5572#endif 5573 5574 bool success = false; 5575 5576 if (ConditionPassed(opcode)) 5577 { 5578 uint32_t Rd, Rn, Rm; 5579 ARM_ShifterType shift_t; 5580 uint32_t shift_n; // the shift applied to the value read from Rm 5581 bool setflags; 5582 uint32_t carry; 5583 switch (encoding) 5584 { 5585 case eEncodingT1: 5586 Rd = Rn = Bits32(opcode, 2, 0); 5587 Rm = Bits32(opcode, 5, 3); 5588 setflags = !InITBlock(); 5589 shift_t = SRType_LSL; 5590 shift_n = 0; 5591 break; 5592 case eEncodingT2: 5593 Rd = Bits32(opcode, 11, 8); 5594 Rn = Bits32(opcode, 19, 16); 5595 Rm = Bits32(opcode, 3, 0); 5596 setflags = BitIsSet(opcode, 20); 5597 shift_n = DecodeImmShiftThumb(opcode, shift_t); 5598 // if Rd == '1111' && S == '1' then SEE TST (register); 5599 if (Rd == 15 && setflags) 5600 return EmulateTSTReg(opcode, eEncodingT2); 5601 if (Rd == 13 || (Rd == 15 && !setflags) || BadReg(Rn) || BadReg(Rm)) 5602 return false; 5603 break; 5604 case eEncodingA1: 5605 Rd = Bits32(opcode, 15, 12); 5606 Rn = Bits32(opcode, 19, 16); 5607 Rm = Bits32(opcode, 3, 0); 5608 setflags = BitIsSet(opcode, 20); 5609 shift_n = DecodeImmShiftARM(opcode, shift_t); 5610 5611 if (Rd == 15 && setflags) 5612 return EmulateSUBSPcLrEtc (opcode, encoding); 5613 break; 5614 default: 5615 return false; 5616 } 5617 5618 // Read the first operand. 5619 uint32_t val1 = ReadCoreReg(Rn, &success); 5620 if (!success) 5621 return false; 5622 5623 // Read the second operand. 5624 uint32_t val2 = ReadCoreReg(Rm, &success); 5625 if (!success) 5626 return false; 5627 5628 uint32_t shifted = Shift_C(val2, shift_t, shift_n, APSR_C, carry, &success); 5629 if (!success) 5630 return false; 5631 uint32_t result = val1 & shifted; 5632 5633 EmulateInstruction::Context context; 5634 context.type = EmulateInstruction::eContextImmediate; 5635 context.SetNoArgs (); 5636 5637 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry)) 5638 return false; 5639 } 5640 return true; 5641} 5642 5643// Bitwise Bit Clear (immediate) performs a bitwise AND of a register value and the complement of an 5644// immediate value, and writes the result to the destination register. It can optionally update the 5645// condition flags based on the result. 5646bool 5647EmulateInstructionARM::EmulateBICImm (const uint32_t opcode, const ARMEncoding encoding) 5648{ 5649#if 0 5650 // ARM pseudo code... 5651 if ConditionPassed() then 5652 EncodingSpecificOperations(); 5653 result = R[n] AND NOT(imm32); 5654 if d == 15 then // Can only occur for ARM encoding 5655 ALUWritePC(result); // setflags is always FALSE here 5656 else 5657 R[d] = result; 5658 if setflags then 5659 APSR.N = result<31>; 5660 APSR.Z = IsZeroBit(result); 5661 APSR.C = carry; 5662 // APSR.V unchanged 5663#endif 5664 5665 bool success = false; 5666 5667 if (ConditionPassed(opcode)) 5668 { 5669 uint32_t Rd, Rn; 5670 uint32_t imm32; // the immediate value to be bitwise inverted and ANDed to the value obtained from Rn 5671 bool setflags; 5672 uint32_t carry; // the carry bit after ARM/Thumb Expand operation 5673 switch (encoding) 5674 { 5675 case eEncodingT1: 5676 Rd = Bits32(opcode, 11, 8); 5677 Rn = Bits32(opcode, 19, 16); 5678 setflags = BitIsSet(opcode, 20); 5679 imm32 = ThumbExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C) 5680 if (BadReg(Rd) || BadReg(Rn)) 5681 return false; 5682 break; 5683 case eEncodingA1: 5684 Rd = Bits32(opcode, 15, 12); 5685 Rn = Bits32(opcode, 19, 16); 5686 setflags = BitIsSet(opcode, 20); 5687 imm32 = ARMExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ARMExpandImm(imm12, APSR.C) 5688 5689 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions; 5690 if (Rd == 15 && setflags) 5691 return EmulateSUBSPcLrEtc (opcode, encoding); 5692 break; 5693 default: 5694 return false; 5695 } 5696 5697 // Read the first operand. 5698 uint32_t val1 = ReadCoreReg(Rn, &success); 5699 if (!success) 5700 return false; 5701 5702 uint32_t result = val1 & ~imm32; 5703 5704 EmulateInstruction::Context context; 5705 context.type = EmulateInstruction::eContextImmediate; 5706 context.SetNoArgs (); 5707 5708 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry)) 5709 return false; 5710 } 5711 return true; 5712} 5713 5714// Bitwise Bit Clear (register) performs a bitwise AND of a register value and the complement of an 5715// optionally-shifted register value, and writes the result to the destination register. 5716// It can optionally update the condition flags based on the result. 5717bool 5718EmulateInstructionARM::EmulateBICReg (const uint32_t opcode, const ARMEncoding encoding) 5719{ 5720#if 0 5721 // ARM pseudo code... 5722 if ConditionPassed() then 5723 EncodingSpecificOperations(); 5724 (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C); 5725 result = R[n] AND NOT(shifted); 5726 if d == 15 then // Can only occur for ARM encoding 5727 ALUWritePC(result); // setflags is always FALSE here 5728 else 5729 R[d] = result; 5730 if setflags then 5731 APSR.N = result<31>; 5732 APSR.Z = IsZeroBit(result); 5733 APSR.C = carry; 5734 // APSR.V unchanged 5735#endif 5736 5737 bool success = false; 5738 5739 if (ConditionPassed(opcode)) 5740 { 5741 uint32_t Rd, Rn, Rm; 5742 ARM_ShifterType shift_t; 5743 uint32_t shift_n; // the shift applied to the value read from Rm 5744 bool setflags; 5745 uint32_t carry; 5746 switch (encoding) 5747 { 5748 case eEncodingT1: 5749 Rd = Rn = Bits32(opcode, 2, 0); 5750 Rm = Bits32(opcode, 5, 3); 5751 setflags = !InITBlock(); 5752 shift_t = SRType_LSL; 5753 shift_n = 0; 5754 break; 5755 case eEncodingT2: 5756 Rd = Bits32(opcode, 11, 8); 5757 Rn = Bits32(opcode, 19, 16); 5758 Rm = Bits32(opcode, 3, 0); 5759 setflags = BitIsSet(opcode, 20); 5760 shift_n = DecodeImmShiftThumb(opcode, shift_t); 5761 if (BadReg(Rd) || BadReg(Rn) || BadReg(Rm)) 5762 return false; 5763 break; 5764 case eEncodingA1: 5765 Rd = Bits32(opcode, 15, 12); 5766 Rn = Bits32(opcode, 19, 16); 5767 Rm = Bits32(opcode, 3, 0); 5768 setflags = BitIsSet(opcode, 20); 5769 shift_n = DecodeImmShiftARM(opcode, shift_t); 5770 5771 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions; 5772 if (Rd == 15 && setflags) 5773 return EmulateSUBSPcLrEtc (opcode, encoding); 5774 break; 5775 default: 5776 return false; 5777 } 5778 5779 // Read the first operand. 5780 uint32_t val1 = ReadCoreReg(Rn, &success); 5781 if (!success) 5782 return false; 5783 5784 // Read the second operand. 5785 uint32_t val2 = ReadCoreReg(Rm, &success); 5786 if (!success) 5787 return false; 5788 5789 uint32_t shifted = Shift_C(val2, shift_t, shift_n, APSR_C, carry, &success); 5790 if (!success) 5791 return false; 5792 uint32_t result = val1 & ~shifted; 5793 5794 EmulateInstruction::Context context; 5795 context.type = EmulateInstruction::eContextImmediate; 5796 context.SetNoArgs (); 5797 5798 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry)) 5799 return false; 5800 } 5801 return true; 5802} 5803 5804// LDR (immediate, ARM) calculates an address from a base register value and an immediate offset, loads a word 5805// from memory, and writes it to a register. It can use offset, post-indexed, or pre-indexed addressing. 5806bool 5807EmulateInstructionARM::EmulateLDRImmediateARM (const uint32_t opcode, const ARMEncoding encoding) 5808{ 5809#if 0 5810 if ConditionPassed() then 5811 EncodingSpecificOperations(); 5812 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32); 5813 address = if index then offset_addr else R[n]; 5814 data = MemU[address,4]; 5815 if wback then R[n] = offset_addr; 5816 if t == 15 then 5817 if address<1:0> == '00' then LoadWritePC(data); else UNPREDICTABLE; 5818 elsif UnalignedSupport() || address<1:0> = '00' then 5819 R[t] = data; 5820 else // Can only apply before ARMv7 5821 R[t] = ROR(data, 8*UInt(address<1:0>)); 5822#endif 5823 5824 bool success = false; 5825 5826 if (ConditionPassed(opcode)) 5827 { 5828 const uint32_t addr_byte_size = GetAddressByteSize(); 5829 5830 uint32_t t; 5831 uint32_t n; 5832 uint32_t imm32; 5833 bool index; 5834 bool add; 5835 bool wback; 5836 5837 switch (encoding) 5838 { 5839 case eEncodingA1: 5840 // if Rn == '1111' then SEE LDR (literal); 5841 // if P == '0' && W == '1' then SEE LDRT; 5842 // if Rn == '1101' && P == '0' && U == '1' && W == '0' && imm12 == '000000000100' then SEE POP; 5843 // t == UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32); 5844 t = Bits32 (opcode, 15, 12); 5845 n = Bits32 (opcode, 19, 16); 5846 imm32 = Bits32 (opcode, 11, 0); 5847 5848 // index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1'); 5849 index = BitIsSet (opcode, 24); 5850 add = BitIsSet (opcode, 23); 5851 wback = (BitIsClear (opcode, 24) || BitIsSet (opcode, 21)); 5852 5853 // if wback && n == t then UNPREDICTABLE; 5854 if (wback && (n == t)) 5855 return false; 5856 5857 break; 5858 5859 default: 5860 return false; 5861 } 5862 5863 addr_t address; 5864 addr_t offset_addr; 5865 addr_t base_address = ReadCoreReg (n, &success); 5866 if (!success) 5867 return false; 5868 5869 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32); 5870 if (add) 5871 offset_addr = base_address + imm32; 5872 else 5873 offset_addr = base_address - imm32; 5874 5875 // address = if index then offset_addr else R[n]; 5876 if (index) 5877 address = offset_addr; 5878 else 5879 address = base_address; 5880 5881 // data = MemU[address,4]; 5882 5883 RegisterInfo base_reg; 5884 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg); 5885 5886 EmulateInstruction::Context context; 5887 context.type = eContextRegisterLoad; 5888 context.SetRegisterPlusOffset (base_reg, address - base_address); 5889 5890 uint64_t data = MemURead (context, address, addr_byte_size, 0, &success); 5891 if (!success) 5892 return false; 5893 5894 // if wback then R[n] = offset_addr; 5895 if (wback) 5896 { 5897 context.type = eContextAdjustBaseRegister; 5898 context.SetAddress (offset_addr); 5899 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr)) 5900 return false; 5901 } 5902 5903 // if t == 15 then 5904 if (t == 15) 5905 { 5906 // if address<1:0> == '00' then LoadWritePC(data); else UNPREDICTABLE; 5907 if (BitIsClear (address, 1) && BitIsClear (address, 0)) 5908 { 5909 // LoadWritePC (data); 5910 context.type = eContextRegisterLoad; 5911 context.SetRegisterPlusOffset (base_reg, address - base_address); 5912 LoadWritePC (context, data); 5913 } 5914 else 5915 return false; 5916 } 5917 // elsif UnalignedSupport() || address<1:0> = '00' then 5918 else if (UnalignedSupport() || (BitIsClear (address, 1) && BitIsClear (address, 0))) 5919 { 5920 // R[t] = data; 5921 context.type = eContextRegisterLoad; 5922 context.SetRegisterPlusOffset (base_reg, address - base_address); 5923 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data)) 5924 return false; 5925 } 5926 // else // Can only apply before ARMv7 5927 else 5928 { 5929 // R[t] = ROR(data, 8*UInt(address<1:0>)); 5930 data = ROR (data, Bits32 (address, 1, 0), &success); 5931 if (!success) 5932 return false; 5933 context.type = eContextRegisterLoad; 5934 context.SetImmediate (data); 5935 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data)) 5936 return false; 5937 } 5938 5939 } 5940 return true; 5941} 5942 5943// LDR (register) calculates an address from a base register value and an offset register value, loads a word 5944// from memory, and writes it to a resgister. The offset register value can optionally be shifted. 5945bool 5946EmulateInstructionARM::EmulateLDRRegister (const uint32_t opcode, const ARMEncoding encoding) 5947{ 5948#if 0 5949 if ConditionPassed() then 5950 EncodingSpecificOperations(); NullCheckIfThumbEE(n); 5951 offset = Shift(R[m], shift_t, shift_n, APSR.C); 5952 offset_addr = if add then (R[n] + offset) else (R[n] - offset); 5953 address = if index then offset_addr else R[n]; 5954 data = MemU[address,4]; 5955 if wback then R[n] = offset_addr; 5956 if t == 15 then 5957 if address<1:0> == '00' then LoadWritePC(data); else UNPREDICTABLE; 5958 elsif UnalignedSupport() || address<1:0> = '00' then 5959 R[t] = data; 5960 else // Can only apply before ARMv7 5961 if CurrentInstrSet() == InstrSet_ARM then 5962 R[t] = ROR(data, 8*UInt(address<1:0>)); 5963 else 5964 R[t] = bits(32) UNKNOWN; 5965#endif 5966 5967 bool success = false; 5968 5969 if (ConditionPassed(opcode)) 5970 { 5971 const uint32_t addr_byte_size = GetAddressByteSize(); 5972 5973 uint32_t t; 5974 uint32_t n; 5975 uint32_t m; 5976 bool index; 5977 bool add; 5978 bool wback; 5979 ARM_ShifterType shift_t; 5980 uint32_t shift_n; 5981 5982 switch (encoding) 5983 { 5984 case eEncodingT1: 5985 // if CurrentInstrSet() == InstrSet_ThumbEE then SEE "Modified operation in ThumbEE"; 5986 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm); 5987 t = Bits32 (opcode, 2, 0); 5988 n = Bits32 (opcode, 5, 3); 5989 m = Bits32 (opcode, 8, 6); 5990 5991 // index = TRUE; add = TRUE; wback = FALSE; 5992 index = true; 5993 add = true; 5994 wback = false; 5995 5996 // (shift_t, shift_n) = (SRType_LSL, 0); 5997 shift_t = SRType_LSL; 5998 shift_n = 0; 5999 6000 break; 6001 6002 case eEncodingT2: 6003 // if Rn == '1111' then SEE LDR (literal); 6004 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm); 6005 t = Bits32 (opcode, 15, 12); 6006 n = Bits32 (opcode, 19, 16); 6007 m = Bits32 (opcode, 3, 0); 6008 6009 // index = TRUE; add = TRUE; wback = FALSE; 6010 index = true; 6011 add = true; 6012 wback = false; 6013 6014 // (shift_t, shift_n) = (SRType_LSL, UInt(imm2)); 6015 shift_t = SRType_LSL; 6016 shift_n = Bits32 (opcode, 5, 4); 6017 6018 // if BadReg(m) then UNPREDICTABLE; 6019 if (BadReg (m)) 6020 return false; 6021 6022 // if t == 15 && InITBlock() && !LastInITBlock() then UNPREDICTABLE; 6023 if ((t == 15) && InITBlock() && !LastInITBlock()) 6024 return false; 6025 6026 break; 6027 6028 case eEncodingA1: 6029 { 6030 // if P == '0' && W == '1' then SEE LDRT; 6031 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm); 6032 t = Bits32 (opcode, 15, 12); 6033 n = Bits32 (opcode, 19, 16); 6034 m = Bits32 (opcode, 3, 0); 6035 6036 // index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1'); 6037 index = BitIsSet (opcode, 24); 6038 add = BitIsSet (opcode, 23); 6039 wback = (BitIsClear (opcode, 24) || BitIsSet (opcode, 21)); 6040 6041 // (shift_t, shift_n) = DecodeImmShift(type, imm5); 6042 uint32_t type = Bits32 (opcode, 6, 5); 6043 uint32_t imm5 = Bits32 (opcode, 11, 7); 6044 shift_n = DecodeImmShift (type, imm5, shift_t); 6045 6046 // if m == 15 then UNPREDICTABLE; 6047 if (m == 15) 6048 return false; 6049 6050 // if wback && (n == 15 || n == t) then UNPREDICTABLE; 6051 if (wback && ((n == 15) || (n == t))) 6052 return false; 6053 } 6054 break; 6055 6056 6057 default: 6058 return false; 6059 } 6060 6061 uint32_t Rm = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success); 6062 if (!success) 6063 return false; 6064 6065 uint32_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success); 6066 if (!success) 6067 return false; 6068 6069 addr_t offset_addr; 6070 addr_t address; 6071 6072 // offset = Shift(R[m], shift_t, shift_n, APSR.C); -- Note "The APSR is an application level alias for the CPSR". 6073 addr_t offset = Shift (Rm, shift_t, shift_n, Bit32 (m_opcode_cpsr, APSR_C), &success); 6074 if (!success) 6075 return false; 6076 6077 // offset_addr = if add then (R[n] + offset) else (R[n] - offset); 6078 if (add) 6079 offset_addr = Rn + offset; 6080 else 6081 offset_addr = Rn - offset; 6082 6083 // address = if index then offset_addr else R[n]; 6084 if (index) 6085 address = offset_addr; 6086 else 6087 address = Rn; 6088 6089 // data = MemU[address,4]; 6090 RegisterInfo base_reg; 6091 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg); 6092 6093 EmulateInstruction::Context context; 6094 context.type = eContextRegisterLoad; 6095 context.SetRegisterPlusOffset (base_reg, address - Rn); 6096 6097 uint64_t data = MemURead (context, address, addr_byte_size, 0, &success); 6098 if (!success) 6099 return false; 6100 6101 // if wback then R[n] = offset_addr; 6102 if (wback) 6103 { 6104 context.type = eContextAdjustBaseRegister; 6105 context.SetAddress (offset_addr); 6106 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr)) 6107 return false; 6108 } 6109 6110 // if t == 15 then 6111 if (t == 15) 6112 { 6113 // if address<1:0> == '00' then LoadWritePC(data); else UNPREDICTABLE; 6114 if (BitIsClear (address, 1) && BitIsClear (address, 0)) 6115 { 6116 context.type = eContextRegisterLoad; 6117 context.SetRegisterPlusOffset (base_reg, address - Rn); 6118 LoadWritePC (context, data); 6119 } 6120 else 6121 return false; 6122 } 6123 // elsif UnalignedSupport() || address<1:0> = '00' then 6124 else if (UnalignedSupport () || (BitIsClear (address, 1) && BitIsClear (address, 0))) 6125 { 6126 // R[t] = data; 6127 context.type = eContextRegisterLoad; 6128 context.SetRegisterPlusOffset (base_reg, address - Rn); 6129 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data)) 6130 return false; 6131 } 6132 else // Can only apply before ARMv7 6133 { 6134 // if CurrentInstrSet() == InstrSet_ARM then 6135 if (CurrentInstrSet () == eModeARM) 6136 { 6137 // R[t] = ROR(data, 8*UInt(address<1:0>)); 6138 data = ROR (data, Bits32 (address, 1, 0), &success); 6139 if (!success) 6140 return false; 6141 context.type = eContextRegisterLoad; 6142 context.SetImmediate (data); 6143 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data)) 6144 return false; 6145 } 6146 else 6147 { 6148 // R[t] = bits(32) UNKNOWN; 6149 WriteBits32Unknown (t); 6150 } 6151 } 6152 } 6153 return true; 6154} 6155 6156// LDRB (immediate, Thumb) 6157bool 6158EmulateInstructionARM::EmulateLDRBImmediate (const uint32_t opcode, const ARMEncoding encoding) 6159{ 6160#if 0 6161 if ConditionPassed() then 6162 EncodingSpecificOperations(); NullCheckIfThumbEE(n); 6163 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32); 6164 address = if index then offset_addr else R[n]; 6165 R[t] = ZeroExtend(MemU[address,1], 32); 6166 if wback then R[n] = offset_addr; 6167#endif 6168 6169 bool success = false; 6170 6171 if (ConditionPassed(opcode)) 6172 { 6173 uint32_t t; 6174 uint32_t n; 6175 uint32_t imm32; 6176 bool index; 6177 bool add; 6178 bool wback; 6179 6180 // EncodingSpecificOperations(); NullCheckIfThumbEE(n); 6181 switch (encoding) 6182 { 6183 case eEncodingT1: 6184 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm5, 32); 6185 t = Bits32 (opcode, 2, 0); 6186 n = Bits32 (opcode, 5, 3); 6187 imm32 = Bits32 (opcode, 10, 6); 6188 6189 // index = TRUE; add = TRUE; wback = FALSE; 6190 index = true; 6191 add = true; 6192 wback= false; 6193 6194 break; 6195 6196 case eEncodingT2: 6197 // if Rt == '1111' then SEE PLD; 6198 // if Rn == '1111' then SEE LDRB (literal); 6199 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32); 6200 t = Bits32 (opcode, 15, 12); 6201 n = Bits32 (opcode, 19, 16); 6202 imm32 = Bits32 (opcode, 11, 0); 6203 6204 // index = TRUE; add = TRUE; wback = FALSE; 6205 index = true; 6206 add = true; 6207 wback = false; 6208 6209 // if t == 13 then UNPREDICTABLE; 6210 if (t == 13) 6211 return false; 6212 6213 break; 6214 6215 case eEncodingT3: 6216 // if Rt == '1111' && P == '1' && U == '0' && W == '0' then SEE PLD; 6217 // if Rn == '1111' then SEE LDRB (literal); 6218 // if P == '1' && U == '1' && W == '0' then SEE LDRBT; 6219 // if P == '0' && W == '0' then UNDEFINED; 6220 if (BitIsClear (opcode, 10) && BitIsClear (opcode, 8)) 6221 return false; 6222 6223 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32); 6224 t = Bits32 (opcode, 15, 12); 6225 n = Bits32 (opcode, 19, 16); 6226 imm32 = Bits32 (opcode, 7, 0); 6227 6228 // index = (P == '1'); add = (U == '1'); wback = (W == '1'); 6229 index = BitIsSet (opcode, 10); 6230 add = BitIsSet (opcode, 9); 6231 wback = BitIsSet (opcode, 8); 6232 6233 // if BadReg(t) || (wback && n == t) then UNPREDICTABLE; 6234 if (BadReg (t) || (wback && (n == t))) 6235 return false; 6236 6237 break; 6238 6239 default: 6240 return false; 6241 } 6242 6243 uint32_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success); 6244 if (!success) 6245 return false; 6246 6247 addr_t address; 6248 addr_t offset_addr; 6249 6250 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32); 6251 if (add) 6252 offset_addr = Rn + imm32; 6253 else 6254 offset_addr = Rn - imm32; 6255 6256 // address = if index then offset_addr else R[n]; 6257 if (index) 6258 address = offset_addr; 6259 else 6260 address = Rn; 6261 6262 // R[t] = ZeroExtend(MemU[address,1], 32); 6263 RegisterInfo base_reg; 6264 RegisterInfo data_reg; 6265 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg); 6266 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + t, data_reg); 6267 6268 EmulateInstruction::Context context; 6269 context.type = eContextRegisterLoad; 6270 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, address - Rn); 6271 6272 uint64_t data = MemURead (context, address, 1, 0, &success); 6273 if (!success) 6274 return false; 6275 6276 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data)) 6277 return false; 6278 6279 // if wback then R[n] = offset_addr; 6280 if (wback) 6281 { 6282 context.type = eContextAdjustBaseRegister; 6283 context.SetAddress (offset_addr); 6284 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr)) 6285 return false; 6286 } 6287 } 6288 return true; 6289} 6290 6291// LDRB (literal) calculates an address from the PC value and an immediate offset, loads a byte from memory, 6292// zero-extends it to form a 32-bit word and writes it to a register. 6293bool 6294EmulateInstructionARM::EmulateLDRBLiteral (const uint32_t opcode, const ARMEncoding encoding) 6295{ 6296#if 0 6297 if ConditionPassed() then 6298 EncodingSpecificOperations(); NullCheckIfThumbEE(15); 6299 base = Align(PC,4); 6300 address = if add then (base + imm32) else (base - imm32); 6301 R[t] = ZeroExtend(MemU[address,1], 32); 6302#endif 6303 6304 bool success = false; 6305 6306 if (ConditionPassed(opcode)) 6307 { 6308 uint32_t t; 6309 uint32_t imm32; 6310 bool add; 6311 switch (encoding) 6312 { 6313 case eEncodingT1: 6314 // if Rt == '1111' then SEE PLD; 6315 // t = UInt(Rt); imm32 = ZeroExtend(imm12, 32); add = (U == '1'); 6316 t = Bits32 (opcode, 15, 12); 6317 imm32 = Bits32 (opcode, 11, 0); 6318 add = BitIsSet (opcode, 23); 6319 6320 // if t == 13 then UNPREDICTABLE; 6321 if (t == 13) 6322 return false; 6323 6324 break; 6325 6326 case eEncodingA1: 6327 // t == UInt(Rt); imm32 = ZeroExtend(imm12, 32); add = (U == '1'); 6328 t = Bits32 (opcode, 15, 12); 6329 imm32 = Bits32 (opcode, 11, 0); 6330 add = BitIsSet (opcode, 23); 6331 6332 // if t == 15 then UNPREDICTABLE; 6333 if (t == 15) 6334 return false; 6335 break; 6336 6337 default: 6338 return false; 6339 } 6340 6341 // base = Align(PC,4); 6342 uint32_t pc_val = ReadCoreReg (PC_REG, &success); 6343 if (!success) 6344 return false; 6345 6346 uint32_t base = AlignPC (pc_val); 6347 6348 addr_t address; 6349 // address = if add then (base + imm32) else (base - imm32); 6350 if (add) 6351 address = base + imm32; 6352 else 6353 address = base - imm32; 6354 6355 // R[t] = ZeroExtend(MemU[address,1], 32); 6356 EmulateInstruction::Context context; 6357 context.type = eContextRelativeBranchImmediate; 6358 context.SetImmediate (address - base); 6359 6360 uint64_t data = MemURead (context, address, 1, 0, &success); 6361 if (!success) 6362 return false; 6363 6364 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data)) 6365 return false; 6366 } 6367 return true; 6368} 6369 6370// LDRB (register) calculates an address from a base register value and an offset rigister value, loads a byte from 6371// memory, zero-extends it to form a 32-bit word, and writes it to a register. The offset register value can 6372// optionally be shifted. 6373bool 6374EmulateInstructionARM::EmulateLDRBRegister (const uint32_t opcode, const ARMEncoding encoding) 6375{ 6376#if 0 6377 if ConditionPassed() then 6378 EncodingSpecificOperations(); NullCheckIfThumbEE(n); 6379 offset = Shift(R[m], shift_t, shift_n, APSR.C); 6380 offset_addr = if add then (R[n] + offset) else (R[n] - offset); 6381 address = if index then offset_addr else R[n]; 6382 R[t] = ZeroExtend(MemU[address,1],32); 6383 if wback then R[n] = offset_addr; 6384#endif 6385 6386 bool success = false; 6387 6388 if (ConditionPassed(opcode)) 6389 { 6390 uint32_t t; 6391 uint32_t n; 6392 uint32_t m; 6393 bool index; 6394 bool add; 6395 bool wback; 6396 ARM_ShifterType shift_t; 6397 uint32_t shift_n; 6398 6399 // EncodingSpecificOperations(); NullCheckIfThumbEE(n); 6400 switch (encoding) 6401 { 6402 case eEncodingT1: 6403 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm); 6404 t = Bits32 (opcode, 2, 0); 6405 n = Bits32 (opcode, 5, 3); 6406 m = Bits32 (opcode, 8, 6); 6407 6408 // index = TRUE; add = TRUE; wback = FALSE; 6409 index = true; 6410 add = true; 6411 wback = false; 6412 6413 // (shift_t, shift_n) = (SRType_LSL, 0); 6414 shift_t = SRType_LSL; 6415 shift_n = 0; 6416 break; 6417 6418 case eEncodingT2: 6419 // if Rt == '1111' then SEE PLD; 6420 // if Rn == '1111' then SEE LDRB (literal); 6421 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm); 6422 t = Bits32 (opcode, 15, 12); 6423 n = Bits32 (opcode, 19, 16); 6424 m = Bits32 (opcode, 3, 0); 6425 6426 // index = TRUE; add = TRUE; wback = FALSE; 6427 index = true; 6428 add = true; 6429 wback = false; 6430 6431 // (shift_t, shift_n) = (SRType_LSL, UInt(imm2)); 6432 shift_t = SRType_LSL; 6433 shift_n = Bits32 (opcode, 5, 4); 6434 6435 // if t == 13 || BadReg(m) then UNPREDICTABLE; 6436 if ((t == 13) || BadReg (m)) 6437 return false; 6438 break; 6439 6440 case eEncodingA1: 6441 { 6442 // if P == '0' && W == '1' then SEE LDRBT; 6443 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm); 6444 t = Bits32 (opcode, 15, 12); 6445 n = Bits32 (opcode, 19, 16); 6446 m = Bits32 (opcode, 3, 0); 6447 6448 // index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1'); 6449 index = BitIsSet (opcode, 24); 6450 add = BitIsSet (opcode, 23); 6451 wback = (BitIsClear (opcode, 24) || BitIsSet (opcode, 21)); 6452 6453 // (shift_t, shift_n) = DecodeImmShift(type, imm5); 6454 uint32_t type = Bits32 (opcode, 6, 5); 6455 uint32_t imm5 = Bits32 (opcode, 11, 7); 6456 shift_n = DecodeImmShift (type, imm5, shift_t); 6457 6458 // if t == 15 || m == 15 then UNPREDICTABLE; 6459 if ((t == 15) || (m == 15)) 6460 return false; 6461 6462 // if wback && (n == 15 || n == t) then UNPREDICTABLE; 6463 if (wback && ((n == 15) || (n == t))) 6464 return false; 6465 } 6466 break; 6467 6468 default: 6469 return false; 6470 } 6471 6472 addr_t offset_addr; 6473 addr_t address; 6474 6475 // offset = Shift(R[m], shift_t, shift_n, APSR.C); 6476 uint32_t Rm = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success); 6477 if (!success) 6478 return false; 6479 6480 addr_t offset = Shift (Rm, shift_t, shift_n, APSR_C, &success); 6481 if (!success) 6482 return false; 6483 6484 // offset_addr = if add then (R[n] + offset) else (R[n] - offset); 6485 uint32_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success); 6486 if (!success) 6487 return false; 6488 6489 if (add) 6490 offset_addr = Rn + offset; 6491 else 6492 offset_addr = Rn - offset; 6493 6494 // address = if index then offset_addr else R[n]; 6495 if (index) 6496 address = offset_addr; 6497 else 6498 address = Rn; 6499 6500 // R[t] = ZeroExtend(MemU[address,1],32); 6501 RegisterInfo base_reg; 6502 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg); 6503 6504 EmulateInstruction::Context context; 6505 context.type = eContextRegisterLoad; 6506 context.SetRegisterPlusOffset (base_reg, address - Rn); 6507 6508 uint64_t data = MemURead (context, address, 1, 0, &success); 6509 if (!success) 6510 return false; 6511 6512 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data)) 6513 return false; 6514 6515 // if wback then R[n] = offset_addr; 6516 if (wback) 6517 { 6518 context.type = eContextAdjustBaseRegister; 6519 context.SetAddress (offset_addr); 6520 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr)) 6521 return false; 6522 } 6523 } 6524 return true; 6525} 6526 6527// LDRH (immediate, Thumb) calculates an address from a base register value and an immediate offset, loads a 6528// halfword from memory, zero-extends it to form a 32-bit word, and writes it to a register. It can use offset, 6529// post-indexed, or pre-indexed addressing. 6530bool 6531EmulateInstructionARM::EmulateLDRHImmediate (const uint32_t opcode, const ARMEncoding encoding) 6532{ 6533#if 0 6534 if ConditionPassed() then 6535 EncodingSpecificOperations(); NullCheckIfThumbEE(n); 6536 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32); 6537 address = if index then offset_addr else R[n]; 6538 data = MemU[address,2]; 6539 if wback then R[n] = offset_addr; 6540 if UnalignedSupport() || address<0> = '0' then 6541 R[t] = ZeroExtend(data, 32); 6542 else // Can only apply before ARMv7 6543 R[t] = bits(32) UNKNOWN; 6544#endif 6545 6546 6547 bool success = false; 6548 6549 if (ConditionPassed(opcode)) 6550 { 6551 uint32_t t; 6552 uint32_t n; 6553 uint32_t imm32; 6554 bool index; 6555 bool add; 6556 bool wback; 6557 6558 // EncodingSpecificOperations(); NullCheckIfThumbEE(n); 6559 switch (encoding) 6560 { 6561 case eEncodingT1: 6562 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm5:'0', 32); 6563 t = Bits32 (opcode, 2, 0); 6564 n = Bits32 (opcode, 5, 3); 6565 imm32 = Bits32 (opcode, 10, 6) << 1; 6566 6567 // index = TRUE; add = TRUE; wback = FALSE; 6568 index = true; 6569 add = true; 6570 wback = false; 6571 6572 break; 6573 6574 case eEncodingT2: 6575 // if Rt == '1111' then SEE "Unallocated memory hints"; 6576 // if Rn == '1111' then SEE LDRH (literal); 6577 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32); 6578 t = Bits32 (opcode, 15, 12); 6579 n = Bits32 (opcode, 19, 16); 6580 imm32 = Bits32 (opcode, 11, 0); 6581 6582 // index = TRUE; add = TRUE; wback = FALSE; 6583 index = true; 6584 add = true; 6585 wback = false; 6586 6587 // if t == 13 then UNPREDICTABLE; 6588 if (t == 13) 6589 return false; 6590 break; 6591 6592 case eEncodingT3: 6593 // if Rn == '1111' then SEE LDRH (literal); 6594 // if Rt == '1111' && P == '1' && U == '0' && W == '0' then SEE "Unallocated memory hints"; 6595 // if P == '1' && U == '1' && W == '0' then SEE LDRHT; 6596 // if P == '0' && W == '0' then UNDEFINED; 6597 if (BitIsClear (opcode, 10) && BitIsClear (opcode, 8)) 6598 return false; 6599 6600 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32); 6601 t = Bits32 (opcode, 15, 12); 6602 n = Bits32 (opcode, 19, 16); 6603 imm32 = Bits32 (opcode, 7, 0); 6604 6605 // index = (P == '1'); add = (U == '1'); wback = (W == '1'); 6606 index = BitIsSet (opcode, 10); 6607 add = BitIsSet (opcode, 9); 6608 wback = BitIsSet (opcode, 8); 6609 6610 // if BadReg(t) || (wback && n == t) then UNPREDICTABLE; 6611 if (BadReg (t) || (wback && (n == t))) 6612 return false; 6613 break; 6614 6615 default: 6616 return false; 6617 } 6618 6619 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32); 6620 uint32_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success); 6621 if (!success) 6622 return false; 6623 6624 addr_t offset_addr; 6625 addr_t address; 6626 6627 if (add) 6628 offset_addr = Rn + imm32; 6629 else 6630 offset_addr = Rn - imm32; 6631 6632 // address = if index then offset_addr else R[n]; 6633 if (index) 6634 address = offset_addr; 6635 else 6636 address = Rn; 6637 6638 // data = MemU[address,2]; 6639 RegisterInfo base_reg; 6640 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg); 6641 6642 EmulateInstruction::Context context; 6643 context.type = eContextRegisterLoad; 6644 context.SetRegisterPlusOffset (base_reg, address - Rn); 6645 6646 uint64_t data = MemURead (context, address, 2, 0, &success); 6647 if (!success) 6648 return false; 6649 6650 // if wback then R[n] = offset_addr; 6651 if (wback) 6652 { 6653 context.type = eContextAdjustBaseRegister; 6654 context.SetAddress (offset_addr); 6655 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr)) 6656 return false; 6657 } 6658 6659 // if UnalignedSupport() || address<0> = '0' then 6660 if (UnalignedSupport () || BitIsClear (address, 0)) 6661 { 6662 // R[t] = ZeroExtend(data, 32); 6663 context.type = eContextRegisterLoad; 6664 context.SetRegisterPlusOffset (base_reg, address - Rn); 6665 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data)) 6666 return false; 6667 } 6668 else // Can only apply before ARMv7 6669 { 6670 // R[t] = bits(32) UNKNOWN; 6671 WriteBits32Unknown (t); 6672 } 6673 } 6674 return true; 6675} 6676 6677// LDRH (literal) caculates an address from the PC value and an immediate offset, loads a halfword from memory, 6678// zero-extends it to form a 32-bit word, and writes it to a register. 6679bool 6680EmulateInstructionARM::EmulateLDRHLiteral (const uint32_t opcode, const ARMEncoding encoding) 6681{ 6682#if 0 6683 if ConditionPassed() then 6684 EncodingSpecificOperations(); NullCheckIfThumbEE(15); 6685 base = Align(PC,4); 6686 address = if add then (base + imm32) else (base - imm32); 6687 data = MemU[address,2]; 6688 if UnalignedSupport() || address<0> = '0' then 6689 R[t] = ZeroExtend(data, 32); 6690 else // Can only apply before ARMv7 6691 R[t] = bits(32) UNKNOWN; 6692#endif 6693 6694 bool success = false; 6695 6696 if (ConditionPassed(opcode)) 6697 { 6698 uint32_t t; 6699 uint32_t imm32; 6700 bool add; 6701 6702 // EncodingSpecificOperations(); NullCheckIfThumbEE(15); 6703 switch (encoding) 6704 { 6705 case eEncodingT1: 6706 // if Rt == '1111' then SEE "Unallocated memory hints"; 6707 // t = UInt(Rt); imm32 = ZeroExtend(imm12, 32); add = (U == '1'); 6708 t = Bits32 (opcode, 15, 12); 6709 imm32 = Bits32 (opcode, 11, 0); 6710 add = BitIsSet (opcode, 23); 6711 6712 // if t == 13 then UNPREDICTABLE; 6713 if (t == 13) 6714 return false; 6715 6716 break; 6717 6718 case eEncodingA1: 6719 { 6720 uint32_t imm4H = Bits32 (opcode, 11, 8); 6721 uint32_t imm4L = Bits32 (opcode, 3, 0); 6722 6723 // t == UInt(Rt); imm32 = ZeroExtend(imm4H:imm4L, 32); add = (U == '1'); 6724 t = Bits32 (opcode, 15, 12); 6725 imm32 = (imm4H << 4) | imm4L; 6726 add = BitIsSet (opcode, 23); 6727 6728 // if t == 15 then UNPREDICTABLE; 6729 if (t == 15) 6730 return false; 6731 break; 6732 } 6733 6734 default: 6735 return false; 6736 } 6737 6738 // base = Align(PC,4); 6739 uint64_t pc_value = ReadCoreReg (PC_REG, &success); 6740 if (!success) 6741 return false; 6742 6743 addr_t base = AlignPC (pc_value); 6744 addr_t address; 6745 6746 // address = if add then (base + imm32) else (base - imm32); 6747 if (add) 6748 address = base + imm32; 6749 else 6750 address = base - imm32; 6751 6752 // data = MemU[address,2]; 6753 RegisterInfo base_reg; 6754 GetRegisterInfo (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, base_reg); 6755 6756 EmulateInstruction::Context context; 6757 context.type = eContextRegisterLoad; 6758 context.SetRegisterPlusOffset (base_reg, address - base); 6759 6760 uint64_t data = MemURead (context, address, 2, 0, &success); 6761 if (!success) 6762 return false; 6763 6764 6765 // if UnalignedSupport() || address<0> = '0' then 6766 if (UnalignedSupport () || BitIsClear (address, 0)) 6767 { 6768 // R[t] = ZeroExtend(data, 32); 6769 context.type = eContextRegisterLoad; 6770 context.SetRegisterPlusOffset (base_reg, address - base); 6771 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data)) 6772 return false; 6773 6774 } 6775 else // Can only apply before ARMv7 6776 { 6777 // R[t] = bits(32) UNKNOWN; 6778 WriteBits32Unknown (t); 6779 } 6780 } 6781 return true; 6782} 6783 6784// LDRH (literal) calculates an address from a base register value and an offset register value, loads a halfword 6785// from memory, zero-extends it to form a 32-bit word, and writes it to a register. The offset register value can 6786// be shifted left by 0, 1, 2, or 3 bits. 6787bool 6788EmulateInstructionARM::EmulateLDRHRegister (const uint32_t opcode, const ARMEncoding encoding) 6789{ 6790#if 0 6791 if ConditionPassed() then 6792 EncodingSpecificOperations(); NullCheckIfThumbEE(n); 6793 offset = Shift(R[m], shift_t, shift_n, APSR.C); 6794 offset_addr = if add then (R[n] + offset) else (R[n] - offset); 6795 address = if index then offset_addr else R[n]; 6796 data = MemU[address,2]; 6797 if wback then R[n] = offset_addr; 6798 if UnalignedSupport() || address<0> = '0' then 6799 R[t] = ZeroExtend(data, 32); 6800 else // Can only apply before ARMv7 6801 R[t] = bits(32) UNKNOWN; 6802#endif 6803 6804 bool success = false; 6805 6806 if (ConditionPassed(opcode)) 6807 { 6808 uint32_t t; 6809 uint32_t n; 6810 uint32_t m; 6811 bool index; 6812 bool add; 6813 bool wback; 6814 ARM_ShifterType shift_t; 6815 uint32_t shift_n; 6816 6817 // EncodingSpecificOperations(); NullCheckIfThumbEE(n); 6818 switch (encoding) 6819 { 6820 case eEncodingT1: 6821 // if CurrentInstrSet() == InstrSet_ThumbEE then SEE "Modified operation in ThumbEE"; 6822 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm); 6823 t = Bits32 (opcode, 2, 0); 6824 n = Bits32 (opcode, 5, 3); 6825 m = Bits32 (opcode, 8, 6); 6826 6827 // index = TRUE; add = TRUE; wback = FALSE; 6828 index = true; 6829 add = true; 6830 wback = false; 6831 6832 // (shift_t, shift_n) = (SRType_LSL, 0); 6833 shift_t = SRType_LSL; 6834 shift_n = 0; 6835 6836 break; 6837 6838 case eEncodingT2: 6839 // if Rn == '1111' then SEE LDRH (literal); 6840 // if Rt == '1111' then SEE "Unallocated memory hints"; 6841 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm); 6842 t = Bits32 (opcode, 15, 12); 6843 n = Bits32 (opcode, 19, 16); 6844 m = Bits32 (opcode, 3, 0); 6845 6846 // index = TRUE; add = TRUE; wback = FALSE; 6847 index = true; 6848 add = true; 6849 wback = false; 6850 6851 // (shift_t, shift_n) = (SRType_LSL, UInt(imm2)); 6852 shift_t = SRType_LSL; 6853 shift_n = Bits32 (opcode, 5, 4); 6854 6855 // if t == 13 || BadReg(m) then UNPREDICTABLE; 6856 if ((t == 13) || BadReg (m)) 6857 return false; 6858 break; 6859 6860 case eEncodingA1: 6861 // if P == '0' && W == '1' then SEE LDRHT; 6862 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm); 6863 t = Bits32 (opcode, 15, 12); 6864 n = Bits32 (opcode, 19, 16); 6865 m = Bits32 (opcode, 3, 0); 6866 6867 // index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1'); 6868 index = BitIsSet (opcode, 24); 6869 add = BitIsSet (opcode, 23); 6870 wback = (BitIsClear (opcode, 24) || BitIsSet (opcode, 21)); 6871 6872 // (shift_t, shift_n) = (SRType_LSL, 0); 6873 shift_t = SRType_LSL; 6874 shift_n = 0; 6875 6876 // if t == 15 || m == 15 then UNPREDICTABLE; 6877 if ((t == 15) || (m == 15)) 6878 return false; 6879 6880 // if wback && (n == 15 || n == t) then UNPREDICTABLE; 6881 if (wback && ((n == 15) || (n == t))) 6882 return false; 6883 6884 break; 6885 6886 default: 6887 return false; 6888 } 6889 6890 // offset = Shift(R[m], shift_t, shift_n, APSR.C); 6891 6892 uint64_t Rm = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success); 6893 if (!success) 6894 return false; 6895 6896 addr_t offset = Shift (Rm, shift_t, shift_n, APSR_C, &success); 6897 if (!success) 6898 return false; 6899 6900 addr_t offset_addr; 6901 addr_t address; 6902 6903 // offset_addr = if add then (R[n] + offset) else (R[n] - offset); 6904 uint64_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success); 6905 if (!success) 6906 return false; 6907 6908 if (add) 6909 offset_addr = Rn + offset; 6910 else 6911 offset_addr = Rn - offset; 6912 6913 // address = if index then offset_addr else R[n]; 6914 if (index) 6915 address = offset_addr; 6916 else 6917 address = Rn; 6918 6919 // data = MemU[address,2]; 6920 RegisterInfo base_reg; 6921 RegisterInfo offset_reg; 6922 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg); 6923 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + m, offset_reg); 6924 6925 EmulateInstruction::Context context; 6926 context.type = eContextRegisterLoad; 6927 context.SetRegisterPlusIndirectOffset (base_reg, offset_reg); 6928 uint64_t data = MemURead (context, address, 2, 0, &success); 6929 if (!success) 6930 return false; 6931 6932 // if wback then R[n] = offset_addr; 6933 if (wback) 6934 { 6935 context.type = eContextAdjustBaseRegister; 6936 context.SetAddress (offset_addr); 6937 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr)) 6938 return false; 6939 } 6940 6941 // if UnalignedSupport() || address<0> = '0' then 6942 if (UnalignedSupport() || BitIsClear (address, 0)) 6943 { 6944 // R[t] = ZeroExtend(data, 32); 6945 context.type = eContextRegisterLoad; 6946 context.SetRegisterPlusIndirectOffset (base_reg, offset_reg); 6947 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data)) 6948 return false; 6949 } 6950 else // Can only apply before ARMv7 6951 { 6952 // R[t] = bits(32) UNKNOWN; 6953 WriteBits32Unknown (t); 6954 } 6955 } 6956 return true; 6957} 6958 6959// LDRSB (immediate) calculates an address from a base register value and an immediate offset, loads a byte from 6960// memory, sign-extends it to form a 32-bit word, and writes it to a register. It can use offset, post-indexed, 6961// or pre-indexed addressing. 6962bool 6963EmulateInstructionARM::EmulateLDRSBImmediate (const uint32_t opcode, const ARMEncoding encoding) 6964{ 6965#if 0 6966 if ConditionPassed() then 6967 EncodingSpecificOperations(); NullCheckIfThumbEE(n); 6968 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32); 6969 address = if index then offset_addr else R[n]; 6970 R[t] = SignExtend(MemU[address,1], 32); 6971 if wback then R[n] = offset_addr; 6972#endif 6973 6974 bool success = false; 6975 6976 if (ConditionPassed(opcode)) 6977 { 6978 uint32_t t; 6979 uint32_t n; 6980 uint32_t imm32; 6981 bool index; 6982 bool add; 6983 bool wback; 6984 6985 // EncodingSpecificOperations(); NullCheckIfThumbEE(n); 6986 switch (encoding) 6987 { 6988 case eEncodingT1: 6989 // if Rt == '1111' then SEE PLI; 6990 // if Rn == '1111' then SEE LDRSB (literal); 6991 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32); 6992 t = Bits32 (opcode, 15, 12); 6993 n = Bits32 (opcode, 19, 16); 6994 imm32 = Bits32 (opcode, 11, 0); 6995 6996 // index = TRUE; add = TRUE; wback = FALSE; 6997 index = true; 6998 add = true; 6999 wback = false; 7000 7001 // if t == 13 then UNPREDICTABLE; 7002 if (t == 13) 7003 return false; 7004 7005 break; 7006 7007 case eEncodingT2: 7008 // if Rt == '1111' && P == '1' && U == '0' && W == '0' then SEE PLI; 7009 // if Rn == '1111' then SEE LDRSB (literal); 7010 // if P == '1' && U == '1' && W == '0' then SEE LDRSBT; 7011 // if P == '0' && W == '0' then UNDEFINED; 7012 if (BitIsClear (opcode, 10) && BitIsClear (opcode, 8)) 7013 return false; 7014 7015 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32); 7016 t = Bits32 (opcode, 15, 12); 7017 n = Bits32 (opcode, 19, 16); 7018 imm32 = Bits32 (opcode, 7, 0); 7019 7020 // index = (P == '1'); add = (U == '1'); wback = (W == '1'); 7021 index = BitIsSet (opcode, 10); 7022 add = BitIsSet (opcode, 9); 7023 wback = BitIsSet (opcode, 8); 7024 7025 // if BadReg(t) || (wback && n == t) then UNPREDICTABLE; 7026 if (((t == 13) || ((t == 15) 7027 && (BitIsClear (opcode, 10) || BitIsSet (opcode, 9) || BitIsSet (opcode, 8)))) 7028 || (wback && (n == t))) 7029 return false; 7030 7031 break; 7032 7033 case eEncodingA1: 7034 { 7035 // if Rn == '1111' then SEE LDRSB (literal); 7036 // if P == '0' && W == '1' then SEE LDRSBT; 7037 // t == UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm4H:imm4L, 32); 7038 t = Bits32 (opcode, 15, 12); 7039 n = Bits32 (opcode, 19, 16); 7040 7041 uint32_t imm4H = Bits32 (opcode, 11, 8); 7042 uint32_t imm4L = Bits32 (opcode, 3, 0); 7043 imm32 = (imm4H << 4) | imm4L; 7044 7045 // index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1'); 7046 index = BitIsSet (opcode, 24); 7047 add = BitIsSet (opcode, 23); 7048 wback = (BitIsClear (opcode, 24) || BitIsSet (opcode, 21)); 7049 7050 // if t == 15 || (wback && n == t) then UNPREDICTABLE; 7051 if ((t == 15) || (wback && (n == t))) 7052 return false; 7053 7054 break; 7055 } 7056 7057 default: 7058 return false; 7059 } 7060 7061 uint64_t Rn = ReadCoreReg (n, &success); 7062 if (!success) 7063 return false; 7064 7065 addr_t offset_addr; 7066 addr_t address; 7067 7068 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32); 7069 if (add) 7070 offset_addr = Rn + imm32; 7071 else 7072 offset_addr = Rn - imm32; 7073 7074 // address = if index then offset_addr else R[n]; 7075 if (index) 7076 address = offset_addr; 7077 else 7078 address = Rn; 7079 7080 // R[t] = SignExtend(MemU[address,1], 32); 7081 RegisterInfo base_reg; 7082 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg); 7083 7084 EmulateInstruction::Context context; 7085 context.type = eContextRegisterLoad; 7086 context.SetRegisterPlusOffset (base_reg, address - Rn); 7087 7088 uint64_t unsigned_data = MemURead (context, address, 1, 0, &success); 7089 if (!success) 7090 return false; 7091 7092 int64_t signed_data = llvm::SignExtend64<8>(unsigned_data); 7093 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, (uint64_t) signed_data)) 7094 return false; 7095 7096 // if wback then R[n] = offset_addr; 7097 if (wback) 7098 { 7099 context.type = eContextAdjustBaseRegister; 7100 context.SetAddress (offset_addr); 7101 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr)) 7102 return false; 7103 } 7104 } 7105 7106 return true; 7107} 7108 7109// LDRSB (literal) calculates an address from the PC value and an immediate offset, loads a byte from memory, 7110// sign-extends it to form a 32-bit word, and writes tit to a register. 7111bool 7112EmulateInstructionARM::EmulateLDRSBLiteral (const uint32_t opcode, const ARMEncoding encoding) 7113{ 7114#if 0 7115 if ConditionPassed() then 7116 EncodingSpecificOperations(); NullCheckIfThumbEE(15); 7117 base = Align(PC,4); 7118 address = if add then (base + imm32) else (base - imm32); 7119 R[t] = SignExtend(MemU[address,1], 32); 7120#endif 7121 7122 bool success = false; 7123 7124 if (ConditionPassed(opcode)) 7125 { 7126 uint32_t t; 7127 uint32_t imm32; 7128 bool add; 7129 7130 // EncodingSpecificOperations(); NullCheckIfThumbEE(15); 7131 switch (encoding) 7132 { 7133 case eEncodingT1: 7134 // if Rt == '1111' then SEE PLI; 7135 // t = UInt(Rt); imm32 = ZeroExtend(imm12, 32); add = (U == '1'); 7136 t = Bits32 (opcode, 15, 12); 7137 imm32 = Bits32 (opcode, 11, 0); 7138 add = BitIsSet (opcode, 23); 7139 7140 // if t == 13 then UNPREDICTABLE; 7141 if (t == 13) 7142 return false; 7143 7144 break; 7145 7146 case eEncodingA1: 7147 { 7148 // t == UInt(Rt); imm32 = ZeroExtend(imm4H:imm4L, 32); add = (U == '1'); 7149 t = Bits32 (opcode, 15, 12); 7150 uint32_t imm4H = Bits32 (opcode, 11, 8); 7151 uint32_t imm4L = Bits32 (opcode, 3, 0); 7152 imm32 = (imm4H << 4) | imm4L; 7153 add = BitIsSet (opcode, 23); 7154 7155 // if t == 15 then UNPREDICTABLE; 7156 if (t == 15) 7157 return false; 7158 7159 break; 7160 } 7161 7162 default: 7163 return false; 7164 } 7165 7166 // base = Align(PC,4); 7167 uint64_t pc_value = ReadCoreReg (PC_REG, &success); 7168 if (!success) 7169 return false; 7170 uint64_t base = AlignPC (pc_value); 7171 7172 // address = if add then (base + imm32) else (base - imm32); 7173 addr_t address; 7174 if (add) 7175 address = base + imm32; 7176 else 7177 address = base - imm32; 7178 7179 // R[t] = SignExtend(MemU[address,1], 32); 7180 RegisterInfo base_reg; 7181 GetRegisterInfo (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, base_reg); 7182 7183 EmulateInstruction::Context context; 7184 context.type = eContextRegisterLoad; 7185 context.SetRegisterPlusOffset (base_reg, address - base); 7186 7187 uint64_t unsigned_data = MemURead (context, address, 1, 0, &success); 7188 if (!success) 7189 return false; 7190 7191 int64_t signed_data = llvm::SignExtend64<8>(unsigned_data); 7192 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, (uint64_t) signed_data)) 7193 return false; 7194 } 7195 return true; 7196} 7197 7198// LDRSB (register) calculates an address from a base register value and an offset register value, loadsa byte from 7199// memory, sign-extends it to form a 32-bit word, and writes it to a register. The offset register value can be 7200// shifted left by 0, 1, 2, or 3 bits. 7201bool 7202EmulateInstructionARM::EmulateLDRSBRegister (const uint32_t opcode, const ARMEncoding encoding) 7203{ 7204#if 0 7205 if ConditionPassed() then 7206 EncodingSpecificOperations(); NullCheckIfThumbEE(n); 7207 offset = Shift(R[m], shift_t, shift_n, APSR.C); 7208 offset_addr = if add then (R[n] + offset) else (R[n] - offset); 7209 address = if index then offset_addr else R[n]; 7210 R[t] = SignExtend(MemU[address,1], 32); 7211 if wback then R[n] = offset_addr; 7212#endif 7213 7214 bool success = false; 7215 7216 if (ConditionPassed(opcode)) 7217 { 7218 uint32_t t; 7219 uint32_t n; 7220 uint32_t m; 7221 bool index; 7222 bool add; 7223 bool wback; 7224 ARM_ShifterType shift_t; 7225 uint32_t shift_n; 7226 7227 // EncodingSpecificOperations(); NullCheckIfThumbEE(n); 7228 switch (encoding) 7229 { 7230 case eEncodingT1: 7231 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm); 7232 t = Bits32 (opcode, 2, 0); 7233 n = Bits32 (opcode, 5, 3); 7234 m = Bits32 (opcode, 8, 6); 7235 7236 // index = TRUE; add = TRUE; wback = FALSE; 7237 index = true; 7238 add = true; 7239 wback = false; 7240 7241 // (shift_t, shift_n) = (SRType_LSL, 0); 7242 shift_t = SRType_LSL; 7243 shift_n = 0; 7244 7245 break; 7246 7247 case eEncodingT2: 7248 // if Rt == '1111' then SEE PLI; 7249 // if Rn == '1111' then SEE LDRSB (literal); 7250 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm); 7251 t = Bits32 (opcode, 15, 12); 7252 n = Bits32 (opcode, 19, 16); 7253 m = Bits32 (opcode, 3, 0); 7254 7255 // index = TRUE; add = TRUE; wback = FALSE; 7256 index = true; 7257 add = true; 7258 wback = false; 7259 7260 // (shift_t, shift_n) = (SRType_LSL, UInt(imm2)); 7261 shift_t = SRType_LSL; 7262 shift_n = Bits32 (opcode, 5, 4); 7263 7264 // if t == 13 || BadReg(m) then UNPREDICTABLE; 7265 if ((t == 13) || BadReg (m)) 7266 return false; 7267 break; 7268 7269 case eEncodingA1: 7270 // if P == '0' && W == '1' then SEE LDRSBT; 7271 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm); 7272 t = Bits32 (opcode, 15, 12); 7273 n = Bits32 (opcode, 19, 16); 7274 m = Bits32 (opcode, 3, 0); 7275 7276 // index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1'); 7277 index = BitIsSet (opcode, 24); 7278 add = BitIsSet (opcode, 23); 7279 wback = BitIsClear (opcode, 24) || BitIsSet (opcode, 21); 7280 7281 // (shift_t, shift_n) = (SRType_LSL, 0); 7282 shift_t = SRType_LSL; 7283 shift_n = 0; 7284 7285 // if t == 15 || m == 15 then UNPREDICTABLE; 7286 if ((t == 15) || (m == 15)) 7287 return false; 7288 7289 // if wback && (n == 15 || n == t) then UNPREDICTABLE; 7290 if (wback && ((n == 15) || (n == t))) 7291 return false; 7292 break; 7293 7294 default: 7295 return false; 7296 } 7297 7298 uint64_t Rm = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success); 7299 if (!success) 7300 return false; 7301 7302 // offset = Shift(R[m], shift_t, shift_n, APSR.C); 7303 addr_t offset = Shift (Rm, shift_t, shift_n, APSR_C, &success); 7304 if (!success) 7305 return false; 7306 7307 addr_t offset_addr; 7308 addr_t address; 7309 7310 // offset_addr = if add then (R[n] + offset) else (R[n] - offset); 7311 uint64_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success); 7312 if (!success) 7313 return false; 7314 7315 if (add) 7316 offset_addr = Rn + offset; 7317 else 7318 offset_addr = Rn - offset; 7319 7320 // address = if index then offset_addr else R[n]; 7321 if (index) 7322 address = offset_addr; 7323 else 7324 address = Rn; 7325 7326 // R[t] = SignExtend(MemU[address,1], 32); 7327 RegisterInfo base_reg; 7328 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg); 7329 RegisterInfo offset_reg; 7330 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + m, offset_reg); 7331 7332 EmulateInstruction::Context context; 7333 context.type = eContextRegisterLoad; 7334 context.SetRegisterPlusIndirectOffset (base_reg, offset_reg); 7335 7336 uint64_t unsigned_data = MemURead (context, address, 1, 0, &success); 7337 if (!success) 7338 return false; 7339 7340 int64_t signed_data = llvm::SignExtend64<8>(unsigned_data); 7341 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, (uint64_t) signed_data)) 7342 return false; 7343 7344 // if wback then R[n] = offset_addr; 7345 if (wback) 7346 { 7347 context.type = eContextAdjustBaseRegister; 7348 context.SetAddress (offset_addr); 7349 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr)) 7350 return false; 7351 } 7352 } 7353 return true; 7354} 7355 7356// LDRSH (immediate) calculates an address from a base register value and an immediate offset, loads a halfword from 7357// memory, sign-extends it to form a 32-bit word, and writes it to a register. It can use offset, post-indexed, or 7358// pre-indexed addressing. 7359bool 7360EmulateInstructionARM::EmulateLDRSHImmediate (const uint32_t opcode, const ARMEncoding encoding) 7361{ 7362#if 0 7363 if ConditionPassed() then 7364 EncodingSpecificOperations(); NullCheckIfThumbEE(n); 7365 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32); 7366 address = if index then offset_addr else R[n]; 7367 data = MemU[address,2]; 7368 if wback then R[n] = offset_addr; 7369 if UnalignedSupport() || address<0> = '0' then 7370 R[t] = SignExtend(data, 32); 7371 else // Can only apply before ARMv7 7372 R[t] = bits(32) UNKNOWN; 7373#endif 7374 7375 bool success = false; 7376 7377 if (ConditionPassed(opcode)) 7378 { 7379 uint32_t t; 7380 uint32_t n; 7381 uint32_t imm32; 7382 bool index; 7383 bool add; 7384 bool wback; 7385 7386 // EncodingSpecificOperations(); NullCheckIfThumbEE(n); 7387 switch (encoding) 7388 { 7389 case eEncodingT1: 7390 // if Rn == '1111' then SEE LDRSH (literal); 7391 // if Rt == '1111' then SEE "Unallocated memory hints"; 7392 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32); 7393 t = Bits32 (opcode, 15, 12); 7394 n = Bits32 (opcode, 19, 16); 7395 imm32 = Bits32 (opcode, 11, 0); 7396 7397 // index = TRUE; add = TRUE; wback = FALSE; 7398 index = true; 7399 add = true; 7400 wback = false; 7401 7402 // if t == 13 then UNPREDICTABLE; 7403 if (t == 13) 7404 return false; 7405 7406 break; 7407 7408 case eEncodingT2: 7409 // if Rn == '1111' then SEE LDRSH (literal); 7410 // if Rt == '1111' && P == '1' && U == '0' && W == '0' then SEE "Unallocated memory hints"; 7411 // if P == '1' && U == '1' && W == '0' then SEE LDRSHT; 7412 // if P == '0' && W == '0' then UNDEFINED; 7413 if (BitIsClear (opcode, 10) && BitIsClear (opcode, 8)) 7414 return false; 7415 7416 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32); 7417 t = Bits32 (opcode, 15, 12); 7418 n = Bits32 (opcode, 19, 16); 7419 imm32 = Bits32 (opcode, 7, 0); 7420 7421 // index = (P == '1'); add = (U == '1'); wback = (W == '1'); 7422 index = BitIsSet (opcode, 10); 7423 add = BitIsSet (opcode, 9); 7424 wback = BitIsSet (opcode, 8); 7425 7426 // if BadReg(t) || (wback && n == t) then UNPREDICTABLE; 7427 if (BadReg (t) || (wback && (n == t))) 7428 return false; 7429 7430 break; 7431 7432 case eEncodingA1: 7433 { 7434 // if Rn == '1111' then SEE LDRSH (literal); 7435 // if P == '0' && W == '1' then SEE LDRSHT; 7436 // t == UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm4H:imm4L, 32); 7437 t = Bits32 (opcode, 15, 12); 7438 n = Bits32 (opcode, 19, 16); 7439 uint32_t imm4H = Bits32 (opcode, 11,8); 7440 uint32_t imm4L = Bits32 (opcode, 3, 0); 7441 imm32 = (imm4H << 4) | imm4L; 7442 7443 // index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1'); 7444 index = BitIsSet (opcode, 24); 7445 add = BitIsSet (opcode, 23); 7446 wback = BitIsClear (opcode, 24) || BitIsSet (opcode, 21); 7447 7448 // if t == 15 || (wback && n == t) then UNPREDICTABLE; 7449 if ((t == 15) || (wback && (n == t))) 7450 return false; 7451 7452 break; 7453 } 7454 7455 default: 7456 return false; 7457 } 7458 7459 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32); 7460 uint64_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success); 7461 if (!success) 7462 return false; 7463 7464 addr_t offset_addr; 7465 if (add) 7466 offset_addr = Rn + imm32; 7467 else 7468 offset_addr = Rn - imm32; 7469 7470 // address = if index then offset_addr else R[n]; 7471 addr_t address; 7472 if (index) 7473 address = offset_addr; 7474 else 7475 address = Rn; 7476 7477 // data = MemU[address,2]; 7478 RegisterInfo base_reg; 7479 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg); 7480 7481 EmulateInstruction::Context context; 7482 context.type = eContextRegisterLoad; 7483 context.SetRegisterPlusOffset (base_reg, address - Rn); 7484 7485 uint64_t data = MemURead (context, address, 2, 0, &success); 7486 if (!success) 7487 return false; 7488 7489 // if wback then R[n] = offset_addr; 7490 if (wback) 7491 { 7492 context.type = eContextAdjustBaseRegister; 7493 context.SetAddress (offset_addr); 7494 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr)) 7495 return false; 7496 } 7497 7498 // if UnalignedSupport() || address<0> = '0' then 7499 if (UnalignedSupport() || BitIsClear (address, 0)) 7500 { 7501 // R[t] = SignExtend(data, 32); 7502 int64_t signed_data = llvm::SignExtend64<16>(data); 7503 context.type = eContextRegisterLoad; 7504 context.SetRegisterPlusOffset (base_reg, address - Rn); 7505 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, (uint64_t) signed_data)) 7506 return false; 7507 } 7508 else // Can only apply before ARMv7 7509 { 7510 // R[t] = bits(32) UNKNOWN; 7511 WriteBits32Unknown (t); 7512 } 7513 } 7514 return true; 7515} 7516 7517// LDRSH (literal) calculates an address from the PC value and an immediate offset, loads a halfword from memory, 7518// sign-extends it to from a 32-bit word, and writes it to a register. 7519bool 7520EmulateInstructionARM::EmulateLDRSHLiteral (const uint32_t opcode, const ARMEncoding encoding) 7521{ 7522#if 0 7523 if ConditionPassed() then 7524 EncodingSpecificOperations(); NullCheckIfThumbEE(15); 7525 base = Align(PC,4); 7526 address = if add then (base + imm32) else (base - imm32); 7527 data = MemU[address,2]; 7528 if UnalignedSupport() || address<0> = '0' then 7529 R[t] = SignExtend(data, 32); 7530 else // Can only apply before ARMv7 7531 R[t] = bits(32) UNKNOWN; 7532#endif 7533 7534 bool success = false; 7535 7536 if (ConditionPassed(opcode)) 7537 { 7538 uint32_t t; 7539 uint32_t imm32; 7540 bool add; 7541 7542 // EncodingSpecificOperations(); NullCheckIfThumbEE(15); 7543 switch (encoding) 7544 { 7545 case eEncodingT1: 7546 // if Rt == '1111' then SEE "Unallocated memory hints"; 7547 // t = UInt(Rt); imm32 = ZeroExtend(imm12, 32); add = (U == '1'); 7548 t = Bits32 (opcode, 15, 12); 7549 imm32 = Bits32 (opcode, 11, 0); 7550 add = BitIsSet (opcode, 23); 7551 7552 // if t == 13 then UNPREDICTABLE; 7553 if (t == 13) 7554 return false; 7555 7556 break; 7557 7558 case eEncodingA1: 7559 { 7560 // t == UInt(Rt); imm32 = ZeroExtend(imm4H:imm4L, 32); add = (U == '1'); 7561 t = Bits32 (opcode, 15, 12); 7562 uint32_t imm4H = Bits32 (opcode, 11, 8); 7563 uint32_t imm4L = Bits32 (opcode, 3, 0); 7564 imm32 = (imm4H << 4) | imm4L; 7565 add = BitIsSet (opcode, 23); 7566 7567 // if t == 15 then UNPREDICTABLE; 7568 if (t == 15) 7569 return false; 7570 7571 break; 7572 } 7573 default: 7574 return false; 7575 } 7576 7577 // base = Align(PC,4); 7578 uint64_t pc_value = ReadCoreReg (PC_REG, &success); 7579 if (!success) 7580 return false; 7581 7582 uint64_t base = AlignPC (pc_value); 7583 7584 addr_t address; 7585 // address = if add then (base + imm32) else (base - imm32); 7586 if (add) 7587 address = base + imm32; 7588 else 7589 address = base - imm32; 7590 7591 // data = MemU[address,2]; 7592 RegisterInfo base_reg; 7593 GetRegisterInfo (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, base_reg); 7594 7595 EmulateInstruction::Context context; 7596 context.type = eContextRegisterLoad; 7597 context.SetRegisterPlusOffset (base_reg, imm32); 7598 7599 uint64_t data = MemURead (context, address, 2, 0, &success); 7600 if (!success) 7601 return false; 7602 7603 // if UnalignedSupport() || address<0> = '0' then 7604 if (UnalignedSupport() || BitIsClear (address, 0)) 7605 { 7606 // R[t] = SignExtend(data, 32); 7607 int64_t signed_data = llvm::SignExtend64<16>(data); 7608 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, (uint64_t) signed_data)) 7609 return false; 7610 } 7611 else // Can only apply before ARMv7 7612 { 7613 // R[t] = bits(32) UNKNOWN; 7614 WriteBits32Unknown (t); 7615 } 7616 } 7617 return true; 7618} 7619 7620// LDRSH (register) calculates an address from a base register value and an offset register value, loads a halfword 7621// from memory, sign-extends it to form a 32-bit word, and writes it to a register. The offset register value can be 7622// shifted left by 0, 1, 2, or 3 bits. 7623bool 7624EmulateInstructionARM::EmulateLDRSHRegister (const uint32_t opcode, const ARMEncoding encoding) 7625{ 7626#if 0 7627 if ConditionPassed() then 7628 EncodingSpecificOperations(); NullCheckIfThumbEE(n); 7629 offset = Shift(R[m], shift_t, shift_n, APSR.C); 7630 offset_addr = if add then (R[n] + offset) else (R[n] - offset); 7631 address = if index then offset_addr else R[n]; 7632 data = MemU[address,2]; 7633 if wback then R[n] = offset_addr; 7634 if UnalignedSupport() || address<0> = '0' then 7635 R[t] = SignExtend(data, 32); 7636 else // Can only apply before ARMv7 7637 R[t] = bits(32) UNKNOWN; 7638#endif 7639 7640 bool success = false; 7641 7642 if (ConditionPassed(opcode)) 7643 { 7644 uint32_t t; 7645 uint32_t n; 7646 uint32_t m; 7647 bool index; 7648 bool add; 7649 bool wback; 7650 ARM_ShifterType shift_t; 7651 uint32_t shift_n; 7652 7653 // EncodingSpecificOperations(); NullCheckIfThumbEE(n); 7654 switch (encoding) 7655 { 7656 case eEncodingT1: 7657 // if CurrentInstrSet() == InstrSet_ThumbEE then SEE "Modified operation in ThumbEE"; 7658 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm); 7659 t = Bits32 (opcode, 2, 0); 7660 n = Bits32 (opcode, 5, 3); 7661 m = Bits32 (opcode, 8, 6); 7662 7663 // index = TRUE; add = TRUE; wback = FALSE; 7664 index = true; 7665 add = true; 7666 wback = false; 7667 7668 // (shift_t, shift_n) = (SRType_LSL, 0); 7669 shift_t = SRType_LSL; 7670 shift_n = 0; 7671 7672 break; 7673 7674 case eEncodingT2: 7675 // if Rn == '1111' then SEE LDRSH (literal); 7676 // if Rt == '1111' then SEE "Unallocated memory hints"; 7677 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm); 7678 t = Bits32 (opcode, 15, 12); 7679 n = Bits32 (opcode, 19, 16); 7680 m = Bits32 (opcode, 3, 0); 7681 7682 // index = TRUE; add = TRUE; wback = FALSE; 7683 index = true; 7684 add = true; 7685 wback = false; 7686 7687 // (shift_t, shift_n) = (SRType_LSL, UInt(imm2)); 7688 shift_t = SRType_LSL; 7689 shift_n = Bits32 (opcode, 5, 4); 7690 7691 // if t == 13 || BadReg(m) then UNPREDICTABLE; 7692 if ((t == 13) || BadReg (m)) 7693 return false; 7694 7695 break; 7696 7697 case eEncodingA1: 7698 // if P == '0' && W == '1' then SEE LDRSHT; 7699 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm); 7700 t = Bits32 (opcode, 15, 12); 7701 n = Bits32 (opcode, 19, 16); 7702 m = Bits32 (opcode, 3, 0); 7703 7704 // index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1'); 7705 index = BitIsSet (opcode, 24); 7706 add = BitIsSet (opcode, 23); 7707 wback = BitIsClear (opcode, 24) || BitIsSet (opcode, 21); 7708 7709 // (shift_t, shift_n) = (SRType_LSL, 0); 7710 shift_t = SRType_LSL; 7711 shift_n = 0; 7712 7713 // if t == 15 || m == 15 then UNPREDICTABLE; 7714 if ((t == 15) || (m == 15)) 7715 return false; 7716 7717 // if wback && (n == 15 || n == t) then UNPREDICTABLE; 7718 if (wback && ((n == 15) || (n == t))) 7719 return false; 7720 7721 break; 7722 7723 default: 7724 return false; 7725 } 7726 7727 uint64_t Rm = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success); 7728 if (!success) 7729 return false; 7730 7731 uint64_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success); 7732 if (!success) 7733 return false; 7734 7735 // offset = Shift(R[m], shift_t, shift_n, APSR.C); 7736 addr_t offset = Shift (Rm, shift_t, shift_n, APSR_C, &success); 7737 if (!success) 7738 return false; 7739 7740 addr_t offset_addr; 7741 addr_t address; 7742 7743 // offset_addr = if add then (R[n] + offset) else (R[n] - offset); 7744 if (add) 7745 offset_addr = Rn + offset; 7746 else 7747 offset_addr = Rn - offset; 7748 7749 // address = if index then offset_addr else R[n]; 7750 if (index) 7751 address = offset_addr; 7752 else 7753 address = Rn; 7754 7755 // data = MemU[address,2]; 7756 RegisterInfo base_reg; 7757 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg); 7758 7759 RegisterInfo offset_reg; 7760 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + m, offset_reg); 7761 7762 EmulateInstruction::Context context; 7763 context.type = eContextRegisterLoad; 7764 context.SetRegisterPlusIndirectOffset (base_reg, offset_reg); 7765 7766 uint64_t data = MemURead (context, address, 2, 0, &success); 7767 if (!success) 7768 return false; 7769 7770 // if wback then R[n] = offset_addr; 7771 if (wback) 7772 { 7773 context.type = eContextAdjustBaseRegister; 7774 context.SetAddress (offset_addr); 7775 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr)) 7776 return false; 7777 } 7778 7779 // if UnalignedSupport() || address<0> = '0' then 7780 if (UnalignedSupport() || BitIsClear (address, 0)) 7781 { 7782 // R[t] = SignExtend(data, 32); 7783 context.type = eContextRegisterLoad; 7784 context.SetRegisterPlusIndirectOffset (base_reg, offset_reg); 7785 7786 int64_t signed_data = llvm::SignExtend64<16>(data); 7787 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, (uint64_t) signed_data)) 7788 return false; 7789 } 7790 else // Can only apply before ARMv7 7791 { 7792 // R[t] = bits(32) UNKNOWN; 7793 WriteBits32Unknown (t); 7794 } 7795 } 7796 return true; 7797} 7798 7799// SXTB extracts an 8-bit value from a register, sign-extends it to 32 bits, and writes the result to the destination 7800// register. You can specifiy a rotation by 0, 8, 16, or 24 bits before extracting the 8-bit value. 7801bool 7802EmulateInstructionARM::EmulateSXTB (const uint32_t opcode, const ARMEncoding encoding) 7803{ 7804#if 0 7805 if ConditionPassed() then 7806 EncodingSpecificOperations(); 7807 rotated = ROR(R[m], rotation); 7808 R[d] = SignExtend(rotated<7:0>, 32); 7809#endif 7810 7811 bool success = false; 7812 7813 if (ConditionPassed(opcode)) 7814 { 7815 uint32_t d; 7816 uint32_t m; 7817 uint32_t rotation; 7818 7819 // EncodingSpecificOperations(); 7820 switch (encoding) 7821 { 7822 case eEncodingT1: 7823 // d = UInt(Rd); m = UInt(Rm); rotation = 0; 7824 d = Bits32 (opcode, 2, 0); 7825 m = Bits32 (opcode, 5, 3); 7826 rotation = 0; 7827 7828 break; 7829 7830 case eEncodingT2: 7831 // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:'000'); 7832 d = Bits32 (opcode, 11, 8); 7833 m = Bits32 (opcode, 3, 0); 7834 rotation = Bits32 (opcode, 5, 4) << 3; 7835 7836 // if BadReg(d) || BadReg(m) then UNPREDICTABLE; 7837 if (BadReg (d) || BadReg (m)) 7838 return false; 7839 7840 break; 7841 7842 case eEncodingA1: 7843 // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:'000'); 7844 d = Bits32 (opcode, 15, 12); 7845 m = Bits32 (opcode, 3, 0); 7846 rotation = Bits32 (opcode, 11, 10) << 3; 7847 7848 // if d == 15 || m == 15 then UNPREDICTABLE; 7849 if ((d == 15) || (m == 15)) 7850 return false; 7851 7852 break; 7853 7854 default: 7855 return false; 7856 } 7857 7858 uint64_t Rm = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success); 7859 if (!success) 7860 return false; 7861 7862 // rotated = ROR(R[m], rotation); 7863 uint64_t rotated = ROR (Rm, rotation, &success); 7864 if (!success) 7865 return false; 7866 7867 // R[d] = SignExtend(rotated<7:0>, 32); 7868 int64_t data = llvm::SignExtend64<8>(rotated); 7869 7870 RegisterInfo source_reg; 7871 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + m, source_reg); 7872 7873 EmulateInstruction::Context context; 7874 context.type = eContextRegisterLoad; 7875 context.SetRegister (source_reg); 7876 7877 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + d, (uint64_t) data)) 7878 return false; 7879 } 7880 return true; 7881} 7882 7883// SXTH extracts a 16-bit value from a register, sign-extends it to 32 bits, and writes the result to the destination 7884// register. You can specify a rotation by 0, 8, 16, or 24 bits before extracting the 16-bit value. 7885bool 7886EmulateInstructionARM::EmulateSXTH (const uint32_t opcode, const ARMEncoding encoding) 7887{ 7888#if 0 7889 if ConditionPassed() then 7890 EncodingSpecificOperations(); 7891 rotated = ROR(R[m], rotation); 7892 R[d] = SignExtend(rotated<15:0>, 32); 7893#endif 7894 7895 bool success = false; 7896 7897 if (ConditionPassed(opcode)) 7898 { 7899 uint32_t d; 7900 uint32_t m; 7901 uint32_t rotation; 7902 7903 // EncodingSpecificOperations(); 7904 switch (encoding) 7905 { 7906 case eEncodingT1: 7907 // d = UInt(Rd); m = UInt(Rm); rotation = 0; 7908 d = Bits32 (opcode, 2, 0); 7909 m = Bits32 (opcode, 5, 3); 7910 rotation = 0; 7911 7912 break; 7913 7914 case eEncodingT2: 7915 // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:'000'); 7916 d = Bits32 (opcode, 11, 8); 7917 m = Bits32 (opcode, 3, 0); 7918 rotation = Bits32 (opcode, 5, 4) << 3; 7919 7920 // if BadReg(d) || BadReg(m) then UNPREDICTABLE; 7921 if (BadReg (d) || BadReg (m)) 7922 return false; 7923 7924 break; 7925 7926 case eEncodingA1: 7927 // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:'000'); 7928 d = Bits32 (opcode, 15, 12); 7929 m = Bits32 (opcode, 3, 0); 7930 rotation = Bits32 (opcode, 11, 10) << 3; 7931 7932 // if d == 15 || m == 15 then UNPREDICTABLE; 7933 if ((d == 15) || (m == 15)) 7934 return false; 7935 7936 break; 7937 7938 default: 7939 return false; 7940 } 7941 7942 uint64_t Rm = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success); 7943 if (!success) 7944 return false; 7945 7946 // rotated = ROR(R[m], rotation); 7947 uint64_t rotated = ROR (Rm, rotation, &success); 7948 if (!success) 7949 return false; 7950 7951 // R[d] = SignExtend(rotated<15:0>, 32); 7952 RegisterInfo source_reg; 7953 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + m, source_reg); 7954 7955 EmulateInstruction::Context context; 7956 context.type = eContextRegisterLoad; 7957 context.SetRegister (source_reg); 7958 7959 int64_t data = llvm::SignExtend64<16> (rotated); 7960 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + d, (uint64_t) data)) 7961 return false; 7962 } 7963 7964 return true; 7965} 7966 7967// UXTB extracts an 8-bit value from a register, zero-extneds it to 32 bits, and writes the result to the destination 7968// register. You can specify a rotation by 0, 8, 16, or 24 bits before extracting the 8-bit value. 7969bool 7970EmulateInstructionARM::EmulateUXTB (const uint32_t opcode, const ARMEncoding encoding) 7971{ 7972#if 0 7973 if ConditionPassed() then 7974 EncodingSpecificOperations(); 7975 rotated = ROR(R[m], rotation); 7976 R[d] = ZeroExtend(rotated<7:0>, 32); 7977#endif 7978 7979 bool success = false; 7980 7981 if (ConditionPassed(opcode)) 7982 { 7983 uint32_t d; 7984 uint32_t m; 7985 uint32_t rotation; 7986 7987 // EncodingSpecificOperations(); 7988 switch (encoding) 7989 { 7990 case eEncodingT1: 7991 // d = UInt(Rd); m = UInt(Rm); rotation = 0; 7992 d = Bits32 (opcode, 2, 0); 7993 m = Bits32 (opcode, 5, 3); 7994 rotation = 0; 7995 7996 break; 7997 7998 case eEncodingT2: 7999 // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:'000'); 8000 d = Bits32 (opcode, 11, 8); 8001 m = Bits32 (opcode, 3, 0); 8002 rotation = Bits32 (opcode, 5, 4) << 3; 8003 8004 // if BadReg(d) || BadReg(m) then UNPREDICTABLE; 8005 if (BadReg (d) || BadReg (m)) 8006 return false; 8007 8008 break; 8009 8010 case eEncodingA1: 8011 // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:'000'); 8012 d = Bits32 (opcode, 15, 12); 8013 m = Bits32 (opcode, 3, 0); 8014 rotation = Bits32 (opcode, 11, 10) << 3; 8015 8016 // if d == 15 || m == 15 then UNPREDICTABLE; 8017 if ((d == 15) || (m == 15)) 8018 return false; 8019 8020 break; 8021 8022 default: 8023 return false; 8024 } 8025 8026 uint64_t Rm = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success); 8027 if (!success) 8028 return false; 8029 8030 // rotated = ROR(R[m], rotation); 8031 uint64_t rotated = ROR (Rm, rotation, &success); 8032 if (!success) 8033 return false; 8034 8035 // R[d] = ZeroExtend(rotated<7:0>, 32); 8036 RegisterInfo source_reg; 8037 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + m, source_reg); 8038 8039 EmulateInstruction::Context context; 8040 context.type = eContextRegisterLoad; 8041 context.SetRegister (source_reg); 8042 8043 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + d, Bits32 (rotated, 7, 0))) 8044 return false; 8045 } 8046 return true; 8047} 8048 8049// UXTH extracts a 16-bit value from a register, zero-extends it to 32 bits, and writes the result to the destination 8050// register. You can specify a rotation by 0, 8, 16, or 24 bits before extracting the 16-bit value. 8051bool 8052EmulateInstructionARM::EmulateUXTH (const uint32_t opcode, const ARMEncoding encoding) 8053{ 8054#if 0 8055 if ConditionPassed() then 8056 EncodingSpecificOperations(); 8057 rotated = ROR(R[m], rotation); 8058 R[d] = ZeroExtend(rotated<15:0>, 32); 8059#endif 8060 8061 bool success = false; 8062 8063 if (ConditionPassed(opcode)) 8064 { 8065 uint32_t d; 8066 uint32_t m; 8067 uint32_t rotation; 8068 8069 switch (encoding) 8070 { 8071 case eEncodingT1: 8072 // d = UInt(Rd); m = UInt(Rm); rotation = 0; 8073 d = Bits32 (opcode, 2, 0); 8074 m = Bits32 (opcode, 5, 3); 8075 rotation = 0; 8076 8077 break; 8078 8079 case eEncodingT2: 8080 // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:'000'); 8081 d = Bits32 (opcode, 11, 8); 8082 m = Bits32 (opcode, 3, 0); 8083 rotation = Bits32 (opcode, 5, 4) << 3; 8084 8085 // if BadReg(d) || BadReg(m) then UNPREDICTABLE; 8086 if (BadReg (d) || BadReg (m)) 8087 return false; 8088 8089 break; 8090 8091 case eEncodingA1: 8092 // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:'000'); 8093 d = Bits32 (opcode, 15, 12); 8094 m = Bits32 (opcode, 3, 0); 8095 rotation = Bits32 (opcode, 11, 10) << 3; 8096 8097 // if d == 15 || m == 15 then UNPREDICTABLE; 8098 if ((d == 15) || (m == 15)) 8099 return false; 8100 8101 break; 8102 8103 default: 8104 return false; 8105 } 8106 8107 uint64_t Rm = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success); 8108 if (!success) 8109 return false; 8110 8111 // rotated = ROR(R[m], rotation); 8112 uint64_t rotated = ROR (Rm, rotation, &success); 8113 if (!success) 8114 return false; 8115 8116 // R[d] = ZeroExtend(rotated<15:0>, 32); 8117 RegisterInfo source_reg; 8118 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + m, source_reg); 8119 8120 EmulateInstruction::Context context; 8121 context.type = eContextRegisterLoad; 8122 context.SetRegister (source_reg); 8123 8124 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + d, Bits32 (rotated, 15, 0))) 8125 return false; 8126 } 8127 return true; 8128} 8129 8130// RFE (Return From Exception) loads the PC and the CPSR from the word at the specified address and the following 8131// word respectively. 8132bool 8133EmulateInstructionARM::EmulateRFE (const uint32_t opcode, const ARMEncoding encoding) 8134{ 8135#if 0 8136 if ConditionPassed() then 8137 EncodingSpecificOperations(); 8138 if !CurrentModeIsPrivileged() || CurrentInstrSet() == InstrSet_ThumbEE then 8139 UNPREDICTABLE; 8140 else 8141 address = if increment then R[n] else R[n]-8; 8142 if wordhigher then address = address+4; 8143 CPSRWriteByInstr(MemA[address+4,4], '1111', TRUE); 8144 BranchWritePC(MemA[address,4]); 8145 if wback then R[n] = if increment then R[n]+8 else R[n]-8; 8146#endif 8147 8148 bool success = false; 8149 8150 if (ConditionPassed(opcode)) 8151 { 8152 uint32_t n; 8153 bool wback; 8154 bool increment; 8155 bool wordhigher; 8156 8157 // EncodingSpecificOperations(); 8158 switch (encoding) 8159 { 8160 case eEncodingT1: 8161 // n = UInt(Rn); wback = (W == '1'); increment = FALSE; wordhigher = FALSE; 8162 n = Bits32 (opcode, 19, 16); 8163 wback = BitIsSet (opcode, 21); 8164 increment = false; 8165 wordhigher = false; 8166 8167 // if n == 15 then UNPREDICTABLE; 8168 if (n == 15) 8169 return false; 8170 8171 // if InITBlock() && !LastInITBlock() then UNPREDICTABLE; 8172 if (InITBlock() && !LastInITBlock()) 8173 return false; 8174 8175 break; 8176 8177 case eEncodingT2: 8178 // n = UInt(Rn); wback = (W == '1'); increment = TRUE; wordhigher = FALSE; 8179 n = Bits32 (opcode, 19, 16); 8180 wback = BitIsSet (opcode, 21); 8181 increment = true; 8182 wordhigher = false; 8183 8184 // if n == 15 then UNPREDICTABLE; 8185 if (n == 15) 8186 return false; 8187 8188 // if InITBlock() && !LastInITBlock() then UNPREDICTABLE; 8189 if (InITBlock() && !LastInITBlock()) 8190 return false; 8191 8192 break; 8193 8194 case eEncodingA1: 8195 // n = UInt(Rn); 8196 n = Bits32 (opcode, 19, 16); 8197 8198 // wback = (W == '1'); inc = (U == '1'); wordhigher = (P == U); 8199 wback = BitIsSet (opcode, 21); 8200 increment = BitIsSet (opcode, 23); 8201 wordhigher = (Bit32 (opcode, 24) == Bit32 (opcode, 23)); 8202 8203 // if n == 15 then UNPREDICTABLE; 8204 if (n == 15) 8205 return false; 8206 8207 break; 8208 8209 default: 8210 return false; 8211 } 8212 8213 // if !CurrentModeIsPrivileged() || CurrentInstrSet() == InstrSet_ThumbEE then 8214 if (!CurrentModeIsPrivileged ()) 8215 // UNPREDICTABLE; 8216 return false; 8217 else 8218 { 8219 uint64_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success); 8220 if (!success) 8221 return false; 8222 8223 addr_t address; 8224 // address = if increment then R[n] else R[n]-8; 8225 if (increment) 8226 address = Rn; 8227 else 8228 address = Rn - 8; 8229 8230 // if wordhigher then address = address+4; 8231 if (wordhigher) 8232 address = address + 4; 8233 8234 // CPSRWriteByInstr(MemA[address+4,4], '1111', TRUE); 8235 RegisterInfo base_reg; 8236 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg); 8237 8238 EmulateInstruction::Context context; 8239 context.type = eContextReturnFromException; 8240 context.SetRegisterPlusOffset (base_reg, address - Rn); 8241 8242 uint64_t data = MemARead (context, address + 4, 4, 0, &success); 8243 if (!success) 8244 return false; 8245 8246 CPSRWriteByInstr (data, 15, true); 8247 8248 // BranchWritePC(MemA[address,4]); 8249 uint64_t data2 = MemARead (context, address, 4, 0, &success); 8250 if (!success) 8251 return false; 8252 8253 BranchWritePC (context, data2); 8254 8255 // if wback then R[n] = if increment then R[n]+8 else R[n]-8; 8256 if (wback) 8257 { 8258 context.type = eContextAdjustBaseRegister; 8259 if (increment) 8260 { 8261 context.SetOffset (8); 8262 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, Rn + 8)) 8263 return false; 8264 } 8265 else 8266 { 8267 context.SetOffset (-8); 8268 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, Rn - 8)) 8269 return false; 8270 } 8271 } // if wback 8272 } 8273 } // if ConditionPassed() 8274 return true; 8275} 8276 8277// Bitwise Exclusive OR (immediate) performs a bitwise exclusive OR of a register value and an immediate value, 8278// and writes the result to the destination register. It can optionally update the condition flags based on 8279// the result. 8280bool 8281EmulateInstructionARM::EmulateEORImm (const uint32_t opcode, const ARMEncoding encoding) 8282{ 8283#if 0 8284 // ARM pseudo code... 8285 if ConditionPassed() then 8286 EncodingSpecificOperations(); 8287 result = R[n] EOR imm32; 8288 if d == 15 then // Can only occur for ARM encoding 8289 ALUWritePC(result); // setflags is always FALSE here 8290 else 8291 R[d] = result; 8292 if setflags then 8293 APSR.N = result<31>; 8294 APSR.Z = IsZeroBit(result); 8295 APSR.C = carry; 8296 // APSR.V unchanged 8297#endif 8298 8299 bool success = false; 8300 8301 if (ConditionPassed(opcode)) 8302 { 8303 uint32_t Rd, Rn; 8304 uint32_t imm32; // the immediate value to be ORed to the value obtained from Rn 8305 bool setflags; 8306 uint32_t carry; // the carry bit after ARM/Thumb Expand operation 8307 switch (encoding) 8308 { 8309 case eEncodingT1: 8310 Rd = Bits32(opcode, 11, 8); 8311 Rn = Bits32(opcode, 19, 16); 8312 setflags = BitIsSet(opcode, 20); 8313 imm32 = ThumbExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C) 8314 // if Rd == '1111' && S == '1' then SEE TEQ (immediate); 8315 if (Rd == 15 && setflags) 8316 return EmulateTEQImm (opcode, eEncodingT1); 8317 if (Rd == 13 || (Rd == 15 && !setflags) || BadReg(Rn)) 8318 return false; 8319 break; 8320 case eEncodingA1: 8321 Rd = Bits32(opcode, 15, 12); 8322 Rn = Bits32(opcode, 19, 16); 8323 setflags = BitIsSet(opcode, 20); 8324 imm32 = ARMExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ARMExpandImm(imm12, APSR.C) 8325 8326 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions; 8327 if (Rd == 15 && setflags) 8328 return EmulateSUBSPcLrEtc (opcode, encoding); 8329 break; 8330 default: 8331 return false; 8332 } 8333 8334 // Read the first operand. 8335 uint32_t val1 = ReadCoreReg(Rn, &success); 8336 if (!success) 8337 return false; 8338 8339 uint32_t result = val1 ^ imm32; 8340 8341 EmulateInstruction::Context context; 8342 context.type = EmulateInstruction::eContextImmediate; 8343 context.SetNoArgs (); 8344 8345 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry)) 8346 return false; 8347 } 8348 return true; 8349} 8350 8351// Bitwise Exclusive OR (register) performs a bitwise exclusive OR of a register value and an 8352// optionally-shifted register value, and writes the result to the destination register. 8353// It can optionally update the condition flags based on the result. 8354bool 8355EmulateInstructionARM::EmulateEORReg (const uint32_t opcode, const ARMEncoding encoding) 8356{ 8357#if 0 8358 // ARM pseudo code... 8359 if ConditionPassed() then 8360 EncodingSpecificOperations(); 8361 (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C); 8362 result = R[n] EOR shifted; 8363 if d == 15 then // Can only occur for ARM encoding 8364 ALUWritePC(result); // setflags is always FALSE here 8365 else 8366 R[d] = result; 8367 if setflags then 8368 APSR.N = result<31>; 8369 APSR.Z = IsZeroBit(result); 8370 APSR.C = carry; 8371 // APSR.V unchanged 8372#endif 8373 8374 bool success = false; 8375 8376 if (ConditionPassed(opcode)) 8377 { 8378 uint32_t Rd, Rn, Rm; 8379 ARM_ShifterType shift_t; 8380 uint32_t shift_n; // the shift applied to the value read from Rm 8381 bool setflags; 8382 uint32_t carry; 8383 switch (encoding) 8384 { 8385 case eEncodingT1: 8386 Rd = Rn = Bits32(opcode, 2, 0); 8387 Rm = Bits32(opcode, 5, 3); 8388 setflags = !InITBlock(); 8389 shift_t = SRType_LSL; 8390 shift_n = 0; 8391 break; 8392 case eEncodingT2: 8393 Rd = Bits32(opcode, 11, 8); 8394 Rn = Bits32(opcode, 19, 16); 8395 Rm = Bits32(opcode, 3, 0); 8396 setflags = BitIsSet(opcode, 20); 8397 shift_n = DecodeImmShiftThumb(opcode, shift_t); 8398 // if Rd == '1111' && S == '1' then SEE TEQ (register); 8399 if (Rd == 15 && setflags) 8400 return EmulateTEQReg (opcode, eEncodingT1); 8401 if (Rd == 13 || (Rd == 15 && !setflags) || BadReg(Rn) || BadReg(Rm)) 8402 return false; 8403 break; 8404 case eEncodingA1: 8405 Rd = Bits32(opcode, 15, 12); 8406 Rn = Bits32(opcode, 19, 16); 8407 Rm = Bits32(opcode, 3, 0); 8408 setflags = BitIsSet(opcode, 20); 8409 shift_n = DecodeImmShiftARM(opcode, shift_t); 8410 8411 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions; 8412 if (Rd == 15 && setflags) 8413 return EmulateSUBSPcLrEtc (opcode, encoding); 8414 break; 8415 default: 8416 return false; 8417 } 8418 8419 // Read the first operand. 8420 uint32_t val1 = ReadCoreReg(Rn, &success); 8421 if (!success) 8422 return false; 8423 8424 // Read the second operand. 8425 uint32_t val2 = ReadCoreReg(Rm, &success); 8426 if (!success) 8427 return false; 8428 8429 uint32_t shifted = Shift_C(val2, shift_t, shift_n, APSR_C, carry, &success); 8430 if (!success) 8431 return false; 8432 uint32_t result = val1 ^ shifted; 8433 8434 EmulateInstruction::Context context; 8435 context.type = EmulateInstruction::eContextImmediate; 8436 context.SetNoArgs (); 8437 8438 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry)) 8439 return false; 8440 } 8441 return true; 8442} 8443 8444// Bitwise OR (immediate) performs a bitwise (inclusive) OR of a register value and an immediate value, and 8445// writes the result to the destination register. It can optionally update the condition flags based 8446// on the result. 8447bool 8448EmulateInstructionARM::EmulateORRImm (const uint32_t opcode, const ARMEncoding encoding) 8449{ 8450#if 0 8451 // ARM pseudo code... 8452 if ConditionPassed() then 8453 EncodingSpecificOperations(); 8454 result = R[n] OR imm32; 8455 if d == 15 then // Can only occur for ARM encoding 8456 ALUWritePC(result); // setflags is always FALSE here 8457 else 8458 R[d] = result; 8459 if setflags then 8460 APSR.N = result<31>; 8461 APSR.Z = IsZeroBit(result); 8462 APSR.C = carry; 8463 // APSR.V unchanged 8464#endif 8465 8466 bool success = false; 8467 8468 if (ConditionPassed(opcode)) 8469 { 8470 uint32_t Rd, Rn; 8471 uint32_t imm32; // the immediate value to be ORed to the value obtained from Rn 8472 bool setflags; 8473 uint32_t carry; // the carry bit after ARM/Thumb Expand operation 8474 switch (encoding) 8475 { 8476 case eEncodingT1: 8477 Rd = Bits32(opcode, 11, 8); 8478 Rn = Bits32(opcode, 19, 16); 8479 setflags = BitIsSet(opcode, 20); 8480 imm32 = ThumbExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C) 8481 // if Rn == '1111' then SEE MOV (immediate); 8482 if (Rn == 15) 8483 return EmulateMOVRdImm (opcode, eEncodingT2); 8484 if (BadReg(Rd) || Rn == 13) 8485 return false; 8486 break; 8487 case eEncodingA1: 8488 Rd = Bits32(opcode, 15, 12); 8489 Rn = Bits32(opcode, 19, 16); 8490 setflags = BitIsSet(opcode, 20); 8491 imm32 = ARMExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ARMExpandImm(imm12, APSR.C) 8492 8493 if (Rd == 15 && setflags) 8494 return EmulateSUBSPcLrEtc (opcode, encoding); 8495 break; 8496 default: 8497 return false; 8498 } 8499 8500 // Read the first operand. 8501 uint32_t val1 = ReadCoreReg(Rn, &success); 8502 if (!success) 8503 return false; 8504 8505 uint32_t result = val1 | imm32; 8506 8507 EmulateInstruction::Context context; 8508 context.type = EmulateInstruction::eContextImmediate; 8509 context.SetNoArgs (); 8510 8511 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry)) 8512 return false; 8513 } 8514 return true; 8515} 8516 8517// Bitwise OR (register) performs a bitwise (inclusive) OR of a register value and an optionally-shifted register 8518// value, and writes the result to the destination register. It can optionally update the condition flags based 8519// on the result. 8520bool 8521EmulateInstructionARM::EmulateORRReg (const uint32_t opcode, const ARMEncoding encoding) 8522{ 8523#if 0 8524 // ARM pseudo code... 8525 if ConditionPassed() then 8526 EncodingSpecificOperations(); 8527 (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C); 8528 result = R[n] OR shifted; 8529 if d == 15 then // Can only occur for ARM encoding 8530 ALUWritePC(result); // setflags is always FALSE here 8531 else 8532 R[d] = result; 8533 if setflags then 8534 APSR.N = result<31>; 8535 APSR.Z = IsZeroBit(result); 8536 APSR.C = carry; 8537 // APSR.V unchanged 8538#endif 8539 8540 bool success = false; 8541 8542 if (ConditionPassed(opcode)) 8543 { 8544 uint32_t Rd, Rn, Rm; 8545 ARM_ShifterType shift_t; 8546 uint32_t shift_n; // the shift applied to the value read from Rm 8547 bool setflags; 8548 uint32_t carry; 8549 switch (encoding) 8550 { 8551 case eEncodingT1: 8552 Rd = Rn = Bits32(opcode, 2, 0); 8553 Rm = Bits32(opcode, 5, 3); 8554 setflags = !InITBlock(); 8555 shift_t = SRType_LSL; 8556 shift_n = 0; 8557 break; 8558 case eEncodingT2: 8559 Rd = Bits32(opcode, 11, 8); 8560 Rn = Bits32(opcode, 19, 16); 8561 Rm = Bits32(opcode, 3, 0); 8562 setflags = BitIsSet(opcode, 20); 8563 shift_n = DecodeImmShiftThumb(opcode, shift_t); 8564 // if Rn == '1111' then SEE MOV (register); 8565 if (Rn == 15) 8566 return EmulateMOVRdRm (opcode, eEncodingT3); 8567 if (BadReg(Rd) || Rn == 13 || BadReg(Rm)) 8568 return false; 8569 break; 8570 case eEncodingA1: 8571 Rd = Bits32(opcode, 15, 12); 8572 Rn = Bits32(opcode, 19, 16); 8573 Rm = Bits32(opcode, 3, 0); 8574 setflags = BitIsSet(opcode, 20); 8575 shift_n = DecodeImmShiftARM(opcode, shift_t); 8576 8577 if (Rd == 15 && setflags) 8578 return EmulateSUBSPcLrEtc (opcode, encoding); 8579 break; 8580 default: 8581 return false; 8582 } 8583 8584 // Read the first operand. 8585 uint32_t val1 = ReadCoreReg(Rn, &success); 8586 if (!success) 8587 return false; 8588 8589 // Read the second operand. 8590 uint32_t val2 = ReadCoreReg(Rm, &success); 8591 if (!success) 8592 return false; 8593 8594 uint32_t shifted = Shift_C(val2, shift_t, shift_n, APSR_C, carry, &success); 8595 if (!success) 8596 return false; 8597 uint32_t result = val1 | shifted; 8598 8599 EmulateInstruction::Context context; 8600 context.type = EmulateInstruction::eContextImmediate; 8601 context.SetNoArgs (); 8602 8603 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry)) 8604 return false; 8605 } 8606 return true; 8607} 8608 8609// Reverse Subtract (immediate) subtracts a register value from an immediate value, and writes the result to 8610// the destination register. It can optionally update the condition flags based on the result. 8611bool 8612EmulateInstructionARM::EmulateRSBImm (const uint32_t opcode, const ARMEncoding encoding) 8613{ 8614#if 0 8615 // ARM pseudo code... 8616 if ConditionPassed() then 8617 EncodingSpecificOperations(); 8618 (result, carry, overflow) = AddWithCarry(NOT(R[n]), imm32, '1'); 8619 if d == 15 then // Can only occur for ARM encoding 8620 ALUWritePC(result); // setflags is always FALSE here 8621 else 8622 R[d] = result; 8623 if setflags then 8624 APSR.N = result<31>; 8625 APSR.Z = IsZeroBit(result); 8626 APSR.C = carry; 8627 APSR.V = overflow; 8628#endif 8629 8630 bool success = false; 8631 8632 uint32_t Rd; // the destination register 8633 uint32_t Rn; // the first operand 8634 bool setflags; 8635 uint32_t imm32; // the immediate value to be added to the value obtained from Rn 8636 switch (encoding) { 8637 case eEncodingT1: 8638 Rd = Bits32(opcode, 2, 0); 8639 Rn = Bits32(opcode, 5, 3); 8640 setflags = !InITBlock(); 8641 imm32 = 0; 8642 break; 8643 case eEncodingT2: 8644 Rd = Bits32(opcode, 11, 8); 8645 Rn = Bits32(opcode, 19, 16); 8646 setflags = BitIsSet(opcode, 20); 8647 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8) 8648 if (BadReg(Rd) || BadReg(Rn)) 8649 return false; 8650 break; 8651 case eEncodingA1: 8652 Rd = Bits32(opcode, 15, 12); 8653 Rn = Bits32(opcode, 19, 16); 8654 setflags = BitIsSet(opcode, 20); 8655 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12) 8656 8657 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions; 8658 if (Rd == 15 && setflags) 8659 return EmulateSUBSPcLrEtc (opcode, encoding); 8660 break; 8661 default: 8662 return false; 8663 } 8664 // Read the register value from the operand register Rn. 8665 uint32_t reg_val = ReadCoreReg(Rn, &success); 8666 if (!success) 8667 return false; 8668 8669 AddWithCarryResult res = AddWithCarry(~reg_val, imm32, 1); 8670 8671 EmulateInstruction::Context context; 8672 context.type = EmulateInstruction::eContextImmediate; 8673 context.SetNoArgs (); 8674 8675 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow)) 8676 return false; 8677 8678 return true; 8679} 8680 8681// Reverse Subtract (register) subtracts a register value from an optionally-shifted register value, and writes the 8682// result to the destination register. It can optionally update the condition flags based on the result. 8683bool 8684EmulateInstructionARM::EmulateRSBReg (const uint32_t opcode, const ARMEncoding encoding) 8685{ 8686#if 0 8687 // ARM pseudo code... 8688 if ConditionPassed() then 8689 EncodingSpecificOperations(); 8690 shifted = Shift(R[m], shift_t, shift_n, APSR.C); 8691 (result, carry, overflow) = AddWithCarry(NOT(R[n]), shifted, '1'); 8692 if d == 15 then // Can only occur for ARM encoding 8693 ALUWritePC(result); // setflags is always FALSE here 8694 else 8695 R[d] = result; 8696 if setflags then 8697 APSR.N = result<31>; 8698 APSR.Z = IsZeroBit(result); 8699 APSR.C = carry; 8700 APSR.V = overflow; 8701#endif 8702 8703 bool success = false; 8704 8705 uint32_t Rd; // the destination register 8706 uint32_t Rn; // the first operand 8707 uint32_t Rm; // the second operand 8708 bool setflags; 8709 ARM_ShifterType shift_t; 8710 uint32_t shift_n; // the shift applied to the value read from Rm 8711 switch (encoding) { 8712 case eEncodingT1: 8713 Rd = Bits32(opcode, 11, 8); 8714 Rn = Bits32(opcode, 19, 16); 8715 Rm = Bits32(opcode, 3, 0); 8716 setflags = BitIsSet(opcode, 20); 8717 shift_n = DecodeImmShiftThumb(opcode, shift_t); 8718 // if (BadReg(d) || BadReg(m)) then UNPREDICTABLE; 8719 if (BadReg(Rd) || BadReg(Rn) || BadReg(Rm)) 8720 return false; 8721 break; 8722 case eEncodingA1: 8723 Rd = Bits32(opcode, 15, 12); 8724 Rn = Bits32(opcode, 19, 16); 8725 Rm = Bits32(opcode, 3, 0); 8726 setflags = BitIsSet(opcode, 20); 8727 shift_n = DecodeImmShiftARM(opcode, shift_t); 8728 8729 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions; 8730 if (Rd == 15 && setflags) 8731 return EmulateSUBSPcLrEtc (opcode, encoding); 8732 break; 8733 default: 8734 return false; 8735 } 8736 // Read the register value from register Rn. 8737 uint32_t val1 = ReadCoreReg(Rn, &success); 8738 if (!success) 8739 return false; 8740 8741 // Read the register value from register Rm. 8742 uint32_t val2 = ReadCoreReg(Rm, &success); 8743 if (!success) 8744 return false; 8745 8746 uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C, &success); 8747 if (!success) 8748 return false; 8749 AddWithCarryResult res = AddWithCarry(~val1, shifted, 1); 8750 8751 EmulateInstruction::Context context; 8752 context.type = EmulateInstruction::eContextImmediate; 8753 context.SetNoArgs(); 8754 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow)) 8755 return false; 8756 8757 return true; 8758} 8759 8760// Reverse Subtract with Carry (immediate) subtracts a register value and the value of NOT (Carry flag) from 8761// an immediate value, and writes the result to the destination register. It can optionally update the condition 8762// flags based on the result. 8763bool 8764EmulateInstructionARM::EmulateRSCImm (const uint32_t opcode, const ARMEncoding encoding) 8765{ 8766#if 0 8767 // ARM pseudo code... 8768 if ConditionPassed() then 8769 EncodingSpecificOperations(); 8770 (result, carry, overflow) = AddWithCarry(NOT(R[n]), imm32, APSR.C); 8771 if d == 15 then 8772 ALUWritePC(result); // setflags is always FALSE here 8773 else 8774 R[d] = result; 8775 if setflags then 8776 APSR.N = result<31>; 8777 APSR.Z = IsZeroBit(result); 8778 APSR.C = carry; 8779 APSR.V = overflow; 8780#endif 8781 8782 bool success = false; 8783 8784 uint32_t Rd; // the destination register 8785 uint32_t Rn; // the first operand 8786 bool setflags; 8787 uint32_t imm32; // the immediate value to be added to the value obtained from Rn 8788 switch (encoding) { 8789 case eEncodingA1: 8790 Rd = Bits32(opcode, 15, 12); 8791 Rn = Bits32(opcode, 19, 16); 8792 setflags = BitIsSet(opcode, 20); 8793 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12) 8794 8795 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions; 8796 if (Rd == 15 && setflags) 8797 return EmulateSUBSPcLrEtc (opcode, encoding); 8798 break; 8799 default: 8800 return false; 8801 } 8802 // Read the register value from the operand register Rn. 8803 uint32_t reg_val = ReadCoreReg(Rn, &success); 8804 if (!success) 8805 return false; 8806 8807 AddWithCarryResult res = AddWithCarry(~reg_val, imm32, APSR_C); 8808 8809 EmulateInstruction::Context context; 8810 context.type = EmulateInstruction::eContextImmediate; 8811 context.SetNoArgs (); 8812 8813 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow)) 8814 return false; 8815 8816 return true; 8817} 8818 8819// Reverse Subtract with Carry (register) subtracts a register value and the value of NOT (Carry flag) from an 8820// optionally-shifted register value, and writes the result to the destination register. It can optionally update the 8821// condition flags based on the result. 8822bool 8823EmulateInstructionARM::EmulateRSCReg (const uint32_t opcode, const ARMEncoding encoding) 8824{ 8825#if 0 8826 // ARM pseudo code... 8827 if ConditionPassed() then 8828 EncodingSpecificOperations(); 8829 shifted = Shift(R[m], shift_t, shift_n, APSR.C); 8830 (result, carry, overflow) = AddWithCarry(NOT(R[n]), shifted, APSR.C); 8831 if d == 15 then 8832 ALUWritePC(result); // setflags is always FALSE here 8833 else 8834 R[d] = result; 8835 if setflags then 8836 APSR.N = result<31>; 8837 APSR.Z = IsZeroBit(result); 8838 APSR.C = carry; 8839 APSR.V = overflow; 8840#endif 8841 8842 bool success = false; 8843 8844 uint32_t Rd; // the destination register 8845 uint32_t Rn; // the first operand 8846 uint32_t Rm; // the second operand 8847 bool setflags; 8848 ARM_ShifterType shift_t; 8849 uint32_t shift_n; // the shift applied to the value read from Rm 8850 switch (encoding) { 8851 case eEncodingA1: 8852 Rd = Bits32(opcode, 15, 12); 8853 Rn = Bits32(opcode, 19, 16); 8854 Rm = Bits32(opcode, 3, 0); 8855 setflags = BitIsSet(opcode, 20); 8856 shift_n = DecodeImmShiftARM(opcode, shift_t); 8857 8858 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions; 8859 if (Rd == 15 && setflags) 8860 return EmulateSUBSPcLrEtc (opcode, encoding); 8861 break; 8862 default: 8863 return false; 8864 } 8865 // Read the register value from register Rn. 8866 uint32_t val1 = ReadCoreReg(Rn, &success); 8867 if (!success) 8868 return false; 8869 8870 // Read the register value from register Rm. 8871 uint32_t val2 = ReadCoreReg(Rm, &success); 8872 if (!success) 8873 return false; 8874 8875 uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C, &success); 8876 if (!success) 8877 return false; 8878 AddWithCarryResult res = AddWithCarry(~val1, shifted, APSR_C); 8879 8880 EmulateInstruction::Context context; 8881 context.type = EmulateInstruction::eContextImmediate; 8882 context.SetNoArgs(); 8883 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow)) 8884 return false; 8885 8886 return true; 8887} 8888 8889// Subtract with Carry (immediate) subtracts an immediate value and the value of 8890// NOT (Carry flag) from a register value, and writes the result to the destination register. 8891// It can optionally update the condition flags based on the result. 8892bool 8893EmulateInstructionARM::EmulateSBCImm (const uint32_t opcode, const ARMEncoding encoding) 8894{ 8895#if 0 8896 // ARM pseudo code... 8897 if ConditionPassed() then 8898 EncodingSpecificOperations(); 8899 (result, carry, overflow) = AddWithCarry(R[n], NOT(imm32), APSR.C); 8900 if d == 15 then // Can only occur for ARM encoding 8901 ALUWritePC(result); // setflags is always FALSE here 8902 else 8903 R[d] = result; 8904 if setflags then 8905 APSR.N = result<31>; 8906 APSR.Z = IsZeroBit(result); 8907 APSR.C = carry; 8908 APSR.V = overflow; 8909#endif 8910 8911 bool success = false; 8912 8913 uint32_t Rd; // the destination register 8914 uint32_t Rn; // the first operand 8915 bool setflags; 8916 uint32_t imm32; // the immediate value to be added to the value obtained from Rn 8917 switch (encoding) { 8918 case eEncodingT1: 8919 Rd = Bits32(opcode, 11, 8); 8920 Rn = Bits32(opcode, 19, 16); 8921 setflags = BitIsSet(opcode, 20); 8922 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8) 8923 if (BadReg(Rd) || BadReg(Rn)) 8924 return false; 8925 break; 8926 case eEncodingA1: 8927 Rd = Bits32(opcode, 15, 12); 8928 Rn = Bits32(opcode, 19, 16); 8929 setflags = BitIsSet(opcode, 20); 8930 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12) 8931 8932 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions; 8933 if (Rd == 15 && setflags) 8934 return EmulateSUBSPcLrEtc (opcode, encoding); 8935 break; 8936 default: 8937 return false; 8938 } 8939 // Read the register value from the operand register Rn. 8940 uint32_t reg_val = ReadCoreReg(Rn, &success); 8941 if (!success) 8942 return false; 8943 8944 AddWithCarryResult res = AddWithCarry(reg_val, ~imm32, APSR_C); 8945 8946 EmulateInstruction::Context context; 8947 context.type = EmulateInstruction::eContextImmediate; 8948 context.SetNoArgs (); 8949 8950 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow)) 8951 return false; 8952 8953 return true; 8954} 8955 8956// Subtract with Carry (register) subtracts an optionally-shifted register value and the value of 8957// NOT (Carry flag) from a register value, and writes the result to the destination register. 8958// It can optionally update the condition flags based on the result. 8959bool 8960EmulateInstructionARM::EmulateSBCReg (const uint32_t opcode, const ARMEncoding encoding) 8961{ 8962#if 0 8963 // ARM pseudo code... 8964 if ConditionPassed() then 8965 EncodingSpecificOperations(); 8966 shifted = Shift(R[m], shift_t, shift_n, APSR.C); 8967 (result, carry, overflow) = AddWithCarry(R[n], NOT(shifted), APSR.C); 8968 if d == 15 then // Can only occur for ARM encoding 8969 ALUWritePC(result); // setflags is always FALSE here 8970 else 8971 R[d] = result; 8972 if setflags then 8973 APSR.N = result<31>; 8974 APSR.Z = IsZeroBit(result); 8975 APSR.C = carry; 8976 APSR.V = overflow; 8977#endif 8978 8979 bool success = false; 8980 8981 uint32_t Rd; // the destination register 8982 uint32_t Rn; // the first operand 8983 uint32_t Rm; // the second operand 8984 bool setflags; 8985 ARM_ShifterType shift_t; 8986 uint32_t shift_n; // the shift applied to the value read from Rm 8987 switch (encoding) { 8988 case eEncodingT1: 8989 Rd = Rn = Bits32(opcode, 2, 0); 8990 Rm = Bits32(opcode, 5, 3); 8991 setflags = !InITBlock(); 8992 shift_t = SRType_LSL; 8993 shift_n = 0; 8994 break; 8995 case eEncodingT2: 8996 Rd = Bits32(opcode, 11, 8); 8997 Rn = Bits32(opcode, 19, 16); 8998 Rm = Bits32(opcode, 3, 0); 8999 setflags = BitIsSet(opcode, 20); 9000 shift_n = DecodeImmShiftThumb(opcode, shift_t); 9001 if (BadReg(Rd) || BadReg(Rn) || BadReg(Rm)) 9002 return false; 9003 break; 9004 case eEncodingA1: 9005 Rd = Bits32(opcode, 15, 12); 9006 Rn = Bits32(opcode, 19, 16); 9007 Rm = Bits32(opcode, 3, 0); 9008 setflags = BitIsSet(opcode, 20); 9009 shift_n = DecodeImmShiftARM(opcode, shift_t); 9010 9011 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions; 9012 if (Rd == 15 && setflags) 9013 return EmulateSUBSPcLrEtc (opcode, encoding); 9014 break; 9015 default: 9016 return false; 9017 } 9018 // Read the register value from register Rn. 9019 uint32_t val1 = ReadCoreReg(Rn, &success); 9020 if (!success) 9021 return false; 9022 9023 // Read the register value from register Rm. 9024 uint32_t val2 = ReadCoreReg(Rm, &success); 9025 if (!success) 9026 return false; 9027 9028 uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C, &success); 9029 if (!success) 9030 return false; 9031 AddWithCarryResult res = AddWithCarry(val1, ~shifted, APSR_C); 9032 9033 EmulateInstruction::Context context; 9034 context.type = EmulateInstruction::eContextImmediate; 9035 context.SetNoArgs(); 9036 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow)) 9037 return false; 9038 9039 return true; 9040} 9041 9042// This instruction subtracts an immediate value from a register value, and writes the result 9043// to the destination register. It can optionally update the condition flags based on the result. 9044bool 9045EmulateInstructionARM::EmulateSUBImmThumb (const uint32_t opcode, const ARMEncoding encoding) 9046{ 9047#if 0 9048 // ARM pseudo code... 9049 if ConditionPassed() then 9050 EncodingSpecificOperations(); 9051 (result, carry, overflow) = AddWithCarry(R[n], NOT(imm32), '1'); 9052 R[d] = result; 9053 if setflags then 9054 APSR.N = result<31>; 9055 APSR.Z = IsZeroBit(result); 9056 APSR.C = carry; 9057 APSR.V = overflow; 9058#endif 9059 9060 bool success = false; 9061 9062 uint32_t Rd; // the destination register 9063 uint32_t Rn; // the first operand 9064 bool setflags; 9065 uint32_t imm32; // the immediate value to be subtracted from the value obtained from Rn 9066 switch (encoding) { 9067 case eEncodingT1: 9068 Rd = Bits32(opcode, 2, 0); 9069 Rn = Bits32(opcode, 5, 3); 9070 setflags = !InITBlock(); 9071 imm32 = Bits32(opcode, 8, 6); // imm32 = ZeroExtend(imm3, 32) 9072 break; 9073 case eEncodingT2: 9074 Rd = Rn = Bits32(opcode, 10, 8); 9075 setflags = !InITBlock(); 9076 imm32 = Bits32(opcode, 7, 0); // imm32 = ZeroExtend(imm8, 32) 9077 break; 9078 case eEncodingT3: 9079 Rd = Bits32(opcode, 11, 8); 9080 Rn = Bits32(opcode, 19, 16); 9081 setflags = BitIsSet(opcode, 20); 9082 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8) 9083 9084 // if Rd == '1111' && S == '1' then SEE CMP (immediate); 9085 if (Rd == 15 && setflags) 9086 return EmulateCMPImm (opcode, eEncodingT2); 9087 9088 // if Rn == '1101' then SEE SUB (SP minus immediate); 9089 if (Rn == 13) 9090 return EmulateSUBSPImm (opcode, eEncodingT2); 9091 9092 // if d == 13 || (d == 15 && S == '0') || n == 15 then UNPREDICTABLE; 9093 if (Rd == 13 || (Rd == 15 && !setflags) || Rn == 15) 9094 return false; 9095 break; 9096 case eEncodingT4: 9097 Rd = Bits32(opcode, 11, 8); 9098 Rn = Bits32(opcode, 19, 16); 9099 setflags = BitIsSet(opcode, 20); 9100 imm32 = ThumbImm12(opcode); // imm32 = ZeroExtend(i:imm3:imm8, 32) 9101 9102 // if Rn == '1111' then SEE ADR; 9103 if (Rn == 15) 9104 return EmulateADR (opcode, eEncodingT2); 9105 9106 // if Rn == '1101' then SEE SUB (SP minus immediate); 9107 if (Rn == 13) 9108 return EmulateSUBSPImm (opcode, eEncodingT3); 9109 9110 if (BadReg(Rd)) 9111 return false; 9112 break; 9113 default: 9114 return false; 9115 } 9116 // Read the register value from the operand register Rn. 9117 uint32_t reg_val = ReadCoreReg(Rn, &success); 9118 if (!success) 9119 return false; 9120 9121 AddWithCarryResult res = AddWithCarry(reg_val, ~imm32, 1); 9122 9123 EmulateInstruction::Context context; 9124 context.type = EmulateInstruction::eContextImmediate; 9125 context.SetNoArgs (); 9126 9127 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow)) 9128 return false; 9129 9130 return true; 9131} 9132 9133// This instruction subtracts an immediate value from a register value, and writes the result 9134// to the destination register. It can optionally update the condition flags based on the result. 9135bool 9136EmulateInstructionARM::EmulateSUBImmARM (const uint32_t opcode, const ARMEncoding encoding) 9137{ 9138#if 0 9139 // ARM pseudo code... 9140 if ConditionPassed() then 9141 EncodingSpecificOperations(); 9142 (result, carry, overflow) = AddWithCarry(R[n], NOT(imm32), '1'); 9143 if d == 15 then 9144 ALUWritePC(result); // setflags is always FALSE here 9145 else 9146 R[d] = result; 9147 if setflags then 9148 APSR.N = result<31>; 9149 APSR.Z = IsZeroBit(result); 9150 APSR.C = carry; 9151 APSR.V = overflow; 9152#endif 9153 9154 bool success = false; 9155 9156 uint32_t Rd; // the destination register 9157 uint32_t Rn; // the first operand 9158 bool setflags; 9159 uint32_t imm32; // the immediate value to be subtracted from the value obtained from Rn 9160 switch (encoding) { 9161 case eEncodingA1: 9162 Rd = Bits32(opcode, 15, 12); 9163 Rn = Bits32(opcode, 19, 16); 9164 setflags = BitIsSet(opcode, 20); 9165 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12) 9166 9167 // if Rn == '1111' && S == '0' then SEE ADR; 9168 if (Rn == 15 && !setflags) 9169 return EmulateADR (opcode, eEncodingA2); 9170 9171 // if Rn == '1101' then SEE SUB (SP minus immediate); 9172 if (Rn == 13) 9173 return EmulateSUBSPImm (opcode, eEncodingA1); 9174 9175 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions; 9176 if (Rd == 15 && setflags) 9177 return EmulateSUBSPcLrEtc (opcode, encoding); 9178 break; 9179 default: 9180 return false; 9181 } 9182 // Read the register value from the operand register Rn. 9183 uint32_t reg_val = ReadCoreReg(Rn, &success); 9184 if (!success) 9185 return false; 9186 9187 AddWithCarryResult res = AddWithCarry(reg_val, ~imm32, 1); 9188 9189 EmulateInstruction::Context context; 9190 context.type = EmulateInstruction::eContextImmediate; 9191 context.SetNoArgs (); 9192 9193 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow)) 9194 return false; 9195 9196 return true; 9197} 9198 9199// Test Equivalence (immediate) performs a bitwise exclusive OR operation on a register value and an 9200// immediate value. It updates the condition flags based on the result, and discards the result. 9201bool 9202EmulateInstructionARM::EmulateTEQImm (const uint32_t opcode, const ARMEncoding encoding) 9203{ 9204#if 0 9205 // ARM pseudo code... 9206 if ConditionPassed() then 9207 EncodingSpecificOperations(); 9208 result = R[n] EOR imm32; 9209 APSR.N = result<31>; 9210 APSR.Z = IsZeroBit(result); 9211 APSR.C = carry; 9212 // APSR.V unchanged 9213#endif 9214 9215 bool success = false; 9216 9217 if (ConditionPassed(opcode)) 9218 { 9219 uint32_t Rn; 9220 uint32_t imm32; // the immediate value to be ANDed to the value obtained from Rn 9221 uint32_t carry; // the carry bit after ARM/Thumb Expand operation 9222 switch (encoding) 9223 { 9224 case eEncodingT1: 9225 Rn = Bits32(opcode, 19, 16); 9226 imm32 = ThumbExpandImm_C (opcode, APSR_C, carry); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C) 9227 if (BadReg(Rn)) 9228 return false; 9229 break; 9230 case eEncodingA1: 9231 Rn = Bits32(opcode, 19, 16); 9232 imm32 = ARMExpandImm_C (opcode, APSR_C, carry); // (imm32, carry) = ARMExpandImm(imm12, APSR.C) 9233 break; 9234 default: 9235 return false; 9236 } 9237 9238 // Read the first operand. 9239 uint32_t val1 = ReadCoreReg(Rn, &success); 9240 if (!success) 9241 return false; 9242 9243 uint32_t result = val1 ^ imm32; 9244 9245 EmulateInstruction::Context context; 9246 context.type = EmulateInstruction::eContextImmediate; 9247 context.SetNoArgs (); 9248 9249 if (!WriteFlags(context, result, carry)) 9250 return false; 9251 } 9252 return true; 9253} 9254 9255// Test Equivalence (register) performs a bitwise exclusive OR operation on a register value and an 9256// optionally-shifted register value. It updates the condition flags based on the result, and discards 9257// the result. 9258bool 9259EmulateInstructionARM::EmulateTEQReg (const uint32_t opcode, const ARMEncoding encoding) 9260{ 9261#if 0 9262 // ARM pseudo code... 9263 if ConditionPassed() then 9264 EncodingSpecificOperations(); 9265 (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C); 9266 result = R[n] EOR shifted; 9267 APSR.N = result<31>; 9268 APSR.Z = IsZeroBit(result); 9269 APSR.C = carry; 9270 // APSR.V unchanged 9271#endif 9272 9273 bool success = false; 9274 9275 if (ConditionPassed(opcode)) 9276 { 9277 uint32_t Rn, Rm; 9278 ARM_ShifterType shift_t; 9279 uint32_t shift_n; // the shift applied to the value read from Rm 9280 uint32_t carry; 9281 switch (encoding) 9282 { 9283 case eEncodingT1: 9284 Rn = Bits32(opcode, 19, 16); 9285 Rm = Bits32(opcode, 3, 0); 9286 shift_n = DecodeImmShiftThumb(opcode, shift_t); 9287 if (BadReg(Rn) || BadReg(Rm)) 9288 return false; 9289 break; 9290 case eEncodingA1: 9291 Rn = Bits32(opcode, 19, 16); 9292 Rm = Bits32(opcode, 3, 0); 9293 shift_n = DecodeImmShiftARM(opcode, shift_t); 9294 break; 9295 default: 9296 return false; 9297 } 9298 9299 // Read the first operand. 9300 uint32_t val1 = ReadCoreReg(Rn, &success); 9301 if (!success) 9302 return false; 9303 9304 // Read the second operand. 9305 uint32_t val2 = ReadCoreReg(Rm, &success); 9306 if (!success) 9307 return false; 9308 9309 uint32_t shifted = Shift_C(val2, shift_t, shift_n, APSR_C, carry, &success); 9310 if (!success) 9311 return false; 9312 uint32_t result = val1 ^ shifted; 9313 9314 EmulateInstruction::Context context; 9315 context.type = EmulateInstruction::eContextImmediate; 9316 context.SetNoArgs (); 9317 9318 if (!WriteFlags(context, result, carry)) 9319 return false; 9320 } 9321 return true; 9322} 9323 9324// Test (immediate) performs a bitwise AND operation on a register value and an immediate value. 9325// It updates the condition flags based on the result, and discards the result. 9326bool 9327EmulateInstructionARM::EmulateTSTImm (const uint32_t opcode, const ARMEncoding encoding) 9328{ 9329#if 0 9330 // ARM pseudo code... 9331 if ConditionPassed() then 9332 EncodingSpecificOperations(); 9333 result = R[n] AND imm32; 9334 APSR.N = result<31>; 9335 APSR.Z = IsZeroBit(result); 9336 APSR.C = carry; 9337 // APSR.V unchanged 9338#endif 9339 9340 bool success = false; 9341 9342 if (ConditionPassed(opcode)) 9343 { 9344 uint32_t Rn; 9345 uint32_t imm32; // the immediate value to be ANDed to the value obtained from Rn 9346 uint32_t carry; // the carry bit after ARM/Thumb Expand operation 9347 switch (encoding) 9348 { 9349 case eEncodingT1: 9350 Rn = Bits32(opcode, 19, 16); 9351 imm32 = ThumbExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C) 9352 if (BadReg(Rn)) 9353 return false; 9354 break; 9355 case eEncodingA1: 9356 Rn = Bits32(opcode, 19, 16); 9357 imm32 = ARMExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ARMExpandImm(imm12, APSR.C) 9358 break; 9359 default: 9360 return false; 9361 } 9362 9363 // Read the first operand. 9364 uint32_t val1 = ReadCoreReg(Rn, &success); 9365 if (!success) 9366 return false; 9367 9368 uint32_t result = val1 & imm32; 9369 9370 EmulateInstruction::Context context; 9371 context.type = EmulateInstruction::eContextImmediate; 9372 context.SetNoArgs (); 9373 9374 if (!WriteFlags(context, result, carry)) 9375 return false; 9376 } 9377 return true; 9378} 9379 9380// Test (register) performs a bitwise AND operation on a register value and an optionally-shifted register value. 9381// It updates the condition flags based on the result, and discards the result. 9382bool 9383EmulateInstructionARM::EmulateTSTReg (const uint32_t opcode, const ARMEncoding encoding) 9384{ 9385#if 0 9386 // ARM pseudo code... 9387 if ConditionPassed() then 9388 EncodingSpecificOperations(); 9389 (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C); 9390 result = R[n] AND shifted; 9391 APSR.N = result<31>; 9392 APSR.Z = IsZeroBit(result); 9393 APSR.C = carry; 9394 // APSR.V unchanged 9395#endif 9396 9397 bool success = false; 9398 9399 if (ConditionPassed(opcode)) 9400 { 9401 uint32_t Rn, Rm; 9402 ARM_ShifterType shift_t; 9403 uint32_t shift_n; // the shift applied to the value read from Rm 9404 uint32_t carry; 9405 switch (encoding) 9406 { 9407 case eEncodingT1: 9408 Rn = Bits32(opcode, 2, 0); 9409 Rm = Bits32(opcode, 5, 3); 9410 shift_t = SRType_LSL; 9411 shift_n = 0; 9412 break; 9413 case eEncodingT2: 9414 Rn = Bits32(opcode, 19, 16); 9415 Rm = Bits32(opcode, 3, 0); 9416 shift_n = DecodeImmShiftThumb(opcode, shift_t); 9417 if (BadReg(Rn) || BadReg(Rm)) 9418 return false; 9419 break; 9420 case eEncodingA1: 9421 Rn = Bits32(opcode, 19, 16); 9422 Rm = Bits32(opcode, 3, 0); 9423 shift_n = DecodeImmShiftARM(opcode, shift_t); 9424 break; 9425 default: 9426 return false; 9427 } 9428 9429 // Read the first operand. 9430 uint32_t val1 = ReadCoreReg(Rn, &success); 9431 if (!success) 9432 return false; 9433 9434 // Read the second operand. 9435 uint32_t val2 = ReadCoreReg(Rm, &success); 9436 if (!success) 9437 return false; 9438 9439 uint32_t shifted = Shift_C(val2, shift_t, shift_n, APSR_C, carry, &success); 9440 if (!success) 9441 return false; 9442 uint32_t result = val1 & shifted; 9443 9444 EmulateInstruction::Context context; 9445 context.type = EmulateInstruction::eContextImmediate; 9446 context.SetNoArgs (); 9447 9448 if (!WriteFlags(context, result, carry)) 9449 return false; 9450 } 9451 return true; 9452} 9453 9454// A8.6.216 SUB (SP minus register) 9455bool 9456EmulateInstructionARM::EmulateSUBSPReg (const uint32_t opcode, const ARMEncoding encoding) 9457{ 9458#if 0 9459 if ConditionPassed() then 9460 EncodingSpecificOperations(); 9461 shifted = Shift(R[m], shift_t, shift_n, APSR.C); 9462 (result, carry, overflow) = AddWithCarry(SP, NOT(shifted), �1�); 9463 if d == 15 then // Can only occur for ARM encoding 9464 ALUWritePC(result); // setflags is always FALSE here 9465 else 9466 R[d] = result; 9467 if setflags then 9468 APSR.N = result<31>; 9469 APSR.Z = IsZeroBit(result); 9470 APSR.C = carry; 9471 APSR.V = overflow; 9472#endif 9473 9474 bool success = false; 9475 9476 if (ConditionPassed(opcode)) 9477 { 9478 uint32_t d; 9479 uint32_t m; 9480 bool setflags; 9481 ARM_ShifterType shift_t; 9482 uint32_t shift_n; 9483 9484 switch (encoding) 9485 { 9486 case eEncodingT1: 9487 // d = UInt(Rd); m = UInt(Rm); setflags = (S == �1�); 9488 d = Bits32 (opcode, 11, 8); 9489 m = Bits32 (opcode, 3, 0); 9490 setflags = BitIsSet (opcode, 20); 9491 9492 // (shift_t, shift_n) = DecodeImmShift(type, imm3:imm2); 9493 shift_n = DecodeImmShiftThumb (opcode, shift_t); 9494 9495 // if d == 13 && (shift_t != SRType_LSL || shift_n > 3) then UNPREDICTABLE; 9496 if ((d == 13) && ((shift_t != SRType_LSL) || (shift_n > 3))) 9497 return false; 9498 9499 // if d == 15 || BadReg(m) then UNPREDICTABLE; 9500 if ((d == 15) || BadReg (m)) 9501 return false; 9502 break; 9503 9504 case eEncodingA1: 9505 // d = UInt(Rd); m = UInt(Rm); setflags = (S == �1�); 9506 d = Bits32 (opcode, 15, 12); 9507 m = Bits32 (opcode, 3, 0); 9508 setflags = BitIsSet (opcode, 20); 9509 9510 // if Rd == �1111� && S == �1� then SEE SUBS PC, LR and related instructions; 9511 if (d == 15 && setflags) 9512 EmulateSUBSPcLrEtc (opcode, encoding); 9513 9514 // (shift_t, shift_n) = DecodeImmShift(type, imm5); 9515 shift_n = DecodeImmShiftARM (opcode, shift_t); 9516 break; 9517 9518 default: 9519 return false; 9520 } 9521 9522 // shifted = Shift(R[m], shift_t, shift_n, APSR.C); 9523 uint32_t Rm = ReadCoreReg (m, &success); 9524 if (!success) 9525 return false; 9526 9527 uint32_t shifted = Shift (Rm, shift_t, shift_n, APSR_C, &success); 9528 if (!success) 9529 return false; 9530 9531 // (result, carry, overflow) = AddWithCarry(SP, NOT(shifted), �1�); 9532 uint32_t sp_val = ReadCoreReg (SP_REG, &success); 9533 if (!success) 9534 return false; 9535 9536 AddWithCarryResult res = AddWithCarry (sp_val, ~shifted, 1); 9537 9538 EmulateInstruction::Context context; 9539 context.type = eContextArithmetic; 9540 RegisterInfo sp_reg; 9541 GetRegisterInfo (eRegisterKindDWARF, dwarf_sp, sp_reg); 9542 RegisterInfo dwarf_reg; 9543 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + m, dwarf_reg); 9544 context.SetRegisterRegisterOperands (sp_reg, dwarf_reg); 9545 9546 if (!WriteCoreRegOptionalFlags(context, res.result, dwarf_r0 + d, setflags, res.carry_out, res.overflow)) 9547 return false; 9548 } 9549 return true; 9550} 9551 9552 9553// A8.6.7 ADD (register-shifted register) 9554bool 9555EmulateInstructionARM::EmulateADDRegShift (const uint32_t opcode, const ARMEncoding encoding) 9556{ 9557#if 0 9558 if ConditionPassed() then 9559 EncodingSpecificOperations(); 9560 shift_n = UInt(R[s]<7:0>); 9561 shifted = Shift(R[m], shift_t, shift_n, APSR.C); 9562 (result, carry, overflow) = AddWithCarry(R[n], shifted, �0�); 9563 R[d] = result; 9564 if setflags then 9565 APSR.N = result<31>; 9566 APSR.Z = IsZeroBit(result); 9567 APSR.C = carry; 9568 APSR.V = overflow; 9569#endif 9570 9571 bool success = false; 9572 9573 if (ConditionPassed(opcode)) 9574 { 9575 uint32_t d; 9576 uint32_t n; 9577 uint32_t m; 9578 uint32_t s; 9579 bool setflags; 9580 ARM_ShifterType shift_t; 9581 9582 switch (encoding) 9583 { 9584 case eEncodingA1: 9585 // d = UInt(Rd); n = UInt(Rn); m = UInt(Rm); s = UInt(Rs); 9586 d = Bits32 (opcode, 15, 12); 9587 n = Bits32 (opcode, 19, 16); 9588 m = Bits32 (opcode, 3, 0); 9589 s = Bits32 (opcode, 11, 8); 9590 9591 // setflags = (S == �1�); shift_t = DecodeRegShift(type); 9592 setflags = BitIsSet (opcode, 20); 9593 shift_t = DecodeRegShift (Bits32 (opcode, 6, 5)); 9594 9595 // if d == 15 || n == 15 || m == 15 || s == 15 then UNPREDICTABLE; 9596 if ((d == 15) || (m == 15) || (m == 15) || (s == 15)) 9597 return false; 9598 break; 9599 9600 default: 9601 return false; 9602 } 9603 9604 // shift_n = UInt(R[s]<7:0>); 9605 uint32_t Rs = ReadCoreReg (s, &success); 9606 if (!success) 9607 return false; 9608 9609 uint32_t shift_n = Bits32 (Rs, 7, 0); 9610 9611 // shifted = Shift(R[m], shift_t, shift_n, APSR.C); 9612 uint32_t Rm = ReadCoreReg (m, &success); 9613 if (!success) 9614 return false; 9615 9616 uint32_t shifted = Shift (Rm, shift_t, shift_n, APSR_C, &success); 9617 if (!success) 9618 return false; 9619 9620 // (result, carry, overflow) = AddWithCarry(R[n], shifted, �0�); 9621 uint32_t Rn = ReadCoreReg (n, &success); 9622 if (!success) 9623 return false; 9624 9625 AddWithCarryResult res = AddWithCarry (Rn, shifted, 0); 9626 9627 // R[d] = result; 9628 EmulateInstruction::Context context; 9629 context.type = eContextArithmetic; 9630 RegisterInfo reg_n; 9631 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, reg_n); 9632 RegisterInfo reg_m; 9633 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + m, reg_m); 9634 9635 context.SetRegisterRegisterOperands (reg_n, reg_m); 9636 9637 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + d, res.result)) 9638 return false; 9639 9640 // if setflags then 9641 // APSR.N = result<31>; 9642 // APSR.Z = IsZeroBit(result); 9643 // APSR.C = carry; 9644 // APSR.V = overflow; 9645 if (setflags) 9646 return WriteFlags (context, res.result, res.carry_out, res.overflow); 9647 } 9648 return true; 9649} 9650 9651// A8.6.213 SUB (register) 9652bool 9653EmulateInstructionARM::EmulateSUBReg (const uint32_t opcode, const ARMEncoding encoding) 9654{ 9655#if 0 9656 if ConditionPassed() then 9657 EncodingSpecificOperations(); 9658 shifted = Shift(R[m], shift_t, shift_n, APSR.C); 9659 (result, carry, overflow) = AddWithCarry(R[n], NOT(shifted), �1�); 9660 if d == 15 then // Can only occur for ARM encoding 9661 ALUWritePC(result); // setflags is always FALSE here 9662 else 9663 R[d] = result; 9664 if setflags then 9665 APSR.N = result<31>; 9666 APSR.Z = IsZeroBit(result); 9667 APSR.C = carry; 9668 APSR.V = overflow; 9669#endif 9670 9671 bool success = false; 9672 9673 if (ConditionPassed(opcode)) 9674 { 9675 uint32_t d; 9676 uint32_t n; 9677 uint32_t m; 9678 bool setflags; 9679 ARM_ShifterType shift_t; 9680 uint32_t shift_n; 9681 9682 switch (encoding) 9683 { 9684 case eEncodingT1: 9685 // d = UInt(Rd); n = UInt(Rn); m = UInt(Rm); setflags = !InITBlock(); 9686 d = Bits32 (opcode, 2, 0); 9687 n = Bits32 (opcode, 5, 3); 9688 m = Bits32 (opcode, 8, 6); 9689 setflags = !InITBlock(); 9690 9691 // (shift_t, shift_n) = (SRType_LSL, 0); 9692 shift_t = SRType_LSL; 9693 shift_n = 0; 9694 9695 break; 9696 9697 case eEncodingT2: 9698 // if Rd == �1111� && S == �1� then SEE CMP (register); 9699 // if Rn == �1101� then SEE SUB (SP minus register); 9700 // d = UInt(Rd); n = UInt(Rn); m = UInt(Rm); setflags = (S == �1�); 9701 d = Bits32 (opcode, 11, 8); 9702 n = Bits32 (opcode, 19, 16); 9703 m = Bits32 (opcode, 3, 0); 9704 setflags = BitIsSet (opcode, 20); 9705 9706 // (shift_t, shift_n) = DecodeImmShift(type, imm3:imm2); 9707 shift_n = DecodeImmShiftThumb (opcode, shift_t); 9708 9709 // if d == 13 || (d == 15 && S == '0') || n == 15 || BadReg(m) then UNPREDICTABLE; 9710 if ((d == 13) || ((d == 15) && BitIsClear (opcode, 20)) || (n == 15) || BadReg (m)) 9711 return false; 9712 9713 break; 9714 9715 case eEncodingA1: 9716 // if Rn == �1101� then SEE SUB (SP minus register); 9717 // d = UInt(Rd); n = UInt(Rn); m = UInt(Rm); setflags = (S == �1�); 9718 d = Bits32 (opcode, 15, 12); 9719 n = Bits32 (opcode, 19, 16); 9720 m = Bits32 (opcode, 3, 0); 9721 setflags = BitIsSet (opcode, 20); 9722 9723 // if Rd == �1111� && S == �1� then SEE SUBS PC, LR and related instructions; 9724 if ((d == 15) && setflags) 9725 EmulateSUBSPcLrEtc (opcode, encoding); 9726 9727 // (shift_t, shift_n) = DecodeImmShift(type, imm5); 9728 shift_n = DecodeImmShiftARM (opcode, shift_t); 9729 9730 break; 9731 9732 default: 9733 return false; 9734 } 9735 9736 // shifted = Shift(R[m], shift_t, shift_n, APSR.C); 9737 uint32_t Rm = ReadCoreReg (m, &success); 9738 if (!success) 9739 return false; 9740 9741 uint32_t shifted = Shift (Rm, shift_t, shift_n, APSR_C, &success); 9742 if (!success) 9743 return false; 9744 9745 // (result, carry, overflow) = AddWithCarry(R[n], NOT(shifted), �1�); 9746 uint32_t Rn = ReadCoreReg (n, &success); 9747 if (!success) 9748 return false; 9749 9750 AddWithCarryResult res = AddWithCarry (Rn, ~shifted, 1); 9751 9752 // if d == 15 then // Can only occur for ARM encoding 9753 // ALUWritePC(result); // setflags is always FALSE here 9754 // else 9755 // R[d] = result; 9756 // if setflags then 9757 // APSR.N = result<31>; 9758 // APSR.Z = IsZeroBit(result); 9759 // APSR.C = carry; 9760 // APSR.V = overflow; 9761 9762 EmulateInstruction::Context context; 9763 context.type = eContextArithmetic; 9764 RegisterInfo reg_n; 9765 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, reg_n); 9766 RegisterInfo reg_m; 9767 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + m, reg_m); 9768 context.SetRegisterRegisterOperands (reg_n, reg_m); 9769 9770 if (!WriteCoreRegOptionalFlags (context, res.result, dwarf_r0 + d, setflags, res.carry_out, res.overflow)) 9771 return false; 9772 } 9773 return true; 9774} 9775 9776// A8.6.202 STREX 9777// Store Register Exclusive calculates an address from a base register value and an immediate offset, and stores a 9778// word from a register to memory if the executing processor has exclusive access to the memory addressed. 9779bool 9780EmulateInstructionARM::EmulateSTREX (const uint32_t opcode, const ARMEncoding encoding) 9781{ 9782#if 0 9783 if ConditionPassed() then 9784 EncodingSpecificOperations(); NullCheckIfThumbEE(n); 9785 address = R[n] + imm32; 9786 if ExclusiveMonitorsPass(address,4) then 9787 MemA[address,4] = R[t]; 9788 R[d] = 0; 9789 else 9790 R[d] = 1; 9791#endif 9792 9793 bool success = false; 9794 9795 if (ConditionPassed(opcode)) 9796 { 9797 uint32_t d; 9798 uint32_t t; 9799 uint32_t n; 9800 uint32_t imm32; 9801 const uint32_t addr_byte_size = GetAddressByteSize(); 9802 9803 switch (encoding) 9804 { 9805 case eEncodingT1: 9806 // d = UInt(Rd); t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8:�00�, 32); 9807 d = Bits32 (opcode, 11, 8); 9808 t = Bits32 (opcode, 15, 12); 9809 n = Bits32 (opcode, 19, 16); 9810 imm32 = Bits32 (opcode, 7, 0) << 2; 9811 9812 // if BadReg(d) || BadReg(t) || n == 15 then UNPREDICTABLE; 9813 if (BadReg (d) || BadReg (t) || (n == 15)) 9814 return false; 9815 9816 // if d == n || d == t then UNPREDICTABLE; 9817 if ((d == n) || (d == t)) 9818 return false; 9819 9820 break; 9821 9822 case eEncodingA1: 9823 // d = UInt(Rd); t = UInt(Rt); n = UInt(Rn); imm32 = Zeros(32); // Zero offset 9824 d = Bits32 (opcode, 15, 12); 9825 t = Bits32 (opcode, 3, 0); 9826 n = Bits32 (opcode, 19, 16); 9827 imm32 = 0; 9828 9829 // if d == 15 || t == 15 || n == 15 then UNPREDICTABLE; 9830 if ((d == 15) || (t == 15) || (n == 15)) 9831 return false; 9832 9833 // if d == n || d == t then UNPREDICTABLE; 9834 if ((d == n) || (d == t)) 9835 return false; 9836 9837 break; 9838 9839 default: 9840 return false; 9841 } 9842 9843 // address = R[n] + imm32; 9844 uint32_t Rn = ReadCoreReg (n, &success); 9845 if (!success) 9846 return false; 9847 9848 addr_t address = Rn + imm32; 9849 9850 RegisterInfo base_reg; 9851 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg); 9852 RegisterInfo data_reg; 9853 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + t, data_reg); 9854 EmulateInstruction::Context context; 9855 context.type = eContextRegisterStore; 9856 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, imm32); 9857 9858 // if ExclusiveMonitorsPass(address,4) then 9859 // if (ExclusiveMonitorsPass (address, addr_byte_size)) -- For now, for the sake of emulation, we will say this 9860 // always return true. 9861 if (true) 9862 { 9863 // MemA[address,4] = R[t]; 9864 uint32_t Rt = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + t, 0, &success); 9865 if (!success) 9866 return false; 9867 9868 if (!MemAWrite (context, address, Rt, addr_byte_size)) 9869 return false; 9870 9871 // R[d] = 0; 9872 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, 0)) 9873 return false; 9874 } 9875 else 9876 { 9877 // R[d] = 1; 9878 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, 1)) 9879 return false; 9880 } 9881 } 9882 return true; 9883} 9884 9885// A8.6.197 STRB (immediate, ARM) 9886bool 9887EmulateInstructionARM::EmulateSTRBImmARM (const uint32_t opcode, const ARMEncoding encoding) 9888{ 9889#if 0 9890 if ConditionPassed() then 9891 EncodingSpecificOperations(); 9892 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32); 9893 address = if index then offset_addr else R[n]; 9894 MemU[address,1] = R[t]<7:0>; 9895 if wback then R[n] = offset_addr; 9896#endif 9897 9898 bool success = false; 9899 9900 if (ConditionPassed(opcode)) 9901 { 9902 uint32_t t; 9903 uint32_t n; 9904 uint32_t imm32; 9905 bool index; 9906 bool add; 9907 bool wback; 9908 9909 switch (encoding) 9910 { 9911 case eEncodingA1: 9912 // if P == �0� && W == �1� then SEE STRBT; 9913 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32); 9914 t = Bits32 (opcode, 15, 12); 9915 n = Bits32 (opcode, 19, 16); 9916 imm32 = Bits32 (opcode, 11, 0); 9917 9918 // index = (P == �1�); add = (U == �1�); wback = (P == �0�) || (W == �1�); 9919 index = BitIsSet (opcode, 24); 9920 add = BitIsSet (opcode, 23); 9921 wback = BitIsClear (opcode, 24) || BitIsSet (opcode, 21); 9922 9923 // if t == 15 then UNPREDICTABLE; 9924 if (t == 15) 9925 return false; 9926 9927 // if wback && (n == 15 || n == t) then UNPREDICTABLE; 9928 if (wback && ((n == 15) || (n == t))) 9929 return false; 9930 9931 break; 9932 9933 default: 9934 return false; 9935 } 9936 9937 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32); 9938 uint32_t Rn = ReadCoreReg (n, &success); 9939 if (!success) 9940 return false; 9941 9942 addr_t offset_addr; 9943 if (add) 9944 offset_addr = Rn + imm32; 9945 else 9946 offset_addr = Rn - imm32; 9947 9948 // address = if index then offset_addr else R[n]; 9949 addr_t address; 9950 if (index) 9951 address = offset_addr; 9952 else 9953 address = Rn; 9954 9955 // MemU[address,1] = R[t]<7:0>; 9956 uint32_t Rt = ReadCoreReg (t, &success); 9957 if (!success) 9958 return false; 9959 9960 RegisterInfo base_reg; 9961 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg); 9962 RegisterInfo data_reg; 9963 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + t, data_reg); 9964 EmulateInstruction::Context context; 9965 context.type = eContextRegisterStore; 9966 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, address - Rn); 9967 9968 if (!MemUWrite (context, address, Bits32 (Rt, 7, 0), 1)) 9969 return false; 9970 9971 // if wback then R[n] = offset_addr; 9972 if (wback) 9973 { 9974 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr)) 9975 return false; 9976 } 9977 } 9978 return true; 9979} 9980 9981// A8.6.194 STR (immediate, ARM) 9982bool 9983EmulateInstructionARM::EmulateSTRImmARM (const uint32_t opcode, const ARMEncoding encoding) 9984{ 9985#if 0 9986 if ConditionPassed() then 9987 EncodingSpecificOperations(); 9988 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32); 9989 address = if index then offset_addr else R[n]; 9990 MemU[address,4] = if t == 15 then PCStoreValue() else R[t]; 9991 if wback then R[n] = offset_addr; 9992#endif 9993 9994 bool success = false; 9995 9996 if (ConditionPassed(opcode)) 9997 { 9998 uint32_t t; 9999 uint32_t n; 10000 uint32_t imm32; 10001 bool index; 10002 bool add; 10003 bool wback; 10004 10005 const uint32_t addr_byte_size = GetAddressByteSize(); 10006 10007 switch (encoding) 10008 { 10009 case eEncodingA1: 10010 // if P == �0� && W == �1� then SEE STRT; 10011 // if Rn == �1101� && P == �1� && U == �0� && W == �1� && imm12 == �000000000100� then SEE PUSH; 10012 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32); 10013 t = Bits32 (opcode, 15, 12); 10014 n = Bits32 (opcode, 19, 16); 10015 imm32 = Bits32 (opcode, 11, 0); 10016 10017 // index = (P == �1�); add = (U == �1�); wback = (P == �0�) || (W == �1�); 10018 index = BitIsSet (opcode, 24); 10019 add = BitIsSet (opcode, 23); 10020 wback = BitIsClear (opcode, 24) || BitIsSet (opcode, 21); 10021 10022 // if wback && (n == 15 || n == t) then UNPREDICTABLE; 10023 if (wback && ((n == 15) || (n == t))) 10024 return false; 10025 10026 break; 10027 10028 default: 10029 return false; 10030 } 10031 10032 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32); 10033 uint32_t Rn = ReadCoreReg (n, &success); 10034 if (!success) 10035 return false; 10036 10037 addr_t offset_addr; 10038 if (add) 10039 offset_addr = Rn + imm32; 10040 else 10041 offset_addr = Rn - imm32; 10042 10043 // address = if index then offset_addr else R[n]; 10044 addr_t address; 10045 if (index) 10046 address = offset_addr; 10047 else 10048 address = Rn; 10049 10050 RegisterInfo base_reg; 10051 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg); 10052 RegisterInfo data_reg; 10053 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + t, data_reg); 10054 EmulateInstruction::Context context; 10055 context.type = eContextRegisterStore; 10056 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, address - Rn); 10057 10058 // MemU[address,4] = if t == 15 then PCStoreValue() else R[t]; 10059 uint32_t Rt = ReadCoreReg (t, &success); 10060 if (!success) 10061 return false; 10062 10063 if (t == 15) 10064 { 10065 uint32_t pc_value = ReadCoreReg (PC_REG, &success); 10066 if (!success) 10067 return false; 10068 10069 if (!MemUWrite (context, address, pc_value, addr_byte_size)) 10070 return false; 10071 } 10072 else 10073 { 10074 if (!MemUWrite (context, address, Rt, addr_byte_size)) 10075 return false; 10076 } 10077 10078 // if wback then R[n] = offset_addr; 10079 if (wback) 10080 { 10081 context.type = eContextAdjustBaseRegister; 10082 context.SetImmediate (offset_addr); 10083 10084 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr)) 10085 return false; 10086 } 10087 } 10088 return true; 10089} 10090 10091// A8.6.66 LDRD (immediate) 10092// Load Register Dual (immediate) calculates an address from a base register value and an immediate offset, loads two 10093// words from memory, and writes them to two registers. It can use offset, post-indexed, or pre-indexed addressing. 10094bool 10095EmulateInstructionARM::EmulateLDRDImmediate (const uint32_t opcode, const ARMEncoding encoding) 10096{ 10097#if 0 10098 if ConditionPassed() then 10099 EncodingSpecificOperations(); NullCheckIfThumbEE(n); 10100 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32); 10101 address = if index then offset_addr else R[n]; 10102 R[t] = MemA[address,4]; 10103 R[t2] = MemA[address+4,4]; 10104 if wback then R[n] = offset_addr; 10105#endif 10106 10107 bool success = false; 10108 10109 if (ConditionPassed(opcode)) 10110 { 10111 uint32_t t; 10112 uint32_t t2; 10113 uint32_t n; 10114 uint32_t imm32; 10115 bool index; 10116 bool add; 10117 bool wback; 10118 10119 switch (encoding) 10120 { 10121 case eEncodingT1: 10122 //if P == �0� && W == �0� then SEE �Related encodings�; 10123 //if Rn == �1111� then SEE LDRD (literal); 10124 //t = UInt(Rt); t2 = UInt(Rt2); n = UInt(Rn); imm32 = ZeroExtend(imm8:�00�, 32); 10125 t = Bits32 (opcode, 15, 12); 10126 t2 = Bits32 (opcode, 11, 8); 10127 n = Bits32 (opcode, 19, 16); 10128 imm32 = Bits32 (opcode, 7, 0) << 2; 10129 10130 //index = (P == �1�); add = (U == �1�); wback = (W == �1�); 10131 index = BitIsSet (opcode, 24); 10132 add = BitIsSet (opcode, 23); 10133 wback = BitIsSet (opcode, 21); 10134 10135 //if wback && (n == t || n == t2) then UNPREDICTABLE; 10136 if (wback && ((n == t) || (n == t2))) 10137 return false; 10138 10139 //if BadReg(t) || BadReg(t2) || t == t2 then UNPREDICTABLE; 10140 if (BadReg (t) || BadReg (t2) || (t == t2)) 10141 return false; 10142 10143 break; 10144 10145 case eEncodingA1: 10146 //if Rn == �1111� then SEE LDRD (literal); 10147 //if Rt<0> == �1� then UNPREDICTABLE; 10148 //t = UInt(Rt); t2 = t+1; n = UInt(Rn); imm32 = ZeroExtend(imm4H:imm4L, 32); 10149 t = Bits32 (opcode, 15, 12); 10150 if (BitIsSet (t, 0)) 10151 return false; 10152 t2 = t + 1; 10153 n = Bits32 (opcode, 19, 16); 10154 imm32 = (Bits32 (opcode, 11, 8) << 4) | Bits32 (opcode, 3, 0); 10155 10156 //index = (P == �1�); add = (U == �1�); wback = (P == �0�) || (W == �1�); 10157 index = BitIsSet (opcode, 24); 10158 add = BitIsSet (opcode, 23); 10159 wback = BitIsClear (opcode, 24) || BitIsSet (opcode, 21); 10160 10161 //if P == �0� && W == �1� then UNPREDICTABLE; 10162 if (BitIsClear (opcode, 24) && BitIsSet (opcode, 21)) 10163 return false; 10164 10165 //if wback && (n == t || n == t2) then UNPREDICTABLE; 10166 if (wback && ((n == t) || (n == t2))) 10167 return false; 10168 10169 //if t2 == 15 then UNPREDICTABLE; 10170 if (t2 == 15) 10171 return false; 10172 10173 break; 10174 10175 default: 10176 return false; 10177 } 10178 10179 //offset_addr = if add then (R[n] + imm32) else (R[n] - imm32); 10180 uint32_t Rn = ReadCoreReg (n, &success); 10181 if (!success) 10182 return false; 10183 10184 addr_t offset_addr; 10185 if (add) 10186 offset_addr = Rn + imm32; 10187 else 10188 offset_addr = Rn - imm32; 10189 10190 //address = if index then offset_addr else R[n]; 10191 addr_t address; 10192 if (index) 10193 address = offset_addr; 10194 else 10195 address = Rn; 10196 10197 //R[t] = MemA[address,4]; 10198 RegisterInfo base_reg; 10199 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg); 10200 10201 EmulateInstruction::Context context; 10202 context.type = eContextRegisterLoad; 10203 context.SetRegisterPlusOffset (base_reg, address - Rn); 10204 10205 const uint32_t addr_byte_size = GetAddressByteSize(); 10206 uint32_t data = MemARead (context, address, addr_byte_size, 0, &success); 10207 if (!success) 10208 return false; 10209 10210 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data)) 10211 return false; 10212 10213 //R[t2] = MemA[address+4,4]; 10214 10215 context.SetRegisterPlusOffset (base_reg, (address + 4) - Rn); 10216 data = MemARead (context, address + 4, addr_byte_size, 0, &success); 10217 if (!success) 10218 return false; 10219 10220 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t2, data)) 10221 return false; 10222 10223 //if wback then R[n] = offset_addr; 10224 if (wback) 10225 { 10226 context.type = eContextAdjustBaseRegister; 10227 context.SetAddress (offset_addr); 10228 10229 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr)) 10230 return false; 10231 } 10232 } 10233 return true; 10234} 10235 10236// A8.6.68 LDRD (register) 10237// Load Register Dual (register) calculates an address from a base register value and a register offset, loads two 10238// words from memory, and writes them to two registers. It can use offset, post-indexed or pre-indexed addressing. 10239bool 10240EmulateInstructionARM::EmulateLDRDRegister (const uint32_t opcode, const ARMEncoding encoding) 10241{ 10242#if 0 10243 if ConditionPassed() then 10244 EncodingSpecificOperations(); 10245 offset_addr = if add then (R[n] + R[m]) else (R[n] - R[m]); 10246 address = if index then offset_addr else R[n]; 10247 R[t] = MemA[address,4]; 10248 R[t2] = MemA[address+4,4]; 10249 if wback then R[n] = offset_addr; 10250#endif 10251 10252 bool success = false; 10253 10254 if (ConditionPassed(opcode)) 10255 { 10256 uint32_t t; 10257 uint32_t t2; 10258 uint32_t n; 10259 uint32_t m; 10260 bool index; 10261 bool add; 10262 bool wback; 10263 10264 switch (encoding) 10265 { 10266 case eEncodingA1: 10267 // if Rt<0> == �1� then UNPREDICTABLE; 10268 // t = UInt(Rt); t2 = t+1; n = UInt(Rn); m = UInt(Rm); 10269 t = Bits32 (opcode, 15, 12); 10270 if (BitIsSet (t, 0)) 10271 return false; 10272 t2 = t + 1; 10273 n = Bits32 (opcode, 19, 16); 10274 m = Bits32 (opcode, 3, 0); 10275 10276 // index = (P == �1�); add = (U == �1�); wback = (P == �0�) || (W == �1�); 10277 index = BitIsSet (opcode, 24); 10278 add = BitIsSet (opcode, 23); 10279 wback = BitIsClear (opcode, 24) || BitIsSet (opcode, 21); 10280 10281 // if P == �0� && W == �1� then UNPREDICTABLE; 10282 if (BitIsClear (opcode, 24) && BitIsSet (opcode, 21)) 10283 return false; 10284 10285 // if t2 == 15 || m == 15 || m == t || m == t2 then UNPREDICTABLE; 10286 if ((t2 == 15) || (m == 15) || (m == t) || (m == t2)) 10287 return false; 10288 10289 // if wback && (n == 15 || n == t || n == t2) then UNPREDICTABLE; 10290 if (wback && ((n == 15) || (n == t) || (n == t2))) 10291 return false; 10292 10293 // if ArchVersion() < 6 && wback && m == n then UNPREDICTABLE; 10294 if ((ArchVersion() < 6) && wback && (m == n)) 10295 return false; 10296 break; 10297 10298 default: 10299 return false; 10300 } 10301 10302 uint32_t Rn = ReadCoreReg (n, &success); 10303 if (!success) 10304 return false; 10305 RegisterInfo base_reg; 10306 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg); 10307 10308 uint32_t Rm = ReadCoreReg (m, &success); 10309 if (!success) 10310 return false; 10311 RegisterInfo offset_reg; 10312 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + m, offset_reg); 10313 10314 // offset_addr = if add then (R[n] + R[m]) else (R[n] - R[m]); 10315 addr_t offset_addr; 10316 if (add) 10317 offset_addr = Rn + Rm; 10318 else 10319 offset_addr = Rn - Rm; 10320 10321 // address = if index then offset_addr else R[n]; 10322 addr_t address; 10323 if (index) 10324 address = offset_addr; 10325 else 10326 address = Rn; 10327 10328 EmulateInstruction::Context context; 10329 context.type = eContextRegisterLoad; 10330 context.SetRegisterPlusIndirectOffset (base_reg, offset_reg); 10331 10332 // R[t] = MemA[address,4]; 10333 const uint32_t addr_byte_size = GetAddressByteSize(); 10334 uint32_t data = MemARead (context, address, addr_byte_size, 0, &success); 10335 if (!success) 10336 return false; 10337 10338 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data)) 10339 return false; 10340 10341 // R[t2] = MemA[address+4,4]; 10342 10343 data = MemARead (context, address + 4, addr_byte_size, 0, &success); 10344 if (!success) 10345 return false; 10346 10347 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t2, data)) 10348 return false; 10349 10350 // if wback then R[n] = offset_addr; 10351 if (wback) 10352 { 10353 context.type = eContextAdjustBaseRegister; 10354 context.SetAddress (offset_addr); 10355 10356 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr)) 10357 return false; 10358 } 10359 } 10360 return true; 10361} 10362 10363// A8.6.200 STRD (immediate) 10364// Store Register Dual (immediate) calculates an address from a base register value and an immediate offset, and 10365// stores two words from two registers to memory. It can use offset, post-indexed, or pre-indexed addressing. 10366bool 10367EmulateInstructionARM::EmulateSTRDImm (const uint32_t opcode, const ARMEncoding encoding) 10368{ 10369#if 0 10370 if ConditionPassed() then 10371 EncodingSpecificOperations(); NullCheckIfThumbEE(n); 10372 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32); 10373 address = if index then offset_addr else R[n]; 10374 MemA[address,4] = R[t]; 10375 MemA[address+4,4] = R[t2]; 10376 if wback then R[n] = offset_addr; 10377#endif 10378 10379 bool success = false; 10380 10381 if (ConditionPassed(opcode)) 10382 { 10383 uint32_t t; 10384 uint32_t t2; 10385 uint32_t n; 10386 uint32_t imm32; 10387 bool index; 10388 bool add; 10389 bool wback; 10390 10391 switch (encoding) 10392 { 10393 case eEncodingT1: 10394 // if P == �0� && W == �0� then SEE �Related encodings�; 10395 // t = UInt(Rt); t2 = UInt(Rt2); n = UInt(Rn); imm32 = ZeroExtend(imm8:�00�, 32); 10396 t = Bits32 (opcode, 15, 12); 10397 t2 = Bits32 (opcode, 11, 8); 10398 n = Bits32 (opcode, 19, 16); 10399 imm32 = Bits32 (opcode, 7, 0) << 2; 10400 10401 // index = (P == �1�); add = (U == �1�); wback = (W == �1�); 10402 index = BitIsSet (opcode, 24); 10403 add = BitIsSet (opcode, 23); 10404 wback = BitIsSet (opcode, 21); 10405 10406 // if wback && (n == t || n == t2) then UNPREDICTABLE; 10407 if (wback && ((n == t) || (n == t2))) 10408 return false; 10409 10410 // if n == 15 || BadReg(t) || BadReg(t2) then UNPREDICTABLE; 10411 if ((n == 15) || BadReg (t) || BadReg (t2)) 10412 return false; 10413 10414 break; 10415 10416 case eEncodingA1: 10417 // if Rt<0> == �1� then UNPREDICTABLE; 10418 // t = UInt(Rt); t2 = t+1; n = UInt(Rn); imm32 = ZeroExtend(imm4H:imm4L, 32); 10419 t = Bits32 (opcode, 15, 12); 10420 if (BitIsSet (t, 0)) 10421 return false; 10422 10423 t2 = t + 1; 10424 n = Bits32 (opcode, 19, 16); 10425 imm32 = (Bits32 (opcode, 11, 8) << 4) | Bits32 (opcode, 3, 0); 10426 10427 // index = (P == �1�); add = (U == �1�); wback = (P == �0�) || (W == �1�); 10428 index = BitIsSet (opcode, 24); 10429 add = BitIsSet (opcode, 23); 10430 wback = BitIsClear (opcode, 24) || BitIsSet (opcode, 21); 10431 10432 // if P == �0� && W == �1� then UNPREDICTABLE; 10433 if (BitIsClear (opcode, 24) && BitIsSet (opcode, 21)) 10434 return false; 10435 10436 // if wback && (n == 15 || n == t || n == t2) then UNPREDICTABLE; 10437 if (wback && ((n == 15) || (n == t) || (n == t2))) 10438 return false; 10439 10440 // if t2 == 15 then UNPREDICTABLE; 10441 if (t2 == 15) 10442 return false; 10443 10444 break; 10445 10446 default: 10447 return false; 10448 } 10449 10450 RegisterInfo base_reg; 10451 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg); 10452 10453 uint32_t Rn = ReadCoreReg (n, &success); 10454 if (!success) 10455 return false; 10456 10457 //offset_addr = if add then (R[n] + imm32) else (R[n] - imm32); 10458 addr_t offset_addr; 10459 if (add) 10460 offset_addr = Rn + imm32; 10461 else 10462 offset_addr = Rn - imm32; 10463 10464 //address = if index then offset_addr else R[n]; 10465 addr_t address; 10466 if (index) 10467 address = offset_addr; 10468 else 10469 address = Rn; 10470 10471 //MemA[address,4] = R[t]; 10472 RegisterInfo data_reg; 10473 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + t, data_reg); 10474 10475 uint32_t data = ReadCoreReg (t, &success); 10476 if (!success) 10477 return false; 10478 10479 EmulateInstruction::Context context; 10480 context.type = eContextRegisterStore; 10481 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, address - Rn); 10482 10483 const uint32_t addr_byte_size = GetAddressByteSize(); 10484 10485 if (!MemAWrite (context, address, data, addr_byte_size)) 10486 return false; 10487 10488 //MemA[address+4,4] = R[t2]; 10489 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + t2, data_reg); 10490 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, (address + 4) - Rn); 10491 10492 data = ReadCoreReg (t2, &success); 10493 if (!success) 10494 return false; 10495 10496 if (!MemAWrite (context, address + 4, data, addr_byte_size)) 10497 return false; 10498 10499 //if wback then R[n] = offset_addr; 10500 if (wback) 10501 { 10502 context.type = eContextAdjustBaseRegister; 10503 context.SetAddress (offset_addr); 10504 10505 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr)) 10506 return false; 10507 } 10508 } 10509 return true; 10510} 10511 10512 10513// A8.6.201 STRD (register) 10514bool 10515EmulateInstructionARM::EmulateSTRDReg (const uint32_t opcode, const ARMEncoding encoding) 10516{ 10517#if 0 10518 if ConditionPassed() then 10519 EncodingSpecificOperations(); 10520 offset_addr = if add then (R[n] + R[m]) else (R[n] - R[m]); 10521 address = if index then offset_addr else R[n]; 10522 MemA[address,4] = R[t]; 10523 MemA[address+4,4] = R[t2]; 10524 if wback then R[n] = offset_addr; 10525#endif 10526 10527 bool success = false; 10528 10529 if (ConditionPassed(opcode)) 10530 { 10531 uint32_t t; 10532 uint32_t t2; 10533 uint32_t n; 10534 uint32_t m; 10535 bool index; 10536 bool add; 10537 bool wback; 10538 10539 switch (encoding) 10540 { 10541 case eEncodingA1: 10542 // if Rt<0> == �1� then UNPREDICTABLE; 10543 // t = UInt(Rt); t2 = t+1; n = UInt(Rn); m = UInt(Rm); 10544 t = Bits32 (opcode, 15, 12); 10545 if (BitIsSet (t, 0)) 10546 return false; 10547 10548 t2 = t+1; 10549 n = Bits32 (opcode, 19, 16); 10550 m = Bits32 (opcode, 3, 0); 10551 10552 // index = (P == �1�); add = (U == �1�); wback = (P == �0�) || (W == �1�); 10553 index = BitIsSet (opcode, 24); 10554 add = BitIsSet (opcode, 23); 10555 wback = BitIsClear (opcode, 24) || BitIsSet (opcode, 21); 10556 10557 // if P == �0� && W == �1� then UNPREDICTABLE; 10558 if (BitIsClear (opcode, 24) && BitIsSet (opcode, 21)) 10559 return false; 10560 10561 // if t2 == 15 || m == 15 then UNPREDICTABLE; 10562 if ((t2 == 15) || (m == 15)) 10563 return false; 10564 10565 // if wback && (n == 15 || n == t || n == t2) then UNPREDICTABLE; 10566 if (wback && ((n == 15) || (n == t) || (n == t2))) 10567 return false; 10568 10569 // if ArchVersion() < 6 && wback && m == n then UNPREDICTABLE; 10570 if ((ArchVersion() < 6) && wback && (m == n)) 10571 return false; 10572 10573 break; 10574 10575 default: 10576 return false; 10577 } 10578 10579 RegisterInfo base_reg; 10580 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg); 10581 RegisterInfo offset_reg; 10582 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + m, offset_reg); 10583 RegisterInfo data_reg; 10584 10585 uint32_t Rn = ReadCoreReg (n, &success); 10586 if (!success) 10587 return false; 10588 10589 uint32_t Rm = ReadCoreReg (m, &success); 10590 if (!success) 10591 return false; 10592 10593 // offset_addr = if add then (R[n] + R[m]) else (R[n] - R[m]); 10594 addr_t offset_addr; 10595 if (add) 10596 offset_addr = Rn + Rm; 10597 else 10598 offset_addr = Rn - Rm; 10599 10600 // address = if index then offset_addr else R[n]; 10601 addr_t address; 10602 if (index) 10603 address = offset_addr; 10604 else 10605 address = Rn; 10606 // MemA[address,4] = R[t]; 10607 uint32_t Rt = ReadCoreReg (t, &success); 10608 if (!success) 10609 return false; 10610 10611 EmulateInstruction::Context context; 10612 context.type = eContextRegisterStore; 10613 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + t, data_reg); 10614 context.SetRegisterToRegisterPlusIndirectOffset (base_reg, offset_reg, data_reg); 10615 10616 const uint32_t addr_byte_size = GetAddressByteSize(); 10617 10618 if (!MemAWrite (context, address, Rt, addr_byte_size)) 10619 return false; 10620 10621 // MemA[address+4,4] = R[t2]; 10622 uint32_t Rt2 = ReadCoreReg (t2, &success); 10623 if (!success) 10624 return false; 10625 10626 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + t2, data_reg); 10627 10628 context.SetRegisterToRegisterPlusIndirectOffset (base_reg, offset_reg, data_reg); 10629 10630 if (!MemAWrite (context, address + 4, Rt2, addr_byte_size)) 10631 return false; 10632 10633 // if wback then R[n] = offset_addr; 10634 if (wback) 10635 { 10636 context.type = eContextAdjustBaseRegister; 10637 context.SetAddress (offset_addr); 10638 10639 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr)) 10640 return false; 10641 10642 } 10643 } 10644 return true; 10645} 10646 10647// A8.6.319 VLDM 10648// Vector Load Multiple loads multiple extension registers from consecutive memory locations using an address from 10649// an ARM core register. 10650bool 10651EmulateInstructionARM::EmulateVLDM (const uint32_t opcode, const ARMEncoding encoding) 10652{ 10653#if 0 10654 if ConditionPassed() then 10655 EncodingSpecificOperations(); CheckVFPEnabled(TRUE); NullCheckIfThumbEE(n); 10656 address = if add then R[n] else R[n]-imm32; 10657 if wback then R[n] = if add then R[n]+imm32 else R[n]-imm32; 10658 for r = 0 to regs-1 10659 if single_regs then 10660 S[d+r] = MemA[address,4]; address = address+4; 10661 else 10662 word1 = MemA[address,4]; word2 = MemA[address+4,4]; address = address+8; 10663 // Combine the word-aligned words in the correct order for current endianness. 10664 D[d+r] = if BigEndian() then word1:word2 else word2:word1; 10665#endif 10666 10667 bool success = false; 10668 10669 if (ConditionPassed(opcode)) 10670 { 10671 bool single_regs; 10672 bool add; 10673 bool wback; 10674 uint32_t d; 10675 uint32_t n; 10676 uint32_t imm32; 10677 uint32_t regs; 10678 10679 switch (encoding) 10680 { 10681 case eEncodingT1: 10682 case eEncodingA1: 10683 // if P == �0� && U == �0� && W == �0� then SEE �Related encodings�; 10684 // if P == �0� && U == �1� && W == �1� && Rn == �1101� then SEE VPOP; 10685 // if P == �1� && W == �0� then SEE VLDR; 10686 // if P == U && W == �1� then UNDEFINED; 10687 if ((Bit32 (opcode, 24) == Bit32 (opcode, 23)) && BitIsSet (opcode, 21)) 10688 return false; 10689 10690 // // Remaining combinations are PUW = 010 (IA without !), 011 (IA with !), 101 (DB with !) 10691 // single_regs = FALSE; add = (U == �1�); wback = (W == �1�); 10692 single_regs = false; 10693 add = BitIsSet (opcode, 23); 10694 wback = BitIsSet (opcode, 21); 10695 10696 // d = UInt(D:Vd); n = UInt(Rn); imm32 = ZeroExtend(imm8:�00�, 32); 10697 d = (Bit32 (opcode, 22) << 4) | Bits32 (opcode, 15, 12); 10698 n = Bits32 (opcode, 19, 16); 10699 imm32 = Bits32 (opcode, 7, 0) << 2; 10700 10701 // regs = UInt(imm8) DIV 2; // If UInt(imm8) is odd, see �FLDMX�. 10702 regs = Bits32 (opcode, 7, 0) / 2; 10703 10704 // if n == 15 && (wback || CurrentInstrSet() != InstrSet_ARM) then UNPREDICTABLE; 10705 if (n == 15 && (wback || CurrentInstrSet() != eModeARM)) 10706 return false; 10707 10708 // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE; 10709 if ((regs == 0) || (regs > 16) || ((d + regs) > 32)) 10710 return false; 10711 10712 break; 10713 10714 case eEncodingT2: 10715 case eEncodingA2: 10716 // if P == �0� && U == �0� && W == �0� then SEE �Related encodings�; 10717 // if P == �0� && U == �1� && W == �1� && Rn == �1101� then SEE VPOP; 10718 // if P == �1� && W == �0� then SEE VLDR; 10719 // if P == U && W == �1� then UNDEFINED; 10720 if ((Bit32 (opcode, 24) == Bit32 (opcode, 23)) && BitIsSet (opcode, 21)) 10721 return false; 10722 10723 // // Remaining combinations are PUW = 010 (IA without !), 011 (IA with !), 101 (DB with !) 10724 // single_regs = TRUE; add = (U == �1�); wback = (W == �1�); d = UInt(Vd:D); n = UInt(Rn); 10725 single_regs = true; 10726 add = BitIsSet (opcode, 23); 10727 wback = BitIsSet (opcode, 21); 10728 d = (Bits32 (opcode, 15, 12) << 1) | Bit32 (opcode, 22); 10729 n = Bits32 (opcode, 19, 16); 10730 10731 // imm32 = ZeroExtend(imm8:�00�, 32); regs = UInt(imm8); 10732 imm32 = Bits32 (opcode, 7, 0) << 2; 10733 regs = Bits32 (opcode, 7, 0); 10734 10735 // if n == 15 && (wback || CurrentInstrSet() != InstrSet_ARM) then UNPREDICTABLE; 10736 if ((n == 15) && (wback || (CurrentInstrSet() != eModeARM))) 10737 return false; 10738 10739 // if regs == 0 || (d+regs) > 32 then UNPREDICTABLE; 10740 if ((regs == 0) || ((d + regs) > 32)) 10741 return false; 10742 break; 10743 10744 default: 10745 return false; 10746 } 10747 10748 RegisterInfo base_reg; 10749 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg); 10750 10751 uint32_t Rn = ReadCoreReg (n, &success); 10752 if (!success) 10753 return false; 10754 10755 // address = if add then R[n] else R[n]-imm32; 10756 addr_t address; 10757 if (add) 10758 address = Rn; 10759 else 10760 address = Rn - imm32; 10761 10762 // if wback then R[n] = if add then R[n]+imm32 else R[n]-imm32; 10763 EmulateInstruction::Context context; 10764 10765 if (wback) 10766 { 10767 uint32_t value; 10768 if (add) 10769 value = Rn + imm32; 10770 else 10771 value = Rn - imm32; 10772 10773 context.type = eContextAdjustBaseRegister; 10774 context.SetImmediateSigned (value - Rn); 10775 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, value)) 10776 return false; 10777 10778 } 10779 10780 const uint32_t addr_byte_size = GetAddressByteSize(); 10781 uint32_t start_reg = single_regs ? dwarf_s0 : dwarf_d0; 10782 10783 context.type = eContextRegisterLoad; 10784 10785 // for r = 0 to regs-1 10786 for (uint32_t r = 0; r < regs; ++r) 10787 { 10788 if (single_regs) 10789 { 10790 // S[d+r] = MemA[address,4]; address = address+4; 10791 context.SetRegisterPlusOffset (base_reg, address - Rn); 10792 10793 uint32_t data = MemARead (context, address, addr_byte_size, 0, &success); 10794 if (!success) 10795 return false; 10796 10797 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, start_reg + d + r, data)) 10798 return false; 10799 10800 address = address + 4; 10801 } 10802 else 10803 { 10804 // word1 = MemA[address,4]; word2 = MemA[address+4,4]; address = address+8; 10805 context.SetRegisterPlusOffset (base_reg, address - Rn); 10806 uint32_t word1 = MemARead (context, address, addr_byte_size, 0, &success); 10807 if (!success) 10808 return false; 10809 10810 context.SetRegisterPlusOffset (base_reg, (address + 4) - Rn); 10811 uint32_t word2 = MemARead (context, address + 4, addr_byte_size, 0, &success); 10812 if (!success) 10813 return false; 10814 10815 address = address + 8; 10816 // // Combine the word-aligned words in the correct order for current endianness. 10817 // D[d+r] = if BigEndian() then word1:word2 else word2:word1; 10818 uint64_t data; 10819 if (GetByteOrder() == eByteOrderBig) 10820 { 10821 data = word1; 10822 data = (data << 32) | word2; 10823 } 10824 else 10825 { 10826 data = word2; 10827 data = (data << 32) | word1; 10828 } 10829 10830 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, start_reg + d + r, data)) 10831 return false; 10832 } 10833 } 10834 } 10835 return true; 10836} 10837 10838// A8.6.399 VSTM 10839// Vector Store Multiple stores multiple extension registers to consecutive memory locations using an address from an 10840// ARM core register. 10841bool 10842EmulateInstructionARM::EmulateVSTM (const uint32_t opcode, const ARMEncoding encoding) 10843{ 10844#if 0 10845 if ConditionPassed() then 10846 EncodingSpecificOperations(); CheckVFPEnabled(TRUE); NullCheckIfThumbEE(n); 10847 address = if add then R[n] else R[n]-imm32; 10848 if wback then R[n] = if add then R[n]+imm32 else R[n]-imm32; 10849 for r = 0 to regs-1 10850 if single_regs then 10851 MemA[address,4] = S[d+r]; address = address+4; 10852 else 10853 // Store as two word-aligned words in the correct order for current endianness. 10854 MemA[address,4] = if BigEndian() then D[d+r]<63:32> else D[d+r]<31:0>; 10855 MemA[address+4,4] = if BigEndian() then D[d+r]<31:0> else D[d+r]<63:32>; 10856 address = address+8; 10857#endif 10858 10859 bool success = false; 10860 10861 if (ConditionPassed (opcode)) 10862 { 10863 bool single_regs; 10864 bool add; 10865 bool wback; 10866 uint32_t d; 10867 uint32_t n; 10868 uint32_t imm32; 10869 uint32_t regs; 10870 10871 switch (encoding) 10872 { 10873 case eEncodingT1: 10874 case eEncodingA1: 10875 // if P == �0� && U == �0� && W == �0� then SEE �Related encodings�; 10876 // if P == �1� && U == �0� && W == �1� && Rn == �1101� then SEE VPUSH; 10877 // if P == �1� && W == �0� then SEE VSTR; 10878 // if P == U && W == �1� then UNDEFINED; 10879 if ((Bit32 (opcode, 24) == Bit32 (opcode, 23)) && BitIsSet (opcode, 21)) 10880 return false; 10881 10882 // // Remaining combinations are PUW = 010 (IA without !), 011 (IA with !), 101 (DB with !) 10883 // single_regs = FALSE; add = (U == �1�); wback = (W == �1�); 10884 single_regs = false; 10885 add = BitIsSet (opcode, 23); 10886 wback = BitIsSet (opcode, 21); 10887 10888 // d = UInt(D:Vd); n = UInt(Rn); imm32 = ZeroExtend(imm8:�00�, 32); 10889 d = (Bit32 (opcode, 22) << 4) | Bits32 (opcode, 15, 12); 10890 n = Bits32 (opcode, 19, 16); 10891 imm32 = Bits32 (opcode, 7, 0) << 2; 10892 10893 // regs = UInt(imm8) DIV 2; // If UInt(imm8) is odd, see �FSTMX�. 10894 regs = Bits32 (opcode, 7, 0) / 2; 10895 10896 // if n == 15 && (wback || CurrentInstrSet() != InstrSet_ARM) then UNPREDICTABLE; 10897 if ((n == 15) && (wback || (CurrentInstrSet() != eModeARM))) 10898 return false; 10899 10900 // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE; 10901 if ((regs == 0) || (regs > 16) || ((d + regs) > 32)) 10902 return false; 10903 10904 break; 10905 10906 case eEncodingT2: 10907 case eEncodingA2: 10908 // if P == �0� && U == �0� && W == �0� then SEE �Related encodings�; 10909 // if P == �1� && U == �0� && W == �1� && Rn == �1101� then SEE VPUSH; 10910 // if P == �1� && W == �0� then SEE VSTR; 10911 // if P == U && W == �1� then UNDEFINED; 10912 if ((Bit32 (opcode, 24) == Bit32 (opcode, 23)) && BitIsSet (opcode, 21)) 10913 return false; 10914 10915 // // Remaining combinations are PUW = 010 (IA without !), 011 (IA with !), 101 (DB with !) 10916 // single_regs = TRUE; add = (U == �1�); wback = (W == �1�); d = UInt(Vd:D); n = UInt(Rn); 10917 single_regs = true; 10918 add = BitIsSet (opcode, 23); 10919 wback = BitIsSet (opcode, 21); 10920 d = (Bits32 (opcode, 15, 12) << 1) | Bit32 (opcode, 22); 10921 n = Bits32 (opcode, 19, 16); 10922 10923 // imm32 = ZeroExtend(imm8:�00�, 32); regs = UInt(imm8); 10924 imm32 = Bits32 (opcode, 7, 0) << 2; 10925 regs = Bits32 (opcode, 7, 0); 10926 10927 // if n == 15 && (wback || CurrentInstrSet() != InstrSet_ARM) then UNPREDICTABLE; 10928 if ((n == 15) && (wback || (CurrentInstrSet () != eModeARM))) 10929 return false; 10930 10931 // if regs == 0 || (d+regs) > 32 then UNPREDICTABLE; 10932 if ((regs == 0) || ((d + regs) > 32)) 10933 return false; 10934 10935 break; 10936 10937 default: 10938 return false; 10939 } 10940 10941 RegisterInfo base_reg; 10942 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg); 10943 10944 uint32_t Rn = ReadCoreReg (n, &success); 10945 if (!success) 10946 return false; 10947 10948 // address = if add then R[n] else R[n]-imm32; 10949 addr_t address; 10950 if (add) 10951 address = Rn; 10952 else 10953 address = Rn - imm32; 10954 10955 EmulateInstruction::Context context; 10956 // if wback then R[n] = if add then R[n]+imm32 else R[n]-imm32; 10957 if (wback) 10958 { 10959 uint32_t value; 10960 if (add) 10961 value = Rn + imm32; 10962 else 10963 value = Rn - imm32; 10964 10965 context.type = eContextAdjustBaseRegister; 10966 context.SetRegisterPlusOffset (base_reg, value - Rn); 10967 10968 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, value)) 10969 return false; 10970 } 10971 10972 const uint32_t addr_byte_size = GetAddressByteSize(); 10973 uint32_t start_reg = single_regs ? dwarf_s0 : dwarf_d0; 10974 10975 context.type = eContextRegisterStore; 10976 // for r = 0 to regs-1 10977 for (uint32_t r = 0; r < regs; ++r) 10978 { 10979 10980 if (single_regs) 10981 { 10982 // MemA[address,4] = S[d+r]; address = address+4; 10983 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, start_reg + d + r, 0, &success); 10984 if (!success) 10985 return false; 10986 10987 RegisterInfo data_reg; 10988 GetRegisterInfo (eRegisterKindDWARF, start_reg + d + r, data_reg); 10989 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, address - Rn); 10990 if (!MemAWrite (context, address, data, addr_byte_size)) 10991 return false; 10992 10993 address = address + 4; 10994 } 10995 else 10996 { 10997 // // Store as two word-aligned words in the correct order for current endianness. 10998 // MemA[address,4] = if BigEndian() then D[d+r]<63:32> else D[d+r]<31:0>; 10999 // MemA[address+4,4] = if BigEndian() then D[d+r]<31:0> else D[d+r]<63:32>; 11000 uint64_t data = ReadRegisterUnsigned (eRegisterKindDWARF, start_reg + d + r, 0, &success); 11001 if (!success) 11002 return false; 11003 11004 RegisterInfo data_reg; 11005 GetRegisterInfo (eRegisterKindDWARF, start_reg + d + r, data_reg); 11006 11007 if (GetByteOrder() == eByteOrderBig) 11008 { 11009 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, address - Rn); 11010 if (!MemAWrite (context, address, Bits64 (data, 63, 32), addr_byte_size)) 11011 return false; 11012 11013 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, (address + 4) - Rn); 11014 if (!MemAWrite (context, address+ 4, Bits64 (data, 31, 0), addr_byte_size)) 11015 return false; 11016 } 11017 else 11018 { 11019 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, address - Rn); 11020 if (!MemAWrite (context, address, Bits64 (data, 31, 0), addr_byte_size)) 11021 return false; 11022 11023 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, (address + 4) - Rn); 11024 if (!MemAWrite (context, address + 4, Bits64 (data, 63, 32), addr_byte_size)) 11025 return false; 11026 } 11027 // address = address+8; 11028 address = address + 8; 11029 } 11030 } 11031 } 11032 return true; 11033} 11034 11035// A8.6.320 11036// This instruciton loads a single extension register fronm memory, using an address from an ARM core register, with 11037// an optional offset. 11038bool 11039EmulateInstructionARM::EmulateVLDR (const uint32_t opcode, ARMEncoding encoding) 11040{ 11041#if 0 11042 if ConditionPassed() then 11043 EncodingSpecificOperations(); CheckVFPEnabled(TRUE); NullCheckIfThumbEE(n); 11044 base = if n == 15 then Align(PC,4) else R[n]; 11045 address = if add then (base + imm32) else (base - imm32); 11046 if single_reg then 11047 S[d] = MemA[address,4]; 11048 else 11049 word1 = MemA[address,4]; word2 = MemA[address+4,4]; 11050 // Combine the word-aligned words in the correct order for current endianness. 11051 D[d] = if BigEndian() then word1:word2 else word2:word1; 11052#endif 11053 11054 bool success = false; 11055 11056 if (ConditionPassed (opcode)) 11057 { 11058 bool single_reg; 11059 bool add; 11060 uint32_t imm32; 11061 uint32_t d; 11062 uint32_t n; 11063 11064 switch (encoding) 11065 { 11066 case eEncodingT1: 11067 case eEncodingA1: 11068 // single_reg = FALSE; add = (U == �1�); imm32 = ZeroExtend(imm8:�00�, 32); 11069 single_reg = false; 11070 add = BitIsSet (opcode, 23); 11071 imm32 = Bits32 (opcode, 7, 0) << 2; 11072 11073 // d = UInt(D:Vd); n = UInt(Rn); 11074 d = (Bit32 (opcode, 22) << 4) | Bits32 (opcode, 15, 12); 11075 n = Bits32 (opcode, 19, 16); 11076 11077 break; 11078 11079 case eEncodingT2: 11080 case eEncodingA2: 11081 // single_reg = TRUE; add = (U == �1�); imm32 = ZeroExtend(imm8:�00�, 32); 11082 single_reg = true; 11083 add = BitIsSet (opcode, 23); 11084 imm32 = Bits32 (opcode, 7, 0) << 2; 11085 11086 // d = UInt(Vd:D); n = UInt(Rn); 11087 d = (Bits32 (opcode, 15, 12) << 1) | Bit32 (opcode, 22); 11088 n = Bits32 (opcode, 19, 16); 11089 11090 break; 11091 11092 default: 11093 return false; 11094 } 11095 RegisterInfo base_reg; 11096 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg); 11097 11098 uint32_t Rn = ReadCoreReg (n, &success); 11099 if (!success) 11100 return false; 11101 11102 // base = if n == 15 then Align(PC,4) else R[n]; 11103 uint32_t base; 11104 if (n == 15) 11105 base = AlignPC (Rn); 11106 else 11107 base = Rn; 11108 11109 // address = if add then (base + imm32) else (base - imm32); 11110 addr_t address; 11111 if (add) 11112 address = base + imm32; 11113 else 11114 address = base - imm32; 11115 11116 const uint32_t addr_byte_size = GetAddressByteSize(); 11117 uint32_t start_reg = single_reg ? dwarf_s0 : dwarf_d0; 11118 11119 EmulateInstruction::Context context; 11120 context.type = eContextRegisterLoad; 11121 context.SetRegisterPlusOffset (base_reg, address - base); 11122 11123 if (single_reg) 11124 { 11125 // S[d] = MemA[address,4]; 11126 uint32_t data = MemARead (context, address, addr_byte_size, 0, &success); 11127 if (!success) 11128 return false; 11129 11130 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, start_reg + d, data)) 11131 return false; 11132 } 11133 else 11134 { 11135 // word1 = MemA[address,4]; word2 = MemA[address+4,4]; 11136 uint32_t word1 = MemARead (context, address, addr_byte_size, 0, &success); 11137 if (!success) 11138 return false; 11139 11140 context.SetRegisterPlusOffset (base_reg, (address + 4) - base); 11141 uint32_t word2 = MemARead (context, address + 4, addr_byte_size, 0, &success); 11142 if (!success) 11143 return false; 11144 // // Combine the word-aligned words in the correct order for current endianness. 11145 // D[d] = if BigEndian() then word1:word2 else word2:word1; 11146 uint64_t data64; 11147 if (GetByteOrder() == eByteOrderBig) 11148 { 11149 data64 = word1; 11150 data64 = (data64 << 32) | word2; 11151 } 11152 else 11153 { 11154 data64 = word2; 11155 data64 = (data64 << 32) | word1; 11156 } 11157 11158 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, start_reg + d, data64)) 11159 return false; 11160 } 11161 } 11162 return true; 11163} 11164 11165// A8.6.400 VSTR 11166// This instruction stores a signle extension register to memory, using an address from an ARM core register, with an 11167// optional offset. 11168bool 11169EmulateInstructionARM::EmulateVSTR (const uint32_t opcode, ARMEncoding encoding) 11170{ 11171#if 0 11172 if ConditionPassed() then 11173 EncodingSpecificOperations(); CheckVFPEnabled(TRUE); NullCheckIfThumbEE(n); 11174 address = if add then (R[n] + imm32) else (R[n] - imm32); 11175 if single_reg then 11176 MemA[address,4] = S[d]; 11177 else 11178 // Store as two word-aligned words in the correct order for current endianness. 11179 MemA[address,4] = if BigEndian() then D[d]<63:32> else D[d]<31:0>; 11180 MemA[address+4,4] = if BigEndian() then D[d]<31:0> else D[d]<63:32>; 11181#endif 11182 11183 bool success = false; 11184 11185 if (ConditionPassed (opcode)) 11186 { 11187 bool single_reg; 11188 bool add; 11189 uint32_t imm32; 11190 uint32_t d; 11191 uint32_t n; 11192 11193 switch (encoding) 11194 { 11195 case eEncodingT1: 11196 case eEncodingA1: 11197 // single_reg = FALSE; add = (U == �1�); imm32 = ZeroExtend(imm8:�00�, 32); 11198 single_reg = false; 11199 add = BitIsSet (opcode, 23); 11200 imm32 = Bits32 (opcode, 7, 0) << 2; 11201 11202 // d = UInt(D:Vd); n = UInt(Rn); 11203 d = (Bit32 (opcode, 22) << 4) | Bits32 (opcode, 15, 12); 11204 n = Bits32 (opcode, 19, 16); 11205 11206 // if n == 15 && CurrentInstrSet() != InstrSet_ARM then UNPREDICTABLE; 11207 if ((n == 15) && (CurrentInstrSet() != eModeARM)) 11208 return false; 11209 11210 break; 11211 11212 case eEncodingT2: 11213 case eEncodingA2: 11214 // single_reg = TRUE; add = (U == �1�); imm32 = ZeroExtend(imm8:�00�, 32); 11215 single_reg = true; 11216 add = BitIsSet (opcode, 23); 11217 imm32 = Bits32 (opcode, 7, 0) << 2; 11218 11219 // d = UInt(Vd:D); n = UInt(Rn); 11220 d = (Bits32 (opcode, 15, 12) << 1) | Bit32 (opcode, 22); 11221 n = Bits32 (opcode, 19, 16); 11222 11223 // if n == 15 && CurrentInstrSet() != InstrSet_ARM then UNPREDICTABLE; 11224 if ((n == 15) && (CurrentInstrSet() != eModeARM)) 11225 return false; 11226 11227 break; 11228 11229 default: 11230 return false; 11231 } 11232 11233 RegisterInfo base_reg; 11234 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg); 11235 11236 uint32_t Rn = ReadCoreReg (n, &success); 11237 if (!success) 11238 return false; 11239 11240 // address = if add then (R[n] + imm32) else (R[n] - imm32); 11241 addr_t address; 11242 if (add) 11243 address = Rn + imm32; 11244 else 11245 address = Rn - imm32; 11246 11247 const uint32_t addr_byte_size = GetAddressByteSize(); 11248 uint32_t start_reg = single_reg ? dwarf_s0 : dwarf_d0; 11249 11250 RegisterInfo data_reg; 11251 GetRegisterInfo (eRegisterKindDWARF, start_reg + d, data_reg); 11252 EmulateInstruction::Context context; 11253 context.type = eContextRegisterStore; 11254 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, address - Rn); 11255 11256 if (single_reg) 11257 { 11258 // MemA[address,4] = S[d]; 11259 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, start_reg + d, 0, &success); 11260 if (!success) 11261 return false; 11262 11263 if (!MemAWrite (context, address, data, addr_byte_size)) 11264 return false; 11265 } 11266 else 11267 { 11268 // // Store as two word-aligned words in the correct order for current endianness. 11269 // MemA[address,4] = if BigEndian() then D[d]<63:32> else D[d]<31:0>; 11270 // MemA[address+4,4] = if BigEndian() then D[d]<31:0> else D[d]<63:32>; 11271 uint64_t data = ReadRegisterUnsigned (eRegisterKindDWARF, start_reg + d, 0, &success); 11272 if (!success) 11273 return false; 11274 11275 if (GetByteOrder() == eByteOrderBig) 11276 { 11277 if (!MemAWrite (context, address, Bits64 (data, 63, 32), addr_byte_size)) 11278 return false; 11279 11280 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, (address + 4) - Rn); 11281 if (!MemAWrite (context, address + 4, Bits64 (data, 31, 0), addr_byte_size)) 11282 return false; 11283 } 11284 else 11285 { 11286 if (!MemAWrite (context, address, Bits64 (data, 31, 0), addr_byte_size)) 11287 return false; 11288 11289 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, (address + 4) - Rn); 11290 if (!MemAWrite (context, address + 4, Bits64 (data, 63, 32), addr_byte_size)) 11291 return false; 11292 } 11293 } 11294 } 11295 return true; 11296} 11297 11298// A8.6.307 VLDI1 (multiple single elements) 11299// This instruction loads elements from memory into one, two, three or four registers, without de-interleaving. Every 11300// element of each register is loaded. 11301bool 11302EmulateInstructionARM::EmulateVLD1Multiple (const uint32_t opcode, ARMEncoding encoding) 11303{ 11304#if 0 11305 if ConditionPassed() then 11306 EncodingSpecificOperations(); CheckAdvSIMDEnabled(); NullCheckIfThumbEE(n); 11307 address = R[n]; if (address MOD alignment) != 0 then GenerateAlignmentException(); 11308 if wback then R[n] = R[n] + (if register_index then R[m] else 8*regs); 11309 for r = 0 to regs-1 11310 for e = 0 to elements-1 11311 Elem[D[d+r],e,esize] = MemU[address,ebytes]; 11312 address = address + ebytes; 11313#endif 11314 11315 bool success = false; 11316 11317 if (ConditionPassed (opcode)) 11318 { 11319 uint32_t regs; 11320 uint32_t alignment; 11321 uint32_t ebytes; 11322 uint32_t esize; 11323 uint32_t elements; 11324 uint32_t d; 11325 uint32_t n; 11326 uint32_t m; 11327 bool wback; 11328 bool register_index; 11329 11330 switch (encoding) 11331 { 11332 case eEncodingT1: 11333 case eEncodingA1: 11334 { 11335 // case type of 11336 // when �0111� 11337 // regs = 1; if align<1> == �1� then UNDEFINED; 11338 // when �1010� 11339 // regs = 2; if align == �11� then UNDEFINED; 11340 // when �0110� 11341 // regs = 3; if align<1> == �1� then UNDEFINED; 11342 // when �0010� 11343 // regs = 4; 11344 // otherwise 11345 // SEE �Related encodings�; 11346 uint32_t type = Bits32 (opcode, 11, 8); 11347 uint32_t align = Bits32 (opcode, 5, 4); 11348 if (type == 7) // '0111' 11349 { 11350 regs = 1; 11351 if (BitIsSet (align, 1)) 11352 return false; 11353 } 11354 else if (type == 10) // '1010' 11355 { 11356 regs = 2; 11357 if (align == 3) 11358 return false; 11359 11360 } 11361 else if (type == 6) // '0110' 11362 { 11363 regs = 3; 11364 if (BitIsSet (align, 1)) 11365 return false; 11366 } 11367 else if (type == 2) // '0010' 11368 { 11369 regs = 4; 11370 } 11371 else 11372 return false; 11373 11374 // alignment = if align == �00� then 1 else 4 << UInt(align); 11375 if (align == 0) 11376 alignment = 1; 11377 else 11378 alignment = 4 << align; 11379 11380 // ebytes = 1 << UInt(size); esize = 8 * ebytes; elements = 8 DIV ebytes; 11381 ebytes = 1 << Bits32 (opcode, 7, 6); 11382 esize = 8 * ebytes; 11383 elements = 8 / ebytes; 11384 11385 // d = UInt(D:Vd); n = UInt(Rn); m = UInt(Rm); 11386 d = (Bit32 (opcode, 22) << 4) | Bits32 (opcode, 15, 12); 11387 n = Bits32 (opcode, 19, 15); 11388 m = Bits32 (opcode, 3, 0); 11389 11390 // wback = (m != 15); register_index = (m != 15 && m != 13); 11391 wback = (m != 15); 11392 register_index = ((m != 15) && (m != 13)); 11393 11394 // if d+regs > 32 then UNPREDICTABLE; 11395 if ((d + regs) > 32) 11396 return false; 11397 } 11398 break; 11399 11400 default: 11401 return false; 11402 } 11403 11404 RegisterInfo base_reg; 11405 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg); 11406 11407 uint32_t Rn = ReadCoreReg (n, &success); 11408 if (!success) 11409 return false; 11410 11411 // address = R[n]; if (address MOD alignment) != 0 then GenerateAlignmentException(); 11412 addr_t address = Rn; 11413 if ((address % alignment) != 0) 11414 return false; 11415 11416 EmulateInstruction::Context context; 11417 // if wback then R[n] = R[n] + (if register_index then R[m] else 8*regs); 11418 if (wback) 11419 { 11420 uint32_t Rm = ReadCoreReg (m, &success); 11421 if (!success) 11422 return false; 11423 11424 uint32_t offset; 11425 if (register_index) 11426 offset = Rm; 11427 else 11428 offset = 8 * regs; 11429 11430 uint32_t value = Rn + offset; 11431 context.type = eContextAdjustBaseRegister; 11432 context.SetRegisterPlusOffset (base_reg, offset); 11433 11434 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, value)) 11435 return false; 11436 11437 } 11438 11439 // for r = 0 to regs-1 11440 for (uint32_t r = 0; r < regs; ++r) 11441 { 11442 // for e = 0 to elements-1 11443 uint64_t assembled_data = 0; 11444 for (uint32_t e = 0; e < elements; ++e) 11445 { 11446 // Elem[D[d+r],e,esize] = MemU[address,ebytes]; 11447 context.type = eContextRegisterLoad; 11448 context.SetRegisterPlusOffset (base_reg, address - Rn); 11449 uint64_t data = MemURead (context, address, ebytes, 0, &success); 11450 if (!success) 11451 return false; 11452 11453 assembled_data = (data << (e * esize)) | assembled_data; // New data goes to the left of existing data 11454 11455 // address = address + ebytes; 11456 address = address + ebytes; 11457 } 11458 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_d0 + d + r, assembled_data)) 11459 return false; 11460 } 11461 } 11462 return true; 11463} 11464 11465// A8.6.308 VLD1 (single element to one lane) 11466// 11467bool 11468EmulateInstructionARM::EmulateVLD1Single (const uint32_t opcode, const ARMEncoding encoding) 11469{ 11470#if 0 11471 if ConditionPassed() then 11472 EncodingSpecificOperations(); CheckAdvSIMDEnabled(); NullCheckIfThumbEE(n); 11473 address = R[n]; if (address MOD alignment) != 0 then GenerateAlignmentException(); 11474 if wback then R[n] = R[n] + (if register_index then R[m] else ebytes); 11475 Elem[D[d],index,esize] = MemU[address,ebytes]; 11476#endif 11477 11478 bool success = false; 11479 11480 if (ConditionPassed (opcode)) 11481 { 11482 uint32_t ebytes; 11483 uint32_t esize; 11484 uint32_t index; 11485 uint32_t alignment; 11486 uint32_t d; 11487 uint32_t n; 11488 uint32_t m; 11489 bool wback; 11490 bool register_index; 11491 11492 switch (encoding) 11493 { 11494 case eEncodingT1: 11495 case eEncodingA1: 11496 { 11497 uint32_t size = Bits32 (opcode, 11, 10); 11498 uint32_t index_align = Bits32 (opcode, 7, 4); 11499 // if size == �11� then SEE VLD1 (single element to all lanes); 11500 if (size == 3) 11501 return EmulateVLD1SingleAll (opcode, encoding); 11502 // case size of 11503 if (size == 0) // when '00' 11504 { 11505 // if index_align<0> != �0� then UNDEFINED; 11506 if (BitIsClear (index_align, 0)) 11507 return false; 11508 11509 // ebytes = 1; esize = 8; index = UInt(index_align<3:1>); alignment = 1; 11510 ebytes = 1; 11511 esize = 8; 11512 index = Bits32 (index_align, 3, 1); 11513 alignment = 1; 11514 } 11515 else if (size == 1) // when �01� 11516 { 11517 // if index_align<1> != �0� then UNDEFINED; 11518 if (BitIsClear (index_align, 1)) 11519 return false; 11520 11521 // ebytes = 2; esize = 16; index = UInt(index_align<3:2>); 11522 ebytes = 2; 11523 esize = 16; 11524 index = Bits32 (index_align, 3, 2); 11525 11526 // alignment = if index_align<0> == �0� then 1 else 2; 11527 if (BitIsClear (index_align, 0)) 11528 alignment = 1; 11529 else 11530 alignment = 2; 11531 } 11532 else if (size == 2) // when �10� 11533 { 11534 // if index_align<2> != �0� then UNDEFINED; 11535 if (BitIsClear (index_align, 2)) 11536 return false; 11537 11538 // if index_align<1:0> != �00� && index_align<1:0> != �11� then UNDEFINED; 11539 if ((Bits32 (index_align, 1, 0) != 0) && (Bits32 (index_align, 1, 0) != 3)) 11540 return false; 11541 11542 // ebytes = 4; esize = 32; index = UInt(index_align<3>); 11543 ebytes = 4; 11544 esize = 32; 11545 index = Bit32 (index_align, 3); 11546 11547 // alignment = if index_align<1:0> == �00� then 1 else 4; 11548 if (Bits32 (index_align, 1, 0) == 0) 11549 alignment = 1; 11550 else 11551 alignment = 4; 11552 } 11553 else 11554 { 11555 return false; 11556 } 11557 // d = UInt(D:Vd); n = UInt(Rn); m = UInt(Rm); 11558 d = (Bit32 (opcode, 22) << 4) | Bits32 (opcode, 15, 12); 11559 n = Bits32 (opcode, 19, 16); 11560 m = Bits32 (opcode, 3, 0); 11561 11562 // wback = (m != 15); register_index = (m != 15 && m != 13); if n == 15 then UNPREDICTABLE; 11563 wback = (m != 15); 11564 register_index = ((m != 15) && (m != 13)); 11565 11566 if (n == 15) 11567 return false; 11568 11569 } 11570 break; 11571 11572 default: 11573 return false; 11574 } 11575 11576 RegisterInfo base_reg; 11577 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg); 11578 11579 uint32_t Rn = ReadCoreReg (n, &success); 11580 if (!success) 11581 return false; 11582 11583 // address = R[n]; if (address MOD alignment) != 0 then GenerateAlignmentException(); 11584 addr_t address = Rn; 11585 if ((address % alignment) != 0) 11586 return false; 11587 11588 EmulateInstruction::Context context; 11589 // if wback then R[n] = R[n] + (if register_index then R[m] else ebytes); 11590 if (wback) 11591 { 11592 uint32_t Rm = ReadCoreReg (m, &success); 11593 if (!success) 11594 return false; 11595 11596 uint32_t offset; 11597 if (register_index) 11598 offset = Rm; 11599 else 11600 offset = ebytes; 11601 11602 uint32_t value = Rn + offset; 11603 11604 context.type = eContextAdjustBaseRegister; 11605 context.SetRegisterPlusOffset (base_reg, offset); 11606 11607 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, value)) 11608 return false; 11609 } 11610 11611 // Elem[D[d],index,esize] = MemU[address,ebytes]; 11612 uint32_t element = MemURead (context, address, esize, 0, &success); 11613 if (!success) 11614 return false; 11615 11616 element = element << (index * esize); 11617 11618 uint64_t reg_data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_d0 + d, 0, &success); 11619 if (!success) 11620 return false; 11621 11622 uint64_t all_ones = -1; 11623 uint64_t mask = all_ones << ((index+1) * esize); // mask is all 1's to left of where 'element' goes, & all 0's 11624 // at element & to the right of element. 11625 if (index > 0) 11626 mask = mask | Bits64 (all_ones, (index * esize) - 1, 0); // add 1's to the right of where 'element' goes. 11627 // now mask should be 0's where element goes & 1's 11628 // everywhere else. 11629 11630 uint64_t masked_reg = reg_data & mask; // Take original reg value & zero out 'element' bits 11631 reg_data = masked_reg & element; // Put 'element' into those bits in reg_data. 11632 11633 context.type = eContextRegisterLoad; 11634 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + d, reg_data)) 11635 return false; 11636 } 11637 return true; 11638} 11639 11640// A8.6.391 VST1 (multiple single elements) 11641// Vector Store (multiple single elements) stores elements to memory from one, two, three, or four regsiters, without 11642// interleaving. Every element of each register is stored. 11643bool 11644EmulateInstructionARM::EmulateVST1Multiple (const uint32_t opcode, ARMEncoding encoding) 11645{ 11646#if 0 11647 if ConditionPassed() then 11648 EncodingSpecificOperations(); CheckAdvSIMDEnabled(); NullCheckIfThumbEE(n); 11649 address = R[n]; if (address MOD alignment) != 0 then GenerateAlignmentException(); 11650 if wback then R[n] = R[n] + (if register_index then R[m] else 8*regs); 11651 for r = 0 to regs-1 11652 for e = 0 to elements-1 11653 MemU[address,ebytes] = Elem[D[d+r],e,esize]; 11654 address = address + ebytes; 11655#endif 11656 11657 bool success = false; 11658 11659 if (ConditionPassed (opcode)) 11660 { 11661 uint32_t regs; 11662 uint32_t alignment; 11663 uint32_t ebytes; 11664 uint32_t esize; 11665 uint32_t elements; 11666 uint32_t d; 11667 uint32_t n; 11668 uint32_t m; 11669 bool wback; 11670 bool register_index; 11671 11672 switch (encoding) 11673 { 11674 case eEncodingT1: 11675 case eEncodingA1: 11676 { 11677 uint32_t type = Bits32 (opcode, 11, 8); 11678 uint32_t align = Bits32 (opcode, 5, 4); 11679 11680 // case type of 11681 if (type == 7) // when �0111� 11682 { 11683 // regs = 1; if align<1> == �1� then UNDEFINED; 11684 regs = 1; 11685 if (BitIsSet (align, 1)) 11686 return false; 11687 } 11688 else if (type == 10) // when �1010� 11689 { 11690 // regs = 2; if align == �11� then UNDEFINED; 11691 regs = 2; 11692 if (align == 3) 11693 return false; 11694 } 11695 else if (type == 6) // when �0110� 11696 { 11697 // regs = 3; if align<1> == �1� then UNDEFINED; 11698 regs = 3; 11699 if (BitIsSet (align, 1)) 11700 return false; 11701 } 11702 else if (type == 2) // when �0010� 11703 // regs = 4; 11704 regs = 4; 11705 else // otherwise 11706 // SEE �Related encodings�; 11707 return false; 11708 11709 // alignment = if align == �00� then 1 else 4 << UInt(align); 11710 if (align == 0) 11711 alignment = 1; 11712 else 11713 alignment = 4 << align; 11714 11715 // ebytes = 1 << UInt(size); esize = 8 * ebytes; elements = 8 DIV ebytes; 11716 ebytes = 1 << Bits32 (opcode,7, 6); 11717 esize = 8 * ebytes; 11718 elements = 8 / ebytes; 11719 11720 // d = UInt(D:Vd); n = UInt(Rn); m = UInt(Rm); 11721 d = (Bit32 (opcode, 22) << 4) | Bits32 (opcode, 15, 12); 11722 n = Bits32 (opcode, 19, 16); 11723 m = Bits32 (opcode, 3, 0); 11724 11725 // wback = (m != 15); register_index = (m != 15 && m != 13); 11726 wback = (m != 15); 11727 register_index = ((m != 15) && (m != 13)); 11728 11729 // if d+regs > 32 then UNPREDICTABLE; if n == 15 then UNPREDICTABLE; 11730 if ((d + regs) > 32) 11731 return false; 11732 11733 if (n == 15) 11734 return false; 11735 11736 } 11737 break; 11738 11739 default: 11740 return false; 11741 } 11742 11743 RegisterInfo base_reg; 11744 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg); 11745 11746 uint32_t Rn = ReadCoreReg (n, &success); 11747 if (!success) 11748 return false; 11749 11750 // address = R[n]; if (address MOD alignment) != 0 then GenerateAlignmentException(); 11751 addr_t address = Rn; 11752 if ((address % alignment) != 0) 11753 return false; 11754 11755 EmulateInstruction::Context context; 11756 // if wback then R[n] = R[n] + (if register_index then R[m] else 8*regs); 11757 if (wback) 11758 { 11759 uint32_t Rm = ReadCoreReg (m, &success); 11760 if (!success) 11761 return false; 11762 11763 uint32_t offset; 11764 if (register_index) 11765 offset = Rm; 11766 else 11767 offset = 8 * regs; 11768 11769 context.type = eContextAdjustBaseRegister; 11770 context.SetRegisterPlusOffset (base_reg, offset); 11771 11772 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, Rn + offset)) 11773 return false; 11774 } 11775 11776 RegisterInfo data_reg; 11777 context.type = eContextRegisterStore; 11778 // for r = 0 to regs-1 11779 for (uint32_t r = 0; r < regs; ++r) 11780 { 11781 GetRegisterInfo (eRegisterKindDWARF, dwarf_d0 + d + r, data_reg); 11782 uint64_t register_data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_d0 + d + r, 0, &success); 11783 if (!success) 11784 return false; 11785 11786 // for e = 0 to elements-1 11787 for (uint32_t e = 0; e < elements; ++e) 11788 { 11789 // MemU[address,ebytes] = Elem[D[d+r],e,esize]; 11790 uint64_t word = Bits64 (register_data, ((e + 1) * esize) - 1, e * esize); 11791 11792 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, address - Rn); 11793 if (!MemUWrite (context, address, word, ebytes)) 11794 return false; 11795 11796 // address = address + ebytes; 11797 address = address + ebytes; 11798 } 11799 } 11800 } 11801 return true; 11802} 11803 11804// A8.6.392 VST1 (single element from one lane) 11805// This instruction stores one element to memory from one element of a register. 11806bool 11807EmulateInstructionARM::EmulateVST1Single (const uint32_t opcode, ARMEncoding encoding) 11808{ 11809#if 0 11810 if ConditionPassed() then 11811 EncodingSpecificOperations(); CheckAdvSIMDEnabled(); NullCheckIfThumbEE(n); 11812 address = R[n]; if (address MOD alignment) != 0 then GenerateAlignmentException(); 11813 if wback then R[n] = R[n] + (if register_index then R[m] else ebytes); 11814 MemU[address,ebytes] = Elem[D[d],index,esize]; 11815#endif 11816 11817 bool success = false; 11818 11819 if (ConditionPassed (opcode)) 11820 { 11821 uint32_t ebytes; 11822 uint32_t esize; 11823 uint32_t index; 11824 uint32_t alignment; 11825 uint32_t d; 11826 uint32_t n; 11827 uint32_t m; 11828 bool wback; 11829 bool register_index; 11830 11831 switch (encoding) 11832 { 11833 case eEncodingT1: 11834 case eEncodingA1: 11835 { 11836 uint32_t size = Bits32 (opcode, 11, 10); 11837 uint32_t index_align = Bits32 (opcode, 7, 4); 11838 11839 // if size == �11� then UNDEFINED; 11840 if (size == 3) 11841 return false; 11842 11843 // case size of 11844 if (size == 0) // when �00� 11845 { 11846 // if index_align<0> != �0� then UNDEFINED; 11847 if (BitIsClear (index_align, 0)) 11848 return false; 11849 // ebytes = 1; esize = 8; index = UInt(index_align<3:1>); alignment = 1; 11850 ebytes = 1; 11851 esize = 8; 11852 index = Bits32 (index_align, 3, 1); 11853 alignment = 1; 11854 } 11855 else if (size == 1) // when �01� 11856 { 11857 // if index_align<1> != �0� then UNDEFINED; 11858 if (BitIsClear (index_align, 1)) 11859 return false; 11860 11861 // ebytes = 2; esize = 16; index = UInt(index_align<3:2>); 11862 ebytes = 2; 11863 esize = 16; 11864 index = Bits32 (index_align, 3, 2); 11865 11866 // alignment = if index_align<0> == �0� then 1 else 2; 11867 if (BitIsClear (index_align, 0)) 11868 alignment = 1; 11869 else 11870 alignment = 2; 11871 } 11872 else if (size == 2) // when �10� 11873 { 11874 // if index_align<2> != �0� then UNDEFINED; 11875 if (BitIsClear (index_align, 2)) 11876 return false; 11877 11878 // if index_align<1:0> != �00� && index_align<1:0> != �11� then UNDEFINED; 11879 if ((Bits32 (index_align, 1, 0) != 0) && (Bits32 (index_align, 1, 0) != 3)) 11880 return false; 11881 11882 // ebytes = 4; esize = 32; index = UInt(index_align<3>); 11883 ebytes = 4; 11884 esize = 32; 11885 index = Bit32 (index_align, 3); 11886 11887 // alignment = if index_align<1:0> == �00� then 1 else 4; 11888 if (Bits32 (index_align, 1, 0) == 0) 11889 alignment = 1; 11890 else 11891 alignment = 4; 11892 } 11893 else 11894 { 11895 return false; 11896 } 11897 // d = UInt(D:Vd); n = UInt(Rn); m = UInt(Rm); 11898 d = (Bit32 (opcode, 22) << 4) | Bits32 (opcode, 15, 12); 11899 n = Bits32 (opcode, 19, 16); 11900 m = Bits32 (opcode, 3, 0); 11901 11902 // wback = (m != 15); register_index = (m != 15 && m != 13); if n == 15 then UNPREDICTABLE; 11903 wback = (m != 15); 11904 register_index = ((m != 15) && (m != 13)); 11905 11906 if (n == 15) 11907 return false; 11908 } 11909 break; 11910 11911 default: 11912 return false; 11913 } 11914 11915 RegisterInfo base_reg; 11916 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg); 11917 11918 uint32_t Rn = ReadCoreReg (n, &success); 11919 if (!success) 11920 return false; 11921 11922 // address = R[n]; if (address MOD alignment) != 0 then GenerateAlignmentException(); 11923 addr_t address = Rn; 11924 if ((address % alignment) != 0) 11925 return false; 11926 11927 EmulateInstruction::Context context; 11928 // if wback then R[n] = R[n] + (if register_index then R[m] else ebytes); 11929 if (wback) 11930 { 11931 uint32_t Rm = ReadCoreReg (m, &success); 11932 if (!success) 11933 return false; 11934 11935 uint32_t offset; 11936 if (register_index) 11937 offset = Rm; 11938 else 11939 offset = ebytes; 11940 11941 context.type = eContextAdjustBaseRegister; 11942 context.SetRegisterPlusOffset (base_reg, offset); 11943 11944 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, Rn + offset)) 11945 return false; 11946 } 11947 11948 // MemU[address,ebytes] = Elem[D[d],index,esize]; 11949 uint64_t register_data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_d0 + d, 0, &success); 11950 if (!success) 11951 return false; 11952 11953 uint64_t word = Bits64 (register_data, ((index + 1) * esize) - 1, index * esize); 11954 11955 RegisterInfo data_reg; 11956 GetRegisterInfo (eRegisterKindDWARF, dwarf_d0 + d, data_reg); 11957 context.type = eContextRegisterStore; 11958 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, address - Rn); 11959 11960 if (!MemUWrite (context, address, word, ebytes)) 11961 return false; 11962 } 11963 return true; 11964} 11965 11966// A8.6.309 VLD1 (single element to all lanes) 11967// This instruction loads one element from memory into every element of one or two vectors. 11968bool 11969EmulateInstructionARM::EmulateVLD1SingleAll (const uint32_t opcode, const ARMEncoding encoding) 11970{ 11971#if 0 11972 if ConditionPassed() then 11973 EncodingSpecificOperations(); CheckAdvSIMDEnabled(); NullCheckIfThumbEE(n); 11974 address = R[n]; if (address MOD alignment) != 0 then GenerateAlignmentException(); 11975 if wback then R[n] = R[n] + (if register_index then R[m] else ebytes); 11976 replicated_element = Replicate(MemU[address,ebytes], elements); 11977 for r = 0 to regs-1 11978 D[d+r] = replicated_element; 11979#endif 11980 11981 bool success = false; 11982 11983 if (ConditionPassed (opcode)) 11984 { 11985 uint32_t ebytes; 11986 uint32_t elements; 11987 uint32_t regs; 11988 uint32_t alignment; 11989 uint32_t d; 11990 uint32_t n; 11991 uint32_t m; 11992 bool wback; 11993 bool register_index; 11994 11995 switch (encoding) 11996 { 11997 case eEncodingT1: 11998 case eEncodingA1: 11999 { 12000 //if size == �11� || (size == �00� && a == �1�) then UNDEFINED; 12001 uint32_t size = Bits32 (opcode, 7, 6); 12002 if ((size == 3) || ((size == 0) && BitIsSet (opcode, 4))) 12003 return false; 12004 12005 //ebytes = 1 << UInt(size); elements = 8 DIV ebytes; regs = if T == �0� then 1 else 2; 12006 ebytes = 1 << size; 12007 elements = 8 / ebytes; 12008 if (BitIsClear (opcode, 5)) 12009 regs = 1; 12010 else 12011 regs = 2; 12012 12013 //alignment = if a == �0� then 1 else ebytes; 12014 if (BitIsClear (opcode, 4)) 12015 alignment = 1; 12016 else 12017 alignment = ebytes; 12018 12019 //d = UInt(D:Vd); n = UInt(Rn); m = UInt(Rm); 12020 d = (Bit32 (opcode, 22) << 4) | Bits32 (opcode, 15, 12); 12021 n = Bits32 (opcode, 19, 16); 12022 m = Bits32 (opcode, 3, 0); 12023 12024 //wback = (m != 15); register_index = (m != 15 && m != 13); 12025 wback = (m != 15); 12026 register_index = ((m != 15) && (m != 13)); 12027 12028 //if d+regs > 32 then UNPREDICTABLE; if n == 15 then UNPREDICTABLE; 12029 if ((d + regs) > 32) 12030 return false; 12031 12032 if (n == 15) 12033 return false; 12034 } 12035 break; 12036 12037 default: 12038 return false; 12039 } 12040 12041 RegisterInfo base_reg; 12042 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg); 12043 12044 uint32_t Rn = ReadCoreReg (n, &success); 12045 if (!success) 12046 return false; 12047 12048 // address = R[n]; if (address MOD alignment) != 0 then GenerateAlignmentException(); 12049 addr_t address = Rn; 12050 if ((address % alignment) != 0) 12051 return false; 12052 12053 EmulateInstruction::Context context; 12054 // if wback then R[n] = R[n] + (if register_index then R[m] else ebytes); 12055 if (wback) 12056 { 12057 uint32_t Rm = ReadCoreReg (m, &success); 12058 if (!success) 12059 return false; 12060 12061 uint32_t offset; 12062 if (register_index) 12063 offset = Rm; 12064 else 12065 offset = ebytes; 12066 12067 context.type = eContextAdjustBaseRegister; 12068 context.SetRegisterPlusOffset (base_reg, offset); 12069 12070 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, Rn + offset)) 12071 return false; 12072 } 12073 12074 // replicated_element = Replicate(MemU[address,ebytes], elements); 12075 12076 context.type = eContextRegisterLoad; 12077 uint64_t word = MemURead (context, address, ebytes, 0, &success); 12078 if (!success) 12079 return false; 12080 12081 uint64_t replicated_element = 0; 12082 uint32_t esize = ebytes * 8; 12083 for (uint32_t e = 0; e < elements; ++e) 12084 replicated_element = (replicated_element << esize) | Bits64 (word, esize - 1, 0); 12085 12086 // for r = 0 to regs-1 12087 for (uint32_t r = 0; r < regs; ++r) 12088 { 12089 // D[d+r] = replicated_element; 12090 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_d0 + d + r, replicated_element)) 12091 return false; 12092 } 12093 } 12094 return true; 12095} 12096 12097// B6.2.13 SUBS PC, LR and related instructions 12098//The SUBS PC, LR, #<const? instruction provides an exception return without the use of the stack. It subtracts the 12099// immediate constant from the LR, branches to the resulting address, and also copies the SPSR to the CPSR. 12100bool 12101EmulateInstructionARM::EmulateSUBSPcLrEtc (const uint32_t opcode, const ARMEncoding encoding) 12102{ 12103#if 0 12104 if ConditionPassed() then 12105 EncodingSpecificOperations(); 12106 if CurrentInstrSet() == InstrSet_ThumbEE then 12107 UNPREDICTABLE; 12108 operand2 = if register_form then Shift(R[m], shift_t, shift_n, APSR.C) else imm32; 12109 case opcode of 12110 when �0000� result = R[n] AND operand2; // AND 12111 when �0001� result = R[n] EOR operand2; // EOR 12112 when �0010� (result, -, -) = AddWithCarry(R[n], NOT(operand2), �1�); // SUB 12113 when �0011� (result, -, -) = AddWithCarry(NOT(R[n]), operand2, �1�); // RSB 12114 when �0100� (result, -, -) = AddWithCarry(R[n], operand2, �0�); // ADD 12115 when �0101� (result, -, -) = AddWithCarry(R[n], operand2, APSR.c); // ADC 12116 when �0110� (result, -, -) = AddWithCarry(R[n], NOT(operand2), APSR.C); // SBC 12117 when �0111� (result, -, -) = AddWithCarry(NOT(R[n]), operand2, APSR.C); // RSC 12118 when �1100� result = R[n] OR operand2; // ORR 12119 when �1101� result = operand2; // MOV 12120 when �1110� result = R[n] AND NOT(operand2); // BIC 12121 when �1111� result = NOT(operand2); // MVN 12122 CPSRWriteByInstr(SPSR[], �1111�, TRUE); 12123 BranchWritePC(result); 12124#endif 12125 12126 bool success = false; 12127 12128 if (ConditionPassed (opcode)) 12129 { 12130 uint32_t n; 12131 uint32_t m; 12132 uint32_t imm32; 12133 bool register_form; 12134 ARM_ShifterType shift_t; 12135 uint32_t shift_n; 12136 uint32_t code; 12137 12138 switch (encoding) 12139 { 12140 case eEncodingT1: 12141 // if CurrentInstrSet() == InstrSet_ThumbEE then UNPREDICTABLE 12142 // n = 14; imm32 = ZeroExtend(imm8, 32); register_form = FALSE; opcode = �0010�; // = SUB 12143 n = 14; 12144 imm32 = Bits32 (opcode, 7, 0); 12145 register_form = false; 12146 code = 2; 12147 12148 // if InITBlock() && !LastInITBlock() then UNPREDICTABLE; 12149 if (InITBlock() && !LastInITBlock()) 12150 return false; 12151 12152 break; 12153 12154 case eEncodingA1: 12155 // n = UInt(Rn); imm32 = ARMExpandImm(imm12); register_form = FALSE; 12156 n = Bits32 (opcode, 19, 16); 12157 imm32 = ARMExpandImm (opcode); 12158 register_form = false; 12159 code = Bits32 (opcode, 24, 21); 12160 12161 break; 12162 12163 case eEncodingA2: 12164 // n = UInt(Rn); m = UInt(Rm); register_form = TRUE; 12165 n = Bits32 (opcode, 19, 16); 12166 m = Bits32 (opcode, 3, 0); 12167 register_form = true; 12168 12169 // (shift_t, shift_n) = DecodeImmShift(type, imm5); 12170 shift_n = DecodeImmShiftARM (opcode, shift_t); 12171 12172 break; 12173 12174 default: 12175 return false; 12176 } 12177 12178 // operand2 = if register_form then Shift(R[m], shift_t, shift_n, APSR.C) else imm32; 12179 uint32_t operand2; 12180 if (register_form) 12181 { 12182 uint32_t Rm = ReadCoreReg (m, &success); 12183 if (!success) 12184 return false; 12185 12186 operand2 = Shift (Rm, shift_t, shift_n, APSR_C, &success); 12187 if (!success) 12188 return false; 12189 } 12190 else 12191 { 12192 operand2 = imm32; 12193 } 12194 12195 uint32_t Rn = ReadCoreReg (n, &success); 12196 if (!success) 12197 return false; 12198 12199 AddWithCarryResult result; 12200 12201 // case opcode of 12202 switch (code) 12203 { 12204 case 0: // when �0000� 12205 // result = R[n] AND operand2; // AND 12206 result.result = Rn & operand2; 12207 break; 12208 12209 case 1: // when �0001� 12210 // result = R[n] EOR operand2; // EOR 12211 result.result = Rn ^ operand2; 12212 break; 12213 12214 case 2: // when �0010� 12215 // (result, -, -) = AddWithCarry(R[n], NOT(operand2), �1�); // SUB 12216 result = AddWithCarry (Rn, ~(operand2), 1); 12217 break; 12218 12219 case 3: // when �0011� 12220 // (result, -, -) = AddWithCarry(NOT(R[n]), operand2, �1�); // RSB 12221 result = AddWithCarry (~(Rn), operand2, 1); 12222 break; 12223 12224 case 4: // when �0100� 12225 // (result, -, -) = AddWithCarry(R[n], operand2, �0�); // ADD 12226 result = AddWithCarry (Rn, operand2, 0); 12227 break; 12228 12229 case 5: // when �0101� 12230 // (result, -, -) = AddWithCarry(R[n], operand2, APSR.c); // ADC 12231 result = AddWithCarry (Rn, operand2, APSR_C); 12232 break; 12233 12234 case 6: // when �0110� 12235 // (result, -, -) = AddWithCarry(R[n], NOT(operand2), APSR.C); // SBC 12236 result = AddWithCarry (Rn, ~(operand2), APSR_C); 12237 break; 12238 12239 case 7: // when �0111� 12240 // (result, -, -) = AddWithCarry(NOT(R[n]), operand2, APSR.C); // RSC 12241 result = AddWithCarry (~(Rn), operand2, APSR_C); 12242 break; 12243 12244 case 10: // when �1100� 12245 // result = R[n] OR operand2; // ORR 12246 result.result = Rn | operand2; 12247 break; 12248 12249 case 11: // when �1101� 12250 // result = operand2; // MOV 12251 result.result = operand2; 12252 break; 12253 12254 case 12: // when �1110� 12255 // result = R[n] AND NOT(operand2); // BIC 12256 result.result = Rn & ~(operand2); 12257 break; 12258 12259 case 15: // when �1111� 12260 // result = NOT(operand2); // MVN 12261 result.result = ~(operand2); 12262 break; 12263 12264 default: 12265 return false; 12266 } 12267 // CPSRWriteByInstr(SPSR[], �1111�, TRUE); 12268 12269 // For now, in emulation mode, we don't have access to the SPSR, so we will use the CPSR instead, and hope for 12270 // the best. 12271 uint32_t spsr = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_cpsr, 0, &success); 12272 if (!success) 12273 return false; 12274 12275 CPSRWriteByInstr (spsr, 15, true); 12276 12277 // BranchWritePC(result); 12278 EmulateInstruction::Context context; 12279 context.type = eContextAdjustPC; 12280 context.SetImmediate (result.result); 12281 12282 BranchWritePC (context, result.result); 12283 } 12284 return true; 12285} 12286 12287EmulateInstructionARM::ARMOpcode* 12288EmulateInstructionARM::GetARMOpcodeForInstruction (const uint32_t opcode, uint32_t arm_isa) 12289{ 12290 static ARMOpcode 12291 g_arm_opcodes[] = 12292 { 12293 //---------------------------------------------------------------------- 12294 // Prologue instructions 12295 //---------------------------------------------------------------------- 12296 12297 // push register(s) 12298 { 0x0fff0000, 0x092d0000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulatePUSH, "push <registers>" }, 12299 { 0x0fff0fff, 0x052d0004, ARMvAll, eEncodingA2, No_VFP, eSize32, &EmulateInstructionARM::EmulatePUSH, "push <register>" }, 12300 12301 // set r7 to point to a stack offset 12302 { 0x0ffff000, 0x028d7000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateADDRdSPImm, "add r7, sp, #<const>" }, 12303 { 0x0ffff000, 0x024c7000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBR7IPImm, "sub r7, ip, #<const>"}, 12304 // copy the stack pointer to ip 12305 { 0x0fffffff, 0x01a0c00d, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateMOVRdSP, "mov ip, sp" }, 12306 { 0x0ffff000, 0x028dc000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateADDRdSPImm, "add ip, sp, #<const>" }, 12307 { 0x0ffff000, 0x024dc000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBIPSPImm, "sub ip, sp, #<const>"}, 12308 12309 // adjust the stack pointer 12310 { 0x0ffff000, 0x024dd000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBSPImm, "sub sp, sp, #<const>"}, 12311 { 0x0fef0010, 0x004d0000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBSPReg, "sub{s}<c> <Rd>, sp, <Rm>{,<shift>}" }, 12312 12313 // push one register 12314 // if Rn == '1101' && imm12 == '000000000100' then SEE PUSH; 12315 { 0x0e5f0000, 0x040d0000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTRRtSP, "str Rt, [sp, #-imm12]!" }, 12316 12317 // vector push consecutive extension register(s) 12318 { 0x0fbf0f00, 0x0d2d0b00, ARMV6T2_ABOVE, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateVPUSH, "vpush.64 <list>"}, 12319 { 0x0fbf0f00, 0x0d2d0a00, ARMV6T2_ABOVE, eEncodingA2, No_VFP, eSize32, &EmulateInstructionARM::EmulateVPUSH, "vpush.32 <list>"}, 12320 12321 //---------------------------------------------------------------------- 12322 // Epilogue instructions 12323 //---------------------------------------------------------------------- 12324 12325 { 0x0fff0000, 0x08bd0000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulatePOP, "pop <registers>"}, 12326 { 0x0fff0fff, 0x049d0004, ARMvAll, eEncodingA2, No_VFP, eSize32, &EmulateInstructionARM::EmulatePOP, "pop <register>"}, 12327 { 0x0fbf0f00, 0x0cbd0b00, ARMV6T2_ABOVE, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateVPOP, "vpop.64 <list>"}, 12328 { 0x0fbf0f00, 0x0cbd0a00, ARMV6T2_ABOVE, eEncodingA2, No_VFP, eSize32, &EmulateInstructionARM::EmulateVPOP, "vpop.32 <list>"}, 12329 12330 //---------------------------------------------------------------------- 12331 // Supervisor Call (previously Software Interrupt) 12332 //---------------------------------------------------------------------- 12333 { 0x0f000000, 0x0f000000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSVC, "svc #imm24"}, 12334 12335 //---------------------------------------------------------------------- 12336 // Branch instructions 12337 //---------------------------------------------------------------------- 12338 { 0x0f000000, 0x0a000000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateB, "b #imm24"}, 12339 // To resolve ambiguity, "blx <label>" should come before "bl <label>". 12340 { 0xfe000000, 0xfa000000, ARMV5_ABOVE, eEncodingA2, No_VFP, eSize32, &EmulateInstructionARM::EmulateBLXImmediate, "blx <label>"}, 12341 { 0x0f000000, 0x0b000000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateBLXImmediate, "bl <label>"}, 12342 { 0x0ffffff0, 0x012fff30, ARMV5_ABOVE, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateBLXRm, "blx <Rm>"}, 12343 // for example, "bx lr" 12344 { 0x0ffffff0, 0x012fff10, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateBXRm, "bx <Rm>"}, 12345 // bxj 12346 { 0x0ffffff0, 0x012fff20, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateBXJRm, "bxj <Rm>"}, 12347 12348 //---------------------------------------------------------------------- 12349 // Data-processing instructions 12350 //---------------------------------------------------------------------- 12351 // adc (immediate) 12352 { 0x0fe00000, 0x02a00000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateADCImm, "adc{s}<c> <Rd>, <Rn>, #const"}, 12353 // adc (register) 12354 { 0x0fe00010, 0x00a00000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateADCReg, "adc{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"}, 12355 // add (immediate) 12356 { 0x0fe00000, 0x02800000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateADDImmARM, "add{s}<c> <Rd>, <Rn>, #const"}, 12357 // add (register) 12358 { 0x0fe00010, 0x00800000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateADDReg, "add{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"}, 12359 // add (register-shifted register) 12360 { 0x0fe00090, 0x00800010, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateADDRegShift, "add{s}<c> <Rd>, <Rn>, <Rm>, <type> <RS>"}, 12361 // adr 12362 { 0x0fff0000, 0x028f0000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateADR, "add<c> <Rd>, PC, #<const>"}, 12363 { 0x0fff0000, 0x024f0000, ARMvAll, eEncodingA2, No_VFP, eSize32, &EmulateInstructionARM::EmulateADR, "sub<c> <Rd>, PC, #<const>"}, 12364 // and (immediate) 12365 { 0x0fe00000, 0x02000000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateANDImm, "and{s}<c> <Rd>, <Rn>, #const"}, 12366 // and (register) 12367 { 0x0fe00010, 0x00000000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateANDReg, "and{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"}, 12368 // bic (immediate) 12369 { 0x0fe00000, 0x03c00000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateBICImm, "bic{s}<c> <Rd>, <Rn>, #const"}, 12370 // bic (register) 12371 { 0x0fe00010, 0x01c00000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateBICReg, "bic{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"}, 12372 // eor (immediate) 12373 { 0x0fe00000, 0x02200000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateEORImm, "eor{s}<c> <Rd>, <Rn>, #const"}, 12374 // eor (register) 12375 { 0x0fe00010, 0x00200000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateEORReg, "eor{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"}, 12376 // orr (immediate) 12377 { 0x0fe00000, 0x03800000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateORRImm, "orr{s}<c> <Rd>, <Rn>, #const"}, 12378 // orr (register) 12379 { 0x0fe00010, 0x01800000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateORRReg, "orr{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"}, 12380 // rsb (immediate) 12381 { 0x0fe00000, 0x02600000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateRSBImm, "rsb{s}<c> <Rd>, <Rn>, #<const>"}, 12382 // rsb (register) 12383 { 0x0fe00010, 0x00600000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateRSBReg, "rsb{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"}, 12384 // rsc (immediate) 12385 { 0x0fe00000, 0x02e00000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateRSCImm, "rsc{s}<c> <Rd>, <Rn>, #<const>"}, 12386 // rsc (register) 12387 { 0x0fe00010, 0x00e00000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateRSCReg, "rsc{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"}, 12388 // sbc (immediate) 12389 { 0x0fe00000, 0x02c00000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSBCImm, "sbc{s}<c> <Rd>, <Rn>, #<const>"}, 12390 // sbc (register) 12391 { 0x0fe00010, 0x00c00000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSBCReg, "sbc{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"}, 12392 // sub (immediate, ARM) 12393 { 0x0fe00000, 0x02400000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBImmARM, "sub{s}<c> <Rd>, <Rn>, #<const>"}, 12394 // sub (sp minus immediate) 12395 { 0x0fef0000, 0x024d0000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBSPImm, "sub{s}<c> <Rd>, sp, #<const>"}, 12396 // sub (register) 12397 { 0x0fe00010, 0x00400000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBReg, "sub{s}<c> <Rd>, <Rn>, <Rm>{,<shift>}"}, 12398 // teq (immediate) 12399 { 0x0ff0f000, 0x03300000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateTEQImm, "teq<c> <Rn>, #const"}, 12400 // teq (register) 12401 { 0x0ff0f010, 0x01300000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateTEQReg, "teq<c> <Rn>, <Rm> {,<shift>}"}, 12402 // tst (immediate) 12403 { 0x0ff0f000, 0x03100000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateTSTImm, "tst<c> <Rn>, #const"}, 12404 // tst (register) 12405 { 0x0ff0f010, 0x01100000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateTSTReg, "tst<c> <Rn>, <Rm> {,<shift>}"}, 12406 12407 // mov (immediate) 12408 { 0x0fef0000, 0x03a00000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateMOVRdImm, "mov{s}<c> <Rd>, #<const>"}, 12409 { 0x0ff00000, 0x03000000, ARMV6T2_ABOVE, eEncodingA2, No_VFP, eSize32, &EmulateInstructionARM::EmulateMOVRdImm, "movw<c> <Rd>, #<imm16>" }, 12410 // mov (register) 12411 { 0x0fef0ff0, 0x01a00000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateMOVRdRm, "mov{s}<c> <Rd>, <Rm>"}, 12412 // mvn (immediate) 12413 { 0x0fef0000, 0x03e00000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateMVNImm, "mvn{s}<c> <Rd>, #<const>"}, 12414 // mvn (register) 12415 { 0x0fef0010, 0x01e00000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateMVNReg, "mvn{s}<c> <Rd>, <Rm> {,<shift>}"}, 12416 // cmn (immediate) 12417 { 0x0ff0f000, 0x03700000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateCMNImm, "cmn<c> <Rn>, #<const>"}, 12418 // cmn (register) 12419 { 0x0ff0f010, 0x01700000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateCMNReg, "cmn<c> <Rn>, <Rm> {,<shift>}"}, 12420 // cmp (immediate) 12421 { 0x0ff0f000, 0x03500000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateCMPImm, "cmp<c> <Rn>, #<const>"}, 12422 // cmp (register) 12423 { 0x0ff0f010, 0x01500000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateCMPReg, "cmp<c> <Rn>, <Rm> {,<shift>}"}, 12424 // asr (immediate) 12425 { 0x0fef0070, 0x01a00040, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateASRImm, "asr{s}<c> <Rd>, <Rm>, #imm"}, 12426 // asr (register) 12427 { 0x0fef00f0, 0x01a00050, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateASRReg, "asr{s}<c> <Rd>, <Rn>, <Rm>"}, 12428 // lsl (immediate) 12429 { 0x0fef0070, 0x01a00000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLSLImm, "lsl{s}<c> <Rd>, <Rm>, #imm"}, 12430 // lsl (register) 12431 { 0x0fef00f0, 0x01a00010, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLSLReg, "lsl{s}<c> <Rd>, <Rn>, <Rm>"}, 12432 // lsr (immediate) 12433 { 0x0fef0070, 0x01a00020, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLSRImm, "lsr{s}<c> <Rd>, <Rm>, #imm"}, 12434 // lsr (register) 12435 { 0x0fef00f0, 0x01a00050, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLSRReg, "lsr{s}<c> <Rd>, <Rn>, <Rm>"}, 12436 // rrx is a special case encoding of ror (immediate) 12437 { 0x0fef0ff0, 0x01a00060, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateRRX, "rrx{s}<c> <Rd>, <Rm>"}, 12438 // ror (immediate) 12439 { 0x0fef0070, 0x01a00060, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateRORImm, "ror{s}<c> <Rd>, <Rm>, #imm"}, 12440 // ror (register) 12441 { 0x0fef00f0, 0x01a00070, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateRORReg, "ror{s}<c> <Rd>, <Rn>, <Rm>"}, 12442 // mul 12443 { 0x0fe000f0, 0x00000090, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateMUL, "mul{s}<c> <Rd>,<R>,<Rm>" }, 12444 12445 // subs pc, lr and related instructions 12446 { 0x0e10f000, 0x0210f000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBSPcLrEtc, "<opc>S<c> PC,#<const> | <Rn>,#<const>" }, 12447 { 0x0e10f010, 0x0010f000, ARMvAll, eEncodingA2, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBSPcLrEtc, "<opc>S<c> PC,<Rn>,<Rm{,<shift>}" }, 12448 12449 //---------------------------------------------------------------------- 12450 // Load instructions 12451 //---------------------------------------------------------------------- 12452 { 0x0fd00000, 0x08900000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDM, "ldm<c> <Rn>{!} <registers>" }, 12453 { 0x0fd00000, 0x08100000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDMDA, "ldmda<c> <Rn>{!} <registers>" }, 12454 { 0x0fd00000, 0x09100000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDMDB, "ldmdb<c> <Rn>{!} <registers>" }, 12455 { 0x0fd00000, 0x09900000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDMIB, "ldmib<c> <Rn<{!} <registers>" }, 12456 { 0x0e500000, 0x04100000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRImmediateARM, "ldr<c> <Rt> [<Rn> {#+/-<imm12>}]" }, 12457 { 0x0e500010, 0x06100000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRRegister, "ldr<c> <Rt> [<Rn> +/-<Rm> {<shift>}] {!}" }, 12458 { 0x0e5f0000, 0x045f0000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRBLiteral, "ldrb<c> <Rt>, [...]"}, 12459 { 0xfe500010, 0x06500000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRBRegister, "ldrb<c> <Rt>, [<Rn>,+/-<Rm>{, <shift>}]{!}" }, 12460 { 0x0e5f00f0, 0x005f00b0, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRHLiteral, "ldrh<c> <Rt>, <label>" }, 12461 { 0x0e5000f0, 0x001000b0, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRHRegister, "ldrh<c> <Rt>,[<Rn>,+/-<Rm>]{!}" }, 12462 { 0x0e5000f0, 0x005000d0, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRSBImmediate, "ldrsb<c> <Rt>, [<Rn>{,#+/-<imm8>}]" }, 12463 { 0x0e5f00f0, 0x005f00d0, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRSBLiteral, "ldrsb<c> <Rt> <label>" }, 12464 { 0x0e5000f0, 0x001000d0, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRSBRegister, "ldrsb<c> <Rt>,[<Rn>,+/-<Rm>]{!}" }, 12465 { 0x0e5000f0, 0x005000f0, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRSHImmediate, "ldrsh<c> <Rt>,[<Rn>{,#+/-<imm8>}]"}, 12466 { 0x0e5f00f0, 0x005f00f0, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRSHLiteral, "ldrsh<c> <Rt>,<label>" }, 12467 { 0x0e5000f0, 0x001000f0, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRSHRegister, "ldrsh<c> <Rt>,[<Rn>,+/-<Rm>]{!}" }, 12468 { 0x0e5000f0, 0x004000d0, ARMV5TE_ABOVE, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRDImmediate, "ldrd<c> <Rt>, <Rt2>, [<Rn>,#+/-<imm8>]!"}, 12469 { 0x0e500ff0, 0x000000d0, ARMV5TE_ABOVE, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRDRegister, "ldrd<c> <Rt>, <Rt2>, [<Rn>, +/-<Rm>]{!}"}, 12470 { 0x0e100f00, 0x0c100b00, ARMvAll, eEncodingA1, VFPv2_ABOVE, eSize32, &EmulateInstructionARM::EmulateVLDM, "vldm{mode}<c> <Rn>{!}, <list>"}, 12471 { 0x0e100f00, 0x0c100a00, ARMvAll, eEncodingA2, VFPv2v3, eSize32, &EmulateInstructionARM::EmulateVLDM, "vldm{mode}<c> <Rn>{!}, <list>"}, 12472 { 0x0f300f00, 0x0d100b00, ARMvAll, eEncodingA1, VFPv2_ABOVE, eSize32, &EmulateInstructionARM::EmulateVLDR, "vldr<c> <Dd>, [<Rn>{,#+/-<imm>}]"}, 12473 { 0x0f300f00, 0x0d100a00, ARMvAll, eEncodingA2, VFPv2v3, eSize32, &EmulateInstructionARM::EmulateVLDR, "vldr<c> <Sd>, [<Rn>{,#+/-<imm>}]"}, 12474 { 0xffb00000, 0xf4200000, ARMvAll, eEncodingA1, AdvancedSIMD, eSize32, &EmulateInstructionARM::EmulateVLD1Multiple, "vld1<c>.<size> <list>, [<Rn>{@<align>}], <Rm>"}, 12475 { 0xffb00300, 0xf4a00000, ARMvAll, eEncodingA1, AdvancedSIMD, eSize32, &EmulateInstructionARM::EmulateVLD1Single, "vld1<c>.<size> <list>, [<Rn>{@<align>}], <Rm>"}, 12476 { 0xffb00f00, 0xf4a00c00, ARMvAll, eEncodingA1, AdvancedSIMD, eSize32, &EmulateInstructionARM::EmulateVLD1SingleAll, "vld1<c>.<size> <list>, [<Rn>{@<align>}], <Rm>"}, 12477 12478 //---------------------------------------------------------------------- 12479 // Store instructions 12480 //---------------------------------------------------------------------- 12481 { 0x0fd00000, 0x08800000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTM, "stm<c> <Rn>{!} <registers>" }, 12482 { 0x0fd00000, 0x08000000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTMDA, "stmda<c> <Rn>{!} <registers>" }, 12483 { 0x0fd00000, 0x09000000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTMDB, "stmdb<c> <Rn>{!} <registers>" }, 12484 { 0x0fd00000, 0x09800000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTMIB, "stmib<c> <Rn>{!} <registers>" }, 12485 { 0x0e500010, 0x06000000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTRRegister, "str<c> <Rt> [<Rn> +/-<Rm> {<shift>}]{!}" }, 12486 { 0x0e5000f0, 0x000000b0, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTRHRegister, "strh<c> <Rt>,[<Rn>,+/-<Rm>[{!}" }, 12487 { 0x0ff00ff0, 0x01800f90, ARMV6_ABOVE, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTREX, "strex<c> <Rd>, <Rt>, [<Rn>]"}, 12488 { 0x0e500000, 0x04400000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTRBImmARM, "strb<c> <Rt>,[<Rn>,#+/-<imm12>]!"}, 12489 { 0x0e500000, 0x04000000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTRImmARM, "str<c> <Rt>,[<Rn>,#+/-<imm12>]!"}, 12490 { 0x0e5000f0, 0x004000f0, ARMV5TE_ABOVE, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTRDImm, "strd<c> <Rt>, <Rt2>, [<Rn> #+/-<imm8>]!"}, 12491 { 0x0e500ff0, 0x000000f0, ARMV5TE_ABOVE, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTRDReg, "strd<c> <Rt>, <Rt2>, [<Rn>, +/-<Rm>]{!}"}, 12492 { 0x0e100f00, 0x0c000b00, ARMvAll, eEncodingA1, VFPv2_ABOVE, eSize32, &EmulateInstructionARM::EmulateVSTM, "vstm{mode}<c> <Rn>{!} <list>"}, 12493 { 0x0e100f00, 0x0c000a00, ARMvAll, eEncodingA2, VFPv2v3, eSize32, &EmulateInstructionARM::EmulateVSTM, "vstm{mode}<c> <Rn>{!} <list>"}, 12494 { 0x0f300f00, 0x0d000b00, ARMvAll, eEncodingA1, VFPv2_ABOVE, eSize32, &EmulateInstructionARM::EmulateVSTR, "vstr<c> <Dd> [<Rn>{,#+/-<imm>}]"}, 12495 { 0x0f300f00, 0x0d000a00, ARMvAll, eEncodingA2, VFPv2v3, eSize32, &EmulateInstructionARM::EmulateVSTR, "vstr<c> <Sd> [<Rn>{,#+/-<imm>}]"}, 12496 { 0xffb00000, 0xf4000000, ARMvAll, eEncodingA1, AdvancedSIMD, eSize32, &EmulateInstructionARM::EmulateVST1Multiple, "vst1<c>.<size> <list>, [<Rn>{@<align>}], <Rm>"}, 12497 { 0xffb00300, 0xf4800000, ARMvAll, eEncodingA1, AdvancedSIMD, eSize32, &EmulateInstructionARM::EmulateVST1Single, "vst1<c>.<size> <list>, [<Rn>{@<align>}], <Rm>"}, 12498 12499 //---------------------------------------------------------------------- 12500 // Other instructions 12501 //---------------------------------------------------------------------- 12502 { 0x0fff00f0, 0x06af00f0, ARMV6_ABOVE, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSXTB, "sxtb<c> <Rd>,<Rm>{,<rotation>}" }, 12503 { 0x0fff00f0, 0x06bf0070, ARMV6_ABOVE, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSXTH, "sxth<c> <Rd>,<Rm>{,<rotation>}" }, 12504 { 0x0fff00f0, 0x06ef0070, ARMV6_ABOVE, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateUXTB, "uxtb<c> <Rd>,<Rm>{,<rotation>}" }, 12505 { 0x0fff00f0, 0x06ff0070, ARMV6_ABOVE, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateUXTH, "uxth<c> <Rd>,<Rm>{,<rotation>}" }, 12506 { 0xfe500000, 0xf8100000, ARMV6_ABOVE, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateRFE, "rfe{<amode>} <Rn>{!}" } 12507 12508 }; 12509 static const size_t k_num_arm_opcodes = sizeof(g_arm_opcodes)/sizeof(ARMOpcode); 12510 12511 for (size_t i=0; i<k_num_arm_opcodes; ++i) 12512 { 12513 if ((g_arm_opcodes[i].mask & opcode) == g_arm_opcodes[i].value && 12514 (g_arm_opcodes[i].variants & arm_isa) != 0) 12515 return &g_arm_opcodes[i]; 12516 } 12517 return NULL; 12518} 12519 12520 12521EmulateInstructionARM::ARMOpcode* 12522EmulateInstructionARM::GetThumbOpcodeForInstruction (const uint32_t opcode, uint32_t arm_isa) 12523{ 12524 12525 static ARMOpcode 12526 g_thumb_opcodes[] = 12527 { 12528 //---------------------------------------------------------------------- 12529 // Prologue instructions 12530 //---------------------------------------------------------------------- 12531 12532 // push register(s) 12533 { 0xfffffe00, 0x0000b400, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulatePUSH, "push <registers>" }, 12534 { 0xffff0000, 0xe92d0000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulatePUSH, "push.w <registers>" }, 12535 { 0xffff0fff, 0xf84d0d04, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, &EmulateInstructionARM::EmulatePUSH, "push.w <register>" }, 12536 12537 // set r7 to point to a stack offset 12538 { 0xffffff00, 0x0000af00, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateADDRdSPImm, "add r7, sp, #imm" }, 12539 // copy the stack pointer to r7 12540 { 0xffffffff, 0x0000466f, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateMOVRdSP, "mov r7, sp" }, 12541 // move from high register to low register (comes after "mov r7, sp" to resolve ambiguity) 12542 { 0xffffffc0, 0x00004640, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateMOVLowHigh, "mov r0-r7, r8-r15" }, 12543 12544 // PC-relative load into register (see also EmulateADDSPRm) 12545 { 0xfffff800, 0x00004800, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateLDRRtPCRelative, "ldr <Rt>, [PC, #imm]"}, 12546 12547 // adjust the stack pointer 12548 { 0xffffff87, 0x00004485, ARMvAll, eEncodingT2, No_VFP, eSize16, &EmulateInstructionARM::EmulateADDSPRm, "add sp, <Rm>"}, 12549 { 0xffffff80, 0x0000b080, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateSUBSPImm, "sub sp, sp, #imm"}, 12550 { 0xfbef8f00, 0xf1ad0d00, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBSPImm, "sub.w sp, sp, #<const>"}, 12551 { 0xfbff8f00, 0xf2ad0d00, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBSPImm, "subw sp, sp, #imm12"}, 12552 { 0xffef8000, 0xebad0000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBSPReg, "sub{s}<c> <Rd>, sp, <Rm>{,<shift>}" }, 12553 12554 // vector push consecutive extension register(s) 12555 { 0xffbf0f00, 0xed2d0b00, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateVPUSH, "vpush.64 <list>"}, 12556 { 0xffbf0f00, 0xed2d0a00, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateVPUSH, "vpush.32 <list>"}, 12557 12558 //---------------------------------------------------------------------- 12559 // Epilogue instructions 12560 //---------------------------------------------------------------------- 12561 12562 { 0xfffff800, 0x0000a800, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateADDSPImm, "add<c> <Rd>, sp, #imm"}, 12563 { 0xffffff80, 0x0000b000, ARMvAll, eEncodingT2, No_VFP, eSize16, &EmulateInstructionARM::EmulateADDSPImm, "add sp, #imm"}, 12564 { 0xfffffe00, 0x0000bc00, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulatePOP, "pop <registers>"}, 12565 { 0xffff0000, 0xe8bd0000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulatePOP, "pop.w <registers>" }, 12566 { 0xffff0fff, 0xf85d0d04, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, &EmulateInstructionARM::EmulatePOP, "pop.w <register>" }, 12567 { 0xffbf0f00, 0xecbd0b00, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateVPOP, "vpop.64 <list>"}, 12568 { 0xffbf0f00, 0xecbd0a00, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateVPOP, "vpop.32 <list>"}, 12569 12570 //---------------------------------------------------------------------- 12571 // Supervisor Call (previously Software Interrupt) 12572 //---------------------------------------------------------------------- 12573 { 0xffffff00, 0x0000df00, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateSVC, "svc #imm8"}, 12574 12575 //---------------------------------------------------------------------- 12576 // If Then makes up to four following instructions conditional. 12577 //---------------------------------------------------------------------- 12578 // The next 5 opcode _must_ come before the if then instruction 12579 { 0xffffffff, 0x0000bf00, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateNop, "nop"}, 12580 { 0xffffffff, 0x0000bf10, ARMV7_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateNop, "nop YIELD (yield hint)"}, 12581 { 0xffffffff, 0x0000bf20, ARMV7_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateNop, "nop WFE (wait for event hint)"}, 12582 { 0xffffffff, 0x0000bf30, ARMV7_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateNop, "nop WFI (wait for interrupt hint)"}, 12583 { 0xffffffff, 0x0000bf40, ARMV7_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateNop, "nop SEV (send event hint)"}, 12584 { 0xffffff00, 0x0000bf00, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateIT, "it{<x>{<y>{<z>}}} <firstcond>"}, 12585 12586 //---------------------------------------------------------------------- 12587 // Branch instructions 12588 //---------------------------------------------------------------------- 12589 // To resolve ambiguity, "b<c> #imm8" should come after "svc #imm8". 12590 { 0xfffff000, 0x0000d000, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateB, "b<c> #imm8 (outside IT)"}, 12591 { 0xfffff800, 0x0000e000, ARMvAll, eEncodingT2, No_VFP, eSize16, &EmulateInstructionARM::EmulateB, "b<c> #imm11 (outside or last in IT)"}, 12592 { 0xf800d000, 0xf0008000, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, &EmulateInstructionARM::EmulateB, "b<c>.w #imm8 (outside IT)"}, 12593 { 0xf800d000, 0xf0009000, ARMV6T2_ABOVE, eEncodingT4, No_VFP, eSize32, &EmulateInstructionARM::EmulateB, "b<c>.w #imm8 (outside or last in IT)"}, 12594 // J1 == J2 == 1 12595 { 0xf800d000, 0xf000d000, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateBLXImmediate, "bl <label>"}, 12596 // J1 == J2 == 1 12597 { 0xf800d001, 0xf000c000, ARMV5_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateBLXImmediate, "blx <label>"}, 12598 { 0xffffff87, 0x00004780, ARMV5_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateBLXRm, "blx <Rm>"}, 12599 // for example, "bx lr" 12600 { 0xffffff87, 0x00004700, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateBXRm, "bx <Rm>"}, 12601 // bxj 12602 { 0xfff0ffff, 0xf3c08f00, ARMV5J_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateBXJRm, "bxj <Rm>"}, 12603 // compare and branch 12604 { 0xfffff500, 0x0000b100, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateCB, "cb{n}z <Rn>, <label>"}, 12605 // table branch byte 12606 { 0xfff0fff0, 0xe8d0f000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateTB, "tbb<c> <Rn>, <Rm>"}, 12607 // table branch halfword 12608 { 0xfff0fff0, 0xe8d0f010, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateTB, "tbh<c> <Rn>, <Rm>, lsl #1"}, 12609 12610 //---------------------------------------------------------------------- 12611 // Data-processing instructions 12612 //---------------------------------------------------------------------- 12613 // adc (immediate) 12614 { 0xfbe08000, 0xf1400000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateADCImm, "adc{s}<c> <Rd>, <Rn>, #<const>"}, 12615 // adc (register) 12616 { 0xffffffc0, 0x00004140, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateADCReg, "adcs|adc<c> <Rdn>, <Rm>"}, 12617 { 0xffe08000, 0xeb400000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateADCReg, "adc{s}<c>.w <Rd>, <Rn>, <Rm> {,<shift>}"}, 12618 // add (register) 12619 { 0xfffffe00, 0x00001800, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateADDReg, "adds|add<c> <Rd>, <Rn>, <Rm>"}, 12620 // Make sure "add sp, <Rm>" comes before this instruction, so there's no ambiguity decoding the two. 12621 { 0xffffff00, 0x00004400, ARMvAll, eEncodingT2, No_VFP, eSize16, &EmulateInstructionARM::EmulateADDReg, "add<c> <Rdn>, <Rm>"}, 12622 // adr 12623 { 0xfffff800, 0x0000a000, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateADR, "add<c> <Rd>, PC, #<const>"}, 12624 { 0xfbff8000, 0xf2af0000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateADR, "sub<c> <Rd>, PC, #<const>"}, 12625 { 0xfbff8000, 0xf20f0000, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, &EmulateInstructionARM::EmulateADR, "add<c> <Rd>, PC, #<const>"}, 12626 // and (immediate) 12627 { 0xfbe08000, 0xf0000000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateANDImm, "and{s}<c> <Rd>, <Rn>, #<const>"}, 12628 // and (register) 12629 { 0xffffffc0, 0x00004000, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateANDReg, "ands|and<c> <Rdn>, <Rm>"}, 12630 { 0xffe08000, 0xea000000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateANDReg, "and{s}<c>.w <Rd>, <Rn>, <Rm> {,<shift>}"}, 12631 // bic (immediate) 12632 { 0xfbe08000, 0xf0200000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateBICImm, "bic{s}<c> <Rd>, <Rn>, #<const>"}, 12633 // bic (register) 12634 { 0xffffffc0, 0x00004380, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateBICReg, "bics|bic<c> <Rdn>, <Rm>"}, 12635 { 0xffe08000, 0xea200000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateBICReg, "bic{s}<c>.w <Rd>, <Rn>, <Rm> {,<shift>}"}, 12636 // eor (immediate) 12637 { 0xfbe08000, 0xf0800000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateEORImm, "eor{s}<c> <Rd>, <Rn>, #<const>"}, 12638 // eor (register) 12639 { 0xffffffc0, 0x00004040, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateEORReg, "eors|eor<c> <Rdn>, <Rm>"}, 12640 { 0xffe08000, 0xea800000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateEORReg, "eor{s}<c>.w <Rd>, <Rn>, <Rm> {,<shift>}"}, 12641 // orr (immediate) 12642 { 0xfbe08000, 0xf0400000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateORRImm, "orr{s}<c> <Rd>, <Rn>, #<const>"}, 12643 // orr (register) 12644 { 0xffffffc0, 0x00004300, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateORRReg, "orrs|orr<c> <Rdn>, <Rm>"}, 12645 { 0xffe08000, 0xea400000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateORRReg, "orr{s}<c>.w <Rd>, <Rn>, <Rm> {,<shift>}"}, 12646 // rsb (immediate) 12647 { 0xffffffc0, 0x00004240, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateRSBImm, "rsbs|rsb<c> <Rd>, <Rn>, #0"}, 12648 { 0xfbe08000, 0xf1c00000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateRSBImm, "rsb{s}<c>.w <Rd>, <Rn>, #<const>"}, 12649 // rsb (register) 12650 { 0xffe08000, 0xea400000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateRSBReg, "rsb{s}<c>.w <Rd>, <Rn>, <Rm> {,<shift>}"}, 12651 // sbc (immediate) 12652 { 0xfbe08000, 0xf1600000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSBCImm, "sbc{s}<c> <Rd>, <Rn>, #<const>"}, 12653 // sbc (register) 12654 { 0xffffffc0, 0x00004180, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateSBCReg, "sbcs|sbc<c> <Rdn>, <Rm>"}, 12655 { 0xffe08000, 0xeb600000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateSBCReg, "sbc{s}<c>.w <Rd>, <Rn>, <Rm> {,<shift>}"}, 12656 // add (immediate, Thumb) 12657 { 0xfffffe00, 0x00001c00, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateADDImmThumb, "adds|add<c> <Rd>,<Rn>,#<imm3>" }, 12658 { 0xfffff800, 0x00003000, ARMV4T_ABOVE, eEncodingT2, No_VFP, eSize16, &EmulateInstructionARM::EmulateADDImmThumb, "adds|add<c> <Rdn>,#<imm8>" }, 12659 { 0xfbe08000, 0xf1000000, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, &EmulateInstructionARM::EmulateADDImmThumb, "add{s}<c>.w <Rd>,<Rn>,#<const>" }, 12660 { 0xfbf08000, 0xf2000000, ARMV6T2_ABOVE, eEncodingT4, No_VFP, eSize32, &EmulateInstructionARM::EmulateADDImmThumb, "addw<c> <Rd>,<Rn>,#<imm12>" }, 12661 // sub (immediate, Thumb) 12662 { 0xfffffe00, 0x00001e00, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateSUBImmThumb, "subs|sub<c> <Rd>, <Rn> #imm3"}, 12663 { 0xfffff800, 0x00003800, ARMvAll, eEncodingT2, No_VFP, eSize16, &EmulateInstructionARM::EmulateSUBImmThumb, "subs|sub<c> <Rdn>, #imm8"}, 12664 { 0xfbe08000, 0xf1a00000, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBImmThumb, "sub{s}<c>.w <Rd>, <Rn>, #<const>"}, 12665 { 0xfbf08000, 0xf2a00000, ARMV6T2_ABOVE, eEncodingT4, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBImmThumb, "subw<c> <Rd>, <Rn>, #imm12"}, 12666 // sub (sp minus immediate) 12667 { 0xfbef8000, 0xf1ad0000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBSPImm, "sub{s}.w <Rd>, sp, #<const>"}, 12668 { 0xfbff8000, 0xf2ad0000, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBSPImm, "subw<c> <Rd>, sp, #imm12"}, 12669 // sub (register) 12670 { 0xfffffe00, 0x00001a00, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateSUBReg, "subs|sub<c> <Rd>, <Rn>, <Rm>"}, 12671 { 0xffe08000, 0xeba00000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBReg, "sub{s}<c>.w <Rd>, <Rn>, <Rm>{,<shift>}"}, 12672 // teq (immediate) 12673 { 0xfbf08f00, 0xf0900f00, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateTEQImm, "teq<c> <Rn>, #<const>"}, 12674 // teq (register) 12675 { 0xfff08f00, 0xea900f00, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateTEQReg, "teq<c> <Rn>, <Rm> {,<shift>}"}, 12676 // tst (immediate) 12677 { 0xfbf08f00, 0xf0100f00, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateTSTImm, "tst<c> <Rn>, #<const>"}, 12678 // tst (register) 12679 { 0xffffffc0, 0x00004200, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateTSTReg, "tst<c> <Rdn>, <Rm>"}, 12680 { 0xfff08f00, 0xea100f00, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateTSTReg, "tst<c>.w <Rn>, <Rm> {,<shift>}"}, 12681 12682 12683 // move from high register to high register 12684 { 0xffffff00, 0x00004600, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateMOVRdRm, "mov<c> <Rd>, <Rm>"}, 12685 // move from low register to low register 12686 { 0xffffffc0, 0x00000000, ARMvAll, eEncodingT2, No_VFP, eSize16, &EmulateInstructionARM::EmulateMOVRdRm, "movs <Rd>, <Rm>"}, 12687 // mov{s}<c>.w <Rd>, <Rm> 12688 { 0xffeff0f0, 0xea4f0000, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, &EmulateInstructionARM::EmulateMOVRdRm, "mov{s}<c>.w <Rd>, <Rm>"}, 12689 // move immediate 12690 { 0xfffff800, 0x00002000, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateMOVRdImm, "movs|mov<c> <Rd>, #imm8"}, 12691 { 0xfbef8000, 0xf04f0000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateMOVRdImm, "mov{s}<c>.w <Rd>, #<const>"}, 12692 { 0xfbf08000, 0xf2400000, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, &EmulateInstructionARM::EmulateMOVRdImm, "movw<c> <Rd>,#<imm16>"}, 12693 // mvn (immediate) 12694 { 0xfbef8000, 0xf06f0000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateMVNImm, "mvn{s} <Rd>, #<const>"}, 12695 // mvn (register) 12696 { 0xffffffc0, 0x000043c0, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateMVNReg, "mvns|mvn<c> <Rd>, <Rm>"}, 12697 { 0xffef8000, 0xea6f0000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateMVNReg, "mvn{s}<c>.w <Rd>, <Rm> {,<shift>}"}, 12698 // cmn (immediate) 12699 { 0xfbf08f00, 0xf1100f00, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateCMNImm, "cmn<c> <Rn>, #<const>"}, 12700 // cmn (register) 12701 { 0xffffffc0, 0x000042c0, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateCMNReg, "cmn<c> <Rn>, <Rm>"}, 12702 { 0xfff08f00, 0xeb100f00, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateCMNReg, "cmn<c> <Rn>, <Rm> {,<shift>}"}, 12703 // cmp (immediate) 12704 { 0xfffff800, 0x00002800, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateCMPImm, "cmp<c> <Rn>, #imm8"}, 12705 { 0xfbf08f00, 0xf1b00f00, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateCMPImm, "cmp<c>.w <Rn>, #<const>"}, 12706 // cmp (register) (Rn and Rm both from r0-r7) 12707 { 0xffffffc0, 0x00004280, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateCMPReg, "cmp<c> <Rn>, <Rm>"}, 12708 // cmp (register) (Rn and Rm not both from r0-r7) 12709 { 0xffffff00, 0x00004500, ARMvAll, eEncodingT2, No_VFP, eSize16, &EmulateInstructionARM::EmulateCMPReg, "cmp<c> <Rn>, <Rm>"}, 12710 // asr (immediate) 12711 { 0xfffff800, 0x00001000, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateASRImm, "asrs|asr<c> <Rd>, <Rm>, #imm"}, 12712 { 0xffef8030, 0xea4f0020, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateASRImm, "asr{s}<c>.w <Rd>, <Rm>, #imm"}, 12713 // asr (register) 12714 { 0xffffffc0, 0x00004100, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateASRReg, "asrs|asr<c> <Rdn>, <Rm>"}, 12715 { 0xffe0f0f0, 0xfa40f000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateASRReg, "asr{s}<c>.w <Rd>, <Rn>, <Rm>"}, 12716 // lsl (immediate) 12717 { 0xfffff800, 0x00000000, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateLSLImm, "lsls|lsl<c> <Rd>, <Rm>, #imm"}, 12718 { 0xffef8030, 0xea4f0000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateLSLImm, "lsl{s}<c>.w <Rd>, <Rm>, #imm"}, 12719 // lsl (register) 12720 { 0xffffffc0, 0x00004080, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateLSLReg, "lsls|lsl<c> <Rdn>, <Rm>"}, 12721 { 0xffe0f0f0, 0xfa00f000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateLSLReg, "lsl{s}<c>.w <Rd>, <Rn>, <Rm>"}, 12722 // lsr (immediate) 12723 { 0xfffff800, 0x00000800, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateLSRImm, "lsrs|lsr<c> <Rd>, <Rm>, #imm"}, 12724 { 0xffef8030, 0xea4f0010, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateLSRImm, "lsr{s}<c>.w <Rd>, <Rm>, #imm"}, 12725 // lsr (register) 12726 { 0xffffffc0, 0x000040c0, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateLSRReg, "lsrs|lsr<c> <Rdn>, <Rm>"}, 12727 { 0xffe0f0f0, 0xfa20f000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateLSRReg, "lsr{s}<c>.w <Rd>, <Rn>, <Rm>"}, 12728 // rrx is a special case encoding of ror (immediate) 12729 { 0xffeff0f0, 0xea4f0030, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateRRX, "rrx{s}<c>.w <Rd>, <Rm>"}, 12730 // ror (immediate) 12731 { 0xffef8030, 0xea4f0030, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateRORImm, "ror{s}<c>.w <Rd>, <Rm>, #imm"}, 12732 // ror (register) 12733 { 0xffffffc0, 0x000041c0, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateRORReg, "rors|ror<c> <Rdn>, <Rm>"}, 12734 { 0xffe0f0f0, 0xfa60f000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateRORReg, "ror{s}<c>.w <Rd>, <Rn>, <Rm>"}, 12735 // mul 12736 { 0xffffffc0, 0x00004340, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateMUL, "muls <Rdm>,<Rn>,<Rdm>" }, 12737 // mul 12738 { 0xfff0f0f0, 0xfb00f000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateMUL, "mul<c> <Rd>,<Rn>,<Rm>" }, 12739 12740 // subs pc, lr and related instructions 12741 { 0xffffff00, 0xf3de8f00, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBSPcLrEtc, "SUBS<c> PC, LR, #<imm8>" }, 12742 12743 //---------------------------------------------------------------------- 12744 // RFE instructions *** IMPORTANT *** THESE MUST BE LISTED **BEFORE** THE LDM.. Instructions in this table; 12745 // otherwise the wrong instructions will be selected. 12746 //---------------------------------------------------------------------- 12747 12748 { 0xffd0ffff, 0xe810c000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateRFE, "rfedb<c> <Rn>{!}" }, 12749 { 0xffd0ffff, 0xe990c000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateRFE, "rfe{ia}<c> <Rn>{!}" }, 12750 12751 //---------------------------------------------------------------------- 12752 // Load instructions 12753 //---------------------------------------------------------------------- 12754 { 0xfffff800, 0x0000c800, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateLDM, "ldm<c> <Rn>{!} <registers>" }, 12755 { 0xffd02000, 0xe8900000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDM, "ldm<c>.w <Rn>{!} <registers>" }, 12756 { 0xffd00000, 0xe9100000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDMDB, "ldmdb<c> <Rn>{!} <registers>" }, 12757 { 0xfffff800, 0x00006800, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateLDRRtRnImm, "ldr<c> <Rt>, [<Rn>{,#imm}]"}, 12758 { 0xfffff800, 0x00009800, ARMV4T_ABOVE, eEncodingT2, No_VFP, eSize16, &EmulateInstructionARM::EmulateLDRRtRnImm, "ldr<c> <Rt>, [SP{,#imm}]"}, 12759 { 0xfff00000, 0xf8d00000, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRRtRnImm, "ldr<c>.w <Rt>, [<Rn>{,#imm12}]"}, 12760 { 0xfff00800, 0xf8500800, ARMV6T2_ABOVE, eEncodingT4, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRRtRnImm, "ldr<c> <Rt>, [<Rn>{,#+/-<imm8>}]{!}"}, 12761 // Thumb2 PC-relative load into register 12762 { 0xff7f0000, 0xf85f0000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRRtPCRelative, "ldr<c>.w <Rt>, [PC, +/-#imm}]"}, 12763 { 0xfffffe00, 0x00005800, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateLDRRegister, "ldr<c> <Rt>, [<Rn>, <Rm>]" }, 12764 { 0xfff00fc0, 0xf8500000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRRegister, "ldr<c>.w <Rt>, [<Rn>,<Rm>{,LSL #<imm2>}]" }, 12765 { 0xfffff800, 0x00007800, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateLDRBImmediate, "ldrb<c> <Rt>,[<Rn>{,#<imm5>}]" }, 12766 { 0xfff00000, 0xf8900000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRBImmediate, "ldrb<c>.w <Rt>,[<Rn>{,#<imm12>}]" }, 12767 { 0xfff00800, 0xf8100800, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRBImmediate, "ldrb<c> <Rt>,[<Rn>, #+/-<imm8>]{!}" }, 12768 { 0xff7f0000, 0xf81f0000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRBLiteral, "ldrb<c> <Rt>,[...]" }, 12769 { 0xfffffe00, 0x00005c00, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateLDRBRegister, "ldrb<c> <Rt>,[<Rn>,<Rm>]" }, 12770 { 0xfff00fc0, 0xf8100000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRBRegister, "ldrb<c>.w <Rt>,[<Rn>,<Rm>{,LSL #imm2>}]" }, 12771 { 0xfffff800, 0x00008800, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateLDRHImmediate, "ldrh<c> <Rt>, [<Rn>{,#<imm>}]" }, 12772 { 0xfff00000, 0xf8b00000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRHImmediate, "ldrh<c>.w <Rt>,[<Rn>{,#<imm12>}]" }, 12773 { 0xfff00800, 0xf8300800, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRHImmediate, "ldrh<c> <Rt>,[<Rn>,#+/-<imm8>]{!}" }, 12774 { 0xff7f0000, 0xf83f0000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRHLiteral, "ldrh<c> <Rt>, <label>" }, 12775 { 0xfffffe00, 0x00005a00, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateLDRHRegister, "ldrh<c> <Rt>, [<Rn>,<Rm>]" }, 12776 { 0xfff00fc0, 0xf8300000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRHRegister, "ldrh<c>.w <Rt>,[<Rn>,<Rm>{,LSL #<imm2>}]" }, 12777 { 0xfff00000, 0xf9900000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRSBImmediate, "ldrsb<c> <Rt>,[<Rn>,#<imm12>]" }, 12778 { 0xfff00800, 0xf9100800, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRSBImmediate, "ldrsb<c> <Rt>,[<Rn>,#+/-<imm8>]" }, 12779 { 0xff7f0000, 0xf91f0000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRSBLiteral, "ldrsb<c> <Rt>, <label>" }, 12780 { 0xfffffe00, 0x00005600, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateLDRSBRegister, "ldrsb<c> <Rt>,[<Rn>,<Rm>]" }, 12781 { 0xfff00fc0, 0xf9100000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRSBRegister, "ldrsb<c>.w <Rt>,[<Rn>,<Rm>{,LSL #imm2>}]" }, 12782 { 0xfff00000, 0xf9b00000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRSHImmediate, "ldrsh<c> <Rt>,[<Rn>,#<imm12>]" }, 12783 { 0xfff00800, 0xf9300800, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRSHImmediate, "ldrsh<c> <Rt>,[<Rn>,#+/-<imm8>]" }, 12784 { 0xff7f0000, 0xf93f0000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRSHLiteral, "ldrsh<c> <Rt>,<label>" }, 12785 { 0xfffffe00, 0x00005e00, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateLDRSHRegister, "ldrsh<c> <Rt>,[<Rn>,<Rm>]" }, 12786 { 0xfff00fc0, 0xf9300000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRSHRegister, "ldrsh<c>.w <Rt>,[<Rn>,<Rm>{,LSL #<imm2>}]" }, 12787 { 0xfe500000, 0xe8500000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRDImmediate, "ldrd<c> <Rt>, <Rt2>, [<Rn>,#+/-<imm>]!"}, 12788 { 0xfe100f00, 0xec100b00, ARMvAll, eEncodingT1, VFPv2_ABOVE, eSize32, &EmulateInstructionARM::EmulateVLDM, "vldm{mode}<c> <Rn>{!}, <list>"}, 12789 { 0xfe100f00, 0xec100a00, ARMvAll, eEncodingT2, VFPv2v3, eSize32, &EmulateInstructionARM::EmulateVLDM, "vldm{mode}<c> <Rn>{!}, <list>" }, 12790 { 0xffe00f00, 0xed100b00, ARMvAll, eEncodingT1, VFPv2_ABOVE, eSize32, &EmulateInstructionARM::EmulateVLDR, "vldr<c> <Dd>, [<Rn>{,#+/-<imm>}]"}, 12791 { 0xff300f00, 0xed100a00, ARMvAll, eEncodingT2, VFPv2v3, eSize32, &EmulateInstructionARM::EmulateVLDR, "vldr<c> <Sd>, {<Rn>{,#+/-<imm>}]"}, 12792 { 0xffb00000, 0xf9200000, ARMvAll, eEncodingT1, AdvancedSIMD, eSize32, &EmulateInstructionARM::EmulateVLD1Multiple, "vld1<c>.<size> <list>, [<Rn>{@<align>}],<Rm>"}, 12793 { 0xffb00300, 0xf9a00000, ARMvAll, eEncodingT1, AdvancedSIMD, eSize32, &EmulateInstructionARM::EmulateVLD1Single, "vld1<c>.<size> <list>, [<Rn>{@<align>}],<Rm>"}, 12794 { 0xffb00f00, 0xf9a00c00, ARMvAll, eEncodingT1, AdvancedSIMD, eSize32, &EmulateInstructionARM::EmulateVLD1SingleAll, "vld1<c>.<size> <list>, [<Rn>{@<align>}], <Rm>"}, 12795 12796 //---------------------------------------------------------------------- 12797 // Store instructions 12798 //---------------------------------------------------------------------- 12799 { 0xfffff800, 0x0000c000, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateSTM, "stm<c> <Rn>{!} <registers>" }, 12800 { 0xffd00000, 0xe8800000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTM, "stm<c>.w <Rn>{!} <registers>" }, 12801 { 0xffd00000, 0xe9000000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTMDB, "stmdb<c> <Rn>{!} <registers>" }, 12802 { 0xfffff800, 0x00006000, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateSTRThumb, "str<c> <Rt>, [<Rn>{,#<imm>}]" }, 12803 { 0xfffff800, 0x00009000, ARMV4T_ABOVE, eEncodingT2, No_VFP, eSize16, &EmulateInstructionARM::EmulateSTRThumb, "str<c> <Rt>, [SP,#<imm>]" }, 12804 { 0xfff00000, 0xf8c00000, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTRThumb, "str<c>.w <Rt>, [<Rn>,#<imm12>]" }, 12805 { 0xfff00800, 0xf8400800, ARMV6T2_ABOVE, eEncodingT4, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTRThumb, "str<c> <Rt>, [<Rn>,#+/-<imm8>]" }, 12806 { 0xfffffe00, 0x00005000, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateSTRRegister, "str<c> <Rt> ,{<Rn>, <Rm>]" }, 12807 { 0xfff00fc0, 0xf8400000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTRRegister, "str<c>.w <Rt>, [<Rn>, <Rm> {lsl #imm2>}]" }, 12808 { 0xfffff800, 0x00007000, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateSTRBThumb, "strb<c> <Rt>, [<Rn>, #<imm5>]" }, 12809 { 0xfff00000, 0xf8800000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTRBThumb, "strb<c>.w <Rt>, [<Rn>, #<imm12>]" }, 12810 { 0xfff00800, 0xf8000800, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTRBThumb, "strb<c> <Rt> ,[<Rn>, #+/-<imm8>]{!}" }, 12811 { 0xfffffe00, 0x00005200, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateSTRHRegister, "strh<c> <Rt>,[<Rn>,<Rm>]" }, 12812 { 0xfff00fc0, 0xf8200000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTRHRegister, "strh<c>.w <Rt>,[<Rn>,<Rm>{,LSL #<imm2>}]" }, 12813 { 0xfff00000, 0xe8400000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTREX, "strex<c> <Rd>, <Rt>, [<Rn{,#<imm>}]" }, 12814 { 0xfe500000, 0xe8400000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTRDImm, "strd<c> <Rt>, <Rt2>, [<Rn>, #+/-<imm>]!"}, 12815 { 0xfe100f00, 0xec000b00, ARMvAll, eEncodingT1, VFPv2_ABOVE, eSize32, &EmulateInstructionARM::EmulateVSTM, "vstm{mode}<c> <Rn>{!}, <list>"}, 12816 { 0xfea00f00, 0xec000a00, ARMvAll, eEncodingT2, VFPv2v3, eSize32, &EmulateInstructionARM::EmulateVSTM, "vstm{mode}<c> <Rn>{!}, <list>"}, 12817 { 0xff300f00, 0xed000b00, ARMvAll, eEncodingT1, VFPv2_ABOVE, eSize32, &EmulateInstructionARM::EmulateVSTR, "vstr<c> <Dd>, [<Rn>{,#+/-<imm>}]"}, 12818 { 0xff300f00, 0xed000a00, ARMvAll, eEncodingT2, VFPv2v3, eSize32, &EmulateInstructionARM::EmulateVSTR, "vstr<c> <Sd>, [<Rn>{,#+/-<imm>}]"}, 12819 { 0xffb00000, 0xf9000000, ARMvAll, eEncodingT1, AdvancedSIMD, eSize32, &EmulateInstructionARM::EmulateVST1Multiple, "vst1<c>.<size> <list>, [<Rn>{@<align>}], <Rm>"}, 12820 { 0xffb00300, 0xf9800000, ARMvAll, eEncodingT1, AdvancedSIMD, eSize32, &EmulateInstructionARM::EmulateVST1Single, "vst1<c>.<size> <list>, [<Rn>{@<align>}], <Rm>"}, 12821 12822 //---------------------------------------------------------------------- 12823 // Other instructions 12824 //---------------------------------------------------------------------- 12825 { 0xffffffc0, 0x0000b240, ARMV6_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateSXTB, "sxtb<c> <Rd>,<Rm>" }, 12826 { 0xfffff080, 0xfa4ff080, ARMV6_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateSXTB, "sxtb<c>.w <Rd>,<Rm>{,<rotation>}" }, 12827 { 0xffffffc0, 0x0000b200, ARMV6_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateSXTH, "sxth<c> <Rd>,<Rm>" }, 12828 { 0xfffff080, 0xfa0ff080, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateSXTH, "sxth<c>.w <Rd>,<Rm>{,<rotation>}" }, 12829 { 0xffffffc0, 0x0000b2c0, ARMV6_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateUXTB, "uxtb<c> <Rd>,<Rm>" }, 12830 { 0xfffff080, 0xfa5ff080, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateUXTB, "uxtb<c>.w <Rd>,<Rm>{,<rotation>}" }, 12831 { 0xffffffc0, 0x0000b280, ARMV6_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateUXTH, "uxth<c> <Rd>,<Rm>" }, 12832 { 0xfffff080, 0xfa1ff080, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateUXTH, "uxth<c>.w <Rd>,<Rm>{,<rotation>}" }, 12833 }; 12834 12835 const size_t k_num_thumb_opcodes = sizeof(g_thumb_opcodes)/sizeof(ARMOpcode); 12836 for (size_t i=0; i<k_num_thumb_opcodes; ++i) 12837 { 12838 if ((g_thumb_opcodes[i].mask & opcode) == g_thumb_opcodes[i].value && 12839 (g_thumb_opcodes[i].variants & arm_isa) != 0) 12840 return &g_thumb_opcodes[i]; 12841 } 12842 return NULL; 12843} 12844 12845bool 12846EmulateInstructionARM::SetArchitecture (const ArchSpec &arch) 12847{ 12848 m_arch = arch; 12849 m_arm_isa = 0; 12850 const char *arch_cstr = arch.GetArchitectureName (); 12851 if (arch_cstr) 12852 { 12853 if (0 == ::strcasecmp(arch_cstr, "armv4t")) m_arm_isa = ARMv4T; 12854 else if (0 == ::strcasecmp(arch_cstr, "armv5tej")) m_arm_isa = ARMv5TEJ; 12855 else if (0 == ::strcasecmp(arch_cstr, "armv5te")) m_arm_isa = ARMv5TE; 12856 else if (0 == ::strcasecmp(arch_cstr, "armv5t")) m_arm_isa = ARMv5T; 12857 else if (0 == ::strcasecmp(arch_cstr, "armv6k")) m_arm_isa = ARMv6K; 12858 else if (0 == ::strcasecmp(arch_cstr, "armv6t2")) m_arm_isa = ARMv6T2; 12859 else if (0 == ::strcasecmp(arch_cstr, "armv7s")) m_arm_isa = ARMv7S; 12860 else if (0 == ::strcasecmp(arch_cstr, "arm")) m_arm_isa = ARMvAll; 12861 else if (0 == ::strcasecmp(arch_cstr, "thumb")) m_arm_isa = ARMvAll; 12862 else if (0 == ::strncasecmp(arch_cstr,"armv4", 5)) m_arm_isa = ARMv4; 12863 else if (0 == ::strncasecmp(arch_cstr,"armv6", 5)) m_arm_isa = ARMv6; 12864 else if (0 == ::strncasecmp(arch_cstr,"armv7", 5)) m_arm_isa = ARMv7; 12865 else if (0 == ::strncasecmp(arch_cstr,"armv8", 5)) m_arm_isa = ARMv8; 12866 } 12867 return m_arm_isa != 0; 12868} 12869 12870bool 12871EmulateInstructionARM::SetInstruction (const Opcode &insn_opcode, const Address &inst_addr, Target *target) 12872{ 12873 if (EmulateInstruction::SetInstruction (insn_opcode, inst_addr, target)) 12874 { 12875 if (m_arch.GetTriple().getArch() == llvm::Triple::thumb) 12876 m_opcode_mode = eModeThumb; 12877 else 12878 { 12879 AddressClass addr_class = inst_addr.GetAddressClass(); 12880 12881 if ((addr_class == eAddressClassCode) || (addr_class == eAddressClassUnknown)) 12882 m_opcode_mode = eModeARM; 12883 else if (addr_class == eAddressClassCodeAlternateISA) 12884 m_opcode_mode = eModeThumb; 12885 else 12886 return false; 12887 } 12888 if (m_opcode_mode == eModeThumb) 12889 m_opcode_cpsr = CPSR_MODE_USR | MASK_CPSR_T; 12890 else 12891 m_opcode_cpsr = CPSR_MODE_USR; 12892 return true; 12893 } 12894 return false; 12895} 12896 12897bool 12898EmulateInstructionARM::ReadInstruction () 12899{ 12900 bool success = false; 12901 m_opcode_cpsr = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS, 0, &success); 12902 if (success) 12903 { 12904 addr_t pc = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, LLDB_INVALID_ADDRESS, &success); 12905 if (success) 12906 { 12907 Context read_inst_context; 12908 read_inst_context.type = eContextReadOpcode; 12909 read_inst_context.SetNoArgs (); 12910 12911 if (m_opcode_cpsr & MASK_CPSR_T) 12912 { 12913 m_opcode_mode = eModeThumb; 12914 uint32_t thumb_opcode = MemARead(read_inst_context, pc, 2, 0, &success); 12915 12916 if (success) 12917 { 12918 if ((thumb_opcode & 0xe000) != 0xe000 || ((thumb_opcode & 0x1800u) == 0)) 12919 { 12920 m_opcode.SetOpcode16 (thumb_opcode, GetByteOrder()); 12921 } 12922 else 12923 { 12924 m_opcode.SetOpcode32 ((thumb_opcode << 16) | MemARead(read_inst_context, pc + 2, 2, 0, &success), GetByteOrder()); 12925 } 12926 } 12927 } 12928 else 12929 { 12930 m_opcode_mode = eModeARM; 12931 m_opcode.SetOpcode32 (MemARead(read_inst_context, pc, 4, 0, &success), GetByteOrder()); 12932 } 12933 } 12934 } 12935 if (!success) 12936 { 12937 m_opcode_mode = eModeInvalid; 12938 m_addr = LLDB_INVALID_ADDRESS; 12939 } 12940 return success; 12941} 12942 12943uint32_t 12944EmulateInstructionARM::ArchVersion () 12945{ 12946 return m_arm_isa; 12947} 12948 12949bool 12950EmulateInstructionARM::ConditionPassed (const uint32_t opcode, bool *is_conditional) 12951{ 12952 // If we are ignoring conditions, then always return true. 12953 // this allows us to iterate over disassembly code and still 12954 // emulate an instruction even if we don't have all the right 12955 // bits set in the CPSR register... 12956 if (m_ignore_conditions) 12957 return true; 12958 12959 if (is_conditional) 12960 *is_conditional = true; 12961 12962 const uint32_t cond = CurrentCond (opcode); 12963 12964 if (cond == UINT32_MAX) 12965 return false; 12966 12967 bool result = false; 12968 switch (UnsignedBits(cond, 3, 1)) 12969 { 12970 case 0: 12971 if (m_opcode_cpsr == 0) 12972 result = true; 12973 else 12974 result = (m_opcode_cpsr & MASK_CPSR_Z) != 0; 12975 break; 12976 case 1: 12977 if (m_opcode_cpsr == 0) 12978 result = true; 12979 else 12980 result = (m_opcode_cpsr & MASK_CPSR_C) != 0; 12981 break; 12982 case 2: 12983 if (m_opcode_cpsr == 0) 12984 result = true; 12985 else 12986 result = (m_opcode_cpsr & MASK_CPSR_N) != 0; 12987 break; 12988 case 3: 12989 if (m_opcode_cpsr == 0) 12990 result = true; 12991 else 12992 result = (m_opcode_cpsr & MASK_CPSR_V) != 0; 12993 break; 12994 case 4: 12995 if (m_opcode_cpsr == 0) 12996 result = true; 12997 else 12998 result = ((m_opcode_cpsr & MASK_CPSR_C) != 0) && ((m_opcode_cpsr & MASK_CPSR_Z) == 0); 12999 break; 13000 case 5: 13001 if (m_opcode_cpsr == 0) 13002 result = true; 13003 else 13004 { 13005 bool n = (m_opcode_cpsr & MASK_CPSR_N); 13006 bool v = (m_opcode_cpsr & MASK_CPSR_V); 13007 result = n == v; 13008 } 13009 break; 13010 case 6: 13011 if (m_opcode_cpsr == 0) 13012 result = true; 13013 else 13014 { 13015 bool n = (m_opcode_cpsr & MASK_CPSR_N); 13016 bool v = (m_opcode_cpsr & MASK_CPSR_V); 13017 result = n == v && ((m_opcode_cpsr & MASK_CPSR_Z) == 0); 13018 } 13019 break; 13020 case 7: 13021 // Always execute (cond == 0b1110, or the special 0b1111 which gives 13022 // opcodes different meanings, but always means execution happpens. 13023 if (is_conditional) 13024 *is_conditional = false; 13025 result = true; 13026 break; 13027 } 13028 13029 if (cond & 1) 13030 result = !result; 13031 return result; 13032} 13033 13034uint32_t 13035EmulateInstructionARM::CurrentCond (const uint32_t opcode) 13036{ 13037 switch (m_opcode_mode) 13038 { 13039 case eModeInvalid: 13040 break; 13041 13042 case eModeARM: 13043 return UnsignedBits(opcode, 31, 28); 13044 13045 case eModeThumb: 13046 // For T1 and T3 encodings of the Branch instruction, it returns the 4-bit 13047 // 'cond' field of the encoding. 13048 { 13049 const uint32_t byte_size = m_opcode.GetByteSize(); 13050 if (byte_size == 2) 13051 { 13052 if (Bits32(opcode, 15, 12) == 0x0d && Bits32(opcode, 11, 7) != 0x0f) 13053 return Bits32(opcode, 11, 7); 13054 } 13055 else if (byte_size == 4) 13056 { 13057 if (Bits32(opcode, 31, 27) == 0x1e && 13058 Bits32(opcode, 15, 14) == 0x02 && 13059 Bits32(opcode, 12, 12) == 0x00 && 13060 Bits32(opcode, 25, 22) <= 0x0d) 13061 { 13062 return Bits32(opcode, 25, 22); 13063 } 13064 } 13065 else 13066 // We have an invalid thumb instruction, let's bail out. 13067 break; 13068 13069 return m_it_session.GetCond(); 13070 } 13071 } 13072 return UINT32_MAX; // Return invalid value 13073} 13074 13075bool 13076EmulateInstructionARM::InITBlock() 13077{ 13078 return CurrentInstrSet() == eModeThumb && m_it_session.InITBlock(); 13079} 13080 13081bool 13082EmulateInstructionARM::LastInITBlock() 13083{ 13084 return CurrentInstrSet() == eModeThumb && m_it_session.LastInITBlock(); 13085} 13086 13087bool 13088EmulateInstructionARM::BadMode (uint32_t mode) 13089{ 13090 13091 switch (mode) 13092 { 13093 case 16: return false; // '10000' 13094 case 17: return false; // '10001' 13095 case 18: return false; // '10010' 13096 case 19: return false; // '10011' 13097 case 22: return false; // '10110' 13098 case 23: return false; // '10111' 13099 case 27: return false; // '11011' 13100 case 31: return false; // '11111' 13101 default: return true; 13102 } 13103 return true; 13104} 13105 13106bool 13107EmulateInstructionARM::CurrentModeIsPrivileged () 13108{ 13109 uint32_t mode = Bits32 (m_opcode_cpsr, 4, 0); 13110 13111 if (BadMode (mode)) 13112 return false; 13113 13114 if (mode == 16) 13115 return false; 13116 13117 return true; 13118} 13119 13120void 13121EmulateInstructionARM::CPSRWriteByInstr (uint32_t value, uint32_t bytemask, bool affect_execstate) 13122{ 13123 bool privileged = CurrentModeIsPrivileged(); 13124 13125 uint32_t tmp_cpsr = Bits32 (m_opcode_cpsr, 23, 20) << 20; 13126 13127 if (BitIsSet (bytemask, 3)) 13128 { 13129 tmp_cpsr = tmp_cpsr | (Bits32 (value, 31, 27) << 27); 13130 if (affect_execstate) 13131 tmp_cpsr = tmp_cpsr | (Bits32 (value, 26, 24) << 24); 13132 } 13133 13134 if (BitIsSet (bytemask, 2)) 13135 { 13136 tmp_cpsr = tmp_cpsr | (Bits32 (value, 19, 16) << 16); 13137 } 13138 13139 if (BitIsSet (bytemask, 1)) 13140 { 13141 if (affect_execstate) 13142 tmp_cpsr = tmp_cpsr | (Bits32 (value, 15, 10) << 10); 13143 tmp_cpsr = tmp_cpsr | (Bit32 (value, 9) << 9); 13144 if (privileged) 13145 tmp_cpsr = tmp_cpsr | (Bit32 (value, 8) << 8); 13146 } 13147 13148 if (BitIsSet (bytemask, 0)) 13149 { 13150 if (privileged) 13151 tmp_cpsr = tmp_cpsr | (Bits32 (value, 7, 6) << 6); 13152 if (affect_execstate) 13153 tmp_cpsr = tmp_cpsr | (Bit32 (value, 5) << 5); 13154 if (privileged) 13155 tmp_cpsr = tmp_cpsr | Bits32 (value, 4, 0); 13156 } 13157 13158 m_opcode_cpsr = tmp_cpsr; 13159} 13160 13161 13162bool 13163EmulateInstructionARM::BranchWritePC (const Context &context, uint32_t addr) 13164{ 13165 addr_t target; 13166 13167 // Check the current instruction set. 13168 if (CurrentInstrSet() == eModeARM) 13169 target = addr & 0xfffffffc; 13170 else 13171 target = addr & 0xfffffffe; 13172 13173 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, target)) 13174 return false; 13175 13176 return true; 13177} 13178 13179// As a side effect, BXWritePC sets context.arg2 to eModeARM or eModeThumb by inspecting addr. 13180bool 13181EmulateInstructionARM::BXWritePC (Context &context, uint32_t addr) 13182{ 13183 addr_t target; 13184 // If the CPSR is changed due to switching between ARM and Thumb ISETSTATE, 13185 // we want to record it and issue a WriteRegister callback so the clients 13186 // can track the mode changes accordingly. 13187 bool cpsr_changed = false; 13188 13189 if (BitIsSet(addr, 0)) 13190 { 13191 if (CurrentInstrSet() != eModeThumb) 13192 { 13193 SelectInstrSet(eModeThumb); 13194 cpsr_changed = true; 13195 } 13196 target = addr & 0xfffffffe; 13197 context.SetISA (eModeThumb); 13198 } 13199 else if (BitIsClear(addr, 1)) 13200 { 13201 if (CurrentInstrSet() != eModeARM) 13202 { 13203 SelectInstrSet(eModeARM); 13204 cpsr_changed = true; 13205 } 13206 target = addr & 0xfffffffc; 13207 context.SetISA (eModeARM); 13208 } 13209 else 13210 return false; // address<1:0> == '10' => UNPREDICTABLE 13211 13212 if (cpsr_changed) 13213 { 13214 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS, m_new_inst_cpsr)) 13215 return false; 13216 } 13217 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, target)) 13218 return false; 13219 13220 return true; 13221} 13222 13223// Dispatches to either BXWritePC or BranchWritePC based on architecture versions. 13224bool 13225EmulateInstructionARM::LoadWritePC (Context &context, uint32_t addr) 13226{ 13227 if (ArchVersion() >= ARMv5T) 13228 return BXWritePC(context, addr); 13229 else 13230 return BranchWritePC((const Context)context, addr); 13231} 13232 13233// Dispatches to either BXWritePC or BranchWritePC based on architecture versions and current instruction set. 13234bool 13235EmulateInstructionARM::ALUWritePC (Context &context, uint32_t addr) 13236{ 13237 if (ArchVersion() >= ARMv7 && CurrentInstrSet() == eModeARM) 13238 return BXWritePC(context, addr); 13239 else 13240 return BranchWritePC((const Context)context, addr); 13241} 13242 13243EmulateInstructionARM::Mode 13244EmulateInstructionARM::CurrentInstrSet () 13245{ 13246 return m_opcode_mode; 13247} 13248 13249// Set the 'T' bit of our CPSR. The m_opcode_mode gets updated when the next 13250// ReadInstruction() is performed. This function has a side effect of updating 13251// the m_new_inst_cpsr member variable if necessary. 13252bool 13253EmulateInstructionARM::SelectInstrSet (Mode arm_or_thumb) 13254{ 13255 m_new_inst_cpsr = m_opcode_cpsr; 13256 switch (arm_or_thumb) 13257 { 13258 default: 13259 return false; 13260 case eModeARM: 13261 // Clear the T bit. 13262 m_new_inst_cpsr &= ~MASK_CPSR_T; 13263 break; 13264 case eModeThumb: 13265 // Set the T bit. 13266 m_new_inst_cpsr |= MASK_CPSR_T; 13267 break; 13268 } 13269 return true; 13270} 13271 13272// This function returns TRUE if the processor currently provides support for 13273// unaligned memory accesses, or FALSE otherwise. This is always TRUE in ARMv7, 13274// controllable by the SCTLR.U bit in ARMv6, and always FALSE before ARMv6. 13275bool 13276EmulateInstructionARM::UnalignedSupport() 13277{ 13278 return (ArchVersion() >= ARMv7); 13279} 13280 13281// The main addition and subtraction instructions can produce status information 13282// about both unsigned carry and signed overflow conditions. This status 13283// information can be used to synthesize multi-word additions and subtractions. 13284EmulateInstructionARM::AddWithCarryResult 13285EmulateInstructionARM::AddWithCarry (uint32_t x, uint32_t y, uint8_t carry_in) 13286{ 13287 uint32_t result; 13288 uint8_t carry_out; 13289 uint8_t overflow; 13290 13291 uint64_t unsigned_sum = x + y + carry_in; 13292 int64_t signed_sum = (int32_t)x + (int32_t)y + (int32_t)carry_in; 13293 13294 result = UnsignedBits(unsigned_sum, 31, 0); 13295// carry_out = (result == unsigned_sum ? 0 : 1); 13296 overflow = ((int32_t)result == signed_sum ? 0 : 1); 13297 13298 if (carry_in) 13299 carry_out = ((int32_t) x >= (int32_t) (~y)) ? 1 : 0; 13300 else 13301 carry_out = ((int32_t) x > (int32_t) y) ? 1 : 0; 13302 13303 AddWithCarryResult res = { result, carry_out, overflow }; 13304 return res; 13305} 13306 13307uint32_t 13308EmulateInstructionARM::ReadCoreReg(uint32_t num, bool *success) 13309{ 13310 uint32_t reg_kind, reg_num; 13311 switch (num) 13312 { 13313 case SP_REG: 13314 reg_kind = eRegisterKindGeneric; 13315 reg_num = LLDB_REGNUM_GENERIC_SP; 13316 break; 13317 case LR_REG: 13318 reg_kind = eRegisterKindGeneric; 13319 reg_num = LLDB_REGNUM_GENERIC_RA; 13320 break; 13321 case PC_REG: 13322 reg_kind = eRegisterKindGeneric; 13323 reg_num = LLDB_REGNUM_GENERIC_PC; 13324 break; 13325 default: 13326 if (num < SP_REG) 13327 { 13328 reg_kind = eRegisterKindDWARF; 13329 reg_num = dwarf_r0 + num; 13330 } 13331 else 13332 { 13333 //assert(0 && "Invalid register number"); 13334 *success = false; 13335 return UINT32_MAX; 13336 } 13337 break; 13338 } 13339 13340 // Read our register. 13341 uint32_t val = ReadRegisterUnsigned (reg_kind, reg_num, 0, success); 13342 13343 // When executing an ARM instruction , PC reads as the address of the current 13344 // instruction plus 8. 13345 // When executing a Thumb instruction , PC reads as the address of the current 13346 // instruction plus 4. 13347 if (num == 15) 13348 { 13349 if (CurrentInstrSet() == eModeARM) 13350 val += 8; 13351 else 13352 val += 4; 13353 } 13354 13355 return val; 13356} 13357 13358// Write the result to the ARM core register Rd, and optionally update the 13359// condition flags based on the result. 13360// 13361// This helper method tries to encapsulate the following pseudocode from the 13362// ARM Architecture Reference Manual: 13363// 13364// if d == 15 then // Can only occur for encoding A1 13365// ALUWritePC(result); // setflags is always FALSE here 13366// else 13367// R[d] = result; 13368// if setflags then 13369// APSR.N = result<31>; 13370// APSR.Z = IsZeroBit(result); 13371// APSR.C = carry; 13372// // APSR.V unchanged 13373// 13374// In the above case, the API client does not pass in the overflow arg, which 13375// defaults to ~0u. 13376bool 13377EmulateInstructionARM::WriteCoreRegOptionalFlags (Context &context, 13378 const uint32_t result, 13379 const uint32_t Rd, 13380 bool setflags, 13381 const uint32_t carry, 13382 const uint32_t overflow) 13383{ 13384 if (Rd == 15) 13385 { 13386 if (!ALUWritePC (context, result)) 13387 return false; 13388 } 13389 else 13390 { 13391 uint32_t reg_kind, reg_num; 13392 switch (Rd) 13393 { 13394 case SP_REG: 13395 reg_kind = eRegisterKindGeneric; 13396 reg_num = LLDB_REGNUM_GENERIC_SP; 13397 break; 13398 case LR_REG: 13399 reg_kind = eRegisterKindGeneric; 13400 reg_num = LLDB_REGNUM_GENERIC_RA; 13401 break; 13402 default: 13403 reg_kind = eRegisterKindDWARF; 13404 reg_num = dwarf_r0 + Rd; 13405 } 13406 if (!WriteRegisterUnsigned (context, reg_kind, reg_num, result)) 13407 return false; 13408 if (setflags) 13409 return WriteFlags (context, result, carry, overflow); 13410 } 13411 return true; 13412} 13413 13414// This helper method tries to encapsulate the following pseudocode from the 13415// ARM Architecture Reference Manual: 13416// 13417// APSR.N = result<31>; 13418// APSR.Z = IsZeroBit(result); 13419// APSR.C = carry; 13420// APSR.V = overflow 13421// 13422// Default arguments can be specified for carry and overflow parameters, which means 13423// not to update the respective flags. 13424bool 13425EmulateInstructionARM::WriteFlags (Context &context, 13426 const uint32_t result, 13427 const uint32_t carry, 13428 const uint32_t overflow) 13429{ 13430 m_new_inst_cpsr = m_opcode_cpsr; 13431 SetBit32(m_new_inst_cpsr, CPSR_N_POS, Bit32(result, CPSR_N_POS)); 13432 SetBit32(m_new_inst_cpsr, CPSR_Z_POS, result == 0 ? 1 : 0); 13433 if (carry != ~0u) 13434 SetBit32(m_new_inst_cpsr, CPSR_C_POS, carry); 13435 if (overflow != ~0u) 13436 SetBit32(m_new_inst_cpsr, CPSR_V_POS, overflow); 13437 if (m_new_inst_cpsr != m_opcode_cpsr) 13438 { 13439 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS, m_new_inst_cpsr)) 13440 return false; 13441 } 13442 return true; 13443} 13444 13445bool 13446EmulateInstructionARM::EvaluateInstruction (uint32_t evaluate_options) 13447{ 13448 // Advance the ITSTATE bits to their values for the next instruction. 13449 if (m_opcode_mode == eModeThumb && m_it_session.InITBlock()) 13450 m_it_session.ITAdvance(); 13451 13452 ARMOpcode *opcode_data = NULL; 13453 13454 if (m_opcode_mode == eModeThumb) 13455 opcode_data = GetThumbOpcodeForInstruction (m_opcode.GetOpcode32(), m_arm_isa); 13456 else if (m_opcode_mode == eModeARM) 13457 opcode_data = GetARMOpcodeForInstruction (m_opcode.GetOpcode32(), m_arm_isa); 13458 13459 if (opcode_data == NULL) 13460 return false; 13461 13462 const bool auto_advance_pc = evaluate_options & eEmulateInstructionOptionAutoAdvancePC; 13463 m_ignore_conditions = evaluate_options & eEmulateInstructionOptionIgnoreConditions; 13464 13465 bool success = false; 13466 if (m_opcode_cpsr == 0 || m_ignore_conditions == false) 13467 { 13468 m_opcode_cpsr = ReadRegisterUnsigned (eRegisterKindDWARF, 13469 dwarf_cpsr, 13470 0, 13471 &success); 13472 } 13473 13474 // Only return false if we are unable to read the CPSR if we care about conditions 13475 if (success == false && m_ignore_conditions == false) 13476 return false; 13477 13478 uint32_t orig_pc_value = 0; 13479 if (auto_advance_pc) 13480 { 13481 orig_pc_value = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc, 0, &success); 13482 if (!success) 13483 return false; 13484 } 13485 13486 // Call the Emulate... function. 13487 success = (this->*opcode_data->callback) (m_opcode.GetOpcode32(), opcode_data->encoding); 13488 if (!success) 13489 return false; 13490 13491 if (auto_advance_pc) 13492 { 13493 uint32_t after_pc_value = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc, 0, &success); 13494 if (!success) 13495 return false; 13496 13497 if (auto_advance_pc && (after_pc_value == orig_pc_value)) 13498 { 13499 if (opcode_data->size == eSize32) 13500 after_pc_value += 4; 13501 else if (opcode_data->size == eSize16) 13502 after_pc_value += 2; 13503 13504 EmulateInstruction::Context context; 13505 context.type = eContextAdvancePC; 13506 context.SetNoArgs(); 13507 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc, after_pc_value)) 13508 return false; 13509 13510 } 13511 } 13512 return true; 13513} 13514 13515bool 13516EmulateInstructionARM::TestEmulation (Stream *out_stream, ArchSpec &arch, OptionValueDictionary *test_data) 13517{ 13518 if (!test_data) 13519 { 13520 out_stream->Printf ("TestEmulation: Missing test data.\n"); 13521 return false; 13522 } 13523 13524 static ConstString opcode_key ("opcode"); 13525 static ConstString before_key ("before_state"); 13526 static ConstString after_key ("after_state"); 13527 13528 OptionValueSP value_sp = test_data->GetValueForKey (opcode_key); 13529 13530 uint32_t test_opcode; 13531 if ((value_sp.get() == NULL) || (value_sp->GetType() != OptionValue::eTypeUInt64)) 13532 { 13533 out_stream->Printf ("TestEmulation: Error reading opcode from test file.\n"); 13534 return false; 13535 } 13536 test_opcode = value_sp->GetUInt64Value (); 13537 13538 if (arch.GetTriple().getArch() == llvm::Triple::arm) 13539 { 13540 m_opcode_mode = eModeARM; 13541 m_opcode.SetOpcode32 (test_opcode, GetByteOrder()); 13542 } 13543 else if (arch.GetTriple().getArch() == llvm::Triple::thumb) 13544 { 13545 m_opcode_mode = eModeThumb; 13546 if (test_opcode < 0x10000) 13547 m_opcode.SetOpcode16 (test_opcode, GetByteOrder()); 13548 else 13549 m_opcode.SetOpcode32 (test_opcode, GetByteOrder()); 13550 13551 } 13552 else 13553 { 13554 out_stream->Printf ("TestEmulation: Invalid arch.\n"); 13555 return false; 13556 } 13557 13558 EmulationStateARM before_state; 13559 EmulationStateARM after_state; 13560 13561 value_sp = test_data->GetValueForKey (before_key); 13562 if ((value_sp.get() == NULL) || (value_sp->GetType() != OptionValue::eTypeDictionary)) 13563 { 13564 out_stream->Printf ("TestEmulation: Failed to find 'before' state.\n"); 13565 return false; 13566 } 13567 13568 OptionValueDictionary *state_dictionary = value_sp->GetAsDictionary (); 13569 if (!before_state.LoadStateFromDictionary (state_dictionary)) 13570 { 13571 out_stream->Printf ("TestEmulation: Failed loading 'before' state.\n"); 13572 return false; 13573 } 13574 13575 value_sp = test_data->GetValueForKey (after_key); 13576 if ((value_sp.get() == NULL) || (value_sp->GetType() != OptionValue::eTypeDictionary)) 13577 { 13578 out_stream->Printf ("TestEmulation: Failed to find 'after' state.\n"); 13579 return false; 13580 } 13581 13582 state_dictionary = value_sp->GetAsDictionary (); 13583 if (!after_state.LoadStateFromDictionary (state_dictionary)) 13584 { 13585 out_stream->Printf ("TestEmulation: Failed loading 'after' state.\n"); 13586 return false; 13587 } 13588 13589 SetBaton ((void *) &before_state); 13590 SetCallbacks (&EmulationStateARM::ReadPseudoMemory, 13591 &EmulationStateARM::WritePseudoMemory, 13592 &EmulationStateARM::ReadPseudoRegister, 13593 &EmulationStateARM::WritePseudoRegister); 13594 13595 bool success = EvaluateInstruction (eEmulateInstructionOptionAutoAdvancePC); 13596 if (!success) 13597 { 13598 out_stream->Printf ("TestEmulation: EvaluateInstruction() failed.\n"); 13599 return false; 13600 } 13601 13602 success = before_state.CompareState (after_state); 13603 if (!success) 13604 out_stream->Printf ("TestEmulation: 'before' and 'after' states do not match.\n"); 13605 13606 return success; 13607} 13608// 13609// 13610//const char * 13611//EmulateInstructionARM::GetRegisterName (uint32_t reg_kind, uint32_t reg_num) 13612//{ 13613// if (reg_kind == eRegisterKindGeneric) 13614// { 13615// switch (reg_num) 13616// { 13617// case LLDB_REGNUM_GENERIC_PC: return "pc"; 13618// case LLDB_REGNUM_GENERIC_SP: return "sp"; 13619// case LLDB_REGNUM_GENERIC_FP: return "fp"; 13620// case LLDB_REGNUM_GENERIC_RA: return "lr"; 13621// case LLDB_REGNUM_GENERIC_FLAGS: return "cpsr"; 13622// default: return NULL; 13623// } 13624// } 13625// else if (reg_kind == eRegisterKindDWARF) 13626// { 13627// return GetARMDWARFRegisterName (reg_num); 13628// } 13629// return NULL; 13630//} 13631// 13632bool 13633EmulateInstructionARM::CreateFunctionEntryUnwind (UnwindPlan &unwind_plan) 13634{ 13635 unwind_plan.Clear(); 13636 unwind_plan.SetRegisterKind (eRegisterKindDWARF); 13637 13638 UnwindPlan::RowSP row(new UnwindPlan::Row); 13639 13640 // Our previous Call Frame Address is the stack pointer 13641 row->SetCFARegister (dwarf_sp); 13642 13643 // Our previous PC is in the LR 13644 row->SetRegisterLocationToRegister(dwarf_pc, dwarf_lr, true); 13645 unwind_plan.AppendRow (row); 13646 13647 // All other registers are the same. 13648 13649 unwind_plan.SetSourceName ("EmulateInstructionARM"); 13650 unwind_plan.SetSourcedFromCompiler (eLazyBoolNo); 13651 unwind_plan.SetUnwindPlanValidAtAllInstructions (eLazyBoolYes); 13652 return true; 13653} 13654