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