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