EmulateInstructionARM.cpp revision 688926f8fb9a56964249ec970b4ae313a5b366d4
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_inst_cpsr, CPSR_C) 28#define APSR_V Bit32(m_inst_cpsr, CPSR_V) 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 ARMV6T2_ABOVE (ARMv6T2|ARMv7|ARMv8) 133 134//---------------------------------------------------------------------- 135// 136// EmulateInstructionARM implementation 137// 138//---------------------------------------------------------------------- 139 140void 141EmulateInstructionARM::Initialize () 142{ 143} 144 145void 146EmulateInstructionARM::Terminate () 147{ 148} 149 150// Write "bits (32) UNKNOWN" to memory address "address". Helper function for many ARM instructions. 151bool 152EmulateInstructionARM::WriteBits32UnknownToMemory (addr_t address) 153{ 154 EmulateInstruction::Context context; 155 context.type = EmulateInstruction::eContextWriteMemoryRandomBits; 156 context.SetNoArgs (); 157 158 uint32_t random_data = rand (); 159 const uint32_t addr_byte_size = GetAddressByteSize(); 160 161 if (!MemAWrite (context, address, random_data, addr_byte_size)) 162 return false; 163 164 return true; 165} 166 167// Write "bits (32) UNKNOWN" to register n. Helper function for many ARM instructions. 168bool 169EmulateInstructionARM::WriteBits32Unknown (int n) 170{ 171 EmulateInstruction::Context context; 172 context.type = EmulateInstruction::eContextWriteRegisterRandomBits; 173 context.SetNoArgs (); 174 175 bool success; 176 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success); 177 178 if (!success) 179 return false; 180 181 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, data)) 182 return false; 183 184 return true; 185} 186 187// Push Multiple Registers stores multiple registers to the stack, storing to 188// consecutive memory locations ending just below the address in SP, and updates 189// SP to point to the start of the stored data. 190bool 191EmulateInstructionARM::EmulatePUSH (ARMEncoding encoding) 192{ 193#if 0 194 // ARM pseudo code... 195 if (ConditionPassed()) 196 { 197 EncodingSpecificOperations(); 198 NullCheckIfThumbEE(13); 199 address = SP - 4*BitCount(registers); 200 201 for (i = 0 to 14) 202 { 203 if (registers<i> == ’1’) 204 { 205 if i == 13 && i != LowestSetBit(registers) // Only possible for encoding A1 206 MemA[address,4] = bits(32) UNKNOWN; 207 else 208 MemA[address,4] = R[i]; 209 address = address + 4; 210 } 211 } 212 213 if (registers<15> == ’1’) // Only possible for encoding A1 or A2 214 MemA[address,4] = PCStoreValue(); 215 216 SP = SP - 4*BitCount(registers); 217 } 218#endif 219 220 bool success = false; 221 const uint32_t opcode = OpcodeAsUnsigned (&success); 222 if (!success) 223 return false; 224 225 if (ConditionPassed()) 226 { 227 const uint32_t addr_byte_size = GetAddressByteSize(); 228 const addr_t sp = ReadCoreReg (SP_REG, &success); 229 if (!success) 230 return false; 231 uint32_t registers = 0; 232 uint32_t Rt; // the source register 233 switch (encoding) { 234 case eEncodingT1: 235 registers = Bits32(opcode, 7, 0); 236 // The M bit represents LR. 237 if (Bit32(opcode, 8)) 238 registers |= (1u << 14); 239 // if BitCount(registers) < 1 then UNPREDICTABLE; 240 if (BitCount(registers) < 1) 241 return false; 242 break; 243 case eEncodingT2: 244 // Ignore bits 15 & 13. 245 registers = Bits32(opcode, 15, 0) & ~0xa000; 246 // if BitCount(registers) < 2 then UNPREDICTABLE; 247 if (BitCount(registers) < 2) 248 return false; 249 break; 250 case eEncodingT3: 251 Rt = Bits32(opcode, 15, 12); 252 // if BadReg(t) then UNPREDICTABLE; 253 if (BadReg(Rt)) 254 return false; 255 registers = (1u << Rt); 256 break; 257 case eEncodingA1: 258 registers = Bits32(opcode, 15, 0); 259 // Instead of return false, let's handle the following case as well, 260 // which amounts to pushing one reg onto the full descending stacks. 261 // if BitCount(register_list) < 2 then SEE STMDB / STMFD; 262 break; 263 case eEncodingA2: 264 Rt = Bits32(opcode, 15, 12); 265 // if t == 13 then UNPREDICTABLE; 266 if (Rt == dwarf_sp) 267 return false; 268 registers = (1u << Rt); 269 break; 270 default: 271 return false; 272 } 273 addr_t sp_offset = addr_byte_size * BitCount (registers); 274 addr_t addr = sp - sp_offset; 275 uint32_t i; 276 277 EmulateInstruction::Context context; 278 context.type = EmulateInstruction::eContextPushRegisterOnStack; 279 Register dwarf_reg; 280 dwarf_reg.SetRegister (eRegisterKindDWARF, 0); 281 for (i=0; i<15; ++i) 282 { 283 if (BitIsSet (registers, i)) 284 { 285 dwarf_reg.num = dwarf_r0 + i; 286 context.SetRegisterPlusOffset (dwarf_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 (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 const uint32_t opcode = OpcodeAsUnsigned (&success); 343 if (!success) 344 return false; 345 346 if (ConditionPassed()) 347 { 348 const uint32_t addr_byte_size = GetAddressByteSize(); 349 const addr_t sp = ReadCoreReg (SP_REG, &success); 350 if (!success) 351 return false; 352 uint32_t registers = 0; 353 uint32_t Rt; // the destination register 354 switch (encoding) { 355 case eEncodingT1: 356 registers = Bits32(opcode, 7, 0); 357 // The P bit represents PC. 358 if (Bit32(opcode, 8)) 359 registers |= (1u << 15); 360 // if BitCount(registers) < 1 then UNPREDICTABLE; 361 if (BitCount(registers) < 1) 362 return false; 363 break; 364 case eEncodingT2: 365 // Ignore bit 13. 366 registers = Bits32(opcode, 15, 0) & ~0x2000; 367 // if BitCount(registers) < 2 || (P == '1' && M == '1') then UNPREDICTABLE; 368 if (BitCount(registers) < 2 || (Bit32(opcode, 15) && Bit32(opcode, 14))) 369 return false; 370 // if registers<15> == '1' && InITBlock() && !LastInITBlock() then UNPREDICTABLE; 371 if (BitIsSet(registers, 15) && InITBlock() && !LastInITBlock()) 372 return false; 373 break; 374 case eEncodingT3: 375 Rt = Bits32(opcode, 15, 12); 376 // if t == 13 || (t == 15 && InITBlock() && !LastInITBlock()) then UNPREDICTABLE; 377 if (Rt == 13) 378 return false; 379 if (Rt == 15 && InITBlock() && !LastInITBlock()) 380 return false; 381 registers = (1u << Rt); 382 break; 383 case eEncodingA1: 384 registers = Bits32(opcode, 15, 0); 385 // Instead of return false, let's handle the following case as well, 386 // which amounts to popping one reg from the full descending stacks. 387 // if BitCount(register_list) < 2 then SEE LDM / LDMIA / LDMFD; 388 389 // if registers<13> == ‘1’ && ArchVersion() >= 7 then UNPREDICTABLE; 390 if (BitIsSet(opcode, 13) && ArchVersion() >= ARMv7) 391 return false; 392 break; 393 case eEncodingA2: 394 Rt = Bits32(opcode, 15, 12); 395 // if t == 13 then UNPREDICTABLE; 396 if (Rt == dwarf_sp) 397 return false; 398 registers = (1u << Rt); 399 break; 400 default: 401 return false; 402 } 403 addr_t sp_offset = addr_byte_size * BitCount (registers); 404 addr_t addr = sp; 405 uint32_t i, data; 406 407 EmulateInstruction::Context context; 408 context.type = EmulateInstruction::eContextPopRegisterOffStack; 409 Register dwarf_reg; 410 dwarf_reg.SetRegister (eRegisterKindDWARF, 0); 411 for (i=0; i<15; ++i) 412 { 413 if (BitIsSet (registers, i)) 414 { 415 dwarf_reg.num = dwarf_r0 + i; 416 context.SetRegisterPlusOffset (dwarf_reg, addr - sp); 417 data = MemARead(context, addr, 4, 0, &success); 418 if (!success) 419 return false; 420 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_reg.num, data)) 421 return false; 422 addr += addr_byte_size; 423 } 424 } 425 426 if (BitIsSet (registers, 15)) 427 { 428 dwarf_reg.num = dwarf_pc; 429 context.SetRegisterPlusOffset (dwarf_reg, addr - sp); 430 data = MemARead(context, addr, 4, 0, &success); 431 if (!success) 432 return false; 433 // In ARMv5T and above, this is an interworking branch. 434 if (!LoadWritePC(context, data)) 435 return false; 436 addr += addr_byte_size; 437 } 438 439 context.type = EmulateInstruction::eContextAdjustStackPointer; 440 context.SetImmediateSigned (sp_offset); 441 442 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, sp + sp_offset)) 443 return false; 444 } 445 return true; 446} 447 448// Set r7 or ip to point to saved value residing within the stack. 449// ADD (SP plus immediate) 450bool 451EmulateInstructionARM::EmulateADDRdSPImm (ARMEncoding encoding) 452{ 453#if 0 454 // ARM pseudo code... 455 if (ConditionPassed()) 456 { 457 EncodingSpecificOperations(); 458 (result, carry, overflow) = AddWithCarry(SP, imm32, ‘0’); 459 if d == 15 then 460 ALUWritePC(result); // setflags is always FALSE here 461 else 462 R[d] = result; 463 if setflags then 464 APSR.N = result<31>; 465 APSR.Z = IsZeroBit(result); 466 APSR.C = carry; 467 APSR.V = overflow; 468 } 469#endif 470 471 bool success = false; 472 const uint32_t opcode = OpcodeAsUnsigned (&success); 473 if (!success) 474 return false; 475 476 if (ConditionPassed()) 477 { 478 const addr_t sp = ReadCoreReg (SP_REG, &success); 479 if (!success) 480 return false; 481 uint32_t Rd; // the destination register 482 uint32_t imm32; 483 switch (encoding) { 484 case eEncodingT1: 485 Rd = 7; 486 imm32 = Bits32(opcode, 7, 0) << 2; // imm32 = ZeroExtend(imm8:'00', 32) 487 break; 488 case eEncodingA1: 489 Rd = Bits32(opcode, 15, 12); 490 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12) 491 break; 492 default: 493 return false; 494 } 495 addr_t sp_offset = imm32; 496 addr_t addr = sp + sp_offset; // a pointer to the stack area 497 498 EmulateInstruction::Context context; 499 context.type = EmulateInstruction::eContextRegisterPlusOffset; 500 Register sp_reg; 501 sp_reg.SetRegister (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP); 502 context.SetRegisterPlusOffset (sp_reg, sp_offset); 503 504 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + Rd, addr)) 505 return false; 506 } 507 return true; 508} 509 510// Set r7 or ip to the current stack pointer. 511// MOV (register) 512bool 513EmulateInstructionARM::EmulateMOVRdSP (ARMEncoding encoding) 514{ 515#if 0 516 // ARM pseudo code... 517 if (ConditionPassed()) 518 { 519 EncodingSpecificOperations(); 520 result = R[m]; 521 if d == 15 then 522 ALUWritePC(result); // setflags is always FALSE here 523 else 524 R[d] = result; 525 if setflags then 526 APSR.N = result<31>; 527 APSR.Z = IsZeroBit(result); 528 // APSR.C unchanged 529 // APSR.V unchanged 530 } 531#endif 532 533 bool success = false; 534 //const uint32_t opcode = OpcodeAsUnsigned (&success); 535 //if (!success) 536 // return false; 537 538 if (ConditionPassed()) 539 { 540 const addr_t sp = ReadCoreReg (SP_REG, &success); 541 if (!success) 542 return false; 543 uint32_t Rd; // the destination register 544 switch (encoding) { 545 case eEncodingT1: 546 Rd = 7; 547 break; 548 case eEncodingA1: 549 Rd = 12; 550 break; 551 default: 552 return false; 553 } 554 555 EmulateInstruction::Context context; 556 context.type = EmulateInstruction::eContextRegisterPlusOffset; 557 Register sp_reg; 558 sp_reg.SetRegister (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP); 559 context.SetRegisterPlusOffset (sp_reg, 0); 560 561 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + Rd, sp)) 562 return false; 563 } 564 return true; 565} 566 567// Move from high register (r8-r15) to low register (r0-r7). 568// MOV (register) 569bool 570EmulateInstructionARM::EmulateMOVLowHigh (ARMEncoding encoding) 571{ 572 return EmulateMOVRdRm (encoding); 573} 574 575// Move from register to register. 576// MOV (register) 577bool 578EmulateInstructionARM::EmulateMOVRdRm (ARMEncoding encoding) 579{ 580#if 0 581 // ARM pseudo code... 582 if (ConditionPassed()) 583 { 584 EncodingSpecificOperations(); 585 result = R[m]; 586 if d == 15 then 587 ALUWritePC(result); // setflags is always FALSE here 588 else 589 R[d] = result; 590 if setflags then 591 APSR.N = result<31>; 592 APSR.Z = IsZeroBit(result); 593 // APSR.C unchanged 594 // APSR.V unchanged 595 } 596#endif 597 598 bool success = false; 599 const uint32_t opcode = OpcodeAsUnsigned (&success); 600 if (!success) 601 return false; 602 603 if (ConditionPassed()) 604 { 605 uint32_t Rm; // the source register 606 uint32_t Rd; // the destination register 607 bool setflags; 608 switch (encoding) { 609 case eEncodingT1: 610 Rd = Bit32(opcode, 7) << 3 | Bits32(opcode, 2, 0); 611 Rm = Bits32(opcode, 6, 3); 612 setflags = false; 613 if (Rd == 15 && InITBlock() && !LastInITBlock()) 614 return false; 615 break; 616 case eEncodingT2: 617 Rd = Bits32(opcode, 2, 0); 618 Rm = Bits32(opcode, 5, 3); 619 setflags = true; 620 if (InITBlock()) 621 return false; 622 break; 623 case eEncodingT3: 624 Rd = Bits32(opcode, 11, 8); 625 Rm = Bits32(opcode, 3, 0); 626 setflags = BitIsSet(opcode, 20); 627 // if setflags && (BadReg(d) || BadReg(m)) then UNPREDICTABLE; 628 if (setflags && (BadReg(Rd) || BadReg(Rm))) 629 return false; 630 // if !setflags && (d == 15 || m == 15 || (d == 13 && m == 13)) then UNPREDICTABLE; 631 if (!setflags && (Rd == 15 || Rm == 15 || (Rd == 13 && Rm == 13))) 632 return false; 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::eContextRegisterPlusOffset; 643 Register dwarf_reg; 644 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + Rm); 645 context.SetRegisterPlusOffset (dwarf_reg, 0); 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 (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 bool success = false; 677 const uint32_t opcode = OpcodeAsUnsigned (&success); 678 if (!success) 679 return false; 680 681 if (ConditionPassed()) 682 { 683 uint32_t Rd; // the destination register 684 uint32_t imm32; // the immediate value to be written to Rd 685 uint32_t carry; // the carry bit after ThumbExpandImm_C or ARMExpandImm_C. 686 bool setflags; 687 switch (encoding) { 688 case eEncodingT1: 689 Rd = Bits32(opcode, 10, 8); 690 setflags = !InITBlock(); 691 imm32 = Bits32(opcode, 7, 0); // imm32 = ZeroExtend(imm8, 32) 692 carry = APSR_C; 693 break; 694 case eEncodingT2: 695 Rd = Bits32(opcode, 11, 8); 696 setflags = BitIsSet(opcode, 20); 697 imm32 = ThumbExpandImm_C(opcode, APSR_C, carry); 698 if (BadReg(Rd)) 699 return false; 700 break; 701 default: 702 return false; 703 } 704 uint32_t result = imm32; 705 706 // The context specifies that an immediate is to be moved into Rd. 707 EmulateInstruction::Context context; 708 context.type = EmulateInstruction::eContextImmediate; 709 context.SetNoArgs (); 710 711 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry)) 712 return false; 713 } 714 return true; 715} 716 717// Bitwise NOT (immediate) writes the bitwise inverse of an immediate value to the destination register. 718// It can optionally update the condition flags based on the value. 719bool 720EmulateInstructionARM::EmulateMVNImm (ARMEncoding encoding) 721{ 722#if 0 723 // ARM pseudo code... 724 if (ConditionPassed()) 725 { 726 EncodingSpecificOperations(); 727 result = NOT(imm32); 728 if d == 15 then // Can only occur for ARM encoding 729 ALUWritePC(result); // setflags is always FALSE here 730 else 731 R[d] = result; 732 if setflags then 733 APSR.N = result<31>; 734 APSR.Z = IsZeroBit(result); 735 APSR.C = carry; 736 // APSR.V unchanged 737 } 738#endif 739 bool success = false; 740 const uint32_t opcode = OpcodeAsUnsigned (&success); 741 if (!success) 742 return false; 743 744 if (ConditionPassed()) 745 { 746 uint32_t Rd; // the destination register 747 uint32_t imm32; // the output after ThumbExpandImm_C or ARMExpandImm_C 748 uint32_t carry; // the carry bit after ThumbExpandImm_C or ARMExpandImm_C 749 bool setflags; 750 switch (encoding) { 751 case eEncodingT1: 752 Rd = Bits32(opcode, 11, 8); 753 setflags = BitIsSet(opcode, 20); 754 imm32 = ThumbExpandImm_C(opcode, APSR_C, carry); 755 break; 756 case eEncodingA1: 757 Rd = Bits32(opcode, 15, 12); 758 setflags = BitIsSet(opcode, 20); 759 imm32 = ARMExpandImm_C(opcode, APSR_C, carry); 760 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions; 761 // TODO: Emulate SUBS PC, LR and related instructions. 762 if (Rd == 15 && setflags) 763 return false; 764 break; 765 default: 766 return false; 767 } 768 uint32_t result = ~imm32; 769 770 // The context specifies that an immediate is to be moved into Rd. 771 EmulateInstruction::Context context; 772 context.type = EmulateInstruction::eContextImmediate; 773 context.SetNoArgs (); 774 775 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry)) 776 return false; 777 } 778 return true; 779} 780 781// Bitwise NOT (register) writes the bitwise inverse of a register value to the destination register. 782// It can optionally update the condition flags based on the result. 783bool 784EmulateInstructionARM::EmulateMVNReg (ARMEncoding encoding) 785{ 786#if 0 787 // ARM pseudo code... 788 if (ConditionPassed()) 789 { 790 EncodingSpecificOperations(); 791 (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C); 792 result = NOT(shifted); 793 if d == 15 then // Can only occur for ARM encoding 794 ALUWritePC(result); // setflags is always FALSE here 795 else 796 R[d] = result; 797 if setflags then 798 APSR.N = result<31>; 799 APSR.Z = IsZeroBit(result); 800 APSR.C = carry; 801 // APSR.V unchanged 802 } 803#endif 804 805 bool success = false; 806 const uint32_t opcode = OpcodeAsUnsigned (&success); 807 if (!success) 808 return false; 809 810 if (ConditionPassed()) 811 { 812 uint32_t Rm; // the source register 813 uint32_t Rd; // the destination register 814 ARM_ShifterType shift_t; 815 uint32_t shift_n; // the shift applied to the value read from Rm 816 bool setflags; 817 uint32_t carry; // the carry bit after the shift operation 818 switch (encoding) { 819 case eEncodingT1: 820 Rd = Bits32(opcode, 2, 0); 821 Rm = Bits32(opcode, 5, 3); 822 setflags = !InITBlock(); 823 shift_t = SRType_LSL; 824 shift_n = 0; 825 if (InITBlock()) 826 return false; 827 break; 828 case eEncodingT2: 829 Rd = Bits32(opcode, 11, 8); 830 Rm = Bits32(opcode, 3, 0); 831 setflags = BitIsSet(opcode, 20); 832 shift_n = DecodeImmShift(Bits32(opcode, 5, 4), Bits32(opcode, 14, 12)<<2 | Bits32(opcode, 7, 6), shift_t); 833 // if (BadReg(d) || BadReg(m)) then UNPREDICTABLE; 834 if ((BadReg(Rd) || BadReg(Rm))) 835 return false; 836 case eEncodingA1: 837 Rd = Bits32(opcode, 15, 12); 838 Rm = Bits32(opcode, 3, 0); 839 setflags = BitIsSet(opcode, 20); 840 shift_n = DecodeImmShift(Bits32(opcode, 6, 5), Bits32(opcode, 11, 7), shift_t); 841 break; 842 default: 843 return false; 844 } 845 uint32_t value = ReadCoreReg(Rm, &success); 846 if (!success) 847 return false; 848 849 uint32_t shifted = Shift_C(value, shift_t, shift_n, APSR_C, carry); 850 uint32_t result = ~shifted; 851 852 // The context specifies that an immediate is to be moved into Rd. 853 EmulateInstruction::Context context; 854 context.type = EmulateInstruction::eContextImmediate; 855 context.SetNoArgs (); 856 857 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry)) 858 return false; 859 } 860 return true; 861} 862 863// PC relative immediate load into register, possibly followed by ADD (SP plus register). 864// LDR (literal) 865bool 866EmulateInstructionARM::EmulateLDRRtPCRelative (ARMEncoding encoding) 867{ 868#if 0 869 // ARM pseudo code... 870 if (ConditionPassed()) 871 { 872 EncodingSpecificOperations(); NullCheckIfThumbEE(15); 873 base = Align(PC,4); 874 address = if add then (base + imm32) else (base - imm32); 875 data = MemU[address,4]; 876 if t == 15 then 877 if address<1:0> == ‘00’ then LoadWritePC(data); else UNPREDICTABLE; 878 elsif UnalignedSupport() || address<1:0> = ‘00’ then 879 R[t] = data; 880 else // Can only apply before ARMv7 881 if CurrentInstrSet() == InstrSet_ARM then 882 R[t] = ROR(data, 8*UInt(address<1:0>)); 883 else 884 R[t] = bits(32) UNKNOWN; 885 } 886#endif 887 888 bool success = false; 889 const uint32_t opcode = OpcodeAsUnsigned (&success); 890 if (!success) 891 return false; 892 893 if (ConditionPassed()) 894 { 895 const uint32_t pc = ReadCoreReg(PC_REG, &success); 896 if (!success) 897 return false; 898 899 // PC relative immediate load context 900 EmulateInstruction::Context context; 901 context.type = EmulateInstruction::eContextRegisterPlusOffset; 902 Register pc_reg; 903 pc_reg.SetRegister (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC); 904 context.SetRegisterPlusOffset (pc_reg, 0); 905 906 uint32_t Rt; // the destination register 907 uint32_t imm32; // immediate offset from the PC 908 bool add; // +imm32 or -imm32? 909 addr_t base; // the base address 910 addr_t address; // the PC relative address 911 uint32_t data; // the literal data value from the PC relative load 912 switch (encoding) { 913 case eEncodingT1: 914 Rt = Bits32(opcode, 10, 8); 915 imm32 = Bits32(opcode, 7, 0) << 2; // imm32 = ZeroExtend(imm8:'00', 32); 916 add = true; 917 break; 918 case eEncodingT2: 919 Rt = Bits32(opcode, 15, 12); 920 imm32 = Bits32(opcode, 11, 0) << 2; // imm32 = ZeroExtend(imm12, 32); 921 add = BitIsSet(opcode, 23); 922 if (Rt == 15 && InITBlock() && !LastInITBlock()) 923 return false; 924 break; 925 default: 926 return false; 927 } 928 929 base = Align(pc, 4); 930 if (add) 931 address = base + imm32; 932 else 933 address = base - imm32; 934 935 context.SetRegisterPlusOffset(pc_reg, address - base); 936 data = MemURead(context, address, 4, 0, &success); 937 if (!success) 938 return false; 939 940 if (Rt == 15) 941 { 942 if (Bits32(address, 1, 0) == 0) 943 { 944 // In ARMv5T and above, this is an interworking branch. 945 if (!LoadWritePC(context, data)) 946 return false; 947 } 948 else 949 return false; 950 } 951 else if (UnalignedSupport() || Bits32(address, 1, 0) == 0) 952 { 953 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + Rt, data)) 954 return false; 955 } 956 else // We don't handle ARM for now. 957 return false; 958 959 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + Rt, data)) 960 return false; 961 } 962 return true; 963} 964 965// An add operation to adjust the SP. 966// ADD (SP plus immediate) 967bool 968EmulateInstructionARM::EmulateADDSPImm (ARMEncoding encoding) 969{ 970#if 0 971 // ARM pseudo code... 972 if (ConditionPassed()) 973 { 974 EncodingSpecificOperations(); 975 (result, carry, overflow) = AddWithCarry(SP, imm32, ‘0’); 976 if d == 15 then // Can only occur for ARM encoding 977 ALUWritePC(result); // setflags is always FALSE here 978 else 979 R[d] = result; 980 if setflags then 981 APSR.N = result<31>; 982 APSR.Z = IsZeroBit(result); 983 APSR.C = carry; 984 APSR.V = overflow; 985 } 986#endif 987 988 bool success = false; 989 const uint32_t opcode = OpcodeAsUnsigned (&success); 990 if (!success) 991 return false; 992 993 if (ConditionPassed()) 994 { 995 const addr_t sp = ReadCoreReg (SP_REG, &success); 996 if (!success) 997 return false; 998 uint32_t imm32; // the immediate operand 999 switch (encoding) { 1000 case eEncodingT2: 1001 imm32 = ThumbImmScaled(opcode); // imm32 = ZeroExtend(imm7:'00', 32) 1002 break; 1003 default: 1004 return false; 1005 } 1006 addr_t sp_offset = imm32; 1007 addr_t addr = sp + sp_offset; // the adjusted stack pointer value 1008 1009 EmulateInstruction::Context context; 1010 context.type = EmulateInstruction::eContextAdjustStackPointer; 1011 context.SetImmediateSigned (sp_offset); 1012 1013 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, addr)) 1014 return false; 1015 } 1016 return true; 1017} 1018 1019// An add operation to adjust the SP. 1020// ADD (SP plus register) 1021bool 1022EmulateInstructionARM::EmulateADDSPRm (ARMEncoding encoding) 1023{ 1024#if 0 1025 // ARM pseudo code... 1026 if (ConditionPassed()) 1027 { 1028 EncodingSpecificOperations(); 1029 shifted = Shift(R[m], shift_t, shift_n, APSR.C); 1030 (result, carry, overflow) = AddWithCarry(SP, shifted, ‘0’); 1031 if d == 15 then 1032 ALUWritePC(result); // setflags is always FALSE here 1033 else 1034 R[d] = result; 1035 if setflags then 1036 APSR.N = result<31>; 1037 APSR.Z = IsZeroBit(result); 1038 APSR.C = carry; 1039 APSR.V = overflow; 1040 } 1041#endif 1042 1043 bool success = false; 1044 const uint32_t opcode = OpcodeAsUnsigned (&success); 1045 if (!success) 1046 return false; 1047 1048 if (ConditionPassed()) 1049 { 1050 const addr_t sp = ReadCoreReg (SP_REG, &success); 1051 if (!success) 1052 return false; 1053 uint32_t Rm; // the second operand 1054 switch (encoding) { 1055 case eEncodingT2: 1056 Rm = Bits32(opcode, 6, 3); 1057 break; 1058 default: 1059 return false; 1060 } 1061 int32_t reg_value = ReadCoreReg(Rm, &success); 1062 if (!success) 1063 return false; 1064 1065 addr_t addr = (int32_t)sp + reg_value; // the adjusted stack pointer value 1066 1067 EmulateInstruction::Context context; 1068 context.type = EmulateInstruction::eContextAdjustStackPointer; 1069 context.SetImmediateSigned (reg_value); 1070 1071 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, addr)) 1072 return false; 1073 } 1074 return true; 1075} 1076 1077// Branch with Link and Exchange Instruction Sets (immediate) calls a subroutine 1078// at a PC-relative address, and changes instruction set from ARM to Thumb, or 1079// from Thumb to ARM. 1080// BLX (immediate) 1081bool 1082EmulateInstructionARM::EmulateBLXImmediate (ARMEncoding encoding) 1083{ 1084#if 0 1085 // ARM pseudo code... 1086 if (ConditionPassed()) 1087 { 1088 EncodingSpecificOperations(); 1089 if CurrentInstrSet() == InstrSet_ARM then 1090 LR = PC - 4; 1091 else 1092 LR = PC<31:1> : '1'; 1093 if targetInstrSet == InstrSet_ARM then 1094 targetAddress = Align(PC,4) + imm32; 1095 else 1096 targetAddress = PC + imm32; 1097 SelectInstrSet(targetInstrSet); 1098 BranchWritePC(targetAddress); 1099 } 1100#endif 1101 1102 bool success = false; 1103 const uint32_t opcode = OpcodeAsUnsigned (&success); 1104 if (!success) 1105 return false; 1106 1107 if (ConditionPassed()) 1108 { 1109 EmulateInstruction::Context context; 1110 context.type = EmulateInstruction::eContextRelativeBranchImmediate; 1111 const uint32_t pc = ReadCoreReg(PC_REG, &success); 1112 if (!success) 1113 return false; 1114 addr_t lr; // next instruction address 1115 addr_t target; // target address 1116 int32_t imm32; // PC-relative offset 1117 switch (encoding) { 1118 case eEncodingT1: 1119 { 1120 lr = pc | 1u; // return address 1121 uint32_t S = Bit32(opcode, 26); 1122 uint32_t imm10 = Bits32(opcode, 25, 16); 1123 uint32_t J1 = Bit32(opcode, 13); 1124 uint32_t J2 = Bit32(opcode, 11); 1125 uint32_t imm11 = Bits32(opcode, 10, 0); 1126 uint32_t I1 = !(J1 ^ S); 1127 uint32_t I2 = !(J2 ^ S); 1128 uint32_t imm25 = (S << 24) | (I1 << 23) | (I2 << 22) | (imm10 << 12) | (imm11 << 1); 1129 imm32 = llvm::SignExtend32<25>(imm25); 1130 target = pc + imm32; 1131 context.SetModeAndImmediateSigned (eModeThumb, 4 + imm32); 1132 if (InITBlock() && !LastInITBlock()) 1133 return false; 1134 break; 1135 } 1136 case eEncodingT2: 1137 { 1138 lr = pc | 1u; // return address 1139 uint32_t S = Bit32(opcode, 26); 1140 uint32_t imm10H = Bits32(opcode, 25, 16); 1141 uint32_t J1 = Bit32(opcode, 13); 1142 uint32_t J2 = Bit32(opcode, 11); 1143 uint32_t imm10L = Bits32(opcode, 10, 1); 1144 uint32_t I1 = !(J1 ^ S); 1145 uint32_t I2 = !(J2 ^ S); 1146 uint32_t imm25 = (S << 24) | (I1 << 23) | (I2 << 22) | (imm10H << 12) | (imm10L << 2); 1147 imm32 = llvm::SignExtend32<25>(imm25); 1148 target = Align(pc, 4) + imm32; 1149 context.SetModeAndImmediateSigned (eModeARM, 4 + imm32); 1150 if (InITBlock() && !LastInITBlock()) 1151 return false; 1152 break; 1153 } 1154 case eEncodingA1: 1155 lr = pc + 4; // return address 1156 imm32 = llvm::SignExtend32<26>(Bits32(opcode, 23, 0) << 2); 1157 target = Align(pc, 4) + imm32; 1158 context.SetModeAndImmediateSigned (eModeARM, 8 + imm32); 1159 break; 1160 case eEncodingA2: 1161 lr = pc + 4; // return address 1162 imm32 = llvm::SignExtend32<26>(Bits32(opcode, 23, 0) << 2 | Bits32(opcode, 24, 24) << 1); 1163 target = pc + imm32; 1164 context.SetModeAndImmediateSigned (eModeThumb, 8 + imm32); 1165 break; 1166 default: 1167 return false; 1168 } 1169 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_RA, lr)) 1170 return false; 1171 if (!BranchWritePC(context, target)) 1172 return false; 1173 } 1174 return true; 1175} 1176 1177// Branch with Link and Exchange (register) calls a subroutine at an address and 1178// instruction set specified by a register. 1179// BLX (register) 1180bool 1181EmulateInstructionARM::EmulateBLXRm (ARMEncoding encoding) 1182{ 1183#if 0 1184 // ARM pseudo code... 1185 if (ConditionPassed()) 1186 { 1187 EncodingSpecificOperations(); 1188 target = R[m]; 1189 if CurrentInstrSet() == InstrSet_ARM then 1190 next_instr_addr = PC - 4; 1191 LR = next_instr_addr; 1192 else 1193 next_instr_addr = PC - 2; 1194 LR = next_instr_addr<31:1> : ‘1’; 1195 BXWritePC(target); 1196 } 1197#endif 1198 1199 bool success = false; 1200 const uint32_t opcode = OpcodeAsUnsigned (&success); 1201 if (!success) 1202 return false; 1203 1204 if (ConditionPassed()) 1205 { 1206 EmulateInstruction::Context context; 1207 context.type = EmulateInstruction::eContextAbsoluteBranchRegister; 1208 const uint32_t pc = ReadCoreReg(PC_REG, &success); 1209 addr_t lr; // next instruction address 1210 if (!success) 1211 return false; 1212 uint32_t Rm; // the register with the target address 1213 switch (encoding) { 1214 case eEncodingT1: 1215 lr = (pc - 2) | 1u; // return address 1216 Rm = Bits32(opcode, 6, 3); 1217 // if m == 15 then UNPREDICTABLE; 1218 if (Rm == 15) 1219 return false; 1220 if (InITBlock() && !LastInITBlock()) 1221 return false; 1222 break; 1223 case eEncodingA1: 1224 lr = pc - 4; // return address 1225 Rm = Bits32(opcode, 3, 0); 1226 // if m == 15 then UNPREDICTABLE; 1227 if (Rm == 15) 1228 return false; 1229 break; 1230 default: 1231 return false; 1232 } 1233 addr_t target = ReadCoreReg (Rm, &success); 1234 if (!success) 1235 return false; 1236 Register dwarf_reg; 1237 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + Rm); 1238 context.SetRegister (dwarf_reg); 1239 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_RA, lr)) 1240 return false; 1241 if (!BXWritePC(context, target)) 1242 return false; 1243 } 1244 return true; 1245} 1246 1247// Branch and Exchange causes a branch to an address and instruction set specified by a register. 1248// BX 1249bool 1250EmulateInstructionARM::EmulateBXRm (ARMEncoding encoding) 1251{ 1252#if 0 1253 // ARM pseudo code... 1254 if (ConditionPassed()) 1255 { 1256 EncodingSpecificOperations(); 1257 BXWritePC(R[m]); 1258 } 1259#endif 1260 1261 bool success = false; 1262 const uint32_t opcode = OpcodeAsUnsigned (&success); 1263 if (!success) 1264 return false; 1265 1266 if (ConditionPassed()) 1267 { 1268 EmulateInstruction::Context context; 1269 context.type = EmulateInstruction::eContextAbsoluteBranchRegister; 1270 uint32_t Rm; // the register with the target address 1271 switch (encoding) { 1272 case eEncodingT1: 1273 Rm = Bits32(opcode, 6, 3); 1274 if (InITBlock() && !LastInITBlock()) 1275 return false; 1276 break; 1277 case eEncodingA1: 1278 Rm = Bits32(opcode, 3, 0); 1279 break; 1280 default: 1281 return false; 1282 } 1283 addr_t target = ReadCoreReg (Rm, &success); 1284 if (!success) 1285 return false; 1286 1287 Register dwarf_reg; 1288 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + Rm); 1289 context.SetRegister (dwarf_reg); 1290 if (!BXWritePC(context, target)) 1291 return false; 1292 } 1293 return true; 1294} 1295 1296// Set r7 to point to some ip offset. 1297// SUB (immediate) 1298bool 1299EmulateInstructionARM::EmulateSUBR7IPImm (ARMEncoding encoding) 1300{ 1301#if 0 1302 // ARM pseudo code... 1303 if (ConditionPassed()) 1304 { 1305 EncodingSpecificOperations(); 1306 (result, carry, overflow) = AddWithCarry(SP, NOT(imm32), ‘1’); 1307 if d == 15 then // Can only occur for ARM encoding 1308 ALUWritePC(result); // setflags is always FALSE here 1309 else 1310 R[d] = result; 1311 if setflags then 1312 APSR.N = result<31>; 1313 APSR.Z = IsZeroBit(result); 1314 APSR.C = carry; 1315 APSR.V = overflow; 1316 } 1317#endif 1318 1319 bool success = false; 1320 const uint32_t opcode = OpcodeAsUnsigned (&success); 1321 if (!success) 1322 return false; 1323 1324 if (ConditionPassed()) 1325 { 1326 const addr_t ip = ReadCoreReg (12, &success); 1327 if (!success) 1328 return false; 1329 uint32_t imm32; 1330 switch (encoding) { 1331 case eEncodingA1: 1332 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12) 1333 break; 1334 default: 1335 return false; 1336 } 1337 addr_t ip_offset = imm32; 1338 addr_t addr = ip - ip_offset; // the adjusted ip value 1339 1340 EmulateInstruction::Context context; 1341 context.type = EmulateInstruction::eContextRegisterPlusOffset; 1342 Register dwarf_reg; 1343 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r12); 1344 context.SetRegisterPlusOffset (dwarf_reg, -ip_offset); 1345 1346 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r7, addr)) 1347 return false; 1348 } 1349 return true; 1350} 1351 1352// Set ip to point to some stack offset. 1353// SUB (SP minus immediate) 1354bool 1355EmulateInstructionARM::EmulateSUBIPSPImm (ARMEncoding encoding) 1356{ 1357#if 0 1358 // ARM pseudo code... 1359 if (ConditionPassed()) 1360 { 1361 EncodingSpecificOperations(); 1362 (result, carry, overflow) = AddWithCarry(SP, NOT(imm32), ‘1’); 1363 if d == 15 then // Can only occur for ARM encoding 1364 ALUWritePC(result); // setflags is always FALSE here 1365 else 1366 R[d] = result; 1367 if setflags then 1368 APSR.N = result<31>; 1369 APSR.Z = IsZeroBit(result); 1370 APSR.C = carry; 1371 APSR.V = overflow; 1372 } 1373#endif 1374 1375 bool success = false; 1376 const uint32_t opcode = OpcodeAsUnsigned (&success); 1377 if (!success) 1378 return false; 1379 1380 if (ConditionPassed()) 1381 { 1382 const addr_t sp = ReadCoreReg (SP_REG, &success); 1383 if (!success) 1384 return false; 1385 uint32_t imm32; 1386 switch (encoding) { 1387 case eEncodingA1: 1388 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12) 1389 break; 1390 default: 1391 return false; 1392 } 1393 addr_t sp_offset = imm32; 1394 addr_t addr = sp - sp_offset; // the adjusted stack pointer value 1395 1396 EmulateInstruction::Context context; 1397 context.type = EmulateInstruction::eContextRegisterPlusOffset; 1398 Register dwarf_reg; 1399 dwarf_reg.SetRegister (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP); 1400 context.SetRegisterPlusOffset (dwarf_reg, -sp_offset); 1401 1402 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r12, addr)) 1403 return false; 1404 } 1405 return true; 1406} 1407 1408// A sub operation to adjust the SP -- allocate space for local storage. 1409bool 1410EmulateInstructionARM::EmulateSUBSPImm (ARMEncoding encoding) 1411{ 1412#if 0 1413 // ARM pseudo code... 1414 if (ConditionPassed()) 1415 { 1416 EncodingSpecificOperations(); 1417 (result, carry, overflow) = AddWithCarry(SP, NOT(imm32), ‘1’); 1418 if d == 15 then // Can only occur for ARM encoding 1419 ALUWritePC(result); // setflags is always FALSE here 1420 else 1421 R[d] = result; 1422 if setflags then 1423 APSR.N = result<31>; 1424 APSR.Z = IsZeroBit(result); 1425 APSR.C = carry; 1426 APSR.V = overflow; 1427 } 1428#endif 1429 1430 bool success = false; 1431 const uint32_t opcode = OpcodeAsUnsigned (&success); 1432 if (!success) 1433 return false; 1434 1435 if (ConditionPassed()) 1436 { 1437 const addr_t sp = ReadCoreReg (SP_REG, &success); 1438 if (!success) 1439 return false; 1440 uint32_t imm32; 1441 switch (encoding) { 1442 case eEncodingT1: 1443 imm32 = ThumbImmScaled(opcode); // imm32 = ZeroExtend(imm7:'00', 32) 1444 case eEncodingT2: 1445 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8) 1446 break; 1447 case eEncodingT3: 1448 imm32 = ThumbImm12(opcode); // imm32 = ZeroExtend(i:imm3:imm8, 32) 1449 break; 1450 case eEncodingA1: 1451 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12) 1452 break; 1453 default: 1454 return false; 1455 } 1456 addr_t sp_offset = imm32; 1457 addr_t addr = sp - sp_offset; // the adjusted stack pointer value 1458 1459 EmulateInstruction::Context context; 1460 context.type = EmulateInstruction::eContextAdjustStackPointer; 1461 context.SetImmediateSigned (-sp_offset); 1462 1463 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, addr)) 1464 return false; 1465 } 1466 return true; 1467} 1468 1469// A store operation to the stack that also updates the SP. 1470bool 1471EmulateInstructionARM::EmulateSTRRtSP (ARMEncoding encoding) 1472{ 1473#if 0 1474 // ARM pseudo code... 1475 if (ConditionPassed()) 1476 { 1477 EncodingSpecificOperations(); 1478 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32); 1479 address = if index then offset_addr else R[n]; 1480 MemU[address,4] = if t == 15 then PCStoreValue() else R[t]; 1481 if wback then R[n] = offset_addr; 1482 } 1483#endif 1484 1485 bool success = false; 1486 const uint32_t opcode = OpcodeAsUnsigned (&success); 1487 if (!success) 1488 return false; 1489 1490 if (ConditionPassed()) 1491 { 1492 const uint32_t addr_byte_size = GetAddressByteSize(); 1493 const addr_t sp = ReadCoreReg (SP_REG, &success); 1494 if (!success) 1495 return false; 1496 uint32_t Rt; // the source register 1497 uint32_t imm12; 1498 switch (encoding) { 1499 case eEncodingA1: 1500 Rt = Bits32(opcode, 15, 12); 1501 imm12 = Bits32(opcode, 11, 0); 1502 break; 1503 default: 1504 return false; 1505 } 1506 addr_t sp_offset = imm12; 1507 addr_t addr = sp - sp_offset; 1508 1509 EmulateInstruction::Context context; 1510 context.type = EmulateInstruction::eContextPushRegisterOnStack; 1511 Register dwarf_reg; 1512 dwarf_reg.SetRegister (eRegisterKindDWARF, 0); 1513 if (Rt != 15) 1514 { 1515 dwarf_reg.num = dwarf_r0 + Rt; 1516 context.SetRegisterPlusOffset (dwarf_reg, addr - sp); 1517 uint32_t reg_value = ReadCoreReg(Rt, &success); 1518 if (!success) 1519 return false; 1520 if (!MemUWrite (context, addr, reg_value, addr_byte_size)) 1521 return false; 1522 } 1523 else 1524 { 1525 dwarf_reg.num = dwarf_pc; 1526 context.SetRegisterPlusOffset (dwarf_reg, addr - sp); 1527 const uint32_t pc = ReadCoreReg(PC_REG, &success); 1528 if (!success) 1529 return false; 1530 if (!MemUWrite (context, addr, pc + 8, addr_byte_size)) 1531 return false; 1532 } 1533 1534 context.type = EmulateInstruction::eContextAdjustStackPointer; 1535 context.SetImmediateSigned (-sp_offset); 1536 1537 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, sp - sp_offset)) 1538 return false; 1539 } 1540 return true; 1541} 1542 1543// Vector Push stores multiple extension registers to the stack. 1544// It also updates SP to point to the start of the stored data. 1545bool 1546EmulateInstructionARM::EmulateVPUSH (ARMEncoding encoding) 1547{ 1548#if 0 1549 // ARM pseudo code... 1550 if (ConditionPassed()) 1551 { 1552 EncodingSpecificOperations(); CheckVFPEnabled(TRUE); NullCheckIfThumbEE(13); 1553 address = SP - imm32; 1554 SP = SP - imm32; 1555 if single_regs then 1556 for r = 0 to regs-1 1557 MemA[address,4] = S[d+r]; address = address+4; 1558 else 1559 for r = 0 to regs-1 1560 // Store as two word-aligned words in the correct order for current endianness. 1561 MemA[address,4] = if BigEndian() then D[d+r]<63:32> else D[d+r]<31:0>; 1562 MemA[address+4,4] = if BigEndian() then D[d+r]<31:0> else D[d+r]<63:32>; 1563 address = address+8; 1564 } 1565#endif 1566 1567 bool success = false; 1568 const uint32_t opcode = OpcodeAsUnsigned (&success); 1569 if (!success) 1570 return false; 1571 1572 if (ConditionPassed()) 1573 { 1574 const uint32_t addr_byte_size = GetAddressByteSize(); 1575 const addr_t sp = ReadCoreReg (SP_REG, &success); 1576 if (!success) 1577 return false; 1578 bool single_regs; 1579 uint32_t d; // UInt(D:Vd) or UInt(Vd:D) starting register 1580 uint32_t imm32; // stack offset 1581 uint32_t regs; // number of registers 1582 switch (encoding) { 1583 case eEncodingT1: 1584 case eEncodingA1: 1585 single_regs = false; 1586 d = Bit32(opcode, 22) << 4 | Bits32(opcode, 15, 12); 1587 imm32 = Bits32(opcode, 7, 0) * addr_byte_size; 1588 // If UInt(imm8) is odd, see "FSTMX". 1589 regs = Bits32(opcode, 7, 0) / 2; 1590 // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE; 1591 if (regs == 0 || regs > 16 || (d + regs) > 32) 1592 return false; 1593 break; 1594 case eEncodingT2: 1595 case eEncodingA2: 1596 single_regs = true; 1597 d = Bits32(opcode, 15, 12) << 1 | Bit32(opcode, 22); 1598 imm32 = Bits32(opcode, 7, 0) * addr_byte_size; 1599 regs = Bits32(opcode, 7, 0); 1600 // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE; 1601 if (regs == 0 || regs > 16 || (d + regs) > 32) 1602 return false; 1603 break; 1604 default: 1605 return false; 1606 } 1607 uint32_t start_reg = single_regs ? dwarf_s0 : dwarf_d0; 1608 uint32_t reg_byte_size = single_regs ? addr_byte_size : addr_byte_size * 2; 1609 addr_t sp_offset = imm32; 1610 addr_t addr = sp - sp_offset; 1611 uint32_t i; 1612 1613 EmulateInstruction::Context context; 1614 context.type = EmulateInstruction::eContextPushRegisterOnStack; 1615 Register dwarf_reg; 1616 dwarf_reg.SetRegister (eRegisterKindDWARF, 0); 1617 for (i=d; i<regs; ++i) 1618 { 1619 dwarf_reg.num = start_reg + i; 1620 context.SetRegisterPlusOffset ( dwarf_reg, addr - sp); 1621 // uint64_t to accommodate 64-bit registers. 1622 uint64_t reg_value = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_reg.num, 0, &success); 1623 if (!success) 1624 return false; 1625 if (!MemAWrite (context, addr, reg_value, reg_byte_size)) 1626 return false; 1627 addr += reg_byte_size; 1628 } 1629 1630 context.type = EmulateInstruction::eContextAdjustStackPointer; 1631 context.SetImmediateSigned (-sp_offset); 1632 1633 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, sp - sp_offset)) 1634 return false; 1635 } 1636 return true; 1637} 1638 1639// Vector Pop loads multiple extension registers from the stack. 1640// It also updates SP to point just above the loaded data. 1641bool 1642EmulateInstructionARM::EmulateVPOP (ARMEncoding encoding) 1643{ 1644#if 0 1645 // ARM pseudo code... 1646 if (ConditionPassed()) 1647 { 1648 EncodingSpecificOperations(); CheckVFPEnabled(TRUE); NullCheckIfThumbEE(13); 1649 address = SP; 1650 SP = SP + imm32; 1651 if single_regs then 1652 for r = 0 to regs-1 1653 S[d+r] = MemA[address,4]; address = address+4; 1654 else 1655 for r = 0 to regs-1 1656 word1 = MemA[address,4]; word2 = MemA[address+4,4]; address = address+8; 1657 // Combine the word-aligned words in the correct order for current endianness. 1658 D[d+r] = if BigEndian() then word1:word2 else word2:word1; 1659 } 1660#endif 1661 1662 bool success = false; 1663 const uint32_t opcode = OpcodeAsUnsigned (&success); 1664 if (!success) 1665 return false; 1666 1667 if (ConditionPassed()) 1668 { 1669 const uint32_t addr_byte_size = GetAddressByteSize(); 1670 const addr_t sp = ReadCoreReg (SP_REG, &success); 1671 if (!success) 1672 return false; 1673 bool single_regs; 1674 uint32_t d; // UInt(D:Vd) or UInt(Vd:D) starting register 1675 uint32_t imm32; // stack offset 1676 uint32_t regs; // number of registers 1677 switch (encoding) { 1678 case eEncodingT1: 1679 case eEncodingA1: 1680 single_regs = false; 1681 d = Bit32(opcode, 22) << 4 | Bits32(opcode, 15, 12); 1682 imm32 = Bits32(opcode, 7, 0) * addr_byte_size; 1683 // If UInt(imm8) is odd, see "FLDMX". 1684 regs = Bits32(opcode, 7, 0) / 2; 1685 // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE; 1686 if (regs == 0 || regs > 16 || (d + regs) > 32) 1687 return false; 1688 break; 1689 case eEncodingT2: 1690 case eEncodingA2: 1691 single_regs = true; 1692 d = Bits32(opcode, 15, 12) << 1 | Bit32(opcode, 22); 1693 imm32 = Bits32(opcode, 7, 0) * addr_byte_size; 1694 regs = Bits32(opcode, 7, 0); 1695 // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE; 1696 if (regs == 0 || regs > 16 || (d + regs) > 32) 1697 return false; 1698 break; 1699 default: 1700 return false; 1701 } 1702 uint32_t start_reg = single_regs ? dwarf_s0 : dwarf_d0; 1703 uint32_t reg_byte_size = single_regs ? addr_byte_size : addr_byte_size * 2; 1704 addr_t sp_offset = imm32; 1705 addr_t addr = sp; 1706 uint32_t i; 1707 uint64_t data; // uint64_t to accomodate 64-bit registers. 1708 1709 EmulateInstruction::Context context; 1710 context.type = EmulateInstruction::eContextPopRegisterOffStack; 1711 Register dwarf_reg; 1712 dwarf_reg.SetRegister (eRegisterKindDWARF, 0); 1713 for (i=d; i<regs; ++i) 1714 { 1715 dwarf_reg.num = start_reg + i; 1716 context.SetRegisterPlusOffset (dwarf_reg, addr - sp); 1717 data = MemARead(context, addr, reg_byte_size, 0, &success); 1718 if (!success) 1719 return false; 1720 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_reg.num, data)) 1721 return false; 1722 addr += reg_byte_size; 1723 } 1724 1725 context.type = EmulateInstruction::eContextAdjustStackPointer; 1726 context.SetImmediateSigned (sp_offset); 1727 1728 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, sp + sp_offset)) 1729 return false; 1730 } 1731 return true; 1732} 1733 1734// SVC (previously SWI) 1735bool 1736EmulateInstructionARM::EmulateSVC (ARMEncoding encoding) 1737{ 1738#if 0 1739 // ARM pseudo code... 1740 if (ConditionPassed()) 1741 { 1742 EncodingSpecificOperations(); 1743 CallSupervisor(); 1744 } 1745#endif 1746 1747 bool success = false; 1748 const uint32_t opcode = OpcodeAsUnsigned (&success); 1749 if (!success) 1750 return false; 1751 1752 if (ConditionPassed()) 1753 { 1754 const uint32_t pc = ReadCoreReg(PC_REG, &success); 1755 addr_t lr; // next instruction address 1756 if (!success) 1757 return false; 1758 uint32_t imm32; // the immediate constant 1759 uint32_t mode; // ARM or Thumb mode 1760 switch (encoding) { 1761 case eEncodingT1: 1762 lr = (pc + 2) | 1u; // return address 1763 imm32 = Bits32(opcode, 7, 0); 1764 mode = eModeThumb; 1765 break; 1766 case eEncodingA1: 1767 lr = pc + 4; // return address 1768 imm32 = Bits32(opcode, 23, 0); 1769 mode = eModeARM; 1770 break; 1771 default: 1772 return false; 1773 } 1774 1775 EmulateInstruction::Context context; 1776 context.type = EmulateInstruction::eContextSupervisorCall; 1777 context.SetModeAndImmediate (mode, imm32); 1778 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_RA, lr)) 1779 return false; 1780 } 1781 return true; 1782} 1783 1784// If Then makes up to four following instructions (the IT block) conditional. 1785bool 1786EmulateInstructionARM::EmulateIT (ARMEncoding encoding) 1787{ 1788#if 0 1789 // ARM pseudo code... 1790 EncodingSpecificOperations(); 1791 ITSTATE.IT<7:0> = firstcond:mask; 1792#endif 1793 1794 bool success = false; 1795 const uint32_t opcode = OpcodeAsUnsigned (&success); 1796 if (!success) 1797 return false; 1798 1799 m_it_session.InitIT(Bits32(opcode, 7, 0)); 1800 return true; 1801} 1802 1803// Branch causes a branch to a target address. 1804bool 1805EmulateInstructionARM::EmulateB (ARMEncoding encoding) 1806{ 1807#if 0 1808 // ARM pseudo code... 1809 if (ConditionPassed()) 1810 { 1811 EncodingSpecificOperations(); 1812 BranchWritePC(PC + imm32); 1813 } 1814#endif 1815 1816 bool success = false; 1817 const uint32_t opcode = OpcodeAsUnsigned (&success); 1818 if (!success) 1819 return false; 1820 1821 if (ConditionPassed()) 1822 { 1823 EmulateInstruction::Context context; 1824 context.type = EmulateInstruction::eContextRelativeBranchImmediate; 1825 const uint32_t pc = ReadCoreReg(PC_REG, &success); 1826 if (!success) 1827 return false; 1828 addr_t target; // target address 1829 int32_t imm32; // PC-relative offset 1830 switch (encoding) { 1831 case eEncodingT1: 1832 // The 'cond' field is handled in EmulateInstructionARM::CurrentCond(). 1833 imm32 = llvm::SignExtend32<9>(Bits32(opcode, 7, 0) << 1); 1834 target = pc + imm32; 1835 context.SetModeAndImmediateSigned (eModeThumb, 4 + imm32); 1836 break; 1837 case eEncodingT2: 1838 imm32 = llvm::SignExtend32<12>(Bits32(opcode, 10, 0)); 1839 target = pc + imm32; 1840 context.SetModeAndImmediateSigned (eModeThumb, 4 + imm32); 1841 break; 1842 case eEncodingT3: 1843 // The 'cond' field is handled in EmulateInstructionARM::CurrentCond(). 1844 { 1845 uint32_t S = Bit32(opcode, 26); 1846 uint32_t imm6 = Bits32(opcode, 21, 16); 1847 uint32_t J1 = Bit32(opcode, 13); 1848 uint32_t J2 = Bit32(opcode, 11); 1849 uint32_t imm11 = Bits32(opcode, 10, 0); 1850 uint32_t imm21 = (S << 20) | (J2 << 19) | (J1 << 18) | (imm6 << 12) | (imm11 << 1); 1851 imm32 = llvm::SignExtend32<21>(imm21); 1852 target = pc + imm32; 1853 context.SetModeAndImmediateSigned (eModeThumb, 4 + imm32); 1854 break; 1855 } 1856 case eEncodingT4: 1857 { 1858 uint32_t S = Bit32(opcode, 26); 1859 uint32_t imm10 = Bits32(opcode, 25, 16); 1860 uint32_t J1 = Bit32(opcode, 13); 1861 uint32_t J2 = Bit32(opcode, 11); 1862 uint32_t imm11 = Bits32(opcode, 10, 0); 1863 uint32_t I1 = !(J1 ^ S); 1864 uint32_t I2 = !(J2 ^ S); 1865 uint32_t imm25 = (S << 24) | (I1 << 23) | (I2 << 22) | (imm10 << 12) | (imm11 << 1); 1866 imm32 = llvm::SignExtend32<25>(imm25); 1867 target = pc + imm32; 1868 context.SetModeAndImmediateSigned (eModeThumb, 4 + imm32); 1869 break; 1870 } 1871 case eEncodingA1: 1872 imm32 = llvm::SignExtend32<26>(Bits32(opcode, 23, 0) << 2); 1873 target = pc + imm32; 1874 context.SetModeAndImmediateSigned (eModeARM, 8 + imm32); 1875 break; 1876 default: 1877 return false; 1878 } 1879 if (!BranchWritePC(context, target)) 1880 return false; 1881 } 1882 return true; 1883} 1884 1885// Compare and Branch on Nonzero and Compare and Branch on Zero compare the value in a register with 1886// zero and conditionally branch forward a constant value. They do not affect the condition flags. 1887// CBNZ, CBZ 1888bool 1889EmulateInstructionARM::EmulateCB (ARMEncoding encoding) 1890{ 1891#if 0 1892 // ARM pseudo code... 1893 EncodingSpecificOperations(); 1894 if nonzero ^ IsZero(R[n]) then 1895 BranchWritePC(PC + imm32); 1896#endif 1897 1898 bool success = false; 1899 const uint32_t opcode = OpcodeAsUnsigned (&success); 1900 if (!success) 1901 return false; 1902 1903 // Read the register value from the operand register Rn. 1904 uint32_t reg_val = ReadCoreReg(Bits32(opcode, 2, 0), &success); 1905 if (!success) 1906 return false; 1907 1908 EmulateInstruction::Context context; 1909 context.type = EmulateInstruction::eContextRelativeBranchImmediate; 1910 const uint32_t pc = ReadCoreReg(PC_REG, &success); 1911 if (!success) 1912 return false; 1913 1914 addr_t target; // target address 1915 uint32_t imm32; // PC-relative offset to branch forward 1916 bool nonzero; 1917 switch (encoding) { 1918 case eEncodingT1: 1919 imm32 = Bit32(opcode, 9) << 6 | Bits32(opcode, 7, 3) << 1; 1920 nonzero = BitIsSet(opcode, 11); 1921 target = pc + imm32; 1922 context.SetModeAndImmediateSigned (eModeThumb, 4 + imm32); 1923 break; 1924 default: 1925 return false; 1926 } 1927 if (nonzero ^ (reg_val == 0)) 1928 if (!BranchWritePC(context, target)) 1929 return false; 1930 1931 return true; 1932} 1933 1934// Table Branch Byte causes a PC-relative forward branch using a table of single byte offsets. 1935// A base register provides a pointer to the table, and a second register supplies an index into the table. 1936// The branch length is twice the value of the byte returned from the table. 1937// 1938// Table Branch Halfword causes a PC-relative forward branch using a table of single halfword offsets. 1939// A base register provides a pointer to the table, and a second register supplies an index into the table. 1940// The branch length is twice the value of the halfword returned from the table. 1941// TBB, TBH 1942bool 1943EmulateInstructionARM::EmulateTB (ARMEncoding encoding) 1944{ 1945#if 0 1946 // ARM pseudo code... 1947 EncodingSpecificOperations(); NullCheckIfThumbEE(n); 1948 if is_tbh then 1949 halfwords = UInt(MemU[R[n]+LSL(R[m],1), 2]); 1950 else 1951 halfwords = UInt(MemU[R[n]+R[m], 1]); 1952 BranchWritePC(PC + 2*halfwords); 1953#endif 1954 1955 bool success = false; 1956 const uint32_t opcode = OpcodeAsUnsigned (&success); 1957 if (!success) 1958 return false; 1959 1960 uint32_t Rn; // the base register which contains the address of the table of branch lengths 1961 uint32_t Rm; // the index register which contains an integer pointing to a byte/halfword in the table 1962 bool is_tbh; // true if table branch halfword 1963 switch (encoding) { 1964 case eEncodingT1: 1965 Rn = Bits32(opcode, 19, 16); 1966 Rm = Bits32(opcode, 3, 0); 1967 is_tbh = BitIsSet(opcode, 4); 1968 if (Rn == 13 || BadReg(Rm)) 1969 return false; 1970 if (InITBlock() && !LastInITBlock()) 1971 return false; 1972 break; 1973 default: 1974 return false; 1975 } 1976 1977 // Read the address of the table from the operand register Rn. 1978 // The PC can be used, in which case the table immediately follows this instruction. 1979 uint32_t base = ReadCoreReg(Rm, &success); 1980 if (!success) 1981 return false; 1982 1983 // the table index 1984 uint32_t index = ReadCoreReg(Rm, &success); 1985 if (!success) 1986 return false; 1987 1988 // the offsetted table address 1989 addr_t addr = base + (is_tbh ? index*2 : index); 1990 1991 // PC-relative offset to branch forward 1992 EmulateInstruction::Context context; 1993 context.type = EmulateInstruction::eContextTableBranchReadMemory; 1994 uint32_t offset = MemURead(context, addr, is_tbh ? 2 : 1, 0, &success) * 2; 1995 if (!success) 1996 return false; 1997 1998 const uint32_t pc = ReadCoreReg(PC_REG, &success); 1999 if (!success) 2000 return false; 2001 2002 // target address 2003 addr_t target = pc + offset; 2004 context.type = EmulateInstruction::eContextRelativeBranchImmediate; 2005 context.SetModeAndImmediateSigned (eModeThumb, 4 + offset); 2006 2007 if (!BranchWritePC(context, target)) 2008 return false; 2009 2010 return true; 2011} 2012 2013// This instruction adds an immediate value to a register value, and writes the result to the destination 2014// register. It can optionally update the condition flags based on the result. 2015bool 2016EmulateInstructionARM::EmulateADDImmARM (ARMEncoding encoding) 2017{ 2018#if 0 2019 // ARM pseudo code... 2020 if ConditionPassed() then 2021 EncodingSpecificOperations(); 2022 (result, carry, overflow) = AddWithCarry(R[n], imm32, '0'); 2023 if d == 15 then 2024 ALUWritePC(result); // setflags is always FALSE here 2025 else 2026 R[d] = result; 2027 if setflags then 2028 APSR.N = result<31>; 2029 APSR.Z = IsZeroBit(result); 2030 APSR.C = carry; 2031 APSR.V = overflow; 2032#endif 2033 2034 bool success = false; 2035 const uint32_t opcode = OpcodeAsUnsigned (&success); 2036 if (!success) 2037 return false; 2038 2039 if (ConditionPassed()) 2040 { 2041 uint32_t Rd, Rn; 2042 uint32_t imm32; // the immediate value to be added to the value obtained from Rn 2043 bool setflags; 2044 switch (encoding) 2045 { 2046 case eEncodingA1: 2047 Rd = Bits32(opcode, 15, 12); 2048 Rn = Bits32(opcode, 19, 16); 2049 setflags = BitIsSet(opcode, 20); 2050 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12) 2051 break; 2052 default: 2053 return false; 2054 } 2055 2056 // Read the first operand. 2057 uint32_t val1 = ReadCoreReg(Rn, &success); 2058 if (!success) 2059 return false; 2060 2061 AddWithCarryResult res = AddWithCarry(val1, imm32, 0); 2062 2063 EmulateInstruction::Context context; 2064 context.type = EmulateInstruction::eContextImmediate; 2065 context.SetNoArgs (); 2066 2067 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow)) 2068 return false; 2069 } 2070 return true; 2071} 2072 2073// This instruction adds a register value and an optionally-shifted register value, and writes the result 2074// to the destination register. It can optionally update the condition flags based on the result. 2075bool 2076EmulateInstructionARM::EmulateADDReg (ARMEncoding encoding) 2077{ 2078#if 0 2079 // ARM pseudo code... 2080 if ConditionPassed() then 2081 EncodingSpecificOperations(); 2082 shifted = Shift(R[m], shift_t, shift_n, APSR.C); 2083 (result, carry, overflow) = AddWithCarry(R[n], shifted, '0'); 2084 if d == 15 then 2085 ALUWritePC(result); // setflags is always FALSE here 2086 else 2087 R[d] = result; 2088 if setflags then 2089 APSR.N = result<31>; 2090 APSR.Z = IsZeroBit(result); 2091 APSR.C = carry; 2092 APSR.V = overflow; 2093#endif 2094 2095 bool success = false; 2096 const uint32_t opcode = OpcodeAsUnsigned (&success); 2097 if (!success) 2098 return false; 2099 2100 if (ConditionPassed()) 2101 { 2102 uint32_t Rd, Rn, Rm; 2103 ARM_ShifterType shift_t; 2104 uint32_t shift_n; // the shift applied to the value read from Rm 2105 bool setflags; 2106 switch (encoding) 2107 { 2108 case eEncodingT1: 2109 Rd = Bits32(opcode, 2, 0); 2110 Rn = Bits32(opcode, 5, 3); 2111 Rm = Bits32(opcode, 8, 6); 2112 setflags = !InITBlock(); 2113 shift_t = SRType_LSL; 2114 shift_n = 0; 2115 case eEncodingT2: 2116 Rd = Rn = Bit32(opcode, 7) << 3 | Bits32(opcode, 2, 0); 2117 Rm = Bits32(opcode, 6, 3); 2118 setflags = false; 2119 shift_t = SRType_LSL; 2120 shift_n = 0; 2121 if (Rn == 15 && Rm == 15) 2122 return false; 2123 if (Rd == 15 && InITBlock() && !LastInITBlock()) 2124 return false; 2125 break; 2126 case eEncodingA1: 2127 Rd = Bits32(opcode, 15, 12); 2128 Rn = Bits32(opcode, 19, 16); 2129 Rm = Bits32(opcode, 3, 0); 2130 setflags = BitIsSet(opcode, 20); 2131 shift_n = DecodeImmShift(Bits32(opcode, 6, 5), Bits32(opcode, 11, 7), shift_t); 2132 break; 2133 default: 2134 return false; 2135 } 2136 2137 // Read the first operand. 2138 uint32_t val1 = ReadCoreReg(Rn, &success); 2139 if (!success) 2140 return false; 2141 2142 // Read the second operand. 2143 uint32_t val2 = ReadCoreReg(Rm, &success); 2144 if (!success) 2145 return false; 2146 2147 uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C); 2148 AddWithCarryResult res = AddWithCarry(val1, shifted, 0); 2149 2150 EmulateInstruction::Context context; 2151 context.type = EmulateInstruction::eContextImmediate; 2152 context.SetNoArgs (); 2153 2154 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow)) 2155 return false; 2156 } 2157 return true; 2158} 2159 2160// Compare Negative (immediate) adds a register value and an immediate value. 2161// It updates the condition flags based on the result, and discards the result. 2162bool 2163EmulateInstructionARM::EmulateCMNImm (ARMEncoding encoding) 2164{ 2165#if 0 2166 // ARM pseudo code... 2167 if ConditionPassed() then 2168 EncodingSpecificOperations(); 2169 (result, carry, overflow) = AddWithCarry(R[n], imm32, '0'); 2170 APSR.N = result<31>; 2171 APSR.Z = IsZeroBit(result); 2172 APSR.C = carry; 2173 APSR.V = overflow; 2174#endif 2175 2176 bool success = false; 2177 const uint32_t opcode = OpcodeAsUnsigned (&success); 2178 if (!success) 2179 return false; 2180 2181 uint32_t Rn; // the first operand 2182 uint32_t imm32; // the immediate value to be compared with 2183 switch (encoding) { 2184 case eEncodingT1: 2185 Rn = Bits32(opcode, 10, 8); 2186 imm32 = Bits32(opcode, 7, 0); 2187 case eEncodingA1: 2188 Rn = Bits32(opcode, 19, 16); 2189 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12) 2190 break; 2191 default: 2192 return false; 2193 } 2194 // Read the register value from the operand register Rn. 2195 uint32_t reg_val = ReadCoreReg(Rn, &success); 2196 if (!success) 2197 return false; 2198 2199 AddWithCarryResult res = AddWithCarry(reg_val, ~imm32, 1); 2200 2201 EmulateInstruction::Context context; 2202 context.type = EmulateInstruction::eContextImmediate; 2203 context.SetNoArgs (); 2204 if (!WriteFlags(context, res.result, res.carry_out, res.overflow)) 2205 return false; 2206 2207 return true; 2208} 2209 2210// Compare Negative (register) adds a register value and an optionally-shifted register value. 2211// It updates the condition flags based on the result, and discards the result. 2212bool 2213EmulateInstructionARM::EmulateCMNReg (ARMEncoding encoding) 2214{ 2215#if 0 2216 // ARM pseudo code... 2217 if ConditionPassed() then 2218 EncodingSpecificOperations(); 2219 shifted = Shift(R[m], shift_t, shift_n, APSR.C); 2220 (result, carry, overflow) = AddWithCarry(R[n], shifted, '0'); 2221 APSR.N = result<31>; 2222 APSR.Z = IsZeroBit(result); 2223 APSR.C = carry; 2224 APSR.V = overflow; 2225#endif 2226 2227 bool success = false; 2228 const uint32_t opcode = OpcodeAsUnsigned (&success); 2229 if (!success) 2230 return false; 2231 2232 uint32_t Rn; // the first operand 2233 uint32_t Rm; // the second operand 2234 ARM_ShifterType shift_t; 2235 uint32_t shift_n; // the shift applied to the value read from Rm 2236 switch (encoding) { 2237 case eEncodingT1: 2238 Rn = Bits32(opcode, 2, 0); 2239 Rm = Bits32(opcode, 5, 3); 2240 shift_t = SRType_LSL; 2241 shift_n = 0; 2242 break; 2243 case eEncodingT2: 2244 Rn = Bit32(opcode, 7) << 3 | Bits32(opcode, 2, 0); 2245 Rm = Bits32(opcode, 6, 3); 2246 shift_t = SRType_LSL; 2247 shift_n = 0; 2248 if (Rn < 8 && Rm < 8) 2249 return false; 2250 if (Rn == 15 || Rm == 15) 2251 return false; 2252 break; 2253 case eEncodingA1: 2254 Rn = Bits32(opcode, 19, 16); 2255 Rm = Bits32(opcode, 3, 0); 2256 shift_n = DecodeImmShift(Bits32(opcode, 6, 5), Bits32(opcode, 11, 7), shift_t); 2257 default: 2258 return false; 2259 } 2260 // Read the register value from register Rn. 2261 uint32_t val1 = ReadCoreReg(Rn, &success); 2262 if (!success) 2263 return false; 2264 2265 // Read the register value from register Rm. 2266 uint32_t val2 = ReadCoreReg(Rm, &success); 2267 if (!success) 2268 return false; 2269 2270 uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C); 2271 AddWithCarryResult res = AddWithCarry(val1, ~shifted, 1); 2272 2273 EmulateInstruction::Context context; 2274 context.type = EmulateInstruction::eContextImmediate; 2275 context.SetNoArgs(); 2276 if (!WriteFlags(context, res.result, res.carry_out, res.overflow)) 2277 return false; 2278 2279 return true; 2280} 2281 2282// Compare (immediate) subtracts an immediate value from a register value. 2283// It updates the condition flags based on the result, and discards the result. 2284bool 2285EmulateInstructionARM::EmulateCMPImm (ARMEncoding encoding) 2286{ 2287#if 0 2288 // ARM pseudo code... 2289 if ConditionPassed() then 2290 EncodingSpecificOperations(); 2291 (result, carry, overflow) = AddWithCarry(R[n], NOT(imm32), '1'); 2292 APSR.N = result<31>; 2293 APSR.Z = IsZeroBit(result); 2294 APSR.C = carry; 2295 APSR.V = overflow; 2296#endif 2297 2298 bool success = false; 2299 const uint32_t opcode = OpcodeAsUnsigned (&success); 2300 if (!success) 2301 return false; 2302 2303 uint32_t Rn; // the first operand 2304 uint32_t imm32; // the immediate value to be compared with 2305 switch (encoding) { 2306 case eEncodingT1: 2307 Rn = Bits32(opcode, 10, 8); 2308 imm32 = Bits32(opcode, 7, 0); 2309 case eEncodingA1: 2310 Rn = Bits32(opcode, 19, 16); 2311 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12) 2312 break; 2313 default: 2314 return false; 2315 } 2316 // Read the register value from the operand register Rn. 2317 uint32_t reg_val = ReadCoreReg(Rn, &success); 2318 if (!success) 2319 return false; 2320 2321 AddWithCarryResult res = AddWithCarry(reg_val, ~imm32, 1); 2322 2323 EmulateInstruction::Context context; 2324 context.type = EmulateInstruction::eContextImmediate; 2325 context.SetNoArgs (); 2326 if (!WriteFlags(context, res.result, res.carry_out, res.overflow)) 2327 return false; 2328 2329 return true; 2330} 2331 2332// Compare (register) subtracts an optionally-shifted register value from a register value. 2333// It updates the condition flags based on the result, and discards the result. 2334bool 2335EmulateInstructionARM::EmulateCMPReg (ARMEncoding encoding) 2336{ 2337#if 0 2338 // ARM pseudo code... 2339 if ConditionPassed() then 2340 EncodingSpecificOperations(); 2341 shifted = Shift(R[m], shift_t, shift_n, APSR.C); 2342 (result, carry, overflow) = AddWithCarry(R[n], NOT(shifted), '1'); 2343 APSR.N = result<31>; 2344 APSR.Z = IsZeroBit(result); 2345 APSR.C = carry; 2346 APSR.V = overflow; 2347#endif 2348 2349 bool success = false; 2350 const uint32_t opcode = OpcodeAsUnsigned (&success); 2351 if (!success) 2352 return false; 2353 2354 uint32_t Rn; // the first operand 2355 uint32_t Rm; // the second operand 2356 ARM_ShifterType shift_t; 2357 uint32_t shift_n; // the shift applied to the value read from Rm 2358 switch (encoding) { 2359 case eEncodingT1: 2360 Rn = Bits32(opcode, 2, 0); 2361 Rm = Bits32(opcode, 5, 3); 2362 shift_t = SRType_LSL; 2363 shift_n = 0; 2364 break; 2365 case eEncodingT2: 2366 Rn = Bit32(opcode, 7) << 3 | Bits32(opcode, 2, 0); 2367 Rm = Bits32(opcode, 6, 3); 2368 shift_t = SRType_LSL; 2369 shift_n = 0; 2370 if (Rn < 8 && Rm < 8) 2371 return false; 2372 if (Rn == 15 || Rm == 15) 2373 return false; 2374 break; 2375 case eEncodingA1: 2376 Rn = Bits32(opcode, 19, 16); 2377 Rm = Bits32(opcode, 3, 0); 2378 shift_n = DecodeImmShift(Bits32(opcode, 6, 5), Bits32(opcode, 11, 7), shift_t); 2379 default: 2380 return false; 2381 } 2382 // Read the register value from register Rn. 2383 uint32_t val1 = ReadCoreReg(Rn, &success); 2384 if (!success) 2385 return false; 2386 2387 // Read the register value from register Rm. 2388 uint32_t val2 = ReadCoreReg(Rm, &success); 2389 if (!success) 2390 return false; 2391 2392 uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C); 2393 AddWithCarryResult res = AddWithCarry(val1, ~shifted, 1); 2394 2395 EmulateInstruction::Context context; 2396 context.type = EmulateInstruction::eContextImmediate; 2397 context.SetNoArgs(); 2398 if (!WriteFlags(context, res.result, res.carry_out, res.overflow)) 2399 return false; 2400 2401 return true; 2402} 2403 2404// Arithmetic Shift Right (immediate) shifts a register value right by an immediate number of bits, 2405// shifting in copies of its sign bit, and writes the result to the destination register. It can 2406// optionally update the condition flags based on the result. 2407bool 2408EmulateInstructionARM::EmulateASRImm (ARMEncoding encoding) 2409{ 2410#if 0 2411 // ARM pseudo code... 2412 if ConditionPassed() then 2413 EncodingSpecificOperations(); 2414 (result, carry) = Shift_C(R[m], SRType_ASR, shift_n, APSR.C); 2415 if d == 15 then // Can only occur for ARM encoding 2416 ALUWritePC(result); // setflags is always FALSE here 2417 else 2418 R[d] = result; 2419 if setflags then 2420 APSR.N = result<31>; 2421 APSR.Z = IsZeroBit(result); 2422 APSR.C = carry; 2423 // APSR.V unchanged 2424#endif 2425 2426 return EmulateShiftImm(encoding, SRType_ASR); 2427} 2428 2429// Arithmetic Shift Right (register) shifts a register value right by a variable number of bits, 2430// shifting in copies of its sign bit, and writes the result to the destination register. 2431// The variable number of bits is read from the bottom byte of a register. It can optionally update 2432// the condition flags based on the result. 2433bool 2434EmulateInstructionARM::EmulateASRReg (ARMEncoding encoding) 2435{ 2436#if 0 2437 // ARM pseudo code... 2438 if ConditionPassed() then 2439 EncodingSpecificOperations(); 2440 shift_n = UInt(R[m]<7:0>); 2441 (result, carry) = Shift_C(R[m], SRType_ASR, shift_n, APSR.C); 2442 R[d] = result; 2443 if setflags then 2444 APSR.N = result<31>; 2445 APSR.Z = IsZeroBit(result); 2446 APSR.C = carry; 2447 // APSR.V unchanged 2448#endif 2449 2450 return EmulateShiftReg(encoding, SRType_ASR); 2451} 2452 2453// Logical Shift Left (immediate) shifts a register value left by an immediate number of bits, 2454// shifting in zeros, and writes the result to the destination register. It can optionally 2455// update the condition flags based on the result. 2456bool 2457EmulateInstructionARM::EmulateLSLImm (ARMEncoding encoding) 2458{ 2459#if 0 2460 // ARM pseudo code... 2461 if ConditionPassed() then 2462 EncodingSpecificOperations(); 2463 (result, carry) = Shift_C(R[m], SRType_LSL, shift_n, APSR.C); 2464 if d == 15 then // Can only occur for ARM encoding 2465 ALUWritePC(result); // setflags is always FALSE here 2466 else 2467 R[d] = result; 2468 if setflags then 2469 APSR.N = result<31>; 2470 APSR.Z = IsZeroBit(result); 2471 APSR.C = carry; 2472 // APSR.V unchanged 2473#endif 2474 2475 return EmulateShiftImm(encoding, SRType_LSL); 2476} 2477 2478// Logical Shift Left (register) shifts a register value left by a variable number of bits, 2479// shifting in zeros, and writes the result to the destination register. The variable number 2480// of bits is read from the bottom byte of a register. It can optionally update the condition 2481// flags based on the result. 2482bool 2483EmulateInstructionARM::EmulateLSLReg (ARMEncoding encoding) 2484{ 2485#if 0 2486 // ARM pseudo code... 2487 if ConditionPassed() then 2488 EncodingSpecificOperations(); 2489 shift_n = UInt(R[m]<7:0>); 2490 (result, carry) = Shift_C(R[m], SRType_LSL, shift_n, APSR.C); 2491 R[d] = result; 2492 if setflags then 2493 APSR.N = result<31>; 2494 APSR.Z = IsZeroBit(result); 2495 APSR.C = carry; 2496 // APSR.V unchanged 2497#endif 2498 2499 return EmulateShiftReg(encoding, SRType_LSL); 2500} 2501 2502// Logical Shift Right (immediate) shifts a register value right by an immediate number of bits, 2503// shifting in zeros, and writes the result to the destination register. It can optionally 2504// update the condition flags based on the result. 2505bool 2506EmulateInstructionARM::EmulateLSRImm (ARMEncoding encoding) 2507{ 2508#if 0 2509 // ARM pseudo code... 2510 if ConditionPassed() then 2511 EncodingSpecificOperations(); 2512 (result, carry) = Shift_C(R[m], SRType_LSR, shift_n, APSR.C); 2513 if d == 15 then // Can only occur for ARM encoding 2514 ALUWritePC(result); // setflags is always FALSE here 2515 else 2516 R[d] = result; 2517 if setflags then 2518 APSR.N = result<31>; 2519 APSR.Z = IsZeroBit(result); 2520 APSR.C = carry; 2521 // APSR.V unchanged 2522#endif 2523 2524 return EmulateShiftImm(encoding, SRType_LSR); 2525} 2526 2527// Logical Shift Right (register) shifts a register value right by a variable number of bits, 2528// shifting in zeros, and writes the result to the destination register. The variable number 2529// of bits is read from the bottom byte of a register. It can optionally update the condition 2530// flags based on the result. 2531bool 2532EmulateInstructionARM::EmulateLSRReg (ARMEncoding encoding) 2533{ 2534#if 0 2535 // ARM pseudo code... 2536 if ConditionPassed() then 2537 EncodingSpecificOperations(); 2538 shift_n = UInt(R[m]<7:0>); 2539 (result, carry) = Shift_C(R[m], SRType_LSR, shift_n, APSR.C); 2540 R[d] = result; 2541 if setflags then 2542 APSR.N = result<31>; 2543 APSR.Z = IsZeroBit(result); 2544 APSR.C = carry; 2545 // APSR.V unchanged 2546#endif 2547 2548 return EmulateShiftReg(encoding, SRType_LSR); 2549} 2550 2551// Rotate Right (immediate) provides the value of the contents of a register rotated by a constant value. 2552// The bits that are rotated off the right end are inserted into the vacated bit positions on the left. 2553// It can optionally update the condition flags based on the result. 2554bool 2555EmulateInstructionARM::EmulateRORImm (ARMEncoding encoding) 2556{ 2557#if 0 2558 // ARM pseudo code... 2559 if ConditionPassed() then 2560 EncodingSpecificOperations(); 2561 (result, carry) = Shift_C(R[m], SRType_ROR, shift_n, APSR.C); 2562 if d == 15 then // Can only occur for ARM encoding 2563 ALUWritePC(result); // setflags is always FALSE here 2564 else 2565 R[d] = result; 2566 if setflags then 2567 APSR.N = result<31>; 2568 APSR.Z = IsZeroBit(result); 2569 APSR.C = carry; 2570 // APSR.V unchanged 2571#endif 2572 2573 return EmulateShiftImm(encoding, SRType_ROR); 2574} 2575 2576// Rotate Right (register) provides the value of the contents of a register rotated by a variable number of bits. 2577// The bits that are rotated off the right end are inserted into the vacated bit positions on the left. 2578// The variable number of bits is read from the bottom byte of a register. It can optionally update the condition 2579// flags based on the result. 2580bool 2581EmulateInstructionARM::EmulateRORReg (ARMEncoding encoding) 2582{ 2583#if 0 2584 // ARM pseudo code... 2585 if ConditionPassed() then 2586 EncodingSpecificOperations(); 2587 shift_n = UInt(R[m]<7:0>); 2588 (result, carry) = Shift_C(R[m], SRType_ROR, shift_n, APSR.C); 2589 R[d] = result; 2590 if setflags then 2591 APSR.N = result<31>; 2592 APSR.Z = IsZeroBit(result); 2593 APSR.C = carry; 2594 // APSR.V unchanged 2595#endif 2596 2597 return EmulateShiftReg(encoding, SRType_ROR); 2598} 2599 2600// Rotate Right with Extend provides the value of the contents of a register shifted right by one place, 2601// with the carry flag shifted into bit [31]. 2602// 2603// RRX can optionally update the condition flags based on the result. 2604// In that case, bit [0] is shifted into the carry flag. 2605bool 2606EmulateInstructionARM::EmulateRRX (ARMEncoding encoding) 2607{ 2608#if 0 2609 // ARM pseudo code... 2610 if ConditionPassed() then 2611 EncodingSpecificOperations(); 2612 (result, carry) = Shift_C(R[m], SRType_RRX, 1, APSR.C); 2613 if d == 15 then // Can only occur for ARM encoding 2614 ALUWritePC(result); // setflags is always FALSE here 2615 else 2616 R[d] = result; 2617 if setflags then 2618 APSR.N = result<31>; 2619 APSR.Z = IsZeroBit(result); 2620 APSR.C = carry; 2621 // APSR.V unchanged 2622#endif 2623 2624 return EmulateShiftImm(encoding, SRType_RRX); 2625} 2626 2627bool 2628EmulateInstructionARM::EmulateShiftImm (ARMEncoding encoding, ARM_ShifterType shift_type) 2629{ 2630 assert(shift_type == SRType_ASR || shift_type == SRType_LSL || shift_type == SRType_LSR); 2631 2632 bool success = false; 2633 const uint32_t opcode = OpcodeAsUnsigned (&success); 2634 if (!success) 2635 return false; 2636 2637 if (ConditionPassed()) 2638 { 2639 uint32_t Rd; // the destination register 2640 uint32_t Rm; // the first operand register 2641 uint32_t imm5; // encoding for the shift amount 2642 uint32_t carry; // the carry bit after the shift operation 2643 bool setflags; 2644 2645 // Special case handling! 2646 // A8.6.139 ROR (immediate) -- Encoding T1 2647 if (shift_type == SRType_ROR && encoding == eEncodingT1) 2648 { 2649 // Morph the T1 encoding from the ARM Architecture Manual into T2 encoding to 2650 // have the same decoding of bit fields as the other Thumb2 shift operations. 2651 encoding = eEncodingT2; 2652 } 2653 2654 switch (encoding) { 2655 case eEncodingT1: 2656 // Due to the above special case handling! 2657 assert(shift_type != SRType_ROR); 2658 2659 Rd = Bits32(opcode, 2, 0); 2660 Rm = Bits32(opcode, 5, 3); 2661 setflags = !InITBlock(); 2662 imm5 = Bits32(opcode, 10, 6); 2663 break; 2664 case eEncodingT2: 2665 // A8.6.141 RRX 2666 assert(shift_type != SRType_RRX); 2667 2668 Rd = Bits32(opcode, 11, 8); 2669 Rm = Bits32(opcode, 3, 0); 2670 setflags = BitIsSet(opcode, 20); 2671 imm5 = Bits32(opcode, 14, 12) << 2 | Bits32(opcode, 7, 6); 2672 if (BadReg(Rd) || BadReg(Rm)) 2673 return false; 2674 break; 2675 case eEncodingA1: 2676 Rd = Bits32(opcode, 15, 12); 2677 Rm = Bits32(opcode, 3, 0); 2678 setflags = BitIsSet(opcode, 20); 2679 imm5 = Bits32(opcode, 11, 7); 2680 break; 2681 default: 2682 return false; 2683 } 2684 2685 // A8.6.139 ROR (immediate) 2686 if (shift_type == SRType_ROR && imm5 == 0) 2687 shift_type = SRType_RRX; 2688 2689 // Get the first operand. 2690 uint32_t value = ReadCoreReg (Rm, &success); 2691 if (!success) 2692 return false; 2693 2694 // Decode the shift amount if not RRX. 2695 uint32_t amt = (shift_type == SRType_RRX ? 1 : DecodeImmShift(shift_type, imm5)); 2696 2697 uint32_t result = Shift_C(value, shift_type, amt, APSR_C, carry); 2698 2699 // The context specifies that an immediate is to be moved into Rd. 2700 EmulateInstruction::Context context; 2701 context.type = EmulateInstruction::eContextImmediate; 2702 context.SetNoArgs (); 2703 2704 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry)) 2705 return false; 2706 } 2707 return true; 2708} 2709 2710bool 2711EmulateInstructionARM::EmulateShiftReg (ARMEncoding encoding, ARM_ShifterType shift_type) 2712{ 2713 assert(shift_type == SRType_ASR || shift_type == SRType_LSL || shift_type == SRType_LSR); 2714 2715 bool success = false; 2716 const uint32_t opcode = OpcodeAsUnsigned (&success); 2717 if (!success) 2718 return false; 2719 2720 if (ConditionPassed()) 2721 { 2722 uint32_t Rd; // the destination register 2723 uint32_t Rn; // the first operand register 2724 uint32_t Rm; // the register whose bottom byte contains the amount to shift by 2725 uint32_t carry; // the carry bit after the shift operation 2726 bool setflags; 2727 switch (encoding) { 2728 case eEncodingT1: 2729 Rd = Bits32(opcode, 2, 0); 2730 Rn = Rd; 2731 Rm = Bits32(opcode, 5, 3); 2732 setflags = !InITBlock(); 2733 break; 2734 case eEncodingT2: 2735 Rd = Bits32(opcode, 11, 8); 2736 Rn = Bits32(opcode, 19, 16); 2737 Rm = Bits32(opcode, 3, 0); 2738 setflags = BitIsSet(opcode, 20); 2739 if (BadReg(Rd) || BadReg(Rn) || BadReg(Rm)) 2740 return false; 2741 break; 2742 case eEncodingA1: 2743 Rd = Bits32(opcode, 15, 12); 2744 Rn = Bits32(opcode, 3, 0); 2745 Rm = Bits32(opcode, 11, 8); 2746 setflags = BitIsSet(opcode, 20); 2747 if (Rd == 15 || Rn == 15 || Rm == 15) 2748 return false; 2749 break; 2750 default: 2751 return false; 2752 } 2753 2754 // Get the first operand. 2755 uint32_t value = ReadCoreReg (Rn, &success); 2756 if (!success) 2757 return false; 2758 // Get the Rm register content. 2759 uint32_t val = ReadCoreReg (Rm, &success); 2760 if (!success) 2761 return false; 2762 2763 // Get the shift amount. 2764 uint32_t amt = Bits32(val, 7, 0); 2765 2766 uint32_t result = Shift_C(value, shift_type, amt, APSR_C, carry); 2767 2768 // The context specifies that an immediate is to be moved into Rd. 2769 EmulateInstruction::Context context; 2770 context.type = EmulateInstruction::eContextImmediate; 2771 context.SetNoArgs (); 2772 2773 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry)) 2774 return false; 2775 } 2776 return true; 2777} 2778 2779// LDM loads multiple registers from consecutive memory locations, using an 2780// address from a base register. Optionally the address just above the highest of those locations 2781// can be written back to the base register. 2782bool 2783EmulateInstructionARM::EmulateLDM (ARMEncoding encoding) 2784{ 2785#if 0 2786 // ARM pseudo code... 2787 if ConditionPassed() 2788 EncodingSpecificOperations(); NullCheckIfThumbEE (n); 2789 address = R[n]; 2790 2791 for i = 0 to 14 2792 if registers<i> == '1' then 2793 R[i] = MemA[address, 4]; address = address + 4; 2794 if registers<15> == '1' then 2795 LoadWritePC (MemA[address, 4]); 2796 2797 if wback && registers<n> == '0' then R[n] = R[n] + 4 * BitCount (registers); 2798 if wback && registers<n> == '1' then R[n] = bits(32) UNKNOWN; // Only possible for encoding A1 2799 2800#endif 2801 2802 bool success = false; 2803 const uint32_t opcode = OpcodeAsUnsigned (&success); 2804 if (!success) 2805 return false; 2806 2807 if (ConditionPassed()) 2808 { 2809 uint32_t n; 2810 uint32_t registers = 0; 2811 bool wback; 2812 const uint32_t addr_byte_size = GetAddressByteSize(); 2813 switch (encoding) 2814 { 2815 case eEncodingT1: 2816 // n = UInt(Rn); registers = ’00000000’:register_list; wback = (registers<n> == ’0’); 2817 n = Bits32 (opcode, 10, 8); 2818 registers = Bits32 (opcode, 7, 0); 2819 registers = registers & 0x00ff; // Make sure the top 8 bits are zeros. 2820 wback = BitIsClear (registers, n); 2821 // if BitCount(registers) < 1 then UNPREDICTABLE; 2822 if (BitCount(registers) < 1) 2823 return false; 2824 break; 2825 case eEncodingT2: 2826 // if W == ’1’ && Rn == ’1101’ then SEE POP; 2827 // n = UInt(Rn); registers = P:M:’0’:register_list; wback = (W == ’1’); 2828 n = Bits32 (opcode, 19, 16); 2829 registers = Bits32 (opcode, 15, 0); 2830 registers = registers & 0xdfff; // Make sure bit 13 is zero. 2831 wback = BitIsSet (opcode, 21); 2832 2833 // if n == 15 || BitCount(registers) < 2 || (P == ’1’ && M == ’1’) then UNPREDICTABLE; 2834 if ((n == 15) 2835 || (BitCount (registers) < 2) 2836 || (BitIsSet (opcode, 14) && BitIsSet (opcode, 15))) 2837 return false; 2838 2839 // if registers<15> == ’1’ && InITBlock() && !LastInITBlock() then UNPREDICTABLE; 2840 if (BitIsSet (registers, 15) && InITBlock() && !LastInITBlock()) 2841 return false; 2842 2843 // if wback && registers<n> == ’1’ then UNPREDICTABLE; 2844 if (wback 2845 && BitIsSet (registers, n)) 2846 return false; 2847 break; 2848 2849 case eEncodingA1: 2850 n = Bits32 (opcode, 19, 16); 2851 registers = Bits32 (opcode, 15, 0); 2852 wback = BitIsSet (opcode, 21); 2853 if ((n == 15) 2854 || (BitCount (registers) < 1)) 2855 return false; 2856 break; 2857 default: 2858 return false; 2859 } 2860 2861 int32_t offset = 0; 2862 const addr_t base_address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success); 2863 if (!success) 2864 return false; 2865 2866 EmulateInstruction::Context context; 2867 context.type = EmulateInstruction::eContextRegisterPlusOffset; 2868 Register dwarf_reg; 2869 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n); 2870 context.SetRegisterPlusOffset (dwarf_reg, offset); 2871 2872 for (int i = 0; i < 14; ++i) 2873 { 2874 if (BitIsSet (registers, i)) 2875 { 2876 context.type = EmulateInstruction::eContextRegisterPlusOffset; 2877 context.SetRegisterPlusOffset (dwarf_reg, offset); 2878 if (wback && (n == 13)) // Pop Instruction 2879 context.type = EmulateInstruction::eContextPopRegisterOffStack; 2880 2881 // R[i] = MemA [address, 4]; address = address + 4; 2882 uint32_t data = MemARead (context, base_address + offset, addr_byte_size, 0, &success); 2883 if (!success) 2884 return false; 2885 2886 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + i, data)) 2887 return false; 2888 2889 offset += addr_byte_size; 2890 } 2891 } 2892 2893 if (BitIsSet (registers, 15)) 2894 { 2895 //LoadWritePC (MemA [address, 4]); 2896 context.type = EmulateInstruction::eContextRegisterPlusOffset; 2897 context.SetRegisterPlusOffset (dwarf_reg, offset); 2898 uint32_t data = MemARead (context, base_address + offset, addr_byte_size, 0, &success); 2899 if (!success) 2900 return false; 2901 // In ARMv5T and above, this is an interworking branch. 2902 if (!LoadWritePC(context, data)) 2903 return false; 2904 } 2905 2906 if (wback && BitIsClear (registers, n)) 2907 { 2908 // R[n] = R[n] + 4 * BitCount (registers) 2909 int32_t offset = addr_byte_size * BitCount (registers); 2910 context.type = EmulateInstruction::eContextAdjustBaseRegister; 2911 context.SetRegisterPlusOffset (dwarf_reg, offset); 2912 2913 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, base_address + offset)) 2914 return false; 2915 } 2916 if (wback && BitIsSet (registers, n)) 2917 // R[n] bits(32) UNKNOWN; 2918 return WriteBits32Unknown (n); 2919 } 2920 return true; 2921} 2922 2923// LDMDA loads multiple registers from consecutive memory locations using an address from a base registers. 2924// The consecutive memorty locations end at this address and the address just below the lowest of those locations 2925// can optionally be written back tot he base registers. 2926bool 2927EmulateInstructionARM::EmulateLDMDA (ARMEncoding encoding) 2928{ 2929#if 0 2930 // ARM pseudo code... 2931 if ConditionPassed() then 2932 EncodingSpecificOperations(); 2933 address = R[n] - 4*BitCount(registers) + 4; 2934 2935 for i = 0 to 14 2936 if registers<i> == ’1’ then 2937 R[i] = MemA[address,4]; address = address + 4; 2938 2939 if registers<15> == ’1’ then 2940 LoadWritePC(MemA[address,4]); 2941 2942 if wback && registers<n> == ’0’ then R[n] = R[n] - 4*BitCount(registers); 2943 if wback && registers<n> == ’1’ then R[n] = bits(32) UNKNOWN; 2944#endif 2945 2946 bool success = false; 2947 const uint32_t opcode = OpcodeAsUnsigned (&success); 2948 if (!success) 2949 return false; 2950 2951 if (ConditionPassed()) 2952 { 2953 uint32_t n; 2954 uint32_t registers = 0; 2955 bool wback; 2956 const uint32_t addr_byte_size = GetAddressByteSize(); 2957 2958 // EncodingSpecificOperations(); 2959 switch (encoding) 2960 { 2961 case eEncodingA1: 2962 // n = UInt(Rn); registers = register_list; wback = (W == ’1’); 2963 n = Bits32 (opcode, 19, 16); 2964 registers = Bits32 (opcode, 15, 0); 2965 wback = BitIsSet (opcode, 21); 2966 2967 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE; 2968 if ((n == 15) || (BitCount (registers) < 1)) 2969 return false; 2970 2971 break; 2972 2973 default: 2974 return false; 2975 } 2976 // address = R[n] - 4*BitCount(registers) + 4; 2977 2978 int32_t offset = 0; 2979 addr_t address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success); 2980 2981 if (!success) 2982 return false; 2983 2984 address = address - (addr_byte_size * BitCount (registers)) + addr_byte_size; 2985 2986 EmulateInstruction::Context context; 2987 context.type = EmulateInstruction::eContextRegisterPlusOffset; 2988 Register dwarf_reg; 2989 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n); 2990 context.SetRegisterPlusOffset (dwarf_reg, offset); 2991 2992 // for i = 0 to 14 2993 for (int i = 0; i < 14; ++i) 2994 { 2995 // if registers<i> == ’1’ then 2996 if (BitIsSet (registers, i)) 2997 { 2998 // R[i] = MemA[address,4]; address = address + 4; 2999 context.SetRegisterPlusOffset (dwarf_reg, offset); 3000 uint32_t data = MemARead (context, address + offset, addr_byte_size, 0, &success); 3001 if (!success) 3002 return false; 3003 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + i, data)) 3004 return false; 3005 offset += addr_byte_size; 3006 } 3007 } 3008 3009 // if registers<15> == ’1’ then 3010 // LoadWritePC(MemA[address,4]); 3011 if (BitIsSet (registers, 15)) 3012 { 3013 context.SetRegisterPlusOffset (dwarf_reg, offset); 3014 uint32_t data = MemARead (context, address + offset, addr_byte_size, 0, &success); 3015 if (!success) 3016 return false; 3017 // In ARMv5T and above, this is an interworking branch. 3018 if (!LoadWritePC(context, data)) 3019 return false; 3020 } 3021 3022 // if wback && registers<n> == ’0’ then R[n] = R[n] - 4*BitCount(registers); 3023 if (wback && BitIsClear (registers, n)) 3024 { 3025 addr_t addr = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success); 3026 if (!success) 3027 return false; 3028 3029 offset = (addr_byte_size * BitCount (registers)) * -1; 3030 context.type = EmulateInstruction::eContextAdjustBaseRegister; 3031 context.SetImmediateSigned (offset); 3032 addr = addr + offset; 3033 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, addr)) 3034 return false; 3035 } 3036 3037 // if wback && registers<n> == ’1’ then R[n] = bits(32) UNKNOWN; 3038 if (wback && BitIsSet (registers, n)) 3039 return WriteBits32Unknown (n); 3040 } 3041 return true; 3042} 3043 3044// LDMDB loads multiple registers from consecutive memory locations using an address from a base register. The 3045// consecutive memory lcoations end just below this address, and the address of the lowest of those locations can 3046// be optionally written back to the base register. 3047bool 3048EmulateInstructionARM::EmulateLDMDB (ARMEncoding encoding) 3049{ 3050#if 0 3051 // ARM pseudo code... 3052 if ConditionPassed() then 3053 EncodingSpecificOperations(); NullCheckIfThumbEE(n); 3054 address = R[n] - 4*BitCount(registers); 3055 3056 for i = 0 to 14 3057 if registers<i> == ’1’ then 3058 R[i] = MemA[address,4]; address = address + 4; 3059 if registers<15> == ’1’ then 3060 LoadWritePC(MemA[address,4]); 3061 3062 if wback && registers<n> == ’0’ then R[n] = R[n] - 4*BitCount(registers); 3063 if wback && registers<n> == ’1’ then R[n] = bits(32) UNKNOWN; // Only possible for encoding A1 3064#endif 3065 3066 bool success = false; 3067 const uint32_t opcode = OpcodeAsUnsigned (&success); 3068 if (!success) 3069 return false; 3070 3071 if (ConditionPassed()) 3072 { 3073 uint32_t n; 3074 uint32_t registers = 0; 3075 bool wback; 3076 const uint32_t addr_byte_size = GetAddressByteSize(); 3077 switch (encoding) 3078 { 3079 case eEncodingT1: 3080 // n = UInt(Rn); registers = P:M:’0’:register_list; wback = (W == ’1’); 3081 n = Bits32 (opcode, 19, 16); 3082 registers = Bits32 (opcode, 15, 0); 3083 registers = registers & 0xdfff; // Make sure bit 13 is a zero. 3084 wback = BitIsSet (opcode, 21); 3085 3086 // if n == 15 || BitCount(registers) < 2 || (P == ’1’ && M == ’1’) then UNPREDICTABLE; 3087 if ((n == 15) 3088 || (BitCount (registers) < 2) 3089 || (BitIsSet (opcode, 14) && BitIsSet (opcode, 15))) 3090 return false; 3091 3092 // if registers<15> == ’1’ && InITBlock() && !LastInITBlock() then UNPREDICTABLE; 3093 if (BitIsSet (registers, 15) && InITBlock() && !LastInITBlock()) 3094 return false; 3095 3096 // if wback && registers<n> == ’1’ then UNPREDICTABLE; 3097 if (wback && BitIsSet (registers, n)) 3098 return false; 3099 3100 break; 3101 3102 case eEncodingA1: 3103 // n = UInt(Rn); registers = register_list; wback = (W == ’1’); 3104 n = Bits32 (opcode, 19, 16); 3105 registers = Bits32 (opcode, 15, 0); 3106 wback = BitIsSet (opcode, 21); 3107 3108 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE; 3109 if ((n == 15) || (BitCount (registers) < 1)) 3110 return false; 3111 3112 break; 3113 3114 default: 3115 return false; 3116 } 3117 3118 // address = R[n] - 4*BitCount(registers); 3119 3120 int32_t offset = 0; 3121 addr_t address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success); 3122 3123 if (!success) 3124 return false; 3125 3126 address = address - (addr_byte_size * BitCount (registers)); 3127 EmulateInstruction::Context context; 3128 context.type = EmulateInstruction::eContextRegisterPlusOffset; 3129 Register dwarf_reg; 3130 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n); 3131 context.SetRegisterPlusOffset (dwarf_reg, offset); 3132 3133 for (int i = 0; i < 14; ++i) 3134 { 3135 if (BitIsSet (registers, i)) 3136 { 3137 // R[i] = MemA[address,4]; address = address + 4; 3138 context.SetRegisterPlusOffset (dwarf_reg, offset); 3139 uint32_t data = MemARead (context, address + offset, addr_byte_size, 0, &success); 3140 if (!success) 3141 return false; 3142 3143 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + i, data)) 3144 return false; 3145 3146 offset += addr_byte_size; 3147 } 3148 } 3149 3150 // if registers<15> == ’1’ then 3151 // LoadWritePC(MemA[address,4]); 3152 if (BitIsSet (registers, 15)) 3153 { 3154 context.SetRegisterPlusOffset (dwarf_reg, offset); 3155 uint32_t data = MemARead (context, address + offset, addr_byte_size, 0, &success); 3156 if (!success) 3157 return false; 3158 // In ARMv5T and above, this is an interworking branch. 3159 if (!LoadWritePC(context, data)) 3160 return false; 3161 } 3162 3163 // if wback && registers<n> == ’0’ then R[n] = R[n] - 4*BitCount(registers); 3164 if (wback && BitIsClear (registers, n)) 3165 { 3166 addr_t addr = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success); 3167 if (!success) 3168 return false; 3169 3170 offset = (addr_byte_size * BitCount (registers)) * -1; 3171 context.type = EmulateInstruction::eContextAdjustBaseRegister; 3172 context.SetImmediateSigned (offset); 3173 addr = addr + offset; 3174 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, addr)) 3175 return false; 3176 } 3177 3178 // if wback && registers<n> == ’1’ then R[n] = bits(32) UNKNOWN; // Only possible for encoding A1 3179 if (wback && BitIsSet (registers, n)) 3180 return WriteBits32Unknown (n); 3181 } 3182 return true; 3183} 3184 3185// LDMIB loads multiple registers from consecutive memory locations using an address from a base register. The 3186// consecutive memory locations start just above this address, and thea ddress of the last of those locations can 3187// optinoally be written back to the base register. 3188bool 3189EmulateInstructionARM::EmulateLDMIB (ARMEncoding encoding) 3190{ 3191#if 0 3192 if ConditionPassed() then 3193 EncodingSpecificOperations(); 3194 address = R[n] + 4; 3195 3196 for i = 0 to 14 3197 if registers<i> == ’1’ then 3198 R[i] = MemA[address,4]; address = address + 4; 3199 if registers<15> == ’1’ then 3200 LoadWritePC(MemA[address,4]); 3201 3202 if wback && registers<n> == ’0’ then R[n] = R[n] + 4*BitCount(registers); 3203 if wback && registers<n> == ’1’ then R[n] = bits(32) UNKNOWN; 3204#endif 3205 3206 bool success = false; 3207 const uint32_t opcode = OpcodeAsUnsigned (&success); 3208 if (!success) 3209 return false; 3210 3211 if (ConditionPassed()) 3212 { 3213 uint32_t n; 3214 uint32_t registers = 0; 3215 bool wback; 3216 const uint32_t addr_byte_size = GetAddressByteSize(); 3217 switch (encoding) 3218 { 3219 case eEncodingA1: 3220 // n = UInt(Rn); registers = register_list; wback = (W == ’1’); 3221 n = Bits32 (opcode, 19, 16); 3222 registers = Bits32 (opcode, 15, 0); 3223 wback = BitIsSet (opcode, 21); 3224 3225 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE; 3226 if ((n == 15) || (BitCount (registers) < 1)) 3227 return false; 3228 3229 break; 3230 default: 3231 return false; 3232 } 3233 // address = R[n] + 4; 3234 3235 int32_t offset = 0; 3236 addr_t address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success); 3237 3238 if (!success) 3239 return false; 3240 3241 address = address + addr_byte_size; 3242 3243 EmulateInstruction::Context context; 3244 context.type = EmulateInstruction::eContextRegisterPlusOffset; 3245 Register dwarf_reg; 3246 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n); 3247 context.SetRegisterPlusOffset (dwarf_reg, offset); 3248 3249 for (int i = 0; i < 14; ++i) 3250 { 3251 if (BitIsSet (registers, i)) 3252 { 3253 // R[i] = MemA[address,4]; address = address + 4; 3254 3255 context.SetRegisterPlusOffset (dwarf_reg, offset); 3256 uint32_t data = MemARead (context, address + offset, addr_byte_size, 0, &success); 3257 if (!success) 3258 return false; 3259 3260 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + i, data)) 3261 return false; 3262 3263 offset += addr_byte_size; 3264 } 3265 } 3266 3267 // if registers<15> == ’1’ then 3268 // LoadWritePC(MemA[address,4]); 3269 if (BitIsSet (registers, 15)) 3270 { 3271 context.SetRegisterPlusOffset (dwarf_reg, offset); 3272 uint32_t data = MemARead (context, address + offset, addr_byte_size, 0, &success); 3273 if (!success) 3274 return false; 3275 // In ARMv5T and above, this is an interworking branch. 3276 if (!LoadWritePC(context, data)) 3277 return false; 3278 } 3279 3280 // if wback && registers<n> == ’0’ then R[n] = R[n] + 4*BitCount(registers); 3281 if (wback && BitIsClear (registers, n)) 3282 { 3283 addr_t addr = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success); 3284 if (!success) 3285 return false; 3286 3287 offset = addr_byte_size * BitCount (registers); 3288 context.type = EmulateInstruction::eContextAdjustBaseRegister; 3289 context.SetImmediateSigned (offset); 3290 addr = addr + offset; 3291 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, addr)) 3292 return false; 3293 } 3294 3295 // if wback && registers<n> == ’1’ then R[n] = bits(32) UNKNOWN; // Only possible for encoding A1 3296 if (wback && BitIsSet (registers, n)) 3297 return WriteBits32Unknown (n); 3298 } 3299 return true; 3300} 3301 3302// Load Register (immediate) calculates an address from a base register value and 3303// an immediate offset, loads a word from memory, and writes to a register. 3304// LDR (immediate, Thumb) 3305bool 3306EmulateInstructionARM::EmulateLDRRtRnImm (ARMEncoding encoding) 3307{ 3308#if 0 3309 // ARM pseudo code... 3310 if (ConditionPassed()) 3311 { 3312 EncodingSpecificOperations(); NullCheckIfThumbEE(15); 3313 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32); 3314 address = if index then offset_addr else R[n]; 3315 data = MemU[address,4]; 3316 if wback then R[n] = offset_addr; 3317 if t == 15 then 3318 if address<1:0> == '00' then LoadWritePC(data); else UNPREDICTABLE; 3319 elsif UnalignedSupport() || address<1:0> = '00' then 3320 R[t] = data; 3321 else R[t] = bits(32) UNKNOWN; // Can only apply before ARMv7 3322 } 3323#endif 3324 3325 bool success = false; 3326 const uint32_t opcode = OpcodeAsUnsigned (&success); 3327 if (!success) 3328 return false; 3329 3330 if (ConditionPassed()) 3331 { 3332 uint32_t Rt; // the destination register 3333 uint32_t Rn; // the base register 3334 uint32_t imm32; // the immediate offset used to form the address 3335 addr_t offset_addr; // the offset address 3336 addr_t address; // the calculated address 3337 uint32_t data; // the literal data value from memory load 3338 bool add, index, wback; 3339 switch (encoding) { 3340 case eEncodingT1: 3341 Rt = Bits32(opcode, 5, 3); 3342 Rn = Bits32(opcode, 2, 0); 3343 imm32 = Bits32(opcode, 10, 6) << 2; // imm32 = ZeroExtend(imm5:'00', 32); 3344 // index = TRUE; add = TRUE; wback = FALSE 3345 add = true; 3346 index = true; 3347 wback = false; 3348 break; 3349 default: 3350 return false; 3351 } 3352 uint32_t base = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + Rn, 0, &success); 3353 if (!success) 3354 return false; 3355 if (add) 3356 offset_addr = base + imm32; 3357 else 3358 offset_addr = base - imm32; 3359 3360 address = (index ? offset_addr : base); 3361 3362 if (wback) 3363 { 3364 EmulateInstruction::Context ctx; 3365 ctx.type = EmulateInstruction::eContextRegisterPlusOffset; 3366 Register dwarf_reg; 3367 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + Rn); 3368 ctx.SetRegisterPlusOffset (dwarf_reg, (int32_t) (offset_addr - base)); 3369 3370 if (!WriteRegisterUnsigned (ctx, eRegisterKindDWARF, dwarf_r0 + Rn, offset_addr)) 3371 return false; 3372 } 3373 3374 // Prepare to write to the Rt register. 3375 EmulateInstruction::Context context; 3376 context.type = EmulateInstruction::eContextImmediate; 3377 context.SetNoArgs (); 3378 3379 // Read memory from the address. 3380 data = MemURead(context, address, 4, 0, &success); 3381 if (!success) 3382 return false; 3383 3384 if (Rt == 15) 3385 { 3386 if (Bits32(address, 1, 0) == 0) 3387 { 3388 if (!LoadWritePC(context, data)) 3389 return false; 3390 } 3391 else 3392 return false; 3393 } 3394 else if (UnalignedSupport() || Bits32(address, 1, 0) == 0) 3395 { 3396 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + Rt, data)) 3397 return false; 3398 } 3399 else 3400 return false; 3401 } 3402 return true; 3403} 3404 3405// STM (Store Multiple Increment After) stores multiple registers to consecutive memory locations using an address 3406// from a base register. The consecutive memory locations start at this address, and teh address just above the last 3407// of those locations can optionally be written back to the base register. 3408bool 3409EmulateInstructionARM::EmulateSTM (ARMEncoding encoding) 3410{ 3411#if 0 3412 if ConditionPassed() then 3413 EncodingSpecificOperations(); NullCheckIfThumbEE(n); 3414 address = R[n]; 3415 3416 for i = 0 to 14 3417 if registers<i> == ’1’ then 3418 if i == n && wback && i != LowestSetBit(registers) then 3419 MemA[address,4] = bits(32) UNKNOWN; // Only possible for encodings T1 and A1 3420 else 3421 MemA[address,4] = R[i]; 3422 address = address + 4; 3423 3424 if registers<15> == ’1’ then // Only possible for encoding A1 3425 MemA[address,4] = PCStoreValue(); 3426 if wback then R[n] = R[n] + 4*BitCount(registers); 3427#endif 3428 3429 bool success = false; 3430 const uint32_t opcode = OpcodeAsUnsigned (&success); 3431 if (!success) 3432 return false; 3433 3434 if (ConditionPassed ()) 3435 { 3436 uint32_t n; 3437 uint32_t registers = 0; 3438 bool wback; 3439 const uint32_t addr_byte_size = GetAddressByteSize(); 3440 3441 // EncodingSpecificOperations(); NullCheckIfThumbEE(n); 3442 switch (encoding) 3443 { 3444 case eEncodingT1: 3445 // n = UInt(Rn); registers = ’00000000’:register_list; wback = TRUE; 3446 n = Bits32 (opcode, 10, 8); 3447 registers = Bits32 (opcode, 7, 0); 3448 registers = registers & 0x00ff; // Make sure the top 8 bits are zeros. 3449 wback = true; 3450 3451 // if BitCount(registers) < 1 then UNPREDICTABLE; 3452 if (BitCount (registers) < 1) 3453 return false; 3454 3455 break; 3456 3457 case eEncodingT2: 3458 // n = UInt(Rn); registers = ’0’:M:’0’:register_list; wback = (W == ’1’); 3459 n = Bits32 (opcode, 19, 16); 3460 registers = Bits32 (opcode, 15, 0); 3461 registers = registers & 0x5fff; // Make sure bits 15 & 13 are zeros. 3462 wback = BitIsSet (opcode, 21); 3463 3464 // if n == 15 || BitCount(registers) < 2 then UNPREDICTABLE; 3465 if ((n == 15) || (BitCount (registers) < 2)) 3466 return false; 3467 3468 // if wback && registers<n> == ’1’ then UNPREDICTABLE; 3469 if (wback && BitIsSet (registers, n)) 3470 return false; 3471 3472 break; 3473 3474 case eEncodingA1: 3475 // n = UInt(Rn); registers = register_list; wback = (W == ’1’); 3476 n = Bits32 (opcode, 19, 16); 3477 registers = Bits32 (opcode, 15, 0); 3478 wback = BitIsSet (opcode, 21); 3479 3480 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE; 3481 if ((n == 15) || (BitCount (registers) < 1)) 3482 return false; 3483 3484 break; 3485 3486 default: 3487 return false; 3488 } 3489 3490 // address = R[n]; 3491 int32_t offset = 0; 3492 const addr_t address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success); 3493 if (!success) 3494 return false; 3495 3496 EmulateInstruction::Context context; 3497 context.type = EmulateInstruction::eContextRegisterStore; 3498 Register base_reg; 3499 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n); 3500 3501 // for i = 0 to 14 3502 for (int i = 0; i < 14; ++i) 3503 { 3504 int lowest_set_bit = 14; 3505 // if registers<i> == ’1’ then 3506 if (BitIsSet (registers, i)) 3507 { 3508 if (i < lowest_set_bit) 3509 lowest_set_bit = i; 3510 // if i == n && wback && i != LowestSetBit(registers) then 3511 if ((i == n) && wback && (i != lowest_set_bit)) 3512 // MemA[address,4] = bits(32) UNKNOWN; // Only possible for encodings T1 and A1 3513 WriteBits32UnknownToMemory (address + offset); 3514 else 3515 { 3516 // MemA[address,4] = R[i]; 3517 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + i, 0, &success); 3518 if (!success) 3519 return false; 3520 3521 Register data_reg; 3522 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + i); 3523 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, offset); 3524 if (!MemAWrite (context, address + offset, data, addr_byte_size)) 3525 return false; 3526 } 3527 3528 // address = address + 4; 3529 offset += addr_byte_size; 3530 } 3531 } 3532 3533 // if registers<15> == ’1’ then // Only possible for encoding A1 3534 // MemA[address,4] = PCStoreValue(); 3535 if (BitIsSet (registers, 15)) 3536 { 3537 Register pc_reg; 3538 pc_reg.SetRegister (eRegisterKindDWARF, dwarf_pc); 3539 context.SetRegisterPlusOffset (pc_reg, 8); 3540 const uint32_t pc = ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success); 3541 if (!success) 3542 return false; 3543 3544 if (!MemAWrite (context, address + offset, pc + 8, addr_byte_size)) 3545 return false; 3546 } 3547 3548 // if wback then R[n] = R[n] + 4*BitCount(registers); 3549 if (wback) 3550 { 3551 offset = addr_byte_size * BitCount (registers); 3552 context.type = EmulateInstruction::eContextAdjustBaseRegister; 3553 context.SetImmediateSigned (offset); 3554 addr_t data = address + offset; 3555 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, data)) 3556 return false; 3557 } 3558 } 3559 return true; 3560} 3561 3562// STMDA (Store Multiple Decrement After) stores multiple registers to consecutive memory locations using an address 3563// from a base register. The consecutive memory locations end at this address, and the address just below the lowest 3564// of those locations can optionally be written back to the base register. 3565bool 3566EmulateInstructionARM::EmulateSTMDA (ARMEncoding encoding) 3567{ 3568#if 0 3569 if ConditionPassed() then 3570 EncodingSpecificOperations(); 3571 address = R[n] - 4*BitCount(registers) + 4; 3572 3573 for i = 0 to 14 3574 if registers<i> == ’1’ then 3575 if i == n && wback && i != LowestSetBit(registers) then 3576 MemA[address,4] = bits(32) UNKNOWN; 3577 else 3578 MemA[address,4] = R[i]; 3579 address = address + 4; 3580 3581 if registers<15> == ’1’ then 3582 MemA[address,4] = PCStoreValue(); 3583 3584 if wback then R[n] = R[n] - 4*BitCount(registers); 3585#endif 3586 3587 bool success = false; 3588 const uint32_t opcode = OpcodeAsUnsigned (&success); 3589 if (!success) 3590 return false; 3591 3592 if (ConditionPassed ()) 3593 { 3594 uint32_t n; 3595 uint32_t registers = 0; 3596 bool wback; 3597 const uint32_t addr_byte_size = GetAddressByteSize(); 3598 3599 // EncodingSpecificOperations(); 3600 switch (encoding) 3601 { 3602 case eEncodingA1: 3603 // n = UInt(Rn); registers = register_list; wback = (W == ’1’); 3604 n = Bits32 (opcode, 19, 16); 3605 registers = Bits32 (opcode, 15, 0); 3606 wback = BitIsSet (opcode, 21); 3607 3608 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE; 3609 if ((n == 15) || (BitCount (registers) < 1)) 3610 return false; 3611 break; 3612 default: 3613 return false; 3614 } 3615 3616 // address = R[n] - 4*BitCount(registers) + 4; 3617 int32_t offset = 0; 3618 addr_t address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success); 3619 if (!success) 3620 return false; 3621 3622 address = address - (addr_byte_size * BitCount (registers)) + 4; 3623 3624 EmulateInstruction::Context context; 3625 context.type = EmulateInstruction::eContextRegisterStore; 3626 Register base_reg; 3627 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n); 3628 3629 // for i = 0 to 14 3630 for (int i = 0; i < 14; ++i) 3631 { 3632 int lowest_bit_set = 14; 3633 // if registers<i> == ’1’ then 3634 if (BitIsSet (registers, i)) 3635 { 3636 if (i < lowest_bit_set) 3637 lowest_bit_set = i; 3638 //if i == n && wback && i != LowestSetBit(registers) then 3639 if ((i == n) && wback && (i != lowest_bit_set)) 3640 // MemA[address,4] = bits(32) UNKNOWN; 3641 WriteBits32UnknownToMemory (address + offset); 3642 else 3643 { 3644 // MemA[address,4] = R[i]; 3645 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + i, 0, &success); 3646 if (!success) 3647 return false; 3648 3649 Register data_reg; 3650 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + i); 3651 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, offset); 3652 if (!MemAWrite (context, address + offset, data, addr_byte_size)) 3653 return false; 3654 } 3655 3656 // address = address + 4; 3657 offset += addr_byte_size; 3658 } 3659 } 3660 3661 // if registers<15> == ’1’ then 3662 // MemA[address,4] = PCStoreValue(); 3663 if (BitIsSet (registers, 15)) 3664 { 3665 Register pc_reg; 3666 pc_reg.SetRegister (eRegisterKindDWARF, dwarf_pc); 3667 context.SetRegisterPlusOffset (pc_reg, 8); 3668 const uint32_t pc = ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success); 3669 if (!success) 3670 return false; 3671 3672 if (!MemAWrite (context, address + offset, pc + 8, addr_byte_size)) 3673 return false; 3674 } 3675 3676 // if wback then R[n] = R[n] - 4*BitCount(registers); 3677 if (wback) 3678 { 3679 offset = (addr_byte_size * BitCount (registers)) * -1; 3680 context.type = EmulateInstruction::eContextAdjustBaseRegister; 3681 context.SetImmediateSigned (offset); 3682 addr_t data = address + offset; 3683 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, data)) 3684 return false; 3685 } 3686 } 3687 return true; 3688} 3689 3690// STMDB (Store Multiple Decrement Before) stores multiple registers to consecutive memory locations using an address 3691// from a base register. The consecutive memory locations end just below this address, and the address of the first of 3692// those locations can optionally be written back to the base register. 3693bool 3694EmulateInstructionARM::EmulateSTMDB (ARMEncoding encoding) 3695{ 3696#if 0 3697 if ConditionPassed() then 3698 EncodingSpecificOperations(); NullCheckIfThumbEE(n); 3699 address = R[n] - 4*BitCount(registers); 3700 3701 for i = 0 to 14 3702 if registers<i> == ’1’ then 3703 if i == n && wback && i != LowestSetBit(registers) then 3704 MemA[address,4] = bits(32) UNKNOWN; // Only possible for encoding A1 3705 else 3706 MemA[address,4] = R[i]; 3707 address = address + 4; 3708 3709 if registers<15> == ’1’ then // Only possible for encoding A1 3710 MemA[address,4] = PCStoreValue(); 3711 3712 if wback then R[n] = R[n] - 4*BitCount(registers); 3713#endif 3714 3715 3716 bool success = false; 3717 const uint32_t opcode = OpcodeAsUnsigned (&success); 3718 if (!success) 3719 return false; 3720 3721 if (ConditionPassed ()) 3722 { 3723 uint32_t n; 3724 uint32_t registers = 0; 3725 bool wback; 3726 const uint32_t addr_byte_size = GetAddressByteSize(); 3727 3728 // EncodingSpecificOperations(); NullCheckIfThumbEE(n); 3729 switch (encoding) 3730 { 3731 case eEncodingT1: 3732 // if W == ’1’ && Rn == ’1101’ then SEE PUSH; 3733 if ((BitIsSet (opcode, 21)) && (Bits32 (opcode, 19, 16) == 13)) 3734 { 3735 // See PUSH 3736 } 3737 // n = UInt(Rn); registers = ’0’:M:’0’:register_list; wback = (W == ’1’); 3738 n = Bits32 (opcode, 19, 16); 3739 registers = Bits32 (opcode, 15, 0); 3740 registers = registers & 0x5fff; // Make sure bits 15 & 13 are zeros. 3741 wback = BitIsSet (opcode, 21); 3742 // if n == 15 || BitCount(registers) < 2 then UNPREDICTABLE; 3743 if ((n == 15) || BitCount (registers) < 2) 3744 return false; 3745 // if wback && registers<n> == ’1’ then UNPREDICTABLE; 3746 if (wback && BitIsSet (registers, n)) 3747 return false; 3748 break; 3749 3750 case eEncodingA1: 3751 // if W == ’1’ && Rn == ’1101’ && BitCount(register_list) >= 2 then SEE PUSH; 3752 if (BitIsSet (opcode, 21) && (Bits32 (opcode, 19, 16) == 13) && BitCount (Bits32 (opcode, 15, 0)) >= 2) 3753 { 3754 // See Push 3755 } 3756 // n = UInt(Rn); registers = register_list; wback = (W == ’1’); 3757 n = Bits32 (opcode, 19, 16); 3758 registers = Bits32 (opcode, 15, 0); 3759 wback = BitIsSet (opcode, 21); 3760 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE; 3761 if ((n == 15) || BitCount (registers) < 1) 3762 return false; 3763 break; 3764 3765 default: 3766 return false; 3767 } 3768 3769 // address = R[n] - 4*BitCount(registers); 3770 3771 int32_t offset = 0; 3772 addr_t address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success); 3773 if (!success) 3774 return false; 3775 3776 address = address - (addr_byte_size * BitCount (registers)); 3777 3778 EmulateInstruction::Context context; 3779 context.type = EmulateInstruction::eContextRegisterStore; 3780 Register base_reg; 3781 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n); 3782 3783 // for i = 0 to 14 3784 for (int i = 0; i < 14; ++i) 3785 { 3786 uint32_t lowest_set_bit = 14; 3787 // if registers<i> == ’1’ then 3788 if (BitIsSet (registers, i)) 3789 { 3790 if (i < lowest_set_bit) 3791 lowest_set_bit = i; 3792 // if i == n && wback && i != LowestSetBit(registers) then 3793 if ((i == n) && wback && (i != lowest_set_bit)) 3794 // MemA[address,4] = bits(32) UNKNOWN; // Only possible for encoding A1 3795 WriteBits32UnknownToMemory (address + offset); 3796 else 3797 { 3798 // MemA[address,4] = R[i]; 3799 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + i, 0, &success); 3800 if (!success) 3801 return false; 3802 3803 Register data_reg; 3804 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + i); 3805 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, offset); 3806 if (!MemAWrite (context, address + offset, data, addr_byte_size)) 3807 return false; 3808 } 3809 3810 // address = address + 4; 3811 offset += addr_byte_size; 3812 } 3813 } 3814 3815 // if registers<15> == ’1’ then // Only possible for encoding A1 3816 // MemA[address,4] = PCStoreValue(); 3817 if (BitIsSet (registers, 15)) 3818 { 3819 Register pc_reg; 3820 pc_reg.SetRegister (eRegisterKindDWARF, dwarf_pc); 3821 context.SetRegisterPlusOffset (pc_reg, 8); 3822 const uint32_t pc = ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success); 3823 if (!success) 3824 return false; 3825 3826 if (!MemAWrite (context, address + offset, pc + 8, addr_byte_size)) 3827 return false; 3828 } 3829 3830 // if wback then R[n] = R[n] - 4*BitCount(registers); 3831 if (wback) 3832 { 3833 offset = (addr_byte_size * BitCount (registers)) * -1; 3834 context.type = EmulateInstruction::eContextAdjustBaseRegister; 3835 context.SetImmediateSigned (offset); 3836 addr_t data = address + offset; 3837 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, data)) 3838 return false; 3839 } 3840 } 3841 return true; 3842} 3843 3844// STMIB (Store Multiple Increment Before) stores multiple registers to consecutive memory locations using an address 3845// from a base register. The consecutive memory locations start just above this address, and the address of the last 3846// of those locations can optionally be written back to the base register. 3847bool 3848EmulateInstructionARM::EmulateSTMIB (ARMEncoding encoding) 3849{ 3850#if 0 3851 if ConditionPassed() then 3852 EncodingSpecificOperations(); 3853 address = R[n] + 4; 3854 3855 for i = 0 to 14 3856 if registers<i> == ’1’ then 3857 if i == n && wback && i != LowestSetBit(registers) then 3858 MemA[address,4] = bits(32) UNKNOWN; 3859 else 3860 MemA[address,4] = R[i]; 3861 address = address + 4; 3862 3863 if registers<15> == ’1’ then 3864 MemA[address,4] = PCStoreValue(); 3865 3866 if wback then R[n] = R[n] + 4*BitCount(registers); 3867#endif 3868 3869 bool success = false; 3870 const uint32_t opcode = OpcodeAsUnsigned (&success); 3871 if (!success) 3872 return false; 3873 3874 if (ConditionPassed()) 3875 { 3876 uint32_t n; 3877 uint32_t registers = 0; 3878 bool wback; 3879 const uint32_t addr_byte_size = GetAddressByteSize(); 3880 3881 // EncodingSpecificOperations(); 3882 switch (encoding) 3883 { 3884 case eEncodingA1: 3885 // n = UInt(Rn); registers = register_list; wback = (W == ’1’); 3886 n = Bits32 (opcode, 19, 16); 3887 registers = Bits32 (opcode, 15, 0); 3888 wback = BitIsSet (opcode, 21); 3889 3890 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE; 3891 if ((n == 15) && (BitCount (registers) < 1)) 3892 return false; 3893 break; 3894 default: 3895 return false; 3896 } 3897 // address = R[n] + 4; 3898 3899 int32_t offset = 0; 3900 addr_t address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success); 3901 if (!success) 3902 return false; 3903 3904 address = address + addr_byte_size; 3905 3906 EmulateInstruction::Context context; 3907 context.type = EmulateInstruction::eContextRegisterStore; 3908 Register base_reg; 3909 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n); 3910 3911 uint32_t lowest_set_bit = 14; 3912 // for i = 0 to 14 3913 for (int i = 0; i < 14; ++i) 3914 { 3915 // if registers<i> == ’1’ then 3916 if (BitIsSet (registers, i)) 3917 { 3918 if (i < lowest_set_bit) 3919 lowest_set_bit = i; 3920 // if i == n && wback && i != LowestSetBit(registers) then 3921 if ((i == n) && wback && (i != lowest_set_bit)) 3922 // MemA[address,4] = bits(32) UNKNOWN; 3923 WriteBits32UnknownToMemory (address + offset); 3924 // else 3925 else 3926 { 3927 // MemA[address,4] = R[i]; 3928 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + i, 0, &success); 3929 if (!success) 3930 return false; 3931 3932 Register data_reg; 3933 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + i); 3934 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, offset); 3935 if (!MemAWrite (context, address + offset, data, addr_byte_size)) 3936 return false; 3937 } 3938 3939 // address = address + 4; 3940 offset += addr_byte_size; 3941 } 3942 } 3943 3944 // if registers<15> == ’1’ then 3945 // MemA[address,4] = PCStoreValue(); 3946 if (BitIsSet (registers, 15)) 3947 { 3948 Register pc_reg; 3949 pc_reg.SetRegister (eRegisterKindDWARF, dwarf_pc); 3950 context.SetRegisterPlusOffset (pc_reg, 8); 3951 const uint32_t pc = ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success); 3952 if (!success) 3953 return false; 3954 3955 if (!MemAWrite (context, address + offset, pc + 8, addr_byte_size)) 3956 return false; 3957 } 3958 3959 // if wback then R[n] = R[n] + 4*BitCount(registers); 3960 if (wback) 3961 { 3962 offset = addr_byte_size * BitCount (registers); 3963 context.type = EmulateInstruction::eContextAdjustBaseRegister; 3964 context.SetImmediateSigned (offset); 3965 addr_t data = address + offset; 3966 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, data)) 3967 return false; 3968 } 3969 } 3970 return true; 3971} 3972 3973// STR (store immediate) calcualtes an address from a base register value and an immediate offset, and stores a word 3974// from a register to memory. It can use offset, post-indexed, or pre-indexed addressing. 3975bool 3976EmulateInstructionARM::EmulateSTRThumb (ARMEncoding encoding) 3977{ 3978#if 0 3979 if ConditionPassed() then 3980 EncodingSpecificOperations(); NullCheckIfThumbEE(n); 3981 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32); 3982 address = if index then offset_addr else R[n]; 3983 if UnalignedSupport() || address<1:0> == ’00’ then 3984 MemU[address,4] = R[t]; 3985 else // Can only occur before ARMv7 3986 MemU[address,4] = bits(32) UNKNOWN; 3987 if wback then R[n] = offset_addr; 3988#endif 3989 3990 bool success = false; 3991 const uint32_t opcode = OpcodeAsUnsigned (&success); 3992 if (!success) 3993 return false; 3994 3995 if (ConditionPassed()) 3996 { 3997 const uint32_t addr_byte_size = GetAddressByteSize(); 3998 3999 uint32_t t; 4000 uint32_t n; 4001 uint32_t imm32; 4002 bool index; 4003 bool add; 4004 bool wback; 4005 // EncodingSpecificOperations (); NullCheckIfThumbEE(n); 4006 switch (encoding) 4007 { 4008 case eEncodingT1: 4009 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm5:’00’, 32); 4010 t = Bits32 (opcode, 2, 0); 4011 n = Bits32 (opcode, 5, 3); 4012 imm32 = Bits32 (opcode, 10, 6) << 2; 4013 4014 // index = TRUE; add = TRUE; wback = FALSE; 4015 index = true; 4016 add = false; 4017 wback = false; 4018 break; 4019 4020 case eEncodingT2: 4021 // t = UInt(Rt); n = 13; imm32 = ZeroExtend(imm8:’00’, 32); 4022 t = Bits32 (opcode, 10, 8); 4023 n = 13; 4024 imm32 = Bits32 (opcode, 7, 0) << 2; 4025 4026 // index = TRUE; add = TRUE; wback = FALSE; 4027 index = true; 4028 add = true; 4029 wback = false; 4030 break; 4031 4032 case eEncodingT3: 4033 // if Rn == ’1111’ then UNDEFINED; 4034 if (Bits32 (opcode, 19, 16) == 15) 4035 return false; 4036 4037 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32); 4038 t = Bits32 (opcode, 15, 12); 4039 n = Bits32 (opcode, 19, 16); 4040 imm32 = Bits32 (opcode, 11, 0); 4041 4042 // index = TRUE; add = TRUE; wback = FALSE; 4043 index = true; 4044 add = true; 4045 wback = false; 4046 4047 // if t == 15 then UNPREDICTABLE; 4048 if (t == 15) 4049 return false; 4050 break; 4051 4052 case eEncodingT4: 4053 // if P == ’1’ && U == ’1’ && W == ’0’ then SEE STRT; 4054 // if Rn == ’1101’ && P == ’1’ && U == ’0’ && W == ’1’ && imm8 == ’00000100’ then SEE PUSH; 4055 // if Rn == ’1111’ || (P == ’0’ && W == ’0’) then UNDEFINED; 4056 if ((Bits32 (opcode, 19, 16) == 15) 4057 || (BitIsClear (opcode, 10) && BitIsClear (opcode, 8))) 4058 return false; 4059 4060 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32); 4061 t = Bits32 (opcode, 15, 12); 4062 n = Bits32 (opcode, 19, 16); 4063 imm32 = Bits32 (opcode, 7, 0); 4064 4065 // index = (P == ’1’); add = (U == ’1’); wback = (W == ’1’); 4066 index = BitIsSet (opcode, 10); 4067 add = BitIsSet (opcode, 9); 4068 wback = BitIsSet (opcode, 8); 4069 4070 // if t == 15 || (wback && n == t) then UNPREDICTABLE; 4071 if ((t == 15) || (wback && (n == t))) 4072 return false; 4073 break; 4074 4075 default: 4076 return false; 4077 } 4078 4079 addr_t offset_addr; 4080 addr_t address; 4081 4082 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32); 4083 uint32_t base_address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success); 4084 if (!success) 4085 return false; 4086 4087 if (add) 4088 offset_addr = base_address + imm32; 4089 else 4090 offset_addr = base_address - imm32; 4091 4092 // address = if index then offset_addr else R[n]; 4093 if (index) 4094 address = offset_addr; 4095 else 4096 address = base_address; 4097 4098 EmulateInstruction::Context context; 4099 context.type = eContextRegisterStore; 4100 Register base_reg; 4101 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n); 4102 4103 // if UnalignedSupport() || address<1:0> == ’00’ then 4104 if (UnalignedSupport () || (BitIsClear (address, 1) && BitIsClear (address, 0))) 4105 { 4106 // MemU[address,4] = R[t]; 4107 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + t, 0, &success); 4108 if (!success) 4109 return false; 4110 4111 Register data_reg; 4112 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + t); 4113 int32_t offset = address - base_address; 4114 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, offset); 4115 if (!MemUWrite (context, address, data, addr_byte_size)) 4116 return false; 4117 } 4118 else 4119 { 4120 // MemU[address,4] = bits(32) UNKNOWN; 4121 WriteBits32UnknownToMemory (address); 4122 } 4123 4124 // if wback then R[n] = offset_addr; 4125 if (wback) 4126 { 4127 context.type = eContextRegisterLoad; 4128 context.SetAddress (offset_addr); 4129 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr)) 4130 return false; 4131 } 4132 } 4133 return true; 4134} 4135 4136// STR (Store Register) calculates an address from a base register value and an offset register value, stores a 4137// word from a register to memory. The offset register value can optionally be shifted. 4138bool 4139EmulateInstructionARM::EmulateSTRRegister (ARMEncoding encoding) 4140{ 4141#if 0 4142 if ConditionPassed() then 4143 EncodingSpecificOperations(); NullCheckIfThumbEE(n); 4144 offset = Shift(R[m], shift_t, shift_n, APSR.C); 4145 offset_addr = if add then (R[n] + offset) else (R[n] - offset); 4146 address = if index then offset_addr else R[n]; 4147 if t == 15 then // Only possible for encoding A1 4148 data = PCStoreValue(); 4149 else 4150 data = R[t]; 4151 if UnalignedSupport() || address<1:0> == ’00’ || CurrentInstrSet() == InstrSet_ARM then 4152 MemU[address,4] = data; 4153 else // Can only occur before ARMv7 4154 MemU[address,4] = bits(32) UNKNOWN; 4155 if wback then R[n] = offset_addr; 4156#endif 4157 4158 bool success = false; 4159 const uint32_t opcode = OpcodeAsUnsigned (&success); 4160 if (!success) 4161 return false; 4162 4163 if (ConditionPassed()) 4164 { 4165 const uint32_t addr_byte_size = GetAddressByteSize(); 4166 4167 uint32_t t; 4168 uint32_t n; 4169 uint32_t m; 4170 ARM_ShifterType shift_t; 4171 uint32_t shift_n; 4172 bool index; 4173 bool add; 4174 bool wback; 4175 4176 // EncodingSpecificOperations (); NullCheckIfThumbEE(n); 4177 switch (encoding) 4178 { 4179 case eEncodingT1: 4180 // if CurrentInstrSet() == InstrSet_ThumbEE then SEE "Modified operation in ThumbEE"; 4181 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm); 4182 t = Bits32 (opcode, 2, 0); 4183 n = Bits32 (opcode, 5, 3); 4184 m = Bits32 (opcode, 8, 6); 4185 4186 // index = TRUE; add = TRUE; wback = FALSE; 4187 index = true; 4188 add = true; 4189 wback = false; 4190 4191 // (shift_t, shift_n) = (SRType_LSL, 0); 4192 shift_t = SRType_LSL; 4193 shift_n = 0; 4194 break; 4195 4196 case eEncodingT2: 4197 // if Rn == ’1111’ then UNDEFINED; 4198 if (Bits32 (opcode, 19, 16) == 15) 4199 return false; 4200 4201 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm); 4202 t = Bits32 (opcode, 15, 12); 4203 n = Bits32 (opcode, 19, 16); 4204 m = Bits32 (opcode, 3, 0); 4205 4206 // index = TRUE; add = TRUE; wback = FALSE; 4207 index = true; 4208 add = true; 4209 wback = false; 4210 4211 // (shift_t, shift_n) = (SRType_LSL, UInt(imm2)); 4212 shift_t = SRType_LSL; 4213 shift_n = Bits32 (opcode, 5, 4); 4214 4215 // if t == 15 || BadReg(m) then UNPREDICTABLE; 4216 if ((t == 15) || (BadReg (m))) 4217 return false; 4218 break; 4219 4220 case eEncodingA1: 4221 { 4222 // if P == ’0’ && W == ’1’ then SEE STRT; 4223 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm); 4224 t = Bits32 (opcode, 15, 12); 4225 n = Bits32 (opcode, 19, 16); 4226 m = Bits32 (opcode, 3, 0); 4227 4228 // index = (P == ’1’); add = (U == ’1’); wback = (P == ’0’) || (W == ’1’); 4229 index = BitIsSet (opcode, 24); 4230 add = BitIsSet (opcode, 23); 4231 wback = (BitIsClear (opcode, 24) || BitIsSet (opcode, 21)); 4232 4233 // (shift_t, shift_n) = DecodeImmShift(type, imm5); 4234 uint32_t typ = Bits32 (opcode, 6, 5); 4235 uint32_t imm5 = Bits32 (opcode, 11, 7); 4236 shift_n = DecodeImmShift(typ, imm5, shift_t); 4237 4238 // if m == 15 then UNPREDICTABLE; 4239 if (m == 15) 4240 return false; 4241 4242 // if wback && (n == 15 || n == t) then UNPREDICTABLE; 4243 if (wback && ((n == 15) || (n == t))) 4244 return false; 4245 4246 break; 4247 } 4248 default: 4249 return false; 4250 } 4251 4252 addr_t offset_addr; 4253 addr_t address; 4254 int32_t offset = 0; 4255 4256 addr_t base_address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success); 4257 if (!success) 4258 return false; 4259 4260 uint32_t Rm_data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success); 4261 if (!success) 4262 return false; 4263 4264 // offset = Shift(R[m], shift_t, shift_n, APSR.C); 4265 offset = Shift (Rm_data, shift_t, shift_n, APSR_C); 4266 4267 // offset_addr = if add then (R[n] + offset) else (R[n] - offset); 4268 if (add) 4269 offset_addr = base_address + offset; 4270 else 4271 offset_addr = base_address - offset; 4272 4273 // address = if index then offset_addr else R[n]; 4274 if (index) 4275 address = offset_addr; 4276 else 4277 address = base_address; 4278 4279 uint32_t data; 4280 // if t == 15 then // Only possible for encoding A1 4281 if (t == 15) 4282 // data = PCStoreValue(); 4283 data = ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success); 4284 else 4285 // data = R[t]; 4286 data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + t, 0, &success); 4287 4288 if (!success) 4289 return false; 4290 4291 EmulateInstruction::Context context; 4292 context.type = eContextRegisterStore; 4293 4294 // if UnalignedSupport() || address<1:0> == ’00’ || CurrentInstrSet() == InstrSet_ARM then 4295 if (UnalignedSupport () 4296 || (BitIsClear (address, 1) && BitIsClear (address, 0)) 4297 || CurrentInstrSet() == eModeARM) 4298 { 4299 // MemU[address,4] = data; 4300 4301 Register base_reg; 4302 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n); 4303 4304 Register data_reg; 4305 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + t); 4306 4307 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, address - base_address); 4308 if (!MemUWrite (context, address, data, addr_byte_size)) 4309 return false; 4310 4311 } 4312 else 4313 // MemU[address,4] = bits(32) UNKNOWN; 4314 WriteBits32UnknownToMemory (address); 4315 4316 // if wback then R[n] = offset_addr; 4317 if (wback) 4318 { 4319 context.type = eContextRegisterLoad; 4320 context.SetAddress (offset_addr); 4321 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr)) 4322 return false; 4323 } 4324 4325 } 4326 return true; 4327} 4328 4329bool 4330EmulateInstructionARM::EmulateSTRBThumb (ARMEncoding encoding) 4331{ 4332#if 0 4333 if ConditionPassed() then 4334 EncodingSpecificOperations(); NullCheckIfThumbEE(n); 4335 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32); 4336 address = if index then offset_addr else R[n]; 4337 MemU[address,1] = R[t]<7:0>; 4338 if wback then R[n] = offset_addr; 4339#endif 4340 4341 4342 bool success = false; 4343 const uint32_t opcode = OpcodeAsUnsigned (&success); 4344 if (!success) 4345 return false; 4346 4347 if (ConditionPassed ()) 4348 { 4349 uint32_t t; 4350 uint32_t n; 4351 uint32_t imm32; 4352 bool index; 4353 bool add; 4354 bool wback; 4355 // EncodingSpecificOperations(); NullCheckIfThumbEE(n); 4356 switch (encoding) 4357 { 4358 case eEncodingT1: 4359 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm5, 32); 4360 t = Bits32 (opcode, 2, 0); 4361 n = Bits32 (opcode, 5, 3); 4362 imm32 = Bits32 (opcode, 10, 6); 4363 4364 // index = TRUE; add = TRUE; wback = FALSE; 4365 index = true; 4366 add = true; 4367 wback = false; 4368 break; 4369 4370 case eEncodingT2: 4371 // if Rn == ’1111’ then UNDEFINED; 4372 if (Bits32 (opcode, 19, 16) == 15) 4373 return false; 4374 4375 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32); 4376 t = Bits32 (opcode, 15, 12); 4377 n = Bits32 (opcode, 19, 16); 4378 imm32 = Bits32 (opcode, 11, 0); 4379 4380 // index = TRUE; add = TRUE; wback = FALSE; 4381 index = true; 4382 add = true; 4383 wback = false; 4384 4385 // if BadReg(t) then UNPREDICTABLE; 4386 if (BadReg (t)) 4387 return false; 4388 break; 4389 4390 case eEncodingT3: 4391 // if P == ’1’ && U == ’1’ && W == ’0’ then SEE STRBT; 4392 // if Rn == ’1111’ || (P == ’0’ && W == ’0’) then UNDEFINED; 4393 if (Bits32 (opcode, 19, 16) == 15) 4394 return false; 4395 4396 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32); 4397 t = Bits32 (opcode, 15, 12); 4398 n = Bits32 (opcode, 19, 16); 4399 imm32 = Bits32 (opcode, 7, 0); 4400 4401 // index = (P == ’1’); add = (U == ’1’); wback = (W == ’1’); 4402 index = BitIsSet (opcode, 10); 4403 add = BitIsSet (opcode, 9); 4404 wback = BitIsSet (opcode, 8); 4405 4406 // if BadReg(t) || (wback && n == t) then UNPREDICTABLE 4407 if ((BadReg (t)) || (wback && (n == t))) 4408 return false; 4409 break; 4410 4411 default: 4412 return false; 4413 } 4414 4415 addr_t offset_addr; 4416 addr_t address; 4417 addr_t base_address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success); 4418 if (!success) 4419 return false; 4420 4421 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32); 4422 if (add) 4423 offset_addr = base_address + imm32; 4424 else 4425 offset_addr = base_address - imm32; 4426 4427 // address = if index then offset_addr else R[n]; 4428 if (index) 4429 address = offset_addr; 4430 else 4431 address = base_address; 4432 4433 // MemU[address,1] = R[t]<7:0> 4434 Register base_reg; 4435 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n); 4436 4437 Register data_reg; 4438 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + t); 4439 4440 EmulateInstruction::Context context; 4441 context.type = eContextRegisterStore; 4442 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, address - base_address); 4443 4444 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + t, 0, &success); 4445 if (!success) 4446 return false; 4447 4448 data = Bits32 (data, 7, 0); 4449 4450 if (!MemUWrite (context, address, data, 1)) 4451 return false; 4452 4453 // if wback then R[n] = offset_addr; 4454 if (wback) 4455 { 4456 context.type = eContextRegisterLoad; 4457 context.SetAddress (offset_addr); 4458 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr)) 4459 return false; 4460 } 4461 4462 } 4463 4464 return true; 4465} 4466 4467// Add with Carry (immediate) adds an immediate value and the carry flag value to a register value, 4468// and writes the result to the destination register. It can optionally update the condition flags 4469// based on the result. 4470bool 4471EmulateInstructionARM::EmulateADCImm (ARMEncoding encoding) 4472{ 4473#if 0 4474 // ARM pseudo code... 4475 if ConditionPassed() then 4476 EncodingSpecificOperations(); 4477 (result, carry, overflow) = AddWithCarry(R[n], imm32, APSR.C); 4478 if d == 15 then // Can only occur for ARM encoding 4479 ALUWritePC(result); // setflags is always FALSE here 4480 else 4481 R[d] = result; 4482 if setflags then 4483 APSR.N = result<31>; 4484 APSR.Z = IsZeroBit(result); 4485 APSR.C = carry; 4486 APSR.V = overflow; 4487#endif 4488 4489 bool success = false; 4490 const uint32_t opcode = OpcodeAsUnsigned (&success); 4491 if (!success) 4492 return false; 4493 4494 if (ConditionPassed()) 4495 { 4496 uint32_t Rd, Rn; 4497 uint32_t imm32; // the immediate value to be added to the value obtained from Rn 4498 bool setflags; 4499 switch (encoding) 4500 { 4501 case eEncodingT1: 4502 Rd = Bits32(opcode, 11, 8); 4503 Rn = Bits32(opcode, 19, 16); 4504 setflags = BitIsSet(opcode, 20); 4505 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8) 4506 if (BadReg(Rd) || BadReg(Rn)) 4507 return false; 4508 break; 4509 case eEncodingA1: 4510 Rd = Bits32(opcode, 15, 12); 4511 Rn = Bits32(opcode, 19, 16); 4512 setflags = BitIsSet(opcode, 20); 4513 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12) 4514 // TODO: Emulate SUBS PC, LR and related instructions. 4515 if (Rd == 15 && setflags) 4516 return false; 4517 break; 4518 default: 4519 return false; 4520 } 4521 4522 // Read the first operand. 4523 int32_t val1 = ReadCoreReg(Rn, &success); 4524 if (!success) 4525 return false; 4526 4527 AddWithCarryResult res = AddWithCarry(val1, imm32, APSR_C); 4528 4529 EmulateInstruction::Context context; 4530 context.type = EmulateInstruction::eContextImmediate; 4531 context.SetNoArgs (); 4532 4533 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow)) 4534 return false; 4535 } 4536 return true; 4537} 4538 4539// Add with Carry (register) adds a register value, the carry flag value, and an optionally-shifted 4540// register value, and writes the result to the destination register. It can optionally update the 4541// condition flags based on the result. 4542bool 4543EmulateInstructionARM::EmulateADCReg (ARMEncoding encoding) 4544{ 4545#if 0 4546 // ARM pseudo code... 4547 if ConditionPassed() then 4548 EncodingSpecificOperations(); 4549 shifted = Shift(R[m], shift_t, shift_n, APSR.C); 4550 (result, carry, overflow) = AddWithCarry(R[n], shifted, APSR.C); 4551 if d == 15 then // Can only occur for ARM encoding 4552 ALUWritePC(result); // setflags is always FALSE here 4553 else 4554 R[d] = result; 4555 if setflags then 4556 APSR.N = result<31>; 4557 APSR.Z = IsZeroBit(result); 4558 APSR.C = carry; 4559 APSR.V = overflow; 4560#endif 4561 4562 bool success = false; 4563 const uint32_t opcode = OpcodeAsUnsigned (&success); 4564 if (!success) 4565 return false; 4566 4567 if (ConditionPassed()) 4568 { 4569 uint32_t Rd, Rn, Rm; 4570 ARM_ShifterType shift_t; 4571 uint32_t shift_n; // the shift applied to the value read from Rm 4572 bool setflags; 4573 switch (encoding) 4574 { 4575 case eEncodingT1: 4576 Rd = Rn = Bits32(opcode, 2, 0); 4577 Rm = Bits32(opcode, 5, 3); 4578 setflags = !InITBlock(); 4579 shift_t = SRType_LSL; 4580 shift_n = 0; 4581 case eEncodingT2: 4582 Rd = Bits32(opcode, 11, 8); 4583 Rn = Bits32(opcode, 19, 16); 4584 Rm = Bits32(opcode, 3, 0); 4585 setflags = BitIsSet(opcode, 20); 4586 shift_n = DecodeImmShift(Bits32(opcode, 5, 4), Bits32(opcode, 14, 12)<<2 | Bits32(opcode, 7, 6), shift_t); 4587 if (BadReg(Rd) || BadReg(Rn) || BadReg(Rm)) 4588 return false; 4589 break; 4590 case eEncodingA1: 4591 Rd = Bits32(opcode, 15, 12); 4592 Rn = Bits32(opcode, 19, 16); 4593 Rm = Bits32(opcode, 3, 0); 4594 setflags = BitIsSet(opcode, 20); 4595 shift_n = DecodeImmShift(Bits32(opcode, 6, 5), Bits32(opcode, 11, 7), shift_t); 4596 // TODO: Emulate SUBS PC, LR and related instructions. 4597 if (Rd == 15 && setflags) 4598 return false; 4599 break; 4600 default: 4601 return false; 4602 } 4603 4604 // Read the first operand. 4605 int32_t val1 = ReadCoreReg(Rn, &success); 4606 if (!success) 4607 return false; 4608 4609 // Read the second operand. 4610 int32_t val2 = ReadCoreReg(Rm, &success); 4611 if (!success) 4612 return false; 4613 4614 uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C); 4615 AddWithCarryResult res = AddWithCarry(val1, shifted, APSR_C); 4616 4617 EmulateInstruction::Context context; 4618 context.type = EmulateInstruction::eContextImmediate; 4619 context.SetNoArgs (); 4620 4621 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow)) 4622 return false; 4623 } 4624 return true; 4625} 4626 4627// This instruction performs a bitwise AND of a register value and an immediate value, and writes the result 4628// to the destination register. It can optionally update the condition flags based on the result. 4629bool 4630EmulateInstructionARM::EmulateANDImm (ARMEncoding encoding) 4631{ 4632#if 0 4633 // ARM pseudo code... 4634 if ConditionPassed() then 4635 EncodingSpecificOperations(); 4636 result = R[n] AND imm32; 4637 if d == 15 then // Can only occur for ARM encoding 4638 ALUWritePC(result); // setflags is always FALSE here 4639 else 4640 R[d] = result; 4641 if setflags then 4642 APSR.N = result<31>; 4643 APSR.Z = IsZeroBit(result); 4644 APSR.C = carry; 4645 // APSR.V unchanged 4646#endif 4647 4648 bool success = false; 4649 const uint32_t opcode = OpcodeAsUnsigned (&success); 4650 if (!success) 4651 return false; 4652 4653 if (ConditionPassed()) 4654 { 4655 uint32_t Rd, Rn; 4656 uint32_t imm32; // the immediate value to be ANDed to the value obtained from Rn 4657 bool setflags; 4658 uint32_t carry; // the carry bit after ARM/Thumb Expand operation 4659 switch (encoding) 4660 { 4661 case eEncodingT1: 4662 Rd = Bits32(opcode, 11, 8); 4663 Rn = Bits32(opcode, 19, 16); 4664 setflags = BitIsSet(opcode, 20); 4665 imm32 = ThumbExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C) 4666 // if Rd == '1111' && S == '1' then SEE TST (immediate); 4667 if (Rd == 15 && setflags) 4668 return EmulateTSTImm(eEncodingT1); 4669 if (Rd == 13 || (Rd == 15 && !setflags) || BadReg(Rn)) 4670 return false; 4671 break; 4672 case eEncodingA1: 4673 Rd = Bits32(opcode, 15, 12); 4674 Rn = Bits32(opcode, 19, 16); 4675 setflags = BitIsSet(opcode, 20); 4676 imm32 = ARMExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ARMExpandImm(imm12, APSR.C) 4677 // TODO: Emulate SUBS PC, LR and related instructions. 4678 if (Rd == 15 && setflags) 4679 return false; 4680 break; 4681 default: 4682 return false; 4683 } 4684 4685 // Read the first operand. 4686 uint32_t val1 = ReadCoreReg(Rn, &success); 4687 if (!success) 4688 return false; 4689 4690 uint32_t result = val1 & imm32; 4691 4692 EmulateInstruction::Context context; 4693 context.type = EmulateInstruction::eContextImmediate; 4694 context.SetNoArgs (); 4695 4696 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry)) 4697 return false; 4698 } 4699 return true; 4700} 4701 4702// This instruction performs a bitwise AND of a register value and an optionally-shifted register value, 4703// and writes the result to the destination register. It can optionally update the condition flags 4704// based on the result. 4705bool 4706EmulateInstructionARM::EmulateANDReg (ARMEncoding encoding) 4707{ 4708#if 0 4709 // ARM pseudo code... 4710 if ConditionPassed() then 4711 EncodingSpecificOperations(); 4712 (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C); 4713 result = R[n] AND shifted; 4714 if d == 15 then // Can only occur for ARM encoding 4715 ALUWritePC(result); // setflags is always FALSE here 4716 else 4717 R[d] = result; 4718 if setflags then 4719 APSR.N = result<31>; 4720 APSR.Z = IsZeroBit(result); 4721 APSR.C = carry; 4722 // APSR.V unchanged 4723#endif 4724 4725 bool success = false; 4726 const uint32_t opcode = OpcodeAsUnsigned (&success); 4727 if (!success) 4728 return false; 4729 4730 if (ConditionPassed()) 4731 { 4732 uint32_t Rd, Rn, Rm; 4733 ARM_ShifterType shift_t; 4734 uint32_t shift_n; // the shift applied to the value read from Rm 4735 bool setflags; 4736 uint32_t carry; 4737 switch (encoding) 4738 { 4739 case eEncodingT1: 4740 Rd = Rn = Bits32(opcode, 2, 0); 4741 Rm = Bits32(opcode, 5, 3); 4742 setflags = !InITBlock(); 4743 shift_t = SRType_LSL; 4744 shift_n = 0; 4745 case eEncodingT2: 4746 Rd = Bits32(opcode, 11, 8); 4747 Rn = Bits32(opcode, 19, 16); 4748 Rm = Bits32(opcode, 3, 0); 4749 setflags = BitIsSet(opcode, 20); 4750 shift_n = DecodeImmShift(Bits32(opcode, 5, 4), Bits32(opcode, 14, 12)<<2 | Bits32(opcode, 7, 6), shift_t); 4751 // if Rd == '1111' && S == '1' then SEE TST (register); 4752 if (Rd == 15 && setflags) 4753 return EmulateTSTReg(eEncodingT2); 4754 if (Rd == 13 || (Rd == 15 && !setflags) || BadReg(Rn) || BadReg(Rm)) 4755 return false; 4756 break; 4757 case eEncodingA1: 4758 Rd = Bits32(opcode, 15, 12); 4759 Rn = Bits32(opcode, 19, 16); 4760 Rm = Bits32(opcode, 3, 0); 4761 setflags = BitIsSet(opcode, 20); 4762 shift_n = DecodeImmShift(Bits32(opcode, 6, 5), Bits32(opcode, 11, 7), shift_t); 4763 // TODO: Emulate SUBS PC, LR and related instructions. 4764 if (Rd == 15 && setflags) 4765 return false; 4766 break; 4767 default: 4768 return false; 4769 } 4770 4771 // Read the first operand. 4772 uint32_t val1 = ReadCoreReg(Rn, &success); 4773 if (!success) 4774 return false; 4775 4776 // Read the second operand. 4777 uint32_t val2 = ReadCoreReg(Rm, &success); 4778 if (!success) 4779 return false; 4780 4781 uint32_t shifted = Shift_C(val2, shift_t, shift_n, APSR_C, carry); 4782 uint32_t result = val1 & shifted; 4783 4784 EmulateInstruction::Context context; 4785 context.type = EmulateInstruction::eContextImmediate; 4786 context.SetNoArgs (); 4787 4788 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry)) 4789 return false; 4790 } 4791 return true; 4792} 4793 4794// LDR (immediate, ARM) calculates an address from a base register value and an immediate offset, loads a word 4795// from memory, and writes it to a register. It can use offset, post-indexed, or pre-indexed addressing. 4796bool 4797EmulateInstructionARM::EmulateLDRImmediateARM (ARMEncoding encoding) 4798{ 4799#if 0 4800 if ConditionPassed() then 4801 EncodingSpecificOperations(); 4802 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32); 4803 address = if index then offset_addr else R[n]; 4804 data = MemU[address,4]; 4805 if wback then R[n] = offset_addr; 4806 if t == 15 then 4807 if address<1:0> == ’00’ then LoadWritePC(data); else UNPREDICTABLE; 4808 elsif UnalignedSupport() || address<1:0> = ’00’ then 4809 R[t] = data; 4810 else // Can only apply before ARMv7 4811 R[t] = ROR(data, 8*UInt(address<1:0>)); 4812#endif 4813 4814 bool success = false; 4815 const uint32_t opcode = OpcodeAsUnsigned (&success); 4816 if (!success) 4817 return false; 4818 4819 if (ConditionPassed ()) 4820 { 4821 const uint32_t addr_byte_size = GetAddressByteSize(); 4822 4823 uint32_t t; 4824 uint32_t n; 4825 uint32_t imm32; 4826 bool index; 4827 bool add; 4828 bool wback; 4829 4830 switch (encoding) 4831 { 4832 case eEncodingA1: 4833 // if Rn == ’1111’ then SEE LDR (literal); 4834 // if P == ’0’ && W == ’1’ then SEE LDRT; 4835 // if Rn == ’1101’ && P == ’0’ && U == ’1’ && W == ’0’ && imm12 == ’000000000100’ then SEE POP; 4836 // t == UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32); 4837 t = Bits32 (opcode, 15, 12); 4838 n = Bits32 (opcode, 19, 16); 4839 imm32 = Bits32 (opcode, 11, 0); 4840 4841 // index = (P == ’1’); add = (U == ’1’); wback = (P == ’0’) || (W == ’1’); 4842 index = BitIsSet (opcode, 24); 4843 add = BitIsSet (opcode, 23); 4844 wback = (BitIsClear (opcode, 24) || BitIsSet (opcode, 21)); 4845 4846 // if wback && n == t then UNPREDICTABLE; 4847 if (wback && (n == t)) 4848 return false; 4849 4850 break; 4851 4852 default: 4853 return false; 4854 } 4855 4856 addr_t address; 4857 addr_t offset_addr; 4858 addr_t base_address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success); 4859 if (!success) 4860 return false; 4861 4862 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32); 4863 if (add) 4864 offset_addr = base_address + imm32; 4865 else 4866 offset_addr = base_address - imm32; 4867 4868 // address = if index then offset_addr else R[n]; 4869 if (index) 4870 address = offset_addr; 4871 else 4872 address = base_address; 4873 4874 // data = MemU[address,4]; 4875 4876 Register base_reg; 4877 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n); 4878 4879 EmulateInstruction::Context context; 4880 context.type = eContextRegisterLoad; 4881 context.SetRegisterPlusOffset (base_reg, address - base_address); 4882 4883 uint64_t data = MemURead (context, address, addr_byte_size, 0, &success); 4884 if (!success) 4885 return false; 4886 4887 // if wback then R[n] = offset_addr; 4888 if (wback) 4889 { 4890 context.type = eContextAdjustBaseRegister; 4891 context.SetAddress (offset_addr); 4892 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr)) 4893 return false; 4894 } 4895 4896 // if t == 15 then 4897 if (t == 15) 4898 { 4899 // if address<1:0> == ’00’ then LoadWritePC(data); else UNPREDICTABLE; 4900 if (BitIsClear (address, 1) && BitIsClear (address, 0)) 4901 { 4902 // LoadWritePC (data); 4903 context.type = eContextRegisterLoad; 4904 context.SetRegisterPlusOffset (base_reg, address - base_address); 4905 LoadWritePC (context, data); 4906 } 4907 else 4908 return false; 4909 } 4910 // elsif UnalignedSupport() || address<1:0> = ’00’ then 4911 else if (UnalignedSupport() || (BitIsClear (address, 1) && BitIsClear (address, 0))) 4912 { 4913 // R[t] = data; 4914 context.type = eContextRegisterLoad; 4915 context.SetRegisterPlusOffset (base_reg, address - base_address); 4916 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data)) 4917 return false; 4918 } 4919 // else // Can only apply before ARMv7 4920 else 4921 { 4922 // R[t] = ROR(data, 8*UInt(address<1:0>)); 4923 data = ROR (data, Bits32 (address, 1, 0)); 4924 context.type = eContextRegisterLoad; 4925 context.SetImmediate (data); 4926 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data)) 4927 return false; 4928 } 4929 4930 } 4931 return true; 4932} 4933 4934// LDR (register) calculates an address from a base register value and an offset register value, loads a word 4935// from memory, and writes it to a resgister. The offset register value can optionally be shifted. 4936bool 4937EmulateInstructionARM::EmulateLDRRegister (ARMEncoding encoding) 4938{ 4939#if 0 4940 if ConditionPassed() then 4941 EncodingSpecificOperations(); NullCheckIfThumbEE(n); 4942 offset = Shift(R[m], shift_t, shift_n, APSR.C); 4943 offset_addr = if add then (R[n] + offset) else (R[n] - offset); 4944 address = if index then offset_addr else R[n]; 4945 data = MemU[address,4]; 4946 if wback then R[n] = offset_addr; 4947 if t == 15 then 4948 if address<1:0> == ’00’ then LoadWritePC(data); else UNPREDICTABLE; 4949 elsif UnalignedSupport() || address<1:0> = ’00’ then 4950 R[t] = data; 4951 else // Can only apply before ARMv7 4952 if CurrentInstrSet() == InstrSet_ARM then 4953 R[t] = ROR(data, 8*UInt(address<1:0>)); 4954 else 4955 R[t] = bits(32) UNKNOWN; 4956#endif 4957 4958 bool success = false; 4959 const uint32_t opcode = OpcodeAsUnsigned (&success); 4960 if (!success) 4961 return false; 4962 4963 if (ConditionPassed ()) 4964 { 4965 const uint32_t addr_byte_size = GetAddressByteSize(); 4966 4967 uint32_t t; 4968 uint32_t n; 4969 uint32_t m; 4970 bool index; 4971 bool add; 4972 bool wback; 4973 ARM_ShifterType shift_t; 4974 uint32_t shift_n; 4975 4976 switch (encoding) 4977 { 4978 case eEncodingT1: 4979 // if CurrentInstrSet() == InstrSet_ThumbEE then SEE "Modified operation in ThumbEE"; 4980 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm); 4981 t = Bits32 (opcode, 2, 0); 4982 n = Bits32 (opcode, 5, 3); 4983 m = Bits32 (opcode, 8, 6); 4984 4985 // index = TRUE; add = TRUE; wback = FALSE; 4986 index = true; 4987 add = true; 4988 wback = false; 4989 4990 // (shift_t, shift_n) = (SRType_LSL, 0); 4991 shift_t = SRType_LSL; 4992 shift_n = 0; 4993 4994 break; 4995 4996 case eEncodingT2: 4997 // if Rn == ’1111’ then SEE LDR (literal); 4998 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm); 4999 t = Bits32 (opcode, 15, 12); 5000 n = Bits32 (opcode, 19, 16); 5001 m = Bits32 (opcode, 3, 0); 5002 5003 // index = TRUE; add = TRUE; wback = FALSE; 5004 index = true; 5005 add = true; 5006 wback = false; 5007 5008 // (shift_t, shift_n) = (SRType_LSL, UInt(imm2)); 5009 shift_t = SRType_LSL; 5010 shift_n = Bits32 (opcode, 5, 4); 5011 5012 // if BadReg(m) then UNPREDICTABLE; 5013 if (BadReg (m)) 5014 return false; 5015 5016 // if t == 15 && InITBlock() && !LastInITBlock() then UNPREDICTABLE; 5017 if ((t == 15) && InITBlock() && !LastInITBlock()) 5018 return false; 5019 5020 break; 5021 5022 case eEncodingA1: 5023 { 5024 // if P == ’0’ && W == ’1’ then SEE LDRT; 5025 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm); 5026 t = Bits32 (opcode, 15, 12); 5027 n = Bits32 (opcode, 19, 16); 5028 m = Bits32 (opcode, 3, 0); 5029 5030 // index = (P == ’1’); add = (U == ’1’); wback = (P == ’0’) || (W == ’1’); 5031 index = BitIsSet (opcode, 24); 5032 add = BitIsSet (opcode, 23); 5033 wback = (BitIsClear (opcode, 24) || BitIsSet (opcode, 21)); 5034 5035 // (shift_t, shift_n) = DecodeImmShift(type, imm5); 5036 uint32_t type = Bits32 (opcode, 6, 5); 5037 uint32_t imm5 = Bits32 (opcode, 11, 7); 5038 shift_n = DecodeImmShift (type, imm5, shift_t); 5039 5040 // if m == 15 then UNPREDICTABLE; 5041 if (m == 15) 5042 return false; 5043 5044 // if wback && (n == 15 || n == t) then UNPREDICTABLE; 5045 if (wback && ((n == 15) || (n == t))) 5046 return false; 5047 } 5048 break; 5049 5050 5051 default: 5052 return false; 5053 } 5054 5055 uint32_t Rm = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success); 5056 if (!success) 5057 return false; 5058 5059 uint32_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success); 5060 if (!success) 5061 return false; 5062 5063 addr_t offset_addr; 5064 addr_t address; 5065 5066 // offset = Shift(R[m], shift_t, shift_n, APSR.C); -- Note "The APSR is an application level alias for the CPSR". 5067 addr_t offset = Shift (Rm, shift_t, shift_n, Bit32 (m_inst_cpsr, CPSR_C)); 5068 5069 // offset_addr = if add then (R[n] + offset) else (R[n] - offset); 5070 if (add) 5071 offset_addr = Rn + offset; 5072 else 5073 offset_addr = Rn - offset; 5074 5075 // address = if index then offset_addr else R[n]; 5076 if (index) 5077 address = offset_addr; 5078 else 5079 address = Rn; 5080 5081 // data = MemU[address,4]; 5082 Register base_reg; 5083 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n); 5084 5085 EmulateInstruction::Context context; 5086 context.type = eContextRegisterLoad; 5087 context.SetRegisterPlusOffset (base_reg, address - Rn); 5088 5089 uint64_t data = MemURead (context, address, addr_byte_size, 0, &success); 5090 if (!success) 5091 return false; 5092 5093 // if wback then R[n] = offset_addr; 5094 if (wback) 5095 { 5096 context.type = eContextAdjustBaseRegister; 5097 context.SetAddress (offset_addr); 5098 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr)) 5099 return false; 5100 } 5101 5102 // if t == 15 then 5103 if (t == 15) 5104 { 5105 // if address<1:0> == ’00’ then LoadWritePC(data); else UNPREDICTABLE; 5106 if (BitIsClear (address, 1) && BitIsClear (address, 0)) 5107 { 5108 context.type = eContextRegisterLoad; 5109 context.SetRegisterPlusOffset (base_reg, address - Rn); 5110 LoadWritePC (context, data); 5111 } 5112 else 5113 return false; 5114 } 5115 // elsif UnalignedSupport() || address<1:0> = ’00’ then 5116 else if (UnalignedSupport () || (BitIsClear (address, 1) && BitIsClear (address, 0))) 5117 { 5118 // R[t] = data; 5119 context.type = eContextRegisterLoad; 5120 context.SetRegisterPlusOffset (base_reg, address - Rn); 5121 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data)) 5122 return false; 5123 } 5124 else // Can only apply before ARMv7 5125 { 5126 // if CurrentInstrSet() == InstrSet_ARM then 5127 if (CurrentInstrSet () == eModeARM) 5128 { 5129 // R[t] = ROR(data, 8*UInt(address<1:0>)); 5130 data = ROR (data, Bits32 (address, 1, 0)); 5131 context.type = eContextRegisterLoad; 5132 context.SetImmediate (data); 5133 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data)) 5134 return false; 5135 } 5136 else 5137 { 5138 // R[t] = bits(32) UNKNOWN; 5139 WriteBits32Unknown (t); 5140 } 5141 } 5142 } 5143 return true; 5144} 5145 5146// LDRB (immediate, Thumb) 5147bool 5148EmulateInstructionARM::EmulateLDRBImmediate (ARMEncoding encoding) 5149{ 5150#if 0 5151 if ConditionPassed() then 5152 EncodingSpecificOperations(); NullCheckIfThumbEE(n); 5153 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32); 5154 address = if index then offset_addr else R[n]; 5155 R[t] = ZeroExtend(MemU[address,1], 32); 5156 if wback then R[n] = offset_addr; 5157#endif 5158 5159 bool success = false; 5160 const uint32_t opcode = OpcodeAsUnsigned (&success); 5161 if (!success) 5162 return false; 5163 5164 if (ConditionPassed ()) 5165 { 5166 uint32_t t; 5167 uint32_t n; 5168 uint32_t imm32; 5169 bool index; 5170 bool add; 5171 bool wback; 5172 5173 // EncodingSpecificOperations(); NullCheckIfThumbEE(n); 5174 switch (encoding) 5175 { 5176 case eEncodingT1: 5177 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm5, 32); 5178 t = Bits32 (opcode, 2, 0); 5179 n = Bits32 (opcode, 5, 3); 5180 imm32 = Bits32 (opcode, 10, 6); 5181 5182 // index = TRUE; add = TRUE; wback = FALSE; 5183 index = true; 5184 add = true; 5185 wback= false; 5186 5187 break; 5188 5189 case eEncodingT2: 5190 // if Rt == ’1111’ then SEE PLD; 5191 // if Rn == ’1111’ then SEE LDRB (literal); 5192 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32); 5193 t = Bits32 (opcode, 15, 12); 5194 n = Bits32 (opcode, 19, 16); 5195 imm32 = Bits32 (opcode, 11, 0); 5196 5197 // index = TRUE; add = TRUE; wback = FALSE; 5198 index = true; 5199 add = true; 5200 wback = false; 5201 5202 // if t == 13 then UNPREDICTABLE; 5203 if (t == 13) 5204 return false; 5205 5206 break; 5207 5208 case eEncodingT3: 5209 // if Rt == ’1111’ && P == ’1’ && U == ’0’ && W == ’0’ then SEE PLD; 5210 // if Rn == ’1111’ then SEE LDRB (literal); 5211 // if P == ’1’ && U == ’1’ && W == ’0’ then SEE LDRBT; 5212 // if P == ’0’ && W == ’0’ then UNDEFINED; 5213 if (BitIsClear (opcode, 10) && BitIsClear (opcode, 8)) 5214 return false; 5215 5216 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32); 5217 t = Bits32 (opcode, 15, 12); 5218 n = Bits32 (opcode, 19, 16); 5219 imm32 = Bits32 (opcode, 7, 0); 5220 5221 // index = (P == ’1’); add = (U == ’1’); wback = (W == ’1’); 5222 index = BitIsSet (opcode, 10); 5223 add = BitIsSet (opcode, 9); 5224 wback = BitIsSet (opcode, 8); 5225 5226 // if BadReg(t) || (wback && n == t) then UNPREDICTABLE; 5227 if (BadReg (t) || (wback && (n == t))) 5228 return false; 5229 5230 break; 5231 5232 default: 5233 return false; 5234 } 5235 5236 uint32_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success); 5237 if (!success) 5238 return false; 5239 5240 addr_t address; 5241 addr_t offset_addr; 5242 5243 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32); 5244 if (add) 5245 offset_addr = Rn + imm32; 5246 else 5247 offset_addr = Rn - imm32; 5248 5249 // address = if index then offset_addr else R[n]; 5250 if (index) 5251 address = offset_addr; 5252 else 5253 address = Rn; 5254 5255 // R[t] = ZeroExtend(MemU[address,1], 32); 5256 Register base_reg; 5257 Register data_reg; 5258 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n); 5259 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + t); 5260 5261 EmulateInstruction::Context context; 5262 context.type = eContextRegisterLoad; 5263 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, address - Rn); 5264 5265 uint64_t data = MemURead (context, address, 1, 0, &success); 5266 if (!success) 5267 return false; 5268 5269 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data)) 5270 return false; 5271 5272 // if wback then R[n] = offset_addr; 5273 if (wback) 5274 { 5275 context.type = eContextAdjustBaseRegister; 5276 context.SetAddress (offset_addr); 5277 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr)) 5278 return false; 5279 } 5280 } 5281 return true; 5282} 5283 5284// LDRB (literal) calculates an address from the PC value and an immediate offset, loads a byte from memory, 5285// zero-extends it to form a 32-bit word and writes it to a register. 5286bool 5287EmulateInstructionARM::EmulateLDRBLiteral (ARMEncoding encoding) 5288{ 5289#if 0 5290 if ConditionPassed() then 5291 EncodingSpecificOperations(); NullCheckIfThumbEE(15); 5292 base = Align(PC,4); 5293 address = if add then (base + imm32) else (base - imm32); 5294 R[t] = ZeroExtend(MemU[address,1], 32); 5295#endif 5296 5297 bool success = false; 5298 const uint32_t opcode = OpcodeAsUnsigned (&success); 5299 if (!success) 5300 return false; 5301 5302 if (ConditionPassed ()) 5303 { 5304 uint32_t t; 5305 uint32_t imm32; 5306 bool add; 5307 switch (encoding) 5308 { 5309 case eEncodingT1: 5310 // if Rt == ’1111’ then SEE PLD; 5311 // t = UInt(Rt); imm32 = ZeroExtend(imm12, 32); add = (U == ’1’); 5312 t = Bits32 (opcode, 15, 12); 5313 imm32 = Bits32 (opcode, 11, 0); 5314 add = BitIsSet (opcode, 23); 5315 5316 // if t == 13 then UNPREDICTABLE; 5317 if (t == 13) 5318 return false; 5319 5320 break; 5321 5322 case eEncodingA1: 5323 // t == UInt(Rt); imm32 = ZeroExtend(imm12, 32); add = (U == ’1’); 5324 t = Bits32 (opcode, 15, 12); 5325 imm32 = Bits32 (opcode, 11, 0); 5326 add = BitIsSet (opcode, 23); 5327 5328 // if t == 15 then UNPREDICTABLE; 5329 if (t == 15) 5330 return false; 5331 break; 5332 5333 default: 5334 return false; 5335 } 5336 5337 // base = Align(PC,4); 5338 uint32_t pc_val = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success); 5339 if (!success) 5340 return false; 5341 5342 uint32_t base = AlignPC (pc_val); 5343 5344 addr_t address; 5345 // address = if add then (base + imm32) else (base - imm32); 5346 if (add) 5347 address = base + imm32; 5348 else 5349 address = base - imm32; 5350 5351 // R[t] = ZeroExtend(MemU[address,1], 32); 5352 EmulateInstruction::Context context; 5353 context.type = eContextRelativeBranchImmediate; 5354 context.SetImmediate (address - base); 5355 5356 uint64_t data = MemURead (context, address, 1, 0, &success); 5357 if (!success) 5358 return false; 5359 5360 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data)) 5361 return false; 5362 } 5363 return true; 5364} 5365 5366// LDRB (register) calculates an address from a base register value and an offset rigister value, loads a byte from 5367// memory, zero-extends it to form a 32-bit word, and writes it to a register. The offset register value can 5368// optionally be shifted. 5369bool 5370EmulateInstructionARM::EmulateLDRBRegister (ARMEncoding encoding) 5371{ 5372#if 0 5373 if ConditionPassed() then 5374 EncodingSpecificOperations(); NullCheckIfThumbEE(n); 5375 offset = Shift(R[m], shift_t, shift_n, APSR.C); 5376 offset_addr = if add then (R[n] + offset) else (R[n] - offset); 5377 address = if index then offset_addr else R[n]; 5378 R[t] = ZeroExtend(MemU[address,1],32); 5379 if wback then R[n] = offset_addr; 5380#endif 5381 5382 bool success = false; 5383 const uint32_t opcode = OpcodeAsUnsigned (&success); 5384 if (!success) 5385 return false; 5386 5387 if (ConditionPassed ()) 5388 { 5389 uint32_t t; 5390 uint32_t n; 5391 uint32_t m; 5392 bool index; 5393 bool add; 5394 bool wback; 5395 ARM_ShifterType shift_t; 5396 uint32_t shift_n; 5397 5398 // EncodingSpecificOperations(); NullCheckIfThumbEE(n); 5399 switch (encoding) 5400 { 5401 case eEncodingT1: 5402 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm); 5403 t = Bits32 (opcode, 2, 0); 5404 n = Bits32 (opcode, 5, 3); 5405 m = Bits32 (opcode, 8, 6); 5406 5407 // index = TRUE; add = TRUE; wback = FALSE; 5408 index = true; 5409 add = true; 5410 wback = false; 5411 5412 // (shift_t, shift_n) = (SRType_LSL, 0); 5413 shift_t = SRType_LSL; 5414 shift_n = 0; 5415 break; 5416 5417 case eEncodingT2: 5418 // if Rt == ’1111’ then SEE PLD; 5419 // if Rn == ’1111’ then SEE LDRB (literal); 5420 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm); 5421 t = Bits32 (opcode, 15, 12); 5422 n = Bits32 (opcode, 19, 16); 5423 m = Bits32 (opcode, 3, 0); 5424 5425 // index = TRUE; add = TRUE; wback = FALSE; 5426 index = true; 5427 add = true; 5428 wback = false; 5429 5430 // (shift_t, shift_n) = (SRType_LSL, UInt(imm2)); 5431 shift_t = SRType_LSL; 5432 shift_n = Bits32 (opcode, 5, 4); 5433 5434 // if t == 13 || BadReg(m) then UNPREDICTABLE; 5435 if ((t == 13) || BadReg (m)) 5436 return false; 5437 break; 5438 5439 case eEncodingA1: 5440 { 5441 // if P == ’0’ && W == ’1’ then SEE LDRBT; 5442 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm); 5443 t = Bits32 (opcode, 15, 12); 5444 n = Bits32 (opcode, 19, 16); 5445 m = Bits32 (opcode, 3, 0); 5446 5447 // index = (P == ’1’); add = (U == ’1’); wback = (P == ’0’) || (W == ’1’); 5448 index = BitIsSet (opcode, 24); 5449 add = BitIsSet (opcode, 23); 5450 wback = (BitIsClear (opcode, 24) || BitIsSet (opcode, 21)); 5451 5452 // (shift_t, shift_n) = DecodeImmShift(type, imm5); 5453 uint32_t type = Bits32 (opcode, 6, 5); 5454 uint32_t imm5 = Bits32 (opcode, 11, 7); 5455 shift_n = DecodeImmShift (type, imm5, shift_t); 5456 5457 // if t == 15 || m == 15 then UNPREDICTABLE; 5458 if ((t == 15) || (m == 15)) 5459 return false; 5460 5461 // if wback && (n == 15 || n == t) then UNPREDICTABLE; 5462 if (wback && ((n == 15) || (n == t))) 5463 return false; 5464 } 5465 break; 5466 5467 default: 5468 return false; 5469 } 5470 5471 addr_t offset_addr; 5472 addr_t address; 5473 5474 // offset = Shift(R[m], shift_t, shift_n, APSR.C); 5475 uint32_t Rm = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success); 5476 if (!success) 5477 return false; 5478 5479 addr_t offset = Shift (Rm, shift_t, shift_n, APSR_C); 5480 5481 // offset_addr = if add then (R[n] + offset) else (R[n] - offset); 5482 uint32_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success); 5483 if (!success) 5484 return false; 5485 5486 if (add) 5487 offset_addr = Rn + offset; 5488 else 5489 offset_addr = Rn - offset; 5490 5491 // address = if index then offset_addr else R[n]; 5492 if (index) 5493 address = offset_addr; 5494 else 5495 address = Rn; 5496 5497 // R[t] = ZeroExtend(MemU[address,1],32); 5498 Register base_reg; 5499 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n); 5500 5501 EmulateInstruction::Context context; 5502 context.type = eContextRegisterLoad; 5503 context.SetRegisterPlusOffset (base_reg, address - Rn); 5504 5505 uint64_t data = MemURead (context, address, 1, 0, &success); 5506 if (!success) 5507 return false; 5508 5509 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data)) 5510 return false; 5511 5512 // if wback then R[n] = offset_addr; 5513 if (wback) 5514 { 5515 context.type = eContextAdjustBaseRegister; 5516 context.SetAddress (offset_addr); 5517 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr)) 5518 return false; 5519 } 5520 } 5521 return true; 5522} 5523 5524// Bitwise Exclusive OR (immediate) performs a bitwise exclusive OR of a register value and an immediate value, 5525// and writes the result to the destination register. It can optionally update the condition flags based on 5526// the result. 5527bool 5528EmulateInstructionARM::EmulateEORImm (ARMEncoding encoding) 5529{ 5530#if 0 5531 // ARM pseudo code... 5532 if ConditionPassed() then 5533 EncodingSpecificOperations(); 5534 result = R[n] EOR imm32; 5535 if d == 15 then // Can only occur for ARM encoding 5536 ALUWritePC(result); // setflags is always FALSE here 5537 else 5538 R[d] = result; 5539 if setflags then 5540 APSR.N = result<31>; 5541 APSR.Z = IsZeroBit(result); 5542 APSR.C = carry; 5543 // APSR.V unchanged 5544#endif 5545 5546 bool success = false; 5547 const uint32_t opcode = OpcodeAsUnsigned (&success); 5548 if (!success) 5549 return false; 5550 5551 if (ConditionPassed()) 5552 { 5553 uint32_t Rd, Rn; 5554 uint32_t imm32; // the immediate value to be ORed to the value obtained from Rn 5555 bool setflags; 5556 uint32_t carry; // the carry bit after ARM/Thumb Expand operation 5557 switch (encoding) 5558 { 5559 case eEncodingT1: 5560 Rd = Bits32(opcode, 11, 8); 5561 Rn = Bits32(opcode, 19, 16); 5562 setflags = BitIsSet(opcode, 20); 5563 imm32 = ThumbExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C) 5564 // if Rd == '1111' && S == '1' then SEE TEQ (immediate); 5565 if (Rd == 15 && setflags) 5566 return EmulateTEQImm(eEncodingT1); 5567 if (Rd == 13 || (Rd == 15 && !setflags) || BadReg(Rn)) 5568 return false; 5569 break; 5570 case eEncodingA1: 5571 Rd = Bits32(opcode, 15, 12); 5572 Rn = Bits32(opcode, 19, 16); 5573 setflags = BitIsSet(opcode, 20); 5574 imm32 = ARMExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ARMExpandImm(imm12, APSR.C) 5575 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions; 5576 // TODO: Emulate SUBS PC, LR and related instructions. 5577 if (Rd == 15 && setflags) 5578 return false; 5579 break; 5580 default: 5581 return false; 5582 } 5583 5584 // Read the first operand. 5585 uint32_t val1 = ReadCoreReg(Rn, &success); 5586 if (!success) 5587 return false; 5588 5589 uint32_t result = val1 ^ imm32; 5590 5591 EmulateInstruction::Context context; 5592 context.type = EmulateInstruction::eContextImmediate; 5593 context.SetNoArgs (); 5594 5595 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry)) 5596 return false; 5597 } 5598 return true; 5599} 5600 5601// Bitwise Exclusive OR (register) performs a bitwise exclusive OR of a register value and an 5602// optionally-shifted register value, and writes the result to the destination register. 5603// It can optionally update the condition flags based on the result. 5604bool 5605EmulateInstructionARM::EmulateEORReg (ARMEncoding encoding) 5606{ 5607#if 0 5608 // ARM pseudo code... 5609 if ConditionPassed() then 5610 EncodingSpecificOperations(); 5611 (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C); 5612 result = R[n] EOR shifted; 5613 if d == 15 then // Can only occur for ARM encoding 5614 ALUWritePC(result); // setflags is always FALSE here 5615 else 5616 R[d] = result; 5617 if setflags then 5618 APSR.N = result<31>; 5619 APSR.Z = IsZeroBit(result); 5620 APSR.C = carry; 5621 // APSR.V unchanged 5622#endif 5623 5624 bool success = false; 5625 const uint32_t opcode = OpcodeAsUnsigned (&success); 5626 if (!success) 5627 return false; 5628 5629 if (ConditionPassed()) 5630 { 5631 uint32_t Rd, Rn, Rm; 5632 ARM_ShifterType shift_t; 5633 uint32_t shift_n; // the shift applied to the value read from Rm 5634 bool setflags; 5635 uint32_t carry; 5636 switch (encoding) 5637 { 5638 case eEncodingT1: 5639 Rd = Rn = Bits32(opcode, 2, 0); 5640 Rm = Bits32(opcode, 5, 3); 5641 setflags = !InITBlock(); 5642 shift_t = SRType_LSL; 5643 shift_n = 0; 5644 case eEncodingT2: 5645 Rd = Bits32(opcode, 11, 8); 5646 Rn = Bits32(opcode, 19, 16); 5647 Rm = Bits32(opcode, 3, 0); 5648 setflags = BitIsSet(opcode, 20); 5649 shift_n = DecodeImmShift(Bits32(opcode, 5, 4), Bits32(opcode, 14, 12)<<2 | Bits32(opcode, 7, 6), shift_t); 5650 // if Rd == ‘1111’ && S == ‘1’ then SEE TEQ (register); 5651 if (Rd == 15 && setflags) 5652 return EmulateTEQReg(eEncodingT1); 5653 if (Rd == 13 || (Rd == 15 && !setflags) || BadReg(Rn) || BadReg(Rm)) 5654 return false; 5655 break; 5656 case eEncodingA1: 5657 Rd = Bits32(opcode, 15, 12); 5658 Rn = Bits32(opcode, 19, 16); 5659 Rm = Bits32(opcode, 3, 0); 5660 setflags = BitIsSet(opcode, 20); 5661 shift_n = DecodeImmShift(Bits32(opcode, 6, 5), Bits32(opcode, 11, 7), shift_t); 5662 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions; 5663 // TODO: Emulate SUBS PC, LR and related instructions. 5664 if (Rd == 15 && setflags) 5665 return false; 5666 break; 5667 default: 5668 return false; 5669 } 5670 5671 // Read the first operand. 5672 uint32_t val1 = ReadCoreReg(Rn, &success); 5673 if (!success) 5674 return false; 5675 5676 // Read the second operand. 5677 uint32_t val2 = ReadCoreReg(Rm, &success); 5678 if (!success) 5679 return false; 5680 5681 uint32_t shifted = Shift_C(val2, shift_t, shift_n, APSR_C, carry); 5682 uint32_t result = val1 ^ shifted; 5683 5684 EmulateInstruction::Context context; 5685 context.type = EmulateInstruction::eContextImmediate; 5686 context.SetNoArgs (); 5687 5688 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry)) 5689 return false; 5690 } 5691 return true; 5692} 5693 5694// Bitwise OR (immediate) performs a bitwise (inclusive) OR of a register value and an immediate value, and 5695// writes the result to the destination register. It can optionally update the condition flags based 5696// on the result. 5697bool 5698EmulateInstructionARM::EmulateORRImm (ARMEncoding encoding) 5699{ 5700#if 0 5701 // ARM pseudo code... 5702 if ConditionPassed() then 5703 EncodingSpecificOperations(); 5704 result = R[n] OR imm32; 5705 if d == 15 then // Can only occur for ARM encoding 5706 ALUWritePC(result); // setflags is always FALSE here 5707 else 5708 R[d] = result; 5709 if setflags then 5710 APSR.N = result<31>; 5711 APSR.Z = IsZeroBit(result); 5712 APSR.C = carry; 5713 // APSR.V unchanged 5714#endif 5715 5716 bool success = false; 5717 const uint32_t opcode = OpcodeAsUnsigned (&success); 5718 if (!success) 5719 return false; 5720 5721 if (ConditionPassed()) 5722 { 5723 uint32_t Rd, Rn; 5724 uint32_t imm32; // the immediate value to be ORed to the value obtained from Rn 5725 bool setflags; 5726 uint32_t carry; // the carry bit after ARM/Thumb Expand operation 5727 switch (encoding) 5728 { 5729 case eEncodingT1: 5730 Rd = Bits32(opcode, 11, 8); 5731 Rn = Bits32(opcode, 19, 16); 5732 setflags = BitIsSet(opcode, 20); 5733 imm32 = ThumbExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C) 5734 // if Rn == ‘1111’ then SEE MOV (immediate); 5735 if (Rn == 15) 5736 return EmulateMOVRdImm(eEncodingT2); 5737 if (BadReg(Rd) || Rn == 13) 5738 return false; 5739 break; 5740 case eEncodingA1: 5741 Rd = Bits32(opcode, 15, 12); 5742 Rn = Bits32(opcode, 19, 16); 5743 setflags = BitIsSet(opcode, 20); 5744 imm32 = ARMExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ARMExpandImm(imm12, APSR.C) 5745 // TODO: Emulate SUBS PC, LR and related instructions. 5746 if (Rd == 15 && setflags) 5747 return false; 5748 break; 5749 default: 5750 return false; 5751 } 5752 5753 // Read the first operand. 5754 uint32_t val1 = ReadCoreReg(Rn, &success); 5755 if (!success) 5756 return false; 5757 5758 uint32_t result = val1 | imm32; 5759 5760 EmulateInstruction::Context context; 5761 context.type = EmulateInstruction::eContextImmediate; 5762 context.SetNoArgs (); 5763 5764 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry)) 5765 return false; 5766 } 5767 return true; 5768} 5769 5770// Bitwise OR (register) performs a bitwise (inclusive) OR of a register value and an optionally-shifted register 5771// value, and writes the result to the destination register. It can optionally update the condition flags based 5772// on the result. 5773bool 5774EmulateInstructionARM::EmulateORRReg (ARMEncoding encoding) 5775{ 5776#if 0 5777 // ARM pseudo code... 5778 if ConditionPassed() then 5779 EncodingSpecificOperations(); 5780 (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C); 5781 result = R[n] OR shifted; 5782 if d == 15 then // Can only occur for ARM encoding 5783 ALUWritePC(result); // setflags is always FALSE here 5784 else 5785 R[d] = result; 5786 if setflags then 5787 APSR.N = result<31>; 5788 APSR.Z = IsZeroBit(result); 5789 APSR.C = carry; 5790 // APSR.V unchanged 5791#endif 5792 5793 bool success = false; 5794 const uint32_t opcode = OpcodeAsUnsigned (&success); 5795 if (!success) 5796 return false; 5797 5798 if (ConditionPassed()) 5799 { 5800 uint32_t Rd, Rn, Rm; 5801 ARM_ShifterType shift_t; 5802 uint32_t shift_n; // the shift applied to the value read from Rm 5803 bool setflags; 5804 uint32_t carry; 5805 switch (encoding) 5806 { 5807 case eEncodingT1: 5808 Rd = Rn = Bits32(opcode, 2, 0); 5809 Rm = Bits32(opcode, 5, 3); 5810 setflags = !InITBlock(); 5811 shift_t = SRType_LSL; 5812 shift_n = 0; 5813 case eEncodingT2: 5814 Rd = Bits32(opcode, 11, 8); 5815 Rn = Bits32(opcode, 19, 16); 5816 Rm = Bits32(opcode, 3, 0); 5817 setflags = BitIsSet(opcode, 20); 5818 shift_n = DecodeImmShift(Bits32(opcode, 5, 4), Bits32(opcode, 14, 12)<<2 | Bits32(opcode, 7, 6), shift_t); 5819 // if Rn == ‘1111’ then SEE MOV (register); 5820 if (Rn == 15) 5821 return EmulateMOVRdRm(eEncodingT3); 5822 if (BadReg(Rd) || Rn == 13 || BadReg(Rm)) 5823 return false; 5824 break; 5825 case eEncodingA1: 5826 Rd = Bits32(opcode, 15, 12); 5827 Rn = Bits32(opcode, 19, 16); 5828 Rm = Bits32(opcode, 3, 0); 5829 setflags = BitIsSet(opcode, 20); 5830 shift_n = DecodeImmShift(Bits32(opcode, 6, 5), Bits32(opcode, 11, 7), shift_t); 5831 // TODO: Emulate SUBS PC, LR and related instructions. 5832 if (Rd == 15 && setflags) 5833 return false; 5834 break; 5835 default: 5836 return false; 5837 } 5838 5839 // Read the first operand. 5840 uint32_t val1 = ReadCoreReg(Rn, &success); 5841 if (!success) 5842 return false; 5843 5844 // Read the second operand. 5845 uint32_t val2 = ReadCoreReg(Rm, &success); 5846 if (!success) 5847 return false; 5848 5849 uint32_t shifted = Shift_C(val2, shift_t, shift_n, APSR_C, carry); 5850 uint32_t result = val1 | shifted; 5851 5852 EmulateInstruction::Context context; 5853 context.type = EmulateInstruction::eContextImmediate; 5854 context.SetNoArgs (); 5855 5856 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry)) 5857 return false; 5858 } 5859 return true; 5860} 5861 5862// Test Equivalence (immediate) performs a bitwise exclusive OR operation on a register value and an 5863// immediate value. It updates the condition flags based on the result, and discards the result. 5864bool 5865EmulateInstructionARM::EmulateTEQImm (ARMEncoding encoding) 5866{ 5867#if 0 5868 // ARM pseudo code... 5869 if ConditionPassed() then 5870 EncodingSpecificOperations(); 5871 result = R[n] EOR imm32; 5872 APSR.N = result<31>; 5873 APSR.Z = IsZeroBit(result); 5874 APSR.C = carry; 5875 // APSR.V unchanged 5876#endif 5877 5878 bool success = false; 5879 const uint32_t opcode = OpcodeAsUnsigned (&success); 5880 if (!success) 5881 return false; 5882 5883 if (ConditionPassed()) 5884 { 5885 uint32_t Rn; 5886 uint32_t imm32; // the immediate value to be ANDed to the value obtained from Rn 5887 uint32_t carry; // the carry bit after ARM/Thumb Expand operation 5888 switch (encoding) 5889 { 5890 case eEncodingT1: 5891 Rn = Bits32(opcode, 19, 16); 5892 imm32 = ThumbExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C) 5893 if (BadReg(Rn)) 5894 return false; 5895 break; 5896 case eEncodingA1: 5897 Rn = Bits32(opcode, 19, 16); 5898 imm32 = ARMExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ARMExpandImm(imm12, APSR.C) 5899 break; 5900 default: 5901 return false; 5902 } 5903 5904 // Read the first operand. 5905 uint32_t val1 = ReadCoreReg(Rn, &success); 5906 if (!success) 5907 return false; 5908 5909 uint32_t result = val1 ^ imm32; 5910 5911 EmulateInstruction::Context context; 5912 context.type = EmulateInstruction::eContextImmediate; 5913 context.SetNoArgs (); 5914 5915 if (!WriteFlags(context, result, carry)) 5916 return false; 5917 } 5918 return true; 5919} 5920 5921// Test Equivalence (register) performs a bitwise exclusive OR operation on a register value and an 5922// optionally-shifted register value. It updates the condition flags based on the result, and discards 5923// the result. 5924bool 5925EmulateInstructionARM::EmulateTEQReg (ARMEncoding encoding) 5926{ 5927#if 0 5928 // ARM pseudo code... 5929 if ConditionPassed() then 5930 EncodingSpecificOperations(); 5931 (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C); 5932 result = R[n] EOR shifted; 5933 APSR.N = result<31>; 5934 APSR.Z = IsZeroBit(result); 5935 APSR.C = carry; 5936 // APSR.V unchanged 5937#endif 5938 5939 bool success = false; 5940 const uint32_t opcode = OpcodeAsUnsigned (&success); 5941 if (!success) 5942 return false; 5943 5944 if (ConditionPassed()) 5945 { 5946 uint32_t Rn, Rm; 5947 ARM_ShifterType shift_t; 5948 uint32_t shift_n; // the shift applied to the value read from Rm 5949 uint32_t carry; 5950 switch (encoding) 5951 { 5952 case eEncodingT1: 5953 Rn = Bits32(opcode, 19, 16); 5954 Rm = Bits32(opcode, 3, 0); 5955 shift_n = DecodeImmShift(Bits32(opcode, 5, 4), Bits32(opcode, 14, 12)<<2 | Bits32(opcode, 7, 6), shift_t); 5956 if (BadReg(Rn) || BadReg(Rm)) 5957 return false; 5958 break; 5959 case eEncodingA1: 5960 Rn = Bits32(opcode, 19, 16); 5961 Rm = Bits32(opcode, 3, 0); 5962 shift_n = DecodeImmShift(Bits32(opcode, 6, 5), Bits32(opcode, 11, 7), shift_t); 5963 break; 5964 default: 5965 return false; 5966 } 5967 5968 // Read the first operand. 5969 uint32_t val1 = ReadCoreReg(Rn, &success); 5970 if (!success) 5971 return false; 5972 5973 // Read the second operand. 5974 uint32_t val2 = ReadCoreReg(Rm, &success); 5975 if (!success) 5976 return false; 5977 5978 uint32_t shifted = Shift_C(val2, shift_t, shift_n, APSR_C, carry); 5979 uint32_t result = val1 ^ shifted; 5980 5981 EmulateInstruction::Context context; 5982 context.type = EmulateInstruction::eContextImmediate; 5983 context.SetNoArgs (); 5984 5985 if (!WriteFlags(context, result, carry)) 5986 return false; 5987 } 5988 return true; 5989} 5990 5991// Test (immediate) performs a bitwise AND operation on a register value and an immediate value. 5992// It updates the condition flags based on the result, and discards the result. 5993bool 5994EmulateInstructionARM::EmulateTSTImm (ARMEncoding encoding) 5995{ 5996#if 0 5997 // ARM pseudo code... 5998 if ConditionPassed() then 5999 EncodingSpecificOperations(); 6000 result = R[n] AND imm32; 6001 APSR.N = result<31>; 6002 APSR.Z = IsZeroBit(result); 6003 APSR.C = carry; 6004 // APSR.V unchanged 6005#endif 6006 6007 bool success = false; 6008 const uint32_t opcode = OpcodeAsUnsigned (&success); 6009 if (!success) 6010 return false; 6011 6012 if (ConditionPassed()) 6013 { 6014 uint32_t Rn; 6015 uint32_t imm32; // the immediate value to be ANDed to the value obtained from Rn 6016 uint32_t carry; // the carry bit after ARM/Thumb Expand operation 6017 switch (encoding) 6018 { 6019 case eEncodingT1: 6020 Rn = Bits32(opcode, 19, 16); 6021 imm32 = ThumbExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C) 6022 if (BadReg(Rn)) 6023 return false; 6024 break; 6025 case eEncodingA1: 6026 Rn = Bits32(opcode, 19, 16); 6027 imm32 = ARMExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ARMExpandImm(imm12, APSR.C) 6028 break; 6029 default: 6030 return false; 6031 } 6032 6033 // Read the first operand. 6034 uint32_t val1 = ReadCoreReg(Rn, &success); 6035 if (!success) 6036 return false; 6037 6038 uint32_t result = val1 & imm32; 6039 6040 EmulateInstruction::Context context; 6041 context.type = EmulateInstruction::eContextImmediate; 6042 context.SetNoArgs (); 6043 6044 if (!WriteFlags(context, result, carry)) 6045 return false; 6046 } 6047 return true; 6048} 6049 6050// Test (register) performs a bitwise AND operation on a register value and an optionally-shifted register value. 6051// It updates the condition flags based on the result, and discards the result. 6052bool 6053EmulateInstructionARM::EmulateTSTReg (ARMEncoding encoding) 6054{ 6055#if 0 6056 // ARM pseudo code... 6057 if ConditionPassed() then 6058 EncodingSpecificOperations(); 6059 (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C); 6060 result = R[n] AND shifted; 6061 APSR.N = result<31>; 6062 APSR.Z = IsZeroBit(result); 6063 APSR.C = carry; 6064 // APSR.V unchanged 6065#endif 6066 6067 bool success = false; 6068 const uint32_t opcode = OpcodeAsUnsigned (&success); 6069 if (!success) 6070 return false; 6071 6072 if (ConditionPassed()) 6073 { 6074 uint32_t Rn, Rm; 6075 ARM_ShifterType shift_t; 6076 uint32_t shift_n; // the shift applied to the value read from Rm 6077 uint32_t carry; 6078 switch (encoding) 6079 { 6080 case eEncodingT1: 6081 Rn = Bits32(opcode, 2, 0); 6082 Rm = Bits32(opcode, 5, 3); 6083 shift_t = SRType_LSL; 6084 shift_n = 0; 6085 case eEncodingT2: 6086 Rn = Bits32(opcode, 19, 16); 6087 Rm = Bits32(opcode, 3, 0); 6088 shift_n = DecodeImmShift(Bits32(opcode, 5, 4), Bits32(opcode, 14, 12)<<2 | Bits32(opcode, 7, 6), shift_t); 6089 if (BadReg(Rn) || BadReg(Rm)) 6090 return false; 6091 break; 6092 case eEncodingA1: 6093 Rn = Bits32(opcode, 19, 16); 6094 Rm = Bits32(opcode, 3, 0); 6095 shift_n = DecodeImmShift(Bits32(opcode, 6, 5), Bits32(opcode, 11, 7), shift_t); 6096 break; 6097 default: 6098 return false; 6099 } 6100 6101 // Read the first operand. 6102 uint32_t val1 = ReadCoreReg(Rn, &success); 6103 if (!success) 6104 return false; 6105 6106 // Read the second operand. 6107 uint32_t val2 = ReadCoreReg(Rm, &success); 6108 if (!success) 6109 return false; 6110 6111 uint32_t shifted = Shift_C(val2, shift_t, shift_n, APSR_C, carry); 6112 uint32_t result = val1 & shifted; 6113 6114 EmulateInstruction::Context context; 6115 context.type = EmulateInstruction::eContextImmediate; 6116 context.SetNoArgs (); 6117 6118 if (!WriteFlags(context, result, carry)) 6119 return false; 6120 } 6121 return true; 6122} 6123 6124EmulateInstructionARM::ARMOpcode* 6125EmulateInstructionARM::GetARMOpcodeForInstruction (const uint32_t opcode) 6126{ 6127 static ARMOpcode 6128 g_arm_opcodes[] = 6129 { 6130 //---------------------------------------------------------------------- 6131 // Prologue instructions 6132 //---------------------------------------------------------------------- 6133 6134 // push register(s) 6135 { 0x0fff0000, 0x092d0000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulatePUSH, "push <registers>" }, 6136 { 0x0fff0fff, 0x052d0004, ARMvAll, eEncodingA2, eSize32, &EmulateInstructionARM::EmulatePUSH, "push <register>" }, 6137 6138 // set r7 to point to a stack offset 6139 { 0x0ffff000, 0x028d7000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateADDRdSPImm, "add r7, sp, #<const>" }, 6140 { 0x0ffff000, 0x024c7000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSUBR7IPImm, "sub r7, ip, #<const>"}, 6141 // copy the stack pointer to ip 6142 { 0x0fffffff, 0x01a0c00d, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateMOVRdSP, "mov ip, sp" }, 6143 { 0x0ffff000, 0x028dc000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateADDRdSPImm, "add ip, sp, #<const>" }, 6144 { 0x0ffff000, 0x024dc000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSUBIPSPImm, "sub ip, sp, #<const>"}, 6145 6146 // adjust the stack pointer 6147 { 0x0ffff000, 0x024dd000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSUBSPImm, "sub sp, sp, #<const>"}, 6148 6149 // push one register 6150 // if Rn == '1101' && imm12 == '000000000100' then SEE PUSH; 6151 { 0x0fff0000, 0x052d0000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSTRRtSP, "str Rt, [sp, #-imm12]!" }, 6152 6153 // vector push consecutive extension register(s) 6154 { 0x0fbf0f00, 0x0d2d0b00, ARMV6T2_ABOVE, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateVPUSH, "vpush.64 <list>"}, 6155 { 0x0fbf0f00, 0x0d2d0a00, ARMV6T2_ABOVE, eEncodingA2, eSize32, &EmulateInstructionARM::EmulateVPUSH, "vpush.32 <list>"}, 6156 6157 //---------------------------------------------------------------------- 6158 // Epilogue instructions 6159 //---------------------------------------------------------------------- 6160 6161 { 0x0fff0000, 0x08bd0000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulatePOP, "pop <registers>"}, 6162 { 0x0fff0fff, 0x049d0004, ARMvAll, eEncodingA2, eSize32, &EmulateInstructionARM::EmulatePOP, "pop <register>"}, 6163 { 0x0fbf0f00, 0x0cbd0b00, ARMV6T2_ABOVE, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateVPOP, "vpop.64 <list>"}, 6164 { 0x0fbf0f00, 0x0cbd0a00, ARMV6T2_ABOVE, eEncodingA2, eSize32, &EmulateInstructionARM::EmulateVPOP, "vpop.32 <list>"}, 6165 6166 //---------------------------------------------------------------------- 6167 // Supervisor Call (previously Software Interrupt) 6168 //---------------------------------------------------------------------- 6169 { 0x0f000000, 0x0f000000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSVC, "svc #imm24"}, 6170 6171 //---------------------------------------------------------------------- 6172 // Branch instructions 6173 //---------------------------------------------------------------------- 6174 { 0x0f000000, 0x0a000000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSVC, "b #imm24"}, 6175 // To resolve ambiguity, "blx <label>" should come before "bl <label>". 6176 { 0xfe000000, 0xfa000000, ARMV5_ABOVE, eEncodingA2, eSize32, &EmulateInstructionARM::EmulateBLXImmediate, "blx <label>"}, 6177 { 0x0f000000, 0x0b000000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateBLXImmediate, "bl <label>"}, 6178 { 0x0ffffff0, 0x012fff30, ARMV5_ABOVE, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateBLXRm, "blx <Rm>"}, 6179 // for example, "bx lr" 6180 { 0x0ffffff0, 0x012fff10, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateBXRm, "bx <Rm>"}, 6181 6182 //---------------------------------------------------------------------- 6183 // Data-processing instructions 6184 //---------------------------------------------------------------------- 6185 // adc (immediate) 6186 { 0x0fe00000, 0x02a00000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateADCImm, "adc{s}<c> <Rd>, <Rn>, #const"}, 6187 // adc (register) 6188 { 0x0fe00010, 0x00a00000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateADCReg, "adc{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"}, 6189 // add (immediate) 6190 { 0x0fe00000, 0x02800000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateADDImmARM, "add{s}<c> <Rd>, <Rn>, #const"}, 6191 // add (register) 6192 { 0x0fe00010, 0x00800000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateADDReg, "add{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"}, 6193 // and (immediate) 6194 { 0x0fe00000, 0x02000000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateANDImm, "and{s}<c> <Rd>, <Rn>, #const"}, 6195 // and (register) 6196 { 0x0fe00010, 0x00000000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateANDReg, "and{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"}, 6197 // eor (immediate) 6198 { 0x0fe00000, 0x02200000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateEORImm, "eor{s}<c> <Rd>, <Rn>, #const"}, 6199 // eor (register) 6200 { 0x0fe00010, 0x00200000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateEORReg, "eor{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"}, 6201 // orr (immediate) 6202 { 0x0fe00000, 0x03800000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateORRImm, "orr{s}<c> <Rd>, <Rn>, #const"}, 6203 // orr (register) 6204 { 0x0fe00010, 0x01800000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateORRReg, "orr{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"}, 6205 // teq (immediate) 6206 { 0x0ff0f000, 0x03300000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateTEQImm, "teq<c> <Rn>, #const"}, 6207 // teq (register) 6208 { 0x0ff0f010, 0x01300000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateTEQReg, "teq<c> <Rn>, <Rm> {,<shift>}"}, 6209 // tst (immediate) 6210 { 0x0ff0f000, 0x03100000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateTSTImm, "tst<c> <Rn>, #const"}, 6211 // tst (register) 6212 { 0x0ff0f010, 0x01100000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateTSTReg, "tst<c> <Rn>, <Rm> {,<shift>}"}, 6213 6214 6215 // mvn (immediate) 6216 { 0x0fef0000, 0x03e00000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateMVNImm, "mvn{s}<c> <Rd>, #<const>"}, 6217 // mvn (register) 6218 { 0x0fef0010, 0x01e00000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateMVNReg, "mvn{s}<c> <Rd>, <Rm> {,<shift>}"}, 6219 // cmn (immediate) 6220 { 0x0ff0f000, 0x03700000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateCMNImm, "cmn<c> <Rn>, #<const>"}, 6221 // cmn (register) 6222 { 0x0ff0f010, 0x01700000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateCMNReg, "cmn<c> <Rn>, <Rm> {,<shift>}"}, 6223 // cmp (immediate) 6224 { 0x0ff0f000, 0x03500000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateCMPImm, "cmp<c> <Rn>, #<const>"}, 6225 // cmp (register) 6226 { 0x0ff0f010, 0x01500000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateCMPReg, "cmp<c> <Rn>, <Rm> {,<shift>}"}, 6227 // asr (immediate) 6228 { 0x0fef0070, 0x01a00040, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateASRImm, "asr{s}<c> <Rd>, <Rm>, #imm"}, 6229 // asr (register) 6230 { 0x0fef00f0, 0x01a00050, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateASRReg, "asr{s}<c> <Rd>, <Rn>, <Rm>"}, 6231 // lsl (immediate) 6232 { 0x0fef0070, 0x01a00000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLSLImm, "lsl{s}<c> <Rd>, <Rm>, #imm"}, 6233 // lsl (register) 6234 { 0x0fef00f0, 0x01a00010, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLSLReg, "lsl{s}<c> <Rd>, <Rn>, <Rm>"}, 6235 // lsr (immediate) 6236 { 0x0fef0070, 0x01a00020, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLSRImm, "lsr{s}<c> <Rd>, <Rm>, #imm"}, 6237 // lsr (register) 6238 { 0x0fef00f0, 0x01a00050, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLSRReg, "lsr{s}<c> <Rd>, <Rn>, <Rm>"}, 6239 // rrx is a special case encoding of ror (immediate) 6240 { 0x0fef0ff0, 0x01a00060, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateRRX, "rrx{s}<c> <Rd>, <Rm>"}, 6241 // ror (immediate) 6242 { 0x0fef0070, 0x01a00060, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateRORImm, "ror{s}<c> <Rd>, <Rm>, #imm"}, 6243 // ror (register) 6244 { 0x0fef00f0, 0x01a00070, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateRORReg, "ror{s}<c> <Rd>, <Rn>, <Rm>"}, 6245 6246 //---------------------------------------------------------------------- 6247 // Load instructions 6248 //---------------------------------------------------------------------- 6249 { 0x0fd00000, 0x08900000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDM, "ldm<c> <Rn>{!} <registers>" }, 6250 { 0x0fd00000, 0x08100000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDMDA, "ldmda<c> <Rn>{!} <registers>" }, 6251 { 0x0fd00000, 0x09100000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDMDB, "ldmdb<c> <Rn>{!} <registers>" }, 6252 { 0x0fd00000, 0x09900000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDMIB, "ldmib<c> <Rn<{!} <registers>" }, 6253 { 0x0e500000, 0x04100000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDRImmediateARM, "ldr<c> <Rt> [<Rn> {#+/-<imm12>}]" }, 6254 { 0x0e500010, 0x06100000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDRRegister, "ldr<c> <Rt> [<Rn> +/-<Rm> {<shift>}] {!}" }, 6255 { 0x0e5f0000, 0x045f0000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDRBLiteral, "ldrb<c> <Rt>, [...]"}, 6256 { 0xfe500010, 0x06500000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDRBRegister, "ldrb<c> <Rt>, [<Rn>,+/-<Rm>{, <shift>}]{!}" }, 6257 6258 //---------------------------------------------------------------------- 6259 // Store instructions 6260 //---------------------------------------------------------------------- 6261 { 0x0fd00000, 0x08800000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSTM, "stm<c> <Rn>{!} <registers>" }, 6262 { 0x0fd00000, 0x08000000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSTMDA, "stmda<c> <Rn>{!} <registers>" }, 6263 { 0x0fd00000, 0x09000000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSTMDB, "stmdb<c> <Rn>{!} <registers>" }, 6264 { 0x0fd00000, 0x09800000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSTMIB, "stmib<c> <Rn>{!} <registers>" }, 6265 { 0x0e500010, 0x06000000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSTRRegister, "str<c> <Rt> [<Rn> +/-<Rm> {<shift>}]{!}" } 6266 6267 6268 }; 6269 static const size_t k_num_arm_opcodes = sizeof(g_arm_opcodes)/sizeof(ARMOpcode); 6270 6271 for (size_t i=0; i<k_num_arm_opcodes; ++i) 6272 { 6273 if ((g_arm_opcodes[i].mask & opcode) == g_arm_opcodes[i].value) 6274 return &g_arm_opcodes[i]; 6275 } 6276 return NULL; 6277} 6278 6279 6280EmulateInstructionARM::ARMOpcode* 6281EmulateInstructionARM::GetThumbOpcodeForInstruction (const uint32_t opcode) 6282{ 6283 6284 static ARMOpcode 6285 g_thumb_opcodes[] = 6286 { 6287 //---------------------------------------------------------------------- 6288 // Prologue instructions 6289 //---------------------------------------------------------------------- 6290 6291 // push register(s) 6292 { 0xfffffe00, 0x0000b400, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulatePUSH, "push <registers>" }, 6293 { 0xffff0000, 0xe92d0000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulatePUSH, "push.w <registers>" }, 6294 { 0xffff0fff, 0xf84d0d04, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulatePUSH, "push.w <register>" }, 6295 6296 // set r7 to point to a stack offset 6297 { 0xffffff00, 0x0000af00, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateADDRdSPImm, "add r7, sp, #imm" }, 6298 // copy the stack pointer to r7 6299 { 0xffffffff, 0x0000466f, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateMOVRdSP, "mov r7, sp" }, 6300 // move from high register to low register (comes after "mov r7, sp" to resolve ambiguity) 6301 { 0xffffffc0, 0x00004640, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateMOVLowHigh, "mov r0-r7, r8-r15" }, 6302 6303 // PC-relative load into register (see also EmulateADDSPRm) 6304 { 0xfffff800, 0x00004800, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLDRRtPCRelative, "ldr <Rt>, [PC, #imm]"}, 6305 6306 // adjust the stack pointer 6307 { 0xffffff87, 0x00004485, ARMvAll, eEncodingT2, eSize16, &EmulateInstructionARM::EmulateADDSPRm, "add sp, <Rm>"}, 6308 { 0xffffff80, 0x0000b080, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateSUBSPImm, "add sp, sp, #imm"}, 6309 { 0xfbef8f00, 0xf1ad0d00, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateSUBSPImm, "sub.w sp, sp, #<const>"}, 6310 { 0xfbff8f00, 0xf2ad0d00, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulateSUBSPImm, "subw sp, sp, #imm12"}, 6311 6312 // vector push consecutive extension register(s) 6313 { 0xffbf0f00, 0xed2d0b00, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateVPUSH, "vpush.64 <list>"}, 6314 { 0xffbf0f00, 0xed2d0a00, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateVPUSH, "vpush.32 <list>"}, 6315 6316 //---------------------------------------------------------------------- 6317 // Epilogue instructions 6318 //---------------------------------------------------------------------- 6319 6320 { 0xffffff80, 0x0000b000, ARMvAll, eEncodingT2, eSize16, &EmulateInstructionARM::EmulateADDSPImm, "add sp, #imm"}, 6321 { 0xfffffe00, 0x0000bc00, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulatePOP, "pop <registers>"}, 6322 { 0xffff0000, 0xe8bd0000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulatePOP, "pop.w <registers>" }, 6323 { 0xffff0fff, 0xf85d0d04, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulatePOP, "pop.w <register>" }, 6324 { 0xffbf0f00, 0xecbd0b00, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateVPOP, "vpop.64 <list>"}, 6325 { 0xffbf0f00, 0xecbd0a00, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateVPOP, "vpop.32 <list>"}, 6326 6327 //---------------------------------------------------------------------- 6328 // Supervisor Call (previously Software Interrupt) 6329 //---------------------------------------------------------------------- 6330 { 0xffffff00, 0x0000df00, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateSVC, "svc #imm8"}, 6331 6332 //---------------------------------------------------------------------- 6333 // If Then makes up to four following instructions conditional. 6334 //---------------------------------------------------------------------- 6335 { 0xffffff00, 0x0000bf00, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateIT, "it{<x>{<y>{<z>}}} <firstcond>"}, 6336 6337 //---------------------------------------------------------------------- 6338 // Branch instructions 6339 //---------------------------------------------------------------------- 6340 // To resolve ambiguity, "b<c> #imm8" should come after "svc #imm8". 6341 { 0xfffff000, 0x0000d000, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateB, "b<c> #imm8 (outside IT)"}, 6342 { 0xffff8000, 0x0000e000, ARMvAll, eEncodingT2, eSize16, &EmulateInstructionARM::EmulateB, "b #imm11 (outside or last in IT)"}, 6343 { 0xf800d000, 0xf0008000, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulateB, "b<c>.w #imm8 (outside IT)"}, 6344 { 0xf800d000, 0xf0009000, ARMV6T2_ABOVE, eEncodingT4, eSize32, &EmulateInstructionARM::EmulateB, "b.w #imm8 (outside or last in IT)"}, 6345 // J1 == J2 == 1 6346 { 0xf800f800, 0xf000f800, ARMV4T_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateBLXImmediate, "bl <label>"}, 6347 // J1 == J2 == 1 6348 { 0xf800e800, 0xf000e800, ARMV5_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateBLXImmediate, "blx <label>"}, 6349 { 0xffffff87, 0x00004780, ARMV5_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateBLXRm, "blx <Rm>"}, 6350 // for example, "bx lr" 6351 { 0xffffff87, 0x00004700, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateBXRm, "bx <Rm>"}, 6352 // compare and branch 6353 { 0xfffff500, 0x0000b100, ARMV6T2_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateCB, "cb{n}z <Rn>, <label>"}, 6354 // table branch byte 6355 { 0xfff0fff0, 0xe8d0f000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateTB, "tbb<c> <Rn>, <Rm>"}, 6356 // table branch halfword 6357 { 0xfff0fff0, 0xe8d0f010, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateTB, "tbh<c> <Rn>, <Rm>, lsl #1"}, 6358 6359 //---------------------------------------------------------------------- 6360 // Data-processing instructions 6361 //---------------------------------------------------------------------- 6362 // adc (immediate) 6363 { 0xfbe08000, 0xf1400000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateADCImm, "adc{s}<c> <Rd>, <Rn>, #<const>"}, 6364 // adc (register) 6365 { 0xffffffc0, 0x00004140, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateADCReg, "adcs|adc<c> <Rdn>, <Rm>"}, 6366 { 0xffe08000, 0xeb400000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateADCReg, "adc{s}<c>.w <Rd>, <Rn>, <Rm> {,<shift>}"}, 6367 // add (register) 6368 { 0xfffffe00, 0x00001800, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateADDReg, "adds|add<c> <Rd>, <Rn>, <Rm>"}, 6369 // Make sure "add sp, <Rm>" comes before this instruction, so there's no ambiguity decoding the two. 6370 { 0xffffff00, 0x00004400, ARMvAll, eEncodingT2, eSize16, &EmulateInstructionARM::EmulateADDReg, "add<c> <Rdn>, <Rm>"}, 6371 // and (immediate) 6372 { 0xfbe08000, 0xf0000000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateANDImm, "and{s}<c> <Rd>, <Rn>, #<const>"}, 6373 // and (register) 6374 { 0xffffffc0, 0x00004000, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateANDReg, "ands|and<c> <Rdn>, <Rm>"}, 6375 { 0xffe08000, 0xea000000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateANDReg, "and{s}<c>.w <Rd>, <Rn>, <Rm> {,<shift>}"}, 6376 // eor (immediate) 6377 { 0xfbe08000, 0xf0800000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateEORImm, "eor{s}<c> <Rd>, <Rn>, #<const>"}, 6378 // eor (register) 6379 { 0xffffffc0, 0x00004040, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateEORReg, "eors|eor<c> <Rdn>, <Rm>"}, 6380 { 0xffe08000, 0xea800000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateEORReg, "eor{s}<c>.w <Rd>, <Rn>, <Rm> {,<shift>}"}, 6381 // orr (immediate) 6382 { 0xfbe08000, 0xf0400000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateORRImm, "orr{s}<c> <Rd>, <Rn>, #<const>"}, 6383 // orr (register) 6384 { 0xffffffc0, 0x00004300, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateORRReg, "orrs|orr<c> <Rdn>, <Rm>"}, 6385 { 0xffe08000, 0xea400000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateORRReg, "orr{s}<c>.w <Rd>, <Rn>, <Rm> {,<shift>}"}, 6386 // teq (immediate) 6387 { 0xfbf08f00, 0xf0900f00, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateTEQImm, "teq<c> <Rn>, #<const>"}, 6388 // teq (register) 6389 { 0xfff08f00, 0xea900f00, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateTEQReg, "teq<c> <Rn>, <Rm> {,<shift>}"}, 6390 // tst (immediate) 6391 { 0xfbf08f00, 0xf0100f00, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateTSTImm, "tst<c> <Rn>, #<const>"}, 6392 // tst (register) 6393 { 0xffffffc0, 0x00004200, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateTSTReg, "tst<c> <Rdn>, <Rm>"}, 6394 { 0xfff08f00, 0xea100f00, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateTSTReg, "tst<c>.w <Rn>, <Rm> {,<shift>}"}, 6395 6396 6397 // move from high register to high register 6398 { 0xffffff00, 0x00004600, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateMOVRdRm, "mov<c> <Rd>, <Rm>"}, 6399 // move from low register to low register 6400 { 0xffffffc0, 0x00000000, ARMvAll, eEncodingT2, eSize16, &EmulateInstructionARM::EmulateMOVRdRm, "movs <Rd>, <Rm>"}, 6401 // mov{s}<c>.w <Rd>, <Rm> 6402 { 0xffeff0f0, 0xea4f0000, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulateMOVRdRm, "mov{s}<c>.w <Rd>, <Rm>"}, 6403 // move immediate 6404 { 0xfffff800, 0x00002000, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateMOVRdImm, "movs|mov<c> <Rd>, #imm8"}, 6405 { 0xfbef8000, 0xf04f0000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateMOVRdImm, "mov{s}<c>.w <Rd>, #<const>"}, 6406 // mvn (immediate) 6407 { 0xfbef8000, 0xf06f0000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateMVNImm, "mvn{s} <Rd>, #<const>"}, 6408 // mvn (register) 6409 { 0xffffffc0, 0x000043c0, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateMVNReg, "mvns|mvn<c> <Rd>, <Rm>"}, 6410 { 0xffef8000, 0xea6f0000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateMVNReg, "mvn{s}<c>.w <Rd>, <Rm> {,<shift>}"}, 6411 // cmn (immediate) 6412 { 0xfbf08f00, 0xf1100f00, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateCMNImm, "cmn<c> <Rn>, #<const>"}, 6413 // cmn (register) 6414 { 0xffffffc0, 0x000042c0, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateCMNReg, "cmn<c> <Rn>, <Rm>"}, 6415 { 0xfff08f00, 0xeb100f00, ARMvAll, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateCMNReg, "cmn<c> <Rn>, <Rm> {,<shift>}"}, 6416 // cmp (immediate) 6417 { 0xfffff800, 0x00002800, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateCMPImm, "cmp<c> <Rn>, #imm8"}, 6418 // cmp (register) (Rn and Rm both from r0-r7) 6419 { 0xffffffc0, 0x00004280, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateCMPReg, "cmp<c> <Rn>, <Rm>"}, 6420 // cmp (register) (Rn and Rm not both from r0-r7) 6421 { 0xffffff00, 0x00004500, ARMvAll, eEncodingT2, eSize16, &EmulateInstructionARM::EmulateCMPReg, "cmp<c> <Rn>, <Rm>"}, 6422 // asr (immediate) 6423 { 0xfffff800, 0x00001000, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateASRImm, "asrs|asr<c> <Rd>, <Rm>, #imm"}, 6424 { 0xffef8030, 0xea4f0020, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateASRImm, "asr{s}<c>.w <Rd>, <Rm>, #imm"}, 6425 // asr (register) 6426 { 0xffffffc0, 0x00004100, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateASRReg, "asrs|asr<c> <Rdn>, <Rm>"}, 6427 { 0xffe0f0f0, 0xfa40f000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateASRReg, "asr{s}<c>.w <Rd>, <Rn>, <Rm>"}, 6428 // lsl (immediate) 6429 { 0xfffff800, 0x00000000, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLSLImm, "lsls|lsl<c> <Rd>, <Rm>, #imm"}, 6430 { 0xffef8030, 0xea4f0000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLSLImm, "lsl{s}<c>.w <Rd>, <Rm>, #imm"}, 6431 // lsl (register) 6432 { 0xffffffc0, 0x00004080, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLSLReg, "lsls|lsl<c> <Rdn>, <Rm>"}, 6433 { 0xffe0f0f0, 0xfa00f000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLSLReg, "lsl{s}<c>.w <Rd>, <Rn>, <Rm>"}, 6434 // lsr (immediate) 6435 { 0xfffff800, 0x00000800, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLSRImm, "lsrs|lsr<c> <Rd>, <Rm>, #imm"}, 6436 { 0xffef8030, 0xea4f0010, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLSRImm, "lsr{s}<c>.w <Rd>, <Rm>, #imm"}, 6437 // lsr (register) 6438 { 0xffffffc0, 0x000040c0, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLSRReg, "lsrs|lsr<c> <Rdn>, <Rm>"}, 6439 { 0xffe0f0f0, 0xfa20f000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLSRReg, "lsr{s}<c>.w <Rd>, <Rn>, <Rm>"}, 6440 // rrx is a special case encoding of ror (immediate) 6441 { 0xffeff0f0, 0xea4f0030, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateRRX, "rrx{s}<c>.w <Rd>, <Rm>"}, 6442 // ror (immediate) 6443 { 0xffef8030, 0xea4f0030, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateRORImm, "ror{s}<c>.w <Rd>, <Rm>, #imm"}, 6444 // ror (register) 6445 { 0xffffffc0, 0x000041c0, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateRORReg, "rors|ror<c> <Rdn>, <Rm>"}, 6446 { 0xffe0f0f0, 0xfa60f000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateRORReg, "ror{s}<c>.w <Rd>, <Rn>, <Rm>"}, 6447 6448 //---------------------------------------------------------------------- 6449 // Load instructions 6450 //---------------------------------------------------------------------- 6451 { 0xfffff800, 0x0000c800, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLDM, "ldm<c> <Rn>{!} <registers>" }, 6452 { 0xffd02000, 0xe8900000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLDM, "ldm<c>.w <Rn>{!} <registers>" }, 6453 { 0xffd00000, 0xe9100000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateLDMDB, "ldmdb<c> <Rn>{!} <registers>" }, 6454 { 0xfffff800, 0x00006800, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLDRRtRnImm, "ldr<c> <Rt>, [<Rn>{,#imm}]"}, 6455 // Thumb2 PC-relative load into register 6456 { 0xff7f0000, 0xf85f0000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLDRRtPCRelative, "ldr<c>.w <Rt>, [PC, +/-#imm}]"}, 6457 { 0xfffffe00, 0x00005800, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLDRRegister, "ldr<c> <Rt>, [<Rn>, <Rm>]" }, 6458 { 0xfff00fc0, 0xf8500000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLDRRegister, "ldr<c>.w <Rt>, [<Rn>,<Rm>{,LSL #<imm2>}]" }, 6459 { 0xfffff800, 0x00007800, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLDRBImmediate, "ldrb<c> <Rt>,[<Rn>{,#<imm5>}]" }, 6460 { 0xfff00000, 0xf8900000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLDRBImmediate, "ldrb<c>.w <Rt>,[<Rn>{,#<imm12>}]" }, 6461 { 0xfff00800, 0xf8100800, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulateLDRBImmediate, "ldrb<c> <Rt>,[>Rn>, #+/-<imm8>]{!}" }, 6462 { 0xff7f0000, 0xf81f0000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateLDRBLiteral, "ldrb<c> <Rt>,[...]" }, 6463 { 0xfffffe00, 0x00005c00, ARMV6T2_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLDRBRegister, "ldrb<c> <Rt>,[<Rn>,<Rm>]" }, 6464 { 0xfff00fc0, 0xf8100000, ARMV6T2_ABOVE, eEncodingT2, eSize32,&EmulateInstructionARM::EmulateLDRBRegister, "ldrb<c>.w <Rt>,[<Rn>,<Rm>{,LSL #imm2>}]" }, 6465 6466 //---------------------------------------------------------------------- 6467 // Store instructions 6468 //---------------------------------------------------------------------- 6469 { 0xfffff800, 0x0000c000, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateSTM, "stm<c> <Rn>{!} <registers>" }, 6470 { 0xffd00000, 0xe8800000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateSTM, "stm<c>.w <Rn>{!} <registers>" }, 6471 { 0xffd00000, 0xe9000000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateSTMDB, "stmdb<c> <Rn>{!} <registers>" }, 6472 { 0xfffff800, 0x00006000, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateSTRThumb, "str<c> <Rt>, [<Rn>{,#<imm>}]" }, 6473 { 0xfffff800, 0x00009000, ARMV4T_ABOVE, eEncodingT2, eSize16, &EmulateInstructionARM::EmulateSTRThumb, "str<c> <Rt>, [SP,#<imm>]" }, 6474 { 0xfff00000, 0xf8c00000, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulateSTRThumb, "str<c>.w <Rt>, [<Rn>,#<imm12>]" }, 6475 { 0xfff00800, 0xf8400800, ARMV6T2_ABOVE, eEncodingT4, eSize32, &EmulateInstructionARM::EmulateSTRThumb, "str<c> <Rt>, [<Rn>,#+/-<imm8>]" }, 6476 { 0xfffffe00, 0x00005000, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateSTRRegister, "str<c> <Rt> ,{<Rn>, <Rm>]" }, 6477 { 0xfff00fc0, 0xf8400000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateSTRRegister, "str<c>.w <Rt>, [<Rn>, <Rm> {lsl #imm2>}]" }, 6478 { 0xfffff800, 0x00007000, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateSTRBThumb, "strb<c> <Rt>, [<Rn>, #<imm5>]" }, 6479 { 0xfff00000, 0xf8800000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateSTRBThumb, "strb<c>.w <Rt>, [<Rn>, #<imm12>]" }, 6480 { 0xfff00800, 0xf8000800, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulateSTRBThumb, "strb<c> <Rt> ,[<Rn>, #+/-<imm8>]{!}" } 6481 }; 6482 6483 const size_t k_num_thumb_opcodes = sizeof(g_thumb_opcodes)/sizeof(ARMOpcode); 6484 for (size_t i=0; i<k_num_thumb_opcodes; ++i) 6485 { 6486 if ((g_thumb_opcodes[i].mask & opcode) == g_thumb_opcodes[i].value) 6487 return &g_thumb_opcodes[i]; 6488 } 6489 return NULL; 6490} 6491 6492bool 6493EmulateInstructionARM::SetArchitecture (const ArchSpec &arch) 6494{ 6495 m_arm_isa = 0; 6496 const char *arch_cstr = arch.AsCString (); 6497 if (arch_cstr) 6498 { 6499 if (0 == ::strcasecmp(arch_cstr, "armv4t")) m_arm_isa = ARMv4T; 6500 else if (0 == ::strcasecmp(arch_cstr, "armv4")) m_arm_isa = ARMv4; 6501 else if (0 == ::strcasecmp(arch_cstr, "armv5tej")) m_arm_isa = ARMv5TEJ; 6502 else if (0 == ::strcasecmp(arch_cstr, "armv5te")) m_arm_isa = ARMv5TE; 6503 else if (0 == ::strcasecmp(arch_cstr, "armv5t")) m_arm_isa = ARMv5T; 6504 else if (0 == ::strcasecmp(arch_cstr, "armv6k")) m_arm_isa = ARMv6K; 6505 else if (0 == ::strcasecmp(arch_cstr, "armv6")) m_arm_isa = ARMv6; 6506 else if (0 == ::strcasecmp(arch_cstr, "armv6t2")) m_arm_isa = ARMv6T2; 6507 else if (0 == ::strcasecmp(arch_cstr, "armv7")) m_arm_isa = ARMv7; 6508 else if (0 == ::strcasecmp(arch_cstr, "armv8")) m_arm_isa = ARMv8; 6509 } 6510 return m_arm_isa != 0; 6511} 6512 6513 6514bool 6515EmulateInstructionARM::ReadInstruction () 6516{ 6517 bool success = false; 6518 m_inst_cpsr = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS, 0, &success); 6519 if (success) 6520 { 6521 addr_t pc = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, LLDB_INVALID_ADDRESS, &success); 6522 if (success) 6523 { 6524 Context read_inst_context; 6525 read_inst_context.type = eContextReadOpcode; 6526 read_inst_context.SetNoArgs (); 6527 6528 if (m_inst_cpsr & MASK_CPSR_T) 6529 { 6530 m_inst_mode = eModeThumb; 6531 uint32_t thumb_opcode = MemARead(read_inst_context, pc, 2, 0, &success); 6532 6533 if (success) 6534 { 6535 if ((m_inst.opcode.inst16 & 0xe000) != 0xe000 || ((m_inst.opcode.inst16 & 0x1800u) == 0)) 6536 { 6537 m_inst.opcode_type = eOpcode16; 6538 m_inst.opcode.inst16 = thumb_opcode; 6539 } 6540 else 6541 { 6542 m_inst.opcode_type = eOpcode32; 6543 m_inst.opcode.inst32 = (thumb_opcode << 16) | MemARead(read_inst_context, pc + 2, 2, 0, &success); 6544 } 6545 } 6546 } 6547 else 6548 { 6549 m_inst_mode = eModeARM; 6550 m_inst.opcode_type = eOpcode32; 6551 m_inst.opcode.inst32 = MemARead(read_inst_context, pc, 4, 0, &success); 6552 } 6553 } 6554 } 6555 if (!success) 6556 { 6557 m_inst_mode = eModeInvalid; 6558 m_inst_pc = LLDB_INVALID_ADDRESS; 6559 } 6560 return success; 6561} 6562 6563uint32_t 6564EmulateInstructionARM::ArchVersion () 6565{ 6566 return m_arm_isa; 6567} 6568 6569bool 6570EmulateInstructionARM::ConditionPassed () 6571{ 6572 if (m_inst_cpsr == 0) 6573 return false; 6574 6575 const uint32_t cond = CurrentCond (); 6576 6577 if (cond == UINT32_MAX) 6578 return false; 6579 6580 bool result = false; 6581 switch (UnsignedBits(cond, 3, 1)) 6582 { 6583 case 0: result = (m_inst_cpsr & MASK_CPSR_Z) != 0; break; 6584 case 1: result = (m_inst_cpsr & MASK_CPSR_C) != 0; break; 6585 case 2: result = (m_inst_cpsr & MASK_CPSR_N) != 0; break; 6586 case 3: result = (m_inst_cpsr & MASK_CPSR_V) != 0; break; 6587 case 4: result = ((m_inst_cpsr & MASK_CPSR_C) != 0) && ((m_inst_cpsr & MASK_CPSR_Z) == 0); break; 6588 case 5: 6589 { 6590 bool n = (m_inst_cpsr & MASK_CPSR_N); 6591 bool v = (m_inst_cpsr & MASK_CPSR_V); 6592 result = n == v; 6593 } 6594 break; 6595 case 6: 6596 { 6597 bool n = (m_inst_cpsr & MASK_CPSR_N); 6598 bool v = (m_inst_cpsr & MASK_CPSR_V); 6599 result = n == v && ((m_inst_cpsr & MASK_CPSR_Z) == 0); 6600 } 6601 break; 6602 case 7: 6603 result = true; 6604 break; 6605 } 6606 6607 if (cond & 1) 6608 result = !result; 6609 return result; 6610} 6611 6612uint32_t 6613EmulateInstructionARM::CurrentCond () 6614{ 6615 switch (m_inst_mode) 6616 { 6617 default: 6618 case eModeInvalid: 6619 break; 6620 6621 case eModeARM: 6622 return UnsignedBits(m_inst.opcode.inst32, 31, 28); 6623 6624 case eModeThumb: 6625 // For T1 and T3 encodings of the Branch instruction, it returns the 4-bit 6626 // 'cond' field of the encoding. 6627 if (m_inst.opcode_type == eOpcode16 && 6628 Bits32(m_inst.opcode.inst16, 15, 12) == 0x0d && 6629 Bits32(m_inst.opcode.inst16, 11, 7) != 0x0f) 6630 { 6631 return Bits32(m_inst.opcode.inst16, 11, 7); 6632 } 6633 else if (m_inst.opcode_type == eOpcode32 && 6634 Bits32(m_inst.opcode.inst32, 31, 27) == 0x1e && 6635 Bits32(m_inst.opcode.inst32, 15, 14) == 0x02 && 6636 Bits32(m_inst.opcode.inst32, 12, 12) == 0x00 && 6637 Bits32(m_inst.opcode.inst32, 25, 22) <= 0x0d) 6638 { 6639 return Bits32(m_inst.opcode.inst32, 25, 22); 6640 } 6641 6642 return m_it_session.GetCond(); 6643 } 6644 return UINT32_MAX; // Return invalid value 6645} 6646 6647bool 6648EmulateInstructionARM::InITBlock() 6649{ 6650 return CurrentInstrSet() == eModeThumb && m_it_session.InITBlock(); 6651} 6652 6653bool 6654EmulateInstructionARM::LastInITBlock() 6655{ 6656 return CurrentInstrSet() == eModeThumb && m_it_session.LastInITBlock(); 6657} 6658 6659bool 6660EmulateInstructionARM::BranchWritePC (const Context &context, uint32_t addr) 6661{ 6662 addr_t target; 6663 6664 // Check the current instruction set. 6665 if (CurrentInstrSet() == eModeARM) 6666 target = addr & 0xfffffffc; 6667 else 6668 target = addr & 0xfffffffe; 6669 6670 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, target)) 6671 return false; 6672 6673 return true; 6674} 6675 6676// As a side effect, BXWritePC sets context.arg2 to eModeARM or eModeThumb by inspecting addr. 6677bool 6678EmulateInstructionARM::BXWritePC (Context &context, uint32_t addr) 6679{ 6680 addr_t target; 6681 // If the CPSR is changed due to switching between ARM and Thumb ISETSTATE, 6682 // we want to record it and issue a WriteRegister callback so the clients 6683 // can track the mode changes accordingly. 6684 bool cpsr_changed = false; 6685 6686 if (BitIsSet(addr, 0)) 6687 { 6688 if (CurrentInstrSet() != eModeThumb) 6689 { 6690 SelectInstrSet(eModeThumb); 6691 cpsr_changed = true; 6692 } 6693 target = addr & 0xfffffffe; 6694 context.SetMode (eModeThumb); 6695 } 6696 else if (BitIsClear(addr, 1)) 6697 { 6698 if (CurrentInstrSet() != eModeARM) 6699 { 6700 SelectInstrSet(eModeARM); 6701 cpsr_changed = true; 6702 } 6703 target = addr & 0xfffffffc; 6704 context.SetMode (eModeARM); 6705 } 6706 else 6707 return false; // address<1:0> == '10' => UNPREDICTABLE 6708 6709 if (cpsr_changed) 6710 { 6711 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS, m_new_inst_cpsr)) 6712 return false; 6713 } 6714 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, target)) 6715 return false; 6716 6717 return true; 6718} 6719 6720// Dispatches to either BXWritePC or BranchWritePC based on architecture versions. 6721bool 6722EmulateInstructionARM::LoadWritePC (Context &context, uint32_t addr) 6723{ 6724 if (ArchVersion() >= ARMv5T) 6725 return BXWritePC(context, addr); 6726 else 6727 return BranchWritePC((const Context)context, addr); 6728} 6729 6730// Dispatches to either BXWritePC or BranchWritePC based on architecture versions and current instruction set. 6731bool 6732EmulateInstructionARM::ALUWritePC (Context &context, uint32_t addr) 6733{ 6734 if (ArchVersion() >= ARMv7 && CurrentInstrSet() == eModeARM) 6735 return BXWritePC(context, addr); 6736 else 6737 return BranchWritePC((const Context)context, addr); 6738} 6739 6740EmulateInstructionARM::Mode 6741EmulateInstructionARM::CurrentInstrSet () 6742{ 6743 return m_inst_mode; 6744} 6745 6746// Set the 'T' bit of our CPSR. The m_inst_mode gets updated when the next 6747// ReadInstruction() is performed. This function has a side effect of updating 6748// the m_new_inst_cpsr member variable if necessary. 6749bool 6750EmulateInstructionARM::SelectInstrSet (Mode arm_or_thumb) 6751{ 6752 m_new_inst_cpsr = m_inst_cpsr; 6753 switch (arm_or_thumb) 6754 { 6755 default: 6756 return false; 6757 eModeARM: 6758 // Clear the T bit. 6759 m_new_inst_cpsr &= ~MASK_CPSR_T; 6760 break; 6761 eModeThumb: 6762 // Set the T bit. 6763 m_new_inst_cpsr |= MASK_CPSR_T; 6764 break; 6765 } 6766 return true; 6767} 6768 6769// This function returns TRUE if the processor currently provides support for 6770// unaligned memory accesses, or FALSE otherwise. This is always TRUE in ARMv7, 6771// controllable by the SCTLR.U bit in ARMv6, and always FALSE before ARMv6. 6772bool 6773EmulateInstructionARM::UnalignedSupport() 6774{ 6775 return (ArchVersion() >= ARMv7); 6776} 6777 6778// The main addition and subtraction instructions can produce status information 6779// about both unsigned carry and signed overflow conditions. This status 6780// information can be used to synthesize multi-word additions and subtractions. 6781EmulateInstructionARM::AddWithCarryResult 6782EmulateInstructionARM::AddWithCarry (uint32_t x, uint32_t y, uint8_t carry_in) 6783{ 6784 uint32_t result; 6785 uint8_t carry_out; 6786 uint8_t overflow; 6787 6788 uint64_t unsigned_sum = x + y + carry_in; 6789 int64_t signed_sum = (int32_t)x + (int32_t)y + (int32_t)carry_in; 6790 6791 result = UnsignedBits(unsigned_sum, 31, 0); 6792 carry_out = (result == unsigned_sum ? 0 : 1); 6793 overflow = ((int32_t)result == signed_sum ? 0 : 1); 6794 6795 AddWithCarryResult res = { result, carry_out, overflow }; 6796 return res; 6797} 6798 6799uint32_t 6800EmulateInstructionARM::ReadCoreReg(uint32_t num, bool *success) 6801{ 6802 uint32_t reg_kind, reg_num; 6803 switch (num) 6804 { 6805 case SP_REG: 6806 reg_kind = eRegisterKindGeneric; 6807 reg_num = LLDB_REGNUM_GENERIC_SP; 6808 break; 6809 case LR_REG: 6810 reg_kind = eRegisterKindGeneric; 6811 reg_num = LLDB_REGNUM_GENERIC_RA; 6812 break; 6813 case PC_REG: 6814 reg_kind = eRegisterKindGeneric; 6815 reg_num = LLDB_REGNUM_GENERIC_PC; 6816 break; 6817 default: 6818 if (0 <= num && num < SP_REG) 6819 { 6820 reg_kind = eRegisterKindDWARF; 6821 reg_num = dwarf_r0 + num; 6822 } 6823 else 6824 { 6825 assert(0 && "Invalid register number"); 6826 *success = false; 6827 return ~0u; 6828 } 6829 break; 6830 } 6831 6832 // Read our register. 6833 uint32_t val = ReadRegisterUnsigned (reg_kind, reg_num, 0, success); 6834 6835 // When executing an ARM instruction , PC reads as the address of the current 6836 // instruction plus 8. 6837 // When executing a Thumb instruction , PC reads as the address of the current 6838 // instruction plus 4. 6839 if (num == 15) 6840 { 6841 if (CurrentInstrSet() == eModeARM) 6842 val += 8; 6843 else 6844 val += 4; 6845 } 6846 6847 return val; 6848} 6849 6850// Write the result to the ARM core register Rd, and optionally update the 6851// condition flags based on the result. 6852// 6853// This helper method tries to encapsulate the following pseudocode from the 6854// ARM Architecture Reference Manual: 6855// 6856// if d == 15 then // Can only occur for encoding A1 6857// ALUWritePC(result); // setflags is always FALSE here 6858// else 6859// R[d] = result; 6860// if setflags then 6861// APSR.N = result<31>; 6862// APSR.Z = IsZeroBit(result); 6863// APSR.C = carry; 6864// // APSR.V unchanged 6865// 6866// In the above case, the API client does not pass in the overflow arg, which 6867// defaults to ~0u. 6868bool 6869EmulateInstructionARM::WriteCoreRegOptionalFlags (Context &context, 6870 const uint32_t result, 6871 const uint32_t Rd, 6872 bool setflags, 6873 const uint32_t carry, 6874 const uint32_t overflow) 6875{ 6876 if (Rd == 15) 6877 { 6878 if (!ALUWritePC (context, result)) 6879 return false; 6880 } 6881 else 6882 { 6883 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + Rd, result)) 6884 return false; 6885 if (setflags) 6886 return WriteFlags (context, result, carry, overflow); 6887 } 6888 return true; 6889} 6890 6891// This helper method tries to encapsulate the following pseudocode from the 6892// ARM Architecture Reference Manual: 6893// 6894// APSR.N = result<31>; 6895// APSR.Z = IsZeroBit(result); 6896// APSR.C = carry; 6897// APSR.V = overflow 6898// 6899// Default arguments can be specified for carry and overflow parameters, which means 6900// not to update the respective flags. 6901bool 6902EmulateInstructionARM::WriteFlags (Context &context, 6903 const uint32_t result, 6904 const uint32_t carry, 6905 const uint32_t overflow) 6906{ 6907 m_new_inst_cpsr = m_inst_cpsr; 6908 SetBit32(m_new_inst_cpsr, CPSR_N, Bit32(result, CPSR_N)); 6909 SetBit32(m_new_inst_cpsr, CPSR_Z, result == 0 ? 1 : 0); 6910 if (carry != ~0u) 6911 SetBit32(m_new_inst_cpsr, CPSR_C, carry); 6912 if (overflow != ~0u) 6913 SetBit32(m_new_inst_cpsr, CPSR_V, overflow); 6914 if (m_new_inst_cpsr != m_inst_cpsr) 6915 { 6916 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS, m_new_inst_cpsr)) 6917 return false; 6918 } 6919 return true; 6920} 6921 6922bool 6923EmulateInstructionARM::EvaluateInstruction () 6924{ 6925 // Advance the ITSTATE bits to their values for the next instruction. 6926 if (m_inst_mode == eModeThumb && m_it_session.InITBlock()) 6927 m_it_session.ITAdvance(); 6928 6929 return false; 6930} 6931