EmulateInstructionARM.cpp revision 93767b8fceecd605d3e3dc3803b7d51823f17b2f
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_opcode_cpsr, CPSR_C_POS) 28#define APSR_V Bit32(m_opcode_cpsr, CPSR_V_POS) 29 30#define AlignPC(pc_val) (pc_val & 0xFFFFFFFC) 31 32//---------------------------------------------------------------------- 33// 34// ITSession implementation 35// 36//---------------------------------------------------------------------- 37 38// A8.6.50 39// Valid return values are {1, 2, 3, 4}, with 0 signifying an error condition. 40static unsigned short CountITSize(unsigned ITMask) { 41 // First count the trailing zeros of the IT mask. 42 unsigned TZ = llvm::CountTrailingZeros_32(ITMask); 43 if (TZ > 3) 44 { 45 printf("Encoding error: IT Mask '0000'\n"); 46 return 0; 47 } 48 return (4 - TZ); 49} 50 51// Init ITState. Note that at least one bit is always 1 in mask. 52bool ITSession::InitIT(unsigned short bits7_0) 53{ 54 ITCounter = CountITSize(Bits32(bits7_0, 3, 0)); 55 if (ITCounter == 0) 56 return false; 57 58 // A8.6.50 IT 59 unsigned short FirstCond = Bits32(bits7_0, 7, 4); 60 if (FirstCond == 0xF) 61 { 62 printf("Encoding error: IT FirstCond '1111'\n"); 63 return false; 64 } 65 if (FirstCond == 0xE && ITCounter != 1) 66 { 67 printf("Encoding error: IT FirstCond '1110' && Mask != '1000'\n"); 68 return false; 69 } 70 71 ITState = bits7_0; 72 return true; 73} 74 75// Update ITState if necessary. 76void ITSession::ITAdvance() 77{ 78 assert(ITCounter); 79 --ITCounter; 80 if (ITCounter == 0) 81 ITState = 0; 82 else 83 { 84 unsigned short NewITState4_0 = Bits32(ITState, 4, 0) << 1; 85 SetBits32(ITState, 4, 0, NewITState4_0); 86 } 87} 88 89// Return true if we're inside an IT Block. 90bool ITSession::InITBlock() 91{ 92 return ITCounter != 0; 93} 94 95// Return true if we're the last instruction inside an IT Block. 96bool ITSession::LastInITBlock() 97{ 98 return ITCounter == 1; 99} 100 101// Get condition bits for the current thumb instruction. 102uint32_t ITSession::GetCond() 103{ 104 if (InITBlock()) 105 return Bits32(ITState, 7, 4); 106 else 107 return COND_AL; 108} 109 110// ARM constants used during decoding 111#define REG_RD 0 112#define LDM_REGLIST 1 113#define SP_REG 13 114#define LR_REG 14 115#define PC_REG 15 116#define PC_REGLIST_BIT 0x8000 117 118#define ARMv4 (1u << 0) 119#define ARMv4T (1u << 1) 120#define ARMv5T (1u << 2) 121#define ARMv5TE (1u << 3) 122#define ARMv5TEJ (1u << 4) 123#define ARMv6 (1u << 5) 124#define ARMv6K (1u << 6) 125#define ARMv6T2 (1u << 7) 126#define ARMv7 (1u << 8) 127#define ARMv8 (1u << 9) 128#define ARMvAll (0xffffffffu) 129 130#define ARMV4T_ABOVE (ARMv4T|ARMv5T|ARMv5TE|ARMv5TEJ|ARMv6|ARMv6K|ARMv6T2|ARMv7|ARMv8) 131#define ARMV5_ABOVE (ARMv5T|ARMv5TE|ARMv5TEJ|ARMv6|ARMv6K|ARMv6T2|ARMv7|ARMv8) 132#define ARMV5TE_ABOVE (ARMv5TE|ARMv5TEJ|ARMv6|ARMv6K|ARMv6T2|ARMv7|ARMv8) 133#define ARMV5J_ABOVE (ARMv5TEJ|ARMv6|ARMv6K|ARMv6T2|ARMv7|ARMv8) 134#define ARMV6_ABOVE (ARMv6|ARMv6K|ARMv6T2|ARMv7|ARMv8) 135#define ARMV6T2_ABOVE (ARMv6T2|ARMv7|ARMv8) 136 137#define No_VFP 0 138#define VFPv1 (1u << 1) 139#define VFPv2 (1u << 2) 140#define VFPv3 (1u << 3) 141#define AdvancedSIMD (1u << 4) 142 143#define VFPv1_ABOVE (VFPv1 | VFPv2 | VFPv3 | AdvancedSIMD) 144#define VFPv2_ABOVE (VFPv2 | VFPv3 | AdvancedSIMD) 145#define VFPv2v3 (VFPv2 | VFPv3) 146 147//---------------------------------------------------------------------- 148// 149// EmulateInstructionARM implementation 150// 151//---------------------------------------------------------------------- 152 153void 154EmulateInstructionARM::Initialize () 155{ 156} 157 158void 159EmulateInstructionARM::Terminate () 160{ 161} 162 163// Write "bits (32) UNKNOWN" to memory address "address". Helper function for many ARM instructions. 164bool 165EmulateInstructionARM::WriteBits32UnknownToMemory (addr_t address) 166{ 167 EmulateInstruction::Context context; 168 context.type = EmulateInstruction::eContextWriteMemoryRandomBits; 169 context.SetNoArgs (); 170 171 uint32_t random_data = rand (); 172 const uint32_t addr_byte_size = GetAddressByteSize(); 173 174 if (!MemAWrite (context, address, random_data, addr_byte_size)) 175 return false; 176 177 return true; 178} 179 180// Write "bits (32) UNKNOWN" to register n. Helper function for many ARM instructions. 181bool 182EmulateInstructionARM::WriteBits32Unknown (int n) 183{ 184 EmulateInstruction::Context context; 185 context.type = EmulateInstruction::eContextWriteRegisterRandomBits; 186 context.SetNoArgs (); 187 188 bool success; 189 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success); 190 191 if (!success) 192 return false; 193 194 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, data)) 195 return false; 196 197 return true; 198} 199 200// Push Multiple Registers stores multiple registers to the stack, storing to 201// consecutive memory locations ending just below the address in SP, and updates 202// SP to point to the start of the stored data. 203bool 204EmulateInstructionARM::EmulatePUSH (const uint32_t opcode, const ARMEncoding encoding) 205{ 206#if 0 207 // ARM pseudo code... 208 if (ConditionPassed()) 209 { 210 EncodingSpecificOperations(); 211 NullCheckIfThumbEE(13); 212 address = SP - 4*BitCount(registers); 213 214 for (i = 0 to 14) 215 { 216 if (registers<i> == '1') 217 { 218 if i == 13 && i != LowestSetBit(registers) // Only possible for encoding A1 219 MemA[address,4] = bits(32) UNKNOWN; 220 else 221 MemA[address,4] = R[i]; 222 address = address + 4; 223 } 224 } 225 226 if (registers<15> == '1') // Only possible for encoding A1 or A2 227 MemA[address,4] = PCStoreValue(); 228 229 SP = SP - 4*BitCount(registers); 230 } 231#endif 232 233 bool success = false; 234 if (ConditionPassed(opcode)) 235 { 236 const uint32_t addr_byte_size = GetAddressByteSize(); 237 const addr_t sp = ReadCoreReg (SP_REG, &success); 238 if (!success) 239 return false; 240 uint32_t registers = 0; 241 uint32_t Rt; // the source register 242 switch (encoding) { 243 case eEncodingT1: 244 registers = Bits32(opcode, 7, 0); 245 // The M bit represents LR. 246 if (Bit32(opcode, 8)) 247 registers |= (1u << 14); 248 // if BitCount(registers) < 1 then UNPREDICTABLE; 249 if (BitCount(registers) < 1) 250 return false; 251 break; 252 case eEncodingT2: 253 // Ignore bits 15 & 13. 254 registers = Bits32(opcode, 15, 0) & ~0xa000; 255 // if BitCount(registers) < 2 then UNPREDICTABLE; 256 if (BitCount(registers) < 2) 257 return false; 258 break; 259 case eEncodingT3: 260 Rt = Bits32(opcode, 15, 12); 261 // if BadReg(t) then UNPREDICTABLE; 262 if (BadReg(Rt)) 263 return false; 264 registers = (1u << Rt); 265 break; 266 case eEncodingA1: 267 registers = Bits32(opcode, 15, 0); 268 // Instead of return false, let's handle the following case as well, 269 // which amounts to pushing one reg onto the full descending stacks. 270 // if BitCount(register_list) < 2 then SEE STMDB / STMFD; 271 break; 272 case eEncodingA2: 273 Rt = Bits32(opcode, 15, 12); 274 // if t == 13 then UNPREDICTABLE; 275 if (Rt == dwarf_sp) 276 return false; 277 registers = (1u << Rt); 278 break; 279 default: 280 return false; 281 } 282 addr_t sp_offset = addr_byte_size * BitCount (registers); 283 addr_t addr = sp - sp_offset; 284 uint32_t i; 285 286 EmulateInstruction::Context context; 287 context.type = EmulateInstruction::eContextPushRegisterOnStack; 288 Register dwarf_reg; 289 dwarf_reg.SetRegister (eRegisterKindDWARF, 0); 290 Register sp_reg; 291 sp_reg.SetRegister (eRegisterKindDWARF, dwarf_sp); 292 for (i=0; i<15; ++i) 293 { 294 if (BitIsSet (registers, i)) 295 { 296 dwarf_reg.num = dwarf_r0 + i; 297 context.SetRegisterToRegisterPlusOffset (dwarf_reg, sp_reg, addr - sp); 298 uint32_t reg_value = ReadCoreReg(i, &success); 299 if (!success) 300 return false; 301 if (!MemAWrite (context, addr, reg_value, addr_byte_size)) 302 return false; 303 addr += addr_byte_size; 304 } 305 } 306 307 if (BitIsSet (registers, 15)) 308 { 309 dwarf_reg.num = dwarf_pc; 310 context.SetRegisterPlusOffset (dwarf_reg, addr - sp); 311 const uint32_t pc = ReadCoreReg(PC_REG, &success); 312 if (!success) 313 return false; 314 if (!MemAWrite (context, addr, pc, addr_byte_size)) 315 return false; 316 } 317 318 context.type = EmulateInstruction::eContextAdjustStackPointer; 319 context.SetImmediateSigned (-sp_offset); 320 321 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, sp - sp_offset)) 322 return false; 323 } 324 return true; 325} 326 327// Pop Multiple Registers loads multiple registers from the stack, loading from 328// consecutive memory locations staring at the address in SP, and updates 329// SP to point just above the loaded data. 330bool 331EmulateInstructionARM::EmulatePOP (const uint32_t opcode, const ARMEncoding encoding) 332{ 333#if 0 334 // ARM pseudo code... 335 if (ConditionPassed()) 336 { 337 EncodingSpecificOperations(); NullCheckIfThumbEE(13); 338 address = SP; 339 for i = 0 to 14 340 if registers<i> == '1' then 341 R[i} = if UnalignedAllowed then MemU[address,4] else MemA[address,4]; address = address + 4; 342 if registers<15> == '1' then 343 if UnalignedAllowed then 344 LoadWritePC(MemU[address,4]); 345 else 346 LoadWritePC(MemA[address,4]); 347 if registers<13> == '0' then SP = SP + 4*BitCount(registers); 348 if registers<13> == '1' then SP = bits(32) UNKNOWN; 349 } 350#endif 351 352 bool success = false; 353 354 if (ConditionPassed(opcode)) 355 { 356 const uint32_t addr_byte_size = GetAddressByteSize(); 357 const addr_t sp = ReadCoreReg (SP_REG, &success); 358 if (!success) 359 return false; 360 uint32_t registers = 0; 361 uint32_t Rt; // the destination register 362 switch (encoding) { 363 case eEncodingT1: 364 registers = Bits32(opcode, 7, 0); 365 // The P bit represents PC. 366 if (Bit32(opcode, 8)) 367 registers |= (1u << 15); 368 // if BitCount(registers) < 1 then UNPREDICTABLE; 369 if (BitCount(registers) < 1) 370 return false; 371 break; 372 case eEncodingT2: 373 // Ignore bit 13. 374 registers = Bits32(opcode, 15, 0) & ~0x2000; 375 // if BitCount(registers) < 2 || (P == '1' && M == '1') then UNPREDICTABLE; 376 if (BitCount(registers) < 2 || (Bit32(opcode, 15) && Bit32(opcode, 14))) 377 return false; 378 // if registers<15> == '1' && InITBlock() && !LastInITBlock() then UNPREDICTABLE; 379 if (BitIsSet(registers, 15) && InITBlock() && !LastInITBlock()) 380 return false; 381 break; 382 case eEncodingT3: 383 Rt = Bits32(opcode, 15, 12); 384 // if t == 13 || (t == 15 && InITBlock() && !LastInITBlock()) then UNPREDICTABLE; 385 if (Rt == 13) 386 return false; 387 if (Rt == 15 && InITBlock() && !LastInITBlock()) 388 return false; 389 registers = (1u << Rt); 390 break; 391 case eEncodingA1: 392 registers = Bits32(opcode, 15, 0); 393 // Instead of return false, let's handle the following case as well, 394 // which amounts to popping one reg from the full descending stacks. 395 // if BitCount(register_list) < 2 then SEE LDM / LDMIA / LDMFD; 396 397 // if registers<13> == '1' && ArchVersion() >= 7 then UNPREDICTABLE; 398 if (BitIsSet(opcode, 13) && ArchVersion() >= ARMv7) 399 return false; 400 break; 401 case eEncodingA2: 402 Rt = Bits32(opcode, 15, 12); 403 // if t == 13 then UNPREDICTABLE; 404 if (Rt == dwarf_sp) 405 return false; 406 registers = (1u << Rt); 407 break; 408 default: 409 return false; 410 } 411 addr_t sp_offset = addr_byte_size * BitCount (registers); 412 addr_t addr = sp; 413 uint32_t i, data; 414 415 EmulateInstruction::Context context; 416 context.type = EmulateInstruction::eContextPopRegisterOffStack; 417 Register dwarf_reg; 418 dwarf_reg.SetRegister (eRegisterKindDWARF, 0); 419 Register sp_reg; 420 sp_reg.SetRegister (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP); 421 for (i=0; i<15; ++i) 422 { 423 if (BitIsSet (registers, i)) 424 { 425 dwarf_reg.num = dwarf_r0 + i; 426 context.SetRegisterPlusOffset (sp_reg, addr - sp); 427 data = MemARead(context, addr, 4, 0, &success); 428 if (!success) 429 return false; 430 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_reg.num, data)) 431 return false; 432 addr += addr_byte_size; 433 } 434 } 435 436 if (BitIsSet (registers, 15)) 437 { 438 dwarf_reg.num = dwarf_pc; 439 context.SetRegisterPlusOffset (sp_reg, addr - sp); 440 data = MemARead(context, addr, 4, 0, &success); 441 if (!success) 442 return false; 443 // In ARMv5T and above, this is an interworking branch. 444 if (!LoadWritePC(context, data)) 445 return false; 446 addr += addr_byte_size; 447 } 448 449 context.type = EmulateInstruction::eContextAdjustStackPointer; 450 context.SetImmediateSigned (sp_offset); 451 452 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, sp + sp_offset)) 453 return false; 454 } 455 return true; 456} 457 458// Set r7 or ip to point to saved value residing within the stack. 459// ADD (SP plus immediate) 460bool 461EmulateInstructionARM::EmulateADDRdSPImm (const uint32_t opcode, const ARMEncoding encoding) 462{ 463#if 0 464 // ARM pseudo code... 465 if (ConditionPassed()) 466 { 467 EncodingSpecificOperations(); 468 (result, carry, overflow) = AddWithCarry(SP, imm32, '0'); 469 if d == 15 then 470 ALUWritePC(result); // setflags is always FALSE here 471 else 472 R[d] = result; 473 if setflags then 474 APSR.N = result<31>; 475 APSR.Z = IsZeroBit(result); 476 APSR.C = carry; 477 APSR.V = overflow; 478 } 479#endif 480 481 bool success = false; 482 483 if (ConditionPassed(opcode)) 484 { 485 const addr_t sp = ReadCoreReg (SP_REG, &success); 486 if (!success) 487 return false; 488 uint32_t Rd; // the destination register 489 uint32_t imm32; 490 switch (encoding) { 491 case eEncodingT1: 492 Rd = 7; 493 imm32 = Bits32(opcode, 7, 0) << 2; // imm32 = ZeroExtend(imm8:'00', 32) 494 break; 495 case eEncodingA1: 496 Rd = Bits32(opcode, 15, 12); 497 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12) 498 break; 499 default: 500 return false; 501 } 502 addr_t sp_offset = imm32; 503 addr_t addr = sp + sp_offset; // a pointer to the stack area 504 505 EmulateInstruction::Context context; 506 context.type = EmulateInstruction::eContextRegisterPlusOffset; 507 Register sp_reg; 508 sp_reg.SetRegister (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP); 509 context.SetRegisterPlusOffset (sp_reg, sp_offset); 510 511 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + Rd, addr)) 512 return false; 513 } 514 return true; 515} 516 517// Set r7 or ip to the current stack pointer. 518// MOV (register) 519bool 520EmulateInstructionARM::EmulateMOVRdSP (const uint32_t opcode, const ARMEncoding encoding) 521{ 522#if 0 523 // ARM pseudo code... 524 if (ConditionPassed()) 525 { 526 EncodingSpecificOperations(); 527 result = R[m]; 528 if d == 15 then 529 ALUWritePC(result); // setflags is always FALSE here 530 else 531 R[d] = result; 532 if setflags then 533 APSR.N = result<31>; 534 APSR.Z = IsZeroBit(result); 535 // APSR.C unchanged 536 // APSR.V unchanged 537 } 538#endif 539 540 bool success = false; 541 542 if (ConditionPassed(opcode)) 543 { 544 const addr_t sp = ReadCoreReg (SP_REG, &success); 545 if (!success) 546 return false; 547 uint32_t Rd; // the destination register 548 switch (encoding) { 549 case eEncodingT1: 550 Rd = 7; 551 break; 552 case eEncodingA1: 553 Rd = 12; 554 break; 555 default: 556 return false; 557 } 558 559 EmulateInstruction::Context context; 560 context.type = EmulateInstruction::eContextRegisterPlusOffset; 561 Register sp_reg; 562 sp_reg.SetRegister (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP); 563 context.SetRegisterPlusOffset (sp_reg, 0); 564 565 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + Rd, sp)) 566 return false; 567 } 568 return true; 569} 570 571// Move from high register (r8-r15) to low register (r0-r7). 572// MOV (register) 573bool 574EmulateInstructionARM::EmulateMOVLowHigh (const uint32_t opcode, const ARMEncoding encoding) 575{ 576 return EmulateMOVRdRm (opcode, encoding); 577} 578 579// Move from register to register. 580// MOV (register) 581bool 582EmulateInstructionARM::EmulateMOVRdRm (const uint32_t opcode, const ARMEncoding encoding) 583{ 584#if 0 585 // ARM pseudo code... 586 if (ConditionPassed()) 587 { 588 EncodingSpecificOperations(); 589 result = R[m]; 590 if d == 15 then 591 ALUWritePC(result); // setflags is always FALSE here 592 else 593 R[d] = result; 594 if setflags then 595 APSR.N = result<31>; 596 APSR.Z = IsZeroBit(result); 597 // APSR.C unchanged 598 // APSR.V unchanged 599 } 600#endif 601 602 bool success = false; 603 604 if (ConditionPassed(opcode)) 605 { 606 uint32_t Rm; // the source register 607 uint32_t Rd; // the destination register 608 bool setflags; 609 switch (encoding) { 610 case eEncodingT1: 611 Rd = Bit32(opcode, 7) << 3 | Bits32(opcode, 2, 0); 612 Rm = Bits32(opcode, 6, 3); 613 setflags = false; 614 if (Rd == 15 && InITBlock() && !LastInITBlock()) 615 return false; 616 break; 617 case eEncodingT2: 618 Rd = Bits32(opcode, 2, 0); 619 Rm = Bits32(opcode, 5, 3); 620 setflags = true; 621 if (InITBlock()) 622 return false; 623 break; 624 case eEncodingT3: 625 Rd = Bits32(opcode, 11, 8); 626 Rm = Bits32(opcode, 3, 0); 627 setflags = BitIsSet(opcode, 20); 628 // if setflags && (BadReg(d) || BadReg(m)) then UNPREDICTABLE; 629 if (setflags && (BadReg(Rd) || BadReg(Rm))) 630 return false; 631 // if !setflags && (d == 15 || m == 15 || (d == 13 && m == 13)) then UNPREDICTABLE; 632 if (!setflags && (Rd == 15 || Rm == 15 || (Rd == 13 && Rm == 13))) 633 return false; 634 break; 635 case eEncodingA1: 636 Rd = Bits32(opcode, 15, 12); 637 Rm = Bits32(opcode, 3, 0); 638 setflags = BitIsSet(opcode, 20); 639 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions; 640 // TODO: Emulate SUBS PC, LR and related instructions. 641 if (Rd == 15 && setflags) 642 return false; 643 break; 644 default: 645 return false; 646 } 647 uint32_t result = ReadCoreReg(Rm, &success); 648 if (!success) 649 return false; 650 651 // The context specifies that Rm is to be moved into Rd. 652 EmulateInstruction::Context context; 653 context.type = EmulateInstruction::eContextRegisterLoad; 654 Register dwarf_reg; 655 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + Rm); 656 context.SetRegister (dwarf_reg); 657 658 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags)) 659 return false; 660 } 661 return true; 662} 663 664// Move (immediate) writes an immediate value to the destination register. It 665// can optionally update the condition flags based on the value. 666// MOV (immediate) 667bool 668EmulateInstructionARM::EmulateMOVRdImm (const uint32_t opcode, const ARMEncoding encoding) 669{ 670#if 0 671 // ARM pseudo code... 672 if (ConditionPassed()) 673 { 674 EncodingSpecificOperations(); 675 result = imm32; 676 if d == 15 then // Can only occur for ARM encoding 677 ALUWritePC(result); // setflags is always FALSE here 678 else 679 R[d] = result; 680 if setflags then 681 APSR.N = result<31>; 682 APSR.Z = IsZeroBit(result); 683 APSR.C = carry; 684 // APSR.V unchanged 685 } 686#endif 687 688 if (ConditionPassed(opcode)) 689 { 690 uint32_t Rd; // the destination register 691 uint32_t imm32; // the immediate value to be written to Rd 692 uint32_t carry; // the carry bit after ThumbExpandImm_C or ARMExpandImm_C. 693 bool setflags; 694 switch (encoding) { 695 case eEncodingT1: 696 Rd = Bits32(opcode, 10, 8); 697 setflags = !InITBlock(); 698 imm32 = Bits32(opcode, 7, 0); // imm32 = ZeroExtend(imm8, 32) 699 carry = APSR_C; 700 701 break; 702 703 case eEncodingT2: 704 Rd = Bits32(opcode, 11, 8); 705 setflags = BitIsSet(opcode, 20); 706 imm32 = ThumbExpandImm_C(opcode, APSR_C, carry); 707 if (BadReg(Rd)) 708 return false; 709 710 break; 711 712 case eEncodingT3: 713 { 714 // d = UInt(Rd); setflags = FALSE; imm32 = ZeroExtend(imm4:i:imm3:imm8, 32); 715 Rd = Bits32 (opcode, 11, 8); 716 setflags = false; 717 uint32_t imm4 = Bits32 (opcode, 19, 16); 718 uint32_t imm3 = Bits32 (opcode, 14, 12); 719 uint32_t i = Bit32 (opcode, 26); 720 uint32_t imm8 = Bits32 (opcode, 7, 0); 721 imm32 = (imm4 << 12) | (i << 11) | (imm3 << 8) | imm8; 722 723 // if BadReg(d) then UNPREDICTABLE; 724 if (BadReg (Rd)) 725 return false; 726 } 727 break; 728 729 case eEncodingA1: 730 // if Rd == ‘1111’ && S == ‘1’ then SEE SUBS PC, LR and related instructions; 731 // d = UInt(Rd); setflags = (S == ‘1’); (imm32, carry) = ARMExpandImm_C(imm12, APSR.C); 732 Rd = Bits32 (opcode, 15, 12); 733 setflags = BitIsSet (opcode, 20); 734 imm32 = ARMExpandImm_C (opcode, APSR_C, carry); 735 736 break; 737 738 case eEncodingA2: 739 { 740 // d = UInt(Rd); setflags = FALSE; imm32 = ZeroExtend(imm4:imm12, 32); 741 Rd = Bits32 (opcode, 15, 12); 742 setflags = false; 743 uint32_t imm4 = Bits32 (opcode, 19, 16); 744 uint32_t imm12 = Bits32 (opcode, 11, 0); 745 imm32 = (imm4 << 12) | imm12; 746 747 // if d == 15 then UNPREDICTABLE; 748 if (Rd == 15) 749 return false; 750 } 751 break; 752 753 default: 754 return false; 755 } 756 uint32_t result = imm32; 757 758 // The context specifies that an immediate is to be moved into Rd. 759 EmulateInstruction::Context context; 760 context.type = EmulateInstruction::eContextImmediate; 761 context.SetNoArgs (); 762 763 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry)) 764 return false; 765 } 766 return true; 767} 768 769// MUL multiplies two register values. The least significant 32 bits of the result are written to the destination 770// register. These 32 bits do not depend on whether the source register values are considered to be signed values or 771// unsigned values. 772// 773// Optionally, it can update the condition flags based on the result. In the Thumb instruction set, this option is 774// limited to only a few forms of the instruction. 775bool 776EmulateInstructionARM::EmulateMUL (const uint32_t opcode, const ARMEncoding encoding) 777{ 778#if 0 779 if ConditionPassed() then 780 EncodingSpecificOperations(); 781 operand1 = SInt(R[n]); // operand1 = UInt(R[n]) produces the same final results 782 operand2 = SInt(R[m]); // operand2 = UInt(R[m]) produces the same final results 783 result = operand1 * operand2; 784 R[d] = result<31:0>; 785 if setflags then 786 APSR.N = result<31>; 787 APSR.Z = IsZeroBit(result); 788 if ArchVersion() == 4 then 789 APSR.C = bit UNKNOWN; 790 // else APSR.C unchanged 791 // APSR.V always unchanged 792#endif 793 794 if (ConditionPassed(opcode)) 795 { 796 uint32_t d; 797 uint32_t n; 798 uint32_t m; 799 bool setflags; 800 801 // EncodingSpecificOperations(); 802 switch (encoding) 803 { 804 case eEncodingT1: 805 // d = UInt(Rdm); n = UInt(Rn); m = UInt(Rdm); setflags = !InITBlock(); 806 d = Bits32 (opcode, 2, 0); 807 n = Bits32 (opcode, 5, 3); 808 m = Bits32 (opcode, 2, 0); 809 setflags = !InITBlock(); 810 811 // if ArchVersion() < 6 && d == n then UNPREDICTABLE; 812 if ((ArchVersion() < ARMv6) && (d == n)) 813 return false; 814 815 break; 816 817 case eEncodingT2: 818 // d = UInt(Rd); n = UInt(Rn); m = UInt(Rm); setflags = FALSE; 819 d = Bits32 (opcode, 11, 8); 820 n = Bits32 (opcode, 19, 16); 821 m = Bits32 (opcode, 3, 0); 822 setflags = false; 823 824 // if BadReg(d) || BadReg(n) || BadReg(m) then UNPREDICTABLE; 825 if (BadReg (d) || BadReg (n) || BadReg (m)) 826 return false; 827 828 break; 829 830 case eEncodingA1: 831 // d = UInt(Rd); n = UInt(Rn); m = UInt(Rm); setflags = (S == '1'); 832 d = Bits32 (opcode, 19, 16); 833 n = Bits32 (opcode, 3, 0); 834 m = Bits32 (opcode, 11, 8); 835 setflags = BitIsSet (opcode, 20); 836 837 // if d == 15 || n == 15 || m == 15 then UNPREDICTABLE; 838 if ((d == 15) || (n == 15) || (m == 15)) 839 return false; 840 841 // if ArchVersion() < 6 && d == n then UNPREDICTABLE; 842 if ((ArchVersion() < ARMv6) && (d == n)) 843 return false; 844 845 break; 846 847 default: 848 return false; 849 } 850 851 bool success = false; 852 853 // operand1 = SInt(R[n]); // operand1 = UInt(R[n]) produces the same final results 854 uint64_t operand1 = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success); 855 if (!success) 856 return false; 857 858 // operand2 = SInt(R[m]); // operand2 = UInt(R[m]) produces the same final results 859 uint64_t operand2 = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success); 860 if (!success) 861 return false; 862 863 // result = operand1 * operand2; 864 uint64_t result = operand1 * operand2; 865 866 // R[d] = result<31:0>; 867 Register op1_reg; 868 Register op2_reg; 869 op1_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n); 870 op2_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + m); 871 872 EmulateInstruction::Context context; 873 context.type = eContextMultiplication; 874 context.SetRegisterRegisterOperands (op1_reg, op2_reg); 875 876 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + d, (0x0000ffff & result))) 877 return false; 878 879 // if setflags then 880 if (setflags) 881 { 882 // APSR.N = result<31>; 883 // APSR.Z = IsZeroBit(result); 884 m_new_inst_cpsr = m_opcode_cpsr; 885 SetBit32 (m_new_inst_cpsr, CPSR_N_POS, Bit32 (result, 31)); 886 SetBit32 (m_new_inst_cpsr, CPSR_Z_POS, result == 0 ? 1 : 0); 887 if (m_new_inst_cpsr != m_opcode_cpsr) 888 { 889 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS, m_new_inst_cpsr)) 890 return false; 891 } 892 893 // if ArchVersion() == 4 then 894 // APSR.C = bit UNKNOWN; 895 } 896 } 897 return true; 898} 899 900// Bitwise NOT (immediate) writes the bitwise inverse of an immediate value to the destination register. 901// It can optionally update the condition flags based on the value. 902bool 903EmulateInstructionARM::EmulateMVNImm (const uint32_t opcode, const ARMEncoding encoding) 904{ 905#if 0 906 // ARM pseudo code... 907 if (ConditionPassed()) 908 { 909 EncodingSpecificOperations(); 910 result = NOT(imm32); 911 if d == 15 then // Can only occur for ARM encoding 912 ALUWritePC(result); // setflags is always FALSE here 913 else 914 R[d] = result; 915 if setflags then 916 APSR.N = result<31>; 917 APSR.Z = IsZeroBit(result); 918 APSR.C = carry; 919 // APSR.V unchanged 920 } 921#endif 922 923 if (ConditionPassed(opcode)) 924 { 925 uint32_t Rd; // the destination register 926 uint32_t imm32; // the output after ThumbExpandImm_C or ARMExpandImm_C 927 uint32_t carry; // the carry bit after ThumbExpandImm_C or ARMExpandImm_C 928 bool setflags; 929 switch (encoding) { 930 case eEncodingT1: 931 Rd = Bits32(opcode, 11, 8); 932 setflags = BitIsSet(opcode, 20); 933 imm32 = ThumbExpandImm_C(opcode, APSR_C, carry); 934 break; 935 case eEncodingA1: 936 Rd = Bits32(opcode, 15, 12); 937 setflags = BitIsSet(opcode, 20); 938 imm32 = ARMExpandImm_C(opcode, APSR_C, carry); 939 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions; 940 // TODO: Emulate SUBS PC, LR and related instructions. 941 if (Rd == 15 && setflags) 942 return false; 943 break; 944 default: 945 return false; 946 } 947 uint32_t result = ~imm32; 948 949 // The context specifies that an immediate is to be moved into Rd. 950 EmulateInstruction::Context context; 951 context.type = EmulateInstruction::eContextImmediate; 952 context.SetNoArgs (); 953 954 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry)) 955 return false; 956 } 957 return true; 958} 959 960// Bitwise NOT (register) writes the bitwise inverse of a register value to the destination register. 961// It can optionally update the condition flags based on the result. 962bool 963EmulateInstructionARM::EmulateMVNReg (const uint32_t opcode, const ARMEncoding encoding) 964{ 965#if 0 966 // ARM pseudo code... 967 if (ConditionPassed()) 968 { 969 EncodingSpecificOperations(); 970 (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C); 971 result = NOT(shifted); 972 if d == 15 then // Can only occur for ARM encoding 973 ALUWritePC(result); // setflags is always FALSE here 974 else 975 R[d] = result; 976 if setflags then 977 APSR.N = result<31>; 978 APSR.Z = IsZeroBit(result); 979 APSR.C = carry; 980 // APSR.V unchanged 981 } 982#endif 983 984 if (ConditionPassed(opcode)) 985 { 986 uint32_t Rm; // the source register 987 uint32_t Rd; // the destination register 988 ARM_ShifterType shift_t; 989 uint32_t shift_n; // the shift applied to the value read from Rm 990 bool setflags; 991 uint32_t carry; // the carry bit after the shift operation 992 switch (encoding) { 993 case eEncodingT1: 994 Rd = Bits32(opcode, 2, 0); 995 Rm = Bits32(opcode, 5, 3); 996 setflags = !InITBlock(); 997 shift_t = SRType_LSL; 998 shift_n = 0; 999 if (InITBlock()) 1000 return false; 1001 break; 1002 case eEncodingT2: 1003 Rd = Bits32(opcode, 11, 8); 1004 Rm = Bits32(opcode, 3, 0); 1005 setflags = BitIsSet(opcode, 20); 1006 shift_n = DecodeImmShiftThumb(opcode, shift_t); 1007 // if (BadReg(d) || BadReg(m)) then UNPREDICTABLE; 1008 if (BadReg(Rd) || BadReg(Rm)) 1009 return false; 1010 break; 1011 case eEncodingA1: 1012 Rd = Bits32(opcode, 15, 12); 1013 Rm = Bits32(opcode, 3, 0); 1014 setflags = BitIsSet(opcode, 20); 1015 shift_n = DecodeImmShiftARM(opcode, shift_t); 1016 break; 1017 default: 1018 return false; 1019 } 1020 bool success = false; 1021 uint32_t value = ReadCoreReg(Rm, &success); 1022 if (!success) 1023 return false; 1024 1025 uint32_t shifted = Shift_C(value, shift_t, shift_n, APSR_C, carry); 1026 uint32_t result = ~shifted; 1027 1028 // The context specifies that an immediate is to be moved into Rd. 1029 EmulateInstruction::Context context; 1030 context.type = EmulateInstruction::eContextImmediate; 1031 context.SetNoArgs (); 1032 1033 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry)) 1034 return false; 1035 } 1036 return true; 1037} 1038 1039// PC relative immediate load into register, possibly followed by ADD (SP plus register). 1040// LDR (literal) 1041bool 1042EmulateInstructionARM::EmulateLDRRtPCRelative (const uint32_t opcode, const ARMEncoding encoding) 1043{ 1044#if 0 1045 // ARM pseudo code... 1046 if (ConditionPassed()) 1047 { 1048 EncodingSpecificOperations(); NullCheckIfThumbEE(15); 1049 base = Align(PC,4); 1050 address = if add then (base + imm32) else (base - imm32); 1051 data = MemU[address,4]; 1052 if t == 15 then 1053 if address<1:0> == '00' then LoadWritePC(data); else UNPREDICTABLE; 1054 elsif UnalignedSupport() || address<1:0> = '00' then 1055 R[t] = data; 1056 else // Can only apply before ARMv7 1057 if CurrentInstrSet() == InstrSet_ARM then 1058 R[t] = ROR(data, 8*UInt(address<1:0>)); 1059 else 1060 R[t] = bits(32) UNKNOWN; 1061 } 1062#endif 1063 1064 if (ConditionPassed(opcode)) 1065 { 1066 bool success = false; 1067 const uint32_t pc = ReadCoreReg(PC_REG, &success); 1068 if (!success) 1069 return false; 1070 1071 // PC relative immediate load context 1072 EmulateInstruction::Context context; 1073 context.type = EmulateInstruction::eContextRegisterPlusOffset; 1074 Register pc_reg; 1075 pc_reg.SetRegister (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC); 1076 context.SetRegisterPlusOffset (pc_reg, 0); 1077 1078 uint32_t Rt; // the destination register 1079 uint32_t imm32; // immediate offset from the PC 1080 bool add; // +imm32 or -imm32? 1081 addr_t base; // the base address 1082 addr_t address; // the PC relative address 1083 uint32_t data; // the literal data value from the PC relative load 1084 switch (encoding) { 1085 case eEncodingT1: 1086 Rt = Bits32(opcode, 10, 8); 1087 imm32 = Bits32(opcode, 7, 0) << 2; // imm32 = ZeroExtend(imm8:'00', 32); 1088 add = true; 1089 break; 1090 case eEncodingT2: 1091 Rt = Bits32(opcode, 15, 12); 1092 imm32 = Bits32(opcode, 11, 0) << 2; // imm32 = ZeroExtend(imm12, 32); 1093 add = BitIsSet(opcode, 23); 1094 if (Rt == 15 && InITBlock() && !LastInITBlock()) 1095 return false; 1096 break; 1097 default: 1098 return false; 1099 } 1100 1101 base = Align(pc, 4); 1102 if (add) 1103 address = base + imm32; 1104 else 1105 address = base - imm32; 1106 1107 context.SetRegisterPlusOffset(pc_reg, address - base); 1108 data = MemURead(context, address, 4, 0, &success); 1109 if (!success) 1110 return false; 1111 1112 if (Rt == 15) 1113 { 1114 if (Bits32(address, 1, 0) == 0) 1115 { 1116 // In ARMv5T and above, this is an interworking branch. 1117 if (!LoadWritePC(context, data)) 1118 return false; 1119 } 1120 else 1121 return false; 1122 } 1123 else if (UnalignedSupport() || Bits32(address, 1, 0) == 0) 1124 { 1125 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + Rt, data)) 1126 return false; 1127 } 1128 else // We don't handle ARM for now. 1129 return false; 1130 1131 } 1132 return true; 1133} 1134 1135// An add operation to adjust the SP. 1136// ADD (SP plus immediate) 1137bool 1138EmulateInstructionARM::EmulateADDSPImm (const uint32_t opcode, const ARMEncoding encoding) 1139{ 1140#if 0 1141 // ARM pseudo code... 1142 if (ConditionPassed()) 1143 { 1144 EncodingSpecificOperations(); 1145 (result, carry, overflow) = AddWithCarry(SP, imm32, '0'); 1146 if d == 15 then // Can only occur for ARM encoding 1147 ALUWritePC(result); // setflags is always FALSE here 1148 else 1149 R[d] = result; 1150 if setflags then 1151 APSR.N = result<31>; 1152 APSR.Z = IsZeroBit(result); 1153 APSR.C = carry; 1154 APSR.V = overflow; 1155 } 1156#endif 1157 1158 bool success = false; 1159 1160 if (ConditionPassed(opcode)) 1161 { 1162 const addr_t sp = ReadCoreReg (SP_REG, &success); 1163 if (!success) 1164 return false; 1165 uint32_t imm32; // the immediate operand 1166 uint32_t d; 1167 bool setflags; 1168 switch (encoding) 1169 { 1170 case eEncodingT1: 1171 // d = UInt(Rd); setflags = FALSE; imm32 = ZeroExtend(imm8:'00', 32); 1172 d = Bits32 (opcode, 10, 8); 1173 setflags = false; 1174 imm32 = (Bits32 (opcode, 7, 0) << 2); 1175 1176 break; 1177 1178 case eEncodingT2: 1179 // d = 13; setflags = FALSE; imm32 = ZeroExtend(imm7:'00', 32); 1180 d = 13; 1181 setflags = false; 1182 imm32 = ThumbImm7Scaled(opcode); // imm32 = ZeroExtend(imm7:'00', 32) 1183 1184 break; 1185 1186 default: 1187 return false; 1188 } 1189 addr_t sp_offset = imm32; 1190 addr_t addr = sp + sp_offset; // the adjusted stack pointer value 1191 1192 EmulateInstruction::Context context; 1193 context.type = EmulateInstruction::eContextAdjustStackPointer; 1194 context.SetImmediateSigned (sp_offset); 1195 1196 if (d == 15) 1197 { 1198 if (!ALUWritePC (context, addr)) 1199 return false; 1200 } 1201 else 1202 { 1203 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + d, addr)) 1204 return false; 1205 } 1206 } 1207 return true; 1208} 1209 1210// An add operation to adjust the SP. 1211// ADD (SP plus register) 1212bool 1213EmulateInstructionARM::EmulateADDSPRm (const uint32_t opcode, const ARMEncoding encoding) 1214{ 1215#if 0 1216 // ARM pseudo code... 1217 if (ConditionPassed()) 1218 { 1219 EncodingSpecificOperations(); 1220 shifted = Shift(R[m], shift_t, shift_n, APSR.C); 1221 (result, carry, overflow) = AddWithCarry(SP, shifted, '0'); 1222 if d == 15 then 1223 ALUWritePC(result); // setflags is always FALSE here 1224 else 1225 R[d] = result; 1226 if setflags then 1227 APSR.N = result<31>; 1228 APSR.Z = IsZeroBit(result); 1229 APSR.C = carry; 1230 APSR.V = overflow; 1231 } 1232#endif 1233 1234 bool success = false; 1235 1236 if (ConditionPassed(opcode)) 1237 { 1238 const addr_t sp = ReadCoreReg (SP_REG, &success); 1239 if (!success) 1240 return false; 1241 uint32_t Rm; // the second operand 1242 switch (encoding) { 1243 case eEncodingT2: 1244 Rm = Bits32(opcode, 6, 3); 1245 break; 1246 default: 1247 return false; 1248 } 1249 int32_t reg_value = ReadCoreReg(Rm, &success); 1250 if (!success) 1251 return false; 1252 1253 addr_t addr = (int32_t)sp + reg_value; // the adjusted stack pointer value 1254 1255 EmulateInstruction::Context context; 1256 context.type = EmulateInstruction::eContextAdjustStackPointer; 1257 context.SetImmediateSigned (reg_value); 1258 1259 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, addr)) 1260 return false; 1261 } 1262 return true; 1263} 1264 1265// Branch with Link and Exchange Instruction Sets (immediate) calls a subroutine 1266// at a PC-relative address, and changes instruction set from ARM to Thumb, or 1267// from Thumb to ARM. 1268// BLX (immediate) 1269bool 1270EmulateInstructionARM::EmulateBLXImmediate (const uint32_t opcode, const ARMEncoding encoding) 1271{ 1272#if 0 1273 // ARM pseudo code... 1274 if (ConditionPassed()) 1275 { 1276 EncodingSpecificOperations(); 1277 if CurrentInstrSet() == InstrSet_ARM then 1278 LR = PC - 4; 1279 else 1280 LR = PC<31:1> : '1'; 1281 if targetInstrSet == InstrSet_ARM then 1282 targetAddress = Align(PC,4) + imm32; 1283 else 1284 targetAddress = PC + imm32; 1285 SelectInstrSet(targetInstrSet); 1286 BranchWritePC(targetAddress); 1287 } 1288#endif 1289 1290 bool success = true; 1291 1292 if (ConditionPassed(opcode)) 1293 { 1294 EmulateInstruction::Context context; 1295 context.type = EmulateInstruction::eContextRelativeBranchImmediate; 1296 const uint32_t pc = ReadCoreReg(PC_REG, &success); 1297 if (!success) 1298 return false; 1299 addr_t lr; // next instruction address 1300 addr_t target; // target address 1301 int32_t imm32; // PC-relative offset 1302 switch (encoding) { 1303 case eEncodingT1: 1304 { 1305 lr = pc | 1u; // return address 1306 uint32_t S = Bit32(opcode, 26); 1307 uint32_t imm10 = Bits32(opcode, 25, 16); 1308 uint32_t J1 = Bit32(opcode, 13); 1309 uint32_t J2 = Bit32(opcode, 11); 1310 uint32_t imm11 = Bits32(opcode, 10, 0); 1311 uint32_t I1 = !(J1 ^ S); 1312 uint32_t I2 = !(J2 ^ S); 1313 uint32_t imm25 = (S << 24) | (I1 << 23) | (I2 << 22) | (imm10 << 12) | (imm11 << 1); 1314 imm32 = llvm::SignExtend32<25>(imm25); 1315 target = pc + imm32; 1316 context.SetModeAndImmediateSigned (eModeThumb, 4 + imm32); 1317 if (InITBlock() && !LastInITBlock()) 1318 return false; 1319 break; 1320 } 1321 case eEncodingT2: 1322 { 1323 lr = pc | 1u; // return address 1324 uint32_t S = Bit32(opcode, 26); 1325 uint32_t imm10H = Bits32(opcode, 25, 16); 1326 uint32_t J1 = Bit32(opcode, 13); 1327 uint32_t J2 = Bit32(opcode, 11); 1328 uint32_t imm10L = Bits32(opcode, 10, 1); 1329 uint32_t I1 = !(J1 ^ S); 1330 uint32_t I2 = !(J2 ^ S); 1331 uint32_t imm25 = (S << 24) | (I1 << 23) | (I2 << 22) | (imm10H << 12) | (imm10L << 2); 1332 imm32 = llvm::SignExtend32<25>(imm25); 1333 target = Align(pc, 4) + imm32; 1334 context.SetModeAndImmediateSigned (eModeARM, 4 + imm32); 1335 if (InITBlock() && !LastInITBlock()) 1336 return false; 1337 break; 1338 } 1339 case eEncodingA1: 1340 lr = pc - 4; // return address 1341 imm32 = llvm::SignExtend32<26>(Bits32(opcode, 23, 0) << 2); 1342 target = Align(pc, 4) + imm32; 1343 context.SetModeAndImmediateSigned (eModeARM, 8 + imm32); 1344 break; 1345 case eEncodingA2: 1346 lr = pc - 4; // return address 1347 imm32 = llvm::SignExtend32<26>(Bits32(opcode, 23, 0) << 2 | Bits32(opcode, 24, 24) << 1); 1348 target = pc + imm32; 1349 context.SetModeAndImmediateSigned (eModeThumb, 8 + imm32); 1350 break; 1351 default: 1352 return false; 1353 } 1354 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_RA, lr)) 1355 return false; 1356 if (!BranchWritePC(context, target)) 1357 return false; 1358 } 1359 return true; 1360} 1361 1362// Branch with Link and Exchange (register) calls a subroutine at an address and 1363// instruction set specified by a register. 1364// BLX (register) 1365bool 1366EmulateInstructionARM::EmulateBLXRm (const uint32_t opcode, const ARMEncoding encoding) 1367{ 1368#if 0 1369 // ARM pseudo code... 1370 if (ConditionPassed()) 1371 { 1372 EncodingSpecificOperations(); 1373 target = R[m]; 1374 if CurrentInstrSet() == InstrSet_ARM then 1375 next_instr_addr = PC - 4; 1376 LR = next_instr_addr; 1377 else 1378 next_instr_addr = PC - 2; 1379 LR = next_instr_addr<31:1> : '1'; 1380 BXWritePC(target); 1381 } 1382#endif 1383 1384 bool success = false; 1385 1386 if (ConditionPassed(opcode)) 1387 { 1388 EmulateInstruction::Context context; 1389 context.type = EmulateInstruction::eContextAbsoluteBranchRegister; 1390 const uint32_t pc = ReadCoreReg(PC_REG, &success); 1391 addr_t lr; // next instruction address 1392 if (!success) 1393 return false; 1394 uint32_t Rm; // the register with the target address 1395 switch (encoding) { 1396 case eEncodingT1: 1397 lr = (pc - 2) | 1u; // return address 1398 Rm = Bits32(opcode, 6, 3); 1399 // if m == 15 then UNPREDICTABLE; 1400 if (Rm == 15) 1401 return false; 1402 if (InITBlock() && !LastInITBlock()) 1403 return false; 1404 break; 1405 case eEncodingA1: 1406 lr = pc - 4; // return address 1407 Rm = Bits32(opcode, 3, 0); 1408 // if m == 15 then UNPREDICTABLE; 1409 if (Rm == 15) 1410 return false; 1411 break; 1412 default: 1413 return false; 1414 } 1415 addr_t target = ReadCoreReg (Rm, &success); 1416 if (!success) 1417 return false; 1418 Register dwarf_reg; 1419 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + Rm); 1420 context.SetRegister (dwarf_reg); 1421 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_RA, lr)) 1422 return false; 1423 if (!BXWritePC(context, target)) 1424 return false; 1425 } 1426 return true; 1427} 1428 1429// Branch and Exchange causes a branch to an address and instruction set specified by a register. 1430bool 1431EmulateInstructionARM::EmulateBXRm (const uint32_t opcode, const ARMEncoding encoding) 1432{ 1433#if 0 1434 // ARM pseudo code... 1435 if (ConditionPassed()) 1436 { 1437 EncodingSpecificOperations(); 1438 BXWritePC(R[m]); 1439 } 1440#endif 1441 1442 if (ConditionPassed(opcode)) 1443 { 1444 EmulateInstruction::Context context; 1445 context.type = EmulateInstruction::eContextAbsoluteBranchRegister; 1446 uint32_t Rm; // the register with the target address 1447 switch (encoding) { 1448 case eEncodingT1: 1449 Rm = Bits32(opcode, 6, 3); 1450 if (InITBlock() && !LastInITBlock()) 1451 return false; 1452 break; 1453 case eEncodingA1: 1454 Rm = Bits32(opcode, 3, 0); 1455 break; 1456 default: 1457 return false; 1458 } 1459 bool success = false; 1460 addr_t target = ReadCoreReg (Rm, &success); 1461 if (!success) 1462 return false; 1463 1464 Register dwarf_reg; 1465 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + Rm); 1466 context.SetRegister (dwarf_reg); 1467 if (!BXWritePC(context, target)) 1468 return false; 1469 } 1470 return true; 1471} 1472 1473// Branch and Exchange Jazelle attempts to change to Jazelle state. If the attempt fails, it branches to an 1474// address and instruction set specified by a register as though it were a BX instruction. 1475// 1476// TODO: Emulate Jazelle architecture? 1477// We currently assume that switching to Jazelle state fails, thus treating BXJ as a BX operation. 1478bool 1479EmulateInstructionARM::EmulateBXJRm (const uint32_t opcode, const ARMEncoding encoding) 1480{ 1481#if 0 1482 // ARM pseudo code... 1483 if (ConditionPassed()) 1484 { 1485 EncodingSpecificOperations(); 1486 if JMCR.JE == '0' || CurrentInstrSet() == InstrSet_ThumbEE then 1487 BXWritePC(R[m]); 1488 else 1489 if JazelleAcceptsExecution() then 1490 SwitchToJazelleExecution(); 1491 else 1492 SUBARCHITECTURE_DEFINED handler call; 1493 } 1494#endif 1495 1496 if (ConditionPassed(opcode)) 1497 { 1498 EmulateInstruction::Context context; 1499 context.type = EmulateInstruction::eContextAbsoluteBranchRegister; 1500 uint32_t Rm; // the register with the target address 1501 switch (encoding) { 1502 case eEncodingT1: 1503 Rm = Bits32(opcode, 19, 16); 1504 if (BadReg(Rm)) 1505 return false; 1506 if (InITBlock() && !LastInITBlock()) 1507 return false; 1508 break; 1509 case eEncodingA1: 1510 Rm = Bits32(opcode, 3, 0); 1511 if (Rm == 15) 1512 return false; 1513 break; 1514 default: 1515 return false; 1516 } 1517 bool success = false; 1518 addr_t target = ReadCoreReg (Rm, &success); 1519 if (!success) 1520 return false; 1521 1522 Register dwarf_reg; 1523 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + Rm); 1524 context.SetRegister (dwarf_reg); 1525 if (!BXWritePC(context, target)) 1526 return false; 1527 } 1528 return true; 1529} 1530 1531// Set r7 to point to some ip offset. 1532// SUB (immediate) 1533bool 1534EmulateInstructionARM::EmulateSUBR7IPImm (const uint32_t opcode, const ARMEncoding encoding) 1535{ 1536#if 0 1537 // ARM pseudo code... 1538 if (ConditionPassed()) 1539 { 1540 EncodingSpecificOperations(); 1541 (result, carry, overflow) = AddWithCarry(SP, NOT(imm32), '1'); 1542 if d == 15 then // Can only occur for ARM encoding 1543 ALUWritePC(result); // setflags is always FALSE here 1544 else 1545 R[d] = result; 1546 if setflags then 1547 APSR.N = result<31>; 1548 APSR.Z = IsZeroBit(result); 1549 APSR.C = carry; 1550 APSR.V = overflow; 1551 } 1552#endif 1553 1554 if (ConditionPassed(opcode)) 1555 { 1556 bool success = false; 1557 const addr_t ip = ReadCoreReg (12, &success); 1558 if (!success) 1559 return false; 1560 uint32_t imm32; 1561 switch (encoding) { 1562 case eEncodingA1: 1563 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12) 1564 break; 1565 default: 1566 return false; 1567 } 1568 addr_t ip_offset = imm32; 1569 addr_t addr = ip - ip_offset; // the adjusted ip value 1570 1571 EmulateInstruction::Context context; 1572 context.type = EmulateInstruction::eContextRegisterPlusOffset; 1573 Register dwarf_reg; 1574 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r12); 1575 context.SetRegisterPlusOffset (dwarf_reg, -ip_offset); 1576 1577 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r7, addr)) 1578 return false; 1579 } 1580 return true; 1581} 1582 1583// Set ip to point to some stack offset. 1584// SUB (SP minus immediate) 1585bool 1586EmulateInstructionARM::EmulateSUBIPSPImm (const uint32_t opcode, const ARMEncoding encoding) 1587{ 1588#if 0 1589 // ARM pseudo code... 1590 if (ConditionPassed()) 1591 { 1592 EncodingSpecificOperations(); 1593 (result, carry, overflow) = AddWithCarry(SP, NOT(imm32), '1'); 1594 if d == 15 then // Can only occur for ARM encoding 1595 ALUWritePC(result); // setflags is always FALSE here 1596 else 1597 R[d] = result; 1598 if setflags then 1599 APSR.N = result<31>; 1600 APSR.Z = IsZeroBit(result); 1601 APSR.C = carry; 1602 APSR.V = overflow; 1603 } 1604#endif 1605 1606 if (ConditionPassed(opcode)) 1607 { 1608 bool success = false; 1609 const addr_t sp = ReadCoreReg (SP_REG, &success); 1610 if (!success) 1611 return false; 1612 uint32_t imm32; 1613 switch (encoding) { 1614 case eEncodingA1: 1615 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12) 1616 break; 1617 default: 1618 return false; 1619 } 1620 addr_t sp_offset = imm32; 1621 addr_t addr = sp - sp_offset; // the adjusted stack pointer value 1622 1623 EmulateInstruction::Context context; 1624 context.type = EmulateInstruction::eContextRegisterPlusOffset; 1625 Register dwarf_reg; 1626 dwarf_reg.SetRegister (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP); 1627 context.SetRegisterPlusOffset (dwarf_reg, -sp_offset); 1628 1629 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r12, addr)) 1630 return false; 1631 } 1632 return true; 1633} 1634 1635// This instruction subtracts an immediate value from the SP value, and writes 1636// the result to the destination register. 1637// 1638// If Rd == 13 => A sub operation to adjust the SP -- allocate space for local storage. 1639bool 1640EmulateInstructionARM::EmulateSUBSPImm (const uint32_t opcode, const ARMEncoding encoding) 1641{ 1642#if 0 1643 // ARM pseudo code... 1644 if (ConditionPassed()) 1645 { 1646 EncodingSpecificOperations(); 1647 (result, carry, overflow) = AddWithCarry(SP, NOT(imm32), '1'); 1648 if d == 15 then // Can only occur for ARM encoding 1649 ALUWritePC(result); // setflags is always FALSE here 1650 else 1651 R[d] = result; 1652 if setflags then 1653 APSR.N = result<31>; 1654 APSR.Z = IsZeroBit(result); 1655 APSR.C = carry; 1656 APSR.V = overflow; 1657 } 1658#endif 1659 1660 bool success = false; 1661 if (ConditionPassed(opcode)) 1662 { 1663 const addr_t sp = ReadCoreReg (SP_REG, &success); 1664 if (!success) 1665 return false; 1666 1667 uint32_t Rd; 1668 bool setflags; 1669 uint32_t imm32; 1670 switch (encoding) { 1671 case eEncodingT1: 1672 Rd = 13; 1673 setflags = false; 1674 imm32 = ThumbImm7Scaled(opcode); // imm32 = ZeroExtend(imm7:'00', 32) 1675 break; 1676 case eEncodingT2: 1677 Rd = Bits32(opcode, 11, 8); 1678 setflags = BitIsSet(opcode, 20); 1679 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8) 1680 if (Rd == 15 && setflags) 1681 return EmulateCMPImm(opcode, eEncodingT2); 1682 if (Rd == 15 && !setflags) 1683 return false; 1684 break; 1685 case eEncodingT3: 1686 Rd = Bits32(opcode, 11, 8); 1687 setflags = false; 1688 imm32 = ThumbImm12(opcode); // imm32 = ZeroExtend(i:imm3:imm8, 32) 1689 if (Rd == 15) 1690 return false; 1691 break; 1692 case eEncodingA1: 1693 Rd = Bits32(opcode, 15, 12); 1694 setflags = BitIsSet(opcode, 20); 1695 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12) 1696 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions; 1697 // TODO: Emulate SUBS PC, LR and related instructions. 1698 if (Rd == 15 && setflags) 1699 return false; 1700 break; 1701 default: 1702 return false; 1703 } 1704 AddWithCarryResult res = AddWithCarry(sp, ~imm32, 1); 1705 1706 EmulateInstruction::Context context; 1707 if (Rd == 13) 1708 { 1709 uint64_t imm64 = imm32; // Need to expand it to 64 bits before attempting to negate it, or the wrong 1710 // value gets passed down to context.SetImmediateSigned. 1711 context.type = EmulateInstruction::eContextAdjustStackPointer; 1712 context.SetImmediateSigned (-imm64); // the stack pointer offset 1713 } 1714 else 1715 { 1716 context.type = EmulateInstruction::eContextImmediate; 1717 context.SetNoArgs (); 1718 } 1719 1720 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow)) 1721 return false; 1722 } 1723 return true; 1724} 1725 1726// A store operation to the stack that also updates the SP. 1727bool 1728EmulateInstructionARM::EmulateSTRRtSP (const uint32_t opcode, const ARMEncoding encoding) 1729{ 1730#if 0 1731 // ARM pseudo code... 1732 if (ConditionPassed()) 1733 { 1734 EncodingSpecificOperations(); 1735 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32); 1736 address = if index then offset_addr else R[n]; 1737 MemU[address,4] = if t == 15 then PCStoreValue() else R[t]; 1738 if wback then R[n] = offset_addr; 1739 } 1740#endif 1741 1742 bool success = false; 1743 1744 if (ConditionPassed(opcode)) 1745 { 1746 const uint32_t addr_byte_size = GetAddressByteSize(); 1747 const addr_t sp = ReadCoreReg (SP_REG, &success); 1748 if (!success) 1749 return false; 1750 uint32_t Rt; // the source register 1751 uint32_t imm12; 1752 uint32_t Rn; // This function assumes Rn is the SP, but we should verify that. 1753 1754 bool index; 1755 bool add; 1756 bool wback; 1757 switch (encoding) { 1758 case eEncodingA1: 1759 Rt = Bits32(opcode, 15, 12); 1760 imm12 = Bits32(opcode, 11, 0); 1761 Rn = Bits32 (opcode, 19, 16); 1762 1763 if (Rn != 13) // 13 is the SP reg on ARM. Verify that Rn == SP. 1764 return false; 1765 1766 index = BitIsSet (opcode, 24); 1767 add = BitIsSet (opcode, 23); 1768 wback = (BitIsClear (opcode, 24) || BitIsSet (opcode, 21)); 1769 1770 if (wback && ((Rn == 15) || (Rn == Rt))) 1771 return false; 1772 break; 1773 default: 1774 return false; 1775 } 1776 addr_t offset_addr; 1777 if (add) 1778 offset_addr = sp + imm12; 1779 else 1780 offset_addr = sp - imm12; 1781 1782 addr_t addr; 1783 if (index) 1784 addr = offset_addr; 1785 else 1786 addr = sp; 1787 1788 EmulateInstruction::Context context; 1789 context.type = EmulateInstruction::eContextPushRegisterOnStack; 1790 Register sp_reg; 1791 sp_reg.SetRegister (eRegisterKindDWARF, dwarf_sp); 1792 context.SetRegisterPlusOffset (sp_reg, addr - sp); 1793 if (Rt != 15) 1794 { 1795 uint32_t reg_value = ReadCoreReg(Rt, &success); 1796 if (!success) 1797 return false; 1798 if (!MemUWrite (context, addr, reg_value, addr_byte_size)) 1799 return false; 1800 } 1801 else 1802 { 1803 const uint32_t pc = ReadCoreReg(PC_REG, &success); 1804 if (!success) 1805 return false; 1806 if (!MemUWrite (context, addr, pc, addr_byte_size)) 1807 return false; 1808 } 1809 1810 1811 if (wback) 1812 { 1813 context.type = EmulateInstruction::eContextAdjustStackPointer; 1814 context.SetImmediateSigned (addr - sp); 1815 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, offset_addr)) 1816 return false; 1817 } 1818 } 1819 return true; 1820} 1821 1822// Vector Push stores multiple extension registers to the stack. 1823// It also updates SP to point to the start of the stored data. 1824bool 1825EmulateInstructionARM::EmulateVPUSH (const uint32_t opcode, const ARMEncoding encoding) 1826{ 1827#if 0 1828 // ARM pseudo code... 1829 if (ConditionPassed()) 1830 { 1831 EncodingSpecificOperations(); CheckVFPEnabled(TRUE); NullCheckIfThumbEE(13); 1832 address = SP - imm32; 1833 SP = SP - imm32; 1834 if single_regs then 1835 for r = 0 to regs-1 1836 MemA[address,4] = S[d+r]; address = address+4; 1837 else 1838 for r = 0 to regs-1 1839 // Store as two word-aligned words in the correct order for current endianness. 1840 MemA[address,4] = if BigEndian() then D[d+r]<63:32> else D[d+r]<31:0>; 1841 MemA[address+4,4] = if BigEndian() then D[d+r]<31:0> else D[d+r]<63:32>; 1842 address = address+8; 1843 } 1844#endif 1845 1846 bool success = false; 1847 1848 if (ConditionPassed(opcode)) 1849 { 1850 const uint32_t addr_byte_size = GetAddressByteSize(); 1851 const addr_t sp = ReadCoreReg (SP_REG, &success); 1852 if (!success) 1853 return false; 1854 bool single_regs; 1855 uint32_t d; // UInt(D:Vd) or UInt(Vd:D) starting register 1856 uint32_t imm32; // stack offset 1857 uint32_t regs; // number of registers 1858 switch (encoding) { 1859 case eEncodingT1: 1860 case eEncodingA1: 1861 single_regs = false; 1862 d = Bit32(opcode, 22) << 4 | Bits32(opcode, 15, 12); 1863 imm32 = Bits32(opcode, 7, 0) * addr_byte_size; 1864 // If UInt(imm8) is odd, see "FSTMX". 1865 regs = Bits32(opcode, 7, 0) / 2; 1866 // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE; 1867 if (regs == 0 || regs > 16 || (d + regs) > 32) 1868 return false; 1869 break; 1870 case eEncodingT2: 1871 case eEncodingA2: 1872 single_regs = true; 1873 d = Bits32(opcode, 15, 12) << 1 | Bit32(opcode, 22); 1874 imm32 = Bits32(opcode, 7, 0) * addr_byte_size; 1875 regs = Bits32(opcode, 7, 0); 1876 // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE; 1877 if (regs == 0 || regs > 16 || (d + regs) > 32) 1878 return false; 1879 break; 1880 default: 1881 return false; 1882 } 1883 uint32_t start_reg = single_regs ? dwarf_s0 : dwarf_d0; 1884 uint32_t reg_byte_size = single_regs ? addr_byte_size : addr_byte_size * 2; 1885 addr_t sp_offset = imm32; 1886 addr_t addr = sp - sp_offset; 1887 uint32_t i; 1888 1889 EmulateInstruction::Context context; 1890 context.type = EmulateInstruction::eContextPushRegisterOnStack; 1891 Register dwarf_reg; 1892 dwarf_reg.SetRegister (eRegisterKindDWARF, 0); 1893 Register sp_reg; 1894 sp_reg.SetRegister (eRegisterKindDWARF, dwarf_sp); 1895 for (i=0; i<regs; ++i) 1896 { 1897 dwarf_reg.num = start_reg + d + i; 1898 context.SetRegisterToRegisterPlusOffset ( dwarf_reg, sp_reg, addr - sp); 1899 // uint64_t to accommodate 64-bit registers. 1900 uint64_t reg_value = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_reg.num, 0, &success); 1901 if (!success) 1902 return false; 1903 if (!MemAWrite (context, addr, reg_value, reg_byte_size)) 1904 return false; 1905 addr += reg_byte_size; 1906 } 1907 1908 context.type = EmulateInstruction::eContextAdjustStackPointer; 1909 context.SetImmediateSigned (-sp_offset); 1910 1911 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, sp - sp_offset)) 1912 return false; 1913 } 1914 return true; 1915} 1916 1917// Vector Pop loads multiple extension registers from the stack. 1918// It also updates SP to point just above the loaded data. 1919bool 1920EmulateInstructionARM::EmulateVPOP (const uint32_t opcode, const ARMEncoding encoding) 1921{ 1922#if 0 1923 // ARM pseudo code... 1924 if (ConditionPassed()) 1925 { 1926 EncodingSpecificOperations(); CheckVFPEnabled(TRUE); NullCheckIfThumbEE(13); 1927 address = SP; 1928 SP = SP + imm32; 1929 if single_regs then 1930 for r = 0 to regs-1 1931 S[d+r] = MemA[address,4]; address = address+4; 1932 else 1933 for r = 0 to regs-1 1934 word1 = MemA[address,4]; word2 = MemA[address+4,4]; address = address+8; 1935 // Combine the word-aligned words in the correct order for current endianness. 1936 D[d+r] = if BigEndian() then word1:word2 else word2:word1; 1937 } 1938#endif 1939 1940 bool success = false; 1941 1942 if (ConditionPassed(opcode)) 1943 { 1944 const uint32_t addr_byte_size = GetAddressByteSize(); 1945 const addr_t sp = ReadCoreReg (SP_REG, &success); 1946 if (!success) 1947 return false; 1948 bool single_regs; 1949 uint32_t d; // UInt(D:Vd) or UInt(Vd:D) starting register 1950 uint32_t imm32; // stack offset 1951 uint32_t regs; // number of registers 1952 switch (encoding) { 1953 case eEncodingT1: 1954 case eEncodingA1: 1955 single_regs = false; 1956 d = Bit32(opcode, 22) << 4 | Bits32(opcode, 15, 12); 1957 imm32 = Bits32(opcode, 7, 0) * addr_byte_size; 1958 // If UInt(imm8) is odd, see "FLDMX". 1959 regs = Bits32(opcode, 7, 0) / 2; 1960 // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE; 1961 if (regs == 0 || regs > 16 || (d + regs) > 32) 1962 return false; 1963 break; 1964 case eEncodingT2: 1965 case eEncodingA2: 1966 single_regs = true; 1967 d = Bits32(opcode, 15, 12) << 1 | Bit32(opcode, 22); 1968 imm32 = Bits32(opcode, 7, 0) * addr_byte_size; 1969 regs = Bits32(opcode, 7, 0); 1970 // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE; 1971 if (regs == 0 || regs > 16 || (d + regs) > 32) 1972 return false; 1973 break; 1974 default: 1975 return false; 1976 } 1977 uint32_t start_reg = single_regs ? dwarf_s0 : dwarf_d0; 1978 uint32_t reg_byte_size = single_regs ? addr_byte_size : addr_byte_size * 2; 1979 addr_t sp_offset = imm32; 1980 addr_t addr = sp; 1981 uint32_t i; 1982 uint64_t data; // uint64_t to accomodate 64-bit registers. 1983 1984 EmulateInstruction::Context context; 1985 context.type = EmulateInstruction::eContextPopRegisterOffStack; 1986 Register dwarf_reg; 1987 dwarf_reg.SetRegister (eRegisterKindDWARF, 0); 1988 Register sp_reg; 1989 sp_reg.SetRegister (eRegisterKindDWARF, dwarf_sp); 1990 for (i=0; i<regs; ++i) 1991 { 1992 dwarf_reg.num = start_reg + d + i; 1993 context.SetRegisterPlusOffset (sp_reg, addr - sp); 1994 data = MemARead(context, addr, reg_byte_size, 0, &success); 1995 if (!success) 1996 return false; 1997 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_reg.num, data)) 1998 return false; 1999 addr += reg_byte_size; 2000 } 2001 2002 context.type = EmulateInstruction::eContextAdjustStackPointer; 2003 context.SetImmediateSigned (sp_offset); 2004 2005 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, sp + sp_offset)) 2006 return false; 2007 } 2008 return true; 2009} 2010 2011// SVC (previously SWI) 2012bool 2013EmulateInstructionARM::EmulateSVC (const uint32_t opcode, const ARMEncoding encoding) 2014{ 2015#if 0 2016 // ARM pseudo code... 2017 if (ConditionPassed()) 2018 { 2019 EncodingSpecificOperations(); 2020 CallSupervisor(); 2021 } 2022#endif 2023 2024 bool success = false; 2025 2026 if (ConditionPassed(opcode)) 2027 { 2028 const uint32_t pc = ReadCoreReg(PC_REG, &success); 2029 addr_t lr; // next instruction address 2030 if (!success) 2031 return false; 2032 uint32_t imm32; // the immediate constant 2033 uint32_t mode; // ARM or Thumb mode 2034 switch (encoding) { 2035 case eEncodingT1: 2036 lr = (pc + 2) | 1u; // return address 2037 imm32 = Bits32(opcode, 7, 0); 2038 mode = eModeThumb; 2039 break; 2040 case eEncodingA1: 2041 lr = pc + 4; // return address 2042 imm32 = Bits32(opcode, 23, 0); 2043 mode = eModeARM; 2044 break; 2045 default: 2046 return false; 2047 } 2048 2049 EmulateInstruction::Context context; 2050 context.type = EmulateInstruction::eContextSupervisorCall; 2051 context.SetModeAndImmediate (mode, imm32); 2052 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_RA, lr)) 2053 return false; 2054 } 2055 return true; 2056} 2057 2058// If Then makes up to four following instructions (the IT block) conditional. 2059bool 2060EmulateInstructionARM::EmulateIT (const uint32_t opcode, const ARMEncoding encoding) 2061{ 2062#if 0 2063 // ARM pseudo code... 2064 EncodingSpecificOperations(); 2065 ITSTATE.IT<7:0> = firstcond:mask; 2066#endif 2067 2068 m_it_session.InitIT(Bits32(opcode, 7, 0)); 2069 return true; 2070} 2071 2072// Branch causes a branch to a target address. 2073bool 2074EmulateInstructionARM::EmulateB (const uint32_t opcode, const ARMEncoding encoding) 2075{ 2076#if 0 2077 // ARM pseudo code... 2078 if (ConditionPassed()) 2079 { 2080 EncodingSpecificOperations(); 2081 BranchWritePC(PC + imm32); 2082 } 2083#endif 2084 2085 bool success = false; 2086 2087 if (ConditionPassed(opcode)) 2088 { 2089 EmulateInstruction::Context context; 2090 context.type = EmulateInstruction::eContextRelativeBranchImmediate; 2091 const uint32_t pc = ReadCoreReg(PC_REG, &success); 2092 if (!success) 2093 return false; 2094 addr_t target; // target address 2095 int32_t imm32; // PC-relative offset 2096 switch (encoding) { 2097 case eEncodingT1: 2098 // The 'cond' field is handled in EmulateInstructionARM::CurrentCond(). 2099 imm32 = llvm::SignExtend32<9>(Bits32(opcode, 7, 0) << 1); 2100 target = pc + imm32; 2101 context.SetModeAndImmediateSigned (eModeThumb, 4 + imm32); 2102 break; 2103 case eEncodingT2: 2104 imm32 = llvm::SignExtend32<12>(Bits32(opcode, 10, 0)); 2105 target = pc + imm32; 2106 context.SetModeAndImmediateSigned (eModeThumb, 4 + imm32); 2107 break; 2108 case eEncodingT3: 2109 // The 'cond' field is handled in EmulateInstructionARM::CurrentCond(). 2110 { 2111 uint32_t S = Bit32(opcode, 26); 2112 uint32_t imm6 = Bits32(opcode, 21, 16); 2113 uint32_t J1 = Bit32(opcode, 13); 2114 uint32_t J2 = Bit32(opcode, 11); 2115 uint32_t imm11 = Bits32(opcode, 10, 0); 2116 uint32_t imm21 = (S << 20) | (J2 << 19) | (J1 << 18) | (imm6 << 12) | (imm11 << 1); 2117 imm32 = llvm::SignExtend32<21>(imm21); 2118 target = pc + imm32; 2119 context.SetModeAndImmediateSigned (eModeThumb, 4 + imm32); 2120 break; 2121 } 2122 case eEncodingT4: 2123 { 2124 uint32_t S = Bit32(opcode, 26); 2125 uint32_t imm10 = Bits32(opcode, 25, 16); 2126 uint32_t J1 = Bit32(opcode, 13); 2127 uint32_t J2 = Bit32(opcode, 11); 2128 uint32_t imm11 = Bits32(opcode, 10, 0); 2129 uint32_t I1 = !(J1 ^ S); 2130 uint32_t I2 = !(J2 ^ S); 2131 uint32_t imm25 = (S << 24) | (I1 << 23) | (I2 << 22) | (imm10 << 12) | (imm11 << 1); 2132 imm32 = llvm::SignExtend32<25>(imm25); 2133 target = pc + imm32; 2134 context.SetModeAndImmediateSigned (eModeThumb, 4 + imm32); 2135 break; 2136 } 2137 case eEncodingA1: 2138 imm32 = llvm::SignExtend32<26>(Bits32(opcode, 23, 0) << 2); 2139 target = pc + imm32; 2140 context.SetModeAndImmediateSigned (eModeARM, 8 + imm32); 2141 break; 2142 default: 2143 return false; 2144 } 2145 if (!BranchWritePC(context, target)) 2146 return false; 2147 } 2148 return true; 2149} 2150 2151// Compare and Branch on Nonzero and Compare and Branch on Zero compare the value in a register with 2152// zero and conditionally branch forward a constant value. They do not affect the condition flags. 2153// CBNZ, CBZ 2154bool 2155EmulateInstructionARM::EmulateCB (const uint32_t opcode, const ARMEncoding encoding) 2156{ 2157#if 0 2158 // ARM pseudo code... 2159 EncodingSpecificOperations(); 2160 if nonzero ^ IsZero(R[n]) then 2161 BranchWritePC(PC + imm32); 2162#endif 2163 2164 bool success = false; 2165 2166 // Read the register value from the operand register Rn. 2167 uint32_t reg_val = ReadCoreReg(Bits32(opcode, 2, 0), &success); 2168 if (!success) 2169 return false; 2170 2171 EmulateInstruction::Context context; 2172 context.type = EmulateInstruction::eContextRelativeBranchImmediate; 2173 const uint32_t pc = ReadCoreReg(PC_REG, &success); 2174 if (!success) 2175 return false; 2176 2177 addr_t target; // target address 2178 uint32_t imm32; // PC-relative offset to branch forward 2179 bool nonzero; 2180 switch (encoding) { 2181 case eEncodingT1: 2182 imm32 = Bit32(opcode, 9) << 6 | Bits32(opcode, 7, 3) << 1; 2183 nonzero = BitIsSet(opcode, 11); 2184 target = pc + imm32; 2185 context.SetModeAndImmediateSigned (eModeThumb, 4 + imm32); 2186 break; 2187 default: 2188 return false; 2189 } 2190 if (nonzero ^ (reg_val == 0)) 2191 if (!BranchWritePC(context, target)) 2192 return false; 2193 2194 return true; 2195} 2196 2197// Table Branch Byte causes a PC-relative forward branch using a table of single byte offsets. 2198// A base register provides a pointer to the table, and a second register supplies an index into the table. 2199// The branch length is twice the value of the byte returned from the table. 2200// 2201// Table Branch Halfword causes a PC-relative forward branch using a table of single halfword offsets. 2202// A base register provides a pointer to the table, and a second register supplies an index into the table. 2203// The branch length is twice the value of the halfword returned from the table. 2204// TBB, TBH 2205bool 2206EmulateInstructionARM::EmulateTB (const uint32_t opcode, const ARMEncoding encoding) 2207{ 2208#if 0 2209 // ARM pseudo code... 2210 EncodingSpecificOperations(); NullCheckIfThumbEE(n); 2211 if is_tbh then 2212 halfwords = UInt(MemU[R[n]+LSL(R[m],1), 2]); 2213 else 2214 halfwords = UInt(MemU[R[n]+R[m], 1]); 2215 BranchWritePC(PC + 2*halfwords); 2216#endif 2217 2218 bool success = false; 2219 2220 uint32_t Rn; // the base register which contains the address of the table of branch lengths 2221 uint32_t Rm; // the index register which contains an integer pointing to a byte/halfword in the table 2222 bool is_tbh; // true if table branch halfword 2223 switch (encoding) { 2224 case eEncodingT1: 2225 Rn = Bits32(opcode, 19, 16); 2226 Rm = Bits32(opcode, 3, 0); 2227 is_tbh = BitIsSet(opcode, 4); 2228 if (Rn == 13 || BadReg(Rm)) 2229 return false; 2230 if (InITBlock() && !LastInITBlock()) 2231 return false; 2232 break; 2233 default: 2234 return false; 2235 } 2236 2237 // Read the address of the table from the operand register Rn. 2238 // The PC can be used, in which case the table immediately follows this instruction. 2239 uint32_t base = ReadCoreReg(Rm, &success); 2240 if (!success) 2241 return false; 2242 2243 // the table index 2244 uint32_t index = ReadCoreReg(Rm, &success); 2245 if (!success) 2246 return false; 2247 2248 // the offsetted table address 2249 addr_t addr = base + (is_tbh ? index*2 : index); 2250 2251 // PC-relative offset to branch forward 2252 EmulateInstruction::Context context; 2253 context.type = EmulateInstruction::eContextTableBranchReadMemory; 2254 uint32_t offset = MemURead(context, addr, is_tbh ? 2 : 1, 0, &success) * 2; 2255 if (!success) 2256 return false; 2257 2258 const uint32_t pc = ReadCoreReg(PC_REG, &success); 2259 if (!success) 2260 return false; 2261 2262 // target address 2263 addr_t target = pc + offset; 2264 context.type = EmulateInstruction::eContextRelativeBranchImmediate; 2265 context.SetModeAndImmediateSigned (eModeThumb, 4 + offset); 2266 2267 if (!BranchWritePC(context, target)) 2268 return false; 2269 2270 return true; 2271} 2272 2273// This instruction adds an immediate value to a register value, and writes the result to the destination register. 2274// It can optionally update the condition flags based on the result. 2275bool 2276EmulateInstructionARM::EmulateADDImmThumb (const uint32_t opcode, const ARMEncoding encoding) 2277{ 2278#if 0 2279 if ConditionPassed() then 2280 EncodingSpecificOperations(); 2281 (result, carry, overflow) = AddWithCarry(R[n], imm32, '0'); 2282 R[d] = result; 2283 if setflags then 2284 APSR.N = result<31>; 2285 APSR.Z = IsZeroBit(result); 2286 APSR.C = carry; 2287 APSR.V = overflow; 2288#endif 2289 2290 bool success = false; 2291 2292 if (ConditionPassed(opcode)) 2293 { 2294 uint32_t d; 2295 uint32_t n; 2296 bool setflags; 2297 uint32_t imm32; 2298 uint32_t carry_out; 2299 2300 //EncodingSpecificOperations(); 2301 switch (encoding) 2302 { 2303 case eEncodingT1: 2304 // d = UInt(Rd); n = UInt(Rn); setflags = !InITBlock(); imm32 = ZeroExtend(imm3, 32); 2305 d = Bits32 (opcode, 2, 0); 2306 n = Bits32 (opcode, 5, 3); 2307 setflags = !InITBlock(); 2308 imm32 = Bits32 (opcode, 8,6); 2309 2310 break; 2311 2312 case eEncodingT2: 2313 // d = UInt(Rdn); n = UInt(Rdn); setflags = !InITBlock(); imm32 = ZeroExtend(imm8, 32); 2314 d = Bits32 (opcode, 10, 8); 2315 n = Bits32 (opcode, 10, 8); 2316 setflags = !InITBlock(); 2317 imm32 = Bits32 (opcode, 7, 0); 2318 2319 break; 2320 2321 case eEncodingT3: 2322 // if Rd == '1111' && S == '1' then SEE CMN (immediate); 2323 // if Rn == '1101' then SEE ADD (SP plus immediate); 2324 // d = UInt(Rd); n = UInt(Rn); setflags = (S == '1'); imm32 = ThumbExpandImm(i:imm3:imm8); 2325 d = Bits32 (opcode, 11, 8); 2326 n = Bits32 (opcode, 19, 16); 2327 setflags = BitIsSet (opcode, 20); 2328 imm32 = ThumbExpandImm_C (opcode, APSR_C, carry_out); 2329 2330 // if BadReg(d) || n == 15 then UNPREDICTABLE; 2331 if (BadReg (d) || (n == 15)) 2332 return false; 2333 2334 break; 2335 2336 case eEncodingT4: 2337 { 2338 // if Rn == '1111' then SEE ADR; 2339 // if Rn == '1101' then SEE ADD (SP plus immediate); 2340 // d = UInt(Rd); n = UInt(Rn); setflags = FALSE; imm32 = ZeroExtend(i:imm3:imm8, 32); 2341 d = Bits32 (opcode, 11, 8); 2342 n = Bits32 (opcode, 19, 16); 2343 setflags = false; 2344 uint32_t i = Bit32 (opcode, 26); 2345 uint32_t imm3 = Bits32 (opcode, 14, 12); 2346 uint32_t imm8 = Bits32 (opcode, 7, 0); 2347 imm32 = (i << 11) | (imm3 << 8) | imm8; 2348 2349 // if BadReg(d) then UNPREDICTABLE; 2350 if (BadReg (d)) 2351 return false; 2352 2353 break; 2354 } 2355 default: 2356 return false; 2357 } 2358 2359 uint64_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success); 2360 if (!success) 2361 return false; 2362 2363 //(result, carry, overflow) = AddWithCarry(R[n], imm32, '0'); 2364 AddWithCarryResult res = AddWithCarry (Rn, imm32, 0); 2365 2366 Register reg_n; 2367 reg_n.SetRegister (eRegisterKindDWARF, dwarf_r0 + n); 2368 2369 EmulateInstruction::Context context; 2370 context.type = eContextAddition; 2371 context.SetRegisterPlusOffset (reg_n, imm32); 2372 2373 //R[d] = result; 2374 //if setflags then 2375 //APSR.N = result<31>; 2376 //APSR.Z = IsZeroBit(result); 2377 //APSR.C = carry; 2378 //APSR.V = overflow; 2379 if (!WriteCoreRegOptionalFlags (context, res.result, d, setflags, res.carry_out, res.overflow)) 2380 return false; 2381 2382 } 2383 return true; 2384} 2385 2386// This instruction adds an immediate value to a register value, and writes the result to the destination 2387// register. It can optionally update the condition flags based on the result. 2388bool 2389EmulateInstructionARM::EmulateADDImmARM (const uint32_t opcode, const ARMEncoding encoding) 2390{ 2391#if 0 2392 // ARM pseudo code... 2393 if ConditionPassed() then 2394 EncodingSpecificOperations(); 2395 (result, carry, overflow) = AddWithCarry(R[n], imm32, '0'); 2396 if d == 15 then 2397 ALUWritePC(result); // setflags is always FALSE here 2398 else 2399 R[d] = result; 2400 if setflags then 2401 APSR.N = result<31>; 2402 APSR.Z = IsZeroBit(result); 2403 APSR.C = carry; 2404 APSR.V = overflow; 2405#endif 2406 2407 bool success = false; 2408 2409 if (ConditionPassed(opcode)) 2410 { 2411 uint32_t Rd, Rn; 2412 uint32_t imm32; // the immediate value to be added to the value obtained from Rn 2413 bool setflags; 2414 switch (encoding) 2415 { 2416 case eEncodingA1: 2417 Rd = Bits32(opcode, 15, 12); 2418 Rn = Bits32(opcode, 19, 16); 2419 setflags = BitIsSet(opcode, 20); 2420 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12) 2421 break; 2422 default: 2423 return false; 2424 } 2425 2426 // Read the first operand. 2427 uint32_t val1 = ReadCoreReg(Rn, &success); 2428 if (!success) 2429 return false; 2430 2431 AddWithCarryResult res = AddWithCarry(val1, imm32, 0); 2432 2433 EmulateInstruction::Context context; 2434 context.type = EmulateInstruction::eContextImmediate; 2435 context.SetNoArgs (); 2436 2437 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow)) 2438 return false; 2439 } 2440 return true; 2441} 2442 2443// This instruction adds a register value and an optionally-shifted register value, and writes the result 2444// to the destination register. It can optionally update the condition flags based on the result. 2445bool 2446EmulateInstructionARM::EmulateADDReg (const uint32_t opcode, const ARMEncoding encoding) 2447{ 2448#if 0 2449 // ARM pseudo code... 2450 if ConditionPassed() then 2451 EncodingSpecificOperations(); 2452 shifted = Shift(R[m], shift_t, shift_n, APSR.C); 2453 (result, carry, overflow) = AddWithCarry(R[n], shifted, '0'); 2454 if d == 15 then 2455 ALUWritePC(result); // setflags is always FALSE here 2456 else 2457 R[d] = result; 2458 if setflags then 2459 APSR.N = result<31>; 2460 APSR.Z = IsZeroBit(result); 2461 APSR.C = carry; 2462 APSR.V = overflow; 2463#endif 2464 2465 bool success = false; 2466 2467 if (ConditionPassed(opcode)) 2468 { 2469 uint32_t Rd, Rn, Rm; 2470 ARM_ShifterType shift_t; 2471 uint32_t shift_n; // the shift applied to the value read from Rm 2472 bool setflags; 2473 switch (encoding) 2474 { 2475 case eEncodingT1: 2476 Rd = Bits32(opcode, 2, 0); 2477 Rn = Bits32(opcode, 5, 3); 2478 Rm = Bits32(opcode, 8, 6); 2479 setflags = !InITBlock(); 2480 shift_t = SRType_LSL; 2481 shift_n = 0; 2482 break; 2483 case eEncodingT2: 2484 Rd = Rn = Bit32(opcode, 7) << 3 | Bits32(opcode, 2, 0); 2485 Rm = Bits32(opcode, 6, 3); 2486 setflags = false; 2487 shift_t = SRType_LSL; 2488 shift_n = 0; 2489 if (Rn == 15 && Rm == 15) 2490 return false; 2491 if (Rd == 15 && InITBlock() && !LastInITBlock()) 2492 return false; 2493 break; 2494 case eEncodingA1: 2495 Rd = Bits32(opcode, 15, 12); 2496 Rn = Bits32(opcode, 19, 16); 2497 Rm = Bits32(opcode, 3, 0); 2498 setflags = BitIsSet(opcode, 20); 2499 shift_n = DecodeImmShiftARM(opcode, shift_t); 2500 break; 2501 default: 2502 return false; 2503 } 2504 2505 // Read the first operand. 2506 uint32_t val1 = ReadCoreReg(Rn, &success); 2507 if (!success) 2508 return false; 2509 2510 // Read the second operand. 2511 uint32_t val2 = ReadCoreReg(Rm, &success); 2512 if (!success) 2513 return false; 2514 2515 uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C); 2516 AddWithCarryResult res = AddWithCarry(val1, shifted, 0); 2517 2518 EmulateInstruction::Context context; 2519 context.type = EmulateInstruction::eContextAddition; 2520 Register op1_reg; 2521 Register op2_reg; 2522 op1_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + Rn); 2523 op2_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + Rm); 2524 context.SetRegisterRegisterOperands (op1_reg, op2_reg); 2525 2526 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow)) 2527 return false; 2528 } 2529 return true; 2530} 2531 2532// Compare Negative (immediate) adds a register value and an immediate value. 2533// It updates the condition flags based on the result, and discards the result. 2534bool 2535EmulateInstructionARM::EmulateCMNImm (const uint32_t opcode, const ARMEncoding encoding) 2536{ 2537#if 0 2538 // ARM pseudo code... 2539 if ConditionPassed() then 2540 EncodingSpecificOperations(); 2541 (result, carry, overflow) = AddWithCarry(R[n], imm32, '0'); 2542 APSR.N = result<31>; 2543 APSR.Z = IsZeroBit(result); 2544 APSR.C = carry; 2545 APSR.V = overflow; 2546#endif 2547 2548 bool success = false; 2549 2550 uint32_t Rn; // the first operand 2551 uint32_t imm32; // the immediate value to be compared with 2552 switch (encoding) { 2553 case eEncodingT1: 2554 Rn = Bits32(opcode, 19, 16); 2555 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8) 2556 if (Rn == 15) 2557 return false; 2558 break; 2559 case eEncodingA1: 2560 Rn = Bits32(opcode, 19, 16); 2561 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12) 2562 break; 2563 default: 2564 return false; 2565 } 2566 // Read the register value from the operand register Rn. 2567 uint32_t reg_val = ReadCoreReg(Rn, &success); 2568 if (!success) 2569 return false; 2570 2571 AddWithCarryResult res = AddWithCarry(reg_val, imm32, 0); 2572 2573 EmulateInstruction::Context context; 2574 context.type = EmulateInstruction::eContextImmediate; 2575 context.SetNoArgs (); 2576 if (!WriteFlags(context, res.result, res.carry_out, res.overflow)) 2577 return false; 2578 2579 return true; 2580} 2581 2582// Compare Negative (register) adds a register value and an optionally-shifted register value. 2583// It updates the condition flags based on the result, and discards the result. 2584bool 2585EmulateInstructionARM::EmulateCMNReg (const uint32_t opcode, const ARMEncoding encoding) 2586{ 2587#if 0 2588 // ARM pseudo code... 2589 if ConditionPassed() then 2590 EncodingSpecificOperations(); 2591 shifted = Shift(R[m], shift_t, shift_n, APSR.C); 2592 (result, carry, overflow) = AddWithCarry(R[n], shifted, '0'); 2593 APSR.N = result<31>; 2594 APSR.Z = IsZeroBit(result); 2595 APSR.C = carry; 2596 APSR.V = overflow; 2597#endif 2598 2599 bool success = false; 2600 2601 uint32_t Rn; // the first operand 2602 uint32_t Rm; // the second operand 2603 ARM_ShifterType shift_t; 2604 uint32_t shift_n; // the shift applied to the value read from Rm 2605 switch (encoding) { 2606 case eEncodingT1: 2607 Rn = Bits32(opcode, 2, 0); 2608 Rm = Bits32(opcode, 5, 3); 2609 shift_t = SRType_LSL; 2610 shift_n = 0; 2611 break; 2612 case eEncodingT2: 2613 Rn = Bits32(opcode, 19, 16); 2614 Rm = Bits32(opcode, 3, 0); 2615 shift_n = DecodeImmShiftThumb(opcode, shift_t); 2616 // if n == 15 || BadReg(m) then UNPREDICTABLE; 2617 if (Rn == 15 || BadReg(Rm)) 2618 return false; 2619 break; 2620 case eEncodingA1: 2621 Rn = Bits32(opcode, 19, 16); 2622 Rm = Bits32(opcode, 3, 0); 2623 shift_n = DecodeImmShiftARM(opcode, shift_t); 2624 break; 2625 default: 2626 return false; 2627 } 2628 // Read the register value from register Rn. 2629 uint32_t val1 = ReadCoreReg(Rn, &success); 2630 if (!success) 2631 return false; 2632 2633 // Read the register value from register Rm. 2634 uint32_t val2 = ReadCoreReg(Rm, &success); 2635 if (!success) 2636 return false; 2637 2638 uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C); 2639 AddWithCarryResult res = AddWithCarry(val1, shifted, 0); 2640 2641 EmulateInstruction::Context context; 2642 context.type = EmulateInstruction::eContextImmediate; 2643 context.SetNoArgs(); 2644 if (!WriteFlags(context, res.result, res.carry_out, res.overflow)) 2645 return false; 2646 2647 return true; 2648} 2649 2650// Compare (immediate) subtracts an immediate value from a register value. 2651// It updates the condition flags based on the result, and discards the result. 2652bool 2653EmulateInstructionARM::EmulateCMPImm (const uint32_t opcode, const ARMEncoding encoding) 2654{ 2655#if 0 2656 // ARM pseudo code... 2657 if ConditionPassed() then 2658 EncodingSpecificOperations(); 2659 (result, carry, overflow) = AddWithCarry(R[n], NOT(imm32), '1'); 2660 APSR.N = result<31>; 2661 APSR.Z = IsZeroBit(result); 2662 APSR.C = carry; 2663 APSR.V = overflow; 2664#endif 2665 2666 bool success = false; 2667 2668 uint32_t Rn; // the first operand 2669 uint32_t imm32; // the immediate value to be compared with 2670 switch (encoding) { 2671 case eEncodingT1: 2672 Rn = Bits32(opcode, 10, 8); 2673 imm32 = Bits32(opcode, 7, 0); 2674 break; 2675 case eEncodingT2: 2676 Rn = Bits32(opcode, 19, 16); 2677 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8) 2678 if (Rn == 15) 2679 return false; 2680 break; 2681 case eEncodingA1: 2682 Rn = Bits32(opcode, 19, 16); 2683 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12) 2684 break; 2685 default: 2686 return false; 2687 } 2688 // Read the register value from the operand register Rn. 2689 uint32_t reg_val = ReadCoreReg(Rn, &success); 2690 if (!success) 2691 return false; 2692 2693 AddWithCarryResult res = AddWithCarry(reg_val, ~imm32, 1); 2694 2695 EmulateInstruction::Context context; 2696 context.type = EmulateInstruction::eContextImmediate; 2697 context.SetNoArgs (); 2698 if (!WriteFlags(context, res.result, res.carry_out, res.overflow)) 2699 return false; 2700 2701 return true; 2702} 2703 2704// Compare (register) subtracts an optionally-shifted register value from a register value. 2705// It updates the condition flags based on the result, and discards the result. 2706bool 2707EmulateInstructionARM::EmulateCMPReg (const uint32_t opcode, const ARMEncoding encoding) 2708{ 2709#if 0 2710 // ARM pseudo code... 2711 if ConditionPassed() then 2712 EncodingSpecificOperations(); 2713 shifted = Shift(R[m], shift_t, shift_n, APSR.C); 2714 (result, carry, overflow) = AddWithCarry(R[n], NOT(shifted), '1'); 2715 APSR.N = result<31>; 2716 APSR.Z = IsZeroBit(result); 2717 APSR.C = carry; 2718 APSR.V = overflow; 2719#endif 2720 2721 bool success = false; 2722 2723 uint32_t Rn; // the first operand 2724 uint32_t Rm; // the second operand 2725 ARM_ShifterType shift_t; 2726 uint32_t shift_n; // the shift applied to the value read from Rm 2727 switch (encoding) { 2728 case eEncodingT1: 2729 Rn = Bits32(opcode, 2, 0); 2730 Rm = Bits32(opcode, 5, 3); 2731 shift_t = SRType_LSL; 2732 shift_n = 0; 2733 break; 2734 case eEncodingT2: 2735 Rn = Bit32(opcode, 7) << 3 | Bits32(opcode, 2, 0); 2736 Rm = Bits32(opcode, 6, 3); 2737 shift_t = SRType_LSL; 2738 shift_n = 0; 2739 if (Rn < 8 && Rm < 8) 2740 return false; 2741 if (Rn == 15 || Rm == 15) 2742 return false; 2743 break; 2744 case eEncodingA1: 2745 Rn = Bits32(opcode, 19, 16); 2746 Rm = Bits32(opcode, 3, 0); 2747 shift_n = DecodeImmShiftARM(opcode, shift_t); 2748 break; 2749 default: 2750 return false; 2751 } 2752 // Read the register value from register Rn. 2753 uint32_t val1 = ReadCoreReg(Rn, &success); 2754 if (!success) 2755 return false; 2756 2757 // Read the register value from register Rm. 2758 uint32_t val2 = ReadCoreReg(Rm, &success); 2759 if (!success) 2760 return false; 2761 2762 uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C); 2763 AddWithCarryResult res = AddWithCarry(val1, ~shifted, 1); 2764 2765 EmulateInstruction::Context context; 2766 context.type = EmulateInstruction::eContextImmediate; 2767 context.SetNoArgs(); 2768 if (!WriteFlags(context, res.result, res.carry_out, res.overflow)) 2769 return false; 2770 2771 return true; 2772} 2773 2774// Arithmetic Shift Right (immediate) shifts a register value right by an immediate number of bits, 2775// shifting in copies of its sign bit, and writes the result to the destination register. It can 2776// optionally update the condition flags based on the result. 2777bool 2778EmulateInstructionARM::EmulateASRImm (const uint32_t opcode, const ARMEncoding encoding) 2779{ 2780#if 0 2781 // ARM pseudo code... 2782 if ConditionPassed() then 2783 EncodingSpecificOperations(); 2784 (result, carry) = Shift_C(R[m], SRType_ASR, shift_n, APSR.C); 2785 if d == 15 then // Can only occur for ARM encoding 2786 ALUWritePC(result); // setflags is always FALSE here 2787 else 2788 R[d] = result; 2789 if setflags then 2790 APSR.N = result<31>; 2791 APSR.Z = IsZeroBit(result); 2792 APSR.C = carry; 2793 // APSR.V unchanged 2794#endif 2795 2796 return EmulateShiftImm (opcode, encoding, SRType_ASR); 2797} 2798 2799// Arithmetic Shift Right (register) shifts a register value right by a variable number of bits, 2800// shifting in copies of its sign bit, and writes the result to the destination register. 2801// The variable number of bits is read from the bottom byte of a register. It can optionally update 2802// the condition flags based on the result. 2803bool 2804EmulateInstructionARM::EmulateASRReg (const uint32_t opcode, const ARMEncoding encoding) 2805{ 2806#if 0 2807 // ARM pseudo code... 2808 if ConditionPassed() then 2809 EncodingSpecificOperations(); 2810 shift_n = UInt(R[m]<7:0>); 2811 (result, carry) = Shift_C(R[m], SRType_ASR, shift_n, APSR.C); 2812 R[d] = result; 2813 if setflags then 2814 APSR.N = result<31>; 2815 APSR.Z = IsZeroBit(result); 2816 APSR.C = carry; 2817 // APSR.V unchanged 2818#endif 2819 2820 return EmulateShiftReg (opcode, encoding, SRType_ASR); 2821} 2822 2823// Logical Shift Left (immediate) shifts a register value left by an immediate number of bits, 2824// shifting in zeros, and writes the result to the destination register. It can optionally 2825// update the condition flags based on the result. 2826bool 2827EmulateInstructionARM::EmulateLSLImm (const uint32_t opcode, const ARMEncoding encoding) 2828{ 2829#if 0 2830 // ARM pseudo code... 2831 if ConditionPassed() then 2832 EncodingSpecificOperations(); 2833 (result, carry) = Shift_C(R[m], SRType_LSL, shift_n, APSR.C); 2834 if d == 15 then // Can only occur for ARM encoding 2835 ALUWritePC(result); // setflags is always FALSE here 2836 else 2837 R[d] = result; 2838 if setflags then 2839 APSR.N = result<31>; 2840 APSR.Z = IsZeroBit(result); 2841 APSR.C = carry; 2842 // APSR.V unchanged 2843#endif 2844 2845 return EmulateShiftImm (opcode, encoding, SRType_LSL); 2846} 2847 2848// Logical Shift Left (register) shifts a register value left by a variable number of bits, 2849// shifting in zeros, and writes the result to the destination register. The variable number 2850// of bits is read from the bottom byte of a register. It can optionally update the condition 2851// flags based on the result. 2852bool 2853EmulateInstructionARM::EmulateLSLReg (const uint32_t opcode, const ARMEncoding encoding) 2854{ 2855#if 0 2856 // ARM pseudo code... 2857 if ConditionPassed() then 2858 EncodingSpecificOperations(); 2859 shift_n = UInt(R[m]<7:0>); 2860 (result, carry) = Shift_C(R[m], SRType_LSL, shift_n, APSR.C); 2861 R[d] = result; 2862 if setflags then 2863 APSR.N = result<31>; 2864 APSR.Z = IsZeroBit(result); 2865 APSR.C = carry; 2866 // APSR.V unchanged 2867#endif 2868 2869 return EmulateShiftReg (opcode, encoding, SRType_LSL); 2870} 2871 2872// Logical Shift Right (immediate) shifts a register value right by an immediate number of bits, 2873// shifting in zeros, and writes the result to the destination register. It can optionally 2874// update the condition flags based on the result. 2875bool 2876EmulateInstructionARM::EmulateLSRImm (const uint32_t opcode, const ARMEncoding encoding) 2877{ 2878#if 0 2879 // ARM pseudo code... 2880 if ConditionPassed() then 2881 EncodingSpecificOperations(); 2882 (result, carry) = Shift_C(R[m], SRType_LSR, shift_n, APSR.C); 2883 if d == 15 then // Can only occur for ARM encoding 2884 ALUWritePC(result); // setflags is always FALSE here 2885 else 2886 R[d] = result; 2887 if setflags then 2888 APSR.N = result<31>; 2889 APSR.Z = IsZeroBit(result); 2890 APSR.C = carry; 2891 // APSR.V unchanged 2892#endif 2893 2894 return EmulateShiftImm (opcode, encoding, SRType_LSR); 2895} 2896 2897// Logical Shift Right (register) shifts a register value right by a variable number of bits, 2898// shifting in zeros, and writes the result to the destination register. The variable number 2899// of bits is read from the bottom byte of a register. It can optionally update the condition 2900// flags based on the result. 2901bool 2902EmulateInstructionARM::EmulateLSRReg (const uint32_t opcode, const ARMEncoding encoding) 2903{ 2904#if 0 2905 // ARM pseudo code... 2906 if ConditionPassed() then 2907 EncodingSpecificOperations(); 2908 shift_n = UInt(R[m]<7:0>); 2909 (result, carry) = Shift_C(R[m], SRType_LSR, shift_n, APSR.C); 2910 R[d] = result; 2911 if setflags then 2912 APSR.N = result<31>; 2913 APSR.Z = IsZeroBit(result); 2914 APSR.C = carry; 2915 // APSR.V unchanged 2916#endif 2917 2918 return EmulateShiftReg (opcode, encoding, SRType_LSR); 2919} 2920 2921// Rotate Right (immediate) provides the value of the contents of a register rotated by a constant value. 2922// The bits that are rotated off the right end are inserted into the vacated bit positions on the left. 2923// It can optionally update the condition flags based on the result. 2924bool 2925EmulateInstructionARM::EmulateRORImm (const uint32_t opcode, const ARMEncoding encoding) 2926{ 2927#if 0 2928 // ARM pseudo code... 2929 if ConditionPassed() then 2930 EncodingSpecificOperations(); 2931 (result, carry) = Shift_C(R[m], SRType_ROR, shift_n, APSR.C); 2932 if d == 15 then // Can only occur for ARM encoding 2933 ALUWritePC(result); // setflags is always FALSE here 2934 else 2935 R[d] = result; 2936 if setflags then 2937 APSR.N = result<31>; 2938 APSR.Z = IsZeroBit(result); 2939 APSR.C = carry; 2940 // APSR.V unchanged 2941#endif 2942 2943 return EmulateShiftImm (opcode, encoding, SRType_ROR); 2944} 2945 2946// Rotate Right (register) provides the value of the contents of a register rotated by a variable number of bits. 2947// The bits that are rotated off the right end are inserted into the vacated bit positions on the left. 2948// The variable number of bits is read from the bottom byte of a register. It can optionally update the condition 2949// flags based on the result. 2950bool 2951EmulateInstructionARM::EmulateRORReg (const uint32_t opcode, const ARMEncoding encoding) 2952{ 2953#if 0 2954 // ARM pseudo code... 2955 if ConditionPassed() then 2956 EncodingSpecificOperations(); 2957 shift_n = UInt(R[m]<7:0>); 2958 (result, carry) = Shift_C(R[m], SRType_ROR, shift_n, APSR.C); 2959 R[d] = result; 2960 if setflags then 2961 APSR.N = result<31>; 2962 APSR.Z = IsZeroBit(result); 2963 APSR.C = carry; 2964 // APSR.V unchanged 2965#endif 2966 2967 return EmulateShiftReg (opcode, encoding, SRType_ROR); 2968} 2969 2970// Rotate Right with Extend provides the value of the contents of a register shifted right by one place, 2971// with the carry flag shifted into bit [31]. 2972// 2973// RRX can optionally update the condition flags based on the result. 2974// In that case, bit [0] is shifted into the carry flag. 2975bool 2976EmulateInstructionARM::EmulateRRX (const uint32_t opcode, const ARMEncoding encoding) 2977{ 2978#if 0 2979 // ARM pseudo code... 2980 if ConditionPassed() then 2981 EncodingSpecificOperations(); 2982 (result, carry) = Shift_C(R[m], SRType_RRX, 1, APSR.C); 2983 if d == 15 then // Can only occur for ARM encoding 2984 ALUWritePC(result); // setflags is always FALSE here 2985 else 2986 R[d] = result; 2987 if setflags then 2988 APSR.N = result<31>; 2989 APSR.Z = IsZeroBit(result); 2990 APSR.C = carry; 2991 // APSR.V unchanged 2992#endif 2993 2994 return EmulateShiftImm (opcode, encoding, SRType_RRX); 2995} 2996 2997bool 2998EmulateInstructionARM::EmulateShiftImm (const uint32_t opcode, const ARMEncoding encoding, ARM_ShifterType shift_type) 2999{ 3000 assert(shift_type == SRType_ASR 3001 || shift_type == SRType_LSL 3002 || shift_type == SRType_LSR 3003 || shift_type == SRType_ROR 3004 || shift_type == SRType_RRX); 3005 3006 bool success = false; 3007 3008 if (ConditionPassed(opcode)) 3009 { 3010 uint32_t Rd; // the destination register 3011 uint32_t Rm; // the first operand register 3012 uint32_t imm5; // encoding for the shift amount 3013 uint32_t carry; // the carry bit after the shift operation 3014 bool setflags; 3015 3016 // Special case handling! 3017 // A8.6.139 ROR (immediate) -- Encoding T1 3018 ARMEncoding use_encoding = encoding; 3019 if (shift_type == SRType_ROR && use_encoding == eEncodingT1) 3020 { 3021 // Morph the T1 encoding from the ARM Architecture Manual into T2 encoding to 3022 // have the same decoding of bit fields as the other Thumb2 shift operations. 3023 use_encoding = eEncodingT2; 3024 } 3025 3026 switch (use_encoding) { 3027 case eEncodingT1: 3028 // Due to the above special case handling! 3029 assert(shift_type != SRType_ROR); 3030 3031 Rd = Bits32(opcode, 2, 0); 3032 Rm = Bits32(opcode, 5, 3); 3033 setflags = !InITBlock(); 3034 imm5 = Bits32(opcode, 10, 6); 3035 break; 3036 case eEncodingT2: 3037 // A8.6.141 RRX 3038 assert(shift_type != SRType_RRX); 3039 3040 Rd = Bits32(opcode, 11, 8); 3041 Rm = Bits32(opcode, 3, 0); 3042 setflags = BitIsSet(opcode, 20); 3043 imm5 = Bits32(opcode, 14, 12) << 2 | Bits32(opcode, 7, 6); 3044 if (BadReg(Rd) || BadReg(Rm)) 3045 return false; 3046 break; 3047 case eEncodingA1: 3048 Rd = Bits32(opcode, 15, 12); 3049 Rm = Bits32(opcode, 3, 0); 3050 setflags = BitIsSet(opcode, 20); 3051 imm5 = Bits32(opcode, 11, 7); 3052 break; 3053 default: 3054 return false; 3055 } 3056 3057 // A8.6.139 ROR (immediate) 3058 if (shift_type == SRType_ROR && imm5 == 0) 3059 shift_type = SRType_RRX; 3060 3061 // Get the first operand. 3062 uint32_t value = ReadCoreReg (Rm, &success); 3063 if (!success) 3064 return false; 3065 3066 // Decode the shift amount if not RRX. 3067 uint32_t amt = (shift_type == SRType_RRX ? 1 : DecodeImmShift(shift_type, imm5)); 3068 3069 uint32_t result = Shift_C(value, shift_type, amt, APSR_C, carry); 3070 3071 // The context specifies that an immediate is to be moved into Rd. 3072 EmulateInstruction::Context context; 3073 context.type = EmulateInstruction::eContextImmediate; 3074 context.SetNoArgs (); 3075 3076 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry)) 3077 return false; 3078 } 3079 return true; 3080} 3081 3082bool 3083EmulateInstructionARM::EmulateShiftReg (const uint32_t opcode, const ARMEncoding encoding, ARM_ShifterType shift_type) 3084{ 3085 assert(shift_type == SRType_ASR || shift_type == SRType_LSL || shift_type == SRType_LSR); 3086 3087 bool success = false; 3088 3089 if (ConditionPassed(opcode)) 3090 { 3091 uint32_t Rd; // the destination register 3092 uint32_t Rn; // the first operand register 3093 uint32_t Rm; // the register whose bottom byte contains the amount to shift by 3094 uint32_t carry; // the carry bit after the shift operation 3095 bool setflags; 3096 switch (encoding) { 3097 case eEncodingT1: 3098 Rd = Bits32(opcode, 2, 0); 3099 Rn = Rd; 3100 Rm = Bits32(opcode, 5, 3); 3101 setflags = !InITBlock(); 3102 break; 3103 case eEncodingT2: 3104 Rd = Bits32(opcode, 11, 8); 3105 Rn = Bits32(opcode, 19, 16); 3106 Rm = Bits32(opcode, 3, 0); 3107 setflags = BitIsSet(opcode, 20); 3108 if (BadReg(Rd) || BadReg(Rn) || BadReg(Rm)) 3109 return false; 3110 break; 3111 case eEncodingA1: 3112 Rd = Bits32(opcode, 15, 12); 3113 Rn = Bits32(opcode, 3, 0); 3114 Rm = Bits32(opcode, 11, 8); 3115 setflags = BitIsSet(opcode, 20); 3116 if (Rd == 15 || Rn == 15 || Rm == 15) 3117 return false; 3118 break; 3119 default: 3120 return false; 3121 } 3122 3123 // Get the first operand. 3124 uint32_t value = ReadCoreReg (Rn, &success); 3125 if (!success) 3126 return false; 3127 // Get the Rm register content. 3128 uint32_t val = ReadCoreReg (Rm, &success); 3129 if (!success) 3130 return false; 3131 3132 // Get the shift amount. 3133 uint32_t amt = Bits32(val, 7, 0); 3134 3135 uint32_t result = Shift_C(value, shift_type, amt, APSR_C, carry); 3136 3137 // The context specifies that an immediate is to be moved into Rd. 3138 EmulateInstruction::Context context; 3139 context.type = EmulateInstruction::eContextImmediate; 3140 context.SetNoArgs (); 3141 3142 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry)) 3143 return false; 3144 } 3145 return true; 3146} 3147 3148// LDM loads multiple registers from consecutive memory locations, using an 3149// address from a base register. Optionally the address just above the highest of those locations 3150// can be written back to the base register. 3151bool 3152EmulateInstructionARM::EmulateLDM (const uint32_t opcode, const ARMEncoding encoding) 3153{ 3154#if 0 3155 // ARM pseudo code... 3156 if ConditionPassed() 3157 EncodingSpecificOperations(); NullCheckIfThumbEE (n); 3158 address = R[n]; 3159 3160 for i = 0 to 14 3161 if registers<i> == '1' then 3162 R[i] = MemA[address, 4]; address = address + 4; 3163 if registers<15> == '1' then 3164 LoadWritePC (MemA[address, 4]); 3165 3166 if wback && registers<n> == '0' then R[n] = R[n] + 4 * BitCount (registers); 3167 if wback && registers<n> == '1' then R[n] = bits(32) UNKNOWN; // Only possible for encoding A1 3168 3169#endif 3170 3171 bool success = false; 3172 3173 if (ConditionPassed(opcode)) 3174 { 3175 uint32_t n; 3176 uint32_t registers = 0; 3177 bool wback; 3178 const uint32_t addr_byte_size = GetAddressByteSize(); 3179 switch (encoding) 3180 { 3181 case eEncodingT1: 3182 // n = UInt(Rn); registers = '00000000':register_list; wback = (registers<n> == '0'); 3183 n = Bits32 (opcode, 10, 8); 3184 registers = Bits32 (opcode, 7, 0); 3185 registers = registers & 0x00ff; // Make sure the top 8 bits are zeros. 3186 wback = BitIsClear (registers, n); 3187 // if BitCount(registers) < 1 then UNPREDICTABLE; 3188 if (BitCount(registers) < 1) 3189 return false; 3190 break; 3191 case eEncodingT2: 3192 // if W == '1' && Rn == '1101' then SEE POP; 3193 // n = UInt(Rn); registers = P:M:'0':register_list; wback = (W == '1'); 3194 n = Bits32 (opcode, 19, 16); 3195 registers = Bits32 (opcode, 15, 0); 3196 registers = registers & 0xdfff; // Make sure bit 13 is zero. 3197 wback = BitIsSet (opcode, 21); 3198 3199 // if n == 15 || BitCount(registers) < 2 || (P == '1' && M == '1') then UNPREDICTABLE; 3200 if ((n == 15) 3201 || (BitCount (registers) < 2) 3202 || (BitIsSet (opcode, 14) && BitIsSet (opcode, 15))) 3203 return false; 3204 3205 // if registers<15> == '1' && InITBlock() && !LastInITBlock() then UNPREDICTABLE; 3206 if (BitIsSet (registers, 15) && InITBlock() && !LastInITBlock()) 3207 return false; 3208 3209 // if wback && registers<n> == '1' then UNPREDICTABLE; 3210 if (wback 3211 && BitIsSet (registers, n)) 3212 return false; 3213 break; 3214 3215 case eEncodingA1: 3216 n = Bits32 (opcode, 19, 16); 3217 registers = Bits32 (opcode, 15, 0); 3218 wback = BitIsSet (opcode, 21); 3219 if ((n == 15) 3220 || (BitCount (registers) < 1)) 3221 return false; 3222 break; 3223 default: 3224 return false; 3225 } 3226 3227 int32_t offset = 0; 3228 const addr_t base_address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success); 3229 if (!success) 3230 return false; 3231 3232 EmulateInstruction::Context context; 3233 context.type = EmulateInstruction::eContextRegisterPlusOffset; 3234 Register dwarf_reg; 3235 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n); 3236 context.SetRegisterPlusOffset (dwarf_reg, offset); 3237 3238 for (int i = 0; i < 14; ++i) 3239 { 3240 if (BitIsSet (registers, i)) 3241 { 3242 context.type = EmulateInstruction::eContextRegisterPlusOffset; 3243 context.SetRegisterPlusOffset (dwarf_reg, offset); 3244 if (wback && (n == 13)) // Pop Instruction 3245 context.type = EmulateInstruction::eContextPopRegisterOffStack; 3246 3247 // R[i] = MemA [address, 4]; address = address + 4; 3248 uint32_t data = MemARead (context, base_address + offset, addr_byte_size, 0, &success); 3249 if (!success) 3250 return false; 3251 3252 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + i, data)) 3253 return false; 3254 3255 offset += addr_byte_size; 3256 } 3257 } 3258 3259 if (BitIsSet (registers, 15)) 3260 { 3261 //LoadWritePC (MemA [address, 4]); 3262 context.type = EmulateInstruction::eContextRegisterPlusOffset; 3263 context.SetRegisterPlusOffset (dwarf_reg, offset); 3264 uint32_t data = MemARead (context, base_address + offset, addr_byte_size, 0, &success); 3265 if (!success) 3266 return false; 3267 // In ARMv5T and above, this is an interworking branch. 3268 if (!LoadWritePC(context, data)) 3269 return false; 3270 } 3271 3272 if (wback && BitIsClear (registers, n)) 3273 { 3274 // R[n] = R[n] + 4 * BitCount (registers) 3275 int32_t offset = addr_byte_size * BitCount (registers); 3276 context.type = EmulateInstruction::eContextAdjustBaseRegister; 3277 context.SetRegisterPlusOffset (dwarf_reg, offset); 3278 3279 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, base_address + offset)) 3280 return false; 3281 } 3282 if (wback && BitIsSet (registers, n)) 3283 // R[n] bits(32) UNKNOWN; 3284 return WriteBits32Unknown (n); 3285 } 3286 return true; 3287} 3288 3289// LDMDA loads multiple registers from consecutive memory locations using an address from a base register. 3290// The consecutive memory locations end at this address and the address just below the lowest of those locations 3291// can optionally be written back to the base register. 3292bool 3293EmulateInstructionARM::EmulateLDMDA (const uint32_t opcode, const ARMEncoding encoding) 3294{ 3295#if 0 3296 // ARM pseudo code... 3297 if ConditionPassed() then 3298 EncodingSpecificOperations(); 3299 address = R[n] - 4*BitCount(registers) + 4; 3300 3301 for i = 0 to 14 3302 if registers<i> == '1' then 3303 R[i] = MemA[address,4]; address = address + 4; 3304 3305 if registers<15> == '1' then 3306 LoadWritePC(MemA[address,4]); 3307 3308 if wback && registers<n> == '0' then R[n] = R[n] - 4*BitCount(registers); 3309 if wback && registers<n> == '1' then R[n] = bits(32) UNKNOWN; 3310#endif 3311 3312 bool success = false; 3313 3314 if (ConditionPassed(opcode)) 3315 { 3316 uint32_t n; 3317 uint32_t registers = 0; 3318 bool wback; 3319 const uint32_t addr_byte_size = GetAddressByteSize(); 3320 3321 // EncodingSpecificOperations(); 3322 switch (encoding) 3323 { 3324 case eEncodingA1: 3325 // n = UInt(Rn); registers = register_list; wback = (W == '1'); 3326 n = Bits32 (opcode, 19, 16); 3327 registers = Bits32 (opcode, 15, 0); 3328 wback = BitIsSet (opcode, 21); 3329 3330 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE; 3331 if ((n == 15) || (BitCount (registers) < 1)) 3332 return false; 3333 3334 break; 3335 3336 default: 3337 return false; 3338 } 3339 // address = R[n] - 4*BitCount(registers) + 4; 3340 3341 int32_t offset = 0; 3342 addr_t Rn = ReadCoreReg (n, &success); 3343 3344 if (!success) 3345 return false; 3346 3347 addr_t address = Rn - (addr_byte_size * BitCount (registers)) + addr_byte_size; 3348 3349 EmulateInstruction::Context context; 3350 context.type = EmulateInstruction::eContextRegisterPlusOffset; 3351 Register dwarf_reg; 3352 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n); 3353 context.SetRegisterPlusOffset (dwarf_reg, offset); 3354 3355 // for i = 0 to 14 3356 for (int i = 0; i < 14; ++i) 3357 { 3358 // if registers<i> == '1' then 3359 if (BitIsSet (registers, i)) 3360 { 3361 // R[i] = MemA[address,4]; address = address + 4; 3362 context.SetRegisterPlusOffset (dwarf_reg, Rn - (address + offset)); 3363 uint32_t data = MemARead (context, address + offset, addr_byte_size, 0, &success); 3364 if (!success) 3365 return false; 3366 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + i, data)) 3367 return false; 3368 offset += addr_byte_size; 3369 } 3370 } 3371 3372 // if registers<15> == '1' then 3373 // LoadWritePC(MemA[address,4]); 3374 if (BitIsSet (registers, 15)) 3375 { 3376 context.SetRegisterPlusOffset (dwarf_reg, offset); 3377 uint32_t data = MemARead (context, address + offset, addr_byte_size, 0, &success); 3378 if (!success) 3379 return false; 3380 // In ARMv5T and above, this is an interworking branch. 3381 if (!LoadWritePC(context, data)) 3382 return false; 3383 } 3384 3385 // if wback && registers<n> == '0' then R[n] = R[n] - 4*BitCount(registers); 3386 if (wback && BitIsClear (registers, n)) 3387 { 3388 if (!success) 3389 return false; 3390 3391 offset = (addr_byte_size * BitCount (registers)) * -1; 3392 context.type = EmulateInstruction::eContextAdjustBaseRegister; 3393 context.SetImmediateSigned (offset); 3394 addr_t addr = Rn + offset; 3395 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, addr)) 3396 return false; 3397 } 3398 3399 // if wback && registers<n> == '1' then R[n] = bits(32) UNKNOWN; 3400 if (wback && BitIsSet (registers, n)) 3401 return WriteBits32Unknown (n); 3402 } 3403 return true; 3404} 3405 3406// LDMDB loads multiple registers from consecutive memory locations using an address from a base register. The 3407// consecutive memory lcoations end just below this address, and the address of the lowest of those locations can 3408// be optionally written back to the base register. 3409bool 3410EmulateInstructionARM::EmulateLDMDB (const uint32_t opcode, const ARMEncoding encoding) 3411{ 3412#if 0 3413 // ARM pseudo code... 3414 if ConditionPassed() then 3415 EncodingSpecificOperations(); NullCheckIfThumbEE(n); 3416 address = R[n] - 4*BitCount(registers); 3417 3418 for i = 0 to 14 3419 if registers<i> == '1' then 3420 R[i] = MemA[address,4]; address = address + 4; 3421 if registers<15> == '1' then 3422 LoadWritePC(MemA[address,4]); 3423 3424 if wback && registers<n> == '0' then R[n] = R[n] - 4*BitCount(registers); 3425 if wback && registers<n> == '1' then R[n] = bits(32) UNKNOWN; // Only possible for encoding A1 3426#endif 3427 3428 bool success = false; 3429 3430 if (ConditionPassed(opcode)) 3431 { 3432 uint32_t n; 3433 uint32_t registers = 0; 3434 bool wback; 3435 const uint32_t addr_byte_size = GetAddressByteSize(); 3436 switch (encoding) 3437 { 3438 case eEncodingT1: 3439 // n = UInt(Rn); registers = P:M:'0':register_list; wback = (W == '1'); 3440 n = Bits32 (opcode, 19, 16); 3441 registers = Bits32 (opcode, 15, 0); 3442 registers = registers & 0xdfff; // Make sure bit 13 is a zero. 3443 wback = BitIsSet (opcode, 21); 3444 3445 // if n == 15 || BitCount(registers) < 2 || (P == '1' && M == '1') then UNPREDICTABLE; 3446 if ((n == 15) 3447 || (BitCount (registers) < 2) 3448 || (BitIsSet (opcode, 14) && BitIsSet (opcode, 15))) 3449 return false; 3450 3451 // if registers<15> == '1' && InITBlock() && !LastInITBlock() then UNPREDICTABLE; 3452 if (BitIsSet (registers, 15) && InITBlock() && !LastInITBlock()) 3453 return false; 3454 3455 // if wback && registers<n> == '1' then UNPREDICTABLE; 3456 if (wback && BitIsSet (registers, n)) 3457 return false; 3458 3459 break; 3460 3461 case eEncodingA1: 3462 // n = UInt(Rn); registers = register_list; wback = (W == '1'); 3463 n = Bits32 (opcode, 19, 16); 3464 registers = Bits32 (opcode, 15, 0); 3465 wback = BitIsSet (opcode, 21); 3466 3467 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE; 3468 if ((n == 15) || (BitCount (registers) < 1)) 3469 return false; 3470 3471 break; 3472 3473 default: 3474 return false; 3475 } 3476 3477 // address = R[n] - 4*BitCount(registers); 3478 3479 int32_t offset = 0; 3480 addr_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success); 3481 3482 if (!success) 3483 return false; 3484 3485 addr_t address = Rn - (addr_byte_size * BitCount (registers)); 3486 EmulateInstruction::Context context; 3487 context.type = EmulateInstruction::eContextRegisterPlusOffset; 3488 Register dwarf_reg; 3489 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n); 3490 context.SetRegisterPlusOffset (dwarf_reg, Rn - address); 3491 3492 for (int i = 0; i < 14; ++i) 3493 { 3494 if (BitIsSet (registers, i)) 3495 { 3496 // R[i] = MemA[address,4]; address = address + 4; 3497 context.SetRegisterPlusOffset (dwarf_reg, Rn - (address + offset)); 3498 uint32_t data = MemARead (context, address + offset, addr_byte_size, 0, &success); 3499 if (!success) 3500 return false; 3501 3502 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + i, data)) 3503 return false; 3504 3505 offset += addr_byte_size; 3506 } 3507 } 3508 3509 // if registers<15> == '1' then 3510 // LoadWritePC(MemA[address,4]); 3511 if (BitIsSet (registers, 15)) 3512 { 3513 context.SetRegisterPlusOffset (dwarf_reg, offset); 3514 uint32_t data = MemARead (context, address + offset, addr_byte_size, 0, &success); 3515 if (!success) 3516 return false; 3517 // In ARMv5T and above, this is an interworking branch. 3518 if (!LoadWritePC(context, data)) 3519 return false; 3520 } 3521 3522 // if wback && registers<n> == '0' then R[n] = R[n] - 4*BitCount(registers); 3523 if (wback && BitIsClear (registers, n)) 3524 { 3525 if (!success) 3526 return false; 3527 3528 offset = (addr_byte_size * BitCount (registers)) * -1; 3529 context.type = EmulateInstruction::eContextAdjustBaseRegister; 3530 context.SetImmediateSigned (offset); 3531 addr_t addr = Rn + offset; 3532 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, addr)) 3533 return false; 3534 } 3535 3536 // if wback && registers<n> == '1' then R[n] = bits(32) UNKNOWN; // Only possible for encoding A1 3537 if (wback && BitIsSet (registers, n)) 3538 return WriteBits32Unknown (n); 3539 } 3540 return true; 3541} 3542 3543// LDMIB loads multiple registers from consecutive memory locations using an address from a base register. The 3544// consecutive memory locations start just above this address, and thea ddress of the last of those locations can 3545// optinoally be written back to the base register. 3546bool 3547EmulateInstructionARM::EmulateLDMIB (const uint32_t opcode, const ARMEncoding encoding) 3548{ 3549#if 0 3550 if ConditionPassed() then 3551 EncodingSpecificOperations(); 3552 address = R[n] + 4; 3553 3554 for i = 0 to 14 3555 if registers<i> == '1' then 3556 R[i] = MemA[address,4]; address = address + 4; 3557 if registers<15> == '1' then 3558 LoadWritePC(MemA[address,4]); 3559 3560 if wback && registers<n> == '0' then R[n] = R[n] + 4*BitCount(registers); 3561 if wback && registers<n> == '1' then R[n] = bits(32) UNKNOWN; 3562#endif 3563 3564 bool success = false; 3565 3566 if (ConditionPassed(opcode)) 3567 { 3568 uint32_t n; 3569 uint32_t registers = 0; 3570 bool wback; 3571 const uint32_t addr_byte_size = GetAddressByteSize(); 3572 switch (encoding) 3573 { 3574 case eEncodingA1: 3575 // n = UInt(Rn); registers = register_list; wback = (W == '1'); 3576 n = Bits32 (opcode, 19, 16); 3577 registers = Bits32 (opcode, 15, 0); 3578 wback = BitIsSet (opcode, 21); 3579 3580 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE; 3581 if ((n == 15) || (BitCount (registers) < 1)) 3582 return false; 3583 3584 break; 3585 default: 3586 return false; 3587 } 3588 // address = R[n] + 4; 3589 3590 int32_t offset = 0; 3591 addr_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success); 3592 3593 if (!success) 3594 return false; 3595 3596 addr_t address = Rn + addr_byte_size; 3597 3598 EmulateInstruction::Context context; 3599 context.type = EmulateInstruction::eContextRegisterPlusOffset; 3600 Register dwarf_reg; 3601 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n); 3602 context.SetRegisterPlusOffset (dwarf_reg, offset); 3603 3604 for (int i = 0; i < 14; ++i) 3605 { 3606 if (BitIsSet (registers, i)) 3607 { 3608 // R[i] = MemA[address,4]; address = address + 4; 3609 3610 context.SetRegisterPlusOffset (dwarf_reg, offset + addr_byte_size); 3611 uint32_t data = MemARead (context, address + offset, addr_byte_size, 0, &success); 3612 if (!success) 3613 return false; 3614 3615 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + i, data)) 3616 return false; 3617 3618 offset += addr_byte_size; 3619 } 3620 } 3621 3622 // if registers<15> == '1' then 3623 // LoadWritePC(MemA[address,4]); 3624 if (BitIsSet (registers, 15)) 3625 { 3626 context.SetRegisterPlusOffset (dwarf_reg, offset); 3627 uint32_t data = MemARead (context, address + offset, addr_byte_size, 0, &success); 3628 if (!success) 3629 return false; 3630 // In ARMv5T and above, this is an interworking branch. 3631 if (!LoadWritePC(context, data)) 3632 return false; 3633 } 3634 3635 // if wback && registers<n> == '0' then R[n] = R[n] + 4*BitCount(registers); 3636 if (wback && BitIsClear (registers, n)) 3637 { 3638 if (!success) 3639 return false; 3640 3641 offset = addr_byte_size * BitCount (registers); 3642 context.type = EmulateInstruction::eContextAdjustBaseRegister; 3643 context.SetImmediateSigned (offset); 3644 addr_t addr = Rn + offset; 3645 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, addr)) 3646 return false; 3647 } 3648 3649 // if wback && registers<n> == '1' then R[n] = bits(32) UNKNOWN; // Only possible for encoding A1 3650 if (wback && BitIsSet (registers, n)) 3651 return WriteBits32Unknown (n); 3652 } 3653 return true; 3654} 3655 3656// Load Register (immediate) calculates an address from a base register value and 3657// an immediate offset, loads a word from memory, and writes to a register. 3658// LDR (immediate, Thumb) 3659bool 3660EmulateInstructionARM::EmulateLDRRtRnImm (const uint32_t opcode, const ARMEncoding encoding) 3661{ 3662#if 0 3663 // ARM pseudo code... 3664 if (ConditionPassed()) 3665 { 3666 EncodingSpecificOperations(); NullCheckIfThumbEE(15); 3667 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32); 3668 address = if index then offset_addr else R[n]; 3669 data = MemU[address,4]; 3670 if wback then R[n] = offset_addr; 3671 if t == 15 then 3672 if address<1:0> == '00' then LoadWritePC(data); else UNPREDICTABLE; 3673 elsif UnalignedSupport() || address<1:0> = '00' then 3674 R[t] = data; 3675 else R[t] = bits(32) UNKNOWN; // Can only apply before ARMv7 3676 } 3677#endif 3678 3679 bool success = false; 3680 3681 if (ConditionPassed(opcode)) 3682 { 3683 uint32_t Rt; // the destination register 3684 uint32_t Rn; // the base register 3685 uint32_t imm32; // the immediate offset used to form the address 3686 addr_t offset_addr; // the offset address 3687 addr_t address; // the calculated address 3688 uint32_t data; // the literal data value from memory load 3689 bool add, index, wback; 3690 switch (encoding) { 3691 case eEncodingT1: 3692 Rt = Bits32(opcode, 5, 3); 3693 Rn = Bits32(opcode, 2, 0); 3694 imm32 = Bits32(opcode, 10, 6) << 2; // imm32 = ZeroExtend(imm5:'00', 32); 3695 // index = TRUE; add = TRUE; wback = FALSE 3696 add = true; 3697 index = true; 3698 wback = false; 3699 3700 break; 3701 3702 case eEncodingT2: 3703 // t = UInt(Rt); n = 13; imm32 = ZeroExtend(imm8:'00', 32); 3704 Rt = Bits32 (opcode, 10, 8); 3705 Rn = 13; 3706 imm32 = Bits32 (opcode, 7, 0) << 2; 3707 3708 // index = TRUE; add = TRUE; wback = FALSE; 3709 index = true; 3710 add = true; 3711 wback = false; 3712 3713 break; 3714 3715 case eEncodingT3: 3716 // if Rn == '1111' then SEE LDR (literal); 3717 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32); 3718 Rt = Bits32 (opcode, 15, 12); 3719 Rn = Bits32 (opcode, 19, 16); 3720 imm32 = Bits32 (opcode, 11, 0); 3721 3722 // index = TRUE; add = TRUE; wback = FALSE; 3723 index = true; 3724 add = true; 3725 wback = false; 3726 3727 // if t == 15 && InITBlock() && !LastInITBlock() then UNPREDICTABLE; 3728 if ((Rt == 15) && InITBlock() && !LastInITBlock()) 3729 return false; 3730 3731 break; 3732 3733 case eEncodingT4: 3734 // if Rn == '1111' then SEE LDR (literal); 3735 // if P == '1' && U == '1' && W == '0' then SEE LDRT; 3736 // if Rn == '1101' && P == '0' && U == '1' && W == '1' && imm8 == '00000100' then SEE POP; 3737 // if P == '0' && W == '0' then UNDEFINED; 3738 if (BitIsClear (opcode, 10) && BitIsClear (opcode, 8)) 3739 return false; 3740 3741 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32); 3742 Rt = Bits32 (opcode, 15, 12); 3743 Rn = Bits32 (opcode, 19, 16); 3744 imm32 = Bits32 (opcode, 7, 0); 3745 3746 // index = (P == '1'); add = (U == '1'); wback = (W == '1'); 3747 index = BitIsSet (opcode, 10); 3748 add = BitIsSet (opcode, 9); 3749 wback = BitIsSet (opcode, 8); 3750 3751 // if (wback && n == t) || (t == 15 && InITBlock() && !LastInITBlock()) then UNPREDICTABLE; 3752 if ((wback && (Rn == Rt)) || ((Rt == 15) && InITBlock() && !LastInITBlock())) 3753 return false; 3754 3755 break; 3756 3757 default: 3758 return false; 3759 } 3760 uint32_t base = ReadCoreReg (Rn, &success); 3761 if (!success) 3762 return false; 3763 if (add) 3764 offset_addr = base + imm32; 3765 else 3766 offset_addr = base - imm32; 3767 3768 address = (index ? offset_addr : base); 3769 3770 Register base_reg; 3771 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + Rn); 3772 if (wback) 3773 { 3774 EmulateInstruction::Context ctx; 3775 ctx.type = EmulateInstruction::eContextAdjustBaseRegister; 3776 ctx.SetRegisterPlusOffset (base_reg, (int32_t) (offset_addr - base)); 3777 3778 if (!WriteRegisterUnsigned (ctx, eRegisterKindDWARF, dwarf_r0 + Rn, offset_addr)) 3779 return false; 3780 } 3781 3782 // Prepare to write to the Rt register. 3783 EmulateInstruction::Context context; 3784 context.type = EmulateInstruction::eContextRegisterLoad; 3785 context.SetRegisterPlusOffset (base_reg, (int32_t) (offset_addr - base)); 3786 3787 // Read memory from the address. 3788 data = MemURead(context, address, 4, 0, &success); 3789 if (!success) 3790 return false; 3791 3792 if (Rt == 15) 3793 { 3794 if (Bits32(address, 1, 0) == 0) 3795 { 3796 if (!LoadWritePC(context, data)) 3797 return false; 3798 } 3799 else 3800 return false; 3801 } 3802 else if (UnalignedSupport() || Bits32(address, 1, 0) == 0) 3803 { 3804 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + Rt, data)) 3805 return false; 3806 } 3807 else 3808 WriteBits32Unknown (Rt); 3809 } 3810 return true; 3811} 3812 3813// STM (Store Multiple Increment After) stores multiple registers to consecutive memory locations using an address 3814// from a base register. The consecutive memory locations start at this address, and teh address just above the last 3815// of those locations can optionally be written back to the base register. 3816bool 3817EmulateInstructionARM::EmulateSTM (const uint32_t opcode, const ARMEncoding encoding) 3818{ 3819#if 0 3820 if ConditionPassed() then 3821 EncodingSpecificOperations(); NullCheckIfThumbEE(n); 3822 address = R[n]; 3823 3824 for i = 0 to 14 3825 if registers<i> == '1' then 3826 if i == n && wback && i != LowestSetBit(registers) then 3827 MemA[address,4] = bits(32) UNKNOWN; // Only possible for encodings T1 and A1 3828 else 3829 MemA[address,4] = R[i]; 3830 address = address + 4; 3831 3832 if registers<15> == '1' then // Only possible for encoding A1 3833 MemA[address,4] = PCStoreValue(); 3834 if wback then R[n] = R[n] + 4*BitCount(registers); 3835#endif 3836 3837 bool success = false; 3838 3839 if (ConditionPassed(opcode)) 3840 { 3841 uint32_t n; 3842 uint32_t registers = 0; 3843 bool wback; 3844 const uint32_t addr_byte_size = GetAddressByteSize(); 3845 3846 // EncodingSpecificOperations(); NullCheckIfThumbEE(n); 3847 switch (encoding) 3848 { 3849 case eEncodingT1: 3850 // n = UInt(Rn); registers = '00000000':register_list; wback = TRUE; 3851 n = Bits32 (opcode, 10, 8); 3852 registers = Bits32 (opcode, 7, 0); 3853 registers = registers & 0x00ff; // Make sure the top 8 bits are zeros. 3854 wback = true; 3855 3856 // if BitCount(registers) < 1 then UNPREDICTABLE; 3857 if (BitCount (registers) < 1) 3858 return false; 3859 3860 break; 3861 3862 case eEncodingT2: 3863 // n = UInt(Rn); registers = '0':M:'0':register_list; wback = (W == '1'); 3864 n = Bits32 (opcode, 19, 16); 3865 registers = Bits32 (opcode, 15, 0); 3866 registers = registers & 0x5fff; // Make sure bits 15 & 13 are zeros. 3867 wback = BitIsSet (opcode, 21); 3868 3869 // if n == 15 || BitCount(registers) < 2 then UNPREDICTABLE; 3870 if ((n == 15) || (BitCount (registers) < 2)) 3871 return false; 3872 3873 // if wback && registers<n> == '1' then UNPREDICTABLE; 3874 if (wback && BitIsSet (registers, n)) 3875 return false; 3876 3877 break; 3878 3879 case eEncodingA1: 3880 // n = UInt(Rn); registers = register_list; wback = (W == '1'); 3881 n = Bits32 (opcode, 19, 16); 3882 registers = Bits32 (opcode, 15, 0); 3883 wback = BitIsSet (opcode, 21); 3884 3885 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE; 3886 if ((n == 15) || (BitCount (registers) < 1)) 3887 return false; 3888 3889 break; 3890 3891 default: 3892 return false; 3893 } 3894 3895 // address = R[n]; 3896 int32_t offset = 0; 3897 const addr_t address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success); 3898 if (!success) 3899 return false; 3900 3901 EmulateInstruction::Context context; 3902 context.type = EmulateInstruction::eContextRegisterStore; 3903 Register base_reg; 3904 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n); 3905 3906 // for i = 0 to 14 3907 int lowest_set_bit = 14; 3908 for (int i = 0; i < 14; ++i) 3909 { 3910 // if registers<i> == '1' then 3911 if (BitIsSet (registers, i)) 3912 { 3913 if (i < lowest_set_bit) 3914 lowest_set_bit = i; 3915 // if i == n && wback && i != LowestSetBit(registers) then 3916 if ((i == n) && wback && (i != lowest_set_bit)) 3917 // MemA[address,4] = bits(32) UNKNOWN; // Only possible for encodings T1 and A1 3918 WriteBits32UnknownToMemory (address + offset); 3919 else 3920 { 3921 // MemA[address,4] = R[i]; 3922 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + i, 0, &success); 3923 if (!success) 3924 return false; 3925 3926 Register data_reg; 3927 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + i); 3928 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, offset); 3929 if (!MemAWrite (context, address + offset, data, addr_byte_size)) 3930 return false; 3931 } 3932 3933 // address = address + 4; 3934 offset += addr_byte_size; 3935 } 3936 } 3937 3938 // if registers<15> == '1' then // Only possible for encoding A1 3939 // MemA[address,4] = PCStoreValue(); 3940 if (BitIsSet (registers, 15)) 3941 { 3942 Register pc_reg; 3943 pc_reg.SetRegister (eRegisterKindDWARF, dwarf_pc); 3944 context.SetRegisterPlusOffset (pc_reg, 8); 3945 const uint32_t pc = ReadCoreReg (PC_REG, &success); 3946 if (!success) 3947 return false; 3948 3949 if (!MemAWrite (context, address + offset, pc, addr_byte_size)) 3950 return false; 3951 } 3952 3953 // if wback then R[n] = R[n] + 4*BitCount(registers); 3954 if (wback) 3955 { 3956 offset = addr_byte_size * BitCount (registers); 3957 context.type = EmulateInstruction::eContextAdjustBaseRegister; 3958 context.SetImmediateSigned (offset); 3959 addr_t data = address + offset; 3960 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, data)) 3961 return false; 3962 } 3963 } 3964 return true; 3965} 3966 3967// STMDA (Store Multiple Decrement After) stores multiple registers to consecutive memory locations using an address 3968// from a base register. The consecutive memory locations end at this address, and the address just below the lowest 3969// of those locations can optionally be written back to the base register. 3970bool 3971EmulateInstructionARM::EmulateSTMDA (const uint32_t opcode, const ARMEncoding encoding) 3972{ 3973#if 0 3974 if ConditionPassed() then 3975 EncodingSpecificOperations(); 3976 address = R[n] - 4*BitCount(registers) + 4; 3977 3978 for i = 0 to 14 3979 if registers<i> == '1' then 3980 if i == n && wback && i != LowestSetBit(registers) then 3981 MemA[address,4] = bits(32) UNKNOWN; 3982 else 3983 MemA[address,4] = R[i]; 3984 address = address + 4; 3985 3986 if registers<15> == '1' then 3987 MemA[address,4] = PCStoreValue(); 3988 3989 if wback then R[n] = R[n] - 4*BitCount(registers); 3990#endif 3991 3992 bool success = false; 3993 3994 if (ConditionPassed(opcode)) 3995 { 3996 uint32_t n; 3997 uint32_t registers = 0; 3998 bool wback; 3999 const uint32_t addr_byte_size = GetAddressByteSize(); 4000 4001 // EncodingSpecificOperations(); 4002 switch (encoding) 4003 { 4004 case eEncodingA1: 4005 // n = UInt(Rn); registers = register_list; wback = (W == '1'); 4006 n = Bits32 (opcode, 19, 16); 4007 registers = Bits32 (opcode, 15, 0); 4008 wback = BitIsSet (opcode, 21); 4009 4010 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE; 4011 if ((n == 15) || (BitCount (registers) < 1)) 4012 return false; 4013 break; 4014 default: 4015 return false; 4016 } 4017 4018 // address = R[n] - 4*BitCount(registers) + 4; 4019 int32_t offset = 0; 4020 addr_t Rn = ReadCoreReg (n, &success); 4021 if (!success) 4022 return false; 4023 4024 addr_t address = Rn - (addr_byte_size * BitCount (registers)) + 4; 4025 4026 EmulateInstruction::Context context; 4027 context.type = EmulateInstruction::eContextRegisterStore; 4028 Register base_reg; 4029 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n); 4030 4031 // for i = 0 to 14 4032 int lowest_bit_set = 14; 4033 for (int i = 0; i < 14; ++i) 4034 { 4035 // if registers<i> == '1' then 4036 if (BitIsSet (registers, i)) 4037 { 4038 if (i < lowest_bit_set) 4039 lowest_bit_set = i; 4040 //if i == n && wback && i != LowestSetBit(registers) then 4041 if ((i == n) && wback && (i != lowest_bit_set)) 4042 // MemA[address,4] = bits(32) UNKNOWN; 4043 WriteBits32UnknownToMemory (address + offset); 4044 else 4045 { 4046 // MemA[address,4] = R[i]; 4047 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + i, 0, &success); 4048 if (!success) 4049 return false; 4050 4051 Register data_reg; 4052 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + i); 4053 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, Rn - (address + offset)); 4054 if (!MemAWrite (context, address + offset, data, addr_byte_size)) 4055 return false; 4056 } 4057 4058 // address = address + 4; 4059 offset += addr_byte_size; 4060 } 4061 } 4062 4063 // if registers<15> == '1' then 4064 // MemA[address,4] = PCStoreValue(); 4065 if (BitIsSet (registers, 15)) 4066 { 4067 Register pc_reg; 4068 pc_reg.SetRegister (eRegisterKindDWARF, dwarf_pc); 4069 context.SetRegisterPlusOffset (pc_reg, 8); 4070 const uint32_t pc = ReadCoreReg (PC_REG, &success); 4071 if (!success) 4072 return false; 4073 4074 if (!MemAWrite (context, address + offset, pc, addr_byte_size)) 4075 return false; 4076 } 4077 4078 // if wback then R[n] = R[n] - 4*BitCount(registers); 4079 if (wback) 4080 { 4081 offset = (addr_byte_size * BitCount (registers)) * -1; 4082 context.type = EmulateInstruction::eContextAdjustBaseRegister; 4083 context.SetImmediateSigned (offset); 4084 addr_t data = Rn + offset; 4085 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, data)) 4086 return false; 4087 } 4088 } 4089 return true; 4090} 4091 4092// STMDB (Store Multiple Decrement Before) stores multiple registers to consecutive memory locations using an address 4093// from a base register. The consecutive memory locations end just below this address, and the address of the first of 4094// those locations can optionally be written back to the base register. 4095bool 4096EmulateInstructionARM::EmulateSTMDB (const uint32_t opcode, const ARMEncoding encoding) 4097{ 4098#if 0 4099 if ConditionPassed() then 4100 EncodingSpecificOperations(); NullCheckIfThumbEE(n); 4101 address = R[n] - 4*BitCount(registers); 4102 4103 for i = 0 to 14 4104 if registers<i> == '1' then 4105 if i == n && wback && i != LowestSetBit(registers) then 4106 MemA[address,4] = bits(32) UNKNOWN; // Only possible for encoding A1 4107 else 4108 MemA[address,4] = R[i]; 4109 address = address + 4; 4110 4111 if registers<15> == '1' then // Only possible for encoding A1 4112 MemA[address,4] = PCStoreValue(); 4113 4114 if wback then R[n] = R[n] - 4*BitCount(registers); 4115#endif 4116 4117 4118 bool success = false; 4119 4120 if (ConditionPassed(opcode)) 4121 { 4122 uint32_t n; 4123 uint32_t registers = 0; 4124 bool wback; 4125 const uint32_t addr_byte_size = GetAddressByteSize(); 4126 4127 // EncodingSpecificOperations(); NullCheckIfThumbEE(n); 4128 switch (encoding) 4129 { 4130 case eEncodingT1: 4131 // if W == '1' && Rn == '1101' then SEE PUSH; 4132 if ((BitIsSet (opcode, 21)) && (Bits32 (opcode, 19, 16) == 13)) 4133 { 4134 // See PUSH 4135 } 4136 // n = UInt(Rn); registers = '0':M:'0':register_list; wback = (W == '1'); 4137 n = Bits32 (opcode, 19, 16); 4138 registers = Bits32 (opcode, 15, 0); 4139 registers = registers & 0x5fff; // Make sure bits 15 & 13 are zeros. 4140 wback = BitIsSet (opcode, 21); 4141 // if n == 15 || BitCount(registers) < 2 then UNPREDICTABLE; 4142 if ((n == 15) || BitCount (registers) < 2) 4143 return false; 4144 // if wback && registers<n> == '1' then UNPREDICTABLE; 4145 if (wback && BitIsSet (registers, n)) 4146 return false; 4147 break; 4148 4149 case eEncodingA1: 4150 // if W == '1' && Rn == '1101’ && BitCount(register_list) >= 2 then SEE PUSH; 4151 if (BitIsSet (opcode, 21) && (Bits32 (opcode, 19, 16) == 13) && BitCount (Bits32 (opcode, 15, 0)) >= 2) 4152 { 4153 // See Push 4154 } 4155 // n = UInt(Rn); registers = register_list; wback = (W == '1'); 4156 n = Bits32 (opcode, 19, 16); 4157 registers = Bits32 (opcode, 15, 0); 4158 wback = BitIsSet (opcode, 21); 4159 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE; 4160 if ((n == 15) || BitCount (registers) < 1) 4161 return false; 4162 break; 4163 4164 default: 4165 return false; 4166 } 4167 4168 // address = R[n] - 4*BitCount(registers); 4169 4170 int32_t offset = 0; 4171 addr_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success); 4172 if (!success) 4173 return false; 4174 4175 addr_t address = Rn - (addr_byte_size * BitCount (registers)); 4176 4177 EmulateInstruction::Context context; 4178 context.type = EmulateInstruction::eContextRegisterStore; 4179 Register base_reg; 4180 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n); 4181 4182 // for i = 0 to 14 4183 uint32_t lowest_set_bit = 14; 4184 for (int i = 0; i < 14; ++i) 4185 { 4186 // if registers<i> == '1' then 4187 if (BitIsSet (registers, i)) 4188 { 4189 if (i < lowest_set_bit) 4190 lowest_set_bit = i; 4191 // if i == n && wback && i != LowestSetBit(registers) then 4192 if ((i == n) && wback && (i != lowest_set_bit)) 4193 // MemA[address,4] = bits(32) UNKNOWN; // Only possible for encoding A1 4194 WriteBits32UnknownToMemory (address + offset); 4195 else 4196 { 4197 // MemA[address,4] = R[i]; 4198 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + i, 0, &success); 4199 if (!success) 4200 return false; 4201 4202 Register data_reg; 4203 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + i); 4204 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, Rn - (address + offset)); 4205 if (!MemAWrite (context, address + offset, data, addr_byte_size)) 4206 return false; 4207 } 4208 4209 // address = address + 4; 4210 offset += addr_byte_size; 4211 } 4212 } 4213 4214 // if registers<15> == '1' then // Only possible for encoding A1 4215 // MemA[address,4] = PCStoreValue(); 4216 if (BitIsSet (registers, 15)) 4217 { 4218 Register pc_reg; 4219 pc_reg.SetRegister (eRegisterKindDWARF, dwarf_pc); 4220 context.SetRegisterPlusOffset (pc_reg, 8); 4221 const uint32_t pc = ReadCoreReg (PC_REG, &success); 4222 if (!success) 4223 return false; 4224 4225 if (!MemAWrite (context, address + offset, pc, addr_byte_size)) 4226 return false; 4227 } 4228 4229 // if wback then R[n] = R[n] - 4*BitCount(registers); 4230 if (wback) 4231 { 4232 offset = (addr_byte_size * BitCount (registers)) * -1; 4233 context.type = EmulateInstruction::eContextAdjustBaseRegister; 4234 context.SetImmediateSigned (offset); 4235 addr_t data = Rn + offset; 4236 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, data)) 4237 return false; 4238 } 4239 } 4240 return true; 4241} 4242 4243// STMIB (Store Multiple Increment Before) stores multiple registers to consecutive memory locations using an address 4244// from a base register. The consecutive memory locations start just above this address, and the address of the last 4245// of those locations can optionally be written back to the base register. 4246bool 4247EmulateInstructionARM::EmulateSTMIB (const uint32_t opcode, const ARMEncoding encoding) 4248{ 4249#if 0 4250 if ConditionPassed() then 4251 EncodingSpecificOperations(); 4252 address = R[n] + 4; 4253 4254 for i = 0 to 14 4255 if registers<i> == '1' then 4256 if i == n && wback && i != LowestSetBit(registers) then 4257 MemA[address,4] = bits(32) UNKNOWN; 4258 else 4259 MemA[address,4] = R[i]; 4260 address = address + 4; 4261 4262 if registers<15> == '1' then 4263 MemA[address,4] = PCStoreValue(); 4264 4265 if wback then R[n] = R[n] + 4*BitCount(registers); 4266#endif 4267 4268 bool success = false; 4269 4270 if (ConditionPassed(opcode)) 4271 { 4272 uint32_t n; 4273 uint32_t registers = 0; 4274 bool wback; 4275 const uint32_t addr_byte_size = GetAddressByteSize(); 4276 4277 // EncodingSpecificOperations(); 4278 switch (encoding) 4279 { 4280 case eEncodingA1: 4281 // n = UInt(Rn); registers = register_list; wback = (W == '1'); 4282 n = Bits32 (opcode, 19, 16); 4283 registers = Bits32 (opcode, 15, 0); 4284 wback = BitIsSet (opcode, 21); 4285 4286 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE; 4287 if ((n == 15) && (BitCount (registers) < 1)) 4288 return false; 4289 break; 4290 default: 4291 return false; 4292 } 4293 // address = R[n] + 4; 4294 4295 int32_t offset = 0; 4296 addr_t Rn = ReadCoreReg (n, &success); 4297 if (!success) 4298 return false; 4299 4300 addr_t address = Rn + addr_byte_size; 4301 4302 EmulateInstruction::Context context; 4303 context.type = EmulateInstruction::eContextRegisterStore; 4304 Register base_reg; 4305 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n); 4306 4307 uint32_t lowest_set_bit = 14; 4308 // for i = 0 to 14 4309 for (int i = 0; i < 14; ++i) 4310 { 4311 // if registers<i> == '1' then 4312 if (BitIsSet (registers, i)) 4313 { 4314 if (i < lowest_set_bit) 4315 lowest_set_bit = i; 4316 // if i == n && wback && i != LowestSetBit(registers) then 4317 if ((i == n) && wback && (i != lowest_set_bit)) 4318 // MemA[address,4] = bits(32) UNKNOWN; 4319 WriteBits32UnknownToMemory (address + offset); 4320 // else 4321 else 4322 { 4323 // MemA[address,4] = R[i]; 4324 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + i, 0, &success); 4325 if (!success) 4326 return false; 4327 4328 Register data_reg; 4329 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + i); 4330 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, offset + addr_byte_size); 4331 if (!MemAWrite (context, address + offset, data, addr_byte_size)) 4332 return false; 4333 } 4334 4335 // address = address + 4; 4336 offset += addr_byte_size; 4337 } 4338 } 4339 4340 // if registers<15> == '1' then 4341 // MemA[address,4] = PCStoreValue(); 4342 if (BitIsSet (registers, 15)) 4343 { 4344 Register pc_reg; 4345 pc_reg.SetRegister (eRegisterKindDWARF, dwarf_pc); 4346 context.SetRegisterPlusOffset (pc_reg, 8); 4347 const uint32_t pc = ReadCoreReg (PC_REG, &success); 4348 if (!success) 4349 return false; 4350 4351 if (!MemAWrite (context, address + offset, pc, addr_byte_size)) 4352 return false; 4353 } 4354 4355 // if wback then R[n] = R[n] + 4*BitCount(registers); 4356 if (wback) 4357 { 4358 offset = addr_byte_size * BitCount (registers); 4359 context.type = EmulateInstruction::eContextAdjustBaseRegister; 4360 context.SetImmediateSigned (offset); 4361 addr_t data = Rn + offset; 4362 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, data)) 4363 return false; 4364 } 4365 } 4366 return true; 4367} 4368 4369// STR (store immediate) calcualtes an address from a base register value and an immediate offset, and stores a word 4370// from a register to memory. It can use offset, post-indexed, or pre-indexed addressing. 4371bool 4372EmulateInstructionARM::EmulateSTRThumb (const uint32_t opcode, const ARMEncoding encoding) 4373{ 4374#if 0 4375 if ConditionPassed() then 4376 EncodingSpecificOperations(); NullCheckIfThumbEE(n); 4377 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32); 4378 address = if index then offset_addr else R[n]; 4379 if UnalignedSupport() || address<1:0> == '00' then 4380 MemU[address,4] = R[t]; 4381 else // Can only occur before ARMv7 4382 MemU[address,4] = bits(32) UNKNOWN; 4383 if wback then R[n] = offset_addr; 4384#endif 4385 4386 bool success = false; 4387 4388 if (ConditionPassed(opcode)) 4389 { 4390 const uint32_t addr_byte_size = GetAddressByteSize(); 4391 4392 uint32_t t; 4393 uint32_t n; 4394 uint32_t imm32; 4395 bool index; 4396 bool add; 4397 bool wback; 4398 // EncodingSpecificOperations (); NullCheckIfThumbEE(n); 4399 switch (encoding) 4400 { 4401 case eEncodingT1: 4402 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm5:'00', 32); 4403 t = Bits32 (opcode, 2, 0); 4404 n = Bits32 (opcode, 5, 3); 4405 imm32 = Bits32 (opcode, 10, 6) << 2; 4406 4407 // index = TRUE; add = TRUE; wback = FALSE; 4408 index = true; 4409 add = false; 4410 wback = false; 4411 break; 4412 4413 case eEncodingT2: 4414 // t = UInt(Rt); n = 13; imm32 = ZeroExtend(imm8:'00', 32); 4415 t = Bits32 (opcode, 10, 8); 4416 n = 13; 4417 imm32 = Bits32 (opcode, 7, 0) << 2; 4418 4419 // index = TRUE; add = TRUE; wback = FALSE; 4420 index = true; 4421 add = true; 4422 wback = false; 4423 break; 4424 4425 case eEncodingT3: 4426 // if Rn == '1111' then UNDEFINED; 4427 if (Bits32 (opcode, 19, 16) == 15) 4428 return false; 4429 4430 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32); 4431 t = Bits32 (opcode, 15, 12); 4432 n = Bits32 (opcode, 19, 16); 4433 imm32 = Bits32 (opcode, 11, 0); 4434 4435 // index = TRUE; add = TRUE; wback = FALSE; 4436 index = true; 4437 add = true; 4438 wback = false; 4439 4440 // if t == 15 then UNPREDICTABLE; 4441 if (t == 15) 4442 return false; 4443 break; 4444 4445 case eEncodingT4: 4446 // if P == '1' && U == '1' && W == '0' then SEE STRT; 4447 // if Rn == '1101' && P == '1' && U == '0' && W == '1' && imm8 == '00000100' then SEE PUSH; 4448 // if Rn == '1111' || (P == '0' && W == '0') then UNDEFINED; 4449 if ((Bits32 (opcode, 19, 16) == 15) 4450 || (BitIsClear (opcode, 10) && BitIsClear (opcode, 8))) 4451 return false; 4452 4453 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32); 4454 t = Bits32 (opcode, 15, 12); 4455 n = Bits32 (opcode, 19, 16); 4456 imm32 = Bits32 (opcode, 7, 0); 4457 4458 // index = (P == '1'); add = (U == '1'); wback = (W == '1'); 4459 index = BitIsSet (opcode, 10); 4460 add = BitIsSet (opcode, 9); 4461 wback = BitIsSet (opcode, 8); 4462 4463 // if t == 15 || (wback && n == t) then UNPREDICTABLE; 4464 if ((t == 15) || (wback && (n == t))) 4465 return false; 4466 break; 4467 4468 default: 4469 return false; 4470 } 4471 4472 addr_t offset_addr; 4473 addr_t address; 4474 4475 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32); 4476 uint32_t base_address = ReadCoreReg (n, &success); 4477 if (!success) 4478 return false; 4479 4480 if (add) 4481 offset_addr = base_address + imm32; 4482 else 4483 offset_addr = base_address - imm32; 4484 4485 // address = if index then offset_addr else R[n]; 4486 if (index) 4487 address = offset_addr; 4488 else 4489 address = base_address; 4490 4491 EmulateInstruction::Context context; 4492 context.type = eContextRegisterStore; 4493 Register base_reg; 4494 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n); 4495 4496 // if UnalignedSupport() || address<1:0> == '00' then 4497 if (UnalignedSupport () || (BitIsClear (address, 1) && BitIsClear (address, 0))) 4498 { 4499 // MemU[address,4] = R[t]; 4500 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + t, 0, &success); 4501 if (!success) 4502 return false; 4503 4504 Register data_reg; 4505 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + t); 4506 int32_t offset = address - base_address; 4507 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, offset); 4508 if (!MemUWrite (context, address, data, addr_byte_size)) 4509 return false; 4510 } 4511 else 4512 { 4513 // MemU[address,4] = bits(32) UNKNOWN; 4514 WriteBits32UnknownToMemory (address); 4515 } 4516 4517 // if wback then R[n] = offset_addr; 4518 if (wback) 4519 { 4520 context.type = eContextRegisterLoad; 4521 context.SetAddress (offset_addr); 4522 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr)) 4523 return false; 4524 } 4525 } 4526 return true; 4527} 4528 4529// STR (Store Register) calculates an address from a base register value and an offset register value, stores a 4530// word from a register to memory. The offset register value can optionally be shifted. 4531bool 4532EmulateInstructionARM::EmulateSTRRegister (const uint32_t opcode, const ARMEncoding encoding) 4533{ 4534#if 0 4535 if ConditionPassed() then 4536 EncodingSpecificOperations(); NullCheckIfThumbEE(n); 4537 offset = Shift(R[m], shift_t, shift_n, APSR.C); 4538 offset_addr = if add then (R[n] + offset) else (R[n] - offset); 4539 address = if index then offset_addr else R[n]; 4540 if t == 15 then // Only possible for encoding A1 4541 data = PCStoreValue(); 4542 else 4543 data = R[t]; 4544 if UnalignedSupport() || address<1:0> == '00' || CurrentInstrSet() == InstrSet_ARM then 4545 MemU[address,4] = data; 4546 else // Can only occur before ARMv7 4547 MemU[address,4] = bits(32) UNKNOWN; 4548 if wback then R[n] = offset_addr; 4549#endif 4550 4551 bool success = false; 4552 4553 if (ConditionPassed(opcode)) 4554 { 4555 const uint32_t addr_byte_size = GetAddressByteSize(); 4556 4557 uint32_t t; 4558 uint32_t n; 4559 uint32_t m; 4560 ARM_ShifterType shift_t; 4561 uint32_t shift_n; 4562 bool index; 4563 bool add; 4564 bool wback; 4565 4566 // EncodingSpecificOperations (); NullCheckIfThumbEE(n); 4567 switch (encoding) 4568 { 4569 case eEncodingT1: 4570 // if CurrentInstrSet() == InstrSet_ThumbEE then SEE "Modified operation in ThumbEE"; 4571 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm); 4572 t = Bits32 (opcode, 2, 0); 4573 n = Bits32 (opcode, 5, 3); 4574 m = Bits32 (opcode, 8, 6); 4575 4576 // index = TRUE; add = TRUE; wback = FALSE; 4577 index = true; 4578 add = true; 4579 wback = false; 4580 4581 // (shift_t, shift_n) = (SRType_LSL, 0); 4582 shift_t = SRType_LSL; 4583 shift_n = 0; 4584 break; 4585 4586 case eEncodingT2: 4587 // if Rn == '1111' then UNDEFINED; 4588 if (Bits32 (opcode, 19, 16) == 15) 4589 return false; 4590 4591 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm); 4592 t = Bits32 (opcode, 15, 12); 4593 n = Bits32 (opcode, 19, 16); 4594 m = Bits32 (opcode, 3, 0); 4595 4596 // index = TRUE; add = TRUE; wback = FALSE; 4597 index = true; 4598 add = true; 4599 wback = false; 4600 4601 // (shift_t, shift_n) = (SRType_LSL, UInt(imm2)); 4602 shift_t = SRType_LSL; 4603 shift_n = Bits32 (opcode, 5, 4); 4604 4605 // if t == 15 || BadReg(m) then UNPREDICTABLE; 4606 if ((t == 15) || (BadReg (m))) 4607 return false; 4608 break; 4609 4610 case eEncodingA1: 4611 { 4612 // if P == '0' && W == '1' then SEE STRT; 4613 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm); 4614 t = Bits32 (opcode, 15, 12); 4615 n = Bits32 (opcode, 19, 16); 4616 m = Bits32 (opcode, 3, 0); 4617 4618 // index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1'); 4619 index = BitIsSet (opcode, 24); 4620 add = BitIsSet (opcode, 23); 4621 wback = (BitIsClear (opcode, 24) || BitIsSet (opcode, 21)); 4622 4623 // (shift_t, shift_n) = DecodeImmShift(type, imm5); 4624 uint32_t typ = Bits32 (opcode, 6, 5); 4625 uint32_t imm5 = Bits32 (opcode, 11, 7); 4626 shift_n = DecodeImmShift(typ, imm5, shift_t); 4627 4628 // if m == 15 then UNPREDICTABLE; 4629 if (m == 15) 4630 return false; 4631 4632 // if wback && (n == 15 || n == t) then UNPREDICTABLE; 4633 if (wback && ((n == 15) || (n == t))) 4634 return false; 4635 4636 break; 4637 } 4638 default: 4639 return false; 4640 } 4641 4642 addr_t offset_addr; 4643 addr_t address; 4644 int32_t offset = 0; 4645 4646 addr_t base_address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success); 4647 if (!success) 4648 return false; 4649 4650 uint32_t Rm_data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success); 4651 if (!success) 4652 return false; 4653 4654 // offset = Shift(R[m], shift_t, shift_n, APSR.C); 4655 offset = Shift (Rm_data, shift_t, shift_n, APSR_C); 4656 4657 // offset_addr = if add then (R[n] + offset) else (R[n] - offset); 4658 if (add) 4659 offset_addr = base_address + offset; 4660 else 4661 offset_addr = base_address - offset; 4662 4663 // address = if index then offset_addr else R[n]; 4664 if (index) 4665 address = offset_addr; 4666 else 4667 address = base_address; 4668 4669 uint32_t data; 4670 // if t == 15 then // Only possible for encoding A1 4671 if (t == 15) 4672 // data = PCStoreValue(); 4673 data = ReadCoreReg (PC_REG, &success); 4674 else 4675 // data = R[t]; 4676 data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + t, 0, &success); 4677 4678 if (!success) 4679 return false; 4680 4681 EmulateInstruction::Context context; 4682 context.type = eContextRegisterStore; 4683 4684 // if UnalignedSupport() || address<1:0> == '00' || CurrentInstrSet() == InstrSet_ARM then 4685 if (UnalignedSupport () 4686 || (BitIsClear (address, 1) && BitIsClear (address, 0)) 4687 || CurrentInstrSet() == eModeARM) 4688 { 4689 // MemU[address,4] = data; 4690 4691 Register base_reg; 4692 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n); 4693 4694 Register data_reg; 4695 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + t); 4696 4697 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, address - base_address); 4698 if (!MemUWrite (context, address, data, addr_byte_size)) 4699 return false; 4700 4701 } 4702 else 4703 // MemU[address,4] = bits(32) UNKNOWN; 4704 WriteBits32UnknownToMemory (address); 4705 4706 // if wback then R[n] = offset_addr; 4707 if (wback) 4708 { 4709 context.type = eContextRegisterLoad; 4710 context.SetAddress (offset_addr); 4711 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr)) 4712 return false; 4713 } 4714 4715 } 4716 return true; 4717} 4718 4719bool 4720EmulateInstructionARM::EmulateSTRBThumb (const uint32_t opcode, const ARMEncoding encoding) 4721{ 4722#if 0 4723 if ConditionPassed() then 4724 EncodingSpecificOperations(); NullCheckIfThumbEE(n); 4725 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32); 4726 address = if index then offset_addr else R[n]; 4727 MemU[address,1] = R[t]<7:0>; 4728 if wback then R[n] = offset_addr; 4729#endif 4730 4731 4732 bool success = false; 4733 4734 if (ConditionPassed(opcode)) 4735 { 4736 uint32_t t; 4737 uint32_t n; 4738 uint32_t imm32; 4739 bool index; 4740 bool add; 4741 bool wback; 4742 // EncodingSpecificOperations(); NullCheckIfThumbEE(n); 4743 switch (encoding) 4744 { 4745 case eEncodingT1: 4746 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm5, 32); 4747 t = Bits32 (opcode, 2, 0); 4748 n = Bits32 (opcode, 5, 3); 4749 imm32 = Bits32 (opcode, 10, 6); 4750 4751 // index = TRUE; add = TRUE; wback = FALSE; 4752 index = true; 4753 add = true; 4754 wback = false; 4755 break; 4756 4757 case eEncodingT2: 4758 // if Rn == '1111' then UNDEFINED; 4759 if (Bits32 (opcode, 19, 16) == 15) 4760 return false; 4761 4762 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32); 4763 t = Bits32 (opcode, 15, 12); 4764 n = Bits32 (opcode, 19, 16); 4765 imm32 = Bits32 (opcode, 11, 0); 4766 4767 // index = TRUE; add = TRUE; wback = FALSE; 4768 index = true; 4769 add = true; 4770 wback = false; 4771 4772 // if BadReg(t) then UNPREDICTABLE; 4773 if (BadReg (t)) 4774 return false; 4775 break; 4776 4777 case eEncodingT3: 4778 // if P == '1' && U == '1' && W == '0' then SEE STRBT; 4779 // if Rn == '1111' || (P == '0' && W == '0') then UNDEFINED; 4780 if (Bits32 (opcode, 19, 16) == 15) 4781 return false; 4782 4783 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32); 4784 t = Bits32 (opcode, 15, 12); 4785 n = Bits32 (opcode, 19, 16); 4786 imm32 = Bits32 (opcode, 7, 0); 4787 4788 // index = (P == '1'); add = (U == '1'); wback = (W == '1'); 4789 index = BitIsSet (opcode, 10); 4790 add = BitIsSet (opcode, 9); 4791 wback = BitIsSet (opcode, 8); 4792 4793 // if BadReg(t) || (wback && n == t) then UNPREDICTABLE 4794 if ((BadReg (t)) || (wback && (n == t))) 4795 return false; 4796 break; 4797 4798 default: 4799 return false; 4800 } 4801 4802 addr_t offset_addr; 4803 addr_t address; 4804 addr_t base_address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success); 4805 if (!success) 4806 return false; 4807 4808 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32); 4809 if (add) 4810 offset_addr = base_address + imm32; 4811 else 4812 offset_addr = base_address - imm32; 4813 4814 // address = if index then offset_addr else R[n]; 4815 if (index) 4816 address = offset_addr; 4817 else 4818 address = base_address; 4819 4820 // MemU[address,1] = R[t]<7:0> 4821 Register base_reg; 4822 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n); 4823 4824 Register data_reg; 4825 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + t); 4826 4827 EmulateInstruction::Context context; 4828 context.type = eContextRegisterStore; 4829 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, address - base_address); 4830 4831 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + t, 0, &success); 4832 if (!success) 4833 return false; 4834 4835 data = Bits32 (data, 7, 0); 4836 4837 if (!MemUWrite (context, address, data, 1)) 4838 return false; 4839 4840 // if wback then R[n] = offset_addr; 4841 if (wback) 4842 { 4843 context.type = eContextRegisterLoad; 4844 context.SetAddress (offset_addr); 4845 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr)) 4846 return false; 4847 } 4848 4849 } 4850 4851 return true; 4852} 4853 4854// STRH (register) calculates an address from a base register value and an offset register value, and stores a 4855// halfword from a register to memory. The offset register alue can be shifted left by 0, 1, 2, or 3 bits. 4856bool 4857EmulateInstructionARM::EmulateSTRHRegister (const uint32_t opcode, const ARMEncoding encoding) 4858{ 4859#if 0 4860 if ConditionPassed() then 4861 EncodingSpecificOperations(); NullCheckIfThumbEE(n); 4862 offset = Shift(R[m], shift_t, shift_n, APSR.C); 4863 offset_addr = if add then (R[n] + offset) else (R[n] - offset); 4864 address = if index then offset_addr else R[n]; 4865 if UnalignedSupport() || address<0> == '0' then 4866 MemU[address,2] = R[t]<15:0>; 4867 else // Can only occur before ARMv7 4868 MemU[address,2] = bits(16) UNKNOWN; 4869 if wback then R[n] = offset_addr; 4870#endif 4871 4872 bool success = false; 4873 4874 if (ConditionPassed(opcode)) 4875 { 4876 uint32_t t; 4877 uint32_t n; 4878 uint32_t m; 4879 bool index; 4880 bool add; 4881 bool wback; 4882 ARM_ShifterType shift_t; 4883 uint32_t shift_n; 4884 4885 // EncodingSpecificOperations(); NullCheckIfThumbEE(n); 4886 switch (encoding) 4887 { 4888 case eEncodingT1: 4889 // if CurrentInstrSet() == InstrSet_ThumbEE then SEE "Modified operation in ThumbEE"; 4890 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm); 4891 t = Bits32 (opcode, 2, 0); 4892 n = Bits32 (opcode, 5, 3); 4893 m = Bits32 (opcode, 8, 6); 4894 4895 // index = TRUE; add = TRUE; wback = FALSE; 4896 index = true; 4897 add = true; 4898 wback = false; 4899 4900 // (shift_t, shift_n) = (SRType_LSL, 0); 4901 shift_t = SRType_LSL; 4902 shift_n = 0; 4903 4904 break; 4905 4906 case eEncodingT2: 4907 // if Rn == '1111' then UNDEFINED; 4908 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm); 4909 t = Bits32 (opcode, 15, 12); 4910 n = Bits32 (opcode, 19, 16); 4911 m = Bits32 (opcode, 3, 0); 4912 if (n == 15) 4913 return false; 4914 4915 // index = TRUE; add = TRUE; wback = FALSE; 4916 index = true; 4917 add = true; 4918 wback = false; 4919 4920 // (shift_t, shift_n) = (SRType_LSL, UInt(imm2)); 4921 shift_t = SRType_LSL; 4922 shift_n = Bits32 (opcode, 5, 4); 4923 4924 // if BadReg(t) || BadReg(m) then UNPREDICTABLE; 4925 if (BadReg (t) || BadReg (m)) 4926 return false; 4927 4928 break; 4929 4930 case eEncodingA1: 4931 // if P == '0' && W == '1' then SEE STRHT; 4932 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm); 4933 t = Bits32 (opcode, 15, 12); 4934 n = Bits32 (opcode, 19, 16); 4935 m = Bits32 (opcode, 3, 0); 4936 4937 // index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1'); 4938 index = BitIsSet (opcode, 24); 4939 add = BitIsSet (opcode, 23); 4940 wback = (BitIsClear (opcode, 24) || BitIsSet (opcode, 21)); 4941 4942 // (shift_t, shift_n) = (SRType_LSL, 0); 4943 shift_t = SRType_LSL; 4944 shift_n = 0; 4945 4946 // if t == 15 || m == 15 then UNPREDICTABLE; 4947 if ((t == 15) || (m == 15)) 4948 return false; 4949 4950 // if wback && (n == 15 || n == t) then UNPREDICTABLE; 4951 if (wback && ((n == 15) || (n == t))) 4952 return false; 4953 4954 break; 4955 4956 default: 4957 return false; 4958 } 4959 4960 uint32_t Rm = ReadCoreReg (m, &success); 4961 if (!success) 4962 return false; 4963 4964 uint32_t Rn = ReadCoreReg (n, &success); 4965 if (!success) 4966 return false; 4967 4968 // offset = Shift(R[m], shift_t, shift_n, APSR.C); 4969 uint32_t offset = Shift (Rm, shift_t, shift_n, APSR_C); 4970 4971 // offset_addr = if add then (R[n] + offset) else (R[n] - offset); 4972 addr_t offset_addr; 4973 if (add) 4974 offset_addr = Rn + offset; 4975 else 4976 offset_addr = Rn - offset; 4977 4978 // address = if index then offset_addr else R[n]; 4979 addr_t address; 4980 if (index) 4981 address = offset_addr; 4982 else 4983 address = Rn; 4984 4985 EmulateInstruction::Context context; 4986 context.type = eContextRegisterStore; 4987 Register base_reg; 4988 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n); 4989 Register offset_reg; 4990 offset_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + m); 4991 4992 // if UnalignedSupport() || address<0> == '0' then 4993 if (UnalignedSupport() || BitIsClear (address, 0)) 4994 { 4995 // MemU[address,2] = R[t]<15:0>; 4996 uint32_t Rt = ReadCoreReg (t, &success); 4997 if (!success) 4998 return false; 4999 5000 EmulateInstruction::Context context; 5001 context.type = eContextRegisterStore; 5002 Register base_reg; 5003 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n); 5004 Register offset_reg; 5005 offset_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + m); 5006 Register data_reg; 5007 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + t); 5008 context.SetRegisterToRegisterPlusIndirectOffset (base_reg, offset_reg, data_reg); 5009 5010 if (!MemUWrite (context, address, Bits32 (Rt, 15, 0), 2)) 5011 return false; 5012 } 5013 else // Can only occur before ARMv7 5014 { 5015 // MemU[address,2] = bits(16) UNKNOWN; 5016 } 5017 5018 // if wback then R[n] = offset_addr; 5019 if (wback) 5020 { 5021 context.type = eContextAdjustBaseRegister; 5022 context.SetAddress (offset_addr); 5023 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr)) 5024 return false; 5025 } 5026 } 5027 5028 return true; 5029} 5030 5031// Add with Carry (immediate) adds an immediate value and the carry flag value to a register value, 5032// and writes the result to the destination register. It can optionally update the condition flags 5033// based on the result. 5034bool 5035EmulateInstructionARM::EmulateADCImm (const uint32_t opcode, const ARMEncoding encoding) 5036{ 5037#if 0 5038 // ARM pseudo code... 5039 if ConditionPassed() then 5040 EncodingSpecificOperations(); 5041 (result, carry, overflow) = AddWithCarry(R[n], imm32, APSR.C); 5042 if d == 15 then // Can only occur for ARM encoding 5043 ALUWritePC(result); // setflags is always FALSE here 5044 else 5045 R[d] = result; 5046 if setflags then 5047 APSR.N = result<31>; 5048 APSR.Z = IsZeroBit(result); 5049 APSR.C = carry; 5050 APSR.V = overflow; 5051#endif 5052 5053 bool success = false; 5054 5055 if (ConditionPassed(opcode)) 5056 { 5057 uint32_t Rd, Rn; 5058 uint32_t imm32; // the immediate value to be added to the value obtained from Rn 5059 bool setflags; 5060 switch (encoding) 5061 { 5062 case eEncodingT1: 5063 Rd = Bits32(opcode, 11, 8); 5064 Rn = Bits32(opcode, 19, 16); 5065 setflags = BitIsSet(opcode, 20); 5066 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8) 5067 if (BadReg(Rd) || BadReg(Rn)) 5068 return false; 5069 break; 5070 case eEncodingA1: 5071 Rd = Bits32(opcode, 15, 12); 5072 Rn = Bits32(opcode, 19, 16); 5073 setflags = BitIsSet(opcode, 20); 5074 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12) 5075 // TODO: Emulate SUBS PC, LR and related instructions. 5076 if (Rd == 15 && setflags) 5077 return false; 5078 break; 5079 default: 5080 return false; 5081 } 5082 5083 // Read the first operand. 5084 int32_t val1 = ReadCoreReg(Rn, &success); 5085 if (!success) 5086 return false; 5087 5088 AddWithCarryResult res = AddWithCarry(val1, imm32, APSR_C); 5089 5090 EmulateInstruction::Context context; 5091 context.type = EmulateInstruction::eContextImmediate; 5092 context.SetNoArgs (); 5093 5094 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow)) 5095 return false; 5096 } 5097 return true; 5098} 5099 5100// Add with Carry (register) adds a register value, the carry flag value, and an optionally-shifted 5101// register value, and writes the result to the destination register. It can optionally update the 5102// condition flags based on the result. 5103bool 5104EmulateInstructionARM::EmulateADCReg (const uint32_t opcode, const ARMEncoding encoding) 5105{ 5106#if 0 5107 // ARM pseudo code... 5108 if ConditionPassed() then 5109 EncodingSpecificOperations(); 5110 shifted = Shift(R[m], shift_t, shift_n, APSR.C); 5111 (result, carry, overflow) = AddWithCarry(R[n], shifted, APSR.C); 5112 if d == 15 then // Can only occur for ARM encoding 5113 ALUWritePC(result); // setflags is always FALSE here 5114 else 5115 R[d] = result; 5116 if setflags then 5117 APSR.N = result<31>; 5118 APSR.Z = IsZeroBit(result); 5119 APSR.C = carry; 5120 APSR.V = overflow; 5121#endif 5122 5123 bool success = false; 5124 5125 if (ConditionPassed(opcode)) 5126 { 5127 uint32_t Rd, Rn, Rm; 5128 ARM_ShifterType shift_t; 5129 uint32_t shift_n; // the shift applied to the value read from Rm 5130 bool setflags; 5131 switch (encoding) 5132 { 5133 case eEncodingT1: 5134 Rd = Rn = Bits32(opcode, 2, 0); 5135 Rm = Bits32(opcode, 5, 3); 5136 setflags = !InITBlock(); 5137 shift_t = SRType_LSL; 5138 shift_n = 0; 5139 break; 5140 case eEncodingT2: 5141 Rd = Bits32(opcode, 11, 8); 5142 Rn = Bits32(opcode, 19, 16); 5143 Rm = Bits32(opcode, 3, 0); 5144 setflags = BitIsSet(opcode, 20); 5145 shift_n = DecodeImmShiftThumb(opcode, shift_t); 5146 if (BadReg(Rd) || BadReg(Rn) || BadReg(Rm)) 5147 return false; 5148 break; 5149 case eEncodingA1: 5150 Rd = Bits32(opcode, 15, 12); 5151 Rn = Bits32(opcode, 19, 16); 5152 Rm = Bits32(opcode, 3, 0); 5153 setflags = BitIsSet(opcode, 20); 5154 shift_n = DecodeImmShiftARM(opcode, shift_t); 5155 // TODO: Emulate SUBS PC, LR and related instructions. 5156 if (Rd == 15 && setflags) 5157 return false; 5158 break; 5159 default: 5160 return false; 5161 } 5162 5163 // Read the first operand. 5164 int32_t val1 = ReadCoreReg(Rn, &success); 5165 if (!success) 5166 return false; 5167 5168 // Read the second operand. 5169 int32_t val2 = ReadCoreReg(Rm, &success); 5170 if (!success) 5171 return false; 5172 5173 uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C); 5174 AddWithCarryResult res = AddWithCarry(val1, shifted, APSR_C); 5175 5176 EmulateInstruction::Context context; 5177 context.type = EmulateInstruction::eContextImmediate; 5178 context.SetNoArgs (); 5179 5180 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow)) 5181 return false; 5182 } 5183 return true; 5184} 5185 5186// This instruction adds an immediate value to the PC value to form a PC-relative address, 5187// and writes the result to the destination register. 5188bool 5189EmulateInstructionARM::EmulateADR (const uint32_t opcode, const ARMEncoding encoding) 5190{ 5191#if 0 5192 // ARM pseudo code... 5193 if ConditionPassed() then 5194 EncodingSpecificOperations(); 5195 result = if add then (Align(PC,4) + imm32) else (Align(PC,4) - imm32); 5196 if d == 15 then // Can only occur for ARM encodings 5197 ALUWritePC(result); 5198 else 5199 R[d] = result; 5200#endif 5201 5202 bool success = false; 5203 5204 if (ConditionPassed(opcode)) 5205 { 5206 uint32_t Rd; 5207 uint32_t imm32; // the immediate value to be added/subtracted to/from the PC 5208 bool add; 5209 switch (encoding) 5210 { 5211 case eEncodingT1: 5212 Rd = Bits32(opcode, 10, 8); 5213 imm32 = ThumbImm8Scaled(opcode); // imm32 = ZeroExtend(imm8:'00', 32) 5214 break; 5215 case eEncodingT2: 5216 case eEncodingT3: 5217 Rd = Bits32(opcode, 11, 8); 5218 imm32 = ThumbImm12(opcode); // imm32 = ZeroExtend(i:imm3:imm8, 32) 5219 add = (Bits32(opcode, 24, 21) == 0); // 0b0000 => ADD; 0b0101 => SUB 5220 if (BadReg(Rd)) 5221 return false; 5222 break; 5223 case eEncodingA1: 5224 case eEncodingA2: 5225 Rd = Bits32(opcode, 15, 12); 5226 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12) 5227 add = (Bits32(opcode, 24, 21) == 0x4); // 0b0100 => ADD; 0b0010 => SUB 5228 break; 5229 default: 5230 return false; 5231 } 5232 5233 // Read the PC value. 5234 uint32_t pc = ReadCoreReg(PC_REG, &success); 5235 if (!success) 5236 return false; 5237 5238 uint32_t result = (add ? Align(pc, 4) + imm32 : Align(pc, 4) - imm32); 5239 5240 EmulateInstruction::Context context; 5241 context.type = EmulateInstruction::eContextImmediate; 5242 context.SetNoArgs (); 5243 5244 if (!WriteCoreReg(context, result, Rd)) 5245 return false; 5246 } 5247 return true; 5248} 5249 5250// This instruction performs a bitwise AND of a register value and an immediate value, and writes the result 5251// to the destination register. It can optionally update the condition flags based on the result. 5252bool 5253EmulateInstructionARM::EmulateANDImm (const uint32_t opcode, const ARMEncoding encoding) 5254{ 5255#if 0 5256 // ARM pseudo code... 5257 if ConditionPassed() then 5258 EncodingSpecificOperations(); 5259 result = R[n] AND imm32; 5260 if d == 15 then // Can only occur for ARM encoding 5261 ALUWritePC(result); // setflags is always FALSE here 5262 else 5263 R[d] = result; 5264 if setflags then 5265 APSR.N = result<31>; 5266 APSR.Z = IsZeroBit(result); 5267 APSR.C = carry; 5268 // APSR.V unchanged 5269#endif 5270 5271 bool success = false; 5272 5273 if (ConditionPassed(opcode)) 5274 { 5275 uint32_t Rd, Rn; 5276 uint32_t imm32; // the immediate value to be ANDed to the value obtained from Rn 5277 bool setflags; 5278 uint32_t carry; // the carry bit after ARM/Thumb Expand operation 5279 switch (encoding) 5280 { 5281 case eEncodingT1: 5282 Rd = Bits32(opcode, 11, 8); 5283 Rn = Bits32(opcode, 19, 16); 5284 setflags = BitIsSet(opcode, 20); 5285 imm32 = ThumbExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C) 5286 // if Rd == '1111' && S == '1' then SEE TST (immediate); 5287 if (Rd == 15 && setflags) 5288 return EmulateTSTImm(opcode, eEncodingT1); 5289 if (Rd == 13 || (Rd == 15 && !setflags) || BadReg(Rn)) 5290 return false; 5291 break; 5292 case eEncodingA1: 5293 Rd = Bits32(opcode, 15, 12); 5294 Rn = Bits32(opcode, 19, 16); 5295 setflags = BitIsSet(opcode, 20); 5296 imm32 = ARMExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ARMExpandImm(imm12, APSR.C) 5297 // TODO: Emulate SUBS PC, LR and related instructions. 5298 if (Rd == 15 && setflags) 5299 return false; 5300 break; 5301 default: 5302 return false; 5303 } 5304 5305 // Read the first operand. 5306 uint32_t val1 = ReadCoreReg(Rn, &success); 5307 if (!success) 5308 return false; 5309 5310 uint32_t result = val1 & imm32; 5311 5312 EmulateInstruction::Context context; 5313 context.type = EmulateInstruction::eContextImmediate; 5314 context.SetNoArgs (); 5315 5316 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry)) 5317 return false; 5318 } 5319 return true; 5320} 5321 5322// This instruction performs a bitwise AND of a register value and an optionally-shifted register value, 5323// and writes the result to the destination register. It can optionally update the condition flags 5324// based on the result. 5325bool 5326EmulateInstructionARM::EmulateANDReg (const uint32_t opcode, const ARMEncoding encoding) 5327{ 5328#if 0 5329 // ARM pseudo code... 5330 if ConditionPassed() then 5331 EncodingSpecificOperations(); 5332 (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C); 5333 result = R[n] AND shifted; 5334 if d == 15 then // Can only occur for ARM encoding 5335 ALUWritePC(result); // setflags is always FALSE here 5336 else 5337 R[d] = result; 5338 if setflags then 5339 APSR.N = result<31>; 5340 APSR.Z = IsZeroBit(result); 5341 APSR.C = carry; 5342 // APSR.V unchanged 5343#endif 5344 5345 bool success = false; 5346 5347 if (ConditionPassed(opcode)) 5348 { 5349 uint32_t Rd, Rn, Rm; 5350 ARM_ShifterType shift_t; 5351 uint32_t shift_n; // the shift applied to the value read from Rm 5352 bool setflags; 5353 uint32_t carry; 5354 switch (encoding) 5355 { 5356 case eEncodingT1: 5357 Rd = Rn = Bits32(opcode, 2, 0); 5358 Rm = Bits32(opcode, 5, 3); 5359 setflags = !InITBlock(); 5360 shift_t = SRType_LSL; 5361 shift_n = 0; 5362 break; 5363 case eEncodingT2: 5364 Rd = Bits32(opcode, 11, 8); 5365 Rn = Bits32(opcode, 19, 16); 5366 Rm = Bits32(opcode, 3, 0); 5367 setflags = BitIsSet(opcode, 20); 5368 shift_n = DecodeImmShiftThumb(opcode, shift_t); 5369 // if Rd == '1111' && S == '1' then SEE TST (register); 5370 if (Rd == 15 && setflags) 5371 return EmulateTSTReg(opcode, eEncodingT2); 5372 if (Rd == 13 || (Rd == 15 && !setflags) || BadReg(Rn) || BadReg(Rm)) 5373 return false; 5374 break; 5375 case eEncodingA1: 5376 Rd = Bits32(opcode, 15, 12); 5377 Rn = Bits32(opcode, 19, 16); 5378 Rm = Bits32(opcode, 3, 0); 5379 setflags = BitIsSet(opcode, 20); 5380 shift_n = DecodeImmShiftARM(opcode, shift_t); 5381 // TODO: Emulate SUBS PC, LR and related instructions. 5382 if (Rd == 15 && setflags) 5383 return false; 5384 break; 5385 default: 5386 return false; 5387 } 5388 5389 // Read the first operand. 5390 uint32_t val1 = ReadCoreReg(Rn, &success); 5391 if (!success) 5392 return false; 5393 5394 // Read the second operand. 5395 uint32_t val2 = ReadCoreReg(Rm, &success); 5396 if (!success) 5397 return false; 5398 5399 uint32_t shifted = Shift_C(val2, shift_t, shift_n, APSR_C, carry); 5400 uint32_t result = val1 & shifted; 5401 5402 EmulateInstruction::Context context; 5403 context.type = EmulateInstruction::eContextImmediate; 5404 context.SetNoArgs (); 5405 5406 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry)) 5407 return false; 5408 } 5409 return true; 5410} 5411 5412// Bitwise Bit Clear (immediate) performs a bitwise AND of a register value and the complement of an 5413// immediate value, and writes the result to the destination register. It can optionally update the 5414// condition flags based on the result. 5415bool 5416EmulateInstructionARM::EmulateBICImm (const uint32_t opcode, const ARMEncoding encoding) 5417{ 5418#if 0 5419 // ARM pseudo code... 5420 if ConditionPassed() then 5421 EncodingSpecificOperations(); 5422 result = R[n] AND NOT(imm32); 5423 if d == 15 then // Can only occur for ARM encoding 5424 ALUWritePC(result); // setflags is always FALSE here 5425 else 5426 R[d] = result; 5427 if setflags then 5428 APSR.N = result<31>; 5429 APSR.Z = IsZeroBit(result); 5430 APSR.C = carry; 5431 // APSR.V unchanged 5432#endif 5433 5434 bool success = false; 5435 5436 if (ConditionPassed(opcode)) 5437 { 5438 uint32_t Rd, Rn; 5439 uint32_t imm32; // the immediate value to be bitwise inverted and ANDed to the value obtained from Rn 5440 bool setflags; 5441 uint32_t carry; // the carry bit after ARM/Thumb Expand operation 5442 switch (encoding) 5443 { 5444 case eEncodingT1: 5445 Rd = Bits32(opcode, 11, 8); 5446 Rn = Bits32(opcode, 19, 16); 5447 setflags = BitIsSet(opcode, 20); 5448 imm32 = ThumbExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C) 5449 if (BadReg(Rd) || BadReg(Rn)) 5450 return false; 5451 break; 5452 case eEncodingA1: 5453 Rd = Bits32(opcode, 15, 12); 5454 Rn = Bits32(opcode, 19, 16); 5455 setflags = BitIsSet(opcode, 20); 5456 imm32 = ARMExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ARMExpandImm(imm12, APSR.C) 5457 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions; 5458 // TODO: Emulate SUBS PC, LR and related instructions. 5459 if (Rd == 15 && setflags) 5460 return false; 5461 break; 5462 default: 5463 return false; 5464 } 5465 5466 // Read the first operand. 5467 uint32_t val1 = ReadCoreReg(Rn, &success); 5468 if (!success) 5469 return false; 5470 5471 uint32_t result = val1 & ~imm32; 5472 5473 EmulateInstruction::Context context; 5474 context.type = EmulateInstruction::eContextImmediate; 5475 context.SetNoArgs (); 5476 5477 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry)) 5478 return false; 5479 } 5480 return true; 5481} 5482 5483// Bitwise Bit Clear (register) performs a bitwise AND of a register value and the complement of an 5484// optionally-shifted register value, and writes the result to the destination register. 5485// It can optionally update the condition flags based on the result. 5486bool 5487EmulateInstructionARM::EmulateBICReg (const uint32_t opcode, const ARMEncoding encoding) 5488{ 5489#if 0 5490 // ARM pseudo code... 5491 if ConditionPassed() then 5492 EncodingSpecificOperations(); 5493 (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C); 5494 result = R[n] AND NOT(shifted); 5495 if d == 15 then // Can only occur for ARM encoding 5496 ALUWritePC(result); // setflags is always FALSE here 5497 else 5498 R[d] = result; 5499 if setflags then 5500 APSR.N = result<31>; 5501 APSR.Z = IsZeroBit(result); 5502 APSR.C = carry; 5503 // APSR.V unchanged 5504#endif 5505 5506 bool success = false; 5507 5508 if (ConditionPassed(opcode)) 5509 { 5510 uint32_t Rd, Rn, Rm; 5511 ARM_ShifterType shift_t; 5512 uint32_t shift_n; // the shift applied to the value read from Rm 5513 bool setflags; 5514 uint32_t carry; 5515 switch (encoding) 5516 { 5517 case eEncodingT1: 5518 Rd = Rn = Bits32(opcode, 2, 0); 5519 Rm = Bits32(opcode, 5, 3); 5520 setflags = !InITBlock(); 5521 shift_t = SRType_LSL; 5522 shift_n = 0; 5523 break; 5524 case eEncodingT2: 5525 Rd = Bits32(opcode, 11, 8); 5526 Rn = Bits32(opcode, 19, 16); 5527 Rm = Bits32(opcode, 3, 0); 5528 setflags = BitIsSet(opcode, 20); 5529 shift_n = DecodeImmShiftThumb(opcode, shift_t); 5530 if (BadReg(Rd) || BadReg(Rn) || BadReg(Rm)) 5531 return false; 5532 break; 5533 case eEncodingA1: 5534 Rd = Bits32(opcode, 15, 12); 5535 Rn = Bits32(opcode, 19, 16); 5536 Rm = Bits32(opcode, 3, 0); 5537 setflags = BitIsSet(opcode, 20); 5538 shift_n = DecodeImmShiftARM(opcode, shift_t); 5539 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions; 5540 // TODO: Emulate SUBS PC, LR and related instructions. 5541 if (Rd == 15 && setflags) 5542 return false; 5543 break; 5544 default: 5545 return false; 5546 } 5547 5548 // Read the first operand. 5549 uint32_t val1 = ReadCoreReg(Rn, &success); 5550 if (!success) 5551 return false; 5552 5553 // Read the second operand. 5554 uint32_t val2 = ReadCoreReg(Rm, &success); 5555 if (!success) 5556 return false; 5557 5558 uint32_t shifted = Shift_C(val2, shift_t, shift_n, APSR_C, carry); 5559 uint32_t result = val1 & ~shifted; 5560 5561 EmulateInstruction::Context context; 5562 context.type = EmulateInstruction::eContextImmediate; 5563 context.SetNoArgs (); 5564 5565 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry)) 5566 return false; 5567 } 5568 return true; 5569} 5570 5571// LDR (immediate, ARM) calculates an address from a base register value and an immediate offset, loads a word 5572// from memory, and writes it to a register. It can use offset, post-indexed, or pre-indexed addressing. 5573bool 5574EmulateInstructionARM::EmulateLDRImmediateARM (const uint32_t opcode, const ARMEncoding encoding) 5575{ 5576#if 0 5577 if ConditionPassed() then 5578 EncodingSpecificOperations(); 5579 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32); 5580 address = if index then offset_addr else R[n]; 5581 data = MemU[address,4]; 5582 if wback then R[n] = offset_addr; 5583 if t == 15 then 5584 if address<1:0> == '00' then LoadWritePC(data); else UNPREDICTABLE; 5585 elsif UnalignedSupport() || address<1:0> = '00' then 5586 R[t] = data; 5587 else // Can only apply before ARMv7 5588 R[t] = ROR(data, 8*UInt(address<1:0>)); 5589#endif 5590 5591 bool success = false; 5592 5593 if (ConditionPassed(opcode)) 5594 { 5595 const uint32_t addr_byte_size = GetAddressByteSize(); 5596 5597 uint32_t t; 5598 uint32_t n; 5599 uint32_t imm32; 5600 bool index; 5601 bool add; 5602 bool wback; 5603 5604 switch (encoding) 5605 { 5606 case eEncodingA1: 5607 // if Rn == '1111' then SEE LDR (literal); 5608 // if P == '0' && W == '1' then SEE LDRT; 5609 // if Rn == '1101' && P == '0' && U == '1' && W == '0' && imm12 == '000000000100' then SEE POP; 5610 // t == UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32); 5611 t = Bits32 (opcode, 15, 12); 5612 n = Bits32 (opcode, 19, 16); 5613 imm32 = Bits32 (opcode, 11, 0); 5614 5615 // index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1'); 5616 index = BitIsSet (opcode, 24); 5617 add = BitIsSet (opcode, 23); 5618 wback = (BitIsClear (opcode, 24) || BitIsSet (opcode, 21)); 5619 5620 // if wback && n == t then UNPREDICTABLE; 5621 if (wback && (n == t)) 5622 return false; 5623 5624 break; 5625 5626 default: 5627 return false; 5628 } 5629 5630 addr_t address; 5631 addr_t offset_addr; 5632 addr_t base_address = ReadCoreReg (n, &success); 5633 if (!success) 5634 return false; 5635 5636 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32); 5637 if (add) 5638 offset_addr = base_address + imm32; 5639 else 5640 offset_addr = base_address - imm32; 5641 5642 // address = if index then offset_addr else R[n]; 5643 if (index) 5644 address = offset_addr; 5645 else 5646 address = base_address; 5647 5648 // data = MemU[address,4]; 5649 5650 Register base_reg; 5651 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n); 5652 5653 EmulateInstruction::Context context; 5654 context.type = eContextRegisterLoad; 5655 context.SetRegisterPlusOffset (base_reg, address - base_address); 5656 5657 uint64_t data = MemURead (context, address, addr_byte_size, 0, &success); 5658 if (!success) 5659 return false; 5660 5661 // if wback then R[n] = offset_addr; 5662 if (wback) 5663 { 5664 context.type = eContextAdjustBaseRegister; 5665 context.SetAddress (offset_addr); 5666 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr)) 5667 return false; 5668 } 5669 5670 // if t == 15 then 5671 if (t == 15) 5672 { 5673 // if address<1:0> == '00' then LoadWritePC(data); else UNPREDICTABLE; 5674 if (BitIsClear (address, 1) && BitIsClear (address, 0)) 5675 { 5676 // LoadWritePC (data); 5677 context.type = eContextRegisterLoad; 5678 context.SetRegisterPlusOffset (base_reg, address - base_address); 5679 LoadWritePC (context, data); 5680 } 5681 else 5682 return false; 5683 } 5684 // elsif UnalignedSupport() || address<1:0> = '00' then 5685 else if (UnalignedSupport() || (BitIsClear (address, 1) && BitIsClear (address, 0))) 5686 { 5687 // R[t] = data; 5688 context.type = eContextRegisterLoad; 5689 context.SetRegisterPlusOffset (base_reg, address - base_address); 5690 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data)) 5691 return false; 5692 } 5693 // else // Can only apply before ARMv7 5694 else 5695 { 5696 // R[t] = ROR(data, 8*UInt(address<1:0>)); 5697 data = ROR (data, Bits32 (address, 1, 0)); 5698 context.type = eContextRegisterLoad; 5699 context.SetImmediate (data); 5700 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data)) 5701 return false; 5702 } 5703 5704 } 5705 return true; 5706} 5707 5708// LDR (register) calculates an address from a base register value and an offset register value, loads a word 5709// from memory, and writes it to a resgister. The offset register value can optionally be shifted. 5710bool 5711EmulateInstructionARM::EmulateLDRRegister (const uint32_t opcode, const ARMEncoding encoding) 5712{ 5713#if 0 5714 if ConditionPassed() then 5715 EncodingSpecificOperations(); NullCheckIfThumbEE(n); 5716 offset = Shift(R[m], shift_t, shift_n, APSR.C); 5717 offset_addr = if add then (R[n] + offset) else (R[n] - offset); 5718 address = if index then offset_addr else R[n]; 5719 data = MemU[address,4]; 5720 if wback then R[n] = offset_addr; 5721 if t == 15 then 5722 if address<1:0> == '00' then LoadWritePC(data); else UNPREDICTABLE; 5723 elsif UnalignedSupport() || address<1:0> = '00' then 5724 R[t] = data; 5725 else // Can only apply before ARMv7 5726 if CurrentInstrSet() == InstrSet_ARM then 5727 R[t] = ROR(data, 8*UInt(address<1:0>)); 5728 else 5729 R[t] = bits(32) UNKNOWN; 5730#endif 5731 5732 bool success = false; 5733 5734 if (ConditionPassed(opcode)) 5735 { 5736 const uint32_t addr_byte_size = GetAddressByteSize(); 5737 5738 uint32_t t; 5739 uint32_t n; 5740 uint32_t m; 5741 bool index; 5742 bool add; 5743 bool wback; 5744 ARM_ShifterType shift_t; 5745 uint32_t shift_n; 5746 5747 switch (encoding) 5748 { 5749 case eEncodingT1: 5750 // if CurrentInstrSet() == InstrSet_ThumbEE then SEE "Modified operation in ThumbEE"; 5751 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm); 5752 t = Bits32 (opcode, 2, 0); 5753 n = Bits32 (opcode, 5, 3); 5754 m = Bits32 (opcode, 8, 6); 5755 5756 // index = TRUE; add = TRUE; wback = FALSE; 5757 index = true; 5758 add = true; 5759 wback = false; 5760 5761 // (shift_t, shift_n) = (SRType_LSL, 0); 5762 shift_t = SRType_LSL; 5763 shift_n = 0; 5764 5765 break; 5766 5767 case eEncodingT2: 5768 // if Rn == '1111' then SEE LDR (literal); 5769 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm); 5770 t = Bits32 (opcode, 15, 12); 5771 n = Bits32 (opcode, 19, 16); 5772 m = Bits32 (opcode, 3, 0); 5773 5774 // index = TRUE; add = TRUE; wback = FALSE; 5775 index = true; 5776 add = true; 5777 wback = false; 5778 5779 // (shift_t, shift_n) = (SRType_LSL, UInt(imm2)); 5780 shift_t = SRType_LSL; 5781 shift_n = Bits32 (opcode, 5, 4); 5782 5783 // if BadReg(m) then UNPREDICTABLE; 5784 if (BadReg (m)) 5785 return false; 5786 5787 // if t == 15 && InITBlock() && !LastInITBlock() then UNPREDICTABLE; 5788 if ((t == 15) && InITBlock() && !LastInITBlock()) 5789 return false; 5790 5791 break; 5792 5793 case eEncodingA1: 5794 { 5795 // if P == '0' && W == '1' then SEE LDRT; 5796 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm); 5797 t = Bits32 (opcode, 15, 12); 5798 n = Bits32 (opcode, 19, 16); 5799 m = Bits32 (opcode, 3, 0); 5800 5801 // index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1'); 5802 index = BitIsSet (opcode, 24); 5803 add = BitIsSet (opcode, 23); 5804 wback = (BitIsClear (opcode, 24) || BitIsSet (opcode, 21)); 5805 5806 // (shift_t, shift_n) = DecodeImmShift(type, imm5); 5807 uint32_t type = Bits32 (opcode, 6, 5); 5808 uint32_t imm5 = Bits32 (opcode, 11, 7); 5809 shift_n = DecodeImmShift (type, imm5, shift_t); 5810 5811 // if m == 15 then UNPREDICTABLE; 5812 if (m == 15) 5813 return false; 5814 5815 // if wback && (n == 15 || n == t) then UNPREDICTABLE; 5816 if (wback && ((n == 15) || (n == t))) 5817 return false; 5818 } 5819 break; 5820 5821 5822 default: 5823 return false; 5824 } 5825 5826 uint32_t Rm = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success); 5827 if (!success) 5828 return false; 5829 5830 uint32_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success); 5831 if (!success) 5832 return false; 5833 5834 addr_t offset_addr; 5835 addr_t address; 5836 5837 // offset = Shift(R[m], shift_t, shift_n, APSR.C); -- Note "The APSR is an application level alias for the CPSR". 5838 addr_t offset = Shift (Rm, shift_t, shift_n, Bit32 (m_opcode_cpsr, APSR_C)); 5839 5840 // offset_addr = if add then (R[n] + offset) else (R[n] - offset); 5841 if (add) 5842 offset_addr = Rn + offset; 5843 else 5844 offset_addr = Rn - offset; 5845 5846 // address = if index then offset_addr else R[n]; 5847 if (index) 5848 address = offset_addr; 5849 else 5850 address = Rn; 5851 5852 // data = MemU[address,4]; 5853 Register base_reg; 5854 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n); 5855 5856 EmulateInstruction::Context context; 5857 context.type = eContextRegisterLoad; 5858 context.SetRegisterPlusOffset (base_reg, address - Rn); 5859 5860 uint64_t data = MemURead (context, address, addr_byte_size, 0, &success); 5861 if (!success) 5862 return false; 5863 5864 // if wback then R[n] = offset_addr; 5865 if (wback) 5866 { 5867 context.type = eContextAdjustBaseRegister; 5868 context.SetAddress (offset_addr); 5869 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr)) 5870 return false; 5871 } 5872 5873 // if t == 15 then 5874 if (t == 15) 5875 { 5876 // if address<1:0> == '00' then LoadWritePC(data); else UNPREDICTABLE; 5877 if (BitIsClear (address, 1) && BitIsClear (address, 0)) 5878 { 5879 context.type = eContextRegisterLoad; 5880 context.SetRegisterPlusOffset (base_reg, address - Rn); 5881 LoadWritePC (context, data); 5882 } 5883 else 5884 return false; 5885 } 5886 // elsif UnalignedSupport() || address<1:0> = '00' then 5887 else if (UnalignedSupport () || (BitIsClear (address, 1) && BitIsClear (address, 0))) 5888 { 5889 // R[t] = data; 5890 context.type = eContextRegisterLoad; 5891 context.SetRegisterPlusOffset (base_reg, address - Rn); 5892 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data)) 5893 return false; 5894 } 5895 else // Can only apply before ARMv7 5896 { 5897 // if CurrentInstrSet() == InstrSet_ARM then 5898 if (CurrentInstrSet () == eModeARM) 5899 { 5900 // R[t] = ROR(data, 8*UInt(address<1:0>)); 5901 data = ROR (data, Bits32 (address, 1, 0)); 5902 context.type = eContextRegisterLoad; 5903 context.SetImmediate (data); 5904 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data)) 5905 return false; 5906 } 5907 else 5908 { 5909 // R[t] = bits(32) UNKNOWN; 5910 WriteBits32Unknown (t); 5911 } 5912 } 5913 } 5914 return true; 5915} 5916 5917// LDRB (immediate, Thumb) 5918bool 5919EmulateInstructionARM::EmulateLDRBImmediate (const uint32_t opcode, const ARMEncoding encoding) 5920{ 5921#if 0 5922 if ConditionPassed() then 5923 EncodingSpecificOperations(); NullCheckIfThumbEE(n); 5924 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32); 5925 address = if index then offset_addr else R[n]; 5926 R[t] = ZeroExtend(MemU[address,1], 32); 5927 if wback then R[n] = offset_addr; 5928#endif 5929 5930 bool success = false; 5931 5932 if (ConditionPassed(opcode)) 5933 { 5934 uint32_t t; 5935 uint32_t n; 5936 uint32_t imm32; 5937 bool index; 5938 bool add; 5939 bool wback; 5940 5941 // EncodingSpecificOperations(); NullCheckIfThumbEE(n); 5942 switch (encoding) 5943 { 5944 case eEncodingT1: 5945 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm5, 32); 5946 t = Bits32 (opcode, 2, 0); 5947 n = Bits32 (opcode, 5, 3); 5948 imm32 = Bits32 (opcode, 10, 6); 5949 5950 // index = TRUE; add = TRUE; wback = FALSE; 5951 index = true; 5952 add = true; 5953 wback= false; 5954 5955 break; 5956 5957 case eEncodingT2: 5958 // if Rt == '1111' then SEE PLD; 5959 // if Rn == '1111' then SEE LDRB (literal); 5960 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32); 5961 t = Bits32 (opcode, 15, 12); 5962 n = Bits32 (opcode, 19, 16); 5963 imm32 = Bits32 (opcode, 11, 0); 5964 5965 // index = TRUE; add = TRUE; wback = FALSE; 5966 index = true; 5967 add = true; 5968 wback = false; 5969 5970 // if t == 13 then UNPREDICTABLE; 5971 if (t == 13) 5972 return false; 5973 5974 break; 5975 5976 case eEncodingT3: 5977 // if Rt == '1111' && P == '1' && U == '0' && W == '0' then SEE PLD; 5978 // if Rn == '1111' then SEE LDRB (literal); 5979 // if P == '1' && U == '1' && W == '0' then SEE LDRBT; 5980 // if P == '0' && W == '0' then UNDEFINED; 5981 if (BitIsClear (opcode, 10) && BitIsClear (opcode, 8)) 5982 return false; 5983 5984 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32); 5985 t = Bits32 (opcode, 15, 12); 5986 n = Bits32 (opcode, 19, 16); 5987 imm32 = Bits32 (opcode, 7, 0); 5988 5989 // index = (P == '1'); add = (U == '1'); wback = (W == '1'); 5990 index = BitIsSet (opcode, 10); 5991 add = BitIsSet (opcode, 9); 5992 wback = BitIsSet (opcode, 8); 5993 5994 // if BadReg(t) || (wback && n == t) then UNPREDICTABLE; 5995 if (BadReg (t) || (wback && (n == t))) 5996 return false; 5997 5998 break; 5999 6000 default: 6001 return false; 6002 } 6003 6004 uint32_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success); 6005 if (!success) 6006 return false; 6007 6008 addr_t address; 6009 addr_t offset_addr; 6010 6011 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32); 6012 if (add) 6013 offset_addr = Rn + imm32; 6014 else 6015 offset_addr = Rn - imm32; 6016 6017 // address = if index then offset_addr else R[n]; 6018 if (index) 6019 address = offset_addr; 6020 else 6021 address = Rn; 6022 6023 // R[t] = ZeroExtend(MemU[address,1], 32); 6024 Register base_reg; 6025 Register data_reg; 6026 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n); 6027 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + t); 6028 6029 EmulateInstruction::Context context; 6030 context.type = eContextRegisterLoad; 6031 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, address - Rn); 6032 6033 uint64_t data = MemURead (context, address, 1, 0, &success); 6034 if (!success) 6035 return false; 6036 6037 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data)) 6038 return false; 6039 6040 // if wback then R[n] = offset_addr; 6041 if (wback) 6042 { 6043 context.type = eContextAdjustBaseRegister; 6044 context.SetAddress (offset_addr); 6045 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr)) 6046 return false; 6047 } 6048 } 6049 return true; 6050} 6051 6052// LDRB (literal) calculates an address from the PC value and an immediate offset, loads a byte from memory, 6053// zero-extends it to form a 32-bit word and writes it to a register. 6054bool 6055EmulateInstructionARM::EmulateLDRBLiteral (const uint32_t opcode, const ARMEncoding encoding) 6056{ 6057#if 0 6058 if ConditionPassed() then 6059 EncodingSpecificOperations(); NullCheckIfThumbEE(15); 6060 base = Align(PC,4); 6061 address = if add then (base + imm32) else (base - imm32); 6062 R[t] = ZeroExtend(MemU[address,1], 32); 6063#endif 6064 6065 bool success = false; 6066 6067 if (ConditionPassed(opcode)) 6068 { 6069 uint32_t t; 6070 uint32_t imm32; 6071 bool add; 6072 switch (encoding) 6073 { 6074 case eEncodingT1: 6075 // if Rt == '1111' then SEE PLD; 6076 // t = UInt(Rt); imm32 = ZeroExtend(imm12, 32); add = (U == '1'); 6077 t = Bits32 (opcode, 15, 12); 6078 imm32 = Bits32 (opcode, 11, 0); 6079 add = BitIsSet (opcode, 23); 6080 6081 // if t == 13 then UNPREDICTABLE; 6082 if (t == 13) 6083 return false; 6084 6085 break; 6086 6087 case eEncodingA1: 6088 // t == UInt(Rt); imm32 = ZeroExtend(imm12, 32); add = (U == '1'); 6089 t = Bits32 (opcode, 15, 12); 6090 imm32 = Bits32 (opcode, 11, 0); 6091 add = BitIsSet (opcode, 23); 6092 6093 // if t == 15 then UNPREDICTABLE; 6094 if (t == 15) 6095 return false; 6096 break; 6097 6098 default: 6099 return false; 6100 } 6101 6102 // base = Align(PC,4); 6103 uint32_t pc_val = ReadCoreReg (PC_REG, &success); 6104 if (!success) 6105 return false; 6106 6107 uint32_t base = AlignPC (pc_val); 6108 6109 addr_t address; 6110 // address = if add then (base + imm32) else (base - imm32); 6111 if (add) 6112 address = base + imm32; 6113 else 6114 address = base - imm32; 6115 6116 // R[t] = ZeroExtend(MemU[address,1], 32); 6117 EmulateInstruction::Context context; 6118 context.type = eContextRelativeBranchImmediate; 6119 context.SetImmediate (address - base); 6120 6121 uint64_t data = MemURead (context, address, 1, 0, &success); 6122 if (!success) 6123 return false; 6124 6125 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data)) 6126 return false; 6127 } 6128 return true; 6129} 6130 6131// LDRB (register) calculates an address from a base register value and an offset rigister value, loads a byte from 6132// memory, zero-extends it to form a 32-bit word, and writes it to a register. The offset register value can 6133// optionally be shifted. 6134bool 6135EmulateInstructionARM::EmulateLDRBRegister (const uint32_t opcode, const ARMEncoding encoding) 6136{ 6137#if 0 6138 if ConditionPassed() then 6139 EncodingSpecificOperations(); NullCheckIfThumbEE(n); 6140 offset = Shift(R[m], shift_t, shift_n, APSR.C); 6141 offset_addr = if add then (R[n] + offset) else (R[n] - offset); 6142 address = if index then offset_addr else R[n]; 6143 R[t] = ZeroExtend(MemU[address,1],32); 6144 if wback then R[n] = offset_addr; 6145#endif 6146 6147 bool success = false; 6148 6149 if (ConditionPassed(opcode)) 6150 { 6151 uint32_t t; 6152 uint32_t n; 6153 uint32_t m; 6154 bool index; 6155 bool add; 6156 bool wback; 6157 ARM_ShifterType shift_t; 6158 uint32_t shift_n; 6159 6160 // EncodingSpecificOperations(); NullCheckIfThumbEE(n); 6161 switch (encoding) 6162 { 6163 case eEncodingT1: 6164 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm); 6165 t = Bits32 (opcode, 2, 0); 6166 n = Bits32 (opcode, 5, 3); 6167 m = Bits32 (opcode, 8, 6); 6168 6169 // index = TRUE; add = TRUE; wback = FALSE; 6170 index = true; 6171 add = true; 6172 wback = false; 6173 6174 // (shift_t, shift_n) = (SRType_LSL, 0); 6175 shift_t = SRType_LSL; 6176 shift_n = 0; 6177 break; 6178 6179 case eEncodingT2: 6180 // if Rt == '1111' then SEE PLD; 6181 // if Rn == '1111' then SEE LDRB (literal); 6182 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm); 6183 t = Bits32 (opcode, 15, 12); 6184 n = Bits32 (opcode, 19, 16); 6185 m = Bits32 (opcode, 3, 0); 6186 6187 // index = TRUE; add = TRUE; wback = FALSE; 6188 index = true; 6189 add = true; 6190 wback = false; 6191 6192 // (shift_t, shift_n) = (SRType_LSL, UInt(imm2)); 6193 shift_t = SRType_LSL; 6194 shift_n = Bits32 (opcode, 5, 4); 6195 6196 // if t == 13 || BadReg(m) then UNPREDICTABLE; 6197 if ((t == 13) || BadReg (m)) 6198 return false; 6199 break; 6200 6201 case eEncodingA1: 6202 { 6203 // if P == '0' && W == '1' then SEE LDRBT; 6204 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm); 6205 t = Bits32 (opcode, 15, 12); 6206 n = Bits32 (opcode, 19, 16); 6207 m = Bits32 (opcode, 3, 0); 6208 6209 // index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1'); 6210 index = BitIsSet (opcode, 24); 6211 add = BitIsSet (opcode, 23); 6212 wback = (BitIsClear (opcode, 24) || BitIsSet (opcode, 21)); 6213 6214 // (shift_t, shift_n) = DecodeImmShift(type, imm5); 6215 uint32_t type = Bits32 (opcode, 6, 5); 6216 uint32_t imm5 = Bits32 (opcode, 11, 7); 6217 shift_n = DecodeImmShift (type, imm5, shift_t); 6218 6219 // if t == 15 || m == 15 then UNPREDICTABLE; 6220 if ((t == 15) || (m == 15)) 6221 return false; 6222 6223 // if wback && (n == 15 || n == t) then UNPREDICTABLE; 6224 if (wback && ((n == 15) || (n == t))) 6225 return false; 6226 } 6227 break; 6228 6229 default: 6230 return false; 6231 } 6232 6233 addr_t offset_addr; 6234 addr_t address; 6235 6236 // offset = Shift(R[m], shift_t, shift_n, APSR.C); 6237 uint32_t Rm = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success); 6238 if (!success) 6239 return false; 6240 6241 addr_t offset = Shift (Rm, shift_t, shift_n, APSR_C); 6242 6243 // offset_addr = if add then (R[n] + offset) else (R[n] - offset); 6244 uint32_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success); 6245 if (!success) 6246 return false; 6247 6248 if (add) 6249 offset_addr = Rn + offset; 6250 else 6251 offset_addr = Rn - offset; 6252 6253 // address = if index then offset_addr else R[n]; 6254 if (index) 6255 address = offset_addr; 6256 else 6257 address = Rn; 6258 6259 // R[t] = ZeroExtend(MemU[address,1],32); 6260 Register base_reg; 6261 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n); 6262 6263 EmulateInstruction::Context context; 6264 context.type = eContextRegisterLoad; 6265 context.SetRegisterPlusOffset (base_reg, address - Rn); 6266 6267 uint64_t data = MemURead (context, address, 1, 0, &success); 6268 if (!success) 6269 return false; 6270 6271 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data)) 6272 return false; 6273 6274 // if wback then R[n] = offset_addr; 6275 if (wback) 6276 { 6277 context.type = eContextAdjustBaseRegister; 6278 context.SetAddress (offset_addr); 6279 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr)) 6280 return false; 6281 } 6282 } 6283 return true; 6284} 6285 6286// LDRH (immediate, Thumb) calculates an address from a base register value and an immediate offset, loads a 6287// halfword from memory, zero-extends it to form a 32-bit word, and writes it to a register. It can use offset, 6288// post-indexed, or pre-indexed addressing. 6289bool 6290EmulateInstructionARM::EmulateLDRHImmediate (const uint32_t opcode, const ARMEncoding encoding) 6291{ 6292#if 0 6293 if ConditionPassed() then 6294 EncodingSpecificOperations(); NullCheckIfThumbEE(n); 6295 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32); 6296 address = if index then offset_addr else R[n]; 6297 data = MemU[address,2]; 6298 if wback then R[n] = offset_addr; 6299 if UnalignedSupport() || address<0> = '0' then 6300 R[t] = ZeroExtend(data, 32); 6301 else // Can only apply before ARMv7 6302 R[t] = bits(32) UNKNOWN; 6303#endif 6304 6305 6306 bool success = false; 6307 6308 if (ConditionPassed(opcode)) 6309 { 6310 uint32_t t; 6311 uint32_t n; 6312 uint32_t imm32; 6313 bool index; 6314 bool add; 6315 bool wback; 6316 6317 // EncodingSpecificOperations(); NullCheckIfThumbEE(n); 6318 switch (encoding) 6319 { 6320 case eEncodingT1: 6321 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm5:'0', 32); 6322 t = Bits32 (opcode, 2, 0); 6323 n = Bits32 (opcode, 5, 3); 6324 imm32 = Bits32 (opcode, 10, 6) << 1; 6325 6326 // index = TRUE; add = TRUE; wback = FALSE; 6327 index = true; 6328 add = true; 6329 wback = false; 6330 6331 break; 6332 6333 case eEncodingT2: 6334 // if Rt == '1111' then SEE "Unallocated memory hints"; 6335 // if Rn == '1111' then SEE LDRH (literal); 6336 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32); 6337 t = Bits32 (opcode, 15, 12); 6338 n = Bits32 (opcode, 19, 16); 6339 imm32 = Bits32 (opcode, 11, 0); 6340 6341 // index = TRUE; add = TRUE; wback = FALSE; 6342 index = true; 6343 add = true; 6344 wback = false; 6345 6346 // if t == 13 then UNPREDICTABLE; 6347 if (t == 13) 6348 return false; 6349 break; 6350 6351 case eEncodingT3: 6352 // if Rn == '1111' then SEE LDRH (literal); 6353 // if Rt == '1111' && P == '1' && U == '0' && W == '0' then SEE "Unallocated memory hints"; 6354 // if P == '1' && U == '1' && W == '0' then SEE LDRHT; 6355 // if P == '0' && W == '0' then UNDEFINED; 6356 if (BitIsClear (opcode, 10) && BitIsClear (opcode, 8)) 6357 return false; 6358 6359 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32); 6360 t = Bits32 (opcode, 15, 12); 6361 n = Bits32 (opcode, 19, 16); 6362 imm32 = Bits32 (opcode, 7, 0); 6363 6364 // index = (P == '1'); add = (U == '1'); wback = (W == '1'); 6365 index = BitIsSet (opcode, 10); 6366 add = BitIsSet (opcode, 9); 6367 wback = BitIsSet (opcode, 8); 6368 6369 // if BadReg(t) || (wback && n == t) then UNPREDICTABLE; 6370 if (BadReg (t) || (wback && (n == t))) 6371 return false; 6372 break; 6373 6374 default: 6375 return false; 6376 } 6377 6378 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32); 6379 uint32_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success); 6380 if (!success) 6381 return false; 6382 6383 addr_t offset_addr; 6384 addr_t address; 6385 6386 if (add) 6387 offset_addr = Rn + imm32; 6388 else 6389 offset_addr = Rn - imm32; 6390 6391 // address = if index then offset_addr else R[n]; 6392 if (index) 6393 address = offset_addr; 6394 else 6395 address = Rn; 6396 6397 // data = MemU[address,2]; 6398 Register base_reg; 6399 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n); 6400 6401 EmulateInstruction::Context context; 6402 context.type = eContextRegisterLoad; 6403 context.SetRegisterPlusOffset (base_reg, address - Rn); 6404 6405 uint64_t data = MemURead (context, address, 2, 0, &success); 6406 if (!success) 6407 return false; 6408 6409 // if wback then R[n] = offset_addr; 6410 if (wback) 6411 { 6412 context.type = eContextAdjustBaseRegister; 6413 context.SetAddress (offset_addr); 6414 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr)) 6415 return false; 6416 } 6417 6418 // if UnalignedSupport() || address<0> = '0' then 6419 if (UnalignedSupport () || BitIsClear (address, 0)) 6420 { 6421 // R[t] = ZeroExtend(data, 32); 6422 context.type = eContextRegisterLoad; 6423 context.SetRegisterPlusOffset (base_reg, address - Rn); 6424 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data)) 6425 return false; 6426 } 6427 else // Can only apply before ARMv7 6428 { 6429 // R[t] = bits(32) UNKNOWN; 6430 WriteBits32Unknown (t); 6431 } 6432 } 6433 return true; 6434} 6435 6436// LDRH (literal) caculates an address from the PC value and an immediate offset, loads a halfword from memory, 6437// zero-extends it to form a 32-bit word, and writes it to a register. 6438bool 6439EmulateInstructionARM::EmulateLDRHLiteral (const uint32_t opcode, const ARMEncoding encoding) 6440{ 6441#if 0 6442 if ConditionPassed() then 6443 EncodingSpecificOperations(); NullCheckIfThumbEE(15); 6444 base = Align(PC,4); 6445 address = if add then (base + imm32) else (base - imm32); 6446 data = MemU[address,2]; 6447 if UnalignedSupport() || address<0> = '0' then 6448 R[t] = ZeroExtend(data, 32); 6449 else // Can only apply before ARMv7 6450 R[t] = bits(32) UNKNOWN; 6451#endif 6452 6453 bool success = false; 6454 6455 if (ConditionPassed(opcode)) 6456 { 6457 uint32_t t; 6458 uint32_t imm32; 6459 bool add; 6460 6461 // EncodingSpecificOperations(); NullCheckIfThumbEE(15); 6462 switch (encoding) 6463 { 6464 case eEncodingT1: 6465 // if Rt == '1111' then SEE "Unallocated memory hints"; 6466 // t = UInt(Rt); imm32 = ZeroExtend(imm12, 32); add = (U == '1'); 6467 t = Bits32 (opcode, 15, 12); 6468 imm32 = Bits32 (opcode, 11, 0); 6469 add = BitIsSet (opcode, 23); 6470 6471 // if t == 13 then UNPREDICTABLE; 6472 if (t == 13) 6473 return false; 6474 6475 break; 6476 6477 case eEncodingA1: 6478 { 6479 uint32_t imm4H = Bits32 (opcode, 11, 8); 6480 uint32_t imm4L = Bits32 (opcode, 3, 0); 6481 6482 // t == UInt(Rt); imm32 = ZeroExtend(imm4H:imm4L, 32); add = (U == '1'); 6483 t = Bits32 (opcode, 15, 12); 6484 imm32 = (imm4H << 4) | imm4L; 6485 add = BitIsSet (opcode, 23); 6486 6487 // if t == 15 then UNPREDICTABLE; 6488 if (t == 15) 6489 return false; 6490 break; 6491 } 6492 6493 default: 6494 return false; 6495 } 6496 6497 // base = Align(PC,4); 6498 uint64_t pc_value = ReadCoreReg (PC_REG, &success); 6499 if (!success) 6500 return false; 6501 6502 addr_t base = AlignPC (pc_value); 6503 addr_t address; 6504 6505 // address = if add then (base + imm32) else (base - imm32); 6506 if (add) 6507 address = base + imm32; 6508 else 6509 address = base - imm32; 6510 6511 // data = MemU[address,2]; 6512 Register base_reg; 6513 base_reg.SetRegister (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC); 6514 6515 EmulateInstruction::Context context; 6516 context.type = eContextRegisterLoad; 6517 context.SetRegisterPlusOffset (base_reg, address - base); 6518 6519 uint64_t data = MemURead (context, address, 2, 0, &success); 6520 if (!success) 6521 return false; 6522 6523 6524 // if UnalignedSupport() || address<0> = '0' then 6525 if (UnalignedSupport () || BitIsClear (address, 0)) 6526 { 6527 // R[t] = ZeroExtend(data, 32); 6528 context.type = eContextRegisterLoad; 6529 context.SetRegisterPlusOffset (base_reg, address - base); 6530 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data)) 6531 return false; 6532 6533 } 6534 else // Can only apply before ARMv7 6535 { 6536 // R[t] = bits(32) UNKNOWN; 6537 WriteBits32Unknown (t); 6538 } 6539 } 6540 return true; 6541} 6542 6543// LDRH (literal) calculates an address from a base register value and an offset register value, loads a halfword 6544// from memory, zero-extends it to form a 32-bit word, and writes it to a register. The offset register value can 6545// be shifted left by 0, 1, 2, or 3 bits. 6546bool 6547EmulateInstructionARM::EmulateLDRHRegister (const uint32_t opcode, const ARMEncoding encoding) 6548{ 6549#if 0 6550 if ConditionPassed() then 6551 EncodingSpecificOperations(); NullCheckIfThumbEE(n); 6552 offset = Shift(R[m], shift_t, shift_n, APSR.C); 6553 offset_addr = if add then (R[n] + offset) else (R[n] - offset); 6554 address = if index then offset_addr else R[n]; 6555 data = MemU[address,2]; 6556 if wback then R[n] = offset_addr; 6557 if UnalignedSupport() || address<0> = '0' then 6558 R[t] = ZeroExtend(data, 32); 6559 else // Can only apply before ARMv7 6560 R[t] = bits(32) UNKNOWN; 6561#endif 6562 6563 bool success = false; 6564 6565 if (ConditionPassed(opcode)) 6566 { 6567 uint32_t t; 6568 uint32_t n; 6569 uint32_t m; 6570 bool index; 6571 bool add; 6572 bool wback; 6573 ARM_ShifterType shift_t; 6574 uint32_t shift_n; 6575 6576 // EncodingSpecificOperations(); NullCheckIfThumbEE(n); 6577 switch (encoding) 6578 { 6579 case eEncodingT1: 6580 // if CurrentInstrSet() == InstrSet_ThumbEE then SEE "Modified operation in ThumbEE"; 6581 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm); 6582 t = Bits32 (opcode, 2, 0); 6583 n = Bits32 (opcode, 5, 3); 6584 m = Bits32 (opcode, 8, 6); 6585 6586 // index = TRUE; add = TRUE; wback = FALSE; 6587 index = true; 6588 add = true; 6589 wback = false; 6590 6591 // (shift_t, shift_n) = (SRType_LSL, 0); 6592 shift_t = SRType_LSL; 6593 shift_n = 0; 6594 6595 break; 6596 6597 case eEncodingT2: 6598 // if Rn == '1111' then SEE LDRH (literal); 6599 // if Rt == '1111' then SEE "Unallocated memory hints"; 6600 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm); 6601 t = Bits32 (opcode, 15, 12); 6602 n = Bits32 (opcode, 19, 16); 6603 m = Bits32 (opcode, 3, 0); 6604 6605 // index = TRUE; add = TRUE; wback = FALSE; 6606 index = true; 6607 add = true; 6608 wback = false; 6609 6610 // (shift_t, shift_n) = (SRType_LSL, UInt(imm2)); 6611 shift_t = SRType_LSL; 6612 shift_n = Bits32 (opcode, 5, 4); 6613 6614 // if t == 13 || BadReg(m) then UNPREDICTABLE; 6615 if ((t == 13) || BadReg (m)) 6616 return false; 6617 break; 6618 6619 case eEncodingA1: 6620 // if P == '0' && W == '1' then SEE LDRHT; 6621 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm); 6622 t = Bits32 (opcode, 15, 12); 6623 n = Bits32 (opcode, 19, 16); 6624 m = Bits32 (opcode, 3, 0); 6625 6626 // index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1'); 6627 index = BitIsSet (opcode, 24); 6628 add = BitIsSet (opcode, 23); 6629 wback = (BitIsClear (opcode, 24) || BitIsSet (opcode, 21)); 6630 6631 // (shift_t, shift_n) = (SRType_LSL, 0); 6632 shift_t = SRType_LSL; 6633 shift_n = 0; 6634 6635 // if t == 15 || m == 15 then UNPREDICTABLE; 6636 if ((t == 15) || (m == 15)) 6637 return false; 6638 6639 // if wback && (n == 15 || n == t) then UNPREDICTABLE; 6640 if (wback && ((n == 15) || (n == t))) 6641 return false; 6642 6643 break; 6644 6645 default: 6646 return false; 6647 } 6648 6649 // offset = Shift(R[m], shift_t, shift_n, APSR.C); 6650 6651 uint64_t Rm = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success); 6652 if (!success) 6653 return false; 6654 6655 addr_t offset = Shift (Rm, shift_t, shift_n, APSR_C); 6656 6657 addr_t offset_addr; 6658 addr_t address; 6659 6660 // offset_addr = if add then (R[n] + offset) else (R[n] - offset); 6661 uint64_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success); 6662 if (!success) 6663 return false; 6664 6665 if (add) 6666 offset_addr = Rn + offset; 6667 else 6668 offset_addr = Rn - offset; 6669 6670 // address = if index then offset_addr else R[n]; 6671 if (index) 6672 address = offset_addr; 6673 else 6674 address = Rn; 6675 6676 // data = MemU[address,2]; 6677 Register base_reg; 6678 Register offset_reg; 6679 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n); 6680 offset_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + m); 6681 6682 EmulateInstruction::Context context; 6683 context.type = eContextRegisterLoad; 6684 context.SetRegisterPlusIndirectOffset (base_reg, offset_reg); 6685 uint64_t data = MemURead (context, address, 2, 0, &success); 6686 if (!success) 6687 return false; 6688 6689 // if wback then R[n] = offset_addr; 6690 if (wback) 6691 { 6692 context.type = eContextAdjustBaseRegister; 6693 context.SetAddress (offset_addr); 6694 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr)) 6695 return false; 6696 } 6697 6698 // if UnalignedSupport() || address<0> = '0' then 6699 if (UnalignedSupport() || BitIsClear (address, 0)) 6700 { 6701 // R[t] = ZeroExtend(data, 32); 6702 context.type = eContextRegisterLoad; 6703 context.SetRegisterPlusIndirectOffset (base_reg, offset_reg); 6704 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data)) 6705 return false; 6706 } 6707 else // Can only apply before ARMv7 6708 { 6709 // R[t] = bits(32) UNKNOWN; 6710 WriteBits32Unknown (t); 6711 } 6712 } 6713 return true; 6714} 6715 6716// LDRSB (immediate) calculates an address from a base register value and an immediate offset, loads a byte from 6717// memory, sign-extends it to form a 32-bit word, and writes it to a register. It can use offset, post-indexed, 6718// or pre-indexed addressing. 6719bool 6720EmulateInstructionARM::EmulateLDRSBImmediate (const uint32_t opcode, const ARMEncoding encoding) 6721{ 6722#if 0 6723 if ConditionPassed() then 6724 EncodingSpecificOperations(); NullCheckIfThumbEE(n); 6725 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32); 6726 address = if index then offset_addr else R[n]; 6727 R[t] = SignExtend(MemU[address,1], 32); 6728 if wback then R[n] = offset_addr; 6729#endif 6730 6731 bool success = false; 6732 6733 if (ConditionPassed(opcode)) 6734 { 6735 uint32_t t; 6736 uint32_t n; 6737 uint32_t imm32; 6738 bool index; 6739 bool add; 6740 bool wback; 6741 6742 // EncodingSpecificOperations(); NullCheckIfThumbEE(n); 6743 switch (encoding) 6744 { 6745 case eEncodingT1: 6746 // if Rt == '1111' then SEE PLI; 6747 // if Rn == '1111' then SEE LDRSB (literal); 6748 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32); 6749 t = Bits32 (opcode, 15, 12); 6750 n = Bits32 (opcode, 19, 16); 6751 imm32 = Bits32 (opcode, 11, 0); 6752 6753 // index = TRUE; add = TRUE; wback = FALSE; 6754 index = true; 6755 add = true; 6756 wback = false; 6757 6758 // if t == 13 then UNPREDICTABLE; 6759 if (t == 13) 6760 return false; 6761 6762 break; 6763 6764 case eEncodingT2: 6765 // if Rt == '1111' && P == '1' && U == '0' && W == '0' then SEE PLI; 6766 // if Rn == '1111' then SEE LDRSB (literal); 6767 // if P == '1' && U == '1' && W == '0' then SEE LDRSBT; 6768 // if P == '0' && W == '0' then UNDEFINED; 6769 if (BitIsClear (opcode, 10) && BitIsClear (opcode, 8)) 6770 return false; 6771 6772 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32); 6773 t = Bits32 (opcode, 15, 12); 6774 n = Bits32 (opcode, 19, 16); 6775 imm32 = Bits32 (opcode, 7, 0); 6776 6777 // index = (P == '1'); add = (U == '1'); wback = (W == '1'); 6778 index = BitIsSet (opcode, 10); 6779 add = BitIsSet (opcode, 9); 6780 wback = BitIsSet (opcode, 8); 6781 6782 // if BadReg(t) || (wback && n == t) then UNPREDICTABLE; 6783 if (((t == 13) || ((t == 15) 6784 && (BitIsClear (opcode, 10) || BitIsSet (opcode, 9) || BitIsSet (opcode, 8)))) 6785 || (wback && (n == t))) 6786 return false; 6787 6788 break; 6789 6790 case eEncodingA1: 6791 { 6792 // if Rn == '1111' then SEE LDRSB (literal); 6793 // if P == '0' && W == '1' then SEE LDRSBT; 6794 // t == UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm4H:imm4L, 32); 6795 t = Bits32 (opcode, 15, 12); 6796 n = Bits32 (opcode, 19, 16); 6797 6798 uint32_t imm4H = Bits32 (opcode, 11, 8); 6799 uint32_t imm4L = Bits32 (opcode, 3, 0); 6800 imm32 = (imm4H << 4) | imm4L; 6801 6802 // index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1'); 6803 index = BitIsSet (opcode, 24); 6804 add = BitIsSet (opcode, 23); 6805 wback = (BitIsClear (opcode, 24) || BitIsSet (opcode, 21)); 6806 6807 // if t == 15 || (wback && n == t) then UNPREDICTABLE; 6808 if ((t == 15) || (wback && (n == t))) 6809 return false; 6810 6811 break; 6812 } 6813 6814 default: 6815 return false; 6816 } 6817 6818 uint64_t Rn = ReadCoreReg (n, &success); 6819 if (!success) 6820 return false; 6821 6822 addr_t offset_addr; 6823 addr_t address; 6824 6825 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32); 6826 if (add) 6827 offset_addr = Rn + imm32; 6828 else 6829 offset_addr = Rn - imm32; 6830 6831 // address = if index then offset_addr else R[n]; 6832 if (index) 6833 address = offset_addr; 6834 else 6835 address = Rn; 6836 6837 // R[t] = SignExtend(MemU[address,1], 32); 6838 Register base_reg; 6839 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n); 6840 6841 EmulateInstruction::Context context; 6842 context.type = eContextRegisterLoad; 6843 context.SetRegisterPlusOffset (base_reg, address - Rn); 6844 6845 uint64_t unsigned_data = MemURead (context, address, 1, 0, &success); 6846 if (!success) 6847 return false; 6848 6849 int64_t signed_data = llvm::SignExtend64<8>(unsigned_data); 6850 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, (uint64_t) signed_data)) 6851 return false; 6852 6853 // if wback then R[n] = offset_addr; 6854 if (wback) 6855 { 6856 context.type = eContextAdjustBaseRegister; 6857 context.SetAddress (offset_addr); 6858 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr)) 6859 return false; 6860 } 6861 } 6862 6863 return true; 6864} 6865 6866// LDRSB (literal) calculates an address from the PC value and an immediate offset, loads a byte from memory, 6867// sign-extends it to form a 32-bit word, and writes tit to a register. 6868bool 6869EmulateInstructionARM::EmulateLDRSBLiteral (const uint32_t opcode, const ARMEncoding encoding) 6870{ 6871#if 0 6872 if ConditionPassed() then 6873 EncodingSpecificOperations(); NullCheckIfThumbEE(15); 6874 base = Align(PC,4); 6875 address = if add then (base + imm32) else (base - imm32); 6876 R[t] = SignExtend(MemU[address,1], 32); 6877#endif 6878 6879 bool success = false; 6880 6881 if (ConditionPassed(opcode)) 6882 { 6883 uint32_t t; 6884 uint32_t imm32; 6885 bool add; 6886 6887 // EncodingSpecificOperations(); NullCheckIfThumbEE(15); 6888 switch (encoding) 6889 { 6890 case eEncodingT1: 6891 // if Rt == '1111' then SEE PLI; 6892 // t = UInt(Rt); imm32 = ZeroExtend(imm12, 32); add = (U == '1'); 6893 t = Bits32 (opcode, 15, 12); 6894 imm32 = Bits32 (opcode, 11, 0); 6895 add = BitIsSet (opcode, 23); 6896 6897 // if t == 13 then UNPREDICTABLE; 6898 if (t == 13) 6899 return false; 6900 6901 break; 6902 6903 case eEncodingA1: 6904 { 6905 // t == UInt(Rt); imm32 = ZeroExtend(imm4H:imm4L, 32); add = (U == '1'); 6906 t = Bits32 (opcode, 15, 12); 6907 uint32_t imm4H = Bits32 (opcode, 11, 8); 6908 uint32_t imm4L = Bits32 (opcode, 3, 0); 6909 imm32 = (imm4H << 4) | imm4L; 6910 add = BitIsSet (opcode, 23); 6911 6912 // if t == 15 then UNPREDICTABLE; 6913 if (t == 15) 6914 return false; 6915 6916 break; 6917 } 6918 6919 default: 6920 return false; 6921 } 6922 6923 // base = Align(PC,4); 6924 uint64_t pc_value = ReadCoreReg (PC_REG, &success); 6925 if (!success) 6926 return false; 6927 uint64_t base = AlignPC (pc_value); 6928 6929 // address = if add then (base + imm32) else (base - imm32); 6930 addr_t address; 6931 if (add) 6932 address = base + imm32; 6933 else 6934 address = base - imm32; 6935 6936 // R[t] = SignExtend(MemU[address,1], 32); 6937 Register base_reg; 6938 base_reg.SetRegister (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC); 6939 6940 EmulateInstruction::Context context; 6941 context.type = eContextRegisterLoad; 6942 context.SetRegisterPlusOffset (base_reg, address - base); 6943 6944 uint64_t unsigned_data = MemURead (context, address, 1, 0, &success); 6945 if (!success) 6946 return false; 6947 6948 int64_t signed_data = llvm::SignExtend64<8>(unsigned_data); 6949 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, (uint64_t) signed_data)) 6950 return false; 6951 } 6952 return true; 6953} 6954 6955// LDRSB (register) calculates an address from a base register value and an offset register value, loadsa byte from 6956// memory, sign-extends it to form a 32-bit word, and writes it to a register. The offset register value can be 6957// shifted left by 0, 1, 2, or 3 bits. 6958bool 6959EmulateInstructionARM::EmulateLDRSBRegister (const uint32_t opcode, const ARMEncoding encoding) 6960{ 6961#if 0 6962 if ConditionPassed() then 6963 EncodingSpecificOperations(); NullCheckIfThumbEE(n); 6964 offset = Shift(R[m], shift_t, shift_n, APSR.C); 6965 offset_addr = if add then (R[n] + offset) else (R[n] - offset); 6966 address = if index then offset_addr else R[n]; 6967 R[t] = SignExtend(MemU[address,1], 32); 6968 if wback then R[n] = offset_addr; 6969#endif 6970 6971 bool success = false; 6972 6973 if (ConditionPassed(opcode)) 6974 { 6975 uint32_t t; 6976 uint32_t n; 6977 uint32_t m; 6978 bool index; 6979 bool add; 6980 bool wback; 6981 ARM_ShifterType shift_t; 6982 uint32_t shift_n; 6983 6984 // EncodingSpecificOperations(); NullCheckIfThumbEE(n); 6985 switch (encoding) 6986 { 6987 case eEncodingT1: 6988 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm); 6989 t = Bits32 (opcode, 2, 0); 6990 n = Bits32 (opcode, 5, 3); 6991 m = Bits32 (opcode, 8, 6); 6992 6993 // index = TRUE; add = TRUE; wback = FALSE; 6994 index = true; 6995 add = true; 6996 wback = false; 6997 6998 // (shift_t, shift_n) = (SRType_LSL, 0); 6999 shift_t = SRType_LSL; 7000 shift_n = 0; 7001 7002 break; 7003 7004 case eEncodingT2: 7005 // if Rt == '1111' then SEE PLI; 7006 // if Rn == '1111' then SEE LDRSB (literal); 7007 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm); 7008 t = Bits32 (opcode, 15, 12); 7009 n = Bits32 (opcode, 19, 16); 7010 m = Bits32 (opcode, 3, 0); 7011 7012 // index = TRUE; add = TRUE; wback = FALSE; 7013 index = true; 7014 add = true; 7015 wback = false; 7016 7017 // (shift_t, shift_n) = (SRType_LSL, UInt(imm2)); 7018 shift_t = SRType_LSL; 7019 shift_n = Bits32 (opcode, 5, 4); 7020 7021 // if t == 13 || BadReg(m) then UNPREDICTABLE; 7022 if ((t == 13) || BadReg (m)) 7023 return false; 7024 break; 7025 7026 case eEncodingA1: 7027 // if P == '0' && W == '1' then SEE LDRSBT; 7028 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm); 7029 t = Bits32 (opcode, 15, 12); 7030 n = Bits32 (opcode, 19, 16); 7031 m = Bits32 (opcode, 3, 0); 7032 7033 // index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1'); 7034 index = BitIsSet (opcode, 24); 7035 add = BitIsSet (opcode, 23); 7036 wback = BitIsClear (opcode, 24) || BitIsSet (opcode, 21); 7037 7038 // (shift_t, shift_n) = (SRType_LSL, 0); 7039 shift_t = SRType_LSL; 7040 shift_n = 0; 7041 7042 // if t == 15 || m == 15 then UNPREDICTABLE; 7043 if ((t == 15) || (m == 15)) 7044 return false; 7045 7046 // if wback && (n == 15 || n == t) then UNPREDICTABLE; 7047 if (wback && ((n == 15) || (n == t))) 7048 return false; 7049 break; 7050 7051 default: 7052 return false; 7053 } 7054 7055 uint64_t Rm = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success); 7056 if (!success) 7057 return false; 7058 7059 // offset = Shift(R[m], shift_t, shift_n, APSR.C); 7060 addr_t offset = Shift (Rm, shift_t, shift_n, APSR_C); 7061 7062 addr_t offset_addr; 7063 addr_t address; 7064 7065 // offset_addr = if add then (R[n] + offset) else (R[n] - offset); 7066 uint64_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success); 7067 if (!success) 7068 return false; 7069 7070 if (add) 7071 offset_addr = Rn + offset; 7072 else 7073 offset_addr = Rn - offset; 7074 7075 // address = if index then offset_addr else R[n]; 7076 if (index) 7077 address = offset_addr; 7078 else 7079 address = Rn; 7080 7081 // R[t] = SignExtend(MemU[address,1], 32); 7082 Register base_reg; 7083 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n); 7084 Register offset_reg; 7085 offset_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + m); 7086 7087 EmulateInstruction::Context context; 7088 context.type = eContextRegisterLoad; 7089 context.SetRegisterPlusIndirectOffset (base_reg, offset_reg); 7090 7091 uint64_t unsigned_data = MemURead (context, address, 1, 0, &success); 7092 if (!success) 7093 return false; 7094 7095 int64_t signed_data = llvm::SignExtend64<8>(unsigned_data); 7096 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, (uint64_t) signed_data)) 7097 return false; 7098 7099 // if wback then R[n] = offset_addr; 7100 if (wback) 7101 { 7102 context.type = eContextAdjustBaseRegister; 7103 context.SetAddress (offset_addr); 7104 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr)) 7105 return false; 7106 } 7107 } 7108 return true; 7109} 7110 7111// LDRSH (immediate) calculates an address from a base register value and an immediate offset, loads a halfword from 7112// memory, sign-extends it to form a 32-bit word, and writes it to a register. It can use offset, post-indexed, or 7113// pre-indexed addressing. 7114bool 7115EmulateInstructionARM::EmulateLDRSHImmediate (const uint32_t opcode, const ARMEncoding encoding) 7116{ 7117#if 0 7118 if ConditionPassed() then 7119 EncodingSpecificOperations(); NullCheckIfThumbEE(n); 7120 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32); 7121 address = if index then offset_addr else R[n]; 7122 data = MemU[address,2]; 7123 if wback then R[n] = offset_addr; 7124 if UnalignedSupport() || address<0> = '0' then 7125 R[t] = SignExtend(data, 32); 7126 else // Can only apply before ARMv7 7127 R[t] = bits(32) UNKNOWN; 7128#endif 7129 7130 bool success = false; 7131 7132 if (ConditionPassed(opcode)) 7133 { 7134 uint32_t t; 7135 uint32_t n; 7136 uint32_t imm32; 7137 bool index; 7138 bool add; 7139 bool wback; 7140 7141 // EncodingSpecificOperations(); NullCheckIfThumbEE(n); 7142 switch (encoding) 7143 { 7144 case eEncodingT1: 7145 // if Rn == '1111' then SEE LDRSH (literal); 7146 // if Rt == '1111' then SEE "Unallocated memory hints"; 7147 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32); 7148 t = Bits32 (opcode, 15, 12); 7149 n = Bits32 (opcode, 19, 16); 7150 imm32 = Bits32 (opcode, 11, 0); 7151 7152 // index = TRUE; add = TRUE; wback = FALSE; 7153 index = true; 7154 add = true; 7155 wback = false; 7156 7157 // if t == 13 then UNPREDICTABLE; 7158 if (t == 13) 7159 return false; 7160 7161 break; 7162 7163 case eEncodingT2: 7164 // if Rn == '1111' then SEE LDRSH (literal); 7165 // if Rt == '1111' && P == '1' && U == '0' && W == '0' then SEE "Unallocated memory hints"; 7166 // if P == '1' && U == '1' && W == '0' then SEE LDRSHT; 7167 // if P == '0' && W == '0' then UNDEFINED; 7168 if (BitIsClear (opcode, 10) && BitIsClear (opcode, 8)) 7169 return false; 7170 7171 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32); 7172 t = Bits32 (opcode, 15, 12); 7173 n = Bits32 (opcode, 19, 16); 7174 imm32 = Bits32 (opcode, 7, 0); 7175 7176 // index = (P == '1'); add = (U == '1'); wback = (W == '1'); 7177 index = BitIsSet (opcode, 10); 7178 add = BitIsSet (opcode, 9); 7179 wback = BitIsSet (opcode, 8); 7180 7181 // if BadReg(t) || (wback && n == t) then UNPREDICTABLE; 7182 if (BadReg (t) || (wback && (n == t))) 7183 return false; 7184 7185 break; 7186 7187 case eEncodingA1: 7188 { 7189 // if Rn == '1111' then SEE LDRSH (literal); 7190 // if P == '0' && W == '1' then SEE LDRSHT; 7191 // t == UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm4H:imm4L, 32); 7192 t = Bits32 (opcode, 15, 12); 7193 n = Bits32 (opcode, 19, 16); 7194 uint32_t imm4H = Bits32 (opcode, 11,8); 7195 uint32_t imm4L = Bits32 (opcode, 3, 0); 7196 imm32 = (imm4H << 4) | imm4L; 7197 7198 // index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1'); 7199 index = BitIsSet (opcode, 24); 7200 add = BitIsSet (opcode, 23); 7201 wback = BitIsClear (opcode, 24) || BitIsSet (opcode, 21); 7202 7203 // if t == 15 || (wback && n == t) then UNPREDICTABLE; 7204 if ((t == 15) || (wback && (n == t))) 7205 return false; 7206 7207 break; 7208 } 7209 7210 default: 7211 return false; 7212 } 7213 7214 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32); 7215 uint64_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success); 7216 if (!success) 7217 return false; 7218 7219 addr_t offset_addr; 7220 if (add) 7221 offset_addr = Rn + imm32; 7222 else 7223 offset_addr = Rn - imm32; 7224 7225 // address = if index then offset_addr else R[n]; 7226 addr_t address; 7227 if (index) 7228 address = offset_addr; 7229 else 7230 address = Rn; 7231 7232 // data = MemU[address,2]; 7233 Register base_reg; 7234 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n); 7235 7236 EmulateInstruction::Context context; 7237 context.type = eContextRegisterLoad; 7238 context.SetRegisterPlusOffset (base_reg, address - Rn); 7239 7240 uint64_t data = MemURead (context, address, 2, 0, &success); 7241 if (!success) 7242 return false; 7243 7244 // if wback then R[n] = offset_addr; 7245 if (wback) 7246 { 7247 context.type = eContextAdjustBaseRegister; 7248 context.SetAddress (offset_addr); 7249 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr)) 7250 return false; 7251 } 7252 7253 // if UnalignedSupport() || address<0> = '0' then 7254 if (UnalignedSupport() || BitIsClear (address, 0)) 7255 { 7256 // R[t] = SignExtend(data, 32); 7257 int64_t signed_data = llvm::SignExtend64<16>(data); 7258 context.type = eContextRegisterLoad; 7259 context.SetRegisterPlusOffset (base_reg, address - Rn); 7260 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, (uint64_t) signed_data)) 7261 return false; 7262 } 7263 else // Can only apply before ARMv7 7264 { 7265 // R[t] = bits(32) UNKNOWN; 7266 WriteBits32Unknown (t); 7267 } 7268 } 7269 return true; 7270} 7271 7272// LDRSH (literal) calculates an address from the PC value and an immediate offset, loads a halfword from memory, 7273// sign-extends it to from a 32-bit word, and writes it to a register. 7274bool 7275EmulateInstructionARM::EmulateLDRSHLiteral (const uint32_t opcode, const ARMEncoding encoding) 7276{ 7277#if 0 7278 if ConditionPassed() then 7279 EncodingSpecificOperations(); NullCheckIfThumbEE(15); 7280 base = Align(PC,4); 7281 address = if add then (base + imm32) else (base - imm32); 7282 data = MemU[address,2]; 7283 if UnalignedSupport() || address<0> = '0' then 7284 R[t] = SignExtend(data, 32); 7285 else // Can only apply before ARMv7 7286 R[t] = bits(32) UNKNOWN; 7287#endif 7288 7289 bool success = false; 7290 7291 if (ConditionPassed(opcode)) 7292 { 7293 uint32_t t; 7294 uint32_t imm32; 7295 bool add; 7296 7297 // EncodingSpecificOperations(); NullCheckIfThumbEE(15); 7298 switch (encoding) 7299 { 7300 case eEncodingT1: 7301 // if Rt == '1111' then SEE "Unallocated memory hints"; 7302 // t = UInt(Rt); imm32 = ZeroExtend(imm12, 32); add = (U == '1'); 7303 t = Bits32 (opcode, 15, 12); 7304 imm32 = Bits32 (opcode, 11, 0); 7305 add = BitIsSet (opcode, 23); 7306 7307 // if t == 13 then UNPREDICTABLE; 7308 if (t == 13) 7309 return false; 7310 7311 break; 7312 7313 case eEncodingA1: 7314 { 7315 // t == UInt(Rt); imm32 = ZeroExtend(imm4H:imm4L, 32); add = (U == '1'); 7316 t = Bits32 (opcode, 15, 12); 7317 uint32_t imm4H = Bits32 (opcode, 11, 8); 7318 uint32_t imm4L = Bits32 (opcode, 3, 0); 7319 imm32 = (imm4H << 4) | imm4L; 7320 add = BitIsSet (opcode, 23); 7321 7322 // if t == 15 then UNPREDICTABLE; 7323 if (t == 15) 7324 return false; 7325 7326 break; 7327 } 7328 default: 7329 return false; 7330 } 7331 7332 // base = Align(PC,4); 7333 uint64_t pc_value = ReadCoreReg (PC_REG, &success); 7334 if (!success) 7335 return false; 7336 7337 uint64_t base = AlignPC (pc_value); 7338 7339 addr_t address; 7340 // address = if add then (base + imm32) else (base - imm32); 7341 if (add) 7342 address = base + imm32; 7343 else 7344 address = base - imm32; 7345 7346 // data = MemU[address,2]; 7347 Register base_reg; 7348 base_reg.SetRegister (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC); 7349 7350 EmulateInstruction::Context context; 7351 context.type = eContextRegisterLoad; 7352 context.SetRegisterPlusOffset (base_reg, imm32); 7353 7354 uint64_t data = MemURead (context, address, 2, 0, &success); 7355 if (!success) 7356 return false; 7357 7358 // if UnalignedSupport() || address<0> = '0' then 7359 if (UnalignedSupport() || BitIsClear (address, 0)) 7360 { 7361 // R[t] = SignExtend(data, 32); 7362 int64_t signed_data = llvm::SignExtend64<16>(data); 7363 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, (uint64_t) signed_data)) 7364 return false; 7365 } 7366 else // Can only apply before ARMv7 7367 { 7368 // R[t] = bits(32) UNKNOWN; 7369 WriteBits32Unknown (t); 7370 } 7371 } 7372 return true; 7373} 7374 7375// LDRSH (register) calculates an address from a base register value and an offset register value, loads a halfword 7376// from memory, sign-extends it to form a 32-bit word, and writes it to a register. The offset register value can be 7377// shifted left by 0, 1, 2, or 3 bits. 7378bool 7379EmulateInstructionARM::EmulateLDRSHRegister (const uint32_t opcode, const ARMEncoding encoding) 7380{ 7381#if 0 7382 if ConditionPassed() then 7383 EncodingSpecificOperations(); NullCheckIfThumbEE(n); 7384 offset = Shift(R[m], shift_t, shift_n, APSR.C); 7385 offset_addr = if add then (R[n] + offset) else (R[n] - offset); 7386 address = if index then offset_addr else R[n]; 7387 data = MemU[address,2]; 7388 if wback then R[n] = offset_addr; 7389 if UnalignedSupport() || address<0> = '0' then 7390 R[t] = SignExtend(data, 32); 7391 else // Can only apply before ARMv7 7392 R[t] = bits(32) UNKNOWN; 7393#endif 7394 7395 bool success = false; 7396 7397 if (ConditionPassed(opcode)) 7398 { 7399 uint32_t t; 7400 uint32_t n; 7401 uint32_t m; 7402 bool index; 7403 bool add; 7404 bool wback; 7405 ARM_ShifterType shift_t; 7406 uint32_t shift_n; 7407 7408 // EncodingSpecificOperations(); NullCheckIfThumbEE(n); 7409 switch (encoding) 7410 { 7411 case eEncodingT1: 7412 // if CurrentInstrSet() == InstrSet_ThumbEE then SEE "Modified operation in ThumbEE"; 7413 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm); 7414 t = Bits32 (opcode, 2, 0); 7415 n = Bits32 (opcode, 5, 3); 7416 m = Bits32 (opcode, 8, 6); 7417 7418 // index = TRUE; add = TRUE; wback = FALSE; 7419 index = true; 7420 add = true; 7421 wback = false; 7422 7423 // (shift_t, shift_n) = (SRType_LSL, 0); 7424 shift_t = SRType_LSL; 7425 shift_n = 0; 7426 7427 break; 7428 7429 case eEncodingT2: 7430 // if Rn == '1111' then SEE LDRSH (literal); 7431 // if Rt == '1111' then SEE "Unallocated memory hints"; 7432 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm); 7433 t = Bits32 (opcode, 15, 12); 7434 n = Bits32 (opcode, 19, 16); 7435 m = Bits32 (opcode, 3, 0); 7436 7437 // index = TRUE; add = TRUE; wback = FALSE; 7438 index = true; 7439 add = true; 7440 wback = false; 7441 7442 // (shift_t, shift_n) = (SRType_LSL, UInt(imm2)); 7443 shift_t = SRType_LSL; 7444 shift_n = Bits32 (opcode, 5, 4); 7445 7446 // if t == 13 || BadReg(m) then UNPREDICTABLE; 7447 if ((t == 13) || BadReg (m)) 7448 return false; 7449 7450 break; 7451 7452 case eEncodingA1: 7453 // if P == '0' && W == '1' then SEE LDRSHT; 7454 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm); 7455 t = Bits32 (opcode, 15, 12); 7456 n = Bits32 (opcode, 19, 16); 7457 m = Bits32 (opcode, 3, 0); 7458 7459 // index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1'); 7460 index = BitIsSet (opcode, 24); 7461 add = BitIsSet (opcode, 23); 7462 wback = BitIsClear (opcode, 24) || BitIsSet (opcode, 21); 7463 7464 // (shift_t, shift_n) = (SRType_LSL, 0); 7465 shift_t = SRType_LSL; 7466 shift_n = 0; 7467 7468 // if t == 15 || m == 15 then UNPREDICTABLE; 7469 if ((t == 15) || (m == 15)) 7470 return false; 7471 7472 // if wback && (n == 15 || n == t) then UNPREDICTABLE; 7473 if (wback && ((n == 15) || (n == t))) 7474 return false; 7475 7476 break; 7477 7478 default: 7479 break; 7480 } 7481 7482 uint64_t Rm = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success); 7483 if (!success) 7484 return false; 7485 7486 uint64_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success); 7487 if (!success) 7488 return false; 7489 7490 // offset = Shift(R[m], shift_t, shift_n, APSR.C); 7491 addr_t offset = Shift (Rm, shift_t, shift_n, APSR_C); 7492 7493 addr_t offset_addr; 7494 addr_t address; 7495 7496 // offset_addr = if add then (R[n] + offset) else (R[n] - offset); 7497 if (add) 7498 offset_addr = Rn + offset; 7499 else 7500 offset_addr = Rn - offset; 7501 7502 // address = if index then offset_addr else R[n]; 7503 if (index) 7504 address = offset_addr; 7505 else 7506 address = Rn; 7507 7508 // data = MemU[address,2]; 7509 Register base_reg; 7510 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n); 7511 7512 Register offset_reg; 7513 offset_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + m); 7514 7515 EmulateInstruction::Context context; 7516 context.type = eContextRegisterLoad; 7517 context.SetRegisterPlusIndirectOffset (base_reg, offset_reg); 7518 7519 uint64_t data = MemURead (context, address, 2, 0, &success); 7520 if (!success) 7521 return false; 7522 7523 // if wback then R[n] = offset_addr; 7524 if (wback) 7525 { 7526 context.type = eContextAdjustBaseRegister; 7527 context.SetAddress (offset_addr); 7528 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr)) 7529 return false; 7530 } 7531 7532 // if UnalignedSupport() || address<0> = '0' then 7533 if (UnalignedSupport() || BitIsClear (address, 0)) 7534 { 7535 // R[t] = SignExtend(data, 32); 7536 context.type = eContextRegisterLoad; 7537 context.SetRegisterPlusIndirectOffset (base_reg, offset_reg); 7538 7539 int64_t signed_data = llvm::SignExtend64<16>(data); 7540 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, (uint64_t) signed_data)) 7541 return false; 7542 } 7543 else // Can only apply before ARMv7 7544 { 7545 // R[t] = bits(32) UNKNOWN; 7546 WriteBits32Unknown (t); 7547 } 7548 } 7549 return true; 7550} 7551 7552// SXTB extracts an 8-bit value from a register, sign-extends it to 32 bits, and writes the result to the destination 7553// register. You can specifiy a rotation by 0, 8, 16, or 24 bits before extracting the 8-bit value. 7554bool 7555EmulateInstructionARM::EmulateSXTB (const uint32_t opcode, const ARMEncoding encoding) 7556{ 7557#if 0 7558 if ConditionPassed() then 7559 EncodingSpecificOperations(); 7560 rotated = ROR(R[m], rotation); 7561 R[d] = SignExtend(rotated<7:0>, 32); 7562#endif 7563 7564 bool success = false; 7565 7566 if (ConditionPassed(opcode)) 7567 { 7568 uint32_t d; 7569 uint32_t m; 7570 uint32_t rotation; 7571 7572 // EncodingSpecificOperations(); 7573 switch (encoding) 7574 { 7575 case eEncodingT1: 7576 // d = UInt(Rd); m = UInt(Rm); rotation = 0; 7577 d = Bits32 (opcode, 2, 0); 7578 m = Bits32 (opcode, 5, 3); 7579 rotation = 0; 7580 7581 break; 7582 7583 case eEncodingT2: 7584 // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:'000'); 7585 d = Bits32 (opcode, 11, 8); 7586 m = Bits32 (opcode, 3, 0); 7587 rotation = Bits32 (opcode, 5, 4) << 3; 7588 7589 // if BadReg(d) || BadReg(m) then UNPREDICTABLE; 7590 if (BadReg (d) || BadReg (m)) 7591 return false; 7592 7593 break; 7594 7595 case eEncodingA1: 7596 // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:'000'); 7597 d = Bits32 (opcode, 15, 12); 7598 m = Bits32 (opcode, 3, 0); 7599 rotation = Bits32 (opcode, 11, 10) << 3; 7600 7601 // if d == 15 || m == 15 then UNPREDICTABLE; 7602 if ((d == 15) || (m == 15)) 7603 return false; 7604 7605 break; 7606 7607 default: 7608 return false; 7609 } 7610 7611 uint64_t Rm = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success); 7612 if (!success) 7613 return false; 7614 7615 // rotated = ROR(R[m], rotation); 7616 uint64_t rotated = ROR (Rm, rotation); 7617 7618 // R[d] = SignExtend(rotated<7:0>, 32); 7619 int64_t data = llvm::SignExtend64<8>(rotated); 7620 7621 Register source_reg; 7622 source_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + m); 7623 7624 EmulateInstruction::Context context; 7625 context.type = eContextRegisterLoad; 7626 context.SetRegister (source_reg); 7627 7628 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + d, (uint64_t) data)) 7629 return false; 7630 } 7631 return true; 7632} 7633 7634// SXTH extracts a 16-bit value from a register, sign-extends it to 32 bits, and writes the result to the destination 7635// register. You can specify a rotation by 0, 8, 16, or 24 bits before extracting the 16-bit value. 7636bool 7637EmulateInstructionARM::EmulateSXTH (const uint32_t opcode, const ARMEncoding encoding) 7638{ 7639#if 0 7640 if ConditionPassed() then 7641 EncodingSpecificOperations(); 7642 rotated = ROR(R[m], rotation); 7643 R[d] = SignExtend(rotated<15:0>, 32); 7644#endif 7645 7646 bool success = false; 7647 7648 if (ConditionPassed(opcode)) 7649 { 7650 uint32_t d; 7651 uint32_t m; 7652 uint32_t rotation; 7653 7654 // EncodingSpecificOperations(); 7655 switch (encoding) 7656 { 7657 case eEncodingT1: 7658 // d = UInt(Rd); m = UInt(Rm); rotation = 0; 7659 d = Bits32 (opcode, 2, 0); 7660 m = Bits32 (opcode, 5, 3); 7661 rotation = 0; 7662 7663 break; 7664 7665 case eEncodingT2: 7666 // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:'000'); 7667 d = Bits32 (opcode, 11, 8); 7668 m = Bits32 (opcode, 3, 0); 7669 rotation = Bits32 (opcode, 5, 4) << 3; 7670 7671 // if BadReg(d) || BadReg(m) then UNPREDICTABLE; 7672 if (BadReg (d) || BadReg (m)) 7673 return false; 7674 7675 break; 7676 7677 case eEncodingA1: 7678 // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:'000'); 7679 d = Bits32 (opcode, 15, 12); 7680 m = Bits32 (opcode, 3, 0); 7681 rotation = Bits32 (opcode, 11, 10) << 3; 7682 7683 // if d == 15 || m == 15 then UNPREDICTABLE; 7684 if ((d == 15) || (m == 15)) 7685 return false; 7686 7687 break; 7688 7689 default: 7690 return false; 7691 } 7692 7693 uint64_t Rm = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success); 7694 if (!success) 7695 return false; 7696 7697 // rotated = ROR(R[m], rotation); 7698 uint64_t rotated = ROR (Rm, rotation); 7699 7700 // R[d] = SignExtend(rotated<15:0>, 32); 7701 Register source_reg; 7702 source_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + m); 7703 7704 EmulateInstruction::Context context; 7705 context.type = eContextRegisterLoad; 7706 context.SetRegister (source_reg); 7707 7708 int64_t data = llvm::SignExtend64<16> (rotated); 7709 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + d, (uint64_t) data)) 7710 return false; 7711 } 7712 7713 return true; 7714} 7715 7716// UXTB extracts an 8-bit value from a register, zero-extneds it to 32 bits, and writes the result to the destination 7717// register. You can specify a rotation by 0, 8, 16, or 24 bits before extracting the 8-bit value. 7718bool 7719EmulateInstructionARM::EmulateUXTB (const uint32_t opcode, const ARMEncoding encoding) 7720{ 7721#if 0 7722 if ConditionPassed() then 7723 EncodingSpecificOperations(); 7724 rotated = ROR(R[m], rotation); 7725 R[d] = ZeroExtend(rotated<7:0>, 32); 7726#endif 7727 7728 bool success = false; 7729 7730 if (ConditionPassed(opcode)) 7731 { 7732 uint32_t d; 7733 uint32_t m; 7734 uint32_t rotation; 7735 7736 // EncodingSpecificOperations(); 7737 switch (encoding) 7738 { 7739 case eEncodingT1: 7740 // d = UInt(Rd); m = UInt(Rm); rotation = 0; 7741 d = Bits32 (opcode, 2, 0); 7742 m = Bits32 (opcode, 5, 3); 7743 rotation = 0; 7744 7745 break; 7746 7747 case eEncodingT2: 7748 // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:'000'); 7749 d = Bits32 (opcode, 11, 8); 7750 m = Bits32 (opcode, 3, 0); 7751 rotation = Bits32 (opcode, 5, 4) << 3; 7752 7753 // if BadReg(d) || BadReg(m) then UNPREDICTABLE; 7754 if (BadReg (d) || BadReg (m)) 7755 return false; 7756 7757 break; 7758 7759 case eEncodingA1: 7760 // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:'000'); 7761 d = Bits32 (opcode, 15, 12); 7762 m = Bits32 (opcode, 3, 0); 7763 rotation = Bits32 (opcode, 11, 10) << 3; 7764 7765 // if d == 15 || m == 15 then UNPREDICTABLE; 7766 if ((d == 15) || (m == 15)) 7767 return false; 7768 7769 break; 7770 7771 default: 7772 return false; 7773 } 7774 7775 uint64_t Rm = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success); 7776 if (!success) 7777 return false; 7778 7779 // rotated = ROR(R[m], rotation); 7780 uint64_t rotated = ROR (Rm, rotation); 7781 7782 // R[d] = ZeroExtend(rotated<7:0>, 32); 7783 Register source_reg; 7784 source_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + m); 7785 7786 EmulateInstruction::Context context; 7787 context.type = eContextRegisterLoad; 7788 context.SetRegister (source_reg); 7789 7790 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + d, Bits32 (rotated, 7, 0))) 7791 return false; 7792 } 7793 return true; 7794} 7795 7796// UXTH extracts a 16-bit value from a register, zero-extends it to 32 bits, and writes the result to the destination 7797// register. You can specify a rotation by 0, 8, 16, or 24 bits before extracting the 16-bit value. 7798bool 7799EmulateInstructionARM::EmulateUXTH (const uint32_t opcode, const ARMEncoding encoding) 7800{ 7801#if 0 7802 if ConditionPassed() then 7803 EncodingSpecificOperations(); 7804 rotated = ROR(R[m], rotation); 7805 R[d] = ZeroExtend(rotated<15:0>, 32); 7806#endif 7807 7808 bool success = false; 7809 7810 if (ConditionPassed(opcode)) 7811 { 7812 uint32_t d; 7813 uint32_t m; 7814 uint32_t rotation; 7815 7816 switch (encoding) 7817 { 7818 case eEncodingT1: 7819 // d = UInt(Rd); m = UInt(Rm); rotation = 0; 7820 d = Bits32 (opcode, 2, 0); 7821 m = Bits32 (opcode, 5, 3); 7822 rotation = 0; 7823 7824 break; 7825 7826 case eEncodingT2: 7827 // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:'000'); 7828 d = Bits32 (opcode, 11, 8); 7829 m = Bits32 (opcode, 3, 0); 7830 rotation = Bits32 (opcode, 5, 4) << 3; 7831 7832 // if BadReg(d) || BadReg(m) then UNPREDICTABLE; 7833 if (BadReg (d) || BadReg (m)) 7834 return false; 7835 7836 break; 7837 7838 case eEncodingA1: 7839 // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:'000'); 7840 d = Bits32 (opcode, 15, 12); 7841 m = Bits32 (opcode, 3, 0); 7842 rotation = Bits32 (opcode, 11, 10) << 3; 7843 7844 // if d == 15 || m == 15 then UNPREDICTABLE; 7845 if ((d == 15) || (m == 15)) 7846 return false; 7847 7848 break; 7849 7850 default: 7851 return false; 7852 } 7853 7854 uint64_t Rm = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success); 7855 if (!success) 7856 return false; 7857 7858 // rotated = ROR(R[m], rotation); 7859 uint64_t rotated = ROR (Rm, rotation); 7860 7861 // R[d] = ZeroExtend(rotated<15:0>, 32); 7862 Register source_reg; 7863 source_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + m); 7864 7865 EmulateInstruction::Context context; 7866 context.type = eContextRegisterLoad; 7867 context.SetRegister (source_reg); 7868 7869 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + d, Bits32 (rotated, 15, 0))) 7870 return false; 7871 } 7872 return true; 7873} 7874 7875// RFE (Return From Exception) loads the PC and the CPSR from the word at the specified address and the following 7876// word respectively. 7877bool 7878EmulateInstructionARM::EmulateRFE (const uint32_t opcode, const ARMEncoding encoding) 7879{ 7880#if 0 7881 if ConditionPassed() then 7882 EncodingSpecificOperations(); 7883 if !CurrentModeIsPrivileged() || CurrentInstrSet() == InstrSet_ThumbEE then 7884 UNPREDICTABLE; 7885 else 7886 address = if increment then R[n] else R[n]-8; 7887 if wordhigher then address = address+4; 7888 CPSRWriteByInstr(MemA[address+4,4], '1111', TRUE); 7889 BranchWritePC(MemA[address,4]); 7890 if wback then R[n] = if increment then R[n]+8 else R[n]-8; 7891#endif 7892 7893 bool success = false; 7894 7895 if (ConditionPassed(opcode)) 7896 { 7897 uint32_t n; 7898 bool wback; 7899 bool increment; 7900 bool wordhigher; 7901 7902 // EncodingSpecificOperations(); 7903 switch (encoding) 7904 { 7905 case eEncodingT1: 7906 // n = UInt(Rn); wback = (W == '1'); increment = FALSE; wordhigher = FALSE; 7907 n = Bits32 (opcode, 19, 16); 7908 wback = BitIsSet (opcode, 21); 7909 increment = false; 7910 wordhigher = false; 7911 7912 // if n == 15 then UNPREDICTABLE; 7913 if (n == 15) 7914 return false; 7915 7916 // if InITBlock() && !LastInITBlock() then UNPREDICTABLE; 7917 if (InITBlock() && !LastInITBlock()) 7918 return false; 7919 7920 break; 7921 7922 case eEncodingT2: 7923 // n = UInt(Rn); wback = (W == '1'); increment = TRUE; wordhigher = FALSE; 7924 n = Bits32 (opcode, 19, 16); 7925 wback = BitIsSet (opcode, 21); 7926 increment = true; 7927 wordhigher = false; 7928 7929 // if n == 15 then UNPREDICTABLE; 7930 if (n == 15) 7931 return false; 7932 7933 // if InITBlock() && !LastInITBlock() then UNPREDICTABLE; 7934 if (InITBlock() && !LastInITBlock()) 7935 return false; 7936 7937 break; 7938 7939 case eEncodingA1: 7940 // n = UInt(Rn); 7941 n = Bits32 (opcode, 19, 16); 7942 7943 // wback = (W == '1'); inc = (U == '1'); wordhigher = (P == U); 7944 wback = BitIsSet (opcode, 21); 7945 increment = BitIsSet (opcode, 23); 7946 wordhigher = (Bit32 (opcode, 24) == Bit32 (opcode, 23)); 7947 7948 // if n == 15 then UNPREDICTABLE; 7949 if (n == 15) 7950 return false; 7951 7952 break; 7953 7954 default: 7955 return false; 7956 } 7957 7958 // if !CurrentModeIsPrivileged() || CurrentInstrSet() == InstrSet_ThumbEE then 7959 if (!CurrentModeIsPrivileged ()) 7960 // UNPREDICTABLE; 7961 return false; 7962 else 7963 { 7964 uint64_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success); 7965 if (!success) 7966 return false; 7967 7968 addr_t address; 7969 // address = if increment then R[n] else R[n]-8; 7970 if (increment) 7971 address = Rn; 7972 else 7973 address = Rn - 8; 7974 7975 // if wordhigher then address = address+4; 7976 if (wordhigher) 7977 address = address + 4; 7978 7979 // CPSRWriteByInstr(MemA[address+4,4], '1111', TRUE); 7980 Register base_reg; 7981 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n); 7982 7983 EmulateInstruction::Context context; 7984 context.type = eContextReturnFromException; 7985 context.SetRegisterPlusOffset (base_reg, address - Rn); 7986 7987 uint64_t data = MemARead (context, address + 4, 4, 0, &success); 7988 if (!success) 7989 return false; 7990 7991 CPSRWriteByInstr (data, 15, true); 7992 7993 // BranchWritePC(MemA[address,4]); 7994 uint64_t data2 = MemARead (context, address, 4, 0, &success); 7995 if (!success) 7996 return false; 7997 7998 BranchWritePC (context, data2); 7999 8000 // if wback then R[n] = if increment then R[n]+8 else R[n]-8; 8001 if (wback) 8002 { 8003 context.type = eContextAdjustBaseRegister; 8004 if (increment) 8005 { 8006 context.SetOffset (8); 8007 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, Rn + 8)) 8008 return false; 8009 } 8010 else 8011 { 8012 context.SetOffset (-8); 8013 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, Rn - 8)) 8014 return false; 8015 } 8016 } // if wback 8017 } 8018 } // if ConditionPassed() 8019 return true; 8020} 8021 8022// Bitwise Exclusive OR (immediate) performs a bitwise exclusive OR of a register value and an immediate value, 8023// and writes the result to the destination register. It can optionally update the condition flags based on 8024// the result. 8025bool 8026EmulateInstructionARM::EmulateEORImm (const uint32_t opcode, const ARMEncoding encoding) 8027{ 8028#if 0 8029 // ARM pseudo code... 8030 if ConditionPassed() then 8031 EncodingSpecificOperations(); 8032 result = R[n] EOR imm32; 8033 if d == 15 then // Can only occur for ARM encoding 8034 ALUWritePC(result); // setflags is always FALSE here 8035 else 8036 R[d] = result; 8037 if setflags then 8038 APSR.N = result<31>; 8039 APSR.Z = IsZeroBit(result); 8040 APSR.C = carry; 8041 // APSR.V unchanged 8042#endif 8043 8044 bool success = false; 8045 8046 if (ConditionPassed(opcode)) 8047 { 8048 uint32_t Rd, Rn; 8049 uint32_t imm32; // the immediate value to be ORed to the value obtained from Rn 8050 bool setflags; 8051 uint32_t carry; // the carry bit after ARM/Thumb Expand operation 8052 switch (encoding) 8053 { 8054 case eEncodingT1: 8055 Rd = Bits32(opcode, 11, 8); 8056 Rn = Bits32(opcode, 19, 16); 8057 setflags = BitIsSet(opcode, 20); 8058 imm32 = ThumbExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C) 8059 // if Rd == '1111' && S == '1' then SEE TEQ (immediate); 8060 if (Rd == 15 && setflags) 8061 return EmulateTEQImm (opcode, eEncodingT1); 8062 if (Rd == 13 || (Rd == 15 && !setflags) || BadReg(Rn)) 8063 return false; 8064 break; 8065 case eEncodingA1: 8066 Rd = Bits32(opcode, 15, 12); 8067 Rn = Bits32(opcode, 19, 16); 8068 setflags = BitIsSet(opcode, 20); 8069 imm32 = ARMExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ARMExpandImm(imm12, APSR.C) 8070 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions; 8071 // TODO: Emulate SUBS PC, LR and related instructions. 8072 if (Rd == 15 && setflags) 8073 return false; 8074 break; 8075 default: 8076 return false; 8077 } 8078 8079 // Read the first operand. 8080 uint32_t val1 = ReadCoreReg(Rn, &success); 8081 if (!success) 8082 return false; 8083 8084 uint32_t result = val1 ^ imm32; 8085 8086 EmulateInstruction::Context context; 8087 context.type = EmulateInstruction::eContextImmediate; 8088 context.SetNoArgs (); 8089 8090 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry)) 8091 return false; 8092 } 8093 return true; 8094} 8095 8096// Bitwise Exclusive OR (register) performs a bitwise exclusive OR of a register value and an 8097// optionally-shifted register value, and writes the result to the destination register. 8098// It can optionally update the condition flags based on the result. 8099bool 8100EmulateInstructionARM::EmulateEORReg (const uint32_t opcode, const ARMEncoding encoding) 8101{ 8102#if 0 8103 // ARM pseudo code... 8104 if ConditionPassed() then 8105 EncodingSpecificOperations(); 8106 (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C); 8107 result = R[n] EOR shifted; 8108 if d == 15 then // Can only occur for ARM encoding 8109 ALUWritePC(result); // setflags is always FALSE here 8110 else 8111 R[d] = result; 8112 if setflags then 8113 APSR.N = result<31>; 8114 APSR.Z = IsZeroBit(result); 8115 APSR.C = carry; 8116 // APSR.V unchanged 8117#endif 8118 8119 bool success = false; 8120 8121 if (ConditionPassed(opcode)) 8122 { 8123 uint32_t Rd, Rn, Rm; 8124 ARM_ShifterType shift_t; 8125 uint32_t shift_n; // the shift applied to the value read from Rm 8126 bool setflags; 8127 uint32_t carry; 8128 switch (encoding) 8129 { 8130 case eEncodingT1: 8131 Rd = Rn = Bits32(opcode, 2, 0); 8132 Rm = Bits32(opcode, 5, 3); 8133 setflags = !InITBlock(); 8134 shift_t = SRType_LSL; 8135 shift_n = 0; 8136 break; 8137 case eEncodingT2: 8138 Rd = Bits32(opcode, 11, 8); 8139 Rn = Bits32(opcode, 19, 16); 8140 Rm = Bits32(opcode, 3, 0); 8141 setflags = BitIsSet(opcode, 20); 8142 shift_n = DecodeImmShiftThumb(opcode, shift_t); 8143 // if Rd == '1111' && S == '1' then SEE TEQ (register); 8144 if (Rd == 15 && setflags) 8145 return EmulateTEQReg (opcode, eEncodingT1); 8146 if (Rd == 13 || (Rd == 15 && !setflags) || BadReg(Rn) || BadReg(Rm)) 8147 return false; 8148 break; 8149 case eEncodingA1: 8150 Rd = Bits32(opcode, 15, 12); 8151 Rn = Bits32(opcode, 19, 16); 8152 Rm = Bits32(opcode, 3, 0); 8153 setflags = BitIsSet(opcode, 20); 8154 shift_n = DecodeImmShiftARM(opcode, shift_t); 8155 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions; 8156 // TODO: Emulate SUBS PC, LR and related instructions. 8157 if (Rd == 15 && setflags) 8158 return false; 8159 break; 8160 default: 8161 return false; 8162 } 8163 8164 // Read the first operand. 8165 uint32_t val1 = ReadCoreReg(Rn, &success); 8166 if (!success) 8167 return false; 8168 8169 // Read the second operand. 8170 uint32_t val2 = ReadCoreReg(Rm, &success); 8171 if (!success) 8172 return false; 8173 8174 uint32_t shifted = Shift_C(val2, shift_t, shift_n, APSR_C, carry); 8175 uint32_t result = val1 ^ shifted; 8176 8177 EmulateInstruction::Context context; 8178 context.type = EmulateInstruction::eContextImmediate; 8179 context.SetNoArgs (); 8180 8181 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry)) 8182 return false; 8183 } 8184 return true; 8185} 8186 8187// Bitwise OR (immediate) performs a bitwise (inclusive) OR of a register value and an immediate value, and 8188// writes the result to the destination register. It can optionally update the condition flags based 8189// on the result. 8190bool 8191EmulateInstructionARM::EmulateORRImm (const uint32_t opcode, const ARMEncoding encoding) 8192{ 8193#if 0 8194 // ARM pseudo code... 8195 if ConditionPassed() then 8196 EncodingSpecificOperations(); 8197 result = R[n] OR imm32; 8198 if d == 15 then // Can only occur for ARM encoding 8199 ALUWritePC(result); // setflags is always FALSE here 8200 else 8201 R[d] = result; 8202 if setflags then 8203 APSR.N = result<31>; 8204 APSR.Z = IsZeroBit(result); 8205 APSR.C = carry; 8206 // APSR.V unchanged 8207#endif 8208 8209 bool success = false; 8210 8211 if (ConditionPassed(opcode)) 8212 { 8213 uint32_t Rd, Rn; 8214 uint32_t imm32; // the immediate value to be ORed to the value obtained from Rn 8215 bool setflags; 8216 uint32_t carry; // the carry bit after ARM/Thumb Expand operation 8217 switch (encoding) 8218 { 8219 case eEncodingT1: 8220 Rd = Bits32(opcode, 11, 8); 8221 Rn = Bits32(opcode, 19, 16); 8222 setflags = BitIsSet(opcode, 20); 8223 imm32 = ThumbExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C) 8224 // if Rn == '1111' then SEE MOV (immediate); 8225 if (Rn == 15) 8226 return EmulateMOVRdImm (opcode, eEncodingT2); 8227 if (BadReg(Rd) || Rn == 13) 8228 return false; 8229 break; 8230 case eEncodingA1: 8231 Rd = Bits32(opcode, 15, 12); 8232 Rn = Bits32(opcode, 19, 16); 8233 setflags = BitIsSet(opcode, 20); 8234 imm32 = ARMExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ARMExpandImm(imm12, APSR.C) 8235 // TODO: Emulate SUBS PC, LR and related instructions. 8236 if (Rd == 15 && setflags) 8237 return false; 8238 break; 8239 default: 8240 return false; 8241 } 8242 8243 // Read the first operand. 8244 uint32_t val1 = ReadCoreReg(Rn, &success); 8245 if (!success) 8246 return false; 8247 8248 uint32_t result = val1 | imm32; 8249 8250 EmulateInstruction::Context context; 8251 context.type = EmulateInstruction::eContextImmediate; 8252 context.SetNoArgs (); 8253 8254 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry)) 8255 return false; 8256 } 8257 return true; 8258} 8259 8260// Bitwise OR (register) performs a bitwise (inclusive) OR of a register value and an optionally-shifted register 8261// value, and writes the result to the destination register. It can optionally update the condition flags based 8262// on the result. 8263bool 8264EmulateInstructionARM::EmulateORRReg (const uint32_t opcode, const ARMEncoding encoding) 8265{ 8266#if 0 8267 // ARM pseudo code... 8268 if ConditionPassed() then 8269 EncodingSpecificOperations(); 8270 (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C); 8271 result = R[n] OR shifted; 8272 if d == 15 then // Can only occur for ARM encoding 8273 ALUWritePC(result); // setflags is always FALSE here 8274 else 8275 R[d] = result; 8276 if setflags then 8277 APSR.N = result<31>; 8278 APSR.Z = IsZeroBit(result); 8279 APSR.C = carry; 8280 // APSR.V unchanged 8281#endif 8282 8283 bool success = false; 8284 8285 if (ConditionPassed(opcode)) 8286 { 8287 uint32_t Rd, Rn, Rm; 8288 ARM_ShifterType shift_t; 8289 uint32_t shift_n; // the shift applied to the value read from Rm 8290 bool setflags; 8291 uint32_t carry; 8292 switch (encoding) 8293 { 8294 case eEncodingT1: 8295 Rd = Rn = Bits32(opcode, 2, 0); 8296 Rm = Bits32(opcode, 5, 3); 8297 setflags = !InITBlock(); 8298 shift_t = SRType_LSL; 8299 shift_n = 0; 8300 break; 8301 case eEncodingT2: 8302 Rd = Bits32(opcode, 11, 8); 8303 Rn = Bits32(opcode, 19, 16); 8304 Rm = Bits32(opcode, 3, 0); 8305 setflags = BitIsSet(opcode, 20); 8306 shift_n = DecodeImmShiftThumb(opcode, shift_t); 8307 // if Rn == '1111' then SEE MOV (register); 8308 if (Rn == 15) 8309 return EmulateMOVRdRm (opcode, eEncodingT3); 8310 if (BadReg(Rd) || Rn == 13 || BadReg(Rm)) 8311 return false; 8312 break; 8313 case eEncodingA1: 8314 Rd = Bits32(opcode, 15, 12); 8315 Rn = Bits32(opcode, 19, 16); 8316 Rm = Bits32(opcode, 3, 0); 8317 setflags = BitIsSet(opcode, 20); 8318 shift_n = DecodeImmShiftARM(opcode, shift_t); 8319 // TODO: Emulate SUBS PC, LR and related instructions. 8320 if (Rd == 15 && setflags) 8321 return false; 8322 break; 8323 default: 8324 return false; 8325 } 8326 8327 // Read the first operand. 8328 uint32_t val1 = ReadCoreReg(Rn, &success); 8329 if (!success) 8330 return false; 8331 8332 // Read the second operand. 8333 uint32_t val2 = ReadCoreReg(Rm, &success); 8334 if (!success) 8335 return false; 8336 8337 uint32_t shifted = Shift_C(val2, shift_t, shift_n, APSR_C, carry); 8338 uint32_t result = val1 | shifted; 8339 8340 EmulateInstruction::Context context; 8341 context.type = EmulateInstruction::eContextImmediate; 8342 context.SetNoArgs (); 8343 8344 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry)) 8345 return false; 8346 } 8347 return true; 8348} 8349 8350// Reverse Subtract (immediate) subtracts a register value from an immediate value, and writes the result to 8351// the destination register. It can optionally update the condition flags based on the result. 8352bool 8353EmulateInstructionARM::EmulateRSBImm (const uint32_t opcode, const ARMEncoding encoding) 8354{ 8355#if 0 8356 // ARM pseudo code... 8357 if ConditionPassed() then 8358 EncodingSpecificOperations(); 8359 (result, carry, overflow) = AddWithCarry(NOT(R[n]), imm32, '1'); 8360 if d == 15 then // Can only occur for ARM encoding 8361 ALUWritePC(result); // setflags is always FALSE here 8362 else 8363 R[d] = result; 8364 if setflags then 8365 APSR.N = result<31>; 8366 APSR.Z = IsZeroBit(result); 8367 APSR.C = carry; 8368 APSR.V = overflow; 8369#endif 8370 8371 bool success = false; 8372 8373 uint32_t Rd; // the destination register 8374 uint32_t Rn; // the first operand 8375 bool setflags; 8376 uint32_t imm32; // the immediate value to be added to the value obtained from Rn 8377 switch (encoding) { 8378 case eEncodingT1: 8379 Rd = Bits32(opcode, 2, 0); 8380 Rn = Bits32(opcode, 5, 3); 8381 setflags = !InITBlock(); 8382 imm32 = 0; 8383 break; 8384 case eEncodingT2: 8385 Rd = Bits32(opcode, 11, 8); 8386 Rn = Bits32(opcode, 19, 16); 8387 setflags = BitIsSet(opcode, 20); 8388 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8) 8389 if (BadReg(Rd) || BadReg(Rn)) 8390 return false; 8391 break; 8392 case eEncodingA1: 8393 Rd = Bits32(opcode, 15, 12); 8394 Rn = Bits32(opcode, 19, 16); 8395 setflags = BitIsSet(opcode, 20); 8396 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12) 8397 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions; 8398 // TODO: Emulate SUBS PC, LR and related instructions. 8399 if (Rd == 15 && setflags) 8400 return false; 8401 break; 8402 default: 8403 return false; 8404 } 8405 // Read the register value from the operand register Rn. 8406 uint32_t reg_val = ReadCoreReg(Rn, &success); 8407 if (!success) 8408 return false; 8409 8410 AddWithCarryResult res = AddWithCarry(~reg_val, imm32, 1); 8411 8412 EmulateInstruction::Context context; 8413 context.type = EmulateInstruction::eContextImmediate; 8414 context.SetNoArgs (); 8415 8416 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow)) 8417 return false; 8418 8419 return true; 8420} 8421 8422// Reverse Subtract (register) subtracts a register value from an optionally-shifted register value, and writes the 8423// result to the destination register. It can optionally update the condition flags based on the result. 8424bool 8425EmulateInstructionARM::EmulateRSBReg (const uint32_t opcode, const ARMEncoding encoding) 8426{ 8427#if 0 8428 // ARM pseudo code... 8429 if ConditionPassed() then 8430 EncodingSpecificOperations(); 8431 shifted = Shift(R[m], shift_t, shift_n, APSR.C); 8432 (result, carry, overflow) = AddWithCarry(NOT(R[n]), shifted, '1'); 8433 if d == 15 then // Can only occur for ARM encoding 8434 ALUWritePC(result); // setflags is always FALSE here 8435 else 8436 R[d] = result; 8437 if setflags then 8438 APSR.N = result<31>; 8439 APSR.Z = IsZeroBit(result); 8440 APSR.C = carry; 8441 APSR.V = overflow; 8442#endif 8443 8444 bool success = false; 8445 8446 uint32_t Rd; // the destination register 8447 uint32_t Rn; // the first operand 8448 uint32_t Rm; // the second operand 8449 bool setflags; 8450 ARM_ShifterType shift_t; 8451 uint32_t shift_n; // the shift applied to the value read from Rm 8452 switch (encoding) { 8453 case eEncodingT1: 8454 Rd = Bits32(opcode, 11, 8); 8455 Rn = Bits32(opcode, 19, 16); 8456 Rm = Bits32(opcode, 3, 0); 8457 setflags = BitIsSet(opcode, 20); 8458 shift_n = DecodeImmShiftThumb(opcode, shift_t); 8459 // if (BadReg(d) || BadReg(m)) then UNPREDICTABLE; 8460 if (BadReg(Rd) || BadReg(Rn) || BadReg(Rm)) 8461 return false; 8462 break; 8463 case eEncodingA1: 8464 Rd = Bits32(opcode, 15, 12); 8465 Rn = Bits32(opcode, 19, 16); 8466 Rm = Bits32(opcode, 3, 0); 8467 setflags = BitIsSet(opcode, 20); 8468 shift_n = DecodeImmShiftARM(opcode, shift_t); 8469 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions; 8470 // TODO: Emulate SUBS PC, LR and related instructions. 8471 if (Rd == 15 && setflags) 8472 return false; 8473 break; 8474 default: 8475 return false; 8476 } 8477 // Read the register value from register Rn. 8478 uint32_t val1 = ReadCoreReg(Rn, &success); 8479 if (!success) 8480 return false; 8481 8482 // Read the register value from register Rm. 8483 uint32_t val2 = ReadCoreReg(Rm, &success); 8484 if (!success) 8485 return false; 8486 8487 uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C); 8488 AddWithCarryResult res = AddWithCarry(~val1, shifted, 1); 8489 8490 EmulateInstruction::Context context; 8491 context.type = EmulateInstruction::eContextImmediate; 8492 context.SetNoArgs(); 8493 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow)) 8494 return false; 8495 8496 return true; 8497} 8498 8499// Reverse Subtract with Carry (immediate) subtracts a register value and the value of NOT (Carry flag) from 8500// an immediate value, and writes the result to the destination register. It can optionally update the condition 8501// flags based on the result. 8502bool 8503EmulateInstructionARM::EmulateRSCImm (const uint32_t opcode, const ARMEncoding encoding) 8504{ 8505#if 0 8506 // ARM pseudo code... 8507 if ConditionPassed() then 8508 EncodingSpecificOperations(); 8509 (result, carry, overflow) = AddWithCarry(NOT(R[n]), imm32, APSR.C); 8510 if d == 15 then 8511 ALUWritePC(result); // setflags is always FALSE here 8512 else 8513 R[d] = result; 8514 if setflags then 8515 APSR.N = result<31>; 8516 APSR.Z = IsZeroBit(result); 8517 APSR.C = carry; 8518 APSR.V = overflow; 8519#endif 8520 8521 bool success = false; 8522 8523 uint32_t Rd; // the destination register 8524 uint32_t Rn; // the first operand 8525 bool setflags; 8526 uint32_t imm32; // the immediate value to be added to the value obtained from Rn 8527 switch (encoding) { 8528 case eEncodingA1: 8529 Rd = Bits32(opcode, 15, 12); 8530 Rn = Bits32(opcode, 19, 16); 8531 setflags = BitIsSet(opcode, 20); 8532 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12) 8533 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions; 8534 // TODO: Emulate SUBS PC, LR and related instructions. 8535 if (Rd == 15 && setflags) 8536 return false; 8537 break; 8538 default: 8539 return false; 8540 } 8541 // Read the register value from the operand register Rn. 8542 uint32_t reg_val = ReadCoreReg(Rn, &success); 8543 if (!success) 8544 return false; 8545 8546 AddWithCarryResult res = AddWithCarry(~reg_val, imm32, APSR_C); 8547 8548 EmulateInstruction::Context context; 8549 context.type = EmulateInstruction::eContextImmediate; 8550 context.SetNoArgs (); 8551 8552 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow)) 8553 return false; 8554 8555 return true; 8556} 8557 8558// Reverse Subtract with Carry (register) subtracts a register value and the value of NOT (Carry flag) from an 8559// optionally-shifted register value, and writes the result to the destination register. It can optionally update the 8560// condition flags based on the result. 8561bool 8562EmulateInstructionARM::EmulateRSCReg (const uint32_t opcode, const ARMEncoding encoding) 8563{ 8564#if 0 8565 // ARM pseudo code... 8566 if ConditionPassed() then 8567 EncodingSpecificOperations(); 8568 shifted = Shift(R[m], shift_t, shift_n, APSR.C); 8569 (result, carry, overflow) = AddWithCarry(NOT(R[n]), shifted, APSR.C); 8570 if d == 15 then 8571 ALUWritePC(result); // setflags is always FALSE here 8572 else 8573 R[d] = result; 8574 if setflags then 8575 APSR.N = result<31>; 8576 APSR.Z = IsZeroBit(result); 8577 APSR.C = carry; 8578 APSR.V = overflow; 8579#endif 8580 8581 bool success = false; 8582 8583 uint32_t Rd; // the destination register 8584 uint32_t Rn; // the first operand 8585 uint32_t Rm; // the second operand 8586 bool setflags; 8587 ARM_ShifterType shift_t; 8588 uint32_t shift_n; // the shift applied to the value read from Rm 8589 switch (encoding) { 8590 case eEncodingA1: 8591 Rd = Bits32(opcode, 15, 12); 8592 Rn = Bits32(opcode, 19, 16); 8593 Rm = Bits32(opcode, 3, 0); 8594 setflags = BitIsSet(opcode, 20); 8595 shift_n = DecodeImmShiftARM(opcode, shift_t); 8596 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions; 8597 // TODO: Emulate SUBS PC, LR and related instructions. 8598 if (Rd == 15 && setflags) 8599 return false; 8600 break; 8601 default: 8602 return false; 8603 } 8604 // Read the register value from register Rn. 8605 uint32_t val1 = ReadCoreReg(Rn, &success); 8606 if (!success) 8607 return false; 8608 8609 // Read the register value from register Rm. 8610 uint32_t val2 = ReadCoreReg(Rm, &success); 8611 if (!success) 8612 return false; 8613 8614 uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C); 8615 AddWithCarryResult res = AddWithCarry(~val1, shifted, APSR_C); 8616 8617 EmulateInstruction::Context context; 8618 context.type = EmulateInstruction::eContextImmediate; 8619 context.SetNoArgs(); 8620 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow)) 8621 return false; 8622 8623 return true; 8624} 8625 8626// Subtract with Carry (immediate) subtracts an immediate value and the value of 8627// NOT (Carry flag) from a register value, and writes the result to the destination register. 8628// It can optionally update the condition flags based on the result. 8629bool 8630EmulateInstructionARM::EmulateSBCImm (const uint32_t opcode, const ARMEncoding encoding) 8631{ 8632#if 0 8633 // ARM pseudo code... 8634 if ConditionPassed() then 8635 EncodingSpecificOperations(); 8636 (result, carry, overflow) = AddWithCarry(R[n], NOT(imm32), APSR.C); 8637 if d == 15 then // Can only occur for ARM encoding 8638 ALUWritePC(result); // setflags is always FALSE here 8639 else 8640 R[d] = result; 8641 if setflags then 8642 APSR.N = result<31>; 8643 APSR.Z = IsZeroBit(result); 8644 APSR.C = carry; 8645 APSR.V = overflow; 8646#endif 8647 8648 bool success = false; 8649 8650 uint32_t Rd; // the destination register 8651 uint32_t Rn; // the first operand 8652 bool setflags; 8653 uint32_t imm32; // the immediate value to be added to the value obtained from Rn 8654 switch (encoding) { 8655 case eEncodingT1: 8656 Rd = Bits32(opcode, 11, 8); 8657 Rn = Bits32(opcode, 19, 16); 8658 setflags = BitIsSet(opcode, 20); 8659 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8) 8660 if (BadReg(Rd) || BadReg(Rn)) 8661 return false; 8662 break; 8663 case eEncodingA1: 8664 Rd = Bits32(opcode, 15, 12); 8665 Rn = Bits32(opcode, 19, 16); 8666 setflags = BitIsSet(opcode, 20); 8667 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12) 8668 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions; 8669 // TODO: Emulate SUBS PC, LR and related instructions. 8670 if (Rd == 15 && setflags) 8671 return false; 8672 break; 8673 default: 8674 return false; 8675 } 8676 // Read the register value from the operand register Rn. 8677 uint32_t reg_val = ReadCoreReg(Rn, &success); 8678 if (!success) 8679 return false; 8680 8681 AddWithCarryResult res = AddWithCarry(reg_val, ~imm32, APSR_C); 8682 8683 EmulateInstruction::Context context; 8684 context.type = EmulateInstruction::eContextImmediate; 8685 context.SetNoArgs (); 8686 8687 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow)) 8688 return false; 8689 8690 return true; 8691} 8692 8693// Subtract with Carry (register) subtracts an optionally-shifted register value and the value of 8694// NOT (Carry flag) from a register value, and writes the result to the destination register. 8695// It can optionally update the condition flags based on the result. 8696bool 8697EmulateInstructionARM::EmulateSBCReg (const uint32_t opcode, const ARMEncoding encoding) 8698{ 8699#if 0 8700 // ARM pseudo code... 8701 if ConditionPassed() then 8702 EncodingSpecificOperations(); 8703 shifted = Shift(R[m], shift_t, shift_n, APSR.C); 8704 (result, carry, overflow) = AddWithCarry(R[n], NOT(shifted), APSR.C); 8705 if d == 15 then // Can only occur for ARM encoding 8706 ALUWritePC(result); // setflags is always FALSE here 8707 else 8708 R[d] = result; 8709 if setflags then 8710 APSR.N = result<31>; 8711 APSR.Z = IsZeroBit(result); 8712 APSR.C = carry; 8713 APSR.V = overflow; 8714#endif 8715 8716 bool success = false; 8717 8718 uint32_t Rd; // the destination register 8719 uint32_t Rn; // the first operand 8720 uint32_t Rm; // the second operand 8721 bool setflags; 8722 ARM_ShifterType shift_t; 8723 uint32_t shift_n; // the shift applied to the value read from Rm 8724 switch (encoding) { 8725 case eEncodingT1: 8726 Rd = Rn = Bits32(opcode, 2, 0); 8727 Rm = Bits32(opcode, 5, 3); 8728 setflags = !InITBlock(); 8729 shift_t = SRType_LSL; 8730 shift_n = 0; 8731 break; 8732 case eEncodingT2: 8733 Rd = Bits32(opcode, 11, 8); 8734 Rn = Bits32(opcode, 19, 16); 8735 Rm = Bits32(opcode, 3, 0); 8736 setflags = BitIsSet(opcode, 20); 8737 shift_n = DecodeImmShiftThumb(opcode, shift_t); 8738 if (BadReg(Rd) || BadReg(Rn) || BadReg(Rm)) 8739 return false; 8740 break; 8741 case eEncodingA1: 8742 Rd = Bits32(opcode, 15, 12); 8743 Rn = Bits32(opcode, 19, 16); 8744 Rm = Bits32(opcode, 3, 0); 8745 setflags = BitIsSet(opcode, 20); 8746 shift_n = DecodeImmShiftARM(opcode, shift_t); 8747 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions; 8748 // TODO: Emulate SUBS PC, LR and related instructions. 8749 if (Rd == 15 && setflags) 8750 return false; 8751 break; 8752 default: 8753 return false; 8754 } 8755 // Read the register value from register Rn. 8756 uint32_t val1 = ReadCoreReg(Rn, &success); 8757 if (!success) 8758 return false; 8759 8760 // Read the register value from register Rm. 8761 uint32_t val2 = ReadCoreReg(Rm, &success); 8762 if (!success) 8763 return false; 8764 8765 uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C); 8766 AddWithCarryResult res = AddWithCarry(val1, ~shifted, APSR_C); 8767 8768 EmulateInstruction::Context context; 8769 context.type = EmulateInstruction::eContextImmediate; 8770 context.SetNoArgs(); 8771 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow)) 8772 return false; 8773 8774 return true; 8775} 8776 8777// This instruction subtracts an immediate value from a register value, and writes the result 8778// to the destination register. It can optionally update the condition flags based on the result. 8779bool 8780EmulateInstructionARM::EmulateSUBImmThumb (const uint32_t opcode, const ARMEncoding encoding) 8781{ 8782#if 0 8783 // ARM pseudo code... 8784 if ConditionPassed() then 8785 EncodingSpecificOperations(); 8786 (result, carry, overflow) = AddWithCarry(R[n], NOT(imm32), '1'); 8787 R[d] = result; 8788 if setflags then 8789 APSR.N = result<31>; 8790 APSR.Z = IsZeroBit(result); 8791 APSR.C = carry; 8792 APSR.V = overflow; 8793#endif 8794 8795 bool success = false; 8796 8797 uint32_t Rd; // the destination register 8798 uint32_t Rn; // the first operand 8799 bool setflags; 8800 uint32_t imm32; // the immediate value to be subtracted from the value obtained from Rn 8801 switch (encoding) { 8802 case eEncodingT1: 8803 Rd = Bits32(opcode, 2, 0); 8804 Rn = Bits32(opcode, 5, 3); 8805 setflags = !InITBlock(); 8806 imm32 = Bits32(opcode, 8, 6); // imm32 = ZeroExtend(imm3, 32) 8807 break; 8808 case eEncodingT2: 8809 Rd = Rn = Bits32(opcode, 10, 8); 8810 setflags = !InITBlock(); 8811 imm32 = Bits32(opcode, 7, 0); // imm32 = ZeroExtend(imm8, 32) 8812 break; 8813 case eEncodingT3: 8814 Rd = Bits32(opcode, 11, 8); 8815 Rn = Bits32(opcode, 19, 16); 8816 setflags = BitIsSet(opcode, 20); 8817 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8) 8818 8819 // if Rd == '1111' && S == '1' then SEE CMP (immediate); 8820 if (Rd == 15 && setflags) 8821 return EmulateCMPImm (opcode, eEncodingT2); 8822 8823 // if Rn == '1101' then SEE SUB (SP minus immediate); 8824 if (Rn == 13) 8825 return EmulateSUBSPImm (opcode, eEncodingT2); 8826 8827 // if d == 13 || (d == 15 && S == '0') || n == 15 then UNPREDICTABLE; 8828 if (Rd == 13 || (Rd == 15 && !setflags) || Rn == 15) 8829 return false; 8830 break; 8831 case eEncodingT4: 8832 Rd = Bits32(opcode, 11, 8); 8833 Rn = Bits32(opcode, 19, 16); 8834 setflags = BitIsSet(opcode, 20); 8835 imm32 = ThumbImm12(opcode); // imm32 = ZeroExtend(i:imm3:imm8, 32) 8836 8837 // if Rn == '1111' then SEE ADR; 8838 if (Rn == 15) 8839 return EmulateADR (opcode, eEncodingT2); 8840 8841 // if Rn == '1101' then SEE SUB (SP minus immediate); 8842 if (Rn == 13) 8843 return EmulateSUBSPImm (opcode, eEncodingT3); 8844 8845 if (BadReg(Rd)) 8846 return false; 8847 break; 8848 default: 8849 return false; 8850 } 8851 // Read the register value from the operand register Rn. 8852 uint32_t reg_val = ReadCoreReg(Rn, &success); 8853 if (!success) 8854 return false; 8855 8856 AddWithCarryResult res = AddWithCarry(reg_val, ~imm32, 1); 8857 8858 EmulateInstruction::Context context; 8859 context.type = EmulateInstruction::eContextImmediate; 8860 context.SetNoArgs (); 8861 8862 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow)) 8863 return false; 8864 8865 return true; 8866} 8867 8868// This instruction subtracts an immediate value from a register value, and writes the result 8869// to the destination register. It can optionally update the condition flags based on the result. 8870bool 8871EmulateInstructionARM::EmulateSUBImmARM (const uint32_t opcode, const ARMEncoding encoding) 8872{ 8873#if 0 8874 // ARM pseudo code... 8875 if ConditionPassed() then 8876 EncodingSpecificOperations(); 8877 (result, carry, overflow) = AddWithCarry(R[n], NOT(imm32), '1'); 8878 if d == 15 then 8879 ALUWritePC(result); // setflags is always FALSE here 8880 else 8881 R[d] = result; 8882 if setflags then 8883 APSR.N = result<31>; 8884 APSR.Z = IsZeroBit(result); 8885 APSR.C = carry; 8886 APSR.V = overflow; 8887#endif 8888 8889 bool success = false; 8890 8891 uint32_t Rd; // the destination register 8892 uint32_t Rn; // the first operand 8893 bool setflags; 8894 uint32_t imm32; // the immediate value to be subtracted from the value obtained from Rn 8895 switch (encoding) { 8896 case eEncodingA1: 8897 Rd = Bits32(opcode, 15, 12); 8898 Rn = Bits32(opcode, 19, 16); 8899 setflags = BitIsSet(opcode, 20); 8900 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12) 8901 8902 // if Rn == '1111' && S == '0' then SEE ADR; 8903 if (Rn == 15 && !setflags) 8904 return EmulateADR (opcode, eEncodingA2); 8905 8906 // if Rn == '1101' then SEE SUB (SP minus immediate); 8907 if (Rn == 13) 8908 return EmulateSUBSPImm (opcode, eEncodingA1); 8909 8910 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions; 8911 // TODO: Emulate SUBS PC, LR and related instructions. 8912 if (Rd == 15 && setflags) 8913 return false; 8914 break; 8915 default: 8916 return false; 8917 } 8918 // Read the register value from the operand register Rn. 8919 uint32_t reg_val = ReadCoreReg(Rn, &success); 8920 if (!success) 8921 return false; 8922 8923 AddWithCarryResult res = AddWithCarry(reg_val, ~imm32, 1); 8924 8925 EmulateInstruction::Context context; 8926 context.type = EmulateInstruction::eContextImmediate; 8927 context.SetNoArgs (); 8928 8929 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow)) 8930 return false; 8931 8932 return true; 8933} 8934 8935// Test Equivalence (immediate) performs a bitwise exclusive OR operation on a register value and an 8936// immediate value. It updates the condition flags based on the result, and discards the result. 8937bool 8938EmulateInstructionARM::EmulateTEQImm (const uint32_t opcode, const ARMEncoding encoding) 8939{ 8940#if 0 8941 // ARM pseudo code... 8942 if ConditionPassed() then 8943 EncodingSpecificOperations(); 8944 result = R[n] EOR imm32; 8945 APSR.N = result<31>; 8946 APSR.Z = IsZeroBit(result); 8947 APSR.C = carry; 8948 // APSR.V unchanged 8949#endif 8950 8951 bool success = false; 8952 8953 if (ConditionPassed(opcode)) 8954 { 8955 uint32_t Rn; 8956 uint32_t imm32; // the immediate value to be ANDed to the value obtained from Rn 8957 uint32_t carry; // the carry bit after ARM/Thumb Expand operation 8958 switch (encoding) 8959 { 8960 case eEncodingT1: 8961 Rn = Bits32(opcode, 19, 16); 8962 imm32 = ThumbExpandImm_C (opcode, APSR_C, carry); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C) 8963 if (BadReg(Rn)) 8964 return false; 8965 break; 8966 case eEncodingA1: 8967 Rn = Bits32(opcode, 19, 16); 8968 imm32 = ARMExpandImm_C (opcode, APSR_C, carry); // (imm32, carry) = ARMExpandImm(imm12, APSR.C) 8969 break; 8970 default: 8971 return false; 8972 } 8973 8974 // Read the first operand. 8975 uint32_t val1 = ReadCoreReg(Rn, &success); 8976 if (!success) 8977 return false; 8978 8979 uint32_t result = val1 ^ imm32; 8980 8981 EmulateInstruction::Context context; 8982 context.type = EmulateInstruction::eContextImmediate; 8983 context.SetNoArgs (); 8984 8985 if (!WriteFlags(context, result, carry)) 8986 return false; 8987 } 8988 return true; 8989} 8990 8991// Test Equivalence (register) performs a bitwise exclusive OR operation on a register value and an 8992// optionally-shifted register value. It updates the condition flags based on the result, and discards 8993// the result. 8994bool 8995EmulateInstructionARM::EmulateTEQReg (const uint32_t opcode, const ARMEncoding encoding) 8996{ 8997#if 0 8998 // ARM pseudo code... 8999 if ConditionPassed() then 9000 EncodingSpecificOperations(); 9001 (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C); 9002 result = R[n] EOR shifted; 9003 APSR.N = result<31>; 9004 APSR.Z = IsZeroBit(result); 9005 APSR.C = carry; 9006 // APSR.V unchanged 9007#endif 9008 9009 bool success = false; 9010 9011 if (ConditionPassed(opcode)) 9012 { 9013 uint32_t Rn, Rm; 9014 ARM_ShifterType shift_t; 9015 uint32_t shift_n; // the shift applied to the value read from Rm 9016 uint32_t carry; 9017 switch (encoding) 9018 { 9019 case eEncodingT1: 9020 Rn = Bits32(opcode, 19, 16); 9021 Rm = Bits32(opcode, 3, 0); 9022 shift_n = DecodeImmShiftThumb(opcode, shift_t); 9023 if (BadReg(Rn) || BadReg(Rm)) 9024 return false; 9025 break; 9026 case eEncodingA1: 9027 Rn = Bits32(opcode, 19, 16); 9028 Rm = Bits32(opcode, 3, 0); 9029 shift_n = DecodeImmShiftARM(opcode, shift_t); 9030 break; 9031 default: 9032 return false; 9033 } 9034 9035 // Read the first operand. 9036 uint32_t val1 = ReadCoreReg(Rn, &success); 9037 if (!success) 9038 return false; 9039 9040 // Read the second operand. 9041 uint32_t val2 = ReadCoreReg(Rm, &success); 9042 if (!success) 9043 return false; 9044 9045 uint32_t shifted = Shift_C(val2, shift_t, shift_n, APSR_C, carry); 9046 uint32_t result = val1 ^ shifted; 9047 9048 EmulateInstruction::Context context; 9049 context.type = EmulateInstruction::eContextImmediate; 9050 context.SetNoArgs (); 9051 9052 if (!WriteFlags(context, result, carry)) 9053 return false; 9054 } 9055 return true; 9056} 9057 9058// Test (immediate) performs a bitwise AND operation on a register value and an immediate value. 9059// It updates the condition flags based on the result, and discards the result. 9060bool 9061EmulateInstructionARM::EmulateTSTImm (const uint32_t opcode, const ARMEncoding encoding) 9062{ 9063#if 0 9064 // ARM pseudo code... 9065 if ConditionPassed() then 9066 EncodingSpecificOperations(); 9067 result = R[n] AND imm32; 9068 APSR.N = result<31>; 9069 APSR.Z = IsZeroBit(result); 9070 APSR.C = carry; 9071 // APSR.V unchanged 9072#endif 9073 9074 bool success = false; 9075 9076 if (ConditionPassed(opcode)) 9077 { 9078 uint32_t Rn; 9079 uint32_t imm32; // the immediate value to be ANDed to the value obtained from Rn 9080 uint32_t carry; // the carry bit after ARM/Thumb Expand operation 9081 switch (encoding) 9082 { 9083 case eEncodingT1: 9084 Rn = Bits32(opcode, 19, 16); 9085 imm32 = ThumbExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C) 9086 if (BadReg(Rn)) 9087 return false; 9088 break; 9089 case eEncodingA1: 9090 Rn = Bits32(opcode, 19, 16); 9091 imm32 = ARMExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ARMExpandImm(imm12, APSR.C) 9092 break; 9093 default: 9094 return false; 9095 } 9096 9097 // Read the first operand. 9098 uint32_t val1 = ReadCoreReg(Rn, &success); 9099 if (!success) 9100 return false; 9101 9102 uint32_t result = val1 & imm32; 9103 9104 EmulateInstruction::Context context; 9105 context.type = EmulateInstruction::eContextImmediate; 9106 context.SetNoArgs (); 9107 9108 if (!WriteFlags(context, result, carry)) 9109 return false; 9110 } 9111 return true; 9112} 9113 9114// Test (register) performs a bitwise AND operation on a register value and an optionally-shifted register value. 9115// It updates the condition flags based on the result, and discards the result. 9116bool 9117EmulateInstructionARM::EmulateTSTReg (const uint32_t opcode, const ARMEncoding encoding) 9118{ 9119#if 0 9120 // ARM pseudo code... 9121 if ConditionPassed() then 9122 EncodingSpecificOperations(); 9123 (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C); 9124 result = R[n] AND shifted; 9125 APSR.N = result<31>; 9126 APSR.Z = IsZeroBit(result); 9127 APSR.C = carry; 9128 // APSR.V unchanged 9129#endif 9130 9131 bool success = false; 9132 9133 if (ConditionPassed(opcode)) 9134 { 9135 uint32_t Rn, Rm; 9136 ARM_ShifterType shift_t; 9137 uint32_t shift_n; // the shift applied to the value read from Rm 9138 uint32_t carry; 9139 switch (encoding) 9140 { 9141 case eEncodingT1: 9142 Rn = Bits32(opcode, 2, 0); 9143 Rm = Bits32(opcode, 5, 3); 9144 shift_t = SRType_LSL; 9145 shift_n = 0; 9146 break; 9147 case eEncodingT2: 9148 Rn = Bits32(opcode, 19, 16); 9149 Rm = Bits32(opcode, 3, 0); 9150 shift_n = DecodeImmShiftThumb(opcode, shift_t); 9151 if (BadReg(Rn) || BadReg(Rm)) 9152 return false; 9153 break; 9154 case eEncodingA1: 9155 Rn = Bits32(opcode, 19, 16); 9156 Rm = Bits32(opcode, 3, 0); 9157 shift_n = DecodeImmShiftARM(opcode, shift_t); 9158 break; 9159 default: 9160 return false; 9161 } 9162 9163 // Read the first operand. 9164 uint32_t val1 = ReadCoreReg(Rn, &success); 9165 if (!success) 9166 return false; 9167 9168 // Read the second operand. 9169 uint32_t val2 = ReadCoreReg(Rm, &success); 9170 if (!success) 9171 return false; 9172 9173 uint32_t shifted = Shift_C(val2, shift_t, shift_n, APSR_C, carry); 9174 uint32_t result = val1 & shifted; 9175 9176 EmulateInstruction::Context context; 9177 context.type = EmulateInstruction::eContextImmediate; 9178 context.SetNoArgs (); 9179 9180 if (!WriteFlags(context, result, carry)) 9181 return false; 9182 } 9183 return true; 9184} 9185 9186// A8.6.216 SUB (SP minus register) 9187bool 9188EmulateInstructionARM::EmulateSUBSPReg (const uint32_t opcode, const ARMEncoding encoding) 9189{ 9190#if 0 9191 if ConditionPassed() then 9192 EncodingSpecificOperations(); 9193 shifted = Shift(R[m], shift_t, shift_n, APSR.C); 9194 (result, carry, overflow) = AddWithCarry(SP, NOT(shifted), ‘1’); 9195 if d == 15 then // Can only occur for ARM encoding 9196 ALUWritePC(result); // setflags is always FALSE here 9197 else 9198 R[d] = result; 9199 if setflags then 9200 APSR.N = result<31>; 9201 APSR.Z = IsZeroBit(result); 9202 APSR.C = carry; 9203 APSR.V = overflow; 9204#endif 9205 9206 bool success = false; 9207 9208 if (ConditionPassed(opcode)) 9209 { 9210 uint32_t d; 9211 uint32_t m; 9212 bool setflags; 9213 ARM_ShifterType shift_t; 9214 uint32_t shift_n; 9215 9216 switch (encoding) 9217 { 9218 case eEncodingT1: 9219 // d = UInt(Rd); m = UInt(Rm); setflags = (S == ‘1’); 9220 d = Bits32 (opcode, 11, 8); 9221 m = Bits32 (opcode, 3, 0); 9222 setflags = BitIsSet (opcode, 20); 9223 9224 // (shift_t, shift_n) = DecodeImmShift(type, imm3:imm2); 9225 shift_n = DecodeImmShiftThumb (opcode, shift_t); 9226 9227 // if d == 13 && (shift_t != SRType_LSL || shift_n > 3) then UNPREDICTABLE; 9228 if ((d == 13) && ((shift_t != SRType_LSL) || (shift_n > 3))) 9229 return false; 9230 9231 // if d == 15 || BadReg(m) then UNPREDICTABLE; 9232 if ((d == 15) || BadReg (m)) 9233 return false; 9234 break; 9235 9236 case eEncodingA1: 9237 // if Rd == ‘1111’ && S == ‘1’ then SEE SUBS PC, LR and related instructions; 9238 // d = UInt(Rd); m = UInt(Rm); setflags = (S == ‘1’); 9239 d = Bits32 (opcode, 15, 12); 9240 m = Bits32 (opcode, 3, 0); 9241 setflags = BitIsSet (opcode, 20); 9242 9243 // (shift_t, shift_n) = DecodeImmShift(type, imm5); 9244 shift_n = DecodeImmShiftARM (opcode, shift_t); 9245 break; 9246 9247 default: 9248 return false; 9249 } 9250 9251 // shifted = Shift(R[m], shift_t, shift_n, APSR.C); 9252 uint32_t Rm = ReadCoreReg (m, &success); 9253 if (!success) 9254 return false; 9255 9256 uint32_t shifted = Shift (Rm, shift_t, shift_n, APSR_C); 9257 9258 // (result, carry, overflow) = AddWithCarry(SP, NOT(shifted), ‘1’); 9259 uint32_t sp_val = ReadCoreReg (SP_REG, &success); 9260 if (!success) 9261 return false; 9262 9263 AddWithCarryResult res = AddWithCarry (sp_val, ~shifted, 1); 9264 9265 EmulateInstruction::Context context; 9266 context.type = eContextSubtraction; 9267 Register sp_reg; 9268 sp_reg.SetRegister (eRegisterKindDWARF, dwarf_sp); 9269 Register dwarf_reg; 9270 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + m); 9271 context.SetRegisterRegisterOperands (sp_reg, dwarf_reg); 9272 9273 if (!WriteCoreRegOptionalFlags(context, res.result, dwarf_r0 + d, setflags, res.carry_out, res.overflow)) 9274 return false; 9275 } 9276 return true; 9277} 9278 9279 9280// A8.6.7 ADD (register-shifted register) 9281bool 9282EmulateInstructionARM::EmulateADDRegShift (const uint32_t opcode, const ARMEncoding encoding) 9283{ 9284#if 0 9285 if ConditionPassed() then 9286 EncodingSpecificOperations(); 9287 shift_n = UInt(R[s]<7:0>); 9288 shifted = Shift(R[m], shift_t, shift_n, APSR.C); 9289 (result, carry, overflow) = AddWithCarry(R[n], shifted, ‘0’); 9290 R[d] = result; 9291 if setflags then 9292 APSR.N = result<31>; 9293 APSR.Z = IsZeroBit(result); 9294 APSR.C = carry; 9295 APSR.V = overflow; 9296#endif 9297 9298 bool success = false; 9299 9300 if (ConditionPassed(opcode)) 9301 { 9302 uint32_t d; 9303 uint32_t n; 9304 uint32_t m; 9305 uint32_t s; 9306 bool setflags; 9307 ARM_ShifterType shift_t; 9308 9309 switch (encoding) 9310 { 9311 case eEncodingA1: 9312 // d = UInt(Rd); n = UInt(Rn); m = UInt(Rm); s = UInt(Rs); 9313 d = Bits32 (opcode, 15, 12); 9314 n = Bits32 (opcode, 19, 16); 9315 m = Bits32 (opcode, 3, 0); 9316 s = Bits32 (opcode, 11, 8); 9317 9318 // setflags = (S == ‘1’); shift_t = DecodeRegShift(type); 9319 setflags = BitIsSet (opcode, 20); 9320 shift_t = DecodeRegShift (Bits32 (opcode, 6, 5)); 9321 9322 // if d == 15 || n == 15 || m == 15 || s == 15 then UNPREDICTABLE; 9323 if ((d == 15) || (m == 15) || (m == 15) || (s == 15)) 9324 return false; 9325 break; 9326 9327 default: 9328 return false; 9329 } 9330 9331 // shift_n = UInt(R[s]<7:0>); 9332 uint32_t Rs = ReadCoreReg (s, &success); 9333 if (!success) 9334 return false; 9335 9336 uint32_t shift_n = Bits32 (Rs, 7, 0); 9337 9338 // shifted = Shift(R[m], shift_t, shift_n, APSR.C); 9339 uint32_t Rm = ReadCoreReg (m, &success); 9340 if (!success) 9341 return false; 9342 9343 uint32_t shifted = Shift (Rm, shift_t, shift_n, APSR_C); 9344 9345 // (result, carry, overflow) = AddWithCarry(R[n], shifted, ‘0’); 9346 uint32_t Rn = ReadCoreReg (n, &success); 9347 if (!success) 9348 return false; 9349 9350 AddWithCarryResult res = AddWithCarry (Rn, shifted, 0); 9351 9352 // R[d] = result; 9353 EmulateInstruction::Context context; 9354 context.type = eContextAddition; 9355 Register reg_n; 9356 reg_n.SetRegister (eRegisterKindDWARF, dwarf_r0 +n); 9357 Register reg_m; 9358 reg_m.SetRegister (eRegisterKindDWARF, dwarf_r0 + m); 9359 9360 context.SetRegisterRegisterOperands (reg_n, reg_m); 9361 9362 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + d, res.result)) 9363 return false; 9364 9365 // if setflags then 9366 // APSR.N = result<31>; 9367 // APSR.Z = IsZeroBit(result); 9368 // APSR.C = carry; 9369 // APSR.V = overflow; 9370 if (setflags) 9371 return WriteFlags (context, res.result, res.carry_out, res.overflow); 9372 } 9373 return true; 9374} 9375 9376// A8.6.213 SUB (register) 9377bool 9378EmulateInstructionARM::EmulateSUBReg (const uint32_t opcode, const ARMEncoding encoding) 9379{ 9380#if 0 9381 if ConditionPassed() then 9382 EncodingSpecificOperations(); 9383 shifted = Shift(R[m], shift_t, shift_n, APSR.C); 9384 (result, carry, overflow) = AddWithCarry(R[n], NOT(shifted), ‘1’); 9385 if d == 15 then // Can only occur for ARM encoding 9386 ALUWritePC(result); // setflags is always FALSE here 9387 else 9388 R[d] = result; 9389 if setflags then 9390 APSR.N = result<31>; 9391 APSR.Z = IsZeroBit(result); 9392 APSR.C = carry; 9393 APSR.V = overflow; 9394#endif 9395 9396 bool success = false; 9397 9398 if (ConditionPassed(opcode)) 9399 { 9400 uint32_t d; 9401 uint32_t n; 9402 uint32_t m; 9403 bool setflags; 9404 ARM_ShifterType shift_t; 9405 uint32_t shift_n; 9406 9407 switch (encoding) 9408 { 9409 case eEncodingT1: 9410 // d = UInt(Rd); n = UInt(Rn); m = UInt(Rm); setflags = !InITBlock(); 9411 d = Bits32 (opcode, 2, 0); 9412 n = Bits32 (opcode, 5, 3); 9413 m = Bits32 (opcode, 8, 6); 9414 setflags = !InITBlock(); 9415 9416 // (shift_t, shift_n) = (SRType_LSL, 0); 9417 shift_t = SRType_LSL; 9418 shift_n = 0; 9419 9420 break; 9421 9422 case eEncodingT2: 9423 // if Rd == ‘1111’ && S == ‘1’ then SEE CMP (register); 9424 // if Rn == ‘1101’ then SEE SUB (SP minus register); 9425 // d = UInt(Rd); n = UInt(Rn); m = UInt(Rm); setflags = (S == ‘1’); 9426 d = Bits32 (opcode, 11, 8); 9427 n = Bits32 (opcode, 19, 16); 9428 m = Bits32 (opcode, 3, 0); 9429 setflags = BitIsSet (opcode, 20); 9430 9431 // (shift_t, shift_n) = DecodeImmShift(type, imm3:imm2); 9432 shift_n = DecodeImmShiftThumb (opcode, shift_t); 9433 9434 // if d == 13 || (d == 15 && S == '0') || n == 15 || BadReg(m) then UNPREDICTABLE; 9435 if ((d == 13) || ((d == 15) && BitIsClear (opcode, 20)) || (n == 15) || BadReg (m)) 9436 return false; 9437 9438 break; 9439 9440 case eEncodingA1: 9441 // if Rd == ‘1111’ && S == ‘1’ then SEE SUBS PC, LR and related instructions; 9442 // if Rn == ‘1101’ then SEE SUB (SP minus register); 9443 // d = UInt(Rd); n = UInt(Rn); m = UInt(Rm); setflags = (S == ‘1’); 9444 d = Bits32 (opcode, 15, 12); 9445 n = Bits32 (opcode, 19, 16); 9446 m = Bits32 (opcode, 3, 0); 9447 setflags = BitIsSet (opcode, 20); 9448 9449 // (shift_t, shift_n) = DecodeImmShift(type, imm5); 9450 shift_n = DecodeImmShiftARM (opcode, shift_t); 9451 9452 break; 9453 9454 default: 9455 return false; 9456 } 9457 9458 // shifted = Shift(R[m], shift_t, shift_n, APSR.C); 9459 uint32_t Rm = ReadCoreReg (m, &success); 9460 if (!success) 9461 return false; 9462 9463 uint32_t shifted = Shift (Rm, shift_t, shift_n, APSR_C); 9464 9465 // (result, carry, overflow) = AddWithCarry(R[n], NOT(shifted), ‘1’); 9466 uint32_t Rn = ReadCoreReg (n, &success); 9467 if (!success) 9468 return false; 9469 9470 AddWithCarryResult res = AddWithCarry (Rn, ~shifted, 1); 9471 9472 // if d == 15 then // Can only occur for ARM encoding 9473 // ALUWritePC(result); // setflags is always FALSE here 9474 // else 9475 // R[d] = result; 9476 // if setflags then 9477 // APSR.N = result<31>; 9478 // APSR.Z = IsZeroBit(result); 9479 // APSR.C = carry; 9480 // APSR.V = overflow; 9481 9482 EmulateInstruction::Context context; 9483 context.type = eContextSubtraction; 9484 Register reg_n; 9485 reg_n.SetRegister (eRegisterKindDWARF, dwarf_r0 + n); 9486 Register reg_m; 9487 reg_m.SetRegister (eRegisterKindDWARF, dwarf_r0 + m); 9488 context.SetRegisterRegisterOperands (reg_n, reg_m); 9489 9490 if (!WriteCoreRegOptionalFlags (context, res.result, dwarf_r0 + d, setflags, res.carry_out, res.overflow)) 9491 return false; 9492 } 9493 return true; 9494} 9495 9496// A8.6.202 STREX 9497// Store Register Exclusive calculates an address from a base register value and an immediate offset, and stores a 9498// word from a register to memory if the executing processor has exclusive access to the memory addressed. 9499bool 9500EmulateInstructionARM::EmulateSTREX (const uint32_t opcode, const ARMEncoding encoding) 9501{ 9502#if 0 9503 if ConditionPassed() then 9504 EncodingSpecificOperations(); NullCheckIfThumbEE(n); 9505 address = R[n] + imm32; 9506 if ExclusiveMonitorsPass(address,4) then 9507 MemA[address,4] = R[t]; 9508 R[d] = 0; 9509 else 9510 R[d] = 1; 9511#endif 9512 9513 bool success = false; 9514 9515 if (ConditionPassed(opcode)) 9516 { 9517 uint32_t d; 9518 uint32_t t; 9519 uint32_t n; 9520 uint32_t imm32; 9521 const uint32_t addr_byte_size = GetAddressByteSize(); 9522 9523 switch (encoding) 9524 { 9525 case eEncodingT1: 9526 // d = UInt(Rd); t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8:’00’, 32); 9527 d = Bits32 (opcode, 11, 8); 9528 t = Bits32 (opcode, 15, 12); 9529 n = Bits32 (opcode, 19, 16); 9530 imm32 = Bits32 (opcode, 7, 0) << 2; 9531 9532 // if BadReg(d) || BadReg(t) || n == 15 then UNPREDICTABLE; 9533 if (BadReg (d) || BadReg (t) || (n == 15)) 9534 return false; 9535 9536 // if d == n || d == t then UNPREDICTABLE; 9537 if ((d == n) || (d == t)) 9538 return false; 9539 9540 break; 9541 9542 case eEncodingA1: 9543 // d = UInt(Rd); t = UInt(Rt); n = UInt(Rn); imm32 = Zeros(32); // Zero offset 9544 d = Bits32 (opcode, 15, 12); 9545 t = Bits32 (opcode, 3, 0); 9546 n = Bits32 (opcode, 19, 16); 9547 imm32 = 0; 9548 9549 // if d == 15 || t == 15 || n == 15 then UNPREDICTABLE; 9550 if ((d == 15) || (t == 15) || (n == 15)) 9551 return false; 9552 9553 // if d == n || d == t then UNPREDICTABLE; 9554 if ((d == n) || (d == t)) 9555 return false; 9556 9557 break; 9558 9559 default: 9560 return false; 9561 } 9562 9563 // address = R[n] + imm32; 9564 uint32_t Rn = ReadCoreReg (n, &success); 9565 if (!success) 9566 return false; 9567 9568 addr_t address = Rn + imm32; 9569 9570 Register base_reg; 9571 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n); 9572 Register data_reg; 9573 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + t); 9574 EmulateInstruction::Context context; 9575 context.type = eContextRegisterStore; 9576 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, imm32); 9577 9578 // if ExclusiveMonitorsPass(address,4) then 9579 // if (ExclusiveMonitorsPass (address, addr_byte_size)) -- For now, for the sake of emulation, we will say this 9580 // always return true. 9581 if (true) 9582 { 9583 // MemA[address,4] = R[t]; 9584 uint32_t Rt = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + t, 0, &success); 9585 if (!success) 9586 return false; 9587 9588 if (!MemAWrite (context, address, Rt, addr_byte_size)) 9589 return false; 9590 9591 // R[d] = 0; 9592 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, 0)) 9593 return false; 9594 } 9595 else 9596 { 9597 // R[d] = 1; 9598 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, 1)) 9599 return false; 9600 } 9601 } 9602 return true; 9603} 9604 9605// A8.6.197 STRB (immediate, ARM) 9606bool 9607EmulateInstructionARM::EmulateSTRBImmARM (const uint32_t opcode, const ARMEncoding encoding) 9608{ 9609#if 0 9610 if ConditionPassed() then 9611 EncodingSpecificOperations(); 9612 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32); 9613 address = if index then offset_addr else R[n]; 9614 MemU[address,1] = R[t]<7:0>; 9615 if wback then R[n] = offset_addr; 9616#endif 9617 9618 bool success = false; 9619 9620 if (ConditionPassed(opcode)) 9621 { 9622 uint32_t t; 9623 uint32_t n; 9624 uint32_t imm32; 9625 bool index; 9626 bool add; 9627 bool wback; 9628 9629 switch (encoding) 9630 { 9631 case eEncodingA1: 9632 // if P == ‘0’ && W == ‘1’ then SEE STRBT; 9633 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32); 9634 t = Bits32 (opcode, 15, 12); 9635 n = Bits32 (opcode, 19, 16); 9636 imm32 = Bits32 (opcode, 11, 0); 9637 9638 // index = (P == ‘1’); add = (U == ‘1’); wback = (P == ‘0’) || (W == ‘1’); 9639 index = BitIsSet (opcode, 24); 9640 add = BitIsSet (opcode, 23); 9641 wback = BitIsClear (opcode, 24) || BitIsSet (opcode, 21); 9642 9643 // if t == 15 then UNPREDICTABLE; 9644 if (t == 15) 9645 return false; 9646 9647 // if wback && (n == 15 || n == t) then UNPREDICTABLE; 9648 if (wback && ((n == 15) || (n == t))) 9649 return false; 9650 9651 break; 9652 9653 default: 9654 return false; 9655 } 9656 9657 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32); 9658 uint32_t Rn = ReadCoreReg (n, &success); 9659 if (!success) 9660 return false; 9661 9662 addr_t offset_addr; 9663 if (add) 9664 offset_addr = Rn + imm32; 9665 else 9666 offset_addr = Rn - imm32; 9667 9668 // address = if index then offset_addr else R[n]; 9669 addr_t address; 9670 if (index) 9671 address = offset_addr; 9672 else 9673 address = Rn; 9674 9675 // MemU[address,1] = R[t]<7:0>; 9676 uint32_t Rt = ReadCoreReg (t, &success); 9677 if (!success) 9678 return false; 9679 9680 Register base_reg; 9681 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n); 9682 Register data_reg; 9683 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + t); 9684 EmulateInstruction::Context context; 9685 context.type = eContextRegisterStore; 9686 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, address - Rn); 9687 9688 if (!MemUWrite (context, address, Bits32 (Rt, 7, 0), 1)) 9689 return false; 9690 9691 // if wback then R[n] = offset_addr; 9692 if (wback) 9693 { 9694 if (WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr)) 9695 return false; 9696 } 9697 } 9698 return true; 9699} 9700 9701// A8.6.194 STR (immediate, ARM) 9702bool 9703EmulateInstructionARM::EmulateSTRImmARM (const uint32_t opcode, const ARMEncoding encoding) 9704{ 9705#if 0 9706 if ConditionPassed() then 9707 EncodingSpecificOperations(); 9708 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32); 9709 address = if index then offset_addr else R[n]; 9710 MemU[address,4] = if t == 15 then PCStoreValue() else R[t]; 9711 if wback then R[n] = offset_addr; 9712#endif 9713 9714 bool success = false; 9715 9716 if (ConditionPassed(opcode)) 9717 { 9718 uint32_t t; 9719 uint32_t n; 9720 uint32_t imm32; 9721 bool index; 9722 bool add; 9723 bool wback; 9724 9725 const uint32_t addr_byte_size = GetAddressByteSize(); 9726 9727 switch (encoding) 9728 { 9729 case eEncodingA1: 9730 // if P == ‘0’ && W == ‘1’ then SEE STRT; 9731 // if Rn == ‘1101’ && P == ‘1’ && U == ‘0’ && W == ‘1’ && imm12 == ‘000000000100’ then SEE PUSH; 9732 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32); 9733 t = Bits32 (opcode, 15, 12); 9734 n = Bits32 (opcode, 19, 16); 9735 imm32 = Bits32 (opcode, 11, 0); 9736 9737 // index = (P == ‘1’); add = (U == ‘1’); wback = (P == ‘0’) || (W == ‘1’); 9738 index = BitIsSet (opcode, 24); 9739 add = BitIsSet (opcode, 23); 9740 wback = BitIsClear (opcode, 24) || BitIsSet (opcode, 21); 9741 9742 // if wback && (n == 15 || n == t) then UNPREDICTABLE; 9743 if (wback && ((n == 15) || (n == t))) 9744 return false; 9745 9746 break; 9747 9748 default: 9749 return false; 9750 } 9751 9752 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32); 9753 uint32_t Rn = ReadCoreReg (n, &success); 9754 if (!success) 9755 return false; 9756 9757 addr_t offset_addr; 9758 if (add) 9759 offset_addr = Rn + imm32; 9760 else 9761 offset_addr = Rn - imm32; 9762 9763 // address = if index then offset_addr else R[n]; 9764 addr_t address; 9765 if (index) 9766 address = offset_addr; 9767 else 9768 address = Rn; 9769 9770 Register base_reg; 9771 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n); 9772 Register data_reg; 9773 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + t); 9774 EmulateInstruction::Context context; 9775 context.type = eContextRegisterStore; 9776 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, address - Rn); 9777 9778 // MemU[address,4] = if t == 15 then PCStoreValue() else R[t]; 9779 uint32_t Rt = ReadCoreReg (t, &success); 9780 if (!success) 9781 return false; 9782 9783 if (t == 15) 9784 { 9785 uint32_t pc_value = ReadCoreReg (PC_REG, &success); 9786 if (!success) 9787 return false; 9788 9789 if (!MemUWrite (context, address, pc_value, addr_byte_size)) 9790 return false; 9791 } 9792 else 9793 { 9794 if (!MemUWrite (context, address, Rt, addr_byte_size)) 9795 return false; 9796 } 9797 9798 // if wback then R[n] = offset_addr; 9799 if (wback) 9800 { 9801 context.type = eContextAdjustBaseRegister; 9802 context.SetImmediate (offset_addr); 9803 9804 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr)) 9805 return false; 9806 } 9807 } 9808 return true; 9809} 9810 9811// A8.6.66 LDRD (immediate) 9812// Load Register Dual (immediate) calculates an address from a base register value and an immediate offset, loads two 9813// words from memory, and writes them to two registers. It can use offset, post-indexed, or pre-indexed addressing. 9814bool 9815EmulateInstructionARM::EmulateLDRDImmediate (const uint32_t opcode, const ARMEncoding encoding) 9816{ 9817#if 0 9818 if ConditionPassed() then 9819 EncodingSpecificOperations(); NullCheckIfThumbEE(n); 9820 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32); 9821 address = if index then offset_addr else R[n]; 9822 R[t] = MemA[address,4]; 9823 R[t2] = MemA[address+4,4]; 9824 if wback then R[n] = offset_addr; 9825#endif 9826 9827 bool success = false; 9828 9829 if (ConditionPassed(opcode)) 9830 { 9831 uint32_t t; 9832 uint32_t t2; 9833 uint32_t n; 9834 uint32_t imm32; 9835 bool index; 9836 bool add; 9837 bool wback; 9838 9839 switch (encoding) 9840 { 9841 case eEncodingT1: 9842 //if P == ‘0’ && W == ‘0’ then SEE “Related encodings”; 9843 //if Rn == ‘1111’ then SEE LDRD (literal); 9844 //t = UInt(Rt); t2 = UInt(Rt2); n = UInt(Rn); imm32 = ZeroExtend(imm8:’00’, 32); 9845 t = Bits32 (opcode, 15, 12); 9846 t2 = Bits32 (opcode, 11, 8); 9847 n = Bits32 (opcode, 19, 16); 9848 imm32 = Bits32 (opcode, 7, 0) << 2; 9849 9850 //index = (P == ‘1’); add = (U == ‘1’); wback = (W == ‘1’); 9851 index = BitIsSet (opcode, 24); 9852 add = BitIsSet (opcode, 23); 9853 wback = BitIsSet (opcode, 21); 9854 9855 //if wback && (n == t || n == t2) then UNPREDICTABLE; 9856 if (wback && ((n == t) || (n == t2))) 9857 return false; 9858 9859 //if BadReg(t) || BadReg(t2) || t == t2 then UNPREDICTABLE; 9860 if (BadReg (t) || BadReg (t2) || (t == t2)) 9861 return false; 9862 9863 break; 9864 9865 case eEncodingA1: 9866 //if Rn == ‘1111’ then SEE LDRD (literal); 9867 //if Rt<0> == ‘1’ then UNPREDICTABLE; 9868 //t = UInt(Rt); t2 = t+1; n = UInt(Rn); imm32 = ZeroExtend(imm4H:imm4L, 32); 9869 t = Bits32 (opcode, 15, 12); 9870 if (BitIsSet (t, 0)) 9871 return false; 9872 t2 = t + 1; 9873 n = Bits32 (opcode, 19, 16); 9874 imm32 = (Bits32 (opcode, 11, 8) << 4) | Bits32 (opcode, 3, 0); 9875 9876 //index = (P == ‘1’); add = (U == ‘1’); wback = (P == ‘0’) || (W == ‘1’); 9877 index = BitIsSet (opcode, 24); 9878 add = BitIsSet (opcode, 23); 9879 wback = BitIsClear (opcode, 24) || BitIsSet (opcode, 21); 9880 9881 //if P == ‘0’ && W == ‘1’ then UNPREDICTABLE; 9882 if (BitIsClear (opcode, 24) && BitIsSet (opcode, 21)) 9883 return false; 9884 9885 //if wback && (n == t || n == t2) then UNPREDICTABLE; 9886 if (wback && ((n == t) || (n == t2))) 9887 return false; 9888 9889 //if t2 == 15 then UNPREDICTABLE; 9890 if (t2 == 15) 9891 return false; 9892 9893 break; 9894 9895 default: 9896 return false; 9897 } 9898 9899 //offset_addr = if add then (R[n] + imm32) else (R[n] - imm32); 9900 uint32_t Rn = ReadCoreReg (n, &success); 9901 if (!success) 9902 return false; 9903 9904 addr_t offset_addr; 9905 if (add) 9906 offset_addr = Rn + imm32; 9907 else 9908 offset_addr = Rn - imm32; 9909 9910 //address = if index then offset_addr else R[n]; 9911 addr_t address; 9912 if (index) 9913 address = offset_addr; 9914 else 9915 address = Rn; 9916 9917 //R[t] = MemA[address,4]; 9918 Register base_reg; 9919 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n); 9920 9921 EmulateInstruction::Context context; 9922 context.type = eContextRegisterLoad; 9923 context.SetRegisterPlusOffset (base_reg, address - Rn); 9924 9925 const uint32_t addr_byte_size = GetAddressByteSize(); 9926 uint32_t data = MemARead (context, address, addr_byte_size, 0, &success); 9927 if (!success) 9928 return false; 9929 9930 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data)) 9931 return false; 9932 9933 //R[t2] = MemA[address+4,4]; 9934 9935 context.SetRegisterPlusOffset (base_reg, (address + 4) - Rn); 9936 data = MemARead (context, address + 4, addr_byte_size, 0, &success); 9937 if (!success) 9938 return false; 9939 9940 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t2, data)) 9941 return false; 9942 9943 //if wback then R[n] = offset_addr; 9944 if (wback) 9945 { 9946 context.type = eContextAdjustBaseRegister; 9947 context.SetAddress (offset_addr); 9948 9949 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr)) 9950 return false; 9951 } 9952 } 9953 return true; 9954} 9955 9956// A8.6.68 LDRD (register) 9957// Load Register Dual (register) calculates an address from a base register value and a register offset, loads two 9958// words from memory, and writes them to two registers. It can use offset, post-indexed or pre-indexed addressing. 9959bool 9960EmulateInstructionARM::EmulateLDRDRegister (const uint32_t opcode, const ARMEncoding encoding) 9961{ 9962#if 0 9963 if ConditionPassed() then 9964 EncodingSpecificOperations(); 9965 offset_addr = if add then (R[n] + R[m]) else (R[n] - R[m]); 9966 address = if index then offset_addr else R[n]; 9967 R[t] = MemA[address,4]; 9968 R[t2] = MemA[address+4,4]; 9969 if wback then R[n] = offset_addr; 9970#endif 9971 9972 bool success = false; 9973 9974 if (ConditionPassed(opcode)) 9975 { 9976 uint32_t t; 9977 uint32_t t2; 9978 uint32_t n; 9979 uint32_t m; 9980 bool index; 9981 bool add; 9982 bool wback; 9983 9984 switch (encoding) 9985 { 9986 case eEncodingA1: 9987 // if Rt<0> == ‘1’ then UNPREDICTABLE; 9988 // t = UInt(Rt); t2 = t+1; n = UInt(Rn); m = UInt(Rm); 9989 t = Bits32 (opcode, 15, 12); 9990 if (BitIsSet (t, 0)) 9991 return false; 9992 t2 = t + 1; 9993 n = Bits32 (opcode, 19, 16); 9994 m = Bits32 (opcode, 3, 0); 9995 9996 // index = (P == ‘1’); add = (U == ‘1’); wback = (P == ‘0’) || (W == ‘1’); 9997 index = BitIsSet (opcode, 24); 9998 add = BitIsSet (opcode, 23); 9999 wback = BitIsClear (opcode, 24) || BitIsSet (opcode, 21); 10000 10001 // if P == ‘0’ && W == ‘1’ then UNPREDICTABLE; 10002 if (BitIsClear (opcode, 24) && BitIsSet (opcode, 21)) 10003 return false; 10004 10005 // if t2 == 15 || m == 15 || m == t || m == t2 then UNPREDICTABLE; 10006 if ((t2 == 15) || (m == 15) || (m == t) || (m == t2)) 10007 return false; 10008 10009 // if wback && (n == 15 || n == t || n == t2) then UNPREDICTABLE; 10010 if (wback && ((n == 15) || (n == t) || (n == t2))) 10011 return false; 10012 10013 // if ArchVersion() < 6 && wback && m == n then UNPREDICTABLE; 10014 if ((ArchVersion() < 6) && wback && (m == n)) 10015 return false; 10016 break; 10017 10018 default: 10019 return false; 10020 } 10021 10022 uint32_t Rn = ReadCoreReg (n, &success); 10023 if (!success) 10024 return false; 10025 Register base_reg; 10026 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n); 10027 10028 uint32_t Rm = ReadCoreReg (m, &success); 10029 if (!success) 10030 return false; 10031 Register offset_reg; 10032 offset_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + m); 10033 10034 // offset_addr = if add then (R[n] + R[m]) else (R[n] - R[m]); 10035 addr_t offset_addr; 10036 if (add) 10037 offset_addr = Rn + Rm; 10038 else 10039 offset_addr = Rn - Rm; 10040 10041 // address = if index then offset_addr else R[n]; 10042 addr_t address; 10043 if (index) 10044 address = offset_addr; 10045 else 10046 address = Rn; 10047 10048 EmulateInstruction::Context context; 10049 context.type = eContextRegisterLoad; 10050 context.SetRegisterPlusIndirectOffset (base_reg, offset_reg); 10051 10052 // R[t] = MemA[address,4]; 10053 const uint32_t addr_byte_size = GetAddressByteSize(); 10054 uint32_t data = MemARead (context, address, addr_byte_size, 0, &success); 10055 if (!success) 10056 return false; 10057 10058 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data)) 10059 return false; 10060 10061 // R[t2] = MemA[address+4,4]; 10062 10063 data = MemARead (context, address + 4, addr_byte_size, 0, &success); 10064 if (!success) 10065 return false; 10066 10067 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t2, data)) 10068 return false; 10069 10070 // if wback then R[n] = offset_addr; 10071 if (wback) 10072 { 10073 context.type = eContextAdjustBaseRegister; 10074 context.SetAddress (offset_addr); 10075 10076 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr)) 10077 return false; 10078 } 10079 } 10080 return true; 10081} 10082 10083// A8.6.200 STRD (immediate) 10084// Store Register Dual (immediate) calculates an address from a base register value and an immediate offset, and 10085// stores two words from two registers to memory. It can use offset, post-indexed, or pre-indexed addressing. 10086bool 10087EmulateInstructionARM::EmulateSTRDImm (const uint32_t opcode, const ARMEncoding encoding) 10088{ 10089#if 0 10090 if ConditionPassed() then 10091 EncodingSpecificOperations(); NullCheckIfThumbEE(n); 10092 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32); 10093 address = if index then offset_addr else R[n]; 10094 MemA[address,4] = R[t]; 10095 MemA[address+4,4] = R[t2]; 10096 if wback then R[n] = offset_addr; 10097#endif 10098 10099 bool success = false; 10100 10101 if (ConditionPassed(opcode)) 10102 { 10103 uint32_t t; 10104 uint32_t t2; 10105 uint32_t n; 10106 uint32_t imm32; 10107 bool index; 10108 bool add; 10109 bool wback; 10110 10111 switch (encoding) 10112 { 10113 case eEncodingT1: 10114 // if P == ‘0’ && W == ‘0’ then SEE “Related encodings”; 10115 // t = UInt(Rt); t2 = UInt(Rt2); n = UInt(Rn); imm32 = ZeroExtend(imm8:’00’, 32); 10116 t = Bits32 (opcode, 15, 12); 10117 t2 = Bits32 (opcode, 11, 8); 10118 n = Bits32 (opcode, 19, 16); 10119 imm32 = Bits32 (opcode, 7, 0) << 2; 10120 10121 // index = (P == ‘1’); add = (U == ‘1’); wback = (W == ‘1’); 10122 index = BitIsSet (opcode, 24); 10123 add = BitIsSet (opcode, 23); 10124 wback = BitIsSet (opcode, 21); 10125 10126 // if wback && (n == t || n == t2) then UNPREDICTABLE; 10127 if (wback && ((n == t) || (n == t2))) 10128 return false; 10129 10130 // if n == 15 || BadReg(t) || BadReg(t2) then UNPREDICTABLE; 10131 if ((n == 15) || BadReg (t) || BadReg (t2)) 10132 return false; 10133 10134 break; 10135 10136 case eEncodingA1: 10137 // if Rt<0> == ‘1’ then UNPREDICTABLE; 10138 // t = UInt(Rt); t2 = t+1; n = UInt(Rn); imm32 = ZeroExtend(imm4H:imm4L, 32); 10139 t = Bits32 (opcode, 15, 12); 10140 if (BitIsSet (t, 0)) 10141 return false; 10142 10143 t2 = t + 1; 10144 n = Bits32 (opcode, 19, 16); 10145 imm32 = (Bits32 (opcode, 11, 8) << 4) | Bits32 (opcode, 3, 0); 10146 10147 // index = (P == ‘1’); add = (U == ‘1’); wback = (P == ‘0’) || (W == ‘1’); 10148 index = BitIsSet (opcode, 24); 10149 add = BitIsSet (opcode, 23); 10150 wback = BitIsClear (opcode, 24) || BitIsSet (opcode, 21); 10151 10152 // if P == ‘0’ && W == ‘1’ then UNPREDICTABLE; 10153 if (BitIsClear (opcode, 24) && BitIsSet (opcode, 21)) 10154 return false; 10155 10156 // if wback && (n == 15 || n == t || n == t2) then UNPREDICTABLE; 10157 if (wback && ((n == 15) || (n == t) || (n == t2))) 10158 return false; 10159 10160 // if t2 == 15 then UNPREDICTABLE; 10161 if (t2 == 15) 10162 return false; 10163 10164 break; 10165 10166 default: 10167 return false; 10168 } 10169 10170 Register base_reg; 10171 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n); 10172 10173 uint32_t Rn = ReadCoreReg (n, &success); 10174 if (!success) 10175 return false; 10176 10177 //offset_addr = if add then (R[n] + imm32) else (R[n] - imm32); 10178 addr_t offset_addr; 10179 if (add) 10180 offset_addr = Rn + imm32; 10181 else 10182 offset_addr = Rn - imm32; 10183 10184 //address = if index then offset_addr else R[n]; 10185 addr_t address; 10186 if (index) 10187 address = offset_addr; 10188 else 10189 address = Rn; 10190 10191 //MemA[address,4] = R[t]; 10192 Register data_reg; 10193 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + t); 10194 10195 uint32_t data = ReadCoreReg (t, &success); 10196 if (!success) 10197 return false; 10198 10199 EmulateInstruction::Context context; 10200 context.type = eContextRegisterStore; 10201 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, address - Rn); 10202 10203 const uint32_t addr_byte_size = GetAddressByteSize(); 10204 10205 if (!MemAWrite (context, address, data, addr_byte_size)) 10206 return false; 10207 10208 //MemA[address+4,4] = R[t2]; 10209 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + t2); 10210 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, (address + 4) - Rn); 10211 10212 data = ReadCoreReg (t2, &success); 10213 if (!success) 10214 return false; 10215 10216 if (!MemAWrite (context, address + 4, data, addr_byte_size)) 10217 return false; 10218 10219 //if wback then R[n] = offset_addr; 10220 if (wback) 10221 { 10222 context.type = eContextAdjustBaseRegister; 10223 context.SetAddress (offset_addr); 10224 10225 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr)) 10226 return false; 10227 } 10228 } 10229 return true; 10230} 10231 10232 10233// A8.6.201 STRD (register) 10234bool 10235EmulateInstructionARM::EmulateSTRDReg (const uint32_t opcode, const ARMEncoding encoding) 10236{ 10237#if 0 10238 if ConditionPassed() then 10239 EncodingSpecificOperations(); 10240 offset_addr = if add then (R[n] + R[m]) else (R[n] - R[m]); 10241 address = if index then offset_addr else R[n]; 10242 MemA[address,4] = R[t]; 10243 MemA[address+4,4] = R[t2]; 10244 if wback then R[n] = offset_addr; 10245#endif 10246 10247 bool success = false; 10248 10249 if (ConditionPassed(opcode)) 10250 { 10251 uint32_t t; 10252 uint32_t t2; 10253 uint32_t n; 10254 uint32_t m; 10255 bool index; 10256 bool add; 10257 bool wback; 10258 10259 switch (encoding) 10260 { 10261 case eEncodingA1: 10262 // if Rt<0> == ‘1’ then UNPREDICTABLE; 10263 // t = UInt(Rt); t2 = t+1; n = UInt(Rn); m = UInt(Rm); 10264 t = Bits32 (opcode, 15, 12); 10265 if (BitIsSet (t, 0)) 10266 return false; 10267 10268 t2 = t+1; 10269 n = Bits32 (opcode, 19, 16); 10270 m = Bits32 (opcode, 3, 0); 10271 10272 // index = (P == ‘1’); add = (U == ‘1’); wback = (P == ‘0’) || (W == ‘1’); 10273 index = BitIsSet (opcode, 24); 10274 add = BitIsSet (opcode, 23); 10275 wback = BitIsClear (opcode, 24) || BitIsSet (opcode, 21); 10276 10277 // if P == ‘0’ && W == ‘1’ then UNPREDICTABLE; 10278 if (BitIsClear (opcode, 24) && BitIsSet (opcode, 21)) 10279 return false; 10280 10281 // if t2 == 15 || m == 15 then UNPREDICTABLE; 10282 if ((t2 == 15) || (m == 15)) 10283 return false; 10284 10285 // if wback && (n == 15 || n == t || n == t2) then UNPREDICTABLE; 10286 if (wback && ((n == 15) || (n == t) || (n == t2))) 10287 return false; 10288 10289 // if ArchVersion() < 6 && wback && m == n then UNPREDICTABLE; 10290 if ((ArchVersion() < 6) && wback && (m == n)) 10291 return false; 10292 10293 break; 10294 10295 default: 10296 return false; 10297 } 10298 10299 Register base_reg; 10300 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n); 10301 Register offset_reg; 10302 offset_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + m); 10303 Register data_reg; 10304 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + t); 10305 10306 uint32_t Rn = ReadCoreReg (n, &success); 10307 if (!success) 10308 return false; 10309 10310 uint32_t Rm = ReadCoreReg (m, &success); 10311 if (!success) 10312 return false; 10313 10314 // offset_addr = if add then (R[n] + R[m]) else (R[n] - R[m]); 10315 addr_t offset_addr; 10316 if (add) 10317 offset_addr = Rn + Rm; 10318 else 10319 offset_addr = Rn - Rm; 10320 10321 // address = if index then offset_addr else R[n]; 10322 addr_t address; 10323 if (index) 10324 address = offset_addr; 10325 else 10326 address = Rn; 10327 // MemA[address,4] = R[t]; 10328 uint32_t Rt = ReadCoreReg (t, &success); 10329 if (!success) 10330 return false; 10331 10332 EmulateInstruction::Context context; 10333 context.type = eContextRegisterStore; 10334 context.SetRegisterToRegisterPlusIndirectOffset (base_reg, offset_reg, data_reg); 10335 10336 const uint32_t addr_byte_size = GetAddressByteSize(); 10337 10338 if (!MemAWrite (context, address, Rt, addr_byte_size)) 10339 return false; 10340 10341 // MemA[address+4,4] = R[t2]; 10342 uint32_t Rt2 = ReadCoreReg (t2, &success); 10343 if (!success) 10344 return false; 10345 10346 data_reg.num = dwarf_r0 + t2; 10347 10348 context.SetRegisterToRegisterPlusIndirectOffset (base_reg, offset_reg, data_reg); 10349 10350 if (!MemAWrite (context, address + 4, Rt2, addr_byte_size)) 10351 return false; 10352 10353 // if wback then R[n] = offset_addr; 10354 if (wback) 10355 { 10356 context.type = eContextAdjustBaseRegister; 10357 context.SetAddress (offset_addr); 10358 10359 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr)) 10360 return false; 10361 10362 } 10363 } 10364 return true; 10365} 10366 10367// A8.6.319 VLDM 10368// Vector Load Multiple loads multiple extension registers from consecutive memory locations using an address from 10369// an ARM core register. 10370bool 10371EmulateInstructionARM::EmulateVLDM (const uint32_t opcode, const ARMEncoding encoding) 10372{ 10373#if 0 10374 if ConditionPassed() then 10375 EncodingSpecificOperations(); CheckVFPEnabled(TRUE); NullCheckIfThumbEE(n); 10376 address = if add then R[n] else R[n]-imm32; 10377 if wback then R[n] = if add then R[n}+imm32 else R[n]-imm32; 10378 for r = 0 to regs-1 10379 if single_regs then 10380 S[d+r] = MemA[address,4]; address = address+4; 10381 else 10382 word1 = MemA[address,4]; word2 = MemA[address+4,4]; address = address+8; 10383 // Combine the word-aligned words in the correct order for current endianness. 10384 D[d+r] = if BigEndian() then word1:word2 else word2:word1; 10385#endif 10386 10387 bool success = false; 10388 10389 if (ConditionPassed(opcode)) 10390 { 10391 bool single_regs; 10392 bool add; 10393 bool wback; 10394 uint32_t d; 10395 uint32_t n; 10396 uint32_t imm32; 10397 uint32_t regs; 10398 10399 switch (encoding) 10400 { 10401 case eEncodingT1: 10402 case eEncodingA1: 10403 // if P == ‘0’ && U == ‘0’ && W == ‘0’ then SEE “Related encodings”; 10404 // if P == ‘0’ && U == ‘1’ && W == ‘1’ && Rn == ‘1101’ then SEE VPOP; 10405 // if P == ‘1’ && W == ‘0’ then SEE VLDR; 10406 // if P == U && W == ‘1’ then UNDEFINED; 10407 if ((Bit32 (opcode, 24) == Bit32 (opcode, 23)) && BitIsSet (opcode, 21)) 10408 return false; 10409 10410 // // Remaining combinations are PUW = 010 (IA without !), 011 (IA with !), 101 (DB with !) 10411 // single_regs = FALSE; add = (U == ‘1’); wback = (W == ‘1’); 10412 single_regs = false; 10413 add = BitIsSet (opcode, 23); 10414 wback = BitIsSet (opcode, 21); 10415 10416 // d = UInt(D:Vd); n = UInt(Rn); imm32 = ZeroExtend(imm8:’00’, 32); 10417 d = (Bit32 (opcode, 22) << 4) | Bits32 (opcode, 15, 12); 10418 n = Bits32 (opcode, 19, 16); 10419 imm32 = Bits32 (opcode, 7, 0) << 2; 10420 10421 // regs = UInt(imm8) DIV 2; // If UInt(imm8) is odd, see “FLDMX”. 10422 regs = Bits32 (opcode, 7, 0) / 2; 10423 10424 // if n == 15 && (wback || CurrentInstrSet() != InstrSet_ARM) then UNPREDICTABLE; 10425 if (n == 15 && (wback || CurrentInstrSet() != eModeARM)) 10426 return false; 10427 10428 // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE; 10429 if ((regs == 0) || (regs > 16) || ((d + regs) > 32)) 10430 return false; 10431 10432 break; 10433 10434 case eEncodingT2: 10435 case eEncodingA2: 10436 // if P == ‘0’ && U == ‘0’ && W == ‘0’ then SEE “Related encodings”; 10437 // if P == ‘0’ && U == ‘1’ && W == ‘1’ && Rn == ‘1101’ then SEE VPOP; 10438 // if P == ‘1’ && W == ‘0’ then SEE VLDR; 10439 // if P == U && W == ‘1’ then UNDEFINED; 10440 if ((Bit32 (opcode, 24) == Bit32 (opcode, 23)) && BitIsSet (opcode, 21)) 10441 return false; 10442 10443 // // Remaining combinations are PUW = 010 (IA without !), 011 (IA with !), 101 (DB with !) 10444 // single_regs = TRUE; add = (U == ‘1’); wback = (W == ‘1’); d = UInt(Vd:D); n = UInt(Rn); 10445 single_regs = true; 10446 add = BitIsSet (opcode, 23); 10447 wback = BitIsSet (opcode, 21); 10448 d = (Bits32 (opcode, 15, 12) << 1) | Bit32 (opcode, 22); 10449 n = Bits32 (opcode, 19, 16); 10450 10451 // imm32 = ZeroExtend(imm8:’00’, 32); regs = UInt(imm8); 10452 imm32 = Bits32 (opcode, 7, 0) << 2; 10453 regs = Bits32 (opcode, 7, 0); 10454 10455 // if n == 15 && (wback || CurrentInstrSet() != InstrSet_ARM) then UNPREDICTABLE; 10456 if ((n == 15) && (wback || (CurrentInstrSet() != eModeARM))) 10457 return false; 10458 10459 // if regs == 0 || (d+regs) > 32 then UNPREDICTABLE; 10460 if ((regs == 0) || ((d + regs) > 32)) 10461 return false; 10462 break; 10463 10464 default: 10465 return false; 10466 } 10467 10468 Register base_reg; 10469 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n); 10470 10471 uint32_t Rn = ReadCoreReg (n, &success); 10472 if (!success) 10473 return false; 10474 10475 // address = if add then R[n] else R[n]-imm32; 10476 addr_t address; 10477 if (add) 10478 address = Rn; 10479 else 10480 address = Rn - imm32; 10481 10482 // if wback then R[n] = if add then R[n}+imm32 else R[n]-imm32; 10483 EmulateInstruction::Context context; 10484 10485 if (wback) 10486 { 10487 uint32_t value; 10488 if (add) 10489 value = Rn + imm32; 10490 else 10491 value = Rn - imm32; 10492 10493 context.type = eContextAdjustBaseRegister; 10494 context.SetImmediateSigned (value - Rn); 10495 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, value)) 10496 return false; 10497 10498 } 10499 10500 const uint32_t addr_byte_size = GetAddressByteSize(); 10501 uint32_t start_reg = single_regs ? dwarf_s0 : dwarf_d0; 10502 10503 context.type = eContextRegisterLoad; 10504 10505 // for r = 0 to regs-1 10506 for (uint32_t r = 0; r < regs; ++r) 10507 { 10508 if (single_regs) 10509 { 10510 // S[d+r] = MemA[address,4]; address = address+4; 10511 context.SetRegisterPlusOffset (base_reg, address - Rn); 10512 10513 uint32_t data = MemARead (context, address, addr_byte_size, 0, &success); 10514 if (!success) 10515 return false; 10516 10517 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, start_reg + d + r, data)) 10518 return false; 10519 10520 address = address + 4; 10521 } 10522 else 10523 { 10524 // word1 = MemA[address,4]; word2 = MemA[address+4,4]; address = address+8; 10525 context.SetRegisterPlusOffset (base_reg, address - Rn); 10526 uint32_t word1 = MemARead (context, address, addr_byte_size, 0, &success); 10527 if (!success) 10528 return false; 10529 10530 context.SetRegisterPlusOffset (base_reg, (address + 4) - Rn); 10531 uint32_t word2 = MemARead (context, address + 4, addr_byte_size, 0, &success); 10532 if (!success) 10533 return false; 10534 10535 address = address + 8; 10536 // // Combine the word-aligned words in the correct order for current endianness. 10537 // D[d+r] = if BigEndian() then word1:word2 else word2:word1; 10538 uint64_t data; 10539 if (m_byte_order == eByteOrderBig) 10540 { 10541 data = word1; 10542 data = (data << 32) | word2; 10543 } 10544 else 10545 { 10546 data = word2; 10547 data = (data << 32) | word1; 10548 } 10549 10550 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, start_reg + d + r, data)) 10551 return false; 10552 } 10553 } 10554 } 10555 return true; 10556} 10557 10558// A8.6.399 VSTM 10559// Vector Store Multiple stores multiple extension registers to consecutive memory locations using an address from an 10560// ARM core register. 10561bool 10562EmulateInstructionARM::EmulateVSTM (const uint32_t opcode, const ARMEncoding encoding) 10563{ 10564#if 0 10565 if ConditionPassed() then 10566 EncodingSpecificOperations(); CheckVFPEnabled(TRUE); NullCheckIfThumbEE(n); 10567 address = if add then R[n] else R[n]-imm32; 10568 if wback then R[n] = if add then R[n}+imm32 else R[n]-imm32; 10569 for r = 0 to regs-1 10570 if single_regs then 10571 MemA[address,4] = S[d+r]; address = address+4; 10572 else 10573 // Store as two word-aligned words in the correct order for current endianness. 10574 MemA[address,4] = if BigEndian() then D[d+r]<63:32> else D[d+r]<31:0>; 10575 MemA[address+4,4] = if BigEndian() then D[d+r]<31:0> else D[d+r]<63:32>; 10576 address = address+8; 10577#endif 10578 10579 bool success = false; 10580 10581 if (ConditionPassed (opcode)) 10582 { 10583 bool single_regs; 10584 bool add; 10585 bool wback; 10586 uint32_t d; 10587 uint32_t n; 10588 uint32_t imm32; 10589 uint32_t regs; 10590 10591 switch (encoding) 10592 { 10593 case eEncodingT1: 10594 case eEncodingA1: 10595 // if P == ‘0’ && U == ‘0’ && W == ‘0’ then SEE “Related encodings”; 10596 // if P == ‘1’ && U == ‘0’ && W == ‘1’ && Rn == ‘1101’ then SEE VPUSH; 10597 // if P == ‘1’ && W == ‘0’ then SEE VSTR; 10598 // if P == U && W == ‘1’ then UNDEFINED; 10599 if ((Bit32 (opcode, 24) == Bit32 (opcode, 23)) && BitIsSet (opcode, 21)) 10600 return false; 10601 10602 // // Remaining combinations are PUW = 010 (IA without !), 011 (IA with !), 101 (DB with !) 10603 // single_regs = FALSE; add = (U == ‘1’); wback = (W == ‘1’); 10604 single_regs = false; 10605 add = BitIsSet (opcode, 23); 10606 wback = BitIsSet (opcode, 21); 10607 10608 // d = UInt(D:Vd); n = UInt(Rn); imm32 = ZeroExtend(imm8:’00’, 32); 10609 d = (Bit32 (opcode, 22) << 4) | Bits32 (opcode, 15, 12); 10610 n = Bits32 (opcode, 19, 16); 10611 imm32 = Bits32 (opcode, 7, 0) << 2; 10612 10613 // regs = UInt(imm8) DIV 2; // If UInt(imm8) is odd, see “FSTMX”. 10614 regs = Bits32 (opcode, 7, 0) / 2; 10615 10616 // if n == 15 && (wback || CurrentInstrSet() != InstrSet_ARM) then UNPREDICTABLE; 10617 if ((n == 15) && (wback || (CurrentInstrSet() != eModeARM))) 10618 return false; 10619 10620 // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE; 10621 if ((regs == 0) || (regs > 16) || ((d + regs) > 32)) 10622 return false; 10623 10624 break; 10625 10626 case eEncodingT2: 10627 case eEncodingA2: 10628 // if P == ‘0’ && U == ‘0’ && W == ‘0’ then SEE “Related encodings”; 10629 // if P == ‘1’ && U == ‘0’ && W == ‘1’ && Rn == ‘1101’ then SEE VPUSH; 10630 // if P == ‘1’ && W == ‘0’ then SEE VSTR; 10631 // if P == U && W == ‘1’ then UNDEFINED; 10632 if ((Bit32 (opcode, 24) == Bit32 (opcode, 23)) && BitIsSet (opcode, 21)) 10633 return false; 10634 10635 // // Remaining combinations are PUW = 010 (IA without !), 011 (IA with !), 101 (DB with !) 10636 // single_regs = TRUE; add = (U == ‘1’); wback = (W == ‘1’); d = UInt(Vd:D); n = UInt(Rn); 10637 single_regs = true; 10638 add = BitIsSet (opcode, 23); 10639 wback = BitIsSet (opcode, 21); 10640 d = (Bits32 (opcode, 15, 12) << 1) | Bit32 (opcode, 22); 10641 n = Bits32 (opcode, 19, 16); 10642 10643 // imm32 = ZeroExtend(imm8:’00’, 32); regs = UInt(imm8); 10644 imm32 = Bits32 (opcode, 7, 0) << 2; 10645 regs = Bits32 (opcode, 7, 0); 10646 10647 // if n == 15 && (wback || CurrentInstrSet() != InstrSet_ARM) then UNPREDICTABLE; 10648 if ((n == 15) && (wback || (CurrentInstrSet () != eModeARM))) 10649 return false; 10650 10651 // if regs == 0 || (d+regs) > 32 then UNPREDICTABLE; 10652 if ((regs == 0) || ((d + regs) > 32)) 10653 return false; 10654 10655 break; 10656 10657 default: 10658 return false; 10659 } 10660 10661 Register base_reg; 10662 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n); 10663 10664 uint32_t Rn = ReadCoreReg (n, &success); 10665 if (!success) 10666 return false; 10667 10668 // address = if add then R[n] else R[n]-imm32; 10669 addr_t address; 10670 if (add) 10671 address = Rn; 10672 else 10673 address = Rn - imm32; 10674 10675 EmulateInstruction::Context context; 10676 // if wback then R[n] = if add then R[n}+imm32 else R[n]-imm32; 10677 if (wback) 10678 { 10679 uint32_t value; 10680 if (add) 10681 value = Rn + imm32; 10682 else 10683 value = Rn - imm32; 10684 10685 context.type = eContextAdjustBaseRegister; 10686 context.SetRegisterPlusOffset (base_reg, value - Rn); 10687 10688 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, value)) 10689 return false; 10690 } 10691 10692 const uint32_t addr_byte_size = GetAddressByteSize(); 10693 uint32_t start_reg = single_regs ? dwarf_s0 : dwarf_d0; 10694 10695 context.type = eContextRegisterStore; 10696 // for r = 0 to regs-1 10697 for (int r = 0; r < regs; ++r) 10698 { 10699 Register data_reg; 10700 data_reg.SetRegister (eRegisterKindDWARF, 0); 10701 if (single_regs) 10702 { 10703 // MemA[address,4] = S[d+r]; address = address+4; 10704 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, start_reg + d + r, 0, &success); 10705 if (!success) 10706 return false; 10707 10708 data_reg.num = start_reg + d + r; 10709 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, address - Rn); 10710 if (!MemAWrite (context, address, data, addr_byte_size)) 10711 return false; 10712 10713 address = address + 4; 10714 } 10715 else 10716 { 10717 // // Store as two word-aligned words in the correct order for current endianness. 10718 // MemA[address,4] = if BigEndian() then D[d+r]<63:32> else D[d+r]<31:0>; 10719 // MemA[address+4,4] = if BigEndian() then D[d+r]<31:0> else D[d+r]<63:32>; 10720 uint64_t data = ReadRegisterUnsigned (eRegisterKindDWARF, start_reg + d + r, 0, &success); 10721 if (!success) 10722 return false; 10723 10724 data_reg.num = start_reg + d + r; 10725 10726 if (m_byte_order == eByteOrderBig) 10727 { 10728 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, address - Rn); 10729 if (!MemAWrite (context, address, Bits64 (data, 63, 32), addr_byte_size)) 10730 return false; 10731 10732 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, (address + 4) - Rn); 10733 if (!MemAWrite (context, address+ 4, Bits64 (data, 31, 0), addr_byte_size)) 10734 return false; 10735 } 10736 else 10737 { 10738 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, address - Rn); 10739 if (!MemAWrite (context, address, Bits64 (data, 31, 0), addr_byte_size)) 10740 return false; 10741 10742 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, (address + 4) - Rn); 10743 if (!MemAWrite (context, address + 4, Bits64 (data, 63, 32), addr_byte_size)) 10744 return false; 10745 } 10746 // address = address+8; 10747 address = address + 8; 10748 } 10749 } 10750 } 10751 return true; 10752} 10753 10754// A8.6.320 10755// This instruciton loads a single extension register fronm memory, using an address from an ARM core register, with 10756// an optional offset. 10757bool 10758EmulateInstructionARM::EmulateVLDR (const uint32_t opcode, ARMEncoding encoding) 10759{ 10760#if 0 10761 if ConditionPassed() then 10762 EncodingSpecificOperations(); CheckVFPEnabled(TRUE); NullCheckIfThumbEE(n); 10763 base = if n == 15 then Align(PC,4) else R[n]; 10764 address = if add then (base + imm32) else (base - imm32); 10765 if single_reg then 10766 S[d] = MemA[address,4]; 10767 else 10768 word1 = MemA[address,4]; word2 = MemA[address+4,4]; 10769 // Combine the word-aligned words in the correct order for current endianness. 10770 D[d] = if BigEndian() then word1:word2 else word2:word1; 10771#endif 10772 10773 bool success = false; 10774 10775 if (ConditionPassed (opcode)) 10776 { 10777 bool single_reg; 10778 bool add; 10779 uint32_t imm32; 10780 uint32_t d; 10781 uint32_t n; 10782 10783 switch (encoding) 10784 { 10785 case eEncodingT1: 10786 case eEncodingA1: 10787 // single_reg = FALSE; add = (U == ‘1’); imm32 = ZeroExtend(imm8:’00’, 32); 10788 single_reg = false; 10789 add = BitIsSet (opcode, 23); 10790 imm32 = Bits32 (opcode, 7, 0) << 2; 10791 10792 // d = UInt(D:Vd); n = UInt(Rn); 10793 d = (Bit32 (opcode, 22) << 4) | Bits32 (opcode, 15, 12); 10794 n = Bits32 (opcode, 19, 16); 10795 10796 break; 10797 10798 case eEncodingT2: 10799 case eEncodingA2: 10800 // single_reg = TRUE; add = (U == ‘1’); imm32 = ZeroExtend(imm8:’00’, 32); 10801 single_reg = true; 10802 add = BitIsSet (opcode, 23); 10803 imm32 = Bits32 (opcode, 7, 0) << 2; 10804 10805 // d = UInt(Vd:D); n = UInt(Rn); 10806 d = (Bits32 (opcode, 15, 12) << 1) | Bit32 (opcode, 22); 10807 n = Bits32 (opcode, 19, 16); 10808 10809 break; 10810 10811 default: 10812 return false; 10813 } 10814 Register base_reg; 10815 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n); 10816 10817 uint32_t Rn = ReadCoreReg (n, &success); 10818 if (!success) 10819 return false; 10820 10821 // base = if n == 15 then Align(PC,4) else R[n]; 10822 uint32_t base; 10823 if (n == 15) 10824 base = AlignPC (Rn); 10825 else 10826 base = Rn; 10827 10828 // address = if add then (base + imm32) else (base - imm32); 10829 addr_t address; 10830 if (add) 10831 address = base + imm32; 10832 else 10833 address = base - imm32; 10834 10835 const uint32_t addr_byte_size = GetAddressByteSize(); 10836 uint32_t start_reg = single_reg ? dwarf_s0 : dwarf_d0; 10837 10838 EmulateInstruction::Context context; 10839 context.type = eContextRegisterLoad; 10840 context.SetRegisterPlusOffset (base_reg, address - base); 10841 10842 if (single_reg) 10843 { 10844 // S[d] = MemA[address,4]; 10845 uint32_t data = MemARead (context, address, addr_byte_size, 0, &success); 10846 if (!success) 10847 return false; 10848 10849 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, start_reg + d, data)) 10850 return false; 10851 } 10852 else 10853 { 10854 // word1 = MemA[address,4]; word2 = MemA[address+4,4]; 10855 uint32_t word1 = MemARead (context, address, addr_byte_size, 0, &success); 10856 if (!success) 10857 return false; 10858 10859 context.SetRegisterPlusOffset (base_reg, (address + 4) - base); 10860 uint32_t word2 = MemARead (context, address + 4, addr_byte_size, 0, &success); 10861 if (!success) 10862 return false; 10863 // // Combine the word-aligned words in the correct order for current endianness. 10864 // D[d] = if BigEndian() then word1:word2 else word2:word1; 10865 uint64_t data64; 10866 if (m_byte_order == eByteOrderBig) 10867 { 10868 data64 = word1; 10869 data64 = (data64 << 32) | word2; 10870 } 10871 else 10872 { 10873 data64 = word2; 10874 data64 = (data64 << 32) | word1; 10875 } 10876 10877 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, start_reg + d, data64)) 10878 return false; 10879 } 10880 } 10881 return true; 10882} 10883 10884// A8.6.400 VSTR 10885// This instruction stores a signle extension register to memory, using an address from an ARM core register, with an 10886// optional offset. 10887bool 10888EmulateInstructionARM::EmulateVSTR (const uint32_t opcode, ARMEncoding encoding) 10889{ 10890#if 0 10891 if ConditionPassed() then 10892 EncodingSpecificOperations(); CheckVFPEnabled(TRUE); NullCheckIfThumbEE(n); 10893 address = if add then (R[n] + imm32) else (R[n] - imm32); 10894 if single_reg then 10895 MemA[address,4] = S[d]; 10896 else 10897 // Store as two word-aligned words in the correct order for current endianness. 10898 MemA[address,4] = if BigEndian() then D[d]<63:32> else D[d]<31:0>; 10899 MemA[address+4,4] = if BigEndian() then D[d]<31:0> else D[d]<63:32>; 10900#endif 10901 10902 bool success = false; 10903 10904 if (ConditionPassed (opcode)) 10905 { 10906 bool single_reg; 10907 bool add; 10908 uint32_t imm32; 10909 uint32_t d; 10910 uint32_t n; 10911 10912 switch (encoding) 10913 { 10914 case eEncodingT1: 10915 case eEncodingA1: 10916 // single_reg = FALSE; add = (U == ‘1’); imm32 = ZeroExtend(imm8:’00’, 32); 10917 single_reg = false; 10918 add = BitIsSet (opcode, 23); 10919 imm32 = Bits32 (opcode, 7, 0) << 2; 10920 10921 // d = UInt(D:Vd); n = UInt(Rn); 10922 d = (Bit32 (opcode, 22) << 4) | Bits32 (opcode, 15, 12); 10923 n = Bits32 (opcode, 19, 16); 10924 10925 // if n == 15 && CurrentInstrSet() != InstrSet_ARM then UNPREDICTABLE; 10926 if ((n == 15) && (CurrentInstrSet() != eModeARM)) 10927 return false; 10928 10929 break; 10930 10931 case eEncodingT2: 10932 case eEncodingA2: 10933 // single_reg = TRUE; add = (U == ‘1’); imm32 = ZeroExtend(imm8:’00’, 32); 10934 single_reg = true; 10935 add = BitIsSet (opcode, 23); 10936 imm32 = Bits32 (opcode, 7, 0) << 2; 10937 10938 // d = UInt(Vd:D); n = UInt(Rn); 10939 d = (Bits32 (opcode, 15, 12) << 1) | Bit32 (opcode, 22); 10940 n = Bits32 (opcode, 19, 16); 10941 10942 // if n == 15 && CurrentInstrSet() != InstrSet_ARM then UNPREDICTABLE; 10943 if ((n == 15) && (CurrentInstrSet() != eModeARM)) 10944 return false; 10945 10946 break; 10947 10948 default: 10949 return false; 10950 } 10951 10952 Register base_reg; 10953 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n); 10954 10955 uint32_t Rn = ReadCoreReg (n, &success); 10956 if (!success) 10957 return false; 10958 10959 // address = if add then (R[n] + imm32) else (R[n] - imm32); 10960 addr_t address; 10961 if (add) 10962 address = Rn + imm32; 10963 else 10964 address = Rn - imm32; 10965 10966 const uint32_t addr_byte_size = GetAddressByteSize(); 10967 uint32_t start_reg = single_reg ? dwarf_s0 : dwarf_d0; 10968 10969 Register data_reg; 10970 data_reg.SetRegister (eRegisterKindDWARF, start_reg + d); 10971 EmulateInstruction::Context context; 10972 context.type = eContextRegisterStore; 10973 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, address - Rn); 10974 10975 if (single_reg) 10976 { 10977 // MemA[address,4] = S[d]; 10978 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, start_reg + d, 0, &success); 10979 if (!success) 10980 return false; 10981 10982 if (!MemAWrite (context, address, data, addr_byte_size)) 10983 return false; 10984 } 10985 else 10986 { 10987 // // Store as two word-aligned words in the correct order for current endianness. 10988 // MemA[address,4] = if BigEndian() then D[d]<63:32> else D[d]<31:0>; 10989 // MemA[address+4,4] = if BigEndian() then D[d]<31:0> else D[d]<63:32>; 10990 uint64_t data = ReadRegisterUnsigned (eRegisterKindDWARF, start_reg + d, 0, &success); 10991 if (!success) 10992 return false; 10993 10994 if (m_byte_order == eByteOrderBig) 10995 { 10996 if (!MemAWrite (context, address, Bits64 (data, 63, 32), addr_byte_size)) 10997 return false; 10998 10999 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, (address + 4) - Rn); 11000 if (!MemAWrite (context, address + 4, Bits64 (data, 31, 0), addr_byte_size)) 11001 return false; 11002 } 11003 else 11004 { 11005 if (!MemAWrite (context, address, Bits64 (data, 31, 0), addr_byte_size)) 11006 return false; 11007 11008 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, (address + 4) - Rn); 11009 if (!MemAWrite (context, address + 4, Bits64 (data, 63, 32), addr_byte_size)) 11010 return false; 11011 } 11012 } 11013 } 11014 return true; 11015} 11016 11017// A8.6.307 VLDI1 (multiple single elements) 11018// This instruction loads elements from memory into one, two, three or four registers, without de-interleaving. Every 11019// element of each register is loaded. 11020bool 11021EmulateInstructionARM::EmulateVLD1Multiple (const uint32_t opcode, ARMEncoding encoding) 11022{ 11023#if 0 11024 if ConditionPassed() then 11025 EncodingSpecificOperations(); CheckAdvSIMDEnabled(); NullCheckIfThumbEE(n); 11026 address = R[n]; if (address MOD alignment) != 0 then GenerateAlignmentException(); 11027 if wback then R[n] = R[n] + (if register_index then R[m] else 8*regs); 11028 for r = 0 to regs-1 11029 for e = 0 to elements-1 11030 Elem[D[d+r],e,esize] = MemU[address,ebytes]; 11031 address = address + ebytes; 11032#endif 11033 11034 bool success = false; 11035 11036 if (ConditionPassed (opcode)) 11037 { 11038 uint32_t regs; 11039 uint32_t alignment; 11040 uint32_t ebytes; 11041 uint32_t esize; 11042 uint32_t elements; 11043 uint32_t d; 11044 uint32_t n; 11045 uint32_t m; 11046 bool wback; 11047 bool register_index; 11048 11049 switch (encoding) 11050 { 11051 case eEncodingT1: 11052 case eEncodingA1: 11053 { 11054 // case type of 11055 // when ‘0111’ 11056 // regs = 1; if align<1> == ‘1’ then UNDEFINED; 11057 // when ‘1010’ 11058 // regs = 2; if align == ‘11’ then UNDEFINED; 11059 // when ‘0110’ 11060 // regs = 3; if align<1> == ‘1’ then UNDEFINED; 11061 // when ‘0010’ 11062 // regs = 4; 11063 // otherwise 11064 // SEE “Related encodings”; 11065 uint32_t type = Bits32 (opcode, 11, 8); 11066 uint32_t align = Bits32 (opcode, 5, 4); 11067 if (type == 7) // '0111' 11068 { 11069 regs = 1; 11070 if (BitIsSet (align, 1)) 11071 return false; 11072 } 11073 else if (type == 10) // '1010' 11074 { 11075 regs = 2; 11076 if (align == 3) 11077 return false; 11078 11079 } 11080 else if (type == 6) // '0110' 11081 { 11082 regs = 3; 11083 if (BitIsSet (align, 1)) 11084 return false; 11085 } 11086 else if (type == 2) // '0010' 11087 { 11088 regs = 4; 11089 } 11090 else 11091 return false; 11092 11093 // alignment = if align == ‘00’ then 1 else 4 << UInt(align); 11094 if (align == 0) 11095 alignment = 1; 11096 else 11097 alignment = 4 << align; 11098 11099 // ebytes = 1 << UInt(size); esize = 8 * ebytes; elements = 8 DIV ebytes; 11100 ebytes = 1 << Bits32 (opcode, 7, 6); 11101 esize = 8 * ebytes; 11102 elements = 8 / ebytes; 11103 11104 // d = UInt(D:Vd); n = UInt(Rn); m = UInt(Rm); 11105 d = (Bit32 (opcode, 22) << 4) | Bits32 (opcode, 15, 12); 11106 n = Bits32 (opcode, 19, 15); 11107 m = Bits32 (opcode, 3, 0); 11108 11109 // wback = (m != 15); register_index = (m != 15 && m != 13); 11110 wback = (m != 15); 11111 register_index = ((m != 15) && (m != 13)); 11112 11113 // if d+regs > 32 then UNPREDICTABLE; 11114 if ((d + regs) > 32) 11115 return false; 11116 } 11117 break; 11118 11119 default: 11120 return false; 11121 } 11122 11123 Register base_reg; 11124 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n); 11125 11126 uint32_t Rn = ReadCoreReg (n, &success); 11127 if (!success) 11128 return false; 11129 11130 // address = R[n]; if (address MOD alignment) != 0 then GenerateAlignmentException(); 11131 addr_t address = Rn; 11132 if ((address % alignment) != 0) 11133 return false; 11134 11135 EmulateInstruction::Context context; 11136 // if wback then R[n] = R[n] + (if register_index then R[m] else 8*regs); 11137 if (wback) 11138 { 11139 uint32_t Rm = ReadCoreReg (m, &success); 11140 if (!success) 11141 return false; 11142 11143 uint32_t offset; 11144 if (register_index) 11145 offset = Rm; 11146 else 11147 offset = 8 * regs; 11148 11149 uint32_t value = Rn + offset; 11150 context.type = eContextAdjustBaseRegister; 11151 context.SetRegisterPlusOffset (base_reg, offset); 11152 11153 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, value)) 11154 return false; 11155 11156 } 11157 11158 // for r = 0 to regs-1 11159 for (int r = 0; r < regs; ++r) 11160 { 11161 // for e = 0 to elements-1 11162 uint64_t assembled_data = 0; 11163 for (int e = 0; e < elements; ++e) 11164 { 11165 // Elem[D[d+r],e,esize] = MemU[address,ebytes]; 11166 context.type = eContextRegisterLoad; 11167 context.SetRegisterPlusOffset (base_reg, address - Rn); 11168 uint64_t data = MemURead (context, address, ebytes, 0, &success); 11169 if (!success) 11170 return false; 11171 11172 assembled_data = (data << (e * esize)) | assembled_data; // New data goes to the left of existing data 11173 11174 // address = address + ebytes; 11175 address = address + ebytes; 11176 } 11177 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_d0 + d + r, assembled_data)) 11178 return false; 11179 } 11180 } 11181 return true; 11182} 11183 11184// A8.6.308 VLD1 (single element to one lane) 11185// 11186bool 11187EmulateInstructionARM::EmulateVLD1Single (const uint32_t opcode, const ARMEncoding encoding) 11188{ 11189#if 0 11190 if ConditionPassed() then 11191 EncodingSpecificOperations(); CheckAdvSIMDEnabled(); NullCheckIfThumbEE(n); 11192 address = R[n]; if (address MOD alignment) != 0 then GenerateAlignmentException(); 11193 if wback then R[n] = R[n] + (if register_index then R[m] else ebytes); 11194 Elem[D[d],index,esize] = MemU[address,ebytes]; 11195#endif 11196 11197 bool success = false; 11198 11199 if (ConditionPassed (opcode)) 11200 { 11201 uint32_t ebytes; 11202 uint32_t esize; 11203 uint32_t index; 11204 uint32_t alignment; 11205 uint32_t d; 11206 uint32_t n; 11207 uint32_t m; 11208 bool wback; 11209 bool register_index; 11210 11211 switch (encoding) 11212 { 11213 case eEncodingT1: 11214 case eEncodingA1: 11215 { 11216 uint32_t size = Bits32 (opcode, 11, 10); 11217 uint32_t index_align = Bits32 (opcode, 7, 4); 11218 // if size == ‘11’ then SEE VLD1 (single element to all lanes); 11219 // if (size == 3) 11220 // return EmulateVLD1SingleAll (opcode, encoding); 11221 // case size of 11222 if (size == 0) // when '00' 11223 { 11224 // if index_align<0> != ‘0’ then UNDEFINED; 11225 if (BitIsClear (index_align, 0)) 11226 return false; 11227 11228 // ebytes = 1; esize = 8; index = UInt(index_align<3:1>); alignment = 1; 11229 ebytes = 1; 11230 esize = 8; 11231 index = Bits32 (index_align, 3, 1); 11232 alignment = 1; 11233 } 11234 else if (size == 1) // when ‘01’ 11235 { 11236 // if index_align<1> != ‘0’ then UNDEFINED; 11237 if (BitIsClear (index_align, 1)) 11238 return false; 11239 11240 // ebytes = 2; esize = 16; index = UInt(index_align<3:2>); 11241 ebytes = 2; 11242 esize = 16; 11243 index = Bits32 (index_align, 3, 2); 11244 11245 // alignment = if index_align<0> == ‘0’ then 1 else 2; 11246 if (BitIsClear (index_align, 0)) 11247 alignment = 1; 11248 else 11249 alignment = 2; 11250 } 11251 else if (size == 2) // when ‘10’ 11252 { 11253 // if index_align<2> != ‘0’ then UNDEFINED; 11254 if (BitIsClear (index_align, 2)) 11255 return false; 11256 11257 // if index_align<1:0> != ‘00’ && index_align<1:0> != ‘11’ then UNDEFINED; 11258 if ((Bits32 (index_align, 1, 0) != 0) && (Bits32 (index_align, 1, 0) != 3)) 11259 return false; 11260 11261 // ebytes = 4; esize = 32; index = UInt(index_align<3>); 11262 ebytes = 4; 11263 esize = 32; 11264 index = Bit32 (index_align, 3); 11265 11266 // alignment = if index_align<1:0> == ‘00’ then 1 else 4; 11267 if (Bits32 (index_align, 1, 0) == 0) 11268 alignment = 1; 11269 else 11270 alignment = 4; 11271 } 11272 // d = UInt(D:Vd); n = UInt(Rn); m = UInt(Rm); 11273 d = (Bit32 (opcode, 22) << 4) | Bits32 (opcode, 15, 12); 11274 n = Bits32 (opcode, 19, 16); 11275 m = Bits32 (opcode, 3, 0); 11276 11277 // wback = (m != 15); register_index = (m != 15 && m != 13); if n == 15 then UNPREDICTABLE; 11278 wback = (m != 15); 11279 register_index = ((m != 15) && (m != 13)); 11280 11281 if (n == 15) 11282 return false; 11283 11284 } 11285 break; 11286 11287 default: 11288 return false; 11289 } 11290 11291 Register base_reg; 11292 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n); 11293 11294 uint32_t Rn = ReadCoreReg (n, &success); 11295 if (!success) 11296 return false; 11297 11298 // address = R[n]; if (address MOD alignment) != 0 then GenerateAlignmentException(); 11299 addr_t address = Rn; 11300 if ((address % alignment) != 0) 11301 return false; 11302 11303 EmulateInstruction::Context context; 11304 // if wback then R[n] = R[n] + (if register_index then R[m] else ebytes); 11305 if (wback) 11306 { 11307 uint32_t Rm = ReadCoreReg (m, &success); 11308 if (!success) 11309 return false; 11310 11311 uint32_t offset; 11312 if (register_index) 11313 offset = Rm; 11314 else 11315 offset = ebytes; 11316 11317 uint32_t value = Rn + offset; 11318 11319 context.type = eContextAdjustBaseRegister; 11320 context.SetRegisterPlusOffset (base_reg, offset); 11321 11322 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, value)) 11323 return false; 11324 } 11325 11326 // Elem[D[d],index,esize] = MemU[address,ebytes]; 11327 uint32_t element = MemURead (context, address, esize, 0, &success); 11328 if (!success) 11329 return false; 11330 11331 element = element << (index * esize); 11332 11333 uint64_t reg_data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_d0 + d, 0, &success); 11334 if (!success) 11335 return false; 11336 11337 uint64_t all_ones = -1; 11338 uint64_t mask = all_ones << ((index+1) * esize); // mask is all 1's to left of where 'element' goes, & all 0's 11339 // at element & to the right of element. 11340 if (index > 0) 11341 mask = mask | Bits64 (all_ones, (index * esize) - 1, 0); // add 1's to the right of where 'element' goes. 11342 // now mask should be 0's where element goes & 1's 11343 // everywhere else. 11344 11345 uint64_t masked_reg = reg_data & mask; // Take original reg value & zero out 'element' bits 11346 reg_data = masked_reg & element; // Put 'element' into those bits in reg_data. 11347 11348 context.type = eContextRegisterLoad; 11349 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + d, reg_data)) 11350 return false; 11351 } 11352 return true; 11353} 11354 11355// A8.6.391 VST1 (multiple single elements) 11356// Vector Store (multiple single elements) stores elements to memory from one, two, three, or four regsiters, without 11357// interleaving. Every element of each register is stored. 11358bool 11359EmulateInstructionARM::EmulateVST1Multiple (const uint32_t opcode, ARMEncoding encoding) 11360{ 11361#if 0 11362 if ConditionPassed() then 11363 EncodingSpecificOperations(); CheckAdvSIMDEnabled(); NullCheckIfThumbEE(n); 11364 address = R[n]; if (address MOD alignment) != 0 then GenerateAlignmentException(); 11365 if wback then R[n] = R[n] + (if register_index then R[m] else 8*regs); 11366 for r = 0 to regs-1 11367 for e = 0 to elements-1 11368 MemU[address,ebytes] = Elem[D[d+r],e,esize]; 11369 address = address + ebytes; 11370#endif 11371 11372 bool success = false; 11373 11374 if (ConditionPassed (opcode)) 11375 { 11376 uint32_t regs; 11377 uint32_t alignment; 11378 uint32_t ebytes; 11379 uint32_t esize; 11380 uint32_t elements; 11381 uint32_t d; 11382 uint32_t n; 11383 uint32_t m; 11384 bool wback; 11385 bool register_index; 11386 11387 switch (encoding) 11388 { 11389 case eEncodingT1: 11390 case eEncodingA1: 11391 { 11392 uint32_t type = Bits32 (opcode, 11, 8); 11393 uint32_t align = Bits32 (opcode, 5, 4); 11394 11395 // case type of 11396 if (type == 7) // when ‘0111’ 11397 { 11398 // regs = 1; if align<1> == ‘1’ then UNDEFINED; 11399 regs = 1; 11400 if (BitIsSet (align, 1)) 11401 return false; 11402 } 11403 else if (type == 10) // when ‘1010’ 11404 { 11405 // regs = 2; if align == ‘11’ then UNDEFINED; 11406 regs = 2; 11407 if (align == 3) 11408 return false; 11409 } 11410 else if (type == 6) // when ‘0110’ 11411 { 11412 // regs = 3; if align<1> == ‘1’ then UNDEFINED; 11413 regs = 3; 11414 if (BitIsSet (align, 1)) 11415 return false; 11416 } 11417 else if (type == 2) // when ‘0010’ 11418 // regs = 4; 11419 regs = 4; 11420 else // otherwise 11421 // SEE “Related encodings”; 11422 return false; 11423 11424 // alignment = if align == ‘00’ then 1 else 4 << UInt(align); 11425 if (align == 0) 11426 alignment = 0; 11427 else 11428 alignment = 4 << align; 11429 11430 // ebytes = 1 << UInt(size); esize = 8 * ebytes; elements = 8 DIV ebytes; 11431 ebytes = 1 << Bits32 (opcode,7, 6); 11432 esize = 8 * ebytes; 11433 elements = 8 / ebytes; 11434 11435 // d = UInt(D:Vd); n = UInt(Rn); m = UInt(Rm); 11436 d = (Bit32 (opcode, 22) << 4) | Bits32 (opcode, 15, 12); 11437 n = Bits32 (opcode, 19, 16); 11438 m = Bits32 (opcode, 3, 0); 11439 11440 // wback = (m != 15); register_index = (m != 15 && m != 13); 11441 wback = (m != 15); 11442 register_index = ((m != 15) && (m != 13)); 11443 11444 // if d+regs > 32 then UNPREDICTABLE; if n == 15 then UNPREDICTABLE; 11445 if ((d + regs) > 32) 11446 return false; 11447 11448 if (n == 15) 11449 return false; 11450 11451 } 11452 break; 11453 11454 default: 11455 return false; 11456 } 11457 11458 Register base_reg; 11459 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n); 11460 11461 uint32_t Rn = ReadCoreReg (n, &success); 11462 if (!success) 11463 return false; 11464 11465 // address = R[n]; if (address MOD alignment) != 0 then GenerateAlignmentException(); 11466 addr_t address = Rn; 11467 if ((address % alignment) != 0) 11468 return false; 11469 11470 EmulateInstruction::Context context; 11471 // if wback then R[n] = R[n] + (if register_index then R[m] else 8*regs); 11472 if (wback) 11473 { 11474 uint32_t Rm = ReadCoreReg (m, &success); 11475 if (!success) 11476 return false; 11477 11478 uint32_t offset; 11479 if (register_index) 11480 offset = Rm; 11481 else 11482 offset = 8 * regs; 11483 11484 context.type = eContextAdjustBaseRegister; 11485 context.SetRegisterPlusOffset (base_reg, offset); 11486 11487 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, Rn + offset)) 11488 return false; 11489 } 11490 11491 context.type = eContextRegisterStore; 11492 Register data_reg; 11493 data_reg.SetRegister (eRegisterKindDWARF, 0); 11494 // for r = 0 to regs-1 11495 for (int r = 0; r < regs; ++r) 11496 { 11497 data_reg.num = dwarf_d0 + d + r; 11498 uint64_t register_data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_d0 + d + r, 0, &success); 11499 if (!success) 11500 return false; 11501 11502 // for e = 0 to elements-1 11503 for (int e = 0; e < elements; ++e) 11504 { 11505 // MemU[address,ebytes] = Elem[D[d+r],e,esize]; 11506 uint64_t word = Bits64 (register_data, ((e + 1) * esize) - 1, e * esize); 11507 11508 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, address - Rn); 11509 if (!MemUWrite (context, address, word, ebytes)) 11510 return false; 11511 11512 // address = address + ebytes; 11513 address = address + ebytes; 11514 } 11515 } 11516 } 11517 return true; 11518} 11519 11520// A8.6.392 VST1 (single element from one lane) 11521// This instruction stores one element to memory from one element of a register. 11522bool 11523EmulateInstructionARM::EmulateVST1Single (const uint32_t opcode, ARMEncoding encoding) 11524{ 11525#if 0 11526 if ConditionPassed() then 11527 EncodingSpecificOperations(); CheckAdvSIMDEnabled(); NullCheckIfThumbEE(n); 11528 address = R[n]; if (address MOD alignment) != 0 then GenerateAlignmentException(); 11529 if wback then R[n] = R[n] + (if register_index then R[m] else ebytes); 11530 MemU[address,ebytes] = Elem[D[d],index,esize]; 11531#endif 11532 11533 bool success = false; 11534 11535 if (ConditionPassed (opcode)) 11536 { 11537 uint32_t ebytes; 11538 uint32_t esize; 11539 uint32_t index; 11540 uint32_t alignment; 11541 uint32_t d; 11542 uint32_t n; 11543 uint32_t m; 11544 bool wback; 11545 bool register_index; 11546 11547 switch (encoding) 11548 { 11549 case eEncodingT1: 11550 case eEncodingA1: 11551 { 11552 uint32_t size = Bits32 (opcode, 11, 10); 11553 uint32_t index_align = Bits32 (opcode, 7, 4); 11554 11555 // if size == ‘11’ then UNDEFINED; 11556 if (size == 3) 11557 return false; 11558 11559 // case size of 11560 if (size == 0) // when ‘00’ 11561 { 11562 // if index_align<0> != ‘0’ then UNDEFINED; 11563 if (BitIsClear (index_align, 0)) 11564 return false; 11565 // ebytes = 1; esize = 8; index = UInt(index_align<3:1>); alignment = 1; 11566 ebytes = 1; 11567 esize = 8; 11568 index = Bits32 (index_align, 3, 1); 11569 alignment = 1; 11570 } 11571 else if (size == 1) // when ‘01’ 11572 { 11573 // if index_align<1> != ‘0’ then UNDEFINED; 11574 if (BitIsClear (index_align, 1)) 11575 return false; 11576 11577 // ebytes = 2; esize = 16; index = UInt(index_align<3:2>); 11578 ebytes = 2; 11579 esize = 16; 11580 index = Bits32 (index_align, 3, 2); 11581 11582 // alignment = if index_align<0> == ‘0’ then 1 else 2; 11583 if (BitIsClear (index_align, 0)) 11584 alignment = 1; 11585 else 11586 alignment = 2; 11587 } 11588 else if (size == 2) // when ‘10’ 11589 { 11590 // if index_align<2> != ‘0’ then UNDEFINED; 11591 if (BitIsClear (index_align, 2)) 11592 return false; 11593 11594 // if index_align<1:0> != ‘00’ && index_align<1:0> != ‘11’ then UNDEFINED; 11595 if ((Bits32 (index_align, 1, 0) != 0) && (Bits32 (index_align, 1, 0) != 3)) 11596 return false; 11597 11598 // ebytes = 4; esize = 32; index = UInt(index_align<3>); 11599 ebytes = 4; 11600 esize = 32; 11601 index = Bit32 (index_align, 3); 11602 11603 // alignment = if index_align<1:0> == ‘00’ then 1 else 4; 11604 if (Bits32 (index_align, 1, 0) == 0) 11605 alignment = 1; 11606 else 11607 alignment = 4; 11608 } 11609 // d = UInt(D:Vd); n = UInt(Rn); m = UInt(Rm); 11610 d = (Bit32 (opcode, 22) << 4) | Bits32 (opcode, 15, 12); 11611 n = Bits32 (opcode, 19, 16); 11612 m = Bits32 (opcode, 3, 0); 11613 11614 // wback = (m != 15); register_index = (m != 15 && m != 13); if n == 15 then UNPREDICTABLE; 11615 wback = (m != 15); 11616 register_index = ((m != 15) && (m != 13)); 11617 11618 if (n == 15) 11619 return false; 11620 } 11621 break; 11622 11623 default: 11624 return false; 11625 } 11626 11627 Register base_reg; 11628 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n); 11629 11630 uint32_t Rn = ReadCoreReg (n, &success); 11631 if (!success) 11632 return false; 11633 11634 // address = R[n]; if (address MOD alignment) != 0 then GenerateAlignmentException(); 11635 addr_t address = Rn; 11636 if ((address % alignment) != 0) 11637 return false; 11638 11639 EmulateInstruction::Context context; 11640 // if wback then R[n] = R[n] + (if register_index then R[m] else ebytes); 11641 if (wback) 11642 { 11643 uint32_t Rm = ReadCoreReg (m, &success); 11644 if (!success) 11645 return false; 11646 11647 uint32_t offset; 11648 if (register_index) 11649 offset = Rm; 11650 else 11651 offset = ebytes; 11652 11653 context.type = eContextAdjustBaseRegister; 11654 context.SetRegisterPlusOffset (base_reg, offset); 11655 11656 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, Rn + offset)) 11657 return false; 11658 } 11659 11660 // MemU[address,ebytes] = Elem[D[d],index,esize]; 11661 uint64_t register_data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_d0 + d, 0, &success); 11662 if (!success) 11663 return false; 11664 11665 uint64_t word = Bits64 (register_data, ((index + 1) * esize) - 1, index * esize); 11666 11667 Register data_reg; 11668 data_reg.SetRegister (eRegisterKindDWARF, dwarf_d0 + d); 11669 context.type = eContextRegisterStore; 11670 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, address - Rn); 11671 11672 if (!MemUWrite (context, address, word, ebytes)) 11673 return false; 11674 } 11675 return true; 11676} 11677 11678// A8.6.309 VST1 (single element to all lanes) 11679// 11680bool 11681EmulateInstructionARM::EmulateVST1SingleAll (const uint32_t opcode, const ARMEncoding encoding) 11682{ 11683#if 0 11684 if ConditionPassed() then 11685 EncodingSpecificOperations(); CheckAdvSIMDEnabled(); NullCheckIfThumbEE(n); 11686 address = R[n]; if (address MOD alignment) != 0 then GenerateAlignmentException(); 11687 if wback then R[n] = R[n] + (if register_index then R[m] else ebytes); 11688 replicated_element = Replicate(MemU[address,ebytes], elements); 11689 for r = 0 to regs-1 11690 D[d+r] = replicated_element; 11691#endif 11692 11693 bool success = false; 11694 11695 if (ConditionPassed (opcode)) 11696 { 11697 uint32_t ebytes; 11698 uint32_t elements; 11699 uint32_t regs; 11700 uint32_t alignment; 11701 uint32_t d; 11702 uint32_t n; 11703 uint32_t m; 11704 bool wback; 11705 bool register_index; 11706 11707 switch (encoding) 11708 { 11709 case eEncodingT1: 11710 case eEncodingA1: 11711 { 11712 //if size == ‘11’ || (size == ‘00’ && a == ‘1’) then UNDEFINED; 11713 uint32_t size = Bits32 (opcode, 7, 6); 11714 if ((size == 3) || ((size == 0) && BitIsSet (opcode, 4))) 11715 return false; 11716 11717 //ebytes = 1 << UInt(size); elements = 8 DIV ebytes; regs = if T == ‘0’ then 1 else 2; 11718 ebytes = 1 << size; 11719 elements = 8 / ebytes; 11720 if (BitIsClear (opcode, 5)) 11721 regs = 1; 11722 else 11723 regs = 2; 11724 11725 //alignment = if a == ‘0’ then 1 else ebytes; 11726 if (BitIsClear (opcode, 4)) 11727 alignment = 1; 11728 else 11729 alignment = ebytes; 11730 11731 //d = UInt(D:Vd); n = UInt(Rn); m = UInt(Rm); 11732 d = (Bit32 (opcode, 22) << 4) | Bits32 (opcode, 15, 12); 11733 n = Bits32 (opcode, 19, 16); 11734 m = Bits32 (opcode, 3, 0); 11735 11736 //wback = (m != 15); register_index = (m != 15 && m != 13); 11737 wback = (m != 15); 11738 register_index = ((m != 15) && (m != 13)); 11739 11740 //if d+regs > 32 then UNPREDICTABLE; if n == 15 then UNPREDICTABLE; 11741 if ((d + regs) > 32) 11742 return false; 11743 11744 if (n == 15) 11745 return false; 11746 } 11747 break; 11748 11749 default: 11750 break; 11751 } 11752 11753 Register base_reg; 11754 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 +n); 11755 11756 uint32_t Rn = ReadCoreReg (n, &success); 11757 if (!success) 11758 return false; 11759 11760 // address = R[n]; if (address MOD alignment) != 0 then GenerateAlignmentException(); 11761 addr_t address = Rn; 11762 if ((address % alignment) != 0) 11763 return false; 11764 11765 EmulateInstruction::Context context; 11766 // if wback then R[n] = R[n] + (if register_index then R[m] else ebytes); 11767 if (wback) 11768 { 11769 uint32_t Rm = ReadCoreReg (m, &success); 11770 if (!success) 11771 return false; 11772 11773 uint32_t offset; 11774 if (register_index) 11775 offset = Rm; 11776 else 11777 offset = ebytes; 11778 11779 context.type = eContextAdjustBaseRegister; 11780 context.SetRegisterPlusOffset (base_reg, offset); 11781 11782 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, Rn + offset)) 11783 return false; 11784 } 11785 11786 // replicated_element = Replicate(MemU[address,ebytes], elements); 11787 11788 context.type = eContextRegisterLoad; 11789 uint64_t word = MemURead (context, address, ebytes, 0, &success); 11790 if (!success) 11791 return false; 11792 11793 uint64_t replicated_element; 11794 uint32_t esize = ebytes * 8; 11795 for (int e = 0; e < elements; ++e) 11796 replicated_element = (replicated_element << esize) | Bits64 (word, esize - 1, 0); 11797 11798 // for r = 0 to regs-1 11799 for (int r = 0; r < regs; ++r) 11800 { 11801 // D[d+r] = replicated_element; 11802 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_d0 + d + r, replicated_element)) 11803 return false; 11804 } 11805 } 11806 return true; 11807} 11808 11809EmulateInstructionARM::ARMOpcode* 11810EmulateInstructionARM::GetARMOpcodeForInstruction (const uint32_t opcode) 11811{ 11812 static ARMOpcode 11813 g_arm_opcodes[] = 11814 { 11815 //---------------------------------------------------------------------- 11816 // Prologue instructions 11817 //---------------------------------------------------------------------- 11818 11819 // push register(s) 11820 { 0x0fff0000, 0x092d0000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulatePUSH, "push <registers>" }, 11821 { 0x0fff0fff, 0x052d0004, ARMvAll, eEncodingA2, No_VFP, eSize32, &EmulateInstructionARM::EmulatePUSH, "push <register>" }, 11822 11823 // set r7 to point to a stack offset 11824 { 0x0ffff000, 0x028d7000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateADDRdSPImm, "add r7, sp, #<const>" }, 11825 { 0x0ffff000, 0x024c7000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBR7IPImm, "sub r7, ip, #<const>"}, 11826 // copy the stack pointer to ip 11827 { 0x0fffffff, 0x01a0c00d, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateMOVRdSP, "mov ip, sp" }, 11828 { 0x0ffff000, 0x028dc000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateADDRdSPImm, "add ip, sp, #<const>" }, 11829 { 0x0ffff000, 0x024dc000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBIPSPImm, "sub ip, sp, #<const>"}, 11830 11831 // adjust the stack pointer 11832 { 0x0ffff000, 0x024dd000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBSPImm, "sub sp, sp, #<const>"}, 11833 { 0x0fef0010, 0x004d0000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBSPReg, "sub{s}<c> <Rd>, sp, <Rm>{,<shift>}" }, 11834 11835 // push one register 11836 // if Rn == '1101' && imm12 == '000000000100' then SEE PUSH; 11837 { 0x0e5f0000, 0x040d0000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTRRtSP, "str Rt, [sp, #-imm12]!" }, 11838 11839 // vector push consecutive extension register(s) 11840 { 0x0fbf0f00, 0x0d2d0b00, ARMV6T2_ABOVE, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateVPUSH, "vpush.64 <list>"}, 11841 { 0x0fbf0f00, 0x0d2d0a00, ARMV6T2_ABOVE, eEncodingA2, No_VFP, eSize32, &EmulateInstructionARM::EmulateVPUSH, "vpush.32 <list>"}, 11842 11843 //---------------------------------------------------------------------- 11844 // Epilogue instructions 11845 //---------------------------------------------------------------------- 11846 11847 { 0x0fff0000, 0x08bd0000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulatePOP, "pop <registers>"}, 11848 { 0x0fff0fff, 0x049d0004, ARMvAll, eEncodingA2, No_VFP, eSize32, &EmulateInstructionARM::EmulatePOP, "pop <register>"}, 11849 { 0x0fbf0f00, 0x0cbd0b00, ARMV6T2_ABOVE, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateVPOP, "vpop.64 <list>"}, 11850 { 0x0fbf0f00, 0x0cbd0a00, ARMV6T2_ABOVE, eEncodingA2, No_VFP, eSize32, &EmulateInstructionARM::EmulateVPOP, "vpop.32 <list>"}, 11851 11852 //---------------------------------------------------------------------- 11853 // Supervisor Call (previously Software Interrupt) 11854 //---------------------------------------------------------------------- 11855 { 0x0f000000, 0x0f000000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSVC, "svc #imm24"}, 11856 11857 //---------------------------------------------------------------------- 11858 // Branch instructions 11859 //---------------------------------------------------------------------- 11860 { 0x0f000000, 0x0a000000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateB, "b #imm24"}, 11861 // To resolve ambiguity, "blx <label>" should come before "bl <label>". 11862 { 0xfe000000, 0xfa000000, ARMV5_ABOVE, eEncodingA2, No_VFP, eSize32, &EmulateInstructionARM::EmulateBLXImmediate, "blx <label>"}, 11863 { 0x0f000000, 0x0b000000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateBLXImmediate, "bl <label>"}, 11864 { 0x0ffffff0, 0x012fff30, ARMV5_ABOVE, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateBLXRm, "blx <Rm>"}, 11865 // for example, "bx lr" 11866 { 0x0ffffff0, 0x012fff10, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateBXRm, "bx <Rm>"}, 11867 // bxj 11868 { 0x0ffffff0, 0x012fff20, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateBXJRm, "bxj <Rm>"}, 11869 11870 //---------------------------------------------------------------------- 11871 // Data-processing instructions 11872 //---------------------------------------------------------------------- 11873 // adc (immediate) 11874 { 0x0fe00000, 0x02a00000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateADCImm, "adc{s}<c> <Rd>, <Rn>, #const"}, 11875 // adc (register) 11876 { 0x0fe00010, 0x00a00000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateADCReg, "adc{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"}, 11877 // add (immediate) 11878 { 0x0fe00000, 0x02800000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateADDImmARM, "add{s}<c> <Rd>, <Rn>, #const"}, 11879 // add (register) 11880 { 0x0fe00010, 0x00800000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateADDReg, "add{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"}, 11881 // add (register-shifted register) 11882 { 0x0fe00090, 0x00800010, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateADDRegShift, "add{s}<c> <Rd>, <Rn>m, <Rm>, <type> <RS>"}, 11883 // adr 11884 { 0x0fff0000, 0x028f0000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateADR, "add<c> <Rd>, PC, #<const>"}, 11885 { 0x0fff0000, 0x024f0000, ARMvAll, eEncodingA2, No_VFP, eSize32, &EmulateInstructionARM::EmulateADR, "sub<c> <Rd>, PC, #<const>"}, 11886 // and (immediate) 11887 { 0x0fe00000, 0x02000000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateANDImm, "and{s}<c> <Rd>, <Rn>, #const"}, 11888 // and (register) 11889 { 0x0fe00010, 0x00000000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateANDReg, "and{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"}, 11890 // bic (immediate) 11891 { 0x0fe00000, 0x03c00000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateBICImm, "bic{s}<c> <Rd>, <Rn>, #const"}, 11892 // bic (register) 11893 { 0x0fe00010, 0x01c00000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateBICReg, "bic{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"}, 11894 // eor (immediate) 11895 { 0x0fe00000, 0x02200000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateEORImm, "eor{s}<c> <Rd>, <Rn>, #const"}, 11896 // eor (register) 11897 { 0x0fe00010, 0x00200000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateEORReg, "eor{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"}, 11898 // orr (immediate) 11899 { 0x0fe00000, 0x03800000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateORRImm, "orr{s}<c> <Rd>, <Rn>, #const"}, 11900 // orr (register) 11901 { 0x0fe00010, 0x01800000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateORRReg, "orr{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"}, 11902 // rsb (immediate) 11903 { 0x0fe00000, 0x02600000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateRSBImm, "rsb{s}<c> <Rd>, <Rn>, #<const>"}, 11904 // rsb (register) 11905 { 0x0fe00010, 0x00600000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateRSBReg, "rsb{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"}, 11906 // rsc (immediate) 11907 { 0x0fe00000, 0x02e00000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateRSCImm, "rsc{s}<c> <Rd>, <Rn>, #<const>"}, 11908 // rsc (register) 11909 { 0x0fe00010, 0x00e00000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateRSCReg, "rsc{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"}, 11910 // sbc (immediate) 11911 { 0x0fe00000, 0x02c00000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSBCImm, "sbc{s}<c> <Rd>, <Rn>, #<const>"}, 11912 // sbc (register) 11913 { 0x0fe00010, 0x00c00000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSBCReg, "sbc{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"}, 11914 // sub (immediate, ARM) 11915 { 0x0fe00000, 0x02400000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBImmARM, "sub{s}<c> <Rd>, <Rn>, #<const>"}, 11916 // sub (sp minus immediate) 11917 { 0x0fef0000, 0x024d0000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBSPImm, "sub{s}<c> <Rd>, sp, #<const>"}, 11918 // sub (register) 11919 { 0x0fe00010, 0x00400000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBReg, "sub{s}<c> <Rd>, <Rn>, <Rm>{,<shift>}"}, 11920 // teq (immediate) 11921 { 0x0ff0f000, 0x03300000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateTEQImm, "teq<c> <Rn>, #const"}, 11922 // teq (register) 11923 { 0x0ff0f010, 0x01300000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateTEQReg, "teq<c> <Rn>, <Rm> {,<shift>}"}, 11924 // tst (immediate) 11925 { 0x0ff0f000, 0x03100000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateTSTImm, "tst<c> <Rn>, #const"}, 11926 // tst (register) 11927 { 0x0ff0f010, 0x01100000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateTSTReg, "tst<c> <Rn>, <Rm> {,<shift>}"}, 11928 11929 // mov (immediate) 11930 { 0x0fef0000, 0x03a00000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateMOVRdImm, "mov{s}<c> <Rd>, #<const>"}, 11931 { 0x0ff00000, 0x03000000, ARMV6T2_ABOVE, eEncodingA2, No_VFP, eSize32, &EmulateInstructionARM::EmulateMOVRdImm, "movw<c> <Rd>, #<imm16>" }, 11932 // mov (register) 11933 { 0x0fef0ff0, 0x01a00000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateMOVRdRm, "mov{s}<c> <Rd>, <Rm>"}, 11934 // mvn (immediate) 11935 { 0x0fef0000, 0x03e00000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateMVNImm, "mvn{s}<c> <Rd>, #<const>"}, 11936 // mvn (register) 11937 { 0x0fef0010, 0x01e00000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateMVNReg, "mvn{s}<c> <Rd>, <Rm> {,<shift>}"}, 11938 // cmn (immediate) 11939 { 0x0ff0f000, 0x03700000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateCMNImm, "cmn<c> <Rn>, #<const>"}, 11940 // cmn (register) 11941 { 0x0ff0f010, 0x01700000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateCMNReg, "cmn<c> <Rn>, <Rm> {,<shift>}"}, 11942 // cmp (immediate) 11943 { 0x0ff0f000, 0x03500000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateCMPImm, "cmp<c> <Rn>, #<const>"}, 11944 // cmp (register) 11945 { 0x0ff0f010, 0x01500000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateCMPReg, "cmp<c> <Rn>, <Rm> {,<shift>}"}, 11946 // asr (immediate) 11947 { 0x0fef0070, 0x01a00040, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateASRImm, "asr{s}<c> <Rd>, <Rm>, #imm"}, 11948 // asr (register) 11949 { 0x0fef00f0, 0x01a00050, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateASRReg, "asr{s}<c> <Rd>, <Rn>, <Rm>"}, 11950 // lsl (immediate) 11951 { 0x0fef0070, 0x01a00000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLSLImm, "lsl{s}<c> <Rd>, <Rm>, #imm"}, 11952 // lsl (register) 11953 { 0x0fef00f0, 0x01a00010, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLSLReg, "lsl{s}<c> <Rd>, <Rn>, <Rm>"}, 11954 // lsr (immediate) 11955 { 0x0fef0070, 0x01a00020, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLSRImm, "lsr{s}<c> <Rd>, <Rm>, #imm"}, 11956 // lsr (register) 11957 { 0x0fef00f0, 0x01a00050, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLSRReg, "lsr{s}<c> <Rd>, <Rn>, <Rm>"}, 11958 // rrx is a special case encoding of ror (immediate) 11959 { 0x0fef0ff0, 0x01a00060, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateRRX, "rrx{s}<c> <Rd>, <Rm>"}, 11960 // ror (immediate) 11961 { 0x0fef0070, 0x01a00060, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateRORImm, "ror{s}<c> <Rd>, <Rm>, #imm"}, 11962 // ror (register) 11963 { 0x0fef00f0, 0x01a00070, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateRORReg, "ror{s}<c> <Rd>, <Rn>, <Rm>"}, 11964 // mul 11965 { 0x0fe000f0, 0x00000090, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateMUL, "mul{s}<c> <Rd>,<R>,<Rm>" }, 11966 11967 //---------------------------------------------------------------------- 11968 // Load instructions 11969 //---------------------------------------------------------------------- 11970 { 0x0fd00000, 0x08900000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDM, "ldm<c> <Rn>{!} <registers>" }, 11971 { 0x0fd00000, 0x08100000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDMDA, "ldmda<c> <Rn>{!} <registers>" }, 11972 { 0x0fd00000, 0x09100000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDMDB, "ldmdb<c> <Rn>{!} <registers>" }, 11973 { 0x0fd00000, 0x09900000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDMIB, "ldmib<c> <Rn<{!} <registers>" }, 11974 { 0x0e500000, 0x04100000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRImmediateARM, "ldr<c> <Rt> [<Rn> {#+/-<imm12>}]" }, 11975 { 0x0e500010, 0x06100000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRRegister, "ldr<c> <Rt> [<Rn> +/-<Rm> {<shift>}] {!}" }, 11976 { 0x0e5f0000, 0x045f0000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRBLiteral, "ldrb<c> <Rt>, [...]"}, 11977 { 0xfe500010, 0x06500000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRBRegister, "ldrb<c> <Rt>, [<Rn>,+/-<Rm>{, <shift>}]{!}" }, 11978 { 0x0e5f00f0, 0x005f00b0, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRHLiteral, "ldrh<c> <Rt>, <label>" }, 11979 { 0x0e5000f0, 0x001000b0, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRHRegister, "ldrh<c> <Rt>,[<Rn>,+/-<Rm>]{!}" }, 11980 { 0x0e5000f0, 0x005000d0, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRSBImmediate, "ldrsb<c> <Rt>, [<Rn>{,#+/-<imm8>}]" }, 11981 { 0x0e5f00f0, 0x005f00d0, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRSBLiteral, "ldrsb<c> <Rt> <label>" }, 11982 { 0x0e5000f0, 0x001000d0, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRSBRegister, "ldrsb<c> <Rt>,[<Rn>,+/-<Rm>]{!}" }, 11983 { 0x0e5000f0, 0x005000f0, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRSHImmediate, "ldrsh<c> <Rt>,[<Rn>{,#+/-<imm8>}]"}, 11984 { 0x0e5f00f0, 0x005f00f0, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRSHLiteral, "ldrsh<c> <Rt>,<label>" }, 11985 { 0x0e5000f0, 0x001000f0, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRSHRegister, "ldrsh<c> <Rt>,[<Rn>,+/-<Rm>]{!}" }, 11986 { 0x0e5000f0, 0x004000d0, ARMV5TE_ABOVE, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRDImmediate, "ldrd<c> <Rt>, <Rt2>, [<Rn>,#+/-<imm8>]!"}, 11987 { 0x0e500ff0, 0x000000d0, ARMV5TE_ABOVE, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRDRegister, "ldrd<c> <Rt>, <Rt2>, [<Rn>, +/-<Rm>]{!}"}, 11988 { 0x0e100f00, 0x0c100b00, ARMvAll, eEncodingA1, VFPv2_ABOVE, eSize32, &EmulateInstructionARM::EmulateVLDM, "vldm{mode}<c> <Rn>{!}, <list>"}, 11989 { 0x0e100f00, 0x0c100a00, ARMvAll, eEncodingA2, VFPv2v3, eSize32, &EmulateInstructionARM::EmulateVLDM, "vldm{mode}<c> <Rn>{!}, <list>"}, 11990 { 0x0f300f00, 0x0d100b00, ARMvAll, eEncodingA1, VFPv2_ABOVE, eSize32, &EmulateInstructionARM::EmulateVLDR, "vldr<c> <Dd>, [<Rn>{,#+/-<imm>}]"}, 11991 { 0x0f300f00, 0x0d100a00, ARMvAll, eEncodingA2, VFPv2v3, eSize32, &EmulateInstructionARM::EmulateVLDR, "vldr<c> <Sd>, [<Rn>{,#+/-<imm>}]"}, 11992 { 0xffb00000, 0xf4200000, ARMvAll, eEncodingA1, AdvancedSIMD, eSize32, &EmulateInstructionARM::EmulateVLD1Multiple, "vld1<c>.<size> <list>, [<Rn>{@<align>}], <Rm>"}, 11993 { 0xffb00300, 0xf4a00000, ARMvAll, eEncodingA1, AdvancedSIMD, eSize32, &EmulateInstructionARM::EmulateVLD1Single, "vld1<c>.<size> <list>, [<Rn>{@<align>}], <Rm>"}, 11994 { 0xffb00f00, 0xf4a00c00, ARMvAll, eEncodingA1, AdvancedSIMD, eSize32, &EmulateInstructionARM::EmulateVLD1SingleAll, "vld1<c>.<size> <list>, [<Rn>{@<align>}], <Rm>"}, 11995 11996 //---------------------------------------------------------------------- 11997 // Store instructions 11998 //---------------------------------------------------------------------- 11999 { 0x0fd00000, 0x08800000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTM, "stm<c> <Rn>{!} <registers>" }, 12000 { 0x0fd00000, 0x08000000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTMDA, "stmda<c> <Rn>{!} <registers>" }, 12001 { 0x0fd00000, 0x09000000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTMDB, "stmdb<c> <Rn>{!} <registers>" }, 12002 { 0x0fd00000, 0x09800000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTMIB, "stmib<c> <Rn>{!} <registers>" }, 12003 { 0x0e500010, 0x06000000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTRRegister, "str<c> <Rt> [<Rn> +/-<Rm> {<shift>}]{!}" }, 12004 { 0x0e5000f0, 0x000000b0, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTRHRegister, "strh<c> <Rt>,[<Rn>,+/-<Rm>[{!}" }, 12005 { 0x0ff00ff0, 0x01800f90, ARMV6_ABOVE, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTREX, "strex<c> <Rd>, <Rt>, [<Rn>]"}, 12006 { 0x0e500000, 0x04400000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTRBImmARM, "strb<c> <Rt>,[<Rn>,#+/-<imm12>]!"}, 12007 { 0x0e500000, 0x04000000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTRImmARM, "str<c> <Rt>,[<Rn>,#+/-<imm12>]!"}, 12008 { 0x0e5000f0, 0x004000f0, ARMV5TE_ABOVE, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTRDImm, "strc<c> <Rt>, <Rt2>, [<Rn> #+/-<imm8>]!"}, 12009 { 0x0e500ff0, 0x000000f0, ARMV5TE_ABOVE, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTRDReg, "strd<c> <Rt>, <Rt2>, [<Rn>, +/-<Rm>]{!}"}, 12010 { 0x0e100f00, 0x0c000b00, ARMvAll, eEncodingA1, VFPv2_ABOVE, eSize32, &EmulateInstructionARM::EmulateVSTM, "vstm{mode}<c> <Rn>{!} <list>"}, 12011 { 0x0e100f00, 0x0c000a00, ARMvAll, eEncodingA2, VFPv2v3, eSize32, &EmulateInstructionARM::EmulateVSTM, "vstm{mode}<c> <Rn>{!} <list>"}, 12012 { 0x0f300f00, 0x0d000b00, ARMvAll, eEncodingA1, VFPv2_ABOVE, eSize32, &EmulateInstructionARM::EmulateVSTR, "vstr<c> <Dd> [<Rn>{,#+/-<imm>}]"}, 12013 { 0x0f300f00, 0x0d000a00, ARMvAll, eEncodingA2, VFPv2v3, eSize32, &EmulateInstructionARM::EmulateVSTR, "vstr<c> <Sd> [<Rn>{,#+/-<imm>}]"}, 12014 { 0xffb00000, 0xf4000000, ARMvAll, eEncodingA1, AdvancedSIMD, eSize32, &EmulateInstructionARM::EmulateVST1Multiple, "vst1<c>.<size> <list>, [<Rn>{@<align>}], <Rm>"}, 12015 { 0xffb00300, 0xf4800000, ARMvAll, eEncodingA1, AdvancedSIMD, eSize32, &EmulateInstructionARM::EmulateVST1Single, "vst1<c>.<size> <list>, [<Rn>{@<align>}], <Rm>"}, 12016 12017 //---------------------------------------------------------------------- 12018 // Other instructions 12019 //---------------------------------------------------------------------- 12020 { 0x0fff00f0, 0x06af00f0, ARMV6_ABOVE, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSXTB, "sxtb<c> <Rd>,<Rm>{,<rotation>}" }, 12021 { 0x0fff00f0, 0x06bf0070, ARMV6_ABOVE, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSXTH, "sxth<c> <Rd>,<Rm>{,<rotation>}" }, 12022 { 0x0fff00f0, 0x06ef0070, ARMV6_ABOVE, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateUXTB, "uxtb<c> <Rd>,<Rm>{,<rotation>}" }, 12023 { 0x0fff00f0, 0x06ff0070, ARMV6_ABOVE, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateUXTH, "uxth<c> <Rd>,<Rm>{,<rotation>}" }, 12024 { 0xfe500000, 0xf8100000, ARMV6_ABOVE, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateRFE, "rfe{<amode>} <Rn>{!}" } 12025 12026 }; 12027 static const size_t k_num_arm_opcodes = sizeof(g_arm_opcodes)/sizeof(ARMOpcode); 12028 12029 for (size_t i=0; i<k_num_arm_opcodes; ++i) 12030 { 12031 if ((g_arm_opcodes[i].mask & opcode) == g_arm_opcodes[i].value) 12032 return &g_arm_opcodes[i]; 12033 } 12034 return NULL; 12035} 12036 12037 12038EmulateInstructionARM::ARMOpcode* 12039EmulateInstructionARM::GetThumbOpcodeForInstruction (const uint32_t opcode) 12040{ 12041 12042 static ARMOpcode 12043 g_thumb_opcodes[] = 12044 { 12045 //---------------------------------------------------------------------- 12046 // Prologue instructions 12047 //---------------------------------------------------------------------- 12048 12049 // push register(s) 12050 { 0xfffffe00, 0x0000b400, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulatePUSH, "push <registers>" }, 12051 { 0xffff0000, 0xe92d0000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulatePUSH, "push.w <registers>" }, 12052 { 0xffff0fff, 0xf84d0d04, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, &EmulateInstructionARM::EmulatePUSH, "push.w <register>" }, 12053 12054 // set r7 to point to a stack offset 12055 { 0xffffff00, 0x0000af00, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateADDRdSPImm, "add r7, sp, #imm" }, 12056 // copy the stack pointer to r7 12057 { 0xffffffff, 0x0000466f, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateMOVRdSP, "mov r7, sp" }, 12058 // move from high register to low register (comes after "mov r7, sp" to resolve ambiguity) 12059 { 0xffffffc0, 0x00004640, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateMOVLowHigh, "mov r0-r7, r8-r15" }, 12060 12061 // PC-relative load into register (see also EmulateADDSPRm) 12062 { 0xfffff800, 0x00004800, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateLDRRtPCRelative, "ldr <Rt>, [PC, #imm]"}, 12063 12064 // adjust the stack pointer 12065 { 0xffffff87, 0x00004485, ARMvAll, eEncodingT2, No_VFP, eSize16, &EmulateInstructionARM::EmulateADDSPRm, "add sp, <Rm>"}, 12066 { 0xffffff80, 0x0000b080, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateSUBSPImm, "sub sp, sp, #imm"}, 12067 { 0xfbef8f00, 0xf1ad0d00, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBSPImm, "sub.w sp, sp, #<const>"}, 12068 { 0xfbff8f00, 0xf2ad0d00, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBSPImm, "subw sp, sp, #imm12"}, 12069 { 0xffef8000, 0xebad0000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBSPReg, "sub{s}<c> <Rd>, sp, <Rm>{,<shift>}" }, 12070 12071 // vector push consecutive extension register(s) 12072 { 0xffbf0f00, 0xed2d0b00, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateVPUSH, "vpush.64 <list>"}, 12073 { 0xffbf0f00, 0xed2d0a00, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateVPUSH, "vpush.32 <list>"}, 12074 12075 //---------------------------------------------------------------------- 12076 // Epilogue instructions 12077 //---------------------------------------------------------------------- 12078 12079 { 0xfffff800, 0x0000a800, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateADDSPImm, "add<c> <Rd>, sp, #imm"}, 12080 { 0xffffff80, 0x0000b000, ARMvAll, eEncodingT2, No_VFP, eSize16, &EmulateInstructionARM::EmulateADDSPImm, "add sp, #imm"}, 12081 { 0xfffffe00, 0x0000bc00, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulatePOP, "pop <registers>"}, 12082 { 0xffff0000, 0xe8bd0000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulatePOP, "pop.w <registers>" }, 12083 { 0xffff0fff, 0xf85d0d04, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, &EmulateInstructionARM::EmulatePOP, "pop.w <register>" }, 12084 { 0xffbf0f00, 0xecbd0b00, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateVPOP, "vpop.64 <list>"}, 12085 { 0xffbf0f00, 0xecbd0a00, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateVPOP, "vpop.32 <list>"}, 12086 12087 //---------------------------------------------------------------------- 12088 // Supervisor Call (previously Software Interrupt) 12089 //---------------------------------------------------------------------- 12090 { 0xffffff00, 0x0000df00, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateSVC, "svc #imm8"}, 12091 12092 //---------------------------------------------------------------------- 12093 // If Then makes up to four following instructions conditional. 12094 //---------------------------------------------------------------------- 12095 { 0xffffff00, 0x0000bf00, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateIT, "it{<x>{<y>{<z>}}} <firstcond>"}, 12096 12097 //---------------------------------------------------------------------- 12098 // Branch instructions 12099 //---------------------------------------------------------------------- 12100 // To resolve ambiguity, "b<c> #imm8" should come after "svc #imm8". 12101 { 0xfffff000, 0x0000d000, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateB, "b<c> #imm8 (outside IT)"}, 12102 { 0xfffff800, 0x0000e000, ARMvAll, eEncodingT2, No_VFP, eSize16, &EmulateInstructionARM::EmulateB, "b<c> #imm11 (outside or last in IT)"}, 12103 { 0xf800d000, 0xf0008000, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, &EmulateInstructionARM::EmulateB, "b<c>.w #imm8 (outside IT)"}, 12104 { 0xf800d000, 0xf0009000, ARMV6T2_ABOVE, eEncodingT4, No_VFP, eSize32, &EmulateInstructionARM::EmulateB, "b<c>.w #imm8 (outside or last in IT)"}, 12105 // J1 == J2 == 1 12106 { 0xf800d000, 0xf000d000, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateBLXImmediate, "bl <label>"}, 12107 // J1 == J2 == 1 12108 { 0xf800d001, 0xf000c000, ARMV5_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateBLXImmediate, "blx <label>"}, 12109 { 0xffffff87, 0x00004780, ARMV5_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateBLXRm, "blx <Rm>"}, 12110 // for example, "bx lr" 12111 { 0xffffff87, 0x00004700, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateBXRm, "bx <Rm>"}, 12112 // bxj 12113 { 0xfff0ffff, 0xf3c08f00, ARMV5J_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateBXJRm, "bxj <Rm>"}, 12114 // compare and branch 12115 { 0xfffff500, 0x0000b100, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateCB, "cb{n}z <Rn>, <label>"}, 12116 // table branch byte 12117 { 0xfff0fff0, 0xe8d0f000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateTB, "tbb<c> <Rn>, <Rm>"}, 12118 // table branch halfword 12119 { 0xfff0fff0, 0xe8d0f010, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateTB, "tbh<c> <Rn>, <Rm>, lsl #1"}, 12120 12121 //---------------------------------------------------------------------- 12122 // Data-processing instructions 12123 //---------------------------------------------------------------------- 12124 // adc (immediate) 12125 { 0xfbe08000, 0xf1400000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateADCImm, "adc{s}<c> <Rd>, <Rn>, #<const>"}, 12126 // adc (register) 12127 { 0xffffffc0, 0x00004140, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateADCReg, "adcs|adc<c> <Rdn>, <Rm>"}, 12128 { 0xffe08000, 0xeb400000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateADCReg, "adc{s}<c>.w <Rd>, <Rn>, <Rm> {,<shift>}"}, 12129 // add (register) 12130 { 0xfffffe00, 0x00001800, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateADDReg, "adds|add<c> <Rd>, <Rn>, <Rm>"}, 12131 // Make sure "add sp, <Rm>" comes before this instruction, so there's no ambiguity decoding the two. 12132 { 0xffffff00, 0x00004400, ARMvAll, eEncodingT2, No_VFP, eSize16, &EmulateInstructionARM::EmulateADDReg, "add<c> <Rdn>, <Rm>"}, 12133 // adr 12134 { 0xfffff800, 0x0000a000, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateADR, "add<c> <Rd>, PC, #<const>"}, 12135 { 0xfbff8000, 0xf2af0000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateADR, "sub<c> <Rd>, PC, #<const>"}, 12136 { 0xfbff8000, 0xf20f0000, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, &EmulateInstructionARM::EmulateADR, "add<c> <Rd>, PC, #<const>"}, 12137 // and (immediate) 12138 { 0xfbe08000, 0xf0000000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateANDImm, "and{s}<c> <Rd>, <Rn>, #<const>"}, 12139 // and (register) 12140 { 0xffffffc0, 0x00004000, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateANDReg, "ands|and<c> <Rdn>, <Rm>"}, 12141 { 0xffe08000, 0xea000000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateANDReg, "and{s}<c>.w <Rd>, <Rn>, <Rm> {,<shift>}"}, 12142 // bic (immediate) 12143 { 0xfbe08000, 0xf0200000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateBICImm, "bic{s}<c> <Rd>, <Rn>, #<const>"}, 12144 // bic (register) 12145 { 0xffffffc0, 0x00004380, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateBICReg, "bics|bic<c> <Rdn>, <Rm>"}, 12146 { 0xffe08000, 0xea200000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateBICReg, "bic{s}<c>.w <Rd>, <Rn>, <Rm> {,<shift>}"}, 12147 // eor (immediate) 12148 { 0xfbe08000, 0xf0800000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateEORImm, "eor{s}<c> <Rd>, <Rn>, #<const>"}, 12149 // eor (register) 12150 { 0xffffffc0, 0x00004040, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateEORReg, "eors|eor<c> <Rdn>, <Rm>"}, 12151 { 0xffe08000, 0xea800000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateEORReg, "eor{s}<c>.w <Rd>, <Rn>, <Rm> {,<shift>}"}, 12152 // orr (immediate) 12153 { 0xfbe08000, 0xf0400000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateORRImm, "orr{s}<c> <Rd>, <Rn>, #<const>"}, 12154 // orr (register) 12155 { 0xffffffc0, 0x00004300, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateORRReg, "orrs|orr<c> <Rdn>, <Rm>"}, 12156 { 0xffe08000, 0xea400000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateORRReg, "orr{s}<c>.w <Rd>, <Rn>, <Rm> {,<shift>}"}, 12157 // rsb (immediate) 12158 { 0xffffffc0, 0x00004240, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateRSBImm, "rsbs|rsb<c> <Rd>, <Rn>, #0"}, 12159 { 0xfbe08000, 0xf1c00000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateRSBImm, "rsb{s}<c>.w <Rd>, <Rn>, #<const>"}, 12160 // rsb (register) 12161 { 0xffe08000, 0xea400000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateRSBReg, "rsb{s}<c>.w <Rd>, <Rn>, <Rm> {,<shift>}"}, 12162 // sbc (immediate) 12163 { 0xfbe08000, 0xf1600000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSBCImm, "sbc{s}<c> <Rd>, <Rn>, #<const>"}, 12164 // sbc (register) 12165 { 0xffffffc0, 0x00004180, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateSBCReg, "sbcs|sbc<c> <Rdn>, <Rm>"}, 12166 { 0xffe08000, 0xeb600000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateSBCReg, "sbc{s}<c>.w <Rd>, <Rn>, <Rm> {,<shift>}"}, 12167 // add (immediate, Thumb) 12168 { 0xfffffe00, 0x00001c00, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateADDImmThumb, "adds|add<c> <Rd>,<Rn>,#<imm3>" }, 12169 { 0xfffff800, 0x00003000, ARMV4T_ABOVE, eEncodingT2, No_VFP, eSize16, &EmulateInstructionARM::EmulateADDImmThumb, "adds|add<c> <Rdn>,#<imm8>" }, 12170 { 0xfbe08000, 0xf1000000, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, &EmulateInstructionARM::EmulateADDImmThumb, "add{s}<c>.w <Rd>,<Rn>,#<const>" }, 12171 { 0xfbf08000, 0xf2000000, ARMV6T2_ABOVE, eEncodingT4, No_VFP, eSize32, &EmulateInstructionARM::EmulateADDImmThumb, "addw<c> <Rd>,<Rn>,#<imm12>" }, 12172 // sub (immediate, Thumb) 12173 { 0xfffffe00, 0x00001e00, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateSUBImmThumb, "subs|sub<c> <Rd>, <Rn> #imm3"}, 12174 { 0xfffff800, 0x00003800, ARMvAll, eEncodingT2, No_VFP, eSize16, &EmulateInstructionARM::EmulateSUBImmThumb, "subs|sub<c> <Rdn>, #imm8"}, 12175 { 0xfbe08000, 0xf1a00000, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBImmThumb, "sub{s}<c>.w <Rd>, <Rn>, #<const>"}, 12176 { 0xfbf08000, 0xf2a00000, ARMV6T2_ABOVE, eEncodingT4, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBImmThumb, "subw<c> <Rd>, <Rn>, #imm12"}, 12177 // sub (sp minus immediate) 12178 { 0xfbef8000, 0xf1ad0000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBSPImm, "sub{s}.w <Rd>, sp, #<const>"}, 12179 { 0xfbff8000, 0xf2ad0000, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBSPImm, "subw<c> <Rd>, sp, #imm12"}, 12180 // sub (register) 12181 { 0xfffffe00, 0x00001a00, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateSUBReg, "subs|sub<c> <Rd>, <Rn>, <Rm>"}, 12182 { 0xffe08000, 0xeba00000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBReg, "sub{s}<c>.w <Rd>, <Rn>, <Rm>{,<shift>}"}, 12183 // teq (immediate) 12184 { 0xfbf08f00, 0xf0900f00, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateTEQImm, "teq<c> <Rn>, #<const>"}, 12185 // teq (register) 12186 { 0xfff08f00, 0xea900f00, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateTEQReg, "teq<c> <Rn>, <Rm> {,<shift>}"}, 12187 // tst (immediate) 12188 { 0xfbf08f00, 0xf0100f00, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateTSTImm, "tst<c> <Rn>, #<const>"}, 12189 // tst (register) 12190 { 0xffffffc0, 0x00004200, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateTSTReg, "tst<c> <Rdn>, <Rm>"}, 12191 { 0xfff08f00, 0xea100f00, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateTSTReg, "tst<c>.w <Rn>, <Rm> {,<shift>}"}, 12192 12193 12194 // move from high register to high register 12195 { 0xffffff00, 0x00004600, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateMOVRdRm, "mov<c> <Rd>, <Rm>"}, 12196 // move from low register to low register 12197 { 0xffffffc0, 0x00000000, ARMvAll, eEncodingT2, No_VFP, eSize16, &EmulateInstructionARM::EmulateMOVRdRm, "movs <Rd>, <Rm>"}, 12198 // mov{s}<c>.w <Rd>, <Rm> 12199 { 0xffeff0f0, 0xea4f0000, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, &EmulateInstructionARM::EmulateMOVRdRm, "mov{s}<c>.w <Rd>, <Rm>"}, 12200 // move immediate 12201 { 0xfffff800, 0x00002000, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateMOVRdImm, "movs|mov<c> <Rd>, #imm8"}, 12202 { 0xfbef8000, 0xf04f0000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateMOVRdImm, "mov{s}<c>.w <Rd>, #<const>"}, 12203 { 0xfbf08000, 0xf2400000, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, &EmulateInstructionARM::EmulateMOVRdImm, "movw<c> <Rd>,#<imm16>"}, 12204 // mvn (immediate) 12205 { 0xfbef8000, 0xf06f0000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateMVNImm, "mvn{s} <Rd>, #<const>"}, 12206 // mvn (register) 12207 { 0xffffffc0, 0x000043c0, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateMVNReg, "mvns|mvn<c> <Rd>, <Rm>"}, 12208 { 0xffef8000, 0xea6f0000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateMVNReg, "mvn{s}<c>.w <Rd>, <Rm> {,<shift>}"}, 12209 // cmn (immediate) 12210 { 0xfbf08f00, 0xf1100f00, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateCMNImm, "cmn<c> <Rn>, #<const>"}, 12211 // cmn (register) 12212 { 0xffffffc0, 0x000042c0, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateCMNReg, "cmn<c> <Rn>, <Rm>"}, 12213 { 0xfff08f00, 0xeb100f00, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateCMNReg, "cmn<c> <Rn>, <Rm> {,<shift>}"}, 12214 // cmp (immediate) 12215 { 0xfffff800, 0x00002800, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateCMPImm, "cmp<c> <Rn>, #imm8"}, 12216 { 0xfbf08f00, 0xf1b00f00, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateCMPImm, "cmp<c>.w <Rn>, #<const>"}, 12217 // cmp (register) (Rn and Rm both from r0-r7) 12218 { 0xffffffc0, 0x00004280, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateCMPReg, "cmp<c> <Rn>, <Rm>"}, 12219 // cmp (register) (Rn and Rm not both from r0-r7) 12220 { 0xffffff00, 0x00004500, ARMvAll, eEncodingT2, No_VFP, eSize16, &EmulateInstructionARM::EmulateCMPReg, "cmp<c> <Rn>, <Rm>"}, 12221 // asr (immediate) 12222 { 0xfffff800, 0x00001000, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateASRImm, "asrs|asr<c> <Rd>, <Rm>, #imm"}, 12223 { 0xffef8030, 0xea4f0020, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateASRImm, "asr{s}<c>.w <Rd>, <Rm>, #imm"}, 12224 // asr (register) 12225 { 0xffffffc0, 0x00004100, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateASRReg, "asrs|asr<c> <Rdn>, <Rm>"}, 12226 { 0xffe0f0f0, 0xfa40f000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateASRReg, "asr{s}<c>.w <Rd>, <Rn>, <Rm>"}, 12227 // lsl (immediate) 12228 { 0xfffff800, 0x00000000, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateLSLImm, "lsls|lsl<c> <Rd>, <Rm>, #imm"}, 12229 { 0xffef8030, 0xea4f0000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateLSLImm, "lsl{s}<c>.w <Rd>, <Rm>, #imm"}, 12230 // lsl (register) 12231 { 0xffffffc0, 0x00004080, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateLSLReg, "lsls|lsl<c> <Rdn>, <Rm>"}, 12232 { 0xffe0f0f0, 0xfa00f000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateLSLReg, "lsl{s}<c>.w <Rd>, <Rn>, <Rm>"}, 12233 // lsr (immediate) 12234 { 0xfffff800, 0x00000800, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateLSRImm, "lsrs|lsr<c> <Rd>, <Rm>, #imm"}, 12235 { 0xffef8030, 0xea4f0010, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateLSRImm, "lsr{s}<c>.w <Rd>, <Rm>, #imm"}, 12236 // lsr (register) 12237 { 0xffffffc0, 0x000040c0, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateLSRReg, "lsrs|lsr<c> <Rdn>, <Rm>"}, 12238 { 0xffe0f0f0, 0xfa20f000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateLSRReg, "lsr{s}<c>.w <Rd>, <Rn>, <Rm>"}, 12239 // rrx is a special case encoding of ror (immediate) 12240 { 0xffeff0f0, 0xea4f0030, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateRRX, "rrx{s}<c>.w <Rd>, <Rm>"}, 12241 // ror (immediate) 12242 { 0xffef8030, 0xea4f0030, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateRORImm, "ror{s}<c>.w <Rd>, <Rm>, #imm"}, 12243 // ror (register) 12244 { 0xffffffc0, 0x000041c0, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateRORReg, "rors|ror<c> <Rdn>, <Rm>"}, 12245 { 0xffe0f0f0, 0xfa60f000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateRORReg, "ror{s}<c>.w <Rd>, <Rn>, <Rm>"}, 12246 // mul 12247 { 0xffffffc0, 0x00004340, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateMUL, "muls <Rdm>,<Rn>,<Rdm>" }, 12248 // mul 12249 { 0xfff0f0f0, 0xfb00f000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateMUL, "mul<c> <Rd>,<Rn>,<Rm>" }, 12250 12251 //---------------------------------------------------------------------- 12252 // Load instructions 12253 //---------------------------------------------------------------------- 12254 { 0xfffff800, 0x0000c800, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateLDM, "ldm<c> <Rn>{!} <registers>" }, 12255 { 0xffd02000, 0xe8900000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDM, "ldm<c>.w <Rn>{!} <registers>" }, 12256 { 0xffd00000, 0xe9100000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDMDB, "ldmdb<c> <Rn>{!} <registers>" }, 12257 { 0xfffff800, 0x00006800, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateLDRRtRnImm, "ldr<c> <Rt>, [<Rn>{,#imm}]"}, 12258 { 0xfffff800, 0x00009800, ARMV4T_ABOVE, eEncodingT2, No_VFP, eSize16, &EmulateInstructionARM::EmulateLDRRtRnImm, "ldr<c> <Rt>, [SP{,#imm}]"}, 12259 { 0xfff00000, 0xf8d00000, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRRtRnImm, "ldr<c>.w <Rt>, [<Rn>{,#imm12}]"}, 12260 { 0xfff00800, 0xf8500800, ARMV6T2_ABOVE, eEncodingT4, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRRtRnImm, "ldr<c> <Rt>, [<Rn>{,#+/-<imm8>}]{!}"}, 12261 // Thumb2 PC-relative load into register 12262 { 0xff7f0000, 0xf85f0000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRRtPCRelative, "ldr<c>.w <Rt>, [PC, +/-#imm}]"}, 12263 { 0xfffffe00, 0x00005800, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateLDRRegister, "ldr<c> <Rt>, [<Rn>, <Rm>]" }, 12264 { 0xfff00fc0, 0xf8500000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRRegister, "ldr<c>.w <Rt>, [<Rn>,<Rm>{,LSL #<imm2>}]" }, 12265 { 0xfffff800, 0x00007800, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateLDRBImmediate, "ldrb<c> <Rt>,[<Rn>{,#<imm5>}]" }, 12266 { 0xfff00000, 0xf8900000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRBImmediate, "ldrb<c>.w <Rt>,[<Rn>{,#<imm12>}]" }, 12267 { 0xfff00800, 0xf8100800, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRBImmediate, "ldrb<c> <Rt>,[>Rn>, #+/-<imm8>]{!}" }, 12268 { 0xff7f0000, 0xf81f0000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRBLiteral, "ldrb<c> <Rt>,[...]" }, 12269 { 0xfffffe00, 0x00005c00, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateLDRBRegister, "ldrb<c> <Rt>,[<Rn>,<Rm>]" }, 12270 { 0xfff00fc0, 0xf8100000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRBRegister, "ldrb<c>.w <Rt>,[<Rn>,<Rm>{,LSL #imm2>}]" }, 12271 { 0xfffff800, 0x00008800, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateLDRHImmediate, "ldrh<c> <Rt>, [<Rn>{,#<imm>}]" }, 12272 { 0xfff00000, 0xf8b00000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRHImmediate, "ldrh<c>.w <Rt>,[<Rn>{,#<imm12>}]" }, 12273 { 0xfff00800, 0xf8300800, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRHImmediate, "ldrh<c> <Rt>,[<Rn>,#+/-<imm8>]{!}" }, 12274 { 0xff7f0000, 0xf83f0000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRHLiteral, "ldrh<c> <Rt>, <label>" }, 12275 { 0xfffffe00, 0x00005a00, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateLDRHRegister, "ldrh<c> <Rt>, [<Rn>,<Rm>]" }, 12276 { 0xfff00fc0, 0xf8300000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRHRegister, "ldrh<c>.w <Rt>,[<Rn>,<Rm>{,LSL #<imm2>}]" }, 12277 { 0xfff00000, 0xf9900000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRSBImmediate, "ldrsb<c> <Rt>,[<Rn>,#<imm12>]" }, 12278 { 0xfff00800, 0xf9100800, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRSBImmediate, "ldrsb<c> <Rt>,[<Rn>,#+/-<imm8>]" }, 12279 { 0xff7f0000, 0xf91f0000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRSBLiteral, "ldrsb<c> <Rt>, <label>" }, 12280 { 0xfffffe00, 0x00005600, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateLDRSBRegister, "ldrsb<c> <Rt>,[<Rn>,<Rm>]" }, 12281 { 0xfff00fc0, 0xf9100000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRSBRegister, "ldrsb<c>.w <Rt>,[<Rn>,<Rm>{,LSL #imm2>}]" }, 12282 { 0xfff00000, 0xf9b00000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRSHImmediate, "ldrsh<c> <Rt>,[<Rn>,#<imm12>]" }, 12283 { 0xfff00800, 0xf9300800, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRSHImmediate, "ldrsh<c> <Rt>,[<Rn>,#+/-<imm8>]" }, 12284 { 0xff7f0000, 0xf93f0000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRSHLiteral, "ldrsh<c> <Rt>,<label>" }, 12285 { 0xfffffe00, 0x00005e00, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateLDRSHRegister, "ldrsh<c> <Rt>,[<Rn>,<Rm>]" }, 12286 { 0xfff00fc0, 0xf9300000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRSHRegister, "ldrsh<c>.w <Rt>,[<Rn>,<Rm>{,LSL #<imm2>}]" }, 12287 { 0xfe500000, 0xe8500000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRDImmediate, "ldrd<c> <Rt?, <Rt2>, [<Rn>,#+/-<imm>]!"}, 12288 { 0xfe100f00, 0xec100b00, ARMvAll, eEncodingT1, VFPv2_ABOVE, eSize32, &EmulateInstructionARM::EmulateVLDM, "vldm{mode}<c> <Rn>{!}, <list>"}, 12289 { 0xfe100f00, 0xec100a00, ARMvAll, eEncodingT2, VFPv2v3, eSize32, &EmulateInstructionARM::EmulateVLDM, "vldm{mode}<c> <Rn>{!}, <list>" }, 12290 { 0xffe00f00, 0xed100b00, ARMvAll, eEncodingT1, VFPv2_ABOVE, eSize32, &EmulateInstructionARM::EmulateVLDR, "vldr<c> <Dd>, [<Rn>{,#+/-<imm>}]"}, 12291 { 0xff300f00, 0xed100a00, ARMvAll, eEncodingT2, VFPv2v3, eSize32, &EmulateInstructionARM::EmulateVLDR, "vldr<c> <Sd>, {<Rn>{,#+/-<imm>}]"}, 12292 { 0xffb00000, 0xf9200000, ARMvAll, eEncodingT1, AdvancedSIMD, eSize32, &EmulateInstructionARM::EmulateVLD1Multiple, "vld1<c>.<size> <list>, [<Rn>{@<align>}],<Rm>"}, 12293 { 0xffb00300, 0xf9a00000, ARMvAll, eEncodingT1, AdvancedSIMD, eSize32, &EmulateInstructionARM::EmulateVLD1Single, "vld1<c>.<size> <list>, [<Rn>{@<align>}],<Rm>"}, 12294 { 0xffb00f00, 0xf9a00c00, ARMvAll, eEncodingT1, AdvancedSIMD, eSize32, &EmulateInstructionARM::EmulateVLD1SingleAll, "vld1<c>.<size> <list>, [<Rn>{@<align>}], <Rm>"}, 12295 12296 //---------------------------------------------------------------------- 12297 // Store instructions 12298 //---------------------------------------------------------------------- 12299 { 0xfffff800, 0x0000c000, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateSTM, "stm<c> <Rn>{!} <registers>" }, 12300 { 0xffd00000, 0xe8800000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTM, "stm<c>.w <Rn>{!} <registers>" }, 12301 { 0xffd00000, 0xe9000000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTMDB, "stmdb<c> <Rn>{!} <registers>" }, 12302 { 0xfffff800, 0x00006000, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateSTRThumb, "str<c> <Rt>, [<Rn>{,#<imm>}]" }, 12303 { 0xfffff800, 0x00009000, ARMV4T_ABOVE, eEncodingT2, No_VFP, eSize16, &EmulateInstructionARM::EmulateSTRThumb, "str<c> <Rt>, [SP,#<imm>]" }, 12304 { 0xfff00000, 0xf8c00000, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTRThumb, "str<c>.w <Rt>, [<Rn>,#<imm12>]" }, 12305 { 0xfff00800, 0xf8400800, ARMV6T2_ABOVE, eEncodingT4, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTRThumb, "str<c> <Rt>, [<Rn>,#+/-<imm8>]" }, 12306 { 0xfffffe00, 0x00005000, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateSTRRegister, "str<c> <Rt> ,{<Rn>, <Rm>]" }, 12307 { 0xfff00fc0, 0xf8400000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTRRegister, "str<c>.w <Rt>, [<Rn>, <Rm> {lsl #imm2>}]" }, 12308 { 0xfffff800, 0x00007000, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateSTRBThumb, "strb<c> <Rt>, [<Rn>, #<imm5>]" }, 12309 { 0xfff00000, 0xf8800000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTRBThumb, "strb<c>.w <Rt>, [<Rn>, #<imm12>]" }, 12310 { 0xfff00800, 0xf8000800, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTRBThumb, "strb<c> <Rt> ,[<Rn>, #+/-<imm8>]{!}" }, 12311 { 0xfffffe00, 0x00005200, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateSTRHRegister, "strh<c> <Rt>,[<Rn>,<Rm>]" }, 12312 { 0xfff00fc0, 0xf8200000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTRHRegister, "strh<c>.w <Rt>,[<Rn>,<Rm>{,LSL #<imm2>}]" }, 12313 { 0xfff00000, 0xe8400000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTREX, "strex<c> <Rd>, <Rt>, [<Rn{,#<imm>}]" }, 12314 { 0xfe500000, 0xe8400000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTRDImm, "strd<c> <Rt>, <Rt2>, [<Rn>, #+/-<imm>]!"}, 12315 { 0xfe100f00, 0xec000b00, ARMvAll, eEncodingT1, VFPv2_ABOVE, eSize32, &EmulateInstructionARM::EmulateVSTM, "vstm{mode}<c> <Rn>{!}, <list>"}, 12316 { 0xfea00f00, 0xec000a00, ARMvAll, eEncodingT2, VFPv2v3, eSize32, &EmulateInstructionARM::EmulateVSTM, "vstm{mode}<c> <Rn>{!}, <list>"}, 12317 { 0xff300f00, 0xed000b00, ARMvAll, eEncodingT1, VFPv2_ABOVE, eSize32, &EmulateInstructionARM::EmulateVSTR, "vstr<c> <Dd>, [<Rn>{,#+/-<imm>}]"}, 12318 { 0xff300f00, 0xed000a00, ARMvAll, eEncodingT2, VFPv2v3, eSize32, &EmulateInstructionARM::EmulateVSTR, "vstr<c> <Sd>, [<Rn>{,#+/-<imm>}]"}, 12319 { 0xffb00000, 0xfa000000, ARMvAll, eEncodingT1, AdvancedSIMD, eSize32, &EmulateInstructionARM::EmulateVST1Multiple, "vst1<c>.<size> <list>, [<Rn>{@<align>}], <Rm>"}, 12320 { 0xffb00300, 0xf9800000, ARMvAll, eEncodingT1, AdvancedSIMD, eSize32, &EmulateInstructionARM::EmulateVST1Single, "vst1<c>.<size> <list>, [<Rn>{@<align>}], <Rm>"}, 12321 12322 //---------------------------------------------------------------------- 12323 // Other instructions 12324 //---------------------------------------------------------------------- 12325 { 0xffffffc0, 0x0000b240, ARMV6_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateSXTB, "sxtb<c> <Rd>,<Rm>" }, 12326 { 0xfffff080, 0xfa4ff080, ARMV6_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateSXTB, "sxtb<c>.w <Rd>,<Rm>{,<rotation>}" }, 12327 { 0xffffffc0, 0x0000b200, ARMV6_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateSXTH, "sxth<c> <Rd>,<Rm>" }, 12328 { 0xfffff080, 0xfa0ff080, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateSXTH, "sxth<c>.w <Rd>,<Rm>{,<rotation>}" }, 12329 { 0xffffffc0, 0x0000b2c0, ARMV6_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateUXTB, "uxtb<c> <Rd>,<Rm>" }, 12330 { 0xfffff080, 0xfa5ff080, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateUXTB, "uxtb<c>.w <Rd>,<Rm>{,<rotation>}" }, 12331 { 0xffffffc0, 0x0000b280, ARMV6_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateUXTH, "uxth<c> <Rd>,<Rm>" }, 12332 { 0xfffff080, 0xfa1ff080, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateUXTH, "uxth<c>.w <Rd>,<Rm>{,<rotation>}" }, 12333 { 0xffd00000, 0xe8100000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateRFE, "rfedb<c> <Rn>{!}" }, 12334 { 0xffd00000, 0xe9900000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateRFE, "rfe{ia}<c> <Rn>{!}" } 12335 12336 }; 12337 12338 const size_t k_num_thumb_opcodes = sizeof(g_thumb_opcodes)/sizeof(ARMOpcode); 12339 for (size_t i=0; i<k_num_thumb_opcodes; ++i) 12340 { 12341 if ((g_thumb_opcodes[i].mask & opcode) == g_thumb_opcodes[i].value) 12342 return &g_thumb_opcodes[i]; 12343 } 12344 return NULL; 12345} 12346 12347bool 12348EmulateInstructionARM::SetArchitecture (const ArchSpec &arch) 12349{ 12350 m_arm_isa = 0; 12351 const char *arch_cstr = arch.GetArchitectureName (); 12352 if (arch_cstr) 12353 { 12354 if (0 == ::strcasecmp(arch_cstr, "armv4t")) m_arm_isa = ARMv4T; 12355 else if (0 == ::strcasecmp(arch_cstr, "armv4")) m_arm_isa = ARMv4; 12356 else if (0 == ::strcasecmp(arch_cstr, "armv5tej")) m_arm_isa = ARMv5TEJ; 12357 else if (0 == ::strcasecmp(arch_cstr, "armv5te")) m_arm_isa = ARMv5TE; 12358 else if (0 == ::strcasecmp(arch_cstr, "armv5t")) m_arm_isa = ARMv5T; 12359 else if (0 == ::strcasecmp(arch_cstr, "armv6k")) m_arm_isa = ARMv6K; 12360 else if (0 == ::strcasecmp(arch_cstr, "armv6")) m_arm_isa = ARMv6; 12361 else if (0 == ::strcasecmp(arch_cstr, "armv6t2")) m_arm_isa = ARMv6T2; 12362 else if (0 == ::strcasecmp(arch_cstr, "armv7")) m_arm_isa = ARMv7; 12363 else if (0 == ::strcasecmp(arch_cstr, "armv8")) m_arm_isa = ARMv8; 12364 } 12365 return m_arm_isa != 0; 12366} 12367 12368 12369bool 12370EmulateInstructionARM::ReadInstruction () 12371{ 12372 bool success = false; 12373 m_opcode_cpsr = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS, 0, &success); 12374 if (success) 12375 { 12376 addr_t pc = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, LLDB_INVALID_ADDRESS, &success); 12377 if (success) 12378 { 12379 Context read_inst_context; 12380 read_inst_context.type = eContextReadOpcode; 12381 read_inst_context.SetNoArgs (); 12382 12383 if (m_opcode_cpsr & MASK_CPSR_T) 12384 { 12385 m_opcode_mode = eModeThumb; 12386 uint32_t thumb_opcode = MemARead(read_inst_context, pc, 2, 0, &success); 12387 12388 if (success) 12389 { 12390 if ((thumb_opcode & 0xe000) != 0xe000 || ((thumb_opcode & 0x1800u) == 0)) 12391 { 12392 m_opcode.SetOpcode16 (thumb_opcode); 12393 } 12394 else 12395 { 12396 m_opcode.SetOpcode32 ((thumb_opcode << 16) | MemARead(read_inst_context, pc + 2, 2, 0, &success)); 12397 } 12398 } 12399 } 12400 else 12401 { 12402 m_opcode_mode = eModeARM; 12403 m_opcode.SetOpcode32 (MemARead(read_inst_context, pc, 4, 0, &success)); 12404 } 12405 } 12406 } 12407 if (!success) 12408 { 12409 m_opcode_mode = eModeInvalid; 12410 m_opcode_pc = LLDB_INVALID_ADDRESS; 12411 } 12412 return success; 12413} 12414 12415uint32_t 12416EmulateInstructionARM::ArchVersion () 12417{ 12418 return m_arm_isa; 12419} 12420 12421bool 12422EmulateInstructionARM::ConditionPassed (const uint32_t opcode) 12423{ 12424 if (m_opcode_cpsr == 0) 12425 return false; 12426 12427 const uint32_t cond = CurrentCond (opcode); 12428 12429 if (cond == UINT32_MAX) 12430 return false; 12431 12432 bool result = false; 12433 switch (UnsignedBits(cond, 3, 1)) 12434 { 12435 case 0: result = (m_opcode_cpsr & MASK_CPSR_Z) != 0; break; 12436 case 1: result = (m_opcode_cpsr & MASK_CPSR_C) != 0; break; 12437 case 2: result = (m_opcode_cpsr & MASK_CPSR_N) != 0; break; 12438 case 3: result = (m_opcode_cpsr & MASK_CPSR_V) != 0; break; 12439 case 4: result = ((m_opcode_cpsr & MASK_CPSR_C) != 0) && ((m_opcode_cpsr & MASK_CPSR_Z) == 0); break; 12440 case 5: 12441 { 12442 bool n = (m_opcode_cpsr & MASK_CPSR_N); 12443 bool v = (m_opcode_cpsr & MASK_CPSR_V); 12444 result = n == v; 12445 } 12446 break; 12447 case 6: 12448 { 12449 bool n = (m_opcode_cpsr & MASK_CPSR_N); 12450 bool v = (m_opcode_cpsr & MASK_CPSR_V); 12451 result = n == v && ((m_opcode_cpsr & MASK_CPSR_Z) == 0); 12452 } 12453 break; 12454 case 7: 12455 result = true; 12456 break; 12457 } 12458 12459 if (cond & 1) 12460 result = !result; 12461 return result; 12462} 12463 12464uint32_t 12465EmulateInstructionARM::CurrentCond (const uint32_t opcode) 12466{ 12467 switch (m_opcode_mode) 12468 { 12469 default: 12470 case eModeInvalid: 12471 break; 12472 12473 case eModeARM: 12474 return UnsignedBits(opcode, 31, 28); 12475 12476 case eModeThumb: 12477 // For T1 and T3 encodings of the Branch instruction, it returns the 4-bit 12478 // 'cond' field of the encoding. 12479 { 12480 const uint32_t byte_size = m_opcode.GetByteSize(); 12481 if (byte_size == 2) 12482 { 12483 if (Bits32(opcode, 15, 12) == 0x0d && Bits32(opcode, 11, 7) != 0x0f) 12484 return Bits32(opcode, 11, 7); 12485 } 12486 else 12487 { 12488 assert (byte_size == 4); 12489 if (Bits32(opcode, 31, 27) == 0x1e && 12490 Bits32(opcode, 15, 14) == 0x02 && 12491 Bits32(opcode, 12, 12) == 0x00 && 12492 Bits32(opcode, 25, 22) <= 0x0d) 12493 { 12494 return Bits32(opcode, 25, 22); 12495 } 12496 } 12497 12498 return m_it_session.GetCond(); 12499 } 12500 } 12501 return UINT32_MAX; // Return invalid value 12502} 12503 12504bool 12505EmulateInstructionARM::InITBlock() 12506{ 12507 return CurrentInstrSet() == eModeThumb && m_it_session.InITBlock(); 12508} 12509 12510bool 12511EmulateInstructionARM::LastInITBlock() 12512{ 12513 return CurrentInstrSet() == eModeThumb && m_it_session.LastInITBlock(); 12514} 12515 12516bool 12517EmulateInstructionARM::BadMode (uint32_t mode) 12518{ 12519 12520 switch (mode) 12521 { 12522 case 16: return false; // '10000' 12523 case 17: return false; // '10001' 12524 case 18: return false; // '10010' 12525 case 19: return false; // '10011' 12526 case 22: return false; // '10110' 12527 case 23: return false; // '10111' 12528 case 27: return false; // '11011' 12529 case 31: return false; // '11111' 12530 default: return true; 12531 } 12532 return true; 12533} 12534 12535bool 12536EmulateInstructionARM::CurrentModeIsPrivileged () 12537{ 12538 uint32_t mode = Bits32 (m_opcode_cpsr, 4, 0); 12539 12540 if (BadMode (mode)) 12541 return false; 12542 12543 if (mode == 16) 12544 return false; 12545 12546 return true; 12547} 12548 12549void 12550EmulateInstructionARM::CPSRWriteByInstr (uint32_t value, uint32_t bytemask, bool affect_execstate) 12551{ 12552 bool privileged = CurrentModeIsPrivileged(); 12553 12554 uint32_t tmp_cpsr = 0; 12555 12556 tmp_cpsr = tmp_cpsr | (Bits32 (m_opcode_cpsr, 23, 20) << 20); 12557 12558 if (BitIsSet (bytemask, 3)) 12559 { 12560 tmp_cpsr = tmp_cpsr | (Bits32 (value, 31, 27) << 27); 12561 if (affect_execstate) 12562 tmp_cpsr = tmp_cpsr | (Bits32 (value, 26, 24) << 24); 12563 } 12564 12565 if (BitIsSet (bytemask, 2)) 12566 { 12567 tmp_cpsr = tmp_cpsr | (Bits32 (value, 19, 16) << 16); 12568 } 12569 12570 if (BitIsSet (bytemask, 1)) 12571 { 12572 if (affect_execstate) 12573 tmp_cpsr = tmp_cpsr | (Bits32 (value, 15, 10) << 10); 12574 tmp_cpsr = tmp_cpsr | (Bit32 (value, 9) << 9); 12575 if (privileged) 12576 tmp_cpsr = tmp_cpsr | (Bit32 (value, 8) << 8); 12577 } 12578 12579 if (BitIsSet (bytemask, 0)) 12580 { 12581 if (privileged) 12582 tmp_cpsr = tmp_cpsr | (Bits32 (value, 7, 6) << 6); 12583 if (affect_execstate) 12584 tmp_cpsr = tmp_cpsr | (Bit32 (value, 5) << 5); 12585 if (privileged) 12586 tmp_cpsr = tmp_cpsr | Bits32 (value, 4, 0); 12587 } 12588 12589 m_opcode_cpsr = tmp_cpsr; 12590} 12591 12592 12593bool 12594EmulateInstructionARM::BranchWritePC (const Context &context, uint32_t addr) 12595{ 12596 addr_t target; 12597 12598 // Check the current instruction set. 12599 if (CurrentInstrSet() == eModeARM) 12600 target = addr & 0xfffffffc; 12601 else 12602 target = addr & 0xfffffffe; 12603 12604 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, target)) 12605 return false; 12606 12607 return true; 12608} 12609 12610// As a side effect, BXWritePC sets context.arg2 to eModeARM or eModeThumb by inspecting addr. 12611bool 12612EmulateInstructionARM::BXWritePC (Context &context, uint32_t addr) 12613{ 12614 addr_t target; 12615 // If the CPSR is changed due to switching between ARM and Thumb ISETSTATE, 12616 // we want to record it and issue a WriteRegister callback so the clients 12617 // can track the mode changes accordingly. 12618 bool cpsr_changed = false; 12619 12620 if (BitIsSet(addr, 0)) 12621 { 12622 if (CurrentInstrSet() != eModeThumb) 12623 { 12624 SelectInstrSet(eModeThumb); 12625 cpsr_changed = true; 12626 } 12627 target = addr & 0xfffffffe; 12628 context.SetMode (eModeThumb); 12629 } 12630 else if (BitIsClear(addr, 1)) 12631 { 12632 if (CurrentInstrSet() != eModeARM) 12633 { 12634 SelectInstrSet(eModeARM); 12635 cpsr_changed = true; 12636 } 12637 target = addr & 0xfffffffc; 12638 context.SetMode (eModeARM); 12639 } 12640 else 12641 return false; // address<1:0> == '10' => UNPREDICTABLE 12642 12643 if (cpsr_changed) 12644 { 12645 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS, m_new_inst_cpsr)) 12646 return false; 12647 } 12648 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, target)) 12649 return false; 12650 12651 return true; 12652} 12653 12654// Dispatches to either BXWritePC or BranchWritePC based on architecture versions. 12655bool 12656EmulateInstructionARM::LoadWritePC (Context &context, uint32_t addr) 12657{ 12658 if (ArchVersion() >= ARMv5T) 12659 return BXWritePC(context, addr); 12660 else 12661 return BranchWritePC((const Context)context, addr); 12662} 12663 12664// Dispatches to either BXWritePC or BranchWritePC based on architecture versions and current instruction set. 12665bool 12666EmulateInstructionARM::ALUWritePC (Context &context, uint32_t addr) 12667{ 12668 if (ArchVersion() >= ARMv7 && CurrentInstrSet() == eModeARM) 12669 return BXWritePC(context, addr); 12670 else 12671 return BranchWritePC((const Context)context, addr); 12672} 12673 12674EmulateInstructionARM::Mode 12675EmulateInstructionARM::CurrentInstrSet () 12676{ 12677 return m_opcode_mode; 12678} 12679 12680// Set the 'T' bit of our CPSR. The m_opcode_mode gets updated when the next 12681// ReadInstruction() is performed. This function has a side effect of updating 12682// the m_new_inst_cpsr member variable if necessary. 12683bool 12684EmulateInstructionARM::SelectInstrSet (Mode arm_or_thumb) 12685{ 12686 m_new_inst_cpsr = m_opcode_cpsr; 12687 switch (arm_or_thumb) 12688 { 12689 default: 12690 return false; 12691 eModeARM: 12692 // Clear the T bit. 12693 m_new_inst_cpsr &= ~MASK_CPSR_T; 12694 break; 12695 eModeThumb: 12696 // Set the T bit. 12697 m_new_inst_cpsr |= MASK_CPSR_T; 12698 break; 12699 } 12700 return true; 12701} 12702 12703// This function returns TRUE if the processor currently provides support for 12704// unaligned memory accesses, or FALSE otherwise. This is always TRUE in ARMv7, 12705// controllable by the SCTLR.U bit in ARMv6, and always FALSE before ARMv6. 12706bool 12707EmulateInstructionARM::UnalignedSupport() 12708{ 12709 return (ArchVersion() >= ARMv7); 12710} 12711 12712// The main addition and subtraction instructions can produce status information 12713// about both unsigned carry and signed overflow conditions. This status 12714// information can be used to synthesize multi-word additions and subtractions. 12715EmulateInstructionARM::AddWithCarryResult 12716EmulateInstructionARM::AddWithCarry (uint32_t x, uint32_t y, uint8_t carry_in) 12717{ 12718 uint32_t result; 12719 uint8_t carry_out; 12720 uint8_t overflow; 12721 12722 uint64_t unsigned_sum = x + y + carry_in; 12723 int64_t signed_sum = (int32_t)x + (int32_t)y + (int32_t)carry_in; 12724 12725 result = UnsignedBits(unsigned_sum, 31, 0); 12726 carry_out = (result == unsigned_sum ? 0 : 1); 12727 overflow = ((int32_t)result == signed_sum ? 0 : 1); 12728 12729 AddWithCarryResult res = { result, carry_out, overflow }; 12730 return res; 12731} 12732 12733uint32_t 12734EmulateInstructionARM::ReadCoreReg(uint32_t num, bool *success) 12735{ 12736 uint32_t reg_kind, reg_num; 12737 switch (num) 12738 { 12739 case SP_REG: 12740 reg_kind = eRegisterKindGeneric; 12741 reg_num = LLDB_REGNUM_GENERIC_SP; 12742 break; 12743 case LR_REG: 12744 reg_kind = eRegisterKindGeneric; 12745 reg_num = LLDB_REGNUM_GENERIC_RA; 12746 break; 12747 case PC_REG: 12748 reg_kind = eRegisterKindGeneric; 12749 reg_num = LLDB_REGNUM_GENERIC_PC; 12750 break; 12751 default: 12752 if (num < SP_REG) 12753 { 12754 reg_kind = eRegisterKindDWARF; 12755 reg_num = dwarf_r0 + num; 12756 } 12757 else 12758 { 12759 assert(0 && "Invalid register number"); 12760 *success = false; 12761 return UINT32_MAX; 12762 } 12763 break; 12764 } 12765 12766 // Read our register. 12767 uint32_t val = ReadRegisterUnsigned (reg_kind, reg_num, 0, success); 12768 12769 // When executing an ARM instruction , PC reads as the address of the current 12770 // instruction plus 8. 12771 // When executing a Thumb instruction , PC reads as the address of the current 12772 // instruction plus 4. 12773 if (num == 15) 12774 { 12775 if (CurrentInstrSet() == eModeARM) 12776 val += 8; 12777 else 12778 val += 4; 12779 } 12780 12781 return val; 12782} 12783 12784// Write the result to the ARM core register Rd, and optionally update the 12785// condition flags based on the result. 12786// 12787// This helper method tries to encapsulate the following pseudocode from the 12788// ARM Architecture Reference Manual: 12789// 12790// if d == 15 then // Can only occur for encoding A1 12791// ALUWritePC(result); // setflags is always FALSE here 12792// else 12793// R[d] = result; 12794// if setflags then 12795// APSR.N = result<31>; 12796// APSR.Z = IsZeroBit(result); 12797// APSR.C = carry; 12798// // APSR.V unchanged 12799// 12800// In the above case, the API client does not pass in the overflow arg, which 12801// defaults to ~0u. 12802bool 12803EmulateInstructionARM::WriteCoreRegOptionalFlags (Context &context, 12804 const uint32_t result, 12805 const uint32_t Rd, 12806 bool setflags, 12807 const uint32_t carry, 12808 const uint32_t overflow) 12809{ 12810 if (Rd == 15) 12811 { 12812 if (!ALUWritePC (context, result)) 12813 return false; 12814 } 12815 else 12816 { 12817 uint32_t reg_kind, reg_num; 12818 switch (Rd) 12819 { 12820 case SP_REG: 12821 reg_kind = eRegisterKindGeneric; 12822 reg_num = LLDB_REGNUM_GENERIC_SP; 12823 break; 12824 case LR_REG: 12825 reg_kind = eRegisterKindGeneric; 12826 reg_num = LLDB_REGNUM_GENERIC_RA; 12827 break; 12828 default: 12829 reg_kind = eRegisterKindDWARF; 12830 reg_num = dwarf_r0 + Rd; 12831 } 12832 if (!WriteRegisterUnsigned (context, reg_kind, reg_num, result)) 12833 return false; 12834 if (setflags) 12835 return WriteFlags (context, result, carry, overflow); 12836 } 12837 return true; 12838} 12839 12840// This helper method tries to encapsulate the following pseudocode from the 12841// ARM Architecture Reference Manual: 12842// 12843// APSR.N = result<31>; 12844// APSR.Z = IsZeroBit(result); 12845// APSR.C = carry; 12846// APSR.V = overflow 12847// 12848// Default arguments can be specified for carry and overflow parameters, which means 12849// not to update the respective flags. 12850bool 12851EmulateInstructionARM::WriteFlags (Context &context, 12852 const uint32_t result, 12853 const uint32_t carry, 12854 const uint32_t overflow) 12855{ 12856 m_new_inst_cpsr = m_opcode_cpsr; 12857 SetBit32(m_new_inst_cpsr, CPSR_N_POS, Bit32(result, CPSR_N_POS)); 12858 SetBit32(m_new_inst_cpsr, CPSR_Z_POS, result == 0 ? 1 : 0); 12859 if (carry != ~0u) 12860 SetBit32(m_new_inst_cpsr, CPSR_C_POS, carry); 12861 if (overflow != ~0u) 12862 SetBit32(m_new_inst_cpsr, CPSR_V_POS, overflow); 12863 if (m_new_inst_cpsr != m_opcode_cpsr) 12864 { 12865 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS, m_new_inst_cpsr)) 12866 return false; 12867 } 12868 return true; 12869} 12870 12871bool 12872EmulateInstructionARM::EvaluateInstruction () 12873{ 12874 // Advance the ITSTATE bits to their values for the next instruction. 12875 if (m_opcode_mode == eModeThumb && m_it_session.InITBlock()) 12876 m_it_session.ITAdvance(); 12877 12878 return false; 12879} 12880