EmulateInstructionARM.cpp revision d05b4903bb95b07e709986961fe387921dd0e029
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/ConstString.h" 15 16#include "Plugins/Process/Utility/ARMDefines.h" 17#include "Plugins/Process/Utility/ARMUtils.h" 18#include "Utility/ARM_DWARF_Registers.h" 19 20#include "llvm/Support/MathExtras.h" // for SignExtend32 template function 21 // and CountTrailingZeros_32 function 22 23using namespace lldb; 24using namespace lldb_private; 25 26// Convenient macro definitions. 27#define APSR_C Bit32(m_opcode_cpsr, CPSR_C_POS) 28#define APSR_V Bit32(m_opcode_cpsr, CPSR_V_POS) 29 30#define AlignPC(pc_val) (pc_val & 0xFFFFFFFC) 31 32//---------------------------------------------------------------------- 33// 34// ITSession implementation 35// 36//---------------------------------------------------------------------- 37 38// A8.6.50 39// Valid return values are {1, 2, 3, 4}, with 0 signifying an error condition. 40static unsigned short CountITSize(unsigned ITMask) { 41 // First count the trailing zeros of the IT mask. 42 unsigned TZ = llvm::CountTrailingZeros_32(ITMask); 43 if (TZ > 3) 44 { 45 printf("Encoding error: IT Mask '0000'\n"); 46 return 0; 47 } 48 return (4 - TZ); 49} 50 51// Init ITState. Note that at least one bit is always 1 in mask. 52bool ITSession::InitIT(unsigned short bits7_0) 53{ 54 ITCounter = CountITSize(Bits32(bits7_0, 3, 0)); 55 if (ITCounter == 0) 56 return false; 57 58 // A8.6.50 IT 59 unsigned short FirstCond = Bits32(bits7_0, 7, 4); 60 if (FirstCond == 0xF) 61 { 62 printf("Encoding error: IT FirstCond '1111'\n"); 63 return false; 64 } 65 if (FirstCond == 0xE && ITCounter != 1) 66 { 67 printf("Encoding error: IT FirstCond '1110' && Mask != '1000'\n"); 68 return false; 69 } 70 71 ITState = bits7_0; 72 return true; 73} 74 75// Update ITState if necessary. 76void ITSession::ITAdvance() 77{ 78 assert(ITCounter); 79 --ITCounter; 80 if (ITCounter == 0) 81 ITState = 0; 82 else 83 { 84 unsigned short NewITState4_0 = Bits32(ITState, 4, 0) << 1; 85 SetBits32(ITState, 4, 0, NewITState4_0); 86 } 87} 88 89// Return true if we're inside an IT Block. 90bool ITSession::InITBlock() 91{ 92 return ITCounter != 0; 93} 94 95// Return true if we're the last instruction inside an IT Block. 96bool ITSession::LastInITBlock() 97{ 98 return ITCounter == 1; 99} 100 101// Get condition bits for the current thumb instruction. 102uint32_t ITSession::GetCond() 103{ 104 if (InITBlock()) 105 return Bits32(ITState, 7, 4); 106 else 107 return COND_AL; 108} 109 110// ARM constants used during decoding 111#define REG_RD 0 112#define LDM_REGLIST 1 113#define SP_REG 13 114#define LR_REG 14 115#define PC_REG 15 116#define PC_REGLIST_BIT 0x8000 117 118#define ARMv4 (1u << 0) 119#define ARMv4T (1u << 1) 120#define ARMv5T (1u << 2) 121#define ARMv5TE (1u << 3) 122#define ARMv5TEJ (1u << 4) 123#define ARMv6 (1u << 5) 124#define ARMv6K (1u << 6) 125#define ARMv6T2 (1u << 7) 126#define ARMv7 (1u << 8) 127#define ARMv8 (1u << 9) 128#define ARMvAll (0xffffffffu) 129 130#define ARMV4T_ABOVE (ARMv4T|ARMv5T|ARMv5TE|ARMv5TEJ|ARMv6|ARMv6K|ARMv6T2|ARMv7|ARMv8) 131#define ARMV5_ABOVE (ARMv5T|ARMv5TE|ARMv5TEJ|ARMv6|ARMv6K|ARMv6T2|ARMv7|ARMv8) 132#define ARMV5J_ABOVE (ARMv5TEJ|ARMv6|ARMv6K|ARMv6T2|ARMv7|ARMv8) 133#define ARMV6_ABOVE (ARMv6|ARMv6K|ARMv6T2|ARMv7|ARMv8) 134#define ARMV6T2_ABOVE (ARMv6T2|ARMv7|ARMv8) 135 136//---------------------------------------------------------------------- 137// 138// EmulateInstructionARM implementation 139// 140//---------------------------------------------------------------------- 141 142void 143EmulateInstructionARM::Initialize () 144{ 145} 146 147void 148EmulateInstructionARM::Terminate () 149{ 150} 151 152// Write "bits (32) UNKNOWN" to memory address "address". Helper function for many ARM instructions. 153bool 154EmulateInstructionARM::WriteBits32UnknownToMemory (addr_t address) 155{ 156 EmulateInstruction::Context context; 157 context.type = EmulateInstruction::eContextWriteMemoryRandomBits; 158 context.SetNoArgs (); 159 160 uint32_t random_data = rand (); 161 const uint32_t addr_byte_size = GetAddressByteSize(); 162 163 if (!MemAWrite (context, address, random_data, addr_byte_size)) 164 return false; 165 166 return true; 167} 168 169// Write "bits (32) UNKNOWN" to register n. Helper function for many ARM instructions. 170bool 171EmulateInstructionARM::WriteBits32Unknown (int n) 172{ 173 EmulateInstruction::Context context; 174 context.type = EmulateInstruction::eContextWriteRegisterRandomBits; 175 context.SetNoArgs (); 176 177 bool success; 178 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success); 179 180 if (!success) 181 return false; 182 183 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, data)) 184 return false; 185 186 return true; 187} 188 189// Push Multiple Registers stores multiple registers to the stack, storing to 190// consecutive memory locations ending just below the address in SP, and updates 191// SP to point to the start of the stored data. 192bool 193EmulateInstructionARM::EmulatePUSH (const uint32_t opcode, const ARMEncoding encoding) 194{ 195#if 0 196 // ARM pseudo code... 197 if (ConditionPassed()) 198 { 199 EncodingSpecificOperations(); 200 NullCheckIfThumbEE(13); 201 address = SP - 4*BitCount(registers); 202 203 for (i = 0 to 14) 204 { 205 if (registers<i> == '1') 206 { 207 if i == 13 && i != LowestSetBit(registers) // Only possible for encoding A1 208 MemA[address,4] = bits(32) UNKNOWN; 209 else 210 MemA[address,4] = R[i]; 211 address = address + 4; 212 } 213 } 214 215 if (registers<15> == '1') // Only possible for encoding A1 or A2 216 MemA[address,4] = PCStoreValue(); 217 218 SP = SP - 4*BitCount(registers); 219 } 220#endif 221 222 bool success = false; 223 if (ConditionPassed(opcode)) 224 { 225 const uint32_t addr_byte_size = GetAddressByteSize(); 226 const addr_t sp = ReadCoreReg (SP_REG, &success); 227 if (!success) 228 return false; 229 uint32_t registers = 0; 230 uint32_t Rt; // the source register 231 switch (encoding) { 232 case eEncodingT1: 233 registers = Bits32(opcode, 7, 0); 234 // The M bit represents LR. 235 if (Bit32(opcode, 8)) 236 registers |= (1u << 14); 237 // if BitCount(registers) < 1 then UNPREDICTABLE; 238 if (BitCount(registers) < 1) 239 return false; 240 break; 241 case eEncodingT2: 242 // Ignore bits 15 & 13. 243 registers = Bits32(opcode, 15, 0) & ~0xa000; 244 // if BitCount(registers) < 2 then UNPREDICTABLE; 245 if (BitCount(registers) < 2) 246 return false; 247 break; 248 case eEncodingT3: 249 Rt = Bits32(opcode, 15, 12); 250 // if BadReg(t) then UNPREDICTABLE; 251 if (BadReg(Rt)) 252 return false; 253 registers = (1u << Rt); 254 break; 255 case eEncodingA1: 256 registers = Bits32(opcode, 15, 0); 257 // Instead of return false, let's handle the following case as well, 258 // which amounts to pushing one reg onto the full descending stacks. 259 // if BitCount(register_list) < 2 then SEE STMDB / STMFD; 260 break; 261 case eEncodingA2: 262 Rt = Bits32(opcode, 15, 12); 263 // if t == 13 then UNPREDICTABLE; 264 if (Rt == dwarf_sp) 265 return false; 266 registers = (1u << Rt); 267 break; 268 default: 269 return false; 270 } 271 addr_t sp_offset = addr_byte_size * BitCount (registers); 272 addr_t addr = sp - sp_offset; 273 uint32_t i; 274 275 EmulateInstruction::Context context; 276 context.type = EmulateInstruction::eContextPushRegisterOnStack; 277 Register dwarf_reg; 278 dwarf_reg.SetRegister (eRegisterKindDWARF, 0); 279 Register sp_reg; 280 sp_reg.SetRegister (eRegisterKindDWARF, dwarf_sp); 281 for (i=0; i<15; ++i) 282 { 283 if (BitIsSet (registers, i)) 284 { 285 dwarf_reg.num = dwarf_r0 + i; 286 context.SetRegisterToRegisterPlusOffset (dwarf_reg, sp_reg, addr - sp); 287 uint32_t reg_value = ReadCoreReg(i, &success); 288 if (!success) 289 return false; 290 if (!MemAWrite (context, addr, reg_value, addr_byte_size)) 291 return false; 292 addr += addr_byte_size; 293 } 294 } 295 296 if (BitIsSet (registers, 15)) 297 { 298 dwarf_reg.num = dwarf_pc; 299 context.SetRegisterPlusOffset (dwarf_reg, addr - sp); 300 const uint32_t pc = ReadCoreReg(PC_REG, &success); 301 if (!success) 302 return false; 303 if (!MemAWrite (context, addr, pc, addr_byte_size)) 304 return false; 305 } 306 307 context.type = EmulateInstruction::eContextAdjustStackPointer; 308 context.SetImmediateSigned (-sp_offset); 309 310 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, sp - sp_offset)) 311 return false; 312 } 313 return true; 314} 315 316// Pop Multiple Registers loads multiple registers from the stack, loading from 317// consecutive memory locations staring at the address in SP, and updates 318// SP to point just above the loaded data. 319bool 320EmulateInstructionARM::EmulatePOP (const uint32_t opcode, const ARMEncoding encoding) 321{ 322#if 0 323 // ARM pseudo code... 324 if (ConditionPassed()) 325 { 326 EncodingSpecificOperations(); NullCheckIfThumbEE(13); 327 address = SP; 328 for i = 0 to 14 329 if registers<i> == '1' then 330 R[i} = if UnalignedAllowed then MemU[address,4] else MemA[address,4]; address = address + 4; 331 if registers<15> == '1' then 332 if UnalignedAllowed then 333 LoadWritePC(MemU[address,4]); 334 else 335 LoadWritePC(MemA[address,4]); 336 if registers<13> == '0' then SP = SP + 4*BitCount(registers); 337 if registers<13> == '1' then SP = bits(32) UNKNOWN; 338 } 339#endif 340 341 bool success = false; 342 343 if (ConditionPassed(opcode)) 344 { 345 const uint32_t addr_byte_size = GetAddressByteSize(); 346 const addr_t sp = ReadCoreReg (SP_REG, &success); 347 if (!success) 348 return false; 349 uint32_t registers = 0; 350 uint32_t Rt; // the destination register 351 switch (encoding) { 352 case eEncodingT1: 353 registers = Bits32(opcode, 7, 0); 354 // The P bit represents PC. 355 if (Bit32(opcode, 8)) 356 registers |= (1u << 15); 357 // if BitCount(registers) < 1 then UNPREDICTABLE; 358 if (BitCount(registers) < 1) 359 return false; 360 break; 361 case eEncodingT2: 362 // Ignore bit 13. 363 registers = Bits32(opcode, 15, 0) & ~0x2000; 364 // if BitCount(registers) < 2 || (P == '1' && M == '1') then UNPREDICTABLE; 365 if (BitCount(registers) < 2 || (Bit32(opcode, 15) && Bit32(opcode, 14))) 366 return false; 367 // if registers<15> == '1' && InITBlock() && !LastInITBlock() then UNPREDICTABLE; 368 if (BitIsSet(registers, 15) && InITBlock() && !LastInITBlock()) 369 return false; 370 break; 371 case eEncodingT3: 372 Rt = Bits32(opcode, 15, 12); 373 // if t == 13 || (t == 15 && InITBlock() && !LastInITBlock()) then UNPREDICTABLE; 374 if (Rt == 13) 375 return false; 376 if (Rt == 15 && InITBlock() && !LastInITBlock()) 377 return false; 378 registers = (1u << Rt); 379 break; 380 case eEncodingA1: 381 registers = Bits32(opcode, 15, 0); 382 // Instead of return false, let's handle the following case as well, 383 // which amounts to popping one reg from the full descending stacks. 384 // if BitCount(register_list) < 2 then SEE LDM / LDMIA / LDMFD; 385 386 // if registers<13> == '1' && ArchVersion() >= 7 then UNPREDICTABLE; 387 if (BitIsSet(opcode, 13) && ArchVersion() >= ARMv7) 388 return false; 389 break; 390 case eEncodingA2: 391 Rt = Bits32(opcode, 15, 12); 392 // if t == 13 then UNPREDICTABLE; 393 if (Rt == dwarf_sp) 394 return false; 395 registers = (1u << Rt); 396 break; 397 default: 398 return false; 399 } 400 addr_t sp_offset = addr_byte_size * BitCount (registers); 401 addr_t addr = sp; 402 uint32_t i, data; 403 404 EmulateInstruction::Context context; 405 context.type = EmulateInstruction::eContextPopRegisterOffStack; 406 Register dwarf_reg; 407 dwarf_reg.SetRegister (eRegisterKindDWARF, 0); 408 Register sp_reg; 409 sp_reg.SetRegister (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP); 410 for (i=0; i<15; ++i) 411 { 412 if (BitIsSet (registers, i)) 413 { 414 dwarf_reg.num = dwarf_r0 + i; 415 context.SetRegisterPlusOffset (sp_reg, addr - sp); 416 data = MemARead(context, addr, 4, 0, &success); 417 if (!success) 418 return false; 419 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_reg.num, data)) 420 return false; 421 addr += addr_byte_size; 422 } 423 } 424 425 if (BitIsSet (registers, 15)) 426 { 427 dwarf_reg.num = dwarf_pc; 428 context.SetRegisterPlusOffset (sp_reg, addr - sp); 429 data = MemARead(context, addr, 4, 0, &success); 430 if (!success) 431 return false; 432 // In ARMv5T and above, this is an interworking branch. 433 if (!LoadWritePC(context, data)) 434 return false; 435 addr += addr_byte_size; 436 } 437 438 context.type = EmulateInstruction::eContextAdjustStackPointer; 439 context.SetImmediateSigned (sp_offset); 440 441 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, sp + sp_offset)) 442 return false; 443 } 444 return true; 445} 446 447// Set r7 or ip to point to saved value residing within the stack. 448// ADD (SP plus immediate) 449bool 450EmulateInstructionARM::EmulateADDRdSPImm (const uint32_t opcode, const ARMEncoding encoding) 451{ 452#if 0 453 // ARM pseudo code... 454 if (ConditionPassed()) 455 { 456 EncodingSpecificOperations(); 457 (result, carry, overflow) = AddWithCarry(SP, imm32, '0'); 458 if d == 15 then 459 ALUWritePC(result); // setflags is always FALSE here 460 else 461 R[d] = result; 462 if setflags then 463 APSR.N = result<31>; 464 APSR.Z = IsZeroBit(result); 465 APSR.C = carry; 466 APSR.V = overflow; 467 } 468#endif 469 470 bool success = false; 471 472 if (ConditionPassed(opcode)) 473 { 474 const addr_t sp = ReadCoreReg (SP_REG, &success); 475 if (!success) 476 return false; 477 uint32_t Rd; // the destination register 478 uint32_t imm32; 479 switch (encoding) { 480 case eEncodingT1: 481 Rd = 7; 482 imm32 = Bits32(opcode, 7, 0) << 2; // imm32 = ZeroExtend(imm8:'00', 32) 483 break; 484 case eEncodingA1: 485 Rd = Bits32(opcode, 15, 12); 486 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12) 487 break; 488 default: 489 return false; 490 } 491 addr_t sp_offset = imm32; 492 addr_t addr = sp + sp_offset; // a pointer to the stack area 493 494 EmulateInstruction::Context context; 495 context.type = EmulateInstruction::eContextRegisterPlusOffset; 496 Register sp_reg; 497 sp_reg.SetRegister (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP); 498 context.SetRegisterPlusOffset (sp_reg, sp_offset); 499 500 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + Rd, addr)) 501 return false; 502 } 503 return true; 504} 505 506// Set r7 or ip to the current stack pointer. 507// MOV (register) 508bool 509EmulateInstructionARM::EmulateMOVRdSP (const uint32_t opcode, const ARMEncoding encoding) 510{ 511#if 0 512 // ARM pseudo code... 513 if (ConditionPassed()) 514 { 515 EncodingSpecificOperations(); 516 result = R[m]; 517 if d == 15 then 518 ALUWritePC(result); // setflags is always FALSE here 519 else 520 R[d] = result; 521 if setflags then 522 APSR.N = result<31>; 523 APSR.Z = IsZeroBit(result); 524 // APSR.C unchanged 525 // APSR.V unchanged 526 } 527#endif 528 529 bool success = false; 530 531 if (ConditionPassed(opcode)) 532 { 533 const addr_t sp = ReadCoreReg (SP_REG, &success); 534 if (!success) 535 return false; 536 uint32_t Rd; // the destination register 537 switch (encoding) { 538 case eEncodingT1: 539 Rd = 7; 540 break; 541 case eEncodingA1: 542 Rd = 12; 543 break; 544 default: 545 return false; 546 } 547 548 EmulateInstruction::Context context; 549 context.type = EmulateInstruction::eContextRegisterPlusOffset; 550 Register sp_reg; 551 sp_reg.SetRegister (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP); 552 context.SetRegisterPlusOffset (sp_reg, 0); 553 554 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + Rd, sp)) 555 return false; 556 } 557 return true; 558} 559 560// Move from high register (r8-r15) to low register (r0-r7). 561// MOV (register) 562bool 563EmulateInstructionARM::EmulateMOVLowHigh (const uint32_t opcode, const ARMEncoding encoding) 564{ 565 return EmulateMOVRdRm (opcode, encoding); 566} 567 568// Move from register to register. 569// MOV (register) 570bool 571EmulateInstructionARM::EmulateMOVRdRm (const uint32_t opcode, const ARMEncoding encoding) 572{ 573#if 0 574 // ARM pseudo code... 575 if (ConditionPassed()) 576 { 577 EncodingSpecificOperations(); 578 result = R[m]; 579 if d == 15 then 580 ALUWritePC(result); // setflags is always FALSE here 581 else 582 R[d] = result; 583 if setflags then 584 APSR.N = result<31>; 585 APSR.Z = IsZeroBit(result); 586 // APSR.C unchanged 587 // APSR.V unchanged 588 } 589#endif 590 591 bool success = false; 592 593 if (ConditionPassed(opcode)) 594 { 595 uint32_t Rm; // the source register 596 uint32_t Rd; // the destination register 597 bool setflags; 598 switch (encoding) { 599 case eEncodingT1: 600 Rd = Bit32(opcode, 7) << 3 | Bits32(opcode, 2, 0); 601 Rm = Bits32(opcode, 6, 3); 602 setflags = false; 603 if (Rd == 15 && InITBlock() && !LastInITBlock()) 604 return false; 605 break; 606 case eEncodingT2: 607 Rd = Bits32(opcode, 2, 0); 608 Rm = Bits32(opcode, 5, 3); 609 setflags = true; 610 if (InITBlock()) 611 return false; 612 break; 613 case eEncodingT3: 614 Rd = Bits32(opcode, 11, 8); 615 Rm = Bits32(opcode, 3, 0); 616 setflags = BitIsSet(opcode, 20); 617 // if setflags && (BadReg(d) || BadReg(m)) then UNPREDICTABLE; 618 if (setflags && (BadReg(Rd) || BadReg(Rm))) 619 return false; 620 // if !setflags && (d == 15 || m == 15 || (d == 13 && m == 13)) then UNPREDICTABLE; 621 if (!setflags && (Rd == 15 || Rm == 15 || (Rd == 13 && Rm == 13))) 622 return false; 623 break; 624 case eEncodingA1: 625 Rd = Bits32(opcode, 15, 12); 626 Rm = Bits32(opcode, 3, 0); 627 setflags = BitIsSet(opcode, 20); 628 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions; 629 // TODO: Emulate SUBS PC, LR and related instructions. 630 if (Rd == 15 && setflags) 631 return false; 632 break; 633 default: 634 return false; 635 } 636 uint32_t result = ReadCoreReg(Rm, &success); 637 if (!success) 638 return false; 639 640 // The context specifies that Rm is to be moved into Rd. 641 EmulateInstruction::Context context; 642 context.type = EmulateInstruction::eContextRegisterLoad; 643 Register dwarf_reg; 644 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + Rm); 645 context.SetRegister (dwarf_reg); 646 647 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags)) 648 return false; 649 } 650 return true; 651} 652 653// Move (immediate) writes an immediate value to the destination register. It 654// can optionally update the condition flags based on the value. 655// MOV (immediate) 656bool 657EmulateInstructionARM::EmulateMOVRdImm (const uint32_t opcode, const ARMEncoding encoding) 658{ 659#if 0 660 // ARM pseudo code... 661 if (ConditionPassed()) 662 { 663 EncodingSpecificOperations(); 664 result = imm32; 665 if d == 15 then // Can only occur for ARM encoding 666 ALUWritePC(result); // setflags is always FALSE here 667 else 668 R[d] = result; 669 if setflags then 670 APSR.N = result<31>; 671 APSR.Z = IsZeroBit(result); 672 APSR.C = carry; 673 // APSR.V unchanged 674 } 675#endif 676 677 if (ConditionPassed(opcode)) 678 { 679 uint32_t Rd; // the destination register 680 uint32_t imm32; // the immediate value to be written to Rd 681 uint32_t carry; // the carry bit after ThumbExpandImm_C or ARMExpandImm_C. 682 bool setflags; 683 switch (encoding) { 684 case eEncodingT1: 685 Rd = Bits32(opcode, 10, 8); 686 setflags = !InITBlock(); 687 imm32 = Bits32(opcode, 7, 0); // imm32 = ZeroExtend(imm8, 32) 688 carry = APSR_C; 689 690 break; 691 692 case eEncodingT2: 693 Rd = Bits32(opcode, 11, 8); 694 setflags = BitIsSet(opcode, 20); 695 imm32 = ThumbExpandImm_C(opcode, APSR_C, carry); 696 if (BadReg(Rd)) 697 return false; 698 699 break; 700 701 case eEncodingT3: 702 { 703 // d = UInt(Rd); setflags = FALSE; imm32 = ZeroExtend(imm4:i:imm3:imm8, 32); 704 Rd = Bits32 (opcode, 11, 8); 705 setflags = false; 706 uint32_t imm4 = Bits32 (opcode, 19, 16); 707 uint32_t imm3 = Bits32 (opcode, 14, 12); 708 uint32_t i = Bit32 (opcode, 26); 709 uint32_t imm8 = Bits32 (opcode, 7, 0); 710 imm32 = (imm4 << 12) | (i << 11) | (imm3 << 8) | imm8; 711 712 // if BadReg(d) then UNPREDICTABLE; 713 if (BadReg (Rd)) 714 return false; 715 } 716 break; 717 718 case eEncodingA1: 719 // if Rd == ‘1111’ && S == ‘1’ then SEE SUBS PC, LR and related instructions; 720 // d = UInt(Rd); setflags = (S == ‘1’); (imm32, carry) = ARMExpandImm_C(imm12, APSR.C); 721 Rd = Bits32 (opcode, 15, 12); 722 setflags = BitIsSet (opcode, 20); 723 imm32 = ARMExpandImm_C (opcode, APSR_C, carry); 724 725 break; 726 727 case eEncodingA2: 728 { 729 // d = UInt(Rd); setflags = FALSE; imm32 = ZeroExtend(imm4:imm12, 32); 730 Rd = Bits32 (opcode, 15, 12); 731 setflags = false; 732 uint32_t imm4 = Bits32 (opcode, 19, 16); 733 uint32_t imm12 = Bits32 (opcode, 11, 0); 734 imm32 = (imm4 << 12) | imm12; 735 736 // if d == 15 then UNPREDICTABLE; 737 if (Rd == 15) 738 return false; 739 } 740 break; 741 742 default: 743 return false; 744 } 745 uint32_t result = imm32; 746 747 // The context specifies that an immediate is to be moved into Rd. 748 EmulateInstruction::Context context; 749 context.type = EmulateInstruction::eContextImmediate; 750 context.SetNoArgs (); 751 752 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry)) 753 return false; 754 } 755 return true; 756} 757 758// MUL multiplies two register values. The least significant 32 bits of the result are written to the destination 759// register. These 32 bits do not depend on whether the source register values are considered to be signed values or 760// unsigned values. 761// 762// Optionally, it can update the condition flags based on the result. In the Thumb instruction set, this option is 763// limited to only a few forms of the instruction. 764bool 765EmulateInstructionARM::EmulateMUL (const uint32_t opcode, const ARMEncoding encoding) 766{ 767#if 0 768 if ConditionPassed() then 769 EncodingSpecificOperations(); 770 operand1 = SInt(R[n]); // operand1 = UInt(R[n]) produces the same final results 771 operand2 = SInt(R[m]); // operand2 = UInt(R[m]) produces the same final results 772 result = operand1 * operand2; 773 R[d] = result<31:0>; 774 if setflags then 775 APSR.N = result<31>; 776 APSR.Z = IsZeroBit(result); 777 if ArchVersion() == 4 then 778 APSR.C = bit UNKNOWN; 779 // else APSR.C unchanged 780 // APSR.V always unchanged 781#endif 782 783 if (ConditionPassed(opcode)) 784 { 785 uint32_t d; 786 uint32_t n; 787 uint32_t m; 788 bool setflags; 789 790 // EncodingSpecificOperations(); 791 switch (encoding) 792 { 793 case eEncodingT1: 794 // d = UInt(Rdm); n = UInt(Rn); m = UInt(Rdm); setflags = !InITBlock(); 795 d = Bits32 (opcode, 2, 0); 796 n = Bits32 (opcode, 5, 3); 797 m = Bits32 (opcode, 2, 0); 798 setflags = !InITBlock(); 799 800 // if ArchVersion() < 6 && d == n then UNPREDICTABLE; 801 if ((ArchVersion() < ARMv6) && (d == n)) 802 return false; 803 804 break; 805 806 case eEncodingT2: 807 // d = UInt(Rd); n = UInt(Rn); m = UInt(Rm); setflags = FALSE; 808 d = Bits32 (opcode, 11, 8); 809 n = Bits32 (opcode, 19, 16); 810 m = Bits32 (opcode, 3, 0); 811 setflags = false; 812 813 // if BadReg(d) || BadReg(n) || BadReg(m) then UNPREDICTABLE; 814 if (BadReg (d) || BadReg (n) || BadReg (m)) 815 return false; 816 817 break; 818 819 case eEncodingA1: 820 // d = UInt(Rd); n = UInt(Rn); m = UInt(Rm); setflags = (S == '1'); 821 d = Bits32 (opcode, 19, 16); 822 n = Bits32 (opcode, 3, 0); 823 m = Bits32 (opcode, 11, 8); 824 setflags = BitIsSet (opcode, 20); 825 826 // if d == 15 || n == 15 || m == 15 then UNPREDICTABLE; 827 if ((d == 15) || (n == 15) || (m == 15)) 828 return false; 829 830 // if ArchVersion() < 6 && d == n then UNPREDICTABLE; 831 if ((ArchVersion() < ARMv6) && (d == n)) 832 return false; 833 834 break; 835 836 default: 837 return false; 838 } 839 840 bool success = false; 841 842 // operand1 = SInt(R[n]); // operand1 = UInt(R[n]) produces the same final results 843 uint64_t operand1 = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success); 844 if (!success) 845 return false; 846 847 // operand2 = SInt(R[m]); // operand2 = UInt(R[m]) produces the same final results 848 uint64_t operand2 = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success); 849 if (!success) 850 return false; 851 852 // result = operand1 * operand2; 853 uint64_t result = operand1 * operand2; 854 855 // R[d] = result<31:0>; 856 Register op1_reg; 857 Register op2_reg; 858 op1_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n); 859 op2_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + m); 860 861 EmulateInstruction::Context context; 862 context.type = eContextMultiplication; 863 context.SetRegisterRegisterOperands (op1_reg, op2_reg); 864 865 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + d, (0x0000ffff & result))) 866 return false; 867 868 // if setflags then 869 if (setflags) 870 { 871 // APSR.N = result<31>; 872 // APSR.Z = IsZeroBit(result); 873 m_new_inst_cpsr = m_opcode_cpsr; 874 SetBit32 (m_new_inst_cpsr, CPSR_N_POS, Bit32 (result, 31)); 875 SetBit32 (m_new_inst_cpsr, CPSR_Z_POS, result == 0 ? 1 : 0); 876 if (m_new_inst_cpsr != m_opcode_cpsr) 877 { 878 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS, m_new_inst_cpsr)) 879 return false; 880 } 881 882 // if ArchVersion() == 4 then 883 // APSR.C = bit UNKNOWN; 884 } 885 } 886 return true; 887} 888 889// Bitwise NOT (immediate) writes the bitwise inverse of an immediate value to the destination register. 890// It can optionally update the condition flags based on the value. 891bool 892EmulateInstructionARM::EmulateMVNImm (const uint32_t opcode, const ARMEncoding encoding) 893{ 894#if 0 895 // ARM pseudo code... 896 if (ConditionPassed()) 897 { 898 EncodingSpecificOperations(); 899 result = NOT(imm32); 900 if d == 15 then // Can only occur for ARM encoding 901 ALUWritePC(result); // setflags is always FALSE here 902 else 903 R[d] = result; 904 if setflags then 905 APSR.N = result<31>; 906 APSR.Z = IsZeroBit(result); 907 APSR.C = carry; 908 // APSR.V unchanged 909 } 910#endif 911 912 if (ConditionPassed(opcode)) 913 { 914 uint32_t Rd; // the destination register 915 uint32_t imm32; // the output after ThumbExpandImm_C or ARMExpandImm_C 916 uint32_t carry; // the carry bit after ThumbExpandImm_C or ARMExpandImm_C 917 bool setflags; 918 switch (encoding) { 919 case eEncodingT1: 920 Rd = Bits32(opcode, 11, 8); 921 setflags = BitIsSet(opcode, 20); 922 imm32 = ThumbExpandImm_C(opcode, APSR_C, carry); 923 break; 924 case eEncodingA1: 925 Rd = Bits32(opcode, 15, 12); 926 setflags = BitIsSet(opcode, 20); 927 imm32 = ARMExpandImm_C(opcode, APSR_C, carry); 928 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions; 929 // TODO: Emulate SUBS PC, LR and related instructions. 930 if (Rd == 15 && setflags) 931 return false; 932 break; 933 default: 934 return false; 935 } 936 uint32_t result = ~imm32; 937 938 // The context specifies that an immediate is to be moved into Rd. 939 EmulateInstruction::Context context; 940 context.type = EmulateInstruction::eContextImmediate; 941 context.SetNoArgs (); 942 943 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry)) 944 return false; 945 } 946 return true; 947} 948 949// Bitwise NOT (register) writes the bitwise inverse of a register value to the destination register. 950// It can optionally update the condition flags based on the result. 951bool 952EmulateInstructionARM::EmulateMVNReg (const uint32_t opcode, const ARMEncoding encoding) 953{ 954#if 0 955 // ARM pseudo code... 956 if (ConditionPassed()) 957 { 958 EncodingSpecificOperations(); 959 (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C); 960 result = NOT(shifted); 961 if d == 15 then // Can only occur for ARM encoding 962 ALUWritePC(result); // setflags is always FALSE here 963 else 964 R[d] = result; 965 if setflags then 966 APSR.N = result<31>; 967 APSR.Z = IsZeroBit(result); 968 APSR.C = carry; 969 // APSR.V unchanged 970 } 971#endif 972 973 if (ConditionPassed(opcode)) 974 { 975 uint32_t Rm; // the source register 976 uint32_t Rd; // the destination register 977 ARM_ShifterType shift_t; 978 uint32_t shift_n; // the shift applied to the value read from Rm 979 bool setflags; 980 uint32_t carry; // the carry bit after the shift operation 981 switch (encoding) { 982 case eEncodingT1: 983 Rd = Bits32(opcode, 2, 0); 984 Rm = Bits32(opcode, 5, 3); 985 setflags = !InITBlock(); 986 shift_t = SRType_LSL; 987 shift_n = 0; 988 if (InITBlock()) 989 return false; 990 break; 991 case eEncodingT2: 992 Rd = Bits32(opcode, 11, 8); 993 Rm = Bits32(opcode, 3, 0); 994 setflags = BitIsSet(opcode, 20); 995 shift_n = DecodeImmShiftThumb(opcode, shift_t); 996 // if (BadReg(d) || BadReg(m)) then UNPREDICTABLE; 997 if (BadReg(Rd) || BadReg(Rm)) 998 return false; 999 break; 1000 case eEncodingA1: 1001 Rd = Bits32(opcode, 15, 12); 1002 Rm = Bits32(opcode, 3, 0); 1003 setflags = BitIsSet(opcode, 20); 1004 shift_n = DecodeImmShiftARM(opcode, shift_t); 1005 break; 1006 default: 1007 return false; 1008 } 1009 bool success = false; 1010 uint32_t value = ReadCoreReg(Rm, &success); 1011 if (!success) 1012 return false; 1013 1014 uint32_t shifted = Shift_C(value, shift_t, shift_n, APSR_C, carry); 1015 uint32_t result = ~shifted; 1016 1017 // The context specifies that an immediate is to be moved into Rd. 1018 EmulateInstruction::Context context; 1019 context.type = EmulateInstruction::eContextImmediate; 1020 context.SetNoArgs (); 1021 1022 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry)) 1023 return false; 1024 } 1025 return true; 1026} 1027 1028// PC relative immediate load into register, possibly followed by ADD (SP plus register). 1029// LDR (literal) 1030bool 1031EmulateInstructionARM::EmulateLDRRtPCRelative (const uint32_t opcode, const ARMEncoding encoding) 1032{ 1033#if 0 1034 // ARM pseudo code... 1035 if (ConditionPassed()) 1036 { 1037 EncodingSpecificOperations(); NullCheckIfThumbEE(15); 1038 base = Align(PC,4); 1039 address = if add then (base + imm32) else (base - imm32); 1040 data = MemU[address,4]; 1041 if t == 15 then 1042 if address<1:0> == '00' then LoadWritePC(data); else UNPREDICTABLE; 1043 elsif UnalignedSupport() || address<1:0> = '00' then 1044 R[t] = data; 1045 else // Can only apply before ARMv7 1046 if CurrentInstrSet() == InstrSet_ARM then 1047 R[t] = ROR(data, 8*UInt(address<1:0>)); 1048 else 1049 R[t] = bits(32) UNKNOWN; 1050 } 1051#endif 1052 1053 if (ConditionPassed(opcode)) 1054 { 1055 bool success = false; 1056 const uint32_t pc = ReadCoreReg(PC_REG, &success); 1057 if (!success) 1058 return false; 1059 1060 // PC relative immediate load context 1061 EmulateInstruction::Context context; 1062 context.type = EmulateInstruction::eContextRegisterPlusOffset; 1063 Register pc_reg; 1064 pc_reg.SetRegister (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC); 1065 context.SetRegisterPlusOffset (pc_reg, 0); 1066 1067 uint32_t Rt; // the destination register 1068 uint32_t imm32; // immediate offset from the PC 1069 bool add; // +imm32 or -imm32? 1070 addr_t base; // the base address 1071 addr_t address; // the PC relative address 1072 uint32_t data; // the literal data value from the PC relative load 1073 switch (encoding) { 1074 case eEncodingT1: 1075 Rt = Bits32(opcode, 10, 8); 1076 imm32 = Bits32(opcode, 7, 0) << 2; // imm32 = ZeroExtend(imm8:'00', 32); 1077 add = true; 1078 break; 1079 case eEncodingT2: 1080 Rt = Bits32(opcode, 15, 12); 1081 imm32 = Bits32(opcode, 11, 0) << 2; // imm32 = ZeroExtend(imm12, 32); 1082 add = BitIsSet(opcode, 23); 1083 if (Rt == 15 && InITBlock() && !LastInITBlock()) 1084 return false; 1085 break; 1086 default: 1087 return false; 1088 } 1089 1090 base = Align(pc, 4); 1091 if (add) 1092 address = base + imm32; 1093 else 1094 address = base - imm32; 1095 1096 context.SetRegisterPlusOffset(pc_reg, address - base); 1097 data = MemURead(context, address, 4, 0, &success); 1098 if (!success) 1099 return false; 1100 1101 if (Rt == 15) 1102 { 1103 if (Bits32(address, 1, 0) == 0) 1104 { 1105 // In ARMv5T and above, this is an interworking branch. 1106 if (!LoadWritePC(context, data)) 1107 return false; 1108 } 1109 else 1110 return false; 1111 } 1112 else if (UnalignedSupport() || Bits32(address, 1, 0) == 0) 1113 { 1114 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + Rt, data)) 1115 return false; 1116 } 1117 else // We don't handle ARM for now. 1118 return false; 1119 1120 } 1121 return true; 1122} 1123 1124// An add operation to adjust the SP. 1125// ADD (SP plus immediate) 1126bool 1127EmulateInstructionARM::EmulateADDSPImm (const uint32_t opcode, const ARMEncoding encoding) 1128{ 1129#if 0 1130 // ARM pseudo code... 1131 if (ConditionPassed()) 1132 { 1133 EncodingSpecificOperations(); 1134 (result, carry, overflow) = AddWithCarry(SP, imm32, '0'); 1135 if d == 15 then // Can only occur for ARM encoding 1136 ALUWritePC(result); // setflags is always FALSE here 1137 else 1138 R[d] = result; 1139 if setflags then 1140 APSR.N = result<31>; 1141 APSR.Z = IsZeroBit(result); 1142 APSR.C = carry; 1143 APSR.V = overflow; 1144 } 1145#endif 1146 1147 bool success = false; 1148 1149 if (ConditionPassed(opcode)) 1150 { 1151 const addr_t sp = ReadCoreReg (SP_REG, &success); 1152 if (!success) 1153 return false; 1154 uint32_t imm32; // the immediate operand 1155 uint32_t d; 1156 bool setflags; 1157 switch (encoding) 1158 { 1159 case eEncodingT1: 1160 // d = UInt(Rd); setflags = FALSE; imm32 = ZeroExtend(imm8:'00', 32); 1161 d = Bits32 (opcode, 10, 8); 1162 setflags = false; 1163 imm32 = (Bits32 (opcode, 7, 0) << 2); 1164 1165 break; 1166 1167 case eEncodingT2: 1168 // d = 13; setflags = FALSE; imm32 = ZeroExtend(imm7:'00', 32); 1169 d = 13; 1170 setflags = false; 1171 imm32 = ThumbImm7Scaled(opcode); // imm32 = ZeroExtend(imm7:'00', 32) 1172 1173 break; 1174 1175 default: 1176 return false; 1177 } 1178 addr_t sp_offset = imm32; 1179 addr_t addr = sp + sp_offset; // the adjusted stack pointer value 1180 1181 EmulateInstruction::Context context; 1182 context.type = EmulateInstruction::eContextAdjustStackPointer; 1183 context.SetImmediateSigned (sp_offset); 1184 1185 if (d == 15) 1186 { 1187 if (!ALUWritePC (context, addr)) 1188 return false; 1189 } 1190 else 1191 { 1192 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + d, addr)) 1193 return false; 1194 } 1195 } 1196 return true; 1197} 1198 1199// An add operation to adjust the SP. 1200// ADD (SP plus register) 1201bool 1202EmulateInstructionARM::EmulateADDSPRm (const uint32_t opcode, const ARMEncoding encoding) 1203{ 1204#if 0 1205 // ARM pseudo code... 1206 if (ConditionPassed()) 1207 { 1208 EncodingSpecificOperations(); 1209 shifted = Shift(R[m], shift_t, shift_n, APSR.C); 1210 (result, carry, overflow) = AddWithCarry(SP, shifted, '0'); 1211 if d == 15 then 1212 ALUWritePC(result); // setflags is always FALSE here 1213 else 1214 R[d] = result; 1215 if setflags then 1216 APSR.N = result<31>; 1217 APSR.Z = IsZeroBit(result); 1218 APSR.C = carry; 1219 APSR.V = overflow; 1220 } 1221#endif 1222 1223 bool success = false; 1224 1225 if (ConditionPassed(opcode)) 1226 { 1227 const addr_t sp = ReadCoreReg (SP_REG, &success); 1228 if (!success) 1229 return false; 1230 uint32_t Rm; // the second operand 1231 switch (encoding) { 1232 case eEncodingT2: 1233 Rm = Bits32(opcode, 6, 3); 1234 break; 1235 default: 1236 return false; 1237 } 1238 int32_t reg_value = ReadCoreReg(Rm, &success); 1239 if (!success) 1240 return false; 1241 1242 addr_t addr = (int32_t)sp + reg_value; // the adjusted stack pointer value 1243 1244 EmulateInstruction::Context context; 1245 context.type = EmulateInstruction::eContextAdjustStackPointer; 1246 context.SetImmediateSigned (reg_value); 1247 1248 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, addr)) 1249 return false; 1250 } 1251 return true; 1252} 1253 1254// Branch with Link and Exchange Instruction Sets (immediate) calls a subroutine 1255// at a PC-relative address, and changes instruction set from ARM to Thumb, or 1256// from Thumb to ARM. 1257// BLX (immediate) 1258bool 1259EmulateInstructionARM::EmulateBLXImmediate (const uint32_t opcode, const ARMEncoding encoding) 1260{ 1261#if 0 1262 // ARM pseudo code... 1263 if (ConditionPassed()) 1264 { 1265 EncodingSpecificOperations(); 1266 if CurrentInstrSet() == InstrSet_ARM then 1267 LR = PC - 4; 1268 else 1269 LR = PC<31:1> : '1'; 1270 if targetInstrSet == InstrSet_ARM then 1271 targetAddress = Align(PC,4) + imm32; 1272 else 1273 targetAddress = PC + imm32; 1274 SelectInstrSet(targetInstrSet); 1275 BranchWritePC(targetAddress); 1276 } 1277#endif 1278 1279 bool success = true; 1280 1281 if (ConditionPassed(opcode)) 1282 { 1283 EmulateInstruction::Context context; 1284 context.type = EmulateInstruction::eContextRelativeBranchImmediate; 1285 const uint32_t pc = ReadCoreReg(PC_REG, &success); 1286 if (!success) 1287 return false; 1288 addr_t lr; // next instruction address 1289 addr_t target; // target address 1290 int32_t imm32; // PC-relative offset 1291 switch (encoding) { 1292 case eEncodingT1: 1293 { 1294 lr = pc | 1u; // return address 1295 uint32_t S = Bit32(opcode, 26); 1296 uint32_t imm10 = Bits32(opcode, 25, 16); 1297 uint32_t J1 = Bit32(opcode, 13); 1298 uint32_t J2 = Bit32(opcode, 11); 1299 uint32_t imm11 = Bits32(opcode, 10, 0); 1300 uint32_t I1 = !(J1 ^ S); 1301 uint32_t I2 = !(J2 ^ S); 1302 uint32_t imm25 = (S << 24) | (I1 << 23) | (I2 << 22) | (imm10 << 12) | (imm11 << 1); 1303 imm32 = llvm::SignExtend32<25>(imm25); 1304 target = pc + imm32; 1305 context.SetModeAndImmediateSigned (eModeThumb, 4 + imm32); 1306 if (InITBlock() && !LastInITBlock()) 1307 return false; 1308 break; 1309 } 1310 case eEncodingT2: 1311 { 1312 lr = pc | 1u; // return address 1313 uint32_t S = Bit32(opcode, 26); 1314 uint32_t imm10H = Bits32(opcode, 25, 16); 1315 uint32_t J1 = Bit32(opcode, 13); 1316 uint32_t J2 = Bit32(opcode, 11); 1317 uint32_t imm10L = Bits32(opcode, 10, 1); 1318 uint32_t I1 = !(J1 ^ S); 1319 uint32_t I2 = !(J2 ^ S); 1320 uint32_t imm25 = (S << 24) | (I1 << 23) | (I2 << 22) | (imm10H << 12) | (imm10L << 2); 1321 imm32 = llvm::SignExtend32<25>(imm25); 1322 target = Align(pc, 4) + imm32; 1323 context.SetModeAndImmediateSigned (eModeARM, 4 + imm32); 1324 if (InITBlock() && !LastInITBlock()) 1325 return false; 1326 break; 1327 } 1328 case eEncodingA1: 1329 lr = pc - 4; // return address 1330 imm32 = llvm::SignExtend32<26>(Bits32(opcode, 23, 0) << 2); 1331 target = Align(pc, 4) + imm32; 1332 context.SetModeAndImmediateSigned (eModeARM, 8 + imm32); 1333 break; 1334 case eEncodingA2: 1335 lr = pc - 4; // return address 1336 imm32 = llvm::SignExtend32<26>(Bits32(opcode, 23, 0) << 2 | Bits32(opcode, 24, 24) << 1); 1337 target = pc + imm32; 1338 context.SetModeAndImmediateSigned (eModeThumb, 8 + imm32); 1339 break; 1340 default: 1341 return false; 1342 } 1343 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_RA, lr)) 1344 return false; 1345 if (!BranchWritePC(context, target)) 1346 return false; 1347 } 1348 return true; 1349} 1350 1351// Branch with Link and Exchange (register) calls a subroutine at an address and 1352// instruction set specified by a register. 1353// BLX (register) 1354bool 1355EmulateInstructionARM::EmulateBLXRm (const uint32_t opcode, const ARMEncoding encoding) 1356{ 1357#if 0 1358 // ARM pseudo code... 1359 if (ConditionPassed()) 1360 { 1361 EncodingSpecificOperations(); 1362 target = R[m]; 1363 if CurrentInstrSet() == InstrSet_ARM then 1364 next_instr_addr = PC - 4; 1365 LR = next_instr_addr; 1366 else 1367 next_instr_addr = PC - 2; 1368 LR = next_instr_addr<31:1> : '1'; 1369 BXWritePC(target); 1370 } 1371#endif 1372 1373 bool success = false; 1374 1375 if (ConditionPassed(opcode)) 1376 { 1377 EmulateInstruction::Context context; 1378 context.type = EmulateInstruction::eContextAbsoluteBranchRegister; 1379 const uint32_t pc = ReadCoreReg(PC_REG, &success); 1380 addr_t lr; // next instruction address 1381 if (!success) 1382 return false; 1383 uint32_t Rm; // the register with the target address 1384 switch (encoding) { 1385 case eEncodingT1: 1386 lr = (pc - 2) | 1u; // return address 1387 Rm = Bits32(opcode, 6, 3); 1388 // if m == 15 then UNPREDICTABLE; 1389 if (Rm == 15) 1390 return false; 1391 if (InITBlock() && !LastInITBlock()) 1392 return false; 1393 break; 1394 case eEncodingA1: 1395 lr = pc - 4; // return address 1396 Rm = Bits32(opcode, 3, 0); 1397 // if m == 15 then UNPREDICTABLE; 1398 if (Rm == 15) 1399 return false; 1400 break; 1401 default: 1402 return false; 1403 } 1404 addr_t target = ReadCoreReg (Rm, &success); 1405 if (!success) 1406 return false; 1407 Register dwarf_reg; 1408 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + Rm); 1409 context.SetRegister (dwarf_reg); 1410 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_RA, lr)) 1411 return false; 1412 if (!BXWritePC(context, target)) 1413 return false; 1414 } 1415 return true; 1416} 1417 1418// Branch and Exchange causes a branch to an address and instruction set specified by a register. 1419bool 1420EmulateInstructionARM::EmulateBXRm (const uint32_t opcode, const ARMEncoding encoding) 1421{ 1422#if 0 1423 // ARM pseudo code... 1424 if (ConditionPassed()) 1425 { 1426 EncodingSpecificOperations(); 1427 BXWritePC(R[m]); 1428 } 1429#endif 1430 1431 if (ConditionPassed(opcode)) 1432 { 1433 EmulateInstruction::Context context; 1434 context.type = EmulateInstruction::eContextAbsoluteBranchRegister; 1435 uint32_t Rm; // the register with the target address 1436 switch (encoding) { 1437 case eEncodingT1: 1438 Rm = Bits32(opcode, 6, 3); 1439 if (InITBlock() && !LastInITBlock()) 1440 return false; 1441 break; 1442 case eEncodingA1: 1443 Rm = Bits32(opcode, 3, 0); 1444 break; 1445 default: 1446 return false; 1447 } 1448 bool success = false; 1449 addr_t target = ReadCoreReg (Rm, &success); 1450 if (!success) 1451 return false; 1452 1453 Register dwarf_reg; 1454 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + Rm); 1455 context.SetRegister (dwarf_reg); 1456 if (!BXWritePC(context, target)) 1457 return false; 1458 } 1459 return true; 1460} 1461 1462// Branch and Exchange Jazelle attempts to change to Jazelle state. If the attempt fails, it branches to an 1463// address and instruction set specified by a register as though it were a BX instruction. 1464// 1465// TODO: Emulate Jazelle architecture? 1466// We currently assume that switching to Jazelle state fails, thus treating BXJ as a BX operation. 1467bool 1468EmulateInstructionARM::EmulateBXJRm (const uint32_t opcode, const ARMEncoding encoding) 1469{ 1470#if 0 1471 // ARM pseudo code... 1472 if (ConditionPassed()) 1473 { 1474 EncodingSpecificOperations(); 1475 if JMCR.JE == '0' || CurrentInstrSet() == InstrSet_ThumbEE then 1476 BXWritePC(R[m]); 1477 else 1478 if JazelleAcceptsExecution() then 1479 SwitchToJazelleExecution(); 1480 else 1481 SUBARCHITECTURE_DEFINED handler call; 1482 } 1483#endif 1484 1485 if (ConditionPassed(opcode)) 1486 { 1487 EmulateInstruction::Context context; 1488 context.type = EmulateInstruction::eContextAbsoluteBranchRegister; 1489 uint32_t Rm; // the register with the target address 1490 switch (encoding) { 1491 case eEncodingT1: 1492 Rm = Bits32(opcode, 19, 16); 1493 if (BadReg(Rm)) 1494 return false; 1495 if (InITBlock() && !LastInITBlock()) 1496 return false; 1497 break; 1498 case eEncodingA1: 1499 Rm = Bits32(opcode, 3, 0); 1500 if (Rm == 15) 1501 return false; 1502 break; 1503 default: 1504 return false; 1505 } 1506 bool success = false; 1507 addr_t target = ReadCoreReg (Rm, &success); 1508 if (!success) 1509 return false; 1510 1511 Register dwarf_reg; 1512 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + Rm); 1513 context.SetRegister (dwarf_reg); 1514 if (!BXWritePC(context, target)) 1515 return false; 1516 } 1517 return true; 1518} 1519 1520// Set r7 to point to some ip offset. 1521// SUB (immediate) 1522bool 1523EmulateInstructionARM::EmulateSUBR7IPImm (const uint32_t opcode, const ARMEncoding encoding) 1524{ 1525#if 0 1526 // ARM pseudo code... 1527 if (ConditionPassed()) 1528 { 1529 EncodingSpecificOperations(); 1530 (result, carry, overflow) = AddWithCarry(SP, NOT(imm32), '1'); 1531 if d == 15 then // Can only occur for ARM encoding 1532 ALUWritePC(result); // setflags is always FALSE here 1533 else 1534 R[d] = result; 1535 if setflags then 1536 APSR.N = result<31>; 1537 APSR.Z = IsZeroBit(result); 1538 APSR.C = carry; 1539 APSR.V = overflow; 1540 } 1541#endif 1542 1543 if (ConditionPassed(opcode)) 1544 { 1545 bool success = false; 1546 const addr_t ip = ReadCoreReg (12, &success); 1547 if (!success) 1548 return false; 1549 uint32_t imm32; 1550 switch (encoding) { 1551 case eEncodingA1: 1552 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12) 1553 break; 1554 default: 1555 return false; 1556 } 1557 addr_t ip_offset = imm32; 1558 addr_t addr = ip - ip_offset; // the adjusted ip value 1559 1560 EmulateInstruction::Context context; 1561 context.type = EmulateInstruction::eContextRegisterPlusOffset; 1562 Register dwarf_reg; 1563 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r12); 1564 context.SetRegisterPlusOffset (dwarf_reg, -ip_offset); 1565 1566 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r7, addr)) 1567 return false; 1568 } 1569 return true; 1570} 1571 1572// Set ip to point to some stack offset. 1573// SUB (SP minus immediate) 1574bool 1575EmulateInstructionARM::EmulateSUBIPSPImm (const uint32_t opcode, const ARMEncoding encoding) 1576{ 1577#if 0 1578 // ARM pseudo code... 1579 if (ConditionPassed()) 1580 { 1581 EncodingSpecificOperations(); 1582 (result, carry, overflow) = AddWithCarry(SP, NOT(imm32), '1'); 1583 if d == 15 then // Can only occur for ARM encoding 1584 ALUWritePC(result); // setflags is always FALSE here 1585 else 1586 R[d] = result; 1587 if setflags then 1588 APSR.N = result<31>; 1589 APSR.Z = IsZeroBit(result); 1590 APSR.C = carry; 1591 APSR.V = overflow; 1592 } 1593#endif 1594 1595 if (ConditionPassed(opcode)) 1596 { 1597 bool success = false; 1598 const addr_t sp = ReadCoreReg (SP_REG, &success); 1599 if (!success) 1600 return false; 1601 uint32_t imm32; 1602 switch (encoding) { 1603 case eEncodingA1: 1604 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12) 1605 break; 1606 default: 1607 return false; 1608 } 1609 addr_t sp_offset = imm32; 1610 addr_t addr = sp - sp_offset; // the adjusted stack pointer value 1611 1612 EmulateInstruction::Context context; 1613 context.type = EmulateInstruction::eContextRegisterPlusOffset; 1614 Register dwarf_reg; 1615 dwarf_reg.SetRegister (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP); 1616 context.SetRegisterPlusOffset (dwarf_reg, -sp_offset); 1617 1618 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r12, addr)) 1619 return false; 1620 } 1621 return true; 1622} 1623 1624// This instruction subtracts an immediate value from the SP value, and writes 1625// the result to the destination register. 1626// 1627// If Rd == 13 => A sub operation to adjust the SP -- allocate space for local storage. 1628bool 1629EmulateInstructionARM::EmulateSUBSPImm (const uint32_t opcode, const ARMEncoding encoding) 1630{ 1631#if 0 1632 // ARM pseudo code... 1633 if (ConditionPassed()) 1634 { 1635 EncodingSpecificOperations(); 1636 (result, carry, overflow) = AddWithCarry(SP, NOT(imm32), '1'); 1637 if d == 15 then // Can only occur for ARM encoding 1638 ALUWritePC(result); // setflags is always FALSE here 1639 else 1640 R[d] = result; 1641 if setflags then 1642 APSR.N = result<31>; 1643 APSR.Z = IsZeroBit(result); 1644 APSR.C = carry; 1645 APSR.V = overflow; 1646 } 1647#endif 1648 1649 bool success = false; 1650 if (ConditionPassed(opcode)) 1651 { 1652 const addr_t sp = ReadCoreReg (SP_REG, &success); 1653 if (!success) 1654 return false; 1655 1656 uint32_t Rd; 1657 bool setflags; 1658 uint32_t imm32; 1659 switch (encoding) { 1660 case eEncodingT1: 1661 Rd = 13; 1662 setflags = false; 1663 imm32 = ThumbImm7Scaled(opcode); // imm32 = ZeroExtend(imm7:'00', 32) 1664 break; 1665 case eEncodingT2: 1666 Rd = Bits32(opcode, 11, 8); 1667 setflags = BitIsSet(opcode, 20); 1668 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8) 1669 if (Rd == 15 && setflags) 1670 return EmulateCMPImm(opcode, eEncodingT2); 1671 if (Rd == 15 && !setflags) 1672 return false; 1673 break; 1674 case eEncodingT3: 1675 Rd = Bits32(opcode, 11, 8); 1676 setflags = false; 1677 imm32 = ThumbImm12(opcode); // imm32 = ZeroExtend(i:imm3:imm8, 32) 1678 if (Rd == 15) 1679 return false; 1680 break; 1681 case eEncodingA1: 1682 Rd = Bits32(opcode, 15, 12); 1683 setflags = BitIsSet(opcode, 20); 1684 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12) 1685 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions; 1686 // TODO: Emulate SUBS PC, LR and related instructions. 1687 if (Rd == 15 && setflags) 1688 return false; 1689 break; 1690 default: 1691 return false; 1692 } 1693 AddWithCarryResult res = AddWithCarry(sp, ~imm32, 1); 1694 1695 EmulateInstruction::Context context; 1696 if (Rd == 13) 1697 { 1698 uint64_t imm64 = imm32; // Need to expand it to 64 bits before attempting to negate it, or the wrong 1699 // value gets passed down to context.SetImmediateSigned. 1700 context.type = EmulateInstruction::eContextAdjustStackPointer; 1701 context.SetImmediateSigned (-imm64); // the stack pointer offset 1702 } 1703 else 1704 { 1705 context.type = EmulateInstruction::eContextImmediate; 1706 context.SetNoArgs (); 1707 } 1708 1709 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow)) 1710 return false; 1711 } 1712 return true; 1713} 1714 1715// A store operation to the stack that also updates the SP. 1716bool 1717EmulateInstructionARM::EmulateSTRRtSP (const uint32_t opcode, const ARMEncoding encoding) 1718{ 1719#if 0 1720 // ARM pseudo code... 1721 if (ConditionPassed()) 1722 { 1723 EncodingSpecificOperations(); 1724 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32); 1725 address = if index then offset_addr else R[n]; 1726 MemU[address,4] = if t == 15 then PCStoreValue() else R[t]; 1727 if wback then R[n] = offset_addr; 1728 } 1729#endif 1730 1731 bool success = false; 1732 1733 if (ConditionPassed(opcode)) 1734 { 1735 const uint32_t addr_byte_size = GetAddressByteSize(); 1736 const addr_t sp = ReadCoreReg (SP_REG, &success); 1737 if (!success) 1738 return false; 1739 uint32_t Rt; // the source register 1740 uint32_t imm12; 1741 uint32_t Rn; // This function assumes Rn is the SP, but we should verify that. 1742 1743 bool index; 1744 bool add; 1745 bool wback; 1746 switch (encoding) { 1747 case eEncodingA1: 1748 Rt = Bits32(opcode, 15, 12); 1749 imm12 = Bits32(opcode, 11, 0); 1750 Rn = Bits32 (opcode, 19, 16); 1751 1752 if (Rn != 13) // 13 is the SP reg on ARM. Verify that Rn == SP. 1753 return false; 1754 1755 index = BitIsSet (opcode, 24); 1756 add = BitIsSet (opcode, 23); 1757 wback = (BitIsClear (opcode, 24) || BitIsSet (opcode, 21)); 1758 1759 if (wback && ((Rn == 15) || (Rn == Rt))) 1760 return false; 1761 break; 1762 default: 1763 return false; 1764 } 1765 addr_t offset_addr; 1766 if (add) 1767 offset_addr = sp + imm12; 1768 else 1769 offset_addr = sp - imm12; 1770 1771 addr_t addr; 1772 if (index) 1773 addr = offset_addr; 1774 else 1775 addr = sp; 1776 1777 EmulateInstruction::Context context; 1778 context.type = EmulateInstruction::eContextPushRegisterOnStack; 1779 Register sp_reg; 1780 sp_reg.SetRegister (eRegisterKindDWARF, dwarf_sp); 1781 context.SetRegisterPlusOffset (sp_reg, addr - sp); 1782 if (Rt != 15) 1783 { 1784 uint32_t reg_value = ReadCoreReg(Rt, &success); 1785 if (!success) 1786 return false; 1787 if (!MemUWrite (context, addr, reg_value, addr_byte_size)) 1788 return false; 1789 } 1790 else 1791 { 1792 const uint32_t pc = ReadCoreReg(PC_REG, &success); 1793 if (!success) 1794 return false; 1795 if (!MemUWrite (context, addr, pc, addr_byte_size)) 1796 return false; 1797 } 1798 1799 1800 if (wback) 1801 { 1802 context.type = EmulateInstruction::eContextAdjustStackPointer; 1803 context.SetImmediateSigned (addr - sp); 1804 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, offset_addr)) 1805 return false; 1806 } 1807 } 1808 return true; 1809} 1810 1811// Vector Push stores multiple extension registers to the stack. 1812// It also updates SP to point to the start of the stored data. 1813bool 1814EmulateInstructionARM::EmulateVPUSH (const uint32_t opcode, const ARMEncoding encoding) 1815{ 1816#if 0 1817 // ARM pseudo code... 1818 if (ConditionPassed()) 1819 { 1820 EncodingSpecificOperations(); CheckVFPEnabled(TRUE); NullCheckIfThumbEE(13); 1821 address = SP - imm32; 1822 SP = SP - imm32; 1823 if single_regs then 1824 for r = 0 to regs-1 1825 MemA[address,4] = S[d+r]; address = address+4; 1826 else 1827 for r = 0 to regs-1 1828 // Store as two word-aligned words in the correct order for current endianness. 1829 MemA[address,4] = if BigEndian() then D[d+r]<63:32> else D[d+r]<31:0>; 1830 MemA[address+4,4] = if BigEndian() then D[d+r]<31:0> else D[d+r]<63:32>; 1831 address = address+8; 1832 } 1833#endif 1834 1835 bool success = false; 1836 1837 if (ConditionPassed(opcode)) 1838 { 1839 const uint32_t addr_byte_size = GetAddressByteSize(); 1840 const addr_t sp = ReadCoreReg (SP_REG, &success); 1841 if (!success) 1842 return false; 1843 bool single_regs; 1844 uint32_t d; // UInt(D:Vd) or UInt(Vd:D) starting register 1845 uint32_t imm32; // stack offset 1846 uint32_t regs; // number of registers 1847 switch (encoding) { 1848 case eEncodingT1: 1849 case eEncodingA1: 1850 single_regs = false; 1851 d = Bit32(opcode, 22) << 4 | Bits32(opcode, 15, 12); 1852 imm32 = Bits32(opcode, 7, 0) * addr_byte_size; 1853 // If UInt(imm8) is odd, see "FSTMX". 1854 regs = Bits32(opcode, 7, 0) / 2; 1855 // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE; 1856 if (regs == 0 || regs > 16 || (d + regs) > 32) 1857 return false; 1858 break; 1859 case eEncodingT2: 1860 case eEncodingA2: 1861 single_regs = true; 1862 d = Bits32(opcode, 15, 12) << 1 | Bit32(opcode, 22); 1863 imm32 = Bits32(opcode, 7, 0) * addr_byte_size; 1864 regs = Bits32(opcode, 7, 0); 1865 // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE; 1866 if (regs == 0 || regs > 16 || (d + regs) > 32) 1867 return false; 1868 break; 1869 default: 1870 return false; 1871 } 1872 uint32_t start_reg = single_regs ? dwarf_s0 : dwarf_d0; 1873 uint32_t reg_byte_size = single_regs ? addr_byte_size : addr_byte_size * 2; 1874 addr_t sp_offset = imm32; 1875 addr_t addr = sp - sp_offset; 1876 uint32_t i; 1877 1878 EmulateInstruction::Context context; 1879 context.type = EmulateInstruction::eContextPushRegisterOnStack; 1880 Register dwarf_reg; 1881 dwarf_reg.SetRegister (eRegisterKindDWARF, 0); 1882 Register sp_reg; 1883 sp_reg.SetRegister (eRegisterKindDWARF, dwarf_sp); 1884 for (i=0; i<regs; ++i) 1885 { 1886 dwarf_reg.num = start_reg + d + i; 1887 context.SetRegisterToRegisterPlusOffset ( dwarf_reg, sp_reg, addr - sp); 1888 // uint64_t to accommodate 64-bit registers. 1889 uint64_t reg_value = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_reg.num, 0, &success); 1890 if (!success) 1891 return false; 1892 if (!MemAWrite (context, addr, reg_value, reg_byte_size)) 1893 return false; 1894 addr += reg_byte_size; 1895 } 1896 1897 context.type = EmulateInstruction::eContextAdjustStackPointer; 1898 context.SetImmediateSigned (-sp_offset); 1899 1900 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, sp - sp_offset)) 1901 return false; 1902 } 1903 return true; 1904} 1905 1906// Vector Pop loads multiple extension registers from the stack. 1907// It also updates SP to point just above the loaded data. 1908bool 1909EmulateInstructionARM::EmulateVPOP (const uint32_t opcode, const ARMEncoding encoding) 1910{ 1911#if 0 1912 // ARM pseudo code... 1913 if (ConditionPassed()) 1914 { 1915 EncodingSpecificOperations(); CheckVFPEnabled(TRUE); NullCheckIfThumbEE(13); 1916 address = SP; 1917 SP = SP + imm32; 1918 if single_regs then 1919 for r = 0 to regs-1 1920 S[d+r] = MemA[address,4]; address = address+4; 1921 else 1922 for r = 0 to regs-1 1923 word1 = MemA[address,4]; word2 = MemA[address+4,4]; address = address+8; 1924 // Combine the word-aligned words in the correct order for current endianness. 1925 D[d+r] = if BigEndian() then word1:word2 else word2:word1; 1926 } 1927#endif 1928 1929 bool success = false; 1930 1931 if (ConditionPassed(opcode)) 1932 { 1933 const uint32_t addr_byte_size = GetAddressByteSize(); 1934 const addr_t sp = ReadCoreReg (SP_REG, &success); 1935 if (!success) 1936 return false; 1937 bool single_regs; 1938 uint32_t d; // UInt(D:Vd) or UInt(Vd:D) starting register 1939 uint32_t imm32; // stack offset 1940 uint32_t regs; // number of registers 1941 switch (encoding) { 1942 case eEncodingT1: 1943 case eEncodingA1: 1944 single_regs = false; 1945 d = Bit32(opcode, 22) << 4 | Bits32(opcode, 15, 12); 1946 imm32 = Bits32(opcode, 7, 0) * addr_byte_size; 1947 // If UInt(imm8) is odd, see "FLDMX". 1948 regs = Bits32(opcode, 7, 0) / 2; 1949 // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE; 1950 if (regs == 0 || regs > 16 || (d + regs) > 32) 1951 return false; 1952 break; 1953 case eEncodingT2: 1954 case eEncodingA2: 1955 single_regs = true; 1956 d = Bits32(opcode, 15, 12) << 1 | Bit32(opcode, 22); 1957 imm32 = Bits32(opcode, 7, 0) * addr_byte_size; 1958 regs = Bits32(opcode, 7, 0); 1959 // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE; 1960 if (regs == 0 || regs > 16 || (d + regs) > 32) 1961 return false; 1962 break; 1963 default: 1964 return false; 1965 } 1966 uint32_t start_reg = single_regs ? dwarf_s0 : dwarf_d0; 1967 uint32_t reg_byte_size = single_regs ? addr_byte_size : addr_byte_size * 2; 1968 addr_t sp_offset = imm32; 1969 addr_t addr = sp; 1970 uint32_t i; 1971 uint64_t data; // uint64_t to accomodate 64-bit registers. 1972 1973 EmulateInstruction::Context context; 1974 context.type = EmulateInstruction::eContextPopRegisterOffStack; 1975 Register dwarf_reg; 1976 dwarf_reg.SetRegister (eRegisterKindDWARF, 0); 1977 Register sp_reg; 1978 sp_reg.SetRegister (eRegisterKindDWARF, dwarf_sp); 1979 for (i=0; i<regs; ++i) 1980 { 1981 dwarf_reg.num = start_reg + d + i; 1982 context.SetRegisterPlusOffset (sp_reg, addr - sp); 1983 data = MemARead(context, addr, reg_byte_size, 0, &success); 1984 if (!success) 1985 return false; 1986 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_reg.num, data)) 1987 return false; 1988 addr += reg_byte_size; 1989 } 1990 1991 context.type = EmulateInstruction::eContextAdjustStackPointer; 1992 context.SetImmediateSigned (sp_offset); 1993 1994 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, sp + sp_offset)) 1995 return false; 1996 } 1997 return true; 1998} 1999 2000// SVC (previously SWI) 2001bool 2002EmulateInstructionARM::EmulateSVC (const uint32_t opcode, const ARMEncoding encoding) 2003{ 2004#if 0 2005 // ARM pseudo code... 2006 if (ConditionPassed()) 2007 { 2008 EncodingSpecificOperations(); 2009 CallSupervisor(); 2010 } 2011#endif 2012 2013 bool success = false; 2014 2015 if (ConditionPassed(opcode)) 2016 { 2017 const uint32_t pc = ReadCoreReg(PC_REG, &success); 2018 addr_t lr; // next instruction address 2019 if (!success) 2020 return false; 2021 uint32_t imm32; // the immediate constant 2022 uint32_t mode; // ARM or Thumb mode 2023 switch (encoding) { 2024 case eEncodingT1: 2025 lr = (pc + 2) | 1u; // return address 2026 imm32 = Bits32(opcode, 7, 0); 2027 mode = eModeThumb; 2028 break; 2029 case eEncodingA1: 2030 lr = pc + 4; // return address 2031 imm32 = Bits32(opcode, 23, 0); 2032 mode = eModeARM; 2033 break; 2034 default: 2035 return false; 2036 } 2037 2038 EmulateInstruction::Context context; 2039 context.type = EmulateInstruction::eContextSupervisorCall; 2040 context.SetModeAndImmediate (mode, imm32); 2041 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_RA, lr)) 2042 return false; 2043 } 2044 return true; 2045} 2046 2047// If Then makes up to four following instructions (the IT block) conditional. 2048bool 2049EmulateInstructionARM::EmulateIT (const uint32_t opcode, const ARMEncoding encoding) 2050{ 2051#if 0 2052 // ARM pseudo code... 2053 EncodingSpecificOperations(); 2054 ITSTATE.IT<7:0> = firstcond:mask; 2055#endif 2056 2057 m_it_session.InitIT(Bits32(opcode, 7, 0)); 2058 return true; 2059} 2060 2061// Branch causes a branch to a target address. 2062bool 2063EmulateInstructionARM::EmulateB (const uint32_t opcode, const ARMEncoding encoding) 2064{ 2065#if 0 2066 // ARM pseudo code... 2067 if (ConditionPassed()) 2068 { 2069 EncodingSpecificOperations(); 2070 BranchWritePC(PC + imm32); 2071 } 2072#endif 2073 2074 bool success = false; 2075 2076 if (ConditionPassed(opcode)) 2077 { 2078 EmulateInstruction::Context context; 2079 context.type = EmulateInstruction::eContextRelativeBranchImmediate; 2080 const uint32_t pc = ReadCoreReg(PC_REG, &success); 2081 if (!success) 2082 return false; 2083 addr_t target; // target address 2084 int32_t imm32; // PC-relative offset 2085 switch (encoding) { 2086 case eEncodingT1: 2087 // The 'cond' field is handled in EmulateInstructionARM::CurrentCond(). 2088 imm32 = llvm::SignExtend32<9>(Bits32(opcode, 7, 0) << 1); 2089 target = pc + imm32; 2090 context.SetModeAndImmediateSigned (eModeThumb, 4 + imm32); 2091 break; 2092 case eEncodingT2: 2093 imm32 = llvm::SignExtend32<12>(Bits32(opcode, 10, 0)); 2094 target = pc + imm32; 2095 context.SetModeAndImmediateSigned (eModeThumb, 4 + imm32); 2096 break; 2097 case eEncodingT3: 2098 // The 'cond' field is handled in EmulateInstructionARM::CurrentCond(). 2099 { 2100 uint32_t S = Bit32(opcode, 26); 2101 uint32_t imm6 = Bits32(opcode, 21, 16); 2102 uint32_t J1 = Bit32(opcode, 13); 2103 uint32_t J2 = Bit32(opcode, 11); 2104 uint32_t imm11 = Bits32(opcode, 10, 0); 2105 uint32_t imm21 = (S << 20) | (J2 << 19) | (J1 << 18) | (imm6 << 12) | (imm11 << 1); 2106 imm32 = llvm::SignExtend32<21>(imm21); 2107 target = pc + imm32; 2108 context.SetModeAndImmediateSigned (eModeThumb, 4 + imm32); 2109 break; 2110 } 2111 case eEncodingT4: 2112 { 2113 uint32_t S = Bit32(opcode, 26); 2114 uint32_t imm10 = Bits32(opcode, 25, 16); 2115 uint32_t J1 = Bit32(opcode, 13); 2116 uint32_t J2 = Bit32(opcode, 11); 2117 uint32_t imm11 = Bits32(opcode, 10, 0); 2118 uint32_t I1 = !(J1 ^ S); 2119 uint32_t I2 = !(J2 ^ S); 2120 uint32_t imm25 = (S << 24) | (I1 << 23) | (I2 << 22) | (imm10 << 12) | (imm11 << 1); 2121 imm32 = llvm::SignExtend32<25>(imm25); 2122 target = pc + imm32; 2123 context.SetModeAndImmediateSigned (eModeThumb, 4 + imm32); 2124 break; 2125 } 2126 case eEncodingA1: 2127 imm32 = llvm::SignExtend32<26>(Bits32(opcode, 23, 0) << 2); 2128 target = pc + imm32; 2129 context.SetModeAndImmediateSigned (eModeARM, 8 + imm32); 2130 break; 2131 default: 2132 return false; 2133 } 2134 if (!BranchWritePC(context, target)) 2135 return false; 2136 } 2137 return true; 2138} 2139 2140// Compare and Branch on Nonzero and Compare and Branch on Zero compare the value in a register with 2141// zero and conditionally branch forward a constant value. They do not affect the condition flags. 2142// CBNZ, CBZ 2143bool 2144EmulateInstructionARM::EmulateCB (const uint32_t opcode, const ARMEncoding encoding) 2145{ 2146#if 0 2147 // ARM pseudo code... 2148 EncodingSpecificOperations(); 2149 if nonzero ^ IsZero(R[n]) then 2150 BranchWritePC(PC + imm32); 2151#endif 2152 2153 bool success = false; 2154 2155 // Read the register value from the operand register Rn. 2156 uint32_t reg_val = ReadCoreReg(Bits32(opcode, 2, 0), &success); 2157 if (!success) 2158 return false; 2159 2160 EmulateInstruction::Context context; 2161 context.type = EmulateInstruction::eContextRelativeBranchImmediate; 2162 const uint32_t pc = ReadCoreReg(PC_REG, &success); 2163 if (!success) 2164 return false; 2165 2166 addr_t target; // target address 2167 uint32_t imm32; // PC-relative offset to branch forward 2168 bool nonzero; 2169 switch (encoding) { 2170 case eEncodingT1: 2171 imm32 = Bit32(opcode, 9) << 6 | Bits32(opcode, 7, 3) << 1; 2172 nonzero = BitIsSet(opcode, 11); 2173 target = pc + imm32; 2174 context.SetModeAndImmediateSigned (eModeThumb, 4 + imm32); 2175 break; 2176 default: 2177 return false; 2178 } 2179 if (nonzero ^ (reg_val == 0)) 2180 if (!BranchWritePC(context, target)) 2181 return false; 2182 2183 return true; 2184} 2185 2186// Table Branch Byte causes a PC-relative forward branch using a table of single byte offsets. 2187// A base register provides a pointer to the table, and a second register supplies an index into the table. 2188// The branch length is twice the value of the byte returned from the table. 2189// 2190// Table Branch Halfword causes a PC-relative forward branch using a table of single halfword offsets. 2191// A base register provides a pointer to the table, and a second register supplies an index into the table. 2192// The branch length is twice the value of the halfword returned from the table. 2193// TBB, TBH 2194bool 2195EmulateInstructionARM::EmulateTB (const uint32_t opcode, const ARMEncoding encoding) 2196{ 2197#if 0 2198 // ARM pseudo code... 2199 EncodingSpecificOperations(); NullCheckIfThumbEE(n); 2200 if is_tbh then 2201 halfwords = UInt(MemU[R[n]+LSL(R[m],1), 2]); 2202 else 2203 halfwords = UInt(MemU[R[n]+R[m], 1]); 2204 BranchWritePC(PC + 2*halfwords); 2205#endif 2206 2207 bool success = false; 2208 2209 uint32_t Rn; // the base register which contains the address of the table of branch lengths 2210 uint32_t Rm; // the index register which contains an integer pointing to a byte/halfword in the table 2211 bool is_tbh; // true if table branch halfword 2212 switch (encoding) { 2213 case eEncodingT1: 2214 Rn = Bits32(opcode, 19, 16); 2215 Rm = Bits32(opcode, 3, 0); 2216 is_tbh = BitIsSet(opcode, 4); 2217 if (Rn == 13 || BadReg(Rm)) 2218 return false; 2219 if (InITBlock() && !LastInITBlock()) 2220 return false; 2221 break; 2222 default: 2223 return false; 2224 } 2225 2226 // Read the address of the table from the operand register Rn. 2227 // The PC can be used, in which case the table immediately follows this instruction. 2228 uint32_t base = ReadCoreReg(Rm, &success); 2229 if (!success) 2230 return false; 2231 2232 // the table index 2233 uint32_t index = ReadCoreReg(Rm, &success); 2234 if (!success) 2235 return false; 2236 2237 // the offsetted table address 2238 addr_t addr = base + (is_tbh ? index*2 : index); 2239 2240 // PC-relative offset to branch forward 2241 EmulateInstruction::Context context; 2242 context.type = EmulateInstruction::eContextTableBranchReadMemory; 2243 uint32_t offset = MemURead(context, addr, is_tbh ? 2 : 1, 0, &success) * 2; 2244 if (!success) 2245 return false; 2246 2247 const uint32_t pc = ReadCoreReg(PC_REG, &success); 2248 if (!success) 2249 return false; 2250 2251 // target address 2252 addr_t target = pc + offset; 2253 context.type = EmulateInstruction::eContextRelativeBranchImmediate; 2254 context.SetModeAndImmediateSigned (eModeThumb, 4 + offset); 2255 2256 if (!BranchWritePC(context, target)) 2257 return false; 2258 2259 return true; 2260} 2261 2262// This instruction adds an immediate value to a register value, and writes the result to the destination register. 2263// It can optionally update the condition flags based on the result. 2264bool 2265EmulateInstructionARM::EmulateADDImmThumb (const uint32_t opcode, const ARMEncoding encoding) 2266{ 2267#if 0 2268 if ConditionPassed() then 2269 EncodingSpecificOperations(); 2270 (result, carry, overflow) = AddWithCarry(R[n], imm32, '0'); 2271 R[d] = result; 2272 if setflags then 2273 APSR.N = result<31>; 2274 APSR.Z = IsZeroBit(result); 2275 APSR.C = carry; 2276 APSR.V = overflow; 2277#endif 2278 2279 bool success = false; 2280 2281 if (ConditionPassed(opcode)) 2282 { 2283 uint32_t d; 2284 uint32_t n; 2285 bool setflags; 2286 uint32_t imm32; 2287 uint32_t carry_out; 2288 2289 //EncodingSpecificOperations(); 2290 switch (encoding) 2291 { 2292 case eEncodingT1: 2293 // d = UInt(Rd); n = UInt(Rn); setflags = !InITBlock(); imm32 = ZeroExtend(imm3, 32); 2294 d = Bits32 (opcode, 2, 0); 2295 n = Bits32 (opcode, 5, 3); 2296 setflags = !InITBlock(); 2297 imm32 = Bits32 (opcode, 8,6); 2298 2299 break; 2300 2301 case eEncodingT2: 2302 // d = UInt(Rdn); n = UInt(Rdn); setflags = !InITBlock(); imm32 = ZeroExtend(imm8, 32); 2303 d = Bits32 (opcode, 10, 8); 2304 n = Bits32 (opcode, 10, 8); 2305 setflags = !InITBlock(); 2306 imm32 = Bits32 (opcode, 7, 0); 2307 2308 break; 2309 2310 case eEncodingT3: 2311 // if Rd == '1111' && S == '1' then SEE CMN (immediate); 2312 // if Rn == '1101' then SEE ADD (SP plus immediate); 2313 // d = UInt(Rd); n = UInt(Rn); setflags = (S == '1'); imm32 = ThumbExpandImm(i:imm3:imm8); 2314 d = Bits32 (opcode, 11, 8); 2315 n = Bits32 (opcode, 19, 16); 2316 setflags = BitIsSet (opcode, 20); 2317 imm32 = ThumbExpandImm_C (opcode, APSR_C, carry_out); 2318 2319 // if BadReg(d) || n == 15 then UNPREDICTABLE; 2320 if (BadReg (d) || (n == 15)) 2321 return false; 2322 2323 break; 2324 2325 case eEncodingT4: 2326 { 2327 // if Rn == '1111' then SEE ADR; 2328 // if Rn == '1101' then SEE ADD (SP plus immediate); 2329 // d = UInt(Rd); n = UInt(Rn); setflags = FALSE; imm32 = ZeroExtend(i:imm3:imm8, 32); 2330 d = Bits32 (opcode, 11, 8); 2331 n = Bits32 (opcode, 19, 16); 2332 setflags = false; 2333 uint32_t i = Bit32 (opcode, 26); 2334 uint32_t imm3 = Bits32 (opcode, 14, 12); 2335 uint32_t imm8 = Bits32 (opcode, 7, 0); 2336 imm32 = (i << 11) | (imm3 << 8) | imm8; 2337 2338 // if BadReg(d) then UNPREDICTABLE; 2339 if (BadReg (d)) 2340 return false; 2341 2342 break; 2343 } 2344 default: 2345 return false; 2346 } 2347 2348 uint64_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success); 2349 if (!success) 2350 return false; 2351 2352 //(result, carry, overflow) = AddWithCarry(R[n], imm32, '0'); 2353 AddWithCarryResult res = AddWithCarry (Rn, imm32, 0); 2354 2355 Register reg_n; 2356 reg_n.SetRegister (eRegisterKindDWARF, dwarf_r0 + n); 2357 2358 EmulateInstruction::Context context; 2359 context.type = eContextAddition; 2360 context.SetRegisterPlusOffset (reg_n, imm32); 2361 2362 //R[d] = result; 2363 //if setflags then 2364 //APSR.N = result<31>; 2365 //APSR.Z = IsZeroBit(result); 2366 //APSR.C = carry; 2367 //APSR.V = overflow; 2368 if (!WriteCoreRegOptionalFlags (context, res.result, d, setflags, res.carry_out, res.overflow)) 2369 return false; 2370 2371 } 2372 return true; 2373} 2374 2375// This instruction adds an immediate value to a register value, and writes the result to the destination 2376// register. It can optionally update the condition flags based on the result. 2377bool 2378EmulateInstructionARM::EmulateADDImmARM (const uint32_t opcode, const ARMEncoding encoding) 2379{ 2380#if 0 2381 // ARM pseudo code... 2382 if ConditionPassed() then 2383 EncodingSpecificOperations(); 2384 (result, carry, overflow) = AddWithCarry(R[n], imm32, '0'); 2385 if d == 15 then 2386 ALUWritePC(result); // setflags is always FALSE here 2387 else 2388 R[d] = result; 2389 if setflags then 2390 APSR.N = result<31>; 2391 APSR.Z = IsZeroBit(result); 2392 APSR.C = carry; 2393 APSR.V = overflow; 2394#endif 2395 2396 bool success = false; 2397 2398 if (ConditionPassed(opcode)) 2399 { 2400 uint32_t Rd, Rn; 2401 uint32_t imm32; // the immediate value to be added to the value obtained from Rn 2402 bool setflags; 2403 switch (encoding) 2404 { 2405 case eEncodingA1: 2406 Rd = Bits32(opcode, 15, 12); 2407 Rn = Bits32(opcode, 19, 16); 2408 setflags = BitIsSet(opcode, 20); 2409 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12) 2410 break; 2411 default: 2412 return false; 2413 } 2414 2415 // Read the first operand. 2416 uint32_t val1 = ReadCoreReg(Rn, &success); 2417 if (!success) 2418 return false; 2419 2420 AddWithCarryResult res = AddWithCarry(val1, imm32, 0); 2421 2422 EmulateInstruction::Context context; 2423 context.type = EmulateInstruction::eContextImmediate; 2424 context.SetNoArgs (); 2425 2426 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow)) 2427 return false; 2428 } 2429 return true; 2430} 2431 2432// This instruction adds a register value and an optionally-shifted register value, and writes the result 2433// to the destination register. It can optionally update the condition flags based on the result. 2434bool 2435EmulateInstructionARM::EmulateADDReg (const uint32_t opcode, const ARMEncoding encoding) 2436{ 2437#if 0 2438 // ARM pseudo code... 2439 if ConditionPassed() then 2440 EncodingSpecificOperations(); 2441 shifted = Shift(R[m], shift_t, shift_n, APSR.C); 2442 (result, carry, overflow) = AddWithCarry(R[n], shifted, '0'); 2443 if d == 15 then 2444 ALUWritePC(result); // setflags is always FALSE here 2445 else 2446 R[d] = result; 2447 if setflags then 2448 APSR.N = result<31>; 2449 APSR.Z = IsZeroBit(result); 2450 APSR.C = carry; 2451 APSR.V = overflow; 2452#endif 2453 2454 bool success = false; 2455 2456 if (ConditionPassed(opcode)) 2457 { 2458 uint32_t Rd, Rn, Rm; 2459 ARM_ShifterType shift_t; 2460 uint32_t shift_n; // the shift applied to the value read from Rm 2461 bool setflags; 2462 switch (encoding) 2463 { 2464 case eEncodingT1: 2465 Rd = Bits32(opcode, 2, 0); 2466 Rn = Bits32(opcode, 5, 3); 2467 Rm = Bits32(opcode, 8, 6); 2468 setflags = !InITBlock(); 2469 shift_t = SRType_LSL; 2470 shift_n = 0; 2471 break; 2472 case eEncodingT2: 2473 Rd = Rn = Bit32(opcode, 7) << 3 | Bits32(opcode, 2, 0); 2474 Rm = Bits32(opcode, 6, 3); 2475 setflags = false; 2476 shift_t = SRType_LSL; 2477 shift_n = 0; 2478 if (Rn == 15 && Rm == 15) 2479 return false; 2480 if (Rd == 15 && InITBlock() && !LastInITBlock()) 2481 return false; 2482 break; 2483 case eEncodingA1: 2484 Rd = Bits32(opcode, 15, 12); 2485 Rn = Bits32(opcode, 19, 16); 2486 Rm = Bits32(opcode, 3, 0); 2487 setflags = BitIsSet(opcode, 20); 2488 shift_n = DecodeImmShiftARM(opcode, shift_t); 2489 break; 2490 default: 2491 return false; 2492 } 2493 2494 // Read the first operand. 2495 uint32_t val1 = ReadCoreReg(Rn, &success); 2496 if (!success) 2497 return false; 2498 2499 // Read the second operand. 2500 uint32_t val2 = ReadCoreReg(Rm, &success); 2501 if (!success) 2502 return false; 2503 2504 uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C); 2505 AddWithCarryResult res = AddWithCarry(val1, shifted, 0); 2506 2507 EmulateInstruction::Context context; 2508 context.type = EmulateInstruction::eContextAddition; 2509 Register op1_reg; 2510 Register op2_reg; 2511 op1_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + Rn); 2512 op2_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + Rm); 2513 context.SetRegisterRegisterOperands (op1_reg, op2_reg); 2514 2515 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow)) 2516 return false; 2517 } 2518 return true; 2519} 2520 2521// Compare Negative (immediate) adds a register value and an immediate value. 2522// It updates the condition flags based on the result, and discards the result. 2523bool 2524EmulateInstructionARM::EmulateCMNImm (const uint32_t opcode, const ARMEncoding encoding) 2525{ 2526#if 0 2527 // ARM pseudo code... 2528 if ConditionPassed() then 2529 EncodingSpecificOperations(); 2530 (result, carry, overflow) = AddWithCarry(R[n], imm32, '0'); 2531 APSR.N = result<31>; 2532 APSR.Z = IsZeroBit(result); 2533 APSR.C = carry; 2534 APSR.V = overflow; 2535#endif 2536 2537 bool success = false; 2538 2539 uint32_t Rn; // the first operand 2540 uint32_t imm32; // the immediate value to be compared with 2541 switch (encoding) { 2542 case eEncodingT1: 2543 Rn = Bits32(opcode, 19, 16); 2544 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8) 2545 if (Rn == 15) 2546 return false; 2547 break; 2548 case eEncodingA1: 2549 Rn = Bits32(opcode, 19, 16); 2550 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12) 2551 break; 2552 default: 2553 return false; 2554 } 2555 // Read the register value from the operand register Rn. 2556 uint32_t reg_val = ReadCoreReg(Rn, &success); 2557 if (!success) 2558 return false; 2559 2560 AddWithCarryResult res = AddWithCarry(reg_val, imm32, 0); 2561 2562 EmulateInstruction::Context context; 2563 context.type = EmulateInstruction::eContextImmediate; 2564 context.SetNoArgs (); 2565 if (!WriteFlags(context, res.result, res.carry_out, res.overflow)) 2566 return false; 2567 2568 return true; 2569} 2570 2571// Compare Negative (register) adds a register value and an optionally-shifted register value. 2572// It updates the condition flags based on the result, and discards the result. 2573bool 2574EmulateInstructionARM::EmulateCMNReg (const uint32_t opcode, const ARMEncoding encoding) 2575{ 2576#if 0 2577 // ARM pseudo code... 2578 if ConditionPassed() then 2579 EncodingSpecificOperations(); 2580 shifted = Shift(R[m], shift_t, shift_n, APSR.C); 2581 (result, carry, overflow) = AddWithCarry(R[n], shifted, '0'); 2582 APSR.N = result<31>; 2583 APSR.Z = IsZeroBit(result); 2584 APSR.C = carry; 2585 APSR.V = overflow; 2586#endif 2587 2588 bool success = false; 2589 2590 uint32_t Rn; // the first operand 2591 uint32_t Rm; // the second operand 2592 ARM_ShifterType shift_t; 2593 uint32_t shift_n; // the shift applied to the value read from Rm 2594 switch (encoding) { 2595 case eEncodingT1: 2596 Rn = Bits32(opcode, 2, 0); 2597 Rm = Bits32(opcode, 5, 3); 2598 shift_t = SRType_LSL; 2599 shift_n = 0; 2600 break; 2601 case eEncodingT2: 2602 Rn = Bits32(opcode, 19, 16); 2603 Rm = Bits32(opcode, 3, 0); 2604 shift_n = DecodeImmShiftThumb(opcode, shift_t); 2605 // if n == 15 || BadReg(m) then UNPREDICTABLE; 2606 if (Rn == 15 || BadReg(Rm)) 2607 return false; 2608 break; 2609 case eEncodingA1: 2610 Rn = Bits32(opcode, 19, 16); 2611 Rm = Bits32(opcode, 3, 0); 2612 shift_n = DecodeImmShiftARM(opcode, shift_t); 2613 break; 2614 default: 2615 return false; 2616 } 2617 // Read the register value from register Rn. 2618 uint32_t val1 = ReadCoreReg(Rn, &success); 2619 if (!success) 2620 return false; 2621 2622 // Read the register value from register Rm. 2623 uint32_t val2 = ReadCoreReg(Rm, &success); 2624 if (!success) 2625 return false; 2626 2627 uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C); 2628 AddWithCarryResult res = AddWithCarry(val1, shifted, 0); 2629 2630 EmulateInstruction::Context context; 2631 context.type = EmulateInstruction::eContextImmediate; 2632 context.SetNoArgs(); 2633 if (!WriteFlags(context, res.result, res.carry_out, res.overflow)) 2634 return false; 2635 2636 return true; 2637} 2638 2639// Compare (immediate) subtracts an immediate value from a register value. 2640// It updates the condition flags based on the result, and discards the result. 2641bool 2642EmulateInstructionARM::EmulateCMPImm (const uint32_t opcode, const ARMEncoding encoding) 2643{ 2644#if 0 2645 // ARM pseudo code... 2646 if ConditionPassed() then 2647 EncodingSpecificOperations(); 2648 (result, carry, overflow) = AddWithCarry(R[n], NOT(imm32), '1'); 2649 APSR.N = result<31>; 2650 APSR.Z = IsZeroBit(result); 2651 APSR.C = carry; 2652 APSR.V = overflow; 2653#endif 2654 2655 bool success = false; 2656 2657 uint32_t Rn; // the first operand 2658 uint32_t imm32; // the immediate value to be compared with 2659 switch (encoding) { 2660 case eEncodingT1: 2661 Rn = Bits32(opcode, 10, 8); 2662 imm32 = Bits32(opcode, 7, 0); 2663 break; 2664 case eEncodingT2: 2665 Rn = Bits32(opcode, 19, 16); 2666 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8) 2667 if (Rn == 15) 2668 return false; 2669 break; 2670 case eEncodingA1: 2671 Rn = Bits32(opcode, 19, 16); 2672 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12) 2673 break; 2674 default: 2675 return false; 2676 } 2677 // Read the register value from the operand register Rn. 2678 uint32_t reg_val = ReadCoreReg(Rn, &success); 2679 if (!success) 2680 return false; 2681 2682 AddWithCarryResult res = AddWithCarry(reg_val, ~imm32, 1); 2683 2684 EmulateInstruction::Context context; 2685 context.type = EmulateInstruction::eContextImmediate; 2686 context.SetNoArgs (); 2687 if (!WriteFlags(context, res.result, res.carry_out, res.overflow)) 2688 return false; 2689 2690 return true; 2691} 2692 2693// Compare (register) subtracts an optionally-shifted register value from a register value. 2694// It updates the condition flags based on the result, and discards the result. 2695bool 2696EmulateInstructionARM::EmulateCMPReg (const uint32_t opcode, const ARMEncoding encoding) 2697{ 2698#if 0 2699 // ARM pseudo code... 2700 if ConditionPassed() then 2701 EncodingSpecificOperations(); 2702 shifted = Shift(R[m], shift_t, shift_n, APSR.C); 2703 (result, carry, overflow) = AddWithCarry(R[n], NOT(shifted), '1'); 2704 APSR.N = result<31>; 2705 APSR.Z = IsZeroBit(result); 2706 APSR.C = carry; 2707 APSR.V = overflow; 2708#endif 2709 2710 bool success = false; 2711 2712 uint32_t Rn; // the first operand 2713 uint32_t Rm; // the second operand 2714 ARM_ShifterType shift_t; 2715 uint32_t shift_n; // the shift applied to the value read from Rm 2716 switch (encoding) { 2717 case eEncodingT1: 2718 Rn = Bits32(opcode, 2, 0); 2719 Rm = Bits32(opcode, 5, 3); 2720 shift_t = SRType_LSL; 2721 shift_n = 0; 2722 break; 2723 case eEncodingT2: 2724 Rn = Bit32(opcode, 7) << 3 | Bits32(opcode, 2, 0); 2725 Rm = Bits32(opcode, 6, 3); 2726 shift_t = SRType_LSL; 2727 shift_n = 0; 2728 if (Rn < 8 && Rm < 8) 2729 return false; 2730 if (Rn == 15 || Rm == 15) 2731 return false; 2732 break; 2733 case eEncodingA1: 2734 Rn = Bits32(opcode, 19, 16); 2735 Rm = Bits32(opcode, 3, 0); 2736 shift_n = DecodeImmShiftARM(opcode, shift_t); 2737 break; 2738 default: 2739 return false; 2740 } 2741 // Read the register value from register Rn. 2742 uint32_t val1 = ReadCoreReg(Rn, &success); 2743 if (!success) 2744 return false; 2745 2746 // Read the register value from register Rm. 2747 uint32_t val2 = ReadCoreReg(Rm, &success); 2748 if (!success) 2749 return false; 2750 2751 uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C); 2752 AddWithCarryResult res = AddWithCarry(val1, ~shifted, 1); 2753 2754 EmulateInstruction::Context context; 2755 context.type = EmulateInstruction::eContextImmediate; 2756 context.SetNoArgs(); 2757 if (!WriteFlags(context, res.result, res.carry_out, res.overflow)) 2758 return false; 2759 2760 return true; 2761} 2762 2763// Arithmetic Shift Right (immediate) shifts a register value right by an immediate number of bits, 2764// shifting in copies of its sign bit, and writes the result to the destination register. It can 2765// optionally update the condition flags based on the result. 2766bool 2767EmulateInstructionARM::EmulateASRImm (const uint32_t opcode, const ARMEncoding encoding) 2768{ 2769#if 0 2770 // ARM pseudo code... 2771 if ConditionPassed() then 2772 EncodingSpecificOperations(); 2773 (result, carry) = Shift_C(R[m], SRType_ASR, shift_n, APSR.C); 2774 if d == 15 then // Can only occur for ARM encoding 2775 ALUWritePC(result); // setflags is always FALSE here 2776 else 2777 R[d] = result; 2778 if setflags then 2779 APSR.N = result<31>; 2780 APSR.Z = IsZeroBit(result); 2781 APSR.C = carry; 2782 // APSR.V unchanged 2783#endif 2784 2785 return EmulateShiftImm (opcode, encoding, SRType_ASR); 2786} 2787 2788// Arithmetic Shift Right (register) shifts a register value right by a variable number of bits, 2789// shifting in copies of its sign bit, and writes the result to the destination register. 2790// The variable number of bits is read from the bottom byte of a register. It can optionally update 2791// the condition flags based on the result. 2792bool 2793EmulateInstructionARM::EmulateASRReg (const uint32_t opcode, const ARMEncoding encoding) 2794{ 2795#if 0 2796 // ARM pseudo code... 2797 if ConditionPassed() then 2798 EncodingSpecificOperations(); 2799 shift_n = UInt(R[m]<7:0>); 2800 (result, carry) = Shift_C(R[m], SRType_ASR, shift_n, APSR.C); 2801 R[d] = result; 2802 if setflags then 2803 APSR.N = result<31>; 2804 APSR.Z = IsZeroBit(result); 2805 APSR.C = carry; 2806 // APSR.V unchanged 2807#endif 2808 2809 return EmulateShiftReg (opcode, encoding, SRType_ASR); 2810} 2811 2812// Logical Shift Left (immediate) shifts a register value left by an immediate number of bits, 2813// shifting in zeros, and writes the result to the destination register. It can optionally 2814// update the condition flags based on the result. 2815bool 2816EmulateInstructionARM::EmulateLSLImm (const uint32_t opcode, const ARMEncoding encoding) 2817{ 2818#if 0 2819 // ARM pseudo code... 2820 if ConditionPassed() then 2821 EncodingSpecificOperations(); 2822 (result, carry) = Shift_C(R[m], SRType_LSL, shift_n, APSR.C); 2823 if d == 15 then // Can only occur for ARM encoding 2824 ALUWritePC(result); // setflags is always FALSE here 2825 else 2826 R[d] = result; 2827 if setflags then 2828 APSR.N = result<31>; 2829 APSR.Z = IsZeroBit(result); 2830 APSR.C = carry; 2831 // APSR.V unchanged 2832#endif 2833 2834 return EmulateShiftImm (opcode, encoding, SRType_LSL); 2835} 2836 2837// Logical Shift Left (register) shifts a register value left by a variable number of bits, 2838// shifting in zeros, and writes the result to the destination register. The variable number 2839// of bits is read from the bottom byte of a register. It can optionally update the condition 2840// flags based on the result. 2841bool 2842EmulateInstructionARM::EmulateLSLReg (const uint32_t opcode, const ARMEncoding encoding) 2843{ 2844#if 0 2845 // ARM pseudo code... 2846 if ConditionPassed() then 2847 EncodingSpecificOperations(); 2848 shift_n = UInt(R[m]<7:0>); 2849 (result, carry) = Shift_C(R[m], SRType_LSL, shift_n, APSR.C); 2850 R[d] = result; 2851 if setflags then 2852 APSR.N = result<31>; 2853 APSR.Z = IsZeroBit(result); 2854 APSR.C = carry; 2855 // APSR.V unchanged 2856#endif 2857 2858 return EmulateShiftReg (opcode, encoding, SRType_LSL); 2859} 2860 2861// Logical Shift Right (immediate) shifts a register value right by an immediate number of bits, 2862// shifting in zeros, and writes the result to the destination register. It can optionally 2863// update the condition flags based on the result. 2864bool 2865EmulateInstructionARM::EmulateLSRImm (const uint32_t opcode, const ARMEncoding encoding) 2866{ 2867#if 0 2868 // ARM pseudo code... 2869 if ConditionPassed() then 2870 EncodingSpecificOperations(); 2871 (result, carry) = Shift_C(R[m], SRType_LSR, shift_n, APSR.C); 2872 if d == 15 then // Can only occur for ARM encoding 2873 ALUWritePC(result); // setflags is always FALSE here 2874 else 2875 R[d] = result; 2876 if setflags then 2877 APSR.N = result<31>; 2878 APSR.Z = IsZeroBit(result); 2879 APSR.C = carry; 2880 // APSR.V unchanged 2881#endif 2882 2883 return EmulateShiftImm (opcode, encoding, SRType_LSR); 2884} 2885 2886// Logical Shift Right (register) shifts a register value right by a variable number of bits, 2887// shifting in zeros, and writes the result to the destination register. The variable number 2888// of bits is read from the bottom byte of a register. It can optionally update the condition 2889// flags based on the result. 2890bool 2891EmulateInstructionARM::EmulateLSRReg (const uint32_t opcode, const ARMEncoding encoding) 2892{ 2893#if 0 2894 // ARM pseudo code... 2895 if ConditionPassed() then 2896 EncodingSpecificOperations(); 2897 shift_n = UInt(R[m]<7:0>); 2898 (result, carry) = Shift_C(R[m], SRType_LSR, shift_n, APSR.C); 2899 R[d] = result; 2900 if setflags then 2901 APSR.N = result<31>; 2902 APSR.Z = IsZeroBit(result); 2903 APSR.C = carry; 2904 // APSR.V unchanged 2905#endif 2906 2907 return EmulateShiftReg (opcode, encoding, SRType_LSR); 2908} 2909 2910// Rotate Right (immediate) provides the value of the contents of a register rotated by a constant value. 2911// The bits that are rotated off the right end are inserted into the vacated bit positions on the left. 2912// It can optionally update the condition flags based on the result. 2913bool 2914EmulateInstructionARM::EmulateRORImm (const uint32_t opcode, const ARMEncoding encoding) 2915{ 2916#if 0 2917 // ARM pseudo code... 2918 if ConditionPassed() then 2919 EncodingSpecificOperations(); 2920 (result, carry) = Shift_C(R[m], SRType_ROR, shift_n, APSR.C); 2921 if d == 15 then // Can only occur for ARM encoding 2922 ALUWritePC(result); // setflags is always FALSE here 2923 else 2924 R[d] = result; 2925 if setflags then 2926 APSR.N = result<31>; 2927 APSR.Z = IsZeroBit(result); 2928 APSR.C = carry; 2929 // APSR.V unchanged 2930#endif 2931 2932 return EmulateShiftImm (opcode, encoding, SRType_ROR); 2933} 2934 2935// Rotate Right (register) provides the value of the contents of a register rotated by a variable number of bits. 2936// The bits that are rotated off the right end are inserted into the vacated bit positions on the left. 2937// The variable number of bits is read from the bottom byte of a register. It can optionally update the condition 2938// flags based on the result. 2939bool 2940EmulateInstructionARM::EmulateRORReg (const uint32_t opcode, const ARMEncoding encoding) 2941{ 2942#if 0 2943 // ARM pseudo code... 2944 if ConditionPassed() then 2945 EncodingSpecificOperations(); 2946 shift_n = UInt(R[m]<7:0>); 2947 (result, carry) = Shift_C(R[m], SRType_ROR, shift_n, APSR.C); 2948 R[d] = result; 2949 if setflags then 2950 APSR.N = result<31>; 2951 APSR.Z = IsZeroBit(result); 2952 APSR.C = carry; 2953 // APSR.V unchanged 2954#endif 2955 2956 return EmulateShiftReg (opcode, encoding, SRType_ROR); 2957} 2958 2959// Rotate Right with Extend provides the value of the contents of a register shifted right by one place, 2960// with the carry flag shifted into bit [31]. 2961// 2962// RRX can optionally update the condition flags based on the result. 2963// In that case, bit [0] is shifted into the carry flag. 2964bool 2965EmulateInstructionARM::EmulateRRX (const uint32_t opcode, const ARMEncoding encoding) 2966{ 2967#if 0 2968 // ARM pseudo code... 2969 if ConditionPassed() then 2970 EncodingSpecificOperations(); 2971 (result, carry) = Shift_C(R[m], SRType_RRX, 1, APSR.C); 2972 if d == 15 then // Can only occur for ARM encoding 2973 ALUWritePC(result); // setflags is always FALSE here 2974 else 2975 R[d] = result; 2976 if setflags then 2977 APSR.N = result<31>; 2978 APSR.Z = IsZeroBit(result); 2979 APSR.C = carry; 2980 // APSR.V unchanged 2981#endif 2982 2983 return EmulateShiftImm (opcode, encoding, SRType_RRX); 2984} 2985 2986bool 2987EmulateInstructionARM::EmulateShiftImm (const uint32_t opcode, const ARMEncoding encoding, ARM_ShifterType shift_type) 2988{ 2989 assert(shift_type == SRType_ASR 2990 || shift_type == SRType_LSL 2991 || shift_type == SRType_LSR 2992 || shift_type == SRType_ROR 2993 || shift_type == SRType_RRX); 2994 2995 bool success = false; 2996 2997 if (ConditionPassed(opcode)) 2998 { 2999 uint32_t Rd; // the destination register 3000 uint32_t Rm; // the first operand register 3001 uint32_t imm5; // encoding for the shift amount 3002 uint32_t carry; // the carry bit after the shift operation 3003 bool setflags; 3004 3005 // Special case handling! 3006 // A8.6.139 ROR (immediate) -- Encoding T1 3007 ARMEncoding use_encoding = encoding; 3008 if (shift_type == SRType_ROR && use_encoding == eEncodingT1) 3009 { 3010 // Morph the T1 encoding from the ARM Architecture Manual into T2 encoding to 3011 // have the same decoding of bit fields as the other Thumb2 shift operations. 3012 use_encoding = eEncodingT2; 3013 } 3014 3015 switch (use_encoding) { 3016 case eEncodingT1: 3017 // Due to the above special case handling! 3018 assert(shift_type != SRType_ROR); 3019 3020 Rd = Bits32(opcode, 2, 0); 3021 Rm = Bits32(opcode, 5, 3); 3022 setflags = !InITBlock(); 3023 imm5 = Bits32(opcode, 10, 6); 3024 break; 3025 case eEncodingT2: 3026 // A8.6.141 RRX 3027 assert(shift_type != SRType_RRX); 3028 3029 Rd = Bits32(opcode, 11, 8); 3030 Rm = Bits32(opcode, 3, 0); 3031 setflags = BitIsSet(opcode, 20); 3032 imm5 = Bits32(opcode, 14, 12) << 2 | Bits32(opcode, 7, 6); 3033 if (BadReg(Rd) || BadReg(Rm)) 3034 return false; 3035 break; 3036 case eEncodingA1: 3037 Rd = Bits32(opcode, 15, 12); 3038 Rm = Bits32(opcode, 3, 0); 3039 setflags = BitIsSet(opcode, 20); 3040 imm5 = Bits32(opcode, 11, 7); 3041 break; 3042 default: 3043 return false; 3044 } 3045 3046 // A8.6.139 ROR (immediate) 3047 if (shift_type == SRType_ROR && imm5 == 0) 3048 shift_type = SRType_RRX; 3049 3050 // Get the first operand. 3051 uint32_t value = ReadCoreReg (Rm, &success); 3052 if (!success) 3053 return false; 3054 3055 // Decode the shift amount if not RRX. 3056 uint32_t amt = (shift_type == SRType_RRX ? 1 : DecodeImmShift(shift_type, imm5)); 3057 3058 uint32_t result = Shift_C(value, shift_type, amt, APSR_C, carry); 3059 3060 // The context specifies that an immediate is to be moved into Rd. 3061 EmulateInstruction::Context context; 3062 context.type = EmulateInstruction::eContextImmediate; 3063 context.SetNoArgs (); 3064 3065 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry)) 3066 return false; 3067 } 3068 return true; 3069} 3070 3071bool 3072EmulateInstructionARM::EmulateShiftReg (const uint32_t opcode, const ARMEncoding encoding, ARM_ShifterType shift_type) 3073{ 3074 assert(shift_type == SRType_ASR || shift_type == SRType_LSL || shift_type == SRType_LSR); 3075 3076 bool success = false; 3077 3078 if (ConditionPassed(opcode)) 3079 { 3080 uint32_t Rd; // the destination register 3081 uint32_t Rn; // the first operand register 3082 uint32_t Rm; // the register whose bottom byte contains the amount to shift by 3083 uint32_t carry; // the carry bit after the shift operation 3084 bool setflags; 3085 switch (encoding) { 3086 case eEncodingT1: 3087 Rd = Bits32(opcode, 2, 0); 3088 Rn = Rd; 3089 Rm = Bits32(opcode, 5, 3); 3090 setflags = !InITBlock(); 3091 break; 3092 case eEncodingT2: 3093 Rd = Bits32(opcode, 11, 8); 3094 Rn = Bits32(opcode, 19, 16); 3095 Rm = Bits32(opcode, 3, 0); 3096 setflags = BitIsSet(opcode, 20); 3097 if (BadReg(Rd) || BadReg(Rn) || BadReg(Rm)) 3098 return false; 3099 break; 3100 case eEncodingA1: 3101 Rd = Bits32(opcode, 15, 12); 3102 Rn = Bits32(opcode, 3, 0); 3103 Rm = Bits32(opcode, 11, 8); 3104 setflags = BitIsSet(opcode, 20); 3105 if (Rd == 15 || Rn == 15 || Rm == 15) 3106 return false; 3107 break; 3108 default: 3109 return false; 3110 } 3111 3112 // Get the first operand. 3113 uint32_t value = ReadCoreReg (Rn, &success); 3114 if (!success) 3115 return false; 3116 // Get the Rm register content. 3117 uint32_t val = ReadCoreReg (Rm, &success); 3118 if (!success) 3119 return false; 3120 3121 // Get the shift amount. 3122 uint32_t amt = Bits32(val, 7, 0); 3123 3124 uint32_t result = Shift_C(value, shift_type, amt, APSR_C, carry); 3125 3126 // The context specifies that an immediate is to be moved into Rd. 3127 EmulateInstruction::Context context; 3128 context.type = EmulateInstruction::eContextImmediate; 3129 context.SetNoArgs (); 3130 3131 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry)) 3132 return false; 3133 } 3134 return true; 3135} 3136 3137// LDM loads multiple registers from consecutive memory locations, using an 3138// address from a base register. Optionally the address just above the highest of those locations 3139// can be written back to the base register. 3140bool 3141EmulateInstructionARM::EmulateLDM (const uint32_t opcode, const ARMEncoding encoding) 3142{ 3143#if 0 3144 // ARM pseudo code... 3145 if ConditionPassed() 3146 EncodingSpecificOperations(); NullCheckIfThumbEE (n); 3147 address = R[n]; 3148 3149 for i = 0 to 14 3150 if registers<i> == '1' then 3151 R[i] = MemA[address, 4]; address = address + 4; 3152 if registers<15> == '1' then 3153 LoadWritePC (MemA[address, 4]); 3154 3155 if wback && registers<n> == '0' then R[n] = R[n] + 4 * BitCount (registers); 3156 if wback && registers<n> == '1' then R[n] = bits(32) UNKNOWN; // Only possible for encoding A1 3157 3158#endif 3159 3160 bool success = false; 3161 3162 if (ConditionPassed(opcode)) 3163 { 3164 uint32_t n; 3165 uint32_t registers = 0; 3166 bool wback; 3167 const uint32_t addr_byte_size = GetAddressByteSize(); 3168 switch (encoding) 3169 { 3170 case eEncodingT1: 3171 // n = UInt(Rn); registers = '00000000':register_list; wback = (registers<n> == '0'); 3172 n = Bits32 (opcode, 10, 8); 3173 registers = Bits32 (opcode, 7, 0); 3174 registers = registers & 0x00ff; // Make sure the top 8 bits are zeros. 3175 wback = BitIsClear (registers, n); 3176 // if BitCount(registers) < 1 then UNPREDICTABLE; 3177 if (BitCount(registers) < 1) 3178 return false; 3179 break; 3180 case eEncodingT2: 3181 // if W == '1' && Rn == '1101' then SEE POP; 3182 // n = UInt(Rn); registers = P:M:'0':register_list; wback = (W == '1'); 3183 n = Bits32 (opcode, 19, 16); 3184 registers = Bits32 (opcode, 15, 0); 3185 registers = registers & 0xdfff; // Make sure bit 13 is zero. 3186 wback = BitIsSet (opcode, 21); 3187 3188 // if n == 15 || BitCount(registers) < 2 || (P == '1' && M == '1') then UNPREDICTABLE; 3189 if ((n == 15) 3190 || (BitCount (registers) < 2) 3191 || (BitIsSet (opcode, 14) && BitIsSet (opcode, 15))) 3192 return false; 3193 3194 // if registers<15> == '1' && InITBlock() && !LastInITBlock() then UNPREDICTABLE; 3195 if (BitIsSet (registers, 15) && InITBlock() && !LastInITBlock()) 3196 return false; 3197 3198 // if wback && registers<n> == '1' then UNPREDICTABLE; 3199 if (wback 3200 && BitIsSet (registers, n)) 3201 return false; 3202 break; 3203 3204 case eEncodingA1: 3205 n = Bits32 (opcode, 19, 16); 3206 registers = Bits32 (opcode, 15, 0); 3207 wback = BitIsSet (opcode, 21); 3208 if ((n == 15) 3209 || (BitCount (registers) < 1)) 3210 return false; 3211 break; 3212 default: 3213 return false; 3214 } 3215 3216 int32_t offset = 0; 3217 const addr_t base_address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success); 3218 if (!success) 3219 return false; 3220 3221 EmulateInstruction::Context context; 3222 context.type = EmulateInstruction::eContextRegisterPlusOffset; 3223 Register dwarf_reg; 3224 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n); 3225 context.SetRegisterPlusOffset (dwarf_reg, offset); 3226 3227 for (int i = 0; i < 14; ++i) 3228 { 3229 if (BitIsSet (registers, i)) 3230 { 3231 context.type = EmulateInstruction::eContextRegisterPlusOffset; 3232 context.SetRegisterPlusOffset (dwarf_reg, offset); 3233 if (wback && (n == 13)) // Pop Instruction 3234 context.type = EmulateInstruction::eContextPopRegisterOffStack; 3235 3236 // R[i] = MemA [address, 4]; address = address + 4; 3237 uint32_t data = MemARead (context, base_address + offset, addr_byte_size, 0, &success); 3238 if (!success) 3239 return false; 3240 3241 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + i, data)) 3242 return false; 3243 3244 offset += addr_byte_size; 3245 } 3246 } 3247 3248 if (BitIsSet (registers, 15)) 3249 { 3250 //LoadWritePC (MemA [address, 4]); 3251 context.type = EmulateInstruction::eContextRegisterPlusOffset; 3252 context.SetRegisterPlusOffset (dwarf_reg, offset); 3253 uint32_t data = MemARead (context, base_address + offset, addr_byte_size, 0, &success); 3254 if (!success) 3255 return false; 3256 // In ARMv5T and above, this is an interworking branch. 3257 if (!LoadWritePC(context, data)) 3258 return false; 3259 } 3260 3261 if (wback && BitIsClear (registers, n)) 3262 { 3263 // R[n] = R[n] + 4 * BitCount (registers) 3264 int32_t offset = addr_byte_size * BitCount (registers); 3265 context.type = EmulateInstruction::eContextAdjustBaseRegister; 3266 context.SetRegisterPlusOffset (dwarf_reg, offset); 3267 3268 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, base_address + offset)) 3269 return false; 3270 } 3271 if (wback && BitIsSet (registers, n)) 3272 // R[n] bits(32) UNKNOWN; 3273 return WriteBits32Unknown (n); 3274 } 3275 return true; 3276} 3277 3278// LDMDA loads multiple registers from consecutive memory locations using an address from a base register. 3279// The consecutive memory locations end at this address and the address just below the lowest of those locations 3280// can optionally be written back to the base register. 3281bool 3282EmulateInstructionARM::EmulateLDMDA (const uint32_t opcode, const ARMEncoding encoding) 3283{ 3284#if 0 3285 // ARM pseudo code... 3286 if ConditionPassed() then 3287 EncodingSpecificOperations(); 3288 address = R[n] - 4*BitCount(registers) + 4; 3289 3290 for i = 0 to 14 3291 if registers<i> == '1' then 3292 R[i] = MemA[address,4]; address = address + 4; 3293 3294 if registers<15> == '1' then 3295 LoadWritePC(MemA[address,4]); 3296 3297 if wback && registers<n> == '0' then R[n] = R[n] - 4*BitCount(registers); 3298 if wback && registers<n> == '1' then R[n] = bits(32) UNKNOWN; 3299#endif 3300 3301 bool success = false; 3302 3303 if (ConditionPassed(opcode)) 3304 { 3305 uint32_t n; 3306 uint32_t registers = 0; 3307 bool wback; 3308 const uint32_t addr_byte_size = GetAddressByteSize(); 3309 3310 // EncodingSpecificOperations(); 3311 switch (encoding) 3312 { 3313 case eEncodingA1: 3314 // n = UInt(Rn); registers = register_list; wback = (W == '1'); 3315 n = Bits32 (opcode, 19, 16); 3316 registers = Bits32 (opcode, 15, 0); 3317 wback = BitIsSet (opcode, 21); 3318 3319 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE; 3320 if ((n == 15) || (BitCount (registers) < 1)) 3321 return false; 3322 3323 break; 3324 3325 default: 3326 return false; 3327 } 3328 // address = R[n] - 4*BitCount(registers) + 4; 3329 3330 int32_t offset = 0; 3331 addr_t Rn = ReadCoreReg (n, &success); 3332 3333 if (!success) 3334 return false; 3335 3336 addr_t address = Rn - (addr_byte_size * BitCount (registers)) + addr_byte_size; 3337 3338 EmulateInstruction::Context context; 3339 context.type = EmulateInstruction::eContextRegisterPlusOffset; 3340 Register dwarf_reg; 3341 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n); 3342 context.SetRegisterPlusOffset (dwarf_reg, offset); 3343 3344 // for i = 0 to 14 3345 for (int i = 0; i < 14; ++i) 3346 { 3347 // if registers<i> == '1' then 3348 if (BitIsSet (registers, i)) 3349 { 3350 // R[i] = MemA[address,4]; address = address + 4; 3351 context.SetRegisterPlusOffset (dwarf_reg, Rn - (address + offset)); 3352 uint32_t data = MemARead (context, address + offset, addr_byte_size, 0, &success); 3353 if (!success) 3354 return false; 3355 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + i, data)) 3356 return false; 3357 offset += addr_byte_size; 3358 } 3359 } 3360 3361 // if registers<15> == '1' then 3362 // LoadWritePC(MemA[address,4]); 3363 if (BitIsSet (registers, 15)) 3364 { 3365 context.SetRegisterPlusOffset (dwarf_reg, offset); 3366 uint32_t data = MemARead (context, address + offset, addr_byte_size, 0, &success); 3367 if (!success) 3368 return false; 3369 // In ARMv5T and above, this is an interworking branch. 3370 if (!LoadWritePC(context, data)) 3371 return false; 3372 } 3373 3374 // if wback && registers<n> == '0' then R[n] = R[n] - 4*BitCount(registers); 3375 if (wback && BitIsClear (registers, n)) 3376 { 3377 if (!success) 3378 return false; 3379 3380 offset = (addr_byte_size * BitCount (registers)) * -1; 3381 context.type = EmulateInstruction::eContextAdjustBaseRegister; 3382 context.SetImmediateSigned (offset); 3383 addr_t addr = Rn + offset; 3384 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, addr)) 3385 return false; 3386 } 3387 3388 // if wback && registers<n> == '1' then R[n] = bits(32) UNKNOWN; 3389 if (wback && BitIsSet (registers, n)) 3390 return WriteBits32Unknown (n); 3391 } 3392 return true; 3393} 3394 3395// LDMDB loads multiple registers from consecutive memory locations using an address from a base register. The 3396// consecutive memory lcoations end just below this address, and the address of the lowest of those locations can 3397// be optionally written back to the base register. 3398bool 3399EmulateInstructionARM::EmulateLDMDB (const uint32_t opcode, const ARMEncoding encoding) 3400{ 3401#if 0 3402 // ARM pseudo code... 3403 if ConditionPassed() then 3404 EncodingSpecificOperations(); NullCheckIfThumbEE(n); 3405 address = R[n] - 4*BitCount(registers); 3406 3407 for i = 0 to 14 3408 if registers<i> == '1' then 3409 R[i] = MemA[address,4]; address = address + 4; 3410 if registers<15> == '1' then 3411 LoadWritePC(MemA[address,4]); 3412 3413 if wback && registers<n> == '0' then R[n] = R[n] - 4*BitCount(registers); 3414 if wback && registers<n> == '1' then R[n] = bits(32) UNKNOWN; // Only possible for encoding A1 3415#endif 3416 3417 bool success = false; 3418 3419 if (ConditionPassed(opcode)) 3420 { 3421 uint32_t n; 3422 uint32_t registers = 0; 3423 bool wback; 3424 const uint32_t addr_byte_size = GetAddressByteSize(); 3425 switch (encoding) 3426 { 3427 case eEncodingT1: 3428 // n = UInt(Rn); registers = P:M:'0':register_list; wback = (W == '1'); 3429 n = Bits32 (opcode, 19, 16); 3430 registers = Bits32 (opcode, 15, 0); 3431 registers = registers & 0xdfff; // Make sure bit 13 is a zero. 3432 wback = BitIsSet (opcode, 21); 3433 3434 // if n == 15 || BitCount(registers) < 2 || (P == '1' && M == '1') then UNPREDICTABLE; 3435 if ((n == 15) 3436 || (BitCount (registers) < 2) 3437 || (BitIsSet (opcode, 14) && BitIsSet (opcode, 15))) 3438 return false; 3439 3440 // if registers<15> == '1' && InITBlock() && !LastInITBlock() then UNPREDICTABLE; 3441 if (BitIsSet (registers, 15) && InITBlock() && !LastInITBlock()) 3442 return false; 3443 3444 // if wback && registers<n> == '1' then UNPREDICTABLE; 3445 if (wback && BitIsSet (registers, n)) 3446 return false; 3447 3448 break; 3449 3450 case eEncodingA1: 3451 // n = UInt(Rn); registers = register_list; wback = (W == '1'); 3452 n = Bits32 (opcode, 19, 16); 3453 registers = Bits32 (opcode, 15, 0); 3454 wback = BitIsSet (opcode, 21); 3455 3456 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE; 3457 if ((n == 15) || (BitCount (registers) < 1)) 3458 return false; 3459 3460 break; 3461 3462 default: 3463 return false; 3464 } 3465 3466 // address = R[n] - 4*BitCount(registers); 3467 3468 int32_t offset = 0; 3469 addr_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success); 3470 3471 if (!success) 3472 return false; 3473 3474 addr_t address = Rn - (addr_byte_size * BitCount (registers)); 3475 EmulateInstruction::Context context; 3476 context.type = EmulateInstruction::eContextRegisterPlusOffset; 3477 Register dwarf_reg; 3478 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n); 3479 context.SetRegisterPlusOffset (dwarf_reg, Rn - address); 3480 3481 for (int i = 0; i < 14; ++i) 3482 { 3483 if (BitIsSet (registers, i)) 3484 { 3485 // R[i] = MemA[address,4]; address = address + 4; 3486 context.SetRegisterPlusOffset (dwarf_reg, Rn - (address + offset)); 3487 uint32_t data = MemARead (context, address + offset, addr_byte_size, 0, &success); 3488 if (!success) 3489 return false; 3490 3491 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + i, data)) 3492 return false; 3493 3494 offset += addr_byte_size; 3495 } 3496 } 3497 3498 // if registers<15> == '1' then 3499 // LoadWritePC(MemA[address,4]); 3500 if (BitIsSet (registers, 15)) 3501 { 3502 context.SetRegisterPlusOffset (dwarf_reg, offset); 3503 uint32_t data = MemARead (context, address + offset, addr_byte_size, 0, &success); 3504 if (!success) 3505 return false; 3506 // In ARMv5T and above, this is an interworking branch. 3507 if (!LoadWritePC(context, data)) 3508 return false; 3509 } 3510 3511 // if wback && registers<n> == '0' then R[n] = R[n] - 4*BitCount(registers); 3512 if (wback && BitIsClear (registers, n)) 3513 { 3514 if (!success) 3515 return false; 3516 3517 offset = (addr_byte_size * BitCount (registers)) * -1; 3518 context.type = EmulateInstruction::eContextAdjustBaseRegister; 3519 context.SetImmediateSigned (offset); 3520 addr_t addr = Rn + offset; 3521 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, addr)) 3522 return false; 3523 } 3524 3525 // if wback && registers<n> == '1' then R[n] = bits(32) UNKNOWN; // Only possible for encoding A1 3526 if (wback && BitIsSet (registers, n)) 3527 return WriteBits32Unknown (n); 3528 } 3529 return true; 3530} 3531 3532// LDMIB loads multiple registers from consecutive memory locations using an address from a base register. The 3533// consecutive memory locations start just above this address, and thea ddress of the last of those locations can 3534// optinoally be written back to the base register. 3535bool 3536EmulateInstructionARM::EmulateLDMIB (const uint32_t opcode, const ARMEncoding encoding) 3537{ 3538#if 0 3539 if ConditionPassed() then 3540 EncodingSpecificOperations(); 3541 address = R[n] + 4; 3542 3543 for i = 0 to 14 3544 if registers<i> == '1' then 3545 R[i] = MemA[address,4]; address = address + 4; 3546 if registers<15> == '1' then 3547 LoadWritePC(MemA[address,4]); 3548 3549 if wback && registers<n> == '0' then R[n] = R[n] + 4*BitCount(registers); 3550 if wback && registers<n> == '1' then R[n] = bits(32) UNKNOWN; 3551#endif 3552 3553 bool success = false; 3554 3555 if (ConditionPassed(opcode)) 3556 { 3557 uint32_t n; 3558 uint32_t registers = 0; 3559 bool wback; 3560 const uint32_t addr_byte_size = GetAddressByteSize(); 3561 switch (encoding) 3562 { 3563 case eEncodingA1: 3564 // n = UInt(Rn); registers = register_list; wback = (W == '1'); 3565 n = Bits32 (opcode, 19, 16); 3566 registers = Bits32 (opcode, 15, 0); 3567 wback = BitIsSet (opcode, 21); 3568 3569 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE; 3570 if ((n == 15) || (BitCount (registers) < 1)) 3571 return false; 3572 3573 break; 3574 default: 3575 return false; 3576 } 3577 // address = R[n] + 4; 3578 3579 int32_t offset = 0; 3580 addr_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success); 3581 3582 if (!success) 3583 return false; 3584 3585 addr_t address = Rn + addr_byte_size; 3586 3587 EmulateInstruction::Context context; 3588 context.type = EmulateInstruction::eContextRegisterPlusOffset; 3589 Register dwarf_reg; 3590 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n); 3591 context.SetRegisterPlusOffset (dwarf_reg, offset); 3592 3593 for (int i = 0; i < 14; ++i) 3594 { 3595 if (BitIsSet (registers, i)) 3596 { 3597 // R[i] = MemA[address,4]; address = address + 4; 3598 3599 context.SetRegisterPlusOffset (dwarf_reg, offset + addr_byte_size); 3600 uint32_t data = MemARead (context, address + offset, addr_byte_size, 0, &success); 3601 if (!success) 3602 return false; 3603 3604 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + i, data)) 3605 return false; 3606 3607 offset += addr_byte_size; 3608 } 3609 } 3610 3611 // if registers<15> == '1' then 3612 // LoadWritePC(MemA[address,4]); 3613 if (BitIsSet (registers, 15)) 3614 { 3615 context.SetRegisterPlusOffset (dwarf_reg, offset); 3616 uint32_t data = MemARead (context, address + offset, addr_byte_size, 0, &success); 3617 if (!success) 3618 return false; 3619 // In ARMv5T and above, this is an interworking branch. 3620 if (!LoadWritePC(context, data)) 3621 return false; 3622 } 3623 3624 // if wback && registers<n> == '0' then R[n] = R[n] + 4*BitCount(registers); 3625 if (wback && BitIsClear (registers, n)) 3626 { 3627 if (!success) 3628 return false; 3629 3630 offset = addr_byte_size * BitCount (registers); 3631 context.type = EmulateInstruction::eContextAdjustBaseRegister; 3632 context.SetImmediateSigned (offset); 3633 addr_t addr = Rn + offset; 3634 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, addr)) 3635 return false; 3636 } 3637 3638 // if wback && registers<n> == '1' then R[n] = bits(32) UNKNOWN; // Only possible for encoding A1 3639 if (wback && BitIsSet (registers, n)) 3640 return WriteBits32Unknown (n); 3641 } 3642 return true; 3643} 3644 3645// Load Register (immediate) calculates an address from a base register value and 3646// an immediate offset, loads a word from memory, and writes to a register. 3647// LDR (immediate, Thumb) 3648bool 3649EmulateInstructionARM::EmulateLDRRtRnImm (const uint32_t opcode, const ARMEncoding encoding) 3650{ 3651#if 0 3652 // ARM pseudo code... 3653 if (ConditionPassed()) 3654 { 3655 EncodingSpecificOperations(); NullCheckIfThumbEE(15); 3656 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32); 3657 address = if index then offset_addr else R[n]; 3658 data = MemU[address,4]; 3659 if wback then R[n] = offset_addr; 3660 if t == 15 then 3661 if address<1:0> == '00' then LoadWritePC(data); else UNPREDICTABLE; 3662 elsif UnalignedSupport() || address<1:0> = '00' then 3663 R[t] = data; 3664 else R[t] = bits(32) UNKNOWN; // Can only apply before ARMv7 3665 } 3666#endif 3667 3668 bool success = false; 3669 3670 if (ConditionPassed(opcode)) 3671 { 3672 uint32_t Rt; // the destination register 3673 uint32_t Rn; // the base register 3674 uint32_t imm32; // the immediate offset used to form the address 3675 addr_t offset_addr; // the offset address 3676 addr_t address; // the calculated address 3677 uint32_t data; // the literal data value from memory load 3678 bool add, index, wback; 3679 switch (encoding) { 3680 case eEncodingT1: 3681 Rt = Bits32(opcode, 5, 3); 3682 Rn = Bits32(opcode, 2, 0); 3683 imm32 = Bits32(opcode, 10, 6) << 2; // imm32 = ZeroExtend(imm5:'00', 32); 3684 // index = TRUE; add = TRUE; wback = FALSE 3685 add = true; 3686 index = true; 3687 wback = false; 3688 3689 break; 3690 3691 case eEncodingT2: 3692 // t = UInt(Rt); n = 13; imm32 = ZeroExtend(imm8:'00', 32); 3693 Rt = Bits32 (opcode, 10, 8); 3694 Rn = 13; 3695 imm32 = Bits32 (opcode, 7, 0) << 2; 3696 3697 // index = TRUE; add = TRUE; wback = FALSE; 3698 index = true; 3699 add = true; 3700 wback = false; 3701 3702 break; 3703 3704 case eEncodingT3: 3705 // if Rn == '1111' then SEE LDR (literal); 3706 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32); 3707 Rt = Bits32 (opcode, 15, 12); 3708 Rn = Bits32 (opcode, 19, 16); 3709 imm32 = Bits32 (opcode, 11, 0); 3710 3711 // index = TRUE; add = TRUE; wback = FALSE; 3712 index = true; 3713 add = true; 3714 wback = false; 3715 3716 // if t == 15 && InITBlock() && !LastInITBlock() then UNPREDICTABLE; 3717 if ((Rt == 15) && InITBlock() && !LastInITBlock()) 3718 return false; 3719 3720 break; 3721 3722 case eEncodingT4: 3723 // if Rn == '1111' then SEE LDR (literal); 3724 // if P == '1' && U == '1' && W == '0' then SEE LDRT; 3725 // if Rn == '1101' && P == '0' && U == '1' && W == '1' && imm8 == '00000100' then SEE POP; 3726 // if P == '0' && W == '0' then UNDEFINED; 3727 if (BitIsClear (opcode, 10) && BitIsClear (opcode, 8)) 3728 return false; 3729 3730 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32); 3731 Rt = Bits32 (opcode, 15, 12); 3732 Rn = Bits32 (opcode, 19, 16); 3733 imm32 = Bits32 (opcode, 7, 0); 3734 3735 // index = (P == '1'); add = (U == '1'); wback = (W == '1'); 3736 index = BitIsSet (opcode, 10); 3737 add = BitIsSet (opcode, 9); 3738 wback = BitIsSet (opcode, 8); 3739 3740 // if (wback && n == t) || (t == 15 && InITBlock() && !LastInITBlock()) then UNPREDICTABLE; 3741 if ((wback && (Rn == Rt)) || ((Rt == 15) && InITBlock() && !LastInITBlock())) 3742 return false; 3743 3744 break; 3745 3746 default: 3747 return false; 3748 } 3749 uint32_t base = ReadCoreReg (Rn, &success); 3750 if (!success) 3751 return false; 3752 if (add) 3753 offset_addr = base + imm32; 3754 else 3755 offset_addr = base - imm32; 3756 3757 address = (index ? offset_addr : base); 3758 3759 Register base_reg; 3760 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + Rn); 3761 if (wback) 3762 { 3763 EmulateInstruction::Context ctx; 3764 ctx.type = EmulateInstruction::eContextAdjustBaseRegister; 3765 ctx.SetRegisterPlusOffset (base_reg, (int32_t) (offset_addr - base)); 3766 3767 if (!WriteRegisterUnsigned (ctx, eRegisterKindDWARF, dwarf_r0 + Rn, offset_addr)) 3768 return false; 3769 } 3770 3771 // Prepare to write to the Rt register. 3772 EmulateInstruction::Context context; 3773 context.type = EmulateInstruction::eContextRegisterLoad; 3774 context.SetRegisterPlusOffset (base_reg, (int32_t) (offset_addr - base)); 3775 3776 // Read memory from the address. 3777 data = MemURead(context, address, 4, 0, &success); 3778 if (!success) 3779 return false; 3780 3781 if (Rt == 15) 3782 { 3783 if (Bits32(address, 1, 0) == 0) 3784 { 3785 if (!LoadWritePC(context, data)) 3786 return false; 3787 } 3788 else 3789 return false; 3790 } 3791 else if (UnalignedSupport() || Bits32(address, 1, 0) == 0) 3792 { 3793 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + Rt, data)) 3794 return false; 3795 } 3796 else 3797 WriteBits32Unknown (Rt); 3798 } 3799 return true; 3800} 3801 3802// STM (Store Multiple Increment After) stores multiple registers to consecutive memory locations using an address 3803// from a base register. The consecutive memory locations start at this address, and teh address just above the last 3804// of those locations can optionally be written back to the base register. 3805bool 3806EmulateInstructionARM::EmulateSTM (const uint32_t opcode, const ARMEncoding encoding) 3807{ 3808#if 0 3809 if ConditionPassed() then 3810 EncodingSpecificOperations(); NullCheckIfThumbEE(n); 3811 address = R[n]; 3812 3813 for i = 0 to 14 3814 if registers<i> == '1' then 3815 if i == n && wback && i != LowestSetBit(registers) then 3816 MemA[address,4] = bits(32) UNKNOWN; // Only possible for encodings T1 and A1 3817 else 3818 MemA[address,4] = R[i]; 3819 address = address + 4; 3820 3821 if registers<15> == '1' then // Only possible for encoding A1 3822 MemA[address,4] = PCStoreValue(); 3823 if wback then R[n] = R[n] + 4*BitCount(registers); 3824#endif 3825 3826 bool success = false; 3827 3828 if (ConditionPassed(opcode)) 3829 { 3830 uint32_t n; 3831 uint32_t registers = 0; 3832 bool wback; 3833 const uint32_t addr_byte_size = GetAddressByteSize(); 3834 3835 // EncodingSpecificOperations(); NullCheckIfThumbEE(n); 3836 switch (encoding) 3837 { 3838 case eEncodingT1: 3839 // n = UInt(Rn); registers = '00000000':register_list; wback = TRUE; 3840 n = Bits32 (opcode, 10, 8); 3841 registers = Bits32 (opcode, 7, 0); 3842 registers = registers & 0x00ff; // Make sure the top 8 bits are zeros. 3843 wback = true; 3844 3845 // if BitCount(registers) < 1 then UNPREDICTABLE; 3846 if (BitCount (registers) < 1) 3847 return false; 3848 3849 break; 3850 3851 case eEncodingT2: 3852 // n = UInt(Rn); registers = '0':M:'0':register_list; wback = (W == '1'); 3853 n = Bits32 (opcode, 19, 16); 3854 registers = Bits32 (opcode, 15, 0); 3855 registers = registers & 0x5fff; // Make sure bits 15 & 13 are zeros. 3856 wback = BitIsSet (opcode, 21); 3857 3858 // if n == 15 || BitCount(registers) < 2 then UNPREDICTABLE; 3859 if ((n == 15) || (BitCount (registers) < 2)) 3860 return false; 3861 3862 // if wback && registers<n> == '1' then UNPREDICTABLE; 3863 if (wback && BitIsSet (registers, n)) 3864 return false; 3865 3866 break; 3867 3868 case eEncodingA1: 3869 // n = UInt(Rn); registers = register_list; wback = (W == '1'); 3870 n = Bits32 (opcode, 19, 16); 3871 registers = Bits32 (opcode, 15, 0); 3872 wback = BitIsSet (opcode, 21); 3873 3874 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE; 3875 if ((n == 15) || (BitCount (registers) < 1)) 3876 return false; 3877 3878 break; 3879 3880 default: 3881 return false; 3882 } 3883 3884 // address = R[n]; 3885 int32_t offset = 0; 3886 const addr_t address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success); 3887 if (!success) 3888 return false; 3889 3890 EmulateInstruction::Context context; 3891 context.type = EmulateInstruction::eContextRegisterStore; 3892 Register base_reg; 3893 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n); 3894 3895 // for i = 0 to 14 3896 int lowest_set_bit = 14; 3897 for (int i = 0; i < 14; ++i) 3898 { 3899 // if registers<i> == '1' then 3900 if (BitIsSet (registers, i)) 3901 { 3902 if (i < lowest_set_bit) 3903 lowest_set_bit = i; 3904 // if i == n && wback && i != LowestSetBit(registers) then 3905 if ((i == n) && wback && (i != lowest_set_bit)) 3906 // MemA[address,4] = bits(32) UNKNOWN; // Only possible for encodings T1 and A1 3907 WriteBits32UnknownToMemory (address + offset); 3908 else 3909 { 3910 // MemA[address,4] = R[i]; 3911 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + i, 0, &success); 3912 if (!success) 3913 return false; 3914 3915 Register data_reg; 3916 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + i); 3917 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, offset); 3918 if (!MemAWrite (context, address + offset, data, addr_byte_size)) 3919 return false; 3920 } 3921 3922 // address = address + 4; 3923 offset += addr_byte_size; 3924 } 3925 } 3926 3927 // if registers<15> == '1' then // Only possible for encoding A1 3928 // MemA[address,4] = PCStoreValue(); 3929 if (BitIsSet (registers, 15)) 3930 { 3931 Register pc_reg; 3932 pc_reg.SetRegister (eRegisterKindDWARF, dwarf_pc); 3933 context.SetRegisterPlusOffset (pc_reg, 8); 3934 const uint32_t pc = ReadCoreReg (PC_REG, &success); 3935 if (!success) 3936 return false; 3937 3938 if (!MemAWrite (context, address + offset, pc, addr_byte_size)) 3939 return false; 3940 } 3941 3942 // if wback then R[n] = R[n] + 4*BitCount(registers); 3943 if (wback) 3944 { 3945 offset = addr_byte_size * BitCount (registers); 3946 context.type = EmulateInstruction::eContextAdjustBaseRegister; 3947 context.SetImmediateSigned (offset); 3948 addr_t data = address + offset; 3949 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, data)) 3950 return false; 3951 } 3952 } 3953 return true; 3954} 3955 3956// STMDA (Store Multiple Decrement After) stores multiple registers to consecutive memory locations using an address 3957// from a base register. The consecutive memory locations end at this address, and the address just below the lowest 3958// of those locations can optionally be written back to the base register. 3959bool 3960EmulateInstructionARM::EmulateSTMDA (const uint32_t opcode, const ARMEncoding encoding) 3961{ 3962#if 0 3963 if ConditionPassed() then 3964 EncodingSpecificOperations(); 3965 address = R[n] - 4*BitCount(registers) + 4; 3966 3967 for i = 0 to 14 3968 if registers<i> == '1' then 3969 if i == n && wback && i != LowestSetBit(registers) then 3970 MemA[address,4] = bits(32) UNKNOWN; 3971 else 3972 MemA[address,4] = R[i]; 3973 address = address + 4; 3974 3975 if registers<15> == '1' then 3976 MemA[address,4] = PCStoreValue(); 3977 3978 if wback then R[n] = R[n] - 4*BitCount(registers); 3979#endif 3980 3981 bool success = false; 3982 3983 if (ConditionPassed(opcode)) 3984 { 3985 uint32_t n; 3986 uint32_t registers = 0; 3987 bool wback; 3988 const uint32_t addr_byte_size = GetAddressByteSize(); 3989 3990 // EncodingSpecificOperations(); 3991 switch (encoding) 3992 { 3993 case eEncodingA1: 3994 // n = UInt(Rn); registers = register_list; wback = (W == '1'); 3995 n = Bits32 (opcode, 19, 16); 3996 registers = Bits32 (opcode, 15, 0); 3997 wback = BitIsSet (opcode, 21); 3998 3999 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE; 4000 if ((n == 15) || (BitCount (registers) < 1)) 4001 return false; 4002 break; 4003 default: 4004 return false; 4005 } 4006 4007 // address = R[n] - 4*BitCount(registers) + 4; 4008 int32_t offset = 0; 4009 addr_t Rn = ReadCoreReg (n, &success); 4010 if (!success) 4011 return false; 4012 4013 addr_t address = Rn - (addr_byte_size * BitCount (registers)) + 4; 4014 4015 EmulateInstruction::Context context; 4016 context.type = EmulateInstruction::eContextRegisterStore; 4017 Register base_reg; 4018 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n); 4019 4020 // for i = 0 to 14 4021 int lowest_bit_set = 14; 4022 for (int i = 0; i < 14; ++i) 4023 { 4024 // if registers<i> == '1' then 4025 if (BitIsSet (registers, i)) 4026 { 4027 if (i < lowest_bit_set) 4028 lowest_bit_set = i; 4029 //if i == n && wback && i != LowestSetBit(registers) then 4030 if ((i == n) && wback && (i != lowest_bit_set)) 4031 // MemA[address,4] = bits(32) UNKNOWN; 4032 WriteBits32UnknownToMemory (address + offset); 4033 else 4034 { 4035 // MemA[address,4] = R[i]; 4036 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + i, 0, &success); 4037 if (!success) 4038 return false; 4039 4040 Register data_reg; 4041 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + i); 4042 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, Rn - (address + offset)); 4043 if (!MemAWrite (context, address + offset, data, addr_byte_size)) 4044 return false; 4045 } 4046 4047 // address = address + 4; 4048 offset += addr_byte_size; 4049 } 4050 } 4051 4052 // if registers<15> == '1' then 4053 // MemA[address,4] = PCStoreValue(); 4054 if (BitIsSet (registers, 15)) 4055 { 4056 Register pc_reg; 4057 pc_reg.SetRegister (eRegisterKindDWARF, dwarf_pc); 4058 context.SetRegisterPlusOffset (pc_reg, 8); 4059 const uint32_t pc = ReadCoreReg (PC_REG, &success); 4060 if (!success) 4061 return false; 4062 4063 if (!MemAWrite (context, address + offset, pc, addr_byte_size)) 4064 return false; 4065 } 4066 4067 // if wback then R[n] = R[n] - 4*BitCount(registers); 4068 if (wback) 4069 { 4070 offset = (addr_byte_size * BitCount (registers)) * -1; 4071 context.type = EmulateInstruction::eContextAdjustBaseRegister; 4072 context.SetImmediateSigned (offset); 4073 addr_t data = Rn + offset; 4074 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, data)) 4075 return false; 4076 } 4077 } 4078 return true; 4079} 4080 4081// STMDB (Store Multiple Decrement Before) stores multiple registers to consecutive memory locations using an address 4082// from a base register. The consecutive memory locations end just below this address, and the address of the first of 4083// those locations can optionally be written back to the base register. 4084bool 4085EmulateInstructionARM::EmulateSTMDB (const uint32_t opcode, const ARMEncoding encoding) 4086{ 4087#if 0 4088 if ConditionPassed() then 4089 EncodingSpecificOperations(); NullCheckIfThumbEE(n); 4090 address = R[n] - 4*BitCount(registers); 4091 4092 for i = 0 to 14 4093 if registers<i> == '1' then 4094 if i == n && wback && i != LowestSetBit(registers) then 4095 MemA[address,4] = bits(32) UNKNOWN; // Only possible for encoding A1 4096 else 4097 MemA[address,4] = R[i]; 4098 address = address + 4; 4099 4100 if registers<15> == '1' then // Only possible for encoding A1 4101 MemA[address,4] = PCStoreValue(); 4102 4103 if wback then R[n] = R[n] - 4*BitCount(registers); 4104#endif 4105 4106 4107 bool success = false; 4108 4109 if (ConditionPassed(opcode)) 4110 { 4111 uint32_t n; 4112 uint32_t registers = 0; 4113 bool wback; 4114 const uint32_t addr_byte_size = GetAddressByteSize(); 4115 4116 // EncodingSpecificOperations(); NullCheckIfThumbEE(n); 4117 switch (encoding) 4118 { 4119 case eEncodingT1: 4120 // if W == '1' && Rn == '1101' then SEE PUSH; 4121 if ((BitIsSet (opcode, 21)) && (Bits32 (opcode, 19, 16) == 13)) 4122 { 4123 // See PUSH 4124 } 4125 // n = UInt(Rn); registers = '0':M:'0':register_list; wback = (W == '1'); 4126 n = Bits32 (opcode, 19, 16); 4127 registers = Bits32 (opcode, 15, 0); 4128 registers = registers & 0x5fff; // Make sure bits 15 & 13 are zeros. 4129 wback = BitIsSet (opcode, 21); 4130 // if n == 15 || BitCount(registers) < 2 then UNPREDICTABLE; 4131 if ((n == 15) || BitCount (registers) < 2) 4132 return false; 4133 // if wback && registers<n> == '1' then UNPREDICTABLE; 4134 if (wback && BitIsSet (registers, n)) 4135 return false; 4136 break; 4137 4138 case eEncodingA1: 4139 // if W == '1' && Rn == '1101’ && BitCount(register_list) >= 2 then SEE PUSH; 4140 if (BitIsSet (opcode, 21) && (Bits32 (opcode, 19, 16) == 13) && BitCount (Bits32 (opcode, 15, 0)) >= 2) 4141 { 4142 // See Push 4143 } 4144 // n = UInt(Rn); registers = register_list; wback = (W == '1'); 4145 n = Bits32 (opcode, 19, 16); 4146 registers = Bits32 (opcode, 15, 0); 4147 wback = BitIsSet (opcode, 21); 4148 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE; 4149 if ((n == 15) || BitCount (registers) < 1) 4150 return false; 4151 break; 4152 4153 default: 4154 return false; 4155 } 4156 4157 // address = R[n] - 4*BitCount(registers); 4158 4159 int32_t offset = 0; 4160 addr_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success); 4161 if (!success) 4162 return false; 4163 4164 addr_t address = Rn - (addr_byte_size * BitCount (registers)); 4165 4166 EmulateInstruction::Context context; 4167 context.type = EmulateInstruction::eContextRegisterStore; 4168 Register base_reg; 4169 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n); 4170 4171 // for i = 0 to 14 4172 uint32_t lowest_set_bit = 14; 4173 for (int i = 0; i < 14; ++i) 4174 { 4175 // if registers<i> == '1' then 4176 if (BitIsSet (registers, i)) 4177 { 4178 if (i < lowest_set_bit) 4179 lowest_set_bit = i; 4180 // if i == n && wback && i != LowestSetBit(registers) then 4181 if ((i == n) && wback && (i != lowest_set_bit)) 4182 // MemA[address,4] = bits(32) UNKNOWN; // Only possible for encoding A1 4183 WriteBits32UnknownToMemory (address + offset); 4184 else 4185 { 4186 // MemA[address,4] = R[i]; 4187 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + i, 0, &success); 4188 if (!success) 4189 return false; 4190 4191 Register data_reg; 4192 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + i); 4193 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, Rn - (address + offset)); 4194 if (!MemAWrite (context, address + offset, data, addr_byte_size)) 4195 return false; 4196 } 4197 4198 // address = address + 4; 4199 offset += addr_byte_size; 4200 } 4201 } 4202 4203 // if registers<15> == '1' then // Only possible for encoding A1 4204 // MemA[address,4] = PCStoreValue(); 4205 if (BitIsSet (registers, 15)) 4206 { 4207 Register pc_reg; 4208 pc_reg.SetRegister (eRegisterKindDWARF, dwarf_pc); 4209 context.SetRegisterPlusOffset (pc_reg, 8); 4210 const uint32_t pc = ReadCoreReg (PC_REG, &success); 4211 if (!success) 4212 return false; 4213 4214 if (!MemAWrite (context, address + offset, pc, addr_byte_size)) 4215 return false; 4216 } 4217 4218 // if wback then R[n] = R[n] - 4*BitCount(registers); 4219 if (wback) 4220 { 4221 offset = (addr_byte_size * BitCount (registers)) * -1; 4222 context.type = EmulateInstruction::eContextAdjustBaseRegister; 4223 context.SetImmediateSigned (offset); 4224 addr_t data = Rn + offset; 4225 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, data)) 4226 return false; 4227 } 4228 } 4229 return true; 4230} 4231 4232// STMIB (Store Multiple Increment Before) stores multiple registers to consecutive memory locations using an address 4233// from a base register. The consecutive memory locations start just above this address, and the address of the last 4234// of those locations can optionally be written back to the base register. 4235bool 4236EmulateInstructionARM::EmulateSTMIB (const uint32_t opcode, const ARMEncoding encoding) 4237{ 4238#if 0 4239 if ConditionPassed() then 4240 EncodingSpecificOperations(); 4241 address = R[n] + 4; 4242 4243 for i = 0 to 14 4244 if registers<i> == '1' then 4245 if i == n && wback && i != LowestSetBit(registers) then 4246 MemA[address,4] = bits(32) UNKNOWN; 4247 else 4248 MemA[address,4] = R[i]; 4249 address = address + 4; 4250 4251 if registers<15> == '1' then 4252 MemA[address,4] = PCStoreValue(); 4253 4254 if wback then R[n] = R[n] + 4*BitCount(registers); 4255#endif 4256 4257 bool success = false; 4258 4259 if (ConditionPassed(opcode)) 4260 { 4261 uint32_t n; 4262 uint32_t registers = 0; 4263 bool wback; 4264 const uint32_t addr_byte_size = GetAddressByteSize(); 4265 4266 // EncodingSpecificOperations(); 4267 switch (encoding) 4268 { 4269 case eEncodingA1: 4270 // n = UInt(Rn); registers = register_list; wback = (W == '1'); 4271 n = Bits32 (opcode, 19, 16); 4272 registers = Bits32 (opcode, 15, 0); 4273 wback = BitIsSet (opcode, 21); 4274 4275 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE; 4276 if ((n == 15) && (BitCount (registers) < 1)) 4277 return false; 4278 break; 4279 default: 4280 return false; 4281 } 4282 // address = R[n] + 4; 4283 4284 int32_t offset = 0; 4285 addr_t Rn = ReadCoreReg (n, &success); 4286 if (!success) 4287 return false; 4288 4289 addr_t address = Rn + addr_byte_size; 4290 4291 EmulateInstruction::Context context; 4292 context.type = EmulateInstruction::eContextRegisterStore; 4293 Register base_reg; 4294 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n); 4295 4296 uint32_t lowest_set_bit = 14; 4297 // for i = 0 to 14 4298 for (int i = 0; i < 14; ++i) 4299 { 4300 // if registers<i> == '1' then 4301 if (BitIsSet (registers, i)) 4302 { 4303 if (i < lowest_set_bit) 4304 lowest_set_bit = i; 4305 // if i == n && wback && i != LowestSetBit(registers) then 4306 if ((i == n) && wback && (i != lowest_set_bit)) 4307 // MemA[address,4] = bits(32) UNKNOWN; 4308 WriteBits32UnknownToMemory (address + offset); 4309 // else 4310 else 4311 { 4312 // MemA[address,4] = R[i]; 4313 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + i, 0, &success); 4314 if (!success) 4315 return false; 4316 4317 Register data_reg; 4318 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + i); 4319 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, offset + addr_byte_size); 4320 if (!MemAWrite (context, address + offset, data, addr_byte_size)) 4321 return false; 4322 } 4323 4324 // address = address + 4; 4325 offset += addr_byte_size; 4326 } 4327 } 4328 4329 // if registers<15> == '1' then 4330 // MemA[address,4] = PCStoreValue(); 4331 if (BitIsSet (registers, 15)) 4332 { 4333 Register pc_reg; 4334 pc_reg.SetRegister (eRegisterKindDWARF, dwarf_pc); 4335 context.SetRegisterPlusOffset (pc_reg, 8); 4336 const uint32_t pc = ReadCoreReg (PC_REG, &success); 4337 if (!success) 4338 return false; 4339 4340 if (!MemAWrite (context, address + offset, pc, addr_byte_size)) 4341 return false; 4342 } 4343 4344 // if wback then R[n] = R[n] + 4*BitCount(registers); 4345 if (wback) 4346 { 4347 offset = addr_byte_size * BitCount (registers); 4348 context.type = EmulateInstruction::eContextAdjustBaseRegister; 4349 context.SetImmediateSigned (offset); 4350 addr_t data = Rn + offset; 4351 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, data)) 4352 return false; 4353 } 4354 } 4355 return true; 4356} 4357 4358// STR (store immediate) calcualtes an address from a base register value and an immediate offset, and stores a word 4359// from a register to memory. It can use offset, post-indexed, or pre-indexed addressing. 4360bool 4361EmulateInstructionARM::EmulateSTRThumb (const uint32_t opcode, const ARMEncoding encoding) 4362{ 4363#if 0 4364 if ConditionPassed() then 4365 EncodingSpecificOperations(); NullCheckIfThumbEE(n); 4366 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32); 4367 address = if index then offset_addr else R[n]; 4368 if UnalignedSupport() || address<1:0> == '00' then 4369 MemU[address,4] = R[t]; 4370 else // Can only occur before ARMv7 4371 MemU[address,4] = bits(32) UNKNOWN; 4372 if wback then R[n] = offset_addr; 4373#endif 4374 4375 bool success = false; 4376 4377 if (ConditionPassed(opcode)) 4378 { 4379 const uint32_t addr_byte_size = GetAddressByteSize(); 4380 4381 uint32_t t; 4382 uint32_t n; 4383 uint32_t imm32; 4384 bool index; 4385 bool add; 4386 bool wback; 4387 // EncodingSpecificOperations (); NullCheckIfThumbEE(n); 4388 switch (encoding) 4389 { 4390 case eEncodingT1: 4391 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm5:'00', 32); 4392 t = Bits32 (opcode, 2, 0); 4393 n = Bits32 (opcode, 5, 3); 4394 imm32 = Bits32 (opcode, 10, 6) << 2; 4395 4396 // index = TRUE; add = TRUE; wback = FALSE; 4397 index = true; 4398 add = false; 4399 wback = false; 4400 break; 4401 4402 case eEncodingT2: 4403 // t = UInt(Rt); n = 13; imm32 = ZeroExtend(imm8:'00', 32); 4404 t = Bits32 (opcode, 10, 8); 4405 n = 13; 4406 imm32 = Bits32 (opcode, 7, 0) << 2; 4407 4408 // index = TRUE; add = TRUE; wback = FALSE; 4409 index = true; 4410 add = true; 4411 wback = false; 4412 break; 4413 4414 case eEncodingT3: 4415 // if Rn == '1111' then UNDEFINED; 4416 if (Bits32 (opcode, 19, 16) == 15) 4417 return false; 4418 4419 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32); 4420 t = Bits32 (opcode, 15, 12); 4421 n = Bits32 (opcode, 19, 16); 4422 imm32 = Bits32 (opcode, 11, 0); 4423 4424 // index = TRUE; add = TRUE; wback = FALSE; 4425 index = true; 4426 add = true; 4427 wback = false; 4428 4429 // if t == 15 then UNPREDICTABLE; 4430 if (t == 15) 4431 return false; 4432 break; 4433 4434 case eEncodingT4: 4435 // if P == '1' && U == '1' && W == '0' then SEE STRT; 4436 // if Rn == '1101' && P == '1' && U == '0' && W == '1' && imm8 == '00000100' then SEE PUSH; 4437 // if Rn == '1111' || (P == '0' && W == '0') then UNDEFINED; 4438 if ((Bits32 (opcode, 19, 16) == 15) 4439 || (BitIsClear (opcode, 10) && BitIsClear (opcode, 8))) 4440 return false; 4441 4442 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32); 4443 t = Bits32 (opcode, 15, 12); 4444 n = Bits32 (opcode, 19, 16); 4445 imm32 = Bits32 (opcode, 7, 0); 4446 4447 // index = (P == '1'); add = (U == '1'); wback = (W == '1'); 4448 index = BitIsSet (opcode, 10); 4449 add = BitIsSet (opcode, 9); 4450 wback = BitIsSet (opcode, 8); 4451 4452 // if t == 15 || (wback && n == t) then UNPREDICTABLE; 4453 if ((t == 15) || (wback && (n == t))) 4454 return false; 4455 break; 4456 4457 default: 4458 return false; 4459 } 4460 4461 addr_t offset_addr; 4462 addr_t address; 4463 4464 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32); 4465 uint32_t base_address = ReadCoreReg (n, &success); 4466 if (!success) 4467 return false; 4468 4469 if (add) 4470 offset_addr = base_address + imm32; 4471 else 4472 offset_addr = base_address - imm32; 4473 4474 // address = if index then offset_addr else R[n]; 4475 if (index) 4476 address = offset_addr; 4477 else 4478 address = base_address; 4479 4480 EmulateInstruction::Context context; 4481 context.type = eContextRegisterStore; 4482 Register base_reg; 4483 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n); 4484 4485 // if UnalignedSupport() || address<1:0> == '00' then 4486 if (UnalignedSupport () || (BitIsClear (address, 1) && BitIsClear (address, 0))) 4487 { 4488 // MemU[address,4] = R[t]; 4489 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + t, 0, &success); 4490 if (!success) 4491 return false; 4492 4493 Register data_reg; 4494 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + t); 4495 int32_t offset = address - base_address; 4496 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, offset); 4497 if (!MemUWrite (context, address, data, addr_byte_size)) 4498 return false; 4499 } 4500 else 4501 { 4502 // MemU[address,4] = bits(32) UNKNOWN; 4503 WriteBits32UnknownToMemory (address); 4504 } 4505 4506 // if wback then R[n] = offset_addr; 4507 if (wback) 4508 { 4509 context.type = eContextRegisterLoad; 4510 context.SetAddress (offset_addr); 4511 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr)) 4512 return false; 4513 } 4514 } 4515 return true; 4516} 4517 4518// STR (Store Register) calculates an address from a base register value and an offset register value, stores a 4519// word from a register to memory. The offset register value can optionally be shifted. 4520bool 4521EmulateInstructionARM::EmulateSTRRegister (const uint32_t opcode, const ARMEncoding encoding) 4522{ 4523#if 0 4524 if ConditionPassed() then 4525 EncodingSpecificOperations(); NullCheckIfThumbEE(n); 4526 offset = Shift(R[m], shift_t, shift_n, APSR.C); 4527 offset_addr = if add then (R[n] + offset) else (R[n] - offset); 4528 address = if index then offset_addr else R[n]; 4529 if t == 15 then // Only possible for encoding A1 4530 data = PCStoreValue(); 4531 else 4532 data = R[t]; 4533 if UnalignedSupport() || address<1:0> == '00' || CurrentInstrSet() == InstrSet_ARM then 4534 MemU[address,4] = data; 4535 else // Can only occur before ARMv7 4536 MemU[address,4] = bits(32) UNKNOWN; 4537 if wback then R[n] = offset_addr; 4538#endif 4539 4540 bool success = false; 4541 4542 if (ConditionPassed(opcode)) 4543 { 4544 const uint32_t addr_byte_size = GetAddressByteSize(); 4545 4546 uint32_t t; 4547 uint32_t n; 4548 uint32_t m; 4549 ARM_ShifterType shift_t; 4550 uint32_t shift_n; 4551 bool index; 4552 bool add; 4553 bool wback; 4554 4555 // EncodingSpecificOperations (); NullCheckIfThumbEE(n); 4556 switch (encoding) 4557 { 4558 case eEncodingT1: 4559 // if CurrentInstrSet() == InstrSet_ThumbEE then SEE "Modified operation in ThumbEE"; 4560 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm); 4561 t = Bits32 (opcode, 2, 0); 4562 n = Bits32 (opcode, 5, 3); 4563 m = Bits32 (opcode, 8, 6); 4564 4565 // index = TRUE; add = TRUE; wback = FALSE; 4566 index = true; 4567 add = true; 4568 wback = false; 4569 4570 // (shift_t, shift_n) = (SRType_LSL, 0); 4571 shift_t = SRType_LSL; 4572 shift_n = 0; 4573 break; 4574 4575 case eEncodingT2: 4576 // if Rn == '1111' then UNDEFINED; 4577 if (Bits32 (opcode, 19, 16) == 15) 4578 return false; 4579 4580 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm); 4581 t = Bits32 (opcode, 15, 12); 4582 n = Bits32 (opcode, 19, 16); 4583 m = Bits32 (opcode, 3, 0); 4584 4585 // index = TRUE; add = TRUE; wback = FALSE; 4586 index = true; 4587 add = true; 4588 wback = false; 4589 4590 // (shift_t, shift_n) = (SRType_LSL, UInt(imm2)); 4591 shift_t = SRType_LSL; 4592 shift_n = Bits32 (opcode, 5, 4); 4593 4594 // if t == 15 || BadReg(m) then UNPREDICTABLE; 4595 if ((t == 15) || (BadReg (m))) 4596 return false; 4597 break; 4598 4599 case eEncodingA1: 4600 { 4601 // if P == '0' && W == '1' then SEE STRT; 4602 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm); 4603 t = Bits32 (opcode, 15, 12); 4604 n = Bits32 (opcode, 19, 16); 4605 m = Bits32 (opcode, 3, 0); 4606 4607 // index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1'); 4608 index = BitIsSet (opcode, 24); 4609 add = BitIsSet (opcode, 23); 4610 wback = (BitIsClear (opcode, 24) || BitIsSet (opcode, 21)); 4611 4612 // (shift_t, shift_n) = DecodeImmShift(type, imm5); 4613 uint32_t typ = Bits32 (opcode, 6, 5); 4614 uint32_t imm5 = Bits32 (opcode, 11, 7); 4615 shift_n = DecodeImmShift(typ, imm5, shift_t); 4616 4617 // if m == 15 then UNPREDICTABLE; 4618 if (m == 15) 4619 return false; 4620 4621 // if wback && (n == 15 || n == t) then UNPREDICTABLE; 4622 if (wback && ((n == 15) || (n == t))) 4623 return false; 4624 4625 break; 4626 } 4627 default: 4628 return false; 4629 } 4630 4631 addr_t offset_addr; 4632 addr_t address; 4633 int32_t offset = 0; 4634 4635 addr_t base_address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success); 4636 if (!success) 4637 return false; 4638 4639 uint32_t Rm_data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success); 4640 if (!success) 4641 return false; 4642 4643 // offset = Shift(R[m], shift_t, shift_n, APSR.C); 4644 offset = Shift (Rm_data, shift_t, shift_n, APSR_C); 4645 4646 // offset_addr = if add then (R[n] + offset) else (R[n] - offset); 4647 if (add) 4648 offset_addr = base_address + offset; 4649 else 4650 offset_addr = base_address - offset; 4651 4652 // address = if index then offset_addr else R[n]; 4653 if (index) 4654 address = offset_addr; 4655 else 4656 address = base_address; 4657 4658 uint32_t data; 4659 // if t == 15 then // Only possible for encoding A1 4660 if (t == 15) 4661 // data = PCStoreValue(); 4662 data = ReadCoreReg (PC_REG, &success); 4663 else 4664 // data = R[t]; 4665 data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + t, 0, &success); 4666 4667 if (!success) 4668 return false; 4669 4670 EmulateInstruction::Context context; 4671 context.type = eContextRegisterStore; 4672 4673 // if UnalignedSupport() || address<1:0> == '00' || CurrentInstrSet() == InstrSet_ARM then 4674 if (UnalignedSupport () 4675 || (BitIsClear (address, 1) && BitIsClear (address, 0)) 4676 || CurrentInstrSet() == eModeARM) 4677 { 4678 // MemU[address,4] = data; 4679 4680 Register base_reg; 4681 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n); 4682 4683 Register data_reg; 4684 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + t); 4685 4686 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, address - base_address); 4687 if (!MemUWrite (context, address, data, addr_byte_size)) 4688 return false; 4689 4690 } 4691 else 4692 // MemU[address,4] = bits(32) UNKNOWN; 4693 WriteBits32UnknownToMemory (address); 4694 4695 // if wback then R[n] = offset_addr; 4696 if (wback) 4697 { 4698 context.type = eContextRegisterLoad; 4699 context.SetAddress (offset_addr); 4700 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr)) 4701 return false; 4702 } 4703 4704 } 4705 return true; 4706} 4707 4708bool 4709EmulateInstructionARM::EmulateSTRBThumb (const uint32_t opcode, const ARMEncoding encoding) 4710{ 4711#if 0 4712 if ConditionPassed() then 4713 EncodingSpecificOperations(); NullCheckIfThumbEE(n); 4714 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32); 4715 address = if index then offset_addr else R[n]; 4716 MemU[address,1] = R[t]<7:0>; 4717 if wback then R[n] = offset_addr; 4718#endif 4719 4720 4721 bool success = false; 4722 4723 if (ConditionPassed(opcode)) 4724 { 4725 uint32_t t; 4726 uint32_t n; 4727 uint32_t imm32; 4728 bool index; 4729 bool add; 4730 bool wback; 4731 // EncodingSpecificOperations(); NullCheckIfThumbEE(n); 4732 switch (encoding) 4733 { 4734 case eEncodingT1: 4735 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm5, 32); 4736 t = Bits32 (opcode, 2, 0); 4737 n = Bits32 (opcode, 5, 3); 4738 imm32 = Bits32 (opcode, 10, 6); 4739 4740 // index = TRUE; add = TRUE; wback = FALSE; 4741 index = true; 4742 add = true; 4743 wback = false; 4744 break; 4745 4746 case eEncodingT2: 4747 // if Rn == '1111' then UNDEFINED; 4748 if (Bits32 (opcode, 19, 16) == 15) 4749 return false; 4750 4751 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32); 4752 t = Bits32 (opcode, 15, 12); 4753 n = Bits32 (opcode, 19, 16); 4754 imm32 = Bits32 (opcode, 11, 0); 4755 4756 // index = TRUE; add = TRUE; wback = FALSE; 4757 index = true; 4758 add = true; 4759 wback = false; 4760 4761 // if BadReg(t) then UNPREDICTABLE; 4762 if (BadReg (t)) 4763 return false; 4764 break; 4765 4766 case eEncodingT3: 4767 // if P == '1' && U == '1' && W == '0' then SEE STRBT; 4768 // if Rn == '1111' || (P == '0' && W == '0') then UNDEFINED; 4769 if (Bits32 (opcode, 19, 16) == 15) 4770 return false; 4771 4772 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32); 4773 t = Bits32 (opcode, 15, 12); 4774 n = Bits32 (opcode, 19, 16); 4775 imm32 = Bits32 (opcode, 7, 0); 4776 4777 // index = (P == '1'); add = (U == '1'); wback = (W == '1'); 4778 index = BitIsSet (opcode, 10); 4779 add = BitIsSet (opcode, 9); 4780 wback = BitIsSet (opcode, 8); 4781 4782 // if BadReg(t) || (wback && n == t) then UNPREDICTABLE 4783 if ((BadReg (t)) || (wback && (n == t))) 4784 return false; 4785 break; 4786 4787 default: 4788 return false; 4789 } 4790 4791 addr_t offset_addr; 4792 addr_t address; 4793 addr_t base_address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success); 4794 if (!success) 4795 return false; 4796 4797 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32); 4798 if (add) 4799 offset_addr = base_address + imm32; 4800 else 4801 offset_addr = base_address - imm32; 4802 4803 // address = if index then offset_addr else R[n]; 4804 if (index) 4805 address = offset_addr; 4806 else 4807 address = base_address; 4808 4809 // MemU[address,1] = R[t]<7:0> 4810 Register base_reg; 4811 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n); 4812 4813 Register data_reg; 4814 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + t); 4815 4816 EmulateInstruction::Context context; 4817 context.type = eContextRegisterStore; 4818 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, address - base_address); 4819 4820 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + t, 0, &success); 4821 if (!success) 4822 return false; 4823 4824 data = Bits32 (data, 7, 0); 4825 4826 if (!MemUWrite (context, address, data, 1)) 4827 return false; 4828 4829 // if wback then R[n] = offset_addr; 4830 if (wback) 4831 { 4832 context.type = eContextRegisterLoad; 4833 context.SetAddress (offset_addr); 4834 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr)) 4835 return false; 4836 } 4837 4838 } 4839 4840 return true; 4841} 4842 4843// STRH (register) calculates an address from a base register value and an offset register value, and stores a 4844// halfword from a register to memory. The offset register alue can be shifted left by 0, 1, 2, or 3 bits. 4845bool 4846EmulateInstructionARM::EmulateSTRHRegister (const uint32_t opcode, const ARMEncoding encoding) 4847{ 4848#if 0 4849 if ConditionPassed() then 4850 EncodingSpecificOperations(); NullCheckIfThumbEE(n); 4851 offset = Shift(R[m], shift_t, shift_n, APSR.C); 4852 offset_addr = if add then (R[n] + offset) else (R[n] - offset); 4853 address = if index then offset_addr else R[n]; 4854 if UnalignedSupport() || address<0> == '0' then 4855 MemU[address,2] = R[t]<15:0>; 4856 else // Can only occur before ARMv7 4857 MemU[address,2] = bits(16) UNKNOWN; 4858 if wback then R[n] = offset_addr; 4859#endif 4860 4861 bool success = false; 4862 4863 if (ConditionPassed(opcode)) 4864 { 4865 uint32_t t; 4866 uint32_t n; 4867 uint32_t m; 4868 bool index; 4869 bool add; 4870 bool wback; 4871 ARM_ShifterType shift_t; 4872 uint32_t shift_n; 4873 4874 // EncodingSpecificOperations(); NullCheckIfThumbEE(n); 4875 switch (encoding) 4876 { 4877 case eEncodingT1: 4878 // if CurrentInstrSet() == InstrSet_ThumbEE then SEE "Modified operation in ThumbEE"; 4879 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm); 4880 t = Bits32 (opcode, 2, 0); 4881 n = Bits32 (opcode, 5, 3); 4882 m = Bits32 (opcode, 8, 6); 4883 4884 // index = TRUE; add = TRUE; wback = FALSE; 4885 index = true; 4886 add = true; 4887 wback = false; 4888 4889 // (shift_t, shift_n) = (SRType_LSL, 0); 4890 shift_t = SRType_LSL; 4891 shift_n = 0; 4892 4893 break; 4894 4895 case eEncodingT2: 4896 // if Rn == '1111' then UNDEFINED; 4897 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm); 4898 t = Bits32 (opcode, 15, 12); 4899 n = Bits32 (opcode, 19, 16); 4900 m = Bits32 (opcode, 3, 0); 4901 if (n == 15) 4902 return false; 4903 4904 // index = TRUE; add = TRUE; wback = FALSE; 4905 index = true; 4906 add = true; 4907 wback = false; 4908 4909 // (shift_t, shift_n) = (SRType_LSL, UInt(imm2)); 4910 shift_t = SRType_LSL; 4911 shift_n = Bits32 (opcode, 5, 4); 4912 4913 // if BadReg(t) || BadReg(m) then UNPREDICTABLE; 4914 if (BadReg (t) || BadReg (m)) 4915 return false; 4916 4917 break; 4918 4919 case eEncodingA1: 4920 // if P == '0' && W == '1' then SEE STRHT; 4921 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm); 4922 t = Bits32 (opcode, 15, 12); 4923 n = Bits32 (opcode, 19, 16); 4924 m = Bits32 (opcode, 3, 0); 4925 4926 // index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1'); 4927 index = BitIsSet (opcode, 24); 4928 add = BitIsSet (opcode, 23); 4929 wback = (BitIsClear (opcode, 24) || BitIsSet (opcode, 21)); 4930 4931 // (shift_t, shift_n) = (SRType_LSL, 0); 4932 shift_t = SRType_LSL; 4933 shift_n = 0; 4934 4935 // if t == 15 || m == 15 then UNPREDICTABLE; 4936 if ((t == 15) || (m == 15)) 4937 return false; 4938 4939 // if wback && (n == 15 || n == t) then UNPREDICTABLE; 4940 if (wback && ((n == 15) || (n == t))) 4941 return false; 4942 4943 break; 4944 4945 default: 4946 return false; 4947 } 4948 4949 uint32_t Rm = ReadCoreReg (m, &success); 4950 if (!success) 4951 return false; 4952 4953 uint32_t Rn = ReadCoreReg (n, &success); 4954 if (!success) 4955 return false; 4956 4957 // offset = Shift(R[m], shift_t, shift_n, APSR.C); 4958 uint32_t offset = Shift (Rm, shift_t, shift_n, APSR_C); 4959 4960 // offset_addr = if add then (R[n] + offset) else (R[n] - offset); 4961 addr_t offset_addr; 4962 if (add) 4963 offset_addr = Rn + offset; 4964 else 4965 offset_addr = Rn - offset; 4966 4967 // address = if index then offset_addr else R[n]; 4968 addr_t address; 4969 if (index) 4970 address = offset_addr; 4971 else 4972 address = Rn; 4973 4974 EmulateInstruction::Context context; 4975 context.type = eContextRegisterStore; 4976 Register base_reg; 4977 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n); 4978 Register offset_reg; 4979 offset_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + m); 4980 4981 // if UnalignedSupport() || address<0> == '0' then 4982 if (UnalignedSupport() || BitIsClear (address, 0)) 4983 { 4984 // MemU[address,2] = R[t]<15:0>; 4985 uint32_t Rt = ReadCoreReg (t, &success); 4986 if (!success) 4987 return false; 4988 4989 EmulateInstruction::Context context; 4990 context.type = eContextRegisterStore; 4991 Register base_reg; 4992 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n); 4993 Register offset_reg; 4994 offset_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + m); 4995 Register data_reg; 4996 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + t); 4997 context.SetRegisterToRegisterPlusIndirectOffset (base_reg, offset_reg, data_reg); 4998 4999 if (!MemUWrite (context, address, Bits32 (Rt, 15, 0), 2)) 5000 return false; 5001 } 5002 else // Can only occur before ARMv7 5003 { 5004 // MemU[address,2] = bits(16) UNKNOWN; 5005 } 5006 5007 // if wback then R[n] = offset_addr; 5008 if (wback) 5009 { 5010 context.type = eContextAdjustBaseRegister; 5011 context.SetAddress (offset_addr); 5012 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr)) 5013 return false; 5014 } 5015 } 5016 5017 return true; 5018} 5019 5020// Add with Carry (immediate) adds an immediate value and the carry flag value to a register value, 5021// and writes the result to the destination register. It can optionally update the condition flags 5022// based on the result. 5023bool 5024EmulateInstructionARM::EmulateADCImm (const uint32_t opcode, const ARMEncoding encoding) 5025{ 5026#if 0 5027 // ARM pseudo code... 5028 if ConditionPassed() then 5029 EncodingSpecificOperations(); 5030 (result, carry, overflow) = AddWithCarry(R[n], imm32, APSR.C); 5031 if d == 15 then // Can only occur for ARM encoding 5032 ALUWritePC(result); // setflags is always FALSE here 5033 else 5034 R[d] = result; 5035 if setflags then 5036 APSR.N = result<31>; 5037 APSR.Z = IsZeroBit(result); 5038 APSR.C = carry; 5039 APSR.V = overflow; 5040#endif 5041 5042 bool success = false; 5043 5044 if (ConditionPassed(opcode)) 5045 { 5046 uint32_t Rd, Rn; 5047 uint32_t imm32; // the immediate value to be added to the value obtained from Rn 5048 bool setflags; 5049 switch (encoding) 5050 { 5051 case eEncodingT1: 5052 Rd = Bits32(opcode, 11, 8); 5053 Rn = Bits32(opcode, 19, 16); 5054 setflags = BitIsSet(opcode, 20); 5055 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8) 5056 if (BadReg(Rd) || BadReg(Rn)) 5057 return false; 5058 break; 5059 case eEncodingA1: 5060 Rd = Bits32(opcode, 15, 12); 5061 Rn = Bits32(opcode, 19, 16); 5062 setflags = BitIsSet(opcode, 20); 5063 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12) 5064 // TODO: Emulate SUBS PC, LR and related instructions. 5065 if (Rd == 15 && setflags) 5066 return false; 5067 break; 5068 default: 5069 return false; 5070 } 5071 5072 // Read the first operand. 5073 int32_t val1 = ReadCoreReg(Rn, &success); 5074 if (!success) 5075 return false; 5076 5077 AddWithCarryResult res = AddWithCarry(val1, imm32, APSR_C); 5078 5079 EmulateInstruction::Context context; 5080 context.type = EmulateInstruction::eContextImmediate; 5081 context.SetNoArgs (); 5082 5083 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow)) 5084 return false; 5085 } 5086 return true; 5087} 5088 5089// Add with Carry (register) adds a register value, the carry flag value, and an optionally-shifted 5090// register value, and writes the result to the destination register. It can optionally update the 5091// condition flags based on the result. 5092bool 5093EmulateInstructionARM::EmulateADCReg (const uint32_t opcode, const ARMEncoding encoding) 5094{ 5095#if 0 5096 // ARM pseudo code... 5097 if ConditionPassed() then 5098 EncodingSpecificOperations(); 5099 shifted = Shift(R[m], shift_t, shift_n, APSR.C); 5100 (result, carry, overflow) = AddWithCarry(R[n], shifted, APSR.C); 5101 if d == 15 then // Can only occur for ARM encoding 5102 ALUWritePC(result); // setflags is always FALSE here 5103 else 5104 R[d] = result; 5105 if setflags then 5106 APSR.N = result<31>; 5107 APSR.Z = IsZeroBit(result); 5108 APSR.C = carry; 5109 APSR.V = overflow; 5110#endif 5111 5112 bool success = false; 5113 5114 if (ConditionPassed(opcode)) 5115 { 5116 uint32_t Rd, Rn, Rm; 5117 ARM_ShifterType shift_t; 5118 uint32_t shift_n; // the shift applied to the value read from Rm 5119 bool setflags; 5120 switch (encoding) 5121 { 5122 case eEncodingT1: 5123 Rd = Rn = Bits32(opcode, 2, 0); 5124 Rm = Bits32(opcode, 5, 3); 5125 setflags = !InITBlock(); 5126 shift_t = SRType_LSL; 5127 shift_n = 0; 5128 break; 5129 case eEncodingT2: 5130 Rd = Bits32(opcode, 11, 8); 5131 Rn = Bits32(opcode, 19, 16); 5132 Rm = Bits32(opcode, 3, 0); 5133 setflags = BitIsSet(opcode, 20); 5134 shift_n = DecodeImmShiftThumb(opcode, shift_t); 5135 if (BadReg(Rd) || BadReg(Rn) || BadReg(Rm)) 5136 return false; 5137 break; 5138 case eEncodingA1: 5139 Rd = Bits32(opcode, 15, 12); 5140 Rn = Bits32(opcode, 19, 16); 5141 Rm = Bits32(opcode, 3, 0); 5142 setflags = BitIsSet(opcode, 20); 5143 shift_n = DecodeImmShiftARM(opcode, shift_t); 5144 // TODO: Emulate SUBS PC, LR and related instructions. 5145 if (Rd == 15 && setflags) 5146 return false; 5147 break; 5148 default: 5149 return false; 5150 } 5151 5152 // Read the first operand. 5153 int32_t val1 = ReadCoreReg(Rn, &success); 5154 if (!success) 5155 return false; 5156 5157 // Read the second operand. 5158 int32_t val2 = ReadCoreReg(Rm, &success); 5159 if (!success) 5160 return false; 5161 5162 uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C); 5163 AddWithCarryResult res = AddWithCarry(val1, shifted, APSR_C); 5164 5165 EmulateInstruction::Context context; 5166 context.type = EmulateInstruction::eContextImmediate; 5167 context.SetNoArgs (); 5168 5169 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow)) 5170 return false; 5171 } 5172 return true; 5173} 5174 5175// This instruction adds an immediate value to the PC value to form a PC-relative address, 5176// and writes the result to the destination register. 5177bool 5178EmulateInstructionARM::EmulateADR (const uint32_t opcode, const ARMEncoding encoding) 5179{ 5180#if 0 5181 // ARM pseudo code... 5182 if ConditionPassed() then 5183 EncodingSpecificOperations(); 5184 result = if add then (Align(PC,4) + imm32) else (Align(PC,4) - imm32); 5185 if d == 15 then // Can only occur for ARM encodings 5186 ALUWritePC(result); 5187 else 5188 R[d] = result; 5189#endif 5190 5191 bool success = false; 5192 5193 if (ConditionPassed(opcode)) 5194 { 5195 uint32_t Rd; 5196 uint32_t imm32; // the immediate value to be added/subtracted to/from the PC 5197 bool add; 5198 switch (encoding) 5199 { 5200 case eEncodingT1: 5201 Rd = Bits32(opcode, 10, 8); 5202 imm32 = ThumbImm8Scaled(opcode); // imm32 = ZeroExtend(imm8:'00', 32) 5203 break; 5204 case eEncodingT2: 5205 case eEncodingT3: 5206 Rd = Bits32(opcode, 11, 8); 5207 imm32 = ThumbImm12(opcode); // imm32 = ZeroExtend(i:imm3:imm8, 32) 5208 add = (Bits32(opcode, 24, 21) == 0); // 0b0000 => ADD; 0b0101 => SUB 5209 if (BadReg(Rd)) 5210 return false; 5211 break; 5212 case eEncodingA1: 5213 case eEncodingA2: 5214 Rd = Bits32(opcode, 15, 12); 5215 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12) 5216 add = (Bits32(opcode, 24, 21) == 0x4); // 0b0100 => ADD; 0b0010 => SUB 5217 break; 5218 default: 5219 return false; 5220 } 5221 5222 // Read the PC value. 5223 uint32_t pc = ReadCoreReg(PC_REG, &success); 5224 if (!success) 5225 return false; 5226 5227 uint32_t result = (add ? Align(pc, 4) + imm32 : Align(pc, 4) - imm32); 5228 5229 EmulateInstruction::Context context; 5230 context.type = EmulateInstruction::eContextImmediate; 5231 context.SetNoArgs (); 5232 5233 if (!WriteCoreReg(context, result, Rd)) 5234 return false; 5235 } 5236 return true; 5237} 5238 5239// This instruction performs a bitwise AND of a register value and an immediate value, and writes the result 5240// to the destination register. It can optionally update the condition flags based on the result. 5241bool 5242EmulateInstructionARM::EmulateANDImm (const uint32_t opcode, const ARMEncoding encoding) 5243{ 5244#if 0 5245 // ARM pseudo code... 5246 if ConditionPassed() then 5247 EncodingSpecificOperations(); 5248 result = R[n] AND imm32; 5249 if d == 15 then // Can only occur for ARM encoding 5250 ALUWritePC(result); // setflags is always FALSE here 5251 else 5252 R[d] = result; 5253 if setflags then 5254 APSR.N = result<31>; 5255 APSR.Z = IsZeroBit(result); 5256 APSR.C = carry; 5257 // APSR.V unchanged 5258#endif 5259 5260 bool success = false; 5261 5262 if (ConditionPassed(opcode)) 5263 { 5264 uint32_t Rd, Rn; 5265 uint32_t imm32; // the immediate value to be ANDed to the value obtained from Rn 5266 bool setflags; 5267 uint32_t carry; // the carry bit after ARM/Thumb Expand operation 5268 switch (encoding) 5269 { 5270 case eEncodingT1: 5271 Rd = Bits32(opcode, 11, 8); 5272 Rn = Bits32(opcode, 19, 16); 5273 setflags = BitIsSet(opcode, 20); 5274 imm32 = ThumbExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C) 5275 // if Rd == '1111' && S == '1' then SEE TST (immediate); 5276 if (Rd == 15 && setflags) 5277 return EmulateTSTImm(opcode, eEncodingT1); 5278 if (Rd == 13 || (Rd == 15 && !setflags) || BadReg(Rn)) 5279 return false; 5280 break; 5281 case eEncodingA1: 5282 Rd = Bits32(opcode, 15, 12); 5283 Rn = Bits32(opcode, 19, 16); 5284 setflags = BitIsSet(opcode, 20); 5285 imm32 = ARMExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ARMExpandImm(imm12, APSR.C) 5286 // TODO: Emulate SUBS PC, LR and related instructions. 5287 if (Rd == 15 && setflags) 5288 return false; 5289 break; 5290 default: 5291 return false; 5292 } 5293 5294 // Read the first operand. 5295 uint32_t val1 = ReadCoreReg(Rn, &success); 5296 if (!success) 5297 return false; 5298 5299 uint32_t result = val1 & imm32; 5300 5301 EmulateInstruction::Context context; 5302 context.type = EmulateInstruction::eContextImmediate; 5303 context.SetNoArgs (); 5304 5305 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry)) 5306 return false; 5307 } 5308 return true; 5309} 5310 5311// This instruction performs a bitwise AND of a register value and an optionally-shifted register value, 5312// and writes the result to the destination register. It can optionally update the condition flags 5313// based on the result. 5314bool 5315EmulateInstructionARM::EmulateANDReg (const uint32_t opcode, const ARMEncoding encoding) 5316{ 5317#if 0 5318 // ARM pseudo code... 5319 if ConditionPassed() then 5320 EncodingSpecificOperations(); 5321 (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C); 5322 result = R[n] AND shifted; 5323 if d == 15 then // Can only occur for ARM encoding 5324 ALUWritePC(result); // setflags is always FALSE here 5325 else 5326 R[d] = result; 5327 if setflags then 5328 APSR.N = result<31>; 5329 APSR.Z = IsZeroBit(result); 5330 APSR.C = carry; 5331 // APSR.V unchanged 5332#endif 5333 5334 bool success = false; 5335 5336 if (ConditionPassed(opcode)) 5337 { 5338 uint32_t Rd, Rn, Rm; 5339 ARM_ShifterType shift_t; 5340 uint32_t shift_n; // the shift applied to the value read from Rm 5341 bool setflags; 5342 uint32_t carry; 5343 switch (encoding) 5344 { 5345 case eEncodingT1: 5346 Rd = Rn = Bits32(opcode, 2, 0); 5347 Rm = Bits32(opcode, 5, 3); 5348 setflags = !InITBlock(); 5349 shift_t = SRType_LSL; 5350 shift_n = 0; 5351 break; 5352 case eEncodingT2: 5353 Rd = Bits32(opcode, 11, 8); 5354 Rn = Bits32(opcode, 19, 16); 5355 Rm = Bits32(opcode, 3, 0); 5356 setflags = BitIsSet(opcode, 20); 5357 shift_n = DecodeImmShiftThumb(opcode, shift_t); 5358 // if Rd == '1111' && S == '1' then SEE TST (register); 5359 if (Rd == 15 && setflags) 5360 return EmulateTSTReg(opcode, eEncodingT2); 5361 if (Rd == 13 || (Rd == 15 && !setflags) || BadReg(Rn) || BadReg(Rm)) 5362 return false; 5363 break; 5364 case eEncodingA1: 5365 Rd = Bits32(opcode, 15, 12); 5366 Rn = Bits32(opcode, 19, 16); 5367 Rm = Bits32(opcode, 3, 0); 5368 setflags = BitIsSet(opcode, 20); 5369 shift_n = DecodeImmShiftARM(opcode, shift_t); 5370 // TODO: Emulate SUBS PC, LR and related instructions. 5371 if (Rd == 15 && setflags) 5372 return false; 5373 break; 5374 default: 5375 return false; 5376 } 5377 5378 // Read the first operand. 5379 uint32_t val1 = ReadCoreReg(Rn, &success); 5380 if (!success) 5381 return false; 5382 5383 // Read the second operand. 5384 uint32_t val2 = ReadCoreReg(Rm, &success); 5385 if (!success) 5386 return false; 5387 5388 uint32_t shifted = Shift_C(val2, shift_t, shift_n, APSR_C, carry); 5389 uint32_t result = val1 & shifted; 5390 5391 EmulateInstruction::Context context; 5392 context.type = EmulateInstruction::eContextImmediate; 5393 context.SetNoArgs (); 5394 5395 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry)) 5396 return false; 5397 } 5398 return true; 5399} 5400 5401// Bitwise Bit Clear (immediate) performs a bitwise AND of a register value and the complement of an 5402// immediate value, and writes the result to the destination register. It can optionally update the 5403// condition flags based on the result. 5404bool 5405EmulateInstructionARM::EmulateBICImm (const uint32_t opcode, const ARMEncoding encoding) 5406{ 5407#if 0 5408 // ARM pseudo code... 5409 if ConditionPassed() then 5410 EncodingSpecificOperations(); 5411 result = R[n] AND NOT(imm32); 5412 if d == 15 then // Can only occur for ARM encoding 5413 ALUWritePC(result); // setflags is always FALSE here 5414 else 5415 R[d] = result; 5416 if setflags then 5417 APSR.N = result<31>; 5418 APSR.Z = IsZeroBit(result); 5419 APSR.C = carry; 5420 // APSR.V unchanged 5421#endif 5422 5423 bool success = false; 5424 5425 if (ConditionPassed(opcode)) 5426 { 5427 uint32_t Rd, Rn; 5428 uint32_t imm32; // the immediate value to be bitwise inverted and ANDed to the value obtained from Rn 5429 bool setflags; 5430 uint32_t carry; // the carry bit after ARM/Thumb Expand operation 5431 switch (encoding) 5432 { 5433 case eEncodingT1: 5434 Rd = Bits32(opcode, 11, 8); 5435 Rn = Bits32(opcode, 19, 16); 5436 setflags = BitIsSet(opcode, 20); 5437 imm32 = ThumbExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C) 5438 if (BadReg(Rd) || BadReg(Rn)) 5439 return false; 5440 break; 5441 case eEncodingA1: 5442 Rd = Bits32(opcode, 15, 12); 5443 Rn = Bits32(opcode, 19, 16); 5444 setflags = BitIsSet(opcode, 20); 5445 imm32 = ARMExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ARMExpandImm(imm12, APSR.C) 5446 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions; 5447 // TODO: Emulate SUBS PC, LR and related instructions. 5448 if (Rd == 15 && setflags) 5449 return false; 5450 break; 5451 default: 5452 return false; 5453 } 5454 5455 // Read the first operand. 5456 uint32_t val1 = ReadCoreReg(Rn, &success); 5457 if (!success) 5458 return false; 5459 5460 uint32_t result = val1 & ~imm32; 5461 5462 EmulateInstruction::Context context; 5463 context.type = EmulateInstruction::eContextImmediate; 5464 context.SetNoArgs (); 5465 5466 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry)) 5467 return false; 5468 } 5469 return true; 5470} 5471 5472// Bitwise Bit Clear (register) performs a bitwise AND of a register value and the complement of an 5473// optionally-shifted register value, and writes the result to the destination register. 5474// It can optionally update the condition flags based on the result. 5475bool 5476EmulateInstructionARM::EmulateBICReg (const uint32_t opcode, const ARMEncoding encoding) 5477{ 5478#if 0 5479 // ARM pseudo code... 5480 if ConditionPassed() then 5481 EncodingSpecificOperations(); 5482 (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C); 5483 result = R[n] AND NOT(shifted); 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, Rm; 5500 ARM_ShifterType shift_t; 5501 uint32_t shift_n; // the shift applied to the value read from Rm 5502 bool setflags; 5503 uint32_t carry; 5504 switch (encoding) 5505 { 5506 case eEncodingT1: 5507 Rd = Rn = Bits32(opcode, 2, 0); 5508 Rm = Bits32(opcode, 5, 3); 5509 setflags = !InITBlock(); 5510 shift_t = SRType_LSL; 5511 shift_n = 0; 5512 break; 5513 case eEncodingT2: 5514 Rd = Bits32(opcode, 11, 8); 5515 Rn = Bits32(opcode, 19, 16); 5516 Rm = Bits32(opcode, 3, 0); 5517 setflags = BitIsSet(opcode, 20); 5518 shift_n = DecodeImmShiftThumb(opcode, shift_t); 5519 if (BadReg(Rd) || BadReg(Rn) || BadReg(Rm)) 5520 return false; 5521 break; 5522 case eEncodingA1: 5523 Rd = Bits32(opcode, 15, 12); 5524 Rn = Bits32(opcode, 19, 16); 5525 Rm = Bits32(opcode, 3, 0); 5526 setflags = BitIsSet(opcode, 20); 5527 shift_n = DecodeImmShiftARM(opcode, shift_t); 5528 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions; 5529 // TODO: Emulate SUBS PC, LR and related instructions. 5530 if (Rd == 15 && setflags) 5531 return false; 5532 break; 5533 default: 5534 return false; 5535 } 5536 5537 // Read the first operand. 5538 uint32_t val1 = ReadCoreReg(Rn, &success); 5539 if (!success) 5540 return false; 5541 5542 // Read the second operand. 5543 uint32_t val2 = ReadCoreReg(Rm, &success); 5544 if (!success) 5545 return false; 5546 5547 uint32_t shifted = Shift_C(val2, shift_t, shift_n, APSR_C, carry); 5548 uint32_t result = val1 & ~shifted; 5549 5550 EmulateInstruction::Context context; 5551 context.type = EmulateInstruction::eContextImmediate; 5552 context.SetNoArgs (); 5553 5554 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry)) 5555 return false; 5556 } 5557 return true; 5558} 5559 5560// LDR (immediate, ARM) calculates an address from a base register value and an immediate offset, loads a word 5561// from memory, and writes it to a register. It can use offset, post-indexed, or pre-indexed addressing. 5562bool 5563EmulateInstructionARM::EmulateLDRImmediateARM (const uint32_t opcode, const ARMEncoding encoding) 5564{ 5565#if 0 5566 if ConditionPassed() then 5567 EncodingSpecificOperations(); 5568 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32); 5569 address = if index then offset_addr else R[n]; 5570 data = MemU[address,4]; 5571 if wback then R[n] = offset_addr; 5572 if t == 15 then 5573 if address<1:0> == '00' then LoadWritePC(data); else UNPREDICTABLE; 5574 elsif UnalignedSupport() || address<1:0> = '00' then 5575 R[t] = data; 5576 else // Can only apply before ARMv7 5577 R[t] = ROR(data, 8*UInt(address<1:0>)); 5578#endif 5579 5580 bool success = false; 5581 5582 if (ConditionPassed(opcode)) 5583 { 5584 const uint32_t addr_byte_size = GetAddressByteSize(); 5585 5586 uint32_t t; 5587 uint32_t n; 5588 uint32_t imm32; 5589 bool index; 5590 bool add; 5591 bool wback; 5592 5593 switch (encoding) 5594 { 5595 case eEncodingA1: 5596 // if Rn == '1111' then SEE LDR (literal); 5597 // if P == '0' && W == '1' then SEE LDRT; 5598 // if Rn == '1101' && P == '0' && U == '1' && W == '0' && imm12 == '000000000100' then SEE POP; 5599 // t == UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32); 5600 t = Bits32 (opcode, 15, 12); 5601 n = Bits32 (opcode, 19, 16); 5602 imm32 = Bits32 (opcode, 11, 0); 5603 5604 // index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1'); 5605 index = BitIsSet (opcode, 24); 5606 add = BitIsSet (opcode, 23); 5607 wback = (BitIsClear (opcode, 24) || BitIsSet (opcode, 21)); 5608 5609 // if wback && n == t then UNPREDICTABLE; 5610 if (wback && (n == t)) 5611 return false; 5612 5613 break; 5614 5615 default: 5616 return false; 5617 } 5618 5619 addr_t address; 5620 addr_t offset_addr; 5621 addr_t base_address = ReadCoreReg (n, &success); 5622 if (!success) 5623 return false; 5624 5625 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32); 5626 if (add) 5627 offset_addr = base_address + imm32; 5628 else 5629 offset_addr = base_address - imm32; 5630 5631 // address = if index then offset_addr else R[n]; 5632 if (index) 5633 address = offset_addr; 5634 else 5635 address = base_address; 5636 5637 // data = MemU[address,4]; 5638 5639 Register base_reg; 5640 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n); 5641 5642 EmulateInstruction::Context context; 5643 context.type = eContextRegisterLoad; 5644 context.SetRegisterPlusOffset (base_reg, address - base_address); 5645 5646 uint64_t data = MemURead (context, address, addr_byte_size, 0, &success); 5647 if (!success) 5648 return false; 5649 5650 // if wback then R[n] = offset_addr; 5651 if (wback) 5652 { 5653 context.type = eContextAdjustBaseRegister; 5654 context.SetAddress (offset_addr); 5655 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr)) 5656 return false; 5657 } 5658 5659 // if t == 15 then 5660 if (t == 15) 5661 { 5662 // if address<1:0> == '00' then LoadWritePC(data); else UNPREDICTABLE; 5663 if (BitIsClear (address, 1) && BitIsClear (address, 0)) 5664 { 5665 // LoadWritePC (data); 5666 context.type = eContextRegisterLoad; 5667 context.SetRegisterPlusOffset (base_reg, address - base_address); 5668 LoadWritePC (context, data); 5669 } 5670 else 5671 return false; 5672 } 5673 // elsif UnalignedSupport() || address<1:0> = '00' then 5674 else if (UnalignedSupport() || (BitIsClear (address, 1) && BitIsClear (address, 0))) 5675 { 5676 // R[t] = data; 5677 context.type = eContextRegisterLoad; 5678 context.SetRegisterPlusOffset (base_reg, address - base_address); 5679 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data)) 5680 return false; 5681 } 5682 // else // Can only apply before ARMv7 5683 else 5684 { 5685 // R[t] = ROR(data, 8*UInt(address<1:0>)); 5686 data = ROR (data, Bits32 (address, 1, 0)); 5687 context.type = eContextRegisterLoad; 5688 context.SetImmediate (data); 5689 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data)) 5690 return false; 5691 } 5692 5693 } 5694 return true; 5695} 5696 5697// LDR (register) calculates an address from a base register value and an offset register value, loads a word 5698// from memory, and writes it to a resgister. The offset register value can optionally be shifted. 5699bool 5700EmulateInstructionARM::EmulateLDRRegister (const uint32_t opcode, const ARMEncoding encoding) 5701{ 5702#if 0 5703 if ConditionPassed() then 5704 EncodingSpecificOperations(); NullCheckIfThumbEE(n); 5705 offset = Shift(R[m], shift_t, shift_n, APSR.C); 5706 offset_addr = if add then (R[n] + offset) else (R[n] - offset); 5707 address = if index then offset_addr else R[n]; 5708 data = MemU[address,4]; 5709 if wback then R[n] = offset_addr; 5710 if t == 15 then 5711 if address<1:0> == '00' then LoadWritePC(data); else UNPREDICTABLE; 5712 elsif UnalignedSupport() || address<1:0> = '00' then 5713 R[t] = data; 5714 else // Can only apply before ARMv7 5715 if CurrentInstrSet() == InstrSet_ARM then 5716 R[t] = ROR(data, 8*UInt(address<1:0>)); 5717 else 5718 R[t] = bits(32) UNKNOWN; 5719#endif 5720 5721 bool success = false; 5722 5723 if (ConditionPassed(opcode)) 5724 { 5725 const uint32_t addr_byte_size = GetAddressByteSize(); 5726 5727 uint32_t t; 5728 uint32_t n; 5729 uint32_t m; 5730 bool index; 5731 bool add; 5732 bool wback; 5733 ARM_ShifterType shift_t; 5734 uint32_t shift_n; 5735 5736 switch (encoding) 5737 { 5738 case eEncodingT1: 5739 // if CurrentInstrSet() == InstrSet_ThumbEE then SEE "Modified operation in ThumbEE"; 5740 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm); 5741 t = Bits32 (opcode, 2, 0); 5742 n = Bits32 (opcode, 5, 3); 5743 m = Bits32 (opcode, 8, 6); 5744 5745 // index = TRUE; add = TRUE; wback = FALSE; 5746 index = true; 5747 add = true; 5748 wback = false; 5749 5750 // (shift_t, shift_n) = (SRType_LSL, 0); 5751 shift_t = SRType_LSL; 5752 shift_n = 0; 5753 5754 break; 5755 5756 case eEncodingT2: 5757 // if Rn == '1111' then SEE LDR (literal); 5758 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm); 5759 t = Bits32 (opcode, 15, 12); 5760 n = Bits32 (opcode, 19, 16); 5761 m = Bits32 (opcode, 3, 0); 5762 5763 // index = TRUE; add = TRUE; wback = FALSE; 5764 index = true; 5765 add = true; 5766 wback = false; 5767 5768 // (shift_t, shift_n) = (SRType_LSL, UInt(imm2)); 5769 shift_t = SRType_LSL; 5770 shift_n = Bits32 (opcode, 5, 4); 5771 5772 // if BadReg(m) then UNPREDICTABLE; 5773 if (BadReg (m)) 5774 return false; 5775 5776 // if t == 15 && InITBlock() && !LastInITBlock() then UNPREDICTABLE; 5777 if ((t == 15) && InITBlock() && !LastInITBlock()) 5778 return false; 5779 5780 break; 5781 5782 case eEncodingA1: 5783 { 5784 // if P == '0' && W == '1' then SEE LDRT; 5785 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm); 5786 t = Bits32 (opcode, 15, 12); 5787 n = Bits32 (opcode, 19, 16); 5788 m = Bits32 (opcode, 3, 0); 5789 5790 // index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1'); 5791 index = BitIsSet (opcode, 24); 5792 add = BitIsSet (opcode, 23); 5793 wback = (BitIsClear (opcode, 24) || BitIsSet (opcode, 21)); 5794 5795 // (shift_t, shift_n) = DecodeImmShift(type, imm5); 5796 uint32_t type = Bits32 (opcode, 6, 5); 5797 uint32_t imm5 = Bits32 (opcode, 11, 7); 5798 shift_n = DecodeImmShift (type, imm5, shift_t); 5799 5800 // if m == 15 then UNPREDICTABLE; 5801 if (m == 15) 5802 return false; 5803 5804 // if wback && (n == 15 || n == t) then UNPREDICTABLE; 5805 if (wback && ((n == 15) || (n == t))) 5806 return false; 5807 } 5808 break; 5809 5810 5811 default: 5812 return false; 5813 } 5814 5815 uint32_t Rm = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success); 5816 if (!success) 5817 return false; 5818 5819 uint32_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success); 5820 if (!success) 5821 return false; 5822 5823 addr_t offset_addr; 5824 addr_t address; 5825 5826 // offset = Shift(R[m], shift_t, shift_n, APSR.C); -- Note "The APSR is an application level alias for the CPSR". 5827 addr_t offset = Shift (Rm, shift_t, shift_n, Bit32 (m_opcode_cpsr, APSR_C)); 5828 5829 // offset_addr = if add then (R[n] + offset) else (R[n] - offset); 5830 if (add) 5831 offset_addr = Rn + offset; 5832 else 5833 offset_addr = Rn - offset; 5834 5835 // address = if index then offset_addr else R[n]; 5836 if (index) 5837 address = offset_addr; 5838 else 5839 address = Rn; 5840 5841 // data = MemU[address,4]; 5842 Register base_reg; 5843 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n); 5844 5845 EmulateInstruction::Context context; 5846 context.type = eContextRegisterLoad; 5847 context.SetRegisterPlusOffset (base_reg, address - Rn); 5848 5849 uint64_t data = MemURead (context, address, addr_byte_size, 0, &success); 5850 if (!success) 5851 return false; 5852 5853 // if wback then R[n] = offset_addr; 5854 if (wback) 5855 { 5856 context.type = eContextAdjustBaseRegister; 5857 context.SetAddress (offset_addr); 5858 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr)) 5859 return false; 5860 } 5861 5862 // if t == 15 then 5863 if (t == 15) 5864 { 5865 // if address<1:0> == '00' then LoadWritePC(data); else UNPREDICTABLE; 5866 if (BitIsClear (address, 1) && BitIsClear (address, 0)) 5867 { 5868 context.type = eContextRegisterLoad; 5869 context.SetRegisterPlusOffset (base_reg, address - Rn); 5870 LoadWritePC (context, data); 5871 } 5872 else 5873 return false; 5874 } 5875 // elsif UnalignedSupport() || address<1:0> = '00' then 5876 else if (UnalignedSupport () || (BitIsClear (address, 1) && BitIsClear (address, 0))) 5877 { 5878 // R[t] = data; 5879 context.type = eContextRegisterLoad; 5880 context.SetRegisterPlusOffset (base_reg, address - Rn); 5881 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data)) 5882 return false; 5883 } 5884 else // Can only apply before ARMv7 5885 { 5886 // if CurrentInstrSet() == InstrSet_ARM then 5887 if (CurrentInstrSet () == eModeARM) 5888 { 5889 // R[t] = ROR(data, 8*UInt(address<1:0>)); 5890 data = ROR (data, Bits32 (address, 1, 0)); 5891 context.type = eContextRegisterLoad; 5892 context.SetImmediate (data); 5893 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data)) 5894 return false; 5895 } 5896 else 5897 { 5898 // R[t] = bits(32) UNKNOWN; 5899 WriteBits32Unknown (t); 5900 } 5901 } 5902 } 5903 return true; 5904} 5905 5906// LDRB (immediate, Thumb) 5907bool 5908EmulateInstructionARM::EmulateLDRBImmediate (const uint32_t opcode, const ARMEncoding encoding) 5909{ 5910#if 0 5911 if ConditionPassed() then 5912 EncodingSpecificOperations(); NullCheckIfThumbEE(n); 5913 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32); 5914 address = if index then offset_addr else R[n]; 5915 R[t] = ZeroExtend(MemU[address,1], 32); 5916 if wback then R[n] = offset_addr; 5917#endif 5918 5919 bool success = false; 5920 5921 if (ConditionPassed(opcode)) 5922 { 5923 uint32_t t; 5924 uint32_t n; 5925 uint32_t imm32; 5926 bool index; 5927 bool add; 5928 bool wback; 5929 5930 // EncodingSpecificOperations(); NullCheckIfThumbEE(n); 5931 switch (encoding) 5932 { 5933 case eEncodingT1: 5934 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm5, 32); 5935 t = Bits32 (opcode, 2, 0); 5936 n = Bits32 (opcode, 5, 3); 5937 imm32 = Bits32 (opcode, 10, 6); 5938 5939 // index = TRUE; add = TRUE; wback = FALSE; 5940 index = true; 5941 add = true; 5942 wback= false; 5943 5944 break; 5945 5946 case eEncodingT2: 5947 // if Rt == '1111' then SEE PLD; 5948 // if Rn == '1111' then SEE LDRB (literal); 5949 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32); 5950 t = Bits32 (opcode, 15, 12); 5951 n = Bits32 (opcode, 19, 16); 5952 imm32 = Bits32 (opcode, 11, 0); 5953 5954 // index = TRUE; add = TRUE; wback = FALSE; 5955 index = true; 5956 add = true; 5957 wback = false; 5958 5959 // if t == 13 then UNPREDICTABLE; 5960 if (t == 13) 5961 return false; 5962 5963 break; 5964 5965 case eEncodingT3: 5966 // if Rt == '1111' && P == '1' && U == '0' && W == '0' then SEE PLD; 5967 // if Rn == '1111' then SEE LDRB (literal); 5968 // if P == '1' && U == '1' && W == '0' then SEE LDRBT; 5969 // if P == '0' && W == '0' then UNDEFINED; 5970 if (BitIsClear (opcode, 10) && BitIsClear (opcode, 8)) 5971 return false; 5972 5973 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32); 5974 t = Bits32 (opcode, 15, 12); 5975 n = Bits32 (opcode, 19, 16); 5976 imm32 = Bits32 (opcode, 7, 0); 5977 5978 // index = (P == '1'); add = (U == '1'); wback = (W == '1'); 5979 index = BitIsSet (opcode, 10); 5980 add = BitIsSet (opcode, 9); 5981 wback = BitIsSet (opcode, 8); 5982 5983 // if BadReg(t) || (wback && n == t) then UNPREDICTABLE; 5984 if (BadReg (t) || (wback && (n == t))) 5985 return false; 5986 5987 break; 5988 5989 default: 5990 return false; 5991 } 5992 5993 uint32_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success); 5994 if (!success) 5995 return false; 5996 5997 addr_t address; 5998 addr_t offset_addr; 5999 6000 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32); 6001 if (add) 6002 offset_addr = Rn + imm32; 6003 else 6004 offset_addr = Rn - imm32; 6005 6006 // address = if index then offset_addr else R[n]; 6007 if (index) 6008 address = offset_addr; 6009 else 6010 address = Rn; 6011 6012 // R[t] = ZeroExtend(MemU[address,1], 32); 6013 Register base_reg; 6014 Register data_reg; 6015 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n); 6016 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + t); 6017 6018 EmulateInstruction::Context context; 6019 context.type = eContextRegisterLoad; 6020 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, address - Rn); 6021 6022 uint64_t data = MemURead (context, address, 1, 0, &success); 6023 if (!success) 6024 return false; 6025 6026 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data)) 6027 return false; 6028 6029 // if wback then R[n] = offset_addr; 6030 if (wback) 6031 { 6032 context.type = eContextAdjustBaseRegister; 6033 context.SetAddress (offset_addr); 6034 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr)) 6035 return false; 6036 } 6037 } 6038 return true; 6039} 6040 6041// LDRB (literal) calculates an address from the PC value and an immediate offset, loads a byte from memory, 6042// zero-extends it to form a 32-bit word and writes it to a register. 6043bool 6044EmulateInstructionARM::EmulateLDRBLiteral (const uint32_t opcode, const ARMEncoding encoding) 6045{ 6046#if 0 6047 if ConditionPassed() then 6048 EncodingSpecificOperations(); NullCheckIfThumbEE(15); 6049 base = Align(PC,4); 6050 address = if add then (base + imm32) else (base - imm32); 6051 R[t] = ZeroExtend(MemU[address,1], 32); 6052#endif 6053 6054 bool success = false; 6055 6056 if (ConditionPassed(opcode)) 6057 { 6058 uint32_t t; 6059 uint32_t imm32; 6060 bool add; 6061 switch (encoding) 6062 { 6063 case eEncodingT1: 6064 // if Rt == '1111' then SEE PLD; 6065 // t = UInt(Rt); imm32 = ZeroExtend(imm12, 32); add = (U == '1'); 6066 t = Bits32 (opcode, 15, 12); 6067 imm32 = Bits32 (opcode, 11, 0); 6068 add = BitIsSet (opcode, 23); 6069 6070 // if t == 13 then UNPREDICTABLE; 6071 if (t == 13) 6072 return false; 6073 6074 break; 6075 6076 case eEncodingA1: 6077 // t == UInt(Rt); imm32 = ZeroExtend(imm12, 32); add = (U == '1'); 6078 t = Bits32 (opcode, 15, 12); 6079 imm32 = Bits32 (opcode, 11, 0); 6080 add = BitIsSet (opcode, 23); 6081 6082 // if t == 15 then UNPREDICTABLE; 6083 if (t == 15) 6084 return false; 6085 break; 6086 6087 default: 6088 return false; 6089 } 6090 6091 // base = Align(PC,4); 6092 uint32_t pc_val = ReadCoreReg (PC_REG, &success); 6093 if (!success) 6094 return false; 6095 6096 uint32_t base = AlignPC (pc_val); 6097 6098 addr_t address; 6099 // address = if add then (base + imm32) else (base - imm32); 6100 if (add) 6101 address = base + imm32; 6102 else 6103 address = base - imm32; 6104 6105 // R[t] = ZeroExtend(MemU[address,1], 32); 6106 EmulateInstruction::Context context; 6107 context.type = eContextRelativeBranchImmediate; 6108 context.SetImmediate (address - base); 6109 6110 uint64_t data = MemURead (context, address, 1, 0, &success); 6111 if (!success) 6112 return false; 6113 6114 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data)) 6115 return false; 6116 } 6117 return true; 6118} 6119 6120// LDRB (register) calculates an address from a base register value and an offset rigister value, loads a byte from 6121// memory, zero-extends it to form a 32-bit word, and writes it to a register. The offset register value can 6122// optionally be shifted. 6123bool 6124EmulateInstructionARM::EmulateLDRBRegister (const uint32_t opcode, const ARMEncoding encoding) 6125{ 6126#if 0 6127 if ConditionPassed() then 6128 EncodingSpecificOperations(); NullCheckIfThumbEE(n); 6129 offset = Shift(R[m], shift_t, shift_n, APSR.C); 6130 offset_addr = if add then (R[n] + offset) else (R[n] - offset); 6131 address = if index then offset_addr else R[n]; 6132 R[t] = ZeroExtend(MemU[address,1],32); 6133 if wback then R[n] = offset_addr; 6134#endif 6135 6136 bool success = false; 6137 6138 if (ConditionPassed(opcode)) 6139 { 6140 uint32_t t; 6141 uint32_t n; 6142 uint32_t m; 6143 bool index; 6144 bool add; 6145 bool wback; 6146 ARM_ShifterType shift_t; 6147 uint32_t shift_n; 6148 6149 // EncodingSpecificOperations(); NullCheckIfThumbEE(n); 6150 switch (encoding) 6151 { 6152 case eEncodingT1: 6153 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm); 6154 t = Bits32 (opcode, 2, 0); 6155 n = Bits32 (opcode, 5, 3); 6156 m = Bits32 (opcode, 8, 6); 6157 6158 // index = TRUE; add = TRUE; wback = FALSE; 6159 index = true; 6160 add = true; 6161 wback = false; 6162 6163 // (shift_t, shift_n) = (SRType_LSL, 0); 6164 shift_t = SRType_LSL; 6165 shift_n = 0; 6166 break; 6167 6168 case eEncodingT2: 6169 // if Rt == '1111' then SEE PLD; 6170 // if Rn == '1111' then SEE LDRB (literal); 6171 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm); 6172 t = Bits32 (opcode, 15, 12); 6173 n = Bits32 (opcode, 19, 16); 6174 m = Bits32 (opcode, 3, 0); 6175 6176 // index = TRUE; add = TRUE; wback = FALSE; 6177 index = true; 6178 add = true; 6179 wback = false; 6180 6181 // (shift_t, shift_n) = (SRType_LSL, UInt(imm2)); 6182 shift_t = SRType_LSL; 6183 shift_n = Bits32 (opcode, 5, 4); 6184 6185 // if t == 13 || BadReg(m) then UNPREDICTABLE; 6186 if ((t == 13) || BadReg (m)) 6187 return false; 6188 break; 6189 6190 case eEncodingA1: 6191 { 6192 // if P == '0' && W == '1' then SEE LDRBT; 6193 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm); 6194 t = Bits32 (opcode, 15, 12); 6195 n = Bits32 (opcode, 19, 16); 6196 m = Bits32 (opcode, 3, 0); 6197 6198 // index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1'); 6199 index = BitIsSet (opcode, 24); 6200 add = BitIsSet (opcode, 23); 6201 wback = (BitIsClear (opcode, 24) || BitIsSet (opcode, 21)); 6202 6203 // (shift_t, shift_n) = DecodeImmShift(type, imm5); 6204 uint32_t type = Bits32 (opcode, 6, 5); 6205 uint32_t imm5 = Bits32 (opcode, 11, 7); 6206 shift_n = DecodeImmShift (type, imm5, shift_t); 6207 6208 // if t == 15 || m == 15 then UNPREDICTABLE; 6209 if ((t == 15) || (m == 15)) 6210 return false; 6211 6212 // if wback && (n == 15 || n == t) then UNPREDICTABLE; 6213 if (wback && ((n == 15) || (n == t))) 6214 return false; 6215 } 6216 break; 6217 6218 default: 6219 return false; 6220 } 6221 6222 addr_t offset_addr; 6223 addr_t address; 6224 6225 // offset = Shift(R[m], shift_t, shift_n, APSR.C); 6226 uint32_t Rm = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success); 6227 if (!success) 6228 return false; 6229 6230 addr_t offset = Shift (Rm, shift_t, shift_n, APSR_C); 6231 6232 // offset_addr = if add then (R[n] + offset) else (R[n] - offset); 6233 uint32_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success); 6234 if (!success) 6235 return false; 6236 6237 if (add) 6238 offset_addr = Rn + offset; 6239 else 6240 offset_addr = Rn - offset; 6241 6242 // address = if index then offset_addr else R[n]; 6243 if (index) 6244 address = offset_addr; 6245 else 6246 address = Rn; 6247 6248 // R[t] = ZeroExtend(MemU[address,1],32); 6249 Register base_reg; 6250 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n); 6251 6252 EmulateInstruction::Context context; 6253 context.type = eContextRegisterLoad; 6254 context.SetRegisterPlusOffset (base_reg, address - Rn); 6255 6256 uint64_t data = MemURead (context, address, 1, 0, &success); 6257 if (!success) 6258 return false; 6259 6260 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data)) 6261 return false; 6262 6263 // if wback then R[n] = offset_addr; 6264 if (wback) 6265 { 6266 context.type = eContextAdjustBaseRegister; 6267 context.SetAddress (offset_addr); 6268 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr)) 6269 return false; 6270 } 6271 } 6272 return true; 6273} 6274 6275// LDRH (immediate, Thumb) calculates an address from a base register value and an immediate offset, loads a 6276// halfword from memory, zero-extends it to form a 32-bit word, and writes it to a register. It can use offset, 6277// post-indexed, or pre-indexed addressing. 6278bool 6279EmulateInstructionARM::EmulateLDRHImmediate (const uint32_t opcode, const ARMEncoding encoding) 6280{ 6281#if 0 6282 if ConditionPassed() then 6283 EncodingSpecificOperations(); NullCheckIfThumbEE(n); 6284 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32); 6285 address = if index then offset_addr else R[n]; 6286 data = MemU[address,2]; 6287 if wback then R[n] = offset_addr; 6288 if UnalignedSupport() || address<0> = '0' then 6289 R[t] = ZeroExtend(data, 32); 6290 else // Can only apply before ARMv7 6291 R[t] = bits(32) UNKNOWN; 6292#endif 6293 6294 6295 bool success = false; 6296 6297 if (ConditionPassed(opcode)) 6298 { 6299 uint32_t t; 6300 uint32_t n; 6301 uint32_t imm32; 6302 bool index; 6303 bool add; 6304 bool wback; 6305 6306 // EncodingSpecificOperations(); NullCheckIfThumbEE(n); 6307 switch (encoding) 6308 { 6309 case eEncodingT1: 6310 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm5:'0', 32); 6311 t = Bits32 (opcode, 2, 0); 6312 n = Bits32 (opcode, 5, 3); 6313 imm32 = Bits32 (opcode, 10, 6) << 1; 6314 6315 // index = TRUE; add = TRUE; wback = FALSE; 6316 index = true; 6317 add = true; 6318 wback = false; 6319 6320 break; 6321 6322 case eEncodingT2: 6323 // if Rt == '1111' then SEE "Unallocated memory hints"; 6324 // if Rn == '1111' then SEE LDRH (literal); 6325 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32); 6326 t = Bits32 (opcode, 15, 12); 6327 n = Bits32 (opcode, 19, 16); 6328 imm32 = Bits32 (opcode, 11, 0); 6329 6330 // index = TRUE; add = TRUE; wback = FALSE; 6331 index = true; 6332 add = true; 6333 wback = false; 6334 6335 // if t == 13 then UNPREDICTABLE; 6336 if (t == 13) 6337 return false; 6338 break; 6339 6340 case eEncodingT3: 6341 // if Rn == '1111' then SEE LDRH (literal); 6342 // if Rt == '1111' && P == '1' && U == '0' && W == '0' then SEE "Unallocated memory hints"; 6343 // if P == '1' && U == '1' && W == '0' then SEE LDRHT; 6344 // if P == '0' && W == '0' then UNDEFINED; 6345 if (BitIsClear (opcode, 10) && BitIsClear (opcode, 8)) 6346 return false; 6347 6348 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32); 6349 t = Bits32 (opcode, 15, 12); 6350 n = Bits32 (opcode, 19, 16); 6351 imm32 = Bits32 (opcode, 7, 0); 6352 6353 // index = (P == '1'); add = (U == '1'); wback = (W == '1'); 6354 index = BitIsSet (opcode, 10); 6355 add = BitIsSet (opcode, 9); 6356 wback = BitIsSet (opcode, 8); 6357 6358 // if BadReg(t) || (wback && n == t) then UNPREDICTABLE; 6359 if (BadReg (t) || (wback && (n == t))) 6360 return false; 6361 break; 6362 6363 default: 6364 return false; 6365 } 6366 6367 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32); 6368 uint32_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success); 6369 if (!success) 6370 return false; 6371 6372 addr_t offset_addr; 6373 addr_t address; 6374 6375 if (add) 6376 offset_addr = Rn + imm32; 6377 else 6378 offset_addr = Rn - imm32; 6379 6380 // address = if index then offset_addr else R[n]; 6381 if (index) 6382 address = offset_addr; 6383 else 6384 address = Rn; 6385 6386 // data = MemU[address,2]; 6387 Register base_reg; 6388 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n); 6389 6390 EmulateInstruction::Context context; 6391 context.type = eContextRegisterLoad; 6392 context.SetRegisterPlusOffset (base_reg, address - Rn); 6393 6394 uint64_t data = MemURead (context, address, 2, 0, &success); 6395 if (!success) 6396 return false; 6397 6398 // if wback then R[n] = offset_addr; 6399 if (wback) 6400 { 6401 context.type = eContextAdjustBaseRegister; 6402 context.SetAddress (offset_addr); 6403 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr)) 6404 return false; 6405 } 6406 6407 // if UnalignedSupport() || address<0> = '0' then 6408 if (UnalignedSupport () || BitIsClear (address, 0)) 6409 { 6410 // R[t] = ZeroExtend(data, 32); 6411 context.type = eContextRegisterLoad; 6412 context.SetRegisterPlusOffset (base_reg, address - Rn); 6413 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data)) 6414 return false; 6415 } 6416 else // Can only apply before ARMv7 6417 { 6418 // R[t] = bits(32) UNKNOWN; 6419 WriteBits32Unknown (t); 6420 } 6421 } 6422 return true; 6423} 6424 6425// LDRH (literal) caculates an address from the PC value and an immediate offset, loads a halfword from memory, 6426// zero-extends it to form a 32-bit word, and writes it to a register. 6427bool 6428EmulateInstructionARM::EmulateLDRHLiteral (const uint32_t opcode, const ARMEncoding encoding) 6429{ 6430#if 0 6431 if ConditionPassed() then 6432 EncodingSpecificOperations(); NullCheckIfThumbEE(15); 6433 base = Align(PC,4); 6434 address = if add then (base + imm32) else (base - imm32); 6435 data = MemU[address,2]; 6436 if UnalignedSupport() || address<0> = '0' then 6437 R[t] = ZeroExtend(data, 32); 6438 else // Can only apply before ARMv7 6439 R[t] = bits(32) UNKNOWN; 6440#endif 6441 6442 bool success = false; 6443 6444 if (ConditionPassed(opcode)) 6445 { 6446 uint32_t t; 6447 uint32_t imm32; 6448 bool add; 6449 6450 // EncodingSpecificOperations(); NullCheckIfThumbEE(15); 6451 switch (encoding) 6452 { 6453 case eEncodingT1: 6454 // if Rt == '1111' then SEE "Unallocated memory hints"; 6455 // t = UInt(Rt); imm32 = ZeroExtend(imm12, 32); add = (U == '1'); 6456 t = Bits32 (opcode, 15, 12); 6457 imm32 = Bits32 (opcode, 11, 0); 6458 add = BitIsSet (opcode, 23); 6459 6460 // if t == 13 then UNPREDICTABLE; 6461 if (t == 13) 6462 return false; 6463 6464 break; 6465 6466 case eEncodingA1: 6467 { 6468 uint32_t imm4H = Bits32 (opcode, 11, 8); 6469 uint32_t imm4L = Bits32 (opcode, 3, 0); 6470 6471 // t == UInt(Rt); imm32 = ZeroExtend(imm4H:imm4L, 32); add = (U == '1'); 6472 t = Bits32 (opcode, 15, 12); 6473 imm32 = (imm4H << 4) | imm4L; 6474 add = BitIsSet (opcode, 23); 6475 6476 // if t == 15 then UNPREDICTABLE; 6477 if (t == 15) 6478 return false; 6479 break; 6480 } 6481 6482 default: 6483 return false; 6484 } 6485 6486 // base = Align(PC,4); 6487 uint64_t pc_value = ReadCoreReg (PC_REG, &success); 6488 if (!success) 6489 return false; 6490 6491 addr_t base = AlignPC (pc_value); 6492 addr_t address; 6493 6494 // address = if add then (base + imm32) else (base - imm32); 6495 if (add) 6496 address = base + imm32; 6497 else 6498 address = base - imm32; 6499 6500 // data = MemU[address,2]; 6501 Register base_reg; 6502 base_reg.SetRegister (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC); 6503 6504 EmulateInstruction::Context context; 6505 context.type = eContextRegisterLoad; 6506 context.SetRegisterPlusOffset (base_reg, address - base); 6507 6508 uint64_t data = MemURead (context, address, 2, 0, &success); 6509 if (!success) 6510 return false; 6511 6512 6513 // if UnalignedSupport() || address<0> = '0' then 6514 if (UnalignedSupport () || BitIsClear (address, 0)) 6515 { 6516 // R[t] = ZeroExtend(data, 32); 6517 context.type = eContextRegisterLoad; 6518 context.SetRegisterPlusOffset (base_reg, address - base); 6519 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data)) 6520 return false; 6521 6522 } 6523 else // Can only apply before ARMv7 6524 { 6525 // R[t] = bits(32) UNKNOWN; 6526 WriteBits32Unknown (t); 6527 } 6528 } 6529 return true; 6530} 6531 6532// LDRH (literal) calculates an address from a base register value and an offset register value, loads a halfword 6533// from memory, zero-extends it to form a 32-bit word, and writes it to a register. The offset register value can 6534// be shifted left by 0, 1, 2, or 3 bits. 6535bool 6536EmulateInstructionARM::EmulateLDRHRegister (const uint32_t opcode, const ARMEncoding encoding) 6537{ 6538#if 0 6539 if ConditionPassed() then 6540 EncodingSpecificOperations(); NullCheckIfThumbEE(n); 6541 offset = Shift(R[m], shift_t, shift_n, APSR.C); 6542 offset_addr = if add then (R[n] + offset) else (R[n] - offset); 6543 address = if index then offset_addr else R[n]; 6544 data = MemU[address,2]; 6545 if wback then R[n] = offset_addr; 6546 if UnalignedSupport() || address<0> = '0' then 6547 R[t] = ZeroExtend(data, 32); 6548 else // Can only apply before ARMv7 6549 R[t] = bits(32) UNKNOWN; 6550#endif 6551 6552 bool success = false; 6553 6554 if (ConditionPassed(opcode)) 6555 { 6556 uint32_t t; 6557 uint32_t n; 6558 uint32_t m; 6559 bool index; 6560 bool add; 6561 bool wback; 6562 ARM_ShifterType shift_t; 6563 uint32_t shift_n; 6564 6565 // EncodingSpecificOperations(); NullCheckIfThumbEE(n); 6566 switch (encoding) 6567 { 6568 case eEncodingT1: 6569 // if CurrentInstrSet() == InstrSet_ThumbEE then SEE "Modified operation in ThumbEE"; 6570 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm); 6571 t = Bits32 (opcode, 2, 0); 6572 n = Bits32 (opcode, 5, 3); 6573 m = Bits32 (opcode, 8, 6); 6574 6575 // index = TRUE; add = TRUE; wback = FALSE; 6576 index = true; 6577 add = true; 6578 wback = false; 6579 6580 // (shift_t, shift_n) = (SRType_LSL, 0); 6581 shift_t = SRType_LSL; 6582 shift_n = 0; 6583 6584 break; 6585 6586 case eEncodingT2: 6587 // if Rn == '1111' then SEE LDRH (literal); 6588 // if Rt == '1111' then SEE "Unallocated memory hints"; 6589 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm); 6590 t = Bits32 (opcode, 15, 12); 6591 n = Bits32 (opcode, 19, 16); 6592 m = Bits32 (opcode, 3, 0); 6593 6594 // index = TRUE; add = TRUE; wback = FALSE; 6595 index = true; 6596 add = true; 6597 wback = false; 6598 6599 // (shift_t, shift_n) = (SRType_LSL, UInt(imm2)); 6600 shift_t = SRType_LSL; 6601 shift_n = Bits32 (opcode, 5, 4); 6602 6603 // if t == 13 || BadReg(m) then UNPREDICTABLE; 6604 if ((t == 13) || BadReg (m)) 6605 return false; 6606 break; 6607 6608 case eEncodingA1: 6609 // if P == '0' && W == '1' then SEE LDRHT; 6610 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm); 6611 t = Bits32 (opcode, 15, 12); 6612 n = Bits32 (opcode, 19, 16); 6613 m = Bits32 (opcode, 3, 0); 6614 6615 // index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1'); 6616 index = BitIsSet (opcode, 24); 6617 add = BitIsSet (opcode, 23); 6618 wback = (BitIsClear (opcode, 24) || BitIsSet (opcode, 21)); 6619 6620 // (shift_t, shift_n) = (SRType_LSL, 0); 6621 shift_t = SRType_LSL; 6622 shift_n = 0; 6623 6624 // if t == 15 || m == 15 then UNPREDICTABLE; 6625 if ((t == 15) || (m == 15)) 6626 return false; 6627 6628 // if wback && (n == 15 || n == t) then UNPREDICTABLE; 6629 if (wback && ((n == 15) || (n == t))) 6630 return false; 6631 6632 break; 6633 6634 default: 6635 return false; 6636 } 6637 6638 // offset = Shift(R[m], shift_t, shift_n, APSR.C); 6639 6640 uint64_t Rm = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success); 6641 if (!success) 6642 return false; 6643 6644 addr_t offset = Shift (Rm, shift_t, shift_n, APSR_C); 6645 6646 addr_t offset_addr; 6647 addr_t address; 6648 6649 // offset_addr = if add then (R[n] + offset) else (R[n] - offset); 6650 uint64_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success); 6651 if (!success) 6652 return false; 6653 6654 if (add) 6655 offset_addr = Rn + offset; 6656 else 6657 offset_addr = Rn - offset; 6658 6659 // address = if index then offset_addr else R[n]; 6660 if (index) 6661 address = offset_addr; 6662 else 6663 address = Rn; 6664 6665 // data = MemU[address,2]; 6666 Register base_reg; 6667 Register offset_reg; 6668 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n); 6669 offset_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + m); 6670 6671 EmulateInstruction::Context context; 6672 context.type = eContextRegisterLoad; 6673 context.SetRegisterPlusIndirectOffset (base_reg, offset_reg); 6674 uint64_t data = MemURead (context, address, 2, 0, &success); 6675 if (!success) 6676 return false; 6677 6678 // if wback then R[n] = offset_addr; 6679 if (wback) 6680 { 6681 context.type = eContextAdjustBaseRegister; 6682 context.SetAddress (offset_addr); 6683 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr)) 6684 return false; 6685 } 6686 6687 // if UnalignedSupport() || address<0> = '0' then 6688 if (UnalignedSupport() || BitIsClear (address, 0)) 6689 { 6690 // R[t] = ZeroExtend(data, 32); 6691 context.type = eContextRegisterLoad; 6692 context.SetRegisterPlusIndirectOffset (base_reg, offset_reg); 6693 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data)) 6694 return false; 6695 } 6696 else // Can only apply before ARMv7 6697 { 6698 // R[t] = bits(32) UNKNOWN; 6699 WriteBits32Unknown (t); 6700 } 6701 } 6702 return true; 6703} 6704 6705// LDRSB (immediate) calculates an address from a base register value and an immediate offset, loads a byte from 6706// memory, sign-extends it to form a 32-bit word, and writes it to a register. It can use offset, post-indexed, 6707// or pre-indexed addressing. 6708bool 6709EmulateInstructionARM::EmulateLDRSBImmediate (const uint32_t opcode, const ARMEncoding encoding) 6710{ 6711#if 0 6712 if ConditionPassed() then 6713 EncodingSpecificOperations(); NullCheckIfThumbEE(n); 6714 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32); 6715 address = if index then offset_addr else R[n]; 6716 R[t] = SignExtend(MemU[address,1], 32); 6717 if wback then R[n] = offset_addr; 6718#endif 6719 6720 bool success = false; 6721 6722 if (ConditionPassed(opcode)) 6723 { 6724 uint32_t t; 6725 uint32_t n; 6726 uint32_t imm32; 6727 bool index; 6728 bool add; 6729 bool wback; 6730 6731 // EncodingSpecificOperations(); NullCheckIfThumbEE(n); 6732 switch (encoding) 6733 { 6734 case eEncodingT1: 6735 // if Rt == '1111' then SEE PLI; 6736 // if Rn == '1111' then SEE LDRSB (literal); 6737 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32); 6738 t = Bits32 (opcode, 15, 12); 6739 n = Bits32 (opcode, 19, 16); 6740 imm32 = Bits32 (opcode, 11, 0); 6741 6742 // index = TRUE; add = TRUE; wback = FALSE; 6743 index = true; 6744 add = true; 6745 wback = false; 6746 6747 // if t == 13 then UNPREDICTABLE; 6748 if (t == 13) 6749 return false; 6750 6751 break; 6752 6753 case eEncodingT2: 6754 // if Rt == '1111' && P == '1' && U == '0' && W == '0' then SEE PLI; 6755 // if Rn == '1111' then SEE LDRSB (literal); 6756 // if P == '1' && U == '1' && W == '0' then SEE LDRSBT; 6757 // if P == '0' && W == '0' then UNDEFINED; 6758 if (BitIsClear (opcode, 10) && BitIsClear (opcode, 8)) 6759 return false; 6760 6761 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32); 6762 t = Bits32 (opcode, 15, 12); 6763 n = Bits32 (opcode, 19, 16); 6764 imm32 = Bits32 (opcode, 7, 0); 6765 6766 // index = (P == '1'); add = (U == '1'); wback = (W == '1'); 6767 index = BitIsSet (opcode, 10); 6768 add = BitIsSet (opcode, 9); 6769 wback = BitIsSet (opcode, 8); 6770 6771 // if BadReg(t) || (wback && n == t) then UNPREDICTABLE; 6772 if (((t == 13) || ((t == 15) 6773 && (BitIsClear (opcode, 10) || BitIsSet (opcode, 9) || BitIsSet (opcode, 8)))) 6774 || (wback && (n == t))) 6775 return false; 6776 6777 break; 6778 6779 case eEncodingA1: 6780 { 6781 // if Rn == '1111' then SEE LDRSB (literal); 6782 // if P == '0' && W == '1' then SEE LDRSBT; 6783 // t == UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm4H:imm4L, 32); 6784 t = Bits32 (opcode, 15, 12); 6785 n = Bits32 (opcode, 19, 16); 6786 6787 uint32_t imm4H = Bits32 (opcode, 11, 8); 6788 uint32_t imm4L = Bits32 (opcode, 3, 0); 6789 imm32 = (imm4H << 4) | imm4L; 6790 6791 // index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1'); 6792 index = BitIsSet (opcode, 24); 6793 add = BitIsSet (opcode, 23); 6794 wback = (BitIsClear (opcode, 24) || BitIsSet (opcode, 21)); 6795 6796 // if t == 15 || (wback && n == t) then UNPREDICTABLE; 6797 if ((t == 15) || (wback && (n == t))) 6798 return false; 6799 6800 break; 6801 } 6802 6803 default: 6804 return false; 6805 } 6806 6807 uint64_t Rn = ReadCoreReg (n, &success); 6808 if (!success) 6809 return false; 6810 6811 addr_t offset_addr; 6812 addr_t address; 6813 6814 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32); 6815 if (add) 6816 offset_addr = Rn + imm32; 6817 else 6818 offset_addr = Rn - imm32; 6819 6820 // address = if index then offset_addr else R[n]; 6821 if (index) 6822 address = offset_addr; 6823 else 6824 address = Rn; 6825 6826 // R[t] = SignExtend(MemU[address,1], 32); 6827 Register base_reg; 6828 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n); 6829 6830 EmulateInstruction::Context context; 6831 context.type = eContextRegisterLoad; 6832 context.SetRegisterPlusOffset (base_reg, address - Rn); 6833 6834 uint64_t unsigned_data = MemURead (context, address, 1, 0, &success); 6835 if (!success) 6836 return false; 6837 6838 int64_t signed_data = llvm::SignExtend64<8>(unsigned_data); 6839 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, (uint64_t) signed_data)) 6840 return false; 6841 6842 // if wback then R[n] = offset_addr; 6843 if (wback) 6844 { 6845 context.type = eContextAdjustBaseRegister; 6846 context.SetAddress (offset_addr); 6847 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr)) 6848 return false; 6849 } 6850 } 6851 6852 return true; 6853} 6854 6855// LDRSB (literal) calculates an address from the PC value and an immediate offset, loads a byte from memory, 6856// sign-extends it to form a 32-bit word, and writes tit to a register. 6857bool 6858EmulateInstructionARM::EmulateLDRSBLiteral (const uint32_t opcode, const ARMEncoding encoding) 6859{ 6860#if 0 6861 if ConditionPassed() then 6862 EncodingSpecificOperations(); NullCheckIfThumbEE(15); 6863 base = Align(PC,4); 6864 address = if add then (base + imm32) else (base - imm32); 6865 R[t] = SignExtend(MemU[address,1], 32); 6866#endif 6867 6868 bool success = false; 6869 6870 if (ConditionPassed(opcode)) 6871 { 6872 uint32_t t; 6873 uint32_t imm32; 6874 bool add; 6875 6876 // EncodingSpecificOperations(); NullCheckIfThumbEE(15); 6877 switch (encoding) 6878 { 6879 case eEncodingT1: 6880 // if Rt == '1111' then SEE PLI; 6881 // t = UInt(Rt); imm32 = ZeroExtend(imm12, 32); add = (U == '1'); 6882 t = Bits32 (opcode, 15, 12); 6883 imm32 = Bits32 (opcode, 11, 0); 6884 add = BitIsSet (opcode, 23); 6885 6886 // if t == 13 then UNPREDICTABLE; 6887 if (t == 13) 6888 return false; 6889 6890 break; 6891 6892 case eEncodingA1: 6893 { 6894 // t == UInt(Rt); imm32 = ZeroExtend(imm4H:imm4L, 32); add = (U == '1'); 6895 t = Bits32 (opcode, 15, 12); 6896 uint32_t imm4H = Bits32 (opcode, 11, 8); 6897 uint32_t imm4L = Bits32 (opcode, 3, 0); 6898 imm32 = (imm4H << 4) | imm4L; 6899 add = BitIsSet (opcode, 23); 6900 6901 // if t == 15 then UNPREDICTABLE; 6902 if (t == 15) 6903 return false; 6904 6905 break; 6906 } 6907 6908 default: 6909 return false; 6910 } 6911 6912 // base = Align(PC,4); 6913 uint64_t pc_value = ReadCoreReg (PC_REG, &success); 6914 if (!success) 6915 return false; 6916 uint64_t base = AlignPC (pc_value); 6917 6918 // address = if add then (base + imm32) else (base - imm32); 6919 addr_t address; 6920 if (add) 6921 address = base + imm32; 6922 else 6923 address = base - imm32; 6924 6925 // R[t] = SignExtend(MemU[address,1], 32); 6926 Register base_reg; 6927 base_reg.SetRegister (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC); 6928 6929 EmulateInstruction::Context context; 6930 context.type = eContextRegisterLoad; 6931 context.SetRegisterPlusOffset (base_reg, address - base); 6932 6933 uint64_t unsigned_data = MemURead (context, address, 1, 0, &success); 6934 if (!success) 6935 return false; 6936 6937 int64_t signed_data = llvm::SignExtend64<8>(unsigned_data); 6938 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, (uint64_t) signed_data)) 6939 return false; 6940 } 6941 return true; 6942} 6943 6944// LDRSB (register) calculates an address from a base register value and an offset register value, loadsa byte from 6945// memory, sign-extends it to form a 32-bit word, and writes it to a register. The offset register value can be 6946// shifted left by 0, 1, 2, or 3 bits. 6947bool 6948EmulateInstructionARM::EmulateLDRSBRegister (const uint32_t opcode, const ARMEncoding encoding) 6949{ 6950#if 0 6951 if ConditionPassed() then 6952 EncodingSpecificOperations(); NullCheckIfThumbEE(n); 6953 offset = Shift(R[m], shift_t, shift_n, APSR.C); 6954 offset_addr = if add then (R[n] + offset) else (R[n] - offset); 6955 address = if index then offset_addr else R[n]; 6956 R[t] = SignExtend(MemU[address,1], 32); 6957 if wback then R[n] = offset_addr; 6958#endif 6959 6960 bool success = false; 6961 6962 if (ConditionPassed(opcode)) 6963 { 6964 uint32_t t; 6965 uint32_t n; 6966 uint32_t m; 6967 bool index; 6968 bool add; 6969 bool wback; 6970 ARM_ShifterType shift_t; 6971 uint32_t shift_n; 6972 6973 // EncodingSpecificOperations(); NullCheckIfThumbEE(n); 6974 switch (encoding) 6975 { 6976 case eEncodingT1: 6977 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm); 6978 t = Bits32 (opcode, 2, 0); 6979 n = Bits32 (opcode, 5, 3); 6980 m = Bits32 (opcode, 8, 6); 6981 6982 // index = TRUE; add = TRUE; wback = FALSE; 6983 index = true; 6984 add = true; 6985 wback = false; 6986 6987 // (shift_t, shift_n) = (SRType_LSL, 0); 6988 shift_t = SRType_LSL; 6989 shift_n = 0; 6990 6991 break; 6992 6993 case eEncodingT2: 6994 // if Rt == '1111' then SEE PLI; 6995 // if Rn == '1111' then SEE LDRSB (literal); 6996 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm); 6997 t = Bits32 (opcode, 15, 12); 6998 n = Bits32 (opcode, 19, 16); 6999 m = Bits32 (opcode, 3, 0); 7000 7001 // index = TRUE; add = TRUE; wback = FALSE; 7002 index = true; 7003 add = true; 7004 wback = false; 7005 7006 // (shift_t, shift_n) = (SRType_LSL, UInt(imm2)); 7007 shift_t = SRType_LSL; 7008 shift_n = Bits32 (opcode, 5, 4); 7009 7010 // if t == 13 || BadReg(m) then UNPREDICTABLE; 7011 if ((t == 13) || BadReg (m)) 7012 return false; 7013 break; 7014 7015 case eEncodingA1: 7016 // if P == '0' && W == '1' then SEE LDRSBT; 7017 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm); 7018 t = Bits32 (opcode, 15, 12); 7019 n = Bits32 (opcode, 19, 16); 7020 m = Bits32 (opcode, 3, 0); 7021 7022 // index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1'); 7023 index = BitIsSet (opcode, 24); 7024 add = BitIsSet (opcode, 23); 7025 wback = BitIsClear (opcode, 24) || BitIsSet (opcode, 21); 7026 7027 // (shift_t, shift_n) = (SRType_LSL, 0); 7028 shift_t = SRType_LSL; 7029 shift_n = 0; 7030 7031 // if t == 15 || m == 15 then UNPREDICTABLE; 7032 if ((t == 15) || (m == 15)) 7033 return false; 7034 7035 // if wback && (n == 15 || n == t) then UNPREDICTABLE; 7036 if (wback && ((n == 15) || (n == t))) 7037 return false; 7038 break; 7039 7040 default: 7041 return false; 7042 } 7043 7044 uint64_t Rm = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success); 7045 if (!success) 7046 return false; 7047 7048 // offset = Shift(R[m], shift_t, shift_n, APSR.C); 7049 addr_t offset = Shift (Rm, shift_t, shift_n, APSR_C); 7050 7051 addr_t offset_addr; 7052 addr_t address; 7053 7054 // offset_addr = if add then (R[n] + offset) else (R[n] - offset); 7055 uint64_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success); 7056 if (!success) 7057 return false; 7058 7059 if (add) 7060 offset_addr = Rn + offset; 7061 else 7062 offset_addr = Rn - offset; 7063 7064 // address = if index then offset_addr else R[n]; 7065 if (index) 7066 address = offset_addr; 7067 else 7068 address = Rn; 7069 7070 // R[t] = SignExtend(MemU[address,1], 32); 7071 Register base_reg; 7072 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n); 7073 Register offset_reg; 7074 offset_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + m); 7075 7076 EmulateInstruction::Context context; 7077 context.type = eContextRegisterLoad; 7078 context.SetRegisterPlusIndirectOffset (base_reg, offset_reg); 7079 7080 uint64_t unsigned_data = MemURead (context, address, 1, 0, &success); 7081 if (!success) 7082 return false; 7083 7084 int64_t signed_data = llvm::SignExtend64<8>(unsigned_data); 7085 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, (uint64_t) signed_data)) 7086 return false; 7087 7088 // if wback then R[n] = offset_addr; 7089 if (wback) 7090 { 7091 context.type = eContextAdjustBaseRegister; 7092 context.SetAddress (offset_addr); 7093 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr)) 7094 return false; 7095 } 7096 } 7097 return true; 7098} 7099 7100// LDRSH (immediate) calculates an address from a base register value and an immediate offset, loads a halfword from 7101// memory, sign-extends it to form a 32-bit word, and writes it to a register. It can use offset, post-indexed, or 7102// pre-indexed addressing. 7103bool 7104EmulateInstructionARM::EmulateLDRSHImmediate (const uint32_t opcode, const ARMEncoding encoding) 7105{ 7106#if 0 7107 if ConditionPassed() then 7108 EncodingSpecificOperations(); NullCheckIfThumbEE(n); 7109 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32); 7110 address = if index then offset_addr else R[n]; 7111 data = MemU[address,2]; 7112 if wback then R[n] = offset_addr; 7113 if UnalignedSupport() || address<0> = '0' then 7114 R[t] = SignExtend(data, 32); 7115 else // Can only apply before ARMv7 7116 R[t] = bits(32) UNKNOWN; 7117#endif 7118 7119 bool success = false; 7120 7121 if (ConditionPassed(opcode)) 7122 { 7123 uint32_t t; 7124 uint32_t n; 7125 uint32_t imm32; 7126 bool index; 7127 bool add; 7128 bool wback; 7129 7130 // EncodingSpecificOperations(); NullCheckIfThumbEE(n); 7131 switch (encoding) 7132 { 7133 case eEncodingT1: 7134 // if Rn == '1111' then SEE LDRSH (literal); 7135 // if Rt == '1111' then SEE "Unallocated memory hints"; 7136 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32); 7137 t = Bits32 (opcode, 15, 12); 7138 n = Bits32 (opcode, 19, 16); 7139 imm32 = Bits32 (opcode, 11, 0); 7140 7141 // index = TRUE; add = TRUE; wback = FALSE; 7142 index = true; 7143 add = true; 7144 wback = false; 7145 7146 // if t == 13 then UNPREDICTABLE; 7147 if (t == 13) 7148 return false; 7149 7150 break; 7151 7152 case eEncodingT2: 7153 // if Rn == '1111' then SEE LDRSH (literal); 7154 // if Rt == '1111' && P == '1' && U == '0' && W == '0' then SEE "Unallocated memory hints"; 7155 // if P == '1' && U == '1' && W == '0' then SEE LDRSHT; 7156 // if P == '0' && W == '0' then UNDEFINED; 7157 if (BitIsClear (opcode, 10) && BitIsClear (opcode, 8)) 7158 return false; 7159 7160 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32); 7161 t = Bits32 (opcode, 15, 12); 7162 n = Bits32 (opcode, 19, 16); 7163 imm32 = Bits32 (opcode, 7, 0); 7164 7165 // index = (P == '1'); add = (U == '1'); wback = (W == '1'); 7166 index = BitIsSet (opcode, 10); 7167 add = BitIsSet (opcode, 9); 7168 wback = BitIsSet (opcode, 8); 7169 7170 // if BadReg(t) || (wback && n == t) then UNPREDICTABLE; 7171 if (BadReg (t) || (wback && (n == t))) 7172 return false; 7173 7174 break; 7175 7176 case eEncodingA1: 7177 { 7178 // if Rn == '1111' then SEE LDRSH (literal); 7179 // if P == '0' && W == '1' then SEE LDRSHT; 7180 // t == UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm4H:imm4L, 32); 7181 t = Bits32 (opcode, 15, 12); 7182 n = Bits32 (opcode, 19, 16); 7183 uint32_t imm4H = Bits32 (opcode, 11,8); 7184 uint32_t imm4L = Bits32 (opcode, 3, 0); 7185 imm32 = (imm4H << 4) | imm4L; 7186 7187 // index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1'); 7188 index = BitIsSet (opcode, 24); 7189 add = BitIsSet (opcode, 23); 7190 wback = BitIsClear (opcode, 24) || BitIsSet (opcode, 21); 7191 7192 // if t == 15 || (wback && n == t) then UNPREDICTABLE; 7193 if ((t == 15) || (wback && (n == t))) 7194 return false; 7195 7196 break; 7197 } 7198 7199 default: 7200 return false; 7201 } 7202 7203 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32); 7204 uint64_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success); 7205 if (!success) 7206 return false; 7207 7208 addr_t offset_addr; 7209 if (add) 7210 offset_addr = Rn + imm32; 7211 else 7212 offset_addr = Rn - imm32; 7213 7214 // address = if index then offset_addr else R[n]; 7215 addr_t address; 7216 if (index) 7217 address = offset_addr; 7218 else 7219 address = Rn; 7220 7221 // data = MemU[address,2]; 7222 Register base_reg; 7223 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n); 7224 7225 EmulateInstruction::Context context; 7226 context.type = eContextRegisterLoad; 7227 context.SetRegisterPlusOffset (base_reg, address - Rn); 7228 7229 uint64_t data = MemURead (context, address, 2, 0, &success); 7230 if (!success) 7231 return false; 7232 7233 // if wback then R[n] = offset_addr; 7234 if (wback) 7235 { 7236 context.type = eContextAdjustBaseRegister; 7237 context.SetAddress (offset_addr); 7238 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr)) 7239 return false; 7240 } 7241 7242 // if UnalignedSupport() || address<0> = '0' then 7243 if (UnalignedSupport() || BitIsClear (address, 0)) 7244 { 7245 // R[t] = SignExtend(data, 32); 7246 int64_t signed_data = llvm::SignExtend64<16>(data); 7247 context.type = eContextRegisterLoad; 7248 context.SetRegisterPlusOffset (base_reg, address - Rn); 7249 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, (uint64_t) signed_data)) 7250 return false; 7251 } 7252 else // Can only apply before ARMv7 7253 { 7254 // R[t] = bits(32) UNKNOWN; 7255 WriteBits32Unknown (t); 7256 } 7257 } 7258 return true; 7259} 7260 7261// LDRSH (literal) calculates an address from the PC value and an immediate offset, loads a halfword from memory, 7262// sign-extends it to from a 32-bit word, and writes it to a register. 7263bool 7264EmulateInstructionARM::EmulateLDRSHLiteral (const uint32_t opcode, const ARMEncoding encoding) 7265{ 7266#if 0 7267 if ConditionPassed() then 7268 EncodingSpecificOperations(); NullCheckIfThumbEE(15); 7269 base = Align(PC,4); 7270 address = if add then (base + imm32) else (base - imm32); 7271 data = MemU[address,2]; 7272 if UnalignedSupport() || address<0> = '0' then 7273 R[t] = SignExtend(data, 32); 7274 else // Can only apply before ARMv7 7275 R[t] = bits(32) UNKNOWN; 7276#endif 7277 7278 bool success = false; 7279 7280 if (ConditionPassed(opcode)) 7281 { 7282 uint32_t t; 7283 uint32_t imm32; 7284 bool add; 7285 7286 // EncodingSpecificOperations(); NullCheckIfThumbEE(15); 7287 switch (encoding) 7288 { 7289 case eEncodingT1: 7290 // if Rt == '1111' then SEE "Unallocated memory hints"; 7291 // t = UInt(Rt); imm32 = ZeroExtend(imm12, 32); add = (U == '1'); 7292 t = Bits32 (opcode, 15, 12); 7293 imm32 = Bits32 (opcode, 11, 0); 7294 add = BitIsSet (opcode, 23); 7295 7296 // if t == 13 then UNPREDICTABLE; 7297 if (t == 13) 7298 return false; 7299 7300 break; 7301 7302 case eEncodingA1: 7303 { 7304 // t == UInt(Rt); imm32 = ZeroExtend(imm4H:imm4L, 32); add = (U == '1'); 7305 t = Bits32 (opcode, 15, 12); 7306 uint32_t imm4H = Bits32 (opcode, 11, 8); 7307 uint32_t imm4L = Bits32 (opcode, 3, 0); 7308 imm32 = (imm4H << 4) | imm4L; 7309 add = BitIsSet (opcode, 23); 7310 7311 // if t == 15 then UNPREDICTABLE; 7312 if (t == 15) 7313 return false; 7314 7315 break; 7316 } 7317 default: 7318 return false; 7319 } 7320 7321 // base = Align(PC,4); 7322 uint64_t pc_value = ReadCoreReg (PC_REG, &success); 7323 if (!success) 7324 return false; 7325 7326 uint64_t base = AlignPC (pc_value); 7327 7328 addr_t address; 7329 // address = if add then (base + imm32) else (base - imm32); 7330 if (add) 7331 address = base + imm32; 7332 else 7333 address = base - imm32; 7334 7335 // data = MemU[address,2]; 7336 Register base_reg; 7337 base_reg.SetRegister (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC); 7338 7339 EmulateInstruction::Context context; 7340 context.type = eContextRegisterLoad; 7341 context.SetRegisterPlusOffset (base_reg, imm32); 7342 7343 uint64_t data = MemURead (context, address, 2, 0, &success); 7344 if (!success) 7345 return false; 7346 7347 // if UnalignedSupport() || address<0> = '0' then 7348 if (UnalignedSupport() || BitIsClear (address, 0)) 7349 { 7350 // R[t] = SignExtend(data, 32); 7351 int64_t signed_data = llvm::SignExtend64<16>(data); 7352 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, (uint64_t) signed_data)) 7353 return false; 7354 } 7355 else // Can only apply before ARMv7 7356 { 7357 // R[t] = bits(32) UNKNOWN; 7358 WriteBits32Unknown (t); 7359 } 7360 } 7361 return true; 7362} 7363 7364// LDRSH (register) calculates an address from a base register value and an offset register value, loads a halfword 7365// from memory, sign-extends it to form a 32-bit word, and writes it to a register. The offset register value can be 7366// shifted left by 0, 1, 2, or 3 bits. 7367bool 7368EmulateInstructionARM::EmulateLDRSHRegister (const uint32_t opcode, const ARMEncoding encoding) 7369{ 7370#if 0 7371 if ConditionPassed() then 7372 EncodingSpecificOperations(); NullCheckIfThumbEE(n); 7373 offset = Shift(R[m], shift_t, shift_n, APSR.C); 7374 offset_addr = if add then (R[n] + offset) else (R[n] - offset); 7375 address = if index then offset_addr else R[n]; 7376 data = MemU[address,2]; 7377 if wback then R[n] = offset_addr; 7378 if UnalignedSupport() || address<0> = '0' then 7379 R[t] = SignExtend(data, 32); 7380 else // Can only apply before ARMv7 7381 R[t] = bits(32) UNKNOWN; 7382#endif 7383 7384 bool success = false; 7385 7386 if (ConditionPassed(opcode)) 7387 { 7388 uint32_t t; 7389 uint32_t n; 7390 uint32_t m; 7391 bool index; 7392 bool add; 7393 bool wback; 7394 ARM_ShifterType shift_t; 7395 uint32_t shift_n; 7396 7397 // EncodingSpecificOperations(); NullCheckIfThumbEE(n); 7398 switch (encoding) 7399 { 7400 case eEncodingT1: 7401 // if CurrentInstrSet() == InstrSet_ThumbEE then SEE "Modified operation in ThumbEE"; 7402 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm); 7403 t = Bits32 (opcode, 2, 0); 7404 n = Bits32 (opcode, 5, 3); 7405 m = Bits32 (opcode, 8, 6); 7406 7407 // index = TRUE; add = TRUE; wback = FALSE; 7408 index = true; 7409 add = true; 7410 wback = false; 7411 7412 // (shift_t, shift_n) = (SRType_LSL, 0); 7413 shift_t = SRType_LSL; 7414 shift_n = 0; 7415 7416 break; 7417 7418 case eEncodingT2: 7419 // if Rn == '1111' then SEE LDRSH (literal); 7420 // if Rt == '1111' then SEE "Unallocated memory hints"; 7421 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm); 7422 t = Bits32 (opcode, 15, 12); 7423 n = Bits32 (opcode, 19, 16); 7424 m = Bits32 (opcode, 3, 0); 7425 7426 // index = TRUE; add = TRUE; wback = FALSE; 7427 index = true; 7428 add = true; 7429 wback = false; 7430 7431 // (shift_t, shift_n) = (SRType_LSL, UInt(imm2)); 7432 shift_t = SRType_LSL; 7433 shift_n = Bits32 (opcode, 5, 4); 7434 7435 // if t == 13 || BadReg(m) then UNPREDICTABLE; 7436 if ((t == 13) || BadReg (m)) 7437 return false; 7438 7439 break; 7440 7441 case eEncodingA1: 7442 // if P == '0' && W == '1' then SEE LDRSHT; 7443 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm); 7444 t = Bits32 (opcode, 15, 12); 7445 n = Bits32 (opcode, 19, 16); 7446 m = Bits32 (opcode, 3, 0); 7447 7448 // index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1'); 7449 index = BitIsSet (opcode, 24); 7450 add = BitIsSet (opcode, 23); 7451 wback = BitIsClear (opcode, 24) || BitIsSet (opcode, 21); 7452 7453 // (shift_t, shift_n) = (SRType_LSL, 0); 7454 shift_t = SRType_LSL; 7455 shift_n = 0; 7456 7457 // if t == 15 || m == 15 then UNPREDICTABLE; 7458 if ((t == 15) || (m == 15)) 7459 return false; 7460 7461 // if wback && (n == 15 || n == t) then UNPREDICTABLE; 7462 if (wback && ((n == 15) || (n == t))) 7463 return false; 7464 7465 break; 7466 7467 default: 7468 break; 7469 } 7470 7471 uint64_t Rm = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success); 7472 if (!success) 7473 return false; 7474 7475 uint64_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success); 7476 if (!success) 7477 return false; 7478 7479 // offset = Shift(R[m], shift_t, shift_n, APSR.C); 7480 addr_t offset = Shift (Rm, shift_t, shift_n, APSR_C); 7481 7482 addr_t offset_addr; 7483 addr_t address; 7484 7485 // offset_addr = if add then (R[n] + offset) else (R[n] - offset); 7486 if (add) 7487 offset_addr = Rn + offset; 7488 else 7489 offset_addr = Rn - offset; 7490 7491 // address = if index then offset_addr else R[n]; 7492 if (index) 7493 address = offset_addr; 7494 else 7495 address = Rn; 7496 7497 // data = MemU[address,2]; 7498 Register base_reg; 7499 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n); 7500 7501 Register offset_reg; 7502 offset_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + m); 7503 7504 EmulateInstruction::Context context; 7505 context.type = eContextRegisterLoad; 7506 context.SetRegisterPlusIndirectOffset (base_reg, offset_reg); 7507 7508 uint64_t data = MemURead (context, address, 2, 0, &success); 7509 if (!success) 7510 return false; 7511 7512 // if wback then R[n] = offset_addr; 7513 if (wback) 7514 { 7515 context.type = eContextAdjustBaseRegister; 7516 context.SetAddress (offset_addr); 7517 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr)) 7518 return false; 7519 } 7520 7521 // if UnalignedSupport() || address<0> = '0' then 7522 if (UnalignedSupport() || BitIsClear (address, 0)) 7523 { 7524 // R[t] = SignExtend(data, 32); 7525 context.type = eContextRegisterLoad; 7526 context.SetRegisterPlusIndirectOffset (base_reg, offset_reg); 7527 7528 int64_t signed_data = llvm::SignExtend64<16>(data); 7529 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, (uint64_t) signed_data)) 7530 return false; 7531 } 7532 else // Can only apply before ARMv7 7533 { 7534 // R[t] = bits(32) UNKNOWN; 7535 WriteBits32Unknown (t); 7536 } 7537 } 7538 return true; 7539} 7540 7541// SXTB extracts an 8-bit value from a register, sign-extends it to 32 bits, and writes the result to the destination 7542// register. You can specifiy a rotation by 0, 8, 16, or 24 bits before extracting the 8-bit value. 7543bool 7544EmulateInstructionARM::EmulateSXTB (const uint32_t opcode, const ARMEncoding encoding) 7545{ 7546#if 0 7547 if ConditionPassed() then 7548 EncodingSpecificOperations(); 7549 rotated = ROR(R[m], rotation); 7550 R[d] = SignExtend(rotated<7:0>, 32); 7551#endif 7552 7553 bool success = false; 7554 7555 if (ConditionPassed(opcode)) 7556 { 7557 uint32_t d; 7558 uint32_t m; 7559 uint32_t rotation; 7560 7561 // EncodingSpecificOperations(); 7562 switch (encoding) 7563 { 7564 case eEncodingT1: 7565 // d = UInt(Rd); m = UInt(Rm); rotation = 0; 7566 d = Bits32 (opcode, 2, 0); 7567 m = Bits32 (opcode, 5, 3); 7568 rotation = 0; 7569 7570 break; 7571 7572 case eEncodingT2: 7573 // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:'000'); 7574 d = Bits32 (opcode, 11, 8); 7575 m = Bits32 (opcode, 3, 0); 7576 rotation = Bits32 (opcode, 5, 4) << 3; 7577 7578 // if BadReg(d) || BadReg(m) then UNPREDICTABLE; 7579 if (BadReg (d) || BadReg (m)) 7580 return false; 7581 7582 break; 7583 7584 case eEncodingA1: 7585 // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:'000'); 7586 d = Bits32 (opcode, 15, 12); 7587 m = Bits32 (opcode, 3, 0); 7588 rotation = Bits32 (opcode, 11, 10) << 3; 7589 7590 // if d == 15 || m == 15 then UNPREDICTABLE; 7591 if ((d == 15) || (m == 15)) 7592 return false; 7593 7594 break; 7595 7596 default: 7597 return false; 7598 } 7599 7600 uint64_t Rm = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success); 7601 if (!success) 7602 return false; 7603 7604 // rotated = ROR(R[m], rotation); 7605 uint64_t rotated = ROR (Rm, rotation); 7606 7607 // R[d] = SignExtend(rotated<7:0>, 32); 7608 int64_t data = llvm::SignExtend64<8>(rotated); 7609 7610 Register source_reg; 7611 source_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + m); 7612 7613 EmulateInstruction::Context context; 7614 context.type = eContextRegisterLoad; 7615 context.SetRegister (source_reg); 7616 7617 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + d, (uint64_t) data)) 7618 return false; 7619 } 7620 return true; 7621} 7622 7623// SXTH extracts a 16-bit value from a register, sign-extends it to 32 bits, and writes the result to the destination 7624// register. You can specify a rotation by 0, 8, 16, or 24 bits before extracting the 16-bit value. 7625bool 7626EmulateInstructionARM::EmulateSXTH (const uint32_t opcode, const ARMEncoding encoding) 7627{ 7628#if 0 7629 if ConditionPassed() then 7630 EncodingSpecificOperations(); 7631 rotated = ROR(R[m], rotation); 7632 R[d] = SignExtend(rotated<15:0>, 32); 7633#endif 7634 7635 bool success = false; 7636 7637 if (ConditionPassed(opcode)) 7638 { 7639 uint32_t d; 7640 uint32_t m; 7641 uint32_t rotation; 7642 7643 // EncodingSpecificOperations(); 7644 switch (encoding) 7645 { 7646 case eEncodingT1: 7647 // d = UInt(Rd); m = UInt(Rm); rotation = 0; 7648 d = Bits32 (opcode, 2, 0); 7649 m = Bits32 (opcode, 5, 3); 7650 rotation = 0; 7651 7652 break; 7653 7654 case eEncodingT2: 7655 // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:'000'); 7656 d = Bits32 (opcode, 11, 8); 7657 m = Bits32 (opcode, 3, 0); 7658 rotation = Bits32 (opcode, 5, 4) << 3; 7659 7660 // if BadReg(d) || BadReg(m) then UNPREDICTABLE; 7661 if (BadReg (d) || BadReg (m)) 7662 return false; 7663 7664 break; 7665 7666 case eEncodingA1: 7667 // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:'000'); 7668 d = Bits32 (opcode, 15, 12); 7669 m = Bits32 (opcode, 3, 0); 7670 rotation = Bits32 (opcode, 11, 10) << 3; 7671 7672 // if d == 15 || m == 15 then UNPREDICTABLE; 7673 if ((d == 15) || (m == 15)) 7674 return false; 7675 7676 break; 7677 7678 default: 7679 return false; 7680 } 7681 7682 uint64_t Rm = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success); 7683 if (!success) 7684 return false; 7685 7686 // rotated = ROR(R[m], rotation); 7687 uint64_t rotated = ROR (Rm, rotation); 7688 7689 // R[d] = SignExtend(rotated<15:0>, 32); 7690 Register source_reg; 7691 source_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + m); 7692 7693 EmulateInstruction::Context context; 7694 context.type = eContextRegisterLoad; 7695 context.SetRegister (source_reg); 7696 7697 int64_t data = llvm::SignExtend64<16> (rotated); 7698 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + d, (uint64_t) data)) 7699 return false; 7700 } 7701 7702 return true; 7703} 7704 7705// UXTB extracts an 8-bit value from a register, zero-extneds it to 32 bits, and writes the result to the destination 7706// register. You can specify a rotation by 0, 8, 16, or 24 bits before extracting the 8-bit value. 7707bool 7708EmulateInstructionARM::EmulateUXTB (const uint32_t opcode, const ARMEncoding encoding) 7709{ 7710#if 0 7711 if ConditionPassed() then 7712 EncodingSpecificOperations(); 7713 rotated = ROR(R[m], rotation); 7714 R[d] = ZeroExtend(rotated<7:0>, 32); 7715#endif 7716 7717 bool success = false; 7718 7719 if (ConditionPassed(opcode)) 7720 { 7721 uint32_t d; 7722 uint32_t m; 7723 uint32_t rotation; 7724 7725 // EncodingSpecificOperations(); 7726 switch (encoding) 7727 { 7728 case eEncodingT1: 7729 // d = UInt(Rd); m = UInt(Rm); rotation = 0; 7730 d = Bits32 (opcode, 2, 0); 7731 m = Bits32 (opcode, 5, 3); 7732 rotation = 0; 7733 7734 break; 7735 7736 case eEncodingT2: 7737 // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:'000'); 7738 d = Bits32 (opcode, 11, 8); 7739 m = Bits32 (opcode, 3, 0); 7740 rotation = Bits32 (opcode, 5, 4) << 3; 7741 7742 // if BadReg(d) || BadReg(m) then UNPREDICTABLE; 7743 if (BadReg (d) || BadReg (m)) 7744 return false; 7745 7746 break; 7747 7748 case eEncodingA1: 7749 // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:'000'); 7750 d = Bits32 (opcode, 15, 12); 7751 m = Bits32 (opcode, 3, 0); 7752 rotation = Bits32 (opcode, 11, 10) << 3; 7753 7754 // if d == 15 || m == 15 then UNPREDICTABLE; 7755 if ((d == 15) || (m == 15)) 7756 return false; 7757 7758 break; 7759 7760 default: 7761 return false; 7762 } 7763 7764 uint64_t Rm = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success); 7765 if (!success) 7766 return false; 7767 7768 // rotated = ROR(R[m], rotation); 7769 uint64_t rotated = ROR (Rm, rotation); 7770 7771 // R[d] = ZeroExtend(rotated<7:0>, 32); 7772 Register source_reg; 7773 source_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + m); 7774 7775 EmulateInstruction::Context context; 7776 context.type = eContextRegisterLoad; 7777 context.SetRegister (source_reg); 7778 7779 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + d, Bits32 (rotated, 7, 0))) 7780 return false; 7781 } 7782 return true; 7783} 7784 7785// UXTH extracts a 16-bit value from a register, zero-extends it to 32 bits, and writes the result to the destination 7786// register. You can specify a rotation by 0, 8, 16, or 24 bits before extracting the 16-bit value. 7787bool 7788EmulateInstructionARM::EmulateUXTH (const uint32_t opcode, const ARMEncoding encoding) 7789{ 7790#if 0 7791 if ConditionPassed() then 7792 EncodingSpecificOperations(); 7793 rotated = ROR(R[m], rotation); 7794 R[d] = ZeroExtend(rotated<15:0>, 32); 7795#endif 7796 7797 bool success = false; 7798 7799 if (ConditionPassed(opcode)) 7800 { 7801 uint32_t d; 7802 uint32_t m; 7803 uint32_t rotation; 7804 7805 switch (encoding) 7806 { 7807 case eEncodingT1: 7808 // d = UInt(Rd); m = UInt(Rm); rotation = 0; 7809 d = Bits32 (opcode, 2, 0); 7810 m = Bits32 (opcode, 5, 3); 7811 rotation = 0; 7812 7813 break; 7814 7815 case eEncodingT2: 7816 // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:'000'); 7817 d = Bits32 (opcode, 11, 8); 7818 m = Bits32 (opcode, 3, 0); 7819 rotation = Bits32 (opcode, 5, 4) << 3; 7820 7821 // if BadReg(d) || BadReg(m) then UNPREDICTABLE; 7822 if (BadReg (d) || BadReg (m)) 7823 return false; 7824 7825 break; 7826 7827 case eEncodingA1: 7828 // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:'000'); 7829 d = Bits32 (opcode, 15, 12); 7830 m = Bits32 (opcode, 3, 0); 7831 rotation = Bits32 (opcode, 11, 10) << 3; 7832 7833 // if d == 15 || m == 15 then UNPREDICTABLE; 7834 if ((d == 15) || (m == 15)) 7835 return false; 7836 7837 break; 7838 7839 default: 7840 return false; 7841 } 7842 7843 uint64_t Rm = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success); 7844 if (!success) 7845 return false; 7846 7847 // rotated = ROR(R[m], rotation); 7848 uint64_t rotated = ROR (Rm, rotation); 7849 7850 // R[d] = ZeroExtend(rotated<15:0>, 32); 7851 Register source_reg; 7852 source_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + m); 7853 7854 EmulateInstruction::Context context; 7855 context.type = eContextRegisterLoad; 7856 context.SetRegister (source_reg); 7857 7858 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + d, Bits32 (rotated, 15, 0))) 7859 return false; 7860 } 7861 return true; 7862} 7863 7864// RFE (Return From Exception) loads the PC and the CPSR from the word at the specified address and the following 7865// word respectively. 7866bool 7867EmulateInstructionARM::EmulateRFE (const uint32_t opcode, const ARMEncoding encoding) 7868{ 7869#if 0 7870 if ConditionPassed() then 7871 EncodingSpecificOperations(); 7872 if !CurrentModeIsPrivileged() || CurrentInstrSet() == InstrSet_ThumbEE then 7873 UNPREDICTABLE; 7874 else 7875 address = if increment then R[n] else R[n]-8; 7876 if wordhigher then address = address+4; 7877 CPSRWriteByInstr(MemA[address+4,4], '1111', TRUE); 7878 BranchWritePC(MemA[address,4]); 7879 if wback then R[n] = if increment then R[n]+8 else R[n]-8; 7880#endif 7881 7882 bool success = false; 7883 7884 if (ConditionPassed(opcode)) 7885 { 7886 uint32_t n; 7887 bool wback; 7888 bool increment; 7889 bool wordhigher; 7890 7891 // EncodingSpecificOperations(); 7892 switch (encoding) 7893 { 7894 case eEncodingT1: 7895 // n = UInt(Rn); wback = (W == '1'); increment = FALSE; wordhigher = FALSE; 7896 n = Bits32 (opcode, 19, 16); 7897 wback = BitIsSet (opcode, 21); 7898 increment = false; 7899 wordhigher = false; 7900 7901 // if n == 15 then UNPREDICTABLE; 7902 if (n == 15) 7903 return false; 7904 7905 // if InITBlock() && !LastInITBlock() then UNPREDICTABLE; 7906 if (InITBlock() && !LastInITBlock()) 7907 return false; 7908 7909 break; 7910 7911 case eEncodingT2: 7912 // n = UInt(Rn); wback = (W == '1'); increment = TRUE; wordhigher = FALSE; 7913 n = Bits32 (opcode, 19, 16); 7914 wback = BitIsSet (opcode, 21); 7915 increment = true; 7916 wordhigher = false; 7917 7918 // if n == 15 then UNPREDICTABLE; 7919 if (n == 15) 7920 return false; 7921 7922 // if InITBlock() && !LastInITBlock() then UNPREDICTABLE; 7923 if (InITBlock() && !LastInITBlock()) 7924 return false; 7925 7926 break; 7927 7928 case eEncodingA1: 7929 // n = UInt(Rn); 7930 n = Bits32 (opcode, 19, 16); 7931 7932 // wback = (W == '1'); inc = (U == '1'); wordhigher = (P == U); 7933 wback = BitIsSet (opcode, 21); 7934 increment = BitIsSet (opcode, 23); 7935 wordhigher = (Bit32 (opcode, 24) == Bit32 (opcode, 23)); 7936 7937 // if n == 15 then UNPREDICTABLE; 7938 if (n == 15) 7939 return false; 7940 7941 break; 7942 7943 default: 7944 return false; 7945 } 7946 7947 // if !CurrentModeIsPrivileged() || CurrentInstrSet() == InstrSet_ThumbEE then 7948 if (!CurrentModeIsPrivileged ()) 7949 // UNPREDICTABLE; 7950 return false; 7951 else 7952 { 7953 uint64_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success); 7954 if (!success) 7955 return false; 7956 7957 addr_t address; 7958 // address = if increment then R[n] else R[n]-8; 7959 if (increment) 7960 address = Rn; 7961 else 7962 address = Rn - 8; 7963 7964 // if wordhigher then address = address+4; 7965 if (wordhigher) 7966 address = address + 4; 7967 7968 // CPSRWriteByInstr(MemA[address+4,4], '1111', TRUE); 7969 Register base_reg; 7970 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n); 7971 7972 EmulateInstruction::Context context; 7973 context.type = eContextReturnFromException; 7974 context.SetRegisterPlusOffset (base_reg, address - Rn); 7975 7976 uint64_t data = MemARead (context, address + 4, 4, 0, &success); 7977 if (!success) 7978 return false; 7979 7980 CPSRWriteByInstr (data, 15, true); 7981 7982 // BranchWritePC(MemA[address,4]); 7983 uint64_t data2 = MemARead (context, address, 4, 0, &success); 7984 if (!success) 7985 return false; 7986 7987 BranchWritePC (context, data2); 7988 7989 // if wback then R[n] = if increment then R[n]+8 else R[n]-8; 7990 if (wback) 7991 { 7992 context.type = eContextAdjustBaseRegister; 7993 if (increment) 7994 { 7995 context.SetOffset (8); 7996 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, Rn + 8)) 7997 return false; 7998 } 7999 else 8000 { 8001 context.SetOffset (-8); 8002 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, Rn - 8)) 8003 return false; 8004 } 8005 } // if wback 8006 } 8007 } // if ConditionPassed() 8008 return true; 8009} 8010 8011// Bitwise Exclusive OR (immediate) performs a bitwise exclusive OR of a register value and an immediate value, 8012// and writes the result to the destination register. It can optionally update the condition flags based on 8013// the result. 8014bool 8015EmulateInstructionARM::EmulateEORImm (const uint32_t opcode, const ARMEncoding encoding) 8016{ 8017#if 0 8018 // ARM pseudo code... 8019 if ConditionPassed() then 8020 EncodingSpecificOperations(); 8021 result = R[n] EOR imm32; 8022 if d == 15 then // Can only occur for ARM encoding 8023 ALUWritePC(result); // setflags is always FALSE here 8024 else 8025 R[d] = result; 8026 if setflags then 8027 APSR.N = result<31>; 8028 APSR.Z = IsZeroBit(result); 8029 APSR.C = carry; 8030 // APSR.V unchanged 8031#endif 8032 8033 bool success = false; 8034 8035 if (ConditionPassed(opcode)) 8036 { 8037 uint32_t Rd, Rn; 8038 uint32_t imm32; // the immediate value to be ORed to the value obtained from Rn 8039 bool setflags; 8040 uint32_t carry; // the carry bit after ARM/Thumb Expand operation 8041 switch (encoding) 8042 { 8043 case eEncodingT1: 8044 Rd = Bits32(opcode, 11, 8); 8045 Rn = Bits32(opcode, 19, 16); 8046 setflags = BitIsSet(opcode, 20); 8047 imm32 = ThumbExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C) 8048 // if Rd == '1111' && S == '1' then SEE TEQ (immediate); 8049 if (Rd == 15 && setflags) 8050 return EmulateTEQImm (opcode, eEncodingT1); 8051 if (Rd == 13 || (Rd == 15 && !setflags) || BadReg(Rn)) 8052 return false; 8053 break; 8054 case eEncodingA1: 8055 Rd = Bits32(opcode, 15, 12); 8056 Rn = Bits32(opcode, 19, 16); 8057 setflags = BitIsSet(opcode, 20); 8058 imm32 = ARMExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ARMExpandImm(imm12, APSR.C) 8059 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions; 8060 // TODO: Emulate SUBS PC, LR and related instructions. 8061 if (Rd == 15 && setflags) 8062 return false; 8063 break; 8064 default: 8065 return false; 8066 } 8067 8068 // Read the first operand. 8069 uint32_t val1 = ReadCoreReg(Rn, &success); 8070 if (!success) 8071 return false; 8072 8073 uint32_t result = val1 ^ imm32; 8074 8075 EmulateInstruction::Context context; 8076 context.type = EmulateInstruction::eContextImmediate; 8077 context.SetNoArgs (); 8078 8079 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry)) 8080 return false; 8081 } 8082 return true; 8083} 8084 8085// Bitwise Exclusive OR (register) performs a bitwise exclusive OR of a register value and an 8086// optionally-shifted register value, and writes the result to the destination register. 8087// It can optionally update the condition flags based on the result. 8088bool 8089EmulateInstructionARM::EmulateEORReg (const uint32_t opcode, const ARMEncoding encoding) 8090{ 8091#if 0 8092 // ARM pseudo code... 8093 if ConditionPassed() then 8094 EncodingSpecificOperations(); 8095 (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C); 8096 result = R[n] EOR shifted; 8097 if d == 15 then // Can only occur for ARM encoding 8098 ALUWritePC(result); // setflags is always FALSE here 8099 else 8100 R[d] = result; 8101 if setflags then 8102 APSR.N = result<31>; 8103 APSR.Z = IsZeroBit(result); 8104 APSR.C = carry; 8105 // APSR.V unchanged 8106#endif 8107 8108 bool success = false; 8109 8110 if (ConditionPassed(opcode)) 8111 { 8112 uint32_t Rd, Rn, Rm; 8113 ARM_ShifterType shift_t; 8114 uint32_t shift_n; // the shift applied to the value read from Rm 8115 bool setflags; 8116 uint32_t carry; 8117 switch (encoding) 8118 { 8119 case eEncodingT1: 8120 Rd = Rn = Bits32(opcode, 2, 0); 8121 Rm = Bits32(opcode, 5, 3); 8122 setflags = !InITBlock(); 8123 shift_t = SRType_LSL; 8124 shift_n = 0; 8125 break; 8126 case eEncodingT2: 8127 Rd = Bits32(opcode, 11, 8); 8128 Rn = Bits32(opcode, 19, 16); 8129 Rm = Bits32(opcode, 3, 0); 8130 setflags = BitIsSet(opcode, 20); 8131 shift_n = DecodeImmShiftThumb(opcode, shift_t); 8132 // if Rd == '1111' && S == '1' then SEE TEQ (register); 8133 if (Rd == 15 && setflags) 8134 return EmulateTEQReg (opcode, eEncodingT1); 8135 if (Rd == 13 || (Rd == 15 && !setflags) || BadReg(Rn) || BadReg(Rm)) 8136 return false; 8137 break; 8138 case eEncodingA1: 8139 Rd = Bits32(opcode, 15, 12); 8140 Rn = Bits32(opcode, 19, 16); 8141 Rm = Bits32(opcode, 3, 0); 8142 setflags = BitIsSet(opcode, 20); 8143 shift_n = DecodeImmShiftARM(opcode, shift_t); 8144 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions; 8145 // TODO: Emulate SUBS PC, LR and related instructions. 8146 if (Rd == 15 && setflags) 8147 return false; 8148 break; 8149 default: 8150 return false; 8151 } 8152 8153 // Read the first operand. 8154 uint32_t val1 = ReadCoreReg(Rn, &success); 8155 if (!success) 8156 return false; 8157 8158 // Read the second operand. 8159 uint32_t val2 = ReadCoreReg(Rm, &success); 8160 if (!success) 8161 return false; 8162 8163 uint32_t shifted = Shift_C(val2, shift_t, shift_n, APSR_C, carry); 8164 uint32_t result = val1 ^ shifted; 8165 8166 EmulateInstruction::Context context; 8167 context.type = EmulateInstruction::eContextImmediate; 8168 context.SetNoArgs (); 8169 8170 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry)) 8171 return false; 8172 } 8173 return true; 8174} 8175 8176// Bitwise OR (immediate) performs a bitwise (inclusive) OR of a register value and an immediate value, and 8177// writes the result to the destination register. It can optionally update the condition flags based 8178// on the result. 8179bool 8180EmulateInstructionARM::EmulateORRImm (const uint32_t opcode, const ARMEncoding encoding) 8181{ 8182#if 0 8183 // ARM pseudo code... 8184 if ConditionPassed() then 8185 EncodingSpecificOperations(); 8186 result = R[n] OR imm32; 8187 if d == 15 then // Can only occur for ARM encoding 8188 ALUWritePC(result); // setflags is always FALSE here 8189 else 8190 R[d] = result; 8191 if setflags then 8192 APSR.N = result<31>; 8193 APSR.Z = IsZeroBit(result); 8194 APSR.C = carry; 8195 // APSR.V unchanged 8196#endif 8197 8198 bool success = false; 8199 8200 if (ConditionPassed(opcode)) 8201 { 8202 uint32_t Rd, Rn; 8203 uint32_t imm32; // the immediate value to be ORed to the value obtained from Rn 8204 bool setflags; 8205 uint32_t carry; // the carry bit after ARM/Thumb Expand operation 8206 switch (encoding) 8207 { 8208 case eEncodingT1: 8209 Rd = Bits32(opcode, 11, 8); 8210 Rn = Bits32(opcode, 19, 16); 8211 setflags = BitIsSet(opcode, 20); 8212 imm32 = ThumbExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C) 8213 // if Rn == '1111' then SEE MOV (immediate); 8214 if (Rn == 15) 8215 return EmulateMOVRdImm (opcode, eEncodingT2); 8216 if (BadReg(Rd) || Rn == 13) 8217 return false; 8218 break; 8219 case eEncodingA1: 8220 Rd = Bits32(opcode, 15, 12); 8221 Rn = Bits32(opcode, 19, 16); 8222 setflags = BitIsSet(opcode, 20); 8223 imm32 = ARMExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ARMExpandImm(imm12, APSR.C) 8224 // TODO: Emulate SUBS PC, LR and related instructions. 8225 if (Rd == 15 && setflags) 8226 return false; 8227 break; 8228 default: 8229 return false; 8230 } 8231 8232 // Read the first operand. 8233 uint32_t val1 = ReadCoreReg(Rn, &success); 8234 if (!success) 8235 return false; 8236 8237 uint32_t result = val1 | imm32; 8238 8239 EmulateInstruction::Context context; 8240 context.type = EmulateInstruction::eContextImmediate; 8241 context.SetNoArgs (); 8242 8243 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry)) 8244 return false; 8245 } 8246 return true; 8247} 8248 8249// Bitwise OR (register) performs a bitwise (inclusive) OR of a register value and an optionally-shifted register 8250// value, and writes the result to the destination register. It can optionally update the condition flags based 8251// on the result. 8252bool 8253EmulateInstructionARM::EmulateORRReg (const uint32_t opcode, const ARMEncoding encoding) 8254{ 8255#if 0 8256 // ARM pseudo code... 8257 if ConditionPassed() then 8258 EncodingSpecificOperations(); 8259 (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C); 8260 result = R[n] OR shifted; 8261 if d == 15 then // Can only occur for ARM encoding 8262 ALUWritePC(result); // setflags is always FALSE here 8263 else 8264 R[d] = result; 8265 if setflags then 8266 APSR.N = result<31>; 8267 APSR.Z = IsZeroBit(result); 8268 APSR.C = carry; 8269 // APSR.V unchanged 8270#endif 8271 8272 bool success = false; 8273 8274 if (ConditionPassed(opcode)) 8275 { 8276 uint32_t Rd, Rn, Rm; 8277 ARM_ShifterType shift_t; 8278 uint32_t shift_n; // the shift applied to the value read from Rm 8279 bool setflags; 8280 uint32_t carry; 8281 switch (encoding) 8282 { 8283 case eEncodingT1: 8284 Rd = Rn = Bits32(opcode, 2, 0); 8285 Rm = Bits32(opcode, 5, 3); 8286 setflags = !InITBlock(); 8287 shift_t = SRType_LSL; 8288 shift_n = 0; 8289 break; 8290 case eEncodingT2: 8291 Rd = Bits32(opcode, 11, 8); 8292 Rn = Bits32(opcode, 19, 16); 8293 Rm = Bits32(opcode, 3, 0); 8294 setflags = BitIsSet(opcode, 20); 8295 shift_n = DecodeImmShiftThumb(opcode, shift_t); 8296 // if Rn == '1111' then SEE MOV (register); 8297 if (Rn == 15) 8298 return EmulateMOVRdRm (opcode, eEncodingT3); 8299 if (BadReg(Rd) || Rn == 13 || BadReg(Rm)) 8300 return false; 8301 break; 8302 case eEncodingA1: 8303 Rd = Bits32(opcode, 15, 12); 8304 Rn = Bits32(opcode, 19, 16); 8305 Rm = Bits32(opcode, 3, 0); 8306 setflags = BitIsSet(opcode, 20); 8307 shift_n = DecodeImmShiftARM(opcode, shift_t); 8308 // TODO: Emulate SUBS PC, LR and related instructions. 8309 if (Rd == 15 && setflags) 8310 return false; 8311 break; 8312 default: 8313 return false; 8314 } 8315 8316 // Read the first operand. 8317 uint32_t val1 = ReadCoreReg(Rn, &success); 8318 if (!success) 8319 return false; 8320 8321 // Read the second operand. 8322 uint32_t val2 = ReadCoreReg(Rm, &success); 8323 if (!success) 8324 return false; 8325 8326 uint32_t shifted = Shift_C(val2, shift_t, shift_n, APSR_C, carry); 8327 uint32_t result = val1 | shifted; 8328 8329 EmulateInstruction::Context context; 8330 context.type = EmulateInstruction::eContextImmediate; 8331 context.SetNoArgs (); 8332 8333 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry)) 8334 return false; 8335 } 8336 return true; 8337} 8338 8339// Reverse Subtract (immediate) subtracts a register value from an immediate value, and writes the result to 8340// the destination register. It can optionally update the condition flags based on the result. 8341bool 8342EmulateInstructionARM::EmulateRSBImm (const uint32_t opcode, const ARMEncoding encoding) 8343{ 8344#if 0 8345 // ARM pseudo code... 8346 if ConditionPassed() then 8347 EncodingSpecificOperations(); 8348 (result, carry, overflow) = AddWithCarry(NOT(R[n]), imm32, '1'); 8349 if d == 15 then // Can only occur for ARM encoding 8350 ALUWritePC(result); // setflags is always FALSE here 8351 else 8352 R[d] = result; 8353 if setflags then 8354 APSR.N = result<31>; 8355 APSR.Z = IsZeroBit(result); 8356 APSR.C = carry; 8357 APSR.V = overflow; 8358#endif 8359 8360 bool success = false; 8361 8362 uint32_t Rd; // the destination register 8363 uint32_t Rn; // the first operand 8364 bool setflags; 8365 uint32_t imm32; // the immediate value to be added to the value obtained from Rn 8366 switch (encoding) { 8367 case eEncodingT1: 8368 Rd = Bits32(opcode, 2, 0); 8369 Rn = Bits32(opcode, 5, 3); 8370 setflags = !InITBlock(); 8371 imm32 = 0; 8372 break; 8373 case eEncodingT2: 8374 Rd = Bits32(opcode, 11, 8); 8375 Rn = Bits32(opcode, 19, 16); 8376 setflags = BitIsSet(opcode, 20); 8377 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8) 8378 if (BadReg(Rd) || BadReg(Rn)) 8379 return false; 8380 break; 8381 case eEncodingA1: 8382 Rd = Bits32(opcode, 15, 12); 8383 Rn = Bits32(opcode, 19, 16); 8384 setflags = BitIsSet(opcode, 20); 8385 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12) 8386 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions; 8387 // TODO: Emulate SUBS PC, LR and related instructions. 8388 if (Rd == 15 && setflags) 8389 return false; 8390 break; 8391 default: 8392 return false; 8393 } 8394 // Read the register value from the operand register Rn. 8395 uint32_t reg_val = ReadCoreReg(Rn, &success); 8396 if (!success) 8397 return false; 8398 8399 AddWithCarryResult res = AddWithCarry(~reg_val, imm32, 1); 8400 8401 EmulateInstruction::Context context; 8402 context.type = EmulateInstruction::eContextImmediate; 8403 context.SetNoArgs (); 8404 8405 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow)) 8406 return false; 8407 8408 return true; 8409} 8410 8411// Reverse Subtract (register) subtracts a register value from an optionally-shifted register value, and writes the 8412// result to the destination register. It can optionally update the condition flags based on the result. 8413bool 8414EmulateInstructionARM::EmulateRSBReg (const uint32_t opcode, const ARMEncoding encoding) 8415{ 8416#if 0 8417 // ARM pseudo code... 8418 if ConditionPassed() then 8419 EncodingSpecificOperations(); 8420 shifted = Shift(R[m], shift_t, shift_n, APSR.C); 8421 (result, carry, overflow) = AddWithCarry(NOT(R[n]), shifted, '1'); 8422 if d == 15 then // Can only occur for ARM encoding 8423 ALUWritePC(result); // setflags is always FALSE here 8424 else 8425 R[d] = result; 8426 if setflags then 8427 APSR.N = result<31>; 8428 APSR.Z = IsZeroBit(result); 8429 APSR.C = carry; 8430 APSR.V = overflow; 8431#endif 8432 8433 bool success = false; 8434 8435 uint32_t Rd; // the destination register 8436 uint32_t Rn; // the first operand 8437 uint32_t Rm; // the second operand 8438 bool setflags; 8439 ARM_ShifterType shift_t; 8440 uint32_t shift_n; // the shift applied to the value read from Rm 8441 switch (encoding) { 8442 case eEncodingT1: 8443 Rd = Bits32(opcode, 11, 8); 8444 Rn = Bits32(opcode, 19, 16); 8445 Rm = Bits32(opcode, 3, 0); 8446 setflags = BitIsSet(opcode, 20); 8447 shift_n = DecodeImmShiftThumb(opcode, shift_t); 8448 // if (BadReg(d) || BadReg(m)) then UNPREDICTABLE; 8449 if (BadReg(Rd) || BadReg(Rn) || BadReg(Rm)) 8450 return false; 8451 break; 8452 case eEncodingA1: 8453 Rd = Bits32(opcode, 15, 12); 8454 Rn = Bits32(opcode, 19, 16); 8455 Rm = Bits32(opcode, 3, 0); 8456 setflags = BitIsSet(opcode, 20); 8457 shift_n = DecodeImmShiftARM(opcode, shift_t); 8458 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions; 8459 // TODO: Emulate SUBS PC, LR and related instructions. 8460 if (Rd == 15 && setflags) 8461 return false; 8462 break; 8463 default: 8464 return false; 8465 } 8466 // Read the register value from register Rn. 8467 uint32_t val1 = ReadCoreReg(Rn, &success); 8468 if (!success) 8469 return false; 8470 8471 // Read the register value from register Rm. 8472 uint32_t val2 = ReadCoreReg(Rm, &success); 8473 if (!success) 8474 return false; 8475 8476 uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C); 8477 AddWithCarryResult res = AddWithCarry(~val1, shifted, 1); 8478 8479 EmulateInstruction::Context context; 8480 context.type = EmulateInstruction::eContextImmediate; 8481 context.SetNoArgs(); 8482 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow)) 8483 return false; 8484 8485 return true; 8486} 8487 8488// Reverse Subtract with Carry (immediate) subtracts a register value and the value of NOT (Carry flag) from 8489// an immediate value, and writes the result to the destination register. It can optionally update the condition 8490// flags based on the result. 8491bool 8492EmulateInstructionARM::EmulateRSCImm (const uint32_t opcode, const ARMEncoding encoding) 8493{ 8494#if 0 8495 // ARM pseudo code... 8496 if ConditionPassed() then 8497 EncodingSpecificOperations(); 8498 (result, carry, overflow) = AddWithCarry(NOT(R[n]), imm32, APSR.C); 8499 if d == 15 then 8500 ALUWritePC(result); // setflags is always FALSE here 8501 else 8502 R[d] = result; 8503 if setflags then 8504 APSR.N = result<31>; 8505 APSR.Z = IsZeroBit(result); 8506 APSR.C = carry; 8507 APSR.V = overflow; 8508#endif 8509 8510 bool success = false; 8511 8512 uint32_t Rd; // the destination register 8513 uint32_t Rn; // the first operand 8514 bool setflags; 8515 uint32_t imm32; // the immediate value to be added to the value obtained from Rn 8516 switch (encoding) { 8517 case eEncodingA1: 8518 Rd = Bits32(opcode, 15, 12); 8519 Rn = Bits32(opcode, 19, 16); 8520 setflags = BitIsSet(opcode, 20); 8521 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12) 8522 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions; 8523 // TODO: Emulate SUBS PC, LR and related instructions. 8524 if (Rd == 15 && setflags) 8525 return false; 8526 break; 8527 default: 8528 return false; 8529 } 8530 // Read the register value from the operand register Rn. 8531 uint32_t reg_val = ReadCoreReg(Rn, &success); 8532 if (!success) 8533 return false; 8534 8535 AddWithCarryResult res = AddWithCarry(~reg_val, imm32, APSR_C); 8536 8537 EmulateInstruction::Context context; 8538 context.type = EmulateInstruction::eContextImmediate; 8539 context.SetNoArgs (); 8540 8541 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow)) 8542 return false; 8543 8544 return true; 8545} 8546 8547// Reverse Subtract with Carry (register) subtracts a register value and the value of NOT (Carry flag) from an 8548// optionally-shifted register value, and writes the result to the destination register. It can optionally update the 8549// condition flags based on the result. 8550bool 8551EmulateInstructionARM::EmulateRSCReg (const uint32_t opcode, const ARMEncoding encoding) 8552{ 8553#if 0 8554 // ARM pseudo code... 8555 if ConditionPassed() then 8556 EncodingSpecificOperations(); 8557 shifted = Shift(R[m], shift_t, shift_n, APSR.C); 8558 (result, carry, overflow) = AddWithCarry(NOT(R[n]), shifted, APSR.C); 8559 if d == 15 then 8560 ALUWritePC(result); // setflags is always FALSE here 8561 else 8562 R[d] = result; 8563 if setflags then 8564 APSR.N = result<31>; 8565 APSR.Z = IsZeroBit(result); 8566 APSR.C = carry; 8567 APSR.V = overflow; 8568#endif 8569 8570 bool success = false; 8571 8572 uint32_t Rd; // the destination register 8573 uint32_t Rn; // the first operand 8574 uint32_t Rm; // the second operand 8575 bool setflags; 8576 ARM_ShifterType shift_t; 8577 uint32_t shift_n; // the shift applied to the value read from Rm 8578 switch (encoding) { 8579 case eEncodingA1: 8580 Rd = Bits32(opcode, 15, 12); 8581 Rn = Bits32(opcode, 19, 16); 8582 Rm = Bits32(opcode, 3, 0); 8583 setflags = BitIsSet(opcode, 20); 8584 shift_n = DecodeImmShiftARM(opcode, shift_t); 8585 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions; 8586 // TODO: Emulate SUBS PC, LR and related instructions. 8587 if (Rd == 15 && setflags) 8588 return false; 8589 break; 8590 default: 8591 return false; 8592 } 8593 // Read the register value from register Rn. 8594 uint32_t val1 = ReadCoreReg(Rn, &success); 8595 if (!success) 8596 return false; 8597 8598 // Read the register value from register Rm. 8599 uint32_t val2 = ReadCoreReg(Rm, &success); 8600 if (!success) 8601 return false; 8602 8603 uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C); 8604 AddWithCarryResult res = AddWithCarry(~val1, shifted, APSR_C); 8605 8606 EmulateInstruction::Context context; 8607 context.type = EmulateInstruction::eContextImmediate; 8608 context.SetNoArgs(); 8609 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow)) 8610 return false; 8611 8612 return true; 8613} 8614 8615// Subtract with Carry (immediate) subtracts an immediate value and the value of 8616// NOT (Carry flag) from a register value, and writes the result to the destination register. 8617// It can optionally update the condition flags based on the result. 8618bool 8619EmulateInstructionARM::EmulateSBCImm (const uint32_t opcode, const ARMEncoding encoding) 8620{ 8621#if 0 8622 // ARM pseudo code... 8623 if ConditionPassed() then 8624 EncodingSpecificOperations(); 8625 (result, carry, overflow) = AddWithCarry(R[n], NOT(imm32), APSR.C); 8626 if d == 15 then // Can only occur for ARM encoding 8627 ALUWritePC(result); // setflags is always FALSE here 8628 else 8629 R[d] = result; 8630 if setflags then 8631 APSR.N = result<31>; 8632 APSR.Z = IsZeroBit(result); 8633 APSR.C = carry; 8634 APSR.V = overflow; 8635#endif 8636 8637 bool success = false; 8638 8639 uint32_t Rd; // the destination register 8640 uint32_t Rn; // the first operand 8641 bool setflags; 8642 uint32_t imm32; // the immediate value to be added to the value obtained from Rn 8643 switch (encoding) { 8644 case eEncodingT1: 8645 Rd = Bits32(opcode, 11, 8); 8646 Rn = Bits32(opcode, 19, 16); 8647 setflags = BitIsSet(opcode, 20); 8648 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8) 8649 if (BadReg(Rd) || BadReg(Rn)) 8650 return false; 8651 break; 8652 case eEncodingA1: 8653 Rd = Bits32(opcode, 15, 12); 8654 Rn = Bits32(opcode, 19, 16); 8655 setflags = BitIsSet(opcode, 20); 8656 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12) 8657 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions; 8658 // TODO: Emulate SUBS PC, LR and related instructions. 8659 if (Rd == 15 && setflags) 8660 return false; 8661 break; 8662 default: 8663 return false; 8664 } 8665 // Read the register value from the operand register Rn. 8666 uint32_t reg_val = ReadCoreReg(Rn, &success); 8667 if (!success) 8668 return false; 8669 8670 AddWithCarryResult res = AddWithCarry(reg_val, ~imm32, APSR_C); 8671 8672 EmulateInstruction::Context context; 8673 context.type = EmulateInstruction::eContextImmediate; 8674 context.SetNoArgs (); 8675 8676 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow)) 8677 return false; 8678 8679 return true; 8680} 8681 8682// Subtract with Carry (register) subtracts an optionally-shifted register value and the value of 8683// NOT (Carry flag) from a register value, and writes the result to the destination register. 8684// It can optionally update the condition flags based on the result. 8685bool 8686EmulateInstructionARM::EmulateSBCReg (const uint32_t opcode, const ARMEncoding encoding) 8687{ 8688#if 0 8689 // ARM pseudo code... 8690 if ConditionPassed() then 8691 EncodingSpecificOperations(); 8692 shifted = Shift(R[m], shift_t, shift_n, APSR.C); 8693 (result, carry, overflow) = AddWithCarry(R[n], NOT(shifted), APSR.C); 8694 if d == 15 then // Can only occur for ARM encoding 8695 ALUWritePC(result); // setflags is always FALSE here 8696 else 8697 R[d] = result; 8698 if setflags then 8699 APSR.N = result<31>; 8700 APSR.Z = IsZeroBit(result); 8701 APSR.C = carry; 8702 APSR.V = overflow; 8703#endif 8704 8705 bool success = false; 8706 8707 uint32_t Rd; // the destination register 8708 uint32_t Rn; // the first operand 8709 uint32_t Rm; // the second operand 8710 bool setflags; 8711 ARM_ShifterType shift_t; 8712 uint32_t shift_n; // the shift applied to the value read from Rm 8713 switch (encoding) { 8714 case eEncodingT1: 8715 Rd = Rn = Bits32(opcode, 2, 0); 8716 Rm = Bits32(opcode, 5, 3); 8717 setflags = !InITBlock(); 8718 shift_t = SRType_LSL; 8719 shift_n = 0; 8720 break; 8721 case eEncodingT2: 8722 Rd = Bits32(opcode, 11, 8); 8723 Rn = Bits32(opcode, 19, 16); 8724 Rm = Bits32(opcode, 3, 0); 8725 setflags = BitIsSet(opcode, 20); 8726 shift_n = DecodeImmShiftThumb(opcode, shift_t); 8727 if (BadReg(Rd) || BadReg(Rn) || BadReg(Rm)) 8728 return false; 8729 break; 8730 case eEncodingA1: 8731 Rd = Bits32(opcode, 15, 12); 8732 Rn = Bits32(opcode, 19, 16); 8733 Rm = Bits32(opcode, 3, 0); 8734 setflags = BitIsSet(opcode, 20); 8735 shift_n = DecodeImmShiftARM(opcode, shift_t); 8736 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions; 8737 // TODO: Emulate SUBS PC, LR and related instructions. 8738 if (Rd == 15 && setflags) 8739 return false; 8740 break; 8741 default: 8742 return false; 8743 } 8744 // Read the register value from register Rn. 8745 uint32_t val1 = ReadCoreReg(Rn, &success); 8746 if (!success) 8747 return false; 8748 8749 // Read the register value from register Rm. 8750 uint32_t val2 = ReadCoreReg(Rm, &success); 8751 if (!success) 8752 return false; 8753 8754 uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C); 8755 AddWithCarryResult res = AddWithCarry(val1, ~shifted, APSR_C); 8756 8757 EmulateInstruction::Context context; 8758 context.type = EmulateInstruction::eContextImmediate; 8759 context.SetNoArgs(); 8760 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow)) 8761 return false; 8762 8763 return true; 8764} 8765 8766// This instruction subtracts an immediate value from a register value, and writes the result 8767// to the destination register. It can optionally update the condition flags based on the result. 8768bool 8769EmulateInstructionARM::EmulateSUBImmThumb (const uint32_t opcode, const ARMEncoding encoding) 8770{ 8771#if 0 8772 // ARM pseudo code... 8773 if ConditionPassed() then 8774 EncodingSpecificOperations(); 8775 (result, carry, overflow) = AddWithCarry(R[n], NOT(imm32), '1'); 8776 R[d] = result; 8777 if setflags then 8778 APSR.N = result<31>; 8779 APSR.Z = IsZeroBit(result); 8780 APSR.C = carry; 8781 APSR.V = overflow; 8782#endif 8783 8784 bool success = false; 8785 8786 uint32_t Rd; // the destination register 8787 uint32_t Rn; // the first operand 8788 bool setflags; 8789 uint32_t imm32; // the immediate value to be subtracted from the value obtained from Rn 8790 switch (encoding) { 8791 case eEncodingT1: 8792 Rd = Bits32(opcode, 2, 0); 8793 Rn = Bits32(opcode, 5, 3); 8794 setflags = !InITBlock(); 8795 imm32 = Bits32(opcode, 8, 6); // imm32 = ZeroExtend(imm3, 32) 8796 break; 8797 case eEncodingT2: 8798 Rd = Rn = Bits32(opcode, 10, 8); 8799 setflags = !InITBlock(); 8800 imm32 = Bits32(opcode, 7, 0); // imm32 = ZeroExtend(imm8, 32) 8801 break; 8802 case eEncodingT3: 8803 Rd = Bits32(opcode, 11, 8); 8804 Rn = Bits32(opcode, 19, 16); 8805 setflags = BitIsSet(opcode, 20); 8806 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8) 8807 8808 // if Rd == '1111' && S == '1' then SEE CMP (immediate); 8809 if (Rd == 15 && setflags) 8810 return EmulateCMPImm (opcode, eEncodingT2); 8811 8812 // if Rn == '1101' then SEE SUB (SP minus immediate); 8813 if (Rn == 13) 8814 return EmulateSUBSPImm (opcode, eEncodingT2); 8815 8816 // if d == 13 || (d == 15 && S == '0') || n == 15 then UNPREDICTABLE; 8817 if (Rd == 13 || (Rd == 15 && !setflags) || Rn == 15) 8818 return false; 8819 break; 8820 case eEncodingT4: 8821 Rd = Bits32(opcode, 11, 8); 8822 Rn = Bits32(opcode, 19, 16); 8823 setflags = BitIsSet(opcode, 20); 8824 imm32 = ThumbImm12(opcode); // imm32 = ZeroExtend(i:imm3:imm8, 32) 8825 8826 // if Rn == '1111' then SEE ADR; 8827 if (Rn == 15) 8828 return EmulateADR (opcode, eEncodingT2); 8829 8830 // if Rn == '1101' then SEE SUB (SP minus immediate); 8831 if (Rn == 13) 8832 return EmulateSUBSPImm (opcode, eEncodingT3); 8833 8834 if (BadReg(Rd)) 8835 return false; 8836 break; 8837 default: 8838 return false; 8839 } 8840 // Read the register value from the operand register Rn. 8841 uint32_t reg_val = ReadCoreReg(Rn, &success); 8842 if (!success) 8843 return false; 8844 8845 AddWithCarryResult res = AddWithCarry(reg_val, ~imm32, 1); 8846 8847 EmulateInstruction::Context context; 8848 context.type = EmulateInstruction::eContextImmediate; 8849 context.SetNoArgs (); 8850 8851 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow)) 8852 return false; 8853 8854 return true; 8855} 8856 8857// This instruction subtracts an immediate value from a register value, and writes the result 8858// to the destination register. It can optionally update the condition flags based on the result. 8859bool 8860EmulateInstructionARM::EmulateSUBImmARM (const uint32_t opcode, const ARMEncoding encoding) 8861{ 8862#if 0 8863 // ARM pseudo code... 8864 if ConditionPassed() then 8865 EncodingSpecificOperations(); 8866 (result, carry, overflow) = AddWithCarry(R[n], NOT(imm32), '1'); 8867 if d == 15 then 8868 ALUWritePC(result); // setflags is always FALSE here 8869 else 8870 R[d] = result; 8871 if setflags then 8872 APSR.N = result<31>; 8873 APSR.Z = IsZeroBit(result); 8874 APSR.C = carry; 8875 APSR.V = overflow; 8876#endif 8877 8878 bool success = false; 8879 8880 uint32_t Rd; // the destination register 8881 uint32_t Rn; // the first operand 8882 bool setflags; 8883 uint32_t imm32; // the immediate value to be subtracted from the value obtained from Rn 8884 switch (encoding) { 8885 case eEncodingA1: 8886 Rd = Bits32(opcode, 15, 12); 8887 Rn = Bits32(opcode, 19, 16); 8888 setflags = BitIsSet(opcode, 20); 8889 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12) 8890 8891 // if Rn == '1111' && S == '0' then SEE ADR; 8892 if (Rn == 15 && !setflags) 8893 return EmulateADR (opcode, eEncodingA2); 8894 8895 // if Rn == '1101' then SEE SUB (SP minus immediate); 8896 if (Rn == 13) 8897 return EmulateSUBSPImm (opcode, eEncodingA1); 8898 8899 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions; 8900 // TODO: Emulate SUBS PC, LR and related instructions. 8901 if (Rd == 15 && setflags) 8902 return false; 8903 break; 8904 default: 8905 return false; 8906 } 8907 // Read the register value from the operand register Rn. 8908 uint32_t reg_val = ReadCoreReg(Rn, &success); 8909 if (!success) 8910 return false; 8911 8912 AddWithCarryResult res = AddWithCarry(reg_val, ~imm32, 1); 8913 8914 EmulateInstruction::Context context; 8915 context.type = EmulateInstruction::eContextImmediate; 8916 context.SetNoArgs (); 8917 8918 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow)) 8919 return false; 8920 8921 return true; 8922} 8923 8924// Test Equivalence (immediate) performs a bitwise exclusive OR operation on a register value and an 8925// immediate value. It updates the condition flags based on the result, and discards the result. 8926bool 8927EmulateInstructionARM::EmulateTEQImm (const uint32_t opcode, const ARMEncoding encoding) 8928{ 8929#if 0 8930 // ARM pseudo code... 8931 if ConditionPassed() then 8932 EncodingSpecificOperations(); 8933 result = R[n] EOR imm32; 8934 APSR.N = result<31>; 8935 APSR.Z = IsZeroBit(result); 8936 APSR.C = carry; 8937 // APSR.V unchanged 8938#endif 8939 8940 bool success = false; 8941 8942 if (ConditionPassed(opcode)) 8943 { 8944 uint32_t Rn; 8945 uint32_t imm32; // the immediate value to be ANDed to the value obtained from Rn 8946 uint32_t carry; // the carry bit after ARM/Thumb Expand operation 8947 switch (encoding) 8948 { 8949 case eEncodingT1: 8950 Rn = Bits32(opcode, 19, 16); 8951 imm32 = ThumbExpandImm_C (opcode, APSR_C, carry); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C) 8952 if (BadReg(Rn)) 8953 return false; 8954 break; 8955 case eEncodingA1: 8956 Rn = Bits32(opcode, 19, 16); 8957 imm32 = ARMExpandImm_C (opcode, APSR_C, carry); // (imm32, carry) = ARMExpandImm(imm12, APSR.C) 8958 break; 8959 default: 8960 return false; 8961 } 8962 8963 // Read the first operand. 8964 uint32_t val1 = ReadCoreReg(Rn, &success); 8965 if (!success) 8966 return false; 8967 8968 uint32_t result = val1 ^ imm32; 8969 8970 EmulateInstruction::Context context; 8971 context.type = EmulateInstruction::eContextImmediate; 8972 context.SetNoArgs (); 8973 8974 if (!WriteFlags(context, result, carry)) 8975 return false; 8976 } 8977 return true; 8978} 8979 8980// Test Equivalence (register) performs a bitwise exclusive OR operation on a register value and an 8981// optionally-shifted register value. It updates the condition flags based on the result, and discards 8982// the result. 8983bool 8984EmulateInstructionARM::EmulateTEQReg (const uint32_t opcode, const ARMEncoding encoding) 8985{ 8986#if 0 8987 // ARM pseudo code... 8988 if ConditionPassed() then 8989 EncodingSpecificOperations(); 8990 (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C); 8991 result = R[n] EOR shifted; 8992 APSR.N = result<31>; 8993 APSR.Z = IsZeroBit(result); 8994 APSR.C = carry; 8995 // APSR.V unchanged 8996#endif 8997 8998 bool success = false; 8999 9000 if (ConditionPassed(opcode)) 9001 { 9002 uint32_t Rn, Rm; 9003 ARM_ShifterType shift_t; 9004 uint32_t shift_n; // the shift applied to the value read from Rm 9005 uint32_t carry; 9006 switch (encoding) 9007 { 9008 case eEncodingT1: 9009 Rn = Bits32(opcode, 19, 16); 9010 Rm = Bits32(opcode, 3, 0); 9011 shift_n = DecodeImmShiftThumb(opcode, shift_t); 9012 if (BadReg(Rn) || BadReg(Rm)) 9013 return false; 9014 break; 9015 case eEncodingA1: 9016 Rn = Bits32(opcode, 19, 16); 9017 Rm = Bits32(opcode, 3, 0); 9018 shift_n = DecodeImmShiftARM(opcode, shift_t); 9019 break; 9020 default: 9021 return false; 9022 } 9023 9024 // Read the first operand. 9025 uint32_t val1 = ReadCoreReg(Rn, &success); 9026 if (!success) 9027 return false; 9028 9029 // Read the second operand. 9030 uint32_t val2 = ReadCoreReg(Rm, &success); 9031 if (!success) 9032 return false; 9033 9034 uint32_t shifted = Shift_C(val2, shift_t, shift_n, APSR_C, carry); 9035 uint32_t result = val1 ^ shifted; 9036 9037 EmulateInstruction::Context context; 9038 context.type = EmulateInstruction::eContextImmediate; 9039 context.SetNoArgs (); 9040 9041 if (!WriteFlags(context, result, carry)) 9042 return false; 9043 } 9044 return true; 9045} 9046 9047// Test (immediate) performs a bitwise AND operation on a register value and an immediate value. 9048// It updates the condition flags based on the result, and discards the result. 9049bool 9050EmulateInstructionARM::EmulateTSTImm (const uint32_t opcode, const ARMEncoding encoding) 9051{ 9052#if 0 9053 // ARM pseudo code... 9054 if ConditionPassed() then 9055 EncodingSpecificOperations(); 9056 result = R[n] AND imm32; 9057 APSR.N = result<31>; 9058 APSR.Z = IsZeroBit(result); 9059 APSR.C = carry; 9060 // APSR.V unchanged 9061#endif 9062 9063 bool success = false; 9064 9065 if (ConditionPassed(opcode)) 9066 { 9067 uint32_t Rn; 9068 uint32_t imm32; // the immediate value to be ANDed to the value obtained from Rn 9069 uint32_t carry; // the carry bit after ARM/Thumb Expand operation 9070 switch (encoding) 9071 { 9072 case eEncodingT1: 9073 Rn = Bits32(opcode, 19, 16); 9074 imm32 = ThumbExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C) 9075 if (BadReg(Rn)) 9076 return false; 9077 break; 9078 case eEncodingA1: 9079 Rn = Bits32(opcode, 19, 16); 9080 imm32 = ARMExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ARMExpandImm(imm12, APSR.C) 9081 break; 9082 default: 9083 return false; 9084 } 9085 9086 // Read the first operand. 9087 uint32_t val1 = ReadCoreReg(Rn, &success); 9088 if (!success) 9089 return false; 9090 9091 uint32_t result = val1 & imm32; 9092 9093 EmulateInstruction::Context context; 9094 context.type = EmulateInstruction::eContextImmediate; 9095 context.SetNoArgs (); 9096 9097 if (!WriteFlags(context, result, carry)) 9098 return false; 9099 } 9100 return true; 9101} 9102 9103// Test (register) performs a bitwise AND operation on a register value and an optionally-shifted register value. 9104// It updates the condition flags based on the result, and discards the result. 9105bool 9106EmulateInstructionARM::EmulateTSTReg (const uint32_t opcode, const ARMEncoding encoding) 9107{ 9108#if 0 9109 // ARM pseudo code... 9110 if ConditionPassed() then 9111 EncodingSpecificOperations(); 9112 (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C); 9113 result = R[n] AND shifted; 9114 APSR.N = result<31>; 9115 APSR.Z = IsZeroBit(result); 9116 APSR.C = carry; 9117 // APSR.V unchanged 9118#endif 9119 9120 bool success = false; 9121 9122 if (ConditionPassed(opcode)) 9123 { 9124 uint32_t Rn, Rm; 9125 ARM_ShifterType shift_t; 9126 uint32_t shift_n; // the shift applied to the value read from Rm 9127 uint32_t carry; 9128 switch (encoding) 9129 { 9130 case eEncodingT1: 9131 Rn = Bits32(opcode, 2, 0); 9132 Rm = Bits32(opcode, 5, 3); 9133 shift_t = SRType_LSL; 9134 shift_n = 0; 9135 break; 9136 case eEncodingT2: 9137 Rn = Bits32(opcode, 19, 16); 9138 Rm = Bits32(opcode, 3, 0); 9139 shift_n = DecodeImmShiftThumb(opcode, shift_t); 9140 if (BadReg(Rn) || BadReg(Rm)) 9141 return false; 9142 break; 9143 case eEncodingA1: 9144 Rn = Bits32(opcode, 19, 16); 9145 Rm = Bits32(opcode, 3, 0); 9146 shift_n = DecodeImmShiftARM(opcode, shift_t); 9147 break; 9148 default: 9149 return false; 9150 } 9151 9152 // Read the first operand. 9153 uint32_t val1 = ReadCoreReg(Rn, &success); 9154 if (!success) 9155 return false; 9156 9157 // Read the second operand. 9158 uint32_t val2 = ReadCoreReg(Rm, &success); 9159 if (!success) 9160 return false; 9161 9162 uint32_t shifted = Shift_C(val2, shift_t, shift_n, APSR_C, carry); 9163 uint32_t result = val1 & shifted; 9164 9165 EmulateInstruction::Context context; 9166 context.type = EmulateInstruction::eContextImmediate; 9167 context.SetNoArgs (); 9168 9169 if (!WriteFlags(context, result, carry)) 9170 return false; 9171 } 9172 return true; 9173} 9174 9175// A8.6.216 SUB (SP minus register) 9176bool 9177EmulateInstructionARM::EmulateSUBSPReg (const uint32_t opcode, const ARMEncoding encoding) 9178{ 9179#if 0 9180 if ConditionPassed() then 9181 EncodingSpecificOperations(); 9182 shifted = Shift(R[m], shift_t, shift_n, APSR.C); 9183 (result, carry, overflow) = AddWithCarry(SP, NOT(shifted), ‘1’); 9184 if d == 15 then // Can only occur for ARM encoding 9185 ALUWritePC(result); // setflags is always FALSE here 9186 else 9187 R[d] = result; 9188 if setflags then 9189 APSR.N = result<31>; 9190 APSR.Z = IsZeroBit(result); 9191 APSR.C = carry; 9192 APSR.V = overflow; 9193#endif 9194 9195 bool success = false; 9196 9197 if (ConditionPassed(opcode)) 9198 { 9199 uint32_t d; 9200 uint32_t m; 9201 bool setflags; 9202 ARM_ShifterType shift_t; 9203 uint32_t shift_n; 9204 9205 switch (encoding) 9206 { 9207 case eEncodingT1: 9208 // d = UInt(Rd); m = UInt(Rm); setflags = (S == ‘1’); 9209 d = Bits32 (opcode, 11, 8); 9210 m = Bits32 (opcode, 3, 0); 9211 setflags = BitIsSet (opcode, 20); 9212 9213 // (shift_t, shift_n) = DecodeImmShift(type, imm3:imm2); 9214 shift_n = DecodeImmShiftThumb (opcode, shift_t); 9215 9216 // if d == 13 && (shift_t != SRType_LSL || shift_n > 3) then UNPREDICTABLE; 9217 if ((d == 13) && ((shift_t != SRType_LSL) || (shift_n > 3))) 9218 return false; 9219 9220 // if d == 15 || BadReg(m) then UNPREDICTABLE; 9221 if ((d == 15) || BadReg (m)) 9222 return false; 9223 break; 9224 9225 case eEncodingA1: 9226 // if Rd == ‘1111’ && S == ‘1’ then SEE SUBS PC, LR and related instructions; 9227 // d = UInt(Rd); m = UInt(Rm); setflags = (S == ‘1’); 9228 d = Bits32 (opcode, 15, 12); 9229 m = Bits32 (opcode, 3, 0); 9230 setflags = BitIsSet (opcode, 20); 9231 9232 // (shift_t, shift_n) = DecodeImmShift(type, imm5); 9233 shift_n = DecodeImmShiftARM (opcode, shift_t); 9234 break; 9235 9236 default: 9237 return false; 9238 } 9239 9240 // shifted = Shift(R[m], shift_t, shift_n, APSR.C); 9241 uint32_t Rm = ReadCoreReg (m, &success); 9242 if (!success) 9243 return false; 9244 9245 uint32_t shifted = Shift (Rm, shift_t, shift_n, APSR_C); 9246 9247 // (result, carry, overflow) = AddWithCarry(SP, NOT(shifted), ‘1’); 9248 uint32_t sp_val = ReadCoreReg (SP_REG, &success); 9249 if (!success) 9250 return false; 9251 9252 AddWithCarryResult res = AddWithCarry (sp_val, ~shifted, 1); 9253 9254 EmulateInstruction::Context context; 9255 context.type = eContextSubtraction; 9256 Register sp_reg; 9257 sp_reg.SetRegister (eRegisterKindDWARF, dwarf_sp); 9258 Register dwarf_reg; 9259 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + m); 9260 context.SetRegisterRegisterOperands (sp_reg, dwarf_reg); 9261 9262 uint32_t regnum = dwarf_r0 + d; 9263 9264 if (!WriteCoreRegOptionalFlags(context, res.result, regnum, setflags, res.carry_out, res.overflow)) 9265 return false; 9266 } 9267 return true; 9268} 9269 9270 9271// A8.6.7 ADD (register-shifted register) 9272bool 9273EmulateInstructionARM::EmulateAddRegShift (const uint32_t opcode, const ARMEncoding encoding) 9274{ 9275#if 0 9276#endif 9277 9278 //bool success = false; 9279 9280 if (ConditionPassed(opcode)) 9281 { 9282 switch (encoding) 9283 { 9284 } 9285 } 9286 return true; 9287} 9288 9289// A8.6.213 SUB (register) 9290bool 9291EmulateInstructionARM::EmulateSUBReg (const uint32_t opcode, const ARMEncoding encoding) 9292{ 9293#if 0 9294#endif 9295 9296 //bool success = false; 9297 9298 if (ConditionPassed(opcode)) 9299 { 9300 switch (encoding) 9301 { 9302 } 9303 } 9304 return true; 9305} 9306 9307// A8.6.202 STREX 9308bool 9309EmulateInstructionARM::EmulateSTREX (const uint32_t opcode, const ARMEncoding encoding) 9310{ 9311#if 0 9312#endif 9313 9314 //bool success = false; 9315 9316 if (ConditionPassed(opcode)) 9317 { 9318 switch (encoding) 9319 { 9320 } 9321 } 9322 return true; 9323} 9324 9325// A8.6.197 STRB (immediate, ARM) 9326bool 9327EmulateInstructionARM::EmulateSTRBImmARM (const uint32_t opcode, const ARMEncoding encoding) 9328{ 9329#if 0 9330#endif 9331 9332 //bool success = false; 9333 9334 if (ConditionPassed(opcode)) 9335 { 9336 switch (encoding) 9337 { 9338 } 9339 } 9340 return true; 9341} 9342 9343// A8.6.194 STR (immediate, ARM) 9344bool 9345EmulateInstructionARM::EmulateSTRImmARM (const uint32_t opcode, const ARMEncoding encoding) 9346{ 9347#if 0 9348#endif 9349 9350 //bool success = false; 9351 9352 if (ConditionPassed(opcode)) 9353 { 9354 switch (encoding) 9355 { 9356 } 9357 } 9358 return true; 9359} 9360 9361// A8.6.74 LDRH (immediate, ARM) 9362bool 9363EmulateInstructionARM::EmulateLDRHImmediateARM (const uint32_t opcode, const ARMEncoding encoding) 9364{ 9365#if 0 9366#endif 9367 9368 //bool success = false; 9369 9370 if (ConditionPassed(opcode)) 9371 { 9372 switch (encoding) 9373 { 9374 } 9375 } 9376 return true; 9377} 9378 9379// A8.6.69 LDREX 9380bool 9381EmulateInstructionARM::EmulateLDREX (const uint32_t opcode, const ARMEncoding encoding) 9382{ 9383#if 0 9384#endif 9385 9386 //bool success = false; 9387 9388 if (ConditionPassed(opcode)) 9389 { 9390 switch (encoding) 9391 { 9392 } 9393 } 9394 return true; 9395} 9396 9397// A8.6.62 LDRB (immediate, ARM) 9398bool 9399EmulateInstructionARM::EmulateLDRBImmediateARM (const uint32_t opcode, const ARMEncoding encoding) 9400{ 9401#if 0 9402#endif 9403 9404 //bool success = false; 9405 9406 if (ConditionPassed(opcode)) 9407 { 9408 switch (encoding) 9409 { 9410 } 9411 } 9412 return true; 9413} 9414 9415// A8.6.59 LDR (literal) 9416bool 9417EmulateInstructionARM::EmulateLDRLiteral (const uint32_t opcode, const ARMEncoding encoding) 9418{ 9419#if 0 9420#endif 9421 9422 //bool success = false; 9423 9424 if (ConditionPassed(opcode)) 9425 { 9426 switch (encoding) 9427 { 9428 } 9429 } 9430 return true; 9431} 9432 9433 9434 9435// A8.6.65 LDRBT 9436bool 9437EmulateInstructionARM::EmulateLDRBT (const uint32_t opcode, const ARMEncoding encoding) 9438{ 9439#if 0 9440#endif 9441 9442 //bool success = false; 9443 9444 if (ConditionPassed(opcode)) 9445 { 9446 switch (encoding) 9447 { 9448 } 9449 } 9450 return true; 9451} 9452 9453 9454// A8.6.66 LDRD (immediate) 9455bool 9456EmulateInstructionARM::EmulateLDRDImmediate (const uint32_t opcode, const ARMEncoding encoding) 9457{ 9458#if 0 9459#endif 9460 9461 //bool success = false; 9462 9463 if (ConditionPassed(opcode)) 9464 { 9465 switch (encoding) 9466 { 9467 } 9468 } 9469 return true; 9470} 9471 9472 9473// A8.6.67 LDRD (literal) 9474bool 9475EmulateInstructionARM::EmulateLDRDLiteral (const uint32_t opcode, const ARMEncoding encoding) 9476{ 9477#if 0 9478#endif 9479 9480 //bool success = false; 9481 9482 if (ConditionPassed(opcode)) 9483 { 9484 switch (encoding) 9485 { 9486 } 9487 } 9488 return true; 9489} 9490 9491 9492// A8.6.68 LDRD (register) 9493bool 9494EmulateInstructionARM::EmulateLDRDRegister (const uint32_t opcode, const ARMEncoding encoding) 9495{ 9496#if 0 9497#endif 9498 9499 //bool success = false; 9500 9501 if (ConditionPassed(opcode)) 9502 { 9503 switch (encoding) 9504 { 9505 } 9506 } 9507 return true; 9508} 9509 9510 9511// A8.6.70 LDREXB 9512bool 9513EmulateInstructionARM::EmulateLDREXB (const uint32_t opcode, const ARMEncoding encoding) 9514{ 9515#if 0 9516#endif 9517 9518 //bool success = false; 9519 9520 if (ConditionPassed(opcode)) 9521 { 9522 switch (encoding) 9523 { 9524 } 9525 } 9526 return true; 9527} 9528 9529 9530// A8.6.71 LDREXD 9531bool 9532EmulateInstructionARM::EmulateLDREXD (const uint32_t opcode, const ARMEncoding encoding) 9533{ 9534#if 0 9535#endif 9536 9537 //bool success = false; 9538 9539 if (ConditionPassed(opcode)) 9540 { 9541 switch (encoding) 9542 { 9543 } 9544 } 9545 return true; 9546} 9547 9548 9549// A8.6.72 LDREXH 9550bool 9551EmulateInstructionARM::EmulateLDREXH (const uint32_t opcode, const ARMEncoding encoding) 9552{ 9553#if 0 9554#endif 9555 9556 //bool success = false; 9557 9558 if (ConditionPassed(opcode)) 9559 { 9560 switch (encoding) 9561 { 9562 } 9563 } 9564 return true; 9565} 9566 9567 9568 9569// A8.6.77 LDRHT 9570bool 9571EmulateInstructionARM::EmulateLDRHT (const uint32_t opcode, const ARMEncoding encoding) 9572{ 9573#if 0 9574#endif 9575 9576 //bool success = false; 9577 9578 if (ConditionPassed(opcode)) 9579 { 9580 switch (encoding) 9581 { 9582 } 9583 } 9584 return true; 9585} 9586 9587 9588// A8.6.81 LDRSBT 9589bool 9590EmulateInstructionARM::EmulateLDRSBT (const uint32_t opcode, const ARMEncoding encoding) 9591{ 9592#if 0 9593#endif 9594 9595 //bool success = false; 9596 9597 if (ConditionPassed(opcode)) 9598 { 9599 switch (encoding) 9600 { 9601 } 9602 } 9603 return true; 9604} 9605 9606 9607// A8.6.85 LDRSHT 9608bool 9609EmulateInstructionARM::EmulateLDRSHT (const uint32_t opcode, const ARMEncoding encoding) 9610{ 9611#if 0 9612#endif 9613 9614 //bool success = false; 9615 9616 if (ConditionPassed(opcode)) 9617 { 9618 switch (encoding) 9619 { 9620 } 9621 } 9622 return true; 9623} 9624 9625 9626// A8.6.86 LDRT 9627bool 9628EmulateInstructionARM::EmulateLDRT (const uint32_t opcode, const ARMEncoding encoding) 9629{ 9630#if 0 9631#endif 9632 9633 //bool success = false; 9634 9635 if (ConditionPassed(opcode)) 9636 { 9637 switch (encoding) 9638 { 9639 } 9640 } 9641 return true; 9642} 9643 9644 9645 9646// A8.6.198 STRB (register) 9647bool 9648EmulateInstructionARM::EmulateSTRBReg (const uint32_t opcode, const ARMEncoding encoding) 9649{ 9650#if 0 9651#endif 9652 9653 //bool success = false; 9654 9655 if (ConditionPassed(opcode)) 9656 { 9657 switch (encoding) 9658 { 9659 } 9660 } 9661 return true; 9662} 9663 9664 9665// A8.6.199 STRBT 9666bool 9667EmulateInstructionARM::EmulateSTRBT (const uint32_t opcode, const ARMEncoding encoding) 9668{ 9669#if 0 9670#endif 9671 9672 //bool success = false; 9673 9674 if (ConditionPassed(opcode)) 9675 { 9676 switch (encoding) 9677 { 9678 } 9679 } 9680 return true; 9681} 9682 9683 9684// A8.6.200 STRD (immediate) 9685bool 9686EmulateInstructionARM::EmulateSTRDImm (const uint32_t opcode, const ARMEncoding encoding) 9687{ 9688#if 0 9689#endif 9690 9691 //bool success = false; 9692 9693 if (ConditionPassed(opcode)) 9694 { 9695 switch (encoding) 9696 { 9697 } 9698 } 9699 return true; 9700} 9701 9702 9703// A8.6.201 STRD (register) 9704bool 9705EmulateInstructionARM::EmulateSTRDReg (const uint32_t opcode, const ARMEncoding encoding) 9706{ 9707#if 0 9708#endif 9709 9710 //bool success = false; 9711 9712 if (ConditionPassed(opcode)) 9713 { 9714 switch (encoding) 9715 { 9716 } 9717 } 9718 return true; 9719} 9720 9721 9722// A8.6.203 STREXB 9723bool 9724EmulateInstructionARM::EmulateSTREXB (const uint32_t opcode, const ARMEncoding encoding) 9725{ 9726#if 0 9727#endif 9728 9729 //bool success = false; 9730 9731 if (ConditionPassed(opcode)) 9732 { 9733 switch (encoding) 9734 { 9735 } 9736 } 9737 return true; 9738} 9739 9740 9741// A8.6.204 STREXD 9742bool 9743EmulateInstructionARM::EmulateSTREXD (const uint32_t opcode, const ARMEncoding encoding) 9744{ 9745#if 0 9746#endif 9747 9748 //bool success = false; 9749 9750 if (ConditionPassed(opcode)) 9751 { 9752 switch (encoding) 9753 { 9754 } 9755 } 9756 return true; 9757} 9758 9759 9760// A8.6.205 STREXH 9761bool 9762EmulateInstructionARM::EmulateSTREXH (const uint32_t opcode, const ARMEncoding encoding) 9763{ 9764#if 0 9765#endif 9766 9767 //bool success = false; 9768 9769 if (ConditionPassed(opcode)) 9770 { 9771 switch (encoding) 9772 { 9773 } 9774 } 9775 return true; 9776} 9777 9778 9779// A8.6.206 STRH (immediate, Thumb) 9780bool 9781EmulateInstructionARM::EmulateSTRHImmThumb (const uint32_t opcode, const ARMEncoding encoding) 9782{ 9783#if 0 9784#endif 9785 9786 //bool success = false; 9787 9788 if (ConditionPassed(opcode)) 9789 { 9790 switch (encoding) 9791 { 9792 } 9793 } 9794 return true; 9795} 9796 9797 9798// A8.6.207 STRH (immediate, ARM) 9799bool 9800EmulateInstructionARM::EmulateSTRHImmARM (const uint32_t opcode, const ARMEncoding encoding) 9801{ 9802#if 0 9803#endif 9804 9805 //bool success = false; 9806 9807 if (ConditionPassed(opcode)) 9808 { 9809 switch (encoding) 9810 { 9811 } 9812 } 9813 return true; 9814} 9815 9816 9817 9818// A8.6.209 STRHT 9819bool 9820EmulateInstructionARM::EmulateSTRHT (const uint32_t opcode, const ARMEncoding encoding) 9821{ 9822#if 0 9823#endif 9824 9825 //bool success = false; 9826 9827 if (ConditionPassed(opcode)) 9828 { 9829 switch (encoding) 9830 { 9831 } 9832 } 9833 return true; 9834} 9835 9836 9837// A8.6.210 STRT 9838bool 9839EmulateInstructionARM::EmulateSTRT (const uint32_t opcode, const ARMEncoding encoding) 9840{ 9841#if 0 9842#endif 9843 9844 // bool success = false; 9845 9846 if (ConditionPassed(opcode)) 9847 { 9848 switch (encoding) 9849 { 9850 } 9851 } 9852 return true; 9853} 9854 9855 9856 9857 9858EmulateInstructionARM::ARMOpcode* 9859EmulateInstructionARM::GetARMOpcodeForInstruction (const uint32_t opcode) 9860{ 9861 static ARMOpcode 9862 g_arm_opcodes[] = 9863 { 9864 //---------------------------------------------------------------------- 9865 // Prologue instructions 9866 //---------------------------------------------------------------------- 9867 9868 // push register(s) 9869 { 0x0fff0000, 0x092d0000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulatePUSH, "push <registers>" }, 9870 { 0x0fff0fff, 0x052d0004, ARMvAll, eEncodingA2, eSize32, &EmulateInstructionARM::EmulatePUSH, "push <register>" }, 9871 9872 // set r7 to point to a stack offset 9873 { 0x0ffff000, 0x028d7000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateADDRdSPImm, "add r7, sp, #<const>" }, 9874 { 0x0ffff000, 0x024c7000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSUBR7IPImm, "sub r7, ip, #<const>"}, 9875 // copy the stack pointer to ip 9876 { 0x0fffffff, 0x01a0c00d, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateMOVRdSP, "mov ip, sp" }, 9877 { 0x0ffff000, 0x028dc000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateADDRdSPImm, "add ip, sp, #<const>" }, 9878 { 0x0ffff000, 0x024dc000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSUBIPSPImm, "sub ip, sp, #<const>"}, 9879 9880 // adjust the stack pointer 9881 { 0x0ffff000, 0x024dd000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSUBSPImm, "sub sp, sp, #<const>"}, 9882 { 0x0fef0010, 0x004d0000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSUBSPReg, "sub{s}<c> <Rd>, sp, <Rm>{,<shift>}" }, 9883 9884 // push one register 9885 // if Rn == '1101' && imm12 == '000000000100' then SEE PUSH; 9886 { 0x0e5f0000, 0x040d0000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSTRRtSP, "str Rt, [sp, #-imm12]!" }, 9887 9888 // vector push consecutive extension register(s) 9889 { 0x0fbf0f00, 0x0d2d0b00, ARMV6T2_ABOVE, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateVPUSH, "vpush.64 <list>"}, 9890 { 0x0fbf0f00, 0x0d2d0a00, ARMV6T2_ABOVE, eEncodingA2, eSize32, &EmulateInstructionARM::EmulateVPUSH, "vpush.32 <list>"}, 9891 9892 //---------------------------------------------------------------------- 9893 // Epilogue instructions 9894 //---------------------------------------------------------------------- 9895 9896 { 0x0fff0000, 0x08bd0000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulatePOP, "pop <registers>"}, 9897 { 0x0fff0fff, 0x049d0004, ARMvAll, eEncodingA2, eSize32, &EmulateInstructionARM::EmulatePOP, "pop <register>"}, 9898 { 0x0fbf0f00, 0x0cbd0b00, ARMV6T2_ABOVE, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateVPOP, "vpop.64 <list>"}, 9899 { 0x0fbf0f00, 0x0cbd0a00, ARMV6T2_ABOVE, eEncodingA2, eSize32, &EmulateInstructionARM::EmulateVPOP, "vpop.32 <list>"}, 9900 9901 //---------------------------------------------------------------------- 9902 // Supervisor Call (previously Software Interrupt) 9903 //---------------------------------------------------------------------- 9904 { 0x0f000000, 0x0f000000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSVC, "svc #imm24"}, 9905 9906 //---------------------------------------------------------------------- 9907 // Branch instructions 9908 //---------------------------------------------------------------------- 9909 { 0x0f000000, 0x0a000000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateB, "b #imm24"}, 9910 // To resolve ambiguity, "blx <label>" should come before "bl <label>". 9911 { 0xfe000000, 0xfa000000, ARMV5_ABOVE, eEncodingA2, eSize32, &EmulateInstructionARM::EmulateBLXImmediate, "blx <label>"}, 9912 { 0x0f000000, 0x0b000000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateBLXImmediate, "bl <label>"}, 9913 { 0x0ffffff0, 0x012fff30, ARMV5_ABOVE, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateBLXRm, "blx <Rm>"}, 9914 // for example, "bx lr" 9915 { 0x0ffffff0, 0x012fff10, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateBXRm, "bx <Rm>"}, 9916 // bxj 9917 { 0x0ffffff0, 0x012fff20, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateBXJRm, "bxj <Rm>"}, 9918 9919 //---------------------------------------------------------------------- 9920 // Data-processing instructions 9921 //---------------------------------------------------------------------- 9922 // adc (immediate) 9923 { 0x0fe00000, 0x02a00000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateADCImm, "adc{s}<c> <Rd>, <Rn>, #const"}, 9924 // adc (register) 9925 { 0x0fe00010, 0x00a00000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateADCReg, "adc{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"}, 9926 // add (immediate) 9927 { 0x0fe00000, 0x02800000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateADDImmARM, "add{s}<c> <Rd>, <Rn>, #const"}, 9928 // add (register) 9929 { 0x0fe00010, 0x00800000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateADDReg, "add{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"}, 9930 // adr 9931 { 0x0fff0000, 0x028f0000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateADR, "add<c> <Rd>, PC, #<const>"}, 9932 { 0x0fff0000, 0x024f0000, ARMvAll, eEncodingA2, eSize32, &EmulateInstructionARM::EmulateADR, "sub<c> <Rd>, PC, #<const>"}, 9933 // and (immediate) 9934 { 0x0fe00000, 0x02000000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateANDImm, "and{s}<c> <Rd>, <Rn>, #const"}, 9935 // and (register) 9936 { 0x0fe00010, 0x00000000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateANDReg, "and{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"}, 9937 // bic (immediate) 9938 { 0x0fe00000, 0x03c00000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateBICImm, "bic{s}<c> <Rd>, <Rn>, #const"}, 9939 // bic (register) 9940 { 0x0fe00010, 0x01c00000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateBICReg, "bic{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"}, 9941 // eor (immediate) 9942 { 0x0fe00000, 0x02200000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateEORImm, "eor{s}<c> <Rd>, <Rn>, #const"}, 9943 // eor (register) 9944 { 0x0fe00010, 0x00200000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateEORReg, "eor{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"}, 9945 // orr (immediate) 9946 { 0x0fe00000, 0x03800000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateORRImm, "orr{s}<c> <Rd>, <Rn>, #const"}, 9947 // orr (register) 9948 { 0x0fe00010, 0x01800000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateORRReg, "orr{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"}, 9949 // rsb (immediate) 9950 { 0x0fe00000, 0x02600000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateRSBImm, "rsb{s}<c> <Rd>, <Rn>, #<const>"}, 9951 // rsb (register) 9952 { 0x0fe00010, 0x00600000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateRSBReg, "rsb{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"}, 9953 // rsc (immediate) 9954 { 0x0fe00000, 0x02e00000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateRSCImm, "rsc{s}<c> <Rd>, <Rn>, #<const>"}, 9955 // rsc (register) 9956 { 0x0fe00010, 0x00e00000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateRSCReg, "rsc{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"}, 9957 // sbc (immediate) 9958 { 0x0fe00000, 0x02c00000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSBCImm, "sbc{s}<c> <Rd>, <Rn>, #<const>"}, 9959 // sbc (register) 9960 { 0x0fe00010, 0x00c00000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSBCReg, "sbc{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"}, 9961 // sub (immediate, ARM) 9962 { 0x0fe00000, 0x02400000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSUBImmARM, "sub{s}<c> <Rd>, <Rn>, #<const>"}, 9963 // sub (sp minus immediate) 9964 { 0x0fef0000, 0x024d0000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSUBSPImm, "sub{s}<c> <Rd>, sp, #<const>"}, 9965 // teq (immediate) 9966 { 0x0ff0f000, 0x03300000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateTEQImm, "teq<c> <Rn>, #const"}, 9967 // teq (register) 9968 { 0x0ff0f010, 0x01300000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateTEQReg, "teq<c> <Rn>, <Rm> {,<shift>}"}, 9969 // tst (immediate) 9970 { 0x0ff0f000, 0x03100000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateTSTImm, "tst<c> <Rn>, #const"}, 9971 // tst (register) 9972 { 0x0ff0f010, 0x01100000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateTSTReg, "tst<c> <Rn>, <Rm> {,<shift>}"}, 9973 9974 // mov (immediate) 9975 { 0x0fef0000, 0x03a00000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateMOVRdImm, "mov{s}<c> <Rd>, #<const>"}, 9976 { 0x0ff00000, 0x03000000, ARMV6T2_ABOVE, eEncodingA2, eSize32, &EmulateInstructionARM::EmulateMOVRdImm, "movw<c> <Rd>, #<imm16>" }, 9977 // mov (register) 9978 { 0x0fef0ff0, 0x01a00000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateMOVRdRm, "mov{s}<c> <Rd>, <Rm>"}, 9979 // mvn (immediate) 9980 { 0x0fef0000, 0x03e00000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateMVNImm, "mvn{s}<c> <Rd>, #<const>"}, 9981 // mvn (register) 9982 { 0x0fef0010, 0x01e00000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateMVNReg, "mvn{s}<c> <Rd>, <Rm> {,<shift>}"}, 9983 // cmn (immediate) 9984 { 0x0ff0f000, 0x03700000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateCMNImm, "cmn<c> <Rn>, #<const>"}, 9985 // cmn (register) 9986 { 0x0ff0f010, 0x01700000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateCMNReg, "cmn<c> <Rn>, <Rm> {,<shift>}"}, 9987 // cmp (immediate) 9988 { 0x0ff0f000, 0x03500000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateCMPImm, "cmp<c> <Rn>, #<const>"}, 9989 // cmp (register) 9990 { 0x0ff0f010, 0x01500000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateCMPReg, "cmp<c> <Rn>, <Rm> {,<shift>}"}, 9991 // asr (immediate) 9992 { 0x0fef0070, 0x01a00040, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateASRImm, "asr{s}<c> <Rd>, <Rm>, #imm"}, 9993 // asr (register) 9994 { 0x0fef00f0, 0x01a00050, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateASRReg, "asr{s}<c> <Rd>, <Rn>, <Rm>"}, 9995 // lsl (immediate) 9996 { 0x0fef0070, 0x01a00000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLSLImm, "lsl{s}<c> <Rd>, <Rm>, #imm"}, 9997 // lsl (register) 9998 { 0x0fef00f0, 0x01a00010, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLSLReg, "lsl{s}<c> <Rd>, <Rn>, <Rm>"}, 9999 // lsr (immediate) 10000 { 0x0fef0070, 0x01a00020, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLSRImm, "lsr{s}<c> <Rd>, <Rm>, #imm"}, 10001 // lsr (register) 10002 { 0x0fef00f0, 0x01a00050, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLSRReg, "lsr{s}<c> <Rd>, <Rn>, <Rm>"}, 10003 // rrx is a special case encoding of ror (immediate) 10004 { 0x0fef0ff0, 0x01a00060, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateRRX, "rrx{s}<c> <Rd>, <Rm>"}, 10005 // ror (immediate) 10006 { 0x0fef0070, 0x01a00060, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateRORImm, "ror{s}<c> <Rd>, <Rm>, #imm"}, 10007 // ror (register) 10008 { 0x0fef00f0, 0x01a00070, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateRORReg, "ror{s}<c> <Rd>, <Rn>, <Rm>"}, 10009 // mul 10010 { 0x0fe000f0, 0x00000090, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateMUL, "mul{s}<c> <Rd>,<R>,<Rm>" }, 10011 10012 //---------------------------------------------------------------------- 10013 // Load instructions 10014 //---------------------------------------------------------------------- 10015 { 0x0fd00000, 0x08900000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDM, "ldm<c> <Rn>{!} <registers>" }, 10016 { 0x0fd00000, 0x08100000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDMDA, "ldmda<c> <Rn>{!} <registers>" }, 10017 { 0x0fd00000, 0x09100000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDMDB, "ldmdb<c> <Rn>{!} <registers>" }, 10018 { 0x0fd00000, 0x09900000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDMIB, "ldmib<c> <Rn<{!} <registers>" }, 10019 { 0x0e500000, 0x04100000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDRImmediateARM, "ldr<c> <Rt> [<Rn> {#+/-<imm12>}]" }, 10020 { 0x0e500010, 0x06100000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDRRegister, "ldr<c> <Rt> [<Rn> +/-<Rm> {<shift>}] {!}" }, 10021 { 0x0e5f0000, 0x045f0000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDRBLiteral, "ldrb<c> <Rt>, [...]"}, 10022 { 0xfe500010, 0x06500000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDRBRegister, "ldrb<c> <Rt>, [<Rn>,+/-<Rm>{, <shift>}]{!}" }, 10023 { 0x0e5f00f0, 0x005f00b0, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDRHLiteral, "ldrh<c> <Rt>, <label>" }, 10024 { 0x0e5000f0, 0x001000b0, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDRHRegister, "ldrh<c> <Rt>,[<Rn>,+/-<Rm>]{!}" }, 10025 { 0x0e5000f0, 0x005000d0, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDRSBImmediate, "ldrsb<c> <Rt>, [<Rn>{,#+/-<imm8>}]" }, 10026 { 0x0e5f00f0, 0x005f00d0, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDRSBLiteral, "ldrsb<c> <Rt> <label>" }, 10027 { 0x0e5000f0, 0x001000d0, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDRSBRegister, "ldrsb<c> <Rt>,[<Rn>,+/-<Rm>]{!}" }, 10028 { 0x0e5000f0, 0x005000f0, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDRSHImmediate, "ldrsh<c> <Rt>,[<Rn>{,#+/-<imm8>}]"}, 10029 { 0x0e5f00f0, 0x005f00f0, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDRSHLiteral, "ldrsh<c> <Rt>,<label>" }, 10030 { 0x0e5000f0, 0x001000f0, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDRSHRegister, "ldrsh<c> <Rt>,[<Rn>,+/-<Rm>]{!}" }, 10031 10032 //---------------------------------------------------------------------- 10033 // Store instructions 10034 //---------------------------------------------------------------------- 10035 { 0x0fd00000, 0x08800000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSTM, "stm<c> <Rn>{!} <registers>" }, 10036 { 0x0fd00000, 0x08000000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSTMDA, "stmda<c> <Rn>{!} <registers>" }, 10037 { 0x0fd00000, 0x09000000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSTMDB, "stmdb<c> <Rn>{!} <registers>" }, 10038 { 0x0fd00000, 0x09800000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSTMIB, "stmib<c> <Rn>{!} <registers>" }, 10039 { 0x0e500010, 0x06000000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSTRRegister, "str<c> <Rt> [<Rn> +/-<Rm> {<shift>}]{!}" }, 10040 { 0x0e5000f0, 0x000000b0, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSTRHRegister, "strh<c> <Rt>,[<Rn>,+/-<Rm>[{!}" }, 10041 10042 //---------------------------------------------------------------------- 10043 // Other instructions 10044 //---------------------------------------------------------------------- 10045 { 0x0fff00f0, 0x06af00f0, ARMV6_ABOVE, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSXTB, "sxtb<c> <Rd>,<Rm>{,<rotation>}" }, 10046 { 0x0fff00f0, 0x06bf0070, ARMV6_ABOVE, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSXTH, "sxth<c> <Rd>,<Rm>{,<rotation>}" }, 10047 { 0x0fff00f0, 0x06ef0070, ARMV6_ABOVE, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateUXTB, "uxtb<c> <Rd>,<Rm>{,<rotation>}" }, 10048 { 0x0fff00f0, 0x06ff0070, ARMV6_ABOVE, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateUXTH, "uxth<c> <Rd>,<Rm>{,<rotation>}" }, 10049 { 0xfe500000, 0xf8100000, ARMV6_ABOVE, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateRFE, "rfe{<amode>} <Rn>{!}" } 10050 10051 }; 10052 static const size_t k_num_arm_opcodes = sizeof(g_arm_opcodes)/sizeof(ARMOpcode); 10053 10054 for (size_t i=0; i<k_num_arm_opcodes; ++i) 10055 { 10056 if ((g_arm_opcodes[i].mask & opcode) == g_arm_opcodes[i].value) 10057 return &g_arm_opcodes[i]; 10058 } 10059 return NULL; 10060} 10061 10062 10063EmulateInstructionARM::ARMOpcode* 10064EmulateInstructionARM::GetThumbOpcodeForInstruction (const uint32_t opcode) 10065{ 10066 10067 static ARMOpcode 10068 g_thumb_opcodes[] = 10069 { 10070 //---------------------------------------------------------------------- 10071 // Prologue instructions 10072 //---------------------------------------------------------------------- 10073 10074 // push register(s) 10075 { 0xfffffe00, 0x0000b400, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulatePUSH, "push <registers>" }, 10076 { 0xffff0000, 0xe92d0000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulatePUSH, "push.w <registers>" }, 10077 { 0xffff0fff, 0xf84d0d04, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulatePUSH, "push.w <register>" }, 10078 10079 // set r7 to point to a stack offset 10080 { 0xffffff00, 0x0000af00, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateADDRdSPImm, "add r7, sp, #imm" }, 10081 // copy the stack pointer to r7 10082 { 0xffffffff, 0x0000466f, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateMOVRdSP, "mov r7, sp" }, 10083 // move from high register to low register (comes after "mov r7, sp" to resolve ambiguity) 10084 { 0xffffffc0, 0x00004640, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateMOVLowHigh, "mov r0-r7, r8-r15" }, 10085 10086 // PC-relative load into register (see also EmulateADDSPRm) 10087 { 0xfffff800, 0x00004800, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLDRRtPCRelative, "ldr <Rt>, [PC, #imm]"}, 10088 10089 // adjust the stack pointer 10090 { 0xffffff87, 0x00004485, ARMvAll, eEncodingT2, eSize16, &EmulateInstructionARM::EmulateADDSPRm, "add sp, <Rm>"}, 10091 { 0xffffff80, 0x0000b080, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateSUBSPImm, "sub sp, sp, #imm"}, 10092 { 0xfbef8f00, 0xf1ad0d00, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateSUBSPImm, "sub.w sp, sp, #<const>"}, 10093 { 0xfbff8f00, 0xf2ad0d00, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulateSUBSPImm, "subw sp, sp, #imm12"}, 10094 { 0xffef8000, 0xebad0000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateSUBSPReg, "sub{s}<c> <Rd>, sp, <Rm>{,<shift>}" }, 10095 10096 // vector push consecutive extension register(s) 10097 { 0xffbf0f00, 0xed2d0b00, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateVPUSH, "vpush.64 <list>"}, 10098 { 0xffbf0f00, 0xed2d0a00, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateVPUSH, "vpush.32 <list>"}, 10099 10100 //---------------------------------------------------------------------- 10101 // Epilogue instructions 10102 //---------------------------------------------------------------------- 10103 10104 { 0xfffff800, 0x0000a800, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateADDSPImm, "add<c> <Rd>, sp, #imm"}, 10105 { 0xffffff80, 0x0000b000, ARMvAll, eEncodingT2, eSize16, &EmulateInstructionARM::EmulateADDSPImm, "add sp, #imm"}, 10106 { 0xfffffe00, 0x0000bc00, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulatePOP, "pop <registers>"}, 10107 { 0xffff0000, 0xe8bd0000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulatePOP, "pop.w <registers>" }, 10108 { 0xffff0fff, 0xf85d0d04, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulatePOP, "pop.w <register>" }, 10109 { 0xffbf0f00, 0xecbd0b00, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateVPOP, "vpop.64 <list>"}, 10110 { 0xffbf0f00, 0xecbd0a00, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateVPOP, "vpop.32 <list>"}, 10111 10112 //---------------------------------------------------------------------- 10113 // Supervisor Call (previously Software Interrupt) 10114 //---------------------------------------------------------------------- 10115 { 0xffffff00, 0x0000df00, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateSVC, "svc #imm8"}, 10116 10117 //---------------------------------------------------------------------- 10118 // If Then makes up to four following instructions conditional. 10119 //---------------------------------------------------------------------- 10120 { 0xffffff00, 0x0000bf00, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateIT, "it{<x>{<y>{<z>}}} <firstcond>"}, 10121 10122 //---------------------------------------------------------------------- 10123 // Branch instructions 10124 //---------------------------------------------------------------------- 10125 // To resolve ambiguity, "b<c> #imm8" should come after "svc #imm8". 10126 { 0xfffff000, 0x0000d000, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateB, "b<c> #imm8 (outside IT)"}, 10127 { 0xfffff800, 0x0000e000, ARMvAll, eEncodingT2, eSize16, &EmulateInstructionARM::EmulateB, "b<c> #imm11 (outside or last in IT)"}, 10128 { 0xf800d000, 0xf0008000, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulateB, "b<c>.w #imm8 (outside IT)"}, 10129 { 0xf800d000, 0xf0009000, ARMV6T2_ABOVE, eEncodingT4, eSize32, &EmulateInstructionARM::EmulateB, "b<c>.w #imm8 (outside or last in IT)"}, 10130 // J1 == J2 == 1 10131 { 0xf800d000, 0xf000d000, ARMV4T_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateBLXImmediate, "bl <label>"}, 10132 // J1 == J2 == 1 10133 { 0xf800d001, 0xf000c000, ARMV5_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateBLXImmediate, "blx <label>"}, 10134 { 0xffffff87, 0x00004780, ARMV5_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateBLXRm, "blx <Rm>"}, 10135 // for example, "bx lr" 10136 { 0xffffff87, 0x00004700, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateBXRm, "bx <Rm>"}, 10137 // bxj 10138 { 0xfff0ffff, 0xf3c08f00, ARMV5J_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateBXJRm, "bxj <Rm>"}, 10139 // compare and branch 10140 { 0xfffff500, 0x0000b100, ARMV6T2_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateCB, "cb{n}z <Rn>, <label>"}, 10141 // table branch byte 10142 { 0xfff0fff0, 0xe8d0f000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateTB, "tbb<c> <Rn>, <Rm>"}, 10143 // table branch halfword 10144 { 0xfff0fff0, 0xe8d0f010, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateTB, "tbh<c> <Rn>, <Rm>, lsl #1"}, 10145 10146 //---------------------------------------------------------------------- 10147 // Data-processing instructions 10148 //---------------------------------------------------------------------- 10149 // adc (immediate) 10150 { 0xfbe08000, 0xf1400000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateADCImm, "adc{s}<c> <Rd>, <Rn>, #<const>"}, 10151 // adc (register) 10152 { 0xffffffc0, 0x00004140, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateADCReg, "adcs|adc<c> <Rdn>, <Rm>"}, 10153 { 0xffe08000, 0xeb400000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateADCReg, "adc{s}<c>.w <Rd>, <Rn>, <Rm> {,<shift>}"}, 10154 // add (register) 10155 { 0xfffffe00, 0x00001800, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateADDReg, "adds|add<c> <Rd>, <Rn>, <Rm>"}, 10156 // Make sure "add sp, <Rm>" comes before this instruction, so there's no ambiguity decoding the two. 10157 { 0xffffff00, 0x00004400, ARMvAll, eEncodingT2, eSize16, &EmulateInstructionARM::EmulateADDReg, "add<c> <Rdn>, <Rm>"}, 10158 // adr 10159 { 0xfffff800, 0x0000a000, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateADR, "add<c> <Rd>, PC, #<const>"}, 10160 { 0xfbff8000, 0xf2af0000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateADR, "sub<c> <Rd>, PC, #<const>"}, 10161 { 0xfbff8000, 0xf20f0000, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulateADR, "add<c> <Rd>, PC, #<const>"}, 10162 // and (immediate) 10163 { 0xfbe08000, 0xf0000000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateANDImm, "and{s}<c> <Rd>, <Rn>, #<const>"}, 10164 // and (register) 10165 { 0xffffffc0, 0x00004000, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateANDReg, "ands|and<c> <Rdn>, <Rm>"}, 10166 { 0xffe08000, 0xea000000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateANDReg, "and{s}<c>.w <Rd>, <Rn>, <Rm> {,<shift>}"}, 10167 // bic (immediate) 10168 { 0xfbe08000, 0xf0200000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateBICImm, "bic{s}<c> <Rd>, <Rn>, #<const>"}, 10169 // bic (register) 10170 { 0xffffffc0, 0x00004380, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateBICReg, "bics|bic<c> <Rdn>, <Rm>"}, 10171 { 0xffe08000, 0xea200000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateBICReg, "bic{s}<c>.w <Rd>, <Rn>, <Rm> {,<shift>}"}, 10172 // eor (immediate) 10173 { 0xfbe08000, 0xf0800000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateEORImm, "eor{s}<c> <Rd>, <Rn>, #<const>"}, 10174 // eor (register) 10175 { 0xffffffc0, 0x00004040, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateEORReg, "eors|eor<c> <Rdn>, <Rm>"}, 10176 { 0xffe08000, 0xea800000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateEORReg, "eor{s}<c>.w <Rd>, <Rn>, <Rm> {,<shift>}"}, 10177 // orr (immediate) 10178 { 0xfbe08000, 0xf0400000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateORRImm, "orr{s}<c> <Rd>, <Rn>, #<const>"}, 10179 // orr (register) 10180 { 0xffffffc0, 0x00004300, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateORRReg, "orrs|orr<c> <Rdn>, <Rm>"}, 10181 { 0xffe08000, 0xea400000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateORRReg, "orr{s}<c>.w <Rd>, <Rn>, <Rm> {,<shift>}"}, 10182 // rsb (immediate) 10183 { 0xffffffc0, 0x00004240, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateRSBImm, "rsbs|rsb<c> <Rd>, <Rn>, #0"}, 10184 { 0xfbe08000, 0xf1c00000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateRSBImm, "rsb{s}<c>.w <Rd>, <Rn>, #<const>"}, 10185 // rsb (register) 10186 { 0xffe08000, 0xea400000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateRSBReg, "rsb{s}<c>.w <Rd>, <Rn>, <Rm> {,<shift>}"}, 10187 // sbc (immediate) 10188 { 0xfbe08000, 0xf1600000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateSBCImm, "sbc{s}<c> <Rd>, <Rn>, #<const>"}, 10189 // sbc (register) 10190 { 0xffffffc0, 0x00004180, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateSBCReg, "sbcs|sbc<c> <Rdn>, <Rm>"}, 10191 { 0xffe08000, 0xeb600000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateSBCReg, "sbc{s}<c>.w <Rd>, <Rn>, <Rm> {,<shift>}"}, 10192 // add (immediate, Thumb) 10193 { 0xfffffe00, 0x00001c00, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateADDImmThumb, "adds|add<c> <Rd>,<Rn>,#<imm3>" }, 10194 { 0xfffff800, 0x00003000, ARMV4T_ABOVE, eEncodingT2, eSize16, &EmulateInstructionARM::EmulateADDImmThumb, "adds|add<c> <Rdn>,#<imm8>" }, 10195 { 0xfbe08000, 0xf1000000, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulateADDImmThumb, "add{s}<c>.w <Rd>,<Rn>,#<const>" }, 10196 { 0xfbf08000, 0xf2000000, ARMV6T2_ABOVE, eEncodingT4, eSize32, &EmulateInstructionARM::EmulateADDImmThumb, "addw<c> <Rd>,<Rn>,#<imm12>" }, 10197 // sub (immediate, Thumb) 10198 { 0xfffffe00, 0x00001e00, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateSUBImmThumb, "subs|sub<c> <Rd>, <Rn> #imm3"}, 10199 { 0xfffff800, 0x00003800, ARMvAll, eEncodingT2, eSize16, &EmulateInstructionARM::EmulateSUBImmThumb, "subs|sub<c> <Rdn>, #imm8"}, 10200 { 0xfbe08000, 0xf1a00000, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulateSUBImmThumb, "sub{s}<c>.w <Rd>, <Rn>, #<const>"}, 10201 { 0xfbf08000, 0xf2a00000, ARMV6T2_ABOVE, eEncodingT4, eSize32, &EmulateInstructionARM::EmulateSUBImmThumb, "subw<c> <Rd>, <Rn>, #imm12"}, 10202 // sub (sp minus immediate) 10203 { 0xfbef8000, 0xf1ad0000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateSUBSPImm, "sub{s}.w <Rd>, sp, #<const>"}, 10204 { 0xfbff8000, 0xf2ad0000, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulateSUBSPImm, "subw<c> <Rd>, sp, #imm12"}, 10205 // teq (immediate) 10206 { 0xfbf08f00, 0xf0900f00, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateTEQImm, "teq<c> <Rn>, #<const>"}, 10207 // teq (register) 10208 { 0xfff08f00, 0xea900f00, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateTEQReg, "teq<c> <Rn>, <Rm> {,<shift>}"}, 10209 // tst (immediate) 10210 { 0xfbf08f00, 0xf0100f00, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateTSTImm, "tst<c> <Rn>, #<const>"}, 10211 // tst (register) 10212 { 0xffffffc0, 0x00004200, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateTSTReg, "tst<c> <Rdn>, <Rm>"}, 10213 { 0xfff08f00, 0xea100f00, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateTSTReg, "tst<c>.w <Rn>, <Rm> {,<shift>}"}, 10214 10215 10216 // move from high register to high register 10217 { 0xffffff00, 0x00004600, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateMOVRdRm, "mov<c> <Rd>, <Rm>"}, 10218 // move from low register to low register 10219 { 0xffffffc0, 0x00000000, ARMvAll, eEncodingT2, eSize16, &EmulateInstructionARM::EmulateMOVRdRm, "movs <Rd>, <Rm>"}, 10220 // mov{s}<c>.w <Rd>, <Rm> 10221 { 0xffeff0f0, 0xea4f0000, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulateMOVRdRm, "mov{s}<c>.w <Rd>, <Rm>"}, 10222 // move immediate 10223 { 0xfffff800, 0x00002000, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateMOVRdImm, "movs|mov<c> <Rd>, #imm8"}, 10224 { 0xfbef8000, 0xf04f0000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateMOVRdImm, "mov{s}<c>.w <Rd>, #<const>"}, 10225 { 0xfbf08000, 0xf2400000, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulateMOVRdImm, "movw<c> <Rd>,#<imm16>"}, 10226 // mvn (immediate) 10227 { 0xfbef8000, 0xf06f0000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateMVNImm, "mvn{s} <Rd>, #<const>"}, 10228 // mvn (register) 10229 { 0xffffffc0, 0x000043c0, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateMVNReg, "mvns|mvn<c> <Rd>, <Rm>"}, 10230 { 0xffef8000, 0xea6f0000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateMVNReg, "mvn{s}<c>.w <Rd>, <Rm> {,<shift>}"}, 10231 // cmn (immediate) 10232 { 0xfbf08f00, 0xf1100f00, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateCMNImm, "cmn<c> <Rn>, #<const>"}, 10233 // cmn (register) 10234 { 0xffffffc0, 0x000042c0, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateCMNReg, "cmn<c> <Rn>, <Rm>"}, 10235 { 0xfff08f00, 0xeb100f00, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateCMNReg, "cmn<c> <Rn>, <Rm> {,<shift>}"}, 10236 // cmp (immediate) 10237 { 0xfffff800, 0x00002800, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateCMPImm, "cmp<c> <Rn>, #imm8"}, 10238 { 0xfbf08f00, 0xf1b00f00, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateCMPImm, "cmp<c>.w <Rn>, #<const>"}, 10239 // cmp (register) (Rn and Rm both from r0-r7) 10240 { 0xffffffc0, 0x00004280, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateCMPReg, "cmp<c> <Rn>, <Rm>"}, 10241 // cmp (register) (Rn and Rm not both from r0-r7) 10242 { 0xffffff00, 0x00004500, ARMvAll, eEncodingT2, eSize16, &EmulateInstructionARM::EmulateCMPReg, "cmp<c> <Rn>, <Rm>"}, 10243 // asr (immediate) 10244 { 0xfffff800, 0x00001000, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateASRImm, "asrs|asr<c> <Rd>, <Rm>, #imm"}, 10245 { 0xffef8030, 0xea4f0020, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateASRImm, "asr{s}<c>.w <Rd>, <Rm>, #imm"}, 10246 // asr (register) 10247 { 0xffffffc0, 0x00004100, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateASRReg, "asrs|asr<c> <Rdn>, <Rm>"}, 10248 { 0xffe0f0f0, 0xfa40f000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateASRReg, "asr{s}<c>.w <Rd>, <Rn>, <Rm>"}, 10249 // lsl (immediate) 10250 { 0xfffff800, 0x00000000, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLSLImm, "lsls|lsl<c> <Rd>, <Rm>, #imm"}, 10251 { 0xffef8030, 0xea4f0000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLSLImm, "lsl{s}<c>.w <Rd>, <Rm>, #imm"}, 10252 // lsl (register) 10253 { 0xffffffc0, 0x00004080, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLSLReg, "lsls|lsl<c> <Rdn>, <Rm>"}, 10254 { 0xffe0f0f0, 0xfa00f000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLSLReg, "lsl{s}<c>.w <Rd>, <Rn>, <Rm>"}, 10255 // lsr (immediate) 10256 { 0xfffff800, 0x00000800, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLSRImm, "lsrs|lsr<c> <Rd>, <Rm>, #imm"}, 10257 { 0xffef8030, 0xea4f0010, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLSRImm, "lsr{s}<c>.w <Rd>, <Rm>, #imm"}, 10258 // lsr (register) 10259 { 0xffffffc0, 0x000040c0, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLSRReg, "lsrs|lsr<c> <Rdn>, <Rm>"}, 10260 { 0xffe0f0f0, 0xfa20f000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLSRReg, "lsr{s}<c>.w <Rd>, <Rn>, <Rm>"}, 10261 // rrx is a special case encoding of ror (immediate) 10262 { 0xffeff0f0, 0xea4f0030, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateRRX, "rrx{s}<c>.w <Rd>, <Rm>"}, 10263 // ror (immediate) 10264 { 0xffef8030, 0xea4f0030, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateRORImm, "ror{s}<c>.w <Rd>, <Rm>, #imm"}, 10265 // ror (register) 10266 { 0xffffffc0, 0x000041c0, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateRORReg, "rors|ror<c> <Rdn>, <Rm>"}, 10267 { 0xffe0f0f0, 0xfa60f000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateRORReg, "ror{s}<c>.w <Rd>, <Rn>, <Rm>"}, 10268 // mul 10269 { 0xffffffc0, 0x00004340, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateMUL, "muls <Rdm>,<Rn>,<Rdm>" }, 10270 // mul 10271 { 0xfff0f0f0, 0xfb00f000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateMUL, "mul<c> <Rd>,<Rn>,<Rm>" }, 10272 10273 //---------------------------------------------------------------------- 10274 // Load instructions 10275 //---------------------------------------------------------------------- 10276 { 0xfffff800, 0x0000c800, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLDM, "ldm<c> <Rn>{!} <registers>" }, 10277 { 0xffd02000, 0xe8900000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLDM, "ldm<c>.w <Rn>{!} <registers>" }, 10278 { 0xffd00000, 0xe9100000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateLDMDB, "ldmdb<c> <Rn>{!} <registers>" }, 10279 { 0xfffff800, 0x00006800, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLDRRtRnImm, "ldr<c> <Rt>, [<Rn>{,#imm}]"}, 10280 { 0xfffff800, 0x00009800, ARMV4T_ABOVE, eEncodingT2, eSize16, &EmulateInstructionARM::EmulateLDRRtRnImm, "ldr<c> <Rt>, [SP{,#imm}]"}, 10281 { 0xfff00000, 0xf8d00000, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulateLDRRtRnImm, "ldr<c>.w <Rt>, [<Rn>{,#imm12}]"}, 10282 { 0xfff00800, 0xf8500800, ARMV6T2_ABOVE, eEncodingT4, eSize32, &EmulateInstructionARM::EmulateLDRRtRnImm, "ldr<c> <Rt>, [<Rn>{,#+/-<imm8>}]{!}"}, 10283 // Thumb2 PC-relative load into register 10284 { 0xff7f0000, 0xf85f0000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLDRRtPCRelative, "ldr<c>.w <Rt>, [PC, +/-#imm}]"}, 10285 { 0xfffffe00, 0x00005800, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLDRRegister, "ldr<c> <Rt>, [<Rn>, <Rm>]" }, 10286 { 0xfff00fc0, 0xf8500000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLDRRegister, "ldr<c>.w <Rt>, [<Rn>,<Rm>{,LSL #<imm2>}]" }, 10287 { 0xfffff800, 0x00007800, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLDRBImmediate, "ldrb<c> <Rt>,[<Rn>{,#<imm5>}]" }, 10288 { 0xfff00000, 0xf8900000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLDRBImmediate, "ldrb<c>.w <Rt>,[<Rn>{,#<imm12>}]" }, 10289 { 0xfff00800, 0xf8100800, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulateLDRBImmediate, "ldrb<c> <Rt>,[>Rn>, #+/-<imm8>]{!}" }, 10290 { 0xff7f0000, 0xf81f0000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateLDRBLiteral, "ldrb<c> <Rt>,[...]" }, 10291 { 0xfffffe00, 0x00005c00, ARMV6T2_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLDRBRegister, "ldrb<c> <Rt>,[<Rn>,<Rm>]" }, 10292 { 0xfff00fc0, 0xf8100000, ARMV6T2_ABOVE, eEncodingT2, eSize32,&EmulateInstructionARM::EmulateLDRBRegister, "ldrb<c>.w <Rt>,[<Rn>,<Rm>{,LSL #imm2>}]" }, 10293 { 0xfffff800, 0x00008800, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLDRHImmediate, "ldrh<c> <Rt>, [<Rn>{,#<imm>}]" }, 10294 { 0xfff00000, 0xf8b00000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLDRHImmediate, "ldrh<c>.w <Rt>,[<Rn>{,#<imm12>}]" }, 10295 { 0xfff00800, 0xf8300800, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulateLDRHImmediate, "ldrh<c> <Rt>,[<Rn>,#+/-<imm8>]{!}" }, 10296 { 0xff7f0000, 0xf83f0000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateLDRHLiteral, "ldrh<c> <Rt>, <label>" }, 10297 { 0xfffffe00, 0x00005a00, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLDRHRegister, "ldrh<c> <Rt>, [<Rn>,<Rm>]" }, 10298 { 0xfff00fc0, 0xf8300000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLDRHRegister, "ldrh<c>.w <Rt>,[<Rn>,<Rm>{,LSL #<imm2>}]" }, 10299 { 0xfff00000, 0xf9900000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateLDRSBImmediate, "ldrsb<c> <Rt>,[<Rn>,#<imm12>]" }, 10300 { 0xfff00800, 0xf9100800, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLDRSBImmediate, "ldrsb<c> <Rt>,[<Rn>,#+/-<imm8>]" }, 10301 { 0xff7f0000, 0xf91f0000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateLDRSBLiteral, "ldrsb<c> <Rt>, <label>" }, 10302 { 0xfffffe00, 0x00005600, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLDRSBRegister, "ldrsb<c> <Rt>,[<Rn>,<Rm>]" }, 10303 { 0xfff00fc0, 0xf9100000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLDRSBRegister, "ldrsb<c>.w <Rt>,[<Rn>,<Rm>{,LSL #imm2>}]" }, 10304 { 0xfff00000, 0xf9b00000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateLDRSHImmediate, "ldrsh<c> <Rt>,[<Rn>,#<imm12>]" }, 10305 { 0xfff00800, 0xf9300800, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLDRSHImmediate, "ldrsh<c> <Rt>,[<Rn>,#+/-<imm8>]" }, 10306 { 0xff7f0000, 0xf93f0000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateLDRSHLiteral, "ldrsh<c> <Rt>,<label>" }, 10307 { 0xfffffe00, 0x00005e00, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLDRSHRegister, "ldrsh<c> <Rt>,[<Rn>,<Rm>]" }, 10308 { 0xfff00fc0, 0xf9300000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLDRSHRegister, "ldrsh<c>.w <Rt>,[<Rn>,<Rm>{,LSL #<imm2>}]" }, 10309 10310 //---------------------------------------------------------------------- 10311 // Store instructions 10312 //---------------------------------------------------------------------- 10313 { 0xfffff800, 0x0000c000, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateSTM, "stm<c> <Rn>{!} <registers>" }, 10314 { 0xffd00000, 0xe8800000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateSTM, "stm<c>.w <Rn>{!} <registers>" }, 10315 { 0xffd00000, 0xe9000000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateSTMDB, "stmdb<c> <Rn>{!} <registers>" }, 10316 { 0xfffff800, 0x00006000, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateSTRThumb, "str<c> <Rt>, [<Rn>{,#<imm>}]" }, 10317 { 0xfffff800, 0x00009000, ARMV4T_ABOVE, eEncodingT2, eSize16, &EmulateInstructionARM::EmulateSTRThumb, "str<c> <Rt>, [SP,#<imm>]" }, 10318 { 0xfff00000, 0xf8c00000, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulateSTRThumb, "str<c>.w <Rt>, [<Rn>,#<imm12>]" }, 10319 { 0xfff00800, 0xf8400800, ARMV6T2_ABOVE, eEncodingT4, eSize32, &EmulateInstructionARM::EmulateSTRThumb, "str<c> <Rt>, [<Rn>,#+/-<imm8>]" }, 10320 { 0xfffffe00, 0x00005000, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateSTRRegister, "str<c> <Rt> ,{<Rn>, <Rm>]" }, 10321 { 0xfff00fc0, 0xf8400000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateSTRRegister, "str<c>.w <Rt>, [<Rn>, <Rm> {lsl #imm2>}]" }, 10322 { 0xfffff800, 0x00007000, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateSTRBThumb, "strb<c> <Rt>, [<Rn>, #<imm5>]" }, 10323 { 0xfff00000, 0xf8800000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateSTRBThumb, "strb<c>.w <Rt>, [<Rn>, #<imm12>]" }, 10324 { 0xfff00800, 0xf8000800, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulateSTRBThumb, "strb<c> <Rt> ,[<Rn>, #+/-<imm8>]{!}" }, 10325 { 0xfffffe00, 0x00005200, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateSTRHRegister, "strh<c> <Rt>,[<Rn>,<Rm>]" }, 10326 { 0xfff00fc0, 0xf8200000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateSTRHRegister, "strh<c>.w <Rt>,[<Rn>,<Rm>{,LSL #<imm2>}]" }, 10327 10328 //---------------------------------------------------------------------- 10329 // Other instructions 10330 //---------------------------------------------------------------------- 10331 { 0xffffffc0, 0x0000b240, ARMV6_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateSXTB, "sxtb<c> <Rd>,<Rm>" }, 10332 { 0xfffff080, 0xfa4ff080, ARMV6_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateSXTB, "sxtb<c>.w <Rd>,<Rm>{,<rotation>}" }, 10333 { 0xffffffc0, 0x0000b200, ARMV6_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateSXTH, "sxth<c> <Rd>,<Rm>" }, 10334 { 0xfffff080, 0xfa0ff080, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateSXTH, "sxth<c>.w <Rd>,<Rm>{,<rotation>}" }, 10335 { 0xffffffc0, 0x0000b2c0, ARMV6_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateUXTB, "uxtb<c> <Rd>,<Rm>" }, 10336 { 0xfffff080, 0xfa5ff080, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateUXTB, "uxtb<c>.w <Rd>,<Rm>{,<rotation>}" }, 10337 { 0xffffffc0, 0x0000b280, ARMV6_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateUXTH, "uxth<c> <Rd>,<Rm>" }, 10338 { 0xfffff080, 0xfa1ff080, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateUXTH, "uxth<c>.w <Rd>,<Rm>{,<rotation>}" }, 10339 { 0xffd00000, 0xe8100000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateRFE, "rfedb<c> <Rn>{!}" }, 10340 { 0xffd00000, 0xe9900000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateRFE, "rfe{ia}<c> <Rn>{!}" } 10341 10342 }; 10343 10344 const size_t k_num_thumb_opcodes = sizeof(g_thumb_opcodes)/sizeof(ARMOpcode); 10345 for (size_t i=0; i<k_num_thumb_opcodes; ++i) 10346 { 10347 if ((g_thumb_opcodes[i].mask & opcode) == g_thumb_opcodes[i].value) 10348 return &g_thumb_opcodes[i]; 10349 } 10350 return NULL; 10351} 10352 10353bool 10354EmulateInstructionARM::SetArchitecture (const ArchSpec &arch) 10355{ 10356 m_arm_isa = 0; 10357 const char *arch_cstr = arch.GetArchitectureName (); 10358 if (arch_cstr) 10359 { 10360 if (0 == ::strcasecmp(arch_cstr, "armv4t")) m_arm_isa = ARMv4T; 10361 else if (0 == ::strcasecmp(arch_cstr, "armv4")) m_arm_isa = ARMv4; 10362 else if (0 == ::strcasecmp(arch_cstr, "armv5tej")) m_arm_isa = ARMv5TEJ; 10363 else if (0 == ::strcasecmp(arch_cstr, "armv5te")) m_arm_isa = ARMv5TE; 10364 else if (0 == ::strcasecmp(arch_cstr, "armv5t")) m_arm_isa = ARMv5T; 10365 else if (0 == ::strcasecmp(arch_cstr, "armv6k")) m_arm_isa = ARMv6K; 10366 else if (0 == ::strcasecmp(arch_cstr, "armv6")) m_arm_isa = ARMv6; 10367 else if (0 == ::strcasecmp(arch_cstr, "armv6t2")) m_arm_isa = ARMv6T2; 10368 else if (0 == ::strcasecmp(arch_cstr, "armv7")) m_arm_isa = ARMv7; 10369 else if (0 == ::strcasecmp(arch_cstr, "armv8")) m_arm_isa = ARMv8; 10370 } 10371 return m_arm_isa != 0; 10372} 10373 10374 10375bool 10376EmulateInstructionARM::ReadInstruction () 10377{ 10378 bool success = false; 10379 m_opcode_cpsr = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS, 0, &success); 10380 if (success) 10381 { 10382 addr_t pc = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, LLDB_INVALID_ADDRESS, &success); 10383 if (success) 10384 { 10385 Context read_inst_context; 10386 read_inst_context.type = eContextReadOpcode; 10387 read_inst_context.SetNoArgs (); 10388 10389 if (m_opcode_cpsr & MASK_CPSR_T) 10390 { 10391 m_opcode_mode = eModeThumb; 10392 uint32_t thumb_opcode = MemARead(read_inst_context, pc, 2, 0, &success); 10393 10394 if (success) 10395 { 10396 if ((thumb_opcode & 0xe000) != 0xe000 || ((thumb_opcode & 0x1800u) == 0)) 10397 { 10398 m_opcode.SetOpcode16 (thumb_opcode); 10399 } 10400 else 10401 { 10402 m_opcode.SetOpcode32 ((thumb_opcode << 16) | MemARead(read_inst_context, pc + 2, 2, 0, &success)); 10403 } 10404 } 10405 } 10406 else 10407 { 10408 m_opcode_mode = eModeARM; 10409 m_opcode.SetOpcode32 (MemARead(read_inst_context, pc, 4, 0, &success)); 10410 } 10411 } 10412 } 10413 if (!success) 10414 { 10415 m_opcode_mode = eModeInvalid; 10416 m_opcode_pc = LLDB_INVALID_ADDRESS; 10417 } 10418 return success; 10419} 10420 10421uint32_t 10422EmulateInstructionARM::ArchVersion () 10423{ 10424 return m_arm_isa; 10425} 10426 10427bool 10428EmulateInstructionARM::ConditionPassed (const uint32_t opcode) 10429{ 10430 if (m_opcode_cpsr == 0) 10431 return false; 10432 10433 const uint32_t cond = CurrentCond (opcode); 10434 10435 if (cond == UINT32_MAX) 10436 return false; 10437 10438 bool result = false; 10439 switch (UnsignedBits(cond, 3, 1)) 10440 { 10441 case 0: result = (m_opcode_cpsr & MASK_CPSR_Z) != 0; break; 10442 case 1: result = (m_opcode_cpsr & MASK_CPSR_C) != 0; break; 10443 case 2: result = (m_opcode_cpsr & MASK_CPSR_N) != 0; break; 10444 case 3: result = (m_opcode_cpsr & MASK_CPSR_V) != 0; break; 10445 case 4: result = ((m_opcode_cpsr & MASK_CPSR_C) != 0) && ((m_opcode_cpsr & MASK_CPSR_Z) == 0); break; 10446 case 5: 10447 { 10448 bool n = (m_opcode_cpsr & MASK_CPSR_N); 10449 bool v = (m_opcode_cpsr & MASK_CPSR_V); 10450 result = n == v; 10451 } 10452 break; 10453 case 6: 10454 { 10455 bool n = (m_opcode_cpsr & MASK_CPSR_N); 10456 bool v = (m_opcode_cpsr & MASK_CPSR_V); 10457 result = n == v && ((m_opcode_cpsr & MASK_CPSR_Z) == 0); 10458 } 10459 break; 10460 case 7: 10461 result = true; 10462 break; 10463 } 10464 10465 if (cond & 1) 10466 result = !result; 10467 return result; 10468} 10469 10470uint32_t 10471EmulateInstructionARM::CurrentCond (const uint32_t opcode) 10472{ 10473 switch (m_opcode_mode) 10474 { 10475 default: 10476 case eModeInvalid: 10477 break; 10478 10479 case eModeARM: 10480 return UnsignedBits(opcode, 31, 28); 10481 10482 case eModeThumb: 10483 // For T1 and T3 encodings of the Branch instruction, it returns the 4-bit 10484 // 'cond' field of the encoding. 10485 { 10486 const uint32_t byte_size = m_opcode.GetByteSize(); 10487 if (byte_size == 2) 10488 { 10489 if (Bits32(opcode, 15, 12) == 0x0d && Bits32(opcode, 11, 7) != 0x0f) 10490 return Bits32(opcode, 11, 7); 10491 } 10492 else 10493 { 10494 assert (byte_size == 4); 10495 if (Bits32(opcode, 31, 27) == 0x1e && 10496 Bits32(opcode, 15, 14) == 0x02 && 10497 Bits32(opcode, 12, 12) == 0x00 && 10498 Bits32(opcode, 25, 22) <= 0x0d) 10499 { 10500 return Bits32(opcode, 25, 22); 10501 } 10502 } 10503 10504 return m_it_session.GetCond(); 10505 } 10506 } 10507 return UINT32_MAX; // Return invalid value 10508} 10509 10510bool 10511EmulateInstructionARM::InITBlock() 10512{ 10513 return CurrentInstrSet() == eModeThumb && m_it_session.InITBlock(); 10514} 10515 10516bool 10517EmulateInstructionARM::LastInITBlock() 10518{ 10519 return CurrentInstrSet() == eModeThumb && m_it_session.LastInITBlock(); 10520} 10521 10522bool 10523EmulateInstructionARM::BadMode (uint32_t mode) 10524{ 10525 10526 switch (mode) 10527 { 10528 case 16: return false; // '10000' 10529 case 17: return false; // '10001' 10530 case 18: return false; // '10010' 10531 case 19: return false; // '10011' 10532 case 22: return false; // '10110' 10533 case 23: return false; // '10111' 10534 case 27: return false; // '11011' 10535 case 31: return false; // '11111' 10536 default: return true; 10537 } 10538 return true; 10539} 10540 10541bool 10542EmulateInstructionARM::CurrentModeIsPrivileged () 10543{ 10544 uint32_t mode = Bits32 (m_opcode_cpsr, 4, 0); 10545 10546 if (BadMode (mode)) 10547 return false; 10548 10549 if (mode == 16) 10550 return false; 10551 10552 return true; 10553} 10554 10555void 10556EmulateInstructionARM::CPSRWriteByInstr (uint32_t value, uint32_t bytemask, bool affect_execstate) 10557{ 10558 bool privileged = CurrentModeIsPrivileged(); 10559 10560 uint32_t tmp_cpsr = 0; 10561 10562 tmp_cpsr = tmp_cpsr | (Bits32 (m_opcode_cpsr, 23, 20) << 20); 10563 10564 if (BitIsSet (bytemask, 3)) 10565 { 10566 tmp_cpsr = tmp_cpsr | (Bits32 (value, 31, 27) << 27); 10567 if (affect_execstate) 10568 tmp_cpsr = tmp_cpsr | (Bits32 (value, 26, 24) << 24); 10569 } 10570 10571 if (BitIsSet (bytemask, 2)) 10572 { 10573 tmp_cpsr = tmp_cpsr | (Bits32 (value, 19, 16) << 16); 10574 } 10575 10576 if (BitIsSet (bytemask, 1)) 10577 { 10578 if (affect_execstate) 10579 tmp_cpsr = tmp_cpsr | (Bits32 (value, 15, 10) << 10); 10580 tmp_cpsr = tmp_cpsr | (Bit32 (value, 9) << 9); 10581 if (privileged) 10582 tmp_cpsr = tmp_cpsr | (Bit32 (value, 8) << 8); 10583 } 10584 10585 if (BitIsSet (bytemask, 0)) 10586 { 10587 if (privileged) 10588 tmp_cpsr = tmp_cpsr | (Bits32 (value, 7, 6) << 6); 10589 if (affect_execstate) 10590 tmp_cpsr = tmp_cpsr | (Bit32 (value, 5) << 5); 10591 if (privileged) 10592 tmp_cpsr = tmp_cpsr | Bits32 (value, 4, 0); 10593 } 10594 10595 m_opcode_cpsr = tmp_cpsr; 10596} 10597 10598 10599bool 10600EmulateInstructionARM::BranchWritePC (const Context &context, uint32_t addr) 10601{ 10602 addr_t target; 10603 10604 // Check the current instruction set. 10605 if (CurrentInstrSet() == eModeARM) 10606 target = addr & 0xfffffffc; 10607 else 10608 target = addr & 0xfffffffe; 10609 10610 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, target)) 10611 return false; 10612 10613 return true; 10614} 10615 10616// As a side effect, BXWritePC sets context.arg2 to eModeARM or eModeThumb by inspecting addr. 10617bool 10618EmulateInstructionARM::BXWritePC (Context &context, uint32_t addr) 10619{ 10620 addr_t target; 10621 // If the CPSR is changed due to switching between ARM and Thumb ISETSTATE, 10622 // we want to record it and issue a WriteRegister callback so the clients 10623 // can track the mode changes accordingly. 10624 bool cpsr_changed = false; 10625 10626 if (BitIsSet(addr, 0)) 10627 { 10628 if (CurrentInstrSet() != eModeThumb) 10629 { 10630 SelectInstrSet(eModeThumb); 10631 cpsr_changed = true; 10632 } 10633 target = addr & 0xfffffffe; 10634 context.SetMode (eModeThumb); 10635 } 10636 else if (BitIsClear(addr, 1)) 10637 { 10638 if (CurrentInstrSet() != eModeARM) 10639 { 10640 SelectInstrSet(eModeARM); 10641 cpsr_changed = true; 10642 } 10643 target = addr & 0xfffffffc; 10644 context.SetMode (eModeARM); 10645 } 10646 else 10647 return false; // address<1:0> == '10' => UNPREDICTABLE 10648 10649 if (cpsr_changed) 10650 { 10651 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS, m_new_inst_cpsr)) 10652 return false; 10653 } 10654 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, target)) 10655 return false; 10656 10657 return true; 10658} 10659 10660// Dispatches to either BXWritePC or BranchWritePC based on architecture versions. 10661bool 10662EmulateInstructionARM::LoadWritePC (Context &context, uint32_t addr) 10663{ 10664 if (ArchVersion() >= ARMv5T) 10665 return BXWritePC(context, addr); 10666 else 10667 return BranchWritePC((const Context)context, addr); 10668} 10669 10670// Dispatches to either BXWritePC or BranchWritePC based on architecture versions and current instruction set. 10671bool 10672EmulateInstructionARM::ALUWritePC (Context &context, uint32_t addr) 10673{ 10674 if (ArchVersion() >= ARMv7 && CurrentInstrSet() == eModeARM) 10675 return BXWritePC(context, addr); 10676 else 10677 return BranchWritePC((const Context)context, addr); 10678} 10679 10680EmulateInstructionARM::Mode 10681EmulateInstructionARM::CurrentInstrSet () 10682{ 10683 return m_opcode_mode; 10684} 10685 10686// Set the 'T' bit of our CPSR. The m_opcode_mode gets updated when the next 10687// ReadInstruction() is performed. This function has a side effect of updating 10688// the m_new_inst_cpsr member variable if necessary. 10689bool 10690EmulateInstructionARM::SelectInstrSet (Mode arm_or_thumb) 10691{ 10692 m_new_inst_cpsr = m_opcode_cpsr; 10693 switch (arm_or_thumb) 10694 { 10695 default: 10696 return false; 10697 eModeARM: 10698 // Clear the T bit. 10699 m_new_inst_cpsr &= ~MASK_CPSR_T; 10700 break; 10701 eModeThumb: 10702 // Set the T bit. 10703 m_new_inst_cpsr |= MASK_CPSR_T; 10704 break; 10705 } 10706 return true; 10707} 10708 10709// This function returns TRUE if the processor currently provides support for 10710// unaligned memory accesses, or FALSE otherwise. This is always TRUE in ARMv7, 10711// controllable by the SCTLR.U bit in ARMv6, and always FALSE before ARMv6. 10712bool 10713EmulateInstructionARM::UnalignedSupport() 10714{ 10715 return (ArchVersion() >= ARMv7); 10716} 10717 10718// The main addition and subtraction instructions can produce status information 10719// about both unsigned carry and signed overflow conditions. This status 10720// information can be used to synthesize multi-word additions and subtractions. 10721EmulateInstructionARM::AddWithCarryResult 10722EmulateInstructionARM::AddWithCarry (uint32_t x, uint32_t y, uint8_t carry_in) 10723{ 10724 uint32_t result; 10725 uint8_t carry_out; 10726 uint8_t overflow; 10727 10728 uint64_t unsigned_sum = x + y + carry_in; 10729 int64_t signed_sum = (int32_t)x + (int32_t)y + (int32_t)carry_in; 10730 10731 result = UnsignedBits(unsigned_sum, 31, 0); 10732 carry_out = (result == unsigned_sum ? 0 : 1); 10733 overflow = ((int32_t)result == signed_sum ? 0 : 1); 10734 10735 AddWithCarryResult res = { result, carry_out, overflow }; 10736 return res; 10737} 10738 10739uint32_t 10740EmulateInstructionARM::ReadCoreReg(uint32_t num, bool *success) 10741{ 10742 uint32_t reg_kind, reg_num; 10743 switch (num) 10744 { 10745 case SP_REG: 10746 reg_kind = eRegisterKindGeneric; 10747 reg_num = LLDB_REGNUM_GENERIC_SP; 10748 break; 10749 case LR_REG: 10750 reg_kind = eRegisterKindGeneric; 10751 reg_num = LLDB_REGNUM_GENERIC_RA; 10752 break; 10753 case PC_REG: 10754 reg_kind = eRegisterKindGeneric; 10755 reg_num = LLDB_REGNUM_GENERIC_PC; 10756 break; 10757 default: 10758 if (num < SP_REG) 10759 { 10760 reg_kind = eRegisterKindDWARF; 10761 reg_num = dwarf_r0 + num; 10762 } 10763 else 10764 { 10765 assert(0 && "Invalid register number"); 10766 *success = false; 10767 return UINT32_MAX; 10768 } 10769 break; 10770 } 10771 10772 // Read our register. 10773 uint32_t val = ReadRegisterUnsigned (reg_kind, reg_num, 0, success); 10774 10775 // When executing an ARM instruction , PC reads as the address of the current 10776 // instruction plus 8. 10777 // When executing a Thumb instruction , PC reads as the address of the current 10778 // instruction plus 4. 10779 if (num == 15) 10780 { 10781 if (CurrentInstrSet() == eModeARM) 10782 val += 8; 10783 else 10784 val += 4; 10785 } 10786 10787 return val; 10788} 10789 10790// Write the result to the ARM core register Rd, and optionally update the 10791// condition flags based on the result. 10792// 10793// This helper method tries to encapsulate the following pseudocode from the 10794// ARM Architecture Reference Manual: 10795// 10796// if d == 15 then // Can only occur for encoding A1 10797// ALUWritePC(result); // setflags is always FALSE here 10798// else 10799// R[d] = result; 10800// if setflags then 10801// APSR.N = result<31>; 10802// APSR.Z = IsZeroBit(result); 10803// APSR.C = carry; 10804// // APSR.V unchanged 10805// 10806// In the above case, the API client does not pass in the overflow arg, which 10807// defaults to ~0u. 10808bool 10809EmulateInstructionARM::WriteCoreRegOptionalFlags (Context &context, 10810 const uint32_t result, 10811 const uint32_t Rd, 10812 bool setflags, 10813 const uint32_t carry, 10814 const uint32_t overflow) 10815{ 10816 if (Rd == 15) 10817 { 10818 if (!ALUWritePC (context, result)) 10819 return false; 10820 } 10821 else 10822 { 10823 uint32_t reg_kind, reg_num; 10824 switch (Rd) 10825 { 10826 case SP_REG: 10827 reg_kind = eRegisterKindGeneric; 10828 reg_num = LLDB_REGNUM_GENERIC_SP; 10829 break; 10830 case LR_REG: 10831 reg_kind = eRegisterKindGeneric; 10832 reg_num = LLDB_REGNUM_GENERIC_RA; 10833 break; 10834 default: 10835 reg_kind = eRegisterKindDWARF; 10836 reg_num = dwarf_r0 + Rd; 10837 } 10838 if (!WriteRegisterUnsigned (context, reg_kind, reg_num, result)) 10839 return false; 10840 if (setflags) 10841 return WriteFlags (context, result, carry, overflow); 10842 } 10843 return true; 10844} 10845 10846// This helper method tries to encapsulate the following pseudocode from the 10847// ARM Architecture Reference Manual: 10848// 10849// APSR.N = result<31>; 10850// APSR.Z = IsZeroBit(result); 10851// APSR.C = carry; 10852// APSR.V = overflow 10853// 10854// Default arguments can be specified for carry and overflow parameters, which means 10855// not to update the respective flags. 10856bool 10857EmulateInstructionARM::WriteFlags (Context &context, 10858 const uint32_t result, 10859 const uint32_t carry, 10860 const uint32_t overflow) 10861{ 10862 m_new_inst_cpsr = m_opcode_cpsr; 10863 SetBit32(m_new_inst_cpsr, CPSR_N_POS, Bit32(result, CPSR_N_POS)); 10864 SetBit32(m_new_inst_cpsr, CPSR_Z_POS, result == 0 ? 1 : 0); 10865 if (carry != ~0u) 10866 SetBit32(m_new_inst_cpsr, CPSR_C_POS, carry); 10867 if (overflow != ~0u) 10868 SetBit32(m_new_inst_cpsr, CPSR_V_POS, overflow); 10869 if (m_new_inst_cpsr != m_opcode_cpsr) 10870 { 10871 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS, m_new_inst_cpsr)) 10872 return false; 10873 } 10874 return true; 10875} 10876 10877bool 10878EmulateInstructionARM::EvaluateInstruction () 10879{ 10880 // Advance the ITSTATE bits to their values for the next instruction. 10881 if (m_opcode_mode == eModeThumb && m_it_session.InITBlock()) 10882 m_it_session.ITAdvance(); 10883 10884 return false; 10885} 10886