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 XScale accumulator
262 // 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
906 // SP to point to the start of the stored data.
907 bool EmulateInstructionARM::EmulatePUSH(const uint32_t opcode,
908 const ARMEncoding encoding) {
910 // ARM pseudo code...
911 if (ConditionPassed())
913 EncodingSpecificOperations();
914 NullCheckIfThumbEE(13);
915 address = SP - 4*BitCount(registers);
919 if (registers<i> == '1')
921 if i == 13 && i != LowestSetBit(registers) // Only possible for encoding A1
922 MemA[address,4] = bits(32) UNKNOWN;
924 MemA[address,4] = R[i];
925 address = address + 4;
929 if (registers<15> == '1') // Only possible for encoding A1 or A2
930 MemA[address,4] = PCStoreValue();
932 SP = SP - 4*BitCount(registers);
936 bool success = false;
937 if (ConditionPassed(opcode)) {
938 const uint32_t addr_byte_size = GetAddressByteSize();
939 const addr_t sp = ReadCoreReg(SP_REG, &success);
942 uint32_t registers = 0;
943 uint32_t Rt; // the source register
946 registers = Bits32(opcode, 7, 0);
947 // The M bit represents LR.
948 if (Bit32(opcode, 8))
949 registers |= (1u << 14);
950 // if BitCount(registers) < 1 then UNPREDICTABLE;
951 if (BitCount(registers) < 1)
955 // Ignore bits 15 & 13.
956 registers = Bits32(opcode, 15, 0) & ~0xa000;
957 // if BitCount(registers) < 2 then UNPREDICTABLE;
958 if (BitCount(registers) < 2)
962 Rt = Bits32(opcode, 15, 12);
963 // if BadReg(t) then UNPREDICTABLE;
966 registers = (1u << Rt);
969 registers = Bits32(opcode, 15, 0);
970 // Instead of return false, let's handle the following case as well,
971 // which amounts to pushing one reg onto the full descending stacks.
972 // if BitCount(register_list) < 2 then SEE STMDB / STMFD;
975 Rt = Bits32(opcode, 15, 12);
976 // if t == 13 then UNPREDICTABLE;
979 registers = (1u << Rt);
984 addr_t sp_offset = addr_byte_size * BitCount(registers);
985 addr_t addr = sp - sp_offset;
988 EmulateInstruction::Context context;
989 context.type = EmulateInstruction::eContextPushRegisterOnStack;
990 RegisterInfo reg_info;
992 GetRegisterInfo(eRegisterKindDWARF, dwarf_sp, sp_reg);
993 for (i = 0; i < 15; ++i) {
994 if (BitIsSet(registers, i)) {
995 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + i, reg_info);
996 context.SetRegisterToRegisterPlusOffset(reg_info, sp_reg, addr - sp);
997 uint32_t reg_value = ReadCoreReg(i, &success);
1000 if (!MemAWrite(context, addr, reg_value, addr_byte_size))
1002 addr += addr_byte_size;
1006 if (BitIsSet(registers, 15)) {
1007 GetRegisterInfo(eRegisterKindDWARF, dwarf_pc, reg_info);
1008 context.SetRegisterToRegisterPlusOffset(reg_info, sp_reg, addr - sp);
1009 const uint32_t pc = ReadCoreReg(PC_REG, &success);
1012 if (!MemAWrite(context, addr, pc, addr_byte_size))
1016 context.type = EmulateInstruction::eContextAdjustStackPointer;
1017 context.SetImmediateSigned(-sp_offset);
1019 if (!WriteRegisterUnsigned(context, eRegisterKindGeneric,
1020 LLDB_REGNUM_GENERIC_SP, sp - sp_offset))
1026 // Pop Multiple Registers loads multiple registers from the stack, loading from
1027 // consecutive memory locations staring at the address in SP, and updates
1028 // SP to point just above the loaded data.
1029 bool EmulateInstructionARM::EmulatePOP(const uint32_t opcode,
1030 const ARMEncoding encoding) {
1032 // ARM pseudo code...
1033 if (ConditionPassed())
1035 EncodingSpecificOperations(); NullCheckIfThumbEE(13);
1038 if registers<i> == '1' then
1039 R[i] = if UnalignedAllowed then MemU[address,4] else MemA[address,4]; address = address + 4;
1040 if registers<15> == '1' then
1041 if UnalignedAllowed then
1042 LoadWritePC(MemU[address,4]);
1044 LoadWritePC(MemA[address,4]);
1045 if registers<13> == '0' then SP = SP + 4*BitCount(registers);
1046 if registers<13> == '1' then SP = bits(32) UNKNOWN;
1050 bool success = false;
1052 if (ConditionPassed(opcode)) {
1053 const uint32_t addr_byte_size = GetAddressByteSize();
1054 const addr_t sp = ReadCoreReg(SP_REG, &success);
1057 uint32_t registers = 0;
1058 uint32_t Rt; // the destination register
1061 registers = Bits32(opcode, 7, 0);
1062 // The P bit represents PC.
1063 if (Bit32(opcode, 8))
1064 registers |= (1u << 15);
1065 // if BitCount(registers) < 1 then UNPREDICTABLE;
1066 if (BitCount(registers) < 1)
1071 registers = Bits32(opcode, 15, 0) & ~0x2000;
1072 // if BitCount(registers) < 2 || (P == '1' && M == '1') then
1074 if (BitCount(registers) < 2 || (Bit32(opcode, 15) && Bit32(opcode, 14)))
1076 // if registers<15> == '1' && InITBlock() && !LastInITBlock() then
1078 if (BitIsSet(registers, 15) && InITBlock() && !LastInITBlock())
1082 Rt = Bits32(opcode, 15, 12);
1083 // if t == 13 || (t == 15 && InITBlock() && !LastInITBlock()) then
1087 if (Rt == 15 && InITBlock() && !LastInITBlock())
1089 registers = (1u << Rt);
1092 registers = Bits32(opcode, 15, 0);
1093 // Instead of return false, let's handle the following case as well,
1094 // which amounts to popping one reg from the full descending stacks.
1095 // if BitCount(register_list) < 2 then SEE LDM / LDMIA / LDMFD;
1097 // if registers<13> == '1' && ArchVersion() >= 7 then UNPREDICTABLE;
1098 if (BitIsSet(opcode, 13) && ArchVersion() >= ARMv7)
1102 Rt = Bits32(opcode, 15, 12);
1103 // if t == 13 then UNPREDICTABLE;
1106 registers = (1u << Rt);
1111 addr_t sp_offset = addr_byte_size * BitCount(registers);
1115 EmulateInstruction::Context context;
1116 context.type = EmulateInstruction::eContextPopRegisterOffStack;
1118 RegisterInfo sp_reg;
1119 GetRegisterInfo(eRegisterKindDWARF, dwarf_sp, sp_reg);
1121 for (i = 0; i < 15; ++i) {
1122 if (BitIsSet(registers, i)) {
1123 context.SetAddress(addr);
1124 data = MemARead(context, addr, 4, 0, &success);
1127 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + i,
1130 addr += addr_byte_size;
1134 if (BitIsSet(registers, 15)) {
1135 context.SetRegisterPlusOffset(sp_reg, addr - sp);
1136 data = MemARead(context, addr, 4, 0, &success);
1139 // In ARMv5T and above, this is an interworking branch.
1140 if (!LoadWritePC(context, data))
1142 // addr += addr_byte_size;
1145 context.type = EmulateInstruction::eContextAdjustStackPointer;
1146 context.SetImmediateSigned(sp_offset);
1148 if (!WriteRegisterUnsigned(context, eRegisterKindGeneric,
1149 LLDB_REGNUM_GENERIC_SP, sp + sp_offset))
1155 // Set r7 or ip to point to saved value residing within the stack.
1156 // ADD (SP plus immediate)
1157 bool EmulateInstructionARM::EmulateADDRdSPImm(const uint32_t opcode,
1158 const ARMEncoding encoding) {
1160 // ARM pseudo code...
1161 if (ConditionPassed())
1163 EncodingSpecificOperations();
1164 (result, carry, overflow) = AddWithCarry(SP, imm32, '0');
1166 ALUWritePC(result); // setflags is always FALSE here
1170 APSR.N = result<31>;
1171 APSR.Z = IsZeroBit(result);
1177 bool success = false;
1179 if (ConditionPassed(opcode)) {
1180 const addr_t sp = ReadCoreReg(SP_REG, &success);
1183 uint32_t Rd; // the destination register
1188 imm32 = Bits32(opcode, 7, 0) << 2; // imm32 = ZeroExtend(imm8:'00', 32)
1191 Rd = Bits32(opcode, 15, 12);
1192 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
1197 addr_t sp_offset = imm32;
1198 addr_t addr = sp + sp_offset; // a pointer to the stack area
1200 EmulateInstruction::Context context;
1201 if (Rd == GetFramePointerRegisterNumber())
1202 context.type = eContextSetFramePointer;
1204 context.type = EmulateInstruction::eContextRegisterPlusOffset;
1205 RegisterInfo sp_reg;
1206 GetRegisterInfo(eRegisterKindDWARF, dwarf_sp, sp_reg);
1207 context.SetRegisterPlusOffset(sp_reg, sp_offset);
1209 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + Rd,
1216 // Set r7 or ip to the current stack pointer.
1218 bool EmulateInstructionARM::EmulateMOVRdSP(const uint32_t opcode,
1219 const ARMEncoding encoding) {
1221 // ARM pseudo code...
1222 if (ConditionPassed())
1224 EncodingSpecificOperations();
1227 ALUWritePC(result); // setflags is always FALSE here
1231 APSR.N = result<31>;
1232 APSR.Z = IsZeroBit(result);
1238 bool success = false;
1240 if (ConditionPassed(opcode)) {
1241 const addr_t sp = ReadCoreReg(SP_REG, &success);
1244 uint32_t Rd; // the destination register
1256 EmulateInstruction::Context context;
1257 if (Rd == GetFramePointerRegisterNumber())
1258 context.type = EmulateInstruction::eContextSetFramePointer;
1260 context.type = EmulateInstruction::eContextRegisterPlusOffset;
1261 RegisterInfo sp_reg;
1262 GetRegisterInfo(eRegisterKindDWARF, dwarf_sp, sp_reg);
1263 context.SetRegisterPlusOffset(sp_reg, 0);
1265 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + Rd, sp))
1271 // Move from high register (r8-r15) to low register (r0-r7).
1273 bool EmulateInstructionARM::EmulateMOVLowHigh(const uint32_t opcode,
1274 const ARMEncoding encoding) {
1275 return EmulateMOVRdRm(opcode, encoding);
1278 // Move from register to register.
1280 bool EmulateInstructionARM::EmulateMOVRdRm(const uint32_t opcode,
1281 const ARMEncoding encoding) {
1283 // ARM pseudo code...
1284 if (ConditionPassed())
1286 EncodingSpecificOperations();
1289 ALUWritePC(result); // setflags is always FALSE here
1293 APSR.N = result<31>;
1294 APSR.Z = IsZeroBit(result);
1300 bool success = false;
1302 if (ConditionPassed(opcode)) {
1303 uint32_t Rm; // the source register
1304 uint32_t Rd; // the destination register
1308 Rd = Bit32(opcode, 7) << 3 | Bits32(opcode, 2, 0);
1309 Rm = Bits32(opcode, 6, 3);
1311 if (Rd == 15 && InITBlock() && !LastInITBlock())
1315 Rd = Bits32(opcode, 2, 0);
1316 Rm = Bits32(opcode, 5, 3);
1322 Rd = Bits32(opcode, 11, 8);
1323 Rm = Bits32(opcode, 3, 0);
1324 setflags = BitIsSet(opcode, 20);
1325 // if setflags && (BadReg(d) || BadReg(m)) then UNPREDICTABLE;
1326 if (setflags && (BadReg(Rd) || BadReg(Rm)))
1328 // if !setflags && (d == 15 || m == 15 || (d == 13 && m == 13)) then
1330 if (!setflags && (Rd == 15 || Rm == 15 || (Rd == 13 && Rm == 13)))
1334 Rd = Bits32(opcode, 15, 12);
1335 Rm = Bits32(opcode, 3, 0);
1336 setflags = BitIsSet(opcode, 20);
1338 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related
1340 if (Rd == 15 && setflags)
1341 return EmulateSUBSPcLrEtc(opcode, encoding);
1346 uint32_t result = ReadCoreReg(Rm, &success);
1350 // The context specifies that Rm is to be moved into Rd.
1351 EmulateInstruction::Context context;
1353 context.type = EmulateInstruction::eContextAdjustStackPointer;
1355 context.type = EmulateInstruction::eContextRegisterPlusOffset;
1356 RegisterInfo dwarf_reg;
1357 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + Rm, dwarf_reg);
1358 context.SetRegisterPlusOffset(dwarf_reg, 0);
1360 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags))
1366 // Move (immediate) writes an immediate value to the destination register. It
1367 // can optionally update the condition flags based on the value.
1369 bool EmulateInstructionARM::EmulateMOVRdImm(const uint32_t opcode,
1370 const ARMEncoding encoding) {
1372 // ARM pseudo code...
1373 if (ConditionPassed())
1375 EncodingSpecificOperations();
1377 if d == 15 then // Can only occur for ARM encoding
1378 ALUWritePC(result); // setflags is always FALSE here
1382 APSR.N = result<31>;
1383 APSR.Z = IsZeroBit(result);
1389 if (ConditionPassed(opcode)) {
1390 uint32_t Rd; // the destination register
1391 uint32_t imm32; // the immediate value to be written to Rd
1393 0; // the carry bit after ThumbExpandImm_C or ARMExpandImm_C.
1394 // for setflags == false, this value is a don't care initialized to
1395 // 0 to silence the static analyzer
1399 Rd = Bits32(opcode, 10, 8);
1400 setflags = !InITBlock();
1401 imm32 = Bits32(opcode, 7, 0); // imm32 = ZeroExtend(imm8, 32)
1407 Rd = Bits32(opcode, 11, 8);
1408 setflags = BitIsSet(opcode, 20);
1409 imm32 = ThumbExpandImm_C(opcode, APSR_C, carry);
1416 // d = UInt(Rd); setflags = FALSE; imm32 = ZeroExtend(imm4:i:imm3:imm8,
1418 Rd = Bits32(opcode, 11, 8);
1420 uint32_t imm4 = Bits32(opcode, 19, 16);
1421 uint32_t imm3 = Bits32(opcode, 14, 12);
1422 uint32_t i = Bit32(opcode, 26);
1423 uint32_t imm8 = Bits32(opcode, 7, 0);
1424 imm32 = (imm4 << 12) | (i << 11) | (imm3 << 8) | imm8;
1426 // if BadReg(d) then UNPREDICTABLE;
1432 // d = UInt(Rd); setflags = (S == '1'); (imm32, carry) =
1433 // ARMExpandImm_C(imm12, APSR.C);
1434 Rd = Bits32(opcode, 15, 12);
1435 setflags = BitIsSet(opcode, 20);
1436 imm32 = ARMExpandImm_C(opcode, APSR_C, carry);
1438 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related
1440 if ((Rd == 15) && setflags)
1441 return EmulateSUBSPcLrEtc(opcode, encoding);
1446 // d = UInt(Rd); setflags = FALSE; imm32 = ZeroExtend(imm4:imm12, 32);
1447 Rd = Bits32(opcode, 15, 12);
1449 uint32_t imm4 = Bits32(opcode, 19, 16);
1450 uint32_t imm12 = Bits32(opcode, 11, 0);
1451 imm32 = (imm4 << 12) | imm12;
1453 // if d == 15 then UNPREDICTABLE;
1461 uint32_t result = imm32;
1463 // The context specifies that an immediate is to be moved into Rd.
1464 EmulateInstruction::Context context;
1465 context.type = EmulateInstruction::eContextImmediate;
1466 context.SetNoArgs();
1468 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
1474 // MUL multiplies two register values. The least significant 32 bits of the
1475 // result are written to the destination
1476 // register. These 32 bits do not depend on whether the source register values
1477 // are considered to be signed values or unsigned values.
1479 // Optionally, it can update the condition flags based on the result. In the
1480 // Thumb instruction set, this option is limited to only a few forms of the
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. It can optionally update the condition flags based
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. It can optionally update the condition flags based on
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
2009 // subroutine at a PC-relative address, and changes instruction set from ARM to
2010 // Thumb, or 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
2114 // and 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 address and instruction set specified by a
2224 // register as though it were a BX instruction.
2226 // TODO: Emulate Jazelle architecture?
2227 // We currently assume that switching to Jazelle state fails, thus
2228 // treating BXJ as a BX operation.
2229 bool EmulateInstructionARM::EmulateBXJRm(const uint32_t opcode,
2230 const ARMEncoding encoding) {
2232 // ARM pseudo code...
2233 if (ConditionPassed())
2235 EncodingSpecificOperations();
2236 if JMCR.JE == '0' || CurrentInstrSet() == InstrSet_ThumbEE then
2239 if JazelleAcceptsExecution() then
2240 SwitchToJazelleExecution();
2242 SUBARCHITECTURE_DEFINED handler call;
2246 if (ConditionPassed(opcode)) {
2247 EmulateInstruction::Context context;
2248 context.type = EmulateInstruction::eContextAbsoluteBranchRegister;
2249 uint32_t Rm; // the register with the target address
2252 Rm = Bits32(opcode, 19, 16);
2255 if (InITBlock() && !LastInITBlock())
2259 Rm = Bits32(opcode, 3, 0);
2266 bool success = false;
2267 addr_t target = ReadCoreReg(Rm, &success);
2271 RegisterInfo dwarf_reg;
2272 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + Rm, dwarf_reg);
2273 context.SetRegister(dwarf_reg);
2274 if (!BXWritePC(context, target))
2280 // Set r7 to point to some ip offset.
2282 bool EmulateInstructionARM::EmulateSUBR7IPImm(const uint32_t opcode,
2283 const ARMEncoding encoding) {
2285 // ARM pseudo code...
2286 if (ConditionPassed())
2288 EncodingSpecificOperations();
2289 (result, carry, overflow) = AddWithCarry(SP, NOT(imm32), '1');
2290 if d == 15 then // Can only occur for ARM encoding
2291 ALUWritePC(result); // setflags is always FALSE here
2295 APSR.N = result<31>;
2296 APSR.Z = IsZeroBit(result);
2302 if (ConditionPassed(opcode)) {
2303 bool success = false;
2304 const addr_t ip = ReadCoreReg(12, &success);
2310 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
2315 addr_t ip_offset = imm32;
2316 addr_t addr = ip - ip_offset; // the adjusted ip value
2318 EmulateInstruction::Context context;
2319 context.type = EmulateInstruction::eContextRegisterPlusOffset;
2320 RegisterInfo dwarf_reg;
2321 GetRegisterInfo(eRegisterKindDWARF, dwarf_r12, dwarf_reg);
2322 context.SetRegisterPlusOffset(dwarf_reg, -ip_offset);
2324 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r7, addr))
2330 // Set ip to point to some stack offset.
2331 // SUB (SP minus immediate)
2332 bool EmulateInstructionARM::EmulateSUBIPSPImm(const uint32_t opcode,
2333 const ARMEncoding encoding) {
2335 // ARM pseudo code...
2336 if (ConditionPassed())
2338 EncodingSpecificOperations();
2339 (result, carry, overflow) = AddWithCarry(SP, NOT(imm32), '1');
2340 if d == 15 then // Can only occur for ARM encoding
2341 ALUWritePC(result); // setflags is always FALSE here
2345 APSR.N = result<31>;
2346 APSR.Z = IsZeroBit(result);
2352 if (ConditionPassed(opcode)) {
2353 bool success = false;
2354 const addr_t sp = ReadCoreReg(SP_REG, &success);
2360 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
2365 addr_t sp_offset = imm32;
2366 addr_t addr = sp - sp_offset; // the adjusted stack pointer value
2368 EmulateInstruction::Context context;
2369 context.type = EmulateInstruction::eContextRegisterPlusOffset;
2370 RegisterInfo dwarf_reg;
2371 GetRegisterInfo(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, dwarf_reg);
2372 context.SetRegisterPlusOffset(dwarf_reg, -sp_offset);
2374 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r12, addr))
2380 // This instruction subtracts an immediate value from the SP value, and writes
2381 // the result to the destination register.
2383 // If Rd == 13 => A sub operation to adjust the SP -- allocate space for local
2385 bool EmulateInstructionARM::EmulateSUBSPImm(const uint32_t opcode,
2386 const ARMEncoding encoding) {
2388 // ARM pseudo code...
2389 if (ConditionPassed())
2391 EncodingSpecificOperations();
2392 (result, carry, overflow) = AddWithCarry(SP, NOT(imm32), '1');
2393 if d == 15 then // Can only occur for ARM encoding
2394 ALUWritePC(result); // setflags is always FALSE here
2398 APSR.N = result<31>;
2399 APSR.Z = IsZeroBit(result);
2405 bool success = false;
2406 if (ConditionPassed(opcode)) {
2407 const addr_t sp = ReadCoreReg(SP_REG, &success);
2418 imm32 = ThumbImm7Scaled(opcode); // imm32 = ZeroExtend(imm7:'00', 32)
2421 Rd = Bits32(opcode, 11, 8);
2422 setflags = BitIsSet(opcode, 20);
2423 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8)
2424 if (Rd == 15 && setflags)
2425 return EmulateCMPImm(opcode, eEncodingT2);
2426 if (Rd == 15 && !setflags)
2430 Rd = Bits32(opcode, 11, 8);
2432 imm32 = ThumbImm12(opcode); // imm32 = ZeroExtend(i:imm3:imm8, 32)
2437 Rd = Bits32(opcode, 15, 12);
2438 setflags = BitIsSet(opcode, 20);
2439 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
2441 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related
2443 if (Rd == 15 && setflags)
2444 return EmulateSUBSPcLrEtc(opcode, encoding);
2449 AddWithCarryResult res = AddWithCarry(sp, ~imm32, 1);
2451 EmulateInstruction::Context context;
2453 uint64_t imm64 = imm32; // Need to expand it to 64 bits before attempting
2454 // to negate it, or the wrong
2455 // value gets passed down to context.SetImmediateSigned.
2456 context.type = EmulateInstruction::eContextAdjustStackPointer;
2457 context.SetImmediateSigned(-imm64); // the stack pointer offset
2459 context.type = EmulateInstruction::eContextImmediate;
2460 context.SetNoArgs();
2463 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags,
2464 res.carry_out, res.overflow))
2470 // A store operation to the stack that also updates the SP.
2471 bool EmulateInstructionARM::EmulateSTRRtSP(const uint32_t opcode,
2472 const ARMEncoding encoding) {
2474 // ARM pseudo code...
2475 if (ConditionPassed())
2477 EncodingSpecificOperations();
2478 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
2479 address = if index then offset_addr else R[n];
2480 MemU[address,4] = if t == 15 then PCStoreValue() else R[t];
2481 if wback then R[n] = offset_addr;
2485 bool success = false;
2486 if (ConditionPassed(opcode)) {
2487 const uint32_t addr_byte_size = GetAddressByteSize();
2488 const addr_t sp = ReadCoreReg(SP_REG, &success);
2491 uint32_t Rt; // the source register
2494 Rn; // This function assumes Rn is the SP, but we should verify that.
2501 Rt = Bits32(opcode, 15, 12);
2502 imm12 = Bits32(opcode, 11, 0);
2503 Rn = Bits32(opcode, 19, 16);
2505 if (Rn != 13) // 13 is the SP reg on ARM. Verify that Rn == SP.
2508 index = BitIsSet(opcode, 24);
2509 add = BitIsSet(opcode, 23);
2510 wback = (BitIsClear(opcode, 24) || BitIsSet(opcode, 21));
2512 if (wback && ((Rn == 15) || (Rn == Rt)))
2520 offset_addr = sp + imm12;
2522 offset_addr = sp - imm12;
2530 EmulateInstruction::Context context;
2531 context.type = EmulateInstruction::eContextPushRegisterOnStack;
2532 RegisterInfo sp_reg;
2533 RegisterInfo dwarf_reg;
2535 GetRegisterInfo(eRegisterKindDWARF, dwarf_sp, sp_reg);
2536 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + Rt, dwarf_reg);
2537 context.SetRegisterToRegisterPlusOffset(dwarf_reg, sp_reg, addr - sp);
2539 uint32_t reg_value = ReadCoreReg(Rt, &success);
2542 if (!MemUWrite(context, addr, reg_value, addr_byte_size))
2545 const uint32_t pc = ReadCoreReg(PC_REG, &success);
2548 if (!MemUWrite(context, addr, pc, addr_byte_size))
2553 context.type = EmulateInstruction::eContextAdjustStackPointer;
2554 context.SetImmediateSigned(addr - sp);
2555 if (!WriteRegisterUnsigned(context, eRegisterKindGeneric,
2556 LLDB_REGNUM_GENERIC_SP, offset_addr))
2563 // Vector Push stores multiple extension registers to the stack. It also
2564 // updates SP to point to the start of the stored data.
2565 bool EmulateInstructionARM::EmulateVPUSH(const uint32_t opcode,
2566 const ARMEncoding encoding) {
2568 // ARM pseudo code...
2569 if (ConditionPassed())
2571 EncodingSpecificOperations(); CheckVFPEnabled(TRUE); NullCheckIfThumbEE(13);
2572 address = SP - imm32;
2576 MemA[address,4] = S[d+r]; address = address+4;
2579 // Store as two word-aligned words in the correct order for
2580 // 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. It also
2657 // 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
2674 // current endianness.
2675 D[d+r] = if BigEndian() then word1:word2 else word2:word1;
2679 bool success = false;
2680 if (ConditionPassed(opcode)) {
2681 const uint32_t addr_byte_size = GetAddressByteSize();
2682 const addr_t sp = ReadCoreReg(SP_REG, &success);
2686 uint32_t d; // UInt(D:Vd) or UInt(Vd:D) starting register
2687 uint32_t imm32; // stack offset
2688 uint32_t regs; // number of registers
2692 single_regs = false;
2693 d = Bit32(opcode, 22) << 4 | Bits32(opcode, 15, 12);
2694 imm32 = Bits32(opcode, 7, 0) * addr_byte_size;
2695 // If UInt(imm8) is odd, see "FLDMX".
2696 regs = Bits32(opcode, 7, 0) / 2;
2697 // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE;
2698 if (regs == 0 || regs > 16 || (d + regs) > 32)
2704 d = Bits32(opcode, 15, 12) << 1 | Bit32(opcode, 22);
2705 imm32 = Bits32(opcode, 7, 0) * addr_byte_size;
2706 regs = Bits32(opcode, 7, 0);
2707 // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE;
2708 if (regs == 0 || regs > 16 || (d + regs) > 32)
2714 uint32_t start_reg = single_regs ? dwarf_s0 : dwarf_d0;
2715 uint32_t reg_byte_size = single_regs ? addr_byte_size : addr_byte_size * 2;
2716 addr_t sp_offset = imm32;
2719 uint64_t data; // uint64_t to accommodate 64-bit registers.
2721 EmulateInstruction::Context context;
2722 context.type = EmulateInstruction::eContextPopRegisterOffStack;
2724 RegisterInfo dwarf_reg;
2725 RegisterInfo sp_reg;
2726 GetRegisterInfo(eRegisterKindDWARF, dwarf_sp, sp_reg);
2727 for (i = 0; i < regs; ++i) {
2728 GetRegisterInfo(eRegisterKindDWARF, start_reg + d + i, dwarf_reg);
2729 context.SetAddress(addr);
2730 data = MemARead(context, addr, reg_byte_size, 0, &success);
2733 if (!WriteRegisterUnsigned(context, &dwarf_reg, data))
2735 addr += reg_byte_size;
2738 context.type = EmulateInstruction::eContextAdjustStackPointer;
2739 context.SetImmediateSigned(sp_offset);
2741 if (!WriteRegisterUnsigned(context, eRegisterKindGeneric,
2742 LLDB_REGNUM_GENERIC_SP, sp + sp_offset))
2748 // SVC (previously SWI)
2749 bool EmulateInstructionARM::EmulateSVC(const uint32_t opcode,
2750 const ARMEncoding encoding) {
2752 // ARM pseudo code...
2753 if (ConditionPassed())
2755 EncodingSpecificOperations();
2760 bool success = false;
2762 if (ConditionPassed(opcode)) {
2763 const uint32_t pc = ReadCoreReg(PC_REG, &success);
2764 addr_t lr; // next instruction address
2767 uint32_t imm32; // the immediate constant
2768 uint32_t mode; // ARM or Thumb mode
2771 lr = (pc + 2) | 1u; // return address
2772 imm32 = Bits32(opcode, 7, 0);
2776 lr = pc + 4; // return address
2777 imm32 = Bits32(opcode, 23, 0);
2784 EmulateInstruction::Context context;
2785 context.type = EmulateInstruction::eContextSupervisorCall;
2786 context.SetISAAndImmediate(mode, imm32);
2787 if (!WriteRegisterUnsigned(context, eRegisterKindGeneric,
2788 LLDB_REGNUM_GENERIC_RA, lr))
2794 // If Then makes up to four following instructions (the IT block) conditional.
2795 bool EmulateInstructionARM::EmulateIT(const uint32_t opcode,
2796 const ARMEncoding encoding) {
2798 // ARM pseudo code...
2799 EncodingSpecificOperations();
2800 ITSTATE.IT<7:0> = firstcond:mask;
2803 m_it_session.InitIT(Bits32(opcode, 7, 0));
2807 bool EmulateInstructionARM::EmulateNop(const uint32_t opcode,
2808 const ARMEncoding encoding) {
2809 // NOP, nothing to do...
2813 // Branch causes a branch to a target address.
2814 bool EmulateInstructionARM::EmulateB(const uint32_t opcode,
2815 const ARMEncoding encoding) {
2817 // ARM pseudo code...
2818 if (ConditionPassed())
2820 EncodingSpecificOperations();
2821 BranchWritePC(PC + imm32);
2825 bool success = false;
2827 if (ConditionPassed(opcode)) {
2828 EmulateInstruction::Context context;
2829 context.type = EmulateInstruction::eContextRelativeBranchImmediate;
2830 const uint32_t pc = ReadCoreReg(PC_REG, &success);
2833 addr_t target; // target address
2834 int32_t imm32; // PC-relative offset
2837 // The 'cond' field is handled in EmulateInstructionARM::CurrentCond().
2838 imm32 = llvm::SignExtend32<9>(Bits32(opcode, 7, 0) << 1);
2839 target = pc + imm32;
2840 context.SetISAAndImmediateSigned(eModeThumb, 4 + imm32);
2843 imm32 = llvm::SignExtend32<12>(Bits32(opcode, 10, 0) << 1);
2844 target = pc + imm32;
2845 context.SetISAAndImmediateSigned(eModeThumb, 4 + imm32);
2848 // The 'cond' field is handled in EmulateInstructionARM::CurrentCond().
2850 if (Bits32(opcode, 25, 23) == 7)
2851 return false; // See Branches and miscellaneous control on page
2854 uint32_t S = Bit32(opcode, 26);
2855 uint32_t imm6 = Bits32(opcode, 21, 16);
2856 uint32_t J1 = Bit32(opcode, 13);
2857 uint32_t J2 = Bit32(opcode, 11);
2858 uint32_t imm11 = Bits32(opcode, 10, 0);
2860 (S << 20) | (J2 << 19) | (J1 << 18) | (imm6 << 12) | (imm11 << 1);
2861 imm32 = llvm::SignExtend32<21>(imm21);
2862 target = pc + imm32;
2863 context.SetISAAndImmediateSigned(eModeThumb, 4 + imm32);
2867 uint32_t S = Bit32(opcode, 26);
2868 uint32_t imm10 = Bits32(opcode, 25, 16);
2869 uint32_t J1 = Bit32(opcode, 13);
2870 uint32_t J2 = Bit32(opcode, 11);
2871 uint32_t imm11 = Bits32(opcode, 10, 0);
2872 uint32_t I1 = !(J1 ^ S);
2873 uint32_t I2 = !(J2 ^ S);
2875 (S << 24) | (I1 << 23) | (I2 << 22) | (imm10 << 12) | (imm11 << 1);
2876 imm32 = llvm::SignExtend32<25>(imm25);
2877 target = pc + imm32;
2878 context.SetISAAndImmediateSigned(eModeThumb, 4 + imm32);
2882 imm32 = llvm::SignExtend32<26>(Bits32(opcode, 23, 0) << 2);
2883 target = pc + imm32;
2884 context.SetISAAndImmediateSigned(eModeARM, 8 + imm32);
2889 if (!BranchWritePC(context, target))
2895 // Compare and Branch on Nonzero and Compare and Branch on Zero compare the
2896 // value in a register with zero and conditionally branch forward a constant
2897 // value. They do not affect the condition flags. CBNZ, CBZ
2898 bool EmulateInstructionARM::EmulateCB(const uint32_t opcode,
2899 const ARMEncoding encoding) {
2901 // ARM pseudo code...
2902 EncodingSpecificOperations();
2903 if nonzero ^ IsZero(R[n]) then
2904 BranchWritePC(PC + imm32);
2907 bool success = false;
2909 // Read the register value from the operand register Rn.
2910 uint32_t reg_val = ReadCoreReg(Bits32(opcode, 2, 0), &success);
2914 EmulateInstruction::Context context;
2915 context.type = EmulateInstruction::eContextRelativeBranchImmediate;
2916 const uint32_t pc = ReadCoreReg(PC_REG, &success);
2920 addr_t target; // target address
2921 uint32_t imm32; // PC-relative offset to branch forward
2925 imm32 = Bit32(opcode, 9) << 6 | Bits32(opcode, 7, 3) << 1;
2926 nonzero = BitIsSet(opcode, 11);
2927 target = pc + imm32;
2928 context.SetISAAndImmediateSigned(eModeThumb, 4 + imm32);
2933 if (m_ignore_conditions || (nonzero ^ (reg_val == 0)))
2934 if (!BranchWritePC(context, target))
2940 // Table Branch Byte causes a PC-relative forward branch using a table of
2941 // single byte offsets.
2942 // A base register provides a pointer to the table, and a second register
2943 // supplies an index into the table.
2944 // The branch length is twice the value of the byte returned from the table.
2946 // Table Branch Halfword causes a PC-relative forward branch using a table of
2947 // single halfword offsets.
2948 // A base register provides a pointer to the table, and a second register
2949 // supplies an index into the table.
2950 // The branch length is twice the value of the halfword returned from the
2952 bool EmulateInstructionARM::EmulateTB(const uint32_t opcode,
2953 const ARMEncoding encoding) {
2955 // ARM pseudo code...
2956 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
2958 halfwords = UInt(MemU[R[n]+LSL(R[m],1), 2]);
2960 halfwords = UInt(MemU[R[n]+R[m], 1]);
2961 BranchWritePC(PC + 2*halfwords);
2964 bool success = false;
2966 if (ConditionPassed(opcode)) {
2967 uint32_t Rn; // the base register which contains the address of the table of
2969 uint32_t Rm; // the index register which contains an integer pointing to a
2970 // byte/halfword in the table
2971 bool is_tbh; // true if table branch halfword
2974 Rn = Bits32(opcode, 19, 16);
2975 Rm = Bits32(opcode, 3, 0);
2976 is_tbh = BitIsSet(opcode, 4);
2977 if (Rn == 13 || BadReg(Rm))
2979 if (InITBlock() && !LastInITBlock())
2986 // Read the address of the table from the operand register Rn. The PC can
2987 // be used, in which case the table immediately follows this instruction.
2988 uint32_t base = ReadCoreReg(Rn, &success);
2993 uint32_t index = ReadCoreReg(Rm, &success);
2997 // the offsetted table address
2998 addr_t addr = base + (is_tbh ? index * 2 : index);
3000 // PC-relative offset to branch forward
3001 EmulateInstruction::Context context;
3002 context.type = EmulateInstruction::eContextTableBranchReadMemory;
3003 uint32_t offset = MemURead(context, addr, is_tbh ? 2 : 1, 0, &success) * 2;
3007 const uint32_t pc = ReadCoreReg(PC_REG, &success);
3012 addr_t target = pc + offset;
3013 context.type = EmulateInstruction::eContextRelativeBranchImmediate;
3014 context.SetISAAndImmediateSigned(eModeThumb, 4 + offset);
3016 if (!BranchWritePC(context, target))
3023 // This instruction adds an immediate value to a register value, and writes the
3024 // result to the destination register. It can optionally update the condition
3025 // flags based on the result.
3026 bool EmulateInstructionARM::EmulateADDImmThumb(const uint32_t opcode,
3027 const ARMEncoding encoding) {
3029 if ConditionPassed() then
3030 EncodingSpecificOperations();
3031 (result, carry, overflow) = AddWithCarry(R[n], imm32, '0');
3034 APSR.N = result<31>;
3035 APSR.Z = IsZeroBit(result);
3040 bool success = false;
3042 if (ConditionPassed(opcode)) {
3049 // EncodingSpecificOperations();
3052 // d = UInt(Rd); n = UInt(Rn); setflags = !InITBlock(); imm32 =
3053 // ZeroExtend(imm3, 32);
3054 d = Bits32(opcode, 2, 0);
3055 n = Bits32(opcode, 5, 3);
3056 setflags = !InITBlock();
3057 imm32 = Bits32(opcode, 8, 6);
3062 // d = UInt(Rdn); n = UInt(Rdn); setflags = !InITBlock(); imm32 =
3063 // ZeroExtend(imm8, 32);
3064 d = Bits32(opcode, 10, 8);
3065 n = Bits32(opcode, 10, 8);
3066 setflags = !InITBlock();
3067 imm32 = Bits32(opcode, 7, 0);
3072 // if Rd == '1111' && S == '1' then SEE CMN (immediate);
3073 // d = UInt(Rd); n = UInt(Rn); setflags = (S == '1'); imm32 =
3074 // ThumbExpandImm(i:imm3:imm8);
3075 d = Bits32(opcode, 11, 8);
3076 n = Bits32(opcode, 19, 16);
3077 setflags = BitIsSet(opcode, 20);
3078 imm32 = ThumbExpandImm_C(opcode, APSR_C, carry_out);
3080 // if Rn == '1101' then SEE ADD (SP plus immediate);
3082 return EmulateADDSPImm(opcode, eEncodingT3);
3084 // if BadReg(d) || n == 15 then UNPREDICTABLE;
3085 if (BadReg(d) || (n == 15))
3091 // if Rn == '1111' then SEE ADR;
3092 // d = UInt(Rd); n = UInt(Rn); setflags = FALSE; imm32 =
3093 // ZeroExtend(i:imm3:imm8, 32);
3094 d = Bits32(opcode, 11, 8);
3095 n = Bits32(opcode, 19, 16);
3097 uint32_t i = Bit32(opcode, 26);
3098 uint32_t imm3 = Bits32(opcode, 14, 12);
3099 uint32_t imm8 = Bits32(opcode, 7, 0);
3100 imm32 = (i << 11) | (imm3 << 8) | imm8;
3102 // if Rn == '1101' then SEE ADD (SP plus immediate);
3104 return EmulateADDSPImm(opcode, eEncodingT4);
3106 // if BadReg(d) then UNPREDICTABLE;
3118 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
3122 //(result, carry, overflow) = AddWithCarry(R[n], imm32, '0');
3123 AddWithCarryResult res = AddWithCarry(Rn, imm32, 0);
3126 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n, reg_n);
3128 EmulateInstruction::Context context;
3129 context.type = eContextArithmetic;
3130 context.SetRegisterPlusOffset(reg_n, imm32);
3134 // APSR.N = result<31>;
3135 // APSR.Z = IsZeroBit(result);
3137 // APSR.V = overflow;
3138 if (!WriteCoreRegOptionalFlags(context, res.result, d, setflags,
3139 res.carry_out, res.overflow))
3145 // This instruction adds an immediate value to a register value, and writes the
3146 // result to the destination register. It can optionally update the condition
3147 // flags based on the result.
3148 bool EmulateInstructionARM::EmulateADDImmARM(const uint32_t opcode,
3149 const ARMEncoding encoding) {
3151 // ARM pseudo code...
3152 if ConditionPassed() then
3153 EncodingSpecificOperations();
3154 (result, carry, overflow) = AddWithCarry(R[n], imm32, '0');
3156 ALUWritePC(result); // setflags is always FALSE here
3160 APSR.N = result<31>;
3161 APSR.Z = IsZeroBit(result);
3166 bool success = false;
3168 if (ConditionPassed(opcode)) {
3171 imm32; // the immediate value to be added to the value obtained from Rn
3175 Rd = Bits32(opcode, 15, 12);
3176 Rn = Bits32(opcode, 19, 16);
3177 setflags = BitIsSet(opcode, 20);
3178 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
3184 // Read the first operand.
3185 uint32_t val1 = ReadCoreReg(Rn, &success);
3189 AddWithCarryResult res = AddWithCarry(val1, imm32, 0);
3191 EmulateInstruction::Context context;
3193 context.type = EmulateInstruction::eContextAdjustStackPointer;
3194 else if (Rd == GetFramePointerRegisterNumber())
3195 context.type = EmulateInstruction::eContextSetFramePointer;
3197 context.type = EmulateInstruction::eContextRegisterPlusOffset;
3199 RegisterInfo dwarf_reg;
3200 GetRegisterInfo(eRegisterKindDWARF, Rn, dwarf_reg);
3201 context.SetRegisterPlusOffset(dwarf_reg, imm32);
3203 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags,
3204 res.carry_out, res.overflow))
3210 // This instruction adds a register value and an optionally-shifted register
3211 // value, and writes the result to the destination register. It can optionally
3212 // update the condition flags based on the result.
3213 bool EmulateInstructionARM::EmulateADDReg(const uint32_t opcode,
3214 const ARMEncoding encoding) {
3216 // ARM pseudo code...
3217 if ConditionPassed() then
3218 EncodingSpecificOperations();
3219 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
3220 (result, carry, overflow) = AddWithCarry(R[n], shifted, '0');
3222 ALUWritePC(result); // setflags is always FALSE here
3226 APSR.N = result<31>;
3227 APSR.Z = IsZeroBit(result);
3232 bool success = false;
3234 if (ConditionPassed(opcode)) {
3235 uint32_t Rd, Rn, Rm;
3236 ARM_ShifterType shift_t;
3237 uint32_t shift_n; // the shift applied to the value read from Rm
3241 Rd = Bits32(opcode, 2, 0);
3242 Rn = Bits32(opcode, 5, 3);
3243 Rm = Bits32(opcode, 8, 6);
3244 setflags = !InITBlock();
3245 shift_t = SRType_LSL;
3249 Rd = Rn = Bit32(opcode, 7) << 3 | Bits32(opcode, 2, 0);
3250 Rm = Bits32(opcode, 6, 3);
3252 shift_t = SRType_LSL;
3254 if (Rn == 15 && Rm == 15)
3256 if (Rd == 15 && InITBlock() && !LastInITBlock())
3260 Rd = Bits32(opcode, 15, 12);
3261 Rn = Bits32(opcode, 19, 16);
3262 Rm = Bits32(opcode, 3, 0);
3263 setflags = BitIsSet(opcode, 20);
3264 shift_n = DecodeImmShiftARM(opcode, shift_t);
3270 // Read the first operand.
3271 uint32_t val1 = ReadCoreReg(Rn, &success);
3275 // Read the second operand.
3276 uint32_t val2 = ReadCoreReg(Rm, &success);
3280 uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C, &success);
3283 AddWithCarryResult res = AddWithCarry(val1, shifted, 0);
3285 EmulateInstruction::Context context;
3286 context.type = eContextArithmetic;
3287 RegisterInfo op1_reg;
3288 RegisterInfo op2_reg;
3289 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + Rn, op1_reg);
3290 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + Rm, op2_reg);
3291 context.SetRegisterRegisterOperands(op1_reg, op2_reg);
3293 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags,
3294 res.carry_out, res.overflow))
3300 // Compare Negative (immediate) adds a register value and an immediate value.
3301 // It updates the condition flags based on the result, and discards the result.
3302 bool EmulateInstructionARM::EmulateCMNImm(const uint32_t opcode,
3303 const ARMEncoding encoding) {
3305 // ARM pseudo code...
3306 if ConditionPassed() then
3307 EncodingSpecificOperations();
3308 (result, carry, overflow) = AddWithCarry(R[n], imm32, '0');
3309 APSR.N = result<31>;
3310 APSR.Z = IsZeroBit(result);
3315 bool success = false;
3317 uint32_t Rn; // the first operand
3318 uint32_t imm32; // the immediate value to be compared with
3321 Rn = Bits32(opcode, 19, 16);
3322 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8)
3327 Rn = Bits32(opcode, 19, 16);
3328 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
3333 // Read the register value from the operand register Rn.
3334 uint32_t reg_val = ReadCoreReg(Rn, &success);
3338 AddWithCarryResult res = AddWithCarry(reg_val, imm32, 0);
3340 EmulateInstruction::Context context;
3341 context.type = EmulateInstruction::eContextImmediate;
3342 context.SetNoArgs();
3343 if (!WriteFlags(context, res.result, res.carry_out, res.overflow))
3349 // Compare Negative (register) adds a register value and an optionally-shifted
3350 // register value. It updates the condition flags based on the result, and
3351 // discards the result.
3352 bool EmulateInstructionARM::EmulateCMNReg(const uint32_t opcode,
3353 const ARMEncoding encoding) {
3355 // ARM pseudo code...
3356 if ConditionPassed() then
3357 EncodingSpecificOperations();
3358 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
3359 (result, carry, overflow) = AddWithCarry(R[n], shifted, '0');
3360 APSR.N = result<31>;
3361 APSR.Z = IsZeroBit(result);
3366 bool success = false;
3368 uint32_t Rn; // the first operand
3369 uint32_t Rm; // the second operand
3370 ARM_ShifterType shift_t;
3371 uint32_t shift_n; // the shift applied to the value read from Rm
3374 Rn = Bits32(opcode, 2, 0);
3375 Rm = Bits32(opcode, 5, 3);
3376 shift_t = SRType_LSL;
3380 Rn = Bits32(opcode, 19, 16);
3381 Rm = Bits32(opcode, 3, 0);
3382 shift_n = DecodeImmShiftThumb(opcode, shift_t);
3383 // if n == 15 || BadReg(m) then UNPREDICTABLE;
3384 if (Rn == 15 || BadReg(Rm))
3388 Rn = Bits32(opcode, 19, 16);
3389 Rm = Bits32(opcode, 3, 0);
3390 shift_n = DecodeImmShiftARM(opcode, shift_t);
3395 // Read the register value from register Rn.
3396 uint32_t val1 = ReadCoreReg(Rn, &success);
3400 // Read the register value from register Rm.
3401 uint32_t val2 = ReadCoreReg(Rm, &success);
3405 uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C, &success);
3408 AddWithCarryResult res = AddWithCarry(val1, shifted, 0);
3410 EmulateInstruction::Context context;
3411 context.type = EmulateInstruction::eContextImmediate;
3412 context.SetNoArgs();
3413 if (!WriteFlags(context, res.result, res.carry_out, res.overflow))
3419 // Compare (immediate) subtracts an immediate value from a register value. It
3420 // updates the condition flags based on the result, and discards the result.
3421 bool EmulateInstructionARM::EmulateCMPImm(const uint32_t opcode,
3422 const ARMEncoding encoding) {
3424 // ARM pseudo code...
3425 if ConditionPassed() then
3426 EncodingSpecificOperations();
3427 (result, carry, overflow) = AddWithCarry(R[n], NOT(imm32), '1');
3428 APSR.N = result<31>;
3429 APSR.Z = IsZeroBit(result);
3434 bool success = false;
3436 uint32_t Rn; // the first operand
3437 uint32_t imm32; // the immediate value to be compared with
3440 Rn = Bits32(opcode, 10, 8);
3441 imm32 = Bits32(opcode, 7, 0);
3444 Rn = Bits32(opcode, 19, 16);
3445 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8)
3450 Rn = Bits32(opcode, 19, 16);
3451 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
3456 // Read the register value from the operand register Rn.
3457 uint32_t reg_val = ReadCoreReg(Rn, &success);
3461 AddWithCarryResult res = AddWithCarry(reg_val, ~imm32, 1);
3463 EmulateInstruction::Context context;
3464 context.type = EmulateInstruction::eContextImmediate;
3465 context.SetNoArgs();
3466 if (!WriteFlags(context, res.result, res.carry_out, res.overflow))
3472 // Compare (register) subtracts an optionally-shifted register value from a
3473 // register value. It updates the condition flags based on the result, and
3474 // discards the result.
3475 bool EmulateInstructionARM::EmulateCMPReg(const uint32_t opcode,
3476 const ARMEncoding encoding) {
3478 // ARM pseudo code...
3479 if ConditionPassed() then
3480 EncodingSpecificOperations();
3481 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
3482 (result, carry, overflow) = AddWithCarry(R[n], NOT(shifted), '1');
3483 APSR.N = result<31>;
3484 APSR.Z = IsZeroBit(result);
3489 bool success = false;
3491 uint32_t Rn; // the first operand
3492 uint32_t Rm; // the second operand
3493 ARM_ShifterType shift_t;
3494 uint32_t shift_n; // the shift applied to the value read from Rm
3497 Rn = Bits32(opcode, 2, 0);
3498 Rm = Bits32(opcode, 5, 3);
3499 shift_t = SRType_LSL;
3503 Rn = Bit32(opcode, 7) << 3 | Bits32(opcode, 2, 0);
3504 Rm = Bits32(opcode, 6, 3);
3505 shift_t = SRType_LSL;
3507 if (Rn < 8 && Rm < 8)
3509 if (Rn == 15 || Rm == 15)
3513 Rn = Bits32(opcode, 19, 16);
3514 Rm = Bits32(opcode, 3, 0);
3515 shift_n = DecodeImmShiftThumb(opcode, shift_t);
3516 if (Rn == 15 || BadReg(Rm))
3520 Rn = Bits32(opcode, 19, 16);
3521 Rm = Bits32(opcode, 3, 0);
3522 shift_n = DecodeImmShiftARM(opcode, shift_t);
3527 // Read the register value from register Rn.
3528 uint32_t val1 = ReadCoreReg(Rn, &success);
3532 // Read the register value from register Rm.
3533 uint32_t val2 = ReadCoreReg(Rm, &success);
3537 uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C, &success);
3540 AddWithCarryResult res = AddWithCarry(val1, ~shifted, 1);
3542 EmulateInstruction::Context context;
3543 context.type = EmulateInstruction::eContextImmediate;
3544 context.SetNoArgs();
3545 if (!WriteFlags(context, res.result, res.carry_out, res.overflow))
3551 // Arithmetic Shift Right (immediate) shifts a register value right by an
3552 // immediate number of bits, shifting in copies of its sign bit, and writes the
3553 // result to the destination register. It can optionally update the condition
3554 // flags based on the result.
3555 bool EmulateInstructionARM::EmulateASRImm(const uint32_t opcode,
3556 const ARMEncoding encoding) {
3558 // ARM pseudo code...
3559 if ConditionPassed() then
3560 EncodingSpecificOperations();
3561 (result, carry) = Shift_C(R[m], SRType_ASR, shift_n, APSR.C);
3562 if d == 15 then // Can only occur for ARM encoding
3563 ALUWritePC(result); // setflags is always FALSE here
3567 APSR.N = result<31>;
3568 APSR.Z = IsZeroBit(result);
3573 return EmulateShiftImm(opcode, encoding, SRType_ASR);
3576 // Arithmetic Shift Right (register) shifts a register value right by a
3577 // variable number of bits, shifting in copies of its sign bit, and writes the
3578 // result to the destination register. The variable number of bits is read from
3579 // the bottom byte of a register. It can optionally update the condition flags
3580 // based on the result.
3581 bool EmulateInstructionARM::EmulateASRReg(const uint32_t opcode,
3582 const ARMEncoding encoding) {
3584 // ARM pseudo code...
3585 if ConditionPassed() then
3586 EncodingSpecificOperations();
3587 shift_n = UInt(R[m]<7:0>);
3588 (result, carry) = Shift_C(R[m], SRType_ASR, shift_n, APSR.C);
3591 APSR.N = result<31>;
3592 APSR.Z = IsZeroBit(result);
3597 return EmulateShiftReg(opcode, encoding, SRType_ASR);
3600 // Logical Shift Left (immediate) shifts a register value left by an immediate
3601 // number of bits, shifting in zeros, and writes the result to the destination
3602 // register. It can optionally update the condition flags based on the result.
3603 bool EmulateInstructionARM::EmulateLSLImm(const uint32_t opcode,
3604 const ARMEncoding encoding) {
3606 // ARM pseudo code...
3607 if ConditionPassed() then
3608 EncodingSpecificOperations();
3609 (result, carry) = Shift_C(R[m], SRType_LSL, shift_n, APSR.C);
3610 if d == 15 then // Can only occur for ARM encoding
3611 ALUWritePC(result); // setflags is always FALSE here
3615 APSR.N = result<31>;
3616 APSR.Z = IsZeroBit(result);
3621 return EmulateShiftImm(opcode, encoding, SRType_LSL);
3624 // Logical Shift Left (register) shifts a register value left by a variable
3625 // number of bits, shifting in zeros, and writes the result to the destination
3626 // register. The variable number of bits is read from the bottom byte of a
3627 // register. It can optionally update the condition flags based on the result.
3628 bool EmulateInstructionARM::EmulateLSLReg(const uint32_t opcode,
3629 const ARMEncoding encoding) {
3631 // ARM pseudo code...
3632 if ConditionPassed() then
3633 EncodingSpecificOperations();
3634 shift_n = UInt(R[m]<7:0>);
3635 (result, carry) = Shift_C(R[m], SRType_LSL, shift_n, APSR.C);
3638 APSR.N = result<31>;
3639 APSR.Z = IsZeroBit(result);
3644 return EmulateShiftReg(opcode, encoding, SRType_LSL);
3647 // Logical Shift Right (immediate) shifts a register value right by an
3648 // immediate number of bits, shifting in zeros, and writes the result to the
3649 // destination register. It can optionally update the condition flags based on
3651 bool EmulateInstructionARM::EmulateLSRImm(const uint32_t opcode,
3652 const ARMEncoding encoding) {
3654 // ARM pseudo code...
3655 if ConditionPassed() then
3656 EncodingSpecificOperations();
3657 (result, carry) = Shift_C(R[m], SRType_LSR, shift_n, APSR.C);
3658 if d == 15 then // Can only occur for ARM encoding
3659 ALUWritePC(result); // setflags is always FALSE here
3663 APSR.N = result<31>;
3664 APSR.Z = IsZeroBit(result);
3669 return EmulateShiftImm(opcode, encoding, SRType_LSR);
3672 // Logical Shift Right (register) shifts a register value right by a variable
3673 // number of bits, shifting in zeros, and writes the result to the destination
3674 // register. The variable number of bits is read from the bottom byte of a
3675 // register. It can optionally update the condition flags based on the result.
3676 bool EmulateInstructionARM::EmulateLSRReg(const uint32_t opcode,
3677 const ARMEncoding encoding) {
3679 // ARM pseudo code...
3680 if ConditionPassed() then
3681 EncodingSpecificOperations();
3682 shift_n = UInt(R[m]<7:0>);
3683 (result, carry) = Shift_C(R[m], SRType_LSR, shift_n, APSR.C);
3686 APSR.N = result<31>;
3687 APSR.Z = IsZeroBit(result);
3692 return EmulateShiftReg(opcode, encoding, SRType_LSR);
3695 // Rotate Right (immediate) provides the value of the contents of a register
3696 // rotated by a constant value. The bits that are rotated off the right end are
3697 // inserted into the vacated bit positions on the left. It can optionally
3698 // update the condition flags based on the result.
3699 bool EmulateInstructionARM::EmulateRORImm(const uint32_t opcode,
3700 const ARMEncoding encoding) {
3702 // ARM pseudo code...
3703 if ConditionPassed() then
3704 EncodingSpecificOperations();
3705 (result, carry) = Shift_C(R[m], SRType_ROR, shift_n, APSR.C);
3706 if d == 15 then // Can only occur for ARM encoding
3707 ALUWritePC(result); // setflags is always FALSE here
3711 APSR.N = result<31>;
3712 APSR.Z = IsZeroBit(result);
3717 return EmulateShiftImm(opcode, encoding, SRType_ROR);
3720 // Rotate Right (register) provides the value of the contents of a register
3721 // rotated by a variable number of bits. The bits that are rotated off the
3722 // right end are inserted into the vacated bit positions on the left. The
3723 // variable number of bits is read from the bottom byte of a register. It can
3724 // optionally update the condition flags based on the result.
3725 bool EmulateInstructionARM::EmulateRORReg(const uint32_t opcode,
3726 const ARMEncoding encoding) {
3728 // ARM pseudo code...
3729 if ConditionPassed() then
3730 EncodingSpecificOperations();
3731 shift_n = UInt(R[m]<7:0>);
3732 (result, carry) = Shift_C(R[m], SRType_ROR, shift_n, APSR.C);
3735 APSR.N = result<31>;
3736 APSR.Z = IsZeroBit(result);
3741 return EmulateShiftReg(opcode, encoding, SRType_ROR);
3744 // Rotate Right with Extend provides the value of the contents of a register
3745 // shifted right by one place, with the carry flag shifted into bit [31].
3747 // RRX can optionally update the condition flags based on the result.
3748 // In that case, bit [0] is shifted into the carry flag.
3749 bool EmulateInstructionARM::EmulateRRX(const uint32_t opcode,
3750 const ARMEncoding encoding) {
3752 // ARM pseudo code...
3753 if ConditionPassed() then
3754 EncodingSpecificOperations();
3755 (result, carry) = Shift_C(R[m], SRType_RRX, 1, APSR.C);
3756 if d == 15 then // Can only occur for ARM encoding
3757 ALUWritePC(result); // setflags is always FALSE here
3761 APSR.N = result<31>;
3762 APSR.Z = IsZeroBit(result);
3767 return EmulateShiftImm(opcode, encoding, SRType_RRX);
3770 bool EmulateInstructionARM::EmulateShiftImm(const uint32_t opcode,
3771 const ARMEncoding encoding,
3772 ARM_ShifterType shift_type) {
3773 // assert(shift_type == SRType_ASR
3774 // || shift_type == SRType_LSL
3775 // || shift_type == SRType_LSR
3776 // || shift_type == SRType_ROR
3777 // || shift_type == SRType_RRX);
3779 bool success = false;
3781 if (ConditionPassed(opcode)) {
3782 uint32_t Rd; // the destination register
3783 uint32_t Rm; // the first operand register
3784 uint32_t imm5; // encoding for the shift amount
3785 uint32_t carry; // the carry bit after the shift operation
3788 // Special case handling!
3789 // A8.6.139 ROR (immediate) -- Encoding T1
3790 ARMEncoding use_encoding = encoding;
3791 if (shift_type == SRType_ROR && use_encoding == eEncodingT1) {
3792 // Morph the T1 encoding from the ARM Architecture Manual into T2
3793 // encoding to have the same decoding of bit fields as the other Thumb2
3794 // shift operations.
3795 use_encoding = eEncodingT2;
3798 switch (use_encoding) {
3800 // Due to the above special case handling!
3801 if (shift_type == SRType_ROR)
3804 Rd = Bits32(opcode, 2, 0);
3805 Rm = Bits32(opcode, 5, 3);
3806 setflags = !InITBlock();
3807 imm5 = Bits32(opcode, 10, 6);
3811 // There's no imm form of RRX instructions.
3812 if (shift_type == SRType_RRX)
3815 Rd = Bits32(opcode, 11, 8);
3816 Rm = Bits32(opcode, 3, 0);
3817 setflags = BitIsSet(opcode, 20);
3818 imm5 = Bits32(opcode, 14, 12) << 2 | Bits32(opcode, 7, 6);
3819 if (BadReg(Rd) || BadReg(Rm))
3823 Rd = Bits32(opcode, 15, 12);
3824 Rm = Bits32(opcode, 3, 0);
3825 setflags = BitIsSet(opcode, 20);
3826 imm5 = Bits32(opcode, 11, 7);
3832 // A8.6.139 ROR (immediate)
3833 if (shift_type == SRType_ROR && imm5 == 0)
3834 shift_type = SRType_RRX;
3836 // Get the first operand.
3837 uint32_t value = ReadCoreReg(Rm, &success);
3841 // Decode the shift amount if not RRX.
3843 (shift_type == SRType_RRX ? 1 : DecodeImmShift(shift_type, imm5));
3845 uint32_t result = Shift_C(value, shift_type, amt, APSR_C, carry, &success);
3849 // The context specifies that an immediate is to be moved into Rd.
3850 EmulateInstruction::Context context;
3851 context.type = EmulateInstruction::eContextImmediate;
3852 context.SetNoArgs();
3854 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
3860 bool EmulateInstructionARM::EmulateShiftReg(const uint32_t opcode,
3861 const ARMEncoding encoding,
3862 ARM_ShifterType shift_type) {
3863 // assert(shift_type == SRType_ASR
3864 // || shift_type == SRType_LSL
3865 // || shift_type == SRType_LSR
3866 // || shift_type == SRType_ROR);
3868 bool success = false;
3870 if (ConditionPassed(opcode)) {
3871 uint32_t Rd; // the destination register
3872 uint32_t Rn; // the first operand register
3874 Rm; // the register whose bottom byte contains the amount to shift by
3875 uint32_t carry; // the carry bit after the shift operation
3879 Rd = Bits32(opcode, 2, 0);
3881 Rm = Bits32(opcode, 5, 3);
3882 setflags = !InITBlock();
3885 Rd = Bits32(opcode, 11, 8);
3886 Rn = Bits32(opcode, 19, 16);
3887 Rm = Bits32(opcode, 3, 0);
3888 setflags = BitIsSet(opcode, 20);
3889 if (BadReg(Rd) || BadReg(Rn) || BadReg(Rm))
3893 Rd = Bits32(opcode, 15, 12);
3894 Rn = Bits32(opcode, 3, 0);
3895 Rm = Bits32(opcode, 11, 8);
3896 setflags = BitIsSet(opcode, 20);
3897 if (Rd == 15 || Rn == 15 || Rm == 15)
3904 // Get the first operand.
3905 uint32_t value = ReadCoreReg(Rn, &success);
3908 // Get the Rm register content.
3909 uint32_t val = ReadCoreReg(Rm, &success);
3913 // Get the shift amount.
3914 uint32_t amt = Bits32(val, 7, 0);
3916 uint32_t result = Shift_C(value, shift_type, amt, APSR_C, carry, &success);
3920 // The context specifies that an immediate is to be moved into Rd.
3921 EmulateInstruction::Context context;
3922 context.type = EmulateInstruction::eContextImmediate;
3923 context.SetNoArgs();
3925 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
3931 // LDM loads multiple registers from consecutive memory locations, using an
3932 // address from a base register. Optionally the address just above the highest
3933 // of those locations can be written back to the base register.
3934 bool EmulateInstructionARM::EmulateLDM(const uint32_t opcode,
3935 const ARMEncoding encoding) {
3937 // ARM pseudo code...
3938 if ConditionPassed()
3939 EncodingSpecificOperations(); NullCheckIfThumbEE (n);
3943 if registers<i> == '1' then
3944 R[i] = MemA[address, 4]; address = address + 4;
3945 if registers<15> == '1' then
3946 LoadWritePC (MemA[address, 4]);
3948 if wback && registers<n> == '0' then R[n] = R[n] + 4 * BitCount (registers);
3949 if wback && registers<n> == '1' then R[n] = bits(32) UNKNOWN; // Only possible for encoding A1
3953 bool success = false;
3954 if (ConditionPassed(opcode)) {
3956 uint32_t registers = 0;
3958 const uint32_t addr_byte_size = GetAddressByteSize();
3961 // n = UInt(Rn); registers = '00000000':register_list; wback =
3962 // (registers<n> == '0');
3963 n = Bits32(opcode, 10, 8);
3964 registers = Bits32(opcode, 7, 0);
3965 registers = registers & 0x00ff; // Make sure the top 8 bits are zeros.
3966 wback = BitIsClear(registers, n);
3967 // if BitCount(registers) < 1 then UNPREDICTABLE;
3968 if (BitCount(registers) < 1)
3972 // if W == '1' && Rn == '1101' then SEE POP;
3973 // n = UInt(Rn); registers = P:M:'0':register_list; wback = (W == '1');
3974 n = Bits32(opcode, 19, 16);
3975 registers = Bits32(opcode, 15, 0);
3976 registers = registers & 0xdfff; // Make sure bit 13 is zero.
3977 wback = BitIsSet(opcode, 21);
3979 // if n == 15 || BitCount(registers) < 2 || (P == '1' && M == '1') then
3981 if ((n == 15) || (BitCount(registers) < 2) ||
3982 (BitIsSet(opcode, 14) && BitIsSet(opcode, 15)))
3985 // if registers<15> == '1' && InITBlock() && !LastInITBlock() then
3987 if (BitIsSet(registers, 15) && InITBlock() && !LastInITBlock())
3990 // if wback && registers<n> == '1' then UNPREDICTABLE;
3991 if (wback && BitIsSet(registers, n))
3996 n = Bits32(opcode, 19, 16);
3997 registers = Bits32(opcode, 15, 0);
3998 wback = BitIsSet(opcode, 21);
3999 if ((n == 15) || (BitCount(registers) < 1))
4007 const addr_t base_address =
4008 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
4012 EmulateInstruction::Context context;
4013 context.type = EmulateInstruction::eContextRegisterPlusOffset;
4014 RegisterInfo dwarf_reg;
4015 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n, dwarf_reg);
4016 context.SetRegisterPlusOffset(dwarf_reg, offset);
4018 for (int i = 0; i < 14; ++i) {
4019 if (BitIsSet(registers, i)) {
4020 context.type = EmulateInstruction::eContextRegisterPlusOffset;
4021 context.SetRegisterPlusOffset(dwarf_reg, offset);
4022 if (wback && (n == 13)) // Pop Instruction
4024 context.type = EmulateInstruction::eContextPopRegisterOffStack;
4025 context.SetAddress(base_address + offset);
4028 // R[i] = MemA [address, 4]; address = address + 4;
4029 uint32_t data = MemARead(context, base_address + offset, addr_byte_size,
4034 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + i,
4038 offset += addr_byte_size;
4042 if (BitIsSet(registers, 15)) {
4043 // LoadWritePC (MemA [address, 4]);
4044 context.type = EmulateInstruction::eContextRegisterPlusOffset;
4045 context.SetRegisterPlusOffset(dwarf_reg, offset);
4047 MemARead(context, base_address + offset, addr_byte_size, 0, &success);
4050 // In ARMv5T and above, this is an interworking branch.
4051 if (!LoadWritePC(context, data))
4055 if (wback && BitIsClear(registers, n)) {
4056 // R[n] = R[n] + 4 * BitCount (registers)
4057 int32_t offset = addr_byte_size * BitCount(registers);
4058 context.type = EmulateInstruction::eContextAdjustBaseRegister;
4059 context.SetRegisterPlusOffset(dwarf_reg, offset);
4061 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n,
4062 base_address + offset))
4065 if (wback && BitIsSet(registers, n))
4066 // R[n] bits(32) UNKNOWN;
4067 return WriteBits32Unknown(n);
4072 // LDMDA loads multiple registers from consecutive memory locations using an
4073 // address from a base register.
4074 // The consecutive memory locations end at this address and the address just
4075 // below the lowest of those locations can optionally be written back to the
4077 bool EmulateInstructionARM::EmulateLDMDA(const uint32_t opcode,
4078 const ARMEncoding encoding) {
4080 // ARM pseudo code...
4081 if ConditionPassed() then
4082 EncodingSpecificOperations();
4083 address = R[n] - 4*BitCount(registers) + 4;
4086 if registers<i> == '1' then
4087 R[i] = MemA[address,4]; address = address + 4;
4089 if registers<15> == '1' then
4090 LoadWritePC(MemA[address,4]);
4092 if wback && registers<n> == '0' then R[n] = R[n] - 4*BitCount(registers);
4093 if wback && registers<n> == '1' then R[n] = bits(32) UNKNOWN;
4096 bool success = false;
4098 if (ConditionPassed(opcode)) {
4100 uint32_t registers = 0;
4102 const uint32_t addr_byte_size = GetAddressByteSize();
4104 // EncodingSpecificOperations();
4107 // n = UInt(Rn); registers = register_list; wback = (W == '1');
4108 n = Bits32(opcode, 19, 16);
4109 registers = Bits32(opcode, 15, 0);
4110 wback = BitIsSet(opcode, 21);
4112 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
4113 if ((n == 15) || (BitCount(registers) < 1))
4121 // address = R[n] - 4*BitCount(registers) + 4;
4124 addr_t Rn = ReadCoreReg(n, &success);
4130 Rn - (addr_byte_size * BitCount(registers)) + addr_byte_size;
4132 EmulateInstruction::Context context;
4133 context.type = EmulateInstruction::eContextRegisterPlusOffset;
4134 RegisterInfo dwarf_reg;
4135 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n, dwarf_reg);
4136 context.SetRegisterPlusOffset(dwarf_reg, offset);
4139 for (int i = 0; i < 14; ++i) {
4140 // if registers<i> == '1' then
4141 if (BitIsSet(registers, i)) {
4142 // R[i] = MemA[address,4]; address = address + 4;
4143 context.SetRegisterPlusOffset(dwarf_reg, Rn - (address + offset));
4145 MemARead(context, address + offset, addr_byte_size, 0, &success);
4148 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + i,
4151 offset += addr_byte_size;
4155 // if registers<15> == '1' then
4156 // LoadWritePC(MemA[address,4]);
4157 if (BitIsSet(registers, 15)) {
4158 context.SetRegisterPlusOffset(dwarf_reg, offset);
4160 MemARead(context, address + offset, addr_byte_size, 0, &success);
4163 // In ARMv5T and above, this is an interworking branch.
4164 if (!LoadWritePC(context, data))
4168 // if wback && registers<n> == '0' then R[n] = R[n] - 4*BitCount(registers);
4169 if (wback && BitIsClear(registers, n)) {
4173 offset = (addr_byte_size * BitCount(registers)) * -1;
4174 context.type = EmulateInstruction::eContextAdjustBaseRegister;
4175 context.SetImmediateSigned(offset);
4176 addr_t addr = Rn + offset;
4177 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n,
4182 // if wback && registers<n> == '1' then R[n] = bits(32) UNKNOWN;
4183 if (wback && BitIsSet(registers, n))
4184 return WriteBits32Unknown(n);
4189 // LDMDB loads multiple registers from consecutive memory locations using an
4190 // address from a base register. The
4191 // consecutive memory locations end just below this address, and the address of
4192 // the lowest of those locations can be optionally written back to the base
4194 bool EmulateInstructionARM::EmulateLDMDB(const uint32_t opcode,
4195 const ARMEncoding encoding) {
4197 // ARM pseudo code...
4198 if ConditionPassed() then
4199 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
4200 address = R[n] - 4*BitCount(registers);
4203 if registers<i> == '1' then
4204 R[i] = MemA[address,4]; address = address + 4;
4205 if registers<15> == '1' then
4206 LoadWritePC(MemA[address,4]);
4208 if wback && registers<n> == '0' then R[n] = R[n] - 4*BitCount(registers);
4209 if wback && registers<n> == '1' then R[n] = bits(32) UNKNOWN; // Only possible for encoding A1
4212 bool success = false;
4214 if (ConditionPassed(opcode)) {
4216 uint32_t registers = 0;
4218 const uint32_t addr_byte_size = GetAddressByteSize();
4221 // n = UInt(Rn); registers = P:M:'0':register_list; wback = (W == '1');
4222 n = Bits32(opcode, 19, 16);
4223 registers = Bits32(opcode, 15, 0);
4224 registers = registers & 0xdfff; // Make sure bit 13 is a zero.
4225 wback = BitIsSet(opcode, 21);
4227 // if n == 15 || BitCount(registers) < 2 || (P == '1' && M == '1') then
4229 if ((n == 15) || (BitCount(registers) < 2) ||
4230 (BitIsSet(opcode, 14) && BitIsSet(opcode, 15)))
4233 // if registers<15> == '1' && InITBlock() && !LastInITBlock() then
4235 if (BitIsSet(registers, 15) && InITBlock() && !LastInITBlock())
4238 // if wback && registers<n> == '1' then UNPREDICTABLE;
4239 if (wback && BitIsSet(registers, n))
4245 // n = UInt(Rn); registers = register_list; wback = (W == '1');
4246 n = Bits32(opcode, 19, 16);
4247 registers = Bits32(opcode, 15, 0);
4248 wback = BitIsSet(opcode, 21);
4250 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
4251 if ((n == 15) || (BitCount(registers) < 1))
4260 // address = R[n] - 4*BitCount(registers);
4264 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
4269 addr_t address = Rn - (addr_byte_size * BitCount(registers));
4270 EmulateInstruction::Context context;
4271 context.type = EmulateInstruction::eContextRegisterPlusOffset;
4272 RegisterInfo dwarf_reg;
4273 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n, dwarf_reg);
4274 context.SetRegisterPlusOffset(dwarf_reg, Rn - address);
4276 for (int i = 0; i < 14; ++i) {
4277 if (BitIsSet(registers, i)) {
4278 // R[i] = MemA[address,4]; address = address + 4;
4279 context.SetRegisterPlusOffset(dwarf_reg, Rn - (address + offset));
4281 MemARead(context, address + offset, addr_byte_size, 0, &success);
4285 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + i,
4289 offset += addr_byte_size;
4293 // if registers<15> == '1' then
4294 // LoadWritePC(MemA[address,4]);
4295 if (BitIsSet(registers, 15)) {
4296 context.SetRegisterPlusOffset(dwarf_reg, offset);
4298 MemARead(context, address + offset, addr_byte_size, 0, &success);
4301 // In ARMv5T and above, this is an interworking branch.
4302 if (!LoadWritePC(context, data))
4306 // if wback && registers<n> == '0' then R[n] = R[n] - 4*BitCount(registers);
4307 if (wback && BitIsClear(registers, n)) {
4311 offset = (addr_byte_size * BitCount(registers)) * -1;
4312 context.type = EmulateInstruction::eContextAdjustBaseRegister;
4313 context.SetImmediateSigned(offset);
4314 addr_t addr = Rn + offset;
4315 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n,
4320 // if wback && registers<n> == '1' then R[n] = bits(32) UNKNOWN; // Only
4321 // possible for encoding A1
4322 if (wback && BitIsSet(registers, n))
4323 return WriteBits32Unknown(n);
4328 // LDMIB loads multiple registers from consecutive memory locations using an
4329 // address from a base register. The
4330 // consecutive memory locations start just above this address, and thea ddress
4331 // of the last of those locations can optinoally be written back to the base
4333 bool EmulateInstructionARM::EmulateLDMIB(const uint32_t opcode,
4334 const ARMEncoding encoding) {
4336 if ConditionPassed() then
4337 EncodingSpecificOperations();
4341 if registers<i> == '1' then
4342 R[i] = MemA[address,4]; address = address + 4;
4343 if registers<15> == '1' then
4344 LoadWritePC(MemA[address,4]);
4346 if wback && registers<n> == '0' then R[n] = R[n] + 4*BitCount(registers);
4347 if wback && registers<n> == '1' then R[n] = bits(32) UNKNOWN;
4350 bool success = false;
4352 if (ConditionPassed(opcode)) {
4354 uint32_t registers = 0;
4356 const uint32_t addr_byte_size = GetAddressByteSize();
4359 // n = UInt(Rn); registers = register_list; wback = (W == '1');
4360 n = Bits32(opcode, 19, 16);
4361 registers = Bits32(opcode, 15, 0);
4362 wback = BitIsSet(opcode, 21);
4364 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
4365 if ((n == 15) || (BitCount(registers) < 1))
4372 // address = R[n] + 4;
4376 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
4381 addr_t address = Rn + addr_byte_size;
4383 EmulateInstruction::Context context;
4384 context.type = EmulateInstruction::eContextRegisterPlusOffset;
4385 RegisterInfo dwarf_reg;
4386 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n, dwarf_reg);
4387 context.SetRegisterPlusOffset(dwarf_reg, offset);
4389 for (int i = 0; i < 14; ++i) {
4390 if (BitIsSet(registers, i)) {
4391 // R[i] = MemA[address,4]; address = address + 4;
4393 context.SetRegisterPlusOffset(dwarf_reg, offset + addr_byte_size);
4395 MemARead(context, address + offset, addr_byte_size, 0, &success);
4399 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + i,
4403 offset += addr_byte_size;
4407 // if registers<15> == '1' then
4408 // LoadWritePC(MemA[address,4]);
4409 if (BitIsSet(registers, 15)) {
4410 context.SetRegisterPlusOffset(dwarf_reg, offset);
4412 MemARead(context, address + offset, addr_byte_size, 0, &success);
4415 // In ARMv5T and above, this is an interworking branch.
4416 if (!LoadWritePC(context, data))
4420 // if wback && registers<n> == '0' then R[n] = R[n] + 4*BitCount(registers);
4421 if (wback && BitIsClear(registers, n)) {
4425 offset = addr_byte_size * BitCount(registers);
4426 context.type = EmulateInstruction::eContextAdjustBaseRegister;
4427 context.SetImmediateSigned(offset);
4428 addr_t addr = Rn + offset;
4429 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n,
4434 // if wback && registers<n> == '1' then R[n] = bits(32) UNKNOWN; // Only
4435 // possible for encoding A1
4436 if (wback && BitIsSet(registers, n))
4437 return WriteBits32Unknown(n);
4442 // Load Register (immediate) calculates an address from a base register value
4443 // and an immediate offset, loads a word from memory, and writes to a register.
4444 // LDR (immediate, Thumb)
4445 bool EmulateInstructionARM::EmulateLDRRtRnImm(const uint32_t opcode,
4446 const ARMEncoding encoding) {
4448 // ARM pseudo code...
4449 if (ConditionPassed())
4451 EncodingSpecificOperations(); NullCheckIfThumbEE(15);
4452 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
4453 address = if index then offset_addr else R[n];
4454 data = MemU[address,4];
4455 if wback then R[n] = offset_addr;
4457 if address<1:0> == '00' then LoadWritePC(data); else UNPREDICTABLE;
4458 elsif UnalignedSupport() || address<1:0> = '00' then
4460 else R[t] = bits(32) UNKNOWN; // Can only apply before ARMv7
4464 bool success = false;
4466 if (ConditionPassed(opcode)) {
4467 uint32_t Rt; // the destination register
4468 uint32_t Rn; // the base register
4469 uint32_t imm32; // the immediate offset used to form the address
4470 addr_t offset_addr; // the offset address
4471 addr_t address; // the calculated address
4472 uint32_t data; // the literal data value from memory load
4473 bool add, index, wback;
4476 Rt = Bits32(opcode, 2, 0);
4477 Rn = Bits32(opcode, 5, 3);
4478 imm32 = Bits32(opcode, 10, 6) << 2; // imm32 = ZeroExtend(imm5:'00', 32);
4479 // index = TRUE; add = TRUE; wback = FALSE
4487 // t = UInt(Rt); n = 13; imm32 = ZeroExtend(imm8:'00', 32);
4488 Rt = Bits32(opcode, 10, 8);
4490 imm32 = Bits32(opcode, 7, 0) << 2;
4492 // index = TRUE; add = TRUE; wback = FALSE;
4500 // if Rn == '1111' then SEE LDR (literal);
4501 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
4502 Rt = Bits32(opcode, 15, 12);
4503 Rn = Bits32(opcode, 19, 16);
4504 imm32 = Bits32(opcode, 11, 0);
4506 // index = TRUE; add = TRUE; wback = FALSE;
4511 // if t == 15 && InITBlock() && !LastInITBlock() then UNPREDICTABLE;
4512 if ((Rt == 15) && InITBlock() && !LastInITBlock())
4518 // if Rn == '1111' then SEE LDR (literal);
4519 // if P == '1' && U == '1' && W == '0' then SEE LDRT;
4520 // if Rn == '1101' && P == '0' && U == '1' && W == '1' && imm8 ==
4521 // '00000100' then SEE POP;
4522 // if P == '0' && W == '0' then UNDEFINED;
4523 if (BitIsClear(opcode, 10) && BitIsClear(opcode, 8))
4526 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32);
4527 Rt = Bits32(opcode, 15, 12);
4528 Rn = Bits32(opcode, 19, 16);
4529 imm32 = Bits32(opcode, 7, 0);
4531 // index = (P == '1'); add = (U == '1'); wback = (W == '1');
4532 index = BitIsSet(opcode, 10);
4533 add = BitIsSet(opcode, 9);
4534 wback = BitIsSet(opcode, 8);
4536 // if (wback && n == t) || (t == 15 && InITBlock() && !LastInITBlock())
4537 // then UNPREDICTABLE;
4538 if ((wback && (Rn == Rt)) ||
4539 ((Rt == 15) && InITBlock() && !LastInITBlock()))
4547 uint32_t base = ReadCoreReg(Rn, &success);
4551 offset_addr = base + imm32;
4553 offset_addr = base - imm32;
4555 address = (index ? offset_addr : base);
4557 RegisterInfo base_reg;
4558 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + Rn, base_reg);
4560 EmulateInstruction::Context ctx;
4562 ctx.type = eContextAdjustStackPointer;
4563 ctx.SetImmediateSigned((int32_t)(offset_addr - base));
4564 } else if (Rn == GetFramePointerRegisterNumber()) {
4565 ctx.type = eContextSetFramePointer;
4566 ctx.SetRegisterPlusOffset(base_reg, (int32_t)(offset_addr - base));
4568 ctx.type = EmulateInstruction::eContextAdjustBaseRegister;
4569 ctx.SetRegisterPlusOffset(base_reg, (int32_t)(offset_addr - base));
4572 if (!WriteRegisterUnsigned(ctx, eRegisterKindDWARF, dwarf_r0 + Rn,
4577 // Prepare to write to the Rt register.
4578 EmulateInstruction::Context context;
4579 context.type = EmulateInstruction::eContextRegisterLoad;
4580 context.SetRegisterPlusOffset(base_reg, (int32_t)(offset_addr - base));
4582 // Read memory from the address.
4583 data = MemURead(context, address, 4, 0, &success);
4588 if (Bits32(address, 1, 0) == 0) {
4589 if (!LoadWritePC(context, data))
4593 } else if (UnalignedSupport() || Bits32(address, 1, 0) == 0) {
4594 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + Rt,
4598 WriteBits32Unknown(Rt);
4603 // STM (Store Multiple Increment After) stores multiple registers to consecutive
4604 // memory locations using an address
4605 // from a base register. The consecutive memory locations start at this
4606 // address, and the address just above the last of those locations can
4607 // optionally be written back to the base register.
4608 bool EmulateInstructionARM::EmulateSTM(const uint32_t opcode,
4609 const ARMEncoding encoding) {
4611 if ConditionPassed() then
4612 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
4616 if registers<i> == '1' then
4617 if i == n && wback && i != LowestSetBit(registers) then
4618 MemA[address,4] = bits(32) UNKNOWN; // Only possible for encodings T1 and A1
4620 MemA[address,4] = R[i];
4621 address = address + 4;
4623 if registers<15> == '1' then // Only possible for encoding A1
4624 MemA[address,4] = PCStoreValue();
4625 if wback then R[n] = R[n] + 4*BitCount(registers);
4628 bool success = false;
4630 if (ConditionPassed(opcode)) {
4632 uint32_t registers = 0;
4634 const uint32_t addr_byte_size = GetAddressByteSize();
4636 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
4639 // n = UInt(Rn); registers = '00000000':register_list; wback = TRUE;
4640 n = Bits32(opcode, 10, 8);
4641 registers = Bits32(opcode, 7, 0);
4642 registers = registers & 0x00ff; // Make sure the top 8 bits are zeros.
4645 // if BitCount(registers) < 1 then UNPREDICTABLE;
4646 if (BitCount(registers) < 1)
4652 // n = UInt(Rn); registers = '0':M:'0':register_list; wback = (W == '1');
4653 n = Bits32(opcode, 19, 16);
4654 registers = Bits32(opcode, 15, 0);
4655 registers = registers & 0x5fff; // Make sure bits 15 & 13 are zeros.
4656 wback = BitIsSet(opcode, 21);
4658 // if n == 15 || BitCount(registers) < 2 then UNPREDICTABLE;
4659 if ((n == 15) || (BitCount(registers) < 2))
4662 // if wback && registers<n> == '1' then UNPREDICTABLE;
4663 if (wback && BitIsSet(registers, n))
4669 // n = UInt(Rn); registers = register_list; wback = (W == '1');
4670 n = Bits32(opcode, 19, 16);
4671 registers = Bits32(opcode, 15, 0);
4672 wback = BitIsSet(opcode, 21);
4674 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
4675 if ((n == 15) || (BitCount(registers) < 1))
4686 const addr_t address =
4687 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
4691 EmulateInstruction::Context context;
4692 context.type = EmulateInstruction::eContextRegisterStore;
4693 RegisterInfo base_reg;
4694 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n, base_reg);
4697 uint32_t lowest_set_bit = 14;
4698 for (uint32_t i = 0; i < 14; ++i) {
4699 // if registers<i> == '1' then
4700 if (BitIsSet(registers, i)) {
4701 if (i < lowest_set_bit)
4703 // if i == n && wback && i != LowestSetBit(registers) then
4704 if ((i == n) && wback && (i != lowest_set_bit))
4705 // MemA[address,4] = bits(32) UNKNOWN; // Only possible for encodings
4707 WriteBits32UnknownToMemory(address + offset);
4709 // MemA[address,4] = R[i];
4710 uint32_t data = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + i,
4715 RegisterInfo data_reg;
4716 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + i, data_reg);
4717 context.SetRegisterToRegisterPlusOffset(data_reg, base_reg, offset);
4718 if (!MemAWrite(context, address + offset, data, addr_byte_size))
4722 // address = address + 4;
4723 offset += addr_byte_size;
4727 // if registers<15> == '1' then // Only possible for encoding A1
4728 // MemA[address,4] = PCStoreValue();
4729 if (BitIsSet(registers, 15)) {
4730 RegisterInfo pc_reg;
4731 GetRegisterInfo(eRegisterKindDWARF, dwarf_pc, pc_reg);
4732 context.SetRegisterPlusOffset(pc_reg, 8);
4733 const uint32_t pc = ReadCoreReg(PC_REG, &success);
4737 if (!MemAWrite(context, address + offset, pc, addr_byte_size))
4741 // if wback then R[n] = R[n] + 4*BitCount(registers);
4743 offset = addr_byte_size * BitCount(registers);
4744 context.type = EmulateInstruction::eContextAdjustBaseRegister;
4745 context.SetImmediateSigned(offset);
4746 addr_t data = address + offset;
4747 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n,
4755 // STMDA (Store Multiple Decrement After) stores multiple registers to
4756 // consecutive memory locations using an address from a base register. The
4757 // consecutive memory locations end at this address, and the address just below
4758 // the lowest of those locations can optionally be written back to the base
4760 bool EmulateInstructionARM::EmulateSTMDA(const uint32_t opcode,
4761 const ARMEncoding encoding) {
4763 if ConditionPassed() then
4764 EncodingSpecificOperations();
4765 address = R[n] - 4*BitCount(registers) + 4;
4768 if registers<i> == '1' then
4769 if i == n && wback && i != LowestSetBit(registers) then
4770 MemA[address,4] = bits(32) UNKNOWN;
4772 MemA[address,4] = R[i];
4773 address = address + 4;
4775 if registers<15> == '1' then
4776 MemA[address,4] = PCStoreValue();
4778 if wback then R[n] = R[n] - 4*BitCount(registers);
4781 bool success = false;
4783 if (ConditionPassed(opcode)) {
4785 uint32_t registers = 0;
4787 const uint32_t addr_byte_size = GetAddressByteSize();
4789 // EncodingSpecificOperations();
4792 // n = UInt(Rn); registers = register_list; wback = (W == '1');
4793 n = Bits32(opcode, 19, 16);
4794 registers = Bits32(opcode, 15, 0);
4795 wback = BitIsSet(opcode, 21);
4797 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
4798 if ((n == 15) || (BitCount(registers) < 1))
4805 // address = R[n] - 4*BitCount(registers) + 4;
4807 addr_t Rn = ReadCoreReg(n, &success);
4811 addr_t address = Rn - (addr_byte_size * BitCount(registers)) + 4;
4813 EmulateInstruction::Context context;
4814 context.type = EmulateInstruction::eContextRegisterStore;
4815 RegisterInfo base_reg;
4816 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n, base_reg);
4819 uint32_t lowest_bit_set = 14;
4820 for (uint32_t i = 0; i < 14; ++i) {
4821 // if registers<i> == '1' then
4822 if (BitIsSet(registers, i)) {
4823 if (i < lowest_bit_set)
4825 // if i == n && wback && i != LowestSetBit(registers) then
4826 if ((i == n) && wback && (i != lowest_bit_set))
4827 // MemA[address,4] = bits(32) UNKNOWN;
4828 WriteBits32UnknownToMemory(address + offset);
4830 // MemA[address,4] = R[i];
4831 uint32_t data = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + i,
4836 RegisterInfo data_reg;
4837 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + i, data_reg);
4838 context.SetRegisterToRegisterPlusOffset(data_reg, base_reg,
4839 Rn - (address + offset));
4840 if (!MemAWrite(context, address + offset, data, addr_byte_size))
4844 // address = address + 4;
4845 offset += addr_byte_size;
4849 // if registers<15> == '1' then
4850 // MemA[address,4] = PCStoreValue();
4851 if (BitIsSet(registers, 15)) {
4852 RegisterInfo pc_reg;
4853 GetRegisterInfo(eRegisterKindDWARF, dwarf_pc, pc_reg);
4854 context.SetRegisterPlusOffset(pc_reg, 8);
4855 const uint32_t pc = ReadCoreReg(PC_REG, &success);
4859 if (!MemAWrite(context, address + offset, pc, addr_byte_size))
4863 // if wback then R[n] = R[n] - 4*BitCount(registers);
4865 offset = (addr_byte_size * BitCount(registers)) * -1;
4866 context.type = EmulateInstruction::eContextAdjustBaseRegister;
4867 context.SetImmediateSigned(offset);
4868 addr_t data = Rn + offset;
4869 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n,
4877 // STMDB (Store Multiple Decrement Before) stores multiple registers to
4878 // consecutive memory locations using an address from a base register. The
4879 // consecutive memory locations end just below this address, and the address of
4880 // the first of those locations can optionally be written back to the base
4882 bool EmulateInstructionARM::EmulateSTMDB(const uint32_t opcode,
4883 const ARMEncoding encoding) {
4885 if ConditionPassed() then
4886 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
4887 address = R[n] - 4*BitCount(registers);
4890 if registers<i> == '1' then
4891 if i == n && wback && i != LowestSetBit(registers) then
4892 MemA[address,4] = bits(32) UNKNOWN; // Only possible for encoding A1
4894 MemA[address,4] = R[i];
4895 address = address + 4;
4897 if registers<15> == '1' then // Only possible for encoding A1
4898 MemA[address,4] = PCStoreValue();
4900 if wback then R[n] = R[n] - 4*BitCount(registers);
4903 bool success = false;
4905 if (ConditionPassed(opcode)) {
4907 uint32_t registers = 0;
4909 const uint32_t addr_byte_size = GetAddressByteSize();
4911 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
4914 // if W == '1' && Rn == '1101' then SEE PUSH;
4915 if ((BitIsSet(opcode, 21)) && (Bits32(opcode, 19, 16) == 13)) {
4918 // n = UInt(Rn); registers = '0':M:'0':register_list; wback = (W == '1');
4919 n = Bits32(opcode, 19, 16);
4920 registers = Bits32(opcode, 15, 0);
4921 registers = registers & 0x5fff; // Make sure bits 15 & 13 are zeros.
4922 wback = BitIsSet(opcode, 21);
4923 // if n == 15 || BitCount(registers) < 2 then UNPREDICTABLE;
4924 if ((n == 15) || BitCount(registers) < 2)
4926 // if wback && registers<n> == '1' then UNPREDICTABLE;
4927 if (wback && BitIsSet(registers, n))
4932 // if W == '1' && Rn == '1101' && BitCount(register_list) >= 2 then SEE
4934 if (BitIsSet(opcode, 21) && (Bits32(opcode, 19, 16) == 13) &&
4935 BitCount(Bits32(opcode, 15, 0)) >= 2) {
4938 // n = UInt(Rn); registers = register_list; wback = (W == '1');
4939 n = Bits32(opcode, 19, 16);
4940 registers = Bits32(opcode, 15, 0);
4941 wback = BitIsSet(opcode, 21);
4942 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
4943 if ((n == 15) || BitCount(registers) < 1)
4951 // address = R[n] - 4*BitCount(registers);
4955 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
4959 addr_t address = Rn - (addr_byte_size * BitCount(registers));
4961 EmulateInstruction::Context context;
4962 context.type = EmulateInstruction::eContextRegisterStore;
4963 RegisterInfo base_reg;
4964 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n, base_reg);
4967 uint32_t lowest_set_bit = 14;
4968 for (uint32_t i = 0; i < 14; ++i) {
4969 // if registers<i> == '1' then
4970 if (BitIsSet(registers, i)) {
4971 if (i < lowest_set_bit)
4973 // if i == n && wback && i != LowestSetBit(registers) then
4974 if ((i == n) && wback && (i != lowest_set_bit))
4975 // MemA[address,4] = bits(32) UNKNOWN; // Only possible for encoding
4977 WriteBits32UnknownToMemory(address + offset);
4979 // MemA[address,4] = R[i];
4980 uint32_t data = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + i,
4985 RegisterInfo data_reg;
4986 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + i, data_reg);
4987 context.SetRegisterToRegisterPlusOffset(data_reg, base_reg,
4988 Rn - (address + offset));
4989 if (!MemAWrite(context, address + offset, data, addr_byte_size))
4993 // address = address + 4;
4994 offset += addr_byte_size;
4998 // if registers<15> == '1' then // Only possible for encoding A1
4999 // MemA[address,4] = PCStoreValue();
5000 if (BitIsSet(registers, 15)) {
5001 RegisterInfo pc_reg;
5002 GetRegisterInfo(eRegisterKindDWARF, dwarf_pc, pc_reg);
5003 context.SetRegisterPlusOffset(pc_reg, 8);
5004 const uint32_t pc = ReadCoreReg(PC_REG, &success);
5008 if (!MemAWrite(context, address + offset, pc, addr_byte_size))
5012 // if wback then R[n] = R[n] - 4*BitCount(registers);
5014 offset = (addr_byte_size * BitCount(registers)) * -1;
5015 context.type = EmulateInstruction::eContextAdjustBaseRegister;
5016 context.SetImmediateSigned(offset);
5017 addr_t data = Rn + offset;
5018 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n,
5026 // STMIB (Store Multiple Increment Before) stores multiple registers to
5027 // consecutive memory locations using an address from a base register. The
5028 // consecutive memory locations start just above this address, and the address
5029 // of the last of those locations can optionally be written back to the base
5031 bool EmulateInstructionARM::EmulateSTMIB(const uint32_t opcode,
5032 const ARMEncoding encoding) {
5034 if ConditionPassed() then
5035 EncodingSpecificOperations();
5039 if registers<i> == '1' then
5040 if i == n && wback && i != LowestSetBit(registers) then
5041 MemA[address,4] = bits(32) UNKNOWN;
5043 MemA[address,4] = R[i];
5044 address = address + 4;
5046 if registers<15> == '1' then
5047 MemA[address,4] = PCStoreValue();
5049 if wback then R[n] = R[n] + 4*BitCount(registers);
5052 bool success = false;
5054 if (ConditionPassed(opcode)) {
5056 uint32_t registers = 0;
5058 const uint32_t addr_byte_size = GetAddressByteSize();
5060 // EncodingSpecificOperations();
5063 // n = UInt(Rn); registers = register_list; wback = (W == '1');
5064 n = Bits32(opcode, 19, 16);
5065 registers = Bits32(opcode, 15, 0);
5066 wback = BitIsSet(opcode, 21);
5068 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
5069 if ((n == 15) && (BitCount(registers) < 1))
5075 // address = R[n] + 4;
5078 addr_t Rn = ReadCoreReg(n, &success);
5082 addr_t address = Rn + addr_byte_size;
5084 EmulateInstruction::Context context;
5085 context.type = EmulateInstruction::eContextRegisterStore;
5086 RegisterInfo base_reg;
5087 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n, base_reg);
5089 uint32_t lowest_set_bit = 14;
5091 for (uint32_t i = 0; i < 14; ++i) {
5092 // if registers<i> == '1' then
5093 if (BitIsSet(registers, i)) {
5094 if (i < lowest_set_bit)
5096 // if i == n && wback && i != LowestSetBit(registers) then
5097 if ((i == n) && wback && (i != lowest_set_bit))
5098 // MemA[address,4] = bits(32) UNKNOWN;
5099 WriteBits32UnknownToMemory(address + offset);
5102 // MemA[address,4] = R[i];
5103 uint32_t data = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + i,
5108 RegisterInfo data_reg;
5109 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + i, data_reg);
5110 context.SetRegisterToRegisterPlusOffset(data_reg, base_reg,
5111 offset + addr_byte_size);
5112 if (!MemAWrite(context, address + offset, data, addr_byte_size))
5116 // address = address + 4;
5117 offset += addr_byte_size;
5121 // if registers<15> == '1' then
5122 // MemA[address,4] = PCStoreValue();
5123 if (BitIsSet(registers, 15)) {
5124 RegisterInfo pc_reg;
5125 GetRegisterInfo(eRegisterKindDWARF, dwarf_pc, pc_reg);
5126 context.SetRegisterPlusOffset(pc_reg, 8);
5127 const uint32_t pc = ReadCoreReg(PC_REG, &success);
5131 if (!MemAWrite(context, address + offset, pc, addr_byte_size))
5135 // if wback then R[n] = R[n] + 4*BitCount(registers);
5137 offset = addr_byte_size * BitCount(registers);
5138 context.type = EmulateInstruction::eContextAdjustBaseRegister;
5139 context.SetImmediateSigned(offset);
5140 addr_t data = Rn + offset;
5141 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n,
5149 // STR (store immediate) calculates an address from a base register value and an
5150 // immediate offset, and stores a word
5151 // from a register to memory. It can use offset, post-indexed, or pre-indexed
5153 bool EmulateInstructionARM::EmulateSTRThumb(const uint32_t opcode,
5154 const ARMEncoding encoding) {
5156 if ConditionPassed() then
5157 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
5158 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
5159 address = if index then offset_addr else R[n];
5160 if UnalignedSupport() || address<1:0> == '00' then
5161 MemU[address,4] = R[t];
5162 else // Can only occur before ARMv7
5163 MemU[address,4] = bits(32) UNKNOWN;
5164 if wback then R[n] = offset_addr;
5167 bool success = false;
5169 if (ConditionPassed(opcode)) {
5170 const uint32_t addr_byte_size = GetAddressByteSize();
5178 // EncodingSpecificOperations (); NullCheckIfThumbEE(n);
5181 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm5:'00', 32);
5182 t = Bits32(opcode, 2, 0);
5183 n = Bits32(opcode, 5, 3);
5184 imm32 = Bits32(opcode, 10, 6) << 2;
5186 // index = TRUE; add = TRUE; wback = FALSE;
5193 // t = UInt(Rt); n = 13; imm32 = ZeroExtend(imm8:'00', 32);
5194 t = Bits32(opcode, 10, 8);
5196 imm32 = Bits32(opcode, 7, 0) << 2;
5198 // index = TRUE; add = TRUE; wback = FALSE;
5205 // if Rn == '1111' then UNDEFINED;
5206 if (Bits32(opcode, 19, 16) == 15)
5209 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
5210 t = Bits32(opcode, 15, 12);
5211 n = Bits32(opcode, 19, 16);
5212 imm32 = Bits32(opcode, 11, 0);
5214 // index = TRUE; add = TRUE; wback = FALSE;
5219 // if t == 15 then UNPREDICTABLE;
5225 // if P == '1' && U == '1' && W == '0' then SEE STRT;
5226 // if Rn == '1101' && P == '1' && U == '0' && W == '1' && imm8 ==
5227 // '00000100' then SEE PUSH;
5228 // if Rn == '1111' || (P == '0' && W == '0') then UNDEFINED;
5229 if ((Bits32(opcode, 19, 16) == 15) ||
5230 (BitIsClear(opcode, 10) && BitIsClear(opcode, 8)))
5233 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32);
5234 t = Bits32(opcode, 15, 12);
5235 n = Bits32(opcode, 19, 16);
5236 imm32 = Bits32(opcode, 7, 0);
5238 // index = (P == '1'); add = (U == '1'); wback = (W == '1');
5239 index = BitIsSet(opcode, 10);
5240 add = BitIsSet(opcode, 9);
5241 wback = BitIsSet(opcode, 8);
5243 // if t == 15 || (wback && n == t) then UNPREDICTABLE;
5244 if ((t == 15) || (wback && (n == t)))
5255 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
5256 uint32_t base_address = ReadCoreReg(n, &success);
5261 offset_addr = base_address + imm32;
5263 offset_addr = base_address - imm32;
5265 // address = if index then offset_addr else R[n];
5267 address = offset_addr;
5269 address = base_address;
5271 EmulateInstruction::Context context;
5273 context.type = eContextPushRegisterOnStack;
5275 context.type = eContextRegisterStore;
5277 RegisterInfo base_reg;
5278 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n, base_reg);
5280 // if UnalignedSupport() || address<1:0> == '00' then
5281 if (UnalignedSupport() ||
5282 (BitIsClear(address, 1) && BitIsClear(address, 0))) {
5283 // MemU[address,4] = R[t];
5285 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + t, 0, &success);
5289 RegisterInfo data_reg;
5290 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + t, data_reg);
5291 int32_t offset = address - base_address;
5292 context.SetRegisterToRegisterPlusOffset(data_reg, base_reg, offset);
5293 if (!MemUWrite(context, address, data, addr_byte_size))
5296 // MemU[address,4] = bits(32) UNKNOWN;
5297 WriteBits32UnknownToMemory(address);
5300 // if wback then R[n] = offset_addr;
5303 context.type = eContextAdjustStackPointer;
5305 context.type = eContextAdjustBaseRegister;
5306 context.SetAddress(offset_addr);
5308 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n,
5316 // STR (Store Register) calculates an address from a base register value and an
5317 // offset register value, stores a
5318 // word from a register to memory. The offset register value can optionally
5320 bool EmulateInstructionARM::EmulateSTRRegister(const uint32_t opcode,
5321 const ARMEncoding encoding) {
5323 if ConditionPassed() then
5324 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
5325 offset = Shift(R[m], shift_t, shift_n, APSR.C);
5326 offset_addr = if add then (R[n] + offset) else (R[n] - offset);
5327 address = if index then offset_addr else R[n];
5328 if t == 15 then // Only possible for encoding A1
5329 data = PCStoreValue();
5332 if UnalignedSupport() || address<1:0> == '00' || CurrentInstrSet() == InstrSet_ARM then
5333 MemU[address,4] = data;
5334 else // Can only occur before ARMv7
5335 MemU[address,4] = bits(32) UNKNOWN;
5336 if wback then R[n] = offset_addr;
5339 bool success = false;
5341 if (ConditionPassed(opcode)) {
5342 const uint32_t addr_byte_size = GetAddressByteSize();
5347 ARM_ShifterType shift_t;
5353 // EncodingSpecificOperations (); NullCheckIfThumbEE(n);
5356 // if CurrentInstrSet() == InstrSet_ThumbEE then SEE "Modified operation
5358 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
5359 t = Bits32(opcode, 2, 0);
5360 n = Bits32(opcode, 5, 3);
5361 m = Bits32(opcode, 8, 6);
5363 // index = TRUE; add = TRUE; wback = FALSE;
5368 // (shift_t, shift_n) = (SRType_LSL, 0);
5369 shift_t = SRType_LSL;
5374 // if Rn == '1111' then UNDEFINED;
5375 if (Bits32(opcode, 19, 16) == 15)
5378 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
5379 t = Bits32(opcode, 15, 12);
5380 n = Bits32(opcode, 19, 16);
5381 m = Bits32(opcode, 3, 0);
5383 // index = TRUE; add = TRUE; wback = FALSE;
5388 // (shift_t, shift_n) = (SRType_LSL, UInt(imm2));
5389 shift_t = SRType_LSL;
5390 shift_n = Bits32(opcode, 5, 4);
5392 // if t == 15 || BadReg(m) then UNPREDICTABLE;
5393 if ((t == 15) || (BadReg(m)))
5398 // if P == '0' && W == '1' then SEE STRT;
5399 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
5400 t = Bits32(opcode, 15, 12);
5401 n = Bits32(opcode, 19, 16);
5402 m = Bits32(opcode, 3, 0);
5404 // index = (P == '1'); add = (U == '1'); wback = (P == '0') ||
5406 index = BitIsSet(opcode, 24);
5407 add = BitIsSet(opcode, 23);
5408 wback = (BitIsClear(opcode, 24) || BitIsSet(opcode, 21));
5410 // (shift_t, shift_n) = DecodeImmShift(type, imm5);
5411 uint32_t typ = Bits32(opcode, 6, 5);
5412 uint32_t imm5 = Bits32(opcode, 11, 7);
5413 shift_n = DecodeImmShift(typ, imm5, shift_t);
5415 // if m == 15 then UNPREDICTABLE;
5419 // if wback && (n == 15 || n == t) then UNPREDICTABLE;
5420 if (wback && ((n == 15) || (n == t)))
5433 addr_t base_address =
5434 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
5439 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
5443 // offset = Shift(R[m], shift_t, shift_n, APSR.C);
5444 offset = Shift(Rm_data, shift_t, shift_n, APSR_C, &success);
5448 // offset_addr = if add then (R[n] + offset) else (R[n] - offset);
5450 offset_addr = base_address + offset;
5452 offset_addr = base_address - offset;
5454 // address = if index then offset_addr else R[n];
5456 address = offset_addr;
5458 address = base_address;
5461 // if t == 15 then // Only possible for encoding A1
5463 // data = PCStoreValue();
5464 data = ReadCoreReg(PC_REG, &success);
5468 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + t, 0, &success);
5473 EmulateInstruction::Context context;
5474 context.type = eContextRegisterStore;
5476 // if UnalignedSupport() || address<1:0> == '00' || CurrentInstrSet() ==
5477 // InstrSet_ARM then
5478 if (UnalignedSupport() ||
5479 (BitIsClear(address, 1) && BitIsClear(address, 0)) ||
5480 CurrentInstrSet() == eModeARM) {
5481 // MemU[address,4] = data;
5483 RegisterInfo base_reg;
5484 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n, base_reg);
5486 RegisterInfo data_reg;
5487 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + t, data_reg);
5489 context.SetRegisterToRegisterPlusOffset(data_reg, base_reg,
5490 address - base_address);
5491 if (!MemUWrite(context, address, data, addr_byte_size))
5495 // MemU[address,4] = bits(32) UNKNOWN;
5496 WriteBits32UnknownToMemory(address);
5498 // if wback then R[n] = offset_addr;
5500 context.type = eContextRegisterLoad;
5501 context.SetAddress(offset_addr);
5502 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n,
5510 bool EmulateInstructionARM::EmulateSTRBThumb(const uint32_t opcode,
5511 const ARMEncoding encoding) {
5513 if ConditionPassed() then
5514 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
5515 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
5516 address = if index then offset_addr else R[n];
5517 MemU[address,1] = R[t]<7:0>;
5518 if wback then R[n] = offset_addr;
5521 bool success = false;
5523 if (ConditionPassed(opcode)) {
5530 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
5533 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm5, 32);
5534 t = Bits32(opcode, 2, 0);
5535 n = Bits32(opcode, 5, 3);
5536 imm32 = Bits32(opcode, 10, 6);
5538 // index = TRUE; add = TRUE; wback = FALSE;
5545 // if Rn == '1111' then UNDEFINED;
5546 if (Bits32(opcode, 19, 16) == 15)
5549 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
5550 t = Bits32(opcode, 15, 12);
5551 n = Bits32(opcode, 19, 16);
5552 imm32 = Bits32(opcode, 11, 0);
5554 // index = TRUE; add = TRUE; wback = FALSE;
5559 // if BadReg(t) then UNPREDICTABLE;
5565 // if P == '1' && U == '1' && W == '0' then SEE STRBT;
5566 // if Rn == '1111' || (P == '0' && W == '0') then UNDEFINED;
5567 if (Bits32(opcode, 19, 16) == 15)
5570 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32);
5571 t = Bits32(opcode, 15, 12);
5572 n = Bits32(opcode, 19, 16);
5573 imm32 = Bits32(opcode, 7, 0);
5575 // index = (P == '1'); add = (U == '1'); wback = (W == '1');
5576 index = BitIsSet(opcode, 10);
5577 add = BitIsSet(opcode, 9);
5578 wback = BitIsSet(opcode, 8);
5580 // if BadReg(t) || (wback && n == t) then UNPREDICTABLE
5581 if ((BadReg(t)) || (wback && (n == t)))
5591 addr_t base_address =
5592 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
5596 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
5598 offset_addr = base_address + imm32;
5600 offset_addr = base_address - imm32;
5602 // address = if index then offset_addr else R[n];
5604 address = offset_addr;
5606 address = base_address;
5608 // MemU[address,1] = R[t]<7:0>
5609 RegisterInfo base_reg;
5610 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n, base_reg);
5612 RegisterInfo data_reg;
5613 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + t, data_reg);
5615 EmulateInstruction::Context context;
5616 context.type = eContextRegisterStore;
5617 context.SetRegisterToRegisterPlusOffset(data_reg, base_reg,
5618 address - base_address);
5621 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + t, 0, &success);
5625 data = Bits32(data, 7, 0);
5627 if (!MemUWrite(context, address, data, 1))
5630 // if wback then R[n] = offset_addr;
5632 context.type = eContextRegisterLoad;
5633 context.SetAddress(offset_addr);
5634 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n,
5643 // STRH (register) calculates an address from a base register value and an
5644 // offset register value, and stores a
5645 // halfword from a register to memory. The offset register value can be
5646 // shifted left by 0, 1, 2, or 3 bits.
5647 bool EmulateInstructionARM::EmulateSTRHRegister(const uint32_t opcode,
5648 const ARMEncoding encoding) {
5650 if ConditionPassed() then
5651 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
5652 offset = Shift(R[m], shift_t, shift_n, APSR.C);
5653 offset_addr = if add then (R[n] + offset) else (R[n] - offset);
5654 address = if index then offset_addr else R[n];
5655 if UnalignedSupport() || address<0> == '0' then
5656 MemU[address,2] = R[t]<15:0>;
5657 else // Can only occur before ARMv7
5658 MemU[address,2] = bits(16) UNKNOWN;
5659 if wback then R[n] = offset_addr;
5662 bool success = false;
5664 if (ConditionPassed(opcode)) {
5671 ARM_ShifterType shift_t;
5674 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
5677 // if CurrentInstrSet() == InstrSet_ThumbEE then SEE "Modified operation
5679 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
5680 t = Bits32(opcode, 2, 0);
5681 n = Bits32(opcode, 5, 3);
5682 m = Bits32(opcode, 8, 6);
5684 // index = TRUE; add = TRUE; wback = FALSE;
5689 // (shift_t, shift_n) = (SRType_LSL, 0);
5690 shift_t = SRType_LSL;
5696 // if Rn == '1111' then UNDEFINED;
5697 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
5698 t = Bits32(opcode, 15, 12);
5699 n = Bits32(opcode, 19, 16);
5700 m = Bits32(opcode, 3, 0);
5704 // index = TRUE; add = TRUE; wback = FALSE;
5709 // (shift_t, shift_n) = (SRType_LSL, UInt(imm2));
5710 shift_t = SRType_LSL;
5711 shift_n = Bits32(opcode, 5, 4);
5713 // if BadReg(t) || BadReg(m) then UNPREDICTABLE;
5714 if (BadReg(t) || BadReg(m))
5720 // if P == '0' && W == '1' then SEE STRHT;
5721 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
5722 t = Bits32(opcode, 15, 12);
5723 n = Bits32(opcode, 19, 16);
5724 m = Bits32(opcode, 3, 0);
5726 // index = (P == '1'); add = (U == '1'); wback = (P == '0') ||
5728 index = BitIsSet(opcode, 24);
5729 add = BitIsSet(opcode, 23);
5730 wback = (BitIsClear(opcode, 24) || BitIsSet(opcode, 21));
5732 // (shift_t, shift_n) = (SRType_LSL, 0);
5733 shift_t = SRType_LSL;
5736 // if t == 15 || m == 15 then UNPREDICTABLE;
5737 if ((t == 15) || (m == 15))
5740 // if wback && (n == 15 || n == t) then UNPREDICTABLE;
5741 if (wback && ((n == 15) || (n == t)))
5750 uint32_t Rm = ReadCoreReg(m, &success);
5754 uint32_t Rn = ReadCoreReg(n, &success);
5758 // offset = Shift(R[m], shift_t, shift_n, APSR.C);
5759 uint32_t offset = Shift(Rm, shift_t, shift_n, APSR_C, &success);
5763 // offset_addr = if add then (R[n] + offset) else (R[n] - offset);
5766 offset_addr = Rn + offset;
5768 offset_addr = Rn - offset;
5770 // address = if index then offset_addr else R[n];
5773 address = offset_addr;
5777 EmulateInstruction::Context context;
5778 context.type = eContextRegisterStore;
5779 RegisterInfo base_reg;
5780 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n, base_reg);
5781 RegisterInfo offset_reg;
5782 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + m, offset_reg);
5784 // if UnalignedSupport() || address<0> == '0' then
5785 if (UnalignedSupport() || BitIsClear(address, 0)) {
5786 // MemU[address,2] = R[t]<15:0>;
5787 uint32_t Rt = ReadCoreReg(t, &success);
5791 EmulateInstruction::Context context;
5792 context.type = eContextRegisterStore;
5793 RegisterInfo base_reg;
5794 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n, base_reg);
5795 RegisterInfo offset_reg;
5796 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + m, offset_reg);
5797 RegisterInfo data_reg;
5798 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + t, data_reg);
5799 context.SetRegisterToRegisterPlusIndirectOffset(base_reg, offset_reg,
5802 if (!MemUWrite(context, address, Bits32(Rt, 15, 0), 2))
5804 } else // Can only occur before ARMv7
5806 // MemU[address,2] = bits(16) UNKNOWN;
5809 // if wback then R[n] = offset_addr;
5811 context.type = eContextAdjustBaseRegister;
5812 context.SetAddress(offset_addr);
5813 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n,
5822 // Add with Carry (immediate) adds an immediate value and the carry flag value
5823 // to a register value, and writes the result to the destination register. It
5824 // can optionally update the condition flags based on the result.
5825 bool EmulateInstructionARM::EmulateADCImm(const uint32_t opcode,
5826 const ARMEncoding encoding) {
5828 // ARM pseudo code...
5829 if ConditionPassed() then
5830 EncodingSpecificOperations();
5831 (result, carry, overflow) = AddWithCarry(R[n], imm32, APSR.C);
5832 if d == 15 then // Can only occur for ARM encoding
5833 ALUWritePC(result); // setflags is always FALSE here
5837 APSR.N = result<31>;
5838 APSR.Z = IsZeroBit(result);
5843 bool success = false;
5845 if (ConditionPassed(opcode)) {
5848 imm32; // the immediate value to be added to the value obtained from Rn
5852 Rd = Bits32(opcode, 11, 8);
5853 Rn = Bits32(opcode, 19, 16);
5854 setflags = BitIsSet(opcode, 20);
5855 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8)
5856 if (BadReg(Rd) || BadReg(Rn))
5860 Rd = Bits32(opcode, 15, 12);
5861 Rn = Bits32(opcode, 19, 16);
5862 setflags = BitIsSet(opcode, 20);
5863 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
5865 if (Rd == 15 && setflags)
5866 return EmulateSUBSPcLrEtc(opcode, encoding);
5872 // Read the first operand.
5873 int32_t val1 = ReadCoreReg(Rn, &success);
5877 AddWithCarryResult res = AddWithCarry(val1, imm32, APSR_C);
5879 EmulateInstruction::Context context;
5880 context.type = EmulateInstruction::eContextImmediate;
5881 context.SetNoArgs();
5883 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags,
5884 res.carry_out, res.overflow))
5890 // Add with Carry (register) adds a register value, the carry flag value, and
5891 // an optionally-shifted register value, and writes the result to the
5892 // destination register. It can optionally update the condition flags based on
5894 bool EmulateInstructionARM::EmulateADCReg(const uint32_t opcode,
5895 const ARMEncoding encoding) {
5897 // ARM pseudo code...
5898 if ConditionPassed() then
5899 EncodingSpecificOperations();
5900 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
5901 (result, carry, overflow) = AddWithCarry(R[n], shifted, APSR.C);
5902 if d == 15 then // Can only occur for ARM encoding
5903 ALUWritePC(result); // setflags is always FALSE here
5907 APSR.N = result<31>;
5908 APSR.Z = IsZeroBit(result);
5913 bool success = false;
5915 if (ConditionPassed(opcode)) {
5916 uint32_t Rd, Rn, Rm;
5917 ARM_ShifterType shift_t;
5918 uint32_t shift_n; // the shift applied to the value read from Rm
5922 Rd = Rn = Bits32(opcode, 2, 0);
5923 Rm = Bits32(opcode, 5, 3);
5924 setflags = !InITBlock();
5925 shift_t = SRType_LSL;
5929 Rd = Bits32(opcode, 11, 8);
5930 Rn = Bits32(opcode, 19, 16);
5931 Rm = Bits32(opcode, 3, 0);
5932 setflags = BitIsSet(opcode, 20);
5933 shift_n = DecodeImmShiftThumb(opcode, shift_t);
5934 if (BadReg(Rd) || BadReg(Rn) || BadReg(Rm))
5938 Rd = Bits32(opcode, 15, 12);
5939 Rn = Bits32(opcode, 19, 16);
5940 Rm = Bits32(opcode, 3, 0);
5941 setflags = BitIsSet(opcode, 20);
5942 shift_n = DecodeImmShiftARM(opcode, shift_t);
5944 if (Rd == 15 && setflags)
5945 return EmulateSUBSPcLrEtc(opcode, encoding);
5951 // Read the first operand.
5952 int32_t val1 = ReadCoreReg(Rn, &success);
5956 // Read the second operand.
5957 int32_t val2 = ReadCoreReg(Rm, &success);
5961 uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C, &success);
5964 AddWithCarryResult res = AddWithCarry(val1, shifted, APSR_C);
5966 EmulateInstruction::Context context;
5967 context.type = EmulateInstruction::eContextImmediate;
5968 context.SetNoArgs();
5970 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags,
5971 res.carry_out, res.overflow))
5977 // This instruction adds an immediate value to the PC value to form a PC-
5978 // relative address, and writes the result to the destination register.
5979 bool EmulateInstructionARM::EmulateADR(const uint32_t opcode,
5980 const ARMEncoding encoding) {
5982 // ARM pseudo code...
5983 if ConditionPassed() then
5984 EncodingSpecificOperations();
5985 result = if add then (Align(PC,4) + imm32) else (Align(PC,4) - imm32);
5986 if d == 15 then // Can only occur for ARM encodings
5992 bool success = false;
5994 if (ConditionPassed(opcode)) {
5996 uint32_t imm32; // the immediate value to be added/subtracted to/from the PC
6000 Rd = Bits32(opcode, 10, 8);
6001 imm32 = ThumbImm8Scaled(opcode); // imm32 = ZeroExtend(imm8:'00', 32)
6006 Rd = Bits32(opcode, 11, 8);
6007 imm32 = ThumbImm12(opcode); // imm32 = ZeroExtend(i:imm3:imm8, 32)
6008 add = (Bits32(opcode, 24, 21) == 0); // 0b0000 => ADD; 0b0101 => SUB
6014 Rd = Bits32(opcode, 15, 12);
6015 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
6016 add = (Bits32(opcode, 24, 21) == 0x4); // 0b0100 => ADD; 0b0010 => SUB
6022 // Read the PC value.
6023 uint32_t pc = ReadCoreReg(PC_REG, &success);
6027 uint32_t result = (add ? Align(pc, 4) + imm32 : Align(pc, 4) - imm32);
6029 EmulateInstruction::Context context;
6030 context.type = EmulateInstruction::eContextImmediate;
6031 context.SetNoArgs();
6033 if (!WriteCoreReg(context, result, Rd))
6039 // This instruction performs a bitwise AND of a register value and an immediate
6040 // value, and writes the result to the destination register. It can optionally
6041 // update the condition flags based on the result.
6042 bool EmulateInstructionARM::EmulateANDImm(const uint32_t opcode,
6043 const ARMEncoding encoding) {
6045 // ARM pseudo code...
6046 if ConditionPassed() then
6047 EncodingSpecificOperations();
6048 result = R[n] AND imm32;
6049 if d == 15 then // Can only occur for ARM encoding
6050 ALUWritePC(result); // setflags is always FALSE here
6054 APSR.N = result<31>;
6055 APSR.Z = IsZeroBit(result);
6060 bool success = false;
6062 if (ConditionPassed(opcode)) {
6065 imm32; // the immediate value to be ANDed to the value obtained from Rn
6067 uint32_t carry; // the carry bit after ARM/Thumb Expand operation
6070 Rd = Bits32(opcode, 11, 8);
6071 Rn = Bits32(opcode, 19, 16);
6072 setflags = BitIsSet(opcode, 20);
6073 imm32 = ThumbExpandImm_C(
6075 carry); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C)
6076 // if Rd == '1111' && S == '1' then SEE TST (immediate);
6077 if (Rd == 15 && setflags)
6078 return EmulateTSTImm(opcode, eEncodingT1);
6079 if (Rd == 13 || (Rd == 15 && !setflags) || BadReg(Rn))
6083 Rd = Bits32(opcode, 15, 12);
6084 Rn = Bits32(opcode, 19, 16);
6085 setflags = BitIsSet(opcode, 20);
6087 ARMExpandImm_C(opcode, APSR_C,
6088 carry); // (imm32, carry) = ARMExpandImm(imm12, APSR.C)
6090 if (Rd == 15 && setflags)
6091 return EmulateSUBSPcLrEtc(opcode, encoding);
6097 // Read the first operand.
6098 uint32_t val1 = ReadCoreReg(Rn, &success);
6102 uint32_t result = val1 & imm32;
6104 EmulateInstruction::Context context;
6105 context.type = EmulateInstruction::eContextImmediate;
6106 context.SetNoArgs();
6108 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
6114 // This instruction performs a bitwise AND of a register value and an
6115 // optionally-shifted register value, and writes the result to the destination
6116 // register. It can optionally update the condition flags based on the result.
6117 bool EmulateInstructionARM::EmulateANDReg(const uint32_t opcode,
6118 const ARMEncoding encoding) {
6120 // ARM pseudo code...
6121 if ConditionPassed() then
6122 EncodingSpecificOperations();
6123 (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C);
6124 result = R[n] AND shifted;
6125 if d == 15 then // Can only occur for ARM encoding
6126 ALUWritePC(result); // setflags is always FALSE here
6130 APSR.N = result<31>;
6131 APSR.Z = IsZeroBit(result);
6136 bool success = false;
6138 if (ConditionPassed(opcode)) {
6139 uint32_t Rd, Rn, Rm;
6140 ARM_ShifterType shift_t;
6141 uint32_t shift_n; // the shift applied to the value read from Rm
6146 Rd = Rn = Bits32(opcode, 2, 0);
6147 Rm = Bits32(opcode, 5, 3);
6148 setflags = !InITBlock();
6149 shift_t = SRType_LSL;
6153 Rd = Bits32(opcode, 11, 8);
6154 Rn = Bits32(opcode, 19, 16);
6155 Rm = Bits32(opcode, 3, 0);
6156 setflags = BitIsSet(opcode, 20);
6157 shift_n = DecodeImmShiftThumb(opcode, shift_t);
6158 // if Rd == '1111' && S == '1' then SEE TST (register);
6159 if (Rd == 15 && setflags)
6160 return EmulateTSTReg(opcode, eEncodingT2);
6161 if (Rd == 13 || (Rd == 15 && !setflags) || BadReg(Rn) || BadReg(Rm))
6165 Rd = Bits32(opcode, 15, 12);
6166 Rn = Bits32(opcode, 19, 16);
6167 Rm = Bits32(opcode, 3, 0);
6168 setflags = BitIsSet(opcode, 20);
6169 shift_n = DecodeImmShiftARM(opcode, shift_t);
6171 if (Rd == 15 && setflags)
6172 return EmulateSUBSPcLrEtc(opcode, encoding);
6178 // Read the first operand.
6179 uint32_t val1 = ReadCoreReg(Rn, &success);
6183 // Read the second operand.
6184 uint32_t val2 = ReadCoreReg(Rm, &success);
6188 uint32_t shifted = Shift_C(val2, shift_t, shift_n, APSR_C, carry, &success);
6191 uint32_t result = val1 & shifted;
6193 EmulateInstruction::Context context;
6194 context.type = EmulateInstruction::eContextImmediate;
6195 context.SetNoArgs();
6197 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
6203 // Bitwise Bit Clear (immediate) performs a bitwise AND of a register value and
6204 // the complement of an immediate value, and writes the result to the
6205 // destination register. It can optionally update the condition flags based on
6207 bool EmulateInstructionARM::EmulateBICImm(const uint32_t opcode,
6208 const ARMEncoding encoding) {
6210 // ARM pseudo code...
6211 if ConditionPassed() then
6212 EncodingSpecificOperations();
6213 result = R[n] AND NOT(imm32);
6214 if d == 15 then // Can only occur for ARM encoding
6215 ALUWritePC(result); // setflags is always FALSE here
6219 APSR.N = result<31>;
6220 APSR.Z = IsZeroBit(result);
6225 bool success = false;
6227 if (ConditionPassed(opcode)) {
6229 uint32_t imm32; // the immediate value to be bitwise inverted and ANDed to
6230 // the value obtained from Rn
6232 uint32_t carry; // the carry bit after ARM/Thumb Expand operation
6235 Rd = Bits32(opcode, 11, 8);
6236 Rn = Bits32(opcode, 19, 16);
6237 setflags = BitIsSet(opcode, 20);
6238 imm32 = ThumbExpandImm_C(
6240 carry); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C)
6241 if (BadReg(Rd) || BadReg(Rn))
6245 Rd = Bits32(opcode, 15, 12);
6246 Rn = Bits32(opcode, 19, 16);
6247 setflags = BitIsSet(opcode, 20);
6249 ARMExpandImm_C(opcode, APSR_C,
6250 carry); // (imm32, carry) = ARMExpandImm(imm12, APSR.C)
6252 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related
6254 if (Rd == 15 && setflags)
6255 return EmulateSUBSPcLrEtc(opcode, encoding);
6261 // Read the first operand.
6262 uint32_t val1 = ReadCoreReg(Rn, &success);
6266 uint32_t result = val1 & ~imm32;
6268 EmulateInstruction::Context context;
6269 context.type = EmulateInstruction::eContextImmediate;
6270 context.SetNoArgs();
6272 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
6278 // Bitwise Bit Clear (register) performs a bitwise AND of a register value and
6279 // the complement of an optionally-shifted register value, and writes the
6280 // result to the destination register. It can optionally update the condition
6281 // flags based on the result.
6282 bool EmulateInstructionARM::EmulateBICReg(const uint32_t opcode,
6283 const ARMEncoding encoding) {
6285 // ARM pseudo code...
6286 if ConditionPassed() then
6287 EncodingSpecificOperations();
6288 (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C);
6289 result = R[n] AND NOT(shifted);
6290 if d == 15 then // Can only occur for ARM encoding
6291 ALUWritePC(result); // setflags is always FALSE here
6295 APSR.N = result<31>;
6296 APSR.Z = IsZeroBit(result);
6301 bool success = false;
6303 if (ConditionPassed(opcode)) {
6304 uint32_t Rd, Rn, Rm;
6305 ARM_ShifterType shift_t;
6306 uint32_t shift_n; // the shift applied to the value read from Rm
6311 Rd = Rn = Bits32(opcode, 2, 0);
6312 Rm = Bits32(opcode, 5, 3);
6313 setflags = !InITBlock();
6314 shift_t = SRType_LSL;
6318 Rd = Bits32(opcode, 11, 8);
6319 Rn = Bits32(opcode, 19, 16);
6320 Rm = Bits32(opcode, 3, 0);
6321 setflags = BitIsSet(opcode, 20);
6322 shift_n = DecodeImmShiftThumb(opcode, shift_t);
6323 if (BadReg(Rd) || BadReg(Rn) || BadReg(Rm))
6327 Rd = Bits32(opcode, 15, 12);
6328 Rn = Bits32(opcode, 19, 16);
6329 Rm = Bits32(opcode, 3, 0);
6330 setflags = BitIsSet(opcode, 20);
6331 shift_n = DecodeImmShiftARM(opcode, shift_t);
6333 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related
6335 if (Rd == 15 && setflags)
6336 return EmulateSUBSPcLrEtc(opcode, encoding);
6342 // Read the first operand.
6343 uint32_t val1 = ReadCoreReg(Rn, &success);
6347 // Read the second operand.
6348 uint32_t val2 = ReadCoreReg(Rm, &success);
6352 uint32_t shifted = Shift_C(val2, shift_t, shift_n, APSR_C, carry, &success);
6355 uint32_t result = val1 & ~shifted;
6357 EmulateInstruction::Context context;
6358 context.type = EmulateInstruction::eContextImmediate;
6359 context.SetNoArgs();
6361 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
6367 // LDR (immediate, ARM) calculates an address from a base register value and an
6368 // immediate offset, loads a word
6369 // from memory, and writes it to a register. It can use offset, post-indexed,
6370 // or pre-indexed addressing.
6371 bool EmulateInstructionARM::EmulateLDRImmediateARM(const uint32_t opcode,
6372 const ARMEncoding encoding) {
6374 if ConditionPassed() then
6375 EncodingSpecificOperations();
6376 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
6377 address = if index then offset_addr else R[n];
6378 data = MemU[address,4];
6379 if wback then R[n] = offset_addr;
6381 if address<1:0> == '00' then LoadWritePC(data); else UNPREDICTABLE;
6382 elsif UnalignedSupport() || address<1:0> = '00' then
6384 else // Can only apply before ARMv7
6385 R[t] = ROR(data, 8*UInt(address<1:0>));
6388 bool success = false;
6390 if (ConditionPassed(opcode)) {
6391 const uint32_t addr_byte_size = GetAddressByteSize();
6402 // if Rn == '1111' then SEE LDR (literal);
6403 // if P == '0' && W == '1' then SEE LDRT;
6404 // if Rn == '1101' && P == '0' && U == '1' && W == '0' && imm12 ==
6405 // '000000000100' then SEE POP;
6406 // t == UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
6407 t = Bits32(opcode, 15, 12);
6408 n = Bits32(opcode, 19, 16);
6409 imm32 = Bits32(opcode, 11, 0);
6411 // index = (P == '1'); add = (U == '1'); wback = (P == '0') ||
6413 index = BitIsSet(opcode, 24);
6414 add = BitIsSet(opcode, 23);
6415 wback = (BitIsClear(opcode, 24) || BitIsSet(opcode, 21));
6417 // if wback && n == t then UNPREDICTABLE;
6418 if (wback && (n == t))
6429 addr_t base_address = ReadCoreReg(n, &success);
6433 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
6435 offset_addr = base_address + imm32;
6437 offset_addr = base_address - imm32;
6439 // address = if index then offset_addr else R[n];
6441 address = offset_addr;
6443 address = base_address;
6445 // data = MemU[address,4];
6447 RegisterInfo base_reg;
6448 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n, base_reg);
6450 EmulateInstruction::Context context;
6451 context.type = eContextRegisterLoad;
6452 context.SetRegisterPlusOffset(base_reg, address - base_address);
6454 uint64_t data = MemURead(context, address, addr_byte_size, 0, &success);
6458 // if wback then R[n] = offset_addr;
6460 context.type = eContextAdjustBaseRegister;
6461 context.SetAddress(offset_addr);
6462 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n,
6469 // if address<1:0> == '00' then LoadWritePC(data); else UNPREDICTABLE;
6470 if (BitIsClear(address, 1) && BitIsClear(address, 0)) {
6471 // LoadWritePC (data);
6472 context.type = eContextRegisterLoad;
6473 context.SetRegisterPlusOffset(base_reg, address - base_address);
6474 LoadWritePC(context, data);
6478 // elsif UnalignedSupport() || address<1:0> = '00' then
6479 else if (UnalignedSupport() ||
6480 (BitIsClear(address, 1) && BitIsClear(address, 0))) {
6482 context.type = eContextRegisterLoad;
6483 context.SetRegisterPlusOffset(base_reg, address - base_address);
6484 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + t,
6488 // else // Can only apply before ARMv7
6490 // R[t] = ROR(data, 8*UInt(address<1:0>));
6491 data = ROR(data, Bits32(address, 1, 0), &success);
6494 context.type = eContextRegisterLoad;
6495 context.SetImmediate(data);
6496 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + t,
6504 // LDR (register) calculates an address from a base register value and an offset
6505 // register value, loads a word
6506 // from memory, and writes it to a register. The offset register value can
6507 // optionally be shifted.
6508 bool EmulateInstructionARM::EmulateLDRRegister(const uint32_t opcode,
6509 const ARMEncoding encoding) {
6511 if ConditionPassed() then
6512 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
6513 offset = Shift(R[m], shift_t, shift_n, APSR.C);
6514 offset_addr = if add then (R[n] + offset) else (R[n] - offset);
6515 address = if index then offset_addr else R[n];
6516 data = MemU[address,4];
6517 if wback then R[n] = offset_addr;
6519 if address<1:0> == '00' then LoadWritePC(data); else UNPREDICTABLE;
6520 elsif UnalignedSupport() || address<1:0> = '00' then
6522 else // Can only apply before ARMv7
6523 if CurrentInstrSet() == InstrSet_ARM then
6524 R[t] = ROR(data, 8*UInt(address<1:0>));
6526 R[t] = bits(32) UNKNOWN;
6529 bool success = false;
6531 if (ConditionPassed(opcode)) {
6532 const uint32_t addr_byte_size = GetAddressByteSize();
6540 ARM_ShifterType shift_t;
6545 // if CurrentInstrSet() == InstrSet_ThumbEE then SEE "Modified operation
6547 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
6548 t = Bits32(opcode, 2, 0);
6549 n = Bits32(opcode, 5, 3);
6550 m = Bits32(opcode, 8, 6);
6552 // index = TRUE; add = TRUE; wback = FALSE;
6557 // (shift_t, shift_n) = (SRType_LSL, 0);
6558 shift_t = SRType_LSL;
6564 // if Rn == '1111' then SEE LDR (literal);
6565 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
6566 t = Bits32(opcode, 15, 12);
6567 n = Bits32(opcode, 19, 16);
6568 m = Bits32(opcode, 3, 0);
6570 // index = TRUE; add = TRUE; wback = FALSE;
6575 // (shift_t, shift_n) = (SRType_LSL, UInt(imm2));
6576 shift_t = SRType_LSL;
6577 shift_n = Bits32(opcode, 5, 4);
6579 // if BadReg(m) then UNPREDICTABLE;
6583 // if t == 15 && InITBlock() && !LastInITBlock() then UNPREDICTABLE;
6584 if ((t == 15) && InITBlock() && !LastInITBlock())
6590 // if P == '0' && W == '1' then SEE LDRT;
6591 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
6592 t = Bits32(opcode, 15, 12);
6593 n = Bits32(opcode, 19, 16);
6594 m = Bits32(opcode, 3, 0);
6596 // index = (P == '1'); add = (U == '1'); wback = (P == '0') ||
6598 index = BitIsSet(opcode, 24);
6599 add = BitIsSet(opcode, 23);
6600 wback = (BitIsClear(opcode, 24) || BitIsSet(opcode, 21));
6602 // (shift_t, shift_n) = DecodeImmShift(type, imm5);
6603 uint32_t type = Bits32(opcode, 6, 5);
6604 uint32_t imm5 = Bits32(opcode, 11, 7);
6605 shift_n = DecodeImmShift(type, imm5, shift_t);
6607 // if m == 15 then UNPREDICTABLE;
6611 // if wback && (n == 15 || n == t) then UNPREDICTABLE;
6612 if (wback && ((n == 15) || (n == t)))
6621 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
6626 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
6633 // offset = Shift(R[m], shift_t, shift_n, APSR.C); -- Note "The APSR is
6634 // an application level alias for the CPSR".
6636 Shift(Rm, shift_t, shift_n, Bit32(m_opcode_cpsr, APSR_C), &success);
6640 // offset_addr = if add then (R[n] + offset) else (R[n] - offset);
6642 offset_addr = Rn + offset;
6644 offset_addr = Rn - offset;
6646 // address = if index then offset_addr else R[n];
6648 address = offset_addr;
6652 // data = MemU[address,4];
6653 RegisterInfo base_reg;
6654 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n, base_reg);
6656 EmulateInstruction::Context context;
6657 context.type = eContextRegisterLoad;
6658 context.SetRegisterPlusOffset(base_reg, address - Rn);
6660 uint64_t data = MemURead(context, address, addr_byte_size, 0, &success);
6664 // if wback then R[n] = offset_addr;
6666 context.type = eContextAdjustBaseRegister;
6667 context.SetAddress(offset_addr);
6668 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n,
6675 // if address<1:0> == '00' then LoadWritePC(data); else UNPREDICTABLE;
6676 if (BitIsClear(address, 1) && BitIsClear(address, 0)) {
6677 context.type = eContextRegisterLoad;
6678 context.SetRegisterPlusOffset(base_reg, address - Rn);
6679 LoadWritePC(context, data);
6683 // elsif UnalignedSupport() || address<1:0> = '00' then
6684 else if (UnalignedSupport() ||
6685 (BitIsClear(address, 1) && BitIsClear(address, 0))) {
6687 context.type = eContextRegisterLoad;
6688 context.SetRegisterPlusOffset(base_reg, address - Rn);
6689 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + t,
6692 } else // Can only apply before ARMv7
6694 // if CurrentInstrSet() == InstrSet_ARM then
6695 if (CurrentInstrSet() == eModeARM) {
6696 // R[t] = ROR(data, 8*UInt(address<1:0>));
6697 data = ROR(data, Bits32(address, 1, 0), &success);
6700 context.type = eContextRegisterLoad;
6701 context.SetImmediate(data);
6702 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + t,
6706 // R[t] = bits(32) UNKNOWN;
6707 WriteBits32Unknown(t);
6714 // LDRB (immediate, Thumb)
6715 bool EmulateInstructionARM::EmulateLDRBImmediate(const uint32_t opcode,
6716 const ARMEncoding encoding) {
6718 if ConditionPassed() then
6719 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
6720 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
6721 address = if index then offset_addr else R[n];
6722 R[t] = ZeroExtend(MemU[address,1], 32);
6723 if wback then R[n] = offset_addr;
6726 bool success = false;
6728 if (ConditionPassed(opcode)) {
6736 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
6739 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm5, 32);
6740 t = Bits32(opcode, 2, 0);
6741 n = Bits32(opcode, 5, 3);
6742 imm32 = Bits32(opcode, 10, 6);
6744 // index = TRUE; add = TRUE; wback = FALSE;
6752 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
6753 t = Bits32(opcode, 15, 12);
6754 n = Bits32(opcode, 19, 16);
6755 imm32 = Bits32(opcode, 11, 0);
6757 // index = TRUE; add = TRUE; wback = FALSE;
6762 // if Rt == '1111' then SEE PLD;
6764 return false; // PLD is not implemented yet
6766 // if Rn == '1111' then SEE LDRB (literal);
6768 return EmulateLDRBLiteral(opcode, eEncodingT1);
6770 // if t == 13 then UNPREDICTABLE;
6777 // if P == '1' && U == '1' && W == '0' then SEE LDRBT;
6778 // if P == '0' && W == '0' then UNDEFINED;
6779 if (BitIsClear(opcode, 10) && BitIsClear(opcode, 8))
6782 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32);
6783 t = Bits32(opcode, 15, 12);
6784 n = Bits32(opcode, 19, 16);
6785 imm32 = Bits32(opcode, 7, 0);
6787 // index = (P == '1'); add = (U == '1'); wback = (W == '1');
6788 index = BitIsSet(opcode, 10);
6789 add = BitIsSet(opcode, 9);
6790 wback = BitIsSet(opcode, 8);
6792 // if Rt == '1111' && P == '1' && U == '0' && W == '0' then SEE PLD;
6794 return false; // PLD is not implemented yet
6796 // if Rn == '1111' then SEE LDRB (literal);
6798 return EmulateLDRBLiteral(opcode, eEncodingT1);
6800 // if BadReg(t) || (wback && n == t) then UNPREDICTABLE;
6801 if (BadReg(t) || (wback && (n == t)))
6811 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
6818 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
6820 offset_addr = Rn + imm32;
6822 offset_addr = Rn - imm32;
6824 // address = if index then offset_addr else R[n];
6826 address = offset_addr;
6830 // R[t] = ZeroExtend(MemU[address,1], 32);
6831 RegisterInfo base_reg;
6832 RegisterInfo data_reg;
6833 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n, base_reg);
6834 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + t, data_reg);
6836 EmulateInstruction::Context context;
6837 context.type = eContextRegisterLoad;
6838 context.SetRegisterToRegisterPlusOffset(data_reg, base_reg, address - Rn);
6840 uint64_t data = MemURead(context, address, 1, 0, &success);
6844 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + t, data))
6847 // if wback then R[n] = offset_addr;
6849 context.type = eContextAdjustBaseRegister;
6850 context.SetAddress(offset_addr);
6851 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n,
6859 // LDRB (literal) calculates an address from the PC value and an immediate
6860 // offset, loads a byte from memory,
6861 // zero-extends it to form a 32-bit word and writes it to a register.
6862 bool EmulateInstructionARM::EmulateLDRBLiteral(const uint32_t opcode,
6863 const ARMEncoding encoding) {
6865 if ConditionPassed() then
6866 EncodingSpecificOperations(); NullCheckIfThumbEE(15);
6868 address = if add then (base + imm32) else (base - imm32);
6869 R[t] = ZeroExtend(MemU[address,1], 32);
6872 bool success = false;
6874 if (ConditionPassed(opcode)) {
6880 // t = UInt(Rt); imm32 = ZeroExtend(imm12, 32); add = (U == '1');
6881 t = Bits32(opcode, 15, 12);
6882 imm32 = Bits32(opcode, 11, 0);
6883 add = BitIsSet(opcode, 23);
6885 // if Rt == '1111' then SEE PLD;
6887 return false; // PLD is not implemented yet
6889 // if t == 13 then UNPREDICTABLE;
6896 // t == UInt(Rt); imm32 = ZeroExtend(imm12, 32); add = (U == '1');
6897 t = Bits32(opcode, 15, 12);
6898 imm32 = Bits32(opcode, 11, 0);
6899 add = BitIsSet(opcode, 23);
6901 // if t == 15 then UNPREDICTABLE;
6910 // base = Align(PC,4);
6911 uint32_t pc_val = ReadCoreReg(PC_REG, &success);
6915 uint32_t base = AlignPC(pc_val);
6918 // address = if add then (base + imm32) else (base - imm32);
6920 address = base + imm32;
6922 address = base - imm32;
6924 // R[t] = ZeroExtend(MemU[address,1], 32);
6925 EmulateInstruction::Context context;
6926 context.type = eContextRelativeBranchImmediate;
6927 context.SetImmediate(address - base);
6929 uint64_t data = MemURead(context, address, 1, 0, &success);
6933 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + t, data))
6939 // LDRB (register) calculates an address from a base register value and an
6940 // offset rigister value, loads a byte from memory, zero-extends it to form a
6941 // 32-bit word, and writes it to a register. The offset register value can
6942 // optionally be shifted.
6943 bool EmulateInstructionARM::EmulateLDRBRegister(const uint32_t opcode,
6944 const ARMEncoding encoding) {
6946 if ConditionPassed() then
6947 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
6948 offset = Shift(R[m], shift_t, shift_n, APSR.C);
6949 offset_addr = if add then (R[n] + offset) else (R[n] - offset);
6950 address = if index then offset_addr else R[n];
6951 R[t] = ZeroExtend(MemU[address,1],32);
6952 if wback then R[n] = offset_addr;
6955 bool success = false;
6957 if (ConditionPassed(opcode)) {
6964 ARM_ShifterType shift_t;
6967 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
6970 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
6971 t = Bits32(opcode, 2, 0);
6972 n = Bits32(opcode, 5, 3);
6973 m = Bits32(opcode, 8, 6);
6975 // index = TRUE; add = TRUE; wback = FALSE;
6980 // (shift_t, shift_n) = (SRType_LSL, 0);
6981 shift_t = SRType_LSL;
6986 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
6987 t = Bits32(opcode, 15, 12);
6988 n = Bits32(opcode, 19, 16);
6989 m = Bits32(opcode, 3, 0);
6991 // index = TRUE; add = TRUE; wback = FALSE;
6996 // (shift_t, shift_n) = (SRType_LSL, UInt(imm2));
6997 shift_t = SRType_LSL;
6998 shift_n = Bits32(opcode, 5, 4);
7000 // if Rt == '1111' then SEE PLD;
7002 return false; // PLD is not implemented yet
7004 // if Rn == '1111' then SEE LDRB (literal);
7006 return EmulateLDRBLiteral(opcode, eEncodingT1);
7008 // if t == 13 || BadReg(m) then UNPREDICTABLE;
7009 if ((t == 13) || BadReg(m))
7014 // if P == '0' && W == '1' then SEE LDRBT;
7015 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
7016 t = Bits32(opcode, 15, 12);
7017 n = Bits32(opcode, 19, 16);
7018 m = Bits32(opcode, 3, 0);
7020 // index = (P == '1'); add = (U == '1'); wback = (P == '0') ||
7022 index = BitIsSet(opcode, 24);
7023 add = BitIsSet(opcode, 23);
7024 wback = (BitIsClear(opcode, 24) || BitIsSet(opcode, 21));
7026 // (shift_t, shift_n) = DecodeImmShift(type, imm5);
7027 uint32_t type = Bits32(opcode, 6, 5);
7028 uint32_t imm5 = Bits32(opcode, 11, 7);
7029 shift_n = DecodeImmShift(type, imm5, shift_t);
7031 // if t == 15 || m == 15 then UNPREDICTABLE;
7032 if ((t == 15) || (m == 15))
7035 // if wback && (n == 15 || n == t) then UNPREDICTABLE;
7036 if (wback && ((n == 15) || (n == t)))
7047 // offset = Shift(R[m], shift_t, shift_n, APSR.C);
7049 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
7053 addr_t offset = Shift(Rm, shift_t, shift_n, APSR_C, &success);
7057 // offset_addr = if add then (R[n] + offset) else (R[n] - offset);
7059 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
7064 offset_addr = Rn + offset;
7066 offset_addr = Rn - offset;
7068 // address = if index then offset_addr else R[n];
7070 address = offset_addr;
7074 // R[t] = ZeroExtend(MemU[address,1],32);
7075 RegisterInfo base_reg;
7076 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n, base_reg);
7078 EmulateInstruction::Context context;
7079 context.type = eContextRegisterLoad;
7080 context.SetRegisterPlusOffset(base_reg, address - Rn);
7082 uint64_t data = MemURead(context, address, 1, 0, &success);
7086 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + t, data))
7089 // if wback then R[n] = offset_addr;
7091 context.type = eContextAdjustBaseRegister;
7092 context.SetAddress(offset_addr);
7093 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n,
7101 // LDRH (immediate, Thumb) calculates an address from a base register value and
7102 // an immediate offset, loads a
7103 // halfword from memory, zero-extends it to form a 32-bit word, and writes it
7104 // to a register. It can use offset, post-indexed, or pre-indexed addressing.
7105 bool EmulateInstructionARM::EmulateLDRHImmediate(const uint32_t opcode,
7106 const ARMEncoding encoding) {
7108 if ConditionPassed() then
7109 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
7110 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
7111 address = if index then offset_addr else R[n];
7112 data = MemU[address,2];
7113 if wback then R[n] = offset_addr;
7114 if UnalignedSupport() || address<0> = '0' then
7115 R[t] = ZeroExtend(data, 32);
7116 else // Can only apply before ARMv7
7117 R[t] = bits(32) UNKNOWN;
7120 bool success = false;
7122 if (ConditionPassed(opcode)) {
7130 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
7133 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm5:'0', 32);
7134 t = Bits32(opcode, 2, 0);
7135 n = Bits32(opcode, 5, 3);
7136 imm32 = Bits32(opcode, 10, 6) << 1;
7138 // index = TRUE; add = TRUE; wback = FALSE;
7146 // if Rt == '1111' then SEE "Unallocated memory hints";
7147 // if Rn == '1111' then SEE LDRH (literal);
7148 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
7149 t = Bits32(opcode, 15, 12);
7150 n = Bits32(opcode, 19, 16);
7151 imm32 = Bits32(opcode, 11, 0);
7153 // index = TRUE; add = TRUE; wback = FALSE;
7158 // if t == 13 then UNPREDICTABLE;
7164 // if Rn == '1111' then SEE LDRH (literal);
7165 // if Rt == '1111' && P == '1' && U == '0' && W == '0' then SEE
7166 // "Unallocated memory hints";
7167 // if P == '1' && U == '1' && W == '0' then SEE LDRHT;
7168 // if P == '0' && W == '0' then UNDEFINED;
7169 if (BitIsClear(opcode, 10) && BitIsClear(opcode, 8))
7172 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32);
7173 t = Bits32(opcode, 15, 12);
7174 n = Bits32(opcode, 19, 16);
7175 imm32 = Bits32(opcode, 7, 0);
7177 // index = (P == '1'); add = (U == '1'); wback = (W == '1');
7178 index = BitIsSet(opcode, 10);
7179 add = BitIsSet(opcode, 9);
7180 wback = BitIsSet(opcode, 8);
7182 // if BadReg(t) || (wback && n == t) then UNPREDICTABLE;
7183 if (BadReg(t) || (wback && (n == t)))
7191 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
7193 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
7201 offset_addr = Rn + imm32;
7203 offset_addr = Rn - imm32;
7205 // address = if index then offset_addr else R[n];
7207 address = offset_addr;
7211 // data = MemU[address,2];
7212 RegisterInfo base_reg;
7213 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n, base_reg);
7215 EmulateInstruction::Context context;
7216 context.type = eContextRegisterLoad;
7217 context.SetRegisterPlusOffset(base_reg, address - Rn);
7219 uint64_t data = MemURead(context, address, 2, 0, &success);
7223 // if wback then R[n] = offset_addr;
7225 context.type = eContextAdjustBaseRegister;
7226 context.SetAddress(offset_addr);
7227 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n,
7232 // if UnalignedSupport() || address<0> = '0' then
7233 if (UnalignedSupport() || BitIsClear(address, 0)) {
7234 // R[t] = ZeroExtend(data, 32);
7235 context.type = eContextRegisterLoad;
7236 context.SetRegisterPlusOffset(base_reg, address - Rn);
7237 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + t,
7240 } else // Can only apply before ARMv7
7242 // R[t] = bits(32) UNKNOWN;
7243 WriteBits32Unknown(t);
7249 // LDRH (literal) caculates an address from the PC value and an immediate
7250 // offset, loads a halfword from memory,
7251 // zero-extends it to form a 32-bit word, and writes it to a register.
7252 bool EmulateInstructionARM::EmulateLDRHLiteral(const uint32_t opcode,
7253 const ARMEncoding encoding) {
7255 if ConditionPassed() then
7256 EncodingSpecificOperations(); NullCheckIfThumbEE(15);
7258 address = if add then (base + imm32) else (base - imm32);
7259 data = MemU[address,2];
7260 if UnalignedSupport() || address<0> = '0' then
7261 R[t] = ZeroExtend(data, 32);
7262 else // Can only apply before ARMv7
7263 R[t] = bits(32) UNKNOWN;
7266 bool success = false;
7268 if (ConditionPassed(opcode)) {
7273 // EncodingSpecificOperations(); NullCheckIfThumbEE(15);
7276 // if Rt == '1111' then SEE "Unallocated memory hints";
7277 // t = UInt(Rt); imm32 = ZeroExtend(imm12, 32); add = (U == '1');
7278 t = Bits32(opcode, 15, 12);
7279 imm32 = Bits32(opcode, 11, 0);
7280 add = BitIsSet(opcode, 23);
7282 // if t == 13 then UNPREDICTABLE;
7289 uint32_t imm4H = Bits32(opcode, 11, 8);
7290 uint32_t imm4L = Bits32(opcode, 3, 0);
7292 // t == UInt(Rt); imm32 = ZeroExtend(imm4H:imm4L, 32); add = (U == '1');
7293 t = Bits32(opcode, 15, 12);
7294 imm32 = (imm4H << 4) | imm4L;
7295 add = BitIsSet(opcode, 23);
7297 // if t == 15 then UNPREDICTABLE;
7307 // base = Align(PC,4);
7308 uint64_t pc_value = ReadCoreReg(PC_REG, &success);
7312 addr_t base = AlignPC(pc_value);
7315 // address = if add then (base + imm32) else (base - imm32);
7317 address = base + imm32;
7319 address = base - imm32;
7321 // data = MemU[address,2];
7322 RegisterInfo base_reg;
7323 GetRegisterInfo(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, base_reg);
7325 EmulateInstruction::Context context;
7326 context.type = eContextRegisterLoad;
7327 context.SetRegisterPlusOffset(base_reg, address - base);
7329 uint64_t data = MemURead(context, address, 2, 0, &success);
7333 // if UnalignedSupport() || address<0> = '0' then
7334 if (UnalignedSupport() || BitIsClear(address, 0)) {
7335 // R[t] = ZeroExtend(data, 32);
7336 context.type = eContextRegisterLoad;
7337 context.SetRegisterPlusOffset(base_reg, address - base);
7338 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + t,
7342 } else // Can only apply before ARMv7
7344 // R[t] = bits(32) UNKNOWN;
7345 WriteBits32Unknown(t);
7351 // LDRH (literal) calculates an address from a base register value and an offset
7352 // register value, loads a halfword
7353 // from memory, zero-extends it to form a 32-bit word, and writes it to a
7354 // register. The offset register value can be shifted left by 0, 1, 2, or 3
7356 bool EmulateInstructionARM::EmulateLDRHRegister(const uint32_t opcode,
7357 const ARMEncoding encoding) {
7359 if ConditionPassed() then
7360 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
7361 offset = Shift(R[m], shift_t, shift_n, APSR.C);
7362 offset_addr = if add then (R[n] + offset) else (R[n] - offset);
7363 address = if index then offset_addr else R[n];
7364 data = MemU[address,2];
7365 if wback then R[n] = offset_addr;
7366 if UnalignedSupport() || address<0> = '0' then
7367 R[t] = ZeroExtend(data, 32);
7368 else // Can only apply before ARMv7
7369 R[t] = bits(32) UNKNOWN;
7372 bool success = false;
7374 if (ConditionPassed(opcode)) {
7381 ARM_ShifterType shift_t;
7384 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
7387 // if CurrentInstrSet() == InstrSet_ThumbEE then SEE "Modified operation
7389 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
7390 t = Bits32(opcode, 2, 0);
7391 n = Bits32(opcode, 5, 3);
7392 m = Bits32(opcode, 8, 6);
7394 // index = TRUE; add = TRUE; wback = FALSE;
7399 // (shift_t, shift_n) = (SRType_LSL, 0);
7400 shift_t = SRType_LSL;
7406 // if Rn == '1111' then SEE LDRH (literal);
7407 // if Rt == '1111' then SEE "Unallocated memory hints";
7408 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
7409 t = Bits32(opcode, 15, 12);
7410 n = Bits32(opcode, 19, 16);
7411 m = Bits32(opcode, 3, 0);
7413 // index = TRUE; add = TRUE; wback = FALSE;
7418 // (shift_t, shift_n) = (SRType_LSL, UInt(imm2));
7419 shift_t = SRType_LSL;
7420 shift_n = Bits32(opcode, 5, 4);
7422 // if t == 13 || BadReg(m) then UNPREDICTABLE;
7423 if ((t == 13) || BadReg(m))
7428 // if P == '0' && W == '1' then SEE LDRHT;
7429 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
7430 t = Bits32(opcode, 15, 12);
7431 n = Bits32(opcode, 19, 16);
7432 m = Bits32(opcode, 3, 0);
7434 // index = (P == '1'); add = (U == '1'); wback = (P == '0') ||
7436 index = BitIsSet(opcode, 24);
7437 add = BitIsSet(opcode, 23);
7438 wback = (BitIsClear(opcode, 24) || BitIsSet(opcode, 21));
7440 // (shift_t, shift_n) = (SRType_LSL, 0);
7441 shift_t = SRType_LSL;
7444 // if t == 15 || m == 15 then UNPREDICTABLE;
7445 if ((t == 15) || (m == 15))
7448 // if wback && (n == 15 || n == t) then UNPREDICTABLE;
7449 if (wback && ((n == 15) || (n == t)))
7458 // offset = Shift(R[m], shift_t, shift_n, APSR.C);
7461 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
7465 addr_t offset = Shift(Rm, shift_t, shift_n, APSR_C, &success);
7472 // offset_addr = if add then (R[n] + offset) else (R[n] - offset);
7474 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
7479 offset_addr = Rn + offset;
7481 offset_addr = Rn - offset;
7483 // address = if index then offset_addr else R[n];
7485 address = offset_addr;
7489 // data = MemU[address,2];
7490 RegisterInfo base_reg;
7491 RegisterInfo offset_reg;
7492 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n, base_reg);
7493 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + m, offset_reg);
7495 EmulateInstruction::Context context;
7496 context.type = eContextRegisterLoad;
7497 context.SetRegisterPlusIndirectOffset(base_reg, offset_reg);
7498 uint64_t data = MemURead(context, address, 2, 0, &success);
7502 // if wback then R[n] = offset_addr;
7504 context.type = eContextAdjustBaseRegister;
7505 context.SetAddress(offset_addr);
7506 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n,
7511 // if UnalignedSupport() || address<0> = '0' then
7512 if (UnalignedSupport() || BitIsClear(address, 0)) {
7513 // R[t] = ZeroExtend(data, 32);
7514 context.type = eContextRegisterLoad;
7515 context.SetRegisterPlusIndirectOffset(base_reg, offset_reg);
7516 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + t,
7519 } else // Can only apply before ARMv7
7521 // R[t] = bits(32) UNKNOWN;
7522 WriteBits32Unknown(t);
7528 // LDRSB (immediate) calculates an address from a base register value and an
7529 // immediate offset, loads a byte from
7530 // memory, sign-extends it to form a 32-bit word, and writes it to a register.
7531 // It can use offset, post-indexed, or pre-indexed addressing.
7532 bool EmulateInstructionARM::EmulateLDRSBImmediate(const uint32_t opcode,
7533 const ARMEncoding encoding) {
7535 if ConditionPassed() then
7536 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
7537 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
7538 address = if index then offset_addr else R[n];
7539 R[t] = SignExtend(MemU[address,1], 32);
7540 if wback then R[n] = offset_addr;
7543 bool success = false;
7545 if (ConditionPassed(opcode)) {
7553 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
7556 // if Rt == '1111' then SEE PLI;
7557 // if Rn == '1111' then SEE LDRSB (literal);
7558 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
7559 t = Bits32(opcode, 15, 12);
7560 n = Bits32(opcode, 19, 16);
7561 imm32 = Bits32(opcode, 11, 0);
7563 // index = TRUE; add = TRUE; wback = FALSE;
7568 // if t == 13 then UNPREDICTABLE;
7575 // if Rt == '1111' && P == '1' && U == '0' && W == '0' then SEE PLI;
7576 // if Rn == '1111' then SEE LDRSB (literal);
7577 // if P == '1' && U == '1' && W == '0' then SEE LDRSBT;
7578 // if P == '0' && W == '0' then UNDEFINED;
7579 if (BitIsClear(opcode, 10) && BitIsClear(opcode, 8))
7582 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32);
7583 t = Bits32(opcode, 15, 12);
7584 n = Bits32(opcode, 19, 16);
7585 imm32 = Bits32(opcode, 7, 0);
7587 // index = (P == '1'); add = (U == '1'); wback = (W == '1');
7588 index = BitIsSet(opcode, 10);
7589 add = BitIsSet(opcode, 9);
7590 wback = BitIsSet(opcode, 8);
7592 // if BadReg(t) || (wback && n == t) then UNPREDICTABLE;
7594 ((t == 15) && (BitIsClear(opcode, 10) || BitIsSet(opcode, 9) ||
7595 BitIsSet(opcode, 8)))) ||
7596 (wback && (n == t)))
7602 // if Rn == '1111' then SEE LDRSB (literal);
7603 // if P == '0' && W == '1' then SEE LDRSBT;
7604 // t == UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm4H:imm4L, 32);
7605 t = Bits32(opcode, 15, 12);
7606 n = Bits32(opcode, 19, 16);
7608 uint32_t imm4H = Bits32(opcode, 11, 8);
7609 uint32_t imm4L = Bits32(opcode, 3, 0);
7610 imm32 = (imm4H << 4) | imm4L;
7612 // index = (P == '1'); add = (U == '1'); wback = (P == '0') ||
7614 index = BitIsSet(opcode, 24);
7615 add = BitIsSet(opcode, 23);
7616 wback = (BitIsClear(opcode, 24) || BitIsSet(opcode, 21));
7618 // if t == 15 || (wback && n == t) then UNPREDICTABLE;
7619 if ((t == 15) || (wback && (n == t)))
7629 uint64_t Rn = ReadCoreReg(n, &success);
7636 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
7638 offset_addr = Rn + imm32;
7640 offset_addr = Rn - imm32;
7642 // address = if index then offset_addr else R[n];
7644 address = offset_addr;
7648 // R[t] = SignExtend(MemU[address,1], 32);
7649 RegisterInfo base_reg;
7650 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n, base_reg);
7652 EmulateInstruction::Context context;
7653 context.type = eContextRegisterLoad;
7654 context.SetRegisterPlusOffset(base_reg, address - Rn);
7656 uint64_t unsigned_data = MemURead(context, address, 1, 0, &success);
7660 int64_t signed_data = llvm::SignExtend64<8>(unsigned_data);
7661 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + t,
7662 (uint64_t)signed_data))
7665 // if wback then R[n] = offset_addr;
7667 context.type = eContextAdjustBaseRegister;
7668 context.SetAddress(offset_addr);
7669 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n,
7678 // LDRSB (literal) calculates an address from the PC value and an immediate
7679 // offset, loads a byte from memory,
7680 // sign-extends it to form a 32-bit word, and writes tit to a register.
7681 bool EmulateInstructionARM::EmulateLDRSBLiteral(const uint32_t opcode,
7682 const ARMEncoding encoding) {
7684 if ConditionPassed() then
7685 EncodingSpecificOperations(); NullCheckIfThumbEE(15);
7687 address = if add then (base + imm32) else (base - imm32);
7688 R[t] = SignExtend(MemU[address,1], 32);
7691 bool success = false;
7693 if (ConditionPassed(opcode)) {
7698 // EncodingSpecificOperations(); NullCheckIfThumbEE(15);
7701 // if Rt == '1111' then SEE PLI;
7702 // t = UInt(Rt); imm32 = ZeroExtend(imm12, 32); add = (U == '1');
7703 t = Bits32(opcode, 15, 12);
7704 imm32 = Bits32(opcode, 11, 0);
7705 add = BitIsSet(opcode, 23);
7707 // if t == 13 then UNPREDICTABLE;
7714 // t == UInt(Rt); imm32 = ZeroExtend(imm4H:imm4L, 32); add = (U == '1');
7715 t = Bits32(opcode, 15, 12);
7716 uint32_t imm4H = Bits32(opcode, 11, 8);
7717 uint32_t imm4L = Bits32(opcode, 3, 0);
7718 imm32 = (imm4H << 4) | imm4L;
7719 add = BitIsSet(opcode, 23);
7721 // if t == 15 then UNPREDICTABLE;
7732 // base = Align(PC,4);
7733 uint64_t pc_value = ReadCoreReg(PC_REG, &success);
7736 uint64_t base = AlignPC(pc_value);
7738 // address = if add then (base + imm32) else (base - imm32);
7741 address = base + imm32;
7743 address = base - imm32;
7745 // R[t] = SignExtend(MemU[address,1], 32);
7746 RegisterInfo base_reg;
7747 GetRegisterInfo(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, base_reg);
7749 EmulateInstruction::Context context;
7750 context.type = eContextRegisterLoad;
7751 context.SetRegisterPlusOffset(base_reg, address - base);
7753 uint64_t unsigned_data = MemURead(context, address, 1, 0, &success);
7757 int64_t signed_data = llvm::SignExtend64<8>(unsigned_data);
7758 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + t,
7759 (uint64_t)signed_data))
7765 // LDRSB (register) calculates an address from a base register value and an
7766 // offset register value, loadsa byte from
7767 // memory, sign-extends it to form a 32-bit word, and writes it to a register.
7768 // The offset register value can be shifted left by 0, 1, 2, or 3 bits.
7769 bool EmulateInstructionARM::EmulateLDRSBRegister(const uint32_t opcode,
7770 const ARMEncoding encoding) {
7772 if ConditionPassed() then
7773 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
7774 offset = Shift(R[m], shift_t, shift_n, APSR.C);
7775 offset_addr = if add then (R[n] + offset) else (R[n] - offset);
7776 address = if index then offset_addr else R[n];
7777 R[t] = SignExtend(MemU[address,1], 32);
7778 if wback then R[n] = offset_addr;
7781 bool success = false;
7783 if (ConditionPassed(opcode)) {
7790 ARM_ShifterType shift_t;
7793 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
7796 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
7797 t = Bits32(opcode, 2, 0);
7798 n = Bits32(opcode, 5, 3);
7799 m = Bits32(opcode, 8, 6);
7801 // index = TRUE; add = TRUE; wback = FALSE;
7806 // (shift_t, shift_n) = (SRType_LSL, 0);
7807 shift_t = SRType_LSL;
7813 // if Rt == '1111' then SEE PLI;
7814 // if Rn == '1111' then SEE LDRSB (literal);
7815 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
7816 t = Bits32(opcode, 15, 12);
7817 n = Bits32(opcode, 19, 16);
7818 m = Bits32(opcode, 3, 0);
7820 // index = TRUE; add = TRUE; wback = FALSE;
7825 // (shift_t, shift_n) = (SRType_LSL, UInt(imm2));
7826 shift_t = SRType_LSL;
7827 shift_n = Bits32(opcode, 5, 4);
7829 // if t == 13 || BadReg(m) then UNPREDICTABLE;
7830 if ((t == 13) || BadReg(m))
7835 // if P == '0' && W == '1' then SEE LDRSBT;
7836 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
7837 t = Bits32(opcode, 15, 12);
7838 n = Bits32(opcode, 19, 16);
7839 m = Bits32(opcode, 3, 0);
7841 // index = (P == '1'); add = (U == '1'); wback = (P == '0') ||
7843 index = BitIsSet(opcode, 24);
7844 add = BitIsSet(opcode, 23);
7845 wback = BitIsClear(opcode, 24) || BitIsSet(opcode, 21);
7847 // (shift_t, shift_n) = (SRType_LSL, 0);
7848 shift_t = SRType_LSL;
7851 // if t == 15 || m == 15 then UNPREDICTABLE;
7852 if ((t == 15) || (m == 15))
7855 // if wback && (n == 15 || n == t) then UNPREDICTABLE;
7856 if (wback && ((n == 15) || (n == t)))
7865 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
7869 // offset = Shift(R[m], shift_t, shift_n, APSR.C);
7870 addr_t offset = Shift(Rm, shift_t, shift_n, APSR_C, &success);
7877 // offset_addr = if add then (R[n] + offset) else (R[n] - offset);
7879 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
7884 offset_addr = Rn + offset;
7886 offset_addr = Rn - offset;
7888 // address = if index then offset_addr else R[n];
7890 address = offset_addr;
7894 // R[t] = SignExtend(MemU[address,1], 32);
7895 RegisterInfo base_reg;
7896 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n, base_reg);
7897 RegisterInfo offset_reg;
7898 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + m, offset_reg);
7900 EmulateInstruction::Context context;
7901 context.type = eContextRegisterLoad;
7902 context.SetRegisterPlusIndirectOffset(base_reg, offset_reg);
7904 uint64_t unsigned_data = MemURead(context, address, 1, 0, &success);
7908 int64_t signed_data = llvm::SignExtend64<8>(unsigned_data);
7909 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + t,
7910 (uint64_t)signed_data))
7913 // if wback then R[n] = offset_addr;
7915 context.type = eContextAdjustBaseRegister;
7916 context.SetAddress(offset_addr);
7917 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n,
7925 // LDRSH (immediate) calculates an address from a base register value and an
7926 // immediate offset, loads a halfword from
7927 // memory, sign-extends it to form a 32-bit word, and writes it to a register.
7928 // It can use offset, post-indexed, or pre-indexed addressing.
7929 bool EmulateInstructionARM::EmulateLDRSHImmediate(const uint32_t opcode,
7930 const ARMEncoding encoding) {
7932 if ConditionPassed() then
7933 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
7934 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
7935 address = if index then offset_addr else R[n];
7936 data = MemU[address,2];
7937 if wback then R[n] = offset_addr;
7938 if UnalignedSupport() || address<0> = '0' then
7939 R[t] = SignExtend(data, 32);
7940 else // Can only apply before ARMv7
7941 R[t] = bits(32) UNKNOWN;
7944 bool success = false;
7946 if (ConditionPassed(opcode)) {
7954 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
7957 // if Rn == '1111' then SEE LDRSH (literal);
7958 // if Rt == '1111' then SEE "Unallocated memory hints";
7959 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
7960 t = Bits32(opcode, 15, 12);
7961 n = Bits32(opcode, 19, 16);
7962 imm32 = Bits32(opcode, 11, 0);
7964 // index = TRUE; add = TRUE; wback = FALSE;
7969 // if t == 13 then UNPREDICTABLE;
7976 // if Rn == '1111' then SEE LDRSH (literal);
7977 // if Rt == '1111' && P == '1' && U == '0' && W == '0' then SEE
7978 // "Unallocated memory hints";
7979 // if P == '1' && U == '1' && W == '0' then SEE LDRSHT;
7980 // if P == '0' && W == '0' then UNDEFINED;
7981 if (BitIsClear(opcode, 10) && BitIsClear(opcode, 8))
7984 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32);
7985 t = Bits32(opcode, 15, 12);
7986 n = Bits32(opcode, 19, 16);
7987 imm32 = Bits32(opcode, 7, 0);
7989 // index = (P == '1'); add = (U == '1'); wback = (W == '1');
7990 index = BitIsSet(opcode, 10);
7991 add = BitIsSet(opcode, 9);
7992 wback = BitIsSet(opcode, 8);
7994 // if BadReg(t) || (wback && n == t) then UNPREDICTABLE;
7995 if (BadReg(t) || (wback && (n == t)))
8001 // if Rn == '1111' then SEE LDRSH (literal);
8002 // if P == '0' && W == '1' then SEE LDRSHT;
8003 // t == UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm4H:imm4L, 32);
8004 t = Bits32(opcode, 15, 12);
8005 n = Bits32(opcode, 19, 16);
8006 uint32_t imm4H = Bits32(opcode, 11, 8);
8007 uint32_t imm4L = Bits32(opcode, 3, 0);
8008 imm32 = (imm4H << 4) | imm4L;
8010 // index = (P == '1'); add = (U == '1'); wback = (P == '0') ||
8012 index = BitIsSet(opcode, 24);
8013 add = BitIsSet(opcode, 23);
8014 wback = BitIsClear(opcode, 24) || BitIsSet(opcode, 21);
8016 // if t == 15 || (wback && n == t) then UNPREDICTABLE;
8017 if ((t == 15) || (wback && (n == t)))
8027 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
8029 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
8035 offset_addr = Rn + imm32;
8037 offset_addr = Rn - imm32;
8039 // address = if index then offset_addr else R[n];
8042 address = offset_addr;
8046 // data = MemU[address,2];
8047 RegisterInfo base_reg;
8048 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n, base_reg);
8050 EmulateInstruction::Context context;
8051 context.type = eContextRegisterLoad;
8052 context.SetRegisterPlusOffset(base_reg, address - Rn);
8054 uint64_t data = MemURead(context, address, 2, 0, &success);
8058 // if wback then R[n] = offset_addr;
8060 context.type = eContextAdjustBaseRegister;
8061 context.SetAddress(offset_addr);
8062 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n,
8067 // if UnalignedSupport() || address<0> = '0' then
8068 if (UnalignedSupport() || BitIsClear(address, 0)) {
8069 // R[t] = SignExtend(data, 32);
8070 int64_t signed_data = llvm::SignExtend64<16>(data);
8071 context.type = eContextRegisterLoad;
8072 context.SetRegisterPlusOffset(base_reg, address - Rn);
8073 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + t,
8074 (uint64_t)signed_data))
8076 } else // Can only apply before ARMv7
8078 // R[t] = bits(32) UNKNOWN;
8079 WriteBits32Unknown(t);
8085 // LDRSH (literal) calculates an address from the PC value and an immediate
8086 // offset, loads a halfword from memory,
8087 // sign-extends it to from a 32-bit word, and writes it to a register.
8088 bool EmulateInstructionARM::EmulateLDRSHLiteral(const uint32_t opcode,
8089 const ARMEncoding encoding) {
8091 if ConditionPassed() then
8092 EncodingSpecificOperations(); NullCheckIfThumbEE(15);
8094 address = if add then (base + imm32) else (base - imm32);
8095 data = MemU[address,2];
8096 if UnalignedSupport() || address<0> = '0' then
8097 R[t] = SignExtend(data, 32);
8098 else // Can only apply before ARMv7
8099 R[t] = bits(32) UNKNOWN;
8102 bool success = false;
8104 if (ConditionPassed(opcode)) {
8109 // EncodingSpecificOperations(); NullCheckIfThumbEE(15);
8112 // if Rt == '1111' then SEE "Unallocated memory hints";
8113 // t = UInt(Rt); imm32 = ZeroExtend(imm12, 32); add = (U == '1');
8114 t = Bits32(opcode, 15, 12);
8115 imm32 = Bits32(opcode, 11, 0);
8116 add = BitIsSet(opcode, 23);
8118 // if t == 13 then UNPREDICTABLE;
8125 // t == UInt(Rt); imm32 = ZeroExtend(imm4H:imm4L, 32); add = (U == '1');
8126 t = Bits32(opcode, 15, 12);
8127 uint32_t imm4H = Bits32(opcode, 11, 8);
8128 uint32_t imm4L = Bits32(opcode, 3, 0);
8129 imm32 = (imm4H << 4) | imm4L;
8130 add = BitIsSet(opcode, 23);
8132 // if t == 15 then UNPREDICTABLE;
8142 // base = Align(PC,4);
8143 uint64_t pc_value = ReadCoreReg(PC_REG, &success);
8147 uint64_t base = AlignPC(pc_value);
8150 // address = if add then (base + imm32) else (base - imm32);
8152 address = base + imm32;
8154 address = base - imm32;
8156 // data = MemU[address,2];
8157 RegisterInfo base_reg;
8158 GetRegisterInfo(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, base_reg);
8160 EmulateInstruction::Context context;
8161 context.type = eContextRegisterLoad;
8162 context.SetRegisterPlusOffset(base_reg, imm32);
8164 uint64_t data = MemURead(context, address, 2, 0, &success);
8168 // if UnalignedSupport() || address<0> = '0' then
8169 if (UnalignedSupport() || BitIsClear(address, 0)) {
8170 // R[t] = SignExtend(data, 32);
8171 int64_t signed_data = llvm::SignExtend64<16>(data);
8172 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + t,
8173 (uint64_t)signed_data))
8175 } else // Can only apply before ARMv7
8177 // R[t] = bits(32) UNKNOWN;
8178 WriteBits32Unknown(t);
8184 // LDRSH (register) calculates an address from a base register value and an
8185 // offset register value, loads a halfword
8186 // from memory, sign-extends it to form a 32-bit word, and writes it to a
8187 // register. The offset register value can be shifted left by 0, 1, 2, or 3
8189 bool EmulateInstructionARM::EmulateLDRSHRegister(const uint32_t opcode,
8190 const ARMEncoding encoding) {
8192 if ConditionPassed() then
8193 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
8194 offset = Shift(R[m], shift_t, shift_n, APSR.C);
8195 offset_addr = if add then (R[n] + offset) else (R[n] - offset);
8196 address = if index then offset_addr else R[n];
8197 data = MemU[address,2];
8198 if wback then R[n] = offset_addr;
8199 if UnalignedSupport() || address<0> = '0' then
8200 R[t] = SignExtend(data, 32);
8201 else // Can only apply before ARMv7
8202 R[t] = bits(32) UNKNOWN;
8205 bool success = false;
8207 if (ConditionPassed(opcode)) {
8214 ARM_ShifterType shift_t;
8217 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
8220 // if CurrentInstrSet() == InstrSet_ThumbEE then SEE "Modified operation
8222 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
8223 t = Bits32(opcode, 2, 0);
8224 n = Bits32(opcode, 5, 3);
8225 m = Bits32(opcode, 8, 6);
8227 // index = TRUE; add = TRUE; wback = FALSE;
8232 // (shift_t, shift_n) = (SRType_LSL, 0);
8233 shift_t = SRType_LSL;
8239 // if Rn == '1111' then SEE LDRSH (literal);
8240 // if Rt == '1111' then SEE "Unallocated memory hints";
8241 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
8242 t = Bits32(opcode, 15, 12);
8243 n = Bits32(opcode, 19, 16);
8244 m = Bits32(opcode, 3, 0);
8246 // index = TRUE; add = TRUE; wback = FALSE;
8251 // (shift_t, shift_n) = (SRType_LSL, UInt(imm2));
8252 shift_t = SRType_LSL;
8253 shift_n = Bits32(opcode, 5, 4);
8255 // if t == 13 || BadReg(m) then UNPREDICTABLE;
8256 if ((t == 13) || BadReg(m))
8262 // if P == '0' && W == '1' then SEE LDRSHT;
8263 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
8264 t = Bits32(opcode, 15, 12);
8265 n = Bits32(opcode, 19, 16);
8266 m = Bits32(opcode, 3, 0);
8268 // index = (P == '1'); add = (U == '1'); wback = (P == '0') ||
8270 index = BitIsSet(opcode, 24);
8271 add = BitIsSet(opcode, 23);
8272 wback = BitIsClear(opcode, 24) || BitIsSet(opcode, 21);
8274 // (shift_t, shift_n) = (SRType_LSL, 0);
8275 shift_t = SRType_LSL;
8278 // if t == 15 || m == 15 then UNPREDICTABLE;
8279 if ((t == 15) || (m == 15))
8282 // if wback && (n == 15 || n == t) then UNPREDICTABLE;
8283 if (wback && ((n == 15) || (n == t)))
8293 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
8298 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
8302 // offset = Shift(R[m], shift_t, shift_n, APSR.C);
8303 addr_t offset = Shift(Rm, shift_t, shift_n, APSR_C, &success);
8310 // offset_addr = if add then (R[n] + offset) else (R[n] - offset);
8312 offset_addr = Rn + offset;
8314 offset_addr = Rn - offset;
8316 // address = if index then offset_addr else R[n];
8318 address = offset_addr;
8322 // data = MemU[address,2];
8323 RegisterInfo base_reg;
8324 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n, base_reg);
8326 RegisterInfo offset_reg;
8327 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + m, offset_reg);
8329 EmulateInstruction::Context context;
8330 context.type = eContextRegisterLoad;
8331 context.SetRegisterPlusIndirectOffset(base_reg, offset_reg);
8333 uint64_t data = MemURead(context, address, 2, 0, &success);
8337 // if wback then R[n] = offset_addr;
8339 context.type = eContextAdjustBaseRegister;
8340 context.SetAddress(offset_addr);
8341 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n,
8346 // if UnalignedSupport() || address<0> = '0' then
8347 if (UnalignedSupport() || BitIsClear(address, 0)) {
8348 // R[t] = SignExtend(data, 32);
8349 context.type = eContextRegisterLoad;
8350 context.SetRegisterPlusIndirectOffset(base_reg, offset_reg);
8352 int64_t signed_data = llvm::SignExtend64<16>(data);
8353 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + t,
8354 (uint64_t)signed_data))
8356 } else // Can only apply before ARMv7
8358 // R[t] = bits(32) UNKNOWN;
8359 WriteBits32Unknown(t);
8365 // SXTB extracts an 8-bit value from a register, sign-extends it to 32 bits, and
8366 // writes the result to the destination
8367 // register. You can specifiy a rotation by 0, 8, 16, or 24 bits before
8368 // extracting the 8-bit value.
8369 bool EmulateInstructionARM::EmulateSXTB(const uint32_t opcode,
8370 const ARMEncoding encoding) {
8372 if ConditionPassed() then
8373 EncodingSpecificOperations();
8374 rotated = ROR(R[m], rotation);
8375 R[d] = SignExtend(rotated<7:0>, 32);
8378 bool success = false;
8380 if (ConditionPassed(opcode)) {
8385 // EncodingSpecificOperations();
8388 // d = UInt(Rd); m = UInt(Rm); rotation = 0;
8389 d = Bits32(opcode, 2, 0);
8390 m = Bits32(opcode, 5, 3);
8396 // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:'000');
8397 d = Bits32(opcode, 11, 8);
8398 m = Bits32(opcode, 3, 0);
8399 rotation = Bits32(opcode, 5, 4) << 3;
8401 // if BadReg(d) || BadReg(m) then UNPREDICTABLE;
8402 if (BadReg(d) || BadReg(m))
8408 // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:'000');
8409 d = Bits32(opcode, 15, 12);
8410 m = Bits32(opcode, 3, 0);
8411 rotation = Bits32(opcode, 11, 10) << 3;
8413 // if d == 15 || m == 15 then UNPREDICTABLE;
8414 if ((d == 15) || (m == 15))
8424 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
8428 // rotated = ROR(R[m], rotation);
8429 uint64_t rotated = ROR(Rm, rotation, &success);
8433 // R[d] = SignExtend(rotated<7:0>, 32);
8434 int64_t data = llvm::SignExtend64<8>(rotated);
8436 RegisterInfo source_reg;
8437 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + m, source_reg);
8439 EmulateInstruction::Context context;
8440 context.type = eContextRegisterLoad;
8441 context.SetRegister(source_reg);
8443 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + d,
8450 // SXTH extracts a 16-bit value from a register, sign-extends it to 32 bits, and
8451 // writes the result to the destination
8452 // register. You can specify a rotation by 0, 8, 16, or 24 bits before
8453 // extracting the 16-bit value.
8454 bool EmulateInstructionARM::EmulateSXTH(const uint32_t opcode,
8455 const ARMEncoding encoding) {
8457 if ConditionPassed() then
8458 EncodingSpecificOperations();
8459 rotated = ROR(R[m], rotation);
8460 R[d] = SignExtend(rotated<15:0>, 32);
8463 bool success = false;
8465 if (ConditionPassed(opcode)) {
8470 // EncodingSpecificOperations();
8473 // d = UInt(Rd); m = UInt(Rm); rotation = 0;
8474 d = Bits32(opcode, 2, 0);
8475 m = Bits32(opcode, 5, 3);
8481 // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:'000');
8482 d = Bits32(opcode, 11, 8);
8483 m = Bits32(opcode, 3, 0);
8484 rotation = Bits32(opcode, 5, 4) << 3;
8486 // if BadReg(d) || BadReg(m) then UNPREDICTABLE;
8487 if (BadReg(d) || BadReg(m))
8493 // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:'000');
8494 d = Bits32(opcode, 15, 12);
8495 m = Bits32(opcode, 3, 0);
8496 rotation = Bits32(opcode, 11, 10) << 3;
8498 // if d == 15 || m == 15 then UNPREDICTABLE;
8499 if ((d == 15) || (m == 15))
8509 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
8513 // rotated = ROR(R[m], rotation);
8514 uint64_t rotated = ROR(Rm, rotation, &success);
8518 // R[d] = SignExtend(rotated<15:0>, 32);
8519 RegisterInfo source_reg;
8520 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + m, source_reg);
8522 EmulateInstruction::Context context;
8523 context.type = eContextRegisterLoad;
8524 context.SetRegister(source_reg);
8526 int64_t data = llvm::SignExtend64<16>(rotated);
8527 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + d,
8535 // UXTB extracts an 8-bit value from a register, zero-extneds it to 32 bits, and
8536 // writes the result to the destination
8537 // register. You can specify a rotation by 0, 8, 16, or 24 bits before
8538 // extracting the 8-bit value.
8539 bool EmulateInstructionARM::EmulateUXTB(const uint32_t opcode,
8540 const ARMEncoding encoding) {
8542 if ConditionPassed() then
8543 EncodingSpecificOperations();
8544 rotated = ROR(R[m], rotation);
8545 R[d] = ZeroExtend(rotated<7:0>, 32);
8548 bool success = false;
8550 if (ConditionPassed(opcode)) {
8555 // EncodingSpecificOperations();
8558 // d = UInt(Rd); m = UInt(Rm); rotation = 0;
8559 d = Bits32(opcode, 2, 0);
8560 m = Bits32(opcode, 5, 3);
8566 // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:'000');
8567 d = Bits32(opcode, 11, 8);
8568 m = Bits32(opcode, 3, 0);
8569 rotation = Bits32(opcode, 5, 4) << 3;
8571 // if BadReg(d) || BadReg(m) then UNPREDICTABLE;
8572 if (BadReg(d) || BadReg(m))
8578 // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:'000');
8579 d = Bits32(opcode, 15, 12);
8580 m = Bits32(opcode, 3, 0);
8581 rotation = Bits32(opcode, 11, 10) << 3;
8583 // if d == 15 || m == 15 then UNPREDICTABLE;
8584 if ((d == 15) || (m == 15))
8594 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
8598 // rotated = ROR(R[m], rotation);
8599 uint64_t rotated = ROR(Rm, rotation, &success);
8603 // R[d] = ZeroExtend(rotated<7:0>, 32);
8604 RegisterInfo source_reg;
8605 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + m, source_reg);
8607 EmulateInstruction::Context context;
8608 context.type = eContextRegisterLoad;
8609 context.SetRegister(source_reg);
8611 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + d,
8612 Bits32(rotated, 7, 0)))
8618 // UXTH extracts a 16-bit value from a register, zero-extends it to 32 bits, and
8619 // writes the result to the destination
8620 // register. You can specify a rotation by 0, 8, 16, or 24 bits before
8621 // extracting the 16-bit value.
8622 bool EmulateInstructionARM::EmulateUXTH(const uint32_t opcode,
8623 const ARMEncoding encoding) {
8625 if ConditionPassed() then
8626 EncodingSpecificOperations();
8627 rotated = ROR(R[m], rotation);
8628 R[d] = ZeroExtend(rotated<15:0>, 32);
8631 bool success = false;
8633 if (ConditionPassed(opcode)) {
8640 // d = UInt(Rd); m = UInt(Rm); rotation = 0;
8641 d = Bits32(opcode, 2, 0);
8642 m = Bits32(opcode, 5, 3);
8648 // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:'000');
8649 d = Bits32(opcode, 11, 8);
8650 m = Bits32(opcode, 3, 0);
8651 rotation = Bits32(opcode, 5, 4) << 3;
8653 // if BadReg(d) || BadReg(m) then UNPREDICTABLE;
8654 if (BadReg(d) || BadReg(m))
8660 // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:'000');
8661 d = Bits32(opcode, 15, 12);
8662 m = Bits32(opcode, 3, 0);
8663 rotation = Bits32(opcode, 11, 10) << 3;
8665 // if d == 15 || m == 15 then UNPREDICTABLE;
8666 if ((d == 15) || (m == 15))
8676 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
8680 // rotated = ROR(R[m], rotation);
8681 uint64_t rotated = ROR(Rm, rotation, &success);
8685 // R[d] = ZeroExtend(rotated<15:0>, 32);
8686 RegisterInfo source_reg;
8687 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + m, source_reg);
8689 EmulateInstruction::Context context;
8690 context.type = eContextRegisterLoad;
8691 context.SetRegister(source_reg);
8693 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + d,
8694 Bits32(rotated, 15, 0)))
8700 // RFE (Return From Exception) loads the PC and the CPSR from the word at the
8701 // specified address and the following
8702 // word respectively.
8703 bool EmulateInstructionARM::EmulateRFE(const uint32_t opcode,
8704 const ARMEncoding encoding) {
8706 if ConditionPassed() then
8707 EncodingSpecificOperations();
8708 if !CurrentModeIsPrivileged() || CurrentInstrSet() == InstrSet_ThumbEE then
8711 address = if increment then R[n] else R[n]-8;
8712 if wordhigher then address = address+4;
8713 CPSRWriteByInstr(MemA[address+4,4], '1111', TRUE);
8714 BranchWritePC(MemA[address,4]);
8715 if wback then R[n] = if increment then R[n]+8 else R[n]-8;
8718 bool success = false;
8720 if (ConditionPassed(opcode)) {
8726 // EncodingSpecificOperations();
8729 // n = UInt(Rn); wback = (W == '1'); increment = FALSE; wordhigher =
8731 n = Bits32(opcode, 19, 16);
8732 wback = BitIsSet(opcode, 21);
8736 // if n == 15 then UNPREDICTABLE;
8740 // if InITBlock() && !LastInITBlock() then UNPREDICTABLE;
8741 if (InITBlock() && !LastInITBlock())
8747 // n = UInt(Rn); wback = (W == '1'); increment = TRUE; wordhigher = FALSE;
8748 n = Bits32(opcode, 19, 16);
8749 wback = BitIsSet(opcode, 21);
8753 // if n == 15 then UNPREDICTABLE;
8757 // if InITBlock() && !LastInITBlock() then UNPREDICTABLE;
8758 if (InITBlock() && !LastInITBlock())
8765 n = Bits32(opcode, 19, 16);
8767 // wback = (W == '1'); inc = (U == '1'); wordhigher = (P == U);
8768 wback = BitIsSet(opcode, 21);
8769 increment = BitIsSet(opcode, 23);
8770 wordhigher = (Bit32(opcode, 24) == Bit32(opcode, 23));
8772 // if n == 15 then UNPREDICTABLE;
8782 // if !CurrentModeIsPrivileged() || CurrentInstrSet() == InstrSet_ThumbEE
8784 if (!CurrentModeIsPrivileged())
8789 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
8794 // address = if increment then R[n] else R[n]-8;
8800 // if wordhigher then address = address+4;
8802 address = address + 4;
8804 // CPSRWriteByInstr(MemA[address+4,4], '1111', TRUE);
8805 RegisterInfo base_reg;
8806 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n, base_reg);
8808 EmulateInstruction::Context context;
8809 context.type = eContextReturnFromException;
8810 context.SetRegisterPlusOffset(base_reg, address - Rn);
8812 uint64_t data = MemARead(context, address + 4, 4, 0, &success);
8816 CPSRWriteByInstr(data, 15, true);
8818 // BranchWritePC(MemA[address,4]);
8819 uint64_t data2 = MemARead(context, address, 4, 0, &success);
8823 BranchWritePC(context, data2);
8825 // if wback then R[n] = if increment then R[n]+8 else R[n]-8;
8827 context.type = eContextAdjustBaseRegister;
8829 context.SetOffset(8);
8830 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n,
8834 context.SetOffset(-8);
8835 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n,
8841 } // if ConditionPassed()
8845 // Bitwise Exclusive OR (immediate) performs a bitwise exclusive OR of a
8846 // register value and an immediate value, and writes the result to the
8847 // destination register. It can optionally update the condition flags based on
8849 bool EmulateInstructionARM::EmulateEORImm(const uint32_t opcode,
8850 const ARMEncoding encoding) {
8852 // ARM pseudo code...
8853 if ConditionPassed() then
8854 EncodingSpecificOperations();
8855 result = R[n] EOR imm32;
8856 if d == 15 then // Can only occur for ARM encoding
8857 ALUWritePC(result); // setflags is always FALSE here
8861 APSR.N = result<31>;
8862 APSR.Z = IsZeroBit(result);
8867 bool success = false;
8869 if (ConditionPassed(opcode)) {
8872 imm32; // the immediate value to be ORed to the value obtained from Rn
8874 uint32_t carry; // the carry bit after ARM/Thumb Expand operation
8877 Rd = Bits32(opcode, 11, 8);
8878 Rn = Bits32(opcode, 19, 16);
8879 setflags = BitIsSet(opcode, 20);
8880 imm32 = ThumbExpandImm_C(
8882 carry); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C)
8883 // if Rd == '1111' && S == '1' then SEE TEQ (immediate);
8884 if (Rd == 15 && setflags)
8885 return EmulateTEQImm(opcode, eEncodingT1);
8886 if (Rd == 13 || (Rd == 15 && !setflags) || BadReg(Rn))
8890 Rd = Bits32(opcode, 15, 12);
8891 Rn = Bits32(opcode, 19, 16);
8892 setflags = BitIsSet(opcode, 20);
8894 ARMExpandImm_C(opcode, APSR_C,
8895 carry); // (imm32, carry) = ARMExpandImm(imm12, APSR.C)
8897 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related
8899 if (Rd == 15 && setflags)
8900 return EmulateSUBSPcLrEtc(opcode, encoding);
8906 // Read the first operand.
8907 uint32_t val1 = ReadCoreReg(Rn, &success);
8911 uint32_t result = val1 ^ imm32;
8913 EmulateInstruction::Context context;
8914 context.type = EmulateInstruction::eContextImmediate;
8915 context.SetNoArgs();
8917 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
8923 // Bitwise Exclusive OR (register) performs a bitwise exclusive OR of a
8924 // register value and an optionally-shifted register value, and writes the
8925 // result to the destination register. It can optionally update the condition
8926 // flags based on the result.
8927 bool EmulateInstructionARM::EmulateEORReg(const uint32_t opcode,
8928 const ARMEncoding encoding) {
8930 // ARM pseudo code...
8931 if ConditionPassed() then
8932 EncodingSpecificOperations();
8933 (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C);
8934 result = R[n] EOR shifted;
8935 if d == 15 then // Can only occur for ARM encoding
8936 ALUWritePC(result); // setflags is always FALSE here
8940 APSR.N = result<31>;
8941 APSR.Z = IsZeroBit(result);
8946 bool success = false;
8948 if (ConditionPassed(opcode)) {
8949 uint32_t Rd, Rn, Rm;
8950 ARM_ShifterType shift_t;
8951 uint32_t shift_n; // the shift applied to the value read from Rm
8956 Rd = Rn = Bits32(opcode, 2, 0);
8957 Rm = Bits32(opcode, 5, 3);
8958 setflags = !InITBlock();
8959 shift_t = SRType_LSL;
8963 Rd = Bits32(opcode, 11, 8);
8964 Rn = Bits32(opcode, 19, 16);
8965 Rm = Bits32(opcode, 3, 0);
8966 setflags = BitIsSet(opcode, 20);
8967 shift_n = DecodeImmShiftThumb(opcode, shift_t);
8968 // if Rd == '1111' && S == '1' then SEE TEQ (register);
8969 if (Rd == 15 && setflags)
8970 return EmulateTEQReg(opcode, eEncodingT1);
8971 if (Rd == 13 || (Rd == 15 && !setflags) || BadReg(Rn) || BadReg(Rm))
8975 Rd = Bits32(opcode, 15, 12);
8976 Rn = Bits32(opcode, 19, 16);
8977 Rm = Bits32(opcode, 3, 0);
8978 setflags = BitIsSet(opcode, 20);
8979 shift_n = DecodeImmShiftARM(opcode, shift_t);
8981 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related
8983 if (Rd == 15 && setflags)
8984 return EmulateSUBSPcLrEtc(opcode, encoding);
8990 // Read the first operand.
8991 uint32_t val1 = ReadCoreReg(Rn, &success);
8995 // Read the second operand.
8996 uint32_t val2 = ReadCoreReg(Rm, &success);
9000 uint32_t shifted = Shift_C(val2, shift_t, shift_n, APSR_C, carry, &success);
9003 uint32_t result = val1 ^ shifted;
9005 EmulateInstruction::Context context;
9006 context.type = EmulateInstruction::eContextImmediate;
9007 context.SetNoArgs();
9009 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
9015 // Bitwise OR (immediate) performs a bitwise (inclusive) OR of a register value
9016 // and an immediate value, and writes the result to the destination register.
9017 // It can optionally update the condition flags based on the result.
9018 bool EmulateInstructionARM::EmulateORRImm(const uint32_t opcode,
9019 const ARMEncoding encoding) {
9021 // ARM pseudo code...
9022 if ConditionPassed() then
9023 EncodingSpecificOperations();
9024 result = R[n] OR imm32;
9025 if d == 15 then // Can only occur for ARM encoding
9026 ALUWritePC(result); // setflags is always FALSE here
9030 APSR.N = result<31>;
9031 APSR.Z = IsZeroBit(result);
9036 bool success = false;
9038 if (ConditionPassed(opcode)) {
9041 imm32; // the immediate value to be ORed to the value obtained from Rn
9043 uint32_t carry; // the carry bit after ARM/Thumb Expand operation
9046 Rd = Bits32(opcode, 11, 8);
9047 Rn = Bits32(opcode, 19, 16);
9048 setflags = BitIsSet(opcode, 20);
9049 imm32 = ThumbExpandImm_C(
9051 carry); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C)
9052 // if Rn == '1111' then SEE MOV (immediate);
9054 return EmulateMOVRdImm(opcode, eEncodingT2);
9055 if (BadReg(Rd) || Rn == 13)
9059 Rd = Bits32(opcode, 15, 12);
9060 Rn = Bits32(opcode, 19, 16);
9061 setflags = BitIsSet(opcode, 20);
9063 ARMExpandImm_C(opcode, APSR_C,
9064 carry); // (imm32, carry) = ARMExpandImm(imm12, APSR.C)
9066 if (Rd == 15 && setflags)
9067 return EmulateSUBSPcLrEtc(opcode, encoding);
9073 // Read the first operand.
9074 uint32_t val1 = ReadCoreReg(Rn, &success);
9078 uint32_t result = val1 | imm32;
9080 EmulateInstruction::Context context;
9081 context.type = EmulateInstruction::eContextImmediate;
9082 context.SetNoArgs();
9084 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
9090 // Bitwise OR (register) performs a bitwise (inclusive) OR of a register value
9091 // and an optionally-shifted register value, and writes the result to the
9092 // destination register. It can optionally update the condition flags based on
9094 bool EmulateInstructionARM::EmulateORRReg(const uint32_t opcode,
9095 const ARMEncoding encoding) {
9097 // ARM pseudo code...
9098 if ConditionPassed() then
9099 EncodingSpecificOperations();
9100 (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C);
9101 result = R[n] OR shifted;
9102 if d == 15 then // Can only occur for ARM encoding
9103 ALUWritePC(result); // setflags is always FALSE here
9107 APSR.N = result<31>;
9108 APSR.Z = IsZeroBit(result);
9113 bool success = false;
9115 if (ConditionPassed(opcode)) {
9116 uint32_t Rd, Rn, Rm;
9117 ARM_ShifterType shift_t;
9118 uint32_t shift_n; // the shift applied to the value read from Rm
9123 Rd = Rn = Bits32(opcode, 2, 0);
9124 Rm = Bits32(opcode, 5, 3);
9125 setflags = !InITBlock();
9126 shift_t = SRType_LSL;
9130 Rd = Bits32(opcode, 11, 8);
9131 Rn = Bits32(opcode, 19, 16);
9132 Rm = Bits32(opcode, 3, 0);
9133 setflags = BitIsSet(opcode, 20);
9134 shift_n = DecodeImmShiftThumb(opcode, shift_t);
9135 // if Rn == '1111' then SEE MOV (register);
9137 return EmulateMOVRdRm(opcode, eEncodingT3);
9138 if (BadReg(Rd) || Rn == 13 || BadReg(Rm))
9142 Rd = Bits32(opcode, 15, 12);
9143 Rn = Bits32(opcode, 19, 16);
9144 Rm = Bits32(opcode, 3, 0);
9145 setflags = BitIsSet(opcode, 20);
9146 shift_n = DecodeImmShiftARM(opcode, shift_t);
9148 if (Rd == 15 && setflags)
9149 return EmulateSUBSPcLrEtc(opcode, encoding);
9155 // Read the first operand.
9156 uint32_t val1 = ReadCoreReg(Rn, &success);
9160 // Read the second operand.
9161 uint32_t val2 = ReadCoreReg(Rm, &success);
9165 uint32_t shifted = Shift_C(val2, shift_t, shift_n, APSR_C, carry, &success);
9168 uint32_t result = val1 | shifted;
9170 EmulateInstruction::Context context;
9171 context.type = EmulateInstruction::eContextImmediate;
9172 context.SetNoArgs();
9174 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
9180 // Reverse Subtract (immediate) subtracts a register value from an immediate
9181 // value, and writes the result to the destination register. It can optionally
9182 // update the condition flags based on the result.
9183 bool EmulateInstructionARM::EmulateRSBImm(const uint32_t opcode,
9184 const ARMEncoding encoding) {
9186 // ARM pseudo code...
9187 if ConditionPassed() then
9188 EncodingSpecificOperations();
9189 (result, carry, overflow) = AddWithCarry(NOT(R[n]), imm32, '1');
9190 if d == 15 then // Can only occur for ARM encoding
9191 ALUWritePC(result); // setflags is always FALSE here
9195 APSR.N = result<31>;
9196 APSR.Z = IsZeroBit(result);
9201 bool success = false;
9203 uint32_t Rd; // the destination register
9204 uint32_t Rn; // the first operand
9207 imm32; // the immediate value to be added to the value obtained from Rn
9210 Rd = Bits32(opcode, 2, 0);
9211 Rn = Bits32(opcode, 5, 3);
9212 setflags = !InITBlock();
9216 Rd = Bits32(opcode, 11, 8);
9217 Rn = Bits32(opcode, 19, 16);
9218 setflags = BitIsSet(opcode, 20);
9219 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8)
9220 if (BadReg(Rd) || BadReg(Rn))
9224 Rd = Bits32(opcode, 15, 12);
9225 Rn = Bits32(opcode, 19, 16);
9226 setflags = BitIsSet(opcode, 20);
9227 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
9229 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related
9231 if (Rd == 15 && setflags)
9232 return EmulateSUBSPcLrEtc(opcode, encoding);
9237 // Read the register value from the operand register Rn.
9238 uint32_t reg_val = ReadCoreReg(Rn, &success);
9242 AddWithCarryResult res = AddWithCarry(~reg_val, imm32, 1);
9244 EmulateInstruction::Context context;
9245 context.type = EmulateInstruction::eContextImmediate;
9246 context.SetNoArgs();
9248 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags,
9249 res.carry_out, res.overflow))
9255 // Reverse Subtract (register) subtracts a register value from an optionally-
9256 // shifted register value, and writes the result to the destination register.
9257 // It can optionally update the condition flags based on the result.
9258 bool EmulateInstructionARM::EmulateRSBReg(const uint32_t opcode,
9259 const ARMEncoding encoding) {
9261 // ARM pseudo code...
9262 if ConditionPassed() then
9263 EncodingSpecificOperations();
9264 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
9265 (result, carry, overflow) = AddWithCarry(NOT(R[n]), shifted, '1');
9266 if d == 15 then // Can only occur for ARM encoding
9267 ALUWritePC(result); // setflags is always FALSE here
9271 APSR.N = result<31>;
9272 APSR.Z = IsZeroBit(result);
9277 bool success = false;
9279 uint32_t Rd; // the destination register
9280 uint32_t Rn; // the first operand
9281 uint32_t Rm; // the second operand
9283 ARM_ShifterType shift_t;
9284 uint32_t shift_n; // the shift applied to the value read from Rm
9287 Rd = Bits32(opcode, 11, 8);
9288 Rn = Bits32(opcode, 19, 16);
9289 Rm = Bits32(opcode, 3, 0);
9290 setflags = BitIsSet(opcode, 20);
9291 shift_n = DecodeImmShiftThumb(opcode, shift_t);
9292 // if (BadReg(d) || BadReg(m)) then UNPREDICTABLE;
9293 if (BadReg(Rd) || BadReg(Rn) || BadReg(Rm))
9297 Rd = Bits32(opcode, 15, 12);
9298 Rn = Bits32(opcode, 19, 16);
9299 Rm = Bits32(opcode, 3, 0);
9300 setflags = BitIsSet(opcode, 20);
9301 shift_n = DecodeImmShiftARM(opcode, shift_t);
9303 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related
9305 if (Rd == 15 && setflags)
9306 return EmulateSUBSPcLrEtc(opcode, encoding);
9311 // Read the register value from register Rn.
9312 uint32_t val1 = ReadCoreReg(Rn, &success);
9316 // Read the register value from register Rm.
9317 uint32_t val2 = ReadCoreReg(Rm, &success);
9321 uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C, &success);
9324 AddWithCarryResult res = AddWithCarry(~val1, shifted, 1);
9326 EmulateInstruction::Context context;
9327 context.type = EmulateInstruction::eContextImmediate;
9328 context.SetNoArgs();
9329 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags,
9330 res.carry_out, res.overflow))
9336 // Reverse Subtract with Carry (immediate) subtracts a register value and the
9337 // value of NOT (Carry flag) from an immediate value, and writes the result to
9338 // the destination register. It can optionally update the condition flags based
9340 bool EmulateInstructionARM::EmulateRSCImm(const uint32_t opcode,
9341 const ARMEncoding encoding) {
9343 // ARM pseudo code...
9344 if ConditionPassed() then
9345 EncodingSpecificOperations();
9346 (result, carry, overflow) = AddWithCarry(NOT(R[n]), imm32, APSR.C);
9348 ALUWritePC(result); // setflags is always FALSE here
9352 APSR.N = result<31>;
9353 APSR.Z = IsZeroBit(result);
9358 bool success = false;
9360 uint32_t Rd; // the destination register
9361 uint32_t Rn; // the first operand
9364 imm32; // the immediate value to be added to the value obtained from Rn
9367 Rd = Bits32(opcode, 15, 12);
9368 Rn = Bits32(opcode, 19, 16);
9369 setflags = BitIsSet(opcode, 20);
9370 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
9372 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related
9374 if (Rd == 15 && setflags)
9375 return EmulateSUBSPcLrEtc(opcode, encoding);
9380 // Read the register value from the operand register Rn.
9381 uint32_t reg_val = ReadCoreReg(Rn, &success);
9385 AddWithCarryResult res = AddWithCarry(~reg_val, imm32, APSR_C);
9387 EmulateInstruction::Context context;
9388 context.type = EmulateInstruction::eContextImmediate;
9389 context.SetNoArgs();
9391 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags,
9392 res.carry_out, res.overflow))
9398 // Reverse Subtract with Carry (register) subtracts a register value and the
9399 // value of NOT (Carry flag) from an optionally-shifted register value, and
9400 // writes the result to the destination register. It can optionally update the
9401 // condition flags based on the result.
9402 bool EmulateInstructionARM::EmulateRSCReg(const uint32_t opcode,
9403 const ARMEncoding encoding) {
9405 // ARM pseudo code...
9406 if ConditionPassed() then
9407 EncodingSpecificOperations();
9408 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
9409 (result, carry, overflow) = AddWithCarry(NOT(R[n]), shifted, APSR.C);
9411 ALUWritePC(result); // setflags is always FALSE here
9415 APSR.N = result<31>;
9416 APSR.Z = IsZeroBit(result);
9421 bool success = false;
9423 uint32_t Rd; // the destination register
9424 uint32_t Rn; // the first operand
9425 uint32_t Rm; // the second operand
9427 ARM_ShifterType shift_t;
9428 uint32_t shift_n; // the shift applied to the value read from Rm
9431 Rd = Bits32(opcode, 15, 12);
9432 Rn = Bits32(opcode, 19, 16);
9433 Rm = Bits32(opcode, 3, 0);
9434 setflags = BitIsSet(opcode, 20);
9435 shift_n = DecodeImmShiftARM(opcode, shift_t);
9437 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related
9439 if (Rd == 15 && setflags)
9440 return EmulateSUBSPcLrEtc(opcode, encoding);
9445 // Read the register value from register Rn.
9446 uint32_t val1 = ReadCoreReg(Rn, &success);
9450 // Read the register value from register Rm.
9451 uint32_t val2 = ReadCoreReg(Rm, &success);
9455 uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C, &success);
9458 AddWithCarryResult res = AddWithCarry(~val1, shifted, APSR_C);
9460 EmulateInstruction::Context context;
9461 context.type = EmulateInstruction::eContextImmediate;
9462 context.SetNoArgs();
9463 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags,
9464 res.carry_out, res.overflow))
9470 // Subtract with Carry (immediate) subtracts an immediate value and the value
9472 // NOT (Carry flag) from a register value, and writes the result to the
9473 // destination register.
9474 // It can optionally update the condition flags based on the result.
9475 bool EmulateInstructionARM::EmulateSBCImm(const uint32_t opcode,
9476 const ARMEncoding encoding) {
9478 // ARM pseudo code...
9479 if ConditionPassed() then
9480 EncodingSpecificOperations();
9481 (result, carry, overflow) = AddWithCarry(R[n], NOT(imm32), APSR.C);
9482 if d == 15 then // Can only occur for ARM encoding
9483 ALUWritePC(result); // setflags is always FALSE here
9487 APSR.N = result<31>;
9488 APSR.Z = IsZeroBit(result);
9493 bool success = false;
9495 uint32_t Rd; // the destination register
9496 uint32_t Rn; // the first operand
9499 imm32; // the immediate value to be added to the value obtained from Rn
9502 Rd = Bits32(opcode, 11, 8);
9503 Rn = Bits32(opcode, 19, 16);
9504 setflags = BitIsSet(opcode, 20);
9505 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8)
9506 if (BadReg(Rd) || BadReg(Rn))
9510 Rd = Bits32(opcode, 15, 12);
9511 Rn = Bits32(opcode, 19, 16);
9512 setflags = BitIsSet(opcode, 20);
9513 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
9515 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related
9517 if (Rd == 15 && setflags)
9518 return EmulateSUBSPcLrEtc(opcode, encoding);
9523 // Read the register value from the operand register Rn.
9524 uint32_t reg_val = ReadCoreReg(Rn, &success);
9528 AddWithCarryResult res = AddWithCarry(reg_val, ~imm32, APSR_C);
9530 EmulateInstruction::Context context;
9531 context.type = EmulateInstruction::eContextImmediate;
9532 context.SetNoArgs();
9534 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags,
9535 res.carry_out, res.overflow))
9541 // Subtract with Carry (register) subtracts an optionally-shifted register
9542 // value and the value of
9543 // NOT (Carry flag) from a register value, and writes the result to the
9544 // destination register.
9545 // It can optionally update the condition flags based on the result.
9546 bool EmulateInstructionARM::EmulateSBCReg(const uint32_t opcode,
9547 const ARMEncoding encoding) {
9549 // ARM pseudo code...
9550 if ConditionPassed() then
9551 EncodingSpecificOperations();
9552 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
9553 (result, carry, overflow) = AddWithCarry(R[n], NOT(shifted), APSR.C);
9554 if d == 15 then // Can only occur for ARM encoding
9555 ALUWritePC(result); // setflags is always FALSE here
9559 APSR.N = result<31>;
9560 APSR.Z = IsZeroBit(result);
9565 bool success = false;
9567 uint32_t Rd; // the destination register
9568 uint32_t Rn; // the first operand
9569 uint32_t Rm; // the second operand
9571 ARM_ShifterType shift_t;
9572 uint32_t shift_n; // the shift applied to the value read from Rm
9575 Rd = Rn = Bits32(opcode, 2, 0);
9576 Rm = Bits32(opcode, 5, 3);
9577 setflags = !InITBlock();
9578 shift_t = SRType_LSL;
9582 Rd = Bits32(opcode, 11, 8);
9583 Rn = Bits32(opcode, 19, 16);
9584 Rm = Bits32(opcode, 3, 0);
9585 setflags = BitIsSet(opcode, 20);
9586 shift_n = DecodeImmShiftThumb(opcode, shift_t);
9587 if (BadReg(Rd) || BadReg(Rn) || BadReg(Rm))
9591 Rd = Bits32(opcode, 15, 12);
9592 Rn = Bits32(opcode, 19, 16);
9593 Rm = Bits32(opcode, 3, 0);
9594 setflags = BitIsSet(opcode, 20);
9595 shift_n = DecodeImmShiftARM(opcode, shift_t);
9597 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related
9599 if (Rd == 15 && setflags)
9600 return EmulateSUBSPcLrEtc(opcode, encoding);
9605 // Read the register value from register Rn.
9606 uint32_t val1 = ReadCoreReg(Rn, &success);
9610 // Read the register value from register Rm.
9611 uint32_t val2 = ReadCoreReg(Rm, &success);
9615 uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C, &success);
9618 AddWithCarryResult res = AddWithCarry(val1, ~shifted, APSR_C);
9620 EmulateInstruction::Context context;
9621 context.type = EmulateInstruction::eContextImmediate;
9622 context.SetNoArgs();
9623 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags,
9624 res.carry_out, res.overflow))
9630 // This instruction subtracts an immediate value from a register value, and
9631 // writes the result to the destination register. It can optionally update the
9632 // condition flags based on the result.
9633 bool EmulateInstructionARM::EmulateSUBImmThumb(const uint32_t opcode,
9634 const ARMEncoding encoding) {
9636 // ARM pseudo code...
9637 if ConditionPassed() then
9638 EncodingSpecificOperations();
9639 (result, carry, overflow) = AddWithCarry(R[n], NOT(imm32), '1');
9642 APSR.N = result<31>;
9643 APSR.Z = IsZeroBit(result);
9648 bool success = false;
9650 uint32_t Rd; // the destination register
9651 uint32_t Rn; // the first operand
9653 uint32_t imm32; // the immediate value to be subtracted from the value
9657 Rd = Bits32(opcode, 2, 0);
9658 Rn = Bits32(opcode, 5, 3);
9659 setflags = !InITBlock();
9660 imm32 = Bits32(opcode, 8, 6); // imm32 = ZeroExtend(imm3, 32)
9663 Rd = Rn = Bits32(opcode, 10, 8);
9664 setflags = !InITBlock();
9665 imm32 = Bits32(opcode, 7, 0); // imm32 = ZeroExtend(imm8, 32)
9668 Rd = Bits32(opcode, 11, 8);
9669 Rn = Bits32(opcode, 19, 16);
9670 setflags = BitIsSet(opcode, 20);
9671 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8)
9673 // if Rd == '1111' && S == '1' then SEE CMP (immediate);
9674 if (Rd == 15 && setflags)
9675 return EmulateCMPImm(opcode, eEncodingT2);
9677 // if Rn == '1101' then SEE SUB (SP minus immediate);
9679 return EmulateSUBSPImm(opcode, eEncodingT2);
9681 // if d == 13 || (d == 15 && S == '0') || n == 15 then UNPREDICTABLE;
9682 if (Rd == 13 || (Rd == 15 && !setflags) || Rn == 15)
9686 Rd = Bits32(opcode, 11, 8);
9687 Rn = Bits32(opcode, 19, 16);
9688 setflags = BitIsSet(opcode, 20);
9689 imm32 = ThumbImm12(opcode); // imm32 = ZeroExtend(i:imm3:imm8, 32)
9691 // if Rn == '1111' then SEE ADR;
9693 return EmulateADR(opcode, eEncodingT2);
9695 // if Rn == '1101' then SEE SUB (SP minus immediate);
9697 return EmulateSUBSPImm(opcode, eEncodingT3);
9705 // Read the register value from the operand register Rn.
9706 uint32_t reg_val = ReadCoreReg(Rn, &success);
9710 AddWithCarryResult res = AddWithCarry(reg_val, ~imm32, 1);
9712 EmulateInstruction::Context context;
9713 context.type = EmulateInstruction::eContextImmediate;
9714 context.SetNoArgs();
9716 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags,
9717 res.carry_out, res.overflow))
9723 // This instruction subtracts an immediate value from a register value, and
9724 // writes the result to the destination register. It can optionally update the
9725 // condition flags based on the result.
9726 bool EmulateInstructionARM::EmulateSUBImmARM(const uint32_t opcode,
9727 const ARMEncoding encoding) {
9729 // ARM pseudo code...
9730 if ConditionPassed() then
9731 EncodingSpecificOperations();
9732 (result, carry, overflow) = AddWithCarry(R[n], NOT(imm32), '1');
9734 ALUWritePC(result); // setflags is always FALSE here
9738 APSR.N = result<31>;
9739 APSR.Z = IsZeroBit(result);
9744 bool success = false;
9746 if (ConditionPassed(opcode)) {
9747 uint32_t Rd; // the destination register
9748 uint32_t Rn; // the first operand
9750 uint32_t imm32; // the immediate value to be subtracted from the value
9754 Rd = Bits32(opcode, 15, 12);
9755 Rn = Bits32(opcode, 19, 16);
9756 setflags = BitIsSet(opcode, 20);
9757 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
9759 // if Rn == '1111' && S == '0' then SEE ADR;
9760 if (Rn == 15 && !setflags)
9761 return EmulateADR(opcode, eEncodingA2);
9763 // if Rn == '1101' then SEE SUB (SP minus immediate);
9765 return EmulateSUBSPImm(opcode, eEncodingA1);
9767 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related
9769 if (Rd == 15 && setflags)
9770 return EmulateSUBSPcLrEtc(opcode, encoding);
9775 // Read the register value from the operand register Rn.
9776 uint32_t reg_val = ReadCoreReg(Rn, &success);
9780 AddWithCarryResult res = AddWithCarry(reg_val, ~imm32, 1);
9782 EmulateInstruction::Context context;
9784 context.type = EmulateInstruction::eContextAdjustStackPointer;
9786 context.type = EmulateInstruction::eContextRegisterPlusOffset;
9788 RegisterInfo dwarf_reg;
9789 GetRegisterInfo(eRegisterKindDWARF, Rn, dwarf_reg);
9790 int64_t imm32_signed = imm32;
9791 context.SetRegisterPlusOffset(dwarf_reg, -imm32_signed);
9793 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags,
9794 res.carry_out, res.overflow))
9800 // Test Equivalence (immediate) performs a bitwise exclusive OR operation on a
9801 // register value and an immediate value. It updates the condition flags based
9802 // on the result, and discards the result.
9803 bool EmulateInstructionARM::EmulateTEQImm(const uint32_t opcode,
9804 const ARMEncoding encoding) {
9806 // ARM pseudo code...
9807 if ConditionPassed() then
9808 EncodingSpecificOperations();
9809 result = R[n] EOR imm32;
9810 APSR.N = result<31>;
9811 APSR.Z = IsZeroBit(result);
9816 bool success = false;
9818 if (ConditionPassed(opcode)) {
9821 imm32; // the immediate value to be ANDed to the value obtained from Rn
9822 uint32_t carry; // the carry bit after ARM/Thumb Expand operation
9825 Rn = Bits32(opcode, 19, 16);
9826 imm32 = ThumbExpandImm_C(
9828 carry); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C)
9833 Rn = Bits32(opcode, 19, 16);
9835 ARMExpandImm_C(opcode, APSR_C,
9836 carry); // (imm32, carry) = ARMExpandImm(imm12, APSR.C)
9842 // Read the first operand.
9843 uint32_t val1 = ReadCoreReg(Rn, &success);
9847 uint32_t result = val1 ^ imm32;
9849 EmulateInstruction::Context context;
9850 context.type = EmulateInstruction::eContextImmediate;
9851 context.SetNoArgs();
9853 if (!WriteFlags(context, result, carry))
9859 // Test Equivalence (register) performs a bitwise exclusive OR operation on a
9860 // register value and an optionally-shifted register value. It updates the
9861 // condition flags based on the result, and discards the result.
9862 bool EmulateInstructionARM::EmulateTEQReg(const uint32_t opcode,
9863 const ARMEncoding encoding) {
9865 // ARM pseudo code...
9866 if ConditionPassed() then
9867 EncodingSpecificOperations();
9868 (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C);
9869 result = R[n] EOR shifted;
9870 APSR.N = result<31>;
9871 APSR.Z = IsZeroBit(result);
9876 bool success = false;
9878 if (ConditionPassed(opcode)) {
9880 ARM_ShifterType shift_t;
9881 uint32_t shift_n; // the shift applied to the value read from Rm
9885 Rn = Bits32(opcode, 19, 16);
9886 Rm = Bits32(opcode, 3, 0);
9887 shift_n = DecodeImmShiftThumb(opcode, shift_t);
9888 if (BadReg(Rn) || BadReg(Rm))
9892 Rn = Bits32(opcode, 19, 16);
9893 Rm = Bits32(opcode, 3, 0);
9894 shift_n = DecodeImmShiftARM(opcode, shift_t);
9900 // Read the first operand.
9901 uint32_t val1 = ReadCoreReg(Rn, &success);
9905 // Read the second operand.
9906 uint32_t val2 = ReadCoreReg(Rm, &success);
9910 uint32_t shifted = Shift_C(val2, shift_t, shift_n, APSR_C, carry, &success);
9913 uint32_t result = val1 ^ shifted;
9915 EmulateInstruction::Context context;
9916 context.type = EmulateInstruction::eContextImmediate;
9917 context.SetNoArgs();
9919 if (!WriteFlags(context, result, carry))
9925 // Test (immediate) performs a bitwise AND operation on a register value and an
9926 // immediate value. It updates the condition flags based on the result, and
9927 // discards the result.
9928 bool EmulateInstructionARM::EmulateTSTImm(const uint32_t opcode,
9929 const ARMEncoding encoding) {
9931 // ARM pseudo code...
9932 if ConditionPassed() then
9933 EncodingSpecificOperations();
9934 result = R[n] AND imm32;
9935 APSR.N = result<31>;
9936 APSR.Z = IsZeroBit(result);
9941 bool success = false;
9943 if (ConditionPassed(opcode)) {
9946 imm32; // the immediate value to be ANDed to the value obtained from Rn
9947 uint32_t carry; // the carry bit after ARM/Thumb Expand operation
9950 Rn = Bits32(opcode, 19, 16);
9951 imm32 = ThumbExpandImm_C(
9953 carry); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C)
9958 Rn = Bits32(opcode, 19, 16);
9960 ARMExpandImm_C(opcode, APSR_C,
9961 carry); // (imm32, carry) = ARMExpandImm(imm12, APSR.C)
9967 // Read the first operand.
9968 uint32_t val1 = ReadCoreReg(Rn, &success);
9972 uint32_t result = val1 & imm32;
9974 EmulateInstruction::Context context;
9975 context.type = EmulateInstruction::eContextImmediate;
9976 context.SetNoArgs();
9978 if (!WriteFlags(context, result, carry))
9984 // Test (register) performs a bitwise AND operation on a register value and an
9985 // optionally-shifted register value. It updates the condition flags based on
9986 // the result, and discards the result.
9987 bool EmulateInstructionARM::EmulateTSTReg(const uint32_t opcode,
9988 const ARMEncoding encoding) {
9990 // ARM pseudo code...
9991 if ConditionPassed() then
9992 EncodingSpecificOperations();
9993 (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C);
9994 result = R[n] AND shifted;
9995 APSR.N = result<31>;
9996 APSR.Z = IsZeroBit(result);
10001 bool success = false;
10003 if (ConditionPassed(opcode)) {
10005 ARM_ShifterType shift_t;
10006 uint32_t shift_n; // the shift applied to the value read from Rm
10008 switch (encoding) {
10010 Rn = Bits32(opcode, 2, 0);
10011 Rm = Bits32(opcode, 5, 3);
10012 shift_t = SRType_LSL;
10016 Rn = Bits32(opcode, 19, 16);
10017 Rm = Bits32(opcode, 3, 0);
10018 shift_n = DecodeImmShiftThumb(opcode, shift_t);
10019 if (BadReg(Rn) || BadReg(Rm))
10023 Rn = Bits32(opcode, 19, 16);
10024 Rm = Bits32(opcode, 3, 0);
10025 shift_n = DecodeImmShiftARM(opcode, shift_t);
10031 // Read the first operand.
10032 uint32_t val1 = ReadCoreReg(Rn, &success);
10036 // Read the second operand.
10037 uint32_t val2 = ReadCoreReg(Rm, &success);
10041 uint32_t shifted = Shift_C(val2, shift_t, shift_n, APSR_C, carry, &success);
10044 uint32_t result = val1 & shifted;
10046 EmulateInstruction::Context context;
10047 context.type = EmulateInstruction::eContextImmediate;
10048 context.SetNoArgs();
10050 if (!WriteFlags(context, result, carry))
10056 // A8.6.216 SUB (SP minus register)
10057 bool EmulateInstructionARM::EmulateSUBSPReg(const uint32_t opcode,
10058 const ARMEncoding encoding) {
10060 if ConditionPassed() then
10061 EncodingSpecificOperations();
10062 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
10063 (result, carry, overflow) = AddWithCarry(SP, NOT(shifted), '1');
10064 if d == 15 then // Can only occur for ARM encoding
10065 ALUWritePC(result); // setflags is always FALSE here
10069 APSR.N = result<31>;
10070 APSR.Z = IsZeroBit(result);
10075 bool success = false;
10077 if (ConditionPassed(opcode)) {
10081 ARM_ShifterType shift_t;
10084 switch (encoding) {
10086 // d = UInt(Rd); m = UInt(Rm); setflags = (S == '1');
10087 d = Bits32(opcode, 11, 8);
10088 m = Bits32(opcode, 3, 0);
10089 setflags = BitIsSet(opcode, 20);
10091 // (shift_t, shift_n) = DecodeImmShift(type, imm3:imm2);
10092 shift_n = DecodeImmShiftThumb(opcode, shift_t);
10094 // if d == 13 && (shift_t != SRType_LSL || shift_n > 3) then
10096 if ((d == 13) && ((shift_t != SRType_LSL) || (shift_n > 3)))
10099 // if d == 15 || BadReg(m) then UNPREDICTABLE;
10100 if ((d == 15) || BadReg(m))
10105 // d = UInt(Rd); m = UInt(Rm); setflags = (S == '1');
10106 d = Bits32(opcode, 15, 12);
10107 m = Bits32(opcode, 3, 0);
10108 setflags = BitIsSet(opcode, 20);
10110 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related
10112 if (d == 15 && setflags)
10113 EmulateSUBSPcLrEtc(opcode, encoding);
10115 // (shift_t, shift_n) = DecodeImmShift(type, imm5);
10116 shift_n = DecodeImmShiftARM(opcode, shift_t);
10123 // shifted = Shift(R[m], shift_t, shift_n, APSR.C);
10124 uint32_t Rm = ReadCoreReg(m, &success);
10128 uint32_t shifted = Shift(Rm, shift_t, shift_n, APSR_C, &success);
10132 // (result, carry, overflow) = AddWithCarry(SP, NOT(shifted), '1');
10133 uint32_t sp_val = ReadCoreReg(SP_REG, &success);
10137 AddWithCarryResult res = AddWithCarry(sp_val, ~shifted, 1);
10139 EmulateInstruction::Context context;
10140 context.type = eContextArithmetic;
10141 RegisterInfo sp_reg;
10142 GetRegisterInfo(eRegisterKindDWARF, dwarf_sp, sp_reg);
10143 RegisterInfo dwarf_reg;
10144 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + m, dwarf_reg);
10145 context.SetRegisterRegisterOperands(sp_reg, dwarf_reg);
10147 if (!WriteCoreRegOptionalFlags(context, res.result, dwarf_r0 + d, setflags,
10148 res.carry_out, res.overflow))
10154 // A8.6.7 ADD (register-shifted register)
10155 bool EmulateInstructionARM::EmulateADDRegShift(const uint32_t opcode,
10156 const ARMEncoding encoding) {
10158 if ConditionPassed() then
10159 EncodingSpecificOperations();
10160 shift_n = UInt(R[s]<7:0>);
10161 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
10162 (result, carry, overflow) = AddWithCarry(R[n], shifted, '0');
10165 APSR.N = result<31>;
10166 APSR.Z = IsZeroBit(result);
10171 bool success = false;
10173 if (ConditionPassed(opcode)) {
10179 ARM_ShifterType shift_t;
10181 switch (encoding) {
10183 // d = UInt(Rd); n = UInt(Rn); m = UInt(Rm); s = UInt(Rs);
10184 d = Bits32(opcode, 15, 12);
10185 n = Bits32(opcode, 19, 16);
10186 m = Bits32(opcode, 3, 0);
10187 s = Bits32(opcode, 11, 8);
10189 // setflags = (S == '1'); shift_t = DecodeRegShift(type);
10190 setflags = BitIsSet(opcode, 20);
10191 shift_t = DecodeRegShift(Bits32(opcode, 6, 5));
10193 // if d == 15 || n == 15 || m == 15 || s == 15 then UNPREDICTABLE;
10194 if ((d == 15) || (m == 15) || (m == 15) || (s == 15))
10202 // shift_n = UInt(R[s]<7:0>);
10203 uint32_t Rs = ReadCoreReg(s, &success);
10207 uint32_t shift_n = Bits32(Rs, 7, 0);
10209 // shifted = Shift(R[m], shift_t, shift_n, APSR.C);
10210 uint32_t Rm = ReadCoreReg(m, &success);
10214 uint32_t shifted = Shift(Rm, shift_t, shift_n, APSR_C, &success);
10218 // (result, carry, overflow) = AddWithCarry(R[n], shifted, '0');
10219 uint32_t Rn = ReadCoreReg(n, &success);
10223 AddWithCarryResult res = AddWithCarry(Rn, shifted, 0);
10226 EmulateInstruction::Context context;
10227 context.type = eContextArithmetic;
10228 RegisterInfo reg_n;
10229 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n, reg_n);
10230 RegisterInfo reg_m;
10231 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + m, reg_m);
10233 context.SetRegisterRegisterOperands(reg_n, reg_m);
10235 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + d,
10239 // if setflags then
10240 // APSR.N = result<31>;
10241 // APSR.Z = IsZeroBit(result);
10243 // APSR.V = overflow;
10245 return WriteFlags(context, res.result, res.carry_out, res.overflow);
10250 // A8.6.213 SUB (register)
10251 bool EmulateInstructionARM::EmulateSUBReg(const uint32_t opcode,
10252 const ARMEncoding encoding) {
10254 if ConditionPassed() then
10255 EncodingSpecificOperations();
10256 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
10257 (result, carry, overflow) = AddWithCarry(R[n], NOT(shifted), '1');
10258 if d == 15 then // Can only occur for ARM encoding
10259 ALUWritePC(result); // setflags is always FALSE here
10263 APSR.N = result<31>;
10264 APSR.Z = IsZeroBit(result);
10269 bool success = false;
10271 if (ConditionPassed(opcode)) {
10276 ARM_ShifterType shift_t;
10279 switch (encoding) {
10281 // d = UInt(Rd); n = UInt(Rn); m = UInt(Rm); setflags = !InITBlock();
10282 d = Bits32(opcode, 2, 0);
10283 n = Bits32(opcode, 5, 3);
10284 m = Bits32(opcode, 8, 6);
10285 setflags = !InITBlock();
10287 // (shift_t, shift_n) = (SRType_LSL, 0);
10288 shift_t = SRType_LSL;
10294 // d = UInt(Rd); n = UInt(Rn); m = UInt(Rm); setflags = (S =="1");
10295 d = Bits32(opcode, 11, 8);
10296 n = Bits32(opcode, 19, 16);
10297 m = Bits32(opcode, 3, 0);
10298 setflags = BitIsSet(opcode, 20);
10300 // if Rd == "1111" && S == "1" then SEE CMP (register);
10301 if (d == 15 && setflags == 1)
10302 return EmulateCMPImm(opcode, eEncodingT3);
10304 // if Rn == "1101" then SEE SUB (SP minus register);
10306 return EmulateSUBSPReg(opcode, eEncodingT1);
10308 // (shift_t, shift_n) = DecodeImmShift(type, imm3:imm2);
10309 shift_n = DecodeImmShiftThumb(opcode, shift_t);
10311 // if d == 13 || (d == 15 && S == '0') || n == 15 || BadReg(m) then
10313 if ((d == 13) || ((d == 15) && BitIsClear(opcode, 20)) || (n == 15) ||
10320 // if Rn == '1101' then SEE SUB (SP minus register);
10321 // d = UInt(Rd); n = UInt(Rn); m = UInt(Rm); setflags = (S == '1');
10322 d = Bits32(opcode, 15, 12);
10323 n = Bits32(opcode, 19, 16);
10324 m = Bits32(opcode, 3, 0);
10325 setflags = BitIsSet(opcode, 20);
10327 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related
10329 if ((d == 15) && setflags)
10330 EmulateSUBSPcLrEtc(opcode, encoding);
10332 // (shift_t, shift_n) = DecodeImmShift(type, imm5);
10333 shift_n = DecodeImmShiftARM(opcode, shift_t);
10341 // shifted = Shift(R[m], shift_t, shift_n, APSR.C);
10342 uint32_t Rm = ReadCoreReg(m, &success);
10346 uint32_t shifted = Shift(Rm, shift_t, shift_n, APSR_C, &success);
10350 // (result, carry, overflow) = AddWithCarry(R[n], NOT(shifted), '1');
10351 uint32_t Rn = ReadCoreReg(n, &success);
10355 AddWithCarryResult res = AddWithCarry(Rn, ~shifted, 1);
10357 // if d == 15 then // Can only occur for ARM encoding ALUWritePC(result);
10358 // // setflags is always FALSE here else
10360 // if setflags then
10361 // APSR.N = result<31>;
10362 // APSR.Z = IsZeroBit(result);
10364 // APSR.V = overflow;
10366 EmulateInstruction::Context context;
10367 context.type = eContextArithmetic;
10368 RegisterInfo reg_n;
10369 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n, reg_n);
10370 RegisterInfo reg_m;
10371 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + m, reg_m);
10372 context.SetRegisterRegisterOperands(reg_n, reg_m);
10374 if (!WriteCoreRegOptionalFlags(context, res.result, dwarf_r0 + d, setflags,
10375 res.carry_out, res.overflow))
10382 // Store Register Exclusive calculates an address from a base register value
10383 // and an immediate offset, and stores a word from a register to memory if the
10384 // executing processor has exclusive access to the memory addressed.
10385 bool EmulateInstructionARM::EmulateSTREX(const uint32_t opcode,
10386 const ARMEncoding encoding) {
10388 if ConditionPassed() then
10389 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
10390 address = R[n] + imm32;
10391 if ExclusiveMonitorsPass(address,4) then
10392 MemA[address,4] = R[t];
10398 bool success = false;
10400 if (ConditionPassed(opcode)) {
10405 const uint32_t addr_byte_size = GetAddressByteSize();
10407 switch (encoding) {
10409 // d = UInt(Rd); t = UInt(Rt); n = UInt(Rn); imm32 =
10410 // ZeroExtend(imm8:'00',
10412 d = Bits32(opcode, 11, 8);
10413 t = Bits32(opcode, 15, 12);
10414 n = Bits32(opcode, 19, 16);
10415 imm32 = Bits32(opcode, 7, 0) << 2;
10417 // if BadReg(d) || BadReg(t) || n == 15 then UNPREDICTABLE;
10418 if (BadReg(d) || BadReg(t) || (n == 15))
10421 // if d == n || d == t then UNPREDICTABLE;
10422 if ((d == n) || (d == t))
10428 // d = UInt(Rd); t = UInt(Rt); n = UInt(Rn); imm32 = Zeros(32); // Zero
10430 d = Bits32(opcode, 15, 12);
10431 t = Bits32(opcode, 3, 0);
10432 n = Bits32(opcode, 19, 16);
10435 // if d == 15 || t == 15 || n == 15 then UNPREDICTABLE;
10436 if ((d == 15) || (t == 15) || (n == 15))
10439 // if d == n || d == t then UNPREDICTABLE;
10440 if ((d == n) || (d == t))
10449 // address = R[n] + imm32;
10450 uint32_t Rn = ReadCoreReg(n, &success);
10454 addr_t address = Rn + imm32;
10456 RegisterInfo base_reg;
10457 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n, base_reg);
10458 RegisterInfo data_reg;
10459 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + t, data_reg);
10460 EmulateInstruction::Context context;
10461 context.type = eContextRegisterStore;
10462 context.SetRegisterToRegisterPlusOffset(data_reg, base_reg, imm32);
10464 // if ExclusiveMonitorsPass(address,4) then if (ExclusiveMonitorsPass
10465 // (address, addr_byte_size)) -- For now, for the sake of emulation, we
10470 // MemA[address,4] = R[t];
10472 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + t, 0, &success);
10476 if (!MemAWrite(context, address, Rt, addr_byte_size))
10480 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + t, 0))
10483 #if 0 // unreachable because if true
10487 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, 1))
10490 #endif // unreachable because if true
10495 // A8.6.197 STRB (immediate, ARM)
10496 bool EmulateInstructionARM::EmulateSTRBImmARM(const uint32_t opcode,
10497 const ARMEncoding encoding) {
10499 if ConditionPassed() then
10500 EncodingSpecificOperations();
10501 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
10502 address = if index then offset_addr else R[n];
10503 MemU[address,1] = R[t]<7:0>;
10504 if wback then R[n] = offset_addr;
10507 bool success = false;
10509 if (ConditionPassed(opcode)) {
10517 switch (encoding) {
10519 // if P == '0' && W == '1' then SEE STRBT;
10520 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
10521 t = Bits32(opcode, 15, 12);
10522 n = Bits32(opcode, 19, 16);
10523 imm32 = Bits32(opcode, 11, 0);
10525 // index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1');
10526 index = BitIsSet(opcode, 24);
10527 add = BitIsSet(opcode, 23);
10528 wback = BitIsClear(opcode, 24) || BitIsSet(opcode, 21);
10530 // if t == 15 then UNPREDICTABLE;
10534 // if wback && (n == 15 || n == t) then UNPREDICTABLE;
10535 if (wback && ((n == 15) || (n == t)))
10544 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
10545 uint32_t Rn = ReadCoreReg(n, &success);
10549 addr_t offset_addr;
10551 offset_addr = Rn + imm32;
10553 offset_addr = Rn - imm32;
10555 // address = if index then offset_addr else R[n];
10558 address = offset_addr;
10562 // MemU[address,1] = R[t]<7:0>;
10563 uint32_t Rt = ReadCoreReg(t, &success);
10567 RegisterInfo base_reg;
10568 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n, base_reg);
10569 RegisterInfo data_reg;
10570 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + t, data_reg);
10571 EmulateInstruction::Context context;
10572 context.type = eContextRegisterStore;
10573 context.SetRegisterToRegisterPlusOffset(data_reg, base_reg, address - Rn);
10575 if (!MemUWrite(context, address, Bits32(Rt, 7, 0), 1))
10578 // if wback then R[n] = offset_addr;
10580 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n,
10588 // A8.6.194 STR (immediate, ARM)
10589 bool EmulateInstructionARM::EmulateSTRImmARM(const uint32_t opcode,
10590 const ARMEncoding encoding) {
10592 if ConditionPassed() then
10593 EncodingSpecificOperations();
10594 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
10595 address = if index then offset_addr else R[n];
10596 MemU[address,4] = if t == 15 then PCStoreValue() else R[t];
10597 if wback then R[n] = offset_addr;
10600 bool success = false;
10602 if (ConditionPassed(opcode)) {
10610 const uint32_t addr_byte_size = GetAddressByteSize();
10612 switch (encoding) {
10614 // if P == '0' && W == '1' then SEE STRT;
10615 // if Rn == '1101' && P == '1' && U == '0' && W == '1' && imm12 ==
10616 // '000000000100' then SEE PUSH;
10617 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
10618 t = Bits32(opcode, 15, 12);
10619 n = Bits32(opcode, 19, 16);
10620 imm32 = Bits32(opcode, 11, 0);
10622 // index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1');
10623 index = BitIsSet(opcode, 24);
10624 add = BitIsSet(opcode, 23);
10625 wback = BitIsClear(opcode, 24) || BitIsSet(opcode, 21);
10627 // if wback && (n == 15 || n == t) then UNPREDICTABLE;
10628 if (wback && ((n == 15) || (n == t)))
10637 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
10638 uint32_t Rn = ReadCoreReg(n, &success);
10642 addr_t offset_addr;
10644 offset_addr = Rn + imm32;
10646 offset_addr = Rn - imm32;
10648 // address = if index then offset_addr else R[n];
10651 address = offset_addr;
10655 RegisterInfo base_reg;
10656 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n, base_reg);
10657 RegisterInfo data_reg;
10658 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + t, data_reg);
10659 EmulateInstruction::Context context;
10660 context.type = eContextRegisterStore;
10661 context.SetRegisterToRegisterPlusOffset(data_reg, base_reg, address - Rn);
10663 // MemU[address,4] = if t == 15 then PCStoreValue() else R[t];
10664 uint32_t Rt = ReadCoreReg(t, &success);
10669 uint32_t pc_value = ReadCoreReg(PC_REG, &success);
10673 if (!MemUWrite(context, address, pc_value, addr_byte_size))
10676 if (!MemUWrite(context, address, Rt, addr_byte_size))
10680 // if wback then R[n] = offset_addr;
10682 context.type = eContextAdjustBaseRegister;
10683 context.SetImmediate(offset_addr);
10685 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n,
10693 // A8.6.66 LDRD (immediate)
10694 // Load Register Dual (immediate) calculates an address from a base register
10695 // value and an immediate offset, loads two words from memory, and writes them
10696 // to two registers. It can use offset, post-indexed, or pre-indexed
10698 bool EmulateInstructionARM::EmulateLDRDImmediate(const uint32_t opcode,
10699 const ARMEncoding encoding) {
10701 if ConditionPassed() then
10702 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
10703 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
10704 address = if index then offset_addr else R[n];
10705 R[t] = MemA[address,4];
10706 R[t2] = MemA[address+4,4];
10707 if wback then R[n] = offset_addr;
10710 bool success = false;
10712 if (ConditionPassed(opcode)) {
10721 switch (encoding) {
10723 // if P == '0' && W == '0' then SEE 'Related encodings';
10724 // if Rn == '1111' then SEE LDRD (literal);
10725 // t = UInt(Rt); t2 = UInt(Rt2); n = UInt(Rn); imm32 =
10726 // ZeroExtend(imm8:'00', 32);
10727 t = Bits32(opcode, 15, 12);
10728 t2 = Bits32(opcode, 11, 8);
10729 n = Bits32(opcode, 19, 16);
10730 imm32 = Bits32(opcode, 7, 0) << 2;
10732 // index = (P == '1'); add = (U == '1'); wback = (W == '1');
10733 index = BitIsSet(opcode, 24);
10734 add = BitIsSet(opcode, 23);
10735 wback = BitIsSet(opcode, 21);
10737 // if wback && (n == t || n == t2) then UNPREDICTABLE;
10738 if (wback && ((n == t) || (n == t2)))
10741 // if BadReg(t) || BadReg(t2) || t == t2 then UNPREDICTABLE;
10742 if (BadReg(t) || BadReg(t2) || (t == t2))
10748 // if Rn == '1111' then SEE LDRD (literal);
10749 // if Rt<0> == '1' then UNPREDICTABLE;
10750 // t = UInt(Rt); t2 = t+1; n = UInt(Rn); imm32 = ZeroExtend(imm4H:imm4L,
10752 t = Bits32(opcode, 15, 12);
10753 if (BitIsSet(t, 0))
10756 n = Bits32(opcode, 19, 16);
10757 imm32 = (Bits32(opcode, 11, 8) << 4) | Bits32(opcode, 3, 0);
10759 // index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1');
10760 index = BitIsSet(opcode, 24);
10761 add = BitIsSet(opcode, 23);
10762 wback = BitIsClear(opcode, 24) || BitIsSet(opcode, 21);
10764 // if P == '0' && W == '1' then UNPREDICTABLE;
10765 if (BitIsClear(opcode, 24) && BitIsSet(opcode, 21))
10768 // if wback && (n == t || n == t2) then UNPREDICTABLE;
10769 if (wback && ((n == t) || (n == t2)))
10772 // if t2 == 15 then UNPREDICTABLE;
10782 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
10783 uint32_t Rn = ReadCoreReg(n, &success);
10787 addr_t offset_addr;
10789 offset_addr = Rn + imm32;
10791 offset_addr = Rn - imm32;
10793 // address = if index then offset_addr else R[n];
10796 address = offset_addr;
10800 // R[t] = MemA[address,4];
10801 RegisterInfo base_reg;
10802 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n, base_reg);
10804 EmulateInstruction::Context context;
10806 context.type = eContextPopRegisterOffStack;
10808 context.type = eContextRegisterLoad;
10809 context.SetAddress(address);
10811 const uint32_t addr_byte_size = GetAddressByteSize();
10812 uint32_t data = MemARead(context, address, addr_byte_size, 0, &success);
10816 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + t, data))
10819 // R[t2] = MemA[address+4,4];
10820 context.SetAddress(address + 4);
10821 data = MemARead(context, address + 4, addr_byte_size, 0, &success);
10825 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + t2,
10829 // if wback then R[n] = offset_addr;
10831 context.type = eContextAdjustBaseRegister;
10832 context.SetAddress(offset_addr);
10834 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n,
10842 // A8.6.68 LDRD (register)
10843 // Load Register Dual (register) calculates an address from a base register
10844 // value and a register offset, loads two words from memory, and writes them to
10845 // two registers. It can use offset, post-indexed or pre-indexed addressing.
10846 bool EmulateInstructionARM::EmulateLDRDRegister(const uint32_t opcode,
10847 const ARMEncoding encoding) {
10849 if ConditionPassed() then
10850 EncodingSpecificOperations();
10851 offset_addr = if add then (R[n] + R[m]) else (R[n] - R[m]);
10852 address = if index then offset_addr else R[n];
10853 R[t] = MemA[address,4];
10854 R[t2] = MemA[address+4,4];
10855 if wback then R[n] = offset_addr;
10858 bool success = false;
10860 if (ConditionPassed(opcode)) {
10869 switch (encoding) {
10871 // if Rt<0> == '1' then UNPREDICTABLE;
10872 // t = UInt(Rt); t2 = t+1; n = UInt(Rn); m = UInt(Rm);
10873 t = Bits32(opcode, 15, 12);
10874 if (BitIsSet(t, 0))
10877 n = Bits32(opcode, 19, 16);
10878 m = Bits32(opcode, 3, 0);
10880 // index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1');
10881 index = BitIsSet(opcode, 24);
10882 add = BitIsSet(opcode, 23);
10883 wback = BitIsClear(opcode, 24) || BitIsSet(opcode, 21);
10885 // if P == '0' && W == '1' then UNPREDICTABLE;
10886 if (BitIsClear(opcode, 24) && BitIsSet(opcode, 21))
10889 // if t2 == 15 || m == 15 || m == t || m == t2 then UNPREDICTABLE;
10890 if ((t2 == 15) || (m == 15) || (m == t) || (m == t2))
10893 // if wback && (n == 15 || n == t || n == t2) then UNPREDICTABLE;
10894 if (wback && ((n == 15) || (n == t) || (n == t2)))
10897 // if ArchVersion() < 6 && wback && m == n then UNPREDICTABLE;
10898 if ((ArchVersion() < 6) && wback && (m == n))
10906 uint32_t Rn = ReadCoreReg(n, &success);
10909 RegisterInfo base_reg;
10910 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n, base_reg);
10912 uint32_t Rm = ReadCoreReg(m, &success);
10915 RegisterInfo offset_reg;
10916 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + m, offset_reg);
10918 // offset_addr = if add then (R[n] + R[m]) else (R[n] - R[m]);
10919 addr_t offset_addr;
10921 offset_addr = Rn + Rm;
10923 offset_addr = Rn - Rm;
10925 // address = if index then offset_addr else R[n];
10928 address = offset_addr;
10932 EmulateInstruction::Context context;
10934 context.type = eContextPopRegisterOffStack;
10936 context.type = eContextRegisterLoad;
10937 context.SetAddress(address);
10939 // R[t] = MemA[address,4];
10940 const uint32_t addr_byte_size = GetAddressByteSize();
10941 uint32_t data = MemARead(context, address, addr_byte_size, 0, &success);
10945 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + t, data))
10948 // R[t2] = MemA[address+4,4];
10950 data = MemARead(context, address + 4, addr_byte_size, 0, &success);
10954 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + t2,
10958 // if wback then R[n] = offset_addr;
10960 context.type = eContextAdjustBaseRegister;
10961 context.SetAddress(offset_addr);
10963 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n,
10971 // A8.6.200 STRD (immediate)
10972 // Store Register Dual (immediate) calculates an address from a base register
10973 // value and an immediate offset, and stores two words from two registers to
10974 // memory. It can use offset, post-indexed, or pre-indexed addressing.
10975 bool EmulateInstructionARM::EmulateSTRDImm(const uint32_t opcode,
10976 const ARMEncoding encoding) {
10978 if ConditionPassed() then
10979 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
10980 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
10981 address = if index then offset_addr else R[n];
10982 MemA[address,4] = R[t];
10983 MemA[address+4,4] = R[t2];
10984 if wback then R[n] = offset_addr;
10987 bool success = false;
10989 if (ConditionPassed(opcode)) {
10998 switch (encoding) {
11000 // if P == '0' && W == '0' then SEE 'Related encodings';
11001 // t = UInt(Rt); t2 = UInt(Rt2); n = UInt(Rn); imm32 =
11002 // ZeroExtend(imm8:'00', 32);
11003 t = Bits32(opcode, 15, 12);
11004 t2 = Bits32(opcode, 11, 8);
11005 n = Bits32(opcode, 19, 16);
11006 imm32 = Bits32(opcode, 7, 0) << 2;
11008 // index = (P == '1'); add = (U == '1'); wback = (W == '1');
11009 index = BitIsSet(opcode, 24);
11010 add = BitIsSet(opcode, 23);
11011 wback = BitIsSet(opcode, 21);
11013 // if wback && (n == t || n == t2) then UNPREDICTABLE;
11014 if (wback && ((n == t) || (n == t2)))
11017 // if n == 15 || BadReg(t) || BadReg(t2) then UNPREDICTABLE;
11018 if ((n == 15) || BadReg(t) || BadReg(t2))
11024 // if Rt<0> == '1' then UNPREDICTABLE;
11025 // t = UInt(Rt); t2 = t+1; n = UInt(Rn); imm32 = ZeroExtend(imm4H:imm4L,
11027 t = Bits32(opcode, 15, 12);
11028 if (BitIsSet(t, 0))
11032 n = Bits32(opcode, 19, 16);
11033 imm32 = (Bits32(opcode, 11, 8) << 4) | Bits32(opcode, 3, 0);
11035 // index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1');
11036 index = BitIsSet(opcode, 24);
11037 add = BitIsSet(opcode, 23);
11038 wback = BitIsClear(opcode, 24) || BitIsSet(opcode, 21);
11040 // if P == '0' && W == '1' then UNPREDICTABLE;
11041 if (BitIsClear(opcode, 24) && BitIsSet(opcode, 21))
11044 // if wback && (n == 15 || n == t || n == t2) then UNPREDICTABLE;
11045 if (wback && ((n == 15) || (n == t) || (n == t2)))
11048 // if t2 == 15 then UNPREDICTABLE;
11058 RegisterInfo base_reg;
11059 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n, base_reg);
11061 uint32_t Rn = ReadCoreReg(n, &success);
11065 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
11066 addr_t offset_addr;
11068 offset_addr = Rn + imm32;
11070 offset_addr = Rn - imm32;
11072 // address = if index then offset_addr else R[n];
11075 address = offset_addr;
11079 // MemA[address,4] = R[t];
11080 RegisterInfo data_reg;
11081 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + t, data_reg);
11083 uint32_t data = ReadCoreReg(t, &success);
11087 EmulateInstruction::Context context;
11089 context.type = eContextPushRegisterOnStack;
11091 context.type = eContextRegisterStore;
11092 context.SetRegisterToRegisterPlusOffset(data_reg, base_reg, address - Rn);
11094 const uint32_t addr_byte_size = GetAddressByteSize();
11096 if (!MemAWrite(context, address, data, addr_byte_size))
11099 // MemA[address+4,4] = R[t2];
11100 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + t2, data_reg);
11101 context.SetRegisterToRegisterPlusOffset(data_reg, base_reg,
11102 (address + 4) - Rn);
11104 data = ReadCoreReg(t2, &success);
11108 if (!MemAWrite(context, address + 4, data, addr_byte_size))
11111 // if wback then R[n] = offset_addr;
11114 context.type = eContextAdjustStackPointer;
11116 context.type = eContextAdjustBaseRegister;
11117 context.SetAddress(offset_addr);
11119 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n,
11127 // A8.6.201 STRD (register)
11128 bool EmulateInstructionARM::EmulateSTRDReg(const uint32_t opcode,
11129 const ARMEncoding encoding) {
11131 if ConditionPassed() then
11132 EncodingSpecificOperations();
11133 offset_addr = if add then (R[n] + R[m]) else (R[n] - R[m]);
11134 address = if index then offset_addr else R[n];
11135 MemA[address,4] = R[t];
11136 MemA[address+4,4] = R[t2];
11137 if wback then R[n] = offset_addr;
11140 bool success = false;
11142 if (ConditionPassed(opcode)) {
11151 switch (encoding) {
11153 // if Rt<0> == '1' then UNPREDICTABLE;
11154 // t = UInt(Rt); t2 = t+1; n = UInt(Rn); m = UInt(Rm);
11155 t = Bits32(opcode, 15, 12);
11156 if (BitIsSet(t, 0))
11160 n = Bits32(opcode, 19, 16);
11161 m = Bits32(opcode, 3, 0);
11163 // index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1');
11164 index = BitIsSet(opcode, 24);
11165 add = BitIsSet(opcode, 23);
11166 wback = BitIsClear(opcode, 24) || BitIsSet(opcode, 21);
11168 // if P == '0' && W == '1' then UNPREDICTABLE;
11169 if (BitIsClear(opcode, 24) && BitIsSet(opcode, 21))
11172 // if t2 == 15 || m == 15 then UNPREDICTABLE;
11173 if ((t2 == 15) || (m == 15))
11176 // if wback && (n == 15 || n == t || n == t2) then UNPREDICTABLE;
11177 if (wback && ((n == 15) || (n == t) || (n == t2)))
11180 // if ArchVersion() < 6 && wback && m == n then UNPREDICTABLE;
11181 if ((ArchVersion() < 6) && wback && (m == n))
11190 RegisterInfo base_reg;
11191 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n, base_reg);
11192 RegisterInfo offset_reg;
11193 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + m, offset_reg);
11194 RegisterInfo data_reg;
11196 uint32_t Rn = ReadCoreReg(n, &success);
11200 uint32_t Rm = ReadCoreReg(m, &success);
11204 // offset_addr = if add then (R[n] + R[m]) else (R[n] - R[m]);
11205 addr_t offset_addr;
11207 offset_addr = Rn + Rm;
11209 offset_addr = Rn - Rm;
11211 // address = if index then offset_addr else R[n];
11214 address = offset_addr;
11217 // MemA[address,4] = R[t];
11218 uint32_t Rt = ReadCoreReg(t, &success);
11222 EmulateInstruction::Context context;
11224 context.type = eContextPushRegisterOnStack;
11226 context.type = eContextRegisterStore;
11228 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + t, data_reg);
11229 context.SetRegisterToRegisterPlusIndirectOffset(base_reg, offset_reg,
11232 const uint32_t addr_byte_size = GetAddressByteSize();
11234 if (!MemAWrite(context, address, Rt, addr_byte_size))
11237 // MemA[address+4,4] = R[t2];
11238 uint32_t Rt2 = ReadCoreReg(t2, &success);
11242 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + t2, data_reg);
11244 context.SetRegisterToRegisterPlusIndirectOffset(base_reg, offset_reg,
11247 if (!MemAWrite(context, address + 4, Rt2, addr_byte_size))
11250 // if wback then R[n] = offset_addr;
11252 context.type = eContextAdjustBaseRegister;
11253 context.SetAddress(offset_addr);
11255 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n,
11264 // Vector Load Multiple loads multiple extension registers from consecutive
11265 // memory locations using an address from an ARM core register.
11266 bool EmulateInstructionARM::EmulateVLDM(const uint32_t opcode,
11267 const ARMEncoding encoding) {
11269 if ConditionPassed() then
11270 EncodingSpecificOperations(); CheckVFPEnabled(TRUE); NullCheckIfThumbEE(n);
11271 address = if add then R[n] else R[n]-imm32;
11272 if wback then R[n] = if add then R[n]+imm32 else R[n]-imm32;
11273 for r = 0 to regs-1
11274 if single_regs then
11275 S[d+r] = MemA[address,4]; address = address+4;
11277 word1 = MemA[address,4]; word2 = MemA[address+4,4]; address = address+8;
11278 // Combine the word-aligned words in the correct order for
11279 // current endianness.
11280 D[d+r] = if BigEndian() then word1:word2 else word2:word1;
11283 bool success = false;
11285 if (ConditionPassed(opcode)) {
11294 switch (encoding) {
11297 // if P == '0' && U == '0' && W == '0' then SEE 'Related encodings';
11298 // if P == '0' && U == '1' && W == '1' && Rn == '1101' then SEE VPOP;
11299 // if P == '1' && W == '0' then SEE VLDR;
11300 // if P == U && W == '1' then UNDEFINED;
11301 if ((Bit32(opcode, 24) == Bit32(opcode, 23)) && BitIsSet(opcode, 21))
11304 // // Remaining combinations are PUW = 010 (IA without !), 011 (IA with
11305 // !), 101 (DB with !)
11306 // single_regs = FALSE; add = (U == '1'); wback = (W == '1');
11307 single_regs = false;
11308 add = BitIsSet(opcode, 23);
11309 wback = BitIsSet(opcode, 21);
11311 // d = UInt(D:Vd); n = UInt(Rn); imm32 = ZeroExtend(imm8:'00', 32);
11312 d = (Bit32(opcode, 22) << 4) | Bits32(opcode, 15, 12);
11313 n = Bits32(opcode, 19, 16);
11314 imm32 = Bits32(opcode, 7, 0) << 2;
11316 // regs = UInt(imm8) DIV 2; // If UInt(imm8) is odd, see 'FLDMX'.
11317 regs = Bits32(opcode, 7, 0) / 2;
11319 // if n == 15 && (wback || CurrentInstrSet() != InstrSet_ARM) then
11321 if (n == 15 && (wback || CurrentInstrSet() != eModeARM))
11324 // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE;
11325 if ((regs == 0) || (regs > 16) || ((d + regs) > 32))
11332 // if P == '0' && U == '0' && W == '0' then SEE 'Related encodings';
11333 // if P == '0' && U == '1' && W == '1' && Rn == '1101' then SEE VPOP;
11334 // if P == '1' && W == '0' then SEE VLDR;
11335 // if P == U && W == '1' then UNDEFINED;
11336 if ((Bit32(opcode, 24) == Bit32(opcode, 23)) && BitIsSet(opcode, 21))
11339 // // Remaining combinations are PUW = 010 (IA without !), 011 (IA with
11340 // !), 101 (DB with !) single_regs = TRUE; add = (U == '1'); wback = (W
11342 // UInt(Vd:D); n = UInt(Rn);
11343 single_regs = true;
11344 add = BitIsSet(opcode, 23);
11345 wback = BitIsSet(opcode, 21);
11346 d = (Bits32(opcode, 15, 12) << 1) | Bit32(opcode, 22);
11347 n = Bits32(opcode, 19, 16);
11349 // imm32 = ZeroExtend(imm8:'00', 32); regs = UInt(imm8);
11350 imm32 = Bits32(opcode, 7, 0) << 2;
11351 regs = Bits32(opcode, 7, 0);
11353 // if n == 15 && (wback || CurrentInstrSet() != InstrSet_ARM) then
11355 if ((n == 15) && (wback || (CurrentInstrSet() != eModeARM)))
11358 // if regs == 0 || (d+regs) > 32 then UNPREDICTABLE;
11359 if ((regs == 0) || ((d + regs) > 32))
11367 RegisterInfo base_reg;
11368 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n, base_reg);
11370 uint32_t Rn = ReadCoreReg(n, &success);
11374 // address = if add then R[n] else R[n]-imm32;
11379 address = Rn - imm32;
11381 // if wback then R[n] = if add then R[n]+imm32 else R[n]-imm32;
11382 EmulateInstruction::Context context;
11387 value = Rn + imm32;
11389 value = Rn - imm32;
11391 context.type = eContextAdjustBaseRegister;
11392 context.SetImmediateSigned(value - Rn);
11393 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n,
11398 const uint32_t addr_byte_size = GetAddressByteSize();
11399 uint32_t start_reg = single_regs ? dwarf_s0 : dwarf_d0;
11401 context.type = eContextRegisterLoad;
11403 // for r = 0 to regs-1
11404 for (uint32_t r = 0; r < regs; ++r) {
11406 // S[d+r] = MemA[address,4]; address = address+4;
11407 context.SetRegisterPlusOffset(base_reg, address - Rn);
11409 uint32_t data = MemARead(context, address, addr_byte_size, 0, &success);
11413 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF,
11414 start_reg + d + r, data))
11417 address = address + 4;
11419 // word1 = MemA[address,4]; word2 = MemA[address+4,4]; address =
11421 context.SetRegisterPlusOffset(base_reg, address - Rn);
11423 MemARead(context, address, addr_byte_size, 0, &success);
11427 context.SetRegisterPlusOffset(base_reg, (address + 4) - Rn);
11429 MemARead(context, address + 4, addr_byte_size, 0, &success);
11433 address = address + 8;
11434 // // Combine the word-aligned words in the correct order for current
11436 // D[d+r] = if BigEndian() then word1:word2 else word2:word1;
11438 if (GetByteOrder() == eByteOrderBig) {
11440 data = (data << 32) | word2;
11443 data = (data << 32) | word1;
11446 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF,
11447 start_reg + d + r, data))
11456 // Vector Store Multiple stores multiple extension registers to consecutive
11457 // memory locations using an address from an
11458 // ARM core register.
11459 bool EmulateInstructionARM::EmulateVSTM(const uint32_t opcode,
11460 const ARMEncoding encoding) {
11462 if ConditionPassed() then
11463 EncodingSpecificOperations(); CheckVFPEnabled(TRUE); NullCheckIfThumbEE(n);
11464 address = if add then R[n] else R[n]-imm32;
11465 if wback then R[n] = if add then R[n]+imm32 else R[n]-imm32;
11466 for r = 0 to regs-1
11467 if single_regs then
11468 MemA[address,4] = S[d+r]; address = address+4;
11470 // Store as two word-aligned words in the correct order for
11471 // current endianness.
11472 MemA[address,4] = if BigEndian() then D[d+r]<63:32> else D[d+r]<31:0>;
11473 MemA[address+4,4] = if BigEndian() then D[d+r]<31:0> else D[d+r]<63:32>;
11474 address = address+8;
11477 bool success = false;
11479 if (ConditionPassed(opcode)) {
11488 switch (encoding) {
11491 // if P == '0' && U == '0' && W == '0' then SEE 'Related encodings';
11492 // if P == '1' && U == '0' && W == '1' && Rn == '1101' then SEE VPUSH;
11493 // if P == '1' && W == '0' then SEE VSTR;
11494 // if P == U && W == '1' then UNDEFINED;
11495 if ((Bit32(opcode, 24) == Bit32(opcode, 23)) && BitIsSet(opcode, 21))
11498 // // Remaining combinations are PUW = 010 (IA without !), 011 (IA with
11499 // !), 101 (DB with !)
11500 // single_regs = FALSE; add = (U == '1'); wback = (W == '1');
11501 single_regs = false;
11502 add = BitIsSet(opcode, 23);
11503 wback = BitIsSet(opcode, 21);
11505 // d = UInt(D:Vd); n = UInt(Rn); imm32 = ZeroExtend(imm8:'00', 32);
11506 d = (Bit32(opcode, 22) << 4) | Bits32(opcode, 15, 12);
11507 n = Bits32(opcode, 19, 16);
11508 imm32 = Bits32(opcode, 7, 0) << 2;
11510 // regs = UInt(imm8) DIV 2; // If UInt(imm8) is odd, see 'FSTMX'.
11511 regs = Bits32(opcode, 7, 0) / 2;
11513 // if n == 15 && (wback || CurrentInstrSet() != InstrSet_ARM) then
11515 if ((n == 15) && (wback || (CurrentInstrSet() != eModeARM)))
11518 // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE;
11519 if ((regs == 0) || (regs > 16) || ((d + regs) > 32))
11526 // if P == '0' && U == '0' && W == '0' then SEE 'Related encodings';
11527 // if P == '1' && U == '0' && W == '1' && Rn == '1101' then SEE VPUSH;
11528 // if P == '1' && W == '0' then SEE VSTR;
11529 // if P == U && W == '1' then UNDEFINED;
11530 if ((Bit32(opcode, 24) == Bit32(opcode, 23)) && BitIsSet(opcode, 21))
11533 // // Remaining combinations are PUW = 010 (IA without !), 011 (IA with
11534 // !), 101 (DB with !) single_regs = TRUE; add = (U == '1'); wback = (W
11536 // UInt(Vd:D); n = UInt(Rn);
11537 single_regs = true;
11538 add = BitIsSet(opcode, 23);
11539 wback = BitIsSet(opcode, 21);
11540 d = (Bits32(opcode, 15, 12) << 1) | Bit32(opcode, 22);
11541 n = Bits32(opcode, 19, 16);
11543 // imm32 = ZeroExtend(imm8:'00', 32); regs = UInt(imm8);
11544 imm32 = Bits32(opcode, 7, 0) << 2;
11545 regs = Bits32(opcode, 7, 0);
11547 // if n == 15 && (wback || CurrentInstrSet() != InstrSet_ARM) then
11549 if ((n == 15) && (wback || (CurrentInstrSet() != eModeARM)))
11552 // if regs == 0 || (d+regs) > 32 then UNPREDICTABLE;
11553 if ((regs == 0) || ((d + regs) > 32))
11562 RegisterInfo base_reg;
11563 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n, base_reg);
11565 uint32_t Rn = ReadCoreReg(n, &success);
11569 // address = if add then R[n] else R[n]-imm32;
11574 address = Rn - imm32;
11576 EmulateInstruction::Context context;
11577 // if wback then R[n] = if add then R[n]+imm32 else R[n]-imm32;
11581 value = Rn + imm32;
11583 value = Rn - imm32;
11585 context.type = eContextAdjustBaseRegister;
11586 context.SetRegisterPlusOffset(base_reg, value - Rn);
11588 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n,
11593 const uint32_t addr_byte_size = GetAddressByteSize();
11594 uint32_t start_reg = single_regs ? dwarf_s0 : dwarf_d0;
11596 context.type = eContextRegisterStore;
11597 // for r = 0 to regs-1
11598 for (uint32_t r = 0; r < regs; ++r) {
11601 // MemA[address,4] = S[d+r]; address = address+4;
11602 uint32_t data = ReadRegisterUnsigned(eRegisterKindDWARF,
11603 start_reg + d + r, 0, &success);
11607 RegisterInfo data_reg;
11608 GetRegisterInfo(eRegisterKindDWARF, start_reg + d + r, data_reg);
11609 context.SetRegisterToRegisterPlusOffset(data_reg, base_reg,
11611 if (!MemAWrite(context, address, data, addr_byte_size))
11614 address = address + 4;
11616 // // Store as two word-aligned words in the correct order for current
11617 // endianness. MemA[address,4] = if BigEndian() then D[d+r]<63:32> else
11619 // MemA[address+4,4] = if BigEndian() then D[d+r]<31:0> else
11621 uint64_t data = ReadRegisterUnsigned(eRegisterKindDWARF,
11622 start_reg + d + r, 0, &success);
11626 RegisterInfo data_reg;
11627 GetRegisterInfo(eRegisterKindDWARF, start_reg + d + r, data_reg);
11629 if (GetByteOrder() == eByteOrderBig) {
11630 context.SetRegisterToRegisterPlusOffset(data_reg, base_reg,
11632 if (!MemAWrite(context, address, Bits64(data, 63, 32),
11636 context.SetRegisterToRegisterPlusOffset(data_reg, base_reg,
11637 (address + 4) - Rn);
11638 if (!MemAWrite(context, address + 4, Bits64(data, 31, 0),
11642 context.SetRegisterToRegisterPlusOffset(data_reg, base_reg,
11644 if (!MemAWrite(context, address, Bits64(data, 31, 0), addr_byte_size))
11647 context.SetRegisterToRegisterPlusOffset(data_reg, base_reg,
11648 (address + 4) - Rn);
11649 if (!MemAWrite(context, address + 4, Bits64(data, 63, 32),
11653 // address = address+8;
11654 address = address + 8;
11662 // This instruction loads a single extension register from memory, using an
11663 // address from an ARM core register, with an optional offset.
11664 bool EmulateInstructionARM::EmulateVLDR(const uint32_t opcode,
11665 ARMEncoding encoding) {
11667 if ConditionPassed() then
11668 EncodingSpecificOperations(); CheckVFPEnabled(TRUE); NullCheckIfThumbEE(n);
11669 base = if n == 15 then Align(PC,4) else R[n];
11670 address = if add then (base + imm32) else (base - imm32);
11672 S[d] = MemA[address,4];
11674 word1 = MemA[address,4]; word2 = MemA[address+4,4];
11675 // Combine the word-aligned words in the correct order for current
11677 D[d] = if BigEndian() then word1:word2 else word2:word1;
11680 bool success = false;
11682 if (ConditionPassed(opcode)) {
11689 switch (encoding) {
11692 // single_reg = FALSE; add = (U == '1'); imm32 = ZeroExtend(imm8:'00',
11694 single_reg = false;
11695 add = BitIsSet(opcode, 23);
11696 imm32 = Bits32(opcode, 7, 0) << 2;
11698 // d = UInt(D:Vd); n = UInt(Rn);
11699 d = (Bit32(opcode, 22) << 4) | Bits32(opcode, 15, 12);
11700 n = Bits32(opcode, 19, 16);
11706 // single_reg = TRUE; add = (U == '1'); imm32 = ZeroExtend(imm8:'00', 32);
11708 add = BitIsSet(opcode, 23);
11709 imm32 = Bits32(opcode, 7, 0) << 2;
11711 // d = UInt(Vd:D); n = UInt(Rn);
11712 d = (Bits32(opcode, 15, 12) << 1) | Bit32(opcode, 22);
11713 n = Bits32(opcode, 19, 16);
11720 RegisterInfo base_reg;
11721 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n, base_reg);
11723 uint32_t Rn = ReadCoreReg(n, &success);
11727 // base = if n == 15 then Align(PC,4) else R[n];
11730 base = AlignPC(Rn);
11734 // address = if add then (base + imm32) else (base - imm32);
11737 address = base + imm32;
11739 address = base - imm32;
11741 const uint32_t addr_byte_size = GetAddressByteSize();
11742 uint32_t start_reg = single_reg ? dwarf_s0 : dwarf_d0;
11744 EmulateInstruction::Context context;
11745 context.type = eContextRegisterLoad;
11746 context.SetRegisterPlusOffset(base_reg, address - base);
11749 // S[d] = MemA[address,4];
11750 uint32_t data = MemARead(context, address, addr_byte_size, 0, &success);
11754 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, start_reg + d,
11758 // word1 = MemA[address,4]; word2 = MemA[address+4,4];
11759 uint32_t word1 = MemARead(context, address, addr_byte_size, 0, &success);
11763 context.SetRegisterPlusOffset(base_reg, (address + 4) - base);
11765 MemARead(context, address + 4, addr_byte_size, 0, &success);
11768 // // Combine the word-aligned words in the correct order for current
11770 // D[d] = if BigEndian() then word1:word2 else word2:word1;
11772 if (GetByteOrder() == eByteOrderBig) {
11774 data64 = (data64 << 32) | word2;
11777 data64 = (data64 << 32) | word1;
11780 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, start_reg + d,
11789 // This instruction stores a signle extension register to memory, using an
11790 // address from an ARM core register, with an optional offset.
11791 bool EmulateInstructionARM::EmulateVSTR(const uint32_t opcode,
11792 ARMEncoding encoding) {
11794 if ConditionPassed() then
11795 EncodingSpecificOperations(); CheckVFPEnabled(TRUE); NullCheckIfThumbEE(n);
11796 address = if add then (R[n] + imm32) else (R[n] - imm32);
11798 MemA[address,4] = S[d];
11800 // Store as two word-aligned words in the correct order for current
11802 MemA[address,4] = if BigEndian() then D[d]<63:32> else D[d]<31:0>;
11803 MemA[address+4,4] = if BigEndian() then D[d]<31:0> else D[d]<63:32>;
11806 bool success = false;
11808 if (ConditionPassed(opcode)) {
11815 switch (encoding) {
11818 // single_reg = FALSE; add = (U == '1'); imm32 = ZeroExtend(imm8:'00',
11820 single_reg = false;
11821 add = BitIsSet(opcode, 23);
11822 imm32 = Bits32(opcode, 7, 0) << 2;
11824 // d = UInt(D:Vd); n = UInt(Rn);
11825 d = (Bit32(opcode, 22) << 4) | Bits32(opcode, 15, 12);
11826 n = Bits32(opcode, 19, 16);
11828 // if n == 15 && CurrentInstrSet() != InstrSet_ARM then UNPREDICTABLE;
11829 if ((n == 15) && (CurrentInstrSet() != eModeARM))
11836 // single_reg = TRUE; add = (U == '1'); imm32 = ZeroExtend(imm8:'00', 32);
11838 add = BitIsSet(opcode, 23);
11839 imm32 = Bits32(opcode, 7, 0) << 2;
11841 // d = UInt(Vd:D); n = UInt(Rn);
11842 d = (Bits32(opcode, 15, 12) << 1) | Bit32(opcode, 22);
11843 n = Bits32(opcode, 19, 16);
11845 // if n == 15 && CurrentInstrSet() != InstrSet_ARM then UNPREDICTABLE;
11846 if ((n == 15) && (CurrentInstrSet() != eModeARM))
11855 RegisterInfo base_reg;
11856 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n, base_reg);
11858 uint32_t Rn = ReadCoreReg(n, &success);
11862 // address = if add then (R[n] + imm32) else (R[n] - imm32);
11865 address = Rn + imm32;
11867 address = Rn - imm32;
11869 const uint32_t addr_byte_size = GetAddressByteSize();
11870 uint32_t start_reg = single_reg ? dwarf_s0 : dwarf_d0;
11872 RegisterInfo data_reg;
11873 GetRegisterInfo(eRegisterKindDWARF, start_reg + d, data_reg);
11874 EmulateInstruction::Context context;
11875 context.type = eContextRegisterStore;
11876 context.SetRegisterToRegisterPlusOffset(data_reg, base_reg, address - Rn);
11879 // MemA[address,4] = S[d];
11881 ReadRegisterUnsigned(eRegisterKindDWARF, start_reg + d, 0, &success);
11885 if (!MemAWrite(context, address, data, addr_byte_size))
11888 // // Store as two word-aligned words in the correct order for current
11890 // MemA[address,4] = if BigEndian() then D[d]<63:32> else D[d]<31:0>;
11891 // MemA[address+4,4] = if BigEndian() then D[d]<31:0> else D[d]<63:32>;
11893 ReadRegisterUnsigned(eRegisterKindDWARF, start_reg + d, 0, &success);
11897 if (GetByteOrder() == eByteOrderBig) {
11898 if (!MemAWrite(context, address, Bits64(data, 63, 32), addr_byte_size))
11901 context.SetRegisterToRegisterPlusOffset(data_reg, base_reg,
11902 (address + 4) - Rn);
11903 if (!MemAWrite(context, address + 4, Bits64(data, 31, 0),
11907 if (!MemAWrite(context, address, Bits64(data, 31, 0), addr_byte_size))
11910 context.SetRegisterToRegisterPlusOffset(data_reg, base_reg,
11911 (address + 4) - Rn);
11912 if (!MemAWrite(context, address + 4, Bits64(data, 63, 32),
11921 // A8.6.307 VLDI1 (multiple single elements) This instruction loads elements
11922 // from memory into one, two, three or four registers, without de-interleaving.
11923 // Every element of each register is loaded.
11924 bool EmulateInstructionARM::EmulateVLD1Multiple(const uint32_t opcode,
11925 ARMEncoding encoding) {
11927 if ConditionPassed() then
11928 EncodingSpecificOperations(); CheckAdvSIMDEnabled(); NullCheckIfThumbEE(n);
11929 address = R[n]; if (address MOD alignment) != 0 then GenerateAlignmentException();
11930 if wback then R[n] = R[n] + (if register_index then R[m] else 8*regs);
11931 for r = 0 to regs-1
11932 for e = 0 to elements-1
11933 Elem[D[d+r],e,esize] = MemU[address,ebytes];
11934 address = address + ebytes;
11937 bool success = false;
11939 if (ConditionPassed(opcode)) {
11941 uint32_t alignment;
11949 bool register_index;
11951 switch (encoding) {
11953 case eEncodingA1: {
11956 // regs = 1; if align<1> == '1' then UNDEFINED;
11958 // regs = 2; if align == '11' then UNDEFINED;
11960 // regs = 3; if align<1> == '1' then UNDEFINED;
11964 // SEE 'Related encodings';
11965 uint32_t type = Bits32(opcode, 11, 8);
11966 uint32_t align = Bits32(opcode, 5, 4);
11967 if (type == 7) // '0111'
11970 if (BitIsSet(align, 1))
11972 } else if (type == 10) // '1010'
11978 } else if (type == 6) // '0110'
11981 if (BitIsSet(align, 1))
11983 } else if (type == 2) // '0010'
11989 // alignment = if align == '00' then 1 else 4 << UInt(align);
11993 alignment = 4 << align;
11995 // ebytes = 1 << UInt(size); esize = 8 * ebytes; elements = 8 DIV ebytes;
11996 ebytes = 1 << Bits32(opcode, 7, 6);
11997 esize = 8 * ebytes;
11998 elements = 8 / ebytes;
12000 // d = UInt(D:Vd); n = UInt(Rn); m = UInt(Rm);
12001 d = (Bit32(opcode, 22) << 4) | Bits32(opcode, 15, 12);
12002 n = Bits32(opcode, 19, 15);
12003 m = Bits32(opcode, 3, 0);
12005 // wback = (m != 15); register_index = (m != 15 && m != 13);
12007 register_index = ((m != 15) && (m != 13));
12009 // if d+regs > 32 then UNPREDICTABLE;
12010 if ((d + regs) > 32)
12018 RegisterInfo base_reg;
12019 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n, base_reg);
12021 uint32_t Rn = ReadCoreReg(n, &success);
12025 // address = R[n]; if (address MOD alignment) != 0 then
12026 // GenerateAlignmentException();
12027 addr_t address = Rn;
12028 if ((address % alignment) != 0)
12031 EmulateInstruction::Context context;
12032 // if wback then R[n] = R[n] + (if register_index then R[m] else 8*regs);
12034 uint32_t Rm = ReadCoreReg(m, &success);
12039 if (register_index)
12044 uint32_t value = Rn + offset;
12045 context.type = eContextAdjustBaseRegister;
12046 context.SetRegisterPlusOffset(base_reg, offset);
12048 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n,
12053 // for r = 0 to regs-1
12054 for (uint32_t r = 0; r < regs; ++r) {
12055 // for e = 0 to elements-1
12056 uint64_t assembled_data = 0;
12057 for (uint32_t e = 0; e < elements; ++e) {
12058 // Elem[D[d+r],e,esize] = MemU[address,ebytes];
12059 context.type = eContextRegisterLoad;
12060 context.SetRegisterPlusOffset(base_reg, address - Rn);
12061 uint64_t data = MemURead(context, address, ebytes, 0, &success);
12066 (data << (e * esize)) |
12067 assembled_data; // New data goes to the left of existing data
12069 // address = address + ebytes;
12070 address = address + ebytes;
12072 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_d0 + d + r,
12080 // A8.6.308 VLD1 (single element to one lane)
12082 bool EmulateInstructionARM::EmulateVLD1Single(const uint32_t opcode,
12083 const ARMEncoding encoding) {
12085 if ConditionPassed() then
12086 EncodingSpecificOperations(); CheckAdvSIMDEnabled(); NullCheckIfThumbEE(n);
12087 address = R[n]; if (address MOD alignment) != 0 then GenerateAlignmentException();
12088 if wback then R[n] = R[n] + (if register_index then R[m] else ebytes);
12089 Elem[D[d],index,esize] = MemU[address,ebytes];
12092 bool success = false;
12094 if (ConditionPassed(opcode)) {
12098 uint32_t alignment;
12103 bool register_index;
12105 switch (encoding) {
12107 case eEncodingA1: {
12108 uint32_t size = Bits32(opcode, 11, 10);
12109 uint32_t index_align = Bits32(opcode, 7, 4);
12110 // if size == '11' then SEE VLD1 (single element to all lanes);
12112 return EmulateVLD1SingleAll(opcode, encoding);
12114 if (size == 0) // when '00'
12116 // if index_align<0> != '0' then UNDEFINED;
12117 if (BitIsClear(index_align, 0))
12120 // ebytes = 1; esize = 8; index = UInt(index_align<3:1>); alignment = 1;
12123 index = Bits32(index_align, 3, 1);
12125 } else if (size == 1) // when '01'
12127 // if index_align<1> != '0' then UNDEFINED;
12128 if (BitIsClear(index_align, 1))
12131 // ebytes = 2; esize = 16; index = UInt(index_align<3:2>);
12134 index = Bits32(index_align, 3, 2);
12136 // alignment = if index_align<0> == '0' then 1 else 2;
12137 if (BitIsClear(index_align, 0))
12141 } else if (size == 2) // when '10'
12143 // if index_align<2> != '0' then UNDEFINED;
12144 if (BitIsClear(index_align, 2))
12147 // if index_align<1:0> != '00' && index_align<1:0> != '11' then
12149 if ((Bits32(index_align, 1, 0) != 0) &&
12150 (Bits32(index_align, 1, 0) != 3))
12153 // ebytes = 4; esize = 32; index = UInt(index_align<3>);
12156 index = Bit32(index_align, 3);
12158 // alignment = if index_align<1:0> == '00' then 1 else 4;
12159 if (Bits32(index_align, 1, 0) == 0)
12166 // d = UInt(D:Vd); n = UInt(Rn); m = UInt(Rm);
12167 d = (Bit32(opcode, 22) << 4) | Bits32(opcode, 15, 12);
12168 n = Bits32(opcode, 19, 16);
12169 m = Bits32(opcode, 3, 0);
12171 // wback = (m != 15); register_index = (m != 15 && m != 13); if n == 15
12172 // then UNPREDICTABLE;
12174 register_index = ((m != 15) && (m != 13));
12185 RegisterInfo base_reg;
12186 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n, base_reg);
12188 uint32_t Rn = ReadCoreReg(n, &success);
12192 // address = R[n]; if (address MOD alignment) != 0 then
12193 // GenerateAlignmentException();
12194 addr_t address = Rn;
12195 if ((address % alignment) != 0)
12198 EmulateInstruction::Context context;
12199 // if wback then R[n] = R[n] + (if register_index then R[m] else ebytes);
12201 uint32_t Rm = ReadCoreReg(m, &success);
12206 if (register_index)
12211 uint32_t value = Rn + offset;
12213 context.type = eContextAdjustBaseRegister;
12214 context.SetRegisterPlusOffset(base_reg, offset);
12216 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n,
12221 // Elem[D[d],index,esize] = MemU[address,ebytes];
12222 uint32_t element = MemURead(context, address, esize, 0, &success);
12226 element = element << (index * esize);
12228 uint64_t reg_data =
12229 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_d0 + d, 0, &success);
12233 uint64_t all_ones = -1;
12234 uint64_t mask = all_ones
12235 << ((index + 1) * esize); // mask is all 1's to left of
12236 // where 'element' goes, & all 0's
12237 // at element & to the right of element.
12239 mask = mask | Bits64(all_ones, (index * esize) - 1,
12240 0); // add 1's to the right of where 'element' goes.
12241 // now mask should be 0's where element goes & 1's everywhere else.
12243 uint64_t masked_reg =
12244 reg_data & mask; // Take original reg value & zero out 'element' bits
12246 masked_reg & element; // Put 'element' into those bits in reg_data.
12248 context.type = eContextRegisterLoad;
12249 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + d,
12256 // A8.6.391 VST1 (multiple single elements) Vector Store (multiple single
12257 // elements) stores elements to memory from one, two, three, or four registers,
12258 // without interleaving. Every element of each register is stored.
12259 bool EmulateInstructionARM::EmulateVST1Multiple(const uint32_t opcode,
12260 ARMEncoding encoding) {
12262 if ConditionPassed() then
12263 EncodingSpecificOperations(); CheckAdvSIMDEnabled(); NullCheckIfThumbEE(n);
12264 address = R[n]; if (address MOD alignment) != 0 then GenerateAlignmentException();
12265 if wback then R[n] = R[n] + (if register_index then R[m] else 8*regs);
12266 for r = 0 to regs-1
12267 for e = 0 to elements-1
12268 MemU[address,ebytes] = Elem[D[d+r],e,esize];
12269 address = address + ebytes;
12272 bool success = false;
12274 if (ConditionPassed(opcode)) {
12276 uint32_t alignment;
12284 bool register_index;
12286 switch (encoding) {
12288 case eEncodingA1: {
12289 uint32_t type = Bits32(opcode, 11, 8);
12290 uint32_t align = Bits32(opcode, 5, 4);
12293 if (type == 7) // when '0111'
12295 // regs = 1; if align<1> == '1' then UNDEFINED;
12297 if (BitIsSet(align, 1))
12299 } else if (type == 10) // when '1010'
12301 // regs = 2; if align == '11' then UNDEFINED;
12305 } else if (type == 6) // when '0110'
12307 // regs = 3; if align<1> == '1' then UNDEFINED;
12309 if (BitIsSet(align, 1))
12311 } else if (type == 2) // when '0010'
12315 // SEE 'Related encodings';
12318 // alignment = if align == '00' then 1 else 4 << UInt(align);
12322 alignment = 4 << align;
12324 // ebytes = 1 << UInt(size); esize = 8 * ebytes; elements = 8 DIV ebytes;
12325 ebytes = 1 << Bits32(opcode, 7, 6);
12326 esize = 8 * ebytes;
12327 elements = 8 / ebytes;
12329 // d = UInt(D:Vd); n = UInt(Rn); m = UInt(Rm);
12330 d = (Bit32(opcode, 22) << 4) | Bits32(opcode, 15, 12);
12331 n = Bits32(opcode, 19, 16);
12332 m = Bits32(opcode, 3, 0);
12334 // wback = (m != 15); register_index = (m != 15 && m != 13);
12336 register_index = ((m != 15) && (m != 13));
12338 // if d+regs > 32 then UNPREDICTABLE; if n == 15 then UNPREDICTABLE;
12339 if ((d + regs) > 32)
12351 RegisterInfo base_reg;
12352 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n, base_reg);
12354 uint32_t Rn = ReadCoreReg(n, &success);
12358 // address = R[n]; if (address MOD alignment) != 0 then
12359 // GenerateAlignmentException();
12360 addr_t address = Rn;
12361 if ((address % alignment) != 0)
12364 EmulateInstruction::Context context;
12365 // if wback then R[n] = R[n] + (if register_index then R[m] else 8*regs);
12367 uint32_t Rm = ReadCoreReg(m, &success);
12372 if (register_index)
12377 context.type = eContextAdjustBaseRegister;
12378 context.SetRegisterPlusOffset(base_reg, offset);
12380 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n,
12385 RegisterInfo data_reg;
12386 context.type = eContextRegisterStore;
12387 // for r = 0 to regs-1
12388 for (uint32_t r = 0; r < regs; ++r) {
12389 GetRegisterInfo(eRegisterKindDWARF, dwarf_d0 + d + r, data_reg);
12390 uint64_t register_data = ReadRegisterUnsigned(
12391 eRegisterKindDWARF, dwarf_d0 + d + r, 0, &success);
12395 // for e = 0 to elements-1
12396 for (uint32_t e = 0; e < elements; ++e) {
12397 // MemU[address,ebytes] = Elem[D[d+r],e,esize];
12398 uint64_t word = Bits64(register_data, ((e + 1) * esize) - 1, e * esize);
12400 context.SetRegisterToRegisterPlusOffset(data_reg, base_reg,
12402 if (!MemUWrite(context, address, word, ebytes))
12405 // address = address + ebytes;
12406 address = address + ebytes;
12413 // A8.6.392 VST1 (single element from one lane) This instruction stores one
12414 // element to memory from one element of a register.
12415 bool EmulateInstructionARM::EmulateVST1Single(const uint32_t opcode,
12416 ARMEncoding encoding) {
12418 if ConditionPassed() then
12419 EncodingSpecificOperations(); CheckAdvSIMDEnabled(); NullCheckIfThumbEE(n);
12420 address = R[n]; if (address MOD alignment) != 0 then GenerateAlignmentException();
12421 if wback then R[n] = R[n] + (if register_index then R[m] else ebytes);
12422 MemU[address,ebytes] = Elem[D[d],index,esize];
12425 bool success = false;
12427 if (ConditionPassed(opcode)) {
12431 uint32_t alignment;
12436 bool register_index;
12438 switch (encoding) {
12440 case eEncodingA1: {
12441 uint32_t size = Bits32(opcode, 11, 10);
12442 uint32_t index_align = Bits32(opcode, 7, 4);
12444 // if size == '11' then UNDEFINED;
12449 if (size == 0) // when '00'
12451 // if index_align<0> != '0' then UNDEFINED;
12452 if (BitIsClear(index_align, 0))
12454 // ebytes = 1; esize = 8; index = UInt(index_align<3:1>); alignment = 1;
12457 index = Bits32(index_align, 3, 1);
12459 } else if (size == 1) // when '01'
12461 // if index_align<1> != '0' then UNDEFINED;
12462 if (BitIsClear(index_align, 1))
12465 // ebytes = 2; esize = 16; index = UInt(index_align<3:2>);
12468 index = Bits32(index_align, 3, 2);
12470 // alignment = if index_align<0> == '0' then 1 else 2;
12471 if (BitIsClear(index_align, 0))
12475 } else if (size == 2) // when '10'
12477 // if index_align<2> != '0' then UNDEFINED;
12478 if (BitIsClear(index_align, 2))
12481 // if index_align<1:0> != '00' && index_align<1:0> != '11' then
12483 if ((Bits32(index_align, 1, 0) != 0) &&
12484 (Bits32(index_align, 1, 0) != 3))
12487 // ebytes = 4; esize = 32; index = UInt(index_align<3>);
12490 index = Bit32(index_align, 3);
12492 // alignment = if index_align<1:0> == '00' then 1 else 4;
12493 if (Bits32(index_align, 1, 0) == 0)
12500 // d = UInt(D:Vd); n = UInt(Rn); m = UInt(Rm);
12501 d = (Bit32(opcode, 22) << 4) | Bits32(opcode, 15, 12);
12502 n = Bits32(opcode, 19, 16);
12503 m = Bits32(opcode, 3, 0);
12505 // wback = (m != 15); register_index = (m != 15 && m != 13); if n == 15
12506 // then UNPREDICTABLE;
12508 register_index = ((m != 15) && (m != 13));
12518 RegisterInfo base_reg;
12519 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n, base_reg);
12521 uint32_t Rn = ReadCoreReg(n, &success);
12525 // address = R[n]; if (address MOD alignment) != 0 then
12526 // GenerateAlignmentException();
12527 addr_t address = Rn;
12528 if ((address % alignment) != 0)
12531 EmulateInstruction::Context context;
12532 // if wback then R[n] = R[n] + (if register_index then R[m] else ebytes);
12534 uint32_t Rm = ReadCoreReg(m, &success);
12539 if (register_index)
12544 context.type = eContextAdjustBaseRegister;
12545 context.SetRegisterPlusOffset(base_reg, offset);
12547 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n,
12552 // MemU[address,ebytes] = Elem[D[d],index,esize];
12553 uint64_t register_data =
12554 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_d0 + d, 0, &success);
12559 Bits64(register_data, ((index + 1) * esize) - 1, index * esize);
12561 RegisterInfo data_reg;
12562 GetRegisterInfo(eRegisterKindDWARF, dwarf_d0 + d, data_reg);
12563 context.type = eContextRegisterStore;
12564 context.SetRegisterToRegisterPlusOffset(data_reg, base_reg, address - Rn);
12566 if (!MemUWrite(context, address, word, ebytes))
12572 // A8.6.309 VLD1 (single element to all lanes) This instruction loads one
12573 // element from memory into every element of one or two vectors.
12574 bool EmulateInstructionARM::EmulateVLD1SingleAll(const uint32_t opcode,
12575 const ARMEncoding encoding) {
12577 if ConditionPassed() then
12578 EncodingSpecificOperations(); CheckAdvSIMDEnabled(); NullCheckIfThumbEE(n);
12579 address = R[n]; if (address MOD alignment) != 0 then GenerateAlignmentException();
12580 if wback then R[n] = R[n] + (if register_index then R[m] else ebytes);
12581 replicated_element = Replicate(MemU[address,ebytes], elements);
12582 for r = 0 to regs-1
12583 D[d+r] = replicated_element;
12586 bool success = false;
12588 if (ConditionPassed(opcode)) {
12592 uint32_t alignment;
12597 bool register_index;
12599 switch (encoding) {
12601 case eEncodingA1: {
12602 // if size == '11' || (size == '00' && a == '1') then UNDEFINED;
12603 uint32_t size = Bits32(opcode, 7, 6);
12604 if ((size == 3) || ((size == 0) && BitIsSet(opcode, 4)))
12607 // ebytes = 1 << UInt(size); elements = 8 DIV ebytes; regs = if T == '0'
12609 ebytes = 1 << size;
12610 elements = 8 / ebytes;
12611 if (BitIsClear(opcode, 5))
12616 // alignment = if a == '0' then 1 else ebytes;
12617 if (BitIsClear(opcode, 4))
12620 alignment = ebytes;
12622 // d = UInt(D:Vd); n = UInt(Rn); m = UInt(Rm);
12623 d = (Bit32(opcode, 22) << 4) | Bits32(opcode, 15, 12);
12624 n = Bits32(opcode, 19, 16);
12625 m = Bits32(opcode, 3, 0);
12627 // wback = (m != 15); register_index = (m != 15 && m != 13);
12629 register_index = ((m != 15) && (m != 13));
12631 // if d+regs > 32 then UNPREDICTABLE; if n == 15 then UNPREDICTABLE;
12632 if ((d + regs) > 32)
12643 RegisterInfo base_reg;
12644 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n, base_reg);
12646 uint32_t Rn = ReadCoreReg(n, &success);
12650 // address = R[n]; if (address MOD alignment) != 0 then
12651 // GenerateAlignmentException();
12652 addr_t address = Rn;
12653 if ((address % alignment) != 0)
12656 EmulateInstruction::Context context;
12657 // if wback then R[n] = R[n] + (if register_index then R[m] else ebytes);
12659 uint32_t Rm = ReadCoreReg(m, &success);
12664 if (register_index)
12669 context.type = eContextAdjustBaseRegister;
12670 context.SetRegisterPlusOffset(base_reg, offset);
12672 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n,
12677 // replicated_element = Replicate(MemU[address,ebytes], elements);
12679 context.type = eContextRegisterLoad;
12680 uint64_t word = MemURead(context, address, ebytes, 0, &success);
12684 uint64_t replicated_element = 0;
12685 uint32_t esize = ebytes * 8;
12686 for (uint32_t e = 0; e < elements; ++e)
12687 replicated_element =
12688 (replicated_element << esize) | Bits64(word, esize - 1, 0);
12690 // for r = 0 to regs-1
12691 for (uint32_t r = 0; r < regs; ++r) {
12692 // D[d+r] = replicated_element;
12693 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_d0 + d + r,
12694 replicated_element))
12701 // B6.2.13 SUBS PC, LR and related instructions The SUBS PC, LR, #<const?
12702 // instruction provides an exception return without the use of the stack. It
12703 // subtracts the immediate constant from the LR, branches to the resulting
12704 // address, and also copies the SPSR to the CPSR.
12705 bool EmulateInstructionARM::EmulateSUBSPcLrEtc(const uint32_t opcode,
12706 const ARMEncoding encoding) {
12708 if ConditionPassed() then
12709 EncodingSpecificOperations();
12710 if CurrentInstrSet() == InstrSet_ThumbEE then
12712 operand2 = if register_form then Shift(R[m], shift_t, shift_n, APSR.C) else imm32;
12714 when '0000' result = R[n] AND operand2; // AND
12715 when '0001' result = R[n] EOR operand2; // EOR
12716 when '0010' (result, -, -) = AddWithCarry(R[n], NOT(operand2), '1'); // SUB
12717 when '0011' (result, -, -) = AddWithCarry(NOT(R[n]), operand2, '1'); // RSB
12718 when '0100' (result, -, -) = AddWithCarry(R[n], operand2, '0'); // ADD
12719 when '0101' (result, -, -) = AddWithCarry(R[n], operand2, APSR.c); // ADC
12720 when '0110' (result, -, -) = AddWithCarry(R[n], NOT(operand2), APSR.C); // SBC
12721 when '0111' (result, -, -) = AddWithCarry(NOT(R[n]), operand2, APSR.C); // RSC
12722 when '1100' result = R[n] OR operand2; // ORR
12723 when '1101' result = operand2; // MOV
12724 when '1110' result = R[n] AND NOT(operand2); // BIC
12725 when '1111' result = NOT(operand2); // MVN
12726 CPSRWriteByInstr(SPSR[], '1111', TRUE);
12727 BranchWritePC(result);
12730 bool success = false;
12732 if (ConditionPassed(opcode)) {
12736 bool register_form;
12737 ARM_ShifterType shift_t;
12741 switch (encoding) {
12743 // if CurrentInstrSet() == InstrSet_ThumbEE then UNPREDICTABLE n = 14;
12744 // imm32 = ZeroExtend(imm8, 32); register_form = FALSE; opcode = '0010';
12747 imm32 = Bits32(opcode, 7, 0);
12748 register_form = false;
12751 // if InITBlock() && !LastInITBlock() then UNPREDICTABLE;
12752 if (InITBlock() && !LastInITBlock())
12758 // n = UInt(Rn); imm32 = ARMExpandImm(imm12); register_form = FALSE;
12759 n = Bits32(opcode, 19, 16);
12760 imm32 = ARMExpandImm(opcode);
12761 register_form = false;
12762 code = Bits32(opcode, 24, 21);
12767 // n = UInt(Rn); m = UInt(Rm); register_form = TRUE;
12768 n = Bits32(opcode, 19, 16);
12769 m = Bits32(opcode, 3, 0);
12770 register_form = true;
12772 // (shift_t, shift_n) = DecodeImmShift(type, imm5);
12773 shift_n = DecodeImmShiftARM(opcode, shift_t);
12781 // operand2 = if register_form then Shift(R[m], shift_t, shift_n, APSR.C)
12784 if (register_form) {
12785 uint32_t Rm = ReadCoreReg(m, &success);
12789 operand2 = Shift(Rm, shift_t, shift_n, APSR_C, &success);
12796 uint32_t Rn = ReadCoreReg(n, &success);
12800 AddWithCarryResult result;
12804 case 0: // when '0000'
12805 // result = R[n] AND operand2; // AND
12806 result.result = Rn & operand2;
12809 case 1: // when '0001'
12810 // result = R[n] EOR operand2; // EOR
12811 result.result = Rn ^ operand2;
12814 case 2: // when '0010'
12815 // (result, -, -) = AddWithCarry(R[n], NOT(operand2), '1'); // SUB
12816 result = AddWithCarry(Rn, ~(operand2), 1);
12819 case 3: // when '0011'
12820 // (result, -, -) = AddWithCarry(NOT(R[n]), operand2, '1'); // RSB
12821 result = AddWithCarry(~(Rn), operand2, 1);
12824 case 4: // when '0100'
12825 // (result, -, -) = AddWithCarry(R[n], operand2, '0'); // ADD
12826 result = AddWithCarry(Rn, operand2, 0);
12829 case 5: // when '0101'
12830 // (result, -, -) = AddWithCarry(R[n], operand2, APSR.c); // ADC
12831 result = AddWithCarry(Rn, operand2, APSR_C);
12834 case 6: // when '0110'
12835 // (result, -, -) = AddWithCarry(R[n], NOT(operand2), APSR.C); // SBC
12836 result = AddWithCarry(Rn, ~(operand2), APSR_C);
12839 case 7: // when '0111'
12840 // (result, -, -) = AddWithCarry(NOT(R[n]), operand2, APSR.C); // RSC
12841 result = AddWithCarry(~(Rn), operand2, APSR_C);
12844 case 10: // when '1100'
12845 // result = R[n] OR operand2; // ORR
12846 result.result = Rn | operand2;
12849 case 11: // when '1101'
12850 // result = operand2; // MOV
12851 result.result = operand2;
12854 case 12: // when '1110'
12855 // result = R[n] AND NOT(operand2); // BIC
12856 result.result = Rn & ~(operand2);
12859 case 15: // when '1111'
12860 // result = NOT(operand2); // MVN
12861 result.result = ~(operand2);
12867 // CPSRWriteByInstr(SPSR[], '1111', TRUE);
12869 // For now, in emulation mode, we don't have access to the SPSR, so we will
12870 // use the CPSR instead, and hope for the best.
12872 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_cpsr, 0, &success);
12876 CPSRWriteByInstr(spsr, 15, true);
12878 // BranchWritePC(result);
12879 EmulateInstruction::Context context;
12880 context.type = eContextAdjustPC;
12881 context.SetImmediate(result.result);
12883 BranchWritePC(context, result.result);
12888 EmulateInstructionARM::ARMOpcode *
12889 EmulateInstructionARM::GetARMOpcodeForInstruction(const uint32_t opcode,
12890 uint32_t arm_isa) {
12891 static ARMOpcode g_arm_opcodes[] = {
12892 //----------------------------------------------------------------------
12893 // Prologue instructions
12894 //----------------------------------------------------------------------
12896 // push register(s)
12897 {0x0fff0000, 0x092d0000, ARMvAll, eEncodingA1, No_VFP, eSize32,
12898 &EmulateInstructionARM::EmulatePUSH, "push <registers>"},
12899 {0x0fff0fff, 0x052d0004, ARMvAll, eEncodingA2, No_VFP, eSize32,
12900 &EmulateInstructionARM::EmulatePUSH, "push <register>"},
12902 // set r7 to point to a stack offset
12903 {0x0ffff000, 0x028d7000, ARMvAll, eEncodingA1, No_VFP, eSize32,
12904 &EmulateInstructionARM::EmulateADDRdSPImm, "add r7, sp, #<const>"},
12905 {0x0ffff000, 0x024c7000, ARMvAll, eEncodingA1, No_VFP, eSize32,
12906 &EmulateInstructionARM::EmulateSUBR7IPImm, "sub r7, ip, #<const>"},
12907 // copy the stack pointer to ip
12908 {0x0fffffff, 0x01a0c00d, ARMvAll, eEncodingA1, No_VFP, eSize32,
12909 &EmulateInstructionARM::EmulateMOVRdSP, "mov ip, sp"},
12910 {0x0ffff000, 0x028dc000, ARMvAll, eEncodingA1, No_VFP, eSize32,
12911 &EmulateInstructionARM::EmulateADDRdSPImm, "add ip, sp, #<const>"},
12912 {0x0ffff000, 0x024dc000, ARMvAll, eEncodingA1, No_VFP, eSize32,
12913 &EmulateInstructionARM::EmulateSUBIPSPImm, "sub ip, sp, #<const>"},
12915 // adjust the stack pointer
12916 {0x0ffff000, 0x024dd000, ARMvAll, eEncodingA1, No_VFP, eSize32,
12917 &EmulateInstructionARM::EmulateSUBSPImm, "sub sp, sp, #<const>"},
12918 {0x0fef0010, 0x004d0000, ARMvAll, eEncodingA1, No_VFP, eSize32,
12919 &EmulateInstructionARM::EmulateSUBSPReg,
12920 "sub{s}<c> <Rd>, sp, <Rm>{,<shift>}"},
12922 // push one register
12923 // if Rn == '1101' && imm12 == '000000000100' then SEE PUSH;
12924 {0x0e5f0000, 0x040d0000, ARMvAll, eEncodingA1, No_VFP, eSize32,
12925 &EmulateInstructionARM::EmulateSTRRtSP, "str Rt, [sp, #-imm12]!"},
12927 // vector push consecutive extension register(s)
12928 {0x0fbf0f00, 0x0d2d0b00, ARMV6T2_ABOVE, eEncodingA1, No_VFP, eSize32,
12929 &EmulateInstructionARM::EmulateVPUSH, "vpush.64 <list>"},
12930 {0x0fbf0f00, 0x0d2d0a00, ARMV6T2_ABOVE, eEncodingA2, No_VFP, eSize32,
12931 &EmulateInstructionARM::EmulateVPUSH, "vpush.32 <list>"},
12933 //----------------------------------------------------------------------
12934 // Epilogue instructions
12935 //----------------------------------------------------------------------
12937 {0x0fff0000, 0x08bd0000, ARMvAll, eEncodingA1, No_VFP, eSize32,
12938 &EmulateInstructionARM::EmulatePOP, "pop <registers>"},
12939 {0x0fff0fff, 0x049d0004, ARMvAll, eEncodingA2, No_VFP, eSize32,
12940 &EmulateInstructionARM::EmulatePOP, "pop <register>"},
12941 {0x0fbf0f00, 0x0cbd0b00, ARMV6T2_ABOVE, eEncodingA1, No_VFP, eSize32,
12942 &EmulateInstructionARM::EmulateVPOP, "vpop.64 <list>"},
12943 {0x0fbf0f00, 0x0cbd0a00, ARMV6T2_ABOVE, eEncodingA2, No_VFP, eSize32,
12944 &EmulateInstructionARM::EmulateVPOP, "vpop.32 <list>"},
12946 //----------------------------------------------------------------------
12947 // Supervisor Call (previously Software Interrupt)
12948 //----------------------------------------------------------------------
12949 {0x0f000000, 0x0f000000, ARMvAll, eEncodingA1, No_VFP, eSize32,
12950 &EmulateInstructionARM::EmulateSVC, "svc #imm24"},
12952 //----------------------------------------------------------------------
12953 // Branch instructions
12954 //----------------------------------------------------------------------
12955 // To resolve ambiguity, "blx <label>" should come before "b #imm24" and
12957 {0xfe000000, 0xfa000000, ARMV5_ABOVE, eEncodingA2, No_VFP, eSize32,
12958 &EmulateInstructionARM::EmulateBLXImmediate, "blx <label>"},
12959 {0x0f000000, 0x0a000000, ARMvAll, eEncodingA1, No_VFP, eSize32,
12960 &EmulateInstructionARM::EmulateB, "b #imm24"},
12961 {0x0f000000, 0x0b000000, ARMvAll, eEncodingA1, No_VFP, eSize32,
12962 &EmulateInstructionARM::EmulateBLXImmediate, "bl <label>"},
12963 {0x0ffffff0, 0x012fff30, ARMV5_ABOVE, eEncodingA1, No_VFP, eSize32,
12964 &EmulateInstructionARM::EmulateBLXRm, "blx <Rm>"},
12965 // for example, "bx lr"
12966 {0x0ffffff0, 0x012fff10, ARMvAll, eEncodingA1, No_VFP, eSize32,
12967 &EmulateInstructionARM::EmulateBXRm, "bx <Rm>"},
12969 {0x0ffffff0, 0x012fff20, ARMvAll, eEncodingA1, No_VFP, eSize32,
12970 &EmulateInstructionARM::EmulateBXJRm, "bxj <Rm>"},
12972 //----------------------------------------------------------------------
12973 // Data-processing instructions
12974 //----------------------------------------------------------------------
12976 {0x0fe00000, 0x02a00000, ARMvAll, eEncodingA1, No_VFP, eSize32,
12977 &EmulateInstructionARM::EmulateADCImm, "adc{s}<c> <Rd>, <Rn>, #const"},
12979 {0x0fe00010, 0x00a00000, ARMvAll, eEncodingA1, No_VFP, eSize32,
12980 &EmulateInstructionARM::EmulateADCReg,
12981 "adc{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
12983 {0x0fe00000, 0x02800000, ARMvAll, eEncodingA1, No_VFP, eSize32,
12984 &EmulateInstructionARM::EmulateADDImmARM,
12985 "add{s}<c> <Rd>, <Rn>, #const"},
12987 {0x0fe00010, 0x00800000, ARMvAll, eEncodingA1, No_VFP, eSize32,
12988 &EmulateInstructionARM::EmulateADDReg,
12989 "add{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
12990 // add (register-shifted register)
12991 {0x0fe00090, 0x00800010, ARMvAll, eEncodingA1, No_VFP, eSize32,
12992 &EmulateInstructionARM::EmulateADDRegShift,
12993 "add{s}<c> <Rd>, <Rn>, <Rm>, <type> <RS>"},
12995 {0x0fff0000, 0x028f0000, ARMvAll, eEncodingA1, No_VFP, eSize32,
12996 &EmulateInstructionARM::EmulateADR, "add<c> <Rd>, PC, #<const>"},
12997 {0x0fff0000, 0x024f0000, ARMvAll, eEncodingA2, No_VFP, eSize32,
12998 &EmulateInstructionARM::EmulateADR, "sub<c> <Rd>, PC, #<const>"},
13000 {0x0fe00000, 0x02000000, ARMvAll, eEncodingA1, No_VFP, eSize32,
13001 &EmulateInstructionARM::EmulateANDImm, "and{s}<c> <Rd>, <Rn>, #const"},
13003 {0x0fe00010, 0x00000000, ARMvAll, eEncodingA1, No_VFP, eSize32,
13004 &EmulateInstructionARM::EmulateANDReg,
13005 "and{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
13007 {0x0fe00000, 0x03c00000, ARMvAll, eEncodingA1, No_VFP, eSize32,
13008 &EmulateInstructionARM::EmulateBICImm, "bic{s}<c> <Rd>, <Rn>, #const"},
13010 {0x0fe00010, 0x01c00000, ARMvAll, eEncodingA1, No_VFP, eSize32,
13011 &EmulateInstructionARM::EmulateBICReg,
13012 "bic{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
13014 {0x0fe00000, 0x02200000, ARMvAll, eEncodingA1, No_VFP, eSize32,
13015 &EmulateInstructionARM::EmulateEORImm, "eor{s}<c> <Rd>, <Rn>, #const"},
13017 {0x0fe00010, 0x00200000, ARMvAll, eEncodingA1, No_VFP, eSize32,
13018 &EmulateInstructionARM::EmulateEORReg,
13019 "eor{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
13021 {0x0fe00000, 0x03800000, ARMvAll, eEncodingA1, No_VFP, eSize32,
13022 &EmulateInstructionARM::EmulateORRImm, "orr{s}<c> <Rd>, <Rn>, #const"},
13024 {0x0fe00010, 0x01800000, ARMvAll, eEncodingA1, No_VFP, eSize32,
13025 &EmulateInstructionARM::EmulateORRReg,
13026 "orr{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
13028 {0x0fe00000, 0x02600000, ARMvAll, eEncodingA1, No_VFP, eSize32,
13029 &EmulateInstructionARM::EmulateRSBImm, "rsb{s}<c> <Rd>, <Rn>, #<const>"},
13031 {0x0fe00010, 0x00600000, ARMvAll, eEncodingA1, No_VFP, eSize32,
13032 &EmulateInstructionARM::EmulateRSBReg,
13033 "rsb{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
13035 {0x0fe00000, 0x02e00000, ARMvAll, eEncodingA1, No_VFP, eSize32,
13036 &EmulateInstructionARM::EmulateRSCImm, "rsc{s}<c> <Rd>, <Rn>, #<const>"},
13038 {0x0fe00010, 0x00e00000, ARMvAll, eEncodingA1, No_VFP, eSize32,
13039 &EmulateInstructionARM::EmulateRSCReg,
13040 "rsc{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
13042 {0x0fe00000, 0x02c00000, ARMvAll, eEncodingA1, No_VFP, eSize32,
13043 &EmulateInstructionARM::EmulateSBCImm, "sbc{s}<c> <Rd>, <Rn>, #<const>"},
13045 {0x0fe00010, 0x00c00000, ARMvAll, eEncodingA1, No_VFP, eSize32,
13046 &EmulateInstructionARM::EmulateSBCReg,
13047 "sbc{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
13048 // sub (immediate, ARM)
13049 {0x0fe00000, 0x02400000, ARMvAll, eEncodingA1, No_VFP, eSize32,
13050 &EmulateInstructionARM::EmulateSUBImmARM,
13051 "sub{s}<c> <Rd>, <Rn>, #<const>"},
13052 // sub (sp minus immediate)
13053 {0x0fef0000, 0x024d0000, ARMvAll, eEncodingA1, No_VFP, eSize32,
13054 &EmulateInstructionARM::EmulateSUBSPImm, "sub{s}<c> <Rd>, sp, #<const>"},
13056 {0x0fe00010, 0x00400000, ARMvAll, eEncodingA1, No_VFP, eSize32,
13057 &EmulateInstructionARM::EmulateSUBReg,
13058 "sub{s}<c> <Rd>, <Rn>, <Rm>{,<shift>}"},
13060 {0x0ff0f000, 0x03300000, ARMvAll, eEncodingA1, No_VFP, eSize32,
13061 &EmulateInstructionARM::EmulateTEQImm, "teq<c> <Rn>, #const"},
13063 {0x0ff0f010, 0x01300000, ARMvAll, eEncodingA1, No_VFP, eSize32,
13064 &EmulateInstructionARM::EmulateTEQReg, "teq<c> <Rn>, <Rm> {,<shift>}"},
13066 {0x0ff0f000, 0x03100000, ARMvAll, eEncodingA1, No_VFP, eSize32,
13067 &EmulateInstructionARM::EmulateTSTImm, "tst<c> <Rn>, #const"},
13069 {0x0ff0f010, 0x01100000, ARMvAll, eEncodingA1, No_VFP, eSize32,
13070 &EmulateInstructionARM::EmulateTSTReg, "tst<c> <Rn>, <Rm> {,<shift>}"},
13073 {0x0fef0000, 0x03a00000, ARMvAll, eEncodingA1, No_VFP, eSize32,
13074 &EmulateInstructionARM::EmulateMOVRdImm, "mov{s}<c> <Rd>, #<const>"},
13075 {0x0ff00000, 0x03000000, ARMV6T2_ABOVE, eEncodingA2, No_VFP, eSize32,
13076 &EmulateInstructionARM::EmulateMOVRdImm, "movw<c> <Rd>, #<imm16>"},
13078 {0x0fef0ff0, 0x01a00000, ARMvAll, eEncodingA1, No_VFP, eSize32,
13079 &EmulateInstructionARM::EmulateMOVRdRm, "mov{s}<c> <Rd>, <Rm>"},
13081 {0x0fef0000, 0x03e00000, ARMvAll, eEncodingA1, No_VFP, eSize32,
13082 &EmulateInstructionARM::EmulateMVNImm, "mvn{s}<c> <Rd>, #<const>"},
13084 {0x0fef0010, 0x01e00000, ARMvAll, eEncodingA1, No_VFP, eSize32,
13085 &EmulateInstructionARM::EmulateMVNReg,
13086 "mvn{s}<c> <Rd>, <Rm> {,<shift>}"},
13088 {0x0ff0f000, 0x03700000, ARMvAll, eEncodingA1, No_VFP, eSize32,
13089 &EmulateInstructionARM::EmulateCMNImm, "cmn<c> <Rn>, #<const>"},
13091 {0x0ff0f010, 0x01700000, ARMvAll, eEncodingA1, No_VFP, eSize32,
13092 &EmulateInstructionARM::EmulateCMNReg, "cmn<c> <Rn>, <Rm> {,<shift>}"},
13094 {0x0ff0f000, 0x03500000, ARMvAll, eEncodingA1, No_VFP, eSize32,
13095 &EmulateInstructionARM::EmulateCMPImm, "cmp<c> <Rn>, #<const>"},
13097 {0x0ff0f010, 0x01500000, ARMvAll, eEncodingA1, No_VFP, eSize32,
13098 &EmulateInstructionARM::EmulateCMPReg, "cmp<c> <Rn>, <Rm> {,<shift>}"},
13100 {0x0fef0070, 0x01a00040, ARMvAll, eEncodingA1, No_VFP, eSize32,
13101 &EmulateInstructionARM::EmulateASRImm, "asr{s}<c> <Rd>, <Rm>, #imm"},
13103 {0x0fef00f0, 0x01a00050, ARMvAll, eEncodingA1, No_VFP, eSize32,
13104 &EmulateInstructionARM::EmulateASRReg, "asr{s}<c> <Rd>, <Rn>, <Rm>"},
13106 {0x0fef0070, 0x01a00000, ARMvAll, eEncodingA1, No_VFP, eSize32,
13107 &EmulateInstructionARM::EmulateLSLImm, "lsl{s}<c> <Rd>, <Rm>, #imm"},
13109 {0x0fef00f0, 0x01a00010, ARMvAll, eEncodingA1, No_VFP, eSize32,
13110 &EmulateInstructionARM::EmulateLSLReg, "lsl{s}<c> <Rd>, <Rn>, <Rm>"},
13112 {0x0fef0070, 0x01a00020, ARMvAll, eEncodingA1, No_VFP, eSize32,
13113 &EmulateInstructionARM::EmulateLSRImm, "lsr{s}<c> <Rd>, <Rm>, #imm"},
13115 {0x0fef00f0, 0x01a00050, ARMvAll, eEncodingA1, No_VFP, eSize32,
13116 &EmulateInstructionARM::EmulateLSRReg, "lsr{s}<c> <Rd>, <Rn>, <Rm>"},
13117 // rrx is a special case encoding of ror (immediate)
13118 {0x0fef0ff0, 0x01a00060, ARMvAll, eEncodingA1, No_VFP, eSize32,
13119 &EmulateInstructionARM::EmulateRRX, "rrx{s}<c> <Rd>, <Rm>"},
13121 {0x0fef0070, 0x01a00060, ARMvAll, eEncodingA1, No_VFP, eSize32,
13122 &EmulateInstructionARM::EmulateRORImm, "ror{s}<c> <Rd>, <Rm>, #imm"},
13124 {0x0fef00f0, 0x01a00070, ARMvAll, eEncodingA1, No_VFP, eSize32,
13125 &EmulateInstructionARM::EmulateRORReg, "ror{s}<c> <Rd>, <Rn>, <Rm>"},
13127 {0x0fe000f0, 0x00000090, ARMvAll, eEncodingA1, No_VFP, eSize32,
13128 &EmulateInstructionARM::EmulateMUL, "mul{s}<c> <Rd>,<R>,<Rm>"},
13130 // subs pc, lr and related instructions
13131 {0x0e10f000, 0x0210f000, ARMvAll, eEncodingA1, No_VFP, eSize32,
13132 &EmulateInstructionARM::EmulateSUBSPcLrEtc,
13133 "<opc>S<c> PC,#<const> | <Rn>,#<const>"},
13134 {0x0e10f010, 0x0010f000, ARMvAll, eEncodingA2, No_VFP, eSize32,
13135 &EmulateInstructionARM::EmulateSUBSPcLrEtc,
13136 "<opc>S<c> PC,<Rn>,<Rm{,<shift>}"},
13138 //----------------------------------------------------------------------
13139 // Load instructions
13140 //----------------------------------------------------------------------
13141 {0x0fd00000, 0x08900000, ARMvAll, eEncodingA1, No_VFP, eSize32,
13142 &EmulateInstructionARM::EmulateLDM, "ldm<c> <Rn>{!} <registers>"},
13143 {0x0fd00000, 0x08100000, ARMvAll, eEncodingA1, No_VFP, eSize32,
13144 &EmulateInstructionARM::EmulateLDMDA, "ldmda<c> <Rn>{!} <registers>"},
13145 {0x0fd00000, 0x09100000, ARMvAll, eEncodingA1, No_VFP, eSize32,
13146 &EmulateInstructionARM::EmulateLDMDB, "ldmdb<c> <Rn>{!} <registers>"},
13147 {0x0fd00000, 0x09900000, ARMvAll, eEncodingA1, No_VFP, eSize32,
13148 &EmulateInstructionARM::EmulateLDMIB, "ldmib<c> <Rn<{!} <registers>"},
13149 {0x0e500000, 0x04100000, ARMvAll, eEncodingA1, No_VFP, eSize32,
13150 &EmulateInstructionARM::EmulateLDRImmediateARM,
13151 "ldr<c> <Rt> [<Rn> {#+/-<imm12>}]"},
13152 {0x0e500010, 0x06100000, ARMvAll, eEncodingA1, No_VFP, eSize32,
13153 &EmulateInstructionARM::EmulateLDRRegister,
13154 "ldr<c> <Rt> [<Rn> +/-<Rm> {<shift>}] {!}"},
13155 {0x0e5f0000, 0x045f0000, ARMvAll, eEncodingA1, No_VFP, eSize32,
13156 &EmulateInstructionARM::EmulateLDRBLiteral, "ldrb<c> <Rt>, [...]"},
13157 {0xfe500010, 0x06500000, ARMvAll, eEncodingA1, No_VFP, eSize32,
13158 &EmulateInstructionARM::EmulateLDRBRegister,
13159 "ldrb<c> <Rt>, [<Rn>,+/-<Rm>{, <shift>}]{!}"},
13160 {0x0e5f00f0, 0x005f00b0, ARMvAll, eEncodingA1, No_VFP, eSize32,
13161 &EmulateInstructionARM::EmulateLDRHLiteral, "ldrh<c> <Rt>, <label>"},
13162 {0x0e5000f0, 0x001000b0, ARMvAll, eEncodingA1, No_VFP, eSize32,
13163 &EmulateInstructionARM::EmulateLDRHRegister,
13164 "ldrh<c> <Rt>,[<Rn>,+/-<Rm>]{!}"},
13165 {0x0e5000f0, 0x005000d0, ARMvAll, eEncodingA1, No_VFP, eSize32,
13166 &EmulateInstructionARM::EmulateLDRSBImmediate,
13167 "ldrsb<c> <Rt>, [<Rn>{,#+/-<imm8>}]"},
13168 {0x0e5f00f0, 0x005f00d0, ARMvAll, eEncodingA1, No_VFP, eSize32,
13169 &EmulateInstructionARM::EmulateLDRSBLiteral, "ldrsb<c> <Rt> <label>"},
13170 {0x0e5000f0, 0x001000d0, ARMvAll, eEncodingA1, No_VFP, eSize32,
13171 &EmulateInstructionARM::EmulateLDRSBRegister,
13172 "ldrsb<c> <Rt>,[<Rn>,+/-<Rm>]{!}"},
13173 {0x0e5000f0, 0x005000f0, ARMvAll, eEncodingA1, No_VFP, eSize32,
13174 &EmulateInstructionARM::EmulateLDRSHImmediate,
13175 "ldrsh<c> <Rt>,[<Rn>{,#+/-<imm8>}]"},
13176 {0x0e5f00f0, 0x005f00f0, ARMvAll, eEncodingA1, No_VFP, eSize32,
13177 &EmulateInstructionARM::EmulateLDRSHLiteral, "ldrsh<c> <Rt>,<label>"},
13178 {0x0e5000f0, 0x001000f0, ARMvAll, eEncodingA1, No_VFP, eSize32,
13179 &EmulateInstructionARM::EmulateLDRSHRegister,
13180 "ldrsh<c> <Rt>,[<Rn>,+/-<Rm>]{!}"},
13181 {0x0e5000f0, 0x004000d0, ARMV5TE_ABOVE, eEncodingA1, No_VFP, eSize32,
13182 &EmulateInstructionARM::EmulateLDRDImmediate,
13183 "ldrd<c> <Rt>, <Rt2>, [<Rn>,#+/-<imm8>]!"},
13184 {0x0e500ff0, 0x000000d0, ARMV5TE_ABOVE, eEncodingA1, No_VFP, eSize32,
13185 &EmulateInstructionARM::EmulateLDRDRegister,
13186 "ldrd<c> <Rt>, <Rt2>, [<Rn>, +/-<Rm>]{!}"},
13187 {0x0e100f00, 0x0c100b00, ARMvAll, eEncodingA1, VFPv2_ABOVE, eSize32,
13188 &EmulateInstructionARM::EmulateVLDM, "vldm{mode}<c> <Rn>{!}, <list>"},
13189 {0x0e100f00, 0x0c100a00, ARMvAll, eEncodingA2, VFPv2v3, eSize32,
13190 &EmulateInstructionARM::EmulateVLDM, "vldm{mode}<c> <Rn>{!}, <list>"},
13191 {0x0f300f00, 0x0d100b00, ARMvAll, eEncodingA1, VFPv2_ABOVE, eSize32,
13192 &EmulateInstructionARM::EmulateVLDR, "vldr<c> <Dd>, [<Rn>{,#+/-<imm>}]"},
13193 {0x0f300f00, 0x0d100a00, ARMvAll, eEncodingA2, VFPv2v3, eSize32,
13194 &EmulateInstructionARM::EmulateVLDR, "vldr<c> <Sd>, [<Rn>{,#+/-<imm>}]"},
13195 {0xffb00000, 0xf4200000, ARMvAll, eEncodingA1, AdvancedSIMD, eSize32,
13196 &EmulateInstructionARM::EmulateVLD1Multiple,
13197 "vld1<c>.<size> <list>, [<Rn>{@<align>}], <Rm>"},
13198 {0xffb00300, 0xf4a00000, ARMvAll, eEncodingA1, AdvancedSIMD, eSize32,
13199 &EmulateInstructionARM::EmulateVLD1Single,
13200 "vld1<c>.<size> <list>, [<Rn>{@<align>}], <Rm>"},
13201 {0xffb00f00, 0xf4a00c00, ARMvAll, eEncodingA1, AdvancedSIMD, eSize32,
13202 &EmulateInstructionARM::EmulateVLD1SingleAll,
13203 "vld1<c>.<size> <list>, [<Rn>{@<align>}], <Rm>"},
13205 //----------------------------------------------------------------------
13206 // Store instructions
13207 //----------------------------------------------------------------------
13208 {0x0fd00000, 0x08800000, ARMvAll, eEncodingA1, No_VFP, eSize32,
13209 &EmulateInstructionARM::EmulateSTM, "stm<c> <Rn>{!} <registers>"},
13210 {0x0fd00000, 0x08000000, ARMvAll, eEncodingA1, No_VFP, eSize32,
13211 &EmulateInstructionARM::EmulateSTMDA, "stmda<c> <Rn>{!} <registers>"},
13212 {0x0fd00000, 0x09000000, ARMvAll, eEncodingA1, No_VFP, eSize32,
13213 &EmulateInstructionARM::EmulateSTMDB, "stmdb<c> <Rn>{!} <registers>"},
13214 {0x0fd00000, 0x09800000, ARMvAll, eEncodingA1, No_VFP, eSize32,
13215 &EmulateInstructionARM::EmulateSTMIB, "stmib<c> <Rn>{!} <registers>"},
13216 {0x0e500010, 0x06000000, ARMvAll, eEncodingA1, No_VFP, eSize32,
13217 &EmulateInstructionARM::EmulateSTRRegister,
13218 "str<c> <Rt> [<Rn> +/-<Rm> {<shift>}]{!}"},
13219 {0x0e5000f0, 0x000000b0, ARMvAll, eEncodingA1, No_VFP, eSize32,
13220 &EmulateInstructionARM::EmulateSTRHRegister,
13221 "strh<c> <Rt>,[<Rn>,+/-<Rm>[{!}"},
13222 {0x0ff00ff0, 0x01800f90, ARMV6_ABOVE, eEncodingA1, No_VFP, eSize32,
13223 &EmulateInstructionARM::EmulateSTREX, "strex<c> <Rd>, <Rt>, [<Rn>]"},
13224 {0x0e500000, 0x04400000, ARMvAll, eEncodingA1, No_VFP, eSize32,
13225 &EmulateInstructionARM::EmulateSTRBImmARM,
13226 "strb<c> <Rt>,[<Rn>,#+/-<imm12>]!"},
13227 {0x0e500000, 0x04000000, ARMvAll, eEncodingA1, No_VFP, eSize32,
13228 &EmulateInstructionARM::EmulateSTRImmARM,
13229 "str<c> <Rt>,[<Rn>,#+/-<imm12>]!"},
13230 {0x0e5000f0, 0x004000f0, ARMV5TE_ABOVE, eEncodingA1, No_VFP, eSize32,
13231 &EmulateInstructionARM::EmulateSTRDImm,
13232 "strd<c> <Rt>, <Rt2>, [<Rn> #+/-<imm8>]!"},
13233 {0x0e500ff0, 0x000000f0, ARMV5TE_ABOVE, eEncodingA1, No_VFP, eSize32,
13234 &EmulateInstructionARM::EmulateSTRDReg,
13235 "strd<c> <Rt>, <Rt2>, [<Rn>, +/-<Rm>]{!}"},
13236 {0x0e100f00, 0x0c000b00, ARMvAll, eEncodingA1, VFPv2_ABOVE, eSize32,
13237 &EmulateInstructionARM::EmulateVSTM, "vstm{mode}<c> <Rn>{!} <list>"},
13238 {0x0e100f00, 0x0c000a00, ARMvAll, eEncodingA2, VFPv2v3, eSize32,
13239 &EmulateInstructionARM::EmulateVSTM, "vstm{mode}<c> <Rn>{!} <list>"},
13240 {0x0f300f00, 0x0d000b00, ARMvAll, eEncodingA1, VFPv2_ABOVE, eSize32,
13241 &EmulateInstructionARM::EmulateVSTR, "vstr<c> <Dd> [<Rn>{,#+/-<imm>}]"},
13242 {0x0f300f00, 0x0d000a00, ARMvAll, eEncodingA2, VFPv2v3, eSize32,
13243 &EmulateInstructionARM::EmulateVSTR, "vstr<c> <Sd> [<Rn>{,#+/-<imm>}]"},
13244 {0xffb00000, 0xf4000000, ARMvAll, eEncodingA1, AdvancedSIMD, eSize32,
13245 &EmulateInstructionARM::EmulateVST1Multiple,
13246 "vst1<c>.<size> <list>, [<Rn>{@<align>}], <Rm>"},
13247 {0xffb00300, 0xf4800000, ARMvAll, eEncodingA1, AdvancedSIMD, eSize32,
13248 &EmulateInstructionARM::EmulateVST1Single,
13249 "vst1<c>.<size> <list>, [<Rn>{@<align>}], <Rm>"},
13251 //----------------------------------------------------------------------
13252 // Other instructions
13253 //----------------------------------------------------------------------
13254 {0x0fff00f0, 0x06af00f0, ARMV6_ABOVE, eEncodingA1, No_VFP, eSize32,
13255 &EmulateInstructionARM::EmulateSXTB, "sxtb<c> <Rd>,<Rm>{,<rotation>}"},
13256 {0x0fff00f0, 0x06bf0070, ARMV6_ABOVE, eEncodingA1, No_VFP, eSize32,
13257 &EmulateInstructionARM::EmulateSXTH, "sxth<c> <Rd>,<Rm>{,<rotation>}"},
13258 {0x0fff00f0, 0x06ef0070, ARMV6_ABOVE, eEncodingA1, No_VFP, eSize32,
13259 &EmulateInstructionARM::EmulateUXTB, "uxtb<c> <Rd>,<Rm>{,<rotation>}"},
13260 {0x0fff00f0, 0x06ff0070, ARMV6_ABOVE, eEncodingA1, No_VFP, eSize32,
13261 &EmulateInstructionARM::EmulateUXTH, "uxth<c> <Rd>,<Rm>{,<rotation>}"},
13262 {0xfe500000, 0xf8100000, ARMV6_ABOVE, eEncodingA1, No_VFP, eSize32,
13263 &EmulateInstructionARM::EmulateRFE, "rfe{<amode>} <Rn>{!}"}
13266 static const size_t k_num_arm_opcodes = llvm::array_lengthof(g_arm_opcodes);
13268 for (size_t i = 0; i < k_num_arm_opcodes; ++i) {
13269 if ((g_arm_opcodes[i].mask & opcode) == g_arm_opcodes[i].value &&
13270 (g_arm_opcodes[i].variants & arm_isa) != 0)
13271 return &g_arm_opcodes[i];
13276 EmulateInstructionARM::ARMOpcode *
13277 EmulateInstructionARM::GetThumbOpcodeForInstruction(const uint32_t opcode,
13278 uint32_t arm_isa) {
13280 static ARMOpcode g_thumb_opcodes[] = {
13281 //----------------------------------------------------------------------
13282 // Prologue instructions
13283 //----------------------------------------------------------------------
13285 // push register(s)
13286 {0xfffffe00, 0x0000b400, ARMvAll, eEncodingT1, No_VFP, eSize16,
13287 &EmulateInstructionARM::EmulatePUSH, "push <registers>"},
13288 {0xffff0000, 0xe92d0000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
13289 &EmulateInstructionARM::EmulatePUSH, "push.w <registers>"},
13290 {0xffff0fff, 0xf84d0d04, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32,
13291 &EmulateInstructionARM::EmulatePUSH, "push.w <register>"},
13293 // set r7 to point to a stack offset
13294 {0xffffff00, 0x0000af00, ARMvAll, eEncodingT1, No_VFP, eSize16,
13295 &EmulateInstructionARM::EmulateADDRdSPImm, "add r7, sp, #imm"},
13296 // copy the stack pointer to r7
13297 {0xffffffff, 0x0000466f, ARMvAll, eEncodingT1, No_VFP, eSize16,
13298 &EmulateInstructionARM::EmulateMOVRdSP, "mov r7, sp"},
13299 // move from high register to low register (comes after "mov r7, sp" to
13300 // resolve ambiguity)
13301 {0xffffffc0, 0x00004640, ARMvAll, eEncodingT1, No_VFP, eSize16,
13302 &EmulateInstructionARM::EmulateMOVLowHigh, "mov r0-r7, r8-r15"},
13304 // PC-relative load into register (see also EmulateADDSPRm)
13305 {0xfffff800, 0x00004800, ARMvAll, eEncodingT1, No_VFP, eSize16,
13306 &EmulateInstructionARM::EmulateLDRRtPCRelative, "ldr <Rt>, [PC, #imm]"},
13308 // adjust the stack pointer
13309 {0xffffff87, 0x00004485, ARMvAll, eEncodingT2, No_VFP, eSize16,
13310 &EmulateInstructionARM::EmulateADDSPRm, "add sp, <Rm>"},
13311 {0xffffff80, 0x0000b080, ARMvAll, eEncodingT1, No_VFP, eSize16,
13312 &EmulateInstructionARM::EmulateSUBSPImm, "sub sp, sp, #imm"},
13313 {0xfbef8f00, 0xf1ad0d00, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
13314 &EmulateInstructionARM::EmulateSUBSPImm, "sub.w sp, sp, #<const>"},
13315 {0xfbff8f00, 0xf2ad0d00, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32,
13316 &EmulateInstructionARM::EmulateSUBSPImm, "subw sp, sp, #imm12"},
13317 {0xffef8000, 0xebad0000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32,
13318 &EmulateInstructionARM::EmulateSUBSPReg,
13319 "sub{s}<c> <Rd>, sp, <Rm>{,<shift>}"},
13321 // vector push consecutive extension register(s)
13322 {0xffbf0f00, 0xed2d0b00, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32,
13323 &EmulateInstructionARM::EmulateVPUSH, "vpush.64 <list>"},
13324 {0xffbf0f00, 0xed2d0a00, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
13325 &EmulateInstructionARM::EmulateVPUSH, "vpush.32 <list>"},
13327 //----------------------------------------------------------------------
13328 // Epilogue instructions
13329 //----------------------------------------------------------------------
13331 {0xfffff800, 0x0000a800, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16,
13332 &EmulateInstructionARM::EmulateADDSPImm, "add<c> <Rd>, sp, #imm"},
13333 {0xffffff80, 0x0000b000, ARMvAll, eEncodingT2, No_VFP, eSize16,
13334 &EmulateInstructionARM::EmulateADDSPImm, "add sp, #imm"},
13335 {0xfffffe00, 0x0000bc00, ARMvAll, eEncodingT1, No_VFP, eSize16,
13336 &EmulateInstructionARM::EmulatePOP, "pop <registers>"},
13337 {0xffff0000, 0xe8bd0000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
13338 &EmulateInstructionARM::EmulatePOP, "pop.w <registers>"},
13339 {0xffff0fff, 0xf85d0d04, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32,
13340 &EmulateInstructionARM::EmulatePOP, "pop.w <register>"},
13341 {0xffbf0f00, 0xecbd0b00, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32,
13342 &EmulateInstructionARM::EmulateVPOP, "vpop.64 <list>"},
13343 {0xffbf0f00, 0xecbd0a00, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
13344 &EmulateInstructionARM::EmulateVPOP, "vpop.32 <list>"},
13346 //----------------------------------------------------------------------
13347 // Supervisor Call (previously Software Interrupt)
13348 //----------------------------------------------------------------------
13349 {0xffffff00, 0x0000df00, ARMvAll, eEncodingT1, No_VFP, eSize16,
13350 &EmulateInstructionARM::EmulateSVC, "svc #imm8"},
13352 //----------------------------------------------------------------------
13353 // If Then makes up to four following instructions conditional.
13354 //----------------------------------------------------------------------
13355 // The next 5 opcode _must_ come before the if then instruction
13356 {0xffffffff, 0x0000bf00, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize16,
13357 &EmulateInstructionARM::EmulateNop, "nop"},
13358 {0xffffffff, 0x0000bf10, ARMV7_ABOVE, eEncodingT1, No_VFP, eSize16,
13359 &EmulateInstructionARM::EmulateNop, "nop YIELD (yield hint)"},
13360 {0xffffffff, 0x0000bf20, ARMV7_ABOVE, eEncodingT1, No_VFP, eSize16,
13361 &EmulateInstructionARM::EmulateNop, "nop WFE (wait for event hint)"},
13362 {0xffffffff, 0x0000bf30, ARMV7_ABOVE, eEncodingT1, No_VFP, eSize16,
13363 &EmulateInstructionARM::EmulateNop, "nop WFI (wait for interrupt hint)"},
13364 {0xffffffff, 0x0000bf40, ARMV7_ABOVE, eEncodingT1, No_VFP, eSize16,
13365 &EmulateInstructionARM::EmulateNop, "nop SEV (send event hint)"},
13366 {0xffffff00, 0x0000bf00, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize16,
13367 &EmulateInstructionARM::EmulateIT, "it{<x>{<y>{<z>}}} <firstcond>"},
13369 //----------------------------------------------------------------------
13370 // Branch instructions
13371 //----------------------------------------------------------------------
13372 // To resolve ambiguity, "b<c> #imm8" should come after "svc #imm8".
13373 {0xfffff000, 0x0000d000, ARMvAll, eEncodingT1, No_VFP, eSize16,
13374 &EmulateInstructionARM::EmulateB, "b<c> #imm8 (outside IT)"},
13375 {0xfffff800, 0x0000e000, ARMvAll, eEncodingT2, No_VFP, eSize16,
13376 &EmulateInstructionARM::EmulateB, "b<c> #imm11 (outside or last in IT)"},
13377 {0xf800d000, 0xf0008000, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32,
13378 &EmulateInstructionARM::EmulateB, "b<c>.w #imm8 (outside IT)"},
13379 {0xf800d000, 0xf0009000, ARMV6T2_ABOVE, eEncodingT4, No_VFP, eSize32,
13380 &EmulateInstructionARM::EmulateB,
13381 "b<c>.w #imm8 (outside or last in IT)"},
13383 {0xf800d000, 0xf000d000, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize32,
13384 &EmulateInstructionARM::EmulateBLXImmediate, "bl <label>"},
13386 {0xf800d001, 0xf000c000, ARMV5_ABOVE, eEncodingT2, No_VFP, eSize32,
13387 &EmulateInstructionARM::EmulateBLXImmediate, "blx <label>"},
13388 {0xffffff87, 0x00004780, ARMV5_ABOVE, eEncodingT1, No_VFP, eSize16,
13389 &EmulateInstructionARM::EmulateBLXRm, "blx <Rm>"},
13390 // for example, "bx lr"
13391 {0xffffff87, 0x00004700, ARMvAll, eEncodingT1, No_VFP, eSize32,
13392 &EmulateInstructionARM::EmulateBXRm, "bx <Rm>"},
13394 {0xfff0ffff, 0xf3c08f00, ARMV5J_ABOVE, eEncodingT1, No_VFP, eSize32,
13395 &EmulateInstructionARM::EmulateBXJRm, "bxj <Rm>"},
13396 // compare and branch
13397 {0xfffff500, 0x0000b100, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize16,
13398 &EmulateInstructionARM::EmulateCB, "cb{n}z <Rn>, <label>"},
13399 // table branch byte
13400 {0xfff0fff0, 0xe8d0f000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32,
13401 &EmulateInstructionARM::EmulateTB, "tbb<c> <Rn>, <Rm>"},
13402 // table branch halfword
13403 {0xfff0fff0, 0xe8d0f010, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32,
13404 &EmulateInstructionARM::EmulateTB, "tbh<c> <Rn>, <Rm>, lsl #1"},
13406 //----------------------------------------------------------------------
13407 // Data-processing instructions
13408 //----------------------------------------------------------------------
13410 {0xfbe08000, 0xf1400000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32,
13411 &EmulateInstructionARM::EmulateADCImm, "adc{s}<c> <Rd>, <Rn>, #<const>"},
13413 {0xffffffc0, 0x00004140, ARMvAll, eEncodingT1, No_VFP, eSize16,
13414 &EmulateInstructionARM::EmulateADCReg, "adcs|adc<c> <Rdn>, <Rm>"},
13415 {0xffe08000, 0xeb400000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
13416 &EmulateInstructionARM::EmulateADCReg,
13417 "adc{s}<c>.w <Rd>, <Rn>, <Rm> {,<shift>}"},
13419 {0xfffffe00, 0x00001800, ARMvAll, eEncodingT1, No_VFP, eSize16,
13420 &EmulateInstructionARM::EmulateADDReg, "adds|add<c> <Rd>, <Rn>, <Rm>"},
13421 // Make sure "add sp, <Rm>" comes before this instruction, so there's no
13422 // ambiguity decoding the two.
13423 {0xffffff00, 0x00004400, ARMvAll, eEncodingT2, No_VFP, eSize16,
13424 &EmulateInstructionARM::EmulateADDReg, "add<c> <Rdn>, <Rm>"},
13426 {0xfffff800, 0x0000a000, ARMvAll, eEncodingT1, No_VFP, eSize16,
13427 &EmulateInstructionARM::EmulateADR, "add<c> <Rd>, PC, #<const>"},
13428 {0xfbff8000, 0xf2af0000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
13429 &EmulateInstructionARM::EmulateADR, "sub<c> <Rd>, PC, #<const>"},
13430 {0xfbff8000, 0xf20f0000, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32,
13431 &EmulateInstructionARM::EmulateADR, "add<c> <Rd>, PC, #<const>"},
13433 {0xfbe08000, 0xf0000000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32,
13434 &EmulateInstructionARM::EmulateANDImm, "and{s}<c> <Rd>, <Rn>, #<const>"},
13436 {0xffffffc0, 0x00004000, ARMvAll, eEncodingT1, No_VFP, eSize16,
13437 &EmulateInstructionARM::EmulateANDReg, "ands|and<c> <Rdn>, <Rm>"},
13438 {0xffe08000, 0xea000000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
13439 &EmulateInstructionARM::EmulateANDReg,
13440 "and{s}<c>.w <Rd>, <Rn>, <Rm> {,<shift>}"},
13442 {0xfbe08000, 0xf0200000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32,
13443 &EmulateInstructionARM::EmulateBICImm, "bic{s}<c> <Rd>, <Rn>, #<const>"},
13445 {0xffffffc0, 0x00004380, ARMvAll, eEncodingT1, No_VFP, eSize16,
13446 &EmulateInstructionARM::EmulateBICReg, "bics|bic<c> <Rdn>, <Rm>"},
13447 {0xffe08000, 0xea200000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
13448 &EmulateInstructionARM::EmulateBICReg,
13449 "bic{s}<c>.w <Rd>, <Rn>, <Rm> {,<shift>}"},
13451 {0xfbe08000, 0xf0800000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32,
13452 &EmulateInstructionARM::EmulateEORImm, "eor{s}<c> <Rd>, <Rn>, #<const>"},
13454 {0xffffffc0, 0x00004040, ARMvAll, eEncodingT1, No_VFP, eSize16,
13455 &EmulateInstructionARM::EmulateEORReg, "eors|eor<c> <Rdn>, <Rm>"},
13456 {0xffe08000, 0xea800000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
13457 &EmulateInstructionARM::EmulateEORReg,
13458 "eor{s}<c>.w <Rd>, <Rn>, <Rm> {,<shift>}"},
13460 {0xfbe08000, 0xf0400000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32,
13461 &EmulateInstructionARM::EmulateORRImm, "orr{s}<c> <Rd>, <Rn>, #<const>"},
13463 {0xffffffc0, 0x00004300, ARMvAll, eEncodingT1, No_VFP, eSize16,
13464 &EmulateInstructionARM::EmulateORRReg, "orrs|orr<c> <Rdn>, <Rm>"},
13465 {0xffe08000, 0xea400000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
13466 &EmulateInstructionARM::EmulateORRReg,
13467 "orr{s}<c>.w <Rd>, <Rn>, <Rm> {,<shift>}"},
13469 {0xffffffc0, 0x00004240, ARMvAll, eEncodingT1, No_VFP, eSize16,
13470 &EmulateInstructionARM::EmulateRSBImm, "rsbs|rsb<c> <Rd>, <Rn>, #0"},
13471 {0xfbe08000, 0xf1c00000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
13472 &EmulateInstructionARM::EmulateRSBImm,
13473 "rsb{s}<c>.w <Rd>, <Rn>, #<const>"},
13475 {0xffe08000, 0xea400000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32,
13476 &EmulateInstructionARM::EmulateRSBReg,
13477 "rsb{s}<c>.w <Rd>, <Rn>, <Rm> {,<shift>}"},
13479 {0xfbe08000, 0xf1600000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32,
13480 &EmulateInstructionARM::EmulateSBCImm, "sbc{s}<c> <Rd>, <Rn>, #<const>"},
13482 {0xffffffc0, 0x00004180, ARMvAll, eEncodingT1, No_VFP, eSize16,
13483 &EmulateInstructionARM::EmulateSBCReg, "sbcs|sbc<c> <Rdn>, <Rm>"},
13484 {0xffe08000, 0xeb600000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
13485 &EmulateInstructionARM::EmulateSBCReg,
13486 "sbc{s}<c>.w <Rd>, <Rn>, <Rm> {,<shift>}"},
13487 // add (immediate, Thumb)
13488 {0xfffffe00, 0x00001c00, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16,
13489 &EmulateInstructionARM::EmulateADDImmThumb,
13490 "adds|add<c> <Rd>,<Rn>,#<imm3>"},
13491 {0xfffff800, 0x00003000, ARMV4T_ABOVE, eEncodingT2, No_VFP, eSize16,
13492 &EmulateInstructionARM::EmulateADDImmThumb, "adds|add<c> <Rdn>,#<imm8>"},
13493 {0xfbe08000, 0xf1000000, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32,
13494 &EmulateInstructionARM::EmulateADDImmThumb,
13495 "add{s}<c>.w <Rd>,<Rn>,#<const>"},
13496 {0xfbf08000, 0xf2000000, ARMV6T2_ABOVE, eEncodingT4, No_VFP, eSize32,
13497 &EmulateInstructionARM::EmulateADDImmThumb,
13498 "addw<c> <Rd>,<Rn>,#<imm12>"},
13499 // sub (immediate, Thumb)
13500 {0xfffffe00, 0x00001e00, ARMvAll, eEncodingT1, No_VFP, eSize16,
13501 &EmulateInstructionARM::EmulateSUBImmThumb,
13502 "subs|sub<c> <Rd>, <Rn> #imm3"},
13503 {0xfffff800, 0x00003800, ARMvAll, eEncodingT2, No_VFP, eSize16,
13504 &EmulateInstructionARM::EmulateSUBImmThumb, "subs|sub<c> <Rdn>, #imm8"},
13505 {0xfbe08000, 0xf1a00000, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32,
13506 &EmulateInstructionARM::EmulateSUBImmThumb,
13507 "sub{s}<c>.w <Rd>, <Rn>, #<const>"},
13508 {0xfbf08000, 0xf2a00000, ARMV6T2_ABOVE, eEncodingT4, No_VFP, eSize32,
13509 &EmulateInstructionARM::EmulateSUBImmThumb,
13510 "subw<c> <Rd>, <Rn>, #imm12"},
13511 // sub (sp minus immediate)
13512 {0xfbef8000, 0xf1ad0000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
13513 &EmulateInstructionARM::EmulateSUBSPImm, "sub{s}.w <Rd>, sp, #<const>"},
13514 {0xfbff8000, 0xf2ad0000, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32,
13515 &EmulateInstructionARM::EmulateSUBSPImm, "subw<c> <Rd>, sp, #imm12"},
13517 {0xfffffe00, 0x00001a00, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16,
13518 &EmulateInstructionARM::EmulateSUBReg, "subs|sub<c> <Rd>, <Rn>, <Rm>"},
13519 {0xffe08000, 0xeba00000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
13520 &EmulateInstructionARM::EmulateSUBReg,
13521 "sub{s}<c>.w <Rd>, <Rn>, <Rm>{,<shift>}"},
13523 {0xfbf08f00, 0xf0900f00, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32,
13524 &EmulateInstructionARM::EmulateTEQImm, "teq<c> <Rn>, #<const>"},
13526 {0xfff08f00, 0xea900f00, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32,
13527 &EmulateInstructionARM::EmulateTEQReg, "teq<c> <Rn>, <Rm> {,<shift>}"},
13529 {0xfbf08f00, 0xf0100f00, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32,
13530 &EmulateInstructionARM::EmulateTSTImm, "tst<c> <Rn>, #<const>"},
13532 {0xffffffc0, 0x00004200, ARMvAll, eEncodingT1, No_VFP, eSize16,
13533 &EmulateInstructionARM::EmulateTSTReg, "tst<c> <Rdn>, <Rm>"},
13534 {0xfff08f00, 0xea100f00, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
13535 &EmulateInstructionARM::EmulateTSTReg, "tst<c>.w <Rn>, <Rm> {,<shift>}"},
13537 // move from high register to high register
13538 {0xffffff00, 0x00004600, ARMvAll, eEncodingT1, No_VFP, eSize16,
13539 &EmulateInstructionARM::EmulateMOVRdRm, "mov<c> <Rd>, <Rm>"},
13540 // move from low register to low register
13541 {0xffffffc0, 0x00000000, ARMvAll, eEncodingT2, No_VFP, eSize16,
13542 &EmulateInstructionARM::EmulateMOVRdRm, "movs <Rd>, <Rm>"},
13543 // mov{s}<c>.w <Rd>, <Rm>
13544 {0xffeff0f0, 0xea4f0000, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32,
13545 &EmulateInstructionARM::EmulateMOVRdRm, "mov{s}<c>.w <Rd>, <Rm>"},
13547 {0xfffff800, 0x00002000, ARMvAll, eEncodingT1, No_VFP, eSize16,
13548 &EmulateInstructionARM::EmulateMOVRdImm, "movs|mov<c> <Rd>, #imm8"},
13549 {0xfbef8000, 0xf04f0000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
13550 &EmulateInstructionARM::EmulateMOVRdImm, "mov{s}<c>.w <Rd>, #<const>"},
13551 {0xfbf08000, 0xf2400000, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32,
13552 &EmulateInstructionARM::EmulateMOVRdImm, "movw<c> <Rd>,#<imm16>"},
13554 {0xfbef8000, 0xf06f0000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32,
13555 &EmulateInstructionARM::EmulateMVNImm, "mvn{s} <Rd>, #<const>"},
13557 {0xffffffc0, 0x000043c0, ARMvAll, eEncodingT1, No_VFP, eSize16,
13558 &EmulateInstructionARM::EmulateMVNReg, "mvns|mvn<c> <Rd>, <Rm>"},
13559 {0xffef8000, 0xea6f0000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
13560 &EmulateInstructionARM::EmulateMVNReg,
13561 "mvn{s}<c>.w <Rd>, <Rm> {,<shift>}"},
13563 {0xfbf08f00, 0xf1100f00, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32,
13564 &EmulateInstructionARM::EmulateCMNImm, "cmn<c> <Rn>, #<const>"},
13566 {0xffffffc0, 0x000042c0, ARMvAll, eEncodingT1, No_VFP, eSize16,
13567 &EmulateInstructionARM::EmulateCMNReg, "cmn<c> <Rn>, <Rm>"},
13568 {0xfff08f00, 0xeb100f00, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
13569 &EmulateInstructionARM::EmulateCMNReg, "cmn<c> <Rn>, <Rm> {,<shift>}"},
13571 {0xfffff800, 0x00002800, ARMvAll, eEncodingT1, No_VFP, eSize16,
13572 &EmulateInstructionARM::EmulateCMPImm, "cmp<c> <Rn>, #imm8"},
13573 {0xfbf08f00, 0xf1b00f00, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
13574 &EmulateInstructionARM::EmulateCMPImm, "cmp<c>.w <Rn>, #<const>"},
13575 // cmp (register) (Rn and Rm both from r0-r7)
13576 {0xffffffc0, 0x00004280, ARMvAll, eEncodingT1, No_VFP, eSize16,
13577 &EmulateInstructionARM::EmulateCMPReg, "cmp<c> <Rn>, <Rm>"},
13578 // cmp (register) (Rn and Rm not both from r0-r7)
13579 {0xffffff00, 0x00004500, ARMvAll, eEncodingT2, No_VFP, eSize16,
13580 &EmulateInstructionARM::EmulateCMPReg, "cmp<c> <Rn>, <Rm>"},
13581 {0xfff08f00, 0xebb00f00, ARMvAll, eEncodingT3, No_VFP, eSize16,
13582 &EmulateInstructionARM::EmulateCMPReg,
13583 "cmp<c>.w <Rn>, <Rm> {, <shift>}"},
13585 {0xfffff800, 0x00001000, ARMvAll, eEncodingT1, No_VFP, eSize16,
13586 &EmulateInstructionARM::EmulateASRImm, "asrs|asr<c> <Rd>, <Rm>, #imm"},
13587 {0xffef8030, 0xea4f0020, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
13588 &EmulateInstructionARM::EmulateASRImm, "asr{s}<c>.w <Rd>, <Rm>, #imm"},
13590 {0xffffffc0, 0x00004100, ARMvAll, eEncodingT1, No_VFP, eSize16,
13591 &EmulateInstructionARM::EmulateASRReg, "asrs|asr<c> <Rdn>, <Rm>"},
13592 {0xffe0f0f0, 0xfa40f000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
13593 &EmulateInstructionARM::EmulateASRReg, "asr{s}<c>.w <Rd>, <Rn>, <Rm>"},
13595 {0xfffff800, 0x00000000, ARMvAll, eEncodingT1, No_VFP, eSize16,
13596 &EmulateInstructionARM::EmulateLSLImm, "lsls|lsl<c> <Rd>, <Rm>, #imm"},
13597 {0xffef8030, 0xea4f0000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
13598 &EmulateInstructionARM::EmulateLSLImm, "lsl{s}<c>.w <Rd>, <Rm>, #imm"},
13600 {0xffffffc0, 0x00004080, ARMvAll, eEncodingT1, No_VFP, eSize16,
13601 &EmulateInstructionARM::EmulateLSLReg, "lsls|lsl<c> <Rdn>, <Rm>"},
13602 {0xffe0f0f0, 0xfa00f000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
13603 &EmulateInstructionARM::EmulateLSLReg, "lsl{s}<c>.w <Rd>, <Rn>, <Rm>"},
13605 {0xfffff800, 0x00000800, ARMvAll, eEncodingT1, No_VFP, eSize16,
13606 &EmulateInstructionARM::EmulateLSRImm, "lsrs|lsr<c> <Rd>, <Rm>, #imm"},
13607 {0xffef8030, 0xea4f0010, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
13608 &EmulateInstructionARM::EmulateLSRImm, "lsr{s}<c>.w <Rd>, <Rm>, #imm"},
13610 {0xffffffc0, 0x000040c0, ARMvAll, eEncodingT1, No_VFP, eSize16,
13611 &EmulateInstructionARM::EmulateLSRReg, "lsrs|lsr<c> <Rdn>, <Rm>"},
13612 {0xffe0f0f0, 0xfa20f000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
13613 &EmulateInstructionARM::EmulateLSRReg, "lsr{s}<c>.w <Rd>, <Rn>, <Rm>"},
13614 // rrx is a special case encoding of ror (immediate)
13615 {0xffeff0f0, 0xea4f0030, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32,
13616 &EmulateInstructionARM::EmulateRRX, "rrx{s}<c>.w <Rd>, <Rm>"},
13618 {0xffef8030, 0xea4f0030, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32,
13619 &EmulateInstructionARM::EmulateRORImm, "ror{s}<c>.w <Rd>, <Rm>, #imm"},
13621 {0xffffffc0, 0x000041c0, ARMvAll, eEncodingT1, No_VFP, eSize16,
13622 &EmulateInstructionARM::EmulateRORReg, "rors|ror<c> <Rdn>, <Rm>"},
13623 {0xffe0f0f0, 0xfa60f000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
13624 &EmulateInstructionARM::EmulateRORReg, "ror{s}<c>.w <Rd>, <Rn>, <Rm>"},
13626 {0xffffffc0, 0x00004340, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16,
13627 &EmulateInstructionARM::EmulateMUL, "muls <Rdm>,<Rn>,<Rdm>"},
13629 {0xfff0f0f0, 0xfb00f000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
13630 &EmulateInstructionARM::EmulateMUL, "mul<c> <Rd>,<Rn>,<Rm>"},
13632 // subs pc, lr and related instructions
13633 {0xffffff00, 0xf3de8f00, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32,
13634 &EmulateInstructionARM::EmulateSUBSPcLrEtc, "SUBS<c> PC, LR, #<imm8>"},
13636 //----------------------------------------------------------------------
13637 // RFE instructions *** IMPORTANT *** THESE MUST BE LISTED **BEFORE** THE
13638 // LDM.. Instructions in this table;
13639 // otherwise the wrong instructions will be selected.
13640 //----------------------------------------------------------------------
13642 {0xffd0ffff, 0xe810c000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32,
13643 &EmulateInstructionARM::EmulateRFE, "rfedb<c> <Rn>{!}"},
13644 {0xffd0ffff, 0xe990c000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
13645 &EmulateInstructionARM::EmulateRFE, "rfe{ia}<c> <Rn>{!}"},
13647 //----------------------------------------------------------------------
13648 // Load instructions
13649 //----------------------------------------------------------------------
13650 {0xfffff800, 0x0000c800, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16,
13651 &EmulateInstructionARM::EmulateLDM, "ldm<c> <Rn>{!} <registers>"},
13652 {0xffd02000, 0xe8900000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
13653 &EmulateInstructionARM::EmulateLDM, "ldm<c>.w <Rn>{!} <registers>"},
13654 {0xffd00000, 0xe9100000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32,
13655 &EmulateInstructionARM::EmulateLDMDB, "ldmdb<c> <Rn>{!} <registers>"},
13656 {0xfffff800, 0x00006800, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16,
13657 &EmulateInstructionARM::EmulateLDRRtRnImm, "ldr<c> <Rt>, [<Rn>{,#imm}]"},
13658 {0xfffff800, 0x00009800, ARMV4T_ABOVE, eEncodingT2, No_VFP, eSize16,
13659 &EmulateInstructionARM::EmulateLDRRtRnImm, "ldr<c> <Rt>, [SP{,#imm}]"},
13660 {0xfff00000, 0xf8d00000, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32,
13661 &EmulateInstructionARM::EmulateLDRRtRnImm,
13662 "ldr<c>.w <Rt>, [<Rn>{,#imm12}]"},
13663 {0xfff00800, 0xf8500800, ARMV6T2_ABOVE, eEncodingT4, No_VFP, eSize32,
13664 &EmulateInstructionARM::EmulateLDRRtRnImm,
13665 "ldr<c> <Rt>, [<Rn>{,#+/-<imm8>}]{!}"},
13666 // Thumb2 PC-relative load into register
13667 {0xff7f0000, 0xf85f0000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
13668 &EmulateInstructionARM::EmulateLDRRtPCRelative,
13669 "ldr<c>.w <Rt>, [PC, +/-#imm}]"},
13670 {0xfffffe00, 0x00005800, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16,
13671 &EmulateInstructionARM::EmulateLDRRegister, "ldr<c> <Rt>, [<Rn>, <Rm>]"},
13672 {0xfff00fc0, 0xf8500000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
13673 &EmulateInstructionARM::EmulateLDRRegister,
13674 "ldr<c>.w <Rt>, [<Rn>,<Rm>{,LSL #<imm2>}]"},
13675 {0xfffff800, 0x00007800, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16,
13676 &EmulateInstructionARM::EmulateLDRBImmediate,
13677 "ldrb<c> <Rt>,[<Rn>{,#<imm5>}]"},
13678 {0xfff00000, 0xf8900000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
13679 &EmulateInstructionARM::EmulateLDRBImmediate,
13680 "ldrb<c>.w <Rt>,[<Rn>{,#<imm12>}]"},
13681 {0xfff00800, 0xf8100800, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32,
13682 &EmulateInstructionARM::EmulateLDRBImmediate,
13683 "ldrb<c> <Rt>,[<Rn>, #+/-<imm8>]{!}"},
13684 {0xff7f0000, 0xf81f0000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32,
13685 &EmulateInstructionARM::EmulateLDRBLiteral, "ldrb<c> <Rt>,[...]"},
13686 {0xfffffe00, 0x00005c00, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize16,
13687 &EmulateInstructionARM::EmulateLDRBRegister, "ldrb<c> <Rt>,[<Rn>,<Rm>]"},
13688 {0xfff00fc0, 0xf8100000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
13689 &EmulateInstructionARM::EmulateLDRBRegister,
13690 "ldrb<c>.w <Rt>,[<Rn>,<Rm>{,LSL #imm2>}]"},
13691 {0xfffff800, 0x00008800, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16,
13692 &EmulateInstructionARM::EmulateLDRHImmediate,
13693 "ldrh<c> <Rt>, [<Rn>{,#<imm>}]"},
13694 {0xfff00000, 0xf8b00000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
13695 &EmulateInstructionARM::EmulateLDRHImmediate,
13696 "ldrh<c>.w <Rt>,[<Rn>{,#<imm12>}]"},
13697 {0xfff00800, 0xf8300800, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32,
13698 &EmulateInstructionARM::EmulateLDRHImmediate,
13699 "ldrh<c> <Rt>,[<Rn>,#+/-<imm8>]{!}"},
13700 {0xff7f0000, 0xf83f0000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32,
13701 &EmulateInstructionARM::EmulateLDRHLiteral, "ldrh<c> <Rt>, <label>"},
13702 {0xfffffe00, 0x00005a00, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16,
13703 &EmulateInstructionARM::EmulateLDRHRegister,
13704 "ldrh<c> <Rt>, [<Rn>,<Rm>]"},
13705 {0xfff00fc0, 0xf8300000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
13706 &EmulateInstructionARM::EmulateLDRHRegister,
13707 "ldrh<c>.w <Rt>,[<Rn>,<Rm>{,LSL #<imm2>}]"},
13708 {0xfff00000, 0xf9900000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32,
13709 &EmulateInstructionARM::EmulateLDRSBImmediate,
13710 "ldrsb<c> <Rt>,[<Rn>,#<imm12>]"},
13711 {0xfff00800, 0xf9100800, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
13712 &EmulateInstructionARM::EmulateLDRSBImmediate,
13713 "ldrsb<c> <Rt>,[<Rn>,#+/-<imm8>]"},
13714 {0xff7f0000, 0xf91f0000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32,
13715 &EmulateInstructionARM::EmulateLDRSBLiteral, "ldrsb<c> <Rt>, <label>"},
13716 {0xfffffe00, 0x00005600, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16,
13717 &EmulateInstructionARM::EmulateLDRSBRegister,
13718 "ldrsb<c> <Rt>,[<Rn>,<Rm>]"},
13719 {0xfff00fc0, 0xf9100000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
13720 &EmulateInstructionARM::EmulateLDRSBRegister,
13721 "ldrsb<c>.w <Rt>,[<Rn>,<Rm>{,LSL #imm2>}]"},
13722 {0xfff00000, 0xf9b00000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32,
13723 &EmulateInstructionARM::EmulateLDRSHImmediate,
13724 "ldrsh<c> <Rt>,[<Rn>,#<imm12>]"},
13725 {0xfff00800, 0xf9300800, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
13726 &EmulateInstructionARM::EmulateLDRSHImmediate,
13727 "ldrsh<c> <Rt>,[<Rn>,#+/-<imm8>]"},
13728 {0xff7f0000, 0xf93f0000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32,
13729 &EmulateInstructionARM::EmulateLDRSHLiteral, "ldrsh<c> <Rt>,<label>"},
13730 {0xfffffe00, 0x00005e00, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16,
13731 &EmulateInstructionARM::EmulateLDRSHRegister,
13732 "ldrsh<c> <Rt>,[<Rn>,<Rm>]"},
13733 {0xfff00fc0, 0xf9300000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
13734 &EmulateInstructionARM::EmulateLDRSHRegister,
13735 "ldrsh<c>.w <Rt>,[<Rn>,<Rm>{,LSL #<imm2>}]"},
13736 {0xfe500000, 0xe8500000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32,
13737 &EmulateInstructionARM::EmulateLDRDImmediate,
13738 "ldrd<c> <Rt>, <Rt2>, [<Rn>,#+/-<imm>]!"},
13739 {0xfe100f00, 0xec100b00, ARMvAll, eEncodingT1, VFPv2_ABOVE, eSize32,
13740 &EmulateInstructionARM::EmulateVLDM, "vldm{mode}<c> <Rn>{!}, <list>"},
13741 {0xfe100f00, 0xec100a00, ARMvAll, eEncodingT2, VFPv2v3, eSize32,
13742 &EmulateInstructionARM::EmulateVLDM, "vldm{mode}<c> <Rn>{!}, <list>"},
13743 {0xffe00f00, 0xed100b00, ARMvAll, eEncodingT1, VFPv2_ABOVE, eSize32,
13744 &EmulateInstructionARM::EmulateVLDR, "vldr<c> <Dd>, [<Rn>{,#+/-<imm>}]"},
13745 {0xff300f00, 0xed100a00, ARMvAll, eEncodingT2, VFPv2v3, eSize32,
13746 &EmulateInstructionARM::EmulateVLDR, "vldr<c> <Sd>, {<Rn>{,#+/-<imm>}]"},
13747 {0xffb00000, 0xf9200000, ARMvAll, eEncodingT1, AdvancedSIMD, eSize32,
13748 &EmulateInstructionARM::EmulateVLD1Multiple,
13749 "vld1<c>.<size> <list>, [<Rn>{@<align>}],<Rm>"},
13750 {0xffb00300, 0xf9a00000, ARMvAll, eEncodingT1, AdvancedSIMD, eSize32,
13751 &EmulateInstructionARM::EmulateVLD1Single,
13752 "vld1<c>.<size> <list>, [<Rn>{@<align>}],<Rm>"},
13753 {0xffb00f00, 0xf9a00c00, ARMvAll, eEncodingT1, AdvancedSIMD, eSize32,
13754 &EmulateInstructionARM::EmulateVLD1SingleAll,
13755 "vld1<c>.<size> <list>, [<Rn>{@<align>}], <Rm>"},
13757 //----------------------------------------------------------------------
13758 // Store instructions
13759 //----------------------------------------------------------------------
13760 {0xfffff800, 0x0000c000, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16,
13761 &EmulateInstructionARM::EmulateSTM, "stm<c> <Rn>{!} <registers>"},
13762 {0xffd00000, 0xe8800000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
13763 &EmulateInstructionARM::EmulateSTM, "stm<c>.w <Rn>{!} <registers>"},
13764 {0xffd00000, 0xe9000000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32,
13765 &EmulateInstructionARM::EmulateSTMDB, "stmdb<c> <Rn>{!} <registers>"},
13766 {0xfffff800, 0x00006000, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16,
13767 &EmulateInstructionARM::EmulateSTRThumb, "str<c> <Rt>, [<Rn>{,#<imm>}]"},
13768 {0xfffff800, 0x00009000, ARMV4T_ABOVE, eEncodingT2, No_VFP, eSize16,
13769 &EmulateInstructionARM::EmulateSTRThumb, "str<c> <Rt>, [SP,#<imm>]"},
13770 {0xfff00000, 0xf8c00000, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32,
13771 &EmulateInstructionARM::EmulateSTRThumb,
13772 "str<c>.w <Rt>, [<Rn>,#<imm12>]"},
13773 {0xfff00800, 0xf8400800, ARMV6T2_ABOVE, eEncodingT4, No_VFP, eSize32,
13774 &EmulateInstructionARM::EmulateSTRThumb,
13775 "str<c> <Rt>, [<Rn>,#+/-<imm8>]"},
13776 {0xfffffe00, 0x00005000, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16,
13777 &EmulateInstructionARM::EmulateSTRRegister, "str<c> <Rt> ,{<Rn>, <Rm>]"},
13778 {0xfff00fc0, 0xf8400000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
13779 &EmulateInstructionARM::EmulateSTRRegister,
13780 "str<c>.w <Rt>, [<Rn>, <Rm> {lsl #imm2>}]"},
13781 {0xfffff800, 0x00007000, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16,
13782 &EmulateInstructionARM::EmulateSTRBThumb,
13783 "strb<c> <Rt>, [<Rn>, #<imm5>]"},
13784 {0xfff00000, 0xf8800000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
13785 &EmulateInstructionARM::EmulateSTRBThumb,
13786 "strb<c>.w <Rt>, [<Rn>, #<imm12>]"},
13787 {0xfff00800, 0xf8000800, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32,
13788 &EmulateInstructionARM::EmulateSTRBThumb,
13789 "strb<c> <Rt> ,[<Rn>, #+/-<imm8>]{!}"},
13790 {0xfffffe00, 0x00005200, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16,
13791 &EmulateInstructionARM::EmulateSTRHRegister, "strh<c> <Rt>,[<Rn>,<Rm>]"},
13792 {0xfff00fc0, 0xf8200000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
13793 &EmulateInstructionARM::EmulateSTRHRegister,
13794 "strh<c>.w <Rt>,[<Rn>,<Rm>{,LSL #<imm2>}]"},
13795 {0xfff00000, 0xe8400000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32,
13796 &EmulateInstructionARM::EmulateSTREX,
13797 "strex<c> <Rd>, <Rt>, [<Rn{,#<imm>}]"},
13798 {0xfe500000, 0xe8400000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32,
13799 &EmulateInstructionARM::EmulateSTRDImm,
13800 "strd<c> <Rt>, <Rt2>, [<Rn>, #+/-<imm>]!"},
13801 {0xfe100f00, 0xec000b00, ARMvAll, eEncodingT1, VFPv2_ABOVE, eSize32,
13802 &EmulateInstructionARM::EmulateVSTM, "vstm{mode}<c> <Rn>{!}, <list>"},
13803 {0xfea00f00, 0xec000a00, ARMvAll, eEncodingT2, VFPv2v3, eSize32,
13804 &EmulateInstructionARM::EmulateVSTM, "vstm{mode}<c> <Rn>{!}, <list>"},
13805 {0xff300f00, 0xed000b00, ARMvAll, eEncodingT1, VFPv2_ABOVE, eSize32,
13806 &EmulateInstructionARM::EmulateVSTR, "vstr<c> <Dd>, [<Rn>{,#+/-<imm>}]"},
13807 {0xff300f00, 0xed000a00, ARMvAll, eEncodingT2, VFPv2v3, eSize32,
13808 &EmulateInstructionARM::EmulateVSTR, "vstr<c> <Sd>, [<Rn>{,#+/-<imm>}]"},
13809 {0xffb00000, 0xf9000000, ARMvAll, eEncodingT1, AdvancedSIMD, eSize32,
13810 &EmulateInstructionARM::EmulateVST1Multiple,
13811 "vst1<c>.<size> <list>, [<Rn>{@<align>}], <Rm>"},
13812 {0xffb00300, 0xf9800000, ARMvAll, eEncodingT1, AdvancedSIMD, eSize32,
13813 &EmulateInstructionARM::EmulateVST1Single,
13814 "vst1<c>.<size> <list>, [<Rn>{@<align>}], <Rm>"},
13816 //----------------------------------------------------------------------
13817 // Other instructions
13818 //----------------------------------------------------------------------
13819 {0xffffffc0, 0x0000b240, ARMV6_ABOVE, eEncodingT1, No_VFP, eSize16,
13820 &EmulateInstructionARM::EmulateSXTB, "sxtb<c> <Rd>,<Rm>"},
13821 {0xfffff080, 0xfa4ff080, ARMV6_ABOVE, eEncodingT2, No_VFP, eSize32,
13822 &EmulateInstructionARM::EmulateSXTB, "sxtb<c>.w <Rd>,<Rm>{,<rotation>}"},
13823 {0xffffffc0, 0x0000b200, ARMV6_ABOVE, eEncodingT1, No_VFP, eSize16,
13824 &EmulateInstructionARM::EmulateSXTH, "sxth<c> <Rd>,<Rm>"},
13825 {0xfffff080, 0xfa0ff080, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
13826 &EmulateInstructionARM::EmulateSXTH, "sxth<c>.w <Rd>,<Rm>{,<rotation>}"},
13827 {0xffffffc0, 0x0000b2c0, ARMV6_ABOVE, eEncodingT1, No_VFP, eSize16,
13828 &EmulateInstructionARM::EmulateUXTB, "uxtb<c> <Rd>,<Rm>"},
13829 {0xfffff080, 0xfa5ff080, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
13830 &EmulateInstructionARM::EmulateUXTB, "uxtb<c>.w <Rd>,<Rm>{,<rotation>}"},
13831 {0xffffffc0, 0x0000b280, ARMV6_ABOVE, eEncodingT1, No_VFP, eSize16,
13832 &EmulateInstructionARM::EmulateUXTH, "uxth<c> <Rd>,<Rm>"},
13833 {0xfffff080, 0xfa1ff080, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
13834 &EmulateInstructionARM::EmulateUXTH, "uxth<c>.w <Rd>,<Rm>{,<rotation>}"},
13837 const size_t k_num_thumb_opcodes = llvm::array_lengthof(g_thumb_opcodes);
13838 for (size_t i = 0; i < k_num_thumb_opcodes; ++i) {
13839 if ((g_thumb_opcodes[i].mask & opcode) == g_thumb_opcodes[i].value &&
13840 (g_thumb_opcodes[i].variants & arm_isa) != 0)
13841 return &g_thumb_opcodes[i];
13846 bool EmulateInstructionARM::SetArchitecture(const ArchSpec &arch) {
13849 const char *arch_cstr = arch.GetArchitectureName();
13851 if (0 == ::strcasecmp(arch_cstr, "armv4t"))
13852 m_arm_isa = ARMv4T;
13853 else if (0 == ::strcasecmp(arch_cstr, "armv5tej"))
13854 m_arm_isa = ARMv5TEJ;
13855 else if (0 == ::strcasecmp(arch_cstr, "armv5te"))
13856 m_arm_isa = ARMv5TE;
13857 else if (0 == ::strcasecmp(arch_cstr, "armv5t"))
13858 m_arm_isa = ARMv5T;
13859 else if (0 == ::strcasecmp(arch_cstr, "armv6k"))
13860 m_arm_isa = ARMv6K;
13861 else if (0 == ::strcasecmp(arch_cstr, "armv6t2"))
13862 m_arm_isa = ARMv6T2;
13863 else if (0 == ::strcasecmp(arch_cstr, "armv7s"))
13864 m_arm_isa = ARMv7S;
13865 else if (0 == ::strcasecmp(arch_cstr, "arm"))
13866 m_arm_isa = ARMvAll;
13867 else if (0 == ::strcasecmp(arch_cstr, "thumb"))
13868 m_arm_isa = ARMvAll;
13869 else if (0 == ::strncasecmp(arch_cstr, "armv4", 5))
13871 else if (0 == ::strncasecmp(arch_cstr, "armv6", 5))
13873 else if (0 == ::strncasecmp(arch_cstr, "armv7", 5))
13875 else if (0 == ::strncasecmp(arch_cstr, "armv8", 5))
13878 return m_arm_isa != 0;
13881 bool EmulateInstructionARM::SetInstruction(const Opcode &insn_opcode,
13882 const Address &inst_addr,
13884 if (EmulateInstruction::SetInstruction(insn_opcode, inst_addr, target)) {
13885 if (m_arch.GetTriple().getArch() == llvm::Triple::thumb ||
13886 m_arch.IsAlwaysThumbInstructions())
13887 m_opcode_mode = eModeThumb;
13889 AddressClass addr_class = inst_addr.GetAddressClass();
13891 if ((addr_class == AddressClass::eCode) ||
13892 (addr_class == AddressClass::eUnknown))
13893 m_opcode_mode = eModeARM;
13894 else if (addr_class == AddressClass::eCodeAlternateISA)
13895 m_opcode_mode = eModeThumb;
13899 if (m_opcode_mode == eModeThumb || m_arch.IsAlwaysThumbInstructions())
13900 m_opcode_cpsr = CPSR_MODE_USR | MASK_CPSR_T;
13902 m_opcode_cpsr = CPSR_MODE_USR;
13908 bool EmulateInstructionARM::ReadInstruction() {
13909 bool success = false;
13910 m_opcode_cpsr = ReadRegisterUnsigned(eRegisterKindGeneric,
13911 LLDB_REGNUM_GENERIC_FLAGS, 0, &success);
13914 ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC,
13915 LLDB_INVALID_ADDRESS, &success);
13917 Context read_inst_context;
13918 read_inst_context.type = eContextReadOpcode;
13919 read_inst_context.SetNoArgs();
13921 if ((m_opcode_cpsr & MASK_CPSR_T) || m_arch.IsAlwaysThumbInstructions()) {
13922 m_opcode_mode = eModeThumb;
13923 uint32_t thumb_opcode = MemARead(read_inst_context, pc, 2, 0, &success);
13926 if ((thumb_opcode & 0xe000) != 0xe000 ||
13927 ((thumb_opcode & 0x1800u) == 0)) {
13928 m_opcode.SetOpcode16(thumb_opcode, GetByteOrder());
13930 m_opcode.SetOpcode32(
13931 (thumb_opcode << 16) |
13932 MemARead(read_inst_context, pc + 2, 2, 0, &success),
13937 m_opcode_mode = eModeARM;
13938 m_opcode.SetOpcode32(MemARead(read_inst_context, pc, 4, 0, &success),
13942 if (!m_ignore_conditions) {
13943 // If we are not ignoreing the conditions then init the it session from
13944 // the current value of cpsr.
13945 uint32_t it = (Bits32(m_opcode_cpsr, 15, 10) << 2) |
13946 Bits32(m_opcode_cpsr, 26, 25);
13948 m_it_session.InitIT(it);
13953 m_opcode_mode = eModeInvalid;
13954 m_addr = LLDB_INVALID_ADDRESS;
13959 uint32_t EmulateInstructionARM::ArchVersion() { return m_arm_isa; }
13961 bool EmulateInstructionARM::ConditionPassed(const uint32_t opcode) {
13962 // If we are ignoring conditions, then always return true. this allows us to
13963 // iterate over disassembly code and still emulate an instruction even if we
13964 // don't have all the right bits set in the CPSR register...
13965 if (m_ignore_conditions)
13968 const uint32_t cond = CurrentCond(opcode);
13969 if (cond == UINT32_MAX)
13972 bool result = false;
13973 switch (UnsignedBits(cond, 3, 1)) {
13975 if (m_opcode_cpsr == 0)
13978 result = (m_opcode_cpsr & MASK_CPSR_Z) != 0;
13981 if (m_opcode_cpsr == 0)
13984 result = (m_opcode_cpsr & MASK_CPSR_C) != 0;
13987 if (m_opcode_cpsr == 0)
13990 result = (m_opcode_cpsr & MASK_CPSR_N) != 0;
13993 if (m_opcode_cpsr == 0)
13996 result = (m_opcode_cpsr & MASK_CPSR_V) != 0;
13999 if (m_opcode_cpsr == 0)
14002 result = ((m_opcode_cpsr & MASK_CPSR_C) != 0) &&
14003 ((m_opcode_cpsr & MASK_CPSR_Z) == 0);
14006 if (m_opcode_cpsr == 0)
14009 bool n = (m_opcode_cpsr & MASK_CPSR_N);
14010 bool v = (m_opcode_cpsr & MASK_CPSR_V);
14015 if (m_opcode_cpsr == 0)
14018 bool n = (m_opcode_cpsr & MASK_CPSR_N);
14019 bool v = (m_opcode_cpsr & MASK_CPSR_V);
14020 result = n == v && ((m_opcode_cpsr & MASK_CPSR_Z) == 0);
14024 // Always execute (cond == 0b1110, or the special 0b1111 which gives
14025 // opcodes different meanings, but always means execution happens.
14034 uint32_t EmulateInstructionARM::CurrentCond(const uint32_t opcode) {
14035 switch (m_opcode_mode) {
14040 return UnsignedBits(opcode, 31, 28);
14043 // For T1 and T3 encodings of the Branch instruction, it returns the 4-bit
14044 // 'cond' field of the encoding.
14046 const uint32_t byte_size = m_opcode.GetByteSize();
14047 if (byte_size == 2) {
14048 if (Bits32(opcode, 15, 12) == 0x0d && Bits32(opcode, 11, 8) != 0x0f)
14049 return Bits32(opcode, 11, 8);
14050 } else if (byte_size == 4) {
14051 if (Bits32(opcode, 31, 27) == 0x1e && Bits32(opcode, 15, 14) == 0x02 &&
14052 Bits32(opcode, 12, 12) == 0x00 && Bits32(opcode, 25, 22) <= 0x0d) {
14053 return Bits32(opcode, 25, 22);
14056 // We have an invalid thumb instruction, let's bail out.
14059 return m_it_session.GetCond();
14062 return UINT32_MAX; // Return invalid value
14065 bool EmulateInstructionARM::InITBlock() {
14066 return CurrentInstrSet() == eModeThumb && m_it_session.InITBlock();
14069 bool EmulateInstructionARM::LastInITBlock() {
14070 return CurrentInstrSet() == eModeThumb && m_it_session.LastInITBlock();
14073 bool EmulateInstructionARM::BadMode(uint32_t mode) {
14077 return false; // '10000'
14079 return false; // '10001'
14081 return false; // '10010'
14083 return false; // '10011'
14085 return false; // '10110'
14087 return false; // '10111'
14089 return false; // '11011'
14091 return false; // '11111'
14098 bool EmulateInstructionARM::CurrentModeIsPrivileged() {
14099 uint32_t mode = Bits32(m_opcode_cpsr, 4, 0);
14110 void EmulateInstructionARM::CPSRWriteByInstr(uint32_t value, uint32_t bytemask,
14111 bool affect_execstate) {
14112 bool privileged = CurrentModeIsPrivileged();
14114 uint32_t tmp_cpsr = Bits32(m_opcode_cpsr, 23, 20) << 20;
14116 if (BitIsSet(bytemask, 3)) {
14117 tmp_cpsr = tmp_cpsr | (Bits32(value, 31, 27) << 27);
14118 if (affect_execstate)
14119 tmp_cpsr = tmp_cpsr | (Bits32(value, 26, 24) << 24);
14122 if (BitIsSet(bytemask, 2)) {
14123 tmp_cpsr = tmp_cpsr | (Bits32(value, 19, 16) << 16);
14126 if (BitIsSet(bytemask, 1)) {
14127 if (affect_execstate)
14128 tmp_cpsr = tmp_cpsr | (Bits32(value, 15, 10) << 10);
14129 tmp_cpsr = tmp_cpsr | (Bit32(value, 9) << 9);
14131 tmp_cpsr = tmp_cpsr | (Bit32(value, 8) << 8);
14134 if (BitIsSet(bytemask, 0)) {
14136 tmp_cpsr = tmp_cpsr | (Bits32(value, 7, 6) << 6);
14137 if (affect_execstate)
14138 tmp_cpsr = tmp_cpsr | (Bit32(value, 5) << 5);
14140 tmp_cpsr = tmp_cpsr | Bits32(value, 4, 0);
14143 m_opcode_cpsr = tmp_cpsr;
14146 bool EmulateInstructionARM::BranchWritePC(const Context &context,
14150 // Check the current instruction set.
14151 if (CurrentInstrSet() == eModeARM)
14152 target = addr & 0xfffffffc;
14154 target = addr & 0xfffffffe;
14156 if (!WriteRegisterUnsigned(context, eRegisterKindGeneric,
14157 LLDB_REGNUM_GENERIC_PC, target))
14163 // As a side effect, BXWritePC sets context.arg2 to eModeARM or eModeThumb by
14164 // inspecting addr.
14165 bool EmulateInstructionARM::BXWritePC(Context &context, uint32_t addr) {
14167 // If the CPSR is changed due to switching between ARM and Thumb ISETSTATE,
14168 // we want to record it and issue a WriteRegister callback so the clients can
14169 // track the mode changes accordingly.
14170 bool cpsr_changed = false;
14172 if (BitIsSet(addr, 0)) {
14173 if (CurrentInstrSet() != eModeThumb) {
14174 SelectInstrSet(eModeThumb);
14175 cpsr_changed = true;
14177 target = addr & 0xfffffffe;
14178 context.SetISA(eModeThumb);
14179 } else if (BitIsClear(addr, 1)) {
14180 if (CurrentInstrSet() != eModeARM) {
14181 SelectInstrSet(eModeARM);
14182 cpsr_changed = true;
14184 target = addr & 0xfffffffc;
14185 context.SetISA(eModeARM);
14187 return false; // address<1:0> == '10' => UNPREDICTABLE
14189 if (cpsr_changed) {
14190 if (!WriteRegisterUnsigned(context, eRegisterKindGeneric,
14191 LLDB_REGNUM_GENERIC_FLAGS, m_new_inst_cpsr))
14194 if (!WriteRegisterUnsigned(context, eRegisterKindGeneric,
14195 LLDB_REGNUM_GENERIC_PC, target))
14201 // Dispatches to either BXWritePC or BranchWritePC based on architecture
14203 bool EmulateInstructionARM::LoadWritePC(Context &context, uint32_t addr) {
14204 if (ArchVersion() >= ARMv5T)
14205 return BXWritePC(context, addr);
14207 return BranchWritePC((const Context)context, addr);
14210 // Dispatches to either BXWritePC or BranchWritePC based on architecture
14211 // versions and current instruction set.
14212 bool EmulateInstructionARM::ALUWritePC(Context &context, uint32_t addr) {
14213 if (ArchVersion() >= ARMv7 && CurrentInstrSet() == eModeARM)
14214 return BXWritePC(context, addr);
14216 return BranchWritePC((const Context)context, addr);
14219 EmulateInstructionARM::Mode EmulateInstructionARM::CurrentInstrSet() {
14220 return m_opcode_mode;
14223 // Set the 'T' bit of our CPSR. The m_opcode_mode gets updated when the next
14224 // ReadInstruction() is performed. This function has a side effect of updating
14225 // the m_new_inst_cpsr member variable if necessary.
14226 bool EmulateInstructionARM::SelectInstrSet(Mode arm_or_thumb) {
14227 m_new_inst_cpsr = m_opcode_cpsr;
14228 switch (arm_or_thumb) {
14232 // Clear the T bit.
14233 m_new_inst_cpsr &= ~MASK_CPSR_T;
14237 m_new_inst_cpsr |= MASK_CPSR_T;
14243 // This function returns TRUE if the processor currently provides support for
14244 // unaligned memory accesses, or FALSE otherwise. This is always TRUE in ARMv7,
14245 // controllable by the SCTLR.U bit in ARMv6, and always FALSE before ARMv6.
14246 bool EmulateInstructionARM::UnalignedSupport() {
14247 return (ArchVersion() >= ARMv7);
14250 // The main addition and subtraction instructions can produce status
14251 // information about both unsigned carry and signed overflow conditions. This
14252 // status information can be used to synthesize multi-word additions and
14254 EmulateInstructionARM::AddWithCarryResult
14255 EmulateInstructionARM::AddWithCarry(uint32_t x, uint32_t y, uint8_t carry_in) {
14260 uint64_t unsigned_sum = x + y + carry_in;
14261 int64_t signed_sum = (int32_t)x + (int32_t)y + (int32_t)carry_in;
14263 result = UnsignedBits(unsigned_sum, 31, 0);
14264 // carry_out = (result == unsigned_sum ? 0 : 1);
14265 overflow = ((int32_t)result == signed_sum ? 0 : 1);
14268 carry_out = ((int32_t)x >= (int32_t)(~y)) ? 1 : 0;
14270 carry_out = ((int32_t)x > (int32_t)y) ? 1 : 0;
14272 AddWithCarryResult res = {result, carry_out, overflow};
14276 uint32_t EmulateInstructionARM::ReadCoreReg(uint32_t num, bool *success) {
14277 lldb::RegisterKind reg_kind;
14281 reg_kind = eRegisterKindGeneric;
14282 reg_num = LLDB_REGNUM_GENERIC_SP;
14285 reg_kind = eRegisterKindGeneric;
14286 reg_num = LLDB_REGNUM_GENERIC_RA;
14289 reg_kind = eRegisterKindGeneric;
14290 reg_num = LLDB_REGNUM_GENERIC_PC;
14293 if (num < SP_REG) {
14294 reg_kind = eRegisterKindDWARF;
14295 reg_num = dwarf_r0 + num;
14297 // assert(0 && "Invalid register number");
14304 // Read our register.
14305 uint32_t val = ReadRegisterUnsigned(reg_kind, reg_num, 0, success);
14307 // When executing an ARM instruction , PC reads as the address of the current
14308 // instruction plus 8. When executing a Thumb instruction , PC reads as the
14309 // address of the current instruction plus 4.
14311 if (CurrentInstrSet() == eModeARM)
14320 // Write the result to the ARM core register Rd, and optionally update the
14321 // condition flags based on the result.
14323 // This helper method tries to encapsulate the following pseudocode from the
14324 // ARM Architecture Reference Manual:
14326 // if d == 15 then // Can only occur for encoding A1
14327 // ALUWritePC(result); // setflags is always FALSE here
14330 // if setflags then
14331 // APSR.N = result<31>;
14332 // APSR.Z = IsZeroBit(result);
14334 // // APSR.V unchanged
14336 // In the above case, the API client does not pass in the overflow arg, which
14337 // defaults to ~0u.
14338 bool EmulateInstructionARM::WriteCoreRegOptionalFlags(
14339 Context &context, const uint32_t result, const uint32_t Rd, bool setflags,
14340 const uint32_t carry, const uint32_t overflow) {
14342 if (!ALUWritePC(context, result))
14345 lldb::RegisterKind reg_kind;
14349 reg_kind = eRegisterKindGeneric;
14350 reg_num = LLDB_REGNUM_GENERIC_SP;
14353 reg_kind = eRegisterKindGeneric;
14354 reg_num = LLDB_REGNUM_GENERIC_RA;
14357 reg_kind = eRegisterKindDWARF;
14358 reg_num = dwarf_r0 + Rd;
14360 if (!WriteRegisterUnsigned(context, reg_kind, reg_num, result))
14363 return WriteFlags(context, result, carry, overflow);
14368 // This helper method tries to encapsulate the following pseudocode from the
14369 // ARM Architecture Reference Manual:
14371 // APSR.N = result<31>;
14372 // APSR.Z = IsZeroBit(result);
14374 // APSR.V = overflow
14376 // Default arguments can be specified for carry and overflow parameters, which
14377 // means not to update the respective flags.
14378 bool EmulateInstructionARM::WriteFlags(Context &context, const uint32_t result,
14379 const uint32_t carry,
14380 const uint32_t overflow) {
14381 m_new_inst_cpsr = m_opcode_cpsr;
14382 SetBit32(m_new_inst_cpsr, CPSR_N_POS, Bit32(result, CPSR_N_POS));
14383 SetBit32(m_new_inst_cpsr, CPSR_Z_POS, result == 0 ? 1 : 0);
14385 SetBit32(m_new_inst_cpsr, CPSR_C_POS, carry);
14386 if (overflow != ~0u)
14387 SetBit32(m_new_inst_cpsr, CPSR_V_POS, overflow);
14388 if (m_new_inst_cpsr != m_opcode_cpsr) {
14389 if (!WriteRegisterUnsigned(context, eRegisterKindGeneric,
14390 LLDB_REGNUM_GENERIC_FLAGS, m_new_inst_cpsr))
14396 bool EmulateInstructionARM::EvaluateInstruction(uint32_t evaluate_options) {
14397 ARMOpcode *opcode_data = NULL;
14399 if (m_opcode_mode == eModeThumb)
14401 GetThumbOpcodeForInstruction(m_opcode.GetOpcode32(), m_arm_isa);
14402 else if (m_opcode_mode == eModeARM)
14403 opcode_data = GetARMOpcodeForInstruction(m_opcode.GetOpcode32(), m_arm_isa);
14405 const bool auto_advance_pc =
14406 evaluate_options & eEmulateInstructionOptionAutoAdvancePC;
14407 m_ignore_conditions =
14408 evaluate_options & eEmulateInstructionOptionIgnoreConditions;
14410 bool success = false;
14411 if (m_opcode_cpsr == 0 || m_ignore_conditions == false) {
14413 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_cpsr, 0, &success);
14416 // Only return false if we are unable to read the CPSR if we care about
14418 if (success == false && m_ignore_conditions == false)
14421 uint32_t orig_pc_value = 0;
14422 if (auto_advance_pc) {
14424 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc, 0, &success);
14429 // Call the Emulate... function if we managed to decode the opcode.
14431 success = (this->*opcode_data->callback)(m_opcode.GetOpcode32(),
14432 opcode_data->encoding);
14437 // Advance the ITSTATE bits to their values for the next instruction if we
14438 // haven't just executed an IT instruction what initialized it.
14439 if (m_opcode_mode == eModeThumb && m_it_session.InITBlock() &&
14440 (opcode_data == nullptr ||
14441 opcode_data->callback != &EmulateInstructionARM::EmulateIT))
14442 m_it_session.ITAdvance();
14444 if (auto_advance_pc) {
14445 uint32_t after_pc_value =
14446 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc, 0, &success);
14450 if (auto_advance_pc && (after_pc_value == orig_pc_value)) {
14451 after_pc_value += m_opcode.GetByteSize();
14453 EmulateInstruction::Context context;
14454 context.type = eContextAdvancePC;
14455 context.SetNoArgs();
14456 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc,
14464 EmulateInstruction::InstructionCondition
14465 EmulateInstructionARM::GetInstructionCondition() {
14466 const uint32_t cond = CurrentCond(m_opcode.GetOpcode32());
14467 if (cond == 0xe || cond == 0xf || cond == UINT32_MAX)
14468 return EmulateInstruction::UnconditionalCondition;
14472 bool EmulateInstructionARM::TestEmulation(Stream *out_stream, ArchSpec &arch,
14473 OptionValueDictionary *test_data) {
14475 out_stream->Printf("TestEmulation: Missing test data.\n");
14479 static ConstString opcode_key("opcode");
14480 static ConstString before_key("before_state");
14481 static ConstString after_key("after_state");
14483 OptionValueSP value_sp = test_data->GetValueForKey(opcode_key);
14485 uint32_t test_opcode;
14486 if ((value_sp.get() == NULL) ||
14487 (value_sp->GetType() != OptionValue::eTypeUInt64)) {
14488 out_stream->Printf("TestEmulation: Error reading opcode from test file.\n");
14491 test_opcode = value_sp->GetUInt64Value();
14493 if (arch.GetTriple().getArch() == llvm::Triple::thumb ||
14494 arch.IsAlwaysThumbInstructions()) {
14495 m_opcode_mode = eModeThumb;
14496 if (test_opcode < 0x10000)
14497 m_opcode.SetOpcode16(test_opcode, endian::InlHostByteOrder());
14499 m_opcode.SetOpcode32(test_opcode, endian::InlHostByteOrder());
14500 } else if (arch.GetTriple().getArch() == llvm::Triple::arm) {
14501 m_opcode_mode = eModeARM;
14502 m_opcode.SetOpcode32(test_opcode, endian::InlHostByteOrder());
14504 out_stream->Printf("TestEmulation: Invalid arch.\n");
14508 EmulationStateARM before_state;
14509 EmulationStateARM after_state;
14511 value_sp = test_data->GetValueForKey(before_key);
14512 if ((value_sp.get() == NULL) ||
14513 (value_sp->GetType() != OptionValue::eTypeDictionary)) {
14514 out_stream->Printf("TestEmulation: Failed to find 'before' state.\n");
14518 OptionValueDictionary *state_dictionary = value_sp->GetAsDictionary();
14519 if (!before_state.LoadStateFromDictionary(state_dictionary)) {
14520 out_stream->Printf("TestEmulation: Failed loading 'before' state.\n");
14524 value_sp = test_data->GetValueForKey(after_key);
14525 if ((value_sp.get() == NULL) ||
14526 (value_sp->GetType() != OptionValue::eTypeDictionary)) {
14527 out_stream->Printf("TestEmulation: Failed to find 'after' state.\n");
14531 state_dictionary = value_sp->GetAsDictionary();
14532 if (!after_state.LoadStateFromDictionary(state_dictionary)) {
14533 out_stream->Printf("TestEmulation: Failed loading 'after' state.\n");
14537 SetBaton((void *)&before_state);
14538 SetCallbacks(&EmulationStateARM::ReadPseudoMemory,
14539 &EmulationStateARM::WritePseudoMemory,
14540 &EmulationStateARM::ReadPseudoRegister,
14541 &EmulationStateARM::WritePseudoRegister);
14543 bool success = EvaluateInstruction(eEmulateInstructionOptionAutoAdvancePC);
14545 out_stream->Printf("TestEmulation: EvaluateInstruction() failed.\n");
14549 success = before_state.CompareState(after_state);
14551 out_stream->Printf(
14552 "TestEmulation: 'before' and 'after' states do not match.\n");
14559 // EmulateInstructionARM::GetRegisterName (uint32_t reg_kind, uint32_t reg_num)
14561 // if (reg_kind == eRegisterKindGeneric)
14563 // switch (reg_num)
14565 // case LLDB_REGNUM_GENERIC_PC: return "pc";
14566 // case LLDB_REGNUM_GENERIC_SP: return "sp";
14567 // case LLDB_REGNUM_GENERIC_FP: return "fp";
14568 // case LLDB_REGNUM_GENERIC_RA: return "lr";
14569 // case LLDB_REGNUM_GENERIC_FLAGS: return "cpsr";
14570 // default: return NULL;
14573 // else if (reg_kind == eRegisterKindDWARF)
14575 // return GetARMDWARFRegisterName (reg_num);
14580 bool EmulateInstructionARM::CreateFunctionEntryUnwind(UnwindPlan &unwind_plan) {
14581 unwind_plan.Clear();
14582 unwind_plan.SetRegisterKind(eRegisterKindDWARF);
14584 UnwindPlan::RowSP row(new UnwindPlan::Row);
14586 // Our previous Call Frame Address is the stack pointer
14587 row->GetCFAValue().SetIsRegisterPlusOffset(dwarf_sp, 0);
14589 unwind_plan.AppendRow(row);
14590 unwind_plan.SetSourceName("EmulateInstructionARM");
14591 unwind_plan.SetSourcedFromCompiler(eLazyBoolNo);
14592 unwind_plan.SetUnwindPlanValidAtAllInstructions(eLazyBoolYes);
14593 unwind_plan.SetReturnAddressRegister(dwarf_lr);