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/PluginManager.h"
16 #include "lldb/Host/PosixApi.h"
17 #include "lldb/Interpreter/OptionValueArray.h"
18 #include "lldb/Interpreter/OptionValueDictionary.h"
19 #include "lldb/Symbol/UnwindPlan.h"
20 #include "lldb/Utility/ArchSpec.h"
21 #include "lldb/Utility/ConstString.h"
22 #include "lldb/Utility/Stream.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 //----------------------------------------------------------------------
47 static bool GetARMDWARFRegisterInfo(unsigned reg_num, RegisterInfo ®_info) {
48 ::memset(®_info, 0, sizeof(RegisterInfo));
49 ::memset(reg_info.kinds, LLDB_INVALID_REGNUM, sizeof(reg_info.kinds));
51 if (reg_num >= dwarf_q0 && reg_num <= dwarf_q15) {
52 reg_info.byte_size = 16;
53 reg_info.format = eFormatVectorOfUInt8;
54 reg_info.encoding = eEncodingVector;
57 if (reg_num >= dwarf_d0 && reg_num <= dwarf_d31) {
58 reg_info.byte_size = 8;
59 reg_info.format = eFormatFloat;
60 reg_info.encoding = eEncodingIEEE754;
61 } else if (reg_num >= dwarf_s0 && reg_num <= dwarf_s31) {
62 reg_info.byte_size = 4;
63 reg_info.format = eFormatFloat;
64 reg_info.encoding = eEncodingIEEE754;
65 } else if (reg_num >= dwarf_f0 && reg_num <= dwarf_f7) {
66 reg_info.byte_size = 12;
67 reg_info.format = eFormatFloat;
68 reg_info.encoding = eEncodingIEEE754;
70 reg_info.byte_size = 4;
71 reg_info.format = eFormatHex;
72 reg_info.encoding = eEncodingUint;
75 reg_info.kinds[eRegisterKindDWARF] = reg_num;
100 reg_info.name = "r7";
101 reg_info.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_FP;
104 reg_info.name = "r8";
107 reg_info.name = "r9";
110 reg_info.name = "r10";
113 reg_info.name = "r11";
116 reg_info.name = "r12";
119 reg_info.name = "sp";
120 reg_info.alt_name = "r13";
121 reg_info.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_SP;
124 reg_info.name = "lr";
125 reg_info.alt_name = "r14";
126 reg_info.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_RA;
129 reg_info.name = "pc";
130 reg_info.alt_name = "r15";
131 reg_info.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_PC;
134 reg_info.name = "cpsr";
135 reg_info.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_FLAGS;
139 reg_info.name = "s0";
142 reg_info.name = "s1";
145 reg_info.name = "s2";
148 reg_info.name = "s3";
151 reg_info.name = "s4";
154 reg_info.name = "s5";
157 reg_info.name = "s6";
160 reg_info.name = "s7";
163 reg_info.name = "s8";
166 reg_info.name = "s9";
169 reg_info.name = "s10";
172 reg_info.name = "s11";
175 reg_info.name = "s12";
178 reg_info.name = "s13";
181 reg_info.name = "s14";
184 reg_info.name = "s15";
187 reg_info.name = "s16";
190 reg_info.name = "s17";
193 reg_info.name = "s18";
196 reg_info.name = "s19";
199 reg_info.name = "s20";
202 reg_info.name = "s21";
205 reg_info.name = "s22";
208 reg_info.name = "s23";
211 reg_info.name = "s24";
214 reg_info.name = "s25";
217 reg_info.name = "s26";
220 reg_info.name = "s27";
223 reg_info.name = "s28";
226 reg_info.name = "s29";
229 reg_info.name = "s30";
232 reg_info.name = "s31";
237 reg_info.name = "f0";
240 reg_info.name = "f1";
243 reg_info.name = "f2";
246 reg_info.name = "f3";
249 reg_info.name = "f4";
252 reg_info.name = "f5";
255 reg_info.name = "f6";
258 reg_info.name = "f7";
261 // Intel wireless MMX general purpose registers 0 - 7
262 // XScale accumulator register 0 - 7 (they do overlap with wCGR0 - wCGR7)
264 reg_info.name = "wCGR0/ACC0";
267 reg_info.name = "wCGR1/ACC1";
270 reg_info.name = "wCGR2/ACC2";
273 reg_info.name = "wCGR3/ACC3";
276 reg_info.name = "wCGR4/ACC4";
279 reg_info.name = "wCGR5/ACC5";
282 reg_info.name = "wCGR6/ACC6";
285 reg_info.name = "wCGR7/ACC7";
288 // Intel wireless MMX data registers 0 - 15
290 reg_info.name = "wR0";
293 reg_info.name = "wR1";
296 reg_info.name = "wR2";
299 reg_info.name = "wR3";
302 reg_info.name = "wR4";
305 reg_info.name = "wR5";
308 reg_info.name = "wR6";
311 reg_info.name = "wR7";
314 reg_info.name = "wR8";
317 reg_info.name = "wR9";
320 reg_info.name = "wR10";
323 reg_info.name = "wR11";
326 reg_info.name = "wR12";
329 reg_info.name = "wR13";
332 reg_info.name = "wR14";
335 reg_info.name = "wR15";
339 reg_info.name = "spsr";
342 reg_info.name = "spsr_fiq";
345 reg_info.name = "spsr_irq";
348 reg_info.name = "spsr_abt";
351 reg_info.name = "spsr_und";
354 reg_info.name = "spsr_svc";
358 reg_info.name = "r8_usr";
361 reg_info.name = "r9_usr";
364 reg_info.name = "r10_usr";
367 reg_info.name = "r11_usr";
370 reg_info.name = "r12_usr";
373 reg_info.name = "r13_usr";
376 reg_info.name = "r14_usr";
379 reg_info.name = "r8_fiq";
382 reg_info.name = "r9_fiq";
385 reg_info.name = "r10_fiq";
388 reg_info.name = "r11_fiq";
391 reg_info.name = "r12_fiq";
394 reg_info.name = "r13_fiq";
397 reg_info.name = "r14_fiq";
400 reg_info.name = "r13_irq";
403 reg_info.name = "r14_irq";
406 reg_info.name = "r13_abt";
409 reg_info.name = "r14_abt";
412 reg_info.name = "r13_und";
415 reg_info.name = "r14_und";
418 reg_info.name = "r13_svc";
421 reg_info.name = "r14_svc";
424 // Intel wireless MMX control register in co-processor 0 - 7
426 reg_info.name = "wC0";
429 reg_info.name = "wC1";
432 reg_info.name = "wC2";
435 reg_info.name = "wC3";
438 reg_info.name = "wC4";
441 reg_info.name = "wC5";
444 reg_info.name = "wC6";
447 reg_info.name = "wC7";
452 reg_info.name = "d0";
455 reg_info.name = "d1";
458 reg_info.name = "d2";
461 reg_info.name = "d3";
464 reg_info.name = "d4";
467 reg_info.name = "d5";
470 reg_info.name = "d6";
473 reg_info.name = "d7";
476 reg_info.name = "d8";
479 reg_info.name = "d9";
482 reg_info.name = "d10";
485 reg_info.name = "d11";
488 reg_info.name = "d12";
491 reg_info.name = "d13";
494 reg_info.name = "d14";
497 reg_info.name = "d15";
500 reg_info.name = "d16";
503 reg_info.name = "d17";
506 reg_info.name = "d18";
509 reg_info.name = "d19";
512 reg_info.name = "d20";
515 reg_info.name = "d21";
518 reg_info.name = "d22";
521 reg_info.name = "d23";
524 reg_info.name = "d24";
527 reg_info.name = "d25";
530 reg_info.name = "d26";
533 reg_info.name = "d27";
536 reg_info.name = "d28";
539 reg_info.name = "d29";
542 reg_info.name = "d30";
545 reg_info.name = "d31";
548 // NEON 128-bit vector registers (overlays the d registers)
550 reg_info.name = "q0";
553 reg_info.name = "q1";
556 reg_info.name = "q2";
559 reg_info.name = "q3";
562 reg_info.name = "q4";
565 reg_info.name = "q5";
568 reg_info.name = "q6";
571 reg_info.name = "q7";
574 reg_info.name = "q8";
577 reg_info.name = "q9";
580 reg_info.name = "q10";
583 reg_info.name = "q11";
586 reg_info.name = "q12";
589 reg_info.name = "q13";
592 reg_info.name = "q14";
595 reg_info.name = "q15";
605 // Valid return values are {1, 2, 3, 4}, with 0 signifying an error condition.
606 static uint32_t CountITSize(uint32_t ITMask) {
607 // First count the trailing zeros of the IT mask.
608 uint32_t TZ = llvm::countTrailingZeros(ITMask);
610 #ifdef LLDB_CONFIGURATION_DEBUG
611 printf("Encoding error: IT Mask '0000'\n");
618 // Init ITState. Note that at least one bit is always 1 in mask.
619 bool ITSession::InitIT(uint32_t bits7_0) {
620 ITCounter = CountITSize(Bits32(bits7_0, 3, 0));
625 unsigned short FirstCond = Bits32(bits7_0, 7, 4);
626 if (FirstCond == 0xF) {
627 #ifdef LLDB_CONFIGURATION_DEBUG
628 printf("Encoding error: IT FirstCond '1111'\n");
632 if (FirstCond == 0xE && ITCounter != 1) {
633 #ifdef LLDB_CONFIGURATION_DEBUG
634 printf("Encoding error: IT FirstCond '1110' && Mask != '1000'\n");
643 // Update ITState if necessary.
644 void ITSession::ITAdvance() {
645 // assert(ITCounter);
650 unsigned short NewITState4_0 = Bits32(ITState, 4, 0) << 1;
651 SetBits32(ITState, 4, 0, NewITState4_0);
655 // Return true if we're inside an IT Block.
656 bool ITSession::InITBlock() { return ITCounter != 0; }
658 // Return true if we're the last instruction inside an IT Block.
659 bool ITSession::LastInITBlock() { return ITCounter == 1; }
661 // Get condition bits for the current thumb instruction.
662 uint32_t ITSession::GetCond() {
664 return Bits32(ITState, 7, 4);
669 // ARM constants used during decoding
671 #define LDM_REGLIST 1
675 #define PC_REGLIST_BIT 0x8000
677 #define ARMv4 (1u << 0)
678 #define ARMv4T (1u << 1)
679 #define ARMv5T (1u << 2)
680 #define ARMv5TE (1u << 3)
681 #define ARMv5TEJ (1u << 4)
682 #define ARMv6 (1u << 5)
683 #define ARMv6K (1u << 6)
684 #define ARMv6T2 (1u << 7)
685 #define ARMv7 (1u << 8)
686 #define ARMv7S (1u << 9)
687 #define ARMv8 (1u << 10)
688 #define ARMvAll (0xffffffffu)
690 #define ARMV4T_ABOVE \
691 (ARMv4T | ARMv5T | ARMv5TE | ARMv5TEJ | ARMv6 | ARMv6K | ARMv6T2 | ARMv7 | \
693 #define ARMV5_ABOVE \
694 (ARMv5T | ARMv5TE | ARMv5TEJ | ARMv6 | ARMv6K | ARMv6T2 | ARMv7 | ARMv7S | \
696 #define ARMV5TE_ABOVE \
697 (ARMv5TE | ARMv5TEJ | ARMv6 | ARMv6K | ARMv6T2 | ARMv7 | ARMv7S | ARMv8)
698 #define ARMV5J_ABOVE \
699 (ARMv5TEJ | ARMv6 | ARMv6K | ARMv6T2 | ARMv7 | ARMv7S | ARMv8)
700 #define ARMV6_ABOVE (ARMv6 | ARMv6K | ARMv6T2 | ARMv7 | ARMv7S | ARMv8)
701 #define ARMV6T2_ABOVE (ARMv6T2 | ARMv7 | ARMv7S | ARMv8)
702 #define ARMV7_ABOVE (ARMv7 | ARMv7S | ARMv8)
705 #define VFPv1 (1u << 1)
706 #define VFPv2 (1u << 2)
707 #define VFPv3 (1u << 3)
708 #define AdvancedSIMD (1u << 4)
710 #define VFPv1_ABOVE (VFPv1 | VFPv2 | VFPv3 | AdvancedSIMD)
711 #define VFPv2_ABOVE (VFPv2 | VFPv3 | AdvancedSIMD)
712 #define VFPv2v3 (VFPv2 | VFPv3)
714 //----------------------------------------------------------------------
716 // EmulateInstructionARM implementation
718 //----------------------------------------------------------------------
720 void EmulateInstructionARM::Initialize() {
721 PluginManager::RegisterPlugin(GetPluginNameStatic(),
722 GetPluginDescriptionStatic(), CreateInstance);
725 void EmulateInstructionARM::Terminate() {
726 PluginManager::UnregisterPlugin(CreateInstance);
729 ConstString EmulateInstructionARM::GetPluginNameStatic() {
730 static ConstString g_name("arm");
734 const char *EmulateInstructionARM::GetPluginDescriptionStatic() {
735 return "Emulate instructions for the ARM architecture.";
739 EmulateInstructionARM::CreateInstance(const ArchSpec &arch,
740 InstructionType inst_type) {
741 if (EmulateInstructionARM::SupportsEmulatingInstructionsOfTypeStatic(
743 if (arch.GetTriple().getArch() == llvm::Triple::arm) {
744 std::unique_ptr<EmulateInstructionARM> emulate_insn_ap(
745 new EmulateInstructionARM(arch));
747 if (emulate_insn_ap.get())
748 return emulate_insn_ap.release();
749 } else if (arch.GetTriple().getArch() == llvm::Triple::thumb) {
750 std::unique_ptr<EmulateInstructionARM> emulate_insn_ap(
751 new EmulateInstructionARM(arch));
753 if (emulate_insn_ap.get())
754 return emulate_insn_ap.release();
761 bool EmulateInstructionARM::SetTargetTriple(const ArchSpec &arch) {
762 if (arch.GetTriple().getArch() == llvm::Triple::arm)
764 else if (arch.GetTriple().getArch() == llvm::Triple::thumb)
770 // Write "bits (32) UNKNOWN" to memory address "address". Helper function for
771 // many ARM instructions.
772 bool EmulateInstructionARM::WriteBits32UnknownToMemory(addr_t address) {
773 EmulateInstruction::Context context;
774 context.type = EmulateInstruction::eContextWriteMemoryRandomBits;
777 uint32_t random_data = rand();
778 const uint32_t addr_byte_size = GetAddressByteSize();
780 if (!MemAWrite(context, address, random_data, addr_byte_size))
786 // Write "bits (32) UNKNOWN" to register n. Helper function for many ARM
788 bool EmulateInstructionARM::WriteBits32Unknown(int n) {
789 EmulateInstruction::Context context;
790 context.type = EmulateInstruction::eContextWriteRegisterRandomBits;
795 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
800 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n, data))
806 bool EmulateInstructionARM::GetRegisterInfo(lldb::RegisterKind reg_kind,
808 RegisterInfo ®_info) {
809 if (reg_kind == eRegisterKindGeneric) {
811 case LLDB_REGNUM_GENERIC_PC:
812 reg_kind = eRegisterKindDWARF;
815 case LLDB_REGNUM_GENERIC_SP:
816 reg_kind = eRegisterKindDWARF;
819 case LLDB_REGNUM_GENERIC_FP:
820 reg_kind = eRegisterKindDWARF;
823 case LLDB_REGNUM_GENERIC_RA:
824 reg_kind = eRegisterKindDWARF;
827 case LLDB_REGNUM_GENERIC_FLAGS:
828 reg_kind = eRegisterKindDWARF;
829 reg_num = dwarf_cpsr;
836 if (reg_kind == eRegisterKindDWARF)
837 return GetARMDWARFRegisterInfo(reg_num, reg_info);
841 uint32_t EmulateInstructionARM::GetFramePointerRegisterNumber() const {
842 if (m_arch.GetTriple().isAndroid())
843 return LLDB_INVALID_REGNUM; // Don't use frame pointer on android
844 bool is_apple = false;
845 if (m_arch.GetTriple().getVendor() == llvm::Triple::Apple)
847 switch (m_arch.GetTriple().getOS()) {
848 case llvm::Triple::Darwin:
849 case llvm::Triple::MacOSX:
850 case llvm::Triple::IOS:
851 case llvm::Triple::TvOS:
852 case llvm::Triple::WatchOS:
859 /* On Apple iOS et al, the frame pointer register is always r7.
860 * Typically on other ARM systems, thumb code uses r7; arm code uses r11.
863 uint32_t fp_regnum = 11;
868 if (m_opcode_mode == eModeThumb)
874 uint32_t EmulateInstructionARM::GetFramePointerDWARFRegisterNumber() const {
875 bool is_apple = false;
876 if (m_arch.GetTriple().getVendor() == llvm::Triple::Apple)
878 switch (m_arch.GetTriple().getOS()) {
879 case llvm::Triple::Darwin:
880 case llvm::Triple::MacOSX:
881 case llvm::Triple::IOS:
888 /* On Apple iOS et al, the frame pointer register is always r7.
889 * Typically on other ARM systems, thumb code uses r7; arm code uses r11.
892 uint32_t fp_regnum = dwarf_r11;
895 fp_regnum = dwarf_r7;
897 if (m_opcode_mode == eModeThumb)
898 fp_regnum = dwarf_r7;
903 // Push Multiple Registers stores multiple registers to the stack, storing to
904 // consecutive memory locations ending just below the address in SP, and updates
905 // SP to point to the start of the stored data.
906 bool EmulateInstructionARM::EmulatePUSH(const uint32_t opcode,
907 const ARMEncoding encoding) {
909 // ARM pseudo code...
910 if (ConditionPassed())
912 EncodingSpecificOperations();
913 NullCheckIfThumbEE(13);
914 address = SP - 4*BitCount(registers);
918 if (registers<i> == '1')
920 if i == 13 && i != LowestSetBit(registers) // Only possible for encoding A1
921 MemA[address,4] = bits(32) UNKNOWN;
923 MemA[address,4] = R[i];
924 address = address + 4;
928 if (registers<15> == '1') // Only possible for encoding A1 or A2
929 MemA[address,4] = PCStoreValue();
931 SP = SP - 4*BitCount(registers);
935 bool success = false;
936 if (ConditionPassed(opcode)) {
937 const uint32_t addr_byte_size = GetAddressByteSize();
938 const addr_t sp = ReadCoreReg(SP_REG, &success);
941 uint32_t registers = 0;
942 uint32_t Rt; // the source register
945 registers = Bits32(opcode, 7, 0);
946 // The M bit represents LR.
947 if (Bit32(opcode, 8))
948 registers |= (1u << 14);
949 // if BitCount(registers) < 1 then UNPREDICTABLE;
950 if (BitCount(registers) < 1)
954 // Ignore bits 15 & 13.
955 registers = Bits32(opcode, 15, 0) & ~0xa000;
956 // if BitCount(registers) < 2 then UNPREDICTABLE;
957 if (BitCount(registers) < 2)
961 Rt = Bits32(opcode, 15, 12);
962 // if BadReg(t) then UNPREDICTABLE;
965 registers = (1u << Rt);
968 registers = Bits32(opcode, 15, 0);
969 // Instead of return false, let's handle the following case as well,
970 // which amounts to pushing one reg onto the full descending stacks.
971 // if BitCount(register_list) < 2 then SEE STMDB / STMFD;
974 Rt = Bits32(opcode, 15, 12);
975 // if t == 13 then UNPREDICTABLE;
978 registers = (1u << Rt);
983 addr_t sp_offset = addr_byte_size * BitCount(registers);
984 addr_t addr = sp - sp_offset;
987 EmulateInstruction::Context context;
988 context.type = EmulateInstruction::eContextPushRegisterOnStack;
989 RegisterInfo reg_info;
991 GetRegisterInfo(eRegisterKindDWARF, dwarf_sp, sp_reg);
992 for (i = 0; i < 15; ++i) {
993 if (BitIsSet(registers, i)) {
994 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + i, reg_info);
995 context.SetRegisterToRegisterPlusOffset(reg_info, sp_reg, addr - sp);
996 uint32_t reg_value = ReadCoreReg(i, &success);
999 if (!MemAWrite(context, addr, reg_value, addr_byte_size))
1001 addr += addr_byte_size;
1005 if (BitIsSet(registers, 15)) {
1006 GetRegisterInfo(eRegisterKindDWARF, dwarf_pc, reg_info);
1007 context.SetRegisterToRegisterPlusOffset(reg_info, sp_reg, addr - sp);
1008 const uint32_t pc = ReadCoreReg(PC_REG, &success);
1011 if (!MemAWrite(context, addr, pc, addr_byte_size))
1015 context.type = EmulateInstruction::eContextAdjustStackPointer;
1016 context.SetImmediateSigned(-sp_offset);
1018 if (!WriteRegisterUnsigned(context, eRegisterKindGeneric,
1019 LLDB_REGNUM_GENERIC_SP, sp - sp_offset))
1025 // Pop Multiple Registers loads multiple registers from the stack, loading from
1026 // consecutive memory locations staring at the address in SP, and updates
1027 // SP to point just above the loaded data.
1028 bool EmulateInstructionARM::EmulatePOP(const uint32_t opcode,
1029 const ARMEncoding encoding) {
1031 // ARM pseudo code...
1032 if (ConditionPassed())
1034 EncodingSpecificOperations(); NullCheckIfThumbEE(13);
1037 if registers<i> == '1' then
1038 R[i] = if UnalignedAllowed then MemU[address,4] else MemA[address,4]; address = address + 4;
1039 if registers<15> == '1' then
1040 if UnalignedAllowed then
1041 LoadWritePC(MemU[address,4]);
1043 LoadWritePC(MemA[address,4]);
1044 if registers<13> == '0' then SP = SP + 4*BitCount(registers);
1045 if registers<13> == '1' then SP = bits(32) UNKNOWN;
1049 bool success = false;
1051 if (ConditionPassed(opcode)) {
1052 const uint32_t addr_byte_size = GetAddressByteSize();
1053 const addr_t sp = ReadCoreReg(SP_REG, &success);
1056 uint32_t registers = 0;
1057 uint32_t Rt; // the destination register
1060 registers = Bits32(opcode, 7, 0);
1061 // The P bit represents PC.
1062 if (Bit32(opcode, 8))
1063 registers |= (1u << 15);
1064 // if BitCount(registers) < 1 then UNPREDICTABLE;
1065 if (BitCount(registers) < 1)
1070 registers = Bits32(opcode, 15, 0) & ~0x2000;
1071 // if BitCount(registers) < 2 || (P == '1' && M == '1') then
1073 if (BitCount(registers) < 2 || (Bit32(opcode, 15) && Bit32(opcode, 14)))
1075 // if registers<15> == '1' && InITBlock() && !LastInITBlock() then
1077 if (BitIsSet(registers, 15) && InITBlock() && !LastInITBlock())
1081 Rt = Bits32(opcode, 15, 12);
1082 // if t == 13 || (t == 15 && InITBlock() && !LastInITBlock()) then
1086 if (Rt == 15 && InITBlock() && !LastInITBlock())
1088 registers = (1u << Rt);
1091 registers = Bits32(opcode, 15, 0);
1092 // Instead of return false, let's handle the following case as well,
1093 // which amounts to popping one reg from the full descending stacks.
1094 // if BitCount(register_list) < 2 then SEE LDM / LDMIA / LDMFD;
1096 // if registers<13> == '1' && ArchVersion() >= 7 then UNPREDICTABLE;
1097 if (BitIsSet(opcode, 13) && ArchVersion() >= ARMv7)
1101 Rt = Bits32(opcode, 15, 12);
1102 // if t == 13 then UNPREDICTABLE;
1105 registers = (1u << Rt);
1110 addr_t sp_offset = addr_byte_size * BitCount(registers);
1114 EmulateInstruction::Context context;
1115 context.type = EmulateInstruction::eContextPopRegisterOffStack;
1117 RegisterInfo sp_reg;
1118 GetRegisterInfo(eRegisterKindDWARF, dwarf_sp, sp_reg);
1120 for (i = 0; i < 15; ++i) {
1121 if (BitIsSet(registers, i)) {
1122 context.SetAddress(addr);
1123 data = MemARead(context, addr, 4, 0, &success);
1126 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + i,
1129 addr += addr_byte_size;
1133 if (BitIsSet(registers, 15)) {
1134 context.SetRegisterPlusOffset(sp_reg, addr - sp);
1135 data = MemARead(context, addr, 4, 0, &success);
1138 // In ARMv5T and above, this is an interworking branch.
1139 if (!LoadWritePC(context, data))
1141 // addr += addr_byte_size;
1144 context.type = EmulateInstruction::eContextAdjustStackPointer;
1145 context.SetImmediateSigned(sp_offset);
1147 if (!WriteRegisterUnsigned(context, eRegisterKindGeneric,
1148 LLDB_REGNUM_GENERIC_SP, sp + sp_offset))
1154 // Set r7 or ip to point to saved value residing within the stack.
1155 // ADD (SP plus immediate)
1156 bool EmulateInstructionARM::EmulateADDRdSPImm(const uint32_t opcode,
1157 const ARMEncoding encoding) {
1159 // ARM pseudo code...
1160 if (ConditionPassed())
1162 EncodingSpecificOperations();
1163 (result, carry, overflow) = AddWithCarry(SP, imm32, '0');
1165 ALUWritePC(result); // setflags is always FALSE here
1169 APSR.N = result<31>;
1170 APSR.Z = IsZeroBit(result);
1176 bool success = false;
1178 if (ConditionPassed(opcode)) {
1179 const addr_t sp = ReadCoreReg(SP_REG, &success);
1182 uint32_t Rd; // the destination register
1187 imm32 = Bits32(opcode, 7, 0) << 2; // imm32 = ZeroExtend(imm8:'00', 32)
1190 Rd = Bits32(opcode, 15, 12);
1191 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
1196 addr_t sp_offset = imm32;
1197 addr_t addr = sp + sp_offset; // a pointer to the stack area
1199 EmulateInstruction::Context context;
1200 if (Rd == GetFramePointerRegisterNumber())
1201 context.type = eContextSetFramePointer;
1203 context.type = EmulateInstruction::eContextRegisterPlusOffset;
1204 RegisterInfo sp_reg;
1205 GetRegisterInfo(eRegisterKindDWARF, dwarf_sp, sp_reg);
1206 context.SetRegisterPlusOffset(sp_reg, sp_offset);
1208 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + Rd,
1215 // Set r7 or ip to the current stack pointer.
1217 bool EmulateInstructionARM::EmulateMOVRdSP(const uint32_t opcode,
1218 const ARMEncoding encoding) {
1220 // ARM pseudo code...
1221 if (ConditionPassed())
1223 EncodingSpecificOperations();
1226 ALUWritePC(result); // setflags is always FALSE here
1230 APSR.N = result<31>;
1231 APSR.Z = IsZeroBit(result);
1237 bool success = false;
1239 if (ConditionPassed(opcode)) {
1240 const addr_t sp = ReadCoreReg(SP_REG, &success);
1243 uint32_t Rd; // the destination register
1255 EmulateInstruction::Context context;
1256 if (Rd == GetFramePointerRegisterNumber())
1257 context.type = EmulateInstruction::eContextSetFramePointer;
1259 context.type = EmulateInstruction::eContextRegisterPlusOffset;
1260 RegisterInfo sp_reg;
1261 GetRegisterInfo(eRegisterKindDWARF, dwarf_sp, sp_reg);
1262 context.SetRegisterPlusOffset(sp_reg, 0);
1264 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + Rd, sp))
1270 // Move from high register (r8-r15) to low register (r0-r7).
1272 bool EmulateInstructionARM::EmulateMOVLowHigh(const uint32_t opcode,
1273 const ARMEncoding encoding) {
1274 return EmulateMOVRdRm(opcode, encoding);
1277 // Move from register to register.
1279 bool EmulateInstructionARM::EmulateMOVRdRm(const uint32_t opcode,
1280 const ARMEncoding encoding) {
1282 // ARM pseudo code...
1283 if (ConditionPassed())
1285 EncodingSpecificOperations();
1288 ALUWritePC(result); // setflags is always FALSE here
1292 APSR.N = result<31>;
1293 APSR.Z = IsZeroBit(result);
1299 bool success = false;
1301 if (ConditionPassed(opcode)) {
1302 uint32_t Rm; // the source register
1303 uint32_t Rd; // the destination register
1307 Rd = Bit32(opcode, 7) << 3 | Bits32(opcode, 2, 0);
1308 Rm = Bits32(opcode, 6, 3);
1310 if (Rd == 15 && InITBlock() && !LastInITBlock())
1314 Rd = Bits32(opcode, 2, 0);
1315 Rm = Bits32(opcode, 5, 3);
1321 Rd = Bits32(opcode, 11, 8);
1322 Rm = Bits32(opcode, 3, 0);
1323 setflags = BitIsSet(opcode, 20);
1324 // if setflags && (BadReg(d) || BadReg(m)) then UNPREDICTABLE;
1325 if (setflags && (BadReg(Rd) || BadReg(Rm)))
1327 // if !setflags && (d == 15 || m == 15 || (d == 13 && m == 13)) then
1329 if (!setflags && (Rd == 15 || Rm == 15 || (Rd == 13 && Rm == 13)))
1333 Rd = Bits32(opcode, 15, 12);
1334 Rm = Bits32(opcode, 3, 0);
1335 setflags = BitIsSet(opcode, 20);
1337 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related
1339 if (Rd == 15 && setflags)
1340 return EmulateSUBSPcLrEtc(opcode, encoding);
1345 uint32_t result = ReadCoreReg(Rm, &success);
1349 // The context specifies that Rm is to be moved into Rd.
1350 EmulateInstruction::Context context;
1352 context.type = EmulateInstruction::eContextAdjustStackPointer;
1354 context.type = EmulateInstruction::eContextRegisterPlusOffset;
1355 RegisterInfo dwarf_reg;
1356 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + Rm, dwarf_reg);
1357 context.SetRegisterPlusOffset(dwarf_reg, 0);
1359 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags))
1365 // Move (immediate) writes an immediate value to the destination register. It
1366 // can optionally update the condition flags based on the value.
1368 bool EmulateInstructionARM::EmulateMOVRdImm(const uint32_t opcode,
1369 const ARMEncoding encoding) {
1371 // ARM pseudo code...
1372 if (ConditionPassed())
1374 EncodingSpecificOperations();
1376 if d == 15 then // Can only occur for ARM encoding
1377 ALUWritePC(result); // setflags is always FALSE here
1381 APSR.N = result<31>;
1382 APSR.Z = IsZeroBit(result);
1388 if (ConditionPassed(opcode)) {
1389 uint32_t Rd; // the destination register
1390 uint32_t imm32; // the immediate value to be written to Rd
1392 0; // the carry bit after ThumbExpandImm_C or ARMExpandImm_C.
1393 // for setflags == false, this value is a don't care
1394 // initialized to 0 to silence the static analyzer
1398 Rd = Bits32(opcode, 10, 8);
1399 setflags = !InITBlock();
1400 imm32 = Bits32(opcode, 7, 0); // imm32 = ZeroExtend(imm8, 32)
1406 Rd = Bits32(opcode, 11, 8);
1407 setflags = BitIsSet(opcode, 20);
1408 imm32 = ThumbExpandImm_C(opcode, APSR_C, carry);
1415 // d = UInt(Rd); setflags = FALSE; imm32 = ZeroExtend(imm4:i:imm3:imm8,
1417 Rd = Bits32(opcode, 11, 8);
1419 uint32_t imm4 = Bits32(opcode, 19, 16);
1420 uint32_t imm3 = Bits32(opcode, 14, 12);
1421 uint32_t i = Bit32(opcode, 26);
1422 uint32_t imm8 = Bits32(opcode, 7, 0);
1423 imm32 = (imm4 << 12) | (i << 11) | (imm3 << 8) | imm8;
1425 // if BadReg(d) then UNPREDICTABLE;
1431 // d = UInt(Rd); setflags = (S == '1'); (imm32, carry) =
1432 // ARMExpandImm_C(imm12, APSR.C);
1433 Rd = Bits32(opcode, 15, 12);
1434 setflags = BitIsSet(opcode, 20);
1435 imm32 = ARMExpandImm_C(opcode, APSR_C, carry);
1437 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related
1439 if ((Rd == 15) && setflags)
1440 return EmulateSUBSPcLrEtc(opcode, encoding);
1445 // d = UInt(Rd); setflags = FALSE; imm32 = ZeroExtend(imm4:imm12, 32);
1446 Rd = Bits32(opcode, 15, 12);
1448 uint32_t imm4 = Bits32(opcode, 19, 16);
1449 uint32_t imm12 = Bits32(opcode, 11, 0);
1450 imm32 = (imm4 << 12) | imm12;
1452 // if d == 15 then UNPREDICTABLE;
1460 uint32_t result = imm32;
1462 // The context specifies that an immediate is to be moved into Rd.
1463 EmulateInstruction::Context context;
1464 context.type = EmulateInstruction::eContextImmediate;
1465 context.SetNoArgs();
1467 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
1473 // MUL multiplies two register values. The least significant 32 bits of the
1474 // result are written to the destination
1475 // register. These 32 bits do not depend on whether the source register values
1476 // are considered to be signed values or
1479 // Optionally, it can update the condition flags based on the result. In the
1480 // Thumb instruction set, this option is
1481 // limited to only a few forms of the instruction.
1482 bool EmulateInstructionARM::EmulateMUL(const uint32_t opcode,
1483 const ARMEncoding encoding) {
1485 if ConditionPassed() then
1486 EncodingSpecificOperations();
1487 operand1 = SInt(R[n]); // operand1 = UInt(R[n]) produces the same final results
1488 operand2 = SInt(R[m]); // operand2 = UInt(R[m]) produces the same final results
1489 result = operand1 * operand2;
1490 R[d] = result<31:0>;
1492 APSR.N = result<31>;
1493 APSR.Z = IsZeroBit(result);
1494 if ArchVersion() == 4 then
1495 APSR.C = bit UNKNOWN;
1496 // else APSR.C unchanged
1497 // APSR.V always unchanged
1500 if (ConditionPassed(opcode)) {
1506 // EncodingSpecificOperations();
1509 // d = UInt(Rdm); n = UInt(Rn); m = UInt(Rdm); setflags = !InITBlock();
1510 d = Bits32(opcode, 2, 0);
1511 n = Bits32(opcode, 5, 3);
1512 m = Bits32(opcode, 2, 0);
1513 setflags = !InITBlock();
1515 // if ArchVersion() < 6 && d == n then UNPREDICTABLE;
1516 if ((ArchVersion() < ARMv6) && (d == n))
1522 // d = UInt(Rd); n = UInt(Rn); m = UInt(Rm); setflags = FALSE;
1523 d = Bits32(opcode, 11, 8);
1524 n = Bits32(opcode, 19, 16);
1525 m = Bits32(opcode, 3, 0);
1528 // if BadReg(d) || BadReg(n) || BadReg(m) then UNPREDICTABLE;
1529 if (BadReg(d) || BadReg(n) || BadReg(m))
1535 // d = UInt(Rd); n = UInt(Rn); m = UInt(Rm); setflags = (S == '1');
1536 d = Bits32(opcode, 19, 16);
1537 n = Bits32(opcode, 3, 0);
1538 m = Bits32(opcode, 11, 8);
1539 setflags = BitIsSet(opcode, 20);
1541 // if d == 15 || n == 15 || m == 15 then UNPREDICTABLE;
1542 if ((d == 15) || (n == 15) || (m == 15))
1545 // if ArchVersion() < 6 && d == n then UNPREDICTABLE;
1546 if ((ArchVersion() < ARMv6) && (d == n))
1555 bool success = false;
1557 // operand1 = SInt(R[n]); // operand1 = UInt(R[n]) produces the same final
1560 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
1564 // operand2 = SInt(R[m]); // operand2 = UInt(R[m]) produces the same final
1567 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
1571 // result = operand1 * operand2;
1572 uint64_t result = operand1 * operand2;
1574 // R[d] = result<31:0>;
1575 RegisterInfo op1_reg;
1576 RegisterInfo op2_reg;
1577 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n, op1_reg);
1578 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + m, op2_reg);
1580 EmulateInstruction::Context context;
1581 context.type = eContextArithmetic;
1582 context.SetRegisterRegisterOperands(op1_reg, op2_reg);
1584 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + d,
1585 (0x0000ffff & result)))
1590 // APSR.N = result<31>;
1591 // APSR.Z = IsZeroBit(result);
1592 m_new_inst_cpsr = m_opcode_cpsr;
1593 SetBit32(m_new_inst_cpsr, CPSR_N_POS, Bit32(result, 31));
1594 SetBit32(m_new_inst_cpsr, CPSR_Z_POS, result == 0 ? 1 : 0);
1595 if (m_new_inst_cpsr != m_opcode_cpsr) {
1596 if (!WriteRegisterUnsigned(context, eRegisterKindGeneric,
1597 LLDB_REGNUM_GENERIC_FLAGS, m_new_inst_cpsr))
1601 // if ArchVersion() == 4 then
1602 // APSR.C = bit UNKNOWN;
1608 // Bitwise NOT (immediate) writes the bitwise inverse of an immediate value to
1609 // the destination register.
1610 // It can optionally update the condition flags based on the value.
1611 bool EmulateInstructionARM::EmulateMVNImm(const uint32_t opcode,
1612 const ARMEncoding encoding) {
1614 // ARM pseudo code...
1615 if (ConditionPassed())
1617 EncodingSpecificOperations();
1618 result = NOT(imm32);
1619 if d == 15 then // Can only occur for ARM encoding
1620 ALUWritePC(result); // setflags is always FALSE here
1624 APSR.N = result<31>;
1625 APSR.Z = IsZeroBit(result);
1631 if (ConditionPassed(opcode)) {
1632 uint32_t Rd; // the destination register
1633 uint32_t imm32; // the output after ThumbExpandImm_C or ARMExpandImm_C
1634 uint32_t carry; // the carry bit after ThumbExpandImm_C or ARMExpandImm_C
1638 Rd = Bits32(opcode, 11, 8);
1639 setflags = BitIsSet(opcode, 20);
1640 imm32 = ThumbExpandImm_C(opcode, APSR_C, carry);
1643 Rd = Bits32(opcode, 15, 12);
1644 setflags = BitIsSet(opcode, 20);
1645 imm32 = ARMExpandImm_C(opcode, APSR_C, carry);
1647 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related
1649 if (Rd == 15 && setflags)
1650 return EmulateSUBSPcLrEtc(opcode, encoding);
1655 uint32_t result = ~imm32;
1657 // The context specifies that an immediate is to be moved into Rd.
1658 EmulateInstruction::Context context;
1659 context.type = EmulateInstruction::eContextImmediate;
1660 context.SetNoArgs();
1662 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
1668 // Bitwise NOT (register) writes the bitwise inverse of a register value to the
1669 // destination register.
1670 // It can optionally update the condition flags based on the result.
1671 bool EmulateInstructionARM::EmulateMVNReg(const uint32_t opcode,
1672 const ARMEncoding encoding) {
1674 // ARM pseudo code...
1675 if (ConditionPassed())
1677 EncodingSpecificOperations();
1678 (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C);
1679 result = NOT(shifted);
1680 if d == 15 then // Can only occur for ARM encoding
1681 ALUWritePC(result); // setflags is always FALSE here
1685 APSR.N = result<31>;
1686 APSR.Z = IsZeroBit(result);
1692 if (ConditionPassed(opcode)) {
1693 uint32_t Rm; // the source register
1694 uint32_t Rd; // the destination register
1695 ARM_ShifterType shift_t;
1696 uint32_t shift_n; // the shift applied to the value read from Rm
1698 uint32_t carry; // the carry bit after the shift operation
1701 Rd = Bits32(opcode, 2, 0);
1702 Rm = Bits32(opcode, 5, 3);
1703 setflags = !InITBlock();
1704 shift_t = SRType_LSL;
1710 Rd = Bits32(opcode, 11, 8);
1711 Rm = Bits32(opcode, 3, 0);
1712 setflags = BitIsSet(opcode, 20);
1713 shift_n = DecodeImmShiftThumb(opcode, shift_t);
1714 // if (BadReg(d) || BadReg(m)) then UNPREDICTABLE;
1715 if (BadReg(Rd) || BadReg(Rm))
1719 Rd = Bits32(opcode, 15, 12);
1720 Rm = Bits32(opcode, 3, 0);
1721 setflags = BitIsSet(opcode, 20);
1722 shift_n = DecodeImmShiftARM(opcode, shift_t);
1727 bool success = false;
1728 uint32_t value = ReadCoreReg(Rm, &success);
1733 Shift_C(value, shift_t, shift_n, APSR_C, carry, &success);
1736 uint32_t result = ~shifted;
1738 // The context specifies that an immediate is to be moved into Rd.
1739 EmulateInstruction::Context context;
1740 context.type = EmulateInstruction::eContextImmediate;
1741 context.SetNoArgs();
1743 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
1749 // PC relative immediate load into register, possibly followed by ADD (SP plus
1752 bool EmulateInstructionARM::EmulateLDRRtPCRelative(const uint32_t opcode,
1753 const ARMEncoding encoding) {
1755 // ARM pseudo code...
1756 if (ConditionPassed())
1758 EncodingSpecificOperations(); NullCheckIfThumbEE(15);
1760 address = if add then (base + imm32) else (base - imm32);
1761 data = MemU[address,4];
1763 if address<1:0> == '00' then LoadWritePC(data); else UNPREDICTABLE;
1764 elsif UnalignedSupport() || address<1:0> = '00' then
1766 else // Can only apply before ARMv7
1767 if CurrentInstrSet() == InstrSet_ARM then
1768 R[t] = ROR(data, 8*UInt(address<1:0>));
1770 R[t] = bits(32) UNKNOWN;
1774 if (ConditionPassed(opcode)) {
1775 bool success = false;
1776 const uint32_t pc = ReadCoreReg(PC_REG, &success);
1780 // PC relative immediate load context
1781 EmulateInstruction::Context context;
1782 context.type = EmulateInstruction::eContextRegisterPlusOffset;
1783 RegisterInfo pc_reg;
1784 GetRegisterInfo(eRegisterKindDWARF, dwarf_pc, pc_reg);
1785 context.SetRegisterPlusOffset(pc_reg, 0);
1787 uint32_t Rt; // the destination register
1788 uint32_t imm32; // immediate offset from the PC
1789 bool add; // +imm32 or -imm32?
1790 addr_t base; // the base address
1791 addr_t address; // the PC relative address
1792 uint32_t data; // the literal data value from the PC relative load
1795 Rt = Bits32(opcode, 10, 8);
1796 imm32 = Bits32(opcode, 7, 0) << 2; // imm32 = ZeroExtend(imm8:'00', 32);
1800 Rt = Bits32(opcode, 15, 12);
1801 imm32 = Bits32(opcode, 11, 0) << 2; // imm32 = ZeroExtend(imm12, 32);
1802 add = BitIsSet(opcode, 23);
1803 if (Rt == 15 && InITBlock() && !LastInITBlock())
1810 base = Align(pc, 4);
1812 address = base + imm32;
1814 address = base - imm32;
1816 context.SetRegisterPlusOffset(pc_reg, address - base);
1817 data = MemURead(context, address, 4, 0, &success);
1822 if (Bits32(address, 1, 0) == 0) {
1823 // In ARMv5T and above, this is an interworking branch.
1824 if (!LoadWritePC(context, data))
1828 } else if (UnalignedSupport() || Bits32(address, 1, 0) == 0) {
1829 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + Rt,
1832 } else // We don't handle ARM for now.
1838 // An add operation to adjust the SP.
1839 // ADD (SP plus immediate)
1840 bool EmulateInstructionARM::EmulateADDSPImm(const uint32_t opcode,
1841 const ARMEncoding encoding) {
1843 // ARM pseudo code...
1844 if (ConditionPassed())
1846 EncodingSpecificOperations();
1847 (result, carry, overflow) = AddWithCarry(SP, imm32, '0');
1848 if d == 15 then // Can only occur for ARM encoding
1849 ALUWritePC(result); // setflags is always FALSE here
1853 APSR.N = result<31>;
1854 APSR.Z = IsZeroBit(result);
1860 bool success = false;
1862 if (ConditionPassed(opcode)) {
1863 const addr_t sp = ReadCoreReg(SP_REG, &success);
1866 uint32_t imm32; // the immediate operand
1871 // d = UInt(Rd); setflags = FALSE; imm32 = ZeroExtend(imm8:'00', 32);
1872 d = Bits32(opcode, 10, 8);
1873 imm32 = (Bits32(opcode, 7, 0) << 2);
1878 // d = 13; setflags = FALSE; imm32 = ZeroExtend(imm7:'00', 32);
1880 imm32 = ThumbImm7Scaled(opcode); // imm32 = ZeroExtend(imm7:'00', 32)
1885 // d = UInt(Rd); setflags = (S == "1"); imm32 =
1886 // ThumbExpandImm(i:imm3:imm8);
1887 d = Bits32(opcode, 11, 8);
1888 imm32 = ThumbExpandImm(opcode);
1889 setflags = Bit32(opcode, 20);
1891 // if Rd == "1111" && S == "1" then SEE CMN (immediate);
1892 if (d == 15 && setflags == 1)
1893 return false; // CMN (immediate) not yet supported
1895 // if d == 15 && S == "0" then UNPREDICTABLE;
1896 if (d == 15 && setflags == 0)
1901 // if Rn == '1111' then SEE ADR;
1902 // d = UInt(Rd); setflags = FALSE; imm32 = ZeroExtend(i:imm3:imm8, 32);
1903 d = Bits32(opcode, 11, 8);
1905 uint32_t i = Bit32(opcode, 26);
1906 uint32_t imm3 = Bits32(opcode, 14, 12);
1907 uint32_t imm8 = Bits32(opcode, 7, 0);
1908 imm32 = (i << 11) | (imm3 << 8) | imm8;
1910 // if d == 15 then UNPREDICTABLE;
1918 // (result, carry, overflow) = AddWithCarry(R[n], imm32, '0');
1919 AddWithCarryResult res = AddWithCarry(sp, imm32, 0);
1921 EmulateInstruction::Context context;
1923 context.type = EmulateInstruction::eContextAdjustStackPointer;
1925 context.type = EmulateInstruction::eContextRegisterPlusOffset;
1927 RegisterInfo sp_reg;
1928 GetRegisterInfo(eRegisterKindDWARF, dwarf_sp, sp_reg);
1929 context.SetRegisterPlusOffset(sp_reg, res.result - sp);
1932 if (!ALUWritePC(context, res.result))
1937 // APSR.N = result<31>;
1938 // APSR.Z = IsZeroBit(result);
1940 // APSR.V = overflow;
1941 if (!WriteCoreRegOptionalFlags(context, res.result, d, setflags,
1942 res.carry_out, res.overflow))
1949 // An add operation to adjust the SP.
1950 // ADD (SP plus register)
1951 bool EmulateInstructionARM::EmulateADDSPRm(const uint32_t opcode,
1952 const ARMEncoding encoding) {
1954 // ARM pseudo code...
1955 if (ConditionPassed())
1957 EncodingSpecificOperations();
1958 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
1959 (result, carry, overflow) = AddWithCarry(SP, shifted, '0');
1961 ALUWritePC(result); // setflags is always FALSE here
1965 APSR.N = result<31>;
1966 APSR.Z = IsZeroBit(result);
1972 bool success = false;
1974 if (ConditionPassed(opcode)) {
1975 const addr_t sp = ReadCoreReg(SP_REG, &success);
1978 uint32_t Rm; // the second operand
1981 Rm = Bits32(opcode, 6, 3);
1986 int32_t reg_value = ReadCoreReg(Rm, &success);
1990 addr_t addr = (int32_t)sp + reg_value; // the adjusted stack pointer value
1992 EmulateInstruction::Context context;
1993 context.type = eContextArithmetic;
1994 RegisterInfo sp_reg;
1995 GetRegisterInfo(eRegisterKindDWARF, dwarf_sp, sp_reg);
1997 RegisterInfo other_reg;
1998 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + Rm, other_reg);
1999 context.SetRegisterRegisterOperands(sp_reg, other_reg);
2001 if (!WriteRegisterUnsigned(context, eRegisterKindGeneric,
2002 LLDB_REGNUM_GENERIC_SP, addr))
2008 // Branch with Link and Exchange Instruction Sets (immediate) calls a subroutine
2009 // at a PC-relative address, and changes instruction set from ARM to Thumb, or
2010 // from Thumb to ARM.
2012 bool EmulateInstructionARM::EmulateBLXImmediate(const uint32_t opcode,
2013 const ARMEncoding encoding) {
2015 // ARM pseudo code...
2016 if (ConditionPassed())
2018 EncodingSpecificOperations();
2019 if CurrentInstrSet() == InstrSet_ARM then
2022 LR = PC<31:1> : '1';
2023 if targetInstrSet == InstrSet_ARM then
2024 targetAddress = Align(PC,4) + imm32;
2026 targetAddress = PC + imm32;
2027 SelectInstrSet(targetInstrSet);
2028 BranchWritePC(targetAddress);
2032 bool success = true;
2034 if (ConditionPassed(opcode)) {
2035 EmulateInstruction::Context context;
2036 context.type = EmulateInstruction::eContextRelativeBranchImmediate;
2037 const uint32_t pc = ReadCoreReg(PC_REG, &success);
2040 addr_t lr; // next instruction address
2041 addr_t target; // target address
2042 int32_t imm32; // PC-relative offset
2045 lr = pc | 1u; // return address
2046 uint32_t S = Bit32(opcode, 26);
2047 uint32_t imm10 = Bits32(opcode, 25, 16);
2048 uint32_t J1 = Bit32(opcode, 13);
2049 uint32_t J2 = Bit32(opcode, 11);
2050 uint32_t imm11 = Bits32(opcode, 10, 0);
2051 uint32_t I1 = !(J1 ^ S);
2052 uint32_t I2 = !(J2 ^ S);
2054 (S << 24) | (I1 << 23) | (I2 << 22) | (imm10 << 12) | (imm11 << 1);
2055 imm32 = llvm::SignExtend32<25>(imm25);
2056 target = pc + imm32;
2057 SelectInstrSet(eModeThumb);
2058 context.SetISAAndImmediateSigned(eModeThumb, 4 + imm32);
2059 if (InITBlock() && !LastInITBlock())
2064 lr = pc | 1u; // return address
2065 uint32_t S = Bit32(opcode, 26);
2066 uint32_t imm10H = Bits32(opcode, 25, 16);
2067 uint32_t J1 = Bit32(opcode, 13);
2068 uint32_t J2 = Bit32(opcode, 11);
2069 uint32_t imm10L = Bits32(opcode, 10, 1);
2070 uint32_t I1 = !(J1 ^ S);
2071 uint32_t I2 = !(J2 ^ S);
2073 (S << 24) | (I1 << 23) | (I2 << 22) | (imm10H << 12) | (imm10L << 2);
2074 imm32 = llvm::SignExtend32<25>(imm25);
2075 target = Align(pc, 4) + imm32;
2076 SelectInstrSet(eModeARM);
2077 context.SetISAAndImmediateSigned(eModeARM, 4 + imm32);
2078 if (InITBlock() && !LastInITBlock())
2083 lr = pc - 4; // return address
2084 imm32 = llvm::SignExtend32<26>(Bits32(opcode, 23, 0) << 2);
2085 target = Align(pc, 4) + imm32;
2086 SelectInstrSet(eModeARM);
2087 context.SetISAAndImmediateSigned(eModeARM, 8 + imm32);
2090 lr = pc - 4; // return address
2091 imm32 = llvm::SignExtend32<26>(Bits32(opcode, 23, 0) << 2 |
2092 Bits32(opcode, 24, 24) << 1);
2093 target = pc + imm32;
2094 SelectInstrSet(eModeThumb);
2095 context.SetISAAndImmediateSigned(eModeThumb, 8 + imm32);
2100 if (!WriteRegisterUnsigned(context, eRegisterKindGeneric,
2101 LLDB_REGNUM_GENERIC_RA, lr))
2103 if (!BranchWritePC(context, target))
2105 if (m_opcode_cpsr != m_new_inst_cpsr)
2106 if (!WriteRegisterUnsigned(context, eRegisterKindGeneric,
2107 LLDB_REGNUM_GENERIC_FLAGS, m_new_inst_cpsr))
2113 // Branch with Link and Exchange (register) calls a subroutine at an address and
2114 // instruction set specified by a register.
2116 bool EmulateInstructionARM::EmulateBLXRm(const uint32_t opcode,
2117 const ARMEncoding encoding) {
2119 // ARM pseudo code...
2120 if (ConditionPassed())
2122 EncodingSpecificOperations();
2124 if CurrentInstrSet() == InstrSet_ARM then
2125 next_instr_addr = PC - 4;
2126 LR = next_instr_addr;
2128 next_instr_addr = PC - 2;
2129 LR = next_instr_addr<31:1> : '1';
2134 bool success = false;
2136 if (ConditionPassed(opcode)) {
2137 EmulateInstruction::Context context;
2138 context.type = EmulateInstruction::eContextAbsoluteBranchRegister;
2139 const uint32_t pc = ReadCoreReg(PC_REG, &success);
2140 addr_t lr; // next instruction address
2143 uint32_t Rm; // the register with the target address
2146 lr = (pc - 2) | 1u; // return address
2147 Rm = Bits32(opcode, 6, 3);
2148 // if m == 15 then UNPREDICTABLE;
2151 if (InITBlock() && !LastInITBlock())
2155 lr = pc - 4; // return address
2156 Rm = Bits32(opcode, 3, 0);
2157 // if m == 15 then UNPREDICTABLE;
2164 addr_t target = ReadCoreReg(Rm, &success);
2167 RegisterInfo dwarf_reg;
2168 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + Rm, dwarf_reg);
2169 context.SetRegister(dwarf_reg);
2170 if (!WriteRegisterUnsigned(context, eRegisterKindGeneric,
2171 LLDB_REGNUM_GENERIC_RA, lr))
2173 if (!BXWritePC(context, target))
2179 // Branch and Exchange causes a branch to an address and instruction set
2180 // specified by a register.
2181 bool EmulateInstructionARM::EmulateBXRm(const uint32_t opcode,
2182 const ARMEncoding encoding) {
2184 // ARM pseudo code...
2185 if (ConditionPassed())
2187 EncodingSpecificOperations();
2192 if (ConditionPassed(opcode)) {
2193 EmulateInstruction::Context context;
2194 context.type = EmulateInstruction::eContextAbsoluteBranchRegister;
2195 uint32_t Rm; // the register with the target address
2198 Rm = Bits32(opcode, 6, 3);
2199 if (InITBlock() && !LastInITBlock())
2203 Rm = Bits32(opcode, 3, 0);
2208 bool success = false;
2209 addr_t target = ReadCoreReg(Rm, &success);
2213 RegisterInfo dwarf_reg;
2214 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + Rm, dwarf_reg);
2215 context.SetRegister(dwarf_reg);
2216 if (!BXWritePC(context, target))
2222 // Branch and Exchange Jazelle attempts to change to Jazelle state. If the
2223 // attempt fails, it branches to an
2224 // address and instruction set specified by a register as though it were a BX
2227 // TODO: Emulate Jazelle architecture?
2228 // We currently assume that switching to Jazelle state fails, thus
2229 // treating BXJ as a BX operation.
2230 bool EmulateInstructionARM::EmulateBXJRm(const uint32_t opcode,
2231 const ARMEncoding encoding) {
2233 // ARM pseudo code...
2234 if (ConditionPassed())
2236 EncodingSpecificOperations();
2237 if JMCR.JE == '0' || CurrentInstrSet() == InstrSet_ThumbEE then
2240 if JazelleAcceptsExecution() then
2241 SwitchToJazelleExecution();
2243 SUBARCHITECTURE_DEFINED handler call;
2247 if (ConditionPassed(opcode)) {
2248 EmulateInstruction::Context context;
2249 context.type = EmulateInstruction::eContextAbsoluteBranchRegister;
2250 uint32_t Rm; // the register with the target address
2253 Rm = Bits32(opcode, 19, 16);
2256 if (InITBlock() && !LastInITBlock())
2260 Rm = Bits32(opcode, 3, 0);
2267 bool success = false;
2268 addr_t target = ReadCoreReg(Rm, &success);
2272 RegisterInfo dwarf_reg;
2273 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + Rm, dwarf_reg);
2274 context.SetRegister(dwarf_reg);
2275 if (!BXWritePC(context, target))
2281 // Set r7 to point to some ip offset.
2283 bool EmulateInstructionARM::EmulateSUBR7IPImm(const uint32_t opcode,
2284 const ARMEncoding encoding) {
2286 // ARM pseudo code...
2287 if (ConditionPassed())
2289 EncodingSpecificOperations();
2290 (result, carry, overflow) = AddWithCarry(SP, NOT(imm32), '1');
2291 if d == 15 then // Can only occur for ARM encoding
2292 ALUWritePC(result); // setflags is always FALSE here
2296 APSR.N = result<31>;
2297 APSR.Z = IsZeroBit(result);
2303 if (ConditionPassed(opcode)) {
2304 bool success = false;
2305 const addr_t ip = ReadCoreReg(12, &success);
2311 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
2316 addr_t ip_offset = imm32;
2317 addr_t addr = ip - ip_offset; // the adjusted ip value
2319 EmulateInstruction::Context context;
2320 context.type = EmulateInstruction::eContextRegisterPlusOffset;
2321 RegisterInfo dwarf_reg;
2322 GetRegisterInfo(eRegisterKindDWARF, dwarf_r12, dwarf_reg);
2323 context.SetRegisterPlusOffset(dwarf_reg, -ip_offset);
2325 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r7, addr))
2331 // Set ip to point to some stack offset.
2332 // SUB (SP minus immediate)
2333 bool EmulateInstructionARM::EmulateSUBIPSPImm(const uint32_t opcode,
2334 const ARMEncoding encoding) {
2336 // ARM pseudo code...
2337 if (ConditionPassed())
2339 EncodingSpecificOperations();
2340 (result, carry, overflow) = AddWithCarry(SP, NOT(imm32), '1');
2341 if d == 15 then // Can only occur for ARM encoding
2342 ALUWritePC(result); // setflags is always FALSE here
2346 APSR.N = result<31>;
2347 APSR.Z = IsZeroBit(result);
2353 if (ConditionPassed(opcode)) {
2354 bool success = false;
2355 const addr_t sp = ReadCoreReg(SP_REG, &success);
2361 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
2366 addr_t sp_offset = imm32;
2367 addr_t addr = sp - sp_offset; // the adjusted stack pointer value
2369 EmulateInstruction::Context context;
2370 context.type = EmulateInstruction::eContextRegisterPlusOffset;
2371 RegisterInfo dwarf_reg;
2372 GetRegisterInfo(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, dwarf_reg);
2373 context.SetRegisterPlusOffset(dwarf_reg, -sp_offset);
2375 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r12, addr))
2381 // This instruction subtracts an immediate value from the SP value, and writes
2382 // the result to the destination register.
2384 // If Rd == 13 => A sub operation to adjust the SP -- allocate space for local
2386 bool EmulateInstructionARM::EmulateSUBSPImm(const uint32_t opcode,
2387 const ARMEncoding encoding) {
2389 // ARM pseudo code...
2390 if (ConditionPassed())
2392 EncodingSpecificOperations();
2393 (result, carry, overflow) = AddWithCarry(SP, NOT(imm32), '1');
2394 if d == 15 then // Can only occur for ARM encoding
2395 ALUWritePC(result); // setflags is always FALSE here
2399 APSR.N = result<31>;
2400 APSR.Z = IsZeroBit(result);
2406 bool success = false;
2407 if (ConditionPassed(opcode)) {
2408 const addr_t sp = ReadCoreReg(SP_REG, &success);
2419 imm32 = ThumbImm7Scaled(opcode); // imm32 = ZeroExtend(imm7:'00', 32)
2422 Rd = Bits32(opcode, 11, 8);
2423 setflags = BitIsSet(opcode, 20);
2424 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8)
2425 if (Rd == 15 && setflags)
2426 return EmulateCMPImm(opcode, eEncodingT2);
2427 if (Rd == 15 && !setflags)
2431 Rd = Bits32(opcode, 11, 8);
2433 imm32 = ThumbImm12(opcode); // imm32 = ZeroExtend(i:imm3:imm8, 32)
2438 Rd = Bits32(opcode, 15, 12);
2439 setflags = BitIsSet(opcode, 20);
2440 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
2442 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related
2444 if (Rd == 15 && setflags)
2445 return EmulateSUBSPcLrEtc(opcode, encoding);
2450 AddWithCarryResult res = AddWithCarry(sp, ~imm32, 1);
2452 EmulateInstruction::Context context;
2454 uint64_t imm64 = imm32; // Need to expand it to 64 bits before attempting
2455 // to negate it, or the wrong
2456 // value gets passed down to context.SetImmediateSigned.
2457 context.type = EmulateInstruction::eContextAdjustStackPointer;
2458 context.SetImmediateSigned(-imm64); // the stack pointer offset
2460 context.type = EmulateInstruction::eContextImmediate;
2461 context.SetNoArgs();
2464 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags,
2465 res.carry_out, res.overflow))
2471 // A store operation to the stack that also updates the SP.
2472 bool EmulateInstructionARM::EmulateSTRRtSP(const uint32_t opcode,
2473 const ARMEncoding encoding) {
2475 // ARM pseudo code...
2476 if (ConditionPassed())
2478 EncodingSpecificOperations();
2479 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
2480 address = if index then offset_addr else R[n];
2481 MemU[address,4] = if t == 15 then PCStoreValue() else R[t];
2482 if wback then R[n] = offset_addr;
2486 bool success = false;
2487 if (ConditionPassed(opcode)) {
2488 const uint32_t addr_byte_size = GetAddressByteSize();
2489 const addr_t sp = ReadCoreReg(SP_REG, &success);
2492 uint32_t Rt; // the source register
2495 Rn; // This function assumes Rn is the SP, but we should verify that.
2502 Rt = Bits32(opcode, 15, 12);
2503 imm12 = Bits32(opcode, 11, 0);
2504 Rn = Bits32(opcode, 19, 16);
2506 if (Rn != 13) // 13 is the SP reg on ARM. Verify that Rn == SP.
2509 index = BitIsSet(opcode, 24);
2510 add = BitIsSet(opcode, 23);
2511 wback = (BitIsClear(opcode, 24) || BitIsSet(opcode, 21));
2513 if (wback && ((Rn == 15) || (Rn == Rt)))
2521 offset_addr = sp + imm12;
2523 offset_addr = sp - imm12;
2531 EmulateInstruction::Context context;
2532 context.type = EmulateInstruction::eContextPushRegisterOnStack;
2533 RegisterInfo sp_reg;
2534 RegisterInfo dwarf_reg;
2536 GetRegisterInfo(eRegisterKindDWARF, dwarf_sp, sp_reg);
2537 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + Rt, dwarf_reg);
2538 context.SetRegisterToRegisterPlusOffset(dwarf_reg, sp_reg, addr - sp);
2540 uint32_t reg_value = ReadCoreReg(Rt, &success);
2543 if (!MemUWrite(context, addr, reg_value, addr_byte_size))
2546 const uint32_t pc = ReadCoreReg(PC_REG, &success);
2549 if (!MemUWrite(context, addr, pc, addr_byte_size))
2554 context.type = EmulateInstruction::eContextAdjustStackPointer;
2555 context.SetImmediateSigned(addr - sp);
2556 if (!WriteRegisterUnsigned(context, eRegisterKindGeneric,
2557 LLDB_REGNUM_GENERIC_SP, offset_addr))
2564 // Vector Push stores multiple extension registers to the stack.
2565 // It also updates SP to point to the start of the stored data.
2566 bool EmulateInstructionARM::EmulateVPUSH(const uint32_t opcode,
2567 const ARMEncoding encoding) {
2569 // ARM pseudo code...
2570 if (ConditionPassed())
2572 EncodingSpecificOperations(); CheckVFPEnabled(TRUE); NullCheckIfThumbEE(13);
2573 address = SP - imm32;
2577 MemA[address,4] = S[d+r]; address = address+4;
2580 // Store as two word-aligned words in the correct order for current endianness.
2581 MemA[address,4] = if BigEndian() then D[d+r]<63:32> else D[d+r]<31:0>;
2582 MemA[address+4,4] = if BigEndian() then D[d+r]<31:0> else D[d+r]<63:32>;
2583 address = address+8;
2587 bool success = false;
2588 if (ConditionPassed(opcode)) {
2589 const uint32_t addr_byte_size = GetAddressByteSize();
2590 const addr_t sp = ReadCoreReg(SP_REG, &success);
2594 uint32_t d; // UInt(D:Vd) or UInt(Vd:D) starting register
2595 uint32_t imm32; // stack offset
2596 uint32_t regs; // number of registers
2600 single_regs = false;
2601 d = Bit32(opcode, 22) << 4 | Bits32(opcode, 15, 12);
2602 imm32 = Bits32(opcode, 7, 0) * addr_byte_size;
2603 // If UInt(imm8) is odd, see "FSTMX".
2604 regs = Bits32(opcode, 7, 0) / 2;
2605 // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE;
2606 if (regs == 0 || regs > 16 || (d + regs) > 32)
2612 d = Bits32(opcode, 15, 12) << 1 | Bit32(opcode, 22);
2613 imm32 = Bits32(opcode, 7, 0) * addr_byte_size;
2614 regs = Bits32(opcode, 7, 0);
2615 // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE;
2616 if (regs == 0 || regs > 16 || (d + regs) > 32)
2622 uint32_t start_reg = single_regs ? dwarf_s0 : dwarf_d0;
2623 uint32_t reg_byte_size = single_regs ? addr_byte_size : addr_byte_size * 2;
2624 addr_t sp_offset = imm32;
2625 addr_t addr = sp - sp_offset;
2628 EmulateInstruction::Context context;
2629 context.type = EmulateInstruction::eContextPushRegisterOnStack;
2631 RegisterInfo dwarf_reg;
2632 RegisterInfo sp_reg;
2633 GetRegisterInfo(eRegisterKindDWARF, dwarf_sp, sp_reg);
2634 for (i = 0; i < regs; ++i) {
2635 GetRegisterInfo(eRegisterKindDWARF, start_reg + d + i, dwarf_reg);
2636 context.SetRegisterToRegisterPlusOffset(dwarf_reg, sp_reg, addr - sp);
2637 // uint64_t to accommodate 64-bit registers.
2638 uint64_t reg_value = ReadRegisterUnsigned(&dwarf_reg, 0, &success);
2641 if (!MemAWrite(context, addr, reg_value, reg_byte_size))
2643 addr += reg_byte_size;
2646 context.type = EmulateInstruction::eContextAdjustStackPointer;
2647 context.SetImmediateSigned(-sp_offset);
2649 if (!WriteRegisterUnsigned(context, eRegisterKindGeneric,
2650 LLDB_REGNUM_GENERIC_SP, sp - sp_offset))
2656 // Vector Pop loads multiple extension registers from the stack.
2657 // It also updates SP to point just above the loaded data.
2658 bool EmulateInstructionARM::EmulateVPOP(const uint32_t opcode,
2659 const ARMEncoding encoding) {
2661 // ARM pseudo code...
2662 if (ConditionPassed())
2664 EncodingSpecificOperations(); CheckVFPEnabled(TRUE); NullCheckIfThumbEE(13);
2669 S[d+r] = MemA[address,4]; address = address+4;
2672 word1 = MemA[address,4]; word2 = MemA[address+4,4]; address = address+8;
2673 // Combine the word-aligned words in the correct order for current endianness.
2674 D[d+r] = if BigEndian() then word1:word2 else word2:word1;
2678 bool success = false;
2679 if (ConditionPassed(opcode)) {
2680 const uint32_t addr_byte_size = GetAddressByteSize();
2681 const addr_t sp = ReadCoreReg(SP_REG, &success);
2685 uint32_t d; // UInt(D:Vd) or UInt(Vd:D) starting register
2686 uint32_t imm32; // stack offset
2687 uint32_t regs; // number of registers
2691 single_regs = false;
2692 d = Bit32(opcode, 22) << 4 | Bits32(opcode, 15, 12);
2693 imm32 = Bits32(opcode, 7, 0) * addr_byte_size;
2694 // If UInt(imm8) is odd, see "FLDMX".
2695 regs = Bits32(opcode, 7, 0) / 2;
2696 // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE;
2697 if (regs == 0 || regs > 16 || (d + regs) > 32)
2703 d = Bits32(opcode, 15, 12) << 1 | Bit32(opcode, 22);
2704 imm32 = Bits32(opcode, 7, 0) * addr_byte_size;
2705 regs = Bits32(opcode, 7, 0);
2706 // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE;
2707 if (regs == 0 || regs > 16 || (d + regs) > 32)
2713 uint32_t start_reg = single_regs ? dwarf_s0 : dwarf_d0;
2714 uint32_t reg_byte_size = single_regs ? addr_byte_size : addr_byte_size * 2;
2715 addr_t sp_offset = imm32;
2718 uint64_t data; // uint64_t to accommodate 64-bit registers.
2720 EmulateInstruction::Context context;
2721 context.type = EmulateInstruction::eContextPopRegisterOffStack;
2723 RegisterInfo dwarf_reg;
2724 RegisterInfo sp_reg;
2725 GetRegisterInfo(eRegisterKindDWARF, dwarf_sp, sp_reg);
2726 for (i = 0; i < regs; ++i) {
2727 GetRegisterInfo(eRegisterKindDWARF, start_reg + d + i, dwarf_reg);
2728 context.SetAddress(addr);
2729 data = MemARead(context, addr, reg_byte_size, 0, &success);
2732 if (!WriteRegisterUnsigned(context, &dwarf_reg, data))
2734 addr += reg_byte_size;
2737 context.type = EmulateInstruction::eContextAdjustStackPointer;
2738 context.SetImmediateSigned(sp_offset);
2740 if (!WriteRegisterUnsigned(context, eRegisterKindGeneric,
2741 LLDB_REGNUM_GENERIC_SP, sp + sp_offset))
2747 // SVC (previously SWI)
2748 bool EmulateInstructionARM::EmulateSVC(const uint32_t opcode,
2749 const ARMEncoding encoding) {
2751 // ARM pseudo code...
2752 if (ConditionPassed())
2754 EncodingSpecificOperations();
2759 bool success = false;
2761 if (ConditionPassed(opcode)) {
2762 const uint32_t pc = ReadCoreReg(PC_REG, &success);
2763 addr_t lr; // next instruction address
2766 uint32_t imm32; // the immediate constant
2767 uint32_t mode; // ARM or Thumb mode
2770 lr = (pc + 2) | 1u; // return address
2771 imm32 = Bits32(opcode, 7, 0);
2775 lr = pc + 4; // return address
2776 imm32 = Bits32(opcode, 23, 0);
2783 EmulateInstruction::Context context;
2784 context.type = EmulateInstruction::eContextSupervisorCall;
2785 context.SetISAAndImmediate(mode, imm32);
2786 if (!WriteRegisterUnsigned(context, eRegisterKindGeneric,
2787 LLDB_REGNUM_GENERIC_RA, lr))
2793 // If Then makes up to four following instructions (the IT block) conditional.
2794 bool EmulateInstructionARM::EmulateIT(const uint32_t opcode,
2795 const ARMEncoding encoding) {
2797 // ARM pseudo code...
2798 EncodingSpecificOperations();
2799 ITSTATE.IT<7:0> = firstcond:mask;
2802 m_it_session.InitIT(Bits32(opcode, 7, 0));
2806 bool EmulateInstructionARM::EmulateNop(const uint32_t opcode,
2807 const ARMEncoding encoding) {
2808 // NOP, nothing to do...
2812 // Branch causes a branch to a target address.
2813 bool EmulateInstructionARM::EmulateB(const uint32_t opcode,
2814 const ARMEncoding encoding) {
2816 // ARM pseudo code...
2817 if (ConditionPassed())
2819 EncodingSpecificOperations();
2820 BranchWritePC(PC + imm32);
2824 bool success = false;
2826 if (ConditionPassed(opcode)) {
2827 EmulateInstruction::Context context;
2828 context.type = EmulateInstruction::eContextRelativeBranchImmediate;
2829 const uint32_t pc = ReadCoreReg(PC_REG, &success);
2832 addr_t target; // target address
2833 int32_t imm32; // PC-relative offset
2836 // The 'cond' field is handled in EmulateInstructionARM::CurrentCond().
2837 imm32 = llvm::SignExtend32<9>(Bits32(opcode, 7, 0) << 1);
2838 target = pc + imm32;
2839 context.SetISAAndImmediateSigned(eModeThumb, 4 + imm32);
2842 imm32 = llvm::SignExtend32<12>(Bits32(opcode, 10, 0) << 1);
2843 target = pc + imm32;
2844 context.SetISAAndImmediateSigned(eModeThumb, 4 + imm32);
2847 // The 'cond' field is handled in EmulateInstructionARM::CurrentCond().
2849 if (Bits32(opcode, 25, 23) == 7)
2850 return false; // See Branches and miscellaneous control on page
2853 uint32_t S = Bit32(opcode, 26);
2854 uint32_t imm6 = Bits32(opcode, 21, 16);
2855 uint32_t J1 = Bit32(opcode, 13);
2856 uint32_t J2 = Bit32(opcode, 11);
2857 uint32_t imm11 = Bits32(opcode, 10, 0);
2859 (S << 20) | (J2 << 19) | (J1 << 18) | (imm6 << 12) | (imm11 << 1);
2860 imm32 = llvm::SignExtend32<21>(imm21);
2861 target = pc + imm32;
2862 context.SetISAAndImmediateSigned(eModeThumb, 4 + imm32);
2866 uint32_t S = Bit32(opcode, 26);
2867 uint32_t imm10 = Bits32(opcode, 25, 16);
2868 uint32_t J1 = Bit32(opcode, 13);
2869 uint32_t J2 = Bit32(opcode, 11);
2870 uint32_t imm11 = Bits32(opcode, 10, 0);
2871 uint32_t I1 = !(J1 ^ S);
2872 uint32_t I2 = !(J2 ^ S);
2874 (S << 24) | (I1 << 23) | (I2 << 22) | (imm10 << 12) | (imm11 << 1);
2875 imm32 = llvm::SignExtend32<25>(imm25);
2876 target = pc + imm32;
2877 context.SetISAAndImmediateSigned(eModeThumb, 4 + imm32);
2881 imm32 = llvm::SignExtend32<26>(Bits32(opcode, 23, 0) << 2);
2882 target = pc + imm32;
2883 context.SetISAAndImmediateSigned(eModeARM, 8 + imm32);
2888 if (!BranchWritePC(context, target))
2894 // Compare and Branch on Nonzero and Compare and Branch on Zero compare the
2895 // value in a register with
2896 // zero and conditionally branch forward a constant value. They do not affect
2897 // the condition flags.
2899 bool EmulateInstructionARM::EmulateCB(const uint32_t opcode,
2900 const ARMEncoding encoding) {
2902 // ARM pseudo code...
2903 EncodingSpecificOperations();
2904 if nonzero ^ IsZero(R[n]) then
2905 BranchWritePC(PC + imm32);
2908 bool success = false;
2910 // Read the register value from the operand register Rn.
2911 uint32_t reg_val = ReadCoreReg(Bits32(opcode, 2, 0), &success);
2915 EmulateInstruction::Context context;
2916 context.type = EmulateInstruction::eContextRelativeBranchImmediate;
2917 const uint32_t pc = ReadCoreReg(PC_REG, &success);
2921 addr_t target; // target address
2922 uint32_t imm32; // PC-relative offset to branch forward
2926 imm32 = Bit32(opcode, 9) << 6 | Bits32(opcode, 7, 3) << 1;
2927 nonzero = BitIsSet(opcode, 11);
2928 target = pc + imm32;
2929 context.SetISAAndImmediateSigned(eModeThumb, 4 + imm32);
2934 if (m_ignore_conditions || (nonzero ^ (reg_val == 0)))
2935 if (!BranchWritePC(context, target))
2941 // Table Branch Byte causes a PC-relative forward branch using a table of single
2943 // A base register provides a pointer to the table, and a second register
2944 // supplies an index into the table.
2945 // The branch length is twice the value of the byte returned from the table.
2947 // Table Branch Halfword causes a PC-relative forward branch using a table of
2948 // single halfword offsets.
2949 // A base register provides a pointer to the table, and a second register
2950 // supplies an index into the table.
2951 // The branch length is twice the value of the halfword returned from the table.
2953 bool EmulateInstructionARM::EmulateTB(const uint32_t opcode,
2954 const ARMEncoding encoding) {
2956 // ARM pseudo code...
2957 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
2959 halfwords = UInt(MemU[R[n]+LSL(R[m],1), 2]);
2961 halfwords = UInt(MemU[R[n]+R[m], 1]);
2962 BranchWritePC(PC + 2*halfwords);
2965 bool success = false;
2967 if (ConditionPassed(opcode)) {
2968 uint32_t Rn; // the base register which contains the address of the table of
2970 uint32_t Rm; // the index register which contains an integer pointing to a
2971 // byte/halfword in the table
2972 bool is_tbh; // true if table branch halfword
2975 Rn = Bits32(opcode, 19, 16);
2976 Rm = Bits32(opcode, 3, 0);
2977 is_tbh = BitIsSet(opcode, 4);
2978 if (Rn == 13 || BadReg(Rm))
2980 if (InITBlock() && !LastInITBlock())
2987 // Read the address of the table from the operand register Rn.
2988 // The PC can be used, in which case the table immediately follows this
2990 uint32_t base = ReadCoreReg(Rn, &success);
2995 uint32_t index = ReadCoreReg(Rm, &success);
2999 // the offsetted table address
3000 addr_t addr = base + (is_tbh ? index * 2 : index);
3002 // PC-relative offset to branch forward
3003 EmulateInstruction::Context context;
3004 context.type = EmulateInstruction::eContextTableBranchReadMemory;
3005 uint32_t offset = MemURead(context, addr, is_tbh ? 2 : 1, 0, &success) * 2;
3009 const uint32_t pc = ReadCoreReg(PC_REG, &success);
3014 addr_t target = pc + offset;
3015 context.type = EmulateInstruction::eContextRelativeBranchImmediate;
3016 context.SetISAAndImmediateSigned(eModeThumb, 4 + offset);
3018 if (!BranchWritePC(context, target))
3025 // This instruction adds an immediate value to a register value, and writes the
3026 // result to the destination register.
3027 // It can optionally update the condition flags based on the result.
3028 bool EmulateInstructionARM::EmulateADDImmThumb(const uint32_t opcode,
3029 const ARMEncoding encoding) {
3031 if ConditionPassed() then
3032 EncodingSpecificOperations();
3033 (result, carry, overflow) = AddWithCarry(R[n], imm32, '0');
3036 APSR.N = result<31>;
3037 APSR.Z = IsZeroBit(result);
3042 bool success = false;
3044 if (ConditionPassed(opcode)) {
3051 // EncodingSpecificOperations();
3054 // d = UInt(Rd); n = UInt(Rn); setflags = !InITBlock(); imm32 =
3055 // ZeroExtend(imm3, 32);
3056 d = Bits32(opcode, 2, 0);
3057 n = Bits32(opcode, 5, 3);
3058 setflags = !InITBlock();
3059 imm32 = Bits32(opcode, 8, 6);
3064 // d = UInt(Rdn); n = UInt(Rdn); setflags = !InITBlock(); imm32 =
3065 // ZeroExtend(imm8, 32);
3066 d = Bits32(opcode, 10, 8);
3067 n = Bits32(opcode, 10, 8);
3068 setflags = !InITBlock();
3069 imm32 = Bits32(opcode, 7, 0);
3074 // if Rd == '1111' && S == '1' then SEE CMN (immediate);
3075 // d = UInt(Rd); n = UInt(Rn); setflags = (S == '1'); imm32 =
3076 // ThumbExpandImm(i:imm3:imm8);
3077 d = Bits32(opcode, 11, 8);
3078 n = Bits32(opcode, 19, 16);
3079 setflags = BitIsSet(opcode, 20);
3080 imm32 = ThumbExpandImm_C(opcode, APSR_C, carry_out);
3082 // if Rn == '1101' then SEE ADD (SP plus immediate);
3084 return EmulateADDSPImm(opcode, eEncodingT3);
3086 // if BadReg(d) || n == 15 then UNPREDICTABLE;
3087 if (BadReg(d) || (n == 15))
3093 // if Rn == '1111' then SEE ADR;
3094 // d = UInt(Rd); n = UInt(Rn); setflags = FALSE; imm32 =
3095 // ZeroExtend(i:imm3:imm8, 32);
3096 d = Bits32(opcode, 11, 8);
3097 n = Bits32(opcode, 19, 16);
3099 uint32_t i = Bit32(opcode, 26);
3100 uint32_t imm3 = Bits32(opcode, 14, 12);
3101 uint32_t imm8 = Bits32(opcode, 7, 0);
3102 imm32 = (i << 11) | (imm3 << 8) | imm8;
3104 // if Rn == '1101' then SEE ADD (SP plus immediate);
3106 return EmulateADDSPImm(opcode, eEncodingT4);
3108 // if BadReg(d) then UNPREDICTABLE;
3120 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
3124 //(result, carry, overflow) = AddWithCarry(R[n], imm32, '0');
3125 AddWithCarryResult res = AddWithCarry(Rn, imm32, 0);
3128 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n, reg_n);
3130 EmulateInstruction::Context context;
3131 context.type = eContextArithmetic;
3132 context.SetRegisterPlusOffset(reg_n, imm32);
3136 // APSR.N = result<31>;
3137 // APSR.Z = IsZeroBit(result);
3139 // APSR.V = overflow;
3140 if (!WriteCoreRegOptionalFlags(context, res.result, d, setflags,
3141 res.carry_out, res.overflow))
3147 // This instruction adds an immediate value to a register value, and writes the
3148 // result to the destination
3149 // register. It can optionally update the condition flags based on the result.
3150 bool EmulateInstructionARM::EmulateADDImmARM(const uint32_t opcode,
3151 const ARMEncoding encoding) {
3153 // ARM pseudo code...
3154 if ConditionPassed() then
3155 EncodingSpecificOperations();
3156 (result, carry, overflow) = AddWithCarry(R[n], imm32, '0');
3158 ALUWritePC(result); // setflags is always FALSE here
3162 APSR.N = result<31>;
3163 APSR.Z = IsZeroBit(result);
3168 bool success = false;
3170 if (ConditionPassed(opcode)) {
3173 imm32; // the immediate value to be added to the value obtained from Rn
3177 Rd = Bits32(opcode, 15, 12);
3178 Rn = Bits32(opcode, 19, 16);
3179 setflags = BitIsSet(opcode, 20);
3180 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
3186 // Read the first operand.
3187 uint32_t val1 = ReadCoreReg(Rn, &success);
3191 AddWithCarryResult res = AddWithCarry(val1, imm32, 0);
3193 EmulateInstruction::Context context;
3195 context.type = EmulateInstruction::eContextAdjustStackPointer;
3196 else if (Rd == GetFramePointerRegisterNumber())
3197 context.type = EmulateInstruction::eContextSetFramePointer;
3199 context.type = EmulateInstruction::eContextRegisterPlusOffset;
3201 RegisterInfo dwarf_reg;
3202 GetRegisterInfo(eRegisterKindDWARF, Rn, dwarf_reg);
3203 context.SetRegisterPlusOffset(dwarf_reg, imm32);
3205 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags,
3206 res.carry_out, res.overflow))
3212 // This instruction adds a register value and an optionally-shifted register
3213 // value, and writes the result
3214 // to the destination register. It can optionally update the condition flags
3215 // based on the result.
3216 bool EmulateInstructionARM::EmulateADDReg(const uint32_t opcode,
3217 const ARMEncoding encoding) {
3219 // ARM pseudo code...
3220 if ConditionPassed() then
3221 EncodingSpecificOperations();
3222 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
3223 (result, carry, overflow) = AddWithCarry(R[n], shifted, '0');
3225 ALUWritePC(result); // setflags is always FALSE here
3229 APSR.N = result<31>;
3230 APSR.Z = IsZeroBit(result);
3235 bool success = false;
3237 if (ConditionPassed(opcode)) {
3238 uint32_t Rd, Rn, Rm;
3239 ARM_ShifterType shift_t;
3240 uint32_t shift_n; // the shift applied to the value read from Rm
3244 Rd = Bits32(opcode, 2, 0);
3245 Rn = Bits32(opcode, 5, 3);
3246 Rm = Bits32(opcode, 8, 6);
3247 setflags = !InITBlock();
3248 shift_t = SRType_LSL;
3252 Rd = Rn = Bit32(opcode, 7) << 3 | Bits32(opcode, 2, 0);
3253 Rm = Bits32(opcode, 6, 3);
3255 shift_t = SRType_LSL;
3257 if (Rn == 15 && Rm == 15)
3259 if (Rd == 15 && InITBlock() && !LastInITBlock())
3263 Rd = Bits32(opcode, 15, 12);
3264 Rn = Bits32(opcode, 19, 16);
3265 Rm = Bits32(opcode, 3, 0);
3266 setflags = BitIsSet(opcode, 20);
3267 shift_n = DecodeImmShiftARM(opcode, shift_t);
3273 // Read the first operand.
3274 uint32_t val1 = ReadCoreReg(Rn, &success);
3278 // Read the second operand.
3279 uint32_t val2 = ReadCoreReg(Rm, &success);
3283 uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C, &success);
3286 AddWithCarryResult res = AddWithCarry(val1, shifted, 0);
3288 EmulateInstruction::Context context;
3289 context.type = eContextArithmetic;
3290 RegisterInfo op1_reg;
3291 RegisterInfo op2_reg;
3292 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + Rn, op1_reg);
3293 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + Rm, op2_reg);
3294 context.SetRegisterRegisterOperands(op1_reg, op2_reg);
3296 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags,
3297 res.carry_out, res.overflow))
3303 // Compare Negative (immediate) adds a register value and an immediate value.
3304 // It updates the condition flags based on the result, and discards the result.
3305 bool EmulateInstructionARM::EmulateCMNImm(const uint32_t opcode,
3306 const ARMEncoding encoding) {
3308 // ARM pseudo code...
3309 if ConditionPassed() then
3310 EncodingSpecificOperations();
3311 (result, carry, overflow) = AddWithCarry(R[n], imm32, '0');
3312 APSR.N = result<31>;
3313 APSR.Z = IsZeroBit(result);
3318 bool success = false;
3320 uint32_t Rn; // the first operand
3321 uint32_t imm32; // the immediate value to be compared with
3324 Rn = Bits32(opcode, 19, 16);
3325 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8)
3330 Rn = Bits32(opcode, 19, 16);
3331 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
3336 // Read the register value from the operand register Rn.
3337 uint32_t reg_val = ReadCoreReg(Rn, &success);
3341 AddWithCarryResult res = AddWithCarry(reg_val, imm32, 0);
3343 EmulateInstruction::Context context;
3344 context.type = EmulateInstruction::eContextImmediate;
3345 context.SetNoArgs();
3346 if (!WriteFlags(context, res.result, res.carry_out, res.overflow))
3352 // Compare Negative (register) adds a register value and an optionally-shifted
3354 // It updates the condition flags based on the result, and discards the result.
3355 bool EmulateInstructionARM::EmulateCMNReg(const uint32_t opcode,
3356 const ARMEncoding encoding) {
3358 // ARM pseudo code...
3359 if ConditionPassed() then
3360 EncodingSpecificOperations();
3361 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
3362 (result, carry, overflow) = AddWithCarry(R[n], shifted, '0');
3363 APSR.N = result<31>;
3364 APSR.Z = IsZeroBit(result);
3369 bool success = false;
3371 uint32_t Rn; // the first operand
3372 uint32_t Rm; // the second operand
3373 ARM_ShifterType shift_t;
3374 uint32_t shift_n; // the shift applied to the value read from Rm
3377 Rn = Bits32(opcode, 2, 0);
3378 Rm = Bits32(opcode, 5, 3);
3379 shift_t = SRType_LSL;
3383 Rn = Bits32(opcode, 19, 16);
3384 Rm = Bits32(opcode, 3, 0);
3385 shift_n = DecodeImmShiftThumb(opcode, shift_t);
3386 // if n == 15 || BadReg(m) then UNPREDICTABLE;
3387 if (Rn == 15 || BadReg(Rm))
3391 Rn = Bits32(opcode, 19, 16);
3392 Rm = Bits32(opcode, 3, 0);
3393 shift_n = DecodeImmShiftARM(opcode, shift_t);
3398 // Read the register value from register Rn.
3399 uint32_t val1 = ReadCoreReg(Rn, &success);
3403 // Read the register value from register Rm.
3404 uint32_t val2 = ReadCoreReg(Rm, &success);
3408 uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C, &success);
3411 AddWithCarryResult res = AddWithCarry(val1, shifted, 0);
3413 EmulateInstruction::Context context;
3414 context.type = EmulateInstruction::eContextImmediate;
3415 context.SetNoArgs();
3416 if (!WriteFlags(context, res.result, res.carry_out, res.overflow))
3422 // Compare (immediate) subtracts an immediate value from a register value.
3423 // It updates the condition flags based on the result, and discards the result.
3424 bool EmulateInstructionARM::EmulateCMPImm(const uint32_t opcode,
3425 const ARMEncoding encoding) {
3427 // ARM pseudo code...
3428 if ConditionPassed() then
3429 EncodingSpecificOperations();
3430 (result, carry, overflow) = AddWithCarry(R[n], NOT(imm32), '1');
3431 APSR.N = result<31>;
3432 APSR.Z = IsZeroBit(result);
3437 bool success = false;
3439 uint32_t Rn; // the first operand
3440 uint32_t imm32; // the immediate value to be compared with
3443 Rn = Bits32(opcode, 10, 8);
3444 imm32 = Bits32(opcode, 7, 0);
3447 Rn = Bits32(opcode, 19, 16);
3448 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8)
3453 Rn = Bits32(opcode, 19, 16);
3454 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
3459 // Read the register value from the operand register Rn.
3460 uint32_t reg_val = ReadCoreReg(Rn, &success);
3464 AddWithCarryResult res = AddWithCarry(reg_val, ~imm32, 1);
3466 EmulateInstruction::Context context;
3467 context.type = EmulateInstruction::eContextImmediate;
3468 context.SetNoArgs();
3469 if (!WriteFlags(context, res.result, res.carry_out, res.overflow))
3475 // Compare (register) subtracts an optionally-shifted register value from a
3477 // It updates the condition flags based on the result, and discards the result.
3478 bool EmulateInstructionARM::EmulateCMPReg(const uint32_t opcode,
3479 const ARMEncoding encoding) {
3481 // ARM pseudo code...
3482 if ConditionPassed() then
3483 EncodingSpecificOperations();
3484 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
3485 (result, carry, overflow) = AddWithCarry(R[n], NOT(shifted), '1');
3486 APSR.N = result<31>;
3487 APSR.Z = IsZeroBit(result);
3492 bool success = false;
3494 uint32_t Rn; // the first operand
3495 uint32_t Rm; // the second operand
3496 ARM_ShifterType shift_t;
3497 uint32_t shift_n; // the shift applied to the value read from Rm
3500 Rn = Bits32(opcode, 2, 0);
3501 Rm = Bits32(opcode, 5, 3);
3502 shift_t = SRType_LSL;
3506 Rn = Bit32(opcode, 7) << 3 | Bits32(opcode, 2, 0);
3507 Rm = Bits32(opcode, 6, 3);
3508 shift_t = SRType_LSL;
3510 if (Rn < 8 && Rm < 8)
3512 if (Rn == 15 || Rm == 15)
3516 Rn = Bits32(opcode, 19, 16);
3517 Rm = Bits32(opcode, 3, 0);
3518 shift_n = DecodeImmShiftThumb(opcode, shift_t);
3519 if (Rn == 15 || BadReg(Rm))
3523 Rn = Bits32(opcode, 19, 16);
3524 Rm = Bits32(opcode, 3, 0);
3525 shift_n = DecodeImmShiftARM(opcode, shift_t);
3530 // Read the register value from register Rn.
3531 uint32_t val1 = ReadCoreReg(Rn, &success);
3535 // Read the register value from register Rm.
3536 uint32_t val2 = ReadCoreReg(Rm, &success);
3540 uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C, &success);
3543 AddWithCarryResult res = AddWithCarry(val1, ~shifted, 1);
3545 EmulateInstruction::Context context;
3546 context.type = EmulateInstruction::eContextImmediate;
3547 context.SetNoArgs();
3548 if (!WriteFlags(context, res.result, res.carry_out, res.overflow))
3554 // Arithmetic Shift Right (immediate) shifts a register value right by an
3555 // immediate number of bits,
3556 // shifting in copies of its sign bit, and writes the result to the destination
3558 // optionally update the condition flags based on the result.
3559 bool EmulateInstructionARM::EmulateASRImm(const uint32_t opcode,
3560 const ARMEncoding encoding) {
3562 // ARM pseudo code...
3563 if ConditionPassed() then
3564 EncodingSpecificOperations();
3565 (result, carry) = Shift_C(R[m], SRType_ASR, shift_n, APSR.C);
3566 if d == 15 then // Can only occur for ARM encoding
3567 ALUWritePC(result); // setflags is always FALSE here
3571 APSR.N = result<31>;
3572 APSR.Z = IsZeroBit(result);
3577 return EmulateShiftImm(opcode, encoding, SRType_ASR);
3580 // Arithmetic Shift Right (register) shifts a register value right by a variable
3582 // shifting in copies of its sign bit, and writes the result to the destination
3584 // The variable number of bits is read from the bottom byte of a register. It
3585 // can optionally update
3586 // the condition flags based on the result.
3587 bool EmulateInstructionARM::EmulateASRReg(const uint32_t opcode,
3588 const ARMEncoding encoding) {
3590 // ARM pseudo code...
3591 if ConditionPassed() then
3592 EncodingSpecificOperations();
3593 shift_n = UInt(R[m]<7:0>);
3594 (result, carry) = Shift_C(R[m], SRType_ASR, shift_n, APSR.C);
3597 APSR.N = result<31>;
3598 APSR.Z = IsZeroBit(result);
3603 return EmulateShiftReg(opcode, encoding, SRType_ASR);
3606 // Logical Shift Left (immediate) shifts a register value left by an immediate
3608 // shifting in zeros, and writes the result to the destination register. It can
3610 // update the condition flags based on the result.
3611 bool EmulateInstructionARM::EmulateLSLImm(const uint32_t opcode,
3612 const ARMEncoding encoding) {
3614 // ARM pseudo code...
3615 if ConditionPassed() then
3616 EncodingSpecificOperations();
3617 (result, carry) = Shift_C(R[m], SRType_LSL, shift_n, APSR.C);
3618 if d == 15 then // Can only occur for ARM encoding
3619 ALUWritePC(result); // setflags is always FALSE here
3623 APSR.N = result<31>;
3624 APSR.Z = IsZeroBit(result);
3629 return EmulateShiftImm(opcode, encoding, SRType_LSL);
3632 // Logical Shift Left (register) shifts a register value left by a variable
3634 // shifting in zeros, and writes the result to the destination register. The
3636 // of bits is read from the bottom byte of a register. It can optionally update
3638 // flags based on the result.
3639 bool EmulateInstructionARM::EmulateLSLReg(const uint32_t opcode,
3640 const ARMEncoding encoding) {
3642 // ARM pseudo code...
3643 if ConditionPassed() then
3644 EncodingSpecificOperations();
3645 shift_n = UInt(R[m]<7:0>);
3646 (result, carry) = Shift_C(R[m], SRType_LSL, shift_n, APSR.C);
3649 APSR.N = result<31>;
3650 APSR.Z = IsZeroBit(result);
3655 return EmulateShiftReg(opcode, encoding, SRType_LSL);
3658 // Logical Shift Right (immediate) shifts a register value right by an immediate
3660 // shifting in zeros, and writes the result to the destination register. It can
3662 // update the condition flags based on the result.
3663 bool EmulateInstructionARM::EmulateLSRImm(const uint32_t opcode,
3664 const ARMEncoding encoding) {
3666 // ARM pseudo code...
3667 if ConditionPassed() then
3668 EncodingSpecificOperations();
3669 (result, carry) = Shift_C(R[m], SRType_LSR, shift_n, APSR.C);
3670 if d == 15 then // Can only occur for ARM encoding
3671 ALUWritePC(result); // setflags is always FALSE here
3675 APSR.N = result<31>;
3676 APSR.Z = IsZeroBit(result);
3681 return EmulateShiftImm(opcode, encoding, SRType_LSR);
3684 // Logical Shift Right (register) shifts a register value right by a variable
3686 // shifting in zeros, and writes the result to the destination register. The
3688 // of bits is read from the bottom byte of a register. It can optionally update
3690 // flags based on the result.
3691 bool EmulateInstructionARM::EmulateLSRReg(const uint32_t opcode,
3692 const ARMEncoding encoding) {
3694 // ARM pseudo code...
3695 if ConditionPassed() then
3696 EncodingSpecificOperations();
3697 shift_n = UInt(R[m]<7:0>);
3698 (result, carry) = Shift_C(R[m], SRType_LSR, shift_n, APSR.C);
3701 APSR.N = result<31>;
3702 APSR.Z = IsZeroBit(result);
3707 return EmulateShiftReg(opcode, encoding, SRType_LSR);
3710 // Rotate Right (immediate) provides the value of the contents of a register
3711 // rotated by a constant value.
3712 // The bits that are rotated off the right end are inserted into the vacated bit
3713 // positions on the left.
3714 // It can optionally update the condition flags based on the result.
3715 bool EmulateInstructionARM::EmulateRORImm(const uint32_t opcode,
3716 const ARMEncoding encoding) {
3718 // ARM pseudo code...
3719 if ConditionPassed() then
3720 EncodingSpecificOperations();
3721 (result, carry) = Shift_C(R[m], SRType_ROR, shift_n, APSR.C);
3722 if d == 15 then // Can only occur for ARM encoding
3723 ALUWritePC(result); // setflags is always FALSE here
3727 APSR.N = result<31>;
3728 APSR.Z = IsZeroBit(result);
3733 return EmulateShiftImm(opcode, encoding, SRType_ROR);
3736 // Rotate Right (register) provides the value of the contents of a register
3737 // rotated by a variable number of bits.
3738 // The bits that are rotated off the right end are inserted into the vacated bit
3739 // positions on the left.
3740 // The variable number of bits is read from the bottom byte of a register. It
3741 // can optionally update the condition
3742 // flags based on the result.
3743 bool EmulateInstructionARM::EmulateRORReg(const uint32_t opcode,
3744 const ARMEncoding encoding) {
3746 // ARM pseudo code...
3747 if ConditionPassed() then
3748 EncodingSpecificOperations();
3749 shift_n = UInt(R[m]<7:0>);
3750 (result, carry) = Shift_C(R[m], SRType_ROR, shift_n, APSR.C);
3753 APSR.N = result<31>;
3754 APSR.Z = IsZeroBit(result);
3759 return EmulateShiftReg(opcode, encoding, SRType_ROR);
3762 // Rotate Right with Extend provides the value of the contents of a register
3763 // shifted right by one place,
3764 // with the carry flag shifted into bit [31].
3766 // RRX can optionally update the condition flags based on the result.
3767 // In that case, bit [0] is shifted into the carry flag.
3768 bool EmulateInstructionARM::EmulateRRX(const uint32_t opcode,
3769 const ARMEncoding encoding) {
3771 // ARM pseudo code...
3772 if ConditionPassed() then
3773 EncodingSpecificOperations();
3774 (result, carry) = Shift_C(R[m], SRType_RRX, 1, APSR.C);
3775 if d == 15 then // Can only occur for ARM encoding
3776 ALUWritePC(result); // setflags is always FALSE here
3780 APSR.N = result<31>;
3781 APSR.Z = IsZeroBit(result);
3786 return EmulateShiftImm(opcode, encoding, SRType_RRX);
3789 bool EmulateInstructionARM::EmulateShiftImm(const uint32_t opcode,
3790 const ARMEncoding encoding,
3791 ARM_ShifterType shift_type) {
3792 // assert(shift_type == SRType_ASR
3793 // || shift_type == SRType_LSL
3794 // || shift_type == SRType_LSR
3795 // || shift_type == SRType_ROR
3796 // || shift_type == SRType_RRX);
3798 bool success = false;
3800 if (ConditionPassed(opcode)) {
3801 uint32_t Rd; // the destination register
3802 uint32_t Rm; // the first operand register
3803 uint32_t imm5; // encoding for the shift amount
3804 uint32_t carry; // the carry bit after the shift operation
3807 // Special case handling!
3808 // A8.6.139 ROR (immediate) -- Encoding T1
3809 ARMEncoding use_encoding = encoding;
3810 if (shift_type == SRType_ROR && use_encoding == eEncodingT1) {
3811 // Morph the T1 encoding from the ARM Architecture Manual into T2 encoding
3813 // have the same decoding of bit fields as the other Thumb2 shift
3815 use_encoding = eEncodingT2;
3818 switch (use_encoding) {
3820 // Due to the above special case handling!
3821 if (shift_type == SRType_ROR)
3824 Rd = Bits32(opcode, 2, 0);
3825 Rm = Bits32(opcode, 5, 3);
3826 setflags = !InITBlock();
3827 imm5 = Bits32(opcode, 10, 6);
3831 // There's no imm form of RRX instructions.
3832 if (shift_type == SRType_RRX)
3835 Rd = Bits32(opcode, 11, 8);
3836 Rm = Bits32(opcode, 3, 0);
3837 setflags = BitIsSet(opcode, 20);
3838 imm5 = Bits32(opcode, 14, 12) << 2 | Bits32(opcode, 7, 6);
3839 if (BadReg(Rd) || BadReg(Rm))
3843 Rd = Bits32(opcode, 15, 12);
3844 Rm = Bits32(opcode, 3, 0);
3845 setflags = BitIsSet(opcode, 20);
3846 imm5 = Bits32(opcode, 11, 7);
3852 // A8.6.139 ROR (immediate)
3853 if (shift_type == SRType_ROR && imm5 == 0)
3854 shift_type = SRType_RRX;
3856 // Get the first operand.
3857 uint32_t value = ReadCoreReg(Rm, &success);
3861 // Decode the shift amount if not RRX.
3863 (shift_type == SRType_RRX ? 1 : DecodeImmShift(shift_type, imm5));
3865 uint32_t result = Shift_C(value, shift_type, amt, APSR_C, carry, &success);
3869 // The context specifies that an immediate is to be moved into Rd.
3870 EmulateInstruction::Context context;
3871 context.type = EmulateInstruction::eContextImmediate;
3872 context.SetNoArgs();
3874 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
3880 bool EmulateInstructionARM::EmulateShiftReg(const uint32_t opcode,
3881 const ARMEncoding encoding,
3882 ARM_ShifterType shift_type) {
3883 // assert(shift_type == SRType_ASR
3884 // || shift_type == SRType_LSL
3885 // || shift_type == SRType_LSR
3886 // || shift_type == SRType_ROR);
3888 bool success = false;
3890 if (ConditionPassed(opcode)) {
3891 uint32_t Rd; // the destination register
3892 uint32_t Rn; // the first operand register
3894 Rm; // the register whose bottom byte contains the amount to shift by
3895 uint32_t carry; // the carry bit after the shift operation
3899 Rd = Bits32(opcode, 2, 0);
3901 Rm = Bits32(opcode, 5, 3);
3902 setflags = !InITBlock();
3905 Rd = Bits32(opcode, 11, 8);
3906 Rn = Bits32(opcode, 19, 16);
3907 Rm = Bits32(opcode, 3, 0);
3908 setflags = BitIsSet(opcode, 20);
3909 if (BadReg(Rd) || BadReg(Rn) || BadReg(Rm))
3913 Rd = Bits32(opcode, 15, 12);
3914 Rn = Bits32(opcode, 3, 0);
3915 Rm = Bits32(opcode, 11, 8);
3916 setflags = BitIsSet(opcode, 20);
3917 if (Rd == 15 || Rn == 15 || Rm == 15)
3924 // Get the first operand.
3925 uint32_t value = ReadCoreReg(Rn, &success);
3928 // Get the Rm register content.
3929 uint32_t val = ReadCoreReg(Rm, &success);
3933 // Get the shift amount.
3934 uint32_t amt = Bits32(val, 7, 0);
3936 uint32_t result = Shift_C(value, shift_type, amt, APSR_C, carry, &success);
3940 // The context specifies that an immediate is to be moved into Rd.
3941 EmulateInstruction::Context context;
3942 context.type = EmulateInstruction::eContextImmediate;
3943 context.SetNoArgs();
3945 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
3951 // LDM loads multiple registers from consecutive memory locations, using an
3952 // address from a base register. Optionally the address just above the highest
3953 // of those locations
3954 // can be written back to the base register.
3955 bool EmulateInstructionARM::EmulateLDM(const uint32_t opcode,
3956 const ARMEncoding encoding) {
3958 // ARM pseudo code...
3959 if ConditionPassed()
3960 EncodingSpecificOperations(); NullCheckIfThumbEE (n);
3964 if registers<i> == '1' then
3965 R[i] = MemA[address, 4]; address = address + 4;
3966 if registers<15> == '1' then
3967 LoadWritePC (MemA[address, 4]);
3969 if wback && registers<n> == '0' then R[n] = R[n] + 4 * BitCount (registers);
3970 if wback && registers<n> == '1' then R[n] = bits(32) UNKNOWN; // Only possible for encoding A1
3974 bool success = false;
3975 if (ConditionPassed(opcode)) {
3977 uint32_t registers = 0;
3979 const uint32_t addr_byte_size = GetAddressByteSize();
3982 // n = UInt(Rn); registers = '00000000':register_list; wback =
3983 // (registers<n> == '0');
3984 n = Bits32(opcode, 10, 8);
3985 registers = Bits32(opcode, 7, 0);
3986 registers = registers & 0x00ff; // Make sure the top 8 bits are zeros.
3987 wback = BitIsClear(registers, n);
3988 // if BitCount(registers) < 1 then UNPREDICTABLE;
3989 if (BitCount(registers) < 1)
3993 // if W == '1' && Rn == '1101' then SEE POP;
3994 // n = UInt(Rn); registers = P:M:'0':register_list; wback = (W == '1');
3995 n = Bits32(opcode, 19, 16);
3996 registers = Bits32(opcode, 15, 0);
3997 registers = registers & 0xdfff; // Make sure bit 13 is zero.
3998 wback = BitIsSet(opcode, 21);
4000 // if n == 15 || BitCount(registers) < 2 || (P == '1' && M == '1') then
4002 if ((n == 15) || (BitCount(registers) < 2) ||
4003 (BitIsSet(opcode, 14) && BitIsSet(opcode, 15)))
4006 // if registers<15> == '1' && InITBlock() && !LastInITBlock() then
4008 if (BitIsSet(registers, 15) && InITBlock() && !LastInITBlock())
4011 // if wback && registers<n> == '1' then UNPREDICTABLE;
4012 if (wback && BitIsSet(registers, n))
4017 n = Bits32(opcode, 19, 16);
4018 registers = Bits32(opcode, 15, 0);
4019 wback = BitIsSet(opcode, 21);
4020 if ((n == 15) || (BitCount(registers) < 1))
4028 const addr_t base_address =
4029 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
4033 EmulateInstruction::Context context;
4034 context.type = EmulateInstruction::eContextRegisterPlusOffset;
4035 RegisterInfo dwarf_reg;
4036 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n, dwarf_reg);
4037 context.SetRegisterPlusOffset(dwarf_reg, offset);
4039 for (int i = 0; i < 14; ++i) {
4040 if (BitIsSet(registers, i)) {
4041 context.type = EmulateInstruction::eContextRegisterPlusOffset;
4042 context.SetRegisterPlusOffset(dwarf_reg, offset);
4043 if (wback && (n == 13)) // Pop Instruction
4045 context.type = EmulateInstruction::eContextPopRegisterOffStack;
4046 context.SetAddress(base_address + offset);
4049 // R[i] = MemA [address, 4]; address = address + 4;
4050 uint32_t data = MemARead(context, base_address + offset, addr_byte_size,
4055 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + i,
4059 offset += addr_byte_size;
4063 if (BitIsSet(registers, 15)) {
4064 // LoadWritePC (MemA [address, 4]);
4065 context.type = EmulateInstruction::eContextRegisterPlusOffset;
4066 context.SetRegisterPlusOffset(dwarf_reg, offset);
4068 MemARead(context, base_address + offset, addr_byte_size, 0, &success);
4071 // In ARMv5T and above, this is an interworking branch.
4072 if (!LoadWritePC(context, data))
4076 if (wback && BitIsClear(registers, n)) {
4077 // R[n] = R[n] + 4 * BitCount (registers)
4078 int32_t offset = addr_byte_size * BitCount(registers);
4079 context.type = EmulateInstruction::eContextAdjustBaseRegister;
4080 context.SetRegisterPlusOffset(dwarf_reg, offset);
4082 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n,
4083 base_address + offset))
4086 if (wback && BitIsSet(registers, n))
4087 // R[n] bits(32) UNKNOWN;
4088 return WriteBits32Unknown(n);
4093 // LDMDA loads multiple registers from consecutive memory locations using an
4094 // address from a base register.
4095 // The consecutive memory locations end at this address and the address just
4096 // below the lowest of those locations
4097 // can optionally be written back to the base register.
4098 bool EmulateInstructionARM::EmulateLDMDA(const uint32_t opcode,
4099 const ARMEncoding encoding) {
4101 // ARM pseudo code...
4102 if ConditionPassed() then
4103 EncodingSpecificOperations();
4104 address = R[n] - 4*BitCount(registers) + 4;
4107 if registers<i> == '1' then
4108 R[i] = MemA[address,4]; address = address + 4;
4110 if registers<15> == '1' then
4111 LoadWritePC(MemA[address,4]);
4113 if wback && registers<n> == '0' then R[n] = R[n] - 4*BitCount(registers);
4114 if wback && registers<n> == '1' then R[n] = bits(32) UNKNOWN;
4117 bool success = false;
4119 if (ConditionPassed(opcode)) {
4121 uint32_t registers = 0;
4123 const uint32_t addr_byte_size = GetAddressByteSize();
4125 // EncodingSpecificOperations();
4128 // n = UInt(Rn); registers = register_list; wback = (W == '1');
4129 n = Bits32(opcode, 19, 16);
4130 registers = Bits32(opcode, 15, 0);
4131 wback = BitIsSet(opcode, 21);
4133 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
4134 if ((n == 15) || (BitCount(registers) < 1))
4142 // address = R[n] - 4*BitCount(registers) + 4;
4145 addr_t Rn = ReadCoreReg(n, &success);
4151 Rn - (addr_byte_size * BitCount(registers)) + addr_byte_size;
4153 EmulateInstruction::Context context;
4154 context.type = EmulateInstruction::eContextRegisterPlusOffset;
4155 RegisterInfo dwarf_reg;
4156 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n, dwarf_reg);
4157 context.SetRegisterPlusOffset(dwarf_reg, offset);
4160 for (int i = 0; i < 14; ++i) {
4161 // if registers<i> == '1' then
4162 if (BitIsSet(registers, i)) {
4163 // R[i] = MemA[address,4]; address = address + 4;
4164 context.SetRegisterPlusOffset(dwarf_reg, Rn - (address + offset));
4166 MemARead(context, address + offset, addr_byte_size, 0, &success);
4169 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + i,
4172 offset += addr_byte_size;
4176 // if registers<15> == '1' then
4177 // LoadWritePC(MemA[address,4]);
4178 if (BitIsSet(registers, 15)) {
4179 context.SetRegisterPlusOffset(dwarf_reg, offset);
4181 MemARead(context, address + offset, addr_byte_size, 0, &success);
4184 // In ARMv5T and above, this is an interworking branch.
4185 if (!LoadWritePC(context, data))
4189 // if wback && registers<n> == '0' then R[n] = R[n] - 4*BitCount(registers);
4190 if (wback && BitIsClear(registers, n)) {
4194 offset = (addr_byte_size * BitCount(registers)) * -1;
4195 context.type = EmulateInstruction::eContextAdjustBaseRegister;
4196 context.SetImmediateSigned(offset);
4197 addr_t addr = Rn + offset;
4198 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n,
4203 // if wback && registers<n> == '1' then R[n] = bits(32) UNKNOWN;
4204 if (wback && BitIsSet(registers, n))
4205 return WriteBits32Unknown(n);
4210 // LDMDB loads multiple registers from consecutive memory locations using an
4211 // address from a base register. The
4212 // consecutive memory locations end just below this address, and the address of
4213 // the lowest of those locations can
4214 // be optionally written back to the base register.
4215 bool EmulateInstructionARM::EmulateLDMDB(const uint32_t opcode,
4216 const ARMEncoding encoding) {
4218 // ARM pseudo code...
4219 if ConditionPassed() then
4220 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
4221 address = R[n] - 4*BitCount(registers);
4224 if registers<i> == '1' then
4225 R[i] = MemA[address,4]; address = address + 4;
4226 if registers<15> == '1' then
4227 LoadWritePC(MemA[address,4]);
4229 if wback && registers<n> == '0' then R[n] = R[n] - 4*BitCount(registers);
4230 if wback && registers<n> == '1' then R[n] = bits(32) UNKNOWN; // Only possible for encoding A1
4233 bool success = false;
4235 if (ConditionPassed(opcode)) {
4237 uint32_t registers = 0;
4239 const uint32_t addr_byte_size = GetAddressByteSize();
4242 // n = UInt(Rn); registers = P:M:'0':register_list; wback = (W == '1');
4243 n = Bits32(opcode, 19, 16);
4244 registers = Bits32(opcode, 15, 0);
4245 registers = registers & 0xdfff; // Make sure bit 13 is a zero.
4246 wback = BitIsSet(opcode, 21);
4248 // if n == 15 || BitCount(registers) < 2 || (P == '1' && M == '1') then
4250 if ((n == 15) || (BitCount(registers) < 2) ||
4251 (BitIsSet(opcode, 14) && BitIsSet(opcode, 15)))
4254 // if registers<15> == '1' && InITBlock() && !LastInITBlock() then
4256 if (BitIsSet(registers, 15) && InITBlock() && !LastInITBlock())
4259 // if wback && registers<n> == '1' then UNPREDICTABLE;
4260 if (wback && BitIsSet(registers, n))
4266 // n = UInt(Rn); registers = register_list; wback = (W == '1');
4267 n = Bits32(opcode, 19, 16);
4268 registers = Bits32(opcode, 15, 0);
4269 wback = BitIsSet(opcode, 21);
4271 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
4272 if ((n == 15) || (BitCount(registers) < 1))
4281 // address = R[n] - 4*BitCount(registers);
4285 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
4290 addr_t address = Rn - (addr_byte_size * BitCount(registers));
4291 EmulateInstruction::Context context;
4292 context.type = EmulateInstruction::eContextRegisterPlusOffset;
4293 RegisterInfo dwarf_reg;
4294 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n, dwarf_reg);
4295 context.SetRegisterPlusOffset(dwarf_reg, Rn - address);
4297 for (int i = 0; i < 14; ++i) {
4298 if (BitIsSet(registers, i)) {
4299 // R[i] = MemA[address,4]; address = address + 4;
4300 context.SetRegisterPlusOffset(dwarf_reg, Rn - (address + offset));
4302 MemARead(context, address + offset, addr_byte_size, 0, &success);
4306 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + i,
4310 offset += addr_byte_size;
4314 // if registers<15> == '1' then
4315 // LoadWritePC(MemA[address,4]);
4316 if (BitIsSet(registers, 15)) {
4317 context.SetRegisterPlusOffset(dwarf_reg, offset);
4319 MemARead(context, address + offset, addr_byte_size, 0, &success);
4322 // In ARMv5T and above, this is an interworking branch.
4323 if (!LoadWritePC(context, data))
4327 // if wback && registers<n> == '0' then R[n] = R[n] - 4*BitCount(registers);
4328 if (wback && BitIsClear(registers, n)) {
4332 offset = (addr_byte_size * BitCount(registers)) * -1;
4333 context.type = EmulateInstruction::eContextAdjustBaseRegister;
4334 context.SetImmediateSigned(offset);
4335 addr_t addr = Rn + offset;
4336 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n,
4341 // if wback && registers<n> == '1' then R[n] = bits(32) UNKNOWN; // Only
4342 // possible for encoding A1
4343 if (wback && BitIsSet(registers, n))
4344 return WriteBits32Unknown(n);
4349 // LDMIB loads multiple registers from consecutive memory locations using an
4350 // address from a base register. The
4351 // consecutive memory locations start just above this address, and thea ddress
4352 // of the last of those locations can
4353 // optinoally be written back to the base register.
4354 bool EmulateInstructionARM::EmulateLDMIB(const uint32_t opcode,
4355 const ARMEncoding encoding) {
4357 if ConditionPassed() then
4358 EncodingSpecificOperations();
4362 if registers<i> == '1' then
4363 R[i] = MemA[address,4]; address = address + 4;
4364 if registers<15> == '1' then
4365 LoadWritePC(MemA[address,4]);
4367 if wback && registers<n> == '0' then R[n] = R[n] + 4*BitCount(registers);
4368 if wback && registers<n> == '1' then R[n] = bits(32) UNKNOWN;
4371 bool success = false;
4373 if (ConditionPassed(opcode)) {
4375 uint32_t registers = 0;
4377 const uint32_t addr_byte_size = GetAddressByteSize();
4380 // n = UInt(Rn); registers = register_list; wback = (W == '1');
4381 n = Bits32(opcode, 19, 16);
4382 registers = Bits32(opcode, 15, 0);
4383 wback = BitIsSet(opcode, 21);
4385 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
4386 if ((n == 15) || (BitCount(registers) < 1))
4393 // address = R[n] + 4;
4397 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
4402 addr_t address = Rn + addr_byte_size;
4404 EmulateInstruction::Context context;
4405 context.type = EmulateInstruction::eContextRegisterPlusOffset;
4406 RegisterInfo dwarf_reg;
4407 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n, dwarf_reg);
4408 context.SetRegisterPlusOffset(dwarf_reg, offset);
4410 for (int i = 0; i < 14; ++i) {
4411 if (BitIsSet(registers, i)) {
4412 // R[i] = MemA[address,4]; address = address + 4;
4414 context.SetRegisterPlusOffset(dwarf_reg, offset + addr_byte_size);
4416 MemARead(context, address + offset, addr_byte_size, 0, &success);
4420 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + i,
4424 offset += addr_byte_size;
4428 // if registers<15> == '1' then
4429 // LoadWritePC(MemA[address,4]);
4430 if (BitIsSet(registers, 15)) {
4431 context.SetRegisterPlusOffset(dwarf_reg, offset);
4433 MemARead(context, address + offset, addr_byte_size, 0, &success);
4436 // In ARMv5T and above, this is an interworking branch.
4437 if (!LoadWritePC(context, data))
4441 // if wback && registers<n> == '0' then R[n] = R[n] + 4*BitCount(registers);
4442 if (wback && BitIsClear(registers, n)) {
4446 offset = addr_byte_size * BitCount(registers);
4447 context.type = EmulateInstruction::eContextAdjustBaseRegister;
4448 context.SetImmediateSigned(offset);
4449 addr_t addr = Rn + offset;
4450 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n,
4455 // if wback && registers<n> == '1' then R[n] = bits(32) UNKNOWN; // Only
4456 // possible for encoding A1
4457 if (wback && BitIsSet(registers, n))
4458 return WriteBits32Unknown(n);
4463 // Load Register (immediate) calculates an address from a base register value
4465 // an immediate offset, loads a word from memory, and writes to a register.
4466 // LDR (immediate, Thumb)
4467 bool EmulateInstructionARM::EmulateLDRRtRnImm(const uint32_t opcode,
4468 const ARMEncoding encoding) {
4470 // ARM pseudo code...
4471 if (ConditionPassed())
4473 EncodingSpecificOperations(); NullCheckIfThumbEE(15);
4474 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
4475 address = if index then offset_addr else R[n];
4476 data = MemU[address,4];
4477 if wback then R[n] = offset_addr;
4479 if address<1:0> == '00' then LoadWritePC(data); else UNPREDICTABLE;
4480 elsif UnalignedSupport() || address<1:0> = '00' then
4482 else R[t] = bits(32) UNKNOWN; // Can only apply before ARMv7
4486 bool success = false;
4488 if (ConditionPassed(opcode)) {
4489 uint32_t Rt; // the destination register
4490 uint32_t Rn; // the base register
4491 uint32_t imm32; // the immediate offset used to form the address
4492 addr_t offset_addr; // the offset address
4493 addr_t address; // the calculated address
4494 uint32_t data; // the literal data value from memory load
4495 bool add, index, wback;
4498 Rt = Bits32(opcode, 2, 0);
4499 Rn = Bits32(opcode, 5, 3);
4500 imm32 = Bits32(opcode, 10, 6) << 2; // imm32 = ZeroExtend(imm5:'00', 32);
4501 // index = TRUE; add = TRUE; wback = FALSE
4509 // t = UInt(Rt); n = 13; imm32 = ZeroExtend(imm8:'00', 32);
4510 Rt = Bits32(opcode, 10, 8);
4512 imm32 = Bits32(opcode, 7, 0) << 2;
4514 // index = TRUE; add = TRUE; wback = FALSE;
4522 // if Rn == '1111' then SEE LDR (literal);
4523 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
4524 Rt = Bits32(opcode, 15, 12);
4525 Rn = Bits32(opcode, 19, 16);
4526 imm32 = Bits32(opcode, 11, 0);
4528 // index = TRUE; add = TRUE; wback = FALSE;
4533 // if t == 15 && InITBlock() && !LastInITBlock() then UNPREDICTABLE;
4534 if ((Rt == 15) && InITBlock() && !LastInITBlock())
4540 // if Rn == '1111' then SEE LDR (literal);
4541 // if P == '1' && U == '1' && W == '0' then SEE LDRT;
4542 // if Rn == '1101' && P == '0' && U == '1' && W == '1' && imm8 ==
4543 // '00000100' then SEE POP;
4544 // if P == '0' && W == '0' then UNDEFINED;
4545 if (BitIsClear(opcode, 10) && BitIsClear(opcode, 8))
4548 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32);
4549 Rt = Bits32(opcode, 15, 12);
4550 Rn = Bits32(opcode, 19, 16);
4551 imm32 = Bits32(opcode, 7, 0);
4553 // index = (P == '1'); add = (U == '1'); wback = (W == '1');
4554 index = BitIsSet(opcode, 10);
4555 add = BitIsSet(opcode, 9);
4556 wback = BitIsSet(opcode, 8);
4558 // if (wback && n == t) || (t == 15 && InITBlock() && !LastInITBlock())
4559 // then UNPREDICTABLE;
4560 if ((wback && (Rn == Rt)) ||
4561 ((Rt == 15) && InITBlock() && !LastInITBlock()))
4569 uint32_t base = ReadCoreReg(Rn, &success);
4573 offset_addr = base + imm32;
4575 offset_addr = base - imm32;
4577 address = (index ? offset_addr : base);
4579 RegisterInfo base_reg;
4580 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + Rn, base_reg);
4582 EmulateInstruction::Context ctx;
4584 ctx.type = eContextAdjustStackPointer;
4585 ctx.SetImmediateSigned((int32_t)(offset_addr - base));
4586 } else if (Rn == GetFramePointerRegisterNumber()) {
4587 ctx.type = eContextSetFramePointer;
4588 ctx.SetRegisterPlusOffset(base_reg, (int32_t)(offset_addr - base));
4590 ctx.type = EmulateInstruction::eContextAdjustBaseRegister;
4591 ctx.SetRegisterPlusOffset(base_reg, (int32_t)(offset_addr - base));
4594 if (!WriteRegisterUnsigned(ctx, eRegisterKindDWARF, dwarf_r0 + Rn,
4599 // Prepare to write to the Rt register.
4600 EmulateInstruction::Context context;
4601 context.type = EmulateInstruction::eContextRegisterLoad;
4602 context.SetRegisterPlusOffset(base_reg, (int32_t)(offset_addr - base));
4604 // Read memory from the address.
4605 data = MemURead(context, address, 4, 0, &success);
4610 if (Bits32(address, 1, 0) == 0) {
4611 if (!LoadWritePC(context, data))
4615 } else if (UnalignedSupport() || Bits32(address, 1, 0) == 0) {
4616 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + Rt,
4620 WriteBits32Unknown(Rt);
4625 // STM (Store Multiple Increment After) stores multiple registers to consecutive
4626 // memory locations using an address
4627 // from a base register. The consecutive memory locations start at this
4628 // address, and the address just above the last
4629 // of those locations can optionally be written back to the base register.
4630 bool EmulateInstructionARM::EmulateSTM(const uint32_t opcode,
4631 const ARMEncoding encoding) {
4633 if ConditionPassed() then
4634 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
4638 if registers<i> == '1' then
4639 if i == n && wback && i != LowestSetBit(registers) then
4640 MemA[address,4] = bits(32) UNKNOWN; // Only possible for encodings T1 and A1
4642 MemA[address,4] = R[i];
4643 address = address + 4;
4645 if registers<15> == '1' then // Only possible for encoding A1
4646 MemA[address,4] = PCStoreValue();
4647 if wback then R[n] = R[n] + 4*BitCount(registers);
4650 bool success = false;
4652 if (ConditionPassed(opcode)) {
4654 uint32_t registers = 0;
4656 const uint32_t addr_byte_size = GetAddressByteSize();
4658 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
4661 // n = UInt(Rn); registers = '00000000':register_list; wback = TRUE;
4662 n = Bits32(opcode, 10, 8);
4663 registers = Bits32(opcode, 7, 0);
4664 registers = registers & 0x00ff; // Make sure the top 8 bits are zeros.
4667 // if BitCount(registers) < 1 then UNPREDICTABLE;
4668 if (BitCount(registers) < 1)
4674 // n = UInt(Rn); registers = '0':M:'0':register_list; wback = (W == '1');
4675 n = Bits32(opcode, 19, 16);
4676 registers = Bits32(opcode, 15, 0);
4677 registers = registers & 0x5fff; // Make sure bits 15 & 13 are zeros.
4678 wback = BitIsSet(opcode, 21);
4680 // if n == 15 || BitCount(registers) < 2 then UNPREDICTABLE;
4681 if ((n == 15) || (BitCount(registers) < 2))
4684 // if wback && registers<n> == '1' then UNPREDICTABLE;
4685 if (wback && BitIsSet(registers, n))
4691 // n = UInt(Rn); registers = register_list; wback = (W == '1');
4692 n = Bits32(opcode, 19, 16);
4693 registers = Bits32(opcode, 15, 0);
4694 wback = BitIsSet(opcode, 21);
4696 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
4697 if ((n == 15) || (BitCount(registers) < 1))
4708 const addr_t address =
4709 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
4713 EmulateInstruction::Context context;
4714 context.type = EmulateInstruction::eContextRegisterStore;
4715 RegisterInfo base_reg;
4716 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n, base_reg);
4719 uint32_t lowest_set_bit = 14;
4720 for (uint32_t i = 0; i < 14; ++i) {
4721 // if registers<i> == '1' then
4722 if (BitIsSet(registers, i)) {
4723 if (i < lowest_set_bit)
4725 // if i == n && wback && i != LowestSetBit(registers) then
4726 if ((i == n) && wback && (i != lowest_set_bit))
4727 // MemA[address,4] = bits(32) UNKNOWN; // Only possible for encodings
4729 WriteBits32UnknownToMemory(address + offset);
4731 // MemA[address,4] = R[i];
4732 uint32_t data = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + i,
4737 RegisterInfo data_reg;
4738 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + i, data_reg);
4739 context.SetRegisterToRegisterPlusOffset(data_reg, base_reg, offset);
4740 if (!MemAWrite(context, address + offset, data, addr_byte_size))
4744 // address = address + 4;
4745 offset += addr_byte_size;
4749 // if registers<15> == '1' then // Only possible for encoding A1
4750 // MemA[address,4] = PCStoreValue();
4751 if (BitIsSet(registers, 15)) {
4752 RegisterInfo pc_reg;
4753 GetRegisterInfo(eRegisterKindDWARF, dwarf_pc, pc_reg);
4754 context.SetRegisterPlusOffset(pc_reg, 8);
4755 const uint32_t pc = ReadCoreReg(PC_REG, &success);
4759 if (!MemAWrite(context, address + offset, pc, addr_byte_size))
4763 // if wback then R[n] = R[n] + 4*BitCount(registers);
4765 offset = addr_byte_size * BitCount(registers);
4766 context.type = EmulateInstruction::eContextAdjustBaseRegister;
4767 context.SetImmediateSigned(offset);
4768 addr_t data = address + offset;
4769 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n,
4777 // STMDA (Store Multiple Decrement After) stores multiple registers to
4778 // consecutive memory locations using an address
4779 // from a base register. The consecutive memory locations end at this address,
4780 // and the address just below the lowest
4781 // of those locations can optionally be written back to the base register.
4782 bool EmulateInstructionARM::EmulateSTMDA(const uint32_t opcode,
4783 const ARMEncoding encoding) {
4785 if ConditionPassed() then
4786 EncodingSpecificOperations();
4787 address = R[n] - 4*BitCount(registers) + 4;
4790 if registers<i> == '1' then
4791 if i == n && wback && i != LowestSetBit(registers) then
4792 MemA[address,4] = bits(32) UNKNOWN;
4794 MemA[address,4] = R[i];
4795 address = address + 4;
4797 if registers<15> == '1' then
4798 MemA[address,4] = PCStoreValue();
4800 if wback then R[n] = R[n] - 4*BitCount(registers);
4803 bool success = false;
4805 if (ConditionPassed(opcode)) {
4807 uint32_t registers = 0;
4809 const uint32_t addr_byte_size = GetAddressByteSize();
4811 // EncodingSpecificOperations();
4814 // n = UInt(Rn); registers = register_list; wback = (W == '1');
4815 n = Bits32(opcode, 19, 16);
4816 registers = Bits32(opcode, 15, 0);
4817 wback = BitIsSet(opcode, 21);
4819 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
4820 if ((n == 15) || (BitCount(registers) < 1))
4827 // address = R[n] - 4*BitCount(registers) + 4;
4829 addr_t Rn = ReadCoreReg(n, &success);
4833 addr_t address = Rn - (addr_byte_size * BitCount(registers)) + 4;
4835 EmulateInstruction::Context context;
4836 context.type = EmulateInstruction::eContextRegisterStore;
4837 RegisterInfo base_reg;
4838 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n, base_reg);
4841 uint32_t lowest_bit_set = 14;
4842 for (uint32_t i = 0; i < 14; ++i) {
4843 // if registers<i> == '1' then
4844 if (BitIsSet(registers, i)) {
4845 if (i < lowest_bit_set)
4847 // if i == n && wback && i != LowestSetBit(registers) then
4848 if ((i == n) && wback && (i != lowest_bit_set))
4849 // MemA[address,4] = bits(32) UNKNOWN;
4850 WriteBits32UnknownToMemory(address + offset);
4852 // MemA[address,4] = R[i];
4853 uint32_t data = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + i,
4858 RegisterInfo data_reg;
4859 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + i, data_reg);
4860 context.SetRegisterToRegisterPlusOffset(data_reg, base_reg,
4861 Rn - (address + offset));
4862 if (!MemAWrite(context, address + offset, data, addr_byte_size))
4866 // address = address + 4;
4867 offset += addr_byte_size;
4871 // if registers<15> == '1' then
4872 // MemA[address,4] = PCStoreValue();
4873 if (BitIsSet(registers, 15)) {
4874 RegisterInfo pc_reg;
4875 GetRegisterInfo(eRegisterKindDWARF, dwarf_pc, pc_reg);
4876 context.SetRegisterPlusOffset(pc_reg, 8);
4877 const uint32_t pc = ReadCoreReg(PC_REG, &success);
4881 if (!MemAWrite(context, address + offset, pc, addr_byte_size))
4885 // if wback then R[n] = R[n] - 4*BitCount(registers);
4887 offset = (addr_byte_size * BitCount(registers)) * -1;
4888 context.type = EmulateInstruction::eContextAdjustBaseRegister;
4889 context.SetImmediateSigned(offset);
4890 addr_t data = Rn + offset;
4891 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n,
4899 // STMDB (Store Multiple Decrement Before) stores multiple registers to
4900 // consecutive memory locations using an address
4901 // from a base register. The consecutive memory locations end just below this
4902 // address, and the address of the first of
4903 // those locations can optionally be written back to the base register.
4904 bool EmulateInstructionARM::EmulateSTMDB(const uint32_t opcode,
4905 const ARMEncoding encoding) {
4907 if ConditionPassed() then
4908 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
4909 address = R[n] - 4*BitCount(registers);
4912 if registers<i> == '1' then
4913 if i == n && wback && i != LowestSetBit(registers) then
4914 MemA[address,4] = bits(32) UNKNOWN; // Only possible for encoding A1
4916 MemA[address,4] = R[i];
4917 address = address + 4;
4919 if registers<15> == '1' then // Only possible for encoding A1
4920 MemA[address,4] = PCStoreValue();
4922 if wback then R[n] = R[n] - 4*BitCount(registers);
4925 bool success = false;
4927 if (ConditionPassed(opcode)) {
4929 uint32_t registers = 0;
4931 const uint32_t addr_byte_size = GetAddressByteSize();
4933 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
4936 // if W == '1' && Rn == '1101' then SEE PUSH;
4937 if ((BitIsSet(opcode, 21)) && (Bits32(opcode, 19, 16) == 13)) {
4940 // n = UInt(Rn); registers = '0':M:'0':register_list; wback = (W == '1');
4941 n = Bits32(opcode, 19, 16);
4942 registers = Bits32(opcode, 15, 0);
4943 registers = registers & 0x5fff; // Make sure bits 15 & 13 are zeros.
4944 wback = BitIsSet(opcode, 21);
4945 // if n == 15 || BitCount(registers) < 2 then UNPREDICTABLE;
4946 if ((n == 15) || BitCount(registers) < 2)
4948 // if wback && registers<n> == '1' then UNPREDICTABLE;
4949 if (wback && BitIsSet(registers, n))
4954 // if W == '1' && Rn == '1101' && BitCount(register_list) >= 2 then SEE
4956 if (BitIsSet(opcode, 21) && (Bits32(opcode, 19, 16) == 13) &&
4957 BitCount(Bits32(opcode, 15, 0)) >= 2) {
4960 // n = UInt(Rn); registers = register_list; wback = (W == '1');
4961 n = Bits32(opcode, 19, 16);
4962 registers = Bits32(opcode, 15, 0);
4963 wback = BitIsSet(opcode, 21);
4964 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
4965 if ((n == 15) || BitCount(registers) < 1)
4973 // address = R[n] - 4*BitCount(registers);
4977 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
4981 addr_t address = Rn - (addr_byte_size * BitCount(registers));
4983 EmulateInstruction::Context context;
4984 context.type = EmulateInstruction::eContextRegisterStore;
4985 RegisterInfo base_reg;
4986 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n, base_reg);
4989 uint32_t lowest_set_bit = 14;
4990 for (uint32_t i = 0; i < 14; ++i) {
4991 // if registers<i> == '1' then
4992 if (BitIsSet(registers, i)) {
4993 if (i < lowest_set_bit)
4995 // if i == n && wback && i != LowestSetBit(registers) then
4996 if ((i == n) && wback && (i != lowest_set_bit))
4997 // MemA[address,4] = bits(32) UNKNOWN; // Only possible for encoding
4999 WriteBits32UnknownToMemory(address + offset);
5001 // MemA[address,4] = R[i];
5002 uint32_t data = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + i,
5007 RegisterInfo data_reg;
5008 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + i, data_reg);
5009 context.SetRegisterToRegisterPlusOffset(data_reg, base_reg,
5010 Rn - (address + offset));
5011 if (!MemAWrite(context, address + offset, data, addr_byte_size))
5015 // address = address + 4;
5016 offset += addr_byte_size;
5020 // if registers<15> == '1' then // Only possible for encoding A1
5021 // MemA[address,4] = PCStoreValue();
5022 if (BitIsSet(registers, 15)) {
5023 RegisterInfo pc_reg;
5024 GetRegisterInfo(eRegisterKindDWARF, dwarf_pc, pc_reg);
5025 context.SetRegisterPlusOffset(pc_reg, 8);
5026 const uint32_t pc = ReadCoreReg(PC_REG, &success);
5030 if (!MemAWrite(context, address + offset, pc, addr_byte_size))
5034 // if wback then R[n] = R[n] - 4*BitCount(registers);
5036 offset = (addr_byte_size * BitCount(registers)) * -1;
5037 context.type = EmulateInstruction::eContextAdjustBaseRegister;
5038 context.SetImmediateSigned(offset);
5039 addr_t data = Rn + offset;
5040 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n,
5048 // STMIB (Store Multiple Increment Before) stores multiple registers to
5049 // consecutive memory locations using an address
5050 // from a base register. The consecutive memory locations start just above this
5051 // address, and the address of the last
5052 // of those locations can optionally be written back to the base register.
5053 bool EmulateInstructionARM::EmulateSTMIB(const uint32_t opcode,
5054 const ARMEncoding encoding) {
5056 if ConditionPassed() then
5057 EncodingSpecificOperations();
5061 if registers<i> == '1' then
5062 if i == n && wback && i != LowestSetBit(registers) then
5063 MemA[address,4] = bits(32) UNKNOWN;
5065 MemA[address,4] = R[i];
5066 address = address + 4;
5068 if registers<15> == '1' then
5069 MemA[address,4] = PCStoreValue();
5071 if wback then R[n] = R[n] + 4*BitCount(registers);
5074 bool success = false;
5076 if (ConditionPassed(opcode)) {
5078 uint32_t registers = 0;
5080 const uint32_t addr_byte_size = GetAddressByteSize();
5082 // EncodingSpecificOperations();
5085 // n = UInt(Rn); registers = register_list; wback = (W == '1');
5086 n = Bits32(opcode, 19, 16);
5087 registers = Bits32(opcode, 15, 0);
5088 wback = BitIsSet(opcode, 21);
5090 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
5091 if ((n == 15) && (BitCount(registers) < 1))
5097 // address = R[n] + 4;
5100 addr_t Rn = ReadCoreReg(n, &success);
5104 addr_t address = Rn + addr_byte_size;
5106 EmulateInstruction::Context context;
5107 context.type = EmulateInstruction::eContextRegisterStore;
5108 RegisterInfo base_reg;
5109 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n, base_reg);
5111 uint32_t lowest_set_bit = 14;
5113 for (uint32_t i = 0; i < 14; ++i) {
5114 // if registers<i> == '1' then
5115 if (BitIsSet(registers, i)) {
5116 if (i < lowest_set_bit)
5118 // if i == n && wback && i != LowestSetBit(registers) then
5119 if ((i == n) && wback && (i != lowest_set_bit))
5120 // MemA[address,4] = bits(32) UNKNOWN;
5121 WriteBits32UnknownToMemory(address + offset);
5124 // MemA[address,4] = R[i];
5125 uint32_t data = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + i,
5130 RegisterInfo data_reg;
5131 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + i, data_reg);
5132 context.SetRegisterToRegisterPlusOffset(data_reg, base_reg,
5133 offset + addr_byte_size);
5134 if (!MemAWrite(context, address + offset, data, addr_byte_size))
5138 // address = address + 4;
5139 offset += addr_byte_size;
5143 // if registers<15> == '1' then
5144 // MemA[address,4] = PCStoreValue();
5145 if (BitIsSet(registers, 15)) {
5146 RegisterInfo pc_reg;
5147 GetRegisterInfo(eRegisterKindDWARF, dwarf_pc, pc_reg);
5148 context.SetRegisterPlusOffset(pc_reg, 8);
5149 const uint32_t pc = ReadCoreReg(PC_REG, &success);
5153 if (!MemAWrite(context, address + offset, pc, addr_byte_size))
5157 // if wback then R[n] = R[n] + 4*BitCount(registers);
5159 offset = addr_byte_size * BitCount(registers);
5160 context.type = EmulateInstruction::eContextAdjustBaseRegister;
5161 context.SetImmediateSigned(offset);
5162 addr_t data = Rn + offset;
5163 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n,
5171 // STR (store immediate) calculates an address from a base register value and an
5172 // immediate offset, and stores a word
5173 // from a register to memory. It can use offset, post-indexed, or pre-indexed
5175 bool EmulateInstructionARM::EmulateSTRThumb(const uint32_t opcode,
5176 const ARMEncoding encoding) {
5178 if ConditionPassed() then
5179 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
5180 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
5181 address = if index then offset_addr else R[n];
5182 if UnalignedSupport() || address<1:0> == '00' then
5183 MemU[address,4] = R[t];
5184 else // Can only occur before ARMv7
5185 MemU[address,4] = bits(32) UNKNOWN;
5186 if wback then R[n] = offset_addr;
5189 bool success = false;
5191 if (ConditionPassed(opcode)) {
5192 const uint32_t addr_byte_size = GetAddressByteSize();
5200 // EncodingSpecificOperations (); NullCheckIfThumbEE(n);
5203 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm5:'00', 32);
5204 t = Bits32(opcode, 2, 0);
5205 n = Bits32(opcode, 5, 3);
5206 imm32 = Bits32(opcode, 10, 6) << 2;
5208 // index = TRUE; add = TRUE; wback = FALSE;
5215 // t = UInt(Rt); n = 13; imm32 = ZeroExtend(imm8:'00', 32);
5216 t = Bits32(opcode, 10, 8);
5218 imm32 = Bits32(opcode, 7, 0) << 2;
5220 // index = TRUE; add = TRUE; wback = FALSE;
5227 // if Rn == '1111' then UNDEFINED;
5228 if (Bits32(opcode, 19, 16) == 15)
5231 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
5232 t = Bits32(opcode, 15, 12);
5233 n = Bits32(opcode, 19, 16);
5234 imm32 = Bits32(opcode, 11, 0);
5236 // index = TRUE; add = TRUE; wback = FALSE;
5241 // if t == 15 then UNPREDICTABLE;
5247 // if P == '1' && U == '1' && W == '0' then SEE STRT;
5248 // if Rn == '1101' && P == '1' && U == '0' && W == '1' && imm8 ==
5249 // '00000100' then SEE PUSH;
5250 // if Rn == '1111' || (P == '0' && W == '0') then UNDEFINED;
5251 if ((Bits32(opcode, 19, 16) == 15) ||
5252 (BitIsClear(opcode, 10) && BitIsClear(opcode, 8)))
5255 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32);
5256 t = Bits32(opcode, 15, 12);
5257 n = Bits32(opcode, 19, 16);
5258 imm32 = Bits32(opcode, 7, 0);
5260 // index = (P == '1'); add = (U == '1'); wback = (W == '1');
5261 index = BitIsSet(opcode, 10);
5262 add = BitIsSet(opcode, 9);
5263 wback = BitIsSet(opcode, 8);
5265 // if t == 15 || (wback && n == t) then UNPREDICTABLE;
5266 if ((t == 15) || (wback && (n == t)))
5277 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
5278 uint32_t base_address = ReadCoreReg(n, &success);
5283 offset_addr = base_address + imm32;
5285 offset_addr = base_address - imm32;
5287 // address = if index then offset_addr else R[n];
5289 address = offset_addr;
5291 address = base_address;
5293 EmulateInstruction::Context context;
5295 context.type = eContextPushRegisterOnStack;
5297 context.type = eContextRegisterStore;
5299 RegisterInfo base_reg;
5300 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n, base_reg);
5302 // if UnalignedSupport() || address<1:0> == '00' then
5303 if (UnalignedSupport() ||
5304 (BitIsClear(address, 1) && BitIsClear(address, 0))) {
5305 // MemU[address,4] = R[t];
5307 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + t, 0, &success);
5311 RegisterInfo data_reg;
5312 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + t, data_reg);
5313 int32_t offset = address - base_address;
5314 context.SetRegisterToRegisterPlusOffset(data_reg, base_reg, offset);
5315 if (!MemUWrite(context, address, data, addr_byte_size))
5318 // MemU[address,4] = bits(32) UNKNOWN;
5319 WriteBits32UnknownToMemory(address);
5322 // if wback then R[n] = offset_addr;
5325 context.type = eContextAdjustStackPointer;
5327 context.type = eContextAdjustBaseRegister;
5328 context.SetAddress(offset_addr);
5330 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n,
5338 // STR (Store Register) calculates an address from a base register value and an
5339 // offset register value, stores a
5340 // word from a register to memory. The offset register value can optionally be
5342 bool EmulateInstructionARM::EmulateSTRRegister(const uint32_t opcode,
5343 const ARMEncoding encoding) {
5345 if ConditionPassed() then
5346 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
5347 offset = Shift(R[m], shift_t, shift_n, APSR.C);
5348 offset_addr = if add then (R[n] + offset) else (R[n] - offset);
5349 address = if index then offset_addr else R[n];
5350 if t == 15 then // Only possible for encoding A1
5351 data = PCStoreValue();
5354 if UnalignedSupport() || address<1:0> == '00' || CurrentInstrSet() == InstrSet_ARM then
5355 MemU[address,4] = data;
5356 else // Can only occur before ARMv7
5357 MemU[address,4] = bits(32) UNKNOWN;
5358 if wback then R[n] = offset_addr;
5361 bool success = false;
5363 if (ConditionPassed(opcode)) {
5364 const uint32_t addr_byte_size = GetAddressByteSize();
5369 ARM_ShifterType shift_t;
5375 // EncodingSpecificOperations (); NullCheckIfThumbEE(n);
5378 // if CurrentInstrSet() == InstrSet_ThumbEE then SEE "Modified operation
5380 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
5381 t = Bits32(opcode, 2, 0);
5382 n = Bits32(opcode, 5, 3);
5383 m = Bits32(opcode, 8, 6);
5385 // index = TRUE; add = TRUE; wback = FALSE;
5390 // (shift_t, shift_n) = (SRType_LSL, 0);
5391 shift_t = SRType_LSL;
5396 // if Rn == '1111' then UNDEFINED;
5397 if (Bits32(opcode, 19, 16) == 15)
5400 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
5401 t = Bits32(opcode, 15, 12);
5402 n = Bits32(opcode, 19, 16);
5403 m = Bits32(opcode, 3, 0);
5405 // index = TRUE; add = TRUE; wback = FALSE;
5410 // (shift_t, shift_n) = (SRType_LSL, UInt(imm2));
5411 shift_t = SRType_LSL;
5412 shift_n = Bits32(opcode, 5, 4);
5414 // if t == 15 || BadReg(m) then UNPREDICTABLE;
5415 if ((t == 15) || (BadReg(m)))
5420 // if P == '0' && W == '1' then SEE STRT;
5421 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
5422 t = Bits32(opcode, 15, 12);
5423 n = Bits32(opcode, 19, 16);
5424 m = Bits32(opcode, 3, 0);
5426 // index = (P == '1'); add = (U == '1'); wback = (P == '0') ||
5428 index = BitIsSet(opcode, 24);
5429 add = BitIsSet(opcode, 23);
5430 wback = (BitIsClear(opcode, 24) || BitIsSet(opcode, 21));
5432 // (shift_t, shift_n) = DecodeImmShift(type, imm5);
5433 uint32_t typ = Bits32(opcode, 6, 5);
5434 uint32_t imm5 = Bits32(opcode, 11, 7);
5435 shift_n = DecodeImmShift(typ, imm5, shift_t);
5437 // if m == 15 then UNPREDICTABLE;
5441 // if wback && (n == 15 || n == t) then UNPREDICTABLE;
5442 if (wback && ((n == 15) || (n == t)))
5455 addr_t base_address =
5456 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
5461 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
5465 // offset = Shift(R[m], shift_t, shift_n, APSR.C);
5466 offset = Shift(Rm_data, shift_t, shift_n, APSR_C, &success);
5470 // offset_addr = if add then (R[n] + offset) else (R[n] - offset);
5472 offset_addr = base_address + offset;
5474 offset_addr = base_address - offset;
5476 // address = if index then offset_addr else R[n];
5478 address = offset_addr;
5480 address = base_address;
5483 // if t == 15 then // Only possible for encoding A1
5485 // data = PCStoreValue();
5486 data = ReadCoreReg(PC_REG, &success);
5490 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + t, 0, &success);
5495 EmulateInstruction::Context context;
5496 context.type = eContextRegisterStore;
5498 // if UnalignedSupport() || address<1:0> == '00' || CurrentInstrSet() ==
5499 // InstrSet_ARM then
5500 if (UnalignedSupport() ||
5501 (BitIsClear(address, 1) && BitIsClear(address, 0)) ||
5502 CurrentInstrSet() == eModeARM) {
5503 // MemU[address,4] = data;
5505 RegisterInfo base_reg;
5506 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n, base_reg);
5508 RegisterInfo data_reg;
5509 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + t, data_reg);
5511 context.SetRegisterToRegisterPlusOffset(data_reg, base_reg,
5512 address - base_address);
5513 if (!MemUWrite(context, address, data, addr_byte_size))
5517 // MemU[address,4] = bits(32) UNKNOWN;
5518 WriteBits32UnknownToMemory(address);
5520 // if wback then R[n] = offset_addr;
5522 context.type = eContextRegisterLoad;
5523 context.SetAddress(offset_addr);
5524 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n,
5532 bool EmulateInstructionARM::EmulateSTRBThumb(const uint32_t opcode,
5533 const ARMEncoding encoding) {
5535 if ConditionPassed() then
5536 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
5537 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
5538 address = if index then offset_addr else R[n];
5539 MemU[address,1] = R[t]<7:0>;
5540 if wback then R[n] = offset_addr;
5543 bool success = false;
5545 if (ConditionPassed(opcode)) {
5552 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
5555 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm5, 32);
5556 t = Bits32(opcode, 2, 0);
5557 n = Bits32(opcode, 5, 3);
5558 imm32 = Bits32(opcode, 10, 6);
5560 // index = TRUE; add = TRUE; wback = FALSE;
5567 // if Rn == '1111' then UNDEFINED;
5568 if (Bits32(opcode, 19, 16) == 15)
5571 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
5572 t = Bits32(opcode, 15, 12);
5573 n = Bits32(opcode, 19, 16);
5574 imm32 = Bits32(opcode, 11, 0);
5576 // index = TRUE; add = TRUE; wback = FALSE;
5581 // if BadReg(t) then UNPREDICTABLE;
5587 // if P == '1' && U == '1' && W == '0' then SEE STRBT;
5588 // if Rn == '1111' || (P == '0' && W == '0') then UNDEFINED;
5589 if (Bits32(opcode, 19, 16) == 15)
5592 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32);
5593 t = Bits32(opcode, 15, 12);
5594 n = Bits32(opcode, 19, 16);
5595 imm32 = Bits32(opcode, 7, 0);
5597 // index = (P == '1'); add = (U == '1'); wback = (W == '1');
5598 index = BitIsSet(opcode, 10);
5599 add = BitIsSet(opcode, 9);
5600 wback = BitIsSet(opcode, 8);
5602 // if BadReg(t) || (wback && n == t) then UNPREDICTABLE
5603 if ((BadReg(t)) || (wback && (n == t)))
5613 addr_t base_address =
5614 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
5618 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
5620 offset_addr = base_address + imm32;
5622 offset_addr = base_address - imm32;
5624 // address = if index then offset_addr else R[n];
5626 address = offset_addr;
5628 address = base_address;
5630 // MemU[address,1] = R[t]<7:0>
5631 RegisterInfo base_reg;
5632 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n, base_reg);
5634 RegisterInfo data_reg;
5635 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + t, data_reg);
5637 EmulateInstruction::Context context;
5638 context.type = eContextRegisterStore;
5639 context.SetRegisterToRegisterPlusOffset(data_reg, base_reg,
5640 address - base_address);
5643 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + t, 0, &success);
5647 data = Bits32(data, 7, 0);
5649 if (!MemUWrite(context, address, data, 1))
5652 // if wback then R[n] = offset_addr;
5654 context.type = eContextRegisterLoad;
5655 context.SetAddress(offset_addr);
5656 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n,
5665 // STRH (register) calculates an address from a base register value and an
5666 // offset register value, and stores a
5667 // halfword from a register to memory. The offset register value can be shifted
5668 // left by 0, 1, 2, or 3 bits.
5669 bool EmulateInstructionARM::EmulateSTRHRegister(const uint32_t opcode,
5670 const ARMEncoding encoding) {
5672 if ConditionPassed() then
5673 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
5674 offset = Shift(R[m], shift_t, shift_n, APSR.C);
5675 offset_addr = if add then (R[n] + offset) else (R[n] - offset);
5676 address = if index then offset_addr else R[n];
5677 if UnalignedSupport() || address<0> == '0' then
5678 MemU[address,2] = R[t]<15:0>;
5679 else // Can only occur before ARMv7
5680 MemU[address,2] = bits(16) UNKNOWN;
5681 if wback then R[n] = offset_addr;
5684 bool success = false;
5686 if (ConditionPassed(opcode)) {
5693 ARM_ShifterType shift_t;
5696 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
5699 // if CurrentInstrSet() == InstrSet_ThumbEE then SEE "Modified operation
5701 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
5702 t = Bits32(opcode, 2, 0);
5703 n = Bits32(opcode, 5, 3);
5704 m = Bits32(opcode, 8, 6);
5706 // index = TRUE; add = TRUE; wback = FALSE;
5711 // (shift_t, shift_n) = (SRType_LSL, 0);
5712 shift_t = SRType_LSL;
5718 // if Rn == '1111' then UNDEFINED;
5719 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
5720 t = Bits32(opcode, 15, 12);
5721 n = Bits32(opcode, 19, 16);
5722 m = Bits32(opcode, 3, 0);
5726 // index = TRUE; add = TRUE; wback = FALSE;
5731 // (shift_t, shift_n) = (SRType_LSL, UInt(imm2));
5732 shift_t = SRType_LSL;
5733 shift_n = Bits32(opcode, 5, 4);
5735 // if BadReg(t) || BadReg(m) then UNPREDICTABLE;
5736 if (BadReg(t) || BadReg(m))
5742 // if P == '0' && W == '1' then SEE STRHT;
5743 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
5744 t = Bits32(opcode, 15, 12);
5745 n = Bits32(opcode, 19, 16);
5746 m = Bits32(opcode, 3, 0);
5748 // index = (P == '1'); add = (U == '1'); wback = (P == '0') ||
5750 index = BitIsSet(opcode, 24);
5751 add = BitIsSet(opcode, 23);
5752 wback = (BitIsClear(opcode, 24) || BitIsSet(opcode, 21));
5754 // (shift_t, shift_n) = (SRType_LSL, 0);
5755 shift_t = SRType_LSL;
5758 // if t == 15 || m == 15 then UNPREDICTABLE;
5759 if ((t == 15) || (m == 15))
5762 // if wback && (n == 15 || n == t) then UNPREDICTABLE;
5763 if (wback && ((n == 15) || (n == t)))
5772 uint32_t Rm = ReadCoreReg(m, &success);
5776 uint32_t Rn = ReadCoreReg(n, &success);
5780 // offset = Shift(R[m], shift_t, shift_n, APSR.C);
5781 uint32_t offset = Shift(Rm, shift_t, shift_n, APSR_C, &success);
5785 // offset_addr = if add then (R[n] + offset) else (R[n] - offset);
5788 offset_addr = Rn + offset;
5790 offset_addr = Rn - offset;
5792 // address = if index then offset_addr else R[n];
5795 address = offset_addr;
5799 EmulateInstruction::Context context;
5800 context.type = eContextRegisterStore;
5801 RegisterInfo base_reg;
5802 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n, base_reg);
5803 RegisterInfo offset_reg;
5804 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + m, offset_reg);
5806 // if UnalignedSupport() || address<0> == '0' then
5807 if (UnalignedSupport() || BitIsClear(address, 0)) {
5808 // MemU[address,2] = R[t]<15:0>;
5809 uint32_t Rt = ReadCoreReg(t, &success);
5813 EmulateInstruction::Context context;
5814 context.type = eContextRegisterStore;
5815 RegisterInfo base_reg;
5816 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n, base_reg);
5817 RegisterInfo offset_reg;
5818 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + m, offset_reg);
5819 RegisterInfo data_reg;
5820 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + t, data_reg);
5821 context.SetRegisterToRegisterPlusIndirectOffset(base_reg, offset_reg,
5824 if (!MemUWrite(context, address, Bits32(Rt, 15, 0), 2))
5826 } else // Can only occur before ARMv7
5828 // MemU[address,2] = bits(16) UNKNOWN;
5831 // if wback then R[n] = offset_addr;
5833 context.type = eContextAdjustBaseRegister;
5834 context.SetAddress(offset_addr);
5835 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n,
5844 // Add with Carry (immediate) adds an immediate value and the carry flag value
5845 // to a register value,
5846 // and writes the result to the destination register. It can optionally update
5847 // the condition flags
5848 // based on the result.
5849 bool EmulateInstructionARM::EmulateADCImm(const uint32_t opcode,
5850 const ARMEncoding encoding) {
5852 // ARM pseudo code...
5853 if ConditionPassed() then
5854 EncodingSpecificOperations();
5855 (result, carry, overflow) = AddWithCarry(R[n], imm32, APSR.C);
5856 if d == 15 then // Can only occur for ARM encoding
5857 ALUWritePC(result); // setflags is always FALSE here
5861 APSR.N = result<31>;
5862 APSR.Z = IsZeroBit(result);
5867 bool success = false;
5869 if (ConditionPassed(opcode)) {
5872 imm32; // the immediate value to be added to the value obtained from Rn
5876 Rd = Bits32(opcode, 11, 8);
5877 Rn = Bits32(opcode, 19, 16);
5878 setflags = BitIsSet(opcode, 20);
5879 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8)
5880 if (BadReg(Rd) || BadReg(Rn))
5884 Rd = Bits32(opcode, 15, 12);
5885 Rn = Bits32(opcode, 19, 16);
5886 setflags = BitIsSet(opcode, 20);
5887 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
5889 if (Rd == 15 && setflags)
5890 return EmulateSUBSPcLrEtc(opcode, encoding);
5896 // Read the first operand.
5897 int32_t val1 = ReadCoreReg(Rn, &success);
5901 AddWithCarryResult res = AddWithCarry(val1, imm32, APSR_C);
5903 EmulateInstruction::Context context;
5904 context.type = EmulateInstruction::eContextImmediate;
5905 context.SetNoArgs();
5907 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags,
5908 res.carry_out, res.overflow))
5914 // Add with Carry (register) adds a register value, the carry flag value, and an
5915 // optionally-shifted
5916 // register value, and writes the result to the destination register. It can
5917 // optionally update the
5918 // condition flags based on the result.
5919 bool EmulateInstructionARM::EmulateADCReg(const uint32_t opcode,
5920 const ARMEncoding encoding) {
5922 // ARM pseudo code...
5923 if ConditionPassed() then
5924 EncodingSpecificOperations();
5925 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
5926 (result, carry, overflow) = AddWithCarry(R[n], shifted, APSR.C);
5927 if d == 15 then // Can only occur for ARM encoding
5928 ALUWritePC(result); // setflags is always FALSE here
5932 APSR.N = result<31>;
5933 APSR.Z = IsZeroBit(result);
5938 bool success = false;
5940 if (ConditionPassed(opcode)) {
5941 uint32_t Rd, Rn, Rm;
5942 ARM_ShifterType shift_t;
5943 uint32_t shift_n; // the shift applied to the value read from Rm
5947 Rd = Rn = Bits32(opcode, 2, 0);
5948 Rm = Bits32(opcode, 5, 3);
5949 setflags = !InITBlock();
5950 shift_t = SRType_LSL;
5954 Rd = Bits32(opcode, 11, 8);
5955 Rn = Bits32(opcode, 19, 16);
5956 Rm = Bits32(opcode, 3, 0);
5957 setflags = BitIsSet(opcode, 20);
5958 shift_n = DecodeImmShiftThumb(opcode, shift_t);
5959 if (BadReg(Rd) || BadReg(Rn) || BadReg(Rm))
5963 Rd = Bits32(opcode, 15, 12);
5964 Rn = Bits32(opcode, 19, 16);
5965 Rm = Bits32(opcode, 3, 0);
5966 setflags = BitIsSet(opcode, 20);
5967 shift_n = DecodeImmShiftARM(opcode, shift_t);
5969 if (Rd == 15 && setflags)
5970 return EmulateSUBSPcLrEtc(opcode, encoding);
5976 // Read the first operand.
5977 int32_t val1 = ReadCoreReg(Rn, &success);
5981 // Read the second operand.
5982 int32_t val2 = ReadCoreReg(Rm, &success);
5986 uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C, &success);
5989 AddWithCarryResult res = AddWithCarry(val1, shifted, APSR_C);
5991 EmulateInstruction::Context context;
5992 context.type = EmulateInstruction::eContextImmediate;
5993 context.SetNoArgs();
5995 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags,
5996 res.carry_out, res.overflow))
6002 // This instruction adds an immediate value to the PC value to form a
6003 // PC-relative address,
6004 // and writes the result to the destination register.
6005 bool EmulateInstructionARM::EmulateADR(const uint32_t opcode,
6006 const ARMEncoding encoding) {
6008 // ARM pseudo code...
6009 if ConditionPassed() then
6010 EncodingSpecificOperations();
6011 result = if add then (Align(PC,4) + imm32) else (Align(PC,4) - imm32);
6012 if d == 15 then // Can only occur for ARM encodings
6018 bool success = false;
6020 if (ConditionPassed(opcode)) {
6022 uint32_t imm32; // the immediate value to be added/subtracted to/from the PC
6026 Rd = Bits32(opcode, 10, 8);
6027 imm32 = ThumbImm8Scaled(opcode); // imm32 = ZeroExtend(imm8:'00', 32)
6032 Rd = Bits32(opcode, 11, 8);
6033 imm32 = ThumbImm12(opcode); // imm32 = ZeroExtend(i:imm3:imm8, 32)
6034 add = (Bits32(opcode, 24, 21) == 0); // 0b0000 => ADD; 0b0101 => SUB
6040 Rd = Bits32(opcode, 15, 12);
6041 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
6042 add = (Bits32(opcode, 24, 21) == 0x4); // 0b0100 => ADD; 0b0010 => SUB
6048 // Read the PC value.
6049 uint32_t pc = ReadCoreReg(PC_REG, &success);
6053 uint32_t result = (add ? Align(pc, 4) + imm32 : Align(pc, 4) - imm32);
6055 EmulateInstruction::Context context;
6056 context.type = EmulateInstruction::eContextImmediate;
6057 context.SetNoArgs();
6059 if (!WriteCoreReg(context, result, Rd))
6065 // This instruction performs a bitwise AND of a register value and an immediate
6066 // value, and writes the result
6067 // to the destination register. It can optionally update the condition flags
6068 // based on the result.
6069 bool EmulateInstructionARM::EmulateANDImm(const uint32_t opcode,
6070 const ARMEncoding encoding) {
6072 // ARM pseudo code...
6073 if ConditionPassed() then
6074 EncodingSpecificOperations();
6075 result = R[n] AND imm32;
6076 if d == 15 then // Can only occur for ARM encoding
6077 ALUWritePC(result); // setflags is always FALSE here
6081 APSR.N = result<31>;
6082 APSR.Z = IsZeroBit(result);
6087 bool success = false;
6089 if (ConditionPassed(opcode)) {
6092 imm32; // the immediate value to be ANDed to the value obtained from Rn
6094 uint32_t carry; // the carry bit after ARM/Thumb Expand operation
6097 Rd = Bits32(opcode, 11, 8);
6098 Rn = Bits32(opcode, 19, 16);
6099 setflags = BitIsSet(opcode, 20);
6100 imm32 = ThumbExpandImm_C(
6102 carry); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C)
6103 // if Rd == '1111' && S == '1' then SEE TST (immediate);
6104 if (Rd == 15 && setflags)
6105 return EmulateTSTImm(opcode, eEncodingT1);
6106 if (Rd == 13 || (Rd == 15 && !setflags) || BadReg(Rn))
6110 Rd = Bits32(opcode, 15, 12);
6111 Rn = Bits32(opcode, 19, 16);
6112 setflags = BitIsSet(opcode, 20);
6114 ARMExpandImm_C(opcode, APSR_C,
6115 carry); // (imm32, carry) = ARMExpandImm(imm12, APSR.C)
6117 if (Rd == 15 && setflags)
6118 return EmulateSUBSPcLrEtc(opcode, encoding);
6124 // Read the first operand.
6125 uint32_t val1 = ReadCoreReg(Rn, &success);
6129 uint32_t result = val1 & imm32;
6131 EmulateInstruction::Context context;
6132 context.type = EmulateInstruction::eContextImmediate;
6133 context.SetNoArgs();
6135 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
6141 // This instruction performs a bitwise AND of a register value and an
6142 // optionally-shifted register value,
6143 // and writes the result to the destination register. It can optionally update
6144 // the condition flags
6145 // based on the result.
6146 bool EmulateInstructionARM::EmulateANDReg(const uint32_t opcode,
6147 const ARMEncoding encoding) {
6149 // ARM pseudo code...
6150 if ConditionPassed() then
6151 EncodingSpecificOperations();
6152 (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C);
6153 result = R[n] AND shifted;
6154 if d == 15 then // Can only occur for ARM encoding
6155 ALUWritePC(result); // setflags is always FALSE here
6159 APSR.N = result<31>;
6160 APSR.Z = IsZeroBit(result);
6165 bool success = false;
6167 if (ConditionPassed(opcode)) {
6168 uint32_t Rd, Rn, Rm;
6169 ARM_ShifterType shift_t;
6170 uint32_t shift_n; // the shift applied to the value read from Rm
6175 Rd = Rn = Bits32(opcode, 2, 0);
6176 Rm = Bits32(opcode, 5, 3);
6177 setflags = !InITBlock();
6178 shift_t = SRType_LSL;
6182 Rd = Bits32(opcode, 11, 8);
6183 Rn = Bits32(opcode, 19, 16);
6184 Rm = Bits32(opcode, 3, 0);
6185 setflags = BitIsSet(opcode, 20);
6186 shift_n = DecodeImmShiftThumb(opcode, shift_t);
6187 // if Rd == '1111' && S == '1' then SEE TST (register);
6188 if (Rd == 15 && setflags)
6189 return EmulateTSTReg(opcode, eEncodingT2);
6190 if (Rd == 13 || (Rd == 15 && !setflags) || BadReg(Rn) || BadReg(Rm))
6194 Rd = Bits32(opcode, 15, 12);
6195 Rn = Bits32(opcode, 19, 16);
6196 Rm = Bits32(opcode, 3, 0);
6197 setflags = BitIsSet(opcode, 20);
6198 shift_n = DecodeImmShiftARM(opcode, shift_t);
6200 if (Rd == 15 && setflags)
6201 return EmulateSUBSPcLrEtc(opcode, encoding);
6207 // Read the first operand.
6208 uint32_t val1 = ReadCoreReg(Rn, &success);
6212 // Read the second operand.
6213 uint32_t val2 = ReadCoreReg(Rm, &success);
6217 uint32_t shifted = Shift_C(val2, shift_t, shift_n, APSR_C, carry, &success);
6220 uint32_t result = val1 & shifted;
6222 EmulateInstruction::Context context;
6223 context.type = EmulateInstruction::eContextImmediate;
6224 context.SetNoArgs();
6226 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
6232 // Bitwise Bit Clear (immediate) performs a bitwise AND of a register value and
6233 // the complement of an
6234 // immediate value, and writes the result to the destination register. It can
6235 // optionally update the
6236 // condition flags based on the result.
6237 bool EmulateInstructionARM::EmulateBICImm(const uint32_t opcode,
6238 const ARMEncoding encoding) {
6240 // ARM pseudo code...
6241 if ConditionPassed() then
6242 EncodingSpecificOperations();
6243 result = R[n] AND NOT(imm32);
6244 if d == 15 then // Can only occur for ARM encoding
6245 ALUWritePC(result); // setflags is always FALSE here
6249 APSR.N = result<31>;
6250 APSR.Z = IsZeroBit(result);
6255 bool success = false;
6257 if (ConditionPassed(opcode)) {
6259 uint32_t imm32; // the immediate value to be bitwise inverted and ANDed to
6260 // the value obtained from Rn
6262 uint32_t carry; // the carry bit after ARM/Thumb Expand operation
6265 Rd = Bits32(opcode, 11, 8);
6266 Rn = Bits32(opcode, 19, 16);
6267 setflags = BitIsSet(opcode, 20);
6268 imm32 = ThumbExpandImm_C(
6270 carry); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C)
6271 if (BadReg(Rd) || BadReg(Rn))
6275 Rd = Bits32(opcode, 15, 12);
6276 Rn = Bits32(opcode, 19, 16);
6277 setflags = BitIsSet(opcode, 20);
6279 ARMExpandImm_C(opcode, APSR_C,
6280 carry); // (imm32, carry) = ARMExpandImm(imm12, APSR.C)
6282 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related
6284 if (Rd == 15 && setflags)
6285 return EmulateSUBSPcLrEtc(opcode, encoding);
6291 // Read the first operand.
6292 uint32_t val1 = ReadCoreReg(Rn, &success);
6296 uint32_t result = val1 & ~imm32;
6298 EmulateInstruction::Context context;
6299 context.type = EmulateInstruction::eContextImmediate;
6300 context.SetNoArgs();
6302 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
6308 // Bitwise Bit Clear (register) performs a bitwise AND of a register value and
6309 // the complement of an
6310 // optionally-shifted register value, and writes the result to the destination
6312 // It can optionally update the condition flags based on the result.
6313 bool EmulateInstructionARM::EmulateBICReg(const uint32_t opcode,
6314 const ARMEncoding encoding) {
6316 // ARM pseudo code...
6317 if ConditionPassed() then
6318 EncodingSpecificOperations();
6319 (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C);
6320 result = R[n] AND NOT(shifted);
6321 if d == 15 then // Can only occur for ARM encoding
6322 ALUWritePC(result); // setflags is always FALSE here
6326 APSR.N = result<31>;
6327 APSR.Z = IsZeroBit(result);
6332 bool success = false;
6334 if (ConditionPassed(opcode)) {
6335 uint32_t Rd, Rn, Rm;
6336 ARM_ShifterType shift_t;
6337 uint32_t shift_n; // the shift applied to the value read from Rm
6342 Rd = Rn = Bits32(opcode, 2, 0);
6343 Rm = Bits32(opcode, 5, 3);
6344 setflags = !InITBlock();
6345 shift_t = SRType_LSL;
6349 Rd = Bits32(opcode, 11, 8);
6350 Rn = Bits32(opcode, 19, 16);
6351 Rm = Bits32(opcode, 3, 0);
6352 setflags = BitIsSet(opcode, 20);
6353 shift_n = DecodeImmShiftThumb(opcode, shift_t);
6354 if (BadReg(Rd) || BadReg(Rn) || BadReg(Rm))
6358 Rd = Bits32(opcode, 15, 12);
6359 Rn = Bits32(opcode, 19, 16);
6360 Rm = Bits32(opcode, 3, 0);
6361 setflags = BitIsSet(opcode, 20);
6362 shift_n = DecodeImmShiftARM(opcode, shift_t);
6364 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related
6366 if (Rd == 15 && setflags)
6367 return EmulateSUBSPcLrEtc(opcode, encoding);
6373 // Read the first operand.
6374 uint32_t val1 = ReadCoreReg(Rn, &success);
6378 // Read the second operand.
6379 uint32_t val2 = ReadCoreReg(Rm, &success);
6383 uint32_t shifted = Shift_C(val2, shift_t, shift_n, APSR_C, carry, &success);
6386 uint32_t result = val1 & ~shifted;
6388 EmulateInstruction::Context context;
6389 context.type = EmulateInstruction::eContextImmediate;
6390 context.SetNoArgs();
6392 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
6398 // LDR (immediate, ARM) calculates an address from a base register value and an
6399 // immediate offset, loads a word
6400 // from memory, and writes it to a register. It can use offset, post-indexed,
6401 // or pre-indexed addressing.
6402 bool EmulateInstructionARM::EmulateLDRImmediateARM(const uint32_t opcode,
6403 const ARMEncoding encoding) {
6405 if ConditionPassed() then
6406 EncodingSpecificOperations();
6407 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
6408 address = if index then offset_addr else R[n];
6409 data = MemU[address,4];
6410 if wback then R[n] = offset_addr;
6412 if address<1:0> == '00' then LoadWritePC(data); else UNPREDICTABLE;
6413 elsif UnalignedSupport() || address<1:0> = '00' then
6415 else // Can only apply before ARMv7
6416 R[t] = ROR(data, 8*UInt(address<1:0>));
6419 bool success = false;
6421 if (ConditionPassed(opcode)) {
6422 const uint32_t addr_byte_size = GetAddressByteSize();
6433 // if Rn == '1111' then SEE LDR (literal);
6434 // if P == '0' && W == '1' then SEE LDRT;
6435 // if Rn == '1101' && P == '0' && U == '1' && W == '0' && imm12 ==
6436 // '000000000100' then SEE POP;
6437 // t == UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
6438 t = Bits32(opcode, 15, 12);
6439 n = Bits32(opcode, 19, 16);
6440 imm32 = Bits32(opcode, 11, 0);
6442 // index = (P == '1'); add = (U == '1'); wback = (P == '0') ||
6444 index = BitIsSet(opcode, 24);
6445 add = BitIsSet(opcode, 23);
6446 wback = (BitIsClear(opcode, 24) || BitIsSet(opcode, 21));
6448 // if wback && n == t then UNPREDICTABLE;
6449 if (wback && (n == t))
6460 addr_t base_address = ReadCoreReg(n, &success);
6464 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
6466 offset_addr = base_address + imm32;
6468 offset_addr = base_address - imm32;
6470 // address = if index then offset_addr else R[n];
6472 address = offset_addr;
6474 address = base_address;
6476 // data = MemU[address,4];
6478 RegisterInfo base_reg;
6479 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n, base_reg);
6481 EmulateInstruction::Context context;
6482 context.type = eContextRegisterLoad;
6483 context.SetRegisterPlusOffset(base_reg, address - base_address);
6485 uint64_t data = MemURead(context, address, addr_byte_size, 0, &success);
6489 // if wback then R[n] = offset_addr;
6491 context.type = eContextAdjustBaseRegister;
6492 context.SetAddress(offset_addr);
6493 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n,
6500 // if address<1:0> == '00' then LoadWritePC(data); else UNPREDICTABLE;
6501 if (BitIsClear(address, 1) && BitIsClear(address, 0)) {
6502 // LoadWritePC (data);
6503 context.type = eContextRegisterLoad;
6504 context.SetRegisterPlusOffset(base_reg, address - base_address);
6505 LoadWritePC(context, data);
6509 // elsif UnalignedSupport() || address<1:0> = '00' then
6510 else if (UnalignedSupport() ||
6511 (BitIsClear(address, 1) && BitIsClear(address, 0))) {
6513 context.type = eContextRegisterLoad;
6514 context.SetRegisterPlusOffset(base_reg, address - base_address);
6515 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + t,
6519 // else // Can only apply before ARMv7
6521 // R[t] = ROR(data, 8*UInt(address<1:0>));
6522 data = ROR(data, Bits32(address, 1, 0), &success);
6525 context.type = eContextRegisterLoad;
6526 context.SetImmediate(data);
6527 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + t,
6535 // LDR (register) calculates an address from a base register value and an offset
6536 // register value, loads a word
6537 // from memory, and writes it to a register. The offset register value can
6538 // optionally be shifted.
6539 bool EmulateInstructionARM::EmulateLDRRegister(const uint32_t opcode,
6540 const ARMEncoding encoding) {
6542 if ConditionPassed() then
6543 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
6544 offset = Shift(R[m], shift_t, shift_n, APSR.C);
6545 offset_addr = if add then (R[n] + offset) else (R[n] - offset);
6546 address = if index then offset_addr else R[n];
6547 data = MemU[address,4];
6548 if wback then R[n] = offset_addr;
6550 if address<1:0> == '00' then LoadWritePC(data); else UNPREDICTABLE;
6551 elsif UnalignedSupport() || address<1:0> = '00' then
6553 else // Can only apply before ARMv7
6554 if CurrentInstrSet() == InstrSet_ARM then
6555 R[t] = ROR(data, 8*UInt(address<1:0>));
6557 R[t] = bits(32) UNKNOWN;
6560 bool success = false;
6562 if (ConditionPassed(opcode)) {
6563 const uint32_t addr_byte_size = GetAddressByteSize();
6571 ARM_ShifterType shift_t;
6576 // if CurrentInstrSet() == InstrSet_ThumbEE then SEE "Modified operation
6578 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
6579 t = Bits32(opcode, 2, 0);
6580 n = Bits32(opcode, 5, 3);
6581 m = Bits32(opcode, 8, 6);
6583 // index = TRUE; add = TRUE; wback = FALSE;
6588 // (shift_t, shift_n) = (SRType_LSL, 0);
6589 shift_t = SRType_LSL;
6595 // if Rn == '1111' then SEE LDR (literal);
6596 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
6597 t = Bits32(opcode, 15, 12);
6598 n = Bits32(opcode, 19, 16);
6599 m = Bits32(opcode, 3, 0);
6601 // index = TRUE; add = TRUE; wback = FALSE;
6606 // (shift_t, shift_n) = (SRType_LSL, UInt(imm2));
6607 shift_t = SRType_LSL;
6608 shift_n = Bits32(opcode, 5, 4);
6610 // if BadReg(m) then UNPREDICTABLE;
6614 // if t == 15 && InITBlock() && !LastInITBlock() then UNPREDICTABLE;
6615 if ((t == 15) && InITBlock() && !LastInITBlock())
6621 // if P == '0' && W == '1' then SEE LDRT;
6622 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
6623 t = Bits32(opcode, 15, 12);
6624 n = Bits32(opcode, 19, 16);
6625 m = Bits32(opcode, 3, 0);
6627 // index = (P == '1'); add = (U == '1'); wback = (P == '0') ||
6629 index = BitIsSet(opcode, 24);
6630 add = BitIsSet(opcode, 23);
6631 wback = (BitIsClear(opcode, 24) || BitIsSet(opcode, 21));
6633 // (shift_t, shift_n) = DecodeImmShift(type, imm5);
6634 uint32_t type = Bits32(opcode, 6, 5);
6635 uint32_t imm5 = Bits32(opcode, 11, 7);
6636 shift_n = DecodeImmShift(type, imm5, shift_t);
6638 // if m == 15 then UNPREDICTABLE;
6642 // if wback && (n == 15 || n == t) then UNPREDICTABLE;
6643 if (wback && ((n == 15) || (n == t)))
6652 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
6657 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
6664 // offset = Shift(R[m], shift_t, shift_n, APSR.C); -- Note "The APSR is an
6665 // application level alias for the CPSR".
6667 Shift(Rm, shift_t, shift_n, Bit32(m_opcode_cpsr, APSR_C), &success);
6671 // offset_addr = if add then (R[n] + offset) else (R[n] - offset);
6673 offset_addr = Rn + offset;
6675 offset_addr = Rn - offset;
6677 // address = if index then offset_addr else R[n];
6679 address = offset_addr;
6683 // data = MemU[address,4];
6684 RegisterInfo base_reg;
6685 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n, base_reg);
6687 EmulateInstruction::Context context;
6688 context.type = eContextRegisterLoad;
6689 context.SetRegisterPlusOffset(base_reg, address - Rn);
6691 uint64_t data = MemURead(context, address, addr_byte_size, 0, &success);
6695 // if wback then R[n] = offset_addr;
6697 context.type = eContextAdjustBaseRegister;
6698 context.SetAddress(offset_addr);
6699 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n,
6706 // if address<1:0> == '00' then LoadWritePC(data); else UNPREDICTABLE;
6707 if (BitIsClear(address, 1) && BitIsClear(address, 0)) {
6708 context.type = eContextRegisterLoad;
6709 context.SetRegisterPlusOffset(base_reg, address - Rn);
6710 LoadWritePC(context, data);
6714 // elsif UnalignedSupport() || address<1:0> = '00' then
6715 else if (UnalignedSupport() ||
6716 (BitIsClear(address, 1) && BitIsClear(address, 0))) {
6718 context.type = eContextRegisterLoad;
6719 context.SetRegisterPlusOffset(base_reg, address - Rn);
6720 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + t,
6723 } else // Can only apply before ARMv7
6725 // if CurrentInstrSet() == InstrSet_ARM then
6726 if (CurrentInstrSet() == eModeARM) {
6727 // R[t] = ROR(data, 8*UInt(address<1:0>));
6728 data = ROR(data, Bits32(address, 1, 0), &success);
6731 context.type = eContextRegisterLoad;
6732 context.SetImmediate(data);
6733 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + t,
6737 // R[t] = bits(32) UNKNOWN;
6738 WriteBits32Unknown(t);
6745 // LDRB (immediate, Thumb)
6746 bool EmulateInstructionARM::EmulateLDRBImmediate(const uint32_t opcode,
6747 const ARMEncoding encoding) {
6749 if ConditionPassed() then
6750 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
6751 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
6752 address = if index then offset_addr else R[n];
6753 R[t] = ZeroExtend(MemU[address,1], 32);
6754 if wback then R[n] = offset_addr;
6757 bool success = false;
6759 if (ConditionPassed(opcode)) {
6767 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
6770 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm5, 32);
6771 t = Bits32(opcode, 2, 0);
6772 n = Bits32(opcode, 5, 3);
6773 imm32 = Bits32(opcode, 10, 6);
6775 // index = TRUE; add = TRUE; wback = FALSE;
6783 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
6784 t = Bits32(opcode, 15, 12);
6785 n = Bits32(opcode, 19, 16);
6786 imm32 = Bits32(opcode, 11, 0);
6788 // index = TRUE; add = TRUE; wback = FALSE;
6793 // if Rt == '1111' then SEE PLD;
6795 return false; // PLD is not implemented yet
6797 // if Rn == '1111' then SEE LDRB (literal);
6799 return EmulateLDRBLiteral(opcode, eEncodingT1);
6801 // if t == 13 then UNPREDICTABLE;
6808 // if P == '1' && U == '1' && W == '0' then SEE LDRBT;
6809 // if P == '0' && W == '0' then UNDEFINED;
6810 if (BitIsClear(opcode, 10) && BitIsClear(opcode, 8))
6813 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32);
6814 t = Bits32(opcode, 15, 12);
6815 n = Bits32(opcode, 19, 16);
6816 imm32 = Bits32(opcode, 7, 0);
6818 // index = (P == '1'); add = (U == '1'); wback = (W == '1');
6819 index = BitIsSet(opcode, 10);
6820 add = BitIsSet(opcode, 9);
6821 wback = BitIsSet(opcode, 8);
6823 // if Rt == '1111' && P == '1' && U == '0' && W == '0' then SEE PLD;
6825 return false; // PLD is not implemented yet
6827 // if Rn == '1111' then SEE LDRB (literal);
6829 return EmulateLDRBLiteral(opcode, eEncodingT1);
6831 // if BadReg(t) || (wback && n == t) then UNPREDICTABLE;
6832 if (BadReg(t) || (wback && (n == t)))
6842 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
6849 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
6851 offset_addr = Rn + imm32;
6853 offset_addr = Rn - imm32;
6855 // address = if index then offset_addr else R[n];
6857 address = offset_addr;
6861 // R[t] = ZeroExtend(MemU[address,1], 32);
6862 RegisterInfo base_reg;
6863 RegisterInfo data_reg;
6864 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n, base_reg);
6865 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + t, data_reg);
6867 EmulateInstruction::Context context;
6868 context.type = eContextRegisterLoad;
6869 context.SetRegisterToRegisterPlusOffset(data_reg, base_reg, address - Rn);
6871 uint64_t data = MemURead(context, address, 1, 0, &success);
6875 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + t, data))
6878 // if wback then R[n] = offset_addr;
6880 context.type = eContextAdjustBaseRegister;
6881 context.SetAddress(offset_addr);
6882 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n,
6890 // LDRB (literal) calculates an address from the PC value and an immediate
6891 // offset, loads a byte from memory,
6892 // zero-extends it to form a 32-bit word and writes it to a register.
6893 bool EmulateInstructionARM::EmulateLDRBLiteral(const uint32_t opcode,
6894 const ARMEncoding encoding) {
6896 if ConditionPassed() then
6897 EncodingSpecificOperations(); NullCheckIfThumbEE(15);
6899 address = if add then (base + imm32) else (base - imm32);
6900 R[t] = ZeroExtend(MemU[address,1], 32);
6903 bool success = false;
6905 if (ConditionPassed(opcode)) {
6911 // t = UInt(Rt); imm32 = ZeroExtend(imm12, 32); add = (U == '1');
6912 t = Bits32(opcode, 15, 12);
6913 imm32 = Bits32(opcode, 11, 0);
6914 add = BitIsSet(opcode, 23);
6916 // if Rt == '1111' then SEE PLD;
6918 return false; // PLD is not implemented yet
6920 // if t == 13 then UNPREDICTABLE;
6927 // t == UInt(Rt); imm32 = ZeroExtend(imm12, 32); add = (U == '1');
6928 t = Bits32(opcode, 15, 12);
6929 imm32 = Bits32(opcode, 11, 0);
6930 add = BitIsSet(opcode, 23);
6932 // if t == 15 then UNPREDICTABLE;
6941 // base = Align(PC,4);
6942 uint32_t pc_val = ReadCoreReg(PC_REG, &success);
6946 uint32_t base = AlignPC(pc_val);
6949 // address = if add then (base + imm32) else (base - imm32);
6951 address = base + imm32;
6953 address = base - imm32;
6955 // R[t] = ZeroExtend(MemU[address,1], 32);
6956 EmulateInstruction::Context context;
6957 context.type = eContextRelativeBranchImmediate;
6958 context.SetImmediate(address - base);
6960 uint64_t data = MemURead(context, address, 1, 0, &success);
6964 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + t, data))
6970 // LDRB (register) calculates an address from a base register value and an
6971 // offset rigister value, loads a byte from
6972 // memory, zero-extends it to form a 32-bit word, and writes it to a register.
6973 // The offset register value can
6974 // optionally be shifted.
6975 bool EmulateInstructionARM::EmulateLDRBRegister(const uint32_t opcode,
6976 const ARMEncoding encoding) {
6978 if ConditionPassed() then
6979 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
6980 offset = Shift(R[m], shift_t, shift_n, APSR.C);
6981 offset_addr = if add then (R[n] + offset) else (R[n] - offset);
6982 address = if index then offset_addr else R[n];
6983 R[t] = ZeroExtend(MemU[address,1],32);
6984 if wback then R[n] = offset_addr;
6987 bool success = false;
6989 if (ConditionPassed(opcode)) {
6996 ARM_ShifterType shift_t;
6999 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
7002 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
7003 t = Bits32(opcode, 2, 0);
7004 n = Bits32(opcode, 5, 3);
7005 m = Bits32(opcode, 8, 6);
7007 // index = TRUE; add = TRUE; wback = FALSE;
7012 // (shift_t, shift_n) = (SRType_LSL, 0);
7013 shift_t = SRType_LSL;
7018 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
7019 t = Bits32(opcode, 15, 12);
7020 n = Bits32(opcode, 19, 16);
7021 m = Bits32(opcode, 3, 0);
7023 // index = TRUE; add = TRUE; wback = FALSE;
7028 // (shift_t, shift_n) = (SRType_LSL, UInt(imm2));
7029 shift_t = SRType_LSL;
7030 shift_n = Bits32(opcode, 5, 4);
7032 // if Rt == '1111' then SEE PLD;
7034 return false; // PLD is not implemented yet
7036 // if Rn == '1111' then SEE LDRB (literal);
7038 return EmulateLDRBLiteral(opcode, eEncodingT1);
7040 // if t == 13 || BadReg(m) then UNPREDICTABLE;
7041 if ((t == 13) || BadReg(m))
7046 // if P == '0' && W == '1' then SEE LDRBT;
7047 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
7048 t = Bits32(opcode, 15, 12);
7049 n = Bits32(opcode, 19, 16);
7050 m = Bits32(opcode, 3, 0);
7052 // index = (P == '1'); add = (U == '1'); wback = (P == '0') ||
7054 index = BitIsSet(opcode, 24);
7055 add = BitIsSet(opcode, 23);
7056 wback = (BitIsClear(opcode, 24) || BitIsSet(opcode, 21));
7058 // (shift_t, shift_n) = DecodeImmShift(type, imm5);
7059 uint32_t type = Bits32(opcode, 6, 5);
7060 uint32_t imm5 = Bits32(opcode, 11, 7);
7061 shift_n = DecodeImmShift(type, imm5, shift_t);
7063 // if t == 15 || m == 15 then UNPREDICTABLE;
7064 if ((t == 15) || (m == 15))
7067 // if wback && (n == 15 || n == t) then UNPREDICTABLE;
7068 if (wback && ((n == 15) || (n == t)))
7079 // offset = Shift(R[m], shift_t, shift_n, APSR.C);
7081 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
7085 addr_t offset = Shift(Rm, shift_t, shift_n, APSR_C, &success);
7089 // offset_addr = if add then (R[n] + offset) else (R[n] - offset);
7091 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
7096 offset_addr = Rn + offset;
7098 offset_addr = Rn - offset;
7100 // address = if index then offset_addr else R[n];
7102 address = offset_addr;
7106 // R[t] = ZeroExtend(MemU[address,1],32);
7107 RegisterInfo base_reg;
7108 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n, base_reg);
7110 EmulateInstruction::Context context;
7111 context.type = eContextRegisterLoad;
7112 context.SetRegisterPlusOffset(base_reg, address - Rn);
7114 uint64_t data = MemURead(context, address, 1, 0, &success);
7118 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + t, data))
7121 // if wback then R[n] = offset_addr;
7123 context.type = eContextAdjustBaseRegister;
7124 context.SetAddress(offset_addr);
7125 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n,
7133 // LDRH (immediate, Thumb) calculates an address from a base register value and
7134 // an immediate offset, loads a
7135 // halfword from memory, zero-extends it to form a 32-bit word, and writes it to
7136 // a register. It can use offset,
7137 // post-indexed, or pre-indexed addressing.
7138 bool EmulateInstructionARM::EmulateLDRHImmediate(const uint32_t opcode,
7139 const ARMEncoding encoding) {
7141 if ConditionPassed() then
7142 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
7143 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
7144 address = if index then offset_addr else R[n];
7145 data = MemU[address,2];
7146 if wback then R[n] = offset_addr;
7147 if UnalignedSupport() || address<0> = '0' then
7148 R[t] = ZeroExtend(data, 32);
7149 else // Can only apply before ARMv7
7150 R[t] = bits(32) UNKNOWN;
7153 bool success = false;
7155 if (ConditionPassed(opcode)) {
7163 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
7166 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm5:'0', 32);
7167 t = Bits32(opcode, 2, 0);
7168 n = Bits32(opcode, 5, 3);
7169 imm32 = Bits32(opcode, 10, 6) << 1;
7171 // index = TRUE; add = TRUE; wback = FALSE;
7179 // if Rt == '1111' then SEE "Unallocated memory hints";
7180 // if Rn == '1111' then SEE LDRH (literal);
7181 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
7182 t = Bits32(opcode, 15, 12);
7183 n = Bits32(opcode, 19, 16);
7184 imm32 = Bits32(opcode, 11, 0);
7186 // index = TRUE; add = TRUE; wback = FALSE;
7191 // if t == 13 then UNPREDICTABLE;
7197 // if Rn == '1111' then SEE LDRH (literal);
7198 // if Rt == '1111' && P == '1' && U == '0' && W == '0' then SEE
7199 // "Unallocated memory hints";
7200 // if P == '1' && U == '1' && W == '0' then SEE LDRHT;
7201 // if P == '0' && W == '0' then UNDEFINED;
7202 if (BitIsClear(opcode, 10) && BitIsClear(opcode, 8))
7205 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32);
7206 t = Bits32(opcode, 15, 12);
7207 n = Bits32(opcode, 19, 16);
7208 imm32 = Bits32(opcode, 7, 0);
7210 // index = (P == '1'); add = (U == '1'); wback = (W == '1');
7211 index = BitIsSet(opcode, 10);
7212 add = BitIsSet(opcode, 9);
7213 wback = BitIsSet(opcode, 8);
7215 // if BadReg(t) || (wback && n == t) then UNPREDICTABLE;
7216 if (BadReg(t) || (wback && (n == t)))
7224 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
7226 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
7234 offset_addr = Rn + imm32;
7236 offset_addr = Rn - imm32;
7238 // address = if index then offset_addr else R[n];
7240 address = offset_addr;
7244 // data = MemU[address,2];
7245 RegisterInfo base_reg;
7246 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n, base_reg);
7248 EmulateInstruction::Context context;
7249 context.type = eContextRegisterLoad;
7250 context.SetRegisterPlusOffset(base_reg, address - Rn);
7252 uint64_t data = MemURead(context, address, 2, 0, &success);
7256 // if wback then R[n] = offset_addr;
7258 context.type = eContextAdjustBaseRegister;
7259 context.SetAddress(offset_addr);
7260 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n,
7265 // if UnalignedSupport() || address<0> = '0' then
7266 if (UnalignedSupport() || BitIsClear(address, 0)) {
7267 // R[t] = ZeroExtend(data, 32);
7268 context.type = eContextRegisterLoad;
7269 context.SetRegisterPlusOffset(base_reg, address - Rn);
7270 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + t,
7273 } else // Can only apply before ARMv7
7275 // R[t] = bits(32) UNKNOWN;
7276 WriteBits32Unknown(t);
7282 // LDRH (literal) caculates an address from the PC value and an immediate
7283 // offset, loads a halfword from memory,
7284 // zero-extends it to form a 32-bit word, and writes it to a register.
7285 bool EmulateInstructionARM::EmulateLDRHLiteral(const uint32_t opcode,
7286 const ARMEncoding encoding) {
7288 if ConditionPassed() then
7289 EncodingSpecificOperations(); NullCheckIfThumbEE(15);
7291 address = if add then (base + imm32) else (base - imm32);
7292 data = MemU[address,2];
7293 if UnalignedSupport() || address<0> = '0' then
7294 R[t] = ZeroExtend(data, 32);
7295 else // Can only apply before ARMv7
7296 R[t] = bits(32) UNKNOWN;
7299 bool success = false;
7301 if (ConditionPassed(opcode)) {
7306 // EncodingSpecificOperations(); NullCheckIfThumbEE(15);
7309 // if Rt == '1111' then SEE "Unallocated memory hints";
7310 // t = UInt(Rt); imm32 = ZeroExtend(imm12, 32); add = (U == '1');
7311 t = Bits32(opcode, 15, 12);
7312 imm32 = Bits32(opcode, 11, 0);
7313 add = BitIsSet(opcode, 23);
7315 // if t == 13 then UNPREDICTABLE;
7322 uint32_t imm4H = Bits32(opcode, 11, 8);
7323 uint32_t imm4L = Bits32(opcode, 3, 0);
7325 // t == UInt(Rt); imm32 = ZeroExtend(imm4H:imm4L, 32); add = (U == '1');
7326 t = Bits32(opcode, 15, 12);
7327 imm32 = (imm4H << 4) | imm4L;
7328 add = BitIsSet(opcode, 23);
7330 // if t == 15 then UNPREDICTABLE;
7340 // base = Align(PC,4);
7341 uint64_t pc_value = ReadCoreReg(PC_REG, &success);
7345 addr_t base = AlignPC(pc_value);
7348 // address = if add then (base + imm32) else (base - imm32);
7350 address = base + imm32;
7352 address = base - imm32;
7354 // data = MemU[address,2];
7355 RegisterInfo base_reg;
7356 GetRegisterInfo(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, base_reg);
7358 EmulateInstruction::Context context;
7359 context.type = eContextRegisterLoad;
7360 context.SetRegisterPlusOffset(base_reg, address - base);
7362 uint64_t data = MemURead(context, address, 2, 0, &success);
7366 // if UnalignedSupport() || address<0> = '0' then
7367 if (UnalignedSupport() || BitIsClear(address, 0)) {
7368 // R[t] = ZeroExtend(data, 32);
7369 context.type = eContextRegisterLoad;
7370 context.SetRegisterPlusOffset(base_reg, address - base);
7371 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + t,
7375 } else // Can only apply before ARMv7
7377 // R[t] = bits(32) UNKNOWN;
7378 WriteBits32Unknown(t);
7384 // LDRH (literal) calculates an address from a base register value and an offset
7385 // register value, loads a halfword
7386 // from memory, zero-extends it to form a 32-bit word, and writes it to a
7387 // register. The offset register value can
7388 // be shifted left by 0, 1, 2, or 3 bits.
7389 bool EmulateInstructionARM::EmulateLDRHRegister(const uint32_t opcode,
7390 const ARMEncoding encoding) {
7392 if ConditionPassed() then
7393 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
7394 offset = Shift(R[m], shift_t, shift_n, APSR.C);
7395 offset_addr = if add then (R[n] + offset) else (R[n] - offset);
7396 address = if index then offset_addr else R[n];
7397 data = MemU[address,2];
7398 if wback then R[n] = offset_addr;
7399 if UnalignedSupport() || address<0> = '0' then
7400 R[t] = ZeroExtend(data, 32);
7401 else // Can only apply before ARMv7
7402 R[t] = bits(32) UNKNOWN;
7405 bool success = false;
7407 if (ConditionPassed(opcode)) {
7414 ARM_ShifterType shift_t;
7417 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
7420 // if CurrentInstrSet() == InstrSet_ThumbEE then SEE "Modified operation
7422 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
7423 t = Bits32(opcode, 2, 0);
7424 n = Bits32(opcode, 5, 3);
7425 m = Bits32(opcode, 8, 6);
7427 // index = TRUE; add = TRUE; wback = FALSE;
7432 // (shift_t, shift_n) = (SRType_LSL, 0);
7433 shift_t = SRType_LSL;
7439 // if Rn == '1111' then SEE LDRH (literal);
7440 // if Rt == '1111' then SEE "Unallocated memory hints";
7441 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
7442 t = Bits32(opcode, 15, 12);
7443 n = Bits32(opcode, 19, 16);
7444 m = Bits32(opcode, 3, 0);
7446 // index = TRUE; add = TRUE; wback = FALSE;
7451 // (shift_t, shift_n) = (SRType_LSL, UInt(imm2));
7452 shift_t = SRType_LSL;
7453 shift_n = Bits32(opcode, 5, 4);
7455 // if t == 13 || BadReg(m) then UNPREDICTABLE;
7456 if ((t == 13) || BadReg(m))
7461 // if P == '0' && W == '1' then SEE LDRHT;
7462 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
7463 t = Bits32(opcode, 15, 12);
7464 n = Bits32(opcode, 19, 16);
7465 m = Bits32(opcode, 3, 0);
7467 // index = (P == '1'); add = (U == '1'); wback = (P == '0') ||
7469 index = BitIsSet(opcode, 24);
7470 add = BitIsSet(opcode, 23);
7471 wback = (BitIsClear(opcode, 24) || BitIsSet(opcode, 21));
7473 // (shift_t, shift_n) = (SRType_LSL, 0);
7474 shift_t = SRType_LSL;
7477 // if t == 15 || m == 15 then UNPREDICTABLE;
7478 if ((t == 15) || (m == 15))
7481 // if wback && (n == 15 || n == t) then UNPREDICTABLE;
7482 if (wback && ((n == 15) || (n == t)))
7491 // offset = Shift(R[m], shift_t, shift_n, APSR.C);
7494 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
7498 addr_t offset = Shift(Rm, shift_t, shift_n, APSR_C, &success);
7505 // offset_addr = if add then (R[n] + offset) else (R[n] - offset);
7507 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
7512 offset_addr = Rn + offset;
7514 offset_addr = Rn - offset;
7516 // address = if index then offset_addr else R[n];
7518 address = offset_addr;
7522 // data = MemU[address,2];
7523 RegisterInfo base_reg;
7524 RegisterInfo offset_reg;
7525 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n, base_reg);
7526 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + m, offset_reg);
7528 EmulateInstruction::Context context;
7529 context.type = eContextRegisterLoad;
7530 context.SetRegisterPlusIndirectOffset(base_reg, offset_reg);
7531 uint64_t data = MemURead(context, address, 2, 0, &success);
7535 // if wback then R[n] = offset_addr;
7537 context.type = eContextAdjustBaseRegister;
7538 context.SetAddress(offset_addr);
7539 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n,
7544 // if UnalignedSupport() || address<0> = '0' then
7545 if (UnalignedSupport() || BitIsClear(address, 0)) {
7546 // R[t] = ZeroExtend(data, 32);
7547 context.type = eContextRegisterLoad;
7548 context.SetRegisterPlusIndirectOffset(base_reg, offset_reg);
7549 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + t,
7552 } else // Can only apply before ARMv7
7554 // R[t] = bits(32) UNKNOWN;
7555 WriteBits32Unknown(t);
7561 // LDRSB (immediate) calculates an address from a base register value and an
7562 // immediate offset, loads a byte from
7563 // memory, sign-extends it to form a 32-bit word, and writes it to a register.
7564 // It can use offset, post-indexed,
7565 // or pre-indexed addressing.
7566 bool EmulateInstructionARM::EmulateLDRSBImmediate(const uint32_t opcode,
7567 const ARMEncoding encoding) {
7569 if ConditionPassed() then
7570 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
7571 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
7572 address = if index then offset_addr else R[n];
7573 R[t] = SignExtend(MemU[address,1], 32);
7574 if wback then R[n] = offset_addr;
7577 bool success = false;
7579 if (ConditionPassed(opcode)) {
7587 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
7590 // if Rt == '1111' then SEE PLI;
7591 // if Rn == '1111' then SEE LDRSB (literal);
7592 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
7593 t = Bits32(opcode, 15, 12);
7594 n = Bits32(opcode, 19, 16);
7595 imm32 = Bits32(opcode, 11, 0);
7597 // index = TRUE; add = TRUE; wback = FALSE;
7602 // if t == 13 then UNPREDICTABLE;
7609 // if Rt == '1111' && P == '1' && U == '0' && W == '0' then SEE PLI;
7610 // if Rn == '1111' then SEE LDRSB (literal);
7611 // if P == '1' && U == '1' && W == '0' then SEE LDRSBT;
7612 // if P == '0' && W == '0' then UNDEFINED;
7613 if (BitIsClear(opcode, 10) && BitIsClear(opcode, 8))
7616 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32);
7617 t = Bits32(opcode, 15, 12);
7618 n = Bits32(opcode, 19, 16);
7619 imm32 = Bits32(opcode, 7, 0);
7621 // index = (P == '1'); add = (U == '1'); wback = (W == '1');
7622 index = BitIsSet(opcode, 10);
7623 add = BitIsSet(opcode, 9);
7624 wback = BitIsSet(opcode, 8);
7626 // if BadReg(t) || (wback && n == t) then UNPREDICTABLE;
7628 ((t == 15) && (BitIsClear(opcode, 10) || BitIsSet(opcode, 9) ||
7629 BitIsSet(opcode, 8)))) ||
7630 (wback && (n == t)))
7636 // if Rn == '1111' then SEE LDRSB (literal);
7637 // if P == '0' && W == '1' then SEE LDRSBT;
7638 // t == UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm4H:imm4L, 32);
7639 t = Bits32(opcode, 15, 12);
7640 n = Bits32(opcode, 19, 16);
7642 uint32_t imm4H = Bits32(opcode, 11, 8);
7643 uint32_t imm4L = Bits32(opcode, 3, 0);
7644 imm32 = (imm4H << 4) | imm4L;
7646 // index = (P == '1'); add = (U == '1'); wback = (P == '0') ||
7648 index = BitIsSet(opcode, 24);
7649 add = BitIsSet(opcode, 23);
7650 wback = (BitIsClear(opcode, 24) || BitIsSet(opcode, 21));
7652 // if t == 15 || (wback && n == t) then UNPREDICTABLE;
7653 if ((t == 15) || (wback && (n == t)))
7663 uint64_t Rn = ReadCoreReg(n, &success);
7670 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
7672 offset_addr = Rn + imm32;
7674 offset_addr = Rn - imm32;
7676 // address = if index then offset_addr else R[n];
7678 address = offset_addr;
7682 // R[t] = SignExtend(MemU[address,1], 32);
7683 RegisterInfo base_reg;
7684 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n, base_reg);
7686 EmulateInstruction::Context context;
7687 context.type = eContextRegisterLoad;
7688 context.SetRegisterPlusOffset(base_reg, address - Rn);
7690 uint64_t unsigned_data = MemURead(context, address, 1, 0, &success);
7694 int64_t signed_data = llvm::SignExtend64<8>(unsigned_data);
7695 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + t,
7696 (uint64_t)signed_data))
7699 // if wback then R[n] = offset_addr;
7701 context.type = eContextAdjustBaseRegister;
7702 context.SetAddress(offset_addr);
7703 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n,
7712 // LDRSB (literal) calculates an address from the PC value and an immediate
7713 // offset, loads a byte from memory,
7714 // sign-extends it to form a 32-bit word, and writes tit to a register.
7715 bool EmulateInstructionARM::EmulateLDRSBLiteral(const uint32_t opcode,
7716 const ARMEncoding encoding) {
7718 if ConditionPassed() then
7719 EncodingSpecificOperations(); NullCheckIfThumbEE(15);
7721 address = if add then (base + imm32) else (base - imm32);
7722 R[t] = SignExtend(MemU[address,1], 32);
7725 bool success = false;
7727 if (ConditionPassed(opcode)) {
7732 // EncodingSpecificOperations(); NullCheckIfThumbEE(15);
7735 // if Rt == '1111' then SEE PLI;
7736 // t = UInt(Rt); imm32 = ZeroExtend(imm12, 32); add = (U == '1');
7737 t = Bits32(opcode, 15, 12);
7738 imm32 = Bits32(opcode, 11, 0);
7739 add = BitIsSet(opcode, 23);
7741 // if t == 13 then UNPREDICTABLE;
7748 // t == UInt(Rt); imm32 = ZeroExtend(imm4H:imm4L, 32); add = (U == '1');
7749 t = Bits32(opcode, 15, 12);
7750 uint32_t imm4H = Bits32(opcode, 11, 8);
7751 uint32_t imm4L = Bits32(opcode, 3, 0);
7752 imm32 = (imm4H << 4) | imm4L;
7753 add = BitIsSet(opcode, 23);
7755 // if t == 15 then UNPREDICTABLE;
7766 // base = Align(PC,4);
7767 uint64_t pc_value = ReadCoreReg(PC_REG, &success);
7770 uint64_t base = AlignPC(pc_value);
7772 // address = if add then (base + imm32) else (base - imm32);
7775 address = base + imm32;
7777 address = base - imm32;
7779 // R[t] = SignExtend(MemU[address,1], 32);
7780 RegisterInfo base_reg;
7781 GetRegisterInfo(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, base_reg);
7783 EmulateInstruction::Context context;
7784 context.type = eContextRegisterLoad;
7785 context.SetRegisterPlusOffset(base_reg, address - base);
7787 uint64_t unsigned_data = MemURead(context, address, 1, 0, &success);
7791 int64_t signed_data = llvm::SignExtend64<8>(unsigned_data);
7792 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + t,
7793 (uint64_t)signed_data))
7799 // LDRSB (register) calculates an address from a base register value and an
7800 // offset register value, loadsa byte from
7801 // memory, sign-extends it to form a 32-bit word, and writes it to a register.
7802 // The offset register value can be
7803 // shifted left by 0, 1, 2, or 3 bits.
7804 bool EmulateInstructionARM::EmulateLDRSBRegister(const uint32_t opcode,
7805 const ARMEncoding encoding) {
7807 if ConditionPassed() then
7808 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
7809 offset = Shift(R[m], shift_t, shift_n, APSR.C);
7810 offset_addr = if add then (R[n] + offset) else (R[n] - offset);
7811 address = if index then offset_addr else R[n];
7812 R[t] = SignExtend(MemU[address,1], 32);
7813 if wback then R[n] = offset_addr;
7816 bool success = false;
7818 if (ConditionPassed(opcode)) {
7825 ARM_ShifterType shift_t;
7828 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
7831 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
7832 t = Bits32(opcode, 2, 0);
7833 n = Bits32(opcode, 5, 3);
7834 m = Bits32(opcode, 8, 6);
7836 // index = TRUE; add = TRUE; wback = FALSE;
7841 // (shift_t, shift_n) = (SRType_LSL, 0);
7842 shift_t = SRType_LSL;
7848 // if Rt == '1111' then SEE PLI;
7849 // if Rn == '1111' then SEE LDRSB (literal);
7850 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
7851 t = Bits32(opcode, 15, 12);
7852 n = Bits32(opcode, 19, 16);
7853 m = Bits32(opcode, 3, 0);
7855 // index = TRUE; add = TRUE; wback = FALSE;
7860 // (shift_t, shift_n) = (SRType_LSL, UInt(imm2));
7861 shift_t = SRType_LSL;
7862 shift_n = Bits32(opcode, 5, 4);
7864 // if t == 13 || BadReg(m) then UNPREDICTABLE;
7865 if ((t == 13) || BadReg(m))
7870 // if P == '0' && W == '1' then SEE LDRSBT;
7871 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
7872 t = Bits32(opcode, 15, 12);
7873 n = Bits32(opcode, 19, 16);
7874 m = Bits32(opcode, 3, 0);
7876 // index = (P == '1'); add = (U == '1'); wback = (P == '0') ||
7878 index = BitIsSet(opcode, 24);
7879 add = BitIsSet(opcode, 23);
7880 wback = BitIsClear(opcode, 24) || BitIsSet(opcode, 21);
7882 // (shift_t, shift_n) = (SRType_LSL, 0);
7883 shift_t = SRType_LSL;
7886 // if t == 15 || m == 15 then UNPREDICTABLE;
7887 if ((t == 15) || (m == 15))
7890 // if wback && (n == 15 || n == t) then UNPREDICTABLE;
7891 if (wback && ((n == 15) || (n == t)))
7900 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
7904 // offset = Shift(R[m], shift_t, shift_n, APSR.C);
7905 addr_t offset = Shift(Rm, shift_t, shift_n, APSR_C, &success);
7912 // offset_addr = if add then (R[n] + offset) else (R[n] - offset);
7914 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
7919 offset_addr = Rn + offset;
7921 offset_addr = Rn - offset;
7923 // address = if index then offset_addr else R[n];
7925 address = offset_addr;
7929 // R[t] = SignExtend(MemU[address,1], 32);
7930 RegisterInfo base_reg;
7931 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n, base_reg);
7932 RegisterInfo offset_reg;
7933 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + m, offset_reg);
7935 EmulateInstruction::Context context;
7936 context.type = eContextRegisterLoad;
7937 context.SetRegisterPlusIndirectOffset(base_reg, offset_reg);
7939 uint64_t unsigned_data = MemURead(context, address, 1, 0, &success);
7943 int64_t signed_data = llvm::SignExtend64<8>(unsigned_data);
7944 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + t,
7945 (uint64_t)signed_data))
7948 // if wback then R[n] = offset_addr;
7950 context.type = eContextAdjustBaseRegister;
7951 context.SetAddress(offset_addr);
7952 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n,
7960 // LDRSH (immediate) calculates an address from a base register value and an
7961 // immediate offset, loads a halfword from
7962 // memory, sign-extends it to form a 32-bit word, and writes it to a register.
7963 // It can use offset, post-indexed, or
7964 // pre-indexed addressing.
7965 bool EmulateInstructionARM::EmulateLDRSHImmediate(const uint32_t opcode,
7966 const ARMEncoding encoding) {
7968 if ConditionPassed() then
7969 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
7970 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
7971 address = if index then offset_addr else R[n];
7972 data = MemU[address,2];
7973 if wback then R[n] = offset_addr;
7974 if UnalignedSupport() || address<0> = '0' then
7975 R[t] = SignExtend(data, 32);
7976 else // Can only apply before ARMv7
7977 R[t] = bits(32) UNKNOWN;
7980 bool success = false;
7982 if (ConditionPassed(opcode)) {
7990 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
7993 // if Rn == '1111' then SEE LDRSH (literal);
7994 // if Rt == '1111' then SEE "Unallocated memory hints";
7995 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
7996 t = Bits32(opcode, 15, 12);
7997 n = Bits32(opcode, 19, 16);
7998 imm32 = Bits32(opcode, 11, 0);
8000 // index = TRUE; add = TRUE; wback = FALSE;
8005 // if t == 13 then UNPREDICTABLE;
8012 // if Rn == '1111' then SEE LDRSH (literal);
8013 // if Rt == '1111' && P == '1' && U == '0' && W == '0' then SEE
8014 // "Unallocated memory hints";
8015 // if P == '1' && U == '1' && W == '0' then SEE LDRSHT;
8016 // if P == '0' && W == '0' then UNDEFINED;
8017 if (BitIsClear(opcode, 10) && BitIsClear(opcode, 8))
8020 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32);
8021 t = Bits32(opcode, 15, 12);
8022 n = Bits32(opcode, 19, 16);
8023 imm32 = Bits32(opcode, 7, 0);
8025 // index = (P == '1'); add = (U == '1'); wback = (W == '1');
8026 index = BitIsSet(opcode, 10);
8027 add = BitIsSet(opcode, 9);
8028 wback = BitIsSet(opcode, 8);
8030 // if BadReg(t) || (wback && n == t) then UNPREDICTABLE;
8031 if (BadReg(t) || (wback && (n == t)))
8037 // if Rn == '1111' then SEE LDRSH (literal);
8038 // if P == '0' && W == '1' then SEE LDRSHT;
8039 // t == UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm4H:imm4L, 32);
8040 t = Bits32(opcode, 15, 12);
8041 n = Bits32(opcode, 19, 16);
8042 uint32_t imm4H = Bits32(opcode, 11, 8);
8043 uint32_t imm4L = Bits32(opcode, 3, 0);
8044 imm32 = (imm4H << 4) | imm4L;
8046 // index = (P == '1'); add = (U == '1'); wback = (P == '0') ||
8048 index = BitIsSet(opcode, 24);
8049 add = BitIsSet(opcode, 23);
8050 wback = BitIsClear(opcode, 24) || BitIsSet(opcode, 21);
8052 // if t == 15 || (wback && n == t) then UNPREDICTABLE;
8053 if ((t == 15) || (wback && (n == t)))
8063 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
8065 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
8071 offset_addr = Rn + imm32;
8073 offset_addr = Rn - imm32;
8075 // address = if index then offset_addr else R[n];
8078 address = offset_addr;
8082 // data = MemU[address,2];
8083 RegisterInfo base_reg;
8084 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n, base_reg);
8086 EmulateInstruction::Context context;
8087 context.type = eContextRegisterLoad;
8088 context.SetRegisterPlusOffset(base_reg, address - Rn);
8090 uint64_t data = MemURead(context, address, 2, 0, &success);
8094 // if wback then R[n] = offset_addr;
8096 context.type = eContextAdjustBaseRegister;
8097 context.SetAddress(offset_addr);
8098 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n,
8103 // if UnalignedSupport() || address<0> = '0' then
8104 if (UnalignedSupport() || BitIsClear(address, 0)) {
8105 // R[t] = SignExtend(data, 32);
8106 int64_t signed_data = llvm::SignExtend64<16>(data);
8107 context.type = eContextRegisterLoad;
8108 context.SetRegisterPlusOffset(base_reg, address - Rn);
8109 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + t,
8110 (uint64_t)signed_data))
8112 } else // Can only apply before ARMv7
8114 // R[t] = bits(32) UNKNOWN;
8115 WriteBits32Unknown(t);
8121 // LDRSH (literal) calculates an address from the PC value and an immediate
8122 // offset, loads a halfword from memory,
8123 // sign-extends it to from a 32-bit word, and writes it to a register.
8124 bool EmulateInstructionARM::EmulateLDRSHLiteral(const uint32_t opcode,
8125 const ARMEncoding encoding) {
8127 if ConditionPassed() then
8128 EncodingSpecificOperations(); NullCheckIfThumbEE(15);
8130 address = if add then (base + imm32) else (base - imm32);
8131 data = MemU[address,2];
8132 if UnalignedSupport() || address<0> = '0' then
8133 R[t] = SignExtend(data, 32);
8134 else // Can only apply before ARMv7
8135 R[t] = bits(32) UNKNOWN;
8138 bool success = false;
8140 if (ConditionPassed(opcode)) {
8145 // EncodingSpecificOperations(); NullCheckIfThumbEE(15);
8148 // if Rt == '1111' then SEE "Unallocated memory hints";
8149 // t = UInt(Rt); imm32 = ZeroExtend(imm12, 32); add = (U == '1');
8150 t = Bits32(opcode, 15, 12);
8151 imm32 = Bits32(opcode, 11, 0);
8152 add = BitIsSet(opcode, 23);
8154 // if t == 13 then UNPREDICTABLE;
8161 // t == UInt(Rt); imm32 = ZeroExtend(imm4H:imm4L, 32); add = (U == '1');
8162 t = Bits32(opcode, 15, 12);
8163 uint32_t imm4H = Bits32(opcode, 11, 8);
8164 uint32_t imm4L = Bits32(opcode, 3, 0);
8165 imm32 = (imm4H << 4) | imm4L;
8166 add = BitIsSet(opcode, 23);
8168 // if t == 15 then UNPREDICTABLE;
8178 // base = Align(PC,4);
8179 uint64_t pc_value = ReadCoreReg(PC_REG, &success);
8183 uint64_t base = AlignPC(pc_value);
8186 // address = if add then (base + imm32) else (base - imm32);
8188 address = base + imm32;
8190 address = base - imm32;
8192 // data = MemU[address,2];
8193 RegisterInfo base_reg;
8194 GetRegisterInfo(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, base_reg);
8196 EmulateInstruction::Context context;
8197 context.type = eContextRegisterLoad;
8198 context.SetRegisterPlusOffset(base_reg, imm32);
8200 uint64_t data = MemURead(context, address, 2, 0, &success);
8204 // if UnalignedSupport() || address<0> = '0' then
8205 if (UnalignedSupport() || BitIsClear(address, 0)) {
8206 // R[t] = SignExtend(data, 32);
8207 int64_t signed_data = llvm::SignExtend64<16>(data);
8208 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + t,
8209 (uint64_t)signed_data))
8211 } else // Can only apply before ARMv7
8213 // R[t] = bits(32) UNKNOWN;
8214 WriteBits32Unknown(t);
8220 // LDRSH (register) calculates an address from a base register value and an
8221 // offset register value, loads a halfword
8222 // from memory, sign-extends it to form a 32-bit word, and writes it to a
8223 // register. The offset register value can be
8224 // shifted left by 0, 1, 2, or 3 bits.
8225 bool EmulateInstructionARM::EmulateLDRSHRegister(const uint32_t opcode,
8226 const ARMEncoding encoding) {
8228 if ConditionPassed() then
8229 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
8230 offset = Shift(R[m], shift_t, shift_n, APSR.C);
8231 offset_addr = if add then (R[n] + offset) else (R[n] - offset);
8232 address = if index then offset_addr else R[n];
8233 data = MemU[address,2];
8234 if wback then R[n] = offset_addr;
8235 if UnalignedSupport() || address<0> = '0' then
8236 R[t] = SignExtend(data, 32);
8237 else // Can only apply before ARMv7
8238 R[t] = bits(32) UNKNOWN;
8241 bool success = false;
8243 if (ConditionPassed(opcode)) {
8250 ARM_ShifterType shift_t;
8253 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
8256 // if CurrentInstrSet() == InstrSet_ThumbEE then SEE "Modified operation
8258 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
8259 t = Bits32(opcode, 2, 0);
8260 n = Bits32(opcode, 5, 3);
8261 m = Bits32(opcode, 8, 6);
8263 // index = TRUE; add = TRUE; wback = FALSE;
8268 // (shift_t, shift_n) = (SRType_LSL, 0);
8269 shift_t = SRType_LSL;
8275 // if Rn == '1111' then SEE LDRSH (literal);
8276 // if Rt == '1111' then SEE "Unallocated memory hints";
8277 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
8278 t = Bits32(opcode, 15, 12);
8279 n = Bits32(opcode, 19, 16);
8280 m = Bits32(opcode, 3, 0);
8282 // index = TRUE; add = TRUE; wback = FALSE;
8287 // (shift_t, shift_n) = (SRType_LSL, UInt(imm2));
8288 shift_t = SRType_LSL;
8289 shift_n = Bits32(opcode, 5, 4);
8291 // if t == 13 || BadReg(m) then UNPREDICTABLE;
8292 if ((t == 13) || BadReg(m))
8298 // if P == '0' && W == '1' then SEE LDRSHT;
8299 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
8300 t = Bits32(opcode, 15, 12);
8301 n = Bits32(opcode, 19, 16);
8302 m = Bits32(opcode, 3, 0);
8304 // index = (P == '1'); add = (U == '1'); wback = (P == '0') ||
8306 index = BitIsSet(opcode, 24);
8307 add = BitIsSet(opcode, 23);
8308 wback = BitIsClear(opcode, 24) || BitIsSet(opcode, 21);
8310 // (shift_t, shift_n) = (SRType_LSL, 0);
8311 shift_t = SRType_LSL;
8314 // if t == 15 || m == 15 then UNPREDICTABLE;
8315 if ((t == 15) || (m == 15))
8318 // if wback && (n == 15 || n == t) then UNPREDICTABLE;
8319 if (wback && ((n == 15) || (n == t)))
8329 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
8334 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
8338 // offset = Shift(R[m], shift_t, shift_n, APSR.C);
8339 addr_t offset = Shift(Rm, shift_t, shift_n, APSR_C, &success);
8346 // offset_addr = if add then (R[n] + offset) else (R[n] - offset);
8348 offset_addr = Rn + offset;
8350 offset_addr = Rn - offset;
8352 // address = if index then offset_addr else R[n];
8354 address = offset_addr;
8358 // data = MemU[address,2];
8359 RegisterInfo base_reg;
8360 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n, base_reg);
8362 RegisterInfo offset_reg;
8363 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + m, offset_reg);
8365 EmulateInstruction::Context context;
8366 context.type = eContextRegisterLoad;
8367 context.SetRegisterPlusIndirectOffset(base_reg, offset_reg);
8369 uint64_t data = MemURead(context, address, 2, 0, &success);
8373 // if wback then R[n] = offset_addr;
8375 context.type = eContextAdjustBaseRegister;
8376 context.SetAddress(offset_addr);
8377 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n,
8382 // if UnalignedSupport() || address<0> = '0' then
8383 if (UnalignedSupport() || BitIsClear(address, 0)) {
8384 // R[t] = SignExtend(data, 32);
8385 context.type = eContextRegisterLoad;
8386 context.SetRegisterPlusIndirectOffset(base_reg, offset_reg);
8388 int64_t signed_data = llvm::SignExtend64<16>(data);
8389 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + t,
8390 (uint64_t)signed_data))
8392 } else // Can only apply before ARMv7
8394 // R[t] = bits(32) UNKNOWN;
8395 WriteBits32Unknown(t);
8401 // SXTB extracts an 8-bit value from a register, sign-extends it to 32 bits, and
8402 // writes the result to the destination
8403 // register. You can specifiy a rotation by 0, 8, 16, or 24 bits before
8404 // extracting the 8-bit value.
8405 bool EmulateInstructionARM::EmulateSXTB(const uint32_t opcode,
8406 const ARMEncoding encoding) {
8408 if ConditionPassed() then
8409 EncodingSpecificOperations();
8410 rotated = ROR(R[m], rotation);
8411 R[d] = SignExtend(rotated<7:0>, 32);
8414 bool success = false;
8416 if (ConditionPassed(opcode)) {
8421 // EncodingSpecificOperations();
8424 // d = UInt(Rd); m = UInt(Rm); rotation = 0;
8425 d = Bits32(opcode, 2, 0);
8426 m = Bits32(opcode, 5, 3);
8432 // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:'000');
8433 d = Bits32(opcode, 11, 8);
8434 m = Bits32(opcode, 3, 0);
8435 rotation = Bits32(opcode, 5, 4) << 3;
8437 // if BadReg(d) || BadReg(m) then UNPREDICTABLE;
8438 if (BadReg(d) || BadReg(m))
8444 // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:'000');
8445 d = Bits32(opcode, 15, 12);
8446 m = Bits32(opcode, 3, 0);
8447 rotation = Bits32(opcode, 11, 10) << 3;
8449 // if d == 15 || m == 15 then UNPREDICTABLE;
8450 if ((d == 15) || (m == 15))
8460 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
8464 // rotated = ROR(R[m], rotation);
8465 uint64_t rotated = ROR(Rm, rotation, &success);
8469 // R[d] = SignExtend(rotated<7:0>, 32);
8470 int64_t data = llvm::SignExtend64<8>(rotated);
8472 RegisterInfo source_reg;
8473 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + m, source_reg);
8475 EmulateInstruction::Context context;
8476 context.type = eContextRegisterLoad;
8477 context.SetRegister(source_reg);
8479 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + d,
8486 // SXTH extracts a 16-bit value from a register, sign-extends it to 32 bits, and
8487 // writes the result to the destination
8488 // register. You can specify a rotation by 0, 8, 16, or 24 bits before
8489 // extracting the 16-bit value.
8490 bool EmulateInstructionARM::EmulateSXTH(const uint32_t opcode,
8491 const ARMEncoding encoding) {
8493 if ConditionPassed() then
8494 EncodingSpecificOperations();
8495 rotated = ROR(R[m], rotation);
8496 R[d] = SignExtend(rotated<15:0>, 32);
8499 bool success = false;
8501 if (ConditionPassed(opcode)) {
8506 // EncodingSpecificOperations();
8509 // d = UInt(Rd); m = UInt(Rm); rotation = 0;
8510 d = Bits32(opcode, 2, 0);
8511 m = Bits32(opcode, 5, 3);
8517 // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:'000');
8518 d = Bits32(opcode, 11, 8);
8519 m = Bits32(opcode, 3, 0);
8520 rotation = Bits32(opcode, 5, 4) << 3;
8522 // if BadReg(d) || BadReg(m) then UNPREDICTABLE;
8523 if (BadReg(d) || BadReg(m))
8529 // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:'000');
8530 d = Bits32(opcode, 15, 12);
8531 m = Bits32(opcode, 3, 0);
8532 rotation = Bits32(opcode, 11, 10) << 3;
8534 // if d == 15 || m == 15 then UNPREDICTABLE;
8535 if ((d == 15) || (m == 15))
8545 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
8549 // rotated = ROR(R[m], rotation);
8550 uint64_t rotated = ROR(Rm, rotation, &success);
8554 // R[d] = SignExtend(rotated<15:0>, 32);
8555 RegisterInfo source_reg;
8556 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + m, source_reg);
8558 EmulateInstruction::Context context;
8559 context.type = eContextRegisterLoad;
8560 context.SetRegister(source_reg);
8562 int64_t data = llvm::SignExtend64<16>(rotated);
8563 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + d,
8571 // UXTB extracts an 8-bit value from a register, zero-extneds it to 32 bits, and
8572 // writes the result to the destination
8573 // register. You can specify a rotation by 0, 8, 16, or 24 bits before
8574 // extracting the 8-bit value.
8575 bool EmulateInstructionARM::EmulateUXTB(const uint32_t opcode,
8576 const ARMEncoding encoding) {
8578 if ConditionPassed() then
8579 EncodingSpecificOperations();
8580 rotated = ROR(R[m], rotation);
8581 R[d] = ZeroExtend(rotated<7:0>, 32);
8584 bool success = false;
8586 if (ConditionPassed(opcode)) {
8591 // EncodingSpecificOperations();
8594 // d = UInt(Rd); m = UInt(Rm); rotation = 0;
8595 d = Bits32(opcode, 2, 0);
8596 m = Bits32(opcode, 5, 3);
8602 // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:'000');
8603 d = Bits32(opcode, 11, 8);
8604 m = Bits32(opcode, 3, 0);
8605 rotation = Bits32(opcode, 5, 4) << 3;
8607 // if BadReg(d) || BadReg(m) then UNPREDICTABLE;
8608 if (BadReg(d) || BadReg(m))
8614 // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:'000');
8615 d = Bits32(opcode, 15, 12);
8616 m = Bits32(opcode, 3, 0);
8617 rotation = Bits32(opcode, 11, 10) << 3;
8619 // if d == 15 || m == 15 then UNPREDICTABLE;
8620 if ((d == 15) || (m == 15))
8630 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
8634 // rotated = ROR(R[m], rotation);
8635 uint64_t rotated = ROR(Rm, rotation, &success);
8639 // R[d] = ZeroExtend(rotated<7:0>, 32);
8640 RegisterInfo source_reg;
8641 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + m, source_reg);
8643 EmulateInstruction::Context context;
8644 context.type = eContextRegisterLoad;
8645 context.SetRegister(source_reg);
8647 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + d,
8648 Bits32(rotated, 7, 0)))
8654 // UXTH extracts a 16-bit value from a register, zero-extends it to 32 bits, and
8655 // writes the result to the destination
8656 // register. You can specify a rotation by 0, 8, 16, or 24 bits before
8657 // extracting the 16-bit value.
8658 bool EmulateInstructionARM::EmulateUXTH(const uint32_t opcode,
8659 const ARMEncoding encoding) {
8661 if ConditionPassed() then
8662 EncodingSpecificOperations();
8663 rotated = ROR(R[m], rotation);
8664 R[d] = ZeroExtend(rotated<15:0>, 32);
8667 bool success = false;
8669 if (ConditionPassed(opcode)) {
8676 // d = UInt(Rd); m = UInt(Rm); rotation = 0;
8677 d = Bits32(opcode, 2, 0);
8678 m = Bits32(opcode, 5, 3);
8684 // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:'000');
8685 d = Bits32(opcode, 11, 8);
8686 m = Bits32(opcode, 3, 0);
8687 rotation = Bits32(opcode, 5, 4) << 3;
8689 // if BadReg(d) || BadReg(m) then UNPREDICTABLE;
8690 if (BadReg(d) || BadReg(m))
8696 // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:'000');
8697 d = Bits32(opcode, 15, 12);
8698 m = Bits32(opcode, 3, 0);
8699 rotation = Bits32(opcode, 11, 10) << 3;
8701 // if d == 15 || m == 15 then UNPREDICTABLE;
8702 if ((d == 15) || (m == 15))
8712 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
8716 // rotated = ROR(R[m], rotation);
8717 uint64_t rotated = ROR(Rm, rotation, &success);
8721 // R[d] = ZeroExtend(rotated<15:0>, 32);
8722 RegisterInfo source_reg;
8723 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + m, source_reg);
8725 EmulateInstruction::Context context;
8726 context.type = eContextRegisterLoad;
8727 context.SetRegister(source_reg);
8729 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + d,
8730 Bits32(rotated, 15, 0)))
8736 // RFE (Return From Exception) loads the PC and the CPSR from the word at the
8737 // specified address and the following
8738 // word respectively.
8739 bool EmulateInstructionARM::EmulateRFE(const uint32_t opcode,
8740 const ARMEncoding encoding) {
8742 if ConditionPassed() then
8743 EncodingSpecificOperations();
8744 if !CurrentModeIsPrivileged() || CurrentInstrSet() == InstrSet_ThumbEE then
8747 address = if increment then R[n] else R[n]-8;
8748 if wordhigher then address = address+4;
8749 CPSRWriteByInstr(MemA[address+4,4], '1111', TRUE);
8750 BranchWritePC(MemA[address,4]);
8751 if wback then R[n] = if increment then R[n]+8 else R[n]-8;
8754 bool success = false;
8756 if (ConditionPassed(opcode)) {
8762 // EncodingSpecificOperations();
8765 // n = UInt(Rn); wback = (W == '1'); increment = FALSE; wordhigher =
8767 n = Bits32(opcode, 19, 16);
8768 wback = BitIsSet(opcode, 21);
8772 // if n == 15 then UNPREDICTABLE;
8776 // if InITBlock() && !LastInITBlock() then UNPREDICTABLE;
8777 if (InITBlock() && !LastInITBlock())
8783 // n = UInt(Rn); wback = (W == '1'); increment = TRUE; wordhigher = FALSE;
8784 n = Bits32(opcode, 19, 16);
8785 wback = BitIsSet(opcode, 21);
8789 // if n == 15 then UNPREDICTABLE;
8793 // if InITBlock() && !LastInITBlock() then UNPREDICTABLE;
8794 if (InITBlock() && !LastInITBlock())
8801 n = Bits32(opcode, 19, 16);
8803 // wback = (W == '1'); inc = (U == '1'); wordhigher = (P == U);
8804 wback = BitIsSet(opcode, 21);
8805 increment = BitIsSet(opcode, 23);
8806 wordhigher = (Bit32(opcode, 24) == Bit32(opcode, 23));
8808 // if n == 15 then UNPREDICTABLE;
8818 // if !CurrentModeIsPrivileged() || CurrentInstrSet() == InstrSet_ThumbEE
8820 if (!CurrentModeIsPrivileged())
8825 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
8830 // address = if increment then R[n] else R[n]-8;
8836 // if wordhigher then address = address+4;
8838 address = address + 4;
8840 // CPSRWriteByInstr(MemA[address+4,4], '1111', TRUE);
8841 RegisterInfo base_reg;
8842 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n, base_reg);
8844 EmulateInstruction::Context context;
8845 context.type = eContextReturnFromException;
8846 context.SetRegisterPlusOffset(base_reg, address - Rn);
8848 uint64_t data = MemARead(context, address + 4, 4, 0, &success);
8852 CPSRWriteByInstr(data, 15, true);
8854 // BranchWritePC(MemA[address,4]);
8855 uint64_t data2 = MemARead(context, address, 4, 0, &success);
8859 BranchWritePC(context, data2);
8861 // if wback then R[n] = if increment then R[n]+8 else R[n]-8;
8863 context.type = eContextAdjustBaseRegister;
8865 context.SetOffset(8);
8866 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n,
8870 context.SetOffset(-8);
8871 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n,
8877 } // if ConditionPassed()
8881 // Bitwise Exclusive OR (immediate) performs a bitwise exclusive OR of a
8882 // register value and an immediate value,
8883 // and writes the result to the destination register. It can optionally update
8884 // the condition flags based on
8886 bool EmulateInstructionARM::EmulateEORImm(const uint32_t opcode,
8887 const ARMEncoding encoding) {
8889 // ARM pseudo code...
8890 if ConditionPassed() then
8891 EncodingSpecificOperations();
8892 result = R[n] EOR imm32;
8893 if d == 15 then // Can only occur for ARM encoding
8894 ALUWritePC(result); // setflags is always FALSE here
8898 APSR.N = result<31>;
8899 APSR.Z = IsZeroBit(result);
8904 bool success = false;
8906 if (ConditionPassed(opcode)) {
8909 imm32; // the immediate value to be ORed to the value obtained from Rn
8911 uint32_t carry; // the carry bit after ARM/Thumb Expand operation
8914 Rd = Bits32(opcode, 11, 8);
8915 Rn = Bits32(opcode, 19, 16);
8916 setflags = BitIsSet(opcode, 20);
8917 imm32 = ThumbExpandImm_C(
8919 carry); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C)
8920 // if Rd == '1111' && S == '1' then SEE TEQ (immediate);
8921 if (Rd == 15 && setflags)
8922 return EmulateTEQImm(opcode, eEncodingT1);
8923 if (Rd == 13 || (Rd == 15 && !setflags) || BadReg(Rn))
8927 Rd = Bits32(opcode, 15, 12);
8928 Rn = Bits32(opcode, 19, 16);
8929 setflags = BitIsSet(opcode, 20);
8931 ARMExpandImm_C(opcode, APSR_C,
8932 carry); // (imm32, carry) = ARMExpandImm(imm12, APSR.C)
8934 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related
8936 if (Rd == 15 && setflags)
8937 return EmulateSUBSPcLrEtc(opcode, encoding);
8943 // Read the first operand.
8944 uint32_t val1 = ReadCoreReg(Rn, &success);
8948 uint32_t result = val1 ^ imm32;
8950 EmulateInstruction::Context context;
8951 context.type = EmulateInstruction::eContextImmediate;
8952 context.SetNoArgs();
8954 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
8960 // Bitwise Exclusive OR (register) performs a bitwise exclusive OR of a register
8962 // optionally-shifted register value, and writes the result to the destination
8964 // It can optionally update the condition flags based on the result.
8965 bool EmulateInstructionARM::EmulateEORReg(const uint32_t opcode,
8966 const ARMEncoding encoding) {
8968 // ARM pseudo code...
8969 if ConditionPassed() then
8970 EncodingSpecificOperations();
8971 (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C);
8972 result = R[n] EOR shifted;
8973 if d == 15 then // Can only occur for ARM encoding
8974 ALUWritePC(result); // setflags is always FALSE here
8978 APSR.N = result<31>;
8979 APSR.Z = IsZeroBit(result);
8984 bool success = false;
8986 if (ConditionPassed(opcode)) {
8987 uint32_t Rd, Rn, Rm;
8988 ARM_ShifterType shift_t;
8989 uint32_t shift_n; // the shift applied to the value read from Rm
8994 Rd = Rn = Bits32(opcode, 2, 0);
8995 Rm = Bits32(opcode, 5, 3);
8996 setflags = !InITBlock();
8997 shift_t = SRType_LSL;
9001 Rd = Bits32(opcode, 11, 8);
9002 Rn = Bits32(opcode, 19, 16);
9003 Rm = Bits32(opcode, 3, 0);
9004 setflags = BitIsSet(opcode, 20);
9005 shift_n = DecodeImmShiftThumb(opcode, shift_t);
9006 // if Rd == '1111' && S == '1' then SEE TEQ (register);
9007 if (Rd == 15 && setflags)
9008 return EmulateTEQReg(opcode, eEncodingT1);
9009 if (Rd == 13 || (Rd == 15 && !setflags) || BadReg(Rn) || BadReg(Rm))
9013 Rd = Bits32(opcode, 15, 12);
9014 Rn = Bits32(opcode, 19, 16);
9015 Rm = Bits32(opcode, 3, 0);
9016 setflags = BitIsSet(opcode, 20);
9017 shift_n = DecodeImmShiftARM(opcode, shift_t);
9019 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related
9021 if (Rd == 15 && setflags)
9022 return EmulateSUBSPcLrEtc(opcode, encoding);
9028 // Read the first operand.
9029 uint32_t val1 = ReadCoreReg(Rn, &success);
9033 // Read the second operand.
9034 uint32_t val2 = ReadCoreReg(Rm, &success);
9038 uint32_t shifted = Shift_C(val2, shift_t, shift_n, APSR_C, carry, &success);
9041 uint32_t result = val1 ^ shifted;
9043 EmulateInstruction::Context context;
9044 context.type = EmulateInstruction::eContextImmediate;
9045 context.SetNoArgs();
9047 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
9053 // Bitwise OR (immediate) performs a bitwise (inclusive) OR of a register value
9054 // and an immediate value, and
9055 // writes the result to the destination register. It can optionally update the
9056 // condition flags based
9058 bool EmulateInstructionARM::EmulateORRImm(const uint32_t opcode,
9059 const ARMEncoding encoding) {
9061 // ARM pseudo code...
9062 if ConditionPassed() then
9063 EncodingSpecificOperations();
9064 result = R[n] OR imm32;
9065 if d == 15 then // Can only occur for ARM encoding
9066 ALUWritePC(result); // setflags is always FALSE here
9070 APSR.N = result<31>;
9071 APSR.Z = IsZeroBit(result);
9076 bool success = false;
9078 if (ConditionPassed(opcode)) {
9081 imm32; // the immediate value to be ORed to the value obtained from Rn
9083 uint32_t carry; // the carry bit after ARM/Thumb Expand operation
9086 Rd = Bits32(opcode, 11, 8);
9087 Rn = Bits32(opcode, 19, 16);
9088 setflags = BitIsSet(opcode, 20);
9089 imm32 = ThumbExpandImm_C(
9091 carry); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C)
9092 // if Rn == '1111' then SEE MOV (immediate);
9094 return EmulateMOVRdImm(opcode, eEncodingT2);
9095 if (BadReg(Rd) || Rn == 13)
9099 Rd = Bits32(opcode, 15, 12);
9100 Rn = Bits32(opcode, 19, 16);
9101 setflags = BitIsSet(opcode, 20);
9103 ARMExpandImm_C(opcode, APSR_C,
9104 carry); // (imm32, carry) = ARMExpandImm(imm12, APSR.C)
9106 if (Rd == 15 && setflags)
9107 return EmulateSUBSPcLrEtc(opcode, encoding);
9113 // Read the first operand.
9114 uint32_t val1 = ReadCoreReg(Rn, &success);
9118 uint32_t result = val1 | imm32;
9120 EmulateInstruction::Context context;
9121 context.type = EmulateInstruction::eContextImmediate;
9122 context.SetNoArgs();
9124 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
9130 // Bitwise OR (register) performs a bitwise (inclusive) OR of a register value
9131 // and an optionally-shifted register
9132 // value, and writes the result to the destination register. It can optionally
9133 // update the condition flags based
9135 bool EmulateInstructionARM::EmulateORRReg(const uint32_t opcode,
9136 const ARMEncoding encoding) {
9138 // ARM pseudo code...
9139 if ConditionPassed() then
9140 EncodingSpecificOperations();
9141 (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C);
9142 result = R[n] OR shifted;
9143 if d == 15 then // Can only occur for ARM encoding
9144 ALUWritePC(result); // setflags is always FALSE here
9148 APSR.N = result<31>;
9149 APSR.Z = IsZeroBit(result);
9154 bool success = false;
9156 if (ConditionPassed(opcode)) {
9157 uint32_t Rd, Rn, Rm;
9158 ARM_ShifterType shift_t;
9159 uint32_t shift_n; // the shift applied to the value read from Rm
9164 Rd = Rn = Bits32(opcode, 2, 0);
9165 Rm = Bits32(opcode, 5, 3);
9166 setflags = !InITBlock();
9167 shift_t = SRType_LSL;
9171 Rd = Bits32(opcode, 11, 8);
9172 Rn = Bits32(opcode, 19, 16);
9173 Rm = Bits32(opcode, 3, 0);
9174 setflags = BitIsSet(opcode, 20);
9175 shift_n = DecodeImmShiftThumb(opcode, shift_t);
9176 // if Rn == '1111' then SEE MOV (register);
9178 return EmulateMOVRdRm(opcode, eEncodingT3);
9179 if (BadReg(Rd) || Rn == 13 || BadReg(Rm))
9183 Rd = Bits32(opcode, 15, 12);
9184 Rn = Bits32(opcode, 19, 16);
9185 Rm = Bits32(opcode, 3, 0);
9186 setflags = BitIsSet(opcode, 20);
9187 shift_n = DecodeImmShiftARM(opcode, shift_t);
9189 if (Rd == 15 && setflags)
9190 return EmulateSUBSPcLrEtc(opcode, encoding);
9196 // Read the first operand.
9197 uint32_t val1 = ReadCoreReg(Rn, &success);
9201 // Read the second operand.
9202 uint32_t val2 = ReadCoreReg(Rm, &success);
9206 uint32_t shifted = Shift_C(val2, shift_t, shift_n, APSR_C, carry, &success);
9209 uint32_t result = val1 | shifted;
9211 EmulateInstruction::Context context;
9212 context.type = EmulateInstruction::eContextImmediate;
9213 context.SetNoArgs();
9215 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
9221 // Reverse Subtract (immediate) subtracts a register value from an immediate
9222 // value, and writes the result to
9223 // the destination register. It can optionally update the condition flags based
9225 bool EmulateInstructionARM::EmulateRSBImm(const uint32_t opcode,
9226 const ARMEncoding encoding) {
9228 // ARM pseudo code...
9229 if ConditionPassed() then
9230 EncodingSpecificOperations();
9231 (result, carry, overflow) = AddWithCarry(NOT(R[n]), imm32, '1');
9232 if d == 15 then // Can only occur for ARM encoding
9233 ALUWritePC(result); // setflags is always FALSE here
9237 APSR.N = result<31>;
9238 APSR.Z = IsZeroBit(result);
9243 bool success = false;
9245 uint32_t Rd; // the destination register
9246 uint32_t Rn; // the first operand
9249 imm32; // the immediate value to be added to the value obtained from Rn
9252 Rd = Bits32(opcode, 2, 0);
9253 Rn = Bits32(opcode, 5, 3);
9254 setflags = !InITBlock();
9258 Rd = Bits32(opcode, 11, 8);
9259 Rn = Bits32(opcode, 19, 16);
9260 setflags = BitIsSet(opcode, 20);
9261 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8)
9262 if (BadReg(Rd) || BadReg(Rn))
9266 Rd = Bits32(opcode, 15, 12);
9267 Rn = Bits32(opcode, 19, 16);
9268 setflags = BitIsSet(opcode, 20);
9269 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
9271 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related
9273 if (Rd == 15 && setflags)
9274 return EmulateSUBSPcLrEtc(opcode, encoding);
9279 // Read the register value from the operand register Rn.
9280 uint32_t reg_val = ReadCoreReg(Rn, &success);
9284 AddWithCarryResult res = AddWithCarry(~reg_val, imm32, 1);
9286 EmulateInstruction::Context context;
9287 context.type = EmulateInstruction::eContextImmediate;
9288 context.SetNoArgs();
9290 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags,
9291 res.carry_out, res.overflow))
9297 // Reverse Subtract (register) subtracts a register value from an
9298 // optionally-shifted register value, and writes the
9299 // result to the destination register. It can optionally update the condition
9300 // flags based on the result.
9301 bool EmulateInstructionARM::EmulateRSBReg(const uint32_t opcode,
9302 const ARMEncoding encoding) {
9304 // ARM pseudo code...
9305 if ConditionPassed() then
9306 EncodingSpecificOperations();
9307 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
9308 (result, carry, overflow) = AddWithCarry(NOT(R[n]), shifted, '1');
9309 if d == 15 then // Can only occur for ARM encoding
9310 ALUWritePC(result); // setflags is always FALSE here
9314 APSR.N = result<31>;
9315 APSR.Z = IsZeroBit(result);
9320 bool success = false;
9322 uint32_t Rd; // the destination register
9323 uint32_t Rn; // the first operand
9324 uint32_t Rm; // the second operand
9326 ARM_ShifterType shift_t;
9327 uint32_t shift_n; // the shift applied to the value read from Rm
9330 Rd = Bits32(opcode, 11, 8);
9331 Rn = Bits32(opcode, 19, 16);
9332 Rm = Bits32(opcode, 3, 0);
9333 setflags = BitIsSet(opcode, 20);
9334 shift_n = DecodeImmShiftThumb(opcode, shift_t);
9335 // if (BadReg(d) || BadReg(m)) then UNPREDICTABLE;
9336 if (BadReg(Rd) || BadReg(Rn) || BadReg(Rm))
9340 Rd = Bits32(opcode, 15, 12);
9341 Rn = Bits32(opcode, 19, 16);
9342 Rm = Bits32(opcode, 3, 0);
9343 setflags = BitIsSet(opcode, 20);
9344 shift_n = DecodeImmShiftARM(opcode, shift_t);
9346 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related
9348 if (Rd == 15 && setflags)
9349 return EmulateSUBSPcLrEtc(opcode, encoding);
9354 // Read the register value from register Rn.
9355 uint32_t val1 = ReadCoreReg(Rn, &success);
9359 // Read the register value from register Rm.
9360 uint32_t val2 = ReadCoreReg(Rm, &success);
9364 uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C, &success);
9367 AddWithCarryResult res = AddWithCarry(~val1, shifted, 1);
9369 EmulateInstruction::Context context;
9370 context.type = EmulateInstruction::eContextImmediate;
9371 context.SetNoArgs();
9372 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags,
9373 res.carry_out, res.overflow))
9379 // Reverse Subtract with Carry (immediate) subtracts a register value and the
9380 // value of NOT (Carry flag) from
9381 // an immediate value, and writes the result to the destination register. It can
9382 // optionally update the condition
9383 // flags based on the result.
9384 bool EmulateInstructionARM::EmulateRSCImm(const uint32_t opcode,
9385 const ARMEncoding encoding) {
9387 // ARM pseudo code...
9388 if ConditionPassed() then
9389 EncodingSpecificOperations();
9390 (result, carry, overflow) = AddWithCarry(NOT(R[n]), imm32, APSR.C);
9392 ALUWritePC(result); // setflags is always FALSE here
9396 APSR.N = result<31>;
9397 APSR.Z = IsZeroBit(result);
9402 bool success = false;
9404 uint32_t Rd; // the destination register
9405 uint32_t Rn; // the first operand
9408 imm32; // the immediate value to be added to the value obtained from Rn
9411 Rd = Bits32(opcode, 15, 12);
9412 Rn = Bits32(opcode, 19, 16);
9413 setflags = BitIsSet(opcode, 20);
9414 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
9416 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related
9418 if (Rd == 15 && setflags)
9419 return EmulateSUBSPcLrEtc(opcode, encoding);
9424 // Read the register value from the operand register Rn.
9425 uint32_t reg_val = ReadCoreReg(Rn, &success);
9429 AddWithCarryResult res = AddWithCarry(~reg_val, imm32, APSR_C);
9431 EmulateInstruction::Context context;
9432 context.type = EmulateInstruction::eContextImmediate;
9433 context.SetNoArgs();
9435 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags,
9436 res.carry_out, res.overflow))
9442 // Reverse Subtract with Carry (register) subtracts a register value and the
9443 // value of NOT (Carry flag) from an
9444 // optionally-shifted register value, and writes the result to the destination
9445 // register. It can optionally update the
9446 // condition flags based on the result.
9447 bool EmulateInstructionARM::EmulateRSCReg(const uint32_t opcode,
9448 const ARMEncoding encoding) {
9450 // ARM pseudo code...
9451 if ConditionPassed() then
9452 EncodingSpecificOperations();
9453 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
9454 (result, carry, overflow) = AddWithCarry(NOT(R[n]), shifted, APSR.C);
9456 ALUWritePC(result); // setflags is always FALSE here
9460 APSR.N = result<31>;
9461 APSR.Z = IsZeroBit(result);
9466 bool success = false;
9468 uint32_t Rd; // the destination register
9469 uint32_t Rn; // the first operand
9470 uint32_t Rm; // the second operand
9472 ARM_ShifterType shift_t;
9473 uint32_t shift_n; // the shift applied to the value read from Rm
9476 Rd = Bits32(opcode, 15, 12);
9477 Rn = Bits32(opcode, 19, 16);
9478 Rm = Bits32(opcode, 3, 0);
9479 setflags = BitIsSet(opcode, 20);
9480 shift_n = DecodeImmShiftARM(opcode, shift_t);
9482 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related
9484 if (Rd == 15 && setflags)
9485 return EmulateSUBSPcLrEtc(opcode, encoding);
9490 // Read the register value from register Rn.
9491 uint32_t val1 = ReadCoreReg(Rn, &success);
9495 // Read the register value from register Rm.
9496 uint32_t val2 = ReadCoreReg(Rm, &success);
9500 uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C, &success);
9503 AddWithCarryResult res = AddWithCarry(~val1, shifted, APSR_C);
9505 EmulateInstruction::Context context;
9506 context.type = EmulateInstruction::eContextImmediate;
9507 context.SetNoArgs();
9508 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags,
9509 res.carry_out, res.overflow))
9515 // Subtract with Carry (immediate) subtracts an immediate value and the value of
9516 // NOT (Carry flag) from a register value, and writes the result to the
9517 // destination register.
9518 // It can optionally update the condition flags based on the result.
9519 bool EmulateInstructionARM::EmulateSBCImm(const uint32_t opcode,
9520 const ARMEncoding encoding) {
9522 // ARM pseudo code...
9523 if ConditionPassed() then
9524 EncodingSpecificOperations();
9525 (result, carry, overflow) = AddWithCarry(R[n], NOT(imm32), APSR.C);
9526 if d == 15 then // Can only occur for ARM encoding
9527 ALUWritePC(result); // setflags is always FALSE here
9531 APSR.N = result<31>;
9532 APSR.Z = IsZeroBit(result);
9537 bool success = false;
9539 uint32_t Rd; // the destination register
9540 uint32_t Rn; // the first operand
9543 imm32; // the immediate value to be added to the value obtained from Rn
9546 Rd = Bits32(opcode, 11, 8);
9547 Rn = Bits32(opcode, 19, 16);
9548 setflags = BitIsSet(opcode, 20);
9549 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8)
9550 if (BadReg(Rd) || BadReg(Rn))
9554 Rd = Bits32(opcode, 15, 12);
9555 Rn = Bits32(opcode, 19, 16);
9556 setflags = BitIsSet(opcode, 20);
9557 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
9559 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related
9561 if (Rd == 15 && setflags)
9562 return EmulateSUBSPcLrEtc(opcode, encoding);
9567 // Read the register value from the operand register Rn.
9568 uint32_t reg_val = ReadCoreReg(Rn, &success);
9572 AddWithCarryResult res = AddWithCarry(reg_val, ~imm32, APSR_C);
9574 EmulateInstruction::Context context;
9575 context.type = EmulateInstruction::eContextImmediate;
9576 context.SetNoArgs();
9578 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags,
9579 res.carry_out, res.overflow))
9585 // Subtract with Carry (register) subtracts an optionally-shifted register value
9587 // NOT (Carry flag) from a register value, and writes the result to the
9588 // destination register.
9589 // It can optionally update the condition flags based on the result.
9590 bool EmulateInstructionARM::EmulateSBCReg(const uint32_t opcode,
9591 const ARMEncoding encoding) {
9593 // ARM pseudo code...
9594 if ConditionPassed() then
9595 EncodingSpecificOperations();
9596 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
9597 (result, carry, overflow) = AddWithCarry(R[n], NOT(shifted), APSR.C);
9598 if d == 15 then // Can only occur for ARM encoding
9599 ALUWritePC(result); // setflags is always FALSE here
9603 APSR.N = result<31>;
9604 APSR.Z = IsZeroBit(result);
9609 bool success = false;
9611 uint32_t Rd; // the destination register
9612 uint32_t Rn; // the first operand
9613 uint32_t Rm; // the second operand
9615 ARM_ShifterType shift_t;
9616 uint32_t shift_n; // the shift applied to the value read from Rm
9619 Rd = Rn = Bits32(opcode, 2, 0);
9620 Rm = Bits32(opcode, 5, 3);
9621 setflags = !InITBlock();
9622 shift_t = SRType_LSL;
9626 Rd = Bits32(opcode, 11, 8);
9627 Rn = Bits32(opcode, 19, 16);
9628 Rm = Bits32(opcode, 3, 0);
9629 setflags = BitIsSet(opcode, 20);
9630 shift_n = DecodeImmShiftThumb(opcode, shift_t);
9631 if (BadReg(Rd) || BadReg(Rn) || BadReg(Rm))
9635 Rd = Bits32(opcode, 15, 12);
9636 Rn = Bits32(opcode, 19, 16);
9637 Rm = Bits32(opcode, 3, 0);
9638 setflags = BitIsSet(opcode, 20);
9639 shift_n = DecodeImmShiftARM(opcode, shift_t);
9641 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related
9643 if (Rd == 15 && setflags)
9644 return EmulateSUBSPcLrEtc(opcode, encoding);
9649 // Read the register value from register Rn.
9650 uint32_t val1 = ReadCoreReg(Rn, &success);
9654 // Read the register value from register Rm.
9655 uint32_t val2 = ReadCoreReg(Rm, &success);
9659 uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C, &success);
9662 AddWithCarryResult res = AddWithCarry(val1, ~shifted, APSR_C);
9664 EmulateInstruction::Context context;
9665 context.type = EmulateInstruction::eContextImmediate;
9666 context.SetNoArgs();
9667 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags,
9668 res.carry_out, res.overflow))
9674 // This instruction subtracts an immediate value from a register value, and
9675 // writes the result
9676 // to the destination register. It can optionally update the condition flags
9677 // based on the result.
9678 bool EmulateInstructionARM::EmulateSUBImmThumb(const uint32_t opcode,
9679 const ARMEncoding encoding) {
9681 // ARM pseudo code...
9682 if ConditionPassed() then
9683 EncodingSpecificOperations();
9684 (result, carry, overflow) = AddWithCarry(R[n], NOT(imm32), '1');
9687 APSR.N = result<31>;
9688 APSR.Z = IsZeroBit(result);
9693 bool success = false;
9695 uint32_t Rd; // the destination register
9696 uint32_t Rn; // the first operand
9698 uint32_t imm32; // the immediate value to be subtracted from the value
9702 Rd = Bits32(opcode, 2, 0);
9703 Rn = Bits32(opcode, 5, 3);
9704 setflags = !InITBlock();
9705 imm32 = Bits32(opcode, 8, 6); // imm32 = ZeroExtend(imm3, 32)
9708 Rd = Rn = Bits32(opcode, 10, 8);
9709 setflags = !InITBlock();
9710 imm32 = Bits32(opcode, 7, 0); // imm32 = ZeroExtend(imm8, 32)
9713 Rd = Bits32(opcode, 11, 8);
9714 Rn = Bits32(opcode, 19, 16);
9715 setflags = BitIsSet(opcode, 20);
9716 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8)
9718 // if Rd == '1111' && S == '1' then SEE CMP (immediate);
9719 if (Rd == 15 && setflags)
9720 return EmulateCMPImm(opcode, eEncodingT2);
9722 // if Rn == '1101' then SEE SUB (SP minus immediate);
9724 return EmulateSUBSPImm(opcode, eEncodingT2);
9726 // if d == 13 || (d == 15 && S == '0') || n == 15 then UNPREDICTABLE;
9727 if (Rd == 13 || (Rd == 15 && !setflags) || Rn == 15)
9731 Rd = Bits32(opcode, 11, 8);
9732 Rn = Bits32(opcode, 19, 16);
9733 setflags = BitIsSet(opcode, 20);
9734 imm32 = ThumbImm12(opcode); // imm32 = ZeroExtend(i:imm3:imm8, 32)
9736 // if Rn == '1111' then SEE ADR;
9738 return EmulateADR(opcode, eEncodingT2);
9740 // if Rn == '1101' then SEE SUB (SP minus immediate);
9742 return EmulateSUBSPImm(opcode, eEncodingT3);
9750 // Read the register value from the operand register Rn.
9751 uint32_t reg_val = ReadCoreReg(Rn, &success);
9755 AddWithCarryResult res = AddWithCarry(reg_val, ~imm32, 1);
9757 EmulateInstruction::Context context;
9758 context.type = EmulateInstruction::eContextImmediate;
9759 context.SetNoArgs();
9761 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags,
9762 res.carry_out, res.overflow))
9768 // This instruction subtracts an immediate value from a register value, and
9769 // writes the result
9770 // to the destination register. It can optionally update the condition flags
9771 // based on the result.
9772 bool EmulateInstructionARM::EmulateSUBImmARM(const uint32_t opcode,
9773 const ARMEncoding encoding) {
9775 // ARM pseudo code...
9776 if ConditionPassed() then
9777 EncodingSpecificOperations();
9778 (result, carry, overflow) = AddWithCarry(R[n], NOT(imm32), '1');
9780 ALUWritePC(result); // setflags is always FALSE here
9784 APSR.N = result<31>;
9785 APSR.Z = IsZeroBit(result);
9790 bool success = false;
9792 if (ConditionPassed(opcode)) {
9793 uint32_t Rd; // the destination register
9794 uint32_t Rn; // the first operand
9796 uint32_t imm32; // the immediate value to be subtracted from the value
9800 Rd = Bits32(opcode, 15, 12);
9801 Rn = Bits32(opcode, 19, 16);
9802 setflags = BitIsSet(opcode, 20);
9803 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
9805 // if Rn == '1111' && S == '0' then SEE ADR;
9806 if (Rn == 15 && !setflags)
9807 return EmulateADR(opcode, eEncodingA2);
9809 // if Rn == '1101' then SEE SUB (SP minus immediate);
9811 return EmulateSUBSPImm(opcode, eEncodingA1);
9813 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related
9815 if (Rd == 15 && setflags)
9816 return EmulateSUBSPcLrEtc(opcode, encoding);
9821 // Read the register value from the operand register Rn.
9822 uint32_t reg_val = ReadCoreReg(Rn, &success);
9826 AddWithCarryResult res = AddWithCarry(reg_val, ~imm32, 1);
9828 EmulateInstruction::Context context;
9830 context.type = EmulateInstruction::eContextAdjustStackPointer;
9832 context.type = EmulateInstruction::eContextRegisterPlusOffset;
9834 RegisterInfo dwarf_reg;
9835 GetRegisterInfo(eRegisterKindDWARF, Rn, dwarf_reg);
9836 int64_t imm32_signed = imm32;
9837 context.SetRegisterPlusOffset(dwarf_reg, -imm32_signed);
9839 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags,
9840 res.carry_out, res.overflow))
9846 // Test Equivalence (immediate) performs a bitwise exclusive OR operation on a
9847 // register value and an
9848 // immediate value. It updates the condition flags based on the result, and
9849 // discards the result.
9850 bool EmulateInstructionARM::EmulateTEQImm(const uint32_t opcode,
9851 const ARMEncoding encoding) {
9853 // ARM pseudo code...
9854 if ConditionPassed() then
9855 EncodingSpecificOperations();
9856 result = R[n] EOR imm32;
9857 APSR.N = result<31>;
9858 APSR.Z = IsZeroBit(result);
9863 bool success = false;
9865 if (ConditionPassed(opcode)) {
9868 imm32; // the immediate value to be ANDed to the value obtained from Rn
9869 uint32_t carry; // the carry bit after ARM/Thumb Expand operation
9872 Rn = Bits32(opcode, 19, 16);
9873 imm32 = ThumbExpandImm_C(
9875 carry); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C)
9880 Rn = Bits32(opcode, 19, 16);
9882 ARMExpandImm_C(opcode, APSR_C,
9883 carry); // (imm32, carry) = ARMExpandImm(imm12, APSR.C)
9889 // Read the first operand.
9890 uint32_t val1 = ReadCoreReg(Rn, &success);
9894 uint32_t result = val1 ^ imm32;
9896 EmulateInstruction::Context context;
9897 context.type = EmulateInstruction::eContextImmediate;
9898 context.SetNoArgs();
9900 if (!WriteFlags(context, result, carry))
9906 // Test Equivalence (register) performs a bitwise exclusive OR operation on a
9907 // register value and an
9908 // optionally-shifted register value. It updates the condition flags based on
9909 // the result, and discards
9911 bool EmulateInstructionARM::EmulateTEQReg(const uint32_t opcode,
9912 const ARMEncoding encoding) {
9914 // ARM pseudo code...
9915 if ConditionPassed() then
9916 EncodingSpecificOperations();
9917 (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C);
9918 result = R[n] EOR shifted;
9919 APSR.N = result<31>;
9920 APSR.Z = IsZeroBit(result);
9925 bool success = false;
9927 if (ConditionPassed(opcode)) {
9929 ARM_ShifterType shift_t;
9930 uint32_t shift_n; // the shift applied to the value read from Rm
9934 Rn = Bits32(opcode, 19, 16);
9935 Rm = Bits32(opcode, 3, 0);
9936 shift_n = DecodeImmShiftThumb(opcode, shift_t);
9937 if (BadReg(Rn) || BadReg(Rm))
9941 Rn = Bits32(opcode, 19, 16);
9942 Rm = Bits32(opcode, 3, 0);
9943 shift_n = DecodeImmShiftARM(opcode, shift_t);
9949 // Read the first operand.
9950 uint32_t val1 = ReadCoreReg(Rn, &success);
9954 // Read the second operand.
9955 uint32_t val2 = ReadCoreReg(Rm, &success);
9959 uint32_t shifted = Shift_C(val2, shift_t, shift_n, APSR_C, carry, &success);
9962 uint32_t result = val1 ^ shifted;
9964 EmulateInstruction::Context context;
9965 context.type = EmulateInstruction::eContextImmediate;
9966 context.SetNoArgs();
9968 if (!WriteFlags(context, result, carry))
9974 // Test (immediate) performs a bitwise AND operation on a register value and an
9976 // It updates the condition flags based on the result, and discards the result.
9977 bool EmulateInstructionARM::EmulateTSTImm(const uint32_t opcode,
9978 const ARMEncoding encoding) {
9980 // ARM pseudo code...
9981 if ConditionPassed() then
9982 EncodingSpecificOperations();
9983 result = R[n] AND imm32;
9984 APSR.N = result<31>;
9985 APSR.Z = IsZeroBit(result);
9990 bool success = false;
9992 if (ConditionPassed(opcode)) {
9995 imm32; // the immediate value to be ANDed to the value obtained from Rn
9996 uint32_t carry; // the carry bit after ARM/Thumb Expand operation
9999 Rn = Bits32(opcode, 19, 16);
10000 imm32 = ThumbExpandImm_C(
10002 carry); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C)
10007 Rn = Bits32(opcode, 19, 16);
10009 ARMExpandImm_C(opcode, APSR_C,
10010 carry); // (imm32, carry) = ARMExpandImm(imm12, APSR.C)
10016 // Read the first operand.
10017 uint32_t val1 = ReadCoreReg(Rn, &success);
10021 uint32_t result = val1 & imm32;
10023 EmulateInstruction::Context context;
10024 context.type = EmulateInstruction::eContextImmediate;
10025 context.SetNoArgs();
10027 if (!WriteFlags(context, result, carry))
10033 // Test (register) performs a bitwise AND operation on a register value and an
10034 // optionally-shifted register value.
10035 // It updates the condition flags based on the result, and discards the result.
10036 bool EmulateInstructionARM::EmulateTSTReg(const uint32_t opcode,
10037 const ARMEncoding encoding) {
10039 // ARM pseudo code...
10040 if ConditionPassed() then
10041 EncodingSpecificOperations();
10042 (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C);
10043 result = R[n] AND shifted;
10044 APSR.N = result<31>;
10045 APSR.Z = IsZeroBit(result);
10047 // APSR.V unchanged
10050 bool success = false;
10052 if (ConditionPassed(opcode)) {
10054 ARM_ShifterType shift_t;
10055 uint32_t shift_n; // the shift applied to the value read from Rm
10057 switch (encoding) {
10059 Rn = Bits32(opcode, 2, 0);
10060 Rm = Bits32(opcode, 5, 3);
10061 shift_t = SRType_LSL;
10065 Rn = Bits32(opcode, 19, 16);
10066 Rm = Bits32(opcode, 3, 0);
10067 shift_n = DecodeImmShiftThumb(opcode, shift_t);
10068 if (BadReg(Rn) || BadReg(Rm))
10072 Rn = Bits32(opcode, 19, 16);
10073 Rm = Bits32(opcode, 3, 0);
10074 shift_n = DecodeImmShiftARM(opcode, shift_t);
10080 // Read the first operand.
10081 uint32_t val1 = ReadCoreReg(Rn, &success);
10085 // Read the second operand.
10086 uint32_t val2 = ReadCoreReg(Rm, &success);
10090 uint32_t shifted = Shift_C(val2, shift_t, shift_n, APSR_C, carry, &success);
10093 uint32_t result = val1 & shifted;
10095 EmulateInstruction::Context context;
10096 context.type = EmulateInstruction::eContextImmediate;
10097 context.SetNoArgs();
10099 if (!WriteFlags(context, result, carry))
10105 // A8.6.216 SUB (SP minus register)
10106 bool EmulateInstructionARM::EmulateSUBSPReg(const uint32_t opcode,
10107 const ARMEncoding encoding) {
10109 if ConditionPassed() then
10110 EncodingSpecificOperations();
10111 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
10112 (result, carry, overflow) = AddWithCarry(SP, NOT(shifted), '1');
10113 if d == 15 then // Can only occur for ARM encoding
10114 ALUWritePC(result); // setflags is always FALSE here
10118 APSR.N = result<31>;
10119 APSR.Z = IsZeroBit(result);
10124 bool success = false;
10126 if (ConditionPassed(opcode)) {
10130 ARM_ShifterType shift_t;
10133 switch (encoding) {
10135 // d = UInt(Rd); m = UInt(Rm); setflags = (S == '1');
10136 d = Bits32(opcode, 11, 8);
10137 m = Bits32(opcode, 3, 0);
10138 setflags = BitIsSet(opcode, 20);
10140 // (shift_t, shift_n) = DecodeImmShift(type, imm3:imm2);
10141 shift_n = DecodeImmShiftThumb(opcode, shift_t);
10143 // if d == 13 && (shift_t != SRType_LSL || shift_n > 3) then
10145 if ((d == 13) && ((shift_t != SRType_LSL) || (shift_n > 3)))
10148 // if d == 15 || BadReg(m) then UNPREDICTABLE;
10149 if ((d == 15) || BadReg(m))
10154 // d = UInt(Rd); m = UInt(Rm); setflags = (S == '1');
10155 d = Bits32(opcode, 15, 12);
10156 m = Bits32(opcode, 3, 0);
10157 setflags = BitIsSet(opcode, 20);
10159 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related
10161 if (d == 15 && setflags)
10162 EmulateSUBSPcLrEtc(opcode, encoding);
10164 // (shift_t, shift_n) = DecodeImmShift(type, imm5);
10165 shift_n = DecodeImmShiftARM(opcode, shift_t);
10172 // shifted = Shift(R[m], shift_t, shift_n, APSR.C);
10173 uint32_t Rm = ReadCoreReg(m, &success);
10177 uint32_t shifted = Shift(Rm, shift_t, shift_n, APSR_C, &success);
10181 // (result, carry, overflow) = AddWithCarry(SP, NOT(shifted), '1');
10182 uint32_t sp_val = ReadCoreReg(SP_REG, &success);
10186 AddWithCarryResult res = AddWithCarry(sp_val, ~shifted, 1);
10188 EmulateInstruction::Context context;
10189 context.type = eContextArithmetic;
10190 RegisterInfo sp_reg;
10191 GetRegisterInfo(eRegisterKindDWARF, dwarf_sp, sp_reg);
10192 RegisterInfo dwarf_reg;
10193 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + m, dwarf_reg);
10194 context.SetRegisterRegisterOperands(sp_reg, dwarf_reg);
10196 if (!WriteCoreRegOptionalFlags(context, res.result, dwarf_r0 + d, setflags,
10197 res.carry_out, res.overflow))
10203 // A8.6.7 ADD (register-shifted register)
10204 bool EmulateInstructionARM::EmulateADDRegShift(const uint32_t opcode,
10205 const ARMEncoding encoding) {
10207 if ConditionPassed() then
10208 EncodingSpecificOperations();
10209 shift_n = UInt(R[s]<7:0>);
10210 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
10211 (result, carry, overflow) = AddWithCarry(R[n], shifted, '0');
10214 APSR.N = result<31>;
10215 APSR.Z = IsZeroBit(result);
10220 bool success = false;
10222 if (ConditionPassed(opcode)) {
10228 ARM_ShifterType shift_t;
10230 switch (encoding) {
10232 // d = UInt(Rd); n = UInt(Rn); m = UInt(Rm); s = UInt(Rs);
10233 d = Bits32(opcode, 15, 12);
10234 n = Bits32(opcode, 19, 16);
10235 m = Bits32(opcode, 3, 0);
10236 s = Bits32(opcode, 11, 8);
10238 // setflags = (S == '1'); shift_t = DecodeRegShift(type);
10239 setflags = BitIsSet(opcode, 20);
10240 shift_t = DecodeRegShift(Bits32(opcode, 6, 5));
10242 // if d == 15 || n == 15 || m == 15 || s == 15 then UNPREDICTABLE;
10243 if ((d == 15) || (m == 15) || (m == 15) || (s == 15))
10251 // shift_n = UInt(R[s]<7:0>);
10252 uint32_t Rs = ReadCoreReg(s, &success);
10256 uint32_t shift_n = Bits32(Rs, 7, 0);
10258 // shifted = Shift(R[m], shift_t, shift_n, APSR.C);
10259 uint32_t Rm = ReadCoreReg(m, &success);
10263 uint32_t shifted = Shift(Rm, shift_t, shift_n, APSR_C, &success);
10267 // (result, carry, overflow) = AddWithCarry(R[n], shifted, '0');
10268 uint32_t Rn = ReadCoreReg(n, &success);
10272 AddWithCarryResult res = AddWithCarry(Rn, shifted, 0);
10275 EmulateInstruction::Context context;
10276 context.type = eContextArithmetic;
10277 RegisterInfo reg_n;
10278 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n, reg_n);
10279 RegisterInfo reg_m;
10280 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + m, reg_m);
10282 context.SetRegisterRegisterOperands(reg_n, reg_m);
10284 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + d,
10288 // if setflags then
10289 // APSR.N = result<31>;
10290 // APSR.Z = IsZeroBit(result);
10292 // APSR.V = overflow;
10294 return WriteFlags(context, res.result, res.carry_out, res.overflow);
10299 // A8.6.213 SUB (register)
10300 bool EmulateInstructionARM::EmulateSUBReg(const uint32_t opcode,
10301 const ARMEncoding encoding) {
10303 if ConditionPassed() then
10304 EncodingSpecificOperations();
10305 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
10306 (result, carry, overflow) = AddWithCarry(R[n], NOT(shifted), '1');
10307 if d == 15 then // Can only occur for ARM encoding
10308 ALUWritePC(result); // setflags is always FALSE here
10312 APSR.N = result<31>;
10313 APSR.Z = IsZeroBit(result);
10318 bool success = false;
10320 if (ConditionPassed(opcode)) {
10325 ARM_ShifterType shift_t;
10328 switch (encoding) {
10330 // d = UInt(Rd); n = UInt(Rn); m = UInt(Rm); setflags = !InITBlock();
10331 d = Bits32(opcode, 2, 0);
10332 n = Bits32(opcode, 5, 3);
10333 m = Bits32(opcode, 8, 6);
10334 setflags = !InITBlock();
10336 // (shift_t, shift_n) = (SRType_LSL, 0);
10337 shift_t = SRType_LSL;
10343 // d = UInt(Rd); n = UInt(Rn); m = UInt(Rm); setflags = (S =="1");
10344 d = Bits32(opcode, 11, 8);
10345 n = Bits32(opcode, 19, 16);
10346 m = Bits32(opcode, 3, 0);
10347 setflags = BitIsSet(opcode, 20);
10349 // if Rd == "1111" && S == "1" then SEE CMP (register);
10350 if (d == 15 && setflags == 1)
10351 return EmulateCMPImm(opcode, eEncodingT3);
10353 // if Rn == "1101" then SEE SUB (SP minus register);
10355 return EmulateSUBSPReg(opcode, eEncodingT1);
10357 // (shift_t, shift_n) = DecodeImmShift(type, imm3:imm2);
10358 shift_n = DecodeImmShiftThumb(opcode, shift_t);
10360 // if d == 13 || (d == 15 && S == '0') || n == 15 || BadReg(m) then
10362 if ((d == 13) || ((d == 15) && BitIsClear(opcode, 20)) || (n == 15) ||
10369 // if Rn == '1101' then SEE SUB (SP minus register);
10370 // d = UInt(Rd); n = UInt(Rn); m = UInt(Rm); setflags = (S == '1');
10371 d = Bits32(opcode, 15, 12);
10372 n = Bits32(opcode, 19, 16);
10373 m = Bits32(opcode, 3, 0);
10374 setflags = BitIsSet(opcode, 20);
10376 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related
10378 if ((d == 15) && setflags)
10379 EmulateSUBSPcLrEtc(opcode, encoding);
10381 // (shift_t, shift_n) = DecodeImmShift(type, imm5);
10382 shift_n = DecodeImmShiftARM(opcode, shift_t);
10390 // shifted = Shift(R[m], shift_t, shift_n, APSR.C);
10391 uint32_t Rm = ReadCoreReg(m, &success);
10395 uint32_t shifted = Shift(Rm, shift_t, shift_n, APSR_C, &success);
10399 // (result, carry, overflow) = AddWithCarry(R[n], NOT(shifted), '1');
10400 uint32_t Rn = ReadCoreReg(n, &success);
10404 AddWithCarryResult res = AddWithCarry(Rn, ~shifted, 1);
10406 // if d == 15 then // Can only occur for ARM encoding
10407 // ALUWritePC(result); // setflags is always FALSE here
10410 // if setflags then
10411 // APSR.N = result<31>;
10412 // APSR.Z = IsZeroBit(result);
10414 // APSR.V = overflow;
10416 EmulateInstruction::Context context;
10417 context.type = eContextArithmetic;
10418 RegisterInfo reg_n;
10419 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n, reg_n);
10420 RegisterInfo reg_m;
10421 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + m, reg_m);
10422 context.SetRegisterRegisterOperands(reg_n, reg_m);
10424 if (!WriteCoreRegOptionalFlags(context, res.result, dwarf_r0 + d, setflags,
10425 res.carry_out, res.overflow))
10432 // Store Register Exclusive calculates an address from a base register value and
10433 // an immediate offset, and stores a
10434 // word from a register to memory if the executing processor has exclusive
10435 // access to the memory addressed.
10436 bool EmulateInstructionARM::EmulateSTREX(const uint32_t opcode,
10437 const ARMEncoding encoding) {
10439 if ConditionPassed() then
10440 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
10441 address = R[n] + imm32;
10442 if ExclusiveMonitorsPass(address,4) then
10443 MemA[address,4] = R[t];
10449 bool success = false;
10451 if (ConditionPassed(opcode)) {
10456 const uint32_t addr_byte_size = GetAddressByteSize();
10458 switch (encoding) {
10460 // d = UInt(Rd); t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8:'00',
10462 d = Bits32(opcode, 11, 8);
10463 t = Bits32(opcode, 15, 12);
10464 n = Bits32(opcode, 19, 16);
10465 imm32 = Bits32(opcode, 7, 0) << 2;
10467 // if BadReg(d) || BadReg(t) || n == 15 then UNPREDICTABLE;
10468 if (BadReg(d) || BadReg(t) || (n == 15))
10471 // if d == n || d == t then UNPREDICTABLE;
10472 if ((d == n) || (d == t))
10478 // d = UInt(Rd); t = UInt(Rt); n = UInt(Rn); imm32 = Zeros(32); // Zero
10480 d = Bits32(opcode, 15, 12);
10481 t = Bits32(opcode, 3, 0);
10482 n = Bits32(opcode, 19, 16);
10485 // if d == 15 || t == 15 || n == 15 then UNPREDICTABLE;
10486 if ((d == 15) || (t == 15) || (n == 15))
10489 // if d == n || d == t then UNPREDICTABLE;
10490 if ((d == n) || (d == t))
10499 // address = R[n] + imm32;
10500 uint32_t Rn = ReadCoreReg(n, &success);
10504 addr_t address = Rn + imm32;
10506 RegisterInfo base_reg;
10507 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n, base_reg);
10508 RegisterInfo data_reg;
10509 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + t, data_reg);
10510 EmulateInstruction::Context context;
10511 context.type = eContextRegisterStore;
10512 context.SetRegisterToRegisterPlusOffset(data_reg, base_reg, imm32);
10514 // if ExclusiveMonitorsPass(address,4) then
10515 // if (ExclusiveMonitorsPass (address, addr_byte_size)) -- For now, for the
10516 // sake of emulation, we will say this
10520 // MemA[address,4] = R[t];
10522 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + t, 0, &success);
10526 if (!MemAWrite(context, address, Rt, addr_byte_size))
10530 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + t, 0))
10533 #if 0 // unreachable because if true
10537 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, 1))
10540 #endif // unreachable because if true
10545 // A8.6.197 STRB (immediate, ARM)
10546 bool EmulateInstructionARM::EmulateSTRBImmARM(const uint32_t opcode,
10547 const ARMEncoding encoding) {
10549 if ConditionPassed() then
10550 EncodingSpecificOperations();
10551 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
10552 address = if index then offset_addr else R[n];
10553 MemU[address,1] = R[t]<7:0>;
10554 if wback then R[n] = offset_addr;
10557 bool success = false;
10559 if (ConditionPassed(opcode)) {
10567 switch (encoding) {
10569 // if P == '0' && W == '1' then SEE STRBT;
10570 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
10571 t = Bits32(opcode, 15, 12);
10572 n = Bits32(opcode, 19, 16);
10573 imm32 = Bits32(opcode, 11, 0);
10575 // index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1');
10576 index = BitIsSet(opcode, 24);
10577 add = BitIsSet(opcode, 23);
10578 wback = BitIsClear(opcode, 24) || BitIsSet(opcode, 21);
10580 // if t == 15 then UNPREDICTABLE;
10584 // if wback && (n == 15 || n == t) then UNPREDICTABLE;
10585 if (wback && ((n == 15) || (n == t)))
10594 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
10595 uint32_t Rn = ReadCoreReg(n, &success);
10599 addr_t offset_addr;
10601 offset_addr = Rn + imm32;
10603 offset_addr = Rn - imm32;
10605 // address = if index then offset_addr else R[n];
10608 address = offset_addr;
10612 // MemU[address,1] = R[t]<7:0>;
10613 uint32_t Rt = ReadCoreReg(t, &success);
10617 RegisterInfo base_reg;
10618 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n, base_reg);
10619 RegisterInfo data_reg;
10620 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + t, data_reg);
10621 EmulateInstruction::Context context;
10622 context.type = eContextRegisterStore;
10623 context.SetRegisterToRegisterPlusOffset(data_reg, base_reg, address - Rn);
10625 if (!MemUWrite(context, address, Bits32(Rt, 7, 0), 1))
10628 // if wback then R[n] = offset_addr;
10630 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n,
10638 // A8.6.194 STR (immediate, ARM)
10639 bool EmulateInstructionARM::EmulateSTRImmARM(const uint32_t opcode,
10640 const ARMEncoding encoding) {
10642 if ConditionPassed() then
10643 EncodingSpecificOperations();
10644 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
10645 address = if index then offset_addr else R[n];
10646 MemU[address,4] = if t == 15 then PCStoreValue() else R[t];
10647 if wback then R[n] = offset_addr;
10650 bool success = false;
10652 if (ConditionPassed(opcode)) {
10660 const uint32_t addr_byte_size = GetAddressByteSize();
10662 switch (encoding) {
10664 // if P == '0' && W == '1' then SEE STRT;
10665 // if Rn == '1101' && P == '1' && U == '0' && W == '1' && imm12 ==
10666 // '000000000100' then SEE PUSH;
10667 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
10668 t = Bits32(opcode, 15, 12);
10669 n = Bits32(opcode, 19, 16);
10670 imm32 = Bits32(opcode, 11, 0);
10672 // index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1');
10673 index = BitIsSet(opcode, 24);
10674 add = BitIsSet(opcode, 23);
10675 wback = BitIsClear(opcode, 24) || BitIsSet(opcode, 21);
10677 // if wback && (n == 15 || n == t) then UNPREDICTABLE;
10678 if (wback && ((n == 15) || (n == t)))
10687 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
10688 uint32_t Rn = ReadCoreReg(n, &success);
10692 addr_t offset_addr;
10694 offset_addr = Rn + imm32;
10696 offset_addr = Rn - imm32;
10698 // address = if index then offset_addr else R[n];
10701 address = offset_addr;
10705 RegisterInfo base_reg;
10706 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n, base_reg);
10707 RegisterInfo data_reg;
10708 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + t, data_reg);
10709 EmulateInstruction::Context context;
10710 context.type = eContextRegisterStore;
10711 context.SetRegisterToRegisterPlusOffset(data_reg, base_reg, address - Rn);
10713 // MemU[address,4] = if t == 15 then PCStoreValue() else R[t];
10714 uint32_t Rt = ReadCoreReg(t, &success);
10719 uint32_t pc_value = ReadCoreReg(PC_REG, &success);
10723 if (!MemUWrite(context, address, pc_value, addr_byte_size))
10726 if (!MemUWrite(context, address, Rt, addr_byte_size))
10730 // if wback then R[n] = offset_addr;
10732 context.type = eContextAdjustBaseRegister;
10733 context.SetImmediate(offset_addr);
10735 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n,
10743 // A8.6.66 LDRD (immediate)
10744 // Load Register Dual (immediate) calculates an address from a base register
10745 // value and an immediate offset, loads two
10746 // words from memory, and writes them to two registers. It can use offset,
10747 // post-indexed, or pre-indexed addressing.
10748 bool EmulateInstructionARM::EmulateLDRDImmediate(const uint32_t opcode,
10749 const ARMEncoding encoding) {
10751 if ConditionPassed() then
10752 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
10753 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
10754 address = if index then offset_addr else R[n];
10755 R[t] = MemA[address,4];
10756 R[t2] = MemA[address+4,4];
10757 if wback then R[n] = offset_addr;
10760 bool success = false;
10762 if (ConditionPassed(opcode)) {
10771 switch (encoding) {
10773 // if P == '0' && W == '0' then SEE 'Related encodings';
10774 // if Rn == '1111' then SEE LDRD (literal);
10775 // t = UInt(Rt); t2 = UInt(Rt2); n = UInt(Rn); imm32 =
10776 // ZeroExtend(imm8:'00', 32);
10777 t = Bits32(opcode, 15, 12);
10778 t2 = Bits32(opcode, 11, 8);
10779 n = Bits32(opcode, 19, 16);
10780 imm32 = Bits32(opcode, 7, 0) << 2;
10782 // index = (P == '1'); add = (U == '1'); wback = (W == '1');
10783 index = BitIsSet(opcode, 24);
10784 add = BitIsSet(opcode, 23);
10785 wback = BitIsSet(opcode, 21);
10787 // if wback && (n == t || n == t2) then UNPREDICTABLE;
10788 if (wback && ((n == t) || (n == t2)))
10791 // if BadReg(t) || BadReg(t2) || t == t2 then UNPREDICTABLE;
10792 if (BadReg(t) || BadReg(t2) || (t == t2))
10798 // if Rn == '1111' then SEE LDRD (literal);
10799 // if Rt<0> == '1' then UNPREDICTABLE;
10800 // t = UInt(Rt); t2 = t+1; n = UInt(Rn); imm32 = ZeroExtend(imm4H:imm4L,
10802 t = Bits32(opcode, 15, 12);
10803 if (BitIsSet(t, 0))
10806 n = Bits32(opcode, 19, 16);
10807 imm32 = (Bits32(opcode, 11, 8) << 4) | Bits32(opcode, 3, 0);
10809 // index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1');
10810 index = BitIsSet(opcode, 24);
10811 add = BitIsSet(opcode, 23);
10812 wback = BitIsClear(opcode, 24) || BitIsSet(opcode, 21);
10814 // if P == '0' && W == '1' then UNPREDICTABLE;
10815 if (BitIsClear(opcode, 24) && BitIsSet(opcode, 21))
10818 // if wback && (n == t || n == t2) then UNPREDICTABLE;
10819 if (wback && ((n == t) || (n == t2)))
10822 // if t2 == 15 then UNPREDICTABLE;
10832 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
10833 uint32_t Rn = ReadCoreReg(n, &success);
10837 addr_t offset_addr;
10839 offset_addr = Rn + imm32;
10841 offset_addr = Rn - imm32;
10843 // address = if index then offset_addr else R[n];
10846 address = offset_addr;
10850 // R[t] = MemA[address,4];
10851 RegisterInfo base_reg;
10852 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n, base_reg);
10854 EmulateInstruction::Context context;
10856 context.type = eContextPopRegisterOffStack;
10858 context.type = eContextRegisterLoad;
10859 context.SetAddress(address);
10861 const uint32_t addr_byte_size = GetAddressByteSize();
10862 uint32_t data = MemARead(context, address, addr_byte_size, 0, &success);
10866 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + t, data))
10869 // R[t2] = MemA[address+4,4];
10870 context.SetAddress(address + 4);
10871 data = MemARead(context, address + 4, addr_byte_size, 0, &success);
10875 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + t2,
10879 // if wback then R[n] = offset_addr;
10881 context.type = eContextAdjustBaseRegister;
10882 context.SetAddress(offset_addr);
10884 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n,
10892 // A8.6.68 LDRD (register)
10893 // Load Register Dual (register) calculates an address from a base register
10894 // value and a register offset, loads two
10895 // words from memory, and writes them to two registers. It can use offset,
10896 // post-indexed or pre-indexed addressing.
10897 bool EmulateInstructionARM::EmulateLDRDRegister(const uint32_t opcode,
10898 const ARMEncoding encoding) {
10900 if ConditionPassed() then
10901 EncodingSpecificOperations();
10902 offset_addr = if add then (R[n] + R[m]) else (R[n] - R[m]);
10903 address = if index then offset_addr else R[n];
10904 R[t] = MemA[address,4];
10905 R[t2] = MemA[address+4,4];
10906 if wback then R[n] = offset_addr;
10909 bool success = false;
10911 if (ConditionPassed(opcode)) {
10920 switch (encoding) {
10922 // if Rt<0> == '1' then UNPREDICTABLE;
10923 // t = UInt(Rt); t2 = t+1; n = UInt(Rn); m = UInt(Rm);
10924 t = Bits32(opcode, 15, 12);
10925 if (BitIsSet(t, 0))
10928 n = Bits32(opcode, 19, 16);
10929 m = Bits32(opcode, 3, 0);
10931 // index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1');
10932 index = BitIsSet(opcode, 24);
10933 add = BitIsSet(opcode, 23);
10934 wback = BitIsClear(opcode, 24) || BitIsSet(opcode, 21);
10936 // if P == '0' && W == '1' then UNPREDICTABLE;
10937 if (BitIsClear(opcode, 24) && BitIsSet(opcode, 21))
10940 // if t2 == 15 || m == 15 || m == t || m == t2 then UNPREDICTABLE;
10941 if ((t2 == 15) || (m == 15) || (m == t) || (m == t2))
10944 // if wback && (n == 15 || n == t || n == t2) then UNPREDICTABLE;
10945 if (wback && ((n == 15) || (n == t) || (n == t2)))
10948 // if ArchVersion() < 6 && wback && m == n then UNPREDICTABLE;
10949 if ((ArchVersion() < 6) && wback && (m == n))
10957 uint32_t Rn = ReadCoreReg(n, &success);
10960 RegisterInfo base_reg;
10961 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n, base_reg);
10963 uint32_t Rm = ReadCoreReg(m, &success);
10966 RegisterInfo offset_reg;
10967 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + m, offset_reg);
10969 // offset_addr = if add then (R[n] + R[m]) else (R[n] - R[m]);
10970 addr_t offset_addr;
10972 offset_addr = Rn + Rm;
10974 offset_addr = Rn - Rm;
10976 // address = if index then offset_addr else R[n];
10979 address = offset_addr;
10983 EmulateInstruction::Context context;
10985 context.type = eContextPopRegisterOffStack;
10987 context.type = eContextRegisterLoad;
10988 context.SetAddress(address);
10990 // R[t] = MemA[address,4];
10991 const uint32_t addr_byte_size = GetAddressByteSize();
10992 uint32_t data = MemARead(context, address, addr_byte_size, 0, &success);
10996 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + t, data))
10999 // R[t2] = MemA[address+4,4];
11001 data = MemARead(context, address + 4, addr_byte_size, 0, &success);
11005 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + t2,
11009 // if wback then R[n] = offset_addr;
11011 context.type = eContextAdjustBaseRegister;
11012 context.SetAddress(offset_addr);
11014 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n,
11022 // A8.6.200 STRD (immediate)
11023 // Store Register Dual (immediate) calculates an address from a base register
11024 // value and an immediate offset, and
11025 // stores two words from two registers to memory. It can use offset,
11026 // post-indexed, or pre-indexed addressing.
11027 bool EmulateInstructionARM::EmulateSTRDImm(const uint32_t opcode,
11028 const ARMEncoding encoding) {
11030 if ConditionPassed() then
11031 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
11032 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
11033 address = if index then offset_addr else R[n];
11034 MemA[address,4] = R[t];
11035 MemA[address+4,4] = R[t2];
11036 if wback then R[n] = offset_addr;
11039 bool success = false;
11041 if (ConditionPassed(opcode)) {
11050 switch (encoding) {
11052 // if P == '0' && W == '0' then SEE 'Related encodings';
11053 // t = UInt(Rt); t2 = UInt(Rt2); n = UInt(Rn); imm32 =
11054 // ZeroExtend(imm8:'00', 32);
11055 t = Bits32(opcode, 15, 12);
11056 t2 = Bits32(opcode, 11, 8);
11057 n = Bits32(opcode, 19, 16);
11058 imm32 = Bits32(opcode, 7, 0) << 2;
11060 // index = (P == '1'); add = (U == '1'); wback = (W == '1');
11061 index = BitIsSet(opcode, 24);
11062 add = BitIsSet(opcode, 23);
11063 wback = BitIsSet(opcode, 21);
11065 // if wback && (n == t || n == t2) then UNPREDICTABLE;
11066 if (wback && ((n == t) || (n == t2)))
11069 // if n == 15 || BadReg(t) || BadReg(t2) then UNPREDICTABLE;
11070 if ((n == 15) || BadReg(t) || BadReg(t2))
11076 // if Rt<0> == '1' then UNPREDICTABLE;
11077 // t = UInt(Rt); t2 = t+1; n = UInt(Rn); imm32 = ZeroExtend(imm4H:imm4L,
11079 t = Bits32(opcode, 15, 12);
11080 if (BitIsSet(t, 0))
11084 n = Bits32(opcode, 19, 16);
11085 imm32 = (Bits32(opcode, 11, 8) << 4) | Bits32(opcode, 3, 0);
11087 // index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1');
11088 index = BitIsSet(opcode, 24);
11089 add = BitIsSet(opcode, 23);
11090 wback = BitIsClear(opcode, 24) || BitIsSet(opcode, 21);
11092 // if P == '0' && W == '1' then UNPREDICTABLE;
11093 if (BitIsClear(opcode, 24) && BitIsSet(opcode, 21))
11096 // if wback && (n == 15 || n == t || n == t2) then UNPREDICTABLE;
11097 if (wback && ((n == 15) || (n == t) || (n == t2)))
11100 // if t2 == 15 then UNPREDICTABLE;
11110 RegisterInfo base_reg;
11111 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n, base_reg);
11113 uint32_t Rn = ReadCoreReg(n, &success);
11117 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
11118 addr_t offset_addr;
11120 offset_addr = Rn + imm32;
11122 offset_addr = Rn - imm32;
11124 // address = if index then offset_addr else R[n];
11127 address = offset_addr;
11131 // MemA[address,4] = R[t];
11132 RegisterInfo data_reg;
11133 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + t, data_reg);
11135 uint32_t data = ReadCoreReg(t, &success);
11139 EmulateInstruction::Context context;
11141 context.type = eContextPushRegisterOnStack;
11143 context.type = eContextRegisterStore;
11144 context.SetRegisterToRegisterPlusOffset(data_reg, base_reg, address - Rn);
11146 const uint32_t addr_byte_size = GetAddressByteSize();
11148 if (!MemAWrite(context, address, data, addr_byte_size))
11151 // MemA[address+4,4] = R[t2];
11152 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + t2, data_reg);
11153 context.SetRegisterToRegisterPlusOffset(data_reg, base_reg,
11154 (address + 4) - Rn);
11156 data = ReadCoreReg(t2, &success);
11160 if (!MemAWrite(context, address + 4, data, addr_byte_size))
11163 // if wback then R[n] = offset_addr;
11166 context.type = eContextAdjustStackPointer;
11168 context.type = eContextAdjustBaseRegister;
11169 context.SetAddress(offset_addr);
11171 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n,
11179 // A8.6.201 STRD (register)
11180 bool EmulateInstructionARM::EmulateSTRDReg(const uint32_t opcode,
11181 const ARMEncoding encoding) {
11183 if ConditionPassed() then
11184 EncodingSpecificOperations();
11185 offset_addr = if add then (R[n] + R[m]) else (R[n] - R[m]);
11186 address = if index then offset_addr else R[n];
11187 MemA[address,4] = R[t];
11188 MemA[address+4,4] = R[t2];
11189 if wback then R[n] = offset_addr;
11192 bool success = false;
11194 if (ConditionPassed(opcode)) {
11203 switch (encoding) {
11205 // if Rt<0> == '1' then UNPREDICTABLE;
11206 // t = UInt(Rt); t2 = t+1; n = UInt(Rn); m = UInt(Rm);
11207 t = Bits32(opcode, 15, 12);
11208 if (BitIsSet(t, 0))
11212 n = Bits32(opcode, 19, 16);
11213 m = Bits32(opcode, 3, 0);
11215 // index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1');
11216 index = BitIsSet(opcode, 24);
11217 add = BitIsSet(opcode, 23);
11218 wback = BitIsClear(opcode, 24) || BitIsSet(opcode, 21);
11220 // if P == '0' && W == '1' then UNPREDICTABLE;
11221 if (BitIsClear(opcode, 24) && BitIsSet(opcode, 21))
11224 // if t2 == 15 || m == 15 then UNPREDICTABLE;
11225 if ((t2 == 15) || (m == 15))
11228 // if wback && (n == 15 || n == t || n == t2) then UNPREDICTABLE;
11229 if (wback && ((n == 15) || (n == t) || (n == t2)))
11232 // if ArchVersion() < 6 && wback && m == n then UNPREDICTABLE;
11233 if ((ArchVersion() < 6) && wback && (m == n))
11242 RegisterInfo base_reg;
11243 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n, base_reg);
11244 RegisterInfo offset_reg;
11245 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + m, offset_reg);
11246 RegisterInfo data_reg;
11248 uint32_t Rn = ReadCoreReg(n, &success);
11252 uint32_t Rm = ReadCoreReg(m, &success);
11256 // offset_addr = if add then (R[n] + R[m]) else (R[n] - R[m]);
11257 addr_t offset_addr;
11259 offset_addr = Rn + Rm;
11261 offset_addr = Rn - Rm;
11263 // address = if index then offset_addr else R[n];
11266 address = offset_addr;
11269 // MemA[address,4] = R[t];
11270 uint32_t Rt = ReadCoreReg(t, &success);
11274 EmulateInstruction::Context context;
11276 context.type = eContextPushRegisterOnStack;
11278 context.type = eContextRegisterStore;
11280 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + t, data_reg);
11281 context.SetRegisterToRegisterPlusIndirectOffset(base_reg, offset_reg,
11284 const uint32_t addr_byte_size = GetAddressByteSize();
11286 if (!MemAWrite(context, address, Rt, addr_byte_size))
11289 // MemA[address+4,4] = R[t2];
11290 uint32_t Rt2 = ReadCoreReg(t2, &success);
11294 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + t2, data_reg);
11296 context.SetRegisterToRegisterPlusIndirectOffset(base_reg, offset_reg,
11299 if (!MemAWrite(context, address + 4, Rt2, addr_byte_size))
11302 // if wback then R[n] = offset_addr;
11304 context.type = eContextAdjustBaseRegister;
11305 context.SetAddress(offset_addr);
11307 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n,
11316 // Vector Load Multiple loads multiple extension registers from consecutive
11317 // memory locations using an address from
11318 // an ARM core register.
11319 bool EmulateInstructionARM::EmulateVLDM(const uint32_t opcode,
11320 const ARMEncoding encoding) {
11322 if ConditionPassed() then
11323 EncodingSpecificOperations(); CheckVFPEnabled(TRUE); NullCheckIfThumbEE(n);
11324 address = if add then R[n] else R[n]-imm32;
11325 if wback then R[n] = if add then R[n]+imm32 else R[n]-imm32;
11326 for r = 0 to regs-1
11327 if single_regs then
11328 S[d+r] = MemA[address,4]; address = address+4;
11330 word1 = MemA[address,4]; word2 = MemA[address+4,4]; address = address+8;
11331 // Combine the word-aligned words in the correct order for current endianness.
11332 D[d+r] = if BigEndian() then word1:word2 else word2:word1;
11335 bool success = false;
11337 if (ConditionPassed(opcode)) {
11346 switch (encoding) {
11349 // if P == '0' && U == '0' && W == '0' then SEE 'Related encodings';
11350 // if P == '0' && U == '1' && W == '1' && Rn == '1101' then SEE VPOP;
11351 // if P == '1' && W == '0' then SEE VLDR;
11352 // if P == U && W == '1' then UNDEFINED;
11353 if ((Bit32(opcode, 24) == Bit32(opcode, 23)) && BitIsSet(opcode, 21))
11356 // // Remaining combinations are PUW = 010 (IA without !), 011 (IA with
11357 // !), 101 (DB with !)
11358 // single_regs = FALSE; add = (U == '1'); wback = (W == '1');
11359 single_regs = false;
11360 add = BitIsSet(opcode, 23);
11361 wback = BitIsSet(opcode, 21);
11363 // d = UInt(D:Vd); n = UInt(Rn); imm32 = ZeroExtend(imm8:'00', 32);
11364 d = (Bit32(opcode, 22) << 4) | Bits32(opcode, 15, 12);
11365 n = Bits32(opcode, 19, 16);
11366 imm32 = Bits32(opcode, 7, 0) << 2;
11368 // regs = UInt(imm8) DIV 2; // If UInt(imm8) is odd, see 'FLDMX'.
11369 regs = Bits32(opcode, 7, 0) / 2;
11371 // if n == 15 && (wback || CurrentInstrSet() != InstrSet_ARM) then
11373 if (n == 15 && (wback || CurrentInstrSet() != eModeARM))
11376 // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE;
11377 if ((regs == 0) || (regs > 16) || ((d + regs) > 32))
11384 // if P == '0' && U == '0' && W == '0' then SEE 'Related encodings';
11385 // if P == '0' && U == '1' && W == '1' && Rn == '1101' then SEE VPOP;
11386 // if P == '1' && W == '0' then SEE VLDR;
11387 // if P == U && W == '1' then UNDEFINED;
11388 if ((Bit32(opcode, 24) == Bit32(opcode, 23)) && BitIsSet(opcode, 21))
11391 // // Remaining combinations are PUW = 010 (IA without !), 011 (IA with
11392 // !), 101 (DB with !)
11393 // single_regs = TRUE; add = (U == '1'); wback = (W == '1'); d =
11394 // UInt(Vd:D); n = UInt(Rn);
11395 single_regs = true;
11396 add = BitIsSet(opcode, 23);
11397 wback = BitIsSet(opcode, 21);
11398 d = (Bits32(opcode, 15, 12) << 1) | Bit32(opcode, 22);
11399 n = Bits32(opcode, 19, 16);
11401 // imm32 = ZeroExtend(imm8:'00', 32); regs = UInt(imm8);
11402 imm32 = Bits32(opcode, 7, 0) << 2;
11403 regs = Bits32(opcode, 7, 0);
11405 // if n == 15 && (wback || CurrentInstrSet() != InstrSet_ARM) then
11407 if ((n == 15) && (wback || (CurrentInstrSet() != eModeARM)))
11410 // if regs == 0 || (d+regs) > 32 then UNPREDICTABLE;
11411 if ((regs == 0) || ((d + regs) > 32))
11419 RegisterInfo base_reg;
11420 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n, base_reg);
11422 uint32_t Rn = ReadCoreReg(n, &success);
11426 // address = if add then R[n] else R[n]-imm32;
11431 address = Rn - imm32;
11433 // if wback then R[n] = if add then R[n]+imm32 else R[n]-imm32;
11434 EmulateInstruction::Context context;
11439 value = Rn + imm32;
11441 value = Rn - imm32;
11443 context.type = eContextAdjustBaseRegister;
11444 context.SetImmediateSigned(value - Rn);
11445 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n,
11450 const uint32_t addr_byte_size = GetAddressByteSize();
11451 uint32_t start_reg = single_regs ? dwarf_s0 : dwarf_d0;
11453 context.type = eContextRegisterLoad;
11455 // for r = 0 to regs-1
11456 for (uint32_t r = 0; r < regs; ++r) {
11458 // S[d+r] = MemA[address,4]; address = address+4;
11459 context.SetRegisterPlusOffset(base_reg, address - Rn);
11461 uint32_t data = MemARead(context, address, addr_byte_size, 0, &success);
11465 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF,
11466 start_reg + d + r, data))
11469 address = address + 4;
11471 // word1 = MemA[address,4]; word2 = MemA[address+4,4]; address =
11473 context.SetRegisterPlusOffset(base_reg, address - Rn);
11475 MemARead(context, address, addr_byte_size, 0, &success);
11479 context.SetRegisterPlusOffset(base_reg, (address + 4) - Rn);
11481 MemARead(context, address + 4, addr_byte_size, 0, &success);
11485 address = address + 8;
11486 // // Combine the word-aligned words in the correct order for current
11488 // D[d+r] = if BigEndian() then word1:word2 else word2:word1;
11490 if (GetByteOrder() == eByteOrderBig) {
11492 data = (data << 32) | word2;
11495 data = (data << 32) | word1;
11498 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF,
11499 start_reg + d + r, data))
11508 // Vector Store Multiple stores multiple extension registers to consecutive
11509 // memory locations using an address from an
11510 // ARM core register.
11511 bool EmulateInstructionARM::EmulateVSTM(const uint32_t opcode,
11512 const ARMEncoding encoding) {
11514 if ConditionPassed() then
11515 EncodingSpecificOperations(); CheckVFPEnabled(TRUE); NullCheckIfThumbEE(n);
11516 address = if add then R[n] else R[n]-imm32;
11517 if wback then R[n] = if add then R[n]+imm32 else R[n]-imm32;
11518 for r = 0 to regs-1
11519 if single_regs then
11520 MemA[address,4] = S[d+r]; address = address+4;
11522 // Store as two word-aligned words in the correct order for current endianness.
11523 MemA[address,4] = if BigEndian() then D[d+r]<63:32> else D[d+r]<31:0>;
11524 MemA[address+4,4] = if BigEndian() then D[d+r]<31:0> else D[d+r]<63:32>;
11525 address = address+8;
11528 bool success = false;
11530 if (ConditionPassed(opcode)) {
11539 switch (encoding) {
11542 // if P == '0' && U == '0' && W == '0' then SEE 'Related encodings';
11543 // if P == '1' && U == '0' && W == '1' && Rn == '1101' then SEE VPUSH;
11544 // if P == '1' && W == '0' then SEE VSTR;
11545 // if P == U && W == '1' then UNDEFINED;
11546 if ((Bit32(opcode, 24) == Bit32(opcode, 23)) && BitIsSet(opcode, 21))
11549 // // Remaining combinations are PUW = 010 (IA without !), 011 (IA with
11550 // !), 101 (DB with !)
11551 // single_regs = FALSE; add = (U == '1'); wback = (W == '1');
11552 single_regs = false;
11553 add = BitIsSet(opcode, 23);
11554 wback = BitIsSet(opcode, 21);
11556 // d = UInt(D:Vd); n = UInt(Rn); imm32 = ZeroExtend(imm8:'00', 32);
11557 d = (Bit32(opcode, 22) << 4) | Bits32(opcode, 15, 12);
11558 n = Bits32(opcode, 19, 16);
11559 imm32 = Bits32(opcode, 7, 0) << 2;
11561 // regs = UInt(imm8) DIV 2; // If UInt(imm8) is odd, see 'FSTMX'.
11562 regs = Bits32(opcode, 7, 0) / 2;
11564 // if n == 15 && (wback || CurrentInstrSet() != InstrSet_ARM) then
11566 if ((n == 15) && (wback || (CurrentInstrSet() != eModeARM)))
11569 // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE;
11570 if ((regs == 0) || (regs > 16) || ((d + regs) > 32))
11577 // if P == '0' && U == '0' && W == '0' then SEE 'Related encodings';
11578 // if P == '1' && U == '0' && W == '1' && Rn == '1101' then SEE VPUSH;
11579 // if P == '1' && W == '0' then SEE VSTR;
11580 // if P == U && W == '1' then UNDEFINED;
11581 if ((Bit32(opcode, 24) == Bit32(opcode, 23)) && BitIsSet(opcode, 21))
11584 // // Remaining combinations are PUW = 010 (IA without !), 011 (IA with
11585 // !), 101 (DB with !)
11586 // single_regs = TRUE; add = (U == '1'); wback = (W == '1'); d =
11587 // UInt(Vd:D); n = UInt(Rn);
11588 single_regs = true;
11589 add = BitIsSet(opcode, 23);
11590 wback = BitIsSet(opcode, 21);
11591 d = (Bits32(opcode, 15, 12) << 1) | Bit32(opcode, 22);
11592 n = Bits32(opcode, 19, 16);
11594 // imm32 = ZeroExtend(imm8:'00', 32); regs = UInt(imm8);
11595 imm32 = Bits32(opcode, 7, 0) << 2;
11596 regs = Bits32(opcode, 7, 0);
11598 // if n == 15 && (wback || CurrentInstrSet() != InstrSet_ARM) then
11600 if ((n == 15) && (wback || (CurrentInstrSet() != eModeARM)))
11603 // if regs == 0 || (d+regs) > 32 then UNPREDICTABLE;
11604 if ((regs == 0) || ((d + regs) > 32))
11613 RegisterInfo base_reg;
11614 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n, base_reg);
11616 uint32_t Rn = ReadCoreReg(n, &success);
11620 // address = if add then R[n] else R[n]-imm32;
11625 address = Rn - imm32;
11627 EmulateInstruction::Context context;
11628 // if wback then R[n] = if add then R[n]+imm32 else R[n]-imm32;
11632 value = Rn + imm32;
11634 value = Rn - imm32;
11636 context.type = eContextAdjustBaseRegister;
11637 context.SetRegisterPlusOffset(base_reg, value - Rn);
11639 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n,
11644 const uint32_t addr_byte_size = GetAddressByteSize();
11645 uint32_t start_reg = single_regs ? dwarf_s0 : dwarf_d0;
11647 context.type = eContextRegisterStore;
11648 // for r = 0 to regs-1
11649 for (uint32_t r = 0; r < regs; ++r) {
11652 // MemA[address,4] = S[d+r]; address = address+4;
11653 uint32_t data = ReadRegisterUnsigned(eRegisterKindDWARF,
11654 start_reg + d + r, 0, &success);
11658 RegisterInfo data_reg;
11659 GetRegisterInfo(eRegisterKindDWARF, start_reg + d + r, data_reg);
11660 context.SetRegisterToRegisterPlusOffset(data_reg, base_reg,
11662 if (!MemAWrite(context, address, data, addr_byte_size))
11665 address = address + 4;
11667 // // Store as two word-aligned words in the correct order for current
11669 // MemA[address,4] = if BigEndian() then D[d+r]<63:32> else
11671 // MemA[address+4,4] = if BigEndian() then D[d+r]<31:0> else
11673 uint64_t data = ReadRegisterUnsigned(eRegisterKindDWARF,
11674 start_reg + d + r, 0, &success);
11678 RegisterInfo data_reg;
11679 GetRegisterInfo(eRegisterKindDWARF, start_reg + d + r, data_reg);
11681 if (GetByteOrder() == eByteOrderBig) {
11682 context.SetRegisterToRegisterPlusOffset(data_reg, base_reg,
11684 if (!MemAWrite(context, address, Bits64(data, 63, 32),
11688 context.SetRegisterToRegisterPlusOffset(data_reg, base_reg,
11689 (address + 4) - Rn);
11690 if (!MemAWrite(context, address + 4, Bits64(data, 31, 0),
11694 context.SetRegisterToRegisterPlusOffset(data_reg, base_reg,
11696 if (!MemAWrite(context, address, Bits64(data, 31, 0), addr_byte_size))
11699 context.SetRegisterToRegisterPlusOffset(data_reg, base_reg,
11700 (address + 4) - Rn);
11701 if (!MemAWrite(context, address + 4, Bits64(data, 63, 32),
11705 // address = address+8;
11706 address = address + 8;
11714 // This instruction loads a single extension register from memory, using an
11715 // address from an ARM core register, with
11716 // an optional offset.
11717 bool EmulateInstructionARM::EmulateVLDR(const uint32_t opcode,
11718 ARMEncoding encoding) {
11720 if ConditionPassed() then
11721 EncodingSpecificOperations(); CheckVFPEnabled(TRUE); NullCheckIfThumbEE(n);
11722 base = if n == 15 then Align(PC,4) else R[n];
11723 address = if add then (base + imm32) else (base - imm32);
11725 S[d] = MemA[address,4];
11727 word1 = MemA[address,4]; word2 = MemA[address+4,4];
11728 // Combine the word-aligned words in the correct order for current endianness.
11729 D[d] = if BigEndian() then word1:word2 else word2:word1;
11732 bool success = false;
11734 if (ConditionPassed(opcode)) {
11741 switch (encoding) {
11744 // single_reg = FALSE; add = (U == '1'); imm32 = ZeroExtend(imm8:'00',
11746 single_reg = false;
11747 add = BitIsSet(opcode, 23);
11748 imm32 = Bits32(opcode, 7, 0) << 2;
11750 // d = UInt(D:Vd); n = UInt(Rn);
11751 d = (Bit32(opcode, 22) << 4) | Bits32(opcode, 15, 12);
11752 n = Bits32(opcode, 19, 16);
11758 // single_reg = TRUE; add = (U == '1'); imm32 = ZeroExtend(imm8:'00', 32);
11760 add = BitIsSet(opcode, 23);
11761 imm32 = Bits32(opcode, 7, 0) << 2;
11763 // d = UInt(Vd:D); n = UInt(Rn);
11764 d = (Bits32(opcode, 15, 12) << 1) | Bit32(opcode, 22);
11765 n = Bits32(opcode, 19, 16);
11772 RegisterInfo base_reg;
11773 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n, base_reg);
11775 uint32_t Rn = ReadCoreReg(n, &success);
11779 // base = if n == 15 then Align(PC,4) else R[n];
11782 base = AlignPC(Rn);
11786 // address = if add then (base + imm32) else (base - imm32);
11789 address = base + imm32;
11791 address = base - imm32;
11793 const uint32_t addr_byte_size = GetAddressByteSize();
11794 uint32_t start_reg = single_reg ? dwarf_s0 : dwarf_d0;
11796 EmulateInstruction::Context context;
11797 context.type = eContextRegisterLoad;
11798 context.SetRegisterPlusOffset(base_reg, address - base);
11801 // S[d] = MemA[address,4];
11802 uint32_t data = MemARead(context, address, addr_byte_size, 0, &success);
11806 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, start_reg + d,
11810 // word1 = MemA[address,4]; word2 = MemA[address+4,4];
11811 uint32_t word1 = MemARead(context, address, addr_byte_size, 0, &success);
11815 context.SetRegisterPlusOffset(base_reg, (address + 4) - base);
11817 MemARead(context, address + 4, addr_byte_size, 0, &success);
11820 // // Combine the word-aligned words in the correct order for current
11822 // D[d] = if BigEndian() then word1:word2 else word2:word1;
11824 if (GetByteOrder() == eByteOrderBig) {
11826 data64 = (data64 << 32) | word2;
11829 data64 = (data64 << 32) | word1;
11832 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, start_reg + d,
11841 // This instruction stores a signle extension register to memory, using an
11842 // address from an ARM core register, with an
11843 // optional offset.
11844 bool EmulateInstructionARM::EmulateVSTR(const uint32_t opcode,
11845 ARMEncoding encoding) {
11847 if ConditionPassed() then
11848 EncodingSpecificOperations(); CheckVFPEnabled(TRUE); NullCheckIfThumbEE(n);
11849 address = if add then (R[n] + imm32) else (R[n] - imm32);
11851 MemA[address,4] = S[d];
11853 // Store as two word-aligned words in the correct order for current endianness.
11854 MemA[address,4] = if BigEndian() then D[d]<63:32> else D[d]<31:0>;
11855 MemA[address+4,4] = if BigEndian() then D[d]<31:0> else D[d]<63:32>;
11858 bool success = false;
11860 if (ConditionPassed(opcode)) {
11867 switch (encoding) {
11870 // single_reg = FALSE; add = (U == '1'); imm32 = ZeroExtend(imm8:'00',
11872 single_reg = false;
11873 add = BitIsSet(opcode, 23);
11874 imm32 = Bits32(opcode, 7, 0) << 2;
11876 // d = UInt(D:Vd); n = UInt(Rn);
11877 d = (Bit32(opcode, 22) << 4) | Bits32(opcode, 15, 12);
11878 n = Bits32(opcode, 19, 16);
11880 // if n == 15 && CurrentInstrSet() != InstrSet_ARM then UNPREDICTABLE;
11881 if ((n == 15) && (CurrentInstrSet() != eModeARM))
11888 // single_reg = TRUE; add = (U == '1'); imm32 = ZeroExtend(imm8:'00', 32);
11890 add = BitIsSet(opcode, 23);
11891 imm32 = Bits32(opcode, 7, 0) << 2;
11893 // d = UInt(Vd:D); n = UInt(Rn);
11894 d = (Bits32(opcode, 15, 12) << 1) | Bit32(opcode, 22);
11895 n = Bits32(opcode, 19, 16);
11897 // if n == 15 && CurrentInstrSet() != InstrSet_ARM then UNPREDICTABLE;
11898 if ((n == 15) && (CurrentInstrSet() != eModeARM))
11907 RegisterInfo base_reg;
11908 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n, base_reg);
11910 uint32_t Rn = ReadCoreReg(n, &success);
11914 // address = if add then (R[n] + imm32) else (R[n] - imm32);
11917 address = Rn + imm32;
11919 address = Rn - imm32;
11921 const uint32_t addr_byte_size = GetAddressByteSize();
11922 uint32_t start_reg = single_reg ? dwarf_s0 : dwarf_d0;
11924 RegisterInfo data_reg;
11925 GetRegisterInfo(eRegisterKindDWARF, start_reg + d, data_reg);
11926 EmulateInstruction::Context context;
11927 context.type = eContextRegisterStore;
11928 context.SetRegisterToRegisterPlusOffset(data_reg, base_reg, address - Rn);
11931 // MemA[address,4] = S[d];
11933 ReadRegisterUnsigned(eRegisterKindDWARF, start_reg + d, 0, &success);
11937 if (!MemAWrite(context, address, data, addr_byte_size))
11940 // // Store as two word-aligned words in the correct order for current
11942 // MemA[address,4] = if BigEndian() then D[d]<63:32> else D[d]<31:0>;
11943 // MemA[address+4,4] = if BigEndian() then D[d]<31:0> else D[d]<63:32>;
11945 ReadRegisterUnsigned(eRegisterKindDWARF, start_reg + d, 0, &success);
11949 if (GetByteOrder() == eByteOrderBig) {
11950 if (!MemAWrite(context, address, Bits64(data, 63, 32), addr_byte_size))
11953 context.SetRegisterToRegisterPlusOffset(data_reg, base_reg,
11954 (address + 4) - Rn);
11955 if (!MemAWrite(context, address + 4, Bits64(data, 31, 0),
11959 if (!MemAWrite(context, address, Bits64(data, 31, 0), addr_byte_size))
11962 context.SetRegisterToRegisterPlusOffset(data_reg, base_reg,
11963 (address + 4) - Rn);
11964 if (!MemAWrite(context, address + 4, Bits64(data, 63, 32),
11973 // A8.6.307 VLDI1 (multiple single elements)
11974 // This instruction loads elements from memory into one, two, three or four
11975 // registers, without de-interleaving. Every
11976 // element of each register is loaded.
11977 bool EmulateInstructionARM::EmulateVLD1Multiple(const uint32_t opcode,
11978 ARMEncoding encoding) {
11980 if ConditionPassed() then
11981 EncodingSpecificOperations(); CheckAdvSIMDEnabled(); NullCheckIfThumbEE(n);
11982 address = R[n]; if (address MOD alignment) != 0 then GenerateAlignmentException();
11983 if wback then R[n] = R[n] + (if register_index then R[m] else 8*regs);
11984 for r = 0 to regs-1
11985 for e = 0 to elements-1
11986 Elem[D[d+r],e,esize] = MemU[address,ebytes];
11987 address = address + ebytes;
11990 bool success = false;
11992 if (ConditionPassed(opcode)) {
11994 uint32_t alignment;
12002 bool register_index;
12004 switch (encoding) {
12006 case eEncodingA1: {
12009 // regs = 1; if align<1> == '1' then UNDEFINED;
12011 // regs = 2; if align == '11' then UNDEFINED;
12013 // regs = 3; if align<1> == '1' then UNDEFINED;
12017 // SEE 'Related encodings';
12018 uint32_t type = Bits32(opcode, 11, 8);
12019 uint32_t align = Bits32(opcode, 5, 4);
12020 if (type == 7) // '0111'
12023 if (BitIsSet(align, 1))
12025 } else if (type == 10) // '1010'
12031 } else if (type == 6) // '0110'
12034 if (BitIsSet(align, 1))
12036 } else if (type == 2) // '0010'
12042 // alignment = if align == '00' then 1 else 4 << UInt(align);
12046 alignment = 4 << align;
12048 // ebytes = 1 << UInt(size); esize = 8 * ebytes; elements = 8 DIV ebytes;
12049 ebytes = 1 << Bits32(opcode, 7, 6);
12050 esize = 8 * ebytes;
12051 elements = 8 / ebytes;
12053 // d = UInt(D:Vd); n = UInt(Rn); m = UInt(Rm);
12054 d = (Bit32(opcode, 22) << 4) | Bits32(opcode, 15, 12);
12055 n = Bits32(opcode, 19, 15);
12056 m = Bits32(opcode, 3, 0);
12058 // wback = (m != 15); register_index = (m != 15 && m != 13);
12060 register_index = ((m != 15) && (m != 13));
12062 // if d+regs > 32 then UNPREDICTABLE;
12063 if ((d + regs) > 32)
12071 RegisterInfo base_reg;
12072 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n, base_reg);
12074 uint32_t Rn = ReadCoreReg(n, &success);
12078 // address = R[n]; if (address MOD alignment) != 0 then
12079 // GenerateAlignmentException();
12080 addr_t address = Rn;
12081 if ((address % alignment) != 0)
12084 EmulateInstruction::Context context;
12085 // if wback then R[n] = R[n] + (if register_index then R[m] else 8*regs);
12087 uint32_t Rm = ReadCoreReg(m, &success);
12092 if (register_index)
12097 uint32_t value = Rn + offset;
12098 context.type = eContextAdjustBaseRegister;
12099 context.SetRegisterPlusOffset(base_reg, offset);
12101 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n,
12106 // for r = 0 to regs-1
12107 for (uint32_t r = 0; r < regs; ++r) {
12108 // for e = 0 to elements-1
12109 uint64_t assembled_data = 0;
12110 for (uint32_t e = 0; e < elements; ++e) {
12111 // Elem[D[d+r],e,esize] = MemU[address,ebytes];
12112 context.type = eContextRegisterLoad;
12113 context.SetRegisterPlusOffset(base_reg, address - Rn);
12114 uint64_t data = MemURead(context, address, ebytes, 0, &success);
12119 (data << (e * esize)) |
12120 assembled_data; // New data goes to the left of existing data
12122 // address = address + ebytes;
12123 address = address + ebytes;
12125 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_d0 + d + r,
12133 // A8.6.308 VLD1 (single element to one lane)
12135 bool EmulateInstructionARM::EmulateVLD1Single(const uint32_t opcode,
12136 const ARMEncoding encoding) {
12138 if ConditionPassed() then
12139 EncodingSpecificOperations(); CheckAdvSIMDEnabled(); NullCheckIfThumbEE(n);
12140 address = R[n]; if (address MOD alignment) != 0 then GenerateAlignmentException();
12141 if wback then R[n] = R[n] + (if register_index then R[m] else ebytes);
12142 Elem[D[d],index,esize] = MemU[address,ebytes];
12145 bool success = false;
12147 if (ConditionPassed(opcode)) {
12151 uint32_t alignment;
12156 bool register_index;
12158 switch (encoding) {
12160 case eEncodingA1: {
12161 uint32_t size = Bits32(opcode, 11, 10);
12162 uint32_t index_align = Bits32(opcode, 7, 4);
12163 // if size == '11' then SEE VLD1 (single element to all lanes);
12165 return EmulateVLD1SingleAll(opcode, encoding);
12167 if (size == 0) // when '00'
12169 // if index_align<0> != '0' then UNDEFINED;
12170 if (BitIsClear(index_align, 0))
12173 // ebytes = 1; esize = 8; index = UInt(index_align<3:1>); alignment = 1;
12176 index = Bits32(index_align, 3, 1);
12178 } else if (size == 1) // when '01'
12180 // if index_align<1> != '0' then UNDEFINED;
12181 if (BitIsClear(index_align, 1))
12184 // ebytes = 2; esize = 16; index = UInt(index_align<3:2>);
12187 index = Bits32(index_align, 3, 2);
12189 // alignment = if index_align<0> == '0' then 1 else 2;
12190 if (BitIsClear(index_align, 0))
12194 } else if (size == 2) // when '10'
12196 // if index_align<2> != '0' then UNDEFINED;
12197 if (BitIsClear(index_align, 2))
12200 // if index_align<1:0> != '00' && index_align<1:0> != '11' then
12202 if ((Bits32(index_align, 1, 0) != 0) &&
12203 (Bits32(index_align, 1, 0) != 3))
12206 // ebytes = 4; esize = 32; index = UInt(index_align<3>);
12209 index = Bit32(index_align, 3);
12211 // alignment = if index_align<1:0> == '00' then 1 else 4;
12212 if (Bits32(index_align, 1, 0) == 0)
12219 // d = UInt(D:Vd); n = UInt(Rn); m = UInt(Rm);
12220 d = (Bit32(opcode, 22) << 4) | Bits32(opcode, 15, 12);
12221 n = Bits32(opcode, 19, 16);
12222 m = Bits32(opcode, 3, 0);
12224 // wback = (m != 15); register_index = (m != 15 && m != 13); if n == 15
12225 // then UNPREDICTABLE;
12227 register_index = ((m != 15) && (m != 13));
12238 RegisterInfo base_reg;
12239 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n, base_reg);
12241 uint32_t Rn = ReadCoreReg(n, &success);
12245 // address = R[n]; if (address MOD alignment) != 0 then
12246 // GenerateAlignmentException();
12247 addr_t address = Rn;
12248 if ((address % alignment) != 0)
12251 EmulateInstruction::Context context;
12252 // if wback then R[n] = R[n] + (if register_index then R[m] else ebytes);
12254 uint32_t Rm = ReadCoreReg(m, &success);
12259 if (register_index)
12264 uint32_t value = Rn + offset;
12266 context.type = eContextAdjustBaseRegister;
12267 context.SetRegisterPlusOffset(base_reg, offset);
12269 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n,
12274 // Elem[D[d],index,esize] = MemU[address,ebytes];
12275 uint32_t element = MemURead(context, address, esize, 0, &success);
12279 element = element << (index * esize);
12281 uint64_t reg_data =
12282 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_d0 + d, 0, &success);
12286 uint64_t all_ones = -1;
12287 uint64_t mask = all_ones
12288 << ((index + 1) * esize); // mask is all 1's to left of
12289 // where 'element' goes, & all 0's
12290 // at element & to the right of element.
12292 mask = mask | Bits64(all_ones, (index * esize) - 1,
12293 0); // add 1's to the right of where 'element' goes.
12294 // now mask should be 0's where element goes & 1's
12295 // everywhere else.
12297 uint64_t masked_reg =
12298 reg_data & mask; // Take original reg value & zero out 'element' bits
12300 masked_reg & element; // Put 'element' into those bits in reg_data.
12302 context.type = eContextRegisterLoad;
12303 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + d,
12310 // A8.6.391 VST1 (multiple single elements)
12311 // Vector Store (multiple single elements) stores elements to memory from one,
12312 // two, three, or four registers, without
12313 // interleaving. Every element of each register is stored.
12314 bool EmulateInstructionARM::EmulateVST1Multiple(const uint32_t opcode,
12315 ARMEncoding encoding) {
12317 if ConditionPassed() then
12318 EncodingSpecificOperations(); CheckAdvSIMDEnabled(); NullCheckIfThumbEE(n);
12319 address = R[n]; if (address MOD alignment) != 0 then GenerateAlignmentException();
12320 if wback then R[n] = R[n] + (if register_index then R[m] else 8*regs);
12321 for r = 0 to regs-1
12322 for e = 0 to elements-1
12323 MemU[address,ebytes] = Elem[D[d+r],e,esize];
12324 address = address + ebytes;
12327 bool success = false;
12329 if (ConditionPassed(opcode)) {
12331 uint32_t alignment;
12339 bool register_index;
12341 switch (encoding) {
12343 case eEncodingA1: {
12344 uint32_t type = Bits32(opcode, 11, 8);
12345 uint32_t align = Bits32(opcode, 5, 4);
12348 if (type == 7) // when '0111'
12350 // regs = 1; if align<1> == '1' then UNDEFINED;
12352 if (BitIsSet(align, 1))
12354 } else if (type == 10) // when '1010'
12356 // regs = 2; if align == '11' then UNDEFINED;
12360 } else if (type == 6) // when '0110'
12362 // regs = 3; if align<1> == '1' then UNDEFINED;
12364 if (BitIsSet(align, 1))
12366 } else if (type == 2) // when '0010'
12370 // SEE 'Related encodings';
12373 // alignment = if align == '00' then 1 else 4 << UInt(align);
12377 alignment = 4 << align;
12379 // ebytes = 1 << UInt(size); esize = 8 * ebytes; elements = 8 DIV ebytes;
12380 ebytes = 1 << Bits32(opcode, 7, 6);
12381 esize = 8 * ebytes;
12382 elements = 8 / ebytes;
12384 // d = UInt(D:Vd); n = UInt(Rn); m = UInt(Rm);
12385 d = (Bit32(opcode, 22) << 4) | Bits32(opcode, 15, 12);
12386 n = Bits32(opcode, 19, 16);
12387 m = Bits32(opcode, 3, 0);
12389 // wback = (m != 15); register_index = (m != 15 && m != 13);
12391 register_index = ((m != 15) && (m != 13));
12393 // if d+regs > 32 then UNPREDICTABLE; if n == 15 then UNPREDICTABLE;
12394 if ((d + regs) > 32)
12406 RegisterInfo base_reg;
12407 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n, base_reg);
12409 uint32_t Rn = ReadCoreReg(n, &success);
12413 // address = R[n]; if (address MOD alignment) != 0 then
12414 // GenerateAlignmentException();
12415 addr_t address = Rn;
12416 if ((address % alignment) != 0)
12419 EmulateInstruction::Context context;
12420 // if wback then R[n] = R[n] + (if register_index then R[m] else 8*regs);
12422 uint32_t Rm = ReadCoreReg(m, &success);
12427 if (register_index)
12432 context.type = eContextAdjustBaseRegister;
12433 context.SetRegisterPlusOffset(base_reg, offset);
12435 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n,
12440 RegisterInfo data_reg;
12441 context.type = eContextRegisterStore;
12442 // for r = 0 to regs-1
12443 for (uint32_t r = 0; r < regs; ++r) {
12444 GetRegisterInfo(eRegisterKindDWARF, dwarf_d0 + d + r, data_reg);
12445 uint64_t register_data = ReadRegisterUnsigned(
12446 eRegisterKindDWARF, dwarf_d0 + d + r, 0, &success);
12450 // for e = 0 to elements-1
12451 for (uint32_t e = 0; e < elements; ++e) {
12452 // MemU[address,ebytes] = Elem[D[d+r],e,esize];
12453 uint64_t word = Bits64(register_data, ((e + 1) * esize) - 1, e * esize);
12455 context.SetRegisterToRegisterPlusOffset(data_reg, base_reg,
12457 if (!MemUWrite(context, address, word, ebytes))
12460 // address = address + ebytes;
12461 address = address + ebytes;
12468 // A8.6.392 VST1 (single element from one lane)
12469 // This instruction stores one element to memory from one element of a register.
12470 bool EmulateInstructionARM::EmulateVST1Single(const uint32_t opcode,
12471 ARMEncoding encoding) {
12473 if ConditionPassed() then
12474 EncodingSpecificOperations(); CheckAdvSIMDEnabled(); NullCheckIfThumbEE(n);
12475 address = R[n]; if (address MOD alignment) != 0 then GenerateAlignmentException();
12476 if wback then R[n] = R[n] + (if register_index then R[m] else ebytes);
12477 MemU[address,ebytes] = Elem[D[d],index,esize];
12480 bool success = false;
12482 if (ConditionPassed(opcode)) {
12486 uint32_t alignment;
12491 bool register_index;
12493 switch (encoding) {
12495 case eEncodingA1: {
12496 uint32_t size = Bits32(opcode, 11, 10);
12497 uint32_t index_align = Bits32(opcode, 7, 4);
12499 // if size == '11' then UNDEFINED;
12504 if (size == 0) // when '00'
12506 // if index_align<0> != '0' then UNDEFINED;
12507 if (BitIsClear(index_align, 0))
12509 // ebytes = 1; esize = 8; index = UInt(index_align<3:1>); alignment = 1;
12512 index = Bits32(index_align, 3, 1);
12514 } else if (size == 1) // when '01'
12516 // if index_align<1> != '0' then UNDEFINED;
12517 if (BitIsClear(index_align, 1))
12520 // ebytes = 2; esize = 16; index = UInt(index_align<3:2>);
12523 index = Bits32(index_align, 3, 2);
12525 // alignment = if index_align<0> == '0' then 1 else 2;
12526 if (BitIsClear(index_align, 0))
12530 } else if (size == 2) // when '10'
12532 // if index_align<2> != '0' then UNDEFINED;
12533 if (BitIsClear(index_align, 2))
12536 // if index_align<1:0> != '00' && index_align<1:0> != '11' then
12538 if ((Bits32(index_align, 1, 0) != 0) &&
12539 (Bits32(index_align, 1, 0) != 3))
12542 // ebytes = 4; esize = 32; index = UInt(index_align<3>);
12545 index = Bit32(index_align, 3);
12547 // alignment = if index_align<1:0> == '00' then 1 else 4;
12548 if (Bits32(index_align, 1, 0) == 0)
12555 // d = UInt(D:Vd); n = UInt(Rn); m = UInt(Rm);
12556 d = (Bit32(opcode, 22) << 4) | Bits32(opcode, 15, 12);
12557 n = Bits32(opcode, 19, 16);
12558 m = Bits32(opcode, 3, 0);
12560 // wback = (m != 15); register_index = (m != 15 && m != 13); if n == 15
12561 // then UNPREDICTABLE;
12563 register_index = ((m != 15) && (m != 13));
12573 RegisterInfo base_reg;
12574 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n, base_reg);
12576 uint32_t Rn = ReadCoreReg(n, &success);
12580 // address = R[n]; if (address MOD alignment) != 0 then
12581 // GenerateAlignmentException();
12582 addr_t address = Rn;
12583 if ((address % alignment) != 0)
12586 EmulateInstruction::Context context;
12587 // if wback then R[n] = R[n] + (if register_index then R[m] else ebytes);
12589 uint32_t Rm = ReadCoreReg(m, &success);
12594 if (register_index)
12599 context.type = eContextAdjustBaseRegister;
12600 context.SetRegisterPlusOffset(base_reg, offset);
12602 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n,
12607 // MemU[address,ebytes] = Elem[D[d],index,esize];
12608 uint64_t register_data =
12609 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_d0 + d, 0, &success);
12614 Bits64(register_data, ((index + 1) * esize) - 1, index * esize);
12616 RegisterInfo data_reg;
12617 GetRegisterInfo(eRegisterKindDWARF, dwarf_d0 + d, data_reg);
12618 context.type = eContextRegisterStore;
12619 context.SetRegisterToRegisterPlusOffset(data_reg, base_reg, address - Rn);
12621 if (!MemUWrite(context, address, word, ebytes))
12627 // A8.6.309 VLD1 (single element to all lanes)
12628 // This instruction loads one element from memory into every element of one or
12630 bool EmulateInstructionARM::EmulateVLD1SingleAll(const uint32_t opcode,
12631 const ARMEncoding encoding) {
12633 if ConditionPassed() then
12634 EncodingSpecificOperations(); CheckAdvSIMDEnabled(); NullCheckIfThumbEE(n);
12635 address = R[n]; if (address MOD alignment) != 0 then GenerateAlignmentException();
12636 if wback then R[n] = R[n] + (if register_index then R[m] else ebytes);
12637 replicated_element = Replicate(MemU[address,ebytes], elements);
12638 for r = 0 to regs-1
12639 D[d+r] = replicated_element;
12642 bool success = false;
12644 if (ConditionPassed(opcode)) {
12648 uint32_t alignment;
12653 bool register_index;
12655 switch (encoding) {
12657 case eEncodingA1: {
12658 // if size == '11' || (size == '00' && a == '1') then UNDEFINED;
12659 uint32_t size = Bits32(opcode, 7, 6);
12660 if ((size == 3) || ((size == 0) && BitIsSet(opcode, 4)))
12663 // ebytes = 1 << UInt(size); elements = 8 DIV ebytes; regs = if T == '0'
12665 ebytes = 1 << size;
12666 elements = 8 / ebytes;
12667 if (BitIsClear(opcode, 5))
12672 // alignment = if a == '0' then 1 else ebytes;
12673 if (BitIsClear(opcode, 4))
12676 alignment = ebytes;
12678 // d = UInt(D:Vd); n = UInt(Rn); m = UInt(Rm);
12679 d = (Bit32(opcode, 22) << 4) | Bits32(opcode, 15, 12);
12680 n = Bits32(opcode, 19, 16);
12681 m = Bits32(opcode, 3, 0);
12683 // wback = (m != 15); register_index = (m != 15 && m != 13);
12685 register_index = ((m != 15) && (m != 13));
12687 // if d+regs > 32 then UNPREDICTABLE; if n == 15 then UNPREDICTABLE;
12688 if ((d + regs) > 32)
12699 RegisterInfo base_reg;
12700 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n, base_reg);
12702 uint32_t Rn = ReadCoreReg(n, &success);
12706 // address = R[n]; if (address MOD alignment) != 0 then
12707 // GenerateAlignmentException();
12708 addr_t address = Rn;
12709 if ((address % alignment) != 0)
12712 EmulateInstruction::Context context;
12713 // if wback then R[n] = R[n] + (if register_index then R[m] else ebytes);
12715 uint32_t Rm = ReadCoreReg(m, &success);
12720 if (register_index)
12725 context.type = eContextAdjustBaseRegister;
12726 context.SetRegisterPlusOffset(base_reg, offset);
12728 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n,
12733 // replicated_element = Replicate(MemU[address,ebytes], elements);
12735 context.type = eContextRegisterLoad;
12736 uint64_t word = MemURead(context, address, ebytes, 0, &success);
12740 uint64_t replicated_element = 0;
12741 uint32_t esize = ebytes * 8;
12742 for (uint32_t e = 0; e < elements; ++e)
12743 replicated_element =
12744 (replicated_element << esize) | Bits64(word, esize - 1, 0);
12746 // for r = 0 to regs-1
12747 for (uint32_t r = 0; r < regs; ++r) {
12748 // D[d+r] = replicated_element;
12749 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_d0 + d + r,
12750 replicated_element))
12757 // B6.2.13 SUBS PC, LR and related instructions
12758 // The SUBS PC, LR, #<const? instruction provides an exception return without
12759 // the use of the stack. It subtracts the
12760 // immediate constant from the LR, branches to the resulting address, and also
12761 // copies the SPSR to the CPSR.
12762 bool EmulateInstructionARM::EmulateSUBSPcLrEtc(const uint32_t opcode,
12763 const ARMEncoding encoding) {
12765 if ConditionPassed() then
12766 EncodingSpecificOperations();
12767 if CurrentInstrSet() == InstrSet_ThumbEE then
12769 operand2 = if register_form then Shift(R[m], shift_t, shift_n, APSR.C) else imm32;
12771 when '0000' result = R[n] AND operand2; // AND
12772 when '0001' result = R[n] EOR operand2; // EOR
12773 when '0010' (result, -, -) = AddWithCarry(R[n], NOT(operand2), '1'); // SUB
12774 when '0011' (result, -, -) = AddWithCarry(NOT(R[n]), operand2, '1'); // RSB
12775 when '0100' (result, -, -) = AddWithCarry(R[n], operand2, '0'); // ADD
12776 when '0101' (result, -, -) = AddWithCarry(R[n], operand2, APSR.c); // ADC
12777 when '0110' (result, -, -) = AddWithCarry(R[n], NOT(operand2), APSR.C); // SBC
12778 when '0111' (result, -, -) = AddWithCarry(NOT(R[n]), operand2, APSR.C); // RSC
12779 when '1100' result = R[n] OR operand2; // ORR
12780 when '1101' result = operand2; // MOV
12781 when '1110' result = R[n] AND NOT(operand2); // BIC
12782 when '1111' result = NOT(operand2); // MVN
12783 CPSRWriteByInstr(SPSR[], '1111', TRUE);
12784 BranchWritePC(result);
12787 bool success = false;
12789 if (ConditionPassed(opcode)) {
12793 bool register_form;
12794 ARM_ShifterType shift_t;
12798 switch (encoding) {
12800 // if CurrentInstrSet() == InstrSet_ThumbEE then UNPREDICTABLE
12801 // n = 14; imm32 = ZeroExtend(imm8, 32); register_form = FALSE; opcode =
12802 // '0010'; // = SUB
12804 imm32 = Bits32(opcode, 7, 0);
12805 register_form = false;
12808 // if InITBlock() && !LastInITBlock() then UNPREDICTABLE;
12809 if (InITBlock() && !LastInITBlock())
12815 // n = UInt(Rn); imm32 = ARMExpandImm(imm12); register_form = FALSE;
12816 n = Bits32(opcode, 19, 16);
12817 imm32 = ARMExpandImm(opcode);
12818 register_form = false;
12819 code = Bits32(opcode, 24, 21);
12824 // n = UInt(Rn); m = UInt(Rm); register_form = TRUE;
12825 n = Bits32(opcode, 19, 16);
12826 m = Bits32(opcode, 3, 0);
12827 register_form = true;
12829 // (shift_t, shift_n) = DecodeImmShift(type, imm5);
12830 shift_n = DecodeImmShiftARM(opcode, shift_t);
12838 // operand2 = if register_form then Shift(R[m], shift_t, shift_n, APSR.C)
12841 if (register_form) {
12842 uint32_t Rm = ReadCoreReg(m, &success);
12846 operand2 = Shift(Rm, shift_t, shift_n, APSR_C, &success);
12853 uint32_t Rn = ReadCoreReg(n, &success);
12857 AddWithCarryResult result;
12861 case 0: // when '0000'
12862 // result = R[n] AND operand2; // AND
12863 result.result = Rn & operand2;
12866 case 1: // when '0001'
12867 // result = R[n] EOR operand2; // EOR
12868 result.result = Rn ^ operand2;
12871 case 2: // when '0010'
12872 // (result, -, -) = AddWithCarry(R[n], NOT(operand2), '1'); // SUB
12873 result = AddWithCarry(Rn, ~(operand2), 1);
12876 case 3: // when '0011'
12877 // (result, -, -) = AddWithCarry(NOT(R[n]), operand2, '1'); // RSB
12878 result = AddWithCarry(~(Rn), operand2, 1);
12881 case 4: // when '0100'
12882 // (result, -, -) = AddWithCarry(R[n], operand2, '0'); // ADD
12883 result = AddWithCarry(Rn, operand2, 0);
12886 case 5: // when '0101'
12887 // (result, -, -) = AddWithCarry(R[n], operand2, APSR.c); // ADC
12888 result = AddWithCarry(Rn, operand2, APSR_C);
12891 case 6: // when '0110'
12892 // (result, -, -) = AddWithCarry(R[n], NOT(operand2), APSR.C); // SBC
12893 result = AddWithCarry(Rn, ~(operand2), APSR_C);
12896 case 7: // when '0111'
12897 // (result, -, -) = AddWithCarry(NOT(R[n]), operand2, APSR.C); // RSC
12898 result = AddWithCarry(~(Rn), operand2, APSR_C);
12901 case 10: // when '1100'
12902 // result = R[n] OR operand2; // ORR
12903 result.result = Rn | operand2;
12906 case 11: // when '1101'
12907 // result = operand2; // MOV
12908 result.result = operand2;
12911 case 12: // when '1110'
12912 // result = R[n] AND NOT(operand2); // BIC
12913 result.result = Rn & ~(operand2);
12916 case 15: // when '1111'
12917 // result = NOT(operand2); // MVN
12918 result.result = ~(operand2);
12924 // CPSRWriteByInstr(SPSR[], '1111', TRUE);
12926 // For now, in emulation mode, we don't have access to the SPSR, so we will
12927 // use the CPSR instead, and hope for
12930 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_cpsr, 0, &success);
12934 CPSRWriteByInstr(spsr, 15, true);
12936 // BranchWritePC(result);
12937 EmulateInstruction::Context context;
12938 context.type = eContextAdjustPC;
12939 context.SetImmediate(result.result);
12941 BranchWritePC(context, result.result);
12946 EmulateInstructionARM::ARMOpcode *
12947 EmulateInstructionARM::GetARMOpcodeForInstruction(const uint32_t opcode,
12948 uint32_t arm_isa) {
12949 static ARMOpcode g_arm_opcodes[] = {
12950 //----------------------------------------------------------------------
12951 // Prologue instructions
12952 //----------------------------------------------------------------------
12954 // push register(s)
12955 {0x0fff0000, 0x092d0000, ARMvAll, eEncodingA1, No_VFP, eSize32,
12956 &EmulateInstructionARM::EmulatePUSH, "push <registers>"},
12957 {0x0fff0fff, 0x052d0004, ARMvAll, eEncodingA2, No_VFP, eSize32,
12958 &EmulateInstructionARM::EmulatePUSH, "push <register>"},
12960 // set r7 to point to a stack offset
12961 {0x0ffff000, 0x028d7000, ARMvAll, eEncodingA1, No_VFP, eSize32,
12962 &EmulateInstructionARM::EmulateADDRdSPImm, "add r7, sp, #<const>"},
12963 {0x0ffff000, 0x024c7000, ARMvAll, eEncodingA1, No_VFP, eSize32,
12964 &EmulateInstructionARM::EmulateSUBR7IPImm, "sub r7, ip, #<const>"},
12965 // copy the stack pointer to ip
12966 {0x0fffffff, 0x01a0c00d, ARMvAll, eEncodingA1, No_VFP, eSize32,
12967 &EmulateInstructionARM::EmulateMOVRdSP, "mov ip, sp"},
12968 {0x0ffff000, 0x028dc000, ARMvAll, eEncodingA1, No_VFP, eSize32,
12969 &EmulateInstructionARM::EmulateADDRdSPImm, "add ip, sp, #<const>"},
12970 {0x0ffff000, 0x024dc000, ARMvAll, eEncodingA1, No_VFP, eSize32,
12971 &EmulateInstructionARM::EmulateSUBIPSPImm, "sub ip, sp, #<const>"},
12973 // adjust the stack pointer
12974 {0x0ffff000, 0x024dd000, ARMvAll, eEncodingA1, No_VFP, eSize32,
12975 &EmulateInstructionARM::EmulateSUBSPImm, "sub sp, sp, #<const>"},
12976 {0x0fef0010, 0x004d0000, ARMvAll, eEncodingA1, No_VFP, eSize32,
12977 &EmulateInstructionARM::EmulateSUBSPReg,
12978 "sub{s}<c> <Rd>, sp, <Rm>{,<shift>}"},
12980 // push one register
12981 // if Rn == '1101' && imm12 == '000000000100' then SEE PUSH;
12982 {0x0e5f0000, 0x040d0000, ARMvAll, eEncodingA1, No_VFP, eSize32,
12983 &EmulateInstructionARM::EmulateSTRRtSP, "str Rt, [sp, #-imm12]!"},
12985 // vector push consecutive extension register(s)
12986 {0x0fbf0f00, 0x0d2d0b00, ARMV6T2_ABOVE, eEncodingA1, No_VFP, eSize32,
12987 &EmulateInstructionARM::EmulateVPUSH, "vpush.64 <list>"},
12988 {0x0fbf0f00, 0x0d2d0a00, ARMV6T2_ABOVE, eEncodingA2, No_VFP, eSize32,
12989 &EmulateInstructionARM::EmulateVPUSH, "vpush.32 <list>"},
12991 //----------------------------------------------------------------------
12992 // Epilogue instructions
12993 //----------------------------------------------------------------------
12995 {0x0fff0000, 0x08bd0000, ARMvAll, eEncodingA1, No_VFP, eSize32,
12996 &EmulateInstructionARM::EmulatePOP, "pop <registers>"},
12997 {0x0fff0fff, 0x049d0004, ARMvAll, eEncodingA2, No_VFP, eSize32,
12998 &EmulateInstructionARM::EmulatePOP, "pop <register>"},
12999 {0x0fbf0f00, 0x0cbd0b00, ARMV6T2_ABOVE, eEncodingA1, No_VFP, eSize32,
13000 &EmulateInstructionARM::EmulateVPOP, "vpop.64 <list>"},
13001 {0x0fbf0f00, 0x0cbd0a00, ARMV6T2_ABOVE, eEncodingA2, No_VFP, eSize32,
13002 &EmulateInstructionARM::EmulateVPOP, "vpop.32 <list>"},
13004 //----------------------------------------------------------------------
13005 // Supervisor Call (previously Software Interrupt)
13006 //----------------------------------------------------------------------
13007 {0x0f000000, 0x0f000000, ARMvAll, eEncodingA1, No_VFP, eSize32,
13008 &EmulateInstructionARM::EmulateSVC, "svc #imm24"},
13010 //----------------------------------------------------------------------
13011 // Branch instructions
13012 //----------------------------------------------------------------------
13013 // To resolve ambiguity, "blx <label>" should come before "b #imm24" and
13015 {0xfe000000, 0xfa000000, ARMV5_ABOVE, eEncodingA2, No_VFP, eSize32,
13016 &EmulateInstructionARM::EmulateBLXImmediate, "blx <label>"},
13017 {0x0f000000, 0x0a000000, ARMvAll, eEncodingA1, No_VFP, eSize32,
13018 &EmulateInstructionARM::EmulateB, "b #imm24"},
13019 {0x0f000000, 0x0b000000, ARMvAll, eEncodingA1, No_VFP, eSize32,
13020 &EmulateInstructionARM::EmulateBLXImmediate, "bl <label>"},
13021 {0x0ffffff0, 0x012fff30, ARMV5_ABOVE, eEncodingA1, No_VFP, eSize32,
13022 &EmulateInstructionARM::EmulateBLXRm, "blx <Rm>"},
13023 // for example, "bx lr"
13024 {0x0ffffff0, 0x012fff10, ARMvAll, eEncodingA1, No_VFP, eSize32,
13025 &EmulateInstructionARM::EmulateBXRm, "bx <Rm>"},
13027 {0x0ffffff0, 0x012fff20, ARMvAll, eEncodingA1, No_VFP, eSize32,
13028 &EmulateInstructionARM::EmulateBXJRm, "bxj <Rm>"},
13030 //----------------------------------------------------------------------
13031 // Data-processing instructions
13032 //----------------------------------------------------------------------
13034 {0x0fe00000, 0x02a00000, ARMvAll, eEncodingA1, No_VFP, eSize32,
13035 &EmulateInstructionARM::EmulateADCImm, "adc{s}<c> <Rd>, <Rn>, #const"},
13037 {0x0fe00010, 0x00a00000, ARMvAll, eEncodingA1, No_VFP, eSize32,
13038 &EmulateInstructionARM::EmulateADCReg,
13039 "adc{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
13041 {0x0fe00000, 0x02800000, ARMvAll, eEncodingA1, No_VFP, eSize32,
13042 &EmulateInstructionARM::EmulateADDImmARM,
13043 "add{s}<c> <Rd>, <Rn>, #const"},
13045 {0x0fe00010, 0x00800000, ARMvAll, eEncodingA1, No_VFP, eSize32,
13046 &EmulateInstructionARM::EmulateADDReg,
13047 "add{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
13048 // add (register-shifted register)
13049 {0x0fe00090, 0x00800010, ARMvAll, eEncodingA1, No_VFP, eSize32,
13050 &EmulateInstructionARM::EmulateADDRegShift,
13051 "add{s}<c> <Rd>, <Rn>, <Rm>, <type> <RS>"},
13053 {0x0fff0000, 0x028f0000, ARMvAll, eEncodingA1, No_VFP, eSize32,
13054 &EmulateInstructionARM::EmulateADR, "add<c> <Rd>, PC, #<const>"},
13055 {0x0fff0000, 0x024f0000, ARMvAll, eEncodingA2, No_VFP, eSize32,
13056 &EmulateInstructionARM::EmulateADR, "sub<c> <Rd>, PC, #<const>"},
13058 {0x0fe00000, 0x02000000, ARMvAll, eEncodingA1, No_VFP, eSize32,
13059 &EmulateInstructionARM::EmulateANDImm, "and{s}<c> <Rd>, <Rn>, #const"},
13061 {0x0fe00010, 0x00000000, ARMvAll, eEncodingA1, No_VFP, eSize32,
13062 &EmulateInstructionARM::EmulateANDReg,
13063 "and{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
13065 {0x0fe00000, 0x03c00000, ARMvAll, eEncodingA1, No_VFP, eSize32,
13066 &EmulateInstructionARM::EmulateBICImm, "bic{s}<c> <Rd>, <Rn>, #const"},
13068 {0x0fe00010, 0x01c00000, ARMvAll, eEncodingA1, No_VFP, eSize32,
13069 &EmulateInstructionARM::EmulateBICReg,
13070 "bic{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
13072 {0x0fe00000, 0x02200000, ARMvAll, eEncodingA1, No_VFP, eSize32,
13073 &EmulateInstructionARM::EmulateEORImm, "eor{s}<c> <Rd>, <Rn>, #const"},
13075 {0x0fe00010, 0x00200000, ARMvAll, eEncodingA1, No_VFP, eSize32,
13076 &EmulateInstructionARM::EmulateEORReg,
13077 "eor{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
13079 {0x0fe00000, 0x03800000, ARMvAll, eEncodingA1, No_VFP, eSize32,
13080 &EmulateInstructionARM::EmulateORRImm, "orr{s}<c> <Rd>, <Rn>, #const"},
13082 {0x0fe00010, 0x01800000, ARMvAll, eEncodingA1, No_VFP, eSize32,
13083 &EmulateInstructionARM::EmulateORRReg,
13084 "orr{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
13086 {0x0fe00000, 0x02600000, ARMvAll, eEncodingA1, No_VFP, eSize32,
13087 &EmulateInstructionARM::EmulateRSBImm, "rsb{s}<c> <Rd>, <Rn>, #<const>"},
13089 {0x0fe00010, 0x00600000, ARMvAll, eEncodingA1, No_VFP, eSize32,
13090 &EmulateInstructionARM::EmulateRSBReg,
13091 "rsb{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
13093 {0x0fe00000, 0x02e00000, ARMvAll, eEncodingA1, No_VFP, eSize32,
13094 &EmulateInstructionARM::EmulateRSCImm, "rsc{s}<c> <Rd>, <Rn>, #<const>"},
13096 {0x0fe00010, 0x00e00000, ARMvAll, eEncodingA1, No_VFP, eSize32,
13097 &EmulateInstructionARM::EmulateRSCReg,
13098 "rsc{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
13100 {0x0fe00000, 0x02c00000, ARMvAll, eEncodingA1, No_VFP, eSize32,
13101 &EmulateInstructionARM::EmulateSBCImm, "sbc{s}<c> <Rd>, <Rn>, #<const>"},
13103 {0x0fe00010, 0x00c00000, ARMvAll, eEncodingA1, No_VFP, eSize32,
13104 &EmulateInstructionARM::EmulateSBCReg,
13105 "sbc{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
13106 // sub (immediate, ARM)
13107 {0x0fe00000, 0x02400000, ARMvAll, eEncodingA1, No_VFP, eSize32,
13108 &EmulateInstructionARM::EmulateSUBImmARM,
13109 "sub{s}<c> <Rd>, <Rn>, #<const>"},
13110 // sub (sp minus immediate)
13111 {0x0fef0000, 0x024d0000, ARMvAll, eEncodingA1, No_VFP, eSize32,
13112 &EmulateInstructionARM::EmulateSUBSPImm, "sub{s}<c> <Rd>, sp, #<const>"},
13114 {0x0fe00010, 0x00400000, ARMvAll, eEncodingA1, No_VFP, eSize32,
13115 &EmulateInstructionARM::EmulateSUBReg,
13116 "sub{s}<c> <Rd>, <Rn>, <Rm>{,<shift>}"},
13118 {0x0ff0f000, 0x03300000, ARMvAll, eEncodingA1, No_VFP, eSize32,
13119 &EmulateInstructionARM::EmulateTEQImm, "teq<c> <Rn>, #const"},
13121 {0x0ff0f010, 0x01300000, ARMvAll, eEncodingA1, No_VFP, eSize32,
13122 &EmulateInstructionARM::EmulateTEQReg, "teq<c> <Rn>, <Rm> {,<shift>}"},
13124 {0x0ff0f000, 0x03100000, ARMvAll, eEncodingA1, No_VFP, eSize32,
13125 &EmulateInstructionARM::EmulateTSTImm, "tst<c> <Rn>, #const"},
13127 {0x0ff0f010, 0x01100000, ARMvAll, eEncodingA1, No_VFP, eSize32,
13128 &EmulateInstructionARM::EmulateTSTReg, "tst<c> <Rn>, <Rm> {,<shift>}"},
13131 {0x0fef0000, 0x03a00000, ARMvAll, eEncodingA1, No_VFP, eSize32,
13132 &EmulateInstructionARM::EmulateMOVRdImm, "mov{s}<c> <Rd>, #<const>"},
13133 {0x0ff00000, 0x03000000, ARMV6T2_ABOVE, eEncodingA2, No_VFP, eSize32,
13134 &EmulateInstructionARM::EmulateMOVRdImm, "movw<c> <Rd>, #<imm16>"},
13136 {0x0fef0ff0, 0x01a00000, ARMvAll, eEncodingA1, No_VFP, eSize32,
13137 &EmulateInstructionARM::EmulateMOVRdRm, "mov{s}<c> <Rd>, <Rm>"},
13139 {0x0fef0000, 0x03e00000, ARMvAll, eEncodingA1, No_VFP, eSize32,
13140 &EmulateInstructionARM::EmulateMVNImm, "mvn{s}<c> <Rd>, #<const>"},
13142 {0x0fef0010, 0x01e00000, ARMvAll, eEncodingA1, No_VFP, eSize32,
13143 &EmulateInstructionARM::EmulateMVNReg,
13144 "mvn{s}<c> <Rd>, <Rm> {,<shift>}"},
13146 {0x0ff0f000, 0x03700000, ARMvAll, eEncodingA1, No_VFP, eSize32,
13147 &EmulateInstructionARM::EmulateCMNImm, "cmn<c> <Rn>, #<const>"},
13149 {0x0ff0f010, 0x01700000, ARMvAll, eEncodingA1, No_VFP, eSize32,
13150 &EmulateInstructionARM::EmulateCMNReg, "cmn<c> <Rn>, <Rm> {,<shift>}"},
13152 {0x0ff0f000, 0x03500000, ARMvAll, eEncodingA1, No_VFP, eSize32,
13153 &EmulateInstructionARM::EmulateCMPImm, "cmp<c> <Rn>, #<const>"},
13155 {0x0ff0f010, 0x01500000, ARMvAll, eEncodingA1, No_VFP, eSize32,
13156 &EmulateInstructionARM::EmulateCMPReg, "cmp<c> <Rn>, <Rm> {,<shift>}"},
13158 {0x0fef0070, 0x01a00040, ARMvAll, eEncodingA1, No_VFP, eSize32,
13159 &EmulateInstructionARM::EmulateASRImm, "asr{s}<c> <Rd>, <Rm>, #imm"},
13161 {0x0fef00f0, 0x01a00050, ARMvAll, eEncodingA1, No_VFP, eSize32,
13162 &EmulateInstructionARM::EmulateASRReg, "asr{s}<c> <Rd>, <Rn>, <Rm>"},
13164 {0x0fef0070, 0x01a00000, ARMvAll, eEncodingA1, No_VFP, eSize32,
13165 &EmulateInstructionARM::EmulateLSLImm, "lsl{s}<c> <Rd>, <Rm>, #imm"},
13167 {0x0fef00f0, 0x01a00010, ARMvAll, eEncodingA1, No_VFP, eSize32,
13168 &EmulateInstructionARM::EmulateLSLReg, "lsl{s}<c> <Rd>, <Rn>, <Rm>"},
13170 {0x0fef0070, 0x01a00020, ARMvAll, eEncodingA1, No_VFP, eSize32,
13171 &EmulateInstructionARM::EmulateLSRImm, "lsr{s}<c> <Rd>, <Rm>, #imm"},
13173 {0x0fef00f0, 0x01a00050, ARMvAll, eEncodingA1, No_VFP, eSize32,
13174 &EmulateInstructionARM::EmulateLSRReg, "lsr{s}<c> <Rd>, <Rn>, <Rm>"},
13175 // rrx is a special case encoding of ror (immediate)
13176 {0x0fef0ff0, 0x01a00060, ARMvAll, eEncodingA1, No_VFP, eSize32,
13177 &EmulateInstructionARM::EmulateRRX, "rrx{s}<c> <Rd>, <Rm>"},
13179 {0x0fef0070, 0x01a00060, ARMvAll, eEncodingA1, No_VFP, eSize32,
13180 &EmulateInstructionARM::EmulateRORImm, "ror{s}<c> <Rd>, <Rm>, #imm"},
13182 {0x0fef00f0, 0x01a00070, ARMvAll, eEncodingA1, No_VFP, eSize32,
13183 &EmulateInstructionARM::EmulateRORReg, "ror{s}<c> <Rd>, <Rn>, <Rm>"},
13185 {0x0fe000f0, 0x00000090, ARMvAll, eEncodingA1, No_VFP, eSize32,
13186 &EmulateInstructionARM::EmulateMUL, "mul{s}<c> <Rd>,<R>,<Rm>"},
13188 // subs pc, lr and related instructions
13189 {0x0e10f000, 0x0210f000, ARMvAll, eEncodingA1, No_VFP, eSize32,
13190 &EmulateInstructionARM::EmulateSUBSPcLrEtc,
13191 "<opc>S<c> PC,#<const> | <Rn>,#<const>"},
13192 {0x0e10f010, 0x0010f000, ARMvAll, eEncodingA2, No_VFP, eSize32,
13193 &EmulateInstructionARM::EmulateSUBSPcLrEtc,
13194 "<opc>S<c> PC,<Rn>,<Rm{,<shift>}"},
13196 //----------------------------------------------------------------------
13197 // Load instructions
13198 //----------------------------------------------------------------------
13199 {0x0fd00000, 0x08900000, ARMvAll, eEncodingA1, No_VFP, eSize32,
13200 &EmulateInstructionARM::EmulateLDM, "ldm<c> <Rn>{!} <registers>"},
13201 {0x0fd00000, 0x08100000, ARMvAll, eEncodingA1, No_VFP, eSize32,
13202 &EmulateInstructionARM::EmulateLDMDA, "ldmda<c> <Rn>{!} <registers>"},
13203 {0x0fd00000, 0x09100000, ARMvAll, eEncodingA1, No_VFP, eSize32,
13204 &EmulateInstructionARM::EmulateLDMDB, "ldmdb<c> <Rn>{!} <registers>"},
13205 {0x0fd00000, 0x09900000, ARMvAll, eEncodingA1, No_VFP, eSize32,
13206 &EmulateInstructionARM::EmulateLDMIB, "ldmib<c> <Rn<{!} <registers>"},
13207 {0x0e500000, 0x04100000, ARMvAll, eEncodingA1, No_VFP, eSize32,
13208 &EmulateInstructionARM::EmulateLDRImmediateARM,
13209 "ldr<c> <Rt> [<Rn> {#+/-<imm12>}]"},
13210 {0x0e500010, 0x06100000, ARMvAll, eEncodingA1, No_VFP, eSize32,
13211 &EmulateInstructionARM::EmulateLDRRegister,
13212 "ldr<c> <Rt> [<Rn> +/-<Rm> {<shift>}] {!}"},
13213 {0x0e5f0000, 0x045f0000, ARMvAll, eEncodingA1, No_VFP, eSize32,
13214 &EmulateInstructionARM::EmulateLDRBLiteral, "ldrb<c> <Rt>, [...]"},
13215 {0xfe500010, 0x06500000, ARMvAll, eEncodingA1, No_VFP, eSize32,
13216 &EmulateInstructionARM::EmulateLDRBRegister,
13217 "ldrb<c> <Rt>, [<Rn>,+/-<Rm>{, <shift>}]{!}"},
13218 {0x0e5f00f0, 0x005f00b0, ARMvAll, eEncodingA1, No_VFP, eSize32,
13219 &EmulateInstructionARM::EmulateLDRHLiteral, "ldrh<c> <Rt>, <label>"},
13220 {0x0e5000f0, 0x001000b0, ARMvAll, eEncodingA1, No_VFP, eSize32,
13221 &EmulateInstructionARM::EmulateLDRHRegister,
13222 "ldrh<c> <Rt>,[<Rn>,+/-<Rm>]{!}"},
13223 {0x0e5000f0, 0x005000d0, ARMvAll, eEncodingA1, No_VFP, eSize32,
13224 &EmulateInstructionARM::EmulateLDRSBImmediate,
13225 "ldrsb<c> <Rt>, [<Rn>{,#+/-<imm8>}]"},
13226 {0x0e5f00f0, 0x005f00d0, ARMvAll, eEncodingA1, No_VFP, eSize32,
13227 &EmulateInstructionARM::EmulateLDRSBLiteral, "ldrsb<c> <Rt> <label>"},
13228 {0x0e5000f0, 0x001000d0, ARMvAll, eEncodingA1, No_VFP, eSize32,
13229 &EmulateInstructionARM::EmulateLDRSBRegister,
13230 "ldrsb<c> <Rt>,[<Rn>,+/-<Rm>]{!}"},
13231 {0x0e5000f0, 0x005000f0, ARMvAll, eEncodingA1, No_VFP, eSize32,
13232 &EmulateInstructionARM::EmulateLDRSHImmediate,
13233 "ldrsh<c> <Rt>,[<Rn>{,#+/-<imm8>}]"},
13234 {0x0e5f00f0, 0x005f00f0, ARMvAll, eEncodingA1, No_VFP, eSize32,
13235 &EmulateInstructionARM::EmulateLDRSHLiteral, "ldrsh<c> <Rt>,<label>"},
13236 {0x0e5000f0, 0x001000f0, ARMvAll, eEncodingA1, No_VFP, eSize32,
13237 &EmulateInstructionARM::EmulateLDRSHRegister,
13238 "ldrsh<c> <Rt>,[<Rn>,+/-<Rm>]{!}"},
13239 {0x0e5000f0, 0x004000d0, ARMV5TE_ABOVE, eEncodingA1, No_VFP, eSize32,
13240 &EmulateInstructionARM::EmulateLDRDImmediate,
13241 "ldrd<c> <Rt>, <Rt2>, [<Rn>,#+/-<imm8>]!"},
13242 {0x0e500ff0, 0x000000d0, ARMV5TE_ABOVE, eEncodingA1, No_VFP, eSize32,
13243 &EmulateInstructionARM::EmulateLDRDRegister,
13244 "ldrd<c> <Rt>, <Rt2>, [<Rn>, +/-<Rm>]{!}"},
13245 {0x0e100f00, 0x0c100b00, ARMvAll, eEncodingA1, VFPv2_ABOVE, eSize32,
13246 &EmulateInstructionARM::EmulateVLDM, "vldm{mode}<c> <Rn>{!}, <list>"},
13247 {0x0e100f00, 0x0c100a00, ARMvAll, eEncodingA2, VFPv2v3, eSize32,
13248 &EmulateInstructionARM::EmulateVLDM, "vldm{mode}<c> <Rn>{!}, <list>"},
13249 {0x0f300f00, 0x0d100b00, ARMvAll, eEncodingA1, VFPv2_ABOVE, eSize32,
13250 &EmulateInstructionARM::EmulateVLDR, "vldr<c> <Dd>, [<Rn>{,#+/-<imm>}]"},
13251 {0x0f300f00, 0x0d100a00, ARMvAll, eEncodingA2, VFPv2v3, eSize32,
13252 &EmulateInstructionARM::EmulateVLDR, "vldr<c> <Sd>, [<Rn>{,#+/-<imm>}]"},
13253 {0xffb00000, 0xf4200000, ARMvAll, eEncodingA1, AdvancedSIMD, eSize32,
13254 &EmulateInstructionARM::EmulateVLD1Multiple,
13255 "vld1<c>.<size> <list>, [<Rn>{@<align>}], <Rm>"},
13256 {0xffb00300, 0xf4a00000, ARMvAll, eEncodingA1, AdvancedSIMD, eSize32,
13257 &EmulateInstructionARM::EmulateVLD1Single,
13258 "vld1<c>.<size> <list>, [<Rn>{@<align>}], <Rm>"},
13259 {0xffb00f00, 0xf4a00c00, ARMvAll, eEncodingA1, AdvancedSIMD, eSize32,
13260 &EmulateInstructionARM::EmulateVLD1SingleAll,
13261 "vld1<c>.<size> <list>, [<Rn>{@<align>}], <Rm>"},
13263 //----------------------------------------------------------------------
13264 // Store instructions
13265 //----------------------------------------------------------------------
13266 {0x0fd00000, 0x08800000, ARMvAll, eEncodingA1, No_VFP, eSize32,
13267 &EmulateInstructionARM::EmulateSTM, "stm<c> <Rn>{!} <registers>"},
13268 {0x0fd00000, 0x08000000, ARMvAll, eEncodingA1, No_VFP, eSize32,
13269 &EmulateInstructionARM::EmulateSTMDA, "stmda<c> <Rn>{!} <registers>"},
13270 {0x0fd00000, 0x09000000, ARMvAll, eEncodingA1, No_VFP, eSize32,
13271 &EmulateInstructionARM::EmulateSTMDB, "stmdb<c> <Rn>{!} <registers>"},
13272 {0x0fd00000, 0x09800000, ARMvAll, eEncodingA1, No_VFP, eSize32,
13273 &EmulateInstructionARM::EmulateSTMIB, "stmib<c> <Rn>{!} <registers>"},
13274 {0x0e500010, 0x06000000, ARMvAll, eEncodingA1, No_VFP, eSize32,
13275 &EmulateInstructionARM::EmulateSTRRegister,
13276 "str<c> <Rt> [<Rn> +/-<Rm> {<shift>}]{!}"},
13277 {0x0e5000f0, 0x000000b0, ARMvAll, eEncodingA1, No_VFP, eSize32,
13278 &EmulateInstructionARM::EmulateSTRHRegister,
13279 "strh<c> <Rt>,[<Rn>,+/-<Rm>[{!}"},
13280 {0x0ff00ff0, 0x01800f90, ARMV6_ABOVE, eEncodingA1, No_VFP, eSize32,
13281 &EmulateInstructionARM::EmulateSTREX, "strex<c> <Rd>, <Rt>, [<Rn>]"},
13282 {0x0e500000, 0x04400000, ARMvAll, eEncodingA1, No_VFP, eSize32,
13283 &EmulateInstructionARM::EmulateSTRBImmARM,
13284 "strb<c> <Rt>,[<Rn>,#+/-<imm12>]!"},
13285 {0x0e500000, 0x04000000, ARMvAll, eEncodingA1, No_VFP, eSize32,
13286 &EmulateInstructionARM::EmulateSTRImmARM,
13287 "str<c> <Rt>,[<Rn>,#+/-<imm12>]!"},
13288 {0x0e5000f0, 0x004000f0, ARMV5TE_ABOVE, eEncodingA1, No_VFP, eSize32,
13289 &EmulateInstructionARM::EmulateSTRDImm,
13290 "strd<c> <Rt>, <Rt2>, [<Rn> #+/-<imm8>]!"},
13291 {0x0e500ff0, 0x000000f0, ARMV5TE_ABOVE, eEncodingA1, No_VFP, eSize32,
13292 &EmulateInstructionARM::EmulateSTRDReg,
13293 "strd<c> <Rt>, <Rt2>, [<Rn>, +/-<Rm>]{!}"},
13294 {0x0e100f00, 0x0c000b00, ARMvAll, eEncodingA1, VFPv2_ABOVE, eSize32,
13295 &EmulateInstructionARM::EmulateVSTM, "vstm{mode}<c> <Rn>{!} <list>"},
13296 {0x0e100f00, 0x0c000a00, ARMvAll, eEncodingA2, VFPv2v3, eSize32,
13297 &EmulateInstructionARM::EmulateVSTM, "vstm{mode}<c> <Rn>{!} <list>"},
13298 {0x0f300f00, 0x0d000b00, ARMvAll, eEncodingA1, VFPv2_ABOVE, eSize32,
13299 &EmulateInstructionARM::EmulateVSTR, "vstr<c> <Dd> [<Rn>{,#+/-<imm>}]"},
13300 {0x0f300f00, 0x0d000a00, ARMvAll, eEncodingA2, VFPv2v3, eSize32,
13301 &EmulateInstructionARM::EmulateVSTR, "vstr<c> <Sd> [<Rn>{,#+/-<imm>}]"},
13302 {0xffb00000, 0xf4000000, ARMvAll, eEncodingA1, AdvancedSIMD, eSize32,
13303 &EmulateInstructionARM::EmulateVST1Multiple,
13304 "vst1<c>.<size> <list>, [<Rn>{@<align>}], <Rm>"},
13305 {0xffb00300, 0xf4800000, ARMvAll, eEncodingA1, AdvancedSIMD, eSize32,
13306 &EmulateInstructionARM::EmulateVST1Single,
13307 "vst1<c>.<size> <list>, [<Rn>{@<align>}], <Rm>"},
13309 //----------------------------------------------------------------------
13310 // Other instructions
13311 //----------------------------------------------------------------------
13312 {0x0fff00f0, 0x06af00f0, ARMV6_ABOVE, eEncodingA1, No_VFP, eSize32,
13313 &EmulateInstructionARM::EmulateSXTB, "sxtb<c> <Rd>,<Rm>{,<rotation>}"},
13314 {0x0fff00f0, 0x06bf0070, ARMV6_ABOVE, eEncodingA1, No_VFP, eSize32,
13315 &EmulateInstructionARM::EmulateSXTH, "sxth<c> <Rd>,<Rm>{,<rotation>}"},
13316 {0x0fff00f0, 0x06ef0070, ARMV6_ABOVE, eEncodingA1, No_VFP, eSize32,
13317 &EmulateInstructionARM::EmulateUXTB, "uxtb<c> <Rd>,<Rm>{,<rotation>}"},
13318 {0x0fff00f0, 0x06ff0070, ARMV6_ABOVE, eEncodingA1, No_VFP, eSize32,
13319 &EmulateInstructionARM::EmulateUXTH, "uxth<c> <Rd>,<Rm>{,<rotation>}"},
13320 {0xfe500000, 0xf8100000, ARMV6_ABOVE, eEncodingA1, No_VFP, eSize32,
13321 &EmulateInstructionARM::EmulateRFE, "rfe{<amode>} <Rn>{!}"}
13324 static const size_t k_num_arm_opcodes = llvm::array_lengthof(g_arm_opcodes);
13326 for (size_t i = 0; i < k_num_arm_opcodes; ++i) {
13327 if ((g_arm_opcodes[i].mask & opcode) == g_arm_opcodes[i].value &&
13328 (g_arm_opcodes[i].variants & arm_isa) != 0)
13329 return &g_arm_opcodes[i];
13334 EmulateInstructionARM::ARMOpcode *
13335 EmulateInstructionARM::GetThumbOpcodeForInstruction(const uint32_t opcode,
13336 uint32_t arm_isa) {
13338 static ARMOpcode g_thumb_opcodes[] = {
13339 //----------------------------------------------------------------------
13340 // Prologue instructions
13341 //----------------------------------------------------------------------
13343 // push register(s)
13344 {0xfffffe00, 0x0000b400, ARMvAll, eEncodingT1, No_VFP, eSize16,
13345 &EmulateInstructionARM::EmulatePUSH, "push <registers>"},
13346 {0xffff0000, 0xe92d0000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
13347 &EmulateInstructionARM::EmulatePUSH, "push.w <registers>"},
13348 {0xffff0fff, 0xf84d0d04, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32,
13349 &EmulateInstructionARM::EmulatePUSH, "push.w <register>"},
13351 // set r7 to point to a stack offset
13352 {0xffffff00, 0x0000af00, ARMvAll, eEncodingT1, No_VFP, eSize16,
13353 &EmulateInstructionARM::EmulateADDRdSPImm, "add r7, sp, #imm"},
13354 // copy the stack pointer to r7
13355 {0xffffffff, 0x0000466f, ARMvAll, eEncodingT1, No_VFP, eSize16,
13356 &EmulateInstructionARM::EmulateMOVRdSP, "mov r7, sp"},
13357 // move from high register to low register (comes after "mov r7, sp" to
13358 // resolve ambiguity)
13359 {0xffffffc0, 0x00004640, ARMvAll, eEncodingT1, No_VFP, eSize16,
13360 &EmulateInstructionARM::EmulateMOVLowHigh, "mov r0-r7, r8-r15"},
13362 // PC-relative load into register (see also EmulateADDSPRm)
13363 {0xfffff800, 0x00004800, ARMvAll, eEncodingT1, No_VFP, eSize16,
13364 &EmulateInstructionARM::EmulateLDRRtPCRelative, "ldr <Rt>, [PC, #imm]"},
13366 // adjust the stack pointer
13367 {0xffffff87, 0x00004485, ARMvAll, eEncodingT2, No_VFP, eSize16,
13368 &EmulateInstructionARM::EmulateADDSPRm, "add sp, <Rm>"},
13369 {0xffffff80, 0x0000b080, ARMvAll, eEncodingT1, No_VFP, eSize16,
13370 &EmulateInstructionARM::EmulateSUBSPImm, "sub sp, sp, #imm"},
13371 {0xfbef8f00, 0xf1ad0d00, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
13372 &EmulateInstructionARM::EmulateSUBSPImm, "sub.w sp, sp, #<const>"},
13373 {0xfbff8f00, 0xf2ad0d00, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32,
13374 &EmulateInstructionARM::EmulateSUBSPImm, "subw sp, sp, #imm12"},
13375 {0xffef8000, 0xebad0000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32,
13376 &EmulateInstructionARM::EmulateSUBSPReg,
13377 "sub{s}<c> <Rd>, sp, <Rm>{,<shift>}"},
13379 // vector push consecutive extension register(s)
13380 {0xffbf0f00, 0xed2d0b00, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32,
13381 &EmulateInstructionARM::EmulateVPUSH, "vpush.64 <list>"},
13382 {0xffbf0f00, 0xed2d0a00, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
13383 &EmulateInstructionARM::EmulateVPUSH, "vpush.32 <list>"},
13385 //----------------------------------------------------------------------
13386 // Epilogue instructions
13387 //----------------------------------------------------------------------
13389 {0xfffff800, 0x0000a800, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16,
13390 &EmulateInstructionARM::EmulateADDSPImm, "add<c> <Rd>, sp, #imm"},
13391 {0xffffff80, 0x0000b000, ARMvAll, eEncodingT2, No_VFP, eSize16,
13392 &EmulateInstructionARM::EmulateADDSPImm, "add sp, #imm"},
13393 {0xfffffe00, 0x0000bc00, ARMvAll, eEncodingT1, No_VFP, eSize16,
13394 &EmulateInstructionARM::EmulatePOP, "pop <registers>"},
13395 {0xffff0000, 0xe8bd0000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
13396 &EmulateInstructionARM::EmulatePOP, "pop.w <registers>"},
13397 {0xffff0fff, 0xf85d0d04, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32,
13398 &EmulateInstructionARM::EmulatePOP, "pop.w <register>"},
13399 {0xffbf0f00, 0xecbd0b00, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32,
13400 &EmulateInstructionARM::EmulateVPOP, "vpop.64 <list>"},
13401 {0xffbf0f00, 0xecbd0a00, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
13402 &EmulateInstructionARM::EmulateVPOP, "vpop.32 <list>"},
13404 //----------------------------------------------------------------------
13405 // Supervisor Call (previously Software Interrupt)
13406 //----------------------------------------------------------------------
13407 {0xffffff00, 0x0000df00, ARMvAll, eEncodingT1, No_VFP, eSize16,
13408 &EmulateInstructionARM::EmulateSVC, "svc #imm8"},
13410 //----------------------------------------------------------------------
13411 // If Then makes up to four following instructions conditional.
13412 //----------------------------------------------------------------------
13413 // The next 5 opcode _must_ come before the if then instruction
13414 {0xffffffff, 0x0000bf00, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize16,
13415 &EmulateInstructionARM::EmulateNop, "nop"},
13416 {0xffffffff, 0x0000bf10, ARMV7_ABOVE, eEncodingT1, No_VFP, eSize16,
13417 &EmulateInstructionARM::EmulateNop, "nop YIELD (yield hint)"},
13418 {0xffffffff, 0x0000bf20, ARMV7_ABOVE, eEncodingT1, No_VFP, eSize16,
13419 &EmulateInstructionARM::EmulateNop, "nop WFE (wait for event hint)"},
13420 {0xffffffff, 0x0000bf30, ARMV7_ABOVE, eEncodingT1, No_VFP, eSize16,
13421 &EmulateInstructionARM::EmulateNop, "nop WFI (wait for interrupt hint)"},
13422 {0xffffffff, 0x0000bf40, ARMV7_ABOVE, eEncodingT1, No_VFP, eSize16,
13423 &EmulateInstructionARM::EmulateNop, "nop SEV (send event hint)"},
13424 {0xffffff00, 0x0000bf00, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize16,
13425 &EmulateInstructionARM::EmulateIT, "it{<x>{<y>{<z>}}} <firstcond>"},
13427 //----------------------------------------------------------------------
13428 // Branch instructions
13429 //----------------------------------------------------------------------
13430 // To resolve ambiguity, "b<c> #imm8" should come after "svc #imm8".
13431 {0xfffff000, 0x0000d000, ARMvAll, eEncodingT1, No_VFP, eSize16,
13432 &EmulateInstructionARM::EmulateB, "b<c> #imm8 (outside IT)"},
13433 {0xfffff800, 0x0000e000, ARMvAll, eEncodingT2, No_VFP, eSize16,
13434 &EmulateInstructionARM::EmulateB, "b<c> #imm11 (outside or last in IT)"},
13435 {0xf800d000, 0xf0008000, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32,
13436 &EmulateInstructionARM::EmulateB, "b<c>.w #imm8 (outside IT)"},
13437 {0xf800d000, 0xf0009000, ARMV6T2_ABOVE, eEncodingT4, No_VFP, eSize32,
13438 &EmulateInstructionARM::EmulateB,
13439 "b<c>.w #imm8 (outside or last in IT)"},
13441 {0xf800d000, 0xf000d000, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize32,
13442 &EmulateInstructionARM::EmulateBLXImmediate, "bl <label>"},
13444 {0xf800d001, 0xf000c000, ARMV5_ABOVE, eEncodingT2, No_VFP, eSize32,
13445 &EmulateInstructionARM::EmulateBLXImmediate, "blx <label>"},
13446 {0xffffff87, 0x00004780, ARMV5_ABOVE, eEncodingT1, No_VFP, eSize16,
13447 &EmulateInstructionARM::EmulateBLXRm, "blx <Rm>"},
13448 // for example, "bx lr"
13449 {0xffffff87, 0x00004700, ARMvAll, eEncodingT1, No_VFP, eSize32,
13450 &EmulateInstructionARM::EmulateBXRm, "bx <Rm>"},
13452 {0xfff0ffff, 0xf3c08f00, ARMV5J_ABOVE, eEncodingT1, No_VFP, eSize32,
13453 &EmulateInstructionARM::EmulateBXJRm, "bxj <Rm>"},
13454 // compare and branch
13455 {0xfffff500, 0x0000b100, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize16,
13456 &EmulateInstructionARM::EmulateCB, "cb{n}z <Rn>, <label>"},
13457 // table branch byte
13458 {0xfff0fff0, 0xe8d0f000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32,
13459 &EmulateInstructionARM::EmulateTB, "tbb<c> <Rn>, <Rm>"},
13460 // table branch halfword
13461 {0xfff0fff0, 0xe8d0f010, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32,
13462 &EmulateInstructionARM::EmulateTB, "tbh<c> <Rn>, <Rm>, lsl #1"},
13464 //----------------------------------------------------------------------
13465 // Data-processing instructions
13466 //----------------------------------------------------------------------
13468 {0xfbe08000, 0xf1400000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32,
13469 &EmulateInstructionARM::EmulateADCImm, "adc{s}<c> <Rd>, <Rn>, #<const>"},
13471 {0xffffffc0, 0x00004140, ARMvAll, eEncodingT1, No_VFP, eSize16,
13472 &EmulateInstructionARM::EmulateADCReg, "adcs|adc<c> <Rdn>, <Rm>"},
13473 {0xffe08000, 0xeb400000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
13474 &EmulateInstructionARM::EmulateADCReg,
13475 "adc{s}<c>.w <Rd>, <Rn>, <Rm> {,<shift>}"},
13477 {0xfffffe00, 0x00001800, ARMvAll, eEncodingT1, No_VFP, eSize16,
13478 &EmulateInstructionARM::EmulateADDReg, "adds|add<c> <Rd>, <Rn>, <Rm>"},
13479 // Make sure "add sp, <Rm>" comes before this instruction, so there's no
13480 // ambiguity decoding the two.
13481 {0xffffff00, 0x00004400, ARMvAll, eEncodingT2, No_VFP, eSize16,
13482 &EmulateInstructionARM::EmulateADDReg, "add<c> <Rdn>, <Rm>"},
13484 {0xfffff800, 0x0000a000, ARMvAll, eEncodingT1, No_VFP, eSize16,
13485 &EmulateInstructionARM::EmulateADR, "add<c> <Rd>, PC, #<const>"},
13486 {0xfbff8000, 0xf2af0000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
13487 &EmulateInstructionARM::EmulateADR, "sub<c> <Rd>, PC, #<const>"},
13488 {0xfbff8000, 0xf20f0000, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32,
13489 &EmulateInstructionARM::EmulateADR, "add<c> <Rd>, PC, #<const>"},
13491 {0xfbe08000, 0xf0000000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32,
13492 &EmulateInstructionARM::EmulateANDImm, "and{s}<c> <Rd>, <Rn>, #<const>"},
13494 {0xffffffc0, 0x00004000, ARMvAll, eEncodingT1, No_VFP, eSize16,
13495 &EmulateInstructionARM::EmulateANDReg, "ands|and<c> <Rdn>, <Rm>"},
13496 {0xffe08000, 0xea000000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
13497 &EmulateInstructionARM::EmulateANDReg,
13498 "and{s}<c>.w <Rd>, <Rn>, <Rm> {,<shift>}"},
13500 {0xfbe08000, 0xf0200000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32,
13501 &EmulateInstructionARM::EmulateBICImm, "bic{s}<c> <Rd>, <Rn>, #<const>"},
13503 {0xffffffc0, 0x00004380, ARMvAll, eEncodingT1, No_VFP, eSize16,
13504 &EmulateInstructionARM::EmulateBICReg, "bics|bic<c> <Rdn>, <Rm>"},
13505 {0xffe08000, 0xea200000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
13506 &EmulateInstructionARM::EmulateBICReg,
13507 "bic{s}<c>.w <Rd>, <Rn>, <Rm> {,<shift>}"},
13509 {0xfbe08000, 0xf0800000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32,
13510 &EmulateInstructionARM::EmulateEORImm, "eor{s}<c> <Rd>, <Rn>, #<const>"},
13512 {0xffffffc0, 0x00004040, ARMvAll, eEncodingT1, No_VFP, eSize16,
13513 &EmulateInstructionARM::EmulateEORReg, "eors|eor<c> <Rdn>, <Rm>"},
13514 {0xffe08000, 0xea800000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
13515 &EmulateInstructionARM::EmulateEORReg,
13516 "eor{s}<c>.w <Rd>, <Rn>, <Rm> {,<shift>}"},
13518 {0xfbe08000, 0xf0400000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32,
13519 &EmulateInstructionARM::EmulateORRImm, "orr{s}<c> <Rd>, <Rn>, #<const>"},
13521 {0xffffffc0, 0x00004300, ARMvAll, eEncodingT1, No_VFP, eSize16,
13522 &EmulateInstructionARM::EmulateORRReg, "orrs|orr<c> <Rdn>, <Rm>"},
13523 {0xffe08000, 0xea400000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
13524 &EmulateInstructionARM::EmulateORRReg,
13525 "orr{s}<c>.w <Rd>, <Rn>, <Rm> {,<shift>}"},
13527 {0xffffffc0, 0x00004240, ARMvAll, eEncodingT1, No_VFP, eSize16,
13528 &EmulateInstructionARM::EmulateRSBImm, "rsbs|rsb<c> <Rd>, <Rn>, #0"},
13529 {0xfbe08000, 0xf1c00000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
13530 &EmulateInstructionARM::EmulateRSBImm,
13531 "rsb{s}<c>.w <Rd>, <Rn>, #<const>"},
13533 {0xffe08000, 0xea400000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32,
13534 &EmulateInstructionARM::EmulateRSBReg,
13535 "rsb{s}<c>.w <Rd>, <Rn>, <Rm> {,<shift>}"},
13537 {0xfbe08000, 0xf1600000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32,
13538 &EmulateInstructionARM::EmulateSBCImm, "sbc{s}<c> <Rd>, <Rn>, #<const>"},
13540 {0xffffffc0, 0x00004180, ARMvAll, eEncodingT1, No_VFP, eSize16,
13541 &EmulateInstructionARM::EmulateSBCReg, "sbcs|sbc<c> <Rdn>, <Rm>"},
13542 {0xffe08000, 0xeb600000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
13543 &EmulateInstructionARM::EmulateSBCReg,
13544 "sbc{s}<c>.w <Rd>, <Rn>, <Rm> {,<shift>}"},
13545 // add (immediate, Thumb)
13546 {0xfffffe00, 0x00001c00, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16,
13547 &EmulateInstructionARM::EmulateADDImmThumb,
13548 "adds|add<c> <Rd>,<Rn>,#<imm3>"},
13549 {0xfffff800, 0x00003000, ARMV4T_ABOVE, eEncodingT2, No_VFP, eSize16,
13550 &EmulateInstructionARM::EmulateADDImmThumb, "adds|add<c> <Rdn>,#<imm8>"},
13551 {0xfbe08000, 0xf1000000, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32,
13552 &EmulateInstructionARM::EmulateADDImmThumb,
13553 "add{s}<c>.w <Rd>,<Rn>,#<const>"},
13554 {0xfbf08000, 0xf2000000, ARMV6T2_ABOVE, eEncodingT4, No_VFP, eSize32,
13555 &EmulateInstructionARM::EmulateADDImmThumb,
13556 "addw<c> <Rd>,<Rn>,#<imm12>"},
13557 // sub (immediate, Thumb)
13558 {0xfffffe00, 0x00001e00, ARMvAll, eEncodingT1, No_VFP, eSize16,
13559 &EmulateInstructionARM::EmulateSUBImmThumb,
13560 "subs|sub<c> <Rd>, <Rn> #imm3"},
13561 {0xfffff800, 0x00003800, ARMvAll, eEncodingT2, No_VFP, eSize16,
13562 &EmulateInstructionARM::EmulateSUBImmThumb, "subs|sub<c> <Rdn>, #imm8"},
13563 {0xfbe08000, 0xf1a00000, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32,
13564 &EmulateInstructionARM::EmulateSUBImmThumb,
13565 "sub{s}<c>.w <Rd>, <Rn>, #<const>"},
13566 {0xfbf08000, 0xf2a00000, ARMV6T2_ABOVE, eEncodingT4, No_VFP, eSize32,
13567 &EmulateInstructionARM::EmulateSUBImmThumb,
13568 "subw<c> <Rd>, <Rn>, #imm12"},
13569 // sub (sp minus immediate)
13570 {0xfbef8000, 0xf1ad0000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
13571 &EmulateInstructionARM::EmulateSUBSPImm, "sub{s}.w <Rd>, sp, #<const>"},
13572 {0xfbff8000, 0xf2ad0000, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32,
13573 &EmulateInstructionARM::EmulateSUBSPImm, "subw<c> <Rd>, sp, #imm12"},
13575 {0xfffffe00, 0x00001a00, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16,
13576 &EmulateInstructionARM::EmulateSUBReg, "subs|sub<c> <Rd>, <Rn>, <Rm>"},
13577 {0xffe08000, 0xeba00000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
13578 &EmulateInstructionARM::EmulateSUBReg,
13579 "sub{s}<c>.w <Rd>, <Rn>, <Rm>{,<shift>}"},
13581 {0xfbf08f00, 0xf0900f00, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32,
13582 &EmulateInstructionARM::EmulateTEQImm, "teq<c> <Rn>, #<const>"},
13584 {0xfff08f00, 0xea900f00, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32,
13585 &EmulateInstructionARM::EmulateTEQReg, "teq<c> <Rn>, <Rm> {,<shift>}"},
13587 {0xfbf08f00, 0xf0100f00, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32,
13588 &EmulateInstructionARM::EmulateTSTImm, "tst<c> <Rn>, #<const>"},
13590 {0xffffffc0, 0x00004200, ARMvAll, eEncodingT1, No_VFP, eSize16,
13591 &EmulateInstructionARM::EmulateTSTReg, "tst<c> <Rdn>, <Rm>"},
13592 {0xfff08f00, 0xea100f00, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
13593 &EmulateInstructionARM::EmulateTSTReg, "tst<c>.w <Rn>, <Rm> {,<shift>}"},
13595 // move from high register to high register
13596 {0xffffff00, 0x00004600, ARMvAll, eEncodingT1, No_VFP, eSize16,
13597 &EmulateInstructionARM::EmulateMOVRdRm, "mov<c> <Rd>, <Rm>"},
13598 // move from low register to low register
13599 {0xffffffc0, 0x00000000, ARMvAll, eEncodingT2, No_VFP, eSize16,
13600 &EmulateInstructionARM::EmulateMOVRdRm, "movs <Rd>, <Rm>"},
13601 // mov{s}<c>.w <Rd>, <Rm>
13602 {0xffeff0f0, 0xea4f0000, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32,
13603 &EmulateInstructionARM::EmulateMOVRdRm, "mov{s}<c>.w <Rd>, <Rm>"},
13605 {0xfffff800, 0x00002000, ARMvAll, eEncodingT1, No_VFP, eSize16,
13606 &EmulateInstructionARM::EmulateMOVRdImm, "movs|mov<c> <Rd>, #imm8"},
13607 {0xfbef8000, 0xf04f0000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
13608 &EmulateInstructionARM::EmulateMOVRdImm, "mov{s}<c>.w <Rd>, #<const>"},
13609 {0xfbf08000, 0xf2400000, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32,
13610 &EmulateInstructionARM::EmulateMOVRdImm, "movw<c> <Rd>,#<imm16>"},
13612 {0xfbef8000, 0xf06f0000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32,
13613 &EmulateInstructionARM::EmulateMVNImm, "mvn{s} <Rd>, #<const>"},
13615 {0xffffffc0, 0x000043c0, ARMvAll, eEncodingT1, No_VFP, eSize16,
13616 &EmulateInstructionARM::EmulateMVNReg, "mvns|mvn<c> <Rd>, <Rm>"},
13617 {0xffef8000, 0xea6f0000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
13618 &EmulateInstructionARM::EmulateMVNReg,
13619 "mvn{s}<c>.w <Rd>, <Rm> {,<shift>}"},
13621 {0xfbf08f00, 0xf1100f00, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32,
13622 &EmulateInstructionARM::EmulateCMNImm, "cmn<c> <Rn>, #<const>"},
13624 {0xffffffc0, 0x000042c0, ARMvAll, eEncodingT1, No_VFP, eSize16,
13625 &EmulateInstructionARM::EmulateCMNReg, "cmn<c> <Rn>, <Rm>"},
13626 {0xfff08f00, 0xeb100f00, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
13627 &EmulateInstructionARM::EmulateCMNReg, "cmn<c> <Rn>, <Rm> {,<shift>}"},
13629 {0xfffff800, 0x00002800, ARMvAll, eEncodingT1, No_VFP, eSize16,
13630 &EmulateInstructionARM::EmulateCMPImm, "cmp<c> <Rn>, #imm8"},
13631 {0xfbf08f00, 0xf1b00f00, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
13632 &EmulateInstructionARM::EmulateCMPImm, "cmp<c>.w <Rn>, #<const>"},
13633 // cmp (register) (Rn and Rm both from r0-r7)
13634 {0xffffffc0, 0x00004280, ARMvAll, eEncodingT1, No_VFP, eSize16,
13635 &EmulateInstructionARM::EmulateCMPReg, "cmp<c> <Rn>, <Rm>"},
13636 // cmp (register) (Rn and Rm not both from r0-r7)
13637 {0xffffff00, 0x00004500, ARMvAll, eEncodingT2, No_VFP, eSize16,
13638 &EmulateInstructionARM::EmulateCMPReg, "cmp<c> <Rn>, <Rm>"},
13639 {0xfff08f00, 0xebb00f00, ARMvAll, eEncodingT3, No_VFP, eSize16,
13640 &EmulateInstructionARM::EmulateCMPReg,
13641 "cmp<c>.w <Rn>, <Rm> {, <shift>}"},
13643 {0xfffff800, 0x00001000, ARMvAll, eEncodingT1, No_VFP, eSize16,
13644 &EmulateInstructionARM::EmulateASRImm, "asrs|asr<c> <Rd>, <Rm>, #imm"},
13645 {0xffef8030, 0xea4f0020, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
13646 &EmulateInstructionARM::EmulateASRImm, "asr{s}<c>.w <Rd>, <Rm>, #imm"},
13648 {0xffffffc0, 0x00004100, ARMvAll, eEncodingT1, No_VFP, eSize16,
13649 &EmulateInstructionARM::EmulateASRReg, "asrs|asr<c> <Rdn>, <Rm>"},
13650 {0xffe0f0f0, 0xfa40f000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
13651 &EmulateInstructionARM::EmulateASRReg, "asr{s}<c>.w <Rd>, <Rn>, <Rm>"},
13653 {0xfffff800, 0x00000000, ARMvAll, eEncodingT1, No_VFP, eSize16,
13654 &EmulateInstructionARM::EmulateLSLImm, "lsls|lsl<c> <Rd>, <Rm>, #imm"},
13655 {0xffef8030, 0xea4f0000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
13656 &EmulateInstructionARM::EmulateLSLImm, "lsl{s}<c>.w <Rd>, <Rm>, #imm"},
13658 {0xffffffc0, 0x00004080, ARMvAll, eEncodingT1, No_VFP, eSize16,
13659 &EmulateInstructionARM::EmulateLSLReg, "lsls|lsl<c> <Rdn>, <Rm>"},
13660 {0xffe0f0f0, 0xfa00f000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
13661 &EmulateInstructionARM::EmulateLSLReg, "lsl{s}<c>.w <Rd>, <Rn>, <Rm>"},
13663 {0xfffff800, 0x00000800, ARMvAll, eEncodingT1, No_VFP, eSize16,
13664 &EmulateInstructionARM::EmulateLSRImm, "lsrs|lsr<c> <Rd>, <Rm>, #imm"},
13665 {0xffef8030, 0xea4f0010, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
13666 &EmulateInstructionARM::EmulateLSRImm, "lsr{s}<c>.w <Rd>, <Rm>, #imm"},
13668 {0xffffffc0, 0x000040c0, ARMvAll, eEncodingT1, No_VFP, eSize16,
13669 &EmulateInstructionARM::EmulateLSRReg, "lsrs|lsr<c> <Rdn>, <Rm>"},
13670 {0xffe0f0f0, 0xfa20f000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
13671 &EmulateInstructionARM::EmulateLSRReg, "lsr{s}<c>.w <Rd>, <Rn>, <Rm>"},
13672 // rrx is a special case encoding of ror (immediate)
13673 {0xffeff0f0, 0xea4f0030, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32,
13674 &EmulateInstructionARM::EmulateRRX, "rrx{s}<c>.w <Rd>, <Rm>"},
13676 {0xffef8030, 0xea4f0030, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32,
13677 &EmulateInstructionARM::EmulateRORImm, "ror{s}<c>.w <Rd>, <Rm>, #imm"},
13679 {0xffffffc0, 0x000041c0, ARMvAll, eEncodingT1, No_VFP, eSize16,
13680 &EmulateInstructionARM::EmulateRORReg, "rors|ror<c> <Rdn>, <Rm>"},
13681 {0xffe0f0f0, 0xfa60f000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
13682 &EmulateInstructionARM::EmulateRORReg, "ror{s}<c>.w <Rd>, <Rn>, <Rm>"},
13684 {0xffffffc0, 0x00004340, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16,
13685 &EmulateInstructionARM::EmulateMUL, "muls <Rdm>,<Rn>,<Rdm>"},
13687 {0xfff0f0f0, 0xfb00f000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
13688 &EmulateInstructionARM::EmulateMUL, "mul<c> <Rd>,<Rn>,<Rm>"},
13690 // subs pc, lr and related instructions
13691 {0xffffff00, 0xf3de8f00, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32,
13692 &EmulateInstructionARM::EmulateSUBSPcLrEtc, "SUBS<c> PC, LR, #<imm8>"},
13694 //----------------------------------------------------------------------
13695 // RFE instructions *** IMPORTANT *** THESE MUST BE LISTED **BEFORE** THE
13696 // LDM.. Instructions in this table;
13697 // otherwise the wrong instructions will be selected.
13698 //----------------------------------------------------------------------
13700 {0xffd0ffff, 0xe810c000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32,
13701 &EmulateInstructionARM::EmulateRFE, "rfedb<c> <Rn>{!}"},
13702 {0xffd0ffff, 0xe990c000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
13703 &EmulateInstructionARM::EmulateRFE, "rfe{ia}<c> <Rn>{!}"},
13705 //----------------------------------------------------------------------
13706 // Load instructions
13707 //----------------------------------------------------------------------
13708 {0xfffff800, 0x0000c800, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16,
13709 &EmulateInstructionARM::EmulateLDM, "ldm<c> <Rn>{!} <registers>"},
13710 {0xffd02000, 0xe8900000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
13711 &EmulateInstructionARM::EmulateLDM, "ldm<c>.w <Rn>{!} <registers>"},
13712 {0xffd00000, 0xe9100000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32,
13713 &EmulateInstructionARM::EmulateLDMDB, "ldmdb<c> <Rn>{!} <registers>"},
13714 {0xfffff800, 0x00006800, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16,
13715 &EmulateInstructionARM::EmulateLDRRtRnImm, "ldr<c> <Rt>, [<Rn>{,#imm}]"},
13716 {0xfffff800, 0x00009800, ARMV4T_ABOVE, eEncodingT2, No_VFP, eSize16,
13717 &EmulateInstructionARM::EmulateLDRRtRnImm, "ldr<c> <Rt>, [SP{,#imm}]"},
13718 {0xfff00000, 0xf8d00000, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32,
13719 &EmulateInstructionARM::EmulateLDRRtRnImm,
13720 "ldr<c>.w <Rt>, [<Rn>{,#imm12}]"},
13721 {0xfff00800, 0xf8500800, ARMV6T2_ABOVE, eEncodingT4, No_VFP, eSize32,
13722 &EmulateInstructionARM::EmulateLDRRtRnImm,
13723 "ldr<c> <Rt>, [<Rn>{,#+/-<imm8>}]{!}"},
13724 // Thumb2 PC-relative load into register
13725 {0xff7f0000, 0xf85f0000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
13726 &EmulateInstructionARM::EmulateLDRRtPCRelative,
13727 "ldr<c>.w <Rt>, [PC, +/-#imm}]"},
13728 {0xfffffe00, 0x00005800, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16,
13729 &EmulateInstructionARM::EmulateLDRRegister, "ldr<c> <Rt>, [<Rn>, <Rm>]"},
13730 {0xfff00fc0, 0xf8500000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
13731 &EmulateInstructionARM::EmulateLDRRegister,
13732 "ldr<c>.w <Rt>, [<Rn>,<Rm>{,LSL #<imm2>}]"},
13733 {0xfffff800, 0x00007800, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16,
13734 &EmulateInstructionARM::EmulateLDRBImmediate,
13735 "ldrb<c> <Rt>,[<Rn>{,#<imm5>}]"},
13736 {0xfff00000, 0xf8900000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
13737 &EmulateInstructionARM::EmulateLDRBImmediate,
13738 "ldrb<c>.w <Rt>,[<Rn>{,#<imm12>}]"},
13739 {0xfff00800, 0xf8100800, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32,
13740 &EmulateInstructionARM::EmulateLDRBImmediate,
13741 "ldrb<c> <Rt>,[<Rn>, #+/-<imm8>]{!}"},
13742 {0xff7f0000, 0xf81f0000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32,
13743 &EmulateInstructionARM::EmulateLDRBLiteral, "ldrb<c> <Rt>,[...]"},
13744 {0xfffffe00, 0x00005c00, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize16,
13745 &EmulateInstructionARM::EmulateLDRBRegister, "ldrb<c> <Rt>,[<Rn>,<Rm>]"},
13746 {0xfff00fc0, 0xf8100000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
13747 &EmulateInstructionARM::EmulateLDRBRegister,
13748 "ldrb<c>.w <Rt>,[<Rn>,<Rm>{,LSL #imm2>}]"},
13749 {0xfffff800, 0x00008800, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16,
13750 &EmulateInstructionARM::EmulateLDRHImmediate,
13751 "ldrh<c> <Rt>, [<Rn>{,#<imm>}]"},
13752 {0xfff00000, 0xf8b00000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
13753 &EmulateInstructionARM::EmulateLDRHImmediate,
13754 "ldrh<c>.w <Rt>,[<Rn>{,#<imm12>}]"},
13755 {0xfff00800, 0xf8300800, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32,
13756 &EmulateInstructionARM::EmulateLDRHImmediate,
13757 "ldrh<c> <Rt>,[<Rn>,#+/-<imm8>]{!}"},
13758 {0xff7f0000, 0xf83f0000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32,
13759 &EmulateInstructionARM::EmulateLDRHLiteral, "ldrh<c> <Rt>, <label>"},
13760 {0xfffffe00, 0x00005a00, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16,
13761 &EmulateInstructionARM::EmulateLDRHRegister,
13762 "ldrh<c> <Rt>, [<Rn>,<Rm>]"},
13763 {0xfff00fc0, 0xf8300000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
13764 &EmulateInstructionARM::EmulateLDRHRegister,
13765 "ldrh<c>.w <Rt>,[<Rn>,<Rm>{,LSL #<imm2>}]"},
13766 {0xfff00000, 0xf9900000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32,
13767 &EmulateInstructionARM::EmulateLDRSBImmediate,
13768 "ldrsb<c> <Rt>,[<Rn>,#<imm12>]"},
13769 {0xfff00800, 0xf9100800, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
13770 &EmulateInstructionARM::EmulateLDRSBImmediate,
13771 "ldrsb<c> <Rt>,[<Rn>,#+/-<imm8>]"},
13772 {0xff7f0000, 0xf91f0000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32,
13773 &EmulateInstructionARM::EmulateLDRSBLiteral, "ldrsb<c> <Rt>, <label>"},
13774 {0xfffffe00, 0x00005600, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16,
13775 &EmulateInstructionARM::EmulateLDRSBRegister,
13776 "ldrsb<c> <Rt>,[<Rn>,<Rm>]"},
13777 {0xfff00fc0, 0xf9100000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
13778 &EmulateInstructionARM::EmulateLDRSBRegister,
13779 "ldrsb<c>.w <Rt>,[<Rn>,<Rm>{,LSL #imm2>}]"},
13780 {0xfff00000, 0xf9b00000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32,
13781 &EmulateInstructionARM::EmulateLDRSHImmediate,
13782 "ldrsh<c> <Rt>,[<Rn>,#<imm12>]"},
13783 {0xfff00800, 0xf9300800, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
13784 &EmulateInstructionARM::EmulateLDRSHImmediate,
13785 "ldrsh<c> <Rt>,[<Rn>,#+/-<imm8>]"},
13786 {0xff7f0000, 0xf93f0000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32,
13787 &EmulateInstructionARM::EmulateLDRSHLiteral, "ldrsh<c> <Rt>,<label>"},
13788 {0xfffffe00, 0x00005e00, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16,
13789 &EmulateInstructionARM::EmulateLDRSHRegister,
13790 "ldrsh<c> <Rt>,[<Rn>,<Rm>]"},
13791 {0xfff00fc0, 0xf9300000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
13792 &EmulateInstructionARM::EmulateLDRSHRegister,
13793 "ldrsh<c>.w <Rt>,[<Rn>,<Rm>{,LSL #<imm2>}]"},
13794 {0xfe500000, 0xe8500000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32,
13795 &EmulateInstructionARM::EmulateLDRDImmediate,
13796 "ldrd<c> <Rt>, <Rt2>, [<Rn>,#+/-<imm>]!"},
13797 {0xfe100f00, 0xec100b00, ARMvAll, eEncodingT1, VFPv2_ABOVE, eSize32,
13798 &EmulateInstructionARM::EmulateVLDM, "vldm{mode}<c> <Rn>{!}, <list>"},
13799 {0xfe100f00, 0xec100a00, ARMvAll, eEncodingT2, VFPv2v3, eSize32,
13800 &EmulateInstructionARM::EmulateVLDM, "vldm{mode}<c> <Rn>{!}, <list>"},
13801 {0xffe00f00, 0xed100b00, ARMvAll, eEncodingT1, VFPv2_ABOVE, eSize32,
13802 &EmulateInstructionARM::EmulateVLDR, "vldr<c> <Dd>, [<Rn>{,#+/-<imm>}]"},
13803 {0xff300f00, 0xed100a00, ARMvAll, eEncodingT2, VFPv2v3, eSize32,
13804 &EmulateInstructionARM::EmulateVLDR, "vldr<c> <Sd>, {<Rn>{,#+/-<imm>}]"},
13805 {0xffb00000, 0xf9200000, ARMvAll, eEncodingT1, AdvancedSIMD, eSize32,
13806 &EmulateInstructionARM::EmulateVLD1Multiple,
13807 "vld1<c>.<size> <list>, [<Rn>{@<align>}],<Rm>"},
13808 {0xffb00300, 0xf9a00000, ARMvAll, eEncodingT1, AdvancedSIMD, eSize32,
13809 &EmulateInstructionARM::EmulateVLD1Single,
13810 "vld1<c>.<size> <list>, [<Rn>{@<align>}],<Rm>"},
13811 {0xffb00f00, 0xf9a00c00, ARMvAll, eEncodingT1, AdvancedSIMD, eSize32,
13812 &EmulateInstructionARM::EmulateVLD1SingleAll,
13813 "vld1<c>.<size> <list>, [<Rn>{@<align>}], <Rm>"},
13815 //----------------------------------------------------------------------
13816 // Store instructions
13817 //----------------------------------------------------------------------
13818 {0xfffff800, 0x0000c000, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16,
13819 &EmulateInstructionARM::EmulateSTM, "stm<c> <Rn>{!} <registers>"},
13820 {0xffd00000, 0xe8800000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
13821 &EmulateInstructionARM::EmulateSTM, "stm<c>.w <Rn>{!} <registers>"},
13822 {0xffd00000, 0xe9000000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32,
13823 &EmulateInstructionARM::EmulateSTMDB, "stmdb<c> <Rn>{!} <registers>"},
13824 {0xfffff800, 0x00006000, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16,
13825 &EmulateInstructionARM::EmulateSTRThumb, "str<c> <Rt>, [<Rn>{,#<imm>}]"},
13826 {0xfffff800, 0x00009000, ARMV4T_ABOVE, eEncodingT2, No_VFP, eSize16,
13827 &EmulateInstructionARM::EmulateSTRThumb, "str<c> <Rt>, [SP,#<imm>]"},
13828 {0xfff00000, 0xf8c00000, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32,
13829 &EmulateInstructionARM::EmulateSTRThumb,
13830 "str<c>.w <Rt>, [<Rn>,#<imm12>]"},
13831 {0xfff00800, 0xf8400800, ARMV6T2_ABOVE, eEncodingT4, No_VFP, eSize32,
13832 &EmulateInstructionARM::EmulateSTRThumb,
13833 "str<c> <Rt>, [<Rn>,#+/-<imm8>]"},
13834 {0xfffffe00, 0x00005000, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16,
13835 &EmulateInstructionARM::EmulateSTRRegister, "str<c> <Rt> ,{<Rn>, <Rm>]"},
13836 {0xfff00fc0, 0xf8400000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
13837 &EmulateInstructionARM::EmulateSTRRegister,
13838 "str<c>.w <Rt>, [<Rn>, <Rm> {lsl #imm2>}]"},
13839 {0xfffff800, 0x00007000, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16,
13840 &EmulateInstructionARM::EmulateSTRBThumb,
13841 "strb<c> <Rt>, [<Rn>, #<imm5>]"},
13842 {0xfff00000, 0xf8800000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
13843 &EmulateInstructionARM::EmulateSTRBThumb,
13844 "strb<c>.w <Rt>, [<Rn>, #<imm12>]"},
13845 {0xfff00800, 0xf8000800, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32,
13846 &EmulateInstructionARM::EmulateSTRBThumb,
13847 "strb<c> <Rt> ,[<Rn>, #+/-<imm8>]{!}"},
13848 {0xfffffe00, 0x00005200, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16,
13849 &EmulateInstructionARM::EmulateSTRHRegister, "strh<c> <Rt>,[<Rn>,<Rm>]"},
13850 {0xfff00fc0, 0xf8200000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
13851 &EmulateInstructionARM::EmulateSTRHRegister,
13852 "strh<c>.w <Rt>,[<Rn>,<Rm>{,LSL #<imm2>}]"},
13853 {0xfff00000, 0xe8400000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32,
13854 &EmulateInstructionARM::EmulateSTREX,
13855 "strex<c> <Rd>, <Rt>, [<Rn{,#<imm>}]"},
13856 {0xfe500000, 0xe8400000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32,
13857 &EmulateInstructionARM::EmulateSTRDImm,
13858 "strd<c> <Rt>, <Rt2>, [<Rn>, #+/-<imm>]!"},
13859 {0xfe100f00, 0xec000b00, ARMvAll, eEncodingT1, VFPv2_ABOVE, eSize32,
13860 &EmulateInstructionARM::EmulateVSTM, "vstm{mode}<c> <Rn>{!}, <list>"},
13861 {0xfea00f00, 0xec000a00, ARMvAll, eEncodingT2, VFPv2v3, eSize32,
13862 &EmulateInstructionARM::EmulateVSTM, "vstm{mode}<c> <Rn>{!}, <list>"},
13863 {0xff300f00, 0xed000b00, ARMvAll, eEncodingT1, VFPv2_ABOVE, eSize32,
13864 &EmulateInstructionARM::EmulateVSTR, "vstr<c> <Dd>, [<Rn>{,#+/-<imm>}]"},
13865 {0xff300f00, 0xed000a00, ARMvAll, eEncodingT2, VFPv2v3, eSize32,
13866 &EmulateInstructionARM::EmulateVSTR, "vstr<c> <Sd>, [<Rn>{,#+/-<imm>}]"},
13867 {0xffb00000, 0xf9000000, ARMvAll, eEncodingT1, AdvancedSIMD, eSize32,
13868 &EmulateInstructionARM::EmulateVST1Multiple,
13869 "vst1<c>.<size> <list>, [<Rn>{@<align>}], <Rm>"},
13870 {0xffb00300, 0xf9800000, ARMvAll, eEncodingT1, AdvancedSIMD, eSize32,
13871 &EmulateInstructionARM::EmulateVST1Single,
13872 "vst1<c>.<size> <list>, [<Rn>{@<align>}], <Rm>"},
13874 //----------------------------------------------------------------------
13875 // Other instructions
13876 //----------------------------------------------------------------------
13877 {0xffffffc0, 0x0000b240, ARMV6_ABOVE, eEncodingT1, No_VFP, eSize16,
13878 &EmulateInstructionARM::EmulateSXTB, "sxtb<c> <Rd>,<Rm>"},
13879 {0xfffff080, 0xfa4ff080, ARMV6_ABOVE, eEncodingT2, No_VFP, eSize32,
13880 &EmulateInstructionARM::EmulateSXTB, "sxtb<c>.w <Rd>,<Rm>{,<rotation>}"},
13881 {0xffffffc0, 0x0000b200, ARMV6_ABOVE, eEncodingT1, No_VFP, eSize16,
13882 &EmulateInstructionARM::EmulateSXTH, "sxth<c> <Rd>,<Rm>"},
13883 {0xfffff080, 0xfa0ff080, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
13884 &EmulateInstructionARM::EmulateSXTH, "sxth<c>.w <Rd>,<Rm>{,<rotation>}"},
13885 {0xffffffc0, 0x0000b2c0, ARMV6_ABOVE, eEncodingT1, No_VFP, eSize16,
13886 &EmulateInstructionARM::EmulateUXTB, "uxtb<c> <Rd>,<Rm>"},
13887 {0xfffff080, 0xfa5ff080, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
13888 &EmulateInstructionARM::EmulateUXTB, "uxtb<c>.w <Rd>,<Rm>{,<rotation>}"},
13889 {0xffffffc0, 0x0000b280, ARMV6_ABOVE, eEncodingT1, No_VFP, eSize16,
13890 &EmulateInstructionARM::EmulateUXTH, "uxth<c> <Rd>,<Rm>"},
13891 {0xfffff080, 0xfa1ff080, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
13892 &EmulateInstructionARM::EmulateUXTH, "uxth<c>.w <Rd>,<Rm>{,<rotation>}"},
13895 const size_t k_num_thumb_opcodes = llvm::array_lengthof(g_thumb_opcodes);
13896 for (size_t i = 0; i < k_num_thumb_opcodes; ++i) {
13897 if ((g_thumb_opcodes[i].mask & opcode) == g_thumb_opcodes[i].value &&
13898 (g_thumb_opcodes[i].variants & arm_isa) != 0)
13899 return &g_thumb_opcodes[i];
13904 bool EmulateInstructionARM::SetArchitecture(const ArchSpec &arch) {
13907 const char *arch_cstr = arch.GetArchitectureName();
13909 if (0 == ::strcasecmp(arch_cstr, "armv4t"))
13910 m_arm_isa = ARMv4T;
13911 else if (0 == ::strcasecmp(arch_cstr, "armv5tej"))
13912 m_arm_isa = ARMv5TEJ;
13913 else if (0 == ::strcasecmp(arch_cstr, "armv5te"))
13914 m_arm_isa = ARMv5TE;
13915 else if (0 == ::strcasecmp(arch_cstr, "armv5t"))
13916 m_arm_isa = ARMv5T;
13917 else if (0 == ::strcasecmp(arch_cstr, "armv6k"))
13918 m_arm_isa = ARMv6K;
13919 else if (0 == ::strcasecmp(arch_cstr, "armv6t2"))
13920 m_arm_isa = ARMv6T2;
13921 else if (0 == ::strcasecmp(arch_cstr, "armv7s"))
13922 m_arm_isa = ARMv7S;
13923 else if (0 == ::strcasecmp(arch_cstr, "arm"))
13924 m_arm_isa = ARMvAll;
13925 else if (0 == ::strcasecmp(arch_cstr, "thumb"))
13926 m_arm_isa = ARMvAll;
13927 else if (0 == ::strncasecmp(arch_cstr, "armv4", 5))
13929 else if (0 == ::strncasecmp(arch_cstr, "armv6", 5))
13931 else if (0 == ::strncasecmp(arch_cstr, "armv7", 5))
13933 else if (0 == ::strncasecmp(arch_cstr, "armv8", 5))
13936 return m_arm_isa != 0;
13939 bool EmulateInstructionARM::SetInstruction(const Opcode &insn_opcode,
13940 const Address &inst_addr,
13942 if (EmulateInstruction::SetInstruction(insn_opcode, inst_addr, target)) {
13943 if (m_arch.GetTriple().getArch() == llvm::Triple::thumb ||
13944 m_arch.IsAlwaysThumbInstructions())
13945 m_opcode_mode = eModeThumb;
13947 AddressClass addr_class = inst_addr.GetAddressClass();
13949 if ((addr_class == eAddressClassCode) ||
13950 (addr_class == eAddressClassUnknown))
13951 m_opcode_mode = eModeARM;
13952 else if (addr_class == eAddressClassCodeAlternateISA)
13953 m_opcode_mode = eModeThumb;
13957 if (m_opcode_mode == eModeThumb || m_arch.IsAlwaysThumbInstructions())
13958 m_opcode_cpsr = CPSR_MODE_USR | MASK_CPSR_T;
13960 m_opcode_cpsr = CPSR_MODE_USR;
13966 bool EmulateInstructionARM::ReadInstruction() {
13967 bool success = false;
13968 m_opcode_cpsr = ReadRegisterUnsigned(eRegisterKindGeneric,
13969 LLDB_REGNUM_GENERIC_FLAGS, 0, &success);
13972 ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC,
13973 LLDB_INVALID_ADDRESS, &success);
13975 Context read_inst_context;
13976 read_inst_context.type = eContextReadOpcode;
13977 read_inst_context.SetNoArgs();
13979 if ((m_opcode_cpsr & MASK_CPSR_T) || m_arch.IsAlwaysThumbInstructions()) {
13980 m_opcode_mode = eModeThumb;
13981 uint32_t thumb_opcode = MemARead(read_inst_context, pc, 2, 0, &success);
13984 if ((thumb_opcode & 0xe000) != 0xe000 ||
13985 ((thumb_opcode & 0x1800u) == 0)) {
13986 m_opcode.SetOpcode16(thumb_opcode, GetByteOrder());
13988 m_opcode.SetOpcode32(
13989 (thumb_opcode << 16) |
13990 MemARead(read_inst_context, pc + 2, 2, 0, &success),
13995 m_opcode_mode = eModeARM;
13996 m_opcode.SetOpcode32(MemARead(read_inst_context, pc, 4, 0, &success),
14000 if (!m_ignore_conditions) {
14001 // If we are not ignoreing the conditions then init the it session from
14004 uint32_t it = (Bits32(m_opcode_cpsr, 15, 10) << 2) |
14005 Bits32(m_opcode_cpsr, 26, 25);
14007 m_it_session.InitIT(it);
14012 m_opcode_mode = eModeInvalid;
14013 m_addr = LLDB_INVALID_ADDRESS;
14018 uint32_t EmulateInstructionARM::ArchVersion() { return m_arm_isa; }
14020 bool EmulateInstructionARM::ConditionPassed(const uint32_t opcode) {
14021 // If we are ignoring conditions, then always return true.
14022 // this allows us to iterate over disassembly code and still
14023 // emulate an instruction even if we don't have all the right
14024 // bits set in the CPSR register...
14025 if (m_ignore_conditions)
14028 const uint32_t cond = CurrentCond(opcode);
14029 if (cond == UINT32_MAX)
14032 bool result = false;
14033 switch (UnsignedBits(cond, 3, 1)) {
14035 if (m_opcode_cpsr == 0)
14038 result = (m_opcode_cpsr & MASK_CPSR_Z) != 0;
14041 if (m_opcode_cpsr == 0)
14044 result = (m_opcode_cpsr & MASK_CPSR_C) != 0;
14047 if (m_opcode_cpsr == 0)
14050 result = (m_opcode_cpsr & MASK_CPSR_N) != 0;
14053 if (m_opcode_cpsr == 0)
14056 result = (m_opcode_cpsr & MASK_CPSR_V) != 0;
14059 if (m_opcode_cpsr == 0)
14062 result = ((m_opcode_cpsr & MASK_CPSR_C) != 0) &&
14063 ((m_opcode_cpsr & MASK_CPSR_Z) == 0);
14066 if (m_opcode_cpsr == 0)
14069 bool n = (m_opcode_cpsr & MASK_CPSR_N);
14070 bool v = (m_opcode_cpsr & MASK_CPSR_V);
14075 if (m_opcode_cpsr == 0)
14078 bool n = (m_opcode_cpsr & MASK_CPSR_N);
14079 bool v = (m_opcode_cpsr & MASK_CPSR_V);
14080 result = n == v && ((m_opcode_cpsr & MASK_CPSR_Z) == 0);
14084 // Always execute (cond == 0b1110, or the special 0b1111 which gives
14085 // opcodes different meanings, but always means execution happens.
14094 uint32_t EmulateInstructionARM::CurrentCond(const uint32_t opcode) {
14095 switch (m_opcode_mode) {
14100 return UnsignedBits(opcode, 31, 28);
14103 // For T1 and T3 encodings of the Branch instruction, it returns the 4-bit
14104 // 'cond' field of the encoding.
14106 const uint32_t byte_size = m_opcode.GetByteSize();
14107 if (byte_size == 2) {
14108 if (Bits32(opcode, 15, 12) == 0x0d && Bits32(opcode, 11, 8) != 0x0f)
14109 return Bits32(opcode, 11, 8);
14110 } else if (byte_size == 4) {
14111 if (Bits32(opcode, 31, 27) == 0x1e && Bits32(opcode, 15, 14) == 0x02 &&
14112 Bits32(opcode, 12, 12) == 0x00 && Bits32(opcode, 25, 22) <= 0x0d) {
14113 return Bits32(opcode, 25, 22);
14116 // We have an invalid thumb instruction, let's bail out.
14119 return m_it_session.GetCond();
14122 return UINT32_MAX; // Return invalid value
14125 bool EmulateInstructionARM::InITBlock() {
14126 return CurrentInstrSet() == eModeThumb && m_it_session.InITBlock();
14129 bool EmulateInstructionARM::LastInITBlock() {
14130 return CurrentInstrSet() == eModeThumb && m_it_session.LastInITBlock();
14133 bool EmulateInstructionARM::BadMode(uint32_t mode) {
14137 return false; // '10000'
14139 return false; // '10001'
14141 return false; // '10010'
14143 return false; // '10011'
14145 return false; // '10110'
14147 return false; // '10111'
14149 return false; // '11011'
14151 return false; // '11111'
14158 bool EmulateInstructionARM::CurrentModeIsPrivileged() {
14159 uint32_t mode = Bits32(m_opcode_cpsr, 4, 0);
14170 void EmulateInstructionARM::CPSRWriteByInstr(uint32_t value, uint32_t bytemask,
14171 bool affect_execstate) {
14172 bool privileged = CurrentModeIsPrivileged();
14174 uint32_t tmp_cpsr = Bits32(m_opcode_cpsr, 23, 20) << 20;
14176 if (BitIsSet(bytemask, 3)) {
14177 tmp_cpsr = tmp_cpsr | (Bits32(value, 31, 27) << 27);
14178 if (affect_execstate)
14179 tmp_cpsr = tmp_cpsr | (Bits32(value, 26, 24) << 24);
14182 if (BitIsSet(bytemask, 2)) {
14183 tmp_cpsr = tmp_cpsr | (Bits32(value, 19, 16) << 16);
14186 if (BitIsSet(bytemask, 1)) {
14187 if (affect_execstate)
14188 tmp_cpsr = tmp_cpsr | (Bits32(value, 15, 10) << 10);
14189 tmp_cpsr = tmp_cpsr | (Bit32(value, 9) << 9);
14191 tmp_cpsr = tmp_cpsr | (Bit32(value, 8) << 8);
14194 if (BitIsSet(bytemask, 0)) {
14196 tmp_cpsr = tmp_cpsr | (Bits32(value, 7, 6) << 6);
14197 if (affect_execstate)
14198 tmp_cpsr = tmp_cpsr | (Bit32(value, 5) << 5);
14200 tmp_cpsr = tmp_cpsr | Bits32(value, 4, 0);
14203 m_opcode_cpsr = tmp_cpsr;
14206 bool EmulateInstructionARM::BranchWritePC(const Context &context,
14210 // Check the current instruction set.
14211 if (CurrentInstrSet() == eModeARM)
14212 target = addr & 0xfffffffc;
14214 target = addr & 0xfffffffe;
14216 if (!WriteRegisterUnsigned(context, eRegisterKindGeneric,
14217 LLDB_REGNUM_GENERIC_PC, target))
14223 // As a side effect, BXWritePC sets context.arg2 to eModeARM or eModeThumb by
14224 // inspecting addr.
14225 bool EmulateInstructionARM::BXWritePC(Context &context, uint32_t addr) {
14227 // If the CPSR is changed due to switching between ARM and Thumb ISETSTATE,
14228 // we want to record it and issue a WriteRegister callback so the clients
14229 // can track the mode changes accordingly.
14230 bool cpsr_changed = false;
14232 if (BitIsSet(addr, 0)) {
14233 if (CurrentInstrSet() != eModeThumb) {
14234 SelectInstrSet(eModeThumb);
14235 cpsr_changed = true;
14237 target = addr & 0xfffffffe;
14238 context.SetISA(eModeThumb);
14239 } else if (BitIsClear(addr, 1)) {
14240 if (CurrentInstrSet() != eModeARM) {
14241 SelectInstrSet(eModeARM);
14242 cpsr_changed = true;
14244 target = addr & 0xfffffffc;
14245 context.SetISA(eModeARM);
14247 return false; // address<1:0> == '10' => UNPREDICTABLE
14249 if (cpsr_changed) {
14250 if (!WriteRegisterUnsigned(context, eRegisterKindGeneric,
14251 LLDB_REGNUM_GENERIC_FLAGS, m_new_inst_cpsr))
14254 if (!WriteRegisterUnsigned(context, eRegisterKindGeneric,
14255 LLDB_REGNUM_GENERIC_PC, target))
14261 // Dispatches to either BXWritePC or BranchWritePC based on architecture
14263 bool EmulateInstructionARM::LoadWritePC(Context &context, uint32_t addr) {
14264 if (ArchVersion() >= ARMv5T)
14265 return BXWritePC(context, addr);
14267 return BranchWritePC((const Context)context, addr);
14270 // Dispatches to either BXWritePC or BranchWritePC based on architecture
14271 // versions and current instruction set.
14272 bool EmulateInstructionARM::ALUWritePC(Context &context, uint32_t addr) {
14273 if (ArchVersion() >= ARMv7 && CurrentInstrSet() == eModeARM)
14274 return BXWritePC(context, addr);
14276 return BranchWritePC((const Context)context, addr);
14279 EmulateInstructionARM::Mode EmulateInstructionARM::CurrentInstrSet() {
14280 return m_opcode_mode;
14283 // Set the 'T' bit of our CPSR. The m_opcode_mode gets updated when the next
14284 // ReadInstruction() is performed. This function has a side effect of updating
14285 // the m_new_inst_cpsr member variable if necessary.
14286 bool EmulateInstructionARM::SelectInstrSet(Mode arm_or_thumb) {
14287 m_new_inst_cpsr = m_opcode_cpsr;
14288 switch (arm_or_thumb) {
14292 // Clear the T bit.
14293 m_new_inst_cpsr &= ~MASK_CPSR_T;
14297 m_new_inst_cpsr |= MASK_CPSR_T;
14303 // This function returns TRUE if the processor currently provides support for
14304 // unaligned memory accesses, or FALSE otherwise. This is always TRUE in ARMv7,
14305 // controllable by the SCTLR.U bit in ARMv6, and always FALSE before ARMv6.
14306 bool EmulateInstructionARM::UnalignedSupport() {
14307 return (ArchVersion() >= ARMv7);
14310 // The main addition and subtraction instructions can produce status information
14311 // about both unsigned carry and signed overflow conditions. This status
14312 // information can be used to synthesize multi-word additions and subtractions.
14313 EmulateInstructionARM::AddWithCarryResult
14314 EmulateInstructionARM::AddWithCarry(uint32_t x, uint32_t y, uint8_t carry_in) {
14319 uint64_t unsigned_sum = x + y + carry_in;
14320 int64_t signed_sum = (int32_t)x + (int32_t)y + (int32_t)carry_in;
14322 result = UnsignedBits(unsigned_sum, 31, 0);
14323 // carry_out = (result == unsigned_sum ? 0 : 1);
14324 overflow = ((int32_t)result == signed_sum ? 0 : 1);
14327 carry_out = ((int32_t)x >= (int32_t)(~y)) ? 1 : 0;
14329 carry_out = ((int32_t)x > (int32_t)y) ? 1 : 0;
14331 AddWithCarryResult res = {result, carry_out, overflow};
14335 uint32_t EmulateInstructionARM::ReadCoreReg(uint32_t num, bool *success) {
14336 lldb::RegisterKind reg_kind;
14340 reg_kind = eRegisterKindGeneric;
14341 reg_num = LLDB_REGNUM_GENERIC_SP;
14344 reg_kind = eRegisterKindGeneric;
14345 reg_num = LLDB_REGNUM_GENERIC_RA;
14348 reg_kind = eRegisterKindGeneric;
14349 reg_num = LLDB_REGNUM_GENERIC_PC;
14352 if (num < SP_REG) {
14353 reg_kind = eRegisterKindDWARF;
14354 reg_num = dwarf_r0 + num;
14356 // assert(0 && "Invalid register number");
14363 // Read our register.
14364 uint32_t val = ReadRegisterUnsigned(reg_kind, reg_num, 0, success);
14366 // When executing an ARM instruction , PC reads as the address of the current
14367 // instruction plus 8.
14368 // When executing a Thumb instruction , PC reads as the address of the current
14369 // instruction plus 4.
14371 if (CurrentInstrSet() == eModeARM)
14380 // Write the result to the ARM core register Rd, and optionally update the
14381 // condition flags based on the result.
14383 // This helper method tries to encapsulate the following pseudocode from the
14384 // ARM Architecture Reference Manual:
14386 // if d == 15 then // Can only occur for encoding A1
14387 // ALUWritePC(result); // setflags is always FALSE here
14390 // if setflags then
14391 // APSR.N = result<31>;
14392 // APSR.Z = IsZeroBit(result);
14394 // // APSR.V unchanged
14396 // In the above case, the API client does not pass in the overflow arg, which
14397 // defaults to ~0u.
14398 bool EmulateInstructionARM::WriteCoreRegOptionalFlags(
14399 Context &context, const uint32_t result, const uint32_t Rd, bool setflags,
14400 const uint32_t carry, const uint32_t overflow) {
14402 if (!ALUWritePC(context, result))
14405 lldb::RegisterKind reg_kind;
14409 reg_kind = eRegisterKindGeneric;
14410 reg_num = LLDB_REGNUM_GENERIC_SP;
14413 reg_kind = eRegisterKindGeneric;
14414 reg_num = LLDB_REGNUM_GENERIC_RA;
14417 reg_kind = eRegisterKindDWARF;
14418 reg_num = dwarf_r0 + Rd;
14420 if (!WriteRegisterUnsigned(context, reg_kind, reg_num, result))
14423 return WriteFlags(context, result, carry, overflow);
14428 // This helper method tries to encapsulate the following pseudocode from the
14429 // ARM Architecture Reference Manual:
14431 // APSR.N = result<31>;
14432 // APSR.Z = IsZeroBit(result);
14434 // APSR.V = overflow
14436 // Default arguments can be specified for carry and overflow parameters, which
14438 // not to update the respective flags.
14439 bool EmulateInstructionARM::WriteFlags(Context &context, const uint32_t result,
14440 const uint32_t carry,
14441 const uint32_t overflow) {
14442 m_new_inst_cpsr = m_opcode_cpsr;
14443 SetBit32(m_new_inst_cpsr, CPSR_N_POS, Bit32(result, CPSR_N_POS));
14444 SetBit32(m_new_inst_cpsr, CPSR_Z_POS, result == 0 ? 1 : 0);
14446 SetBit32(m_new_inst_cpsr, CPSR_C_POS, carry);
14447 if (overflow != ~0u)
14448 SetBit32(m_new_inst_cpsr, CPSR_V_POS, overflow);
14449 if (m_new_inst_cpsr != m_opcode_cpsr) {
14450 if (!WriteRegisterUnsigned(context, eRegisterKindGeneric,
14451 LLDB_REGNUM_GENERIC_FLAGS, m_new_inst_cpsr))
14457 bool EmulateInstructionARM::EvaluateInstruction(uint32_t evaluate_options) {
14458 ARMOpcode *opcode_data = NULL;
14460 if (m_opcode_mode == eModeThumb)
14462 GetThumbOpcodeForInstruction(m_opcode.GetOpcode32(), m_arm_isa);
14463 else if (m_opcode_mode == eModeARM)
14464 opcode_data = GetARMOpcodeForInstruction(m_opcode.GetOpcode32(), m_arm_isa);
14466 const bool auto_advance_pc =
14467 evaluate_options & eEmulateInstructionOptionAutoAdvancePC;
14468 m_ignore_conditions =
14469 evaluate_options & eEmulateInstructionOptionIgnoreConditions;
14471 bool success = false;
14472 if (m_opcode_cpsr == 0 || m_ignore_conditions == false) {
14474 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_cpsr, 0, &success);
14477 // Only return false if we are unable to read the CPSR if we care about
14479 if (success == false && m_ignore_conditions == false)
14482 uint32_t orig_pc_value = 0;
14483 if (auto_advance_pc) {
14485 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc, 0, &success);
14490 // Call the Emulate... function if we managed to decode the opcode.
14492 success = (this->*opcode_data->callback)(m_opcode.GetOpcode32(),
14493 opcode_data->encoding);
14498 // Advance the ITSTATE bits to their values for the next instruction if we
14499 // haven't just executed
14500 // an IT instruction what initialized it.
14501 if (m_opcode_mode == eModeThumb && m_it_session.InITBlock() &&
14502 (opcode_data == nullptr ||
14503 opcode_data->callback != &EmulateInstructionARM::EmulateIT))
14504 m_it_session.ITAdvance();
14506 if (auto_advance_pc) {
14507 uint32_t after_pc_value =
14508 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc, 0, &success);
14512 if (auto_advance_pc && (after_pc_value == orig_pc_value)) {
14513 after_pc_value += m_opcode.GetByteSize();
14515 EmulateInstruction::Context context;
14516 context.type = eContextAdvancePC;
14517 context.SetNoArgs();
14518 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc,
14526 EmulateInstruction::InstructionCondition
14527 EmulateInstructionARM::GetInstructionCondition() {
14528 const uint32_t cond = CurrentCond(m_opcode.GetOpcode32());
14529 if (cond == 0xe || cond == 0xf || cond == UINT32_MAX)
14530 return EmulateInstruction::UnconditionalCondition;
14534 bool EmulateInstructionARM::TestEmulation(Stream *out_stream, ArchSpec &arch,
14535 OptionValueDictionary *test_data) {
14537 out_stream->Printf("TestEmulation: Missing test data.\n");
14541 static ConstString opcode_key("opcode");
14542 static ConstString before_key("before_state");
14543 static ConstString after_key("after_state");
14545 OptionValueSP value_sp = test_data->GetValueForKey(opcode_key);
14547 uint32_t test_opcode;
14548 if ((value_sp.get() == NULL) ||
14549 (value_sp->GetType() != OptionValue::eTypeUInt64)) {
14550 out_stream->Printf("TestEmulation: Error reading opcode from test file.\n");
14553 test_opcode = value_sp->GetUInt64Value();
14555 if (arch.GetTriple().getArch() == llvm::Triple::thumb ||
14556 arch.IsAlwaysThumbInstructions()) {
14557 m_opcode_mode = eModeThumb;
14558 if (test_opcode < 0x10000)
14559 m_opcode.SetOpcode16(test_opcode, endian::InlHostByteOrder());
14561 m_opcode.SetOpcode32(test_opcode, endian::InlHostByteOrder());
14562 } else if (arch.GetTriple().getArch() == llvm::Triple::arm) {
14563 m_opcode_mode = eModeARM;
14564 m_opcode.SetOpcode32(test_opcode, endian::InlHostByteOrder());
14566 out_stream->Printf("TestEmulation: Invalid arch.\n");
14570 EmulationStateARM before_state;
14571 EmulationStateARM after_state;
14573 value_sp = test_data->GetValueForKey(before_key);
14574 if ((value_sp.get() == NULL) ||
14575 (value_sp->GetType() != OptionValue::eTypeDictionary)) {
14576 out_stream->Printf("TestEmulation: Failed to find 'before' state.\n");
14580 OptionValueDictionary *state_dictionary = value_sp->GetAsDictionary();
14581 if (!before_state.LoadStateFromDictionary(state_dictionary)) {
14582 out_stream->Printf("TestEmulation: Failed loading 'before' state.\n");
14586 value_sp = test_data->GetValueForKey(after_key);
14587 if ((value_sp.get() == NULL) ||
14588 (value_sp->GetType() != OptionValue::eTypeDictionary)) {
14589 out_stream->Printf("TestEmulation: Failed to find 'after' state.\n");
14593 state_dictionary = value_sp->GetAsDictionary();
14594 if (!after_state.LoadStateFromDictionary(state_dictionary)) {
14595 out_stream->Printf("TestEmulation: Failed loading 'after' state.\n");
14599 SetBaton((void *)&before_state);
14600 SetCallbacks(&EmulationStateARM::ReadPseudoMemory,
14601 &EmulationStateARM::WritePseudoMemory,
14602 &EmulationStateARM::ReadPseudoRegister,
14603 &EmulationStateARM::WritePseudoRegister);
14605 bool success = EvaluateInstruction(eEmulateInstructionOptionAutoAdvancePC);
14607 out_stream->Printf("TestEmulation: EvaluateInstruction() failed.\n");
14611 success = before_state.CompareState(after_state);
14613 out_stream->Printf(
14614 "TestEmulation: 'before' and 'after' states do not match.\n");
14621 // EmulateInstructionARM::GetRegisterName (uint32_t reg_kind, uint32_t reg_num)
14623 // if (reg_kind == eRegisterKindGeneric)
14625 // switch (reg_num)
14627 // case LLDB_REGNUM_GENERIC_PC: return "pc";
14628 // case LLDB_REGNUM_GENERIC_SP: return "sp";
14629 // case LLDB_REGNUM_GENERIC_FP: return "fp";
14630 // case LLDB_REGNUM_GENERIC_RA: return "lr";
14631 // case LLDB_REGNUM_GENERIC_FLAGS: return "cpsr";
14632 // default: return NULL;
14635 // else if (reg_kind == eRegisterKindDWARF)
14637 // return GetARMDWARFRegisterName (reg_num);
14642 bool EmulateInstructionARM::CreateFunctionEntryUnwind(UnwindPlan &unwind_plan) {
14643 unwind_plan.Clear();
14644 unwind_plan.SetRegisterKind(eRegisterKindDWARF);
14646 UnwindPlan::RowSP row(new UnwindPlan::Row);
14648 // Our previous Call Frame Address is the stack pointer
14649 row->GetCFAValue().SetIsRegisterPlusOffset(dwarf_sp, 0);
14651 unwind_plan.AppendRow(row);
14652 unwind_plan.SetSourceName("EmulateInstructionARM");
14653 unwind_plan.SetSourcedFromCompiler(eLazyBoolNo);
14654 unwind_plan.SetUnwindPlanValidAtAllInstructions(eLazyBoolYes);
14655 unwind_plan.SetReturnAddressRegister(dwarf_lr);