EmulateInstructionARM.cpp revision 523c554292bc09fd8519379d628b5e9090acbd36
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 "lldb/Core/ArchSpec.h" 14#include "lldb/Core/Address.h" 15#include "lldb/Core/ConstString.h" 16#include "lldb/Core/PluginManager.h" 17 18#include "Plugins/Process/Utility/ARMDefines.h" 19#include "Plugins/Process/Utility/ARMUtils.h" 20#include "Utility/ARM_DWARF_Registers.h" 21 22#include "llvm/Support/MathExtras.h" // for SignExtend32 template function 23 // and CountTrailingZeros_32 function 24 25using namespace lldb; 26using namespace lldb_private; 27 28// Convenient macro definitions. 29#define APSR_C Bit32(m_opcode_cpsr, CPSR_C_POS) 30#define APSR_V Bit32(m_opcode_cpsr, CPSR_V_POS) 31 32#define AlignPC(pc_val) (pc_val & 0xFFFFFFFC) 33 34//---------------------------------------------------------------------- 35// 36// ITSession implementation 37// 38//---------------------------------------------------------------------- 39 40// A8.6.50 41// Valid return values are {1, 2, 3, 4}, with 0 signifying an error condition. 42static unsigned short CountITSize(unsigned ITMask) { 43 // First count the trailing zeros of the IT mask. 44 unsigned TZ = llvm::CountTrailingZeros_32(ITMask); 45 if (TZ > 3) 46 { 47 printf("Encoding error: IT Mask '0000'\n"); 48 return 0; 49 } 50 return (4 - TZ); 51} 52 53// Init ITState. Note that at least one bit is always 1 in mask. 54bool ITSession::InitIT(unsigned short bits7_0) 55{ 56 ITCounter = CountITSize(Bits32(bits7_0, 3, 0)); 57 if (ITCounter == 0) 58 return false; 59 60 // A8.6.50 IT 61 unsigned short FirstCond = Bits32(bits7_0, 7, 4); 62 if (FirstCond == 0xF) 63 { 64 printf("Encoding error: IT FirstCond '1111'\n"); 65 return false; 66 } 67 if (FirstCond == 0xE && ITCounter != 1) 68 { 69 printf("Encoding error: IT FirstCond '1110' && Mask != '1000'\n"); 70 return false; 71 } 72 73 ITState = bits7_0; 74 return true; 75} 76 77// Update ITState if necessary. 78void ITSession::ITAdvance() 79{ 80 assert(ITCounter); 81 --ITCounter; 82 if (ITCounter == 0) 83 ITState = 0; 84 else 85 { 86 unsigned short NewITState4_0 = Bits32(ITState, 4, 0) << 1; 87 SetBits32(ITState, 4, 0, NewITState4_0); 88 } 89} 90 91// Return true if we're inside an IT Block. 92bool ITSession::InITBlock() 93{ 94 return ITCounter != 0; 95} 96 97// Return true if we're the last instruction inside an IT Block. 98bool ITSession::LastInITBlock() 99{ 100 return ITCounter == 1; 101} 102 103// Get condition bits for the current thumb instruction. 104uint32_t ITSession::GetCond() 105{ 106 if (InITBlock()) 107 return Bits32(ITState, 7, 4); 108 else 109 return COND_AL; 110} 111 112// ARM constants used during decoding 113#define REG_RD 0 114#define LDM_REGLIST 1 115#define SP_REG 13 116#define LR_REG 14 117#define PC_REG 15 118#define PC_REGLIST_BIT 0x8000 119 120#define ARMv4 (1u << 0) 121#define ARMv4T (1u << 1) 122#define ARMv5T (1u << 2) 123#define ARMv5TE (1u << 3) 124#define ARMv5TEJ (1u << 4) 125#define ARMv6 (1u << 5) 126#define ARMv6K (1u << 6) 127#define ARMv6T2 (1u << 7) 128#define ARMv7 (1u << 8) 129#define ARMv8 (1u << 9) 130#define ARMvAll (0xffffffffu) 131 132#define ARMV4T_ABOVE (ARMv4T|ARMv5T|ARMv5TE|ARMv5TEJ|ARMv6|ARMv6K|ARMv6T2|ARMv7|ARMv8) 133#define ARMV5_ABOVE (ARMv5T|ARMv5TE|ARMv5TEJ|ARMv6|ARMv6K|ARMv6T2|ARMv7|ARMv8) 134#define ARMV5TE_ABOVE (ARMv5TE|ARMv5TEJ|ARMv6|ARMv6K|ARMv6T2|ARMv7|ARMv8) 135#define ARMV5J_ABOVE (ARMv5TEJ|ARMv6|ARMv6K|ARMv6T2|ARMv7|ARMv8) 136#define ARMV6_ABOVE (ARMv6|ARMv6K|ARMv6T2|ARMv7|ARMv8) 137#define ARMV6T2_ABOVE (ARMv6T2|ARMv7|ARMv8) 138 139#define No_VFP 0 140#define VFPv1 (1u << 1) 141#define VFPv2 (1u << 2) 142#define VFPv3 (1u << 3) 143#define AdvancedSIMD (1u << 4) 144 145#define VFPv1_ABOVE (VFPv1 | VFPv2 | VFPv3 | AdvancedSIMD) 146#define VFPv2_ABOVE (VFPv2 | VFPv3 | AdvancedSIMD) 147#define VFPv2v3 (VFPv2 | VFPv3) 148 149//---------------------------------------------------------------------- 150// 151// EmulateInstructionARM implementation 152// 153//---------------------------------------------------------------------- 154 155void 156EmulateInstructionARM::Initialize () 157{ 158 PluginManager::RegisterPlugin (GetPluginNameStatic (), 159 GetPluginDescriptionStatic (), 160 CreateInstance); 161} 162 163void 164EmulateInstructionARM::Terminate () 165{ 166 PluginManager::UnregisterPlugin (CreateInstance); 167} 168 169const char * 170EmulateInstructionARM::GetPluginNameStatic () 171{ 172 return "lldb.emulate-instruction.arm"; 173} 174 175const char * 176EmulateInstructionARM::GetPluginDescriptionStatic () 177{ 178 return "Emulate instructions for the ARM architecture."; 179} 180 181EmulateInstruction * 182EmulateInstructionARM::CreateInstance (const ArchSpec &arch) 183{ 184 if (arch.GetTriple().getArch() == llvm::Triple::arm) 185 { 186 std::auto_ptr<EmulateInstructionARM> emulate_insn_ap (new EmulateInstructionARM (arch)); 187 188 if (emulate_insn_ap.get()) 189 return emulate_insn_ap.release(); 190 } 191 else if (arch.GetTriple().getArch() == llvm::Triple::thumb) 192 { 193 std::auto_ptr<EmulateInstructionARM> emulate_insn_ap (new EmulateInstructionARM (arch)); 194 195 if (emulate_insn_ap.get()) 196 return emulate_insn_ap.release(); 197 } 198 199 return NULL; 200} 201 202bool 203EmulateInstructionARM::SetTargetTriple (const ArchSpec &arch) 204{ 205 if (arch.GetTriple().getArch () == llvm::Triple::arm) 206 return true; 207 else if (arch.GetTriple().getArch () == llvm::Triple::thumb) 208 return true; 209 210 return false; 211} 212 213// Write "bits (32) UNKNOWN" to memory address "address". Helper function for many ARM instructions. 214bool 215EmulateInstructionARM::WriteBits32UnknownToMemory (addr_t address) 216{ 217 EmulateInstruction::Context context; 218 context.type = EmulateInstruction::eContextWriteMemoryRandomBits; 219 context.SetNoArgs (); 220 221 uint32_t random_data = rand (); 222 const uint32_t addr_byte_size = GetAddressByteSize(); 223 224 if (!MemAWrite (context, address, random_data, addr_byte_size)) 225 return false; 226 227 return true; 228} 229 230// Write "bits (32) UNKNOWN" to register n. Helper function for many ARM instructions. 231bool 232EmulateInstructionARM::WriteBits32Unknown (int n) 233{ 234 EmulateInstruction::Context context; 235 context.type = EmulateInstruction::eContextWriteRegisterRandomBits; 236 context.SetNoArgs (); 237 238 bool success; 239 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success); 240 241 if (!success) 242 return false; 243 244 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, data)) 245 return false; 246 247 return true; 248} 249 250// Push Multiple Registers stores multiple registers to the stack, storing to 251// consecutive memory locations ending just below the address in SP, and updates 252// SP to point to the start of the stored data. 253bool 254EmulateInstructionARM::EmulatePUSH (const uint32_t opcode, const ARMEncoding encoding) 255{ 256#if 0 257 // ARM pseudo code... 258 if (ConditionPassed()) 259 { 260 EncodingSpecificOperations(); 261 NullCheckIfThumbEE(13); 262 address = SP - 4*BitCount(registers); 263 264 for (i = 0 to 14) 265 { 266 if (registers<i> == '1') 267 { 268 if i == 13 && i != LowestSetBit(registers) // Only possible for encoding A1 269 MemA[address,4] = bits(32) UNKNOWN; 270 else 271 MemA[address,4] = R[i]; 272 address = address + 4; 273 } 274 } 275 276 if (registers<15> == '1') // Only possible for encoding A1 or A2 277 MemA[address,4] = PCStoreValue(); 278 279 SP = SP - 4*BitCount(registers); 280 } 281#endif 282 283 bool success = false; 284 if (ConditionPassed(opcode)) 285 { 286 const uint32_t addr_byte_size = GetAddressByteSize(); 287 const addr_t sp = ReadCoreReg (SP_REG, &success); 288 if (!success) 289 return false; 290 uint32_t registers = 0; 291 uint32_t Rt; // the source register 292 switch (encoding) { 293 case eEncodingT1: 294 registers = Bits32(opcode, 7, 0); 295 // The M bit represents LR. 296 if (Bit32(opcode, 8)) 297 registers |= (1u << 14); 298 // if BitCount(registers) < 1 then UNPREDICTABLE; 299 if (BitCount(registers) < 1) 300 return false; 301 break; 302 case eEncodingT2: 303 // Ignore bits 15 & 13. 304 registers = Bits32(opcode, 15, 0) & ~0xa000; 305 // if BitCount(registers) < 2 then UNPREDICTABLE; 306 if (BitCount(registers) < 2) 307 return false; 308 break; 309 case eEncodingT3: 310 Rt = Bits32(opcode, 15, 12); 311 // if BadReg(t) then UNPREDICTABLE; 312 if (BadReg(Rt)) 313 return false; 314 registers = (1u << Rt); 315 break; 316 case eEncodingA1: 317 registers = Bits32(opcode, 15, 0); 318 // Instead of return false, let's handle the following case as well, 319 // which amounts to pushing one reg onto the full descending stacks. 320 // if BitCount(register_list) < 2 then SEE STMDB / STMFD; 321 break; 322 case eEncodingA2: 323 Rt = Bits32(opcode, 15, 12); 324 // if t == 13 then UNPREDICTABLE; 325 if (Rt == dwarf_sp) 326 return false; 327 registers = (1u << Rt); 328 break; 329 default: 330 return false; 331 } 332 addr_t sp_offset = addr_byte_size * BitCount (registers); 333 addr_t addr = sp - sp_offset; 334 uint32_t i; 335 336 EmulateInstruction::Context context; 337 context.type = EmulateInstruction::eContextPushRegisterOnStack; 338 Register dwarf_reg; 339 dwarf_reg.SetRegister (eRegisterKindDWARF, 0); 340 Register sp_reg; 341 sp_reg.SetRegister (eRegisterKindDWARF, dwarf_sp); 342 for (i=0; i<15; ++i) 343 { 344 if (BitIsSet (registers, i)) 345 { 346 dwarf_reg.num = dwarf_r0 + i; 347 context.SetRegisterToRegisterPlusOffset (dwarf_reg, sp_reg, addr - sp); 348 uint32_t reg_value = ReadCoreReg(i, &success); 349 if (!success) 350 return false; 351 if (!MemAWrite (context, addr, reg_value, addr_byte_size)) 352 return false; 353 addr += addr_byte_size; 354 } 355 } 356 357 if (BitIsSet (registers, 15)) 358 { 359 dwarf_reg.num = dwarf_pc; 360 context.SetRegisterPlusOffset (dwarf_reg, addr - sp); 361 const uint32_t pc = ReadCoreReg(PC_REG, &success); 362 if (!success) 363 return false; 364 if (!MemAWrite (context, addr, pc, addr_byte_size)) 365 return false; 366 } 367 368 context.type = EmulateInstruction::eContextAdjustStackPointer; 369 context.SetImmediateSigned (-sp_offset); 370 371 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, sp - sp_offset)) 372 return false; 373 } 374 return true; 375} 376 377// Pop Multiple Registers loads multiple registers from the stack, loading from 378// consecutive memory locations staring at the address in SP, and updates 379// SP to point just above the loaded data. 380bool 381EmulateInstructionARM::EmulatePOP (const uint32_t opcode, const ARMEncoding encoding) 382{ 383#if 0 384 // ARM pseudo code... 385 if (ConditionPassed()) 386 { 387 EncodingSpecificOperations(); NullCheckIfThumbEE(13); 388 address = SP; 389 for i = 0 to 14 390 if registers<i> == '1' then 391 R[i} = if UnalignedAllowed then MemU[address,4] else MemA[address,4]; address = address + 4; 392 if registers<15> == '1' then 393 if UnalignedAllowed then 394 LoadWritePC(MemU[address,4]); 395 else 396 LoadWritePC(MemA[address,4]); 397 if registers<13> == '0' then SP = SP + 4*BitCount(registers); 398 if registers<13> == '1' then SP = bits(32) UNKNOWN; 399 } 400#endif 401 402 bool success = false; 403 404 if (ConditionPassed(opcode)) 405 { 406 const uint32_t addr_byte_size = GetAddressByteSize(); 407 const addr_t sp = ReadCoreReg (SP_REG, &success); 408 if (!success) 409 return false; 410 uint32_t registers = 0; 411 uint32_t Rt; // the destination register 412 switch (encoding) { 413 case eEncodingT1: 414 registers = Bits32(opcode, 7, 0); 415 // The P bit represents PC. 416 if (Bit32(opcode, 8)) 417 registers |= (1u << 15); 418 // if BitCount(registers) < 1 then UNPREDICTABLE; 419 if (BitCount(registers) < 1) 420 return false; 421 break; 422 case eEncodingT2: 423 // Ignore bit 13. 424 registers = Bits32(opcode, 15, 0) & ~0x2000; 425 // if BitCount(registers) < 2 || (P == '1' && M == '1') then UNPREDICTABLE; 426 if (BitCount(registers) < 2 || (Bit32(opcode, 15) && Bit32(opcode, 14))) 427 return false; 428 // if registers<15> == '1' && InITBlock() && !LastInITBlock() then UNPREDICTABLE; 429 if (BitIsSet(registers, 15) && InITBlock() && !LastInITBlock()) 430 return false; 431 break; 432 case eEncodingT3: 433 Rt = Bits32(opcode, 15, 12); 434 // if t == 13 || (t == 15 && InITBlock() && !LastInITBlock()) then UNPREDICTABLE; 435 if (Rt == 13) 436 return false; 437 if (Rt == 15 && InITBlock() && !LastInITBlock()) 438 return false; 439 registers = (1u << Rt); 440 break; 441 case eEncodingA1: 442 registers = Bits32(opcode, 15, 0); 443 // Instead of return false, let's handle the following case as well, 444 // which amounts to popping one reg from the full descending stacks. 445 // if BitCount(register_list) < 2 then SEE LDM / LDMIA / LDMFD; 446 447 // if registers<13> == '1' && ArchVersion() >= 7 then UNPREDICTABLE; 448 if (BitIsSet(opcode, 13) && ArchVersion() >= ARMv7) 449 return false; 450 break; 451 case eEncodingA2: 452 Rt = Bits32(opcode, 15, 12); 453 // if t == 13 then UNPREDICTABLE; 454 if (Rt == dwarf_sp) 455 return false; 456 registers = (1u << Rt); 457 break; 458 default: 459 return false; 460 } 461 addr_t sp_offset = addr_byte_size * BitCount (registers); 462 addr_t addr = sp; 463 uint32_t i, data; 464 465 EmulateInstruction::Context context; 466 context.type = EmulateInstruction::eContextPopRegisterOffStack; 467 Register dwarf_reg; 468 dwarf_reg.SetRegister (eRegisterKindDWARF, 0); 469 Register sp_reg; 470 sp_reg.SetRegister (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP); 471 for (i=0; i<15; ++i) 472 { 473 if (BitIsSet (registers, i)) 474 { 475 dwarf_reg.num = dwarf_r0 + i; 476 context.SetRegisterPlusOffset (sp_reg, addr - sp); 477 data = MemARead(context, addr, 4, 0, &success); 478 if (!success) 479 return false; 480 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_reg.num, data)) 481 return false; 482 addr += addr_byte_size; 483 } 484 } 485 486 if (BitIsSet (registers, 15)) 487 { 488 dwarf_reg.num = dwarf_pc; 489 context.SetRegisterPlusOffset (sp_reg, addr - sp); 490 data = MemARead(context, addr, 4, 0, &success); 491 if (!success) 492 return false; 493 // In ARMv5T and above, this is an interworking branch. 494 if (!LoadWritePC(context, data)) 495 return false; 496 addr += addr_byte_size; 497 } 498 499 context.type = EmulateInstruction::eContextAdjustStackPointer; 500 context.SetImmediateSigned (sp_offset); 501 502 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, sp + sp_offset)) 503 return false; 504 } 505 return true; 506} 507 508// Set r7 or ip to point to saved value residing within the stack. 509// ADD (SP plus immediate) 510bool 511EmulateInstructionARM::EmulateADDRdSPImm (const uint32_t opcode, const ARMEncoding encoding) 512{ 513#if 0 514 // ARM pseudo code... 515 if (ConditionPassed()) 516 { 517 EncodingSpecificOperations(); 518 (result, carry, overflow) = AddWithCarry(SP, imm32, '0'); 519 if d == 15 then 520 ALUWritePC(result); // setflags is always FALSE here 521 else 522 R[d] = result; 523 if setflags then 524 APSR.N = result<31>; 525 APSR.Z = IsZeroBit(result); 526 APSR.C = carry; 527 APSR.V = overflow; 528 } 529#endif 530 531 bool success = false; 532 533 if (ConditionPassed(opcode)) 534 { 535 const addr_t sp = ReadCoreReg (SP_REG, &success); 536 if (!success) 537 return false; 538 uint32_t Rd; // the destination register 539 uint32_t imm32; 540 switch (encoding) { 541 case eEncodingT1: 542 Rd = 7; 543 imm32 = Bits32(opcode, 7, 0) << 2; // imm32 = ZeroExtend(imm8:'00', 32) 544 break; 545 case eEncodingA1: 546 Rd = Bits32(opcode, 15, 12); 547 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12) 548 break; 549 default: 550 return false; 551 } 552 addr_t sp_offset = imm32; 553 addr_t addr = sp + sp_offset; // a pointer to the stack area 554 555 EmulateInstruction::Context context; 556 context.type = EmulateInstruction::eContextAdjustStackPointer; 557 Register sp_reg; 558 sp_reg.SetRegister (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP); 559 context.SetRegisterPlusOffset (sp_reg, sp_offset); 560 561 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + Rd, addr)) 562 return false; 563 } 564 return true; 565} 566 567// Set r7 or ip to the current stack pointer. 568// MOV (register) 569bool 570EmulateInstructionARM::EmulateMOVRdSP (const uint32_t opcode, const ARMEncoding encoding) 571{ 572#if 0 573 // ARM pseudo code... 574 if (ConditionPassed()) 575 { 576 EncodingSpecificOperations(); 577 result = R[m]; 578 if d == 15 then 579 ALUWritePC(result); // setflags is always FALSE here 580 else 581 R[d] = result; 582 if setflags then 583 APSR.N = result<31>; 584 APSR.Z = IsZeroBit(result); 585 // APSR.C unchanged 586 // APSR.V unchanged 587 } 588#endif 589 590 bool success = false; 591 592 if (ConditionPassed(opcode)) 593 { 594 const addr_t sp = ReadCoreReg (SP_REG, &success); 595 if (!success) 596 return false; 597 uint32_t Rd; // the destination register 598 switch (encoding) { 599 case eEncodingT1: 600 Rd = 7; 601 break; 602 case eEncodingA1: 603 Rd = 12; 604 break; 605 default: 606 return false; 607 } 608 609 EmulateInstruction::Context context; 610 context.type = EmulateInstruction::eContextRegisterPlusOffset; 611 Register sp_reg; 612 sp_reg.SetRegister (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP); 613 context.SetRegisterPlusOffset (sp_reg, 0); 614 615 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + Rd, sp)) 616 return false; 617 } 618 return true; 619} 620 621// Move from high register (r8-r15) to low register (r0-r7). 622// MOV (register) 623bool 624EmulateInstructionARM::EmulateMOVLowHigh (const uint32_t opcode, const ARMEncoding encoding) 625{ 626 return EmulateMOVRdRm (opcode, encoding); 627} 628 629// Move from register to register. 630// MOV (register) 631bool 632EmulateInstructionARM::EmulateMOVRdRm (const uint32_t opcode, const ARMEncoding encoding) 633{ 634#if 0 635 // ARM pseudo code... 636 if (ConditionPassed()) 637 { 638 EncodingSpecificOperations(); 639 result = R[m]; 640 if d == 15 then 641 ALUWritePC(result); // setflags is always FALSE here 642 else 643 R[d] = result; 644 if setflags then 645 APSR.N = result<31>; 646 APSR.Z = IsZeroBit(result); 647 // APSR.C unchanged 648 // APSR.V unchanged 649 } 650#endif 651 652 bool success = false; 653 654 if (ConditionPassed(opcode)) 655 { 656 uint32_t Rm; // the source register 657 uint32_t Rd; // the destination register 658 bool setflags; 659 switch (encoding) { 660 case eEncodingT1: 661 Rd = Bit32(opcode, 7) << 3 | Bits32(opcode, 2, 0); 662 Rm = Bits32(opcode, 6, 3); 663 setflags = false; 664 if (Rd == 15 && InITBlock() && !LastInITBlock()) 665 return false; 666 break; 667 case eEncodingT2: 668 Rd = Bits32(opcode, 2, 0); 669 Rm = Bits32(opcode, 5, 3); 670 setflags = true; 671 if (InITBlock()) 672 return false; 673 break; 674 case eEncodingT3: 675 Rd = Bits32(opcode, 11, 8); 676 Rm = Bits32(opcode, 3, 0); 677 setflags = BitIsSet(opcode, 20); 678 // if setflags && (BadReg(d) || BadReg(m)) then UNPREDICTABLE; 679 if (setflags && (BadReg(Rd) || BadReg(Rm))) 680 return false; 681 // if !setflags && (d == 15 || m == 15 || (d == 13 && m == 13)) then UNPREDICTABLE; 682 if (!setflags && (Rd == 15 || Rm == 15 || (Rd == 13 && Rm == 13))) 683 return false; 684 break; 685 case eEncodingA1: 686 Rd = Bits32(opcode, 15, 12); 687 Rm = Bits32(opcode, 3, 0); 688 setflags = BitIsSet(opcode, 20); 689 690 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions; 691 if (Rd == 15 && setflags) 692 return EmulateSUBSPcLrEtc (opcode, encoding); 693 break; 694 default: 695 return false; 696 } 697 uint32_t result = ReadCoreReg(Rm, &success); 698 if (!success) 699 return false; 700 701 // The context specifies that Rm is to be moved into Rd. 702 EmulateInstruction::Context context; 703 context.type = EmulateInstruction::eContextRegisterLoad; 704 Register dwarf_reg; 705 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + Rm); 706 context.SetRegister (dwarf_reg); 707 708 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags)) 709 return false; 710 } 711 return true; 712} 713 714// Move (immediate) writes an immediate value to the destination register. It 715// can optionally update the condition flags based on the value. 716// MOV (immediate) 717bool 718EmulateInstructionARM::EmulateMOVRdImm (const uint32_t opcode, const ARMEncoding encoding) 719{ 720#if 0 721 // ARM pseudo code... 722 if (ConditionPassed()) 723 { 724 EncodingSpecificOperations(); 725 result = imm32; 726 if d == 15 then // Can only occur for ARM encoding 727 ALUWritePC(result); // setflags is always FALSE here 728 else 729 R[d] = result; 730 if setflags then 731 APSR.N = result<31>; 732 APSR.Z = IsZeroBit(result); 733 APSR.C = carry; 734 // APSR.V unchanged 735 } 736#endif 737 738 if (ConditionPassed(opcode)) 739 { 740 uint32_t Rd; // the destination register 741 uint32_t imm32; // the immediate value to be written to Rd 742 uint32_t carry; // the carry bit after ThumbExpandImm_C or ARMExpandImm_C. 743 bool setflags; 744 switch (encoding) { 745 case eEncodingT1: 746 Rd = Bits32(opcode, 10, 8); 747 setflags = !InITBlock(); 748 imm32 = Bits32(opcode, 7, 0); // imm32 = ZeroExtend(imm8, 32) 749 carry = APSR_C; 750 751 break; 752 753 case eEncodingT2: 754 Rd = Bits32(opcode, 11, 8); 755 setflags = BitIsSet(opcode, 20); 756 imm32 = ThumbExpandImm_C(opcode, APSR_C, carry); 757 if (BadReg(Rd)) 758 return false; 759 760 break; 761 762 case eEncodingT3: 763 { 764 // d = UInt(Rd); setflags = FALSE; imm32 = ZeroExtend(imm4:i:imm3:imm8, 32); 765 Rd = Bits32 (opcode, 11, 8); 766 setflags = false; 767 uint32_t imm4 = Bits32 (opcode, 19, 16); 768 uint32_t imm3 = Bits32 (opcode, 14, 12); 769 uint32_t i = Bit32 (opcode, 26); 770 uint32_t imm8 = Bits32 (opcode, 7, 0); 771 imm32 = (imm4 << 12) | (i << 11) | (imm3 << 8) | imm8; 772 773 // if BadReg(d) then UNPREDICTABLE; 774 if (BadReg (Rd)) 775 return false; 776 } 777 break; 778 779 case eEncodingA1: 780 // d = UInt(Rd); setflags = (S == ‘1’); (imm32, carry) = ARMExpandImm_C(imm12, APSR.C); 781 Rd = Bits32 (opcode, 15, 12); 782 setflags = BitIsSet (opcode, 20); 783 imm32 = ARMExpandImm_C (opcode, APSR_C, carry); 784 785 // if Rd == ‘1111’ && S == ‘1’ then SEE SUBS PC, LR and related instructions; 786 if ((Rd == 15) && setflags) 787 return EmulateSUBSPcLrEtc (opcode, encoding); 788 789 break; 790 791 case eEncodingA2: 792 { 793 // d = UInt(Rd); setflags = FALSE; imm32 = ZeroExtend(imm4:imm12, 32); 794 Rd = Bits32 (opcode, 15, 12); 795 setflags = false; 796 uint32_t imm4 = Bits32 (opcode, 19, 16); 797 uint32_t imm12 = Bits32 (opcode, 11, 0); 798 imm32 = (imm4 << 12) | imm12; 799 800 // if d == 15 then UNPREDICTABLE; 801 if (Rd == 15) 802 return false; 803 } 804 break; 805 806 default: 807 return false; 808 } 809 uint32_t result = imm32; 810 811 // The context specifies that an immediate is to be moved into Rd. 812 EmulateInstruction::Context context; 813 context.type = EmulateInstruction::eContextImmediate; 814 context.SetNoArgs (); 815 816 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry)) 817 return false; 818 } 819 return true; 820} 821 822// MUL multiplies two register values. The least significant 32 bits of the result are written to the destination 823// register. These 32 bits do not depend on whether the source register values are considered to be signed values or 824// unsigned values. 825// 826// Optionally, it can update the condition flags based on the result. In the Thumb instruction set, this option is 827// limited to only a few forms of the instruction. 828bool 829EmulateInstructionARM::EmulateMUL (const uint32_t opcode, const ARMEncoding encoding) 830{ 831#if 0 832 if ConditionPassed() then 833 EncodingSpecificOperations(); 834 operand1 = SInt(R[n]); // operand1 = UInt(R[n]) produces the same final results 835 operand2 = SInt(R[m]); // operand2 = UInt(R[m]) produces the same final results 836 result = operand1 * operand2; 837 R[d] = result<31:0>; 838 if setflags then 839 APSR.N = result<31>; 840 APSR.Z = IsZeroBit(result); 841 if ArchVersion() == 4 then 842 APSR.C = bit UNKNOWN; 843 // else APSR.C unchanged 844 // APSR.V always unchanged 845#endif 846 847 if (ConditionPassed(opcode)) 848 { 849 uint32_t d; 850 uint32_t n; 851 uint32_t m; 852 bool setflags; 853 854 // EncodingSpecificOperations(); 855 switch (encoding) 856 { 857 case eEncodingT1: 858 // d = UInt(Rdm); n = UInt(Rn); m = UInt(Rdm); setflags = !InITBlock(); 859 d = Bits32 (opcode, 2, 0); 860 n = Bits32 (opcode, 5, 3); 861 m = Bits32 (opcode, 2, 0); 862 setflags = !InITBlock(); 863 864 // if ArchVersion() < 6 && d == n then UNPREDICTABLE; 865 if ((ArchVersion() < ARMv6) && (d == n)) 866 return false; 867 868 break; 869 870 case eEncodingT2: 871 // d = UInt(Rd); n = UInt(Rn); m = UInt(Rm); setflags = FALSE; 872 d = Bits32 (opcode, 11, 8); 873 n = Bits32 (opcode, 19, 16); 874 m = Bits32 (opcode, 3, 0); 875 setflags = false; 876 877 // if BadReg(d) || BadReg(n) || BadReg(m) then UNPREDICTABLE; 878 if (BadReg (d) || BadReg (n) || BadReg (m)) 879 return false; 880 881 break; 882 883 case eEncodingA1: 884 // d = UInt(Rd); n = UInt(Rn); m = UInt(Rm); setflags = (S == '1'); 885 d = Bits32 (opcode, 19, 16); 886 n = Bits32 (opcode, 3, 0); 887 m = Bits32 (opcode, 11, 8); 888 setflags = BitIsSet (opcode, 20); 889 890 // if d == 15 || n == 15 || m == 15 then UNPREDICTABLE; 891 if ((d == 15) || (n == 15) || (m == 15)) 892 return false; 893 894 // if ArchVersion() < 6 && d == n then UNPREDICTABLE; 895 if ((ArchVersion() < ARMv6) && (d == n)) 896 return false; 897 898 break; 899 900 default: 901 return false; 902 } 903 904 bool success = false; 905 906 // operand1 = SInt(R[n]); // operand1 = UInt(R[n]) produces the same final results 907 uint64_t operand1 = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success); 908 if (!success) 909 return false; 910 911 // operand2 = SInt(R[m]); // operand2 = UInt(R[m]) produces the same final results 912 uint64_t operand2 = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success); 913 if (!success) 914 return false; 915 916 // result = operand1 * operand2; 917 uint64_t result = operand1 * operand2; 918 919 // R[d] = result<31:0>; 920 Register op1_reg; 921 Register op2_reg; 922 op1_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n); 923 op2_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + m); 924 925 EmulateInstruction::Context context; 926 context.type = eContextMultiplication; 927 context.SetRegisterRegisterOperands (op1_reg, op2_reg); 928 929 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + d, (0x0000ffff & result))) 930 return false; 931 932 // if setflags then 933 if (setflags) 934 { 935 // APSR.N = result<31>; 936 // APSR.Z = IsZeroBit(result); 937 m_new_inst_cpsr = m_opcode_cpsr; 938 SetBit32 (m_new_inst_cpsr, CPSR_N_POS, Bit32 (result, 31)); 939 SetBit32 (m_new_inst_cpsr, CPSR_Z_POS, result == 0 ? 1 : 0); 940 if (m_new_inst_cpsr != m_opcode_cpsr) 941 { 942 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS, m_new_inst_cpsr)) 943 return false; 944 } 945 946 // if ArchVersion() == 4 then 947 // APSR.C = bit UNKNOWN; 948 } 949 } 950 return true; 951} 952 953// Bitwise NOT (immediate) writes the bitwise inverse of an immediate value to the destination register. 954// It can optionally update the condition flags based on the value. 955bool 956EmulateInstructionARM::EmulateMVNImm (const uint32_t opcode, const ARMEncoding encoding) 957{ 958#if 0 959 // ARM pseudo code... 960 if (ConditionPassed()) 961 { 962 EncodingSpecificOperations(); 963 result = NOT(imm32); 964 if d == 15 then // Can only occur for ARM encoding 965 ALUWritePC(result); // setflags is always FALSE here 966 else 967 R[d] = result; 968 if setflags then 969 APSR.N = result<31>; 970 APSR.Z = IsZeroBit(result); 971 APSR.C = carry; 972 // APSR.V unchanged 973 } 974#endif 975 976 if (ConditionPassed(opcode)) 977 { 978 uint32_t Rd; // the destination register 979 uint32_t imm32; // the output after ThumbExpandImm_C or ARMExpandImm_C 980 uint32_t carry; // the carry bit after ThumbExpandImm_C or ARMExpandImm_C 981 bool setflags; 982 switch (encoding) { 983 case eEncodingT1: 984 Rd = Bits32(opcode, 11, 8); 985 setflags = BitIsSet(opcode, 20); 986 imm32 = ThumbExpandImm_C(opcode, APSR_C, carry); 987 break; 988 case eEncodingA1: 989 Rd = Bits32(opcode, 15, 12); 990 setflags = BitIsSet(opcode, 20); 991 imm32 = ARMExpandImm_C(opcode, APSR_C, carry); 992 993 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions; 994 if (Rd == 15 && setflags) 995 return EmulateSUBSPcLrEtc (opcode, encoding); 996 break; 997 default: 998 return false; 999 } 1000 uint32_t result = ~imm32; 1001 1002 // The context specifies that an immediate is to be moved into Rd. 1003 EmulateInstruction::Context context; 1004 context.type = EmulateInstruction::eContextImmediate; 1005 context.SetNoArgs (); 1006 1007 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry)) 1008 return false; 1009 } 1010 return true; 1011} 1012 1013// Bitwise NOT (register) writes the bitwise inverse of a register value to the destination register. 1014// It can optionally update the condition flags based on the result. 1015bool 1016EmulateInstructionARM::EmulateMVNReg (const uint32_t opcode, const ARMEncoding encoding) 1017{ 1018#if 0 1019 // ARM pseudo code... 1020 if (ConditionPassed()) 1021 { 1022 EncodingSpecificOperations(); 1023 (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C); 1024 result = NOT(shifted); 1025 if d == 15 then // Can only occur for ARM encoding 1026 ALUWritePC(result); // setflags is always FALSE here 1027 else 1028 R[d] = result; 1029 if setflags then 1030 APSR.N = result<31>; 1031 APSR.Z = IsZeroBit(result); 1032 APSR.C = carry; 1033 // APSR.V unchanged 1034 } 1035#endif 1036 1037 if (ConditionPassed(opcode)) 1038 { 1039 uint32_t Rm; // the source register 1040 uint32_t Rd; // the destination register 1041 ARM_ShifterType shift_t; 1042 uint32_t shift_n; // the shift applied to the value read from Rm 1043 bool setflags; 1044 uint32_t carry; // the carry bit after the shift operation 1045 switch (encoding) { 1046 case eEncodingT1: 1047 Rd = Bits32(opcode, 2, 0); 1048 Rm = Bits32(opcode, 5, 3); 1049 setflags = !InITBlock(); 1050 shift_t = SRType_LSL; 1051 shift_n = 0; 1052 if (InITBlock()) 1053 return false; 1054 break; 1055 case eEncodingT2: 1056 Rd = Bits32(opcode, 11, 8); 1057 Rm = Bits32(opcode, 3, 0); 1058 setflags = BitIsSet(opcode, 20); 1059 shift_n = DecodeImmShiftThumb(opcode, shift_t); 1060 // if (BadReg(d) || BadReg(m)) then UNPREDICTABLE; 1061 if (BadReg(Rd) || BadReg(Rm)) 1062 return false; 1063 break; 1064 case eEncodingA1: 1065 Rd = Bits32(opcode, 15, 12); 1066 Rm = Bits32(opcode, 3, 0); 1067 setflags = BitIsSet(opcode, 20); 1068 shift_n = DecodeImmShiftARM(opcode, shift_t); 1069 break; 1070 default: 1071 return false; 1072 } 1073 bool success = false; 1074 uint32_t value = ReadCoreReg(Rm, &success); 1075 if (!success) 1076 return false; 1077 1078 uint32_t shifted = Shift_C(value, shift_t, shift_n, APSR_C, carry); 1079 uint32_t result = ~shifted; 1080 1081 // The context specifies that an immediate is to be moved into Rd. 1082 EmulateInstruction::Context context; 1083 context.type = EmulateInstruction::eContextImmediate; 1084 context.SetNoArgs (); 1085 1086 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry)) 1087 return false; 1088 } 1089 return true; 1090} 1091 1092// PC relative immediate load into register, possibly followed by ADD (SP plus register). 1093// LDR (literal) 1094bool 1095EmulateInstructionARM::EmulateLDRRtPCRelative (const uint32_t opcode, const ARMEncoding encoding) 1096{ 1097#if 0 1098 // ARM pseudo code... 1099 if (ConditionPassed()) 1100 { 1101 EncodingSpecificOperations(); NullCheckIfThumbEE(15); 1102 base = Align(PC,4); 1103 address = if add then (base + imm32) else (base - imm32); 1104 data = MemU[address,4]; 1105 if t == 15 then 1106 if address<1:0> == '00' then LoadWritePC(data); else UNPREDICTABLE; 1107 elsif UnalignedSupport() || address<1:0> = '00' then 1108 R[t] = data; 1109 else // Can only apply before ARMv7 1110 if CurrentInstrSet() == InstrSet_ARM then 1111 R[t] = ROR(data, 8*UInt(address<1:0>)); 1112 else 1113 R[t] = bits(32) UNKNOWN; 1114 } 1115#endif 1116 1117 if (ConditionPassed(opcode)) 1118 { 1119 bool success = false; 1120 const uint32_t pc = ReadCoreReg(PC_REG, &success); 1121 if (!success) 1122 return false; 1123 1124 // PC relative immediate load context 1125 EmulateInstruction::Context context; 1126 context.type = EmulateInstruction::eContextRegisterPlusOffset; 1127 Register pc_reg; 1128 pc_reg.SetRegister (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC); 1129 context.SetRegisterPlusOffset (pc_reg, 0); 1130 1131 uint32_t Rt; // the destination register 1132 uint32_t imm32; // immediate offset from the PC 1133 bool add; // +imm32 or -imm32? 1134 addr_t base; // the base address 1135 addr_t address; // the PC relative address 1136 uint32_t data; // the literal data value from the PC relative load 1137 switch (encoding) { 1138 case eEncodingT1: 1139 Rt = Bits32(opcode, 10, 8); 1140 imm32 = Bits32(opcode, 7, 0) << 2; // imm32 = ZeroExtend(imm8:'00', 32); 1141 add = true; 1142 break; 1143 case eEncodingT2: 1144 Rt = Bits32(opcode, 15, 12); 1145 imm32 = Bits32(opcode, 11, 0) << 2; // imm32 = ZeroExtend(imm12, 32); 1146 add = BitIsSet(opcode, 23); 1147 if (Rt == 15 && InITBlock() && !LastInITBlock()) 1148 return false; 1149 break; 1150 default: 1151 return false; 1152 } 1153 1154 base = Align(pc, 4); 1155 if (add) 1156 address = base + imm32; 1157 else 1158 address = base - imm32; 1159 1160 context.SetRegisterPlusOffset(pc_reg, address - base); 1161 data = MemURead(context, address, 4, 0, &success); 1162 if (!success) 1163 return false; 1164 1165 if (Rt == 15) 1166 { 1167 if (Bits32(address, 1, 0) == 0) 1168 { 1169 // In ARMv5T and above, this is an interworking branch. 1170 if (!LoadWritePC(context, data)) 1171 return false; 1172 } 1173 else 1174 return false; 1175 } 1176 else if (UnalignedSupport() || Bits32(address, 1, 0) == 0) 1177 { 1178 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + Rt, data)) 1179 return false; 1180 } 1181 else // We don't handle ARM for now. 1182 return false; 1183 1184 } 1185 return true; 1186} 1187 1188// An add operation to adjust the SP. 1189// ADD (SP plus immediate) 1190bool 1191EmulateInstructionARM::EmulateADDSPImm (const uint32_t opcode, const ARMEncoding encoding) 1192{ 1193#if 0 1194 // ARM pseudo code... 1195 if (ConditionPassed()) 1196 { 1197 EncodingSpecificOperations(); 1198 (result, carry, overflow) = AddWithCarry(SP, imm32, '0'); 1199 if d == 15 then // Can only occur for ARM encoding 1200 ALUWritePC(result); // setflags is always FALSE here 1201 else 1202 R[d] = result; 1203 if setflags then 1204 APSR.N = result<31>; 1205 APSR.Z = IsZeroBit(result); 1206 APSR.C = carry; 1207 APSR.V = overflow; 1208 } 1209#endif 1210 1211 bool success = false; 1212 1213 if (ConditionPassed(opcode)) 1214 { 1215 const addr_t sp = ReadCoreReg (SP_REG, &success); 1216 if (!success) 1217 return false; 1218 uint32_t imm32; // the immediate operand 1219 uint32_t d; 1220 bool setflags; 1221 switch (encoding) 1222 { 1223 case eEncodingT1: 1224 // d = UInt(Rd); setflags = FALSE; imm32 = ZeroExtend(imm8:'00', 32); 1225 d = Bits32 (opcode, 10, 8); 1226 setflags = false; 1227 imm32 = (Bits32 (opcode, 7, 0) << 2); 1228 1229 break; 1230 1231 case eEncodingT2: 1232 // d = 13; setflags = FALSE; imm32 = ZeroExtend(imm7:'00', 32); 1233 d = 13; 1234 setflags = false; 1235 imm32 = ThumbImm7Scaled(opcode); // imm32 = ZeroExtend(imm7:'00', 32) 1236 1237 break; 1238 1239 default: 1240 return false; 1241 } 1242 addr_t sp_offset = imm32; 1243 addr_t addr = sp + sp_offset; // the adjusted stack pointer value 1244 1245 EmulateInstruction::Context context; 1246 context.type = EmulateInstruction::eContextAdjustStackPointer; 1247 Register sp_reg; 1248 sp_reg.SetRegister (eRegisterKindDWARF, dwarf_sp); 1249 context.SetRegisterPlusOffset (sp_reg, sp_offset); 1250 1251 if (d == 15) 1252 { 1253 if (!ALUWritePC (context, addr)) 1254 return false; 1255 } 1256 else 1257 { 1258 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + d, addr)) 1259 return false; 1260 } 1261 } 1262 return true; 1263} 1264 1265// An add operation to adjust the SP. 1266// ADD (SP plus register) 1267bool 1268EmulateInstructionARM::EmulateADDSPRm (const uint32_t opcode, const ARMEncoding encoding) 1269{ 1270#if 0 1271 // ARM pseudo code... 1272 if (ConditionPassed()) 1273 { 1274 EncodingSpecificOperations(); 1275 shifted = Shift(R[m], shift_t, shift_n, APSR.C); 1276 (result, carry, overflow) = AddWithCarry(SP, shifted, '0'); 1277 if d == 15 then 1278 ALUWritePC(result); // setflags is always FALSE here 1279 else 1280 R[d] = result; 1281 if setflags then 1282 APSR.N = result<31>; 1283 APSR.Z = IsZeroBit(result); 1284 APSR.C = carry; 1285 APSR.V = overflow; 1286 } 1287#endif 1288 1289 bool success = false; 1290 1291 if (ConditionPassed(opcode)) 1292 { 1293 const addr_t sp = ReadCoreReg (SP_REG, &success); 1294 if (!success) 1295 return false; 1296 uint32_t Rm; // the second operand 1297 switch (encoding) { 1298 case eEncodingT2: 1299 Rm = Bits32(opcode, 6, 3); 1300 break; 1301 default: 1302 return false; 1303 } 1304 int32_t reg_value = ReadCoreReg(Rm, &success); 1305 if (!success) 1306 return false; 1307 1308 addr_t addr = (int32_t)sp + reg_value; // the adjusted stack pointer value 1309 1310 EmulateInstruction::Context context; 1311 context.type = EmulateInstruction::eContextAddition; 1312 Register sp_reg; 1313 sp_reg.SetRegister (eRegisterKindDWARF, dwarf_sp); 1314 Register other_reg; 1315 other_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + Rm); 1316 context.SetRegisterRegisterOperands (sp_reg, other_reg); 1317 1318 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, addr)) 1319 return false; 1320 } 1321 return true; 1322} 1323 1324// Branch with Link and Exchange Instruction Sets (immediate) calls a subroutine 1325// at a PC-relative address, and changes instruction set from ARM to Thumb, or 1326// from Thumb to ARM. 1327// BLX (immediate) 1328bool 1329EmulateInstructionARM::EmulateBLXImmediate (const uint32_t opcode, const ARMEncoding encoding) 1330{ 1331#if 0 1332 // ARM pseudo code... 1333 if (ConditionPassed()) 1334 { 1335 EncodingSpecificOperations(); 1336 if CurrentInstrSet() == InstrSet_ARM then 1337 LR = PC - 4; 1338 else 1339 LR = PC<31:1> : '1'; 1340 if targetInstrSet == InstrSet_ARM then 1341 targetAddress = Align(PC,4) + imm32; 1342 else 1343 targetAddress = PC + imm32; 1344 SelectInstrSet(targetInstrSet); 1345 BranchWritePC(targetAddress); 1346 } 1347#endif 1348 1349 bool success = true; 1350 1351 if (ConditionPassed(opcode)) 1352 { 1353 EmulateInstruction::Context context; 1354 context.type = EmulateInstruction::eContextRelativeBranchImmediate; 1355 const uint32_t pc = ReadCoreReg(PC_REG, &success); 1356 if (!success) 1357 return false; 1358 addr_t lr; // next instruction address 1359 addr_t target; // target address 1360 int32_t imm32; // PC-relative offset 1361 switch (encoding) { 1362 case eEncodingT1: 1363 { 1364 lr = pc | 1u; // return address 1365 uint32_t S = Bit32(opcode, 26); 1366 uint32_t imm10 = Bits32(opcode, 25, 16); 1367 uint32_t J1 = Bit32(opcode, 13); 1368 uint32_t J2 = Bit32(opcode, 11); 1369 uint32_t imm11 = Bits32(opcode, 10, 0); 1370 uint32_t I1 = !(J1 ^ S); 1371 uint32_t I2 = !(J2 ^ S); 1372 uint32_t imm25 = (S << 24) | (I1 << 23) | (I2 << 22) | (imm10 << 12) | (imm11 << 1); 1373 imm32 = llvm::SignExtend32<25>(imm25); 1374 target = pc + imm32; 1375 context.SetModeAndImmediateSigned (eModeThumb, 4 + imm32); 1376 if (InITBlock() && !LastInITBlock()) 1377 return false; 1378 break; 1379 } 1380 case eEncodingT2: 1381 { 1382 lr = pc | 1u; // return address 1383 uint32_t S = Bit32(opcode, 26); 1384 uint32_t imm10H = Bits32(opcode, 25, 16); 1385 uint32_t J1 = Bit32(opcode, 13); 1386 uint32_t J2 = Bit32(opcode, 11); 1387 uint32_t imm10L = Bits32(opcode, 10, 1); 1388 uint32_t I1 = !(J1 ^ S); 1389 uint32_t I2 = !(J2 ^ S); 1390 uint32_t imm25 = (S << 24) | (I1 << 23) | (I2 << 22) | (imm10H << 12) | (imm10L << 2); 1391 imm32 = llvm::SignExtend32<25>(imm25); 1392 target = Align(pc, 4) + imm32; 1393 context.SetModeAndImmediateSigned (eModeARM, 4 + imm32); 1394 if (InITBlock() && !LastInITBlock()) 1395 return false; 1396 break; 1397 } 1398 case eEncodingA1: 1399 lr = pc - 4; // return address 1400 imm32 = llvm::SignExtend32<26>(Bits32(opcode, 23, 0) << 2); 1401 target = Align(pc, 4) + imm32; 1402 context.SetModeAndImmediateSigned (eModeARM, 8 + imm32); 1403 break; 1404 case eEncodingA2: 1405 lr = pc - 4; // return address 1406 imm32 = llvm::SignExtend32<26>(Bits32(opcode, 23, 0) << 2 | Bits32(opcode, 24, 24) << 1); 1407 target = pc + imm32; 1408 context.SetModeAndImmediateSigned (eModeThumb, 8 + imm32); 1409 break; 1410 default: 1411 return false; 1412 } 1413 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_RA, lr)) 1414 return false; 1415 if (!BranchWritePC(context, target)) 1416 return false; 1417 } 1418 return true; 1419} 1420 1421// Branch with Link and Exchange (register) calls a subroutine at an address and 1422// instruction set specified by a register. 1423// BLX (register) 1424bool 1425EmulateInstructionARM::EmulateBLXRm (const uint32_t opcode, const ARMEncoding encoding) 1426{ 1427#if 0 1428 // ARM pseudo code... 1429 if (ConditionPassed()) 1430 { 1431 EncodingSpecificOperations(); 1432 target = R[m]; 1433 if CurrentInstrSet() == InstrSet_ARM then 1434 next_instr_addr = PC - 4; 1435 LR = next_instr_addr; 1436 else 1437 next_instr_addr = PC - 2; 1438 LR = next_instr_addr<31:1> : '1'; 1439 BXWritePC(target); 1440 } 1441#endif 1442 1443 bool success = false; 1444 1445 if (ConditionPassed(opcode)) 1446 { 1447 EmulateInstruction::Context context; 1448 context.type = EmulateInstruction::eContextAbsoluteBranchRegister; 1449 const uint32_t pc = ReadCoreReg(PC_REG, &success); 1450 addr_t lr; // next instruction address 1451 if (!success) 1452 return false; 1453 uint32_t Rm; // the register with the target address 1454 switch (encoding) { 1455 case eEncodingT1: 1456 lr = (pc - 2) | 1u; // return address 1457 Rm = Bits32(opcode, 6, 3); 1458 // if m == 15 then UNPREDICTABLE; 1459 if (Rm == 15) 1460 return false; 1461 if (InITBlock() && !LastInITBlock()) 1462 return false; 1463 break; 1464 case eEncodingA1: 1465 lr = pc - 4; // return address 1466 Rm = Bits32(opcode, 3, 0); 1467 // if m == 15 then UNPREDICTABLE; 1468 if (Rm == 15) 1469 return false; 1470 break; 1471 default: 1472 return false; 1473 } 1474 addr_t target = ReadCoreReg (Rm, &success); 1475 if (!success) 1476 return false; 1477 Register dwarf_reg; 1478 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + Rm); 1479 context.SetRegister (dwarf_reg); 1480 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_RA, lr)) 1481 return false; 1482 if (!BXWritePC(context, target)) 1483 return false; 1484 } 1485 return true; 1486} 1487 1488// Branch and Exchange causes a branch to an address and instruction set specified by a register. 1489bool 1490EmulateInstructionARM::EmulateBXRm (const uint32_t opcode, const ARMEncoding encoding) 1491{ 1492#if 0 1493 // ARM pseudo code... 1494 if (ConditionPassed()) 1495 { 1496 EncodingSpecificOperations(); 1497 BXWritePC(R[m]); 1498 } 1499#endif 1500 1501 if (ConditionPassed(opcode)) 1502 { 1503 EmulateInstruction::Context context; 1504 context.type = EmulateInstruction::eContextAbsoluteBranchRegister; 1505 uint32_t Rm; // the register with the target address 1506 switch (encoding) { 1507 case eEncodingT1: 1508 Rm = Bits32(opcode, 6, 3); 1509 if (InITBlock() && !LastInITBlock()) 1510 return false; 1511 break; 1512 case eEncodingA1: 1513 Rm = Bits32(opcode, 3, 0); 1514 break; 1515 default: 1516 return false; 1517 } 1518 bool success = false; 1519 addr_t target = ReadCoreReg (Rm, &success); 1520 if (!success) 1521 return false; 1522 1523 Register dwarf_reg; 1524 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + Rm); 1525 context.SetRegister (dwarf_reg); 1526 if (!BXWritePC(context, target)) 1527 return false; 1528 } 1529 return true; 1530} 1531 1532// Branch and Exchange Jazelle attempts to change to Jazelle state. If the attempt fails, it branches to an 1533// address and instruction set specified by a register as though it were a BX instruction. 1534// 1535// TODO: Emulate Jazelle architecture? 1536// We currently assume that switching to Jazelle state fails, thus treating BXJ as a BX operation. 1537bool 1538EmulateInstructionARM::EmulateBXJRm (const uint32_t opcode, const ARMEncoding encoding) 1539{ 1540#if 0 1541 // ARM pseudo code... 1542 if (ConditionPassed()) 1543 { 1544 EncodingSpecificOperations(); 1545 if JMCR.JE == '0' || CurrentInstrSet() == InstrSet_ThumbEE then 1546 BXWritePC(R[m]); 1547 else 1548 if JazelleAcceptsExecution() then 1549 SwitchToJazelleExecution(); 1550 else 1551 SUBARCHITECTURE_DEFINED handler call; 1552 } 1553#endif 1554 1555 if (ConditionPassed(opcode)) 1556 { 1557 EmulateInstruction::Context context; 1558 context.type = EmulateInstruction::eContextAbsoluteBranchRegister; 1559 uint32_t Rm; // the register with the target address 1560 switch (encoding) { 1561 case eEncodingT1: 1562 Rm = Bits32(opcode, 19, 16); 1563 if (BadReg(Rm)) 1564 return false; 1565 if (InITBlock() && !LastInITBlock()) 1566 return false; 1567 break; 1568 case eEncodingA1: 1569 Rm = Bits32(opcode, 3, 0); 1570 if (Rm == 15) 1571 return false; 1572 break; 1573 default: 1574 return false; 1575 } 1576 bool success = false; 1577 addr_t target = ReadCoreReg (Rm, &success); 1578 if (!success) 1579 return false; 1580 1581 Register dwarf_reg; 1582 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + Rm); 1583 context.SetRegister (dwarf_reg); 1584 if (!BXWritePC(context, target)) 1585 return false; 1586 } 1587 return true; 1588} 1589 1590// Set r7 to point to some ip offset. 1591// SUB (immediate) 1592bool 1593EmulateInstructionARM::EmulateSUBR7IPImm (const uint32_t opcode, const ARMEncoding encoding) 1594{ 1595#if 0 1596 // ARM pseudo code... 1597 if (ConditionPassed()) 1598 { 1599 EncodingSpecificOperations(); 1600 (result, carry, overflow) = AddWithCarry(SP, NOT(imm32), '1'); 1601 if d == 15 then // Can only occur for ARM encoding 1602 ALUWritePC(result); // setflags is always FALSE here 1603 else 1604 R[d] = result; 1605 if setflags then 1606 APSR.N = result<31>; 1607 APSR.Z = IsZeroBit(result); 1608 APSR.C = carry; 1609 APSR.V = overflow; 1610 } 1611#endif 1612 1613 if (ConditionPassed(opcode)) 1614 { 1615 bool success = false; 1616 const addr_t ip = ReadCoreReg (12, &success); 1617 if (!success) 1618 return false; 1619 uint32_t imm32; 1620 switch (encoding) { 1621 case eEncodingA1: 1622 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12) 1623 break; 1624 default: 1625 return false; 1626 } 1627 addr_t ip_offset = imm32; 1628 addr_t addr = ip - ip_offset; // the adjusted ip value 1629 1630 EmulateInstruction::Context context; 1631 context.type = EmulateInstruction::eContextRegisterPlusOffset; 1632 Register dwarf_reg; 1633 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r12); 1634 context.SetRegisterPlusOffset (dwarf_reg, -ip_offset); 1635 1636 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r7, addr)) 1637 return false; 1638 } 1639 return true; 1640} 1641 1642// Set ip to point to some stack offset. 1643// SUB (SP minus immediate) 1644bool 1645EmulateInstructionARM::EmulateSUBIPSPImm (const uint32_t opcode, const ARMEncoding encoding) 1646{ 1647#if 0 1648 // ARM pseudo code... 1649 if (ConditionPassed()) 1650 { 1651 EncodingSpecificOperations(); 1652 (result, carry, overflow) = AddWithCarry(SP, NOT(imm32), '1'); 1653 if d == 15 then // Can only occur for ARM encoding 1654 ALUWritePC(result); // setflags is always FALSE here 1655 else 1656 R[d] = result; 1657 if setflags then 1658 APSR.N = result<31>; 1659 APSR.Z = IsZeroBit(result); 1660 APSR.C = carry; 1661 APSR.V = overflow; 1662 } 1663#endif 1664 1665 if (ConditionPassed(opcode)) 1666 { 1667 bool success = false; 1668 const addr_t sp = ReadCoreReg (SP_REG, &success); 1669 if (!success) 1670 return false; 1671 uint32_t imm32; 1672 switch (encoding) { 1673 case eEncodingA1: 1674 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12) 1675 break; 1676 default: 1677 return false; 1678 } 1679 addr_t sp_offset = imm32; 1680 addr_t addr = sp - sp_offset; // the adjusted stack pointer value 1681 1682 EmulateInstruction::Context context; 1683 context.type = EmulateInstruction::eContextRegisterPlusOffset; 1684 Register dwarf_reg; 1685 dwarf_reg.SetRegister (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP); 1686 context.SetRegisterPlusOffset (dwarf_reg, -sp_offset); 1687 1688 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r12, addr)) 1689 return false; 1690 } 1691 return true; 1692} 1693 1694// This instruction subtracts an immediate value from the SP value, and writes 1695// the result to the destination register. 1696// 1697// If Rd == 13 => A sub operation to adjust the SP -- allocate space for local storage. 1698bool 1699EmulateInstructionARM::EmulateSUBSPImm (const uint32_t opcode, const ARMEncoding encoding) 1700{ 1701#if 0 1702 // ARM pseudo code... 1703 if (ConditionPassed()) 1704 { 1705 EncodingSpecificOperations(); 1706 (result, carry, overflow) = AddWithCarry(SP, NOT(imm32), '1'); 1707 if d == 15 then // Can only occur for ARM encoding 1708 ALUWritePC(result); // setflags is always FALSE here 1709 else 1710 R[d] = result; 1711 if setflags then 1712 APSR.N = result<31>; 1713 APSR.Z = IsZeroBit(result); 1714 APSR.C = carry; 1715 APSR.V = overflow; 1716 } 1717#endif 1718 1719 bool success = false; 1720 if (ConditionPassed(opcode)) 1721 { 1722 const addr_t sp = ReadCoreReg (SP_REG, &success); 1723 if (!success) 1724 return false; 1725 1726 uint32_t Rd; 1727 bool setflags; 1728 uint32_t imm32; 1729 switch (encoding) { 1730 case eEncodingT1: 1731 Rd = 13; 1732 setflags = false; 1733 imm32 = ThumbImm7Scaled(opcode); // imm32 = ZeroExtend(imm7:'00', 32) 1734 break; 1735 case eEncodingT2: 1736 Rd = Bits32(opcode, 11, 8); 1737 setflags = BitIsSet(opcode, 20); 1738 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8) 1739 if (Rd == 15 && setflags) 1740 return EmulateCMPImm(opcode, eEncodingT2); 1741 if (Rd == 15 && !setflags) 1742 return false; 1743 break; 1744 case eEncodingT3: 1745 Rd = Bits32(opcode, 11, 8); 1746 setflags = false; 1747 imm32 = ThumbImm12(opcode); // imm32 = ZeroExtend(i:imm3:imm8, 32) 1748 if (Rd == 15) 1749 return false; 1750 break; 1751 case eEncodingA1: 1752 Rd = Bits32(opcode, 15, 12); 1753 setflags = BitIsSet(opcode, 20); 1754 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12) 1755 1756 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions; 1757 if (Rd == 15 && setflags) 1758 return EmulateSUBSPcLrEtc (opcode, encoding); 1759 break; 1760 default: 1761 return false; 1762 } 1763 AddWithCarryResult res = AddWithCarry(sp, ~imm32, 1); 1764 1765 EmulateInstruction::Context context; 1766 if (Rd == 13) 1767 { 1768 uint64_t imm64 = imm32; // Need to expand it to 64 bits before attempting to negate it, or the wrong 1769 // value gets passed down to context.SetImmediateSigned. 1770 context.type = EmulateInstruction::eContextAdjustStackPointer; 1771 context.SetImmediateSigned (-imm64); // the stack pointer offset 1772 } 1773 else 1774 { 1775 context.type = EmulateInstruction::eContextImmediate; 1776 context.SetNoArgs (); 1777 } 1778 1779 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow)) 1780 return false; 1781 } 1782 return true; 1783} 1784 1785// A store operation to the stack that also updates the SP. 1786bool 1787EmulateInstructionARM::EmulateSTRRtSP (const uint32_t opcode, const ARMEncoding encoding) 1788{ 1789#if 0 1790 // ARM pseudo code... 1791 if (ConditionPassed()) 1792 { 1793 EncodingSpecificOperations(); 1794 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32); 1795 address = if index then offset_addr else R[n]; 1796 MemU[address,4] = if t == 15 then PCStoreValue() else R[t]; 1797 if wback then R[n] = offset_addr; 1798 } 1799#endif 1800 1801 bool success = false; 1802 1803 if (ConditionPassed(opcode)) 1804 { 1805 const uint32_t addr_byte_size = GetAddressByteSize(); 1806 const addr_t sp = ReadCoreReg (SP_REG, &success); 1807 if (!success) 1808 return false; 1809 uint32_t Rt; // the source register 1810 uint32_t imm12; 1811 uint32_t Rn; // This function assumes Rn is the SP, but we should verify that. 1812 1813 bool index; 1814 bool add; 1815 bool wback; 1816 switch (encoding) { 1817 case eEncodingA1: 1818 Rt = Bits32(opcode, 15, 12); 1819 imm12 = Bits32(opcode, 11, 0); 1820 Rn = Bits32 (opcode, 19, 16); 1821 1822 if (Rn != 13) // 13 is the SP reg on ARM. Verify that Rn == SP. 1823 return false; 1824 1825 index = BitIsSet (opcode, 24); 1826 add = BitIsSet (opcode, 23); 1827 wback = (BitIsClear (opcode, 24) || BitIsSet (opcode, 21)); 1828 1829 if (wback && ((Rn == 15) || (Rn == Rt))) 1830 return false; 1831 break; 1832 default: 1833 return false; 1834 } 1835 addr_t offset_addr; 1836 if (add) 1837 offset_addr = sp + imm12; 1838 else 1839 offset_addr = sp - imm12; 1840 1841 addr_t addr; 1842 if (index) 1843 addr = offset_addr; 1844 else 1845 addr = sp; 1846 1847 EmulateInstruction::Context context; 1848 context.type = EmulateInstruction::eContextPushRegisterOnStack; 1849 Register sp_reg; 1850 sp_reg.SetRegister (eRegisterKindDWARF, dwarf_sp); 1851 context.SetRegisterPlusOffset (sp_reg, addr - sp); 1852 if (Rt != 15) 1853 { 1854 uint32_t reg_value = ReadCoreReg(Rt, &success); 1855 if (!success) 1856 return false; 1857 if (!MemUWrite (context, addr, reg_value, addr_byte_size)) 1858 return false; 1859 } 1860 else 1861 { 1862 const uint32_t pc = ReadCoreReg(PC_REG, &success); 1863 if (!success) 1864 return false; 1865 if (!MemUWrite (context, addr, pc, addr_byte_size)) 1866 return false; 1867 } 1868 1869 1870 if (wback) 1871 { 1872 context.type = EmulateInstruction::eContextAdjustStackPointer; 1873 context.SetImmediateSigned (addr - sp); 1874 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, offset_addr)) 1875 return false; 1876 } 1877 } 1878 return true; 1879} 1880 1881// Vector Push stores multiple extension registers to the stack. 1882// It also updates SP to point to the start of the stored data. 1883bool 1884EmulateInstructionARM::EmulateVPUSH (const uint32_t opcode, const ARMEncoding encoding) 1885{ 1886#if 0 1887 // ARM pseudo code... 1888 if (ConditionPassed()) 1889 { 1890 EncodingSpecificOperations(); CheckVFPEnabled(TRUE); NullCheckIfThumbEE(13); 1891 address = SP - imm32; 1892 SP = SP - imm32; 1893 if single_regs then 1894 for r = 0 to regs-1 1895 MemA[address,4] = S[d+r]; address = address+4; 1896 else 1897 for r = 0 to regs-1 1898 // Store as two word-aligned words in the correct order for current endianness. 1899 MemA[address,4] = if BigEndian() then D[d+r]<63:32> else D[d+r]<31:0>; 1900 MemA[address+4,4] = if BigEndian() then D[d+r]<31:0> else D[d+r]<63:32>; 1901 address = address+8; 1902 } 1903#endif 1904 1905 bool success = false; 1906 1907 if (ConditionPassed(opcode)) 1908 { 1909 const uint32_t addr_byte_size = GetAddressByteSize(); 1910 const addr_t sp = ReadCoreReg (SP_REG, &success); 1911 if (!success) 1912 return false; 1913 bool single_regs; 1914 uint32_t d; // UInt(D:Vd) or UInt(Vd:D) starting register 1915 uint32_t imm32; // stack offset 1916 uint32_t regs; // number of registers 1917 switch (encoding) { 1918 case eEncodingT1: 1919 case eEncodingA1: 1920 single_regs = false; 1921 d = Bit32(opcode, 22) << 4 | Bits32(opcode, 15, 12); 1922 imm32 = Bits32(opcode, 7, 0) * addr_byte_size; 1923 // If UInt(imm8) is odd, see "FSTMX". 1924 regs = Bits32(opcode, 7, 0) / 2; 1925 // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE; 1926 if (regs == 0 || regs > 16 || (d + regs) > 32) 1927 return false; 1928 break; 1929 case eEncodingT2: 1930 case eEncodingA2: 1931 single_regs = true; 1932 d = Bits32(opcode, 15, 12) << 1 | Bit32(opcode, 22); 1933 imm32 = Bits32(opcode, 7, 0) * addr_byte_size; 1934 regs = Bits32(opcode, 7, 0); 1935 // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE; 1936 if (regs == 0 || regs > 16 || (d + regs) > 32) 1937 return false; 1938 break; 1939 default: 1940 return false; 1941 } 1942 uint32_t start_reg = single_regs ? dwarf_s0 : dwarf_d0; 1943 uint32_t reg_byte_size = single_regs ? addr_byte_size : addr_byte_size * 2; 1944 addr_t sp_offset = imm32; 1945 addr_t addr = sp - sp_offset; 1946 uint32_t i; 1947 1948 EmulateInstruction::Context context; 1949 context.type = EmulateInstruction::eContextPushRegisterOnStack; 1950 Register dwarf_reg; 1951 dwarf_reg.SetRegister (eRegisterKindDWARF, 0); 1952 Register sp_reg; 1953 sp_reg.SetRegister (eRegisterKindDWARF, dwarf_sp); 1954 for (i=0; i<regs; ++i) 1955 { 1956 dwarf_reg.num = start_reg + d + i; 1957 context.SetRegisterToRegisterPlusOffset ( dwarf_reg, sp_reg, addr - sp); 1958 // uint64_t to accommodate 64-bit registers. 1959 uint64_t reg_value = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_reg.num, 0, &success); 1960 if (!success) 1961 return false; 1962 if (!MemAWrite (context, addr, reg_value, reg_byte_size)) 1963 return false; 1964 addr += reg_byte_size; 1965 } 1966 1967 context.type = EmulateInstruction::eContextAdjustStackPointer; 1968 context.SetImmediateSigned (-sp_offset); 1969 1970 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, sp - sp_offset)) 1971 return false; 1972 } 1973 return true; 1974} 1975 1976// Vector Pop loads multiple extension registers from the stack. 1977// It also updates SP to point just above the loaded data. 1978bool 1979EmulateInstructionARM::EmulateVPOP (const uint32_t opcode, const ARMEncoding encoding) 1980{ 1981#if 0 1982 // ARM pseudo code... 1983 if (ConditionPassed()) 1984 { 1985 EncodingSpecificOperations(); CheckVFPEnabled(TRUE); NullCheckIfThumbEE(13); 1986 address = SP; 1987 SP = SP + imm32; 1988 if single_regs then 1989 for r = 0 to regs-1 1990 S[d+r] = MemA[address,4]; address = address+4; 1991 else 1992 for r = 0 to regs-1 1993 word1 = MemA[address,4]; word2 = MemA[address+4,4]; address = address+8; 1994 // Combine the word-aligned words in the correct order for current endianness. 1995 D[d+r] = if BigEndian() then word1:word2 else word2:word1; 1996 } 1997#endif 1998 1999 bool success = false; 2000 2001 if (ConditionPassed(opcode)) 2002 { 2003 const uint32_t addr_byte_size = GetAddressByteSize(); 2004 const addr_t sp = ReadCoreReg (SP_REG, &success); 2005 if (!success) 2006 return false; 2007 bool single_regs; 2008 uint32_t d; // UInt(D:Vd) or UInt(Vd:D) starting register 2009 uint32_t imm32; // stack offset 2010 uint32_t regs; // number of registers 2011 switch (encoding) { 2012 case eEncodingT1: 2013 case eEncodingA1: 2014 single_regs = false; 2015 d = Bit32(opcode, 22) << 4 | Bits32(opcode, 15, 12); 2016 imm32 = Bits32(opcode, 7, 0) * addr_byte_size; 2017 // If UInt(imm8) is odd, see "FLDMX". 2018 regs = Bits32(opcode, 7, 0) / 2; 2019 // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE; 2020 if (regs == 0 || regs > 16 || (d + regs) > 32) 2021 return false; 2022 break; 2023 case eEncodingT2: 2024 case eEncodingA2: 2025 single_regs = true; 2026 d = Bits32(opcode, 15, 12) << 1 | Bit32(opcode, 22); 2027 imm32 = Bits32(opcode, 7, 0) * addr_byte_size; 2028 regs = Bits32(opcode, 7, 0); 2029 // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE; 2030 if (regs == 0 || regs > 16 || (d + regs) > 32) 2031 return false; 2032 break; 2033 default: 2034 return false; 2035 } 2036 uint32_t start_reg = single_regs ? dwarf_s0 : dwarf_d0; 2037 uint32_t reg_byte_size = single_regs ? addr_byte_size : addr_byte_size * 2; 2038 addr_t sp_offset = imm32; 2039 addr_t addr = sp; 2040 uint32_t i; 2041 uint64_t data; // uint64_t to accomodate 64-bit registers. 2042 2043 EmulateInstruction::Context context; 2044 context.type = EmulateInstruction::eContextPopRegisterOffStack; 2045 Register dwarf_reg; 2046 dwarf_reg.SetRegister (eRegisterKindDWARF, 0); 2047 Register sp_reg; 2048 sp_reg.SetRegister (eRegisterKindDWARF, dwarf_sp); 2049 for (i=0; i<regs; ++i) 2050 { 2051 dwarf_reg.num = start_reg + d + i; 2052 context.SetRegisterPlusOffset (sp_reg, addr - sp); 2053 data = MemARead(context, addr, reg_byte_size, 0, &success); 2054 if (!success) 2055 return false; 2056 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_reg.num, data)) 2057 return false; 2058 addr += reg_byte_size; 2059 } 2060 2061 context.type = EmulateInstruction::eContextAdjustStackPointer; 2062 context.SetImmediateSigned (sp_offset); 2063 2064 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, sp + sp_offset)) 2065 return false; 2066 } 2067 return true; 2068} 2069 2070// SVC (previously SWI) 2071bool 2072EmulateInstructionARM::EmulateSVC (const uint32_t opcode, const ARMEncoding encoding) 2073{ 2074#if 0 2075 // ARM pseudo code... 2076 if (ConditionPassed()) 2077 { 2078 EncodingSpecificOperations(); 2079 CallSupervisor(); 2080 } 2081#endif 2082 2083 bool success = false; 2084 2085 if (ConditionPassed(opcode)) 2086 { 2087 const uint32_t pc = ReadCoreReg(PC_REG, &success); 2088 addr_t lr; // next instruction address 2089 if (!success) 2090 return false; 2091 uint32_t imm32; // the immediate constant 2092 uint32_t mode; // ARM or Thumb mode 2093 switch (encoding) { 2094 case eEncodingT1: 2095 lr = (pc + 2) | 1u; // return address 2096 imm32 = Bits32(opcode, 7, 0); 2097 mode = eModeThumb; 2098 break; 2099 case eEncodingA1: 2100 lr = pc + 4; // return address 2101 imm32 = Bits32(opcode, 23, 0); 2102 mode = eModeARM; 2103 break; 2104 default: 2105 return false; 2106 } 2107 2108 EmulateInstruction::Context context; 2109 context.type = EmulateInstruction::eContextSupervisorCall; 2110 context.SetModeAndImmediate (mode, imm32); 2111 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_RA, lr)) 2112 return false; 2113 } 2114 return true; 2115} 2116 2117// If Then makes up to four following instructions (the IT block) conditional. 2118bool 2119EmulateInstructionARM::EmulateIT (const uint32_t opcode, const ARMEncoding encoding) 2120{ 2121#if 0 2122 // ARM pseudo code... 2123 EncodingSpecificOperations(); 2124 ITSTATE.IT<7:0> = firstcond:mask; 2125#endif 2126 2127 m_it_session.InitIT(Bits32(opcode, 7, 0)); 2128 return true; 2129} 2130 2131// Branch causes a branch to a target address. 2132bool 2133EmulateInstructionARM::EmulateB (const uint32_t opcode, const ARMEncoding encoding) 2134{ 2135#if 0 2136 // ARM pseudo code... 2137 if (ConditionPassed()) 2138 { 2139 EncodingSpecificOperations(); 2140 BranchWritePC(PC + imm32); 2141 } 2142#endif 2143 2144 bool success = false; 2145 2146 if (ConditionPassed(opcode)) 2147 { 2148 EmulateInstruction::Context context; 2149 context.type = EmulateInstruction::eContextRelativeBranchImmediate; 2150 const uint32_t pc = ReadCoreReg(PC_REG, &success); 2151 if (!success) 2152 return false; 2153 addr_t target; // target address 2154 int32_t imm32; // PC-relative offset 2155 switch (encoding) { 2156 case eEncodingT1: 2157 // The 'cond' field is handled in EmulateInstructionARM::CurrentCond(). 2158 imm32 = llvm::SignExtend32<9>(Bits32(opcode, 7, 0) << 1); 2159 target = pc + imm32; 2160 context.SetModeAndImmediateSigned (eModeThumb, 4 + imm32); 2161 break; 2162 case eEncodingT2: 2163 imm32 = llvm::SignExtend32<12>(Bits32(opcode, 10, 0)); 2164 target = pc + imm32; 2165 context.SetModeAndImmediateSigned (eModeThumb, 4 + imm32); 2166 break; 2167 case eEncodingT3: 2168 // The 'cond' field is handled in EmulateInstructionARM::CurrentCond(). 2169 { 2170 uint32_t S = Bit32(opcode, 26); 2171 uint32_t imm6 = Bits32(opcode, 21, 16); 2172 uint32_t J1 = Bit32(opcode, 13); 2173 uint32_t J2 = Bit32(opcode, 11); 2174 uint32_t imm11 = Bits32(opcode, 10, 0); 2175 uint32_t imm21 = (S << 20) | (J2 << 19) | (J1 << 18) | (imm6 << 12) | (imm11 << 1); 2176 imm32 = llvm::SignExtend32<21>(imm21); 2177 target = pc + imm32; 2178 context.SetModeAndImmediateSigned (eModeThumb, 4 + imm32); 2179 break; 2180 } 2181 case eEncodingT4: 2182 { 2183 uint32_t S = Bit32(opcode, 26); 2184 uint32_t imm10 = Bits32(opcode, 25, 16); 2185 uint32_t J1 = Bit32(opcode, 13); 2186 uint32_t J2 = Bit32(opcode, 11); 2187 uint32_t imm11 = Bits32(opcode, 10, 0); 2188 uint32_t I1 = !(J1 ^ S); 2189 uint32_t I2 = !(J2 ^ S); 2190 uint32_t imm25 = (S << 24) | (I1 << 23) | (I2 << 22) | (imm10 << 12) | (imm11 << 1); 2191 imm32 = llvm::SignExtend32<25>(imm25); 2192 target = pc + imm32; 2193 context.SetModeAndImmediateSigned (eModeThumb, 4 + imm32); 2194 break; 2195 } 2196 case eEncodingA1: 2197 imm32 = llvm::SignExtend32<26>(Bits32(opcode, 23, 0) << 2); 2198 target = pc + imm32; 2199 context.SetModeAndImmediateSigned (eModeARM, 8 + imm32); 2200 break; 2201 default: 2202 return false; 2203 } 2204 if (!BranchWritePC(context, target)) 2205 return false; 2206 } 2207 return true; 2208} 2209 2210// Compare and Branch on Nonzero and Compare and Branch on Zero compare the value in a register with 2211// zero and conditionally branch forward a constant value. They do not affect the condition flags. 2212// CBNZ, CBZ 2213bool 2214EmulateInstructionARM::EmulateCB (const uint32_t opcode, const ARMEncoding encoding) 2215{ 2216#if 0 2217 // ARM pseudo code... 2218 EncodingSpecificOperations(); 2219 if nonzero ^ IsZero(R[n]) then 2220 BranchWritePC(PC + imm32); 2221#endif 2222 2223 bool success = false; 2224 2225 // Read the register value from the operand register Rn. 2226 uint32_t reg_val = ReadCoreReg(Bits32(opcode, 2, 0), &success); 2227 if (!success) 2228 return false; 2229 2230 EmulateInstruction::Context context; 2231 context.type = EmulateInstruction::eContextRelativeBranchImmediate; 2232 const uint32_t pc = ReadCoreReg(PC_REG, &success); 2233 if (!success) 2234 return false; 2235 2236 addr_t target; // target address 2237 uint32_t imm32; // PC-relative offset to branch forward 2238 bool nonzero; 2239 switch (encoding) { 2240 case eEncodingT1: 2241 imm32 = Bit32(opcode, 9) << 6 | Bits32(opcode, 7, 3) << 1; 2242 nonzero = BitIsSet(opcode, 11); 2243 target = pc + imm32; 2244 context.SetModeAndImmediateSigned (eModeThumb, 4 + imm32); 2245 break; 2246 default: 2247 return false; 2248 } 2249 if (nonzero ^ (reg_val == 0)) 2250 if (!BranchWritePC(context, target)) 2251 return false; 2252 2253 return true; 2254} 2255 2256// Table Branch Byte causes a PC-relative forward branch using a table of single byte offsets. 2257// A base register provides a pointer to the table, and a second register supplies an index into the table. 2258// The branch length is twice the value of the byte returned from the table. 2259// 2260// Table Branch Halfword causes a PC-relative forward branch using a table of single halfword offsets. 2261// A base register provides a pointer to the table, and a second register supplies an index into the table. 2262// The branch length is twice the value of the halfword returned from the table. 2263// TBB, TBH 2264bool 2265EmulateInstructionARM::EmulateTB (const uint32_t opcode, const ARMEncoding encoding) 2266{ 2267#if 0 2268 // ARM pseudo code... 2269 EncodingSpecificOperations(); NullCheckIfThumbEE(n); 2270 if is_tbh then 2271 halfwords = UInt(MemU[R[n]+LSL(R[m],1), 2]); 2272 else 2273 halfwords = UInt(MemU[R[n]+R[m], 1]); 2274 BranchWritePC(PC + 2*halfwords); 2275#endif 2276 2277 bool success = false; 2278 2279 uint32_t Rn; // the base register which contains the address of the table of branch lengths 2280 uint32_t Rm; // the index register which contains an integer pointing to a byte/halfword in the table 2281 bool is_tbh; // true if table branch halfword 2282 switch (encoding) { 2283 case eEncodingT1: 2284 Rn = Bits32(opcode, 19, 16); 2285 Rm = Bits32(opcode, 3, 0); 2286 is_tbh = BitIsSet(opcode, 4); 2287 if (Rn == 13 || BadReg(Rm)) 2288 return false; 2289 if (InITBlock() && !LastInITBlock()) 2290 return false; 2291 break; 2292 default: 2293 return false; 2294 } 2295 2296 // Read the address of the table from the operand register Rn. 2297 // The PC can be used, in which case the table immediately follows this instruction. 2298 uint32_t base = ReadCoreReg(Rm, &success); 2299 if (!success) 2300 return false; 2301 2302 // the table index 2303 uint32_t index = ReadCoreReg(Rm, &success); 2304 if (!success) 2305 return false; 2306 2307 // the offsetted table address 2308 addr_t addr = base + (is_tbh ? index*2 : index); 2309 2310 // PC-relative offset to branch forward 2311 EmulateInstruction::Context context; 2312 context.type = EmulateInstruction::eContextTableBranchReadMemory; 2313 uint32_t offset = MemURead(context, addr, is_tbh ? 2 : 1, 0, &success) * 2; 2314 if (!success) 2315 return false; 2316 2317 const uint32_t pc = ReadCoreReg(PC_REG, &success); 2318 if (!success) 2319 return false; 2320 2321 // target address 2322 addr_t target = pc + offset; 2323 context.type = EmulateInstruction::eContextRelativeBranchImmediate; 2324 context.SetModeAndImmediateSigned (eModeThumb, 4 + offset); 2325 2326 if (!BranchWritePC(context, target)) 2327 return false; 2328 2329 return true; 2330} 2331 2332// This instruction adds an immediate value to a register value, and writes the result to the destination register. 2333// It can optionally update the condition flags based on the result. 2334bool 2335EmulateInstructionARM::EmulateADDImmThumb (const uint32_t opcode, const ARMEncoding encoding) 2336{ 2337#if 0 2338 if ConditionPassed() then 2339 EncodingSpecificOperations(); 2340 (result, carry, overflow) = AddWithCarry(R[n], imm32, '0'); 2341 R[d] = result; 2342 if setflags then 2343 APSR.N = result<31>; 2344 APSR.Z = IsZeroBit(result); 2345 APSR.C = carry; 2346 APSR.V = overflow; 2347#endif 2348 2349 bool success = false; 2350 2351 if (ConditionPassed(opcode)) 2352 { 2353 uint32_t d; 2354 uint32_t n; 2355 bool setflags; 2356 uint32_t imm32; 2357 uint32_t carry_out; 2358 2359 //EncodingSpecificOperations(); 2360 switch (encoding) 2361 { 2362 case eEncodingT1: 2363 // d = UInt(Rd); n = UInt(Rn); setflags = !InITBlock(); imm32 = ZeroExtend(imm3, 32); 2364 d = Bits32 (opcode, 2, 0); 2365 n = Bits32 (opcode, 5, 3); 2366 setflags = !InITBlock(); 2367 imm32 = Bits32 (opcode, 8,6); 2368 2369 break; 2370 2371 case eEncodingT2: 2372 // d = UInt(Rdn); n = UInt(Rdn); setflags = !InITBlock(); imm32 = ZeroExtend(imm8, 32); 2373 d = Bits32 (opcode, 10, 8); 2374 n = Bits32 (opcode, 10, 8); 2375 setflags = !InITBlock(); 2376 imm32 = Bits32 (opcode, 7, 0); 2377 2378 break; 2379 2380 case eEncodingT3: 2381 // if Rd == '1111' && S == '1' then SEE CMN (immediate); 2382 // if Rn == '1101' then SEE ADD (SP plus immediate); 2383 // d = UInt(Rd); n = UInt(Rn); setflags = (S == '1'); imm32 = ThumbExpandImm(i:imm3:imm8); 2384 d = Bits32 (opcode, 11, 8); 2385 n = Bits32 (opcode, 19, 16); 2386 setflags = BitIsSet (opcode, 20); 2387 imm32 = ThumbExpandImm_C (opcode, APSR_C, carry_out); 2388 2389 // if BadReg(d) || n == 15 then UNPREDICTABLE; 2390 if (BadReg (d) || (n == 15)) 2391 return false; 2392 2393 break; 2394 2395 case eEncodingT4: 2396 { 2397 // if Rn == '1111' then SEE ADR; 2398 // if Rn == '1101' then SEE ADD (SP plus immediate); 2399 // d = UInt(Rd); n = UInt(Rn); setflags = FALSE; imm32 = ZeroExtend(i:imm3:imm8, 32); 2400 d = Bits32 (opcode, 11, 8); 2401 n = Bits32 (opcode, 19, 16); 2402 setflags = false; 2403 uint32_t i = Bit32 (opcode, 26); 2404 uint32_t imm3 = Bits32 (opcode, 14, 12); 2405 uint32_t imm8 = Bits32 (opcode, 7, 0); 2406 imm32 = (i << 11) | (imm3 << 8) | imm8; 2407 2408 // if BadReg(d) then UNPREDICTABLE; 2409 if (BadReg (d)) 2410 return false; 2411 2412 break; 2413 } 2414 default: 2415 return false; 2416 } 2417 2418 uint64_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success); 2419 if (!success) 2420 return false; 2421 2422 //(result, carry, overflow) = AddWithCarry(R[n], imm32, '0'); 2423 AddWithCarryResult res = AddWithCarry (Rn, imm32, 0); 2424 2425 Register reg_n; 2426 reg_n.SetRegister (eRegisterKindDWARF, dwarf_r0 + n); 2427 2428 EmulateInstruction::Context context; 2429 context.type = eContextAddition; 2430 context.SetRegisterPlusOffset (reg_n, imm32); 2431 2432 //R[d] = result; 2433 //if setflags then 2434 //APSR.N = result<31>; 2435 //APSR.Z = IsZeroBit(result); 2436 //APSR.C = carry; 2437 //APSR.V = overflow; 2438 if (!WriteCoreRegOptionalFlags (context, res.result, d, setflags, res.carry_out, res.overflow)) 2439 return false; 2440 2441 } 2442 return true; 2443} 2444 2445// This instruction adds an immediate value to a register value, and writes the result to the destination 2446// register. It can optionally update the condition flags based on the result. 2447bool 2448EmulateInstructionARM::EmulateADDImmARM (const uint32_t opcode, const ARMEncoding encoding) 2449{ 2450#if 0 2451 // ARM pseudo code... 2452 if ConditionPassed() then 2453 EncodingSpecificOperations(); 2454 (result, carry, overflow) = AddWithCarry(R[n], imm32, '0'); 2455 if d == 15 then 2456 ALUWritePC(result); // setflags is always FALSE here 2457 else 2458 R[d] = result; 2459 if setflags then 2460 APSR.N = result<31>; 2461 APSR.Z = IsZeroBit(result); 2462 APSR.C = carry; 2463 APSR.V = overflow; 2464#endif 2465 2466 bool success = false; 2467 2468 if (ConditionPassed(opcode)) 2469 { 2470 uint32_t Rd, Rn; 2471 uint32_t imm32; // the immediate value to be added to the value obtained from Rn 2472 bool setflags; 2473 switch (encoding) 2474 { 2475 case eEncodingA1: 2476 Rd = Bits32(opcode, 15, 12); 2477 Rn = Bits32(opcode, 19, 16); 2478 setflags = BitIsSet(opcode, 20); 2479 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12) 2480 break; 2481 default: 2482 return false; 2483 } 2484 2485 // Read the first operand. 2486 uint32_t val1 = ReadCoreReg(Rn, &success); 2487 if (!success) 2488 return false; 2489 2490 AddWithCarryResult res = AddWithCarry(val1, imm32, 0); 2491 2492 EmulateInstruction::Context context; 2493 context.type = EmulateInstruction::eContextAddition; 2494 Register dwarf_reg; 2495 dwarf_reg.SetRegister (eRegisterKindDWARF, Rn); 2496 context.SetRegisterPlusOffset (dwarf_reg, imm32); 2497 2498 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow)) 2499 return false; 2500 } 2501 return true; 2502} 2503 2504// This instruction adds a register value and an optionally-shifted register value, and writes the result 2505// to the destination register. It can optionally update the condition flags based on the result. 2506bool 2507EmulateInstructionARM::EmulateADDReg (const uint32_t opcode, const ARMEncoding encoding) 2508{ 2509#if 0 2510 // ARM pseudo code... 2511 if ConditionPassed() then 2512 EncodingSpecificOperations(); 2513 shifted = Shift(R[m], shift_t, shift_n, APSR.C); 2514 (result, carry, overflow) = AddWithCarry(R[n], shifted, '0'); 2515 if d == 15 then 2516 ALUWritePC(result); // setflags is always FALSE here 2517 else 2518 R[d] = result; 2519 if setflags then 2520 APSR.N = result<31>; 2521 APSR.Z = IsZeroBit(result); 2522 APSR.C = carry; 2523 APSR.V = overflow; 2524#endif 2525 2526 bool success = false; 2527 2528 if (ConditionPassed(opcode)) 2529 { 2530 uint32_t Rd, Rn, Rm; 2531 ARM_ShifterType shift_t; 2532 uint32_t shift_n; // the shift applied to the value read from Rm 2533 bool setflags; 2534 switch (encoding) 2535 { 2536 case eEncodingT1: 2537 Rd = Bits32(opcode, 2, 0); 2538 Rn = Bits32(opcode, 5, 3); 2539 Rm = Bits32(opcode, 8, 6); 2540 setflags = !InITBlock(); 2541 shift_t = SRType_LSL; 2542 shift_n = 0; 2543 break; 2544 case eEncodingT2: 2545 Rd = Rn = Bit32(opcode, 7) << 3 | Bits32(opcode, 2, 0); 2546 Rm = Bits32(opcode, 6, 3); 2547 setflags = false; 2548 shift_t = SRType_LSL; 2549 shift_n = 0; 2550 if (Rn == 15 && Rm == 15) 2551 return false; 2552 if (Rd == 15 && InITBlock() && !LastInITBlock()) 2553 return false; 2554 break; 2555 case eEncodingA1: 2556 Rd = Bits32(opcode, 15, 12); 2557 Rn = Bits32(opcode, 19, 16); 2558 Rm = Bits32(opcode, 3, 0); 2559 setflags = BitIsSet(opcode, 20); 2560 shift_n = DecodeImmShiftARM(opcode, shift_t); 2561 break; 2562 default: 2563 return false; 2564 } 2565 2566 // Read the first operand. 2567 uint32_t val1 = ReadCoreReg(Rn, &success); 2568 if (!success) 2569 return false; 2570 2571 // Read the second operand. 2572 uint32_t val2 = ReadCoreReg(Rm, &success); 2573 if (!success) 2574 return false; 2575 2576 uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C); 2577 AddWithCarryResult res = AddWithCarry(val1, shifted, 0); 2578 2579 EmulateInstruction::Context context; 2580 context.type = EmulateInstruction::eContextAddition; 2581 Register op1_reg; 2582 Register op2_reg; 2583 op1_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + Rn); 2584 op2_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + Rm); 2585 context.SetRegisterRegisterOperands (op1_reg, op2_reg); 2586 2587 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow)) 2588 return false; 2589 } 2590 return true; 2591} 2592 2593// Compare Negative (immediate) adds a register value and an immediate value. 2594// It updates the condition flags based on the result, and discards the result. 2595bool 2596EmulateInstructionARM::EmulateCMNImm (const uint32_t opcode, const ARMEncoding encoding) 2597{ 2598#if 0 2599 // ARM pseudo code... 2600 if ConditionPassed() then 2601 EncodingSpecificOperations(); 2602 (result, carry, overflow) = AddWithCarry(R[n], imm32, '0'); 2603 APSR.N = result<31>; 2604 APSR.Z = IsZeroBit(result); 2605 APSR.C = carry; 2606 APSR.V = overflow; 2607#endif 2608 2609 bool success = false; 2610 2611 uint32_t Rn; // the first operand 2612 uint32_t imm32; // the immediate value to be compared with 2613 switch (encoding) { 2614 case eEncodingT1: 2615 Rn = Bits32(opcode, 19, 16); 2616 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8) 2617 if (Rn == 15) 2618 return false; 2619 break; 2620 case eEncodingA1: 2621 Rn = Bits32(opcode, 19, 16); 2622 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12) 2623 break; 2624 default: 2625 return false; 2626 } 2627 // Read the register value from the operand register Rn. 2628 uint32_t reg_val = ReadCoreReg(Rn, &success); 2629 if (!success) 2630 return false; 2631 2632 AddWithCarryResult res = AddWithCarry(reg_val, imm32, 0); 2633 2634 EmulateInstruction::Context context; 2635 context.type = EmulateInstruction::eContextImmediate; 2636 context.SetNoArgs (); 2637 if (!WriteFlags(context, res.result, res.carry_out, res.overflow)) 2638 return false; 2639 2640 return true; 2641} 2642 2643// Compare Negative (register) adds a register value and an optionally-shifted register value. 2644// It updates the condition flags based on the result, and discards the result. 2645bool 2646EmulateInstructionARM::EmulateCMNReg (const uint32_t opcode, const ARMEncoding encoding) 2647{ 2648#if 0 2649 // ARM pseudo code... 2650 if ConditionPassed() then 2651 EncodingSpecificOperations(); 2652 shifted = Shift(R[m], shift_t, shift_n, APSR.C); 2653 (result, carry, overflow) = AddWithCarry(R[n], shifted, '0'); 2654 APSR.N = result<31>; 2655 APSR.Z = IsZeroBit(result); 2656 APSR.C = carry; 2657 APSR.V = overflow; 2658#endif 2659 2660 bool success = false; 2661 2662 uint32_t Rn; // the first operand 2663 uint32_t Rm; // the second operand 2664 ARM_ShifterType shift_t; 2665 uint32_t shift_n; // the shift applied to the value read from Rm 2666 switch (encoding) { 2667 case eEncodingT1: 2668 Rn = Bits32(opcode, 2, 0); 2669 Rm = Bits32(opcode, 5, 3); 2670 shift_t = SRType_LSL; 2671 shift_n = 0; 2672 break; 2673 case eEncodingT2: 2674 Rn = Bits32(opcode, 19, 16); 2675 Rm = Bits32(opcode, 3, 0); 2676 shift_n = DecodeImmShiftThumb(opcode, shift_t); 2677 // if n == 15 || BadReg(m) then UNPREDICTABLE; 2678 if (Rn == 15 || BadReg(Rm)) 2679 return false; 2680 break; 2681 case eEncodingA1: 2682 Rn = Bits32(opcode, 19, 16); 2683 Rm = Bits32(opcode, 3, 0); 2684 shift_n = DecodeImmShiftARM(opcode, shift_t); 2685 break; 2686 default: 2687 return false; 2688 } 2689 // Read the register value from register Rn. 2690 uint32_t val1 = ReadCoreReg(Rn, &success); 2691 if (!success) 2692 return false; 2693 2694 // Read the register value from register Rm. 2695 uint32_t val2 = ReadCoreReg(Rm, &success); 2696 if (!success) 2697 return false; 2698 2699 uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C); 2700 AddWithCarryResult res = AddWithCarry(val1, shifted, 0); 2701 2702 EmulateInstruction::Context context; 2703 context.type = EmulateInstruction::eContextImmediate; 2704 context.SetNoArgs(); 2705 if (!WriteFlags(context, res.result, res.carry_out, res.overflow)) 2706 return false; 2707 2708 return true; 2709} 2710 2711// Compare (immediate) subtracts an immediate value from a register value. 2712// It updates the condition flags based on the result, and discards the result. 2713bool 2714EmulateInstructionARM::EmulateCMPImm (const uint32_t opcode, const ARMEncoding encoding) 2715{ 2716#if 0 2717 // ARM pseudo code... 2718 if ConditionPassed() then 2719 EncodingSpecificOperations(); 2720 (result, carry, overflow) = AddWithCarry(R[n], NOT(imm32), '1'); 2721 APSR.N = result<31>; 2722 APSR.Z = IsZeroBit(result); 2723 APSR.C = carry; 2724 APSR.V = overflow; 2725#endif 2726 2727 bool success = false; 2728 2729 uint32_t Rn; // the first operand 2730 uint32_t imm32; // the immediate value to be compared with 2731 switch (encoding) { 2732 case eEncodingT1: 2733 Rn = Bits32(opcode, 10, 8); 2734 imm32 = Bits32(opcode, 7, 0); 2735 break; 2736 case eEncodingT2: 2737 Rn = Bits32(opcode, 19, 16); 2738 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8) 2739 if (Rn == 15) 2740 return false; 2741 break; 2742 case eEncodingA1: 2743 Rn = Bits32(opcode, 19, 16); 2744 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12) 2745 break; 2746 default: 2747 return false; 2748 } 2749 // Read the register value from the operand register Rn. 2750 uint32_t reg_val = ReadCoreReg(Rn, &success); 2751 if (!success) 2752 return false; 2753 2754 AddWithCarryResult res = AddWithCarry(reg_val, ~imm32, 1); 2755 2756 EmulateInstruction::Context context; 2757 context.type = EmulateInstruction::eContextImmediate; 2758 context.SetNoArgs (); 2759 if (!WriteFlags(context, res.result, res.carry_out, res.overflow)) 2760 return false; 2761 2762 return true; 2763} 2764 2765// Compare (register) subtracts an optionally-shifted register value from a register value. 2766// It updates the condition flags based on the result, and discards the result. 2767bool 2768EmulateInstructionARM::EmulateCMPReg (const uint32_t opcode, const ARMEncoding encoding) 2769{ 2770#if 0 2771 // ARM pseudo code... 2772 if ConditionPassed() then 2773 EncodingSpecificOperations(); 2774 shifted = Shift(R[m], shift_t, shift_n, APSR.C); 2775 (result, carry, overflow) = AddWithCarry(R[n], NOT(shifted), '1'); 2776 APSR.N = result<31>; 2777 APSR.Z = IsZeroBit(result); 2778 APSR.C = carry; 2779 APSR.V = overflow; 2780#endif 2781 2782 bool success = false; 2783 2784 uint32_t Rn; // the first operand 2785 uint32_t Rm; // the second operand 2786 ARM_ShifterType shift_t; 2787 uint32_t shift_n; // the shift applied to the value read from Rm 2788 switch (encoding) { 2789 case eEncodingT1: 2790 Rn = Bits32(opcode, 2, 0); 2791 Rm = Bits32(opcode, 5, 3); 2792 shift_t = SRType_LSL; 2793 shift_n = 0; 2794 break; 2795 case eEncodingT2: 2796 Rn = Bit32(opcode, 7) << 3 | Bits32(opcode, 2, 0); 2797 Rm = Bits32(opcode, 6, 3); 2798 shift_t = SRType_LSL; 2799 shift_n = 0; 2800 if (Rn < 8 && Rm < 8) 2801 return false; 2802 if (Rn == 15 || Rm == 15) 2803 return false; 2804 break; 2805 case eEncodingA1: 2806 Rn = Bits32(opcode, 19, 16); 2807 Rm = Bits32(opcode, 3, 0); 2808 shift_n = DecodeImmShiftARM(opcode, shift_t); 2809 break; 2810 default: 2811 return false; 2812 } 2813 // Read the register value from register Rn. 2814 uint32_t val1 = ReadCoreReg(Rn, &success); 2815 if (!success) 2816 return false; 2817 2818 // Read the register value from register Rm. 2819 uint32_t val2 = ReadCoreReg(Rm, &success); 2820 if (!success) 2821 return false; 2822 2823 uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C); 2824 AddWithCarryResult res = AddWithCarry(val1, ~shifted, 1); 2825 2826 EmulateInstruction::Context context; 2827 context.type = EmulateInstruction::eContextImmediate; 2828 context.SetNoArgs(); 2829 if (!WriteFlags(context, res.result, res.carry_out, res.overflow)) 2830 return false; 2831 2832 return true; 2833} 2834 2835// Arithmetic Shift Right (immediate) shifts a register value right by an immediate number of bits, 2836// shifting in copies of its sign bit, and writes the result to the destination register. It can 2837// optionally update the condition flags based on the result. 2838bool 2839EmulateInstructionARM::EmulateASRImm (const uint32_t opcode, const ARMEncoding encoding) 2840{ 2841#if 0 2842 // ARM pseudo code... 2843 if ConditionPassed() then 2844 EncodingSpecificOperations(); 2845 (result, carry) = Shift_C(R[m], SRType_ASR, shift_n, APSR.C); 2846 if d == 15 then // Can only occur for ARM encoding 2847 ALUWritePC(result); // setflags is always FALSE here 2848 else 2849 R[d] = result; 2850 if setflags then 2851 APSR.N = result<31>; 2852 APSR.Z = IsZeroBit(result); 2853 APSR.C = carry; 2854 // APSR.V unchanged 2855#endif 2856 2857 return EmulateShiftImm (opcode, encoding, SRType_ASR); 2858} 2859 2860// Arithmetic Shift Right (register) shifts a register value right by a variable number of bits, 2861// shifting in copies of its sign bit, and writes the result to the destination register. 2862// The variable number of bits is read from the bottom byte of a register. It can optionally update 2863// the condition flags based on the result. 2864bool 2865EmulateInstructionARM::EmulateASRReg (const uint32_t opcode, const ARMEncoding encoding) 2866{ 2867#if 0 2868 // ARM pseudo code... 2869 if ConditionPassed() then 2870 EncodingSpecificOperations(); 2871 shift_n = UInt(R[m]<7:0>); 2872 (result, carry) = Shift_C(R[m], SRType_ASR, shift_n, APSR.C); 2873 R[d] = result; 2874 if setflags then 2875 APSR.N = result<31>; 2876 APSR.Z = IsZeroBit(result); 2877 APSR.C = carry; 2878 // APSR.V unchanged 2879#endif 2880 2881 return EmulateShiftReg (opcode, encoding, SRType_ASR); 2882} 2883 2884// Logical Shift Left (immediate) shifts a register value left by an immediate number of bits, 2885// shifting in zeros, and writes the result to the destination register. It can optionally 2886// update the condition flags based on the result. 2887bool 2888EmulateInstructionARM::EmulateLSLImm (const uint32_t opcode, const ARMEncoding encoding) 2889{ 2890#if 0 2891 // ARM pseudo code... 2892 if ConditionPassed() then 2893 EncodingSpecificOperations(); 2894 (result, carry) = Shift_C(R[m], SRType_LSL, shift_n, APSR.C); 2895 if d == 15 then // Can only occur for ARM encoding 2896 ALUWritePC(result); // setflags is always FALSE here 2897 else 2898 R[d] = result; 2899 if setflags then 2900 APSR.N = result<31>; 2901 APSR.Z = IsZeroBit(result); 2902 APSR.C = carry; 2903 // APSR.V unchanged 2904#endif 2905 2906 return EmulateShiftImm (opcode, encoding, SRType_LSL); 2907} 2908 2909// Logical Shift Left (register) shifts a register value left by a variable number of bits, 2910// shifting in zeros, and writes the result to the destination register. The variable number 2911// of bits is read from the bottom byte of a register. It can optionally update the condition 2912// flags based on the result. 2913bool 2914EmulateInstructionARM::EmulateLSLReg (const uint32_t opcode, const ARMEncoding encoding) 2915{ 2916#if 0 2917 // ARM pseudo code... 2918 if ConditionPassed() then 2919 EncodingSpecificOperations(); 2920 shift_n = UInt(R[m]<7:0>); 2921 (result, carry) = Shift_C(R[m], SRType_LSL, shift_n, APSR.C); 2922 R[d] = result; 2923 if setflags then 2924 APSR.N = result<31>; 2925 APSR.Z = IsZeroBit(result); 2926 APSR.C = carry; 2927 // APSR.V unchanged 2928#endif 2929 2930 return EmulateShiftReg (opcode, encoding, SRType_LSL); 2931} 2932 2933// Logical Shift Right (immediate) shifts a register value right by an immediate number of bits, 2934// shifting in zeros, and writes the result to the destination register. It can optionally 2935// update the condition flags based on the result. 2936bool 2937EmulateInstructionARM::EmulateLSRImm (const uint32_t opcode, const ARMEncoding encoding) 2938{ 2939#if 0 2940 // ARM pseudo code... 2941 if ConditionPassed() then 2942 EncodingSpecificOperations(); 2943 (result, carry) = Shift_C(R[m], SRType_LSR, shift_n, APSR.C); 2944 if d == 15 then // Can only occur for ARM encoding 2945 ALUWritePC(result); // setflags is always FALSE here 2946 else 2947 R[d] = result; 2948 if setflags then 2949 APSR.N = result<31>; 2950 APSR.Z = IsZeroBit(result); 2951 APSR.C = carry; 2952 // APSR.V unchanged 2953#endif 2954 2955 return EmulateShiftImm (opcode, encoding, SRType_LSR); 2956} 2957 2958// Logical Shift Right (register) shifts a register value right by a variable number of bits, 2959// shifting in zeros, and writes the result to the destination register. The variable number 2960// of bits is read from the bottom byte of a register. It can optionally update the condition 2961// flags based on the result. 2962bool 2963EmulateInstructionARM::EmulateLSRReg (const uint32_t opcode, const ARMEncoding encoding) 2964{ 2965#if 0 2966 // ARM pseudo code... 2967 if ConditionPassed() then 2968 EncodingSpecificOperations(); 2969 shift_n = UInt(R[m]<7:0>); 2970 (result, carry) = Shift_C(R[m], SRType_LSR, shift_n, APSR.C); 2971 R[d] = result; 2972 if setflags then 2973 APSR.N = result<31>; 2974 APSR.Z = IsZeroBit(result); 2975 APSR.C = carry; 2976 // APSR.V unchanged 2977#endif 2978 2979 return EmulateShiftReg (opcode, encoding, SRType_LSR); 2980} 2981 2982// Rotate Right (immediate) provides the value of the contents of a register rotated by a constant value. 2983// The bits that are rotated off the right end are inserted into the vacated bit positions on the left. 2984// It can optionally update the condition flags based on the result. 2985bool 2986EmulateInstructionARM::EmulateRORImm (const uint32_t opcode, const ARMEncoding encoding) 2987{ 2988#if 0 2989 // ARM pseudo code... 2990 if ConditionPassed() then 2991 EncodingSpecificOperations(); 2992 (result, carry) = Shift_C(R[m], SRType_ROR, shift_n, APSR.C); 2993 if d == 15 then // Can only occur for ARM encoding 2994 ALUWritePC(result); // setflags is always FALSE here 2995 else 2996 R[d] = result; 2997 if setflags then 2998 APSR.N = result<31>; 2999 APSR.Z = IsZeroBit(result); 3000 APSR.C = carry; 3001 // APSR.V unchanged 3002#endif 3003 3004 return EmulateShiftImm (opcode, encoding, SRType_ROR); 3005} 3006 3007// Rotate Right (register) provides the value of the contents of a register rotated by a variable number of bits. 3008// The bits that are rotated off the right end are inserted into the vacated bit positions on the left. 3009// The variable number of bits is read from the bottom byte of a register. It can optionally update the condition 3010// flags based on the result. 3011bool 3012EmulateInstructionARM::EmulateRORReg (const uint32_t opcode, const ARMEncoding encoding) 3013{ 3014#if 0 3015 // ARM pseudo code... 3016 if ConditionPassed() then 3017 EncodingSpecificOperations(); 3018 shift_n = UInt(R[m]<7:0>); 3019 (result, carry) = Shift_C(R[m], SRType_ROR, shift_n, APSR.C); 3020 R[d] = result; 3021 if setflags then 3022 APSR.N = result<31>; 3023 APSR.Z = IsZeroBit(result); 3024 APSR.C = carry; 3025 // APSR.V unchanged 3026#endif 3027 3028 return EmulateShiftReg (opcode, encoding, SRType_ROR); 3029} 3030 3031// Rotate Right with Extend provides the value of the contents of a register shifted right by one place, 3032// with the carry flag shifted into bit [31]. 3033// 3034// RRX can optionally update the condition flags based on the result. 3035// In that case, bit [0] is shifted into the carry flag. 3036bool 3037EmulateInstructionARM::EmulateRRX (const uint32_t opcode, const ARMEncoding encoding) 3038{ 3039#if 0 3040 // ARM pseudo code... 3041 if ConditionPassed() then 3042 EncodingSpecificOperations(); 3043 (result, carry) = Shift_C(R[m], SRType_RRX, 1, APSR.C); 3044 if d == 15 then // Can only occur for ARM encoding 3045 ALUWritePC(result); // setflags is always FALSE here 3046 else 3047 R[d] = result; 3048 if setflags then 3049 APSR.N = result<31>; 3050 APSR.Z = IsZeroBit(result); 3051 APSR.C = carry; 3052 // APSR.V unchanged 3053#endif 3054 3055 return EmulateShiftImm (opcode, encoding, SRType_RRX); 3056} 3057 3058bool 3059EmulateInstructionARM::EmulateShiftImm (const uint32_t opcode, const ARMEncoding encoding, ARM_ShifterType shift_type) 3060{ 3061 assert(shift_type == SRType_ASR 3062 || shift_type == SRType_LSL 3063 || shift_type == SRType_LSR 3064 || shift_type == SRType_ROR 3065 || shift_type == SRType_RRX); 3066 3067 bool success = false; 3068 3069 if (ConditionPassed(opcode)) 3070 { 3071 uint32_t Rd; // the destination register 3072 uint32_t Rm; // the first operand register 3073 uint32_t imm5; // encoding for the shift amount 3074 uint32_t carry; // the carry bit after the shift operation 3075 bool setflags; 3076 3077 // Special case handling! 3078 // A8.6.139 ROR (immediate) -- Encoding T1 3079 ARMEncoding use_encoding = encoding; 3080 if (shift_type == SRType_ROR && use_encoding == eEncodingT1) 3081 { 3082 // Morph the T1 encoding from the ARM Architecture Manual into T2 encoding to 3083 // have the same decoding of bit fields as the other Thumb2 shift operations. 3084 use_encoding = eEncodingT2; 3085 } 3086 3087 switch (use_encoding) { 3088 case eEncodingT1: 3089 // Due to the above special case handling! 3090 assert(shift_type != SRType_ROR); 3091 3092 Rd = Bits32(opcode, 2, 0); 3093 Rm = Bits32(opcode, 5, 3); 3094 setflags = !InITBlock(); 3095 imm5 = Bits32(opcode, 10, 6); 3096 break; 3097 case eEncodingT2: 3098 // A8.6.141 RRX 3099 assert(shift_type != SRType_RRX); 3100 3101 Rd = Bits32(opcode, 11, 8); 3102 Rm = Bits32(opcode, 3, 0); 3103 setflags = BitIsSet(opcode, 20); 3104 imm5 = Bits32(opcode, 14, 12) << 2 | Bits32(opcode, 7, 6); 3105 if (BadReg(Rd) || BadReg(Rm)) 3106 return false; 3107 break; 3108 case eEncodingA1: 3109 Rd = Bits32(opcode, 15, 12); 3110 Rm = Bits32(opcode, 3, 0); 3111 setflags = BitIsSet(opcode, 20); 3112 imm5 = Bits32(opcode, 11, 7); 3113 break; 3114 default: 3115 return false; 3116 } 3117 3118 // A8.6.139 ROR (immediate) 3119 if (shift_type == SRType_ROR && imm5 == 0) 3120 shift_type = SRType_RRX; 3121 3122 // Get the first operand. 3123 uint32_t value = ReadCoreReg (Rm, &success); 3124 if (!success) 3125 return false; 3126 3127 // Decode the shift amount if not RRX. 3128 uint32_t amt = (shift_type == SRType_RRX ? 1 : DecodeImmShift(shift_type, imm5)); 3129 3130 uint32_t result = Shift_C(value, shift_type, amt, APSR_C, carry); 3131 3132 // The context specifies that an immediate is to be moved into Rd. 3133 EmulateInstruction::Context context; 3134 context.type = EmulateInstruction::eContextImmediate; 3135 context.SetNoArgs (); 3136 3137 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry)) 3138 return false; 3139 } 3140 return true; 3141} 3142 3143bool 3144EmulateInstructionARM::EmulateShiftReg (const uint32_t opcode, const ARMEncoding encoding, ARM_ShifterType shift_type) 3145{ 3146 assert(shift_type == SRType_ASR || shift_type == SRType_LSL || shift_type == SRType_LSR); 3147 3148 bool success = false; 3149 3150 if (ConditionPassed(opcode)) 3151 { 3152 uint32_t Rd; // the destination register 3153 uint32_t Rn; // the first operand register 3154 uint32_t Rm; // the register whose bottom byte contains the amount to shift by 3155 uint32_t carry; // the carry bit after the shift operation 3156 bool setflags; 3157 switch (encoding) { 3158 case eEncodingT1: 3159 Rd = Bits32(opcode, 2, 0); 3160 Rn = Rd; 3161 Rm = Bits32(opcode, 5, 3); 3162 setflags = !InITBlock(); 3163 break; 3164 case eEncodingT2: 3165 Rd = Bits32(opcode, 11, 8); 3166 Rn = Bits32(opcode, 19, 16); 3167 Rm = Bits32(opcode, 3, 0); 3168 setflags = BitIsSet(opcode, 20); 3169 if (BadReg(Rd) || BadReg(Rn) || BadReg(Rm)) 3170 return false; 3171 break; 3172 case eEncodingA1: 3173 Rd = Bits32(opcode, 15, 12); 3174 Rn = Bits32(opcode, 3, 0); 3175 Rm = Bits32(opcode, 11, 8); 3176 setflags = BitIsSet(opcode, 20); 3177 if (Rd == 15 || Rn == 15 || Rm == 15) 3178 return false; 3179 break; 3180 default: 3181 return false; 3182 } 3183 3184 // Get the first operand. 3185 uint32_t value = ReadCoreReg (Rn, &success); 3186 if (!success) 3187 return false; 3188 // Get the Rm register content. 3189 uint32_t val = ReadCoreReg (Rm, &success); 3190 if (!success) 3191 return false; 3192 3193 // Get the shift amount. 3194 uint32_t amt = Bits32(val, 7, 0); 3195 3196 uint32_t result = Shift_C(value, shift_type, amt, APSR_C, carry); 3197 3198 // The context specifies that an immediate is to be moved into Rd. 3199 EmulateInstruction::Context context; 3200 context.type = EmulateInstruction::eContextImmediate; 3201 context.SetNoArgs (); 3202 3203 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry)) 3204 return false; 3205 } 3206 return true; 3207} 3208 3209// LDM loads multiple registers from consecutive memory locations, using an 3210// address from a base register. Optionally the address just above the highest of those locations 3211// can be written back to the base register. 3212bool 3213EmulateInstructionARM::EmulateLDM (const uint32_t opcode, const ARMEncoding encoding) 3214{ 3215#if 0 3216 // ARM pseudo code... 3217 if ConditionPassed() 3218 EncodingSpecificOperations(); NullCheckIfThumbEE (n); 3219 address = R[n]; 3220 3221 for i = 0 to 14 3222 if registers<i> == '1' then 3223 R[i] = MemA[address, 4]; address = address + 4; 3224 if registers<15> == '1' then 3225 LoadWritePC (MemA[address, 4]); 3226 3227 if wback && registers<n> == '0' then R[n] = R[n] + 4 * BitCount (registers); 3228 if wback && registers<n> == '1' then R[n] = bits(32) UNKNOWN; // Only possible for encoding A1 3229 3230#endif 3231 3232 bool success = false; 3233 3234 if (ConditionPassed(opcode)) 3235 { 3236 uint32_t n; 3237 uint32_t registers = 0; 3238 bool wback; 3239 const uint32_t addr_byte_size = GetAddressByteSize(); 3240 switch (encoding) 3241 { 3242 case eEncodingT1: 3243 // n = UInt(Rn); registers = '00000000':register_list; wback = (registers<n> == '0'); 3244 n = Bits32 (opcode, 10, 8); 3245 registers = Bits32 (opcode, 7, 0); 3246 registers = registers & 0x00ff; // Make sure the top 8 bits are zeros. 3247 wback = BitIsClear (registers, n); 3248 // if BitCount(registers) < 1 then UNPREDICTABLE; 3249 if (BitCount(registers) < 1) 3250 return false; 3251 break; 3252 case eEncodingT2: 3253 // if W == '1' && Rn == '1101' then SEE POP; 3254 // n = UInt(Rn); registers = P:M:'0':register_list; wback = (W == '1'); 3255 n = Bits32 (opcode, 19, 16); 3256 registers = Bits32 (opcode, 15, 0); 3257 registers = registers & 0xdfff; // Make sure bit 13 is zero. 3258 wback = BitIsSet (opcode, 21); 3259 3260 // if n == 15 || BitCount(registers) < 2 || (P == '1' && M == '1') then UNPREDICTABLE; 3261 if ((n == 15) 3262 || (BitCount (registers) < 2) 3263 || (BitIsSet (opcode, 14) && BitIsSet (opcode, 15))) 3264 return false; 3265 3266 // if registers<15> == '1' && InITBlock() && !LastInITBlock() then UNPREDICTABLE; 3267 if (BitIsSet (registers, 15) && InITBlock() && !LastInITBlock()) 3268 return false; 3269 3270 // if wback && registers<n> == '1' then UNPREDICTABLE; 3271 if (wback 3272 && BitIsSet (registers, n)) 3273 return false; 3274 break; 3275 3276 case eEncodingA1: 3277 n = Bits32 (opcode, 19, 16); 3278 registers = Bits32 (opcode, 15, 0); 3279 wback = BitIsSet (opcode, 21); 3280 if ((n == 15) 3281 || (BitCount (registers) < 1)) 3282 return false; 3283 break; 3284 default: 3285 return false; 3286 } 3287 3288 int32_t offset = 0; 3289 const addr_t base_address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success); 3290 if (!success) 3291 return false; 3292 3293 EmulateInstruction::Context context; 3294 context.type = EmulateInstruction::eContextRegisterPlusOffset; 3295 Register dwarf_reg; 3296 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n); 3297 context.SetRegisterPlusOffset (dwarf_reg, offset); 3298 3299 for (int i = 0; i < 14; ++i) 3300 { 3301 if (BitIsSet (registers, i)) 3302 { 3303 context.type = EmulateInstruction::eContextRegisterPlusOffset; 3304 context.SetRegisterPlusOffset (dwarf_reg, offset); 3305 if (wback && (n == 13)) // Pop Instruction 3306 context.type = EmulateInstruction::eContextPopRegisterOffStack; 3307 3308 // R[i] = MemA [address, 4]; address = address + 4; 3309 uint32_t data = MemARead (context, base_address + offset, addr_byte_size, 0, &success); 3310 if (!success) 3311 return false; 3312 3313 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + i, data)) 3314 return false; 3315 3316 offset += addr_byte_size; 3317 } 3318 } 3319 3320 if (BitIsSet (registers, 15)) 3321 { 3322 //LoadWritePC (MemA [address, 4]); 3323 context.type = EmulateInstruction::eContextRegisterPlusOffset; 3324 context.SetRegisterPlusOffset (dwarf_reg, offset); 3325 uint32_t data = MemARead (context, base_address + offset, addr_byte_size, 0, &success); 3326 if (!success) 3327 return false; 3328 // In ARMv5T and above, this is an interworking branch. 3329 if (!LoadWritePC(context, data)) 3330 return false; 3331 } 3332 3333 if (wback && BitIsClear (registers, n)) 3334 { 3335 // R[n] = R[n] + 4 * BitCount (registers) 3336 int32_t offset = addr_byte_size * BitCount (registers); 3337 context.type = EmulateInstruction::eContextAdjustBaseRegister; 3338 context.SetRegisterPlusOffset (dwarf_reg, offset); 3339 3340 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, base_address + offset)) 3341 return false; 3342 } 3343 if (wback && BitIsSet (registers, n)) 3344 // R[n] bits(32) UNKNOWN; 3345 return WriteBits32Unknown (n); 3346 } 3347 return true; 3348} 3349 3350// LDMDA loads multiple registers from consecutive memory locations using an address from a base register. 3351// The consecutive memory locations end at this address and the address just below the lowest of those locations 3352// can optionally be written back to the base register. 3353bool 3354EmulateInstructionARM::EmulateLDMDA (const uint32_t opcode, const ARMEncoding encoding) 3355{ 3356#if 0 3357 // ARM pseudo code... 3358 if ConditionPassed() then 3359 EncodingSpecificOperations(); 3360 address = R[n] - 4*BitCount(registers) + 4; 3361 3362 for i = 0 to 14 3363 if registers<i> == '1' then 3364 R[i] = MemA[address,4]; address = address + 4; 3365 3366 if registers<15> == '1' then 3367 LoadWritePC(MemA[address,4]); 3368 3369 if wback && registers<n> == '0' then R[n] = R[n] - 4*BitCount(registers); 3370 if wback && registers<n> == '1' then R[n] = bits(32) UNKNOWN; 3371#endif 3372 3373 bool success = false; 3374 3375 if (ConditionPassed(opcode)) 3376 { 3377 uint32_t n; 3378 uint32_t registers = 0; 3379 bool wback; 3380 const uint32_t addr_byte_size = GetAddressByteSize(); 3381 3382 // EncodingSpecificOperations(); 3383 switch (encoding) 3384 { 3385 case eEncodingA1: 3386 // n = UInt(Rn); registers = register_list; wback = (W == '1'); 3387 n = Bits32 (opcode, 19, 16); 3388 registers = Bits32 (opcode, 15, 0); 3389 wback = BitIsSet (opcode, 21); 3390 3391 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE; 3392 if ((n == 15) || (BitCount (registers) < 1)) 3393 return false; 3394 3395 break; 3396 3397 default: 3398 return false; 3399 } 3400 // address = R[n] - 4*BitCount(registers) + 4; 3401 3402 int32_t offset = 0; 3403 addr_t Rn = ReadCoreReg (n, &success); 3404 3405 if (!success) 3406 return false; 3407 3408 addr_t address = Rn - (addr_byte_size * BitCount (registers)) + addr_byte_size; 3409 3410 EmulateInstruction::Context context; 3411 context.type = EmulateInstruction::eContextRegisterPlusOffset; 3412 Register dwarf_reg; 3413 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n); 3414 context.SetRegisterPlusOffset (dwarf_reg, offset); 3415 3416 // for i = 0 to 14 3417 for (int i = 0; i < 14; ++i) 3418 { 3419 // if registers<i> == '1' then 3420 if (BitIsSet (registers, i)) 3421 { 3422 // R[i] = MemA[address,4]; address = address + 4; 3423 context.SetRegisterPlusOffset (dwarf_reg, Rn - (address + offset)); 3424 uint32_t data = MemARead (context, address + offset, addr_byte_size, 0, &success); 3425 if (!success) 3426 return false; 3427 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + i, data)) 3428 return false; 3429 offset += addr_byte_size; 3430 } 3431 } 3432 3433 // if registers<15> == '1' then 3434 // LoadWritePC(MemA[address,4]); 3435 if (BitIsSet (registers, 15)) 3436 { 3437 context.SetRegisterPlusOffset (dwarf_reg, offset); 3438 uint32_t data = MemARead (context, address + offset, addr_byte_size, 0, &success); 3439 if (!success) 3440 return false; 3441 // In ARMv5T and above, this is an interworking branch. 3442 if (!LoadWritePC(context, data)) 3443 return false; 3444 } 3445 3446 // if wback && registers<n> == '0' then R[n] = R[n] - 4*BitCount(registers); 3447 if (wback && BitIsClear (registers, n)) 3448 { 3449 if (!success) 3450 return false; 3451 3452 offset = (addr_byte_size * BitCount (registers)) * -1; 3453 context.type = EmulateInstruction::eContextAdjustBaseRegister; 3454 context.SetImmediateSigned (offset); 3455 addr_t addr = Rn + offset; 3456 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, addr)) 3457 return false; 3458 } 3459 3460 // if wback && registers<n> == '1' then R[n] = bits(32) UNKNOWN; 3461 if (wback && BitIsSet (registers, n)) 3462 return WriteBits32Unknown (n); 3463 } 3464 return true; 3465} 3466 3467// LDMDB loads multiple registers from consecutive memory locations using an address from a base register. The 3468// consecutive memory lcoations end just below this address, and the address of the lowest of those locations can 3469// be optionally written back to the base register. 3470bool 3471EmulateInstructionARM::EmulateLDMDB (const uint32_t opcode, const ARMEncoding encoding) 3472{ 3473#if 0 3474 // ARM pseudo code... 3475 if ConditionPassed() then 3476 EncodingSpecificOperations(); NullCheckIfThumbEE(n); 3477 address = R[n] - 4*BitCount(registers); 3478 3479 for i = 0 to 14 3480 if registers<i> == '1' then 3481 R[i] = MemA[address,4]; address = address + 4; 3482 if registers<15> == '1' then 3483 LoadWritePC(MemA[address,4]); 3484 3485 if wback && registers<n> == '0' then R[n] = R[n] - 4*BitCount(registers); 3486 if wback && registers<n> == '1' then R[n] = bits(32) UNKNOWN; // Only possible for encoding A1 3487#endif 3488 3489 bool success = false; 3490 3491 if (ConditionPassed(opcode)) 3492 { 3493 uint32_t n; 3494 uint32_t registers = 0; 3495 bool wback; 3496 const uint32_t addr_byte_size = GetAddressByteSize(); 3497 switch (encoding) 3498 { 3499 case eEncodingT1: 3500 // n = UInt(Rn); registers = P:M:'0':register_list; wback = (W == '1'); 3501 n = Bits32 (opcode, 19, 16); 3502 registers = Bits32 (opcode, 15, 0); 3503 registers = registers & 0xdfff; // Make sure bit 13 is a zero. 3504 wback = BitIsSet (opcode, 21); 3505 3506 // if n == 15 || BitCount(registers) < 2 || (P == '1' && M == '1') then UNPREDICTABLE; 3507 if ((n == 15) 3508 || (BitCount (registers) < 2) 3509 || (BitIsSet (opcode, 14) && BitIsSet (opcode, 15))) 3510 return false; 3511 3512 // if registers<15> == '1' && InITBlock() && !LastInITBlock() then UNPREDICTABLE; 3513 if (BitIsSet (registers, 15) && InITBlock() && !LastInITBlock()) 3514 return false; 3515 3516 // if wback && registers<n> == '1' then UNPREDICTABLE; 3517 if (wback && BitIsSet (registers, n)) 3518 return false; 3519 3520 break; 3521 3522 case eEncodingA1: 3523 // n = UInt(Rn); registers = register_list; wback = (W == '1'); 3524 n = Bits32 (opcode, 19, 16); 3525 registers = Bits32 (opcode, 15, 0); 3526 wback = BitIsSet (opcode, 21); 3527 3528 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE; 3529 if ((n == 15) || (BitCount (registers) < 1)) 3530 return false; 3531 3532 break; 3533 3534 default: 3535 return false; 3536 } 3537 3538 // address = R[n] - 4*BitCount(registers); 3539 3540 int32_t offset = 0; 3541 addr_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success); 3542 3543 if (!success) 3544 return false; 3545 3546 addr_t address = Rn - (addr_byte_size * BitCount (registers)); 3547 EmulateInstruction::Context context; 3548 context.type = EmulateInstruction::eContextRegisterPlusOffset; 3549 Register dwarf_reg; 3550 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n); 3551 context.SetRegisterPlusOffset (dwarf_reg, Rn - address); 3552 3553 for (int i = 0; i < 14; ++i) 3554 { 3555 if (BitIsSet (registers, i)) 3556 { 3557 // R[i] = MemA[address,4]; address = address + 4; 3558 context.SetRegisterPlusOffset (dwarf_reg, Rn - (address + offset)); 3559 uint32_t data = MemARead (context, address + offset, addr_byte_size, 0, &success); 3560 if (!success) 3561 return false; 3562 3563 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + i, data)) 3564 return false; 3565 3566 offset += addr_byte_size; 3567 } 3568 } 3569 3570 // if registers<15> == '1' then 3571 // LoadWritePC(MemA[address,4]); 3572 if (BitIsSet (registers, 15)) 3573 { 3574 context.SetRegisterPlusOffset (dwarf_reg, offset); 3575 uint32_t data = MemARead (context, address + offset, addr_byte_size, 0, &success); 3576 if (!success) 3577 return false; 3578 // In ARMv5T and above, this is an interworking branch. 3579 if (!LoadWritePC(context, data)) 3580 return false; 3581 } 3582 3583 // if wback && registers<n> == '0' then R[n] = R[n] - 4*BitCount(registers); 3584 if (wback && BitIsClear (registers, n)) 3585 { 3586 if (!success) 3587 return false; 3588 3589 offset = (addr_byte_size * BitCount (registers)) * -1; 3590 context.type = EmulateInstruction::eContextAdjustBaseRegister; 3591 context.SetImmediateSigned (offset); 3592 addr_t addr = Rn + offset; 3593 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, addr)) 3594 return false; 3595 } 3596 3597 // if wback && registers<n> == '1' then R[n] = bits(32) UNKNOWN; // Only possible for encoding A1 3598 if (wback && BitIsSet (registers, n)) 3599 return WriteBits32Unknown (n); 3600 } 3601 return true; 3602} 3603 3604// LDMIB loads multiple registers from consecutive memory locations using an address from a base register. The 3605// consecutive memory locations start just above this address, and thea ddress of the last of those locations can 3606// optinoally be written back to the base register. 3607bool 3608EmulateInstructionARM::EmulateLDMIB (const uint32_t opcode, const ARMEncoding encoding) 3609{ 3610#if 0 3611 if ConditionPassed() then 3612 EncodingSpecificOperations(); 3613 address = R[n] + 4; 3614 3615 for i = 0 to 14 3616 if registers<i> == '1' then 3617 R[i] = MemA[address,4]; address = address + 4; 3618 if registers<15> == '1' then 3619 LoadWritePC(MemA[address,4]); 3620 3621 if wback && registers<n> == '0' then R[n] = R[n] + 4*BitCount(registers); 3622 if wback && registers<n> == '1' then R[n] = bits(32) UNKNOWN; 3623#endif 3624 3625 bool success = false; 3626 3627 if (ConditionPassed(opcode)) 3628 { 3629 uint32_t n; 3630 uint32_t registers = 0; 3631 bool wback; 3632 const uint32_t addr_byte_size = GetAddressByteSize(); 3633 switch (encoding) 3634 { 3635 case eEncodingA1: 3636 // n = UInt(Rn); registers = register_list; wback = (W == '1'); 3637 n = Bits32 (opcode, 19, 16); 3638 registers = Bits32 (opcode, 15, 0); 3639 wback = BitIsSet (opcode, 21); 3640 3641 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE; 3642 if ((n == 15) || (BitCount (registers) < 1)) 3643 return false; 3644 3645 break; 3646 default: 3647 return false; 3648 } 3649 // address = R[n] + 4; 3650 3651 int32_t offset = 0; 3652 addr_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success); 3653 3654 if (!success) 3655 return false; 3656 3657 addr_t address = Rn + addr_byte_size; 3658 3659 EmulateInstruction::Context context; 3660 context.type = EmulateInstruction::eContextRegisterPlusOffset; 3661 Register dwarf_reg; 3662 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n); 3663 context.SetRegisterPlusOffset (dwarf_reg, offset); 3664 3665 for (int i = 0; i < 14; ++i) 3666 { 3667 if (BitIsSet (registers, i)) 3668 { 3669 // R[i] = MemA[address,4]; address = address + 4; 3670 3671 context.SetRegisterPlusOffset (dwarf_reg, offset + addr_byte_size); 3672 uint32_t data = MemARead (context, address + offset, addr_byte_size, 0, &success); 3673 if (!success) 3674 return false; 3675 3676 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + i, data)) 3677 return false; 3678 3679 offset += addr_byte_size; 3680 } 3681 } 3682 3683 // if registers<15> == '1' then 3684 // LoadWritePC(MemA[address,4]); 3685 if (BitIsSet (registers, 15)) 3686 { 3687 context.SetRegisterPlusOffset (dwarf_reg, offset); 3688 uint32_t data = MemARead (context, address + offset, addr_byte_size, 0, &success); 3689 if (!success) 3690 return false; 3691 // In ARMv5T and above, this is an interworking branch. 3692 if (!LoadWritePC(context, data)) 3693 return false; 3694 } 3695 3696 // if wback && registers<n> == '0' then R[n] = R[n] + 4*BitCount(registers); 3697 if (wback && BitIsClear (registers, n)) 3698 { 3699 if (!success) 3700 return false; 3701 3702 offset = addr_byte_size * BitCount (registers); 3703 context.type = EmulateInstruction::eContextAdjustBaseRegister; 3704 context.SetImmediateSigned (offset); 3705 addr_t addr = Rn + offset; 3706 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, addr)) 3707 return false; 3708 } 3709 3710 // if wback && registers<n> == '1' then R[n] = bits(32) UNKNOWN; // Only possible for encoding A1 3711 if (wback && BitIsSet (registers, n)) 3712 return WriteBits32Unknown (n); 3713 } 3714 return true; 3715} 3716 3717// Load Register (immediate) calculates an address from a base register value and 3718// an immediate offset, loads a word from memory, and writes to a register. 3719// LDR (immediate, Thumb) 3720bool 3721EmulateInstructionARM::EmulateLDRRtRnImm (const uint32_t opcode, const ARMEncoding encoding) 3722{ 3723#if 0 3724 // ARM pseudo code... 3725 if (ConditionPassed()) 3726 { 3727 EncodingSpecificOperations(); NullCheckIfThumbEE(15); 3728 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32); 3729 address = if index then offset_addr else R[n]; 3730 data = MemU[address,4]; 3731 if wback then R[n] = offset_addr; 3732 if t == 15 then 3733 if address<1:0> == '00' then LoadWritePC(data); else UNPREDICTABLE; 3734 elsif UnalignedSupport() || address<1:0> = '00' then 3735 R[t] = data; 3736 else R[t] = bits(32) UNKNOWN; // Can only apply before ARMv7 3737 } 3738#endif 3739 3740 bool success = false; 3741 3742 if (ConditionPassed(opcode)) 3743 { 3744 uint32_t Rt; // the destination register 3745 uint32_t Rn; // the base register 3746 uint32_t imm32; // the immediate offset used to form the address 3747 addr_t offset_addr; // the offset address 3748 addr_t address; // the calculated address 3749 uint32_t data; // the literal data value from memory load 3750 bool add, index, wback; 3751 switch (encoding) { 3752 case eEncodingT1: 3753 Rt = Bits32(opcode, 5, 3); 3754 Rn = Bits32(opcode, 2, 0); 3755 imm32 = Bits32(opcode, 10, 6) << 2; // imm32 = ZeroExtend(imm5:'00', 32); 3756 // index = TRUE; add = TRUE; wback = FALSE 3757 add = true; 3758 index = true; 3759 wback = false; 3760 3761 break; 3762 3763 case eEncodingT2: 3764 // t = UInt(Rt); n = 13; imm32 = ZeroExtend(imm8:'00', 32); 3765 Rt = Bits32 (opcode, 10, 8); 3766 Rn = 13; 3767 imm32 = Bits32 (opcode, 7, 0) << 2; 3768 3769 // index = TRUE; add = TRUE; wback = FALSE; 3770 index = true; 3771 add = true; 3772 wback = false; 3773 3774 break; 3775 3776 case eEncodingT3: 3777 // if Rn == '1111' then SEE LDR (literal); 3778 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32); 3779 Rt = Bits32 (opcode, 15, 12); 3780 Rn = Bits32 (opcode, 19, 16); 3781 imm32 = Bits32 (opcode, 11, 0); 3782 3783 // index = TRUE; add = TRUE; wback = FALSE; 3784 index = true; 3785 add = true; 3786 wback = false; 3787 3788 // if t == 15 && InITBlock() && !LastInITBlock() then UNPREDICTABLE; 3789 if ((Rt == 15) && InITBlock() && !LastInITBlock()) 3790 return false; 3791 3792 break; 3793 3794 case eEncodingT4: 3795 // if Rn == '1111' then SEE LDR (literal); 3796 // if P == '1' && U == '1' && W == '0' then SEE LDRT; 3797 // if Rn == '1101' && P == '0' && U == '1' && W == '1' && imm8 == '00000100' then SEE POP; 3798 // if P == '0' && W == '0' then UNDEFINED; 3799 if (BitIsClear (opcode, 10) && BitIsClear (opcode, 8)) 3800 return false; 3801 3802 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32); 3803 Rt = Bits32 (opcode, 15, 12); 3804 Rn = Bits32 (opcode, 19, 16); 3805 imm32 = Bits32 (opcode, 7, 0); 3806 3807 // index = (P == '1'); add = (U == '1'); wback = (W == '1'); 3808 index = BitIsSet (opcode, 10); 3809 add = BitIsSet (opcode, 9); 3810 wback = BitIsSet (opcode, 8); 3811 3812 // if (wback && n == t) || (t == 15 && InITBlock() && !LastInITBlock()) then UNPREDICTABLE; 3813 if ((wback && (Rn == Rt)) || ((Rt == 15) && InITBlock() && !LastInITBlock())) 3814 return false; 3815 3816 break; 3817 3818 default: 3819 return false; 3820 } 3821 uint32_t base = ReadCoreReg (Rn, &success); 3822 if (!success) 3823 return false; 3824 if (add) 3825 offset_addr = base + imm32; 3826 else 3827 offset_addr = base - imm32; 3828 3829 address = (index ? offset_addr : base); 3830 3831 Register base_reg; 3832 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + Rn); 3833 if (wback) 3834 { 3835 EmulateInstruction::Context ctx; 3836 ctx.type = EmulateInstruction::eContextAdjustBaseRegister; 3837 ctx.SetRegisterPlusOffset (base_reg, (int32_t) (offset_addr - base)); 3838 3839 if (!WriteRegisterUnsigned (ctx, eRegisterKindDWARF, dwarf_r0 + Rn, offset_addr)) 3840 return false; 3841 } 3842 3843 // Prepare to write to the Rt register. 3844 EmulateInstruction::Context context; 3845 context.type = EmulateInstruction::eContextRegisterLoad; 3846 context.SetRegisterPlusOffset (base_reg, (int32_t) (offset_addr - base)); 3847 3848 // Read memory from the address. 3849 data = MemURead(context, address, 4, 0, &success); 3850 if (!success) 3851 return false; 3852 3853 if (Rt == 15) 3854 { 3855 if (Bits32(address, 1, 0) == 0) 3856 { 3857 if (!LoadWritePC(context, data)) 3858 return false; 3859 } 3860 else 3861 return false; 3862 } 3863 else if (UnalignedSupport() || Bits32(address, 1, 0) == 0) 3864 { 3865 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + Rt, data)) 3866 return false; 3867 } 3868 else 3869 WriteBits32Unknown (Rt); 3870 } 3871 return true; 3872} 3873 3874// STM (Store Multiple Increment After) stores multiple registers to consecutive memory locations using an address 3875// from a base register. The consecutive memory locations start at this address, and teh address just above the last 3876// of those locations can optionally be written back to the base register. 3877bool 3878EmulateInstructionARM::EmulateSTM (const uint32_t opcode, const ARMEncoding encoding) 3879{ 3880#if 0 3881 if ConditionPassed() then 3882 EncodingSpecificOperations(); NullCheckIfThumbEE(n); 3883 address = R[n]; 3884 3885 for i = 0 to 14 3886 if registers<i> == '1' then 3887 if i == n && wback && i != LowestSetBit(registers) then 3888 MemA[address,4] = bits(32) UNKNOWN; // Only possible for encodings T1 and A1 3889 else 3890 MemA[address,4] = R[i]; 3891 address = address + 4; 3892 3893 if registers<15> == '1' then // Only possible for encoding A1 3894 MemA[address,4] = PCStoreValue(); 3895 if wback then R[n] = R[n] + 4*BitCount(registers); 3896#endif 3897 3898 bool success = false; 3899 3900 if (ConditionPassed(opcode)) 3901 { 3902 uint32_t n; 3903 uint32_t registers = 0; 3904 bool wback; 3905 const uint32_t addr_byte_size = GetAddressByteSize(); 3906 3907 // EncodingSpecificOperations(); NullCheckIfThumbEE(n); 3908 switch (encoding) 3909 { 3910 case eEncodingT1: 3911 // n = UInt(Rn); registers = '00000000':register_list; wback = TRUE; 3912 n = Bits32 (opcode, 10, 8); 3913 registers = Bits32 (opcode, 7, 0); 3914 registers = registers & 0x00ff; // Make sure the top 8 bits are zeros. 3915 wback = true; 3916 3917 // if BitCount(registers) < 1 then UNPREDICTABLE; 3918 if (BitCount (registers) < 1) 3919 return false; 3920 3921 break; 3922 3923 case eEncodingT2: 3924 // n = UInt(Rn); registers = '0':M:'0':register_list; wback = (W == '1'); 3925 n = Bits32 (opcode, 19, 16); 3926 registers = Bits32 (opcode, 15, 0); 3927 registers = registers & 0x5fff; // Make sure bits 15 & 13 are zeros. 3928 wback = BitIsSet (opcode, 21); 3929 3930 // if n == 15 || BitCount(registers) < 2 then UNPREDICTABLE; 3931 if ((n == 15) || (BitCount (registers) < 2)) 3932 return false; 3933 3934 // if wback && registers<n> == '1' then UNPREDICTABLE; 3935 if (wback && BitIsSet (registers, n)) 3936 return false; 3937 3938 break; 3939 3940 case eEncodingA1: 3941 // n = UInt(Rn); registers = register_list; wback = (W == '1'); 3942 n = Bits32 (opcode, 19, 16); 3943 registers = Bits32 (opcode, 15, 0); 3944 wback = BitIsSet (opcode, 21); 3945 3946 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE; 3947 if ((n == 15) || (BitCount (registers) < 1)) 3948 return false; 3949 3950 break; 3951 3952 default: 3953 return false; 3954 } 3955 3956 // address = R[n]; 3957 int32_t offset = 0; 3958 const addr_t address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success); 3959 if (!success) 3960 return false; 3961 3962 EmulateInstruction::Context context; 3963 context.type = EmulateInstruction::eContextRegisterStore; 3964 Register base_reg; 3965 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n); 3966 3967 // for i = 0 to 14 3968 int lowest_set_bit = 14; 3969 for (int i = 0; i < 14; ++i) 3970 { 3971 // if registers<i> == '1' then 3972 if (BitIsSet (registers, i)) 3973 { 3974 if (i < lowest_set_bit) 3975 lowest_set_bit = i; 3976 // if i == n && wback && i != LowestSetBit(registers) then 3977 if ((i == n) && wback && (i != lowest_set_bit)) 3978 // MemA[address,4] = bits(32) UNKNOWN; // Only possible for encodings T1 and A1 3979 WriteBits32UnknownToMemory (address + offset); 3980 else 3981 { 3982 // MemA[address,4] = R[i]; 3983 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + i, 0, &success); 3984 if (!success) 3985 return false; 3986 3987 Register data_reg; 3988 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + i); 3989 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, offset); 3990 if (!MemAWrite (context, address + offset, data, addr_byte_size)) 3991 return false; 3992 } 3993 3994 // address = address + 4; 3995 offset += addr_byte_size; 3996 } 3997 } 3998 3999 // if registers<15> == '1' then // Only possible for encoding A1 4000 // MemA[address,4] = PCStoreValue(); 4001 if (BitIsSet (registers, 15)) 4002 { 4003 Register pc_reg; 4004 pc_reg.SetRegister (eRegisterKindDWARF, dwarf_pc); 4005 context.SetRegisterPlusOffset (pc_reg, 8); 4006 const uint32_t pc = ReadCoreReg (PC_REG, &success); 4007 if (!success) 4008 return false; 4009 4010 if (!MemAWrite (context, address + offset, pc, addr_byte_size)) 4011 return false; 4012 } 4013 4014 // if wback then R[n] = R[n] + 4*BitCount(registers); 4015 if (wback) 4016 { 4017 offset = addr_byte_size * BitCount (registers); 4018 context.type = EmulateInstruction::eContextAdjustBaseRegister; 4019 context.SetImmediateSigned (offset); 4020 addr_t data = address + offset; 4021 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, data)) 4022 return false; 4023 } 4024 } 4025 return true; 4026} 4027 4028// STMDA (Store Multiple Decrement After) stores multiple registers to consecutive memory locations using an address 4029// from a base register. The consecutive memory locations end at this address, and the address just below the lowest 4030// of those locations can optionally be written back to the base register. 4031bool 4032EmulateInstructionARM::EmulateSTMDA (const uint32_t opcode, const ARMEncoding encoding) 4033{ 4034#if 0 4035 if ConditionPassed() then 4036 EncodingSpecificOperations(); 4037 address = R[n] - 4*BitCount(registers) + 4; 4038 4039 for i = 0 to 14 4040 if registers<i> == '1' then 4041 if i == n && wback && i != LowestSetBit(registers) then 4042 MemA[address,4] = bits(32) UNKNOWN; 4043 else 4044 MemA[address,4] = R[i]; 4045 address = address + 4; 4046 4047 if registers<15> == '1' then 4048 MemA[address,4] = PCStoreValue(); 4049 4050 if wback then R[n] = R[n] - 4*BitCount(registers); 4051#endif 4052 4053 bool success = false; 4054 4055 if (ConditionPassed(opcode)) 4056 { 4057 uint32_t n; 4058 uint32_t registers = 0; 4059 bool wback; 4060 const uint32_t addr_byte_size = GetAddressByteSize(); 4061 4062 // EncodingSpecificOperations(); 4063 switch (encoding) 4064 { 4065 case eEncodingA1: 4066 // n = UInt(Rn); registers = register_list; wback = (W == '1'); 4067 n = Bits32 (opcode, 19, 16); 4068 registers = Bits32 (opcode, 15, 0); 4069 wback = BitIsSet (opcode, 21); 4070 4071 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE; 4072 if ((n == 15) || (BitCount (registers) < 1)) 4073 return false; 4074 break; 4075 default: 4076 return false; 4077 } 4078 4079 // address = R[n] - 4*BitCount(registers) + 4; 4080 int32_t offset = 0; 4081 addr_t Rn = ReadCoreReg (n, &success); 4082 if (!success) 4083 return false; 4084 4085 addr_t address = Rn - (addr_byte_size * BitCount (registers)) + 4; 4086 4087 EmulateInstruction::Context context; 4088 context.type = EmulateInstruction::eContextRegisterStore; 4089 Register base_reg; 4090 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n); 4091 4092 // for i = 0 to 14 4093 int lowest_bit_set = 14; 4094 for (int i = 0; i < 14; ++i) 4095 { 4096 // if registers<i> == '1' then 4097 if (BitIsSet (registers, i)) 4098 { 4099 if (i < lowest_bit_set) 4100 lowest_bit_set = i; 4101 //if i == n && wback && i != LowestSetBit(registers) then 4102 if ((i == n) && wback && (i != lowest_bit_set)) 4103 // MemA[address,4] = bits(32) UNKNOWN; 4104 WriteBits32UnknownToMemory (address + offset); 4105 else 4106 { 4107 // MemA[address,4] = R[i]; 4108 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + i, 0, &success); 4109 if (!success) 4110 return false; 4111 4112 Register data_reg; 4113 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + i); 4114 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, Rn - (address + offset)); 4115 if (!MemAWrite (context, address + offset, data, addr_byte_size)) 4116 return false; 4117 } 4118 4119 // address = address + 4; 4120 offset += addr_byte_size; 4121 } 4122 } 4123 4124 // if registers<15> == '1' then 4125 // MemA[address,4] = PCStoreValue(); 4126 if (BitIsSet (registers, 15)) 4127 { 4128 Register pc_reg; 4129 pc_reg.SetRegister (eRegisterKindDWARF, dwarf_pc); 4130 context.SetRegisterPlusOffset (pc_reg, 8); 4131 const uint32_t pc = ReadCoreReg (PC_REG, &success); 4132 if (!success) 4133 return false; 4134 4135 if (!MemAWrite (context, address + offset, pc, addr_byte_size)) 4136 return false; 4137 } 4138 4139 // if wback then R[n] = R[n] - 4*BitCount(registers); 4140 if (wback) 4141 { 4142 offset = (addr_byte_size * BitCount (registers)) * -1; 4143 context.type = EmulateInstruction::eContextAdjustBaseRegister; 4144 context.SetImmediateSigned (offset); 4145 addr_t data = Rn + offset; 4146 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, data)) 4147 return false; 4148 } 4149 } 4150 return true; 4151} 4152 4153// STMDB (Store Multiple Decrement Before) stores multiple registers to consecutive memory locations using an address 4154// from a base register. The consecutive memory locations end just below this address, and the address of the first of 4155// those locations can optionally be written back to the base register. 4156bool 4157EmulateInstructionARM::EmulateSTMDB (const uint32_t opcode, const ARMEncoding encoding) 4158{ 4159#if 0 4160 if ConditionPassed() then 4161 EncodingSpecificOperations(); NullCheckIfThumbEE(n); 4162 address = R[n] - 4*BitCount(registers); 4163 4164 for i = 0 to 14 4165 if registers<i> == '1' then 4166 if i == n && wback && i != LowestSetBit(registers) then 4167 MemA[address,4] = bits(32) UNKNOWN; // Only possible for encoding A1 4168 else 4169 MemA[address,4] = R[i]; 4170 address = address + 4; 4171 4172 if registers<15> == '1' then // Only possible for encoding A1 4173 MemA[address,4] = PCStoreValue(); 4174 4175 if wback then R[n] = R[n] - 4*BitCount(registers); 4176#endif 4177 4178 4179 bool success = false; 4180 4181 if (ConditionPassed(opcode)) 4182 { 4183 uint32_t n; 4184 uint32_t registers = 0; 4185 bool wback; 4186 const uint32_t addr_byte_size = GetAddressByteSize(); 4187 4188 // EncodingSpecificOperations(); NullCheckIfThumbEE(n); 4189 switch (encoding) 4190 { 4191 case eEncodingT1: 4192 // if W == '1' && Rn == '1101' then SEE PUSH; 4193 if ((BitIsSet (opcode, 21)) && (Bits32 (opcode, 19, 16) == 13)) 4194 { 4195 // See PUSH 4196 } 4197 // n = UInt(Rn); registers = '0':M:'0':register_list; wback = (W == '1'); 4198 n = Bits32 (opcode, 19, 16); 4199 registers = Bits32 (opcode, 15, 0); 4200 registers = registers & 0x5fff; // Make sure bits 15 & 13 are zeros. 4201 wback = BitIsSet (opcode, 21); 4202 // if n == 15 || BitCount(registers) < 2 then UNPREDICTABLE; 4203 if ((n == 15) || BitCount (registers) < 2) 4204 return false; 4205 // if wback && registers<n> == '1' then UNPREDICTABLE; 4206 if (wback && BitIsSet (registers, n)) 4207 return false; 4208 break; 4209 4210 case eEncodingA1: 4211 // if W == '1' && Rn == '1101’ && BitCount(register_list) >= 2 then SEE PUSH; 4212 if (BitIsSet (opcode, 21) && (Bits32 (opcode, 19, 16) == 13) && BitCount (Bits32 (opcode, 15, 0)) >= 2) 4213 { 4214 // See Push 4215 } 4216 // n = UInt(Rn); registers = register_list; wback = (W == '1'); 4217 n = Bits32 (opcode, 19, 16); 4218 registers = Bits32 (opcode, 15, 0); 4219 wback = BitIsSet (opcode, 21); 4220 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE; 4221 if ((n == 15) || BitCount (registers) < 1) 4222 return false; 4223 break; 4224 4225 default: 4226 return false; 4227 } 4228 4229 // address = R[n] - 4*BitCount(registers); 4230 4231 int32_t offset = 0; 4232 addr_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success); 4233 if (!success) 4234 return false; 4235 4236 addr_t address = Rn - (addr_byte_size * BitCount (registers)); 4237 4238 EmulateInstruction::Context context; 4239 context.type = EmulateInstruction::eContextRegisterStore; 4240 Register base_reg; 4241 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n); 4242 4243 // for i = 0 to 14 4244 uint32_t lowest_set_bit = 14; 4245 for (int i = 0; i < 14; ++i) 4246 { 4247 // if registers<i> == '1' then 4248 if (BitIsSet (registers, i)) 4249 { 4250 if (i < lowest_set_bit) 4251 lowest_set_bit = i; 4252 // if i == n && wback && i != LowestSetBit(registers) then 4253 if ((i == n) && wback && (i != lowest_set_bit)) 4254 // MemA[address,4] = bits(32) UNKNOWN; // Only possible for encoding A1 4255 WriteBits32UnknownToMemory (address + offset); 4256 else 4257 { 4258 // MemA[address,4] = R[i]; 4259 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + i, 0, &success); 4260 if (!success) 4261 return false; 4262 4263 Register data_reg; 4264 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + i); 4265 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, Rn - (address + offset)); 4266 if (!MemAWrite (context, address + offset, data, addr_byte_size)) 4267 return false; 4268 } 4269 4270 // address = address + 4; 4271 offset += addr_byte_size; 4272 } 4273 } 4274 4275 // if registers<15> == '1' then // Only possible for encoding A1 4276 // MemA[address,4] = PCStoreValue(); 4277 if (BitIsSet (registers, 15)) 4278 { 4279 Register pc_reg; 4280 pc_reg.SetRegister (eRegisterKindDWARF, dwarf_pc); 4281 context.SetRegisterPlusOffset (pc_reg, 8); 4282 const uint32_t pc = ReadCoreReg (PC_REG, &success); 4283 if (!success) 4284 return false; 4285 4286 if (!MemAWrite (context, address + offset, pc, addr_byte_size)) 4287 return false; 4288 } 4289 4290 // if wback then R[n] = R[n] - 4*BitCount(registers); 4291 if (wback) 4292 { 4293 offset = (addr_byte_size * BitCount (registers)) * -1; 4294 context.type = EmulateInstruction::eContextAdjustBaseRegister; 4295 context.SetImmediateSigned (offset); 4296 addr_t data = Rn + offset; 4297 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, data)) 4298 return false; 4299 } 4300 } 4301 return true; 4302} 4303 4304// STMIB (Store Multiple Increment Before) stores multiple registers to consecutive memory locations using an address 4305// from a base register. The consecutive memory locations start just above this address, and the address of the last 4306// of those locations can optionally be written back to the base register. 4307bool 4308EmulateInstructionARM::EmulateSTMIB (const uint32_t opcode, const ARMEncoding encoding) 4309{ 4310#if 0 4311 if ConditionPassed() then 4312 EncodingSpecificOperations(); 4313 address = R[n] + 4; 4314 4315 for i = 0 to 14 4316 if registers<i> == '1' then 4317 if i == n && wback && i != LowestSetBit(registers) then 4318 MemA[address,4] = bits(32) UNKNOWN; 4319 else 4320 MemA[address,4] = R[i]; 4321 address = address + 4; 4322 4323 if registers<15> == '1' then 4324 MemA[address,4] = PCStoreValue(); 4325 4326 if wback then R[n] = R[n] + 4*BitCount(registers); 4327#endif 4328 4329 bool success = false; 4330 4331 if (ConditionPassed(opcode)) 4332 { 4333 uint32_t n; 4334 uint32_t registers = 0; 4335 bool wback; 4336 const uint32_t addr_byte_size = GetAddressByteSize(); 4337 4338 // EncodingSpecificOperations(); 4339 switch (encoding) 4340 { 4341 case eEncodingA1: 4342 // n = UInt(Rn); registers = register_list; wback = (W == '1'); 4343 n = Bits32 (opcode, 19, 16); 4344 registers = Bits32 (opcode, 15, 0); 4345 wback = BitIsSet (opcode, 21); 4346 4347 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE; 4348 if ((n == 15) && (BitCount (registers) < 1)) 4349 return false; 4350 break; 4351 default: 4352 return false; 4353 } 4354 // address = R[n] + 4; 4355 4356 int32_t offset = 0; 4357 addr_t Rn = ReadCoreReg (n, &success); 4358 if (!success) 4359 return false; 4360 4361 addr_t address = Rn + addr_byte_size; 4362 4363 EmulateInstruction::Context context; 4364 context.type = EmulateInstruction::eContextRegisterStore; 4365 Register base_reg; 4366 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n); 4367 4368 uint32_t lowest_set_bit = 14; 4369 // for i = 0 to 14 4370 for (int i = 0; i < 14; ++i) 4371 { 4372 // if registers<i> == '1' then 4373 if (BitIsSet (registers, i)) 4374 { 4375 if (i < lowest_set_bit) 4376 lowest_set_bit = i; 4377 // if i == n && wback && i != LowestSetBit(registers) then 4378 if ((i == n) && wback && (i != lowest_set_bit)) 4379 // MemA[address,4] = bits(32) UNKNOWN; 4380 WriteBits32UnknownToMemory (address + offset); 4381 // else 4382 else 4383 { 4384 // MemA[address,4] = R[i]; 4385 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + i, 0, &success); 4386 if (!success) 4387 return false; 4388 4389 Register data_reg; 4390 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + i); 4391 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, offset + addr_byte_size); 4392 if (!MemAWrite (context, address + offset, data, addr_byte_size)) 4393 return false; 4394 } 4395 4396 // address = address + 4; 4397 offset += addr_byte_size; 4398 } 4399 } 4400 4401 // if registers<15> == '1' then 4402 // MemA[address,4] = PCStoreValue(); 4403 if (BitIsSet (registers, 15)) 4404 { 4405 Register pc_reg; 4406 pc_reg.SetRegister (eRegisterKindDWARF, dwarf_pc); 4407 context.SetRegisterPlusOffset (pc_reg, 8); 4408 const uint32_t pc = ReadCoreReg (PC_REG, &success); 4409 if (!success) 4410 return false; 4411 4412 if (!MemAWrite (context, address + offset, pc, addr_byte_size)) 4413 return false; 4414 } 4415 4416 // if wback then R[n] = R[n] + 4*BitCount(registers); 4417 if (wback) 4418 { 4419 offset = addr_byte_size * BitCount (registers); 4420 context.type = EmulateInstruction::eContextAdjustBaseRegister; 4421 context.SetImmediateSigned (offset); 4422 addr_t data = Rn + offset; 4423 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, data)) 4424 return false; 4425 } 4426 } 4427 return true; 4428} 4429 4430// STR (store immediate) calcualtes an address from a base register value and an immediate offset, and stores a word 4431// from a register to memory. It can use offset, post-indexed, or pre-indexed addressing. 4432bool 4433EmulateInstructionARM::EmulateSTRThumb (const uint32_t opcode, const ARMEncoding encoding) 4434{ 4435#if 0 4436 if ConditionPassed() then 4437 EncodingSpecificOperations(); NullCheckIfThumbEE(n); 4438 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32); 4439 address = if index then offset_addr else R[n]; 4440 if UnalignedSupport() || address<1:0> == '00' then 4441 MemU[address,4] = R[t]; 4442 else // Can only occur before ARMv7 4443 MemU[address,4] = bits(32) UNKNOWN; 4444 if wback then R[n] = offset_addr; 4445#endif 4446 4447 bool success = false; 4448 4449 if (ConditionPassed(opcode)) 4450 { 4451 const uint32_t addr_byte_size = GetAddressByteSize(); 4452 4453 uint32_t t; 4454 uint32_t n; 4455 uint32_t imm32; 4456 bool index; 4457 bool add; 4458 bool wback; 4459 // EncodingSpecificOperations (); NullCheckIfThumbEE(n); 4460 switch (encoding) 4461 { 4462 case eEncodingT1: 4463 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm5:'00', 32); 4464 t = Bits32 (opcode, 2, 0); 4465 n = Bits32 (opcode, 5, 3); 4466 imm32 = Bits32 (opcode, 10, 6) << 2; 4467 4468 // index = TRUE; add = TRUE; wback = FALSE; 4469 index = true; 4470 add = false; 4471 wback = false; 4472 break; 4473 4474 case eEncodingT2: 4475 // t = UInt(Rt); n = 13; imm32 = ZeroExtend(imm8:'00', 32); 4476 t = Bits32 (opcode, 10, 8); 4477 n = 13; 4478 imm32 = Bits32 (opcode, 7, 0) << 2; 4479 4480 // index = TRUE; add = TRUE; wback = FALSE; 4481 index = true; 4482 add = true; 4483 wback = false; 4484 break; 4485 4486 case eEncodingT3: 4487 // if Rn == '1111' then UNDEFINED; 4488 if (Bits32 (opcode, 19, 16) == 15) 4489 return false; 4490 4491 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32); 4492 t = Bits32 (opcode, 15, 12); 4493 n = Bits32 (opcode, 19, 16); 4494 imm32 = Bits32 (opcode, 11, 0); 4495 4496 // index = TRUE; add = TRUE; wback = FALSE; 4497 index = true; 4498 add = true; 4499 wback = false; 4500 4501 // if t == 15 then UNPREDICTABLE; 4502 if (t == 15) 4503 return false; 4504 break; 4505 4506 case eEncodingT4: 4507 // if P == '1' && U == '1' && W == '0' then SEE STRT; 4508 // if Rn == '1101' && P == '1' && U == '0' && W == '1' && imm8 == '00000100' then SEE PUSH; 4509 // if Rn == '1111' || (P == '0' && W == '0') then UNDEFINED; 4510 if ((Bits32 (opcode, 19, 16) == 15) 4511 || (BitIsClear (opcode, 10) && BitIsClear (opcode, 8))) 4512 return false; 4513 4514 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32); 4515 t = Bits32 (opcode, 15, 12); 4516 n = Bits32 (opcode, 19, 16); 4517 imm32 = Bits32 (opcode, 7, 0); 4518 4519 // index = (P == '1'); add = (U == '1'); wback = (W == '1'); 4520 index = BitIsSet (opcode, 10); 4521 add = BitIsSet (opcode, 9); 4522 wback = BitIsSet (opcode, 8); 4523 4524 // if t == 15 || (wback && n == t) then UNPREDICTABLE; 4525 if ((t == 15) || (wback && (n == t))) 4526 return false; 4527 break; 4528 4529 default: 4530 return false; 4531 } 4532 4533 addr_t offset_addr; 4534 addr_t address; 4535 4536 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32); 4537 uint32_t base_address = ReadCoreReg (n, &success); 4538 if (!success) 4539 return false; 4540 4541 if (add) 4542 offset_addr = base_address + imm32; 4543 else 4544 offset_addr = base_address - imm32; 4545 4546 // address = if index then offset_addr else R[n]; 4547 if (index) 4548 address = offset_addr; 4549 else 4550 address = base_address; 4551 4552 EmulateInstruction::Context context; 4553 context.type = eContextRegisterStore; 4554 Register base_reg; 4555 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n); 4556 4557 // if UnalignedSupport() || address<1:0> == '00' then 4558 if (UnalignedSupport () || (BitIsClear (address, 1) && BitIsClear (address, 0))) 4559 { 4560 // MemU[address,4] = R[t]; 4561 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + t, 0, &success); 4562 if (!success) 4563 return false; 4564 4565 Register data_reg; 4566 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + t); 4567 int32_t offset = address - base_address; 4568 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, offset); 4569 if (!MemUWrite (context, address, data, addr_byte_size)) 4570 return false; 4571 } 4572 else 4573 { 4574 // MemU[address,4] = bits(32) UNKNOWN; 4575 WriteBits32UnknownToMemory (address); 4576 } 4577 4578 // if wback then R[n] = offset_addr; 4579 if (wback) 4580 { 4581 context.type = eContextRegisterLoad; 4582 context.SetAddress (offset_addr); 4583 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr)) 4584 return false; 4585 } 4586 } 4587 return true; 4588} 4589 4590// STR (Store Register) calculates an address from a base register value and an offset register value, stores a 4591// word from a register to memory. The offset register value can optionally be shifted. 4592bool 4593EmulateInstructionARM::EmulateSTRRegister (const uint32_t opcode, const ARMEncoding encoding) 4594{ 4595#if 0 4596 if ConditionPassed() then 4597 EncodingSpecificOperations(); NullCheckIfThumbEE(n); 4598 offset = Shift(R[m], shift_t, shift_n, APSR.C); 4599 offset_addr = if add then (R[n] + offset) else (R[n] - offset); 4600 address = if index then offset_addr else R[n]; 4601 if t == 15 then // Only possible for encoding A1 4602 data = PCStoreValue(); 4603 else 4604 data = R[t]; 4605 if UnalignedSupport() || address<1:0> == '00' || CurrentInstrSet() == InstrSet_ARM then 4606 MemU[address,4] = data; 4607 else // Can only occur before ARMv7 4608 MemU[address,4] = bits(32) UNKNOWN; 4609 if wback then R[n] = offset_addr; 4610#endif 4611 4612 bool success = false; 4613 4614 if (ConditionPassed(opcode)) 4615 { 4616 const uint32_t addr_byte_size = GetAddressByteSize(); 4617 4618 uint32_t t; 4619 uint32_t n; 4620 uint32_t m; 4621 ARM_ShifterType shift_t; 4622 uint32_t shift_n; 4623 bool index; 4624 bool add; 4625 bool wback; 4626 4627 // EncodingSpecificOperations (); NullCheckIfThumbEE(n); 4628 switch (encoding) 4629 { 4630 case eEncodingT1: 4631 // if CurrentInstrSet() == InstrSet_ThumbEE then SEE "Modified operation in ThumbEE"; 4632 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm); 4633 t = Bits32 (opcode, 2, 0); 4634 n = Bits32 (opcode, 5, 3); 4635 m = Bits32 (opcode, 8, 6); 4636 4637 // index = TRUE; add = TRUE; wback = FALSE; 4638 index = true; 4639 add = true; 4640 wback = false; 4641 4642 // (shift_t, shift_n) = (SRType_LSL, 0); 4643 shift_t = SRType_LSL; 4644 shift_n = 0; 4645 break; 4646 4647 case eEncodingT2: 4648 // if Rn == '1111' then UNDEFINED; 4649 if (Bits32 (opcode, 19, 16) == 15) 4650 return false; 4651 4652 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm); 4653 t = Bits32 (opcode, 15, 12); 4654 n = Bits32 (opcode, 19, 16); 4655 m = Bits32 (opcode, 3, 0); 4656 4657 // index = TRUE; add = TRUE; wback = FALSE; 4658 index = true; 4659 add = true; 4660 wback = false; 4661 4662 // (shift_t, shift_n) = (SRType_LSL, UInt(imm2)); 4663 shift_t = SRType_LSL; 4664 shift_n = Bits32 (opcode, 5, 4); 4665 4666 // if t == 15 || BadReg(m) then UNPREDICTABLE; 4667 if ((t == 15) || (BadReg (m))) 4668 return false; 4669 break; 4670 4671 case eEncodingA1: 4672 { 4673 // if P == '0' && W == '1' then SEE STRT; 4674 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm); 4675 t = Bits32 (opcode, 15, 12); 4676 n = Bits32 (opcode, 19, 16); 4677 m = Bits32 (opcode, 3, 0); 4678 4679 // index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1'); 4680 index = BitIsSet (opcode, 24); 4681 add = BitIsSet (opcode, 23); 4682 wback = (BitIsClear (opcode, 24) || BitIsSet (opcode, 21)); 4683 4684 // (shift_t, shift_n) = DecodeImmShift(type, imm5); 4685 uint32_t typ = Bits32 (opcode, 6, 5); 4686 uint32_t imm5 = Bits32 (opcode, 11, 7); 4687 shift_n = DecodeImmShift(typ, imm5, shift_t); 4688 4689 // if m == 15 then UNPREDICTABLE; 4690 if (m == 15) 4691 return false; 4692 4693 // if wback && (n == 15 || n == t) then UNPREDICTABLE; 4694 if (wback && ((n == 15) || (n == t))) 4695 return false; 4696 4697 break; 4698 } 4699 default: 4700 return false; 4701 } 4702 4703 addr_t offset_addr; 4704 addr_t address; 4705 int32_t offset = 0; 4706 4707 addr_t base_address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success); 4708 if (!success) 4709 return false; 4710 4711 uint32_t Rm_data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success); 4712 if (!success) 4713 return false; 4714 4715 // offset = Shift(R[m], shift_t, shift_n, APSR.C); 4716 offset = Shift (Rm_data, shift_t, shift_n, APSR_C); 4717 4718 // offset_addr = if add then (R[n] + offset) else (R[n] - offset); 4719 if (add) 4720 offset_addr = base_address + offset; 4721 else 4722 offset_addr = base_address - offset; 4723 4724 // address = if index then offset_addr else R[n]; 4725 if (index) 4726 address = offset_addr; 4727 else 4728 address = base_address; 4729 4730 uint32_t data; 4731 // if t == 15 then // Only possible for encoding A1 4732 if (t == 15) 4733 // data = PCStoreValue(); 4734 data = ReadCoreReg (PC_REG, &success); 4735 else 4736 // data = R[t]; 4737 data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + t, 0, &success); 4738 4739 if (!success) 4740 return false; 4741 4742 EmulateInstruction::Context context; 4743 context.type = eContextRegisterStore; 4744 4745 // if UnalignedSupport() || address<1:0> == '00' || CurrentInstrSet() == InstrSet_ARM then 4746 if (UnalignedSupport () 4747 || (BitIsClear (address, 1) && BitIsClear (address, 0)) 4748 || CurrentInstrSet() == eModeARM) 4749 { 4750 // MemU[address,4] = data; 4751 4752 Register base_reg; 4753 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n); 4754 4755 Register data_reg; 4756 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + t); 4757 4758 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, address - base_address); 4759 if (!MemUWrite (context, address, data, addr_byte_size)) 4760 return false; 4761 4762 } 4763 else 4764 // MemU[address,4] = bits(32) UNKNOWN; 4765 WriteBits32UnknownToMemory (address); 4766 4767 // if wback then R[n] = offset_addr; 4768 if (wback) 4769 { 4770 context.type = eContextRegisterLoad; 4771 context.SetAddress (offset_addr); 4772 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr)) 4773 return false; 4774 } 4775 4776 } 4777 return true; 4778} 4779 4780bool 4781EmulateInstructionARM::EmulateSTRBThumb (const uint32_t opcode, const ARMEncoding encoding) 4782{ 4783#if 0 4784 if ConditionPassed() then 4785 EncodingSpecificOperations(); NullCheckIfThumbEE(n); 4786 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32); 4787 address = if index then offset_addr else R[n]; 4788 MemU[address,1] = R[t]<7:0>; 4789 if wback then R[n] = offset_addr; 4790#endif 4791 4792 4793 bool success = false; 4794 4795 if (ConditionPassed(opcode)) 4796 { 4797 uint32_t t; 4798 uint32_t n; 4799 uint32_t imm32; 4800 bool index; 4801 bool add; 4802 bool wback; 4803 // EncodingSpecificOperations(); NullCheckIfThumbEE(n); 4804 switch (encoding) 4805 { 4806 case eEncodingT1: 4807 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm5, 32); 4808 t = Bits32 (opcode, 2, 0); 4809 n = Bits32 (opcode, 5, 3); 4810 imm32 = Bits32 (opcode, 10, 6); 4811 4812 // index = TRUE; add = TRUE; wback = FALSE; 4813 index = true; 4814 add = true; 4815 wback = false; 4816 break; 4817 4818 case eEncodingT2: 4819 // if Rn == '1111' then UNDEFINED; 4820 if (Bits32 (opcode, 19, 16) == 15) 4821 return false; 4822 4823 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32); 4824 t = Bits32 (opcode, 15, 12); 4825 n = Bits32 (opcode, 19, 16); 4826 imm32 = Bits32 (opcode, 11, 0); 4827 4828 // index = TRUE; add = TRUE; wback = FALSE; 4829 index = true; 4830 add = true; 4831 wback = false; 4832 4833 // if BadReg(t) then UNPREDICTABLE; 4834 if (BadReg (t)) 4835 return false; 4836 break; 4837 4838 case eEncodingT3: 4839 // if P == '1' && U == '1' && W == '0' then SEE STRBT; 4840 // if Rn == '1111' || (P == '0' && W == '0') then UNDEFINED; 4841 if (Bits32 (opcode, 19, 16) == 15) 4842 return false; 4843 4844 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32); 4845 t = Bits32 (opcode, 15, 12); 4846 n = Bits32 (opcode, 19, 16); 4847 imm32 = Bits32 (opcode, 7, 0); 4848 4849 // index = (P == '1'); add = (U == '1'); wback = (W == '1'); 4850 index = BitIsSet (opcode, 10); 4851 add = BitIsSet (opcode, 9); 4852 wback = BitIsSet (opcode, 8); 4853 4854 // if BadReg(t) || (wback && n == t) then UNPREDICTABLE 4855 if ((BadReg (t)) || (wback && (n == t))) 4856 return false; 4857 break; 4858 4859 default: 4860 return false; 4861 } 4862 4863 addr_t offset_addr; 4864 addr_t address; 4865 addr_t base_address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success); 4866 if (!success) 4867 return false; 4868 4869 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32); 4870 if (add) 4871 offset_addr = base_address + imm32; 4872 else 4873 offset_addr = base_address - imm32; 4874 4875 // address = if index then offset_addr else R[n]; 4876 if (index) 4877 address = offset_addr; 4878 else 4879 address = base_address; 4880 4881 // MemU[address,1] = R[t]<7:0> 4882 Register base_reg; 4883 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n); 4884 4885 Register data_reg; 4886 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + t); 4887 4888 EmulateInstruction::Context context; 4889 context.type = eContextRegisterStore; 4890 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, address - base_address); 4891 4892 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + t, 0, &success); 4893 if (!success) 4894 return false; 4895 4896 data = Bits32 (data, 7, 0); 4897 4898 if (!MemUWrite (context, address, data, 1)) 4899 return false; 4900 4901 // if wback then R[n] = offset_addr; 4902 if (wback) 4903 { 4904 context.type = eContextRegisterLoad; 4905 context.SetAddress (offset_addr); 4906 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr)) 4907 return false; 4908 } 4909 4910 } 4911 4912 return true; 4913} 4914 4915// STRH (register) calculates an address from a base register value and an offset register value, and stores a 4916// halfword from a register to memory. The offset register alue can be shifted left by 0, 1, 2, or 3 bits. 4917bool 4918EmulateInstructionARM::EmulateSTRHRegister (const uint32_t opcode, const ARMEncoding encoding) 4919{ 4920#if 0 4921 if ConditionPassed() then 4922 EncodingSpecificOperations(); NullCheckIfThumbEE(n); 4923 offset = Shift(R[m], shift_t, shift_n, APSR.C); 4924 offset_addr = if add then (R[n] + offset) else (R[n] - offset); 4925 address = if index then offset_addr else R[n]; 4926 if UnalignedSupport() || address<0> == '0' then 4927 MemU[address,2] = R[t]<15:0>; 4928 else // Can only occur before ARMv7 4929 MemU[address,2] = bits(16) UNKNOWN; 4930 if wback then R[n] = offset_addr; 4931#endif 4932 4933 bool success = false; 4934 4935 if (ConditionPassed(opcode)) 4936 { 4937 uint32_t t; 4938 uint32_t n; 4939 uint32_t m; 4940 bool index; 4941 bool add; 4942 bool wback; 4943 ARM_ShifterType shift_t; 4944 uint32_t shift_n; 4945 4946 // EncodingSpecificOperations(); NullCheckIfThumbEE(n); 4947 switch (encoding) 4948 { 4949 case eEncodingT1: 4950 // if CurrentInstrSet() == InstrSet_ThumbEE then SEE "Modified operation in ThumbEE"; 4951 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm); 4952 t = Bits32 (opcode, 2, 0); 4953 n = Bits32 (opcode, 5, 3); 4954 m = Bits32 (opcode, 8, 6); 4955 4956 // index = TRUE; add = TRUE; wback = FALSE; 4957 index = true; 4958 add = true; 4959 wback = false; 4960 4961 // (shift_t, shift_n) = (SRType_LSL, 0); 4962 shift_t = SRType_LSL; 4963 shift_n = 0; 4964 4965 break; 4966 4967 case eEncodingT2: 4968 // if Rn == '1111' then UNDEFINED; 4969 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm); 4970 t = Bits32 (opcode, 15, 12); 4971 n = Bits32 (opcode, 19, 16); 4972 m = Bits32 (opcode, 3, 0); 4973 if (n == 15) 4974 return false; 4975 4976 // index = TRUE; add = TRUE; wback = FALSE; 4977 index = true; 4978 add = true; 4979 wback = false; 4980 4981 // (shift_t, shift_n) = (SRType_LSL, UInt(imm2)); 4982 shift_t = SRType_LSL; 4983 shift_n = Bits32 (opcode, 5, 4); 4984 4985 // if BadReg(t) || BadReg(m) then UNPREDICTABLE; 4986 if (BadReg (t) || BadReg (m)) 4987 return false; 4988 4989 break; 4990 4991 case eEncodingA1: 4992 // if P == '0' && W == '1' then SEE STRHT; 4993 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm); 4994 t = Bits32 (opcode, 15, 12); 4995 n = Bits32 (opcode, 19, 16); 4996 m = Bits32 (opcode, 3, 0); 4997 4998 // index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1'); 4999 index = BitIsSet (opcode, 24); 5000 add = BitIsSet (opcode, 23); 5001 wback = (BitIsClear (opcode, 24) || BitIsSet (opcode, 21)); 5002 5003 // (shift_t, shift_n) = (SRType_LSL, 0); 5004 shift_t = SRType_LSL; 5005 shift_n = 0; 5006 5007 // if t == 15 || m == 15 then UNPREDICTABLE; 5008 if ((t == 15) || (m == 15)) 5009 return false; 5010 5011 // if wback && (n == 15 || n == t) then UNPREDICTABLE; 5012 if (wback && ((n == 15) || (n == t))) 5013 return false; 5014 5015 break; 5016 5017 default: 5018 return false; 5019 } 5020 5021 uint32_t Rm = ReadCoreReg (m, &success); 5022 if (!success) 5023 return false; 5024 5025 uint32_t Rn = ReadCoreReg (n, &success); 5026 if (!success) 5027 return false; 5028 5029 // offset = Shift(R[m], shift_t, shift_n, APSR.C); 5030 uint32_t offset = Shift (Rm, shift_t, shift_n, APSR_C); 5031 5032 // offset_addr = if add then (R[n] + offset) else (R[n] - offset); 5033 addr_t offset_addr; 5034 if (add) 5035 offset_addr = Rn + offset; 5036 else 5037 offset_addr = Rn - offset; 5038 5039 // address = if index then offset_addr else R[n]; 5040 addr_t address; 5041 if (index) 5042 address = offset_addr; 5043 else 5044 address = Rn; 5045 5046 EmulateInstruction::Context context; 5047 context.type = eContextRegisterStore; 5048 Register base_reg; 5049 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n); 5050 Register offset_reg; 5051 offset_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + m); 5052 5053 // if UnalignedSupport() || address<0> == '0' then 5054 if (UnalignedSupport() || BitIsClear (address, 0)) 5055 { 5056 // MemU[address,2] = R[t]<15:0>; 5057 uint32_t Rt = ReadCoreReg (t, &success); 5058 if (!success) 5059 return false; 5060 5061 EmulateInstruction::Context context; 5062 context.type = eContextRegisterStore; 5063 Register base_reg; 5064 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n); 5065 Register offset_reg; 5066 offset_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + m); 5067 Register data_reg; 5068 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + t); 5069 context.SetRegisterToRegisterPlusIndirectOffset (base_reg, offset_reg, data_reg); 5070 5071 if (!MemUWrite (context, address, Bits32 (Rt, 15, 0), 2)) 5072 return false; 5073 } 5074 else // Can only occur before ARMv7 5075 { 5076 // MemU[address,2] = bits(16) UNKNOWN; 5077 } 5078 5079 // if wback then R[n] = offset_addr; 5080 if (wback) 5081 { 5082 context.type = eContextAdjustBaseRegister; 5083 context.SetAddress (offset_addr); 5084 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr)) 5085 return false; 5086 } 5087 } 5088 5089 return true; 5090} 5091 5092// Add with Carry (immediate) adds an immediate value and the carry flag value to a register value, 5093// and writes the result to the destination register. It can optionally update the condition flags 5094// based on the result. 5095bool 5096EmulateInstructionARM::EmulateADCImm (const uint32_t opcode, const ARMEncoding encoding) 5097{ 5098#if 0 5099 // ARM pseudo code... 5100 if ConditionPassed() then 5101 EncodingSpecificOperations(); 5102 (result, carry, overflow) = AddWithCarry(R[n], imm32, APSR.C); 5103 if d == 15 then // Can only occur for ARM encoding 5104 ALUWritePC(result); // setflags is always FALSE here 5105 else 5106 R[d] = result; 5107 if setflags then 5108 APSR.N = result<31>; 5109 APSR.Z = IsZeroBit(result); 5110 APSR.C = carry; 5111 APSR.V = overflow; 5112#endif 5113 5114 bool success = false; 5115 5116 if (ConditionPassed(opcode)) 5117 { 5118 uint32_t Rd, Rn; 5119 uint32_t imm32; // the immediate value to be added to the value obtained from Rn 5120 bool setflags; 5121 switch (encoding) 5122 { 5123 case eEncodingT1: 5124 Rd = Bits32(opcode, 11, 8); 5125 Rn = Bits32(opcode, 19, 16); 5126 setflags = BitIsSet(opcode, 20); 5127 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8) 5128 if (BadReg(Rd) || BadReg(Rn)) 5129 return false; 5130 break; 5131 case eEncodingA1: 5132 Rd = Bits32(opcode, 15, 12); 5133 Rn = Bits32(opcode, 19, 16); 5134 setflags = BitIsSet(opcode, 20); 5135 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12) 5136 5137 if (Rd == 15 && setflags) 5138 return EmulateSUBSPcLrEtc (opcode, encoding); 5139 break; 5140 default: 5141 return false; 5142 } 5143 5144 // Read the first operand. 5145 int32_t val1 = ReadCoreReg(Rn, &success); 5146 if (!success) 5147 return false; 5148 5149 AddWithCarryResult res = AddWithCarry(val1, imm32, APSR_C); 5150 5151 EmulateInstruction::Context context; 5152 context.type = EmulateInstruction::eContextImmediate; 5153 context.SetNoArgs (); 5154 5155 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow)) 5156 return false; 5157 } 5158 return true; 5159} 5160 5161// Add with Carry (register) adds a register value, the carry flag value, and an optionally-shifted 5162// register value, and writes the result to the destination register. It can optionally update the 5163// condition flags based on the result. 5164bool 5165EmulateInstructionARM::EmulateADCReg (const uint32_t opcode, const ARMEncoding encoding) 5166{ 5167#if 0 5168 // ARM pseudo code... 5169 if ConditionPassed() then 5170 EncodingSpecificOperations(); 5171 shifted = Shift(R[m], shift_t, shift_n, APSR.C); 5172 (result, carry, overflow) = AddWithCarry(R[n], shifted, APSR.C); 5173 if d == 15 then // Can only occur for ARM encoding 5174 ALUWritePC(result); // setflags is always FALSE here 5175 else 5176 R[d] = result; 5177 if setflags then 5178 APSR.N = result<31>; 5179 APSR.Z = IsZeroBit(result); 5180 APSR.C = carry; 5181 APSR.V = overflow; 5182#endif 5183 5184 bool success = false; 5185 5186 if (ConditionPassed(opcode)) 5187 { 5188 uint32_t Rd, Rn, Rm; 5189 ARM_ShifterType shift_t; 5190 uint32_t shift_n; // the shift applied to the value read from Rm 5191 bool setflags; 5192 switch (encoding) 5193 { 5194 case eEncodingT1: 5195 Rd = Rn = Bits32(opcode, 2, 0); 5196 Rm = Bits32(opcode, 5, 3); 5197 setflags = !InITBlock(); 5198 shift_t = SRType_LSL; 5199 shift_n = 0; 5200 break; 5201 case eEncodingT2: 5202 Rd = Bits32(opcode, 11, 8); 5203 Rn = Bits32(opcode, 19, 16); 5204 Rm = Bits32(opcode, 3, 0); 5205 setflags = BitIsSet(opcode, 20); 5206 shift_n = DecodeImmShiftThumb(opcode, shift_t); 5207 if (BadReg(Rd) || BadReg(Rn) || BadReg(Rm)) 5208 return false; 5209 break; 5210 case eEncodingA1: 5211 Rd = Bits32(opcode, 15, 12); 5212 Rn = Bits32(opcode, 19, 16); 5213 Rm = Bits32(opcode, 3, 0); 5214 setflags = BitIsSet(opcode, 20); 5215 shift_n = DecodeImmShiftARM(opcode, shift_t); 5216 5217 if (Rd == 15 && setflags) 5218 return EmulateSUBSPcLrEtc (opcode, encoding); 5219 break; 5220 default: 5221 return false; 5222 } 5223 5224 // Read the first operand. 5225 int32_t val1 = ReadCoreReg(Rn, &success); 5226 if (!success) 5227 return false; 5228 5229 // Read the second operand. 5230 int32_t val2 = ReadCoreReg(Rm, &success); 5231 if (!success) 5232 return false; 5233 5234 uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C); 5235 AddWithCarryResult res = AddWithCarry(val1, shifted, APSR_C); 5236 5237 EmulateInstruction::Context context; 5238 context.type = EmulateInstruction::eContextImmediate; 5239 context.SetNoArgs (); 5240 5241 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow)) 5242 return false; 5243 } 5244 return true; 5245} 5246 5247// This instruction adds an immediate value to the PC value to form a PC-relative address, 5248// and writes the result to the destination register. 5249bool 5250EmulateInstructionARM::EmulateADR (const uint32_t opcode, const ARMEncoding encoding) 5251{ 5252#if 0 5253 // ARM pseudo code... 5254 if ConditionPassed() then 5255 EncodingSpecificOperations(); 5256 result = if add then (Align(PC,4) + imm32) else (Align(PC,4) - imm32); 5257 if d == 15 then // Can only occur for ARM encodings 5258 ALUWritePC(result); 5259 else 5260 R[d] = result; 5261#endif 5262 5263 bool success = false; 5264 5265 if (ConditionPassed(opcode)) 5266 { 5267 uint32_t Rd; 5268 uint32_t imm32; // the immediate value to be added/subtracted to/from the PC 5269 bool add; 5270 switch (encoding) 5271 { 5272 case eEncodingT1: 5273 Rd = Bits32(opcode, 10, 8); 5274 imm32 = ThumbImm8Scaled(opcode); // imm32 = ZeroExtend(imm8:'00', 32) 5275 break; 5276 case eEncodingT2: 5277 case eEncodingT3: 5278 Rd = Bits32(opcode, 11, 8); 5279 imm32 = ThumbImm12(opcode); // imm32 = ZeroExtend(i:imm3:imm8, 32) 5280 add = (Bits32(opcode, 24, 21) == 0); // 0b0000 => ADD; 0b0101 => SUB 5281 if (BadReg(Rd)) 5282 return false; 5283 break; 5284 case eEncodingA1: 5285 case eEncodingA2: 5286 Rd = Bits32(opcode, 15, 12); 5287 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12) 5288 add = (Bits32(opcode, 24, 21) == 0x4); // 0b0100 => ADD; 0b0010 => SUB 5289 break; 5290 default: 5291 return false; 5292 } 5293 5294 // Read the PC value. 5295 uint32_t pc = ReadCoreReg(PC_REG, &success); 5296 if (!success) 5297 return false; 5298 5299 uint32_t result = (add ? Align(pc, 4) + imm32 : Align(pc, 4) - imm32); 5300 5301 EmulateInstruction::Context context; 5302 context.type = EmulateInstruction::eContextImmediate; 5303 context.SetNoArgs (); 5304 5305 if (!WriteCoreReg(context, result, Rd)) 5306 return false; 5307 } 5308 return true; 5309} 5310 5311// This instruction performs a bitwise AND of a register value and an immediate value, and writes the result 5312// to the destination register. It can optionally update the condition flags based on the result. 5313bool 5314EmulateInstructionARM::EmulateANDImm (const uint32_t opcode, const ARMEncoding encoding) 5315{ 5316#if 0 5317 // ARM pseudo code... 5318 if ConditionPassed() then 5319 EncodingSpecificOperations(); 5320 result = R[n] AND imm32; 5321 if d == 15 then // Can only occur for ARM encoding 5322 ALUWritePC(result); // setflags is always FALSE here 5323 else 5324 R[d] = result; 5325 if setflags then 5326 APSR.N = result<31>; 5327 APSR.Z = IsZeroBit(result); 5328 APSR.C = carry; 5329 // APSR.V unchanged 5330#endif 5331 5332 bool success = false; 5333 5334 if (ConditionPassed(opcode)) 5335 { 5336 uint32_t Rd, Rn; 5337 uint32_t imm32; // the immediate value to be ANDed to the value obtained from Rn 5338 bool setflags; 5339 uint32_t carry; // the carry bit after ARM/Thumb Expand operation 5340 switch (encoding) 5341 { 5342 case eEncodingT1: 5343 Rd = Bits32(opcode, 11, 8); 5344 Rn = Bits32(opcode, 19, 16); 5345 setflags = BitIsSet(opcode, 20); 5346 imm32 = ThumbExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C) 5347 // if Rd == '1111' && S == '1' then SEE TST (immediate); 5348 if (Rd == 15 && setflags) 5349 return EmulateTSTImm(opcode, eEncodingT1); 5350 if (Rd == 13 || (Rd == 15 && !setflags) || BadReg(Rn)) 5351 return false; 5352 break; 5353 case eEncodingA1: 5354 Rd = Bits32(opcode, 15, 12); 5355 Rn = Bits32(opcode, 19, 16); 5356 setflags = BitIsSet(opcode, 20); 5357 imm32 = ARMExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ARMExpandImm(imm12, APSR.C) 5358 5359 if (Rd == 15 && setflags) 5360 return EmulateSUBSPcLrEtc (opcode, encoding); 5361 break; 5362 default: 5363 return false; 5364 } 5365 5366 // Read the first operand. 5367 uint32_t val1 = ReadCoreReg(Rn, &success); 5368 if (!success) 5369 return false; 5370 5371 uint32_t result = val1 & imm32; 5372 5373 EmulateInstruction::Context context; 5374 context.type = EmulateInstruction::eContextImmediate; 5375 context.SetNoArgs (); 5376 5377 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry)) 5378 return false; 5379 } 5380 return true; 5381} 5382 5383// This instruction performs a bitwise AND of a register value and an optionally-shifted register value, 5384// and writes the result to the destination register. It can optionally update the condition flags 5385// based on the result. 5386bool 5387EmulateInstructionARM::EmulateANDReg (const uint32_t opcode, const ARMEncoding encoding) 5388{ 5389#if 0 5390 // ARM pseudo code... 5391 if ConditionPassed() then 5392 EncodingSpecificOperations(); 5393 (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C); 5394 result = R[n] AND shifted; 5395 if d == 15 then // Can only occur for ARM encoding 5396 ALUWritePC(result); // setflags is always FALSE here 5397 else 5398 R[d] = result; 5399 if setflags then 5400 APSR.N = result<31>; 5401 APSR.Z = IsZeroBit(result); 5402 APSR.C = carry; 5403 // APSR.V unchanged 5404#endif 5405 5406 bool success = false; 5407 5408 if (ConditionPassed(opcode)) 5409 { 5410 uint32_t Rd, Rn, Rm; 5411 ARM_ShifterType shift_t; 5412 uint32_t shift_n; // the shift applied to the value read from Rm 5413 bool setflags; 5414 uint32_t carry; 5415 switch (encoding) 5416 { 5417 case eEncodingT1: 5418 Rd = Rn = Bits32(opcode, 2, 0); 5419 Rm = Bits32(opcode, 5, 3); 5420 setflags = !InITBlock(); 5421 shift_t = SRType_LSL; 5422 shift_n = 0; 5423 break; 5424 case eEncodingT2: 5425 Rd = Bits32(opcode, 11, 8); 5426 Rn = Bits32(opcode, 19, 16); 5427 Rm = Bits32(opcode, 3, 0); 5428 setflags = BitIsSet(opcode, 20); 5429 shift_n = DecodeImmShiftThumb(opcode, shift_t); 5430 // if Rd == '1111' && S == '1' then SEE TST (register); 5431 if (Rd == 15 && setflags) 5432 return EmulateTSTReg(opcode, eEncodingT2); 5433 if (Rd == 13 || (Rd == 15 && !setflags) || BadReg(Rn) || BadReg(Rm)) 5434 return false; 5435 break; 5436 case eEncodingA1: 5437 Rd = Bits32(opcode, 15, 12); 5438 Rn = Bits32(opcode, 19, 16); 5439 Rm = Bits32(opcode, 3, 0); 5440 setflags = BitIsSet(opcode, 20); 5441 shift_n = DecodeImmShiftARM(opcode, shift_t); 5442 5443 if (Rd == 15 && setflags) 5444 return EmulateSUBSPcLrEtc (opcode, encoding); 5445 break; 5446 default: 5447 return false; 5448 } 5449 5450 // Read the first operand. 5451 uint32_t val1 = ReadCoreReg(Rn, &success); 5452 if (!success) 5453 return false; 5454 5455 // Read the second operand. 5456 uint32_t val2 = ReadCoreReg(Rm, &success); 5457 if (!success) 5458 return false; 5459 5460 uint32_t shifted = Shift_C(val2, shift_t, shift_n, APSR_C, carry); 5461 uint32_t result = val1 & shifted; 5462 5463 EmulateInstruction::Context context; 5464 context.type = EmulateInstruction::eContextImmediate; 5465 context.SetNoArgs (); 5466 5467 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry)) 5468 return false; 5469 } 5470 return true; 5471} 5472 5473// Bitwise Bit Clear (immediate) performs a bitwise AND of a register value and the complement of an 5474// immediate value, and writes the result to the destination register. It can optionally update the 5475// condition flags based on the result. 5476bool 5477EmulateInstructionARM::EmulateBICImm (const uint32_t opcode, const ARMEncoding encoding) 5478{ 5479#if 0 5480 // ARM pseudo code... 5481 if ConditionPassed() then 5482 EncodingSpecificOperations(); 5483 result = R[n] AND NOT(imm32); 5484 if d == 15 then // Can only occur for ARM encoding 5485 ALUWritePC(result); // setflags is always FALSE here 5486 else 5487 R[d] = result; 5488 if setflags then 5489 APSR.N = result<31>; 5490 APSR.Z = IsZeroBit(result); 5491 APSR.C = carry; 5492 // APSR.V unchanged 5493#endif 5494 5495 bool success = false; 5496 5497 if (ConditionPassed(opcode)) 5498 { 5499 uint32_t Rd, Rn; 5500 uint32_t imm32; // the immediate value to be bitwise inverted and ANDed to the value obtained from Rn 5501 bool setflags; 5502 uint32_t carry; // the carry bit after ARM/Thumb Expand operation 5503 switch (encoding) 5504 { 5505 case eEncodingT1: 5506 Rd = Bits32(opcode, 11, 8); 5507 Rn = Bits32(opcode, 19, 16); 5508 setflags = BitIsSet(opcode, 20); 5509 imm32 = ThumbExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C) 5510 if (BadReg(Rd) || BadReg(Rn)) 5511 return false; 5512 break; 5513 case eEncodingA1: 5514 Rd = Bits32(opcode, 15, 12); 5515 Rn = Bits32(opcode, 19, 16); 5516 setflags = BitIsSet(opcode, 20); 5517 imm32 = ARMExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ARMExpandImm(imm12, APSR.C) 5518 5519 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions; 5520 if (Rd == 15 && setflags) 5521 return EmulateSUBSPcLrEtc (opcode, encoding); 5522 break; 5523 default: 5524 return false; 5525 } 5526 5527 // Read the first operand. 5528 uint32_t val1 = ReadCoreReg(Rn, &success); 5529 if (!success) 5530 return false; 5531 5532 uint32_t result = val1 & ~imm32; 5533 5534 EmulateInstruction::Context context; 5535 context.type = EmulateInstruction::eContextImmediate; 5536 context.SetNoArgs (); 5537 5538 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry)) 5539 return false; 5540 } 5541 return true; 5542} 5543 5544// Bitwise Bit Clear (register) performs a bitwise AND of a register value and the complement of an 5545// optionally-shifted register value, and writes the result to the destination register. 5546// It can optionally update the condition flags based on the result. 5547bool 5548EmulateInstructionARM::EmulateBICReg (const uint32_t opcode, const ARMEncoding encoding) 5549{ 5550#if 0 5551 // ARM pseudo code... 5552 if ConditionPassed() then 5553 EncodingSpecificOperations(); 5554 (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C); 5555 result = R[n] AND NOT(shifted); 5556 if d == 15 then // Can only occur for ARM encoding 5557 ALUWritePC(result); // setflags is always FALSE here 5558 else 5559 R[d] = result; 5560 if setflags then 5561 APSR.N = result<31>; 5562 APSR.Z = IsZeroBit(result); 5563 APSR.C = carry; 5564 // APSR.V unchanged 5565#endif 5566 5567 bool success = false; 5568 5569 if (ConditionPassed(opcode)) 5570 { 5571 uint32_t Rd, Rn, Rm; 5572 ARM_ShifterType shift_t; 5573 uint32_t shift_n; // the shift applied to the value read from Rm 5574 bool setflags; 5575 uint32_t carry; 5576 switch (encoding) 5577 { 5578 case eEncodingT1: 5579 Rd = Rn = Bits32(opcode, 2, 0); 5580 Rm = Bits32(opcode, 5, 3); 5581 setflags = !InITBlock(); 5582 shift_t = SRType_LSL; 5583 shift_n = 0; 5584 break; 5585 case eEncodingT2: 5586 Rd = Bits32(opcode, 11, 8); 5587 Rn = Bits32(opcode, 19, 16); 5588 Rm = Bits32(opcode, 3, 0); 5589 setflags = BitIsSet(opcode, 20); 5590 shift_n = DecodeImmShiftThumb(opcode, shift_t); 5591 if (BadReg(Rd) || BadReg(Rn) || BadReg(Rm)) 5592 return false; 5593 break; 5594 case eEncodingA1: 5595 Rd = Bits32(opcode, 15, 12); 5596 Rn = Bits32(opcode, 19, 16); 5597 Rm = Bits32(opcode, 3, 0); 5598 setflags = BitIsSet(opcode, 20); 5599 shift_n = DecodeImmShiftARM(opcode, shift_t); 5600 5601 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions; 5602 if (Rd == 15 && setflags) 5603 return EmulateSUBSPcLrEtc (opcode, encoding); 5604 break; 5605 default: 5606 return false; 5607 } 5608 5609 // Read the first operand. 5610 uint32_t val1 = ReadCoreReg(Rn, &success); 5611 if (!success) 5612 return false; 5613 5614 // Read the second operand. 5615 uint32_t val2 = ReadCoreReg(Rm, &success); 5616 if (!success) 5617 return false; 5618 5619 uint32_t shifted = Shift_C(val2, shift_t, shift_n, APSR_C, carry); 5620 uint32_t result = val1 & ~shifted; 5621 5622 EmulateInstruction::Context context; 5623 context.type = EmulateInstruction::eContextImmediate; 5624 context.SetNoArgs (); 5625 5626 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry)) 5627 return false; 5628 } 5629 return true; 5630} 5631 5632// LDR (immediate, ARM) calculates an address from a base register value and an immediate offset, loads a word 5633// from memory, and writes it to a register. It can use offset, post-indexed, or pre-indexed addressing. 5634bool 5635EmulateInstructionARM::EmulateLDRImmediateARM (const uint32_t opcode, const ARMEncoding encoding) 5636{ 5637#if 0 5638 if ConditionPassed() then 5639 EncodingSpecificOperations(); 5640 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32); 5641 address = if index then offset_addr else R[n]; 5642 data = MemU[address,4]; 5643 if wback then R[n] = offset_addr; 5644 if t == 15 then 5645 if address<1:0> == '00' then LoadWritePC(data); else UNPREDICTABLE; 5646 elsif UnalignedSupport() || address<1:0> = '00' then 5647 R[t] = data; 5648 else // Can only apply before ARMv7 5649 R[t] = ROR(data, 8*UInt(address<1:0>)); 5650#endif 5651 5652 bool success = false; 5653 5654 if (ConditionPassed(opcode)) 5655 { 5656 const uint32_t addr_byte_size = GetAddressByteSize(); 5657 5658 uint32_t t; 5659 uint32_t n; 5660 uint32_t imm32; 5661 bool index; 5662 bool add; 5663 bool wback; 5664 5665 switch (encoding) 5666 { 5667 case eEncodingA1: 5668 // if Rn == '1111' then SEE LDR (literal); 5669 // if P == '0' && W == '1' then SEE LDRT; 5670 // if Rn == '1101' && P == '0' && U == '1' && W == '0' && imm12 == '000000000100' then SEE POP; 5671 // t == UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32); 5672 t = Bits32 (opcode, 15, 12); 5673 n = Bits32 (opcode, 19, 16); 5674 imm32 = Bits32 (opcode, 11, 0); 5675 5676 // index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1'); 5677 index = BitIsSet (opcode, 24); 5678 add = BitIsSet (opcode, 23); 5679 wback = (BitIsClear (opcode, 24) || BitIsSet (opcode, 21)); 5680 5681 // if wback && n == t then UNPREDICTABLE; 5682 if (wback && (n == t)) 5683 return false; 5684 5685 break; 5686 5687 default: 5688 return false; 5689 } 5690 5691 addr_t address; 5692 addr_t offset_addr; 5693 addr_t base_address = ReadCoreReg (n, &success); 5694 if (!success) 5695 return false; 5696 5697 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32); 5698 if (add) 5699 offset_addr = base_address + imm32; 5700 else 5701 offset_addr = base_address - imm32; 5702 5703 // address = if index then offset_addr else R[n]; 5704 if (index) 5705 address = offset_addr; 5706 else 5707 address = base_address; 5708 5709 // data = MemU[address,4]; 5710 5711 Register base_reg; 5712 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n); 5713 5714 EmulateInstruction::Context context; 5715 context.type = eContextRegisterLoad; 5716 context.SetRegisterPlusOffset (base_reg, address - base_address); 5717 5718 uint64_t data = MemURead (context, address, addr_byte_size, 0, &success); 5719 if (!success) 5720 return false; 5721 5722 // if wback then R[n] = offset_addr; 5723 if (wback) 5724 { 5725 context.type = eContextAdjustBaseRegister; 5726 context.SetAddress (offset_addr); 5727 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr)) 5728 return false; 5729 } 5730 5731 // if t == 15 then 5732 if (t == 15) 5733 { 5734 // if address<1:0> == '00' then LoadWritePC(data); else UNPREDICTABLE; 5735 if (BitIsClear (address, 1) && BitIsClear (address, 0)) 5736 { 5737 // LoadWritePC (data); 5738 context.type = eContextRegisterLoad; 5739 context.SetRegisterPlusOffset (base_reg, address - base_address); 5740 LoadWritePC (context, data); 5741 } 5742 else 5743 return false; 5744 } 5745 // elsif UnalignedSupport() || address<1:0> = '00' then 5746 else if (UnalignedSupport() || (BitIsClear (address, 1) && BitIsClear (address, 0))) 5747 { 5748 // R[t] = data; 5749 context.type = eContextRegisterLoad; 5750 context.SetRegisterPlusOffset (base_reg, address - base_address); 5751 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data)) 5752 return false; 5753 } 5754 // else // Can only apply before ARMv7 5755 else 5756 { 5757 // R[t] = ROR(data, 8*UInt(address<1:0>)); 5758 data = ROR (data, Bits32 (address, 1, 0)); 5759 context.type = eContextRegisterLoad; 5760 context.SetImmediate (data); 5761 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data)) 5762 return false; 5763 } 5764 5765 } 5766 return true; 5767} 5768 5769// LDR (register) calculates an address from a base register value and an offset register value, loads a word 5770// from memory, and writes it to a resgister. The offset register value can optionally be shifted. 5771bool 5772EmulateInstructionARM::EmulateLDRRegister (const uint32_t opcode, const ARMEncoding encoding) 5773{ 5774#if 0 5775 if ConditionPassed() then 5776 EncodingSpecificOperations(); NullCheckIfThumbEE(n); 5777 offset = Shift(R[m], shift_t, shift_n, APSR.C); 5778 offset_addr = if add then (R[n] + offset) else (R[n] - offset); 5779 address = if index then offset_addr else R[n]; 5780 data = MemU[address,4]; 5781 if wback then R[n] = offset_addr; 5782 if t == 15 then 5783 if address<1:0> == '00' then LoadWritePC(data); else UNPREDICTABLE; 5784 elsif UnalignedSupport() || address<1:0> = '00' then 5785 R[t] = data; 5786 else // Can only apply before ARMv7 5787 if CurrentInstrSet() == InstrSet_ARM then 5788 R[t] = ROR(data, 8*UInt(address<1:0>)); 5789 else 5790 R[t] = bits(32) UNKNOWN; 5791#endif 5792 5793 bool success = false; 5794 5795 if (ConditionPassed(opcode)) 5796 { 5797 const uint32_t addr_byte_size = GetAddressByteSize(); 5798 5799 uint32_t t; 5800 uint32_t n; 5801 uint32_t m; 5802 bool index; 5803 bool add; 5804 bool wback; 5805 ARM_ShifterType shift_t; 5806 uint32_t shift_n; 5807 5808 switch (encoding) 5809 { 5810 case eEncodingT1: 5811 // if CurrentInstrSet() == InstrSet_ThumbEE then SEE "Modified operation in ThumbEE"; 5812 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm); 5813 t = Bits32 (opcode, 2, 0); 5814 n = Bits32 (opcode, 5, 3); 5815 m = Bits32 (opcode, 8, 6); 5816 5817 // index = TRUE; add = TRUE; wback = FALSE; 5818 index = true; 5819 add = true; 5820 wback = false; 5821 5822 // (shift_t, shift_n) = (SRType_LSL, 0); 5823 shift_t = SRType_LSL; 5824 shift_n = 0; 5825 5826 break; 5827 5828 case eEncodingT2: 5829 // if Rn == '1111' then SEE LDR (literal); 5830 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm); 5831 t = Bits32 (opcode, 15, 12); 5832 n = Bits32 (opcode, 19, 16); 5833 m = Bits32 (opcode, 3, 0); 5834 5835 // index = TRUE; add = TRUE; wback = FALSE; 5836 index = true; 5837 add = true; 5838 wback = false; 5839 5840 // (shift_t, shift_n) = (SRType_LSL, UInt(imm2)); 5841 shift_t = SRType_LSL; 5842 shift_n = Bits32 (opcode, 5, 4); 5843 5844 // if BadReg(m) then UNPREDICTABLE; 5845 if (BadReg (m)) 5846 return false; 5847 5848 // if t == 15 && InITBlock() && !LastInITBlock() then UNPREDICTABLE; 5849 if ((t == 15) && InITBlock() && !LastInITBlock()) 5850 return false; 5851 5852 break; 5853 5854 case eEncodingA1: 5855 { 5856 // if P == '0' && W == '1' then SEE LDRT; 5857 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm); 5858 t = Bits32 (opcode, 15, 12); 5859 n = Bits32 (opcode, 19, 16); 5860 m = Bits32 (opcode, 3, 0); 5861 5862 // index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1'); 5863 index = BitIsSet (opcode, 24); 5864 add = BitIsSet (opcode, 23); 5865 wback = (BitIsClear (opcode, 24) || BitIsSet (opcode, 21)); 5866 5867 // (shift_t, shift_n) = DecodeImmShift(type, imm5); 5868 uint32_t type = Bits32 (opcode, 6, 5); 5869 uint32_t imm5 = Bits32 (opcode, 11, 7); 5870 shift_n = DecodeImmShift (type, imm5, shift_t); 5871 5872 // if m == 15 then UNPREDICTABLE; 5873 if (m == 15) 5874 return false; 5875 5876 // if wback && (n == 15 || n == t) then UNPREDICTABLE; 5877 if (wback && ((n == 15) || (n == t))) 5878 return false; 5879 } 5880 break; 5881 5882 5883 default: 5884 return false; 5885 } 5886 5887 uint32_t Rm = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success); 5888 if (!success) 5889 return false; 5890 5891 uint32_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success); 5892 if (!success) 5893 return false; 5894 5895 addr_t offset_addr; 5896 addr_t address; 5897 5898 // offset = Shift(R[m], shift_t, shift_n, APSR.C); -- Note "The APSR is an application level alias for the CPSR". 5899 addr_t offset = Shift (Rm, shift_t, shift_n, Bit32 (m_opcode_cpsr, APSR_C)); 5900 5901 // offset_addr = if add then (R[n] + offset) else (R[n] - offset); 5902 if (add) 5903 offset_addr = Rn + offset; 5904 else 5905 offset_addr = Rn - offset; 5906 5907 // address = if index then offset_addr else R[n]; 5908 if (index) 5909 address = offset_addr; 5910 else 5911 address = Rn; 5912 5913 // data = MemU[address,4]; 5914 Register base_reg; 5915 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n); 5916 5917 EmulateInstruction::Context context; 5918 context.type = eContextRegisterLoad; 5919 context.SetRegisterPlusOffset (base_reg, address - Rn); 5920 5921 uint64_t data = MemURead (context, address, addr_byte_size, 0, &success); 5922 if (!success) 5923 return false; 5924 5925 // if wback then R[n] = offset_addr; 5926 if (wback) 5927 { 5928 context.type = eContextAdjustBaseRegister; 5929 context.SetAddress (offset_addr); 5930 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr)) 5931 return false; 5932 } 5933 5934 // if t == 15 then 5935 if (t == 15) 5936 { 5937 // if address<1:0> == '00' then LoadWritePC(data); else UNPREDICTABLE; 5938 if (BitIsClear (address, 1) && BitIsClear (address, 0)) 5939 { 5940 context.type = eContextRegisterLoad; 5941 context.SetRegisterPlusOffset (base_reg, address - Rn); 5942 LoadWritePC (context, data); 5943 } 5944 else 5945 return false; 5946 } 5947 // elsif UnalignedSupport() || address<1:0> = '00' then 5948 else if (UnalignedSupport () || (BitIsClear (address, 1) && BitIsClear (address, 0))) 5949 { 5950 // R[t] = data; 5951 context.type = eContextRegisterLoad; 5952 context.SetRegisterPlusOffset (base_reg, address - Rn); 5953 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data)) 5954 return false; 5955 } 5956 else // Can only apply before ARMv7 5957 { 5958 // if CurrentInstrSet() == InstrSet_ARM then 5959 if (CurrentInstrSet () == eModeARM) 5960 { 5961 // R[t] = ROR(data, 8*UInt(address<1:0>)); 5962 data = ROR (data, Bits32 (address, 1, 0)); 5963 context.type = eContextRegisterLoad; 5964 context.SetImmediate (data); 5965 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data)) 5966 return false; 5967 } 5968 else 5969 { 5970 // R[t] = bits(32) UNKNOWN; 5971 WriteBits32Unknown (t); 5972 } 5973 } 5974 } 5975 return true; 5976} 5977 5978// LDRB (immediate, Thumb) 5979bool 5980EmulateInstructionARM::EmulateLDRBImmediate (const uint32_t opcode, const ARMEncoding encoding) 5981{ 5982#if 0 5983 if ConditionPassed() then 5984 EncodingSpecificOperations(); NullCheckIfThumbEE(n); 5985 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32); 5986 address = if index then offset_addr else R[n]; 5987 R[t] = ZeroExtend(MemU[address,1], 32); 5988 if wback then R[n] = offset_addr; 5989#endif 5990 5991 bool success = false; 5992 5993 if (ConditionPassed(opcode)) 5994 { 5995 uint32_t t; 5996 uint32_t n; 5997 uint32_t imm32; 5998 bool index; 5999 bool add; 6000 bool wback; 6001 6002 // EncodingSpecificOperations(); NullCheckIfThumbEE(n); 6003 switch (encoding) 6004 { 6005 case eEncodingT1: 6006 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm5, 32); 6007 t = Bits32 (opcode, 2, 0); 6008 n = Bits32 (opcode, 5, 3); 6009 imm32 = Bits32 (opcode, 10, 6); 6010 6011 // index = TRUE; add = TRUE; wback = FALSE; 6012 index = true; 6013 add = true; 6014 wback= false; 6015 6016 break; 6017 6018 case eEncodingT2: 6019 // if Rt == '1111' then SEE PLD; 6020 // if Rn == '1111' then SEE LDRB (literal); 6021 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32); 6022 t = Bits32 (opcode, 15, 12); 6023 n = Bits32 (opcode, 19, 16); 6024 imm32 = Bits32 (opcode, 11, 0); 6025 6026 // index = TRUE; add = TRUE; wback = FALSE; 6027 index = true; 6028 add = true; 6029 wback = false; 6030 6031 // if t == 13 then UNPREDICTABLE; 6032 if (t == 13) 6033 return false; 6034 6035 break; 6036 6037 case eEncodingT3: 6038 // if Rt == '1111' && P == '1' && U == '0' && W == '0' then SEE PLD; 6039 // if Rn == '1111' then SEE LDRB (literal); 6040 // if P == '1' && U == '1' && W == '0' then SEE LDRBT; 6041 // if P == '0' && W == '0' then UNDEFINED; 6042 if (BitIsClear (opcode, 10) && BitIsClear (opcode, 8)) 6043 return false; 6044 6045 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32); 6046 t = Bits32 (opcode, 15, 12); 6047 n = Bits32 (opcode, 19, 16); 6048 imm32 = Bits32 (opcode, 7, 0); 6049 6050 // index = (P == '1'); add = (U == '1'); wback = (W == '1'); 6051 index = BitIsSet (opcode, 10); 6052 add = BitIsSet (opcode, 9); 6053 wback = BitIsSet (opcode, 8); 6054 6055 // if BadReg(t) || (wback && n == t) then UNPREDICTABLE; 6056 if (BadReg (t) || (wback && (n == t))) 6057 return false; 6058 6059 break; 6060 6061 default: 6062 return false; 6063 } 6064 6065 uint32_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success); 6066 if (!success) 6067 return false; 6068 6069 addr_t address; 6070 addr_t offset_addr; 6071 6072 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32); 6073 if (add) 6074 offset_addr = Rn + imm32; 6075 else 6076 offset_addr = Rn - imm32; 6077 6078 // address = if index then offset_addr else R[n]; 6079 if (index) 6080 address = offset_addr; 6081 else 6082 address = Rn; 6083 6084 // R[t] = ZeroExtend(MemU[address,1], 32); 6085 Register base_reg; 6086 Register data_reg; 6087 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n); 6088 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + t); 6089 6090 EmulateInstruction::Context context; 6091 context.type = eContextRegisterLoad; 6092 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, address - Rn); 6093 6094 uint64_t data = MemURead (context, address, 1, 0, &success); 6095 if (!success) 6096 return false; 6097 6098 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data)) 6099 return false; 6100 6101 // if wback then R[n] = offset_addr; 6102 if (wback) 6103 { 6104 context.type = eContextAdjustBaseRegister; 6105 context.SetAddress (offset_addr); 6106 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr)) 6107 return false; 6108 } 6109 } 6110 return true; 6111} 6112 6113// LDRB (literal) calculates an address from the PC value and an immediate offset, loads a byte from memory, 6114// zero-extends it to form a 32-bit word and writes it to a register. 6115bool 6116EmulateInstructionARM::EmulateLDRBLiteral (const uint32_t opcode, const ARMEncoding encoding) 6117{ 6118#if 0 6119 if ConditionPassed() then 6120 EncodingSpecificOperations(); NullCheckIfThumbEE(15); 6121 base = Align(PC,4); 6122 address = if add then (base + imm32) else (base - imm32); 6123 R[t] = ZeroExtend(MemU[address,1], 32); 6124#endif 6125 6126 bool success = false; 6127 6128 if (ConditionPassed(opcode)) 6129 { 6130 uint32_t t; 6131 uint32_t imm32; 6132 bool add; 6133 switch (encoding) 6134 { 6135 case eEncodingT1: 6136 // if Rt == '1111' then SEE PLD; 6137 // t = UInt(Rt); imm32 = ZeroExtend(imm12, 32); add = (U == '1'); 6138 t = Bits32 (opcode, 15, 12); 6139 imm32 = Bits32 (opcode, 11, 0); 6140 add = BitIsSet (opcode, 23); 6141 6142 // if t == 13 then UNPREDICTABLE; 6143 if (t == 13) 6144 return false; 6145 6146 break; 6147 6148 case eEncodingA1: 6149 // t == UInt(Rt); imm32 = ZeroExtend(imm12, 32); add = (U == '1'); 6150 t = Bits32 (opcode, 15, 12); 6151 imm32 = Bits32 (opcode, 11, 0); 6152 add = BitIsSet (opcode, 23); 6153 6154 // if t == 15 then UNPREDICTABLE; 6155 if (t == 15) 6156 return false; 6157 break; 6158 6159 default: 6160 return false; 6161 } 6162 6163 // base = Align(PC,4); 6164 uint32_t pc_val = ReadCoreReg (PC_REG, &success); 6165 if (!success) 6166 return false; 6167 6168 uint32_t base = AlignPC (pc_val); 6169 6170 addr_t address; 6171 // address = if add then (base + imm32) else (base - imm32); 6172 if (add) 6173 address = base + imm32; 6174 else 6175 address = base - imm32; 6176 6177 // R[t] = ZeroExtend(MemU[address,1], 32); 6178 EmulateInstruction::Context context; 6179 context.type = eContextRelativeBranchImmediate; 6180 context.SetImmediate (address - base); 6181 6182 uint64_t data = MemURead (context, address, 1, 0, &success); 6183 if (!success) 6184 return false; 6185 6186 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data)) 6187 return false; 6188 } 6189 return true; 6190} 6191 6192// LDRB (register) calculates an address from a base register value and an offset rigister value, loads a byte from 6193// memory, zero-extends it to form a 32-bit word, and writes it to a register. The offset register value can 6194// optionally be shifted. 6195bool 6196EmulateInstructionARM::EmulateLDRBRegister (const uint32_t opcode, const ARMEncoding encoding) 6197{ 6198#if 0 6199 if ConditionPassed() then 6200 EncodingSpecificOperations(); NullCheckIfThumbEE(n); 6201 offset = Shift(R[m], shift_t, shift_n, APSR.C); 6202 offset_addr = if add then (R[n] + offset) else (R[n] - offset); 6203 address = if index then offset_addr else R[n]; 6204 R[t] = ZeroExtend(MemU[address,1],32); 6205 if wback then R[n] = offset_addr; 6206#endif 6207 6208 bool success = false; 6209 6210 if (ConditionPassed(opcode)) 6211 { 6212 uint32_t t; 6213 uint32_t n; 6214 uint32_t m; 6215 bool index; 6216 bool add; 6217 bool wback; 6218 ARM_ShifterType shift_t; 6219 uint32_t shift_n; 6220 6221 // EncodingSpecificOperations(); NullCheckIfThumbEE(n); 6222 switch (encoding) 6223 { 6224 case eEncodingT1: 6225 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm); 6226 t = Bits32 (opcode, 2, 0); 6227 n = Bits32 (opcode, 5, 3); 6228 m = Bits32 (opcode, 8, 6); 6229 6230 // index = TRUE; add = TRUE; wback = FALSE; 6231 index = true; 6232 add = true; 6233 wback = false; 6234 6235 // (shift_t, shift_n) = (SRType_LSL, 0); 6236 shift_t = SRType_LSL; 6237 shift_n = 0; 6238 break; 6239 6240 case eEncodingT2: 6241 // if Rt == '1111' then SEE PLD; 6242 // if Rn == '1111' then SEE LDRB (literal); 6243 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm); 6244 t = Bits32 (opcode, 15, 12); 6245 n = Bits32 (opcode, 19, 16); 6246 m = Bits32 (opcode, 3, 0); 6247 6248 // index = TRUE; add = TRUE; wback = FALSE; 6249 index = true; 6250 add = true; 6251 wback = false; 6252 6253 // (shift_t, shift_n) = (SRType_LSL, UInt(imm2)); 6254 shift_t = SRType_LSL; 6255 shift_n = Bits32 (opcode, 5, 4); 6256 6257 // if t == 13 || BadReg(m) then UNPREDICTABLE; 6258 if ((t == 13) || BadReg (m)) 6259 return false; 6260 break; 6261 6262 case eEncodingA1: 6263 { 6264 // if P == '0' && W == '1' then SEE LDRBT; 6265 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm); 6266 t = Bits32 (opcode, 15, 12); 6267 n = Bits32 (opcode, 19, 16); 6268 m = Bits32 (opcode, 3, 0); 6269 6270 // index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1'); 6271 index = BitIsSet (opcode, 24); 6272 add = BitIsSet (opcode, 23); 6273 wback = (BitIsClear (opcode, 24) || BitIsSet (opcode, 21)); 6274 6275 // (shift_t, shift_n) = DecodeImmShift(type, imm5); 6276 uint32_t type = Bits32 (opcode, 6, 5); 6277 uint32_t imm5 = Bits32 (opcode, 11, 7); 6278 shift_n = DecodeImmShift (type, imm5, shift_t); 6279 6280 // if t == 15 || m == 15 then UNPREDICTABLE; 6281 if ((t == 15) || (m == 15)) 6282 return false; 6283 6284 // if wback && (n == 15 || n == t) then UNPREDICTABLE; 6285 if (wback && ((n == 15) || (n == t))) 6286 return false; 6287 } 6288 break; 6289 6290 default: 6291 return false; 6292 } 6293 6294 addr_t offset_addr; 6295 addr_t address; 6296 6297 // offset = Shift(R[m], shift_t, shift_n, APSR.C); 6298 uint32_t Rm = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success); 6299 if (!success) 6300 return false; 6301 6302 addr_t offset = Shift (Rm, shift_t, shift_n, APSR_C); 6303 6304 // offset_addr = if add then (R[n] + offset) else (R[n] - offset); 6305 uint32_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success); 6306 if (!success) 6307 return false; 6308 6309 if (add) 6310 offset_addr = Rn + offset; 6311 else 6312 offset_addr = Rn - offset; 6313 6314 // address = if index then offset_addr else R[n]; 6315 if (index) 6316 address = offset_addr; 6317 else 6318 address = Rn; 6319 6320 // R[t] = ZeroExtend(MemU[address,1],32); 6321 Register base_reg; 6322 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n); 6323 6324 EmulateInstruction::Context context; 6325 context.type = eContextRegisterLoad; 6326 context.SetRegisterPlusOffset (base_reg, address - Rn); 6327 6328 uint64_t data = MemURead (context, address, 1, 0, &success); 6329 if (!success) 6330 return false; 6331 6332 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data)) 6333 return false; 6334 6335 // if wback then R[n] = offset_addr; 6336 if (wback) 6337 { 6338 context.type = eContextAdjustBaseRegister; 6339 context.SetAddress (offset_addr); 6340 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr)) 6341 return false; 6342 } 6343 } 6344 return true; 6345} 6346 6347// LDRH (immediate, Thumb) calculates an address from a base register value and an immediate offset, loads a 6348// halfword from memory, zero-extends it to form a 32-bit word, and writes it to a register. It can use offset, 6349// post-indexed, or pre-indexed addressing. 6350bool 6351EmulateInstructionARM::EmulateLDRHImmediate (const uint32_t opcode, const ARMEncoding encoding) 6352{ 6353#if 0 6354 if ConditionPassed() then 6355 EncodingSpecificOperations(); NullCheckIfThumbEE(n); 6356 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32); 6357 address = if index then offset_addr else R[n]; 6358 data = MemU[address,2]; 6359 if wback then R[n] = offset_addr; 6360 if UnalignedSupport() || address<0> = '0' then 6361 R[t] = ZeroExtend(data, 32); 6362 else // Can only apply before ARMv7 6363 R[t] = bits(32) UNKNOWN; 6364#endif 6365 6366 6367 bool success = false; 6368 6369 if (ConditionPassed(opcode)) 6370 { 6371 uint32_t t; 6372 uint32_t n; 6373 uint32_t imm32; 6374 bool index; 6375 bool add; 6376 bool wback; 6377 6378 // EncodingSpecificOperations(); NullCheckIfThumbEE(n); 6379 switch (encoding) 6380 { 6381 case eEncodingT1: 6382 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm5:'0', 32); 6383 t = Bits32 (opcode, 2, 0); 6384 n = Bits32 (opcode, 5, 3); 6385 imm32 = Bits32 (opcode, 10, 6) << 1; 6386 6387 // index = TRUE; add = TRUE; wback = FALSE; 6388 index = true; 6389 add = true; 6390 wback = false; 6391 6392 break; 6393 6394 case eEncodingT2: 6395 // if Rt == '1111' then SEE "Unallocated memory hints"; 6396 // if Rn == '1111' then SEE LDRH (literal); 6397 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32); 6398 t = Bits32 (opcode, 15, 12); 6399 n = Bits32 (opcode, 19, 16); 6400 imm32 = Bits32 (opcode, 11, 0); 6401 6402 // index = TRUE; add = TRUE; wback = FALSE; 6403 index = true; 6404 add = true; 6405 wback = false; 6406 6407 // if t == 13 then UNPREDICTABLE; 6408 if (t == 13) 6409 return false; 6410 break; 6411 6412 case eEncodingT3: 6413 // if Rn == '1111' then SEE LDRH (literal); 6414 // if Rt == '1111' && P == '1' && U == '0' && W == '0' then SEE "Unallocated memory hints"; 6415 // if P == '1' && U == '1' && W == '0' then SEE LDRHT; 6416 // if P == '0' && W == '0' then UNDEFINED; 6417 if (BitIsClear (opcode, 10) && BitIsClear (opcode, 8)) 6418 return false; 6419 6420 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32); 6421 t = Bits32 (opcode, 15, 12); 6422 n = Bits32 (opcode, 19, 16); 6423 imm32 = Bits32 (opcode, 7, 0); 6424 6425 // index = (P == '1'); add = (U == '1'); wback = (W == '1'); 6426 index = BitIsSet (opcode, 10); 6427 add = BitIsSet (opcode, 9); 6428 wback = BitIsSet (opcode, 8); 6429 6430 // if BadReg(t) || (wback && n == t) then UNPREDICTABLE; 6431 if (BadReg (t) || (wback && (n == t))) 6432 return false; 6433 break; 6434 6435 default: 6436 return false; 6437 } 6438 6439 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32); 6440 uint32_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success); 6441 if (!success) 6442 return false; 6443 6444 addr_t offset_addr; 6445 addr_t address; 6446 6447 if (add) 6448 offset_addr = Rn + imm32; 6449 else 6450 offset_addr = Rn - imm32; 6451 6452 // address = if index then offset_addr else R[n]; 6453 if (index) 6454 address = offset_addr; 6455 else 6456 address = Rn; 6457 6458 // data = MemU[address,2]; 6459 Register base_reg; 6460 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n); 6461 6462 EmulateInstruction::Context context; 6463 context.type = eContextRegisterLoad; 6464 context.SetRegisterPlusOffset (base_reg, address - Rn); 6465 6466 uint64_t data = MemURead (context, address, 2, 0, &success); 6467 if (!success) 6468 return false; 6469 6470 // if wback then R[n] = offset_addr; 6471 if (wback) 6472 { 6473 context.type = eContextAdjustBaseRegister; 6474 context.SetAddress (offset_addr); 6475 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr)) 6476 return false; 6477 } 6478 6479 // if UnalignedSupport() || address<0> = '0' then 6480 if (UnalignedSupport () || BitIsClear (address, 0)) 6481 { 6482 // R[t] = ZeroExtend(data, 32); 6483 context.type = eContextRegisterLoad; 6484 context.SetRegisterPlusOffset (base_reg, address - Rn); 6485 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data)) 6486 return false; 6487 } 6488 else // Can only apply before ARMv7 6489 { 6490 // R[t] = bits(32) UNKNOWN; 6491 WriteBits32Unknown (t); 6492 } 6493 } 6494 return true; 6495} 6496 6497// LDRH (literal) caculates an address from the PC value and an immediate offset, loads a halfword from memory, 6498// zero-extends it to form a 32-bit word, and writes it to a register. 6499bool 6500EmulateInstructionARM::EmulateLDRHLiteral (const uint32_t opcode, const ARMEncoding encoding) 6501{ 6502#if 0 6503 if ConditionPassed() then 6504 EncodingSpecificOperations(); NullCheckIfThumbEE(15); 6505 base = Align(PC,4); 6506 address = if add then (base + imm32) else (base - imm32); 6507 data = MemU[address,2]; 6508 if UnalignedSupport() || address<0> = '0' then 6509 R[t] = ZeroExtend(data, 32); 6510 else // Can only apply before ARMv7 6511 R[t] = bits(32) UNKNOWN; 6512#endif 6513 6514 bool success = false; 6515 6516 if (ConditionPassed(opcode)) 6517 { 6518 uint32_t t; 6519 uint32_t imm32; 6520 bool add; 6521 6522 // EncodingSpecificOperations(); NullCheckIfThumbEE(15); 6523 switch (encoding) 6524 { 6525 case eEncodingT1: 6526 // if Rt == '1111' then SEE "Unallocated memory hints"; 6527 // t = UInt(Rt); imm32 = ZeroExtend(imm12, 32); add = (U == '1'); 6528 t = Bits32 (opcode, 15, 12); 6529 imm32 = Bits32 (opcode, 11, 0); 6530 add = BitIsSet (opcode, 23); 6531 6532 // if t == 13 then UNPREDICTABLE; 6533 if (t == 13) 6534 return false; 6535 6536 break; 6537 6538 case eEncodingA1: 6539 { 6540 uint32_t imm4H = Bits32 (opcode, 11, 8); 6541 uint32_t imm4L = Bits32 (opcode, 3, 0); 6542 6543 // t == UInt(Rt); imm32 = ZeroExtend(imm4H:imm4L, 32); add = (U == '1'); 6544 t = Bits32 (opcode, 15, 12); 6545 imm32 = (imm4H << 4) | imm4L; 6546 add = BitIsSet (opcode, 23); 6547 6548 // if t == 15 then UNPREDICTABLE; 6549 if (t == 15) 6550 return false; 6551 break; 6552 } 6553 6554 default: 6555 return false; 6556 } 6557 6558 // base = Align(PC,4); 6559 uint64_t pc_value = ReadCoreReg (PC_REG, &success); 6560 if (!success) 6561 return false; 6562 6563 addr_t base = AlignPC (pc_value); 6564 addr_t address; 6565 6566 // address = if add then (base + imm32) else (base - imm32); 6567 if (add) 6568 address = base + imm32; 6569 else 6570 address = base - imm32; 6571 6572 // data = MemU[address,2]; 6573 Register base_reg; 6574 base_reg.SetRegister (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC); 6575 6576 EmulateInstruction::Context context; 6577 context.type = eContextRegisterLoad; 6578 context.SetRegisterPlusOffset (base_reg, address - base); 6579 6580 uint64_t data = MemURead (context, address, 2, 0, &success); 6581 if (!success) 6582 return false; 6583 6584 6585 // if UnalignedSupport() || address<0> = '0' then 6586 if (UnalignedSupport () || BitIsClear (address, 0)) 6587 { 6588 // R[t] = ZeroExtend(data, 32); 6589 context.type = eContextRegisterLoad; 6590 context.SetRegisterPlusOffset (base_reg, address - base); 6591 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data)) 6592 return false; 6593 6594 } 6595 else // Can only apply before ARMv7 6596 { 6597 // R[t] = bits(32) UNKNOWN; 6598 WriteBits32Unknown (t); 6599 } 6600 } 6601 return true; 6602} 6603 6604// LDRH (literal) calculates an address from a base register value and an offset register value, loads a halfword 6605// from memory, zero-extends it to form a 32-bit word, and writes it to a register. The offset register value can 6606// be shifted left by 0, 1, 2, or 3 bits. 6607bool 6608EmulateInstructionARM::EmulateLDRHRegister (const uint32_t opcode, const ARMEncoding encoding) 6609{ 6610#if 0 6611 if ConditionPassed() then 6612 EncodingSpecificOperations(); NullCheckIfThumbEE(n); 6613 offset = Shift(R[m], shift_t, shift_n, APSR.C); 6614 offset_addr = if add then (R[n] + offset) else (R[n] - offset); 6615 address = if index then offset_addr else R[n]; 6616 data = MemU[address,2]; 6617 if wback then R[n] = offset_addr; 6618 if UnalignedSupport() || address<0> = '0' then 6619 R[t] = ZeroExtend(data, 32); 6620 else // Can only apply before ARMv7 6621 R[t] = bits(32) UNKNOWN; 6622#endif 6623 6624 bool success = false; 6625 6626 if (ConditionPassed(opcode)) 6627 { 6628 uint32_t t; 6629 uint32_t n; 6630 uint32_t m; 6631 bool index; 6632 bool add; 6633 bool wback; 6634 ARM_ShifterType shift_t; 6635 uint32_t shift_n; 6636 6637 // EncodingSpecificOperations(); NullCheckIfThumbEE(n); 6638 switch (encoding) 6639 { 6640 case eEncodingT1: 6641 // if CurrentInstrSet() == InstrSet_ThumbEE then SEE "Modified operation in ThumbEE"; 6642 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm); 6643 t = Bits32 (opcode, 2, 0); 6644 n = Bits32 (opcode, 5, 3); 6645 m = Bits32 (opcode, 8, 6); 6646 6647 // index = TRUE; add = TRUE; wback = FALSE; 6648 index = true; 6649 add = true; 6650 wback = false; 6651 6652 // (shift_t, shift_n) = (SRType_LSL, 0); 6653 shift_t = SRType_LSL; 6654 shift_n = 0; 6655 6656 break; 6657 6658 case eEncodingT2: 6659 // if Rn == '1111' then SEE LDRH (literal); 6660 // if Rt == '1111' then SEE "Unallocated memory hints"; 6661 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm); 6662 t = Bits32 (opcode, 15, 12); 6663 n = Bits32 (opcode, 19, 16); 6664 m = Bits32 (opcode, 3, 0); 6665 6666 // index = TRUE; add = TRUE; wback = FALSE; 6667 index = true; 6668 add = true; 6669 wback = false; 6670 6671 // (shift_t, shift_n) = (SRType_LSL, UInt(imm2)); 6672 shift_t = SRType_LSL; 6673 shift_n = Bits32 (opcode, 5, 4); 6674 6675 // if t == 13 || BadReg(m) then UNPREDICTABLE; 6676 if ((t == 13) || BadReg (m)) 6677 return false; 6678 break; 6679 6680 case eEncodingA1: 6681 // if P == '0' && W == '1' then SEE LDRHT; 6682 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm); 6683 t = Bits32 (opcode, 15, 12); 6684 n = Bits32 (opcode, 19, 16); 6685 m = Bits32 (opcode, 3, 0); 6686 6687 // index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1'); 6688 index = BitIsSet (opcode, 24); 6689 add = BitIsSet (opcode, 23); 6690 wback = (BitIsClear (opcode, 24) || BitIsSet (opcode, 21)); 6691 6692 // (shift_t, shift_n) = (SRType_LSL, 0); 6693 shift_t = SRType_LSL; 6694 shift_n = 0; 6695 6696 // if t == 15 || m == 15 then UNPREDICTABLE; 6697 if ((t == 15) || (m == 15)) 6698 return false; 6699 6700 // if wback && (n == 15 || n == t) then UNPREDICTABLE; 6701 if (wback && ((n == 15) || (n == t))) 6702 return false; 6703 6704 break; 6705 6706 default: 6707 return false; 6708 } 6709 6710 // offset = Shift(R[m], shift_t, shift_n, APSR.C); 6711 6712 uint64_t Rm = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success); 6713 if (!success) 6714 return false; 6715 6716 addr_t offset = Shift (Rm, shift_t, shift_n, APSR_C); 6717 6718 addr_t offset_addr; 6719 addr_t address; 6720 6721 // offset_addr = if add then (R[n] + offset) else (R[n] - offset); 6722 uint64_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success); 6723 if (!success) 6724 return false; 6725 6726 if (add) 6727 offset_addr = Rn + offset; 6728 else 6729 offset_addr = Rn - offset; 6730 6731 // address = if index then offset_addr else R[n]; 6732 if (index) 6733 address = offset_addr; 6734 else 6735 address = Rn; 6736 6737 // data = MemU[address,2]; 6738 Register base_reg; 6739 Register offset_reg; 6740 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n); 6741 offset_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + m); 6742 6743 EmulateInstruction::Context context; 6744 context.type = eContextRegisterLoad; 6745 context.SetRegisterPlusIndirectOffset (base_reg, offset_reg); 6746 uint64_t data = MemURead (context, address, 2, 0, &success); 6747 if (!success) 6748 return false; 6749 6750 // if wback then R[n] = offset_addr; 6751 if (wback) 6752 { 6753 context.type = eContextAdjustBaseRegister; 6754 context.SetAddress (offset_addr); 6755 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr)) 6756 return false; 6757 } 6758 6759 // if UnalignedSupport() || address<0> = '0' then 6760 if (UnalignedSupport() || BitIsClear (address, 0)) 6761 { 6762 // R[t] = ZeroExtend(data, 32); 6763 context.type = eContextRegisterLoad; 6764 context.SetRegisterPlusIndirectOffset (base_reg, offset_reg); 6765 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data)) 6766 return false; 6767 } 6768 else // Can only apply before ARMv7 6769 { 6770 // R[t] = bits(32) UNKNOWN; 6771 WriteBits32Unknown (t); 6772 } 6773 } 6774 return true; 6775} 6776 6777// LDRSB (immediate) calculates an address from a base register value and an immediate offset, loads a byte from 6778// memory, sign-extends it to form a 32-bit word, and writes it to a register. It can use offset, post-indexed, 6779// or pre-indexed addressing. 6780bool 6781EmulateInstructionARM::EmulateLDRSBImmediate (const uint32_t opcode, const ARMEncoding encoding) 6782{ 6783#if 0 6784 if ConditionPassed() then 6785 EncodingSpecificOperations(); NullCheckIfThumbEE(n); 6786 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32); 6787 address = if index then offset_addr else R[n]; 6788 R[t] = SignExtend(MemU[address,1], 32); 6789 if wback then R[n] = offset_addr; 6790#endif 6791 6792 bool success = false; 6793 6794 if (ConditionPassed(opcode)) 6795 { 6796 uint32_t t; 6797 uint32_t n; 6798 uint32_t imm32; 6799 bool index; 6800 bool add; 6801 bool wback; 6802 6803 // EncodingSpecificOperations(); NullCheckIfThumbEE(n); 6804 switch (encoding) 6805 { 6806 case eEncodingT1: 6807 // if Rt == '1111' then SEE PLI; 6808 // if Rn == '1111' then SEE LDRSB (literal); 6809 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32); 6810 t = Bits32 (opcode, 15, 12); 6811 n = Bits32 (opcode, 19, 16); 6812 imm32 = Bits32 (opcode, 11, 0); 6813 6814 // index = TRUE; add = TRUE; wback = FALSE; 6815 index = true; 6816 add = true; 6817 wback = false; 6818 6819 // if t == 13 then UNPREDICTABLE; 6820 if (t == 13) 6821 return false; 6822 6823 break; 6824 6825 case eEncodingT2: 6826 // if Rt == '1111' && P == '1' && U == '0' && W == '0' then SEE PLI; 6827 // if Rn == '1111' then SEE LDRSB (literal); 6828 // if P == '1' && U == '1' && W == '0' then SEE LDRSBT; 6829 // if P == '0' && W == '0' then UNDEFINED; 6830 if (BitIsClear (opcode, 10) && BitIsClear (opcode, 8)) 6831 return false; 6832 6833 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32); 6834 t = Bits32 (opcode, 15, 12); 6835 n = Bits32 (opcode, 19, 16); 6836 imm32 = Bits32 (opcode, 7, 0); 6837 6838 // index = (P == '1'); add = (U == '1'); wback = (W == '1'); 6839 index = BitIsSet (opcode, 10); 6840 add = BitIsSet (opcode, 9); 6841 wback = BitIsSet (opcode, 8); 6842 6843 // if BadReg(t) || (wback && n == t) then UNPREDICTABLE; 6844 if (((t == 13) || ((t == 15) 6845 && (BitIsClear (opcode, 10) || BitIsSet (opcode, 9) || BitIsSet (opcode, 8)))) 6846 || (wback && (n == t))) 6847 return false; 6848 6849 break; 6850 6851 case eEncodingA1: 6852 { 6853 // if Rn == '1111' then SEE LDRSB (literal); 6854 // if P == '0' && W == '1' then SEE LDRSBT; 6855 // t == UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm4H:imm4L, 32); 6856 t = Bits32 (opcode, 15, 12); 6857 n = Bits32 (opcode, 19, 16); 6858 6859 uint32_t imm4H = Bits32 (opcode, 11, 8); 6860 uint32_t imm4L = Bits32 (opcode, 3, 0); 6861 imm32 = (imm4H << 4) | imm4L; 6862 6863 // index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1'); 6864 index = BitIsSet (opcode, 24); 6865 add = BitIsSet (opcode, 23); 6866 wback = (BitIsClear (opcode, 24) || BitIsSet (opcode, 21)); 6867 6868 // if t == 15 || (wback && n == t) then UNPREDICTABLE; 6869 if ((t == 15) || (wback && (n == t))) 6870 return false; 6871 6872 break; 6873 } 6874 6875 default: 6876 return false; 6877 } 6878 6879 uint64_t Rn = ReadCoreReg (n, &success); 6880 if (!success) 6881 return false; 6882 6883 addr_t offset_addr; 6884 addr_t address; 6885 6886 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32); 6887 if (add) 6888 offset_addr = Rn + imm32; 6889 else 6890 offset_addr = Rn - imm32; 6891 6892 // address = if index then offset_addr else R[n]; 6893 if (index) 6894 address = offset_addr; 6895 else 6896 address = Rn; 6897 6898 // R[t] = SignExtend(MemU[address,1], 32); 6899 Register base_reg; 6900 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n); 6901 6902 EmulateInstruction::Context context; 6903 context.type = eContextRegisterLoad; 6904 context.SetRegisterPlusOffset (base_reg, address - Rn); 6905 6906 uint64_t unsigned_data = MemURead (context, address, 1, 0, &success); 6907 if (!success) 6908 return false; 6909 6910 int64_t signed_data = llvm::SignExtend64<8>(unsigned_data); 6911 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, (uint64_t) signed_data)) 6912 return false; 6913 6914 // if wback then R[n] = offset_addr; 6915 if (wback) 6916 { 6917 context.type = eContextAdjustBaseRegister; 6918 context.SetAddress (offset_addr); 6919 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr)) 6920 return false; 6921 } 6922 } 6923 6924 return true; 6925} 6926 6927// LDRSB (literal) calculates an address from the PC value and an immediate offset, loads a byte from memory, 6928// sign-extends it to form a 32-bit word, and writes tit to a register. 6929bool 6930EmulateInstructionARM::EmulateLDRSBLiteral (const uint32_t opcode, const ARMEncoding encoding) 6931{ 6932#if 0 6933 if ConditionPassed() then 6934 EncodingSpecificOperations(); NullCheckIfThumbEE(15); 6935 base = Align(PC,4); 6936 address = if add then (base + imm32) else (base - imm32); 6937 R[t] = SignExtend(MemU[address,1], 32); 6938#endif 6939 6940 bool success = false; 6941 6942 if (ConditionPassed(opcode)) 6943 { 6944 uint32_t t; 6945 uint32_t imm32; 6946 bool add; 6947 6948 // EncodingSpecificOperations(); NullCheckIfThumbEE(15); 6949 switch (encoding) 6950 { 6951 case eEncodingT1: 6952 // if Rt == '1111' then SEE PLI; 6953 // t = UInt(Rt); imm32 = ZeroExtend(imm12, 32); add = (U == '1'); 6954 t = Bits32 (opcode, 15, 12); 6955 imm32 = Bits32 (opcode, 11, 0); 6956 add = BitIsSet (opcode, 23); 6957 6958 // if t == 13 then UNPREDICTABLE; 6959 if (t == 13) 6960 return false; 6961 6962 break; 6963 6964 case eEncodingA1: 6965 { 6966 // t == UInt(Rt); imm32 = ZeroExtend(imm4H:imm4L, 32); add = (U == '1'); 6967 t = Bits32 (opcode, 15, 12); 6968 uint32_t imm4H = Bits32 (opcode, 11, 8); 6969 uint32_t imm4L = Bits32 (opcode, 3, 0); 6970 imm32 = (imm4H << 4) | imm4L; 6971 add = BitIsSet (opcode, 23); 6972 6973 // if t == 15 then UNPREDICTABLE; 6974 if (t == 15) 6975 return false; 6976 6977 break; 6978 } 6979 6980 default: 6981 return false; 6982 } 6983 6984 // base = Align(PC,4); 6985 uint64_t pc_value = ReadCoreReg (PC_REG, &success); 6986 if (!success) 6987 return false; 6988 uint64_t base = AlignPC (pc_value); 6989 6990 // address = if add then (base + imm32) else (base - imm32); 6991 addr_t address; 6992 if (add) 6993 address = base + imm32; 6994 else 6995 address = base - imm32; 6996 6997 // R[t] = SignExtend(MemU[address,1], 32); 6998 Register base_reg; 6999 base_reg.SetRegister (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC); 7000 7001 EmulateInstruction::Context context; 7002 context.type = eContextRegisterLoad; 7003 context.SetRegisterPlusOffset (base_reg, address - base); 7004 7005 uint64_t unsigned_data = MemURead (context, address, 1, 0, &success); 7006 if (!success) 7007 return false; 7008 7009 int64_t signed_data = llvm::SignExtend64<8>(unsigned_data); 7010 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, (uint64_t) signed_data)) 7011 return false; 7012 } 7013 return true; 7014} 7015 7016// LDRSB (register) calculates an address from a base register value and an offset register value, loadsa byte from 7017// memory, sign-extends it to form a 32-bit word, and writes it to a register. The offset register value can be 7018// shifted left by 0, 1, 2, or 3 bits. 7019bool 7020EmulateInstructionARM::EmulateLDRSBRegister (const uint32_t opcode, const ARMEncoding encoding) 7021{ 7022#if 0 7023 if ConditionPassed() then 7024 EncodingSpecificOperations(); NullCheckIfThumbEE(n); 7025 offset = Shift(R[m], shift_t, shift_n, APSR.C); 7026 offset_addr = if add then (R[n] + offset) else (R[n] - offset); 7027 address = if index then offset_addr else R[n]; 7028 R[t] = SignExtend(MemU[address,1], 32); 7029 if wback then R[n] = offset_addr; 7030#endif 7031 7032 bool success = false; 7033 7034 if (ConditionPassed(opcode)) 7035 { 7036 uint32_t t; 7037 uint32_t n; 7038 uint32_t m; 7039 bool index; 7040 bool add; 7041 bool wback; 7042 ARM_ShifterType shift_t; 7043 uint32_t shift_n; 7044 7045 // EncodingSpecificOperations(); NullCheckIfThumbEE(n); 7046 switch (encoding) 7047 { 7048 case eEncodingT1: 7049 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm); 7050 t = Bits32 (opcode, 2, 0); 7051 n = Bits32 (opcode, 5, 3); 7052 m = Bits32 (opcode, 8, 6); 7053 7054 // index = TRUE; add = TRUE; wback = FALSE; 7055 index = true; 7056 add = true; 7057 wback = false; 7058 7059 // (shift_t, shift_n) = (SRType_LSL, 0); 7060 shift_t = SRType_LSL; 7061 shift_n = 0; 7062 7063 break; 7064 7065 case eEncodingT2: 7066 // if Rt == '1111' then SEE PLI; 7067 // if Rn == '1111' then SEE LDRSB (literal); 7068 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm); 7069 t = Bits32 (opcode, 15, 12); 7070 n = Bits32 (opcode, 19, 16); 7071 m = Bits32 (opcode, 3, 0); 7072 7073 // index = TRUE; add = TRUE; wback = FALSE; 7074 index = true; 7075 add = true; 7076 wback = false; 7077 7078 // (shift_t, shift_n) = (SRType_LSL, UInt(imm2)); 7079 shift_t = SRType_LSL; 7080 shift_n = Bits32 (opcode, 5, 4); 7081 7082 // if t == 13 || BadReg(m) then UNPREDICTABLE; 7083 if ((t == 13) || BadReg (m)) 7084 return false; 7085 break; 7086 7087 case eEncodingA1: 7088 // if P == '0' && W == '1' then SEE LDRSBT; 7089 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm); 7090 t = Bits32 (opcode, 15, 12); 7091 n = Bits32 (opcode, 19, 16); 7092 m = Bits32 (opcode, 3, 0); 7093 7094 // index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1'); 7095 index = BitIsSet (opcode, 24); 7096 add = BitIsSet (opcode, 23); 7097 wback = BitIsClear (opcode, 24) || BitIsSet (opcode, 21); 7098 7099 // (shift_t, shift_n) = (SRType_LSL, 0); 7100 shift_t = SRType_LSL; 7101 shift_n = 0; 7102 7103 // if t == 15 || m == 15 then UNPREDICTABLE; 7104 if ((t == 15) || (m == 15)) 7105 return false; 7106 7107 // if wback && (n == 15 || n == t) then UNPREDICTABLE; 7108 if (wback && ((n == 15) || (n == t))) 7109 return false; 7110 break; 7111 7112 default: 7113 return false; 7114 } 7115 7116 uint64_t Rm = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success); 7117 if (!success) 7118 return false; 7119 7120 // offset = Shift(R[m], shift_t, shift_n, APSR.C); 7121 addr_t offset = Shift (Rm, shift_t, shift_n, APSR_C); 7122 7123 addr_t offset_addr; 7124 addr_t address; 7125 7126 // offset_addr = if add then (R[n] + offset) else (R[n] - offset); 7127 uint64_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success); 7128 if (!success) 7129 return false; 7130 7131 if (add) 7132 offset_addr = Rn + offset; 7133 else 7134 offset_addr = Rn - offset; 7135 7136 // address = if index then offset_addr else R[n]; 7137 if (index) 7138 address = offset_addr; 7139 else 7140 address = Rn; 7141 7142 // R[t] = SignExtend(MemU[address,1], 32); 7143 Register base_reg; 7144 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n); 7145 Register offset_reg; 7146 offset_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + m); 7147 7148 EmulateInstruction::Context context; 7149 context.type = eContextRegisterLoad; 7150 context.SetRegisterPlusIndirectOffset (base_reg, offset_reg); 7151 7152 uint64_t unsigned_data = MemURead (context, address, 1, 0, &success); 7153 if (!success) 7154 return false; 7155 7156 int64_t signed_data = llvm::SignExtend64<8>(unsigned_data); 7157 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, (uint64_t) signed_data)) 7158 return false; 7159 7160 // if wback then R[n] = offset_addr; 7161 if (wback) 7162 { 7163 context.type = eContextAdjustBaseRegister; 7164 context.SetAddress (offset_addr); 7165 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr)) 7166 return false; 7167 } 7168 } 7169 return true; 7170} 7171 7172// LDRSH (immediate) calculates an address from a base register value and an immediate offset, loads a halfword from 7173// memory, sign-extends it to form a 32-bit word, and writes it to a register. It can use offset, post-indexed, or 7174// pre-indexed addressing. 7175bool 7176EmulateInstructionARM::EmulateLDRSHImmediate (const uint32_t opcode, const ARMEncoding encoding) 7177{ 7178#if 0 7179 if ConditionPassed() then 7180 EncodingSpecificOperations(); NullCheckIfThumbEE(n); 7181 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32); 7182 address = if index then offset_addr else R[n]; 7183 data = MemU[address,2]; 7184 if wback then R[n] = offset_addr; 7185 if UnalignedSupport() || address<0> = '0' then 7186 R[t] = SignExtend(data, 32); 7187 else // Can only apply before ARMv7 7188 R[t] = bits(32) UNKNOWN; 7189#endif 7190 7191 bool success = false; 7192 7193 if (ConditionPassed(opcode)) 7194 { 7195 uint32_t t; 7196 uint32_t n; 7197 uint32_t imm32; 7198 bool index; 7199 bool add; 7200 bool wback; 7201 7202 // EncodingSpecificOperations(); NullCheckIfThumbEE(n); 7203 switch (encoding) 7204 { 7205 case eEncodingT1: 7206 // if Rn == '1111' then SEE LDRSH (literal); 7207 // if Rt == '1111' then SEE "Unallocated memory hints"; 7208 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32); 7209 t = Bits32 (opcode, 15, 12); 7210 n = Bits32 (opcode, 19, 16); 7211 imm32 = Bits32 (opcode, 11, 0); 7212 7213 // index = TRUE; add = TRUE; wback = FALSE; 7214 index = true; 7215 add = true; 7216 wback = false; 7217 7218 // if t == 13 then UNPREDICTABLE; 7219 if (t == 13) 7220 return false; 7221 7222 break; 7223 7224 case eEncodingT2: 7225 // if Rn == '1111' then SEE LDRSH (literal); 7226 // if Rt == '1111' && P == '1' && U == '0' && W == '0' then SEE "Unallocated memory hints"; 7227 // if P == '1' && U == '1' && W == '0' then SEE LDRSHT; 7228 // if P == '0' && W == '0' then UNDEFINED; 7229 if (BitIsClear (opcode, 10) && BitIsClear (opcode, 8)) 7230 return false; 7231 7232 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32); 7233 t = Bits32 (opcode, 15, 12); 7234 n = Bits32 (opcode, 19, 16); 7235 imm32 = Bits32 (opcode, 7, 0); 7236 7237 // index = (P == '1'); add = (U == '1'); wback = (W == '1'); 7238 index = BitIsSet (opcode, 10); 7239 add = BitIsSet (opcode, 9); 7240 wback = BitIsSet (opcode, 8); 7241 7242 // if BadReg(t) || (wback && n == t) then UNPREDICTABLE; 7243 if (BadReg (t) || (wback && (n == t))) 7244 return false; 7245 7246 break; 7247 7248 case eEncodingA1: 7249 { 7250 // if Rn == '1111' then SEE LDRSH (literal); 7251 // if P == '0' && W == '1' then SEE LDRSHT; 7252 // t == UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm4H:imm4L, 32); 7253 t = Bits32 (opcode, 15, 12); 7254 n = Bits32 (opcode, 19, 16); 7255 uint32_t imm4H = Bits32 (opcode, 11,8); 7256 uint32_t imm4L = Bits32 (opcode, 3, 0); 7257 imm32 = (imm4H << 4) | imm4L; 7258 7259 // index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1'); 7260 index = BitIsSet (opcode, 24); 7261 add = BitIsSet (opcode, 23); 7262 wback = BitIsClear (opcode, 24) || BitIsSet (opcode, 21); 7263 7264 // if t == 15 || (wback && n == t) then UNPREDICTABLE; 7265 if ((t == 15) || (wback && (n == t))) 7266 return false; 7267 7268 break; 7269 } 7270 7271 default: 7272 return false; 7273 } 7274 7275 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32); 7276 uint64_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success); 7277 if (!success) 7278 return false; 7279 7280 addr_t offset_addr; 7281 if (add) 7282 offset_addr = Rn + imm32; 7283 else 7284 offset_addr = Rn - imm32; 7285 7286 // address = if index then offset_addr else R[n]; 7287 addr_t address; 7288 if (index) 7289 address = offset_addr; 7290 else 7291 address = Rn; 7292 7293 // data = MemU[address,2]; 7294 Register base_reg; 7295 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n); 7296 7297 EmulateInstruction::Context context; 7298 context.type = eContextRegisterLoad; 7299 context.SetRegisterPlusOffset (base_reg, address - Rn); 7300 7301 uint64_t data = MemURead (context, address, 2, 0, &success); 7302 if (!success) 7303 return false; 7304 7305 // if wback then R[n] = offset_addr; 7306 if (wback) 7307 { 7308 context.type = eContextAdjustBaseRegister; 7309 context.SetAddress (offset_addr); 7310 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr)) 7311 return false; 7312 } 7313 7314 // if UnalignedSupport() || address<0> = '0' then 7315 if (UnalignedSupport() || BitIsClear (address, 0)) 7316 { 7317 // R[t] = SignExtend(data, 32); 7318 int64_t signed_data = llvm::SignExtend64<16>(data); 7319 context.type = eContextRegisterLoad; 7320 context.SetRegisterPlusOffset (base_reg, address - Rn); 7321 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, (uint64_t) signed_data)) 7322 return false; 7323 } 7324 else // Can only apply before ARMv7 7325 { 7326 // R[t] = bits(32) UNKNOWN; 7327 WriteBits32Unknown (t); 7328 } 7329 } 7330 return true; 7331} 7332 7333// LDRSH (literal) calculates an address from the PC value and an immediate offset, loads a halfword from memory, 7334// sign-extends it to from a 32-bit word, and writes it to a register. 7335bool 7336EmulateInstructionARM::EmulateLDRSHLiteral (const uint32_t opcode, const ARMEncoding encoding) 7337{ 7338#if 0 7339 if ConditionPassed() then 7340 EncodingSpecificOperations(); NullCheckIfThumbEE(15); 7341 base = Align(PC,4); 7342 address = if add then (base + imm32) else (base - imm32); 7343 data = MemU[address,2]; 7344 if UnalignedSupport() || address<0> = '0' then 7345 R[t] = SignExtend(data, 32); 7346 else // Can only apply before ARMv7 7347 R[t] = bits(32) UNKNOWN; 7348#endif 7349 7350 bool success = false; 7351 7352 if (ConditionPassed(opcode)) 7353 { 7354 uint32_t t; 7355 uint32_t imm32; 7356 bool add; 7357 7358 // EncodingSpecificOperations(); NullCheckIfThumbEE(15); 7359 switch (encoding) 7360 { 7361 case eEncodingT1: 7362 // if Rt == '1111' then SEE "Unallocated memory hints"; 7363 // t = UInt(Rt); imm32 = ZeroExtend(imm12, 32); add = (U == '1'); 7364 t = Bits32 (opcode, 15, 12); 7365 imm32 = Bits32 (opcode, 11, 0); 7366 add = BitIsSet (opcode, 23); 7367 7368 // if t == 13 then UNPREDICTABLE; 7369 if (t == 13) 7370 return false; 7371 7372 break; 7373 7374 case eEncodingA1: 7375 { 7376 // t == UInt(Rt); imm32 = ZeroExtend(imm4H:imm4L, 32); add = (U == '1'); 7377 t = Bits32 (opcode, 15, 12); 7378 uint32_t imm4H = Bits32 (opcode, 11, 8); 7379 uint32_t imm4L = Bits32 (opcode, 3, 0); 7380 imm32 = (imm4H << 4) | imm4L; 7381 add = BitIsSet (opcode, 23); 7382 7383 // if t == 15 then UNPREDICTABLE; 7384 if (t == 15) 7385 return false; 7386 7387 break; 7388 } 7389 default: 7390 return false; 7391 } 7392 7393 // base = Align(PC,4); 7394 uint64_t pc_value = ReadCoreReg (PC_REG, &success); 7395 if (!success) 7396 return false; 7397 7398 uint64_t base = AlignPC (pc_value); 7399 7400 addr_t address; 7401 // address = if add then (base + imm32) else (base - imm32); 7402 if (add) 7403 address = base + imm32; 7404 else 7405 address = base - imm32; 7406 7407 // data = MemU[address,2]; 7408 Register base_reg; 7409 base_reg.SetRegister (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC); 7410 7411 EmulateInstruction::Context context; 7412 context.type = eContextRegisterLoad; 7413 context.SetRegisterPlusOffset (base_reg, imm32); 7414 7415 uint64_t data = MemURead (context, address, 2, 0, &success); 7416 if (!success) 7417 return false; 7418 7419 // if UnalignedSupport() || address<0> = '0' then 7420 if (UnalignedSupport() || BitIsClear (address, 0)) 7421 { 7422 // R[t] = SignExtend(data, 32); 7423 int64_t signed_data = llvm::SignExtend64<16>(data); 7424 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, (uint64_t) signed_data)) 7425 return false; 7426 } 7427 else // Can only apply before ARMv7 7428 { 7429 // R[t] = bits(32) UNKNOWN; 7430 WriteBits32Unknown (t); 7431 } 7432 } 7433 return true; 7434} 7435 7436// LDRSH (register) calculates an address from a base register value and an offset register value, loads a halfword 7437// from memory, sign-extends it to form a 32-bit word, and writes it to a register. The offset register value can be 7438// shifted left by 0, 1, 2, or 3 bits. 7439bool 7440EmulateInstructionARM::EmulateLDRSHRegister (const uint32_t opcode, const ARMEncoding encoding) 7441{ 7442#if 0 7443 if ConditionPassed() then 7444 EncodingSpecificOperations(); NullCheckIfThumbEE(n); 7445 offset = Shift(R[m], shift_t, shift_n, APSR.C); 7446 offset_addr = if add then (R[n] + offset) else (R[n] - offset); 7447 address = if index then offset_addr else R[n]; 7448 data = MemU[address,2]; 7449 if wback then R[n] = offset_addr; 7450 if UnalignedSupport() || address<0> = '0' then 7451 R[t] = SignExtend(data, 32); 7452 else // Can only apply before ARMv7 7453 R[t] = bits(32) UNKNOWN; 7454#endif 7455 7456 bool success = false; 7457 7458 if (ConditionPassed(opcode)) 7459 { 7460 uint32_t t; 7461 uint32_t n; 7462 uint32_t m; 7463 bool index; 7464 bool add; 7465 bool wback; 7466 ARM_ShifterType shift_t; 7467 uint32_t shift_n; 7468 7469 // EncodingSpecificOperations(); NullCheckIfThumbEE(n); 7470 switch (encoding) 7471 { 7472 case eEncodingT1: 7473 // if CurrentInstrSet() == InstrSet_ThumbEE then SEE "Modified operation in ThumbEE"; 7474 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm); 7475 t = Bits32 (opcode, 2, 0); 7476 n = Bits32 (opcode, 5, 3); 7477 m = Bits32 (opcode, 8, 6); 7478 7479 // index = TRUE; add = TRUE; wback = FALSE; 7480 index = true; 7481 add = true; 7482 wback = false; 7483 7484 // (shift_t, shift_n) = (SRType_LSL, 0); 7485 shift_t = SRType_LSL; 7486 shift_n = 0; 7487 7488 break; 7489 7490 case eEncodingT2: 7491 // if Rn == '1111' then SEE LDRSH (literal); 7492 // if Rt == '1111' then SEE "Unallocated memory hints"; 7493 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm); 7494 t = Bits32 (opcode, 15, 12); 7495 n = Bits32 (opcode, 19, 16); 7496 m = Bits32 (opcode, 3, 0); 7497 7498 // index = TRUE; add = TRUE; wback = FALSE; 7499 index = true; 7500 add = true; 7501 wback = false; 7502 7503 // (shift_t, shift_n) = (SRType_LSL, UInt(imm2)); 7504 shift_t = SRType_LSL; 7505 shift_n = Bits32 (opcode, 5, 4); 7506 7507 // if t == 13 || BadReg(m) then UNPREDICTABLE; 7508 if ((t == 13) || BadReg (m)) 7509 return false; 7510 7511 break; 7512 7513 case eEncodingA1: 7514 // if P == '0' && W == '1' then SEE LDRSHT; 7515 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm); 7516 t = Bits32 (opcode, 15, 12); 7517 n = Bits32 (opcode, 19, 16); 7518 m = Bits32 (opcode, 3, 0); 7519 7520 // index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1'); 7521 index = BitIsSet (opcode, 24); 7522 add = BitIsSet (opcode, 23); 7523 wback = BitIsClear (opcode, 24) || BitIsSet (opcode, 21); 7524 7525 // (shift_t, shift_n) = (SRType_LSL, 0); 7526 shift_t = SRType_LSL; 7527 shift_n = 0; 7528 7529 // if t == 15 || m == 15 then UNPREDICTABLE; 7530 if ((t == 15) || (m == 15)) 7531 return false; 7532 7533 // if wback && (n == 15 || n == t) then UNPREDICTABLE; 7534 if (wback && ((n == 15) || (n == t))) 7535 return false; 7536 7537 break; 7538 7539 default: 7540 break; 7541 } 7542 7543 uint64_t Rm = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success); 7544 if (!success) 7545 return false; 7546 7547 uint64_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success); 7548 if (!success) 7549 return false; 7550 7551 // offset = Shift(R[m], shift_t, shift_n, APSR.C); 7552 addr_t offset = Shift (Rm, shift_t, shift_n, APSR_C); 7553 7554 addr_t offset_addr; 7555 addr_t address; 7556 7557 // offset_addr = if add then (R[n] + offset) else (R[n] - offset); 7558 if (add) 7559 offset_addr = Rn + offset; 7560 else 7561 offset_addr = Rn - offset; 7562 7563 // address = if index then offset_addr else R[n]; 7564 if (index) 7565 address = offset_addr; 7566 else 7567 address = Rn; 7568 7569 // data = MemU[address,2]; 7570 Register base_reg; 7571 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n); 7572 7573 Register offset_reg; 7574 offset_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + m); 7575 7576 EmulateInstruction::Context context; 7577 context.type = eContextRegisterLoad; 7578 context.SetRegisterPlusIndirectOffset (base_reg, offset_reg); 7579 7580 uint64_t data = MemURead (context, address, 2, 0, &success); 7581 if (!success) 7582 return false; 7583 7584 // if wback then R[n] = offset_addr; 7585 if (wback) 7586 { 7587 context.type = eContextAdjustBaseRegister; 7588 context.SetAddress (offset_addr); 7589 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr)) 7590 return false; 7591 } 7592 7593 // if UnalignedSupport() || address<0> = '0' then 7594 if (UnalignedSupport() || BitIsClear (address, 0)) 7595 { 7596 // R[t] = SignExtend(data, 32); 7597 context.type = eContextRegisterLoad; 7598 context.SetRegisterPlusIndirectOffset (base_reg, offset_reg); 7599 7600 int64_t signed_data = llvm::SignExtend64<16>(data); 7601 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, (uint64_t) signed_data)) 7602 return false; 7603 } 7604 else // Can only apply before ARMv7 7605 { 7606 // R[t] = bits(32) UNKNOWN; 7607 WriteBits32Unknown (t); 7608 } 7609 } 7610 return true; 7611} 7612 7613// SXTB extracts an 8-bit value from a register, sign-extends it to 32 bits, and writes the result to the destination 7614// register. You can specifiy a rotation by 0, 8, 16, or 24 bits before extracting the 8-bit value. 7615bool 7616EmulateInstructionARM::EmulateSXTB (const uint32_t opcode, const ARMEncoding encoding) 7617{ 7618#if 0 7619 if ConditionPassed() then 7620 EncodingSpecificOperations(); 7621 rotated = ROR(R[m], rotation); 7622 R[d] = SignExtend(rotated<7:0>, 32); 7623#endif 7624 7625 bool success = false; 7626 7627 if (ConditionPassed(opcode)) 7628 { 7629 uint32_t d; 7630 uint32_t m; 7631 uint32_t rotation; 7632 7633 // EncodingSpecificOperations(); 7634 switch (encoding) 7635 { 7636 case eEncodingT1: 7637 // d = UInt(Rd); m = UInt(Rm); rotation = 0; 7638 d = Bits32 (opcode, 2, 0); 7639 m = Bits32 (opcode, 5, 3); 7640 rotation = 0; 7641 7642 break; 7643 7644 case eEncodingT2: 7645 // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:'000'); 7646 d = Bits32 (opcode, 11, 8); 7647 m = Bits32 (opcode, 3, 0); 7648 rotation = Bits32 (opcode, 5, 4) << 3; 7649 7650 // if BadReg(d) || BadReg(m) then UNPREDICTABLE; 7651 if (BadReg (d) || BadReg (m)) 7652 return false; 7653 7654 break; 7655 7656 case eEncodingA1: 7657 // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:'000'); 7658 d = Bits32 (opcode, 15, 12); 7659 m = Bits32 (opcode, 3, 0); 7660 rotation = Bits32 (opcode, 11, 10) << 3; 7661 7662 // if d == 15 || m == 15 then UNPREDICTABLE; 7663 if ((d == 15) || (m == 15)) 7664 return false; 7665 7666 break; 7667 7668 default: 7669 return false; 7670 } 7671 7672 uint64_t Rm = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success); 7673 if (!success) 7674 return false; 7675 7676 // rotated = ROR(R[m], rotation); 7677 uint64_t rotated = ROR (Rm, rotation); 7678 7679 // R[d] = SignExtend(rotated<7:0>, 32); 7680 int64_t data = llvm::SignExtend64<8>(rotated); 7681 7682 Register source_reg; 7683 source_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + m); 7684 7685 EmulateInstruction::Context context; 7686 context.type = eContextRegisterLoad; 7687 context.SetRegister (source_reg); 7688 7689 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + d, (uint64_t) data)) 7690 return false; 7691 } 7692 return true; 7693} 7694 7695// SXTH extracts a 16-bit value from a register, sign-extends it to 32 bits, and writes the result to the destination 7696// register. You can specify a rotation by 0, 8, 16, or 24 bits before extracting the 16-bit value. 7697bool 7698EmulateInstructionARM::EmulateSXTH (const uint32_t opcode, const ARMEncoding encoding) 7699{ 7700#if 0 7701 if ConditionPassed() then 7702 EncodingSpecificOperations(); 7703 rotated = ROR(R[m], rotation); 7704 R[d] = SignExtend(rotated<15:0>, 32); 7705#endif 7706 7707 bool success = false; 7708 7709 if (ConditionPassed(opcode)) 7710 { 7711 uint32_t d; 7712 uint32_t m; 7713 uint32_t rotation; 7714 7715 // EncodingSpecificOperations(); 7716 switch (encoding) 7717 { 7718 case eEncodingT1: 7719 // d = UInt(Rd); m = UInt(Rm); rotation = 0; 7720 d = Bits32 (opcode, 2, 0); 7721 m = Bits32 (opcode, 5, 3); 7722 rotation = 0; 7723 7724 break; 7725 7726 case eEncodingT2: 7727 // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:'000'); 7728 d = Bits32 (opcode, 11, 8); 7729 m = Bits32 (opcode, 3, 0); 7730 rotation = Bits32 (opcode, 5, 4) << 3; 7731 7732 // if BadReg(d) || BadReg(m) then UNPREDICTABLE; 7733 if (BadReg (d) || BadReg (m)) 7734 return false; 7735 7736 break; 7737 7738 case eEncodingA1: 7739 // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:'000'); 7740 d = Bits32 (opcode, 15, 12); 7741 m = Bits32 (opcode, 3, 0); 7742 rotation = Bits32 (opcode, 11, 10) << 3; 7743 7744 // if d == 15 || m == 15 then UNPREDICTABLE; 7745 if ((d == 15) || (m == 15)) 7746 return false; 7747 7748 break; 7749 7750 default: 7751 return false; 7752 } 7753 7754 uint64_t Rm = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success); 7755 if (!success) 7756 return false; 7757 7758 // rotated = ROR(R[m], rotation); 7759 uint64_t rotated = ROR (Rm, rotation); 7760 7761 // R[d] = SignExtend(rotated<15:0>, 32); 7762 Register source_reg; 7763 source_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + m); 7764 7765 EmulateInstruction::Context context; 7766 context.type = eContextRegisterLoad; 7767 context.SetRegister (source_reg); 7768 7769 int64_t data = llvm::SignExtend64<16> (rotated); 7770 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + d, (uint64_t) data)) 7771 return false; 7772 } 7773 7774 return true; 7775} 7776 7777// UXTB extracts an 8-bit value from a register, zero-extneds it to 32 bits, and writes the result to the destination 7778// register. You can specify a rotation by 0, 8, 16, or 24 bits before extracting the 8-bit value. 7779bool 7780EmulateInstructionARM::EmulateUXTB (const uint32_t opcode, const ARMEncoding encoding) 7781{ 7782#if 0 7783 if ConditionPassed() then 7784 EncodingSpecificOperations(); 7785 rotated = ROR(R[m], rotation); 7786 R[d] = ZeroExtend(rotated<7:0>, 32); 7787#endif 7788 7789 bool success = false; 7790 7791 if (ConditionPassed(opcode)) 7792 { 7793 uint32_t d; 7794 uint32_t m; 7795 uint32_t rotation; 7796 7797 // EncodingSpecificOperations(); 7798 switch (encoding) 7799 { 7800 case eEncodingT1: 7801 // d = UInt(Rd); m = UInt(Rm); rotation = 0; 7802 d = Bits32 (opcode, 2, 0); 7803 m = Bits32 (opcode, 5, 3); 7804 rotation = 0; 7805 7806 break; 7807 7808 case eEncodingT2: 7809 // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:'000'); 7810 d = Bits32 (opcode, 11, 8); 7811 m = Bits32 (opcode, 3, 0); 7812 rotation = Bits32 (opcode, 5, 4) << 3; 7813 7814 // if BadReg(d) || BadReg(m) then UNPREDICTABLE; 7815 if (BadReg (d) || BadReg (m)) 7816 return false; 7817 7818 break; 7819 7820 case eEncodingA1: 7821 // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:'000'); 7822 d = Bits32 (opcode, 15, 12); 7823 m = Bits32 (opcode, 3, 0); 7824 rotation = Bits32 (opcode, 11, 10) << 3; 7825 7826 // if d == 15 || m == 15 then UNPREDICTABLE; 7827 if ((d == 15) || (m == 15)) 7828 return false; 7829 7830 break; 7831 7832 default: 7833 return false; 7834 } 7835 7836 uint64_t Rm = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success); 7837 if (!success) 7838 return false; 7839 7840 // rotated = ROR(R[m], rotation); 7841 uint64_t rotated = ROR (Rm, rotation); 7842 7843 // R[d] = ZeroExtend(rotated<7:0>, 32); 7844 Register source_reg; 7845 source_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + m); 7846 7847 EmulateInstruction::Context context; 7848 context.type = eContextRegisterLoad; 7849 context.SetRegister (source_reg); 7850 7851 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + d, Bits32 (rotated, 7, 0))) 7852 return false; 7853 } 7854 return true; 7855} 7856 7857// UXTH extracts a 16-bit value from a register, zero-extends it to 32 bits, and writes the result to the destination 7858// register. You can specify a rotation by 0, 8, 16, or 24 bits before extracting the 16-bit value. 7859bool 7860EmulateInstructionARM::EmulateUXTH (const uint32_t opcode, const ARMEncoding encoding) 7861{ 7862#if 0 7863 if ConditionPassed() then 7864 EncodingSpecificOperations(); 7865 rotated = ROR(R[m], rotation); 7866 R[d] = ZeroExtend(rotated<15:0>, 32); 7867#endif 7868 7869 bool success = false; 7870 7871 if (ConditionPassed(opcode)) 7872 { 7873 uint32_t d; 7874 uint32_t m; 7875 uint32_t rotation; 7876 7877 switch (encoding) 7878 { 7879 case eEncodingT1: 7880 // d = UInt(Rd); m = UInt(Rm); rotation = 0; 7881 d = Bits32 (opcode, 2, 0); 7882 m = Bits32 (opcode, 5, 3); 7883 rotation = 0; 7884 7885 break; 7886 7887 case eEncodingT2: 7888 // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:'000'); 7889 d = Bits32 (opcode, 11, 8); 7890 m = Bits32 (opcode, 3, 0); 7891 rotation = Bits32 (opcode, 5, 4) << 3; 7892 7893 // if BadReg(d) || BadReg(m) then UNPREDICTABLE; 7894 if (BadReg (d) || BadReg (m)) 7895 return false; 7896 7897 break; 7898 7899 case eEncodingA1: 7900 // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:'000'); 7901 d = Bits32 (opcode, 15, 12); 7902 m = Bits32 (opcode, 3, 0); 7903 rotation = Bits32 (opcode, 11, 10) << 3; 7904 7905 // if d == 15 || m == 15 then UNPREDICTABLE; 7906 if ((d == 15) || (m == 15)) 7907 return false; 7908 7909 break; 7910 7911 default: 7912 return false; 7913 } 7914 7915 uint64_t Rm = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success); 7916 if (!success) 7917 return false; 7918 7919 // rotated = ROR(R[m], rotation); 7920 uint64_t rotated = ROR (Rm, rotation); 7921 7922 // R[d] = ZeroExtend(rotated<15:0>, 32); 7923 Register source_reg; 7924 source_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + m); 7925 7926 EmulateInstruction::Context context; 7927 context.type = eContextRegisterLoad; 7928 context.SetRegister (source_reg); 7929 7930 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + d, Bits32 (rotated, 15, 0))) 7931 return false; 7932 } 7933 return true; 7934} 7935 7936// RFE (Return From Exception) loads the PC and the CPSR from the word at the specified address and the following 7937// word respectively. 7938bool 7939EmulateInstructionARM::EmulateRFE (const uint32_t opcode, const ARMEncoding encoding) 7940{ 7941#if 0 7942 if ConditionPassed() then 7943 EncodingSpecificOperations(); 7944 if !CurrentModeIsPrivileged() || CurrentInstrSet() == InstrSet_ThumbEE then 7945 UNPREDICTABLE; 7946 else 7947 address = if increment then R[n] else R[n]-8; 7948 if wordhigher then address = address+4; 7949 CPSRWriteByInstr(MemA[address+4,4], '1111', TRUE); 7950 BranchWritePC(MemA[address,4]); 7951 if wback then R[n] = if increment then R[n]+8 else R[n]-8; 7952#endif 7953 7954 bool success = false; 7955 7956 if (ConditionPassed(opcode)) 7957 { 7958 uint32_t n; 7959 bool wback; 7960 bool increment; 7961 bool wordhigher; 7962 7963 // EncodingSpecificOperations(); 7964 switch (encoding) 7965 { 7966 case eEncodingT1: 7967 // n = UInt(Rn); wback = (W == '1'); increment = FALSE; wordhigher = FALSE; 7968 n = Bits32 (opcode, 19, 16); 7969 wback = BitIsSet (opcode, 21); 7970 increment = false; 7971 wordhigher = false; 7972 7973 // if n == 15 then UNPREDICTABLE; 7974 if (n == 15) 7975 return false; 7976 7977 // if InITBlock() && !LastInITBlock() then UNPREDICTABLE; 7978 if (InITBlock() && !LastInITBlock()) 7979 return false; 7980 7981 break; 7982 7983 case eEncodingT2: 7984 // n = UInt(Rn); wback = (W == '1'); increment = TRUE; wordhigher = FALSE; 7985 n = Bits32 (opcode, 19, 16); 7986 wback = BitIsSet (opcode, 21); 7987 increment = true; 7988 wordhigher = false; 7989 7990 // if n == 15 then UNPREDICTABLE; 7991 if (n == 15) 7992 return false; 7993 7994 // if InITBlock() && !LastInITBlock() then UNPREDICTABLE; 7995 if (InITBlock() && !LastInITBlock()) 7996 return false; 7997 7998 break; 7999 8000 case eEncodingA1: 8001 // n = UInt(Rn); 8002 n = Bits32 (opcode, 19, 16); 8003 8004 // wback = (W == '1'); inc = (U == '1'); wordhigher = (P == U); 8005 wback = BitIsSet (opcode, 21); 8006 increment = BitIsSet (opcode, 23); 8007 wordhigher = (Bit32 (opcode, 24) == Bit32 (opcode, 23)); 8008 8009 // if n == 15 then UNPREDICTABLE; 8010 if (n == 15) 8011 return false; 8012 8013 break; 8014 8015 default: 8016 return false; 8017 } 8018 8019 // if !CurrentModeIsPrivileged() || CurrentInstrSet() == InstrSet_ThumbEE then 8020 if (!CurrentModeIsPrivileged ()) 8021 // UNPREDICTABLE; 8022 return false; 8023 else 8024 { 8025 uint64_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success); 8026 if (!success) 8027 return false; 8028 8029 addr_t address; 8030 // address = if increment then R[n] else R[n]-8; 8031 if (increment) 8032 address = Rn; 8033 else 8034 address = Rn - 8; 8035 8036 // if wordhigher then address = address+4; 8037 if (wordhigher) 8038 address = address + 4; 8039 8040 // CPSRWriteByInstr(MemA[address+4,4], '1111', TRUE); 8041 Register base_reg; 8042 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n); 8043 8044 EmulateInstruction::Context context; 8045 context.type = eContextReturnFromException; 8046 context.SetRegisterPlusOffset (base_reg, address - Rn); 8047 8048 uint64_t data = MemARead (context, address + 4, 4, 0, &success); 8049 if (!success) 8050 return false; 8051 8052 CPSRWriteByInstr (data, 15, true); 8053 8054 // BranchWritePC(MemA[address,4]); 8055 uint64_t data2 = MemARead (context, address, 4, 0, &success); 8056 if (!success) 8057 return false; 8058 8059 BranchWritePC (context, data2); 8060 8061 // if wback then R[n] = if increment then R[n]+8 else R[n]-8; 8062 if (wback) 8063 { 8064 context.type = eContextAdjustBaseRegister; 8065 if (increment) 8066 { 8067 context.SetOffset (8); 8068 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, Rn + 8)) 8069 return false; 8070 } 8071 else 8072 { 8073 context.SetOffset (-8); 8074 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, Rn - 8)) 8075 return false; 8076 } 8077 } // if wback 8078 } 8079 } // if ConditionPassed() 8080 return true; 8081} 8082 8083// Bitwise Exclusive OR (immediate) performs a bitwise exclusive OR of a register value and an immediate value, 8084// and writes the result to the destination register. It can optionally update the condition flags based on 8085// the result. 8086bool 8087EmulateInstructionARM::EmulateEORImm (const uint32_t opcode, const ARMEncoding encoding) 8088{ 8089#if 0 8090 // ARM pseudo code... 8091 if ConditionPassed() then 8092 EncodingSpecificOperations(); 8093 result = R[n] EOR imm32; 8094 if d == 15 then // Can only occur for ARM encoding 8095 ALUWritePC(result); // setflags is always FALSE here 8096 else 8097 R[d] = result; 8098 if setflags then 8099 APSR.N = result<31>; 8100 APSR.Z = IsZeroBit(result); 8101 APSR.C = carry; 8102 // APSR.V unchanged 8103#endif 8104 8105 bool success = false; 8106 8107 if (ConditionPassed(opcode)) 8108 { 8109 uint32_t Rd, Rn; 8110 uint32_t imm32; // the immediate value to be ORed to the value obtained from Rn 8111 bool setflags; 8112 uint32_t carry; // the carry bit after ARM/Thumb Expand operation 8113 switch (encoding) 8114 { 8115 case eEncodingT1: 8116 Rd = Bits32(opcode, 11, 8); 8117 Rn = Bits32(opcode, 19, 16); 8118 setflags = BitIsSet(opcode, 20); 8119 imm32 = ThumbExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C) 8120 // if Rd == '1111' && S == '1' then SEE TEQ (immediate); 8121 if (Rd == 15 && setflags) 8122 return EmulateTEQImm (opcode, eEncodingT1); 8123 if (Rd == 13 || (Rd == 15 && !setflags) || BadReg(Rn)) 8124 return false; 8125 break; 8126 case eEncodingA1: 8127 Rd = Bits32(opcode, 15, 12); 8128 Rn = Bits32(opcode, 19, 16); 8129 setflags = BitIsSet(opcode, 20); 8130 imm32 = ARMExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ARMExpandImm(imm12, APSR.C) 8131 8132 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions; 8133 if (Rd == 15 && setflags) 8134 return EmulateSUBSPcLrEtc (opcode, encoding); 8135 break; 8136 default: 8137 return false; 8138 } 8139 8140 // Read the first operand. 8141 uint32_t val1 = ReadCoreReg(Rn, &success); 8142 if (!success) 8143 return false; 8144 8145 uint32_t result = val1 ^ imm32; 8146 8147 EmulateInstruction::Context context; 8148 context.type = EmulateInstruction::eContextImmediate; 8149 context.SetNoArgs (); 8150 8151 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry)) 8152 return false; 8153 } 8154 return true; 8155} 8156 8157// Bitwise Exclusive OR (register) performs a bitwise exclusive OR of a register value and an 8158// optionally-shifted register value, and writes the result to the destination register. 8159// It can optionally update the condition flags based on the result. 8160bool 8161EmulateInstructionARM::EmulateEORReg (const uint32_t opcode, const ARMEncoding encoding) 8162{ 8163#if 0 8164 // ARM pseudo code... 8165 if ConditionPassed() then 8166 EncodingSpecificOperations(); 8167 (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C); 8168 result = R[n] EOR shifted; 8169 if d == 15 then // Can only occur for ARM encoding 8170 ALUWritePC(result); // setflags is always FALSE here 8171 else 8172 R[d] = result; 8173 if setflags then 8174 APSR.N = result<31>; 8175 APSR.Z = IsZeroBit(result); 8176 APSR.C = carry; 8177 // APSR.V unchanged 8178#endif 8179 8180 bool success = false; 8181 8182 if (ConditionPassed(opcode)) 8183 { 8184 uint32_t Rd, Rn, Rm; 8185 ARM_ShifterType shift_t; 8186 uint32_t shift_n; // the shift applied to the value read from Rm 8187 bool setflags; 8188 uint32_t carry; 8189 switch (encoding) 8190 { 8191 case eEncodingT1: 8192 Rd = Rn = Bits32(opcode, 2, 0); 8193 Rm = Bits32(opcode, 5, 3); 8194 setflags = !InITBlock(); 8195 shift_t = SRType_LSL; 8196 shift_n = 0; 8197 break; 8198 case eEncodingT2: 8199 Rd = Bits32(opcode, 11, 8); 8200 Rn = Bits32(opcode, 19, 16); 8201 Rm = Bits32(opcode, 3, 0); 8202 setflags = BitIsSet(opcode, 20); 8203 shift_n = DecodeImmShiftThumb(opcode, shift_t); 8204 // if Rd == '1111' && S == '1' then SEE TEQ (register); 8205 if (Rd == 15 && setflags) 8206 return EmulateTEQReg (opcode, eEncodingT1); 8207 if (Rd == 13 || (Rd == 15 && !setflags) || BadReg(Rn) || BadReg(Rm)) 8208 return false; 8209 break; 8210 case eEncodingA1: 8211 Rd = Bits32(opcode, 15, 12); 8212 Rn = Bits32(opcode, 19, 16); 8213 Rm = Bits32(opcode, 3, 0); 8214 setflags = BitIsSet(opcode, 20); 8215 shift_n = DecodeImmShiftARM(opcode, shift_t); 8216 8217 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions; 8218 if (Rd == 15 && setflags) 8219 return EmulateSUBSPcLrEtc (opcode, encoding); 8220 break; 8221 default: 8222 return false; 8223 } 8224 8225 // Read the first operand. 8226 uint32_t val1 = ReadCoreReg(Rn, &success); 8227 if (!success) 8228 return false; 8229 8230 // Read the second operand. 8231 uint32_t val2 = ReadCoreReg(Rm, &success); 8232 if (!success) 8233 return false; 8234 8235 uint32_t shifted = Shift_C(val2, shift_t, shift_n, APSR_C, carry); 8236 uint32_t result = val1 ^ shifted; 8237 8238 EmulateInstruction::Context context; 8239 context.type = EmulateInstruction::eContextImmediate; 8240 context.SetNoArgs (); 8241 8242 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry)) 8243 return false; 8244 } 8245 return true; 8246} 8247 8248// Bitwise OR (immediate) performs a bitwise (inclusive) OR of a register value and an immediate value, and 8249// writes the result to the destination register. It can optionally update the condition flags based 8250// on the result. 8251bool 8252EmulateInstructionARM::EmulateORRImm (const uint32_t opcode, const ARMEncoding encoding) 8253{ 8254#if 0 8255 // ARM pseudo code... 8256 if ConditionPassed() then 8257 EncodingSpecificOperations(); 8258 result = R[n] OR imm32; 8259 if d == 15 then // Can only occur for ARM encoding 8260 ALUWritePC(result); // setflags is always FALSE here 8261 else 8262 R[d] = result; 8263 if setflags then 8264 APSR.N = result<31>; 8265 APSR.Z = IsZeroBit(result); 8266 APSR.C = carry; 8267 // APSR.V unchanged 8268#endif 8269 8270 bool success = false; 8271 8272 if (ConditionPassed(opcode)) 8273 { 8274 uint32_t Rd, Rn; 8275 uint32_t imm32; // the immediate value to be ORed to the value obtained from Rn 8276 bool setflags; 8277 uint32_t carry; // the carry bit after ARM/Thumb Expand operation 8278 switch (encoding) 8279 { 8280 case eEncodingT1: 8281 Rd = Bits32(opcode, 11, 8); 8282 Rn = Bits32(opcode, 19, 16); 8283 setflags = BitIsSet(opcode, 20); 8284 imm32 = ThumbExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C) 8285 // if Rn == '1111' then SEE MOV (immediate); 8286 if (Rn == 15) 8287 return EmulateMOVRdImm (opcode, eEncodingT2); 8288 if (BadReg(Rd) || Rn == 13) 8289 return false; 8290 break; 8291 case eEncodingA1: 8292 Rd = Bits32(opcode, 15, 12); 8293 Rn = Bits32(opcode, 19, 16); 8294 setflags = BitIsSet(opcode, 20); 8295 imm32 = ARMExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ARMExpandImm(imm12, APSR.C) 8296 8297 if (Rd == 15 && setflags) 8298 return EmulateSUBSPcLrEtc (opcode, encoding); 8299 break; 8300 default: 8301 return false; 8302 } 8303 8304 // Read the first operand. 8305 uint32_t val1 = ReadCoreReg(Rn, &success); 8306 if (!success) 8307 return false; 8308 8309 uint32_t result = val1 | imm32; 8310 8311 EmulateInstruction::Context context; 8312 context.type = EmulateInstruction::eContextImmediate; 8313 context.SetNoArgs (); 8314 8315 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry)) 8316 return false; 8317 } 8318 return true; 8319} 8320 8321// Bitwise OR (register) performs a bitwise (inclusive) OR of a register value and an optionally-shifted register 8322// value, and writes the result to the destination register. It can optionally update the condition flags based 8323// on the result. 8324bool 8325EmulateInstructionARM::EmulateORRReg (const uint32_t opcode, const ARMEncoding encoding) 8326{ 8327#if 0 8328 // ARM pseudo code... 8329 if ConditionPassed() then 8330 EncodingSpecificOperations(); 8331 (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C); 8332 result = R[n] OR shifted; 8333 if d == 15 then // Can only occur for ARM encoding 8334 ALUWritePC(result); // setflags is always FALSE here 8335 else 8336 R[d] = result; 8337 if setflags then 8338 APSR.N = result<31>; 8339 APSR.Z = IsZeroBit(result); 8340 APSR.C = carry; 8341 // APSR.V unchanged 8342#endif 8343 8344 bool success = false; 8345 8346 if (ConditionPassed(opcode)) 8347 { 8348 uint32_t Rd, Rn, Rm; 8349 ARM_ShifterType shift_t; 8350 uint32_t shift_n; // the shift applied to the value read from Rm 8351 bool setflags; 8352 uint32_t carry; 8353 switch (encoding) 8354 { 8355 case eEncodingT1: 8356 Rd = Rn = Bits32(opcode, 2, 0); 8357 Rm = Bits32(opcode, 5, 3); 8358 setflags = !InITBlock(); 8359 shift_t = SRType_LSL; 8360 shift_n = 0; 8361 break; 8362 case eEncodingT2: 8363 Rd = Bits32(opcode, 11, 8); 8364 Rn = Bits32(opcode, 19, 16); 8365 Rm = Bits32(opcode, 3, 0); 8366 setflags = BitIsSet(opcode, 20); 8367 shift_n = DecodeImmShiftThumb(opcode, shift_t); 8368 // if Rn == '1111' then SEE MOV (register); 8369 if (Rn == 15) 8370 return EmulateMOVRdRm (opcode, eEncodingT3); 8371 if (BadReg(Rd) || Rn == 13 || BadReg(Rm)) 8372 return false; 8373 break; 8374 case eEncodingA1: 8375 Rd = Bits32(opcode, 15, 12); 8376 Rn = Bits32(opcode, 19, 16); 8377 Rm = Bits32(opcode, 3, 0); 8378 setflags = BitIsSet(opcode, 20); 8379 shift_n = DecodeImmShiftARM(opcode, shift_t); 8380 8381 if (Rd == 15 && setflags) 8382 return EmulateSUBSPcLrEtc (opcode, encoding); 8383 break; 8384 default: 8385 return false; 8386 } 8387 8388 // Read the first operand. 8389 uint32_t val1 = ReadCoreReg(Rn, &success); 8390 if (!success) 8391 return false; 8392 8393 // Read the second operand. 8394 uint32_t val2 = ReadCoreReg(Rm, &success); 8395 if (!success) 8396 return false; 8397 8398 uint32_t shifted = Shift_C(val2, shift_t, shift_n, APSR_C, carry); 8399 uint32_t result = val1 | shifted; 8400 8401 EmulateInstruction::Context context; 8402 context.type = EmulateInstruction::eContextImmediate; 8403 context.SetNoArgs (); 8404 8405 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry)) 8406 return false; 8407 } 8408 return true; 8409} 8410 8411// Reverse Subtract (immediate) subtracts a register value from an immediate value, and writes the result to 8412// the destination register. It can optionally update the condition flags based on the result. 8413bool 8414EmulateInstructionARM::EmulateRSBImm (const uint32_t opcode, const ARMEncoding encoding) 8415{ 8416#if 0 8417 // ARM pseudo code... 8418 if ConditionPassed() then 8419 EncodingSpecificOperations(); 8420 (result, carry, overflow) = AddWithCarry(NOT(R[n]), imm32, '1'); 8421 if d == 15 then // Can only occur for ARM encoding 8422 ALUWritePC(result); // setflags is always FALSE here 8423 else 8424 R[d] = result; 8425 if setflags then 8426 APSR.N = result<31>; 8427 APSR.Z = IsZeroBit(result); 8428 APSR.C = carry; 8429 APSR.V = overflow; 8430#endif 8431 8432 bool success = false; 8433 8434 uint32_t Rd; // the destination register 8435 uint32_t Rn; // the first operand 8436 bool setflags; 8437 uint32_t imm32; // the immediate value to be added to the value obtained from Rn 8438 switch (encoding) { 8439 case eEncodingT1: 8440 Rd = Bits32(opcode, 2, 0); 8441 Rn = Bits32(opcode, 5, 3); 8442 setflags = !InITBlock(); 8443 imm32 = 0; 8444 break; 8445 case eEncodingT2: 8446 Rd = Bits32(opcode, 11, 8); 8447 Rn = Bits32(opcode, 19, 16); 8448 setflags = BitIsSet(opcode, 20); 8449 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8) 8450 if (BadReg(Rd) || BadReg(Rn)) 8451 return false; 8452 break; 8453 case eEncodingA1: 8454 Rd = Bits32(opcode, 15, 12); 8455 Rn = Bits32(opcode, 19, 16); 8456 setflags = BitIsSet(opcode, 20); 8457 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12) 8458 8459 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions; 8460 if (Rd == 15 && setflags) 8461 return EmulateSUBSPcLrEtc (opcode, encoding); 8462 break; 8463 default: 8464 return false; 8465 } 8466 // Read the register value from the operand register Rn. 8467 uint32_t reg_val = ReadCoreReg(Rn, &success); 8468 if (!success) 8469 return false; 8470 8471 AddWithCarryResult res = AddWithCarry(~reg_val, imm32, 1); 8472 8473 EmulateInstruction::Context context; 8474 context.type = EmulateInstruction::eContextImmediate; 8475 context.SetNoArgs (); 8476 8477 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow)) 8478 return false; 8479 8480 return true; 8481} 8482 8483// Reverse Subtract (register) subtracts a register value from an optionally-shifted register value, and writes the 8484// result to the destination register. It can optionally update the condition flags based on the result. 8485bool 8486EmulateInstructionARM::EmulateRSBReg (const uint32_t opcode, const ARMEncoding encoding) 8487{ 8488#if 0 8489 // ARM pseudo code... 8490 if ConditionPassed() then 8491 EncodingSpecificOperations(); 8492 shifted = Shift(R[m], shift_t, shift_n, APSR.C); 8493 (result, carry, overflow) = AddWithCarry(NOT(R[n]), shifted, '1'); 8494 if d == 15 then // Can only occur for ARM encoding 8495 ALUWritePC(result); // setflags is always FALSE here 8496 else 8497 R[d] = result; 8498 if setflags then 8499 APSR.N = result<31>; 8500 APSR.Z = IsZeroBit(result); 8501 APSR.C = carry; 8502 APSR.V = overflow; 8503#endif 8504 8505 bool success = false; 8506 8507 uint32_t Rd; // the destination register 8508 uint32_t Rn; // the first operand 8509 uint32_t Rm; // the second operand 8510 bool setflags; 8511 ARM_ShifterType shift_t; 8512 uint32_t shift_n; // the shift applied to the value read from Rm 8513 switch (encoding) { 8514 case eEncodingT1: 8515 Rd = Bits32(opcode, 11, 8); 8516 Rn = Bits32(opcode, 19, 16); 8517 Rm = Bits32(opcode, 3, 0); 8518 setflags = BitIsSet(opcode, 20); 8519 shift_n = DecodeImmShiftThumb(opcode, shift_t); 8520 // if (BadReg(d) || BadReg(m)) then UNPREDICTABLE; 8521 if (BadReg(Rd) || BadReg(Rn) || BadReg(Rm)) 8522 return false; 8523 break; 8524 case eEncodingA1: 8525 Rd = Bits32(opcode, 15, 12); 8526 Rn = Bits32(opcode, 19, 16); 8527 Rm = Bits32(opcode, 3, 0); 8528 setflags = BitIsSet(opcode, 20); 8529 shift_n = DecodeImmShiftARM(opcode, shift_t); 8530 8531 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions; 8532 if (Rd == 15 && setflags) 8533 return EmulateSUBSPcLrEtc (opcode, encoding); 8534 break; 8535 default: 8536 return false; 8537 } 8538 // Read the register value from register Rn. 8539 uint32_t val1 = ReadCoreReg(Rn, &success); 8540 if (!success) 8541 return false; 8542 8543 // Read the register value from register Rm. 8544 uint32_t val2 = ReadCoreReg(Rm, &success); 8545 if (!success) 8546 return false; 8547 8548 uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C); 8549 AddWithCarryResult res = AddWithCarry(~val1, shifted, 1); 8550 8551 EmulateInstruction::Context context; 8552 context.type = EmulateInstruction::eContextImmediate; 8553 context.SetNoArgs(); 8554 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow)) 8555 return false; 8556 8557 return true; 8558} 8559 8560// Reverse Subtract with Carry (immediate) subtracts a register value and the value of NOT (Carry flag) from 8561// an immediate value, and writes the result to the destination register. It can optionally update the condition 8562// flags based on the result. 8563bool 8564EmulateInstructionARM::EmulateRSCImm (const uint32_t opcode, const ARMEncoding encoding) 8565{ 8566#if 0 8567 // ARM pseudo code... 8568 if ConditionPassed() then 8569 EncodingSpecificOperations(); 8570 (result, carry, overflow) = AddWithCarry(NOT(R[n]), imm32, APSR.C); 8571 if d == 15 then 8572 ALUWritePC(result); // setflags is always FALSE here 8573 else 8574 R[d] = result; 8575 if setflags then 8576 APSR.N = result<31>; 8577 APSR.Z = IsZeroBit(result); 8578 APSR.C = carry; 8579 APSR.V = overflow; 8580#endif 8581 8582 bool success = false; 8583 8584 uint32_t Rd; // the destination register 8585 uint32_t Rn; // the first operand 8586 bool setflags; 8587 uint32_t imm32; // the immediate value to be added to the value obtained from Rn 8588 switch (encoding) { 8589 case eEncodingA1: 8590 Rd = Bits32(opcode, 15, 12); 8591 Rn = Bits32(opcode, 19, 16); 8592 setflags = BitIsSet(opcode, 20); 8593 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12) 8594 8595 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions; 8596 if (Rd == 15 && setflags) 8597 return EmulateSUBSPcLrEtc (opcode, encoding); 8598 break; 8599 default: 8600 return false; 8601 } 8602 // Read the register value from the operand register Rn. 8603 uint32_t reg_val = ReadCoreReg(Rn, &success); 8604 if (!success) 8605 return false; 8606 8607 AddWithCarryResult res = AddWithCarry(~reg_val, imm32, APSR_C); 8608 8609 EmulateInstruction::Context context; 8610 context.type = EmulateInstruction::eContextImmediate; 8611 context.SetNoArgs (); 8612 8613 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow)) 8614 return false; 8615 8616 return true; 8617} 8618 8619// Reverse Subtract with Carry (register) subtracts a register value and the value of NOT (Carry flag) from an 8620// optionally-shifted register value, and writes the result to the destination register. It can optionally update the 8621// condition flags based on the result. 8622bool 8623EmulateInstructionARM::EmulateRSCReg (const uint32_t opcode, const ARMEncoding encoding) 8624{ 8625#if 0 8626 // ARM pseudo code... 8627 if ConditionPassed() then 8628 EncodingSpecificOperations(); 8629 shifted = Shift(R[m], shift_t, shift_n, APSR.C); 8630 (result, carry, overflow) = AddWithCarry(NOT(R[n]), shifted, APSR.C); 8631 if d == 15 then 8632 ALUWritePC(result); // setflags is always FALSE here 8633 else 8634 R[d] = result; 8635 if setflags then 8636 APSR.N = result<31>; 8637 APSR.Z = IsZeroBit(result); 8638 APSR.C = carry; 8639 APSR.V = overflow; 8640#endif 8641 8642 bool success = false; 8643 8644 uint32_t Rd; // the destination register 8645 uint32_t Rn; // the first operand 8646 uint32_t Rm; // the second operand 8647 bool setflags; 8648 ARM_ShifterType shift_t; 8649 uint32_t shift_n; // the shift applied to the value read from Rm 8650 switch (encoding) { 8651 case eEncodingA1: 8652 Rd = Bits32(opcode, 15, 12); 8653 Rn = Bits32(opcode, 19, 16); 8654 Rm = Bits32(opcode, 3, 0); 8655 setflags = BitIsSet(opcode, 20); 8656 shift_n = DecodeImmShiftARM(opcode, shift_t); 8657 8658 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions; 8659 if (Rd == 15 && setflags) 8660 return EmulateSUBSPcLrEtc (opcode, encoding); 8661 break; 8662 default: 8663 return false; 8664 } 8665 // Read the register value from register Rn. 8666 uint32_t val1 = ReadCoreReg(Rn, &success); 8667 if (!success) 8668 return false; 8669 8670 // Read the register value from register Rm. 8671 uint32_t val2 = ReadCoreReg(Rm, &success); 8672 if (!success) 8673 return false; 8674 8675 uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C); 8676 AddWithCarryResult res = AddWithCarry(~val1, shifted, APSR_C); 8677 8678 EmulateInstruction::Context context; 8679 context.type = EmulateInstruction::eContextImmediate; 8680 context.SetNoArgs(); 8681 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow)) 8682 return false; 8683 8684 return true; 8685} 8686 8687// Subtract with Carry (immediate) subtracts an immediate value and the value of 8688// NOT (Carry flag) from a register value, and writes the result to the destination register. 8689// It can optionally update the condition flags based on the result. 8690bool 8691EmulateInstructionARM::EmulateSBCImm (const uint32_t opcode, const ARMEncoding encoding) 8692{ 8693#if 0 8694 // ARM pseudo code... 8695 if ConditionPassed() then 8696 EncodingSpecificOperations(); 8697 (result, carry, overflow) = AddWithCarry(R[n], NOT(imm32), APSR.C); 8698 if d == 15 then // Can only occur for ARM encoding 8699 ALUWritePC(result); // setflags is always FALSE here 8700 else 8701 R[d] = result; 8702 if setflags then 8703 APSR.N = result<31>; 8704 APSR.Z = IsZeroBit(result); 8705 APSR.C = carry; 8706 APSR.V = overflow; 8707#endif 8708 8709 bool success = false; 8710 8711 uint32_t Rd; // the destination register 8712 uint32_t Rn; // the first operand 8713 bool setflags; 8714 uint32_t imm32; // the immediate value to be added to the value obtained from Rn 8715 switch (encoding) { 8716 case eEncodingT1: 8717 Rd = Bits32(opcode, 11, 8); 8718 Rn = Bits32(opcode, 19, 16); 8719 setflags = BitIsSet(opcode, 20); 8720 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8) 8721 if (BadReg(Rd) || BadReg(Rn)) 8722 return false; 8723 break; 8724 case eEncodingA1: 8725 Rd = Bits32(opcode, 15, 12); 8726 Rn = Bits32(opcode, 19, 16); 8727 setflags = BitIsSet(opcode, 20); 8728 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12) 8729 8730 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions; 8731 if (Rd == 15 && setflags) 8732 return EmulateSUBSPcLrEtc (opcode, encoding); 8733 break; 8734 default: 8735 return false; 8736 } 8737 // Read the register value from the operand register Rn. 8738 uint32_t reg_val = ReadCoreReg(Rn, &success); 8739 if (!success) 8740 return false; 8741 8742 AddWithCarryResult res = AddWithCarry(reg_val, ~imm32, APSR_C); 8743 8744 EmulateInstruction::Context context; 8745 context.type = EmulateInstruction::eContextImmediate; 8746 context.SetNoArgs (); 8747 8748 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow)) 8749 return false; 8750 8751 return true; 8752} 8753 8754// Subtract with Carry (register) subtracts an optionally-shifted register value and the value of 8755// NOT (Carry flag) from a register value, and writes the result to the destination register. 8756// It can optionally update the condition flags based on the result. 8757bool 8758EmulateInstructionARM::EmulateSBCReg (const uint32_t opcode, const ARMEncoding encoding) 8759{ 8760#if 0 8761 // ARM pseudo code... 8762 if ConditionPassed() then 8763 EncodingSpecificOperations(); 8764 shifted = Shift(R[m], shift_t, shift_n, APSR.C); 8765 (result, carry, overflow) = AddWithCarry(R[n], NOT(shifted), APSR.C); 8766 if d == 15 then // Can only occur for ARM encoding 8767 ALUWritePC(result); // setflags is always FALSE here 8768 else 8769 R[d] = result; 8770 if setflags then 8771 APSR.N = result<31>; 8772 APSR.Z = IsZeroBit(result); 8773 APSR.C = carry; 8774 APSR.V = overflow; 8775#endif 8776 8777 bool success = false; 8778 8779 uint32_t Rd; // the destination register 8780 uint32_t Rn; // the first operand 8781 uint32_t Rm; // the second operand 8782 bool setflags; 8783 ARM_ShifterType shift_t; 8784 uint32_t shift_n; // the shift applied to the value read from Rm 8785 switch (encoding) { 8786 case eEncodingT1: 8787 Rd = Rn = Bits32(opcode, 2, 0); 8788 Rm = Bits32(opcode, 5, 3); 8789 setflags = !InITBlock(); 8790 shift_t = SRType_LSL; 8791 shift_n = 0; 8792 break; 8793 case eEncodingT2: 8794 Rd = Bits32(opcode, 11, 8); 8795 Rn = Bits32(opcode, 19, 16); 8796 Rm = Bits32(opcode, 3, 0); 8797 setflags = BitIsSet(opcode, 20); 8798 shift_n = DecodeImmShiftThumb(opcode, shift_t); 8799 if (BadReg(Rd) || BadReg(Rn) || BadReg(Rm)) 8800 return false; 8801 break; 8802 case eEncodingA1: 8803 Rd = Bits32(opcode, 15, 12); 8804 Rn = Bits32(opcode, 19, 16); 8805 Rm = Bits32(opcode, 3, 0); 8806 setflags = BitIsSet(opcode, 20); 8807 shift_n = DecodeImmShiftARM(opcode, shift_t); 8808 8809 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions; 8810 if (Rd == 15 && setflags) 8811 return EmulateSUBSPcLrEtc (opcode, encoding); 8812 break; 8813 default: 8814 return false; 8815 } 8816 // Read the register value from register Rn. 8817 uint32_t val1 = ReadCoreReg(Rn, &success); 8818 if (!success) 8819 return false; 8820 8821 // Read the register value from register Rm. 8822 uint32_t val2 = ReadCoreReg(Rm, &success); 8823 if (!success) 8824 return false; 8825 8826 uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C); 8827 AddWithCarryResult res = AddWithCarry(val1, ~shifted, APSR_C); 8828 8829 EmulateInstruction::Context context; 8830 context.type = EmulateInstruction::eContextImmediate; 8831 context.SetNoArgs(); 8832 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow)) 8833 return false; 8834 8835 return true; 8836} 8837 8838// This instruction subtracts an immediate value from a register value, and writes the result 8839// to the destination register. It can optionally update the condition flags based on the result. 8840bool 8841EmulateInstructionARM::EmulateSUBImmThumb (const uint32_t opcode, const ARMEncoding encoding) 8842{ 8843#if 0 8844 // ARM pseudo code... 8845 if ConditionPassed() then 8846 EncodingSpecificOperations(); 8847 (result, carry, overflow) = AddWithCarry(R[n], NOT(imm32), '1'); 8848 R[d] = result; 8849 if setflags then 8850 APSR.N = result<31>; 8851 APSR.Z = IsZeroBit(result); 8852 APSR.C = carry; 8853 APSR.V = overflow; 8854#endif 8855 8856 bool success = false; 8857 8858 uint32_t Rd; // the destination register 8859 uint32_t Rn; // the first operand 8860 bool setflags; 8861 uint32_t imm32; // the immediate value to be subtracted from the value obtained from Rn 8862 switch (encoding) { 8863 case eEncodingT1: 8864 Rd = Bits32(opcode, 2, 0); 8865 Rn = Bits32(opcode, 5, 3); 8866 setflags = !InITBlock(); 8867 imm32 = Bits32(opcode, 8, 6); // imm32 = ZeroExtend(imm3, 32) 8868 break; 8869 case eEncodingT2: 8870 Rd = Rn = Bits32(opcode, 10, 8); 8871 setflags = !InITBlock(); 8872 imm32 = Bits32(opcode, 7, 0); // imm32 = ZeroExtend(imm8, 32) 8873 break; 8874 case eEncodingT3: 8875 Rd = Bits32(opcode, 11, 8); 8876 Rn = Bits32(opcode, 19, 16); 8877 setflags = BitIsSet(opcode, 20); 8878 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8) 8879 8880 // if Rd == '1111' && S == '1' then SEE CMP (immediate); 8881 if (Rd == 15 && setflags) 8882 return EmulateCMPImm (opcode, eEncodingT2); 8883 8884 // if Rn == '1101' then SEE SUB (SP minus immediate); 8885 if (Rn == 13) 8886 return EmulateSUBSPImm (opcode, eEncodingT2); 8887 8888 // if d == 13 || (d == 15 && S == '0') || n == 15 then UNPREDICTABLE; 8889 if (Rd == 13 || (Rd == 15 && !setflags) || Rn == 15) 8890 return false; 8891 break; 8892 case eEncodingT4: 8893 Rd = Bits32(opcode, 11, 8); 8894 Rn = Bits32(opcode, 19, 16); 8895 setflags = BitIsSet(opcode, 20); 8896 imm32 = ThumbImm12(opcode); // imm32 = ZeroExtend(i:imm3:imm8, 32) 8897 8898 // if Rn == '1111' then SEE ADR; 8899 if (Rn == 15) 8900 return EmulateADR (opcode, eEncodingT2); 8901 8902 // if Rn == '1101' then SEE SUB (SP minus immediate); 8903 if (Rn == 13) 8904 return EmulateSUBSPImm (opcode, eEncodingT3); 8905 8906 if (BadReg(Rd)) 8907 return false; 8908 break; 8909 default: 8910 return false; 8911 } 8912 // Read the register value from the operand register Rn. 8913 uint32_t reg_val = ReadCoreReg(Rn, &success); 8914 if (!success) 8915 return false; 8916 8917 AddWithCarryResult res = AddWithCarry(reg_val, ~imm32, 1); 8918 8919 EmulateInstruction::Context context; 8920 context.type = EmulateInstruction::eContextImmediate; 8921 context.SetNoArgs (); 8922 8923 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow)) 8924 return false; 8925 8926 return true; 8927} 8928 8929// This instruction subtracts an immediate value from a register value, and writes the result 8930// to the destination register. It can optionally update the condition flags based on the result. 8931bool 8932EmulateInstructionARM::EmulateSUBImmARM (const uint32_t opcode, const ARMEncoding encoding) 8933{ 8934#if 0 8935 // ARM pseudo code... 8936 if ConditionPassed() then 8937 EncodingSpecificOperations(); 8938 (result, carry, overflow) = AddWithCarry(R[n], NOT(imm32), '1'); 8939 if d == 15 then 8940 ALUWritePC(result); // setflags is always FALSE here 8941 else 8942 R[d] = result; 8943 if setflags then 8944 APSR.N = result<31>; 8945 APSR.Z = IsZeroBit(result); 8946 APSR.C = carry; 8947 APSR.V = overflow; 8948#endif 8949 8950 bool success = false; 8951 8952 uint32_t Rd; // the destination register 8953 uint32_t Rn; // the first operand 8954 bool setflags; 8955 uint32_t imm32; // the immediate value to be subtracted from the value obtained from Rn 8956 switch (encoding) { 8957 case eEncodingA1: 8958 Rd = Bits32(opcode, 15, 12); 8959 Rn = Bits32(opcode, 19, 16); 8960 setflags = BitIsSet(opcode, 20); 8961 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12) 8962 8963 // if Rn == '1111' && S == '0' then SEE ADR; 8964 if (Rn == 15 && !setflags) 8965 return EmulateADR (opcode, eEncodingA2); 8966 8967 // if Rn == '1101' then SEE SUB (SP minus immediate); 8968 if (Rn == 13) 8969 return EmulateSUBSPImm (opcode, eEncodingA1); 8970 8971 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions; 8972 if (Rd == 15 && setflags) 8973 return EmulateSUBSPcLrEtc (opcode, encoding); 8974 break; 8975 default: 8976 return false; 8977 } 8978 // Read the register value from the operand register Rn. 8979 uint32_t reg_val = ReadCoreReg(Rn, &success); 8980 if (!success) 8981 return false; 8982 8983 AddWithCarryResult res = AddWithCarry(reg_val, ~imm32, 1); 8984 8985 EmulateInstruction::Context context; 8986 context.type = EmulateInstruction::eContextImmediate; 8987 context.SetNoArgs (); 8988 8989 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow)) 8990 return false; 8991 8992 return true; 8993} 8994 8995// Test Equivalence (immediate) performs a bitwise exclusive OR operation on a register value and an 8996// immediate value. It updates the condition flags based on the result, and discards the result. 8997bool 8998EmulateInstructionARM::EmulateTEQImm (const uint32_t opcode, const ARMEncoding encoding) 8999{ 9000#if 0 9001 // ARM pseudo code... 9002 if ConditionPassed() then 9003 EncodingSpecificOperations(); 9004 result = R[n] EOR imm32; 9005 APSR.N = result<31>; 9006 APSR.Z = IsZeroBit(result); 9007 APSR.C = carry; 9008 // APSR.V unchanged 9009#endif 9010 9011 bool success = false; 9012 9013 if (ConditionPassed(opcode)) 9014 { 9015 uint32_t Rn; 9016 uint32_t imm32; // the immediate value to be ANDed to the value obtained from Rn 9017 uint32_t carry; // the carry bit after ARM/Thumb Expand operation 9018 switch (encoding) 9019 { 9020 case eEncodingT1: 9021 Rn = Bits32(opcode, 19, 16); 9022 imm32 = ThumbExpandImm_C (opcode, APSR_C, carry); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C) 9023 if (BadReg(Rn)) 9024 return false; 9025 break; 9026 case eEncodingA1: 9027 Rn = Bits32(opcode, 19, 16); 9028 imm32 = ARMExpandImm_C (opcode, APSR_C, carry); // (imm32, carry) = ARMExpandImm(imm12, APSR.C) 9029 break; 9030 default: 9031 return false; 9032 } 9033 9034 // Read the first operand. 9035 uint32_t val1 = ReadCoreReg(Rn, &success); 9036 if (!success) 9037 return false; 9038 9039 uint32_t result = val1 ^ imm32; 9040 9041 EmulateInstruction::Context context; 9042 context.type = EmulateInstruction::eContextImmediate; 9043 context.SetNoArgs (); 9044 9045 if (!WriteFlags(context, result, carry)) 9046 return false; 9047 } 9048 return true; 9049} 9050 9051// Test Equivalence (register) performs a bitwise exclusive OR operation on a register value and an 9052// optionally-shifted register value. It updates the condition flags based on the result, and discards 9053// the result. 9054bool 9055EmulateInstructionARM::EmulateTEQReg (const uint32_t opcode, const ARMEncoding encoding) 9056{ 9057#if 0 9058 // ARM pseudo code... 9059 if ConditionPassed() then 9060 EncodingSpecificOperations(); 9061 (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C); 9062 result = R[n] EOR shifted; 9063 APSR.N = result<31>; 9064 APSR.Z = IsZeroBit(result); 9065 APSR.C = carry; 9066 // APSR.V unchanged 9067#endif 9068 9069 bool success = false; 9070 9071 if (ConditionPassed(opcode)) 9072 { 9073 uint32_t Rn, Rm; 9074 ARM_ShifterType shift_t; 9075 uint32_t shift_n; // the shift applied to the value read from Rm 9076 uint32_t carry; 9077 switch (encoding) 9078 { 9079 case eEncodingT1: 9080 Rn = Bits32(opcode, 19, 16); 9081 Rm = Bits32(opcode, 3, 0); 9082 shift_n = DecodeImmShiftThumb(opcode, shift_t); 9083 if (BadReg(Rn) || BadReg(Rm)) 9084 return false; 9085 break; 9086 case eEncodingA1: 9087 Rn = Bits32(opcode, 19, 16); 9088 Rm = Bits32(opcode, 3, 0); 9089 shift_n = DecodeImmShiftARM(opcode, shift_t); 9090 break; 9091 default: 9092 return false; 9093 } 9094 9095 // Read the first operand. 9096 uint32_t val1 = ReadCoreReg(Rn, &success); 9097 if (!success) 9098 return false; 9099 9100 // Read the second operand. 9101 uint32_t val2 = ReadCoreReg(Rm, &success); 9102 if (!success) 9103 return false; 9104 9105 uint32_t shifted = Shift_C(val2, shift_t, shift_n, APSR_C, carry); 9106 uint32_t result = val1 ^ shifted; 9107 9108 EmulateInstruction::Context context; 9109 context.type = EmulateInstruction::eContextImmediate; 9110 context.SetNoArgs (); 9111 9112 if (!WriteFlags(context, result, carry)) 9113 return false; 9114 } 9115 return true; 9116} 9117 9118// Test (immediate) performs a bitwise AND operation on a register value and an immediate value. 9119// It updates the condition flags based on the result, and discards the result. 9120bool 9121EmulateInstructionARM::EmulateTSTImm (const uint32_t opcode, const ARMEncoding encoding) 9122{ 9123#if 0 9124 // ARM pseudo code... 9125 if ConditionPassed() then 9126 EncodingSpecificOperations(); 9127 result = R[n] AND imm32; 9128 APSR.N = result<31>; 9129 APSR.Z = IsZeroBit(result); 9130 APSR.C = carry; 9131 // APSR.V unchanged 9132#endif 9133 9134 bool success = false; 9135 9136 if (ConditionPassed(opcode)) 9137 { 9138 uint32_t Rn; 9139 uint32_t imm32; // the immediate value to be ANDed to the value obtained from Rn 9140 uint32_t carry; // the carry bit after ARM/Thumb Expand operation 9141 switch (encoding) 9142 { 9143 case eEncodingT1: 9144 Rn = Bits32(opcode, 19, 16); 9145 imm32 = ThumbExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C) 9146 if (BadReg(Rn)) 9147 return false; 9148 break; 9149 case eEncodingA1: 9150 Rn = Bits32(opcode, 19, 16); 9151 imm32 = ARMExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ARMExpandImm(imm12, APSR.C) 9152 break; 9153 default: 9154 return false; 9155 } 9156 9157 // Read the first operand. 9158 uint32_t val1 = ReadCoreReg(Rn, &success); 9159 if (!success) 9160 return false; 9161 9162 uint32_t result = val1 & imm32; 9163 9164 EmulateInstruction::Context context; 9165 context.type = EmulateInstruction::eContextImmediate; 9166 context.SetNoArgs (); 9167 9168 if (!WriteFlags(context, result, carry)) 9169 return false; 9170 } 9171 return true; 9172} 9173 9174// Test (register) performs a bitwise AND operation on a register value and an optionally-shifted register value. 9175// It updates the condition flags based on the result, and discards the result. 9176bool 9177EmulateInstructionARM::EmulateTSTReg (const uint32_t opcode, const ARMEncoding encoding) 9178{ 9179#if 0 9180 // ARM pseudo code... 9181 if ConditionPassed() then 9182 EncodingSpecificOperations(); 9183 (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C); 9184 result = R[n] AND shifted; 9185 APSR.N = result<31>; 9186 APSR.Z = IsZeroBit(result); 9187 APSR.C = carry; 9188 // APSR.V unchanged 9189#endif 9190 9191 bool success = false; 9192 9193 if (ConditionPassed(opcode)) 9194 { 9195 uint32_t Rn, Rm; 9196 ARM_ShifterType shift_t; 9197 uint32_t shift_n; // the shift applied to the value read from Rm 9198 uint32_t carry; 9199 switch (encoding) 9200 { 9201 case eEncodingT1: 9202 Rn = Bits32(opcode, 2, 0); 9203 Rm = Bits32(opcode, 5, 3); 9204 shift_t = SRType_LSL; 9205 shift_n = 0; 9206 break; 9207 case eEncodingT2: 9208 Rn = Bits32(opcode, 19, 16); 9209 Rm = Bits32(opcode, 3, 0); 9210 shift_n = DecodeImmShiftThumb(opcode, shift_t); 9211 if (BadReg(Rn) || BadReg(Rm)) 9212 return false; 9213 break; 9214 case eEncodingA1: 9215 Rn = Bits32(opcode, 19, 16); 9216 Rm = Bits32(opcode, 3, 0); 9217 shift_n = DecodeImmShiftARM(opcode, shift_t); 9218 break; 9219 default: 9220 return false; 9221 } 9222 9223 // Read the first operand. 9224 uint32_t val1 = ReadCoreReg(Rn, &success); 9225 if (!success) 9226 return false; 9227 9228 // Read the second operand. 9229 uint32_t val2 = ReadCoreReg(Rm, &success); 9230 if (!success) 9231 return false; 9232 9233 uint32_t shifted = Shift_C(val2, shift_t, shift_n, APSR_C, carry); 9234 uint32_t result = val1 & shifted; 9235 9236 EmulateInstruction::Context context; 9237 context.type = EmulateInstruction::eContextImmediate; 9238 context.SetNoArgs (); 9239 9240 if (!WriteFlags(context, result, carry)) 9241 return false; 9242 } 9243 return true; 9244} 9245 9246// A8.6.216 SUB (SP minus register) 9247bool 9248EmulateInstructionARM::EmulateSUBSPReg (const uint32_t opcode, const ARMEncoding encoding) 9249{ 9250#if 0 9251 if ConditionPassed() then 9252 EncodingSpecificOperations(); 9253 shifted = Shift(R[m], shift_t, shift_n, APSR.C); 9254 (result, carry, overflow) = AddWithCarry(SP, NOT(shifted), ‘1’); 9255 if d == 15 then // Can only occur for ARM encoding 9256 ALUWritePC(result); // setflags is always FALSE here 9257 else 9258 R[d] = result; 9259 if setflags then 9260 APSR.N = result<31>; 9261 APSR.Z = IsZeroBit(result); 9262 APSR.C = carry; 9263 APSR.V = overflow; 9264#endif 9265 9266 bool success = false; 9267 9268 if (ConditionPassed(opcode)) 9269 { 9270 uint32_t d; 9271 uint32_t m; 9272 bool setflags; 9273 ARM_ShifterType shift_t; 9274 uint32_t shift_n; 9275 9276 switch (encoding) 9277 { 9278 case eEncodingT1: 9279 // d = UInt(Rd); m = UInt(Rm); setflags = (S == ‘1’); 9280 d = Bits32 (opcode, 11, 8); 9281 m = Bits32 (opcode, 3, 0); 9282 setflags = BitIsSet (opcode, 20); 9283 9284 // (shift_t, shift_n) = DecodeImmShift(type, imm3:imm2); 9285 shift_n = DecodeImmShiftThumb (opcode, shift_t); 9286 9287 // if d == 13 && (shift_t != SRType_LSL || shift_n > 3) then UNPREDICTABLE; 9288 if ((d == 13) && ((shift_t != SRType_LSL) || (shift_n > 3))) 9289 return false; 9290 9291 // if d == 15 || BadReg(m) then UNPREDICTABLE; 9292 if ((d == 15) || BadReg (m)) 9293 return false; 9294 break; 9295 9296 case eEncodingA1: 9297 // d = UInt(Rd); m = UInt(Rm); setflags = (S == ‘1’); 9298 d = Bits32 (opcode, 15, 12); 9299 m = Bits32 (opcode, 3, 0); 9300 setflags = BitIsSet (opcode, 20); 9301 9302 // if Rd == ‘1111’ && S == ‘1’ then SEE SUBS PC, LR and related instructions; 9303 if (d == 15 && setflags) 9304 EmulateSUBSPcLrEtc (opcode, encoding); 9305 9306 // (shift_t, shift_n) = DecodeImmShift(type, imm5); 9307 shift_n = DecodeImmShiftARM (opcode, shift_t); 9308 break; 9309 9310 default: 9311 return false; 9312 } 9313 9314 // shifted = Shift(R[m], shift_t, shift_n, APSR.C); 9315 uint32_t Rm = ReadCoreReg (m, &success); 9316 if (!success) 9317 return false; 9318 9319 uint32_t shifted = Shift (Rm, shift_t, shift_n, APSR_C); 9320 9321 // (result, carry, overflow) = AddWithCarry(SP, NOT(shifted), ‘1’); 9322 uint32_t sp_val = ReadCoreReg (SP_REG, &success); 9323 if (!success) 9324 return false; 9325 9326 AddWithCarryResult res = AddWithCarry (sp_val, ~shifted, 1); 9327 9328 EmulateInstruction::Context context; 9329 context.type = eContextSubtraction; 9330 Register sp_reg; 9331 sp_reg.SetRegister (eRegisterKindDWARF, dwarf_sp); 9332 Register dwarf_reg; 9333 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + m); 9334 context.SetRegisterRegisterOperands (sp_reg, dwarf_reg); 9335 9336 if (!WriteCoreRegOptionalFlags(context, res.result, dwarf_r0 + d, setflags, res.carry_out, res.overflow)) 9337 return false; 9338 } 9339 return true; 9340} 9341 9342 9343// A8.6.7 ADD (register-shifted register) 9344bool 9345EmulateInstructionARM::EmulateADDRegShift (const uint32_t opcode, const ARMEncoding encoding) 9346{ 9347#if 0 9348 if ConditionPassed() then 9349 EncodingSpecificOperations(); 9350 shift_n = UInt(R[s]<7:0>); 9351 shifted = Shift(R[m], shift_t, shift_n, APSR.C); 9352 (result, carry, overflow) = AddWithCarry(R[n], shifted, ‘0’); 9353 R[d] = result; 9354 if setflags then 9355 APSR.N = result<31>; 9356 APSR.Z = IsZeroBit(result); 9357 APSR.C = carry; 9358 APSR.V = overflow; 9359#endif 9360 9361 bool success = false; 9362 9363 if (ConditionPassed(opcode)) 9364 { 9365 uint32_t d; 9366 uint32_t n; 9367 uint32_t m; 9368 uint32_t s; 9369 bool setflags; 9370 ARM_ShifterType shift_t; 9371 9372 switch (encoding) 9373 { 9374 case eEncodingA1: 9375 // d = UInt(Rd); n = UInt(Rn); m = UInt(Rm); s = UInt(Rs); 9376 d = Bits32 (opcode, 15, 12); 9377 n = Bits32 (opcode, 19, 16); 9378 m = Bits32 (opcode, 3, 0); 9379 s = Bits32 (opcode, 11, 8); 9380 9381 // setflags = (S == ‘1’); shift_t = DecodeRegShift(type); 9382 setflags = BitIsSet (opcode, 20); 9383 shift_t = DecodeRegShift (Bits32 (opcode, 6, 5)); 9384 9385 // if d == 15 || n == 15 || m == 15 || s == 15 then UNPREDICTABLE; 9386 if ((d == 15) || (m == 15) || (m == 15) || (s == 15)) 9387 return false; 9388 break; 9389 9390 default: 9391 return false; 9392 } 9393 9394 // shift_n = UInt(R[s]<7:0>); 9395 uint32_t Rs = ReadCoreReg (s, &success); 9396 if (!success) 9397 return false; 9398 9399 uint32_t shift_n = Bits32 (Rs, 7, 0); 9400 9401 // shifted = Shift(R[m], shift_t, shift_n, APSR.C); 9402 uint32_t Rm = ReadCoreReg (m, &success); 9403 if (!success) 9404 return false; 9405 9406 uint32_t shifted = Shift (Rm, shift_t, shift_n, APSR_C); 9407 9408 // (result, carry, overflow) = AddWithCarry(R[n], shifted, ‘0’); 9409 uint32_t Rn = ReadCoreReg (n, &success); 9410 if (!success) 9411 return false; 9412 9413 AddWithCarryResult res = AddWithCarry (Rn, shifted, 0); 9414 9415 // R[d] = result; 9416 EmulateInstruction::Context context; 9417 context.type = eContextAddition; 9418 Register reg_n; 9419 reg_n.SetRegister (eRegisterKindDWARF, dwarf_r0 +n); 9420 Register reg_m; 9421 reg_m.SetRegister (eRegisterKindDWARF, dwarf_r0 + m); 9422 9423 context.SetRegisterRegisterOperands (reg_n, reg_m); 9424 9425 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + d, res.result)) 9426 return false; 9427 9428 // if setflags then 9429 // APSR.N = result<31>; 9430 // APSR.Z = IsZeroBit(result); 9431 // APSR.C = carry; 9432 // APSR.V = overflow; 9433 if (setflags) 9434 return WriteFlags (context, res.result, res.carry_out, res.overflow); 9435 } 9436 return true; 9437} 9438 9439// A8.6.213 SUB (register) 9440bool 9441EmulateInstructionARM::EmulateSUBReg (const uint32_t opcode, const ARMEncoding encoding) 9442{ 9443#if 0 9444 if ConditionPassed() then 9445 EncodingSpecificOperations(); 9446 shifted = Shift(R[m], shift_t, shift_n, APSR.C); 9447 (result, carry, overflow) = AddWithCarry(R[n], NOT(shifted), ‘1’); 9448 if d == 15 then // Can only occur for ARM encoding 9449 ALUWritePC(result); // setflags is always FALSE here 9450 else 9451 R[d] = result; 9452 if setflags then 9453 APSR.N = result<31>; 9454 APSR.Z = IsZeroBit(result); 9455 APSR.C = carry; 9456 APSR.V = overflow; 9457#endif 9458 9459 bool success = false; 9460 9461 if (ConditionPassed(opcode)) 9462 { 9463 uint32_t d; 9464 uint32_t n; 9465 uint32_t m; 9466 bool setflags; 9467 ARM_ShifterType shift_t; 9468 uint32_t shift_n; 9469 9470 switch (encoding) 9471 { 9472 case eEncodingT1: 9473 // d = UInt(Rd); n = UInt(Rn); m = UInt(Rm); setflags = !InITBlock(); 9474 d = Bits32 (opcode, 2, 0); 9475 n = Bits32 (opcode, 5, 3); 9476 m = Bits32 (opcode, 8, 6); 9477 setflags = !InITBlock(); 9478 9479 // (shift_t, shift_n) = (SRType_LSL, 0); 9480 shift_t = SRType_LSL; 9481 shift_n = 0; 9482 9483 break; 9484 9485 case eEncodingT2: 9486 // if Rd == ‘1111’ && S == ‘1’ then SEE CMP (register); 9487 // if Rn == ‘1101’ then SEE SUB (SP minus register); 9488 // d = UInt(Rd); n = UInt(Rn); m = UInt(Rm); setflags = (S == ‘1’); 9489 d = Bits32 (opcode, 11, 8); 9490 n = Bits32 (opcode, 19, 16); 9491 m = Bits32 (opcode, 3, 0); 9492 setflags = BitIsSet (opcode, 20); 9493 9494 // (shift_t, shift_n) = DecodeImmShift(type, imm3:imm2); 9495 shift_n = DecodeImmShiftThumb (opcode, shift_t); 9496 9497 // if d == 13 || (d == 15 && S == '0') || n == 15 || BadReg(m) then UNPREDICTABLE; 9498 if ((d == 13) || ((d == 15) && BitIsClear (opcode, 20)) || (n == 15) || BadReg (m)) 9499 return false; 9500 9501 break; 9502 9503 case eEncodingA1: 9504 // if Rn == ‘1101’ then SEE SUB (SP minus register); 9505 // d = UInt(Rd); n = UInt(Rn); m = UInt(Rm); setflags = (S == ‘1’); 9506 d = Bits32 (opcode, 15, 12); 9507 n = Bits32 (opcode, 19, 16); 9508 m = Bits32 (opcode, 3, 0); 9509 setflags = BitIsSet (opcode, 20); 9510 9511 // if Rd == ‘1111’ && S == ‘1’ then SEE SUBS PC, LR and related instructions; 9512 if ((d == 15) && setflags) 9513 EmulateSUBSPcLrEtc (opcode, encoding); 9514 9515 // (shift_t, shift_n) = DecodeImmShift(type, imm5); 9516 shift_n = DecodeImmShiftARM (opcode, shift_t); 9517 9518 break; 9519 9520 default: 9521 return false; 9522 } 9523 9524 // shifted = Shift(R[m], shift_t, shift_n, APSR.C); 9525 uint32_t Rm = ReadCoreReg (m, &success); 9526 if (!success) 9527 return false; 9528 9529 uint32_t shifted = Shift (Rm, shift_t, shift_n, APSR_C); 9530 9531 // (result, carry, overflow) = AddWithCarry(R[n], NOT(shifted), ‘1’); 9532 uint32_t Rn = ReadCoreReg (n, &success); 9533 if (!success) 9534 return false; 9535 9536 AddWithCarryResult res = AddWithCarry (Rn, ~shifted, 1); 9537 9538 // if d == 15 then // Can only occur for ARM encoding 9539 // ALUWritePC(result); // setflags is always FALSE here 9540 // else 9541 // R[d] = result; 9542 // if setflags then 9543 // APSR.N = result<31>; 9544 // APSR.Z = IsZeroBit(result); 9545 // APSR.C = carry; 9546 // APSR.V = overflow; 9547 9548 EmulateInstruction::Context context; 9549 context.type = eContextSubtraction; 9550 Register reg_n; 9551 reg_n.SetRegister (eRegisterKindDWARF, dwarf_r0 + n); 9552 Register reg_m; 9553 reg_m.SetRegister (eRegisterKindDWARF, dwarf_r0 + m); 9554 context.SetRegisterRegisterOperands (reg_n, reg_m); 9555 9556 if (!WriteCoreRegOptionalFlags (context, res.result, dwarf_r0 + d, setflags, res.carry_out, res.overflow)) 9557 return false; 9558 } 9559 return true; 9560} 9561 9562// A8.6.202 STREX 9563// Store Register Exclusive calculates an address from a base register value and an immediate offset, and stores a 9564// word from a register to memory if the executing processor has exclusive access to the memory addressed. 9565bool 9566EmulateInstructionARM::EmulateSTREX (const uint32_t opcode, const ARMEncoding encoding) 9567{ 9568#if 0 9569 if ConditionPassed() then 9570 EncodingSpecificOperations(); NullCheckIfThumbEE(n); 9571 address = R[n] + imm32; 9572 if ExclusiveMonitorsPass(address,4) then 9573 MemA[address,4] = R[t]; 9574 R[d] = 0; 9575 else 9576 R[d] = 1; 9577#endif 9578 9579 bool success = false; 9580 9581 if (ConditionPassed(opcode)) 9582 { 9583 uint32_t d; 9584 uint32_t t; 9585 uint32_t n; 9586 uint32_t imm32; 9587 const uint32_t addr_byte_size = GetAddressByteSize(); 9588 9589 switch (encoding) 9590 { 9591 case eEncodingT1: 9592 // d = UInt(Rd); t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8:’00’, 32); 9593 d = Bits32 (opcode, 11, 8); 9594 t = Bits32 (opcode, 15, 12); 9595 n = Bits32 (opcode, 19, 16); 9596 imm32 = Bits32 (opcode, 7, 0) << 2; 9597 9598 // if BadReg(d) || BadReg(t) || n == 15 then UNPREDICTABLE; 9599 if (BadReg (d) || BadReg (t) || (n == 15)) 9600 return false; 9601 9602 // if d == n || d == t then UNPREDICTABLE; 9603 if ((d == n) || (d == t)) 9604 return false; 9605 9606 break; 9607 9608 case eEncodingA1: 9609 // d = UInt(Rd); t = UInt(Rt); n = UInt(Rn); imm32 = Zeros(32); // Zero offset 9610 d = Bits32 (opcode, 15, 12); 9611 t = Bits32 (opcode, 3, 0); 9612 n = Bits32 (opcode, 19, 16); 9613 imm32 = 0; 9614 9615 // if d == 15 || t == 15 || n == 15 then UNPREDICTABLE; 9616 if ((d == 15) || (t == 15) || (n == 15)) 9617 return false; 9618 9619 // if d == n || d == t then UNPREDICTABLE; 9620 if ((d == n) || (d == t)) 9621 return false; 9622 9623 break; 9624 9625 default: 9626 return false; 9627 } 9628 9629 // address = R[n] + imm32; 9630 uint32_t Rn = ReadCoreReg (n, &success); 9631 if (!success) 9632 return false; 9633 9634 addr_t address = Rn + imm32; 9635 9636 Register base_reg; 9637 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n); 9638 Register data_reg; 9639 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + t); 9640 EmulateInstruction::Context context; 9641 context.type = eContextRegisterStore; 9642 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, imm32); 9643 9644 // if ExclusiveMonitorsPass(address,4) then 9645 // if (ExclusiveMonitorsPass (address, addr_byte_size)) -- For now, for the sake of emulation, we will say this 9646 // always return true. 9647 if (true) 9648 { 9649 // MemA[address,4] = R[t]; 9650 uint32_t Rt = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + t, 0, &success); 9651 if (!success) 9652 return false; 9653 9654 if (!MemAWrite (context, address, Rt, addr_byte_size)) 9655 return false; 9656 9657 // R[d] = 0; 9658 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, 0)) 9659 return false; 9660 } 9661 else 9662 { 9663 // R[d] = 1; 9664 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, 1)) 9665 return false; 9666 } 9667 } 9668 return true; 9669} 9670 9671// A8.6.197 STRB (immediate, ARM) 9672bool 9673EmulateInstructionARM::EmulateSTRBImmARM (const uint32_t opcode, const ARMEncoding encoding) 9674{ 9675#if 0 9676 if ConditionPassed() then 9677 EncodingSpecificOperations(); 9678 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32); 9679 address = if index then offset_addr else R[n]; 9680 MemU[address,1] = R[t]<7:0>; 9681 if wback then R[n] = offset_addr; 9682#endif 9683 9684 bool success = false; 9685 9686 if (ConditionPassed(opcode)) 9687 { 9688 uint32_t t; 9689 uint32_t n; 9690 uint32_t imm32; 9691 bool index; 9692 bool add; 9693 bool wback; 9694 9695 switch (encoding) 9696 { 9697 case eEncodingA1: 9698 // if P == ‘0’ && W == ‘1’ then SEE STRBT; 9699 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32); 9700 t = Bits32 (opcode, 15, 12); 9701 n = Bits32 (opcode, 19, 16); 9702 imm32 = Bits32 (opcode, 11, 0); 9703 9704 // index = (P == ‘1’); add = (U == ‘1’); wback = (P == ‘0’) || (W == ‘1’); 9705 index = BitIsSet (opcode, 24); 9706 add = BitIsSet (opcode, 23); 9707 wback = BitIsClear (opcode, 24) || BitIsSet (opcode, 21); 9708 9709 // if t == 15 then UNPREDICTABLE; 9710 if (t == 15) 9711 return false; 9712 9713 // if wback && (n == 15 || n == t) then UNPREDICTABLE; 9714 if (wback && ((n == 15) || (n == t))) 9715 return false; 9716 9717 break; 9718 9719 default: 9720 return false; 9721 } 9722 9723 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32); 9724 uint32_t Rn = ReadCoreReg (n, &success); 9725 if (!success) 9726 return false; 9727 9728 addr_t offset_addr; 9729 if (add) 9730 offset_addr = Rn + imm32; 9731 else 9732 offset_addr = Rn - imm32; 9733 9734 // address = if index then offset_addr else R[n]; 9735 addr_t address; 9736 if (index) 9737 address = offset_addr; 9738 else 9739 address = Rn; 9740 9741 // MemU[address,1] = R[t]<7:0>; 9742 uint32_t Rt = ReadCoreReg (t, &success); 9743 if (!success) 9744 return false; 9745 9746 Register base_reg; 9747 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n); 9748 Register data_reg; 9749 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + t); 9750 EmulateInstruction::Context context; 9751 context.type = eContextRegisterStore; 9752 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, address - Rn); 9753 9754 if (!MemUWrite (context, address, Bits32 (Rt, 7, 0), 1)) 9755 return false; 9756 9757 // if wback then R[n] = offset_addr; 9758 if (wback) 9759 { 9760 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr)) 9761 return false; 9762 } 9763 } 9764 return true; 9765} 9766 9767// A8.6.194 STR (immediate, ARM) 9768bool 9769EmulateInstructionARM::EmulateSTRImmARM (const uint32_t opcode, const ARMEncoding encoding) 9770{ 9771#if 0 9772 if ConditionPassed() then 9773 EncodingSpecificOperations(); 9774 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32); 9775 address = if index then offset_addr else R[n]; 9776 MemU[address,4] = if t == 15 then PCStoreValue() else R[t]; 9777 if wback then R[n] = offset_addr; 9778#endif 9779 9780 bool success = false; 9781 9782 if (ConditionPassed(opcode)) 9783 { 9784 uint32_t t; 9785 uint32_t n; 9786 uint32_t imm32; 9787 bool index; 9788 bool add; 9789 bool wback; 9790 9791 const uint32_t addr_byte_size = GetAddressByteSize(); 9792 9793 switch (encoding) 9794 { 9795 case eEncodingA1: 9796 // if P == ‘0’ && W == ‘1’ then SEE STRT; 9797 // if Rn == ‘1101’ && P == ‘1’ && U == ‘0’ && W == ‘1’ && imm12 == ‘000000000100’ then SEE PUSH; 9798 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32); 9799 t = Bits32 (opcode, 15, 12); 9800 n = Bits32 (opcode, 19, 16); 9801 imm32 = Bits32 (opcode, 11, 0); 9802 9803 // index = (P == ‘1’); add = (U == ‘1’); wback = (P == ‘0’) || (W == ‘1’); 9804 index = BitIsSet (opcode, 24); 9805 add = BitIsSet (opcode, 23); 9806 wback = BitIsClear (opcode, 24) || BitIsSet (opcode, 21); 9807 9808 // if wback && (n == 15 || n == t) then UNPREDICTABLE; 9809 if (wback && ((n == 15) || (n == t))) 9810 return false; 9811 9812 break; 9813 9814 default: 9815 return false; 9816 } 9817 9818 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32); 9819 uint32_t Rn = ReadCoreReg (n, &success); 9820 if (!success) 9821 return false; 9822 9823 addr_t offset_addr; 9824 if (add) 9825 offset_addr = Rn + imm32; 9826 else 9827 offset_addr = Rn - imm32; 9828 9829 // address = if index then offset_addr else R[n]; 9830 addr_t address; 9831 if (index) 9832 address = offset_addr; 9833 else 9834 address = Rn; 9835 9836 Register base_reg; 9837 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n); 9838 Register data_reg; 9839 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + t); 9840 EmulateInstruction::Context context; 9841 context.type = eContextRegisterStore; 9842 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, address - Rn); 9843 9844 // MemU[address,4] = if t == 15 then PCStoreValue() else R[t]; 9845 uint32_t Rt = ReadCoreReg (t, &success); 9846 if (!success) 9847 return false; 9848 9849 if (t == 15) 9850 { 9851 uint32_t pc_value = ReadCoreReg (PC_REG, &success); 9852 if (!success) 9853 return false; 9854 9855 if (!MemUWrite (context, address, pc_value, addr_byte_size)) 9856 return false; 9857 } 9858 else 9859 { 9860 if (!MemUWrite (context, address, Rt, addr_byte_size)) 9861 return false; 9862 } 9863 9864 // if wback then R[n] = offset_addr; 9865 if (wback) 9866 { 9867 context.type = eContextAdjustBaseRegister; 9868 context.SetImmediate (offset_addr); 9869 9870 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr)) 9871 return false; 9872 } 9873 } 9874 return true; 9875} 9876 9877// A8.6.66 LDRD (immediate) 9878// Load Register Dual (immediate) calculates an address from a base register value and an immediate offset, loads two 9879// words from memory, and writes them to two registers. It can use offset, post-indexed, or pre-indexed addressing. 9880bool 9881EmulateInstructionARM::EmulateLDRDImmediate (const uint32_t opcode, const ARMEncoding encoding) 9882{ 9883#if 0 9884 if ConditionPassed() then 9885 EncodingSpecificOperations(); NullCheckIfThumbEE(n); 9886 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32); 9887 address = if index then offset_addr else R[n]; 9888 R[t] = MemA[address,4]; 9889 R[t2] = MemA[address+4,4]; 9890 if wback then R[n] = offset_addr; 9891#endif 9892 9893 bool success = false; 9894 9895 if (ConditionPassed(opcode)) 9896 { 9897 uint32_t t; 9898 uint32_t t2; 9899 uint32_t n; 9900 uint32_t imm32; 9901 bool index; 9902 bool add; 9903 bool wback; 9904 9905 switch (encoding) 9906 { 9907 case eEncodingT1: 9908 //if P == ‘0’ && W == ‘0’ then SEE “Related encodings”; 9909 //if Rn == ‘1111’ then SEE LDRD (literal); 9910 //t = UInt(Rt); t2 = UInt(Rt2); n = UInt(Rn); imm32 = ZeroExtend(imm8:’00’, 32); 9911 t = Bits32 (opcode, 15, 12); 9912 t2 = Bits32 (opcode, 11, 8); 9913 n = Bits32 (opcode, 19, 16); 9914 imm32 = Bits32 (opcode, 7, 0) << 2; 9915 9916 //index = (P == ‘1’); add = (U == ‘1’); wback = (W == ‘1’); 9917 index = BitIsSet (opcode, 24); 9918 add = BitIsSet (opcode, 23); 9919 wback = BitIsSet (opcode, 21); 9920 9921 //if wback && (n == t || n == t2) then UNPREDICTABLE; 9922 if (wback && ((n == t) || (n == t2))) 9923 return false; 9924 9925 //if BadReg(t) || BadReg(t2) || t == t2 then UNPREDICTABLE; 9926 if (BadReg (t) || BadReg (t2) || (t == t2)) 9927 return false; 9928 9929 break; 9930 9931 case eEncodingA1: 9932 //if Rn == ‘1111’ then SEE LDRD (literal); 9933 //if Rt<0> == ‘1’ then UNPREDICTABLE; 9934 //t = UInt(Rt); t2 = t+1; n = UInt(Rn); imm32 = ZeroExtend(imm4H:imm4L, 32); 9935 t = Bits32 (opcode, 15, 12); 9936 if (BitIsSet (t, 0)) 9937 return false; 9938 t2 = t + 1; 9939 n = Bits32 (opcode, 19, 16); 9940 imm32 = (Bits32 (opcode, 11, 8) << 4) | Bits32 (opcode, 3, 0); 9941 9942 //index = (P == ‘1’); add = (U == ‘1’); wback = (P == ‘0’) || (W == ‘1’); 9943 index = BitIsSet (opcode, 24); 9944 add = BitIsSet (opcode, 23); 9945 wback = BitIsClear (opcode, 24) || BitIsSet (opcode, 21); 9946 9947 //if P == ‘0’ && W == ‘1’ then UNPREDICTABLE; 9948 if (BitIsClear (opcode, 24) && BitIsSet (opcode, 21)) 9949 return false; 9950 9951 //if wback && (n == t || n == t2) then UNPREDICTABLE; 9952 if (wback && ((n == t) || (n == t2))) 9953 return false; 9954 9955 //if t2 == 15 then UNPREDICTABLE; 9956 if (t2 == 15) 9957 return false; 9958 9959 break; 9960 9961 default: 9962 return false; 9963 } 9964 9965 //offset_addr = if add then (R[n] + imm32) else (R[n] - imm32); 9966 uint32_t Rn = ReadCoreReg (n, &success); 9967 if (!success) 9968 return false; 9969 9970 addr_t offset_addr; 9971 if (add) 9972 offset_addr = Rn + imm32; 9973 else 9974 offset_addr = Rn - imm32; 9975 9976 //address = if index then offset_addr else R[n]; 9977 addr_t address; 9978 if (index) 9979 address = offset_addr; 9980 else 9981 address = Rn; 9982 9983 //R[t] = MemA[address,4]; 9984 Register base_reg; 9985 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n); 9986 9987 EmulateInstruction::Context context; 9988 context.type = eContextRegisterLoad; 9989 context.SetRegisterPlusOffset (base_reg, address - Rn); 9990 9991 const uint32_t addr_byte_size = GetAddressByteSize(); 9992 uint32_t data = MemARead (context, address, addr_byte_size, 0, &success); 9993 if (!success) 9994 return false; 9995 9996 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data)) 9997 return false; 9998 9999 //R[t2] = MemA[address+4,4]; 10000 10001 context.SetRegisterPlusOffset (base_reg, (address + 4) - Rn); 10002 data = MemARead (context, address + 4, addr_byte_size, 0, &success); 10003 if (!success) 10004 return false; 10005 10006 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t2, data)) 10007 return false; 10008 10009 //if wback then R[n] = offset_addr; 10010 if (wback) 10011 { 10012 context.type = eContextAdjustBaseRegister; 10013 context.SetAddress (offset_addr); 10014 10015 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr)) 10016 return false; 10017 } 10018 } 10019 return true; 10020} 10021 10022// A8.6.68 LDRD (register) 10023// Load Register Dual (register) calculates an address from a base register value and a register offset, loads two 10024// words from memory, and writes them to two registers. It can use offset, post-indexed or pre-indexed addressing. 10025bool 10026EmulateInstructionARM::EmulateLDRDRegister (const uint32_t opcode, const ARMEncoding encoding) 10027{ 10028#if 0 10029 if ConditionPassed() then 10030 EncodingSpecificOperations(); 10031 offset_addr = if add then (R[n] + R[m]) else (R[n] - R[m]); 10032 address = if index then offset_addr else R[n]; 10033 R[t] = MemA[address,4]; 10034 R[t2] = MemA[address+4,4]; 10035 if wback then R[n] = offset_addr; 10036#endif 10037 10038 bool success = false; 10039 10040 if (ConditionPassed(opcode)) 10041 { 10042 uint32_t t; 10043 uint32_t t2; 10044 uint32_t n; 10045 uint32_t m; 10046 bool index; 10047 bool add; 10048 bool wback; 10049 10050 switch (encoding) 10051 { 10052 case eEncodingA1: 10053 // if Rt<0> == ‘1’ then UNPREDICTABLE; 10054 // t = UInt(Rt); t2 = t+1; n = UInt(Rn); m = UInt(Rm); 10055 t = Bits32 (opcode, 15, 12); 10056 if (BitIsSet (t, 0)) 10057 return false; 10058 t2 = t + 1; 10059 n = Bits32 (opcode, 19, 16); 10060 m = Bits32 (opcode, 3, 0); 10061 10062 // index = (P == ‘1’); add = (U == ‘1’); wback = (P == ‘0’) || (W == ‘1’); 10063 index = BitIsSet (opcode, 24); 10064 add = BitIsSet (opcode, 23); 10065 wback = BitIsClear (opcode, 24) || BitIsSet (opcode, 21); 10066 10067 // if P == ‘0’ && W == ‘1’ then UNPREDICTABLE; 10068 if (BitIsClear (opcode, 24) && BitIsSet (opcode, 21)) 10069 return false; 10070 10071 // if t2 == 15 || m == 15 || m == t || m == t2 then UNPREDICTABLE; 10072 if ((t2 == 15) || (m == 15) || (m == t) || (m == t2)) 10073 return false; 10074 10075 // if wback && (n == 15 || n == t || n == t2) then UNPREDICTABLE; 10076 if (wback && ((n == 15) || (n == t) || (n == t2))) 10077 return false; 10078 10079 // if ArchVersion() < 6 && wback && m == n then UNPREDICTABLE; 10080 if ((ArchVersion() < 6) && wback && (m == n)) 10081 return false; 10082 break; 10083 10084 default: 10085 return false; 10086 } 10087 10088 uint32_t Rn = ReadCoreReg (n, &success); 10089 if (!success) 10090 return false; 10091 Register base_reg; 10092 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n); 10093 10094 uint32_t Rm = ReadCoreReg (m, &success); 10095 if (!success) 10096 return false; 10097 Register offset_reg; 10098 offset_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + m); 10099 10100 // offset_addr = if add then (R[n] + R[m]) else (R[n] - R[m]); 10101 addr_t offset_addr; 10102 if (add) 10103 offset_addr = Rn + Rm; 10104 else 10105 offset_addr = Rn - Rm; 10106 10107 // address = if index then offset_addr else R[n]; 10108 addr_t address; 10109 if (index) 10110 address = offset_addr; 10111 else 10112 address = Rn; 10113 10114 EmulateInstruction::Context context; 10115 context.type = eContextRegisterLoad; 10116 context.SetRegisterPlusIndirectOffset (base_reg, offset_reg); 10117 10118 // R[t] = MemA[address,4]; 10119 const uint32_t addr_byte_size = GetAddressByteSize(); 10120 uint32_t data = MemARead (context, address, addr_byte_size, 0, &success); 10121 if (!success) 10122 return false; 10123 10124 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data)) 10125 return false; 10126 10127 // R[t2] = MemA[address+4,4]; 10128 10129 data = MemARead (context, address + 4, addr_byte_size, 0, &success); 10130 if (!success) 10131 return false; 10132 10133 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t2, data)) 10134 return false; 10135 10136 // if wback then R[n] = offset_addr; 10137 if (wback) 10138 { 10139 context.type = eContextAdjustBaseRegister; 10140 context.SetAddress (offset_addr); 10141 10142 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr)) 10143 return false; 10144 } 10145 } 10146 return true; 10147} 10148 10149// A8.6.200 STRD (immediate) 10150// Store Register Dual (immediate) calculates an address from a base register value and an immediate offset, and 10151// stores two words from two registers to memory. It can use offset, post-indexed, or pre-indexed addressing. 10152bool 10153EmulateInstructionARM::EmulateSTRDImm (const uint32_t opcode, const ARMEncoding encoding) 10154{ 10155#if 0 10156 if ConditionPassed() then 10157 EncodingSpecificOperations(); NullCheckIfThumbEE(n); 10158 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32); 10159 address = if index then offset_addr else R[n]; 10160 MemA[address,4] = R[t]; 10161 MemA[address+4,4] = R[t2]; 10162 if wback then R[n] = offset_addr; 10163#endif 10164 10165 bool success = false; 10166 10167 if (ConditionPassed(opcode)) 10168 { 10169 uint32_t t; 10170 uint32_t t2; 10171 uint32_t n; 10172 uint32_t imm32; 10173 bool index; 10174 bool add; 10175 bool wback; 10176 10177 switch (encoding) 10178 { 10179 case eEncodingT1: 10180 // if P == ‘0’ && W == ‘0’ then SEE “Related encodings”; 10181 // t = UInt(Rt); t2 = UInt(Rt2); n = UInt(Rn); imm32 = ZeroExtend(imm8:’00’, 32); 10182 t = Bits32 (opcode, 15, 12); 10183 t2 = Bits32 (opcode, 11, 8); 10184 n = Bits32 (opcode, 19, 16); 10185 imm32 = Bits32 (opcode, 7, 0) << 2; 10186 10187 // index = (P == ‘1’); add = (U == ‘1’); wback = (W == ‘1’); 10188 index = BitIsSet (opcode, 24); 10189 add = BitIsSet (opcode, 23); 10190 wback = BitIsSet (opcode, 21); 10191 10192 // if wback && (n == t || n == t2) then UNPREDICTABLE; 10193 if (wback && ((n == t) || (n == t2))) 10194 return false; 10195 10196 // if n == 15 || BadReg(t) || BadReg(t2) then UNPREDICTABLE; 10197 if ((n == 15) || BadReg (t) || BadReg (t2)) 10198 return false; 10199 10200 break; 10201 10202 case eEncodingA1: 10203 // if Rt<0> == ‘1’ then UNPREDICTABLE; 10204 // t = UInt(Rt); t2 = t+1; n = UInt(Rn); imm32 = ZeroExtend(imm4H:imm4L, 32); 10205 t = Bits32 (opcode, 15, 12); 10206 if (BitIsSet (t, 0)) 10207 return false; 10208 10209 t2 = t + 1; 10210 n = Bits32 (opcode, 19, 16); 10211 imm32 = (Bits32 (opcode, 11, 8) << 4) | Bits32 (opcode, 3, 0); 10212 10213 // index = (P == ‘1’); add = (U == ‘1’); wback = (P == ‘0’) || (W == ‘1’); 10214 index = BitIsSet (opcode, 24); 10215 add = BitIsSet (opcode, 23); 10216 wback = BitIsClear (opcode, 24) || BitIsSet (opcode, 21); 10217 10218 // if P == ‘0’ && W == ‘1’ then UNPREDICTABLE; 10219 if (BitIsClear (opcode, 24) && BitIsSet (opcode, 21)) 10220 return false; 10221 10222 // if wback && (n == 15 || n == t || n == t2) then UNPREDICTABLE; 10223 if (wback && ((n == 15) || (n == t) || (n == t2))) 10224 return false; 10225 10226 // if t2 == 15 then UNPREDICTABLE; 10227 if (t2 == 15) 10228 return false; 10229 10230 break; 10231 10232 default: 10233 return false; 10234 } 10235 10236 Register base_reg; 10237 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n); 10238 10239 uint32_t Rn = ReadCoreReg (n, &success); 10240 if (!success) 10241 return false; 10242 10243 //offset_addr = if add then (R[n] + imm32) else (R[n] - imm32); 10244 addr_t offset_addr; 10245 if (add) 10246 offset_addr = Rn + imm32; 10247 else 10248 offset_addr = Rn - imm32; 10249 10250 //address = if index then offset_addr else R[n]; 10251 addr_t address; 10252 if (index) 10253 address = offset_addr; 10254 else 10255 address = Rn; 10256 10257 //MemA[address,4] = R[t]; 10258 Register data_reg; 10259 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + t); 10260 10261 uint32_t data = ReadCoreReg (t, &success); 10262 if (!success) 10263 return false; 10264 10265 EmulateInstruction::Context context; 10266 context.type = eContextRegisterStore; 10267 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, address - Rn); 10268 10269 const uint32_t addr_byte_size = GetAddressByteSize(); 10270 10271 if (!MemAWrite (context, address, data, addr_byte_size)) 10272 return false; 10273 10274 //MemA[address+4,4] = R[t2]; 10275 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + t2); 10276 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, (address + 4) - Rn); 10277 10278 data = ReadCoreReg (t2, &success); 10279 if (!success) 10280 return false; 10281 10282 if (!MemAWrite (context, address + 4, data, addr_byte_size)) 10283 return false; 10284 10285 //if wback then R[n] = offset_addr; 10286 if (wback) 10287 { 10288 context.type = eContextAdjustBaseRegister; 10289 context.SetAddress (offset_addr); 10290 10291 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr)) 10292 return false; 10293 } 10294 } 10295 return true; 10296} 10297 10298 10299// A8.6.201 STRD (register) 10300bool 10301EmulateInstructionARM::EmulateSTRDReg (const uint32_t opcode, const ARMEncoding encoding) 10302{ 10303#if 0 10304 if ConditionPassed() then 10305 EncodingSpecificOperations(); 10306 offset_addr = if add then (R[n] + R[m]) else (R[n] - R[m]); 10307 address = if index then offset_addr else R[n]; 10308 MemA[address,4] = R[t]; 10309 MemA[address+4,4] = R[t2]; 10310 if wback then R[n] = offset_addr; 10311#endif 10312 10313 bool success = false; 10314 10315 if (ConditionPassed(opcode)) 10316 { 10317 uint32_t t; 10318 uint32_t t2; 10319 uint32_t n; 10320 uint32_t m; 10321 bool index; 10322 bool add; 10323 bool wback; 10324 10325 switch (encoding) 10326 { 10327 case eEncodingA1: 10328 // if Rt<0> == ‘1’ then UNPREDICTABLE; 10329 // t = UInt(Rt); t2 = t+1; n = UInt(Rn); m = UInt(Rm); 10330 t = Bits32 (opcode, 15, 12); 10331 if (BitIsSet (t, 0)) 10332 return false; 10333 10334 t2 = t+1; 10335 n = Bits32 (opcode, 19, 16); 10336 m = Bits32 (opcode, 3, 0); 10337 10338 // index = (P == ‘1’); add = (U == ‘1’); wback = (P == ‘0’) || (W == ‘1’); 10339 index = BitIsSet (opcode, 24); 10340 add = BitIsSet (opcode, 23); 10341 wback = BitIsClear (opcode, 24) || BitIsSet (opcode, 21); 10342 10343 // if P == ‘0’ && W == ‘1’ then UNPREDICTABLE; 10344 if (BitIsClear (opcode, 24) && BitIsSet (opcode, 21)) 10345 return false; 10346 10347 // if t2 == 15 || m == 15 then UNPREDICTABLE; 10348 if ((t2 == 15) || (m == 15)) 10349 return false; 10350 10351 // if wback && (n == 15 || n == t || n == t2) then UNPREDICTABLE; 10352 if (wback && ((n == 15) || (n == t) || (n == t2))) 10353 return false; 10354 10355 // if ArchVersion() < 6 && wback && m == n then UNPREDICTABLE; 10356 if ((ArchVersion() < 6) && wback && (m == n)) 10357 return false; 10358 10359 break; 10360 10361 default: 10362 return false; 10363 } 10364 10365 Register base_reg; 10366 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n); 10367 Register offset_reg; 10368 offset_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + m); 10369 Register data_reg; 10370 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + t); 10371 10372 uint32_t Rn = ReadCoreReg (n, &success); 10373 if (!success) 10374 return false; 10375 10376 uint32_t Rm = ReadCoreReg (m, &success); 10377 if (!success) 10378 return false; 10379 10380 // offset_addr = if add then (R[n] + R[m]) else (R[n] - R[m]); 10381 addr_t offset_addr; 10382 if (add) 10383 offset_addr = Rn + Rm; 10384 else 10385 offset_addr = Rn - Rm; 10386 10387 // address = if index then offset_addr else R[n]; 10388 addr_t address; 10389 if (index) 10390 address = offset_addr; 10391 else 10392 address = Rn; 10393 // MemA[address,4] = R[t]; 10394 uint32_t Rt = ReadCoreReg (t, &success); 10395 if (!success) 10396 return false; 10397 10398 EmulateInstruction::Context context; 10399 context.type = eContextRegisterStore; 10400 context.SetRegisterToRegisterPlusIndirectOffset (base_reg, offset_reg, data_reg); 10401 10402 const uint32_t addr_byte_size = GetAddressByteSize(); 10403 10404 if (!MemAWrite (context, address, Rt, addr_byte_size)) 10405 return false; 10406 10407 // MemA[address+4,4] = R[t2]; 10408 uint32_t Rt2 = ReadCoreReg (t2, &success); 10409 if (!success) 10410 return false; 10411 10412 data_reg.num = dwarf_r0 + t2; 10413 10414 context.SetRegisterToRegisterPlusIndirectOffset (base_reg, offset_reg, data_reg); 10415 10416 if (!MemAWrite (context, address + 4, Rt2, addr_byte_size)) 10417 return false; 10418 10419 // if wback then R[n] = offset_addr; 10420 if (wback) 10421 { 10422 context.type = eContextAdjustBaseRegister; 10423 context.SetAddress (offset_addr); 10424 10425 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr)) 10426 return false; 10427 10428 } 10429 } 10430 return true; 10431} 10432 10433// A8.6.319 VLDM 10434// Vector Load Multiple loads multiple extension registers from consecutive memory locations using an address from 10435// an ARM core register. 10436bool 10437EmulateInstructionARM::EmulateVLDM (const uint32_t opcode, const ARMEncoding encoding) 10438{ 10439#if 0 10440 if ConditionPassed() then 10441 EncodingSpecificOperations(); CheckVFPEnabled(TRUE); NullCheckIfThumbEE(n); 10442 address = if add then R[n] else R[n]-imm32; 10443 if wback then R[n] = if add then R[n}+imm32 else R[n]-imm32; 10444 for r = 0 to regs-1 10445 if single_regs then 10446 S[d+r] = MemA[address,4]; address = address+4; 10447 else 10448 word1 = MemA[address,4]; word2 = MemA[address+4,4]; address = address+8; 10449 // Combine the word-aligned words in the correct order for current endianness. 10450 D[d+r] = if BigEndian() then word1:word2 else word2:word1; 10451#endif 10452 10453 bool success = false; 10454 10455 if (ConditionPassed(opcode)) 10456 { 10457 bool single_regs; 10458 bool add; 10459 bool wback; 10460 uint32_t d; 10461 uint32_t n; 10462 uint32_t imm32; 10463 uint32_t regs; 10464 10465 switch (encoding) 10466 { 10467 case eEncodingT1: 10468 case eEncodingA1: 10469 // if P == ‘0’ && U == ‘0’ && W == ‘0’ then SEE “Related encodings”; 10470 // if P == ‘0’ && U == ‘1’ && W == ‘1’ && Rn == ‘1101’ then SEE VPOP; 10471 // if P == ‘1’ && W == ‘0’ then SEE VLDR; 10472 // if P == U && W == ‘1’ then UNDEFINED; 10473 if ((Bit32 (opcode, 24) == Bit32 (opcode, 23)) && BitIsSet (opcode, 21)) 10474 return false; 10475 10476 // // Remaining combinations are PUW = 010 (IA without !), 011 (IA with !), 101 (DB with !) 10477 // single_regs = FALSE; add = (U == ‘1’); wback = (W == ‘1’); 10478 single_regs = false; 10479 add = BitIsSet (opcode, 23); 10480 wback = BitIsSet (opcode, 21); 10481 10482 // d = UInt(D:Vd); n = UInt(Rn); imm32 = ZeroExtend(imm8:’00’, 32); 10483 d = (Bit32 (opcode, 22) << 4) | Bits32 (opcode, 15, 12); 10484 n = Bits32 (opcode, 19, 16); 10485 imm32 = Bits32 (opcode, 7, 0) << 2; 10486 10487 // regs = UInt(imm8) DIV 2; // If UInt(imm8) is odd, see “FLDMX”. 10488 regs = Bits32 (opcode, 7, 0) / 2; 10489 10490 // if n == 15 && (wback || CurrentInstrSet() != InstrSet_ARM) then UNPREDICTABLE; 10491 if (n == 15 && (wback || CurrentInstrSet() != eModeARM)) 10492 return false; 10493 10494 // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE; 10495 if ((regs == 0) || (regs > 16) || ((d + regs) > 32)) 10496 return false; 10497 10498 break; 10499 10500 case eEncodingT2: 10501 case eEncodingA2: 10502 // if P == ‘0’ && U == ‘0’ && W == ‘0’ then SEE “Related encodings”; 10503 // if P == ‘0’ && U == ‘1’ && W == ‘1’ && Rn == ‘1101’ then SEE VPOP; 10504 // if P == ‘1’ && W == ‘0’ then SEE VLDR; 10505 // if P == U && W == ‘1’ then UNDEFINED; 10506 if ((Bit32 (opcode, 24) == Bit32 (opcode, 23)) && BitIsSet (opcode, 21)) 10507 return false; 10508 10509 // // Remaining combinations are PUW = 010 (IA without !), 011 (IA with !), 101 (DB with !) 10510 // single_regs = TRUE; add = (U == ‘1’); wback = (W == ‘1’); d = UInt(Vd:D); n = UInt(Rn); 10511 single_regs = true; 10512 add = BitIsSet (opcode, 23); 10513 wback = BitIsSet (opcode, 21); 10514 d = (Bits32 (opcode, 15, 12) << 1) | Bit32 (opcode, 22); 10515 n = Bits32 (opcode, 19, 16); 10516 10517 // imm32 = ZeroExtend(imm8:’00’, 32); regs = UInt(imm8); 10518 imm32 = Bits32 (opcode, 7, 0) << 2; 10519 regs = Bits32 (opcode, 7, 0); 10520 10521 // if n == 15 && (wback || CurrentInstrSet() != InstrSet_ARM) then UNPREDICTABLE; 10522 if ((n == 15) && (wback || (CurrentInstrSet() != eModeARM))) 10523 return false; 10524 10525 // if regs == 0 || (d+regs) > 32 then UNPREDICTABLE; 10526 if ((regs == 0) || ((d + regs) > 32)) 10527 return false; 10528 break; 10529 10530 default: 10531 return false; 10532 } 10533 10534 Register base_reg; 10535 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n); 10536 10537 uint32_t Rn = ReadCoreReg (n, &success); 10538 if (!success) 10539 return false; 10540 10541 // address = if add then R[n] else R[n]-imm32; 10542 addr_t address; 10543 if (add) 10544 address = Rn; 10545 else 10546 address = Rn - imm32; 10547 10548 // if wback then R[n] = if add then R[n}+imm32 else R[n]-imm32; 10549 EmulateInstruction::Context context; 10550 10551 if (wback) 10552 { 10553 uint32_t value; 10554 if (add) 10555 value = Rn + imm32; 10556 else 10557 value = Rn - imm32; 10558 10559 context.type = eContextAdjustBaseRegister; 10560 context.SetImmediateSigned (value - Rn); 10561 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, value)) 10562 return false; 10563 10564 } 10565 10566 const uint32_t addr_byte_size = GetAddressByteSize(); 10567 uint32_t start_reg = single_regs ? dwarf_s0 : dwarf_d0; 10568 10569 context.type = eContextRegisterLoad; 10570 10571 // for r = 0 to regs-1 10572 for (uint32_t r = 0; r < regs; ++r) 10573 { 10574 if (single_regs) 10575 { 10576 // S[d+r] = MemA[address,4]; address = address+4; 10577 context.SetRegisterPlusOffset (base_reg, address - Rn); 10578 10579 uint32_t data = MemARead (context, address, addr_byte_size, 0, &success); 10580 if (!success) 10581 return false; 10582 10583 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, start_reg + d + r, data)) 10584 return false; 10585 10586 address = address + 4; 10587 } 10588 else 10589 { 10590 // word1 = MemA[address,4]; word2 = MemA[address+4,4]; address = address+8; 10591 context.SetRegisterPlusOffset (base_reg, address - Rn); 10592 uint32_t word1 = MemARead (context, address, addr_byte_size, 0, &success); 10593 if (!success) 10594 return false; 10595 10596 context.SetRegisterPlusOffset (base_reg, (address + 4) - Rn); 10597 uint32_t word2 = MemARead (context, address + 4, addr_byte_size, 0, &success); 10598 if (!success) 10599 return false; 10600 10601 address = address + 8; 10602 // // Combine the word-aligned words in the correct order for current endianness. 10603 // D[d+r] = if BigEndian() then word1:word2 else word2:word1; 10604 uint64_t data; 10605 if (m_byte_order == eByteOrderBig) 10606 { 10607 data = word1; 10608 data = (data << 32) | word2; 10609 } 10610 else 10611 { 10612 data = word2; 10613 data = (data << 32) | word1; 10614 } 10615 10616 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, start_reg + d + r, data)) 10617 return false; 10618 } 10619 } 10620 } 10621 return true; 10622} 10623 10624// A8.6.399 VSTM 10625// Vector Store Multiple stores multiple extension registers to consecutive memory locations using an address from an 10626// ARM core register. 10627bool 10628EmulateInstructionARM::EmulateVSTM (const uint32_t opcode, const ARMEncoding encoding) 10629{ 10630#if 0 10631 if ConditionPassed() then 10632 EncodingSpecificOperations(); CheckVFPEnabled(TRUE); NullCheckIfThumbEE(n); 10633 address = if add then R[n] else R[n]-imm32; 10634 if wback then R[n] = if add then R[n}+imm32 else R[n]-imm32; 10635 for r = 0 to regs-1 10636 if single_regs then 10637 MemA[address,4] = S[d+r]; address = address+4; 10638 else 10639 // Store as two word-aligned words in the correct order for current endianness. 10640 MemA[address,4] = if BigEndian() then D[d+r]<63:32> else D[d+r]<31:0>; 10641 MemA[address+4,4] = if BigEndian() then D[d+r]<31:0> else D[d+r]<63:32>; 10642 address = address+8; 10643#endif 10644 10645 bool success = false; 10646 10647 if (ConditionPassed (opcode)) 10648 { 10649 bool single_regs; 10650 bool add; 10651 bool wback; 10652 uint32_t d; 10653 uint32_t n; 10654 uint32_t imm32; 10655 uint32_t regs; 10656 10657 switch (encoding) 10658 { 10659 case eEncodingT1: 10660 case eEncodingA1: 10661 // if P == ‘0’ && U == ‘0’ && W == ‘0’ then SEE “Related encodings”; 10662 // if P == ‘1’ && U == ‘0’ && W == ‘1’ && Rn == ‘1101’ then SEE VPUSH; 10663 // if P == ‘1’ && W == ‘0’ then SEE VSTR; 10664 // if P == U && W == ‘1’ then UNDEFINED; 10665 if ((Bit32 (opcode, 24) == Bit32 (opcode, 23)) && BitIsSet (opcode, 21)) 10666 return false; 10667 10668 // // Remaining combinations are PUW = 010 (IA without !), 011 (IA with !), 101 (DB with !) 10669 // single_regs = FALSE; add = (U == ‘1’); wback = (W == ‘1’); 10670 single_regs = false; 10671 add = BitIsSet (opcode, 23); 10672 wback = BitIsSet (opcode, 21); 10673 10674 // d = UInt(D:Vd); n = UInt(Rn); imm32 = ZeroExtend(imm8:’00’, 32); 10675 d = (Bit32 (opcode, 22) << 4) | Bits32 (opcode, 15, 12); 10676 n = Bits32 (opcode, 19, 16); 10677 imm32 = Bits32 (opcode, 7, 0) << 2; 10678 10679 // regs = UInt(imm8) DIV 2; // If UInt(imm8) is odd, see “FSTMX”. 10680 regs = Bits32 (opcode, 7, 0) / 2; 10681 10682 // if n == 15 && (wback || CurrentInstrSet() != InstrSet_ARM) then UNPREDICTABLE; 10683 if ((n == 15) && (wback || (CurrentInstrSet() != eModeARM))) 10684 return false; 10685 10686 // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE; 10687 if ((regs == 0) || (regs > 16) || ((d + regs) > 32)) 10688 return false; 10689 10690 break; 10691 10692 case eEncodingT2: 10693 case eEncodingA2: 10694 // if P == ‘0’ && U == ‘0’ && W == ‘0’ then SEE “Related encodings”; 10695 // if P == ‘1’ && U == ‘0’ && W == ‘1’ && Rn == ‘1101’ then SEE VPUSH; 10696 // if P == ‘1’ && W == ‘0’ then SEE VSTR; 10697 // if P == U && W == ‘1’ then UNDEFINED; 10698 if ((Bit32 (opcode, 24) == Bit32 (opcode, 23)) && BitIsSet (opcode, 21)) 10699 return false; 10700 10701 // // Remaining combinations are PUW = 010 (IA without !), 011 (IA with !), 101 (DB with !) 10702 // single_regs = TRUE; add = (U == ‘1’); wback = (W == ‘1’); d = UInt(Vd:D); n = UInt(Rn); 10703 single_regs = true; 10704 add = BitIsSet (opcode, 23); 10705 wback = BitIsSet (opcode, 21); 10706 d = (Bits32 (opcode, 15, 12) << 1) | Bit32 (opcode, 22); 10707 n = Bits32 (opcode, 19, 16); 10708 10709 // imm32 = ZeroExtend(imm8:’00’, 32); regs = UInt(imm8); 10710 imm32 = Bits32 (opcode, 7, 0) << 2; 10711 regs = Bits32 (opcode, 7, 0); 10712 10713 // if n == 15 && (wback || CurrentInstrSet() != InstrSet_ARM) then UNPREDICTABLE; 10714 if ((n == 15) && (wback || (CurrentInstrSet () != eModeARM))) 10715 return false; 10716 10717 // if regs == 0 || (d+regs) > 32 then UNPREDICTABLE; 10718 if ((regs == 0) || ((d + regs) > 32)) 10719 return false; 10720 10721 break; 10722 10723 default: 10724 return false; 10725 } 10726 10727 Register base_reg; 10728 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n); 10729 10730 uint32_t Rn = ReadCoreReg (n, &success); 10731 if (!success) 10732 return false; 10733 10734 // address = if add then R[n] else R[n]-imm32; 10735 addr_t address; 10736 if (add) 10737 address = Rn; 10738 else 10739 address = Rn - imm32; 10740 10741 EmulateInstruction::Context context; 10742 // if wback then R[n] = if add then R[n}+imm32 else R[n]-imm32; 10743 if (wback) 10744 { 10745 uint32_t value; 10746 if (add) 10747 value = Rn + imm32; 10748 else 10749 value = Rn - imm32; 10750 10751 context.type = eContextAdjustBaseRegister; 10752 context.SetRegisterPlusOffset (base_reg, value - Rn); 10753 10754 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, value)) 10755 return false; 10756 } 10757 10758 const uint32_t addr_byte_size = GetAddressByteSize(); 10759 uint32_t start_reg = single_regs ? dwarf_s0 : dwarf_d0; 10760 10761 context.type = eContextRegisterStore; 10762 // for r = 0 to regs-1 10763 for (int r = 0; r < regs; ++r) 10764 { 10765 Register data_reg; 10766 data_reg.SetRegister (eRegisterKindDWARF, 0); 10767 if (single_regs) 10768 { 10769 // MemA[address,4] = S[d+r]; address = address+4; 10770 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, start_reg + d + r, 0, &success); 10771 if (!success) 10772 return false; 10773 10774 data_reg.num = start_reg + d + r; 10775 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, address - Rn); 10776 if (!MemAWrite (context, address, data, addr_byte_size)) 10777 return false; 10778 10779 address = address + 4; 10780 } 10781 else 10782 { 10783 // // Store as two word-aligned words in the correct order for current endianness. 10784 // MemA[address,4] = if BigEndian() then D[d+r]<63:32> else D[d+r]<31:0>; 10785 // MemA[address+4,4] = if BigEndian() then D[d+r]<31:0> else D[d+r]<63:32>; 10786 uint64_t data = ReadRegisterUnsigned (eRegisterKindDWARF, start_reg + d + r, 0, &success); 10787 if (!success) 10788 return false; 10789 10790 data_reg.num = start_reg + d + r; 10791 10792 if (m_byte_order == eByteOrderBig) 10793 { 10794 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, address - Rn); 10795 if (!MemAWrite (context, address, Bits64 (data, 63, 32), addr_byte_size)) 10796 return false; 10797 10798 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, (address + 4) - Rn); 10799 if (!MemAWrite (context, address+ 4, Bits64 (data, 31, 0), addr_byte_size)) 10800 return false; 10801 } 10802 else 10803 { 10804 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, address - Rn); 10805 if (!MemAWrite (context, address, Bits64 (data, 31, 0), addr_byte_size)) 10806 return false; 10807 10808 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, (address + 4) - Rn); 10809 if (!MemAWrite (context, address + 4, Bits64 (data, 63, 32), addr_byte_size)) 10810 return false; 10811 } 10812 // address = address+8; 10813 address = address + 8; 10814 } 10815 } 10816 } 10817 return true; 10818} 10819 10820// A8.6.320 10821// This instruciton loads a single extension register fronm memory, using an address from an ARM core register, with 10822// an optional offset. 10823bool 10824EmulateInstructionARM::EmulateVLDR (const uint32_t opcode, ARMEncoding encoding) 10825{ 10826#if 0 10827 if ConditionPassed() then 10828 EncodingSpecificOperations(); CheckVFPEnabled(TRUE); NullCheckIfThumbEE(n); 10829 base = if n == 15 then Align(PC,4) else R[n]; 10830 address = if add then (base + imm32) else (base - imm32); 10831 if single_reg then 10832 S[d] = MemA[address,4]; 10833 else 10834 word1 = MemA[address,4]; word2 = MemA[address+4,4]; 10835 // Combine the word-aligned words in the correct order for current endianness. 10836 D[d] = if BigEndian() then word1:word2 else word2:word1; 10837#endif 10838 10839 bool success = false; 10840 10841 if (ConditionPassed (opcode)) 10842 { 10843 bool single_reg; 10844 bool add; 10845 uint32_t imm32; 10846 uint32_t d; 10847 uint32_t n; 10848 10849 switch (encoding) 10850 { 10851 case eEncodingT1: 10852 case eEncodingA1: 10853 // single_reg = FALSE; add = (U == ‘1’); imm32 = ZeroExtend(imm8:’00’, 32); 10854 single_reg = false; 10855 add = BitIsSet (opcode, 23); 10856 imm32 = Bits32 (opcode, 7, 0) << 2; 10857 10858 // d = UInt(D:Vd); n = UInt(Rn); 10859 d = (Bit32 (opcode, 22) << 4) | Bits32 (opcode, 15, 12); 10860 n = Bits32 (opcode, 19, 16); 10861 10862 break; 10863 10864 case eEncodingT2: 10865 case eEncodingA2: 10866 // single_reg = TRUE; add = (U == ‘1’); imm32 = ZeroExtend(imm8:’00’, 32); 10867 single_reg = true; 10868 add = BitIsSet (opcode, 23); 10869 imm32 = Bits32 (opcode, 7, 0) << 2; 10870 10871 // d = UInt(Vd:D); n = UInt(Rn); 10872 d = (Bits32 (opcode, 15, 12) << 1) | Bit32 (opcode, 22); 10873 n = Bits32 (opcode, 19, 16); 10874 10875 break; 10876 10877 default: 10878 return false; 10879 } 10880 Register base_reg; 10881 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n); 10882 10883 uint32_t Rn = ReadCoreReg (n, &success); 10884 if (!success) 10885 return false; 10886 10887 // base = if n == 15 then Align(PC,4) else R[n]; 10888 uint32_t base; 10889 if (n == 15) 10890 base = AlignPC (Rn); 10891 else 10892 base = Rn; 10893 10894 // address = if add then (base + imm32) else (base - imm32); 10895 addr_t address; 10896 if (add) 10897 address = base + imm32; 10898 else 10899 address = base - imm32; 10900 10901 const uint32_t addr_byte_size = GetAddressByteSize(); 10902 uint32_t start_reg = single_reg ? dwarf_s0 : dwarf_d0; 10903 10904 EmulateInstruction::Context context; 10905 context.type = eContextRegisterLoad; 10906 context.SetRegisterPlusOffset (base_reg, address - base); 10907 10908 if (single_reg) 10909 { 10910 // S[d] = MemA[address,4]; 10911 uint32_t data = MemARead (context, address, addr_byte_size, 0, &success); 10912 if (!success) 10913 return false; 10914 10915 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, start_reg + d, data)) 10916 return false; 10917 } 10918 else 10919 { 10920 // word1 = MemA[address,4]; word2 = MemA[address+4,4]; 10921 uint32_t word1 = MemARead (context, address, addr_byte_size, 0, &success); 10922 if (!success) 10923 return false; 10924 10925 context.SetRegisterPlusOffset (base_reg, (address + 4) - base); 10926 uint32_t word2 = MemARead (context, address + 4, addr_byte_size, 0, &success); 10927 if (!success) 10928 return false; 10929 // // Combine the word-aligned words in the correct order for current endianness. 10930 // D[d] = if BigEndian() then word1:word2 else word2:word1; 10931 uint64_t data64; 10932 if (m_byte_order == eByteOrderBig) 10933 { 10934 data64 = word1; 10935 data64 = (data64 << 32) | word2; 10936 } 10937 else 10938 { 10939 data64 = word2; 10940 data64 = (data64 << 32) | word1; 10941 } 10942 10943 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, start_reg + d, data64)) 10944 return false; 10945 } 10946 } 10947 return true; 10948} 10949 10950// A8.6.400 VSTR 10951// This instruction stores a signle extension register to memory, using an address from an ARM core register, with an 10952// optional offset. 10953bool 10954EmulateInstructionARM::EmulateVSTR (const uint32_t opcode, ARMEncoding encoding) 10955{ 10956#if 0 10957 if ConditionPassed() then 10958 EncodingSpecificOperations(); CheckVFPEnabled(TRUE); NullCheckIfThumbEE(n); 10959 address = if add then (R[n] + imm32) else (R[n] - imm32); 10960 if single_reg then 10961 MemA[address,4] = S[d]; 10962 else 10963 // Store as two word-aligned words in the correct order for current endianness. 10964 MemA[address,4] = if BigEndian() then D[d]<63:32> else D[d]<31:0>; 10965 MemA[address+4,4] = if BigEndian() then D[d]<31:0> else D[d]<63:32>; 10966#endif 10967 10968 bool success = false; 10969 10970 if (ConditionPassed (opcode)) 10971 { 10972 bool single_reg; 10973 bool add; 10974 uint32_t imm32; 10975 uint32_t d; 10976 uint32_t n; 10977 10978 switch (encoding) 10979 { 10980 case eEncodingT1: 10981 case eEncodingA1: 10982 // single_reg = FALSE; add = (U == ‘1’); imm32 = ZeroExtend(imm8:’00’, 32); 10983 single_reg = false; 10984 add = BitIsSet (opcode, 23); 10985 imm32 = Bits32 (opcode, 7, 0) << 2; 10986 10987 // d = UInt(D:Vd); n = UInt(Rn); 10988 d = (Bit32 (opcode, 22) << 4) | Bits32 (opcode, 15, 12); 10989 n = Bits32 (opcode, 19, 16); 10990 10991 // if n == 15 && CurrentInstrSet() != InstrSet_ARM then UNPREDICTABLE; 10992 if ((n == 15) && (CurrentInstrSet() != eModeARM)) 10993 return false; 10994 10995 break; 10996 10997 case eEncodingT2: 10998 case eEncodingA2: 10999 // single_reg = TRUE; add = (U == ‘1’); imm32 = ZeroExtend(imm8:’00’, 32); 11000 single_reg = true; 11001 add = BitIsSet (opcode, 23); 11002 imm32 = Bits32 (opcode, 7, 0) << 2; 11003 11004 // d = UInt(Vd:D); n = UInt(Rn); 11005 d = (Bits32 (opcode, 15, 12) << 1) | Bit32 (opcode, 22); 11006 n = Bits32 (opcode, 19, 16); 11007 11008 // if n == 15 && CurrentInstrSet() != InstrSet_ARM then UNPREDICTABLE; 11009 if ((n == 15) && (CurrentInstrSet() != eModeARM)) 11010 return false; 11011 11012 break; 11013 11014 default: 11015 return false; 11016 } 11017 11018 Register base_reg; 11019 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n); 11020 11021 uint32_t Rn = ReadCoreReg (n, &success); 11022 if (!success) 11023 return false; 11024 11025 // address = if add then (R[n] + imm32) else (R[n] - imm32); 11026 addr_t address; 11027 if (add) 11028 address = Rn + imm32; 11029 else 11030 address = Rn - imm32; 11031 11032 const uint32_t addr_byte_size = GetAddressByteSize(); 11033 uint32_t start_reg = single_reg ? dwarf_s0 : dwarf_d0; 11034 11035 Register data_reg; 11036 data_reg.SetRegister (eRegisterKindDWARF, start_reg + d); 11037 EmulateInstruction::Context context; 11038 context.type = eContextRegisterStore; 11039 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, address - Rn); 11040 11041 if (single_reg) 11042 { 11043 // MemA[address,4] = S[d]; 11044 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, start_reg + d, 0, &success); 11045 if (!success) 11046 return false; 11047 11048 if (!MemAWrite (context, address, data, addr_byte_size)) 11049 return false; 11050 } 11051 else 11052 { 11053 // // Store as two word-aligned words in the correct order for current endianness. 11054 // MemA[address,4] = if BigEndian() then D[d]<63:32> else D[d]<31:0>; 11055 // MemA[address+4,4] = if BigEndian() then D[d]<31:0> else D[d]<63:32>; 11056 uint64_t data = ReadRegisterUnsigned (eRegisterKindDWARF, start_reg + d, 0, &success); 11057 if (!success) 11058 return false; 11059 11060 if (m_byte_order == eByteOrderBig) 11061 { 11062 if (!MemAWrite (context, address, Bits64 (data, 63, 32), addr_byte_size)) 11063 return false; 11064 11065 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, (address + 4) - Rn); 11066 if (!MemAWrite (context, address + 4, Bits64 (data, 31, 0), addr_byte_size)) 11067 return false; 11068 } 11069 else 11070 { 11071 if (!MemAWrite (context, address, Bits64 (data, 31, 0), addr_byte_size)) 11072 return false; 11073 11074 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, (address + 4) - Rn); 11075 if (!MemAWrite (context, address + 4, Bits64 (data, 63, 32), addr_byte_size)) 11076 return false; 11077 } 11078 } 11079 } 11080 return true; 11081} 11082 11083// A8.6.307 VLDI1 (multiple single elements) 11084// This instruction loads elements from memory into one, two, three or four registers, without de-interleaving. Every 11085// element of each register is loaded. 11086bool 11087EmulateInstructionARM::EmulateVLD1Multiple (const uint32_t opcode, ARMEncoding encoding) 11088{ 11089#if 0 11090 if ConditionPassed() then 11091 EncodingSpecificOperations(); CheckAdvSIMDEnabled(); NullCheckIfThumbEE(n); 11092 address = R[n]; if (address MOD alignment) != 0 then GenerateAlignmentException(); 11093 if wback then R[n] = R[n] + (if register_index then R[m] else 8*regs); 11094 for r = 0 to regs-1 11095 for e = 0 to elements-1 11096 Elem[D[d+r],e,esize] = MemU[address,ebytes]; 11097 address = address + ebytes; 11098#endif 11099 11100 bool success = false; 11101 11102 if (ConditionPassed (opcode)) 11103 { 11104 uint32_t regs; 11105 uint32_t alignment; 11106 uint32_t ebytes; 11107 uint32_t esize; 11108 uint32_t elements; 11109 uint32_t d; 11110 uint32_t n; 11111 uint32_t m; 11112 bool wback; 11113 bool register_index; 11114 11115 switch (encoding) 11116 { 11117 case eEncodingT1: 11118 case eEncodingA1: 11119 { 11120 // case type of 11121 // when ‘0111’ 11122 // regs = 1; if align<1> == ‘1’ then UNDEFINED; 11123 // when ‘1010’ 11124 // regs = 2; if align == ‘11’ then UNDEFINED; 11125 // when ‘0110’ 11126 // regs = 3; if align<1> == ‘1’ then UNDEFINED; 11127 // when ‘0010’ 11128 // regs = 4; 11129 // otherwise 11130 // SEE “Related encodings”; 11131 uint32_t type = Bits32 (opcode, 11, 8); 11132 uint32_t align = Bits32 (opcode, 5, 4); 11133 if (type == 7) // '0111' 11134 { 11135 regs = 1; 11136 if (BitIsSet (align, 1)) 11137 return false; 11138 } 11139 else if (type == 10) // '1010' 11140 { 11141 regs = 2; 11142 if (align == 3) 11143 return false; 11144 11145 } 11146 else if (type == 6) // '0110' 11147 { 11148 regs = 3; 11149 if (BitIsSet (align, 1)) 11150 return false; 11151 } 11152 else if (type == 2) // '0010' 11153 { 11154 regs = 4; 11155 } 11156 else 11157 return false; 11158 11159 // alignment = if align == ‘00’ then 1 else 4 << UInt(align); 11160 if (align == 0) 11161 alignment = 1; 11162 else 11163 alignment = 4 << align; 11164 11165 // ebytes = 1 << UInt(size); esize = 8 * ebytes; elements = 8 DIV ebytes; 11166 ebytes = 1 << Bits32 (opcode, 7, 6); 11167 esize = 8 * ebytes; 11168 elements = 8 / ebytes; 11169 11170 // d = UInt(D:Vd); n = UInt(Rn); m = UInt(Rm); 11171 d = (Bit32 (opcode, 22) << 4) | Bits32 (opcode, 15, 12); 11172 n = Bits32 (opcode, 19, 15); 11173 m = Bits32 (opcode, 3, 0); 11174 11175 // wback = (m != 15); register_index = (m != 15 && m != 13); 11176 wback = (m != 15); 11177 register_index = ((m != 15) && (m != 13)); 11178 11179 // if d+regs > 32 then UNPREDICTABLE; 11180 if ((d + regs) > 32) 11181 return false; 11182 } 11183 break; 11184 11185 default: 11186 return false; 11187 } 11188 11189 Register base_reg; 11190 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n); 11191 11192 uint32_t Rn = ReadCoreReg (n, &success); 11193 if (!success) 11194 return false; 11195 11196 // address = R[n]; if (address MOD alignment) != 0 then GenerateAlignmentException(); 11197 addr_t address = Rn; 11198 if ((address % alignment) != 0) 11199 return false; 11200 11201 EmulateInstruction::Context context; 11202 // if wback then R[n] = R[n] + (if register_index then R[m] else 8*regs); 11203 if (wback) 11204 { 11205 uint32_t Rm = ReadCoreReg (m, &success); 11206 if (!success) 11207 return false; 11208 11209 uint32_t offset; 11210 if (register_index) 11211 offset = Rm; 11212 else 11213 offset = 8 * regs; 11214 11215 uint32_t value = Rn + offset; 11216 context.type = eContextAdjustBaseRegister; 11217 context.SetRegisterPlusOffset (base_reg, offset); 11218 11219 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, value)) 11220 return false; 11221 11222 } 11223 11224 // for r = 0 to regs-1 11225 for (int r = 0; r < regs; ++r) 11226 { 11227 // for e = 0 to elements-1 11228 uint64_t assembled_data = 0; 11229 for (int e = 0; e < elements; ++e) 11230 { 11231 // Elem[D[d+r],e,esize] = MemU[address,ebytes]; 11232 context.type = eContextRegisterLoad; 11233 context.SetRegisterPlusOffset (base_reg, address - Rn); 11234 uint64_t data = MemURead (context, address, ebytes, 0, &success); 11235 if (!success) 11236 return false; 11237 11238 assembled_data = (data << (e * esize)) | assembled_data; // New data goes to the left of existing data 11239 11240 // address = address + ebytes; 11241 address = address + ebytes; 11242 } 11243 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_d0 + d + r, assembled_data)) 11244 return false; 11245 } 11246 } 11247 return true; 11248} 11249 11250// A8.6.308 VLD1 (single element to one lane) 11251// 11252bool 11253EmulateInstructionARM::EmulateVLD1Single (const uint32_t opcode, const ARMEncoding encoding) 11254{ 11255#if 0 11256 if ConditionPassed() then 11257 EncodingSpecificOperations(); CheckAdvSIMDEnabled(); NullCheckIfThumbEE(n); 11258 address = R[n]; if (address MOD alignment) != 0 then GenerateAlignmentException(); 11259 if wback then R[n] = R[n] + (if register_index then R[m] else ebytes); 11260 Elem[D[d],index,esize] = MemU[address,ebytes]; 11261#endif 11262 11263 bool success = false; 11264 11265 if (ConditionPassed (opcode)) 11266 { 11267 uint32_t ebytes; 11268 uint32_t esize; 11269 uint32_t index; 11270 uint32_t alignment; 11271 uint32_t d; 11272 uint32_t n; 11273 uint32_t m; 11274 bool wback; 11275 bool register_index; 11276 11277 switch (encoding) 11278 { 11279 case eEncodingT1: 11280 case eEncodingA1: 11281 { 11282 uint32_t size = Bits32 (opcode, 11, 10); 11283 uint32_t index_align = Bits32 (opcode, 7, 4); 11284 // if size == ‘11’ then SEE VLD1 (single element to all lanes); 11285 if (size == 3) 11286 return EmulateVLD1SingleAll (opcode, encoding); 11287 // case size of 11288 if (size == 0) // when '00' 11289 { 11290 // if index_align<0> != ‘0’ then UNDEFINED; 11291 if (BitIsClear (index_align, 0)) 11292 return false; 11293 11294 // ebytes = 1; esize = 8; index = UInt(index_align<3:1>); alignment = 1; 11295 ebytes = 1; 11296 esize = 8; 11297 index = Bits32 (index_align, 3, 1); 11298 alignment = 1; 11299 } 11300 else if (size == 1) // when ‘01’ 11301 { 11302 // if index_align<1> != ‘0’ then UNDEFINED; 11303 if (BitIsClear (index_align, 1)) 11304 return false; 11305 11306 // ebytes = 2; esize = 16; index = UInt(index_align<3:2>); 11307 ebytes = 2; 11308 esize = 16; 11309 index = Bits32 (index_align, 3, 2); 11310 11311 // alignment = if index_align<0> == ‘0’ then 1 else 2; 11312 if (BitIsClear (index_align, 0)) 11313 alignment = 1; 11314 else 11315 alignment = 2; 11316 } 11317 else if (size == 2) // when ‘10’ 11318 { 11319 // if index_align<2> != ‘0’ then UNDEFINED; 11320 if (BitIsClear (index_align, 2)) 11321 return false; 11322 11323 // if index_align<1:0> != ‘00’ && index_align<1:0> != ‘11’ then UNDEFINED; 11324 if ((Bits32 (index_align, 1, 0) != 0) && (Bits32 (index_align, 1, 0) != 3)) 11325 return false; 11326 11327 // ebytes = 4; esize = 32; index = UInt(index_align<3>); 11328 ebytes = 4; 11329 esize = 32; 11330 index = Bit32 (index_align, 3); 11331 11332 // alignment = if index_align<1:0> == ‘00’ then 1 else 4; 11333 if (Bits32 (index_align, 1, 0) == 0) 11334 alignment = 1; 11335 else 11336 alignment = 4; 11337 } 11338 // d = UInt(D:Vd); n = UInt(Rn); m = UInt(Rm); 11339 d = (Bit32 (opcode, 22) << 4) | Bits32 (opcode, 15, 12); 11340 n = Bits32 (opcode, 19, 16); 11341 m = Bits32 (opcode, 3, 0); 11342 11343 // wback = (m != 15); register_index = (m != 15 && m != 13); if n == 15 then UNPREDICTABLE; 11344 wback = (m != 15); 11345 register_index = ((m != 15) && (m != 13)); 11346 11347 if (n == 15) 11348 return false; 11349 11350 } 11351 break; 11352 11353 default: 11354 return false; 11355 } 11356 11357 Register base_reg; 11358 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n); 11359 11360 uint32_t Rn = ReadCoreReg (n, &success); 11361 if (!success) 11362 return false; 11363 11364 // address = R[n]; if (address MOD alignment) != 0 then GenerateAlignmentException(); 11365 addr_t address = Rn; 11366 if ((address % alignment) != 0) 11367 return false; 11368 11369 EmulateInstruction::Context context; 11370 // if wback then R[n] = R[n] + (if register_index then R[m] else ebytes); 11371 if (wback) 11372 { 11373 uint32_t Rm = ReadCoreReg (m, &success); 11374 if (!success) 11375 return false; 11376 11377 uint32_t offset; 11378 if (register_index) 11379 offset = Rm; 11380 else 11381 offset = ebytes; 11382 11383 uint32_t value = Rn + offset; 11384 11385 context.type = eContextAdjustBaseRegister; 11386 context.SetRegisterPlusOffset (base_reg, offset); 11387 11388 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, value)) 11389 return false; 11390 } 11391 11392 // Elem[D[d],index,esize] = MemU[address,ebytes]; 11393 uint32_t element = MemURead (context, address, esize, 0, &success); 11394 if (!success) 11395 return false; 11396 11397 element = element << (index * esize); 11398 11399 uint64_t reg_data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_d0 + d, 0, &success); 11400 if (!success) 11401 return false; 11402 11403 uint64_t all_ones = -1; 11404 uint64_t mask = all_ones << ((index+1) * esize); // mask is all 1's to left of where 'element' goes, & all 0's 11405 // at element & to the right of element. 11406 if (index > 0) 11407 mask = mask | Bits64 (all_ones, (index * esize) - 1, 0); // add 1's to the right of where 'element' goes. 11408 // now mask should be 0's where element goes & 1's 11409 // everywhere else. 11410 11411 uint64_t masked_reg = reg_data & mask; // Take original reg value & zero out 'element' bits 11412 reg_data = masked_reg & element; // Put 'element' into those bits in reg_data. 11413 11414 context.type = eContextRegisterLoad; 11415 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + d, reg_data)) 11416 return false; 11417 } 11418 return true; 11419} 11420 11421// A8.6.391 VST1 (multiple single elements) 11422// Vector Store (multiple single elements) stores elements to memory from one, two, three, or four regsiters, without 11423// interleaving. Every element of each register is stored. 11424bool 11425EmulateInstructionARM::EmulateVST1Multiple (const uint32_t opcode, ARMEncoding encoding) 11426{ 11427#if 0 11428 if ConditionPassed() then 11429 EncodingSpecificOperations(); CheckAdvSIMDEnabled(); NullCheckIfThumbEE(n); 11430 address = R[n]; if (address MOD alignment) != 0 then GenerateAlignmentException(); 11431 if wback then R[n] = R[n] + (if register_index then R[m] else 8*regs); 11432 for r = 0 to regs-1 11433 for e = 0 to elements-1 11434 MemU[address,ebytes] = Elem[D[d+r],e,esize]; 11435 address = address + ebytes; 11436#endif 11437 11438 bool success = false; 11439 11440 if (ConditionPassed (opcode)) 11441 { 11442 uint32_t regs; 11443 uint32_t alignment; 11444 uint32_t ebytes; 11445 uint32_t esize; 11446 uint32_t elements; 11447 uint32_t d; 11448 uint32_t n; 11449 uint32_t m; 11450 bool wback; 11451 bool register_index; 11452 11453 switch (encoding) 11454 { 11455 case eEncodingT1: 11456 case eEncodingA1: 11457 { 11458 uint32_t type = Bits32 (opcode, 11, 8); 11459 uint32_t align = Bits32 (opcode, 5, 4); 11460 11461 // case type of 11462 if (type == 7) // when ‘0111’ 11463 { 11464 // regs = 1; if align<1> == ‘1’ then UNDEFINED; 11465 regs = 1; 11466 if (BitIsSet (align, 1)) 11467 return false; 11468 } 11469 else if (type == 10) // when ‘1010’ 11470 { 11471 // regs = 2; if align == ‘11’ then UNDEFINED; 11472 regs = 2; 11473 if (align == 3) 11474 return false; 11475 } 11476 else if (type == 6) // when ‘0110’ 11477 { 11478 // regs = 3; if align<1> == ‘1’ then UNDEFINED; 11479 regs = 3; 11480 if (BitIsSet (align, 1)) 11481 return false; 11482 } 11483 else if (type == 2) // when ‘0010’ 11484 // regs = 4; 11485 regs = 4; 11486 else // otherwise 11487 // SEE “Related encodings”; 11488 return false; 11489 11490 // alignment = if align == ‘00’ then 1 else 4 << UInt(align); 11491 if (align == 0) 11492 alignment = 0; 11493 else 11494 alignment = 4 << align; 11495 11496 // ebytes = 1 << UInt(size); esize = 8 * ebytes; elements = 8 DIV ebytes; 11497 ebytes = 1 << Bits32 (opcode,7, 6); 11498 esize = 8 * ebytes; 11499 elements = 8 / ebytes; 11500 11501 // d = UInt(D:Vd); n = UInt(Rn); m = UInt(Rm); 11502 d = (Bit32 (opcode, 22) << 4) | Bits32 (opcode, 15, 12); 11503 n = Bits32 (opcode, 19, 16); 11504 m = Bits32 (opcode, 3, 0); 11505 11506 // wback = (m != 15); register_index = (m != 15 && m != 13); 11507 wback = (m != 15); 11508 register_index = ((m != 15) && (m != 13)); 11509 11510 // if d+regs > 32 then UNPREDICTABLE; if n == 15 then UNPREDICTABLE; 11511 if ((d + regs) > 32) 11512 return false; 11513 11514 if (n == 15) 11515 return false; 11516 11517 } 11518 break; 11519 11520 default: 11521 return false; 11522 } 11523 11524 Register base_reg; 11525 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n); 11526 11527 uint32_t Rn = ReadCoreReg (n, &success); 11528 if (!success) 11529 return false; 11530 11531 // address = R[n]; if (address MOD alignment) != 0 then GenerateAlignmentException(); 11532 addr_t address = Rn; 11533 if ((address % alignment) != 0) 11534 return false; 11535 11536 EmulateInstruction::Context context; 11537 // if wback then R[n] = R[n] + (if register_index then R[m] else 8*regs); 11538 if (wback) 11539 { 11540 uint32_t Rm = ReadCoreReg (m, &success); 11541 if (!success) 11542 return false; 11543 11544 uint32_t offset; 11545 if (register_index) 11546 offset = Rm; 11547 else 11548 offset = 8 * regs; 11549 11550 context.type = eContextAdjustBaseRegister; 11551 context.SetRegisterPlusOffset (base_reg, offset); 11552 11553 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, Rn + offset)) 11554 return false; 11555 } 11556 11557 context.type = eContextRegisterStore; 11558 Register data_reg; 11559 data_reg.SetRegister (eRegisterKindDWARF, 0); 11560 // for r = 0 to regs-1 11561 for (int r = 0; r < regs; ++r) 11562 { 11563 data_reg.num = dwarf_d0 + d + r; 11564 uint64_t register_data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_d0 + d + r, 0, &success); 11565 if (!success) 11566 return false; 11567 11568 // for e = 0 to elements-1 11569 for (int e = 0; e < elements; ++e) 11570 { 11571 // MemU[address,ebytes] = Elem[D[d+r],e,esize]; 11572 uint64_t word = Bits64 (register_data, ((e + 1) * esize) - 1, e * esize); 11573 11574 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, address - Rn); 11575 if (!MemUWrite (context, address, word, ebytes)) 11576 return false; 11577 11578 // address = address + ebytes; 11579 address = address + ebytes; 11580 } 11581 } 11582 } 11583 return true; 11584} 11585 11586// A8.6.392 VST1 (single element from one lane) 11587// This instruction stores one element to memory from one element of a register. 11588bool 11589EmulateInstructionARM::EmulateVST1Single (const uint32_t opcode, ARMEncoding encoding) 11590{ 11591#if 0 11592 if ConditionPassed() then 11593 EncodingSpecificOperations(); CheckAdvSIMDEnabled(); NullCheckIfThumbEE(n); 11594 address = R[n]; if (address MOD alignment) != 0 then GenerateAlignmentException(); 11595 if wback then R[n] = R[n] + (if register_index then R[m] else ebytes); 11596 MemU[address,ebytes] = Elem[D[d],index,esize]; 11597#endif 11598 11599 bool success = false; 11600 11601 if (ConditionPassed (opcode)) 11602 { 11603 uint32_t ebytes; 11604 uint32_t esize; 11605 uint32_t index; 11606 uint32_t alignment; 11607 uint32_t d; 11608 uint32_t n; 11609 uint32_t m; 11610 bool wback; 11611 bool register_index; 11612 11613 switch (encoding) 11614 { 11615 case eEncodingT1: 11616 case eEncodingA1: 11617 { 11618 uint32_t size = Bits32 (opcode, 11, 10); 11619 uint32_t index_align = Bits32 (opcode, 7, 4); 11620 11621 // if size == ‘11’ then UNDEFINED; 11622 if (size == 3) 11623 return false; 11624 11625 // case size of 11626 if (size == 0) // when ‘00’ 11627 { 11628 // if index_align<0> != ‘0’ then UNDEFINED; 11629 if (BitIsClear (index_align, 0)) 11630 return false; 11631 // ebytes = 1; esize = 8; index = UInt(index_align<3:1>); alignment = 1; 11632 ebytes = 1; 11633 esize = 8; 11634 index = Bits32 (index_align, 3, 1); 11635 alignment = 1; 11636 } 11637 else if (size == 1) // when ‘01’ 11638 { 11639 // if index_align<1> != ‘0’ then UNDEFINED; 11640 if (BitIsClear (index_align, 1)) 11641 return false; 11642 11643 // ebytes = 2; esize = 16; index = UInt(index_align<3:2>); 11644 ebytes = 2; 11645 esize = 16; 11646 index = Bits32 (index_align, 3, 2); 11647 11648 // alignment = if index_align<0> == ‘0’ then 1 else 2; 11649 if (BitIsClear (index_align, 0)) 11650 alignment = 1; 11651 else 11652 alignment = 2; 11653 } 11654 else if (size == 2) // when ‘10’ 11655 { 11656 // if index_align<2> != ‘0’ then UNDEFINED; 11657 if (BitIsClear (index_align, 2)) 11658 return false; 11659 11660 // if index_align<1:0> != ‘00’ && index_align<1:0> != ‘11’ then UNDEFINED; 11661 if ((Bits32 (index_align, 1, 0) != 0) && (Bits32 (index_align, 1, 0) != 3)) 11662 return false; 11663 11664 // ebytes = 4; esize = 32; index = UInt(index_align<3>); 11665 ebytes = 4; 11666 esize = 32; 11667 index = Bit32 (index_align, 3); 11668 11669 // alignment = if index_align<1:0> == ‘00’ then 1 else 4; 11670 if (Bits32 (index_align, 1, 0) == 0) 11671 alignment = 1; 11672 else 11673 alignment = 4; 11674 } 11675 // d = UInt(D:Vd); n = UInt(Rn); m = UInt(Rm); 11676 d = (Bit32 (opcode, 22) << 4) | Bits32 (opcode, 15, 12); 11677 n = Bits32 (opcode, 19, 16); 11678 m = Bits32 (opcode, 3, 0); 11679 11680 // wback = (m != 15); register_index = (m != 15 && m != 13); if n == 15 then UNPREDICTABLE; 11681 wback = (m != 15); 11682 register_index = ((m != 15) && (m != 13)); 11683 11684 if (n == 15) 11685 return false; 11686 } 11687 break; 11688 11689 default: 11690 return false; 11691 } 11692 11693 Register base_reg; 11694 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n); 11695 11696 uint32_t Rn = ReadCoreReg (n, &success); 11697 if (!success) 11698 return false; 11699 11700 // address = R[n]; if (address MOD alignment) != 0 then GenerateAlignmentException(); 11701 addr_t address = Rn; 11702 if ((address % alignment) != 0) 11703 return false; 11704 11705 EmulateInstruction::Context context; 11706 // if wback then R[n] = R[n] + (if register_index then R[m] else ebytes); 11707 if (wback) 11708 { 11709 uint32_t Rm = ReadCoreReg (m, &success); 11710 if (!success) 11711 return false; 11712 11713 uint32_t offset; 11714 if (register_index) 11715 offset = Rm; 11716 else 11717 offset = ebytes; 11718 11719 context.type = eContextAdjustBaseRegister; 11720 context.SetRegisterPlusOffset (base_reg, offset); 11721 11722 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, Rn + offset)) 11723 return false; 11724 } 11725 11726 // MemU[address,ebytes] = Elem[D[d],index,esize]; 11727 uint64_t register_data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_d0 + d, 0, &success); 11728 if (!success) 11729 return false; 11730 11731 uint64_t word = Bits64 (register_data, ((index + 1) * esize) - 1, index * esize); 11732 11733 Register data_reg; 11734 data_reg.SetRegister (eRegisterKindDWARF, dwarf_d0 + d); 11735 context.type = eContextRegisterStore; 11736 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, address - Rn); 11737 11738 if (!MemUWrite (context, address, word, ebytes)) 11739 return false; 11740 } 11741 return true; 11742} 11743 11744// A8.6.309 VLD1 (single element to all lanes) 11745// This instruction loads one element from memory into every element of one or two vectors. 11746bool 11747EmulateInstructionARM::EmulateVLD1SingleAll (const uint32_t opcode, const ARMEncoding encoding) 11748{ 11749#if 0 11750 if ConditionPassed() then 11751 EncodingSpecificOperations(); CheckAdvSIMDEnabled(); NullCheckIfThumbEE(n); 11752 address = R[n]; if (address MOD alignment) != 0 then GenerateAlignmentException(); 11753 if wback then R[n] = R[n] + (if register_index then R[m] else ebytes); 11754 replicated_element = Replicate(MemU[address,ebytes], elements); 11755 for r = 0 to regs-1 11756 D[d+r] = replicated_element; 11757#endif 11758 11759 bool success = false; 11760 11761 if (ConditionPassed (opcode)) 11762 { 11763 uint32_t ebytes; 11764 uint32_t elements; 11765 uint32_t regs; 11766 uint32_t alignment; 11767 uint32_t d; 11768 uint32_t n; 11769 uint32_t m; 11770 bool wback; 11771 bool register_index; 11772 11773 switch (encoding) 11774 { 11775 case eEncodingT1: 11776 case eEncodingA1: 11777 { 11778 //if size == ‘11’ || (size == ‘00’ && a == ‘1’) then UNDEFINED; 11779 uint32_t size = Bits32 (opcode, 7, 6); 11780 if ((size == 3) || ((size == 0) && BitIsSet (opcode, 4))) 11781 return false; 11782 11783 //ebytes = 1 << UInt(size); elements = 8 DIV ebytes; regs = if T == ‘0’ then 1 else 2; 11784 ebytes = 1 << size; 11785 elements = 8 / ebytes; 11786 if (BitIsClear (opcode, 5)) 11787 regs = 1; 11788 else 11789 regs = 2; 11790 11791 //alignment = if a == ‘0’ then 1 else ebytes; 11792 if (BitIsClear (opcode, 4)) 11793 alignment = 1; 11794 else 11795 alignment = ebytes; 11796 11797 //d = UInt(D:Vd); n = UInt(Rn); m = UInt(Rm); 11798 d = (Bit32 (opcode, 22) << 4) | Bits32 (opcode, 15, 12); 11799 n = Bits32 (opcode, 19, 16); 11800 m = Bits32 (opcode, 3, 0); 11801 11802 //wback = (m != 15); register_index = (m != 15 && m != 13); 11803 wback = (m != 15); 11804 register_index = ((m != 15) && (m != 13)); 11805 11806 //if d+regs > 32 then UNPREDICTABLE; if n == 15 then UNPREDICTABLE; 11807 if ((d + regs) > 32) 11808 return false; 11809 11810 if (n == 15) 11811 return false; 11812 } 11813 break; 11814 11815 default: 11816 break; 11817 } 11818 11819 Register base_reg; 11820 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 +n); 11821 11822 uint32_t Rn = ReadCoreReg (n, &success); 11823 if (!success) 11824 return false; 11825 11826 // address = R[n]; if (address MOD alignment) != 0 then GenerateAlignmentException(); 11827 addr_t address = Rn; 11828 if ((address % alignment) != 0) 11829 return false; 11830 11831 EmulateInstruction::Context context; 11832 // if wback then R[n] = R[n] + (if register_index then R[m] else ebytes); 11833 if (wback) 11834 { 11835 uint32_t Rm = ReadCoreReg (m, &success); 11836 if (!success) 11837 return false; 11838 11839 uint32_t offset; 11840 if (register_index) 11841 offset = Rm; 11842 else 11843 offset = ebytes; 11844 11845 context.type = eContextAdjustBaseRegister; 11846 context.SetRegisterPlusOffset (base_reg, offset); 11847 11848 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, Rn + offset)) 11849 return false; 11850 } 11851 11852 // replicated_element = Replicate(MemU[address,ebytes], elements); 11853 11854 context.type = eContextRegisterLoad; 11855 uint64_t word = MemURead (context, address, ebytes, 0, &success); 11856 if (!success) 11857 return false; 11858 11859 uint64_t replicated_element; 11860 uint32_t esize = ebytes * 8; 11861 for (int e = 0; e < elements; ++e) 11862 replicated_element = (replicated_element << esize) | Bits64 (word, esize - 1, 0); 11863 11864 // for r = 0 to regs-1 11865 for (int r = 0; r < regs; ++r) 11866 { 11867 // D[d+r] = replicated_element; 11868 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_d0 + d + r, replicated_element)) 11869 return false; 11870 } 11871 } 11872 return true; 11873} 11874 11875// B6.2.13 SUBS PC, LR and related instructions 11876//The SUBS PC, LR, #<const? instruction provides an exception return without the use of the stack. It subtracts the 11877// immediate constant from the LR, branches to the resulting address, and also copies the SPSR to the CPSR. 11878bool 11879EmulateInstructionARM::EmulateSUBSPcLrEtc (const uint32_t opcode, const ARMEncoding encoding) 11880{ 11881#if 0 11882 if ConditionPassed() then 11883 EncodingSpecificOperations(); 11884 if CurrentInstrSet() == InstrSet_ThumbEE then 11885 UNPREDICTABLE; 11886 operand2 = if register_form then Shift(R[m], shift_t, shift_n, APSR.C) else imm32; 11887 case opcode of 11888 when ‘0000’ result = R[n] AND operand2; // AND 11889 when ‘0001’ result = R[n] EOR operand2; // EOR 11890 when ‘0010’ (result, -, -) = AddWithCarry(R[n], NOT(operand2), ‘1’); // SUB 11891 when ‘0011’ (result, -, -) = AddWithCarry(NOT(R[n]), operand2, ‘1’); // RSB 11892 when ‘0100’ (result, -, -) = AddWithCarry(R[n], operand2, ‘0’); // ADD 11893 when ‘0101’ (result, -, -) = AddWithCarry(R[n], operand2, APSR.c); // ADC 11894 when ‘0110’ (result, -, -) = AddWithCarry(R[n], NOT(operand2), APSR.C); // SBC 11895 when ‘0111’ (result, -, -) = AddWithCarry(NOT(R[n]), operand2, APSR.C); // RSC 11896 when ‘1100’ result = R[n] OR operand2; // ORR 11897 when ‘1101’ result = operand2; // MOV 11898 when ‘1110’ result = R[n] AND NOT(operand2); // BIC 11899 when ‘1111’ result = NOT(operand2); // MVN 11900 CPSRWriteByInstr(SPSR[], ‘1111’, TRUE); 11901 BranchWritePC(result); 11902#endif 11903 11904 bool success = false; 11905 11906 if (ConditionPassed (opcode)) 11907 { 11908 uint32_t n; 11909 uint32_t m; 11910 uint32_t imm32; 11911 bool register_form; 11912 ARM_ShifterType shift_t; 11913 uint32_t shift_n; 11914 uint32_t code; 11915 11916 switch (encoding) 11917 { 11918 case eEncodingT1: 11919 // if CurrentInstrSet() == InstrSet_ThumbEE then UNPREDICTABLE 11920 // n = 14; imm32 = ZeroExtend(imm8, 32); register_form = FALSE; opcode = ‘0010’; // = SUB 11921 n = 14; 11922 imm32 = Bits32 (opcode, 7, 0); 11923 register_form = false; 11924 code = 2; 11925 11926 // if InITBlock() && !LastInITBlock() then UNPREDICTABLE; 11927 if (InITBlock() && !LastInITBlock()) 11928 return false; 11929 11930 break; 11931 11932 case eEncodingA1: 11933 // n = UInt(Rn); imm32 = ARMExpandImm(imm12); register_form = FALSE; 11934 n = Bits32 (opcode, 19, 16); 11935 imm32 = ARMExpandImm (opcode); 11936 register_form = false; 11937 code = Bits32 (opcode, 24, 21); 11938 11939 break; 11940 11941 case eEncodingA2: 11942 // n = UInt(Rn); m = UInt(Rm); register_form = TRUE; 11943 n = Bits32 (opcode, 19, 16); 11944 m = Bits32 (opcode, 3, 0); 11945 register_form = true; 11946 11947 // (shift_t, shift_n) = DecodeImmShift(type, imm5); 11948 shift_n = DecodeImmShiftARM (opcode, shift_t); 11949 11950 break; 11951 11952 default: 11953 return false; 11954 } 11955 11956 // operand2 = if register_form then Shift(R[m], shift_t, shift_n, APSR.C) else imm32; 11957 uint32_t operand2; 11958 if (register_form) 11959 { 11960 uint32_t Rm = ReadCoreReg (m, &success); 11961 if (!success) 11962 return false; 11963 11964 operand2 = Shift (Rm, shift_t, shift_n, APSR_C); 11965 11966 } 11967 else 11968 { 11969 operand2 = imm32; 11970 } 11971 11972 uint32_t Rn = ReadCoreReg (n, &success); 11973 if (!success) 11974 return false; 11975 11976 AddWithCarryResult result; 11977 11978 // case opcode of 11979 switch (code) 11980 { 11981 case 0: // when ‘0000’ 11982 // result = R[n] AND operand2; // AND 11983 result.result = Rn & operand2; 11984 break; 11985 11986 case 1: // when ‘0001’ 11987 // result = R[n] EOR operand2; // EOR 11988 result.result = Rn ^ operand2; 11989 break; 11990 11991 case 2: // when ‘0010’ 11992 // (result, -, -) = AddWithCarry(R[n], NOT(operand2), ‘1’); // SUB 11993 result = AddWithCarry (Rn, ~(operand2), 1); 11994 break; 11995 11996 case 3: // when ‘0011’ 11997 // (result, -, -) = AddWithCarry(NOT(R[n]), operand2, ‘1’); // RSB 11998 result = AddWithCarry (~(Rn), operand2, 1); 11999 break; 12000 12001 case 4: // when ‘0100’ 12002 // (result, -, -) = AddWithCarry(R[n], operand2, ‘0’); // ADD 12003 result = AddWithCarry (Rn, operand2, 0); 12004 break; 12005 12006 case 5: // when ‘0101’ 12007 // (result, -, -) = AddWithCarry(R[n], operand2, APSR.c); // ADC 12008 result = AddWithCarry (Rn, operand2, APSR_C); 12009 break; 12010 12011 case 6: // when ‘0110’ 12012 // (result, -, -) = AddWithCarry(R[n], NOT(operand2), APSR.C); // SBC 12013 result = AddWithCarry (Rn, ~(operand2), APSR_C); 12014 break; 12015 12016 case 7: // when ‘0111’ 12017 // (result, -, -) = AddWithCarry(NOT(R[n]), operand2, APSR.C); // RSC 12018 result = AddWithCarry (~(Rn), operand2, APSR_C); 12019 break; 12020 12021 case 10: // when ‘1100’ 12022 // result = R[n] OR operand2; // ORR 12023 result.result = Rn | operand2; 12024 break; 12025 12026 case 11: // when ‘1101’ 12027 // result = operand2; // MOV 12028 result.result = operand2; 12029 break; 12030 12031 case 12: // when ‘1110’ 12032 // result = R[n] AND NOT(operand2); // BIC 12033 result.result = Rn & ~(operand2); 12034 break; 12035 12036 case 15: // when ‘1111’ 12037 // result = NOT(operand2); // MVN 12038 result.result = ~(operand2); 12039 break; 12040 12041 default: 12042 return false; 12043 } 12044 // CPSRWriteByInstr(SPSR[], ‘1111’, TRUE); 12045 12046 // For now, in emulation mode, we don't have access to the SPSR, so we will use the CPSR instead, and hope for 12047 // the best. 12048 uint32_t spsr = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_cpsr, 0, &success); 12049 if (!success) 12050 return false; 12051 12052 CPSRWriteByInstr (spsr, 15, true); 12053 12054 // BranchWritePC(result); 12055 EmulateInstruction::Context context; 12056 context.type = eContextAdjustPC; 12057 context.SetImmediate (result.result); 12058 12059 BranchWritePC (context, result.result); 12060 } 12061 return true; 12062} 12063 12064EmulateInstructionARM::ARMOpcode* 12065EmulateInstructionARM::GetARMOpcodeForInstruction (const uint32_t opcode) 12066{ 12067 static ARMOpcode 12068 g_arm_opcodes[] = 12069 { 12070 //---------------------------------------------------------------------- 12071 // Prologue instructions 12072 //---------------------------------------------------------------------- 12073 12074 // push register(s) 12075 { 0x0fff0000, 0x092d0000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulatePUSH, "push <registers>" }, 12076 { 0x0fff0fff, 0x052d0004, ARMvAll, eEncodingA2, No_VFP, eSize32, &EmulateInstructionARM::EmulatePUSH, "push <register>" }, 12077 12078 // set r7 to point to a stack offset 12079 { 0x0ffff000, 0x028d7000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateADDRdSPImm, "add r7, sp, #<const>" }, 12080 { 0x0ffff000, 0x024c7000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBR7IPImm, "sub r7, ip, #<const>"}, 12081 // copy the stack pointer to ip 12082 { 0x0fffffff, 0x01a0c00d, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateMOVRdSP, "mov ip, sp" }, 12083 { 0x0ffff000, 0x028dc000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateADDRdSPImm, "add ip, sp, #<const>" }, 12084 { 0x0ffff000, 0x024dc000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBIPSPImm, "sub ip, sp, #<const>"}, 12085 12086 // adjust the stack pointer 12087 { 0x0ffff000, 0x024dd000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBSPImm, "sub sp, sp, #<const>"}, 12088 { 0x0fef0010, 0x004d0000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBSPReg, "sub{s}<c> <Rd>, sp, <Rm>{,<shift>}" }, 12089 12090 // push one register 12091 // if Rn == '1101' && imm12 == '000000000100' then SEE PUSH; 12092 { 0x0e5f0000, 0x040d0000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTRRtSP, "str Rt, [sp, #-imm12]!" }, 12093 12094 // vector push consecutive extension register(s) 12095 { 0x0fbf0f00, 0x0d2d0b00, ARMV6T2_ABOVE, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateVPUSH, "vpush.64 <list>"}, 12096 { 0x0fbf0f00, 0x0d2d0a00, ARMV6T2_ABOVE, eEncodingA2, No_VFP, eSize32, &EmulateInstructionARM::EmulateVPUSH, "vpush.32 <list>"}, 12097 12098 //---------------------------------------------------------------------- 12099 // Epilogue instructions 12100 //---------------------------------------------------------------------- 12101 12102 { 0x0fff0000, 0x08bd0000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulatePOP, "pop <registers>"}, 12103 { 0x0fff0fff, 0x049d0004, ARMvAll, eEncodingA2, No_VFP, eSize32, &EmulateInstructionARM::EmulatePOP, "pop <register>"}, 12104 { 0x0fbf0f00, 0x0cbd0b00, ARMV6T2_ABOVE, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateVPOP, "vpop.64 <list>"}, 12105 { 0x0fbf0f00, 0x0cbd0a00, ARMV6T2_ABOVE, eEncodingA2, No_VFP, eSize32, &EmulateInstructionARM::EmulateVPOP, "vpop.32 <list>"}, 12106 12107 //---------------------------------------------------------------------- 12108 // Supervisor Call (previously Software Interrupt) 12109 //---------------------------------------------------------------------- 12110 { 0x0f000000, 0x0f000000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSVC, "svc #imm24"}, 12111 12112 //---------------------------------------------------------------------- 12113 // Branch instructions 12114 //---------------------------------------------------------------------- 12115 { 0x0f000000, 0x0a000000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateB, "b #imm24"}, 12116 // To resolve ambiguity, "blx <label>" should come before "bl <label>". 12117 { 0xfe000000, 0xfa000000, ARMV5_ABOVE, eEncodingA2, No_VFP, eSize32, &EmulateInstructionARM::EmulateBLXImmediate, "blx <label>"}, 12118 { 0x0f000000, 0x0b000000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateBLXImmediate, "bl <label>"}, 12119 { 0x0ffffff0, 0x012fff30, ARMV5_ABOVE, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateBLXRm, "blx <Rm>"}, 12120 // for example, "bx lr" 12121 { 0x0ffffff0, 0x012fff10, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateBXRm, "bx <Rm>"}, 12122 // bxj 12123 { 0x0ffffff0, 0x012fff20, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateBXJRm, "bxj <Rm>"}, 12124 12125 //---------------------------------------------------------------------- 12126 // Data-processing instructions 12127 //---------------------------------------------------------------------- 12128 // adc (immediate) 12129 { 0x0fe00000, 0x02a00000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateADCImm, "adc{s}<c> <Rd>, <Rn>, #const"}, 12130 // adc (register) 12131 { 0x0fe00010, 0x00a00000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateADCReg, "adc{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"}, 12132 // add (immediate) 12133 { 0x0fe00000, 0x02800000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateADDImmARM, "add{s}<c> <Rd>, <Rn>, #const"}, 12134 // add (register) 12135 { 0x0fe00010, 0x00800000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateADDReg, "add{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"}, 12136 // add (register-shifted register) 12137 { 0x0fe00090, 0x00800010, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateADDRegShift, "add{s}<c> <Rd>, <Rn>, <Rm>, <type> <RS>"}, 12138 // adr 12139 { 0x0fff0000, 0x028f0000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateADR, "add<c> <Rd>, PC, #<const>"}, 12140 { 0x0fff0000, 0x024f0000, ARMvAll, eEncodingA2, No_VFP, eSize32, &EmulateInstructionARM::EmulateADR, "sub<c> <Rd>, PC, #<const>"}, 12141 // and (immediate) 12142 { 0x0fe00000, 0x02000000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateANDImm, "and{s}<c> <Rd>, <Rn>, #const"}, 12143 // and (register) 12144 { 0x0fe00010, 0x00000000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateANDReg, "and{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"}, 12145 // bic (immediate) 12146 { 0x0fe00000, 0x03c00000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateBICImm, "bic{s}<c> <Rd>, <Rn>, #const"}, 12147 // bic (register) 12148 { 0x0fe00010, 0x01c00000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateBICReg, "bic{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"}, 12149 // eor (immediate) 12150 { 0x0fe00000, 0x02200000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateEORImm, "eor{s}<c> <Rd>, <Rn>, #const"}, 12151 // eor (register) 12152 { 0x0fe00010, 0x00200000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateEORReg, "eor{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"}, 12153 // orr (immediate) 12154 { 0x0fe00000, 0x03800000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateORRImm, "orr{s}<c> <Rd>, <Rn>, #const"}, 12155 // orr (register) 12156 { 0x0fe00010, 0x01800000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateORRReg, "orr{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"}, 12157 // rsb (immediate) 12158 { 0x0fe00000, 0x02600000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateRSBImm, "rsb{s}<c> <Rd>, <Rn>, #<const>"}, 12159 // rsb (register) 12160 { 0x0fe00010, 0x00600000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateRSBReg, "rsb{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"}, 12161 // rsc (immediate) 12162 { 0x0fe00000, 0x02e00000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateRSCImm, "rsc{s}<c> <Rd>, <Rn>, #<const>"}, 12163 // rsc (register) 12164 { 0x0fe00010, 0x00e00000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateRSCReg, "rsc{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"}, 12165 // sbc (immediate) 12166 { 0x0fe00000, 0x02c00000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSBCImm, "sbc{s}<c> <Rd>, <Rn>, #<const>"}, 12167 // sbc (register) 12168 { 0x0fe00010, 0x00c00000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSBCReg, "sbc{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"}, 12169 // sub (immediate, ARM) 12170 { 0x0fe00000, 0x02400000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBImmARM, "sub{s}<c> <Rd>, <Rn>, #<const>"}, 12171 // sub (sp minus immediate) 12172 { 0x0fef0000, 0x024d0000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBSPImm, "sub{s}<c> <Rd>, sp, #<const>"}, 12173 // sub (register) 12174 { 0x0fe00010, 0x00400000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBReg, "sub{s}<c> <Rd>, <Rn>, <Rm>{,<shift>}"}, 12175 // teq (immediate) 12176 { 0x0ff0f000, 0x03300000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateTEQImm, "teq<c> <Rn>, #const"}, 12177 // teq (register) 12178 { 0x0ff0f010, 0x01300000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateTEQReg, "teq<c> <Rn>, <Rm> {,<shift>}"}, 12179 // tst (immediate) 12180 { 0x0ff0f000, 0x03100000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateTSTImm, "tst<c> <Rn>, #const"}, 12181 // tst (register) 12182 { 0x0ff0f010, 0x01100000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateTSTReg, "tst<c> <Rn>, <Rm> {,<shift>}"}, 12183 12184 // mov (immediate) 12185 { 0x0fef0000, 0x03a00000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateMOVRdImm, "mov{s}<c> <Rd>, #<const>"}, 12186 { 0x0ff00000, 0x03000000, ARMV6T2_ABOVE, eEncodingA2, No_VFP, eSize32, &EmulateInstructionARM::EmulateMOVRdImm, "movw<c> <Rd>, #<imm16>" }, 12187 // mov (register) 12188 { 0x0fef0ff0, 0x01a00000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateMOVRdRm, "mov{s}<c> <Rd>, <Rm>"}, 12189 // mvn (immediate) 12190 { 0x0fef0000, 0x03e00000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateMVNImm, "mvn{s}<c> <Rd>, #<const>"}, 12191 // mvn (register) 12192 { 0x0fef0010, 0x01e00000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateMVNReg, "mvn{s}<c> <Rd>, <Rm> {,<shift>}"}, 12193 // cmn (immediate) 12194 { 0x0ff0f000, 0x03700000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateCMNImm, "cmn<c> <Rn>, #<const>"}, 12195 // cmn (register) 12196 { 0x0ff0f010, 0x01700000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateCMNReg, "cmn<c> <Rn>, <Rm> {,<shift>}"}, 12197 // cmp (immediate) 12198 { 0x0ff0f000, 0x03500000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateCMPImm, "cmp<c> <Rn>, #<const>"}, 12199 // cmp (register) 12200 { 0x0ff0f010, 0x01500000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateCMPReg, "cmp<c> <Rn>, <Rm> {,<shift>}"}, 12201 // asr (immediate) 12202 { 0x0fef0070, 0x01a00040, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateASRImm, "asr{s}<c> <Rd>, <Rm>, #imm"}, 12203 // asr (register) 12204 { 0x0fef00f0, 0x01a00050, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateASRReg, "asr{s}<c> <Rd>, <Rn>, <Rm>"}, 12205 // lsl (immediate) 12206 { 0x0fef0070, 0x01a00000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLSLImm, "lsl{s}<c> <Rd>, <Rm>, #imm"}, 12207 // lsl (register) 12208 { 0x0fef00f0, 0x01a00010, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLSLReg, "lsl{s}<c> <Rd>, <Rn>, <Rm>"}, 12209 // lsr (immediate) 12210 { 0x0fef0070, 0x01a00020, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLSRImm, "lsr{s}<c> <Rd>, <Rm>, #imm"}, 12211 // lsr (register) 12212 { 0x0fef00f0, 0x01a00050, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLSRReg, "lsr{s}<c> <Rd>, <Rn>, <Rm>"}, 12213 // rrx is a special case encoding of ror (immediate) 12214 { 0x0fef0ff0, 0x01a00060, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateRRX, "rrx{s}<c> <Rd>, <Rm>"}, 12215 // ror (immediate) 12216 { 0x0fef0070, 0x01a00060, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateRORImm, "ror{s}<c> <Rd>, <Rm>, #imm"}, 12217 // ror (register) 12218 { 0x0fef00f0, 0x01a00070, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateRORReg, "ror{s}<c> <Rd>, <Rn>, <Rm>"}, 12219 // mul 12220 { 0x0fe000f0, 0x00000090, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateMUL, "mul{s}<c> <Rd>,<R>,<Rm>" }, 12221 { 0x0e10f000, 0x0210f000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBSPcLrEtc, "<opc>S<c> PC,#<const> | <Rn>,#<const>" }, 12222 { 0x0e10f010, 0x0010f000, ARMvAll, eEncodingA2, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBSPcLrEtc, "<opc>S<c> PC,<Rn>,<Rm{,<shift>}" }, 12223 12224 //---------------------------------------------------------------------- 12225 // Load instructions 12226 //---------------------------------------------------------------------- 12227 { 0x0fd00000, 0x08900000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDM, "ldm<c> <Rn>{!} <registers>" }, 12228 { 0x0fd00000, 0x08100000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDMDA, "ldmda<c> <Rn>{!} <registers>" }, 12229 { 0x0fd00000, 0x09100000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDMDB, "ldmdb<c> <Rn>{!} <registers>" }, 12230 { 0x0fd00000, 0x09900000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDMIB, "ldmib<c> <Rn<{!} <registers>" }, 12231 { 0x0e500000, 0x04100000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRImmediateARM, "ldr<c> <Rt> [<Rn> {#+/-<imm12>}]" }, 12232 { 0x0e500010, 0x06100000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRRegister, "ldr<c> <Rt> [<Rn> +/-<Rm> {<shift>}] {!}" }, 12233 { 0x0e5f0000, 0x045f0000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRBLiteral, "ldrb<c> <Rt>, [...]"}, 12234 { 0xfe500010, 0x06500000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRBRegister, "ldrb<c> <Rt>, [<Rn>,+/-<Rm>{, <shift>}]{!}" }, 12235 { 0x0e5f00f0, 0x005f00b0, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRHLiteral, "ldrh<c> <Rt>, <label>" }, 12236 { 0x0e5000f0, 0x001000b0, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRHRegister, "ldrh<c> <Rt>,[<Rn>,+/-<Rm>]{!}" }, 12237 { 0x0e5000f0, 0x005000d0, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRSBImmediate, "ldrsb<c> <Rt>, [<Rn>{,#+/-<imm8>}]" }, 12238 { 0x0e5f00f0, 0x005f00d0, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRSBLiteral, "ldrsb<c> <Rt> <label>" }, 12239 { 0x0e5000f0, 0x001000d0, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRSBRegister, "ldrsb<c> <Rt>,[<Rn>,+/-<Rm>]{!}" }, 12240 { 0x0e5000f0, 0x005000f0, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRSHImmediate, "ldrsh<c> <Rt>,[<Rn>{,#+/-<imm8>}]"}, 12241 { 0x0e5f00f0, 0x005f00f0, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRSHLiteral, "ldrsh<c> <Rt>,<label>" }, 12242 { 0x0e5000f0, 0x001000f0, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRSHRegister, "ldrsh<c> <Rt>,[<Rn>,+/-<Rm>]{!}" }, 12243 { 0x0e5000f0, 0x004000d0, ARMV5TE_ABOVE, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRDImmediate, "ldrd<c> <Rt>, <Rt2>, [<Rn>,#+/-<imm8>]!"}, 12244 { 0x0e500ff0, 0x000000d0, ARMV5TE_ABOVE, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRDRegister, "ldrd<c> <Rt>, <Rt2>, [<Rn>, +/-<Rm>]{!}"}, 12245 { 0x0e100f00, 0x0c100b00, ARMvAll, eEncodingA1, VFPv2_ABOVE, eSize32, &EmulateInstructionARM::EmulateVLDM, "vldm{mode}<c> <Rn>{!}, <list>"}, 12246 { 0x0e100f00, 0x0c100a00, ARMvAll, eEncodingA2, VFPv2v3, eSize32, &EmulateInstructionARM::EmulateVLDM, "vldm{mode}<c> <Rn>{!}, <list>"}, 12247 { 0x0f300f00, 0x0d100b00, ARMvAll, eEncodingA1, VFPv2_ABOVE, eSize32, &EmulateInstructionARM::EmulateVLDR, "vldr<c> <Dd>, [<Rn>{,#+/-<imm>}]"}, 12248 { 0x0f300f00, 0x0d100a00, ARMvAll, eEncodingA2, VFPv2v3, eSize32, &EmulateInstructionARM::EmulateVLDR, "vldr<c> <Sd>, [<Rn>{,#+/-<imm>}]"}, 12249 { 0xffb00000, 0xf4200000, ARMvAll, eEncodingA1, AdvancedSIMD, eSize32, &EmulateInstructionARM::EmulateVLD1Multiple, "vld1<c>.<size> <list>, [<Rn>{@<align>}], <Rm>"}, 12250 { 0xffb00300, 0xf4a00000, ARMvAll, eEncodingA1, AdvancedSIMD, eSize32, &EmulateInstructionARM::EmulateVLD1Single, "vld1<c>.<size> <list>, [<Rn>{@<align>}], <Rm>"}, 12251 { 0xffb00f00, 0xf4a00c00, ARMvAll, eEncodingA1, AdvancedSIMD, eSize32, &EmulateInstructionARM::EmulateVLD1SingleAll, "vld1<c>.<size> <list>, [<Rn>{@<align>}], <Rm>"}, 12252 12253 //---------------------------------------------------------------------- 12254 // Store instructions 12255 //---------------------------------------------------------------------- 12256 { 0x0fd00000, 0x08800000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTM, "stm<c> <Rn>{!} <registers>" }, 12257 { 0x0fd00000, 0x08000000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTMDA, "stmda<c> <Rn>{!} <registers>" }, 12258 { 0x0fd00000, 0x09000000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTMDB, "stmdb<c> <Rn>{!} <registers>" }, 12259 { 0x0fd00000, 0x09800000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTMIB, "stmib<c> <Rn>{!} <registers>" }, 12260 { 0x0e500010, 0x06000000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTRRegister, "str<c> <Rt> [<Rn> +/-<Rm> {<shift>}]{!}" }, 12261 { 0x0e5000f0, 0x000000b0, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTRHRegister, "strh<c> <Rt>,[<Rn>,+/-<Rm>[{!}" }, 12262 { 0x0ff00ff0, 0x01800f90, ARMV6_ABOVE, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTREX, "strex<c> <Rd>, <Rt>, [<Rn>]"}, 12263 { 0x0e500000, 0x04400000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTRBImmARM, "strb<c> <Rt>,[<Rn>,#+/-<imm12>]!"}, 12264 { 0x0e500000, 0x04000000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTRImmARM, "str<c> <Rt>,[<Rn>,#+/-<imm12>]!"}, 12265 { 0x0e5000f0, 0x004000f0, ARMV5TE_ABOVE, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTRDImm, "strd<c> <Rt>, <Rt2>, [<Rn> #+/-<imm8>]!"}, 12266 { 0x0e500ff0, 0x000000f0, ARMV5TE_ABOVE, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTRDReg, "strd<c> <Rt>, <Rt2>, [<Rn>, +/-<Rm>]{!}"}, 12267 { 0x0e100f00, 0x0c000b00, ARMvAll, eEncodingA1, VFPv2_ABOVE, eSize32, &EmulateInstructionARM::EmulateVSTM, "vstm{mode}<c> <Rn>{!} <list>"}, 12268 { 0x0e100f00, 0x0c000a00, ARMvAll, eEncodingA2, VFPv2v3, eSize32, &EmulateInstructionARM::EmulateVSTM, "vstm{mode}<c> <Rn>{!} <list>"}, 12269 { 0x0f300f00, 0x0d000b00, ARMvAll, eEncodingA1, VFPv2_ABOVE, eSize32, &EmulateInstructionARM::EmulateVSTR, "vstr<c> <Dd> [<Rn>{,#+/-<imm>}]"}, 12270 { 0x0f300f00, 0x0d000a00, ARMvAll, eEncodingA2, VFPv2v3, eSize32, &EmulateInstructionARM::EmulateVSTR, "vstr<c> <Sd> [<Rn>{,#+/-<imm>}]"}, 12271 { 0xffb00000, 0xf4000000, ARMvAll, eEncodingA1, AdvancedSIMD, eSize32, &EmulateInstructionARM::EmulateVST1Multiple, "vst1<c>.<size> <list>, [<Rn>{@<align>}], <Rm>"}, 12272 { 0xffb00300, 0xf4800000, ARMvAll, eEncodingA1, AdvancedSIMD, eSize32, &EmulateInstructionARM::EmulateVST1Single, "vst1<c>.<size> <list>, [<Rn>{@<align>}], <Rm>"}, 12273 12274 //---------------------------------------------------------------------- 12275 // Other instructions 12276 //---------------------------------------------------------------------- 12277 { 0x0fff00f0, 0x06af00f0, ARMV6_ABOVE, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSXTB, "sxtb<c> <Rd>,<Rm>{,<rotation>}" }, 12278 { 0x0fff00f0, 0x06bf0070, ARMV6_ABOVE, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSXTH, "sxth<c> <Rd>,<Rm>{,<rotation>}" }, 12279 { 0x0fff00f0, 0x06ef0070, ARMV6_ABOVE, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateUXTB, "uxtb<c> <Rd>,<Rm>{,<rotation>}" }, 12280 { 0x0fff00f0, 0x06ff0070, ARMV6_ABOVE, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateUXTH, "uxth<c> <Rd>,<Rm>{,<rotation>}" }, 12281 { 0xfe500000, 0xf8100000, ARMV6_ABOVE, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateRFE, "rfe{<amode>} <Rn>{!}" } 12282 12283 }; 12284 static const size_t k_num_arm_opcodes = sizeof(g_arm_opcodes)/sizeof(ARMOpcode); 12285 12286 for (size_t i=0; i<k_num_arm_opcodes; ++i) 12287 { 12288 if ((g_arm_opcodes[i].mask & opcode) == g_arm_opcodes[i].value) 12289 return &g_arm_opcodes[i]; 12290 } 12291 return NULL; 12292} 12293 12294 12295EmulateInstructionARM::ARMOpcode* 12296EmulateInstructionARM::GetThumbOpcodeForInstruction (const uint32_t opcode) 12297{ 12298 12299 static ARMOpcode 12300 g_thumb_opcodes[] = 12301 { 12302 //---------------------------------------------------------------------- 12303 // Prologue instructions 12304 //---------------------------------------------------------------------- 12305 12306 // push register(s) 12307 { 0xfffffe00, 0x0000b400, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulatePUSH, "push <registers>" }, 12308 { 0xffff0000, 0xe92d0000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulatePUSH, "push.w <registers>" }, 12309 { 0xffff0fff, 0xf84d0d04, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, &EmulateInstructionARM::EmulatePUSH, "push.w <register>" }, 12310 12311 // set r7 to point to a stack offset 12312 { 0xffffff00, 0x0000af00, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateADDRdSPImm, "add r7, sp, #imm" }, 12313 // copy the stack pointer to r7 12314 { 0xffffffff, 0x0000466f, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateMOVRdSP, "mov r7, sp" }, 12315 // move from high register to low register (comes after "mov r7, sp" to resolve ambiguity) 12316 { 0xffffffc0, 0x00004640, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateMOVLowHigh, "mov r0-r7, r8-r15" }, 12317 12318 // PC-relative load into register (see also EmulateADDSPRm) 12319 { 0xfffff800, 0x00004800, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateLDRRtPCRelative, "ldr <Rt>, [PC, #imm]"}, 12320 12321 // adjust the stack pointer 12322 { 0xffffff87, 0x00004485, ARMvAll, eEncodingT2, No_VFP, eSize16, &EmulateInstructionARM::EmulateADDSPRm, "add sp, <Rm>"}, 12323 { 0xffffff80, 0x0000b080, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateSUBSPImm, "sub sp, sp, #imm"}, 12324 { 0xfbef8f00, 0xf1ad0d00, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBSPImm, "sub.w sp, sp, #<const>"}, 12325 { 0xfbff8f00, 0xf2ad0d00, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBSPImm, "subw sp, sp, #imm12"}, 12326 { 0xffef8000, 0xebad0000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBSPReg, "sub{s}<c> <Rd>, sp, <Rm>{,<shift>}" }, 12327 12328 // vector push consecutive extension register(s) 12329 { 0xffbf0f00, 0xed2d0b00, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateVPUSH, "vpush.64 <list>"}, 12330 { 0xffbf0f00, 0xed2d0a00, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateVPUSH, "vpush.32 <list>"}, 12331 12332 //---------------------------------------------------------------------- 12333 // Epilogue instructions 12334 //---------------------------------------------------------------------- 12335 12336 { 0xfffff800, 0x0000a800, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateADDSPImm, "add<c> <Rd>, sp, #imm"}, 12337 { 0xffffff80, 0x0000b000, ARMvAll, eEncodingT2, No_VFP, eSize16, &EmulateInstructionARM::EmulateADDSPImm, "add sp, #imm"}, 12338 { 0xfffffe00, 0x0000bc00, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulatePOP, "pop <registers>"}, 12339 { 0xffff0000, 0xe8bd0000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulatePOP, "pop.w <registers>" }, 12340 { 0xffff0fff, 0xf85d0d04, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, &EmulateInstructionARM::EmulatePOP, "pop.w <register>" }, 12341 { 0xffbf0f00, 0xecbd0b00, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateVPOP, "vpop.64 <list>"}, 12342 { 0xffbf0f00, 0xecbd0a00, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateVPOP, "vpop.32 <list>"}, 12343 12344 //---------------------------------------------------------------------- 12345 // Supervisor Call (previously Software Interrupt) 12346 //---------------------------------------------------------------------- 12347 { 0xffffff00, 0x0000df00, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateSVC, "svc #imm8"}, 12348 12349 //---------------------------------------------------------------------- 12350 // If Then makes up to four following instructions conditional. 12351 //---------------------------------------------------------------------- 12352 { 0xffffff00, 0x0000bf00, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateIT, "it{<x>{<y>{<z>}}} <firstcond>"}, 12353 12354 //---------------------------------------------------------------------- 12355 // Branch instructions 12356 //---------------------------------------------------------------------- 12357 // To resolve ambiguity, "b<c> #imm8" should come after "svc #imm8". 12358 { 0xfffff000, 0x0000d000, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateB, "b<c> #imm8 (outside IT)"}, 12359 { 0xfffff800, 0x0000e000, ARMvAll, eEncodingT2, No_VFP, eSize16, &EmulateInstructionARM::EmulateB, "b<c> #imm11 (outside or last in IT)"}, 12360 { 0xf800d000, 0xf0008000, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, &EmulateInstructionARM::EmulateB, "b<c>.w #imm8 (outside IT)"}, 12361 { 0xf800d000, 0xf0009000, ARMV6T2_ABOVE, eEncodingT4, No_VFP, eSize32, &EmulateInstructionARM::EmulateB, "b<c>.w #imm8 (outside or last in IT)"}, 12362 // J1 == J2 == 1 12363 { 0xf800d000, 0xf000d000, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateBLXImmediate, "bl <label>"}, 12364 // J1 == J2 == 1 12365 { 0xf800d001, 0xf000c000, ARMV5_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateBLXImmediate, "blx <label>"}, 12366 { 0xffffff87, 0x00004780, ARMV5_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateBLXRm, "blx <Rm>"}, 12367 // for example, "bx lr" 12368 { 0xffffff87, 0x00004700, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateBXRm, "bx <Rm>"}, 12369 // bxj 12370 { 0xfff0ffff, 0xf3c08f00, ARMV5J_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateBXJRm, "bxj <Rm>"}, 12371 // compare and branch 12372 { 0xfffff500, 0x0000b100, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateCB, "cb{n}z <Rn>, <label>"}, 12373 // table branch byte 12374 { 0xfff0fff0, 0xe8d0f000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateTB, "tbb<c> <Rn>, <Rm>"}, 12375 // table branch halfword 12376 { 0xfff0fff0, 0xe8d0f010, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateTB, "tbh<c> <Rn>, <Rm>, lsl #1"}, 12377 12378 //---------------------------------------------------------------------- 12379 // Data-processing instructions 12380 //---------------------------------------------------------------------- 12381 // adc (immediate) 12382 { 0xfbe08000, 0xf1400000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateADCImm, "adc{s}<c> <Rd>, <Rn>, #<const>"}, 12383 // adc (register) 12384 { 0xffffffc0, 0x00004140, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateADCReg, "adcs|adc<c> <Rdn>, <Rm>"}, 12385 { 0xffe08000, 0xeb400000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateADCReg, "adc{s}<c>.w <Rd>, <Rn>, <Rm> {,<shift>}"}, 12386 // add (register) 12387 { 0xfffffe00, 0x00001800, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateADDReg, "adds|add<c> <Rd>, <Rn>, <Rm>"}, 12388 // Make sure "add sp, <Rm>" comes before this instruction, so there's no ambiguity decoding the two. 12389 { 0xffffff00, 0x00004400, ARMvAll, eEncodingT2, No_VFP, eSize16, &EmulateInstructionARM::EmulateADDReg, "add<c> <Rdn>, <Rm>"}, 12390 // adr 12391 { 0xfffff800, 0x0000a000, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateADR, "add<c> <Rd>, PC, #<const>"}, 12392 { 0xfbff8000, 0xf2af0000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateADR, "sub<c> <Rd>, PC, #<const>"}, 12393 { 0xfbff8000, 0xf20f0000, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, &EmulateInstructionARM::EmulateADR, "add<c> <Rd>, PC, #<const>"}, 12394 // and (immediate) 12395 { 0xfbe08000, 0xf0000000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateANDImm, "and{s}<c> <Rd>, <Rn>, #<const>"}, 12396 // and (register) 12397 { 0xffffffc0, 0x00004000, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateANDReg, "ands|and<c> <Rdn>, <Rm>"}, 12398 { 0xffe08000, 0xea000000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateANDReg, "and{s}<c>.w <Rd>, <Rn>, <Rm> {,<shift>}"}, 12399 // bic (immediate) 12400 { 0xfbe08000, 0xf0200000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateBICImm, "bic{s}<c> <Rd>, <Rn>, #<const>"}, 12401 // bic (register) 12402 { 0xffffffc0, 0x00004380, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateBICReg, "bics|bic<c> <Rdn>, <Rm>"}, 12403 { 0xffe08000, 0xea200000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateBICReg, "bic{s}<c>.w <Rd>, <Rn>, <Rm> {,<shift>}"}, 12404 // eor (immediate) 12405 { 0xfbe08000, 0xf0800000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateEORImm, "eor{s}<c> <Rd>, <Rn>, #<const>"}, 12406 // eor (register) 12407 { 0xffffffc0, 0x00004040, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateEORReg, "eors|eor<c> <Rdn>, <Rm>"}, 12408 { 0xffe08000, 0xea800000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateEORReg, "eor{s}<c>.w <Rd>, <Rn>, <Rm> {,<shift>}"}, 12409 // orr (immediate) 12410 { 0xfbe08000, 0xf0400000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateORRImm, "orr{s}<c> <Rd>, <Rn>, #<const>"}, 12411 // orr (register) 12412 { 0xffffffc0, 0x00004300, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateORRReg, "orrs|orr<c> <Rdn>, <Rm>"}, 12413 { 0xffe08000, 0xea400000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateORRReg, "orr{s}<c>.w <Rd>, <Rn>, <Rm> {,<shift>}"}, 12414 // rsb (immediate) 12415 { 0xffffffc0, 0x00004240, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateRSBImm, "rsbs|rsb<c> <Rd>, <Rn>, #0"}, 12416 { 0xfbe08000, 0xf1c00000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateRSBImm, "rsb{s}<c>.w <Rd>, <Rn>, #<const>"}, 12417 // rsb (register) 12418 { 0xffe08000, 0xea400000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateRSBReg, "rsb{s}<c>.w <Rd>, <Rn>, <Rm> {,<shift>}"}, 12419 // sbc (immediate) 12420 { 0xfbe08000, 0xf1600000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSBCImm, "sbc{s}<c> <Rd>, <Rn>, #<const>"}, 12421 // sbc (register) 12422 { 0xffffffc0, 0x00004180, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateSBCReg, "sbcs|sbc<c> <Rdn>, <Rm>"}, 12423 { 0xffe08000, 0xeb600000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateSBCReg, "sbc{s}<c>.w <Rd>, <Rn>, <Rm> {,<shift>}"}, 12424 // add (immediate, Thumb) 12425 { 0xfffffe00, 0x00001c00, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateADDImmThumb, "adds|add<c> <Rd>,<Rn>,#<imm3>" }, 12426 { 0xfffff800, 0x00003000, ARMV4T_ABOVE, eEncodingT2, No_VFP, eSize16, &EmulateInstructionARM::EmulateADDImmThumb, "adds|add<c> <Rdn>,#<imm8>" }, 12427 { 0xfbe08000, 0xf1000000, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, &EmulateInstructionARM::EmulateADDImmThumb, "add{s}<c>.w <Rd>,<Rn>,#<const>" }, 12428 { 0xfbf08000, 0xf2000000, ARMV6T2_ABOVE, eEncodingT4, No_VFP, eSize32, &EmulateInstructionARM::EmulateADDImmThumb, "addw<c> <Rd>,<Rn>,#<imm12>" }, 12429 // sub (immediate, Thumb) 12430 { 0xfffffe00, 0x00001e00, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateSUBImmThumb, "subs|sub<c> <Rd>, <Rn> #imm3"}, 12431 { 0xfffff800, 0x00003800, ARMvAll, eEncodingT2, No_VFP, eSize16, &EmulateInstructionARM::EmulateSUBImmThumb, "subs|sub<c> <Rdn>, #imm8"}, 12432 { 0xfbe08000, 0xf1a00000, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBImmThumb, "sub{s}<c>.w <Rd>, <Rn>, #<const>"}, 12433 { 0xfbf08000, 0xf2a00000, ARMV6T2_ABOVE, eEncodingT4, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBImmThumb, "subw<c> <Rd>, <Rn>, #imm12"}, 12434 // sub (sp minus immediate) 12435 { 0xfbef8000, 0xf1ad0000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBSPImm, "sub{s}.w <Rd>, sp, #<const>"}, 12436 { 0xfbff8000, 0xf2ad0000, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBSPImm, "subw<c> <Rd>, sp, #imm12"}, 12437 // sub (register) 12438 { 0xfffffe00, 0x00001a00, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateSUBReg, "subs|sub<c> <Rd>, <Rn>, <Rm>"}, 12439 { 0xffe08000, 0xeba00000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBReg, "sub{s}<c>.w <Rd>, <Rn>, <Rm>{,<shift>}"}, 12440 // teq (immediate) 12441 { 0xfbf08f00, 0xf0900f00, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateTEQImm, "teq<c> <Rn>, #<const>"}, 12442 // teq (register) 12443 { 0xfff08f00, 0xea900f00, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateTEQReg, "teq<c> <Rn>, <Rm> {,<shift>}"}, 12444 // tst (immediate) 12445 { 0xfbf08f00, 0xf0100f00, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateTSTImm, "tst<c> <Rn>, #<const>"}, 12446 // tst (register) 12447 { 0xffffffc0, 0x00004200, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateTSTReg, "tst<c> <Rdn>, <Rm>"}, 12448 { 0xfff08f00, 0xea100f00, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateTSTReg, "tst<c>.w <Rn>, <Rm> {,<shift>}"}, 12449 12450 12451 // move from high register to high register 12452 { 0xffffff00, 0x00004600, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateMOVRdRm, "mov<c> <Rd>, <Rm>"}, 12453 // move from low register to low register 12454 { 0xffffffc0, 0x00000000, ARMvAll, eEncodingT2, No_VFP, eSize16, &EmulateInstructionARM::EmulateMOVRdRm, "movs <Rd>, <Rm>"}, 12455 // mov{s}<c>.w <Rd>, <Rm> 12456 { 0xffeff0f0, 0xea4f0000, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, &EmulateInstructionARM::EmulateMOVRdRm, "mov{s}<c>.w <Rd>, <Rm>"}, 12457 // move immediate 12458 { 0xfffff800, 0x00002000, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateMOVRdImm, "movs|mov<c> <Rd>, #imm8"}, 12459 { 0xfbef8000, 0xf04f0000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateMOVRdImm, "mov{s}<c>.w <Rd>, #<const>"}, 12460 { 0xfbf08000, 0xf2400000, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, &EmulateInstructionARM::EmulateMOVRdImm, "movw<c> <Rd>,#<imm16>"}, 12461 // mvn (immediate) 12462 { 0xfbef8000, 0xf06f0000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateMVNImm, "mvn{s} <Rd>, #<const>"}, 12463 // mvn (register) 12464 { 0xffffffc0, 0x000043c0, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateMVNReg, "mvns|mvn<c> <Rd>, <Rm>"}, 12465 { 0xffef8000, 0xea6f0000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateMVNReg, "mvn{s}<c>.w <Rd>, <Rm> {,<shift>}"}, 12466 // cmn (immediate) 12467 { 0xfbf08f00, 0xf1100f00, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateCMNImm, "cmn<c> <Rn>, #<const>"}, 12468 // cmn (register) 12469 { 0xffffffc0, 0x000042c0, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateCMNReg, "cmn<c> <Rn>, <Rm>"}, 12470 { 0xfff08f00, 0xeb100f00, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateCMNReg, "cmn<c> <Rn>, <Rm> {,<shift>}"}, 12471 // cmp (immediate) 12472 { 0xfffff800, 0x00002800, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateCMPImm, "cmp<c> <Rn>, #imm8"}, 12473 { 0xfbf08f00, 0xf1b00f00, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateCMPImm, "cmp<c>.w <Rn>, #<const>"}, 12474 // cmp (register) (Rn and Rm both from r0-r7) 12475 { 0xffffffc0, 0x00004280, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateCMPReg, "cmp<c> <Rn>, <Rm>"}, 12476 // cmp (register) (Rn and Rm not both from r0-r7) 12477 { 0xffffff00, 0x00004500, ARMvAll, eEncodingT2, No_VFP, eSize16, &EmulateInstructionARM::EmulateCMPReg, "cmp<c> <Rn>, <Rm>"}, 12478 // asr (immediate) 12479 { 0xfffff800, 0x00001000, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateASRImm, "asrs|asr<c> <Rd>, <Rm>, #imm"}, 12480 { 0xffef8030, 0xea4f0020, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateASRImm, "asr{s}<c>.w <Rd>, <Rm>, #imm"}, 12481 // asr (register) 12482 { 0xffffffc0, 0x00004100, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateASRReg, "asrs|asr<c> <Rdn>, <Rm>"}, 12483 { 0xffe0f0f0, 0xfa40f000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateASRReg, "asr{s}<c>.w <Rd>, <Rn>, <Rm>"}, 12484 // lsl (immediate) 12485 { 0xfffff800, 0x00000000, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateLSLImm, "lsls|lsl<c> <Rd>, <Rm>, #imm"}, 12486 { 0xffef8030, 0xea4f0000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateLSLImm, "lsl{s}<c>.w <Rd>, <Rm>, #imm"}, 12487 // lsl (register) 12488 { 0xffffffc0, 0x00004080, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateLSLReg, "lsls|lsl<c> <Rdn>, <Rm>"}, 12489 { 0xffe0f0f0, 0xfa00f000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateLSLReg, "lsl{s}<c>.w <Rd>, <Rn>, <Rm>"}, 12490 // lsr (immediate) 12491 { 0xfffff800, 0x00000800, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateLSRImm, "lsrs|lsr<c> <Rd>, <Rm>, #imm"}, 12492 { 0xffef8030, 0xea4f0010, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateLSRImm, "lsr{s}<c>.w <Rd>, <Rm>, #imm"}, 12493 // lsr (register) 12494 { 0xffffffc0, 0x000040c0, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateLSRReg, "lsrs|lsr<c> <Rdn>, <Rm>"}, 12495 { 0xffe0f0f0, 0xfa20f000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateLSRReg, "lsr{s}<c>.w <Rd>, <Rn>, <Rm>"}, 12496 // rrx is a special case encoding of ror (immediate) 12497 { 0xffeff0f0, 0xea4f0030, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateRRX, "rrx{s}<c>.w <Rd>, <Rm>"}, 12498 // ror (immediate) 12499 { 0xffef8030, 0xea4f0030, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateRORImm, "ror{s}<c>.w <Rd>, <Rm>, #imm"}, 12500 // ror (register) 12501 { 0xffffffc0, 0x000041c0, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateRORReg, "rors|ror<c> <Rdn>, <Rm>"}, 12502 { 0xffe0f0f0, 0xfa60f000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateRORReg, "ror{s}<c>.w <Rd>, <Rn>, <Rm>"}, 12503 // mul 12504 { 0xffffffc0, 0x00004340, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateMUL, "muls <Rdm>,<Rn>,<Rdm>" }, 12505 // mul 12506 { 0xfff0f0f0, 0xfb00f000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateMUL, "mul<c> <Rd>,<Rn>,<Rm>" }, 12507 { 0xffffff00, 0xf3de8f00, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBSPcLrEtc, "SUBS<c> PC, LR, #<imm8>" }, 12508 12509 12510 //---------------------------------------------------------------------- 12511 // RFE instructions *** IMPORTANT *** THESE MUST BE LISTED **BEFORE** THE LDM.. Instructions in this table; 12512 // otherwise the wrong instructions will be selected. 12513 //---------------------------------------------------------------------- 12514 12515 { 0xffd0ffff, 0xe810c000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateRFE, "rfedb<c> <Rn>{!}" }, 12516 { 0xffd0ffff, 0xe990c000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateRFE, "rfe{ia}<c> <Rn>{!}" }, 12517 12518 //---------------------------------------------------------------------- 12519 // Load instructions 12520 //---------------------------------------------------------------------- 12521 { 0xfffff800, 0x0000c800, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateLDM, "ldm<c> <Rn>{!} <registers>" }, 12522 { 0xffd02000, 0xe8900000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDM, "ldm<c>.w <Rn>{!} <registers>" }, 12523 { 0xffd00000, 0xe9100000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDMDB, "ldmdb<c> <Rn>{!} <registers>" }, 12524 { 0xfffff800, 0x00006800, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateLDRRtRnImm, "ldr<c> <Rt>, [<Rn>{,#imm}]"}, 12525 { 0xfffff800, 0x00009800, ARMV4T_ABOVE, eEncodingT2, No_VFP, eSize16, &EmulateInstructionARM::EmulateLDRRtRnImm, "ldr<c> <Rt>, [SP{,#imm}]"}, 12526 { 0xfff00000, 0xf8d00000, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRRtRnImm, "ldr<c>.w <Rt>, [<Rn>{,#imm12}]"}, 12527 { 0xfff00800, 0xf8500800, ARMV6T2_ABOVE, eEncodingT4, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRRtRnImm, "ldr<c> <Rt>, [<Rn>{,#+/-<imm8>}]{!}"}, 12528 // Thumb2 PC-relative load into register 12529 { 0xff7f0000, 0xf85f0000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRRtPCRelative, "ldr<c>.w <Rt>, [PC, +/-#imm}]"}, 12530 { 0xfffffe00, 0x00005800, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateLDRRegister, "ldr<c> <Rt>, [<Rn>, <Rm>]" }, 12531 { 0xfff00fc0, 0xf8500000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRRegister, "ldr<c>.w <Rt>, [<Rn>,<Rm>{,LSL #<imm2>}]" }, 12532 { 0xfffff800, 0x00007800, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateLDRBImmediate, "ldrb<c> <Rt>,[<Rn>{,#<imm5>}]" }, 12533 { 0xfff00000, 0xf8900000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRBImmediate, "ldrb<c>.w <Rt>,[<Rn>{,#<imm12>}]" }, 12534 { 0xfff00800, 0xf8100800, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRBImmediate, "ldrb<c> <Rt>,[<Rn>, #+/-<imm8>]{!}" }, 12535 { 0xff7f0000, 0xf81f0000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRBLiteral, "ldrb<c> <Rt>,[...]" }, 12536 { 0xfffffe00, 0x00005c00, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateLDRBRegister, "ldrb<c> <Rt>,[<Rn>,<Rm>]" }, 12537 { 0xfff00fc0, 0xf8100000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRBRegister, "ldrb<c>.w <Rt>,[<Rn>,<Rm>{,LSL #imm2>}]" }, 12538 { 0xfffff800, 0x00008800, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateLDRHImmediate, "ldrh<c> <Rt>, [<Rn>{,#<imm>}]" }, 12539 { 0xfff00000, 0xf8b00000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRHImmediate, "ldrh<c>.w <Rt>,[<Rn>{,#<imm12>}]" }, 12540 { 0xfff00800, 0xf8300800, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRHImmediate, "ldrh<c> <Rt>,[<Rn>,#+/-<imm8>]{!}" }, 12541 { 0xff7f0000, 0xf83f0000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRHLiteral, "ldrh<c> <Rt>, <label>" }, 12542 { 0xfffffe00, 0x00005a00, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateLDRHRegister, "ldrh<c> <Rt>, [<Rn>,<Rm>]" }, 12543 { 0xfff00fc0, 0xf8300000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRHRegister, "ldrh<c>.w <Rt>,[<Rn>,<Rm>{,LSL #<imm2>}]" }, 12544 { 0xfff00000, 0xf9900000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRSBImmediate, "ldrsb<c> <Rt>,[<Rn>,#<imm12>]" }, 12545 { 0xfff00800, 0xf9100800, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRSBImmediate, "ldrsb<c> <Rt>,[<Rn>,#+/-<imm8>]" }, 12546 { 0xff7f0000, 0xf91f0000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRSBLiteral, "ldrsb<c> <Rt>, <label>" }, 12547 { 0xfffffe00, 0x00005600, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateLDRSBRegister, "ldrsb<c> <Rt>,[<Rn>,<Rm>]" }, 12548 { 0xfff00fc0, 0xf9100000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRSBRegister, "ldrsb<c>.w <Rt>,[<Rn>,<Rm>{,LSL #imm2>}]" }, 12549 { 0xfff00000, 0xf9b00000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRSHImmediate, "ldrsh<c> <Rt>,[<Rn>,#<imm12>]" }, 12550 { 0xfff00800, 0xf9300800, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRSHImmediate, "ldrsh<c> <Rt>,[<Rn>,#+/-<imm8>]" }, 12551 { 0xff7f0000, 0xf93f0000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRSHLiteral, "ldrsh<c> <Rt>,<label>" }, 12552 { 0xfffffe00, 0x00005e00, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateLDRSHRegister, "ldrsh<c> <Rt>,[<Rn>,<Rm>]" }, 12553 { 0xfff00fc0, 0xf9300000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRSHRegister, "ldrsh<c>.w <Rt>,[<Rn>,<Rm>{,LSL #<imm2>}]" }, 12554 { 0xfe500000, 0xe8500000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRDImmediate, "ldrd<c> <Rt>, <Rt2>, [<Rn>,#+/-<imm>]!"}, 12555 { 0xfe100f00, 0xec100b00, ARMvAll, eEncodingT1, VFPv2_ABOVE, eSize32, &EmulateInstructionARM::EmulateVLDM, "vldm{mode}<c> <Rn>{!}, <list>"}, 12556 { 0xfe100f00, 0xec100a00, ARMvAll, eEncodingT2, VFPv2v3, eSize32, &EmulateInstructionARM::EmulateVLDM, "vldm{mode}<c> <Rn>{!}, <list>" }, 12557 { 0xffe00f00, 0xed100b00, ARMvAll, eEncodingT1, VFPv2_ABOVE, eSize32, &EmulateInstructionARM::EmulateVLDR, "vldr<c> <Dd>, [<Rn>{,#+/-<imm>}]"}, 12558 { 0xff300f00, 0xed100a00, ARMvAll, eEncodingT2, VFPv2v3, eSize32, &EmulateInstructionARM::EmulateVLDR, "vldr<c> <Sd>, {<Rn>{,#+/-<imm>}]"}, 12559 { 0xffb00000, 0xf9200000, ARMvAll, eEncodingT1, AdvancedSIMD, eSize32, &EmulateInstructionARM::EmulateVLD1Multiple, "vld1<c>.<size> <list>, [<Rn>{@<align>}],<Rm>"}, 12560 { 0xffb00300, 0xf9a00000, ARMvAll, eEncodingT1, AdvancedSIMD, eSize32, &EmulateInstructionARM::EmulateVLD1Single, "vld1<c>.<size> <list>, [<Rn>{@<align>}],<Rm>"}, 12561 { 0xffb00f00, 0xf9a00c00, ARMvAll, eEncodingT1, AdvancedSIMD, eSize32, &EmulateInstructionARM::EmulateVLD1SingleAll, "vld1<c>.<size> <list>, [<Rn>{@<align>}], <Rm>"}, 12562 12563 //---------------------------------------------------------------------- 12564 // Store instructions 12565 //---------------------------------------------------------------------- 12566 { 0xfffff800, 0x0000c000, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateSTM, "stm<c> <Rn>{!} <registers>" }, 12567 { 0xffd00000, 0xe8800000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTM, "stm<c>.w <Rn>{!} <registers>" }, 12568 { 0xffd00000, 0xe9000000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTMDB, "stmdb<c> <Rn>{!} <registers>" }, 12569 { 0xfffff800, 0x00006000, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateSTRThumb, "str<c> <Rt>, [<Rn>{,#<imm>}]" }, 12570 { 0xfffff800, 0x00009000, ARMV4T_ABOVE, eEncodingT2, No_VFP, eSize16, &EmulateInstructionARM::EmulateSTRThumb, "str<c> <Rt>, [SP,#<imm>]" }, 12571 { 0xfff00000, 0xf8c00000, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTRThumb, "str<c>.w <Rt>, [<Rn>,#<imm12>]" }, 12572 { 0xfff00800, 0xf8400800, ARMV6T2_ABOVE, eEncodingT4, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTRThumb, "str<c> <Rt>, [<Rn>,#+/-<imm8>]" }, 12573 { 0xfffffe00, 0x00005000, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateSTRRegister, "str<c> <Rt> ,{<Rn>, <Rm>]" }, 12574 { 0xfff00fc0, 0xf8400000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTRRegister, "str<c>.w <Rt>, [<Rn>, <Rm> {lsl #imm2>}]" }, 12575 { 0xfffff800, 0x00007000, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateSTRBThumb, "strb<c> <Rt>, [<Rn>, #<imm5>]" }, 12576 { 0xfff00000, 0xf8800000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTRBThumb, "strb<c>.w <Rt>, [<Rn>, #<imm12>]" }, 12577 { 0xfff00800, 0xf8000800, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTRBThumb, "strb<c> <Rt> ,[<Rn>, #+/-<imm8>]{!}" }, 12578 { 0xfffffe00, 0x00005200, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateSTRHRegister, "strh<c> <Rt>,[<Rn>,<Rm>]" }, 12579 { 0xfff00fc0, 0xf8200000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTRHRegister, "strh<c>.w <Rt>,[<Rn>,<Rm>{,LSL #<imm2>}]" }, 12580 { 0xfff00000, 0xe8400000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTREX, "strex<c> <Rd>, <Rt>, [<Rn{,#<imm>}]" }, 12581 { 0xfe500000, 0xe8400000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTRDImm, "strd<c> <Rt>, <Rt2>, [<Rn>, #+/-<imm>]!"}, 12582 { 0xfe100f00, 0xec000b00, ARMvAll, eEncodingT1, VFPv2_ABOVE, eSize32, &EmulateInstructionARM::EmulateVSTM, "vstm{mode}<c> <Rn>{!}, <list>"}, 12583 { 0xfea00f00, 0xec000a00, ARMvAll, eEncodingT2, VFPv2v3, eSize32, &EmulateInstructionARM::EmulateVSTM, "vstm{mode}<c> <Rn>{!}, <list>"}, 12584 { 0xff300f00, 0xed000b00, ARMvAll, eEncodingT1, VFPv2_ABOVE, eSize32, &EmulateInstructionARM::EmulateVSTR, "vstr<c> <Dd>, [<Rn>{,#+/-<imm>}]"}, 12585 { 0xff300f00, 0xed000a00, ARMvAll, eEncodingT2, VFPv2v3, eSize32, &EmulateInstructionARM::EmulateVSTR, "vstr<c> <Sd>, [<Rn>{,#+/-<imm>}]"}, 12586 { 0xffb00000, 0xfa000000, ARMvAll, eEncodingT1, AdvancedSIMD, eSize32, &EmulateInstructionARM::EmulateVST1Multiple, "vst1<c>.<size> <list>, [<Rn>{@<align>}], <Rm>"}, 12587 { 0xffb00300, 0xf9800000, ARMvAll, eEncodingT1, AdvancedSIMD, eSize32, &EmulateInstructionARM::EmulateVST1Single, "vst1<c>.<size> <list>, [<Rn>{@<align>}], <Rm>"}, 12588 12589 //---------------------------------------------------------------------- 12590 // Other instructions 12591 //---------------------------------------------------------------------- 12592 { 0xffffffc0, 0x0000b240, ARMV6_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateSXTB, "sxtb<c> <Rd>,<Rm>" }, 12593 { 0xfffff080, 0xfa4ff080, ARMV6_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateSXTB, "sxtb<c>.w <Rd>,<Rm>{,<rotation>}" }, 12594 { 0xffffffc0, 0x0000b200, ARMV6_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateSXTH, "sxth<c> <Rd>,<Rm>" }, 12595 { 0xfffff080, 0xfa0ff080, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateSXTH, "sxth<c>.w <Rd>,<Rm>{,<rotation>}" }, 12596 { 0xffffffc0, 0x0000b2c0, ARMV6_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateUXTB, "uxtb<c> <Rd>,<Rm>" }, 12597 { 0xfffff080, 0xfa5ff080, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateUXTB, "uxtb<c>.w <Rd>,<Rm>{,<rotation>}" }, 12598 { 0xffffffc0, 0x0000b280, ARMV6_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateUXTH, "uxth<c> <Rd>,<Rm>" }, 12599 { 0xfffff080, 0xfa1ff080, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateUXTH, "uxth<c>.w <Rd>,<Rm>{,<rotation>}" }, 12600 }; 12601 12602 const size_t k_num_thumb_opcodes = sizeof(g_thumb_opcodes)/sizeof(ARMOpcode); 12603 for (size_t i=0; i<k_num_thumb_opcodes; ++i) 12604 { 12605 if ((g_thumb_opcodes[i].mask & opcode) == g_thumb_opcodes[i].value) 12606 return &g_thumb_opcodes[i]; 12607 } 12608 return NULL; 12609} 12610 12611bool 12612EmulateInstructionARM::SetArchitecture (const ArchSpec &arch) 12613{ 12614 m_arch = arch; 12615 m_arm_isa = 0; 12616 const char *arch_cstr = arch.GetArchitectureName (); 12617 if (arch_cstr) 12618 { 12619 if (0 == ::strcasecmp(arch_cstr, "armv4t")) m_arm_isa = ARMv4T; 12620 else if (0 == ::strcasecmp(arch_cstr, "armv4")) m_arm_isa = ARMv4; 12621 else if (0 == ::strcasecmp(arch_cstr, "armv5tej")) m_arm_isa = ARMv5TEJ; 12622 else if (0 == ::strcasecmp(arch_cstr, "armv5te")) m_arm_isa = ARMv5TE; 12623 else if (0 == ::strcasecmp(arch_cstr, "armv5t")) m_arm_isa = ARMv5T; 12624 else if (0 == ::strcasecmp(arch_cstr, "armv6k")) m_arm_isa = ARMv6K; 12625 else if (0 == ::strcasecmp(arch_cstr, "armv6")) m_arm_isa = ARMv6; 12626 else if (0 == ::strcasecmp(arch_cstr, "armv6t2")) m_arm_isa = ARMv6T2; 12627 else if (0 == ::strcasecmp(arch_cstr, "armv7")) m_arm_isa = ARMv7; 12628 else if (0 == ::strcasecmp(arch_cstr, "armv8")) m_arm_isa = ARMv8; 12629 } 12630 return m_arm_isa != 0; 12631} 12632 12633bool 12634EmulateInstructionARM::SetInstruction (const Opcode &insn_opcode, const Address &inst_addr) 12635{ 12636 m_opcode = insn_opcode; 12637 12638 if (m_arch.GetTriple().getArch() == llvm::Triple::thumb) 12639 m_opcode_mode = eModeThumb; 12640 else 12641 { 12642 AddressClass addr_class = inst_addr.GetAddressClass(); 12643 12644 if ((addr_class == eAddressClassCode) || (addr_class == eAddressClassUnknown)) 12645 m_opcode_mode = eModeARM; 12646 else if (addr_class == eAddressClassCodeAlternateISA) 12647 m_opcode_mode = eModeThumb; 12648 else 12649 return false; 12650 } 12651 return true; 12652} 12653 12654bool 12655EmulateInstructionARM::ReadInstruction () 12656{ 12657 bool success = false; 12658 m_opcode_cpsr = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS, 0, &success); 12659 if (success) 12660 { 12661 addr_t pc = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, LLDB_INVALID_ADDRESS, &success); 12662 if (success) 12663 { 12664 Context read_inst_context; 12665 read_inst_context.type = eContextReadOpcode; 12666 read_inst_context.SetNoArgs (); 12667 12668 if (m_opcode_cpsr & MASK_CPSR_T) 12669 { 12670 m_opcode_mode = eModeThumb; 12671 uint32_t thumb_opcode = MemARead(read_inst_context, pc, 2, 0, &success); 12672 12673 if (success) 12674 { 12675 if ((thumb_opcode & 0xe000) != 0xe000 || ((thumb_opcode & 0x1800u) == 0)) 12676 { 12677 m_opcode.SetOpcode16 (thumb_opcode); 12678 } 12679 else 12680 { 12681 m_opcode.SetOpcode32 ((thumb_opcode << 16) | MemARead(read_inst_context, pc + 2, 2, 0, &success)); 12682 } 12683 } 12684 } 12685 else 12686 { 12687 m_opcode_mode = eModeARM; 12688 m_opcode.SetOpcode32 (MemARead(read_inst_context, pc, 4, 0, &success)); 12689 } 12690 } 12691 } 12692 if (!success) 12693 { 12694 m_opcode_mode = eModeInvalid; 12695 m_opcode_pc = LLDB_INVALID_ADDRESS; 12696 } 12697 return success; 12698} 12699 12700uint32_t 12701EmulateInstructionARM::ArchVersion () 12702{ 12703 return m_arm_isa; 12704} 12705 12706bool 12707EmulateInstructionARM::ConditionPassed (const uint32_t opcode) 12708{ 12709 12710 const uint32_t cond = CurrentCond (opcode); 12711 12712 if (cond == UINT32_MAX) 12713 return false; 12714 12715 bool result = false; 12716 switch (UnsignedBits(cond, 3, 1)) 12717 { 12718 case 0: 12719 if (m_opcode_cpsr == 0) 12720 return true; 12721 result = (m_opcode_cpsr & MASK_CPSR_Z) != 0; 12722 break; 12723 case 1: 12724 if (m_opcode_cpsr == 0) 12725 return true; 12726 result = (m_opcode_cpsr & MASK_CPSR_C) != 0; 12727 break; 12728 case 2: 12729 if (m_opcode_cpsr == 0) 12730 return true; 12731 result = (m_opcode_cpsr & MASK_CPSR_N) != 0; 12732 break; 12733 case 3: 12734 if (m_opcode_cpsr == 0) 12735 return true; 12736 result = (m_opcode_cpsr & MASK_CPSR_V) != 0; 12737 break; 12738 case 4: 12739 if (m_opcode_cpsr == 0) 12740 return true; 12741 result = ((m_opcode_cpsr & MASK_CPSR_C) != 0) && ((m_opcode_cpsr & MASK_CPSR_Z) == 0); 12742 break; 12743 case 5: 12744 if (m_opcode_cpsr == 0) 12745 return true; 12746 else 12747 { 12748 bool n = (m_opcode_cpsr & MASK_CPSR_N); 12749 bool v = (m_opcode_cpsr & MASK_CPSR_V); 12750 result = n == v; 12751 } 12752 break; 12753 case 6: 12754 if (m_opcode_cpsr == 0) 12755 return true; 12756 else 12757 { 12758 bool n = (m_opcode_cpsr & MASK_CPSR_N); 12759 bool v = (m_opcode_cpsr & MASK_CPSR_V); 12760 result = n == v && ((m_opcode_cpsr & MASK_CPSR_Z) == 0); 12761 } 12762 break; 12763 case 7: 12764 result = true; 12765 break; 12766 } 12767 12768 if (cond & 1) 12769 result = !result; 12770 return result; 12771} 12772 12773uint32_t 12774EmulateInstructionARM::CurrentCond (const uint32_t opcode) 12775{ 12776 switch (m_opcode_mode) 12777 { 12778 default: 12779 case eModeInvalid: 12780 break; 12781 12782 case eModeARM: 12783 return UnsignedBits(opcode, 31, 28); 12784 12785 case eModeThumb: 12786 // For T1 and T3 encodings of the Branch instruction, it returns the 4-bit 12787 // 'cond' field of the encoding. 12788 { 12789 const uint32_t byte_size = m_opcode.GetByteSize(); 12790 if (byte_size == 2) 12791 { 12792 if (Bits32(opcode, 15, 12) == 0x0d && Bits32(opcode, 11, 7) != 0x0f) 12793 return Bits32(opcode, 11, 7); 12794 } 12795 else 12796 { 12797 assert (byte_size == 4); 12798 if (Bits32(opcode, 31, 27) == 0x1e && 12799 Bits32(opcode, 15, 14) == 0x02 && 12800 Bits32(opcode, 12, 12) == 0x00 && 12801 Bits32(opcode, 25, 22) <= 0x0d) 12802 { 12803 return Bits32(opcode, 25, 22); 12804 } 12805 } 12806 12807 return m_it_session.GetCond(); 12808 } 12809 } 12810 return UINT32_MAX; // Return invalid value 12811} 12812 12813bool 12814EmulateInstructionARM::InITBlock() 12815{ 12816 return CurrentInstrSet() == eModeThumb && m_it_session.InITBlock(); 12817} 12818 12819bool 12820EmulateInstructionARM::LastInITBlock() 12821{ 12822 return CurrentInstrSet() == eModeThumb && m_it_session.LastInITBlock(); 12823} 12824 12825bool 12826EmulateInstructionARM::BadMode (uint32_t mode) 12827{ 12828 12829 switch (mode) 12830 { 12831 case 16: return false; // '10000' 12832 case 17: return false; // '10001' 12833 case 18: return false; // '10010' 12834 case 19: return false; // '10011' 12835 case 22: return false; // '10110' 12836 case 23: return false; // '10111' 12837 case 27: return false; // '11011' 12838 case 31: return false; // '11111' 12839 default: return true; 12840 } 12841 return true; 12842} 12843 12844bool 12845EmulateInstructionARM::CurrentModeIsPrivileged () 12846{ 12847 uint32_t mode = Bits32 (m_opcode_cpsr, 4, 0); 12848 12849 if (BadMode (mode)) 12850 return false; 12851 12852 if (mode == 16) 12853 return false; 12854 12855 return true; 12856} 12857 12858void 12859EmulateInstructionARM::CPSRWriteByInstr (uint32_t value, uint32_t bytemask, bool affect_execstate) 12860{ 12861 bool privileged = CurrentModeIsPrivileged(); 12862 12863 uint32_t tmp_cpsr = 0; 12864 12865 tmp_cpsr = tmp_cpsr | (Bits32 (m_opcode_cpsr, 23, 20) << 20); 12866 12867 if (BitIsSet (bytemask, 3)) 12868 { 12869 tmp_cpsr = tmp_cpsr | (Bits32 (value, 31, 27) << 27); 12870 if (affect_execstate) 12871 tmp_cpsr = tmp_cpsr | (Bits32 (value, 26, 24) << 24); 12872 } 12873 12874 if (BitIsSet (bytemask, 2)) 12875 { 12876 tmp_cpsr = tmp_cpsr | (Bits32 (value, 19, 16) << 16); 12877 } 12878 12879 if (BitIsSet (bytemask, 1)) 12880 { 12881 if (affect_execstate) 12882 tmp_cpsr = tmp_cpsr | (Bits32 (value, 15, 10) << 10); 12883 tmp_cpsr = tmp_cpsr | (Bit32 (value, 9) << 9); 12884 if (privileged) 12885 tmp_cpsr = tmp_cpsr | (Bit32 (value, 8) << 8); 12886 } 12887 12888 if (BitIsSet (bytemask, 0)) 12889 { 12890 if (privileged) 12891 tmp_cpsr = tmp_cpsr | (Bits32 (value, 7, 6) << 6); 12892 if (affect_execstate) 12893 tmp_cpsr = tmp_cpsr | (Bit32 (value, 5) << 5); 12894 if (privileged) 12895 tmp_cpsr = tmp_cpsr | Bits32 (value, 4, 0); 12896 } 12897 12898 m_opcode_cpsr = tmp_cpsr; 12899} 12900 12901 12902bool 12903EmulateInstructionARM::BranchWritePC (const Context &context, uint32_t addr) 12904{ 12905 addr_t target; 12906 12907 // Check the current instruction set. 12908 if (CurrentInstrSet() == eModeARM) 12909 target = addr & 0xfffffffc; 12910 else 12911 target = addr & 0xfffffffe; 12912 12913 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, target)) 12914 return false; 12915 12916 return true; 12917} 12918 12919// As a side effect, BXWritePC sets context.arg2 to eModeARM or eModeThumb by inspecting addr. 12920bool 12921EmulateInstructionARM::BXWritePC (Context &context, uint32_t addr) 12922{ 12923 addr_t target; 12924 // If the CPSR is changed due to switching between ARM and Thumb ISETSTATE, 12925 // we want to record it and issue a WriteRegister callback so the clients 12926 // can track the mode changes accordingly. 12927 bool cpsr_changed = false; 12928 12929 if (BitIsSet(addr, 0)) 12930 { 12931 if (CurrentInstrSet() != eModeThumb) 12932 { 12933 SelectInstrSet(eModeThumb); 12934 cpsr_changed = true; 12935 } 12936 target = addr & 0xfffffffe; 12937 context.SetMode (eModeThumb); 12938 } 12939 else if (BitIsClear(addr, 1)) 12940 { 12941 if (CurrentInstrSet() != eModeARM) 12942 { 12943 SelectInstrSet(eModeARM); 12944 cpsr_changed = true; 12945 } 12946 target = addr & 0xfffffffc; 12947 context.SetMode (eModeARM); 12948 } 12949 else 12950 return false; // address<1:0> == '10' => UNPREDICTABLE 12951 12952 if (cpsr_changed) 12953 { 12954 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS, m_new_inst_cpsr)) 12955 return false; 12956 } 12957 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, target)) 12958 return false; 12959 12960 return true; 12961} 12962 12963// Dispatches to either BXWritePC or BranchWritePC based on architecture versions. 12964bool 12965EmulateInstructionARM::LoadWritePC (Context &context, uint32_t addr) 12966{ 12967 if (ArchVersion() >= ARMv5T) 12968 return BXWritePC(context, addr); 12969 else 12970 return BranchWritePC((const Context)context, addr); 12971} 12972 12973// Dispatches to either BXWritePC or BranchWritePC based on architecture versions and current instruction set. 12974bool 12975EmulateInstructionARM::ALUWritePC (Context &context, uint32_t addr) 12976{ 12977 if (ArchVersion() >= ARMv7 && CurrentInstrSet() == eModeARM) 12978 return BXWritePC(context, addr); 12979 else 12980 return BranchWritePC((const Context)context, addr); 12981} 12982 12983EmulateInstructionARM::Mode 12984EmulateInstructionARM::CurrentInstrSet () 12985{ 12986 return m_opcode_mode; 12987} 12988 12989// Set the 'T' bit of our CPSR. The m_opcode_mode gets updated when the next 12990// ReadInstruction() is performed. This function has a side effect of updating 12991// the m_new_inst_cpsr member variable if necessary. 12992bool 12993EmulateInstructionARM::SelectInstrSet (Mode arm_or_thumb) 12994{ 12995 m_new_inst_cpsr = m_opcode_cpsr; 12996 switch (arm_or_thumb) 12997 { 12998 default: 12999 return false; 13000 eModeARM: 13001 // Clear the T bit. 13002 m_new_inst_cpsr &= ~MASK_CPSR_T; 13003 break; 13004 eModeThumb: 13005 // Set the T bit. 13006 m_new_inst_cpsr |= MASK_CPSR_T; 13007 break; 13008 } 13009 return true; 13010} 13011 13012// This function returns TRUE if the processor currently provides support for 13013// unaligned memory accesses, or FALSE otherwise. This is always TRUE in ARMv7, 13014// controllable by the SCTLR.U bit in ARMv6, and always FALSE before ARMv6. 13015bool 13016EmulateInstructionARM::UnalignedSupport() 13017{ 13018 return (ArchVersion() >= ARMv7); 13019} 13020 13021// The main addition and subtraction instructions can produce status information 13022// about both unsigned carry and signed overflow conditions. This status 13023// information can be used to synthesize multi-word additions and subtractions. 13024EmulateInstructionARM::AddWithCarryResult 13025EmulateInstructionARM::AddWithCarry (uint32_t x, uint32_t y, uint8_t carry_in) 13026{ 13027 uint32_t result; 13028 uint8_t carry_out; 13029 uint8_t overflow; 13030 13031 uint64_t unsigned_sum = x + y + carry_in; 13032 int64_t signed_sum = (int32_t)x + (int32_t)y + (int32_t)carry_in; 13033 13034 result = UnsignedBits(unsigned_sum, 31, 0); 13035// carry_out = (result == unsigned_sum ? 0 : 1); 13036 overflow = ((int32_t)result == signed_sum ? 0 : 1); 13037 13038 if (carry_in) 13039 carry_out = ((int32_t) x >= (int32_t) (~y)) ? 1 : 0; 13040 else 13041 carry_out = ((int32_t) x > (int32_t) y) ? 1 : 0; 13042 13043 AddWithCarryResult res = { result, carry_out, overflow }; 13044 return res; 13045} 13046 13047uint32_t 13048EmulateInstructionARM::ReadCoreReg(uint32_t num, bool *success) 13049{ 13050 uint32_t reg_kind, reg_num; 13051 switch (num) 13052 { 13053 case SP_REG: 13054 reg_kind = eRegisterKindGeneric; 13055 reg_num = LLDB_REGNUM_GENERIC_SP; 13056 break; 13057 case LR_REG: 13058 reg_kind = eRegisterKindGeneric; 13059 reg_num = LLDB_REGNUM_GENERIC_RA; 13060 break; 13061 case PC_REG: 13062 reg_kind = eRegisterKindGeneric; 13063 reg_num = LLDB_REGNUM_GENERIC_PC; 13064 break; 13065 default: 13066 if (num < SP_REG) 13067 { 13068 reg_kind = eRegisterKindDWARF; 13069 reg_num = dwarf_r0 + num; 13070 } 13071 else 13072 { 13073 assert(0 && "Invalid register number"); 13074 *success = false; 13075 return UINT32_MAX; 13076 } 13077 break; 13078 } 13079 13080 // Read our register. 13081 uint32_t val = ReadRegisterUnsigned (reg_kind, reg_num, 0, success); 13082 13083 // When executing an ARM instruction , PC reads as the address of the current 13084 // instruction plus 8. 13085 // When executing a Thumb instruction , PC reads as the address of the current 13086 // instruction plus 4. 13087 if (num == 15) 13088 { 13089 if (CurrentInstrSet() == eModeARM) 13090 val += 8; 13091 else 13092 val += 4; 13093 } 13094 13095 return val; 13096} 13097 13098// Write the result to the ARM core register Rd, and optionally update the 13099// condition flags based on the result. 13100// 13101// This helper method tries to encapsulate the following pseudocode from the 13102// ARM Architecture Reference Manual: 13103// 13104// if d == 15 then // Can only occur for encoding A1 13105// ALUWritePC(result); // setflags is always FALSE here 13106// else 13107// R[d] = result; 13108// if setflags then 13109// APSR.N = result<31>; 13110// APSR.Z = IsZeroBit(result); 13111// APSR.C = carry; 13112// // APSR.V unchanged 13113// 13114// In the above case, the API client does not pass in the overflow arg, which 13115// defaults to ~0u. 13116bool 13117EmulateInstructionARM::WriteCoreRegOptionalFlags (Context &context, 13118 const uint32_t result, 13119 const uint32_t Rd, 13120 bool setflags, 13121 const uint32_t carry, 13122 const uint32_t overflow) 13123{ 13124 if (Rd == 15) 13125 { 13126 if (!ALUWritePC (context, result)) 13127 return false; 13128 } 13129 else 13130 { 13131 uint32_t reg_kind, reg_num; 13132 switch (Rd) 13133 { 13134 case SP_REG: 13135 reg_kind = eRegisterKindGeneric; 13136 reg_num = LLDB_REGNUM_GENERIC_SP; 13137 break; 13138 case LR_REG: 13139 reg_kind = eRegisterKindGeneric; 13140 reg_num = LLDB_REGNUM_GENERIC_RA; 13141 break; 13142 default: 13143 reg_kind = eRegisterKindDWARF; 13144 reg_num = dwarf_r0 + Rd; 13145 } 13146 if (!WriteRegisterUnsigned (context, reg_kind, reg_num, result)) 13147 return false; 13148 if (setflags) 13149 return WriteFlags (context, result, carry, overflow); 13150 } 13151 return true; 13152} 13153 13154// This helper method tries to encapsulate the following pseudocode from the 13155// ARM Architecture Reference Manual: 13156// 13157// APSR.N = result<31>; 13158// APSR.Z = IsZeroBit(result); 13159// APSR.C = carry; 13160// APSR.V = overflow 13161// 13162// Default arguments can be specified for carry and overflow parameters, which means 13163// not to update the respective flags. 13164bool 13165EmulateInstructionARM::WriteFlags (Context &context, 13166 const uint32_t result, 13167 const uint32_t carry, 13168 const uint32_t overflow) 13169{ 13170 m_new_inst_cpsr = m_opcode_cpsr; 13171 SetBit32(m_new_inst_cpsr, CPSR_N_POS, Bit32(result, CPSR_N_POS)); 13172 SetBit32(m_new_inst_cpsr, CPSR_Z_POS, result == 0 ? 1 : 0); 13173 if (carry != ~0u) 13174 SetBit32(m_new_inst_cpsr, CPSR_C_POS, carry); 13175 if (overflow != ~0u) 13176 SetBit32(m_new_inst_cpsr, CPSR_V_POS, overflow); 13177 if (m_new_inst_cpsr != m_opcode_cpsr) 13178 { 13179 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS, m_new_inst_cpsr)) 13180 return false; 13181 } 13182 return true; 13183} 13184 13185bool 13186EmulateInstructionARM::EvaluateInstruction () 13187{ 13188 // Advance the ITSTATE bits to their values for the next instruction. 13189 if (m_opcode_mode == eModeThumb && m_it_session.InITBlock()) 13190 m_it_session.ITAdvance(); 13191 13192 13193 ARMOpcode *opcode_data; 13194 13195 if (m_opcode_mode == eModeThumb) 13196 { 13197 if (m_opcode.GetType() == Opcode::eType32) 13198 { 13199 uint16_t upper_bits = Bits32 (m_opcode.GetOpcode32(), 31, 16); 13200 uint16_t lower_bits = Bits32 (m_opcode.GetOpcode32(), 15, 0); 13201 uint32_t swapped = (lower_bits << 16) | upper_bits; 13202 m_opcode.SetOpcode32 (swapped); 13203 } 13204 opcode_data = GetThumbOpcodeForInstruction (m_opcode.GetOpcode32()); 13205 } 13206 else if (m_opcode_mode == eModeARM) 13207 opcode_data = GetARMOpcodeForInstruction (m_opcode.GetOpcode32()); 13208 else 13209 return false; 13210 13211 if (!opcode_data) 13212 return false; 13213 // Verify that we're the right arch for this opcode 13214 13215 switch (m_arm_isa) 13216 { 13217 case ARMv4: 13218 if (opcode_data->variants != ARMvAll) 13219 return false; 13220 break; 13221 13222 case ARMv4T: 13223 if ((opcode_data->variants!= ARMvAll) 13224 && (opcode_data->variants != ARMV4T_ABOVE)) 13225 return false; 13226 break; 13227 13228 case ARMv5T: 13229 case ARMv5TE: 13230 if ((opcode_data->variants != ARMvAll) 13231 && (opcode_data->variants != ARMV4T_ABOVE) 13232 && (opcode_data->variants != ARMV5_ABOVE)) 13233 return false; 13234 break; 13235 13236 case ARMv5TEJ: 13237 if ((opcode_data->variants != ARMvAll) 13238 && (opcode_data->variants != ARMV4T_ABOVE) 13239 && (opcode_data->variants != ARMV5_ABOVE) 13240 && (opcode_data->variants != ARMV5J_ABOVE)) 13241 return false; 13242 break; 13243 13244 case ARMv6: 13245 case ARMv6K: 13246 if ((opcode_data->variants != ARMvAll) 13247 && (opcode_data->variants != ARMV4T_ABOVE) 13248 && (opcode_data->variants != ARMV5_ABOVE) 13249 && (opcode_data->variants != ARMV5J_ABOVE) 13250 && (opcode_data->variants != ARMV6_ABOVE)) 13251 return false; 13252 break; 13253 13254 case ARMv6T2: 13255 case ARMv7: 13256 case ARMv8: 13257 if ((opcode_data->variants != ARMvAll) 13258 && (opcode_data->variants != ARMV4T_ABOVE) 13259 && (opcode_data->variants != ARMV5_ABOVE) 13260 && (opcode_data->variants != ARMV5J_ABOVE) 13261 && (opcode_data->variants != ARMV6_ABOVE) 13262 && (opcode_data->variants != ARMV6T2_ABOVE)) 13263 return false; 13264 break; 13265 13266 default: 13267// if (opcode_data->variants != ARMvAll) 13268// return false; 13269 break; 13270 } 13271 13272 // Just for now, for testing purposes. 13273 if (m_baton == NULL) 13274 fprintf (stdout, "\nEvaluateInstruction, opcode (0x%x), found = '%s'\n", m_opcode.GetOpcode32(), 13275 opcode_data->name); 13276 13277 bool success; 13278 if (m_baton) 13279 { 13280 uint32_t cpsr_value = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_cpsr, 0, &success); 13281 if (success) 13282 m_opcode_cpsr = cpsr_value; 13283 } 13284 13285 uint32_t orig_pc_value = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc, 0, &success); 13286 if (!success) 13287 return false; 13288 13289 success = (this->*opcode_data->callback) (m_opcode.GetOpcode32(), opcode_data->encoding); // Call the Emulate... function. 13290 if (!success) 13291 return false; 13292 13293 uint32_t after_pc_value = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc, 0, &success); 13294 if (!success) 13295 return false; 13296 13297 if (m_advance_pc && (after_pc_value == orig_pc_value)) 13298 { 13299 if (opcode_data->size == eSize32) 13300 after_pc_value += 4; 13301 else if (opcode_data->size == eSize16) 13302 after_pc_value += 2; 13303 13304 EmulateInstruction::Context context; 13305 context.type = eContextAdvancePC; 13306 context.SetNoArgs(); 13307 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc, after_pc_value)) 13308 return false; 13309 13310 } 13311 13312 return true; 13313} 13314