1 //===-- EmulateInstructionARM.cpp -------------------------------*- C++ -*-===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
12 #include "EmulateInstructionARM.h"
13 #include "EmulationStateARM.h"
14 #include "lldb/Core/Address.h"
15 #include "lldb/Core/ArchSpec.h"
16 #include "lldb/Core/ConstString.h"
17 #include "lldb/Core/PluginManager.h"
18 #include "lldb/Core/Stream.h"
19 #include "lldb/Host/PosixApi.h"
20 #include "lldb/Interpreter/OptionValueArray.h"
21 #include "lldb/Interpreter/OptionValueDictionary.h"
22 #include "lldb/Symbol/UnwindPlan.h"
24 #include "Plugins/Process/Utility/ARMDefines.h"
25 #include "Plugins/Process/Utility/ARMUtils.h"
26 #include "Utility/ARM_DWARF_Registers.h"
28 #include "llvm/ADT/STLExtras.h"
29 #include "llvm/Support/MathExtras.h" // for SignExtend32 template function
30 // and countTrailingZeros function
33 using namespace lldb_private;
35 // Convenient macro definitions.
36 #define APSR_C Bit32(m_opcode_cpsr, CPSR_C_POS)
37 #define APSR_V Bit32(m_opcode_cpsr, CPSR_V_POS)
39 #define AlignPC(pc_val) (pc_val & 0xFFFFFFFC)
41 //----------------------------------------------------------------------
43 // ITSession implementation
45 //----------------------------------------------------------------------
48 // Valid return values are {1, 2, 3, 4}, with 0 signifying an error condition.
49 static uint32_t CountITSize(uint32_t ITMask) {
50 // First count the trailing zeros of the IT mask.
51 uint32_t TZ = llvm::countTrailingZeros(ITMask);
53 #ifdef LLDB_CONFIGURATION_DEBUG
54 printf("Encoding error: IT Mask '0000'\n");
61 // Init ITState. Note that at least one bit is always 1 in mask.
62 bool ITSession::InitIT(uint32_t bits7_0) {
63 ITCounter = CountITSize(Bits32(bits7_0, 3, 0));
68 unsigned short FirstCond = Bits32(bits7_0, 7, 4);
69 if (FirstCond == 0xF) {
70 #ifdef LLDB_CONFIGURATION_DEBUG
71 printf("Encoding error: IT FirstCond '1111'\n");
75 if (FirstCond == 0xE && ITCounter != 1) {
76 #ifdef LLDB_CONFIGURATION_DEBUG
77 printf("Encoding error: IT FirstCond '1110' && Mask != '1000'\n");
86 // Update ITState if necessary.
87 void ITSession::ITAdvance() {
93 unsigned short NewITState4_0 = Bits32(ITState, 4, 0) << 1;
94 SetBits32(ITState, 4, 0, NewITState4_0);
98 // Return true if we're inside an IT Block.
99 bool ITSession::InITBlock() { return ITCounter != 0; }
101 // Return true if we're the last instruction inside an IT Block.
102 bool ITSession::LastInITBlock() { return ITCounter == 1; }
104 // Get condition bits for the current thumb instruction.
105 uint32_t ITSession::GetCond() {
107 return Bits32(ITState, 7, 4);
112 // ARM constants used during decoding
114 #define LDM_REGLIST 1
118 #define PC_REGLIST_BIT 0x8000
120 #define ARMv4 (1u << 0)
121 #define ARMv4T (1u << 1)
122 #define ARMv5T (1u << 2)
123 #define ARMv5TE (1u << 3)
124 #define ARMv5TEJ (1u << 4)
125 #define ARMv6 (1u << 5)
126 #define ARMv6K (1u << 6)
127 #define ARMv6T2 (1u << 7)
128 #define ARMv7 (1u << 8)
129 #define ARMv7S (1u << 9)
130 #define ARMv8 (1u << 10)
131 #define ARMvAll (0xffffffffu)
133 #define ARMV4T_ABOVE \
134 (ARMv4T | ARMv5T | ARMv5TE | ARMv5TEJ | ARMv6 | ARMv6K | ARMv6T2 | ARMv7 | \
136 #define ARMV5_ABOVE \
137 (ARMv5T | ARMv5TE | ARMv5TEJ | ARMv6 | ARMv6K | ARMv6T2 | ARMv7 | ARMv7S | \
139 #define ARMV5TE_ABOVE \
140 (ARMv5TE | ARMv5TEJ | ARMv6 | ARMv6K | ARMv6T2 | ARMv7 | ARMv7S | ARMv8)
141 #define ARMV5J_ABOVE \
142 (ARMv5TEJ | ARMv6 | ARMv6K | ARMv6T2 | ARMv7 | ARMv7S | ARMv8)
143 #define ARMV6_ABOVE (ARMv6 | ARMv6K | ARMv6T2 | ARMv7 | ARMv7S | ARMv8)
144 #define ARMV6T2_ABOVE (ARMv6T2 | ARMv7 | ARMv7S | ARMv8)
145 #define ARMV7_ABOVE (ARMv7 | ARMv7S | ARMv8)
148 #define VFPv1 (1u << 1)
149 #define VFPv2 (1u << 2)
150 #define VFPv3 (1u << 3)
151 #define AdvancedSIMD (1u << 4)
153 #define VFPv1_ABOVE (VFPv1 | VFPv2 | VFPv3 | AdvancedSIMD)
154 #define VFPv2_ABOVE (VFPv2 | VFPv3 | AdvancedSIMD)
155 #define VFPv2v3 (VFPv2 | VFPv3)
157 //----------------------------------------------------------------------
159 // EmulateInstructionARM implementation
161 //----------------------------------------------------------------------
163 void EmulateInstructionARM::Initialize() {
164 PluginManager::RegisterPlugin(GetPluginNameStatic(),
165 GetPluginDescriptionStatic(), CreateInstance);
168 void EmulateInstructionARM::Terminate() {
169 PluginManager::UnregisterPlugin(CreateInstance);
172 ConstString EmulateInstructionARM::GetPluginNameStatic() {
173 static ConstString g_name("arm");
177 const char *EmulateInstructionARM::GetPluginDescriptionStatic() {
178 return "Emulate instructions for the ARM architecture.";
182 EmulateInstructionARM::CreateInstance(const ArchSpec &arch,
183 InstructionType inst_type) {
184 if (EmulateInstructionARM::SupportsEmulatingInstructionsOfTypeStatic(
186 if (arch.GetTriple().getArch() == llvm::Triple::arm) {
187 std::unique_ptr<EmulateInstructionARM> emulate_insn_ap(
188 new EmulateInstructionARM(arch));
190 if (emulate_insn_ap.get())
191 return emulate_insn_ap.release();
192 } else if (arch.GetTriple().getArch() == llvm::Triple::thumb) {
193 std::unique_ptr<EmulateInstructionARM> emulate_insn_ap(
194 new EmulateInstructionARM(arch));
196 if (emulate_insn_ap.get())
197 return emulate_insn_ap.release();
204 bool EmulateInstructionARM::SetTargetTriple(const ArchSpec &arch) {
205 if (arch.GetTriple().getArch() == llvm::Triple::arm)
207 else if (arch.GetTriple().getArch() == llvm::Triple::thumb)
213 // Write "bits (32) UNKNOWN" to memory address "address". Helper function for
214 // many ARM instructions.
215 bool EmulateInstructionARM::WriteBits32UnknownToMemory(addr_t address) {
216 EmulateInstruction::Context context;
217 context.type = EmulateInstruction::eContextWriteMemoryRandomBits;
220 uint32_t random_data = rand();
221 const uint32_t addr_byte_size = GetAddressByteSize();
223 if (!MemAWrite(context, address, random_data, addr_byte_size))
229 // Write "bits (32) UNKNOWN" to register n. Helper function for many ARM
231 bool EmulateInstructionARM::WriteBits32Unknown(int n) {
232 EmulateInstruction::Context context;
233 context.type = EmulateInstruction::eContextWriteRegisterRandomBits;
238 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
243 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n, data))
249 bool EmulateInstructionARM::GetRegisterInfo(lldb::RegisterKind reg_kind,
251 RegisterInfo ®_info) {
252 if (reg_kind == eRegisterKindGeneric) {
254 case LLDB_REGNUM_GENERIC_PC:
255 reg_kind = eRegisterKindDWARF;
258 case LLDB_REGNUM_GENERIC_SP:
259 reg_kind = eRegisterKindDWARF;
262 case LLDB_REGNUM_GENERIC_FP:
263 reg_kind = eRegisterKindDWARF;
266 case LLDB_REGNUM_GENERIC_RA:
267 reg_kind = eRegisterKindDWARF;
270 case LLDB_REGNUM_GENERIC_FLAGS:
271 reg_kind = eRegisterKindDWARF;
272 reg_num = dwarf_cpsr;
279 if (reg_kind == eRegisterKindDWARF)
280 return GetARMDWARFRegisterInfo(reg_num, reg_info);
284 uint32_t EmulateInstructionARM::GetFramePointerRegisterNumber() const {
285 if (m_arch.GetTriple().isAndroid())
286 return LLDB_INVALID_REGNUM; // Don't use frame pointer on android
287 bool is_apple = false;
288 if (m_arch.GetTriple().getVendor() == llvm::Triple::Apple)
290 switch (m_arch.GetTriple().getOS()) {
291 case llvm::Triple::Darwin:
292 case llvm::Triple::MacOSX:
293 case llvm::Triple::IOS:
294 case llvm::Triple::TvOS:
295 case llvm::Triple::WatchOS:
302 /* On Apple iOS et al, the frame pointer register is always r7.
303 * Typically on other ARM systems, thumb code uses r7; arm code uses r11.
306 uint32_t fp_regnum = 11;
311 if (m_opcode_mode == eModeThumb)
317 uint32_t EmulateInstructionARM::GetFramePointerDWARFRegisterNumber() const {
318 bool is_apple = false;
319 if (m_arch.GetTriple().getVendor() == llvm::Triple::Apple)
321 switch (m_arch.GetTriple().getOS()) {
322 case llvm::Triple::Darwin:
323 case llvm::Triple::MacOSX:
324 case llvm::Triple::IOS:
331 /* On Apple iOS et al, the frame pointer register is always r7.
332 * Typically on other ARM systems, thumb code uses r7; arm code uses r11.
335 uint32_t fp_regnum = dwarf_r11;
338 fp_regnum = dwarf_r7;
340 if (m_opcode_mode == eModeThumb)
341 fp_regnum = dwarf_r7;
346 // Push Multiple Registers stores multiple registers to the stack, storing to
347 // consecutive memory locations ending just below the address in SP, and updates
348 // SP to point to the start of the stored data.
349 bool EmulateInstructionARM::EmulatePUSH(const uint32_t opcode,
350 const ARMEncoding encoding) {
352 // ARM pseudo code...
353 if (ConditionPassed())
355 EncodingSpecificOperations();
356 NullCheckIfThumbEE(13);
357 address = SP - 4*BitCount(registers);
361 if (registers<i> == '1')
363 if i == 13 && i != LowestSetBit(registers) // Only possible for encoding A1
364 MemA[address,4] = bits(32) UNKNOWN;
366 MemA[address,4] = R[i];
367 address = address + 4;
371 if (registers<15> == '1') // Only possible for encoding A1 or A2
372 MemA[address,4] = PCStoreValue();
374 SP = SP - 4*BitCount(registers);
378 bool success = false;
379 if (ConditionPassed(opcode)) {
380 const uint32_t addr_byte_size = GetAddressByteSize();
381 const addr_t sp = ReadCoreReg(SP_REG, &success);
384 uint32_t registers = 0;
385 uint32_t Rt; // the source register
388 registers = Bits32(opcode, 7, 0);
389 // The M bit represents LR.
390 if (Bit32(opcode, 8))
391 registers |= (1u << 14);
392 // if BitCount(registers) < 1 then UNPREDICTABLE;
393 if (BitCount(registers) < 1)
397 // Ignore bits 15 & 13.
398 registers = Bits32(opcode, 15, 0) & ~0xa000;
399 // if BitCount(registers) < 2 then UNPREDICTABLE;
400 if (BitCount(registers) < 2)
404 Rt = Bits32(opcode, 15, 12);
405 // if BadReg(t) then UNPREDICTABLE;
408 registers = (1u << Rt);
411 registers = Bits32(opcode, 15, 0);
412 // Instead of return false, let's handle the following case as well,
413 // which amounts to pushing one reg onto the full descending stacks.
414 // if BitCount(register_list) < 2 then SEE STMDB / STMFD;
417 Rt = Bits32(opcode, 15, 12);
418 // if t == 13 then UNPREDICTABLE;
421 registers = (1u << Rt);
426 addr_t sp_offset = addr_byte_size * BitCount(registers);
427 addr_t addr = sp - sp_offset;
430 EmulateInstruction::Context context;
431 context.type = EmulateInstruction::eContextPushRegisterOnStack;
432 RegisterInfo reg_info;
434 GetRegisterInfo(eRegisterKindDWARF, dwarf_sp, sp_reg);
435 for (i = 0; i < 15; ++i) {
436 if (BitIsSet(registers, i)) {
437 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + i, reg_info);
438 context.SetRegisterToRegisterPlusOffset(reg_info, sp_reg, addr - sp);
439 uint32_t reg_value = ReadCoreReg(i, &success);
442 if (!MemAWrite(context, addr, reg_value, addr_byte_size))
444 addr += addr_byte_size;
448 if (BitIsSet(registers, 15)) {
449 GetRegisterInfo(eRegisterKindDWARF, dwarf_pc, reg_info);
450 context.SetRegisterToRegisterPlusOffset(reg_info, sp_reg, addr - sp);
451 const uint32_t pc = ReadCoreReg(PC_REG, &success);
454 if (!MemAWrite(context, addr, pc, addr_byte_size))
458 context.type = EmulateInstruction::eContextAdjustStackPointer;
459 context.SetImmediateSigned(-sp_offset);
461 if (!WriteRegisterUnsigned(context, eRegisterKindGeneric,
462 LLDB_REGNUM_GENERIC_SP, sp - sp_offset))
468 // Pop Multiple Registers loads multiple registers from the stack, loading from
469 // consecutive memory locations staring at the address in SP, and updates
470 // SP to point just above the loaded data.
471 bool EmulateInstructionARM::EmulatePOP(const uint32_t opcode,
472 const ARMEncoding encoding) {
474 // ARM pseudo code...
475 if (ConditionPassed())
477 EncodingSpecificOperations(); NullCheckIfThumbEE(13);
480 if registers<i> == '1' then
481 R[i] = if UnalignedAllowed then MemU[address,4] else MemA[address,4]; address = address + 4;
482 if registers<15> == '1' then
483 if UnalignedAllowed then
484 LoadWritePC(MemU[address,4]);
486 LoadWritePC(MemA[address,4]);
487 if registers<13> == '0' then SP = SP + 4*BitCount(registers);
488 if registers<13> == '1' then SP = bits(32) UNKNOWN;
492 bool success = false;
494 if (ConditionPassed(opcode)) {
495 const uint32_t addr_byte_size = GetAddressByteSize();
496 const addr_t sp = ReadCoreReg(SP_REG, &success);
499 uint32_t registers = 0;
500 uint32_t Rt; // the destination register
503 registers = Bits32(opcode, 7, 0);
504 // The P bit represents PC.
505 if (Bit32(opcode, 8))
506 registers |= (1u << 15);
507 // if BitCount(registers) < 1 then UNPREDICTABLE;
508 if (BitCount(registers) < 1)
513 registers = Bits32(opcode, 15, 0) & ~0x2000;
514 // if BitCount(registers) < 2 || (P == '1' && M == '1') then
516 if (BitCount(registers) < 2 || (Bit32(opcode, 15) && Bit32(opcode, 14)))
518 // if registers<15> == '1' && InITBlock() && !LastInITBlock() then
520 if (BitIsSet(registers, 15) && InITBlock() && !LastInITBlock())
524 Rt = Bits32(opcode, 15, 12);
525 // if t == 13 || (t == 15 && InITBlock() && !LastInITBlock()) then
529 if (Rt == 15 && InITBlock() && !LastInITBlock())
531 registers = (1u << Rt);
534 registers = Bits32(opcode, 15, 0);
535 // Instead of return false, let's handle the following case as well,
536 // which amounts to popping one reg from the full descending stacks.
537 // if BitCount(register_list) < 2 then SEE LDM / LDMIA / LDMFD;
539 // if registers<13> == '1' && ArchVersion() >= 7 then UNPREDICTABLE;
540 if (BitIsSet(opcode, 13) && ArchVersion() >= ARMv7)
544 Rt = Bits32(opcode, 15, 12);
545 // if t == 13 then UNPREDICTABLE;
548 registers = (1u << Rt);
553 addr_t sp_offset = addr_byte_size * BitCount(registers);
557 EmulateInstruction::Context context;
558 context.type = EmulateInstruction::eContextPopRegisterOffStack;
561 GetRegisterInfo(eRegisterKindDWARF, dwarf_sp, sp_reg);
563 for (i = 0; i < 15; ++i) {
564 if (BitIsSet(registers, i)) {
565 context.SetAddress(addr);
566 data = MemARead(context, addr, 4, 0, &success);
569 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + i,
572 addr += addr_byte_size;
576 if (BitIsSet(registers, 15)) {
577 context.SetRegisterPlusOffset(sp_reg, addr - sp);
578 data = MemARead(context, addr, 4, 0, &success);
581 // In ARMv5T and above, this is an interworking branch.
582 if (!LoadWritePC(context, data))
584 // addr += addr_byte_size;
587 context.type = EmulateInstruction::eContextAdjustStackPointer;
588 context.SetImmediateSigned(sp_offset);
590 if (!WriteRegisterUnsigned(context, eRegisterKindGeneric,
591 LLDB_REGNUM_GENERIC_SP, sp + sp_offset))
597 // Set r7 or ip to point to saved value residing within the stack.
598 // ADD (SP plus immediate)
599 bool EmulateInstructionARM::EmulateADDRdSPImm(const uint32_t opcode,
600 const ARMEncoding encoding) {
602 // ARM pseudo code...
603 if (ConditionPassed())
605 EncodingSpecificOperations();
606 (result, carry, overflow) = AddWithCarry(SP, imm32, '0');
608 ALUWritePC(result); // setflags is always FALSE here
613 APSR.Z = IsZeroBit(result);
619 bool success = false;
621 if (ConditionPassed(opcode)) {
622 const addr_t sp = ReadCoreReg(SP_REG, &success);
625 uint32_t Rd; // the destination register
630 imm32 = Bits32(opcode, 7, 0) << 2; // imm32 = ZeroExtend(imm8:'00', 32)
633 Rd = Bits32(opcode, 15, 12);
634 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
639 addr_t sp_offset = imm32;
640 addr_t addr = sp + sp_offset; // a pointer to the stack area
642 EmulateInstruction::Context context;
643 if (Rd == GetFramePointerRegisterNumber())
644 context.type = eContextSetFramePointer;
646 context.type = EmulateInstruction::eContextRegisterPlusOffset;
648 GetRegisterInfo(eRegisterKindDWARF, dwarf_sp, sp_reg);
649 context.SetRegisterPlusOffset(sp_reg, sp_offset);
651 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + Rd,
658 // Set r7 or ip to the current stack pointer.
660 bool EmulateInstructionARM::EmulateMOVRdSP(const uint32_t opcode,
661 const ARMEncoding encoding) {
663 // ARM pseudo code...
664 if (ConditionPassed())
666 EncodingSpecificOperations();
669 ALUWritePC(result); // setflags is always FALSE here
674 APSR.Z = IsZeroBit(result);
680 bool success = false;
682 if (ConditionPassed(opcode)) {
683 const addr_t sp = ReadCoreReg(SP_REG, &success);
686 uint32_t Rd; // the destination register
698 EmulateInstruction::Context context;
699 if (Rd == GetFramePointerRegisterNumber())
700 context.type = EmulateInstruction::eContextSetFramePointer;
702 context.type = EmulateInstruction::eContextRegisterPlusOffset;
704 GetRegisterInfo(eRegisterKindDWARF, dwarf_sp, sp_reg);
705 context.SetRegisterPlusOffset(sp_reg, 0);
707 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + Rd, sp))
713 // Move from high register (r8-r15) to low register (r0-r7).
715 bool EmulateInstructionARM::EmulateMOVLowHigh(const uint32_t opcode,
716 const ARMEncoding encoding) {
717 return EmulateMOVRdRm(opcode, encoding);
720 // Move from register to register.
722 bool EmulateInstructionARM::EmulateMOVRdRm(const uint32_t opcode,
723 const ARMEncoding encoding) {
725 // ARM pseudo code...
726 if (ConditionPassed())
728 EncodingSpecificOperations();
731 ALUWritePC(result); // setflags is always FALSE here
736 APSR.Z = IsZeroBit(result);
742 bool success = false;
744 if (ConditionPassed(opcode)) {
745 uint32_t Rm; // the source register
746 uint32_t Rd; // the destination register
750 Rd = Bit32(opcode, 7) << 3 | Bits32(opcode, 2, 0);
751 Rm = Bits32(opcode, 6, 3);
753 if (Rd == 15 && InITBlock() && !LastInITBlock())
757 Rd = Bits32(opcode, 2, 0);
758 Rm = Bits32(opcode, 5, 3);
764 Rd = Bits32(opcode, 11, 8);
765 Rm = Bits32(opcode, 3, 0);
766 setflags = BitIsSet(opcode, 20);
767 // if setflags && (BadReg(d) || BadReg(m)) then UNPREDICTABLE;
768 if (setflags && (BadReg(Rd) || BadReg(Rm)))
770 // if !setflags && (d == 15 || m == 15 || (d == 13 && m == 13)) then
772 if (!setflags && (Rd == 15 || Rm == 15 || (Rd == 13 && Rm == 13)))
776 Rd = Bits32(opcode, 15, 12);
777 Rm = Bits32(opcode, 3, 0);
778 setflags = BitIsSet(opcode, 20);
780 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related
782 if (Rd == 15 && setflags)
783 return EmulateSUBSPcLrEtc(opcode, encoding);
788 uint32_t result = ReadCoreReg(Rm, &success);
792 // The context specifies that Rm is to be moved into Rd.
793 EmulateInstruction::Context context;
795 context.type = EmulateInstruction::eContextAdjustStackPointer;
797 context.type = EmulateInstruction::eContextRegisterPlusOffset;
798 RegisterInfo dwarf_reg;
799 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + Rm, dwarf_reg);
800 context.SetRegisterPlusOffset(dwarf_reg, 0);
802 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags))
808 // Move (immediate) writes an immediate value to the destination register. It
809 // can optionally update the condition flags based on the value.
811 bool EmulateInstructionARM::EmulateMOVRdImm(const uint32_t opcode,
812 const ARMEncoding encoding) {
814 // ARM pseudo code...
815 if (ConditionPassed())
817 EncodingSpecificOperations();
819 if d == 15 then // Can only occur for ARM encoding
820 ALUWritePC(result); // setflags is always FALSE here
825 APSR.Z = IsZeroBit(result);
831 if (ConditionPassed(opcode)) {
832 uint32_t Rd; // the destination register
833 uint32_t imm32; // the immediate value to be written to Rd
835 0; // the carry bit after ThumbExpandImm_C or ARMExpandImm_C.
836 // for setflags == false, this value is a don't care
837 // initialized to 0 to silence the static analyzer
841 Rd = Bits32(opcode, 10, 8);
842 setflags = !InITBlock();
843 imm32 = Bits32(opcode, 7, 0); // imm32 = ZeroExtend(imm8, 32)
849 Rd = Bits32(opcode, 11, 8);
850 setflags = BitIsSet(opcode, 20);
851 imm32 = ThumbExpandImm_C(opcode, APSR_C, carry);
858 // d = UInt(Rd); setflags = FALSE; imm32 = ZeroExtend(imm4:i:imm3:imm8,
860 Rd = Bits32(opcode, 11, 8);
862 uint32_t imm4 = Bits32(opcode, 19, 16);
863 uint32_t imm3 = Bits32(opcode, 14, 12);
864 uint32_t i = Bit32(opcode, 26);
865 uint32_t imm8 = Bits32(opcode, 7, 0);
866 imm32 = (imm4 << 12) | (i << 11) | (imm3 << 8) | imm8;
868 // if BadReg(d) then UNPREDICTABLE;
874 // d = UInt(Rd); setflags = (S == '1'); (imm32, carry) =
875 // ARMExpandImm_C(imm12, APSR.C);
876 Rd = Bits32(opcode, 15, 12);
877 setflags = BitIsSet(opcode, 20);
878 imm32 = ARMExpandImm_C(opcode, APSR_C, carry);
880 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related
882 if ((Rd == 15) && setflags)
883 return EmulateSUBSPcLrEtc(opcode, encoding);
888 // d = UInt(Rd); setflags = FALSE; imm32 = ZeroExtend(imm4:imm12, 32);
889 Rd = Bits32(opcode, 15, 12);
891 uint32_t imm4 = Bits32(opcode, 19, 16);
892 uint32_t imm12 = Bits32(opcode, 11, 0);
893 imm32 = (imm4 << 12) | imm12;
895 // if d == 15 then UNPREDICTABLE;
903 uint32_t result = imm32;
905 // The context specifies that an immediate is to be moved into Rd.
906 EmulateInstruction::Context context;
907 context.type = EmulateInstruction::eContextImmediate;
910 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
916 // MUL multiplies two register values. The least significant 32 bits of the
917 // result are written to the destination
918 // register. These 32 bits do not depend on whether the source register values
919 // are considered to be signed values or
922 // Optionally, it can update the condition flags based on the result. In the
923 // Thumb instruction set, this option is
924 // limited to only a few forms of the instruction.
925 bool EmulateInstructionARM::EmulateMUL(const uint32_t opcode,
926 const ARMEncoding encoding) {
928 if ConditionPassed() then
929 EncodingSpecificOperations();
930 operand1 = SInt(R[n]); // operand1 = UInt(R[n]) produces the same final results
931 operand2 = SInt(R[m]); // operand2 = UInt(R[m]) produces the same final results
932 result = operand1 * operand2;
936 APSR.Z = IsZeroBit(result);
937 if ArchVersion() == 4 then
938 APSR.C = bit UNKNOWN;
939 // else APSR.C unchanged
940 // APSR.V always unchanged
943 if (ConditionPassed(opcode)) {
949 // EncodingSpecificOperations();
952 // d = UInt(Rdm); n = UInt(Rn); m = UInt(Rdm); setflags = !InITBlock();
953 d = Bits32(opcode, 2, 0);
954 n = Bits32(opcode, 5, 3);
955 m = Bits32(opcode, 2, 0);
956 setflags = !InITBlock();
958 // if ArchVersion() < 6 && d == n then UNPREDICTABLE;
959 if ((ArchVersion() < ARMv6) && (d == n))
965 // d = UInt(Rd); n = UInt(Rn); m = UInt(Rm); setflags = FALSE;
966 d = Bits32(opcode, 11, 8);
967 n = Bits32(opcode, 19, 16);
968 m = Bits32(opcode, 3, 0);
971 // if BadReg(d) || BadReg(n) || BadReg(m) then UNPREDICTABLE;
972 if (BadReg(d) || BadReg(n) || BadReg(m))
978 // d = UInt(Rd); n = UInt(Rn); m = UInt(Rm); setflags = (S == '1');
979 d = Bits32(opcode, 19, 16);
980 n = Bits32(opcode, 3, 0);
981 m = Bits32(opcode, 11, 8);
982 setflags = BitIsSet(opcode, 20);
984 // if d == 15 || n == 15 || m == 15 then UNPREDICTABLE;
985 if ((d == 15) || (n == 15) || (m == 15))
988 // if ArchVersion() < 6 && d == n then UNPREDICTABLE;
989 if ((ArchVersion() < ARMv6) && (d == n))
998 bool success = false;
1000 // operand1 = SInt(R[n]); // operand1 = UInt(R[n]) produces the same final
1003 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
1007 // operand2 = SInt(R[m]); // operand2 = UInt(R[m]) produces the same final
1010 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
1014 // result = operand1 * operand2;
1015 uint64_t result = operand1 * operand2;
1017 // R[d] = result<31:0>;
1018 RegisterInfo op1_reg;
1019 RegisterInfo op2_reg;
1020 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n, op1_reg);
1021 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + m, op2_reg);
1023 EmulateInstruction::Context context;
1024 context.type = eContextArithmetic;
1025 context.SetRegisterRegisterOperands(op1_reg, op2_reg);
1027 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + d,
1028 (0x0000ffff & result)))
1033 // APSR.N = result<31>;
1034 // APSR.Z = IsZeroBit(result);
1035 m_new_inst_cpsr = m_opcode_cpsr;
1036 SetBit32(m_new_inst_cpsr, CPSR_N_POS, Bit32(result, 31));
1037 SetBit32(m_new_inst_cpsr, CPSR_Z_POS, result == 0 ? 1 : 0);
1038 if (m_new_inst_cpsr != m_opcode_cpsr) {
1039 if (!WriteRegisterUnsigned(context, eRegisterKindGeneric,
1040 LLDB_REGNUM_GENERIC_FLAGS, m_new_inst_cpsr))
1044 // if ArchVersion() == 4 then
1045 // APSR.C = bit UNKNOWN;
1051 // Bitwise NOT (immediate) writes the bitwise inverse of an immediate value to
1052 // the destination register.
1053 // It can optionally update the condition flags based on the value.
1054 bool EmulateInstructionARM::EmulateMVNImm(const uint32_t opcode,
1055 const ARMEncoding encoding) {
1057 // ARM pseudo code...
1058 if (ConditionPassed())
1060 EncodingSpecificOperations();
1061 result = NOT(imm32);
1062 if d == 15 then // Can only occur for ARM encoding
1063 ALUWritePC(result); // setflags is always FALSE here
1067 APSR.N = result<31>;
1068 APSR.Z = IsZeroBit(result);
1074 if (ConditionPassed(opcode)) {
1075 uint32_t Rd; // the destination register
1076 uint32_t imm32; // the output after ThumbExpandImm_C or ARMExpandImm_C
1077 uint32_t carry; // the carry bit after ThumbExpandImm_C or ARMExpandImm_C
1081 Rd = Bits32(opcode, 11, 8);
1082 setflags = BitIsSet(opcode, 20);
1083 imm32 = ThumbExpandImm_C(opcode, APSR_C, carry);
1086 Rd = Bits32(opcode, 15, 12);
1087 setflags = BitIsSet(opcode, 20);
1088 imm32 = ARMExpandImm_C(opcode, APSR_C, carry);
1090 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related
1092 if (Rd == 15 && setflags)
1093 return EmulateSUBSPcLrEtc(opcode, encoding);
1098 uint32_t result = ~imm32;
1100 // The context specifies that an immediate is to be moved into Rd.
1101 EmulateInstruction::Context context;
1102 context.type = EmulateInstruction::eContextImmediate;
1103 context.SetNoArgs();
1105 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
1111 // Bitwise NOT (register) writes the bitwise inverse of a register value to the
1112 // destination register.
1113 // It can optionally update the condition flags based on the result.
1114 bool EmulateInstructionARM::EmulateMVNReg(const uint32_t opcode,
1115 const ARMEncoding encoding) {
1117 // ARM pseudo code...
1118 if (ConditionPassed())
1120 EncodingSpecificOperations();
1121 (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C);
1122 result = NOT(shifted);
1123 if d == 15 then // Can only occur for ARM encoding
1124 ALUWritePC(result); // setflags is always FALSE here
1128 APSR.N = result<31>;
1129 APSR.Z = IsZeroBit(result);
1135 if (ConditionPassed(opcode)) {
1136 uint32_t Rm; // the source register
1137 uint32_t Rd; // the destination register
1138 ARM_ShifterType shift_t;
1139 uint32_t shift_n; // the shift applied to the value read from Rm
1141 uint32_t carry; // the carry bit after the shift operation
1144 Rd = Bits32(opcode, 2, 0);
1145 Rm = Bits32(opcode, 5, 3);
1146 setflags = !InITBlock();
1147 shift_t = SRType_LSL;
1153 Rd = Bits32(opcode, 11, 8);
1154 Rm = Bits32(opcode, 3, 0);
1155 setflags = BitIsSet(opcode, 20);
1156 shift_n = DecodeImmShiftThumb(opcode, shift_t);
1157 // if (BadReg(d) || BadReg(m)) then UNPREDICTABLE;
1158 if (BadReg(Rd) || BadReg(Rm))
1162 Rd = Bits32(opcode, 15, 12);
1163 Rm = Bits32(opcode, 3, 0);
1164 setflags = BitIsSet(opcode, 20);
1165 shift_n = DecodeImmShiftARM(opcode, shift_t);
1170 bool success = false;
1171 uint32_t value = ReadCoreReg(Rm, &success);
1176 Shift_C(value, shift_t, shift_n, APSR_C, carry, &success);
1179 uint32_t result = ~shifted;
1181 // The context specifies that an immediate is to be moved into Rd.
1182 EmulateInstruction::Context context;
1183 context.type = EmulateInstruction::eContextImmediate;
1184 context.SetNoArgs();
1186 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
1192 // PC relative immediate load into register, possibly followed by ADD (SP plus
1195 bool EmulateInstructionARM::EmulateLDRRtPCRelative(const uint32_t opcode,
1196 const ARMEncoding encoding) {
1198 // ARM pseudo code...
1199 if (ConditionPassed())
1201 EncodingSpecificOperations(); NullCheckIfThumbEE(15);
1203 address = if add then (base + imm32) else (base - imm32);
1204 data = MemU[address,4];
1206 if address<1:0> == '00' then LoadWritePC(data); else UNPREDICTABLE;
1207 elsif UnalignedSupport() || address<1:0> = '00' then
1209 else // Can only apply before ARMv7
1210 if CurrentInstrSet() == InstrSet_ARM then
1211 R[t] = ROR(data, 8*UInt(address<1:0>));
1213 R[t] = bits(32) UNKNOWN;
1217 if (ConditionPassed(opcode)) {
1218 bool success = false;
1219 const uint32_t pc = ReadCoreReg(PC_REG, &success);
1223 // PC relative immediate load context
1224 EmulateInstruction::Context context;
1225 context.type = EmulateInstruction::eContextRegisterPlusOffset;
1226 RegisterInfo pc_reg;
1227 GetRegisterInfo(eRegisterKindDWARF, dwarf_pc, pc_reg);
1228 context.SetRegisterPlusOffset(pc_reg, 0);
1230 uint32_t Rt; // the destination register
1231 uint32_t imm32; // immediate offset from the PC
1232 bool add; // +imm32 or -imm32?
1233 addr_t base; // the base address
1234 addr_t address; // the PC relative address
1235 uint32_t data; // the literal data value from the PC relative load
1238 Rt = Bits32(opcode, 10, 8);
1239 imm32 = Bits32(opcode, 7, 0) << 2; // imm32 = ZeroExtend(imm8:'00', 32);
1243 Rt = Bits32(opcode, 15, 12);
1244 imm32 = Bits32(opcode, 11, 0) << 2; // imm32 = ZeroExtend(imm12, 32);
1245 add = BitIsSet(opcode, 23);
1246 if (Rt == 15 && InITBlock() && !LastInITBlock())
1253 base = Align(pc, 4);
1255 address = base + imm32;
1257 address = base - imm32;
1259 context.SetRegisterPlusOffset(pc_reg, address - base);
1260 data = MemURead(context, address, 4, 0, &success);
1265 if (Bits32(address, 1, 0) == 0) {
1266 // In ARMv5T and above, this is an interworking branch.
1267 if (!LoadWritePC(context, data))
1271 } else if (UnalignedSupport() || Bits32(address, 1, 0) == 0) {
1272 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + Rt,
1275 } else // We don't handle ARM for now.
1281 // An add operation to adjust the SP.
1282 // ADD (SP plus immediate)
1283 bool EmulateInstructionARM::EmulateADDSPImm(const uint32_t opcode,
1284 const ARMEncoding encoding) {
1286 // ARM pseudo code...
1287 if (ConditionPassed())
1289 EncodingSpecificOperations();
1290 (result, carry, overflow) = AddWithCarry(SP, imm32, '0');
1291 if d == 15 then // Can only occur for ARM encoding
1292 ALUWritePC(result); // setflags is always FALSE here
1296 APSR.N = result<31>;
1297 APSR.Z = IsZeroBit(result);
1303 bool success = false;
1305 if (ConditionPassed(opcode)) {
1306 const addr_t sp = ReadCoreReg(SP_REG, &success);
1309 uint32_t imm32; // the immediate operand
1314 // d = UInt(Rd); setflags = FALSE; imm32 = ZeroExtend(imm8:'00', 32);
1315 d = Bits32(opcode, 10, 8);
1316 imm32 = (Bits32(opcode, 7, 0) << 2);
1321 // d = 13; setflags = FALSE; imm32 = ZeroExtend(imm7:'00', 32);
1323 imm32 = ThumbImm7Scaled(opcode); // imm32 = ZeroExtend(imm7:'00', 32)
1328 // d = UInt(Rd); setflags = (S == "1"); imm32 =
1329 // ThumbExpandImm(i:imm3:imm8);
1330 d = Bits32(opcode, 11, 8);
1331 imm32 = ThumbExpandImm(opcode);
1332 setflags = Bit32(opcode, 20);
1334 // if Rd == "1111" && S == "1" then SEE CMN (immediate);
1335 if (d == 15 && setflags == 1)
1336 return false; // CMN (immediate) not yet supported
1338 // if d == 15 && S == "0" then UNPREDICTABLE;
1339 if (d == 15 && setflags == 0)
1344 // if Rn == '1111' then SEE ADR;
1345 // d = UInt(Rd); setflags = FALSE; imm32 = ZeroExtend(i:imm3:imm8, 32);
1346 d = Bits32(opcode, 11, 8);
1348 uint32_t i = Bit32(opcode, 26);
1349 uint32_t imm3 = Bits32(opcode, 14, 12);
1350 uint32_t imm8 = Bits32(opcode, 7, 0);
1351 imm32 = (i << 11) | (imm3 << 8) | imm8;
1353 // if d == 15 then UNPREDICTABLE;
1361 // (result, carry, overflow) = AddWithCarry(R[n], imm32, '0');
1362 AddWithCarryResult res = AddWithCarry(sp, imm32, 0);
1364 EmulateInstruction::Context context;
1366 context.type = EmulateInstruction::eContextAdjustStackPointer;
1368 context.type = EmulateInstruction::eContextRegisterPlusOffset;
1370 RegisterInfo sp_reg;
1371 GetRegisterInfo(eRegisterKindDWARF, dwarf_sp, sp_reg);
1372 context.SetRegisterPlusOffset(sp_reg, res.result - sp);
1375 if (!ALUWritePC(context, res.result))
1380 // APSR.N = result<31>;
1381 // APSR.Z = IsZeroBit(result);
1383 // APSR.V = overflow;
1384 if (!WriteCoreRegOptionalFlags(context, res.result, d, setflags,
1385 res.carry_out, res.overflow))
1392 // An add operation to adjust the SP.
1393 // ADD (SP plus register)
1394 bool EmulateInstructionARM::EmulateADDSPRm(const uint32_t opcode,
1395 const ARMEncoding encoding) {
1397 // ARM pseudo code...
1398 if (ConditionPassed())
1400 EncodingSpecificOperations();
1401 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
1402 (result, carry, overflow) = AddWithCarry(SP, shifted, '0');
1404 ALUWritePC(result); // setflags is always FALSE here
1408 APSR.N = result<31>;
1409 APSR.Z = IsZeroBit(result);
1415 bool success = false;
1417 if (ConditionPassed(opcode)) {
1418 const addr_t sp = ReadCoreReg(SP_REG, &success);
1421 uint32_t Rm; // the second operand
1424 Rm = Bits32(opcode, 6, 3);
1429 int32_t reg_value = ReadCoreReg(Rm, &success);
1433 addr_t addr = (int32_t)sp + reg_value; // the adjusted stack pointer value
1435 EmulateInstruction::Context context;
1436 context.type = eContextArithmetic;
1437 RegisterInfo sp_reg;
1438 GetRegisterInfo(eRegisterKindDWARF, dwarf_sp, sp_reg);
1440 RegisterInfo other_reg;
1441 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + Rm, other_reg);
1442 context.SetRegisterRegisterOperands(sp_reg, other_reg);
1444 if (!WriteRegisterUnsigned(context, eRegisterKindGeneric,
1445 LLDB_REGNUM_GENERIC_SP, addr))
1451 // Branch with Link and Exchange Instruction Sets (immediate) calls a subroutine
1452 // at a PC-relative address, and changes instruction set from ARM to Thumb, or
1453 // from Thumb to ARM.
1455 bool EmulateInstructionARM::EmulateBLXImmediate(const uint32_t opcode,
1456 const ARMEncoding encoding) {
1458 // ARM pseudo code...
1459 if (ConditionPassed())
1461 EncodingSpecificOperations();
1462 if CurrentInstrSet() == InstrSet_ARM then
1465 LR = PC<31:1> : '1';
1466 if targetInstrSet == InstrSet_ARM then
1467 targetAddress = Align(PC,4) + imm32;
1469 targetAddress = PC + imm32;
1470 SelectInstrSet(targetInstrSet);
1471 BranchWritePC(targetAddress);
1475 bool success = true;
1477 if (ConditionPassed(opcode)) {
1478 EmulateInstruction::Context context;
1479 context.type = EmulateInstruction::eContextRelativeBranchImmediate;
1480 const uint32_t pc = ReadCoreReg(PC_REG, &success);
1483 addr_t lr; // next instruction address
1484 addr_t target; // target address
1485 int32_t imm32; // PC-relative offset
1488 lr = pc | 1u; // return address
1489 uint32_t S = Bit32(opcode, 26);
1490 uint32_t imm10 = Bits32(opcode, 25, 16);
1491 uint32_t J1 = Bit32(opcode, 13);
1492 uint32_t J2 = Bit32(opcode, 11);
1493 uint32_t imm11 = Bits32(opcode, 10, 0);
1494 uint32_t I1 = !(J1 ^ S);
1495 uint32_t I2 = !(J2 ^ S);
1497 (S << 24) | (I1 << 23) | (I2 << 22) | (imm10 << 12) | (imm11 << 1);
1498 imm32 = llvm::SignExtend32<25>(imm25);
1499 target = pc + imm32;
1500 SelectInstrSet(eModeThumb);
1501 context.SetISAAndImmediateSigned(eModeThumb, 4 + imm32);
1502 if (InITBlock() && !LastInITBlock())
1507 lr = pc | 1u; // return address
1508 uint32_t S = Bit32(opcode, 26);
1509 uint32_t imm10H = Bits32(opcode, 25, 16);
1510 uint32_t J1 = Bit32(opcode, 13);
1511 uint32_t J2 = Bit32(opcode, 11);
1512 uint32_t imm10L = Bits32(opcode, 10, 1);
1513 uint32_t I1 = !(J1 ^ S);
1514 uint32_t I2 = !(J2 ^ S);
1516 (S << 24) | (I1 << 23) | (I2 << 22) | (imm10H << 12) | (imm10L << 2);
1517 imm32 = llvm::SignExtend32<25>(imm25);
1518 target = Align(pc, 4) + imm32;
1519 SelectInstrSet(eModeARM);
1520 context.SetISAAndImmediateSigned(eModeARM, 4 + imm32);
1521 if (InITBlock() && !LastInITBlock())
1526 lr = pc - 4; // return address
1527 imm32 = llvm::SignExtend32<26>(Bits32(opcode, 23, 0) << 2);
1528 target = Align(pc, 4) + imm32;
1529 SelectInstrSet(eModeARM);
1530 context.SetISAAndImmediateSigned(eModeARM, 8 + imm32);
1533 lr = pc - 4; // return address
1534 imm32 = llvm::SignExtend32<26>(Bits32(opcode, 23, 0) << 2 |
1535 Bits32(opcode, 24, 24) << 1);
1536 target = pc + imm32;
1537 SelectInstrSet(eModeThumb);
1538 context.SetISAAndImmediateSigned(eModeThumb, 8 + imm32);
1543 if (!WriteRegisterUnsigned(context, eRegisterKindGeneric,
1544 LLDB_REGNUM_GENERIC_RA, lr))
1546 if (!BranchWritePC(context, target))
1548 if (m_opcode_cpsr != m_new_inst_cpsr)
1549 if (!WriteRegisterUnsigned(context, eRegisterKindGeneric,
1550 LLDB_REGNUM_GENERIC_FLAGS, m_new_inst_cpsr))
1556 // Branch with Link and Exchange (register) calls a subroutine at an address and
1557 // instruction set specified by a register.
1559 bool EmulateInstructionARM::EmulateBLXRm(const uint32_t opcode,
1560 const ARMEncoding encoding) {
1562 // ARM pseudo code...
1563 if (ConditionPassed())
1565 EncodingSpecificOperations();
1567 if CurrentInstrSet() == InstrSet_ARM then
1568 next_instr_addr = PC - 4;
1569 LR = next_instr_addr;
1571 next_instr_addr = PC - 2;
1572 LR = next_instr_addr<31:1> : '1';
1577 bool success = false;
1579 if (ConditionPassed(opcode)) {
1580 EmulateInstruction::Context context;
1581 context.type = EmulateInstruction::eContextAbsoluteBranchRegister;
1582 const uint32_t pc = ReadCoreReg(PC_REG, &success);
1583 addr_t lr; // next instruction address
1586 uint32_t Rm; // the register with the target address
1589 lr = (pc - 2) | 1u; // return address
1590 Rm = Bits32(opcode, 6, 3);
1591 // if m == 15 then UNPREDICTABLE;
1594 if (InITBlock() && !LastInITBlock())
1598 lr = pc - 4; // return address
1599 Rm = Bits32(opcode, 3, 0);
1600 // if m == 15 then UNPREDICTABLE;
1607 addr_t target = ReadCoreReg(Rm, &success);
1610 RegisterInfo dwarf_reg;
1611 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + Rm, dwarf_reg);
1612 context.SetRegister(dwarf_reg);
1613 if (!WriteRegisterUnsigned(context, eRegisterKindGeneric,
1614 LLDB_REGNUM_GENERIC_RA, lr))
1616 if (!BXWritePC(context, target))
1622 // Branch and Exchange causes a branch to an address and instruction set
1623 // specified by a register.
1624 bool EmulateInstructionARM::EmulateBXRm(const uint32_t opcode,
1625 const ARMEncoding encoding) {
1627 // ARM pseudo code...
1628 if (ConditionPassed())
1630 EncodingSpecificOperations();
1635 if (ConditionPassed(opcode)) {
1636 EmulateInstruction::Context context;
1637 context.type = EmulateInstruction::eContextAbsoluteBranchRegister;
1638 uint32_t Rm; // the register with the target address
1641 Rm = Bits32(opcode, 6, 3);
1642 if (InITBlock() && !LastInITBlock())
1646 Rm = Bits32(opcode, 3, 0);
1651 bool success = false;
1652 addr_t target = ReadCoreReg(Rm, &success);
1656 RegisterInfo dwarf_reg;
1657 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + Rm, dwarf_reg);
1658 context.SetRegister(dwarf_reg);
1659 if (!BXWritePC(context, target))
1665 // Branch and Exchange Jazelle attempts to change to Jazelle state. If the
1666 // attempt fails, it branches to an
1667 // address and instruction set specified by a register as though it were a BX
1670 // TODO: Emulate Jazelle architecture?
1671 // We currently assume that switching to Jazelle state fails, thus
1672 // treating BXJ as a BX operation.
1673 bool EmulateInstructionARM::EmulateBXJRm(const uint32_t opcode,
1674 const ARMEncoding encoding) {
1676 // ARM pseudo code...
1677 if (ConditionPassed())
1679 EncodingSpecificOperations();
1680 if JMCR.JE == '0' || CurrentInstrSet() == InstrSet_ThumbEE then
1683 if JazelleAcceptsExecution() then
1684 SwitchToJazelleExecution();
1686 SUBARCHITECTURE_DEFINED handler call;
1690 if (ConditionPassed(opcode)) {
1691 EmulateInstruction::Context context;
1692 context.type = EmulateInstruction::eContextAbsoluteBranchRegister;
1693 uint32_t Rm; // the register with the target address
1696 Rm = Bits32(opcode, 19, 16);
1699 if (InITBlock() && !LastInITBlock())
1703 Rm = Bits32(opcode, 3, 0);
1710 bool success = false;
1711 addr_t target = ReadCoreReg(Rm, &success);
1715 RegisterInfo dwarf_reg;
1716 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + Rm, dwarf_reg);
1717 context.SetRegister(dwarf_reg);
1718 if (!BXWritePC(context, target))
1724 // Set r7 to point to some ip offset.
1726 bool EmulateInstructionARM::EmulateSUBR7IPImm(const uint32_t opcode,
1727 const ARMEncoding encoding) {
1729 // ARM pseudo code...
1730 if (ConditionPassed())
1732 EncodingSpecificOperations();
1733 (result, carry, overflow) = AddWithCarry(SP, NOT(imm32), '1');
1734 if d == 15 then // Can only occur for ARM encoding
1735 ALUWritePC(result); // setflags is always FALSE here
1739 APSR.N = result<31>;
1740 APSR.Z = IsZeroBit(result);
1746 if (ConditionPassed(opcode)) {
1747 bool success = false;
1748 const addr_t ip = ReadCoreReg(12, &success);
1754 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
1759 addr_t ip_offset = imm32;
1760 addr_t addr = ip - ip_offset; // the adjusted ip value
1762 EmulateInstruction::Context context;
1763 context.type = EmulateInstruction::eContextRegisterPlusOffset;
1764 RegisterInfo dwarf_reg;
1765 GetRegisterInfo(eRegisterKindDWARF, dwarf_r12, dwarf_reg);
1766 context.SetRegisterPlusOffset(dwarf_reg, -ip_offset);
1768 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r7, addr))
1774 // Set ip to point to some stack offset.
1775 // SUB (SP minus immediate)
1776 bool EmulateInstructionARM::EmulateSUBIPSPImm(const uint32_t opcode,
1777 const ARMEncoding encoding) {
1779 // ARM pseudo code...
1780 if (ConditionPassed())
1782 EncodingSpecificOperations();
1783 (result, carry, overflow) = AddWithCarry(SP, NOT(imm32), '1');
1784 if d == 15 then // Can only occur for ARM encoding
1785 ALUWritePC(result); // setflags is always FALSE here
1789 APSR.N = result<31>;
1790 APSR.Z = IsZeroBit(result);
1796 if (ConditionPassed(opcode)) {
1797 bool success = false;
1798 const addr_t sp = ReadCoreReg(SP_REG, &success);
1804 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
1809 addr_t sp_offset = imm32;
1810 addr_t addr = sp - sp_offset; // the adjusted stack pointer value
1812 EmulateInstruction::Context context;
1813 context.type = EmulateInstruction::eContextRegisterPlusOffset;
1814 RegisterInfo dwarf_reg;
1815 GetRegisterInfo(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, dwarf_reg);
1816 context.SetRegisterPlusOffset(dwarf_reg, -sp_offset);
1818 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r12, addr))
1824 // This instruction subtracts an immediate value from the SP value, and writes
1825 // the result to the destination register.
1827 // If Rd == 13 => A sub operation to adjust the SP -- allocate space for local
1829 bool EmulateInstructionARM::EmulateSUBSPImm(const uint32_t opcode,
1830 const ARMEncoding encoding) {
1832 // ARM pseudo code...
1833 if (ConditionPassed())
1835 EncodingSpecificOperations();
1836 (result, carry, overflow) = AddWithCarry(SP, NOT(imm32), '1');
1837 if d == 15 then // Can only occur for ARM encoding
1838 ALUWritePC(result); // setflags is always FALSE here
1842 APSR.N = result<31>;
1843 APSR.Z = IsZeroBit(result);
1849 bool success = false;
1850 if (ConditionPassed(opcode)) {
1851 const addr_t sp = ReadCoreReg(SP_REG, &success);
1862 imm32 = ThumbImm7Scaled(opcode); // imm32 = ZeroExtend(imm7:'00', 32)
1865 Rd = Bits32(opcode, 11, 8);
1866 setflags = BitIsSet(opcode, 20);
1867 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8)
1868 if (Rd == 15 && setflags)
1869 return EmulateCMPImm(opcode, eEncodingT2);
1870 if (Rd == 15 && !setflags)
1874 Rd = Bits32(opcode, 11, 8);
1876 imm32 = ThumbImm12(opcode); // imm32 = ZeroExtend(i:imm3:imm8, 32)
1881 Rd = Bits32(opcode, 15, 12);
1882 setflags = BitIsSet(opcode, 20);
1883 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
1885 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related
1887 if (Rd == 15 && setflags)
1888 return EmulateSUBSPcLrEtc(opcode, encoding);
1893 AddWithCarryResult res = AddWithCarry(sp, ~imm32, 1);
1895 EmulateInstruction::Context context;
1897 uint64_t imm64 = imm32; // Need to expand it to 64 bits before attempting
1898 // to negate it, or the wrong
1899 // value gets passed down to context.SetImmediateSigned.
1900 context.type = EmulateInstruction::eContextAdjustStackPointer;
1901 context.SetImmediateSigned(-imm64); // the stack pointer offset
1903 context.type = EmulateInstruction::eContextImmediate;
1904 context.SetNoArgs();
1907 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags,
1908 res.carry_out, res.overflow))
1914 // A store operation to the stack that also updates the SP.
1915 bool EmulateInstructionARM::EmulateSTRRtSP(const uint32_t opcode,
1916 const ARMEncoding encoding) {
1918 // ARM pseudo code...
1919 if (ConditionPassed())
1921 EncodingSpecificOperations();
1922 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
1923 address = if index then offset_addr else R[n];
1924 MemU[address,4] = if t == 15 then PCStoreValue() else R[t];
1925 if wback then R[n] = offset_addr;
1929 bool success = false;
1930 if (ConditionPassed(opcode)) {
1931 const uint32_t addr_byte_size = GetAddressByteSize();
1932 const addr_t sp = ReadCoreReg(SP_REG, &success);
1935 uint32_t Rt; // the source register
1938 Rn; // This function assumes Rn is the SP, but we should verify that.
1945 Rt = Bits32(opcode, 15, 12);
1946 imm12 = Bits32(opcode, 11, 0);
1947 Rn = Bits32(opcode, 19, 16);
1949 if (Rn != 13) // 13 is the SP reg on ARM. Verify that Rn == SP.
1952 index = BitIsSet(opcode, 24);
1953 add = BitIsSet(opcode, 23);
1954 wback = (BitIsClear(opcode, 24) || BitIsSet(opcode, 21));
1956 if (wback && ((Rn == 15) || (Rn == Rt)))
1964 offset_addr = sp + imm12;
1966 offset_addr = sp - imm12;
1974 EmulateInstruction::Context context;
1975 context.type = EmulateInstruction::eContextPushRegisterOnStack;
1976 RegisterInfo sp_reg;
1977 RegisterInfo dwarf_reg;
1979 GetRegisterInfo(eRegisterKindDWARF, dwarf_sp, sp_reg);
1980 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + Rt, dwarf_reg);
1981 context.SetRegisterToRegisterPlusOffset(dwarf_reg, sp_reg, addr - sp);
1983 uint32_t reg_value = ReadCoreReg(Rt, &success);
1986 if (!MemUWrite(context, addr, reg_value, addr_byte_size))
1989 const uint32_t pc = ReadCoreReg(PC_REG, &success);
1992 if (!MemUWrite(context, addr, pc, addr_byte_size))
1997 context.type = EmulateInstruction::eContextAdjustStackPointer;
1998 context.SetImmediateSigned(addr - sp);
1999 if (!WriteRegisterUnsigned(context, eRegisterKindGeneric,
2000 LLDB_REGNUM_GENERIC_SP, offset_addr))
2007 // Vector Push stores multiple extension registers to the stack.
2008 // It also updates SP to point to the start of the stored data.
2009 bool EmulateInstructionARM::EmulateVPUSH(const uint32_t opcode,
2010 const ARMEncoding encoding) {
2012 // ARM pseudo code...
2013 if (ConditionPassed())
2015 EncodingSpecificOperations(); CheckVFPEnabled(TRUE); NullCheckIfThumbEE(13);
2016 address = SP - imm32;
2020 MemA[address,4] = S[d+r]; address = address+4;
2023 // Store as two word-aligned words in the correct order for current endianness.
2024 MemA[address,4] = if BigEndian() then D[d+r]<63:32> else D[d+r]<31:0>;
2025 MemA[address+4,4] = if BigEndian() then D[d+r]<31:0> else D[d+r]<63:32>;
2026 address = address+8;
2030 bool success = false;
2031 if (ConditionPassed(opcode)) {
2032 const uint32_t addr_byte_size = GetAddressByteSize();
2033 const addr_t sp = ReadCoreReg(SP_REG, &success);
2037 uint32_t d; // UInt(D:Vd) or UInt(Vd:D) starting register
2038 uint32_t imm32; // stack offset
2039 uint32_t regs; // number of registers
2043 single_regs = false;
2044 d = Bit32(opcode, 22) << 4 | Bits32(opcode, 15, 12);
2045 imm32 = Bits32(opcode, 7, 0) * addr_byte_size;
2046 // If UInt(imm8) is odd, see "FSTMX".
2047 regs = Bits32(opcode, 7, 0) / 2;
2048 // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE;
2049 if (regs == 0 || regs > 16 || (d + regs) > 32)
2055 d = Bits32(opcode, 15, 12) << 1 | Bit32(opcode, 22);
2056 imm32 = Bits32(opcode, 7, 0) * addr_byte_size;
2057 regs = Bits32(opcode, 7, 0);
2058 // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE;
2059 if (regs == 0 || regs > 16 || (d + regs) > 32)
2065 uint32_t start_reg = single_regs ? dwarf_s0 : dwarf_d0;
2066 uint32_t reg_byte_size = single_regs ? addr_byte_size : addr_byte_size * 2;
2067 addr_t sp_offset = imm32;
2068 addr_t addr = sp - sp_offset;
2071 EmulateInstruction::Context context;
2072 context.type = EmulateInstruction::eContextPushRegisterOnStack;
2074 RegisterInfo dwarf_reg;
2075 RegisterInfo sp_reg;
2076 GetRegisterInfo(eRegisterKindDWARF, dwarf_sp, sp_reg);
2077 for (i = 0; i < regs; ++i) {
2078 GetRegisterInfo(eRegisterKindDWARF, start_reg + d + i, dwarf_reg);
2079 context.SetRegisterToRegisterPlusOffset(dwarf_reg, sp_reg, addr - sp);
2080 // uint64_t to accommodate 64-bit registers.
2081 uint64_t reg_value = ReadRegisterUnsigned(&dwarf_reg, 0, &success);
2084 if (!MemAWrite(context, addr, reg_value, reg_byte_size))
2086 addr += reg_byte_size;
2089 context.type = EmulateInstruction::eContextAdjustStackPointer;
2090 context.SetImmediateSigned(-sp_offset);
2092 if (!WriteRegisterUnsigned(context, eRegisterKindGeneric,
2093 LLDB_REGNUM_GENERIC_SP, sp - sp_offset))
2099 // Vector Pop loads multiple extension registers from the stack.
2100 // It also updates SP to point just above the loaded data.
2101 bool EmulateInstructionARM::EmulateVPOP(const uint32_t opcode,
2102 const ARMEncoding encoding) {
2104 // ARM pseudo code...
2105 if (ConditionPassed())
2107 EncodingSpecificOperations(); CheckVFPEnabled(TRUE); NullCheckIfThumbEE(13);
2112 S[d+r] = MemA[address,4]; address = address+4;
2115 word1 = MemA[address,4]; word2 = MemA[address+4,4]; address = address+8;
2116 // Combine the word-aligned words in the correct order for current endianness.
2117 D[d+r] = if BigEndian() then word1:word2 else word2:word1;
2121 bool success = false;
2122 if (ConditionPassed(opcode)) {
2123 const uint32_t addr_byte_size = GetAddressByteSize();
2124 const addr_t sp = ReadCoreReg(SP_REG, &success);
2128 uint32_t d; // UInt(D:Vd) or UInt(Vd:D) starting register
2129 uint32_t imm32; // stack offset
2130 uint32_t regs; // number of registers
2134 single_regs = false;
2135 d = Bit32(opcode, 22) << 4 | Bits32(opcode, 15, 12);
2136 imm32 = Bits32(opcode, 7, 0) * addr_byte_size;
2137 // If UInt(imm8) is odd, see "FLDMX".
2138 regs = Bits32(opcode, 7, 0) / 2;
2139 // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE;
2140 if (regs == 0 || regs > 16 || (d + regs) > 32)
2146 d = Bits32(opcode, 15, 12) << 1 | Bit32(opcode, 22);
2147 imm32 = Bits32(opcode, 7, 0) * addr_byte_size;
2148 regs = Bits32(opcode, 7, 0);
2149 // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE;
2150 if (regs == 0 || regs > 16 || (d + regs) > 32)
2156 uint32_t start_reg = single_regs ? dwarf_s0 : dwarf_d0;
2157 uint32_t reg_byte_size = single_regs ? addr_byte_size : addr_byte_size * 2;
2158 addr_t sp_offset = imm32;
2161 uint64_t data; // uint64_t to accommodate 64-bit registers.
2163 EmulateInstruction::Context context;
2164 context.type = EmulateInstruction::eContextPopRegisterOffStack;
2166 RegisterInfo dwarf_reg;
2167 RegisterInfo sp_reg;
2168 GetRegisterInfo(eRegisterKindDWARF, dwarf_sp, sp_reg);
2169 for (i = 0; i < regs; ++i) {
2170 GetRegisterInfo(eRegisterKindDWARF, start_reg + d + i, dwarf_reg);
2171 context.SetAddress(addr);
2172 data = MemARead(context, addr, reg_byte_size, 0, &success);
2175 if (!WriteRegisterUnsigned(context, &dwarf_reg, data))
2177 addr += reg_byte_size;
2180 context.type = EmulateInstruction::eContextAdjustStackPointer;
2181 context.SetImmediateSigned(sp_offset);
2183 if (!WriteRegisterUnsigned(context, eRegisterKindGeneric,
2184 LLDB_REGNUM_GENERIC_SP, sp + sp_offset))
2190 // SVC (previously SWI)
2191 bool EmulateInstructionARM::EmulateSVC(const uint32_t opcode,
2192 const ARMEncoding encoding) {
2194 // ARM pseudo code...
2195 if (ConditionPassed())
2197 EncodingSpecificOperations();
2202 bool success = false;
2204 if (ConditionPassed(opcode)) {
2205 const uint32_t pc = ReadCoreReg(PC_REG, &success);
2206 addr_t lr; // next instruction address
2209 uint32_t imm32; // the immediate constant
2210 uint32_t mode; // ARM or Thumb mode
2213 lr = (pc + 2) | 1u; // return address
2214 imm32 = Bits32(opcode, 7, 0);
2218 lr = pc + 4; // return address
2219 imm32 = Bits32(opcode, 23, 0);
2226 EmulateInstruction::Context context;
2227 context.type = EmulateInstruction::eContextSupervisorCall;
2228 context.SetISAAndImmediate(mode, imm32);
2229 if (!WriteRegisterUnsigned(context, eRegisterKindGeneric,
2230 LLDB_REGNUM_GENERIC_RA, lr))
2236 // If Then makes up to four following instructions (the IT block) conditional.
2237 bool EmulateInstructionARM::EmulateIT(const uint32_t opcode,
2238 const ARMEncoding encoding) {
2240 // ARM pseudo code...
2241 EncodingSpecificOperations();
2242 ITSTATE.IT<7:0> = firstcond:mask;
2245 m_it_session.InitIT(Bits32(opcode, 7, 0));
2249 bool EmulateInstructionARM::EmulateNop(const uint32_t opcode,
2250 const ARMEncoding encoding) {
2251 // NOP, nothing to do...
2255 // Branch causes a branch to a target address.
2256 bool EmulateInstructionARM::EmulateB(const uint32_t opcode,
2257 const ARMEncoding encoding) {
2259 // ARM pseudo code...
2260 if (ConditionPassed())
2262 EncodingSpecificOperations();
2263 BranchWritePC(PC + imm32);
2267 bool success = false;
2269 if (ConditionPassed(opcode)) {
2270 EmulateInstruction::Context context;
2271 context.type = EmulateInstruction::eContextRelativeBranchImmediate;
2272 const uint32_t pc = ReadCoreReg(PC_REG, &success);
2275 addr_t target; // target address
2276 int32_t imm32; // PC-relative offset
2279 // The 'cond' field is handled in EmulateInstructionARM::CurrentCond().
2280 imm32 = llvm::SignExtend32<9>(Bits32(opcode, 7, 0) << 1);
2281 target = pc + imm32;
2282 context.SetISAAndImmediateSigned(eModeThumb, 4 + imm32);
2285 imm32 = llvm::SignExtend32<12>(Bits32(opcode, 10, 0) << 1);
2286 target = pc + imm32;
2287 context.SetISAAndImmediateSigned(eModeThumb, 4 + imm32);
2290 // The 'cond' field is handled in EmulateInstructionARM::CurrentCond().
2292 if (Bits32(opcode, 25, 23) == 7)
2293 return false; // See Branches and miscellaneous control on page
2296 uint32_t S = Bit32(opcode, 26);
2297 uint32_t imm6 = Bits32(opcode, 21, 16);
2298 uint32_t J1 = Bit32(opcode, 13);
2299 uint32_t J2 = Bit32(opcode, 11);
2300 uint32_t imm11 = Bits32(opcode, 10, 0);
2302 (S << 20) | (J2 << 19) | (J1 << 18) | (imm6 << 12) | (imm11 << 1);
2303 imm32 = llvm::SignExtend32<21>(imm21);
2304 target = pc + imm32;
2305 context.SetISAAndImmediateSigned(eModeThumb, 4 + imm32);
2309 uint32_t S = Bit32(opcode, 26);
2310 uint32_t imm10 = Bits32(opcode, 25, 16);
2311 uint32_t J1 = Bit32(opcode, 13);
2312 uint32_t J2 = Bit32(opcode, 11);
2313 uint32_t imm11 = Bits32(opcode, 10, 0);
2314 uint32_t I1 = !(J1 ^ S);
2315 uint32_t I2 = !(J2 ^ S);
2317 (S << 24) | (I1 << 23) | (I2 << 22) | (imm10 << 12) | (imm11 << 1);
2318 imm32 = llvm::SignExtend32<25>(imm25);
2319 target = pc + imm32;
2320 context.SetISAAndImmediateSigned(eModeThumb, 4 + imm32);
2324 imm32 = llvm::SignExtend32<26>(Bits32(opcode, 23, 0) << 2);
2325 target = pc + imm32;
2326 context.SetISAAndImmediateSigned(eModeARM, 8 + imm32);
2331 if (!BranchWritePC(context, target))
2337 // Compare and Branch on Nonzero and Compare and Branch on Zero compare the
2338 // value in a register with
2339 // zero and conditionally branch forward a constant value. They do not affect
2340 // the condition flags.
2342 bool EmulateInstructionARM::EmulateCB(const uint32_t opcode,
2343 const ARMEncoding encoding) {
2345 // ARM pseudo code...
2346 EncodingSpecificOperations();
2347 if nonzero ^ IsZero(R[n]) then
2348 BranchWritePC(PC + imm32);
2351 bool success = false;
2353 // Read the register value from the operand register Rn.
2354 uint32_t reg_val = ReadCoreReg(Bits32(opcode, 2, 0), &success);
2358 EmulateInstruction::Context context;
2359 context.type = EmulateInstruction::eContextRelativeBranchImmediate;
2360 const uint32_t pc = ReadCoreReg(PC_REG, &success);
2364 addr_t target; // target address
2365 uint32_t imm32; // PC-relative offset to branch forward
2369 imm32 = Bit32(opcode, 9) << 6 | Bits32(opcode, 7, 3) << 1;
2370 nonzero = BitIsSet(opcode, 11);
2371 target = pc + imm32;
2372 context.SetISAAndImmediateSigned(eModeThumb, 4 + imm32);
2377 if (m_ignore_conditions || (nonzero ^ (reg_val == 0)))
2378 if (!BranchWritePC(context, target))
2384 // Table Branch Byte causes a PC-relative forward branch using a table of single
2386 // A base register provides a pointer to the table, and a second register
2387 // supplies an index into the table.
2388 // The branch length is twice the value of the byte returned from the table.
2390 // Table Branch Halfword causes a PC-relative forward branch using a table of
2391 // single halfword offsets.
2392 // A base register provides a pointer to the table, and a second register
2393 // supplies an index into the table.
2394 // The branch length is twice the value of the halfword returned from the table.
2396 bool EmulateInstructionARM::EmulateTB(const uint32_t opcode,
2397 const ARMEncoding encoding) {
2399 // ARM pseudo code...
2400 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
2402 halfwords = UInt(MemU[R[n]+LSL(R[m],1), 2]);
2404 halfwords = UInt(MemU[R[n]+R[m], 1]);
2405 BranchWritePC(PC + 2*halfwords);
2408 bool success = false;
2410 if (ConditionPassed(opcode)) {
2411 uint32_t Rn; // the base register which contains the address of the table of
2413 uint32_t Rm; // the index register which contains an integer pointing to a
2414 // byte/halfword in the table
2415 bool is_tbh; // true if table branch halfword
2418 Rn = Bits32(opcode, 19, 16);
2419 Rm = Bits32(opcode, 3, 0);
2420 is_tbh = BitIsSet(opcode, 4);
2421 if (Rn == 13 || BadReg(Rm))
2423 if (InITBlock() && !LastInITBlock())
2430 // Read the address of the table from the operand register Rn.
2431 // The PC can be used, in which case the table immediately follows this
2433 uint32_t base = ReadCoreReg(Rn, &success);
2438 uint32_t index = ReadCoreReg(Rm, &success);
2442 // the offsetted table address
2443 addr_t addr = base + (is_tbh ? index * 2 : index);
2445 // PC-relative offset to branch forward
2446 EmulateInstruction::Context context;
2447 context.type = EmulateInstruction::eContextTableBranchReadMemory;
2448 uint32_t offset = MemURead(context, addr, is_tbh ? 2 : 1, 0, &success) * 2;
2452 const uint32_t pc = ReadCoreReg(PC_REG, &success);
2457 addr_t target = pc + offset;
2458 context.type = EmulateInstruction::eContextRelativeBranchImmediate;
2459 context.SetISAAndImmediateSigned(eModeThumb, 4 + offset);
2461 if (!BranchWritePC(context, target))
2468 // This instruction adds an immediate value to a register value, and writes the
2469 // result to the destination register.
2470 // It can optionally update the condition flags based on the result.
2471 bool EmulateInstructionARM::EmulateADDImmThumb(const uint32_t opcode,
2472 const ARMEncoding encoding) {
2474 if ConditionPassed() then
2475 EncodingSpecificOperations();
2476 (result, carry, overflow) = AddWithCarry(R[n], imm32, '0');
2479 APSR.N = result<31>;
2480 APSR.Z = IsZeroBit(result);
2485 bool success = false;
2487 if (ConditionPassed(opcode)) {
2494 // EncodingSpecificOperations();
2497 // d = UInt(Rd); n = UInt(Rn); setflags = !InITBlock(); imm32 =
2498 // ZeroExtend(imm3, 32);
2499 d = Bits32(opcode, 2, 0);
2500 n = Bits32(opcode, 5, 3);
2501 setflags = !InITBlock();
2502 imm32 = Bits32(opcode, 8, 6);
2507 // d = UInt(Rdn); n = UInt(Rdn); setflags = !InITBlock(); imm32 =
2508 // ZeroExtend(imm8, 32);
2509 d = Bits32(opcode, 10, 8);
2510 n = Bits32(opcode, 10, 8);
2511 setflags = !InITBlock();
2512 imm32 = Bits32(opcode, 7, 0);
2517 // if Rd == '1111' && S == '1' then SEE CMN (immediate);
2518 // d = UInt(Rd); n = UInt(Rn); setflags = (S == '1'); imm32 =
2519 // ThumbExpandImm(i:imm3:imm8);
2520 d = Bits32(opcode, 11, 8);
2521 n = Bits32(opcode, 19, 16);
2522 setflags = BitIsSet(opcode, 20);
2523 imm32 = ThumbExpandImm_C(opcode, APSR_C, carry_out);
2525 // if Rn == '1101' then SEE ADD (SP plus immediate);
2527 return EmulateADDSPImm(opcode, eEncodingT3);
2529 // if BadReg(d) || n == 15 then UNPREDICTABLE;
2530 if (BadReg(d) || (n == 15))
2536 // if Rn == '1111' then SEE ADR;
2537 // d = UInt(Rd); n = UInt(Rn); setflags = FALSE; imm32 =
2538 // ZeroExtend(i:imm3:imm8, 32);
2539 d = Bits32(opcode, 11, 8);
2540 n = Bits32(opcode, 19, 16);
2542 uint32_t i = Bit32(opcode, 26);
2543 uint32_t imm3 = Bits32(opcode, 14, 12);
2544 uint32_t imm8 = Bits32(opcode, 7, 0);
2545 imm32 = (i << 11) | (imm3 << 8) | imm8;
2547 // if Rn == '1101' then SEE ADD (SP plus immediate);
2549 return EmulateADDSPImm(opcode, eEncodingT4);
2551 // if BadReg(d) then UNPREDICTABLE;
2563 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
2567 //(result, carry, overflow) = AddWithCarry(R[n], imm32, '0');
2568 AddWithCarryResult res = AddWithCarry(Rn, imm32, 0);
2571 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n, reg_n);
2573 EmulateInstruction::Context context;
2574 context.type = eContextArithmetic;
2575 context.SetRegisterPlusOffset(reg_n, imm32);
2579 // APSR.N = result<31>;
2580 // APSR.Z = IsZeroBit(result);
2582 // APSR.V = overflow;
2583 if (!WriteCoreRegOptionalFlags(context, res.result, d, setflags,
2584 res.carry_out, res.overflow))
2590 // This instruction adds an immediate value to a register value, and writes the
2591 // result to the destination
2592 // register. It can optionally update the condition flags based on the result.
2593 bool EmulateInstructionARM::EmulateADDImmARM(const uint32_t opcode,
2594 const ARMEncoding encoding) {
2596 // ARM pseudo code...
2597 if ConditionPassed() then
2598 EncodingSpecificOperations();
2599 (result, carry, overflow) = AddWithCarry(R[n], imm32, '0');
2601 ALUWritePC(result); // setflags is always FALSE here
2605 APSR.N = result<31>;
2606 APSR.Z = IsZeroBit(result);
2611 bool success = false;
2613 if (ConditionPassed(opcode)) {
2616 imm32; // the immediate value to be added to the value obtained from Rn
2620 Rd = Bits32(opcode, 15, 12);
2621 Rn = Bits32(opcode, 19, 16);
2622 setflags = BitIsSet(opcode, 20);
2623 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
2629 // Read the first operand.
2630 uint32_t val1 = ReadCoreReg(Rn, &success);
2634 AddWithCarryResult res = AddWithCarry(val1, imm32, 0);
2636 EmulateInstruction::Context context;
2638 context.type = EmulateInstruction::eContextAdjustStackPointer;
2639 else if (Rd == GetFramePointerRegisterNumber())
2640 context.type = EmulateInstruction::eContextSetFramePointer;
2642 context.type = EmulateInstruction::eContextRegisterPlusOffset;
2644 RegisterInfo dwarf_reg;
2645 GetRegisterInfo(eRegisterKindDWARF, Rn, dwarf_reg);
2646 context.SetRegisterPlusOffset(dwarf_reg, imm32);
2648 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags,
2649 res.carry_out, res.overflow))
2655 // This instruction adds a register value and an optionally-shifted register
2656 // value, and writes the result
2657 // to the destination register. It can optionally update the condition flags
2658 // based on the result.
2659 bool EmulateInstructionARM::EmulateADDReg(const uint32_t opcode,
2660 const ARMEncoding encoding) {
2662 // ARM pseudo code...
2663 if ConditionPassed() then
2664 EncodingSpecificOperations();
2665 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
2666 (result, carry, overflow) = AddWithCarry(R[n], shifted, '0');
2668 ALUWritePC(result); // setflags is always FALSE here
2672 APSR.N = result<31>;
2673 APSR.Z = IsZeroBit(result);
2678 bool success = false;
2680 if (ConditionPassed(opcode)) {
2681 uint32_t Rd, Rn, Rm;
2682 ARM_ShifterType shift_t;
2683 uint32_t shift_n; // the shift applied to the value read from Rm
2687 Rd = Bits32(opcode, 2, 0);
2688 Rn = Bits32(opcode, 5, 3);
2689 Rm = Bits32(opcode, 8, 6);
2690 setflags = !InITBlock();
2691 shift_t = SRType_LSL;
2695 Rd = Rn = Bit32(opcode, 7) << 3 | Bits32(opcode, 2, 0);
2696 Rm = Bits32(opcode, 6, 3);
2698 shift_t = SRType_LSL;
2700 if (Rn == 15 && Rm == 15)
2702 if (Rd == 15 && InITBlock() && !LastInITBlock())
2706 Rd = Bits32(opcode, 15, 12);
2707 Rn = Bits32(opcode, 19, 16);
2708 Rm = Bits32(opcode, 3, 0);
2709 setflags = BitIsSet(opcode, 20);
2710 shift_n = DecodeImmShiftARM(opcode, shift_t);
2716 // Read the first operand.
2717 uint32_t val1 = ReadCoreReg(Rn, &success);
2721 // Read the second operand.
2722 uint32_t val2 = ReadCoreReg(Rm, &success);
2726 uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C, &success);
2729 AddWithCarryResult res = AddWithCarry(val1, shifted, 0);
2731 EmulateInstruction::Context context;
2732 context.type = eContextArithmetic;
2733 RegisterInfo op1_reg;
2734 RegisterInfo op2_reg;
2735 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + Rn, op1_reg);
2736 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + Rm, op2_reg);
2737 context.SetRegisterRegisterOperands(op1_reg, op2_reg);
2739 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags,
2740 res.carry_out, res.overflow))
2746 // Compare Negative (immediate) adds a register value and an immediate value.
2747 // It updates the condition flags based on the result, and discards the result.
2748 bool EmulateInstructionARM::EmulateCMNImm(const uint32_t opcode,
2749 const ARMEncoding encoding) {
2751 // ARM pseudo code...
2752 if ConditionPassed() then
2753 EncodingSpecificOperations();
2754 (result, carry, overflow) = AddWithCarry(R[n], imm32, '0');
2755 APSR.N = result<31>;
2756 APSR.Z = IsZeroBit(result);
2761 bool success = false;
2763 uint32_t Rn; // the first operand
2764 uint32_t imm32; // the immediate value to be compared with
2767 Rn = Bits32(opcode, 19, 16);
2768 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8)
2773 Rn = Bits32(opcode, 19, 16);
2774 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
2779 // Read the register value from the operand register Rn.
2780 uint32_t reg_val = ReadCoreReg(Rn, &success);
2784 AddWithCarryResult res = AddWithCarry(reg_val, imm32, 0);
2786 EmulateInstruction::Context context;
2787 context.type = EmulateInstruction::eContextImmediate;
2788 context.SetNoArgs();
2789 if (!WriteFlags(context, res.result, res.carry_out, res.overflow))
2795 // Compare Negative (register) adds a register value and an optionally-shifted
2797 // It updates the condition flags based on the result, and discards the result.
2798 bool EmulateInstructionARM::EmulateCMNReg(const uint32_t opcode,
2799 const ARMEncoding encoding) {
2801 // ARM pseudo code...
2802 if ConditionPassed() then
2803 EncodingSpecificOperations();
2804 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
2805 (result, carry, overflow) = AddWithCarry(R[n], shifted, '0');
2806 APSR.N = result<31>;
2807 APSR.Z = IsZeroBit(result);
2812 bool success = false;
2814 uint32_t Rn; // the first operand
2815 uint32_t Rm; // the second operand
2816 ARM_ShifterType shift_t;
2817 uint32_t shift_n; // the shift applied to the value read from Rm
2820 Rn = Bits32(opcode, 2, 0);
2821 Rm = Bits32(opcode, 5, 3);
2822 shift_t = SRType_LSL;
2826 Rn = Bits32(opcode, 19, 16);
2827 Rm = Bits32(opcode, 3, 0);
2828 shift_n = DecodeImmShiftThumb(opcode, shift_t);
2829 // if n == 15 || BadReg(m) then UNPREDICTABLE;
2830 if (Rn == 15 || BadReg(Rm))
2834 Rn = Bits32(opcode, 19, 16);
2835 Rm = Bits32(opcode, 3, 0);
2836 shift_n = DecodeImmShiftARM(opcode, shift_t);
2841 // Read the register value from register Rn.
2842 uint32_t val1 = ReadCoreReg(Rn, &success);
2846 // Read the register value from register Rm.
2847 uint32_t val2 = ReadCoreReg(Rm, &success);
2851 uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C, &success);
2854 AddWithCarryResult res = AddWithCarry(val1, shifted, 0);
2856 EmulateInstruction::Context context;
2857 context.type = EmulateInstruction::eContextImmediate;
2858 context.SetNoArgs();
2859 if (!WriteFlags(context, res.result, res.carry_out, res.overflow))
2865 // Compare (immediate) subtracts an immediate value from a register value.
2866 // It updates the condition flags based on the result, and discards the result.
2867 bool EmulateInstructionARM::EmulateCMPImm(const uint32_t opcode,
2868 const ARMEncoding encoding) {
2870 // ARM pseudo code...
2871 if ConditionPassed() then
2872 EncodingSpecificOperations();
2873 (result, carry, overflow) = AddWithCarry(R[n], NOT(imm32), '1');
2874 APSR.N = result<31>;
2875 APSR.Z = IsZeroBit(result);
2880 bool success = false;
2882 uint32_t Rn; // the first operand
2883 uint32_t imm32; // the immediate value to be compared with
2886 Rn = Bits32(opcode, 10, 8);
2887 imm32 = Bits32(opcode, 7, 0);
2890 Rn = Bits32(opcode, 19, 16);
2891 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8)
2896 Rn = Bits32(opcode, 19, 16);
2897 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
2902 // Read the register value from the operand register Rn.
2903 uint32_t reg_val = ReadCoreReg(Rn, &success);
2907 AddWithCarryResult res = AddWithCarry(reg_val, ~imm32, 1);
2909 EmulateInstruction::Context context;
2910 context.type = EmulateInstruction::eContextImmediate;
2911 context.SetNoArgs();
2912 if (!WriteFlags(context, res.result, res.carry_out, res.overflow))
2918 // Compare (register) subtracts an optionally-shifted register value from a
2920 // It updates the condition flags based on the result, and discards the result.
2921 bool EmulateInstructionARM::EmulateCMPReg(const uint32_t opcode,
2922 const ARMEncoding encoding) {
2924 // ARM pseudo code...
2925 if ConditionPassed() then
2926 EncodingSpecificOperations();
2927 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
2928 (result, carry, overflow) = AddWithCarry(R[n], NOT(shifted), '1');
2929 APSR.N = result<31>;
2930 APSR.Z = IsZeroBit(result);
2935 bool success = false;
2937 uint32_t Rn; // the first operand
2938 uint32_t Rm; // the second operand
2939 ARM_ShifterType shift_t;
2940 uint32_t shift_n; // the shift applied to the value read from Rm
2943 Rn = Bits32(opcode, 2, 0);
2944 Rm = Bits32(opcode, 5, 3);
2945 shift_t = SRType_LSL;
2949 Rn = Bit32(opcode, 7) << 3 | Bits32(opcode, 2, 0);
2950 Rm = Bits32(opcode, 6, 3);
2951 shift_t = SRType_LSL;
2953 if (Rn < 8 && Rm < 8)
2955 if (Rn == 15 || Rm == 15)
2959 Rn = Bits32(opcode, 19, 16);
2960 Rm = Bits32(opcode, 3, 0);
2961 shift_n = DecodeImmShiftThumb(opcode, shift_t);
2962 if (Rn == 15 || BadReg(Rm))
2966 Rn = Bits32(opcode, 19, 16);
2967 Rm = Bits32(opcode, 3, 0);
2968 shift_n = DecodeImmShiftARM(opcode, shift_t);
2973 // Read the register value from register Rn.
2974 uint32_t val1 = ReadCoreReg(Rn, &success);
2978 // Read the register value from register Rm.
2979 uint32_t val2 = ReadCoreReg(Rm, &success);
2983 uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C, &success);
2986 AddWithCarryResult res = AddWithCarry(val1, ~shifted, 1);
2988 EmulateInstruction::Context context;
2989 context.type = EmulateInstruction::eContextImmediate;
2990 context.SetNoArgs();
2991 if (!WriteFlags(context, res.result, res.carry_out, res.overflow))
2997 // Arithmetic Shift Right (immediate) shifts a register value right by an
2998 // immediate number of bits,
2999 // shifting in copies of its sign bit, and writes the result to the destination
3001 // optionally update the condition flags based on the result.
3002 bool EmulateInstructionARM::EmulateASRImm(const uint32_t opcode,
3003 const ARMEncoding encoding) {
3005 // ARM pseudo code...
3006 if ConditionPassed() then
3007 EncodingSpecificOperations();
3008 (result, carry) = Shift_C(R[m], SRType_ASR, shift_n, APSR.C);
3009 if d == 15 then // Can only occur for ARM encoding
3010 ALUWritePC(result); // setflags is always FALSE here
3014 APSR.N = result<31>;
3015 APSR.Z = IsZeroBit(result);
3020 return EmulateShiftImm(opcode, encoding, SRType_ASR);
3023 // Arithmetic Shift Right (register) shifts a register value right by a variable
3025 // shifting in copies of its sign bit, and writes the result to the destination
3027 // The variable number of bits is read from the bottom byte of a register. It
3028 // can optionally update
3029 // the condition flags based on the result.
3030 bool EmulateInstructionARM::EmulateASRReg(const uint32_t opcode,
3031 const ARMEncoding encoding) {
3033 // ARM pseudo code...
3034 if ConditionPassed() then
3035 EncodingSpecificOperations();
3036 shift_n = UInt(R[m]<7:0>);
3037 (result, carry) = Shift_C(R[m], SRType_ASR, shift_n, APSR.C);
3040 APSR.N = result<31>;
3041 APSR.Z = IsZeroBit(result);
3046 return EmulateShiftReg(opcode, encoding, SRType_ASR);
3049 // Logical Shift Left (immediate) shifts a register value left by an immediate
3051 // shifting in zeros, and writes the result to the destination register. It can
3053 // update the condition flags based on the result.
3054 bool EmulateInstructionARM::EmulateLSLImm(const uint32_t opcode,
3055 const ARMEncoding encoding) {
3057 // ARM pseudo code...
3058 if ConditionPassed() then
3059 EncodingSpecificOperations();
3060 (result, carry) = Shift_C(R[m], SRType_LSL, shift_n, APSR.C);
3061 if d == 15 then // Can only occur for ARM encoding
3062 ALUWritePC(result); // setflags is always FALSE here
3066 APSR.N = result<31>;
3067 APSR.Z = IsZeroBit(result);
3072 return EmulateShiftImm(opcode, encoding, SRType_LSL);
3075 // Logical Shift Left (register) shifts a register value left by a variable
3077 // shifting in zeros, and writes the result to the destination register. The
3079 // of bits is read from the bottom byte of a register. It can optionally update
3081 // flags based on the result.
3082 bool EmulateInstructionARM::EmulateLSLReg(const uint32_t opcode,
3083 const ARMEncoding encoding) {
3085 // ARM pseudo code...
3086 if ConditionPassed() then
3087 EncodingSpecificOperations();
3088 shift_n = UInt(R[m]<7:0>);
3089 (result, carry) = Shift_C(R[m], SRType_LSL, shift_n, APSR.C);
3092 APSR.N = result<31>;
3093 APSR.Z = IsZeroBit(result);
3098 return EmulateShiftReg(opcode, encoding, SRType_LSL);
3101 // Logical Shift Right (immediate) shifts a register value right by an immediate
3103 // shifting in zeros, and writes the result to the destination register. It can
3105 // update the condition flags based on the result.
3106 bool EmulateInstructionARM::EmulateLSRImm(const uint32_t opcode,
3107 const ARMEncoding encoding) {
3109 // ARM pseudo code...
3110 if ConditionPassed() then
3111 EncodingSpecificOperations();
3112 (result, carry) = Shift_C(R[m], SRType_LSR, shift_n, APSR.C);
3113 if d == 15 then // Can only occur for ARM encoding
3114 ALUWritePC(result); // setflags is always FALSE here
3118 APSR.N = result<31>;
3119 APSR.Z = IsZeroBit(result);
3124 return EmulateShiftImm(opcode, encoding, SRType_LSR);
3127 // Logical Shift Right (register) shifts a register value right by a variable
3129 // shifting in zeros, and writes the result to the destination register. The
3131 // of bits is read from the bottom byte of a register. It can optionally update
3133 // flags based on the result.
3134 bool EmulateInstructionARM::EmulateLSRReg(const uint32_t opcode,
3135 const ARMEncoding encoding) {
3137 // ARM pseudo code...
3138 if ConditionPassed() then
3139 EncodingSpecificOperations();
3140 shift_n = UInt(R[m]<7:0>);
3141 (result, carry) = Shift_C(R[m], SRType_LSR, shift_n, APSR.C);
3144 APSR.N = result<31>;
3145 APSR.Z = IsZeroBit(result);
3150 return EmulateShiftReg(opcode, encoding, SRType_LSR);
3153 // Rotate Right (immediate) provides the value of the contents of a register
3154 // rotated by a constant value.
3155 // The bits that are rotated off the right end are inserted into the vacated bit
3156 // positions on the left.
3157 // It can optionally update the condition flags based on the result.
3158 bool EmulateInstructionARM::EmulateRORImm(const uint32_t opcode,
3159 const ARMEncoding encoding) {
3161 // ARM pseudo code...
3162 if ConditionPassed() then
3163 EncodingSpecificOperations();
3164 (result, carry) = Shift_C(R[m], SRType_ROR, shift_n, APSR.C);
3165 if d == 15 then // Can only occur for ARM encoding
3166 ALUWritePC(result); // setflags is always FALSE here
3170 APSR.N = result<31>;
3171 APSR.Z = IsZeroBit(result);
3176 return EmulateShiftImm(opcode, encoding, SRType_ROR);
3179 // Rotate Right (register) provides the value of the contents of a register
3180 // rotated by a variable number of bits.
3181 // The bits that are rotated off the right end are inserted into the vacated bit
3182 // positions on the left.
3183 // The variable number of bits is read from the bottom byte of a register. It
3184 // can optionally update the condition
3185 // flags based on the result.
3186 bool EmulateInstructionARM::EmulateRORReg(const uint32_t opcode,
3187 const ARMEncoding encoding) {
3189 // ARM pseudo code...
3190 if ConditionPassed() then
3191 EncodingSpecificOperations();
3192 shift_n = UInt(R[m]<7:0>);
3193 (result, carry) = Shift_C(R[m], SRType_ROR, shift_n, APSR.C);
3196 APSR.N = result<31>;
3197 APSR.Z = IsZeroBit(result);
3202 return EmulateShiftReg(opcode, encoding, SRType_ROR);
3205 // Rotate Right with Extend provides the value of the contents of a register
3206 // shifted right by one place,
3207 // with the carry flag shifted into bit [31].
3209 // RRX can optionally update the condition flags based on the result.
3210 // In that case, bit [0] is shifted into the carry flag.
3211 bool EmulateInstructionARM::EmulateRRX(const uint32_t opcode,
3212 const ARMEncoding encoding) {
3214 // ARM pseudo code...
3215 if ConditionPassed() then
3216 EncodingSpecificOperations();
3217 (result, carry) = Shift_C(R[m], SRType_RRX, 1, APSR.C);
3218 if d == 15 then // Can only occur for ARM encoding
3219 ALUWritePC(result); // setflags is always FALSE here
3223 APSR.N = result<31>;
3224 APSR.Z = IsZeroBit(result);
3229 return EmulateShiftImm(opcode, encoding, SRType_RRX);
3232 bool EmulateInstructionARM::EmulateShiftImm(const uint32_t opcode,
3233 const ARMEncoding encoding,
3234 ARM_ShifterType shift_type) {
3235 // assert(shift_type == SRType_ASR
3236 // || shift_type == SRType_LSL
3237 // || shift_type == SRType_LSR
3238 // || shift_type == SRType_ROR
3239 // || shift_type == SRType_RRX);
3241 bool success = false;
3243 if (ConditionPassed(opcode)) {
3244 uint32_t Rd; // the destination register
3245 uint32_t Rm; // the first operand register
3246 uint32_t imm5; // encoding for the shift amount
3247 uint32_t carry; // the carry bit after the shift operation
3250 // Special case handling!
3251 // A8.6.139 ROR (immediate) -- Encoding T1
3252 ARMEncoding use_encoding = encoding;
3253 if (shift_type == SRType_ROR && use_encoding == eEncodingT1) {
3254 // Morph the T1 encoding from the ARM Architecture Manual into T2 encoding
3256 // have the same decoding of bit fields as the other Thumb2 shift
3258 use_encoding = eEncodingT2;
3261 switch (use_encoding) {
3263 // Due to the above special case handling!
3264 if (shift_type == SRType_ROR)
3267 Rd = Bits32(opcode, 2, 0);
3268 Rm = Bits32(opcode, 5, 3);
3269 setflags = !InITBlock();
3270 imm5 = Bits32(opcode, 10, 6);
3274 // There's no imm form of RRX instructions.
3275 if (shift_type == SRType_RRX)
3278 Rd = Bits32(opcode, 11, 8);
3279 Rm = Bits32(opcode, 3, 0);
3280 setflags = BitIsSet(opcode, 20);
3281 imm5 = Bits32(opcode, 14, 12) << 2 | Bits32(opcode, 7, 6);
3282 if (BadReg(Rd) || BadReg(Rm))
3286 Rd = Bits32(opcode, 15, 12);
3287 Rm = Bits32(opcode, 3, 0);
3288 setflags = BitIsSet(opcode, 20);
3289 imm5 = Bits32(opcode, 11, 7);
3295 // A8.6.139 ROR (immediate)
3296 if (shift_type == SRType_ROR && imm5 == 0)
3297 shift_type = SRType_RRX;
3299 // Get the first operand.
3300 uint32_t value = ReadCoreReg(Rm, &success);
3304 // Decode the shift amount if not RRX.
3306 (shift_type == SRType_RRX ? 1 : DecodeImmShift(shift_type, imm5));
3308 uint32_t result = Shift_C(value, shift_type, amt, APSR_C, carry, &success);
3312 // The context specifies that an immediate is to be moved into Rd.
3313 EmulateInstruction::Context context;
3314 context.type = EmulateInstruction::eContextImmediate;
3315 context.SetNoArgs();
3317 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
3323 bool EmulateInstructionARM::EmulateShiftReg(const uint32_t opcode,
3324 const ARMEncoding encoding,
3325 ARM_ShifterType shift_type) {
3326 // assert(shift_type == SRType_ASR
3327 // || shift_type == SRType_LSL
3328 // || shift_type == SRType_LSR
3329 // || shift_type == SRType_ROR);
3331 bool success = false;
3333 if (ConditionPassed(opcode)) {
3334 uint32_t Rd; // the destination register
3335 uint32_t Rn; // the first operand register
3337 Rm; // the register whose bottom byte contains the amount to shift by
3338 uint32_t carry; // the carry bit after the shift operation
3342 Rd = Bits32(opcode, 2, 0);
3344 Rm = Bits32(opcode, 5, 3);
3345 setflags = !InITBlock();
3348 Rd = Bits32(opcode, 11, 8);
3349 Rn = Bits32(opcode, 19, 16);
3350 Rm = Bits32(opcode, 3, 0);
3351 setflags = BitIsSet(opcode, 20);
3352 if (BadReg(Rd) || BadReg(Rn) || BadReg(Rm))
3356 Rd = Bits32(opcode, 15, 12);
3357 Rn = Bits32(opcode, 3, 0);
3358 Rm = Bits32(opcode, 11, 8);
3359 setflags = BitIsSet(opcode, 20);
3360 if (Rd == 15 || Rn == 15 || Rm == 15)
3367 // Get the first operand.
3368 uint32_t value = ReadCoreReg(Rn, &success);
3371 // Get the Rm register content.
3372 uint32_t val = ReadCoreReg(Rm, &success);
3376 // Get the shift amount.
3377 uint32_t amt = Bits32(val, 7, 0);
3379 uint32_t result = Shift_C(value, shift_type, amt, APSR_C, carry, &success);
3383 // The context specifies that an immediate is to be moved into Rd.
3384 EmulateInstruction::Context context;
3385 context.type = EmulateInstruction::eContextImmediate;
3386 context.SetNoArgs();
3388 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
3394 // LDM loads multiple registers from consecutive memory locations, using an
3395 // address from a base register. Optionally the address just above the highest
3396 // of those locations
3397 // can be written back to the base register.
3398 bool EmulateInstructionARM::EmulateLDM(const uint32_t opcode,
3399 const ARMEncoding encoding) {
3401 // ARM pseudo code...
3402 if ConditionPassed()
3403 EncodingSpecificOperations(); NullCheckIfThumbEE (n);
3407 if registers<i> == '1' then
3408 R[i] = MemA[address, 4]; address = address + 4;
3409 if registers<15> == '1' then
3410 LoadWritePC (MemA[address, 4]);
3412 if wback && registers<n> == '0' then R[n] = R[n] + 4 * BitCount (registers);
3413 if wback && registers<n> == '1' then R[n] = bits(32) UNKNOWN; // Only possible for encoding A1
3417 bool success = false;
3418 if (ConditionPassed(opcode)) {
3420 uint32_t registers = 0;
3422 const uint32_t addr_byte_size = GetAddressByteSize();
3425 // n = UInt(Rn); registers = '00000000':register_list; wback =
3426 // (registers<n> == '0');
3427 n = Bits32(opcode, 10, 8);
3428 registers = Bits32(opcode, 7, 0);
3429 registers = registers & 0x00ff; // Make sure the top 8 bits are zeros.
3430 wback = BitIsClear(registers, n);
3431 // if BitCount(registers) < 1 then UNPREDICTABLE;
3432 if (BitCount(registers) < 1)
3436 // if W == '1' && Rn == '1101' then SEE POP;
3437 // n = UInt(Rn); registers = P:M:'0':register_list; wback = (W == '1');
3438 n = Bits32(opcode, 19, 16);
3439 registers = Bits32(opcode, 15, 0);
3440 registers = registers & 0xdfff; // Make sure bit 13 is zero.
3441 wback = BitIsSet(opcode, 21);
3443 // if n == 15 || BitCount(registers) < 2 || (P == '1' && M == '1') then
3445 if ((n == 15) || (BitCount(registers) < 2) ||
3446 (BitIsSet(opcode, 14) && BitIsSet(opcode, 15)))
3449 // if registers<15> == '1' && InITBlock() && !LastInITBlock() then
3451 if (BitIsSet(registers, 15) && InITBlock() && !LastInITBlock())
3454 // if wback && registers<n> == '1' then UNPREDICTABLE;
3455 if (wback && BitIsSet(registers, n))
3460 n = Bits32(opcode, 19, 16);
3461 registers = Bits32(opcode, 15, 0);
3462 wback = BitIsSet(opcode, 21);
3463 if ((n == 15) || (BitCount(registers) < 1))
3471 const addr_t base_address =
3472 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
3476 EmulateInstruction::Context context;
3477 context.type = EmulateInstruction::eContextRegisterPlusOffset;
3478 RegisterInfo dwarf_reg;
3479 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n, dwarf_reg);
3480 context.SetRegisterPlusOffset(dwarf_reg, offset);
3482 for (int i = 0; i < 14; ++i) {
3483 if (BitIsSet(registers, i)) {
3484 context.type = EmulateInstruction::eContextRegisterPlusOffset;
3485 context.SetRegisterPlusOffset(dwarf_reg, offset);
3486 if (wback && (n == 13)) // Pop Instruction
3488 context.type = EmulateInstruction::eContextPopRegisterOffStack;
3489 context.SetAddress(base_address + offset);
3492 // R[i] = MemA [address, 4]; address = address + 4;
3493 uint32_t data = MemARead(context, base_address + offset, addr_byte_size,
3498 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + i,
3502 offset += addr_byte_size;
3506 if (BitIsSet(registers, 15)) {
3507 // LoadWritePC (MemA [address, 4]);
3508 context.type = EmulateInstruction::eContextRegisterPlusOffset;
3509 context.SetRegisterPlusOffset(dwarf_reg, offset);
3511 MemARead(context, base_address + offset, addr_byte_size, 0, &success);
3514 // In ARMv5T and above, this is an interworking branch.
3515 if (!LoadWritePC(context, data))
3519 if (wback && BitIsClear(registers, n)) {
3520 // R[n] = R[n] + 4 * BitCount (registers)
3521 int32_t offset = addr_byte_size * BitCount(registers);
3522 context.type = EmulateInstruction::eContextAdjustBaseRegister;
3523 context.SetRegisterPlusOffset(dwarf_reg, offset);
3525 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n,
3526 base_address + offset))
3529 if (wback && BitIsSet(registers, n))
3530 // R[n] bits(32) UNKNOWN;
3531 return WriteBits32Unknown(n);
3536 // LDMDA loads multiple registers from consecutive memory locations using an
3537 // address from a base register.
3538 // The consecutive memory locations end at this address and the address just
3539 // below the lowest of those locations
3540 // can optionally be written back to the base register.
3541 bool EmulateInstructionARM::EmulateLDMDA(const uint32_t opcode,
3542 const ARMEncoding encoding) {
3544 // ARM pseudo code...
3545 if ConditionPassed() then
3546 EncodingSpecificOperations();
3547 address = R[n] - 4*BitCount(registers) + 4;
3550 if registers<i> == '1' then
3551 R[i] = MemA[address,4]; address = address + 4;
3553 if registers<15> == '1' then
3554 LoadWritePC(MemA[address,4]);
3556 if wback && registers<n> == '0' then R[n] = R[n] - 4*BitCount(registers);
3557 if wback && registers<n> == '1' then R[n] = bits(32) UNKNOWN;
3560 bool success = false;
3562 if (ConditionPassed(opcode)) {
3564 uint32_t registers = 0;
3566 const uint32_t addr_byte_size = GetAddressByteSize();
3568 // EncodingSpecificOperations();
3571 // n = UInt(Rn); registers = register_list; wback = (W == '1');
3572 n = Bits32(opcode, 19, 16);
3573 registers = Bits32(opcode, 15, 0);
3574 wback = BitIsSet(opcode, 21);
3576 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
3577 if ((n == 15) || (BitCount(registers) < 1))
3585 // address = R[n] - 4*BitCount(registers) + 4;
3588 addr_t Rn = ReadCoreReg(n, &success);
3594 Rn - (addr_byte_size * BitCount(registers)) + addr_byte_size;
3596 EmulateInstruction::Context context;
3597 context.type = EmulateInstruction::eContextRegisterPlusOffset;
3598 RegisterInfo dwarf_reg;
3599 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n, dwarf_reg);
3600 context.SetRegisterPlusOffset(dwarf_reg, offset);
3603 for (int i = 0; i < 14; ++i) {
3604 // if registers<i> == '1' then
3605 if (BitIsSet(registers, i)) {
3606 // R[i] = MemA[address,4]; address = address + 4;
3607 context.SetRegisterPlusOffset(dwarf_reg, Rn - (address + offset));
3609 MemARead(context, address + offset, addr_byte_size, 0, &success);
3612 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + i,
3615 offset += addr_byte_size;
3619 // if registers<15> == '1' then
3620 // LoadWritePC(MemA[address,4]);
3621 if (BitIsSet(registers, 15)) {
3622 context.SetRegisterPlusOffset(dwarf_reg, offset);
3624 MemARead(context, address + offset, addr_byte_size, 0, &success);
3627 // In ARMv5T and above, this is an interworking branch.
3628 if (!LoadWritePC(context, data))
3632 // if wback && registers<n> == '0' then R[n] = R[n] - 4*BitCount(registers);
3633 if (wback && BitIsClear(registers, n)) {
3637 offset = (addr_byte_size * BitCount(registers)) * -1;
3638 context.type = EmulateInstruction::eContextAdjustBaseRegister;
3639 context.SetImmediateSigned(offset);
3640 addr_t addr = Rn + offset;
3641 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n,
3646 // if wback && registers<n> == '1' then R[n] = bits(32) UNKNOWN;
3647 if (wback && BitIsSet(registers, n))
3648 return WriteBits32Unknown(n);
3653 // LDMDB loads multiple registers from consecutive memory locations using an
3654 // address from a base register. The
3655 // consecutive memory locations end just below this address, and the address of
3656 // the lowest of those locations can
3657 // be optionally written back to the base register.
3658 bool EmulateInstructionARM::EmulateLDMDB(const uint32_t opcode,
3659 const ARMEncoding encoding) {
3661 // ARM pseudo code...
3662 if ConditionPassed() then
3663 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
3664 address = R[n] - 4*BitCount(registers);
3667 if registers<i> == '1' then
3668 R[i] = MemA[address,4]; address = address + 4;
3669 if registers<15> == '1' then
3670 LoadWritePC(MemA[address,4]);
3672 if wback && registers<n> == '0' then R[n] = R[n] - 4*BitCount(registers);
3673 if wback && registers<n> == '1' then R[n] = bits(32) UNKNOWN; // Only possible for encoding A1
3676 bool success = false;
3678 if (ConditionPassed(opcode)) {
3680 uint32_t registers = 0;
3682 const uint32_t addr_byte_size = GetAddressByteSize();
3685 // n = UInt(Rn); registers = P:M:'0':register_list; wback = (W == '1');
3686 n = Bits32(opcode, 19, 16);
3687 registers = Bits32(opcode, 15, 0);
3688 registers = registers & 0xdfff; // Make sure bit 13 is a zero.
3689 wback = BitIsSet(opcode, 21);
3691 // if n == 15 || BitCount(registers) < 2 || (P == '1' && M == '1') then
3693 if ((n == 15) || (BitCount(registers) < 2) ||
3694 (BitIsSet(opcode, 14) && BitIsSet(opcode, 15)))
3697 // if registers<15> == '1' && InITBlock() && !LastInITBlock() then
3699 if (BitIsSet(registers, 15) && InITBlock() && !LastInITBlock())
3702 // if wback && registers<n> == '1' then UNPREDICTABLE;
3703 if (wback && BitIsSet(registers, n))
3709 // n = UInt(Rn); registers = register_list; wback = (W == '1');
3710 n = Bits32(opcode, 19, 16);
3711 registers = Bits32(opcode, 15, 0);
3712 wback = BitIsSet(opcode, 21);
3714 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
3715 if ((n == 15) || (BitCount(registers) < 1))
3724 // address = R[n] - 4*BitCount(registers);
3728 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
3733 addr_t address = Rn - (addr_byte_size * BitCount(registers));
3734 EmulateInstruction::Context context;
3735 context.type = EmulateInstruction::eContextRegisterPlusOffset;
3736 RegisterInfo dwarf_reg;
3737 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n, dwarf_reg);
3738 context.SetRegisterPlusOffset(dwarf_reg, Rn - address);
3740 for (int i = 0; i < 14; ++i) {
3741 if (BitIsSet(registers, i)) {
3742 // R[i] = MemA[address,4]; address = address + 4;
3743 context.SetRegisterPlusOffset(dwarf_reg, Rn - (address + offset));
3745 MemARead(context, address + offset, addr_byte_size, 0, &success);
3749 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + i,
3753 offset += addr_byte_size;
3757 // if registers<15> == '1' then
3758 // LoadWritePC(MemA[address,4]);
3759 if (BitIsSet(registers, 15)) {
3760 context.SetRegisterPlusOffset(dwarf_reg, offset);
3762 MemARead(context, address + offset, addr_byte_size, 0, &success);
3765 // In ARMv5T and above, this is an interworking branch.
3766 if (!LoadWritePC(context, data))
3770 // if wback && registers<n> == '0' then R[n] = R[n] - 4*BitCount(registers);
3771 if (wback && BitIsClear(registers, n)) {
3775 offset = (addr_byte_size * BitCount(registers)) * -1;
3776 context.type = EmulateInstruction::eContextAdjustBaseRegister;
3777 context.SetImmediateSigned(offset);
3778 addr_t addr = Rn + offset;
3779 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n,
3784 // if wback && registers<n> == '1' then R[n] = bits(32) UNKNOWN; // Only
3785 // possible for encoding A1
3786 if (wback && BitIsSet(registers, n))
3787 return WriteBits32Unknown(n);
3792 // LDMIB loads multiple registers from consecutive memory locations using an
3793 // address from a base register. The
3794 // consecutive memory locations start just above this address, and thea ddress
3795 // of the last of those locations can
3796 // optinoally be written back to the base register.
3797 bool EmulateInstructionARM::EmulateLDMIB(const uint32_t opcode,
3798 const ARMEncoding encoding) {
3800 if ConditionPassed() then
3801 EncodingSpecificOperations();
3805 if registers<i> == '1' then
3806 R[i] = MemA[address,4]; address = address + 4;
3807 if registers<15> == '1' then
3808 LoadWritePC(MemA[address,4]);
3810 if wback && registers<n> == '0' then R[n] = R[n] + 4*BitCount(registers);
3811 if wback && registers<n> == '1' then R[n] = bits(32) UNKNOWN;
3814 bool success = false;
3816 if (ConditionPassed(opcode)) {
3818 uint32_t registers = 0;
3820 const uint32_t addr_byte_size = GetAddressByteSize();
3823 // n = UInt(Rn); registers = register_list; wback = (W == '1');
3824 n = Bits32(opcode, 19, 16);
3825 registers = Bits32(opcode, 15, 0);
3826 wback = BitIsSet(opcode, 21);
3828 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
3829 if ((n == 15) || (BitCount(registers) < 1))
3836 // address = R[n] + 4;
3840 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
3845 addr_t address = Rn + addr_byte_size;
3847 EmulateInstruction::Context context;
3848 context.type = EmulateInstruction::eContextRegisterPlusOffset;
3849 RegisterInfo dwarf_reg;
3850 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n, dwarf_reg);
3851 context.SetRegisterPlusOffset(dwarf_reg, offset);
3853 for (int i = 0; i < 14; ++i) {
3854 if (BitIsSet(registers, i)) {
3855 // R[i] = MemA[address,4]; address = address + 4;
3857 context.SetRegisterPlusOffset(dwarf_reg, offset + addr_byte_size);
3859 MemARead(context, address + offset, addr_byte_size, 0, &success);
3863 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + i,
3867 offset += addr_byte_size;
3871 // if registers<15> == '1' then
3872 // LoadWritePC(MemA[address,4]);
3873 if (BitIsSet(registers, 15)) {
3874 context.SetRegisterPlusOffset(dwarf_reg, offset);
3876 MemARead(context, address + offset, addr_byte_size, 0, &success);
3879 // In ARMv5T and above, this is an interworking branch.
3880 if (!LoadWritePC(context, data))
3884 // if wback && registers<n> == '0' then R[n] = R[n] + 4*BitCount(registers);
3885 if (wback && BitIsClear(registers, n)) {
3889 offset = addr_byte_size * BitCount(registers);
3890 context.type = EmulateInstruction::eContextAdjustBaseRegister;
3891 context.SetImmediateSigned(offset);
3892 addr_t addr = Rn + offset;
3893 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n,
3898 // if wback && registers<n> == '1' then R[n] = bits(32) UNKNOWN; // Only
3899 // possible for encoding A1
3900 if (wback && BitIsSet(registers, n))
3901 return WriteBits32Unknown(n);
3906 // Load Register (immediate) calculates an address from a base register value
3908 // an immediate offset, loads a word from memory, and writes to a register.
3909 // LDR (immediate, Thumb)
3910 bool EmulateInstructionARM::EmulateLDRRtRnImm(const uint32_t opcode,
3911 const ARMEncoding encoding) {
3913 // ARM pseudo code...
3914 if (ConditionPassed())
3916 EncodingSpecificOperations(); NullCheckIfThumbEE(15);
3917 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
3918 address = if index then offset_addr else R[n];
3919 data = MemU[address,4];
3920 if wback then R[n] = offset_addr;
3922 if address<1:0> == '00' then LoadWritePC(data); else UNPREDICTABLE;
3923 elsif UnalignedSupport() || address<1:0> = '00' then
3925 else R[t] = bits(32) UNKNOWN; // Can only apply before ARMv7
3929 bool success = false;
3931 if (ConditionPassed(opcode)) {
3932 uint32_t Rt; // the destination register
3933 uint32_t Rn; // the base register
3934 uint32_t imm32; // the immediate offset used to form the address
3935 addr_t offset_addr; // the offset address
3936 addr_t address; // the calculated address
3937 uint32_t data; // the literal data value from memory load
3938 bool add, index, wback;
3941 Rt = Bits32(opcode, 2, 0);
3942 Rn = Bits32(opcode, 5, 3);
3943 imm32 = Bits32(opcode, 10, 6) << 2; // imm32 = ZeroExtend(imm5:'00', 32);
3944 // index = TRUE; add = TRUE; wback = FALSE
3952 // t = UInt(Rt); n = 13; imm32 = ZeroExtend(imm8:'00', 32);
3953 Rt = Bits32(opcode, 10, 8);
3955 imm32 = Bits32(opcode, 7, 0) << 2;
3957 // index = TRUE; add = TRUE; wback = FALSE;
3965 // if Rn == '1111' then SEE LDR (literal);
3966 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
3967 Rt = Bits32(opcode, 15, 12);
3968 Rn = Bits32(opcode, 19, 16);
3969 imm32 = Bits32(opcode, 11, 0);
3971 // index = TRUE; add = TRUE; wback = FALSE;
3976 // if t == 15 && InITBlock() && !LastInITBlock() then UNPREDICTABLE;
3977 if ((Rt == 15) && InITBlock() && !LastInITBlock())
3983 // if Rn == '1111' then SEE LDR (literal);
3984 // if P == '1' && U == '1' && W == '0' then SEE LDRT;
3985 // if Rn == '1101' && P == '0' && U == '1' && W == '1' && imm8 ==
3986 // '00000100' then SEE POP;
3987 // if P == '0' && W == '0' then UNDEFINED;
3988 if (BitIsClear(opcode, 10) && BitIsClear(opcode, 8))
3991 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32);
3992 Rt = Bits32(opcode, 15, 12);
3993 Rn = Bits32(opcode, 19, 16);
3994 imm32 = Bits32(opcode, 7, 0);
3996 // index = (P == '1'); add = (U == '1'); wback = (W == '1');
3997 index = BitIsSet(opcode, 10);
3998 add = BitIsSet(opcode, 9);
3999 wback = BitIsSet(opcode, 8);
4001 // if (wback && n == t) || (t == 15 && InITBlock() && !LastInITBlock())
4002 // then UNPREDICTABLE;
4003 if ((wback && (Rn == Rt)) ||
4004 ((Rt == 15) && InITBlock() && !LastInITBlock()))
4012 uint32_t base = ReadCoreReg(Rn, &success);
4016 offset_addr = base + imm32;
4018 offset_addr = base - imm32;
4020 address = (index ? offset_addr : base);
4022 RegisterInfo base_reg;
4023 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + Rn, base_reg);
4025 EmulateInstruction::Context ctx;
4027 ctx.type = eContextAdjustStackPointer;
4028 ctx.SetImmediateSigned((int32_t)(offset_addr - base));
4029 } else if (Rn == GetFramePointerRegisterNumber()) {
4030 ctx.type = eContextSetFramePointer;
4031 ctx.SetRegisterPlusOffset(base_reg, (int32_t)(offset_addr - base));
4033 ctx.type = EmulateInstruction::eContextAdjustBaseRegister;
4034 ctx.SetRegisterPlusOffset(base_reg, (int32_t)(offset_addr - base));
4037 if (!WriteRegisterUnsigned(ctx, eRegisterKindDWARF, dwarf_r0 + Rn,
4042 // Prepare to write to the Rt register.
4043 EmulateInstruction::Context context;
4044 context.type = EmulateInstruction::eContextRegisterLoad;
4045 context.SetRegisterPlusOffset(base_reg, (int32_t)(offset_addr - base));
4047 // Read memory from the address.
4048 data = MemURead(context, address, 4, 0, &success);
4053 if (Bits32(address, 1, 0) == 0) {
4054 if (!LoadWritePC(context, data))
4058 } else if (UnalignedSupport() || Bits32(address, 1, 0) == 0) {
4059 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + Rt,
4063 WriteBits32Unknown(Rt);
4068 // STM (Store Multiple Increment After) stores multiple registers to consecutive
4069 // memory locations using an address
4070 // from a base register. The consecutive memory locations start at this
4071 // address, and the address just above the last
4072 // of those locations can optionally be written back to the base register.
4073 bool EmulateInstructionARM::EmulateSTM(const uint32_t opcode,
4074 const ARMEncoding encoding) {
4076 if ConditionPassed() then
4077 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
4081 if registers<i> == '1' then
4082 if i == n && wback && i != LowestSetBit(registers) then
4083 MemA[address,4] = bits(32) UNKNOWN; // Only possible for encodings T1 and A1
4085 MemA[address,4] = R[i];
4086 address = address + 4;
4088 if registers<15> == '1' then // Only possible for encoding A1
4089 MemA[address,4] = PCStoreValue();
4090 if wback then R[n] = R[n] + 4*BitCount(registers);
4093 bool success = false;
4095 if (ConditionPassed(opcode)) {
4097 uint32_t registers = 0;
4099 const uint32_t addr_byte_size = GetAddressByteSize();
4101 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
4104 // n = UInt(Rn); registers = '00000000':register_list; wback = TRUE;
4105 n = Bits32(opcode, 10, 8);
4106 registers = Bits32(opcode, 7, 0);
4107 registers = registers & 0x00ff; // Make sure the top 8 bits are zeros.
4110 // if BitCount(registers) < 1 then UNPREDICTABLE;
4111 if (BitCount(registers) < 1)
4117 // n = UInt(Rn); registers = '0':M:'0':register_list; wback = (W == '1');
4118 n = Bits32(opcode, 19, 16);
4119 registers = Bits32(opcode, 15, 0);
4120 registers = registers & 0x5fff; // Make sure bits 15 & 13 are zeros.
4121 wback = BitIsSet(opcode, 21);
4123 // if n == 15 || BitCount(registers) < 2 then UNPREDICTABLE;
4124 if ((n == 15) || (BitCount(registers) < 2))
4127 // if wback && registers<n> == '1' then UNPREDICTABLE;
4128 if (wback && BitIsSet(registers, n))
4134 // n = UInt(Rn); registers = register_list; wback = (W == '1');
4135 n = Bits32(opcode, 19, 16);
4136 registers = Bits32(opcode, 15, 0);
4137 wback = BitIsSet(opcode, 21);
4139 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
4140 if ((n == 15) || (BitCount(registers) < 1))
4151 const addr_t address =
4152 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
4156 EmulateInstruction::Context context;
4157 context.type = EmulateInstruction::eContextRegisterStore;
4158 RegisterInfo base_reg;
4159 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n, base_reg);
4162 uint32_t lowest_set_bit = 14;
4163 for (uint32_t i = 0; i < 14; ++i) {
4164 // if registers<i> == '1' then
4165 if (BitIsSet(registers, i)) {
4166 if (i < lowest_set_bit)
4168 // if i == n && wback && i != LowestSetBit(registers) then
4169 if ((i == n) && wback && (i != lowest_set_bit))
4170 // MemA[address,4] = bits(32) UNKNOWN; // Only possible for encodings
4172 WriteBits32UnknownToMemory(address + offset);
4174 // MemA[address,4] = R[i];
4175 uint32_t data = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + i,
4180 RegisterInfo data_reg;
4181 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + i, data_reg);
4182 context.SetRegisterToRegisterPlusOffset(data_reg, base_reg, offset);
4183 if (!MemAWrite(context, address + offset, data, addr_byte_size))
4187 // address = address + 4;
4188 offset += addr_byte_size;
4192 // if registers<15> == '1' then // Only possible for encoding A1
4193 // MemA[address,4] = PCStoreValue();
4194 if (BitIsSet(registers, 15)) {
4195 RegisterInfo pc_reg;
4196 GetRegisterInfo(eRegisterKindDWARF, dwarf_pc, pc_reg);
4197 context.SetRegisterPlusOffset(pc_reg, 8);
4198 const uint32_t pc = ReadCoreReg(PC_REG, &success);
4202 if (!MemAWrite(context, address + offset, pc, addr_byte_size))
4206 // if wback then R[n] = R[n] + 4*BitCount(registers);
4208 offset = addr_byte_size * BitCount(registers);
4209 context.type = EmulateInstruction::eContextAdjustBaseRegister;
4210 context.SetImmediateSigned(offset);
4211 addr_t data = address + offset;
4212 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n,
4220 // STMDA (Store Multiple Decrement After) stores multiple registers to
4221 // consecutive memory locations using an address
4222 // from a base register. The consecutive memory locations end at this address,
4223 // and the address just below the lowest
4224 // of those locations can optionally be written back to the base register.
4225 bool EmulateInstructionARM::EmulateSTMDA(const uint32_t opcode,
4226 const ARMEncoding encoding) {
4228 if ConditionPassed() then
4229 EncodingSpecificOperations();
4230 address = R[n] - 4*BitCount(registers) + 4;
4233 if registers<i> == '1' then
4234 if i == n && wback && i != LowestSetBit(registers) then
4235 MemA[address,4] = bits(32) UNKNOWN;
4237 MemA[address,4] = R[i];
4238 address = address + 4;
4240 if registers<15> == '1' then
4241 MemA[address,4] = PCStoreValue();
4243 if wback then R[n] = R[n] - 4*BitCount(registers);
4246 bool success = false;
4248 if (ConditionPassed(opcode)) {
4250 uint32_t registers = 0;
4252 const uint32_t addr_byte_size = GetAddressByteSize();
4254 // EncodingSpecificOperations();
4257 // n = UInt(Rn); registers = register_list; wback = (W == '1');
4258 n = Bits32(opcode, 19, 16);
4259 registers = Bits32(opcode, 15, 0);
4260 wback = BitIsSet(opcode, 21);
4262 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
4263 if ((n == 15) || (BitCount(registers) < 1))
4270 // address = R[n] - 4*BitCount(registers) + 4;
4272 addr_t Rn = ReadCoreReg(n, &success);
4276 addr_t address = Rn - (addr_byte_size * BitCount(registers)) + 4;
4278 EmulateInstruction::Context context;
4279 context.type = EmulateInstruction::eContextRegisterStore;
4280 RegisterInfo base_reg;
4281 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n, base_reg);
4284 uint32_t lowest_bit_set = 14;
4285 for (uint32_t i = 0; i < 14; ++i) {
4286 // if registers<i> == '1' then
4287 if (BitIsSet(registers, i)) {
4288 if (i < lowest_bit_set)
4290 // if i == n && wback && i != LowestSetBit(registers) then
4291 if ((i == n) && wback && (i != lowest_bit_set))
4292 // MemA[address,4] = bits(32) UNKNOWN;
4293 WriteBits32UnknownToMemory(address + offset);
4295 // MemA[address,4] = R[i];
4296 uint32_t data = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + i,
4301 RegisterInfo data_reg;
4302 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + i, data_reg);
4303 context.SetRegisterToRegisterPlusOffset(data_reg, base_reg,
4304 Rn - (address + offset));
4305 if (!MemAWrite(context, address + offset, data, addr_byte_size))
4309 // address = address + 4;
4310 offset += addr_byte_size;
4314 // if registers<15> == '1' then
4315 // MemA[address,4] = PCStoreValue();
4316 if (BitIsSet(registers, 15)) {
4317 RegisterInfo pc_reg;
4318 GetRegisterInfo(eRegisterKindDWARF, dwarf_pc, pc_reg);
4319 context.SetRegisterPlusOffset(pc_reg, 8);
4320 const uint32_t pc = ReadCoreReg(PC_REG, &success);
4324 if (!MemAWrite(context, address + offset, pc, addr_byte_size))
4328 // if wback then R[n] = R[n] - 4*BitCount(registers);
4330 offset = (addr_byte_size * BitCount(registers)) * -1;
4331 context.type = EmulateInstruction::eContextAdjustBaseRegister;
4332 context.SetImmediateSigned(offset);
4333 addr_t data = Rn + offset;
4334 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n,
4342 // STMDB (Store Multiple Decrement Before) stores multiple registers to
4343 // consecutive memory locations using an address
4344 // from a base register. The consecutive memory locations end just below this
4345 // address, and the address of the first of
4346 // those locations can optionally be written back to the base register.
4347 bool EmulateInstructionARM::EmulateSTMDB(const uint32_t opcode,
4348 const ARMEncoding encoding) {
4350 if ConditionPassed() then
4351 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
4352 address = R[n] - 4*BitCount(registers);
4355 if registers<i> == '1' then
4356 if i == n && wback && i != LowestSetBit(registers) then
4357 MemA[address,4] = bits(32) UNKNOWN; // Only possible for encoding A1
4359 MemA[address,4] = R[i];
4360 address = address + 4;
4362 if registers<15> == '1' then // Only possible for encoding A1
4363 MemA[address,4] = PCStoreValue();
4365 if wback then R[n] = R[n] - 4*BitCount(registers);
4368 bool success = false;
4370 if (ConditionPassed(opcode)) {
4372 uint32_t registers = 0;
4374 const uint32_t addr_byte_size = GetAddressByteSize();
4376 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
4379 // if W == '1' && Rn == '1101' then SEE PUSH;
4380 if ((BitIsSet(opcode, 21)) && (Bits32(opcode, 19, 16) == 13)) {
4383 // n = UInt(Rn); registers = '0':M:'0':register_list; wback = (W == '1');
4384 n = Bits32(opcode, 19, 16);
4385 registers = Bits32(opcode, 15, 0);
4386 registers = registers & 0x5fff; // Make sure bits 15 & 13 are zeros.
4387 wback = BitIsSet(opcode, 21);
4388 // if n == 15 || BitCount(registers) < 2 then UNPREDICTABLE;
4389 if ((n == 15) || BitCount(registers) < 2)
4391 // if wback && registers<n> == '1' then UNPREDICTABLE;
4392 if (wback && BitIsSet(registers, n))
4397 // if W == '1' && Rn == '1101' && BitCount(register_list) >= 2 then SEE
4399 if (BitIsSet(opcode, 21) && (Bits32(opcode, 19, 16) == 13) &&
4400 BitCount(Bits32(opcode, 15, 0)) >= 2) {
4403 // n = UInt(Rn); registers = register_list; wback = (W == '1');
4404 n = Bits32(opcode, 19, 16);
4405 registers = Bits32(opcode, 15, 0);
4406 wback = BitIsSet(opcode, 21);
4407 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
4408 if ((n == 15) || BitCount(registers) < 1)
4416 // address = R[n] - 4*BitCount(registers);
4420 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
4424 addr_t address = Rn - (addr_byte_size * BitCount(registers));
4426 EmulateInstruction::Context context;
4427 context.type = EmulateInstruction::eContextRegisterStore;
4428 RegisterInfo base_reg;
4429 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n, base_reg);
4432 uint32_t lowest_set_bit = 14;
4433 for (uint32_t i = 0; i < 14; ++i) {
4434 // if registers<i> == '1' then
4435 if (BitIsSet(registers, i)) {
4436 if (i < lowest_set_bit)
4438 // if i == n && wback && i != LowestSetBit(registers) then
4439 if ((i == n) && wback && (i != lowest_set_bit))
4440 // MemA[address,4] = bits(32) UNKNOWN; // Only possible for encoding
4442 WriteBits32UnknownToMemory(address + offset);
4444 // MemA[address,4] = R[i];
4445 uint32_t data = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + i,
4450 RegisterInfo data_reg;
4451 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + i, data_reg);
4452 context.SetRegisterToRegisterPlusOffset(data_reg, base_reg,
4453 Rn - (address + offset));
4454 if (!MemAWrite(context, address + offset, data, addr_byte_size))
4458 // address = address + 4;
4459 offset += addr_byte_size;
4463 // if registers<15> == '1' then // Only possible for encoding A1
4464 // MemA[address,4] = PCStoreValue();
4465 if (BitIsSet(registers, 15)) {
4466 RegisterInfo pc_reg;
4467 GetRegisterInfo(eRegisterKindDWARF, dwarf_pc, pc_reg);
4468 context.SetRegisterPlusOffset(pc_reg, 8);
4469 const uint32_t pc = ReadCoreReg(PC_REG, &success);
4473 if (!MemAWrite(context, address + offset, pc, addr_byte_size))
4477 // if wback then R[n] = R[n] - 4*BitCount(registers);
4479 offset = (addr_byte_size * BitCount(registers)) * -1;
4480 context.type = EmulateInstruction::eContextAdjustBaseRegister;
4481 context.SetImmediateSigned(offset);
4482 addr_t data = Rn + offset;
4483 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n,
4491 // STMIB (Store Multiple Increment Before) stores multiple registers to
4492 // consecutive memory locations using an address
4493 // from a base register. The consecutive memory locations start just above this
4494 // address, and the address of the last
4495 // of those locations can optionally be written back to the base register.
4496 bool EmulateInstructionARM::EmulateSTMIB(const uint32_t opcode,
4497 const ARMEncoding encoding) {
4499 if ConditionPassed() then
4500 EncodingSpecificOperations();
4504 if registers<i> == '1' then
4505 if i == n && wback && i != LowestSetBit(registers) then
4506 MemA[address,4] = bits(32) UNKNOWN;
4508 MemA[address,4] = R[i];
4509 address = address + 4;
4511 if registers<15> == '1' then
4512 MemA[address,4] = PCStoreValue();
4514 if wback then R[n] = R[n] + 4*BitCount(registers);
4517 bool success = false;
4519 if (ConditionPassed(opcode)) {
4521 uint32_t registers = 0;
4523 const uint32_t addr_byte_size = GetAddressByteSize();
4525 // EncodingSpecificOperations();
4528 // n = UInt(Rn); registers = register_list; wback = (W == '1');
4529 n = Bits32(opcode, 19, 16);
4530 registers = Bits32(opcode, 15, 0);
4531 wback = BitIsSet(opcode, 21);
4533 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
4534 if ((n == 15) && (BitCount(registers) < 1))
4540 // address = R[n] + 4;
4543 addr_t Rn = ReadCoreReg(n, &success);
4547 addr_t address = Rn + addr_byte_size;
4549 EmulateInstruction::Context context;
4550 context.type = EmulateInstruction::eContextRegisterStore;
4551 RegisterInfo base_reg;
4552 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n, base_reg);
4554 uint32_t lowest_set_bit = 14;
4556 for (uint32_t i = 0; i < 14; ++i) {
4557 // if registers<i> == '1' then
4558 if (BitIsSet(registers, i)) {
4559 if (i < lowest_set_bit)
4561 // if i == n && wback && i != LowestSetBit(registers) then
4562 if ((i == n) && wback && (i != lowest_set_bit))
4563 // MemA[address,4] = bits(32) UNKNOWN;
4564 WriteBits32UnknownToMemory(address + offset);
4567 // MemA[address,4] = R[i];
4568 uint32_t data = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + i,
4573 RegisterInfo data_reg;
4574 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + i, data_reg);
4575 context.SetRegisterToRegisterPlusOffset(data_reg, base_reg,
4576 offset + addr_byte_size);
4577 if (!MemAWrite(context, address + offset, data, addr_byte_size))
4581 // address = address + 4;
4582 offset += addr_byte_size;
4586 // if registers<15> == '1' then
4587 // MemA[address,4] = PCStoreValue();
4588 if (BitIsSet(registers, 15)) {
4589 RegisterInfo pc_reg;
4590 GetRegisterInfo(eRegisterKindDWARF, dwarf_pc, pc_reg);
4591 context.SetRegisterPlusOffset(pc_reg, 8);
4592 const uint32_t pc = ReadCoreReg(PC_REG, &success);
4596 if (!MemAWrite(context, address + offset, pc, addr_byte_size))
4600 // if wback then R[n] = R[n] + 4*BitCount(registers);
4602 offset = addr_byte_size * BitCount(registers);
4603 context.type = EmulateInstruction::eContextAdjustBaseRegister;
4604 context.SetImmediateSigned(offset);
4605 addr_t data = Rn + offset;
4606 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n,
4614 // STR (store immediate) calculates an address from a base register value and an
4615 // immediate offset, and stores a word
4616 // from a register to memory. It can use offset, post-indexed, or pre-indexed
4618 bool EmulateInstructionARM::EmulateSTRThumb(const uint32_t opcode,
4619 const ARMEncoding encoding) {
4621 if ConditionPassed() then
4622 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
4623 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
4624 address = if index then offset_addr else R[n];
4625 if UnalignedSupport() || address<1:0> == '00' then
4626 MemU[address,4] = R[t];
4627 else // Can only occur before ARMv7
4628 MemU[address,4] = bits(32) UNKNOWN;
4629 if wback then R[n] = offset_addr;
4632 bool success = false;
4634 if (ConditionPassed(opcode)) {
4635 const uint32_t addr_byte_size = GetAddressByteSize();
4643 // EncodingSpecificOperations (); NullCheckIfThumbEE(n);
4646 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm5:'00', 32);
4647 t = Bits32(opcode, 2, 0);
4648 n = Bits32(opcode, 5, 3);
4649 imm32 = Bits32(opcode, 10, 6) << 2;
4651 // index = TRUE; add = TRUE; wback = FALSE;
4658 // t = UInt(Rt); n = 13; imm32 = ZeroExtend(imm8:'00', 32);
4659 t = Bits32(opcode, 10, 8);
4661 imm32 = Bits32(opcode, 7, 0) << 2;
4663 // index = TRUE; add = TRUE; wback = FALSE;
4670 // if Rn == '1111' then UNDEFINED;
4671 if (Bits32(opcode, 19, 16) == 15)
4674 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
4675 t = Bits32(opcode, 15, 12);
4676 n = Bits32(opcode, 19, 16);
4677 imm32 = Bits32(opcode, 11, 0);
4679 // index = TRUE; add = TRUE; wback = FALSE;
4684 // if t == 15 then UNPREDICTABLE;
4690 // if P == '1' && U == '1' && W == '0' then SEE STRT;
4691 // if Rn == '1101' && P == '1' && U == '0' && W == '1' && imm8 ==
4692 // '00000100' then SEE PUSH;
4693 // if Rn == '1111' || (P == '0' && W == '0') then UNDEFINED;
4694 if ((Bits32(opcode, 19, 16) == 15) ||
4695 (BitIsClear(opcode, 10) && BitIsClear(opcode, 8)))
4698 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32);
4699 t = Bits32(opcode, 15, 12);
4700 n = Bits32(opcode, 19, 16);
4701 imm32 = Bits32(opcode, 7, 0);
4703 // index = (P == '1'); add = (U == '1'); wback = (W == '1');
4704 index = BitIsSet(opcode, 10);
4705 add = BitIsSet(opcode, 9);
4706 wback = BitIsSet(opcode, 8);
4708 // if t == 15 || (wback && n == t) then UNPREDICTABLE;
4709 if ((t == 15) || (wback && (n == t)))
4720 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
4721 uint32_t base_address = ReadCoreReg(n, &success);
4726 offset_addr = base_address + imm32;
4728 offset_addr = base_address - imm32;
4730 // address = if index then offset_addr else R[n];
4732 address = offset_addr;
4734 address = base_address;
4736 EmulateInstruction::Context context;
4738 context.type = eContextPushRegisterOnStack;
4740 context.type = eContextRegisterStore;
4742 RegisterInfo base_reg;
4743 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n, base_reg);
4745 // if UnalignedSupport() || address<1:0> == '00' then
4746 if (UnalignedSupport() ||
4747 (BitIsClear(address, 1) && BitIsClear(address, 0))) {
4748 // MemU[address,4] = R[t];
4750 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + t, 0, &success);
4754 RegisterInfo data_reg;
4755 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + t, data_reg);
4756 int32_t offset = address - base_address;
4757 context.SetRegisterToRegisterPlusOffset(data_reg, base_reg, offset);
4758 if (!MemUWrite(context, address, data, addr_byte_size))
4761 // MemU[address,4] = bits(32) UNKNOWN;
4762 WriteBits32UnknownToMemory(address);
4765 // if wback then R[n] = offset_addr;
4768 context.type = eContextAdjustStackPointer;
4770 context.type = eContextAdjustBaseRegister;
4771 context.SetAddress(offset_addr);
4773 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n,
4781 // STR (Store Register) calculates an address from a base register value and an
4782 // offset register value, stores a
4783 // word from a register to memory. The offset register value can optionally be
4785 bool EmulateInstructionARM::EmulateSTRRegister(const uint32_t opcode,
4786 const ARMEncoding encoding) {
4788 if ConditionPassed() then
4789 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
4790 offset = Shift(R[m], shift_t, shift_n, APSR.C);
4791 offset_addr = if add then (R[n] + offset) else (R[n] - offset);
4792 address = if index then offset_addr else R[n];
4793 if t == 15 then // Only possible for encoding A1
4794 data = PCStoreValue();
4797 if UnalignedSupport() || address<1:0> == '00' || CurrentInstrSet() == InstrSet_ARM then
4798 MemU[address,4] = data;
4799 else // Can only occur before ARMv7
4800 MemU[address,4] = bits(32) UNKNOWN;
4801 if wback then R[n] = offset_addr;
4804 bool success = false;
4806 if (ConditionPassed(opcode)) {
4807 const uint32_t addr_byte_size = GetAddressByteSize();
4812 ARM_ShifterType shift_t;
4818 // EncodingSpecificOperations (); NullCheckIfThumbEE(n);
4821 // if CurrentInstrSet() == InstrSet_ThumbEE then SEE "Modified operation
4823 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
4824 t = Bits32(opcode, 2, 0);
4825 n = Bits32(opcode, 5, 3);
4826 m = Bits32(opcode, 8, 6);
4828 // index = TRUE; add = TRUE; wback = FALSE;
4833 // (shift_t, shift_n) = (SRType_LSL, 0);
4834 shift_t = SRType_LSL;
4839 // if Rn == '1111' then UNDEFINED;
4840 if (Bits32(opcode, 19, 16) == 15)
4843 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
4844 t = Bits32(opcode, 15, 12);
4845 n = Bits32(opcode, 19, 16);
4846 m = Bits32(opcode, 3, 0);
4848 // index = TRUE; add = TRUE; wback = FALSE;
4853 // (shift_t, shift_n) = (SRType_LSL, UInt(imm2));
4854 shift_t = SRType_LSL;
4855 shift_n = Bits32(opcode, 5, 4);
4857 // if t == 15 || BadReg(m) then UNPREDICTABLE;
4858 if ((t == 15) || (BadReg(m)))
4863 // if P == '0' && W == '1' then SEE STRT;
4864 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
4865 t = Bits32(opcode, 15, 12);
4866 n = Bits32(opcode, 19, 16);
4867 m = Bits32(opcode, 3, 0);
4869 // index = (P == '1'); add = (U == '1'); wback = (P == '0') ||
4871 index = BitIsSet(opcode, 24);
4872 add = BitIsSet(opcode, 23);
4873 wback = (BitIsClear(opcode, 24) || BitIsSet(opcode, 21));
4875 // (shift_t, shift_n) = DecodeImmShift(type, imm5);
4876 uint32_t typ = Bits32(opcode, 6, 5);
4877 uint32_t imm5 = Bits32(opcode, 11, 7);
4878 shift_n = DecodeImmShift(typ, imm5, shift_t);
4880 // if m == 15 then UNPREDICTABLE;
4884 // if wback && (n == 15 || n == t) then UNPREDICTABLE;
4885 if (wback && ((n == 15) || (n == t)))
4898 addr_t base_address =
4899 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
4904 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
4908 // offset = Shift(R[m], shift_t, shift_n, APSR.C);
4909 offset = Shift(Rm_data, shift_t, shift_n, APSR_C, &success);
4913 // offset_addr = if add then (R[n] + offset) else (R[n] - offset);
4915 offset_addr = base_address + offset;
4917 offset_addr = base_address - offset;
4919 // address = if index then offset_addr else R[n];
4921 address = offset_addr;
4923 address = base_address;
4926 // if t == 15 then // Only possible for encoding A1
4928 // data = PCStoreValue();
4929 data = ReadCoreReg(PC_REG, &success);
4933 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + t, 0, &success);
4938 EmulateInstruction::Context context;
4939 context.type = eContextRegisterStore;
4941 // if UnalignedSupport() || address<1:0> == '00' || CurrentInstrSet() ==
4942 // InstrSet_ARM then
4943 if (UnalignedSupport() ||
4944 (BitIsClear(address, 1) && BitIsClear(address, 0)) ||
4945 CurrentInstrSet() == eModeARM) {
4946 // MemU[address,4] = data;
4948 RegisterInfo base_reg;
4949 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n, base_reg);
4951 RegisterInfo data_reg;
4952 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + t, data_reg);
4954 context.SetRegisterToRegisterPlusOffset(data_reg, base_reg,
4955 address - base_address);
4956 if (!MemUWrite(context, address, data, addr_byte_size))
4960 // MemU[address,4] = bits(32) UNKNOWN;
4961 WriteBits32UnknownToMemory(address);
4963 // if wback then R[n] = offset_addr;
4965 context.type = eContextRegisterLoad;
4966 context.SetAddress(offset_addr);
4967 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n,
4975 bool EmulateInstructionARM::EmulateSTRBThumb(const uint32_t opcode,
4976 const ARMEncoding encoding) {
4978 if ConditionPassed() then
4979 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
4980 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
4981 address = if index then offset_addr else R[n];
4982 MemU[address,1] = R[t]<7:0>;
4983 if wback then R[n] = offset_addr;
4986 bool success = false;
4988 if (ConditionPassed(opcode)) {
4995 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
4998 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm5, 32);
4999 t = Bits32(opcode, 2, 0);
5000 n = Bits32(opcode, 5, 3);
5001 imm32 = Bits32(opcode, 10, 6);
5003 // index = TRUE; add = TRUE; wback = FALSE;
5010 // if Rn == '1111' then UNDEFINED;
5011 if (Bits32(opcode, 19, 16) == 15)
5014 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
5015 t = Bits32(opcode, 15, 12);
5016 n = Bits32(opcode, 19, 16);
5017 imm32 = Bits32(opcode, 11, 0);
5019 // index = TRUE; add = TRUE; wback = FALSE;
5024 // if BadReg(t) then UNPREDICTABLE;
5030 // if P == '1' && U == '1' && W == '0' then SEE STRBT;
5031 // if Rn == '1111' || (P == '0' && W == '0') then UNDEFINED;
5032 if (Bits32(opcode, 19, 16) == 15)
5035 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32);
5036 t = Bits32(opcode, 15, 12);
5037 n = Bits32(opcode, 19, 16);
5038 imm32 = Bits32(opcode, 7, 0);
5040 // index = (P == '1'); add = (U == '1'); wback = (W == '1');
5041 index = BitIsSet(opcode, 10);
5042 add = BitIsSet(opcode, 9);
5043 wback = BitIsSet(opcode, 8);
5045 // if BadReg(t) || (wback && n == t) then UNPREDICTABLE
5046 if ((BadReg(t)) || (wback && (n == t)))
5056 addr_t base_address =
5057 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
5061 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
5063 offset_addr = base_address + imm32;
5065 offset_addr = base_address - imm32;
5067 // address = if index then offset_addr else R[n];
5069 address = offset_addr;
5071 address = base_address;
5073 // MemU[address,1] = R[t]<7:0>
5074 RegisterInfo base_reg;
5075 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n, base_reg);
5077 RegisterInfo data_reg;
5078 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + t, data_reg);
5080 EmulateInstruction::Context context;
5081 context.type = eContextRegisterStore;
5082 context.SetRegisterToRegisterPlusOffset(data_reg, base_reg,
5083 address - base_address);
5086 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + t, 0, &success);
5090 data = Bits32(data, 7, 0);
5092 if (!MemUWrite(context, address, data, 1))
5095 // if wback then R[n] = offset_addr;
5097 context.type = eContextRegisterLoad;
5098 context.SetAddress(offset_addr);
5099 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n,
5108 // STRH (register) calculates an address from a base register value and an
5109 // offset register value, and stores a
5110 // halfword from a register to memory. The offset register value can be shifted
5111 // left by 0, 1, 2, or 3 bits.
5112 bool EmulateInstructionARM::EmulateSTRHRegister(const uint32_t opcode,
5113 const ARMEncoding encoding) {
5115 if ConditionPassed() then
5116 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
5117 offset = Shift(R[m], shift_t, shift_n, APSR.C);
5118 offset_addr = if add then (R[n] + offset) else (R[n] - offset);
5119 address = if index then offset_addr else R[n];
5120 if UnalignedSupport() || address<0> == '0' then
5121 MemU[address,2] = R[t]<15:0>;
5122 else // Can only occur before ARMv7
5123 MemU[address,2] = bits(16) UNKNOWN;
5124 if wback then R[n] = offset_addr;
5127 bool success = false;
5129 if (ConditionPassed(opcode)) {
5136 ARM_ShifterType shift_t;
5139 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
5142 // if CurrentInstrSet() == InstrSet_ThumbEE then SEE "Modified operation
5144 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
5145 t = Bits32(opcode, 2, 0);
5146 n = Bits32(opcode, 5, 3);
5147 m = Bits32(opcode, 8, 6);
5149 // index = TRUE; add = TRUE; wback = FALSE;
5154 // (shift_t, shift_n) = (SRType_LSL, 0);
5155 shift_t = SRType_LSL;
5161 // if Rn == '1111' then UNDEFINED;
5162 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
5163 t = Bits32(opcode, 15, 12);
5164 n = Bits32(opcode, 19, 16);
5165 m = Bits32(opcode, 3, 0);
5169 // index = TRUE; add = TRUE; wback = FALSE;
5174 // (shift_t, shift_n) = (SRType_LSL, UInt(imm2));
5175 shift_t = SRType_LSL;
5176 shift_n = Bits32(opcode, 5, 4);
5178 // if BadReg(t) || BadReg(m) then UNPREDICTABLE;
5179 if (BadReg(t) || BadReg(m))
5185 // if P == '0' && W == '1' then SEE STRHT;
5186 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
5187 t = Bits32(opcode, 15, 12);
5188 n = Bits32(opcode, 19, 16);
5189 m = Bits32(opcode, 3, 0);
5191 // index = (P == '1'); add = (U == '1'); wback = (P == '0') ||
5193 index = BitIsSet(opcode, 24);
5194 add = BitIsSet(opcode, 23);
5195 wback = (BitIsClear(opcode, 24) || BitIsSet(opcode, 21));
5197 // (shift_t, shift_n) = (SRType_LSL, 0);
5198 shift_t = SRType_LSL;
5201 // if t == 15 || m == 15 then UNPREDICTABLE;
5202 if ((t == 15) || (m == 15))
5205 // if wback && (n == 15 || n == t) then UNPREDICTABLE;
5206 if (wback && ((n == 15) || (n == t)))
5215 uint32_t Rm = ReadCoreReg(m, &success);
5219 uint32_t Rn = ReadCoreReg(n, &success);
5223 // offset = Shift(R[m], shift_t, shift_n, APSR.C);
5224 uint32_t offset = Shift(Rm, shift_t, shift_n, APSR_C, &success);
5228 // offset_addr = if add then (R[n] + offset) else (R[n] - offset);
5231 offset_addr = Rn + offset;
5233 offset_addr = Rn - offset;
5235 // address = if index then offset_addr else R[n];
5238 address = offset_addr;
5242 EmulateInstruction::Context context;
5243 context.type = eContextRegisterStore;
5244 RegisterInfo base_reg;
5245 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n, base_reg);
5246 RegisterInfo offset_reg;
5247 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + m, offset_reg);
5249 // if UnalignedSupport() || address<0> == '0' then
5250 if (UnalignedSupport() || BitIsClear(address, 0)) {
5251 // MemU[address,2] = R[t]<15:0>;
5252 uint32_t Rt = ReadCoreReg(t, &success);
5256 EmulateInstruction::Context context;
5257 context.type = eContextRegisterStore;
5258 RegisterInfo base_reg;
5259 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n, base_reg);
5260 RegisterInfo offset_reg;
5261 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + m, offset_reg);
5262 RegisterInfo data_reg;
5263 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + t, data_reg);
5264 context.SetRegisterToRegisterPlusIndirectOffset(base_reg, offset_reg,
5267 if (!MemUWrite(context, address, Bits32(Rt, 15, 0), 2))
5269 } else // Can only occur before ARMv7
5271 // MemU[address,2] = bits(16) UNKNOWN;
5274 // if wback then R[n] = offset_addr;
5276 context.type = eContextAdjustBaseRegister;
5277 context.SetAddress(offset_addr);
5278 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n,
5287 // Add with Carry (immediate) adds an immediate value and the carry flag value
5288 // to a register value,
5289 // and writes the result to the destination register. It can optionally update
5290 // the condition flags
5291 // based on the result.
5292 bool EmulateInstructionARM::EmulateADCImm(const uint32_t opcode,
5293 const ARMEncoding encoding) {
5295 // ARM pseudo code...
5296 if ConditionPassed() then
5297 EncodingSpecificOperations();
5298 (result, carry, overflow) = AddWithCarry(R[n], imm32, APSR.C);
5299 if d == 15 then // Can only occur for ARM encoding
5300 ALUWritePC(result); // setflags is always FALSE here
5304 APSR.N = result<31>;
5305 APSR.Z = IsZeroBit(result);
5310 bool success = false;
5312 if (ConditionPassed(opcode)) {
5315 imm32; // the immediate value to be added to the value obtained from Rn
5319 Rd = Bits32(opcode, 11, 8);
5320 Rn = Bits32(opcode, 19, 16);
5321 setflags = BitIsSet(opcode, 20);
5322 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8)
5323 if (BadReg(Rd) || BadReg(Rn))
5327 Rd = Bits32(opcode, 15, 12);
5328 Rn = Bits32(opcode, 19, 16);
5329 setflags = BitIsSet(opcode, 20);
5330 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
5332 if (Rd == 15 && setflags)
5333 return EmulateSUBSPcLrEtc(opcode, encoding);
5339 // Read the first operand.
5340 int32_t val1 = ReadCoreReg(Rn, &success);
5344 AddWithCarryResult res = AddWithCarry(val1, imm32, APSR_C);
5346 EmulateInstruction::Context context;
5347 context.type = EmulateInstruction::eContextImmediate;
5348 context.SetNoArgs();
5350 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags,
5351 res.carry_out, res.overflow))
5357 // Add with Carry (register) adds a register value, the carry flag value, and an
5358 // optionally-shifted
5359 // register value, and writes the result to the destination register. It can
5360 // optionally update the
5361 // condition flags based on the result.
5362 bool EmulateInstructionARM::EmulateADCReg(const uint32_t opcode,
5363 const ARMEncoding encoding) {
5365 // ARM pseudo code...
5366 if ConditionPassed() then
5367 EncodingSpecificOperations();
5368 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
5369 (result, carry, overflow) = AddWithCarry(R[n], shifted, APSR.C);
5370 if d == 15 then // Can only occur for ARM encoding
5371 ALUWritePC(result); // setflags is always FALSE here
5375 APSR.N = result<31>;
5376 APSR.Z = IsZeroBit(result);
5381 bool success = false;
5383 if (ConditionPassed(opcode)) {
5384 uint32_t Rd, Rn, Rm;
5385 ARM_ShifterType shift_t;
5386 uint32_t shift_n; // the shift applied to the value read from Rm
5390 Rd = Rn = Bits32(opcode, 2, 0);
5391 Rm = Bits32(opcode, 5, 3);
5392 setflags = !InITBlock();
5393 shift_t = SRType_LSL;
5397 Rd = Bits32(opcode, 11, 8);
5398 Rn = Bits32(opcode, 19, 16);
5399 Rm = Bits32(opcode, 3, 0);
5400 setflags = BitIsSet(opcode, 20);
5401 shift_n = DecodeImmShiftThumb(opcode, shift_t);
5402 if (BadReg(Rd) || BadReg(Rn) || BadReg(Rm))
5406 Rd = Bits32(opcode, 15, 12);
5407 Rn = Bits32(opcode, 19, 16);
5408 Rm = Bits32(opcode, 3, 0);
5409 setflags = BitIsSet(opcode, 20);
5410 shift_n = DecodeImmShiftARM(opcode, shift_t);
5412 if (Rd == 15 && setflags)
5413 return EmulateSUBSPcLrEtc(opcode, encoding);
5419 // Read the first operand.
5420 int32_t val1 = ReadCoreReg(Rn, &success);
5424 // Read the second operand.
5425 int32_t val2 = ReadCoreReg(Rm, &success);
5429 uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C, &success);
5432 AddWithCarryResult res = AddWithCarry(val1, shifted, APSR_C);
5434 EmulateInstruction::Context context;
5435 context.type = EmulateInstruction::eContextImmediate;
5436 context.SetNoArgs();
5438 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags,
5439 res.carry_out, res.overflow))
5445 // This instruction adds an immediate value to the PC value to form a
5446 // PC-relative address,
5447 // and writes the result to the destination register.
5448 bool EmulateInstructionARM::EmulateADR(const uint32_t opcode,
5449 const ARMEncoding encoding) {
5451 // ARM pseudo code...
5452 if ConditionPassed() then
5453 EncodingSpecificOperations();
5454 result = if add then (Align(PC,4) + imm32) else (Align(PC,4) - imm32);
5455 if d == 15 then // Can only occur for ARM encodings
5461 bool success = false;
5463 if (ConditionPassed(opcode)) {
5465 uint32_t imm32; // the immediate value to be added/subtracted to/from the PC
5469 Rd = Bits32(opcode, 10, 8);
5470 imm32 = ThumbImm8Scaled(opcode); // imm32 = ZeroExtend(imm8:'00', 32)
5475 Rd = Bits32(opcode, 11, 8);
5476 imm32 = ThumbImm12(opcode); // imm32 = ZeroExtend(i:imm3:imm8, 32)
5477 add = (Bits32(opcode, 24, 21) == 0); // 0b0000 => ADD; 0b0101 => SUB
5483 Rd = Bits32(opcode, 15, 12);
5484 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
5485 add = (Bits32(opcode, 24, 21) == 0x4); // 0b0100 => ADD; 0b0010 => SUB
5491 // Read the PC value.
5492 uint32_t pc = ReadCoreReg(PC_REG, &success);
5496 uint32_t result = (add ? Align(pc, 4) + imm32 : Align(pc, 4) - imm32);
5498 EmulateInstruction::Context context;
5499 context.type = EmulateInstruction::eContextImmediate;
5500 context.SetNoArgs();
5502 if (!WriteCoreReg(context, result, Rd))
5508 // This instruction performs a bitwise AND of a register value and an immediate
5509 // value, and writes the result
5510 // to the destination register. It can optionally update the condition flags
5511 // based on the result.
5512 bool EmulateInstructionARM::EmulateANDImm(const uint32_t opcode,
5513 const ARMEncoding encoding) {
5515 // ARM pseudo code...
5516 if ConditionPassed() then
5517 EncodingSpecificOperations();
5518 result = R[n] AND imm32;
5519 if d == 15 then // Can only occur for ARM encoding
5520 ALUWritePC(result); // setflags is always FALSE here
5524 APSR.N = result<31>;
5525 APSR.Z = IsZeroBit(result);
5530 bool success = false;
5532 if (ConditionPassed(opcode)) {
5535 imm32; // the immediate value to be ANDed to the value obtained from Rn
5537 uint32_t carry; // the carry bit after ARM/Thumb Expand operation
5540 Rd = Bits32(opcode, 11, 8);
5541 Rn = Bits32(opcode, 19, 16);
5542 setflags = BitIsSet(opcode, 20);
5543 imm32 = ThumbExpandImm_C(
5545 carry); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C)
5546 // if Rd == '1111' && S == '1' then SEE TST (immediate);
5547 if (Rd == 15 && setflags)
5548 return EmulateTSTImm(opcode, eEncodingT1);
5549 if (Rd == 13 || (Rd == 15 && !setflags) || BadReg(Rn))
5553 Rd = Bits32(opcode, 15, 12);
5554 Rn = Bits32(opcode, 19, 16);
5555 setflags = BitIsSet(opcode, 20);
5557 ARMExpandImm_C(opcode, APSR_C,
5558 carry); // (imm32, carry) = ARMExpandImm(imm12, APSR.C)
5560 if (Rd == 15 && setflags)
5561 return EmulateSUBSPcLrEtc(opcode, encoding);
5567 // Read the first operand.
5568 uint32_t val1 = ReadCoreReg(Rn, &success);
5572 uint32_t result = val1 & imm32;
5574 EmulateInstruction::Context context;
5575 context.type = EmulateInstruction::eContextImmediate;
5576 context.SetNoArgs();
5578 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
5584 // This instruction performs a bitwise AND of a register value and an
5585 // optionally-shifted register value,
5586 // and writes the result to the destination register. It can optionally update
5587 // the condition flags
5588 // based on the result.
5589 bool EmulateInstructionARM::EmulateANDReg(const uint32_t opcode,
5590 const ARMEncoding encoding) {
5592 // ARM pseudo code...
5593 if ConditionPassed() then
5594 EncodingSpecificOperations();
5595 (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C);
5596 result = R[n] AND shifted;
5597 if d == 15 then // Can only occur for ARM encoding
5598 ALUWritePC(result); // setflags is always FALSE here
5602 APSR.N = result<31>;
5603 APSR.Z = IsZeroBit(result);
5608 bool success = false;
5610 if (ConditionPassed(opcode)) {
5611 uint32_t Rd, Rn, Rm;
5612 ARM_ShifterType shift_t;
5613 uint32_t shift_n; // the shift applied to the value read from Rm
5618 Rd = Rn = Bits32(opcode, 2, 0);
5619 Rm = Bits32(opcode, 5, 3);
5620 setflags = !InITBlock();
5621 shift_t = SRType_LSL;
5625 Rd = Bits32(opcode, 11, 8);
5626 Rn = Bits32(opcode, 19, 16);
5627 Rm = Bits32(opcode, 3, 0);
5628 setflags = BitIsSet(opcode, 20);
5629 shift_n = DecodeImmShiftThumb(opcode, shift_t);
5630 // if Rd == '1111' && S == '1' then SEE TST (register);
5631 if (Rd == 15 && setflags)
5632 return EmulateTSTReg(opcode, eEncodingT2);
5633 if (Rd == 13 || (Rd == 15 && !setflags) || BadReg(Rn) || BadReg(Rm))
5637 Rd = Bits32(opcode, 15, 12);
5638 Rn = Bits32(opcode, 19, 16);
5639 Rm = Bits32(opcode, 3, 0);
5640 setflags = BitIsSet(opcode, 20);
5641 shift_n = DecodeImmShiftARM(opcode, shift_t);
5643 if (Rd == 15 && setflags)
5644 return EmulateSUBSPcLrEtc(opcode, encoding);
5650 // Read the first operand.
5651 uint32_t val1 = ReadCoreReg(Rn, &success);
5655 // Read the second operand.
5656 uint32_t val2 = ReadCoreReg(Rm, &success);
5660 uint32_t shifted = Shift_C(val2, shift_t, shift_n, APSR_C, carry, &success);
5663 uint32_t result = val1 & shifted;
5665 EmulateInstruction::Context context;
5666 context.type = EmulateInstruction::eContextImmediate;
5667 context.SetNoArgs();
5669 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
5675 // Bitwise Bit Clear (immediate) performs a bitwise AND of a register value and
5676 // the complement of an
5677 // immediate value, and writes the result to the destination register. It can
5678 // optionally update the
5679 // condition flags based on the result.
5680 bool EmulateInstructionARM::EmulateBICImm(const uint32_t opcode,
5681 const ARMEncoding encoding) {
5683 // ARM pseudo code...
5684 if ConditionPassed() then
5685 EncodingSpecificOperations();
5686 result = R[n] AND NOT(imm32);
5687 if d == 15 then // Can only occur for ARM encoding
5688 ALUWritePC(result); // setflags is always FALSE here
5692 APSR.N = result<31>;
5693 APSR.Z = IsZeroBit(result);
5698 bool success = false;
5700 if (ConditionPassed(opcode)) {
5702 uint32_t imm32; // the immediate value to be bitwise inverted and ANDed to
5703 // the value obtained from Rn
5705 uint32_t carry; // the carry bit after ARM/Thumb Expand operation
5708 Rd = Bits32(opcode, 11, 8);
5709 Rn = Bits32(opcode, 19, 16);
5710 setflags = BitIsSet(opcode, 20);
5711 imm32 = ThumbExpandImm_C(
5713 carry); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C)
5714 if (BadReg(Rd) || BadReg(Rn))
5718 Rd = Bits32(opcode, 15, 12);
5719 Rn = Bits32(opcode, 19, 16);
5720 setflags = BitIsSet(opcode, 20);
5722 ARMExpandImm_C(opcode, APSR_C,
5723 carry); // (imm32, carry) = ARMExpandImm(imm12, APSR.C)
5725 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related
5727 if (Rd == 15 && setflags)
5728 return EmulateSUBSPcLrEtc(opcode, encoding);
5734 // Read the first operand.
5735 uint32_t val1 = ReadCoreReg(Rn, &success);
5739 uint32_t result = val1 & ~imm32;
5741 EmulateInstruction::Context context;
5742 context.type = EmulateInstruction::eContextImmediate;
5743 context.SetNoArgs();
5745 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
5751 // Bitwise Bit Clear (register) performs a bitwise AND of a register value and
5752 // the complement of an
5753 // optionally-shifted register value, and writes the result to the destination
5755 // It can optionally update the condition flags based on the result.
5756 bool EmulateInstructionARM::EmulateBICReg(const uint32_t opcode,
5757 const ARMEncoding encoding) {
5759 // ARM pseudo code...
5760 if ConditionPassed() then
5761 EncodingSpecificOperations();
5762 (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C);
5763 result = R[n] AND NOT(shifted);
5764 if d == 15 then // Can only occur for ARM encoding
5765 ALUWritePC(result); // setflags is always FALSE here
5769 APSR.N = result<31>;
5770 APSR.Z = IsZeroBit(result);
5775 bool success = false;
5777 if (ConditionPassed(opcode)) {
5778 uint32_t Rd, Rn, Rm;
5779 ARM_ShifterType shift_t;
5780 uint32_t shift_n; // the shift applied to the value read from Rm
5785 Rd = Rn = Bits32(opcode, 2, 0);
5786 Rm = Bits32(opcode, 5, 3);
5787 setflags = !InITBlock();
5788 shift_t = SRType_LSL;
5792 Rd = Bits32(opcode, 11, 8);
5793 Rn = Bits32(opcode, 19, 16);
5794 Rm = Bits32(opcode, 3, 0);
5795 setflags = BitIsSet(opcode, 20);
5796 shift_n = DecodeImmShiftThumb(opcode, shift_t);
5797 if (BadReg(Rd) || BadReg(Rn) || BadReg(Rm))
5801 Rd = Bits32(opcode, 15, 12);
5802 Rn = Bits32(opcode, 19, 16);
5803 Rm = Bits32(opcode, 3, 0);
5804 setflags = BitIsSet(opcode, 20);
5805 shift_n = DecodeImmShiftARM(opcode, shift_t);
5807 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related
5809 if (Rd == 15 && setflags)
5810 return EmulateSUBSPcLrEtc(opcode, encoding);
5816 // Read the first operand.
5817 uint32_t val1 = ReadCoreReg(Rn, &success);
5821 // Read the second operand.
5822 uint32_t val2 = ReadCoreReg(Rm, &success);
5826 uint32_t shifted = Shift_C(val2, shift_t, shift_n, APSR_C, carry, &success);
5829 uint32_t result = val1 & ~shifted;
5831 EmulateInstruction::Context context;
5832 context.type = EmulateInstruction::eContextImmediate;
5833 context.SetNoArgs();
5835 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
5841 // LDR (immediate, ARM) calculates an address from a base register value and an
5842 // immediate offset, loads a word
5843 // from memory, and writes it to a register. It can use offset, post-indexed,
5844 // or pre-indexed addressing.
5845 bool EmulateInstructionARM::EmulateLDRImmediateARM(const uint32_t opcode,
5846 const ARMEncoding encoding) {
5848 if ConditionPassed() then
5849 EncodingSpecificOperations();
5850 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
5851 address = if index then offset_addr else R[n];
5852 data = MemU[address,4];
5853 if wback then R[n] = offset_addr;
5855 if address<1:0> == '00' then LoadWritePC(data); else UNPREDICTABLE;
5856 elsif UnalignedSupport() || address<1:0> = '00' then
5858 else // Can only apply before ARMv7
5859 R[t] = ROR(data, 8*UInt(address<1:0>));
5862 bool success = false;
5864 if (ConditionPassed(opcode)) {
5865 const uint32_t addr_byte_size = GetAddressByteSize();
5876 // if Rn == '1111' then SEE LDR (literal);
5877 // if P == '0' && W == '1' then SEE LDRT;
5878 // if Rn == '1101' && P == '0' && U == '1' && W == '0' && imm12 ==
5879 // '000000000100' then SEE POP;
5880 // t == UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
5881 t = Bits32(opcode, 15, 12);
5882 n = Bits32(opcode, 19, 16);
5883 imm32 = Bits32(opcode, 11, 0);
5885 // index = (P == '1'); add = (U == '1'); wback = (P == '0') ||
5887 index = BitIsSet(opcode, 24);
5888 add = BitIsSet(opcode, 23);
5889 wback = (BitIsClear(opcode, 24) || BitIsSet(opcode, 21));
5891 // if wback && n == t then UNPREDICTABLE;
5892 if (wback && (n == t))
5903 addr_t base_address = ReadCoreReg(n, &success);
5907 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
5909 offset_addr = base_address + imm32;
5911 offset_addr = base_address - imm32;
5913 // address = if index then offset_addr else R[n];
5915 address = offset_addr;
5917 address = base_address;
5919 // data = MemU[address,4];
5921 RegisterInfo base_reg;
5922 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n, base_reg);
5924 EmulateInstruction::Context context;
5925 context.type = eContextRegisterLoad;
5926 context.SetRegisterPlusOffset(base_reg, address - base_address);
5928 uint64_t data = MemURead(context, address, addr_byte_size, 0, &success);
5932 // if wback then R[n] = offset_addr;
5934 context.type = eContextAdjustBaseRegister;
5935 context.SetAddress(offset_addr);
5936 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n,
5943 // if address<1:0> == '00' then LoadWritePC(data); else UNPREDICTABLE;
5944 if (BitIsClear(address, 1) && BitIsClear(address, 0)) {
5945 // LoadWritePC (data);
5946 context.type = eContextRegisterLoad;
5947 context.SetRegisterPlusOffset(base_reg, address - base_address);
5948 LoadWritePC(context, data);
5952 // elsif UnalignedSupport() || address<1:0> = '00' then
5953 else if (UnalignedSupport() ||
5954 (BitIsClear(address, 1) && BitIsClear(address, 0))) {
5956 context.type = eContextRegisterLoad;
5957 context.SetRegisterPlusOffset(base_reg, address - base_address);
5958 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + t,
5962 // else // Can only apply before ARMv7
5964 // R[t] = ROR(data, 8*UInt(address<1:0>));
5965 data = ROR(data, Bits32(address, 1, 0), &success);
5968 context.type = eContextRegisterLoad;
5969 context.SetImmediate(data);
5970 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + t,
5978 // LDR (register) calculates an address from a base register value and an offset
5979 // register value, loads a word
5980 // from memory, and writes it to a register. The offset register value can
5981 // optionally be shifted.
5982 bool EmulateInstructionARM::EmulateLDRRegister(const uint32_t opcode,
5983 const ARMEncoding encoding) {
5985 if ConditionPassed() then
5986 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
5987 offset = Shift(R[m], shift_t, shift_n, APSR.C);
5988 offset_addr = if add then (R[n] + offset) else (R[n] - offset);
5989 address = if index then offset_addr else R[n];
5990 data = MemU[address,4];
5991 if wback then R[n] = offset_addr;
5993 if address<1:0> == '00' then LoadWritePC(data); else UNPREDICTABLE;
5994 elsif UnalignedSupport() || address<1:0> = '00' then
5996 else // Can only apply before ARMv7
5997 if CurrentInstrSet() == InstrSet_ARM then
5998 R[t] = ROR(data, 8*UInt(address<1:0>));
6000 R[t] = bits(32) UNKNOWN;
6003 bool success = false;
6005 if (ConditionPassed(opcode)) {
6006 const uint32_t addr_byte_size = GetAddressByteSize();
6014 ARM_ShifterType shift_t;
6019 // if CurrentInstrSet() == InstrSet_ThumbEE then SEE "Modified operation
6021 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
6022 t = Bits32(opcode, 2, 0);
6023 n = Bits32(opcode, 5, 3);
6024 m = Bits32(opcode, 8, 6);
6026 // index = TRUE; add = TRUE; wback = FALSE;
6031 // (shift_t, shift_n) = (SRType_LSL, 0);
6032 shift_t = SRType_LSL;
6038 // if Rn == '1111' then SEE LDR (literal);
6039 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
6040 t = Bits32(opcode, 15, 12);
6041 n = Bits32(opcode, 19, 16);
6042 m = Bits32(opcode, 3, 0);
6044 // index = TRUE; add = TRUE; wback = FALSE;
6049 // (shift_t, shift_n) = (SRType_LSL, UInt(imm2));
6050 shift_t = SRType_LSL;
6051 shift_n = Bits32(opcode, 5, 4);
6053 // if BadReg(m) then UNPREDICTABLE;
6057 // if t == 15 && InITBlock() && !LastInITBlock() then UNPREDICTABLE;
6058 if ((t == 15) && InITBlock() && !LastInITBlock())
6064 // if P == '0' && W == '1' then SEE LDRT;
6065 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
6066 t = Bits32(opcode, 15, 12);
6067 n = Bits32(opcode, 19, 16);
6068 m = Bits32(opcode, 3, 0);
6070 // index = (P == '1'); add = (U == '1'); wback = (P == '0') ||
6072 index = BitIsSet(opcode, 24);
6073 add = BitIsSet(opcode, 23);
6074 wback = (BitIsClear(opcode, 24) || BitIsSet(opcode, 21));
6076 // (shift_t, shift_n) = DecodeImmShift(type, imm5);
6077 uint32_t type = Bits32(opcode, 6, 5);
6078 uint32_t imm5 = Bits32(opcode, 11, 7);
6079 shift_n = DecodeImmShift(type, imm5, shift_t);
6081 // if m == 15 then UNPREDICTABLE;
6085 // if wback && (n == 15 || n == t) then UNPREDICTABLE;
6086 if (wback && ((n == 15) || (n == t)))
6095 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
6100 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
6107 // offset = Shift(R[m], shift_t, shift_n, APSR.C); -- Note "The APSR is an
6108 // application level alias for the CPSR".
6110 Shift(Rm, shift_t, shift_n, Bit32(m_opcode_cpsr, APSR_C), &success);
6114 // offset_addr = if add then (R[n] + offset) else (R[n] - offset);
6116 offset_addr = Rn + offset;
6118 offset_addr = Rn - offset;
6120 // address = if index then offset_addr else R[n];
6122 address = offset_addr;
6126 // data = MemU[address,4];
6127 RegisterInfo base_reg;
6128 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n, base_reg);
6130 EmulateInstruction::Context context;
6131 context.type = eContextRegisterLoad;
6132 context.SetRegisterPlusOffset(base_reg, address - Rn);
6134 uint64_t data = MemURead(context, address, addr_byte_size, 0, &success);
6138 // if wback then R[n] = offset_addr;
6140 context.type = eContextAdjustBaseRegister;
6141 context.SetAddress(offset_addr);
6142 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n,
6149 // if address<1:0> == '00' then LoadWritePC(data); else UNPREDICTABLE;
6150 if (BitIsClear(address, 1) && BitIsClear(address, 0)) {
6151 context.type = eContextRegisterLoad;
6152 context.SetRegisterPlusOffset(base_reg, address - Rn);
6153 LoadWritePC(context, data);
6157 // elsif UnalignedSupport() || address<1:0> = '00' then
6158 else if (UnalignedSupport() ||
6159 (BitIsClear(address, 1) && BitIsClear(address, 0))) {
6161 context.type = eContextRegisterLoad;
6162 context.SetRegisterPlusOffset(base_reg, address - Rn);
6163 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + t,
6166 } else // Can only apply before ARMv7
6168 // if CurrentInstrSet() == InstrSet_ARM then
6169 if (CurrentInstrSet() == eModeARM) {
6170 // R[t] = ROR(data, 8*UInt(address<1:0>));
6171 data = ROR(data, Bits32(address, 1, 0), &success);
6174 context.type = eContextRegisterLoad;
6175 context.SetImmediate(data);
6176 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + t,
6180 // R[t] = bits(32) UNKNOWN;
6181 WriteBits32Unknown(t);
6188 // LDRB (immediate, Thumb)
6189 bool EmulateInstructionARM::EmulateLDRBImmediate(const uint32_t opcode,
6190 const ARMEncoding encoding) {
6192 if ConditionPassed() then
6193 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
6194 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
6195 address = if index then offset_addr else R[n];
6196 R[t] = ZeroExtend(MemU[address,1], 32);
6197 if wback then R[n] = offset_addr;
6200 bool success = false;
6202 if (ConditionPassed(opcode)) {
6210 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
6213 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm5, 32);
6214 t = Bits32(opcode, 2, 0);
6215 n = Bits32(opcode, 5, 3);
6216 imm32 = Bits32(opcode, 10, 6);
6218 // index = TRUE; add = TRUE; wback = FALSE;
6226 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
6227 t = Bits32(opcode, 15, 12);
6228 n = Bits32(opcode, 19, 16);
6229 imm32 = Bits32(opcode, 11, 0);
6231 // index = TRUE; add = TRUE; wback = FALSE;
6236 // if Rt == '1111' then SEE PLD;
6238 return false; // PLD is not implemented yet
6240 // if Rn == '1111' then SEE LDRB (literal);
6242 return EmulateLDRBLiteral(opcode, eEncodingT1);
6244 // if t == 13 then UNPREDICTABLE;
6251 // if P == '1' && U == '1' && W == '0' then SEE LDRBT;
6252 // if P == '0' && W == '0' then UNDEFINED;
6253 if (BitIsClear(opcode, 10) && BitIsClear(opcode, 8))
6256 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32);
6257 t = Bits32(opcode, 15, 12);
6258 n = Bits32(opcode, 19, 16);
6259 imm32 = Bits32(opcode, 7, 0);
6261 // index = (P == '1'); add = (U == '1'); wback = (W == '1');
6262 index = BitIsSet(opcode, 10);
6263 add = BitIsSet(opcode, 9);
6264 wback = BitIsSet(opcode, 8);
6266 // if Rt == '1111' && P == '1' && U == '0' && W == '0' then SEE PLD;
6268 return false; // PLD is not implemented yet
6270 // if Rn == '1111' then SEE LDRB (literal);
6272 return EmulateLDRBLiteral(opcode, eEncodingT1);
6274 // if BadReg(t) || (wback && n == t) then UNPREDICTABLE;
6275 if (BadReg(t) || (wback && (n == t)))
6285 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
6292 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
6294 offset_addr = Rn + imm32;
6296 offset_addr = Rn - imm32;
6298 // address = if index then offset_addr else R[n];
6300 address = offset_addr;
6304 // R[t] = ZeroExtend(MemU[address,1], 32);
6305 RegisterInfo base_reg;
6306 RegisterInfo data_reg;
6307 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n, base_reg);
6308 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + t, data_reg);
6310 EmulateInstruction::Context context;
6311 context.type = eContextRegisterLoad;
6312 context.SetRegisterToRegisterPlusOffset(data_reg, base_reg, address - Rn);
6314 uint64_t data = MemURead(context, address, 1, 0, &success);
6318 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + t, data))
6321 // if wback then R[n] = offset_addr;
6323 context.type = eContextAdjustBaseRegister;
6324 context.SetAddress(offset_addr);
6325 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n,
6333 // LDRB (literal) calculates an address from the PC value and an immediate
6334 // offset, loads a byte from memory,
6335 // zero-extends it to form a 32-bit word and writes it to a register.
6336 bool EmulateInstructionARM::EmulateLDRBLiteral(const uint32_t opcode,
6337 const ARMEncoding encoding) {
6339 if ConditionPassed() then
6340 EncodingSpecificOperations(); NullCheckIfThumbEE(15);
6342 address = if add then (base + imm32) else (base - imm32);
6343 R[t] = ZeroExtend(MemU[address,1], 32);
6346 bool success = false;
6348 if (ConditionPassed(opcode)) {
6354 // t = UInt(Rt); imm32 = ZeroExtend(imm12, 32); add = (U == '1');
6355 t = Bits32(opcode, 15, 12);
6356 imm32 = Bits32(opcode, 11, 0);
6357 add = BitIsSet(opcode, 23);
6359 // if Rt == '1111' then SEE PLD;
6361 return false; // PLD is not implemented yet
6363 // if t == 13 then UNPREDICTABLE;
6370 // t == UInt(Rt); imm32 = ZeroExtend(imm12, 32); add = (U == '1');
6371 t = Bits32(opcode, 15, 12);
6372 imm32 = Bits32(opcode, 11, 0);
6373 add = BitIsSet(opcode, 23);
6375 // if t == 15 then UNPREDICTABLE;
6384 // base = Align(PC,4);
6385 uint32_t pc_val = ReadCoreReg(PC_REG, &success);
6389 uint32_t base = AlignPC(pc_val);
6392 // address = if add then (base + imm32) else (base - imm32);
6394 address = base + imm32;
6396 address = base - imm32;
6398 // R[t] = ZeroExtend(MemU[address,1], 32);
6399 EmulateInstruction::Context context;
6400 context.type = eContextRelativeBranchImmediate;
6401 context.SetImmediate(address - base);
6403 uint64_t data = MemURead(context, address, 1, 0, &success);
6407 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + t, data))
6413 // LDRB (register) calculates an address from a base register value and an
6414 // offset rigister value, loads a byte from
6415 // memory, zero-extends it to form a 32-bit word, and writes it to a register.
6416 // The offset register value can
6417 // optionally be shifted.
6418 bool EmulateInstructionARM::EmulateLDRBRegister(const uint32_t opcode,
6419 const ARMEncoding encoding) {
6421 if ConditionPassed() then
6422 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
6423 offset = Shift(R[m], shift_t, shift_n, APSR.C);
6424 offset_addr = if add then (R[n] + offset) else (R[n] - offset);
6425 address = if index then offset_addr else R[n];
6426 R[t] = ZeroExtend(MemU[address,1],32);
6427 if wback then R[n] = offset_addr;
6430 bool success = false;
6432 if (ConditionPassed(opcode)) {
6439 ARM_ShifterType shift_t;
6442 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
6445 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
6446 t = Bits32(opcode, 2, 0);
6447 n = Bits32(opcode, 5, 3);
6448 m = Bits32(opcode, 8, 6);
6450 // index = TRUE; add = TRUE; wback = FALSE;
6455 // (shift_t, shift_n) = (SRType_LSL, 0);
6456 shift_t = SRType_LSL;
6461 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
6462 t = Bits32(opcode, 15, 12);
6463 n = Bits32(opcode, 19, 16);
6464 m = Bits32(opcode, 3, 0);
6466 // index = TRUE; add = TRUE; wback = FALSE;
6471 // (shift_t, shift_n) = (SRType_LSL, UInt(imm2));
6472 shift_t = SRType_LSL;
6473 shift_n = Bits32(opcode, 5, 4);
6475 // if Rt == '1111' then SEE PLD;
6477 return false; // PLD is not implemented yet
6479 // if Rn == '1111' then SEE LDRB (literal);
6481 return EmulateLDRBLiteral(opcode, eEncodingT1);
6483 // if t == 13 || BadReg(m) then UNPREDICTABLE;
6484 if ((t == 13) || BadReg(m))
6489 // if P == '0' && W == '1' then SEE LDRBT;
6490 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
6491 t = Bits32(opcode, 15, 12);
6492 n = Bits32(opcode, 19, 16);
6493 m = Bits32(opcode, 3, 0);
6495 // index = (P == '1'); add = (U == '1'); wback = (P == '0') ||
6497 index = BitIsSet(opcode, 24);
6498 add = BitIsSet(opcode, 23);
6499 wback = (BitIsClear(opcode, 24) || BitIsSet(opcode, 21));
6501 // (shift_t, shift_n) = DecodeImmShift(type, imm5);
6502 uint32_t type = Bits32(opcode, 6, 5);
6503 uint32_t imm5 = Bits32(opcode, 11, 7);
6504 shift_n = DecodeImmShift(type, imm5, shift_t);
6506 // if t == 15 || m == 15 then UNPREDICTABLE;
6507 if ((t == 15) || (m == 15))
6510 // if wback && (n == 15 || n == t) then UNPREDICTABLE;
6511 if (wback && ((n == 15) || (n == t)))
6522 // offset = Shift(R[m], shift_t, shift_n, APSR.C);
6524 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
6528 addr_t offset = Shift(Rm, shift_t, shift_n, APSR_C, &success);
6532 // offset_addr = if add then (R[n] + offset) else (R[n] - offset);
6534 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
6539 offset_addr = Rn + offset;
6541 offset_addr = Rn - offset;
6543 // address = if index then offset_addr else R[n];
6545 address = offset_addr;
6549 // R[t] = ZeroExtend(MemU[address,1],32);
6550 RegisterInfo base_reg;
6551 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n, base_reg);
6553 EmulateInstruction::Context context;
6554 context.type = eContextRegisterLoad;
6555 context.SetRegisterPlusOffset(base_reg, address - Rn);
6557 uint64_t data = MemURead(context, address, 1, 0, &success);
6561 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + t, data))
6564 // if wback then R[n] = offset_addr;
6566 context.type = eContextAdjustBaseRegister;
6567 context.SetAddress(offset_addr);
6568 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n,
6576 // LDRH (immediate, Thumb) calculates an address from a base register value and
6577 // an immediate offset, loads a
6578 // halfword from memory, zero-extends it to form a 32-bit word, and writes it to
6579 // a register. It can use offset,
6580 // post-indexed, or pre-indexed addressing.
6581 bool EmulateInstructionARM::EmulateLDRHImmediate(const uint32_t opcode,
6582 const ARMEncoding encoding) {
6584 if ConditionPassed() then
6585 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
6586 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
6587 address = if index then offset_addr else R[n];
6588 data = MemU[address,2];
6589 if wback then R[n] = offset_addr;
6590 if UnalignedSupport() || address<0> = '0' then
6591 R[t] = ZeroExtend(data, 32);
6592 else // Can only apply before ARMv7
6593 R[t] = bits(32) UNKNOWN;
6596 bool success = false;
6598 if (ConditionPassed(opcode)) {
6606 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
6609 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm5:'0', 32);
6610 t = Bits32(opcode, 2, 0);
6611 n = Bits32(opcode, 5, 3);
6612 imm32 = Bits32(opcode, 10, 6) << 1;
6614 // index = TRUE; add = TRUE; wback = FALSE;
6622 // if Rt == '1111' then SEE "Unallocated memory hints";
6623 // if Rn == '1111' then SEE LDRH (literal);
6624 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
6625 t = Bits32(opcode, 15, 12);
6626 n = Bits32(opcode, 19, 16);
6627 imm32 = Bits32(opcode, 11, 0);
6629 // index = TRUE; add = TRUE; wback = FALSE;
6634 // if t == 13 then UNPREDICTABLE;
6640 // if Rn == '1111' then SEE LDRH (literal);
6641 // if Rt == '1111' && P == '1' && U == '0' && W == '0' then SEE
6642 // "Unallocated memory hints";
6643 // if P == '1' && U == '1' && W == '0' then SEE LDRHT;
6644 // if P == '0' && W == '0' then UNDEFINED;
6645 if (BitIsClear(opcode, 10) && BitIsClear(opcode, 8))
6648 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32);
6649 t = Bits32(opcode, 15, 12);
6650 n = Bits32(opcode, 19, 16);
6651 imm32 = Bits32(opcode, 7, 0);
6653 // index = (P == '1'); add = (U == '1'); wback = (W == '1');
6654 index = BitIsSet(opcode, 10);
6655 add = BitIsSet(opcode, 9);
6656 wback = BitIsSet(opcode, 8);
6658 // if BadReg(t) || (wback && n == t) then UNPREDICTABLE;
6659 if (BadReg(t) || (wback && (n == t)))
6667 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
6669 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
6677 offset_addr = Rn + imm32;
6679 offset_addr = Rn - imm32;
6681 // address = if index then offset_addr else R[n];
6683 address = offset_addr;
6687 // data = MemU[address,2];
6688 RegisterInfo base_reg;
6689 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n, base_reg);
6691 EmulateInstruction::Context context;
6692 context.type = eContextRegisterLoad;
6693 context.SetRegisterPlusOffset(base_reg, address - Rn);
6695 uint64_t data = MemURead(context, address, 2, 0, &success);
6699 // if wback then R[n] = offset_addr;
6701 context.type = eContextAdjustBaseRegister;
6702 context.SetAddress(offset_addr);
6703 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n,
6708 // if UnalignedSupport() || address<0> = '0' then
6709 if (UnalignedSupport() || BitIsClear(address, 0)) {
6710 // R[t] = ZeroExtend(data, 32);
6711 context.type = eContextRegisterLoad;
6712 context.SetRegisterPlusOffset(base_reg, address - Rn);
6713 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + t,
6716 } else // Can only apply before ARMv7
6718 // R[t] = bits(32) UNKNOWN;
6719 WriteBits32Unknown(t);
6725 // LDRH (literal) caculates an address from the PC value and an immediate
6726 // offset, loads a halfword from memory,
6727 // zero-extends it to form a 32-bit word, and writes it to a register.
6728 bool EmulateInstructionARM::EmulateLDRHLiteral(const uint32_t opcode,
6729 const ARMEncoding encoding) {
6731 if ConditionPassed() then
6732 EncodingSpecificOperations(); NullCheckIfThumbEE(15);
6734 address = if add then (base + imm32) else (base - imm32);
6735 data = MemU[address,2];
6736 if UnalignedSupport() || address<0> = '0' then
6737 R[t] = ZeroExtend(data, 32);
6738 else // Can only apply before ARMv7
6739 R[t] = bits(32) UNKNOWN;
6742 bool success = false;
6744 if (ConditionPassed(opcode)) {
6749 // EncodingSpecificOperations(); NullCheckIfThumbEE(15);
6752 // if Rt == '1111' then SEE "Unallocated memory hints";
6753 // t = UInt(Rt); imm32 = ZeroExtend(imm12, 32); add = (U == '1');
6754 t = Bits32(opcode, 15, 12);
6755 imm32 = Bits32(opcode, 11, 0);
6756 add = BitIsSet(opcode, 23);
6758 // if t == 13 then UNPREDICTABLE;
6765 uint32_t imm4H = Bits32(opcode, 11, 8);
6766 uint32_t imm4L = Bits32(opcode, 3, 0);
6768 // t == UInt(Rt); imm32 = ZeroExtend(imm4H:imm4L, 32); add = (U == '1');
6769 t = Bits32(opcode, 15, 12);
6770 imm32 = (imm4H << 4) | imm4L;
6771 add = BitIsSet(opcode, 23);
6773 // if t == 15 then UNPREDICTABLE;
6783 // base = Align(PC,4);
6784 uint64_t pc_value = ReadCoreReg(PC_REG, &success);
6788 addr_t base = AlignPC(pc_value);
6791 // address = if add then (base + imm32) else (base - imm32);
6793 address = base + imm32;
6795 address = base - imm32;
6797 // data = MemU[address,2];
6798 RegisterInfo base_reg;
6799 GetRegisterInfo(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, base_reg);
6801 EmulateInstruction::Context context;
6802 context.type = eContextRegisterLoad;
6803 context.SetRegisterPlusOffset(base_reg, address - base);
6805 uint64_t data = MemURead(context, address, 2, 0, &success);
6809 // if UnalignedSupport() || address<0> = '0' then
6810 if (UnalignedSupport() || BitIsClear(address, 0)) {
6811 // R[t] = ZeroExtend(data, 32);
6812 context.type = eContextRegisterLoad;
6813 context.SetRegisterPlusOffset(base_reg, address - base);
6814 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + t,
6818 } else // Can only apply before ARMv7
6820 // R[t] = bits(32) UNKNOWN;
6821 WriteBits32Unknown(t);
6827 // LDRH (literal) calculates an address from a base register value and an offset
6828 // register value, loads a halfword
6829 // from memory, zero-extends it to form a 32-bit word, and writes it to a
6830 // register. The offset register value can
6831 // be shifted left by 0, 1, 2, or 3 bits.
6832 bool EmulateInstructionARM::EmulateLDRHRegister(const uint32_t opcode,
6833 const ARMEncoding encoding) {
6835 if ConditionPassed() then
6836 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
6837 offset = Shift(R[m], shift_t, shift_n, APSR.C);
6838 offset_addr = if add then (R[n] + offset) else (R[n] - offset);
6839 address = if index then offset_addr else R[n];
6840 data = MemU[address,2];
6841 if wback then R[n] = offset_addr;
6842 if UnalignedSupport() || address<0> = '0' then
6843 R[t] = ZeroExtend(data, 32);
6844 else // Can only apply before ARMv7
6845 R[t] = bits(32) UNKNOWN;
6848 bool success = false;
6850 if (ConditionPassed(opcode)) {
6857 ARM_ShifterType shift_t;
6860 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
6863 // if CurrentInstrSet() == InstrSet_ThumbEE then SEE "Modified operation
6865 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
6866 t = Bits32(opcode, 2, 0);
6867 n = Bits32(opcode, 5, 3);
6868 m = Bits32(opcode, 8, 6);
6870 // index = TRUE; add = TRUE; wback = FALSE;
6875 // (shift_t, shift_n) = (SRType_LSL, 0);
6876 shift_t = SRType_LSL;
6882 // if Rn == '1111' then SEE LDRH (literal);
6883 // if Rt == '1111' then SEE "Unallocated memory hints";
6884 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
6885 t = Bits32(opcode, 15, 12);
6886 n = Bits32(opcode, 19, 16);
6887 m = Bits32(opcode, 3, 0);
6889 // index = TRUE; add = TRUE; wback = FALSE;
6894 // (shift_t, shift_n) = (SRType_LSL, UInt(imm2));
6895 shift_t = SRType_LSL;
6896 shift_n = Bits32(opcode, 5, 4);
6898 // if t == 13 || BadReg(m) then UNPREDICTABLE;
6899 if ((t == 13) || BadReg(m))
6904 // if P == '0' && W == '1' then SEE LDRHT;
6905 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
6906 t = Bits32(opcode, 15, 12);
6907 n = Bits32(opcode, 19, 16);
6908 m = Bits32(opcode, 3, 0);
6910 // index = (P == '1'); add = (U == '1'); wback = (P == '0') ||
6912 index = BitIsSet(opcode, 24);
6913 add = BitIsSet(opcode, 23);
6914 wback = (BitIsClear(opcode, 24) || BitIsSet(opcode, 21));
6916 // (shift_t, shift_n) = (SRType_LSL, 0);
6917 shift_t = SRType_LSL;
6920 // if t == 15 || m == 15 then UNPREDICTABLE;
6921 if ((t == 15) || (m == 15))
6924 // if wback && (n == 15 || n == t) then UNPREDICTABLE;
6925 if (wback && ((n == 15) || (n == t)))
6934 // offset = Shift(R[m], shift_t, shift_n, APSR.C);
6937 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
6941 addr_t offset = Shift(Rm, shift_t, shift_n, APSR_C, &success);
6948 // offset_addr = if add then (R[n] + offset) else (R[n] - offset);
6950 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
6955 offset_addr = Rn + offset;
6957 offset_addr = Rn - offset;
6959 // address = if index then offset_addr else R[n];
6961 address = offset_addr;
6965 // data = MemU[address,2];
6966 RegisterInfo base_reg;
6967 RegisterInfo offset_reg;
6968 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n, base_reg);
6969 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + m, offset_reg);
6971 EmulateInstruction::Context context;
6972 context.type = eContextRegisterLoad;
6973 context.SetRegisterPlusIndirectOffset(base_reg, offset_reg);
6974 uint64_t data = MemURead(context, address, 2, 0, &success);
6978 // if wback then R[n] = offset_addr;
6980 context.type = eContextAdjustBaseRegister;
6981 context.SetAddress(offset_addr);
6982 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n,
6987 // if UnalignedSupport() || address<0> = '0' then
6988 if (UnalignedSupport() || BitIsClear(address, 0)) {
6989 // R[t] = ZeroExtend(data, 32);
6990 context.type = eContextRegisterLoad;
6991 context.SetRegisterPlusIndirectOffset(base_reg, offset_reg);
6992 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + t,
6995 } else // Can only apply before ARMv7
6997 // R[t] = bits(32) UNKNOWN;
6998 WriteBits32Unknown(t);
7004 // LDRSB (immediate) calculates an address from a base register value and an
7005 // immediate offset, loads a byte from
7006 // memory, sign-extends it to form a 32-bit word, and writes it to a register.
7007 // It can use offset, post-indexed,
7008 // or pre-indexed addressing.
7009 bool EmulateInstructionARM::EmulateLDRSBImmediate(const uint32_t opcode,
7010 const ARMEncoding encoding) {
7012 if ConditionPassed() then
7013 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
7014 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
7015 address = if index then offset_addr else R[n];
7016 R[t] = SignExtend(MemU[address,1], 32);
7017 if wback then R[n] = offset_addr;
7020 bool success = false;
7022 if (ConditionPassed(opcode)) {
7030 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
7033 // if Rt == '1111' then SEE PLI;
7034 // if Rn == '1111' then SEE LDRSB (literal);
7035 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
7036 t = Bits32(opcode, 15, 12);
7037 n = Bits32(opcode, 19, 16);
7038 imm32 = Bits32(opcode, 11, 0);
7040 // index = TRUE; add = TRUE; wback = FALSE;
7045 // if t == 13 then UNPREDICTABLE;
7052 // if Rt == '1111' && P == '1' && U == '0' && W == '0' then SEE PLI;
7053 // if Rn == '1111' then SEE LDRSB (literal);
7054 // if P == '1' && U == '1' && W == '0' then SEE LDRSBT;
7055 // if P == '0' && W == '0' then UNDEFINED;
7056 if (BitIsClear(opcode, 10) && BitIsClear(opcode, 8))
7059 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32);
7060 t = Bits32(opcode, 15, 12);
7061 n = Bits32(opcode, 19, 16);
7062 imm32 = Bits32(opcode, 7, 0);
7064 // index = (P == '1'); add = (U == '1'); wback = (W == '1');
7065 index = BitIsSet(opcode, 10);
7066 add = BitIsSet(opcode, 9);
7067 wback = BitIsSet(opcode, 8);
7069 // if BadReg(t) || (wback && n == t) then UNPREDICTABLE;
7071 ((t == 15) && (BitIsClear(opcode, 10) || BitIsSet(opcode, 9) ||
7072 BitIsSet(opcode, 8)))) ||
7073 (wback && (n == t)))
7079 // if Rn == '1111' then SEE LDRSB (literal);
7080 // if P == '0' && W == '1' then SEE LDRSBT;
7081 // t == UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm4H:imm4L, 32);
7082 t = Bits32(opcode, 15, 12);
7083 n = Bits32(opcode, 19, 16);
7085 uint32_t imm4H = Bits32(opcode, 11, 8);
7086 uint32_t imm4L = Bits32(opcode, 3, 0);
7087 imm32 = (imm4H << 4) | imm4L;
7089 // index = (P == '1'); add = (U == '1'); wback = (P == '0') ||
7091 index = BitIsSet(opcode, 24);
7092 add = BitIsSet(opcode, 23);
7093 wback = (BitIsClear(opcode, 24) || BitIsSet(opcode, 21));
7095 // if t == 15 || (wback && n == t) then UNPREDICTABLE;
7096 if ((t == 15) || (wback && (n == t)))
7106 uint64_t Rn = ReadCoreReg(n, &success);
7113 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
7115 offset_addr = Rn + imm32;
7117 offset_addr = Rn - imm32;
7119 // address = if index then offset_addr else R[n];
7121 address = offset_addr;
7125 // R[t] = SignExtend(MemU[address,1], 32);
7126 RegisterInfo base_reg;
7127 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n, base_reg);
7129 EmulateInstruction::Context context;
7130 context.type = eContextRegisterLoad;
7131 context.SetRegisterPlusOffset(base_reg, address - Rn);
7133 uint64_t unsigned_data = MemURead(context, address, 1, 0, &success);
7137 int64_t signed_data = llvm::SignExtend64<8>(unsigned_data);
7138 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + t,
7139 (uint64_t)signed_data))
7142 // if wback then R[n] = offset_addr;
7144 context.type = eContextAdjustBaseRegister;
7145 context.SetAddress(offset_addr);
7146 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n,
7155 // LDRSB (literal) calculates an address from the PC value and an immediate
7156 // offset, loads a byte from memory,
7157 // sign-extends it to form a 32-bit word, and writes tit to a register.
7158 bool EmulateInstructionARM::EmulateLDRSBLiteral(const uint32_t opcode,
7159 const ARMEncoding encoding) {
7161 if ConditionPassed() then
7162 EncodingSpecificOperations(); NullCheckIfThumbEE(15);
7164 address = if add then (base + imm32) else (base - imm32);
7165 R[t] = SignExtend(MemU[address,1], 32);
7168 bool success = false;
7170 if (ConditionPassed(opcode)) {
7175 // EncodingSpecificOperations(); NullCheckIfThumbEE(15);
7178 // if Rt == '1111' then SEE PLI;
7179 // t = UInt(Rt); imm32 = ZeroExtend(imm12, 32); add = (U == '1');
7180 t = Bits32(opcode, 15, 12);
7181 imm32 = Bits32(opcode, 11, 0);
7182 add = BitIsSet(opcode, 23);
7184 // if t == 13 then UNPREDICTABLE;
7191 // t == UInt(Rt); imm32 = ZeroExtend(imm4H:imm4L, 32); add = (U == '1');
7192 t = Bits32(opcode, 15, 12);
7193 uint32_t imm4H = Bits32(opcode, 11, 8);
7194 uint32_t imm4L = Bits32(opcode, 3, 0);
7195 imm32 = (imm4H << 4) | imm4L;
7196 add = BitIsSet(opcode, 23);
7198 // if t == 15 then UNPREDICTABLE;
7209 // base = Align(PC,4);
7210 uint64_t pc_value = ReadCoreReg(PC_REG, &success);
7213 uint64_t base = AlignPC(pc_value);
7215 // address = if add then (base + imm32) else (base - imm32);
7218 address = base + imm32;
7220 address = base - imm32;
7222 // R[t] = SignExtend(MemU[address,1], 32);
7223 RegisterInfo base_reg;
7224 GetRegisterInfo(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, base_reg);
7226 EmulateInstruction::Context context;
7227 context.type = eContextRegisterLoad;
7228 context.SetRegisterPlusOffset(base_reg, address - base);
7230 uint64_t unsigned_data = MemURead(context, address, 1, 0, &success);
7234 int64_t signed_data = llvm::SignExtend64<8>(unsigned_data);
7235 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + t,
7236 (uint64_t)signed_data))
7242 // LDRSB (register) calculates an address from a base register value and an
7243 // offset register value, loadsa byte from
7244 // memory, sign-extends it to form a 32-bit word, and writes it to a register.
7245 // The offset register value can be
7246 // shifted left by 0, 1, 2, or 3 bits.
7247 bool EmulateInstructionARM::EmulateLDRSBRegister(const uint32_t opcode,
7248 const ARMEncoding encoding) {
7250 if ConditionPassed() then
7251 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
7252 offset = Shift(R[m], shift_t, shift_n, APSR.C);
7253 offset_addr = if add then (R[n] + offset) else (R[n] - offset);
7254 address = if index then offset_addr else R[n];
7255 R[t] = SignExtend(MemU[address,1], 32);
7256 if wback then R[n] = offset_addr;
7259 bool success = false;
7261 if (ConditionPassed(opcode)) {
7268 ARM_ShifterType shift_t;
7271 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
7274 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
7275 t = Bits32(opcode, 2, 0);
7276 n = Bits32(opcode, 5, 3);
7277 m = Bits32(opcode, 8, 6);
7279 // index = TRUE; add = TRUE; wback = FALSE;
7284 // (shift_t, shift_n) = (SRType_LSL, 0);
7285 shift_t = SRType_LSL;
7291 // if Rt == '1111' then SEE PLI;
7292 // if Rn == '1111' then SEE LDRSB (literal);
7293 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
7294 t = Bits32(opcode, 15, 12);
7295 n = Bits32(opcode, 19, 16);
7296 m = Bits32(opcode, 3, 0);
7298 // index = TRUE; add = TRUE; wback = FALSE;
7303 // (shift_t, shift_n) = (SRType_LSL, UInt(imm2));
7304 shift_t = SRType_LSL;
7305 shift_n = Bits32(opcode, 5, 4);
7307 // if t == 13 || BadReg(m) then UNPREDICTABLE;
7308 if ((t == 13) || BadReg(m))
7313 // if P == '0' && W == '1' then SEE LDRSBT;
7314 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
7315 t = Bits32(opcode, 15, 12);
7316 n = Bits32(opcode, 19, 16);
7317 m = Bits32(opcode, 3, 0);
7319 // index = (P == '1'); add = (U == '1'); wback = (P == '0') ||
7321 index = BitIsSet(opcode, 24);
7322 add = BitIsSet(opcode, 23);
7323 wback = BitIsClear(opcode, 24) || BitIsSet(opcode, 21);
7325 // (shift_t, shift_n) = (SRType_LSL, 0);
7326 shift_t = SRType_LSL;
7329 // if t == 15 || m == 15 then UNPREDICTABLE;
7330 if ((t == 15) || (m == 15))
7333 // if wback && (n == 15 || n == t) then UNPREDICTABLE;
7334 if (wback && ((n == 15) || (n == t)))
7343 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
7347 // offset = Shift(R[m], shift_t, shift_n, APSR.C);
7348 addr_t offset = Shift(Rm, shift_t, shift_n, APSR_C, &success);
7355 // offset_addr = if add then (R[n] + offset) else (R[n] - offset);
7357 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
7362 offset_addr = Rn + offset;
7364 offset_addr = Rn - offset;
7366 // address = if index then offset_addr else R[n];
7368 address = offset_addr;
7372 // R[t] = SignExtend(MemU[address,1], 32);
7373 RegisterInfo base_reg;
7374 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n, base_reg);
7375 RegisterInfo offset_reg;
7376 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + m, offset_reg);
7378 EmulateInstruction::Context context;
7379 context.type = eContextRegisterLoad;
7380 context.SetRegisterPlusIndirectOffset(base_reg, offset_reg);
7382 uint64_t unsigned_data = MemURead(context, address, 1, 0, &success);
7386 int64_t signed_data = llvm::SignExtend64<8>(unsigned_data);
7387 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + t,
7388 (uint64_t)signed_data))
7391 // if wback then R[n] = offset_addr;
7393 context.type = eContextAdjustBaseRegister;
7394 context.SetAddress(offset_addr);
7395 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n,
7403 // LDRSH (immediate) calculates an address from a base register value and an
7404 // immediate offset, loads a halfword from
7405 // memory, sign-extends it to form a 32-bit word, and writes it to a register.
7406 // It can use offset, post-indexed, or
7407 // pre-indexed addressing.
7408 bool EmulateInstructionARM::EmulateLDRSHImmediate(const uint32_t opcode,
7409 const ARMEncoding encoding) {
7411 if ConditionPassed() then
7412 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
7413 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
7414 address = if index then offset_addr else R[n];
7415 data = MemU[address,2];
7416 if wback then R[n] = offset_addr;
7417 if UnalignedSupport() || address<0> = '0' then
7418 R[t] = SignExtend(data, 32);
7419 else // Can only apply before ARMv7
7420 R[t] = bits(32) UNKNOWN;
7423 bool success = false;
7425 if (ConditionPassed(opcode)) {
7433 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
7436 // if Rn == '1111' then SEE LDRSH (literal);
7437 // if Rt == '1111' then SEE "Unallocated memory hints";
7438 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
7439 t = Bits32(opcode, 15, 12);
7440 n = Bits32(opcode, 19, 16);
7441 imm32 = Bits32(opcode, 11, 0);
7443 // index = TRUE; add = TRUE; wback = FALSE;
7448 // if t == 13 then UNPREDICTABLE;
7455 // if Rn == '1111' then SEE LDRSH (literal);
7456 // if Rt == '1111' && P == '1' && U == '0' && W == '0' then SEE
7457 // "Unallocated memory hints";
7458 // if P == '1' && U == '1' && W == '0' then SEE LDRSHT;
7459 // if P == '0' && W == '0' then UNDEFINED;
7460 if (BitIsClear(opcode, 10) && BitIsClear(opcode, 8))
7463 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32);
7464 t = Bits32(opcode, 15, 12);
7465 n = Bits32(opcode, 19, 16);
7466 imm32 = Bits32(opcode, 7, 0);
7468 // index = (P == '1'); add = (U == '1'); wback = (W == '1');
7469 index = BitIsSet(opcode, 10);
7470 add = BitIsSet(opcode, 9);
7471 wback = BitIsSet(opcode, 8);
7473 // if BadReg(t) || (wback && n == t) then UNPREDICTABLE;
7474 if (BadReg(t) || (wback && (n == t)))
7480 // if Rn == '1111' then SEE LDRSH (literal);
7481 // if P == '0' && W == '1' then SEE LDRSHT;
7482 // t == UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm4H:imm4L, 32);
7483 t = Bits32(opcode, 15, 12);
7484 n = Bits32(opcode, 19, 16);
7485 uint32_t imm4H = Bits32(opcode, 11, 8);
7486 uint32_t imm4L = Bits32(opcode, 3, 0);
7487 imm32 = (imm4H << 4) | imm4L;
7489 // index = (P == '1'); add = (U == '1'); wback = (P == '0') ||
7491 index = BitIsSet(opcode, 24);
7492 add = BitIsSet(opcode, 23);
7493 wback = BitIsClear(opcode, 24) || BitIsSet(opcode, 21);
7495 // if t == 15 || (wback && n == t) then UNPREDICTABLE;
7496 if ((t == 15) || (wback && (n == t)))
7506 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
7508 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
7514 offset_addr = Rn + imm32;
7516 offset_addr = Rn - imm32;
7518 // address = if index then offset_addr else R[n];
7521 address = offset_addr;
7525 // data = MemU[address,2];
7526 RegisterInfo base_reg;
7527 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n, base_reg);
7529 EmulateInstruction::Context context;
7530 context.type = eContextRegisterLoad;
7531 context.SetRegisterPlusOffset(base_reg, address - Rn);
7533 uint64_t data = MemURead(context, address, 2, 0, &success);
7537 // if wback then R[n] = offset_addr;
7539 context.type = eContextAdjustBaseRegister;
7540 context.SetAddress(offset_addr);
7541 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n,
7546 // if UnalignedSupport() || address<0> = '0' then
7547 if (UnalignedSupport() || BitIsClear(address, 0)) {
7548 // R[t] = SignExtend(data, 32);
7549 int64_t signed_data = llvm::SignExtend64<16>(data);
7550 context.type = eContextRegisterLoad;
7551 context.SetRegisterPlusOffset(base_reg, address - Rn);
7552 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + t,
7553 (uint64_t)signed_data))
7555 } else // Can only apply before ARMv7
7557 // R[t] = bits(32) UNKNOWN;
7558 WriteBits32Unknown(t);
7564 // LDRSH (literal) calculates an address from the PC value and an immediate
7565 // offset, loads a halfword from memory,
7566 // sign-extends it to from a 32-bit word, and writes it to a register.
7567 bool EmulateInstructionARM::EmulateLDRSHLiteral(const uint32_t opcode,
7568 const ARMEncoding encoding) {
7570 if ConditionPassed() then
7571 EncodingSpecificOperations(); NullCheckIfThumbEE(15);
7573 address = if add then (base + imm32) else (base - imm32);
7574 data = MemU[address,2];
7575 if UnalignedSupport() || address<0> = '0' then
7576 R[t] = SignExtend(data, 32);
7577 else // Can only apply before ARMv7
7578 R[t] = bits(32) UNKNOWN;
7581 bool success = false;
7583 if (ConditionPassed(opcode)) {
7588 // EncodingSpecificOperations(); NullCheckIfThumbEE(15);
7591 // if Rt == '1111' then SEE "Unallocated memory hints";
7592 // t = UInt(Rt); imm32 = ZeroExtend(imm12, 32); add = (U == '1');
7593 t = Bits32(opcode, 15, 12);
7594 imm32 = Bits32(opcode, 11, 0);
7595 add = BitIsSet(opcode, 23);
7597 // if t == 13 then UNPREDICTABLE;
7604 // t == UInt(Rt); imm32 = ZeroExtend(imm4H:imm4L, 32); add = (U == '1');
7605 t = Bits32(opcode, 15, 12);
7606 uint32_t imm4H = Bits32(opcode, 11, 8);
7607 uint32_t imm4L = Bits32(opcode, 3, 0);
7608 imm32 = (imm4H << 4) | imm4L;
7609 add = BitIsSet(opcode, 23);
7611 // if t == 15 then UNPREDICTABLE;
7621 // base = Align(PC,4);
7622 uint64_t pc_value = ReadCoreReg(PC_REG, &success);
7626 uint64_t base = AlignPC(pc_value);
7629 // address = if add then (base + imm32) else (base - imm32);
7631 address = base + imm32;
7633 address = base - imm32;
7635 // data = MemU[address,2];
7636 RegisterInfo base_reg;
7637 GetRegisterInfo(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, base_reg);
7639 EmulateInstruction::Context context;
7640 context.type = eContextRegisterLoad;
7641 context.SetRegisterPlusOffset(base_reg, imm32);
7643 uint64_t data = MemURead(context, address, 2, 0, &success);
7647 // if UnalignedSupport() || address<0> = '0' then
7648 if (UnalignedSupport() || BitIsClear(address, 0)) {
7649 // R[t] = SignExtend(data, 32);
7650 int64_t signed_data = llvm::SignExtend64<16>(data);
7651 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + t,
7652 (uint64_t)signed_data))
7654 } else // Can only apply before ARMv7
7656 // R[t] = bits(32) UNKNOWN;
7657 WriteBits32Unknown(t);
7663 // LDRSH (register) calculates an address from a base register value and an
7664 // offset register value, loads a halfword
7665 // from memory, sign-extends it to form a 32-bit word, and writes it to a
7666 // register. The offset register value can be
7667 // shifted left by 0, 1, 2, or 3 bits.
7668 bool EmulateInstructionARM::EmulateLDRSHRegister(const uint32_t opcode,
7669 const ARMEncoding encoding) {
7671 if ConditionPassed() then
7672 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
7673 offset = Shift(R[m], shift_t, shift_n, APSR.C);
7674 offset_addr = if add then (R[n] + offset) else (R[n] - offset);
7675 address = if index then offset_addr else R[n];
7676 data = MemU[address,2];
7677 if wback then R[n] = offset_addr;
7678 if UnalignedSupport() || address<0> = '0' then
7679 R[t] = SignExtend(data, 32);
7680 else // Can only apply before ARMv7
7681 R[t] = bits(32) UNKNOWN;
7684 bool success = false;
7686 if (ConditionPassed(opcode)) {
7693 ARM_ShifterType shift_t;
7696 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
7699 // if CurrentInstrSet() == InstrSet_ThumbEE then SEE "Modified operation
7701 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
7702 t = Bits32(opcode, 2, 0);
7703 n = Bits32(opcode, 5, 3);
7704 m = Bits32(opcode, 8, 6);
7706 // index = TRUE; add = TRUE; wback = FALSE;
7711 // (shift_t, shift_n) = (SRType_LSL, 0);
7712 shift_t = SRType_LSL;
7718 // if Rn == '1111' then SEE LDRSH (literal);
7719 // if Rt == '1111' then SEE "Unallocated memory hints";
7720 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
7721 t = Bits32(opcode, 15, 12);
7722 n = Bits32(opcode, 19, 16);
7723 m = Bits32(opcode, 3, 0);
7725 // index = TRUE; add = TRUE; wback = FALSE;
7730 // (shift_t, shift_n) = (SRType_LSL, UInt(imm2));
7731 shift_t = SRType_LSL;
7732 shift_n = Bits32(opcode, 5, 4);
7734 // if t == 13 || BadReg(m) then UNPREDICTABLE;
7735 if ((t == 13) || BadReg(m))
7741 // if P == '0' && W == '1' then SEE LDRSHT;
7742 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
7743 t = Bits32(opcode, 15, 12);
7744 n = Bits32(opcode, 19, 16);
7745 m = Bits32(opcode, 3, 0);
7747 // index = (P == '1'); add = (U == '1'); wback = (P == '0') ||
7749 index = BitIsSet(opcode, 24);
7750 add = BitIsSet(opcode, 23);
7751 wback = BitIsClear(opcode, 24) || BitIsSet(opcode, 21);
7753 // (shift_t, shift_n) = (SRType_LSL, 0);
7754 shift_t = SRType_LSL;
7757 // if t == 15 || m == 15 then UNPREDICTABLE;
7758 if ((t == 15) || (m == 15))
7761 // if wback && (n == 15 || n == t) then UNPREDICTABLE;
7762 if (wback && ((n == 15) || (n == t)))
7772 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
7777 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
7781 // offset = Shift(R[m], shift_t, shift_n, APSR.C);
7782 addr_t offset = Shift(Rm, shift_t, shift_n, APSR_C, &success);
7789 // offset_addr = if add then (R[n] + offset) else (R[n] - offset);
7791 offset_addr = Rn + offset;
7793 offset_addr = Rn - offset;
7795 // address = if index then offset_addr else R[n];
7797 address = offset_addr;
7801 // data = MemU[address,2];
7802 RegisterInfo base_reg;
7803 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n, base_reg);
7805 RegisterInfo offset_reg;
7806 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + m, offset_reg);
7808 EmulateInstruction::Context context;
7809 context.type = eContextRegisterLoad;
7810 context.SetRegisterPlusIndirectOffset(base_reg, offset_reg);
7812 uint64_t data = MemURead(context, address, 2, 0, &success);
7816 // if wback then R[n] = offset_addr;
7818 context.type = eContextAdjustBaseRegister;
7819 context.SetAddress(offset_addr);
7820 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n,
7825 // if UnalignedSupport() || address<0> = '0' then
7826 if (UnalignedSupport() || BitIsClear(address, 0)) {
7827 // R[t] = SignExtend(data, 32);
7828 context.type = eContextRegisterLoad;
7829 context.SetRegisterPlusIndirectOffset(base_reg, offset_reg);
7831 int64_t signed_data = llvm::SignExtend64<16>(data);
7832 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + t,
7833 (uint64_t)signed_data))
7835 } else // Can only apply before ARMv7
7837 // R[t] = bits(32) UNKNOWN;
7838 WriteBits32Unknown(t);
7844 // SXTB extracts an 8-bit value from a register, sign-extends it to 32 bits, and
7845 // writes the result to the destination
7846 // register. You can specifiy a rotation by 0, 8, 16, or 24 bits before
7847 // extracting the 8-bit value.
7848 bool EmulateInstructionARM::EmulateSXTB(const uint32_t opcode,
7849 const ARMEncoding encoding) {
7851 if ConditionPassed() then
7852 EncodingSpecificOperations();
7853 rotated = ROR(R[m], rotation);
7854 R[d] = SignExtend(rotated<7:0>, 32);
7857 bool success = false;
7859 if (ConditionPassed(opcode)) {
7864 // EncodingSpecificOperations();
7867 // d = UInt(Rd); m = UInt(Rm); rotation = 0;
7868 d = Bits32(opcode, 2, 0);
7869 m = Bits32(opcode, 5, 3);
7875 // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:'000');
7876 d = Bits32(opcode, 11, 8);
7877 m = Bits32(opcode, 3, 0);
7878 rotation = Bits32(opcode, 5, 4) << 3;
7880 // if BadReg(d) || BadReg(m) then UNPREDICTABLE;
7881 if (BadReg(d) || BadReg(m))
7887 // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:'000');
7888 d = Bits32(opcode, 15, 12);
7889 m = Bits32(opcode, 3, 0);
7890 rotation = Bits32(opcode, 11, 10) << 3;
7892 // if d == 15 || m == 15 then UNPREDICTABLE;
7893 if ((d == 15) || (m == 15))
7903 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
7907 // rotated = ROR(R[m], rotation);
7908 uint64_t rotated = ROR(Rm, rotation, &success);
7912 // R[d] = SignExtend(rotated<7:0>, 32);
7913 int64_t data = llvm::SignExtend64<8>(rotated);
7915 RegisterInfo source_reg;
7916 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + m, source_reg);
7918 EmulateInstruction::Context context;
7919 context.type = eContextRegisterLoad;
7920 context.SetRegister(source_reg);
7922 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + d,
7929 // SXTH extracts a 16-bit value from a register, sign-extends it to 32 bits, and
7930 // writes the result to the destination
7931 // register. You can specify a rotation by 0, 8, 16, or 24 bits before
7932 // extracting the 16-bit value.
7933 bool EmulateInstructionARM::EmulateSXTH(const uint32_t opcode,
7934 const ARMEncoding encoding) {
7936 if ConditionPassed() then
7937 EncodingSpecificOperations();
7938 rotated = ROR(R[m], rotation);
7939 R[d] = SignExtend(rotated<15:0>, 32);
7942 bool success = false;
7944 if (ConditionPassed(opcode)) {
7949 // EncodingSpecificOperations();
7952 // d = UInt(Rd); m = UInt(Rm); rotation = 0;
7953 d = Bits32(opcode, 2, 0);
7954 m = Bits32(opcode, 5, 3);
7960 // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:'000');
7961 d = Bits32(opcode, 11, 8);
7962 m = Bits32(opcode, 3, 0);
7963 rotation = Bits32(opcode, 5, 4) << 3;
7965 // if BadReg(d) || BadReg(m) then UNPREDICTABLE;
7966 if (BadReg(d) || BadReg(m))
7972 // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:'000');
7973 d = Bits32(opcode, 15, 12);
7974 m = Bits32(opcode, 3, 0);
7975 rotation = Bits32(opcode, 11, 10) << 3;
7977 // if d == 15 || m == 15 then UNPREDICTABLE;
7978 if ((d == 15) || (m == 15))
7988 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
7992 // rotated = ROR(R[m], rotation);
7993 uint64_t rotated = ROR(Rm, rotation, &success);
7997 // R[d] = SignExtend(rotated<15:0>, 32);
7998 RegisterInfo source_reg;
7999 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + m, source_reg);
8001 EmulateInstruction::Context context;
8002 context.type = eContextRegisterLoad;
8003 context.SetRegister(source_reg);
8005 int64_t data = llvm::SignExtend64<16>(rotated);
8006 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + d,
8014 // UXTB extracts an 8-bit value from a register, zero-extneds it to 32 bits, and
8015 // writes the result to the destination
8016 // register. You can specify a rotation by 0, 8, 16, or 24 bits before
8017 // extracting the 8-bit value.
8018 bool EmulateInstructionARM::EmulateUXTB(const uint32_t opcode,
8019 const ARMEncoding encoding) {
8021 if ConditionPassed() then
8022 EncodingSpecificOperations();
8023 rotated = ROR(R[m], rotation);
8024 R[d] = ZeroExtend(rotated<7:0>, 32);
8027 bool success = false;
8029 if (ConditionPassed(opcode)) {
8034 // EncodingSpecificOperations();
8037 // d = UInt(Rd); m = UInt(Rm); rotation = 0;
8038 d = Bits32(opcode, 2, 0);
8039 m = Bits32(opcode, 5, 3);
8045 // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:'000');
8046 d = Bits32(opcode, 11, 8);
8047 m = Bits32(opcode, 3, 0);
8048 rotation = Bits32(opcode, 5, 4) << 3;
8050 // if BadReg(d) || BadReg(m) then UNPREDICTABLE;
8051 if (BadReg(d) || BadReg(m))
8057 // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:'000');
8058 d = Bits32(opcode, 15, 12);
8059 m = Bits32(opcode, 3, 0);
8060 rotation = Bits32(opcode, 11, 10) << 3;
8062 // if d == 15 || m == 15 then UNPREDICTABLE;
8063 if ((d == 15) || (m == 15))
8073 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
8077 // rotated = ROR(R[m], rotation);
8078 uint64_t rotated = ROR(Rm, rotation, &success);
8082 // R[d] = ZeroExtend(rotated<7:0>, 32);
8083 RegisterInfo source_reg;
8084 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + m, source_reg);
8086 EmulateInstruction::Context context;
8087 context.type = eContextRegisterLoad;
8088 context.SetRegister(source_reg);
8090 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + d,
8091 Bits32(rotated, 7, 0)))
8097 // UXTH extracts a 16-bit value from a register, zero-extends it to 32 bits, and
8098 // writes the result to the destination
8099 // register. You can specify a rotation by 0, 8, 16, or 24 bits before
8100 // extracting the 16-bit value.
8101 bool EmulateInstructionARM::EmulateUXTH(const uint32_t opcode,
8102 const ARMEncoding encoding) {
8104 if ConditionPassed() then
8105 EncodingSpecificOperations();
8106 rotated = ROR(R[m], rotation);
8107 R[d] = ZeroExtend(rotated<15:0>, 32);
8110 bool success = false;
8112 if (ConditionPassed(opcode)) {
8119 // d = UInt(Rd); m = UInt(Rm); rotation = 0;
8120 d = Bits32(opcode, 2, 0);
8121 m = Bits32(opcode, 5, 3);
8127 // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:'000');
8128 d = Bits32(opcode, 11, 8);
8129 m = Bits32(opcode, 3, 0);
8130 rotation = Bits32(opcode, 5, 4) << 3;
8132 // if BadReg(d) || BadReg(m) then UNPREDICTABLE;
8133 if (BadReg(d) || BadReg(m))
8139 // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:'000');
8140 d = Bits32(opcode, 15, 12);
8141 m = Bits32(opcode, 3, 0);
8142 rotation = Bits32(opcode, 11, 10) << 3;
8144 // if d == 15 || m == 15 then UNPREDICTABLE;
8145 if ((d == 15) || (m == 15))
8155 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
8159 // rotated = ROR(R[m], rotation);
8160 uint64_t rotated = ROR(Rm, rotation, &success);
8164 // R[d] = ZeroExtend(rotated<15:0>, 32);
8165 RegisterInfo source_reg;
8166 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + m, source_reg);
8168 EmulateInstruction::Context context;
8169 context.type = eContextRegisterLoad;
8170 context.SetRegister(source_reg);
8172 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + d,
8173 Bits32(rotated, 15, 0)))
8179 // RFE (Return From Exception) loads the PC and the CPSR from the word at the
8180 // specified address and the following
8181 // word respectively.
8182 bool EmulateInstructionARM::EmulateRFE(const uint32_t opcode,
8183 const ARMEncoding encoding) {
8185 if ConditionPassed() then
8186 EncodingSpecificOperations();
8187 if !CurrentModeIsPrivileged() || CurrentInstrSet() == InstrSet_ThumbEE then
8190 address = if increment then R[n] else R[n]-8;
8191 if wordhigher then address = address+4;
8192 CPSRWriteByInstr(MemA[address+4,4], '1111', TRUE);
8193 BranchWritePC(MemA[address,4]);
8194 if wback then R[n] = if increment then R[n]+8 else R[n]-8;
8197 bool success = false;
8199 if (ConditionPassed(opcode)) {
8205 // EncodingSpecificOperations();
8208 // n = UInt(Rn); wback = (W == '1'); increment = FALSE; wordhigher =
8210 n = Bits32(opcode, 19, 16);
8211 wback = BitIsSet(opcode, 21);
8215 // if n == 15 then UNPREDICTABLE;
8219 // if InITBlock() && !LastInITBlock() then UNPREDICTABLE;
8220 if (InITBlock() && !LastInITBlock())
8226 // n = UInt(Rn); wback = (W == '1'); increment = TRUE; wordhigher = FALSE;
8227 n = Bits32(opcode, 19, 16);
8228 wback = BitIsSet(opcode, 21);
8232 // if n == 15 then UNPREDICTABLE;
8236 // if InITBlock() && !LastInITBlock() then UNPREDICTABLE;
8237 if (InITBlock() && !LastInITBlock())
8244 n = Bits32(opcode, 19, 16);
8246 // wback = (W == '1'); inc = (U == '1'); wordhigher = (P == U);
8247 wback = BitIsSet(opcode, 21);
8248 increment = BitIsSet(opcode, 23);
8249 wordhigher = (Bit32(opcode, 24) == Bit32(opcode, 23));
8251 // if n == 15 then UNPREDICTABLE;
8261 // if !CurrentModeIsPrivileged() || CurrentInstrSet() == InstrSet_ThumbEE
8263 if (!CurrentModeIsPrivileged())
8268 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
8273 // address = if increment then R[n] else R[n]-8;
8279 // if wordhigher then address = address+4;
8281 address = address + 4;
8283 // CPSRWriteByInstr(MemA[address+4,4], '1111', TRUE);
8284 RegisterInfo base_reg;
8285 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n, base_reg);
8287 EmulateInstruction::Context context;
8288 context.type = eContextReturnFromException;
8289 context.SetRegisterPlusOffset(base_reg, address - Rn);
8291 uint64_t data = MemARead(context, address + 4, 4, 0, &success);
8295 CPSRWriteByInstr(data, 15, true);
8297 // BranchWritePC(MemA[address,4]);
8298 uint64_t data2 = MemARead(context, address, 4, 0, &success);
8302 BranchWritePC(context, data2);
8304 // if wback then R[n] = if increment then R[n]+8 else R[n]-8;
8306 context.type = eContextAdjustBaseRegister;
8308 context.SetOffset(8);
8309 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n,
8313 context.SetOffset(-8);
8314 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n,
8320 } // if ConditionPassed()
8324 // Bitwise Exclusive OR (immediate) performs a bitwise exclusive OR of a
8325 // register value and an immediate value,
8326 // and writes the result to the destination register. It can optionally update
8327 // the condition flags based on
8329 bool EmulateInstructionARM::EmulateEORImm(const uint32_t opcode,
8330 const ARMEncoding encoding) {
8332 // ARM pseudo code...
8333 if ConditionPassed() then
8334 EncodingSpecificOperations();
8335 result = R[n] EOR imm32;
8336 if d == 15 then // Can only occur for ARM encoding
8337 ALUWritePC(result); // setflags is always FALSE here
8341 APSR.N = result<31>;
8342 APSR.Z = IsZeroBit(result);
8347 bool success = false;
8349 if (ConditionPassed(opcode)) {
8352 imm32; // the immediate value to be ORed to the value obtained from Rn
8354 uint32_t carry; // the carry bit after ARM/Thumb Expand operation
8357 Rd = Bits32(opcode, 11, 8);
8358 Rn = Bits32(opcode, 19, 16);
8359 setflags = BitIsSet(opcode, 20);
8360 imm32 = ThumbExpandImm_C(
8362 carry); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C)
8363 // if Rd == '1111' && S == '1' then SEE TEQ (immediate);
8364 if (Rd == 15 && setflags)
8365 return EmulateTEQImm(opcode, eEncodingT1);
8366 if (Rd == 13 || (Rd == 15 && !setflags) || BadReg(Rn))
8370 Rd = Bits32(opcode, 15, 12);
8371 Rn = Bits32(opcode, 19, 16);
8372 setflags = BitIsSet(opcode, 20);
8374 ARMExpandImm_C(opcode, APSR_C,
8375 carry); // (imm32, carry) = ARMExpandImm(imm12, APSR.C)
8377 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related
8379 if (Rd == 15 && setflags)
8380 return EmulateSUBSPcLrEtc(opcode, encoding);
8386 // Read the first operand.
8387 uint32_t val1 = ReadCoreReg(Rn, &success);
8391 uint32_t result = val1 ^ imm32;
8393 EmulateInstruction::Context context;
8394 context.type = EmulateInstruction::eContextImmediate;
8395 context.SetNoArgs();
8397 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
8403 // Bitwise Exclusive OR (register) performs a bitwise exclusive OR of a register
8405 // optionally-shifted register value, and writes the result to the destination
8407 // It can optionally update the condition flags based on the result.
8408 bool EmulateInstructionARM::EmulateEORReg(const uint32_t opcode,
8409 const ARMEncoding encoding) {
8411 // ARM pseudo code...
8412 if ConditionPassed() then
8413 EncodingSpecificOperations();
8414 (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C);
8415 result = R[n] EOR shifted;
8416 if d == 15 then // Can only occur for ARM encoding
8417 ALUWritePC(result); // setflags is always FALSE here
8421 APSR.N = result<31>;
8422 APSR.Z = IsZeroBit(result);
8427 bool success = false;
8429 if (ConditionPassed(opcode)) {
8430 uint32_t Rd, Rn, Rm;
8431 ARM_ShifterType shift_t;
8432 uint32_t shift_n; // the shift applied to the value read from Rm
8437 Rd = Rn = Bits32(opcode, 2, 0);
8438 Rm = Bits32(opcode, 5, 3);
8439 setflags = !InITBlock();
8440 shift_t = SRType_LSL;
8444 Rd = Bits32(opcode, 11, 8);
8445 Rn = Bits32(opcode, 19, 16);
8446 Rm = Bits32(opcode, 3, 0);
8447 setflags = BitIsSet(opcode, 20);
8448 shift_n = DecodeImmShiftThumb(opcode, shift_t);
8449 // if Rd == '1111' && S == '1' then SEE TEQ (register);
8450 if (Rd == 15 && setflags)
8451 return EmulateTEQReg(opcode, eEncodingT1);
8452 if (Rd == 13 || (Rd == 15 && !setflags) || BadReg(Rn) || BadReg(Rm))
8456 Rd = Bits32(opcode, 15, 12);
8457 Rn = Bits32(opcode, 19, 16);
8458 Rm = Bits32(opcode, 3, 0);
8459 setflags = BitIsSet(opcode, 20);
8460 shift_n = DecodeImmShiftARM(opcode, shift_t);
8462 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related
8464 if (Rd == 15 && setflags)
8465 return EmulateSUBSPcLrEtc(opcode, encoding);
8471 // Read the first operand.
8472 uint32_t val1 = ReadCoreReg(Rn, &success);
8476 // Read the second operand.
8477 uint32_t val2 = ReadCoreReg(Rm, &success);
8481 uint32_t shifted = Shift_C(val2, shift_t, shift_n, APSR_C, carry, &success);
8484 uint32_t result = val1 ^ shifted;
8486 EmulateInstruction::Context context;
8487 context.type = EmulateInstruction::eContextImmediate;
8488 context.SetNoArgs();
8490 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
8496 // Bitwise OR (immediate) performs a bitwise (inclusive) OR of a register value
8497 // and an immediate value, and
8498 // writes the result to the destination register. It can optionally update the
8499 // condition flags based
8501 bool EmulateInstructionARM::EmulateORRImm(const uint32_t opcode,
8502 const ARMEncoding encoding) {
8504 // ARM pseudo code...
8505 if ConditionPassed() then
8506 EncodingSpecificOperations();
8507 result = R[n] OR imm32;
8508 if d == 15 then // Can only occur for ARM encoding
8509 ALUWritePC(result); // setflags is always FALSE here
8513 APSR.N = result<31>;
8514 APSR.Z = IsZeroBit(result);
8519 bool success = false;
8521 if (ConditionPassed(opcode)) {
8524 imm32; // the immediate value to be ORed to the value obtained from Rn
8526 uint32_t carry; // the carry bit after ARM/Thumb Expand operation
8529 Rd = Bits32(opcode, 11, 8);
8530 Rn = Bits32(opcode, 19, 16);
8531 setflags = BitIsSet(opcode, 20);
8532 imm32 = ThumbExpandImm_C(
8534 carry); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C)
8535 // if Rn == '1111' then SEE MOV (immediate);
8537 return EmulateMOVRdImm(opcode, eEncodingT2);
8538 if (BadReg(Rd) || Rn == 13)
8542 Rd = Bits32(opcode, 15, 12);
8543 Rn = Bits32(opcode, 19, 16);
8544 setflags = BitIsSet(opcode, 20);
8546 ARMExpandImm_C(opcode, APSR_C,
8547 carry); // (imm32, carry) = ARMExpandImm(imm12, APSR.C)
8549 if (Rd == 15 && setflags)
8550 return EmulateSUBSPcLrEtc(opcode, encoding);
8556 // Read the first operand.
8557 uint32_t val1 = ReadCoreReg(Rn, &success);
8561 uint32_t result = val1 | imm32;
8563 EmulateInstruction::Context context;
8564 context.type = EmulateInstruction::eContextImmediate;
8565 context.SetNoArgs();
8567 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
8573 // Bitwise OR (register) performs a bitwise (inclusive) OR of a register value
8574 // and an optionally-shifted register
8575 // value, and writes the result to the destination register. It can optionally
8576 // update the condition flags based
8578 bool EmulateInstructionARM::EmulateORRReg(const uint32_t opcode,
8579 const ARMEncoding encoding) {
8581 // ARM pseudo code...
8582 if ConditionPassed() then
8583 EncodingSpecificOperations();
8584 (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C);
8585 result = R[n] OR shifted;
8586 if d == 15 then // Can only occur for ARM encoding
8587 ALUWritePC(result); // setflags is always FALSE here
8591 APSR.N = result<31>;
8592 APSR.Z = IsZeroBit(result);
8597 bool success = false;
8599 if (ConditionPassed(opcode)) {
8600 uint32_t Rd, Rn, Rm;
8601 ARM_ShifterType shift_t;
8602 uint32_t shift_n; // the shift applied to the value read from Rm
8607 Rd = Rn = Bits32(opcode, 2, 0);
8608 Rm = Bits32(opcode, 5, 3);
8609 setflags = !InITBlock();
8610 shift_t = SRType_LSL;
8614 Rd = Bits32(opcode, 11, 8);
8615 Rn = Bits32(opcode, 19, 16);
8616 Rm = Bits32(opcode, 3, 0);
8617 setflags = BitIsSet(opcode, 20);
8618 shift_n = DecodeImmShiftThumb(opcode, shift_t);
8619 // if Rn == '1111' then SEE MOV (register);
8621 return EmulateMOVRdRm(opcode, eEncodingT3);
8622 if (BadReg(Rd) || Rn == 13 || BadReg(Rm))
8626 Rd = Bits32(opcode, 15, 12);
8627 Rn = Bits32(opcode, 19, 16);
8628 Rm = Bits32(opcode, 3, 0);
8629 setflags = BitIsSet(opcode, 20);
8630 shift_n = DecodeImmShiftARM(opcode, shift_t);
8632 if (Rd == 15 && setflags)
8633 return EmulateSUBSPcLrEtc(opcode, encoding);
8639 // Read the first operand.
8640 uint32_t val1 = ReadCoreReg(Rn, &success);
8644 // Read the second operand.
8645 uint32_t val2 = ReadCoreReg(Rm, &success);
8649 uint32_t shifted = Shift_C(val2, shift_t, shift_n, APSR_C, carry, &success);
8652 uint32_t result = val1 | shifted;
8654 EmulateInstruction::Context context;
8655 context.type = EmulateInstruction::eContextImmediate;
8656 context.SetNoArgs();
8658 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
8664 // Reverse Subtract (immediate) subtracts a register value from an immediate
8665 // value, and writes the result to
8666 // the destination register. It can optionally update the condition flags based
8668 bool EmulateInstructionARM::EmulateRSBImm(const uint32_t opcode,
8669 const ARMEncoding encoding) {
8671 // ARM pseudo code...
8672 if ConditionPassed() then
8673 EncodingSpecificOperations();
8674 (result, carry, overflow) = AddWithCarry(NOT(R[n]), imm32, '1');
8675 if d == 15 then // Can only occur for ARM encoding
8676 ALUWritePC(result); // setflags is always FALSE here
8680 APSR.N = result<31>;
8681 APSR.Z = IsZeroBit(result);
8686 bool success = false;
8688 uint32_t Rd; // the destination register
8689 uint32_t Rn; // the first operand
8692 imm32; // the immediate value to be added to the value obtained from Rn
8695 Rd = Bits32(opcode, 2, 0);
8696 Rn = Bits32(opcode, 5, 3);
8697 setflags = !InITBlock();
8701 Rd = Bits32(opcode, 11, 8);
8702 Rn = Bits32(opcode, 19, 16);
8703 setflags = BitIsSet(opcode, 20);
8704 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8)
8705 if (BadReg(Rd) || BadReg(Rn))
8709 Rd = Bits32(opcode, 15, 12);
8710 Rn = Bits32(opcode, 19, 16);
8711 setflags = BitIsSet(opcode, 20);
8712 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
8714 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related
8716 if (Rd == 15 && setflags)
8717 return EmulateSUBSPcLrEtc(opcode, encoding);
8722 // Read the register value from the operand register Rn.
8723 uint32_t reg_val = ReadCoreReg(Rn, &success);
8727 AddWithCarryResult res = AddWithCarry(~reg_val, imm32, 1);
8729 EmulateInstruction::Context context;
8730 context.type = EmulateInstruction::eContextImmediate;
8731 context.SetNoArgs();
8733 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags,
8734 res.carry_out, res.overflow))
8740 // Reverse Subtract (register) subtracts a register value from an
8741 // optionally-shifted register value, and writes the
8742 // result to the destination register. It can optionally update the condition
8743 // flags based on the result.
8744 bool EmulateInstructionARM::EmulateRSBReg(const uint32_t opcode,
8745 const ARMEncoding encoding) {
8747 // ARM pseudo code...
8748 if ConditionPassed() then
8749 EncodingSpecificOperations();
8750 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
8751 (result, carry, overflow) = AddWithCarry(NOT(R[n]), shifted, '1');
8752 if d == 15 then // Can only occur for ARM encoding
8753 ALUWritePC(result); // setflags is always FALSE here
8757 APSR.N = result<31>;
8758 APSR.Z = IsZeroBit(result);
8763 bool success = false;
8765 uint32_t Rd; // the destination register
8766 uint32_t Rn; // the first operand
8767 uint32_t Rm; // the second operand
8769 ARM_ShifterType shift_t;
8770 uint32_t shift_n; // the shift applied to the value read from Rm
8773 Rd = Bits32(opcode, 11, 8);
8774 Rn = Bits32(opcode, 19, 16);
8775 Rm = Bits32(opcode, 3, 0);
8776 setflags = BitIsSet(opcode, 20);
8777 shift_n = DecodeImmShiftThumb(opcode, shift_t);
8778 // if (BadReg(d) || BadReg(m)) then UNPREDICTABLE;
8779 if (BadReg(Rd) || BadReg(Rn) || BadReg(Rm))
8783 Rd = Bits32(opcode, 15, 12);
8784 Rn = Bits32(opcode, 19, 16);
8785 Rm = Bits32(opcode, 3, 0);
8786 setflags = BitIsSet(opcode, 20);
8787 shift_n = DecodeImmShiftARM(opcode, shift_t);
8789 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related
8791 if (Rd == 15 && setflags)
8792 return EmulateSUBSPcLrEtc(opcode, encoding);
8797 // Read the register value from register Rn.
8798 uint32_t val1 = ReadCoreReg(Rn, &success);
8802 // Read the register value from register Rm.
8803 uint32_t val2 = ReadCoreReg(Rm, &success);
8807 uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C, &success);
8810 AddWithCarryResult res = AddWithCarry(~val1, shifted, 1);
8812 EmulateInstruction::Context context;
8813 context.type = EmulateInstruction::eContextImmediate;
8814 context.SetNoArgs();
8815 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags,
8816 res.carry_out, res.overflow))
8822 // Reverse Subtract with Carry (immediate) subtracts a register value and the
8823 // value of NOT (Carry flag) from
8824 // an immediate value, and writes the result to the destination register. It can
8825 // optionally update the condition
8826 // flags based on the result.
8827 bool EmulateInstructionARM::EmulateRSCImm(const uint32_t opcode,
8828 const ARMEncoding encoding) {
8830 // ARM pseudo code...
8831 if ConditionPassed() then
8832 EncodingSpecificOperations();
8833 (result, carry, overflow) = AddWithCarry(NOT(R[n]), imm32, APSR.C);
8835 ALUWritePC(result); // setflags is always FALSE here
8839 APSR.N = result<31>;
8840 APSR.Z = IsZeroBit(result);
8845 bool success = false;
8847 uint32_t Rd; // the destination register
8848 uint32_t Rn; // the first operand
8851 imm32; // the immediate value to be added to the value obtained from Rn
8854 Rd = Bits32(opcode, 15, 12);
8855 Rn = Bits32(opcode, 19, 16);
8856 setflags = BitIsSet(opcode, 20);
8857 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
8859 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related
8861 if (Rd == 15 && setflags)
8862 return EmulateSUBSPcLrEtc(opcode, encoding);
8867 // Read the register value from the operand register Rn.
8868 uint32_t reg_val = ReadCoreReg(Rn, &success);
8872 AddWithCarryResult res = AddWithCarry(~reg_val, imm32, APSR_C);
8874 EmulateInstruction::Context context;
8875 context.type = EmulateInstruction::eContextImmediate;
8876 context.SetNoArgs();
8878 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags,
8879 res.carry_out, res.overflow))
8885 // Reverse Subtract with Carry (register) subtracts a register value and the
8886 // value of NOT (Carry flag) from an
8887 // optionally-shifted register value, and writes the result to the destination
8888 // register. It can optionally update the
8889 // condition flags based on the result.
8890 bool EmulateInstructionARM::EmulateRSCReg(const uint32_t opcode,
8891 const ARMEncoding encoding) {
8893 // ARM pseudo code...
8894 if ConditionPassed() then
8895 EncodingSpecificOperations();
8896 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
8897 (result, carry, overflow) = AddWithCarry(NOT(R[n]), shifted, APSR.C);
8899 ALUWritePC(result); // setflags is always FALSE here
8903 APSR.N = result<31>;
8904 APSR.Z = IsZeroBit(result);
8909 bool success = false;
8911 uint32_t Rd; // the destination register
8912 uint32_t Rn; // the first operand
8913 uint32_t Rm; // the second operand
8915 ARM_ShifterType shift_t;
8916 uint32_t shift_n; // the shift applied to the value read from Rm
8919 Rd = Bits32(opcode, 15, 12);
8920 Rn = Bits32(opcode, 19, 16);
8921 Rm = Bits32(opcode, 3, 0);
8922 setflags = BitIsSet(opcode, 20);
8923 shift_n = DecodeImmShiftARM(opcode, shift_t);
8925 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related
8927 if (Rd == 15 && setflags)
8928 return EmulateSUBSPcLrEtc(opcode, encoding);
8933 // Read the register value from register Rn.
8934 uint32_t val1 = ReadCoreReg(Rn, &success);
8938 // Read the register value from register Rm.
8939 uint32_t val2 = ReadCoreReg(Rm, &success);
8943 uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C, &success);
8946 AddWithCarryResult res = AddWithCarry(~val1, shifted, APSR_C);
8948 EmulateInstruction::Context context;
8949 context.type = EmulateInstruction::eContextImmediate;
8950 context.SetNoArgs();
8951 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags,
8952 res.carry_out, res.overflow))
8958 // Subtract with Carry (immediate) subtracts an immediate value and the value of
8959 // NOT (Carry flag) from a register value, and writes the result to the
8960 // destination register.
8961 // It can optionally update the condition flags based on the result.
8962 bool EmulateInstructionARM::EmulateSBCImm(const uint32_t opcode,
8963 const ARMEncoding encoding) {
8965 // ARM pseudo code...
8966 if ConditionPassed() then
8967 EncodingSpecificOperations();
8968 (result, carry, overflow) = AddWithCarry(R[n], NOT(imm32), APSR.C);
8969 if d == 15 then // Can only occur for ARM encoding
8970 ALUWritePC(result); // setflags is always FALSE here
8974 APSR.N = result<31>;
8975 APSR.Z = IsZeroBit(result);
8980 bool success = false;
8982 uint32_t Rd; // the destination register
8983 uint32_t Rn; // the first operand
8986 imm32; // the immediate value to be added to the value obtained from Rn
8989 Rd = Bits32(opcode, 11, 8);
8990 Rn = Bits32(opcode, 19, 16);
8991 setflags = BitIsSet(opcode, 20);
8992 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8)
8993 if (BadReg(Rd) || BadReg(Rn))
8997 Rd = Bits32(opcode, 15, 12);
8998 Rn = Bits32(opcode, 19, 16);
8999 setflags = BitIsSet(opcode, 20);
9000 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
9002 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related
9004 if (Rd == 15 && setflags)
9005 return EmulateSUBSPcLrEtc(opcode, encoding);
9010 // Read the register value from the operand register Rn.
9011 uint32_t reg_val = ReadCoreReg(Rn, &success);
9015 AddWithCarryResult res = AddWithCarry(reg_val, ~imm32, APSR_C);
9017 EmulateInstruction::Context context;
9018 context.type = EmulateInstruction::eContextImmediate;
9019 context.SetNoArgs();
9021 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags,
9022 res.carry_out, res.overflow))
9028 // Subtract with Carry (register) subtracts an optionally-shifted register value
9030 // NOT (Carry flag) from a register value, and writes the result to the
9031 // destination register.
9032 // It can optionally update the condition flags based on the result.
9033 bool EmulateInstructionARM::EmulateSBCReg(const uint32_t opcode,
9034 const ARMEncoding encoding) {
9036 // ARM pseudo code...
9037 if ConditionPassed() then
9038 EncodingSpecificOperations();
9039 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
9040 (result, carry, overflow) = AddWithCarry(R[n], NOT(shifted), APSR.C);
9041 if d == 15 then // Can only occur for ARM encoding
9042 ALUWritePC(result); // setflags is always FALSE here
9046 APSR.N = result<31>;
9047 APSR.Z = IsZeroBit(result);
9052 bool success = false;
9054 uint32_t Rd; // the destination register
9055 uint32_t Rn; // the first operand
9056 uint32_t Rm; // the second operand
9058 ARM_ShifterType shift_t;
9059 uint32_t shift_n; // the shift applied to the value read from Rm
9062 Rd = Rn = Bits32(opcode, 2, 0);
9063 Rm = Bits32(opcode, 5, 3);
9064 setflags = !InITBlock();
9065 shift_t = SRType_LSL;
9069 Rd = Bits32(opcode, 11, 8);
9070 Rn = Bits32(opcode, 19, 16);
9071 Rm = Bits32(opcode, 3, 0);
9072 setflags = BitIsSet(opcode, 20);
9073 shift_n = DecodeImmShiftThumb(opcode, shift_t);
9074 if (BadReg(Rd) || BadReg(Rn) || BadReg(Rm))
9078 Rd = Bits32(opcode, 15, 12);
9079 Rn = Bits32(opcode, 19, 16);
9080 Rm = Bits32(opcode, 3, 0);
9081 setflags = BitIsSet(opcode, 20);
9082 shift_n = DecodeImmShiftARM(opcode, shift_t);
9084 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related
9086 if (Rd == 15 && setflags)
9087 return EmulateSUBSPcLrEtc(opcode, encoding);
9092 // Read the register value from register Rn.
9093 uint32_t val1 = ReadCoreReg(Rn, &success);
9097 // Read the register value from register Rm.
9098 uint32_t val2 = ReadCoreReg(Rm, &success);
9102 uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C, &success);
9105 AddWithCarryResult res = AddWithCarry(val1, ~shifted, APSR_C);
9107 EmulateInstruction::Context context;
9108 context.type = EmulateInstruction::eContextImmediate;
9109 context.SetNoArgs();
9110 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags,
9111 res.carry_out, res.overflow))
9117 // This instruction subtracts an immediate value from a register value, and
9118 // writes the result
9119 // to the destination register. It can optionally update the condition flags
9120 // based on the result.
9121 bool EmulateInstructionARM::EmulateSUBImmThumb(const uint32_t opcode,
9122 const ARMEncoding encoding) {
9124 // ARM pseudo code...
9125 if ConditionPassed() then
9126 EncodingSpecificOperations();
9127 (result, carry, overflow) = AddWithCarry(R[n], NOT(imm32), '1');
9130 APSR.N = result<31>;
9131 APSR.Z = IsZeroBit(result);
9136 bool success = false;
9138 uint32_t Rd; // the destination register
9139 uint32_t Rn; // the first operand
9141 uint32_t imm32; // the immediate value to be subtracted from the value
9145 Rd = Bits32(opcode, 2, 0);
9146 Rn = Bits32(opcode, 5, 3);
9147 setflags = !InITBlock();
9148 imm32 = Bits32(opcode, 8, 6); // imm32 = ZeroExtend(imm3, 32)
9151 Rd = Rn = Bits32(opcode, 10, 8);
9152 setflags = !InITBlock();
9153 imm32 = Bits32(opcode, 7, 0); // imm32 = ZeroExtend(imm8, 32)
9156 Rd = Bits32(opcode, 11, 8);
9157 Rn = Bits32(opcode, 19, 16);
9158 setflags = BitIsSet(opcode, 20);
9159 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8)
9161 // if Rd == '1111' && S == '1' then SEE CMP (immediate);
9162 if (Rd == 15 && setflags)
9163 return EmulateCMPImm(opcode, eEncodingT2);
9165 // if Rn == '1101' then SEE SUB (SP minus immediate);
9167 return EmulateSUBSPImm(opcode, eEncodingT2);
9169 // if d == 13 || (d == 15 && S == '0') || n == 15 then UNPREDICTABLE;
9170 if (Rd == 13 || (Rd == 15 && !setflags) || Rn == 15)
9174 Rd = Bits32(opcode, 11, 8);
9175 Rn = Bits32(opcode, 19, 16);
9176 setflags = BitIsSet(opcode, 20);
9177 imm32 = ThumbImm12(opcode); // imm32 = ZeroExtend(i:imm3:imm8, 32)
9179 // if Rn == '1111' then SEE ADR;
9181 return EmulateADR(opcode, eEncodingT2);
9183 // if Rn == '1101' then SEE SUB (SP minus immediate);
9185 return EmulateSUBSPImm(opcode, eEncodingT3);
9193 // Read the register value from the operand register Rn.
9194 uint32_t reg_val = ReadCoreReg(Rn, &success);
9198 AddWithCarryResult res = AddWithCarry(reg_val, ~imm32, 1);
9200 EmulateInstruction::Context context;
9201 context.type = EmulateInstruction::eContextImmediate;
9202 context.SetNoArgs();
9204 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags,
9205 res.carry_out, res.overflow))
9211 // This instruction subtracts an immediate value from a register value, and
9212 // writes the result
9213 // to the destination register. It can optionally update the condition flags
9214 // based on the result.
9215 bool EmulateInstructionARM::EmulateSUBImmARM(const uint32_t opcode,
9216 const ARMEncoding encoding) {
9218 // ARM pseudo code...
9219 if ConditionPassed() then
9220 EncodingSpecificOperations();
9221 (result, carry, overflow) = AddWithCarry(R[n], NOT(imm32), '1');
9223 ALUWritePC(result); // setflags is always FALSE here
9227 APSR.N = result<31>;
9228 APSR.Z = IsZeroBit(result);
9233 bool success = false;
9235 if (ConditionPassed(opcode)) {
9236 uint32_t Rd; // the destination register
9237 uint32_t Rn; // the first operand
9239 uint32_t imm32; // the immediate value to be subtracted from the value
9243 Rd = Bits32(opcode, 15, 12);
9244 Rn = Bits32(opcode, 19, 16);
9245 setflags = BitIsSet(opcode, 20);
9246 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
9248 // if Rn == '1111' && S == '0' then SEE ADR;
9249 if (Rn == 15 && !setflags)
9250 return EmulateADR(opcode, eEncodingA2);
9252 // if Rn == '1101' then SEE SUB (SP minus immediate);
9254 return EmulateSUBSPImm(opcode, eEncodingA1);
9256 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related
9258 if (Rd == 15 && setflags)
9259 return EmulateSUBSPcLrEtc(opcode, encoding);
9264 // Read the register value from the operand register Rn.
9265 uint32_t reg_val = ReadCoreReg(Rn, &success);
9269 AddWithCarryResult res = AddWithCarry(reg_val, ~imm32, 1);
9271 EmulateInstruction::Context context;
9273 context.type = EmulateInstruction::eContextAdjustStackPointer;
9275 context.type = EmulateInstruction::eContextRegisterPlusOffset;
9277 RegisterInfo dwarf_reg;
9278 GetRegisterInfo(eRegisterKindDWARF, Rn, dwarf_reg);
9279 int64_t imm32_signed = imm32;
9280 context.SetRegisterPlusOffset(dwarf_reg, -imm32_signed);
9282 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags,
9283 res.carry_out, res.overflow))
9289 // Test Equivalence (immediate) performs a bitwise exclusive OR operation on a
9290 // register value and an
9291 // immediate value. It updates the condition flags based on the result, and
9292 // discards the result.
9293 bool EmulateInstructionARM::EmulateTEQImm(const uint32_t opcode,
9294 const ARMEncoding encoding) {
9296 // ARM pseudo code...
9297 if ConditionPassed() then
9298 EncodingSpecificOperations();
9299 result = R[n] EOR imm32;
9300 APSR.N = result<31>;
9301 APSR.Z = IsZeroBit(result);
9306 bool success = false;
9308 if (ConditionPassed(opcode)) {
9311 imm32; // the immediate value to be ANDed to the value obtained from Rn
9312 uint32_t carry; // the carry bit after ARM/Thumb Expand operation
9315 Rn = Bits32(opcode, 19, 16);
9316 imm32 = ThumbExpandImm_C(
9318 carry); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C)
9323 Rn = Bits32(opcode, 19, 16);
9325 ARMExpandImm_C(opcode, APSR_C,
9326 carry); // (imm32, carry) = ARMExpandImm(imm12, APSR.C)
9332 // Read the first operand.
9333 uint32_t val1 = ReadCoreReg(Rn, &success);
9337 uint32_t result = val1 ^ imm32;
9339 EmulateInstruction::Context context;
9340 context.type = EmulateInstruction::eContextImmediate;
9341 context.SetNoArgs();
9343 if (!WriteFlags(context, result, carry))
9349 // Test Equivalence (register) performs a bitwise exclusive OR operation on a
9350 // register value and an
9351 // optionally-shifted register value. It updates the condition flags based on
9352 // the result, and discards
9354 bool EmulateInstructionARM::EmulateTEQReg(const uint32_t opcode,
9355 const ARMEncoding encoding) {
9357 // ARM pseudo code...
9358 if ConditionPassed() then
9359 EncodingSpecificOperations();
9360 (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C);
9361 result = R[n] EOR shifted;
9362 APSR.N = result<31>;
9363 APSR.Z = IsZeroBit(result);
9368 bool success = false;
9370 if (ConditionPassed(opcode)) {
9372 ARM_ShifterType shift_t;
9373 uint32_t shift_n; // the shift applied to the value read from Rm
9377 Rn = Bits32(opcode, 19, 16);
9378 Rm = Bits32(opcode, 3, 0);
9379 shift_n = DecodeImmShiftThumb(opcode, shift_t);
9380 if (BadReg(Rn) || BadReg(Rm))
9384 Rn = Bits32(opcode, 19, 16);
9385 Rm = Bits32(opcode, 3, 0);
9386 shift_n = DecodeImmShiftARM(opcode, shift_t);
9392 // Read the first operand.
9393 uint32_t val1 = ReadCoreReg(Rn, &success);
9397 // Read the second operand.
9398 uint32_t val2 = ReadCoreReg(Rm, &success);
9402 uint32_t shifted = Shift_C(val2, shift_t, shift_n, APSR_C, carry, &success);
9405 uint32_t result = val1 ^ shifted;
9407 EmulateInstruction::Context context;
9408 context.type = EmulateInstruction::eContextImmediate;
9409 context.SetNoArgs();
9411 if (!WriteFlags(context, result, carry))
9417 // Test (immediate) performs a bitwise AND operation on a register value and an
9419 // It updates the condition flags based on the result, and discards the result.
9420 bool EmulateInstructionARM::EmulateTSTImm(const uint32_t opcode,
9421 const ARMEncoding encoding) {
9423 // ARM pseudo code...
9424 if ConditionPassed() then
9425 EncodingSpecificOperations();
9426 result = R[n] AND imm32;
9427 APSR.N = result<31>;
9428 APSR.Z = IsZeroBit(result);
9433 bool success = false;
9435 if (ConditionPassed(opcode)) {
9438 imm32; // the immediate value to be ANDed to the value obtained from Rn
9439 uint32_t carry; // the carry bit after ARM/Thumb Expand operation
9442 Rn = Bits32(opcode, 19, 16);
9443 imm32 = ThumbExpandImm_C(
9445 carry); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C)
9450 Rn = Bits32(opcode, 19, 16);
9452 ARMExpandImm_C(opcode, APSR_C,
9453 carry); // (imm32, carry) = ARMExpandImm(imm12, APSR.C)
9459 // Read the first operand.
9460 uint32_t val1 = ReadCoreReg(Rn, &success);
9464 uint32_t result = val1 & imm32;
9466 EmulateInstruction::Context context;
9467 context.type = EmulateInstruction::eContextImmediate;
9468 context.SetNoArgs();
9470 if (!WriteFlags(context, result, carry))
9476 // Test (register) performs a bitwise AND operation on a register value and an
9477 // optionally-shifted register value.
9478 // It updates the condition flags based on the result, and discards the result.
9479 bool EmulateInstructionARM::EmulateTSTReg(const uint32_t opcode,
9480 const ARMEncoding encoding) {
9482 // ARM pseudo code...
9483 if ConditionPassed() then
9484 EncodingSpecificOperations();
9485 (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C);
9486 result = R[n] AND shifted;
9487 APSR.N = result<31>;
9488 APSR.Z = IsZeroBit(result);
9493 bool success = false;
9495 if (ConditionPassed(opcode)) {
9497 ARM_ShifterType shift_t;
9498 uint32_t shift_n; // the shift applied to the value read from Rm
9502 Rn = Bits32(opcode, 2, 0);
9503 Rm = Bits32(opcode, 5, 3);
9504 shift_t = SRType_LSL;
9508 Rn = Bits32(opcode, 19, 16);
9509 Rm = Bits32(opcode, 3, 0);
9510 shift_n = DecodeImmShiftThumb(opcode, shift_t);
9511 if (BadReg(Rn) || BadReg(Rm))
9515 Rn = Bits32(opcode, 19, 16);
9516 Rm = Bits32(opcode, 3, 0);
9517 shift_n = DecodeImmShiftARM(opcode, shift_t);
9523 // Read the first operand.
9524 uint32_t val1 = ReadCoreReg(Rn, &success);
9528 // Read the second operand.
9529 uint32_t val2 = ReadCoreReg(Rm, &success);
9533 uint32_t shifted = Shift_C(val2, shift_t, shift_n, APSR_C, carry, &success);
9536 uint32_t result = val1 & shifted;
9538 EmulateInstruction::Context context;
9539 context.type = EmulateInstruction::eContextImmediate;
9540 context.SetNoArgs();
9542 if (!WriteFlags(context, result, carry))
9548 // A8.6.216 SUB (SP minus register)
9549 bool EmulateInstructionARM::EmulateSUBSPReg(const uint32_t opcode,
9550 const ARMEncoding encoding) {
9552 if ConditionPassed() then
9553 EncodingSpecificOperations();
9554 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
9555 (result, carry, overflow) = AddWithCarry(SP, NOT(shifted), '1');
9556 if d == 15 then // Can only occur for ARM encoding
9557 ALUWritePC(result); // setflags is always FALSE here
9561 APSR.N = result<31>;
9562 APSR.Z = IsZeroBit(result);
9567 bool success = false;
9569 if (ConditionPassed(opcode)) {
9573 ARM_ShifterType shift_t;
9578 // d = UInt(Rd); m = UInt(Rm); setflags = (S == '1');
9579 d = Bits32(opcode, 11, 8);
9580 m = Bits32(opcode, 3, 0);
9581 setflags = BitIsSet(opcode, 20);
9583 // (shift_t, shift_n) = DecodeImmShift(type, imm3:imm2);
9584 shift_n = DecodeImmShiftThumb(opcode, shift_t);
9586 // if d == 13 && (shift_t != SRType_LSL || shift_n > 3) then
9588 if ((d == 13) && ((shift_t != SRType_LSL) || (shift_n > 3)))
9591 // if d == 15 || BadReg(m) then UNPREDICTABLE;
9592 if ((d == 15) || BadReg(m))
9597 // d = UInt(Rd); m = UInt(Rm); setflags = (S == '1');
9598 d = Bits32(opcode, 15, 12);
9599 m = Bits32(opcode, 3, 0);
9600 setflags = BitIsSet(opcode, 20);
9602 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related
9604 if (d == 15 && setflags)
9605 EmulateSUBSPcLrEtc(opcode, encoding);
9607 // (shift_t, shift_n) = DecodeImmShift(type, imm5);
9608 shift_n = DecodeImmShiftARM(opcode, shift_t);
9615 // shifted = Shift(R[m], shift_t, shift_n, APSR.C);
9616 uint32_t Rm = ReadCoreReg(m, &success);
9620 uint32_t shifted = Shift(Rm, shift_t, shift_n, APSR_C, &success);
9624 // (result, carry, overflow) = AddWithCarry(SP, NOT(shifted), '1');
9625 uint32_t sp_val = ReadCoreReg(SP_REG, &success);
9629 AddWithCarryResult res = AddWithCarry(sp_val, ~shifted, 1);
9631 EmulateInstruction::Context context;
9632 context.type = eContextArithmetic;
9633 RegisterInfo sp_reg;
9634 GetRegisterInfo(eRegisterKindDWARF, dwarf_sp, sp_reg);
9635 RegisterInfo dwarf_reg;
9636 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + m, dwarf_reg);
9637 context.SetRegisterRegisterOperands(sp_reg, dwarf_reg);
9639 if (!WriteCoreRegOptionalFlags(context, res.result, dwarf_r0 + d, setflags,
9640 res.carry_out, res.overflow))
9646 // A8.6.7 ADD (register-shifted register)
9647 bool EmulateInstructionARM::EmulateADDRegShift(const uint32_t opcode,
9648 const ARMEncoding encoding) {
9650 if ConditionPassed() then
9651 EncodingSpecificOperations();
9652 shift_n = UInt(R[s]<7:0>);
9653 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
9654 (result, carry, overflow) = AddWithCarry(R[n], shifted, '0');
9657 APSR.N = result<31>;
9658 APSR.Z = IsZeroBit(result);
9663 bool success = false;
9665 if (ConditionPassed(opcode)) {
9671 ARM_ShifterType shift_t;
9675 // d = UInt(Rd); n = UInt(Rn); m = UInt(Rm); s = UInt(Rs);
9676 d = Bits32(opcode, 15, 12);
9677 n = Bits32(opcode, 19, 16);
9678 m = Bits32(opcode, 3, 0);
9679 s = Bits32(opcode, 11, 8);
9681 // setflags = (S == '1'); shift_t = DecodeRegShift(type);
9682 setflags = BitIsSet(opcode, 20);
9683 shift_t = DecodeRegShift(Bits32(opcode, 6, 5));
9685 // if d == 15 || n == 15 || m == 15 || s == 15 then UNPREDICTABLE;
9686 if ((d == 15) || (m == 15) || (m == 15) || (s == 15))
9694 // shift_n = UInt(R[s]<7:0>);
9695 uint32_t Rs = ReadCoreReg(s, &success);
9699 uint32_t shift_n = Bits32(Rs, 7, 0);
9701 // shifted = Shift(R[m], shift_t, shift_n, APSR.C);
9702 uint32_t Rm = ReadCoreReg(m, &success);
9706 uint32_t shifted = Shift(Rm, shift_t, shift_n, APSR_C, &success);
9710 // (result, carry, overflow) = AddWithCarry(R[n], shifted, '0');
9711 uint32_t Rn = ReadCoreReg(n, &success);
9715 AddWithCarryResult res = AddWithCarry(Rn, shifted, 0);
9718 EmulateInstruction::Context context;
9719 context.type = eContextArithmetic;
9721 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n, reg_n);
9723 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + m, reg_m);
9725 context.SetRegisterRegisterOperands(reg_n, reg_m);
9727 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + d,
9732 // APSR.N = result<31>;
9733 // APSR.Z = IsZeroBit(result);
9735 // APSR.V = overflow;
9737 return WriteFlags(context, res.result, res.carry_out, res.overflow);
9742 // A8.6.213 SUB (register)
9743 bool EmulateInstructionARM::EmulateSUBReg(const uint32_t opcode,
9744 const ARMEncoding encoding) {
9746 if ConditionPassed() then
9747 EncodingSpecificOperations();
9748 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
9749 (result, carry, overflow) = AddWithCarry(R[n], NOT(shifted), '1');
9750 if d == 15 then // Can only occur for ARM encoding
9751 ALUWritePC(result); // setflags is always FALSE here
9755 APSR.N = result<31>;
9756 APSR.Z = IsZeroBit(result);
9761 bool success = false;
9763 if (ConditionPassed(opcode)) {
9768 ARM_ShifterType shift_t;
9773 // d = UInt(Rd); n = UInt(Rn); m = UInt(Rm); setflags = !InITBlock();
9774 d = Bits32(opcode, 2, 0);
9775 n = Bits32(opcode, 5, 3);
9776 m = Bits32(opcode, 8, 6);
9777 setflags = !InITBlock();
9779 // (shift_t, shift_n) = (SRType_LSL, 0);
9780 shift_t = SRType_LSL;
9786 // d = UInt(Rd); n = UInt(Rn); m = UInt(Rm); setflags = (S =="1");
9787 d = Bits32(opcode, 11, 8);
9788 n = Bits32(opcode, 19, 16);
9789 m = Bits32(opcode, 3, 0);
9790 setflags = BitIsSet(opcode, 20);
9792 // if Rd == "1111" && S == "1" then SEE CMP (register);
9793 if (d == 15 && setflags == 1)
9794 return EmulateCMPImm(opcode, eEncodingT3);
9796 // if Rn == "1101" then SEE SUB (SP minus register);
9798 return EmulateSUBSPReg(opcode, eEncodingT1);
9800 // (shift_t, shift_n) = DecodeImmShift(type, imm3:imm2);
9801 shift_n = DecodeImmShiftThumb(opcode, shift_t);
9803 // if d == 13 || (d == 15 && S == '0') || n == 15 || BadReg(m) then
9805 if ((d == 13) || ((d == 15) && BitIsClear(opcode, 20)) || (n == 15) ||
9812 // if Rn == '1101' then SEE SUB (SP minus register);
9813 // d = UInt(Rd); n = UInt(Rn); m = UInt(Rm); setflags = (S == '1');
9814 d = Bits32(opcode, 15, 12);
9815 n = Bits32(opcode, 19, 16);
9816 m = Bits32(opcode, 3, 0);
9817 setflags = BitIsSet(opcode, 20);
9819 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related
9821 if ((d == 15) && setflags)
9822 EmulateSUBSPcLrEtc(opcode, encoding);
9824 // (shift_t, shift_n) = DecodeImmShift(type, imm5);
9825 shift_n = DecodeImmShiftARM(opcode, shift_t);
9833 // shifted = Shift(R[m], shift_t, shift_n, APSR.C);
9834 uint32_t Rm = ReadCoreReg(m, &success);
9838 uint32_t shifted = Shift(Rm, shift_t, shift_n, APSR_C, &success);
9842 // (result, carry, overflow) = AddWithCarry(R[n], NOT(shifted), '1');
9843 uint32_t Rn = ReadCoreReg(n, &success);
9847 AddWithCarryResult res = AddWithCarry(Rn, ~shifted, 1);
9849 // if d == 15 then // Can only occur for ARM encoding
9850 // ALUWritePC(result); // setflags is always FALSE here
9854 // APSR.N = result<31>;
9855 // APSR.Z = IsZeroBit(result);
9857 // APSR.V = overflow;
9859 EmulateInstruction::Context context;
9860 context.type = eContextArithmetic;
9862 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n, reg_n);
9864 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + m, reg_m);
9865 context.SetRegisterRegisterOperands(reg_n, reg_m);
9867 if (!WriteCoreRegOptionalFlags(context, res.result, dwarf_r0 + d, setflags,
9868 res.carry_out, res.overflow))
9875 // Store Register Exclusive calculates an address from a base register value and
9876 // an immediate offset, and stores a
9877 // word from a register to memory if the executing processor has exclusive
9878 // access to the memory addressed.
9879 bool EmulateInstructionARM::EmulateSTREX(const uint32_t opcode,
9880 const ARMEncoding encoding) {
9882 if ConditionPassed() then
9883 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
9884 address = R[n] + imm32;
9885 if ExclusiveMonitorsPass(address,4) then
9886 MemA[address,4] = R[t];
9892 bool success = false;
9894 if (ConditionPassed(opcode)) {
9899 const uint32_t addr_byte_size = GetAddressByteSize();
9903 // d = UInt(Rd); t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8:'00',
9905 d = Bits32(opcode, 11, 8);
9906 t = Bits32(opcode, 15, 12);
9907 n = Bits32(opcode, 19, 16);
9908 imm32 = Bits32(opcode, 7, 0) << 2;
9910 // if BadReg(d) || BadReg(t) || n == 15 then UNPREDICTABLE;
9911 if (BadReg(d) || BadReg(t) || (n == 15))
9914 // if d == n || d == t then UNPREDICTABLE;
9915 if ((d == n) || (d == t))
9921 // d = UInt(Rd); t = UInt(Rt); n = UInt(Rn); imm32 = Zeros(32); // Zero
9923 d = Bits32(opcode, 15, 12);
9924 t = Bits32(opcode, 3, 0);
9925 n = Bits32(opcode, 19, 16);
9928 // if d == 15 || t == 15 || n == 15 then UNPREDICTABLE;
9929 if ((d == 15) || (t == 15) || (n == 15))
9932 // if d == n || d == t then UNPREDICTABLE;
9933 if ((d == n) || (d == t))
9942 // address = R[n] + imm32;
9943 uint32_t Rn = ReadCoreReg(n, &success);
9947 addr_t address = Rn + imm32;
9949 RegisterInfo base_reg;
9950 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n, base_reg);
9951 RegisterInfo data_reg;
9952 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + t, data_reg);
9953 EmulateInstruction::Context context;
9954 context.type = eContextRegisterStore;
9955 context.SetRegisterToRegisterPlusOffset(data_reg, base_reg, imm32);
9957 // if ExclusiveMonitorsPass(address,4) then
9958 // if (ExclusiveMonitorsPass (address, addr_byte_size)) -- For now, for the
9959 // sake of emulation, we will say this
9963 // MemA[address,4] = R[t];
9965 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + t, 0, &success);
9969 if (!MemAWrite(context, address, Rt, addr_byte_size))
9973 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + t, 0))
9976 #if 0 // unreachable because if true
9980 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, 1))
9983 #endif // unreachable because if true
9988 // A8.6.197 STRB (immediate, ARM)
9989 bool EmulateInstructionARM::EmulateSTRBImmARM(const uint32_t opcode,
9990 const ARMEncoding encoding) {
9992 if ConditionPassed() then
9993 EncodingSpecificOperations();
9994 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
9995 address = if index then offset_addr else R[n];
9996 MemU[address,1] = R[t]<7:0>;
9997 if wback then R[n] = offset_addr;
10000 bool success = false;
10002 if (ConditionPassed(opcode)) {
10010 switch (encoding) {
10012 // if P == '0' && W == '1' then SEE STRBT;
10013 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
10014 t = Bits32(opcode, 15, 12);
10015 n = Bits32(opcode, 19, 16);
10016 imm32 = Bits32(opcode, 11, 0);
10018 // index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1');
10019 index = BitIsSet(opcode, 24);
10020 add = BitIsSet(opcode, 23);
10021 wback = BitIsClear(opcode, 24) || BitIsSet(opcode, 21);
10023 // if t == 15 then UNPREDICTABLE;
10027 // if wback && (n == 15 || n == t) then UNPREDICTABLE;
10028 if (wback && ((n == 15) || (n == t)))
10037 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
10038 uint32_t Rn = ReadCoreReg(n, &success);
10042 addr_t offset_addr;
10044 offset_addr = Rn + imm32;
10046 offset_addr = Rn - imm32;
10048 // address = if index then offset_addr else R[n];
10051 address = offset_addr;
10055 // MemU[address,1] = R[t]<7:0>;
10056 uint32_t Rt = ReadCoreReg(t, &success);
10060 RegisterInfo base_reg;
10061 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n, base_reg);
10062 RegisterInfo data_reg;
10063 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + t, data_reg);
10064 EmulateInstruction::Context context;
10065 context.type = eContextRegisterStore;
10066 context.SetRegisterToRegisterPlusOffset(data_reg, base_reg, address - Rn);
10068 if (!MemUWrite(context, address, Bits32(Rt, 7, 0), 1))
10071 // if wback then R[n] = offset_addr;
10073 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n,
10081 // A8.6.194 STR (immediate, ARM)
10082 bool EmulateInstructionARM::EmulateSTRImmARM(const uint32_t opcode,
10083 const ARMEncoding encoding) {
10085 if ConditionPassed() then
10086 EncodingSpecificOperations();
10087 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
10088 address = if index then offset_addr else R[n];
10089 MemU[address,4] = if t == 15 then PCStoreValue() else R[t];
10090 if wback then R[n] = offset_addr;
10093 bool success = false;
10095 if (ConditionPassed(opcode)) {
10103 const uint32_t addr_byte_size = GetAddressByteSize();
10105 switch (encoding) {
10107 // if P == '0' && W == '1' then SEE STRT;
10108 // if Rn == '1101' && P == '1' && U == '0' && W == '1' && imm12 ==
10109 // '000000000100' then SEE PUSH;
10110 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
10111 t = Bits32(opcode, 15, 12);
10112 n = Bits32(opcode, 19, 16);
10113 imm32 = Bits32(opcode, 11, 0);
10115 // index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1');
10116 index = BitIsSet(opcode, 24);
10117 add = BitIsSet(opcode, 23);
10118 wback = BitIsClear(opcode, 24) || BitIsSet(opcode, 21);
10120 // if wback && (n == 15 || n == t) then UNPREDICTABLE;
10121 if (wback && ((n == 15) || (n == t)))
10130 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
10131 uint32_t Rn = ReadCoreReg(n, &success);
10135 addr_t offset_addr;
10137 offset_addr = Rn + imm32;
10139 offset_addr = Rn - imm32;
10141 // address = if index then offset_addr else R[n];
10144 address = offset_addr;
10148 RegisterInfo base_reg;
10149 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n, base_reg);
10150 RegisterInfo data_reg;
10151 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + t, data_reg);
10152 EmulateInstruction::Context context;
10153 context.type = eContextRegisterStore;
10154 context.SetRegisterToRegisterPlusOffset(data_reg, base_reg, address - Rn);
10156 // MemU[address,4] = if t == 15 then PCStoreValue() else R[t];
10157 uint32_t Rt = ReadCoreReg(t, &success);
10162 uint32_t pc_value = ReadCoreReg(PC_REG, &success);
10166 if (!MemUWrite(context, address, pc_value, addr_byte_size))
10169 if (!MemUWrite(context, address, Rt, addr_byte_size))
10173 // if wback then R[n] = offset_addr;
10175 context.type = eContextAdjustBaseRegister;
10176 context.SetImmediate(offset_addr);
10178 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n,
10186 // A8.6.66 LDRD (immediate)
10187 // Load Register Dual (immediate) calculates an address from a base register
10188 // value and an immediate offset, loads two
10189 // words from memory, and writes them to two registers. It can use offset,
10190 // post-indexed, or pre-indexed addressing.
10191 bool EmulateInstructionARM::EmulateLDRDImmediate(const uint32_t opcode,
10192 const ARMEncoding encoding) {
10194 if ConditionPassed() then
10195 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
10196 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
10197 address = if index then offset_addr else R[n];
10198 R[t] = MemA[address,4];
10199 R[t2] = MemA[address+4,4];
10200 if wback then R[n] = offset_addr;
10203 bool success = false;
10205 if (ConditionPassed(opcode)) {
10214 switch (encoding) {
10216 // if P == '0' && W == '0' then SEE 'Related encodings';
10217 // if Rn == '1111' then SEE LDRD (literal);
10218 // t = UInt(Rt); t2 = UInt(Rt2); n = UInt(Rn); imm32 =
10219 // ZeroExtend(imm8:'00', 32);
10220 t = Bits32(opcode, 15, 12);
10221 t2 = Bits32(opcode, 11, 8);
10222 n = Bits32(opcode, 19, 16);
10223 imm32 = Bits32(opcode, 7, 0) << 2;
10225 // index = (P == '1'); add = (U == '1'); wback = (W == '1');
10226 index = BitIsSet(opcode, 24);
10227 add = BitIsSet(opcode, 23);
10228 wback = BitIsSet(opcode, 21);
10230 // if wback && (n == t || n == t2) then UNPREDICTABLE;
10231 if (wback && ((n == t) || (n == t2)))
10234 // if BadReg(t) || BadReg(t2) || t == t2 then UNPREDICTABLE;
10235 if (BadReg(t) || BadReg(t2) || (t == t2))
10241 // if Rn == '1111' then SEE LDRD (literal);
10242 // if Rt<0> == '1' then UNPREDICTABLE;
10243 // t = UInt(Rt); t2 = t+1; n = UInt(Rn); imm32 = ZeroExtend(imm4H:imm4L,
10245 t = Bits32(opcode, 15, 12);
10246 if (BitIsSet(t, 0))
10249 n = Bits32(opcode, 19, 16);
10250 imm32 = (Bits32(opcode, 11, 8) << 4) | Bits32(opcode, 3, 0);
10252 // index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1');
10253 index = BitIsSet(opcode, 24);
10254 add = BitIsSet(opcode, 23);
10255 wback = BitIsClear(opcode, 24) || BitIsSet(opcode, 21);
10257 // if P == '0' && W == '1' then UNPREDICTABLE;
10258 if (BitIsClear(opcode, 24) && BitIsSet(opcode, 21))
10261 // if wback && (n == t || n == t2) then UNPREDICTABLE;
10262 if (wback && ((n == t) || (n == t2)))
10265 // if t2 == 15 then UNPREDICTABLE;
10275 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
10276 uint32_t Rn = ReadCoreReg(n, &success);
10280 addr_t offset_addr;
10282 offset_addr = Rn + imm32;
10284 offset_addr = Rn - imm32;
10286 // address = if index then offset_addr else R[n];
10289 address = offset_addr;
10293 // R[t] = MemA[address,4];
10294 RegisterInfo base_reg;
10295 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n, base_reg);
10297 EmulateInstruction::Context context;
10299 context.type = eContextPopRegisterOffStack;
10301 context.type = eContextRegisterLoad;
10302 context.SetAddress(address);
10304 const uint32_t addr_byte_size = GetAddressByteSize();
10305 uint32_t data = MemARead(context, address, addr_byte_size, 0, &success);
10309 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + t, data))
10312 // R[t2] = MemA[address+4,4];
10313 context.SetAddress(address + 4);
10314 data = MemARead(context, address + 4, addr_byte_size, 0, &success);
10318 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + t2,
10322 // if wback then R[n] = offset_addr;
10324 context.type = eContextAdjustBaseRegister;
10325 context.SetAddress(offset_addr);
10327 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n,
10335 // A8.6.68 LDRD (register)
10336 // Load Register Dual (register) calculates an address from a base register
10337 // value and a register offset, loads two
10338 // words from memory, and writes them to two registers. It can use offset,
10339 // post-indexed or pre-indexed addressing.
10340 bool EmulateInstructionARM::EmulateLDRDRegister(const uint32_t opcode,
10341 const ARMEncoding encoding) {
10343 if ConditionPassed() then
10344 EncodingSpecificOperations();
10345 offset_addr = if add then (R[n] + R[m]) else (R[n] - R[m]);
10346 address = if index then offset_addr else R[n];
10347 R[t] = MemA[address,4];
10348 R[t2] = MemA[address+4,4];
10349 if wback then R[n] = offset_addr;
10352 bool success = false;
10354 if (ConditionPassed(opcode)) {
10363 switch (encoding) {
10365 // if Rt<0> == '1' then UNPREDICTABLE;
10366 // t = UInt(Rt); t2 = t+1; n = UInt(Rn); m = UInt(Rm);
10367 t = Bits32(opcode, 15, 12);
10368 if (BitIsSet(t, 0))
10371 n = Bits32(opcode, 19, 16);
10372 m = Bits32(opcode, 3, 0);
10374 // index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1');
10375 index = BitIsSet(opcode, 24);
10376 add = BitIsSet(opcode, 23);
10377 wback = BitIsClear(opcode, 24) || BitIsSet(opcode, 21);
10379 // if P == '0' && W == '1' then UNPREDICTABLE;
10380 if (BitIsClear(opcode, 24) && BitIsSet(opcode, 21))
10383 // if t2 == 15 || m == 15 || m == t || m == t2 then UNPREDICTABLE;
10384 if ((t2 == 15) || (m == 15) || (m == t) || (m == t2))
10387 // if wback && (n == 15 || n == t || n == t2) then UNPREDICTABLE;
10388 if (wback && ((n == 15) || (n == t) || (n == t2)))
10391 // if ArchVersion() < 6 && wback && m == n then UNPREDICTABLE;
10392 if ((ArchVersion() < 6) && wback && (m == n))
10400 uint32_t Rn = ReadCoreReg(n, &success);
10403 RegisterInfo base_reg;
10404 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n, base_reg);
10406 uint32_t Rm = ReadCoreReg(m, &success);
10409 RegisterInfo offset_reg;
10410 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + m, offset_reg);
10412 // offset_addr = if add then (R[n] + R[m]) else (R[n] - R[m]);
10413 addr_t offset_addr;
10415 offset_addr = Rn + Rm;
10417 offset_addr = Rn - Rm;
10419 // address = if index then offset_addr else R[n];
10422 address = offset_addr;
10426 EmulateInstruction::Context context;
10428 context.type = eContextPopRegisterOffStack;
10430 context.type = eContextRegisterLoad;
10431 context.SetAddress(address);
10433 // R[t] = MemA[address,4];
10434 const uint32_t addr_byte_size = GetAddressByteSize();
10435 uint32_t data = MemARead(context, address, addr_byte_size, 0, &success);
10439 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + t, data))
10442 // R[t2] = MemA[address+4,4];
10444 data = MemARead(context, address + 4, addr_byte_size, 0, &success);
10448 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + t2,
10452 // if wback then R[n] = offset_addr;
10454 context.type = eContextAdjustBaseRegister;
10455 context.SetAddress(offset_addr);
10457 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n,
10465 // A8.6.200 STRD (immediate)
10466 // Store Register Dual (immediate) calculates an address from a base register
10467 // value and an immediate offset, and
10468 // stores two words from two registers to memory. It can use offset,
10469 // post-indexed, or pre-indexed addressing.
10470 bool EmulateInstructionARM::EmulateSTRDImm(const uint32_t opcode,
10471 const ARMEncoding encoding) {
10473 if ConditionPassed() then
10474 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
10475 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
10476 address = if index then offset_addr else R[n];
10477 MemA[address,4] = R[t];
10478 MemA[address+4,4] = R[t2];
10479 if wback then R[n] = offset_addr;
10482 bool success = false;
10484 if (ConditionPassed(opcode)) {
10493 switch (encoding) {
10495 // if P == '0' && W == '0' then SEE 'Related encodings';
10496 // t = UInt(Rt); t2 = UInt(Rt2); n = UInt(Rn); imm32 =
10497 // ZeroExtend(imm8:'00', 32);
10498 t = Bits32(opcode, 15, 12);
10499 t2 = Bits32(opcode, 11, 8);
10500 n = Bits32(opcode, 19, 16);
10501 imm32 = Bits32(opcode, 7, 0) << 2;
10503 // index = (P == '1'); add = (U == '1'); wback = (W == '1');
10504 index = BitIsSet(opcode, 24);
10505 add = BitIsSet(opcode, 23);
10506 wback = BitIsSet(opcode, 21);
10508 // if wback && (n == t || n == t2) then UNPREDICTABLE;
10509 if (wback && ((n == t) || (n == t2)))
10512 // if n == 15 || BadReg(t) || BadReg(t2) then UNPREDICTABLE;
10513 if ((n == 15) || BadReg(t) || BadReg(t2))
10519 // if Rt<0> == '1' then UNPREDICTABLE;
10520 // t = UInt(Rt); t2 = t+1; n = UInt(Rn); imm32 = ZeroExtend(imm4H:imm4L,
10522 t = Bits32(opcode, 15, 12);
10523 if (BitIsSet(t, 0))
10527 n = Bits32(opcode, 19, 16);
10528 imm32 = (Bits32(opcode, 11, 8) << 4) | Bits32(opcode, 3, 0);
10530 // index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1');
10531 index = BitIsSet(opcode, 24);
10532 add = BitIsSet(opcode, 23);
10533 wback = BitIsClear(opcode, 24) || BitIsSet(opcode, 21);
10535 // if P == '0' && W == '1' then UNPREDICTABLE;
10536 if (BitIsClear(opcode, 24) && BitIsSet(opcode, 21))
10539 // if wback && (n == 15 || n == t || n == t2) then UNPREDICTABLE;
10540 if (wback && ((n == 15) || (n == t) || (n == t2)))
10543 // if t2 == 15 then UNPREDICTABLE;
10553 RegisterInfo base_reg;
10554 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n, base_reg);
10556 uint32_t Rn = ReadCoreReg(n, &success);
10560 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
10561 addr_t offset_addr;
10563 offset_addr = Rn + imm32;
10565 offset_addr = Rn - imm32;
10567 // address = if index then offset_addr else R[n];
10570 address = offset_addr;
10574 // MemA[address,4] = R[t];
10575 RegisterInfo data_reg;
10576 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + t, data_reg);
10578 uint32_t data = ReadCoreReg(t, &success);
10582 EmulateInstruction::Context context;
10584 context.type = eContextPushRegisterOnStack;
10586 context.type = eContextRegisterStore;
10587 context.SetRegisterToRegisterPlusOffset(data_reg, base_reg, address - Rn);
10589 const uint32_t addr_byte_size = GetAddressByteSize();
10591 if (!MemAWrite(context, address, data, addr_byte_size))
10594 // MemA[address+4,4] = R[t2];
10595 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + t2, data_reg);
10596 context.SetRegisterToRegisterPlusOffset(data_reg, base_reg,
10597 (address + 4) - Rn);
10599 data = ReadCoreReg(t2, &success);
10603 if (!MemAWrite(context, address + 4, data, addr_byte_size))
10606 // if wback then R[n] = offset_addr;
10609 context.type = eContextAdjustStackPointer;
10611 context.type = eContextAdjustBaseRegister;
10612 context.SetAddress(offset_addr);
10614 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n,
10622 // A8.6.201 STRD (register)
10623 bool EmulateInstructionARM::EmulateSTRDReg(const uint32_t opcode,
10624 const ARMEncoding encoding) {
10626 if ConditionPassed() then
10627 EncodingSpecificOperations();
10628 offset_addr = if add then (R[n] + R[m]) else (R[n] - R[m]);
10629 address = if index then offset_addr else R[n];
10630 MemA[address,4] = R[t];
10631 MemA[address+4,4] = R[t2];
10632 if wback then R[n] = offset_addr;
10635 bool success = false;
10637 if (ConditionPassed(opcode)) {
10646 switch (encoding) {
10648 // if Rt<0> == '1' then UNPREDICTABLE;
10649 // t = UInt(Rt); t2 = t+1; n = UInt(Rn); m = UInt(Rm);
10650 t = Bits32(opcode, 15, 12);
10651 if (BitIsSet(t, 0))
10655 n = Bits32(opcode, 19, 16);
10656 m = Bits32(opcode, 3, 0);
10658 // index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1');
10659 index = BitIsSet(opcode, 24);
10660 add = BitIsSet(opcode, 23);
10661 wback = BitIsClear(opcode, 24) || BitIsSet(opcode, 21);
10663 // if P == '0' && W == '1' then UNPREDICTABLE;
10664 if (BitIsClear(opcode, 24) && BitIsSet(opcode, 21))
10667 // if t2 == 15 || m == 15 then UNPREDICTABLE;
10668 if ((t2 == 15) || (m == 15))
10671 // if wback && (n == 15 || n == t || n == t2) then UNPREDICTABLE;
10672 if (wback && ((n == 15) || (n == t) || (n == t2)))
10675 // if ArchVersion() < 6 && wback && m == n then UNPREDICTABLE;
10676 if ((ArchVersion() < 6) && wback && (m == n))
10685 RegisterInfo base_reg;
10686 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n, base_reg);
10687 RegisterInfo offset_reg;
10688 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + m, offset_reg);
10689 RegisterInfo data_reg;
10691 uint32_t Rn = ReadCoreReg(n, &success);
10695 uint32_t Rm = ReadCoreReg(m, &success);
10699 // offset_addr = if add then (R[n] + R[m]) else (R[n] - R[m]);
10700 addr_t offset_addr;
10702 offset_addr = Rn + Rm;
10704 offset_addr = Rn - Rm;
10706 // address = if index then offset_addr else R[n];
10709 address = offset_addr;
10712 // MemA[address,4] = R[t];
10713 uint32_t Rt = ReadCoreReg(t, &success);
10717 EmulateInstruction::Context context;
10719 context.type = eContextPushRegisterOnStack;
10721 context.type = eContextRegisterStore;
10723 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + t, data_reg);
10724 context.SetRegisterToRegisterPlusIndirectOffset(base_reg, offset_reg,
10727 const uint32_t addr_byte_size = GetAddressByteSize();
10729 if (!MemAWrite(context, address, Rt, addr_byte_size))
10732 // MemA[address+4,4] = R[t2];
10733 uint32_t Rt2 = ReadCoreReg(t2, &success);
10737 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + t2, data_reg);
10739 context.SetRegisterToRegisterPlusIndirectOffset(base_reg, offset_reg,
10742 if (!MemAWrite(context, address + 4, Rt2, addr_byte_size))
10745 // if wback then R[n] = offset_addr;
10747 context.type = eContextAdjustBaseRegister;
10748 context.SetAddress(offset_addr);
10750 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n,
10759 // Vector Load Multiple loads multiple extension registers from consecutive
10760 // memory locations using an address from
10761 // an ARM core register.
10762 bool EmulateInstructionARM::EmulateVLDM(const uint32_t opcode,
10763 const ARMEncoding encoding) {
10765 if ConditionPassed() then
10766 EncodingSpecificOperations(); CheckVFPEnabled(TRUE); NullCheckIfThumbEE(n);
10767 address = if add then R[n] else R[n]-imm32;
10768 if wback then R[n] = if add then R[n]+imm32 else R[n]-imm32;
10769 for r = 0 to regs-1
10770 if single_regs then
10771 S[d+r] = MemA[address,4]; address = address+4;
10773 word1 = MemA[address,4]; word2 = MemA[address+4,4]; address = address+8;
10774 // Combine the word-aligned words in the correct order for current endianness.
10775 D[d+r] = if BigEndian() then word1:word2 else word2:word1;
10778 bool success = false;
10780 if (ConditionPassed(opcode)) {
10789 switch (encoding) {
10792 // if P == '0' && U == '0' && W == '0' then SEE 'Related encodings';
10793 // if P == '0' && U == '1' && W == '1' && Rn == '1101' then SEE VPOP;
10794 // if P == '1' && W == '0' then SEE VLDR;
10795 // if P == U && W == '1' then UNDEFINED;
10796 if ((Bit32(opcode, 24) == Bit32(opcode, 23)) && BitIsSet(opcode, 21))
10799 // // Remaining combinations are PUW = 010 (IA without !), 011 (IA with
10800 // !), 101 (DB with !)
10801 // single_regs = FALSE; add = (U == '1'); wback = (W == '1');
10802 single_regs = false;
10803 add = BitIsSet(opcode, 23);
10804 wback = BitIsSet(opcode, 21);
10806 // d = UInt(D:Vd); n = UInt(Rn); imm32 = ZeroExtend(imm8:'00', 32);
10807 d = (Bit32(opcode, 22) << 4) | Bits32(opcode, 15, 12);
10808 n = Bits32(opcode, 19, 16);
10809 imm32 = Bits32(opcode, 7, 0) << 2;
10811 // regs = UInt(imm8) DIV 2; // If UInt(imm8) is odd, see 'FLDMX'.
10812 regs = Bits32(opcode, 7, 0) / 2;
10814 // if n == 15 && (wback || CurrentInstrSet() != InstrSet_ARM) then
10816 if (n == 15 && (wback || CurrentInstrSet() != eModeARM))
10819 // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE;
10820 if ((regs == 0) || (regs > 16) || ((d + regs) > 32))
10827 // if P == '0' && U == '0' && W == '0' then SEE 'Related encodings';
10828 // if P == '0' && U == '1' && W == '1' && Rn == '1101' then SEE VPOP;
10829 // if P == '1' && W == '0' then SEE VLDR;
10830 // if P == U && W == '1' then UNDEFINED;
10831 if ((Bit32(opcode, 24) == Bit32(opcode, 23)) && BitIsSet(opcode, 21))
10834 // // Remaining combinations are PUW = 010 (IA without !), 011 (IA with
10835 // !), 101 (DB with !)
10836 // single_regs = TRUE; add = (U == '1'); wback = (W == '1'); d =
10837 // UInt(Vd:D); n = UInt(Rn);
10838 single_regs = true;
10839 add = BitIsSet(opcode, 23);
10840 wback = BitIsSet(opcode, 21);
10841 d = (Bits32(opcode, 15, 12) << 1) | Bit32(opcode, 22);
10842 n = Bits32(opcode, 19, 16);
10844 // imm32 = ZeroExtend(imm8:'00', 32); regs = UInt(imm8);
10845 imm32 = Bits32(opcode, 7, 0) << 2;
10846 regs = Bits32(opcode, 7, 0);
10848 // if n == 15 && (wback || CurrentInstrSet() != InstrSet_ARM) then
10850 if ((n == 15) && (wback || (CurrentInstrSet() != eModeARM)))
10853 // if regs == 0 || (d+regs) > 32 then UNPREDICTABLE;
10854 if ((regs == 0) || ((d + regs) > 32))
10862 RegisterInfo base_reg;
10863 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n, base_reg);
10865 uint32_t Rn = ReadCoreReg(n, &success);
10869 // address = if add then R[n] else R[n]-imm32;
10874 address = Rn - imm32;
10876 // if wback then R[n] = if add then R[n]+imm32 else R[n]-imm32;
10877 EmulateInstruction::Context context;
10882 value = Rn + imm32;
10884 value = Rn - imm32;
10886 context.type = eContextAdjustBaseRegister;
10887 context.SetImmediateSigned(value - Rn);
10888 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n,
10893 const uint32_t addr_byte_size = GetAddressByteSize();
10894 uint32_t start_reg = single_regs ? dwarf_s0 : dwarf_d0;
10896 context.type = eContextRegisterLoad;
10898 // for r = 0 to regs-1
10899 for (uint32_t r = 0; r < regs; ++r) {
10901 // S[d+r] = MemA[address,4]; address = address+4;
10902 context.SetRegisterPlusOffset(base_reg, address - Rn);
10904 uint32_t data = MemARead(context, address, addr_byte_size, 0, &success);
10908 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF,
10909 start_reg + d + r, data))
10912 address = address + 4;
10914 // word1 = MemA[address,4]; word2 = MemA[address+4,4]; address =
10916 context.SetRegisterPlusOffset(base_reg, address - Rn);
10918 MemARead(context, address, addr_byte_size, 0, &success);
10922 context.SetRegisterPlusOffset(base_reg, (address + 4) - Rn);
10924 MemARead(context, address + 4, addr_byte_size, 0, &success);
10928 address = address + 8;
10929 // // Combine the word-aligned words in the correct order for current
10931 // D[d+r] = if BigEndian() then word1:word2 else word2:word1;
10933 if (GetByteOrder() == eByteOrderBig) {
10935 data = (data << 32) | word2;
10938 data = (data << 32) | word1;
10941 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF,
10942 start_reg + d + r, data))
10951 // Vector Store Multiple stores multiple extension registers to consecutive
10952 // memory locations using an address from an
10953 // ARM core register.
10954 bool EmulateInstructionARM::EmulateVSTM(const uint32_t opcode,
10955 const ARMEncoding encoding) {
10957 if ConditionPassed() then
10958 EncodingSpecificOperations(); CheckVFPEnabled(TRUE); NullCheckIfThumbEE(n);
10959 address = if add then R[n] else R[n]-imm32;
10960 if wback then R[n] = if add then R[n]+imm32 else R[n]-imm32;
10961 for r = 0 to regs-1
10962 if single_regs then
10963 MemA[address,4] = S[d+r]; address = address+4;
10965 // Store as two word-aligned words in the correct order for current endianness.
10966 MemA[address,4] = if BigEndian() then D[d+r]<63:32> else D[d+r]<31:0>;
10967 MemA[address+4,4] = if BigEndian() then D[d+r]<31:0> else D[d+r]<63:32>;
10968 address = address+8;
10971 bool success = false;
10973 if (ConditionPassed(opcode)) {
10982 switch (encoding) {
10985 // if P == '0' && U == '0' && W == '0' then SEE 'Related encodings';
10986 // if P == '1' && U == '0' && W == '1' && Rn == '1101' then SEE VPUSH;
10987 // if P == '1' && W == '0' then SEE VSTR;
10988 // if P == U && W == '1' then UNDEFINED;
10989 if ((Bit32(opcode, 24) == Bit32(opcode, 23)) && BitIsSet(opcode, 21))
10992 // // Remaining combinations are PUW = 010 (IA without !), 011 (IA with
10993 // !), 101 (DB with !)
10994 // single_regs = FALSE; add = (U == '1'); wback = (W == '1');
10995 single_regs = false;
10996 add = BitIsSet(opcode, 23);
10997 wback = BitIsSet(opcode, 21);
10999 // d = UInt(D:Vd); n = UInt(Rn); imm32 = ZeroExtend(imm8:'00', 32);
11000 d = (Bit32(opcode, 22) << 4) | Bits32(opcode, 15, 12);
11001 n = Bits32(opcode, 19, 16);
11002 imm32 = Bits32(opcode, 7, 0) << 2;
11004 // regs = UInt(imm8) DIV 2; // If UInt(imm8) is odd, see 'FSTMX'.
11005 regs = Bits32(opcode, 7, 0) / 2;
11007 // if n == 15 && (wback || CurrentInstrSet() != InstrSet_ARM) then
11009 if ((n == 15) && (wback || (CurrentInstrSet() != eModeARM)))
11012 // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE;
11013 if ((regs == 0) || (regs > 16) || ((d + regs) > 32))
11020 // if P == '0' && U == '0' && W == '0' then SEE 'Related encodings';
11021 // if P == '1' && U == '0' && W == '1' && Rn == '1101' then SEE VPUSH;
11022 // if P == '1' && W == '0' then SEE VSTR;
11023 // if P == U && W == '1' then UNDEFINED;
11024 if ((Bit32(opcode, 24) == Bit32(opcode, 23)) && BitIsSet(opcode, 21))
11027 // // Remaining combinations are PUW = 010 (IA without !), 011 (IA with
11028 // !), 101 (DB with !)
11029 // single_regs = TRUE; add = (U == '1'); wback = (W == '1'); d =
11030 // UInt(Vd:D); n = UInt(Rn);
11031 single_regs = true;
11032 add = BitIsSet(opcode, 23);
11033 wback = BitIsSet(opcode, 21);
11034 d = (Bits32(opcode, 15, 12) << 1) | Bit32(opcode, 22);
11035 n = Bits32(opcode, 19, 16);
11037 // imm32 = ZeroExtend(imm8:'00', 32); regs = UInt(imm8);
11038 imm32 = Bits32(opcode, 7, 0) << 2;
11039 regs = Bits32(opcode, 7, 0);
11041 // if n == 15 && (wback || CurrentInstrSet() != InstrSet_ARM) then
11043 if ((n == 15) && (wback || (CurrentInstrSet() != eModeARM)))
11046 // if regs == 0 || (d+regs) > 32 then UNPREDICTABLE;
11047 if ((regs == 0) || ((d + regs) > 32))
11056 RegisterInfo base_reg;
11057 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n, base_reg);
11059 uint32_t Rn = ReadCoreReg(n, &success);
11063 // address = if add then R[n] else R[n]-imm32;
11068 address = Rn - imm32;
11070 EmulateInstruction::Context context;
11071 // if wback then R[n] = if add then R[n]+imm32 else R[n]-imm32;
11075 value = Rn + imm32;
11077 value = Rn - imm32;
11079 context.type = eContextAdjustBaseRegister;
11080 context.SetRegisterPlusOffset(base_reg, value - Rn);
11082 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n,
11087 const uint32_t addr_byte_size = GetAddressByteSize();
11088 uint32_t start_reg = single_regs ? dwarf_s0 : dwarf_d0;
11090 context.type = eContextRegisterStore;
11091 // for r = 0 to regs-1
11092 for (uint32_t r = 0; r < regs; ++r) {
11095 // MemA[address,4] = S[d+r]; address = address+4;
11096 uint32_t data = ReadRegisterUnsigned(eRegisterKindDWARF,
11097 start_reg + d + r, 0, &success);
11101 RegisterInfo data_reg;
11102 GetRegisterInfo(eRegisterKindDWARF, start_reg + d + r, data_reg);
11103 context.SetRegisterToRegisterPlusOffset(data_reg, base_reg,
11105 if (!MemAWrite(context, address, data, addr_byte_size))
11108 address = address + 4;
11110 // // Store as two word-aligned words in the correct order for current
11112 // MemA[address,4] = if BigEndian() then D[d+r]<63:32> else
11114 // MemA[address+4,4] = if BigEndian() then D[d+r]<31:0> else
11116 uint64_t data = ReadRegisterUnsigned(eRegisterKindDWARF,
11117 start_reg + d + r, 0, &success);
11121 RegisterInfo data_reg;
11122 GetRegisterInfo(eRegisterKindDWARF, start_reg + d + r, data_reg);
11124 if (GetByteOrder() == eByteOrderBig) {
11125 context.SetRegisterToRegisterPlusOffset(data_reg, base_reg,
11127 if (!MemAWrite(context, address, Bits64(data, 63, 32),
11131 context.SetRegisterToRegisterPlusOffset(data_reg, base_reg,
11132 (address + 4) - Rn);
11133 if (!MemAWrite(context, address + 4, Bits64(data, 31, 0),
11137 context.SetRegisterToRegisterPlusOffset(data_reg, base_reg,
11139 if (!MemAWrite(context, address, Bits64(data, 31, 0), addr_byte_size))
11142 context.SetRegisterToRegisterPlusOffset(data_reg, base_reg,
11143 (address + 4) - Rn);
11144 if (!MemAWrite(context, address + 4, Bits64(data, 63, 32),
11148 // address = address+8;
11149 address = address + 8;
11157 // This instruction loads a single extension register from memory, using an
11158 // address from an ARM core register, with
11159 // an optional offset.
11160 bool EmulateInstructionARM::EmulateVLDR(const uint32_t opcode,
11161 ARMEncoding encoding) {
11163 if ConditionPassed() then
11164 EncodingSpecificOperations(); CheckVFPEnabled(TRUE); NullCheckIfThumbEE(n);
11165 base = if n == 15 then Align(PC,4) else R[n];
11166 address = if add then (base + imm32) else (base - imm32);
11168 S[d] = MemA[address,4];
11170 word1 = MemA[address,4]; word2 = MemA[address+4,4];
11171 // Combine the word-aligned words in the correct order for current endianness.
11172 D[d] = if BigEndian() then word1:word2 else word2:word1;
11175 bool success = false;
11177 if (ConditionPassed(opcode)) {
11184 switch (encoding) {
11187 // single_reg = FALSE; add = (U == '1'); imm32 = ZeroExtend(imm8:'00',
11189 single_reg = false;
11190 add = BitIsSet(opcode, 23);
11191 imm32 = Bits32(opcode, 7, 0) << 2;
11193 // d = UInt(D:Vd); n = UInt(Rn);
11194 d = (Bit32(opcode, 22) << 4) | Bits32(opcode, 15, 12);
11195 n = Bits32(opcode, 19, 16);
11201 // single_reg = TRUE; add = (U == '1'); imm32 = ZeroExtend(imm8:'00', 32);
11203 add = BitIsSet(opcode, 23);
11204 imm32 = Bits32(opcode, 7, 0) << 2;
11206 // d = UInt(Vd:D); n = UInt(Rn);
11207 d = (Bits32(opcode, 15, 12) << 1) | Bit32(opcode, 22);
11208 n = Bits32(opcode, 19, 16);
11215 RegisterInfo base_reg;
11216 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n, base_reg);
11218 uint32_t Rn = ReadCoreReg(n, &success);
11222 // base = if n == 15 then Align(PC,4) else R[n];
11225 base = AlignPC(Rn);
11229 // address = if add then (base + imm32) else (base - imm32);
11232 address = base + imm32;
11234 address = base - imm32;
11236 const uint32_t addr_byte_size = GetAddressByteSize();
11237 uint32_t start_reg = single_reg ? dwarf_s0 : dwarf_d0;
11239 EmulateInstruction::Context context;
11240 context.type = eContextRegisterLoad;
11241 context.SetRegisterPlusOffset(base_reg, address - base);
11244 // S[d] = MemA[address,4];
11245 uint32_t data = MemARead(context, address, addr_byte_size, 0, &success);
11249 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, start_reg + d,
11253 // word1 = MemA[address,4]; word2 = MemA[address+4,4];
11254 uint32_t word1 = MemARead(context, address, addr_byte_size, 0, &success);
11258 context.SetRegisterPlusOffset(base_reg, (address + 4) - base);
11260 MemARead(context, address + 4, addr_byte_size, 0, &success);
11263 // // Combine the word-aligned words in the correct order for current
11265 // D[d] = if BigEndian() then word1:word2 else word2:word1;
11267 if (GetByteOrder() == eByteOrderBig) {
11269 data64 = (data64 << 32) | word2;
11272 data64 = (data64 << 32) | word1;
11275 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, start_reg + d,
11284 // This instruction stores a signle extension register to memory, using an
11285 // address from an ARM core register, with an
11286 // optional offset.
11287 bool EmulateInstructionARM::EmulateVSTR(const uint32_t opcode,
11288 ARMEncoding encoding) {
11290 if ConditionPassed() then
11291 EncodingSpecificOperations(); CheckVFPEnabled(TRUE); NullCheckIfThumbEE(n);
11292 address = if add then (R[n] + imm32) else (R[n] - imm32);
11294 MemA[address,4] = S[d];
11296 // Store as two word-aligned words in the correct order for current endianness.
11297 MemA[address,4] = if BigEndian() then D[d]<63:32> else D[d]<31:0>;
11298 MemA[address+4,4] = if BigEndian() then D[d]<31:0> else D[d]<63:32>;
11301 bool success = false;
11303 if (ConditionPassed(opcode)) {
11310 switch (encoding) {
11313 // single_reg = FALSE; add = (U == '1'); imm32 = ZeroExtend(imm8:'00',
11315 single_reg = false;
11316 add = BitIsSet(opcode, 23);
11317 imm32 = Bits32(opcode, 7, 0) << 2;
11319 // d = UInt(D:Vd); n = UInt(Rn);
11320 d = (Bit32(opcode, 22) << 4) | Bits32(opcode, 15, 12);
11321 n = Bits32(opcode, 19, 16);
11323 // if n == 15 && CurrentInstrSet() != InstrSet_ARM then UNPREDICTABLE;
11324 if ((n == 15) && (CurrentInstrSet() != eModeARM))
11331 // single_reg = TRUE; add = (U == '1'); imm32 = ZeroExtend(imm8:'00', 32);
11333 add = BitIsSet(opcode, 23);
11334 imm32 = Bits32(opcode, 7, 0) << 2;
11336 // d = UInt(Vd:D); n = UInt(Rn);
11337 d = (Bits32(opcode, 15, 12) << 1) | Bit32(opcode, 22);
11338 n = Bits32(opcode, 19, 16);
11340 // if n == 15 && CurrentInstrSet() != InstrSet_ARM then UNPREDICTABLE;
11341 if ((n == 15) && (CurrentInstrSet() != eModeARM))
11350 RegisterInfo base_reg;
11351 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n, base_reg);
11353 uint32_t Rn = ReadCoreReg(n, &success);
11357 // address = if add then (R[n] + imm32) else (R[n] - imm32);
11360 address = Rn + imm32;
11362 address = Rn - imm32;
11364 const uint32_t addr_byte_size = GetAddressByteSize();
11365 uint32_t start_reg = single_reg ? dwarf_s0 : dwarf_d0;
11367 RegisterInfo data_reg;
11368 GetRegisterInfo(eRegisterKindDWARF, start_reg + d, data_reg);
11369 EmulateInstruction::Context context;
11370 context.type = eContextRegisterStore;
11371 context.SetRegisterToRegisterPlusOffset(data_reg, base_reg, address - Rn);
11374 // MemA[address,4] = S[d];
11376 ReadRegisterUnsigned(eRegisterKindDWARF, start_reg + d, 0, &success);
11380 if (!MemAWrite(context, address, data, addr_byte_size))
11383 // // Store as two word-aligned words in the correct order for current
11385 // MemA[address,4] = if BigEndian() then D[d]<63:32> else D[d]<31:0>;
11386 // MemA[address+4,4] = if BigEndian() then D[d]<31:0> else D[d]<63:32>;
11388 ReadRegisterUnsigned(eRegisterKindDWARF, start_reg + d, 0, &success);
11392 if (GetByteOrder() == eByteOrderBig) {
11393 if (!MemAWrite(context, address, Bits64(data, 63, 32), addr_byte_size))
11396 context.SetRegisterToRegisterPlusOffset(data_reg, base_reg,
11397 (address + 4) - Rn);
11398 if (!MemAWrite(context, address + 4, Bits64(data, 31, 0),
11402 if (!MemAWrite(context, address, Bits64(data, 31, 0), addr_byte_size))
11405 context.SetRegisterToRegisterPlusOffset(data_reg, base_reg,
11406 (address + 4) - Rn);
11407 if (!MemAWrite(context, address + 4, Bits64(data, 63, 32),
11416 // A8.6.307 VLDI1 (multiple single elements)
11417 // This instruction loads elements from memory into one, two, three or four
11418 // registers, without de-interleaving. Every
11419 // element of each register is loaded.
11420 bool EmulateInstructionARM::EmulateVLD1Multiple(const uint32_t opcode,
11421 ARMEncoding encoding) {
11423 if ConditionPassed() then
11424 EncodingSpecificOperations(); CheckAdvSIMDEnabled(); NullCheckIfThumbEE(n);
11425 address = R[n]; if (address MOD alignment) != 0 then GenerateAlignmentException();
11426 if wback then R[n] = R[n] + (if register_index then R[m] else 8*regs);
11427 for r = 0 to regs-1
11428 for e = 0 to elements-1
11429 Elem[D[d+r],e,esize] = MemU[address,ebytes];
11430 address = address + ebytes;
11433 bool success = false;
11435 if (ConditionPassed(opcode)) {
11437 uint32_t alignment;
11445 bool register_index;
11447 switch (encoding) {
11449 case eEncodingA1: {
11452 // regs = 1; if align<1> == '1' then UNDEFINED;
11454 // regs = 2; if align == '11' then UNDEFINED;
11456 // regs = 3; if align<1> == '1' then UNDEFINED;
11460 // SEE 'Related encodings';
11461 uint32_t type = Bits32(opcode, 11, 8);
11462 uint32_t align = Bits32(opcode, 5, 4);
11463 if (type == 7) // '0111'
11466 if (BitIsSet(align, 1))
11468 } else if (type == 10) // '1010'
11474 } else if (type == 6) // '0110'
11477 if (BitIsSet(align, 1))
11479 } else if (type == 2) // '0010'
11485 // alignment = if align == '00' then 1 else 4 << UInt(align);
11489 alignment = 4 << align;
11491 // ebytes = 1 << UInt(size); esize = 8 * ebytes; elements = 8 DIV ebytes;
11492 ebytes = 1 << Bits32(opcode, 7, 6);
11493 esize = 8 * ebytes;
11494 elements = 8 / ebytes;
11496 // d = UInt(D:Vd); n = UInt(Rn); m = UInt(Rm);
11497 d = (Bit32(opcode, 22) << 4) | Bits32(opcode, 15, 12);
11498 n = Bits32(opcode, 19, 15);
11499 m = Bits32(opcode, 3, 0);
11501 // wback = (m != 15); register_index = (m != 15 && m != 13);
11503 register_index = ((m != 15) && (m != 13));
11505 // if d+regs > 32 then UNPREDICTABLE;
11506 if ((d + regs) > 32)
11514 RegisterInfo base_reg;
11515 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n, base_reg);
11517 uint32_t Rn = ReadCoreReg(n, &success);
11521 // address = R[n]; if (address MOD alignment) != 0 then
11522 // GenerateAlignmentException();
11523 addr_t address = Rn;
11524 if ((address % alignment) != 0)
11527 EmulateInstruction::Context context;
11528 // if wback then R[n] = R[n] + (if register_index then R[m] else 8*regs);
11530 uint32_t Rm = ReadCoreReg(m, &success);
11535 if (register_index)
11540 uint32_t value = Rn + offset;
11541 context.type = eContextAdjustBaseRegister;
11542 context.SetRegisterPlusOffset(base_reg, offset);
11544 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n,
11549 // for r = 0 to regs-1
11550 for (uint32_t r = 0; r < regs; ++r) {
11551 // for e = 0 to elements-1
11552 uint64_t assembled_data = 0;
11553 for (uint32_t e = 0; e < elements; ++e) {
11554 // Elem[D[d+r],e,esize] = MemU[address,ebytes];
11555 context.type = eContextRegisterLoad;
11556 context.SetRegisterPlusOffset(base_reg, address - Rn);
11557 uint64_t data = MemURead(context, address, ebytes, 0, &success);
11562 (data << (e * esize)) |
11563 assembled_data; // New data goes to the left of existing data
11565 // address = address + ebytes;
11566 address = address + ebytes;
11568 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_d0 + d + r,
11576 // A8.6.308 VLD1 (single element to one lane)
11578 bool EmulateInstructionARM::EmulateVLD1Single(const uint32_t opcode,
11579 const ARMEncoding encoding) {
11581 if ConditionPassed() then
11582 EncodingSpecificOperations(); CheckAdvSIMDEnabled(); NullCheckIfThumbEE(n);
11583 address = R[n]; if (address MOD alignment) != 0 then GenerateAlignmentException();
11584 if wback then R[n] = R[n] + (if register_index then R[m] else ebytes);
11585 Elem[D[d],index,esize] = MemU[address,ebytes];
11588 bool success = false;
11590 if (ConditionPassed(opcode)) {
11594 uint32_t alignment;
11599 bool register_index;
11601 switch (encoding) {
11603 case eEncodingA1: {
11604 uint32_t size = Bits32(opcode, 11, 10);
11605 uint32_t index_align = Bits32(opcode, 7, 4);
11606 // if size == '11' then SEE VLD1 (single element to all lanes);
11608 return EmulateVLD1SingleAll(opcode, encoding);
11610 if (size == 0) // when '00'
11612 // if index_align<0> != '0' then UNDEFINED;
11613 if (BitIsClear(index_align, 0))
11616 // ebytes = 1; esize = 8; index = UInt(index_align<3:1>); alignment = 1;
11619 index = Bits32(index_align, 3, 1);
11621 } else if (size == 1) // when '01'
11623 // if index_align<1> != '0' then UNDEFINED;
11624 if (BitIsClear(index_align, 1))
11627 // ebytes = 2; esize = 16; index = UInt(index_align<3:2>);
11630 index = Bits32(index_align, 3, 2);
11632 // alignment = if index_align<0> == '0' then 1 else 2;
11633 if (BitIsClear(index_align, 0))
11637 } else if (size == 2) // when '10'
11639 // if index_align<2> != '0' then UNDEFINED;
11640 if (BitIsClear(index_align, 2))
11643 // if index_align<1:0> != '00' && index_align<1:0> != '11' then
11645 if ((Bits32(index_align, 1, 0) != 0) &&
11646 (Bits32(index_align, 1, 0) != 3))
11649 // ebytes = 4; esize = 32; index = UInt(index_align<3>);
11652 index = Bit32(index_align, 3);
11654 // alignment = if index_align<1:0> == '00' then 1 else 4;
11655 if (Bits32(index_align, 1, 0) == 0)
11662 // d = UInt(D:Vd); n = UInt(Rn); m = UInt(Rm);
11663 d = (Bit32(opcode, 22) << 4) | Bits32(opcode, 15, 12);
11664 n = Bits32(opcode, 19, 16);
11665 m = Bits32(opcode, 3, 0);
11667 // wback = (m != 15); register_index = (m != 15 && m != 13); if n == 15
11668 // then UNPREDICTABLE;
11670 register_index = ((m != 15) && (m != 13));
11681 RegisterInfo base_reg;
11682 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n, base_reg);
11684 uint32_t Rn = ReadCoreReg(n, &success);
11688 // address = R[n]; if (address MOD alignment) != 0 then
11689 // GenerateAlignmentException();
11690 addr_t address = Rn;
11691 if ((address % alignment) != 0)
11694 EmulateInstruction::Context context;
11695 // if wback then R[n] = R[n] + (if register_index then R[m] else ebytes);
11697 uint32_t Rm = ReadCoreReg(m, &success);
11702 if (register_index)
11707 uint32_t value = Rn + offset;
11709 context.type = eContextAdjustBaseRegister;
11710 context.SetRegisterPlusOffset(base_reg, offset);
11712 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n,
11717 // Elem[D[d],index,esize] = MemU[address,ebytes];
11718 uint32_t element = MemURead(context, address, esize, 0, &success);
11722 element = element << (index * esize);
11724 uint64_t reg_data =
11725 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_d0 + d, 0, &success);
11729 uint64_t all_ones = -1;
11730 uint64_t mask = all_ones
11731 << ((index + 1) * esize); // mask is all 1's to left of
11732 // where 'element' goes, & all 0's
11733 // at element & to the right of element.
11735 mask = mask | Bits64(all_ones, (index * esize) - 1,
11736 0); // add 1's to the right of where 'element' goes.
11737 // now mask should be 0's where element goes & 1's
11738 // everywhere else.
11740 uint64_t masked_reg =
11741 reg_data & mask; // Take original reg value & zero out 'element' bits
11743 masked_reg & element; // Put 'element' into those bits in reg_data.
11745 context.type = eContextRegisterLoad;
11746 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + d,
11753 // A8.6.391 VST1 (multiple single elements)
11754 // Vector Store (multiple single elements) stores elements to memory from one,
11755 // two, three, or four registers, without
11756 // interleaving. Every element of each register is stored.
11757 bool EmulateInstructionARM::EmulateVST1Multiple(const uint32_t opcode,
11758 ARMEncoding encoding) {
11760 if ConditionPassed() then
11761 EncodingSpecificOperations(); CheckAdvSIMDEnabled(); NullCheckIfThumbEE(n);
11762 address = R[n]; if (address MOD alignment) != 0 then GenerateAlignmentException();
11763 if wback then R[n] = R[n] + (if register_index then R[m] else 8*regs);
11764 for r = 0 to regs-1
11765 for e = 0 to elements-1
11766 MemU[address,ebytes] = Elem[D[d+r],e,esize];
11767 address = address + ebytes;
11770 bool success = false;
11772 if (ConditionPassed(opcode)) {
11774 uint32_t alignment;
11782 bool register_index;
11784 switch (encoding) {
11786 case eEncodingA1: {
11787 uint32_t type = Bits32(opcode, 11, 8);
11788 uint32_t align = Bits32(opcode, 5, 4);
11791 if (type == 7) // when '0111'
11793 // regs = 1; if align<1> == '1' then UNDEFINED;
11795 if (BitIsSet(align, 1))
11797 } else if (type == 10) // when '1010'
11799 // regs = 2; if align == '11' then UNDEFINED;
11803 } else if (type == 6) // when '0110'
11805 // regs = 3; if align<1> == '1' then UNDEFINED;
11807 if (BitIsSet(align, 1))
11809 } else if (type == 2) // when '0010'
11813 // SEE 'Related encodings';
11816 // alignment = if align == '00' then 1 else 4 << UInt(align);
11820 alignment = 4 << align;
11822 // ebytes = 1 << UInt(size); esize = 8 * ebytes; elements = 8 DIV ebytes;
11823 ebytes = 1 << Bits32(opcode, 7, 6);
11824 esize = 8 * ebytes;
11825 elements = 8 / ebytes;
11827 // d = UInt(D:Vd); n = UInt(Rn); m = UInt(Rm);
11828 d = (Bit32(opcode, 22) << 4) | Bits32(opcode, 15, 12);
11829 n = Bits32(opcode, 19, 16);
11830 m = Bits32(opcode, 3, 0);
11832 // wback = (m != 15); register_index = (m != 15 && m != 13);
11834 register_index = ((m != 15) && (m != 13));
11836 // if d+regs > 32 then UNPREDICTABLE; if n == 15 then UNPREDICTABLE;
11837 if ((d + regs) > 32)
11849 RegisterInfo base_reg;
11850 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n, base_reg);
11852 uint32_t Rn = ReadCoreReg(n, &success);
11856 // address = R[n]; if (address MOD alignment) != 0 then
11857 // GenerateAlignmentException();
11858 addr_t address = Rn;
11859 if ((address % alignment) != 0)
11862 EmulateInstruction::Context context;
11863 // if wback then R[n] = R[n] + (if register_index then R[m] else 8*regs);
11865 uint32_t Rm = ReadCoreReg(m, &success);
11870 if (register_index)
11875 context.type = eContextAdjustBaseRegister;
11876 context.SetRegisterPlusOffset(base_reg, offset);
11878 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n,
11883 RegisterInfo data_reg;
11884 context.type = eContextRegisterStore;
11885 // for r = 0 to regs-1
11886 for (uint32_t r = 0; r < regs; ++r) {
11887 GetRegisterInfo(eRegisterKindDWARF, dwarf_d0 + d + r, data_reg);
11888 uint64_t register_data = ReadRegisterUnsigned(
11889 eRegisterKindDWARF, dwarf_d0 + d + r, 0, &success);
11893 // for e = 0 to elements-1
11894 for (uint32_t e = 0; e < elements; ++e) {
11895 // MemU[address,ebytes] = Elem[D[d+r],e,esize];
11896 uint64_t word = Bits64(register_data, ((e + 1) * esize) - 1, e * esize);
11898 context.SetRegisterToRegisterPlusOffset(data_reg, base_reg,
11900 if (!MemUWrite(context, address, word, ebytes))
11903 // address = address + ebytes;
11904 address = address + ebytes;
11911 // A8.6.392 VST1 (single element from one lane)
11912 // This instruction stores one element to memory from one element of a register.
11913 bool EmulateInstructionARM::EmulateVST1Single(const uint32_t opcode,
11914 ARMEncoding encoding) {
11916 if ConditionPassed() then
11917 EncodingSpecificOperations(); CheckAdvSIMDEnabled(); NullCheckIfThumbEE(n);
11918 address = R[n]; if (address MOD alignment) != 0 then GenerateAlignmentException();
11919 if wback then R[n] = R[n] + (if register_index then R[m] else ebytes);
11920 MemU[address,ebytes] = Elem[D[d],index,esize];
11923 bool success = false;
11925 if (ConditionPassed(opcode)) {
11929 uint32_t alignment;
11934 bool register_index;
11936 switch (encoding) {
11938 case eEncodingA1: {
11939 uint32_t size = Bits32(opcode, 11, 10);
11940 uint32_t index_align = Bits32(opcode, 7, 4);
11942 // if size == '11' then UNDEFINED;
11947 if (size == 0) // when '00'
11949 // if index_align<0> != '0' then UNDEFINED;
11950 if (BitIsClear(index_align, 0))
11952 // ebytes = 1; esize = 8; index = UInt(index_align<3:1>); alignment = 1;
11955 index = Bits32(index_align, 3, 1);
11957 } else if (size == 1) // when '01'
11959 // if index_align<1> != '0' then UNDEFINED;
11960 if (BitIsClear(index_align, 1))
11963 // ebytes = 2; esize = 16; index = UInt(index_align<3:2>);
11966 index = Bits32(index_align, 3, 2);
11968 // alignment = if index_align<0> == '0' then 1 else 2;
11969 if (BitIsClear(index_align, 0))
11973 } else if (size == 2) // when '10'
11975 // if index_align<2> != '0' then UNDEFINED;
11976 if (BitIsClear(index_align, 2))
11979 // if index_align<1:0> != '00' && index_align<1:0> != '11' then
11981 if ((Bits32(index_align, 1, 0) != 0) &&
11982 (Bits32(index_align, 1, 0) != 3))
11985 // ebytes = 4; esize = 32; index = UInt(index_align<3>);
11988 index = Bit32(index_align, 3);
11990 // alignment = if index_align<1:0> == '00' then 1 else 4;
11991 if (Bits32(index_align, 1, 0) == 0)
11998 // d = UInt(D:Vd); n = UInt(Rn); m = UInt(Rm);
11999 d = (Bit32(opcode, 22) << 4) | Bits32(opcode, 15, 12);
12000 n = Bits32(opcode, 19, 16);
12001 m = Bits32(opcode, 3, 0);
12003 // wback = (m != 15); register_index = (m != 15 && m != 13); if n == 15
12004 // then UNPREDICTABLE;
12006 register_index = ((m != 15) && (m != 13));
12016 RegisterInfo base_reg;
12017 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n, base_reg);
12019 uint32_t Rn = ReadCoreReg(n, &success);
12023 // address = R[n]; if (address MOD alignment) != 0 then
12024 // GenerateAlignmentException();
12025 addr_t address = Rn;
12026 if ((address % alignment) != 0)
12029 EmulateInstruction::Context context;
12030 // if wback then R[n] = R[n] + (if register_index then R[m] else ebytes);
12032 uint32_t Rm = ReadCoreReg(m, &success);
12037 if (register_index)
12042 context.type = eContextAdjustBaseRegister;
12043 context.SetRegisterPlusOffset(base_reg, offset);
12045 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n,
12050 // MemU[address,ebytes] = Elem[D[d],index,esize];
12051 uint64_t register_data =
12052 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_d0 + d, 0, &success);
12057 Bits64(register_data, ((index + 1) * esize) - 1, index * esize);
12059 RegisterInfo data_reg;
12060 GetRegisterInfo(eRegisterKindDWARF, dwarf_d0 + d, data_reg);
12061 context.type = eContextRegisterStore;
12062 context.SetRegisterToRegisterPlusOffset(data_reg, base_reg, address - Rn);
12064 if (!MemUWrite(context, address, word, ebytes))
12070 // A8.6.309 VLD1 (single element to all lanes)
12071 // This instruction loads one element from memory into every element of one or
12073 bool EmulateInstructionARM::EmulateVLD1SingleAll(const uint32_t opcode,
12074 const ARMEncoding encoding) {
12076 if ConditionPassed() then
12077 EncodingSpecificOperations(); CheckAdvSIMDEnabled(); NullCheckIfThumbEE(n);
12078 address = R[n]; if (address MOD alignment) != 0 then GenerateAlignmentException();
12079 if wback then R[n] = R[n] + (if register_index then R[m] else ebytes);
12080 replicated_element = Replicate(MemU[address,ebytes], elements);
12081 for r = 0 to regs-1
12082 D[d+r] = replicated_element;
12085 bool success = false;
12087 if (ConditionPassed(opcode)) {
12091 uint32_t alignment;
12096 bool register_index;
12098 switch (encoding) {
12100 case eEncodingA1: {
12101 // if size == '11' || (size == '00' && a == '1') then UNDEFINED;
12102 uint32_t size = Bits32(opcode, 7, 6);
12103 if ((size == 3) || ((size == 0) && BitIsSet(opcode, 4)))
12106 // ebytes = 1 << UInt(size); elements = 8 DIV ebytes; regs = if T == '0'
12108 ebytes = 1 << size;
12109 elements = 8 / ebytes;
12110 if (BitIsClear(opcode, 5))
12115 // alignment = if a == '0' then 1 else ebytes;
12116 if (BitIsClear(opcode, 4))
12119 alignment = ebytes;
12121 // d = UInt(D:Vd); n = UInt(Rn); m = UInt(Rm);
12122 d = (Bit32(opcode, 22) << 4) | Bits32(opcode, 15, 12);
12123 n = Bits32(opcode, 19, 16);
12124 m = Bits32(opcode, 3, 0);
12126 // wback = (m != 15); register_index = (m != 15 && m != 13);
12128 register_index = ((m != 15) && (m != 13));
12130 // if d+regs > 32 then UNPREDICTABLE; if n == 15 then UNPREDICTABLE;
12131 if ((d + regs) > 32)
12142 RegisterInfo base_reg;
12143 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n, base_reg);
12145 uint32_t Rn = ReadCoreReg(n, &success);
12149 // address = R[n]; if (address MOD alignment) != 0 then
12150 // GenerateAlignmentException();
12151 addr_t address = Rn;
12152 if ((address % alignment) != 0)
12155 EmulateInstruction::Context context;
12156 // if wback then R[n] = R[n] + (if register_index then R[m] else ebytes);
12158 uint32_t Rm = ReadCoreReg(m, &success);
12163 if (register_index)
12168 context.type = eContextAdjustBaseRegister;
12169 context.SetRegisterPlusOffset(base_reg, offset);
12171 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n,
12176 // replicated_element = Replicate(MemU[address,ebytes], elements);
12178 context.type = eContextRegisterLoad;
12179 uint64_t word = MemURead(context, address, ebytes, 0, &success);
12183 uint64_t replicated_element = 0;
12184 uint32_t esize = ebytes * 8;
12185 for (uint32_t e = 0; e < elements; ++e)
12186 replicated_element =
12187 (replicated_element << esize) | Bits64(word, esize - 1, 0);
12189 // for r = 0 to regs-1
12190 for (uint32_t r = 0; r < regs; ++r) {
12191 // D[d+r] = replicated_element;
12192 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_d0 + d + r,
12193 replicated_element))
12200 // B6.2.13 SUBS PC, LR and related instructions
12201 // The SUBS PC, LR, #<const? instruction provides an exception return without
12202 // the use of the stack. It subtracts the
12203 // immediate constant from the LR, branches to the resulting address, and also
12204 // copies the SPSR to the CPSR.
12205 bool EmulateInstructionARM::EmulateSUBSPcLrEtc(const uint32_t opcode,
12206 const ARMEncoding encoding) {
12208 if ConditionPassed() then
12209 EncodingSpecificOperations();
12210 if CurrentInstrSet() == InstrSet_ThumbEE then
12212 operand2 = if register_form then Shift(R[m], shift_t, shift_n, APSR.C) else imm32;
12214 when '0000' result = R[n] AND operand2; // AND
12215 when '0001' result = R[n] EOR operand2; // EOR
12216 when '0010' (result, -, -) = AddWithCarry(R[n], NOT(operand2), '1'); // SUB
12217 when '0011' (result, -, -) = AddWithCarry(NOT(R[n]), operand2, '1'); // RSB
12218 when '0100' (result, -, -) = AddWithCarry(R[n], operand2, '0'); // ADD
12219 when '0101' (result, -, -) = AddWithCarry(R[n], operand2, APSR.c); // ADC
12220 when '0110' (result, -, -) = AddWithCarry(R[n], NOT(operand2), APSR.C); // SBC
12221 when '0111' (result, -, -) = AddWithCarry(NOT(R[n]), operand2, APSR.C); // RSC
12222 when '1100' result = R[n] OR operand2; // ORR
12223 when '1101' result = operand2; // MOV
12224 when '1110' result = R[n] AND NOT(operand2); // BIC
12225 when '1111' result = NOT(operand2); // MVN
12226 CPSRWriteByInstr(SPSR[], '1111', TRUE);
12227 BranchWritePC(result);
12230 bool success = false;
12232 if (ConditionPassed(opcode)) {
12236 bool register_form;
12237 ARM_ShifterType shift_t;
12241 switch (encoding) {
12243 // if CurrentInstrSet() == InstrSet_ThumbEE then UNPREDICTABLE
12244 // n = 14; imm32 = ZeroExtend(imm8, 32); register_form = FALSE; opcode =
12245 // '0010'; // = SUB
12247 imm32 = Bits32(opcode, 7, 0);
12248 register_form = false;
12251 // if InITBlock() && !LastInITBlock() then UNPREDICTABLE;
12252 if (InITBlock() && !LastInITBlock())
12258 // n = UInt(Rn); imm32 = ARMExpandImm(imm12); register_form = FALSE;
12259 n = Bits32(opcode, 19, 16);
12260 imm32 = ARMExpandImm(opcode);
12261 register_form = false;
12262 code = Bits32(opcode, 24, 21);
12267 // n = UInt(Rn); m = UInt(Rm); register_form = TRUE;
12268 n = Bits32(opcode, 19, 16);
12269 m = Bits32(opcode, 3, 0);
12270 register_form = true;
12272 // (shift_t, shift_n) = DecodeImmShift(type, imm5);
12273 shift_n = DecodeImmShiftARM(opcode, shift_t);
12281 // operand2 = if register_form then Shift(R[m], shift_t, shift_n, APSR.C)
12284 if (register_form) {
12285 uint32_t Rm = ReadCoreReg(m, &success);
12289 operand2 = Shift(Rm, shift_t, shift_n, APSR_C, &success);
12296 uint32_t Rn = ReadCoreReg(n, &success);
12300 AddWithCarryResult result;
12304 case 0: // when '0000'
12305 // result = R[n] AND operand2; // AND
12306 result.result = Rn & operand2;
12309 case 1: // when '0001'
12310 // result = R[n] EOR operand2; // EOR
12311 result.result = Rn ^ operand2;
12314 case 2: // when '0010'
12315 // (result, -, -) = AddWithCarry(R[n], NOT(operand2), '1'); // SUB
12316 result = AddWithCarry(Rn, ~(operand2), 1);
12319 case 3: // when '0011'
12320 // (result, -, -) = AddWithCarry(NOT(R[n]), operand2, '1'); // RSB
12321 result = AddWithCarry(~(Rn), operand2, 1);
12324 case 4: // when '0100'
12325 // (result, -, -) = AddWithCarry(R[n], operand2, '0'); // ADD
12326 result = AddWithCarry(Rn, operand2, 0);
12329 case 5: // when '0101'
12330 // (result, -, -) = AddWithCarry(R[n], operand2, APSR.c); // ADC
12331 result = AddWithCarry(Rn, operand2, APSR_C);
12334 case 6: // when '0110'
12335 // (result, -, -) = AddWithCarry(R[n], NOT(operand2), APSR.C); // SBC
12336 result = AddWithCarry(Rn, ~(operand2), APSR_C);
12339 case 7: // when '0111'
12340 // (result, -, -) = AddWithCarry(NOT(R[n]), operand2, APSR.C); // RSC
12341 result = AddWithCarry(~(Rn), operand2, APSR_C);
12344 case 10: // when '1100'
12345 // result = R[n] OR operand2; // ORR
12346 result.result = Rn | operand2;
12349 case 11: // when '1101'
12350 // result = operand2; // MOV
12351 result.result = operand2;
12354 case 12: // when '1110'
12355 // result = R[n] AND NOT(operand2); // BIC
12356 result.result = Rn & ~(operand2);
12359 case 15: // when '1111'
12360 // result = NOT(operand2); // MVN
12361 result.result = ~(operand2);
12367 // CPSRWriteByInstr(SPSR[], '1111', TRUE);
12369 // For now, in emulation mode, we don't have access to the SPSR, so we will
12370 // use the CPSR instead, and hope for
12373 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_cpsr, 0, &success);
12377 CPSRWriteByInstr(spsr, 15, true);
12379 // BranchWritePC(result);
12380 EmulateInstruction::Context context;
12381 context.type = eContextAdjustPC;
12382 context.SetImmediate(result.result);
12384 BranchWritePC(context, result.result);
12389 EmulateInstructionARM::ARMOpcode *
12390 EmulateInstructionARM::GetARMOpcodeForInstruction(const uint32_t opcode,
12391 uint32_t arm_isa) {
12392 static ARMOpcode g_arm_opcodes[] = {
12393 //----------------------------------------------------------------------
12394 // Prologue instructions
12395 //----------------------------------------------------------------------
12397 // push register(s)
12398 {0x0fff0000, 0x092d0000, ARMvAll, eEncodingA1, No_VFP, eSize32,
12399 &EmulateInstructionARM::EmulatePUSH, "push <registers>"},
12400 {0x0fff0fff, 0x052d0004, ARMvAll, eEncodingA2, No_VFP, eSize32,
12401 &EmulateInstructionARM::EmulatePUSH, "push <register>"},
12403 // set r7 to point to a stack offset
12404 {0x0ffff000, 0x028d7000, ARMvAll, eEncodingA1, No_VFP, eSize32,
12405 &EmulateInstructionARM::EmulateADDRdSPImm, "add r7, sp, #<const>"},
12406 {0x0ffff000, 0x024c7000, ARMvAll, eEncodingA1, No_VFP, eSize32,
12407 &EmulateInstructionARM::EmulateSUBR7IPImm, "sub r7, ip, #<const>"},
12408 // copy the stack pointer to ip
12409 {0x0fffffff, 0x01a0c00d, ARMvAll, eEncodingA1, No_VFP, eSize32,
12410 &EmulateInstructionARM::EmulateMOVRdSP, "mov ip, sp"},
12411 {0x0ffff000, 0x028dc000, ARMvAll, eEncodingA1, No_VFP, eSize32,
12412 &EmulateInstructionARM::EmulateADDRdSPImm, "add ip, sp, #<const>"},
12413 {0x0ffff000, 0x024dc000, ARMvAll, eEncodingA1, No_VFP, eSize32,
12414 &EmulateInstructionARM::EmulateSUBIPSPImm, "sub ip, sp, #<const>"},
12416 // adjust the stack pointer
12417 {0x0ffff000, 0x024dd000, ARMvAll, eEncodingA1, No_VFP, eSize32,
12418 &EmulateInstructionARM::EmulateSUBSPImm, "sub sp, sp, #<const>"},
12419 {0x0fef0010, 0x004d0000, ARMvAll, eEncodingA1, No_VFP, eSize32,
12420 &EmulateInstructionARM::EmulateSUBSPReg,
12421 "sub{s}<c> <Rd>, sp, <Rm>{,<shift>}"},
12423 // push one register
12424 // if Rn == '1101' && imm12 == '000000000100' then SEE PUSH;
12425 {0x0e5f0000, 0x040d0000, ARMvAll, eEncodingA1, No_VFP, eSize32,
12426 &EmulateInstructionARM::EmulateSTRRtSP, "str Rt, [sp, #-imm12]!"},
12428 // vector push consecutive extension register(s)
12429 {0x0fbf0f00, 0x0d2d0b00, ARMV6T2_ABOVE, eEncodingA1, No_VFP, eSize32,
12430 &EmulateInstructionARM::EmulateVPUSH, "vpush.64 <list>"},
12431 {0x0fbf0f00, 0x0d2d0a00, ARMV6T2_ABOVE, eEncodingA2, No_VFP, eSize32,
12432 &EmulateInstructionARM::EmulateVPUSH, "vpush.32 <list>"},
12434 //----------------------------------------------------------------------
12435 // Epilogue instructions
12436 //----------------------------------------------------------------------
12438 {0x0fff0000, 0x08bd0000, ARMvAll, eEncodingA1, No_VFP, eSize32,
12439 &EmulateInstructionARM::EmulatePOP, "pop <registers>"},
12440 {0x0fff0fff, 0x049d0004, ARMvAll, eEncodingA2, No_VFP, eSize32,
12441 &EmulateInstructionARM::EmulatePOP, "pop <register>"},
12442 {0x0fbf0f00, 0x0cbd0b00, ARMV6T2_ABOVE, eEncodingA1, No_VFP, eSize32,
12443 &EmulateInstructionARM::EmulateVPOP, "vpop.64 <list>"},
12444 {0x0fbf0f00, 0x0cbd0a00, ARMV6T2_ABOVE, eEncodingA2, No_VFP, eSize32,
12445 &EmulateInstructionARM::EmulateVPOP, "vpop.32 <list>"},
12447 //----------------------------------------------------------------------
12448 // Supervisor Call (previously Software Interrupt)
12449 //----------------------------------------------------------------------
12450 {0x0f000000, 0x0f000000, ARMvAll, eEncodingA1, No_VFP, eSize32,
12451 &EmulateInstructionARM::EmulateSVC, "svc #imm24"},
12453 //----------------------------------------------------------------------
12454 // Branch instructions
12455 //----------------------------------------------------------------------
12456 // To resolve ambiguity, "blx <label>" should come before "b #imm24" and
12458 {0xfe000000, 0xfa000000, ARMV5_ABOVE, eEncodingA2, No_VFP, eSize32,
12459 &EmulateInstructionARM::EmulateBLXImmediate, "blx <label>"},
12460 {0x0f000000, 0x0a000000, ARMvAll, eEncodingA1, No_VFP, eSize32,
12461 &EmulateInstructionARM::EmulateB, "b #imm24"},
12462 {0x0f000000, 0x0b000000, ARMvAll, eEncodingA1, No_VFP, eSize32,
12463 &EmulateInstructionARM::EmulateBLXImmediate, "bl <label>"},
12464 {0x0ffffff0, 0x012fff30, ARMV5_ABOVE, eEncodingA1, No_VFP, eSize32,
12465 &EmulateInstructionARM::EmulateBLXRm, "blx <Rm>"},
12466 // for example, "bx lr"
12467 {0x0ffffff0, 0x012fff10, ARMvAll, eEncodingA1, No_VFP, eSize32,
12468 &EmulateInstructionARM::EmulateBXRm, "bx <Rm>"},
12470 {0x0ffffff0, 0x012fff20, ARMvAll, eEncodingA1, No_VFP, eSize32,
12471 &EmulateInstructionARM::EmulateBXJRm, "bxj <Rm>"},
12473 //----------------------------------------------------------------------
12474 // Data-processing instructions
12475 //----------------------------------------------------------------------
12477 {0x0fe00000, 0x02a00000, ARMvAll, eEncodingA1, No_VFP, eSize32,
12478 &EmulateInstructionARM::EmulateADCImm, "adc{s}<c> <Rd>, <Rn>, #const"},
12480 {0x0fe00010, 0x00a00000, ARMvAll, eEncodingA1, No_VFP, eSize32,
12481 &EmulateInstructionARM::EmulateADCReg,
12482 "adc{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
12484 {0x0fe00000, 0x02800000, ARMvAll, eEncodingA1, No_VFP, eSize32,
12485 &EmulateInstructionARM::EmulateADDImmARM,
12486 "add{s}<c> <Rd>, <Rn>, #const"},
12488 {0x0fe00010, 0x00800000, ARMvAll, eEncodingA1, No_VFP, eSize32,
12489 &EmulateInstructionARM::EmulateADDReg,
12490 "add{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
12491 // add (register-shifted register)
12492 {0x0fe00090, 0x00800010, ARMvAll, eEncodingA1, No_VFP, eSize32,
12493 &EmulateInstructionARM::EmulateADDRegShift,
12494 "add{s}<c> <Rd>, <Rn>, <Rm>, <type> <RS>"},
12496 {0x0fff0000, 0x028f0000, ARMvAll, eEncodingA1, No_VFP, eSize32,
12497 &EmulateInstructionARM::EmulateADR, "add<c> <Rd>, PC, #<const>"},
12498 {0x0fff0000, 0x024f0000, ARMvAll, eEncodingA2, No_VFP, eSize32,
12499 &EmulateInstructionARM::EmulateADR, "sub<c> <Rd>, PC, #<const>"},
12501 {0x0fe00000, 0x02000000, ARMvAll, eEncodingA1, No_VFP, eSize32,
12502 &EmulateInstructionARM::EmulateANDImm, "and{s}<c> <Rd>, <Rn>, #const"},
12504 {0x0fe00010, 0x00000000, ARMvAll, eEncodingA1, No_VFP, eSize32,
12505 &EmulateInstructionARM::EmulateANDReg,
12506 "and{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
12508 {0x0fe00000, 0x03c00000, ARMvAll, eEncodingA1, No_VFP, eSize32,
12509 &EmulateInstructionARM::EmulateBICImm, "bic{s}<c> <Rd>, <Rn>, #const"},
12511 {0x0fe00010, 0x01c00000, ARMvAll, eEncodingA1, No_VFP, eSize32,
12512 &EmulateInstructionARM::EmulateBICReg,
12513 "bic{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
12515 {0x0fe00000, 0x02200000, ARMvAll, eEncodingA1, No_VFP, eSize32,
12516 &EmulateInstructionARM::EmulateEORImm, "eor{s}<c> <Rd>, <Rn>, #const"},
12518 {0x0fe00010, 0x00200000, ARMvAll, eEncodingA1, No_VFP, eSize32,
12519 &EmulateInstructionARM::EmulateEORReg,
12520 "eor{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
12522 {0x0fe00000, 0x03800000, ARMvAll, eEncodingA1, No_VFP, eSize32,
12523 &EmulateInstructionARM::EmulateORRImm, "orr{s}<c> <Rd>, <Rn>, #const"},
12525 {0x0fe00010, 0x01800000, ARMvAll, eEncodingA1, No_VFP, eSize32,
12526 &EmulateInstructionARM::EmulateORRReg,
12527 "orr{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
12529 {0x0fe00000, 0x02600000, ARMvAll, eEncodingA1, No_VFP, eSize32,
12530 &EmulateInstructionARM::EmulateRSBImm, "rsb{s}<c> <Rd>, <Rn>, #<const>"},
12532 {0x0fe00010, 0x00600000, ARMvAll, eEncodingA1, No_VFP, eSize32,
12533 &EmulateInstructionARM::EmulateRSBReg,
12534 "rsb{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
12536 {0x0fe00000, 0x02e00000, ARMvAll, eEncodingA1, No_VFP, eSize32,
12537 &EmulateInstructionARM::EmulateRSCImm, "rsc{s}<c> <Rd>, <Rn>, #<const>"},
12539 {0x0fe00010, 0x00e00000, ARMvAll, eEncodingA1, No_VFP, eSize32,
12540 &EmulateInstructionARM::EmulateRSCReg,
12541 "rsc{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
12543 {0x0fe00000, 0x02c00000, ARMvAll, eEncodingA1, No_VFP, eSize32,
12544 &EmulateInstructionARM::EmulateSBCImm, "sbc{s}<c> <Rd>, <Rn>, #<const>"},
12546 {0x0fe00010, 0x00c00000, ARMvAll, eEncodingA1, No_VFP, eSize32,
12547 &EmulateInstructionARM::EmulateSBCReg,
12548 "sbc{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
12549 // sub (immediate, ARM)
12550 {0x0fe00000, 0x02400000, ARMvAll, eEncodingA1, No_VFP, eSize32,
12551 &EmulateInstructionARM::EmulateSUBImmARM,
12552 "sub{s}<c> <Rd>, <Rn>, #<const>"},
12553 // sub (sp minus immediate)
12554 {0x0fef0000, 0x024d0000, ARMvAll, eEncodingA1, No_VFP, eSize32,
12555 &EmulateInstructionARM::EmulateSUBSPImm, "sub{s}<c> <Rd>, sp, #<const>"},
12557 {0x0fe00010, 0x00400000, ARMvAll, eEncodingA1, No_VFP, eSize32,
12558 &EmulateInstructionARM::EmulateSUBReg,
12559 "sub{s}<c> <Rd>, <Rn>, <Rm>{,<shift>}"},
12561 {0x0ff0f000, 0x03300000, ARMvAll, eEncodingA1, No_VFP, eSize32,
12562 &EmulateInstructionARM::EmulateTEQImm, "teq<c> <Rn>, #const"},
12564 {0x0ff0f010, 0x01300000, ARMvAll, eEncodingA1, No_VFP, eSize32,
12565 &EmulateInstructionARM::EmulateTEQReg, "teq<c> <Rn>, <Rm> {,<shift>}"},
12567 {0x0ff0f000, 0x03100000, ARMvAll, eEncodingA1, No_VFP, eSize32,
12568 &EmulateInstructionARM::EmulateTSTImm, "tst<c> <Rn>, #const"},
12570 {0x0ff0f010, 0x01100000, ARMvAll, eEncodingA1, No_VFP, eSize32,
12571 &EmulateInstructionARM::EmulateTSTReg, "tst<c> <Rn>, <Rm> {,<shift>}"},
12574 {0x0fef0000, 0x03a00000, ARMvAll, eEncodingA1, No_VFP, eSize32,
12575 &EmulateInstructionARM::EmulateMOVRdImm, "mov{s}<c> <Rd>, #<const>"},
12576 {0x0ff00000, 0x03000000, ARMV6T2_ABOVE, eEncodingA2, No_VFP, eSize32,
12577 &EmulateInstructionARM::EmulateMOVRdImm, "movw<c> <Rd>, #<imm16>"},
12579 {0x0fef0ff0, 0x01a00000, ARMvAll, eEncodingA1, No_VFP, eSize32,
12580 &EmulateInstructionARM::EmulateMOVRdRm, "mov{s}<c> <Rd>, <Rm>"},
12582 {0x0fef0000, 0x03e00000, ARMvAll, eEncodingA1, No_VFP, eSize32,
12583 &EmulateInstructionARM::EmulateMVNImm, "mvn{s}<c> <Rd>, #<const>"},
12585 {0x0fef0010, 0x01e00000, ARMvAll, eEncodingA1, No_VFP, eSize32,
12586 &EmulateInstructionARM::EmulateMVNReg,
12587 "mvn{s}<c> <Rd>, <Rm> {,<shift>}"},
12589 {0x0ff0f000, 0x03700000, ARMvAll, eEncodingA1, No_VFP, eSize32,
12590 &EmulateInstructionARM::EmulateCMNImm, "cmn<c> <Rn>, #<const>"},
12592 {0x0ff0f010, 0x01700000, ARMvAll, eEncodingA1, No_VFP, eSize32,
12593 &EmulateInstructionARM::EmulateCMNReg, "cmn<c> <Rn>, <Rm> {,<shift>}"},
12595 {0x0ff0f000, 0x03500000, ARMvAll, eEncodingA1, No_VFP, eSize32,
12596 &EmulateInstructionARM::EmulateCMPImm, "cmp<c> <Rn>, #<const>"},
12598 {0x0ff0f010, 0x01500000, ARMvAll, eEncodingA1, No_VFP, eSize32,
12599 &EmulateInstructionARM::EmulateCMPReg, "cmp<c> <Rn>, <Rm> {,<shift>}"},
12601 {0x0fef0070, 0x01a00040, ARMvAll, eEncodingA1, No_VFP, eSize32,
12602 &EmulateInstructionARM::EmulateASRImm, "asr{s}<c> <Rd>, <Rm>, #imm"},
12604 {0x0fef00f0, 0x01a00050, ARMvAll, eEncodingA1, No_VFP, eSize32,
12605 &EmulateInstructionARM::EmulateASRReg, "asr{s}<c> <Rd>, <Rn>, <Rm>"},
12607 {0x0fef0070, 0x01a00000, ARMvAll, eEncodingA1, No_VFP, eSize32,
12608 &EmulateInstructionARM::EmulateLSLImm, "lsl{s}<c> <Rd>, <Rm>, #imm"},
12610 {0x0fef00f0, 0x01a00010, ARMvAll, eEncodingA1, No_VFP, eSize32,
12611 &EmulateInstructionARM::EmulateLSLReg, "lsl{s}<c> <Rd>, <Rn>, <Rm>"},
12613 {0x0fef0070, 0x01a00020, ARMvAll, eEncodingA1, No_VFP, eSize32,
12614 &EmulateInstructionARM::EmulateLSRImm, "lsr{s}<c> <Rd>, <Rm>, #imm"},
12616 {0x0fef00f0, 0x01a00050, ARMvAll, eEncodingA1, No_VFP, eSize32,
12617 &EmulateInstructionARM::EmulateLSRReg, "lsr{s}<c> <Rd>, <Rn>, <Rm>"},
12618 // rrx is a special case encoding of ror (immediate)
12619 {0x0fef0ff0, 0x01a00060, ARMvAll, eEncodingA1, No_VFP, eSize32,
12620 &EmulateInstructionARM::EmulateRRX, "rrx{s}<c> <Rd>, <Rm>"},
12622 {0x0fef0070, 0x01a00060, ARMvAll, eEncodingA1, No_VFP, eSize32,
12623 &EmulateInstructionARM::EmulateRORImm, "ror{s}<c> <Rd>, <Rm>, #imm"},
12625 {0x0fef00f0, 0x01a00070, ARMvAll, eEncodingA1, No_VFP, eSize32,
12626 &EmulateInstructionARM::EmulateRORReg, "ror{s}<c> <Rd>, <Rn>, <Rm>"},
12628 {0x0fe000f0, 0x00000090, ARMvAll, eEncodingA1, No_VFP, eSize32,
12629 &EmulateInstructionARM::EmulateMUL, "mul{s}<c> <Rd>,<R>,<Rm>"},
12631 // subs pc, lr and related instructions
12632 {0x0e10f000, 0x0210f000, ARMvAll, eEncodingA1, No_VFP, eSize32,
12633 &EmulateInstructionARM::EmulateSUBSPcLrEtc,
12634 "<opc>S<c> PC,#<const> | <Rn>,#<const>"},
12635 {0x0e10f010, 0x0010f000, ARMvAll, eEncodingA2, No_VFP, eSize32,
12636 &EmulateInstructionARM::EmulateSUBSPcLrEtc,
12637 "<opc>S<c> PC,<Rn>,<Rm{,<shift>}"},
12639 //----------------------------------------------------------------------
12640 // Load instructions
12641 //----------------------------------------------------------------------
12642 {0x0fd00000, 0x08900000, ARMvAll, eEncodingA1, No_VFP, eSize32,
12643 &EmulateInstructionARM::EmulateLDM, "ldm<c> <Rn>{!} <registers>"},
12644 {0x0fd00000, 0x08100000, ARMvAll, eEncodingA1, No_VFP, eSize32,
12645 &EmulateInstructionARM::EmulateLDMDA, "ldmda<c> <Rn>{!} <registers>"},
12646 {0x0fd00000, 0x09100000, ARMvAll, eEncodingA1, No_VFP, eSize32,
12647 &EmulateInstructionARM::EmulateLDMDB, "ldmdb<c> <Rn>{!} <registers>"},
12648 {0x0fd00000, 0x09900000, ARMvAll, eEncodingA1, No_VFP, eSize32,
12649 &EmulateInstructionARM::EmulateLDMIB, "ldmib<c> <Rn<{!} <registers>"},
12650 {0x0e500000, 0x04100000, ARMvAll, eEncodingA1, No_VFP, eSize32,
12651 &EmulateInstructionARM::EmulateLDRImmediateARM,
12652 "ldr<c> <Rt> [<Rn> {#+/-<imm12>}]"},
12653 {0x0e500010, 0x06100000, ARMvAll, eEncodingA1, No_VFP, eSize32,
12654 &EmulateInstructionARM::EmulateLDRRegister,
12655 "ldr<c> <Rt> [<Rn> +/-<Rm> {<shift>}] {!}"},
12656 {0x0e5f0000, 0x045f0000, ARMvAll, eEncodingA1, No_VFP, eSize32,
12657 &EmulateInstructionARM::EmulateLDRBLiteral, "ldrb<c> <Rt>, [...]"},
12658 {0xfe500010, 0x06500000, ARMvAll, eEncodingA1, No_VFP, eSize32,
12659 &EmulateInstructionARM::EmulateLDRBRegister,
12660 "ldrb<c> <Rt>, [<Rn>,+/-<Rm>{, <shift>}]{!}"},
12661 {0x0e5f00f0, 0x005f00b0, ARMvAll, eEncodingA1, No_VFP, eSize32,
12662 &EmulateInstructionARM::EmulateLDRHLiteral, "ldrh<c> <Rt>, <label>"},
12663 {0x0e5000f0, 0x001000b0, ARMvAll, eEncodingA1, No_VFP, eSize32,
12664 &EmulateInstructionARM::EmulateLDRHRegister,
12665 "ldrh<c> <Rt>,[<Rn>,+/-<Rm>]{!}"},
12666 {0x0e5000f0, 0x005000d0, ARMvAll, eEncodingA1, No_VFP, eSize32,
12667 &EmulateInstructionARM::EmulateLDRSBImmediate,
12668 "ldrsb<c> <Rt>, [<Rn>{,#+/-<imm8>}]"},
12669 {0x0e5f00f0, 0x005f00d0, ARMvAll, eEncodingA1, No_VFP, eSize32,
12670 &EmulateInstructionARM::EmulateLDRSBLiteral, "ldrsb<c> <Rt> <label>"},
12671 {0x0e5000f0, 0x001000d0, ARMvAll, eEncodingA1, No_VFP, eSize32,
12672 &EmulateInstructionARM::EmulateLDRSBRegister,
12673 "ldrsb<c> <Rt>,[<Rn>,+/-<Rm>]{!}"},
12674 {0x0e5000f0, 0x005000f0, ARMvAll, eEncodingA1, No_VFP, eSize32,
12675 &EmulateInstructionARM::EmulateLDRSHImmediate,
12676 "ldrsh<c> <Rt>,[<Rn>{,#+/-<imm8>}]"},
12677 {0x0e5f00f0, 0x005f00f0, ARMvAll, eEncodingA1, No_VFP, eSize32,
12678 &EmulateInstructionARM::EmulateLDRSHLiteral, "ldrsh<c> <Rt>,<label>"},
12679 {0x0e5000f0, 0x001000f0, ARMvAll, eEncodingA1, No_VFP, eSize32,
12680 &EmulateInstructionARM::EmulateLDRSHRegister,
12681 "ldrsh<c> <Rt>,[<Rn>,+/-<Rm>]{!}"},
12682 {0x0e5000f0, 0x004000d0, ARMV5TE_ABOVE, eEncodingA1, No_VFP, eSize32,
12683 &EmulateInstructionARM::EmulateLDRDImmediate,
12684 "ldrd<c> <Rt>, <Rt2>, [<Rn>,#+/-<imm8>]!"},
12685 {0x0e500ff0, 0x000000d0, ARMV5TE_ABOVE, eEncodingA1, No_VFP, eSize32,
12686 &EmulateInstructionARM::EmulateLDRDRegister,
12687 "ldrd<c> <Rt>, <Rt2>, [<Rn>, +/-<Rm>]{!}"},
12688 {0x0e100f00, 0x0c100b00, ARMvAll, eEncodingA1, VFPv2_ABOVE, eSize32,
12689 &EmulateInstructionARM::EmulateVLDM, "vldm{mode}<c> <Rn>{!}, <list>"},
12690 {0x0e100f00, 0x0c100a00, ARMvAll, eEncodingA2, VFPv2v3, eSize32,
12691 &EmulateInstructionARM::EmulateVLDM, "vldm{mode}<c> <Rn>{!}, <list>"},
12692 {0x0f300f00, 0x0d100b00, ARMvAll, eEncodingA1, VFPv2_ABOVE, eSize32,
12693 &EmulateInstructionARM::EmulateVLDR, "vldr<c> <Dd>, [<Rn>{,#+/-<imm>}]"},
12694 {0x0f300f00, 0x0d100a00, ARMvAll, eEncodingA2, VFPv2v3, eSize32,
12695 &EmulateInstructionARM::EmulateVLDR, "vldr<c> <Sd>, [<Rn>{,#+/-<imm>}]"},
12696 {0xffb00000, 0xf4200000, ARMvAll, eEncodingA1, AdvancedSIMD, eSize32,
12697 &EmulateInstructionARM::EmulateVLD1Multiple,
12698 "vld1<c>.<size> <list>, [<Rn>{@<align>}], <Rm>"},
12699 {0xffb00300, 0xf4a00000, ARMvAll, eEncodingA1, AdvancedSIMD, eSize32,
12700 &EmulateInstructionARM::EmulateVLD1Single,
12701 "vld1<c>.<size> <list>, [<Rn>{@<align>}], <Rm>"},
12702 {0xffb00f00, 0xf4a00c00, ARMvAll, eEncodingA1, AdvancedSIMD, eSize32,
12703 &EmulateInstructionARM::EmulateVLD1SingleAll,
12704 "vld1<c>.<size> <list>, [<Rn>{@<align>}], <Rm>"},
12706 //----------------------------------------------------------------------
12707 // Store instructions
12708 //----------------------------------------------------------------------
12709 {0x0fd00000, 0x08800000, ARMvAll, eEncodingA1, No_VFP, eSize32,
12710 &EmulateInstructionARM::EmulateSTM, "stm<c> <Rn>{!} <registers>"},
12711 {0x0fd00000, 0x08000000, ARMvAll, eEncodingA1, No_VFP, eSize32,
12712 &EmulateInstructionARM::EmulateSTMDA, "stmda<c> <Rn>{!} <registers>"},
12713 {0x0fd00000, 0x09000000, ARMvAll, eEncodingA1, No_VFP, eSize32,
12714 &EmulateInstructionARM::EmulateSTMDB, "stmdb<c> <Rn>{!} <registers>"},
12715 {0x0fd00000, 0x09800000, ARMvAll, eEncodingA1, No_VFP, eSize32,
12716 &EmulateInstructionARM::EmulateSTMIB, "stmib<c> <Rn>{!} <registers>"},
12717 {0x0e500010, 0x06000000, ARMvAll, eEncodingA1, No_VFP, eSize32,
12718 &EmulateInstructionARM::EmulateSTRRegister,
12719 "str<c> <Rt> [<Rn> +/-<Rm> {<shift>}]{!}"},
12720 {0x0e5000f0, 0x000000b0, ARMvAll, eEncodingA1, No_VFP, eSize32,
12721 &EmulateInstructionARM::EmulateSTRHRegister,
12722 "strh<c> <Rt>,[<Rn>,+/-<Rm>[{!}"},
12723 {0x0ff00ff0, 0x01800f90, ARMV6_ABOVE, eEncodingA1, No_VFP, eSize32,
12724 &EmulateInstructionARM::EmulateSTREX, "strex<c> <Rd>, <Rt>, [<Rn>]"},
12725 {0x0e500000, 0x04400000, ARMvAll, eEncodingA1, No_VFP, eSize32,
12726 &EmulateInstructionARM::EmulateSTRBImmARM,
12727 "strb<c> <Rt>,[<Rn>,#+/-<imm12>]!"},
12728 {0x0e500000, 0x04000000, ARMvAll, eEncodingA1, No_VFP, eSize32,
12729 &EmulateInstructionARM::EmulateSTRImmARM,
12730 "str<c> <Rt>,[<Rn>,#+/-<imm12>]!"},
12731 {0x0e5000f0, 0x004000f0, ARMV5TE_ABOVE, eEncodingA1, No_VFP, eSize32,
12732 &EmulateInstructionARM::EmulateSTRDImm,
12733 "strd<c> <Rt>, <Rt2>, [<Rn> #+/-<imm8>]!"},
12734 {0x0e500ff0, 0x000000f0, ARMV5TE_ABOVE, eEncodingA1, No_VFP, eSize32,
12735 &EmulateInstructionARM::EmulateSTRDReg,
12736 "strd<c> <Rt>, <Rt2>, [<Rn>, +/-<Rm>]{!}"},
12737 {0x0e100f00, 0x0c000b00, ARMvAll, eEncodingA1, VFPv2_ABOVE, eSize32,
12738 &EmulateInstructionARM::EmulateVSTM, "vstm{mode}<c> <Rn>{!} <list>"},
12739 {0x0e100f00, 0x0c000a00, ARMvAll, eEncodingA2, VFPv2v3, eSize32,
12740 &EmulateInstructionARM::EmulateVSTM, "vstm{mode}<c> <Rn>{!} <list>"},
12741 {0x0f300f00, 0x0d000b00, ARMvAll, eEncodingA1, VFPv2_ABOVE, eSize32,
12742 &EmulateInstructionARM::EmulateVSTR, "vstr<c> <Dd> [<Rn>{,#+/-<imm>}]"},
12743 {0x0f300f00, 0x0d000a00, ARMvAll, eEncodingA2, VFPv2v3, eSize32,
12744 &EmulateInstructionARM::EmulateVSTR, "vstr<c> <Sd> [<Rn>{,#+/-<imm>}]"},
12745 {0xffb00000, 0xf4000000, ARMvAll, eEncodingA1, AdvancedSIMD, eSize32,
12746 &EmulateInstructionARM::EmulateVST1Multiple,
12747 "vst1<c>.<size> <list>, [<Rn>{@<align>}], <Rm>"},
12748 {0xffb00300, 0xf4800000, ARMvAll, eEncodingA1, AdvancedSIMD, eSize32,
12749 &EmulateInstructionARM::EmulateVST1Single,
12750 "vst1<c>.<size> <list>, [<Rn>{@<align>}], <Rm>"},
12752 //----------------------------------------------------------------------
12753 // Other instructions
12754 //----------------------------------------------------------------------
12755 {0x0fff00f0, 0x06af00f0, ARMV6_ABOVE, eEncodingA1, No_VFP, eSize32,
12756 &EmulateInstructionARM::EmulateSXTB, "sxtb<c> <Rd>,<Rm>{,<rotation>}"},
12757 {0x0fff00f0, 0x06bf0070, ARMV6_ABOVE, eEncodingA1, No_VFP, eSize32,
12758 &EmulateInstructionARM::EmulateSXTH, "sxth<c> <Rd>,<Rm>{,<rotation>}"},
12759 {0x0fff00f0, 0x06ef0070, ARMV6_ABOVE, eEncodingA1, No_VFP, eSize32,
12760 &EmulateInstructionARM::EmulateUXTB, "uxtb<c> <Rd>,<Rm>{,<rotation>}"},
12761 {0x0fff00f0, 0x06ff0070, ARMV6_ABOVE, eEncodingA1, No_VFP, eSize32,
12762 &EmulateInstructionARM::EmulateUXTH, "uxth<c> <Rd>,<Rm>{,<rotation>}"},
12763 {0xfe500000, 0xf8100000, ARMV6_ABOVE, eEncodingA1, No_VFP, eSize32,
12764 &EmulateInstructionARM::EmulateRFE, "rfe{<amode>} <Rn>{!}"}
12767 static const size_t k_num_arm_opcodes = llvm::array_lengthof(g_arm_opcodes);
12769 for (size_t i = 0; i < k_num_arm_opcodes; ++i) {
12770 if ((g_arm_opcodes[i].mask & opcode) == g_arm_opcodes[i].value &&
12771 (g_arm_opcodes[i].variants & arm_isa) != 0)
12772 return &g_arm_opcodes[i];
12777 EmulateInstructionARM::ARMOpcode *
12778 EmulateInstructionARM::GetThumbOpcodeForInstruction(const uint32_t opcode,
12779 uint32_t arm_isa) {
12781 static ARMOpcode g_thumb_opcodes[] = {
12782 //----------------------------------------------------------------------
12783 // Prologue instructions
12784 //----------------------------------------------------------------------
12786 // push register(s)
12787 {0xfffffe00, 0x0000b400, ARMvAll, eEncodingT1, No_VFP, eSize16,
12788 &EmulateInstructionARM::EmulatePUSH, "push <registers>"},
12789 {0xffff0000, 0xe92d0000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
12790 &EmulateInstructionARM::EmulatePUSH, "push.w <registers>"},
12791 {0xffff0fff, 0xf84d0d04, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32,
12792 &EmulateInstructionARM::EmulatePUSH, "push.w <register>"},
12794 // set r7 to point to a stack offset
12795 {0xffffff00, 0x0000af00, ARMvAll, eEncodingT1, No_VFP, eSize16,
12796 &EmulateInstructionARM::EmulateADDRdSPImm, "add r7, sp, #imm"},
12797 // copy the stack pointer to r7
12798 {0xffffffff, 0x0000466f, ARMvAll, eEncodingT1, No_VFP, eSize16,
12799 &EmulateInstructionARM::EmulateMOVRdSP, "mov r7, sp"},
12800 // move from high register to low register (comes after "mov r7, sp" to
12801 // resolve ambiguity)
12802 {0xffffffc0, 0x00004640, ARMvAll, eEncodingT1, No_VFP, eSize16,
12803 &EmulateInstructionARM::EmulateMOVLowHigh, "mov r0-r7, r8-r15"},
12805 // PC-relative load into register (see also EmulateADDSPRm)
12806 {0xfffff800, 0x00004800, ARMvAll, eEncodingT1, No_VFP, eSize16,
12807 &EmulateInstructionARM::EmulateLDRRtPCRelative, "ldr <Rt>, [PC, #imm]"},
12809 // adjust the stack pointer
12810 {0xffffff87, 0x00004485, ARMvAll, eEncodingT2, No_VFP, eSize16,
12811 &EmulateInstructionARM::EmulateADDSPRm, "add sp, <Rm>"},
12812 {0xffffff80, 0x0000b080, ARMvAll, eEncodingT1, No_VFP, eSize16,
12813 &EmulateInstructionARM::EmulateSUBSPImm, "sub sp, sp, #imm"},
12814 {0xfbef8f00, 0xf1ad0d00, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
12815 &EmulateInstructionARM::EmulateSUBSPImm, "sub.w sp, sp, #<const>"},
12816 {0xfbff8f00, 0xf2ad0d00, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32,
12817 &EmulateInstructionARM::EmulateSUBSPImm, "subw sp, sp, #imm12"},
12818 {0xffef8000, 0xebad0000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32,
12819 &EmulateInstructionARM::EmulateSUBSPReg,
12820 "sub{s}<c> <Rd>, sp, <Rm>{,<shift>}"},
12822 // vector push consecutive extension register(s)
12823 {0xffbf0f00, 0xed2d0b00, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32,
12824 &EmulateInstructionARM::EmulateVPUSH, "vpush.64 <list>"},
12825 {0xffbf0f00, 0xed2d0a00, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
12826 &EmulateInstructionARM::EmulateVPUSH, "vpush.32 <list>"},
12828 //----------------------------------------------------------------------
12829 // Epilogue instructions
12830 //----------------------------------------------------------------------
12832 {0xfffff800, 0x0000a800, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16,
12833 &EmulateInstructionARM::EmulateADDSPImm, "add<c> <Rd>, sp, #imm"},
12834 {0xffffff80, 0x0000b000, ARMvAll, eEncodingT2, No_VFP, eSize16,
12835 &EmulateInstructionARM::EmulateADDSPImm, "add sp, #imm"},
12836 {0xfffffe00, 0x0000bc00, ARMvAll, eEncodingT1, No_VFP, eSize16,
12837 &EmulateInstructionARM::EmulatePOP, "pop <registers>"},
12838 {0xffff0000, 0xe8bd0000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
12839 &EmulateInstructionARM::EmulatePOP, "pop.w <registers>"},
12840 {0xffff0fff, 0xf85d0d04, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32,
12841 &EmulateInstructionARM::EmulatePOP, "pop.w <register>"},
12842 {0xffbf0f00, 0xecbd0b00, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32,
12843 &EmulateInstructionARM::EmulateVPOP, "vpop.64 <list>"},
12844 {0xffbf0f00, 0xecbd0a00, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
12845 &EmulateInstructionARM::EmulateVPOP, "vpop.32 <list>"},
12847 //----------------------------------------------------------------------
12848 // Supervisor Call (previously Software Interrupt)
12849 //----------------------------------------------------------------------
12850 {0xffffff00, 0x0000df00, ARMvAll, eEncodingT1, No_VFP, eSize16,
12851 &EmulateInstructionARM::EmulateSVC, "svc #imm8"},
12853 //----------------------------------------------------------------------
12854 // If Then makes up to four following instructions conditional.
12855 //----------------------------------------------------------------------
12856 // The next 5 opcode _must_ come before the if then instruction
12857 {0xffffffff, 0x0000bf00, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize16,
12858 &EmulateInstructionARM::EmulateNop, "nop"},
12859 {0xffffffff, 0x0000bf10, ARMV7_ABOVE, eEncodingT1, No_VFP, eSize16,
12860 &EmulateInstructionARM::EmulateNop, "nop YIELD (yield hint)"},
12861 {0xffffffff, 0x0000bf20, ARMV7_ABOVE, eEncodingT1, No_VFP, eSize16,
12862 &EmulateInstructionARM::EmulateNop, "nop WFE (wait for event hint)"},
12863 {0xffffffff, 0x0000bf30, ARMV7_ABOVE, eEncodingT1, No_VFP, eSize16,
12864 &EmulateInstructionARM::EmulateNop, "nop WFI (wait for interrupt hint)"},
12865 {0xffffffff, 0x0000bf40, ARMV7_ABOVE, eEncodingT1, No_VFP, eSize16,
12866 &EmulateInstructionARM::EmulateNop, "nop SEV (send event hint)"},
12867 {0xffffff00, 0x0000bf00, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize16,
12868 &EmulateInstructionARM::EmulateIT, "it{<x>{<y>{<z>}}} <firstcond>"},
12870 //----------------------------------------------------------------------
12871 // Branch instructions
12872 //----------------------------------------------------------------------
12873 // To resolve ambiguity, "b<c> #imm8" should come after "svc #imm8".
12874 {0xfffff000, 0x0000d000, ARMvAll, eEncodingT1, No_VFP, eSize16,
12875 &EmulateInstructionARM::EmulateB, "b<c> #imm8 (outside IT)"},
12876 {0xfffff800, 0x0000e000, ARMvAll, eEncodingT2, No_VFP, eSize16,
12877 &EmulateInstructionARM::EmulateB, "b<c> #imm11 (outside or last in IT)"},
12878 {0xf800d000, 0xf0008000, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32,
12879 &EmulateInstructionARM::EmulateB, "b<c>.w #imm8 (outside IT)"},
12880 {0xf800d000, 0xf0009000, ARMV6T2_ABOVE, eEncodingT4, No_VFP, eSize32,
12881 &EmulateInstructionARM::EmulateB,
12882 "b<c>.w #imm8 (outside or last in IT)"},
12884 {0xf800d000, 0xf000d000, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize32,
12885 &EmulateInstructionARM::EmulateBLXImmediate, "bl <label>"},
12887 {0xf800d001, 0xf000c000, ARMV5_ABOVE, eEncodingT2, No_VFP, eSize32,
12888 &EmulateInstructionARM::EmulateBLXImmediate, "blx <label>"},
12889 {0xffffff87, 0x00004780, ARMV5_ABOVE, eEncodingT1, No_VFP, eSize16,
12890 &EmulateInstructionARM::EmulateBLXRm, "blx <Rm>"},
12891 // for example, "bx lr"
12892 {0xffffff87, 0x00004700, ARMvAll, eEncodingT1, No_VFP, eSize32,
12893 &EmulateInstructionARM::EmulateBXRm, "bx <Rm>"},
12895 {0xfff0ffff, 0xf3c08f00, ARMV5J_ABOVE, eEncodingT1, No_VFP, eSize32,
12896 &EmulateInstructionARM::EmulateBXJRm, "bxj <Rm>"},
12897 // compare and branch
12898 {0xfffff500, 0x0000b100, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize16,
12899 &EmulateInstructionARM::EmulateCB, "cb{n}z <Rn>, <label>"},
12900 // table branch byte
12901 {0xfff0fff0, 0xe8d0f000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32,
12902 &EmulateInstructionARM::EmulateTB, "tbb<c> <Rn>, <Rm>"},
12903 // table branch halfword
12904 {0xfff0fff0, 0xe8d0f010, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32,
12905 &EmulateInstructionARM::EmulateTB, "tbh<c> <Rn>, <Rm>, lsl #1"},
12907 //----------------------------------------------------------------------
12908 // Data-processing instructions
12909 //----------------------------------------------------------------------
12911 {0xfbe08000, 0xf1400000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32,
12912 &EmulateInstructionARM::EmulateADCImm, "adc{s}<c> <Rd>, <Rn>, #<const>"},
12914 {0xffffffc0, 0x00004140, ARMvAll, eEncodingT1, No_VFP, eSize16,
12915 &EmulateInstructionARM::EmulateADCReg, "adcs|adc<c> <Rdn>, <Rm>"},
12916 {0xffe08000, 0xeb400000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
12917 &EmulateInstructionARM::EmulateADCReg,
12918 "adc{s}<c>.w <Rd>, <Rn>, <Rm> {,<shift>}"},
12920 {0xfffffe00, 0x00001800, ARMvAll, eEncodingT1, No_VFP, eSize16,
12921 &EmulateInstructionARM::EmulateADDReg, "adds|add<c> <Rd>, <Rn>, <Rm>"},
12922 // Make sure "add sp, <Rm>" comes before this instruction, so there's no
12923 // ambiguity decoding the two.
12924 {0xffffff00, 0x00004400, ARMvAll, eEncodingT2, No_VFP, eSize16,
12925 &EmulateInstructionARM::EmulateADDReg, "add<c> <Rdn>, <Rm>"},
12927 {0xfffff800, 0x0000a000, ARMvAll, eEncodingT1, No_VFP, eSize16,
12928 &EmulateInstructionARM::EmulateADR, "add<c> <Rd>, PC, #<const>"},
12929 {0xfbff8000, 0xf2af0000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
12930 &EmulateInstructionARM::EmulateADR, "sub<c> <Rd>, PC, #<const>"},
12931 {0xfbff8000, 0xf20f0000, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32,
12932 &EmulateInstructionARM::EmulateADR, "add<c> <Rd>, PC, #<const>"},
12934 {0xfbe08000, 0xf0000000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32,
12935 &EmulateInstructionARM::EmulateANDImm, "and{s}<c> <Rd>, <Rn>, #<const>"},
12937 {0xffffffc0, 0x00004000, ARMvAll, eEncodingT1, No_VFP, eSize16,
12938 &EmulateInstructionARM::EmulateANDReg, "ands|and<c> <Rdn>, <Rm>"},
12939 {0xffe08000, 0xea000000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
12940 &EmulateInstructionARM::EmulateANDReg,
12941 "and{s}<c>.w <Rd>, <Rn>, <Rm> {,<shift>}"},
12943 {0xfbe08000, 0xf0200000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32,
12944 &EmulateInstructionARM::EmulateBICImm, "bic{s}<c> <Rd>, <Rn>, #<const>"},
12946 {0xffffffc0, 0x00004380, ARMvAll, eEncodingT1, No_VFP, eSize16,
12947 &EmulateInstructionARM::EmulateBICReg, "bics|bic<c> <Rdn>, <Rm>"},
12948 {0xffe08000, 0xea200000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
12949 &EmulateInstructionARM::EmulateBICReg,
12950 "bic{s}<c>.w <Rd>, <Rn>, <Rm> {,<shift>}"},
12952 {0xfbe08000, 0xf0800000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32,
12953 &EmulateInstructionARM::EmulateEORImm, "eor{s}<c> <Rd>, <Rn>, #<const>"},
12955 {0xffffffc0, 0x00004040, ARMvAll, eEncodingT1, No_VFP, eSize16,
12956 &EmulateInstructionARM::EmulateEORReg, "eors|eor<c> <Rdn>, <Rm>"},
12957 {0xffe08000, 0xea800000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
12958 &EmulateInstructionARM::EmulateEORReg,
12959 "eor{s}<c>.w <Rd>, <Rn>, <Rm> {,<shift>}"},
12961 {0xfbe08000, 0xf0400000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32,
12962 &EmulateInstructionARM::EmulateORRImm, "orr{s}<c> <Rd>, <Rn>, #<const>"},
12964 {0xffffffc0, 0x00004300, ARMvAll, eEncodingT1, No_VFP, eSize16,
12965 &EmulateInstructionARM::EmulateORRReg, "orrs|orr<c> <Rdn>, <Rm>"},
12966 {0xffe08000, 0xea400000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
12967 &EmulateInstructionARM::EmulateORRReg,
12968 "orr{s}<c>.w <Rd>, <Rn>, <Rm> {,<shift>}"},
12970 {0xffffffc0, 0x00004240, ARMvAll, eEncodingT1, No_VFP, eSize16,
12971 &EmulateInstructionARM::EmulateRSBImm, "rsbs|rsb<c> <Rd>, <Rn>, #0"},
12972 {0xfbe08000, 0xf1c00000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
12973 &EmulateInstructionARM::EmulateRSBImm,
12974 "rsb{s}<c>.w <Rd>, <Rn>, #<const>"},
12976 {0xffe08000, 0xea400000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32,
12977 &EmulateInstructionARM::EmulateRSBReg,
12978 "rsb{s}<c>.w <Rd>, <Rn>, <Rm> {,<shift>}"},
12980 {0xfbe08000, 0xf1600000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32,
12981 &EmulateInstructionARM::EmulateSBCImm, "sbc{s}<c> <Rd>, <Rn>, #<const>"},
12983 {0xffffffc0, 0x00004180, ARMvAll, eEncodingT1, No_VFP, eSize16,
12984 &EmulateInstructionARM::EmulateSBCReg, "sbcs|sbc<c> <Rdn>, <Rm>"},
12985 {0xffe08000, 0xeb600000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
12986 &EmulateInstructionARM::EmulateSBCReg,
12987 "sbc{s}<c>.w <Rd>, <Rn>, <Rm> {,<shift>}"},
12988 // add (immediate, Thumb)
12989 {0xfffffe00, 0x00001c00, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16,
12990 &EmulateInstructionARM::EmulateADDImmThumb,
12991 "adds|add<c> <Rd>,<Rn>,#<imm3>"},
12992 {0xfffff800, 0x00003000, ARMV4T_ABOVE, eEncodingT2, No_VFP, eSize16,
12993 &EmulateInstructionARM::EmulateADDImmThumb, "adds|add<c> <Rdn>,#<imm8>"},
12994 {0xfbe08000, 0xf1000000, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32,
12995 &EmulateInstructionARM::EmulateADDImmThumb,
12996 "add{s}<c>.w <Rd>,<Rn>,#<const>"},
12997 {0xfbf08000, 0xf2000000, ARMV6T2_ABOVE, eEncodingT4, No_VFP, eSize32,
12998 &EmulateInstructionARM::EmulateADDImmThumb,
12999 "addw<c> <Rd>,<Rn>,#<imm12>"},
13000 // sub (immediate, Thumb)
13001 {0xfffffe00, 0x00001e00, ARMvAll, eEncodingT1, No_VFP, eSize16,
13002 &EmulateInstructionARM::EmulateSUBImmThumb,
13003 "subs|sub<c> <Rd>, <Rn> #imm3"},
13004 {0xfffff800, 0x00003800, ARMvAll, eEncodingT2, No_VFP, eSize16,
13005 &EmulateInstructionARM::EmulateSUBImmThumb, "subs|sub<c> <Rdn>, #imm8"},
13006 {0xfbe08000, 0xf1a00000, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32,
13007 &EmulateInstructionARM::EmulateSUBImmThumb,
13008 "sub{s}<c>.w <Rd>, <Rn>, #<const>"},
13009 {0xfbf08000, 0xf2a00000, ARMV6T2_ABOVE, eEncodingT4, No_VFP, eSize32,
13010 &EmulateInstructionARM::EmulateSUBImmThumb,
13011 "subw<c> <Rd>, <Rn>, #imm12"},
13012 // sub (sp minus immediate)
13013 {0xfbef8000, 0xf1ad0000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
13014 &EmulateInstructionARM::EmulateSUBSPImm, "sub{s}.w <Rd>, sp, #<const>"},
13015 {0xfbff8000, 0xf2ad0000, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32,
13016 &EmulateInstructionARM::EmulateSUBSPImm, "subw<c> <Rd>, sp, #imm12"},
13018 {0xfffffe00, 0x00001a00, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16,
13019 &EmulateInstructionARM::EmulateSUBReg, "subs|sub<c> <Rd>, <Rn>, <Rm>"},
13020 {0xffe08000, 0xeba00000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
13021 &EmulateInstructionARM::EmulateSUBReg,
13022 "sub{s}<c>.w <Rd>, <Rn>, <Rm>{,<shift>}"},
13024 {0xfbf08f00, 0xf0900f00, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32,
13025 &EmulateInstructionARM::EmulateTEQImm, "teq<c> <Rn>, #<const>"},
13027 {0xfff08f00, 0xea900f00, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32,
13028 &EmulateInstructionARM::EmulateTEQReg, "teq<c> <Rn>, <Rm> {,<shift>}"},
13030 {0xfbf08f00, 0xf0100f00, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32,
13031 &EmulateInstructionARM::EmulateTSTImm, "tst<c> <Rn>, #<const>"},
13033 {0xffffffc0, 0x00004200, ARMvAll, eEncodingT1, No_VFP, eSize16,
13034 &EmulateInstructionARM::EmulateTSTReg, "tst<c> <Rdn>, <Rm>"},
13035 {0xfff08f00, 0xea100f00, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
13036 &EmulateInstructionARM::EmulateTSTReg, "tst<c>.w <Rn>, <Rm> {,<shift>}"},
13038 // move from high register to high register
13039 {0xffffff00, 0x00004600, ARMvAll, eEncodingT1, No_VFP, eSize16,
13040 &EmulateInstructionARM::EmulateMOVRdRm, "mov<c> <Rd>, <Rm>"},
13041 // move from low register to low register
13042 {0xffffffc0, 0x00000000, ARMvAll, eEncodingT2, No_VFP, eSize16,
13043 &EmulateInstructionARM::EmulateMOVRdRm, "movs <Rd>, <Rm>"},
13044 // mov{s}<c>.w <Rd>, <Rm>
13045 {0xffeff0f0, 0xea4f0000, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32,
13046 &EmulateInstructionARM::EmulateMOVRdRm, "mov{s}<c>.w <Rd>, <Rm>"},
13048 {0xfffff800, 0x00002000, ARMvAll, eEncodingT1, No_VFP, eSize16,
13049 &EmulateInstructionARM::EmulateMOVRdImm, "movs|mov<c> <Rd>, #imm8"},
13050 {0xfbef8000, 0xf04f0000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
13051 &EmulateInstructionARM::EmulateMOVRdImm, "mov{s}<c>.w <Rd>, #<const>"},
13052 {0xfbf08000, 0xf2400000, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32,
13053 &EmulateInstructionARM::EmulateMOVRdImm, "movw<c> <Rd>,#<imm16>"},
13055 {0xfbef8000, 0xf06f0000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32,
13056 &EmulateInstructionARM::EmulateMVNImm, "mvn{s} <Rd>, #<const>"},
13058 {0xffffffc0, 0x000043c0, ARMvAll, eEncodingT1, No_VFP, eSize16,
13059 &EmulateInstructionARM::EmulateMVNReg, "mvns|mvn<c> <Rd>, <Rm>"},
13060 {0xffef8000, 0xea6f0000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
13061 &EmulateInstructionARM::EmulateMVNReg,
13062 "mvn{s}<c>.w <Rd>, <Rm> {,<shift>}"},
13064 {0xfbf08f00, 0xf1100f00, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32,
13065 &EmulateInstructionARM::EmulateCMNImm, "cmn<c> <Rn>, #<const>"},
13067 {0xffffffc0, 0x000042c0, ARMvAll, eEncodingT1, No_VFP, eSize16,
13068 &EmulateInstructionARM::EmulateCMNReg, "cmn<c> <Rn>, <Rm>"},
13069 {0xfff08f00, 0xeb100f00, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
13070 &EmulateInstructionARM::EmulateCMNReg, "cmn<c> <Rn>, <Rm> {,<shift>}"},
13072 {0xfffff800, 0x00002800, ARMvAll, eEncodingT1, No_VFP, eSize16,
13073 &EmulateInstructionARM::EmulateCMPImm, "cmp<c> <Rn>, #imm8"},
13074 {0xfbf08f00, 0xf1b00f00, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
13075 &EmulateInstructionARM::EmulateCMPImm, "cmp<c>.w <Rn>, #<const>"},
13076 // cmp (register) (Rn and Rm both from r0-r7)
13077 {0xffffffc0, 0x00004280, ARMvAll, eEncodingT1, No_VFP, eSize16,
13078 &EmulateInstructionARM::EmulateCMPReg, "cmp<c> <Rn>, <Rm>"},
13079 // cmp (register) (Rn and Rm not both from r0-r7)
13080 {0xffffff00, 0x00004500, ARMvAll, eEncodingT2, No_VFP, eSize16,
13081 &EmulateInstructionARM::EmulateCMPReg, "cmp<c> <Rn>, <Rm>"},
13082 {0xfff08f00, 0xebb00f00, ARMvAll, eEncodingT3, No_VFP, eSize16,
13083 &EmulateInstructionARM::EmulateCMPReg,
13084 "cmp<c>.w <Rn>, <Rm> {, <shift>}"},
13086 {0xfffff800, 0x00001000, ARMvAll, eEncodingT1, No_VFP, eSize16,
13087 &EmulateInstructionARM::EmulateASRImm, "asrs|asr<c> <Rd>, <Rm>, #imm"},
13088 {0xffef8030, 0xea4f0020, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
13089 &EmulateInstructionARM::EmulateASRImm, "asr{s}<c>.w <Rd>, <Rm>, #imm"},
13091 {0xffffffc0, 0x00004100, ARMvAll, eEncodingT1, No_VFP, eSize16,
13092 &EmulateInstructionARM::EmulateASRReg, "asrs|asr<c> <Rdn>, <Rm>"},
13093 {0xffe0f0f0, 0xfa40f000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
13094 &EmulateInstructionARM::EmulateASRReg, "asr{s}<c>.w <Rd>, <Rn>, <Rm>"},
13096 {0xfffff800, 0x00000000, ARMvAll, eEncodingT1, No_VFP, eSize16,
13097 &EmulateInstructionARM::EmulateLSLImm, "lsls|lsl<c> <Rd>, <Rm>, #imm"},
13098 {0xffef8030, 0xea4f0000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
13099 &EmulateInstructionARM::EmulateLSLImm, "lsl{s}<c>.w <Rd>, <Rm>, #imm"},
13101 {0xffffffc0, 0x00004080, ARMvAll, eEncodingT1, No_VFP, eSize16,
13102 &EmulateInstructionARM::EmulateLSLReg, "lsls|lsl<c> <Rdn>, <Rm>"},
13103 {0xffe0f0f0, 0xfa00f000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
13104 &EmulateInstructionARM::EmulateLSLReg, "lsl{s}<c>.w <Rd>, <Rn>, <Rm>"},
13106 {0xfffff800, 0x00000800, ARMvAll, eEncodingT1, No_VFP, eSize16,
13107 &EmulateInstructionARM::EmulateLSRImm, "lsrs|lsr<c> <Rd>, <Rm>, #imm"},
13108 {0xffef8030, 0xea4f0010, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
13109 &EmulateInstructionARM::EmulateLSRImm, "lsr{s}<c>.w <Rd>, <Rm>, #imm"},
13111 {0xffffffc0, 0x000040c0, ARMvAll, eEncodingT1, No_VFP, eSize16,
13112 &EmulateInstructionARM::EmulateLSRReg, "lsrs|lsr<c> <Rdn>, <Rm>"},
13113 {0xffe0f0f0, 0xfa20f000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
13114 &EmulateInstructionARM::EmulateLSRReg, "lsr{s}<c>.w <Rd>, <Rn>, <Rm>"},
13115 // rrx is a special case encoding of ror (immediate)
13116 {0xffeff0f0, 0xea4f0030, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32,
13117 &EmulateInstructionARM::EmulateRRX, "rrx{s}<c>.w <Rd>, <Rm>"},
13119 {0xffef8030, 0xea4f0030, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32,
13120 &EmulateInstructionARM::EmulateRORImm, "ror{s}<c>.w <Rd>, <Rm>, #imm"},
13122 {0xffffffc0, 0x000041c0, ARMvAll, eEncodingT1, No_VFP, eSize16,
13123 &EmulateInstructionARM::EmulateRORReg, "rors|ror<c> <Rdn>, <Rm>"},
13124 {0xffe0f0f0, 0xfa60f000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
13125 &EmulateInstructionARM::EmulateRORReg, "ror{s}<c>.w <Rd>, <Rn>, <Rm>"},
13127 {0xffffffc0, 0x00004340, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16,
13128 &EmulateInstructionARM::EmulateMUL, "muls <Rdm>,<Rn>,<Rdm>"},
13130 {0xfff0f0f0, 0xfb00f000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
13131 &EmulateInstructionARM::EmulateMUL, "mul<c> <Rd>,<Rn>,<Rm>"},
13133 // subs pc, lr and related instructions
13134 {0xffffff00, 0xf3de8f00, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32,
13135 &EmulateInstructionARM::EmulateSUBSPcLrEtc, "SUBS<c> PC, LR, #<imm8>"},
13137 //----------------------------------------------------------------------
13138 // RFE instructions *** IMPORTANT *** THESE MUST BE LISTED **BEFORE** THE
13139 // LDM.. Instructions in this table;
13140 // otherwise the wrong instructions will be selected.
13141 //----------------------------------------------------------------------
13143 {0xffd0ffff, 0xe810c000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32,
13144 &EmulateInstructionARM::EmulateRFE, "rfedb<c> <Rn>{!}"},
13145 {0xffd0ffff, 0xe990c000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
13146 &EmulateInstructionARM::EmulateRFE, "rfe{ia}<c> <Rn>{!}"},
13148 //----------------------------------------------------------------------
13149 // Load instructions
13150 //----------------------------------------------------------------------
13151 {0xfffff800, 0x0000c800, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16,
13152 &EmulateInstructionARM::EmulateLDM, "ldm<c> <Rn>{!} <registers>"},
13153 {0xffd02000, 0xe8900000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
13154 &EmulateInstructionARM::EmulateLDM, "ldm<c>.w <Rn>{!} <registers>"},
13155 {0xffd00000, 0xe9100000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32,
13156 &EmulateInstructionARM::EmulateLDMDB, "ldmdb<c> <Rn>{!} <registers>"},
13157 {0xfffff800, 0x00006800, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16,
13158 &EmulateInstructionARM::EmulateLDRRtRnImm, "ldr<c> <Rt>, [<Rn>{,#imm}]"},
13159 {0xfffff800, 0x00009800, ARMV4T_ABOVE, eEncodingT2, No_VFP, eSize16,
13160 &EmulateInstructionARM::EmulateLDRRtRnImm, "ldr<c> <Rt>, [SP{,#imm}]"},
13161 {0xfff00000, 0xf8d00000, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32,
13162 &EmulateInstructionARM::EmulateLDRRtRnImm,
13163 "ldr<c>.w <Rt>, [<Rn>{,#imm12}]"},
13164 {0xfff00800, 0xf8500800, ARMV6T2_ABOVE, eEncodingT4, No_VFP, eSize32,
13165 &EmulateInstructionARM::EmulateLDRRtRnImm,
13166 "ldr<c> <Rt>, [<Rn>{,#+/-<imm8>}]{!}"},
13167 // Thumb2 PC-relative load into register
13168 {0xff7f0000, 0xf85f0000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
13169 &EmulateInstructionARM::EmulateLDRRtPCRelative,
13170 "ldr<c>.w <Rt>, [PC, +/-#imm}]"},
13171 {0xfffffe00, 0x00005800, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16,
13172 &EmulateInstructionARM::EmulateLDRRegister, "ldr<c> <Rt>, [<Rn>, <Rm>]"},
13173 {0xfff00fc0, 0xf8500000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
13174 &EmulateInstructionARM::EmulateLDRRegister,
13175 "ldr<c>.w <Rt>, [<Rn>,<Rm>{,LSL #<imm2>}]"},
13176 {0xfffff800, 0x00007800, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16,
13177 &EmulateInstructionARM::EmulateLDRBImmediate,
13178 "ldrb<c> <Rt>,[<Rn>{,#<imm5>}]"},
13179 {0xfff00000, 0xf8900000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
13180 &EmulateInstructionARM::EmulateLDRBImmediate,
13181 "ldrb<c>.w <Rt>,[<Rn>{,#<imm12>}]"},
13182 {0xfff00800, 0xf8100800, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32,
13183 &EmulateInstructionARM::EmulateLDRBImmediate,
13184 "ldrb<c> <Rt>,[<Rn>, #+/-<imm8>]{!}"},
13185 {0xff7f0000, 0xf81f0000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32,
13186 &EmulateInstructionARM::EmulateLDRBLiteral, "ldrb<c> <Rt>,[...]"},
13187 {0xfffffe00, 0x00005c00, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize16,
13188 &EmulateInstructionARM::EmulateLDRBRegister, "ldrb<c> <Rt>,[<Rn>,<Rm>]"},
13189 {0xfff00fc0, 0xf8100000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
13190 &EmulateInstructionARM::EmulateLDRBRegister,
13191 "ldrb<c>.w <Rt>,[<Rn>,<Rm>{,LSL #imm2>}]"},
13192 {0xfffff800, 0x00008800, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16,
13193 &EmulateInstructionARM::EmulateLDRHImmediate,
13194 "ldrh<c> <Rt>, [<Rn>{,#<imm>}]"},
13195 {0xfff00000, 0xf8b00000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
13196 &EmulateInstructionARM::EmulateLDRHImmediate,
13197 "ldrh<c>.w <Rt>,[<Rn>{,#<imm12>}]"},
13198 {0xfff00800, 0xf8300800, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32,
13199 &EmulateInstructionARM::EmulateLDRHImmediate,
13200 "ldrh<c> <Rt>,[<Rn>,#+/-<imm8>]{!}"},
13201 {0xff7f0000, 0xf83f0000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32,
13202 &EmulateInstructionARM::EmulateLDRHLiteral, "ldrh<c> <Rt>, <label>"},
13203 {0xfffffe00, 0x00005a00, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16,
13204 &EmulateInstructionARM::EmulateLDRHRegister,
13205 "ldrh<c> <Rt>, [<Rn>,<Rm>]"},
13206 {0xfff00fc0, 0xf8300000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
13207 &EmulateInstructionARM::EmulateLDRHRegister,
13208 "ldrh<c>.w <Rt>,[<Rn>,<Rm>{,LSL #<imm2>}]"},
13209 {0xfff00000, 0xf9900000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32,
13210 &EmulateInstructionARM::EmulateLDRSBImmediate,
13211 "ldrsb<c> <Rt>,[<Rn>,#<imm12>]"},
13212 {0xfff00800, 0xf9100800, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
13213 &EmulateInstructionARM::EmulateLDRSBImmediate,
13214 "ldrsb<c> <Rt>,[<Rn>,#+/-<imm8>]"},
13215 {0xff7f0000, 0xf91f0000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32,
13216 &EmulateInstructionARM::EmulateLDRSBLiteral, "ldrsb<c> <Rt>, <label>"},
13217 {0xfffffe00, 0x00005600, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16,
13218 &EmulateInstructionARM::EmulateLDRSBRegister,
13219 "ldrsb<c> <Rt>,[<Rn>,<Rm>]"},
13220 {0xfff00fc0, 0xf9100000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
13221 &EmulateInstructionARM::EmulateLDRSBRegister,
13222 "ldrsb<c>.w <Rt>,[<Rn>,<Rm>{,LSL #imm2>}]"},
13223 {0xfff00000, 0xf9b00000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32,
13224 &EmulateInstructionARM::EmulateLDRSHImmediate,
13225 "ldrsh<c> <Rt>,[<Rn>,#<imm12>]"},
13226 {0xfff00800, 0xf9300800, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
13227 &EmulateInstructionARM::EmulateLDRSHImmediate,
13228 "ldrsh<c> <Rt>,[<Rn>,#+/-<imm8>]"},
13229 {0xff7f0000, 0xf93f0000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32,
13230 &EmulateInstructionARM::EmulateLDRSHLiteral, "ldrsh<c> <Rt>,<label>"},
13231 {0xfffffe00, 0x00005e00, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16,
13232 &EmulateInstructionARM::EmulateLDRSHRegister,
13233 "ldrsh<c> <Rt>,[<Rn>,<Rm>]"},
13234 {0xfff00fc0, 0xf9300000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
13235 &EmulateInstructionARM::EmulateLDRSHRegister,
13236 "ldrsh<c>.w <Rt>,[<Rn>,<Rm>{,LSL #<imm2>}]"},
13237 {0xfe500000, 0xe8500000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32,
13238 &EmulateInstructionARM::EmulateLDRDImmediate,
13239 "ldrd<c> <Rt>, <Rt2>, [<Rn>,#+/-<imm>]!"},
13240 {0xfe100f00, 0xec100b00, ARMvAll, eEncodingT1, VFPv2_ABOVE, eSize32,
13241 &EmulateInstructionARM::EmulateVLDM, "vldm{mode}<c> <Rn>{!}, <list>"},
13242 {0xfe100f00, 0xec100a00, ARMvAll, eEncodingT2, VFPv2v3, eSize32,
13243 &EmulateInstructionARM::EmulateVLDM, "vldm{mode}<c> <Rn>{!}, <list>"},
13244 {0xffe00f00, 0xed100b00, ARMvAll, eEncodingT1, VFPv2_ABOVE, eSize32,
13245 &EmulateInstructionARM::EmulateVLDR, "vldr<c> <Dd>, [<Rn>{,#+/-<imm>}]"},
13246 {0xff300f00, 0xed100a00, ARMvAll, eEncodingT2, VFPv2v3, eSize32,
13247 &EmulateInstructionARM::EmulateVLDR, "vldr<c> <Sd>, {<Rn>{,#+/-<imm>}]"},
13248 {0xffb00000, 0xf9200000, ARMvAll, eEncodingT1, AdvancedSIMD, eSize32,
13249 &EmulateInstructionARM::EmulateVLD1Multiple,
13250 "vld1<c>.<size> <list>, [<Rn>{@<align>}],<Rm>"},
13251 {0xffb00300, 0xf9a00000, ARMvAll, eEncodingT1, AdvancedSIMD, eSize32,
13252 &EmulateInstructionARM::EmulateVLD1Single,
13253 "vld1<c>.<size> <list>, [<Rn>{@<align>}],<Rm>"},
13254 {0xffb00f00, 0xf9a00c00, ARMvAll, eEncodingT1, AdvancedSIMD, eSize32,
13255 &EmulateInstructionARM::EmulateVLD1SingleAll,
13256 "vld1<c>.<size> <list>, [<Rn>{@<align>}], <Rm>"},
13258 //----------------------------------------------------------------------
13259 // Store instructions
13260 //----------------------------------------------------------------------
13261 {0xfffff800, 0x0000c000, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16,
13262 &EmulateInstructionARM::EmulateSTM, "stm<c> <Rn>{!} <registers>"},
13263 {0xffd00000, 0xe8800000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
13264 &EmulateInstructionARM::EmulateSTM, "stm<c>.w <Rn>{!} <registers>"},
13265 {0xffd00000, 0xe9000000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32,
13266 &EmulateInstructionARM::EmulateSTMDB, "stmdb<c> <Rn>{!} <registers>"},
13267 {0xfffff800, 0x00006000, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16,
13268 &EmulateInstructionARM::EmulateSTRThumb, "str<c> <Rt>, [<Rn>{,#<imm>}]"},
13269 {0xfffff800, 0x00009000, ARMV4T_ABOVE, eEncodingT2, No_VFP, eSize16,
13270 &EmulateInstructionARM::EmulateSTRThumb, "str<c> <Rt>, [SP,#<imm>]"},
13271 {0xfff00000, 0xf8c00000, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32,
13272 &EmulateInstructionARM::EmulateSTRThumb,
13273 "str<c>.w <Rt>, [<Rn>,#<imm12>]"},
13274 {0xfff00800, 0xf8400800, ARMV6T2_ABOVE, eEncodingT4, No_VFP, eSize32,
13275 &EmulateInstructionARM::EmulateSTRThumb,
13276 "str<c> <Rt>, [<Rn>,#+/-<imm8>]"},
13277 {0xfffffe00, 0x00005000, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16,
13278 &EmulateInstructionARM::EmulateSTRRegister, "str<c> <Rt> ,{<Rn>, <Rm>]"},
13279 {0xfff00fc0, 0xf8400000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
13280 &EmulateInstructionARM::EmulateSTRRegister,
13281 "str<c>.w <Rt>, [<Rn>, <Rm> {lsl #imm2>}]"},
13282 {0xfffff800, 0x00007000, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16,
13283 &EmulateInstructionARM::EmulateSTRBThumb,
13284 "strb<c> <Rt>, [<Rn>, #<imm5>]"},
13285 {0xfff00000, 0xf8800000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
13286 &EmulateInstructionARM::EmulateSTRBThumb,
13287 "strb<c>.w <Rt>, [<Rn>, #<imm12>]"},
13288 {0xfff00800, 0xf8000800, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32,
13289 &EmulateInstructionARM::EmulateSTRBThumb,
13290 "strb<c> <Rt> ,[<Rn>, #+/-<imm8>]{!}"},
13291 {0xfffffe00, 0x00005200, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16,
13292 &EmulateInstructionARM::EmulateSTRHRegister, "strh<c> <Rt>,[<Rn>,<Rm>]"},
13293 {0xfff00fc0, 0xf8200000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
13294 &EmulateInstructionARM::EmulateSTRHRegister,
13295 "strh<c>.w <Rt>,[<Rn>,<Rm>{,LSL #<imm2>}]"},
13296 {0xfff00000, 0xe8400000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32,
13297 &EmulateInstructionARM::EmulateSTREX,
13298 "strex<c> <Rd>, <Rt>, [<Rn{,#<imm>}]"},
13299 {0xfe500000, 0xe8400000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32,
13300 &EmulateInstructionARM::EmulateSTRDImm,
13301 "strd<c> <Rt>, <Rt2>, [<Rn>, #+/-<imm>]!"},
13302 {0xfe100f00, 0xec000b00, ARMvAll, eEncodingT1, VFPv2_ABOVE, eSize32,
13303 &EmulateInstructionARM::EmulateVSTM, "vstm{mode}<c> <Rn>{!}, <list>"},
13304 {0xfea00f00, 0xec000a00, ARMvAll, eEncodingT2, VFPv2v3, eSize32,
13305 &EmulateInstructionARM::EmulateVSTM, "vstm{mode}<c> <Rn>{!}, <list>"},
13306 {0xff300f00, 0xed000b00, ARMvAll, eEncodingT1, VFPv2_ABOVE, eSize32,
13307 &EmulateInstructionARM::EmulateVSTR, "vstr<c> <Dd>, [<Rn>{,#+/-<imm>}]"},
13308 {0xff300f00, 0xed000a00, ARMvAll, eEncodingT2, VFPv2v3, eSize32,
13309 &EmulateInstructionARM::EmulateVSTR, "vstr<c> <Sd>, [<Rn>{,#+/-<imm>}]"},
13310 {0xffb00000, 0xf9000000, ARMvAll, eEncodingT1, AdvancedSIMD, eSize32,
13311 &EmulateInstructionARM::EmulateVST1Multiple,
13312 "vst1<c>.<size> <list>, [<Rn>{@<align>}], <Rm>"},
13313 {0xffb00300, 0xf9800000, ARMvAll, eEncodingT1, AdvancedSIMD, eSize32,
13314 &EmulateInstructionARM::EmulateVST1Single,
13315 "vst1<c>.<size> <list>, [<Rn>{@<align>}], <Rm>"},
13317 //----------------------------------------------------------------------
13318 // Other instructions
13319 //----------------------------------------------------------------------
13320 {0xffffffc0, 0x0000b240, ARMV6_ABOVE, eEncodingT1, No_VFP, eSize16,
13321 &EmulateInstructionARM::EmulateSXTB, "sxtb<c> <Rd>,<Rm>"},
13322 {0xfffff080, 0xfa4ff080, ARMV6_ABOVE, eEncodingT2, No_VFP, eSize32,
13323 &EmulateInstructionARM::EmulateSXTB, "sxtb<c>.w <Rd>,<Rm>{,<rotation>}"},
13324 {0xffffffc0, 0x0000b200, ARMV6_ABOVE, eEncodingT1, No_VFP, eSize16,
13325 &EmulateInstructionARM::EmulateSXTH, "sxth<c> <Rd>,<Rm>"},
13326 {0xfffff080, 0xfa0ff080, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
13327 &EmulateInstructionARM::EmulateSXTH, "sxth<c>.w <Rd>,<Rm>{,<rotation>}"},
13328 {0xffffffc0, 0x0000b2c0, ARMV6_ABOVE, eEncodingT1, No_VFP, eSize16,
13329 &EmulateInstructionARM::EmulateUXTB, "uxtb<c> <Rd>,<Rm>"},
13330 {0xfffff080, 0xfa5ff080, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
13331 &EmulateInstructionARM::EmulateUXTB, "uxtb<c>.w <Rd>,<Rm>{,<rotation>}"},
13332 {0xffffffc0, 0x0000b280, ARMV6_ABOVE, eEncodingT1, No_VFP, eSize16,
13333 &EmulateInstructionARM::EmulateUXTH, "uxth<c> <Rd>,<Rm>"},
13334 {0xfffff080, 0xfa1ff080, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
13335 &EmulateInstructionARM::EmulateUXTH, "uxth<c>.w <Rd>,<Rm>{,<rotation>}"},
13338 const size_t k_num_thumb_opcodes = llvm::array_lengthof(g_thumb_opcodes);
13339 for (size_t i = 0; i < k_num_thumb_opcodes; ++i) {
13340 if ((g_thumb_opcodes[i].mask & opcode) == g_thumb_opcodes[i].value &&
13341 (g_thumb_opcodes[i].variants & arm_isa) != 0)
13342 return &g_thumb_opcodes[i];
13347 bool EmulateInstructionARM::SetArchitecture(const ArchSpec &arch) {
13350 const char *arch_cstr = arch.GetArchitectureName();
13352 if (0 == ::strcasecmp(arch_cstr, "armv4t"))
13353 m_arm_isa = ARMv4T;
13354 else if (0 == ::strcasecmp(arch_cstr, "armv5tej"))
13355 m_arm_isa = ARMv5TEJ;
13356 else if (0 == ::strcasecmp(arch_cstr, "armv5te"))
13357 m_arm_isa = ARMv5TE;
13358 else if (0 == ::strcasecmp(arch_cstr, "armv5t"))
13359 m_arm_isa = ARMv5T;
13360 else if (0 == ::strcasecmp(arch_cstr, "armv6k"))
13361 m_arm_isa = ARMv6K;
13362 else if (0 == ::strcasecmp(arch_cstr, "armv6t2"))
13363 m_arm_isa = ARMv6T2;
13364 else if (0 == ::strcasecmp(arch_cstr, "armv7s"))
13365 m_arm_isa = ARMv7S;
13366 else if (0 == ::strcasecmp(arch_cstr, "arm"))
13367 m_arm_isa = ARMvAll;
13368 else if (0 == ::strcasecmp(arch_cstr, "thumb"))
13369 m_arm_isa = ARMvAll;
13370 else if (0 == ::strncasecmp(arch_cstr, "armv4", 5))
13372 else if (0 == ::strncasecmp(arch_cstr, "armv6", 5))
13374 else if (0 == ::strncasecmp(arch_cstr, "armv7", 5))
13376 else if (0 == ::strncasecmp(arch_cstr, "armv8", 5))
13379 return m_arm_isa != 0;
13382 bool EmulateInstructionARM::SetInstruction(const Opcode &insn_opcode,
13383 const Address &inst_addr,
13385 if (EmulateInstruction::SetInstruction(insn_opcode, inst_addr, target)) {
13386 if (m_arch.GetTriple().getArch() == llvm::Triple::thumb ||
13387 m_arch.IsAlwaysThumbInstructions())
13388 m_opcode_mode = eModeThumb;
13390 AddressClass addr_class = inst_addr.GetAddressClass();
13392 if ((addr_class == eAddressClassCode) ||
13393 (addr_class == eAddressClassUnknown))
13394 m_opcode_mode = eModeARM;
13395 else if (addr_class == eAddressClassCodeAlternateISA)
13396 m_opcode_mode = eModeThumb;
13400 if (m_opcode_mode == eModeThumb || m_arch.IsAlwaysThumbInstructions())
13401 m_opcode_cpsr = CPSR_MODE_USR | MASK_CPSR_T;
13403 m_opcode_cpsr = CPSR_MODE_USR;
13409 bool EmulateInstructionARM::ReadInstruction() {
13410 bool success = false;
13411 m_opcode_cpsr = ReadRegisterUnsigned(eRegisterKindGeneric,
13412 LLDB_REGNUM_GENERIC_FLAGS, 0, &success);
13415 ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC,
13416 LLDB_INVALID_ADDRESS, &success);
13418 Context read_inst_context;
13419 read_inst_context.type = eContextReadOpcode;
13420 read_inst_context.SetNoArgs();
13422 if ((m_opcode_cpsr & MASK_CPSR_T) || m_arch.IsAlwaysThumbInstructions()) {
13423 m_opcode_mode = eModeThumb;
13424 uint32_t thumb_opcode = MemARead(read_inst_context, pc, 2, 0, &success);
13427 if ((thumb_opcode & 0xe000) != 0xe000 ||
13428 ((thumb_opcode & 0x1800u) == 0)) {
13429 m_opcode.SetOpcode16(thumb_opcode, GetByteOrder());
13431 m_opcode.SetOpcode32(
13432 (thumb_opcode << 16) |
13433 MemARead(read_inst_context, pc + 2, 2, 0, &success),
13438 m_opcode_mode = eModeARM;
13439 m_opcode.SetOpcode32(MemARead(read_inst_context, pc, 4, 0, &success),
13443 if (!m_ignore_conditions) {
13444 // If we are not ignoreing the conditions then init the it session from
13447 uint32_t it = (Bits32(m_opcode_cpsr, 15, 10) << 2) |
13448 Bits32(m_opcode_cpsr, 26, 25);
13450 m_it_session.InitIT(it);
13455 m_opcode_mode = eModeInvalid;
13456 m_addr = LLDB_INVALID_ADDRESS;
13461 uint32_t EmulateInstructionARM::ArchVersion() { return m_arm_isa; }
13463 bool EmulateInstructionARM::ConditionPassed(const uint32_t opcode) {
13464 // If we are ignoring conditions, then always return true.
13465 // this allows us to iterate over disassembly code and still
13466 // emulate an instruction even if we don't have all the right
13467 // bits set in the CPSR register...
13468 if (m_ignore_conditions)
13471 const uint32_t cond = CurrentCond(opcode);
13472 if (cond == UINT32_MAX)
13475 bool result = false;
13476 switch (UnsignedBits(cond, 3, 1)) {
13478 if (m_opcode_cpsr == 0)
13481 result = (m_opcode_cpsr & MASK_CPSR_Z) != 0;
13484 if (m_opcode_cpsr == 0)
13487 result = (m_opcode_cpsr & MASK_CPSR_C) != 0;
13490 if (m_opcode_cpsr == 0)
13493 result = (m_opcode_cpsr & MASK_CPSR_N) != 0;
13496 if (m_opcode_cpsr == 0)
13499 result = (m_opcode_cpsr & MASK_CPSR_V) != 0;
13502 if (m_opcode_cpsr == 0)
13505 result = ((m_opcode_cpsr & MASK_CPSR_C) != 0) &&
13506 ((m_opcode_cpsr & MASK_CPSR_Z) == 0);
13509 if (m_opcode_cpsr == 0)
13512 bool n = (m_opcode_cpsr & MASK_CPSR_N);
13513 bool v = (m_opcode_cpsr & MASK_CPSR_V);
13518 if (m_opcode_cpsr == 0)
13521 bool n = (m_opcode_cpsr & MASK_CPSR_N);
13522 bool v = (m_opcode_cpsr & MASK_CPSR_V);
13523 result = n == v && ((m_opcode_cpsr & MASK_CPSR_Z) == 0);
13527 // Always execute (cond == 0b1110, or the special 0b1111 which gives
13528 // opcodes different meanings, but always means execution happens.
13537 uint32_t EmulateInstructionARM::CurrentCond(const uint32_t opcode) {
13538 switch (m_opcode_mode) {
13543 return UnsignedBits(opcode, 31, 28);
13546 // For T1 and T3 encodings of the Branch instruction, it returns the 4-bit
13547 // 'cond' field of the encoding.
13549 const uint32_t byte_size = m_opcode.GetByteSize();
13550 if (byte_size == 2) {
13551 if (Bits32(opcode, 15, 12) == 0x0d && Bits32(opcode, 11, 8) != 0x0f)
13552 return Bits32(opcode, 11, 8);
13553 } else if (byte_size == 4) {
13554 if (Bits32(opcode, 31, 27) == 0x1e && Bits32(opcode, 15, 14) == 0x02 &&
13555 Bits32(opcode, 12, 12) == 0x00 && Bits32(opcode, 25, 22) <= 0x0d) {
13556 return Bits32(opcode, 25, 22);
13559 // We have an invalid thumb instruction, let's bail out.
13562 return m_it_session.GetCond();
13565 return UINT32_MAX; // Return invalid value
13568 bool EmulateInstructionARM::InITBlock() {
13569 return CurrentInstrSet() == eModeThumb && m_it_session.InITBlock();
13572 bool EmulateInstructionARM::LastInITBlock() {
13573 return CurrentInstrSet() == eModeThumb && m_it_session.LastInITBlock();
13576 bool EmulateInstructionARM::BadMode(uint32_t mode) {
13580 return false; // '10000'
13582 return false; // '10001'
13584 return false; // '10010'
13586 return false; // '10011'
13588 return false; // '10110'
13590 return false; // '10111'
13592 return false; // '11011'
13594 return false; // '11111'
13601 bool EmulateInstructionARM::CurrentModeIsPrivileged() {
13602 uint32_t mode = Bits32(m_opcode_cpsr, 4, 0);
13613 void EmulateInstructionARM::CPSRWriteByInstr(uint32_t value, uint32_t bytemask,
13614 bool affect_execstate) {
13615 bool privileged = CurrentModeIsPrivileged();
13617 uint32_t tmp_cpsr = Bits32(m_opcode_cpsr, 23, 20) << 20;
13619 if (BitIsSet(bytemask, 3)) {
13620 tmp_cpsr = tmp_cpsr | (Bits32(value, 31, 27) << 27);
13621 if (affect_execstate)
13622 tmp_cpsr = tmp_cpsr | (Bits32(value, 26, 24) << 24);
13625 if (BitIsSet(bytemask, 2)) {
13626 tmp_cpsr = tmp_cpsr | (Bits32(value, 19, 16) << 16);
13629 if (BitIsSet(bytemask, 1)) {
13630 if (affect_execstate)
13631 tmp_cpsr = tmp_cpsr | (Bits32(value, 15, 10) << 10);
13632 tmp_cpsr = tmp_cpsr | (Bit32(value, 9) << 9);
13634 tmp_cpsr = tmp_cpsr | (Bit32(value, 8) << 8);
13637 if (BitIsSet(bytemask, 0)) {
13639 tmp_cpsr = tmp_cpsr | (Bits32(value, 7, 6) << 6);
13640 if (affect_execstate)
13641 tmp_cpsr = tmp_cpsr | (Bit32(value, 5) << 5);
13643 tmp_cpsr = tmp_cpsr | Bits32(value, 4, 0);
13646 m_opcode_cpsr = tmp_cpsr;
13649 bool EmulateInstructionARM::BranchWritePC(const Context &context,
13653 // Check the current instruction set.
13654 if (CurrentInstrSet() == eModeARM)
13655 target = addr & 0xfffffffc;
13657 target = addr & 0xfffffffe;
13659 if (!WriteRegisterUnsigned(context, eRegisterKindGeneric,
13660 LLDB_REGNUM_GENERIC_PC, target))
13666 // As a side effect, BXWritePC sets context.arg2 to eModeARM or eModeThumb by
13667 // inspecting addr.
13668 bool EmulateInstructionARM::BXWritePC(Context &context, uint32_t addr) {
13670 // If the CPSR is changed due to switching between ARM and Thumb ISETSTATE,
13671 // we want to record it and issue a WriteRegister callback so the clients
13672 // can track the mode changes accordingly.
13673 bool cpsr_changed = false;
13675 if (BitIsSet(addr, 0)) {
13676 if (CurrentInstrSet() != eModeThumb) {
13677 SelectInstrSet(eModeThumb);
13678 cpsr_changed = true;
13680 target = addr & 0xfffffffe;
13681 context.SetISA(eModeThumb);
13682 } else if (BitIsClear(addr, 1)) {
13683 if (CurrentInstrSet() != eModeARM) {
13684 SelectInstrSet(eModeARM);
13685 cpsr_changed = true;
13687 target = addr & 0xfffffffc;
13688 context.SetISA(eModeARM);
13690 return false; // address<1:0> == '10' => UNPREDICTABLE
13692 if (cpsr_changed) {
13693 if (!WriteRegisterUnsigned(context, eRegisterKindGeneric,
13694 LLDB_REGNUM_GENERIC_FLAGS, m_new_inst_cpsr))
13697 if (!WriteRegisterUnsigned(context, eRegisterKindGeneric,
13698 LLDB_REGNUM_GENERIC_PC, target))
13704 // Dispatches to either BXWritePC or BranchWritePC based on architecture
13706 bool EmulateInstructionARM::LoadWritePC(Context &context, uint32_t addr) {
13707 if (ArchVersion() >= ARMv5T)
13708 return BXWritePC(context, addr);
13710 return BranchWritePC((const Context)context, addr);
13713 // Dispatches to either BXWritePC or BranchWritePC based on architecture
13714 // versions and current instruction set.
13715 bool EmulateInstructionARM::ALUWritePC(Context &context, uint32_t addr) {
13716 if (ArchVersion() >= ARMv7 && CurrentInstrSet() == eModeARM)
13717 return BXWritePC(context, addr);
13719 return BranchWritePC((const Context)context, addr);
13722 EmulateInstructionARM::Mode EmulateInstructionARM::CurrentInstrSet() {
13723 return m_opcode_mode;
13726 // Set the 'T' bit of our CPSR. The m_opcode_mode gets updated when the next
13727 // ReadInstruction() is performed. This function has a side effect of updating
13728 // the m_new_inst_cpsr member variable if necessary.
13729 bool EmulateInstructionARM::SelectInstrSet(Mode arm_or_thumb) {
13730 m_new_inst_cpsr = m_opcode_cpsr;
13731 switch (arm_or_thumb) {
13735 // Clear the T bit.
13736 m_new_inst_cpsr &= ~MASK_CPSR_T;
13740 m_new_inst_cpsr |= MASK_CPSR_T;
13746 // This function returns TRUE if the processor currently provides support for
13747 // unaligned memory accesses, or FALSE otherwise. This is always TRUE in ARMv7,
13748 // controllable by the SCTLR.U bit in ARMv6, and always FALSE before ARMv6.
13749 bool EmulateInstructionARM::UnalignedSupport() {
13750 return (ArchVersion() >= ARMv7);
13753 // The main addition and subtraction instructions can produce status information
13754 // about both unsigned carry and signed overflow conditions. This status
13755 // information can be used to synthesize multi-word additions and subtractions.
13756 EmulateInstructionARM::AddWithCarryResult
13757 EmulateInstructionARM::AddWithCarry(uint32_t x, uint32_t y, uint8_t carry_in) {
13762 uint64_t unsigned_sum = x + y + carry_in;
13763 int64_t signed_sum = (int32_t)x + (int32_t)y + (int32_t)carry_in;
13765 result = UnsignedBits(unsigned_sum, 31, 0);
13766 // carry_out = (result == unsigned_sum ? 0 : 1);
13767 overflow = ((int32_t)result == signed_sum ? 0 : 1);
13770 carry_out = ((int32_t)x >= (int32_t)(~y)) ? 1 : 0;
13772 carry_out = ((int32_t)x > (int32_t)y) ? 1 : 0;
13774 AddWithCarryResult res = {result, carry_out, overflow};
13778 uint32_t EmulateInstructionARM::ReadCoreReg(uint32_t num, bool *success) {
13779 lldb::RegisterKind reg_kind;
13783 reg_kind = eRegisterKindGeneric;
13784 reg_num = LLDB_REGNUM_GENERIC_SP;
13787 reg_kind = eRegisterKindGeneric;
13788 reg_num = LLDB_REGNUM_GENERIC_RA;
13791 reg_kind = eRegisterKindGeneric;
13792 reg_num = LLDB_REGNUM_GENERIC_PC;
13795 if (num < SP_REG) {
13796 reg_kind = eRegisterKindDWARF;
13797 reg_num = dwarf_r0 + num;
13799 // assert(0 && "Invalid register number");
13806 // Read our register.
13807 uint32_t val = ReadRegisterUnsigned(reg_kind, reg_num, 0, success);
13809 // When executing an ARM instruction , PC reads as the address of the current
13810 // instruction plus 8.
13811 // When executing a Thumb instruction , PC reads as the address of the current
13812 // instruction plus 4.
13814 if (CurrentInstrSet() == eModeARM)
13823 // Write the result to the ARM core register Rd, and optionally update the
13824 // condition flags based on the result.
13826 // This helper method tries to encapsulate the following pseudocode from the
13827 // ARM Architecture Reference Manual:
13829 // if d == 15 then // Can only occur for encoding A1
13830 // ALUWritePC(result); // setflags is always FALSE here
13833 // if setflags then
13834 // APSR.N = result<31>;
13835 // APSR.Z = IsZeroBit(result);
13837 // // APSR.V unchanged
13839 // In the above case, the API client does not pass in the overflow arg, which
13840 // defaults to ~0u.
13841 bool EmulateInstructionARM::WriteCoreRegOptionalFlags(
13842 Context &context, const uint32_t result, const uint32_t Rd, bool setflags,
13843 const uint32_t carry, const uint32_t overflow) {
13845 if (!ALUWritePC(context, result))
13848 lldb::RegisterKind reg_kind;
13852 reg_kind = eRegisterKindGeneric;
13853 reg_num = LLDB_REGNUM_GENERIC_SP;
13856 reg_kind = eRegisterKindGeneric;
13857 reg_num = LLDB_REGNUM_GENERIC_RA;
13860 reg_kind = eRegisterKindDWARF;
13861 reg_num = dwarf_r0 + Rd;
13863 if (!WriteRegisterUnsigned(context, reg_kind, reg_num, result))
13866 return WriteFlags(context, result, carry, overflow);
13871 // This helper method tries to encapsulate the following pseudocode from the
13872 // ARM Architecture Reference Manual:
13874 // APSR.N = result<31>;
13875 // APSR.Z = IsZeroBit(result);
13877 // APSR.V = overflow
13879 // Default arguments can be specified for carry and overflow parameters, which
13881 // not to update the respective flags.
13882 bool EmulateInstructionARM::WriteFlags(Context &context, const uint32_t result,
13883 const uint32_t carry,
13884 const uint32_t overflow) {
13885 m_new_inst_cpsr = m_opcode_cpsr;
13886 SetBit32(m_new_inst_cpsr, CPSR_N_POS, Bit32(result, CPSR_N_POS));
13887 SetBit32(m_new_inst_cpsr, CPSR_Z_POS, result == 0 ? 1 : 0);
13889 SetBit32(m_new_inst_cpsr, CPSR_C_POS, carry);
13890 if (overflow != ~0u)
13891 SetBit32(m_new_inst_cpsr, CPSR_V_POS, overflow);
13892 if (m_new_inst_cpsr != m_opcode_cpsr) {
13893 if (!WriteRegisterUnsigned(context, eRegisterKindGeneric,
13894 LLDB_REGNUM_GENERIC_FLAGS, m_new_inst_cpsr))
13900 bool EmulateInstructionARM::EvaluateInstruction(uint32_t evaluate_options) {
13901 ARMOpcode *opcode_data = NULL;
13903 if (m_opcode_mode == eModeThumb)
13905 GetThumbOpcodeForInstruction(m_opcode.GetOpcode32(), m_arm_isa);
13906 else if (m_opcode_mode == eModeARM)
13907 opcode_data = GetARMOpcodeForInstruction(m_opcode.GetOpcode32(), m_arm_isa);
13909 const bool auto_advance_pc =
13910 evaluate_options & eEmulateInstructionOptionAutoAdvancePC;
13911 m_ignore_conditions =
13912 evaluate_options & eEmulateInstructionOptionIgnoreConditions;
13914 bool success = false;
13915 if (m_opcode_cpsr == 0 || m_ignore_conditions == false) {
13917 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_cpsr, 0, &success);
13920 // Only return false if we are unable to read the CPSR if we care about
13922 if (success == false && m_ignore_conditions == false)
13925 uint32_t orig_pc_value = 0;
13926 if (auto_advance_pc) {
13928 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc, 0, &success);
13933 // Call the Emulate... function if we managed to decode the opcode.
13935 success = (this->*opcode_data->callback)(m_opcode.GetOpcode32(),
13936 opcode_data->encoding);
13941 // Advance the ITSTATE bits to their values for the next instruction if we
13942 // haven't just executed
13943 // an IT instruction what initialized it.
13944 if (m_opcode_mode == eModeThumb && m_it_session.InITBlock() &&
13945 (opcode_data == nullptr ||
13946 opcode_data->callback != &EmulateInstructionARM::EmulateIT))
13947 m_it_session.ITAdvance();
13949 if (auto_advance_pc) {
13950 uint32_t after_pc_value =
13951 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc, 0, &success);
13955 if (auto_advance_pc && (after_pc_value == orig_pc_value)) {
13956 after_pc_value += m_opcode.GetByteSize();
13958 EmulateInstruction::Context context;
13959 context.type = eContextAdvancePC;
13960 context.SetNoArgs();
13961 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc,
13969 EmulateInstruction::InstructionCondition
13970 EmulateInstructionARM::GetInstructionCondition() {
13971 const uint32_t cond = CurrentCond(m_opcode.GetOpcode32());
13972 if (cond == 0xe || cond == 0xf || cond == UINT32_MAX)
13973 return EmulateInstruction::UnconditionalCondition;
13977 bool EmulateInstructionARM::TestEmulation(Stream *out_stream, ArchSpec &arch,
13978 OptionValueDictionary *test_data) {
13980 out_stream->Printf("TestEmulation: Missing test data.\n");
13984 static ConstString opcode_key("opcode");
13985 static ConstString before_key("before_state");
13986 static ConstString after_key("after_state");
13988 OptionValueSP value_sp = test_data->GetValueForKey(opcode_key);
13990 uint32_t test_opcode;
13991 if ((value_sp.get() == NULL) ||
13992 (value_sp->GetType() != OptionValue::eTypeUInt64)) {
13993 out_stream->Printf("TestEmulation: Error reading opcode from test file.\n");
13996 test_opcode = value_sp->GetUInt64Value();
13998 if (arch.GetTriple().getArch() == llvm::Triple::thumb ||
13999 arch.IsAlwaysThumbInstructions()) {
14000 m_opcode_mode = eModeThumb;
14001 if (test_opcode < 0x10000)
14002 m_opcode.SetOpcode16(test_opcode, endian::InlHostByteOrder());
14004 m_opcode.SetOpcode32(test_opcode, endian::InlHostByteOrder());
14005 } else if (arch.GetTriple().getArch() == llvm::Triple::arm) {
14006 m_opcode_mode = eModeARM;
14007 m_opcode.SetOpcode32(test_opcode, endian::InlHostByteOrder());
14009 out_stream->Printf("TestEmulation: Invalid arch.\n");
14013 EmulationStateARM before_state;
14014 EmulationStateARM after_state;
14016 value_sp = test_data->GetValueForKey(before_key);
14017 if ((value_sp.get() == NULL) ||
14018 (value_sp->GetType() != OptionValue::eTypeDictionary)) {
14019 out_stream->Printf("TestEmulation: Failed to find 'before' state.\n");
14023 OptionValueDictionary *state_dictionary = value_sp->GetAsDictionary();
14024 if (!before_state.LoadStateFromDictionary(state_dictionary)) {
14025 out_stream->Printf("TestEmulation: Failed loading 'before' state.\n");
14029 value_sp = test_data->GetValueForKey(after_key);
14030 if ((value_sp.get() == NULL) ||
14031 (value_sp->GetType() != OptionValue::eTypeDictionary)) {
14032 out_stream->Printf("TestEmulation: Failed to find 'after' state.\n");
14036 state_dictionary = value_sp->GetAsDictionary();
14037 if (!after_state.LoadStateFromDictionary(state_dictionary)) {
14038 out_stream->Printf("TestEmulation: Failed loading 'after' state.\n");
14042 SetBaton((void *)&before_state);
14043 SetCallbacks(&EmulationStateARM::ReadPseudoMemory,
14044 &EmulationStateARM::WritePseudoMemory,
14045 &EmulationStateARM::ReadPseudoRegister,
14046 &EmulationStateARM::WritePseudoRegister);
14048 bool success = EvaluateInstruction(eEmulateInstructionOptionAutoAdvancePC);
14050 out_stream->Printf("TestEmulation: EvaluateInstruction() failed.\n");
14054 success = before_state.CompareState(after_state);
14056 out_stream->Printf(
14057 "TestEmulation: 'before' and 'after' states do not match.\n");
14064 // EmulateInstructionARM::GetRegisterName (uint32_t reg_kind, uint32_t reg_num)
14066 // if (reg_kind == eRegisterKindGeneric)
14068 // switch (reg_num)
14070 // case LLDB_REGNUM_GENERIC_PC: return "pc";
14071 // case LLDB_REGNUM_GENERIC_SP: return "sp";
14072 // case LLDB_REGNUM_GENERIC_FP: return "fp";
14073 // case LLDB_REGNUM_GENERIC_RA: return "lr";
14074 // case LLDB_REGNUM_GENERIC_FLAGS: return "cpsr";
14075 // default: return NULL;
14078 // else if (reg_kind == eRegisterKindDWARF)
14080 // return GetARMDWARFRegisterName (reg_num);
14085 bool EmulateInstructionARM::CreateFunctionEntryUnwind(UnwindPlan &unwind_plan) {
14086 unwind_plan.Clear();
14087 unwind_plan.SetRegisterKind(eRegisterKindDWARF);
14089 UnwindPlan::RowSP row(new UnwindPlan::Row);
14091 // Our previous Call Frame Address is the stack pointer
14092 row->GetCFAValue().SetIsRegisterPlusOffset(dwarf_sp, 0);
14094 unwind_plan.AppendRow(row);
14095 unwind_plan.SetSourceName("EmulateInstructionARM");
14096 unwind_plan.SetSourcedFromCompiler(eLazyBoolNo);
14097 unwind_plan.SetUnwindPlanValidAtAllInstructions(eLazyBoolYes);
14098 unwind_plan.SetReturnAddressRegister(dwarf_lr);