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