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