EmulateInstructionARM.cpp revision dfb2e20724a90a4a10558ddaee18b72a1c51e499
1//===-- EmulateInstructionARM.cpp -------------------------------*- C++ -*-===// 2// 3// The LLVM Compiler Infrastructure 4// 5// This file is distributed under the University of Illinois Open Source 6// License. See LICENSE.TXT for details. 7// 8//===----------------------------------------------------------------------===// 9 10#include <stdlib.h> 11 12#include "EmulateInstructionARM.h" 13#include "EmulationStateARM.h" 14#include "lldb/Core/ArchSpec.h" 15#include "lldb/Core/Address.h" 16#include "lldb/Core/ConstString.h" 17#include "lldb/Core/PluginManager.h" 18#include "lldb/Core/Stream.h" 19 20#include "Plugins/Process/Utility/ARMDefines.h" 21#include "Plugins/Process/Utility/ARMUtils.h" 22#include "Utility/ARM_DWARF_Registers.h" 23 24#include "llvm/Support/MathExtras.h" // for SignExtend32 template function 25 // and CountTrailingZeros_32 function 26 27using namespace lldb; 28using namespace lldb_private; 29 30// Convenient macro definitions. 31#define APSR_C Bit32(m_opcode_cpsr, CPSR_C_POS) 32#define APSR_V Bit32(m_opcode_cpsr, CPSR_V_POS) 33 34#define AlignPC(pc_val) (pc_val & 0xFFFFFFFC) 35 36//---------------------------------------------------------------------- 37// 38// ITSession implementation 39// 40//---------------------------------------------------------------------- 41 42// A8.6.50 43// Valid return values are {1, 2, 3, 4}, with 0 signifying an error condition. 44static unsigned short CountITSize(unsigned ITMask) { 45 // First count the trailing zeros of the IT mask. 46 unsigned TZ = llvm::CountTrailingZeros_32(ITMask); 47 if (TZ > 3) 48 { 49 printf("Encoding error: IT Mask '0000'\n"); 50 return 0; 51 } 52 return (4 - TZ); 53} 54 55// Init ITState. Note that at least one bit is always 1 in mask. 56bool ITSession::InitIT(unsigned short bits7_0) 57{ 58 ITCounter = CountITSize(Bits32(bits7_0, 3, 0)); 59 if (ITCounter == 0) 60 return false; 61 62 // A8.6.50 IT 63 unsigned short FirstCond = Bits32(bits7_0, 7, 4); 64 if (FirstCond == 0xF) 65 { 66 printf("Encoding error: IT FirstCond '1111'\n"); 67 return false; 68 } 69 if (FirstCond == 0xE && ITCounter != 1) 70 { 71 printf("Encoding error: IT FirstCond '1110' && Mask != '1000'\n"); 72 return false; 73 } 74 75 ITState = bits7_0; 76 return true; 77} 78 79// Update ITState if necessary. 80void ITSession::ITAdvance() 81{ 82 assert(ITCounter); 83 --ITCounter; 84 if (ITCounter == 0) 85 ITState = 0; 86 else 87 { 88 unsigned short NewITState4_0 = Bits32(ITState, 4, 0) << 1; 89 SetBits32(ITState, 4, 0, NewITState4_0); 90 } 91} 92 93// Return true if we're inside an IT Block. 94bool ITSession::InITBlock() 95{ 96 return ITCounter != 0; 97} 98 99// Return true if we're the last instruction inside an IT Block. 100bool ITSession::LastInITBlock() 101{ 102 return ITCounter == 1; 103} 104 105// Get condition bits for the current thumb instruction. 106uint32_t ITSession::GetCond() 107{ 108 if (InITBlock()) 109 return Bits32(ITState, 7, 4); 110 else 111 return COND_AL; 112} 113 114// ARM constants used during decoding 115#define REG_RD 0 116#define LDM_REGLIST 1 117#define SP_REG 13 118#define LR_REG 14 119#define PC_REG 15 120#define PC_REGLIST_BIT 0x8000 121 122#define ARMv4 (1u << 0) 123#define ARMv4T (1u << 1) 124#define ARMv5T (1u << 2) 125#define ARMv5TE (1u << 3) 126#define ARMv5TEJ (1u << 4) 127#define ARMv6 (1u << 5) 128#define ARMv6K (1u << 6) 129#define ARMv6T2 (1u << 7) 130#define ARMv7 (1u << 8) 131#define ARMv8 (1u << 9) 132#define ARMvAll (0xffffffffu) 133 134#define ARMV4T_ABOVE (ARMv4T|ARMv5T|ARMv5TE|ARMv5TEJ|ARMv6|ARMv6K|ARMv6T2|ARMv7|ARMv8) 135#define ARMV5_ABOVE (ARMv5T|ARMv5TE|ARMv5TEJ|ARMv6|ARMv6K|ARMv6T2|ARMv7|ARMv8) 136#define ARMV5TE_ABOVE (ARMv5TE|ARMv5TEJ|ARMv6|ARMv6K|ARMv6T2|ARMv7|ARMv8) 137#define ARMV5J_ABOVE (ARMv5TEJ|ARMv6|ARMv6K|ARMv6T2|ARMv7|ARMv8) 138#define ARMV6_ABOVE (ARMv6|ARMv6K|ARMv6T2|ARMv7|ARMv8) 139#define ARMV6T2_ABOVE (ARMv6T2|ARMv7|ARMv8) 140 141#define No_VFP 0 142#define VFPv1 (1u << 1) 143#define VFPv2 (1u << 2) 144#define VFPv3 (1u << 3) 145#define AdvancedSIMD (1u << 4) 146 147#define VFPv1_ABOVE (VFPv1 | VFPv2 | VFPv3 | AdvancedSIMD) 148#define VFPv2_ABOVE (VFPv2 | VFPv3 | AdvancedSIMD) 149#define VFPv2v3 (VFPv2 | VFPv3) 150 151//---------------------------------------------------------------------- 152// 153// EmulateInstructionARM implementation 154// 155//---------------------------------------------------------------------- 156 157void 158EmulateInstructionARM::Initialize () 159{ 160 PluginManager::RegisterPlugin (GetPluginNameStatic (), 161 GetPluginDescriptionStatic (), 162 CreateInstance); 163} 164 165void 166EmulateInstructionARM::Terminate () 167{ 168 PluginManager::UnregisterPlugin (CreateInstance); 169} 170 171const char * 172EmulateInstructionARM::GetPluginNameStatic () 173{ 174 return "lldb.emulate-instruction.arm"; 175} 176 177const char * 178EmulateInstructionARM::GetPluginDescriptionStatic () 179{ 180 return "Emulate instructions for the ARM architecture."; 181} 182 183EmulateInstruction * 184EmulateInstructionARM::CreateInstance (const ArchSpec &arch) 185{ 186 if (arch.GetTriple().getArch() == llvm::Triple::arm) 187 { 188 std::auto_ptr<EmulateInstructionARM> emulate_insn_ap (new EmulateInstructionARM (arch)); 189 190 if (emulate_insn_ap.get()) 191 return emulate_insn_ap.release(); 192 } 193 else if (arch.GetTriple().getArch() == llvm::Triple::thumb) 194 { 195 std::auto_ptr<EmulateInstructionARM> emulate_insn_ap (new EmulateInstructionARM (arch)); 196 197 if (emulate_insn_ap.get()) 198 return emulate_insn_ap.release(); 199 } 200 201 return NULL; 202} 203 204bool 205EmulateInstructionARM::SetTargetTriple (const ArchSpec &arch) 206{ 207 if (arch.GetTriple().getArch () == llvm::Triple::arm) 208 return true; 209 else if (arch.GetTriple().getArch () == llvm::Triple::thumb) 210 return true; 211 212 return false; 213} 214 215// Write "bits (32) UNKNOWN" to memory address "address". Helper function for many ARM instructions. 216bool 217EmulateInstructionARM::WriteBits32UnknownToMemory (addr_t address) 218{ 219 EmulateInstruction::Context context; 220 context.type = EmulateInstruction::eContextWriteMemoryRandomBits; 221 context.SetNoArgs (); 222 223 uint32_t random_data = rand (); 224 const uint32_t addr_byte_size = GetAddressByteSize(); 225 226 if (!MemAWrite (context, address, random_data, addr_byte_size)) 227 return false; 228 229 return true; 230} 231 232// Write "bits (32) UNKNOWN" to register n. Helper function for many ARM instructions. 233bool 234EmulateInstructionARM::WriteBits32Unknown (int n) 235{ 236 EmulateInstruction::Context context; 237 context.type = EmulateInstruction::eContextWriteRegisterRandomBits; 238 context.SetNoArgs (); 239 240 bool success; 241 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success); 242 243 if (!success) 244 return false; 245 246 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, data)) 247 return false; 248 249 return true; 250} 251 252// Push Multiple Registers stores multiple registers to the stack, storing to 253// consecutive memory locations ending just below the address in SP, and updates 254// SP to point to the start of the stored data. 255bool 256EmulateInstructionARM::EmulatePUSH (const uint32_t opcode, const ARMEncoding encoding) 257{ 258#if 0 259 // ARM pseudo code... 260 if (ConditionPassed()) 261 { 262 EncodingSpecificOperations(); 263 NullCheckIfThumbEE(13); 264 address = SP - 4*BitCount(registers); 265 266 for (i = 0 to 14) 267 { 268 if (registers<i> == '1') 269 { 270 if i == 13 && i != LowestSetBit(registers) // Only possible for encoding A1 271 MemA[address,4] = bits(32) UNKNOWN; 272 else 273 MemA[address,4] = R[i]; 274 address = address + 4; 275 } 276 } 277 278 if (registers<15> == '1') // Only possible for encoding A1 or A2 279 MemA[address,4] = PCStoreValue(); 280 281 SP = SP - 4*BitCount(registers); 282 } 283#endif 284 285 bool success = false; 286 if (ConditionPassed(opcode)) 287 { 288 const uint32_t addr_byte_size = GetAddressByteSize(); 289 const addr_t sp = ReadCoreReg (SP_REG, &success); 290 if (!success) 291 return false; 292 uint32_t registers = 0; 293 uint32_t Rt; // the source register 294 switch (encoding) { 295 case eEncodingT1: 296 registers = Bits32(opcode, 7, 0); 297 // The M bit represents LR. 298 if (Bit32(opcode, 8)) 299 registers |= (1u << 14); 300 // if BitCount(registers) < 1 then UNPREDICTABLE; 301 if (BitCount(registers) < 1) 302 return false; 303 break; 304 case eEncodingT2: 305 // Ignore bits 15 & 13. 306 registers = Bits32(opcode, 15, 0) & ~0xa000; 307 // if BitCount(registers) < 2 then UNPREDICTABLE; 308 if (BitCount(registers) < 2) 309 return false; 310 break; 311 case eEncodingT3: 312 Rt = Bits32(opcode, 15, 12); 313 // if BadReg(t) then UNPREDICTABLE; 314 if (BadReg(Rt)) 315 return false; 316 registers = (1u << Rt); 317 break; 318 case eEncodingA1: 319 registers = Bits32(opcode, 15, 0); 320 // Instead of return false, let's handle the following case as well, 321 // which amounts to pushing one reg onto the full descending stacks. 322 // if BitCount(register_list) < 2 then SEE STMDB / STMFD; 323 break; 324 case eEncodingA2: 325 Rt = Bits32(opcode, 15, 12); 326 // if t == 13 then UNPREDICTABLE; 327 if (Rt == dwarf_sp) 328 return false; 329 registers = (1u << Rt); 330 break; 331 default: 332 return false; 333 } 334 addr_t sp_offset = addr_byte_size * BitCount (registers); 335 addr_t addr = sp - sp_offset; 336 uint32_t i; 337 338 EmulateInstruction::Context context; 339 context.type = EmulateInstruction::eContextPushRegisterOnStack; 340 Register dwarf_reg; 341 dwarf_reg.SetRegister (eRegisterKindDWARF, 0); 342 Register sp_reg; 343 sp_reg.SetRegister (eRegisterKindDWARF, dwarf_sp); 344 for (i=0; i<15; ++i) 345 { 346 if (BitIsSet (registers, i)) 347 { 348 dwarf_reg.num = dwarf_r0 + i; 349 context.SetRegisterToRegisterPlusOffset (dwarf_reg, sp_reg, addr - sp); 350 uint32_t reg_value = ReadCoreReg(i, &success); 351 if (!success) 352 return false; 353 if (!MemAWrite (context, addr, reg_value, addr_byte_size)) 354 return false; 355 addr += addr_byte_size; 356 } 357 } 358 359 if (BitIsSet (registers, 15)) 360 { 361 dwarf_reg.num = dwarf_pc; 362 context.SetRegisterPlusOffset (dwarf_reg, addr - sp); 363 const uint32_t pc = ReadCoreReg(PC_REG, &success); 364 if (!success) 365 return false; 366 if (!MemAWrite (context, addr, pc, addr_byte_size)) 367 return false; 368 } 369 370 context.type = EmulateInstruction::eContextAdjustStackPointer; 371 context.SetImmediateSigned (-sp_offset); 372 373 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, sp - sp_offset)) 374 return false; 375 } 376 return true; 377} 378 379// Pop Multiple Registers loads multiple registers from the stack, loading from 380// consecutive memory locations staring at the address in SP, and updates 381// SP to point just above the loaded data. 382bool 383EmulateInstructionARM::EmulatePOP (const uint32_t opcode, const ARMEncoding encoding) 384{ 385#if 0 386 // ARM pseudo code... 387 if (ConditionPassed()) 388 { 389 EncodingSpecificOperations(); NullCheckIfThumbEE(13); 390 address = SP; 391 for i = 0 to 14 392 if registers<i> == '1' then 393 R[i} = if UnalignedAllowed then MemU[address,4] else MemA[address,4]; address = address + 4; 394 if registers<15> == '1' then 395 if UnalignedAllowed then 396 LoadWritePC(MemU[address,4]); 397 else 398 LoadWritePC(MemA[address,4]); 399 if registers<13> == '0' then SP = SP + 4*BitCount(registers); 400 if registers<13> == '1' then SP = bits(32) UNKNOWN; 401 } 402#endif 403 404 bool success = false; 405 406 if (ConditionPassed(opcode)) 407 { 408 const uint32_t addr_byte_size = GetAddressByteSize(); 409 const addr_t sp = ReadCoreReg (SP_REG, &success); 410 if (!success) 411 return false; 412 uint32_t registers = 0; 413 uint32_t Rt; // the destination register 414 switch (encoding) { 415 case eEncodingT1: 416 registers = Bits32(opcode, 7, 0); 417 // The P bit represents PC. 418 if (Bit32(opcode, 8)) 419 registers |= (1u << 15); 420 // if BitCount(registers) < 1 then UNPREDICTABLE; 421 if (BitCount(registers) < 1) 422 return false; 423 break; 424 case eEncodingT2: 425 // Ignore bit 13. 426 registers = Bits32(opcode, 15, 0) & ~0x2000; 427 // if BitCount(registers) < 2 || (P == '1' && M == '1') then UNPREDICTABLE; 428 if (BitCount(registers) < 2 || (Bit32(opcode, 15) && Bit32(opcode, 14))) 429 return false; 430 // if registers<15> == '1' && InITBlock() && !LastInITBlock() then UNPREDICTABLE; 431 if (BitIsSet(registers, 15) && InITBlock() && !LastInITBlock()) 432 return false; 433 break; 434 case eEncodingT3: 435 Rt = Bits32(opcode, 15, 12); 436 // if t == 13 || (t == 15 && InITBlock() && !LastInITBlock()) then UNPREDICTABLE; 437 if (Rt == 13) 438 return false; 439 if (Rt == 15 && InITBlock() && !LastInITBlock()) 440 return false; 441 registers = (1u << Rt); 442 break; 443 case eEncodingA1: 444 registers = Bits32(opcode, 15, 0); 445 // Instead of return false, let's handle the following case as well, 446 // which amounts to popping one reg from the full descending stacks. 447 // if BitCount(register_list) < 2 then SEE LDM / LDMIA / LDMFD; 448 449 // if registers<13> == '1' && ArchVersion() >= 7 then UNPREDICTABLE; 450 if (BitIsSet(opcode, 13) && ArchVersion() >= ARMv7) 451 return false; 452 break; 453 case eEncodingA2: 454 Rt = Bits32(opcode, 15, 12); 455 // if t == 13 then UNPREDICTABLE; 456 if (Rt == dwarf_sp) 457 return false; 458 registers = (1u << Rt); 459 break; 460 default: 461 return false; 462 } 463 addr_t sp_offset = addr_byte_size * BitCount (registers); 464 addr_t addr = sp; 465 uint32_t i, data; 466 467 EmulateInstruction::Context context; 468 context.type = EmulateInstruction::eContextPopRegisterOffStack; 469 Register dwarf_reg; 470 dwarf_reg.SetRegister (eRegisterKindDWARF, 0); 471 Register sp_reg; 472 sp_reg.SetRegister (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP); 473 for (i=0; i<15; ++i) 474 { 475 if (BitIsSet (registers, i)) 476 { 477 dwarf_reg.num = dwarf_r0 + i; 478 context.SetRegisterPlusOffset (sp_reg, addr - sp); 479 data = MemARead(context, addr, 4, 0, &success); 480 if (!success) 481 return false; 482 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_reg.num, data)) 483 return false; 484 addr += addr_byte_size; 485 } 486 } 487 488 if (BitIsSet (registers, 15)) 489 { 490 dwarf_reg.num = dwarf_pc; 491 context.SetRegisterPlusOffset (sp_reg, addr - sp); 492 data = MemARead(context, addr, 4, 0, &success); 493 if (!success) 494 return false; 495 // In ARMv5T and above, this is an interworking branch. 496 if (!LoadWritePC(context, data)) 497 return false; 498 addr += addr_byte_size; 499 } 500 501 context.type = EmulateInstruction::eContextAdjustStackPointer; 502 context.SetImmediateSigned (sp_offset); 503 504 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, sp + sp_offset)) 505 return false; 506 } 507 return true; 508} 509 510// Set r7 or ip to point to saved value residing within the stack. 511// ADD (SP plus immediate) 512bool 513EmulateInstructionARM::EmulateADDRdSPImm (const uint32_t opcode, const ARMEncoding encoding) 514{ 515#if 0 516 // ARM pseudo code... 517 if (ConditionPassed()) 518 { 519 EncodingSpecificOperations(); 520 (result, carry, overflow) = AddWithCarry(SP, imm32, '0'); 521 if d == 15 then 522 ALUWritePC(result); // setflags is always FALSE here 523 else 524 R[d] = result; 525 if setflags then 526 APSR.N = result<31>; 527 APSR.Z = IsZeroBit(result); 528 APSR.C = carry; 529 APSR.V = overflow; 530 } 531#endif 532 533 bool success = false; 534 535 if (ConditionPassed(opcode)) 536 { 537 const addr_t sp = ReadCoreReg (SP_REG, &success); 538 if (!success) 539 return false; 540 uint32_t Rd; // the destination register 541 uint32_t imm32; 542 switch (encoding) { 543 case eEncodingT1: 544 Rd = 7; 545 imm32 = Bits32(opcode, 7, 0) << 2; // imm32 = ZeroExtend(imm8:'00', 32) 546 break; 547 case eEncodingA1: 548 Rd = Bits32(opcode, 15, 12); 549 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12) 550 break; 551 default: 552 return false; 553 } 554 addr_t sp_offset = imm32; 555 addr_t addr = sp + sp_offset; // a pointer to the stack area 556 557 EmulateInstruction::Context context; 558 context.type = EmulateInstruction::eContextAdjustStackPointer; 559 Register sp_reg; 560 sp_reg.SetRegister (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP); 561 context.SetRegisterPlusOffset (sp_reg, sp_offset); 562 563 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + Rd, addr)) 564 return false; 565 } 566 return true; 567} 568 569// Set r7 or ip to the current stack pointer. 570// MOV (register) 571bool 572EmulateInstructionARM::EmulateMOVRdSP (const uint32_t opcode, const ARMEncoding encoding) 573{ 574#if 0 575 // ARM pseudo code... 576 if (ConditionPassed()) 577 { 578 EncodingSpecificOperations(); 579 result = R[m]; 580 if d == 15 then 581 ALUWritePC(result); // setflags is always FALSE here 582 else 583 R[d] = result; 584 if setflags then 585 APSR.N = result<31>; 586 APSR.Z = IsZeroBit(result); 587 // APSR.C unchanged 588 // APSR.V unchanged 589 } 590#endif 591 592 bool success = false; 593 594 if (ConditionPassed(opcode)) 595 { 596 const addr_t sp = ReadCoreReg (SP_REG, &success); 597 if (!success) 598 return false; 599 uint32_t Rd; // the destination register 600 switch (encoding) { 601 case eEncodingT1: 602 Rd = 7; 603 break; 604 case eEncodingA1: 605 Rd = 12; 606 break; 607 default: 608 return false; 609 } 610 611 EmulateInstruction::Context context; 612 context.type = EmulateInstruction::eContextRegisterPlusOffset; 613 Register sp_reg; 614 sp_reg.SetRegister (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP); 615 context.SetRegisterPlusOffset (sp_reg, 0); 616 617 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + Rd, sp)) 618 return false; 619 } 620 return true; 621} 622 623// Move from high register (r8-r15) to low register (r0-r7). 624// MOV (register) 625bool 626EmulateInstructionARM::EmulateMOVLowHigh (const uint32_t opcode, const ARMEncoding encoding) 627{ 628 return EmulateMOVRdRm (opcode, encoding); 629} 630 631// Move from register to register. 632// MOV (register) 633bool 634EmulateInstructionARM::EmulateMOVRdRm (const uint32_t opcode, const ARMEncoding encoding) 635{ 636#if 0 637 // ARM pseudo code... 638 if (ConditionPassed()) 639 { 640 EncodingSpecificOperations(); 641 result = R[m]; 642 if d == 15 then 643 ALUWritePC(result); // setflags is always FALSE here 644 else 645 R[d] = result; 646 if setflags then 647 APSR.N = result<31>; 648 APSR.Z = IsZeroBit(result); 649 // APSR.C unchanged 650 // APSR.V unchanged 651 } 652#endif 653 654 bool success = false; 655 656 if (ConditionPassed(opcode)) 657 { 658 uint32_t Rm; // the source register 659 uint32_t Rd; // the destination register 660 bool setflags; 661 switch (encoding) { 662 case eEncodingT1: 663 Rd = Bit32(opcode, 7) << 3 | Bits32(opcode, 2, 0); 664 Rm = Bits32(opcode, 6, 3); 665 setflags = false; 666 if (Rd == 15 && InITBlock() && !LastInITBlock()) 667 return false; 668 break; 669 case eEncodingT2: 670 Rd = Bits32(opcode, 2, 0); 671 Rm = Bits32(opcode, 5, 3); 672 setflags = true; 673 if (InITBlock()) 674 return false; 675 break; 676 case eEncodingT3: 677 Rd = Bits32(opcode, 11, 8); 678 Rm = Bits32(opcode, 3, 0); 679 setflags = BitIsSet(opcode, 20); 680 // if setflags && (BadReg(d) || BadReg(m)) then UNPREDICTABLE; 681 if (setflags && (BadReg(Rd) || BadReg(Rm))) 682 return false; 683 // if !setflags && (d == 15 || m == 15 || (d == 13 && m == 13)) then UNPREDICTABLE; 684 if (!setflags && (Rd == 15 || Rm == 15 || (Rd == 13 && Rm == 13))) 685 return false; 686 break; 687 case eEncodingA1: 688 Rd = Bits32(opcode, 15, 12); 689 Rm = Bits32(opcode, 3, 0); 690 setflags = BitIsSet(opcode, 20); 691 692 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions; 693 if (Rd == 15 && setflags) 694 return EmulateSUBSPcLrEtc (opcode, encoding); 695 break; 696 default: 697 return false; 698 } 699 uint32_t result = ReadCoreReg(Rm, &success); 700 if (!success) 701 return false; 702 703 // The context specifies that Rm is to be moved into Rd. 704 EmulateInstruction::Context context; 705 context.type = EmulateInstruction::eContextRegisterLoad; 706 Register dwarf_reg; 707 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + Rm); 708 context.SetRegister (dwarf_reg); 709 710 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags)) 711 return false; 712 } 713 return true; 714} 715 716// Move (immediate) writes an immediate value to the destination register. It 717// can optionally update the condition flags based on the value. 718// MOV (immediate) 719bool 720EmulateInstructionARM::EmulateMOVRdImm (const uint32_t opcode, const ARMEncoding encoding) 721{ 722#if 0 723 // ARM pseudo code... 724 if (ConditionPassed()) 725 { 726 EncodingSpecificOperations(); 727 result = imm32; 728 if d == 15 then // Can only occur for ARM encoding 729 ALUWritePC(result); // setflags is always FALSE here 730 else 731 R[d] = result; 732 if setflags then 733 APSR.N = result<31>; 734 APSR.Z = IsZeroBit(result); 735 APSR.C = carry; 736 // APSR.V unchanged 737 } 738#endif 739 740 if (ConditionPassed(opcode)) 741 { 742 uint32_t Rd; // the destination register 743 uint32_t imm32; // the immediate value to be written to Rd 744 uint32_t carry; // the carry bit after ThumbExpandImm_C or ARMExpandImm_C. 745 bool setflags; 746 switch (encoding) { 747 case eEncodingT1: 748 Rd = Bits32(opcode, 10, 8); 749 setflags = !InITBlock(); 750 imm32 = Bits32(opcode, 7, 0); // imm32 = ZeroExtend(imm8, 32) 751 carry = APSR_C; 752 753 break; 754 755 case eEncodingT2: 756 Rd = Bits32(opcode, 11, 8); 757 setflags = BitIsSet(opcode, 20); 758 imm32 = ThumbExpandImm_C(opcode, APSR_C, carry); 759 if (BadReg(Rd)) 760 return false; 761 762 break; 763 764 case eEncodingT3: 765 { 766 // d = UInt(Rd); setflags = FALSE; imm32 = ZeroExtend(imm4:i:imm3:imm8, 32); 767 Rd = Bits32 (opcode, 11, 8); 768 setflags = false; 769 uint32_t imm4 = Bits32 (opcode, 19, 16); 770 uint32_t imm3 = Bits32 (opcode, 14, 12); 771 uint32_t i = Bit32 (opcode, 26); 772 uint32_t imm8 = Bits32 (opcode, 7, 0); 773 imm32 = (imm4 << 12) | (i << 11) | (imm3 << 8) | imm8; 774 775 // if BadReg(d) then UNPREDICTABLE; 776 if (BadReg (Rd)) 777 return false; 778 } 779 break; 780 781 case eEncodingA1: 782 // d = UInt(Rd); setflags = (S == ‘1’); (imm32, carry) = ARMExpandImm_C(imm12, APSR.C); 783 Rd = Bits32 (opcode, 15, 12); 784 setflags = BitIsSet (opcode, 20); 785 imm32 = ARMExpandImm_C (opcode, APSR_C, carry); 786 787 // if Rd == ‘1111’ && S == ‘1’ then SEE SUBS PC, LR and related instructions; 788 if ((Rd == 15) && setflags) 789 return EmulateSUBSPcLrEtc (opcode, encoding); 790 791 break; 792 793 case eEncodingA2: 794 { 795 // d = UInt(Rd); setflags = FALSE; imm32 = ZeroExtend(imm4:imm12, 32); 796 Rd = Bits32 (opcode, 15, 12); 797 setflags = false; 798 uint32_t imm4 = Bits32 (opcode, 19, 16); 799 uint32_t imm12 = Bits32 (opcode, 11, 0); 800 imm32 = (imm4 << 12) | imm12; 801 802 // if d == 15 then UNPREDICTABLE; 803 if (Rd == 15) 804 return false; 805 } 806 break; 807 808 default: 809 return false; 810 } 811 uint32_t result = imm32; 812 813 // The context specifies that an immediate is to be moved into Rd. 814 EmulateInstruction::Context context; 815 context.type = EmulateInstruction::eContextImmediate; 816 context.SetNoArgs (); 817 818 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry)) 819 return false; 820 } 821 return true; 822} 823 824// MUL multiplies two register values. The least significant 32 bits of the result are written to the destination 825// register. These 32 bits do not depend on whether the source register values are considered to be signed values or 826// unsigned values. 827// 828// Optionally, it can update the condition flags based on the result. In the Thumb instruction set, this option is 829// limited to only a few forms of the instruction. 830bool 831EmulateInstructionARM::EmulateMUL (const uint32_t opcode, const ARMEncoding encoding) 832{ 833#if 0 834 if ConditionPassed() then 835 EncodingSpecificOperations(); 836 operand1 = SInt(R[n]); // operand1 = UInt(R[n]) produces the same final results 837 operand2 = SInt(R[m]); // operand2 = UInt(R[m]) produces the same final results 838 result = operand1 * operand2; 839 R[d] = result<31:0>; 840 if setflags then 841 APSR.N = result<31>; 842 APSR.Z = IsZeroBit(result); 843 if ArchVersion() == 4 then 844 APSR.C = bit UNKNOWN; 845 // else APSR.C unchanged 846 // APSR.V always unchanged 847#endif 848 849 if (ConditionPassed(opcode)) 850 { 851 uint32_t d; 852 uint32_t n; 853 uint32_t m; 854 bool setflags; 855 856 // EncodingSpecificOperations(); 857 switch (encoding) 858 { 859 case eEncodingT1: 860 // d = UInt(Rdm); n = UInt(Rn); m = UInt(Rdm); setflags = !InITBlock(); 861 d = Bits32 (opcode, 2, 0); 862 n = Bits32 (opcode, 5, 3); 863 m = Bits32 (opcode, 2, 0); 864 setflags = !InITBlock(); 865 866 // if ArchVersion() < 6 && d == n then UNPREDICTABLE; 867 if ((ArchVersion() < ARMv6) && (d == n)) 868 return false; 869 870 break; 871 872 case eEncodingT2: 873 // d = UInt(Rd); n = UInt(Rn); m = UInt(Rm); setflags = FALSE; 874 d = Bits32 (opcode, 11, 8); 875 n = Bits32 (opcode, 19, 16); 876 m = Bits32 (opcode, 3, 0); 877 setflags = false; 878 879 // if BadReg(d) || BadReg(n) || BadReg(m) then UNPREDICTABLE; 880 if (BadReg (d) || BadReg (n) || BadReg (m)) 881 return false; 882 883 break; 884 885 case eEncodingA1: 886 // d = UInt(Rd); n = UInt(Rn); m = UInt(Rm); setflags = (S == '1'); 887 d = Bits32 (opcode, 19, 16); 888 n = Bits32 (opcode, 3, 0); 889 m = Bits32 (opcode, 11, 8); 890 setflags = BitIsSet (opcode, 20); 891 892 // if d == 15 || n == 15 || m == 15 then UNPREDICTABLE; 893 if ((d == 15) || (n == 15) || (m == 15)) 894 return false; 895 896 // if ArchVersion() < 6 && d == n then UNPREDICTABLE; 897 if ((ArchVersion() < ARMv6) && (d == n)) 898 return false; 899 900 break; 901 902 default: 903 return false; 904 } 905 906 bool success = false; 907 908 // operand1 = SInt(R[n]); // operand1 = UInt(R[n]) produces the same final results 909 uint64_t operand1 = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success); 910 if (!success) 911 return false; 912 913 // operand2 = SInt(R[m]); // operand2 = UInt(R[m]) produces the same final results 914 uint64_t operand2 = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success); 915 if (!success) 916 return false; 917 918 // result = operand1 * operand2; 919 uint64_t result = operand1 * operand2; 920 921 // R[d] = result<31:0>; 922 Register op1_reg; 923 Register op2_reg; 924 op1_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n); 925 op2_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + m); 926 927 EmulateInstruction::Context context; 928 context.type = eContextMultiplication; 929 context.SetRegisterRegisterOperands (op1_reg, op2_reg); 930 931 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + d, (0x0000ffff & result))) 932 return false; 933 934 // if setflags then 935 if (setflags) 936 { 937 // APSR.N = result<31>; 938 // APSR.Z = IsZeroBit(result); 939 m_new_inst_cpsr = m_opcode_cpsr; 940 SetBit32 (m_new_inst_cpsr, CPSR_N_POS, Bit32 (result, 31)); 941 SetBit32 (m_new_inst_cpsr, CPSR_Z_POS, result == 0 ? 1 : 0); 942 if (m_new_inst_cpsr != m_opcode_cpsr) 943 { 944 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS, m_new_inst_cpsr)) 945 return false; 946 } 947 948 // if ArchVersion() == 4 then 949 // APSR.C = bit UNKNOWN; 950 } 951 } 952 return true; 953} 954 955// Bitwise NOT (immediate) writes the bitwise inverse of an immediate value to the destination register. 956// It can optionally update the condition flags based on the value. 957bool 958EmulateInstructionARM::EmulateMVNImm (const uint32_t opcode, const ARMEncoding encoding) 959{ 960#if 0 961 // ARM pseudo code... 962 if (ConditionPassed()) 963 { 964 EncodingSpecificOperations(); 965 result = NOT(imm32); 966 if d == 15 then // Can only occur for ARM encoding 967 ALUWritePC(result); // setflags is always FALSE here 968 else 969 R[d] = result; 970 if setflags then 971 APSR.N = result<31>; 972 APSR.Z = IsZeroBit(result); 973 APSR.C = carry; 974 // APSR.V unchanged 975 } 976#endif 977 978 if (ConditionPassed(opcode)) 979 { 980 uint32_t Rd; // the destination register 981 uint32_t imm32; // the output after ThumbExpandImm_C or ARMExpandImm_C 982 uint32_t carry; // the carry bit after ThumbExpandImm_C or ARMExpandImm_C 983 bool setflags; 984 switch (encoding) { 985 case eEncodingT1: 986 Rd = Bits32(opcode, 11, 8); 987 setflags = BitIsSet(opcode, 20); 988 imm32 = ThumbExpandImm_C(opcode, APSR_C, carry); 989 break; 990 case eEncodingA1: 991 Rd = Bits32(opcode, 15, 12); 992 setflags = BitIsSet(opcode, 20); 993 imm32 = ARMExpandImm_C(opcode, APSR_C, carry); 994 995 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions; 996 if (Rd == 15 && setflags) 997 return EmulateSUBSPcLrEtc (opcode, encoding); 998 break; 999 default: 1000 return false; 1001 } 1002 uint32_t result = ~imm32; 1003 1004 // The context specifies that an immediate is to be moved into Rd. 1005 EmulateInstruction::Context context; 1006 context.type = EmulateInstruction::eContextImmediate; 1007 context.SetNoArgs (); 1008 1009 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry)) 1010 return false; 1011 } 1012 return true; 1013} 1014 1015// Bitwise NOT (register) writes the bitwise inverse of a register value to the destination register. 1016// It can optionally update the condition flags based on the result. 1017bool 1018EmulateInstructionARM::EmulateMVNReg (const uint32_t opcode, const ARMEncoding encoding) 1019{ 1020#if 0 1021 // ARM pseudo code... 1022 if (ConditionPassed()) 1023 { 1024 EncodingSpecificOperations(); 1025 (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C); 1026 result = NOT(shifted); 1027 if d == 15 then // Can only occur for ARM encoding 1028 ALUWritePC(result); // setflags is always FALSE here 1029 else 1030 R[d] = result; 1031 if setflags then 1032 APSR.N = result<31>; 1033 APSR.Z = IsZeroBit(result); 1034 APSR.C = carry; 1035 // APSR.V unchanged 1036 } 1037#endif 1038 1039 if (ConditionPassed(opcode)) 1040 { 1041 uint32_t Rm; // the source register 1042 uint32_t Rd; // the destination register 1043 ARM_ShifterType shift_t; 1044 uint32_t shift_n; // the shift applied to the value read from Rm 1045 bool setflags; 1046 uint32_t carry; // the carry bit after the shift operation 1047 switch (encoding) { 1048 case eEncodingT1: 1049 Rd = Bits32(opcode, 2, 0); 1050 Rm = Bits32(opcode, 5, 3); 1051 setflags = !InITBlock(); 1052 shift_t = SRType_LSL; 1053 shift_n = 0; 1054 if (InITBlock()) 1055 return false; 1056 break; 1057 case eEncodingT2: 1058 Rd = Bits32(opcode, 11, 8); 1059 Rm = Bits32(opcode, 3, 0); 1060 setflags = BitIsSet(opcode, 20); 1061 shift_n = DecodeImmShiftThumb(opcode, shift_t); 1062 // if (BadReg(d) || BadReg(m)) then UNPREDICTABLE; 1063 if (BadReg(Rd) || BadReg(Rm)) 1064 return false; 1065 break; 1066 case eEncodingA1: 1067 Rd = Bits32(opcode, 15, 12); 1068 Rm = Bits32(opcode, 3, 0); 1069 setflags = BitIsSet(opcode, 20); 1070 shift_n = DecodeImmShiftARM(opcode, shift_t); 1071 break; 1072 default: 1073 return false; 1074 } 1075 bool success = false; 1076 uint32_t value = ReadCoreReg(Rm, &success); 1077 if (!success) 1078 return false; 1079 1080 uint32_t shifted = Shift_C(value, shift_t, shift_n, APSR_C, carry); 1081 uint32_t result = ~shifted; 1082 1083 // The context specifies that an immediate is to be moved into Rd. 1084 EmulateInstruction::Context context; 1085 context.type = EmulateInstruction::eContextImmediate; 1086 context.SetNoArgs (); 1087 1088 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry)) 1089 return false; 1090 } 1091 return true; 1092} 1093 1094// PC relative immediate load into register, possibly followed by ADD (SP plus register). 1095// LDR (literal) 1096bool 1097EmulateInstructionARM::EmulateLDRRtPCRelative (const uint32_t opcode, const ARMEncoding encoding) 1098{ 1099#if 0 1100 // ARM pseudo code... 1101 if (ConditionPassed()) 1102 { 1103 EncodingSpecificOperations(); NullCheckIfThumbEE(15); 1104 base = Align(PC,4); 1105 address = if add then (base + imm32) else (base - imm32); 1106 data = MemU[address,4]; 1107 if t == 15 then 1108 if address<1:0> == '00' then LoadWritePC(data); else UNPREDICTABLE; 1109 elsif UnalignedSupport() || address<1:0> = '00' then 1110 R[t] = data; 1111 else // Can only apply before ARMv7 1112 if CurrentInstrSet() == InstrSet_ARM then 1113 R[t] = ROR(data, 8*UInt(address<1:0>)); 1114 else 1115 R[t] = bits(32) UNKNOWN; 1116 } 1117#endif 1118 1119 if (ConditionPassed(opcode)) 1120 { 1121 bool success = false; 1122 const uint32_t pc = ReadCoreReg(PC_REG, &success); 1123 if (!success) 1124 return false; 1125 1126 // PC relative immediate load context 1127 EmulateInstruction::Context context; 1128 context.type = EmulateInstruction::eContextRegisterPlusOffset; 1129 Register pc_reg; 1130 pc_reg.SetRegister (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC); 1131 context.SetRegisterPlusOffset (pc_reg, 0); 1132 1133 uint32_t Rt; // the destination register 1134 uint32_t imm32; // immediate offset from the PC 1135 bool add; // +imm32 or -imm32? 1136 addr_t base; // the base address 1137 addr_t address; // the PC relative address 1138 uint32_t data; // the literal data value from the PC relative load 1139 switch (encoding) { 1140 case eEncodingT1: 1141 Rt = Bits32(opcode, 10, 8); 1142 imm32 = Bits32(opcode, 7, 0) << 2; // imm32 = ZeroExtend(imm8:'00', 32); 1143 add = true; 1144 break; 1145 case eEncodingT2: 1146 Rt = Bits32(opcode, 15, 12); 1147 imm32 = Bits32(opcode, 11, 0) << 2; // imm32 = ZeroExtend(imm12, 32); 1148 add = BitIsSet(opcode, 23); 1149 if (Rt == 15 && InITBlock() && !LastInITBlock()) 1150 return false; 1151 break; 1152 default: 1153 return false; 1154 } 1155 1156 base = Align(pc, 4); 1157 if (add) 1158 address = base + imm32; 1159 else 1160 address = base - imm32; 1161 1162 context.SetRegisterPlusOffset(pc_reg, address - base); 1163 data = MemURead(context, address, 4, 0, &success); 1164 if (!success) 1165 return false; 1166 1167 if (Rt == 15) 1168 { 1169 if (Bits32(address, 1, 0) == 0) 1170 { 1171 // In ARMv5T and above, this is an interworking branch. 1172 if (!LoadWritePC(context, data)) 1173 return false; 1174 } 1175 else 1176 return false; 1177 } 1178 else if (UnalignedSupport() || Bits32(address, 1, 0) == 0) 1179 { 1180 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + Rt, data)) 1181 return false; 1182 } 1183 else // We don't handle ARM for now. 1184 return false; 1185 1186 } 1187 return true; 1188} 1189 1190// An add operation to adjust the SP. 1191// ADD (SP plus immediate) 1192bool 1193EmulateInstructionARM::EmulateADDSPImm (const uint32_t opcode, const ARMEncoding encoding) 1194{ 1195#if 0 1196 // ARM pseudo code... 1197 if (ConditionPassed()) 1198 { 1199 EncodingSpecificOperations(); 1200 (result, carry, overflow) = AddWithCarry(SP, imm32, '0'); 1201 if d == 15 then // Can only occur for ARM encoding 1202 ALUWritePC(result); // setflags is always FALSE here 1203 else 1204 R[d] = result; 1205 if setflags then 1206 APSR.N = result<31>; 1207 APSR.Z = IsZeroBit(result); 1208 APSR.C = carry; 1209 APSR.V = overflow; 1210 } 1211#endif 1212 1213 bool success = false; 1214 1215 if (ConditionPassed(opcode)) 1216 { 1217 const addr_t sp = ReadCoreReg (SP_REG, &success); 1218 if (!success) 1219 return false; 1220 uint32_t imm32; // the immediate operand 1221 uint32_t d; 1222 bool setflags; 1223 switch (encoding) 1224 { 1225 case eEncodingT1: 1226 // d = UInt(Rd); setflags = FALSE; imm32 = ZeroExtend(imm8:'00', 32); 1227 d = Bits32 (opcode, 10, 8); 1228 setflags = false; 1229 imm32 = (Bits32 (opcode, 7, 0) << 2); 1230 1231 break; 1232 1233 case eEncodingT2: 1234 // d = 13; setflags = FALSE; imm32 = ZeroExtend(imm7:'00', 32); 1235 d = 13; 1236 setflags = false; 1237 imm32 = ThumbImm7Scaled(opcode); // imm32 = ZeroExtend(imm7:'00', 32) 1238 1239 break; 1240 1241 default: 1242 return false; 1243 } 1244 addr_t sp_offset = imm32; 1245 addr_t addr = sp + sp_offset; // the adjusted stack pointer value 1246 1247 EmulateInstruction::Context context; 1248 context.type = EmulateInstruction::eContextAdjustStackPointer; 1249 Register sp_reg; 1250 sp_reg.SetRegister (eRegisterKindDWARF, dwarf_sp); 1251 context.SetRegisterPlusOffset (sp_reg, sp_offset); 1252 1253 if (d == 15) 1254 { 1255 if (!ALUWritePC (context, addr)) 1256 return false; 1257 } 1258 else 1259 { 1260 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + d, addr)) 1261 return false; 1262 } 1263 } 1264 return true; 1265} 1266 1267// An add operation to adjust the SP. 1268// ADD (SP plus register) 1269bool 1270EmulateInstructionARM::EmulateADDSPRm (const uint32_t opcode, const ARMEncoding encoding) 1271{ 1272#if 0 1273 // ARM pseudo code... 1274 if (ConditionPassed()) 1275 { 1276 EncodingSpecificOperations(); 1277 shifted = Shift(R[m], shift_t, shift_n, APSR.C); 1278 (result, carry, overflow) = AddWithCarry(SP, shifted, '0'); 1279 if d == 15 then 1280 ALUWritePC(result); // setflags is always FALSE here 1281 else 1282 R[d] = result; 1283 if setflags then 1284 APSR.N = result<31>; 1285 APSR.Z = IsZeroBit(result); 1286 APSR.C = carry; 1287 APSR.V = overflow; 1288 } 1289#endif 1290 1291 bool success = false; 1292 1293 if (ConditionPassed(opcode)) 1294 { 1295 const addr_t sp = ReadCoreReg (SP_REG, &success); 1296 if (!success) 1297 return false; 1298 uint32_t Rm; // the second operand 1299 switch (encoding) { 1300 case eEncodingT2: 1301 Rm = Bits32(opcode, 6, 3); 1302 break; 1303 default: 1304 return false; 1305 } 1306 int32_t reg_value = ReadCoreReg(Rm, &success); 1307 if (!success) 1308 return false; 1309 1310 addr_t addr = (int32_t)sp + reg_value; // the adjusted stack pointer value 1311 1312 EmulateInstruction::Context context; 1313 context.type = EmulateInstruction::eContextAddition; 1314 Register sp_reg; 1315 sp_reg.SetRegister (eRegisterKindDWARF, dwarf_sp); 1316 Register other_reg; 1317 other_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + Rm); 1318 context.SetRegisterRegisterOperands (sp_reg, other_reg); 1319 1320 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, addr)) 1321 return false; 1322 } 1323 return true; 1324} 1325 1326// Branch with Link and Exchange Instruction Sets (immediate) calls a subroutine 1327// at a PC-relative address, and changes instruction set from ARM to Thumb, or 1328// from Thumb to ARM. 1329// BLX (immediate) 1330bool 1331EmulateInstructionARM::EmulateBLXImmediate (const uint32_t opcode, const ARMEncoding encoding) 1332{ 1333#if 0 1334 // ARM pseudo code... 1335 if (ConditionPassed()) 1336 { 1337 EncodingSpecificOperations(); 1338 if CurrentInstrSet() == InstrSet_ARM then 1339 LR = PC - 4; 1340 else 1341 LR = PC<31:1> : '1'; 1342 if targetInstrSet == InstrSet_ARM then 1343 targetAddress = Align(PC,4) + imm32; 1344 else 1345 targetAddress = PC + imm32; 1346 SelectInstrSet(targetInstrSet); 1347 BranchWritePC(targetAddress); 1348 } 1349#endif 1350 1351 bool success = true; 1352 1353 if (ConditionPassed(opcode)) 1354 { 1355 EmulateInstruction::Context context; 1356 context.type = EmulateInstruction::eContextRelativeBranchImmediate; 1357 const uint32_t pc = ReadCoreReg(PC_REG, &success); 1358 if (!success) 1359 return false; 1360 addr_t lr; // next instruction address 1361 addr_t target; // target address 1362 int32_t imm32; // PC-relative offset 1363 switch (encoding) { 1364 case eEncodingT1: 1365 { 1366 lr = pc | 1u; // return address 1367 uint32_t S = Bit32(opcode, 26); 1368 uint32_t imm10 = Bits32(opcode, 25, 16); 1369 uint32_t J1 = Bit32(opcode, 13); 1370 uint32_t J2 = Bit32(opcode, 11); 1371 uint32_t imm11 = Bits32(opcode, 10, 0); 1372 uint32_t I1 = !(J1 ^ S); 1373 uint32_t I2 = !(J2 ^ S); 1374 uint32_t imm25 = (S << 24) | (I1 << 23) | (I2 << 22) | (imm10 << 12) | (imm11 << 1); 1375 imm32 = llvm::SignExtend32<25>(imm25); 1376 target = pc + imm32; 1377 context.SetModeAndImmediateSigned (eModeThumb, 4 + imm32); 1378 if (InITBlock() && !LastInITBlock()) 1379 return false; 1380 break; 1381 } 1382 case eEncodingT2: 1383 { 1384 lr = pc | 1u; // return address 1385 uint32_t S = Bit32(opcode, 26); 1386 uint32_t imm10H = Bits32(opcode, 25, 16); 1387 uint32_t J1 = Bit32(opcode, 13); 1388 uint32_t J2 = Bit32(opcode, 11); 1389 uint32_t imm10L = Bits32(opcode, 10, 1); 1390 uint32_t I1 = !(J1 ^ S); 1391 uint32_t I2 = !(J2 ^ S); 1392 uint32_t imm25 = (S << 24) | (I1 << 23) | (I2 << 22) | (imm10H << 12) | (imm10L << 2); 1393 imm32 = llvm::SignExtend32<25>(imm25); 1394 target = Align(pc, 4) + imm32; 1395 context.SetModeAndImmediateSigned (eModeARM, 4 + imm32); 1396 if (InITBlock() && !LastInITBlock()) 1397 return false; 1398 break; 1399 } 1400 case eEncodingA1: 1401 lr = pc - 4; // return address 1402 imm32 = llvm::SignExtend32<26>(Bits32(opcode, 23, 0) << 2); 1403 target = Align(pc, 4) + imm32; 1404 context.SetModeAndImmediateSigned (eModeARM, 8 + imm32); 1405 break; 1406 case eEncodingA2: 1407 lr = pc - 4; // return address 1408 imm32 = llvm::SignExtend32<26>(Bits32(opcode, 23, 0) << 2 | Bits32(opcode, 24, 24) << 1); 1409 target = pc + imm32; 1410 context.SetModeAndImmediateSigned (eModeThumb, 8 + imm32); 1411 break; 1412 default: 1413 return false; 1414 } 1415 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_RA, lr)) 1416 return false; 1417 if (!BranchWritePC(context, target)) 1418 return false; 1419 } 1420 return true; 1421} 1422 1423// Branch with Link and Exchange (register) calls a subroutine at an address and 1424// instruction set specified by a register. 1425// BLX (register) 1426bool 1427EmulateInstructionARM::EmulateBLXRm (const uint32_t opcode, const ARMEncoding encoding) 1428{ 1429#if 0 1430 // ARM pseudo code... 1431 if (ConditionPassed()) 1432 { 1433 EncodingSpecificOperations(); 1434 target = R[m]; 1435 if CurrentInstrSet() == InstrSet_ARM then 1436 next_instr_addr = PC - 4; 1437 LR = next_instr_addr; 1438 else 1439 next_instr_addr = PC - 2; 1440 LR = next_instr_addr<31:1> : '1'; 1441 BXWritePC(target); 1442 } 1443#endif 1444 1445 bool success = false; 1446 1447 if (ConditionPassed(opcode)) 1448 { 1449 EmulateInstruction::Context context; 1450 context.type = EmulateInstruction::eContextAbsoluteBranchRegister; 1451 const uint32_t pc = ReadCoreReg(PC_REG, &success); 1452 addr_t lr; // next instruction address 1453 if (!success) 1454 return false; 1455 uint32_t Rm; // the register with the target address 1456 switch (encoding) { 1457 case eEncodingT1: 1458 lr = (pc - 2) | 1u; // return address 1459 Rm = Bits32(opcode, 6, 3); 1460 // if m == 15 then UNPREDICTABLE; 1461 if (Rm == 15) 1462 return false; 1463 if (InITBlock() && !LastInITBlock()) 1464 return false; 1465 break; 1466 case eEncodingA1: 1467 lr = pc - 4; // return address 1468 Rm = Bits32(opcode, 3, 0); 1469 // if m == 15 then UNPREDICTABLE; 1470 if (Rm == 15) 1471 return false; 1472 break; 1473 default: 1474 return false; 1475 } 1476 addr_t target = ReadCoreReg (Rm, &success); 1477 if (!success) 1478 return false; 1479 Register dwarf_reg; 1480 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + Rm); 1481 context.SetRegister (dwarf_reg); 1482 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_RA, lr)) 1483 return false; 1484 if (!BXWritePC(context, target)) 1485 return false; 1486 } 1487 return true; 1488} 1489 1490// Branch and Exchange causes a branch to an address and instruction set specified by a register. 1491bool 1492EmulateInstructionARM::EmulateBXRm (const uint32_t opcode, const ARMEncoding encoding) 1493{ 1494#if 0 1495 // ARM pseudo code... 1496 if (ConditionPassed()) 1497 { 1498 EncodingSpecificOperations(); 1499 BXWritePC(R[m]); 1500 } 1501#endif 1502 1503 if (ConditionPassed(opcode)) 1504 { 1505 EmulateInstruction::Context context; 1506 context.type = EmulateInstruction::eContextAbsoluteBranchRegister; 1507 uint32_t Rm; // the register with the target address 1508 switch (encoding) { 1509 case eEncodingT1: 1510 Rm = Bits32(opcode, 6, 3); 1511 if (InITBlock() && !LastInITBlock()) 1512 return false; 1513 break; 1514 case eEncodingA1: 1515 Rm = Bits32(opcode, 3, 0); 1516 break; 1517 default: 1518 return false; 1519 } 1520 bool success = false; 1521 addr_t target = ReadCoreReg (Rm, &success); 1522 if (!success) 1523 return false; 1524 1525 Register dwarf_reg; 1526 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + Rm); 1527 context.SetRegister (dwarf_reg); 1528 if (!BXWritePC(context, target)) 1529 return false; 1530 } 1531 return true; 1532} 1533 1534// Branch and Exchange Jazelle attempts to change to Jazelle state. If the attempt fails, it branches to an 1535// address and instruction set specified by a register as though it were a BX instruction. 1536// 1537// TODO: Emulate Jazelle architecture? 1538// We currently assume that switching to Jazelle state fails, thus treating BXJ as a BX operation. 1539bool 1540EmulateInstructionARM::EmulateBXJRm (const uint32_t opcode, const ARMEncoding encoding) 1541{ 1542#if 0 1543 // ARM pseudo code... 1544 if (ConditionPassed()) 1545 { 1546 EncodingSpecificOperations(); 1547 if JMCR.JE == '0' || CurrentInstrSet() == InstrSet_ThumbEE then 1548 BXWritePC(R[m]); 1549 else 1550 if JazelleAcceptsExecution() then 1551 SwitchToJazelleExecution(); 1552 else 1553 SUBARCHITECTURE_DEFINED handler call; 1554 } 1555#endif 1556 1557 if (ConditionPassed(opcode)) 1558 { 1559 EmulateInstruction::Context context; 1560 context.type = EmulateInstruction::eContextAbsoluteBranchRegister; 1561 uint32_t Rm; // the register with the target address 1562 switch (encoding) { 1563 case eEncodingT1: 1564 Rm = Bits32(opcode, 19, 16); 1565 if (BadReg(Rm)) 1566 return false; 1567 if (InITBlock() && !LastInITBlock()) 1568 return false; 1569 break; 1570 case eEncodingA1: 1571 Rm = Bits32(opcode, 3, 0); 1572 if (Rm == 15) 1573 return false; 1574 break; 1575 default: 1576 return false; 1577 } 1578 bool success = false; 1579 addr_t target = ReadCoreReg (Rm, &success); 1580 if (!success) 1581 return false; 1582 1583 Register dwarf_reg; 1584 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + Rm); 1585 context.SetRegister (dwarf_reg); 1586 if (!BXWritePC(context, target)) 1587 return false; 1588 } 1589 return true; 1590} 1591 1592// Set r7 to point to some ip offset. 1593// SUB (immediate) 1594bool 1595EmulateInstructionARM::EmulateSUBR7IPImm (const uint32_t opcode, const ARMEncoding encoding) 1596{ 1597#if 0 1598 // ARM pseudo code... 1599 if (ConditionPassed()) 1600 { 1601 EncodingSpecificOperations(); 1602 (result, carry, overflow) = AddWithCarry(SP, NOT(imm32), '1'); 1603 if d == 15 then // Can only occur for ARM encoding 1604 ALUWritePC(result); // setflags is always FALSE here 1605 else 1606 R[d] = result; 1607 if setflags then 1608 APSR.N = result<31>; 1609 APSR.Z = IsZeroBit(result); 1610 APSR.C = carry; 1611 APSR.V = overflow; 1612 } 1613#endif 1614 1615 if (ConditionPassed(opcode)) 1616 { 1617 bool success = false; 1618 const addr_t ip = ReadCoreReg (12, &success); 1619 if (!success) 1620 return false; 1621 uint32_t imm32; 1622 switch (encoding) { 1623 case eEncodingA1: 1624 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12) 1625 break; 1626 default: 1627 return false; 1628 } 1629 addr_t ip_offset = imm32; 1630 addr_t addr = ip - ip_offset; // the adjusted ip value 1631 1632 EmulateInstruction::Context context; 1633 context.type = EmulateInstruction::eContextRegisterPlusOffset; 1634 Register dwarf_reg; 1635 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r12); 1636 context.SetRegisterPlusOffset (dwarf_reg, -ip_offset); 1637 1638 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r7, addr)) 1639 return false; 1640 } 1641 return true; 1642} 1643 1644// Set ip to point to some stack offset. 1645// SUB (SP minus immediate) 1646bool 1647EmulateInstructionARM::EmulateSUBIPSPImm (const uint32_t opcode, const ARMEncoding encoding) 1648{ 1649#if 0 1650 // ARM pseudo code... 1651 if (ConditionPassed()) 1652 { 1653 EncodingSpecificOperations(); 1654 (result, carry, overflow) = AddWithCarry(SP, NOT(imm32), '1'); 1655 if d == 15 then // Can only occur for ARM encoding 1656 ALUWritePC(result); // setflags is always FALSE here 1657 else 1658 R[d] = result; 1659 if setflags then 1660 APSR.N = result<31>; 1661 APSR.Z = IsZeroBit(result); 1662 APSR.C = carry; 1663 APSR.V = overflow; 1664 } 1665#endif 1666 1667 if (ConditionPassed(opcode)) 1668 { 1669 bool success = false; 1670 const addr_t sp = ReadCoreReg (SP_REG, &success); 1671 if (!success) 1672 return false; 1673 uint32_t imm32; 1674 switch (encoding) { 1675 case eEncodingA1: 1676 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12) 1677 break; 1678 default: 1679 return false; 1680 } 1681 addr_t sp_offset = imm32; 1682 addr_t addr = sp - sp_offset; // the adjusted stack pointer value 1683 1684 EmulateInstruction::Context context; 1685 context.type = EmulateInstruction::eContextRegisterPlusOffset; 1686 Register dwarf_reg; 1687 dwarf_reg.SetRegister (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP); 1688 context.SetRegisterPlusOffset (dwarf_reg, -sp_offset); 1689 1690 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r12, addr)) 1691 return false; 1692 } 1693 return true; 1694} 1695 1696// This instruction subtracts an immediate value from the SP value, and writes 1697// the result to the destination register. 1698// 1699// If Rd == 13 => A sub operation to adjust the SP -- allocate space for local storage. 1700bool 1701EmulateInstructionARM::EmulateSUBSPImm (const uint32_t opcode, const ARMEncoding encoding) 1702{ 1703#if 0 1704 // ARM pseudo code... 1705 if (ConditionPassed()) 1706 { 1707 EncodingSpecificOperations(); 1708 (result, carry, overflow) = AddWithCarry(SP, NOT(imm32), '1'); 1709 if d == 15 then // Can only occur for ARM encoding 1710 ALUWritePC(result); // setflags is always FALSE here 1711 else 1712 R[d] = result; 1713 if setflags then 1714 APSR.N = result<31>; 1715 APSR.Z = IsZeroBit(result); 1716 APSR.C = carry; 1717 APSR.V = overflow; 1718 } 1719#endif 1720 1721 bool success = false; 1722 if (ConditionPassed(opcode)) 1723 { 1724 const addr_t sp = ReadCoreReg (SP_REG, &success); 1725 if (!success) 1726 return false; 1727 1728 uint32_t Rd; 1729 bool setflags; 1730 uint32_t imm32; 1731 switch (encoding) { 1732 case eEncodingT1: 1733 Rd = 13; 1734 setflags = false; 1735 imm32 = ThumbImm7Scaled(opcode); // imm32 = ZeroExtend(imm7:'00', 32) 1736 break; 1737 case eEncodingT2: 1738 Rd = Bits32(opcode, 11, 8); 1739 setflags = BitIsSet(opcode, 20); 1740 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8) 1741 if (Rd == 15 && setflags) 1742 return EmulateCMPImm(opcode, eEncodingT2); 1743 if (Rd == 15 && !setflags) 1744 return false; 1745 break; 1746 case eEncodingT3: 1747 Rd = Bits32(opcode, 11, 8); 1748 setflags = false; 1749 imm32 = ThumbImm12(opcode); // imm32 = ZeroExtend(i:imm3:imm8, 32) 1750 if (Rd == 15) 1751 return false; 1752 break; 1753 case eEncodingA1: 1754 Rd = Bits32(opcode, 15, 12); 1755 setflags = BitIsSet(opcode, 20); 1756 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12) 1757 1758 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions; 1759 if (Rd == 15 && setflags) 1760 return EmulateSUBSPcLrEtc (opcode, encoding); 1761 break; 1762 default: 1763 return false; 1764 } 1765 AddWithCarryResult res = AddWithCarry(sp, ~imm32, 1); 1766 1767 EmulateInstruction::Context context; 1768 if (Rd == 13) 1769 { 1770 uint64_t imm64 = imm32; // Need to expand it to 64 bits before attempting to negate it, or the wrong 1771 // value gets passed down to context.SetImmediateSigned. 1772 context.type = EmulateInstruction::eContextAdjustStackPointer; 1773 context.SetImmediateSigned (-imm64); // the stack pointer offset 1774 } 1775 else 1776 { 1777 context.type = EmulateInstruction::eContextImmediate; 1778 context.SetNoArgs (); 1779 } 1780 1781 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow)) 1782 return false; 1783 } 1784 return true; 1785} 1786 1787// A store operation to the stack that also updates the SP. 1788bool 1789EmulateInstructionARM::EmulateSTRRtSP (const uint32_t opcode, const ARMEncoding encoding) 1790{ 1791#if 0 1792 // ARM pseudo code... 1793 if (ConditionPassed()) 1794 { 1795 EncodingSpecificOperations(); 1796 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32); 1797 address = if index then offset_addr else R[n]; 1798 MemU[address,4] = if t == 15 then PCStoreValue() else R[t]; 1799 if wback then R[n] = offset_addr; 1800 } 1801#endif 1802 1803 bool success = false; 1804 1805 if (ConditionPassed(opcode)) 1806 { 1807 const uint32_t addr_byte_size = GetAddressByteSize(); 1808 const addr_t sp = ReadCoreReg (SP_REG, &success); 1809 if (!success) 1810 return false; 1811 uint32_t Rt; // the source register 1812 uint32_t imm12; 1813 uint32_t Rn; // This function assumes Rn is the SP, but we should verify that. 1814 1815 bool index; 1816 bool add; 1817 bool wback; 1818 switch (encoding) { 1819 case eEncodingA1: 1820 Rt = Bits32(opcode, 15, 12); 1821 imm12 = Bits32(opcode, 11, 0); 1822 Rn = Bits32 (opcode, 19, 16); 1823 1824 if (Rn != 13) // 13 is the SP reg on ARM. Verify that Rn == SP. 1825 return false; 1826 1827 index = BitIsSet (opcode, 24); 1828 add = BitIsSet (opcode, 23); 1829 wback = (BitIsClear (opcode, 24) || BitIsSet (opcode, 21)); 1830 1831 if (wback && ((Rn == 15) || (Rn == Rt))) 1832 return false; 1833 break; 1834 default: 1835 return false; 1836 } 1837 addr_t offset_addr; 1838 if (add) 1839 offset_addr = sp + imm12; 1840 else 1841 offset_addr = sp - imm12; 1842 1843 addr_t addr; 1844 if (index) 1845 addr = offset_addr; 1846 else 1847 addr = sp; 1848 1849 EmulateInstruction::Context context; 1850 context.type = EmulateInstruction::eContextPushRegisterOnStack; 1851 Register sp_reg; 1852 sp_reg.SetRegister (eRegisterKindDWARF, dwarf_sp); 1853 context.SetRegisterPlusOffset (sp_reg, addr - sp); 1854 if (Rt != 15) 1855 { 1856 uint32_t reg_value = ReadCoreReg(Rt, &success); 1857 if (!success) 1858 return false; 1859 if (!MemUWrite (context, addr, reg_value, addr_byte_size)) 1860 return false; 1861 } 1862 else 1863 { 1864 const uint32_t pc = ReadCoreReg(PC_REG, &success); 1865 if (!success) 1866 return false; 1867 if (!MemUWrite (context, addr, pc, addr_byte_size)) 1868 return false; 1869 } 1870 1871 1872 if (wback) 1873 { 1874 context.type = EmulateInstruction::eContextAdjustStackPointer; 1875 context.SetImmediateSigned (addr - sp); 1876 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, offset_addr)) 1877 return false; 1878 } 1879 } 1880 return true; 1881} 1882 1883// Vector Push stores multiple extension registers to the stack. 1884// It also updates SP to point to the start of the stored data. 1885bool 1886EmulateInstructionARM::EmulateVPUSH (const uint32_t opcode, const ARMEncoding encoding) 1887{ 1888#if 0 1889 // ARM pseudo code... 1890 if (ConditionPassed()) 1891 { 1892 EncodingSpecificOperations(); CheckVFPEnabled(TRUE); NullCheckIfThumbEE(13); 1893 address = SP - imm32; 1894 SP = SP - imm32; 1895 if single_regs then 1896 for r = 0 to regs-1 1897 MemA[address,4] = S[d+r]; address = address+4; 1898 else 1899 for r = 0 to regs-1 1900 // Store as two word-aligned words in the correct order for current endianness. 1901 MemA[address,4] = if BigEndian() then D[d+r]<63:32> else D[d+r]<31:0>; 1902 MemA[address+4,4] = if BigEndian() then D[d+r]<31:0> else D[d+r]<63:32>; 1903 address = address+8; 1904 } 1905#endif 1906 1907 bool success = false; 1908 1909 if (ConditionPassed(opcode)) 1910 { 1911 const uint32_t addr_byte_size = GetAddressByteSize(); 1912 const addr_t sp = ReadCoreReg (SP_REG, &success); 1913 if (!success) 1914 return false; 1915 bool single_regs; 1916 uint32_t d; // UInt(D:Vd) or UInt(Vd:D) starting register 1917 uint32_t imm32; // stack offset 1918 uint32_t regs; // number of registers 1919 switch (encoding) { 1920 case eEncodingT1: 1921 case eEncodingA1: 1922 single_regs = false; 1923 d = Bit32(opcode, 22) << 4 | Bits32(opcode, 15, 12); 1924 imm32 = Bits32(opcode, 7, 0) * addr_byte_size; 1925 // If UInt(imm8) is odd, see "FSTMX". 1926 regs = Bits32(opcode, 7, 0) / 2; 1927 // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE; 1928 if (regs == 0 || regs > 16 || (d + regs) > 32) 1929 return false; 1930 break; 1931 case eEncodingT2: 1932 case eEncodingA2: 1933 single_regs = true; 1934 d = Bits32(opcode, 15, 12) << 1 | Bit32(opcode, 22); 1935 imm32 = Bits32(opcode, 7, 0) * addr_byte_size; 1936 regs = Bits32(opcode, 7, 0); 1937 // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE; 1938 if (regs == 0 || regs > 16 || (d + regs) > 32) 1939 return false; 1940 break; 1941 default: 1942 return false; 1943 } 1944 uint32_t start_reg = single_regs ? dwarf_s0 : dwarf_d0; 1945 uint32_t reg_byte_size = single_regs ? addr_byte_size : addr_byte_size * 2; 1946 addr_t sp_offset = imm32; 1947 addr_t addr = sp - sp_offset; 1948 uint32_t i; 1949 1950 EmulateInstruction::Context context; 1951 context.type = EmulateInstruction::eContextPushRegisterOnStack; 1952 Register dwarf_reg; 1953 dwarf_reg.SetRegister (eRegisterKindDWARF, 0); 1954 Register sp_reg; 1955 sp_reg.SetRegister (eRegisterKindDWARF, dwarf_sp); 1956 for (i=0; i<regs; ++i) 1957 { 1958 dwarf_reg.num = start_reg + d + i; 1959 context.SetRegisterToRegisterPlusOffset ( dwarf_reg, sp_reg, addr - sp); 1960 // uint64_t to accommodate 64-bit registers. 1961 uint64_t reg_value = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_reg.num, 0, &success); 1962 if (!success) 1963 return false; 1964 if (!MemAWrite (context, addr, reg_value, reg_byte_size)) 1965 return false; 1966 addr += reg_byte_size; 1967 } 1968 1969 context.type = EmulateInstruction::eContextAdjustStackPointer; 1970 context.SetImmediateSigned (-sp_offset); 1971 1972 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, sp - sp_offset)) 1973 return false; 1974 } 1975 return true; 1976} 1977 1978// Vector Pop loads multiple extension registers from the stack. 1979// It also updates SP to point just above the loaded data. 1980bool 1981EmulateInstructionARM::EmulateVPOP (const uint32_t opcode, const ARMEncoding encoding) 1982{ 1983#if 0 1984 // ARM pseudo code... 1985 if (ConditionPassed()) 1986 { 1987 EncodingSpecificOperations(); CheckVFPEnabled(TRUE); NullCheckIfThumbEE(13); 1988 address = SP; 1989 SP = SP + imm32; 1990 if single_regs then 1991 for r = 0 to regs-1 1992 S[d+r] = MemA[address,4]; address = address+4; 1993 else 1994 for r = 0 to regs-1 1995 word1 = MemA[address,4]; word2 = MemA[address+4,4]; address = address+8; 1996 // Combine the word-aligned words in the correct order for current endianness. 1997 D[d+r] = if BigEndian() then word1:word2 else word2:word1; 1998 } 1999#endif 2000 2001 bool success = false; 2002 2003 if (ConditionPassed(opcode)) 2004 { 2005 const uint32_t addr_byte_size = GetAddressByteSize(); 2006 const addr_t sp = ReadCoreReg (SP_REG, &success); 2007 if (!success) 2008 return false; 2009 bool single_regs; 2010 uint32_t d; // UInt(D:Vd) or UInt(Vd:D) starting register 2011 uint32_t imm32; // stack offset 2012 uint32_t regs; // number of registers 2013 switch (encoding) { 2014 case eEncodingT1: 2015 case eEncodingA1: 2016 single_regs = false; 2017 d = Bit32(opcode, 22) << 4 | Bits32(opcode, 15, 12); 2018 imm32 = Bits32(opcode, 7, 0) * addr_byte_size; 2019 // If UInt(imm8) is odd, see "FLDMX". 2020 regs = Bits32(opcode, 7, 0) / 2; 2021 // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE; 2022 if (regs == 0 || regs > 16 || (d + regs) > 32) 2023 return false; 2024 break; 2025 case eEncodingT2: 2026 case eEncodingA2: 2027 single_regs = true; 2028 d = Bits32(opcode, 15, 12) << 1 | Bit32(opcode, 22); 2029 imm32 = Bits32(opcode, 7, 0) * addr_byte_size; 2030 regs = Bits32(opcode, 7, 0); 2031 // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE; 2032 if (regs == 0 || regs > 16 || (d + regs) > 32) 2033 return false; 2034 break; 2035 default: 2036 return false; 2037 } 2038 uint32_t start_reg = single_regs ? dwarf_s0 : dwarf_d0; 2039 uint32_t reg_byte_size = single_regs ? addr_byte_size : addr_byte_size * 2; 2040 addr_t sp_offset = imm32; 2041 addr_t addr = sp; 2042 uint32_t i; 2043 uint64_t data; // uint64_t to accomodate 64-bit registers. 2044 2045 EmulateInstruction::Context context; 2046 context.type = EmulateInstruction::eContextPopRegisterOffStack; 2047 Register dwarf_reg; 2048 dwarf_reg.SetRegister (eRegisterKindDWARF, 0); 2049 Register sp_reg; 2050 sp_reg.SetRegister (eRegisterKindDWARF, dwarf_sp); 2051 for (i=0; i<regs; ++i) 2052 { 2053 dwarf_reg.num = start_reg + d + i; 2054 context.SetRegisterPlusOffset (sp_reg, addr - sp); 2055 data = MemARead(context, addr, reg_byte_size, 0, &success); 2056 if (!success) 2057 return false; 2058 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_reg.num, data)) 2059 return false; 2060 addr += reg_byte_size; 2061 } 2062 2063 context.type = EmulateInstruction::eContextAdjustStackPointer; 2064 context.SetImmediateSigned (sp_offset); 2065 2066 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, sp + sp_offset)) 2067 return false; 2068 } 2069 return true; 2070} 2071 2072// SVC (previously SWI) 2073bool 2074EmulateInstructionARM::EmulateSVC (const uint32_t opcode, const ARMEncoding encoding) 2075{ 2076#if 0 2077 // ARM pseudo code... 2078 if (ConditionPassed()) 2079 { 2080 EncodingSpecificOperations(); 2081 CallSupervisor(); 2082 } 2083#endif 2084 2085 bool success = false; 2086 2087 if (ConditionPassed(opcode)) 2088 { 2089 const uint32_t pc = ReadCoreReg(PC_REG, &success); 2090 addr_t lr; // next instruction address 2091 if (!success) 2092 return false; 2093 uint32_t imm32; // the immediate constant 2094 uint32_t mode; // ARM or Thumb mode 2095 switch (encoding) { 2096 case eEncodingT1: 2097 lr = (pc + 2) | 1u; // return address 2098 imm32 = Bits32(opcode, 7, 0); 2099 mode = eModeThumb; 2100 break; 2101 case eEncodingA1: 2102 lr = pc + 4; // return address 2103 imm32 = Bits32(opcode, 23, 0); 2104 mode = eModeARM; 2105 break; 2106 default: 2107 return false; 2108 } 2109 2110 EmulateInstruction::Context context; 2111 context.type = EmulateInstruction::eContextSupervisorCall; 2112 context.SetModeAndImmediate (mode, imm32); 2113 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_RA, lr)) 2114 return false; 2115 } 2116 return true; 2117} 2118 2119// If Then makes up to four following instructions (the IT block) conditional. 2120bool 2121EmulateInstructionARM::EmulateIT (const uint32_t opcode, const ARMEncoding encoding) 2122{ 2123#if 0 2124 // ARM pseudo code... 2125 EncodingSpecificOperations(); 2126 ITSTATE.IT<7:0> = firstcond:mask; 2127#endif 2128 2129 m_it_session.InitIT(Bits32(opcode, 7, 0)); 2130 return true; 2131} 2132 2133// Branch causes a branch to a target address. 2134bool 2135EmulateInstructionARM::EmulateB (const uint32_t opcode, const ARMEncoding encoding) 2136{ 2137#if 0 2138 // ARM pseudo code... 2139 if (ConditionPassed()) 2140 { 2141 EncodingSpecificOperations(); 2142 BranchWritePC(PC + imm32); 2143 } 2144#endif 2145 2146 bool success = false; 2147 2148 if (ConditionPassed(opcode)) 2149 { 2150 EmulateInstruction::Context context; 2151 context.type = EmulateInstruction::eContextRelativeBranchImmediate; 2152 const uint32_t pc = ReadCoreReg(PC_REG, &success); 2153 if (!success) 2154 return false; 2155 addr_t target; // target address 2156 int32_t imm32; // PC-relative offset 2157 switch (encoding) { 2158 case eEncodingT1: 2159 // The 'cond' field is handled in EmulateInstructionARM::CurrentCond(). 2160 imm32 = llvm::SignExtend32<9>(Bits32(opcode, 7, 0) << 1); 2161 target = pc + imm32; 2162 context.SetModeAndImmediateSigned (eModeThumb, 4 + imm32); 2163 break; 2164 case eEncodingT2: 2165 imm32 = llvm::SignExtend32<12>(Bits32(opcode, 10, 0)); 2166 target = pc + imm32; 2167 context.SetModeAndImmediateSigned (eModeThumb, 4 + imm32); 2168 break; 2169 case eEncodingT3: 2170 // The 'cond' field is handled in EmulateInstructionARM::CurrentCond(). 2171 { 2172 uint32_t S = Bit32(opcode, 26); 2173 uint32_t imm6 = Bits32(opcode, 21, 16); 2174 uint32_t J1 = Bit32(opcode, 13); 2175 uint32_t J2 = Bit32(opcode, 11); 2176 uint32_t imm11 = Bits32(opcode, 10, 0); 2177 uint32_t imm21 = (S << 20) | (J2 << 19) | (J1 << 18) | (imm6 << 12) | (imm11 << 1); 2178 imm32 = llvm::SignExtend32<21>(imm21); 2179 target = pc + imm32; 2180 context.SetModeAndImmediateSigned (eModeThumb, 4 + imm32); 2181 break; 2182 } 2183 case eEncodingT4: 2184 { 2185 uint32_t S = Bit32(opcode, 26); 2186 uint32_t imm10 = Bits32(opcode, 25, 16); 2187 uint32_t J1 = Bit32(opcode, 13); 2188 uint32_t J2 = Bit32(opcode, 11); 2189 uint32_t imm11 = Bits32(opcode, 10, 0); 2190 uint32_t I1 = !(J1 ^ S); 2191 uint32_t I2 = !(J2 ^ S); 2192 uint32_t imm25 = (S << 24) | (I1 << 23) | (I2 << 22) | (imm10 << 12) | (imm11 << 1); 2193 imm32 = llvm::SignExtend32<25>(imm25); 2194 target = pc + imm32; 2195 context.SetModeAndImmediateSigned (eModeThumb, 4 + imm32); 2196 break; 2197 } 2198 case eEncodingA1: 2199 imm32 = llvm::SignExtend32<26>(Bits32(opcode, 23, 0) << 2); 2200 target = pc + imm32; 2201 context.SetModeAndImmediateSigned (eModeARM, 8 + imm32); 2202 break; 2203 default: 2204 return false; 2205 } 2206 if (!BranchWritePC(context, target)) 2207 return false; 2208 } 2209 return true; 2210} 2211 2212// Compare and Branch on Nonzero and Compare and Branch on Zero compare the value in a register with 2213// zero and conditionally branch forward a constant value. They do not affect the condition flags. 2214// CBNZ, CBZ 2215bool 2216EmulateInstructionARM::EmulateCB (const uint32_t opcode, const ARMEncoding encoding) 2217{ 2218#if 0 2219 // ARM pseudo code... 2220 EncodingSpecificOperations(); 2221 if nonzero ^ IsZero(R[n]) then 2222 BranchWritePC(PC + imm32); 2223#endif 2224 2225 bool success = false; 2226 2227 // Read the register value from the operand register Rn. 2228 uint32_t reg_val = ReadCoreReg(Bits32(opcode, 2, 0), &success); 2229 if (!success) 2230 return false; 2231 2232 EmulateInstruction::Context context; 2233 context.type = EmulateInstruction::eContextRelativeBranchImmediate; 2234 const uint32_t pc = ReadCoreReg(PC_REG, &success); 2235 if (!success) 2236 return false; 2237 2238 addr_t target; // target address 2239 uint32_t imm32; // PC-relative offset to branch forward 2240 bool nonzero; 2241 switch (encoding) { 2242 case eEncodingT1: 2243 imm32 = Bit32(opcode, 9) << 6 | Bits32(opcode, 7, 3) << 1; 2244 nonzero = BitIsSet(opcode, 11); 2245 target = pc + imm32; 2246 context.SetModeAndImmediateSigned (eModeThumb, 4 + imm32); 2247 break; 2248 default: 2249 return false; 2250 } 2251 if (nonzero ^ (reg_val == 0)) 2252 if (!BranchWritePC(context, target)) 2253 return false; 2254 2255 return true; 2256} 2257 2258// Table Branch Byte causes a PC-relative forward branch using a table of single byte offsets. 2259// A base register provides a pointer to the table, and a second register supplies an index into the table. 2260// The branch length is twice the value of the byte returned from the table. 2261// 2262// Table Branch Halfword causes a PC-relative forward branch using a table of single halfword offsets. 2263// A base register provides a pointer to the table, and a second register supplies an index into the table. 2264// The branch length is twice the value of the halfword returned from the table. 2265// TBB, TBH 2266bool 2267EmulateInstructionARM::EmulateTB (const uint32_t opcode, const ARMEncoding encoding) 2268{ 2269#if 0 2270 // ARM pseudo code... 2271 EncodingSpecificOperations(); NullCheckIfThumbEE(n); 2272 if is_tbh then 2273 halfwords = UInt(MemU[R[n]+LSL(R[m],1), 2]); 2274 else 2275 halfwords = UInt(MemU[R[n]+R[m], 1]); 2276 BranchWritePC(PC + 2*halfwords); 2277#endif 2278 2279 bool success = false; 2280 2281 uint32_t Rn; // the base register which contains the address of the table of branch lengths 2282 uint32_t Rm; // the index register which contains an integer pointing to a byte/halfword in the table 2283 bool is_tbh; // true if table branch halfword 2284 switch (encoding) { 2285 case eEncodingT1: 2286 Rn = Bits32(opcode, 19, 16); 2287 Rm = Bits32(opcode, 3, 0); 2288 is_tbh = BitIsSet(opcode, 4); 2289 if (Rn == 13 || BadReg(Rm)) 2290 return false; 2291 if (InITBlock() && !LastInITBlock()) 2292 return false; 2293 break; 2294 default: 2295 return false; 2296 } 2297 2298 // Read the address of the table from the operand register Rn. 2299 // The PC can be used, in which case the table immediately follows this instruction. 2300 uint32_t base = ReadCoreReg(Rm, &success); 2301 if (!success) 2302 return false; 2303 2304 // the table index 2305 uint32_t index = ReadCoreReg(Rm, &success); 2306 if (!success) 2307 return false; 2308 2309 // the offsetted table address 2310 addr_t addr = base + (is_tbh ? index*2 : index); 2311 2312 // PC-relative offset to branch forward 2313 EmulateInstruction::Context context; 2314 context.type = EmulateInstruction::eContextTableBranchReadMemory; 2315 uint32_t offset = MemURead(context, addr, is_tbh ? 2 : 1, 0, &success) * 2; 2316 if (!success) 2317 return false; 2318 2319 const uint32_t pc = ReadCoreReg(PC_REG, &success); 2320 if (!success) 2321 return false; 2322 2323 // target address 2324 addr_t target = pc + offset; 2325 context.type = EmulateInstruction::eContextRelativeBranchImmediate; 2326 context.SetModeAndImmediateSigned (eModeThumb, 4 + offset); 2327 2328 if (!BranchWritePC(context, target)) 2329 return false; 2330 2331 return true; 2332} 2333 2334// This instruction adds an immediate value to a register value, and writes the result to the destination register. 2335// It can optionally update the condition flags based on the result. 2336bool 2337EmulateInstructionARM::EmulateADDImmThumb (const uint32_t opcode, const ARMEncoding encoding) 2338{ 2339#if 0 2340 if ConditionPassed() then 2341 EncodingSpecificOperations(); 2342 (result, carry, overflow) = AddWithCarry(R[n], imm32, '0'); 2343 R[d] = result; 2344 if setflags then 2345 APSR.N = result<31>; 2346 APSR.Z = IsZeroBit(result); 2347 APSR.C = carry; 2348 APSR.V = overflow; 2349#endif 2350 2351 bool success = false; 2352 2353 if (ConditionPassed(opcode)) 2354 { 2355 uint32_t d; 2356 uint32_t n; 2357 bool setflags; 2358 uint32_t imm32; 2359 uint32_t carry_out; 2360 2361 //EncodingSpecificOperations(); 2362 switch (encoding) 2363 { 2364 case eEncodingT1: 2365 // d = UInt(Rd); n = UInt(Rn); setflags = !InITBlock(); imm32 = ZeroExtend(imm3, 32); 2366 d = Bits32 (opcode, 2, 0); 2367 n = Bits32 (opcode, 5, 3); 2368 setflags = !InITBlock(); 2369 imm32 = Bits32 (opcode, 8,6); 2370 2371 break; 2372 2373 case eEncodingT2: 2374 // d = UInt(Rdn); n = UInt(Rdn); setflags = !InITBlock(); imm32 = ZeroExtend(imm8, 32); 2375 d = Bits32 (opcode, 10, 8); 2376 n = Bits32 (opcode, 10, 8); 2377 setflags = !InITBlock(); 2378 imm32 = Bits32 (opcode, 7, 0); 2379 2380 break; 2381 2382 case eEncodingT3: 2383 // if Rd == '1111' && S == '1' then SEE CMN (immediate); 2384 // if Rn == '1101' then SEE ADD (SP plus immediate); 2385 // d = UInt(Rd); n = UInt(Rn); setflags = (S == '1'); imm32 = ThumbExpandImm(i:imm3:imm8); 2386 d = Bits32 (opcode, 11, 8); 2387 n = Bits32 (opcode, 19, 16); 2388 setflags = BitIsSet (opcode, 20); 2389 imm32 = ThumbExpandImm_C (opcode, APSR_C, carry_out); 2390 2391 // if BadReg(d) || n == 15 then UNPREDICTABLE; 2392 if (BadReg (d) || (n == 15)) 2393 return false; 2394 2395 break; 2396 2397 case eEncodingT4: 2398 { 2399 // if Rn == '1111' then SEE ADR; 2400 // if Rn == '1101' then SEE ADD (SP plus immediate); 2401 // d = UInt(Rd); n = UInt(Rn); setflags = FALSE; imm32 = ZeroExtend(i:imm3:imm8, 32); 2402 d = Bits32 (opcode, 11, 8); 2403 n = Bits32 (opcode, 19, 16); 2404 setflags = false; 2405 uint32_t i = Bit32 (opcode, 26); 2406 uint32_t imm3 = Bits32 (opcode, 14, 12); 2407 uint32_t imm8 = Bits32 (opcode, 7, 0); 2408 imm32 = (i << 11) | (imm3 << 8) | imm8; 2409 2410 // if BadReg(d) then UNPREDICTABLE; 2411 if (BadReg (d)) 2412 return false; 2413 2414 break; 2415 } 2416 default: 2417 return false; 2418 } 2419 2420 uint64_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success); 2421 if (!success) 2422 return false; 2423 2424 //(result, carry, overflow) = AddWithCarry(R[n], imm32, '0'); 2425 AddWithCarryResult res = AddWithCarry (Rn, imm32, 0); 2426 2427 Register reg_n; 2428 reg_n.SetRegister (eRegisterKindDWARF, dwarf_r0 + n); 2429 2430 EmulateInstruction::Context context; 2431 context.type = eContextAddition; 2432 context.SetRegisterPlusOffset (reg_n, imm32); 2433 2434 //R[d] = result; 2435 //if setflags then 2436 //APSR.N = result<31>; 2437 //APSR.Z = IsZeroBit(result); 2438 //APSR.C = carry; 2439 //APSR.V = overflow; 2440 if (!WriteCoreRegOptionalFlags (context, res.result, d, setflags, res.carry_out, res.overflow)) 2441 return false; 2442 2443 } 2444 return true; 2445} 2446 2447// This instruction adds an immediate value to a register value, and writes the result to the destination 2448// register. It can optionally update the condition flags based on the result. 2449bool 2450EmulateInstructionARM::EmulateADDImmARM (const uint32_t opcode, const ARMEncoding encoding) 2451{ 2452#if 0 2453 // ARM pseudo code... 2454 if ConditionPassed() then 2455 EncodingSpecificOperations(); 2456 (result, carry, overflow) = AddWithCarry(R[n], imm32, '0'); 2457 if d == 15 then 2458 ALUWritePC(result); // setflags is always FALSE here 2459 else 2460 R[d] = result; 2461 if setflags then 2462 APSR.N = result<31>; 2463 APSR.Z = IsZeroBit(result); 2464 APSR.C = carry; 2465 APSR.V = overflow; 2466#endif 2467 2468 bool success = false; 2469 2470 if (ConditionPassed(opcode)) 2471 { 2472 uint32_t Rd, Rn; 2473 uint32_t imm32; // the immediate value to be added to the value obtained from Rn 2474 bool setflags; 2475 switch (encoding) 2476 { 2477 case eEncodingA1: 2478 Rd = Bits32(opcode, 15, 12); 2479 Rn = Bits32(opcode, 19, 16); 2480 setflags = BitIsSet(opcode, 20); 2481 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12) 2482 break; 2483 default: 2484 return false; 2485 } 2486 2487 // Read the first operand. 2488 uint32_t val1 = ReadCoreReg(Rn, &success); 2489 if (!success) 2490 return false; 2491 2492 AddWithCarryResult res = AddWithCarry(val1, imm32, 0); 2493 2494 EmulateInstruction::Context context; 2495 context.type = EmulateInstruction::eContextAddition; 2496 Register dwarf_reg; 2497 dwarf_reg.SetRegister (eRegisterKindDWARF, Rn); 2498 context.SetRegisterPlusOffset (dwarf_reg, imm32); 2499 2500 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow)) 2501 return false; 2502 } 2503 return true; 2504} 2505 2506// This instruction adds a register value and an optionally-shifted register value, and writes the result 2507// to the destination register. It can optionally update the condition flags based on the result. 2508bool 2509EmulateInstructionARM::EmulateADDReg (const uint32_t opcode, const ARMEncoding encoding) 2510{ 2511#if 0 2512 // ARM pseudo code... 2513 if ConditionPassed() then 2514 EncodingSpecificOperations(); 2515 shifted = Shift(R[m], shift_t, shift_n, APSR.C); 2516 (result, carry, overflow) = AddWithCarry(R[n], shifted, '0'); 2517 if d == 15 then 2518 ALUWritePC(result); // setflags is always FALSE here 2519 else 2520 R[d] = result; 2521 if setflags then 2522 APSR.N = result<31>; 2523 APSR.Z = IsZeroBit(result); 2524 APSR.C = carry; 2525 APSR.V = overflow; 2526#endif 2527 2528 bool success = false; 2529 2530 if (ConditionPassed(opcode)) 2531 { 2532 uint32_t Rd, Rn, Rm; 2533 ARM_ShifterType shift_t; 2534 uint32_t shift_n; // the shift applied to the value read from Rm 2535 bool setflags; 2536 switch (encoding) 2537 { 2538 case eEncodingT1: 2539 Rd = Bits32(opcode, 2, 0); 2540 Rn = Bits32(opcode, 5, 3); 2541 Rm = Bits32(opcode, 8, 6); 2542 setflags = !InITBlock(); 2543 shift_t = SRType_LSL; 2544 shift_n = 0; 2545 break; 2546 case eEncodingT2: 2547 Rd = Rn = Bit32(opcode, 7) << 3 | Bits32(opcode, 2, 0); 2548 Rm = Bits32(opcode, 6, 3); 2549 setflags = false; 2550 shift_t = SRType_LSL; 2551 shift_n = 0; 2552 if (Rn == 15 && Rm == 15) 2553 return false; 2554 if (Rd == 15 && InITBlock() && !LastInITBlock()) 2555 return false; 2556 break; 2557 case eEncodingA1: 2558 Rd = Bits32(opcode, 15, 12); 2559 Rn = Bits32(opcode, 19, 16); 2560 Rm = Bits32(opcode, 3, 0); 2561 setflags = BitIsSet(opcode, 20); 2562 shift_n = DecodeImmShiftARM(opcode, shift_t); 2563 break; 2564 default: 2565 return false; 2566 } 2567 2568 // Read the first operand. 2569 uint32_t val1 = ReadCoreReg(Rn, &success); 2570 if (!success) 2571 return false; 2572 2573 // Read the second operand. 2574 uint32_t val2 = ReadCoreReg(Rm, &success); 2575 if (!success) 2576 return false; 2577 2578 uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C); 2579 AddWithCarryResult res = AddWithCarry(val1, shifted, 0); 2580 2581 EmulateInstruction::Context context; 2582 context.type = EmulateInstruction::eContextAddition; 2583 Register op1_reg; 2584 Register op2_reg; 2585 op1_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + Rn); 2586 op2_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + Rm); 2587 context.SetRegisterRegisterOperands (op1_reg, op2_reg); 2588 2589 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow)) 2590 return false; 2591 } 2592 return true; 2593} 2594 2595// Compare Negative (immediate) adds a register value and an immediate value. 2596// It updates the condition flags based on the result, and discards the result. 2597bool 2598EmulateInstructionARM::EmulateCMNImm (const uint32_t opcode, const ARMEncoding encoding) 2599{ 2600#if 0 2601 // ARM pseudo code... 2602 if ConditionPassed() then 2603 EncodingSpecificOperations(); 2604 (result, carry, overflow) = AddWithCarry(R[n], imm32, '0'); 2605 APSR.N = result<31>; 2606 APSR.Z = IsZeroBit(result); 2607 APSR.C = carry; 2608 APSR.V = overflow; 2609#endif 2610 2611 bool success = false; 2612 2613 uint32_t Rn; // the first operand 2614 uint32_t imm32; // the immediate value to be compared with 2615 switch (encoding) { 2616 case eEncodingT1: 2617 Rn = Bits32(opcode, 19, 16); 2618 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8) 2619 if (Rn == 15) 2620 return false; 2621 break; 2622 case eEncodingA1: 2623 Rn = Bits32(opcode, 19, 16); 2624 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12) 2625 break; 2626 default: 2627 return false; 2628 } 2629 // Read the register value from the operand register Rn. 2630 uint32_t reg_val = ReadCoreReg(Rn, &success); 2631 if (!success) 2632 return false; 2633 2634 AddWithCarryResult res = AddWithCarry(reg_val, imm32, 0); 2635 2636 EmulateInstruction::Context context; 2637 context.type = EmulateInstruction::eContextImmediate; 2638 context.SetNoArgs (); 2639 if (!WriteFlags(context, res.result, res.carry_out, res.overflow)) 2640 return false; 2641 2642 return true; 2643} 2644 2645// Compare Negative (register) adds a register value and an optionally-shifted register value. 2646// It updates the condition flags based on the result, and discards the result. 2647bool 2648EmulateInstructionARM::EmulateCMNReg (const uint32_t opcode, const ARMEncoding encoding) 2649{ 2650#if 0 2651 // ARM pseudo code... 2652 if ConditionPassed() then 2653 EncodingSpecificOperations(); 2654 shifted = Shift(R[m], shift_t, shift_n, APSR.C); 2655 (result, carry, overflow) = AddWithCarry(R[n], shifted, '0'); 2656 APSR.N = result<31>; 2657 APSR.Z = IsZeroBit(result); 2658 APSR.C = carry; 2659 APSR.V = overflow; 2660#endif 2661 2662 bool success = false; 2663 2664 uint32_t Rn; // the first operand 2665 uint32_t Rm; // the second operand 2666 ARM_ShifterType shift_t; 2667 uint32_t shift_n; // the shift applied to the value read from Rm 2668 switch (encoding) { 2669 case eEncodingT1: 2670 Rn = Bits32(opcode, 2, 0); 2671 Rm = Bits32(opcode, 5, 3); 2672 shift_t = SRType_LSL; 2673 shift_n = 0; 2674 break; 2675 case eEncodingT2: 2676 Rn = Bits32(opcode, 19, 16); 2677 Rm = Bits32(opcode, 3, 0); 2678 shift_n = DecodeImmShiftThumb(opcode, shift_t); 2679 // if n == 15 || BadReg(m) then UNPREDICTABLE; 2680 if (Rn == 15 || BadReg(Rm)) 2681 return false; 2682 break; 2683 case eEncodingA1: 2684 Rn = Bits32(opcode, 19, 16); 2685 Rm = Bits32(opcode, 3, 0); 2686 shift_n = DecodeImmShiftARM(opcode, shift_t); 2687 break; 2688 default: 2689 return false; 2690 } 2691 // Read the register value from register Rn. 2692 uint32_t val1 = ReadCoreReg(Rn, &success); 2693 if (!success) 2694 return false; 2695 2696 // Read the register value from register Rm. 2697 uint32_t val2 = ReadCoreReg(Rm, &success); 2698 if (!success) 2699 return false; 2700 2701 uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C); 2702 AddWithCarryResult res = AddWithCarry(val1, shifted, 0); 2703 2704 EmulateInstruction::Context context; 2705 context.type = EmulateInstruction::eContextImmediate; 2706 context.SetNoArgs(); 2707 if (!WriteFlags(context, res.result, res.carry_out, res.overflow)) 2708 return false; 2709 2710 return true; 2711} 2712 2713// Compare (immediate) subtracts an immediate value from a register value. 2714// It updates the condition flags based on the result, and discards the result. 2715bool 2716EmulateInstructionARM::EmulateCMPImm (const uint32_t opcode, const ARMEncoding encoding) 2717{ 2718#if 0 2719 // ARM pseudo code... 2720 if ConditionPassed() then 2721 EncodingSpecificOperations(); 2722 (result, carry, overflow) = AddWithCarry(R[n], NOT(imm32), '1'); 2723 APSR.N = result<31>; 2724 APSR.Z = IsZeroBit(result); 2725 APSR.C = carry; 2726 APSR.V = overflow; 2727#endif 2728 2729 bool success = false; 2730 2731 uint32_t Rn; // the first operand 2732 uint32_t imm32; // the immediate value to be compared with 2733 switch (encoding) { 2734 case eEncodingT1: 2735 Rn = Bits32(opcode, 10, 8); 2736 imm32 = Bits32(opcode, 7, 0); 2737 break; 2738 case eEncodingT2: 2739 Rn = Bits32(opcode, 19, 16); 2740 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8) 2741 if (Rn == 15) 2742 return false; 2743 break; 2744 case eEncodingA1: 2745 Rn = Bits32(opcode, 19, 16); 2746 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12) 2747 break; 2748 default: 2749 return false; 2750 } 2751 // Read the register value from the operand register Rn. 2752 uint32_t reg_val = ReadCoreReg(Rn, &success); 2753 if (!success) 2754 return false; 2755 2756 AddWithCarryResult res = AddWithCarry(reg_val, ~imm32, 1); 2757 2758 EmulateInstruction::Context context; 2759 context.type = EmulateInstruction::eContextImmediate; 2760 context.SetNoArgs (); 2761 if (!WriteFlags(context, res.result, res.carry_out, res.overflow)) 2762 return false; 2763 2764 return true; 2765} 2766 2767// Compare (register) subtracts an optionally-shifted register value from a register value. 2768// It updates the condition flags based on the result, and discards the result. 2769bool 2770EmulateInstructionARM::EmulateCMPReg (const uint32_t opcode, const ARMEncoding encoding) 2771{ 2772#if 0 2773 // ARM pseudo code... 2774 if ConditionPassed() then 2775 EncodingSpecificOperations(); 2776 shifted = Shift(R[m], shift_t, shift_n, APSR.C); 2777 (result, carry, overflow) = AddWithCarry(R[n], NOT(shifted), '1'); 2778 APSR.N = result<31>; 2779 APSR.Z = IsZeroBit(result); 2780 APSR.C = carry; 2781 APSR.V = overflow; 2782#endif 2783 2784 bool success = false; 2785 2786 uint32_t Rn; // the first operand 2787 uint32_t Rm; // the second operand 2788 ARM_ShifterType shift_t; 2789 uint32_t shift_n; // the shift applied to the value read from Rm 2790 switch (encoding) { 2791 case eEncodingT1: 2792 Rn = Bits32(opcode, 2, 0); 2793 Rm = Bits32(opcode, 5, 3); 2794 shift_t = SRType_LSL; 2795 shift_n = 0; 2796 break; 2797 case eEncodingT2: 2798 Rn = Bit32(opcode, 7) << 3 | Bits32(opcode, 2, 0); 2799 Rm = Bits32(opcode, 6, 3); 2800 shift_t = SRType_LSL; 2801 shift_n = 0; 2802 if (Rn < 8 && Rm < 8) 2803 return false; 2804 if (Rn == 15 || Rm == 15) 2805 return false; 2806 break; 2807 case eEncodingA1: 2808 Rn = Bits32(opcode, 19, 16); 2809 Rm = Bits32(opcode, 3, 0); 2810 shift_n = DecodeImmShiftARM(opcode, shift_t); 2811 break; 2812 default: 2813 return false; 2814 } 2815 // Read the register value from register Rn. 2816 uint32_t val1 = ReadCoreReg(Rn, &success); 2817 if (!success) 2818 return false; 2819 2820 // Read the register value from register Rm. 2821 uint32_t val2 = ReadCoreReg(Rm, &success); 2822 if (!success) 2823 return false; 2824 2825 uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C); 2826 AddWithCarryResult res = AddWithCarry(val1, ~shifted, 1); 2827 2828 EmulateInstruction::Context context; 2829 context.type = EmulateInstruction::eContextImmediate; 2830 context.SetNoArgs(); 2831 if (!WriteFlags(context, res.result, res.carry_out, res.overflow)) 2832 return false; 2833 2834 return true; 2835} 2836 2837// Arithmetic Shift Right (immediate) shifts a register value right by an immediate number of bits, 2838// shifting in copies of its sign bit, and writes the result to the destination register. It can 2839// optionally update the condition flags based on the result. 2840bool 2841EmulateInstructionARM::EmulateASRImm (const uint32_t opcode, const ARMEncoding encoding) 2842{ 2843#if 0 2844 // ARM pseudo code... 2845 if ConditionPassed() then 2846 EncodingSpecificOperations(); 2847 (result, carry) = Shift_C(R[m], SRType_ASR, shift_n, APSR.C); 2848 if d == 15 then // Can only occur for ARM encoding 2849 ALUWritePC(result); // setflags is always FALSE here 2850 else 2851 R[d] = result; 2852 if setflags then 2853 APSR.N = result<31>; 2854 APSR.Z = IsZeroBit(result); 2855 APSR.C = carry; 2856 // APSR.V unchanged 2857#endif 2858 2859 return EmulateShiftImm (opcode, encoding, SRType_ASR); 2860} 2861 2862// Arithmetic Shift Right (register) shifts a register value right by a variable number of bits, 2863// shifting in copies of its sign bit, and writes the result to the destination register. 2864// The variable number of bits is read from the bottom byte of a register. It can optionally update 2865// the condition flags based on the result. 2866bool 2867EmulateInstructionARM::EmulateASRReg (const uint32_t opcode, const ARMEncoding encoding) 2868{ 2869#if 0 2870 // ARM pseudo code... 2871 if ConditionPassed() then 2872 EncodingSpecificOperations(); 2873 shift_n = UInt(R[m]<7:0>); 2874 (result, carry) = Shift_C(R[m], SRType_ASR, shift_n, APSR.C); 2875 R[d] = result; 2876 if setflags then 2877 APSR.N = result<31>; 2878 APSR.Z = IsZeroBit(result); 2879 APSR.C = carry; 2880 // APSR.V unchanged 2881#endif 2882 2883 return EmulateShiftReg (opcode, encoding, SRType_ASR); 2884} 2885 2886// Logical Shift Left (immediate) shifts a register value left by an immediate number of bits, 2887// shifting in zeros, and writes the result to the destination register. It can optionally 2888// update the condition flags based on the result. 2889bool 2890EmulateInstructionARM::EmulateLSLImm (const uint32_t opcode, const ARMEncoding encoding) 2891{ 2892#if 0 2893 // ARM pseudo code... 2894 if ConditionPassed() then 2895 EncodingSpecificOperations(); 2896 (result, carry) = Shift_C(R[m], SRType_LSL, shift_n, APSR.C); 2897 if d == 15 then // Can only occur for ARM encoding 2898 ALUWritePC(result); // setflags is always FALSE here 2899 else 2900 R[d] = result; 2901 if setflags then 2902 APSR.N = result<31>; 2903 APSR.Z = IsZeroBit(result); 2904 APSR.C = carry; 2905 // APSR.V unchanged 2906#endif 2907 2908 return EmulateShiftImm (opcode, encoding, SRType_LSL); 2909} 2910 2911// Logical Shift Left (register) shifts a register value left by a variable number of bits, 2912// shifting in zeros, and writes the result to the destination register. The variable number 2913// of bits is read from the bottom byte of a register. It can optionally update the condition 2914// flags based on the result. 2915bool 2916EmulateInstructionARM::EmulateLSLReg (const uint32_t opcode, const ARMEncoding encoding) 2917{ 2918#if 0 2919 // ARM pseudo code... 2920 if ConditionPassed() then 2921 EncodingSpecificOperations(); 2922 shift_n = UInt(R[m]<7:0>); 2923 (result, carry) = Shift_C(R[m], SRType_LSL, shift_n, APSR.C); 2924 R[d] = result; 2925 if setflags then 2926 APSR.N = result<31>; 2927 APSR.Z = IsZeroBit(result); 2928 APSR.C = carry; 2929 // APSR.V unchanged 2930#endif 2931 2932 return EmulateShiftReg (opcode, encoding, SRType_LSL); 2933} 2934 2935// Logical Shift Right (immediate) shifts a register value right by an immediate number of bits, 2936// shifting in zeros, and writes the result to the destination register. It can optionally 2937// update the condition flags based on the result. 2938bool 2939EmulateInstructionARM::EmulateLSRImm (const uint32_t opcode, const ARMEncoding encoding) 2940{ 2941#if 0 2942 // ARM pseudo code... 2943 if ConditionPassed() then 2944 EncodingSpecificOperations(); 2945 (result, carry) = Shift_C(R[m], SRType_LSR, shift_n, APSR.C); 2946 if d == 15 then // Can only occur for ARM encoding 2947 ALUWritePC(result); // setflags is always FALSE here 2948 else 2949 R[d] = result; 2950 if setflags then 2951 APSR.N = result<31>; 2952 APSR.Z = IsZeroBit(result); 2953 APSR.C = carry; 2954 // APSR.V unchanged 2955#endif 2956 2957 return EmulateShiftImm (opcode, encoding, SRType_LSR); 2958} 2959 2960// Logical Shift Right (register) shifts a register value right by a variable number of bits, 2961// shifting in zeros, and writes the result to the destination register. The variable number 2962// of bits is read from the bottom byte of a register. It can optionally update the condition 2963// flags based on the result. 2964bool 2965EmulateInstructionARM::EmulateLSRReg (const uint32_t opcode, const ARMEncoding encoding) 2966{ 2967#if 0 2968 // ARM pseudo code... 2969 if ConditionPassed() then 2970 EncodingSpecificOperations(); 2971 shift_n = UInt(R[m]<7:0>); 2972 (result, carry) = Shift_C(R[m], SRType_LSR, shift_n, APSR.C); 2973 R[d] = result; 2974 if setflags then 2975 APSR.N = result<31>; 2976 APSR.Z = IsZeroBit(result); 2977 APSR.C = carry; 2978 // APSR.V unchanged 2979#endif 2980 2981 return EmulateShiftReg (opcode, encoding, SRType_LSR); 2982} 2983 2984// Rotate Right (immediate) provides the value of the contents of a register rotated by a constant value. 2985// The bits that are rotated off the right end are inserted into the vacated bit positions on the left. 2986// It can optionally update the condition flags based on the result. 2987bool 2988EmulateInstructionARM::EmulateRORImm (const uint32_t opcode, const ARMEncoding encoding) 2989{ 2990#if 0 2991 // ARM pseudo code... 2992 if ConditionPassed() then 2993 EncodingSpecificOperations(); 2994 (result, carry) = Shift_C(R[m], SRType_ROR, shift_n, APSR.C); 2995 if d == 15 then // Can only occur for ARM encoding 2996 ALUWritePC(result); // setflags is always FALSE here 2997 else 2998 R[d] = result; 2999 if setflags then 3000 APSR.N = result<31>; 3001 APSR.Z = IsZeroBit(result); 3002 APSR.C = carry; 3003 // APSR.V unchanged 3004#endif 3005 3006 return EmulateShiftImm (opcode, encoding, SRType_ROR); 3007} 3008 3009// Rotate Right (register) provides the value of the contents of a register rotated by a variable number of bits. 3010// The bits that are rotated off the right end are inserted into the vacated bit positions on the left. 3011// The variable number of bits is read from the bottom byte of a register. It can optionally update the condition 3012// flags based on the result. 3013bool 3014EmulateInstructionARM::EmulateRORReg (const uint32_t opcode, const ARMEncoding encoding) 3015{ 3016#if 0 3017 // ARM pseudo code... 3018 if ConditionPassed() then 3019 EncodingSpecificOperations(); 3020 shift_n = UInt(R[m]<7:0>); 3021 (result, carry) = Shift_C(R[m], SRType_ROR, shift_n, APSR.C); 3022 R[d] = result; 3023 if setflags then 3024 APSR.N = result<31>; 3025 APSR.Z = IsZeroBit(result); 3026 APSR.C = carry; 3027 // APSR.V unchanged 3028#endif 3029 3030 return EmulateShiftReg (opcode, encoding, SRType_ROR); 3031} 3032 3033// Rotate Right with Extend provides the value of the contents of a register shifted right by one place, 3034// with the carry flag shifted into bit [31]. 3035// 3036// RRX can optionally update the condition flags based on the result. 3037// In that case, bit [0] is shifted into the carry flag. 3038bool 3039EmulateInstructionARM::EmulateRRX (const uint32_t opcode, const ARMEncoding encoding) 3040{ 3041#if 0 3042 // ARM pseudo code... 3043 if ConditionPassed() then 3044 EncodingSpecificOperations(); 3045 (result, carry) = Shift_C(R[m], SRType_RRX, 1, APSR.C); 3046 if d == 15 then // Can only occur for ARM encoding 3047 ALUWritePC(result); // setflags is always FALSE here 3048 else 3049 R[d] = result; 3050 if setflags then 3051 APSR.N = result<31>; 3052 APSR.Z = IsZeroBit(result); 3053 APSR.C = carry; 3054 // APSR.V unchanged 3055#endif 3056 3057 return EmulateShiftImm (opcode, encoding, SRType_RRX); 3058} 3059 3060bool 3061EmulateInstructionARM::EmulateShiftImm (const uint32_t opcode, const ARMEncoding encoding, ARM_ShifterType shift_type) 3062{ 3063 assert(shift_type == SRType_ASR 3064 || shift_type == SRType_LSL 3065 || shift_type == SRType_LSR 3066 || shift_type == SRType_ROR 3067 || shift_type == SRType_RRX); 3068 3069 bool success = false; 3070 3071 if (ConditionPassed(opcode)) 3072 { 3073 uint32_t Rd; // the destination register 3074 uint32_t Rm; // the first operand register 3075 uint32_t imm5; // encoding for the shift amount 3076 uint32_t carry; // the carry bit after the shift operation 3077 bool setflags; 3078 3079 // Special case handling! 3080 // A8.6.139 ROR (immediate) -- Encoding T1 3081 ARMEncoding use_encoding = encoding; 3082 if (shift_type == SRType_ROR && use_encoding == eEncodingT1) 3083 { 3084 // Morph the T1 encoding from the ARM Architecture Manual into T2 encoding to 3085 // have the same decoding of bit fields as the other Thumb2 shift operations. 3086 use_encoding = eEncodingT2; 3087 } 3088 3089 switch (use_encoding) { 3090 case eEncodingT1: 3091 // Due to the above special case handling! 3092 assert(shift_type != SRType_ROR); 3093 3094 Rd = Bits32(opcode, 2, 0); 3095 Rm = Bits32(opcode, 5, 3); 3096 setflags = !InITBlock(); 3097 imm5 = Bits32(opcode, 10, 6); 3098 break; 3099 case eEncodingT2: 3100 // A8.6.141 RRX 3101 assert(shift_type != SRType_RRX); 3102 3103 Rd = Bits32(opcode, 11, 8); 3104 Rm = Bits32(opcode, 3, 0); 3105 setflags = BitIsSet(opcode, 20); 3106 imm5 = Bits32(opcode, 14, 12) << 2 | Bits32(opcode, 7, 6); 3107 if (BadReg(Rd) || BadReg(Rm)) 3108 return false; 3109 break; 3110 case eEncodingA1: 3111 Rd = Bits32(opcode, 15, 12); 3112 Rm = Bits32(opcode, 3, 0); 3113 setflags = BitIsSet(opcode, 20); 3114 imm5 = Bits32(opcode, 11, 7); 3115 break; 3116 default: 3117 return false; 3118 } 3119 3120 // A8.6.139 ROR (immediate) 3121 if (shift_type == SRType_ROR && imm5 == 0) 3122 shift_type = SRType_RRX; 3123 3124 // Get the first operand. 3125 uint32_t value = ReadCoreReg (Rm, &success); 3126 if (!success) 3127 return false; 3128 3129 // Decode the shift amount if not RRX. 3130 uint32_t amt = (shift_type == SRType_RRX ? 1 : DecodeImmShift(shift_type, imm5)); 3131 3132 uint32_t result = Shift_C(value, shift_type, amt, APSR_C, carry); 3133 3134 // The context specifies that an immediate is to be moved into Rd. 3135 EmulateInstruction::Context context; 3136 context.type = EmulateInstruction::eContextImmediate; 3137 context.SetNoArgs (); 3138 3139 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry)) 3140 return false; 3141 } 3142 return true; 3143} 3144 3145bool 3146EmulateInstructionARM::EmulateShiftReg (const uint32_t opcode, const ARMEncoding encoding, ARM_ShifterType shift_type) 3147{ 3148 assert(shift_type == SRType_ASR || shift_type == SRType_LSL || shift_type == SRType_LSR); 3149 3150 bool success = false; 3151 3152 if (ConditionPassed(opcode)) 3153 { 3154 uint32_t Rd; // the destination register 3155 uint32_t Rn; // the first operand register 3156 uint32_t Rm; // the register whose bottom byte contains the amount to shift by 3157 uint32_t carry; // the carry bit after the shift operation 3158 bool setflags; 3159 switch (encoding) { 3160 case eEncodingT1: 3161 Rd = Bits32(opcode, 2, 0); 3162 Rn = Rd; 3163 Rm = Bits32(opcode, 5, 3); 3164 setflags = !InITBlock(); 3165 break; 3166 case eEncodingT2: 3167 Rd = Bits32(opcode, 11, 8); 3168 Rn = Bits32(opcode, 19, 16); 3169 Rm = Bits32(opcode, 3, 0); 3170 setflags = BitIsSet(opcode, 20); 3171 if (BadReg(Rd) || BadReg(Rn) || BadReg(Rm)) 3172 return false; 3173 break; 3174 case eEncodingA1: 3175 Rd = Bits32(opcode, 15, 12); 3176 Rn = Bits32(opcode, 3, 0); 3177 Rm = Bits32(opcode, 11, 8); 3178 setflags = BitIsSet(opcode, 20); 3179 if (Rd == 15 || Rn == 15 || Rm == 15) 3180 return false; 3181 break; 3182 default: 3183 return false; 3184 } 3185 3186 // Get the first operand. 3187 uint32_t value = ReadCoreReg (Rn, &success); 3188 if (!success) 3189 return false; 3190 // Get the Rm register content. 3191 uint32_t val = ReadCoreReg (Rm, &success); 3192 if (!success) 3193 return false; 3194 3195 // Get the shift amount. 3196 uint32_t amt = Bits32(val, 7, 0); 3197 3198 uint32_t result = Shift_C(value, shift_type, amt, APSR_C, carry); 3199 3200 // The context specifies that an immediate is to be moved into Rd. 3201 EmulateInstruction::Context context; 3202 context.type = EmulateInstruction::eContextImmediate; 3203 context.SetNoArgs (); 3204 3205 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry)) 3206 return false; 3207 } 3208 return true; 3209} 3210 3211// LDM loads multiple registers from consecutive memory locations, using an 3212// address from a base register. Optionally the address just above the highest of those locations 3213// can be written back to the base register. 3214bool 3215EmulateInstructionARM::EmulateLDM (const uint32_t opcode, const ARMEncoding encoding) 3216{ 3217#if 0 3218 // ARM pseudo code... 3219 if ConditionPassed() 3220 EncodingSpecificOperations(); NullCheckIfThumbEE (n); 3221 address = R[n]; 3222 3223 for i = 0 to 14 3224 if registers<i> == '1' then 3225 R[i] = MemA[address, 4]; address = address + 4; 3226 if registers<15> == '1' then 3227 LoadWritePC (MemA[address, 4]); 3228 3229 if wback && registers<n> == '0' then R[n] = R[n] + 4 * BitCount (registers); 3230 if wback && registers<n> == '1' then R[n] = bits(32) UNKNOWN; // Only possible for encoding A1 3231 3232#endif 3233 3234 bool success = false; 3235 3236 if (ConditionPassed(opcode)) 3237 { 3238 uint32_t n; 3239 uint32_t registers = 0; 3240 bool wback; 3241 const uint32_t addr_byte_size = GetAddressByteSize(); 3242 switch (encoding) 3243 { 3244 case eEncodingT1: 3245 // n = UInt(Rn); registers = '00000000':register_list; wback = (registers<n> == '0'); 3246 n = Bits32 (opcode, 10, 8); 3247 registers = Bits32 (opcode, 7, 0); 3248 registers = registers & 0x00ff; // Make sure the top 8 bits are zeros. 3249 wback = BitIsClear (registers, n); 3250 // if BitCount(registers) < 1 then UNPREDICTABLE; 3251 if (BitCount(registers) < 1) 3252 return false; 3253 break; 3254 case eEncodingT2: 3255 // if W == '1' && Rn == '1101' then SEE POP; 3256 // n = UInt(Rn); registers = P:M:'0':register_list; wback = (W == '1'); 3257 n = Bits32 (opcode, 19, 16); 3258 registers = Bits32 (opcode, 15, 0); 3259 registers = registers & 0xdfff; // Make sure bit 13 is zero. 3260 wback = BitIsSet (opcode, 21); 3261 3262 // if n == 15 || BitCount(registers) < 2 || (P == '1' && M == '1') then UNPREDICTABLE; 3263 if ((n == 15) 3264 || (BitCount (registers) < 2) 3265 || (BitIsSet (opcode, 14) && BitIsSet (opcode, 15))) 3266 return false; 3267 3268 // if registers<15> == '1' && InITBlock() && !LastInITBlock() then UNPREDICTABLE; 3269 if (BitIsSet (registers, 15) && InITBlock() && !LastInITBlock()) 3270 return false; 3271 3272 // if wback && registers<n> == '1' then UNPREDICTABLE; 3273 if (wback 3274 && BitIsSet (registers, n)) 3275 return false; 3276 break; 3277 3278 case eEncodingA1: 3279 n = Bits32 (opcode, 19, 16); 3280 registers = Bits32 (opcode, 15, 0); 3281 wback = BitIsSet (opcode, 21); 3282 if ((n == 15) 3283 || (BitCount (registers) < 1)) 3284 return false; 3285 break; 3286 default: 3287 return false; 3288 } 3289 3290 int32_t offset = 0; 3291 const addr_t base_address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success); 3292 if (!success) 3293 return false; 3294 3295 EmulateInstruction::Context context; 3296 context.type = EmulateInstruction::eContextRegisterPlusOffset; 3297 Register dwarf_reg; 3298 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n); 3299 context.SetRegisterPlusOffset (dwarf_reg, offset); 3300 3301 for (int i = 0; i < 14; ++i) 3302 { 3303 if (BitIsSet (registers, i)) 3304 { 3305 context.type = EmulateInstruction::eContextRegisterPlusOffset; 3306 context.SetRegisterPlusOffset (dwarf_reg, offset); 3307 if (wback && (n == 13)) // Pop Instruction 3308 context.type = EmulateInstruction::eContextPopRegisterOffStack; 3309 3310 // R[i] = MemA [address, 4]; address = address + 4; 3311 uint32_t data = MemARead (context, base_address + offset, addr_byte_size, 0, &success); 3312 if (!success) 3313 return false; 3314 3315 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + i, data)) 3316 return false; 3317 3318 offset += addr_byte_size; 3319 } 3320 } 3321 3322 if (BitIsSet (registers, 15)) 3323 { 3324 //LoadWritePC (MemA [address, 4]); 3325 context.type = EmulateInstruction::eContextRegisterPlusOffset; 3326 context.SetRegisterPlusOffset (dwarf_reg, offset); 3327 uint32_t data = MemARead (context, base_address + offset, addr_byte_size, 0, &success); 3328 if (!success) 3329 return false; 3330 // In ARMv5T and above, this is an interworking branch. 3331 if (!LoadWritePC(context, data)) 3332 return false; 3333 } 3334 3335 if (wback && BitIsClear (registers, n)) 3336 { 3337 // R[n] = R[n] + 4 * BitCount (registers) 3338 int32_t offset = addr_byte_size * BitCount (registers); 3339 context.type = EmulateInstruction::eContextAdjustBaseRegister; 3340 context.SetRegisterPlusOffset (dwarf_reg, offset); 3341 3342 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, base_address + offset)) 3343 return false; 3344 } 3345 if (wback && BitIsSet (registers, n)) 3346 // R[n] bits(32) UNKNOWN; 3347 return WriteBits32Unknown (n); 3348 } 3349 return true; 3350} 3351 3352// LDMDA loads multiple registers from consecutive memory locations using an address from a base register. 3353// The consecutive memory locations end at this address and the address just below the lowest of those locations 3354// can optionally be written back to the base register. 3355bool 3356EmulateInstructionARM::EmulateLDMDA (const uint32_t opcode, const ARMEncoding encoding) 3357{ 3358#if 0 3359 // ARM pseudo code... 3360 if ConditionPassed() then 3361 EncodingSpecificOperations(); 3362 address = R[n] - 4*BitCount(registers) + 4; 3363 3364 for i = 0 to 14 3365 if registers<i> == '1' then 3366 R[i] = MemA[address,4]; address = address + 4; 3367 3368 if registers<15> == '1' then 3369 LoadWritePC(MemA[address,4]); 3370 3371 if wback && registers<n> == '0' then R[n] = R[n] - 4*BitCount(registers); 3372 if wback && registers<n> == '1' then R[n] = bits(32) UNKNOWN; 3373#endif 3374 3375 bool success = false; 3376 3377 if (ConditionPassed(opcode)) 3378 { 3379 uint32_t n; 3380 uint32_t registers = 0; 3381 bool wback; 3382 const uint32_t addr_byte_size = GetAddressByteSize(); 3383 3384 // EncodingSpecificOperations(); 3385 switch (encoding) 3386 { 3387 case eEncodingA1: 3388 // n = UInt(Rn); registers = register_list; wback = (W == '1'); 3389 n = Bits32 (opcode, 19, 16); 3390 registers = Bits32 (opcode, 15, 0); 3391 wback = BitIsSet (opcode, 21); 3392 3393 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE; 3394 if ((n == 15) || (BitCount (registers) < 1)) 3395 return false; 3396 3397 break; 3398 3399 default: 3400 return false; 3401 } 3402 // address = R[n] - 4*BitCount(registers) + 4; 3403 3404 int32_t offset = 0; 3405 addr_t Rn = ReadCoreReg (n, &success); 3406 3407 if (!success) 3408 return false; 3409 3410 addr_t address = Rn - (addr_byte_size * BitCount (registers)) + addr_byte_size; 3411 3412 EmulateInstruction::Context context; 3413 context.type = EmulateInstruction::eContextRegisterPlusOffset; 3414 Register dwarf_reg; 3415 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n); 3416 context.SetRegisterPlusOffset (dwarf_reg, offset); 3417 3418 // for i = 0 to 14 3419 for (int i = 0; i < 14; ++i) 3420 { 3421 // if registers<i> == '1' then 3422 if (BitIsSet (registers, i)) 3423 { 3424 // R[i] = MemA[address,4]; address = address + 4; 3425 context.SetRegisterPlusOffset (dwarf_reg, Rn - (address + offset)); 3426 uint32_t data = MemARead (context, address + offset, addr_byte_size, 0, &success); 3427 if (!success) 3428 return false; 3429 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + i, data)) 3430 return false; 3431 offset += addr_byte_size; 3432 } 3433 } 3434 3435 // if registers<15> == '1' then 3436 // LoadWritePC(MemA[address,4]); 3437 if (BitIsSet (registers, 15)) 3438 { 3439 context.SetRegisterPlusOffset (dwarf_reg, offset); 3440 uint32_t data = MemARead (context, address + offset, addr_byte_size, 0, &success); 3441 if (!success) 3442 return false; 3443 // In ARMv5T and above, this is an interworking branch. 3444 if (!LoadWritePC(context, data)) 3445 return false; 3446 } 3447 3448 // if wback && registers<n> == '0' then R[n] = R[n] - 4*BitCount(registers); 3449 if (wback && BitIsClear (registers, n)) 3450 { 3451 if (!success) 3452 return false; 3453 3454 offset = (addr_byte_size * BitCount (registers)) * -1; 3455 context.type = EmulateInstruction::eContextAdjustBaseRegister; 3456 context.SetImmediateSigned (offset); 3457 addr_t addr = Rn + offset; 3458 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, addr)) 3459 return false; 3460 } 3461 3462 // if wback && registers<n> == '1' then R[n] = bits(32) UNKNOWN; 3463 if (wback && BitIsSet (registers, n)) 3464 return WriteBits32Unknown (n); 3465 } 3466 return true; 3467} 3468 3469// LDMDB loads multiple registers from consecutive memory locations using an address from a base register. The 3470// consecutive memory lcoations end just below this address, and the address of the lowest of those locations can 3471// be optionally written back to the base register. 3472bool 3473EmulateInstructionARM::EmulateLDMDB (const uint32_t opcode, const ARMEncoding encoding) 3474{ 3475#if 0 3476 // ARM pseudo code... 3477 if ConditionPassed() then 3478 EncodingSpecificOperations(); NullCheckIfThumbEE(n); 3479 address = R[n] - 4*BitCount(registers); 3480 3481 for i = 0 to 14 3482 if registers<i> == '1' then 3483 R[i] = MemA[address,4]; address = address + 4; 3484 if registers<15> == '1' then 3485 LoadWritePC(MemA[address,4]); 3486 3487 if wback && registers<n> == '0' then R[n] = R[n] - 4*BitCount(registers); 3488 if wback && registers<n> == '1' then R[n] = bits(32) UNKNOWN; // Only possible for encoding A1 3489#endif 3490 3491 bool success = false; 3492 3493 if (ConditionPassed(opcode)) 3494 { 3495 uint32_t n; 3496 uint32_t registers = 0; 3497 bool wback; 3498 const uint32_t addr_byte_size = GetAddressByteSize(); 3499 switch (encoding) 3500 { 3501 case eEncodingT1: 3502 // n = UInt(Rn); registers = P:M:'0':register_list; wback = (W == '1'); 3503 n = Bits32 (opcode, 19, 16); 3504 registers = Bits32 (opcode, 15, 0); 3505 registers = registers & 0xdfff; // Make sure bit 13 is a zero. 3506 wback = BitIsSet (opcode, 21); 3507 3508 // if n == 15 || BitCount(registers) < 2 || (P == '1' && M == '1') then UNPREDICTABLE; 3509 if ((n == 15) 3510 || (BitCount (registers) < 2) 3511 || (BitIsSet (opcode, 14) && BitIsSet (opcode, 15))) 3512 return false; 3513 3514 // if registers<15> == '1' && InITBlock() && !LastInITBlock() then UNPREDICTABLE; 3515 if (BitIsSet (registers, 15) && InITBlock() && !LastInITBlock()) 3516 return false; 3517 3518 // if wback && registers<n> == '1' then UNPREDICTABLE; 3519 if (wback && BitIsSet (registers, n)) 3520 return false; 3521 3522 break; 3523 3524 case eEncodingA1: 3525 // n = UInt(Rn); registers = register_list; wback = (W == '1'); 3526 n = Bits32 (opcode, 19, 16); 3527 registers = Bits32 (opcode, 15, 0); 3528 wback = BitIsSet (opcode, 21); 3529 3530 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE; 3531 if ((n == 15) || (BitCount (registers) < 1)) 3532 return false; 3533 3534 break; 3535 3536 default: 3537 return false; 3538 } 3539 3540 // address = R[n] - 4*BitCount(registers); 3541 3542 int32_t offset = 0; 3543 addr_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success); 3544 3545 if (!success) 3546 return false; 3547 3548 addr_t address = Rn - (addr_byte_size * BitCount (registers)); 3549 EmulateInstruction::Context context; 3550 context.type = EmulateInstruction::eContextRegisterPlusOffset; 3551 Register dwarf_reg; 3552 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n); 3553 context.SetRegisterPlusOffset (dwarf_reg, Rn - address); 3554 3555 for (int i = 0; i < 14; ++i) 3556 { 3557 if (BitIsSet (registers, i)) 3558 { 3559 // R[i] = MemA[address,4]; address = address + 4; 3560 context.SetRegisterPlusOffset (dwarf_reg, Rn - (address + offset)); 3561 uint32_t data = MemARead (context, address + offset, addr_byte_size, 0, &success); 3562 if (!success) 3563 return false; 3564 3565 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + i, data)) 3566 return false; 3567 3568 offset += addr_byte_size; 3569 } 3570 } 3571 3572 // if registers<15> == '1' then 3573 // LoadWritePC(MemA[address,4]); 3574 if (BitIsSet (registers, 15)) 3575 { 3576 context.SetRegisterPlusOffset (dwarf_reg, offset); 3577 uint32_t data = MemARead (context, address + offset, addr_byte_size, 0, &success); 3578 if (!success) 3579 return false; 3580 // In ARMv5T and above, this is an interworking branch. 3581 if (!LoadWritePC(context, data)) 3582 return false; 3583 } 3584 3585 // if wback && registers<n> == '0' then R[n] = R[n] - 4*BitCount(registers); 3586 if (wback && BitIsClear (registers, n)) 3587 { 3588 if (!success) 3589 return false; 3590 3591 offset = (addr_byte_size * BitCount (registers)) * -1; 3592 context.type = EmulateInstruction::eContextAdjustBaseRegister; 3593 context.SetImmediateSigned (offset); 3594 addr_t addr = Rn + offset; 3595 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, addr)) 3596 return false; 3597 } 3598 3599 // if wback && registers<n> == '1' then R[n] = bits(32) UNKNOWN; // Only possible for encoding A1 3600 if (wback && BitIsSet (registers, n)) 3601 return WriteBits32Unknown (n); 3602 } 3603 return true; 3604} 3605 3606// LDMIB loads multiple registers from consecutive memory locations using an address from a base register. The 3607// consecutive memory locations start just above this address, and thea ddress of the last of those locations can 3608// optinoally be written back to the base register. 3609bool 3610EmulateInstructionARM::EmulateLDMIB (const uint32_t opcode, const ARMEncoding encoding) 3611{ 3612#if 0 3613 if ConditionPassed() then 3614 EncodingSpecificOperations(); 3615 address = R[n] + 4; 3616 3617 for i = 0 to 14 3618 if registers<i> == '1' then 3619 R[i] = MemA[address,4]; address = address + 4; 3620 if registers<15> == '1' then 3621 LoadWritePC(MemA[address,4]); 3622 3623 if wback && registers<n> == '0' then R[n] = R[n] + 4*BitCount(registers); 3624 if wback && registers<n> == '1' then R[n] = bits(32) UNKNOWN; 3625#endif 3626 3627 bool success = false; 3628 3629 if (ConditionPassed(opcode)) 3630 { 3631 uint32_t n; 3632 uint32_t registers = 0; 3633 bool wback; 3634 const uint32_t addr_byte_size = GetAddressByteSize(); 3635 switch (encoding) 3636 { 3637 case eEncodingA1: 3638 // n = UInt(Rn); registers = register_list; wback = (W == '1'); 3639 n = Bits32 (opcode, 19, 16); 3640 registers = Bits32 (opcode, 15, 0); 3641 wback = BitIsSet (opcode, 21); 3642 3643 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE; 3644 if ((n == 15) || (BitCount (registers) < 1)) 3645 return false; 3646 3647 break; 3648 default: 3649 return false; 3650 } 3651 // address = R[n] + 4; 3652 3653 int32_t offset = 0; 3654 addr_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success); 3655 3656 if (!success) 3657 return false; 3658 3659 addr_t address = Rn + addr_byte_size; 3660 3661 EmulateInstruction::Context context; 3662 context.type = EmulateInstruction::eContextRegisterPlusOffset; 3663 Register dwarf_reg; 3664 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n); 3665 context.SetRegisterPlusOffset (dwarf_reg, offset); 3666 3667 for (int i = 0; i < 14; ++i) 3668 { 3669 if (BitIsSet (registers, i)) 3670 { 3671 // R[i] = MemA[address,4]; address = address + 4; 3672 3673 context.SetRegisterPlusOffset (dwarf_reg, offset + addr_byte_size); 3674 uint32_t data = MemARead (context, address + offset, addr_byte_size, 0, &success); 3675 if (!success) 3676 return false; 3677 3678 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + i, data)) 3679 return false; 3680 3681 offset += addr_byte_size; 3682 } 3683 } 3684 3685 // if registers<15> == '1' then 3686 // LoadWritePC(MemA[address,4]); 3687 if (BitIsSet (registers, 15)) 3688 { 3689 context.SetRegisterPlusOffset (dwarf_reg, offset); 3690 uint32_t data = MemARead (context, address + offset, addr_byte_size, 0, &success); 3691 if (!success) 3692 return false; 3693 // In ARMv5T and above, this is an interworking branch. 3694 if (!LoadWritePC(context, data)) 3695 return false; 3696 } 3697 3698 // if wback && registers<n> == '0' then R[n] = R[n] + 4*BitCount(registers); 3699 if (wback && BitIsClear (registers, n)) 3700 { 3701 if (!success) 3702 return false; 3703 3704 offset = addr_byte_size * BitCount (registers); 3705 context.type = EmulateInstruction::eContextAdjustBaseRegister; 3706 context.SetImmediateSigned (offset); 3707 addr_t addr = Rn + offset; 3708 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, addr)) 3709 return false; 3710 } 3711 3712 // if wback && registers<n> == '1' then R[n] = bits(32) UNKNOWN; // Only possible for encoding A1 3713 if (wback && BitIsSet (registers, n)) 3714 return WriteBits32Unknown (n); 3715 } 3716 return true; 3717} 3718 3719// Load Register (immediate) calculates an address from a base register value and 3720// an immediate offset, loads a word from memory, and writes to a register. 3721// LDR (immediate, Thumb) 3722bool 3723EmulateInstructionARM::EmulateLDRRtRnImm (const uint32_t opcode, const ARMEncoding encoding) 3724{ 3725#if 0 3726 // ARM pseudo code... 3727 if (ConditionPassed()) 3728 { 3729 EncodingSpecificOperations(); NullCheckIfThumbEE(15); 3730 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32); 3731 address = if index then offset_addr else R[n]; 3732 data = MemU[address,4]; 3733 if wback then R[n] = offset_addr; 3734 if t == 15 then 3735 if address<1:0> == '00' then LoadWritePC(data); else UNPREDICTABLE; 3736 elsif UnalignedSupport() || address<1:0> = '00' then 3737 R[t] = data; 3738 else R[t] = bits(32) UNKNOWN; // Can only apply before ARMv7 3739 } 3740#endif 3741 3742 bool success = false; 3743 3744 if (ConditionPassed(opcode)) 3745 { 3746 uint32_t Rt; // the destination register 3747 uint32_t Rn; // the base register 3748 uint32_t imm32; // the immediate offset used to form the address 3749 addr_t offset_addr; // the offset address 3750 addr_t address; // the calculated address 3751 uint32_t data; // the literal data value from memory load 3752 bool add, index, wback; 3753 switch (encoding) { 3754 case eEncodingT1: 3755 Rt = Bits32(opcode, 2, 0); 3756 Rn = Bits32(opcode, 5, 3); 3757 imm32 = Bits32(opcode, 10, 6) << 2; // imm32 = ZeroExtend(imm5:'00', 32); 3758 // index = TRUE; add = TRUE; wback = FALSE 3759 add = true; 3760 index = true; 3761 wback = false; 3762 3763 break; 3764 3765 case eEncodingT2: 3766 // t = UInt(Rt); n = 13; imm32 = ZeroExtend(imm8:'00', 32); 3767 Rt = Bits32 (opcode, 10, 8); 3768 Rn = 13; 3769 imm32 = Bits32 (opcode, 7, 0) << 2; 3770 3771 // index = TRUE; add = TRUE; wback = FALSE; 3772 index = true; 3773 add = true; 3774 wback = false; 3775 3776 break; 3777 3778 case eEncodingT3: 3779 // if Rn == '1111' then SEE LDR (literal); 3780 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32); 3781 Rt = Bits32 (opcode, 15, 12); 3782 Rn = Bits32 (opcode, 19, 16); 3783 imm32 = Bits32 (opcode, 11, 0); 3784 3785 // index = TRUE; add = TRUE; wback = FALSE; 3786 index = true; 3787 add = true; 3788 wback = false; 3789 3790 // if t == 15 && InITBlock() && !LastInITBlock() then UNPREDICTABLE; 3791 if ((Rt == 15) && InITBlock() && !LastInITBlock()) 3792 return false; 3793 3794 break; 3795 3796 case eEncodingT4: 3797 // if Rn == '1111' then SEE LDR (literal); 3798 // if P == '1' && U == '1' && W == '0' then SEE LDRT; 3799 // if Rn == '1101' && P == '0' && U == '1' && W == '1' && imm8 == '00000100' then SEE POP; 3800 // if P == '0' && W == '0' then UNDEFINED; 3801 if (BitIsClear (opcode, 10) && BitIsClear (opcode, 8)) 3802 return false; 3803 3804 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32); 3805 Rt = Bits32 (opcode, 15, 12); 3806 Rn = Bits32 (opcode, 19, 16); 3807 imm32 = Bits32 (opcode, 7, 0); 3808 3809 // index = (P == '1'); add = (U == '1'); wback = (W == '1'); 3810 index = BitIsSet (opcode, 10); 3811 add = BitIsSet (opcode, 9); 3812 wback = BitIsSet (opcode, 8); 3813 3814 // if (wback && n == t) || (t == 15 && InITBlock() && !LastInITBlock()) then UNPREDICTABLE; 3815 if ((wback && (Rn == Rt)) || ((Rt == 15) && InITBlock() && !LastInITBlock())) 3816 return false; 3817 3818 break; 3819 3820 default: 3821 return false; 3822 } 3823 uint32_t base = ReadCoreReg (Rn, &success); 3824 if (!success) 3825 return false; 3826 if (add) 3827 offset_addr = base + imm32; 3828 else 3829 offset_addr = base - imm32; 3830 3831 address = (index ? offset_addr : base); 3832 3833 Register base_reg; 3834 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + Rn); 3835 if (wback) 3836 { 3837 EmulateInstruction::Context ctx; 3838 ctx.type = EmulateInstruction::eContextAdjustBaseRegister; 3839 ctx.SetRegisterPlusOffset (base_reg, (int32_t) (offset_addr - base)); 3840 3841 if (!WriteRegisterUnsigned (ctx, eRegisterKindDWARF, dwarf_r0 + Rn, offset_addr)) 3842 return false; 3843 } 3844 3845 // Prepare to write to the Rt register. 3846 EmulateInstruction::Context context; 3847 context.type = EmulateInstruction::eContextRegisterLoad; 3848 context.SetRegisterPlusOffset (base_reg, (int32_t) (offset_addr - base)); 3849 3850 // Read memory from the address. 3851 data = MemURead(context, address, 4, 0, &success); 3852 if (!success) 3853 return false; 3854 3855 if (Rt == 15) 3856 { 3857 if (Bits32(address, 1, 0) == 0) 3858 { 3859 if (!LoadWritePC(context, data)) 3860 return false; 3861 } 3862 else 3863 return false; 3864 } 3865 else if (UnalignedSupport() || Bits32(address, 1, 0) == 0) 3866 { 3867 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + Rt, data)) 3868 return false; 3869 } 3870 else 3871 WriteBits32Unknown (Rt); 3872 } 3873 return true; 3874} 3875 3876// STM (Store Multiple Increment After) stores multiple registers to consecutive memory locations using an address 3877// from a base register. The consecutive memory locations start at this address, and teh address just above the last 3878// of those locations can optionally be written back to the base register. 3879bool 3880EmulateInstructionARM::EmulateSTM (const uint32_t opcode, const ARMEncoding encoding) 3881{ 3882#if 0 3883 if ConditionPassed() then 3884 EncodingSpecificOperations(); NullCheckIfThumbEE(n); 3885 address = R[n]; 3886 3887 for i = 0 to 14 3888 if registers<i> == '1' then 3889 if i == n && wback && i != LowestSetBit(registers) then 3890 MemA[address,4] = bits(32) UNKNOWN; // Only possible for encodings T1 and A1 3891 else 3892 MemA[address,4] = R[i]; 3893 address = address + 4; 3894 3895 if registers<15> == '1' then // Only possible for encoding A1 3896 MemA[address,4] = PCStoreValue(); 3897 if wback then R[n] = R[n] + 4*BitCount(registers); 3898#endif 3899 3900 bool success = false; 3901 3902 if (ConditionPassed(opcode)) 3903 { 3904 uint32_t n; 3905 uint32_t registers = 0; 3906 bool wback; 3907 const uint32_t addr_byte_size = GetAddressByteSize(); 3908 3909 // EncodingSpecificOperations(); NullCheckIfThumbEE(n); 3910 switch (encoding) 3911 { 3912 case eEncodingT1: 3913 // n = UInt(Rn); registers = '00000000':register_list; wback = TRUE; 3914 n = Bits32 (opcode, 10, 8); 3915 registers = Bits32 (opcode, 7, 0); 3916 registers = registers & 0x00ff; // Make sure the top 8 bits are zeros. 3917 wback = true; 3918 3919 // if BitCount(registers) < 1 then UNPREDICTABLE; 3920 if (BitCount (registers) < 1) 3921 return false; 3922 3923 break; 3924 3925 case eEncodingT2: 3926 // n = UInt(Rn); registers = '0':M:'0':register_list; wback = (W == '1'); 3927 n = Bits32 (opcode, 19, 16); 3928 registers = Bits32 (opcode, 15, 0); 3929 registers = registers & 0x5fff; // Make sure bits 15 & 13 are zeros. 3930 wback = BitIsSet (opcode, 21); 3931 3932 // if n == 15 || BitCount(registers) < 2 then UNPREDICTABLE; 3933 if ((n == 15) || (BitCount (registers) < 2)) 3934 return false; 3935 3936 // if wback && registers<n> == '1' then UNPREDICTABLE; 3937 if (wback && BitIsSet (registers, n)) 3938 return false; 3939 3940 break; 3941 3942 case eEncodingA1: 3943 // n = UInt(Rn); registers = register_list; wback = (W == '1'); 3944 n = Bits32 (opcode, 19, 16); 3945 registers = Bits32 (opcode, 15, 0); 3946 wback = BitIsSet (opcode, 21); 3947 3948 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE; 3949 if ((n == 15) || (BitCount (registers) < 1)) 3950 return false; 3951 3952 break; 3953 3954 default: 3955 return false; 3956 } 3957 3958 // address = R[n]; 3959 int32_t offset = 0; 3960 const addr_t address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success); 3961 if (!success) 3962 return false; 3963 3964 EmulateInstruction::Context context; 3965 context.type = EmulateInstruction::eContextRegisterStore; 3966 Register base_reg; 3967 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n); 3968 3969 // for i = 0 to 14 3970 int lowest_set_bit = 14; 3971 for (int i = 0; i < 14; ++i) 3972 { 3973 // if registers<i> == '1' then 3974 if (BitIsSet (registers, i)) 3975 { 3976 if (i < lowest_set_bit) 3977 lowest_set_bit = i; 3978 // if i == n && wback && i != LowestSetBit(registers) then 3979 if ((i == n) && wback && (i != lowest_set_bit)) 3980 // MemA[address,4] = bits(32) UNKNOWN; // Only possible for encodings T1 and A1 3981 WriteBits32UnknownToMemory (address + offset); 3982 else 3983 { 3984 // MemA[address,4] = R[i]; 3985 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + i, 0, &success); 3986 if (!success) 3987 return false; 3988 3989 Register data_reg; 3990 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + i); 3991 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, offset); 3992 if (!MemAWrite (context, address + offset, data, addr_byte_size)) 3993 return false; 3994 } 3995 3996 // address = address + 4; 3997 offset += addr_byte_size; 3998 } 3999 } 4000 4001 // if registers<15> == '1' then // Only possible for encoding A1 4002 // MemA[address,4] = PCStoreValue(); 4003 if (BitIsSet (registers, 15)) 4004 { 4005 Register pc_reg; 4006 pc_reg.SetRegister (eRegisterKindDWARF, dwarf_pc); 4007 context.SetRegisterPlusOffset (pc_reg, 8); 4008 const uint32_t pc = ReadCoreReg (PC_REG, &success); 4009 if (!success) 4010 return false; 4011 4012 if (!MemAWrite (context, address + offset, pc, addr_byte_size)) 4013 return false; 4014 } 4015 4016 // if wback then R[n] = R[n] + 4*BitCount(registers); 4017 if (wback) 4018 { 4019 offset = addr_byte_size * BitCount (registers); 4020 context.type = EmulateInstruction::eContextAdjustBaseRegister; 4021 context.SetImmediateSigned (offset); 4022 addr_t data = address + offset; 4023 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, data)) 4024 return false; 4025 } 4026 } 4027 return true; 4028} 4029 4030// STMDA (Store Multiple Decrement After) stores multiple registers to consecutive memory locations using an address 4031// from a base register. The consecutive memory locations end at this address, and the address just below the lowest 4032// of those locations can optionally be written back to the base register. 4033bool 4034EmulateInstructionARM::EmulateSTMDA (const uint32_t opcode, const ARMEncoding encoding) 4035{ 4036#if 0 4037 if ConditionPassed() then 4038 EncodingSpecificOperations(); 4039 address = R[n] - 4*BitCount(registers) + 4; 4040 4041 for i = 0 to 14 4042 if registers<i> == '1' then 4043 if i == n && wback && i != LowestSetBit(registers) then 4044 MemA[address,4] = bits(32) UNKNOWN; 4045 else 4046 MemA[address,4] = R[i]; 4047 address = address + 4; 4048 4049 if registers<15> == '1' then 4050 MemA[address,4] = PCStoreValue(); 4051 4052 if wback then R[n] = R[n] - 4*BitCount(registers); 4053#endif 4054 4055 bool success = false; 4056 4057 if (ConditionPassed(opcode)) 4058 { 4059 uint32_t n; 4060 uint32_t registers = 0; 4061 bool wback; 4062 const uint32_t addr_byte_size = GetAddressByteSize(); 4063 4064 // EncodingSpecificOperations(); 4065 switch (encoding) 4066 { 4067 case eEncodingA1: 4068 // n = UInt(Rn); registers = register_list; wback = (W == '1'); 4069 n = Bits32 (opcode, 19, 16); 4070 registers = Bits32 (opcode, 15, 0); 4071 wback = BitIsSet (opcode, 21); 4072 4073 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE; 4074 if ((n == 15) || (BitCount (registers) < 1)) 4075 return false; 4076 break; 4077 default: 4078 return false; 4079 } 4080 4081 // address = R[n] - 4*BitCount(registers) + 4; 4082 int32_t offset = 0; 4083 addr_t Rn = ReadCoreReg (n, &success); 4084 if (!success) 4085 return false; 4086 4087 addr_t address = Rn - (addr_byte_size * BitCount (registers)) + 4; 4088 4089 EmulateInstruction::Context context; 4090 context.type = EmulateInstruction::eContextRegisterStore; 4091 Register base_reg; 4092 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n); 4093 4094 // for i = 0 to 14 4095 int lowest_bit_set = 14; 4096 for (int i = 0; i < 14; ++i) 4097 { 4098 // if registers<i> == '1' then 4099 if (BitIsSet (registers, i)) 4100 { 4101 if (i < lowest_bit_set) 4102 lowest_bit_set = i; 4103 //if i == n && wback && i != LowestSetBit(registers) then 4104 if ((i == n) && wback && (i != lowest_bit_set)) 4105 // MemA[address,4] = bits(32) UNKNOWN; 4106 WriteBits32UnknownToMemory (address + offset); 4107 else 4108 { 4109 // MemA[address,4] = R[i]; 4110 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + i, 0, &success); 4111 if (!success) 4112 return false; 4113 4114 Register data_reg; 4115 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + i); 4116 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, Rn - (address + offset)); 4117 if (!MemAWrite (context, address + offset, data, addr_byte_size)) 4118 return false; 4119 } 4120 4121 // address = address + 4; 4122 offset += addr_byte_size; 4123 } 4124 } 4125 4126 // if registers<15> == '1' then 4127 // MemA[address,4] = PCStoreValue(); 4128 if (BitIsSet (registers, 15)) 4129 { 4130 Register pc_reg; 4131 pc_reg.SetRegister (eRegisterKindDWARF, dwarf_pc); 4132 context.SetRegisterPlusOffset (pc_reg, 8); 4133 const uint32_t pc = ReadCoreReg (PC_REG, &success); 4134 if (!success) 4135 return false; 4136 4137 if (!MemAWrite (context, address + offset, pc, addr_byte_size)) 4138 return false; 4139 } 4140 4141 // if wback then R[n] = R[n] - 4*BitCount(registers); 4142 if (wback) 4143 { 4144 offset = (addr_byte_size * BitCount (registers)) * -1; 4145 context.type = EmulateInstruction::eContextAdjustBaseRegister; 4146 context.SetImmediateSigned (offset); 4147 addr_t data = Rn + offset; 4148 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, data)) 4149 return false; 4150 } 4151 } 4152 return true; 4153} 4154 4155// STMDB (Store Multiple Decrement Before) stores multiple registers to consecutive memory locations using an address 4156// from a base register. The consecutive memory locations end just below this address, and the address of the first of 4157// those locations can optionally be written back to the base register. 4158bool 4159EmulateInstructionARM::EmulateSTMDB (const uint32_t opcode, const ARMEncoding encoding) 4160{ 4161#if 0 4162 if ConditionPassed() then 4163 EncodingSpecificOperations(); NullCheckIfThumbEE(n); 4164 address = R[n] - 4*BitCount(registers); 4165 4166 for i = 0 to 14 4167 if registers<i> == '1' then 4168 if i == n && wback && i != LowestSetBit(registers) then 4169 MemA[address,4] = bits(32) UNKNOWN; // Only possible for encoding A1 4170 else 4171 MemA[address,4] = R[i]; 4172 address = address + 4; 4173 4174 if registers<15> == '1' then // Only possible for encoding A1 4175 MemA[address,4] = PCStoreValue(); 4176 4177 if wback then R[n] = R[n] - 4*BitCount(registers); 4178#endif 4179 4180 4181 bool success = false; 4182 4183 if (ConditionPassed(opcode)) 4184 { 4185 uint32_t n; 4186 uint32_t registers = 0; 4187 bool wback; 4188 const uint32_t addr_byte_size = GetAddressByteSize(); 4189 4190 // EncodingSpecificOperations(); NullCheckIfThumbEE(n); 4191 switch (encoding) 4192 { 4193 case eEncodingT1: 4194 // if W == '1' && Rn == '1101' then SEE PUSH; 4195 if ((BitIsSet (opcode, 21)) && (Bits32 (opcode, 19, 16) == 13)) 4196 { 4197 // See PUSH 4198 } 4199 // n = UInt(Rn); registers = '0':M:'0':register_list; wback = (W == '1'); 4200 n = Bits32 (opcode, 19, 16); 4201 registers = Bits32 (opcode, 15, 0); 4202 registers = registers & 0x5fff; // Make sure bits 15 & 13 are zeros. 4203 wback = BitIsSet (opcode, 21); 4204 // if n == 15 || BitCount(registers) < 2 then UNPREDICTABLE; 4205 if ((n == 15) || BitCount (registers) < 2) 4206 return false; 4207 // if wback && registers<n> == '1' then UNPREDICTABLE; 4208 if (wback && BitIsSet (registers, n)) 4209 return false; 4210 break; 4211 4212 case eEncodingA1: 4213 // if W == '1' && Rn == '1101’ && BitCount(register_list) >= 2 then SEE PUSH; 4214 if (BitIsSet (opcode, 21) && (Bits32 (opcode, 19, 16) == 13) && BitCount (Bits32 (opcode, 15, 0)) >= 2) 4215 { 4216 // See Push 4217 } 4218 // n = UInt(Rn); registers = register_list; wback = (W == '1'); 4219 n = Bits32 (opcode, 19, 16); 4220 registers = Bits32 (opcode, 15, 0); 4221 wback = BitIsSet (opcode, 21); 4222 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE; 4223 if ((n == 15) || BitCount (registers) < 1) 4224 return false; 4225 break; 4226 4227 default: 4228 return false; 4229 } 4230 4231 // address = R[n] - 4*BitCount(registers); 4232 4233 int32_t offset = 0; 4234 addr_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success); 4235 if (!success) 4236 return false; 4237 4238 addr_t address = Rn - (addr_byte_size * BitCount (registers)); 4239 4240 EmulateInstruction::Context context; 4241 context.type = EmulateInstruction::eContextRegisterStore; 4242 Register base_reg; 4243 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n); 4244 4245 // for i = 0 to 14 4246 uint32_t lowest_set_bit = 14; 4247 for (int i = 0; i < 14; ++i) 4248 { 4249 // if registers<i> == '1' then 4250 if (BitIsSet (registers, i)) 4251 { 4252 if (i < lowest_set_bit) 4253 lowest_set_bit = i; 4254 // if i == n && wback && i != LowestSetBit(registers) then 4255 if ((i == n) && wback && (i != lowest_set_bit)) 4256 // MemA[address,4] = bits(32) UNKNOWN; // Only possible for encoding A1 4257 WriteBits32UnknownToMemory (address + offset); 4258 else 4259 { 4260 // MemA[address,4] = R[i]; 4261 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + i, 0, &success); 4262 if (!success) 4263 return false; 4264 4265 Register data_reg; 4266 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + i); 4267 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, Rn - (address + offset)); 4268 if (!MemAWrite (context, address + offset, data, addr_byte_size)) 4269 return false; 4270 } 4271 4272 // address = address + 4; 4273 offset += addr_byte_size; 4274 } 4275 } 4276 4277 // if registers<15> == '1' then // Only possible for encoding A1 4278 // MemA[address,4] = PCStoreValue(); 4279 if (BitIsSet (registers, 15)) 4280 { 4281 Register pc_reg; 4282 pc_reg.SetRegister (eRegisterKindDWARF, dwarf_pc); 4283 context.SetRegisterPlusOffset (pc_reg, 8); 4284 const uint32_t pc = ReadCoreReg (PC_REG, &success); 4285 if (!success) 4286 return false; 4287 4288 if (!MemAWrite (context, address + offset, pc, addr_byte_size)) 4289 return false; 4290 } 4291 4292 // if wback then R[n] = R[n] - 4*BitCount(registers); 4293 if (wback) 4294 { 4295 offset = (addr_byte_size * BitCount (registers)) * -1; 4296 context.type = EmulateInstruction::eContextAdjustBaseRegister; 4297 context.SetImmediateSigned (offset); 4298 addr_t data = Rn + offset; 4299 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, data)) 4300 return false; 4301 } 4302 } 4303 return true; 4304} 4305 4306// STMIB (Store Multiple Increment Before) stores multiple registers to consecutive memory locations using an address 4307// from a base register. The consecutive memory locations start just above this address, and the address of the last 4308// of those locations can optionally be written back to the base register. 4309bool 4310EmulateInstructionARM::EmulateSTMIB (const uint32_t opcode, const ARMEncoding encoding) 4311{ 4312#if 0 4313 if ConditionPassed() then 4314 EncodingSpecificOperations(); 4315 address = R[n] + 4; 4316 4317 for i = 0 to 14 4318 if registers<i> == '1' then 4319 if i == n && wback && i != LowestSetBit(registers) then 4320 MemA[address,4] = bits(32) UNKNOWN; 4321 else 4322 MemA[address,4] = R[i]; 4323 address = address + 4; 4324 4325 if registers<15> == '1' then 4326 MemA[address,4] = PCStoreValue(); 4327 4328 if wback then R[n] = R[n] + 4*BitCount(registers); 4329#endif 4330 4331 bool success = false; 4332 4333 if (ConditionPassed(opcode)) 4334 { 4335 uint32_t n; 4336 uint32_t registers = 0; 4337 bool wback; 4338 const uint32_t addr_byte_size = GetAddressByteSize(); 4339 4340 // EncodingSpecificOperations(); 4341 switch (encoding) 4342 { 4343 case eEncodingA1: 4344 // n = UInt(Rn); registers = register_list; wback = (W == '1'); 4345 n = Bits32 (opcode, 19, 16); 4346 registers = Bits32 (opcode, 15, 0); 4347 wback = BitIsSet (opcode, 21); 4348 4349 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE; 4350 if ((n == 15) && (BitCount (registers) < 1)) 4351 return false; 4352 break; 4353 default: 4354 return false; 4355 } 4356 // address = R[n] + 4; 4357 4358 int32_t offset = 0; 4359 addr_t Rn = ReadCoreReg (n, &success); 4360 if (!success) 4361 return false; 4362 4363 addr_t address = Rn + addr_byte_size; 4364 4365 EmulateInstruction::Context context; 4366 context.type = EmulateInstruction::eContextRegisterStore; 4367 Register base_reg; 4368 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n); 4369 4370 uint32_t lowest_set_bit = 14; 4371 // for i = 0 to 14 4372 for (int i = 0; i < 14; ++i) 4373 { 4374 // if registers<i> == '1' then 4375 if (BitIsSet (registers, i)) 4376 { 4377 if (i < lowest_set_bit) 4378 lowest_set_bit = i; 4379 // if i == n && wback && i != LowestSetBit(registers) then 4380 if ((i == n) && wback && (i != lowest_set_bit)) 4381 // MemA[address,4] = bits(32) UNKNOWN; 4382 WriteBits32UnknownToMemory (address + offset); 4383 // else 4384 else 4385 { 4386 // MemA[address,4] = R[i]; 4387 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + i, 0, &success); 4388 if (!success) 4389 return false; 4390 4391 Register data_reg; 4392 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + i); 4393 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, offset + addr_byte_size); 4394 if (!MemAWrite (context, address + offset, data, addr_byte_size)) 4395 return false; 4396 } 4397 4398 // address = address + 4; 4399 offset += addr_byte_size; 4400 } 4401 } 4402 4403 // if registers<15> == '1' then 4404 // MemA[address,4] = PCStoreValue(); 4405 if (BitIsSet (registers, 15)) 4406 { 4407 Register pc_reg; 4408 pc_reg.SetRegister (eRegisterKindDWARF, dwarf_pc); 4409 context.SetRegisterPlusOffset (pc_reg, 8); 4410 const uint32_t pc = ReadCoreReg (PC_REG, &success); 4411 if (!success) 4412 return false; 4413 4414 if (!MemAWrite (context, address + offset, pc, addr_byte_size)) 4415 return false; 4416 } 4417 4418 // if wback then R[n] = R[n] + 4*BitCount(registers); 4419 if (wback) 4420 { 4421 offset = addr_byte_size * BitCount (registers); 4422 context.type = EmulateInstruction::eContextAdjustBaseRegister; 4423 context.SetImmediateSigned (offset); 4424 addr_t data = Rn + offset; 4425 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, data)) 4426 return false; 4427 } 4428 } 4429 return true; 4430} 4431 4432// STR (store immediate) calcualtes an address from a base register value and an immediate offset, and stores a word 4433// from a register to memory. It can use offset, post-indexed, or pre-indexed addressing. 4434bool 4435EmulateInstructionARM::EmulateSTRThumb (const uint32_t opcode, const ARMEncoding encoding) 4436{ 4437#if 0 4438 if ConditionPassed() then 4439 EncodingSpecificOperations(); NullCheckIfThumbEE(n); 4440 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32); 4441 address = if index then offset_addr else R[n]; 4442 if UnalignedSupport() || address<1:0> == '00' then 4443 MemU[address,4] = R[t]; 4444 else // Can only occur before ARMv7 4445 MemU[address,4] = bits(32) UNKNOWN; 4446 if wback then R[n] = offset_addr; 4447#endif 4448 4449 bool success = false; 4450 4451 if (ConditionPassed(opcode)) 4452 { 4453 const uint32_t addr_byte_size = GetAddressByteSize(); 4454 4455 uint32_t t; 4456 uint32_t n; 4457 uint32_t imm32; 4458 bool index; 4459 bool add; 4460 bool wback; 4461 // EncodingSpecificOperations (); NullCheckIfThumbEE(n); 4462 switch (encoding) 4463 { 4464 case eEncodingT1: 4465 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm5:'00', 32); 4466 t = Bits32 (opcode, 2, 0); 4467 n = Bits32 (opcode, 5, 3); 4468 imm32 = Bits32 (opcode, 10, 6) << 2; 4469 4470 // index = TRUE; add = TRUE; wback = FALSE; 4471 index = true; 4472 add = false; 4473 wback = false; 4474 break; 4475 4476 case eEncodingT2: 4477 // t = UInt(Rt); n = 13; imm32 = ZeroExtend(imm8:'00', 32); 4478 t = Bits32 (opcode, 10, 8); 4479 n = 13; 4480 imm32 = Bits32 (opcode, 7, 0) << 2; 4481 4482 // index = TRUE; add = TRUE; wback = FALSE; 4483 index = true; 4484 add = true; 4485 wback = false; 4486 break; 4487 4488 case eEncodingT3: 4489 // if Rn == '1111' then UNDEFINED; 4490 if (Bits32 (opcode, 19, 16) == 15) 4491 return false; 4492 4493 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32); 4494 t = Bits32 (opcode, 15, 12); 4495 n = Bits32 (opcode, 19, 16); 4496 imm32 = Bits32 (opcode, 11, 0); 4497 4498 // index = TRUE; add = TRUE; wback = FALSE; 4499 index = true; 4500 add = true; 4501 wback = false; 4502 4503 // if t == 15 then UNPREDICTABLE; 4504 if (t == 15) 4505 return false; 4506 break; 4507 4508 case eEncodingT4: 4509 // if P == '1' && U == '1' && W == '0' then SEE STRT; 4510 // if Rn == '1101' && P == '1' && U == '0' && W == '1' && imm8 == '00000100' then SEE PUSH; 4511 // if Rn == '1111' || (P == '0' && W == '0') then UNDEFINED; 4512 if ((Bits32 (opcode, 19, 16) == 15) 4513 || (BitIsClear (opcode, 10) && BitIsClear (opcode, 8))) 4514 return false; 4515 4516 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32); 4517 t = Bits32 (opcode, 15, 12); 4518 n = Bits32 (opcode, 19, 16); 4519 imm32 = Bits32 (opcode, 7, 0); 4520 4521 // index = (P == '1'); add = (U == '1'); wback = (W == '1'); 4522 index = BitIsSet (opcode, 10); 4523 add = BitIsSet (opcode, 9); 4524 wback = BitIsSet (opcode, 8); 4525 4526 // if t == 15 || (wback && n == t) then UNPREDICTABLE; 4527 if ((t == 15) || (wback && (n == t))) 4528 return false; 4529 break; 4530 4531 default: 4532 return false; 4533 } 4534 4535 addr_t offset_addr; 4536 addr_t address; 4537 4538 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32); 4539 uint32_t base_address = ReadCoreReg (n, &success); 4540 if (!success) 4541 return false; 4542 4543 if (add) 4544 offset_addr = base_address + imm32; 4545 else 4546 offset_addr = base_address - imm32; 4547 4548 // address = if index then offset_addr else R[n]; 4549 if (index) 4550 address = offset_addr; 4551 else 4552 address = base_address; 4553 4554 EmulateInstruction::Context context; 4555 context.type = eContextRegisterStore; 4556 Register base_reg; 4557 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n); 4558 4559 // if UnalignedSupport() || address<1:0> == '00' then 4560 if (UnalignedSupport () || (BitIsClear (address, 1) && BitIsClear (address, 0))) 4561 { 4562 // MemU[address,4] = R[t]; 4563 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + t, 0, &success); 4564 if (!success) 4565 return false; 4566 4567 Register data_reg; 4568 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + t); 4569 int32_t offset = address - base_address; 4570 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, offset); 4571 if (!MemUWrite (context, address, data, addr_byte_size)) 4572 return false; 4573 } 4574 else 4575 { 4576 // MemU[address,4] = bits(32) UNKNOWN; 4577 WriteBits32UnknownToMemory (address); 4578 } 4579 4580 // if wback then R[n] = offset_addr; 4581 if (wback) 4582 { 4583 context.type = eContextRegisterLoad; 4584 context.SetAddress (offset_addr); 4585 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr)) 4586 return false; 4587 } 4588 } 4589 return true; 4590} 4591 4592// STR (Store Register) calculates an address from a base register value and an offset register value, stores a 4593// word from a register to memory. The offset register value can optionally be shifted. 4594bool 4595EmulateInstructionARM::EmulateSTRRegister (const uint32_t opcode, const ARMEncoding encoding) 4596{ 4597#if 0 4598 if ConditionPassed() then 4599 EncodingSpecificOperations(); NullCheckIfThumbEE(n); 4600 offset = Shift(R[m], shift_t, shift_n, APSR.C); 4601 offset_addr = if add then (R[n] + offset) else (R[n] - offset); 4602 address = if index then offset_addr else R[n]; 4603 if t == 15 then // Only possible for encoding A1 4604 data = PCStoreValue(); 4605 else 4606 data = R[t]; 4607 if UnalignedSupport() || address<1:0> == '00' || CurrentInstrSet() == InstrSet_ARM then 4608 MemU[address,4] = data; 4609 else // Can only occur before ARMv7 4610 MemU[address,4] = bits(32) UNKNOWN; 4611 if wback then R[n] = offset_addr; 4612#endif 4613 4614 bool success = false; 4615 4616 if (ConditionPassed(opcode)) 4617 { 4618 const uint32_t addr_byte_size = GetAddressByteSize(); 4619 4620 uint32_t t; 4621 uint32_t n; 4622 uint32_t m; 4623 ARM_ShifterType shift_t; 4624 uint32_t shift_n; 4625 bool index; 4626 bool add; 4627 bool wback; 4628 4629 // EncodingSpecificOperations (); NullCheckIfThumbEE(n); 4630 switch (encoding) 4631 { 4632 case eEncodingT1: 4633 // if CurrentInstrSet() == InstrSet_ThumbEE then SEE "Modified operation in ThumbEE"; 4634 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm); 4635 t = Bits32 (opcode, 2, 0); 4636 n = Bits32 (opcode, 5, 3); 4637 m = Bits32 (opcode, 8, 6); 4638 4639 // index = TRUE; add = TRUE; wback = FALSE; 4640 index = true; 4641 add = true; 4642 wback = false; 4643 4644 // (shift_t, shift_n) = (SRType_LSL, 0); 4645 shift_t = SRType_LSL; 4646 shift_n = 0; 4647 break; 4648 4649 case eEncodingT2: 4650 // if Rn == '1111' then UNDEFINED; 4651 if (Bits32 (opcode, 19, 16) == 15) 4652 return false; 4653 4654 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm); 4655 t = Bits32 (opcode, 15, 12); 4656 n = Bits32 (opcode, 19, 16); 4657 m = Bits32 (opcode, 3, 0); 4658 4659 // index = TRUE; add = TRUE; wback = FALSE; 4660 index = true; 4661 add = true; 4662 wback = false; 4663 4664 // (shift_t, shift_n) = (SRType_LSL, UInt(imm2)); 4665 shift_t = SRType_LSL; 4666 shift_n = Bits32 (opcode, 5, 4); 4667 4668 // if t == 15 || BadReg(m) then UNPREDICTABLE; 4669 if ((t == 15) || (BadReg (m))) 4670 return false; 4671 break; 4672 4673 case eEncodingA1: 4674 { 4675 // if P == '0' && W == '1' then SEE STRT; 4676 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm); 4677 t = Bits32 (opcode, 15, 12); 4678 n = Bits32 (opcode, 19, 16); 4679 m = Bits32 (opcode, 3, 0); 4680 4681 // index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1'); 4682 index = BitIsSet (opcode, 24); 4683 add = BitIsSet (opcode, 23); 4684 wback = (BitIsClear (opcode, 24) || BitIsSet (opcode, 21)); 4685 4686 // (shift_t, shift_n) = DecodeImmShift(type, imm5); 4687 uint32_t typ = Bits32 (opcode, 6, 5); 4688 uint32_t imm5 = Bits32 (opcode, 11, 7); 4689 shift_n = DecodeImmShift(typ, imm5, shift_t); 4690 4691 // if m == 15 then UNPREDICTABLE; 4692 if (m == 15) 4693 return false; 4694 4695 // if wback && (n == 15 || n == t) then UNPREDICTABLE; 4696 if (wback && ((n == 15) || (n == t))) 4697 return false; 4698 4699 break; 4700 } 4701 default: 4702 return false; 4703 } 4704 4705 addr_t offset_addr; 4706 addr_t address; 4707 int32_t offset = 0; 4708 4709 addr_t base_address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success); 4710 if (!success) 4711 return false; 4712 4713 uint32_t Rm_data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success); 4714 if (!success) 4715 return false; 4716 4717 // offset = Shift(R[m], shift_t, shift_n, APSR.C); 4718 offset = Shift (Rm_data, shift_t, shift_n, APSR_C); 4719 4720 // offset_addr = if add then (R[n] + offset) else (R[n] - offset); 4721 if (add) 4722 offset_addr = base_address + offset; 4723 else 4724 offset_addr = base_address - offset; 4725 4726 // address = if index then offset_addr else R[n]; 4727 if (index) 4728 address = offset_addr; 4729 else 4730 address = base_address; 4731 4732 uint32_t data; 4733 // if t == 15 then // Only possible for encoding A1 4734 if (t == 15) 4735 // data = PCStoreValue(); 4736 data = ReadCoreReg (PC_REG, &success); 4737 else 4738 // data = R[t]; 4739 data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + t, 0, &success); 4740 4741 if (!success) 4742 return false; 4743 4744 EmulateInstruction::Context context; 4745 context.type = eContextRegisterStore; 4746 4747 // if UnalignedSupport() || address<1:0> == '00' || CurrentInstrSet() == InstrSet_ARM then 4748 if (UnalignedSupport () 4749 || (BitIsClear (address, 1) && BitIsClear (address, 0)) 4750 || CurrentInstrSet() == eModeARM) 4751 { 4752 // MemU[address,4] = data; 4753 4754 Register base_reg; 4755 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n); 4756 4757 Register data_reg; 4758 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + t); 4759 4760 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, address - base_address); 4761 if (!MemUWrite (context, address, data, addr_byte_size)) 4762 return false; 4763 4764 } 4765 else 4766 // MemU[address,4] = bits(32) UNKNOWN; 4767 WriteBits32UnknownToMemory (address); 4768 4769 // if wback then R[n] = offset_addr; 4770 if (wback) 4771 { 4772 context.type = eContextRegisterLoad; 4773 context.SetAddress (offset_addr); 4774 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr)) 4775 return false; 4776 } 4777 4778 } 4779 return true; 4780} 4781 4782bool 4783EmulateInstructionARM::EmulateSTRBThumb (const uint32_t opcode, const ARMEncoding encoding) 4784{ 4785#if 0 4786 if ConditionPassed() then 4787 EncodingSpecificOperations(); NullCheckIfThumbEE(n); 4788 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32); 4789 address = if index then offset_addr else R[n]; 4790 MemU[address,1] = R[t]<7:0>; 4791 if wback then R[n] = offset_addr; 4792#endif 4793 4794 4795 bool success = false; 4796 4797 if (ConditionPassed(opcode)) 4798 { 4799 uint32_t t; 4800 uint32_t n; 4801 uint32_t imm32; 4802 bool index; 4803 bool add; 4804 bool wback; 4805 // EncodingSpecificOperations(); NullCheckIfThumbEE(n); 4806 switch (encoding) 4807 { 4808 case eEncodingT1: 4809 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm5, 32); 4810 t = Bits32 (opcode, 2, 0); 4811 n = Bits32 (opcode, 5, 3); 4812 imm32 = Bits32 (opcode, 10, 6); 4813 4814 // index = TRUE; add = TRUE; wback = FALSE; 4815 index = true; 4816 add = true; 4817 wback = false; 4818 break; 4819 4820 case eEncodingT2: 4821 // if Rn == '1111' then UNDEFINED; 4822 if (Bits32 (opcode, 19, 16) == 15) 4823 return false; 4824 4825 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32); 4826 t = Bits32 (opcode, 15, 12); 4827 n = Bits32 (opcode, 19, 16); 4828 imm32 = Bits32 (opcode, 11, 0); 4829 4830 // index = TRUE; add = TRUE; wback = FALSE; 4831 index = true; 4832 add = true; 4833 wback = false; 4834 4835 // if BadReg(t) then UNPREDICTABLE; 4836 if (BadReg (t)) 4837 return false; 4838 break; 4839 4840 case eEncodingT3: 4841 // if P == '1' && U == '1' && W == '0' then SEE STRBT; 4842 // if Rn == '1111' || (P == '0' && W == '0') then UNDEFINED; 4843 if (Bits32 (opcode, 19, 16) == 15) 4844 return false; 4845 4846 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32); 4847 t = Bits32 (opcode, 15, 12); 4848 n = Bits32 (opcode, 19, 16); 4849 imm32 = Bits32 (opcode, 7, 0); 4850 4851 // index = (P == '1'); add = (U == '1'); wback = (W == '1'); 4852 index = BitIsSet (opcode, 10); 4853 add = BitIsSet (opcode, 9); 4854 wback = BitIsSet (opcode, 8); 4855 4856 // if BadReg(t) || (wback && n == t) then UNPREDICTABLE 4857 if ((BadReg (t)) || (wback && (n == t))) 4858 return false; 4859 break; 4860 4861 default: 4862 return false; 4863 } 4864 4865 addr_t offset_addr; 4866 addr_t address; 4867 addr_t base_address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success); 4868 if (!success) 4869 return false; 4870 4871 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32); 4872 if (add) 4873 offset_addr = base_address + imm32; 4874 else 4875 offset_addr = base_address - imm32; 4876 4877 // address = if index then offset_addr else R[n]; 4878 if (index) 4879 address = offset_addr; 4880 else 4881 address = base_address; 4882 4883 // MemU[address,1] = R[t]<7:0> 4884 Register base_reg; 4885 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n); 4886 4887 Register data_reg; 4888 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + t); 4889 4890 EmulateInstruction::Context context; 4891 context.type = eContextRegisterStore; 4892 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, address - base_address); 4893 4894 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + t, 0, &success); 4895 if (!success) 4896 return false; 4897 4898 data = Bits32 (data, 7, 0); 4899 4900 if (!MemUWrite (context, address, data, 1)) 4901 return false; 4902 4903 // if wback then R[n] = offset_addr; 4904 if (wback) 4905 { 4906 context.type = eContextRegisterLoad; 4907 context.SetAddress (offset_addr); 4908 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr)) 4909 return false; 4910 } 4911 4912 } 4913 4914 return true; 4915} 4916 4917// STRH (register) calculates an address from a base register value and an offset register value, and stores a 4918// halfword from a register to memory. The offset register alue can be shifted left by 0, 1, 2, or 3 bits. 4919bool 4920EmulateInstructionARM::EmulateSTRHRegister (const uint32_t opcode, const ARMEncoding encoding) 4921{ 4922#if 0 4923 if ConditionPassed() then 4924 EncodingSpecificOperations(); NullCheckIfThumbEE(n); 4925 offset = Shift(R[m], shift_t, shift_n, APSR.C); 4926 offset_addr = if add then (R[n] + offset) else (R[n] - offset); 4927 address = if index then offset_addr else R[n]; 4928 if UnalignedSupport() || address<0> == '0' then 4929 MemU[address,2] = R[t]<15:0>; 4930 else // Can only occur before ARMv7 4931 MemU[address,2] = bits(16) UNKNOWN; 4932 if wback then R[n] = offset_addr; 4933#endif 4934 4935 bool success = false; 4936 4937 if (ConditionPassed(opcode)) 4938 { 4939 uint32_t t; 4940 uint32_t n; 4941 uint32_t m; 4942 bool index; 4943 bool add; 4944 bool wback; 4945 ARM_ShifterType shift_t; 4946 uint32_t shift_n; 4947 4948 // EncodingSpecificOperations(); NullCheckIfThumbEE(n); 4949 switch (encoding) 4950 { 4951 case eEncodingT1: 4952 // if CurrentInstrSet() == InstrSet_ThumbEE then SEE "Modified operation in ThumbEE"; 4953 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm); 4954 t = Bits32 (opcode, 2, 0); 4955 n = Bits32 (opcode, 5, 3); 4956 m = Bits32 (opcode, 8, 6); 4957 4958 // index = TRUE; add = TRUE; wback = FALSE; 4959 index = true; 4960 add = true; 4961 wback = false; 4962 4963 // (shift_t, shift_n) = (SRType_LSL, 0); 4964 shift_t = SRType_LSL; 4965 shift_n = 0; 4966 4967 break; 4968 4969 case eEncodingT2: 4970 // if Rn == '1111' then UNDEFINED; 4971 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm); 4972 t = Bits32 (opcode, 15, 12); 4973 n = Bits32 (opcode, 19, 16); 4974 m = Bits32 (opcode, 3, 0); 4975 if (n == 15) 4976 return false; 4977 4978 // index = TRUE; add = TRUE; wback = FALSE; 4979 index = true; 4980 add = true; 4981 wback = false; 4982 4983 // (shift_t, shift_n) = (SRType_LSL, UInt(imm2)); 4984 shift_t = SRType_LSL; 4985 shift_n = Bits32 (opcode, 5, 4); 4986 4987 // if BadReg(t) || BadReg(m) then UNPREDICTABLE; 4988 if (BadReg (t) || BadReg (m)) 4989 return false; 4990 4991 break; 4992 4993 case eEncodingA1: 4994 // if P == '0' && W == '1' then SEE STRHT; 4995 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm); 4996 t = Bits32 (opcode, 15, 12); 4997 n = Bits32 (opcode, 19, 16); 4998 m = Bits32 (opcode, 3, 0); 4999 5000 // index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1'); 5001 index = BitIsSet (opcode, 24); 5002 add = BitIsSet (opcode, 23); 5003 wback = (BitIsClear (opcode, 24) || BitIsSet (opcode, 21)); 5004 5005 // (shift_t, shift_n) = (SRType_LSL, 0); 5006 shift_t = SRType_LSL; 5007 shift_n = 0; 5008 5009 // if t == 15 || m == 15 then UNPREDICTABLE; 5010 if ((t == 15) || (m == 15)) 5011 return false; 5012 5013 // if wback && (n == 15 || n == t) then UNPREDICTABLE; 5014 if (wback && ((n == 15) || (n == t))) 5015 return false; 5016 5017 break; 5018 5019 default: 5020 return false; 5021 } 5022 5023 uint32_t Rm = ReadCoreReg (m, &success); 5024 if (!success) 5025 return false; 5026 5027 uint32_t Rn = ReadCoreReg (n, &success); 5028 if (!success) 5029 return false; 5030 5031 // offset = Shift(R[m], shift_t, shift_n, APSR.C); 5032 uint32_t offset = Shift (Rm, shift_t, shift_n, APSR_C); 5033 5034 // offset_addr = if add then (R[n] + offset) else (R[n] - offset); 5035 addr_t offset_addr; 5036 if (add) 5037 offset_addr = Rn + offset; 5038 else 5039 offset_addr = Rn - offset; 5040 5041 // address = if index then offset_addr else R[n]; 5042 addr_t address; 5043 if (index) 5044 address = offset_addr; 5045 else 5046 address = Rn; 5047 5048 EmulateInstruction::Context context; 5049 context.type = eContextRegisterStore; 5050 Register base_reg; 5051 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n); 5052 Register offset_reg; 5053 offset_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + m); 5054 5055 // if UnalignedSupport() || address<0> == '0' then 5056 if (UnalignedSupport() || BitIsClear (address, 0)) 5057 { 5058 // MemU[address,2] = R[t]<15:0>; 5059 uint32_t Rt = ReadCoreReg (t, &success); 5060 if (!success) 5061 return false; 5062 5063 EmulateInstruction::Context context; 5064 context.type = eContextRegisterStore; 5065 Register base_reg; 5066 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n); 5067 Register offset_reg; 5068 offset_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + m); 5069 Register data_reg; 5070 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + t); 5071 context.SetRegisterToRegisterPlusIndirectOffset (base_reg, offset_reg, data_reg); 5072 5073 if (!MemUWrite (context, address, Bits32 (Rt, 15, 0), 2)) 5074 return false; 5075 } 5076 else // Can only occur before ARMv7 5077 { 5078 // MemU[address,2] = bits(16) UNKNOWN; 5079 } 5080 5081 // if wback then R[n] = offset_addr; 5082 if (wback) 5083 { 5084 context.type = eContextAdjustBaseRegister; 5085 context.SetAddress (offset_addr); 5086 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr)) 5087 return false; 5088 } 5089 } 5090 5091 return true; 5092} 5093 5094// Add with Carry (immediate) adds an immediate value and the carry flag value to a register value, 5095// and writes the result to the destination register. It can optionally update the condition flags 5096// based on the result. 5097bool 5098EmulateInstructionARM::EmulateADCImm (const uint32_t opcode, const ARMEncoding encoding) 5099{ 5100#if 0 5101 // ARM pseudo code... 5102 if ConditionPassed() then 5103 EncodingSpecificOperations(); 5104 (result, carry, overflow) = AddWithCarry(R[n], imm32, APSR.C); 5105 if d == 15 then // Can only occur for ARM encoding 5106 ALUWritePC(result); // setflags is always FALSE here 5107 else 5108 R[d] = result; 5109 if setflags then 5110 APSR.N = result<31>; 5111 APSR.Z = IsZeroBit(result); 5112 APSR.C = carry; 5113 APSR.V = overflow; 5114#endif 5115 5116 bool success = false; 5117 5118 if (ConditionPassed(opcode)) 5119 { 5120 uint32_t Rd, Rn; 5121 uint32_t imm32; // the immediate value to be added to the value obtained from Rn 5122 bool setflags; 5123 switch (encoding) 5124 { 5125 case eEncodingT1: 5126 Rd = Bits32(opcode, 11, 8); 5127 Rn = Bits32(opcode, 19, 16); 5128 setflags = BitIsSet(opcode, 20); 5129 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8) 5130 if (BadReg(Rd) || BadReg(Rn)) 5131 return false; 5132 break; 5133 case eEncodingA1: 5134 Rd = Bits32(opcode, 15, 12); 5135 Rn = Bits32(opcode, 19, 16); 5136 setflags = BitIsSet(opcode, 20); 5137 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12) 5138 5139 if (Rd == 15 && setflags) 5140 return EmulateSUBSPcLrEtc (opcode, encoding); 5141 break; 5142 default: 5143 return false; 5144 } 5145 5146 // Read the first operand. 5147 int32_t val1 = ReadCoreReg(Rn, &success); 5148 if (!success) 5149 return false; 5150 5151 AddWithCarryResult res = AddWithCarry(val1, imm32, APSR_C); 5152 5153 EmulateInstruction::Context context; 5154 context.type = EmulateInstruction::eContextImmediate; 5155 context.SetNoArgs (); 5156 5157 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow)) 5158 return false; 5159 } 5160 return true; 5161} 5162 5163// Add with Carry (register) adds a register value, the carry flag value, and an optionally-shifted 5164// register value, and writes the result to the destination register. It can optionally update the 5165// condition flags based on the result. 5166bool 5167EmulateInstructionARM::EmulateADCReg (const uint32_t opcode, const ARMEncoding encoding) 5168{ 5169#if 0 5170 // ARM pseudo code... 5171 if ConditionPassed() then 5172 EncodingSpecificOperations(); 5173 shifted = Shift(R[m], shift_t, shift_n, APSR.C); 5174 (result, carry, overflow) = AddWithCarry(R[n], shifted, APSR.C); 5175 if d == 15 then // Can only occur for ARM encoding 5176 ALUWritePC(result); // setflags is always FALSE here 5177 else 5178 R[d] = result; 5179 if setflags then 5180 APSR.N = result<31>; 5181 APSR.Z = IsZeroBit(result); 5182 APSR.C = carry; 5183 APSR.V = overflow; 5184#endif 5185 5186 bool success = false; 5187 5188 if (ConditionPassed(opcode)) 5189 { 5190 uint32_t Rd, Rn, Rm; 5191 ARM_ShifterType shift_t; 5192 uint32_t shift_n; // the shift applied to the value read from Rm 5193 bool setflags; 5194 switch (encoding) 5195 { 5196 case eEncodingT1: 5197 Rd = Rn = Bits32(opcode, 2, 0); 5198 Rm = Bits32(opcode, 5, 3); 5199 setflags = !InITBlock(); 5200 shift_t = SRType_LSL; 5201 shift_n = 0; 5202 break; 5203 case eEncodingT2: 5204 Rd = Bits32(opcode, 11, 8); 5205 Rn = Bits32(opcode, 19, 16); 5206 Rm = Bits32(opcode, 3, 0); 5207 setflags = BitIsSet(opcode, 20); 5208 shift_n = DecodeImmShiftThumb(opcode, shift_t); 5209 if (BadReg(Rd) || BadReg(Rn) || BadReg(Rm)) 5210 return false; 5211 break; 5212 case eEncodingA1: 5213 Rd = Bits32(opcode, 15, 12); 5214 Rn = Bits32(opcode, 19, 16); 5215 Rm = Bits32(opcode, 3, 0); 5216 setflags = BitIsSet(opcode, 20); 5217 shift_n = DecodeImmShiftARM(opcode, shift_t); 5218 5219 if (Rd == 15 && setflags) 5220 return EmulateSUBSPcLrEtc (opcode, encoding); 5221 break; 5222 default: 5223 return false; 5224 } 5225 5226 // Read the first operand. 5227 int32_t val1 = ReadCoreReg(Rn, &success); 5228 if (!success) 5229 return false; 5230 5231 // Read the second operand. 5232 int32_t val2 = ReadCoreReg(Rm, &success); 5233 if (!success) 5234 return false; 5235 5236 uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C); 5237 AddWithCarryResult res = AddWithCarry(val1, shifted, APSR_C); 5238 5239 EmulateInstruction::Context context; 5240 context.type = EmulateInstruction::eContextImmediate; 5241 context.SetNoArgs (); 5242 5243 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow)) 5244 return false; 5245 } 5246 return true; 5247} 5248 5249// This instruction adds an immediate value to the PC value to form a PC-relative address, 5250// and writes the result to the destination register. 5251bool 5252EmulateInstructionARM::EmulateADR (const uint32_t opcode, const ARMEncoding encoding) 5253{ 5254#if 0 5255 // ARM pseudo code... 5256 if ConditionPassed() then 5257 EncodingSpecificOperations(); 5258 result = if add then (Align(PC,4) + imm32) else (Align(PC,4) - imm32); 5259 if d == 15 then // Can only occur for ARM encodings 5260 ALUWritePC(result); 5261 else 5262 R[d] = result; 5263#endif 5264 5265 bool success = false; 5266 5267 if (ConditionPassed(opcode)) 5268 { 5269 uint32_t Rd; 5270 uint32_t imm32; // the immediate value to be added/subtracted to/from the PC 5271 bool add; 5272 switch (encoding) 5273 { 5274 case eEncodingT1: 5275 Rd = Bits32(opcode, 10, 8); 5276 imm32 = ThumbImm8Scaled(opcode); // imm32 = ZeroExtend(imm8:'00', 32) 5277 break; 5278 case eEncodingT2: 5279 case eEncodingT3: 5280 Rd = Bits32(opcode, 11, 8); 5281 imm32 = ThumbImm12(opcode); // imm32 = ZeroExtend(i:imm3:imm8, 32) 5282 add = (Bits32(opcode, 24, 21) == 0); // 0b0000 => ADD; 0b0101 => SUB 5283 if (BadReg(Rd)) 5284 return false; 5285 break; 5286 case eEncodingA1: 5287 case eEncodingA2: 5288 Rd = Bits32(opcode, 15, 12); 5289 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12) 5290 add = (Bits32(opcode, 24, 21) == 0x4); // 0b0100 => ADD; 0b0010 => SUB 5291 break; 5292 default: 5293 return false; 5294 } 5295 5296 // Read the PC value. 5297 uint32_t pc = ReadCoreReg(PC_REG, &success); 5298 if (!success) 5299 return false; 5300 5301 uint32_t result = (add ? Align(pc, 4) + imm32 : Align(pc, 4) - imm32); 5302 5303 EmulateInstruction::Context context; 5304 context.type = EmulateInstruction::eContextImmediate; 5305 context.SetNoArgs (); 5306 5307 if (!WriteCoreReg(context, result, Rd)) 5308 return false; 5309 } 5310 return true; 5311} 5312 5313// This instruction performs a bitwise AND of a register value and an immediate value, and writes the result 5314// to the destination register. It can optionally update the condition flags based on the result. 5315bool 5316EmulateInstructionARM::EmulateANDImm (const uint32_t opcode, const ARMEncoding encoding) 5317{ 5318#if 0 5319 // ARM pseudo code... 5320 if ConditionPassed() then 5321 EncodingSpecificOperations(); 5322 result = R[n] AND imm32; 5323 if d == 15 then // Can only occur for ARM encoding 5324 ALUWritePC(result); // setflags is always FALSE here 5325 else 5326 R[d] = result; 5327 if setflags then 5328 APSR.N = result<31>; 5329 APSR.Z = IsZeroBit(result); 5330 APSR.C = carry; 5331 // APSR.V unchanged 5332#endif 5333 5334 bool success = false; 5335 5336 if (ConditionPassed(opcode)) 5337 { 5338 uint32_t Rd, Rn; 5339 uint32_t imm32; // the immediate value to be ANDed to the value obtained from Rn 5340 bool setflags; 5341 uint32_t carry; // the carry bit after ARM/Thumb Expand operation 5342 switch (encoding) 5343 { 5344 case eEncodingT1: 5345 Rd = Bits32(opcode, 11, 8); 5346 Rn = Bits32(opcode, 19, 16); 5347 setflags = BitIsSet(opcode, 20); 5348 imm32 = ThumbExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C) 5349 // if Rd == '1111' && S == '1' then SEE TST (immediate); 5350 if (Rd == 15 && setflags) 5351 return EmulateTSTImm(opcode, eEncodingT1); 5352 if (Rd == 13 || (Rd == 15 && !setflags) || BadReg(Rn)) 5353 return false; 5354 break; 5355 case eEncodingA1: 5356 Rd = Bits32(opcode, 15, 12); 5357 Rn = Bits32(opcode, 19, 16); 5358 setflags = BitIsSet(opcode, 20); 5359 imm32 = ARMExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ARMExpandImm(imm12, APSR.C) 5360 5361 if (Rd == 15 && setflags) 5362 return EmulateSUBSPcLrEtc (opcode, encoding); 5363 break; 5364 default: 5365 return false; 5366 } 5367 5368 // Read the first operand. 5369 uint32_t val1 = ReadCoreReg(Rn, &success); 5370 if (!success) 5371 return false; 5372 5373 uint32_t result = val1 & imm32; 5374 5375 EmulateInstruction::Context context; 5376 context.type = EmulateInstruction::eContextImmediate; 5377 context.SetNoArgs (); 5378 5379 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry)) 5380 return false; 5381 } 5382 return true; 5383} 5384 5385// This instruction performs a bitwise AND of a register value and an optionally-shifted register value, 5386// and writes the result to the destination register. It can optionally update the condition flags 5387// based on the result. 5388bool 5389EmulateInstructionARM::EmulateANDReg (const uint32_t opcode, const ARMEncoding encoding) 5390{ 5391#if 0 5392 // ARM pseudo code... 5393 if ConditionPassed() then 5394 EncodingSpecificOperations(); 5395 (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C); 5396 result = R[n] AND shifted; 5397 if d == 15 then // Can only occur for ARM encoding 5398 ALUWritePC(result); // setflags is always FALSE here 5399 else 5400 R[d] = result; 5401 if setflags then 5402 APSR.N = result<31>; 5403 APSR.Z = IsZeroBit(result); 5404 APSR.C = carry; 5405 // APSR.V unchanged 5406#endif 5407 5408 bool success = false; 5409 5410 if (ConditionPassed(opcode)) 5411 { 5412 uint32_t Rd, Rn, Rm; 5413 ARM_ShifterType shift_t; 5414 uint32_t shift_n; // the shift applied to the value read from Rm 5415 bool setflags; 5416 uint32_t carry; 5417 switch (encoding) 5418 { 5419 case eEncodingT1: 5420 Rd = Rn = Bits32(opcode, 2, 0); 5421 Rm = Bits32(opcode, 5, 3); 5422 setflags = !InITBlock(); 5423 shift_t = SRType_LSL; 5424 shift_n = 0; 5425 break; 5426 case eEncodingT2: 5427 Rd = Bits32(opcode, 11, 8); 5428 Rn = Bits32(opcode, 19, 16); 5429 Rm = Bits32(opcode, 3, 0); 5430 setflags = BitIsSet(opcode, 20); 5431 shift_n = DecodeImmShiftThumb(opcode, shift_t); 5432 // if Rd == '1111' && S == '1' then SEE TST (register); 5433 if (Rd == 15 && setflags) 5434 return EmulateTSTReg(opcode, eEncodingT2); 5435 if (Rd == 13 || (Rd == 15 && !setflags) || BadReg(Rn) || BadReg(Rm)) 5436 return false; 5437 break; 5438 case eEncodingA1: 5439 Rd = Bits32(opcode, 15, 12); 5440 Rn = Bits32(opcode, 19, 16); 5441 Rm = Bits32(opcode, 3, 0); 5442 setflags = BitIsSet(opcode, 20); 5443 shift_n = DecodeImmShiftARM(opcode, shift_t); 5444 5445 if (Rd == 15 && setflags) 5446 return EmulateSUBSPcLrEtc (opcode, encoding); 5447 break; 5448 default: 5449 return false; 5450 } 5451 5452 // Read the first operand. 5453 uint32_t val1 = ReadCoreReg(Rn, &success); 5454 if (!success) 5455 return false; 5456 5457 // Read the second operand. 5458 uint32_t val2 = ReadCoreReg(Rm, &success); 5459 if (!success) 5460 return false; 5461 5462 uint32_t shifted = Shift_C(val2, shift_t, shift_n, APSR_C, carry); 5463 uint32_t result = val1 & shifted; 5464 5465 EmulateInstruction::Context context; 5466 context.type = EmulateInstruction::eContextImmediate; 5467 context.SetNoArgs (); 5468 5469 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry)) 5470 return false; 5471 } 5472 return true; 5473} 5474 5475// Bitwise Bit Clear (immediate) performs a bitwise AND of a register value and the complement of an 5476// immediate value, and writes the result to the destination register. It can optionally update the 5477// condition flags based on the result. 5478bool 5479EmulateInstructionARM::EmulateBICImm (const uint32_t opcode, const ARMEncoding encoding) 5480{ 5481#if 0 5482 // ARM pseudo code... 5483 if ConditionPassed() then 5484 EncodingSpecificOperations(); 5485 result = R[n] AND NOT(imm32); 5486 if d == 15 then // Can only occur for ARM encoding 5487 ALUWritePC(result); // setflags is always FALSE here 5488 else 5489 R[d] = result; 5490 if setflags then 5491 APSR.N = result<31>; 5492 APSR.Z = IsZeroBit(result); 5493 APSR.C = carry; 5494 // APSR.V unchanged 5495#endif 5496 5497 bool success = false; 5498 5499 if (ConditionPassed(opcode)) 5500 { 5501 uint32_t Rd, Rn; 5502 uint32_t imm32; // the immediate value to be bitwise inverted and ANDed to the value obtained from Rn 5503 bool setflags; 5504 uint32_t carry; // the carry bit after ARM/Thumb Expand operation 5505 switch (encoding) 5506 { 5507 case eEncodingT1: 5508 Rd = Bits32(opcode, 11, 8); 5509 Rn = Bits32(opcode, 19, 16); 5510 setflags = BitIsSet(opcode, 20); 5511 imm32 = ThumbExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C) 5512 if (BadReg(Rd) || BadReg(Rn)) 5513 return false; 5514 break; 5515 case eEncodingA1: 5516 Rd = Bits32(opcode, 15, 12); 5517 Rn = Bits32(opcode, 19, 16); 5518 setflags = BitIsSet(opcode, 20); 5519 imm32 = ARMExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ARMExpandImm(imm12, APSR.C) 5520 5521 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions; 5522 if (Rd == 15 && setflags) 5523 return EmulateSUBSPcLrEtc (opcode, encoding); 5524 break; 5525 default: 5526 return false; 5527 } 5528 5529 // Read the first operand. 5530 uint32_t val1 = ReadCoreReg(Rn, &success); 5531 if (!success) 5532 return false; 5533 5534 uint32_t result = val1 & ~imm32; 5535 5536 EmulateInstruction::Context context; 5537 context.type = EmulateInstruction::eContextImmediate; 5538 context.SetNoArgs (); 5539 5540 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry)) 5541 return false; 5542 } 5543 return true; 5544} 5545 5546// Bitwise Bit Clear (register) performs a bitwise AND of a register value and the complement of an 5547// optionally-shifted register value, and writes the result to the destination register. 5548// It can optionally update the condition flags based on the result. 5549bool 5550EmulateInstructionARM::EmulateBICReg (const uint32_t opcode, const ARMEncoding encoding) 5551{ 5552#if 0 5553 // ARM pseudo code... 5554 if ConditionPassed() then 5555 EncodingSpecificOperations(); 5556 (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C); 5557 result = R[n] AND NOT(shifted); 5558 if d == 15 then // Can only occur for ARM encoding 5559 ALUWritePC(result); // setflags is always FALSE here 5560 else 5561 R[d] = result; 5562 if setflags then 5563 APSR.N = result<31>; 5564 APSR.Z = IsZeroBit(result); 5565 APSR.C = carry; 5566 // APSR.V unchanged 5567#endif 5568 5569 bool success = false; 5570 5571 if (ConditionPassed(opcode)) 5572 { 5573 uint32_t Rd, Rn, Rm; 5574 ARM_ShifterType shift_t; 5575 uint32_t shift_n; // the shift applied to the value read from Rm 5576 bool setflags; 5577 uint32_t carry; 5578 switch (encoding) 5579 { 5580 case eEncodingT1: 5581 Rd = Rn = Bits32(opcode, 2, 0); 5582 Rm = Bits32(opcode, 5, 3); 5583 setflags = !InITBlock(); 5584 shift_t = SRType_LSL; 5585 shift_n = 0; 5586 break; 5587 case eEncodingT2: 5588 Rd = Bits32(opcode, 11, 8); 5589 Rn = Bits32(opcode, 19, 16); 5590 Rm = Bits32(opcode, 3, 0); 5591 setflags = BitIsSet(opcode, 20); 5592 shift_n = DecodeImmShiftThumb(opcode, shift_t); 5593 if (BadReg(Rd) || BadReg(Rn) || BadReg(Rm)) 5594 return false; 5595 break; 5596 case eEncodingA1: 5597 Rd = Bits32(opcode, 15, 12); 5598 Rn = Bits32(opcode, 19, 16); 5599 Rm = Bits32(opcode, 3, 0); 5600 setflags = BitIsSet(opcode, 20); 5601 shift_n = DecodeImmShiftARM(opcode, shift_t); 5602 5603 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions; 5604 if (Rd == 15 && setflags) 5605 return EmulateSUBSPcLrEtc (opcode, encoding); 5606 break; 5607 default: 5608 return false; 5609 } 5610 5611 // Read the first operand. 5612 uint32_t val1 = ReadCoreReg(Rn, &success); 5613 if (!success) 5614 return false; 5615 5616 // Read the second operand. 5617 uint32_t val2 = ReadCoreReg(Rm, &success); 5618 if (!success) 5619 return false; 5620 5621 uint32_t shifted = Shift_C(val2, shift_t, shift_n, APSR_C, carry); 5622 uint32_t result = val1 & ~shifted; 5623 5624 EmulateInstruction::Context context; 5625 context.type = EmulateInstruction::eContextImmediate; 5626 context.SetNoArgs (); 5627 5628 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry)) 5629 return false; 5630 } 5631 return true; 5632} 5633 5634// LDR (immediate, ARM) calculates an address from a base register value and an immediate offset, loads a word 5635// from memory, and writes it to a register. It can use offset, post-indexed, or pre-indexed addressing. 5636bool 5637EmulateInstructionARM::EmulateLDRImmediateARM (const uint32_t opcode, const ARMEncoding encoding) 5638{ 5639#if 0 5640 if ConditionPassed() then 5641 EncodingSpecificOperations(); 5642 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32); 5643 address = if index then offset_addr else R[n]; 5644 data = MemU[address,4]; 5645 if wback then R[n] = offset_addr; 5646 if t == 15 then 5647 if address<1:0> == '00' then LoadWritePC(data); else UNPREDICTABLE; 5648 elsif UnalignedSupport() || address<1:0> = '00' then 5649 R[t] = data; 5650 else // Can only apply before ARMv7 5651 R[t] = ROR(data, 8*UInt(address<1:0>)); 5652#endif 5653 5654 bool success = false; 5655 5656 if (ConditionPassed(opcode)) 5657 { 5658 const uint32_t addr_byte_size = GetAddressByteSize(); 5659 5660 uint32_t t; 5661 uint32_t n; 5662 uint32_t imm32; 5663 bool index; 5664 bool add; 5665 bool wback; 5666 5667 switch (encoding) 5668 { 5669 case eEncodingA1: 5670 // if Rn == '1111' then SEE LDR (literal); 5671 // if P == '0' && W == '1' then SEE LDRT; 5672 // if Rn == '1101' && P == '0' && U == '1' && W == '0' && imm12 == '000000000100' then SEE POP; 5673 // t == UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32); 5674 t = Bits32 (opcode, 15, 12); 5675 n = Bits32 (opcode, 19, 16); 5676 imm32 = Bits32 (opcode, 11, 0); 5677 5678 // index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1'); 5679 index = BitIsSet (opcode, 24); 5680 add = BitIsSet (opcode, 23); 5681 wback = (BitIsClear (opcode, 24) || BitIsSet (opcode, 21)); 5682 5683 // if wback && n == t then UNPREDICTABLE; 5684 if (wback && (n == t)) 5685 return false; 5686 5687 break; 5688 5689 default: 5690 return false; 5691 } 5692 5693 addr_t address; 5694 addr_t offset_addr; 5695 addr_t base_address = ReadCoreReg (n, &success); 5696 if (!success) 5697 return false; 5698 5699 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32); 5700 if (add) 5701 offset_addr = base_address + imm32; 5702 else 5703 offset_addr = base_address - imm32; 5704 5705 // address = if index then offset_addr else R[n]; 5706 if (index) 5707 address = offset_addr; 5708 else 5709 address = base_address; 5710 5711 // data = MemU[address,4]; 5712 5713 Register base_reg; 5714 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n); 5715 5716 EmulateInstruction::Context context; 5717 context.type = eContextRegisterLoad; 5718 context.SetRegisterPlusOffset (base_reg, address - base_address); 5719 5720 uint64_t data = MemURead (context, address, addr_byte_size, 0, &success); 5721 if (!success) 5722 return false; 5723 5724 // if wback then R[n] = offset_addr; 5725 if (wback) 5726 { 5727 context.type = eContextAdjustBaseRegister; 5728 context.SetAddress (offset_addr); 5729 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr)) 5730 return false; 5731 } 5732 5733 // if t == 15 then 5734 if (t == 15) 5735 { 5736 // if address<1:0> == '00' then LoadWritePC(data); else UNPREDICTABLE; 5737 if (BitIsClear (address, 1) && BitIsClear (address, 0)) 5738 { 5739 // LoadWritePC (data); 5740 context.type = eContextRegisterLoad; 5741 context.SetRegisterPlusOffset (base_reg, address - base_address); 5742 LoadWritePC (context, data); 5743 } 5744 else 5745 return false; 5746 } 5747 // elsif UnalignedSupport() || address<1:0> = '00' then 5748 else if (UnalignedSupport() || (BitIsClear (address, 1) && BitIsClear (address, 0))) 5749 { 5750 // R[t] = data; 5751 context.type = eContextRegisterLoad; 5752 context.SetRegisterPlusOffset (base_reg, address - base_address); 5753 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data)) 5754 return false; 5755 } 5756 // else // Can only apply before ARMv7 5757 else 5758 { 5759 // R[t] = ROR(data, 8*UInt(address<1:0>)); 5760 data = ROR (data, Bits32 (address, 1, 0)); 5761 context.type = eContextRegisterLoad; 5762 context.SetImmediate (data); 5763 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data)) 5764 return false; 5765 } 5766 5767 } 5768 return true; 5769} 5770 5771// LDR (register) calculates an address from a base register value and an offset register value, loads a word 5772// from memory, and writes it to a resgister. The offset register value can optionally be shifted. 5773bool 5774EmulateInstructionARM::EmulateLDRRegister (const uint32_t opcode, const ARMEncoding encoding) 5775{ 5776#if 0 5777 if ConditionPassed() then 5778 EncodingSpecificOperations(); NullCheckIfThumbEE(n); 5779 offset = Shift(R[m], shift_t, shift_n, APSR.C); 5780 offset_addr = if add then (R[n] + offset) else (R[n] - offset); 5781 address = if index then offset_addr else R[n]; 5782 data = MemU[address,4]; 5783 if wback then R[n] = offset_addr; 5784 if t == 15 then 5785 if address<1:0> == '00' then LoadWritePC(data); else UNPREDICTABLE; 5786 elsif UnalignedSupport() || address<1:0> = '00' then 5787 R[t] = data; 5788 else // Can only apply before ARMv7 5789 if CurrentInstrSet() == InstrSet_ARM then 5790 R[t] = ROR(data, 8*UInt(address<1:0>)); 5791 else 5792 R[t] = bits(32) UNKNOWN; 5793#endif 5794 5795 bool success = false; 5796 5797 if (ConditionPassed(opcode)) 5798 { 5799 const uint32_t addr_byte_size = GetAddressByteSize(); 5800 5801 uint32_t t; 5802 uint32_t n; 5803 uint32_t m; 5804 bool index; 5805 bool add; 5806 bool wback; 5807 ARM_ShifterType shift_t; 5808 uint32_t shift_n; 5809 5810 switch (encoding) 5811 { 5812 case eEncodingT1: 5813 // if CurrentInstrSet() == InstrSet_ThumbEE then SEE "Modified operation in ThumbEE"; 5814 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm); 5815 t = Bits32 (opcode, 2, 0); 5816 n = Bits32 (opcode, 5, 3); 5817 m = Bits32 (opcode, 8, 6); 5818 5819 // index = TRUE; add = TRUE; wback = FALSE; 5820 index = true; 5821 add = true; 5822 wback = false; 5823 5824 // (shift_t, shift_n) = (SRType_LSL, 0); 5825 shift_t = SRType_LSL; 5826 shift_n = 0; 5827 5828 break; 5829 5830 case eEncodingT2: 5831 // if Rn == '1111' then SEE LDR (literal); 5832 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm); 5833 t = Bits32 (opcode, 15, 12); 5834 n = Bits32 (opcode, 19, 16); 5835 m = Bits32 (opcode, 3, 0); 5836 5837 // index = TRUE; add = TRUE; wback = FALSE; 5838 index = true; 5839 add = true; 5840 wback = false; 5841 5842 // (shift_t, shift_n) = (SRType_LSL, UInt(imm2)); 5843 shift_t = SRType_LSL; 5844 shift_n = Bits32 (opcode, 5, 4); 5845 5846 // if BadReg(m) then UNPREDICTABLE; 5847 if (BadReg (m)) 5848 return false; 5849 5850 // if t == 15 && InITBlock() && !LastInITBlock() then UNPREDICTABLE; 5851 if ((t == 15) && InITBlock() && !LastInITBlock()) 5852 return false; 5853 5854 break; 5855 5856 case eEncodingA1: 5857 { 5858 // if P == '0' && W == '1' then SEE LDRT; 5859 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm); 5860 t = Bits32 (opcode, 15, 12); 5861 n = Bits32 (opcode, 19, 16); 5862 m = Bits32 (opcode, 3, 0); 5863 5864 // index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1'); 5865 index = BitIsSet (opcode, 24); 5866 add = BitIsSet (opcode, 23); 5867 wback = (BitIsClear (opcode, 24) || BitIsSet (opcode, 21)); 5868 5869 // (shift_t, shift_n) = DecodeImmShift(type, imm5); 5870 uint32_t type = Bits32 (opcode, 6, 5); 5871 uint32_t imm5 = Bits32 (opcode, 11, 7); 5872 shift_n = DecodeImmShift (type, imm5, shift_t); 5873 5874 // if m == 15 then UNPREDICTABLE; 5875 if (m == 15) 5876 return false; 5877 5878 // if wback && (n == 15 || n == t) then UNPREDICTABLE; 5879 if (wback && ((n == 15) || (n == t))) 5880 return false; 5881 } 5882 break; 5883 5884 5885 default: 5886 return false; 5887 } 5888 5889 uint32_t Rm = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success); 5890 if (!success) 5891 return false; 5892 5893 uint32_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success); 5894 if (!success) 5895 return false; 5896 5897 addr_t offset_addr; 5898 addr_t address; 5899 5900 // offset = Shift(R[m], shift_t, shift_n, APSR.C); -- Note "The APSR is an application level alias for the CPSR". 5901 addr_t offset = Shift (Rm, shift_t, shift_n, Bit32 (m_opcode_cpsr, APSR_C)); 5902 5903 // offset_addr = if add then (R[n] + offset) else (R[n] - offset); 5904 if (add) 5905 offset_addr = Rn + offset; 5906 else 5907 offset_addr = Rn - offset; 5908 5909 // address = if index then offset_addr else R[n]; 5910 if (index) 5911 address = offset_addr; 5912 else 5913 address = Rn; 5914 5915 // data = MemU[address,4]; 5916 Register base_reg; 5917 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n); 5918 5919 EmulateInstruction::Context context; 5920 context.type = eContextRegisterLoad; 5921 context.SetRegisterPlusOffset (base_reg, address - Rn); 5922 5923 uint64_t data = MemURead (context, address, addr_byte_size, 0, &success); 5924 if (!success) 5925 return false; 5926 5927 // if wback then R[n] = offset_addr; 5928 if (wback) 5929 { 5930 context.type = eContextAdjustBaseRegister; 5931 context.SetAddress (offset_addr); 5932 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr)) 5933 return false; 5934 } 5935 5936 // if t == 15 then 5937 if (t == 15) 5938 { 5939 // if address<1:0> == '00' then LoadWritePC(data); else UNPREDICTABLE; 5940 if (BitIsClear (address, 1) && BitIsClear (address, 0)) 5941 { 5942 context.type = eContextRegisterLoad; 5943 context.SetRegisterPlusOffset (base_reg, address - Rn); 5944 LoadWritePC (context, data); 5945 } 5946 else 5947 return false; 5948 } 5949 // elsif UnalignedSupport() || address<1:0> = '00' then 5950 else if (UnalignedSupport () || (BitIsClear (address, 1) && BitIsClear (address, 0))) 5951 { 5952 // R[t] = data; 5953 context.type = eContextRegisterLoad; 5954 context.SetRegisterPlusOffset (base_reg, address - Rn); 5955 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data)) 5956 return false; 5957 } 5958 else // Can only apply before ARMv7 5959 { 5960 // if CurrentInstrSet() == InstrSet_ARM then 5961 if (CurrentInstrSet () == eModeARM) 5962 { 5963 // R[t] = ROR(data, 8*UInt(address<1:0>)); 5964 data = ROR (data, Bits32 (address, 1, 0)); 5965 context.type = eContextRegisterLoad; 5966 context.SetImmediate (data); 5967 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data)) 5968 return false; 5969 } 5970 else 5971 { 5972 // R[t] = bits(32) UNKNOWN; 5973 WriteBits32Unknown (t); 5974 } 5975 } 5976 } 5977 return true; 5978} 5979 5980// LDRB (immediate, Thumb) 5981bool 5982EmulateInstructionARM::EmulateLDRBImmediate (const uint32_t opcode, const ARMEncoding encoding) 5983{ 5984#if 0 5985 if ConditionPassed() then 5986 EncodingSpecificOperations(); NullCheckIfThumbEE(n); 5987 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32); 5988 address = if index then offset_addr else R[n]; 5989 R[t] = ZeroExtend(MemU[address,1], 32); 5990 if wback then R[n] = offset_addr; 5991#endif 5992 5993 bool success = false; 5994 5995 if (ConditionPassed(opcode)) 5996 { 5997 uint32_t t; 5998 uint32_t n; 5999 uint32_t imm32; 6000 bool index; 6001 bool add; 6002 bool wback; 6003 6004 // EncodingSpecificOperations(); NullCheckIfThumbEE(n); 6005 switch (encoding) 6006 { 6007 case eEncodingT1: 6008 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm5, 32); 6009 t = Bits32 (opcode, 2, 0); 6010 n = Bits32 (opcode, 5, 3); 6011 imm32 = Bits32 (opcode, 10, 6); 6012 6013 // index = TRUE; add = TRUE; wback = FALSE; 6014 index = true; 6015 add = true; 6016 wback= false; 6017 6018 break; 6019 6020 case eEncodingT2: 6021 // if Rt == '1111' then SEE PLD; 6022 // if Rn == '1111' then SEE LDRB (literal); 6023 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32); 6024 t = Bits32 (opcode, 15, 12); 6025 n = Bits32 (opcode, 19, 16); 6026 imm32 = Bits32 (opcode, 11, 0); 6027 6028 // index = TRUE; add = TRUE; wback = FALSE; 6029 index = true; 6030 add = true; 6031 wback = false; 6032 6033 // if t == 13 then UNPREDICTABLE; 6034 if (t == 13) 6035 return false; 6036 6037 break; 6038 6039 case eEncodingT3: 6040 // if Rt == '1111' && P == '1' && U == '0' && W == '0' then SEE PLD; 6041 // if Rn == '1111' then SEE LDRB (literal); 6042 // if P == '1' && U == '1' && W == '0' then SEE LDRBT; 6043 // if P == '0' && W == '0' then UNDEFINED; 6044 if (BitIsClear (opcode, 10) && BitIsClear (opcode, 8)) 6045 return false; 6046 6047 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32); 6048 t = Bits32 (opcode, 15, 12); 6049 n = Bits32 (opcode, 19, 16); 6050 imm32 = Bits32 (opcode, 7, 0); 6051 6052 // index = (P == '1'); add = (U == '1'); wback = (W == '1'); 6053 index = BitIsSet (opcode, 10); 6054 add = BitIsSet (opcode, 9); 6055 wback = BitIsSet (opcode, 8); 6056 6057 // if BadReg(t) || (wback && n == t) then UNPREDICTABLE; 6058 if (BadReg (t) || (wback && (n == t))) 6059 return false; 6060 6061 break; 6062 6063 default: 6064 return false; 6065 } 6066 6067 uint32_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success); 6068 if (!success) 6069 return false; 6070 6071 addr_t address; 6072 addr_t offset_addr; 6073 6074 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32); 6075 if (add) 6076 offset_addr = Rn + imm32; 6077 else 6078 offset_addr = Rn - imm32; 6079 6080 // address = if index then offset_addr else R[n]; 6081 if (index) 6082 address = offset_addr; 6083 else 6084 address = Rn; 6085 6086 // R[t] = ZeroExtend(MemU[address,1], 32); 6087 Register base_reg; 6088 Register data_reg; 6089 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n); 6090 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + t); 6091 6092 EmulateInstruction::Context context; 6093 context.type = eContextRegisterLoad; 6094 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, address - Rn); 6095 6096 uint64_t data = MemURead (context, address, 1, 0, &success); 6097 if (!success) 6098 return false; 6099 6100 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data)) 6101 return false; 6102 6103 // if wback then R[n] = offset_addr; 6104 if (wback) 6105 { 6106 context.type = eContextAdjustBaseRegister; 6107 context.SetAddress (offset_addr); 6108 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr)) 6109 return false; 6110 } 6111 } 6112 return true; 6113} 6114 6115// LDRB (literal) calculates an address from the PC value and an immediate offset, loads a byte from memory, 6116// zero-extends it to form a 32-bit word and writes it to a register. 6117bool 6118EmulateInstructionARM::EmulateLDRBLiteral (const uint32_t opcode, const ARMEncoding encoding) 6119{ 6120#if 0 6121 if ConditionPassed() then 6122 EncodingSpecificOperations(); NullCheckIfThumbEE(15); 6123 base = Align(PC,4); 6124 address = if add then (base + imm32) else (base - imm32); 6125 R[t] = ZeroExtend(MemU[address,1], 32); 6126#endif 6127 6128 bool success = false; 6129 6130 if (ConditionPassed(opcode)) 6131 { 6132 uint32_t t; 6133 uint32_t imm32; 6134 bool add; 6135 switch (encoding) 6136 { 6137 case eEncodingT1: 6138 // if Rt == '1111' then SEE PLD; 6139 // t = UInt(Rt); imm32 = ZeroExtend(imm12, 32); add = (U == '1'); 6140 t = Bits32 (opcode, 15, 12); 6141 imm32 = Bits32 (opcode, 11, 0); 6142 add = BitIsSet (opcode, 23); 6143 6144 // if t == 13 then UNPREDICTABLE; 6145 if (t == 13) 6146 return false; 6147 6148 break; 6149 6150 case eEncodingA1: 6151 // t == UInt(Rt); imm32 = ZeroExtend(imm12, 32); add = (U == '1'); 6152 t = Bits32 (opcode, 15, 12); 6153 imm32 = Bits32 (opcode, 11, 0); 6154 add = BitIsSet (opcode, 23); 6155 6156 // if t == 15 then UNPREDICTABLE; 6157 if (t == 15) 6158 return false; 6159 break; 6160 6161 default: 6162 return false; 6163 } 6164 6165 // base = Align(PC,4); 6166 uint32_t pc_val = ReadCoreReg (PC_REG, &success); 6167 if (!success) 6168 return false; 6169 6170 uint32_t base = AlignPC (pc_val); 6171 6172 addr_t address; 6173 // address = if add then (base + imm32) else (base - imm32); 6174 if (add) 6175 address = base + imm32; 6176 else 6177 address = base - imm32; 6178 6179 // R[t] = ZeroExtend(MemU[address,1], 32); 6180 EmulateInstruction::Context context; 6181 context.type = eContextRelativeBranchImmediate; 6182 context.SetImmediate (address - base); 6183 6184 uint64_t data = MemURead (context, address, 1, 0, &success); 6185 if (!success) 6186 return false; 6187 6188 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data)) 6189 return false; 6190 } 6191 return true; 6192} 6193 6194// LDRB (register) calculates an address from a base register value and an offset rigister value, loads a byte from 6195// memory, zero-extends it to form a 32-bit word, and writes it to a register. The offset register value can 6196// optionally be shifted. 6197bool 6198EmulateInstructionARM::EmulateLDRBRegister (const uint32_t opcode, const ARMEncoding encoding) 6199{ 6200#if 0 6201 if ConditionPassed() then 6202 EncodingSpecificOperations(); NullCheckIfThumbEE(n); 6203 offset = Shift(R[m], shift_t, shift_n, APSR.C); 6204 offset_addr = if add then (R[n] + offset) else (R[n] - offset); 6205 address = if index then offset_addr else R[n]; 6206 R[t] = ZeroExtend(MemU[address,1],32); 6207 if wback then R[n] = offset_addr; 6208#endif 6209 6210 bool success = false; 6211 6212 if (ConditionPassed(opcode)) 6213 { 6214 uint32_t t; 6215 uint32_t n; 6216 uint32_t m; 6217 bool index; 6218 bool add; 6219 bool wback; 6220 ARM_ShifterType shift_t; 6221 uint32_t shift_n; 6222 6223 // EncodingSpecificOperations(); NullCheckIfThumbEE(n); 6224 switch (encoding) 6225 { 6226 case eEncodingT1: 6227 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm); 6228 t = Bits32 (opcode, 2, 0); 6229 n = Bits32 (opcode, 5, 3); 6230 m = Bits32 (opcode, 8, 6); 6231 6232 // index = TRUE; add = TRUE; wback = FALSE; 6233 index = true; 6234 add = true; 6235 wback = false; 6236 6237 // (shift_t, shift_n) = (SRType_LSL, 0); 6238 shift_t = SRType_LSL; 6239 shift_n = 0; 6240 break; 6241 6242 case eEncodingT2: 6243 // if Rt == '1111' then SEE PLD; 6244 // if Rn == '1111' then SEE LDRB (literal); 6245 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm); 6246 t = Bits32 (opcode, 15, 12); 6247 n = Bits32 (opcode, 19, 16); 6248 m = Bits32 (opcode, 3, 0); 6249 6250 // index = TRUE; add = TRUE; wback = FALSE; 6251 index = true; 6252 add = true; 6253 wback = false; 6254 6255 // (shift_t, shift_n) = (SRType_LSL, UInt(imm2)); 6256 shift_t = SRType_LSL; 6257 shift_n = Bits32 (opcode, 5, 4); 6258 6259 // if t == 13 || BadReg(m) then UNPREDICTABLE; 6260 if ((t == 13) || BadReg (m)) 6261 return false; 6262 break; 6263 6264 case eEncodingA1: 6265 { 6266 // if P == '0' && W == '1' then SEE LDRBT; 6267 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm); 6268 t = Bits32 (opcode, 15, 12); 6269 n = Bits32 (opcode, 19, 16); 6270 m = Bits32 (opcode, 3, 0); 6271 6272 // index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1'); 6273 index = BitIsSet (opcode, 24); 6274 add = BitIsSet (opcode, 23); 6275 wback = (BitIsClear (opcode, 24) || BitIsSet (opcode, 21)); 6276 6277 // (shift_t, shift_n) = DecodeImmShift(type, imm5); 6278 uint32_t type = Bits32 (opcode, 6, 5); 6279 uint32_t imm5 = Bits32 (opcode, 11, 7); 6280 shift_n = DecodeImmShift (type, imm5, shift_t); 6281 6282 // if t == 15 || m == 15 then UNPREDICTABLE; 6283 if ((t == 15) || (m == 15)) 6284 return false; 6285 6286 // if wback && (n == 15 || n == t) then UNPREDICTABLE; 6287 if (wback && ((n == 15) || (n == t))) 6288 return false; 6289 } 6290 break; 6291 6292 default: 6293 return false; 6294 } 6295 6296 addr_t offset_addr; 6297 addr_t address; 6298 6299 // offset = Shift(R[m], shift_t, shift_n, APSR.C); 6300 uint32_t Rm = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success); 6301 if (!success) 6302 return false; 6303 6304 addr_t offset = Shift (Rm, shift_t, shift_n, APSR_C); 6305 6306 // offset_addr = if add then (R[n] + offset) else (R[n] - offset); 6307 uint32_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success); 6308 if (!success) 6309 return false; 6310 6311 if (add) 6312 offset_addr = Rn + offset; 6313 else 6314 offset_addr = Rn - offset; 6315 6316 // address = if index then offset_addr else R[n]; 6317 if (index) 6318 address = offset_addr; 6319 else 6320 address = Rn; 6321 6322 // R[t] = ZeroExtend(MemU[address,1],32); 6323 Register base_reg; 6324 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n); 6325 6326 EmulateInstruction::Context context; 6327 context.type = eContextRegisterLoad; 6328 context.SetRegisterPlusOffset (base_reg, address - Rn); 6329 6330 uint64_t data = MemURead (context, address, 1, 0, &success); 6331 if (!success) 6332 return false; 6333 6334 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data)) 6335 return false; 6336 6337 // if wback then R[n] = offset_addr; 6338 if (wback) 6339 { 6340 context.type = eContextAdjustBaseRegister; 6341 context.SetAddress (offset_addr); 6342 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr)) 6343 return false; 6344 } 6345 } 6346 return true; 6347} 6348 6349// LDRH (immediate, Thumb) calculates an address from a base register value and an immediate offset, loads a 6350// halfword from memory, zero-extends it to form a 32-bit word, and writes it to a register. It can use offset, 6351// post-indexed, or pre-indexed addressing. 6352bool 6353EmulateInstructionARM::EmulateLDRHImmediate (const uint32_t opcode, const ARMEncoding encoding) 6354{ 6355#if 0 6356 if ConditionPassed() then 6357 EncodingSpecificOperations(); NullCheckIfThumbEE(n); 6358 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32); 6359 address = if index then offset_addr else R[n]; 6360 data = MemU[address,2]; 6361 if wback then R[n] = offset_addr; 6362 if UnalignedSupport() || address<0> = '0' then 6363 R[t] = ZeroExtend(data, 32); 6364 else // Can only apply before ARMv7 6365 R[t] = bits(32) UNKNOWN; 6366#endif 6367 6368 6369 bool success = false; 6370 6371 if (ConditionPassed(opcode)) 6372 { 6373 uint32_t t; 6374 uint32_t n; 6375 uint32_t imm32; 6376 bool index; 6377 bool add; 6378 bool wback; 6379 6380 // EncodingSpecificOperations(); NullCheckIfThumbEE(n); 6381 switch (encoding) 6382 { 6383 case eEncodingT1: 6384 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm5:'0', 32); 6385 t = Bits32 (opcode, 2, 0); 6386 n = Bits32 (opcode, 5, 3); 6387 imm32 = Bits32 (opcode, 10, 6) << 1; 6388 6389 // index = TRUE; add = TRUE; wback = FALSE; 6390 index = true; 6391 add = true; 6392 wback = false; 6393 6394 break; 6395 6396 case eEncodingT2: 6397 // if Rt == '1111' then SEE "Unallocated memory hints"; 6398 // if Rn == '1111' then SEE LDRH (literal); 6399 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32); 6400 t = Bits32 (opcode, 15, 12); 6401 n = Bits32 (opcode, 19, 16); 6402 imm32 = Bits32 (opcode, 11, 0); 6403 6404 // index = TRUE; add = TRUE; wback = FALSE; 6405 index = true; 6406 add = true; 6407 wback = false; 6408 6409 // if t == 13 then UNPREDICTABLE; 6410 if (t == 13) 6411 return false; 6412 break; 6413 6414 case eEncodingT3: 6415 // if Rn == '1111' then SEE LDRH (literal); 6416 // if Rt == '1111' && P == '1' && U == '0' && W == '0' then SEE "Unallocated memory hints"; 6417 // if P == '1' && U == '1' && W == '0' then SEE LDRHT; 6418 // if P == '0' && W == '0' then UNDEFINED; 6419 if (BitIsClear (opcode, 10) && BitIsClear (opcode, 8)) 6420 return false; 6421 6422 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32); 6423 t = Bits32 (opcode, 15, 12); 6424 n = Bits32 (opcode, 19, 16); 6425 imm32 = Bits32 (opcode, 7, 0); 6426 6427 // index = (P == '1'); add = (U == '1'); wback = (W == '1'); 6428 index = BitIsSet (opcode, 10); 6429 add = BitIsSet (opcode, 9); 6430 wback = BitIsSet (opcode, 8); 6431 6432 // if BadReg(t) || (wback && n == t) then UNPREDICTABLE; 6433 if (BadReg (t) || (wback && (n == t))) 6434 return false; 6435 break; 6436 6437 default: 6438 return false; 6439 } 6440 6441 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32); 6442 uint32_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success); 6443 if (!success) 6444 return false; 6445 6446 addr_t offset_addr; 6447 addr_t address; 6448 6449 if (add) 6450 offset_addr = Rn + imm32; 6451 else 6452 offset_addr = Rn - imm32; 6453 6454 // address = if index then offset_addr else R[n]; 6455 if (index) 6456 address = offset_addr; 6457 else 6458 address = Rn; 6459 6460 // data = MemU[address,2]; 6461 Register base_reg; 6462 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n); 6463 6464 EmulateInstruction::Context context; 6465 context.type = eContextRegisterLoad; 6466 context.SetRegisterPlusOffset (base_reg, address - Rn); 6467 6468 uint64_t data = MemURead (context, address, 2, 0, &success); 6469 if (!success) 6470 return false; 6471 6472 // if wback then R[n] = offset_addr; 6473 if (wback) 6474 { 6475 context.type = eContextAdjustBaseRegister; 6476 context.SetAddress (offset_addr); 6477 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr)) 6478 return false; 6479 } 6480 6481 // if UnalignedSupport() || address<0> = '0' then 6482 if (UnalignedSupport () || BitIsClear (address, 0)) 6483 { 6484 // R[t] = ZeroExtend(data, 32); 6485 context.type = eContextRegisterLoad; 6486 context.SetRegisterPlusOffset (base_reg, address - Rn); 6487 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data)) 6488 return false; 6489 } 6490 else // Can only apply before ARMv7 6491 { 6492 // R[t] = bits(32) UNKNOWN; 6493 WriteBits32Unknown (t); 6494 } 6495 } 6496 return true; 6497} 6498 6499// LDRH (literal) caculates an address from the PC value and an immediate offset, loads a halfword from memory, 6500// zero-extends it to form a 32-bit word, and writes it to a register. 6501bool 6502EmulateInstructionARM::EmulateLDRHLiteral (const uint32_t opcode, const ARMEncoding encoding) 6503{ 6504#if 0 6505 if ConditionPassed() then 6506 EncodingSpecificOperations(); NullCheckIfThumbEE(15); 6507 base = Align(PC,4); 6508 address = if add then (base + imm32) else (base - imm32); 6509 data = MemU[address,2]; 6510 if UnalignedSupport() || address<0> = '0' then 6511 R[t] = ZeroExtend(data, 32); 6512 else // Can only apply before ARMv7 6513 R[t] = bits(32) UNKNOWN; 6514#endif 6515 6516 bool success = false; 6517 6518 if (ConditionPassed(opcode)) 6519 { 6520 uint32_t t; 6521 uint32_t imm32; 6522 bool add; 6523 6524 // EncodingSpecificOperations(); NullCheckIfThumbEE(15); 6525 switch (encoding) 6526 { 6527 case eEncodingT1: 6528 // if Rt == '1111' then SEE "Unallocated memory hints"; 6529 // t = UInt(Rt); imm32 = ZeroExtend(imm12, 32); add = (U == '1'); 6530 t = Bits32 (opcode, 15, 12); 6531 imm32 = Bits32 (opcode, 11, 0); 6532 add = BitIsSet (opcode, 23); 6533 6534 // if t == 13 then UNPREDICTABLE; 6535 if (t == 13) 6536 return false; 6537 6538 break; 6539 6540 case eEncodingA1: 6541 { 6542 uint32_t imm4H = Bits32 (opcode, 11, 8); 6543 uint32_t imm4L = Bits32 (opcode, 3, 0); 6544 6545 // t == UInt(Rt); imm32 = ZeroExtend(imm4H:imm4L, 32); add = (U == '1'); 6546 t = Bits32 (opcode, 15, 12); 6547 imm32 = (imm4H << 4) | imm4L; 6548 add = BitIsSet (opcode, 23); 6549 6550 // if t == 15 then UNPREDICTABLE; 6551 if (t == 15) 6552 return false; 6553 break; 6554 } 6555 6556 default: 6557 return false; 6558 } 6559 6560 // base = Align(PC,4); 6561 uint64_t pc_value = ReadCoreReg (PC_REG, &success); 6562 if (!success) 6563 return false; 6564 6565 addr_t base = AlignPC (pc_value); 6566 addr_t address; 6567 6568 // address = if add then (base + imm32) else (base - imm32); 6569 if (add) 6570 address = base + imm32; 6571 else 6572 address = base - imm32; 6573 6574 // data = MemU[address,2]; 6575 Register base_reg; 6576 base_reg.SetRegister (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC); 6577 6578 EmulateInstruction::Context context; 6579 context.type = eContextRegisterLoad; 6580 context.SetRegisterPlusOffset (base_reg, address - base); 6581 6582 uint64_t data = MemURead (context, address, 2, 0, &success); 6583 if (!success) 6584 return false; 6585 6586 6587 // if UnalignedSupport() || address<0> = '0' then 6588 if (UnalignedSupport () || BitIsClear (address, 0)) 6589 { 6590 // R[t] = ZeroExtend(data, 32); 6591 context.type = eContextRegisterLoad; 6592 context.SetRegisterPlusOffset (base_reg, address - base); 6593 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data)) 6594 return false; 6595 6596 } 6597 else // Can only apply before ARMv7 6598 { 6599 // R[t] = bits(32) UNKNOWN; 6600 WriteBits32Unknown (t); 6601 } 6602 } 6603 return true; 6604} 6605 6606// LDRH (literal) calculates an address from a base register value and an offset register value, loads a halfword 6607// from memory, zero-extends it to form a 32-bit word, and writes it to a register. The offset register value can 6608// be shifted left by 0, 1, 2, or 3 bits. 6609bool 6610EmulateInstructionARM::EmulateLDRHRegister (const uint32_t opcode, const ARMEncoding encoding) 6611{ 6612#if 0 6613 if ConditionPassed() then 6614 EncodingSpecificOperations(); NullCheckIfThumbEE(n); 6615 offset = Shift(R[m], shift_t, shift_n, APSR.C); 6616 offset_addr = if add then (R[n] + offset) else (R[n] - offset); 6617 address = if index then offset_addr else R[n]; 6618 data = MemU[address,2]; 6619 if wback then R[n] = offset_addr; 6620 if UnalignedSupport() || address<0> = '0' then 6621 R[t] = ZeroExtend(data, 32); 6622 else // Can only apply before ARMv7 6623 R[t] = bits(32) UNKNOWN; 6624#endif 6625 6626 bool success = false; 6627 6628 if (ConditionPassed(opcode)) 6629 { 6630 uint32_t t; 6631 uint32_t n; 6632 uint32_t m; 6633 bool index; 6634 bool add; 6635 bool wback; 6636 ARM_ShifterType shift_t; 6637 uint32_t shift_n; 6638 6639 // EncodingSpecificOperations(); NullCheckIfThumbEE(n); 6640 switch (encoding) 6641 { 6642 case eEncodingT1: 6643 // if CurrentInstrSet() == InstrSet_ThumbEE then SEE "Modified operation in ThumbEE"; 6644 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm); 6645 t = Bits32 (opcode, 2, 0); 6646 n = Bits32 (opcode, 5, 3); 6647 m = Bits32 (opcode, 8, 6); 6648 6649 // index = TRUE; add = TRUE; wback = FALSE; 6650 index = true; 6651 add = true; 6652 wback = false; 6653 6654 // (shift_t, shift_n) = (SRType_LSL, 0); 6655 shift_t = SRType_LSL; 6656 shift_n = 0; 6657 6658 break; 6659 6660 case eEncodingT2: 6661 // if Rn == '1111' then SEE LDRH (literal); 6662 // if Rt == '1111' then SEE "Unallocated memory hints"; 6663 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm); 6664 t = Bits32 (opcode, 15, 12); 6665 n = Bits32 (opcode, 19, 16); 6666 m = Bits32 (opcode, 3, 0); 6667 6668 // index = TRUE; add = TRUE; wback = FALSE; 6669 index = true; 6670 add = true; 6671 wback = false; 6672 6673 // (shift_t, shift_n) = (SRType_LSL, UInt(imm2)); 6674 shift_t = SRType_LSL; 6675 shift_n = Bits32 (opcode, 5, 4); 6676 6677 // if t == 13 || BadReg(m) then UNPREDICTABLE; 6678 if ((t == 13) || BadReg (m)) 6679 return false; 6680 break; 6681 6682 case eEncodingA1: 6683 // if P == '0' && W == '1' then SEE LDRHT; 6684 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm); 6685 t = Bits32 (opcode, 15, 12); 6686 n = Bits32 (opcode, 19, 16); 6687 m = Bits32 (opcode, 3, 0); 6688 6689 // index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1'); 6690 index = BitIsSet (opcode, 24); 6691 add = BitIsSet (opcode, 23); 6692 wback = (BitIsClear (opcode, 24) || BitIsSet (opcode, 21)); 6693 6694 // (shift_t, shift_n) = (SRType_LSL, 0); 6695 shift_t = SRType_LSL; 6696 shift_n = 0; 6697 6698 // if t == 15 || m == 15 then UNPREDICTABLE; 6699 if ((t == 15) || (m == 15)) 6700 return false; 6701 6702 // if wback && (n == 15 || n == t) then UNPREDICTABLE; 6703 if (wback && ((n == 15) || (n == t))) 6704 return false; 6705 6706 break; 6707 6708 default: 6709 return false; 6710 } 6711 6712 // offset = Shift(R[m], shift_t, shift_n, APSR.C); 6713 6714 uint64_t Rm = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success); 6715 if (!success) 6716 return false; 6717 6718 addr_t offset = Shift (Rm, shift_t, shift_n, APSR_C); 6719 6720 addr_t offset_addr; 6721 addr_t address; 6722 6723 // offset_addr = if add then (R[n] + offset) else (R[n] - offset); 6724 uint64_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success); 6725 if (!success) 6726 return false; 6727 6728 if (add) 6729 offset_addr = Rn + offset; 6730 else 6731 offset_addr = Rn - offset; 6732 6733 // address = if index then offset_addr else R[n]; 6734 if (index) 6735 address = offset_addr; 6736 else 6737 address = Rn; 6738 6739 // data = MemU[address,2]; 6740 Register base_reg; 6741 Register offset_reg; 6742 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n); 6743 offset_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + m); 6744 6745 EmulateInstruction::Context context; 6746 context.type = eContextRegisterLoad; 6747 context.SetRegisterPlusIndirectOffset (base_reg, offset_reg); 6748 uint64_t data = MemURead (context, address, 2, 0, &success); 6749 if (!success) 6750 return false; 6751 6752 // if wback then R[n] = offset_addr; 6753 if (wback) 6754 { 6755 context.type = eContextAdjustBaseRegister; 6756 context.SetAddress (offset_addr); 6757 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr)) 6758 return false; 6759 } 6760 6761 // if UnalignedSupport() || address<0> = '0' then 6762 if (UnalignedSupport() || BitIsClear (address, 0)) 6763 { 6764 // R[t] = ZeroExtend(data, 32); 6765 context.type = eContextRegisterLoad; 6766 context.SetRegisterPlusIndirectOffset (base_reg, offset_reg); 6767 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data)) 6768 return false; 6769 } 6770 else // Can only apply before ARMv7 6771 { 6772 // R[t] = bits(32) UNKNOWN; 6773 WriteBits32Unknown (t); 6774 } 6775 } 6776 return true; 6777} 6778 6779// LDRSB (immediate) calculates an address from a base register value and an immediate offset, loads a byte from 6780// memory, sign-extends it to form a 32-bit word, and writes it to a register. It can use offset, post-indexed, 6781// or pre-indexed addressing. 6782bool 6783EmulateInstructionARM::EmulateLDRSBImmediate (const uint32_t opcode, const ARMEncoding encoding) 6784{ 6785#if 0 6786 if ConditionPassed() then 6787 EncodingSpecificOperations(); NullCheckIfThumbEE(n); 6788 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32); 6789 address = if index then offset_addr else R[n]; 6790 R[t] = SignExtend(MemU[address,1], 32); 6791 if wback then R[n] = offset_addr; 6792#endif 6793 6794 bool success = false; 6795 6796 if (ConditionPassed(opcode)) 6797 { 6798 uint32_t t; 6799 uint32_t n; 6800 uint32_t imm32; 6801 bool index; 6802 bool add; 6803 bool wback; 6804 6805 // EncodingSpecificOperations(); NullCheckIfThumbEE(n); 6806 switch (encoding) 6807 { 6808 case eEncodingT1: 6809 // if Rt == '1111' then SEE PLI; 6810 // if Rn == '1111' then SEE LDRSB (literal); 6811 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32); 6812 t = Bits32 (opcode, 15, 12); 6813 n = Bits32 (opcode, 19, 16); 6814 imm32 = Bits32 (opcode, 11, 0); 6815 6816 // index = TRUE; add = TRUE; wback = FALSE; 6817 index = true; 6818 add = true; 6819 wback = false; 6820 6821 // if t == 13 then UNPREDICTABLE; 6822 if (t == 13) 6823 return false; 6824 6825 break; 6826 6827 case eEncodingT2: 6828 // if Rt == '1111' && P == '1' && U == '0' && W == '0' then SEE PLI; 6829 // if Rn == '1111' then SEE LDRSB (literal); 6830 // if P == '1' && U == '1' && W == '0' then SEE LDRSBT; 6831 // if P == '0' && W == '0' then UNDEFINED; 6832 if (BitIsClear (opcode, 10) && BitIsClear (opcode, 8)) 6833 return false; 6834 6835 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32); 6836 t = Bits32 (opcode, 15, 12); 6837 n = Bits32 (opcode, 19, 16); 6838 imm32 = Bits32 (opcode, 7, 0); 6839 6840 // index = (P == '1'); add = (U == '1'); wback = (W == '1'); 6841 index = BitIsSet (opcode, 10); 6842 add = BitIsSet (opcode, 9); 6843 wback = BitIsSet (opcode, 8); 6844 6845 // if BadReg(t) || (wback && n == t) then UNPREDICTABLE; 6846 if (((t == 13) || ((t == 15) 6847 && (BitIsClear (opcode, 10) || BitIsSet (opcode, 9) || BitIsSet (opcode, 8)))) 6848 || (wback && (n == t))) 6849 return false; 6850 6851 break; 6852 6853 case eEncodingA1: 6854 { 6855 // if Rn == '1111' then SEE LDRSB (literal); 6856 // if P == '0' && W == '1' then SEE LDRSBT; 6857 // t == UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm4H:imm4L, 32); 6858 t = Bits32 (opcode, 15, 12); 6859 n = Bits32 (opcode, 19, 16); 6860 6861 uint32_t imm4H = Bits32 (opcode, 11, 8); 6862 uint32_t imm4L = Bits32 (opcode, 3, 0); 6863 imm32 = (imm4H << 4) | imm4L; 6864 6865 // index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1'); 6866 index = BitIsSet (opcode, 24); 6867 add = BitIsSet (opcode, 23); 6868 wback = (BitIsClear (opcode, 24) || BitIsSet (opcode, 21)); 6869 6870 // if t == 15 || (wback && n == t) then UNPREDICTABLE; 6871 if ((t == 15) || (wback && (n == t))) 6872 return false; 6873 6874 break; 6875 } 6876 6877 default: 6878 return false; 6879 } 6880 6881 uint64_t Rn = ReadCoreReg (n, &success); 6882 if (!success) 6883 return false; 6884 6885 addr_t offset_addr; 6886 addr_t address; 6887 6888 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32); 6889 if (add) 6890 offset_addr = Rn + imm32; 6891 else 6892 offset_addr = Rn - imm32; 6893 6894 // address = if index then offset_addr else R[n]; 6895 if (index) 6896 address = offset_addr; 6897 else 6898 address = Rn; 6899 6900 // R[t] = SignExtend(MemU[address,1], 32); 6901 Register base_reg; 6902 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n); 6903 6904 EmulateInstruction::Context context; 6905 context.type = eContextRegisterLoad; 6906 context.SetRegisterPlusOffset (base_reg, address - Rn); 6907 6908 uint64_t unsigned_data = MemURead (context, address, 1, 0, &success); 6909 if (!success) 6910 return false; 6911 6912 int64_t signed_data = llvm::SignExtend64<8>(unsigned_data); 6913 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, (uint64_t) signed_data)) 6914 return false; 6915 6916 // if wback then R[n] = offset_addr; 6917 if (wback) 6918 { 6919 context.type = eContextAdjustBaseRegister; 6920 context.SetAddress (offset_addr); 6921 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr)) 6922 return false; 6923 } 6924 } 6925 6926 return true; 6927} 6928 6929// LDRSB (literal) calculates an address from the PC value and an immediate offset, loads a byte from memory, 6930// sign-extends it to form a 32-bit word, and writes tit to a register. 6931bool 6932EmulateInstructionARM::EmulateLDRSBLiteral (const uint32_t opcode, const ARMEncoding encoding) 6933{ 6934#if 0 6935 if ConditionPassed() then 6936 EncodingSpecificOperations(); NullCheckIfThumbEE(15); 6937 base = Align(PC,4); 6938 address = if add then (base + imm32) else (base - imm32); 6939 R[t] = SignExtend(MemU[address,1], 32); 6940#endif 6941 6942 bool success = false; 6943 6944 if (ConditionPassed(opcode)) 6945 { 6946 uint32_t t; 6947 uint32_t imm32; 6948 bool add; 6949 6950 // EncodingSpecificOperations(); NullCheckIfThumbEE(15); 6951 switch (encoding) 6952 { 6953 case eEncodingT1: 6954 // if Rt == '1111' then SEE PLI; 6955 // t = UInt(Rt); imm32 = ZeroExtend(imm12, 32); add = (U == '1'); 6956 t = Bits32 (opcode, 15, 12); 6957 imm32 = Bits32 (opcode, 11, 0); 6958 add = BitIsSet (opcode, 23); 6959 6960 // if t == 13 then UNPREDICTABLE; 6961 if (t == 13) 6962 return false; 6963 6964 break; 6965 6966 case eEncodingA1: 6967 { 6968 // t == UInt(Rt); imm32 = ZeroExtend(imm4H:imm4L, 32); add = (U == '1'); 6969 t = Bits32 (opcode, 15, 12); 6970 uint32_t imm4H = Bits32 (opcode, 11, 8); 6971 uint32_t imm4L = Bits32 (opcode, 3, 0); 6972 imm32 = (imm4H << 4) | imm4L; 6973 add = BitIsSet (opcode, 23); 6974 6975 // if t == 15 then UNPREDICTABLE; 6976 if (t == 15) 6977 return false; 6978 6979 break; 6980 } 6981 6982 default: 6983 return false; 6984 } 6985 6986 // base = Align(PC,4); 6987 uint64_t pc_value = ReadCoreReg (PC_REG, &success); 6988 if (!success) 6989 return false; 6990 uint64_t base = AlignPC (pc_value); 6991 6992 // address = if add then (base + imm32) else (base - imm32); 6993 addr_t address; 6994 if (add) 6995 address = base + imm32; 6996 else 6997 address = base - imm32; 6998 6999 // R[t] = SignExtend(MemU[address,1], 32); 7000 Register base_reg; 7001 base_reg.SetRegister (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC); 7002 7003 EmulateInstruction::Context context; 7004 context.type = eContextRegisterLoad; 7005 context.SetRegisterPlusOffset (base_reg, address - base); 7006 7007 uint64_t unsigned_data = MemURead (context, address, 1, 0, &success); 7008 if (!success) 7009 return false; 7010 7011 int64_t signed_data = llvm::SignExtend64<8>(unsigned_data); 7012 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, (uint64_t) signed_data)) 7013 return false; 7014 } 7015 return true; 7016} 7017 7018// LDRSB (register) calculates an address from a base register value and an offset register value, loadsa byte from 7019// memory, sign-extends it to form a 32-bit word, and writes it to a register. The offset register value can be 7020// shifted left by 0, 1, 2, or 3 bits. 7021bool 7022EmulateInstructionARM::EmulateLDRSBRegister (const uint32_t opcode, const ARMEncoding encoding) 7023{ 7024#if 0 7025 if ConditionPassed() then 7026 EncodingSpecificOperations(); NullCheckIfThumbEE(n); 7027 offset = Shift(R[m], shift_t, shift_n, APSR.C); 7028 offset_addr = if add then (R[n] + offset) else (R[n] - offset); 7029 address = if index then offset_addr else R[n]; 7030 R[t] = SignExtend(MemU[address,1], 32); 7031 if wback then R[n] = offset_addr; 7032#endif 7033 7034 bool success = false; 7035 7036 if (ConditionPassed(opcode)) 7037 { 7038 uint32_t t; 7039 uint32_t n; 7040 uint32_t m; 7041 bool index; 7042 bool add; 7043 bool wback; 7044 ARM_ShifterType shift_t; 7045 uint32_t shift_n; 7046 7047 // EncodingSpecificOperations(); NullCheckIfThumbEE(n); 7048 switch (encoding) 7049 { 7050 case eEncodingT1: 7051 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm); 7052 t = Bits32 (opcode, 2, 0); 7053 n = Bits32 (opcode, 5, 3); 7054 m = Bits32 (opcode, 8, 6); 7055 7056 // index = TRUE; add = TRUE; wback = FALSE; 7057 index = true; 7058 add = true; 7059 wback = false; 7060 7061 // (shift_t, shift_n) = (SRType_LSL, 0); 7062 shift_t = SRType_LSL; 7063 shift_n = 0; 7064 7065 break; 7066 7067 case eEncodingT2: 7068 // if Rt == '1111' then SEE PLI; 7069 // if Rn == '1111' then SEE LDRSB (literal); 7070 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm); 7071 t = Bits32 (opcode, 15, 12); 7072 n = Bits32 (opcode, 19, 16); 7073 m = Bits32 (opcode, 3, 0); 7074 7075 // index = TRUE; add = TRUE; wback = FALSE; 7076 index = true; 7077 add = true; 7078 wback = false; 7079 7080 // (shift_t, shift_n) = (SRType_LSL, UInt(imm2)); 7081 shift_t = SRType_LSL; 7082 shift_n = Bits32 (opcode, 5, 4); 7083 7084 // if t == 13 || BadReg(m) then UNPREDICTABLE; 7085 if ((t == 13) || BadReg (m)) 7086 return false; 7087 break; 7088 7089 case eEncodingA1: 7090 // if P == '0' && W == '1' then SEE LDRSBT; 7091 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm); 7092 t = Bits32 (opcode, 15, 12); 7093 n = Bits32 (opcode, 19, 16); 7094 m = Bits32 (opcode, 3, 0); 7095 7096 // index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1'); 7097 index = BitIsSet (opcode, 24); 7098 add = BitIsSet (opcode, 23); 7099 wback = BitIsClear (opcode, 24) || BitIsSet (opcode, 21); 7100 7101 // (shift_t, shift_n) = (SRType_LSL, 0); 7102 shift_t = SRType_LSL; 7103 shift_n = 0; 7104 7105 // if t == 15 || m == 15 then UNPREDICTABLE; 7106 if ((t == 15) || (m == 15)) 7107 return false; 7108 7109 // if wback && (n == 15 || n == t) then UNPREDICTABLE; 7110 if (wback && ((n == 15) || (n == t))) 7111 return false; 7112 break; 7113 7114 default: 7115 return false; 7116 } 7117 7118 uint64_t Rm = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success); 7119 if (!success) 7120 return false; 7121 7122 // offset = Shift(R[m], shift_t, shift_n, APSR.C); 7123 addr_t offset = Shift (Rm, shift_t, shift_n, APSR_C); 7124 7125 addr_t offset_addr; 7126 addr_t address; 7127 7128 // offset_addr = if add then (R[n] + offset) else (R[n] - offset); 7129 uint64_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success); 7130 if (!success) 7131 return false; 7132 7133 if (add) 7134 offset_addr = Rn + offset; 7135 else 7136 offset_addr = Rn - offset; 7137 7138 // address = if index then offset_addr else R[n]; 7139 if (index) 7140 address = offset_addr; 7141 else 7142 address = Rn; 7143 7144 // R[t] = SignExtend(MemU[address,1], 32); 7145 Register base_reg; 7146 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n); 7147 Register offset_reg; 7148 offset_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + m); 7149 7150 EmulateInstruction::Context context; 7151 context.type = eContextRegisterLoad; 7152 context.SetRegisterPlusIndirectOffset (base_reg, offset_reg); 7153 7154 uint64_t unsigned_data = MemURead (context, address, 1, 0, &success); 7155 if (!success) 7156 return false; 7157 7158 int64_t signed_data = llvm::SignExtend64<8>(unsigned_data); 7159 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, (uint64_t) signed_data)) 7160 return false; 7161 7162 // if wback then R[n] = offset_addr; 7163 if (wback) 7164 { 7165 context.type = eContextAdjustBaseRegister; 7166 context.SetAddress (offset_addr); 7167 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr)) 7168 return false; 7169 } 7170 } 7171 return true; 7172} 7173 7174// LDRSH (immediate) calculates an address from a base register value and an immediate offset, loads a halfword from 7175// memory, sign-extends it to form a 32-bit word, and writes it to a register. It can use offset, post-indexed, or 7176// pre-indexed addressing. 7177bool 7178EmulateInstructionARM::EmulateLDRSHImmediate (const uint32_t opcode, const ARMEncoding encoding) 7179{ 7180#if 0 7181 if ConditionPassed() then 7182 EncodingSpecificOperations(); NullCheckIfThumbEE(n); 7183 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32); 7184 address = if index then offset_addr else R[n]; 7185 data = MemU[address,2]; 7186 if wback then R[n] = offset_addr; 7187 if UnalignedSupport() || address<0> = '0' then 7188 R[t] = SignExtend(data, 32); 7189 else // Can only apply before ARMv7 7190 R[t] = bits(32) UNKNOWN; 7191#endif 7192 7193 bool success = false; 7194 7195 if (ConditionPassed(opcode)) 7196 { 7197 uint32_t t; 7198 uint32_t n; 7199 uint32_t imm32; 7200 bool index; 7201 bool add; 7202 bool wback; 7203 7204 // EncodingSpecificOperations(); NullCheckIfThumbEE(n); 7205 switch (encoding) 7206 { 7207 case eEncodingT1: 7208 // if Rn == '1111' then SEE LDRSH (literal); 7209 // if Rt == '1111' then SEE "Unallocated memory hints"; 7210 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32); 7211 t = Bits32 (opcode, 15, 12); 7212 n = Bits32 (opcode, 19, 16); 7213 imm32 = Bits32 (opcode, 11, 0); 7214 7215 // index = TRUE; add = TRUE; wback = FALSE; 7216 index = true; 7217 add = true; 7218 wback = false; 7219 7220 // if t == 13 then UNPREDICTABLE; 7221 if (t == 13) 7222 return false; 7223 7224 break; 7225 7226 case eEncodingT2: 7227 // if Rn == '1111' then SEE LDRSH (literal); 7228 // if Rt == '1111' && P == '1' && U == '0' && W == '0' then SEE "Unallocated memory hints"; 7229 // if P == '1' && U == '1' && W == '0' then SEE LDRSHT; 7230 // if P == '0' && W == '0' then UNDEFINED; 7231 if (BitIsClear (opcode, 10) && BitIsClear (opcode, 8)) 7232 return false; 7233 7234 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32); 7235 t = Bits32 (opcode, 15, 12); 7236 n = Bits32 (opcode, 19, 16); 7237 imm32 = Bits32 (opcode, 7, 0); 7238 7239 // index = (P == '1'); add = (U == '1'); wback = (W == '1'); 7240 index = BitIsSet (opcode, 10); 7241 add = BitIsSet (opcode, 9); 7242 wback = BitIsSet (opcode, 8); 7243 7244 // if BadReg(t) || (wback && n == t) then UNPREDICTABLE; 7245 if (BadReg (t) || (wback && (n == t))) 7246 return false; 7247 7248 break; 7249 7250 case eEncodingA1: 7251 { 7252 // if Rn == '1111' then SEE LDRSH (literal); 7253 // if P == '0' && W == '1' then SEE LDRSHT; 7254 // t == UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm4H:imm4L, 32); 7255 t = Bits32 (opcode, 15, 12); 7256 n = Bits32 (opcode, 19, 16); 7257 uint32_t imm4H = Bits32 (opcode, 11,8); 7258 uint32_t imm4L = Bits32 (opcode, 3, 0); 7259 imm32 = (imm4H << 4) | imm4L; 7260 7261 // index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1'); 7262 index = BitIsSet (opcode, 24); 7263 add = BitIsSet (opcode, 23); 7264 wback = BitIsClear (opcode, 24) || BitIsSet (opcode, 21); 7265 7266 // if t == 15 || (wback && n == t) then UNPREDICTABLE; 7267 if ((t == 15) || (wback && (n == t))) 7268 return false; 7269 7270 break; 7271 } 7272 7273 default: 7274 return false; 7275 } 7276 7277 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32); 7278 uint64_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success); 7279 if (!success) 7280 return false; 7281 7282 addr_t offset_addr; 7283 if (add) 7284 offset_addr = Rn + imm32; 7285 else 7286 offset_addr = Rn - imm32; 7287 7288 // address = if index then offset_addr else R[n]; 7289 addr_t address; 7290 if (index) 7291 address = offset_addr; 7292 else 7293 address = Rn; 7294 7295 // data = MemU[address,2]; 7296 Register base_reg; 7297 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n); 7298 7299 EmulateInstruction::Context context; 7300 context.type = eContextRegisterLoad; 7301 context.SetRegisterPlusOffset (base_reg, address - Rn); 7302 7303 uint64_t data = MemURead (context, address, 2, 0, &success); 7304 if (!success) 7305 return false; 7306 7307 // if wback then R[n] = offset_addr; 7308 if (wback) 7309 { 7310 context.type = eContextAdjustBaseRegister; 7311 context.SetAddress (offset_addr); 7312 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr)) 7313 return false; 7314 } 7315 7316 // if UnalignedSupport() || address<0> = '0' then 7317 if (UnalignedSupport() || BitIsClear (address, 0)) 7318 { 7319 // R[t] = SignExtend(data, 32); 7320 int64_t signed_data = llvm::SignExtend64<16>(data); 7321 context.type = eContextRegisterLoad; 7322 context.SetRegisterPlusOffset (base_reg, address - Rn); 7323 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, (uint64_t) signed_data)) 7324 return false; 7325 } 7326 else // Can only apply before ARMv7 7327 { 7328 // R[t] = bits(32) UNKNOWN; 7329 WriteBits32Unknown (t); 7330 } 7331 } 7332 return true; 7333} 7334 7335// LDRSH (literal) calculates an address from the PC value and an immediate offset, loads a halfword from memory, 7336// sign-extends it to from a 32-bit word, and writes it to a register. 7337bool 7338EmulateInstructionARM::EmulateLDRSHLiteral (const uint32_t opcode, const ARMEncoding encoding) 7339{ 7340#if 0 7341 if ConditionPassed() then 7342 EncodingSpecificOperations(); NullCheckIfThumbEE(15); 7343 base = Align(PC,4); 7344 address = if add then (base + imm32) else (base - imm32); 7345 data = MemU[address,2]; 7346 if UnalignedSupport() || address<0> = '0' then 7347 R[t] = SignExtend(data, 32); 7348 else // Can only apply before ARMv7 7349 R[t] = bits(32) UNKNOWN; 7350#endif 7351 7352 bool success = false; 7353 7354 if (ConditionPassed(opcode)) 7355 { 7356 uint32_t t; 7357 uint32_t imm32; 7358 bool add; 7359 7360 // EncodingSpecificOperations(); NullCheckIfThumbEE(15); 7361 switch (encoding) 7362 { 7363 case eEncodingT1: 7364 // if Rt == '1111' then SEE "Unallocated memory hints"; 7365 // t = UInt(Rt); imm32 = ZeroExtend(imm12, 32); add = (U == '1'); 7366 t = Bits32 (opcode, 15, 12); 7367 imm32 = Bits32 (opcode, 11, 0); 7368 add = BitIsSet (opcode, 23); 7369 7370 // if t == 13 then UNPREDICTABLE; 7371 if (t == 13) 7372 return false; 7373 7374 break; 7375 7376 case eEncodingA1: 7377 { 7378 // t == UInt(Rt); imm32 = ZeroExtend(imm4H:imm4L, 32); add = (U == '1'); 7379 t = Bits32 (opcode, 15, 12); 7380 uint32_t imm4H = Bits32 (opcode, 11, 8); 7381 uint32_t imm4L = Bits32 (opcode, 3, 0); 7382 imm32 = (imm4H << 4) | imm4L; 7383 add = BitIsSet (opcode, 23); 7384 7385 // if t == 15 then UNPREDICTABLE; 7386 if (t == 15) 7387 return false; 7388 7389 break; 7390 } 7391 default: 7392 return false; 7393 } 7394 7395 // base = Align(PC,4); 7396 uint64_t pc_value = ReadCoreReg (PC_REG, &success); 7397 if (!success) 7398 return false; 7399 7400 uint64_t base = AlignPC (pc_value); 7401 7402 addr_t address; 7403 // address = if add then (base + imm32) else (base - imm32); 7404 if (add) 7405 address = base + imm32; 7406 else 7407 address = base - imm32; 7408 7409 // data = MemU[address,2]; 7410 Register base_reg; 7411 base_reg.SetRegister (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC); 7412 7413 EmulateInstruction::Context context; 7414 context.type = eContextRegisterLoad; 7415 context.SetRegisterPlusOffset (base_reg, imm32); 7416 7417 uint64_t data = MemURead (context, address, 2, 0, &success); 7418 if (!success) 7419 return false; 7420 7421 // if UnalignedSupport() || address<0> = '0' then 7422 if (UnalignedSupport() || BitIsClear (address, 0)) 7423 { 7424 // R[t] = SignExtend(data, 32); 7425 int64_t signed_data = llvm::SignExtend64<16>(data); 7426 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, (uint64_t) signed_data)) 7427 return false; 7428 } 7429 else // Can only apply before ARMv7 7430 { 7431 // R[t] = bits(32) UNKNOWN; 7432 WriteBits32Unknown (t); 7433 } 7434 } 7435 return true; 7436} 7437 7438// LDRSH (register) calculates an address from a base register value and an offset register value, loads a halfword 7439// from memory, sign-extends it to form a 32-bit word, and writes it to a register. The offset register value can be 7440// shifted left by 0, 1, 2, or 3 bits. 7441bool 7442EmulateInstructionARM::EmulateLDRSHRegister (const uint32_t opcode, const ARMEncoding encoding) 7443{ 7444#if 0 7445 if ConditionPassed() then 7446 EncodingSpecificOperations(); NullCheckIfThumbEE(n); 7447 offset = Shift(R[m], shift_t, shift_n, APSR.C); 7448 offset_addr = if add then (R[n] + offset) else (R[n] - offset); 7449 address = if index then offset_addr else R[n]; 7450 data = MemU[address,2]; 7451 if wback then R[n] = offset_addr; 7452 if UnalignedSupport() || address<0> = '0' then 7453 R[t] = SignExtend(data, 32); 7454 else // Can only apply before ARMv7 7455 R[t] = bits(32) UNKNOWN; 7456#endif 7457 7458 bool success = false; 7459 7460 if (ConditionPassed(opcode)) 7461 { 7462 uint32_t t; 7463 uint32_t n; 7464 uint32_t m; 7465 bool index; 7466 bool add; 7467 bool wback; 7468 ARM_ShifterType shift_t; 7469 uint32_t shift_n; 7470 7471 // EncodingSpecificOperations(); NullCheckIfThumbEE(n); 7472 switch (encoding) 7473 { 7474 case eEncodingT1: 7475 // if CurrentInstrSet() == InstrSet_ThumbEE then SEE "Modified operation in ThumbEE"; 7476 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm); 7477 t = Bits32 (opcode, 2, 0); 7478 n = Bits32 (opcode, 5, 3); 7479 m = Bits32 (opcode, 8, 6); 7480 7481 // index = TRUE; add = TRUE; wback = FALSE; 7482 index = true; 7483 add = true; 7484 wback = false; 7485 7486 // (shift_t, shift_n) = (SRType_LSL, 0); 7487 shift_t = SRType_LSL; 7488 shift_n = 0; 7489 7490 break; 7491 7492 case eEncodingT2: 7493 // if Rn == '1111' then SEE LDRSH (literal); 7494 // if Rt == '1111' then SEE "Unallocated memory hints"; 7495 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm); 7496 t = Bits32 (opcode, 15, 12); 7497 n = Bits32 (opcode, 19, 16); 7498 m = Bits32 (opcode, 3, 0); 7499 7500 // index = TRUE; add = TRUE; wback = FALSE; 7501 index = true; 7502 add = true; 7503 wback = false; 7504 7505 // (shift_t, shift_n) = (SRType_LSL, UInt(imm2)); 7506 shift_t = SRType_LSL; 7507 shift_n = Bits32 (opcode, 5, 4); 7508 7509 // if t == 13 || BadReg(m) then UNPREDICTABLE; 7510 if ((t == 13) || BadReg (m)) 7511 return false; 7512 7513 break; 7514 7515 case eEncodingA1: 7516 // if P == '0' && W == '1' then SEE LDRSHT; 7517 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm); 7518 t = Bits32 (opcode, 15, 12); 7519 n = Bits32 (opcode, 19, 16); 7520 m = Bits32 (opcode, 3, 0); 7521 7522 // index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1'); 7523 index = BitIsSet (opcode, 24); 7524 add = BitIsSet (opcode, 23); 7525 wback = BitIsClear (opcode, 24) || BitIsSet (opcode, 21); 7526 7527 // (shift_t, shift_n) = (SRType_LSL, 0); 7528 shift_t = SRType_LSL; 7529 shift_n = 0; 7530 7531 // if t == 15 || m == 15 then UNPREDICTABLE; 7532 if ((t == 15) || (m == 15)) 7533 return false; 7534 7535 // if wback && (n == 15 || n == t) then UNPREDICTABLE; 7536 if (wback && ((n == 15) || (n == t))) 7537 return false; 7538 7539 break; 7540 7541 default: 7542 break; 7543 } 7544 7545 uint64_t Rm = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success); 7546 if (!success) 7547 return false; 7548 7549 uint64_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success); 7550 if (!success) 7551 return false; 7552 7553 // offset = Shift(R[m], shift_t, shift_n, APSR.C); 7554 addr_t offset = Shift (Rm, shift_t, shift_n, APSR_C); 7555 7556 addr_t offset_addr; 7557 addr_t address; 7558 7559 // offset_addr = if add then (R[n] + offset) else (R[n] - offset); 7560 if (add) 7561 offset_addr = Rn + offset; 7562 else 7563 offset_addr = Rn - offset; 7564 7565 // address = if index then offset_addr else R[n]; 7566 if (index) 7567 address = offset_addr; 7568 else 7569 address = Rn; 7570 7571 // data = MemU[address,2]; 7572 Register base_reg; 7573 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n); 7574 7575 Register offset_reg; 7576 offset_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + m); 7577 7578 EmulateInstruction::Context context; 7579 context.type = eContextRegisterLoad; 7580 context.SetRegisterPlusIndirectOffset (base_reg, offset_reg); 7581 7582 uint64_t data = MemURead (context, address, 2, 0, &success); 7583 if (!success) 7584 return false; 7585 7586 // if wback then R[n] = offset_addr; 7587 if (wback) 7588 { 7589 context.type = eContextAdjustBaseRegister; 7590 context.SetAddress (offset_addr); 7591 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr)) 7592 return false; 7593 } 7594 7595 // if UnalignedSupport() || address<0> = '0' then 7596 if (UnalignedSupport() || BitIsClear (address, 0)) 7597 { 7598 // R[t] = SignExtend(data, 32); 7599 context.type = eContextRegisterLoad; 7600 context.SetRegisterPlusIndirectOffset (base_reg, offset_reg); 7601 7602 int64_t signed_data = llvm::SignExtend64<16>(data); 7603 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, (uint64_t) signed_data)) 7604 return false; 7605 } 7606 else // Can only apply before ARMv7 7607 { 7608 // R[t] = bits(32) UNKNOWN; 7609 WriteBits32Unknown (t); 7610 } 7611 } 7612 return true; 7613} 7614 7615// SXTB extracts an 8-bit value from a register, sign-extends it to 32 bits, and writes the result to the destination 7616// register. You can specifiy a rotation by 0, 8, 16, or 24 bits before extracting the 8-bit value. 7617bool 7618EmulateInstructionARM::EmulateSXTB (const uint32_t opcode, const ARMEncoding encoding) 7619{ 7620#if 0 7621 if ConditionPassed() then 7622 EncodingSpecificOperations(); 7623 rotated = ROR(R[m], rotation); 7624 R[d] = SignExtend(rotated<7:0>, 32); 7625#endif 7626 7627 bool success = false; 7628 7629 if (ConditionPassed(opcode)) 7630 { 7631 uint32_t d; 7632 uint32_t m; 7633 uint32_t rotation; 7634 7635 // EncodingSpecificOperations(); 7636 switch (encoding) 7637 { 7638 case eEncodingT1: 7639 // d = UInt(Rd); m = UInt(Rm); rotation = 0; 7640 d = Bits32 (opcode, 2, 0); 7641 m = Bits32 (opcode, 5, 3); 7642 rotation = 0; 7643 7644 break; 7645 7646 case eEncodingT2: 7647 // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:'000'); 7648 d = Bits32 (opcode, 11, 8); 7649 m = Bits32 (opcode, 3, 0); 7650 rotation = Bits32 (opcode, 5, 4) << 3; 7651 7652 // if BadReg(d) || BadReg(m) then UNPREDICTABLE; 7653 if (BadReg (d) || BadReg (m)) 7654 return false; 7655 7656 break; 7657 7658 case eEncodingA1: 7659 // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:'000'); 7660 d = Bits32 (opcode, 15, 12); 7661 m = Bits32 (opcode, 3, 0); 7662 rotation = Bits32 (opcode, 11, 10) << 3; 7663 7664 // if d == 15 || m == 15 then UNPREDICTABLE; 7665 if ((d == 15) || (m == 15)) 7666 return false; 7667 7668 break; 7669 7670 default: 7671 return false; 7672 } 7673 7674 uint64_t Rm = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success); 7675 if (!success) 7676 return false; 7677 7678 // rotated = ROR(R[m], rotation); 7679 uint64_t rotated = ROR (Rm, rotation); 7680 7681 // R[d] = SignExtend(rotated<7:0>, 32); 7682 int64_t data = llvm::SignExtend64<8>(rotated); 7683 7684 Register source_reg; 7685 source_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + m); 7686 7687 EmulateInstruction::Context context; 7688 context.type = eContextRegisterLoad; 7689 context.SetRegister (source_reg); 7690 7691 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + d, (uint64_t) data)) 7692 return false; 7693 } 7694 return true; 7695} 7696 7697// SXTH extracts a 16-bit value from a register, sign-extends it to 32 bits, and writes the result to the destination 7698// register. You can specify a rotation by 0, 8, 16, or 24 bits before extracting the 16-bit value. 7699bool 7700EmulateInstructionARM::EmulateSXTH (const uint32_t opcode, const ARMEncoding encoding) 7701{ 7702#if 0 7703 if ConditionPassed() then 7704 EncodingSpecificOperations(); 7705 rotated = ROR(R[m], rotation); 7706 R[d] = SignExtend(rotated<15:0>, 32); 7707#endif 7708 7709 bool success = false; 7710 7711 if (ConditionPassed(opcode)) 7712 { 7713 uint32_t d; 7714 uint32_t m; 7715 uint32_t rotation; 7716 7717 // EncodingSpecificOperations(); 7718 switch (encoding) 7719 { 7720 case eEncodingT1: 7721 // d = UInt(Rd); m = UInt(Rm); rotation = 0; 7722 d = Bits32 (opcode, 2, 0); 7723 m = Bits32 (opcode, 5, 3); 7724 rotation = 0; 7725 7726 break; 7727 7728 case eEncodingT2: 7729 // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:'000'); 7730 d = Bits32 (opcode, 11, 8); 7731 m = Bits32 (opcode, 3, 0); 7732 rotation = Bits32 (opcode, 5, 4) << 3; 7733 7734 // if BadReg(d) || BadReg(m) then UNPREDICTABLE; 7735 if (BadReg (d) || BadReg (m)) 7736 return false; 7737 7738 break; 7739 7740 case eEncodingA1: 7741 // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:'000'); 7742 d = Bits32 (opcode, 15, 12); 7743 m = Bits32 (opcode, 3, 0); 7744 rotation = Bits32 (opcode, 11, 10) << 3; 7745 7746 // if d == 15 || m == 15 then UNPREDICTABLE; 7747 if ((d == 15) || (m == 15)) 7748 return false; 7749 7750 break; 7751 7752 default: 7753 return false; 7754 } 7755 7756 uint64_t Rm = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success); 7757 if (!success) 7758 return false; 7759 7760 // rotated = ROR(R[m], rotation); 7761 uint64_t rotated = ROR (Rm, rotation); 7762 7763 // R[d] = SignExtend(rotated<15:0>, 32); 7764 Register source_reg; 7765 source_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + m); 7766 7767 EmulateInstruction::Context context; 7768 context.type = eContextRegisterLoad; 7769 context.SetRegister (source_reg); 7770 7771 int64_t data = llvm::SignExtend64<16> (rotated); 7772 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + d, (uint64_t) data)) 7773 return false; 7774 } 7775 7776 return true; 7777} 7778 7779// UXTB extracts an 8-bit value from a register, zero-extneds it to 32 bits, and writes the result to the destination 7780// register. You can specify a rotation by 0, 8, 16, or 24 bits before extracting the 8-bit value. 7781bool 7782EmulateInstructionARM::EmulateUXTB (const uint32_t opcode, const ARMEncoding encoding) 7783{ 7784#if 0 7785 if ConditionPassed() then 7786 EncodingSpecificOperations(); 7787 rotated = ROR(R[m], rotation); 7788 R[d] = ZeroExtend(rotated<7:0>, 32); 7789#endif 7790 7791 bool success = false; 7792 7793 if (ConditionPassed(opcode)) 7794 { 7795 uint32_t d; 7796 uint32_t m; 7797 uint32_t rotation; 7798 7799 // EncodingSpecificOperations(); 7800 switch (encoding) 7801 { 7802 case eEncodingT1: 7803 // d = UInt(Rd); m = UInt(Rm); rotation = 0; 7804 d = Bits32 (opcode, 2, 0); 7805 m = Bits32 (opcode, 5, 3); 7806 rotation = 0; 7807 7808 break; 7809 7810 case eEncodingT2: 7811 // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:'000'); 7812 d = Bits32 (opcode, 11, 8); 7813 m = Bits32 (opcode, 3, 0); 7814 rotation = Bits32 (opcode, 5, 4) << 3; 7815 7816 // if BadReg(d) || BadReg(m) then UNPREDICTABLE; 7817 if (BadReg (d) || BadReg (m)) 7818 return false; 7819 7820 break; 7821 7822 case eEncodingA1: 7823 // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:'000'); 7824 d = Bits32 (opcode, 15, 12); 7825 m = Bits32 (opcode, 3, 0); 7826 rotation = Bits32 (opcode, 11, 10) << 3; 7827 7828 // if d == 15 || m == 15 then UNPREDICTABLE; 7829 if ((d == 15) || (m == 15)) 7830 return false; 7831 7832 break; 7833 7834 default: 7835 return false; 7836 } 7837 7838 uint64_t Rm = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success); 7839 if (!success) 7840 return false; 7841 7842 // rotated = ROR(R[m], rotation); 7843 uint64_t rotated = ROR (Rm, rotation); 7844 7845 // R[d] = ZeroExtend(rotated<7:0>, 32); 7846 Register source_reg; 7847 source_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + m); 7848 7849 EmulateInstruction::Context context; 7850 context.type = eContextRegisterLoad; 7851 context.SetRegister (source_reg); 7852 7853 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + d, Bits32 (rotated, 7, 0))) 7854 return false; 7855 } 7856 return true; 7857} 7858 7859// UXTH extracts a 16-bit value from a register, zero-extends it to 32 bits, and writes the result to the destination 7860// register. You can specify a rotation by 0, 8, 16, or 24 bits before extracting the 16-bit value. 7861bool 7862EmulateInstructionARM::EmulateUXTH (const uint32_t opcode, const ARMEncoding encoding) 7863{ 7864#if 0 7865 if ConditionPassed() then 7866 EncodingSpecificOperations(); 7867 rotated = ROR(R[m], rotation); 7868 R[d] = ZeroExtend(rotated<15:0>, 32); 7869#endif 7870 7871 bool success = false; 7872 7873 if (ConditionPassed(opcode)) 7874 { 7875 uint32_t d; 7876 uint32_t m; 7877 uint32_t rotation; 7878 7879 switch (encoding) 7880 { 7881 case eEncodingT1: 7882 // d = UInt(Rd); m = UInt(Rm); rotation = 0; 7883 d = Bits32 (opcode, 2, 0); 7884 m = Bits32 (opcode, 5, 3); 7885 rotation = 0; 7886 7887 break; 7888 7889 case eEncodingT2: 7890 // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:'000'); 7891 d = Bits32 (opcode, 11, 8); 7892 m = Bits32 (opcode, 3, 0); 7893 rotation = Bits32 (opcode, 5, 4) << 3; 7894 7895 // if BadReg(d) || BadReg(m) then UNPREDICTABLE; 7896 if (BadReg (d) || BadReg (m)) 7897 return false; 7898 7899 break; 7900 7901 case eEncodingA1: 7902 // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:'000'); 7903 d = Bits32 (opcode, 15, 12); 7904 m = Bits32 (opcode, 3, 0); 7905 rotation = Bits32 (opcode, 11, 10) << 3; 7906 7907 // if d == 15 || m == 15 then UNPREDICTABLE; 7908 if ((d == 15) || (m == 15)) 7909 return false; 7910 7911 break; 7912 7913 default: 7914 return false; 7915 } 7916 7917 uint64_t Rm = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success); 7918 if (!success) 7919 return false; 7920 7921 // rotated = ROR(R[m], rotation); 7922 uint64_t rotated = ROR (Rm, rotation); 7923 7924 // R[d] = ZeroExtend(rotated<15:0>, 32); 7925 Register source_reg; 7926 source_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + m); 7927 7928 EmulateInstruction::Context context; 7929 context.type = eContextRegisterLoad; 7930 context.SetRegister (source_reg); 7931 7932 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + d, Bits32 (rotated, 15, 0))) 7933 return false; 7934 } 7935 return true; 7936} 7937 7938// RFE (Return From Exception) loads the PC and the CPSR from the word at the specified address and the following 7939// word respectively. 7940bool 7941EmulateInstructionARM::EmulateRFE (const uint32_t opcode, const ARMEncoding encoding) 7942{ 7943#if 0 7944 if ConditionPassed() then 7945 EncodingSpecificOperations(); 7946 if !CurrentModeIsPrivileged() || CurrentInstrSet() == InstrSet_ThumbEE then 7947 UNPREDICTABLE; 7948 else 7949 address = if increment then R[n] else R[n]-8; 7950 if wordhigher then address = address+4; 7951 CPSRWriteByInstr(MemA[address+4,4], '1111', TRUE); 7952 BranchWritePC(MemA[address,4]); 7953 if wback then R[n] = if increment then R[n]+8 else R[n]-8; 7954#endif 7955 7956 bool success = false; 7957 7958 if (ConditionPassed(opcode)) 7959 { 7960 uint32_t n; 7961 bool wback; 7962 bool increment; 7963 bool wordhigher; 7964 7965 // EncodingSpecificOperations(); 7966 switch (encoding) 7967 { 7968 case eEncodingT1: 7969 // n = UInt(Rn); wback = (W == '1'); increment = FALSE; wordhigher = FALSE; 7970 n = Bits32 (opcode, 19, 16); 7971 wback = BitIsSet (opcode, 21); 7972 increment = false; 7973 wordhigher = false; 7974 7975 // if n == 15 then UNPREDICTABLE; 7976 if (n == 15) 7977 return false; 7978 7979 // if InITBlock() && !LastInITBlock() then UNPREDICTABLE; 7980 if (InITBlock() && !LastInITBlock()) 7981 return false; 7982 7983 break; 7984 7985 case eEncodingT2: 7986 // n = UInt(Rn); wback = (W == '1'); increment = TRUE; wordhigher = FALSE; 7987 n = Bits32 (opcode, 19, 16); 7988 wback = BitIsSet (opcode, 21); 7989 increment = true; 7990 wordhigher = false; 7991 7992 // if n == 15 then UNPREDICTABLE; 7993 if (n == 15) 7994 return false; 7995 7996 // if InITBlock() && !LastInITBlock() then UNPREDICTABLE; 7997 if (InITBlock() && !LastInITBlock()) 7998 return false; 7999 8000 break; 8001 8002 case eEncodingA1: 8003 // n = UInt(Rn); 8004 n = Bits32 (opcode, 19, 16); 8005 8006 // wback = (W == '1'); inc = (U == '1'); wordhigher = (P == U); 8007 wback = BitIsSet (opcode, 21); 8008 increment = BitIsSet (opcode, 23); 8009 wordhigher = (Bit32 (opcode, 24) == Bit32 (opcode, 23)); 8010 8011 // if n == 15 then UNPREDICTABLE; 8012 if (n == 15) 8013 return false; 8014 8015 break; 8016 8017 default: 8018 return false; 8019 } 8020 8021 // if !CurrentModeIsPrivileged() || CurrentInstrSet() == InstrSet_ThumbEE then 8022 if (!CurrentModeIsPrivileged ()) 8023 // UNPREDICTABLE; 8024 return false; 8025 else 8026 { 8027 uint64_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success); 8028 if (!success) 8029 return false; 8030 8031 addr_t address; 8032 // address = if increment then R[n] else R[n]-8; 8033 if (increment) 8034 address = Rn; 8035 else 8036 address = Rn - 8; 8037 8038 // if wordhigher then address = address+4; 8039 if (wordhigher) 8040 address = address + 4; 8041 8042 // CPSRWriteByInstr(MemA[address+4,4], '1111', TRUE); 8043 Register base_reg; 8044 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n); 8045 8046 EmulateInstruction::Context context; 8047 context.type = eContextReturnFromException; 8048 context.SetRegisterPlusOffset (base_reg, address - Rn); 8049 8050 uint64_t data = MemARead (context, address + 4, 4, 0, &success); 8051 if (!success) 8052 return false; 8053 8054 CPSRWriteByInstr (data, 15, true); 8055 8056 // BranchWritePC(MemA[address,4]); 8057 uint64_t data2 = MemARead (context, address, 4, 0, &success); 8058 if (!success) 8059 return false; 8060 8061 BranchWritePC (context, data2); 8062 8063 // if wback then R[n] = if increment then R[n]+8 else R[n]-8; 8064 if (wback) 8065 { 8066 context.type = eContextAdjustBaseRegister; 8067 if (increment) 8068 { 8069 context.SetOffset (8); 8070 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, Rn + 8)) 8071 return false; 8072 } 8073 else 8074 { 8075 context.SetOffset (-8); 8076 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, Rn - 8)) 8077 return false; 8078 } 8079 } // if wback 8080 } 8081 } // if ConditionPassed() 8082 return true; 8083} 8084 8085// Bitwise Exclusive OR (immediate) performs a bitwise exclusive OR of a register value and an immediate value, 8086// and writes the result to the destination register. It can optionally update the condition flags based on 8087// the result. 8088bool 8089EmulateInstructionARM::EmulateEORImm (const uint32_t opcode, const ARMEncoding encoding) 8090{ 8091#if 0 8092 // ARM pseudo code... 8093 if ConditionPassed() then 8094 EncodingSpecificOperations(); 8095 result = R[n] EOR imm32; 8096 if d == 15 then // Can only occur for ARM encoding 8097 ALUWritePC(result); // setflags is always FALSE here 8098 else 8099 R[d] = result; 8100 if setflags then 8101 APSR.N = result<31>; 8102 APSR.Z = IsZeroBit(result); 8103 APSR.C = carry; 8104 // APSR.V unchanged 8105#endif 8106 8107 bool success = false; 8108 8109 if (ConditionPassed(opcode)) 8110 { 8111 uint32_t Rd, Rn; 8112 uint32_t imm32; // the immediate value to be ORed to the value obtained from Rn 8113 bool setflags; 8114 uint32_t carry; // the carry bit after ARM/Thumb Expand operation 8115 switch (encoding) 8116 { 8117 case eEncodingT1: 8118 Rd = Bits32(opcode, 11, 8); 8119 Rn = Bits32(opcode, 19, 16); 8120 setflags = BitIsSet(opcode, 20); 8121 imm32 = ThumbExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C) 8122 // if Rd == '1111' && S == '1' then SEE TEQ (immediate); 8123 if (Rd == 15 && setflags) 8124 return EmulateTEQImm (opcode, eEncodingT1); 8125 if (Rd == 13 || (Rd == 15 && !setflags) || BadReg(Rn)) 8126 return false; 8127 break; 8128 case eEncodingA1: 8129 Rd = Bits32(opcode, 15, 12); 8130 Rn = Bits32(opcode, 19, 16); 8131 setflags = BitIsSet(opcode, 20); 8132 imm32 = ARMExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ARMExpandImm(imm12, APSR.C) 8133 8134 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions; 8135 if (Rd == 15 && setflags) 8136 return EmulateSUBSPcLrEtc (opcode, encoding); 8137 break; 8138 default: 8139 return false; 8140 } 8141 8142 // Read the first operand. 8143 uint32_t val1 = ReadCoreReg(Rn, &success); 8144 if (!success) 8145 return false; 8146 8147 uint32_t result = val1 ^ imm32; 8148 8149 EmulateInstruction::Context context; 8150 context.type = EmulateInstruction::eContextImmediate; 8151 context.SetNoArgs (); 8152 8153 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry)) 8154 return false; 8155 } 8156 return true; 8157} 8158 8159// Bitwise Exclusive OR (register) performs a bitwise exclusive OR of a register value and an 8160// optionally-shifted register value, and writes the result to the destination register. 8161// It can optionally update the condition flags based on the result. 8162bool 8163EmulateInstructionARM::EmulateEORReg (const uint32_t opcode, const ARMEncoding encoding) 8164{ 8165#if 0 8166 // ARM pseudo code... 8167 if ConditionPassed() then 8168 EncodingSpecificOperations(); 8169 (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C); 8170 result = R[n] EOR shifted; 8171 if d == 15 then // Can only occur for ARM encoding 8172 ALUWritePC(result); // setflags is always FALSE here 8173 else 8174 R[d] = result; 8175 if setflags then 8176 APSR.N = result<31>; 8177 APSR.Z = IsZeroBit(result); 8178 APSR.C = carry; 8179 // APSR.V unchanged 8180#endif 8181 8182 bool success = false; 8183 8184 if (ConditionPassed(opcode)) 8185 { 8186 uint32_t Rd, Rn, Rm; 8187 ARM_ShifterType shift_t; 8188 uint32_t shift_n; // the shift applied to the value read from Rm 8189 bool setflags; 8190 uint32_t carry; 8191 switch (encoding) 8192 { 8193 case eEncodingT1: 8194 Rd = Rn = Bits32(opcode, 2, 0); 8195 Rm = Bits32(opcode, 5, 3); 8196 setflags = !InITBlock(); 8197 shift_t = SRType_LSL; 8198 shift_n = 0; 8199 break; 8200 case eEncodingT2: 8201 Rd = Bits32(opcode, 11, 8); 8202 Rn = Bits32(opcode, 19, 16); 8203 Rm = Bits32(opcode, 3, 0); 8204 setflags = BitIsSet(opcode, 20); 8205 shift_n = DecodeImmShiftThumb(opcode, shift_t); 8206 // if Rd == '1111' && S == '1' then SEE TEQ (register); 8207 if (Rd == 15 && setflags) 8208 return EmulateTEQReg (opcode, eEncodingT1); 8209 if (Rd == 13 || (Rd == 15 && !setflags) || BadReg(Rn) || BadReg(Rm)) 8210 return false; 8211 break; 8212 case eEncodingA1: 8213 Rd = Bits32(opcode, 15, 12); 8214 Rn = Bits32(opcode, 19, 16); 8215 Rm = Bits32(opcode, 3, 0); 8216 setflags = BitIsSet(opcode, 20); 8217 shift_n = DecodeImmShiftARM(opcode, shift_t); 8218 8219 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions; 8220 if (Rd == 15 && setflags) 8221 return EmulateSUBSPcLrEtc (opcode, encoding); 8222 break; 8223 default: 8224 return false; 8225 } 8226 8227 // Read the first operand. 8228 uint32_t val1 = ReadCoreReg(Rn, &success); 8229 if (!success) 8230 return false; 8231 8232 // Read the second operand. 8233 uint32_t val2 = ReadCoreReg(Rm, &success); 8234 if (!success) 8235 return false; 8236 8237 uint32_t shifted = Shift_C(val2, shift_t, shift_n, APSR_C, carry); 8238 uint32_t result = val1 ^ shifted; 8239 8240 EmulateInstruction::Context context; 8241 context.type = EmulateInstruction::eContextImmediate; 8242 context.SetNoArgs (); 8243 8244 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry)) 8245 return false; 8246 } 8247 return true; 8248} 8249 8250// Bitwise OR (immediate) performs a bitwise (inclusive) OR of a register value and an immediate value, and 8251// writes the result to the destination register. It can optionally update the condition flags based 8252// on the result. 8253bool 8254EmulateInstructionARM::EmulateORRImm (const uint32_t opcode, const ARMEncoding encoding) 8255{ 8256#if 0 8257 // ARM pseudo code... 8258 if ConditionPassed() then 8259 EncodingSpecificOperations(); 8260 result = R[n] OR imm32; 8261 if d == 15 then // Can only occur for ARM encoding 8262 ALUWritePC(result); // setflags is always FALSE here 8263 else 8264 R[d] = result; 8265 if setflags then 8266 APSR.N = result<31>; 8267 APSR.Z = IsZeroBit(result); 8268 APSR.C = carry; 8269 // APSR.V unchanged 8270#endif 8271 8272 bool success = false; 8273 8274 if (ConditionPassed(opcode)) 8275 { 8276 uint32_t Rd, Rn; 8277 uint32_t imm32; // the immediate value to be ORed to the value obtained from Rn 8278 bool setflags; 8279 uint32_t carry; // the carry bit after ARM/Thumb Expand operation 8280 switch (encoding) 8281 { 8282 case eEncodingT1: 8283 Rd = Bits32(opcode, 11, 8); 8284 Rn = Bits32(opcode, 19, 16); 8285 setflags = BitIsSet(opcode, 20); 8286 imm32 = ThumbExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C) 8287 // if Rn == '1111' then SEE MOV (immediate); 8288 if (Rn == 15) 8289 return EmulateMOVRdImm (opcode, eEncodingT2); 8290 if (BadReg(Rd) || Rn == 13) 8291 return false; 8292 break; 8293 case eEncodingA1: 8294 Rd = Bits32(opcode, 15, 12); 8295 Rn = Bits32(opcode, 19, 16); 8296 setflags = BitIsSet(opcode, 20); 8297 imm32 = ARMExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ARMExpandImm(imm12, APSR.C) 8298 8299 if (Rd == 15 && setflags) 8300 return EmulateSUBSPcLrEtc (opcode, encoding); 8301 break; 8302 default: 8303 return false; 8304 } 8305 8306 // Read the first operand. 8307 uint32_t val1 = ReadCoreReg(Rn, &success); 8308 if (!success) 8309 return false; 8310 8311 uint32_t result = val1 | imm32; 8312 8313 EmulateInstruction::Context context; 8314 context.type = EmulateInstruction::eContextImmediate; 8315 context.SetNoArgs (); 8316 8317 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry)) 8318 return false; 8319 } 8320 return true; 8321} 8322 8323// Bitwise OR (register) performs a bitwise (inclusive) OR of a register value and an optionally-shifted register 8324// value, and writes the result to the destination register. It can optionally update the condition flags based 8325// on the result. 8326bool 8327EmulateInstructionARM::EmulateORRReg (const uint32_t opcode, const ARMEncoding encoding) 8328{ 8329#if 0 8330 // ARM pseudo code... 8331 if ConditionPassed() then 8332 EncodingSpecificOperations(); 8333 (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C); 8334 result = R[n] OR shifted; 8335 if d == 15 then // Can only occur for ARM encoding 8336 ALUWritePC(result); // setflags is always FALSE here 8337 else 8338 R[d] = result; 8339 if setflags then 8340 APSR.N = result<31>; 8341 APSR.Z = IsZeroBit(result); 8342 APSR.C = carry; 8343 // APSR.V unchanged 8344#endif 8345 8346 bool success = false; 8347 8348 if (ConditionPassed(opcode)) 8349 { 8350 uint32_t Rd, Rn, Rm; 8351 ARM_ShifterType shift_t; 8352 uint32_t shift_n; // the shift applied to the value read from Rm 8353 bool setflags; 8354 uint32_t carry; 8355 switch (encoding) 8356 { 8357 case eEncodingT1: 8358 Rd = Rn = Bits32(opcode, 2, 0); 8359 Rm = Bits32(opcode, 5, 3); 8360 setflags = !InITBlock(); 8361 shift_t = SRType_LSL; 8362 shift_n = 0; 8363 break; 8364 case eEncodingT2: 8365 Rd = Bits32(opcode, 11, 8); 8366 Rn = Bits32(opcode, 19, 16); 8367 Rm = Bits32(opcode, 3, 0); 8368 setflags = BitIsSet(opcode, 20); 8369 shift_n = DecodeImmShiftThumb(opcode, shift_t); 8370 // if Rn == '1111' then SEE MOV (register); 8371 if (Rn == 15) 8372 return EmulateMOVRdRm (opcode, eEncodingT3); 8373 if (BadReg(Rd) || Rn == 13 || BadReg(Rm)) 8374 return false; 8375 break; 8376 case eEncodingA1: 8377 Rd = Bits32(opcode, 15, 12); 8378 Rn = Bits32(opcode, 19, 16); 8379 Rm = Bits32(opcode, 3, 0); 8380 setflags = BitIsSet(opcode, 20); 8381 shift_n = DecodeImmShiftARM(opcode, shift_t); 8382 8383 if (Rd == 15 && setflags) 8384 return EmulateSUBSPcLrEtc (opcode, encoding); 8385 break; 8386 default: 8387 return false; 8388 } 8389 8390 // Read the first operand. 8391 uint32_t val1 = ReadCoreReg(Rn, &success); 8392 if (!success) 8393 return false; 8394 8395 // Read the second operand. 8396 uint32_t val2 = ReadCoreReg(Rm, &success); 8397 if (!success) 8398 return false; 8399 8400 uint32_t shifted = Shift_C(val2, shift_t, shift_n, APSR_C, carry); 8401 uint32_t result = val1 | shifted; 8402 8403 EmulateInstruction::Context context; 8404 context.type = EmulateInstruction::eContextImmediate; 8405 context.SetNoArgs (); 8406 8407 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry)) 8408 return false; 8409 } 8410 return true; 8411} 8412 8413// Reverse Subtract (immediate) subtracts a register value from an immediate value, and writes the result to 8414// the destination register. It can optionally update the condition flags based on the result. 8415bool 8416EmulateInstructionARM::EmulateRSBImm (const uint32_t opcode, const ARMEncoding encoding) 8417{ 8418#if 0 8419 // ARM pseudo code... 8420 if ConditionPassed() then 8421 EncodingSpecificOperations(); 8422 (result, carry, overflow) = AddWithCarry(NOT(R[n]), imm32, '1'); 8423 if d == 15 then // Can only occur for ARM encoding 8424 ALUWritePC(result); // setflags is always FALSE here 8425 else 8426 R[d] = result; 8427 if setflags then 8428 APSR.N = result<31>; 8429 APSR.Z = IsZeroBit(result); 8430 APSR.C = carry; 8431 APSR.V = overflow; 8432#endif 8433 8434 bool success = false; 8435 8436 uint32_t Rd; // the destination register 8437 uint32_t Rn; // the first operand 8438 bool setflags; 8439 uint32_t imm32; // the immediate value to be added to the value obtained from Rn 8440 switch (encoding) { 8441 case eEncodingT1: 8442 Rd = Bits32(opcode, 2, 0); 8443 Rn = Bits32(opcode, 5, 3); 8444 setflags = !InITBlock(); 8445 imm32 = 0; 8446 break; 8447 case eEncodingT2: 8448 Rd = Bits32(opcode, 11, 8); 8449 Rn = Bits32(opcode, 19, 16); 8450 setflags = BitIsSet(opcode, 20); 8451 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8) 8452 if (BadReg(Rd) || BadReg(Rn)) 8453 return false; 8454 break; 8455 case eEncodingA1: 8456 Rd = Bits32(opcode, 15, 12); 8457 Rn = Bits32(opcode, 19, 16); 8458 setflags = BitIsSet(opcode, 20); 8459 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12) 8460 8461 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions; 8462 if (Rd == 15 && setflags) 8463 return EmulateSUBSPcLrEtc (opcode, encoding); 8464 break; 8465 default: 8466 return false; 8467 } 8468 // Read the register value from the operand register Rn. 8469 uint32_t reg_val = ReadCoreReg(Rn, &success); 8470 if (!success) 8471 return false; 8472 8473 AddWithCarryResult res = AddWithCarry(~reg_val, imm32, 1); 8474 8475 EmulateInstruction::Context context; 8476 context.type = EmulateInstruction::eContextImmediate; 8477 context.SetNoArgs (); 8478 8479 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow)) 8480 return false; 8481 8482 return true; 8483} 8484 8485// Reverse Subtract (register) subtracts a register value from an optionally-shifted register value, and writes the 8486// result to the destination register. It can optionally update the condition flags based on the result. 8487bool 8488EmulateInstructionARM::EmulateRSBReg (const uint32_t opcode, const ARMEncoding encoding) 8489{ 8490#if 0 8491 // ARM pseudo code... 8492 if ConditionPassed() then 8493 EncodingSpecificOperations(); 8494 shifted = Shift(R[m], shift_t, shift_n, APSR.C); 8495 (result, carry, overflow) = AddWithCarry(NOT(R[n]), shifted, '1'); 8496 if d == 15 then // Can only occur for ARM encoding 8497 ALUWritePC(result); // setflags is always FALSE here 8498 else 8499 R[d] = result; 8500 if setflags then 8501 APSR.N = result<31>; 8502 APSR.Z = IsZeroBit(result); 8503 APSR.C = carry; 8504 APSR.V = overflow; 8505#endif 8506 8507 bool success = false; 8508 8509 uint32_t Rd; // the destination register 8510 uint32_t Rn; // the first operand 8511 uint32_t Rm; // the second operand 8512 bool setflags; 8513 ARM_ShifterType shift_t; 8514 uint32_t shift_n; // the shift applied to the value read from Rm 8515 switch (encoding) { 8516 case eEncodingT1: 8517 Rd = Bits32(opcode, 11, 8); 8518 Rn = Bits32(opcode, 19, 16); 8519 Rm = Bits32(opcode, 3, 0); 8520 setflags = BitIsSet(opcode, 20); 8521 shift_n = DecodeImmShiftThumb(opcode, shift_t); 8522 // if (BadReg(d) || BadReg(m)) then UNPREDICTABLE; 8523 if (BadReg(Rd) || BadReg(Rn) || BadReg(Rm)) 8524 return false; 8525 break; 8526 case eEncodingA1: 8527 Rd = Bits32(opcode, 15, 12); 8528 Rn = Bits32(opcode, 19, 16); 8529 Rm = Bits32(opcode, 3, 0); 8530 setflags = BitIsSet(opcode, 20); 8531 shift_n = DecodeImmShiftARM(opcode, shift_t); 8532 8533 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions; 8534 if (Rd == 15 && setflags) 8535 return EmulateSUBSPcLrEtc (opcode, encoding); 8536 break; 8537 default: 8538 return false; 8539 } 8540 // Read the register value from register Rn. 8541 uint32_t val1 = ReadCoreReg(Rn, &success); 8542 if (!success) 8543 return false; 8544 8545 // Read the register value from register Rm. 8546 uint32_t val2 = ReadCoreReg(Rm, &success); 8547 if (!success) 8548 return false; 8549 8550 uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C); 8551 AddWithCarryResult res = AddWithCarry(~val1, shifted, 1); 8552 8553 EmulateInstruction::Context context; 8554 context.type = EmulateInstruction::eContextImmediate; 8555 context.SetNoArgs(); 8556 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow)) 8557 return false; 8558 8559 return true; 8560} 8561 8562// Reverse Subtract with Carry (immediate) subtracts a register value and the value of NOT (Carry flag) from 8563// an immediate value, and writes the result to the destination register. It can optionally update the condition 8564// flags based on the result. 8565bool 8566EmulateInstructionARM::EmulateRSCImm (const uint32_t opcode, const ARMEncoding encoding) 8567{ 8568#if 0 8569 // ARM pseudo code... 8570 if ConditionPassed() then 8571 EncodingSpecificOperations(); 8572 (result, carry, overflow) = AddWithCarry(NOT(R[n]), imm32, APSR.C); 8573 if d == 15 then 8574 ALUWritePC(result); // setflags is always FALSE here 8575 else 8576 R[d] = result; 8577 if setflags then 8578 APSR.N = result<31>; 8579 APSR.Z = IsZeroBit(result); 8580 APSR.C = carry; 8581 APSR.V = overflow; 8582#endif 8583 8584 bool success = false; 8585 8586 uint32_t Rd; // the destination register 8587 uint32_t Rn; // the first operand 8588 bool setflags; 8589 uint32_t imm32; // the immediate value to be added to the value obtained from Rn 8590 switch (encoding) { 8591 case eEncodingA1: 8592 Rd = Bits32(opcode, 15, 12); 8593 Rn = Bits32(opcode, 19, 16); 8594 setflags = BitIsSet(opcode, 20); 8595 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12) 8596 8597 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions; 8598 if (Rd == 15 && setflags) 8599 return EmulateSUBSPcLrEtc (opcode, encoding); 8600 break; 8601 default: 8602 return false; 8603 } 8604 // Read the register value from the operand register Rn. 8605 uint32_t reg_val = ReadCoreReg(Rn, &success); 8606 if (!success) 8607 return false; 8608 8609 AddWithCarryResult res = AddWithCarry(~reg_val, imm32, APSR_C); 8610 8611 EmulateInstruction::Context context; 8612 context.type = EmulateInstruction::eContextImmediate; 8613 context.SetNoArgs (); 8614 8615 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow)) 8616 return false; 8617 8618 return true; 8619} 8620 8621// Reverse Subtract with Carry (register) subtracts a register value and the value of NOT (Carry flag) from an 8622// optionally-shifted register value, and writes the result to the destination register. It can optionally update the 8623// condition flags based on the result. 8624bool 8625EmulateInstructionARM::EmulateRSCReg (const uint32_t opcode, const ARMEncoding encoding) 8626{ 8627#if 0 8628 // ARM pseudo code... 8629 if ConditionPassed() then 8630 EncodingSpecificOperations(); 8631 shifted = Shift(R[m], shift_t, shift_n, APSR.C); 8632 (result, carry, overflow) = AddWithCarry(NOT(R[n]), shifted, APSR.C); 8633 if d == 15 then 8634 ALUWritePC(result); // setflags is always FALSE here 8635 else 8636 R[d] = result; 8637 if setflags then 8638 APSR.N = result<31>; 8639 APSR.Z = IsZeroBit(result); 8640 APSR.C = carry; 8641 APSR.V = overflow; 8642#endif 8643 8644 bool success = false; 8645 8646 uint32_t Rd; // the destination register 8647 uint32_t Rn; // the first operand 8648 uint32_t Rm; // the second operand 8649 bool setflags; 8650 ARM_ShifterType shift_t; 8651 uint32_t shift_n; // the shift applied to the value read from Rm 8652 switch (encoding) { 8653 case eEncodingA1: 8654 Rd = Bits32(opcode, 15, 12); 8655 Rn = Bits32(opcode, 19, 16); 8656 Rm = Bits32(opcode, 3, 0); 8657 setflags = BitIsSet(opcode, 20); 8658 shift_n = DecodeImmShiftARM(opcode, shift_t); 8659 8660 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions; 8661 if (Rd == 15 && setflags) 8662 return EmulateSUBSPcLrEtc (opcode, encoding); 8663 break; 8664 default: 8665 return false; 8666 } 8667 // Read the register value from register Rn. 8668 uint32_t val1 = ReadCoreReg(Rn, &success); 8669 if (!success) 8670 return false; 8671 8672 // Read the register value from register Rm. 8673 uint32_t val2 = ReadCoreReg(Rm, &success); 8674 if (!success) 8675 return false; 8676 8677 uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C); 8678 AddWithCarryResult res = AddWithCarry(~val1, shifted, APSR_C); 8679 8680 EmulateInstruction::Context context; 8681 context.type = EmulateInstruction::eContextImmediate; 8682 context.SetNoArgs(); 8683 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow)) 8684 return false; 8685 8686 return true; 8687} 8688 8689// Subtract with Carry (immediate) subtracts an immediate value and the value of 8690// NOT (Carry flag) from a register value, and writes the result to the destination register. 8691// It can optionally update the condition flags based on the result. 8692bool 8693EmulateInstructionARM::EmulateSBCImm (const uint32_t opcode, const ARMEncoding encoding) 8694{ 8695#if 0 8696 // ARM pseudo code... 8697 if ConditionPassed() then 8698 EncodingSpecificOperations(); 8699 (result, carry, overflow) = AddWithCarry(R[n], NOT(imm32), APSR.C); 8700 if d == 15 then // Can only occur for ARM encoding 8701 ALUWritePC(result); // setflags is always FALSE here 8702 else 8703 R[d] = result; 8704 if setflags then 8705 APSR.N = result<31>; 8706 APSR.Z = IsZeroBit(result); 8707 APSR.C = carry; 8708 APSR.V = overflow; 8709#endif 8710 8711 bool success = false; 8712 8713 uint32_t Rd; // the destination register 8714 uint32_t Rn; // the first operand 8715 bool setflags; 8716 uint32_t imm32; // the immediate value to be added to the value obtained from Rn 8717 switch (encoding) { 8718 case eEncodingT1: 8719 Rd = Bits32(opcode, 11, 8); 8720 Rn = Bits32(opcode, 19, 16); 8721 setflags = BitIsSet(opcode, 20); 8722 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8) 8723 if (BadReg(Rd) || BadReg(Rn)) 8724 return false; 8725 break; 8726 case eEncodingA1: 8727 Rd = Bits32(opcode, 15, 12); 8728 Rn = Bits32(opcode, 19, 16); 8729 setflags = BitIsSet(opcode, 20); 8730 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12) 8731 8732 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions; 8733 if (Rd == 15 && setflags) 8734 return EmulateSUBSPcLrEtc (opcode, encoding); 8735 break; 8736 default: 8737 return false; 8738 } 8739 // Read the register value from the operand register Rn. 8740 uint32_t reg_val = ReadCoreReg(Rn, &success); 8741 if (!success) 8742 return false; 8743 8744 AddWithCarryResult res = AddWithCarry(reg_val, ~imm32, APSR_C); 8745 8746 EmulateInstruction::Context context; 8747 context.type = EmulateInstruction::eContextImmediate; 8748 context.SetNoArgs (); 8749 8750 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow)) 8751 return false; 8752 8753 return true; 8754} 8755 8756// Subtract with Carry (register) subtracts an optionally-shifted register value and the value of 8757// NOT (Carry flag) from a register value, and writes the result to the destination register. 8758// It can optionally update the condition flags based on the result. 8759bool 8760EmulateInstructionARM::EmulateSBCReg (const uint32_t opcode, const ARMEncoding encoding) 8761{ 8762#if 0 8763 // ARM pseudo code... 8764 if ConditionPassed() then 8765 EncodingSpecificOperations(); 8766 shifted = Shift(R[m], shift_t, shift_n, APSR.C); 8767 (result, carry, overflow) = AddWithCarry(R[n], NOT(shifted), APSR.C); 8768 if d == 15 then // Can only occur for ARM encoding 8769 ALUWritePC(result); // setflags is always FALSE here 8770 else 8771 R[d] = result; 8772 if setflags then 8773 APSR.N = result<31>; 8774 APSR.Z = IsZeroBit(result); 8775 APSR.C = carry; 8776 APSR.V = overflow; 8777#endif 8778 8779 bool success = false; 8780 8781 uint32_t Rd; // the destination register 8782 uint32_t Rn; // the first operand 8783 uint32_t Rm; // the second operand 8784 bool setflags; 8785 ARM_ShifterType shift_t; 8786 uint32_t shift_n; // the shift applied to the value read from Rm 8787 switch (encoding) { 8788 case eEncodingT1: 8789 Rd = Rn = Bits32(opcode, 2, 0); 8790 Rm = Bits32(opcode, 5, 3); 8791 setflags = !InITBlock(); 8792 shift_t = SRType_LSL; 8793 shift_n = 0; 8794 break; 8795 case eEncodingT2: 8796 Rd = Bits32(opcode, 11, 8); 8797 Rn = Bits32(opcode, 19, 16); 8798 Rm = Bits32(opcode, 3, 0); 8799 setflags = BitIsSet(opcode, 20); 8800 shift_n = DecodeImmShiftThumb(opcode, shift_t); 8801 if (BadReg(Rd) || BadReg(Rn) || BadReg(Rm)) 8802 return false; 8803 break; 8804 case eEncodingA1: 8805 Rd = Bits32(opcode, 15, 12); 8806 Rn = Bits32(opcode, 19, 16); 8807 Rm = Bits32(opcode, 3, 0); 8808 setflags = BitIsSet(opcode, 20); 8809 shift_n = DecodeImmShiftARM(opcode, shift_t); 8810 8811 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions; 8812 if (Rd == 15 && setflags) 8813 return EmulateSUBSPcLrEtc (opcode, encoding); 8814 break; 8815 default: 8816 return false; 8817 } 8818 // Read the register value from register Rn. 8819 uint32_t val1 = ReadCoreReg(Rn, &success); 8820 if (!success) 8821 return false; 8822 8823 // Read the register value from register Rm. 8824 uint32_t val2 = ReadCoreReg(Rm, &success); 8825 if (!success) 8826 return false; 8827 8828 uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C); 8829 AddWithCarryResult res = AddWithCarry(val1, ~shifted, APSR_C); 8830 8831 EmulateInstruction::Context context; 8832 context.type = EmulateInstruction::eContextImmediate; 8833 context.SetNoArgs(); 8834 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow)) 8835 return false; 8836 8837 return true; 8838} 8839 8840// This instruction subtracts an immediate value from a register value, and writes the result 8841// to the destination register. It can optionally update the condition flags based on the result. 8842bool 8843EmulateInstructionARM::EmulateSUBImmThumb (const uint32_t opcode, const ARMEncoding encoding) 8844{ 8845#if 0 8846 // ARM pseudo code... 8847 if ConditionPassed() then 8848 EncodingSpecificOperations(); 8849 (result, carry, overflow) = AddWithCarry(R[n], NOT(imm32), '1'); 8850 R[d] = result; 8851 if setflags then 8852 APSR.N = result<31>; 8853 APSR.Z = IsZeroBit(result); 8854 APSR.C = carry; 8855 APSR.V = overflow; 8856#endif 8857 8858 bool success = false; 8859 8860 uint32_t Rd; // the destination register 8861 uint32_t Rn; // the first operand 8862 bool setflags; 8863 uint32_t imm32; // the immediate value to be subtracted from the value obtained from Rn 8864 switch (encoding) { 8865 case eEncodingT1: 8866 Rd = Bits32(opcode, 2, 0); 8867 Rn = Bits32(opcode, 5, 3); 8868 setflags = !InITBlock(); 8869 imm32 = Bits32(opcode, 8, 6); // imm32 = ZeroExtend(imm3, 32) 8870 break; 8871 case eEncodingT2: 8872 Rd = Rn = Bits32(opcode, 10, 8); 8873 setflags = !InITBlock(); 8874 imm32 = Bits32(opcode, 7, 0); // imm32 = ZeroExtend(imm8, 32) 8875 break; 8876 case eEncodingT3: 8877 Rd = Bits32(opcode, 11, 8); 8878 Rn = Bits32(opcode, 19, 16); 8879 setflags = BitIsSet(opcode, 20); 8880 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8) 8881 8882 // if Rd == '1111' && S == '1' then SEE CMP (immediate); 8883 if (Rd == 15 && setflags) 8884 return EmulateCMPImm (opcode, eEncodingT2); 8885 8886 // if Rn == '1101' then SEE SUB (SP minus immediate); 8887 if (Rn == 13) 8888 return EmulateSUBSPImm (opcode, eEncodingT2); 8889 8890 // if d == 13 || (d == 15 && S == '0') || n == 15 then UNPREDICTABLE; 8891 if (Rd == 13 || (Rd == 15 && !setflags) || Rn == 15) 8892 return false; 8893 break; 8894 case eEncodingT4: 8895 Rd = Bits32(opcode, 11, 8); 8896 Rn = Bits32(opcode, 19, 16); 8897 setflags = BitIsSet(opcode, 20); 8898 imm32 = ThumbImm12(opcode); // imm32 = ZeroExtend(i:imm3:imm8, 32) 8899 8900 // if Rn == '1111' then SEE ADR; 8901 if (Rn == 15) 8902 return EmulateADR (opcode, eEncodingT2); 8903 8904 // if Rn == '1101' then SEE SUB (SP minus immediate); 8905 if (Rn == 13) 8906 return EmulateSUBSPImm (opcode, eEncodingT3); 8907 8908 if (BadReg(Rd)) 8909 return false; 8910 break; 8911 default: 8912 return false; 8913 } 8914 // Read the register value from the operand register Rn. 8915 uint32_t reg_val = ReadCoreReg(Rn, &success); 8916 if (!success) 8917 return false; 8918 8919 AddWithCarryResult res = AddWithCarry(reg_val, ~imm32, 1); 8920 8921 EmulateInstruction::Context context; 8922 context.type = EmulateInstruction::eContextImmediate; 8923 context.SetNoArgs (); 8924 8925 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow)) 8926 return false; 8927 8928 return true; 8929} 8930 8931// This instruction subtracts an immediate value from a register value, and writes the result 8932// to the destination register. It can optionally update the condition flags based on the result. 8933bool 8934EmulateInstructionARM::EmulateSUBImmARM (const uint32_t opcode, const ARMEncoding encoding) 8935{ 8936#if 0 8937 // ARM pseudo code... 8938 if ConditionPassed() then 8939 EncodingSpecificOperations(); 8940 (result, carry, overflow) = AddWithCarry(R[n], NOT(imm32), '1'); 8941 if d == 15 then 8942 ALUWritePC(result); // setflags is always FALSE here 8943 else 8944 R[d] = result; 8945 if setflags then 8946 APSR.N = result<31>; 8947 APSR.Z = IsZeroBit(result); 8948 APSR.C = carry; 8949 APSR.V = overflow; 8950#endif 8951 8952 bool success = false; 8953 8954 uint32_t Rd; // the destination register 8955 uint32_t Rn; // the first operand 8956 bool setflags; 8957 uint32_t imm32; // the immediate value to be subtracted from the value obtained from Rn 8958 switch (encoding) { 8959 case eEncodingA1: 8960 Rd = Bits32(opcode, 15, 12); 8961 Rn = Bits32(opcode, 19, 16); 8962 setflags = BitIsSet(opcode, 20); 8963 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12) 8964 8965 // if Rn == '1111' && S == '0' then SEE ADR; 8966 if (Rn == 15 && !setflags) 8967 return EmulateADR (opcode, eEncodingA2); 8968 8969 // if Rn == '1101' then SEE SUB (SP minus immediate); 8970 if (Rn == 13) 8971 return EmulateSUBSPImm (opcode, eEncodingA1); 8972 8973 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions; 8974 if (Rd == 15 && setflags) 8975 return EmulateSUBSPcLrEtc (opcode, encoding); 8976 break; 8977 default: 8978 return false; 8979 } 8980 // Read the register value from the operand register Rn. 8981 uint32_t reg_val = ReadCoreReg(Rn, &success); 8982 if (!success) 8983 return false; 8984 8985 AddWithCarryResult res = AddWithCarry(reg_val, ~imm32, 1); 8986 8987 EmulateInstruction::Context context; 8988 context.type = EmulateInstruction::eContextImmediate; 8989 context.SetNoArgs (); 8990 8991 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow)) 8992 return false; 8993 8994 return true; 8995} 8996 8997// Test Equivalence (immediate) performs a bitwise exclusive OR operation on a register value and an 8998// immediate value. It updates the condition flags based on the result, and discards the result. 8999bool 9000EmulateInstructionARM::EmulateTEQImm (const uint32_t opcode, const ARMEncoding encoding) 9001{ 9002#if 0 9003 // ARM pseudo code... 9004 if ConditionPassed() then 9005 EncodingSpecificOperations(); 9006 result = R[n] EOR imm32; 9007 APSR.N = result<31>; 9008 APSR.Z = IsZeroBit(result); 9009 APSR.C = carry; 9010 // APSR.V unchanged 9011#endif 9012 9013 bool success = false; 9014 9015 if (ConditionPassed(opcode)) 9016 { 9017 uint32_t Rn; 9018 uint32_t imm32; // the immediate value to be ANDed to the value obtained from Rn 9019 uint32_t carry; // the carry bit after ARM/Thumb Expand operation 9020 switch (encoding) 9021 { 9022 case eEncodingT1: 9023 Rn = Bits32(opcode, 19, 16); 9024 imm32 = ThumbExpandImm_C (opcode, APSR_C, carry); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C) 9025 if (BadReg(Rn)) 9026 return false; 9027 break; 9028 case eEncodingA1: 9029 Rn = Bits32(opcode, 19, 16); 9030 imm32 = ARMExpandImm_C (opcode, APSR_C, carry); // (imm32, carry) = ARMExpandImm(imm12, APSR.C) 9031 break; 9032 default: 9033 return false; 9034 } 9035 9036 // Read the first operand. 9037 uint32_t val1 = ReadCoreReg(Rn, &success); 9038 if (!success) 9039 return false; 9040 9041 uint32_t result = val1 ^ imm32; 9042 9043 EmulateInstruction::Context context; 9044 context.type = EmulateInstruction::eContextImmediate; 9045 context.SetNoArgs (); 9046 9047 if (!WriteFlags(context, result, carry)) 9048 return false; 9049 } 9050 return true; 9051} 9052 9053// Test Equivalence (register) performs a bitwise exclusive OR operation on a register value and an 9054// optionally-shifted register value. It updates the condition flags based on the result, and discards 9055// the result. 9056bool 9057EmulateInstructionARM::EmulateTEQReg (const uint32_t opcode, const ARMEncoding encoding) 9058{ 9059#if 0 9060 // ARM pseudo code... 9061 if ConditionPassed() then 9062 EncodingSpecificOperations(); 9063 (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C); 9064 result = R[n] EOR shifted; 9065 APSR.N = result<31>; 9066 APSR.Z = IsZeroBit(result); 9067 APSR.C = carry; 9068 // APSR.V unchanged 9069#endif 9070 9071 bool success = false; 9072 9073 if (ConditionPassed(opcode)) 9074 { 9075 uint32_t Rn, Rm; 9076 ARM_ShifterType shift_t; 9077 uint32_t shift_n; // the shift applied to the value read from Rm 9078 uint32_t carry; 9079 switch (encoding) 9080 { 9081 case eEncodingT1: 9082 Rn = Bits32(opcode, 19, 16); 9083 Rm = Bits32(opcode, 3, 0); 9084 shift_n = DecodeImmShiftThumb(opcode, shift_t); 9085 if (BadReg(Rn) || BadReg(Rm)) 9086 return false; 9087 break; 9088 case eEncodingA1: 9089 Rn = Bits32(opcode, 19, 16); 9090 Rm = Bits32(opcode, 3, 0); 9091 shift_n = DecodeImmShiftARM(opcode, shift_t); 9092 break; 9093 default: 9094 return false; 9095 } 9096 9097 // Read the first operand. 9098 uint32_t val1 = ReadCoreReg(Rn, &success); 9099 if (!success) 9100 return false; 9101 9102 // Read the second operand. 9103 uint32_t val2 = ReadCoreReg(Rm, &success); 9104 if (!success) 9105 return false; 9106 9107 uint32_t shifted = Shift_C(val2, shift_t, shift_n, APSR_C, carry); 9108 uint32_t result = val1 ^ shifted; 9109 9110 EmulateInstruction::Context context; 9111 context.type = EmulateInstruction::eContextImmediate; 9112 context.SetNoArgs (); 9113 9114 if (!WriteFlags(context, result, carry)) 9115 return false; 9116 } 9117 return true; 9118} 9119 9120// Test (immediate) performs a bitwise AND operation on a register value and an immediate value. 9121// It updates the condition flags based on the result, and discards the result. 9122bool 9123EmulateInstructionARM::EmulateTSTImm (const uint32_t opcode, const ARMEncoding encoding) 9124{ 9125#if 0 9126 // ARM pseudo code... 9127 if ConditionPassed() then 9128 EncodingSpecificOperations(); 9129 result = R[n] AND imm32; 9130 APSR.N = result<31>; 9131 APSR.Z = IsZeroBit(result); 9132 APSR.C = carry; 9133 // APSR.V unchanged 9134#endif 9135 9136 bool success = false; 9137 9138 if (ConditionPassed(opcode)) 9139 { 9140 uint32_t Rn; 9141 uint32_t imm32; // the immediate value to be ANDed to the value obtained from Rn 9142 uint32_t carry; // the carry bit after ARM/Thumb Expand operation 9143 switch (encoding) 9144 { 9145 case eEncodingT1: 9146 Rn = Bits32(opcode, 19, 16); 9147 imm32 = ThumbExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C) 9148 if (BadReg(Rn)) 9149 return false; 9150 break; 9151 case eEncodingA1: 9152 Rn = Bits32(opcode, 19, 16); 9153 imm32 = ARMExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ARMExpandImm(imm12, APSR.C) 9154 break; 9155 default: 9156 return false; 9157 } 9158 9159 // Read the first operand. 9160 uint32_t val1 = ReadCoreReg(Rn, &success); 9161 if (!success) 9162 return false; 9163 9164 uint32_t result = val1 & imm32; 9165 9166 EmulateInstruction::Context context; 9167 context.type = EmulateInstruction::eContextImmediate; 9168 context.SetNoArgs (); 9169 9170 if (!WriteFlags(context, result, carry)) 9171 return false; 9172 } 9173 return true; 9174} 9175 9176// Test (register) performs a bitwise AND operation on a register value and an optionally-shifted register value. 9177// It updates the condition flags based on the result, and discards the result. 9178bool 9179EmulateInstructionARM::EmulateTSTReg (const uint32_t opcode, const ARMEncoding encoding) 9180{ 9181#if 0 9182 // ARM pseudo code... 9183 if ConditionPassed() then 9184 EncodingSpecificOperations(); 9185 (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C); 9186 result = R[n] AND shifted; 9187 APSR.N = result<31>; 9188 APSR.Z = IsZeroBit(result); 9189 APSR.C = carry; 9190 // APSR.V unchanged 9191#endif 9192 9193 bool success = false; 9194 9195 if (ConditionPassed(opcode)) 9196 { 9197 uint32_t Rn, Rm; 9198 ARM_ShifterType shift_t; 9199 uint32_t shift_n; // the shift applied to the value read from Rm 9200 uint32_t carry; 9201 switch (encoding) 9202 { 9203 case eEncodingT1: 9204 Rn = Bits32(opcode, 2, 0); 9205 Rm = Bits32(opcode, 5, 3); 9206 shift_t = SRType_LSL; 9207 shift_n = 0; 9208 break; 9209 case eEncodingT2: 9210 Rn = Bits32(opcode, 19, 16); 9211 Rm = Bits32(opcode, 3, 0); 9212 shift_n = DecodeImmShiftThumb(opcode, shift_t); 9213 if (BadReg(Rn) || BadReg(Rm)) 9214 return false; 9215 break; 9216 case eEncodingA1: 9217 Rn = Bits32(opcode, 19, 16); 9218 Rm = Bits32(opcode, 3, 0); 9219 shift_n = DecodeImmShiftARM(opcode, shift_t); 9220 break; 9221 default: 9222 return false; 9223 } 9224 9225 // Read the first operand. 9226 uint32_t val1 = ReadCoreReg(Rn, &success); 9227 if (!success) 9228 return false; 9229 9230 // Read the second operand. 9231 uint32_t val2 = ReadCoreReg(Rm, &success); 9232 if (!success) 9233 return false; 9234 9235 uint32_t shifted = Shift_C(val2, shift_t, shift_n, APSR_C, carry); 9236 uint32_t result = val1 & shifted; 9237 9238 EmulateInstruction::Context context; 9239 context.type = EmulateInstruction::eContextImmediate; 9240 context.SetNoArgs (); 9241 9242 if (!WriteFlags(context, result, carry)) 9243 return false; 9244 } 9245 return true; 9246} 9247 9248// A8.6.216 SUB (SP minus register) 9249bool 9250EmulateInstructionARM::EmulateSUBSPReg (const uint32_t opcode, const ARMEncoding encoding) 9251{ 9252#if 0 9253 if ConditionPassed() then 9254 EncodingSpecificOperations(); 9255 shifted = Shift(R[m], shift_t, shift_n, APSR.C); 9256 (result, carry, overflow) = AddWithCarry(SP, NOT(shifted), ‘1’); 9257 if d == 15 then // Can only occur for ARM encoding 9258 ALUWritePC(result); // setflags is always FALSE here 9259 else 9260 R[d] = result; 9261 if setflags then 9262 APSR.N = result<31>; 9263 APSR.Z = IsZeroBit(result); 9264 APSR.C = carry; 9265 APSR.V = overflow; 9266#endif 9267 9268 bool success = false; 9269 9270 if (ConditionPassed(opcode)) 9271 { 9272 uint32_t d; 9273 uint32_t m; 9274 bool setflags; 9275 ARM_ShifterType shift_t; 9276 uint32_t shift_n; 9277 9278 switch (encoding) 9279 { 9280 case eEncodingT1: 9281 // d = UInt(Rd); m = UInt(Rm); setflags = (S == ‘1’); 9282 d = Bits32 (opcode, 11, 8); 9283 m = Bits32 (opcode, 3, 0); 9284 setflags = BitIsSet (opcode, 20); 9285 9286 // (shift_t, shift_n) = DecodeImmShift(type, imm3:imm2); 9287 shift_n = DecodeImmShiftThumb (opcode, shift_t); 9288 9289 // if d == 13 && (shift_t != SRType_LSL || shift_n > 3) then UNPREDICTABLE; 9290 if ((d == 13) && ((shift_t != SRType_LSL) || (shift_n > 3))) 9291 return false; 9292 9293 // if d == 15 || BadReg(m) then UNPREDICTABLE; 9294 if ((d == 15) || BadReg (m)) 9295 return false; 9296 break; 9297 9298 case eEncodingA1: 9299 // d = UInt(Rd); m = UInt(Rm); setflags = (S == ‘1’); 9300 d = Bits32 (opcode, 15, 12); 9301 m = Bits32 (opcode, 3, 0); 9302 setflags = BitIsSet (opcode, 20); 9303 9304 // if Rd == ‘1111’ && S == ‘1’ then SEE SUBS PC, LR and related instructions; 9305 if (d == 15 && setflags) 9306 EmulateSUBSPcLrEtc (opcode, encoding); 9307 9308 // (shift_t, shift_n) = DecodeImmShift(type, imm5); 9309 shift_n = DecodeImmShiftARM (opcode, shift_t); 9310 break; 9311 9312 default: 9313 return false; 9314 } 9315 9316 // shifted = Shift(R[m], shift_t, shift_n, APSR.C); 9317 uint32_t Rm = ReadCoreReg (m, &success); 9318 if (!success) 9319 return false; 9320 9321 uint32_t shifted = Shift (Rm, shift_t, shift_n, APSR_C); 9322 9323 // (result, carry, overflow) = AddWithCarry(SP, NOT(shifted), ‘1’); 9324 uint32_t sp_val = ReadCoreReg (SP_REG, &success); 9325 if (!success) 9326 return false; 9327 9328 AddWithCarryResult res = AddWithCarry (sp_val, ~shifted, 1); 9329 9330 EmulateInstruction::Context context; 9331 context.type = eContextSubtraction; 9332 Register sp_reg; 9333 sp_reg.SetRegister (eRegisterKindDWARF, dwarf_sp); 9334 Register dwarf_reg; 9335 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + m); 9336 context.SetRegisterRegisterOperands (sp_reg, dwarf_reg); 9337 9338 if (!WriteCoreRegOptionalFlags(context, res.result, dwarf_r0 + d, setflags, res.carry_out, res.overflow)) 9339 return false; 9340 } 9341 return true; 9342} 9343 9344 9345// A8.6.7 ADD (register-shifted register) 9346bool 9347EmulateInstructionARM::EmulateADDRegShift (const uint32_t opcode, const ARMEncoding encoding) 9348{ 9349#if 0 9350 if ConditionPassed() then 9351 EncodingSpecificOperations(); 9352 shift_n = UInt(R[s]<7:0>); 9353 shifted = Shift(R[m], shift_t, shift_n, APSR.C); 9354 (result, carry, overflow) = AddWithCarry(R[n], shifted, ‘0’); 9355 R[d] = result; 9356 if setflags then 9357 APSR.N = result<31>; 9358 APSR.Z = IsZeroBit(result); 9359 APSR.C = carry; 9360 APSR.V = overflow; 9361#endif 9362 9363 bool success = false; 9364 9365 if (ConditionPassed(opcode)) 9366 { 9367 uint32_t d; 9368 uint32_t n; 9369 uint32_t m; 9370 uint32_t s; 9371 bool setflags; 9372 ARM_ShifterType shift_t; 9373 9374 switch (encoding) 9375 { 9376 case eEncodingA1: 9377 // d = UInt(Rd); n = UInt(Rn); m = UInt(Rm); s = UInt(Rs); 9378 d = Bits32 (opcode, 15, 12); 9379 n = Bits32 (opcode, 19, 16); 9380 m = Bits32 (opcode, 3, 0); 9381 s = Bits32 (opcode, 11, 8); 9382 9383 // setflags = (S == ‘1’); shift_t = DecodeRegShift(type); 9384 setflags = BitIsSet (opcode, 20); 9385 shift_t = DecodeRegShift (Bits32 (opcode, 6, 5)); 9386 9387 // if d == 15 || n == 15 || m == 15 || s == 15 then UNPREDICTABLE; 9388 if ((d == 15) || (m == 15) || (m == 15) || (s == 15)) 9389 return false; 9390 break; 9391 9392 default: 9393 return false; 9394 } 9395 9396 // shift_n = UInt(R[s]<7:0>); 9397 uint32_t Rs = ReadCoreReg (s, &success); 9398 if (!success) 9399 return false; 9400 9401 uint32_t shift_n = Bits32 (Rs, 7, 0); 9402 9403 // shifted = Shift(R[m], shift_t, shift_n, APSR.C); 9404 uint32_t Rm = ReadCoreReg (m, &success); 9405 if (!success) 9406 return false; 9407 9408 uint32_t shifted = Shift (Rm, shift_t, shift_n, APSR_C); 9409 9410 // (result, carry, overflow) = AddWithCarry(R[n], shifted, ‘0’); 9411 uint32_t Rn = ReadCoreReg (n, &success); 9412 if (!success) 9413 return false; 9414 9415 AddWithCarryResult res = AddWithCarry (Rn, shifted, 0); 9416 9417 // R[d] = result; 9418 EmulateInstruction::Context context; 9419 context.type = eContextAddition; 9420 Register reg_n; 9421 reg_n.SetRegister (eRegisterKindDWARF, dwarf_r0 +n); 9422 Register reg_m; 9423 reg_m.SetRegister (eRegisterKindDWARF, dwarf_r0 + m); 9424 9425 context.SetRegisterRegisterOperands (reg_n, reg_m); 9426 9427 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + d, res.result)) 9428 return false; 9429 9430 // if setflags then 9431 // APSR.N = result<31>; 9432 // APSR.Z = IsZeroBit(result); 9433 // APSR.C = carry; 9434 // APSR.V = overflow; 9435 if (setflags) 9436 return WriteFlags (context, res.result, res.carry_out, res.overflow); 9437 } 9438 return true; 9439} 9440 9441// A8.6.213 SUB (register) 9442bool 9443EmulateInstructionARM::EmulateSUBReg (const uint32_t opcode, const ARMEncoding encoding) 9444{ 9445#if 0 9446 if ConditionPassed() then 9447 EncodingSpecificOperations(); 9448 shifted = Shift(R[m], shift_t, shift_n, APSR.C); 9449 (result, carry, overflow) = AddWithCarry(R[n], NOT(shifted), ‘1’); 9450 if d == 15 then // Can only occur for ARM encoding 9451 ALUWritePC(result); // setflags is always FALSE here 9452 else 9453 R[d] = result; 9454 if setflags then 9455 APSR.N = result<31>; 9456 APSR.Z = IsZeroBit(result); 9457 APSR.C = carry; 9458 APSR.V = overflow; 9459#endif 9460 9461 bool success = false; 9462 9463 if (ConditionPassed(opcode)) 9464 { 9465 uint32_t d; 9466 uint32_t n; 9467 uint32_t m; 9468 bool setflags; 9469 ARM_ShifterType shift_t; 9470 uint32_t shift_n; 9471 9472 switch (encoding) 9473 { 9474 case eEncodingT1: 9475 // d = UInt(Rd); n = UInt(Rn); m = UInt(Rm); setflags = !InITBlock(); 9476 d = Bits32 (opcode, 2, 0); 9477 n = Bits32 (opcode, 5, 3); 9478 m = Bits32 (opcode, 8, 6); 9479 setflags = !InITBlock(); 9480 9481 // (shift_t, shift_n) = (SRType_LSL, 0); 9482 shift_t = SRType_LSL; 9483 shift_n = 0; 9484 9485 break; 9486 9487 case eEncodingT2: 9488 // if Rd == ‘1111’ && S == ‘1’ then SEE CMP (register); 9489 // if Rn == ‘1101’ then SEE SUB (SP minus register); 9490 // d = UInt(Rd); n = UInt(Rn); m = UInt(Rm); setflags = (S == ‘1’); 9491 d = Bits32 (opcode, 11, 8); 9492 n = Bits32 (opcode, 19, 16); 9493 m = Bits32 (opcode, 3, 0); 9494 setflags = BitIsSet (opcode, 20); 9495 9496 // (shift_t, shift_n) = DecodeImmShift(type, imm3:imm2); 9497 shift_n = DecodeImmShiftThumb (opcode, shift_t); 9498 9499 // if d == 13 || (d == 15 && S == '0') || n == 15 || BadReg(m) then UNPREDICTABLE; 9500 if ((d == 13) || ((d == 15) && BitIsClear (opcode, 20)) || (n == 15) || BadReg (m)) 9501 return false; 9502 9503 break; 9504 9505 case eEncodingA1: 9506 // if Rn == ‘1101’ then SEE SUB (SP minus register); 9507 // d = UInt(Rd); n = UInt(Rn); m = UInt(Rm); setflags = (S == ‘1’); 9508 d = Bits32 (opcode, 15, 12); 9509 n = Bits32 (opcode, 19, 16); 9510 m = Bits32 (opcode, 3, 0); 9511 setflags = BitIsSet (opcode, 20); 9512 9513 // if Rd == ‘1111’ && S == ‘1’ then SEE SUBS PC, LR and related instructions; 9514 if ((d == 15) && setflags) 9515 EmulateSUBSPcLrEtc (opcode, encoding); 9516 9517 // (shift_t, shift_n) = DecodeImmShift(type, imm5); 9518 shift_n = DecodeImmShiftARM (opcode, shift_t); 9519 9520 break; 9521 9522 default: 9523 return false; 9524 } 9525 9526 // shifted = Shift(R[m], shift_t, shift_n, APSR.C); 9527 uint32_t Rm = ReadCoreReg (m, &success); 9528 if (!success) 9529 return false; 9530 9531 uint32_t shifted = Shift (Rm, shift_t, shift_n, APSR_C); 9532 9533 // (result, carry, overflow) = AddWithCarry(R[n], NOT(shifted), ‘1’); 9534 uint32_t Rn = ReadCoreReg (n, &success); 9535 if (!success) 9536 return false; 9537 9538 AddWithCarryResult res = AddWithCarry (Rn, ~shifted, 1); 9539 9540 // if d == 15 then // Can only occur for ARM encoding 9541 // ALUWritePC(result); // setflags is always FALSE here 9542 // else 9543 // R[d] = result; 9544 // if setflags then 9545 // APSR.N = result<31>; 9546 // APSR.Z = IsZeroBit(result); 9547 // APSR.C = carry; 9548 // APSR.V = overflow; 9549 9550 EmulateInstruction::Context context; 9551 context.type = eContextSubtraction; 9552 Register reg_n; 9553 reg_n.SetRegister (eRegisterKindDWARF, dwarf_r0 + n); 9554 Register reg_m; 9555 reg_m.SetRegister (eRegisterKindDWARF, dwarf_r0 + m); 9556 context.SetRegisterRegisterOperands (reg_n, reg_m); 9557 9558 if (!WriteCoreRegOptionalFlags (context, res.result, dwarf_r0 + d, setflags, res.carry_out, res.overflow)) 9559 return false; 9560 } 9561 return true; 9562} 9563 9564// A8.6.202 STREX 9565// Store Register Exclusive calculates an address from a base register value and an immediate offset, and stores a 9566// word from a register to memory if the executing processor has exclusive access to the memory addressed. 9567bool 9568EmulateInstructionARM::EmulateSTREX (const uint32_t opcode, const ARMEncoding encoding) 9569{ 9570#if 0 9571 if ConditionPassed() then 9572 EncodingSpecificOperations(); NullCheckIfThumbEE(n); 9573 address = R[n] + imm32; 9574 if ExclusiveMonitorsPass(address,4) then 9575 MemA[address,4] = R[t]; 9576 R[d] = 0; 9577 else 9578 R[d] = 1; 9579#endif 9580 9581 bool success = false; 9582 9583 if (ConditionPassed(opcode)) 9584 { 9585 uint32_t d; 9586 uint32_t t; 9587 uint32_t n; 9588 uint32_t imm32; 9589 const uint32_t addr_byte_size = GetAddressByteSize(); 9590 9591 switch (encoding) 9592 { 9593 case eEncodingT1: 9594 // d = UInt(Rd); t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8:’00’, 32); 9595 d = Bits32 (opcode, 11, 8); 9596 t = Bits32 (opcode, 15, 12); 9597 n = Bits32 (opcode, 19, 16); 9598 imm32 = Bits32 (opcode, 7, 0) << 2; 9599 9600 // if BadReg(d) || BadReg(t) || n == 15 then UNPREDICTABLE; 9601 if (BadReg (d) || BadReg (t) || (n == 15)) 9602 return false; 9603 9604 // if d == n || d == t then UNPREDICTABLE; 9605 if ((d == n) || (d == t)) 9606 return false; 9607 9608 break; 9609 9610 case eEncodingA1: 9611 // d = UInt(Rd); t = UInt(Rt); n = UInt(Rn); imm32 = Zeros(32); // Zero offset 9612 d = Bits32 (opcode, 15, 12); 9613 t = Bits32 (opcode, 3, 0); 9614 n = Bits32 (opcode, 19, 16); 9615 imm32 = 0; 9616 9617 // if d == 15 || t == 15 || n == 15 then UNPREDICTABLE; 9618 if ((d == 15) || (t == 15) || (n == 15)) 9619 return false; 9620 9621 // if d == n || d == t then UNPREDICTABLE; 9622 if ((d == n) || (d == t)) 9623 return false; 9624 9625 break; 9626 9627 default: 9628 return false; 9629 } 9630 9631 // address = R[n] + imm32; 9632 uint32_t Rn = ReadCoreReg (n, &success); 9633 if (!success) 9634 return false; 9635 9636 addr_t address = Rn + imm32; 9637 9638 Register base_reg; 9639 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n); 9640 Register data_reg; 9641 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + t); 9642 EmulateInstruction::Context context; 9643 context.type = eContextRegisterStore; 9644 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, imm32); 9645 9646 // if ExclusiveMonitorsPass(address,4) then 9647 // if (ExclusiveMonitorsPass (address, addr_byte_size)) -- For now, for the sake of emulation, we will say this 9648 // always return true. 9649 if (true) 9650 { 9651 // MemA[address,4] = R[t]; 9652 uint32_t Rt = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + t, 0, &success); 9653 if (!success) 9654 return false; 9655 9656 if (!MemAWrite (context, address, Rt, addr_byte_size)) 9657 return false; 9658 9659 // R[d] = 0; 9660 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, 0)) 9661 return false; 9662 } 9663 else 9664 { 9665 // R[d] = 1; 9666 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, 1)) 9667 return false; 9668 } 9669 } 9670 return true; 9671} 9672 9673// A8.6.197 STRB (immediate, ARM) 9674bool 9675EmulateInstructionARM::EmulateSTRBImmARM (const uint32_t opcode, const ARMEncoding encoding) 9676{ 9677#if 0 9678 if ConditionPassed() then 9679 EncodingSpecificOperations(); 9680 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32); 9681 address = if index then offset_addr else R[n]; 9682 MemU[address,1] = R[t]<7:0>; 9683 if wback then R[n] = offset_addr; 9684#endif 9685 9686 bool success = false; 9687 9688 if (ConditionPassed(opcode)) 9689 { 9690 uint32_t t; 9691 uint32_t n; 9692 uint32_t imm32; 9693 bool index; 9694 bool add; 9695 bool wback; 9696 9697 switch (encoding) 9698 { 9699 case eEncodingA1: 9700 // if P == ‘0’ && W == ‘1’ then SEE STRBT; 9701 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32); 9702 t = Bits32 (opcode, 15, 12); 9703 n = Bits32 (opcode, 19, 16); 9704 imm32 = Bits32 (opcode, 11, 0); 9705 9706 // index = (P == ‘1’); add = (U == ‘1’); wback = (P == ‘0’) || (W == ‘1’); 9707 index = BitIsSet (opcode, 24); 9708 add = BitIsSet (opcode, 23); 9709 wback = BitIsClear (opcode, 24) || BitIsSet (opcode, 21); 9710 9711 // if t == 15 then UNPREDICTABLE; 9712 if (t == 15) 9713 return false; 9714 9715 // if wback && (n == 15 || n == t) then UNPREDICTABLE; 9716 if (wback && ((n == 15) || (n == t))) 9717 return false; 9718 9719 break; 9720 9721 default: 9722 return false; 9723 } 9724 9725 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32); 9726 uint32_t Rn = ReadCoreReg (n, &success); 9727 if (!success) 9728 return false; 9729 9730 addr_t offset_addr; 9731 if (add) 9732 offset_addr = Rn + imm32; 9733 else 9734 offset_addr = Rn - imm32; 9735 9736 // address = if index then offset_addr else R[n]; 9737 addr_t address; 9738 if (index) 9739 address = offset_addr; 9740 else 9741 address = Rn; 9742 9743 // MemU[address,1] = R[t]<7:0>; 9744 uint32_t Rt = ReadCoreReg (t, &success); 9745 if (!success) 9746 return false; 9747 9748 Register base_reg; 9749 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n); 9750 Register data_reg; 9751 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + t); 9752 EmulateInstruction::Context context; 9753 context.type = eContextRegisterStore; 9754 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, address - Rn); 9755 9756 if (!MemUWrite (context, address, Bits32 (Rt, 7, 0), 1)) 9757 return false; 9758 9759 // if wback then R[n] = offset_addr; 9760 if (wback) 9761 { 9762 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr)) 9763 return false; 9764 } 9765 } 9766 return true; 9767} 9768 9769// A8.6.194 STR (immediate, ARM) 9770bool 9771EmulateInstructionARM::EmulateSTRImmARM (const uint32_t opcode, const ARMEncoding encoding) 9772{ 9773#if 0 9774 if ConditionPassed() then 9775 EncodingSpecificOperations(); 9776 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32); 9777 address = if index then offset_addr else R[n]; 9778 MemU[address,4] = if t == 15 then PCStoreValue() else R[t]; 9779 if wback then R[n] = offset_addr; 9780#endif 9781 9782 bool success = false; 9783 9784 if (ConditionPassed(opcode)) 9785 { 9786 uint32_t t; 9787 uint32_t n; 9788 uint32_t imm32; 9789 bool index; 9790 bool add; 9791 bool wback; 9792 9793 const uint32_t addr_byte_size = GetAddressByteSize(); 9794 9795 switch (encoding) 9796 { 9797 case eEncodingA1: 9798 // if P == ‘0’ && W == ‘1’ then SEE STRT; 9799 // if Rn == ‘1101’ && P == ‘1’ && U == ‘0’ && W == ‘1’ && imm12 == ‘000000000100’ then SEE PUSH; 9800 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32); 9801 t = Bits32 (opcode, 15, 12); 9802 n = Bits32 (opcode, 19, 16); 9803 imm32 = Bits32 (opcode, 11, 0); 9804 9805 // index = (P == ‘1’); add = (U == ‘1’); wback = (P == ‘0’) || (W == ‘1’); 9806 index = BitIsSet (opcode, 24); 9807 add = BitIsSet (opcode, 23); 9808 wback = BitIsClear (opcode, 24) || BitIsSet (opcode, 21); 9809 9810 // if wback && (n == 15 || n == t) then UNPREDICTABLE; 9811 if (wback && ((n == 15) || (n == t))) 9812 return false; 9813 9814 break; 9815 9816 default: 9817 return false; 9818 } 9819 9820 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32); 9821 uint32_t Rn = ReadCoreReg (n, &success); 9822 if (!success) 9823 return false; 9824 9825 addr_t offset_addr; 9826 if (add) 9827 offset_addr = Rn + imm32; 9828 else 9829 offset_addr = Rn - imm32; 9830 9831 // address = if index then offset_addr else R[n]; 9832 addr_t address; 9833 if (index) 9834 address = offset_addr; 9835 else 9836 address = Rn; 9837 9838 Register base_reg; 9839 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n); 9840 Register data_reg; 9841 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + t); 9842 EmulateInstruction::Context context; 9843 context.type = eContextRegisterStore; 9844 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, address - Rn); 9845 9846 // MemU[address,4] = if t == 15 then PCStoreValue() else R[t]; 9847 uint32_t Rt = ReadCoreReg (t, &success); 9848 if (!success) 9849 return false; 9850 9851 if (t == 15) 9852 { 9853 uint32_t pc_value = ReadCoreReg (PC_REG, &success); 9854 if (!success) 9855 return false; 9856 9857 if (!MemUWrite (context, address, pc_value, addr_byte_size)) 9858 return false; 9859 } 9860 else 9861 { 9862 if (!MemUWrite (context, address, Rt, addr_byte_size)) 9863 return false; 9864 } 9865 9866 // if wback then R[n] = offset_addr; 9867 if (wback) 9868 { 9869 context.type = eContextAdjustBaseRegister; 9870 context.SetImmediate (offset_addr); 9871 9872 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr)) 9873 return false; 9874 } 9875 } 9876 return true; 9877} 9878 9879// A8.6.66 LDRD (immediate) 9880// Load Register Dual (immediate) calculates an address from a base register value and an immediate offset, loads two 9881// words from memory, and writes them to two registers. It can use offset, post-indexed, or pre-indexed addressing. 9882bool 9883EmulateInstructionARM::EmulateLDRDImmediate (const uint32_t opcode, const ARMEncoding encoding) 9884{ 9885#if 0 9886 if ConditionPassed() then 9887 EncodingSpecificOperations(); NullCheckIfThumbEE(n); 9888 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32); 9889 address = if index then offset_addr else R[n]; 9890 R[t] = MemA[address,4]; 9891 R[t2] = MemA[address+4,4]; 9892 if wback then R[n] = offset_addr; 9893#endif 9894 9895 bool success = false; 9896 9897 if (ConditionPassed(opcode)) 9898 { 9899 uint32_t t; 9900 uint32_t t2; 9901 uint32_t n; 9902 uint32_t imm32; 9903 bool index; 9904 bool add; 9905 bool wback; 9906 9907 switch (encoding) 9908 { 9909 case eEncodingT1: 9910 //if P == ‘0’ && W == ‘0’ then SEE “Related encodings”; 9911 //if Rn == ‘1111’ then SEE LDRD (literal); 9912 //t = UInt(Rt); t2 = UInt(Rt2); n = UInt(Rn); imm32 = ZeroExtend(imm8:’00’, 32); 9913 t = Bits32 (opcode, 15, 12); 9914 t2 = Bits32 (opcode, 11, 8); 9915 n = Bits32 (opcode, 19, 16); 9916 imm32 = Bits32 (opcode, 7, 0) << 2; 9917 9918 //index = (P == ‘1’); add = (U == ‘1’); wback = (W == ‘1’); 9919 index = BitIsSet (opcode, 24); 9920 add = BitIsSet (opcode, 23); 9921 wback = BitIsSet (opcode, 21); 9922 9923 //if wback && (n == t || n == t2) then UNPREDICTABLE; 9924 if (wback && ((n == t) || (n == t2))) 9925 return false; 9926 9927 //if BadReg(t) || BadReg(t2) || t == t2 then UNPREDICTABLE; 9928 if (BadReg (t) || BadReg (t2) || (t == t2)) 9929 return false; 9930 9931 break; 9932 9933 case eEncodingA1: 9934 //if Rn == ‘1111’ then SEE LDRD (literal); 9935 //if Rt<0> == ‘1’ then UNPREDICTABLE; 9936 //t = UInt(Rt); t2 = t+1; n = UInt(Rn); imm32 = ZeroExtend(imm4H:imm4L, 32); 9937 t = Bits32 (opcode, 15, 12); 9938 if (BitIsSet (t, 0)) 9939 return false; 9940 t2 = t + 1; 9941 n = Bits32 (opcode, 19, 16); 9942 imm32 = (Bits32 (opcode, 11, 8) << 4) | Bits32 (opcode, 3, 0); 9943 9944 //index = (P == ‘1’); add = (U == ‘1’); wback = (P == ‘0’) || (W == ‘1’); 9945 index = BitIsSet (opcode, 24); 9946 add = BitIsSet (opcode, 23); 9947 wback = BitIsClear (opcode, 24) || BitIsSet (opcode, 21); 9948 9949 //if P == ‘0’ && W == ‘1’ then UNPREDICTABLE; 9950 if (BitIsClear (opcode, 24) && BitIsSet (opcode, 21)) 9951 return false; 9952 9953 //if wback && (n == t || n == t2) then UNPREDICTABLE; 9954 if (wback && ((n == t) || (n == t2))) 9955 return false; 9956 9957 //if t2 == 15 then UNPREDICTABLE; 9958 if (t2 == 15) 9959 return false; 9960 9961 break; 9962 9963 default: 9964 return false; 9965 } 9966 9967 //offset_addr = if add then (R[n] + imm32) else (R[n] - imm32); 9968 uint32_t Rn = ReadCoreReg (n, &success); 9969 if (!success) 9970 return false; 9971 9972 addr_t offset_addr; 9973 if (add) 9974 offset_addr = Rn + imm32; 9975 else 9976 offset_addr = Rn - imm32; 9977 9978 //address = if index then offset_addr else R[n]; 9979 addr_t address; 9980 if (index) 9981 address = offset_addr; 9982 else 9983 address = Rn; 9984 9985 //R[t] = MemA[address,4]; 9986 Register base_reg; 9987 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n); 9988 9989 EmulateInstruction::Context context; 9990 context.type = eContextRegisterLoad; 9991 context.SetRegisterPlusOffset (base_reg, address - Rn); 9992 9993 const uint32_t addr_byte_size = GetAddressByteSize(); 9994 uint32_t data = MemARead (context, address, addr_byte_size, 0, &success); 9995 if (!success) 9996 return false; 9997 9998 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data)) 9999 return false; 10000 10001 //R[t2] = MemA[address+4,4]; 10002 10003 context.SetRegisterPlusOffset (base_reg, (address + 4) - Rn); 10004 data = MemARead (context, address + 4, addr_byte_size, 0, &success); 10005 if (!success) 10006 return false; 10007 10008 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t2, data)) 10009 return false; 10010 10011 //if wback then R[n] = offset_addr; 10012 if (wback) 10013 { 10014 context.type = eContextAdjustBaseRegister; 10015 context.SetAddress (offset_addr); 10016 10017 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr)) 10018 return false; 10019 } 10020 } 10021 return true; 10022} 10023 10024// A8.6.68 LDRD (register) 10025// Load Register Dual (register) calculates an address from a base register value and a register offset, loads two 10026// words from memory, and writes them to two registers. It can use offset, post-indexed or pre-indexed addressing. 10027bool 10028EmulateInstructionARM::EmulateLDRDRegister (const uint32_t opcode, const ARMEncoding encoding) 10029{ 10030#if 0 10031 if ConditionPassed() then 10032 EncodingSpecificOperations(); 10033 offset_addr = if add then (R[n] + R[m]) else (R[n] - R[m]); 10034 address = if index then offset_addr else R[n]; 10035 R[t] = MemA[address,4]; 10036 R[t2] = MemA[address+4,4]; 10037 if wback then R[n] = offset_addr; 10038#endif 10039 10040 bool success = false; 10041 10042 if (ConditionPassed(opcode)) 10043 { 10044 uint32_t t; 10045 uint32_t t2; 10046 uint32_t n; 10047 uint32_t m; 10048 bool index; 10049 bool add; 10050 bool wback; 10051 10052 switch (encoding) 10053 { 10054 case eEncodingA1: 10055 // if Rt<0> == ‘1’ then UNPREDICTABLE; 10056 // t = UInt(Rt); t2 = t+1; n = UInt(Rn); m = UInt(Rm); 10057 t = Bits32 (opcode, 15, 12); 10058 if (BitIsSet (t, 0)) 10059 return false; 10060 t2 = t + 1; 10061 n = Bits32 (opcode, 19, 16); 10062 m = Bits32 (opcode, 3, 0); 10063 10064 // index = (P == ‘1’); add = (U == ‘1’); wback = (P == ‘0’) || (W == ‘1’); 10065 index = BitIsSet (opcode, 24); 10066 add = BitIsSet (opcode, 23); 10067 wback = BitIsClear (opcode, 24) || BitIsSet (opcode, 21); 10068 10069 // if P == ‘0’ && W == ‘1’ then UNPREDICTABLE; 10070 if (BitIsClear (opcode, 24) && BitIsSet (opcode, 21)) 10071 return false; 10072 10073 // if t2 == 15 || m == 15 || m == t || m == t2 then UNPREDICTABLE; 10074 if ((t2 == 15) || (m == 15) || (m == t) || (m == t2)) 10075 return false; 10076 10077 // if wback && (n == 15 || n == t || n == t2) then UNPREDICTABLE; 10078 if (wback && ((n == 15) || (n == t) || (n == t2))) 10079 return false; 10080 10081 // if ArchVersion() < 6 && wback && m == n then UNPREDICTABLE; 10082 if ((ArchVersion() < 6) && wback && (m == n)) 10083 return false; 10084 break; 10085 10086 default: 10087 return false; 10088 } 10089 10090 uint32_t Rn = ReadCoreReg (n, &success); 10091 if (!success) 10092 return false; 10093 Register base_reg; 10094 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n); 10095 10096 uint32_t Rm = ReadCoreReg (m, &success); 10097 if (!success) 10098 return false; 10099 Register offset_reg; 10100 offset_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + m); 10101 10102 // offset_addr = if add then (R[n] + R[m]) else (R[n] - R[m]); 10103 addr_t offset_addr; 10104 if (add) 10105 offset_addr = Rn + Rm; 10106 else 10107 offset_addr = Rn - Rm; 10108 10109 // address = if index then offset_addr else R[n]; 10110 addr_t address; 10111 if (index) 10112 address = offset_addr; 10113 else 10114 address = Rn; 10115 10116 EmulateInstruction::Context context; 10117 context.type = eContextRegisterLoad; 10118 context.SetRegisterPlusIndirectOffset (base_reg, offset_reg); 10119 10120 // R[t] = MemA[address,4]; 10121 const uint32_t addr_byte_size = GetAddressByteSize(); 10122 uint32_t data = MemARead (context, address, addr_byte_size, 0, &success); 10123 if (!success) 10124 return false; 10125 10126 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data)) 10127 return false; 10128 10129 // R[t2] = MemA[address+4,4]; 10130 10131 data = MemARead (context, address + 4, addr_byte_size, 0, &success); 10132 if (!success) 10133 return false; 10134 10135 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t2, data)) 10136 return false; 10137 10138 // if wback then R[n] = offset_addr; 10139 if (wback) 10140 { 10141 context.type = eContextAdjustBaseRegister; 10142 context.SetAddress (offset_addr); 10143 10144 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr)) 10145 return false; 10146 } 10147 } 10148 return true; 10149} 10150 10151// A8.6.200 STRD (immediate) 10152// Store Register Dual (immediate) calculates an address from a base register value and an immediate offset, and 10153// stores two words from two registers to memory. It can use offset, post-indexed, or pre-indexed addressing. 10154bool 10155EmulateInstructionARM::EmulateSTRDImm (const uint32_t opcode, const ARMEncoding encoding) 10156{ 10157#if 0 10158 if ConditionPassed() then 10159 EncodingSpecificOperations(); NullCheckIfThumbEE(n); 10160 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32); 10161 address = if index then offset_addr else R[n]; 10162 MemA[address,4] = R[t]; 10163 MemA[address+4,4] = R[t2]; 10164 if wback then R[n] = offset_addr; 10165#endif 10166 10167 bool success = false; 10168 10169 if (ConditionPassed(opcode)) 10170 { 10171 uint32_t t; 10172 uint32_t t2; 10173 uint32_t n; 10174 uint32_t imm32; 10175 bool index; 10176 bool add; 10177 bool wback; 10178 10179 switch (encoding) 10180 { 10181 case eEncodingT1: 10182 // if P == ‘0’ && W == ‘0’ then SEE “Related encodings”; 10183 // t = UInt(Rt); t2 = UInt(Rt2); n = UInt(Rn); imm32 = ZeroExtend(imm8:’00’, 32); 10184 t = Bits32 (opcode, 15, 12); 10185 t2 = Bits32 (opcode, 11, 8); 10186 n = Bits32 (opcode, 19, 16); 10187 imm32 = Bits32 (opcode, 7, 0) << 2; 10188 10189 // index = (P == ‘1’); add = (U == ‘1’); wback = (W == ‘1’); 10190 index = BitIsSet (opcode, 24); 10191 add = BitIsSet (opcode, 23); 10192 wback = BitIsSet (opcode, 21); 10193 10194 // if wback && (n == t || n == t2) then UNPREDICTABLE; 10195 if (wback && ((n == t) || (n == t2))) 10196 return false; 10197 10198 // if n == 15 || BadReg(t) || BadReg(t2) then UNPREDICTABLE; 10199 if ((n == 15) || BadReg (t) || BadReg (t2)) 10200 return false; 10201 10202 break; 10203 10204 case eEncodingA1: 10205 // if Rt<0> == ‘1’ then UNPREDICTABLE; 10206 // t = UInt(Rt); t2 = t+1; n = UInt(Rn); imm32 = ZeroExtend(imm4H:imm4L, 32); 10207 t = Bits32 (opcode, 15, 12); 10208 if (BitIsSet (t, 0)) 10209 return false; 10210 10211 t2 = t + 1; 10212 n = Bits32 (opcode, 19, 16); 10213 imm32 = (Bits32 (opcode, 11, 8) << 4) | Bits32 (opcode, 3, 0); 10214 10215 // index = (P == ‘1’); add = (U == ‘1’); wback = (P == ‘0’) || (W == ‘1’); 10216 index = BitIsSet (opcode, 24); 10217 add = BitIsSet (opcode, 23); 10218 wback = BitIsClear (opcode, 24) || BitIsSet (opcode, 21); 10219 10220 // if P == ‘0’ && W == ‘1’ then UNPREDICTABLE; 10221 if (BitIsClear (opcode, 24) && BitIsSet (opcode, 21)) 10222 return false; 10223 10224 // if wback && (n == 15 || n == t || n == t2) then UNPREDICTABLE; 10225 if (wback && ((n == 15) || (n == t) || (n == t2))) 10226 return false; 10227 10228 // if t2 == 15 then UNPREDICTABLE; 10229 if (t2 == 15) 10230 return false; 10231 10232 break; 10233 10234 default: 10235 return false; 10236 } 10237 10238 Register base_reg; 10239 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n); 10240 10241 uint32_t Rn = ReadCoreReg (n, &success); 10242 if (!success) 10243 return false; 10244 10245 //offset_addr = if add then (R[n] + imm32) else (R[n] - imm32); 10246 addr_t offset_addr; 10247 if (add) 10248 offset_addr = Rn + imm32; 10249 else 10250 offset_addr = Rn - imm32; 10251 10252 //address = if index then offset_addr else R[n]; 10253 addr_t address; 10254 if (index) 10255 address = offset_addr; 10256 else 10257 address = Rn; 10258 10259 //MemA[address,4] = R[t]; 10260 Register data_reg; 10261 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + t); 10262 10263 uint32_t data = ReadCoreReg (t, &success); 10264 if (!success) 10265 return false; 10266 10267 EmulateInstruction::Context context; 10268 context.type = eContextRegisterStore; 10269 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, address - Rn); 10270 10271 const uint32_t addr_byte_size = GetAddressByteSize(); 10272 10273 if (!MemAWrite (context, address, data, addr_byte_size)) 10274 return false; 10275 10276 //MemA[address+4,4] = R[t2]; 10277 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + t2); 10278 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, (address + 4) - Rn); 10279 10280 data = ReadCoreReg (t2, &success); 10281 if (!success) 10282 return false; 10283 10284 if (!MemAWrite (context, address + 4, data, addr_byte_size)) 10285 return false; 10286 10287 //if wback then R[n] = offset_addr; 10288 if (wback) 10289 { 10290 context.type = eContextAdjustBaseRegister; 10291 context.SetAddress (offset_addr); 10292 10293 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr)) 10294 return false; 10295 } 10296 } 10297 return true; 10298} 10299 10300 10301// A8.6.201 STRD (register) 10302bool 10303EmulateInstructionARM::EmulateSTRDReg (const uint32_t opcode, const ARMEncoding encoding) 10304{ 10305#if 0 10306 if ConditionPassed() then 10307 EncodingSpecificOperations(); 10308 offset_addr = if add then (R[n] + R[m]) else (R[n] - R[m]); 10309 address = if index then offset_addr else R[n]; 10310 MemA[address,4] = R[t]; 10311 MemA[address+4,4] = R[t2]; 10312 if wback then R[n] = offset_addr; 10313#endif 10314 10315 bool success = false; 10316 10317 if (ConditionPassed(opcode)) 10318 { 10319 uint32_t t; 10320 uint32_t t2; 10321 uint32_t n; 10322 uint32_t m; 10323 bool index; 10324 bool add; 10325 bool wback; 10326 10327 switch (encoding) 10328 { 10329 case eEncodingA1: 10330 // if Rt<0> == ‘1’ then UNPREDICTABLE; 10331 // t = UInt(Rt); t2 = t+1; n = UInt(Rn); m = UInt(Rm); 10332 t = Bits32 (opcode, 15, 12); 10333 if (BitIsSet (t, 0)) 10334 return false; 10335 10336 t2 = t+1; 10337 n = Bits32 (opcode, 19, 16); 10338 m = Bits32 (opcode, 3, 0); 10339 10340 // index = (P == ‘1’); add = (U == ‘1’); wback = (P == ‘0’) || (W == ‘1’); 10341 index = BitIsSet (opcode, 24); 10342 add = BitIsSet (opcode, 23); 10343 wback = BitIsClear (opcode, 24) || BitIsSet (opcode, 21); 10344 10345 // if P == ‘0’ && W == ‘1’ then UNPREDICTABLE; 10346 if (BitIsClear (opcode, 24) && BitIsSet (opcode, 21)) 10347 return false; 10348 10349 // if t2 == 15 || m == 15 then UNPREDICTABLE; 10350 if ((t2 == 15) || (m == 15)) 10351 return false; 10352 10353 // if wback && (n == 15 || n == t || n == t2) then UNPREDICTABLE; 10354 if (wback && ((n == 15) || (n == t) || (n == t2))) 10355 return false; 10356 10357 // if ArchVersion() < 6 && wback && m == n then UNPREDICTABLE; 10358 if ((ArchVersion() < 6) && wback && (m == n)) 10359 return false; 10360 10361 break; 10362 10363 default: 10364 return false; 10365 } 10366 10367 Register base_reg; 10368 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n); 10369 Register offset_reg; 10370 offset_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + m); 10371 Register data_reg; 10372 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + t); 10373 10374 uint32_t Rn = ReadCoreReg (n, &success); 10375 if (!success) 10376 return false; 10377 10378 uint32_t Rm = ReadCoreReg (m, &success); 10379 if (!success) 10380 return false; 10381 10382 // offset_addr = if add then (R[n] + R[m]) else (R[n] - R[m]); 10383 addr_t offset_addr; 10384 if (add) 10385 offset_addr = Rn + Rm; 10386 else 10387 offset_addr = Rn - Rm; 10388 10389 // address = if index then offset_addr else R[n]; 10390 addr_t address; 10391 if (index) 10392 address = offset_addr; 10393 else 10394 address = Rn; 10395 // MemA[address,4] = R[t]; 10396 uint32_t Rt = ReadCoreReg (t, &success); 10397 if (!success) 10398 return false; 10399 10400 EmulateInstruction::Context context; 10401 context.type = eContextRegisterStore; 10402 context.SetRegisterToRegisterPlusIndirectOffset (base_reg, offset_reg, data_reg); 10403 10404 const uint32_t addr_byte_size = GetAddressByteSize(); 10405 10406 if (!MemAWrite (context, address, Rt, addr_byte_size)) 10407 return false; 10408 10409 // MemA[address+4,4] = R[t2]; 10410 uint32_t Rt2 = ReadCoreReg (t2, &success); 10411 if (!success) 10412 return false; 10413 10414 data_reg.num = dwarf_r0 + t2; 10415 10416 context.SetRegisterToRegisterPlusIndirectOffset (base_reg, offset_reg, data_reg); 10417 10418 if (!MemAWrite (context, address + 4, Rt2, addr_byte_size)) 10419 return false; 10420 10421 // if wback then R[n] = offset_addr; 10422 if (wback) 10423 { 10424 context.type = eContextAdjustBaseRegister; 10425 context.SetAddress (offset_addr); 10426 10427 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr)) 10428 return false; 10429 10430 } 10431 } 10432 return true; 10433} 10434 10435// A8.6.319 VLDM 10436// Vector Load Multiple loads multiple extension registers from consecutive memory locations using an address from 10437// an ARM core register. 10438bool 10439EmulateInstructionARM::EmulateVLDM (const uint32_t opcode, const ARMEncoding encoding) 10440{ 10441#if 0 10442 if ConditionPassed() then 10443 EncodingSpecificOperations(); CheckVFPEnabled(TRUE); NullCheckIfThumbEE(n); 10444 address = if add then R[n] else R[n]-imm32; 10445 if wback then R[n] = if add then R[n}+imm32 else R[n]-imm32; 10446 for r = 0 to regs-1 10447 if single_regs then 10448 S[d+r] = MemA[address,4]; address = address+4; 10449 else 10450 word1 = MemA[address,4]; word2 = MemA[address+4,4]; address = address+8; 10451 // Combine the word-aligned words in the correct order for current endianness. 10452 D[d+r] = if BigEndian() then word1:word2 else word2:word1; 10453#endif 10454 10455 bool success = false; 10456 10457 if (ConditionPassed(opcode)) 10458 { 10459 bool single_regs; 10460 bool add; 10461 bool wback; 10462 uint32_t d; 10463 uint32_t n; 10464 uint32_t imm32; 10465 uint32_t regs; 10466 10467 switch (encoding) 10468 { 10469 case eEncodingT1: 10470 case eEncodingA1: 10471 // if P == ‘0’ && U == ‘0’ && W == ‘0’ then SEE “Related encodings”; 10472 // if P == ‘0’ && U == ‘1’ && W == ‘1’ && Rn == ‘1101’ then SEE VPOP; 10473 // if P == ‘1’ && W == ‘0’ then SEE VLDR; 10474 // if P == U && W == ‘1’ then UNDEFINED; 10475 if ((Bit32 (opcode, 24) == Bit32 (opcode, 23)) && BitIsSet (opcode, 21)) 10476 return false; 10477 10478 // // Remaining combinations are PUW = 010 (IA without !), 011 (IA with !), 101 (DB with !) 10479 // single_regs = FALSE; add = (U == ‘1’); wback = (W == ‘1’); 10480 single_regs = false; 10481 add = BitIsSet (opcode, 23); 10482 wback = BitIsSet (opcode, 21); 10483 10484 // d = UInt(D:Vd); n = UInt(Rn); imm32 = ZeroExtend(imm8:’00’, 32); 10485 d = (Bit32 (opcode, 22) << 4) | Bits32 (opcode, 15, 12); 10486 n = Bits32 (opcode, 19, 16); 10487 imm32 = Bits32 (opcode, 7, 0) << 2; 10488 10489 // regs = UInt(imm8) DIV 2; // If UInt(imm8) is odd, see “FLDMX”. 10490 regs = Bits32 (opcode, 7, 0) / 2; 10491 10492 // if n == 15 && (wback || CurrentInstrSet() != InstrSet_ARM) then UNPREDICTABLE; 10493 if (n == 15 && (wback || CurrentInstrSet() != eModeARM)) 10494 return false; 10495 10496 // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE; 10497 if ((regs == 0) || (regs > 16) || ((d + regs) > 32)) 10498 return false; 10499 10500 break; 10501 10502 case eEncodingT2: 10503 case eEncodingA2: 10504 // if P == ‘0’ && U == ‘0’ && W == ‘0’ then SEE “Related encodings”; 10505 // if P == ‘0’ && U == ‘1’ && W == ‘1’ && Rn == ‘1101’ then SEE VPOP; 10506 // if P == ‘1’ && W == ‘0’ then SEE VLDR; 10507 // if P == U && W == ‘1’ then UNDEFINED; 10508 if ((Bit32 (opcode, 24) == Bit32 (opcode, 23)) && BitIsSet (opcode, 21)) 10509 return false; 10510 10511 // // Remaining combinations are PUW = 010 (IA without !), 011 (IA with !), 101 (DB with !) 10512 // single_regs = TRUE; add = (U == ‘1’); wback = (W == ‘1’); d = UInt(Vd:D); n = UInt(Rn); 10513 single_regs = true; 10514 add = BitIsSet (opcode, 23); 10515 wback = BitIsSet (opcode, 21); 10516 d = (Bits32 (opcode, 15, 12) << 1) | Bit32 (opcode, 22); 10517 n = Bits32 (opcode, 19, 16); 10518 10519 // imm32 = ZeroExtend(imm8:’00’, 32); regs = UInt(imm8); 10520 imm32 = Bits32 (opcode, 7, 0) << 2; 10521 regs = Bits32 (opcode, 7, 0); 10522 10523 // if n == 15 && (wback || CurrentInstrSet() != InstrSet_ARM) then UNPREDICTABLE; 10524 if ((n == 15) && (wback || (CurrentInstrSet() != eModeARM))) 10525 return false; 10526 10527 // if regs == 0 || (d+regs) > 32 then UNPREDICTABLE; 10528 if ((regs == 0) || ((d + regs) > 32)) 10529 return false; 10530 break; 10531 10532 default: 10533 return false; 10534 } 10535 10536 Register base_reg; 10537 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n); 10538 10539 uint32_t Rn = ReadCoreReg (n, &success); 10540 if (!success) 10541 return false; 10542 10543 // address = if add then R[n] else R[n]-imm32; 10544 addr_t address; 10545 if (add) 10546 address = Rn; 10547 else 10548 address = Rn - imm32; 10549 10550 // if wback then R[n] = if add then R[n}+imm32 else R[n]-imm32; 10551 EmulateInstruction::Context context; 10552 10553 if (wback) 10554 { 10555 uint32_t value; 10556 if (add) 10557 value = Rn + imm32; 10558 else 10559 value = Rn - imm32; 10560 10561 context.type = eContextAdjustBaseRegister; 10562 context.SetImmediateSigned (value - Rn); 10563 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, value)) 10564 return false; 10565 10566 } 10567 10568 const uint32_t addr_byte_size = GetAddressByteSize(); 10569 uint32_t start_reg = single_regs ? dwarf_s0 : dwarf_d0; 10570 10571 context.type = eContextRegisterLoad; 10572 10573 // for r = 0 to regs-1 10574 for (uint32_t r = 0; r < regs; ++r) 10575 { 10576 if (single_regs) 10577 { 10578 // S[d+r] = MemA[address,4]; address = address+4; 10579 context.SetRegisterPlusOffset (base_reg, address - Rn); 10580 10581 uint32_t data = MemARead (context, address, addr_byte_size, 0, &success); 10582 if (!success) 10583 return false; 10584 10585 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, start_reg + d + r, data)) 10586 return false; 10587 10588 address = address + 4; 10589 } 10590 else 10591 { 10592 // word1 = MemA[address,4]; word2 = MemA[address+4,4]; address = address+8; 10593 context.SetRegisterPlusOffset (base_reg, address - Rn); 10594 uint32_t word1 = MemARead (context, address, addr_byte_size, 0, &success); 10595 if (!success) 10596 return false; 10597 10598 context.SetRegisterPlusOffset (base_reg, (address + 4) - Rn); 10599 uint32_t word2 = MemARead (context, address + 4, addr_byte_size, 0, &success); 10600 if (!success) 10601 return false; 10602 10603 address = address + 8; 10604 // // Combine the word-aligned words in the correct order for current endianness. 10605 // D[d+r] = if BigEndian() then word1:word2 else word2:word1; 10606 uint64_t data; 10607 if (m_byte_order == eByteOrderBig) 10608 { 10609 data = word1; 10610 data = (data << 32) | word2; 10611 } 10612 else 10613 { 10614 data = word2; 10615 data = (data << 32) | word1; 10616 } 10617 10618 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, start_reg + d + r, data)) 10619 return false; 10620 } 10621 } 10622 } 10623 return true; 10624} 10625 10626// A8.6.399 VSTM 10627// Vector Store Multiple stores multiple extension registers to consecutive memory locations using an address from an 10628// ARM core register. 10629bool 10630EmulateInstructionARM::EmulateVSTM (const uint32_t opcode, const ARMEncoding encoding) 10631{ 10632#if 0 10633 if ConditionPassed() then 10634 EncodingSpecificOperations(); CheckVFPEnabled(TRUE); NullCheckIfThumbEE(n); 10635 address = if add then R[n] else R[n]-imm32; 10636 if wback then R[n] = if add then R[n}+imm32 else R[n]-imm32; 10637 for r = 0 to regs-1 10638 if single_regs then 10639 MemA[address,4] = S[d+r]; address = address+4; 10640 else 10641 // Store as two word-aligned words in the correct order for current endianness. 10642 MemA[address,4] = if BigEndian() then D[d+r]<63:32> else D[d+r]<31:0>; 10643 MemA[address+4,4] = if BigEndian() then D[d+r]<31:0> else D[d+r]<63:32>; 10644 address = address+8; 10645#endif 10646 10647 bool success = false; 10648 10649 if (ConditionPassed (opcode)) 10650 { 10651 bool single_regs; 10652 bool add; 10653 bool wback; 10654 uint32_t d; 10655 uint32_t n; 10656 uint32_t imm32; 10657 uint32_t regs; 10658 10659 switch (encoding) 10660 { 10661 case eEncodingT1: 10662 case eEncodingA1: 10663 // if P == ‘0’ && U == ‘0’ && W == ‘0’ then SEE “Related encodings”; 10664 // if P == ‘1’ && U == ‘0’ && W == ‘1’ && Rn == ‘1101’ then SEE VPUSH; 10665 // if P == ‘1’ && W == ‘0’ then SEE VSTR; 10666 // if P == U && W == ‘1’ then UNDEFINED; 10667 if ((Bit32 (opcode, 24) == Bit32 (opcode, 23)) && BitIsSet (opcode, 21)) 10668 return false; 10669 10670 // // Remaining combinations are PUW = 010 (IA without !), 011 (IA with !), 101 (DB with !) 10671 // single_regs = FALSE; add = (U == ‘1’); wback = (W == ‘1’); 10672 single_regs = false; 10673 add = BitIsSet (opcode, 23); 10674 wback = BitIsSet (opcode, 21); 10675 10676 // d = UInt(D:Vd); n = UInt(Rn); imm32 = ZeroExtend(imm8:’00’, 32); 10677 d = (Bit32 (opcode, 22) << 4) | Bits32 (opcode, 15, 12); 10678 n = Bits32 (opcode, 19, 16); 10679 imm32 = Bits32 (opcode, 7, 0) << 2; 10680 10681 // regs = UInt(imm8) DIV 2; // If UInt(imm8) is odd, see “FSTMX”. 10682 regs = Bits32 (opcode, 7, 0) / 2; 10683 10684 // if n == 15 && (wback || CurrentInstrSet() != InstrSet_ARM) then UNPREDICTABLE; 10685 if ((n == 15) && (wback || (CurrentInstrSet() != eModeARM))) 10686 return false; 10687 10688 // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE; 10689 if ((regs == 0) || (regs > 16) || ((d + regs) > 32)) 10690 return false; 10691 10692 break; 10693 10694 case eEncodingT2: 10695 case eEncodingA2: 10696 // if P == ‘0’ && U == ‘0’ && W == ‘0’ then SEE “Related encodings”; 10697 // if P == ‘1’ && U == ‘0’ && W == ‘1’ && Rn == ‘1101’ then SEE VPUSH; 10698 // if P == ‘1’ && W == ‘0’ then SEE VSTR; 10699 // if P == U && W == ‘1’ then UNDEFINED; 10700 if ((Bit32 (opcode, 24) == Bit32 (opcode, 23)) && BitIsSet (opcode, 21)) 10701 return false; 10702 10703 // // Remaining combinations are PUW = 010 (IA without !), 011 (IA with !), 101 (DB with !) 10704 // single_regs = TRUE; add = (U == ‘1’); wback = (W == ‘1’); d = UInt(Vd:D); n = UInt(Rn); 10705 single_regs = true; 10706 add = BitIsSet (opcode, 23); 10707 wback = BitIsSet (opcode, 21); 10708 d = (Bits32 (opcode, 15, 12) << 1) | Bit32 (opcode, 22); 10709 n = Bits32 (opcode, 19, 16); 10710 10711 // imm32 = ZeroExtend(imm8:’00’, 32); regs = UInt(imm8); 10712 imm32 = Bits32 (opcode, 7, 0) << 2; 10713 regs = Bits32 (opcode, 7, 0); 10714 10715 // if n == 15 && (wback || CurrentInstrSet() != InstrSet_ARM) then UNPREDICTABLE; 10716 if ((n == 15) && (wback || (CurrentInstrSet () != eModeARM))) 10717 return false; 10718 10719 // if regs == 0 || (d+regs) > 32 then UNPREDICTABLE; 10720 if ((regs == 0) || ((d + regs) > 32)) 10721 return false; 10722 10723 break; 10724 10725 default: 10726 return false; 10727 } 10728 10729 Register base_reg; 10730 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n); 10731 10732 uint32_t Rn = ReadCoreReg (n, &success); 10733 if (!success) 10734 return false; 10735 10736 // address = if add then R[n] else R[n]-imm32; 10737 addr_t address; 10738 if (add) 10739 address = Rn; 10740 else 10741 address = Rn - imm32; 10742 10743 EmulateInstruction::Context context; 10744 // if wback then R[n] = if add then R[n}+imm32 else R[n]-imm32; 10745 if (wback) 10746 { 10747 uint32_t value; 10748 if (add) 10749 value = Rn + imm32; 10750 else 10751 value = Rn - imm32; 10752 10753 context.type = eContextAdjustBaseRegister; 10754 context.SetRegisterPlusOffset (base_reg, value - Rn); 10755 10756 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, value)) 10757 return false; 10758 } 10759 10760 const uint32_t addr_byte_size = GetAddressByteSize(); 10761 uint32_t start_reg = single_regs ? dwarf_s0 : dwarf_d0; 10762 10763 context.type = eContextRegisterStore; 10764 // for r = 0 to regs-1 10765 for (int r = 0; r < regs; ++r) 10766 { 10767 Register data_reg; 10768 data_reg.SetRegister (eRegisterKindDWARF, 0); 10769 if (single_regs) 10770 { 10771 // MemA[address,4] = S[d+r]; address = address+4; 10772 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, start_reg + d + r, 0, &success); 10773 if (!success) 10774 return false; 10775 10776 data_reg.num = start_reg + d + r; 10777 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, address - Rn); 10778 if (!MemAWrite (context, address, data, addr_byte_size)) 10779 return false; 10780 10781 address = address + 4; 10782 } 10783 else 10784 { 10785 // // Store as two word-aligned words in the correct order for current endianness. 10786 // MemA[address,4] = if BigEndian() then D[d+r]<63:32> else D[d+r]<31:0>; 10787 // MemA[address+4,4] = if BigEndian() then D[d+r]<31:0> else D[d+r]<63:32>; 10788 uint64_t data = ReadRegisterUnsigned (eRegisterKindDWARF, start_reg + d + r, 0, &success); 10789 if (!success) 10790 return false; 10791 10792 data_reg.num = start_reg + d + r; 10793 10794 if (m_byte_order == eByteOrderBig) 10795 { 10796 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, address - Rn); 10797 if (!MemAWrite (context, address, Bits64 (data, 63, 32), addr_byte_size)) 10798 return false; 10799 10800 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, (address + 4) - Rn); 10801 if (!MemAWrite (context, address+ 4, Bits64 (data, 31, 0), addr_byte_size)) 10802 return false; 10803 } 10804 else 10805 { 10806 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, address - Rn); 10807 if (!MemAWrite (context, address, Bits64 (data, 31, 0), addr_byte_size)) 10808 return false; 10809 10810 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, (address + 4) - Rn); 10811 if (!MemAWrite (context, address + 4, Bits64 (data, 63, 32), addr_byte_size)) 10812 return false; 10813 } 10814 // address = address+8; 10815 address = address + 8; 10816 } 10817 } 10818 } 10819 return true; 10820} 10821 10822// A8.6.320 10823// This instruciton loads a single extension register fronm memory, using an address from an ARM core register, with 10824// an optional offset. 10825bool 10826EmulateInstructionARM::EmulateVLDR (const uint32_t opcode, ARMEncoding encoding) 10827{ 10828#if 0 10829 if ConditionPassed() then 10830 EncodingSpecificOperations(); CheckVFPEnabled(TRUE); NullCheckIfThumbEE(n); 10831 base = if n == 15 then Align(PC,4) else R[n]; 10832 address = if add then (base + imm32) else (base - imm32); 10833 if single_reg then 10834 S[d] = MemA[address,4]; 10835 else 10836 word1 = MemA[address,4]; word2 = MemA[address+4,4]; 10837 // Combine the word-aligned words in the correct order for current endianness. 10838 D[d] = if BigEndian() then word1:word2 else word2:word1; 10839#endif 10840 10841 bool success = false; 10842 10843 if (ConditionPassed (opcode)) 10844 { 10845 bool single_reg; 10846 bool add; 10847 uint32_t imm32; 10848 uint32_t d; 10849 uint32_t n; 10850 10851 switch (encoding) 10852 { 10853 case eEncodingT1: 10854 case eEncodingA1: 10855 // single_reg = FALSE; add = (U == ‘1’); imm32 = ZeroExtend(imm8:’00’, 32); 10856 single_reg = false; 10857 add = BitIsSet (opcode, 23); 10858 imm32 = Bits32 (opcode, 7, 0) << 2; 10859 10860 // d = UInt(D:Vd); n = UInt(Rn); 10861 d = (Bit32 (opcode, 22) << 4) | Bits32 (opcode, 15, 12); 10862 n = Bits32 (opcode, 19, 16); 10863 10864 break; 10865 10866 case eEncodingT2: 10867 case eEncodingA2: 10868 // single_reg = TRUE; add = (U == ‘1’); imm32 = ZeroExtend(imm8:’00’, 32); 10869 single_reg = true; 10870 add = BitIsSet (opcode, 23); 10871 imm32 = Bits32 (opcode, 7, 0) << 2; 10872 10873 // d = UInt(Vd:D); n = UInt(Rn); 10874 d = (Bits32 (opcode, 15, 12) << 1) | Bit32 (opcode, 22); 10875 n = Bits32 (opcode, 19, 16); 10876 10877 break; 10878 10879 default: 10880 return false; 10881 } 10882 Register base_reg; 10883 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n); 10884 10885 uint32_t Rn = ReadCoreReg (n, &success); 10886 if (!success) 10887 return false; 10888 10889 // base = if n == 15 then Align(PC,4) else R[n]; 10890 uint32_t base; 10891 if (n == 15) 10892 base = AlignPC (Rn); 10893 else 10894 base = Rn; 10895 10896 // address = if add then (base + imm32) else (base - imm32); 10897 addr_t address; 10898 if (add) 10899 address = base + imm32; 10900 else 10901 address = base - imm32; 10902 10903 const uint32_t addr_byte_size = GetAddressByteSize(); 10904 uint32_t start_reg = single_reg ? dwarf_s0 : dwarf_d0; 10905 10906 EmulateInstruction::Context context; 10907 context.type = eContextRegisterLoad; 10908 context.SetRegisterPlusOffset (base_reg, address - base); 10909 10910 if (single_reg) 10911 { 10912 // S[d] = MemA[address,4]; 10913 uint32_t data = MemARead (context, address, addr_byte_size, 0, &success); 10914 if (!success) 10915 return false; 10916 10917 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, start_reg + d, data)) 10918 return false; 10919 } 10920 else 10921 { 10922 // word1 = MemA[address,4]; word2 = MemA[address+4,4]; 10923 uint32_t word1 = MemARead (context, address, addr_byte_size, 0, &success); 10924 if (!success) 10925 return false; 10926 10927 context.SetRegisterPlusOffset (base_reg, (address + 4) - base); 10928 uint32_t word2 = MemARead (context, address + 4, addr_byte_size, 0, &success); 10929 if (!success) 10930 return false; 10931 // // Combine the word-aligned words in the correct order for current endianness. 10932 // D[d] = if BigEndian() then word1:word2 else word2:word1; 10933 uint64_t data64; 10934 if (m_byte_order == eByteOrderBig) 10935 { 10936 data64 = word1; 10937 data64 = (data64 << 32) | word2; 10938 } 10939 else 10940 { 10941 data64 = word2; 10942 data64 = (data64 << 32) | word1; 10943 } 10944 10945 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, start_reg + d, data64)) 10946 return false; 10947 } 10948 } 10949 return true; 10950} 10951 10952// A8.6.400 VSTR 10953// This instruction stores a signle extension register to memory, using an address from an ARM core register, with an 10954// optional offset. 10955bool 10956EmulateInstructionARM::EmulateVSTR (const uint32_t opcode, ARMEncoding encoding) 10957{ 10958#if 0 10959 if ConditionPassed() then 10960 EncodingSpecificOperations(); CheckVFPEnabled(TRUE); NullCheckIfThumbEE(n); 10961 address = if add then (R[n] + imm32) else (R[n] - imm32); 10962 if single_reg then 10963 MemA[address,4] = S[d]; 10964 else 10965 // Store as two word-aligned words in the correct order for current endianness. 10966 MemA[address,4] = if BigEndian() then D[d]<63:32> else D[d]<31:0>; 10967 MemA[address+4,4] = if BigEndian() then D[d]<31:0> else D[d]<63:32>; 10968#endif 10969 10970 bool success = false; 10971 10972 if (ConditionPassed (opcode)) 10973 { 10974 bool single_reg; 10975 bool add; 10976 uint32_t imm32; 10977 uint32_t d; 10978 uint32_t n; 10979 10980 switch (encoding) 10981 { 10982 case eEncodingT1: 10983 case eEncodingA1: 10984 // single_reg = FALSE; add = (U == ‘1’); imm32 = ZeroExtend(imm8:’00’, 32); 10985 single_reg = false; 10986 add = BitIsSet (opcode, 23); 10987 imm32 = Bits32 (opcode, 7, 0) << 2; 10988 10989 // d = UInt(D:Vd); n = UInt(Rn); 10990 d = (Bit32 (opcode, 22) << 4) | Bits32 (opcode, 15, 12); 10991 n = Bits32 (opcode, 19, 16); 10992 10993 // if n == 15 && CurrentInstrSet() != InstrSet_ARM then UNPREDICTABLE; 10994 if ((n == 15) && (CurrentInstrSet() != eModeARM)) 10995 return false; 10996 10997 break; 10998 10999 case eEncodingT2: 11000 case eEncodingA2: 11001 // single_reg = TRUE; add = (U == ‘1’); imm32 = ZeroExtend(imm8:’00’, 32); 11002 single_reg = true; 11003 add = BitIsSet (opcode, 23); 11004 imm32 = Bits32 (opcode, 7, 0) << 2; 11005 11006 // d = UInt(Vd:D); n = UInt(Rn); 11007 d = (Bits32 (opcode, 15, 12) << 1) | Bit32 (opcode, 22); 11008 n = Bits32 (opcode, 19, 16); 11009 11010 // if n == 15 && CurrentInstrSet() != InstrSet_ARM then UNPREDICTABLE; 11011 if ((n == 15) && (CurrentInstrSet() != eModeARM)) 11012 return false; 11013 11014 break; 11015 11016 default: 11017 return false; 11018 } 11019 11020 Register base_reg; 11021 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n); 11022 11023 uint32_t Rn = ReadCoreReg (n, &success); 11024 if (!success) 11025 return false; 11026 11027 // address = if add then (R[n] + imm32) else (R[n] - imm32); 11028 addr_t address; 11029 if (add) 11030 address = Rn + imm32; 11031 else 11032 address = Rn - imm32; 11033 11034 const uint32_t addr_byte_size = GetAddressByteSize(); 11035 uint32_t start_reg = single_reg ? dwarf_s0 : dwarf_d0; 11036 11037 Register data_reg; 11038 data_reg.SetRegister (eRegisterKindDWARF, start_reg + d); 11039 EmulateInstruction::Context context; 11040 context.type = eContextRegisterStore; 11041 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, address - Rn); 11042 11043 if (single_reg) 11044 { 11045 // MemA[address,4] = S[d]; 11046 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, start_reg + d, 0, &success); 11047 if (!success) 11048 return false; 11049 11050 if (!MemAWrite (context, address, data, addr_byte_size)) 11051 return false; 11052 } 11053 else 11054 { 11055 // // Store as two word-aligned words in the correct order for current endianness. 11056 // MemA[address,4] = if BigEndian() then D[d]<63:32> else D[d]<31:0>; 11057 // MemA[address+4,4] = if BigEndian() then D[d]<31:0> else D[d]<63:32>; 11058 uint64_t data = ReadRegisterUnsigned (eRegisterKindDWARF, start_reg + d, 0, &success); 11059 if (!success) 11060 return false; 11061 11062 if (m_byte_order == eByteOrderBig) 11063 { 11064 if (!MemAWrite (context, address, Bits64 (data, 63, 32), addr_byte_size)) 11065 return false; 11066 11067 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, (address + 4) - Rn); 11068 if (!MemAWrite (context, address + 4, Bits64 (data, 31, 0), addr_byte_size)) 11069 return false; 11070 } 11071 else 11072 { 11073 if (!MemAWrite (context, address, Bits64 (data, 31, 0), addr_byte_size)) 11074 return false; 11075 11076 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, (address + 4) - Rn); 11077 if (!MemAWrite (context, address + 4, Bits64 (data, 63, 32), addr_byte_size)) 11078 return false; 11079 } 11080 } 11081 } 11082 return true; 11083} 11084 11085// A8.6.307 VLDI1 (multiple single elements) 11086// This instruction loads elements from memory into one, two, three or four registers, without de-interleaving. Every 11087// element of each register is loaded. 11088bool 11089EmulateInstructionARM::EmulateVLD1Multiple (const uint32_t opcode, ARMEncoding encoding) 11090{ 11091#if 0 11092 if ConditionPassed() then 11093 EncodingSpecificOperations(); CheckAdvSIMDEnabled(); NullCheckIfThumbEE(n); 11094 address = R[n]; if (address MOD alignment) != 0 then GenerateAlignmentException(); 11095 if wback then R[n] = R[n] + (if register_index then R[m] else 8*regs); 11096 for r = 0 to regs-1 11097 for e = 0 to elements-1 11098 Elem[D[d+r],e,esize] = MemU[address,ebytes]; 11099 address = address + ebytes; 11100#endif 11101 11102 bool success = false; 11103 11104 if (ConditionPassed (opcode)) 11105 { 11106 uint32_t regs; 11107 uint32_t alignment; 11108 uint32_t ebytes; 11109 uint32_t esize; 11110 uint32_t elements; 11111 uint32_t d; 11112 uint32_t n; 11113 uint32_t m; 11114 bool wback; 11115 bool register_index; 11116 11117 switch (encoding) 11118 { 11119 case eEncodingT1: 11120 case eEncodingA1: 11121 { 11122 // case type of 11123 // when ‘0111’ 11124 // regs = 1; if align<1> == ‘1’ then UNDEFINED; 11125 // when ‘1010’ 11126 // regs = 2; if align == ‘11’ then UNDEFINED; 11127 // when ‘0110’ 11128 // regs = 3; if align<1> == ‘1’ then UNDEFINED; 11129 // when ‘0010’ 11130 // regs = 4; 11131 // otherwise 11132 // SEE “Related encodings”; 11133 uint32_t type = Bits32 (opcode, 11, 8); 11134 uint32_t align = Bits32 (opcode, 5, 4); 11135 if (type == 7) // '0111' 11136 { 11137 regs = 1; 11138 if (BitIsSet (align, 1)) 11139 return false; 11140 } 11141 else if (type == 10) // '1010' 11142 { 11143 regs = 2; 11144 if (align == 3) 11145 return false; 11146 11147 } 11148 else if (type == 6) // '0110' 11149 { 11150 regs = 3; 11151 if (BitIsSet (align, 1)) 11152 return false; 11153 } 11154 else if (type == 2) // '0010' 11155 { 11156 regs = 4; 11157 } 11158 else 11159 return false; 11160 11161 // alignment = if align == ‘00’ then 1 else 4 << UInt(align); 11162 if (align == 0) 11163 alignment = 1; 11164 else 11165 alignment = 4 << align; 11166 11167 // ebytes = 1 << UInt(size); esize = 8 * ebytes; elements = 8 DIV ebytes; 11168 ebytes = 1 << Bits32 (opcode, 7, 6); 11169 esize = 8 * ebytes; 11170 elements = 8 / ebytes; 11171 11172 // d = UInt(D:Vd); n = UInt(Rn); m = UInt(Rm); 11173 d = (Bit32 (opcode, 22) << 4) | Bits32 (opcode, 15, 12); 11174 n = Bits32 (opcode, 19, 15); 11175 m = Bits32 (opcode, 3, 0); 11176 11177 // wback = (m != 15); register_index = (m != 15 && m != 13); 11178 wback = (m != 15); 11179 register_index = ((m != 15) && (m != 13)); 11180 11181 // if d+regs > 32 then UNPREDICTABLE; 11182 if ((d + regs) > 32) 11183 return false; 11184 } 11185 break; 11186 11187 default: 11188 return false; 11189 } 11190 11191 Register base_reg; 11192 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n); 11193 11194 uint32_t Rn = ReadCoreReg (n, &success); 11195 if (!success) 11196 return false; 11197 11198 // address = R[n]; if (address MOD alignment) != 0 then GenerateAlignmentException(); 11199 addr_t address = Rn; 11200 if ((address % alignment) != 0) 11201 return false; 11202 11203 EmulateInstruction::Context context; 11204 // if wback then R[n] = R[n] + (if register_index then R[m] else 8*regs); 11205 if (wback) 11206 { 11207 uint32_t Rm = ReadCoreReg (m, &success); 11208 if (!success) 11209 return false; 11210 11211 uint32_t offset; 11212 if (register_index) 11213 offset = Rm; 11214 else 11215 offset = 8 * regs; 11216 11217 uint32_t value = Rn + offset; 11218 context.type = eContextAdjustBaseRegister; 11219 context.SetRegisterPlusOffset (base_reg, offset); 11220 11221 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, value)) 11222 return false; 11223 11224 } 11225 11226 // for r = 0 to regs-1 11227 for (int r = 0; r < regs; ++r) 11228 { 11229 // for e = 0 to elements-1 11230 uint64_t assembled_data = 0; 11231 for (int e = 0; e < elements; ++e) 11232 { 11233 // Elem[D[d+r],e,esize] = MemU[address,ebytes]; 11234 context.type = eContextRegisterLoad; 11235 context.SetRegisterPlusOffset (base_reg, address - Rn); 11236 uint64_t data = MemURead (context, address, ebytes, 0, &success); 11237 if (!success) 11238 return false; 11239 11240 assembled_data = (data << (e * esize)) | assembled_data; // New data goes to the left of existing data 11241 11242 // address = address + ebytes; 11243 address = address + ebytes; 11244 } 11245 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_d0 + d + r, assembled_data)) 11246 return false; 11247 } 11248 } 11249 return true; 11250} 11251 11252// A8.6.308 VLD1 (single element to one lane) 11253// 11254bool 11255EmulateInstructionARM::EmulateVLD1Single (const uint32_t opcode, const ARMEncoding encoding) 11256{ 11257#if 0 11258 if ConditionPassed() then 11259 EncodingSpecificOperations(); CheckAdvSIMDEnabled(); NullCheckIfThumbEE(n); 11260 address = R[n]; if (address MOD alignment) != 0 then GenerateAlignmentException(); 11261 if wback then R[n] = R[n] + (if register_index then R[m] else ebytes); 11262 Elem[D[d],index,esize] = MemU[address,ebytes]; 11263#endif 11264 11265 bool success = false; 11266 11267 if (ConditionPassed (opcode)) 11268 { 11269 uint32_t ebytes; 11270 uint32_t esize; 11271 uint32_t index; 11272 uint32_t alignment; 11273 uint32_t d; 11274 uint32_t n; 11275 uint32_t m; 11276 bool wback; 11277 bool register_index; 11278 11279 switch (encoding) 11280 { 11281 case eEncodingT1: 11282 case eEncodingA1: 11283 { 11284 uint32_t size = Bits32 (opcode, 11, 10); 11285 uint32_t index_align = Bits32 (opcode, 7, 4); 11286 // if size == ‘11’ then SEE VLD1 (single element to all lanes); 11287 if (size == 3) 11288 return EmulateVLD1SingleAll (opcode, encoding); 11289 // case size of 11290 if (size == 0) // when '00' 11291 { 11292 // if index_align<0> != ‘0’ then UNDEFINED; 11293 if (BitIsClear (index_align, 0)) 11294 return false; 11295 11296 // ebytes = 1; esize = 8; index = UInt(index_align<3:1>); alignment = 1; 11297 ebytes = 1; 11298 esize = 8; 11299 index = Bits32 (index_align, 3, 1); 11300 alignment = 1; 11301 } 11302 else if (size == 1) // when ‘01’ 11303 { 11304 // if index_align<1> != ‘0’ then UNDEFINED; 11305 if (BitIsClear (index_align, 1)) 11306 return false; 11307 11308 // ebytes = 2; esize = 16; index = UInt(index_align<3:2>); 11309 ebytes = 2; 11310 esize = 16; 11311 index = Bits32 (index_align, 3, 2); 11312 11313 // alignment = if index_align<0> == ‘0’ then 1 else 2; 11314 if (BitIsClear (index_align, 0)) 11315 alignment = 1; 11316 else 11317 alignment = 2; 11318 } 11319 else if (size == 2) // when ‘10’ 11320 { 11321 // if index_align<2> != ‘0’ then UNDEFINED; 11322 if (BitIsClear (index_align, 2)) 11323 return false; 11324 11325 // if index_align<1:0> != ‘00’ && index_align<1:0> != ‘11’ then UNDEFINED; 11326 if ((Bits32 (index_align, 1, 0) != 0) && (Bits32 (index_align, 1, 0) != 3)) 11327 return false; 11328 11329 // ebytes = 4; esize = 32; index = UInt(index_align<3>); 11330 ebytes = 4; 11331 esize = 32; 11332 index = Bit32 (index_align, 3); 11333 11334 // alignment = if index_align<1:0> == ‘00’ then 1 else 4; 11335 if (Bits32 (index_align, 1, 0) == 0) 11336 alignment = 1; 11337 else 11338 alignment = 4; 11339 } 11340 // d = UInt(D:Vd); n = UInt(Rn); m = UInt(Rm); 11341 d = (Bit32 (opcode, 22) << 4) | Bits32 (opcode, 15, 12); 11342 n = Bits32 (opcode, 19, 16); 11343 m = Bits32 (opcode, 3, 0); 11344 11345 // wback = (m != 15); register_index = (m != 15 && m != 13); if n == 15 then UNPREDICTABLE; 11346 wback = (m != 15); 11347 register_index = ((m != 15) && (m != 13)); 11348 11349 if (n == 15) 11350 return false; 11351 11352 } 11353 break; 11354 11355 default: 11356 return false; 11357 } 11358 11359 Register base_reg; 11360 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n); 11361 11362 uint32_t Rn = ReadCoreReg (n, &success); 11363 if (!success) 11364 return false; 11365 11366 // address = R[n]; if (address MOD alignment) != 0 then GenerateAlignmentException(); 11367 addr_t address = Rn; 11368 if ((address % alignment) != 0) 11369 return false; 11370 11371 EmulateInstruction::Context context; 11372 // if wback then R[n] = R[n] + (if register_index then R[m] else ebytes); 11373 if (wback) 11374 { 11375 uint32_t Rm = ReadCoreReg (m, &success); 11376 if (!success) 11377 return false; 11378 11379 uint32_t offset; 11380 if (register_index) 11381 offset = Rm; 11382 else 11383 offset = ebytes; 11384 11385 uint32_t value = Rn + offset; 11386 11387 context.type = eContextAdjustBaseRegister; 11388 context.SetRegisterPlusOffset (base_reg, offset); 11389 11390 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, value)) 11391 return false; 11392 } 11393 11394 // Elem[D[d],index,esize] = MemU[address,ebytes]; 11395 uint32_t element = MemURead (context, address, esize, 0, &success); 11396 if (!success) 11397 return false; 11398 11399 element = element << (index * esize); 11400 11401 uint64_t reg_data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_d0 + d, 0, &success); 11402 if (!success) 11403 return false; 11404 11405 uint64_t all_ones = -1; 11406 uint64_t mask = all_ones << ((index+1) * esize); // mask is all 1's to left of where 'element' goes, & all 0's 11407 // at element & to the right of element. 11408 if (index > 0) 11409 mask = mask | Bits64 (all_ones, (index * esize) - 1, 0); // add 1's to the right of where 'element' goes. 11410 // now mask should be 0's where element goes & 1's 11411 // everywhere else. 11412 11413 uint64_t masked_reg = reg_data & mask; // Take original reg value & zero out 'element' bits 11414 reg_data = masked_reg & element; // Put 'element' into those bits in reg_data. 11415 11416 context.type = eContextRegisterLoad; 11417 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + d, reg_data)) 11418 return false; 11419 } 11420 return true; 11421} 11422 11423// A8.6.391 VST1 (multiple single elements) 11424// Vector Store (multiple single elements) stores elements to memory from one, two, three, or four regsiters, without 11425// interleaving. Every element of each register is stored. 11426bool 11427EmulateInstructionARM::EmulateVST1Multiple (const uint32_t opcode, ARMEncoding encoding) 11428{ 11429#if 0 11430 if ConditionPassed() then 11431 EncodingSpecificOperations(); CheckAdvSIMDEnabled(); NullCheckIfThumbEE(n); 11432 address = R[n]; if (address MOD alignment) != 0 then GenerateAlignmentException(); 11433 if wback then R[n] = R[n] + (if register_index then R[m] else 8*regs); 11434 for r = 0 to regs-1 11435 for e = 0 to elements-1 11436 MemU[address,ebytes] = Elem[D[d+r],e,esize]; 11437 address = address + ebytes; 11438#endif 11439 11440 bool success = false; 11441 11442 if (ConditionPassed (opcode)) 11443 { 11444 uint32_t regs; 11445 uint32_t alignment; 11446 uint32_t ebytes; 11447 uint32_t esize; 11448 uint32_t elements; 11449 uint32_t d; 11450 uint32_t n; 11451 uint32_t m; 11452 bool wback; 11453 bool register_index; 11454 11455 switch (encoding) 11456 { 11457 case eEncodingT1: 11458 case eEncodingA1: 11459 { 11460 uint32_t type = Bits32 (opcode, 11, 8); 11461 uint32_t align = Bits32 (opcode, 5, 4); 11462 11463 // case type of 11464 if (type == 7) // when ‘0111’ 11465 { 11466 // regs = 1; if align<1> == ‘1’ then UNDEFINED; 11467 regs = 1; 11468 if (BitIsSet (align, 1)) 11469 return false; 11470 } 11471 else if (type == 10) // when ‘1010’ 11472 { 11473 // regs = 2; if align == ‘11’ then UNDEFINED; 11474 regs = 2; 11475 if (align == 3) 11476 return false; 11477 } 11478 else if (type == 6) // when ‘0110’ 11479 { 11480 // regs = 3; if align<1> == ‘1’ then UNDEFINED; 11481 regs = 3; 11482 if (BitIsSet (align, 1)) 11483 return false; 11484 } 11485 else if (type == 2) // when ‘0010’ 11486 // regs = 4; 11487 regs = 4; 11488 else // otherwise 11489 // SEE “Related encodings”; 11490 return false; 11491 11492 // alignment = if align == ‘00’ then 1 else 4 << UInt(align); 11493 if (align == 0) 11494 alignment = 0; 11495 else 11496 alignment = 4 << align; 11497 11498 // ebytes = 1 << UInt(size); esize = 8 * ebytes; elements = 8 DIV ebytes; 11499 ebytes = 1 << Bits32 (opcode,7, 6); 11500 esize = 8 * ebytes; 11501 elements = 8 / ebytes; 11502 11503 // d = UInt(D:Vd); n = UInt(Rn); m = UInt(Rm); 11504 d = (Bit32 (opcode, 22) << 4) | Bits32 (opcode, 15, 12); 11505 n = Bits32 (opcode, 19, 16); 11506 m = Bits32 (opcode, 3, 0); 11507 11508 // wback = (m != 15); register_index = (m != 15 && m != 13); 11509 wback = (m != 15); 11510 register_index = ((m != 15) && (m != 13)); 11511 11512 // if d+regs > 32 then UNPREDICTABLE; if n == 15 then UNPREDICTABLE; 11513 if ((d + regs) > 32) 11514 return false; 11515 11516 if (n == 15) 11517 return false; 11518 11519 } 11520 break; 11521 11522 default: 11523 return false; 11524 } 11525 11526 Register base_reg; 11527 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n); 11528 11529 uint32_t Rn = ReadCoreReg (n, &success); 11530 if (!success) 11531 return false; 11532 11533 // address = R[n]; if (address MOD alignment) != 0 then GenerateAlignmentException(); 11534 addr_t address = Rn; 11535 if ((address % alignment) != 0) 11536 return false; 11537 11538 EmulateInstruction::Context context; 11539 // if wback then R[n] = R[n] + (if register_index then R[m] else 8*regs); 11540 if (wback) 11541 { 11542 uint32_t Rm = ReadCoreReg (m, &success); 11543 if (!success) 11544 return false; 11545 11546 uint32_t offset; 11547 if (register_index) 11548 offset = Rm; 11549 else 11550 offset = 8 * regs; 11551 11552 context.type = eContextAdjustBaseRegister; 11553 context.SetRegisterPlusOffset (base_reg, offset); 11554 11555 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, Rn + offset)) 11556 return false; 11557 } 11558 11559 context.type = eContextRegisterStore; 11560 Register data_reg; 11561 data_reg.SetRegister (eRegisterKindDWARF, 0); 11562 // for r = 0 to regs-1 11563 for (int r = 0; r < regs; ++r) 11564 { 11565 data_reg.num = dwarf_d0 + d + r; 11566 uint64_t register_data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_d0 + d + r, 0, &success); 11567 if (!success) 11568 return false; 11569 11570 // for e = 0 to elements-1 11571 for (int e = 0; e < elements; ++e) 11572 { 11573 // MemU[address,ebytes] = Elem[D[d+r],e,esize]; 11574 uint64_t word = Bits64 (register_data, ((e + 1) * esize) - 1, e * esize); 11575 11576 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, address - Rn); 11577 if (!MemUWrite (context, address, word, ebytes)) 11578 return false; 11579 11580 // address = address + ebytes; 11581 address = address + ebytes; 11582 } 11583 } 11584 } 11585 return true; 11586} 11587 11588// A8.6.392 VST1 (single element from one lane) 11589// This instruction stores one element to memory from one element of a register. 11590bool 11591EmulateInstructionARM::EmulateVST1Single (const uint32_t opcode, ARMEncoding encoding) 11592{ 11593#if 0 11594 if ConditionPassed() then 11595 EncodingSpecificOperations(); CheckAdvSIMDEnabled(); NullCheckIfThumbEE(n); 11596 address = R[n]; if (address MOD alignment) != 0 then GenerateAlignmentException(); 11597 if wback then R[n] = R[n] + (if register_index then R[m] else ebytes); 11598 MemU[address,ebytes] = Elem[D[d],index,esize]; 11599#endif 11600 11601 bool success = false; 11602 11603 if (ConditionPassed (opcode)) 11604 { 11605 uint32_t ebytes; 11606 uint32_t esize; 11607 uint32_t index; 11608 uint32_t alignment; 11609 uint32_t d; 11610 uint32_t n; 11611 uint32_t m; 11612 bool wback; 11613 bool register_index; 11614 11615 switch (encoding) 11616 { 11617 case eEncodingT1: 11618 case eEncodingA1: 11619 { 11620 uint32_t size = Bits32 (opcode, 11, 10); 11621 uint32_t index_align = Bits32 (opcode, 7, 4); 11622 11623 // if size == ‘11’ then UNDEFINED; 11624 if (size == 3) 11625 return false; 11626 11627 // case size of 11628 if (size == 0) // when ‘00’ 11629 { 11630 // if index_align<0> != ‘0’ then UNDEFINED; 11631 if (BitIsClear (index_align, 0)) 11632 return false; 11633 // ebytes = 1; esize = 8; index = UInt(index_align<3:1>); alignment = 1; 11634 ebytes = 1; 11635 esize = 8; 11636 index = Bits32 (index_align, 3, 1); 11637 alignment = 1; 11638 } 11639 else if (size == 1) // when ‘01’ 11640 { 11641 // if index_align<1> != ‘0’ then UNDEFINED; 11642 if (BitIsClear (index_align, 1)) 11643 return false; 11644 11645 // ebytes = 2; esize = 16; index = UInt(index_align<3:2>); 11646 ebytes = 2; 11647 esize = 16; 11648 index = Bits32 (index_align, 3, 2); 11649 11650 // alignment = if index_align<0> == ‘0’ then 1 else 2; 11651 if (BitIsClear (index_align, 0)) 11652 alignment = 1; 11653 else 11654 alignment = 2; 11655 } 11656 else if (size == 2) // when ‘10’ 11657 { 11658 // if index_align<2> != ‘0’ then UNDEFINED; 11659 if (BitIsClear (index_align, 2)) 11660 return false; 11661 11662 // if index_align<1:0> != ‘00’ && index_align<1:0> != ‘11’ then UNDEFINED; 11663 if ((Bits32 (index_align, 1, 0) != 0) && (Bits32 (index_align, 1, 0) != 3)) 11664 return false; 11665 11666 // ebytes = 4; esize = 32; index = UInt(index_align<3>); 11667 ebytes = 4; 11668 esize = 32; 11669 index = Bit32 (index_align, 3); 11670 11671 // alignment = if index_align<1:0> == ‘00’ then 1 else 4; 11672 if (Bits32 (index_align, 1, 0) == 0) 11673 alignment = 1; 11674 else 11675 alignment = 4; 11676 } 11677 // d = UInt(D:Vd); n = UInt(Rn); m = UInt(Rm); 11678 d = (Bit32 (opcode, 22) << 4) | Bits32 (opcode, 15, 12); 11679 n = Bits32 (opcode, 19, 16); 11680 m = Bits32 (opcode, 3, 0); 11681 11682 // wback = (m != 15); register_index = (m != 15 && m != 13); if n == 15 then UNPREDICTABLE; 11683 wback = (m != 15); 11684 register_index = ((m != 15) && (m != 13)); 11685 11686 if (n == 15) 11687 return false; 11688 } 11689 break; 11690 11691 default: 11692 return false; 11693 } 11694 11695 Register base_reg; 11696 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n); 11697 11698 uint32_t Rn = ReadCoreReg (n, &success); 11699 if (!success) 11700 return false; 11701 11702 // address = R[n]; if (address MOD alignment) != 0 then GenerateAlignmentException(); 11703 addr_t address = Rn; 11704 if ((address % alignment) != 0) 11705 return false; 11706 11707 EmulateInstruction::Context context; 11708 // if wback then R[n] = R[n] + (if register_index then R[m] else ebytes); 11709 if (wback) 11710 { 11711 uint32_t Rm = ReadCoreReg (m, &success); 11712 if (!success) 11713 return false; 11714 11715 uint32_t offset; 11716 if (register_index) 11717 offset = Rm; 11718 else 11719 offset = ebytes; 11720 11721 context.type = eContextAdjustBaseRegister; 11722 context.SetRegisterPlusOffset (base_reg, offset); 11723 11724 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, Rn + offset)) 11725 return false; 11726 } 11727 11728 // MemU[address,ebytes] = Elem[D[d],index,esize]; 11729 uint64_t register_data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_d0 + d, 0, &success); 11730 if (!success) 11731 return false; 11732 11733 uint64_t word = Bits64 (register_data, ((index + 1) * esize) - 1, index * esize); 11734 11735 Register data_reg; 11736 data_reg.SetRegister (eRegisterKindDWARF, dwarf_d0 + d); 11737 context.type = eContextRegisterStore; 11738 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, address - Rn); 11739 11740 if (!MemUWrite (context, address, word, ebytes)) 11741 return false; 11742 } 11743 return true; 11744} 11745 11746// A8.6.309 VLD1 (single element to all lanes) 11747// This instruction loads one element from memory into every element of one or two vectors. 11748bool 11749EmulateInstructionARM::EmulateVLD1SingleAll (const uint32_t opcode, const ARMEncoding encoding) 11750{ 11751#if 0 11752 if ConditionPassed() then 11753 EncodingSpecificOperations(); CheckAdvSIMDEnabled(); NullCheckIfThumbEE(n); 11754 address = R[n]; if (address MOD alignment) != 0 then GenerateAlignmentException(); 11755 if wback then R[n] = R[n] + (if register_index then R[m] else ebytes); 11756 replicated_element = Replicate(MemU[address,ebytes], elements); 11757 for r = 0 to regs-1 11758 D[d+r] = replicated_element; 11759#endif 11760 11761 bool success = false; 11762 11763 if (ConditionPassed (opcode)) 11764 { 11765 uint32_t ebytes; 11766 uint32_t elements; 11767 uint32_t regs; 11768 uint32_t alignment; 11769 uint32_t d; 11770 uint32_t n; 11771 uint32_t m; 11772 bool wback; 11773 bool register_index; 11774 11775 switch (encoding) 11776 { 11777 case eEncodingT1: 11778 case eEncodingA1: 11779 { 11780 //if size == ‘11’ || (size == ‘00’ && a == ‘1’) then UNDEFINED; 11781 uint32_t size = Bits32 (opcode, 7, 6); 11782 if ((size == 3) || ((size == 0) && BitIsSet (opcode, 4))) 11783 return false; 11784 11785 //ebytes = 1 << UInt(size); elements = 8 DIV ebytes; regs = if T == ‘0’ then 1 else 2; 11786 ebytes = 1 << size; 11787 elements = 8 / ebytes; 11788 if (BitIsClear (opcode, 5)) 11789 regs = 1; 11790 else 11791 regs = 2; 11792 11793 //alignment = if a == ‘0’ then 1 else ebytes; 11794 if (BitIsClear (opcode, 4)) 11795 alignment = 1; 11796 else 11797 alignment = ebytes; 11798 11799 //d = UInt(D:Vd); n = UInt(Rn); m = UInt(Rm); 11800 d = (Bit32 (opcode, 22) << 4) | Bits32 (opcode, 15, 12); 11801 n = Bits32 (opcode, 19, 16); 11802 m = Bits32 (opcode, 3, 0); 11803 11804 //wback = (m != 15); register_index = (m != 15 && m != 13); 11805 wback = (m != 15); 11806 register_index = ((m != 15) && (m != 13)); 11807 11808 //if d+regs > 32 then UNPREDICTABLE; if n == 15 then UNPREDICTABLE; 11809 if ((d + regs) > 32) 11810 return false; 11811 11812 if (n == 15) 11813 return false; 11814 } 11815 break; 11816 11817 default: 11818 break; 11819 } 11820 11821 Register base_reg; 11822 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 +n); 11823 11824 uint32_t Rn = ReadCoreReg (n, &success); 11825 if (!success) 11826 return false; 11827 11828 // address = R[n]; if (address MOD alignment) != 0 then GenerateAlignmentException(); 11829 addr_t address = Rn; 11830 if ((address % alignment) != 0) 11831 return false; 11832 11833 EmulateInstruction::Context context; 11834 // if wback then R[n] = R[n] + (if register_index then R[m] else ebytes); 11835 if (wback) 11836 { 11837 uint32_t Rm = ReadCoreReg (m, &success); 11838 if (!success) 11839 return false; 11840 11841 uint32_t offset; 11842 if (register_index) 11843 offset = Rm; 11844 else 11845 offset = ebytes; 11846 11847 context.type = eContextAdjustBaseRegister; 11848 context.SetRegisterPlusOffset (base_reg, offset); 11849 11850 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, Rn + offset)) 11851 return false; 11852 } 11853 11854 // replicated_element = Replicate(MemU[address,ebytes], elements); 11855 11856 context.type = eContextRegisterLoad; 11857 uint64_t word = MemURead (context, address, ebytes, 0, &success); 11858 if (!success) 11859 return false; 11860 11861 uint64_t replicated_element; 11862 uint32_t esize = ebytes * 8; 11863 for (int e = 0; e < elements; ++e) 11864 replicated_element = (replicated_element << esize) | Bits64 (word, esize - 1, 0); 11865 11866 // for r = 0 to regs-1 11867 for (int r = 0; r < regs; ++r) 11868 { 11869 // D[d+r] = replicated_element; 11870 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_d0 + d + r, replicated_element)) 11871 return false; 11872 } 11873 } 11874 return true; 11875} 11876 11877// B6.2.13 SUBS PC, LR and related instructions 11878//The SUBS PC, LR, #<const? instruction provides an exception return without the use of the stack. It subtracts the 11879// immediate constant from the LR, branches to the resulting address, and also copies the SPSR to the CPSR. 11880bool 11881EmulateInstructionARM::EmulateSUBSPcLrEtc (const uint32_t opcode, const ARMEncoding encoding) 11882{ 11883#if 0 11884 if ConditionPassed() then 11885 EncodingSpecificOperations(); 11886 if CurrentInstrSet() == InstrSet_ThumbEE then 11887 UNPREDICTABLE; 11888 operand2 = if register_form then Shift(R[m], shift_t, shift_n, APSR.C) else imm32; 11889 case opcode of 11890 when ‘0000’ result = R[n] AND operand2; // AND 11891 when ‘0001’ result = R[n] EOR operand2; // EOR 11892 when ‘0010’ (result, -, -) = AddWithCarry(R[n], NOT(operand2), ‘1’); // SUB 11893 when ‘0011’ (result, -, -) = AddWithCarry(NOT(R[n]), operand2, ‘1’); // RSB 11894 when ‘0100’ (result, -, -) = AddWithCarry(R[n], operand2, ‘0’); // ADD 11895 when ‘0101’ (result, -, -) = AddWithCarry(R[n], operand2, APSR.c); // ADC 11896 when ‘0110’ (result, -, -) = AddWithCarry(R[n], NOT(operand2), APSR.C); // SBC 11897 when ‘0111’ (result, -, -) = AddWithCarry(NOT(R[n]), operand2, APSR.C); // RSC 11898 when ‘1100’ result = R[n] OR operand2; // ORR 11899 when ‘1101’ result = operand2; // MOV 11900 when ‘1110’ result = R[n] AND NOT(operand2); // BIC 11901 when ‘1111’ result = NOT(operand2); // MVN 11902 CPSRWriteByInstr(SPSR[], ‘1111’, TRUE); 11903 BranchWritePC(result); 11904#endif 11905 11906 bool success = false; 11907 11908 if (ConditionPassed (opcode)) 11909 { 11910 uint32_t n; 11911 uint32_t m; 11912 uint32_t imm32; 11913 bool register_form; 11914 ARM_ShifterType shift_t; 11915 uint32_t shift_n; 11916 uint32_t code; 11917 11918 switch (encoding) 11919 { 11920 case eEncodingT1: 11921 // if CurrentInstrSet() == InstrSet_ThumbEE then UNPREDICTABLE 11922 // n = 14; imm32 = ZeroExtend(imm8, 32); register_form = FALSE; opcode = ‘0010’; // = SUB 11923 n = 14; 11924 imm32 = Bits32 (opcode, 7, 0); 11925 register_form = false; 11926 code = 2; 11927 11928 // if InITBlock() && !LastInITBlock() then UNPREDICTABLE; 11929 if (InITBlock() && !LastInITBlock()) 11930 return false; 11931 11932 break; 11933 11934 case eEncodingA1: 11935 // n = UInt(Rn); imm32 = ARMExpandImm(imm12); register_form = FALSE; 11936 n = Bits32 (opcode, 19, 16); 11937 imm32 = ARMExpandImm (opcode); 11938 register_form = false; 11939 code = Bits32 (opcode, 24, 21); 11940 11941 break; 11942 11943 case eEncodingA2: 11944 // n = UInt(Rn); m = UInt(Rm); register_form = TRUE; 11945 n = Bits32 (opcode, 19, 16); 11946 m = Bits32 (opcode, 3, 0); 11947 register_form = true; 11948 11949 // (shift_t, shift_n) = DecodeImmShift(type, imm5); 11950 shift_n = DecodeImmShiftARM (opcode, shift_t); 11951 11952 break; 11953 11954 default: 11955 return false; 11956 } 11957 11958 // operand2 = if register_form then Shift(R[m], shift_t, shift_n, APSR.C) else imm32; 11959 uint32_t operand2; 11960 if (register_form) 11961 { 11962 uint32_t Rm = ReadCoreReg (m, &success); 11963 if (!success) 11964 return false; 11965 11966 operand2 = Shift (Rm, shift_t, shift_n, APSR_C); 11967 11968 } 11969 else 11970 { 11971 operand2 = imm32; 11972 } 11973 11974 uint32_t Rn = ReadCoreReg (n, &success); 11975 if (!success) 11976 return false; 11977 11978 AddWithCarryResult result; 11979 11980 // case opcode of 11981 switch (code) 11982 { 11983 case 0: // when ‘0000’ 11984 // result = R[n] AND operand2; // AND 11985 result.result = Rn & operand2; 11986 break; 11987 11988 case 1: // when ‘0001’ 11989 // result = R[n] EOR operand2; // EOR 11990 result.result = Rn ^ operand2; 11991 break; 11992 11993 case 2: // when ‘0010’ 11994 // (result, -, -) = AddWithCarry(R[n], NOT(operand2), ‘1’); // SUB 11995 result = AddWithCarry (Rn, ~(operand2), 1); 11996 break; 11997 11998 case 3: // when ‘0011’ 11999 // (result, -, -) = AddWithCarry(NOT(R[n]), operand2, ‘1’); // RSB 12000 result = AddWithCarry (~(Rn), operand2, 1); 12001 break; 12002 12003 case 4: // when ‘0100’ 12004 // (result, -, -) = AddWithCarry(R[n], operand2, ‘0’); // ADD 12005 result = AddWithCarry (Rn, operand2, 0); 12006 break; 12007 12008 case 5: // when ‘0101’ 12009 // (result, -, -) = AddWithCarry(R[n], operand2, APSR.c); // ADC 12010 result = AddWithCarry (Rn, operand2, APSR_C); 12011 break; 12012 12013 case 6: // when ‘0110’ 12014 // (result, -, -) = AddWithCarry(R[n], NOT(operand2), APSR.C); // SBC 12015 result = AddWithCarry (Rn, ~(operand2), APSR_C); 12016 break; 12017 12018 case 7: // when ‘0111’ 12019 // (result, -, -) = AddWithCarry(NOT(R[n]), operand2, APSR.C); // RSC 12020 result = AddWithCarry (~(Rn), operand2, APSR_C); 12021 break; 12022 12023 case 10: // when ‘1100’ 12024 // result = R[n] OR operand2; // ORR 12025 result.result = Rn | operand2; 12026 break; 12027 12028 case 11: // when ‘1101’ 12029 // result = operand2; // MOV 12030 result.result = operand2; 12031 break; 12032 12033 case 12: // when ‘1110’ 12034 // result = R[n] AND NOT(operand2); // BIC 12035 result.result = Rn & ~(operand2); 12036 break; 12037 12038 case 15: // when ‘1111’ 12039 // result = NOT(operand2); // MVN 12040 result.result = ~(operand2); 12041 break; 12042 12043 default: 12044 return false; 12045 } 12046 // CPSRWriteByInstr(SPSR[], ‘1111’, TRUE); 12047 12048 // For now, in emulation mode, we don't have access to the SPSR, so we will use the CPSR instead, and hope for 12049 // the best. 12050 uint32_t spsr = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_cpsr, 0, &success); 12051 if (!success) 12052 return false; 12053 12054 CPSRWriteByInstr (spsr, 15, true); 12055 12056 // BranchWritePC(result); 12057 EmulateInstruction::Context context; 12058 context.type = eContextAdjustPC; 12059 context.SetImmediate (result.result); 12060 12061 BranchWritePC (context, result.result); 12062 } 12063 return true; 12064} 12065 12066EmulateInstructionARM::ARMOpcode* 12067EmulateInstructionARM::GetARMOpcodeForInstruction (const uint32_t opcode) 12068{ 12069 static ARMOpcode 12070 g_arm_opcodes[] = 12071 { 12072 //---------------------------------------------------------------------- 12073 // Prologue instructions 12074 //---------------------------------------------------------------------- 12075 12076 // push register(s) 12077 { 0x0fff0000, 0x092d0000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulatePUSH, "push <registers>" }, 12078 { 0x0fff0fff, 0x052d0004, ARMvAll, eEncodingA2, No_VFP, eSize32, &EmulateInstructionARM::EmulatePUSH, "push <register>" }, 12079 12080 // set r7 to point to a stack offset 12081 { 0x0ffff000, 0x028d7000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateADDRdSPImm, "add r7, sp, #<const>" }, 12082 { 0x0ffff000, 0x024c7000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBR7IPImm, "sub r7, ip, #<const>"}, 12083 // copy the stack pointer to ip 12084 { 0x0fffffff, 0x01a0c00d, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateMOVRdSP, "mov ip, sp" }, 12085 { 0x0ffff000, 0x028dc000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateADDRdSPImm, "add ip, sp, #<const>" }, 12086 { 0x0ffff000, 0x024dc000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBIPSPImm, "sub ip, sp, #<const>"}, 12087 12088 // adjust the stack pointer 12089 { 0x0ffff000, 0x024dd000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBSPImm, "sub sp, sp, #<const>"}, 12090 { 0x0fef0010, 0x004d0000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBSPReg, "sub{s}<c> <Rd>, sp, <Rm>{,<shift>}" }, 12091 12092 // push one register 12093 // if Rn == '1101' && imm12 == '000000000100' then SEE PUSH; 12094 { 0x0e5f0000, 0x040d0000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTRRtSP, "str Rt, [sp, #-imm12]!" }, 12095 12096 // vector push consecutive extension register(s) 12097 { 0x0fbf0f00, 0x0d2d0b00, ARMV6T2_ABOVE, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateVPUSH, "vpush.64 <list>"}, 12098 { 0x0fbf0f00, 0x0d2d0a00, ARMV6T2_ABOVE, eEncodingA2, No_VFP, eSize32, &EmulateInstructionARM::EmulateVPUSH, "vpush.32 <list>"}, 12099 12100 //---------------------------------------------------------------------- 12101 // Epilogue instructions 12102 //---------------------------------------------------------------------- 12103 12104 { 0x0fff0000, 0x08bd0000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulatePOP, "pop <registers>"}, 12105 { 0x0fff0fff, 0x049d0004, ARMvAll, eEncodingA2, No_VFP, eSize32, &EmulateInstructionARM::EmulatePOP, "pop <register>"}, 12106 { 0x0fbf0f00, 0x0cbd0b00, ARMV6T2_ABOVE, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateVPOP, "vpop.64 <list>"}, 12107 { 0x0fbf0f00, 0x0cbd0a00, ARMV6T2_ABOVE, eEncodingA2, No_VFP, eSize32, &EmulateInstructionARM::EmulateVPOP, "vpop.32 <list>"}, 12108 12109 //---------------------------------------------------------------------- 12110 // Supervisor Call (previously Software Interrupt) 12111 //---------------------------------------------------------------------- 12112 { 0x0f000000, 0x0f000000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSVC, "svc #imm24"}, 12113 12114 //---------------------------------------------------------------------- 12115 // Branch instructions 12116 //---------------------------------------------------------------------- 12117 { 0x0f000000, 0x0a000000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateB, "b #imm24"}, 12118 // To resolve ambiguity, "blx <label>" should come before "bl <label>". 12119 { 0xfe000000, 0xfa000000, ARMV5_ABOVE, eEncodingA2, No_VFP, eSize32, &EmulateInstructionARM::EmulateBLXImmediate, "blx <label>"}, 12120 { 0x0f000000, 0x0b000000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateBLXImmediate, "bl <label>"}, 12121 { 0x0ffffff0, 0x012fff30, ARMV5_ABOVE, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateBLXRm, "blx <Rm>"}, 12122 // for example, "bx lr" 12123 { 0x0ffffff0, 0x012fff10, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateBXRm, "bx <Rm>"}, 12124 // bxj 12125 { 0x0ffffff0, 0x012fff20, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateBXJRm, "bxj <Rm>"}, 12126 12127 //---------------------------------------------------------------------- 12128 // Data-processing instructions 12129 //---------------------------------------------------------------------- 12130 // adc (immediate) 12131 { 0x0fe00000, 0x02a00000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateADCImm, "adc{s}<c> <Rd>, <Rn>, #const"}, 12132 // adc (register) 12133 { 0x0fe00010, 0x00a00000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateADCReg, "adc{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"}, 12134 // add (immediate) 12135 { 0x0fe00000, 0x02800000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateADDImmARM, "add{s}<c> <Rd>, <Rn>, #const"}, 12136 // add (register) 12137 { 0x0fe00010, 0x00800000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateADDReg, "add{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"}, 12138 // add (register-shifted register) 12139 { 0x0fe00090, 0x00800010, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateADDRegShift, "add{s}<c> <Rd>, <Rn>, <Rm>, <type> <RS>"}, 12140 // adr 12141 { 0x0fff0000, 0x028f0000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateADR, "add<c> <Rd>, PC, #<const>"}, 12142 { 0x0fff0000, 0x024f0000, ARMvAll, eEncodingA2, No_VFP, eSize32, &EmulateInstructionARM::EmulateADR, "sub<c> <Rd>, PC, #<const>"}, 12143 // and (immediate) 12144 { 0x0fe00000, 0x02000000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateANDImm, "and{s}<c> <Rd>, <Rn>, #const"}, 12145 // and (register) 12146 { 0x0fe00010, 0x00000000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateANDReg, "and{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"}, 12147 // bic (immediate) 12148 { 0x0fe00000, 0x03c00000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateBICImm, "bic{s}<c> <Rd>, <Rn>, #const"}, 12149 // bic (register) 12150 { 0x0fe00010, 0x01c00000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateBICReg, "bic{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"}, 12151 // eor (immediate) 12152 { 0x0fe00000, 0x02200000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateEORImm, "eor{s}<c> <Rd>, <Rn>, #const"}, 12153 // eor (register) 12154 { 0x0fe00010, 0x00200000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateEORReg, "eor{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"}, 12155 // orr (immediate) 12156 { 0x0fe00000, 0x03800000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateORRImm, "orr{s}<c> <Rd>, <Rn>, #const"}, 12157 // orr (register) 12158 { 0x0fe00010, 0x01800000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateORRReg, "orr{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"}, 12159 // rsb (immediate) 12160 { 0x0fe00000, 0x02600000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateRSBImm, "rsb{s}<c> <Rd>, <Rn>, #<const>"}, 12161 // rsb (register) 12162 { 0x0fe00010, 0x00600000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateRSBReg, "rsb{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"}, 12163 // rsc (immediate) 12164 { 0x0fe00000, 0x02e00000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateRSCImm, "rsc{s}<c> <Rd>, <Rn>, #<const>"}, 12165 // rsc (register) 12166 { 0x0fe00010, 0x00e00000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateRSCReg, "rsc{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"}, 12167 // sbc (immediate) 12168 { 0x0fe00000, 0x02c00000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSBCImm, "sbc{s}<c> <Rd>, <Rn>, #<const>"}, 12169 // sbc (register) 12170 { 0x0fe00010, 0x00c00000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSBCReg, "sbc{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"}, 12171 // sub (immediate, ARM) 12172 { 0x0fe00000, 0x02400000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBImmARM, "sub{s}<c> <Rd>, <Rn>, #<const>"}, 12173 // sub (sp minus immediate) 12174 { 0x0fef0000, 0x024d0000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBSPImm, "sub{s}<c> <Rd>, sp, #<const>"}, 12175 // sub (register) 12176 { 0x0fe00010, 0x00400000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBReg, "sub{s}<c> <Rd>, <Rn>, <Rm>{,<shift>}"}, 12177 // teq (immediate) 12178 { 0x0ff0f000, 0x03300000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateTEQImm, "teq<c> <Rn>, #const"}, 12179 // teq (register) 12180 { 0x0ff0f010, 0x01300000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateTEQReg, "teq<c> <Rn>, <Rm> {,<shift>}"}, 12181 // tst (immediate) 12182 { 0x0ff0f000, 0x03100000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateTSTImm, "tst<c> <Rn>, #const"}, 12183 // tst (register) 12184 { 0x0ff0f010, 0x01100000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateTSTReg, "tst<c> <Rn>, <Rm> {,<shift>}"}, 12185 12186 // mov (immediate) 12187 { 0x0fef0000, 0x03a00000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateMOVRdImm, "mov{s}<c> <Rd>, #<const>"}, 12188 { 0x0ff00000, 0x03000000, ARMV6T2_ABOVE, eEncodingA2, No_VFP, eSize32, &EmulateInstructionARM::EmulateMOVRdImm, "movw<c> <Rd>, #<imm16>" }, 12189 // mov (register) 12190 { 0x0fef0ff0, 0x01a00000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateMOVRdRm, "mov{s}<c> <Rd>, <Rm>"}, 12191 // mvn (immediate) 12192 { 0x0fef0000, 0x03e00000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateMVNImm, "mvn{s}<c> <Rd>, #<const>"}, 12193 // mvn (register) 12194 { 0x0fef0010, 0x01e00000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateMVNReg, "mvn{s}<c> <Rd>, <Rm> {,<shift>}"}, 12195 // cmn (immediate) 12196 { 0x0ff0f000, 0x03700000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateCMNImm, "cmn<c> <Rn>, #<const>"}, 12197 // cmn (register) 12198 { 0x0ff0f010, 0x01700000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateCMNReg, "cmn<c> <Rn>, <Rm> {,<shift>}"}, 12199 // cmp (immediate) 12200 { 0x0ff0f000, 0x03500000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateCMPImm, "cmp<c> <Rn>, #<const>"}, 12201 // cmp (register) 12202 { 0x0ff0f010, 0x01500000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateCMPReg, "cmp<c> <Rn>, <Rm> {,<shift>}"}, 12203 // asr (immediate) 12204 { 0x0fef0070, 0x01a00040, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateASRImm, "asr{s}<c> <Rd>, <Rm>, #imm"}, 12205 // asr (register) 12206 { 0x0fef00f0, 0x01a00050, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateASRReg, "asr{s}<c> <Rd>, <Rn>, <Rm>"}, 12207 // lsl (immediate) 12208 { 0x0fef0070, 0x01a00000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLSLImm, "lsl{s}<c> <Rd>, <Rm>, #imm"}, 12209 // lsl (register) 12210 { 0x0fef00f0, 0x01a00010, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLSLReg, "lsl{s}<c> <Rd>, <Rn>, <Rm>"}, 12211 // lsr (immediate) 12212 { 0x0fef0070, 0x01a00020, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLSRImm, "lsr{s}<c> <Rd>, <Rm>, #imm"}, 12213 // lsr (register) 12214 { 0x0fef00f0, 0x01a00050, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLSRReg, "lsr{s}<c> <Rd>, <Rn>, <Rm>"}, 12215 // rrx is a special case encoding of ror (immediate) 12216 { 0x0fef0ff0, 0x01a00060, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateRRX, "rrx{s}<c> <Rd>, <Rm>"}, 12217 // ror (immediate) 12218 { 0x0fef0070, 0x01a00060, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateRORImm, "ror{s}<c> <Rd>, <Rm>, #imm"}, 12219 // ror (register) 12220 { 0x0fef00f0, 0x01a00070, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateRORReg, "ror{s}<c> <Rd>, <Rn>, <Rm>"}, 12221 // mul 12222 { 0x0fe000f0, 0x00000090, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateMUL, "mul{s}<c> <Rd>,<R>,<Rm>" }, 12223 12224 // subs pc, lr and related instructions 12225 { 0x0e10f000, 0x0210f000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBSPcLrEtc, "<opc>S<c> PC,#<const> | <Rn>,#<const>" }, 12226 { 0x0e10f010, 0x0010f000, ARMvAll, eEncodingA2, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBSPcLrEtc, "<opc>S<c> PC,<Rn>,<Rm{,<shift>}" }, 12227 12228 //---------------------------------------------------------------------- 12229 // Load instructions 12230 //---------------------------------------------------------------------- 12231 { 0x0fd00000, 0x08900000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDM, "ldm<c> <Rn>{!} <registers>" }, 12232 { 0x0fd00000, 0x08100000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDMDA, "ldmda<c> <Rn>{!} <registers>" }, 12233 { 0x0fd00000, 0x09100000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDMDB, "ldmdb<c> <Rn>{!} <registers>" }, 12234 { 0x0fd00000, 0x09900000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDMIB, "ldmib<c> <Rn<{!} <registers>" }, 12235 { 0x0e500000, 0x04100000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRImmediateARM, "ldr<c> <Rt> [<Rn> {#+/-<imm12>}]" }, 12236 { 0x0e500010, 0x06100000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRRegister, "ldr<c> <Rt> [<Rn> +/-<Rm> {<shift>}] {!}" }, 12237 { 0x0e5f0000, 0x045f0000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRBLiteral, "ldrb<c> <Rt>, [...]"}, 12238 { 0xfe500010, 0x06500000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRBRegister, "ldrb<c> <Rt>, [<Rn>,+/-<Rm>{, <shift>}]{!}" }, 12239 { 0x0e5f00f0, 0x005f00b0, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRHLiteral, "ldrh<c> <Rt>, <label>" }, 12240 { 0x0e5000f0, 0x001000b0, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRHRegister, "ldrh<c> <Rt>,[<Rn>,+/-<Rm>]{!}" }, 12241 { 0x0e5000f0, 0x005000d0, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRSBImmediate, "ldrsb<c> <Rt>, [<Rn>{,#+/-<imm8>}]" }, 12242 { 0x0e5f00f0, 0x005f00d0, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRSBLiteral, "ldrsb<c> <Rt> <label>" }, 12243 { 0x0e5000f0, 0x001000d0, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRSBRegister, "ldrsb<c> <Rt>,[<Rn>,+/-<Rm>]{!}" }, 12244 { 0x0e5000f0, 0x005000f0, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRSHImmediate, "ldrsh<c> <Rt>,[<Rn>{,#+/-<imm8>}]"}, 12245 { 0x0e5f00f0, 0x005f00f0, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRSHLiteral, "ldrsh<c> <Rt>,<label>" }, 12246 { 0x0e5000f0, 0x001000f0, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRSHRegister, "ldrsh<c> <Rt>,[<Rn>,+/-<Rm>]{!}" }, 12247 { 0x0e5000f0, 0x004000d0, ARMV5TE_ABOVE, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRDImmediate, "ldrd<c> <Rt>, <Rt2>, [<Rn>,#+/-<imm8>]!"}, 12248 { 0x0e500ff0, 0x000000d0, ARMV5TE_ABOVE, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRDRegister, "ldrd<c> <Rt>, <Rt2>, [<Rn>, +/-<Rm>]{!}"}, 12249 { 0x0e100f00, 0x0c100b00, ARMvAll, eEncodingA1, VFPv2_ABOVE, eSize32, &EmulateInstructionARM::EmulateVLDM, "vldm{mode}<c> <Rn>{!}, <list>"}, 12250 { 0x0e100f00, 0x0c100a00, ARMvAll, eEncodingA2, VFPv2v3, eSize32, &EmulateInstructionARM::EmulateVLDM, "vldm{mode}<c> <Rn>{!}, <list>"}, 12251 { 0x0f300f00, 0x0d100b00, ARMvAll, eEncodingA1, VFPv2_ABOVE, eSize32, &EmulateInstructionARM::EmulateVLDR, "vldr<c> <Dd>, [<Rn>{,#+/-<imm>}]"}, 12252 { 0x0f300f00, 0x0d100a00, ARMvAll, eEncodingA2, VFPv2v3, eSize32, &EmulateInstructionARM::EmulateVLDR, "vldr<c> <Sd>, [<Rn>{,#+/-<imm>}]"}, 12253 { 0xffb00000, 0xf4200000, ARMvAll, eEncodingA1, AdvancedSIMD, eSize32, &EmulateInstructionARM::EmulateVLD1Multiple, "vld1<c>.<size> <list>, [<Rn>{@<align>}], <Rm>"}, 12254 { 0xffb00300, 0xf4a00000, ARMvAll, eEncodingA1, AdvancedSIMD, eSize32, &EmulateInstructionARM::EmulateVLD1Single, "vld1<c>.<size> <list>, [<Rn>{@<align>}], <Rm>"}, 12255 { 0xffb00f00, 0xf4a00c00, ARMvAll, eEncodingA1, AdvancedSIMD, eSize32, &EmulateInstructionARM::EmulateVLD1SingleAll, "vld1<c>.<size> <list>, [<Rn>{@<align>}], <Rm>"}, 12256 12257 //---------------------------------------------------------------------- 12258 // Store instructions 12259 //---------------------------------------------------------------------- 12260 { 0x0fd00000, 0x08800000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTM, "stm<c> <Rn>{!} <registers>" }, 12261 { 0x0fd00000, 0x08000000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTMDA, "stmda<c> <Rn>{!} <registers>" }, 12262 { 0x0fd00000, 0x09000000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTMDB, "stmdb<c> <Rn>{!} <registers>" }, 12263 { 0x0fd00000, 0x09800000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTMIB, "stmib<c> <Rn>{!} <registers>" }, 12264 { 0x0e500010, 0x06000000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTRRegister, "str<c> <Rt> [<Rn> +/-<Rm> {<shift>}]{!}" }, 12265 { 0x0e5000f0, 0x000000b0, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTRHRegister, "strh<c> <Rt>,[<Rn>,+/-<Rm>[{!}" }, 12266 { 0x0ff00ff0, 0x01800f90, ARMV6_ABOVE, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTREX, "strex<c> <Rd>, <Rt>, [<Rn>]"}, 12267 { 0x0e500000, 0x04400000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTRBImmARM, "strb<c> <Rt>,[<Rn>,#+/-<imm12>]!"}, 12268 { 0x0e500000, 0x04000000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTRImmARM, "str<c> <Rt>,[<Rn>,#+/-<imm12>]!"}, 12269 { 0x0e5000f0, 0x004000f0, ARMV5TE_ABOVE, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTRDImm, "strd<c> <Rt>, <Rt2>, [<Rn> #+/-<imm8>]!"}, 12270 { 0x0e500ff0, 0x000000f0, ARMV5TE_ABOVE, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTRDReg, "strd<c> <Rt>, <Rt2>, [<Rn>, +/-<Rm>]{!}"}, 12271 { 0x0e100f00, 0x0c000b00, ARMvAll, eEncodingA1, VFPv2_ABOVE, eSize32, &EmulateInstructionARM::EmulateVSTM, "vstm{mode}<c> <Rn>{!} <list>"}, 12272 { 0x0e100f00, 0x0c000a00, ARMvAll, eEncodingA2, VFPv2v3, eSize32, &EmulateInstructionARM::EmulateVSTM, "vstm{mode}<c> <Rn>{!} <list>"}, 12273 { 0x0f300f00, 0x0d000b00, ARMvAll, eEncodingA1, VFPv2_ABOVE, eSize32, &EmulateInstructionARM::EmulateVSTR, "vstr<c> <Dd> [<Rn>{,#+/-<imm>}]"}, 12274 { 0x0f300f00, 0x0d000a00, ARMvAll, eEncodingA2, VFPv2v3, eSize32, &EmulateInstructionARM::EmulateVSTR, "vstr<c> <Sd> [<Rn>{,#+/-<imm>}]"}, 12275 { 0xffb00000, 0xf4000000, ARMvAll, eEncodingA1, AdvancedSIMD, eSize32, &EmulateInstructionARM::EmulateVST1Multiple, "vst1<c>.<size> <list>, [<Rn>{@<align>}], <Rm>"}, 12276 { 0xffb00300, 0xf4800000, ARMvAll, eEncodingA1, AdvancedSIMD, eSize32, &EmulateInstructionARM::EmulateVST1Single, "vst1<c>.<size> <list>, [<Rn>{@<align>}], <Rm>"}, 12277 12278 //---------------------------------------------------------------------- 12279 // Other instructions 12280 //---------------------------------------------------------------------- 12281 { 0x0fff00f0, 0x06af00f0, ARMV6_ABOVE, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSXTB, "sxtb<c> <Rd>,<Rm>{,<rotation>}" }, 12282 { 0x0fff00f0, 0x06bf0070, ARMV6_ABOVE, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSXTH, "sxth<c> <Rd>,<Rm>{,<rotation>}" }, 12283 { 0x0fff00f0, 0x06ef0070, ARMV6_ABOVE, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateUXTB, "uxtb<c> <Rd>,<Rm>{,<rotation>}" }, 12284 { 0x0fff00f0, 0x06ff0070, ARMV6_ABOVE, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateUXTH, "uxth<c> <Rd>,<Rm>{,<rotation>}" }, 12285 { 0xfe500000, 0xf8100000, ARMV6_ABOVE, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateRFE, "rfe{<amode>} <Rn>{!}" } 12286 12287 }; 12288 static const size_t k_num_arm_opcodes = sizeof(g_arm_opcodes)/sizeof(ARMOpcode); 12289 12290 for (size_t i=0; i<k_num_arm_opcodes; ++i) 12291 { 12292 if ((g_arm_opcodes[i].mask & opcode) == g_arm_opcodes[i].value) 12293 return &g_arm_opcodes[i]; 12294 } 12295 return NULL; 12296} 12297 12298 12299EmulateInstructionARM::ARMOpcode* 12300EmulateInstructionARM::GetThumbOpcodeForInstruction (const uint32_t opcode) 12301{ 12302 12303 static ARMOpcode 12304 g_thumb_opcodes[] = 12305 { 12306 //---------------------------------------------------------------------- 12307 // Prologue instructions 12308 //---------------------------------------------------------------------- 12309 12310 // push register(s) 12311 { 0xfffffe00, 0x0000b400, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulatePUSH, "push <registers>" }, 12312 { 0xffff0000, 0xe92d0000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulatePUSH, "push.w <registers>" }, 12313 { 0xffff0fff, 0xf84d0d04, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, &EmulateInstructionARM::EmulatePUSH, "push.w <register>" }, 12314 12315 // set r7 to point to a stack offset 12316 { 0xffffff00, 0x0000af00, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateADDRdSPImm, "add r7, sp, #imm" }, 12317 // copy the stack pointer to r7 12318 { 0xffffffff, 0x0000466f, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateMOVRdSP, "mov r7, sp" }, 12319 // move from high register to low register (comes after "mov r7, sp" to resolve ambiguity) 12320 { 0xffffffc0, 0x00004640, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateMOVLowHigh, "mov r0-r7, r8-r15" }, 12321 12322 // PC-relative load into register (see also EmulateADDSPRm) 12323 { 0xfffff800, 0x00004800, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateLDRRtPCRelative, "ldr <Rt>, [PC, #imm]"}, 12324 12325 // adjust the stack pointer 12326 { 0xffffff87, 0x00004485, ARMvAll, eEncodingT2, No_VFP, eSize16, &EmulateInstructionARM::EmulateADDSPRm, "add sp, <Rm>"}, 12327 { 0xffffff80, 0x0000b080, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateSUBSPImm, "sub sp, sp, #imm"}, 12328 { 0xfbef8f00, 0xf1ad0d00, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBSPImm, "sub.w sp, sp, #<const>"}, 12329 { 0xfbff8f00, 0xf2ad0d00, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBSPImm, "subw sp, sp, #imm12"}, 12330 { 0xffef8000, 0xebad0000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBSPReg, "sub{s}<c> <Rd>, sp, <Rm>{,<shift>}" }, 12331 12332 // vector push consecutive extension register(s) 12333 { 0xffbf0f00, 0xed2d0b00, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateVPUSH, "vpush.64 <list>"}, 12334 { 0xffbf0f00, 0xed2d0a00, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateVPUSH, "vpush.32 <list>"}, 12335 12336 //---------------------------------------------------------------------- 12337 // Epilogue instructions 12338 //---------------------------------------------------------------------- 12339 12340 { 0xfffff800, 0x0000a800, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateADDSPImm, "add<c> <Rd>, sp, #imm"}, 12341 { 0xffffff80, 0x0000b000, ARMvAll, eEncodingT2, No_VFP, eSize16, &EmulateInstructionARM::EmulateADDSPImm, "add sp, #imm"}, 12342 { 0xfffffe00, 0x0000bc00, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulatePOP, "pop <registers>"}, 12343 { 0xffff0000, 0xe8bd0000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulatePOP, "pop.w <registers>" }, 12344 { 0xffff0fff, 0xf85d0d04, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, &EmulateInstructionARM::EmulatePOP, "pop.w <register>" }, 12345 { 0xffbf0f00, 0xecbd0b00, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateVPOP, "vpop.64 <list>"}, 12346 { 0xffbf0f00, 0xecbd0a00, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateVPOP, "vpop.32 <list>"}, 12347 12348 //---------------------------------------------------------------------- 12349 // Supervisor Call (previously Software Interrupt) 12350 //---------------------------------------------------------------------- 12351 { 0xffffff00, 0x0000df00, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateSVC, "svc #imm8"}, 12352 12353 //---------------------------------------------------------------------- 12354 // If Then makes up to four following instructions conditional. 12355 //---------------------------------------------------------------------- 12356 { 0xffffff00, 0x0000bf00, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateIT, "it{<x>{<y>{<z>}}} <firstcond>"}, 12357 12358 //---------------------------------------------------------------------- 12359 // Branch instructions 12360 //---------------------------------------------------------------------- 12361 // To resolve ambiguity, "b<c> #imm8" should come after "svc #imm8". 12362 { 0xfffff000, 0x0000d000, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateB, "b<c> #imm8 (outside IT)"}, 12363 { 0xfffff800, 0x0000e000, ARMvAll, eEncodingT2, No_VFP, eSize16, &EmulateInstructionARM::EmulateB, "b<c> #imm11 (outside or last in IT)"}, 12364 { 0xf800d000, 0xf0008000, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, &EmulateInstructionARM::EmulateB, "b<c>.w #imm8 (outside IT)"}, 12365 { 0xf800d000, 0xf0009000, ARMV6T2_ABOVE, eEncodingT4, No_VFP, eSize32, &EmulateInstructionARM::EmulateB, "b<c>.w #imm8 (outside or last in IT)"}, 12366 // J1 == J2 == 1 12367 { 0xf800d000, 0xf000d000, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateBLXImmediate, "bl <label>"}, 12368 // J1 == J2 == 1 12369 { 0xf800d001, 0xf000c000, ARMV5_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateBLXImmediate, "blx <label>"}, 12370 { 0xffffff87, 0x00004780, ARMV5_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateBLXRm, "blx <Rm>"}, 12371 // for example, "bx lr" 12372 { 0xffffff87, 0x00004700, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateBXRm, "bx <Rm>"}, 12373 // bxj 12374 { 0xfff0ffff, 0xf3c08f00, ARMV5J_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateBXJRm, "bxj <Rm>"}, 12375 // compare and branch 12376 { 0xfffff500, 0x0000b100, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateCB, "cb{n}z <Rn>, <label>"}, 12377 // table branch byte 12378 { 0xfff0fff0, 0xe8d0f000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateTB, "tbb<c> <Rn>, <Rm>"}, 12379 // table branch halfword 12380 { 0xfff0fff0, 0xe8d0f010, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateTB, "tbh<c> <Rn>, <Rm>, lsl #1"}, 12381 12382 //---------------------------------------------------------------------- 12383 // Data-processing instructions 12384 //---------------------------------------------------------------------- 12385 // adc (immediate) 12386 { 0xfbe08000, 0xf1400000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateADCImm, "adc{s}<c> <Rd>, <Rn>, #<const>"}, 12387 // adc (register) 12388 { 0xffffffc0, 0x00004140, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateADCReg, "adcs|adc<c> <Rdn>, <Rm>"}, 12389 { 0xffe08000, 0xeb400000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateADCReg, "adc{s}<c>.w <Rd>, <Rn>, <Rm> {,<shift>}"}, 12390 // add (register) 12391 { 0xfffffe00, 0x00001800, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateADDReg, "adds|add<c> <Rd>, <Rn>, <Rm>"}, 12392 // Make sure "add sp, <Rm>" comes before this instruction, so there's no ambiguity decoding the two. 12393 { 0xffffff00, 0x00004400, ARMvAll, eEncodingT2, No_VFP, eSize16, &EmulateInstructionARM::EmulateADDReg, "add<c> <Rdn>, <Rm>"}, 12394 // adr 12395 { 0xfffff800, 0x0000a000, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateADR, "add<c> <Rd>, PC, #<const>"}, 12396 { 0xfbff8000, 0xf2af0000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateADR, "sub<c> <Rd>, PC, #<const>"}, 12397 { 0xfbff8000, 0xf20f0000, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, &EmulateInstructionARM::EmulateADR, "add<c> <Rd>, PC, #<const>"}, 12398 // and (immediate) 12399 { 0xfbe08000, 0xf0000000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateANDImm, "and{s}<c> <Rd>, <Rn>, #<const>"}, 12400 // and (register) 12401 { 0xffffffc0, 0x00004000, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateANDReg, "ands|and<c> <Rdn>, <Rm>"}, 12402 { 0xffe08000, 0xea000000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateANDReg, "and{s}<c>.w <Rd>, <Rn>, <Rm> {,<shift>}"}, 12403 // bic (immediate) 12404 { 0xfbe08000, 0xf0200000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateBICImm, "bic{s}<c> <Rd>, <Rn>, #<const>"}, 12405 // bic (register) 12406 { 0xffffffc0, 0x00004380, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateBICReg, "bics|bic<c> <Rdn>, <Rm>"}, 12407 { 0xffe08000, 0xea200000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateBICReg, "bic{s}<c>.w <Rd>, <Rn>, <Rm> {,<shift>}"}, 12408 // eor (immediate) 12409 { 0xfbe08000, 0xf0800000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateEORImm, "eor{s}<c> <Rd>, <Rn>, #<const>"}, 12410 // eor (register) 12411 { 0xffffffc0, 0x00004040, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateEORReg, "eors|eor<c> <Rdn>, <Rm>"}, 12412 { 0xffe08000, 0xea800000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateEORReg, "eor{s}<c>.w <Rd>, <Rn>, <Rm> {,<shift>}"}, 12413 // orr (immediate) 12414 { 0xfbe08000, 0xf0400000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateORRImm, "orr{s}<c> <Rd>, <Rn>, #<const>"}, 12415 // orr (register) 12416 { 0xffffffc0, 0x00004300, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateORRReg, "orrs|orr<c> <Rdn>, <Rm>"}, 12417 { 0xffe08000, 0xea400000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateORRReg, "orr{s}<c>.w <Rd>, <Rn>, <Rm> {,<shift>}"}, 12418 // rsb (immediate) 12419 { 0xffffffc0, 0x00004240, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateRSBImm, "rsbs|rsb<c> <Rd>, <Rn>, #0"}, 12420 { 0xfbe08000, 0xf1c00000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateRSBImm, "rsb{s}<c>.w <Rd>, <Rn>, #<const>"}, 12421 // rsb (register) 12422 { 0xffe08000, 0xea400000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateRSBReg, "rsb{s}<c>.w <Rd>, <Rn>, <Rm> {,<shift>}"}, 12423 // sbc (immediate) 12424 { 0xfbe08000, 0xf1600000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSBCImm, "sbc{s}<c> <Rd>, <Rn>, #<const>"}, 12425 // sbc (register) 12426 { 0xffffffc0, 0x00004180, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateSBCReg, "sbcs|sbc<c> <Rdn>, <Rm>"}, 12427 { 0xffe08000, 0xeb600000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateSBCReg, "sbc{s}<c>.w <Rd>, <Rn>, <Rm> {,<shift>}"}, 12428 // add (immediate, Thumb) 12429 { 0xfffffe00, 0x00001c00, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateADDImmThumb, "adds|add<c> <Rd>,<Rn>,#<imm3>" }, 12430 { 0xfffff800, 0x00003000, ARMV4T_ABOVE, eEncodingT2, No_VFP, eSize16, &EmulateInstructionARM::EmulateADDImmThumb, "adds|add<c> <Rdn>,#<imm8>" }, 12431 { 0xfbe08000, 0xf1000000, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, &EmulateInstructionARM::EmulateADDImmThumb, "add{s}<c>.w <Rd>,<Rn>,#<const>" }, 12432 { 0xfbf08000, 0xf2000000, ARMV6T2_ABOVE, eEncodingT4, No_VFP, eSize32, &EmulateInstructionARM::EmulateADDImmThumb, "addw<c> <Rd>,<Rn>,#<imm12>" }, 12433 // sub (immediate, Thumb) 12434 { 0xfffffe00, 0x00001e00, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateSUBImmThumb, "subs|sub<c> <Rd>, <Rn> #imm3"}, 12435 { 0xfffff800, 0x00003800, ARMvAll, eEncodingT2, No_VFP, eSize16, &EmulateInstructionARM::EmulateSUBImmThumb, "subs|sub<c> <Rdn>, #imm8"}, 12436 { 0xfbe08000, 0xf1a00000, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBImmThumb, "sub{s}<c>.w <Rd>, <Rn>, #<const>"}, 12437 { 0xfbf08000, 0xf2a00000, ARMV6T2_ABOVE, eEncodingT4, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBImmThumb, "subw<c> <Rd>, <Rn>, #imm12"}, 12438 // sub (sp minus immediate) 12439 { 0xfbef8000, 0xf1ad0000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBSPImm, "sub{s}.w <Rd>, sp, #<const>"}, 12440 { 0xfbff8000, 0xf2ad0000, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBSPImm, "subw<c> <Rd>, sp, #imm12"}, 12441 // sub (register) 12442 { 0xfffffe00, 0x00001a00, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateSUBReg, "subs|sub<c> <Rd>, <Rn>, <Rm>"}, 12443 { 0xffe08000, 0xeba00000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBReg, "sub{s}<c>.w <Rd>, <Rn>, <Rm>{,<shift>}"}, 12444 // teq (immediate) 12445 { 0xfbf08f00, 0xf0900f00, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateTEQImm, "teq<c> <Rn>, #<const>"}, 12446 // teq (register) 12447 { 0xfff08f00, 0xea900f00, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateTEQReg, "teq<c> <Rn>, <Rm> {,<shift>}"}, 12448 // tst (immediate) 12449 { 0xfbf08f00, 0xf0100f00, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateTSTImm, "tst<c> <Rn>, #<const>"}, 12450 // tst (register) 12451 { 0xffffffc0, 0x00004200, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateTSTReg, "tst<c> <Rdn>, <Rm>"}, 12452 { 0xfff08f00, 0xea100f00, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateTSTReg, "tst<c>.w <Rn>, <Rm> {,<shift>}"}, 12453 12454 12455 // move from high register to high register 12456 { 0xffffff00, 0x00004600, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateMOVRdRm, "mov<c> <Rd>, <Rm>"}, 12457 // move from low register to low register 12458 { 0xffffffc0, 0x00000000, ARMvAll, eEncodingT2, No_VFP, eSize16, &EmulateInstructionARM::EmulateMOVRdRm, "movs <Rd>, <Rm>"}, 12459 // mov{s}<c>.w <Rd>, <Rm> 12460 { 0xffeff0f0, 0xea4f0000, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, &EmulateInstructionARM::EmulateMOVRdRm, "mov{s}<c>.w <Rd>, <Rm>"}, 12461 // move immediate 12462 { 0xfffff800, 0x00002000, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateMOVRdImm, "movs|mov<c> <Rd>, #imm8"}, 12463 { 0xfbef8000, 0xf04f0000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateMOVRdImm, "mov{s}<c>.w <Rd>, #<const>"}, 12464 { 0xfbf08000, 0xf2400000, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, &EmulateInstructionARM::EmulateMOVRdImm, "movw<c> <Rd>,#<imm16>"}, 12465 // mvn (immediate) 12466 { 0xfbef8000, 0xf06f0000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateMVNImm, "mvn{s} <Rd>, #<const>"}, 12467 // mvn (register) 12468 { 0xffffffc0, 0x000043c0, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateMVNReg, "mvns|mvn<c> <Rd>, <Rm>"}, 12469 { 0xffef8000, 0xea6f0000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateMVNReg, "mvn{s}<c>.w <Rd>, <Rm> {,<shift>}"}, 12470 // cmn (immediate) 12471 { 0xfbf08f00, 0xf1100f00, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateCMNImm, "cmn<c> <Rn>, #<const>"}, 12472 // cmn (register) 12473 { 0xffffffc0, 0x000042c0, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateCMNReg, "cmn<c> <Rn>, <Rm>"}, 12474 { 0xfff08f00, 0xeb100f00, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateCMNReg, "cmn<c> <Rn>, <Rm> {,<shift>}"}, 12475 // cmp (immediate) 12476 { 0xfffff800, 0x00002800, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateCMPImm, "cmp<c> <Rn>, #imm8"}, 12477 { 0xfbf08f00, 0xf1b00f00, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateCMPImm, "cmp<c>.w <Rn>, #<const>"}, 12478 // cmp (register) (Rn and Rm both from r0-r7) 12479 { 0xffffffc0, 0x00004280, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateCMPReg, "cmp<c> <Rn>, <Rm>"}, 12480 // cmp (register) (Rn and Rm not both from r0-r7) 12481 { 0xffffff00, 0x00004500, ARMvAll, eEncodingT2, No_VFP, eSize16, &EmulateInstructionARM::EmulateCMPReg, "cmp<c> <Rn>, <Rm>"}, 12482 // asr (immediate) 12483 { 0xfffff800, 0x00001000, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateASRImm, "asrs|asr<c> <Rd>, <Rm>, #imm"}, 12484 { 0xffef8030, 0xea4f0020, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateASRImm, "asr{s}<c>.w <Rd>, <Rm>, #imm"}, 12485 // asr (register) 12486 { 0xffffffc0, 0x00004100, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateASRReg, "asrs|asr<c> <Rdn>, <Rm>"}, 12487 { 0xffe0f0f0, 0xfa40f000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateASRReg, "asr{s}<c>.w <Rd>, <Rn>, <Rm>"}, 12488 // lsl (immediate) 12489 { 0xfffff800, 0x00000000, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateLSLImm, "lsls|lsl<c> <Rd>, <Rm>, #imm"}, 12490 { 0xffef8030, 0xea4f0000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateLSLImm, "lsl{s}<c>.w <Rd>, <Rm>, #imm"}, 12491 // lsl (register) 12492 { 0xffffffc0, 0x00004080, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateLSLReg, "lsls|lsl<c> <Rdn>, <Rm>"}, 12493 { 0xffe0f0f0, 0xfa00f000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateLSLReg, "lsl{s}<c>.w <Rd>, <Rn>, <Rm>"}, 12494 // lsr (immediate) 12495 { 0xfffff800, 0x00000800, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateLSRImm, "lsrs|lsr<c> <Rd>, <Rm>, #imm"}, 12496 { 0xffef8030, 0xea4f0010, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateLSRImm, "lsr{s}<c>.w <Rd>, <Rm>, #imm"}, 12497 // lsr (register) 12498 { 0xffffffc0, 0x000040c0, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateLSRReg, "lsrs|lsr<c> <Rdn>, <Rm>"}, 12499 { 0xffe0f0f0, 0xfa20f000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateLSRReg, "lsr{s}<c>.w <Rd>, <Rn>, <Rm>"}, 12500 // rrx is a special case encoding of ror (immediate) 12501 { 0xffeff0f0, 0xea4f0030, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateRRX, "rrx{s}<c>.w <Rd>, <Rm>"}, 12502 // ror (immediate) 12503 { 0xffef8030, 0xea4f0030, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateRORImm, "ror{s}<c>.w <Rd>, <Rm>, #imm"}, 12504 // ror (register) 12505 { 0xffffffc0, 0x000041c0, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateRORReg, "rors|ror<c> <Rdn>, <Rm>"}, 12506 { 0xffe0f0f0, 0xfa60f000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateRORReg, "ror{s}<c>.w <Rd>, <Rn>, <Rm>"}, 12507 // mul 12508 { 0xffffffc0, 0x00004340, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateMUL, "muls <Rdm>,<Rn>,<Rdm>" }, 12509 // mul 12510 { 0xfff0f0f0, 0xfb00f000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateMUL, "mul<c> <Rd>,<Rn>,<Rm>" }, 12511 12512 // subs pc, lr and related instructions 12513 { 0xffffff00, 0xf3de8f00, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBSPcLrEtc, "SUBS<c> PC, LR, #<imm8>" }, 12514 12515 //---------------------------------------------------------------------- 12516 // RFE instructions *** IMPORTANT *** THESE MUST BE LISTED **BEFORE** THE LDM.. Instructions in this table; 12517 // otherwise the wrong instructions will be selected. 12518 //---------------------------------------------------------------------- 12519 12520 { 0xffd0ffff, 0xe810c000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateRFE, "rfedb<c> <Rn>{!}" }, 12521 { 0xffd0ffff, 0xe990c000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateRFE, "rfe{ia}<c> <Rn>{!}" }, 12522 12523 //---------------------------------------------------------------------- 12524 // Load instructions 12525 //---------------------------------------------------------------------- 12526 { 0xfffff800, 0x0000c800, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateLDM, "ldm<c> <Rn>{!} <registers>" }, 12527 { 0xffd02000, 0xe8900000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDM, "ldm<c>.w <Rn>{!} <registers>" }, 12528 { 0xffd00000, 0xe9100000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDMDB, "ldmdb<c> <Rn>{!} <registers>" }, 12529 { 0xfffff800, 0x00006800, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateLDRRtRnImm, "ldr<c> <Rt>, [<Rn>{,#imm}]"}, 12530 { 0xfffff800, 0x00009800, ARMV4T_ABOVE, eEncodingT2, No_VFP, eSize16, &EmulateInstructionARM::EmulateLDRRtRnImm, "ldr<c> <Rt>, [SP{,#imm}]"}, 12531 { 0xfff00000, 0xf8d00000, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRRtRnImm, "ldr<c>.w <Rt>, [<Rn>{,#imm12}]"}, 12532 { 0xfff00800, 0xf8500800, ARMV6T2_ABOVE, eEncodingT4, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRRtRnImm, "ldr<c> <Rt>, [<Rn>{,#+/-<imm8>}]{!}"}, 12533 // Thumb2 PC-relative load into register 12534 { 0xff7f0000, 0xf85f0000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRRtPCRelative, "ldr<c>.w <Rt>, [PC, +/-#imm}]"}, 12535 { 0xfffffe00, 0x00005800, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateLDRRegister, "ldr<c> <Rt>, [<Rn>, <Rm>]" }, 12536 { 0xfff00fc0, 0xf8500000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRRegister, "ldr<c>.w <Rt>, [<Rn>,<Rm>{,LSL #<imm2>}]" }, 12537 { 0xfffff800, 0x00007800, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateLDRBImmediate, "ldrb<c> <Rt>,[<Rn>{,#<imm5>}]" }, 12538 { 0xfff00000, 0xf8900000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRBImmediate, "ldrb<c>.w <Rt>,[<Rn>{,#<imm12>}]" }, 12539 { 0xfff00800, 0xf8100800, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRBImmediate, "ldrb<c> <Rt>,[<Rn>, #+/-<imm8>]{!}" }, 12540 { 0xff7f0000, 0xf81f0000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRBLiteral, "ldrb<c> <Rt>,[...]" }, 12541 { 0xfffffe00, 0x00005c00, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateLDRBRegister, "ldrb<c> <Rt>,[<Rn>,<Rm>]" }, 12542 { 0xfff00fc0, 0xf8100000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRBRegister, "ldrb<c>.w <Rt>,[<Rn>,<Rm>{,LSL #imm2>}]" }, 12543 { 0xfffff800, 0x00008800, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateLDRHImmediate, "ldrh<c> <Rt>, [<Rn>{,#<imm>}]" }, 12544 { 0xfff00000, 0xf8b00000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRHImmediate, "ldrh<c>.w <Rt>,[<Rn>{,#<imm12>}]" }, 12545 { 0xfff00800, 0xf8300800, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRHImmediate, "ldrh<c> <Rt>,[<Rn>,#+/-<imm8>]{!}" }, 12546 { 0xff7f0000, 0xf83f0000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRHLiteral, "ldrh<c> <Rt>, <label>" }, 12547 { 0xfffffe00, 0x00005a00, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateLDRHRegister, "ldrh<c> <Rt>, [<Rn>,<Rm>]" }, 12548 { 0xfff00fc0, 0xf8300000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRHRegister, "ldrh<c>.w <Rt>,[<Rn>,<Rm>{,LSL #<imm2>}]" }, 12549 { 0xfff00000, 0xf9900000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRSBImmediate, "ldrsb<c> <Rt>,[<Rn>,#<imm12>]" }, 12550 { 0xfff00800, 0xf9100800, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRSBImmediate, "ldrsb<c> <Rt>,[<Rn>,#+/-<imm8>]" }, 12551 { 0xff7f0000, 0xf91f0000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRSBLiteral, "ldrsb<c> <Rt>, <label>" }, 12552 { 0xfffffe00, 0x00005600, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateLDRSBRegister, "ldrsb<c> <Rt>,[<Rn>,<Rm>]" }, 12553 { 0xfff00fc0, 0xf9100000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRSBRegister, "ldrsb<c>.w <Rt>,[<Rn>,<Rm>{,LSL #imm2>}]" }, 12554 { 0xfff00000, 0xf9b00000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRSHImmediate, "ldrsh<c> <Rt>,[<Rn>,#<imm12>]" }, 12555 { 0xfff00800, 0xf9300800, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRSHImmediate, "ldrsh<c> <Rt>,[<Rn>,#+/-<imm8>]" }, 12556 { 0xff7f0000, 0xf93f0000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRSHLiteral, "ldrsh<c> <Rt>,<label>" }, 12557 { 0xfffffe00, 0x00005e00, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateLDRSHRegister, "ldrsh<c> <Rt>,[<Rn>,<Rm>]" }, 12558 { 0xfff00fc0, 0xf9300000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRSHRegister, "ldrsh<c>.w <Rt>,[<Rn>,<Rm>{,LSL #<imm2>}]" }, 12559 { 0xfe500000, 0xe8500000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRDImmediate, "ldrd<c> <Rt>, <Rt2>, [<Rn>,#+/-<imm>]!"}, 12560 { 0xfe100f00, 0xec100b00, ARMvAll, eEncodingT1, VFPv2_ABOVE, eSize32, &EmulateInstructionARM::EmulateVLDM, "vldm{mode}<c> <Rn>{!}, <list>"}, 12561 { 0xfe100f00, 0xec100a00, ARMvAll, eEncodingT2, VFPv2v3, eSize32, &EmulateInstructionARM::EmulateVLDM, "vldm{mode}<c> <Rn>{!}, <list>" }, 12562 { 0xffe00f00, 0xed100b00, ARMvAll, eEncodingT1, VFPv2_ABOVE, eSize32, &EmulateInstructionARM::EmulateVLDR, "vldr<c> <Dd>, [<Rn>{,#+/-<imm>}]"}, 12563 { 0xff300f00, 0xed100a00, ARMvAll, eEncodingT2, VFPv2v3, eSize32, &EmulateInstructionARM::EmulateVLDR, "vldr<c> <Sd>, {<Rn>{,#+/-<imm>}]"}, 12564 { 0xffb00000, 0xf9200000, ARMvAll, eEncodingT1, AdvancedSIMD, eSize32, &EmulateInstructionARM::EmulateVLD1Multiple, "vld1<c>.<size> <list>, [<Rn>{@<align>}],<Rm>"}, 12565 { 0xffb00300, 0xf9a00000, ARMvAll, eEncodingT1, AdvancedSIMD, eSize32, &EmulateInstructionARM::EmulateVLD1Single, "vld1<c>.<size> <list>, [<Rn>{@<align>}],<Rm>"}, 12566 { 0xffb00f00, 0xf9a00c00, ARMvAll, eEncodingT1, AdvancedSIMD, eSize32, &EmulateInstructionARM::EmulateVLD1SingleAll, "vld1<c>.<size> <list>, [<Rn>{@<align>}], <Rm>"}, 12567 12568 //---------------------------------------------------------------------- 12569 // Store instructions 12570 //---------------------------------------------------------------------- 12571 { 0xfffff800, 0x0000c000, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateSTM, "stm<c> <Rn>{!} <registers>" }, 12572 { 0xffd00000, 0xe8800000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTM, "stm<c>.w <Rn>{!} <registers>" }, 12573 { 0xffd00000, 0xe9000000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTMDB, "stmdb<c> <Rn>{!} <registers>" }, 12574 { 0xfffff800, 0x00006000, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateSTRThumb, "str<c> <Rt>, [<Rn>{,#<imm>}]" }, 12575 { 0xfffff800, 0x00009000, ARMV4T_ABOVE, eEncodingT2, No_VFP, eSize16, &EmulateInstructionARM::EmulateSTRThumb, "str<c> <Rt>, [SP,#<imm>]" }, 12576 { 0xfff00000, 0xf8c00000, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTRThumb, "str<c>.w <Rt>, [<Rn>,#<imm12>]" }, 12577 { 0xfff00800, 0xf8400800, ARMV6T2_ABOVE, eEncodingT4, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTRThumb, "str<c> <Rt>, [<Rn>,#+/-<imm8>]" }, 12578 { 0xfffffe00, 0x00005000, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateSTRRegister, "str<c> <Rt> ,{<Rn>, <Rm>]" }, 12579 { 0xfff00fc0, 0xf8400000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTRRegister, "str<c>.w <Rt>, [<Rn>, <Rm> {lsl #imm2>}]" }, 12580 { 0xfffff800, 0x00007000, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateSTRBThumb, "strb<c> <Rt>, [<Rn>, #<imm5>]" }, 12581 { 0xfff00000, 0xf8800000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTRBThumb, "strb<c>.w <Rt>, [<Rn>, #<imm12>]" }, 12582 { 0xfff00800, 0xf8000800, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTRBThumb, "strb<c> <Rt> ,[<Rn>, #+/-<imm8>]{!}" }, 12583 { 0xfffffe00, 0x00005200, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateSTRHRegister, "strh<c> <Rt>,[<Rn>,<Rm>]" }, 12584 { 0xfff00fc0, 0xf8200000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTRHRegister, "strh<c>.w <Rt>,[<Rn>,<Rm>{,LSL #<imm2>}]" }, 12585 { 0xfff00000, 0xe8400000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTREX, "strex<c> <Rd>, <Rt>, [<Rn{,#<imm>}]" }, 12586 { 0xfe500000, 0xe8400000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTRDImm, "strd<c> <Rt>, <Rt2>, [<Rn>, #+/-<imm>]!"}, 12587 { 0xfe100f00, 0xec000b00, ARMvAll, eEncodingT1, VFPv2_ABOVE, eSize32, &EmulateInstructionARM::EmulateVSTM, "vstm{mode}<c> <Rn>{!}, <list>"}, 12588 { 0xfea00f00, 0xec000a00, ARMvAll, eEncodingT2, VFPv2v3, eSize32, &EmulateInstructionARM::EmulateVSTM, "vstm{mode}<c> <Rn>{!}, <list>"}, 12589 { 0xff300f00, 0xed000b00, ARMvAll, eEncodingT1, VFPv2_ABOVE, eSize32, &EmulateInstructionARM::EmulateVSTR, "vstr<c> <Dd>, [<Rn>{,#+/-<imm>}]"}, 12590 { 0xff300f00, 0xed000a00, ARMvAll, eEncodingT2, VFPv2v3, eSize32, &EmulateInstructionARM::EmulateVSTR, "vstr<c> <Sd>, [<Rn>{,#+/-<imm>}]"}, 12591 { 0xffb00000, 0xfa000000, ARMvAll, eEncodingT1, AdvancedSIMD, eSize32, &EmulateInstructionARM::EmulateVST1Multiple, "vst1<c>.<size> <list>, [<Rn>{@<align>}], <Rm>"}, 12592 { 0xffb00300, 0xf9800000, ARMvAll, eEncodingT1, AdvancedSIMD, eSize32, &EmulateInstructionARM::EmulateVST1Single, "vst1<c>.<size> <list>, [<Rn>{@<align>}], <Rm>"}, 12593 12594 //---------------------------------------------------------------------- 12595 // Other instructions 12596 //---------------------------------------------------------------------- 12597 { 0xffffffc0, 0x0000b240, ARMV6_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateSXTB, "sxtb<c> <Rd>,<Rm>" }, 12598 { 0xfffff080, 0xfa4ff080, ARMV6_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateSXTB, "sxtb<c>.w <Rd>,<Rm>{,<rotation>}" }, 12599 { 0xffffffc0, 0x0000b200, ARMV6_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateSXTH, "sxth<c> <Rd>,<Rm>" }, 12600 { 0xfffff080, 0xfa0ff080, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateSXTH, "sxth<c>.w <Rd>,<Rm>{,<rotation>}" }, 12601 { 0xffffffc0, 0x0000b2c0, ARMV6_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateUXTB, "uxtb<c> <Rd>,<Rm>" }, 12602 { 0xfffff080, 0xfa5ff080, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateUXTB, "uxtb<c>.w <Rd>,<Rm>{,<rotation>}" }, 12603 { 0xffffffc0, 0x0000b280, ARMV6_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateUXTH, "uxth<c> <Rd>,<Rm>" }, 12604 { 0xfffff080, 0xfa1ff080, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateUXTH, "uxth<c>.w <Rd>,<Rm>{,<rotation>}" }, 12605 }; 12606 12607 const size_t k_num_thumb_opcodes = sizeof(g_thumb_opcodes)/sizeof(ARMOpcode); 12608 for (size_t i=0; i<k_num_thumb_opcodes; ++i) 12609 { 12610 if ((g_thumb_opcodes[i].mask & opcode) == g_thumb_opcodes[i].value) 12611 return &g_thumb_opcodes[i]; 12612 } 12613 return NULL; 12614} 12615 12616bool 12617EmulateInstructionARM::SetArchitecture (const ArchSpec &arch) 12618{ 12619 m_arch = arch; 12620 m_arm_isa = 0; 12621 const char *arch_cstr = arch.GetArchitectureName (); 12622 if (arch_cstr) 12623 { 12624 if (0 == ::strcasecmp(arch_cstr, "armv4t")) m_arm_isa = ARMv4T; 12625 else if (0 == ::strcasecmp(arch_cstr, "armv4")) m_arm_isa = ARMv4; 12626 else if (0 == ::strcasecmp(arch_cstr, "armv5tej")) m_arm_isa = ARMv5TEJ; 12627 else if (0 == ::strcasecmp(arch_cstr, "armv5te")) m_arm_isa = ARMv5TE; 12628 else if (0 == ::strcasecmp(arch_cstr, "armv5t")) m_arm_isa = ARMv5T; 12629 else if (0 == ::strcasecmp(arch_cstr, "armv6k")) m_arm_isa = ARMv6K; 12630 else if (0 == ::strcasecmp(arch_cstr, "armv6")) m_arm_isa = ARMv6; 12631 else if (0 == ::strcasecmp(arch_cstr, "armv6t2")) m_arm_isa = ARMv6T2; 12632 else if (0 == ::strcasecmp(arch_cstr, "armv7")) m_arm_isa = ARMv7; 12633 else if (0 == ::strcasecmp(arch_cstr, "armv8")) m_arm_isa = ARMv8; 12634 } 12635 return m_arm_isa != 0; 12636} 12637 12638bool 12639EmulateInstructionARM::SetInstruction (const Opcode &insn_opcode, const Address &inst_addr) 12640{ 12641 m_opcode = insn_opcode; 12642 12643 if (m_arch.GetTriple().getArch() == llvm::Triple::thumb) 12644 m_opcode_mode = eModeThumb; 12645 else 12646 { 12647 AddressClass addr_class = inst_addr.GetAddressClass(); 12648 12649 if ((addr_class == eAddressClassCode) || (addr_class == eAddressClassUnknown)) 12650 m_opcode_mode = eModeARM; 12651 else if (addr_class == eAddressClassCodeAlternateISA) 12652 m_opcode_mode = eModeThumb; 12653 else 12654 return false; 12655 } 12656 return true; 12657} 12658 12659bool 12660EmulateInstructionARM::ReadInstruction () 12661{ 12662 bool success = false; 12663 m_opcode_cpsr = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS, 0, &success); 12664 if (success) 12665 { 12666 addr_t pc = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, LLDB_INVALID_ADDRESS, &success); 12667 if (success) 12668 { 12669 Context read_inst_context; 12670 read_inst_context.type = eContextReadOpcode; 12671 read_inst_context.SetNoArgs (); 12672 12673 if (m_opcode_cpsr & MASK_CPSR_T) 12674 { 12675 m_opcode_mode = eModeThumb; 12676 uint32_t thumb_opcode = MemARead(read_inst_context, pc, 2, 0, &success); 12677 12678 if (success) 12679 { 12680 if ((thumb_opcode & 0xe000) != 0xe000 || ((thumb_opcode & 0x1800u) == 0)) 12681 { 12682 m_opcode.SetOpcode16 (thumb_opcode); 12683 } 12684 else 12685 { 12686 m_opcode.SetOpcode32 ((thumb_opcode << 16) | MemARead(read_inst_context, pc + 2, 2, 0, &success)); 12687 } 12688 } 12689 } 12690 else 12691 { 12692 m_opcode_mode = eModeARM; 12693 m_opcode.SetOpcode32 (MemARead(read_inst_context, pc, 4, 0, &success)); 12694 } 12695 } 12696 } 12697 if (!success) 12698 { 12699 m_opcode_mode = eModeInvalid; 12700 m_opcode_pc = LLDB_INVALID_ADDRESS; 12701 } 12702 return success; 12703} 12704 12705uint32_t 12706EmulateInstructionARM::ArchVersion () 12707{ 12708 return m_arm_isa; 12709} 12710 12711bool 12712EmulateInstructionARM::ConditionPassed (const uint32_t opcode) 12713{ 12714 12715 const uint32_t cond = CurrentCond (opcode); 12716 12717 if (cond == UINT32_MAX) 12718 return false; 12719 12720 bool result = false; 12721 switch (UnsignedBits(cond, 3, 1)) 12722 { 12723 case 0: 12724 if (m_opcode_cpsr == 0) 12725 return true; 12726 result = (m_opcode_cpsr & MASK_CPSR_Z) != 0; 12727 break; 12728 case 1: 12729 if (m_opcode_cpsr == 0) 12730 return true; 12731 result = (m_opcode_cpsr & MASK_CPSR_C) != 0; 12732 break; 12733 case 2: 12734 if (m_opcode_cpsr == 0) 12735 return true; 12736 result = (m_opcode_cpsr & MASK_CPSR_N) != 0; 12737 break; 12738 case 3: 12739 if (m_opcode_cpsr == 0) 12740 return true; 12741 result = (m_opcode_cpsr & MASK_CPSR_V) != 0; 12742 break; 12743 case 4: 12744 if (m_opcode_cpsr == 0) 12745 return true; 12746 result = ((m_opcode_cpsr & MASK_CPSR_C) != 0) && ((m_opcode_cpsr & MASK_CPSR_Z) == 0); 12747 break; 12748 case 5: 12749 if (m_opcode_cpsr == 0) 12750 return true; 12751 else 12752 { 12753 bool n = (m_opcode_cpsr & MASK_CPSR_N); 12754 bool v = (m_opcode_cpsr & MASK_CPSR_V); 12755 result = n == v; 12756 } 12757 break; 12758 case 6: 12759 if (m_opcode_cpsr == 0) 12760 return true; 12761 else 12762 { 12763 bool n = (m_opcode_cpsr & MASK_CPSR_N); 12764 bool v = (m_opcode_cpsr & MASK_CPSR_V); 12765 result = n == v && ((m_opcode_cpsr & MASK_CPSR_Z) == 0); 12766 } 12767 break; 12768 case 7: 12769 result = true; 12770 break; 12771 } 12772 12773 if (cond & 1) 12774 result = !result; 12775 return result; 12776} 12777 12778uint32_t 12779EmulateInstructionARM::CurrentCond (const uint32_t opcode) 12780{ 12781 switch (m_opcode_mode) 12782 { 12783 default: 12784 case eModeInvalid: 12785 break; 12786 12787 case eModeARM: 12788 return UnsignedBits(opcode, 31, 28); 12789 12790 case eModeThumb: 12791 // For T1 and T3 encodings of the Branch instruction, it returns the 4-bit 12792 // 'cond' field of the encoding. 12793 { 12794 const uint32_t byte_size = m_opcode.GetByteSize(); 12795 if (byte_size == 2) 12796 { 12797 if (Bits32(opcode, 15, 12) == 0x0d && Bits32(opcode, 11, 7) != 0x0f) 12798 return Bits32(opcode, 11, 7); 12799 } 12800 else 12801 { 12802 assert (byte_size == 4); 12803 if (Bits32(opcode, 31, 27) == 0x1e && 12804 Bits32(opcode, 15, 14) == 0x02 && 12805 Bits32(opcode, 12, 12) == 0x00 && 12806 Bits32(opcode, 25, 22) <= 0x0d) 12807 { 12808 return Bits32(opcode, 25, 22); 12809 } 12810 } 12811 12812 return m_it_session.GetCond(); 12813 } 12814 } 12815 return UINT32_MAX; // Return invalid value 12816} 12817 12818bool 12819EmulateInstructionARM::InITBlock() 12820{ 12821 return CurrentInstrSet() == eModeThumb && m_it_session.InITBlock(); 12822} 12823 12824bool 12825EmulateInstructionARM::LastInITBlock() 12826{ 12827 return CurrentInstrSet() == eModeThumb && m_it_session.LastInITBlock(); 12828} 12829 12830bool 12831EmulateInstructionARM::BadMode (uint32_t mode) 12832{ 12833 12834 switch (mode) 12835 { 12836 case 16: return false; // '10000' 12837 case 17: return false; // '10001' 12838 case 18: return false; // '10010' 12839 case 19: return false; // '10011' 12840 case 22: return false; // '10110' 12841 case 23: return false; // '10111' 12842 case 27: return false; // '11011' 12843 case 31: return false; // '11111' 12844 default: return true; 12845 } 12846 return true; 12847} 12848 12849bool 12850EmulateInstructionARM::CurrentModeIsPrivileged () 12851{ 12852 uint32_t mode = Bits32 (m_opcode_cpsr, 4, 0); 12853 12854 if (BadMode (mode)) 12855 return false; 12856 12857 if (mode == 16) 12858 return false; 12859 12860 return true; 12861} 12862 12863void 12864EmulateInstructionARM::CPSRWriteByInstr (uint32_t value, uint32_t bytemask, bool affect_execstate) 12865{ 12866 bool privileged = CurrentModeIsPrivileged(); 12867 12868 uint32_t tmp_cpsr = 0; 12869 12870 tmp_cpsr = tmp_cpsr | (Bits32 (m_opcode_cpsr, 23, 20) << 20); 12871 12872 if (BitIsSet (bytemask, 3)) 12873 { 12874 tmp_cpsr = tmp_cpsr | (Bits32 (value, 31, 27) << 27); 12875 if (affect_execstate) 12876 tmp_cpsr = tmp_cpsr | (Bits32 (value, 26, 24) << 24); 12877 } 12878 12879 if (BitIsSet (bytemask, 2)) 12880 { 12881 tmp_cpsr = tmp_cpsr | (Bits32 (value, 19, 16) << 16); 12882 } 12883 12884 if (BitIsSet (bytemask, 1)) 12885 { 12886 if (affect_execstate) 12887 tmp_cpsr = tmp_cpsr | (Bits32 (value, 15, 10) << 10); 12888 tmp_cpsr = tmp_cpsr | (Bit32 (value, 9) << 9); 12889 if (privileged) 12890 tmp_cpsr = tmp_cpsr | (Bit32 (value, 8) << 8); 12891 } 12892 12893 if (BitIsSet (bytemask, 0)) 12894 { 12895 if (privileged) 12896 tmp_cpsr = tmp_cpsr | (Bits32 (value, 7, 6) << 6); 12897 if (affect_execstate) 12898 tmp_cpsr = tmp_cpsr | (Bit32 (value, 5) << 5); 12899 if (privileged) 12900 tmp_cpsr = tmp_cpsr | Bits32 (value, 4, 0); 12901 } 12902 12903 m_opcode_cpsr = tmp_cpsr; 12904} 12905 12906 12907bool 12908EmulateInstructionARM::BranchWritePC (const Context &context, uint32_t addr) 12909{ 12910 addr_t target; 12911 12912 // Check the current instruction set. 12913 if (CurrentInstrSet() == eModeARM) 12914 target = addr & 0xfffffffc; 12915 else 12916 target = addr & 0xfffffffe; 12917 12918 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, target)) 12919 return false; 12920 12921 return true; 12922} 12923 12924// As a side effect, BXWritePC sets context.arg2 to eModeARM or eModeThumb by inspecting addr. 12925bool 12926EmulateInstructionARM::BXWritePC (Context &context, uint32_t addr) 12927{ 12928 addr_t target; 12929 // If the CPSR is changed due to switching between ARM and Thumb ISETSTATE, 12930 // we want to record it and issue a WriteRegister callback so the clients 12931 // can track the mode changes accordingly. 12932 bool cpsr_changed = false; 12933 12934 if (BitIsSet(addr, 0)) 12935 { 12936 if (CurrentInstrSet() != eModeThumb) 12937 { 12938 SelectInstrSet(eModeThumb); 12939 cpsr_changed = true; 12940 } 12941 target = addr & 0xfffffffe; 12942 context.SetMode (eModeThumb); 12943 } 12944 else if (BitIsClear(addr, 1)) 12945 { 12946 if (CurrentInstrSet() != eModeARM) 12947 { 12948 SelectInstrSet(eModeARM); 12949 cpsr_changed = true; 12950 } 12951 target = addr & 0xfffffffc; 12952 context.SetMode (eModeARM); 12953 } 12954 else 12955 return false; // address<1:0> == '10' => UNPREDICTABLE 12956 12957 if (cpsr_changed) 12958 { 12959 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS, m_new_inst_cpsr)) 12960 return false; 12961 } 12962 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, target)) 12963 return false; 12964 12965 return true; 12966} 12967 12968// Dispatches to either BXWritePC or BranchWritePC based on architecture versions. 12969bool 12970EmulateInstructionARM::LoadWritePC (Context &context, uint32_t addr) 12971{ 12972 if (ArchVersion() >= ARMv5T) 12973 return BXWritePC(context, addr); 12974 else 12975 return BranchWritePC((const Context)context, addr); 12976} 12977 12978// Dispatches to either BXWritePC or BranchWritePC based on architecture versions and current instruction set. 12979bool 12980EmulateInstructionARM::ALUWritePC (Context &context, uint32_t addr) 12981{ 12982 if (ArchVersion() >= ARMv7 && CurrentInstrSet() == eModeARM) 12983 return BXWritePC(context, addr); 12984 else 12985 return BranchWritePC((const Context)context, addr); 12986} 12987 12988EmulateInstructionARM::Mode 12989EmulateInstructionARM::CurrentInstrSet () 12990{ 12991 return m_opcode_mode; 12992} 12993 12994// Set the 'T' bit of our CPSR. The m_opcode_mode gets updated when the next 12995// ReadInstruction() is performed. This function has a side effect of updating 12996// the m_new_inst_cpsr member variable if necessary. 12997bool 12998EmulateInstructionARM::SelectInstrSet (Mode arm_or_thumb) 12999{ 13000 m_new_inst_cpsr = m_opcode_cpsr; 13001 switch (arm_or_thumb) 13002 { 13003 default: 13004 return false; 13005 eModeARM: 13006 // Clear the T bit. 13007 m_new_inst_cpsr &= ~MASK_CPSR_T; 13008 break; 13009 eModeThumb: 13010 // Set the T bit. 13011 m_new_inst_cpsr |= MASK_CPSR_T; 13012 break; 13013 } 13014 return true; 13015} 13016 13017// This function returns TRUE if the processor currently provides support for 13018// unaligned memory accesses, or FALSE otherwise. This is always TRUE in ARMv7, 13019// controllable by the SCTLR.U bit in ARMv6, and always FALSE before ARMv6. 13020bool 13021EmulateInstructionARM::UnalignedSupport() 13022{ 13023 return (ArchVersion() >= ARMv7); 13024} 13025 13026// The main addition and subtraction instructions can produce status information 13027// about both unsigned carry and signed overflow conditions. This status 13028// information can be used to synthesize multi-word additions and subtractions. 13029EmulateInstructionARM::AddWithCarryResult 13030EmulateInstructionARM::AddWithCarry (uint32_t x, uint32_t y, uint8_t carry_in) 13031{ 13032 uint32_t result; 13033 uint8_t carry_out; 13034 uint8_t overflow; 13035 13036 uint64_t unsigned_sum = x + y + carry_in; 13037 int64_t signed_sum = (int32_t)x + (int32_t)y + (int32_t)carry_in; 13038 13039 result = UnsignedBits(unsigned_sum, 31, 0); 13040// carry_out = (result == unsigned_sum ? 0 : 1); 13041 overflow = ((int32_t)result == signed_sum ? 0 : 1); 13042 13043 if (carry_in) 13044 carry_out = ((int32_t) x >= (int32_t) (~y)) ? 1 : 0; 13045 else 13046 carry_out = ((int32_t) x > (int32_t) y) ? 1 : 0; 13047 13048 AddWithCarryResult res = { result, carry_out, overflow }; 13049 return res; 13050} 13051 13052uint32_t 13053EmulateInstructionARM::ReadCoreReg(uint32_t num, bool *success) 13054{ 13055 uint32_t reg_kind, reg_num; 13056 switch (num) 13057 { 13058 case SP_REG: 13059 reg_kind = eRegisterKindGeneric; 13060 reg_num = LLDB_REGNUM_GENERIC_SP; 13061 break; 13062 case LR_REG: 13063 reg_kind = eRegisterKindGeneric; 13064 reg_num = LLDB_REGNUM_GENERIC_RA; 13065 break; 13066 case PC_REG: 13067 reg_kind = eRegisterKindGeneric; 13068 reg_num = LLDB_REGNUM_GENERIC_PC; 13069 break; 13070 default: 13071 if (num < SP_REG) 13072 { 13073 reg_kind = eRegisterKindDWARF; 13074 reg_num = dwarf_r0 + num; 13075 } 13076 else 13077 { 13078 assert(0 && "Invalid register number"); 13079 *success = false; 13080 return UINT32_MAX; 13081 } 13082 break; 13083 } 13084 13085 // Read our register. 13086 uint32_t val = ReadRegisterUnsigned (reg_kind, reg_num, 0, success); 13087 13088 // When executing an ARM instruction , PC reads as the address of the current 13089 // instruction plus 8. 13090 // When executing a Thumb instruction , PC reads as the address of the current 13091 // instruction plus 4. 13092 if (num == 15) 13093 { 13094 if (CurrentInstrSet() == eModeARM) 13095 val += 8; 13096 else 13097 val += 4; 13098 } 13099 13100 return val; 13101} 13102 13103// Write the result to the ARM core register Rd, and optionally update the 13104// condition flags based on the result. 13105// 13106// This helper method tries to encapsulate the following pseudocode from the 13107// ARM Architecture Reference Manual: 13108// 13109// if d == 15 then // Can only occur for encoding A1 13110// ALUWritePC(result); // setflags is always FALSE here 13111// else 13112// R[d] = result; 13113// if setflags then 13114// APSR.N = result<31>; 13115// APSR.Z = IsZeroBit(result); 13116// APSR.C = carry; 13117// // APSR.V unchanged 13118// 13119// In the above case, the API client does not pass in the overflow arg, which 13120// defaults to ~0u. 13121bool 13122EmulateInstructionARM::WriteCoreRegOptionalFlags (Context &context, 13123 const uint32_t result, 13124 const uint32_t Rd, 13125 bool setflags, 13126 const uint32_t carry, 13127 const uint32_t overflow) 13128{ 13129 if (Rd == 15) 13130 { 13131 if (!ALUWritePC (context, result)) 13132 return false; 13133 } 13134 else 13135 { 13136 uint32_t reg_kind, reg_num; 13137 switch (Rd) 13138 { 13139 case SP_REG: 13140 reg_kind = eRegisterKindGeneric; 13141 reg_num = LLDB_REGNUM_GENERIC_SP; 13142 break; 13143 case LR_REG: 13144 reg_kind = eRegisterKindGeneric; 13145 reg_num = LLDB_REGNUM_GENERIC_RA; 13146 break; 13147 default: 13148 reg_kind = eRegisterKindDWARF; 13149 reg_num = dwarf_r0 + Rd; 13150 } 13151 if (!WriteRegisterUnsigned (context, reg_kind, reg_num, result)) 13152 return false; 13153 if (setflags) 13154 return WriteFlags (context, result, carry, overflow); 13155 } 13156 return true; 13157} 13158 13159// This helper method tries to encapsulate the following pseudocode from the 13160// ARM Architecture Reference Manual: 13161// 13162// APSR.N = result<31>; 13163// APSR.Z = IsZeroBit(result); 13164// APSR.C = carry; 13165// APSR.V = overflow 13166// 13167// Default arguments can be specified for carry and overflow parameters, which means 13168// not to update the respective flags. 13169bool 13170EmulateInstructionARM::WriteFlags (Context &context, 13171 const uint32_t result, 13172 const uint32_t carry, 13173 const uint32_t overflow) 13174{ 13175 m_new_inst_cpsr = m_opcode_cpsr; 13176 SetBit32(m_new_inst_cpsr, CPSR_N_POS, Bit32(result, CPSR_N_POS)); 13177 SetBit32(m_new_inst_cpsr, CPSR_Z_POS, result == 0 ? 1 : 0); 13178 if (carry != ~0u) 13179 SetBit32(m_new_inst_cpsr, CPSR_C_POS, carry); 13180 if (overflow != ~0u) 13181 SetBit32(m_new_inst_cpsr, CPSR_V_POS, overflow); 13182 if (m_new_inst_cpsr != m_opcode_cpsr) 13183 { 13184 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS, m_new_inst_cpsr)) 13185 return false; 13186 } 13187 return true; 13188} 13189 13190bool 13191EmulateInstructionARM::EvaluateInstruction () 13192{ 13193 // Advance the ITSTATE bits to their values for the next instruction. 13194 if (m_opcode_mode == eModeThumb && m_it_session.InITBlock()) 13195 m_it_session.ITAdvance(); 13196 13197 13198 ARMOpcode *opcode_data; 13199 13200 if (m_opcode_mode == eModeThumb) 13201 opcode_data = GetThumbOpcodeForInstruction (m_opcode.GetOpcode32()); 13202 else if (m_opcode_mode == eModeARM) 13203 opcode_data = GetARMOpcodeForInstruction (m_opcode.GetOpcode32()); 13204 else 13205 return false; 13206 13207 if (!opcode_data) 13208 return false; 13209 // Verify that we're the right arch for this opcode 13210 13211 switch (m_arm_isa) 13212 { 13213 case ARMv4: 13214 if (opcode_data->variants != ARMvAll) 13215 return false; 13216 break; 13217 13218 case ARMv4T: 13219 if ((opcode_data->variants!= ARMvAll) 13220 && (opcode_data->variants != ARMV4T_ABOVE)) 13221 return false; 13222 break; 13223 13224 case ARMv5T: 13225 case ARMv5TE: 13226 if ((opcode_data->variants != ARMvAll) 13227 && (opcode_data->variants != ARMV4T_ABOVE) 13228 && (opcode_data->variants != ARMV5_ABOVE)) 13229 return false; 13230 break; 13231 13232 case ARMv5TEJ: 13233 if ((opcode_data->variants != ARMvAll) 13234 && (opcode_data->variants != ARMV4T_ABOVE) 13235 && (opcode_data->variants != ARMV5_ABOVE) 13236 && (opcode_data->variants != ARMV5J_ABOVE)) 13237 return false; 13238 break; 13239 13240 case ARMv6: 13241 case ARMv6K: 13242 if ((opcode_data->variants != ARMvAll) 13243 && (opcode_data->variants != ARMV4T_ABOVE) 13244 && (opcode_data->variants != ARMV5_ABOVE) 13245 && (opcode_data->variants != ARMV5J_ABOVE) 13246 && (opcode_data->variants != ARMV6_ABOVE)) 13247 return false; 13248 break; 13249 13250 case ARMv6T2: 13251 case ARMv7: 13252 case ARMv8: 13253 if ((opcode_data->variants != ARMvAll) 13254 && (opcode_data->variants != ARMV4T_ABOVE) 13255 && (opcode_data->variants != ARMV5_ABOVE) 13256 && (opcode_data->variants != ARMV5J_ABOVE) 13257 && (opcode_data->variants != ARMV6_ABOVE) 13258 && (opcode_data->variants != ARMV6T2_ABOVE)) 13259 return false; 13260 break; 13261 13262 default: 13263// if (opcode_data->variants != ARMvAll) 13264// return false; 13265 break; 13266 } 13267 13268 // Just for now, for testing purposes. 13269 if (m_baton == NULL) 13270 fprintf (stdout, "\nEvaluateInstruction, opcode (0x%x), found = '%s'\n", m_opcode.GetOpcode32(), 13271 opcode_data->name); 13272 13273 bool success; 13274 if (m_baton) 13275 { 13276 uint32_t cpsr_value = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_cpsr, 0, &success); 13277 if (success) 13278 m_opcode_cpsr = cpsr_value; 13279 } 13280 13281 uint32_t orig_pc_value = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc, 0, &success); 13282 if (!success) 13283 return false; 13284 13285 success = (this->*opcode_data->callback) (m_opcode.GetOpcode32(), opcode_data->encoding); // Call the Emulate... function. 13286 if (!success) 13287 return false; 13288 13289 uint32_t after_pc_value = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc, 0, &success); 13290 if (!success) 13291 return false; 13292 13293 if (m_advance_pc && (after_pc_value == orig_pc_value)) 13294 { 13295 if (opcode_data->size == eSize32) 13296 after_pc_value += 4; 13297 else if (opcode_data->size == eSize16) 13298 after_pc_value += 2; 13299 13300 EmulateInstruction::Context context; 13301 context.type = eContextAdvancePC; 13302 context.SetNoArgs(); 13303 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc, after_pc_value)) 13304 return false; 13305 13306 } 13307 13308 return true; 13309} 13310 13311bool 13312EmulateInstructionARM::TestEmulation (Stream *out_stream, ArchSpec &arch, OptionValueDictionary *test_data) 13313{ 13314 if (!test_data) 13315 { 13316 out_stream->Printf ("TestEmulation: Missing test data.\n"); 13317 return false; 13318 } 13319 13320 static ConstString opcode_key ("opcode"); 13321 static ConstString before_key ("before_state"); 13322 static ConstString after_key ("after_state"); 13323 13324 OptionValueSP value_sp = test_data->GetValueForKey (opcode_key); 13325 13326 uint32_t test_opcode; 13327 if ((value_sp.get() == NULL) || (value_sp->GetType() != OptionValue::eTypeUInt64)) 13328 { 13329 out_stream->Printf ("TestEmulation: Error reading opcode from test file.\n"); 13330 return false; 13331 } 13332 test_opcode = value_sp->GetUInt64Value (); 13333 13334 // If the instruction emulation does not directly update the PC, advance the PC to the next instruction after 13335 // performing the emulation. 13336 SetAdvancePC (true); 13337 13338 if (arch.GetTriple().getArch() == llvm::Triple::arm) 13339 { 13340 m_opcode_mode = eModeARM; 13341 m_opcode.SetOpcode32 (test_opcode); 13342 } 13343 else if (arch.GetTriple().getArch() == llvm::Triple::thumb) 13344 { 13345 m_opcode_mode = eModeThumb; 13346 if (test_opcode < 0x10000) 13347 m_opcode.SetOpcode16 (test_opcode); 13348 else 13349 m_opcode.SetOpcode32 (test_opcode); 13350 13351 } 13352 else 13353 { 13354 out_stream->Printf ("TestEmulation: Invalid arch.\n"); 13355 return false; 13356 } 13357 13358 EmulationStateARM before_state; 13359 EmulationStateARM after_state; 13360 13361 value_sp = test_data->GetValueForKey (before_key); 13362 if ((value_sp.get() == NULL) || (value_sp->GetType() != OptionValue::eTypeDictionary)) 13363 { 13364 out_stream->Printf ("TestEmulation: Failed to find 'before' state.\n"); 13365 return false; 13366 } 13367 13368 OptionValueDictionary *state_dictionary = value_sp->GetAsDictionaryValue (); 13369 if (!before_state.LoadStateFromDictionary (state_dictionary)) 13370 { 13371 out_stream->Printf ("TestEmulation: Failed loading 'before' state.\n"); 13372 return false; 13373 } 13374 13375 value_sp = test_data->GetValueForKey (after_key); 13376 if ((value_sp.get() == NULL) || (value_sp->GetType() != OptionValue::eTypeDictionary)) 13377 { 13378 out_stream->Printf ("TestEmulation: Failed to find 'after' state.\n"); 13379 return false; 13380 } 13381 13382 state_dictionary = value_sp->GetAsDictionaryValue (); 13383 if (!after_state.LoadStateFromDictionary (state_dictionary)) 13384 { 13385 out_stream->Printf ("TestEmulation: Failed loading 'after' state.\n"); 13386 return false; 13387 } 13388 13389 SetBaton ((void *) &before_state); 13390 SetCallbacks (&EmulationStateARM::ReadPseudoMemory, 13391 &EmulationStateARM::WritePseudoMemory, 13392 &EmulationStateARM::ReadPseudoRegister, 13393 &EmulationStateARM::WritePseudoRegister); 13394 13395 bool success = EvaluateInstruction (); 13396 if (!success) 13397 { 13398 out_stream->Printf ("TestEmulation: EvaluateInstruction() failed.\n"); 13399 return false; 13400 } 13401 13402 success = before_state.CompareState (after_state); 13403 if (!success) 13404 out_stream->Printf ("TestEmulation: 'before' and 'after' states do not match.\n"); 13405 13406 return success; 13407} 13408 13409