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