1 //===-- EmulateInstructionARM.cpp -------------------------------*- C++ -*-===//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
11 #include "EmulateInstructionARM.h"
12 #include "EmulationStateARM.h"
13 #include "lldb/Core/Address.h"
14 #include "lldb/Core/PluginManager.h"
15 #include "lldb/Host/PosixApi.h"
16 #include "lldb/Interpreter/OptionValueArray.h"
17 #include "lldb/Interpreter/OptionValueDictionary.h"
18 #include "lldb/Symbol/UnwindPlan.h"
19 #include "lldb/Utility/ArchSpec.h"
20 #include "lldb/Utility/ConstString.h"
21 #include "lldb/Utility/Stream.h"
23 #include "Plugins/Process/Utility/ARMDefines.h"
24 #include "Plugins/Process/Utility/ARMUtils.h"
25 #include "Utility/ARM_DWARF_Registers.h"
27 #include "llvm/ADT/STLExtras.h"
28 #include "llvm/Support/MathExtras.h"
31 using namespace lldb_private;
33 // Convenient macro definitions.
34 #define APSR_C Bit32(m_opcode_cpsr, CPSR_C_POS)
35 #define APSR_V Bit32(m_opcode_cpsr, CPSR_V_POS)
37 #define AlignPC(pc_val) (pc_val & 0xFFFFFFFC)
40 // ITSession implementation
43 static bool GetARMDWARFRegisterInfo(unsigned reg_num, RegisterInfo ®_info) {
44 ::memset(®_info, 0, sizeof(RegisterInfo));
45 ::memset(reg_info.kinds, LLDB_INVALID_REGNUM, sizeof(reg_info.kinds));
47 if (reg_num >= dwarf_q0 && reg_num <= dwarf_q15) {
48 reg_info.byte_size = 16;
49 reg_info.format = eFormatVectorOfUInt8;
50 reg_info.encoding = eEncodingVector;
53 if (reg_num >= dwarf_d0 && reg_num <= dwarf_d31) {
54 reg_info.byte_size = 8;
55 reg_info.format = eFormatFloat;
56 reg_info.encoding = eEncodingIEEE754;
57 } else if (reg_num >= dwarf_s0 && reg_num <= dwarf_s31) {
58 reg_info.byte_size = 4;
59 reg_info.format = eFormatFloat;
60 reg_info.encoding = eEncodingIEEE754;
61 } else if (reg_num >= dwarf_f0 && reg_num <= dwarf_f7) {
62 reg_info.byte_size = 12;
63 reg_info.format = eFormatFloat;
64 reg_info.encoding = eEncodingIEEE754;
66 reg_info.byte_size = 4;
67 reg_info.format = eFormatHex;
68 reg_info.encoding = eEncodingUint;
71 reg_info.kinds[eRegisterKindDWARF] = reg_num;
97 reg_info.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_FP;
100 reg_info.name = "r8";
103 reg_info.name = "r9";
106 reg_info.name = "r10";
109 reg_info.name = "r11";
112 reg_info.name = "r12";
115 reg_info.name = "sp";
116 reg_info.alt_name = "r13";
117 reg_info.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_SP;
120 reg_info.name = "lr";
121 reg_info.alt_name = "r14";
122 reg_info.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_RA;
125 reg_info.name = "pc";
126 reg_info.alt_name = "r15";
127 reg_info.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_PC;
130 reg_info.name = "cpsr";
131 reg_info.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_FLAGS;
135 reg_info.name = "s0";
138 reg_info.name = "s1";
141 reg_info.name = "s2";
144 reg_info.name = "s3";
147 reg_info.name = "s4";
150 reg_info.name = "s5";
153 reg_info.name = "s6";
156 reg_info.name = "s7";
159 reg_info.name = "s8";
162 reg_info.name = "s9";
165 reg_info.name = "s10";
168 reg_info.name = "s11";
171 reg_info.name = "s12";
174 reg_info.name = "s13";
177 reg_info.name = "s14";
180 reg_info.name = "s15";
183 reg_info.name = "s16";
186 reg_info.name = "s17";
189 reg_info.name = "s18";
192 reg_info.name = "s19";
195 reg_info.name = "s20";
198 reg_info.name = "s21";
201 reg_info.name = "s22";
204 reg_info.name = "s23";
207 reg_info.name = "s24";
210 reg_info.name = "s25";
213 reg_info.name = "s26";
216 reg_info.name = "s27";
219 reg_info.name = "s28";
222 reg_info.name = "s29";
225 reg_info.name = "s30";
228 reg_info.name = "s31";
233 reg_info.name = "f0";
236 reg_info.name = "f1";
239 reg_info.name = "f2";
242 reg_info.name = "f3";
245 reg_info.name = "f4";
248 reg_info.name = "f5";
251 reg_info.name = "f6";
254 reg_info.name = "f7";
257 // Intel wireless MMX general purpose registers 0 - 7 XScale accumulator
258 // register 0 - 7 (they do overlap with wCGR0 - wCGR7)
260 reg_info.name = "wCGR0/ACC0";
263 reg_info.name = "wCGR1/ACC1";
266 reg_info.name = "wCGR2/ACC2";
269 reg_info.name = "wCGR3/ACC3";
272 reg_info.name = "wCGR4/ACC4";
275 reg_info.name = "wCGR5/ACC5";
278 reg_info.name = "wCGR6/ACC6";
281 reg_info.name = "wCGR7/ACC7";
284 // Intel wireless MMX data registers 0 - 15
286 reg_info.name = "wR0";
289 reg_info.name = "wR1";
292 reg_info.name = "wR2";
295 reg_info.name = "wR3";
298 reg_info.name = "wR4";
301 reg_info.name = "wR5";
304 reg_info.name = "wR6";
307 reg_info.name = "wR7";
310 reg_info.name = "wR8";
313 reg_info.name = "wR9";
316 reg_info.name = "wR10";
319 reg_info.name = "wR11";
322 reg_info.name = "wR12";
325 reg_info.name = "wR13";
328 reg_info.name = "wR14";
331 reg_info.name = "wR15";
335 reg_info.name = "spsr";
338 reg_info.name = "spsr_fiq";
341 reg_info.name = "spsr_irq";
344 reg_info.name = "spsr_abt";
347 reg_info.name = "spsr_und";
350 reg_info.name = "spsr_svc";
354 reg_info.name = "r8_usr";
357 reg_info.name = "r9_usr";
360 reg_info.name = "r10_usr";
363 reg_info.name = "r11_usr";
366 reg_info.name = "r12_usr";
369 reg_info.name = "r13_usr";
372 reg_info.name = "r14_usr";
375 reg_info.name = "r8_fiq";
378 reg_info.name = "r9_fiq";
381 reg_info.name = "r10_fiq";
384 reg_info.name = "r11_fiq";
387 reg_info.name = "r12_fiq";
390 reg_info.name = "r13_fiq";
393 reg_info.name = "r14_fiq";
396 reg_info.name = "r13_irq";
399 reg_info.name = "r14_irq";
402 reg_info.name = "r13_abt";
405 reg_info.name = "r14_abt";
408 reg_info.name = "r13_und";
411 reg_info.name = "r14_und";
414 reg_info.name = "r13_svc";
417 reg_info.name = "r14_svc";
420 // Intel wireless MMX control register in co-processor 0 - 7
422 reg_info.name = "wC0";
425 reg_info.name = "wC1";
428 reg_info.name = "wC2";
431 reg_info.name = "wC3";
434 reg_info.name = "wC4";
437 reg_info.name = "wC5";
440 reg_info.name = "wC6";
443 reg_info.name = "wC7";
448 reg_info.name = "d0";
451 reg_info.name = "d1";
454 reg_info.name = "d2";
457 reg_info.name = "d3";
460 reg_info.name = "d4";
463 reg_info.name = "d5";
466 reg_info.name = "d6";
469 reg_info.name = "d7";
472 reg_info.name = "d8";
475 reg_info.name = "d9";
478 reg_info.name = "d10";
481 reg_info.name = "d11";
484 reg_info.name = "d12";
487 reg_info.name = "d13";
490 reg_info.name = "d14";
493 reg_info.name = "d15";
496 reg_info.name = "d16";
499 reg_info.name = "d17";
502 reg_info.name = "d18";
505 reg_info.name = "d19";
508 reg_info.name = "d20";
511 reg_info.name = "d21";
514 reg_info.name = "d22";
517 reg_info.name = "d23";
520 reg_info.name = "d24";
523 reg_info.name = "d25";
526 reg_info.name = "d26";
529 reg_info.name = "d27";
532 reg_info.name = "d28";
535 reg_info.name = "d29";
538 reg_info.name = "d30";
541 reg_info.name = "d31";
544 // NEON 128-bit vector registers (overlays the d registers)
546 reg_info.name = "q0";
549 reg_info.name = "q1";
552 reg_info.name = "q2";
555 reg_info.name = "q3";
558 reg_info.name = "q4";
561 reg_info.name = "q5";
564 reg_info.name = "q6";
567 reg_info.name = "q7";
570 reg_info.name = "q8";
573 reg_info.name = "q9";
576 reg_info.name = "q10";
579 reg_info.name = "q11";
582 reg_info.name = "q12";
585 reg_info.name = "q13";
588 reg_info.name = "q14";
591 reg_info.name = "q15";
601 // Valid return values are {1, 2, 3, 4}, with 0 signifying an error condition.
602 static uint32_t CountITSize(uint32_t ITMask) {
603 // First count the trailing zeros of the IT mask.
604 uint32_t TZ = llvm::countTrailingZeros(ITMask);
606 #ifdef LLDB_CONFIGURATION_DEBUG
607 printf("Encoding error: IT Mask '0000'\n");
614 // Init ITState. Note that at least one bit is always 1 in mask.
615 bool ITSession::InitIT(uint32_t bits7_0) {
616 ITCounter = CountITSize(Bits32(bits7_0, 3, 0));
621 unsigned short FirstCond = Bits32(bits7_0, 7, 4);
622 if (FirstCond == 0xF) {
623 #ifdef LLDB_CONFIGURATION_DEBUG
624 printf("Encoding error: IT FirstCond '1111'\n");
628 if (FirstCond == 0xE && ITCounter != 1) {
629 #ifdef LLDB_CONFIGURATION_DEBUG
630 printf("Encoding error: IT FirstCond '1110' && Mask != '1000'\n");
639 // Update ITState if necessary.
640 void ITSession::ITAdvance() {
641 // assert(ITCounter);
646 unsigned short NewITState4_0 = Bits32(ITState, 4, 0) << 1;
647 SetBits32(ITState, 4, 0, NewITState4_0);
651 // Return true if we're inside an IT Block.
652 bool ITSession::InITBlock() { return ITCounter != 0; }
654 // Return true if we're the last instruction inside an IT Block.
655 bool ITSession::LastInITBlock() { return ITCounter == 1; }
657 // Get condition bits for the current thumb instruction.
658 uint32_t ITSession::GetCond() {
660 return Bits32(ITState, 7, 4);
665 // ARM constants used during decoding
667 #define LDM_REGLIST 1
671 #define PC_REGLIST_BIT 0x8000
673 #define ARMv4 (1u << 0)
674 #define ARMv4T (1u << 1)
675 #define ARMv5T (1u << 2)
676 #define ARMv5TE (1u << 3)
677 #define ARMv5TEJ (1u << 4)
678 #define ARMv6 (1u << 5)
679 #define ARMv6K (1u << 6)
680 #define ARMv6T2 (1u << 7)
681 #define ARMv7 (1u << 8)
682 #define ARMv7S (1u << 9)
683 #define ARMv8 (1u << 10)
684 #define ARMvAll (0xffffffffu)
686 #define ARMV4T_ABOVE \
687 (ARMv4T | ARMv5T | ARMv5TE | ARMv5TEJ | ARMv6 | ARMv6K | ARMv6T2 | ARMv7 | \
689 #define ARMV5_ABOVE \
690 (ARMv5T | ARMv5TE | ARMv5TEJ | ARMv6 | ARMv6K | ARMv6T2 | ARMv7 | ARMv7S | \
692 #define ARMV5TE_ABOVE \
693 (ARMv5TE | ARMv5TEJ | ARMv6 | ARMv6K | ARMv6T2 | ARMv7 | ARMv7S | ARMv8)
694 #define ARMV5J_ABOVE \
695 (ARMv5TEJ | ARMv6 | ARMv6K | ARMv6T2 | ARMv7 | ARMv7S | ARMv8)
696 #define ARMV6_ABOVE (ARMv6 | ARMv6K | ARMv6T2 | ARMv7 | ARMv7S | ARMv8)
697 #define ARMV6T2_ABOVE (ARMv6T2 | ARMv7 | ARMv7S | ARMv8)
698 #define ARMV7_ABOVE (ARMv7 | ARMv7S | ARMv8)
701 #define VFPv1 (1u << 1)
702 #define VFPv2 (1u << 2)
703 #define VFPv3 (1u << 3)
704 #define AdvancedSIMD (1u << 4)
706 #define VFPv1_ABOVE (VFPv1 | VFPv2 | VFPv3 | AdvancedSIMD)
707 #define VFPv2_ABOVE (VFPv2 | VFPv3 | AdvancedSIMD)
708 #define VFPv2v3 (VFPv2 | VFPv3)
711 // EmulateInstructionARM implementation
714 void EmulateInstructionARM::Initialize() {
715 PluginManager::RegisterPlugin(GetPluginNameStatic(),
716 GetPluginDescriptionStatic(), CreateInstance);
719 void EmulateInstructionARM::Terminate() {
720 PluginManager::UnregisterPlugin(CreateInstance);
723 ConstString EmulateInstructionARM::GetPluginNameStatic() {
724 static ConstString g_name("arm");
728 const char *EmulateInstructionARM::GetPluginDescriptionStatic() {
729 return "Emulate instructions for the ARM architecture.";
733 EmulateInstructionARM::CreateInstance(const ArchSpec &arch,
734 InstructionType inst_type) {
735 if (EmulateInstructionARM::SupportsEmulatingInstructionsOfTypeStatic(
737 if (arch.GetTriple().getArch() == llvm::Triple::arm) {
738 std::unique_ptr<EmulateInstructionARM> emulate_insn_up(
739 new EmulateInstructionARM(arch));
742 return emulate_insn_up.release();
743 } else if (arch.GetTriple().getArch() == llvm::Triple::thumb) {
744 std::unique_ptr<EmulateInstructionARM> emulate_insn_up(
745 new EmulateInstructionARM(arch));
748 return emulate_insn_up.release();
755 bool EmulateInstructionARM::SetTargetTriple(const ArchSpec &arch) {
756 if (arch.GetTriple().getArch() == llvm::Triple::arm)
758 else if (arch.GetTriple().getArch() == llvm::Triple::thumb)
764 // Write "bits (32) UNKNOWN" to memory address "address". Helper function for
765 // many ARM instructions.
766 bool EmulateInstructionARM::WriteBits32UnknownToMemory(addr_t address) {
767 EmulateInstruction::Context context;
768 context.type = EmulateInstruction::eContextWriteMemoryRandomBits;
771 uint32_t random_data = rand();
772 const uint32_t addr_byte_size = GetAddressByteSize();
774 return MemAWrite(context, address, random_data, addr_byte_size);
777 // Write "bits (32) UNKNOWN" to register n. Helper function for many ARM
779 bool EmulateInstructionARM::WriteBits32Unknown(int n) {
780 EmulateInstruction::Context context;
781 context.type = EmulateInstruction::eContextWriteRegisterRandomBits;
786 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
791 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n, data))
797 bool EmulateInstructionARM::GetRegisterInfo(lldb::RegisterKind reg_kind,
799 RegisterInfo ®_info) {
800 if (reg_kind == eRegisterKindGeneric) {
802 case LLDB_REGNUM_GENERIC_PC:
803 reg_kind = eRegisterKindDWARF;
806 case LLDB_REGNUM_GENERIC_SP:
807 reg_kind = eRegisterKindDWARF;
810 case LLDB_REGNUM_GENERIC_FP:
811 reg_kind = eRegisterKindDWARF;
814 case LLDB_REGNUM_GENERIC_RA:
815 reg_kind = eRegisterKindDWARF;
818 case LLDB_REGNUM_GENERIC_FLAGS:
819 reg_kind = eRegisterKindDWARF;
820 reg_num = dwarf_cpsr;
827 if (reg_kind == eRegisterKindDWARF)
828 return GetARMDWARFRegisterInfo(reg_num, reg_info);
832 uint32_t EmulateInstructionARM::GetFramePointerRegisterNumber() const {
833 if (m_arch.GetTriple().isAndroid())
834 return LLDB_INVALID_REGNUM; // Don't use frame pointer on android
835 bool is_apple = false;
836 if (m_arch.GetTriple().getVendor() == llvm::Triple::Apple)
838 switch (m_arch.GetTriple().getOS()) {
839 case llvm::Triple::Darwin:
840 case llvm::Triple::MacOSX:
841 case llvm::Triple::IOS:
842 case llvm::Triple::TvOS:
843 case llvm::Triple::WatchOS:
844 // NEED_BRIDGEOS_TRIPLE case llvm::Triple::BridgeOS:
851 /* On Apple iOS et al, the frame pointer register is always r7.
852 * Typically on other ARM systems, thumb code uses r7; arm code uses r11.
855 uint32_t fp_regnum = 11;
860 if (m_opcode_mode == eModeThumb)
866 uint32_t EmulateInstructionARM::GetFramePointerDWARFRegisterNumber() const {
867 bool is_apple = false;
868 if (m_arch.GetTriple().getVendor() == llvm::Triple::Apple)
870 switch (m_arch.GetTriple().getOS()) {
871 case llvm::Triple::Darwin:
872 case llvm::Triple::MacOSX:
873 case llvm::Triple::IOS:
880 /* On Apple iOS et al, the frame pointer register is always r7.
881 * Typically on other ARM systems, thumb code uses r7; arm code uses r11.
884 uint32_t fp_regnum = dwarf_r11;
887 fp_regnum = dwarf_r7;
889 if (m_opcode_mode == eModeThumb)
890 fp_regnum = dwarf_r7;
895 // Push Multiple Registers stores multiple registers to the stack, storing to
896 // consecutive memory locations ending just below the address in SP, and
898 // SP to point to the start of the stored data.
899 bool EmulateInstructionARM::EmulatePUSH(const uint32_t opcode,
900 const ARMEncoding encoding) {
902 // ARM pseudo code...
903 if (ConditionPassed())
905 EncodingSpecificOperations();
906 NullCheckIfThumbEE(13);
907 address = SP - 4*BitCount(registers);
911 if (registers<i> == '1')
913 if i == 13 && i != LowestSetBit(registers) // Only possible for encoding A1
914 MemA[address,4] = bits(32) UNKNOWN;
916 MemA[address,4] = R[i];
917 address = address + 4;
921 if (registers<15> == '1') // Only possible for encoding A1 or A2
922 MemA[address,4] = PCStoreValue();
924 SP = SP - 4*BitCount(registers);
928 bool success = false;
929 if (ConditionPassed(opcode)) {
930 const uint32_t addr_byte_size = GetAddressByteSize();
931 const addr_t sp = ReadCoreReg(SP_REG, &success);
934 uint32_t registers = 0;
935 uint32_t Rt; // the source register
938 registers = Bits32(opcode, 7, 0);
939 // The M bit represents LR.
940 if (Bit32(opcode, 8))
941 registers |= (1u << 14);
942 // if BitCount(registers) < 1 then UNPREDICTABLE;
943 if (BitCount(registers) < 1)
947 // Ignore bits 15 & 13.
948 registers = Bits32(opcode, 15, 0) & ~0xa000;
949 // if BitCount(registers) < 2 then UNPREDICTABLE;
950 if (BitCount(registers) < 2)
954 Rt = Bits32(opcode, 15, 12);
955 // if BadReg(t) then UNPREDICTABLE;
958 registers = (1u << Rt);
961 registers = Bits32(opcode, 15, 0);
962 // Instead of return false, let's handle the following case as well,
963 // which amounts to pushing one reg onto the full descending stacks.
964 // if BitCount(register_list) < 2 then SEE STMDB / STMFD;
967 Rt = Bits32(opcode, 15, 12);
968 // if t == 13 then UNPREDICTABLE;
971 registers = (1u << Rt);
976 addr_t sp_offset = addr_byte_size * BitCount(registers);
977 addr_t addr = sp - sp_offset;
980 EmulateInstruction::Context context;
981 context.type = EmulateInstruction::eContextPushRegisterOnStack;
982 RegisterInfo reg_info;
984 GetRegisterInfo(eRegisterKindDWARF, dwarf_sp, sp_reg);
985 for (i = 0; i < 15; ++i) {
986 if (BitIsSet(registers, i)) {
987 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + i, reg_info);
988 context.SetRegisterToRegisterPlusOffset(reg_info, sp_reg, addr - sp);
989 uint32_t reg_value = ReadCoreReg(i, &success);
992 if (!MemAWrite(context, addr, reg_value, addr_byte_size))
994 addr += addr_byte_size;
998 if (BitIsSet(registers, 15)) {
999 GetRegisterInfo(eRegisterKindDWARF, dwarf_pc, reg_info);
1000 context.SetRegisterToRegisterPlusOffset(reg_info, sp_reg, addr - sp);
1001 const uint32_t pc = ReadCoreReg(PC_REG, &success);
1004 if (!MemAWrite(context, addr, pc, addr_byte_size))
1008 context.type = EmulateInstruction::eContextAdjustStackPointer;
1009 context.SetImmediateSigned(-sp_offset);
1011 if (!WriteRegisterUnsigned(context, eRegisterKindGeneric,
1012 LLDB_REGNUM_GENERIC_SP, sp - sp_offset))
1018 // Pop Multiple Registers loads multiple registers from the stack, loading from
1019 // consecutive memory locations staring at the address in SP, and updates
1020 // SP to point just above the loaded data.
1021 bool EmulateInstructionARM::EmulatePOP(const uint32_t opcode,
1022 const ARMEncoding encoding) {
1024 // ARM pseudo code...
1025 if (ConditionPassed())
1027 EncodingSpecificOperations(); NullCheckIfThumbEE(13);
1030 if registers<i> == '1' then
1031 R[i] = if UnalignedAllowed then MemU[address,4] else MemA[address,4]; address = address + 4;
1032 if registers<15> == '1' then
1033 if UnalignedAllowed then
1034 LoadWritePC(MemU[address,4]);
1036 LoadWritePC(MemA[address,4]);
1037 if registers<13> == '0' then SP = SP + 4*BitCount(registers);
1038 if registers<13> == '1' then SP = bits(32) UNKNOWN;
1042 bool success = false;
1044 if (ConditionPassed(opcode)) {
1045 const uint32_t addr_byte_size = GetAddressByteSize();
1046 const addr_t sp = ReadCoreReg(SP_REG, &success);
1049 uint32_t registers = 0;
1050 uint32_t Rt; // the destination register
1053 registers = Bits32(opcode, 7, 0);
1054 // The P bit represents PC.
1055 if (Bit32(opcode, 8))
1056 registers |= (1u << 15);
1057 // if BitCount(registers) < 1 then UNPREDICTABLE;
1058 if (BitCount(registers) < 1)
1063 registers = Bits32(opcode, 15, 0) & ~0x2000;
1064 // if BitCount(registers) < 2 || (P == '1' && M == '1') then
1066 if (BitCount(registers) < 2 || (Bit32(opcode, 15) && Bit32(opcode, 14)))
1068 // if registers<15> == '1' && InITBlock() && !LastInITBlock() then
1070 if (BitIsSet(registers, 15) && InITBlock() && !LastInITBlock())
1074 Rt = Bits32(opcode, 15, 12);
1075 // if t == 13 || (t == 15 && InITBlock() && !LastInITBlock()) then
1079 if (Rt == 15 && InITBlock() && !LastInITBlock())
1081 registers = (1u << Rt);
1084 registers = Bits32(opcode, 15, 0);
1085 // Instead of return false, let's handle the following case as well,
1086 // which amounts to popping one reg from the full descending stacks.
1087 // if BitCount(register_list) < 2 then SEE LDM / LDMIA / LDMFD;
1089 // if registers<13> == '1' && ArchVersion() >= 7 then UNPREDICTABLE;
1090 if (BitIsSet(opcode, 13) && ArchVersion() >= ARMv7)
1094 Rt = Bits32(opcode, 15, 12);
1095 // if t == 13 then UNPREDICTABLE;
1098 registers = (1u << Rt);
1103 addr_t sp_offset = addr_byte_size * BitCount(registers);
1107 EmulateInstruction::Context context;
1108 context.type = EmulateInstruction::eContextPopRegisterOffStack;
1110 RegisterInfo sp_reg;
1111 GetRegisterInfo(eRegisterKindDWARF, dwarf_sp, sp_reg);
1113 for (i = 0; i < 15; ++i) {
1114 if (BitIsSet(registers, i)) {
1115 context.SetAddress(addr);
1116 data = MemARead(context, addr, 4, 0, &success);
1119 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + i,
1122 addr += addr_byte_size;
1126 if (BitIsSet(registers, 15)) {
1127 context.SetRegisterPlusOffset(sp_reg, addr - sp);
1128 data = MemARead(context, addr, 4, 0, &success);
1131 // In ARMv5T and above, this is an interworking branch.
1132 if (!LoadWritePC(context, data))
1134 // addr += addr_byte_size;
1137 context.type = EmulateInstruction::eContextAdjustStackPointer;
1138 context.SetImmediateSigned(sp_offset);
1140 if (!WriteRegisterUnsigned(context, eRegisterKindGeneric,
1141 LLDB_REGNUM_GENERIC_SP, sp + sp_offset))
1147 // Set r7 or ip to point to saved value residing within the stack.
1148 // ADD (SP plus immediate)
1149 bool EmulateInstructionARM::EmulateADDRdSPImm(const uint32_t opcode,
1150 const ARMEncoding encoding) {
1152 // ARM pseudo code...
1153 if (ConditionPassed())
1155 EncodingSpecificOperations();
1156 (result, carry, overflow) = AddWithCarry(SP, imm32, '0');
1158 ALUWritePC(result); // setflags is always FALSE here
1162 APSR.N = result<31>;
1163 APSR.Z = IsZeroBit(result);
1169 bool success = false;
1171 if (ConditionPassed(opcode)) {
1172 const addr_t sp = ReadCoreReg(SP_REG, &success);
1175 uint32_t Rd; // the destination register
1180 imm32 = Bits32(opcode, 7, 0) << 2; // imm32 = ZeroExtend(imm8:'00', 32)
1183 Rd = Bits32(opcode, 15, 12);
1184 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
1189 addr_t sp_offset = imm32;
1190 addr_t addr = sp + sp_offset; // a pointer to the stack area
1192 EmulateInstruction::Context context;
1193 if (Rd == GetFramePointerRegisterNumber())
1194 context.type = eContextSetFramePointer;
1196 context.type = EmulateInstruction::eContextRegisterPlusOffset;
1197 RegisterInfo sp_reg;
1198 GetRegisterInfo(eRegisterKindDWARF, dwarf_sp, sp_reg);
1199 context.SetRegisterPlusOffset(sp_reg, sp_offset);
1201 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + Rd,
1208 // Set r7 or ip to the current stack pointer.
1210 bool EmulateInstructionARM::EmulateMOVRdSP(const uint32_t opcode,
1211 const ARMEncoding encoding) {
1213 // ARM pseudo code...
1214 if (ConditionPassed())
1216 EncodingSpecificOperations();
1219 ALUWritePC(result); // setflags is always FALSE here
1223 APSR.N = result<31>;
1224 APSR.Z = IsZeroBit(result);
1230 bool success = false;
1232 if (ConditionPassed(opcode)) {
1233 const addr_t sp = ReadCoreReg(SP_REG, &success);
1236 uint32_t Rd; // the destination register
1248 EmulateInstruction::Context context;
1249 if (Rd == GetFramePointerRegisterNumber())
1250 context.type = EmulateInstruction::eContextSetFramePointer;
1252 context.type = EmulateInstruction::eContextRegisterPlusOffset;
1253 RegisterInfo sp_reg;
1254 GetRegisterInfo(eRegisterKindDWARF, dwarf_sp, sp_reg);
1255 context.SetRegisterPlusOffset(sp_reg, 0);
1257 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + Rd, sp))
1263 // Move from high register (r8-r15) to low register (r0-r7).
1265 bool EmulateInstructionARM::EmulateMOVLowHigh(const uint32_t opcode,
1266 const ARMEncoding encoding) {
1267 return EmulateMOVRdRm(opcode, encoding);
1270 // Move from register to register.
1272 bool EmulateInstructionARM::EmulateMOVRdRm(const uint32_t opcode,
1273 const ARMEncoding encoding) {
1275 // ARM pseudo code...
1276 if (ConditionPassed())
1278 EncodingSpecificOperations();
1281 ALUWritePC(result); // setflags is always FALSE here
1285 APSR.N = result<31>;
1286 APSR.Z = IsZeroBit(result);
1292 bool success = false;
1294 if (ConditionPassed(opcode)) {
1295 uint32_t Rm; // the source register
1296 uint32_t Rd; // the destination register
1300 Rd = Bit32(opcode, 7) << 3 | Bits32(opcode, 2, 0);
1301 Rm = Bits32(opcode, 6, 3);
1303 if (Rd == 15 && InITBlock() && !LastInITBlock())
1307 Rd = Bits32(opcode, 2, 0);
1308 Rm = Bits32(opcode, 5, 3);
1314 Rd = Bits32(opcode, 11, 8);
1315 Rm = Bits32(opcode, 3, 0);
1316 setflags = BitIsSet(opcode, 20);
1317 // if setflags && (BadReg(d) || BadReg(m)) then UNPREDICTABLE;
1318 if (setflags && (BadReg(Rd) || BadReg(Rm)))
1320 // if !setflags && (d == 15 || m == 15 || (d == 13 && m == 13)) then
1322 if (!setflags && (Rd == 15 || Rm == 15 || (Rd == 13 && Rm == 13)))
1326 Rd = Bits32(opcode, 15, 12);
1327 Rm = Bits32(opcode, 3, 0);
1328 setflags = BitIsSet(opcode, 20);
1330 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related
1332 if (Rd == 15 && setflags)
1333 return EmulateSUBSPcLrEtc(opcode, encoding);
1338 uint32_t result = ReadCoreReg(Rm, &success);
1342 // The context specifies that Rm is to be moved into Rd.
1343 EmulateInstruction::Context context;
1345 context.type = EmulateInstruction::eContextAdjustStackPointer;
1347 context.type = EmulateInstruction::eContextRegisterPlusOffset;
1348 RegisterInfo dwarf_reg;
1349 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + Rm, dwarf_reg);
1350 context.SetRegisterPlusOffset(dwarf_reg, 0);
1352 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags))
1358 // Move (immediate) writes an immediate value to the destination register. It
1359 // can optionally update the condition flags based on the value.
1361 bool EmulateInstructionARM::EmulateMOVRdImm(const uint32_t opcode,
1362 const ARMEncoding encoding) {
1364 // ARM pseudo code...
1365 if (ConditionPassed())
1367 EncodingSpecificOperations();
1369 if d == 15 then // Can only occur for ARM encoding
1370 ALUWritePC(result); // setflags is always FALSE here
1374 APSR.N = result<31>;
1375 APSR.Z = IsZeroBit(result);
1381 if (ConditionPassed(opcode)) {
1382 uint32_t Rd; // the destination register
1383 uint32_t imm32; // the immediate value to be written to Rd
1385 0; // the carry bit after ThumbExpandImm_C or ARMExpandImm_C.
1386 // for setflags == false, this value is a don't care initialized to
1387 // 0 to silence the static analyzer
1391 Rd = Bits32(opcode, 10, 8);
1392 setflags = !InITBlock();
1393 imm32 = Bits32(opcode, 7, 0); // imm32 = ZeroExtend(imm8, 32)
1399 Rd = Bits32(opcode, 11, 8);
1400 setflags = BitIsSet(opcode, 20);
1401 imm32 = ThumbExpandImm_C(opcode, APSR_C, carry);
1408 // d = UInt(Rd); setflags = FALSE; imm32 = ZeroExtend(imm4:i:imm3:imm8,
1410 Rd = Bits32(opcode, 11, 8);
1412 uint32_t imm4 = Bits32(opcode, 19, 16);
1413 uint32_t imm3 = Bits32(opcode, 14, 12);
1414 uint32_t i = Bit32(opcode, 26);
1415 uint32_t imm8 = Bits32(opcode, 7, 0);
1416 imm32 = (imm4 << 12) | (i << 11) | (imm3 << 8) | imm8;
1418 // if BadReg(d) then UNPREDICTABLE;
1424 // d = UInt(Rd); setflags = (S == '1'); (imm32, carry) =
1425 // ARMExpandImm_C(imm12, APSR.C);
1426 Rd = Bits32(opcode, 15, 12);
1427 setflags = BitIsSet(opcode, 20);
1428 imm32 = ARMExpandImm_C(opcode, APSR_C, carry);
1430 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related
1432 if ((Rd == 15) && setflags)
1433 return EmulateSUBSPcLrEtc(opcode, encoding);
1438 // d = UInt(Rd); setflags = FALSE; imm32 = ZeroExtend(imm4:imm12, 32);
1439 Rd = Bits32(opcode, 15, 12);
1441 uint32_t imm4 = Bits32(opcode, 19, 16);
1442 uint32_t imm12 = Bits32(opcode, 11, 0);
1443 imm32 = (imm4 << 12) | imm12;
1445 // if d == 15 then UNPREDICTABLE;
1453 uint32_t result = imm32;
1455 // The context specifies that an immediate is to be moved into Rd.
1456 EmulateInstruction::Context context;
1457 context.type = EmulateInstruction::eContextImmediate;
1458 context.SetNoArgs();
1460 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
1466 // MUL multiplies two register values. The least significant 32 bits of the
1467 // result are written to the destination
1468 // register. These 32 bits do not depend on whether the source register values
1469 // are considered to be signed values or unsigned values.
1471 // Optionally, it can update the condition flags based on the result. In the
1472 // Thumb instruction set, this option is limited to only a few forms of the
1474 bool EmulateInstructionARM::EmulateMUL(const uint32_t opcode,
1475 const ARMEncoding encoding) {
1477 if ConditionPassed() then
1478 EncodingSpecificOperations();
1479 operand1 = SInt(R[n]); // operand1 = UInt(R[n]) produces the same final results
1480 operand2 = SInt(R[m]); // operand2 = UInt(R[m]) produces the same final results
1481 result = operand1 * operand2;
1482 R[d] = result<31:0>;
1484 APSR.N = result<31>;
1485 APSR.Z = IsZeroBit(result);
1486 if ArchVersion() == 4 then
1487 APSR.C = bit UNKNOWN;
1488 // else APSR.C unchanged
1489 // APSR.V always unchanged
1492 if (ConditionPassed(opcode)) {
1498 // EncodingSpecificOperations();
1501 // d = UInt(Rdm); n = UInt(Rn); m = UInt(Rdm); setflags = !InITBlock();
1502 d = Bits32(opcode, 2, 0);
1503 n = Bits32(opcode, 5, 3);
1504 m = Bits32(opcode, 2, 0);
1505 setflags = !InITBlock();
1507 // if ArchVersion() < 6 && d == n then UNPREDICTABLE;
1508 if ((ArchVersion() < ARMv6) && (d == n))
1514 // d = UInt(Rd); n = UInt(Rn); m = UInt(Rm); setflags = FALSE;
1515 d = Bits32(opcode, 11, 8);
1516 n = Bits32(opcode, 19, 16);
1517 m = Bits32(opcode, 3, 0);
1520 // if BadReg(d) || BadReg(n) || BadReg(m) then UNPREDICTABLE;
1521 if (BadReg(d) || BadReg(n) || BadReg(m))
1527 // d = UInt(Rd); n = UInt(Rn); m = UInt(Rm); setflags = (S == '1');
1528 d = Bits32(opcode, 19, 16);
1529 n = Bits32(opcode, 3, 0);
1530 m = Bits32(opcode, 11, 8);
1531 setflags = BitIsSet(opcode, 20);
1533 // if d == 15 || n == 15 || m == 15 then UNPREDICTABLE;
1534 if ((d == 15) || (n == 15) || (m == 15))
1537 // if ArchVersion() < 6 && d == n then UNPREDICTABLE;
1538 if ((ArchVersion() < ARMv6) && (d == n))
1547 bool success = false;
1549 // operand1 = SInt(R[n]); // operand1 = UInt(R[n]) produces the same final
1552 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
1556 // operand2 = SInt(R[m]); // operand2 = UInt(R[m]) produces the same final
1559 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
1563 // result = operand1 * operand2;
1564 uint64_t result = operand1 * operand2;
1566 // R[d] = result<31:0>;
1567 RegisterInfo op1_reg;
1568 RegisterInfo op2_reg;
1569 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n, op1_reg);
1570 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + m, op2_reg);
1572 EmulateInstruction::Context context;
1573 context.type = eContextArithmetic;
1574 context.SetRegisterRegisterOperands(op1_reg, op2_reg);
1576 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + d,
1577 (0x0000ffff & result)))
1582 // APSR.N = result<31>;
1583 // APSR.Z = IsZeroBit(result);
1584 m_new_inst_cpsr = m_opcode_cpsr;
1585 SetBit32(m_new_inst_cpsr, CPSR_N_POS, Bit32(result, 31));
1586 SetBit32(m_new_inst_cpsr, CPSR_Z_POS, result == 0 ? 1 : 0);
1587 if (m_new_inst_cpsr != m_opcode_cpsr) {
1588 if (!WriteRegisterUnsigned(context, eRegisterKindGeneric,
1589 LLDB_REGNUM_GENERIC_FLAGS, m_new_inst_cpsr))
1593 // if ArchVersion() == 4 then
1594 // APSR.C = bit UNKNOWN;
1600 // Bitwise NOT (immediate) writes the bitwise inverse of an immediate value to
1601 // the destination register. It can optionally update the condition flags based
1603 bool EmulateInstructionARM::EmulateMVNImm(const uint32_t opcode,
1604 const ARMEncoding encoding) {
1606 // ARM pseudo code...
1607 if (ConditionPassed())
1609 EncodingSpecificOperations();
1610 result = NOT(imm32);
1611 if d == 15 then // Can only occur for ARM encoding
1612 ALUWritePC(result); // setflags is always FALSE here
1616 APSR.N = result<31>;
1617 APSR.Z = IsZeroBit(result);
1623 if (ConditionPassed(opcode)) {
1624 uint32_t Rd; // the destination register
1625 uint32_t imm32; // the output after ThumbExpandImm_C or ARMExpandImm_C
1626 uint32_t carry; // the carry bit after ThumbExpandImm_C or ARMExpandImm_C
1630 Rd = Bits32(opcode, 11, 8);
1631 setflags = BitIsSet(opcode, 20);
1632 imm32 = ThumbExpandImm_C(opcode, APSR_C, carry);
1635 Rd = Bits32(opcode, 15, 12);
1636 setflags = BitIsSet(opcode, 20);
1637 imm32 = ARMExpandImm_C(opcode, APSR_C, carry);
1639 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related
1641 if (Rd == 15 && setflags)
1642 return EmulateSUBSPcLrEtc(opcode, encoding);
1647 uint32_t result = ~imm32;
1649 // The context specifies that an immediate is to be moved into Rd.
1650 EmulateInstruction::Context context;
1651 context.type = EmulateInstruction::eContextImmediate;
1652 context.SetNoArgs();
1654 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
1660 // Bitwise NOT (register) writes the bitwise inverse of a register value to the
1661 // destination register. It can optionally update the condition flags based on
1663 bool EmulateInstructionARM::EmulateMVNReg(const uint32_t opcode,
1664 const ARMEncoding encoding) {
1666 // ARM pseudo code...
1667 if (ConditionPassed())
1669 EncodingSpecificOperations();
1670 (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C);
1671 result = NOT(shifted);
1672 if d == 15 then // Can only occur for ARM encoding
1673 ALUWritePC(result); // setflags is always FALSE here
1677 APSR.N = result<31>;
1678 APSR.Z = IsZeroBit(result);
1684 if (ConditionPassed(opcode)) {
1685 uint32_t Rm; // the source register
1686 uint32_t Rd; // the destination register
1687 ARM_ShifterType shift_t;
1688 uint32_t shift_n; // the shift applied to the value read from Rm
1690 uint32_t carry; // the carry bit after the shift operation
1693 Rd = Bits32(opcode, 2, 0);
1694 Rm = Bits32(opcode, 5, 3);
1695 setflags = !InITBlock();
1696 shift_t = SRType_LSL;
1702 Rd = Bits32(opcode, 11, 8);
1703 Rm = Bits32(opcode, 3, 0);
1704 setflags = BitIsSet(opcode, 20);
1705 shift_n = DecodeImmShiftThumb(opcode, shift_t);
1706 // if (BadReg(d) || BadReg(m)) then UNPREDICTABLE;
1707 if (BadReg(Rd) || BadReg(Rm))
1711 Rd = Bits32(opcode, 15, 12);
1712 Rm = Bits32(opcode, 3, 0);
1713 setflags = BitIsSet(opcode, 20);
1714 shift_n = DecodeImmShiftARM(opcode, shift_t);
1719 bool success = false;
1720 uint32_t value = ReadCoreReg(Rm, &success);
1725 Shift_C(value, shift_t, shift_n, APSR_C, carry, &success);
1728 uint32_t result = ~shifted;
1730 // The context specifies that an immediate is to be moved into Rd.
1731 EmulateInstruction::Context context;
1732 context.type = EmulateInstruction::eContextImmediate;
1733 context.SetNoArgs();
1735 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
1741 // PC relative immediate load into register, possibly followed by ADD (SP plus
1744 bool EmulateInstructionARM::EmulateLDRRtPCRelative(const uint32_t opcode,
1745 const ARMEncoding encoding) {
1747 // ARM pseudo code...
1748 if (ConditionPassed())
1750 EncodingSpecificOperations(); NullCheckIfThumbEE(15);
1752 address = if add then (base + imm32) else (base - imm32);
1753 data = MemU[address,4];
1755 if address<1:0> == '00' then LoadWritePC(data); else UNPREDICTABLE;
1756 elsif UnalignedSupport() || address<1:0> = '00' then
1758 else // Can only apply before ARMv7
1759 if CurrentInstrSet() == InstrSet_ARM then
1760 R[t] = ROR(data, 8*UInt(address<1:0>));
1762 R[t] = bits(32) UNKNOWN;
1766 if (ConditionPassed(opcode)) {
1767 bool success = false;
1768 const uint32_t pc = ReadCoreReg(PC_REG, &success);
1772 // PC relative immediate load context
1773 EmulateInstruction::Context context;
1774 context.type = EmulateInstruction::eContextRegisterPlusOffset;
1775 RegisterInfo pc_reg;
1776 GetRegisterInfo(eRegisterKindDWARF, dwarf_pc, pc_reg);
1777 context.SetRegisterPlusOffset(pc_reg, 0);
1779 uint32_t Rt; // the destination register
1780 uint32_t imm32; // immediate offset from the PC
1781 bool add; // +imm32 or -imm32?
1782 addr_t base; // the base address
1783 addr_t address; // the PC relative address
1784 uint32_t data; // the literal data value from the PC relative load
1787 Rt = Bits32(opcode, 10, 8);
1788 imm32 = Bits32(opcode, 7, 0) << 2; // imm32 = ZeroExtend(imm8:'00', 32);
1792 Rt = Bits32(opcode, 15, 12);
1793 imm32 = Bits32(opcode, 11, 0) << 2; // imm32 = ZeroExtend(imm12, 32);
1794 add = BitIsSet(opcode, 23);
1795 if (Rt == 15 && InITBlock() && !LastInITBlock())
1802 base = Align(pc, 4);
1804 address = base + imm32;
1806 address = base - imm32;
1808 context.SetRegisterPlusOffset(pc_reg, address - base);
1809 data = MemURead(context, address, 4, 0, &success);
1814 if (Bits32(address, 1, 0) == 0) {
1815 // In ARMv5T and above, this is an interworking branch.
1816 if (!LoadWritePC(context, data))
1820 } else if (UnalignedSupport() || Bits32(address, 1, 0) == 0) {
1821 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + Rt,
1824 } else // We don't handle ARM for now.
1830 // An add operation to adjust the SP.
1831 // ADD (SP plus immediate)
1832 bool EmulateInstructionARM::EmulateADDSPImm(const uint32_t opcode,
1833 const ARMEncoding encoding) {
1835 // ARM pseudo code...
1836 if (ConditionPassed())
1838 EncodingSpecificOperations();
1839 (result, carry, overflow) = AddWithCarry(SP, imm32, '0');
1840 if d == 15 then // Can only occur for ARM encoding
1841 ALUWritePC(result); // setflags is always FALSE here
1845 APSR.N = result<31>;
1846 APSR.Z = IsZeroBit(result);
1852 bool success = false;
1854 if (ConditionPassed(opcode)) {
1855 const addr_t sp = ReadCoreReg(SP_REG, &success);
1858 uint32_t imm32; // the immediate operand
1863 // d = UInt(Rd); setflags = FALSE; imm32 = ZeroExtend(imm8:'00', 32);
1864 d = Bits32(opcode, 10, 8);
1865 imm32 = (Bits32(opcode, 7, 0) << 2);
1870 // d = 13; setflags = FALSE; imm32 = ZeroExtend(imm7:'00', 32);
1872 imm32 = ThumbImm7Scaled(opcode); // imm32 = ZeroExtend(imm7:'00', 32)
1877 // d = UInt(Rd); setflags = (S == "1"); imm32 =
1878 // ThumbExpandImm(i:imm3:imm8);
1879 d = Bits32(opcode, 11, 8);
1880 imm32 = ThumbExpandImm(opcode);
1881 setflags = Bit32(opcode, 20);
1883 // if Rd == "1111" && S == "1" then SEE CMN (immediate);
1884 if (d == 15 && setflags == 1)
1885 return false; // CMN (immediate) not yet supported
1887 // if d == 15 && S == "0" then UNPREDICTABLE;
1888 if (d == 15 && setflags == 0)
1893 // if Rn == '1111' then SEE ADR;
1894 // d = UInt(Rd); setflags = FALSE; imm32 = ZeroExtend(i:imm3:imm8, 32);
1895 d = Bits32(opcode, 11, 8);
1897 uint32_t i = Bit32(opcode, 26);
1898 uint32_t imm3 = Bits32(opcode, 14, 12);
1899 uint32_t imm8 = Bits32(opcode, 7, 0);
1900 imm32 = (i << 11) | (imm3 << 8) | imm8;
1902 // if d == 15 then UNPREDICTABLE;
1910 // (result, carry, overflow) = AddWithCarry(R[n], imm32, '0');
1911 AddWithCarryResult res = AddWithCarry(sp, imm32, 0);
1913 EmulateInstruction::Context context;
1915 context.type = EmulateInstruction::eContextAdjustStackPointer;
1917 context.type = EmulateInstruction::eContextRegisterPlusOffset;
1919 RegisterInfo sp_reg;
1920 GetRegisterInfo(eRegisterKindDWARF, dwarf_sp, sp_reg);
1921 context.SetRegisterPlusOffset(sp_reg, res.result - sp);
1924 if (!ALUWritePC(context, res.result))
1929 // APSR.N = result<31>;
1930 // APSR.Z = IsZeroBit(result);
1932 // APSR.V = overflow;
1933 if (!WriteCoreRegOptionalFlags(context, res.result, d, setflags,
1934 res.carry_out, res.overflow))
1941 // An add operation to adjust the SP.
1942 // ADD (SP plus register)
1943 bool EmulateInstructionARM::EmulateADDSPRm(const uint32_t opcode,
1944 const ARMEncoding encoding) {
1946 // ARM pseudo code...
1947 if (ConditionPassed())
1949 EncodingSpecificOperations();
1950 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
1951 (result, carry, overflow) = AddWithCarry(SP, shifted, '0');
1953 ALUWritePC(result); // setflags is always FALSE here
1957 APSR.N = result<31>;
1958 APSR.Z = IsZeroBit(result);
1964 bool success = false;
1966 if (ConditionPassed(opcode)) {
1967 const addr_t sp = ReadCoreReg(SP_REG, &success);
1970 uint32_t Rm; // the second operand
1973 Rm = Bits32(opcode, 6, 3);
1978 int32_t reg_value = ReadCoreReg(Rm, &success);
1982 addr_t addr = (int32_t)sp + reg_value; // the adjusted stack pointer value
1984 EmulateInstruction::Context context;
1985 context.type = eContextArithmetic;
1986 RegisterInfo sp_reg;
1987 GetRegisterInfo(eRegisterKindDWARF, dwarf_sp, sp_reg);
1989 RegisterInfo other_reg;
1990 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + Rm, other_reg);
1991 context.SetRegisterRegisterOperands(sp_reg, other_reg);
1993 if (!WriteRegisterUnsigned(context, eRegisterKindGeneric,
1994 LLDB_REGNUM_GENERIC_SP, addr))
2000 // Branch with Link and Exchange Instruction Sets (immediate) calls a
2001 // subroutine at a PC-relative address, and changes instruction set from ARM to
2002 // Thumb, or from Thumb to ARM.
2004 bool EmulateInstructionARM::EmulateBLXImmediate(const uint32_t opcode,
2005 const ARMEncoding encoding) {
2007 // ARM pseudo code...
2008 if (ConditionPassed())
2010 EncodingSpecificOperations();
2011 if CurrentInstrSet() == InstrSet_ARM then
2014 LR = PC<31:1> : '1';
2015 if targetInstrSet == InstrSet_ARM then
2016 targetAddress = Align(PC,4) + imm32;
2018 targetAddress = PC + imm32;
2019 SelectInstrSet(targetInstrSet);
2020 BranchWritePC(targetAddress);
2024 bool success = true;
2026 if (ConditionPassed(opcode)) {
2027 EmulateInstruction::Context context;
2028 context.type = EmulateInstruction::eContextRelativeBranchImmediate;
2029 const uint32_t pc = ReadCoreReg(PC_REG, &success);
2032 addr_t lr; // next instruction address
2033 addr_t target; // target address
2034 int32_t imm32; // PC-relative offset
2037 lr = pc | 1u; // return address
2038 uint32_t S = Bit32(opcode, 26);
2039 uint32_t imm10 = Bits32(opcode, 25, 16);
2040 uint32_t J1 = Bit32(opcode, 13);
2041 uint32_t J2 = Bit32(opcode, 11);
2042 uint32_t imm11 = Bits32(opcode, 10, 0);
2043 uint32_t I1 = !(J1 ^ S);
2044 uint32_t I2 = !(J2 ^ S);
2046 (S << 24) | (I1 << 23) | (I2 << 22) | (imm10 << 12) | (imm11 << 1);
2047 imm32 = llvm::SignExtend32<25>(imm25);
2048 target = pc + imm32;
2049 SelectInstrSet(eModeThumb);
2050 context.SetISAAndImmediateSigned(eModeThumb, 4 + imm32);
2051 if (InITBlock() && !LastInITBlock())
2056 lr = pc | 1u; // return address
2057 uint32_t S = Bit32(opcode, 26);
2058 uint32_t imm10H = Bits32(opcode, 25, 16);
2059 uint32_t J1 = Bit32(opcode, 13);
2060 uint32_t J2 = Bit32(opcode, 11);
2061 uint32_t imm10L = Bits32(opcode, 10, 1);
2062 uint32_t I1 = !(J1 ^ S);
2063 uint32_t I2 = !(J2 ^ S);
2065 (S << 24) | (I1 << 23) | (I2 << 22) | (imm10H << 12) | (imm10L << 2);
2066 imm32 = llvm::SignExtend32<25>(imm25);
2067 target = Align(pc, 4) + imm32;
2068 SelectInstrSet(eModeARM);
2069 context.SetISAAndImmediateSigned(eModeARM, 4 + imm32);
2070 if (InITBlock() && !LastInITBlock())
2075 lr = pc - 4; // return address
2076 imm32 = llvm::SignExtend32<26>(Bits32(opcode, 23, 0) << 2);
2077 target = Align(pc, 4) + imm32;
2078 SelectInstrSet(eModeARM);
2079 context.SetISAAndImmediateSigned(eModeARM, 8 + imm32);
2082 lr = pc - 4; // return address
2083 imm32 = llvm::SignExtend32<26>(Bits32(opcode, 23, 0) << 2 |
2084 Bits32(opcode, 24, 24) << 1);
2085 target = pc + imm32;
2086 SelectInstrSet(eModeThumb);
2087 context.SetISAAndImmediateSigned(eModeThumb, 8 + imm32);
2092 if (!WriteRegisterUnsigned(context, eRegisterKindGeneric,
2093 LLDB_REGNUM_GENERIC_RA, lr))
2095 if (!BranchWritePC(context, target))
2097 if (m_opcode_cpsr != m_new_inst_cpsr)
2098 if (!WriteRegisterUnsigned(context, eRegisterKindGeneric,
2099 LLDB_REGNUM_GENERIC_FLAGS, m_new_inst_cpsr))
2105 // Branch with Link and Exchange (register) calls a subroutine at an address
2106 // and instruction set specified by a register.
2108 bool EmulateInstructionARM::EmulateBLXRm(const uint32_t opcode,
2109 const ARMEncoding encoding) {
2111 // ARM pseudo code...
2112 if (ConditionPassed())
2114 EncodingSpecificOperations();
2116 if CurrentInstrSet() == InstrSet_ARM then
2117 next_instr_addr = PC - 4;
2118 LR = next_instr_addr;
2120 next_instr_addr = PC - 2;
2121 LR = next_instr_addr<31:1> : '1';
2126 bool success = false;
2128 if (ConditionPassed(opcode)) {
2129 EmulateInstruction::Context context;
2130 context.type = EmulateInstruction::eContextAbsoluteBranchRegister;
2131 const uint32_t pc = ReadCoreReg(PC_REG, &success);
2132 addr_t lr; // next instruction address
2135 uint32_t Rm; // the register with the target address
2138 lr = (pc - 2) | 1u; // return address
2139 Rm = Bits32(opcode, 6, 3);
2140 // if m == 15 then UNPREDICTABLE;
2143 if (InITBlock() && !LastInITBlock())
2147 lr = pc - 4; // return address
2148 Rm = Bits32(opcode, 3, 0);
2149 // if m == 15 then UNPREDICTABLE;
2156 addr_t target = ReadCoreReg(Rm, &success);
2159 RegisterInfo dwarf_reg;
2160 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + Rm, dwarf_reg);
2161 context.SetRegister(dwarf_reg);
2162 if (!WriteRegisterUnsigned(context, eRegisterKindGeneric,
2163 LLDB_REGNUM_GENERIC_RA, lr))
2165 if (!BXWritePC(context, target))
2171 // Branch and Exchange causes a branch to an address and instruction set
2172 // specified by a register.
2173 bool EmulateInstructionARM::EmulateBXRm(const uint32_t opcode,
2174 const ARMEncoding encoding) {
2176 // ARM pseudo code...
2177 if (ConditionPassed())
2179 EncodingSpecificOperations();
2184 if (ConditionPassed(opcode)) {
2185 EmulateInstruction::Context context;
2186 context.type = EmulateInstruction::eContextAbsoluteBranchRegister;
2187 uint32_t Rm; // the register with the target address
2190 Rm = Bits32(opcode, 6, 3);
2191 if (InITBlock() && !LastInITBlock())
2195 Rm = Bits32(opcode, 3, 0);
2200 bool success = false;
2201 addr_t target = ReadCoreReg(Rm, &success);
2205 RegisterInfo dwarf_reg;
2206 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + Rm, dwarf_reg);
2207 context.SetRegister(dwarf_reg);
2208 if (!BXWritePC(context, target))
2214 // Branch and Exchange Jazelle attempts to change to Jazelle state. If the
2215 // attempt fails, it branches to an address and instruction set specified by a
2216 // register as though it were a BX instruction.
2218 // TODO: Emulate Jazelle architecture?
2219 // We currently assume that switching to Jazelle state fails, thus
2220 // treating BXJ as a BX operation.
2221 bool EmulateInstructionARM::EmulateBXJRm(const uint32_t opcode,
2222 const ARMEncoding encoding) {
2224 // ARM pseudo code...
2225 if (ConditionPassed())
2227 EncodingSpecificOperations();
2228 if JMCR.JE == '0' || CurrentInstrSet() == InstrSet_ThumbEE then
2231 if JazelleAcceptsExecution() then
2232 SwitchToJazelleExecution();
2234 SUBARCHITECTURE_DEFINED handler call;
2238 if (ConditionPassed(opcode)) {
2239 EmulateInstruction::Context context;
2240 context.type = EmulateInstruction::eContextAbsoluteBranchRegister;
2241 uint32_t Rm; // the register with the target address
2244 Rm = Bits32(opcode, 19, 16);
2247 if (InITBlock() && !LastInITBlock())
2251 Rm = Bits32(opcode, 3, 0);
2258 bool success = false;
2259 addr_t target = ReadCoreReg(Rm, &success);
2263 RegisterInfo dwarf_reg;
2264 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + Rm, dwarf_reg);
2265 context.SetRegister(dwarf_reg);
2266 if (!BXWritePC(context, target))
2272 // Set r7 to point to some ip offset.
2274 bool EmulateInstructionARM::EmulateSUBR7IPImm(const uint32_t opcode,
2275 const ARMEncoding encoding) {
2277 // ARM pseudo code...
2278 if (ConditionPassed())
2280 EncodingSpecificOperations();
2281 (result, carry, overflow) = AddWithCarry(SP, NOT(imm32), '1');
2282 if d == 15 then // Can only occur for ARM encoding
2283 ALUWritePC(result); // setflags is always FALSE here
2287 APSR.N = result<31>;
2288 APSR.Z = IsZeroBit(result);
2294 if (ConditionPassed(opcode)) {
2295 bool success = false;
2296 const addr_t ip = ReadCoreReg(12, &success);
2302 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
2307 addr_t ip_offset = imm32;
2308 addr_t addr = ip - ip_offset; // the adjusted ip value
2310 EmulateInstruction::Context context;
2311 context.type = EmulateInstruction::eContextRegisterPlusOffset;
2312 RegisterInfo dwarf_reg;
2313 GetRegisterInfo(eRegisterKindDWARF, dwarf_r12, dwarf_reg);
2314 context.SetRegisterPlusOffset(dwarf_reg, -ip_offset);
2316 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r7, addr))
2322 // Set ip to point to some stack offset.
2323 // SUB (SP minus immediate)
2324 bool EmulateInstructionARM::EmulateSUBIPSPImm(const uint32_t opcode,
2325 const ARMEncoding encoding) {
2327 // ARM pseudo code...
2328 if (ConditionPassed())
2330 EncodingSpecificOperations();
2331 (result, carry, overflow) = AddWithCarry(SP, NOT(imm32), '1');
2332 if d == 15 then // Can only occur for ARM encoding
2333 ALUWritePC(result); // setflags is always FALSE here
2337 APSR.N = result<31>;
2338 APSR.Z = IsZeroBit(result);
2344 if (ConditionPassed(opcode)) {
2345 bool success = false;
2346 const addr_t sp = ReadCoreReg(SP_REG, &success);
2352 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
2357 addr_t sp_offset = imm32;
2358 addr_t addr = sp - sp_offset; // the adjusted stack pointer value
2360 EmulateInstruction::Context context;
2361 context.type = EmulateInstruction::eContextRegisterPlusOffset;
2362 RegisterInfo dwarf_reg;
2363 GetRegisterInfo(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, dwarf_reg);
2364 context.SetRegisterPlusOffset(dwarf_reg, -sp_offset);
2366 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r12, addr))
2372 // This instruction subtracts an immediate value from the SP value, and writes
2373 // the result to the destination register.
2375 // If Rd == 13 => A sub operation to adjust the SP -- allocate space for local
2377 bool EmulateInstructionARM::EmulateSUBSPImm(const uint32_t opcode,
2378 const ARMEncoding encoding) {
2380 // ARM pseudo code...
2381 if (ConditionPassed())
2383 EncodingSpecificOperations();
2384 (result, carry, overflow) = AddWithCarry(SP, NOT(imm32), '1');
2385 if d == 15 then // Can only occur for ARM encoding
2386 ALUWritePC(result); // setflags is always FALSE here
2390 APSR.N = result<31>;
2391 APSR.Z = IsZeroBit(result);
2397 bool success = false;
2398 if (ConditionPassed(opcode)) {
2399 const addr_t sp = ReadCoreReg(SP_REG, &success);
2410 imm32 = ThumbImm7Scaled(opcode); // imm32 = ZeroExtend(imm7:'00', 32)
2413 Rd = Bits32(opcode, 11, 8);
2414 setflags = BitIsSet(opcode, 20);
2415 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8)
2416 if (Rd == 15 && setflags)
2417 return EmulateCMPImm(opcode, eEncodingT2);
2418 if (Rd == 15 && !setflags)
2422 Rd = Bits32(opcode, 11, 8);
2424 imm32 = ThumbImm12(opcode); // imm32 = ZeroExtend(i:imm3:imm8, 32)
2429 Rd = Bits32(opcode, 15, 12);
2430 setflags = BitIsSet(opcode, 20);
2431 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
2433 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related
2435 if (Rd == 15 && setflags)
2436 return EmulateSUBSPcLrEtc(opcode, encoding);
2441 AddWithCarryResult res = AddWithCarry(sp, ~imm32, 1);
2443 EmulateInstruction::Context context;
2445 uint64_t imm64 = imm32; // Need to expand it to 64 bits before attempting
2446 // to negate it, or the wrong
2447 // value gets passed down to context.SetImmediateSigned.
2448 context.type = EmulateInstruction::eContextAdjustStackPointer;
2449 context.SetImmediateSigned(-imm64); // the stack pointer offset
2451 context.type = EmulateInstruction::eContextImmediate;
2452 context.SetNoArgs();
2455 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags,
2456 res.carry_out, res.overflow))
2462 // A store operation to the stack that also updates the SP.
2463 bool EmulateInstructionARM::EmulateSTRRtSP(const uint32_t opcode,
2464 const ARMEncoding encoding) {
2466 // ARM pseudo code...
2467 if (ConditionPassed())
2469 EncodingSpecificOperations();
2470 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
2471 address = if index then offset_addr else R[n];
2472 MemU[address,4] = if t == 15 then PCStoreValue() else R[t];
2473 if wback then R[n] = offset_addr;
2477 bool success = false;
2478 if (ConditionPassed(opcode)) {
2479 const uint32_t addr_byte_size = GetAddressByteSize();
2480 const addr_t sp = ReadCoreReg(SP_REG, &success);
2483 uint32_t Rt; // the source register
2486 Rn; // This function assumes Rn is the SP, but we should verify that.
2493 Rt = Bits32(opcode, 15, 12);
2494 imm12 = Bits32(opcode, 11, 0);
2495 Rn = Bits32(opcode, 19, 16);
2497 if (Rn != 13) // 13 is the SP reg on ARM. Verify that Rn == SP.
2500 index = BitIsSet(opcode, 24);
2501 add = BitIsSet(opcode, 23);
2502 wback = (BitIsClear(opcode, 24) || BitIsSet(opcode, 21));
2504 if (wback && ((Rn == 15) || (Rn == Rt)))
2512 offset_addr = sp + imm12;
2514 offset_addr = sp - imm12;
2522 EmulateInstruction::Context context;
2523 context.type = EmulateInstruction::eContextPushRegisterOnStack;
2524 RegisterInfo sp_reg;
2525 RegisterInfo dwarf_reg;
2527 GetRegisterInfo(eRegisterKindDWARF, dwarf_sp, sp_reg);
2528 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + Rt, dwarf_reg);
2529 context.SetRegisterToRegisterPlusOffset(dwarf_reg, sp_reg, addr - sp);
2531 uint32_t reg_value = ReadCoreReg(Rt, &success);
2534 if (!MemUWrite(context, addr, reg_value, addr_byte_size))
2537 const uint32_t pc = ReadCoreReg(PC_REG, &success);
2540 if (!MemUWrite(context, addr, pc, addr_byte_size))
2545 context.type = EmulateInstruction::eContextAdjustStackPointer;
2546 context.SetImmediateSigned(addr - sp);
2547 if (!WriteRegisterUnsigned(context, eRegisterKindGeneric,
2548 LLDB_REGNUM_GENERIC_SP, offset_addr))
2555 // Vector Push stores multiple extension registers to the stack. It also
2556 // updates SP to point to the start of the stored data.
2557 bool EmulateInstructionARM::EmulateVPUSH(const uint32_t opcode,
2558 const ARMEncoding encoding) {
2560 // ARM pseudo code...
2561 if (ConditionPassed())
2563 EncodingSpecificOperations(); CheckVFPEnabled(TRUE); NullCheckIfThumbEE(13);
2564 address = SP - imm32;
2568 MemA[address,4] = S[d+r]; address = address+4;
2571 // Store as two word-aligned words in the correct order for
2572 // current endianness.
2573 MemA[address,4] = if BigEndian() then D[d+r]<63:32> else D[d+r]<31:0>;
2574 MemA[address+4,4] = if BigEndian() then D[d+r]<31:0> else D[d+r]<63:32>;
2575 address = address+8;
2579 bool success = false;
2580 if (ConditionPassed(opcode)) {
2581 const uint32_t addr_byte_size = GetAddressByteSize();
2582 const addr_t sp = ReadCoreReg(SP_REG, &success);
2586 uint32_t d; // UInt(D:Vd) or UInt(Vd:D) starting register
2587 uint32_t imm32; // stack offset
2588 uint32_t regs; // number of registers
2592 single_regs = false;
2593 d = Bit32(opcode, 22) << 4 | Bits32(opcode, 15, 12);
2594 imm32 = Bits32(opcode, 7, 0) * addr_byte_size;
2595 // If UInt(imm8) is odd, see "FSTMX".
2596 regs = Bits32(opcode, 7, 0) / 2;
2597 // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE;
2598 if (regs == 0 || regs > 16 || (d + regs) > 32)
2604 d = Bits32(opcode, 15, 12) << 1 | Bit32(opcode, 22);
2605 imm32 = Bits32(opcode, 7, 0) * addr_byte_size;
2606 regs = Bits32(opcode, 7, 0);
2607 // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE;
2608 if (regs == 0 || regs > 16 || (d + regs) > 32)
2614 uint32_t start_reg = single_regs ? dwarf_s0 : dwarf_d0;
2615 uint32_t reg_byte_size = single_regs ? addr_byte_size : addr_byte_size * 2;
2616 addr_t sp_offset = imm32;
2617 addr_t addr = sp - sp_offset;
2620 EmulateInstruction::Context context;
2621 context.type = EmulateInstruction::eContextPushRegisterOnStack;
2623 RegisterInfo dwarf_reg;
2624 RegisterInfo sp_reg;
2625 GetRegisterInfo(eRegisterKindDWARF, dwarf_sp, sp_reg);
2626 for (i = 0; i < regs; ++i) {
2627 GetRegisterInfo(eRegisterKindDWARF, start_reg + d + i, dwarf_reg);
2628 context.SetRegisterToRegisterPlusOffset(dwarf_reg, sp_reg, addr - sp);
2629 // uint64_t to accommodate 64-bit registers.
2630 uint64_t reg_value = ReadRegisterUnsigned(&dwarf_reg, 0, &success);
2633 if (!MemAWrite(context, addr, reg_value, reg_byte_size))
2635 addr += reg_byte_size;
2638 context.type = EmulateInstruction::eContextAdjustStackPointer;
2639 context.SetImmediateSigned(-sp_offset);
2641 if (!WriteRegisterUnsigned(context, eRegisterKindGeneric,
2642 LLDB_REGNUM_GENERIC_SP, sp - sp_offset))
2648 // Vector Pop loads multiple extension registers from the stack. It also
2649 // updates SP to point just above the loaded data.
2650 bool EmulateInstructionARM::EmulateVPOP(const uint32_t opcode,
2651 const ARMEncoding encoding) {
2653 // ARM pseudo code...
2654 if (ConditionPassed())
2656 EncodingSpecificOperations(); CheckVFPEnabled(TRUE); NullCheckIfThumbEE(13);
2661 S[d+r] = MemA[address,4]; address = address+4;
2664 word1 = MemA[address,4]; word2 = MemA[address+4,4]; address = address+8;
2665 // Combine the word-aligned words in the correct order for
2666 // current endianness.
2667 D[d+r] = if BigEndian() then word1:word2 else word2:word1;
2671 bool success = false;
2672 if (ConditionPassed(opcode)) {
2673 const uint32_t addr_byte_size = GetAddressByteSize();
2674 const addr_t sp = ReadCoreReg(SP_REG, &success);
2678 uint32_t d; // UInt(D:Vd) or UInt(Vd:D) starting register
2679 uint32_t imm32; // stack offset
2680 uint32_t regs; // number of registers
2684 single_regs = false;
2685 d = Bit32(opcode, 22) << 4 | Bits32(opcode, 15, 12);
2686 imm32 = Bits32(opcode, 7, 0) * addr_byte_size;
2687 // If UInt(imm8) is odd, see "FLDMX".
2688 regs = Bits32(opcode, 7, 0) / 2;
2689 // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE;
2690 if (regs == 0 || regs > 16 || (d + regs) > 32)
2696 d = Bits32(opcode, 15, 12) << 1 | Bit32(opcode, 22);
2697 imm32 = Bits32(opcode, 7, 0) * addr_byte_size;
2698 regs = Bits32(opcode, 7, 0);
2699 // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE;
2700 if (regs == 0 || regs > 16 || (d + regs) > 32)
2706 uint32_t start_reg = single_regs ? dwarf_s0 : dwarf_d0;
2707 uint32_t reg_byte_size = single_regs ? addr_byte_size : addr_byte_size * 2;
2708 addr_t sp_offset = imm32;
2711 uint64_t data; // uint64_t to accommodate 64-bit registers.
2713 EmulateInstruction::Context context;
2714 context.type = EmulateInstruction::eContextPopRegisterOffStack;
2716 RegisterInfo dwarf_reg;
2717 RegisterInfo sp_reg;
2718 GetRegisterInfo(eRegisterKindDWARF, dwarf_sp, sp_reg);
2719 for (i = 0; i < regs; ++i) {
2720 GetRegisterInfo(eRegisterKindDWARF, start_reg + d + i, dwarf_reg);
2721 context.SetAddress(addr);
2722 data = MemARead(context, addr, reg_byte_size, 0, &success);
2725 if (!WriteRegisterUnsigned(context, &dwarf_reg, data))
2727 addr += reg_byte_size;
2730 context.type = EmulateInstruction::eContextAdjustStackPointer;
2731 context.SetImmediateSigned(sp_offset);
2733 if (!WriteRegisterUnsigned(context, eRegisterKindGeneric,
2734 LLDB_REGNUM_GENERIC_SP, sp + sp_offset))
2740 // SVC (previously SWI)
2741 bool EmulateInstructionARM::EmulateSVC(const uint32_t opcode,
2742 const ARMEncoding encoding) {
2744 // ARM pseudo code...
2745 if (ConditionPassed())
2747 EncodingSpecificOperations();
2752 bool success = false;
2754 if (ConditionPassed(opcode)) {
2755 const uint32_t pc = ReadCoreReg(PC_REG, &success);
2756 addr_t lr; // next instruction address
2759 uint32_t imm32; // the immediate constant
2760 uint32_t mode; // ARM or Thumb mode
2763 lr = (pc + 2) | 1u; // return address
2764 imm32 = Bits32(opcode, 7, 0);
2768 lr = pc + 4; // return address
2769 imm32 = Bits32(opcode, 23, 0);
2776 EmulateInstruction::Context context;
2777 context.type = EmulateInstruction::eContextSupervisorCall;
2778 context.SetISAAndImmediate(mode, imm32);
2779 if (!WriteRegisterUnsigned(context, eRegisterKindGeneric,
2780 LLDB_REGNUM_GENERIC_RA, lr))
2786 // If Then makes up to four following instructions (the IT block) conditional.
2787 bool EmulateInstructionARM::EmulateIT(const uint32_t opcode,
2788 const ARMEncoding encoding) {
2790 // ARM pseudo code...
2791 EncodingSpecificOperations();
2792 ITSTATE.IT<7:0> = firstcond:mask;
2795 m_it_session.InitIT(Bits32(opcode, 7, 0));
2799 bool EmulateInstructionARM::EmulateNop(const uint32_t opcode,
2800 const ARMEncoding encoding) {
2801 // NOP, nothing to do...
2805 // Branch causes a branch to a target address.
2806 bool EmulateInstructionARM::EmulateB(const uint32_t opcode,
2807 const ARMEncoding encoding) {
2809 // ARM pseudo code...
2810 if (ConditionPassed())
2812 EncodingSpecificOperations();
2813 BranchWritePC(PC + imm32);
2817 bool success = false;
2819 if (ConditionPassed(opcode)) {
2820 EmulateInstruction::Context context;
2821 context.type = EmulateInstruction::eContextRelativeBranchImmediate;
2822 const uint32_t pc = ReadCoreReg(PC_REG, &success);
2825 addr_t target; // target address
2826 int32_t imm32; // PC-relative offset
2829 // The 'cond' field is handled in EmulateInstructionARM::CurrentCond().
2830 imm32 = llvm::SignExtend32<9>(Bits32(opcode, 7, 0) << 1);
2831 target = pc + imm32;
2832 context.SetISAAndImmediateSigned(eModeThumb, 4 + imm32);
2835 imm32 = llvm::SignExtend32<12>(Bits32(opcode, 10, 0) << 1);
2836 target = pc + imm32;
2837 context.SetISAAndImmediateSigned(eModeThumb, 4 + imm32);
2840 // The 'cond' field is handled in EmulateInstructionARM::CurrentCond().
2842 if (Bits32(opcode, 25, 23) == 7)
2843 return false; // See Branches and miscellaneous control on page
2846 uint32_t S = Bit32(opcode, 26);
2847 uint32_t imm6 = Bits32(opcode, 21, 16);
2848 uint32_t J1 = Bit32(opcode, 13);
2849 uint32_t J2 = Bit32(opcode, 11);
2850 uint32_t imm11 = Bits32(opcode, 10, 0);
2852 (S << 20) | (J2 << 19) | (J1 << 18) | (imm6 << 12) | (imm11 << 1);
2853 imm32 = llvm::SignExtend32<21>(imm21);
2854 target = pc + imm32;
2855 context.SetISAAndImmediateSigned(eModeThumb, 4 + imm32);
2859 uint32_t S = Bit32(opcode, 26);
2860 uint32_t imm10 = Bits32(opcode, 25, 16);
2861 uint32_t J1 = Bit32(opcode, 13);
2862 uint32_t J2 = Bit32(opcode, 11);
2863 uint32_t imm11 = Bits32(opcode, 10, 0);
2864 uint32_t I1 = !(J1 ^ S);
2865 uint32_t I2 = !(J2 ^ S);
2867 (S << 24) | (I1 << 23) | (I2 << 22) | (imm10 << 12) | (imm11 << 1);
2868 imm32 = llvm::SignExtend32<25>(imm25);
2869 target = pc + imm32;
2870 context.SetISAAndImmediateSigned(eModeThumb, 4 + imm32);
2874 imm32 = llvm::SignExtend32<26>(Bits32(opcode, 23, 0) << 2);
2875 target = pc + imm32;
2876 context.SetISAAndImmediateSigned(eModeARM, 8 + imm32);
2881 if (!BranchWritePC(context, target))
2887 // Compare and Branch on Nonzero and Compare and Branch on Zero compare the
2888 // value in a register with zero and conditionally branch forward a constant
2889 // value. They do not affect the condition flags. CBNZ, CBZ
2890 bool EmulateInstructionARM::EmulateCB(const uint32_t opcode,
2891 const ARMEncoding encoding) {
2893 // ARM pseudo code...
2894 EncodingSpecificOperations();
2895 if nonzero ^ IsZero(R[n]) then
2896 BranchWritePC(PC + imm32);
2899 bool success = false;
2901 // Read the register value from the operand register Rn.
2902 uint32_t reg_val = ReadCoreReg(Bits32(opcode, 2, 0), &success);
2906 EmulateInstruction::Context context;
2907 context.type = EmulateInstruction::eContextRelativeBranchImmediate;
2908 const uint32_t pc = ReadCoreReg(PC_REG, &success);
2912 addr_t target; // target address
2913 uint32_t imm32; // PC-relative offset to branch forward
2917 imm32 = Bit32(opcode, 9) << 6 | Bits32(opcode, 7, 3) << 1;
2918 nonzero = BitIsSet(opcode, 11);
2919 target = pc + imm32;
2920 context.SetISAAndImmediateSigned(eModeThumb, 4 + imm32);
2925 if (m_ignore_conditions || (nonzero ^ (reg_val == 0)))
2926 if (!BranchWritePC(context, target))
2932 // Table Branch Byte causes a PC-relative forward branch using a table of
2933 // single byte offsets.
2934 // A base register provides a pointer to the table, and a second register
2935 // supplies an index into the table.
2936 // The branch length is twice the value of the byte returned from the table.
2938 // Table Branch Halfword causes a PC-relative forward branch using a table of
2939 // single halfword offsets.
2940 // A base register provides a pointer to the table, and a second register
2941 // supplies an index into the table.
2942 // The branch length is twice the value of the halfword returned from the
2944 bool EmulateInstructionARM::EmulateTB(const uint32_t opcode,
2945 const ARMEncoding encoding) {
2947 // ARM pseudo code...
2948 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
2950 halfwords = UInt(MemU[R[n]+LSL(R[m],1), 2]);
2952 halfwords = UInt(MemU[R[n]+R[m], 1]);
2953 BranchWritePC(PC + 2*halfwords);
2956 bool success = false;
2958 if (ConditionPassed(opcode)) {
2959 uint32_t Rn; // the base register which contains the address of the table of
2961 uint32_t Rm; // the index register which contains an integer pointing to a
2962 // byte/halfword in the table
2963 bool is_tbh; // true if table branch halfword
2966 Rn = Bits32(opcode, 19, 16);
2967 Rm = Bits32(opcode, 3, 0);
2968 is_tbh = BitIsSet(opcode, 4);
2969 if (Rn == 13 || BadReg(Rm))
2971 if (InITBlock() && !LastInITBlock())
2978 // Read the address of the table from the operand register Rn. The PC can
2979 // be used, in which case the table immediately follows this instruction.
2980 uint32_t base = ReadCoreReg(Rn, &success);
2985 uint32_t index = ReadCoreReg(Rm, &success);
2989 // the offsetted table address
2990 addr_t addr = base + (is_tbh ? index * 2 : index);
2992 // PC-relative offset to branch forward
2993 EmulateInstruction::Context context;
2994 context.type = EmulateInstruction::eContextTableBranchReadMemory;
2995 uint32_t offset = MemURead(context, addr, is_tbh ? 2 : 1, 0, &success) * 2;
2999 const uint32_t pc = ReadCoreReg(PC_REG, &success);
3004 addr_t target = pc + offset;
3005 context.type = EmulateInstruction::eContextRelativeBranchImmediate;
3006 context.SetISAAndImmediateSigned(eModeThumb, 4 + offset);
3008 if (!BranchWritePC(context, target))
3015 // This instruction adds an immediate value to a register value, and writes the
3016 // result to the destination register. It can optionally update the condition
3017 // flags based on the result.
3018 bool EmulateInstructionARM::EmulateADDImmThumb(const uint32_t opcode,
3019 const ARMEncoding encoding) {
3021 if ConditionPassed() then
3022 EncodingSpecificOperations();
3023 (result, carry, overflow) = AddWithCarry(R[n], imm32, '0');
3026 APSR.N = result<31>;
3027 APSR.Z = IsZeroBit(result);
3032 bool success = false;
3034 if (ConditionPassed(opcode)) {
3041 // EncodingSpecificOperations();
3044 // d = UInt(Rd); n = UInt(Rn); setflags = !InITBlock(); imm32 =
3045 // ZeroExtend(imm3, 32);
3046 d = Bits32(opcode, 2, 0);
3047 n = Bits32(opcode, 5, 3);
3048 setflags = !InITBlock();
3049 imm32 = Bits32(opcode, 8, 6);
3054 // d = UInt(Rdn); n = UInt(Rdn); setflags = !InITBlock(); imm32 =
3055 // ZeroExtend(imm8, 32);
3056 d = Bits32(opcode, 10, 8);
3057 n = Bits32(opcode, 10, 8);
3058 setflags = !InITBlock();
3059 imm32 = Bits32(opcode, 7, 0);
3064 // if Rd == '1111' && S == '1' then SEE CMN (immediate);
3065 // d = UInt(Rd); n = UInt(Rn); setflags = (S == '1'); imm32 =
3066 // ThumbExpandImm(i:imm3:imm8);
3067 d = Bits32(opcode, 11, 8);
3068 n = Bits32(opcode, 19, 16);
3069 setflags = BitIsSet(opcode, 20);
3070 imm32 = ThumbExpandImm_C(opcode, APSR_C, carry_out);
3072 // if Rn == '1101' then SEE ADD (SP plus immediate);
3074 return EmulateADDSPImm(opcode, eEncodingT3);
3076 // if BadReg(d) || n == 15 then UNPREDICTABLE;
3077 if (BadReg(d) || (n == 15))
3083 // if Rn == '1111' then SEE ADR;
3084 // d = UInt(Rd); n = UInt(Rn); setflags = FALSE; imm32 =
3085 // ZeroExtend(i:imm3:imm8, 32);
3086 d = Bits32(opcode, 11, 8);
3087 n = Bits32(opcode, 19, 16);
3089 uint32_t i = Bit32(opcode, 26);
3090 uint32_t imm3 = Bits32(opcode, 14, 12);
3091 uint32_t imm8 = Bits32(opcode, 7, 0);
3092 imm32 = (i << 11) | (imm3 << 8) | imm8;
3094 // if Rn == '1101' then SEE ADD (SP plus immediate);
3096 return EmulateADDSPImm(opcode, eEncodingT4);
3098 // if BadReg(d) then UNPREDICTABLE;
3110 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
3114 //(result, carry, overflow) = AddWithCarry(R[n], imm32, '0');
3115 AddWithCarryResult res = AddWithCarry(Rn, imm32, 0);
3118 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n, reg_n);
3120 EmulateInstruction::Context context;
3121 context.type = eContextArithmetic;
3122 context.SetRegisterPlusOffset(reg_n, imm32);
3126 // APSR.N = result<31>;
3127 // APSR.Z = IsZeroBit(result);
3129 // APSR.V = overflow;
3130 if (!WriteCoreRegOptionalFlags(context, res.result, d, setflags,
3131 res.carry_out, res.overflow))
3137 // This instruction adds an immediate value to a register value, and writes the
3138 // result to the destination register. It can optionally update the condition
3139 // flags based on the result.
3140 bool EmulateInstructionARM::EmulateADDImmARM(const uint32_t opcode,
3141 const ARMEncoding encoding) {
3143 // ARM pseudo code...
3144 if ConditionPassed() then
3145 EncodingSpecificOperations();
3146 (result, carry, overflow) = AddWithCarry(R[n], imm32, '0');
3148 ALUWritePC(result); // setflags is always FALSE here
3152 APSR.N = result<31>;
3153 APSR.Z = IsZeroBit(result);
3158 bool success = false;
3160 if (ConditionPassed(opcode)) {
3163 imm32; // the immediate value to be added to the value obtained from Rn
3167 Rd = Bits32(opcode, 15, 12);
3168 Rn = Bits32(opcode, 19, 16);
3169 setflags = BitIsSet(opcode, 20);
3170 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
3176 // Read the first operand.
3177 uint32_t val1 = ReadCoreReg(Rn, &success);
3181 AddWithCarryResult res = AddWithCarry(val1, imm32, 0);
3183 EmulateInstruction::Context context;
3185 context.type = EmulateInstruction::eContextAdjustStackPointer;
3186 else if (Rd == GetFramePointerRegisterNumber())
3187 context.type = EmulateInstruction::eContextSetFramePointer;
3189 context.type = EmulateInstruction::eContextRegisterPlusOffset;
3191 RegisterInfo dwarf_reg;
3192 GetRegisterInfo(eRegisterKindDWARF, Rn, dwarf_reg);
3193 context.SetRegisterPlusOffset(dwarf_reg, imm32);
3195 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags,
3196 res.carry_out, res.overflow))
3202 // This instruction adds a register value and an optionally-shifted register
3203 // value, and writes the result to the destination register. It can optionally
3204 // update the condition flags based on the result.
3205 bool EmulateInstructionARM::EmulateADDReg(const uint32_t opcode,
3206 const ARMEncoding encoding) {
3208 // ARM pseudo code...
3209 if ConditionPassed() then
3210 EncodingSpecificOperations();
3211 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
3212 (result, carry, overflow) = AddWithCarry(R[n], shifted, '0');
3214 ALUWritePC(result); // setflags is always FALSE here
3218 APSR.N = result<31>;
3219 APSR.Z = IsZeroBit(result);
3224 bool success = false;
3226 if (ConditionPassed(opcode)) {
3227 uint32_t Rd, Rn, Rm;
3228 ARM_ShifterType shift_t;
3229 uint32_t shift_n; // the shift applied to the value read from Rm
3233 Rd = Bits32(opcode, 2, 0);
3234 Rn = Bits32(opcode, 5, 3);
3235 Rm = Bits32(opcode, 8, 6);
3236 setflags = !InITBlock();
3237 shift_t = SRType_LSL;
3241 Rd = Rn = Bit32(opcode, 7) << 3 | Bits32(opcode, 2, 0);
3242 Rm = Bits32(opcode, 6, 3);
3244 shift_t = SRType_LSL;
3246 if (Rn == 15 && Rm == 15)
3248 if (Rd == 15 && InITBlock() && !LastInITBlock())
3252 Rd = Bits32(opcode, 15, 12);
3253 Rn = Bits32(opcode, 19, 16);
3254 Rm = Bits32(opcode, 3, 0);
3255 setflags = BitIsSet(opcode, 20);
3256 shift_n = DecodeImmShiftARM(opcode, shift_t);
3262 // Read the first operand.
3263 uint32_t val1 = ReadCoreReg(Rn, &success);
3267 // Read the second operand.
3268 uint32_t val2 = ReadCoreReg(Rm, &success);
3272 uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C, &success);
3275 AddWithCarryResult res = AddWithCarry(val1, shifted, 0);
3277 EmulateInstruction::Context context;
3278 context.type = eContextArithmetic;
3279 RegisterInfo op1_reg;
3280 RegisterInfo op2_reg;
3281 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + Rn, op1_reg);
3282 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + Rm, op2_reg);
3283 context.SetRegisterRegisterOperands(op1_reg, op2_reg);
3285 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags,
3286 res.carry_out, res.overflow))
3292 // Compare Negative (immediate) adds a register value and an immediate value.
3293 // It updates the condition flags based on the result, and discards the result.
3294 bool EmulateInstructionARM::EmulateCMNImm(const uint32_t opcode,
3295 const ARMEncoding encoding) {
3297 // ARM pseudo code...
3298 if ConditionPassed() then
3299 EncodingSpecificOperations();
3300 (result, carry, overflow) = AddWithCarry(R[n], imm32, '0');
3301 APSR.N = result<31>;
3302 APSR.Z = IsZeroBit(result);
3307 bool success = false;
3309 uint32_t Rn; // the first operand
3310 uint32_t imm32; // the immediate value to be compared with
3313 Rn = Bits32(opcode, 19, 16);
3314 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8)
3319 Rn = Bits32(opcode, 19, 16);
3320 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
3325 // Read the register value from the operand register Rn.
3326 uint32_t reg_val = ReadCoreReg(Rn, &success);
3330 AddWithCarryResult res = AddWithCarry(reg_val, imm32, 0);
3332 EmulateInstruction::Context context;
3333 context.type = EmulateInstruction::eContextImmediate;
3334 context.SetNoArgs();
3335 return WriteFlags(context, res.result, res.carry_out, res.overflow);
3338 // Compare Negative (register) adds a register value and an optionally-shifted
3339 // register value. It updates the condition flags based on the result, and
3340 // discards the result.
3341 bool EmulateInstructionARM::EmulateCMNReg(const uint32_t opcode,
3342 const ARMEncoding encoding) {
3344 // ARM pseudo code...
3345 if ConditionPassed() then
3346 EncodingSpecificOperations();
3347 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
3348 (result, carry, overflow) = AddWithCarry(R[n], shifted, '0');
3349 APSR.N = result<31>;
3350 APSR.Z = IsZeroBit(result);
3355 bool success = false;
3357 uint32_t Rn; // the first operand
3358 uint32_t Rm; // the second operand
3359 ARM_ShifterType shift_t;
3360 uint32_t shift_n; // the shift applied to the value read from Rm
3363 Rn = Bits32(opcode, 2, 0);
3364 Rm = Bits32(opcode, 5, 3);
3365 shift_t = SRType_LSL;
3369 Rn = Bits32(opcode, 19, 16);
3370 Rm = Bits32(opcode, 3, 0);
3371 shift_n = DecodeImmShiftThumb(opcode, shift_t);
3372 // if n == 15 || BadReg(m) then UNPREDICTABLE;
3373 if (Rn == 15 || BadReg(Rm))
3377 Rn = Bits32(opcode, 19, 16);
3378 Rm = Bits32(opcode, 3, 0);
3379 shift_n = DecodeImmShiftARM(opcode, shift_t);
3384 // Read the register value from register Rn.
3385 uint32_t val1 = ReadCoreReg(Rn, &success);
3389 // Read the register value from register Rm.
3390 uint32_t val2 = ReadCoreReg(Rm, &success);
3394 uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C, &success);
3397 AddWithCarryResult res = AddWithCarry(val1, shifted, 0);
3399 EmulateInstruction::Context context;
3400 context.type = EmulateInstruction::eContextImmediate;
3401 context.SetNoArgs();
3402 return WriteFlags(context, res.result, res.carry_out, res.overflow);
3405 // Compare (immediate) subtracts an immediate value from a register value. It
3406 // updates the condition flags based on the result, and discards the result.
3407 bool EmulateInstructionARM::EmulateCMPImm(const uint32_t opcode,
3408 const ARMEncoding encoding) {
3410 // ARM pseudo code...
3411 if ConditionPassed() then
3412 EncodingSpecificOperations();
3413 (result, carry, overflow) = AddWithCarry(R[n], NOT(imm32), '1');
3414 APSR.N = result<31>;
3415 APSR.Z = IsZeroBit(result);
3420 bool success = false;
3422 uint32_t Rn; // the first operand
3423 uint32_t imm32; // the immediate value to be compared with
3426 Rn = Bits32(opcode, 10, 8);
3427 imm32 = Bits32(opcode, 7, 0);
3430 Rn = Bits32(opcode, 19, 16);
3431 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8)
3436 Rn = Bits32(opcode, 19, 16);
3437 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
3442 // Read the register value from the operand register Rn.
3443 uint32_t reg_val = ReadCoreReg(Rn, &success);
3447 AddWithCarryResult res = AddWithCarry(reg_val, ~imm32, 1);
3449 EmulateInstruction::Context context;
3450 context.type = EmulateInstruction::eContextImmediate;
3451 context.SetNoArgs();
3452 return WriteFlags(context, res.result, res.carry_out, res.overflow);
3455 // Compare (register) subtracts an optionally-shifted register value from a
3456 // register value. It updates the condition flags based on the result, and
3457 // discards the result.
3458 bool EmulateInstructionARM::EmulateCMPReg(const uint32_t opcode,
3459 const ARMEncoding encoding) {
3461 // ARM pseudo code...
3462 if ConditionPassed() then
3463 EncodingSpecificOperations();
3464 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
3465 (result, carry, overflow) = AddWithCarry(R[n], NOT(shifted), '1');
3466 APSR.N = result<31>;
3467 APSR.Z = IsZeroBit(result);
3472 bool success = false;
3474 uint32_t Rn; // the first operand
3475 uint32_t Rm; // the second operand
3476 ARM_ShifterType shift_t;
3477 uint32_t shift_n; // the shift applied to the value read from Rm
3480 Rn = Bits32(opcode, 2, 0);
3481 Rm = Bits32(opcode, 5, 3);
3482 shift_t = SRType_LSL;
3486 Rn = Bit32(opcode, 7) << 3 | Bits32(opcode, 2, 0);
3487 Rm = Bits32(opcode, 6, 3);
3488 shift_t = SRType_LSL;
3490 if (Rn < 8 && Rm < 8)
3492 if (Rn == 15 || Rm == 15)
3496 Rn = Bits32(opcode, 19, 16);
3497 Rm = Bits32(opcode, 3, 0);
3498 shift_n = DecodeImmShiftThumb(opcode, shift_t);
3499 if (Rn == 15 || BadReg(Rm))
3503 Rn = Bits32(opcode, 19, 16);
3504 Rm = Bits32(opcode, 3, 0);
3505 shift_n = DecodeImmShiftARM(opcode, shift_t);
3510 // Read the register value from register Rn.
3511 uint32_t val1 = ReadCoreReg(Rn, &success);
3515 // Read the register value from register Rm.
3516 uint32_t val2 = ReadCoreReg(Rm, &success);
3520 uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C, &success);
3523 AddWithCarryResult res = AddWithCarry(val1, ~shifted, 1);
3525 EmulateInstruction::Context context;
3526 context.type = EmulateInstruction::eContextImmediate;
3527 context.SetNoArgs();
3528 return WriteFlags(context, res.result, res.carry_out, res.overflow);
3531 // Arithmetic Shift Right (immediate) shifts a register value right by an
3532 // immediate number of bits, shifting in copies of its sign bit, and writes the
3533 // result to the destination register. It can optionally update the condition
3534 // flags based on the result.
3535 bool EmulateInstructionARM::EmulateASRImm(const uint32_t opcode,
3536 const ARMEncoding encoding) {
3538 // ARM pseudo code...
3539 if ConditionPassed() then
3540 EncodingSpecificOperations();
3541 (result, carry) = Shift_C(R[m], SRType_ASR, shift_n, APSR.C);
3542 if d == 15 then // Can only occur for ARM encoding
3543 ALUWritePC(result); // setflags is always FALSE here
3547 APSR.N = result<31>;
3548 APSR.Z = IsZeroBit(result);
3553 return EmulateShiftImm(opcode, encoding, SRType_ASR);
3556 // Arithmetic Shift Right (register) shifts a register value right by a
3557 // variable number of bits, shifting in copies of its sign bit, and writes the
3558 // result to the destination register. The variable number of bits is read from
3559 // the bottom byte of a register. It can optionally update the condition flags
3560 // based on the result.
3561 bool EmulateInstructionARM::EmulateASRReg(const uint32_t opcode,
3562 const ARMEncoding encoding) {
3564 // ARM pseudo code...
3565 if ConditionPassed() then
3566 EncodingSpecificOperations();
3567 shift_n = UInt(R[m]<7:0>);
3568 (result, carry) = Shift_C(R[m], SRType_ASR, shift_n, APSR.C);
3571 APSR.N = result<31>;
3572 APSR.Z = IsZeroBit(result);
3577 return EmulateShiftReg(opcode, encoding, SRType_ASR);
3580 // Logical Shift Left (immediate) shifts a register value left by an immediate
3581 // number of bits, shifting in zeros, and writes the result to the destination
3582 // register. It can optionally update the condition flags based on the result.
3583 bool EmulateInstructionARM::EmulateLSLImm(const uint32_t opcode,
3584 const ARMEncoding encoding) {
3586 // ARM pseudo code...
3587 if ConditionPassed() then
3588 EncodingSpecificOperations();
3589 (result, carry) = Shift_C(R[m], SRType_LSL, shift_n, APSR.C);
3590 if d == 15 then // Can only occur for ARM encoding
3591 ALUWritePC(result); // setflags is always FALSE here
3595 APSR.N = result<31>;
3596 APSR.Z = IsZeroBit(result);
3601 return EmulateShiftImm(opcode, encoding, SRType_LSL);
3604 // Logical Shift Left (register) shifts a register value left by a variable
3605 // number of bits, shifting in zeros, and writes the result to the destination
3606 // register. The variable number of bits is read from the bottom byte of a
3607 // register. It can optionally update the condition flags based on the result.
3608 bool EmulateInstructionARM::EmulateLSLReg(const uint32_t opcode,
3609 const ARMEncoding encoding) {
3611 // ARM pseudo code...
3612 if ConditionPassed() then
3613 EncodingSpecificOperations();
3614 shift_n = UInt(R[m]<7:0>);
3615 (result, carry) = Shift_C(R[m], SRType_LSL, shift_n, APSR.C);
3618 APSR.N = result<31>;
3619 APSR.Z = IsZeroBit(result);
3624 return EmulateShiftReg(opcode, encoding, SRType_LSL);
3627 // Logical Shift Right (immediate) shifts a register value right by an
3628 // immediate number of bits, shifting in zeros, and writes the result to the
3629 // destination register. It can optionally update the condition flags based on
3631 bool EmulateInstructionARM::EmulateLSRImm(const uint32_t opcode,
3632 const ARMEncoding encoding) {
3634 // ARM pseudo code...
3635 if ConditionPassed() then
3636 EncodingSpecificOperations();
3637 (result, carry) = Shift_C(R[m], SRType_LSR, shift_n, APSR.C);
3638 if d == 15 then // Can only occur for ARM encoding
3639 ALUWritePC(result); // setflags is always FALSE here
3643 APSR.N = result<31>;
3644 APSR.Z = IsZeroBit(result);
3649 return EmulateShiftImm(opcode, encoding, SRType_LSR);
3652 // Logical Shift Right (register) shifts a register value right by a variable
3653 // number of bits, shifting in zeros, and writes the result to the destination
3654 // register. The variable number of bits is read from the bottom byte of a
3655 // register. It can optionally update the condition flags based on the result.
3656 bool EmulateInstructionARM::EmulateLSRReg(const uint32_t opcode,
3657 const ARMEncoding encoding) {
3659 // ARM pseudo code...
3660 if ConditionPassed() then
3661 EncodingSpecificOperations();
3662 shift_n = UInt(R[m]<7:0>);
3663 (result, carry) = Shift_C(R[m], SRType_LSR, shift_n, APSR.C);
3666 APSR.N = result<31>;
3667 APSR.Z = IsZeroBit(result);
3672 return EmulateShiftReg(opcode, encoding, SRType_LSR);
3675 // Rotate Right (immediate) provides the value of the contents of a register
3676 // rotated by a constant value. The bits that are rotated off the right end are
3677 // inserted into the vacated bit positions on the left. It can optionally
3678 // update the condition flags based on the result.
3679 bool EmulateInstructionARM::EmulateRORImm(const uint32_t opcode,
3680 const ARMEncoding encoding) {
3682 // ARM pseudo code...
3683 if ConditionPassed() then
3684 EncodingSpecificOperations();
3685 (result, carry) = Shift_C(R[m], SRType_ROR, shift_n, APSR.C);
3686 if d == 15 then // Can only occur for ARM encoding
3687 ALUWritePC(result); // setflags is always FALSE here
3691 APSR.N = result<31>;
3692 APSR.Z = IsZeroBit(result);
3697 return EmulateShiftImm(opcode, encoding, SRType_ROR);
3700 // Rotate Right (register) provides the value of the contents of a register
3701 // rotated by a variable number of bits. The bits that are rotated off the
3702 // right end are inserted into the vacated bit positions on the left. The
3703 // variable number of bits is read from the bottom byte of a register. It can
3704 // optionally update the condition flags based on the result.
3705 bool EmulateInstructionARM::EmulateRORReg(const uint32_t opcode,
3706 const ARMEncoding encoding) {
3708 // ARM pseudo code...
3709 if ConditionPassed() then
3710 EncodingSpecificOperations();
3711 shift_n = UInt(R[m]<7:0>);
3712 (result, carry) = Shift_C(R[m], SRType_ROR, shift_n, APSR.C);
3715 APSR.N = result<31>;
3716 APSR.Z = IsZeroBit(result);
3721 return EmulateShiftReg(opcode, encoding, SRType_ROR);
3724 // Rotate Right with Extend provides the value of the contents of a register
3725 // shifted right by one place, with the carry flag shifted into bit [31].
3727 // RRX can optionally update the condition flags based on the result.
3728 // In that case, bit [0] is shifted into the carry flag.
3729 bool EmulateInstructionARM::EmulateRRX(const uint32_t opcode,
3730 const ARMEncoding encoding) {
3732 // ARM pseudo code...
3733 if ConditionPassed() then
3734 EncodingSpecificOperations();
3735 (result, carry) = Shift_C(R[m], SRType_RRX, 1, APSR.C);
3736 if d == 15 then // Can only occur for ARM encoding
3737 ALUWritePC(result); // setflags is always FALSE here
3741 APSR.N = result<31>;
3742 APSR.Z = IsZeroBit(result);
3747 return EmulateShiftImm(opcode, encoding, SRType_RRX);
3750 bool EmulateInstructionARM::EmulateShiftImm(const uint32_t opcode,
3751 const ARMEncoding encoding,
3752 ARM_ShifterType shift_type) {
3753 // assert(shift_type == SRType_ASR
3754 // || shift_type == SRType_LSL
3755 // || shift_type == SRType_LSR
3756 // || shift_type == SRType_ROR
3757 // || shift_type == SRType_RRX);
3759 bool success = false;
3761 if (ConditionPassed(opcode)) {
3762 uint32_t Rd; // the destination register
3763 uint32_t Rm; // the first operand register
3764 uint32_t imm5; // encoding for the shift amount
3765 uint32_t carry; // the carry bit after the shift operation
3768 // Special case handling!
3769 // A8.6.139 ROR (immediate) -- Encoding T1
3770 ARMEncoding use_encoding = encoding;
3771 if (shift_type == SRType_ROR && use_encoding == eEncodingT1) {
3772 // Morph the T1 encoding from the ARM Architecture Manual into T2
3773 // encoding to have the same decoding of bit fields as the other Thumb2
3774 // shift operations.
3775 use_encoding = eEncodingT2;
3778 switch (use_encoding) {
3780 // Due to the above special case handling!
3781 if (shift_type == SRType_ROR)
3784 Rd = Bits32(opcode, 2, 0);
3785 Rm = Bits32(opcode, 5, 3);
3786 setflags = !InITBlock();
3787 imm5 = Bits32(opcode, 10, 6);
3791 // There's no imm form of RRX instructions.
3792 if (shift_type == SRType_RRX)
3795 Rd = Bits32(opcode, 11, 8);
3796 Rm = Bits32(opcode, 3, 0);
3797 setflags = BitIsSet(opcode, 20);
3798 imm5 = Bits32(opcode, 14, 12) << 2 | Bits32(opcode, 7, 6);
3799 if (BadReg(Rd) || BadReg(Rm))
3803 Rd = Bits32(opcode, 15, 12);
3804 Rm = Bits32(opcode, 3, 0);
3805 setflags = BitIsSet(opcode, 20);
3806 imm5 = Bits32(opcode, 11, 7);
3812 // A8.6.139 ROR (immediate)
3813 if (shift_type == SRType_ROR && imm5 == 0)
3814 shift_type = SRType_RRX;
3816 // Get the first operand.
3817 uint32_t value = ReadCoreReg(Rm, &success);
3821 // Decode the shift amount if not RRX.
3823 (shift_type == SRType_RRX ? 1 : DecodeImmShift(shift_type, imm5));
3825 uint32_t result = Shift_C(value, shift_type, amt, APSR_C, carry, &success);
3829 // The context specifies that an immediate is to be moved into Rd.
3830 EmulateInstruction::Context context;
3831 context.type = EmulateInstruction::eContextImmediate;
3832 context.SetNoArgs();
3834 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
3840 bool EmulateInstructionARM::EmulateShiftReg(const uint32_t opcode,
3841 const ARMEncoding encoding,
3842 ARM_ShifterType shift_type) {
3843 // assert(shift_type == SRType_ASR
3844 // || shift_type == SRType_LSL
3845 // || shift_type == SRType_LSR
3846 // || shift_type == SRType_ROR);
3848 bool success = false;
3850 if (ConditionPassed(opcode)) {
3851 uint32_t Rd; // the destination register
3852 uint32_t Rn; // the first operand register
3854 Rm; // the register whose bottom byte contains the amount to shift by
3855 uint32_t carry; // the carry bit after the shift operation
3859 Rd = Bits32(opcode, 2, 0);
3861 Rm = Bits32(opcode, 5, 3);
3862 setflags = !InITBlock();
3865 Rd = Bits32(opcode, 11, 8);
3866 Rn = Bits32(opcode, 19, 16);
3867 Rm = Bits32(opcode, 3, 0);
3868 setflags = BitIsSet(opcode, 20);
3869 if (BadReg(Rd) || BadReg(Rn) || BadReg(Rm))
3873 Rd = Bits32(opcode, 15, 12);
3874 Rn = Bits32(opcode, 3, 0);
3875 Rm = Bits32(opcode, 11, 8);
3876 setflags = BitIsSet(opcode, 20);
3877 if (Rd == 15 || Rn == 15 || Rm == 15)
3884 // Get the first operand.
3885 uint32_t value = ReadCoreReg(Rn, &success);
3888 // Get the Rm register content.
3889 uint32_t val = ReadCoreReg(Rm, &success);
3893 // Get the shift amount.
3894 uint32_t amt = Bits32(val, 7, 0);
3896 uint32_t result = Shift_C(value, shift_type, amt, APSR_C, carry, &success);
3900 // The context specifies that an immediate is to be moved into Rd.
3901 EmulateInstruction::Context context;
3902 context.type = EmulateInstruction::eContextImmediate;
3903 context.SetNoArgs();
3905 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
3911 // LDM loads multiple registers from consecutive memory locations, using an
3912 // address from a base register. Optionally the address just above the highest
3913 // of those locations can be written back to the base register.
3914 bool EmulateInstructionARM::EmulateLDM(const uint32_t opcode,
3915 const ARMEncoding encoding) {
3917 // ARM pseudo code...
3918 if ConditionPassed()
3919 EncodingSpecificOperations(); NullCheckIfThumbEE (n);
3923 if registers<i> == '1' then
3924 R[i] = MemA[address, 4]; address = address + 4;
3925 if registers<15> == '1' then
3926 LoadWritePC (MemA[address, 4]);
3928 if wback && registers<n> == '0' then R[n] = R[n] + 4 * BitCount (registers);
3929 if wback && registers<n> == '1' then R[n] = bits(32) UNKNOWN; // Only possible for encoding A1
3933 bool success = false;
3934 if (ConditionPassed(opcode)) {
3936 uint32_t registers = 0;
3938 const uint32_t addr_byte_size = GetAddressByteSize();
3941 // n = UInt(Rn); registers = '00000000':register_list; wback =
3942 // (registers<n> == '0');
3943 n = Bits32(opcode, 10, 8);
3944 registers = Bits32(opcode, 7, 0);
3945 registers = registers & 0x00ff; // Make sure the top 8 bits are zeros.
3946 wback = BitIsClear(registers, n);
3947 // if BitCount(registers) < 1 then UNPREDICTABLE;
3948 if (BitCount(registers) < 1)
3952 // if W == '1' && Rn == '1101' then SEE POP;
3953 // n = UInt(Rn); registers = P:M:'0':register_list; wback = (W == '1');
3954 n = Bits32(opcode, 19, 16);
3955 registers = Bits32(opcode, 15, 0);
3956 registers = registers & 0xdfff; // Make sure bit 13 is zero.
3957 wback = BitIsSet(opcode, 21);
3959 // if n == 15 || BitCount(registers) < 2 || (P == '1' && M == '1') then
3961 if ((n == 15) || (BitCount(registers) < 2) ||
3962 (BitIsSet(opcode, 14) && BitIsSet(opcode, 15)))
3965 // if registers<15> == '1' && InITBlock() && !LastInITBlock() then
3967 if (BitIsSet(registers, 15) && InITBlock() && !LastInITBlock())
3970 // if wback && registers<n> == '1' then UNPREDICTABLE;
3971 if (wback && BitIsSet(registers, n))
3976 n = Bits32(opcode, 19, 16);
3977 registers = Bits32(opcode, 15, 0);
3978 wback = BitIsSet(opcode, 21);
3979 if ((n == 15) || (BitCount(registers) < 1))
3987 const addr_t base_address =
3988 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
3992 EmulateInstruction::Context context;
3993 context.type = EmulateInstruction::eContextRegisterPlusOffset;
3994 RegisterInfo dwarf_reg;
3995 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n, dwarf_reg);
3996 context.SetRegisterPlusOffset(dwarf_reg, offset);
3998 for (int i = 0; i < 14; ++i) {
3999 if (BitIsSet(registers, i)) {
4000 context.type = EmulateInstruction::eContextRegisterPlusOffset;
4001 context.SetRegisterPlusOffset(dwarf_reg, offset);
4002 if (wback && (n == 13)) // Pop Instruction
4004 context.type = EmulateInstruction::eContextPopRegisterOffStack;
4005 context.SetAddress(base_address + offset);
4008 // R[i] = MemA [address, 4]; address = address + 4;
4009 uint32_t data = MemARead(context, base_address + offset, addr_byte_size,
4014 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + i,
4018 offset += addr_byte_size;
4022 if (BitIsSet(registers, 15)) {
4023 // LoadWritePC (MemA [address, 4]);
4024 context.type = EmulateInstruction::eContextRegisterPlusOffset;
4025 context.SetRegisterPlusOffset(dwarf_reg, offset);
4027 MemARead(context, base_address + offset, addr_byte_size, 0, &success);
4030 // In ARMv5T and above, this is an interworking branch.
4031 if (!LoadWritePC(context, data))
4035 if (wback && BitIsClear(registers, n)) {
4036 // R[n] = R[n] + 4 * BitCount (registers)
4037 int32_t offset = addr_byte_size * BitCount(registers);
4038 context.type = EmulateInstruction::eContextAdjustBaseRegister;
4039 context.SetRegisterPlusOffset(dwarf_reg, offset);
4041 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n,
4042 base_address + offset))
4045 if (wback && BitIsSet(registers, n))
4046 // R[n] bits(32) UNKNOWN;
4047 return WriteBits32Unknown(n);
4052 // LDMDA loads multiple registers from consecutive memory locations using an
4053 // address from a base register.
4054 // The consecutive memory locations end at this address and the address just
4055 // below the lowest of those locations can optionally be written back to the
4057 bool EmulateInstructionARM::EmulateLDMDA(const uint32_t opcode,
4058 const ARMEncoding encoding) {
4060 // ARM pseudo code...
4061 if ConditionPassed() then
4062 EncodingSpecificOperations();
4063 address = R[n] - 4*BitCount(registers) + 4;
4066 if registers<i> == '1' then
4067 R[i] = MemA[address,4]; address = address + 4;
4069 if registers<15> == '1' then
4070 LoadWritePC(MemA[address,4]);
4072 if wback && registers<n> == '0' then R[n] = R[n] - 4*BitCount(registers);
4073 if wback && registers<n> == '1' then R[n] = bits(32) UNKNOWN;
4076 bool success = false;
4078 if (ConditionPassed(opcode)) {
4080 uint32_t registers = 0;
4082 const uint32_t addr_byte_size = GetAddressByteSize();
4084 // EncodingSpecificOperations();
4087 // n = UInt(Rn); registers = register_list; wback = (W == '1');
4088 n = Bits32(opcode, 19, 16);
4089 registers = Bits32(opcode, 15, 0);
4090 wback = BitIsSet(opcode, 21);
4092 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
4093 if ((n == 15) || (BitCount(registers) < 1))
4101 // address = R[n] - 4*BitCount(registers) + 4;
4104 addr_t Rn = ReadCoreReg(n, &success);
4110 Rn - (addr_byte_size * BitCount(registers)) + addr_byte_size;
4112 EmulateInstruction::Context context;
4113 context.type = EmulateInstruction::eContextRegisterPlusOffset;
4114 RegisterInfo dwarf_reg;
4115 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n, dwarf_reg);
4116 context.SetRegisterPlusOffset(dwarf_reg, offset);
4119 for (int i = 0; i < 14; ++i) {
4120 // if registers<i> == '1' then
4121 if (BitIsSet(registers, i)) {
4122 // R[i] = MemA[address,4]; address = address + 4;
4123 context.SetRegisterPlusOffset(dwarf_reg, Rn - (address + offset));
4125 MemARead(context, address + offset, addr_byte_size, 0, &success);
4128 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + i,
4131 offset += addr_byte_size;
4135 // if registers<15> == '1' then
4136 // LoadWritePC(MemA[address,4]);
4137 if (BitIsSet(registers, 15)) {
4138 context.SetRegisterPlusOffset(dwarf_reg, offset);
4140 MemARead(context, address + offset, addr_byte_size, 0, &success);
4143 // In ARMv5T and above, this is an interworking branch.
4144 if (!LoadWritePC(context, data))
4148 // if wback && registers<n> == '0' then R[n] = R[n] - 4*BitCount(registers);
4149 if (wback && BitIsClear(registers, n)) {
4153 offset = (addr_byte_size * BitCount(registers)) * -1;
4154 context.type = EmulateInstruction::eContextAdjustBaseRegister;
4155 context.SetImmediateSigned(offset);
4156 addr_t addr = Rn + offset;
4157 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n,
4162 // if wback && registers<n> == '1' then R[n] = bits(32) UNKNOWN;
4163 if (wback && BitIsSet(registers, n))
4164 return WriteBits32Unknown(n);
4169 // LDMDB loads multiple registers from consecutive memory locations using an
4170 // address from a base register. The
4171 // consecutive memory locations end just below this address, and the address of
4172 // the lowest of those locations can be optionally written back to the base
4174 bool EmulateInstructionARM::EmulateLDMDB(const uint32_t opcode,
4175 const ARMEncoding encoding) {
4177 // ARM pseudo code...
4178 if ConditionPassed() then
4179 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
4180 address = R[n] - 4*BitCount(registers);
4183 if registers<i> == '1' then
4184 R[i] = MemA[address,4]; address = address + 4;
4185 if registers<15> == '1' then
4186 LoadWritePC(MemA[address,4]);
4188 if wback && registers<n> == '0' then R[n] = R[n] - 4*BitCount(registers);
4189 if wback && registers<n> == '1' then R[n] = bits(32) UNKNOWN; // Only possible for encoding A1
4192 bool success = false;
4194 if (ConditionPassed(opcode)) {
4196 uint32_t registers = 0;
4198 const uint32_t addr_byte_size = GetAddressByteSize();
4201 // n = UInt(Rn); registers = P:M:'0':register_list; wback = (W == '1');
4202 n = Bits32(opcode, 19, 16);
4203 registers = Bits32(opcode, 15, 0);
4204 registers = registers & 0xdfff; // Make sure bit 13 is a zero.
4205 wback = BitIsSet(opcode, 21);
4207 // if n == 15 || BitCount(registers) < 2 || (P == '1' && M == '1') then
4209 if ((n == 15) || (BitCount(registers) < 2) ||
4210 (BitIsSet(opcode, 14) && BitIsSet(opcode, 15)))
4213 // if registers<15> == '1' && InITBlock() && !LastInITBlock() then
4215 if (BitIsSet(registers, 15) && InITBlock() && !LastInITBlock())
4218 // if wback && registers<n> == '1' then UNPREDICTABLE;
4219 if (wback && BitIsSet(registers, n))
4225 // n = UInt(Rn); registers = register_list; wback = (W == '1');
4226 n = Bits32(opcode, 19, 16);
4227 registers = Bits32(opcode, 15, 0);
4228 wback = BitIsSet(opcode, 21);
4230 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
4231 if ((n == 15) || (BitCount(registers) < 1))
4240 // address = R[n] - 4*BitCount(registers);
4244 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
4249 addr_t address = Rn - (addr_byte_size * BitCount(registers));
4250 EmulateInstruction::Context context;
4251 context.type = EmulateInstruction::eContextRegisterPlusOffset;
4252 RegisterInfo dwarf_reg;
4253 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n, dwarf_reg);
4254 context.SetRegisterPlusOffset(dwarf_reg, Rn - address);
4256 for (int i = 0; i < 14; ++i) {
4257 if (BitIsSet(registers, i)) {
4258 // R[i] = MemA[address,4]; address = address + 4;
4259 context.SetRegisterPlusOffset(dwarf_reg, Rn - (address + offset));
4261 MemARead(context, address + offset, addr_byte_size, 0, &success);
4265 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + i,
4269 offset += addr_byte_size;
4273 // if registers<15> == '1' then
4274 // LoadWritePC(MemA[address,4]);
4275 if (BitIsSet(registers, 15)) {
4276 context.SetRegisterPlusOffset(dwarf_reg, offset);
4278 MemARead(context, address + offset, addr_byte_size, 0, &success);
4281 // In ARMv5T and above, this is an interworking branch.
4282 if (!LoadWritePC(context, data))
4286 // if wback && registers<n> == '0' then R[n] = R[n] - 4*BitCount(registers);
4287 if (wback && BitIsClear(registers, n)) {
4291 offset = (addr_byte_size * BitCount(registers)) * -1;
4292 context.type = EmulateInstruction::eContextAdjustBaseRegister;
4293 context.SetImmediateSigned(offset);
4294 addr_t addr = Rn + offset;
4295 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n,
4300 // if wback && registers<n> == '1' then R[n] = bits(32) UNKNOWN; // Only
4301 // possible for encoding A1
4302 if (wback && BitIsSet(registers, n))
4303 return WriteBits32Unknown(n);
4308 // LDMIB loads multiple registers from consecutive memory locations using an
4309 // address from a base register. The
4310 // consecutive memory locations start just above this address, and thea ddress
4311 // of the last of those locations can optinoally be written back to the base
4313 bool EmulateInstructionARM::EmulateLDMIB(const uint32_t opcode,
4314 const ARMEncoding encoding) {
4316 if ConditionPassed() then
4317 EncodingSpecificOperations();
4321 if registers<i> == '1' then
4322 R[i] = MemA[address,4]; address = address + 4;
4323 if registers<15> == '1' then
4324 LoadWritePC(MemA[address,4]);
4326 if wback && registers<n> == '0' then R[n] = R[n] + 4*BitCount(registers);
4327 if wback && registers<n> == '1' then R[n] = bits(32) UNKNOWN;
4330 bool success = false;
4332 if (ConditionPassed(opcode)) {
4334 uint32_t registers = 0;
4336 const uint32_t addr_byte_size = GetAddressByteSize();
4339 // n = UInt(Rn); registers = register_list; wback = (W == '1');
4340 n = Bits32(opcode, 19, 16);
4341 registers = Bits32(opcode, 15, 0);
4342 wback = BitIsSet(opcode, 21);
4344 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
4345 if ((n == 15) || (BitCount(registers) < 1))
4352 // address = R[n] + 4;
4356 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
4361 addr_t address = Rn + addr_byte_size;
4363 EmulateInstruction::Context context;
4364 context.type = EmulateInstruction::eContextRegisterPlusOffset;
4365 RegisterInfo dwarf_reg;
4366 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n, dwarf_reg);
4367 context.SetRegisterPlusOffset(dwarf_reg, offset);
4369 for (int i = 0; i < 14; ++i) {
4370 if (BitIsSet(registers, i)) {
4371 // R[i] = MemA[address,4]; address = address + 4;
4373 context.SetRegisterPlusOffset(dwarf_reg, offset + addr_byte_size);
4375 MemARead(context, address + offset, addr_byte_size, 0, &success);
4379 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + i,
4383 offset += addr_byte_size;
4387 // if registers<15> == '1' then
4388 // LoadWritePC(MemA[address,4]);
4389 if (BitIsSet(registers, 15)) {
4390 context.SetRegisterPlusOffset(dwarf_reg, offset);
4392 MemARead(context, address + offset, addr_byte_size, 0, &success);
4395 // In ARMv5T and above, this is an interworking branch.
4396 if (!LoadWritePC(context, data))
4400 // if wback && registers<n> == '0' then R[n] = R[n] + 4*BitCount(registers);
4401 if (wback && BitIsClear(registers, n)) {
4405 offset = addr_byte_size * BitCount(registers);
4406 context.type = EmulateInstruction::eContextAdjustBaseRegister;
4407 context.SetImmediateSigned(offset);
4408 addr_t addr = Rn + offset;
4409 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n,
4414 // if wback && registers<n> == '1' then R[n] = bits(32) UNKNOWN; // Only
4415 // possible for encoding A1
4416 if (wback && BitIsSet(registers, n))
4417 return WriteBits32Unknown(n);
4422 // Load Register (immediate) calculates an address from a base register value
4423 // and an immediate offset, loads a word from memory, and writes to a register.
4424 // LDR (immediate, Thumb)
4425 bool EmulateInstructionARM::EmulateLDRRtRnImm(const uint32_t opcode,
4426 const ARMEncoding encoding) {
4428 // ARM pseudo code...
4429 if (ConditionPassed())
4431 EncodingSpecificOperations(); NullCheckIfThumbEE(15);
4432 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
4433 address = if index then offset_addr else R[n];
4434 data = MemU[address,4];
4435 if wback then R[n] = offset_addr;
4437 if address<1:0> == '00' then LoadWritePC(data); else UNPREDICTABLE;
4438 elsif UnalignedSupport() || address<1:0> = '00' then
4440 else R[t] = bits(32) UNKNOWN; // Can only apply before ARMv7
4444 bool success = false;
4446 if (ConditionPassed(opcode)) {
4447 uint32_t Rt; // the destination register
4448 uint32_t Rn; // the base register
4449 uint32_t imm32; // the immediate offset used to form the address
4450 addr_t offset_addr; // the offset address
4451 addr_t address; // the calculated address
4452 uint32_t data; // the literal data value from memory load
4453 bool add, index, wback;
4456 Rt = Bits32(opcode, 2, 0);
4457 Rn = Bits32(opcode, 5, 3);
4458 imm32 = Bits32(opcode, 10, 6) << 2; // imm32 = ZeroExtend(imm5:'00', 32);
4459 // index = TRUE; add = TRUE; wback = FALSE
4467 // t = UInt(Rt); n = 13; imm32 = ZeroExtend(imm8:'00', 32);
4468 Rt = Bits32(opcode, 10, 8);
4470 imm32 = Bits32(opcode, 7, 0) << 2;
4472 // index = TRUE; add = TRUE; wback = FALSE;
4480 // if Rn == '1111' then SEE LDR (literal);
4481 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
4482 Rt = Bits32(opcode, 15, 12);
4483 Rn = Bits32(opcode, 19, 16);
4484 imm32 = Bits32(opcode, 11, 0);
4486 // index = TRUE; add = TRUE; wback = FALSE;
4491 // if t == 15 && InITBlock() && !LastInITBlock() then UNPREDICTABLE;
4492 if ((Rt == 15) && InITBlock() && !LastInITBlock())
4498 // if Rn == '1111' then SEE LDR (literal);
4499 // if P == '1' && U == '1' && W == '0' then SEE LDRT;
4500 // if Rn == '1101' && P == '0' && U == '1' && W == '1' && imm8 ==
4501 // '00000100' then SEE POP;
4502 // if P == '0' && W == '0' then UNDEFINED;
4503 if (BitIsClear(opcode, 10) && BitIsClear(opcode, 8))
4506 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32);
4507 Rt = Bits32(opcode, 15, 12);
4508 Rn = Bits32(opcode, 19, 16);
4509 imm32 = Bits32(opcode, 7, 0);
4511 // index = (P == '1'); add = (U == '1'); wback = (W == '1');
4512 index = BitIsSet(opcode, 10);
4513 add = BitIsSet(opcode, 9);
4514 wback = BitIsSet(opcode, 8);
4516 // if (wback && n == t) || (t == 15 && InITBlock() && !LastInITBlock())
4517 // then UNPREDICTABLE;
4518 if ((wback && (Rn == Rt)) ||
4519 ((Rt == 15) && InITBlock() && !LastInITBlock()))
4527 uint32_t base = ReadCoreReg(Rn, &success);
4531 offset_addr = base + imm32;
4533 offset_addr = base - imm32;
4535 address = (index ? offset_addr : base);
4537 RegisterInfo base_reg;
4538 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + Rn, base_reg);
4540 EmulateInstruction::Context ctx;
4542 ctx.type = eContextAdjustStackPointer;
4543 ctx.SetImmediateSigned((int32_t)(offset_addr - base));
4544 } else if (Rn == GetFramePointerRegisterNumber()) {
4545 ctx.type = eContextSetFramePointer;
4546 ctx.SetRegisterPlusOffset(base_reg, (int32_t)(offset_addr - base));
4548 ctx.type = EmulateInstruction::eContextAdjustBaseRegister;
4549 ctx.SetRegisterPlusOffset(base_reg, (int32_t)(offset_addr - base));
4552 if (!WriteRegisterUnsigned(ctx, eRegisterKindDWARF, dwarf_r0 + Rn,
4557 // Prepare to write to the Rt register.
4558 EmulateInstruction::Context context;
4559 context.type = EmulateInstruction::eContextRegisterLoad;
4560 context.SetRegisterPlusOffset(base_reg, (int32_t)(offset_addr - base));
4562 // Read memory from the address.
4563 data = MemURead(context, address, 4, 0, &success);
4568 if (Bits32(address, 1, 0) == 0) {
4569 if (!LoadWritePC(context, data))
4573 } else if (UnalignedSupport() || Bits32(address, 1, 0) == 0) {
4574 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + Rt,
4578 WriteBits32Unknown(Rt);
4583 // STM (Store Multiple Increment After) stores multiple registers to consecutive
4584 // memory locations using an address
4585 // from a base register. The consecutive memory locations start at this
4586 // address, and the address just above the last of those locations can
4587 // optionally be written back to the base register.
4588 bool EmulateInstructionARM::EmulateSTM(const uint32_t opcode,
4589 const ARMEncoding encoding) {
4591 if ConditionPassed() then
4592 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
4596 if registers<i> == '1' then
4597 if i == n && wback && i != LowestSetBit(registers) then
4598 MemA[address,4] = bits(32) UNKNOWN; // Only possible for encodings T1 and A1
4600 MemA[address,4] = R[i];
4601 address = address + 4;
4603 if registers<15> == '1' then // Only possible for encoding A1
4604 MemA[address,4] = PCStoreValue();
4605 if wback then R[n] = R[n] + 4*BitCount(registers);
4608 bool success = false;
4610 if (ConditionPassed(opcode)) {
4612 uint32_t registers = 0;
4614 const uint32_t addr_byte_size = GetAddressByteSize();
4616 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
4619 // n = UInt(Rn); registers = '00000000':register_list; wback = TRUE;
4620 n = Bits32(opcode, 10, 8);
4621 registers = Bits32(opcode, 7, 0);
4622 registers = registers & 0x00ff; // Make sure the top 8 bits are zeros.
4625 // if BitCount(registers) < 1 then UNPREDICTABLE;
4626 if (BitCount(registers) < 1)
4632 // n = UInt(Rn); registers = '0':M:'0':register_list; wback = (W == '1');
4633 n = Bits32(opcode, 19, 16);
4634 registers = Bits32(opcode, 15, 0);
4635 registers = registers & 0x5fff; // Make sure bits 15 & 13 are zeros.
4636 wback = BitIsSet(opcode, 21);
4638 // if n == 15 || BitCount(registers) < 2 then UNPREDICTABLE;
4639 if ((n == 15) || (BitCount(registers) < 2))
4642 // if wback && registers<n> == '1' then UNPREDICTABLE;
4643 if (wback && BitIsSet(registers, n))
4649 // n = UInt(Rn); registers = register_list; wback = (W == '1');
4650 n = Bits32(opcode, 19, 16);
4651 registers = Bits32(opcode, 15, 0);
4652 wback = BitIsSet(opcode, 21);
4654 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
4655 if ((n == 15) || (BitCount(registers) < 1))
4666 const addr_t address =
4667 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
4671 EmulateInstruction::Context context;
4672 context.type = EmulateInstruction::eContextRegisterStore;
4673 RegisterInfo base_reg;
4674 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n, base_reg);
4677 uint32_t lowest_set_bit = 14;
4678 for (uint32_t i = 0; i < 14; ++i) {
4679 // if registers<i> == '1' then
4680 if (BitIsSet(registers, i)) {
4681 if (i < lowest_set_bit)
4683 // if i == n && wback && i != LowestSetBit(registers) then
4684 if ((i == n) && wback && (i != lowest_set_bit))
4685 // MemA[address,4] = bits(32) UNKNOWN; // Only possible for encodings
4687 WriteBits32UnknownToMemory(address + offset);
4689 // MemA[address,4] = R[i];
4690 uint32_t data = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + i,
4695 RegisterInfo data_reg;
4696 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + i, data_reg);
4697 context.SetRegisterToRegisterPlusOffset(data_reg, base_reg, offset);
4698 if (!MemAWrite(context, address + offset, data, addr_byte_size))
4702 // address = address + 4;
4703 offset += addr_byte_size;
4707 // if registers<15> == '1' then // Only possible for encoding A1
4708 // MemA[address,4] = PCStoreValue();
4709 if (BitIsSet(registers, 15)) {
4710 RegisterInfo pc_reg;
4711 GetRegisterInfo(eRegisterKindDWARF, dwarf_pc, pc_reg);
4712 context.SetRegisterPlusOffset(pc_reg, 8);
4713 const uint32_t pc = ReadCoreReg(PC_REG, &success);
4717 if (!MemAWrite(context, address + offset, pc, addr_byte_size))
4721 // if wback then R[n] = R[n] + 4*BitCount(registers);
4723 offset = addr_byte_size * BitCount(registers);
4724 context.type = EmulateInstruction::eContextAdjustBaseRegister;
4725 context.SetImmediateSigned(offset);
4726 addr_t data = address + offset;
4727 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n,
4735 // STMDA (Store Multiple Decrement After) stores multiple registers to
4736 // consecutive memory locations using an address from a base register. The
4737 // consecutive memory locations end at this address, and the address just below
4738 // the lowest of those locations can optionally be written back to the base
4740 bool EmulateInstructionARM::EmulateSTMDA(const uint32_t opcode,
4741 const ARMEncoding encoding) {
4743 if ConditionPassed() then
4744 EncodingSpecificOperations();
4745 address = R[n] - 4*BitCount(registers) + 4;
4748 if registers<i> == '1' then
4749 if i == n && wback && i != LowestSetBit(registers) then
4750 MemA[address,4] = bits(32) UNKNOWN;
4752 MemA[address,4] = R[i];
4753 address = address + 4;
4755 if registers<15> == '1' then
4756 MemA[address,4] = PCStoreValue();
4758 if wback then R[n] = R[n] - 4*BitCount(registers);
4761 bool success = false;
4763 if (ConditionPassed(opcode)) {
4765 uint32_t registers = 0;
4767 const uint32_t addr_byte_size = GetAddressByteSize();
4769 // EncodingSpecificOperations();
4772 // n = UInt(Rn); registers = register_list; wback = (W == '1');
4773 n = Bits32(opcode, 19, 16);
4774 registers = Bits32(opcode, 15, 0);
4775 wback = BitIsSet(opcode, 21);
4777 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
4778 if ((n == 15) || (BitCount(registers) < 1))
4785 // address = R[n] - 4*BitCount(registers) + 4;
4787 addr_t Rn = ReadCoreReg(n, &success);
4791 addr_t address = Rn - (addr_byte_size * BitCount(registers)) + 4;
4793 EmulateInstruction::Context context;
4794 context.type = EmulateInstruction::eContextRegisterStore;
4795 RegisterInfo base_reg;
4796 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n, base_reg);
4799 uint32_t lowest_bit_set = 14;
4800 for (uint32_t i = 0; i < 14; ++i) {
4801 // if registers<i> == '1' then
4802 if (BitIsSet(registers, i)) {
4803 if (i < lowest_bit_set)
4805 // if i == n && wback && i != LowestSetBit(registers) then
4806 if ((i == n) && wback && (i != lowest_bit_set))
4807 // MemA[address,4] = bits(32) UNKNOWN;
4808 WriteBits32UnknownToMemory(address + offset);
4810 // MemA[address,4] = R[i];
4811 uint32_t data = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + i,
4816 RegisterInfo data_reg;
4817 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + i, data_reg);
4818 context.SetRegisterToRegisterPlusOffset(data_reg, base_reg,
4819 Rn - (address + offset));
4820 if (!MemAWrite(context, address + offset, data, addr_byte_size))
4824 // address = address + 4;
4825 offset += addr_byte_size;
4829 // if registers<15> == '1' then
4830 // MemA[address,4] = PCStoreValue();
4831 if (BitIsSet(registers, 15)) {
4832 RegisterInfo pc_reg;
4833 GetRegisterInfo(eRegisterKindDWARF, dwarf_pc, pc_reg);
4834 context.SetRegisterPlusOffset(pc_reg, 8);
4835 const uint32_t pc = ReadCoreReg(PC_REG, &success);
4839 if (!MemAWrite(context, address + offset, pc, addr_byte_size))
4843 // if wback then R[n] = R[n] - 4*BitCount(registers);
4845 offset = (addr_byte_size * BitCount(registers)) * -1;
4846 context.type = EmulateInstruction::eContextAdjustBaseRegister;
4847 context.SetImmediateSigned(offset);
4848 addr_t data = Rn + offset;
4849 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n,
4857 // STMDB (Store Multiple Decrement Before) stores multiple registers to
4858 // consecutive memory locations using an address from a base register. The
4859 // consecutive memory locations end just below this address, and the address of
4860 // the first of those locations can optionally be written back to the base
4862 bool EmulateInstructionARM::EmulateSTMDB(const uint32_t opcode,
4863 const ARMEncoding encoding) {
4865 if ConditionPassed() then
4866 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
4867 address = R[n] - 4*BitCount(registers);
4870 if registers<i> == '1' then
4871 if i == n && wback && i != LowestSetBit(registers) then
4872 MemA[address,4] = bits(32) UNKNOWN; // Only possible for encoding A1
4874 MemA[address,4] = R[i];
4875 address = address + 4;
4877 if registers<15> == '1' then // Only possible for encoding A1
4878 MemA[address,4] = PCStoreValue();
4880 if wback then R[n] = R[n] - 4*BitCount(registers);
4883 bool success = false;
4885 if (ConditionPassed(opcode)) {
4887 uint32_t registers = 0;
4889 const uint32_t addr_byte_size = GetAddressByteSize();
4891 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
4894 // if W == '1' && Rn == '1101' then SEE PUSH;
4895 if ((BitIsSet(opcode, 21)) && (Bits32(opcode, 19, 16) == 13)) {
4898 // n = UInt(Rn); registers = '0':M:'0':register_list; wback = (W == '1');
4899 n = Bits32(opcode, 19, 16);
4900 registers = Bits32(opcode, 15, 0);
4901 registers = registers & 0x5fff; // Make sure bits 15 & 13 are zeros.
4902 wback = BitIsSet(opcode, 21);
4903 // if n == 15 || BitCount(registers) < 2 then UNPREDICTABLE;
4904 if ((n == 15) || BitCount(registers) < 2)
4906 // if wback && registers<n> == '1' then UNPREDICTABLE;
4907 if (wback && BitIsSet(registers, n))
4912 // if W == '1' && Rn == '1101' && BitCount(register_list) >= 2 then SEE
4914 if (BitIsSet(opcode, 21) && (Bits32(opcode, 19, 16) == 13) &&
4915 BitCount(Bits32(opcode, 15, 0)) >= 2) {
4918 // n = UInt(Rn); registers = register_list; wback = (W == '1');
4919 n = Bits32(opcode, 19, 16);
4920 registers = Bits32(opcode, 15, 0);
4921 wback = BitIsSet(opcode, 21);
4922 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
4923 if ((n == 15) || BitCount(registers) < 1)
4931 // address = R[n] - 4*BitCount(registers);
4935 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
4939 addr_t address = Rn - (addr_byte_size * BitCount(registers));
4941 EmulateInstruction::Context context;
4942 context.type = EmulateInstruction::eContextRegisterStore;
4943 RegisterInfo base_reg;
4944 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n, base_reg);
4947 uint32_t lowest_set_bit = 14;
4948 for (uint32_t i = 0; i < 14; ++i) {
4949 // if registers<i> == '1' then
4950 if (BitIsSet(registers, i)) {
4951 if (i < lowest_set_bit)
4953 // if i == n && wback && i != LowestSetBit(registers) then
4954 if ((i == n) && wback && (i != lowest_set_bit))
4955 // MemA[address,4] = bits(32) UNKNOWN; // Only possible for encoding
4957 WriteBits32UnknownToMemory(address + offset);
4959 // MemA[address,4] = R[i];
4960 uint32_t data = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + i,
4965 RegisterInfo data_reg;
4966 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + i, data_reg);
4967 context.SetRegisterToRegisterPlusOffset(data_reg, base_reg,
4968 Rn - (address + offset));
4969 if (!MemAWrite(context, address + offset, data, addr_byte_size))
4973 // address = address + 4;
4974 offset += addr_byte_size;
4978 // if registers<15> == '1' then // Only possible for encoding A1
4979 // MemA[address,4] = PCStoreValue();
4980 if (BitIsSet(registers, 15)) {
4981 RegisterInfo pc_reg;
4982 GetRegisterInfo(eRegisterKindDWARF, dwarf_pc, pc_reg);
4983 context.SetRegisterPlusOffset(pc_reg, 8);
4984 const uint32_t pc = ReadCoreReg(PC_REG, &success);
4988 if (!MemAWrite(context, address + offset, pc, addr_byte_size))
4992 // if wback then R[n] = R[n] - 4*BitCount(registers);
4994 offset = (addr_byte_size * BitCount(registers)) * -1;
4995 context.type = EmulateInstruction::eContextAdjustBaseRegister;
4996 context.SetImmediateSigned(offset);
4997 addr_t data = Rn + offset;
4998 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n,
5006 // STMIB (Store Multiple Increment Before) stores multiple registers to
5007 // consecutive memory locations using an address from a base register. The
5008 // consecutive memory locations start just above this address, and the address
5009 // of the last of those locations can optionally be written back to the base
5011 bool EmulateInstructionARM::EmulateSTMIB(const uint32_t opcode,
5012 const ARMEncoding encoding) {
5014 if ConditionPassed() then
5015 EncodingSpecificOperations();
5019 if registers<i> == '1' then
5020 if i == n && wback && i != LowestSetBit(registers) then
5021 MemA[address,4] = bits(32) UNKNOWN;
5023 MemA[address,4] = R[i];
5024 address = address + 4;
5026 if registers<15> == '1' then
5027 MemA[address,4] = PCStoreValue();
5029 if wback then R[n] = R[n] + 4*BitCount(registers);
5032 bool success = false;
5034 if (ConditionPassed(opcode)) {
5036 uint32_t registers = 0;
5038 const uint32_t addr_byte_size = GetAddressByteSize();
5040 // EncodingSpecificOperations();
5043 // n = UInt(Rn); registers = register_list; wback = (W == '1');
5044 n = Bits32(opcode, 19, 16);
5045 registers = Bits32(opcode, 15, 0);
5046 wback = BitIsSet(opcode, 21);
5048 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
5049 if ((n == 15) && (BitCount(registers) < 1))
5055 // address = R[n] + 4;
5058 addr_t Rn = ReadCoreReg(n, &success);
5062 addr_t address = Rn + addr_byte_size;
5064 EmulateInstruction::Context context;
5065 context.type = EmulateInstruction::eContextRegisterStore;
5066 RegisterInfo base_reg;
5067 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n, base_reg);
5069 uint32_t lowest_set_bit = 14;
5071 for (uint32_t i = 0; i < 14; ++i) {
5072 // if registers<i> == '1' then
5073 if (BitIsSet(registers, i)) {
5074 if (i < lowest_set_bit)
5076 // if i == n && wback && i != LowestSetBit(registers) then
5077 if ((i == n) && wback && (i != lowest_set_bit))
5078 // MemA[address,4] = bits(32) UNKNOWN;
5079 WriteBits32UnknownToMemory(address + offset);
5082 // MemA[address,4] = R[i];
5083 uint32_t data = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + i,
5088 RegisterInfo data_reg;
5089 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + i, data_reg);
5090 context.SetRegisterToRegisterPlusOffset(data_reg, base_reg,
5091 offset + addr_byte_size);
5092 if (!MemAWrite(context, address + offset, data, addr_byte_size))
5096 // address = address + 4;
5097 offset += addr_byte_size;
5101 // if registers<15> == '1' then
5102 // MemA[address,4] = PCStoreValue();
5103 if (BitIsSet(registers, 15)) {
5104 RegisterInfo pc_reg;
5105 GetRegisterInfo(eRegisterKindDWARF, dwarf_pc, pc_reg);
5106 context.SetRegisterPlusOffset(pc_reg, 8);
5107 const uint32_t pc = ReadCoreReg(PC_REG, &success);
5111 if (!MemAWrite(context, address + offset, pc, addr_byte_size))
5115 // if wback then R[n] = R[n] + 4*BitCount(registers);
5117 offset = addr_byte_size * BitCount(registers);
5118 context.type = EmulateInstruction::eContextAdjustBaseRegister;
5119 context.SetImmediateSigned(offset);
5120 addr_t data = Rn + offset;
5121 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n,
5129 // STR (store immediate) calculates an address from a base register value and an
5130 // immediate offset, and stores a word
5131 // from a register to memory. It can use offset, post-indexed, or pre-indexed
5133 bool EmulateInstructionARM::EmulateSTRThumb(const uint32_t opcode,
5134 const ARMEncoding encoding) {
5136 if ConditionPassed() then
5137 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
5138 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
5139 address = if index then offset_addr else R[n];
5140 if UnalignedSupport() || address<1:0> == '00' then
5141 MemU[address,4] = R[t];
5142 else // Can only occur before ARMv7
5143 MemU[address,4] = bits(32) UNKNOWN;
5144 if wback then R[n] = offset_addr;
5147 bool success = false;
5149 if (ConditionPassed(opcode)) {
5150 const uint32_t addr_byte_size = GetAddressByteSize();
5158 // EncodingSpecificOperations (); NullCheckIfThumbEE(n);
5161 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm5:'00', 32);
5162 t = Bits32(opcode, 2, 0);
5163 n = Bits32(opcode, 5, 3);
5164 imm32 = Bits32(opcode, 10, 6) << 2;
5166 // index = TRUE; add = TRUE; wback = FALSE;
5173 // t = UInt(Rt); n = 13; imm32 = ZeroExtend(imm8:'00', 32);
5174 t = Bits32(opcode, 10, 8);
5176 imm32 = Bits32(opcode, 7, 0) << 2;
5178 // index = TRUE; add = TRUE; wback = FALSE;
5185 // if Rn == '1111' then UNDEFINED;
5186 if (Bits32(opcode, 19, 16) == 15)
5189 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
5190 t = Bits32(opcode, 15, 12);
5191 n = Bits32(opcode, 19, 16);
5192 imm32 = Bits32(opcode, 11, 0);
5194 // index = TRUE; add = TRUE; wback = FALSE;
5199 // if t == 15 then UNPREDICTABLE;
5205 // if P == '1' && U == '1' && W == '0' then SEE STRT;
5206 // if Rn == '1101' && P == '1' && U == '0' && W == '1' && imm8 ==
5207 // '00000100' then SEE PUSH;
5208 // if Rn == '1111' || (P == '0' && W == '0') then UNDEFINED;
5209 if ((Bits32(opcode, 19, 16) == 15) ||
5210 (BitIsClear(opcode, 10) && BitIsClear(opcode, 8)))
5213 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32);
5214 t = Bits32(opcode, 15, 12);
5215 n = Bits32(opcode, 19, 16);
5216 imm32 = Bits32(opcode, 7, 0);
5218 // index = (P == '1'); add = (U == '1'); wback = (W == '1');
5219 index = BitIsSet(opcode, 10);
5220 add = BitIsSet(opcode, 9);
5221 wback = BitIsSet(opcode, 8);
5223 // if t == 15 || (wback && n == t) then UNPREDICTABLE;
5224 if ((t == 15) || (wback && (n == t)))
5235 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
5236 uint32_t base_address = ReadCoreReg(n, &success);
5241 offset_addr = base_address + imm32;
5243 offset_addr = base_address - imm32;
5245 // address = if index then offset_addr else R[n];
5247 address = offset_addr;
5249 address = base_address;
5251 EmulateInstruction::Context context;
5253 context.type = eContextPushRegisterOnStack;
5255 context.type = eContextRegisterStore;
5257 RegisterInfo base_reg;
5258 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n, base_reg);
5260 // if UnalignedSupport() || address<1:0> == '00' then
5261 if (UnalignedSupport() ||
5262 (BitIsClear(address, 1) && BitIsClear(address, 0))) {
5263 // MemU[address,4] = R[t];
5265 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + t, 0, &success);
5269 RegisterInfo data_reg;
5270 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + t, data_reg);
5271 int32_t offset = address - base_address;
5272 context.SetRegisterToRegisterPlusOffset(data_reg, base_reg, offset);
5273 if (!MemUWrite(context, address, data, addr_byte_size))
5276 // MemU[address,4] = bits(32) UNKNOWN;
5277 WriteBits32UnknownToMemory(address);
5280 // if wback then R[n] = offset_addr;
5283 context.type = eContextAdjustStackPointer;
5285 context.type = eContextAdjustBaseRegister;
5286 context.SetAddress(offset_addr);
5288 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n,
5296 // STR (Store Register) calculates an address from a base register value and an
5297 // offset register value, stores a
5298 // word from a register to memory. The offset register value can optionally
5300 bool EmulateInstructionARM::EmulateSTRRegister(const uint32_t opcode,
5301 const ARMEncoding encoding) {
5303 if ConditionPassed() then
5304 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
5305 offset = Shift(R[m], shift_t, shift_n, APSR.C);
5306 offset_addr = if add then (R[n] + offset) else (R[n] - offset);
5307 address = if index then offset_addr else R[n];
5308 if t == 15 then // Only possible for encoding A1
5309 data = PCStoreValue();
5312 if UnalignedSupport() || address<1:0> == '00' || CurrentInstrSet() == InstrSet_ARM then
5313 MemU[address,4] = data;
5314 else // Can only occur before ARMv7
5315 MemU[address,4] = bits(32) UNKNOWN;
5316 if wback then R[n] = offset_addr;
5319 bool success = false;
5321 if (ConditionPassed(opcode)) {
5322 const uint32_t addr_byte_size = GetAddressByteSize();
5327 ARM_ShifterType shift_t;
5333 // EncodingSpecificOperations (); NullCheckIfThumbEE(n);
5336 // if CurrentInstrSet() == InstrSet_ThumbEE then SEE "Modified operation
5338 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
5339 t = Bits32(opcode, 2, 0);
5340 n = Bits32(opcode, 5, 3);
5341 m = Bits32(opcode, 8, 6);
5343 // index = TRUE; add = TRUE; wback = FALSE;
5348 // (shift_t, shift_n) = (SRType_LSL, 0);
5349 shift_t = SRType_LSL;
5354 // if Rn == '1111' then UNDEFINED;
5355 if (Bits32(opcode, 19, 16) == 15)
5358 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
5359 t = Bits32(opcode, 15, 12);
5360 n = Bits32(opcode, 19, 16);
5361 m = Bits32(opcode, 3, 0);
5363 // index = TRUE; add = TRUE; wback = FALSE;
5368 // (shift_t, shift_n) = (SRType_LSL, UInt(imm2));
5369 shift_t = SRType_LSL;
5370 shift_n = Bits32(opcode, 5, 4);
5372 // if t == 15 || BadReg(m) then UNPREDICTABLE;
5373 if ((t == 15) || (BadReg(m)))
5378 // if P == '0' && W == '1' then SEE STRT;
5379 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
5380 t = Bits32(opcode, 15, 12);
5381 n = Bits32(opcode, 19, 16);
5382 m = Bits32(opcode, 3, 0);
5384 // index = (P == '1'); add = (U == '1'); wback = (P == '0') ||
5386 index = BitIsSet(opcode, 24);
5387 add = BitIsSet(opcode, 23);
5388 wback = (BitIsClear(opcode, 24) || BitIsSet(opcode, 21));
5390 // (shift_t, shift_n) = DecodeImmShift(type, imm5);
5391 uint32_t typ = Bits32(opcode, 6, 5);
5392 uint32_t imm5 = Bits32(opcode, 11, 7);
5393 shift_n = DecodeImmShift(typ, imm5, shift_t);
5395 // if m == 15 then UNPREDICTABLE;
5399 // if wback && (n == 15 || n == t) then UNPREDICTABLE;
5400 if (wback && ((n == 15) || (n == t)))
5413 addr_t base_address =
5414 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
5419 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
5423 // offset = Shift(R[m], shift_t, shift_n, APSR.C);
5424 offset = Shift(Rm_data, shift_t, shift_n, APSR_C, &success);
5428 // offset_addr = if add then (R[n] + offset) else (R[n] - offset);
5430 offset_addr = base_address + offset;
5432 offset_addr = base_address - offset;
5434 // address = if index then offset_addr else R[n];
5436 address = offset_addr;
5438 address = base_address;
5441 // if t == 15 then // Only possible for encoding A1
5443 // data = PCStoreValue();
5444 data = ReadCoreReg(PC_REG, &success);
5448 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + t, 0, &success);
5453 EmulateInstruction::Context context;
5454 context.type = eContextRegisterStore;
5456 // if UnalignedSupport() || address<1:0> == '00' || CurrentInstrSet() ==
5457 // InstrSet_ARM then
5458 if (UnalignedSupport() ||
5459 (BitIsClear(address, 1) && BitIsClear(address, 0)) ||
5460 CurrentInstrSet() == eModeARM) {
5461 // MemU[address,4] = data;
5463 RegisterInfo base_reg;
5464 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n, base_reg);
5466 RegisterInfo data_reg;
5467 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + t, data_reg);
5469 context.SetRegisterToRegisterPlusOffset(data_reg, base_reg,
5470 address - base_address);
5471 if (!MemUWrite(context, address, data, addr_byte_size))
5475 // MemU[address,4] = bits(32) UNKNOWN;
5476 WriteBits32UnknownToMemory(address);
5478 // if wback then R[n] = offset_addr;
5480 context.type = eContextRegisterLoad;
5481 context.SetAddress(offset_addr);
5482 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n,
5490 bool EmulateInstructionARM::EmulateSTRBThumb(const uint32_t opcode,
5491 const ARMEncoding encoding) {
5493 if ConditionPassed() then
5494 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
5495 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
5496 address = if index then offset_addr else R[n];
5497 MemU[address,1] = R[t]<7:0>;
5498 if wback then R[n] = offset_addr;
5501 bool success = false;
5503 if (ConditionPassed(opcode)) {
5510 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
5513 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm5, 32);
5514 t = Bits32(opcode, 2, 0);
5515 n = Bits32(opcode, 5, 3);
5516 imm32 = Bits32(opcode, 10, 6);
5518 // index = TRUE; add = TRUE; wback = FALSE;
5525 // if Rn == '1111' then UNDEFINED;
5526 if (Bits32(opcode, 19, 16) == 15)
5529 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
5530 t = Bits32(opcode, 15, 12);
5531 n = Bits32(opcode, 19, 16);
5532 imm32 = Bits32(opcode, 11, 0);
5534 // index = TRUE; add = TRUE; wback = FALSE;
5539 // if BadReg(t) then UNPREDICTABLE;
5545 // if P == '1' && U == '1' && W == '0' then SEE STRBT;
5546 // if Rn == '1111' || (P == '0' && W == '0') then UNDEFINED;
5547 if (Bits32(opcode, 19, 16) == 15)
5550 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32);
5551 t = Bits32(opcode, 15, 12);
5552 n = Bits32(opcode, 19, 16);
5553 imm32 = Bits32(opcode, 7, 0);
5555 // index = (P == '1'); add = (U == '1'); wback = (W == '1');
5556 index = BitIsSet(opcode, 10);
5557 add = BitIsSet(opcode, 9);
5558 wback = BitIsSet(opcode, 8);
5560 // if BadReg(t) || (wback && n == t) then UNPREDICTABLE
5561 if ((BadReg(t)) || (wback && (n == t)))
5571 addr_t base_address =
5572 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
5576 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
5578 offset_addr = base_address + imm32;
5580 offset_addr = base_address - imm32;
5582 // address = if index then offset_addr else R[n];
5584 address = offset_addr;
5586 address = base_address;
5588 // MemU[address,1] = R[t]<7:0>
5589 RegisterInfo base_reg;
5590 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n, base_reg);
5592 RegisterInfo data_reg;
5593 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + t, data_reg);
5595 EmulateInstruction::Context context;
5596 context.type = eContextRegisterStore;
5597 context.SetRegisterToRegisterPlusOffset(data_reg, base_reg,
5598 address - base_address);
5601 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + t, 0, &success);
5605 data = Bits32(data, 7, 0);
5607 if (!MemUWrite(context, address, data, 1))
5610 // if wback then R[n] = offset_addr;
5612 context.type = eContextRegisterLoad;
5613 context.SetAddress(offset_addr);
5614 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n,
5623 // STRH (register) calculates an address from a base register value and an
5624 // offset register value, and stores a
5625 // halfword from a register to memory. The offset register value can be
5626 // shifted left by 0, 1, 2, or 3 bits.
5627 bool EmulateInstructionARM::EmulateSTRHRegister(const uint32_t opcode,
5628 const ARMEncoding encoding) {
5630 if ConditionPassed() then
5631 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
5632 offset = Shift(R[m], shift_t, shift_n, APSR.C);
5633 offset_addr = if add then (R[n] + offset) else (R[n] - offset);
5634 address = if index then offset_addr else R[n];
5635 if UnalignedSupport() || address<0> == '0' then
5636 MemU[address,2] = R[t]<15:0>;
5637 else // Can only occur before ARMv7
5638 MemU[address,2] = bits(16) UNKNOWN;
5639 if wback then R[n] = offset_addr;
5642 bool success = false;
5644 if (ConditionPassed(opcode)) {
5651 ARM_ShifterType shift_t;
5654 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
5657 // if CurrentInstrSet() == InstrSet_ThumbEE then SEE "Modified operation
5659 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
5660 t = Bits32(opcode, 2, 0);
5661 n = Bits32(opcode, 5, 3);
5662 m = Bits32(opcode, 8, 6);
5664 // index = TRUE; add = TRUE; wback = FALSE;
5669 // (shift_t, shift_n) = (SRType_LSL, 0);
5670 shift_t = SRType_LSL;
5676 // if Rn == '1111' then UNDEFINED;
5677 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
5678 t = Bits32(opcode, 15, 12);
5679 n = Bits32(opcode, 19, 16);
5680 m = Bits32(opcode, 3, 0);
5684 // index = TRUE; add = TRUE; wback = FALSE;
5689 // (shift_t, shift_n) = (SRType_LSL, UInt(imm2));
5690 shift_t = SRType_LSL;
5691 shift_n = Bits32(opcode, 5, 4);
5693 // if BadReg(t) || BadReg(m) then UNPREDICTABLE;
5694 if (BadReg(t) || BadReg(m))
5700 // if P == '0' && W == '1' then SEE STRHT;
5701 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
5702 t = Bits32(opcode, 15, 12);
5703 n = Bits32(opcode, 19, 16);
5704 m = Bits32(opcode, 3, 0);
5706 // index = (P == '1'); add = (U == '1'); wback = (P == '0') ||
5708 index = BitIsSet(opcode, 24);
5709 add = BitIsSet(opcode, 23);
5710 wback = (BitIsClear(opcode, 24) || BitIsSet(opcode, 21));
5712 // (shift_t, shift_n) = (SRType_LSL, 0);
5713 shift_t = SRType_LSL;
5716 // if t == 15 || m == 15 then UNPREDICTABLE;
5717 if ((t == 15) || (m == 15))
5720 // if wback && (n == 15 || n == t) then UNPREDICTABLE;
5721 if (wback && ((n == 15) || (n == t)))
5730 uint32_t Rm = ReadCoreReg(m, &success);
5734 uint32_t Rn = ReadCoreReg(n, &success);
5738 // offset = Shift(R[m], shift_t, shift_n, APSR.C);
5739 uint32_t offset = Shift(Rm, shift_t, shift_n, APSR_C, &success);
5743 // offset_addr = if add then (R[n] + offset) else (R[n] - offset);
5746 offset_addr = Rn + offset;
5748 offset_addr = Rn - offset;
5750 // address = if index then offset_addr else R[n];
5753 address = offset_addr;
5757 EmulateInstruction::Context context;
5758 context.type = eContextRegisterStore;
5759 RegisterInfo base_reg;
5760 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n, base_reg);
5761 RegisterInfo offset_reg;
5762 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + m, offset_reg);
5764 // if UnalignedSupport() || address<0> == '0' then
5765 if (UnalignedSupport() || BitIsClear(address, 0)) {
5766 // MemU[address,2] = R[t]<15:0>;
5767 uint32_t Rt = ReadCoreReg(t, &success);
5771 EmulateInstruction::Context context;
5772 context.type = eContextRegisterStore;
5773 RegisterInfo base_reg;
5774 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n, base_reg);
5775 RegisterInfo offset_reg;
5776 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + m, offset_reg);
5777 RegisterInfo data_reg;
5778 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + t, data_reg);
5779 context.SetRegisterToRegisterPlusIndirectOffset(base_reg, offset_reg,
5782 if (!MemUWrite(context, address, Bits32(Rt, 15, 0), 2))
5784 } else // Can only occur before ARMv7
5786 // MemU[address,2] = bits(16) UNKNOWN;
5789 // if wback then R[n] = offset_addr;
5791 context.type = eContextAdjustBaseRegister;
5792 context.SetAddress(offset_addr);
5793 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n,
5802 // Add with Carry (immediate) adds an immediate value and the carry flag value
5803 // to a register value, and writes the result to the destination register. It
5804 // can optionally update the condition flags based on the result.
5805 bool EmulateInstructionARM::EmulateADCImm(const uint32_t opcode,
5806 const ARMEncoding encoding) {
5808 // ARM pseudo code...
5809 if ConditionPassed() then
5810 EncodingSpecificOperations();
5811 (result, carry, overflow) = AddWithCarry(R[n], imm32, APSR.C);
5812 if d == 15 then // Can only occur for ARM encoding
5813 ALUWritePC(result); // setflags is always FALSE here
5817 APSR.N = result<31>;
5818 APSR.Z = IsZeroBit(result);
5823 bool success = false;
5825 if (ConditionPassed(opcode)) {
5828 imm32; // the immediate value to be added to the value obtained from Rn
5832 Rd = Bits32(opcode, 11, 8);
5833 Rn = Bits32(opcode, 19, 16);
5834 setflags = BitIsSet(opcode, 20);
5835 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8)
5836 if (BadReg(Rd) || BadReg(Rn))
5840 Rd = Bits32(opcode, 15, 12);
5841 Rn = Bits32(opcode, 19, 16);
5842 setflags = BitIsSet(opcode, 20);
5843 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
5845 if (Rd == 15 && setflags)
5846 return EmulateSUBSPcLrEtc(opcode, encoding);
5852 // Read the first operand.
5853 int32_t val1 = ReadCoreReg(Rn, &success);
5857 AddWithCarryResult res = AddWithCarry(val1, imm32, APSR_C);
5859 EmulateInstruction::Context context;
5860 context.type = EmulateInstruction::eContextImmediate;
5861 context.SetNoArgs();
5863 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags,
5864 res.carry_out, res.overflow))
5870 // Add with Carry (register) adds a register value, the carry flag value, and
5871 // an optionally-shifted register value, and writes the result to the
5872 // destination register. It can optionally update the condition flags based on
5874 bool EmulateInstructionARM::EmulateADCReg(const uint32_t opcode,
5875 const ARMEncoding encoding) {
5877 // ARM pseudo code...
5878 if ConditionPassed() then
5879 EncodingSpecificOperations();
5880 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
5881 (result, carry, overflow) = AddWithCarry(R[n], shifted, APSR.C);
5882 if d == 15 then // Can only occur for ARM encoding
5883 ALUWritePC(result); // setflags is always FALSE here
5887 APSR.N = result<31>;
5888 APSR.Z = IsZeroBit(result);
5893 bool success = false;
5895 if (ConditionPassed(opcode)) {
5896 uint32_t Rd, Rn, Rm;
5897 ARM_ShifterType shift_t;
5898 uint32_t shift_n; // the shift applied to the value read from Rm
5902 Rd = Rn = Bits32(opcode, 2, 0);
5903 Rm = Bits32(opcode, 5, 3);
5904 setflags = !InITBlock();
5905 shift_t = SRType_LSL;
5909 Rd = Bits32(opcode, 11, 8);
5910 Rn = Bits32(opcode, 19, 16);
5911 Rm = Bits32(opcode, 3, 0);
5912 setflags = BitIsSet(opcode, 20);
5913 shift_n = DecodeImmShiftThumb(opcode, shift_t);
5914 if (BadReg(Rd) || BadReg(Rn) || BadReg(Rm))
5918 Rd = Bits32(opcode, 15, 12);
5919 Rn = Bits32(opcode, 19, 16);
5920 Rm = Bits32(opcode, 3, 0);
5921 setflags = BitIsSet(opcode, 20);
5922 shift_n = DecodeImmShiftARM(opcode, shift_t);
5924 if (Rd == 15 && setflags)
5925 return EmulateSUBSPcLrEtc(opcode, encoding);
5931 // Read the first operand.
5932 int32_t val1 = ReadCoreReg(Rn, &success);
5936 // Read the second operand.
5937 int32_t val2 = ReadCoreReg(Rm, &success);
5941 uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C, &success);
5944 AddWithCarryResult res = AddWithCarry(val1, shifted, APSR_C);
5946 EmulateInstruction::Context context;
5947 context.type = EmulateInstruction::eContextImmediate;
5948 context.SetNoArgs();
5950 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags,
5951 res.carry_out, res.overflow))
5957 // This instruction adds an immediate value to the PC value to form a PC-
5958 // relative address, and writes the result to the destination register.
5959 bool EmulateInstructionARM::EmulateADR(const uint32_t opcode,
5960 const ARMEncoding encoding) {
5962 // ARM pseudo code...
5963 if ConditionPassed() then
5964 EncodingSpecificOperations();
5965 result = if add then (Align(PC,4) + imm32) else (Align(PC,4) - imm32);
5966 if d == 15 then // Can only occur for ARM encodings
5972 bool success = false;
5974 if (ConditionPassed(opcode)) {
5976 uint32_t imm32; // the immediate value to be added/subtracted to/from the PC
5980 Rd = Bits32(opcode, 10, 8);
5981 imm32 = ThumbImm8Scaled(opcode); // imm32 = ZeroExtend(imm8:'00', 32)
5986 Rd = Bits32(opcode, 11, 8);
5987 imm32 = ThumbImm12(opcode); // imm32 = ZeroExtend(i:imm3:imm8, 32)
5988 add = (Bits32(opcode, 24, 21) == 0); // 0b0000 => ADD; 0b0101 => SUB
5994 Rd = Bits32(opcode, 15, 12);
5995 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
5996 add = (Bits32(opcode, 24, 21) == 0x4); // 0b0100 => ADD; 0b0010 => SUB
6002 // Read the PC value.
6003 uint32_t pc = ReadCoreReg(PC_REG, &success);
6007 uint32_t result = (add ? Align(pc, 4) + imm32 : Align(pc, 4) - imm32);
6009 EmulateInstruction::Context context;
6010 context.type = EmulateInstruction::eContextImmediate;
6011 context.SetNoArgs();
6013 if (!WriteCoreReg(context, result, Rd))
6019 // This instruction performs a bitwise AND of a register value and an immediate
6020 // value, and writes the result to the destination register. It can optionally
6021 // update the condition flags based on the result.
6022 bool EmulateInstructionARM::EmulateANDImm(const uint32_t opcode,
6023 const ARMEncoding encoding) {
6025 // ARM pseudo code...
6026 if ConditionPassed() then
6027 EncodingSpecificOperations();
6028 result = R[n] AND imm32;
6029 if d == 15 then // Can only occur for ARM encoding
6030 ALUWritePC(result); // setflags is always FALSE here
6034 APSR.N = result<31>;
6035 APSR.Z = IsZeroBit(result);
6040 bool success = false;
6042 if (ConditionPassed(opcode)) {
6045 imm32; // the immediate value to be ANDed to the value obtained from Rn
6047 uint32_t carry; // the carry bit after ARM/Thumb Expand operation
6050 Rd = Bits32(opcode, 11, 8);
6051 Rn = Bits32(opcode, 19, 16);
6052 setflags = BitIsSet(opcode, 20);
6053 imm32 = ThumbExpandImm_C(
6055 carry); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C)
6056 // if Rd == '1111' && S == '1' then SEE TST (immediate);
6057 if (Rd == 15 && setflags)
6058 return EmulateTSTImm(opcode, eEncodingT1);
6059 if (Rd == 13 || (Rd == 15 && !setflags) || BadReg(Rn))
6063 Rd = Bits32(opcode, 15, 12);
6064 Rn = Bits32(opcode, 19, 16);
6065 setflags = BitIsSet(opcode, 20);
6067 ARMExpandImm_C(opcode, APSR_C,
6068 carry); // (imm32, carry) = ARMExpandImm(imm12, APSR.C)
6070 if (Rd == 15 && setflags)
6071 return EmulateSUBSPcLrEtc(opcode, encoding);
6077 // Read the first operand.
6078 uint32_t val1 = ReadCoreReg(Rn, &success);
6082 uint32_t result = val1 & imm32;
6084 EmulateInstruction::Context context;
6085 context.type = EmulateInstruction::eContextImmediate;
6086 context.SetNoArgs();
6088 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
6094 // This instruction performs a bitwise AND of a register value and an
6095 // optionally-shifted register value, and writes the result to the destination
6096 // register. It can optionally update the condition flags based on the result.
6097 bool EmulateInstructionARM::EmulateANDReg(const uint32_t opcode,
6098 const ARMEncoding encoding) {
6100 // ARM pseudo code...
6101 if ConditionPassed() then
6102 EncodingSpecificOperations();
6103 (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C);
6104 result = R[n] AND shifted;
6105 if d == 15 then // Can only occur for ARM encoding
6106 ALUWritePC(result); // setflags is always FALSE here
6110 APSR.N = result<31>;
6111 APSR.Z = IsZeroBit(result);
6116 bool success = false;
6118 if (ConditionPassed(opcode)) {
6119 uint32_t Rd, Rn, Rm;
6120 ARM_ShifterType shift_t;
6121 uint32_t shift_n; // the shift applied to the value read from Rm
6126 Rd = Rn = Bits32(opcode, 2, 0);
6127 Rm = Bits32(opcode, 5, 3);
6128 setflags = !InITBlock();
6129 shift_t = SRType_LSL;
6133 Rd = Bits32(opcode, 11, 8);
6134 Rn = Bits32(opcode, 19, 16);
6135 Rm = Bits32(opcode, 3, 0);
6136 setflags = BitIsSet(opcode, 20);
6137 shift_n = DecodeImmShiftThumb(opcode, shift_t);
6138 // if Rd == '1111' && S == '1' then SEE TST (register);
6139 if (Rd == 15 && setflags)
6140 return EmulateTSTReg(opcode, eEncodingT2);
6141 if (Rd == 13 || (Rd == 15 && !setflags) || BadReg(Rn) || BadReg(Rm))
6145 Rd = Bits32(opcode, 15, 12);
6146 Rn = Bits32(opcode, 19, 16);
6147 Rm = Bits32(opcode, 3, 0);
6148 setflags = BitIsSet(opcode, 20);
6149 shift_n = DecodeImmShiftARM(opcode, shift_t);
6151 if (Rd == 15 && setflags)
6152 return EmulateSUBSPcLrEtc(opcode, encoding);
6158 // Read the first operand.
6159 uint32_t val1 = ReadCoreReg(Rn, &success);
6163 // Read the second operand.
6164 uint32_t val2 = ReadCoreReg(Rm, &success);
6168 uint32_t shifted = Shift_C(val2, shift_t, shift_n, APSR_C, carry, &success);
6171 uint32_t result = val1 & shifted;
6173 EmulateInstruction::Context context;
6174 context.type = EmulateInstruction::eContextImmediate;
6175 context.SetNoArgs();
6177 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
6183 // Bitwise Bit Clear (immediate) performs a bitwise AND of a register value and
6184 // the complement of an immediate value, and writes the result to the
6185 // destination register. It can optionally update the condition flags based on
6187 bool EmulateInstructionARM::EmulateBICImm(const uint32_t opcode,
6188 const ARMEncoding encoding) {
6190 // ARM pseudo code...
6191 if ConditionPassed() then
6192 EncodingSpecificOperations();
6193 result = R[n] AND NOT(imm32);
6194 if d == 15 then // Can only occur for ARM encoding
6195 ALUWritePC(result); // setflags is always FALSE here
6199 APSR.N = result<31>;
6200 APSR.Z = IsZeroBit(result);
6205 bool success = false;
6207 if (ConditionPassed(opcode)) {
6209 uint32_t imm32; // the immediate value to be bitwise inverted and ANDed to
6210 // the value obtained from Rn
6212 uint32_t carry; // the carry bit after ARM/Thumb Expand operation
6215 Rd = Bits32(opcode, 11, 8);
6216 Rn = Bits32(opcode, 19, 16);
6217 setflags = BitIsSet(opcode, 20);
6218 imm32 = ThumbExpandImm_C(
6220 carry); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C)
6221 if (BadReg(Rd) || BadReg(Rn))
6225 Rd = Bits32(opcode, 15, 12);
6226 Rn = Bits32(opcode, 19, 16);
6227 setflags = BitIsSet(opcode, 20);
6229 ARMExpandImm_C(opcode, APSR_C,
6230 carry); // (imm32, carry) = ARMExpandImm(imm12, APSR.C)
6232 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related
6234 if (Rd == 15 && setflags)
6235 return EmulateSUBSPcLrEtc(opcode, encoding);
6241 // Read the first operand.
6242 uint32_t val1 = ReadCoreReg(Rn, &success);
6246 uint32_t result = val1 & ~imm32;
6248 EmulateInstruction::Context context;
6249 context.type = EmulateInstruction::eContextImmediate;
6250 context.SetNoArgs();
6252 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
6258 // Bitwise Bit Clear (register) performs a bitwise AND of a register value and
6259 // the complement of an optionally-shifted register value, and writes the
6260 // result to the destination register. It can optionally update the condition
6261 // flags based on the result.
6262 bool EmulateInstructionARM::EmulateBICReg(const uint32_t opcode,
6263 const ARMEncoding encoding) {
6265 // ARM pseudo code...
6266 if ConditionPassed() then
6267 EncodingSpecificOperations();
6268 (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C);
6269 result = R[n] AND NOT(shifted);
6270 if d == 15 then // Can only occur for ARM encoding
6271 ALUWritePC(result); // setflags is always FALSE here
6275 APSR.N = result<31>;
6276 APSR.Z = IsZeroBit(result);
6281 bool success = false;
6283 if (ConditionPassed(opcode)) {
6284 uint32_t Rd, Rn, Rm;
6285 ARM_ShifterType shift_t;
6286 uint32_t shift_n; // the shift applied to the value read from Rm
6291 Rd = Rn = Bits32(opcode, 2, 0);
6292 Rm = Bits32(opcode, 5, 3);
6293 setflags = !InITBlock();
6294 shift_t = SRType_LSL;
6298 Rd = Bits32(opcode, 11, 8);
6299 Rn = Bits32(opcode, 19, 16);
6300 Rm = Bits32(opcode, 3, 0);
6301 setflags = BitIsSet(opcode, 20);
6302 shift_n = DecodeImmShiftThumb(opcode, shift_t);
6303 if (BadReg(Rd) || BadReg(Rn) || BadReg(Rm))
6307 Rd = Bits32(opcode, 15, 12);
6308 Rn = Bits32(opcode, 19, 16);
6309 Rm = Bits32(opcode, 3, 0);
6310 setflags = BitIsSet(opcode, 20);
6311 shift_n = DecodeImmShiftARM(opcode, shift_t);
6313 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related
6315 if (Rd == 15 && setflags)
6316 return EmulateSUBSPcLrEtc(opcode, encoding);
6322 // Read the first operand.
6323 uint32_t val1 = ReadCoreReg(Rn, &success);
6327 // Read the second operand.
6328 uint32_t val2 = ReadCoreReg(Rm, &success);
6332 uint32_t shifted = Shift_C(val2, shift_t, shift_n, APSR_C, carry, &success);
6335 uint32_t result = val1 & ~shifted;
6337 EmulateInstruction::Context context;
6338 context.type = EmulateInstruction::eContextImmediate;
6339 context.SetNoArgs();
6341 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
6347 // LDR (immediate, ARM) calculates an address from a base register value and an
6348 // immediate offset, loads a word
6349 // from memory, and writes it to a register. It can use offset, post-indexed,
6350 // or pre-indexed addressing.
6351 bool EmulateInstructionARM::EmulateLDRImmediateARM(const uint32_t opcode,
6352 const ARMEncoding encoding) {
6354 if ConditionPassed() then
6355 EncodingSpecificOperations();
6356 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
6357 address = if index then offset_addr else R[n];
6358 data = MemU[address,4];
6359 if wback then R[n] = offset_addr;
6361 if address<1:0> == '00' then LoadWritePC(data); else UNPREDICTABLE;
6362 elsif UnalignedSupport() || address<1:0> = '00' then
6364 else // Can only apply before ARMv7
6365 R[t] = ROR(data, 8*UInt(address<1:0>));
6368 bool success = false;
6370 if (ConditionPassed(opcode)) {
6371 const uint32_t addr_byte_size = GetAddressByteSize();
6382 // if Rn == '1111' then SEE LDR (literal);
6383 // if P == '0' && W == '1' then SEE LDRT;
6384 // if Rn == '1101' && P == '0' && U == '1' && W == '0' && imm12 ==
6385 // '000000000100' then SEE POP;
6386 // t == UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
6387 t = Bits32(opcode, 15, 12);
6388 n = Bits32(opcode, 19, 16);
6389 imm32 = Bits32(opcode, 11, 0);
6391 // index = (P == '1'); add = (U == '1'); wback = (P == '0') ||
6393 index = BitIsSet(opcode, 24);
6394 add = BitIsSet(opcode, 23);
6395 wback = (BitIsClear(opcode, 24) || BitIsSet(opcode, 21));
6397 // if wback && n == t then UNPREDICTABLE;
6398 if (wback && (n == t))
6409 addr_t base_address = ReadCoreReg(n, &success);
6413 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
6415 offset_addr = base_address + imm32;
6417 offset_addr = base_address - imm32;
6419 // address = if index then offset_addr else R[n];
6421 address = offset_addr;
6423 address = base_address;
6425 // data = MemU[address,4];
6427 RegisterInfo base_reg;
6428 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n, base_reg);
6430 EmulateInstruction::Context context;
6431 context.type = eContextRegisterLoad;
6432 context.SetRegisterPlusOffset(base_reg, address - base_address);
6434 uint64_t data = MemURead(context, address, addr_byte_size, 0, &success);
6438 // if wback then R[n] = offset_addr;
6440 context.type = eContextAdjustBaseRegister;
6441 context.SetAddress(offset_addr);
6442 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n,
6449 // if address<1:0> == '00' then LoadWritePC(data); else UNPREDICTABLE;
6450 if (BitIsClear(address, 1) && BitIsClear(address, 0)) {
6451 // LoadWritePC (data);
6452 context.type = eContextRegisterLoad;
6453 context.SetRegisterPlusOffset(base_reg, address - base_address);
6454 LoadWritePC(context, data);
6458 // elsif UnalignedSupport() || address<1:0> = '00' then
6459 else if (UnalignedSupport() ||
6460 (BitIsClear(address, 1) && BitIsClear(address, 0))) {
6462 context.type = eContextRegisterLoad;
6463 context.SetRegisterPlusOffset(base_reg, address - base_address);
6464 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + t,
6468 // else // Can only apply before ARMv7
6470 // R[t] = ROR(data, 8*UInt(address<1:0>));
6471 data = ROR(data, Bits32(address, 1, 0), &success);
6474 context.type = eContextRegisterLoad;
6475 context.SetImmediate(data);
6476 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + t,
6484 // LDR (register) calculates an address from a base register value and an offset
6485 // register value, loads a word
6486 // from memory, and writes it to a register. The offset register value can
6487 // optionally be shifted.
6488 bool EmulateInstructionARM::EmulateLDRRegister(const uint32_t opcode,
6489 const ARMEncoding encoding) {
6491 if ConditionPassed() then
6492 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
6493 offset = Shift(R[m], shift_t, shift_n, APSR.C);
6494 offset_addr = if add then (R[n] + offset) else (R[n] - offset);
6495 address = if index then offset_addr else R[n];
6496 data = MemU[address,4];
6497 if wback then R[n] = offset_addr;
6499 if address<1:0> == '00' then LoadWritePC(data); else UNPREDICTABLE;
6500 elsif UnalignedSupport() || address<1:0> = '00' then
6502 else // Can only apply before ARMv7
6503 if CurrentInstrSet() == InstrSet_ARM then
6504 R[t] = ROR(data, 8*UInt(address<1:0>));
6506 R[t] = bits(32) UNKNOWN;
6509 bool success = false;
6511 if (ConditionPassed(opcode)) {
6512 const uint32_t addr_byte_size = GetAddressByteSize();
6520 ARM_ShifterType shift_t;
6525 // if CurrentInstrSet() == InstrSet_ThumbEE then SEE "Modified operation
6527 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
6528 t = Bits32(opcode, 2, 0);
6529 n = Bits32(opcode, 5, 3);
6530 m = Bits32(opcode, 8, 6);
6532 // index = TRUE; add = TRUE; wback = FALSE;
6537 // (shift_t, shift_n) = (SRType_LSL, 0);
6538 shift_t = SRType_LSL;
6544 // if Rn == '1111' then SEE LDR (literal);
6545 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
6546 t = Bits32(opcode, 15, 12);
6547 n = Bits32(opcode, 19, 16);
6548 m = Bits32(opcode, 3, 0);
6550 // index = TRUE; add = TRUE; wback = FALSE;
6555 // (shift_t, shift_n) = (SRType_LSL, UInt(imm2));
6556 shift_t = SRType_LSL;
6557 shift_n = Bits32(opcode, 5, 4);
6559 // if BadReg(m) then UNPREDICTABLE;
6563 // if t == 15 && InITBlock() && !LastInITBlock() then UNPREDICTABLE;
6564 if ((t == 15) && InITBlock() && !LastInITBlock())
6570 // if P == '0' && W == '1' then SEE LDRT;
6571 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
6572 t = Bits32(opcode, 15, 12);
6573 n = Bits32(opcode, 19, 16);
6574 m = Bits32(opcode, 3, 0);
6576 // index = (P == '1'); add = (U == '1'); wback = (P == '0') ||
6578 index = BitIsSet(opcode, 24);
6579 add = BitIsSet(opcode, 23);
6580 wback = (BitIsClear(opcode, 24) || BitIsSet(opcode, 21));
6582 // (shift_t, shift_n) = DecodeImmShift(type, imm5);
6583 uint32_t type = Bits32(opcode, 6, 5);
6584 uint32_t imm5 = Bits32(opcode, 11, 7);
6585 shift_n = DecodeImmShift(type, imm5, shift_t);
6587 // if m == 15 then UNPREDICTABLE;
6591 // if wback && (n == 15 || n == t) then UNPREDICTABLE;
6592 if (wback && ((n == 15) || (n == t)))
6601 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
6606 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
6613 // offset = Shift(R[m], shift_t, shift_n, APSR.C); -- Note "The APSR is
6614 // an application level alias for the CPSR".
6616 Shift(Rm, shift_t, shift_n, Bit32(m_opcode_cpsr, APSR_C), &success);
6620 // offset_addr = if add then (R[n] + offset) else (R[n] - offset);
6622 offset_addr = Rn + offset;
6624 offset_addr = Rn - offset;
6626 // address = if index then offset_addr else R[n];
6628 address = offset_addr;
6632 // data = MemU[address,4];
6633 RegisterInfo base_reg;
6634 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n, base_reg);
6636 EmulateInstruction::Context context;
6637 context.type = eContextRegisterLoad;
6638 context.SetRegisterPlusOffset(base_reg, address - Rn);
6640 uint64_t data = MemURead(context, address, addr_byte_size, 0, &success);
6644 // if wback then R[n] = offset_addr;
6646 context.type = eContextAdjustBaseRegister;
6647 context.SetAddress(offset_addr);
6648 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n,
6655 // if address<1:0> == '00' then LoadWritePC(data); else UNPREDICTABLE;
6656 if (BitIsClear(address, 1) && BitIsClear(address, 0)) {
6657 context.type = eContextRegisterLoad;
6658 context.SetRegisterPlusOffset(base_reg, address - Rn);
6659 LoadWritePC(context, data);
6663 // elsif UnalignedSupport() || address<1:0> = '00' then
6664 else if (UnalignedSupport() ||
6665 (BitIsClear(address, 1) && BitIsClear(address, 0))) {
6667 context.type = eContextRegisterLoad;
6668 context.SetRegisterPlusOffset(base_reg, address - Rn);
6669 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + t,
6672 } else // Can only apply before ARMv7
6674 // if CurrentInstrSet() == InstrSet_ARM then
6675 if (CurrentInstrSet() == eModeARM) {
6676 // R[t] = ROR(data, 8*UInt(address<1:0>));
6677 data = ROR(data, Bits32(address, 1, 0), &success);
6680 context.type = eContextRegisterLoad;
6681 context.SetImmediate(data);
6682 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + t,
6686 // R[t] = bits(32) UNKNOWN;
6687 WriteBits32Unknown(t);
6694 // LDRB (immediate, Thumb)
6695 bool EmulateInstructionARM::EmulateLDRBImmediate(const uint32_t opcode,
6696 const ARMEncoding encoding) {
6698 if ConditionPassed() then
6699 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
6700 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
6701 address = if index then offset_addr else R[n];
6702 R[t] = ZeroExtend(MemU[address,1], 32);
6703 if wback then R[n] = offset_addr;
6706 bool success = false;
6708 if (ConditionPassed(opcode)) {
6716 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
6719 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm5, 32);
6720 t = Bits32(opcode, 2, 0);
6721 n = Bits32(opcode, 5, 3);
6722 imm32 = Bits32(opcode, 10, 6);
6724 // index = TRUE; add = TRUE; wback = FALSE;
6732 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
6733 t = Bits32(opcode, 15, 12);
6734 n = Bits32(opcode, 19, 16);
6735 imm32 = Bits32(opcode, 11, 0);
6737 // index = TRUE; add = TRUE; wback = FALSE;
6742 // if Rt == '1111' then SEE PLD;
6744 return false; // PLD is not implemented yet
6746 // if Rn == '1111' then SEE LDRB (literal);
6748 return EmulateLDRBLiteral(opcode, eEncodingT1);
6750 // if t == 13 then UNPREDICTABLE;
6757 // if P == '1' && U == '1' && W == '0' then SEE LDRBT;
6758 // if P == '0' && W == '0' then UNDEFINED;
6759 if (BitIsClear(opcode, 10) && BitIsClear(opcode, 8))
6762 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32);
6763 t = Bits32(opcode, 15, 12);
6764 n = Bits32(opcode, 19, 16);
6765 imm32 = Bits32(opcode, 7, 0);
6767 // index = (P == '1'); add = (U == '1'); wback = (W == '1');
6768 index = BitIsSet(opcode, 10);
6769 add = BitIsSet(opcode, 9);
6770 wback = BitIsSet(opcode, 8);
6772 // if Rt == '1111' && P == '1' && U == '0' && W == '0' then SEE PLD;
6774 return false; // PLD is not implemented yet
6776 // if Rn == '1111' then SEE LDRB (literal);
6778 return EmulateLDRBLiteral(opcode, eEncodingT1);
6780 // if BadReg(t) || (wback && n == t) then UNPREDICTABLE;
6781 if (BadReg(t) || (wback && (n == t)))
6791 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
6798 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
6800 offset_addr = Rn + imm32;
6802 offset_addr = Rn - imm32;
6804 // address = if index then offset_addr else R[n];
6806 address = offset_addr;
6810 // R[t] = ZeroExtend(MemU[address,1], 32);
6811 RegisterInfo base_reg;
6812 RegisterInfo data_reg;
6813 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n, base_reg);
6814 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + t, data_reg);
6816 EmulateInstruction::Context context;
6817 context.type = eContextRegisterLoad;
6818 context.SetRegisterToRegisterPlusOffset(data_reg, base_reg, address - Rn);
6820 uint64_t data = MemURead(context, address, 1, 0, &success);
6824 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + t, data))
6827 // if wback then R[n] = offset_addr;
6829 context.type = eContextAdjustBaseRegister;
6830 context.SetAddress(offset_addr);
6831 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n,
6839 // LDRB (literal) calculates an address from the PC value and an immediate
6840 // offset, loads a byte from memory,
6841 // zero-extends it to form a 32-bit word and writes it to a register.
6842 bool EmulateInstructionARM::EmulateLDRBLiteral(const uint32_t opcode,
6843 const ARMEncoding encoding) {
6845 if ConditionPassed() then
6846 EncodingSpecificOperations(); NullCheckIfThumbEE(15);
6848 address = if add then (base + imm32) else (base - imm32);
6849 R[t] = ZeroExtend(MemU[address,1], 32);
6852 bool success = false;
6854 if (ConditionPassed(opcode)) {
6860 // t = UInt(Rt); imm32 = ZeroExtend(imm12, 32); add = (U == '1');
6861 t = Bits32(opcode, 15, 12);
6862 imm32 = Bits32(opcode, 11, 0);
6863 add = BitIsSet(opcode, 23);
6865 // if Rt == '1111' then SEE PLD;
6867 return false; // PLD is not implemented yet
6869 // if t == 13 then UNPREDICTABLE;
6876 // t == UInt(Rt); imm32 = ZeroExtend(imm12, 32); add = (U == '1');
6877 t = Bits32(opcode, 15, 12);
6878 imm32 = Bits32(opcode, 11, 0);
6879 add = BitIsSet(opcode, 23);
6881 // if t == 15 then UNPREDICTABLE;
6890 // base = Align(PC,4);
6891 uint32_t pc_val = ReadCoreReg(PC_REG, &success);
6895 uint32_t base = AlignPC(pc_val);
6898 // address = if add then (base + imm32) else (base - imm32);
6900 address = base + imm32;
6902 address = base - imm32;
6904 // R[t] = ZeroExtend(MemU[address,1], 32);
6905 EmulateInstruction::Context context;
6906 context.type = eContextRelativeBranchImmediate;
6907 context.SetImmediate(address - base);
6909 uint64_t data = MemURead(context, address, 1, 0, &success);
6913 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + t, data))
6919 // LDRB (register) calculates an address from a base register value and an
6920 // offset rigister value, loads a byte from memory, zero-extends it to form a
6921 // 32-bit word, and writes it to a register. The offset register value can
6922 // optionally be shifted.
6923 bool EmulateInstructionARM::EmulateLDRBRegister(const uint32_t opcode,
6924 const ARMEncoding encoding) {
6926 if ConditionPassed() then
6927 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
6928 offset = Shift(R[m], shift_t, shift_n, APSR.C);
6929 offset_addr = if add then (R[n] + offset) else (R[n] - offset);
6930 address = if index then offset_addr else R[n];
6931 R[t] = ZeroExtend(MemU[address,1],32);
6932 if wback then R[n] = offset_addr;
6935 bool success = false;
6937 if (ConditionPassed(opcode)) {
6944 ARM_ShifterType shift_t;
6947 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
6950 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
6951 t = Bits32(opcode, 2, 0);
6952 n = Bits32(opcode, 5, 3);
6953 m = Bits32(opcode, 8, 6);
6955 // index = TRUE; add = TRUE; wback = FALSE;
6960 // (shift_t, shift_n) = (SRType_LSL, 0);
6961 shift_t = SRType_LSL;
6966 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
6967 t = Bits32(opcode, 15, 12);
6968 n = Bits32(opcode, 19, 16);
6969 m = Bits32(opcode, 3, 0);
6971 // index = TRUE; add = TRUE; wback = FALSE;
6976 // (shift_t, shift_n) = (SRType_LSL, UInt(imm2));
6977 shift_t = SRType_LSL;
6978 shift_n = Bits32(opcode, 5, 4);
6980 // if Rt == '1111' then SEE PLD;
6982 return false; // PLD is not implemented yet
6984 // if Rn == '1111' then SEE LDRB (literal);
6986 return EmulateLDRBLiteral(opcode, eEncodingT1);
6988 // if t == 13 || BadReg(m) then UNPREDICTABLE;
6989 if ((t == 13) || BadReg(m))
6994 // if P == '0' && W == '1' then SEE LDRBT;
6995 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
6996 t = Bits32(opcode, 15, 12);
6997 n = Bits32(opcode, 19, 16);
6998 m = Bits32(opcode, 3, 0);
7000 // index = (P == '1'); add = (U == '1'); wback = (P == '0') ||
7002 index = BitIsSet(opcode, 24);
7003 add = BitIsSet(opcode, 23);
7004 wback = (BitIsClear(opcode, 24) || BitIsSet(opcode, 21));
7006 // (shift_t, shift_n) = DecodeImmShift(type, imm5);
7007 uint32_t type = Bits32(opcode, 6, 5);
7008 uint32_t imm5 = Bits32(opcode, 11, 7);
7009 shift_n = DecodeImmShift(type, imm5, shift_t);
7011 // if t == 15 || m == 15 then UNPREDICTABLE;
7012 if ((t == 15) || (m == 15))
7015 // if wback && (n == 15 || n == t) then UNPREDICTABLE;
7016 if (wback && ((n == 15) || (n == t)))
7027 // offset = Shift(R[m], shift_t, shift_n, APSR.C);
7029 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
7033 addr_t offset = Shift(Rm, shift_t, shift_n, APSR_C, &success);
7037 // offset_addr = if add then (R[n] + offset) else (R[n] - offset);
7039 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
7044 offset_addr = Rn + offset;
7046 offset_addr = Rn - offset;
7048 // address = if index then offset_addr else R[n];
7050 address = offset_addr;
7054 // R[t] = ZeroExtend(MemU[address,1],32);
7055 RegisterInfo base_reg;
7056 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n, base_reg);
7058 EmulateInstruction::Context context;
7059 context.type = eContextRegisterLoad;
7060 context.SetRegisterPlusOffset(base_reg, address - Rn);
7062 uint64_t data = MemURead(context, address, 1, 0, &success);
7066 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + t, data))
7069 // if wback then R[n] = offset_addr;
7071 context.type = eContextAdjustBaseRegister;
7072 context.SetAddress(offset_addr);
7073 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n,
7081 // LDRH (immediate, Thumb) calculates an address from a base register value and
7082 // an immediate offset, loads a
7083 // halfword from memory, zero-extends it to form a 32-bit word, and writes it
7084 // to a register. It can use offset, post-indexed, or pre-indexed addressing.
7085 bool EmulateInstructionARM::EmulateLDRHImmediate(const uint32_t opcode,
7086 const ARMEncoding encoding) {
7088 if ConditionPassed() then
7089 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
7090 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
7091 address = if index then offset_addr else R[n];
7092 data = MemU[address,2];
7093 if wback then R[n] = offset_addr;
7094 if UnalignedSupport() || address<0> = '0' then
7095 R[t] = ZeroExtend(data, 32);
7096 else // Can only apply before ARMv7
7097 R[t] = bits(32) UNKNOWN;
7100 bool success = false;
7102 if (ConditionPassed(opcode)) {
7110 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
7113 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm5:'0', 32);
7114 t = Bits32(opcode, 2, 0);
7115 n = Bits32(opcode, 5, 3);
7116 imm32 = Bits32(opcode, 10, 6) << 1;
7118 // index = TRUE; add = TRUE; wback = FALSE;
7126 // if Rt == '1111' then SEE "Unallocated memory hints";
7127 // if Rn == '1111' then SEE LDRH (literal);
7128 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
7129 t = Bits32(opcode, 15, 12);
7130 n = Bits32(opcode, 19, 16);
7131 imm32 = Bits32(opcode, 11, 0);
7133 // index = TRUE; add = TRUE; wback = FALSE;
7138 // if t == 13 then UNPREDICTABLE;
7144 // if Rn == '1111' then SEE LDRH (literal);
7145 // if Rt == '1111' && P == '1' && U == '0' && W == '0' then SEE
7146 // "Unallocated memory hints";
7147 // if P == '1' && U == '1' && W == '0' then SEE LDRHT;
7148 // if P == '0' && W == '0' then UNDEFINED;
7149 if (BitIsClear(opcode, 10) && BitIsClear(opcode, 8))
7152 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32);
7153 t = Bits32(opcode, 15, 12);
7154 n = Bits32(opcode, 19, 16);
7155 imm32 = Bits32(opcode, 7, 0);
7157 // index = (P == '1'); add = (U == '1'); wback = (W == '1');
7158 index = BitIsSet(opcode, 10);
7159 add = BitIsSet(opcode, 9);
7160 wback = BitIsSet(opcode, 8);
7162 // if BadReg(t) || (wback && n == t) then UNPREDICTABLE;
7163 if (BadReg(t) || (wback && (n == t)))
7171 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
7173 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
7181 offset_addr = Rn + imm32;
7183 offset_addr = Rn - imm32;
7185 // address = if index then offset_addr else R[n];
7187 address = offset_addr;
7191 // data = MemU[address,2];
7192 RegisterInfo base_reg;
7193 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n, base_reg);
7195 EmulateInstruction::Context context;
7196 context.type = eContextRegisterLoad;
7197 context.SetRegisterPlusOffset(base_reg, address - Rn);
7199 uint64_t data = MemURead(context, address, 2, 0, &success);
7203 // if wback then R[n] = offset_addr;
7205 context.type = eContextAdjustBaseRegister;
7206 context.SetAddress(offset_addr);
7207 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n,
7212 // if UnalignedSupport() || address<0> = '0' then
7213 if (UnalignedSupport() || BitIsClear(address, 0)) {
7214 // R[t] = ZeroExtend(data, 32);
7215 context.type = eContextRegisterLoad;
7216 context.SetRegisterPlusOffset(base_reg, address - Rn);
7217 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + t,
7220 } else // Can only apply before ARMv7
7222 // R[t] = bits(32) UNKNOWN;
7223 WriteBits32Unknown(t);
7229 // LDRH (literal) caculates an address from the PC value and an immediate
7230 // offset, loads a halfword from memory,
7231 // zero-extends it to form a 32-bit word, and writes it to a register.
7232 bool EmulateInstructionARM::EmulateLDRHLiteral(const uint32_t opcode,
7233 const ARMEncoding encoding) {
7235 if ConditionPassed() then
7236 EncodingSpecificOperations(); NullCheckIfThumbEE(15);
7238 address = if add then (base + imm32) else (base - imm32);
7239 data = MemU[address,2];
7240 if UnalignedSupport() || address<0> = '0' then
7241 R[t] = ZeroExtend(data, 32);
7242 else // Can only apply before ARMv7
7243 R[t] = bits(32) UNKNOWN;
7246 bool success = false;
7248 if (ConditionPassed(opcode)) {
7253 // EncodingSpecificOperations(); NullCheckIfThumbEE(15);
7256 // if Rt == '1111' then SEE "Unallocated memory hints";
7257 // t = UInt(Rt); imm32 = ZeroExtend(imm12, 32); add = (U == '1');
7258 t = Bits32(opcode, 15, 12);
7259 imm32 = Bits32(opcode, 11, 0);
7260 add = BitIsSet(opcode, 23);
7262 // if t == 13 then UNPREDICTABLE;
7269 uint32_t imm4H = Bits32(opcode, 11, 8);
7270 uint32_t imm4L = Bits32(opcode, 3, 0);
7272 // t == UInt(Rt); imm32 = ZeroExtend(imm4H:imm4L, 32); add = (U == '1');
7273 t = Bits32(opcode, 15, 12);
7274 imm32 = (imm4H << 4) | imm4L;
7275 add = BitIsSet(opcode, 23);
7277 // if t == 15 then UNPREDICTABLE;
7287 // base = Align(PC,4);
7288 uint64_t pc_value = ReadCoreReg(PC_REG, &success);
7292 addr_t base = AlignPC(pc_value);
7295 // address = if add then (base + imm32) else (base - imm32);
7297 address = base + imm32;
7299 address = base - imm32;
7301 // data = MemU[address,2];
7302 RegisterInfo base_reg;
7303 GetRegisterInfo(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, base_reg);
7305 EmulateInstruction::Context context;
7306 context.type = eContextRegisterLoad;
7307 context.SetRegisterPlusOffset(base_reg, address - base);
7309 uint64_t data = MemURead(context, address, 2, 0, &success);
7313 // if UnalignedSupport() || address<0> = '0' then
7314 if (UnalignedSupport() || BitIsClear(address, 0)) {
7315 // R[t] = ZeroExtend(data, 32);
7316 context.type = eContextRegisterLoad;
7317 context.SetRegisterPlusOffset(base_reg, address - base);
7318 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + t,
7322 } else // Can only apply before ARMv7
7324 // R[t] = bits(32) UNKNOWN;
7325 WriteBits32Unknown(t);
7331 // LDRH (literal) calculates an address from a base register value and an offset
7332 // register value, loads a halfword
7333 // from memory, zero-extends it to form a 32-bit word, and writes it to a
7334 // register. The offset register value can be shifted left by 0, 1, 2, or 3
7336 bool EmulateInstructionARM::EmulateLDRHRegister(const uint32_t opcode,
7337 const ARMEncoding encoding) {
7339 if ConditionPassed() then
7340 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
7341 offset = Shift(R[m], shift_t, shift_n, APSR.C);
7342 offset_addr = if add then (R[n] + offset) else (R[n] - offset);
7343 address = if index then offset_addr else R[n];
7344 data = MemU[address,2];
7345 if wback then R[n] = offset_addr;
7346 if UnalignedSupport() || address<0> = '0' then
7347 R[t] = ZeroExtend(data, 32);
7348 else // Can only apply before ARMv7
7349 R[t] = bits(32) UNKNOWN;
7352 bool success = false;
7354 if (ConditionPassed(opcode)) {
7361 ARM_ShifterType shift_t;
7364 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
7367 // if CurrentInstrSet() == InstrSet_ThumbEE then SEE "Modified operation
7369 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
7370 t = Bits32(opcode, 2, 0);
7371 n = Bits32(opcode, 5, 3);
7372 m = Bits32(opcode, 8, 6);
7374 // index = TRUE; add = TRUE; wback = FALSE;
7379 // (shift_t, shift_n) = (SRType_LSL, 0);
7380 shift_t = SRType_LSL;
7386 // if Rn == '1111' then SEE LDRH (literal);
7387 // if Rt == '1111' then SEE "Unallocated memory hints";
7388 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
7389 t = Bits32(opcode, 15, 12);
7390 n = Bits32(opcode, 19, 16);
7391 m = Bits32(opcode, 3, 0);
7393 // index = TRUE; add = TRUE; wback = FALSE;
7398 // (shift_t, shift_n) = (SRType_LSL, UInt(imm2));
7399 shift_t = SRType_LSL;
7400 shift_n = Bits32(opcode, 5, 4);
7402 // if t == 13 || BadReg(m) then UNPREDICTABLE;
7403 if ((t == 13) || BadReg(m))
7408 // if P == '0' && W == '1' then SEE LDRHT;
7409 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
7410 t = Bits32(opcode, 15, 12);
7411 n = Bits32(opcode, 19, 16);
7412 m = Bits32(opcode, 3, 0);
7414 // index = (P == '1'); add = (U == '1'); wback = (P == '0') ||
7416 index = BitIsSet(opcode, 24);
7417 add = BitIsSet(opcode, 23);
7418 wback = (BitIsClear(opcode, 24) || BitIsSet(opcode, 21));
7420 // (shift_t, shift_n) = (SRType_LSL, 0);
7421 shift_t = SRType_LSL;
7424 // if t == 15 || m == 15 then UNPREDICTABLE;
7425 if ((t == 15) || (m == 15))
7428 // if wback && (n == 15 || n == t) then UNPREDICTABLE;
7429 if (wback && ((n == 15) || (n == t)))
7438 // offset = Shift(R[m], shift_t, shift_n, APSR.C);
7441 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
7445 addr_t offset = Shift(Rm, shift_t, shift_n, APSR_C, &success);
7452 // offset_addr = if add then (R[n] + offset) else (R[n] - offset);
7454 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
7459 offset_addr = Rn + offset;
7461 offset_addr = Rn - offset;
7463 // address = if index then offset_addr else R[n];
7465 address = offset_addr;
7469 // data = MemU[address,2];
7470 RegisterInfo base_reg;
7471 RegisterInfo offset_reg;
7472 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n, base_reg);
7473 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + m, offset_reg);
7475 EmulateInstruction::Context context;
7476 context.type = eContextRegisterLoad;
7477 context.SetRegisterPlusIndirectOffset(base_reg, offset_reg);
7478 uint64_t data = MemURead(context, address, 2, 0, &success);
7482 // if wback then R[n] = offset_addr;
7484 context.type = eContextAdjustBaseRegister;
7485 context.SetAddress(offset_addr);
7486 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n,
7491 // if UnalignedSupport() || address<0> = '0' then
7492 if (UnalignedSupport() || BitIsClear(address, 0)) {
7493 // R[t] = ZeroExtend(data, 32);
7494 context.type = eContextRegisterLoad;
7495 context.SetRegisterPlusIndirectOffset(base_reg, offset_reg);
7496 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + t,
7499 } else // Can only apply before ARMv7
7501 // R[t] = bits(32) UNKNOWN;
7502 WriteBits32Unknown(t);
7508 // LDRSB (immediate) calculates an address from a base register value and an
7509 // immediate offset, loads a byte from
7510 // memory, sign-extends it to form a 32-bit word, and writes it to a register.
7511 // It can use offset, post-indexed, or pre-indexed addressing.
7512 bool EmulateInstructionARM::EmulateLDRSBImmediate(const uint32_t opcode,
7513 const ARMEncoding encoding) {
7515 if ConditionPassed() then
7516 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
7517 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
7518 address = if index then offset_addr else R[n];
7519 R[t] = SignExtend(MemU[address,1], 32);
7520 if wback then R[n] = offset_addr;
7523 bool success = false;
7525 if (ConditionPassed(opcode)) {
7533 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
7536 // if Rt == '1111' then SEE PLI;
7537 // if Rn == '1111' then SEE LDRSB (literal);
7538 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
7539 t = Bits32(opcode, 15, 12);
7540 n = Bits32(opcode, 19, 16);
7541 imm32 = Bits32(opcode, 11, 0);
7543 // index = TRUE; add = TRUE; wback = FALSE;
7548 // if t == 13 then UNPREDICTABLE;
7555 // if Rt == '1111' && P == '1' && U == '0' && W == '0' then SEE PLI;
7556 // if Rn == '1111' then SEE LDRSB (literal);
7557 // if P == '1' && U == '1' && W == '0' then SEE LDRSBT;
7558 // if P == '0' && W == '0' then UNDEFINED;
7559 if (BitIsClear(opcode, 10) && BitIsClear(opcode, 8))
7562 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32);
7563 t = Bits32(opcode, 15, 12);
7564 n = Bits32(opcode, 19, 16);
7565 imm32 = Bits32(opcode, 7, 0);
7567 // index = (P == '1'); add = (U == '1'); wback = (W == '1');
7568 index = BitIsSet(opcode, 10);
7569 add = BitIsSet(opcode, 9);
7570 wback = BitIsSet(opcode, 8);
7572 // if BadReg(t) || (wback && n == t) then UNPREDICTABLE;
7574 ((t == 15) && (BitIsClear(opcode, 10) || BitIsSet(opcode, 9) ||
7575 BitIsSet(opcode, 8)))) ||
7576 (wback && (n == t)))
7582 // if Rn == '1111' then SEE LDRSB (literal);
7583 // if P == '0' && W == '1' then SEE LDRSBT;
7584 // t == UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm4H:imm4L, 32);
7585 t = Bits32(opcode, 15, 12);
7586 n = Bits32(opcode, 19, 16);
7588 uint32_t imm4H = Bits32(opcode, 11, 8);
7589 uint32_t imm4L = Bits32(opcode, 3, 0);
7590 imm32 = (imm4H << 4) | imm4L;
7592 // index = (P == '1'); add = (U == '1'); wback = (P == '0') ||
7594 index = BitIsSet(opcode, 24);
7595 add = BitIsSet(opcode, 23);
7596 wback = (BitIsClear(opcode, 24) || BitIsSet(opcode, 21));
7598 // if t == 15 || (wback && n == t) then UNPREDICTABLE;
7599 if ((t == 15) || (wback && (n == t)))
7609 uint64_t Rn = ReadCoreReg(n, &success);
7616 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
7618 offset_addr = Rn + imm32;
7620 offset_addr = Rn - imm32;
7622 // address = if index then offset_addr else R[n];
7624 address = offset_addr;
7628 // R[t] = SignExtend(MemU[address,1], 32);
7629 RegisterInfo base_reg;
7630 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n, base_reg);
7632 EmulateInstruction::Context context;
7633 context.type = eContextRegisterLoad;
7634 context.SetRegisterPlusOffset(base_reg, address - Rn);
7636 uint64_t unsigned_data = MemURead(context, address, 1, 0, &success);
7640 int64_t signed_data = llvm::SignExtend64<8>(unsigned_data);
7641 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + t,
7642 (uint64_t)signed_data))
7645 // if wback then R[n] = offset_addr;
7647 context.type = eContextAdjustBaseRegister;
7648 context.SetAddress(offset_addr);
7649 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n,
7658 // LDRSB (literal) calculates an address from the PC value and an immediate
7659 // offset, loads a byte from memory,
7660 // sign-extends it to form a 32-bit word, and writes tit to a register.
7661 bool EmulateInstructionARM::EmulateLDRSBLiteral(const uint32_t opcode,
7662 const ARMEncoding encoding) {
7664 if ConditionPassed() then
7665 EncodingSpecificOperations(); NullCheckIfThumbEE(15);
7667 address = if add then (base + imm32) else (base - imm32);
7668 R[t] = SignExtend(MemU[address,1], 32);
7671 bool success = false;
7673 if (ConditionPassed(opcode)) {
7678 // EncodingSpecificOperations(); NullCheckIfThumbEE(15);
7681 // if Rt == '1111' then SEE PLI;
7682 // t = UInt(Rt); imm32 = ZeroExtend(imm12, 32); add = (U == '1');
7683 t = Bits32(opcode, 15, 12);
7684 imm32 = Bits32(opcode, 11, 0);
7685 add = BitIsSet(opcode, 23);
7687 // if t == 13 then UNPREDICTABLE;
7694 // t == UInt(Rt); imm32 = ZeroExtend(imm4H:imm4L, 32); add = (U == '1');
7695 t = Bits32(opcode, 15, 12);
7696 uint32_t imm4H = Bits32(opcode, 11, 8);
7697 uint32_t imm4L = Bits32(opcode, 3, 0);
7698 imm32 = (imm4H << 4) | imm4L;
7699 add = BitIsSet(opcode, 23);
7701 // if t == 15 then UNPREDICTABLE;
7712 // base = Align(PC,4);
7713 uint64_t pc_value = ReadCoreReg(PC_REG, &success);
7716 uint64_t base = AlignPC(pc_value);
7718 // address = if add then (base + imm32) else (base - imm32);
7721 address = base + imm32;
7723 address = base - imm32;
7725 // R[t] = SignExtend(MemU[address,1], 32);
7726 RegisterInfo base_reg;
7727 GetRegisterInfo(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, base_reg);
7729 EmulateInstruction::Context context;
7730 context.type = eContextRegisterLoad;
7731 context.SetRegisterPlusOffset(base_reg, address - base);
7733 uint64_t unsigned_data = MemURead(context, address, 1, 0, &success);
7737 int64_t signed_data = llvm::SignExtend64<8>(unsigned_data);
7738 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + t,
7739 (uint64_t)signed_data))
7745 // LDRSB (register) calculates an address from a base register value and an
7746 // offset register value, loadsa byte from
7747 // memory, sign-extends it to form a 32-bit word, and writes it to a register.
7748 // The offset register value can be shifted left by 0, 1, 2, or 3 bits.
7749 bool EmulateInstructionARM::EmulateLDRSBRegister(const uint32_t opcode,
7750 const ARMEncoding encoding) {
7752 if ConditionPassed() then
7753 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
7754 offset = Shift(R[m], shift_t, shift_n, APSR.C);
7755 offset_addr = if add then (R[n] + offset) else (R[n] - offset);
7756 address = if index then offset_addr else R[n];
7757 R[t] = SignExtend(MemU[address,1], 32);
7758 if wback then R[n] = offset_addr;
7761 bool success = false;
7763 if (ConditionPassed(opcode)) {
7770 ARM_ShifterType shift_t;
7773 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
7776 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
7777 t = Bits32(opcode, 2, 0);
7778 n = Bits32(opcode, 5, 3);
7779 m = Bits32(opcode, 8, 6);
7781 // index = TRUE; add = TRUE; wback = FALSE;
7786 // (shift_t, shift_n) = (SRType_LSL, 0);
7787 shift_t = SRType_LSL;
7793 // if Rt == '1111' then SEE PLI;
7794 // if Rn == '1111' then SEE LDRSB (literal);
7795 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
7796 t = Bits32(opcode, 15, 12);
7797 n = Bits32(opcode, 19, 16);
7798 m = Bits32(opcode, 3, 0);
7800 // index = TRUE; add = TRUE; wback = FALSE;
7805 // (shift_t, shift_n) = (SRType_LSL, UInt(imm2));
7806 shift_t = SRType_LSL;
7807 shift_n = Bits32(opcode, 5, 4);
7809 // if t == 13 || BadReg(m) then UNPREDICTABLE;
7810 if ((t == 13) || BadReg(m))
7815 // if P == '0' && W == '1' then SEE LDRSBT;
7816 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
7817 t = Bits32(opcode, 15, 12);
7818 n = Bits32(opcode, 19, 16);
7819 m = Bits32(opcode, 3, 0);
7821 // index = (P == '1'); add = (U == '1'); wback = (P == '0') ||
7823 index = BitIsSet(opcode, 24);
7824 add = BitIsSet(opcode, 23);
7825 wback = BitIsClear(opcode, 24) || BitIsSet(opcode, 21);
7827 // (shift_t, shift_n) = (SRType_LSL, 0);
7828 shift_t = SRType_LSL;
7831 // if t == 15 || m == 15 then UNPREDICTABLE;
7832 if ((t == 15) || (m == 15))
7835 // if wback && (n == 15 || n == t) then UNPREDICTABLE;
7836 if (wback && ((n == 15) || (n == t)))
7845 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
7849 // offset = Shift(R[m], shift_t, shift_n, APSR.C);
7850 addr_t offset = Shift(Rm, shift_t, shift_n, APSR_C, &success);
7857 // offset_addr = if add then (R[n] + offset) else (R[n] - offset);
7859 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
7864 offset_addr = Rn + offset;
7866 offset_addr = Rn - offset;
7868 // address = if index then offset_addr else R[n];
7870 address = offset_addr;
7874 // R[t] = SignExtend(MemU[address,1], 32);
7875 RegisterInfo base_reg;
7876 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n, base_reg);
7877 RegisterInfo offset_reg;
7878 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + m, offset_reg);
7880 EmulateInstruction::Context context;
7881 context.type = eContextRegisterLoad;
7882 context.SetRegisterPlusIndirectOffset(base_reg, offset_reg);
7884 uint64_t unsigned_data = MemURead(context, address, 1, 0, &success);
7888 int64_t signed_data = llvm::SignExtend64<8>(unsigned_data);
7889 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + t,
7890 (uint64_t)signed_data))
7893 // if wback then R[n] = offset_addr;
7895 context.type = eContextAdjustBaseRegister;
7896 context.SetAddress(offset_addr);
7897 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n,
7905 // LDRSH (immediate) calculates an address from a base register value and an
7906 // immediate offset, loads a halfword from
7907 // memory, sign-extends it to form a 32-bit word, and writes it to a register.
7908 // It can use offset, post-indexed, or pre-indexed addressing.
7909 bool EmulateInstructionARM::EmulateLDRSHImmediate(const uint32_t opcode,
7910 const ARMEncoding encoding) {
7912 if ConditionPassed() then
7913 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
7914 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
7915 address = if index then offset_addr else R[n];
7916 data = MemU[address,2];
7917 if wback then R[n] = offset_addr;
7918 if UnalignedSupport() || address<0> = '0' then
7919 R[t] = SignExtend(data, 32);
7920 else // Can only apply before ARMv7
7921 R[t] = bits(32) UNKNOWN;
7924 bool success = false;
7926 if (ConditionPassed(opcode)) {
7934 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
7937 // if Rn == '1111' then SEE LDRSH (literal);
7938 // if Rt == '1111' then SEE "Unallocated memory hints";
7939 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
7940 t = Bits32(opcode, 15, 12);
7941 n = Bits32(opcode, 19, 16);
7942 imm32 = Bits32(opcode, 11, 0);
7944 // index = TRUE; add = TRUE; wback = FALSE;
7949 // if t == 13 then UNPREDICTABLE;
7956 // if Rn == '1111' then SEE LDRSH (literal);
7957 // if Rt == '1111' && P == '1' && U == '0' && W == '0' then SEE
7958 // "Unallocated memory hints";
7959 // if P == '1' && U == '1' && W == '0' then SEE LDRSHT;
7960 // if P == '0' && W == '0' then UNDEFINED;
7961 if (BitIsClear(opcode, 10) && BitIsClear(opcode, 8))
7964 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32);
7965 t = Bits32(opcode, 15, 12);
7966 n = Bits32(opcode, 19, 16);
7967 imm32 = Bits32(opcode, 7, 0);
7969 // index = (P == '1'); add = (U == '1'); wback = (W == '1');
7970 index = BitIsSet(opcode, 10);
7971 add = BitIsSet(opcode, 9);
7972 wback = BitIsSet(opcode, 8);
7974 // if BadReg(t) || (wback && n == t) then UNPREDICTABLE;
7975 if (BadReg(t) || (wback && (n == t)))
7981 // if Rn == '1111' then SEE LDRSH (literal);
7982 // if P == '0' && W == '1' then SEE LDRSHT;
7983 // t == UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm4H:imm4L, 32);
7984 t = Bits32(opcode, 15, 12);
7985 n = Bits32(opcode, 19, 16);
7986 uint32_t imm4H = Bits32(opcode, 11, 8);
7987 uint32_t imm4L = Bits32(opcode, 3, 0);
7988 imm32 = (imm4H << 4) | imm4L;
7990 // index = (P == '1'); add = (U == '1'); wback = (P == '0') ||
7992 index = BitIsSet(opcode, 24);
7993 add = BitIsSet(opcode, 23);
7994 wback = BitIsClear(opcode, 24) || BitIsSet(opcode, 21);
7996 // if t == 15 || (wback && n == t) then UNPREDICTABLE;
7997 if ((t == 15) || (wback && (n == t)))
8007 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
8009 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
8015 offset_addr = Rn + imm32;
8017 offset_addr = Rn - imm32;
8019 // address = if index then offset_addr else R[n];
8022 address = offset_addr;
8026 // data = MemU[address,2];
8027 RegisterInfo base_reg;
8028 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n, base_reg);
8030 EmulateInstruction::Context context;
8031 context.type = eContextRegisterLoad;
8032 context.SetRegisterPlusOffset(base_reg, address - Rn);
8034 uint64_t data = MemURead(context, address, 2, 0, &success);
8038 // if wback then R[n] = offset_addr;
8040 context.type = eContextAdjustBaseRegister;
8041 context.SetAddress(offset_addr);
8042 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n,
8047 // if UnalignedSupport() || address<0> = '0' then
8048 if (UnalignedSupport() || BitIsClear(address, 0)) {
8049 // R[t] = SignExtend(data, 32);
8050 int64_t signed_data = llvm::SignExtend64<16>(data);
8051 context.type = eContextRegisterLoad;
8052 context.SetRegisterPlusOffset(base_reg, address - Rn);
8053 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + t,
8054 (uint64_t)signed_data))
8056 } else // Can only apply before ARMv7
8058 // R[t] = bits(32) UNKNOWN;
8059 WriteBits32Unknown(t);
8065 // LDRSH (literal) calculates an address from the PC value and an immediate
8066 // offset, loads a halfword from memory,
8067 // sign-extends it to from a 32-bit word, and writes it to a register.
8068 bool EmulateInstructionARM::EmulateLDRSHLiteral(const uint32_t opcode,
8069 const ARMEncoding encoding) {
8071 if ConditionPassed() then
8072 EncodingSpecificOperations(); NullCheckIfThumbEE(15);
8074 address = if add then (base + imm32) else (base - imm32);
8075 data = MemU[address,2];
8076 if UnalignedSupport() || address<0> = '0' then
8077 R[t] = SignExtend(data, 32);
8078 else // Can only apply before ARMv7
8079 R[t] = bits(32) UNKNOWN;
8082 bool success = false;
8084 if (ConditionPassed(opcode)) {
8089 // EncodingSpecificOperations(); NullCheckIfThumbEE(15);
8092 // if Rt == '1111' then SEE "Unallocated memory hints";
8093 // t = UInt(Rt); imm32 = ZeroExtend(imm12, 32); add = (U == '1');
8094 t = Bits32(opcode, 15, 12);
8095 imm32 = Bits32(opcode, 11, 0);
8096 add = BitIsSet(opcode, 23);
8098 // if t == 13 then UNPREDICTABLE;
8105 // t == UInt(Rt); imm32 = ZeroExtend(imm4H:imm4L, 32); add = (U == '1');
8106 t = Bits32(opcode, 15, 12);
8107 uint32_t imm4H = Bits32(opcode, 11, 8);
8108 uint32_t imm4L = Bits32(opcode, 3, 0);
8109 imm32 = (imm4H << 4) | imm4L;
8110 add = BitIsSet(opcode, 23);
8112 // if t == 15 then UNPREDICTABLE;
8122 // base = Align(PC,4);
8123 uint64_t pc_value = ReadCoreReg(PC_REG, &success);
8127 uint64_t base = AlignPC(pc_value);
8130 // address = if add then (base + imm32) else (base - imm32);
8132 address = base + imm32;
8134 address = base - imm32;
8136 // data = MemU[address,2];
8137 RegisterInfo base_reg;
8138 GetRegisterInfo(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, base_reg);
8140 EmulateInstruction::Context context;
8141 context.type = eContextRegisterLoad;
8142 context.SetRegisterPlusOffset(base_reg, imm32);
8144 uint64_t data = MemURead(context, address, 2, 0, &success);
8148 // if UnalignedSupport() || address<0> = '0' then
8149 if (UnalignedSupport() || BitIsClear(address, 0)) {
8150 // R[t] = SignExtend(data, 32);
8151 int64_t signed_data = llvm::SignExtend64<16>(data);
8152 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + t,
8153 (uint64_t)signed_data))
8155 } else // Can only apply before ARMv7
8157 // R[t] = bits(32) UNKNOWN;
8158 WriteBits32Unknown(t);
8164 // LDRSH (register) calculates an address from a base register value and an
8165 // offset register value, loads a halfword
8166 // from memory, sign-extends it to form a 32-bit word, and writes it to a
8167 // register. The offset register value can be shifted left by 0, 1, 2, or 3
8169 bool EmulateInstructionARM::EmulateLDRSHRegister(const uint32_t opcode,
8170 const ARMEncoding encoding) {
8172 if ConditionPassed() then
8173 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
8174 offset = Shift(R[m], shift_t, shift_n, APSR.C);
8175 offset_addr = if add then (R[n] + offset) else (R[n] - offset);
8176 address = if index then offset_addr else R[n];
8177 data = MemU[address,2];
8178 if wback then R[n] = offset_addr;
8179 if UnalignedSupport() || address<0> = '0' then
8180 R[t] = SignExtend(data, 32);
8181 else // Can only apply before ARMv7
8182 R[t] = bits(32) UNKNOWN;
8185 bool success = false;
8187 if (ConditionPassed(opcode)) {
8194 ARM_ShifterType shift_t;
8197 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
8200 // if CurrentInstrSet() == InstrSet_ThumbEE then SEE "Modified operation
8202 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
8203 t = Bits32(opcode, 2, 0);
8204 n = Bits32(opcode, 5, 3);
8205 m = Bits32(opcode, 8, 6);
8207 // index = TRUE; add = TRUE; wback = FALSE;
8212 // (shift_t, shift_n) = (SRType_LSL, 0);
8213 shift_t = SRType_LSL;
8219 // if Rn == '1111' then SEE LDRSH (literal);
8220 // if Rt == '1111' then SEE "Unallocated memory hints";
8221 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
8222 t = Bits32(opcode, 15, 12);
8223 n = Bits32(opcode, 19, 16);
8224 m = Bits32(opcode, 3, 0);
8226 // index = TRUE; add = TRUE; wback = FALSE;
8231 // (shift_t, shift_n) = (SRType_LSL, UInt(imm2));
8232 shift_t = SRType_LSL;
8233 shift_n = Bits32(opcode, 5, 4);
8235 // if t == 13 || BadReg(m) then UNPREDICTABLE;
8236 if ((t == 13) || BadReg(m))
8242 // if P == '0' && W == '1' then SEE LDRSHT;
8243 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
8244 t = Bits32(opcode, 15, 12);
8245 n = Bits32(opcode, 19, 16);
8246 m = Bits32(opcode, 3, 0);
8248 // index = (P == '1'); add = (U == '1'); wback = (P == '0') ||
8250 index = BitIsSet(opcode, 24);
8251 add = BitIsSet(opcode, 23);
8252 wback = BitIsClear(opcode, 24) || BitIsSet(opcode, 21);
8254 // (shift_t, shift_n) = (SRType_LSL, 0);
8255 shift_t = SRType_LSL;
8258 // if t == 15 || m == 15 then UNPREDICTABLE;
8259 if ((t == 15) || (m == 15))
8262 // if wback && (n == 15 || n == t) then UNPREDICTABLE;
8263 if (wback && ((n == 15) || (n == t)))
8273 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
8278 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
8282 // offset = Shift(R[m], shift_t, shift_n, APSR.C);
8283 addr_t offset = Shift(Rm, shift_t, shift_n, APSR_C, &success);
8290 // offset_addr = if add then (R[n] + offset) else (R[n] - offset);
8292 offset_addr = Rn + offset;
8294 offset_addr = Rn - offset;
8296 // address = if index then offset_addr else R[n];
8298 address = offset_addr;
8302 // data = MemU[address,2];
8303 RegisterInfo base_reg;
8304 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n, base_reg);
8306 RegisterInfo offset_reg;
8307 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + m, offset_reg);
8309 EmulateInstruction::Context context;
8310 context.type = eContextRegisterLoad;
8311 context.SetRegisterPlusIndirectOffset(base_reg, offset_reg);
8313 uint64_t data = MemURead(context, address, 2, 0, &success);
8317 // if wback then R[n] = offset_addr;
8319 context.type = eContextAdjustBaseRegister;
8320 context.SetAddress(offset_addr);
8321 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n,
8326 // if UnalignedSupport() || address<0> = '0' then
8327 if (UnalignedSupport() || BitIsClear(address, 0)) {
8328 // R[t] = SignExtend(data, 32);
8329 context.type = eContextRegisterLoad;
8330 context.SetRegisterPlusIndirectOffset(base_reg, offset_reg);
8332 int64_t signed_data = llvm::SignExtend64<16>(data);
8333 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + t,
8334 (uint64_t)signed_data))
8336 } else // Can only apply before ARMv7
8338 // R[t] = bits(32) UNKNOWN;
8339 WriteBits32Unknown(t);
8345 // SXTB extracts an 8-bit value from a register, sign-extends it to 32 bits, and
8346 // writes the result to the destination
8347 // register. You can specifiy a rotation by 0, 8, 16, or 24 bits before
8348 // extracting the 8-bit value.
8349 bool EmulateInstructionARM::EmulateSXTB(const uint32_t opcode,
8350 const ARMEncoding encoding) {
8352 if ConditionPassed() then
8353 EncodingSpecificOperations();
8354 rotated = ROR(R[m], rotation);
8355 R[d] = SignExtend(rotated<7:0>, 32);
8358 bool success = false;
8360 if (ConditionPassed(opcode)) {
8365 // EncodingSpecificOperations();
8368 // d = UInt(Rd); m = UInt(Rm); rotation = 0;
8369 d = Bits32(opcode, 2, 0);
8370 m = Bits32(opcode, 5, 3);
8376 // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:'000');
8377 d = Bits32(opcode, 11, 8);
8378 m = Bits32(opcode, 3, 0);
8379 rotation = Bits32(opcode, 5, 4) << 3;
8381 // if BadReg(d) || BadReg(m) then UNPREDICTABLE;
8382 if (BadReg(d) || BadReg(m))
8388 // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:'000');
8389 d = Bits32(opcode, 15, 12);
8390 m = Bits32(opcode, 3, 0);
8391 rotation = Bits32(opcode, 11, 10) << 3;
8393 // if d == 15 || m == 15 then UNPREDICTABLE;
8394 if ((d == 15) || (m == 15))
8404 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
8408 // rotated = ROR(R[m], rotation);
8409 uint64_t rotated = ROR(Rm, rotation, &success);
8413 // R[d] = SignExtend(rotated<7:0>, 32);
8414 int64_t data = llvm::SignExtend64<8>(rotated);
8416 RegisterInfo source_reg;
8417 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + m, source_reg);
8419 EmulateInstruction::Context context;
8420 context.type = eContextRegisterLoad;
8421 context.SetRegister(source_reg);
8423 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + d,
8430 // SXTH extracts a 16-bit value from a register, sign-extends it to 32 bits, and
8431 // writes the result to the destination
8432 // register. You can specify a rotation by 0, 8, 16, or 24 bits before
8433 // extracting the 16-bit value.
8434 bool EmulateInstructionARM::EmulateSXTH(const uint32_t opcode,
8435 const ARMEncoding encoding) {
8437 if ConditionPassed() then
8438 EncodingSpecificOperations();
8439 rotated = ROR(R[m], rotation);
8440 R[d] = SignExtend(rotated<15:0>, 32);
8443 bool success = false;
8445 if (ConditionPassed(opcode)) {
8450 // EncodingSpecificOperations();
8453 // d = UInt(Rd); m = UInt(Rm); rotation = 0;
8454 d = Bits32(opcode, 2, 0);
8455 m = Bits32(opcode, 5, 3);
8461 // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:'000');
8462 d = Bits32(opcode, 11, 8);
8463 m = Bits32(opcode, 3, 0);
8464 rotation = Bits32(opcode, 5, 4) << 3;
8466 // if BadReg(d) || BadReg(m) then UNPREDICTABLE;
8467 if (BadReg(d) || BadReg(m))
8473 // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:'000');
8474 d = Bits32(opcode, 15, 12);
8475 m = Bits32(opcode, 3, 0);
8476 rotation = Bits32(opcode, 11, 10) << 3;
8478 // if d == 15 || m == 15 then UNPREDICTABLE;
8479 if ((d == 15) || (m == 15))
8489 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
8493 // rotated = ROR(R[m], rotation);
8494 uint64_t rotated = ROR(Rm, rotation, &success);
8498 // R[d] = SignExtend(rotated<15:0>, 32);
8499 RegisterInfo source_reg;
8500 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + m, source_reg);
8502 EmulateInstruction::Context context;
8503 context.type = eContextRegisterLoad;
8504 context.SetRegister(source_reg);
8506 int64_t data = llvm::SignExtend64<16>(rotated);
8507 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + d,
8515 // UXTB extracts an 8-bit value from a register, zero-extneds it to 32 bits, and
8516 // writes the result to the destination
8517 // register. You can specify a rotation by 0, 8, 16, or 24 bits before
8518 // extracting the 8-bit value.
8519 bool EmulateInstructionARM::EmulateUXTB(const uint32_t opcode,
8520 const ARMEncoding encoding) {
8522 if ConditionPassed() then
8523 EncodingSpecificOperations();
8524 rotated = ROR(R[m], rotation);
8525 R[d] = ZeroExtend(rotated<7:0>, 32);
8528 bool success = false;
8530 if (ConditionPassed(opcode)) {
8535 // EncodingSpecificOperations();
8538 // d = UInt(Rd); m = UInt(Rm); rotation = 0;
8539 d = Bits32(opcode, 2, 0);
8540 m = Bits32(opcode, 5, 3);
8546 // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:'000');
8547 d = Bits32(opcode, 11, 8);
8548 m = Bits32(opcode, 3, 0);
8549 rotation = Bits32(opcode, 5, 4) << 3;
8551 // if BadReg(d) || BadReg(m) then UNPREDICTABLE;
8552 if (BadReg(d) || BadReg(m))
8558 // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:'000');
8559 d = Bits32(opcode, 15, 12);
8560 m = Bits32(opcode, 3, 0);
8561 rotation = Bits32(opcode, 11, 10) << 3;
8563 // if d == 15 || m == 15 then UNPREDICTABLE;
8564 if ((d == 15) || (m == 15))
8574 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
8578 // rotated = ROR(R[m], rotation);
8579 uint64_t rotated = ROR(Rm, rotation, &success);
8583 // R[d] = ZeroExtend(rotated<7:0>, 32);
8584 RegisterInfo source_reg;
8585 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + m, source_reg);
8587 EmulateInstruction::Context context;
8588 context.type = eContextRegisterLoad;
8589 context.SetRegister(source_reg);
8591 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + d,
8592 Bits32(rotated, 7, 0)))
8598 // UXTH extracts a 16-bit value from a register, zero-extends it to 32 bits, and
8599 // writes the result to the destination
8600 // register. You can specify a rotation by 0, 8, 16, or 24 bits before
8601 // extracting the 16-bit value.
8602 bool EmulateInstructionARM::EmulateUXTH(const uint32_t opcode,
8603 const ARMEncoding encoding) {
8605 if ConditionPassed() then
8606 EncodingSpecificOperations();
8607 rotated = ROR(R[m], rotation);
8608 R[d] = ZeroExtend(rotated<15:0>, 32);
8611 bool success = false;
8613 if (ConditionPassed(opcode)) {
8620 // d = UInt(Rd); m = UInt(Rm); rotation = 0;
8621 d = Bits32(opcode, 2, 0);
8622 m = Bits32(opcode, 5, 3);
8628 // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:'000');
8629 d = Bits32(opcode, 11, 8);
8630 m = Bits32(opcode, 3, 0);
8631 rotation = Bits32(opcode, 5, 4) << 3;
8633 // if BadReg(d) || BadReg(m) then UNPREDICTABLE;
8634 if (BadReg(d) || BadReg(m))
8640 // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:'000');
8641 d = Bits32(opcode, 15, 12);
8642 m = Bits32(opcode, 3, 0);
8643 rotation = Bits32(opcode, 11, 10) << 3;
8645 // if d == 15 || m == 15 then UNPREDICTABLE;
8646 if ((d == 15) || (m == 15))
8656 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
8660 // rotated = ROR(R[m], rotation);
8661 uint64_t rotated = ROR(Rm, rotation, &success);
8665 // R[d] = ZeroExtend(rotated<15:0>, 32);
8666 RegisterInfo source_reg;
8667 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + m, source_reg);
8669 EmulateInstruction::Context context;
8670 context.type = eContextRegisterLoad;
8671 context.SetRegister(source_reg);
8673 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + d,
8674 Bits32(rotated, 15, 0)))
8680 // RFE (Return From Exception) loads the PC and the CPSR from the word at the
8681 // specified address and the following
8682 // word respectively.
8683 bool EmulateInstructionARM::EmulateRFE(const uint32_t opcode,
8684 const ARMEncoding encoding) {
8686 if ConditionPassed() then
8687 EncodingSpecificOperations();
8688 if !CurrentModeIsPrivileged() || CurrentInstrSet() == InstrSet_ThumbEE then
8691 address = if increment then R[n] else R[n]-8;
8692 if wordhigher then address = address+4;
8693 CPSRWriteByInstr(MemA[address+4,4], '1111', TRUE);
8694 BranchWritePC(MemA[address,4]);
8695 if wback then R[n] = if increment then R[n]+8 else R[n]-8;
8698 bool success = false;
8700 if (ConditionPassed(opcode)) {
8706 // EncodingSpecificOperations();
8709 // n = UInt(Rn); wback = (W == '1'); increment = FALSE; wordhigher =
8711 n = Bits32(opcode, 19, 16);
8712 wback = BitIsSet(opcode, 21);
8716 // if n == 15 then UNPREDICTABLE;
8720 // if InITBlock() && !LastInITBlock() then UNPREDICTABLE;
8721 if (InITBlock() && !LastInITBlock())
8727 // n = UInt(Rn); wback = (W == '1'); increment = TRUE; wordhigher = FALSE;
8728 n = Bits32(opcode, 19, 16);
8729 wback = BitIsSet(opcode, 21);
8733 // if n == 15 then UNPREDICTABLE;
8737 // if InITBlock() && !LastInITBlock() then UNPREDICTABLE;
8738 if (InITBlock() && !LastInITBlock())
8745 n = Bits32(opcode, 19, 16);
8747 // wback = (W == '1'); inc = (U == '1'); wordhigher = (P == U);
8748 wback = BitIsSet(opcode, 21);
8749 increment = BitIsSet(opcode, 23);
8750 wordhigher = (Bit32(opcode, 24) == Bit32(opcode, 23));
8752 // if n == 15 then UNPREDICTABLE;
8762 // if !CurrentModeIsPrivileged() || CurrentInstrSet() == InstrSet_ThumbEE
8764 if (!CurrentModeIsPrivileged())
8769 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
8774 // address = if increment then R[n] else R[n]-8;
8780 // if wordhigher then address = address+4;
8782 address = address + 4;
8784 // CPSRWriteByInstr(MemA[address+4,4], '1111', TRUE);
8785 RegisterInfo base_reg;
8786 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n, base_reg);
8788 EmulateInstruction::Context context;
8789 context.type = eContextReturnFromException;
8790 context.SetRegisterPlusOffset(base_reg, address - Rn);
8792 uint64_t data = MemARead(context, address + 4, 4, 0, &success);
8796 CPSRWriteByInstr(data, 15, true);
8798 // BranchWritePC(MemA[address,4]);
8799 uint64_t data2 = MemARead(context, address, 4, 0, &success);
8803 BranchWritePC(context, data2);
8805 // if wback then R[n] = if increment then R[n]+8 else R[n]-8;
8807 context.type = eContextAdjustBaseRegister;
8809 context.SetOffset(8);
8810 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n,
8814 context.SetOffset(-8);
8815 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n,
8821 } // if ConditionPassed()
8825 // Bitwise Exclusive OR (immediate) performs a bitwise exclusive OR of a
8826 // register value and an immediate value, and writes the result to the
8827 // destination register. It can optionally update the condition flags based on
8829 bool EmulateInstructionARM::EmulateEORImm(const uint32_t opcode,
8830 const ARMEncoding encoding) {
8832 // ARM pseudo code...
8833 if ConditionPassed() then
8834 EncodingSpecificOperations();
8835 result = R[n] EOR imm32;
8836 if d == 15 then // Can only occur for ARM encoding
8837 ALUWritePC(result); // setflags is always FALSE here
8841 APSR.N = result<31>;
8842 APSR.Z = IsZeroBit(result);
8847 bool success = false;
8849 if (ConditionPassed(opcode)) {
8852 imm32; // the immediate value to be ORed to the value obtained from Rn
8854 uint32_t carry; // the carry bit after ARM/Thumb Expand operation
8857 Rd = Bits32(opcode, 11, 8);
8858 Rn = Bits32(opcode, 19, 16);
8859 setflags = BitIsSet(opcode, 20);
8860 imm32 = ThumbExpandImm_C(
8862 carry); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C)
8863 // if Rd == '1111' && S == '1' then SEE TEQ (immediate);
8864 if (Rd == 15 && setflags)
8865 return EmulateTEQImm(opcode, eEncodingT1);
8866 if (Rd == 13 || (Rd == 15 && !setflags) || BadReg(Rn))
8870 Rd = Bits32(opcode, 15, 12);
8871 Rn = Bits32(opcode, 19, 16);
8872 setflags = BitIsSet(opcode, 20);
8874 ARMExpandImm_C(opcode, APSR_C,
8875 carry); // (imm32, carry) = ARMExpandImm(imm12, APSR.C)
8877 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related
8879 if (Rd == 15 && setflags)
8880 return EmulateSUBSPcLrEtc(opcode, encoding);
8886 // Read the first operand.
8887 uint32_t val1 = ReadCoreReg(Rn, &success);
8891 uint32_t result = val1 ^ imm32;
8893 EmulateInstruction::Context context;
8894 context.type = EmulateInstruction::eContextImmediate;
8895 context.SetNoArgs();
8897 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
8903 // Bitwise Exclusive OR (register) performs a bitwise exclusive OR of a
8904 // register value and an optionally-shifted register value, and writes the
8905 // result to the destination register. It can optionally update the condition
8906 // flags based on the result.
8907 bool EmulateInstructionARM::EmulateEORReg(const uint32_t opcode,
8908 const ARMEncoding encoding) {
8910 // ARM pseudo code...
8911 if ConditionPassed() then
8912 EncodingSpecificOperations();
8913 (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C);
8914 result = R[n] EOR shifted;
8915 if d == 15 then // Can only occur for ARM encoding
8916 ALUWritePC(result); // setflags is always FALSE here
8920 APSR.N = result<31>;
8921 APSR.Z = IsZeroBit(result);
8926 bool success = false;
8928 if (ConditionPassed(opcode)) {
8929 uint32_t Rd, Rn, Rm;
8930 ARM_ShifterType shift_t;
8931 uint32_t shift_n; // the shift applied to the value read from Rm
8936 Rd = Rn = Bits32(opcode, 2, 0);
8937 Rm = Bits32(opcode, 5, 3);
8938 setflags = !InITBlock();
8939 shift_t = SRType_LSL;
8943 Rd = Bits32(opcode, 11, 8);
8944 Rn = Bits32(opcode, 19, 16);
8945 Rm = Bits32(opcode, 3, 0);
8946 setflags = BitIsSet(opcode, 20);
8947 shift_n = DecodeImmShiftThumb(opcode, shift_t);
8948 // if Rd == '1111' && S == '1' then SEE TEQ (register);
8949 if (Rd == 15 && setflags)
8950 return EmulateTEQReg(opcode, eEncodingT1);
8951 if (Rd == 13 || (Rd == 15 && !setflags) || BadReg(Rn) || BadReg(Rm))
8955 Rd = Bits32(opcode, 15, 12);
8956 Rn = Bits32(opcode, 19, 16);
8957 Rm = Bits32(opcode, 3, 0);
8958 setflags = BitIsSet(opcode, 20);
8959 shift_n = DecodeImmShiftARM(opcode, shift_t);
8961 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related
8963 if (Rd == 15 && setflags)
8964 return EmulateSUBSPcLrEtc(opcode, encoding);
8970 // Read the first operand.
8971 uint32_t val1 = ReadCoreReg(Rn, &success);
8975 // Read the second operand.
8976 uint32_t val2 = ReadCoreReg(Rm, &success);
8980 uint32_t shifted = Shift_C(val2, shift_t, shift_n, APSR_C, carry, &success);
8983 uint32_t result = val1 ^ shifted;
8985 EmulateInstruction::Context context;
8986 context.type = EmulateInstruction::eContextImmediate;
8987 context.SetNoArgs();
8989 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
8995 // Bitwise OR (immediate) performs a bitwise (inclusive) OR of a register value
8996 // and an immediate value, and writes the result to the destination register.
8997 // It can optionally update the condition flags based on the result.
8998 bool EmulateInstructionARM::EmulateORRImm(const uint32_t opcode,
8999 const ARMEncoding encoding) {
9001 // ARM pseudo code...
9002 if ConditionPassed() then
9003 EncodingSpecificOperations();
9004 result = R[n] OR imm32;
9005 if d == 15 then // Can only occur for ARM encoding
9006 ALUWritePC(result); // setflags is always FALSE here
9010 APSR.N = result<31>;
9011 APSR.Z = IsZeroBit(result);
9016 bool success = false;
9018 if (ConditionPassed(opcode)) {
9021 imm32; // the immediate value to be ORed to the value obtained from Rn
9023 uint32_t carry; // the carry bit after ARM/Thumb Expand operation
9026 Rd = Bits32(opcode, 11, 8);
9027 Rn = Bits32(opcode, 19, 16);
9028 setflags = BitIsSet(opcode, 20);
9029 imm32 = ThumbExpandImm_C(
9031 carry); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C)
9032 // if Rn == '1111' then SEE MOV (immediate);
9034 return EmulateMOVRdImm(opcode, eEncodingT2);
9035 if (BadReg(Rd) || Rn == 13)
9039 Rd = Bits32(opcode, 15, 12);
9040 Rn = Bits32(opcode, 19, 16);
9041 setflags = BitIsSet(opcode, 20);
9043 ARMExpandImm_C(opcode, APSR_C,
9044 carry); // (imm32, carry) = ARMExpandImm(imm12, APSR.C)
9046 if (Rd == 15 && setflags)
9047 return EmulateSUBSPcLrEtc(opcode, encoding);
9053 // Read the first operand.
9054 uint32_t val1 = ReadCoreReg(Rn, &success);
9058 uint32_t result = val1 | imm32;
9060 EmulateInstruction::Context context;
9061 context.type = EmulateInstruction::eContextImmediate;
9062 context.SetNoArgs();
9064 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
9070 // Bitwise OR (register) performs a bitwise (inclusive) OR of a register value
9071 // and an optionally-shifted register value, and writes the result to the
9072 // destination register. It can optionally update the condition flags based on
9074 bool EmulateInstructionARM::EmulateORRReg(const uint32_t opcode,
9075 const ARMEncoding encoding) {
9077 // ARM pseudo code...
9078 if ConditionPassed() then
9079 EncodingSpecificOperations();
9080 (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C);
9081 result = R[n] OR shifted;
9082 if d == 15 then // Can only occur for ARM encoding
9083 ALUWritePC(result); // setflags is always FALSE here
9087 APSR.N = result<31>;
9088 APSR.Z = IsZeroBit(result);
9093 bool success = false;
9095 if (ConditionPassed(opcode)) {
9096 uint32_t Rd, Rn, Rm;
9097 ARM_ShifterType shift_t;
9098 uint32_t shift_n; // the shift applied to the value read from Rm
9103 Rd = Rn = Bits32(opcode, 2, 0);
9104 Rm = Bits32(opcode, 5, 3);
9105 setflags = !InITBlock();
9106 shift_t = SRType_LSL;
9110 Rd = Bits32(opcode, 11, 8);
9111 Rn = Bits32(opcode, 19, 16);
9112 Rm = Bits32(opcode, 3, 0);
9113 setflags = BitIsSet(opcode, 20);
9114 shift_n = DecodeImmShiftThumb(opcode, shift_t);
9115 // if Rn == '1111' then SEE MOV (register);
9117 return EmulateMOVRdRm(opcode, eEncodingT3);
9118 if (BadReg(Rd) || Rn == 13 || BadReg(Rm))
9122 Rd = Bits32(opcode, 15, 12);
9123 Rn = Bits32(opcode, 19, 16);
9124 Rm = Bits32(opcode, 3, 0);
9125 setflags = BitIsSet(opcode, 20);
9126 shift_n = DecodeImmShiftARM(opcode, shift_t);
9128 if (Rd == 15 && setflags)
9129 return EmulateSUBSPcLrEtc(opcode, encoding);
9135 // Read the first operand.
9136 uint32_t val1 = ReadCoreReg(Rn, &success);
9140 // Read the second operand.
9141 uint32_t val2 = ReadCoreReg(Rm, &success);
9145 uint32_t shifted = Shift_C(val2, shift_t, shift_n, APSR_C, carry, &success);
9148 uint32_t result = val1 | shifted;
9150 EmulateInstruction::Context context;
9151 context.type = EmulateInstruction::eContextImmediate;
9152 context.SetNoArgs();
9154 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
9160 // Reverse Subtract (immediate) subtracts a register value from an immediate
9161 // value, and writes the result to the destination register. It can optionally
9162 // update the condition flags based on the result.
9163 bool EmulateInstructionARM::EmulateRSBImm(const uint32_t opcode,
9164 const ARMEncoding encoding) {
9166 // ARM pseudo code...
9167 if ConditionPassed() then
9168 EncodingSpecificOperations();
9169 (result, carry, overflow) = AddWithCarry(NOT(R[n]), imm32, '1');
9170 if d == 15 then // Can only occur for ARM encoding
9171 ALUWritePC(result); // setflags is always FALSE here
9175 APSR.N = result<31>;
9176 APSR.Z = IsZeroBit(result);
9181 bool success = false;
9183 uint32_t Rd; // the destination register
9184 uint32_t Rn; // the first operand
9187 imm32; // the immediate value to be added to the value obtained from Rn
9190 Rd = Bits32(opcode, 2, 0);
9191 Rn = Bits32(opcode, 5, 3);
9192 setflags = !InITBlock();
9196 Rd = Bits32(opcode, 11, 8);
9197 Rn = Bits32(opcode, 19, 16);
9198 setflags = BitIsSet(opcode, 20);
9199 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8)
9200 if (BadReg(Rd) || BadReg(Rn))
9204 Rd = Bits32(opcode, 15, 12);
9205 Rn = Bits32(opcode, 19, 16);
9206 setflags = BitIsSet(opcode, 20);
9207 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
9209 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related
9211 if (Rd == 15 && setflags)
9212 return EmulateSUBSPcLrEtc(opcode, encoding);
9217 // Read the register value from the operand register Rn.
9218 uint32_t reg_val = ReadCoreReg(Rn, &success);
9222 AddWithCarryResult res = AddWithCarry(~reg_val, imm32, 1);
9224 EmulateInstruction::Context context;
9225 context.type = EmulateInstruction::eContextImmediate;
9226 context.SetNoArgs();
9228 return WriteCoreRegOptionalFlags(context, res.result, Rd, setflags,
9229 res.carry_out, res.overflow);
9232 // Reverse Subtract (register) subtracts a register value from an optionally-
9233 // shifted register value, and writes the result to the destination register.
9234 // It can optionally update the condition flags based on the result.
9235 bool EmulateInstructionARM::EmulateRSBReg(const uint32_t opcode,
9236 const ARMEncoding encoding) {
9238 // ARM pseudo code...
9239 if ConditionPassed() then
9240 EncodingSpecificOperations();
9241 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
9242 (result, carry, overflow) = AddWithCarry(NOT(R[n]), shifted, '1');
9243 if d == 15 then // Can only occur for ARM encoding
9244 ALUWritePC(result); // setflags is always FALSE here
9248 APSR.N = result<31>;
9249 APSR.Z = IsZeroBit(result);
9254 bool success = false;
9256 uint32_t Rd; // the destination register
9257 uint32_t Rn; // the first operand
9258 uint32_t Rm; // the second operand
9260 ARM_ShifterType shift_t;
9261 uint32_t shift_n; // the shift applied to the value read from Rm
9264 Rd = Bits32(opcode, 11, 8);
9265 Rn = Bits32(opcode, 19, 16);
9266 Rm = Bits32(opcode, 3, 0);
9267 setflags = BitIsSet(opcode, 20);
9268 shift_n = DecodeImmShiftThumb(opcode, shift_t);
9269 // if (BadReg(d) || BadReg(m)) then UNPREDICTABLE;
9270 if (BadReg(Rd) || BadReg(Rn) || BadReg(Rm))
9274 Rd = Bits32(opcode, 15, 12);
9275 Rn = Bits32(opcode, 19, 16);
9276 Rm = Bits32(opcode, 3, 0);
9277 setflags = BitIsSet(opcode, 20);
9278 shift_n = DecodeImmShiftARM(opcode, shift_t);
9280 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related
9282 if (Rd == 15 && setflags)
9283 return EmulateSUBSPcLrEtc(opcode, encoding);
9288 // Read the register value from register Rn.
9289 uint32_t val1 = ReadCoreReg(Rn, &success);
9293 // Read the register value from register Rm.
9294 uint32_t val2 = ReadCoreReg(Rm, &success);
9298 uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C, &success);
9301 AddWithCarryResult res = AddWithCarry(~val1, shifted, 1);
9303 EmulateInstruction::Context context;
9304 context.type = EmulateInstruction::eContextImmediate;
9305 context.SetNoArgs();
9306 return WriteCoreRegOptionalFlags(context, res.result, Rd, setflags,
9307 res.carry_out, res.overflow);
9310 // Reverse Subtract with Carry (immediate) subtracts a register value and the
9311 // value of NOT (Carry flag) from an immediate value, and writes the result to
9312 // the destination register. It can optionally update the condition flags based
9314 bool EmulateInstructionARM::EmulateRSCImm(const uint32_t opcode,
9315 const ARMEncoding encoding) {
9317 // ARM pseudo code...
9318 if ConditionPassed() then
9319 EncodingSpecificOperations();
9320 (result, carry, overflow) = AddWithCarry(NOT(R[n]), imm32, APSR.C);
9322 ALUWritePC(result); // setflags is always FALSE here
9326 APSR.N = result<31>;
9327 APSR.Z = IsZeroBit(result);
9332 bool success = false;
9334 uint32_t Rd; // the destination register
9335 uint32_t Rn; // the first operand
9338 imm32; // the immediate value to be added to the value obtained from Rn
9341 Rd = Bits32(opcode, 15, 12);
9342 Rn = Bits32(opcode, 19, 16);
9343 setflags = BitIsSet(opcode, 20);
9344 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
9346 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related
9348 if (Rd == 15 && setflags)
9349 return EmulateSUBSPcLrEtc(opcode, encoding);
9354 // Read the register value from the operand register Rn.
9355 uint32_t reg_val = ReadCoreReg(Rn, &success);
9359 AddWithCarryResult res = AddWithCarry(~reg_val, imm32, APSR_C);
9361 EmulateInstruction::Context context;
9362 context.type = EmulateInstruction::eContextImmediate;
9363 context.SetNoArgs();
9365 return WriteCoreRegOptionalFlags(context, res.result, Rd, setflags,
9366 res.carry_out, res.overflow);
9369 // Reverse Subtract with Carry (register) subtracts a register value and the
9370 // value of NOT (Carry flag) from an optionally-shifted register value, and
9371 // writes the result to the destination register. It can optionally update the
9372 // condition flags based on the result.
9373 bool EmulateInstructionARM::EmulateRSCReg(const uint32_t opcode,
9374 const ARMEncoding encoding) {
9376 // ARM pseudo code...
9377 if ConditionPassed() then
9378 EncodingSpecificOperations();
9379 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
9380 (result, carry, overflow) = AddWithCarry(NOT(R[n]), shifted, APSR.C);
9382 ALUWritePC(result); // setflags is always FALSE here
9386 APSR.N = result<31>;
9387 APSR.Z = IsZeroBit(result);
9392 bool success = false;
9394 uint32_t Rd; // the destination register
9395 uint32_t Rn; // the first operand
9396 uint32_t Rm; // the second operand
9398 ARM_ShifterType shift_t;
9399 uint32_t shift_n; // the shift applied to the value read from Rm
9402 Rd = Bits32(opcode, 15, 12);
9403 Rn = Bits32(opcode, 19, 16);
9404 Rm = Bits32(opcode, 3, 0);
9405 setflags = BitIsSet(opcode, 20);
9406 shift_n = DecodeImmShiftARM(opcode, shift_t);
9408 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related
9410 if (Rd == 15 && setflags)
9411 return EmulateSUBSPcLrEtc(opcode, encoding);
9416 // Read the register value from register Rn.
9417 uint32_t val1 = ReadCoreReg(Rn, &success);
9421 // Read the register value from register Rm.
9422 uint32_t val2 = ReadCoreReg(Rm, &success);
9426 uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C, &success);
9429 AddWithCarryResult res = AddWithCarry(~val1, shifted, APSR_C);
9431 EmulateInstruction::Context context;
9432 context.type = EmulateInstruction::eContextImmediate;
9433 context.SetNoArgs();
9434 return WriteCoreRegOptionalFlags(context, res.result, Rd, setflags,
9435 res.carry_out, res.overflow);
9438 // Subtract with Carry (immediate) subtracts an immediate value and the value
9440 // NOT (Carry flag) from a register value, and writes the result to the
9441 // destination register.
9442 // It can optionally update the condition flags based on the result.
9443 bool EmulateInstructionARM::EmulateSBCImm(const uint32_t opcode,
9444 const ARMEncoding encoding) {
9446 // ARM pseudo code...
9447 if ConditionPassed() then
9448 EncodingSpecificOperations();
9449 (result, carry, overflow) = AddWithCarry(R[n], NOT(imm32), APSR.C);
9450 if d == 15 then // Can only occur for ARM encoding
9451 ALUWritePC(result); // setflags is always FALSE here
9455 APSR.N = result<31>;
9456 APSR.Z = IsZeroBit(result);
9461 bool success = false;
9463 uint32_t Rd; // the destination register
9464 uint32_t Rn; // the first operand
9467 imm32; // the immediate value to be added to the value obtained from Rn
9470 Rd = Bits32(opcode, 11, 8);
9471 Rn = Bits32(opcode, 19, 16);
9472 setflags = BitIsSet(opcode, 20);
9473 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8)
9474 if (BadReg(Rd) || BadReg(Rn))
9478 Rd = Bits32(opcode, 15, 12);
9479 Rn = Bits32(opcode, 19, 16);
9480 setflags = BitIsSet(opcode, 20);
9481 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
9483 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related
9485 if (Rd == 15 && setflags)
9486 return EmulateSUBSPcLrEtc(opcode, encoding);
9491 // Read the register value from the operand register Rn.
9492 uint32_t reg_val = ReadCoreReg(Rn, &success);
9496 AddWithCarryResult res = AddWithCarry(reg_val, ~imm32, APSR_C);
9498 EmulateInstruction::Context context;
9499 context.type = EmulateInstruction::eContextImmediate;
9500 context.SetNoArgs();
9502 return WriteCoreRegOptionalFlags(context, res.result, Rd, setflags,
9503 res.carry_out, res.overflow);
9506 // Subtract with Carry (register) subtracts an optionally-shifted register
9507 // value and the value of
9508 // NOT (Carry flag) from a register value, and writes the result to the
9509 // destination register.
9510 // It can optionally update the condition flags based on the result.
9511 bool EmulateInstructionARM::EmulateSBCReg(const uint32_t opcode,
9512 const ARMEncoding encoding) {
9514 // ARM pseudo code...
9515 if ConditionPassed() then
9516 EncodingSpecificOperations();
9517 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
9518 (result, carry, overflow) = AddWithCarry(R[n], NOT(shifted), APSR.C);
9519 if d == 15 then // Can only occur for ARM encoding
9520 ALUWritePC(result); // setflags is always FALSE here
9524 APSR.N = result<31>;
9525 APSR.Z = IsZeroBit(result);
9530 bool success = false;
9532 uint32_t Rd; // the destination register
9533 uint32_t Rn; // the first operand
9534 uint32_t Rm; // the second operand
9536 ARM_ShifterType shift_t;
9537 uint32_t shift_n; // the shift applied to the value read from Rm
9540 Rd = Rn = Bits32(opcode, 2, 0);
9541 Rm = Bits32(opcode, 5, 3);
9542 setflags = !InITBlock();
9543 shift_t = SRType_LSL;
9547 Rd = Bits32(opcode, 11, 8);
9548 Rn = Bits32(opcode, 19, 16);
9549 Rm = Bits32(opcode, 3, 0);
9550 setflags = BitIsSet(opcode, 20);
9551 shift_n = DecodeImmShiftThumb(opcode, shift_t);
9552 if (BadReg(Rd) || BadReg(Rn) || BadReg(Rm))
9556 Rd = Bits32(opcode, 15, 12);
9557 Rn = Bits32(opcode, 19, 16);
9558 Rm = Bits32(opcode, 3, 0);
9559 setflags = BitIsSet(opcode, 20);
9560 shift_n = DecodeImmShiftARM(opcode, shift_t);
9562 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related
9564 if (Rd == 15 && setflags)
9565 return EmulateSUBSPcLrEtc(opcode, encoding);
9570 // Read the register value from register Rn.
9571 uint32_t val1 = ReadCoreReg(Rn, &success);
9575 // Read the register value from register Rm.
9576 uint32_t val2 = ReadCoreReg(Rm, &success);
9580 uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C, &success);
9583 AddWithCarryResult res = AddWithCarry(val1, ~shifted, APSR_C);
9585 EmulateInstruction::Context context;
9586 context.type = EmulateInstruction::eContextImmediate;
9587 context.SetNoArgs();
9588 return WriteCoreRegOptionalFlags(context, res.result, Rd, setflags,
9589 res.carry_out, res.overflow);
9592 // This instruction subtracts an immediate value from a register value, and
9593 // writes the result to the destination register. It can optionally update the
9594 // condition flags based on the result.
9595 bool EmulateInstructionARM::EmulateSUBImmThumb(const uint32_t opcode,
9596 const ARMEncoding encoding) {
9598 // ARM pseudo code...
9599 if ConditionPassed() then
9600 EncodingSpecificOperations();
9601 (result, carry, overflow) = AddWithCarry(R[n], NOT(imm32), '1');
9604 APSR.N = result<31>;
9605 APSR.Z = IsZeroBit(result);
9610 bool success = false;
9612 uint32_t Rd; // the destination register
9613 uint32_t Rn; // the first operand
9615 uint32_t imm32; // the immediate value to be subtracted from the value
9619 Rd = Bits32(opcode, 2, 0);
9620 Rn = Bits32(opcode, 5, 3);
9621 setflags = !InITBlock();
9622 imm32 = Bits32(opcode, 8, 6); // imm32 = ZeroExtend(imm3, 32)
9625 Rd = Rn = Bits32(opcode, 10, 8);
9626 setflags = !InITBlock();
9627 imm32 = Bits32(opcode, 7, 0); // imm32 = ZeroExtend(imm8, 32)
9630 Rd = Bits32(opcode, 11, 8);
9631 Rn = Bits32(opcode, 19, 16);
9632 setflags = BitIsSet(opcode, 20);
9633 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8)
9635 // if Rd == '1111' && S == '1' then SEE CMP (immediate);
9636 if (Rd == 15 && setflags)
9637 return EmulateCMPImm(opcode, eEncodingT2);
9639 // if Rn == '1101' then SEE SUB (SP minus immediate);
9641 return EmulateSUBSPImm(opcode, eEncodingT2);
9643 // if d == 13 || (d == 15 && S == '0') || n == 15 then UNPREDICTABLE;
9644 if (Rd == 13 || (Rd == 15 && !setflags) || Rn == 15)
9648 Rd = Bits32(opcode, 11, 8);
9649 Rn = Bits32(opcode, 19, 16);
9650 setflags = BitIsSet(opcode, 20);
9651 imm32 = ThumbImm12(opcode); // imm32 = ZeroExtend(i:imm3:imm8, 32)
9653 // if Rn == '1111' then SEE ADR;
9655 return EmulateADR(opcode, eEncodingT2);
9657 // if Rn == '1101' then SEE SUB (SP minus immediate);
9659 return EmulateSUBSPImm(opcode, eEncodingT3);
9667 // Read the register value from the operand register Rn.
9668 uint32_t reg_val = ReadCoreReg(Rn, &success);
9672 AddWithCarryResult res = AddWithCarry(reg_val, ~imm32, 1);
9674 EmulateInstruction::Context context;
9675 context.type = EmulateInstruction::eContextImmediate;
9676 context.SetNoArgs();
9678 return WriteCoreRegOptionalFlags(context, res.result, Rd, setflags,
9679 res.carry_out, res.overflow);
9682 // This instruction subtracts an immediate value from a register value, and
9683 // writes the result to the destination register. It can optionally update the
9684 // condition flags based on the result.
9685 bool EmulateInstructionARM::EmulateSUBImmARM(const uint32_t opcode,
9686 const ARMEncoding encoding) {
9688 // ARM pseudo code...
9689 if ConditionPassed() then
9690 EncodingSpecificOperations();
9691 (result, carry, overflow) = AddWithCarry(R[n], NOT(imm32), '1');
9693 ALUWritePC(result); // setflags is always FALSE here
9697 APSR.N = result<31>;
9698 APSR.Z = IsZeroBit(result);
9703 bool success = false;
9705 if (ConditionPassed(opcode)) {
9706 uint32_t Rd; // the destination register
9707 uint32_t Rn; // the first operand
9709 uint32_t imm32; // the immediate value to be subtracted from the value
9713 Rd = Bits32(opcode, 15, 12);
9714 Rn = Bits32(opcode, 19, 16);
9715 setflags = BitIsSet(opcode, 20);
9716 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
9718 // if Rn == '1111' && S == '0' then SEE ADR;
9719 if (Rn == 15 && !setflags)
9720 return EmulateADR(opcode, eEncodingA2);
9722 // if Rn == '1101' then SEE SUB (SP minus immediate);
9724 return EmulateSUBSPImm(opcode, eEncodingA1);
9726 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related
9728 if (Rd == 15 && setflags)
9729 return EmulateSUBSPcLrEtc(opcode, encoding);
9734 // Read the register value from the operand register Rn.
9735 uint32_t reg_val = ReadCoreReg(Rn, &success);
9739 AddWithCarryResult res = AddWithCarry(reg_val, ~imm32, 1);
9741 EmulateInstruction::Context context;
9743 context.type = EmulateInstruction::eContextAdjustStackPointer;
9745 context.type = EmulateInstruction::eContextRegisterPlusOffset;
9747 RegisterInfo dwarf_reg;
9748 GetRegisterInfo(eRegisterKindDWARF, Rn, dwarf_reg);
9749 int64_t imm32_signed = imm32;
9750 context.SetRegisterPlusOffset(dwarf_reg, -imm32_signed);
9752 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags,
9753 res.carry_out, res.overflow))
9759 // Test Equivalence (immediate) performs a bitwise exclusive OR operation on a
9760 // register value and an immediate value. It updates the condition flags based
9761 // on the result, and discards the result.
9762 bool EmulateInstructionARM::EmulateTEQImm(const uint32_t opcode,
9763 const ARMEncoding encoding) {
9765 // ARM pseudo code...
9766 if ConditionPassed() then
9767 EncodingSpecificOperations();
9768 result = R[n] EOR imm32;
9769 APSR.N = result<31>;
9770 APSR.Z = IsZeroBit(result);
9775 bool success = false;
9777 if (ConditionPassed(opcode)) {
9780 imm32; // the immediate value to be ANDed to the value obtained from Rn
9781 uint32_t carry; // the carry bit after ARM/Thumb Expand operation
9784 Rn = Bits32(opcode, 19, 16);
9785 imm32 = ThumbExpandImm_C(
9787 carry); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C)
9792 Rn = Bits32(opcode, 19, 16);
9794 ARMExpandImm_C(opcode, APSR_C,
9795 carry); // (imm32, carry) = ARMExpandImm(imm12, APSR.C)
9801 // Read the first operand.
9802 uint32_t val1 = ReadCoreReg(Rn, &success);
9806 uint32_t result = val1 ^ imm32;
9808 EmulateInstruction::Context context;
9809 context.type = EmulateInstruction::eContextImmediate;
9810 context.SetNoArgs();
9812 if (!WriteFlags(context, result, carry))
9818 // Test Equivalence (register) performs a bitwise exclusive OR operation on a
9819 // register value and an optionally-shifted register value. It updates the
9820 // condition flags based on the result, and discards the result.
9821 bool EmulateInstructionARM::EmulateTEQReg(const uint32_t opcode,
9822 const ARMEncoding encoding) {
9824 // ARM pseudo code...
9825 if ConditionPassed() then
9826 EncodingSpecificOperations();
9827 (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C);
9828 result = R[n] EOR shifted;
9829 APSR.N = result<31>;
9830 APSR.Z = IsZeroBit(result);
9835 bool success = false;
9837 if (ConditionPassed(opcode)) {
9839 ARM_ShifterType shift_t;
9840 uint32_t shift_n; // the shift applied to the value read from Rm
9844 Rn = Bits32(opcode, 19, 16);
9845 Rm = Bits32(opcode, 3, 0);
9846 shift_n = DecodeImmShiftThumb(opcode, shift_t);
9847 if (BadReg(Rn) || BadReg(Rm))
9851 Rn = Bits32(opcode, 19, 16);
9852 Rm = Bits32(opcode, 3, 0);
9853 shift_n = DecodeImmShiftARM(opcode, shift_t);
9859 // Read the first operand.
9860 uint32_t val1 = ReadCoreReg(Rn, &success);
9864 // Read the second operand.
9865 uint32_t val2 = ReadCoreReg(Rm, &success);
9869 uint32_t shifted = Shift_C(val2, shift_t, shift_n, APSR_C, carry, &success);
9872 uint32_t result = val1 ^ shifted;
9874 EmulateInstruction::Context context;
9875 context.type = EmulateInstruction::eContextImmediate;
9876 context.SetNoArgs();
9878 if (!WriteFlags(context, result, carry))
9884 // Test (immediate) performs a bitwise AND operation on a register value and an
9885 // immediate value. It updates the condition flags based on the result, and
9886 // discards the result.
9887 bool EmulateInstructionARM::EmulateTSTImm(const uint32_t opcode,
9888 const ARMEncoding encoding) {
9890 // ARM pseudo code...
9891 if ConditionPassed() then
9892 EncodingSpecificOperations();
9893 result = R[n] AND imm32;
9894 APSR.N = result<31>;
9895 APSR.Z = IsZeroBit(result);
9900 bool success = false;
9902 if (ConditionPassed(opcode)) {
9905 imm32; // the immediate value to be ANDed to the value obtained from Rn
9906 uint32_t carry; // the carry bit after ARM/Thumb Expand operation
9909 Rn = Bits32(opcode, 19, 16);
9910 imm32 = ThumbExpandImm_C(
9912 carry); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C)
9917 Rn = Bits32(opcode, 19, 16);
9919 ARMExpandImm_C(opcode, APSR_C,
9920 carry); // (imm32, carry) = ARMExpandImm(imm12, APSR.C)
9926 // Read the first operand.
9927 uint32_t val1 = ReadCoreReg(Rn, &success);
9931 uint32_t result = val1 & imm32;
9933 EmulateInstruction::Context context;
9934 context.type = EmulateInstruction::eContextImmediate;
9935 context.SetNoArgs();
9937 if (!WriteFlags(context, result, carry))
9943 // Test (register) performs a bitwise AND operation on a register value and an
9944 // optionally-shifted register value. It updates the condition flags based on
9945 // the result, and discards the result.
9946 bool EmulateInstructionARM::EmulateTSTReg(const uint32_t opcode,
9947 const ARMEncoding encoding) {
9949 // ARM pseudo code...
9950 if ConditionPassed() then
9951 EncodingSpecificOperations();
9952 (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C);
9953 result = R[n] AND shifted;
9954 APSR.N = result<31>;
9955 APSR.Z = IsZeroBit(result);
9960 bool success = false;
9962 if (ConditionPassed(opcode)) {
9964 ARM_ShifterType shift_t;
9965 uint32_t shift_n; // the shift applied to the value read from Rm
9969 Rn = Bits32(opcode, 2, 0);
9970 Rm = Bits32(opcode, 5, 3);
9971 shift_t = SRType_LSL;
9975 Rn = Bits32(opcode, 19, 16);
9976 Rm = Bits32(opcode, 3, 0);
9977 shift_n = DecodeImmShiftThumb(opcode, shift_t);
9978 if (BadReg(Rn) || BadReg(Rm))
9982 Rn = Bits32(opcode, 19, 16);
9983 Rm = Bits32(opcode, 3, 0);
9984 shift_n = DecodeImmShiftARM(opcode, shift_t);
9990 // Read the first operand.
9991 uint32_t val1 = ReadCoreReg(Rn, &success);
9995 // Read the second operand.
9996 uint32_t val2 = ReadCoreReg(Rm, &success);
10000 uint32_t shifted = Shift_C(val2, shift_t, shift_n, APSR_C, carry, &success);
10003 uint32_t result = val1 & shifted;
10005 EmulateInstruction::Context context;
10006 context.type = EmulateInstruction::eContextImmediate;
10007 context.SetNoArgs();
10009 if (!WriteFlags(context, result, carry))
10015 // A8.6.216 SUB (SP minus register)
10016 bool EmulateInstructionARM::EmulateSUBSPReg(const uint32_t opcode,
10017 const ARMEncoding encoding) {
10019 if ConditionPassed() then
10020 EncodingSpecificOperations();
10021 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
10022 (result, carry, overflow) = AddWithCarry(SP, NOT(shifted), '1');
10023 if d == 15 then // Can only occur for ARM encoding
10024 ALUWritePC(result); // setflags is always FALSE here
10028 APSR.N = result<31>;
10029 APSR.Z = IsZeroBit(result);
10034 bool success = false;
10036 if (ConditionPassed(opcode)) {
10040 ARM_ShifterType shift_t;
10043 switch (encoding) {
10045 // d = UInt(Rd); m = UInt(Rm); setflags = (S == '1');
10046 d = Bits32(opcode, 11, 8);
10047 m = Bits32(opcode, 3, 0);
10048 setflags = BitIsSet(opcode, 20);
10050 // (shift_t, shift_n) = DecodeImmShift(type, imm3:imm2);
10051 shift_n = DecodeImmShiftThumb(opcode, shift_t);
10053 // if d == 13 && (shift_t != SRType_LSL || shift_n > 3) then
10055 if ((d == 13) && ((shift_t != SRType_LSL) || (shift_n > 3)))
10058 // if d == 15 || BadReg(m) then UNPREDICTABLE;
10059 if ((d == 15) || BadReg(m))
10064 // d = UInt(Rd); m = UInt(Rm); setflags = (S == '1');
10065 d = Bits32(opcode, 15, 12);
10066 m = Bits32(opcode, 3, 0);
10067 setflags = BitIsSet(opcode, 20);
10069 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related
10071 if (d == 15 && setflags)
10072 EmulateSUBSPcLrEtc(opcode, encoding);
10074 // (shift_t, shift_n) = DecodeImmShift(type, imm5);
10075 shift_n = DecodeImmShiftARM(opcode, shift_t);
10082 // shifted = Shift(R[m], shift_t, shift_n, APSR.C);
10083 uint32_t Rm = ReadCoreReg(m, &success);
10087 uint32_t shifted = Shift(Rm, shift_t, shift_n, APSR_C, &success);
10091 // (result, carry, overflow) = AddWithCarry(SP, NOT(shifted), '1');
10092 uint32_t sp_val = ReadCoreReg(SP_REG, &success);
10096 AddWithCarryResult res = AddWithCarry(sp_val, ~shifted, 1);
10098 EmulateInstruction::Context context;
10099 context.type = eContextArithmetic;
10100 RegisterInfo sp_reg;
10101 GetRegisterInfo(eRegisterKindDWARF, dwarf_sp, sp_reg);
10102 RegisterInfo dwarf_reg;
10103 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + m, dwarf_reg);
10104 context.SetRegisterRegisterOperands(sp_reg, dwarf_reg);
10106 if (!WriteCoreRegOptionalFlags(context, res.result, dwarf_r0 + d, setflags,
10107 res.carry_out, res.overflow))
10113 // A8.6.7 ADD (register-shifted register)
10114 bool EmulateInstructionARM::EmulateADDRegShift(const uint32_t opcode,
10115 const ARMEncoding encoding) {
10117 if ConditionPassed() then
10118 EncodingSpecificOperations();
10119 shift_n = UInt(R[s]<7:0>);
10120 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
10121 (result, carry, overflow) = AddWithCarry(R[n], shifted, '0');
10124 APSR.N = result<31>;
10125 APSR.Z = IsZeroBit(result);
10130 bool success = false;
10132 if (ConditionPassed(opcode)) {
10138 ARM_ShifterType shift_t;
10140 switch (encoding) {
10142 // d = UInt(Rd); n = UInt(Rn); m = UInt(Rm); s = UInt(Rs);
10143 d = Bits32(opcode, 15, 12);
10144 n = Bits32(opcode, 19, 16);
10145 m = Bits32(opcode, 3, 0);
10146 s = Bits32(opcode, 11, 8);
10148 // setflags = (S == '1'); shift_t = DecodeRegShift(type);
10149 setflags = BitIsSet(opcode, 20);
10150 shift_t = DecodeRegShift(Bits32(opcode, 6, 5));
10152 // if d == 15 || n == 15 || m == 15 || s == 15 then UNPREDICTABLE;
10153 if ((d == 15) || (n == 15) || (m == 15) || (s == 15))
10161 // shift_n = UInt(R[s]<7:0>);
10162 uint32_t Rs = ReadCoreReg(s, &success);
10166 uint32_t shift_n = Bits32(Rs, 7, 0);
10168 // shifted = Shift(R[m], shift_t, shift_n, APSR.C);
10169 uint32_t Rm = ReadCoreReg(m, &success);
10173 uint32_t shifted = Shift(Rm, shift_t, shift_n, APSR_C, &success);
10177 // (result, carry, overflow) = AddWithCarry(R[n], shifted, '0');
10178 uint32_t Rn = ReadCoreReg(n, &success);
10182 AddWithCarryResult res = AddWithCarry(Rn, shifted, 0);
10185 EmulateInstruction::Context context;
10186 context.type = eContextArithmetic;
10187 RegisterInfo reg_n;
10188 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n, reg_n);
10189 RegisterInfo reg_m;
10190 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + m, reg_m);
10192 context.SetRegisterRegisterOperands(reg_n, reg_m);
10194 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + d,
10198 // if setflags then
10199 // APSR.N = result<31>;
10200 // APSR.Z = IsZeroBit(result);
10202 // APSR.V = overflow;
10204 return WriteFlags(context, res.result, res.carry_out, res.overflow);
10209 // A8.6.213 SUB (register)
10210 bool EmulateInstructionARM::EmulateSUBReg(const uint32_t opcode,
10211 const ARMEncoding encoding) {
10213 if ConditionPassed() then
10214 EncodingSpecificOperations();
10215 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
10216 (result, carry, overflow) = AddWithCarry(R[n], NOT(shifted), '1');
10217 if d == 15 then // Can only occur for ARM encoding
10218 ALUWritePC(result); // setflags is always FALSE here
10222 APSR.N = result<31>;
10223 APSR.Z = IsZeroBit(result);
10228 bool success = false;
10230 if (ConditionPassed(opcode)) {
10235 ARM_ShifterType shift_t;
10238 switch (encoding) {
10240 // d = UInt(Rd); n = UInt(Rn); m = UInt(Rm); setflags = !InITBlock();
10241 d = Bits32(opcode, 2, 0);
10242 n = Bits32(opcode, 5, 3);
10243 m = Bits32(opcode, 8, 6);
10244 setflags = !InITBlock();
10246 // (shift_t, shift_n) = (SRType_LSL, 0);
10247 shift_t = SRType_LSL;
10253 // d = UInt(Rd); n = UInt(Rn); m = UInt(Rm); setflags = (S =="1");
10254 d = Bits32(opcode, 11, 8);
10255 n = Bits32(opcode, 19, 16);
10256 m = Bits32(opcode, 3, 0);
10257 setflags = BitIsSet(opcode, 20);
10259 // if Rd == "1111" && S == "1" then SEE CMP (register);
10260 if (d == 15 && setflags == 1)
10261 return EmulateCMPImm(opcode, eEncodingT3);
10263 // if Rn == "1101" then SEE SUB (SP minus register);
10265 return EmulateSUBSPReg(opcode, eEncodingT1);
10267 // (shift_t, shift_n) = DecodeImmShift(type, imm3:imm2);
10268 shift_n = DecodeImmShiftThumb(opcode, shift_t);
10270 // if d == 13 || (d == 15 && S == '0') || n == 15 || BadReg(m) then
10272 if ((d == 13) || ((d == 15) && BitIsClear(opcode, 20)) || (n == 15) ||
10279 // if Rn == '1101' then SEE SUB (SP minus register);
10280 // d = UInt(Rd); n = UInt(Rn); m = UInt(Rm); setflags = (S == '1');
10281 d = Bits32(opcode, 15, 12);
10282 n = Bits32(opcode, 19, 16);
10283 m = Bits32(opcode, 3, 0);
10284 setflags = BitIsSet(opcode, 20);
10286 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related
10288 if ((d == 15) && setflags)
10289 EmulateSUBSPcLrEtc(opcode, encoding);
10291 // (shift_t, shift_n) = DecodeImmShift(type, imm5);
10292 shift_n = DecodeImmShiftARM(opcode, shift_t);
10300 // shifted = Shift(R[m], shift_t, shift_n, APSR.C);
10301 uint32_t Rm = ReadCoreReg(m, &success);
10305 uint32_t shifted = Shift(Rm, shift_t, shift_n, APSR_C, &success);
10309 // (result, carry, overflow) = AddWithCarry(R[n], NOT(shifted), '1');
10310 uint32_t Rn = ReadCoreReg(n, &success);
10314 AddWithCarryResult res = AddWithCarry(Rn, ~shifted, 1);
10316 // if d == 15 then // Can only occur for ARM encoding ALUWritePC(result);
10317 // // setflags is always FALSE here else
10319 // if setflags then
10320 // APSR.N = result<31>;
10321 // APSR.Z = IsZeroBit(result);
10323 // APSR.V = overflow;
10325 EmulateInstruction::Context context;
10326 context.type = eContextArithmetic;
10327 RegisterInfo reg_n;
10328 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n, reg_n);
10329 RegisterInfo reg_m;
10330 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + m, reg_m);
10331 context.SetRegisterRegisterOperands(reg_n, reg_m);
10333 if (!WriteCoreRegOptionalFlags(context, res.result, dwarf_r0 + d, setflags,
10334 res.carry_out, res.overflow))
10341 // Store Register Exclusive calculates an address from a base register value
10342 // and an immediate offset, and stores a word from a register to memory if the
10343 // executing processor has exclusive access to the memory addressed.
10344 bool EmulateInstructionARM::EmulateSTREX(const uint32_t opcode,
10345 const ARMEncoding encoding) {
10347 if ConditionPassed() then
10348 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
10349 address = R[n] + imm32;
10350 if ExclusiveMonitorsPass(address,4) then
10351 MemA[address,4] = R[t];
10357 bool success = false;
10359 if (ConditionPassed(opcode)) {
10364 const uint32_t addr_byte_size = GetAddressByteSize();
10366 switch (encoding) {
10368 // d = UInt(Rd); t = UInt(Rt); n = UInt(Rn); imm32 =
10369 // ZeroExtend(imm8:'00',
10371 d = Bits32(opcode, 11, 8);
10372 t = Bits32(opcode, 15, 12);
10373 n = Bits32(opcode, 19, 16);
10374 imm32 = Bits32(opcode, 7, 0) << 2;
10376 // if BadReg(d) || BadReg(t) || n == 15 then UNPREDICTABLE;
10377 if (BadReg(d) || BadReg(t) || (n == 15))
10380 // if d == n || d == t then UNPREDICTABLE;
10381 if ((d == n) || (d == t))
10387 // d = UInt(Rd); t = UInt(Rt); n = UInt(Rn); imm32 = Zeros(32); // Zero
10389 d = Bits32(opcode, 15, 12);
10390 t = Bits32(opcode, 3, 0);
10391 n = Bits32(opcode, 19, 16);
10394 // if d == 15 || t == 15 || n == 15 then UNPREDICTABLE;
10395 if ((d == 15) || (t == 15) || (n == 15))
10398 // if d == n || d == t then UNPREDICTABLE;
10399 if ((d == n) || (d == t))
10408 // address = R[n] + imm32;
10409 uint32_t Rn = ReadCoreReg(n, &success);
10413 addr_t address = Rn + imm32;
10415 RegisterInfo base_reg;
10416 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n, base_reg);
10417 RegisterInfo data_reg;
10418 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + t, data_reg);
10419 EmulateInstruction::Context context;
10420 context.type = eContextRegisterStore;
10421 context.SetRegisterToRegisterPlusOffset(data_reg, base_reg, imm32);
10423 // if ExclusiveMonitorsPass(address,4) then if (ExclusiveMonitorsPass
10424 // (address, addr_byte_size)) -- For now, for the sake of emulation, we
10429 // MemA[address,4] = R[t];
10431 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + t, 0, &success);
10435 if (!MemAWrite(context, address, Rt, addr_byte_size))
10439 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + t, 0))
10442 #if 0 // unreachable because if true
10446 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, 1))
10449 #endif // unreachable because if true
10454 // A8.6.197 STRB (immediate, ARM)
10455 bool EmulateInstructionARM::EmulateSTRBImmARM(const uint32_t opcode,
10456 const ARMEncoding encoding) {
10458 if ConditionPassed() then
10459 EncodingSpecificOperations();
10460 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
10461 address = if index then offset_addr else R[n];
10462 MemU[address,1] = R[t]<7:0>;
10463 if wback then R[n] = offset_addr;
10466 bool success = false;
10468 if (ConditionPassed(opcode)) {
10476 switch (encoding) {
10478 // if P == '0' && W == '1' then SEE STRBT;
10479 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
10480 t = Bits32(opcode, 15, 12);
10481 n = Bits32(opcode, 19, 16);
10482 imm32 = Bits32(opcode, 11, 0);
10484 // index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1');
10485 index = BitIsSet(opcode, 24);
10486 add = BitIsSet(opcode, 23);
10487 wback = BitIsClear(opcode, 24) || BitIsSet(opcode, 21);
10489 // if t == 15 then UNPREDICTABLE;
10493 // if wback && (n == 15 || n == t) then UNPREDICTABLE;
10494 if (wback && ((n == 15) || (n == t)))
10503 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
10504 uint32_t Rn = ReadCoreReg(n, &success);
10508 addr_t offset_addr;
10510 offset_addr = Rn + imm32;
10512 offset_addr = Rn - imm32;
10514 // address = if index then offset_addr else R[n];
10517 address = offset_addr;
10521 // MemU[address,1] = R[t]<7:0>;
10522 uint32_t Rt = ReadCoreReg(t, &success);
10526 RegisterInfo base_reg;
10527 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n, base_reg);
10528 RegisterInfo data_reg;
10529 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + t, data_reg);
10530 EmulateInstruction::Context context;
10531 context.type = eContextRegisterStore;
10532 context.SetRegisterToRegisterPlusOffset(data_reg, base_reg, address - Rn);
10534 if (!MemUWrite(context, address, Bits32(Rt, 7, 0), 1))
10537 // if wback then R[n] = offset_addr;
10539 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n,
10547 // A8.6.194 STR (immediate, ARM)
10548 bool EmulateInstructionARM::EmulateSTRImmARM(const uint32_t opcode,
10549 const ARMEncoding encoding) {
10551 if ConditionPassed() then
10552 EncodingSpecificOperations();
10553 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
10554 address = if index then offset_addr else R[n];
10555 MemU[address,4] = if t == 15 then PCStoreValue() else R[t];
10556 if wback then R[n] = offset_addr;
10559 bool success = false;
10561 if (ConditionPassed(opcode)) {
10569 const uint32_t addr_byte_size = GetAddressByteSize();
10571 switch (encoding) {
10573 // if P == '0' && W == '1' then SEE STRT;
10574 // if Rn == '1101' && P == '1' && U == '0' && W == '1' && imm12 ==
10575 // '000000000100' then SEE PUSH;
10576 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
10577 t = Bits32(opcode, 15, 12);
10578 n = Bits32(opcode, 19, 16);
10579 imm32 = Bits32(opcode, 11, 0);
10581 // index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1');
10582 index = BitIsSet(opcode, 24);
10583 add = BitIsSet(opcode, 23);
10584 wback = BitIsClear(opcode, 24) || BitIsSet(opcode, 21);
10586 // if wback && (n == 15 || n == t) then UNPREDICTABLE;
10587 if (wback && ((n == 15) || (n == t)))
10596 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
10597 uint32_t Rn = ReadCoreReg(n, &success);
10601 addr_t offset_addr;
10603 offset_addr = Rn + imm32;
10605 offset_addr = Rn - imm32;
10607 // address = if index then offset_addr else R[n];
10610 address = offset_addr;
10614 RegisterInfo base_reg;
10615 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n, base_reg);
10616 RegisterInfo data_reg;
10617 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + t, data_reg);
10618 EmulateInstruction::Context context;
10619 context.type = eContextRegisterStore;
10620 context.SetRegisterToRegisterPlusOffset(data_reg, base_reg, address - Rn);
10622 // MemU[address,4] = if t == 15 then PCStoreValue() else R[t];
10623 uint32_t Rt = ReadCoreReg(t, &success);
10628 uint32_t pc_value = ReadCoreReg(PC_REG, &success);
10632 if (!MemUWrite(context, address, pc_value, addr_byte_size))
10635 if (!MemUWrite(context, address, Rt, addr_byte_size))
10639 // if wback then R[n] = offset_addr;
10641 context.type = eContextAdjustBaseRegister;
10642 context.SetImmediate(offset_addr);
10644 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n,
10652 // A8.6.66 LDRD (immediate)
10653 // Load Register Dual (immediate) calculates an address from a base register
10654 // value and an immediate offset, loads two words from memory, and writes them
10655 // to two registers. It can use offset, post-indexed, or pre-indexed
10657 bool EmulateInstructionARM::EmulateLDRDImmediate(const uint32_t opcode,
10658 const ARMEncoding encoding) {
10660 if ConditionPassed() then
10661 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
10662 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
10663 address = if index then offset_addr else R[n];
10664 R[t] = MemA[address,4];
10665 R[t2] = MemA[address+4,4];
10666 if wback then R[n] = offset_addr;
10669 bool success = false;
10671 if (ConditionPassed(opcode)) {
10680 switch (encoding) {
10682 // if P == '0' && W == '0' then SEE 'Related encodings';
10683 // if Rn == '1111' then SEE LDRD (literal);
10684 // t = UInt(Rt); t2 = UInt(Rt2); n = UInt(Rn); imm32 =
10685 // ZeroExtend(imm8:'00', 32);
10686 t = Bits32(opcode, 15, 12);
10687 t2 = Bits32(opcode, 11, 8);
10688 n = Bits32(opcode, 19, 16);
10689 imm32 = Bits32(opcode, 7, 0) << 2;
10691 // index = (P == '1'); add = (U == '1'); wback = (W == '1');
10692 index = BitIsSet(opcode, 24);
10693 add = BitIsSet(opcode, 23);
10694 wback = BitIsSet(opcode, 21);
10696 // if wback && (n == t || n == t2) then UNPREDICTABLE;
10697 if (wback && ((n == t) || (n == t2)))
10700 // if BadReg(t) || BadReg(t2) || t == t2 then UNPREDICTABLE;
10701 if (BadReg(t) || BadReg(t2) || (t == t2))
10707 // if Rn == '1111' then SEE LDRD (literal);
10708 // if Rt<0> == '1' then UNPREDICTABLE;
10709 // t = UInt(Rt); t2 = t+1; n = UInt(Rn); imm32 = ZeroExtend(imm4H:imm4L,
10711 t = Bits32(opcode, 15, 12);
10712 if (BitIsSet(t, 0))
10715 n = Bits32(opcode, 19, 16);
10716 imm32 = (Bits32(opcode, 11, 8) << 4) | Bits32(opcode, 3, 0);
10718 // index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1');
10719 index = BitIsSet(opcode, 24);
10720 add = BitIsSet(opcode, 23);
10721 wback = BitIsClear(opcode, 24) || BitIsSet(opcode, 21);
10723 // if P == '0' && W == '1' then UNPREDICTABLE;
10724 if (BitIsClear(opcode, 24) && BitIsSet(opcode, 21))
10727 // if wback && (n == t || n == t2) then UNPREDICTABLE;
10728 if (wback && ((n == t) || (n == t2)))
10731 // if t2 == 15 then UNPREDICTABLE;
10741 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
10742 uint32_t Rn = ReadCoreReg(n, &success);
10746 addr_t offset_addr;
10748 offset_addr = Rn + imm32;
10750 offset_addr = Rn - imm32;
10752 // address = if index then offset_addr else R[n];
10755 address = offset_addr;
10759 // R[t] = MemA[address,4];
10760 RegisterInfo base_reg;
10761 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n, base_reg);
10763 EmulateInstruction::Context context;
10765 context.type = eContextPopRegisterOffStack;
10767 context.type = eContextRegisterLoad;
10768 context.SetAddress(address);
10770 const uint32_t addr_byte_size = GetAddressByteSize();
10771 uint32_t data = MemARead(context, address, addr_byte_size, 0, &success);
10775 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + t, data))
10778 // R[t2] = MemA[address+4,4];
10779 context.SetAddress(address + 4);
10780 data = MemARead(context, address + 4, addr_byte_size, 0, &success);
10784 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + t2,
10788 // if wback then R[n] = offset_addr;
10790 context.type = eContextAdjustBaseRegister;
10791 context.SetAddress(offset_addr);
10793 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n,
10801 // A8.6.68 LDRD (register)
10802 // Load Register Dual (register) calculates an address from a base register
10803 // value and a register offset, loads two words from memory, and writes them to
10804 // two registers. It can use offset, post-indexed or pre-indexed addressing.
10805 bool EmulateInstructionARM::EmulateLDRDRegister(const uint32_t opcode,
10806 const ARMEncoding encoding) {
10808 if ConditionPassed() then
10809 EncodingSpecificOperations();
10810 offset_addr = if add then (R[n] + R[m]) else (R[n] - R[m]);
10811 address = if index then offset_addr else R[n];
10812 R[t] = MemA[address,4];
10813 R[t2] = MemA[address+4,4];
10814 if wback then R[n] = offset_addr;
10817 bool success = false;
10819 if (ConditionPassed(opcode)) {
10828 switch (encoding) {
10830 // if Rt<0> == '1' then UNPREDICTABLE;
10831 // t = UInt(Rt); t2 = t+1; n = UInt(Rn); m = UInt(Rm);
10832 t = Bits32(opcode, 15, 12);
10833 if (BitIsSet(t, 0))
10836 n = Bits32(opcode, 19, 16);
10837 m = Bits32(opcode, 3, 0);
10839 // index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1');
10840 index = BitIsSet(opcode, 24);
10841 add = BitIsSet(opcode, 23);
10842 wback = BitIsClear(opcode, 24) || BitIsSet(opcode, 21);
10844 // if P == '0' && W == '1' then UNPREDICTABLE;
10845 if (BitIsClear(opcode, 24) && BitIsSet(opcode, 21))
10848 // if t2 == 15 || m == 15 || m == t || m == t2 then UNPREDICTABLE;
10849 if ((t2 == 15) || (m == 15) || (m == t) || (m == t2))
10852 // if wback && (n == 15 || n == t || n == t2) then UNPREDICTABLE;
10853 if (wback && ((n == 15) || (n == t) || (n == t2)))
10856 // if ArchVersion() < 6 && wback && m == n then UNPREDICTABLE;
10857 if ((ArchVersion() < 6) && wback && (m == n))
10865 uint32_t Rn = ReadCoreReg(n, &success);
10868 RegisterInfo base_reg;
10869 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n, base_reg);
10871 uint32_t Rm = ReadCoreReg(m, &success);
10874 RegisterInfo offset_reg;
10875 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + m, offset_reg);
10877 // offset_addr = if add then (R[n] + R[m]) else (R[n] - R[m]);
10878 addr_t offset_addr;
10880 offset_addr = Rn + Rm;
10882 offset_addr = Rn - Rm;
10884 // address = if index then offset_addr else R[n];
10887 address = offset_addr;
10891 EmulateInstruction::Context context;
10893 context.type = eContextPopRegisterOffStack;
10895 context.type = eContextRegisterLoad;
10896 context.SetAddress(address);
10898 // R[t] = MemA[address,4];
10899 const uint32_t addr_byte_size = GetAddressByteSize();
10900 uint32_t data = MemARead(context, address, addr_byte_size, 0, &success);
10904 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + t, data))
10907 // R[t2] = MemA[address+4,4];
10909 data = MemARead(context, address + 4, addr_byte_size, 0, &success);
10913 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + t2,
10917 // if wback then R[n] = offset_addr;
10919 context.type = eContextAdjustBaseRegister;
10920 context.SetAddress(offset_addr);
10922 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n,
10930 // A8.6.200 STRD (immediate)
10931 // Store Register Dual (immediate) calculates an address from a base register
10932 // value and an immediate offset, and stores two words from two registers to
10933 // memory. It can use offset, post-indexed, or pre-indexed addressing.
10934 bool EmulateInstructionARM::EmulateSTRDImm(const uint32_t opcode,
10935 const ARMEncoding encoding) {
10937 if ConditionPassed() then
10938 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
10939 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
10940 address = if index then offset_addr else R[n];
10941 MemA[address,4] = R[t];
10942 MemA[address+4,4] = R[t2];
10943 if wback then R[n] = offset_addr;
10946 bool success = false;
10948 if (ConditionPassed(opcode)) {
10957 switch (encoding) {
10959 // if P == '0' && W == '0' then SEE 'Related encodings';
10960 // t = UInt(Rt); t2 = UInt(Rt2); n = UInt(Rn); imm32 =
10961 // ZeroExtend(imm8:'00', 32);
10962 t = Bits32(opcode, 15, 12);
10963 t2 = Bits32(opcode, 11, 8);
10964 n = Bits32(opcode, 19, 16);
10965 imm32 = Bits32(opcode, 7, 0) << 2;
10967 // index = (P == '1'); add = (U == '1'); wback = (W == '1');
10968 index = BitIsSet(opcode, 24);
10969 add = BitIsSet(opcode, 23);
10970 wback = BitIsSet(opcode, 21);
10972 // if wback && (n == t || n == t2) then UNPREDICTABLE;
10973 if (wback && ((n == t) || (n == t2)))
10976 // if n == 15 || BadReg(t) || BadReg(t2) then UNPREDICTABLE;
10977 if ((n == 15) || BadReg(t) || BadReg(t2))
10983 // if Rt<0> == '1' then UNPREDICTABLE;
10984 // t = UInt(Rt); t2 = t+1; n = UInt(Rn); imm32 = ZeroExtend(imm4H:imm4L,
10986 t = Bits32(opcode, 15, 12);
10987 if (BitIsSet(t, 0))
10991 n = Bits32(opcode, 19, 16);
10992 imm32 = (Bits32(opcode, 11, 8) << 4) | Bits32(opcode, 3, 0);
10994 // index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1');
10995 index = BitIsSet(opcode, 24);
10996 add = BitIsSet(opcode, 23);
10997 wback = BitIsClear(opcode, 24) || BitIsSet(opcode, 21);
10999 // if P == '0' && W == '1' then UNPREDICTABLE;
11000 if (BitIsClear(opcode, 24) && BitIsSet(opcode, 21))
11003 // if wback && (n == 15 || n == t || n == t2) then UNPREDICTABLE;
11004 if (wback && ((n == 15) || (n == t) || (n == t2)))
11007 // if t2 == 15 then UNPREDICTABLE;
11017 RegisterInfo base_reg;
11018 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n, base_reg);
11020 uint32_t Rn = ReadCoreReg(n, &success);
11024 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
11025 addr_t offset_addr;
11027 offset_addr = Rn + imm32;
11029 offset_addr = Rn - imm32;
11031 // address = if index then offset_addr else R[n];
11034 address = offset_addr;
11038 // MemA[address,4] = R[t];
11039 RegisterInfo data_reg;
11040 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + t, data_reg);
11042 uint32_t data = ReadCoreReg(t, &success);
11046 EmulateInstruction::Context context;
11048 context.type = eContextPushRegisterOnStack;
11050 context.type = eContextRegisterStore;
11051 context.SetRegisterToRegisterPlusOffset(data_reg, base_reg, address - Rn);
11053 const uint32_t addr_byte_size = GetAddressByteSize();
11055 if (!MemAWrite(context, address, data, addr_byte_size))
11058 // MemA[address+4,4] = R[t2];
11059 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + t2, data_reg);
11060 context.SetRegisterToRegisterPlusOffset(data_reg, base_reg,
11061 (address + 4) - Rn);
11063 data = ReadCoreReg(t2, &success);
11067 if (!MemAWrite(context, address + 4, data, addr_byte_size))
11070 // if wback then R[n] = offset_addr;
11073 context.type = eContextAdjustStackPointer;
11075 context.type = eContextAdjustBaseRegister;
11076 context.SetAddress(offset_addr);
11078 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n,
11086 // A8.6.201 STRD (register)
11087 bool EmulateInstructionARM::EmulateSTRDReg(const uint32_t opcode,
11088 const ARMEncoding encoding) {
11090 if ConditionPassed() then
11091 EncodingSpecificOperations();
11092 offset_addr = if add then (R[n] + R[m]) else (R[n] - R[m]);
11093 address = if index then offset_addr else R[n];
11094 MemA[address,4] = R[t];
11095 MemA[address+4,4] = R[t2];
11096 if wback then R[n] = offset_addr;
11099 bool success = false;
11101 if (ConditionPassed(opcode)) {
11110 switch (encoding) {
11112 // if Rt<0> == '1' then UNPREDICTABLE;
11113 // t = UInt(Rt); t2 = t+1; n = UInt(Rn); m = UInt(Rm);
11114 t = Bits32(opcode, 15, 12);
11115 if (BitIsSet(t, 0))
11119 n = Bits32(opcode, 19, 16);
11120 m = Bits32(opcode, 3, 0);
11122 // index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1');
11123 index = BitIsSet(opcode, 24);
11124 add = BitIsSet(opcode, 23);
11125 wback = BitIsClear(opcode, 24) || BitIsSet(opcode, 21);
11127 // if P == '0' && W == '1' then UNPREDICTABLE;
11128 if (BitIsClear(opcode, 24) && BitIsSet(opcode, 21))
11131 // if t2 == 15 || m == 15 then UNPREDICTABLE;
11132 if ((t2 == 15) || (m == 15))
11135 // if wback && (n == 15 || n == t || n == t2) then UNPREDICTABLE;
11136 if (wback && ((n == 15) || (n == t) || (n == t2)))
11139 // if ArchVersion() < 6 && wback && m == n then UNPREDICTABLE;
11140 if ((ArchVersion() < 6) && wback && (m == n))
11149 RegisterInfo base_reg;
11150 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n, base_reg);
11151 RegisterInfo offset_reg;
11152 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + m, offset_reg);
11153 RegisterInfo data_reg;
11155 uint32_t Rn = ReadCoreReg(n, &success);
11159 uint32_t Rm = ReadCoreReg(m, &success);
11163 // offset_addr = if add then (R[n] + R[m]) else (R[n] - R[m]);
11164 addr_t offset_addr;
11166 offset_addr = Rn + Rm;
11168 offset_addr = Rn - Rm;
11170 // address = if index then offset_addr else R[n];
11173 address = offset_addr;
11176 // MemA[address,4] = R[t];
11177 uint32_t Rt = ReadCoreReg(t, &success);
11181 EmulateInstruction::Context context;
11183 context.type = eContextPushRegisterOnStack;
11185 context.type = eContextRegisterStore;
11187 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + t, data_reg);
11188 context.SetRegisterToRegisterPlusIndirectOffset(base_reg, offset_reg,
11191 const uint32_t addr_byte_size = GetAddressByteSize();
11193 if (!MemAWrite(context, address, Rt, addr_byte_size))
11196 // MemA[address+4,4] = R[t2];
11197 uint32_t Rt2 = ReadCoreReg(t2, &success);
11201 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + t2, data_reg);
11203 context.SetRegisterToRegisterPlusIndirectOffset(base_reg, offset_reg,
11206 if (!MemAWrite(context, address + 4, Rt2, addr_byte_size))
11209 // if wback then R[n] = offset_addr;
11211 context.type = eContextAdjustBaseRegister;
11212 context.SetAddress(offset_addr);
11214 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n,
11223 // Vector Load Multiple loads multiple extension registers from consecutive
11224 // memory locations using an address from an ARM core register.
11225 bool EmulateInstructionARM::EmulateVLDM(const uint32_t opcode,
11226 const ARMEncoding encoding) {
11228 if ConditionPassed() then
11229 EncodingSpecificOperations(); CheckVFPEnabled(TRUE); NullCheckIfThumbEE(n);
11230 address = if add then R[n] else R[n]-imm32;
11231 if wback then R[n] = if add then R[n]+imm32 else R[n]-imm32;
11232 for r = 0 to regs-1
11233 if single_regs then
11234 S[d+r] = MemA[address,4]; address = address+4;
11236 word1 = MemA[address,4]; word2 = MemA[address+4,4]; address = address+8;
11237 // Combine the word-aligned words in the correct order for
11238 // current endianness.
11239 D[d+r] = if BigEndian() then word1:word2 else word2:word1;
11242 bool success = false;
11244 if (ConditionPassed(opcode)) {
11253 switch (encoding) {
11256 // if P == '0' && U == '0' && W == '0' then SEE 'Related encodings';
11257 // if P == '0' && U == '1' && W == '1' && Rn == '1101' then SEE VPOP;
11258 // if P == '1' && W == '0' then SEE VLDR;
11259 // if P == U && W == '1' then UNDEFINED;
11260 if ((Bit32(opcode, 24) == Bit32(opcode, 23)) && BitIsSet(opcode, 21))
11263 // // Remaining combinations are PUW = 010 (IA without !), 011 (IA with
11264 // !), 101 (DB with !)
11265 // single_regs = FALSE; add = (U == '1'); wback = (W == '1');
11266 single_regs = false;
11267 add = BitIsSet(opcode, 23);
11268 wback = BitIsSet(opcode, 21);
11270 // d = UInt(D:Vd); n = UInt(Rn); imm32 = ZeroExtend(imm8:'00', 32);
11271 d = (Bit32(opcode, 22) << 4) | Bits32(opcode, 15, 12);
11272 n = Bits32(opcode, 19, 16);
11273 imm32 = Bits32(opcode, 7, 0) << 2;
11275 // regs = UInt(imm8) DIV 2; // If UInt(imm8) is odd, see 'FLDMX'.
11276 regs = Bits32(opcode, 7, 0) / 2;
11278 // if n == 15 && (wback || CurrentInstrSet() != InstrSet_ARM) then
11280 if (n == 15 && (wback || CurrentInstrSet() != eModeARM))
11283 // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE;
11284 if ((regs == 0) || (regs > 16) || ((d + regs) > 32))
11291 // if P == '0' && U == '0' && W == '0' then SEE 'Related encodings';
11292 // if P == '0' && U == '1' && W == '1' && Rn == '1101' then SEE VPOP;
11293 // if P == '1' && W == '0' then SEE VLDR;
11294 // if P == U && W == '1' then UNDEFINED;
11295 if ((Bit32(opcode, 24) == Bit32(opcode, 23)) && BitIsSet(opcode, 21))
11298 // // Remaining combinations are PUW = 010 (IA without !), 011 (IA with
11299 // !), 101 (DB with !) single_regs = TRUE; add = (U == '1'); wback = (W
11301 // UInt(Vd:D); n = UInt(Rn);
11302 single_regs = true;
11303 add = BitIsSet(opcode, 23);
11304 wback = BitIsSet(opcode, 21);
11305 d = (Bits32(opcode, 15, 12) << 1) | Bit32(opcode, 22);
11306 n = Bits32(opcode, 19, 16);
11308 // imm32 = ZeroExtend(imm8:'00', 32); regs = UInt(imm8);
11309 imm32 = Bits32(opcode, 7, 0) << 2;
11310 regs = Bits32(opcode, 7, 0);
11312 // if n == 15 && (wback || CurrentInstrSet() != InstrSet_ARM) then
11314 if ((n == 15) && (wback || (CurrentInstrSet() != eModeARM)))
11317 // if regs == 0 || (d+regs) > 32 then UNPREDICTABLE;
11318 if ((regs == 0) || ((d + regs) > 32))
11326 RegisterInfo base_reg;
11327 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n, base_reg);
11329 uint32_t Rn = ReadCoreReg(n, &success);
11333 // address = if add then R[n] else R[n]-imm32;
11338 address = Rn - imm32;
11340 // if wback then R[n] = if add then R[n]+imm32 else R[n]-imm32;
11341 EmulateInstruction::Context context;
11346 value = Rn + imm32;
11348 value = Rn - imm32;
11350 context.type = eContextAdjustBaseRegister;
11351 context.SetImmediateSigned(value - Rn);
11352 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n,
11357 const uint32_t addr_byte_size = GetAddressByteSize();
11358 uint32_t start_reg = single_regs ? dwarf_s0 : dwarf_d0;
11360 context.type = eContextRegisterLoad;
11362 // for r = 0 to regs-1
11363 for (uint32_t r = 0; r < regs; ++r) {
11365 // S[d+r] = MemA[address,4]; address = address+4;
11366 context.SetRegisterPlusOffset(base_reg, address - Rn);
11368 uint32_t data = MemARead(context, address, addr_byte_size, 0, &success);
11372 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF,
11373 start_reg + d + r, data))
11376 address = address + 4;
11378 // word1 = MemA[address,4]; word2 = MemA[address+4,4]; address =
11380 context.SetRegisterPlusOffset(base_reg, address - Rn);
11382 MemARead(context, address, addr_byte_size, 0, &success);
11386 context.SetRegisterPlusOffset(base_reg, (address + 4) - Rn);
11388 MemARead(context, address + 4, addr_byte_size, 0, &success);
11392 address = address + 8;
11393 // // Combine the word-aligned words in the correct order for current
11395 // D[d+r] = if BigEndian() then word1:word2 else word2:word1;
11397 if (GetByteOrder() == eByteOrderBig) {
11399 data = (data << 32) | word2;
11402 data = (data << 32) | word1;
11405 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF,
11406 start_reg + d + r, data))
11415 // Vector Store Multiple stores multiple extension registers to consecutive
11416 // memory locations using an address from an
11417 // ARM core register.
11418 bool EmulateInstructionARM::EmulateVSTM(const uint32_t opcode,
11419 const ARMEncoding encoding) {
11421 if ConditionPassed() then
11422 EncodingSpecificOperations(); CheckVFPEnabled(TRUE); NullCheckIfThumbEE(n);
11423 address = if add then R[n] else R[n]-imm32;
11424 if wback then R[n] = if add then R[n]+imm32 else R[n]-imm32;
11425 for r = 0 to regs-1
11426 if single_regs then
11427 MemA[address,4] = S[d+r]; address = address+4;
11429 // Store as two word-aligned words in the correct order for
11430 // current endianness.
11431 MemA[address,4] = if BigEndian() then D[d+r]<63:32> else D[d+r]<31:0>;
11432 MemA[address+4,4] = if BigEndian() then D[d+r]<31:0> else D[d+r]<63:32>;
11433 address = address+8;
11436 bool success = false;
11438 if (ConditionPassed(opcode)) {
11447 switch (encoding) {
11450 // if P == '0' && U == '0' && W == '0' then SEE 'Related encodings';
11451 // if P == '1' && U == '0' && W == '1' && Rn == '1101' then SEE VPUSH;
11452 // if P == '1' && W == '0' then SEE VSTR;
11453 // if P == U && W == '1' then UNDEFINED;
11454 if ((Bit32(opcode, 24) == Bit32(opcode, 23)) && BitIsSet(opcode, 21))
11457 // // Remaining combinations are PUW = 010 (IA without !), 011 (IA with
11458 // !), 101 (DB with !)
11459 // single_regs = FALSE; add = (U == '1'); wback = (W == '1');
11460 single_regs = false;
11461 add = BitIsSet(opcode, 23);
11462 wback = BitIsSet(opcode, 21);
11464 // d = UInt(D:Vd); n = UInt(Rn); imm32 = ZeroExtend(imm8:'00', 32);
11465 d = (Bit32(opcode, 22) << 4) | Bits32(opcode, 15, 12);
11466 n = Bits32(opcode, 19, 16);
11467 imm32 = Bits32(opcode, 7, 0) << 2;
11469 // regs = UInt(imm8) DIV 2; // If UInt(imm8) is odd, see 'FSTMX'.
11470 regs = Bits32(opcode, 7, 0) / 2;
11472 // if n == 15 && (wback || CurrentInstrSet() != InstrSet_ARM) then
11474 if ((n == 15) && (wback || (CurrentInstrSet() != eModeARM)))
11477 // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE;
11478 if ((regs == 0) || (regs > 16) || ((d + regs) > 32))
11485 // if P == '0' && U == '0' && W == '0' then SEE 'Related encodings';
11486 // if P == '1' && U == '0' && W == '1' && Rn == '1101' then SEE VPUSH;
11487 // if P == '1' && W == '0' then SEE VSTR;
11488 // if P == U && W == '1' then UNDEFINED;
11489 if ((Bit32(opcode, 24) == Bit32(opcode, 23)) && BitIsSet(opcode, 21))
11492 // // Remaining combinations are PUW = 010 (IA without !), 011 (IA with
11493 // !), 101 (DB with !) single_regs = TRUE; add = (U == '1'); wback = (W
11495 // UInt(Vd:D); n = UInt(Rn);
11496 single_regs = true;
11497 add = BitIsSet(opcode, 23);
11498 wback = BitIsSet(opcode, 21);
11499 d = (Bits32(opcode, 15, 12) << 1) | Bit32(opcode, 22);
11500 n = Bits32(opcode, 19, 16);
11502 // imm32 = ZeroExtend(imm8:'00', 32); regs = UInt(imm8);
11503 imm32 = Bits32(opcode, 7, 0) << 2;
11504 regs = Bits32(opcode, 7, 0);
11506 // if n == 15 && (wback || CurrentInstrSet() != InstrSet_ARM) then
11508 if ((n == 15) && (wback || (CurrentInstrSet() != eModeARM)))
11511 // if regs == 0 || (d+regs) > 32 then UNPREDICTABLE;
11512 if ((regs == 0) || ((d + regs) > 32))
11521 RegisterInfo base_reg;
11522 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n, base_reg);
11524 uint32_t Rn = ReadCoreReg(n, &success);
11528 // address = if add then R[n] else R[n]-imm32;
11533 address = Rn - imm32;
11535 EmulateInstruction::Context context;
11536 // if wback then R[n] = if add then R[n]+imm32 else R[n]-imm32;
11540 value = Rn + imm32;
11542 value = Rn - imm32;
11544 context.type = eContextAdjustBaseRegister;
11545 context.SetRegisterPlusOffset(base_reg, value - Rn);
11547 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n,
11552 const uint32_t addr_byte_size = GetAddressByteSize();
11553 uint32_t start_reg = single_regs ? dwarf_s0 : dwarf_d0;
11555 context.type = eContextRegisterStore;
11556 // for r = 0 to regs-1
11557 for (uint32_t r = 0; r < regs; ++r) {
11560 // MemA[address,4] = S[d+r]; address = address+4;
11561 uint32_t data = ReadRegisterUnsigned(eRegisterKindDWARF,
11562 start_reg + d + r, 0, &success);
11566 RegisterInfo data_reg;
11567 GetRegisterInfo(eRegisterKindDWARF, start_reg + d + r, data_reg);
11568 context.SetRegisterToRegisterPlusOffset(data_reg, base_reg,
11570 if (!MemAWrite(context, address, data, addr_byte_size))
11573 address = address + 4;
11575 // // Store as two word-aligned words in the correct order for current
11576 // endianness. MemA[address,4] = if BigEndian() then D[d+r]<63:32> else
11578 // MemA[address+4,4] = if BigEndian() then D[d+r]<31:0> else
11580 uint64_t data = ReadRegisterUnsigned(eRegisterKindDWARF,
11581 start_reg + d + r, 0, &success);
11585 RegisterInfo data_reg;
11586 GetRegisterInfo(eRegisterKindDWARF, start_reg + d + r, data_reg);
11588 if (GetByteOrder() == eByteOrderBig) {
11589 context.SetRegisterToRegisterPlusOffset(data_reg, base_reg,
11591 if (!MemAWrite(context, address, Bits64(data, 63, 32),
11595 context.SetRegisterToRegisterPlusOffset(data_reg, base_reg,
11596 (address + 4) - Rn);
11597 if (!MemAWrite(context, address + 4, Bits64(data, 31, 0),
11601 context.SetRegisterToRegisterPlusOffset(data_reg, base_reg,
11603 if (!MemAWrite(context, address, Bits64(data, 31, 0), addr_byte_size))
11606 context.SetRegisterToRegisterPlusOffset(data_reg, base_reg,
11607 (address + 4) - Rn);
11608 if (!MemAWrite(context, address + 4, Bits64(data, 63, 32),
11612 // address = address+8;
11613 address = address + 8;
11621 // This instruction loads a single extension register from memory, using an
11622 // address from an ARM core register, with an optional offset.
11623 bool EmulateInstructionARM::EmulateVLDR(const uint32_t opcode,
11624 ARMEncoding encoding) {
11626 if ConditionPassed() then
11627 EncodingSpecificOperations(); CheckVFPEnabled(TRUE); NullCheckIfThumbEE(n);
11628 base = if n == 15 then Align(PC,4) else R[n];
11629 address = if add then (base + imm32) else (base - imm32);
11631 S[d] = MemA[address,4];
11633 word1 = MemA[address,4]; word2 = MemA[address+4,4];
11634 // Combine the word-aligned words in the correct order for current
11636 D[d] = if BigEndian() then word1:word2 else word2:word1;
11639 bool success = false;
11641 if (ConditionPassed(opcode)) {
11648 switch (encoding) {
11651 // single_reg = FALSE; add = (U == '1'); imm32 = ZeroExtend(imm8:'00',
11653 single_reg = false;
11654 add = BitIsSet(opcode, 23);
11655 imm32 = Bits32(opcode, 7, 0) << 2;
11657 // d = UInt(D:Vd); n = UInt(Rn);
11658 d = (Bit32(opcode, 22) << 4) | Bits32(opcode, 15, 12);
11659 n = Bits32(opcode, 19, 16);
11665 // single_reg = TRUE; add = (U == '1'); imm32 = ZeroExtend(imm8:'00', 32);
11667 add = BitIsSet(opcode, 23);
11668 imm32 = Bits32(opcode, 7, 0) << 2;
11670 // d = UInt(Vd:D); n = UInt(Rn);
11671 d = (Bits32(opcode, 15, 12) << 1) | Bit32(opcode, 22);
11672 n = Bits32(opcode, 19, 16);
11679 RegisterInfo base_reg;
11680 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n, base_reg);
11682 uint32_t Rn = ReadCoreReg(n, &success);
11686 // base = if n == 15 then Align(PC,4) else R[n];
11689 base = AlignPC(Rn);
11693 // address = if add then (base + imm32) else (base - imm32);
11696 address = base + imm32;
11698 address = base - imm32;
11700 const uint32_t addr_byte_size = GetAddressByteSize();
11701 uint32_t start_reg = single_reg ? dwarf_s0 : dwarf_d0;
11703 EmulateInstruction::Context context;
11704 context.type = eContextRegisterLoad;
11705 context.SetRegisterPlusOffset(base_reg, address - base);
11708 // S[d] = MemA[address,4];
11709 uint32_t data = MemARead(context, address, addr_byte_size, 0, &success);
11713 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, start_reg + d,
11717 // word1 = MemA[address,4]; word2 = MemA[address+4,4];
11718 uint32_t word1 = MemARead(context, address, addr_byte_size, 0, &success);
11722 context.SetRegisterPlusOffset(base_reg, (address + 4) - base);
11724 MemARead(context, address + 4, addr_byte_size, 0, &success);
11727 // // Combine the word-aligned words in the correct order for current
11729 // D[d] = if BigEndian() then word1:word2 else word2:word1;
11731 if (GetByteOrder() == eByteOrderBig) {
11733 data64 = (data64 << 32) | word2;
11736 data64 = (data64 << 32) | word1;
11739 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, start_reg + d,
11748 // This instruction stores a signle extension register to memory, using an
11749 // address from an ARM core register, with an optional offset.
11750 bool EmulateInstructionARM::EmulateVSTR(const uint32_t opcode,
11751 ARMEncoding encoding) {
11753 if ConditionPassed() then
11754 EncodingSpecificOperations(); CheckVFPEnabled(TRUE); NullCheckIfThumbEE(n);
11755 address = if add then (R[n] + imm32) else (R[n] - imm32);
11757 MemA[address,4] = S[d];
11759 // Store as two word-aligned words in the correct order for current
11761 MemA[address,4] = if BigEndian() then D[d]<63:32> else D[d]<31:0>;
11762 MemA[address+4,4] = if BigEndian() then D[d]<31:0> else D[d]<63:32>;
11765 bool success = false;
11767 if (ConditionPassed(opcode)) {
11774 switch (encoding) {
11777 // single_reg = FALSE; add = (U == '1'); imm32 = ZeroExtend(imm8:'00',
11779 single_reg = false;
11780 add = BitIsSet(opcode, 23);
11781 imm32 = Bits32(opcode, 7, 0) << 2;
11783 // d = UInt(D:Vd); n = UInt(Rn);
11784 d = (Bit32(opcode, 22) << 4) | Bits32(opcode, 15, 12);
11785 n = Bits32(opcode, 19, 16);
11787 // if n == 15 && CurrentInstrSet() != InstrSet_ARM then UNPREDICTABLE;
11788 if ((n == 15) && (CurrentInstrSet() != eModeARM))
11795 // single_reg = TRUE; add = (U == '1'); imm32 = ZeroExtend(imm8:'00', 32);
11797 add = BitIsSet(opcode, 23);
11798 imm32 = Bits32(opcode, 7, 0) << 2;
11800 // d = UInt(Vd:D); n = UInt(Rn);
11801 d = (Bits32(opcode, 15, 12) << 1) | Bit32(opcode, 22);
11802 n = Bits32(opcode, 19, 16);
11804 // if n == 15 && CurrentInstrSet() != InstrSet_ARM then UNPREDICTABLE;
11805 if ((n == 15) && (CurrentInstrSet() != eModeARM))
11814 RegisterInfo base_reg;
11815 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n, base_reg);
11817 uint32_t Rn = ReadCoreReg(n, &success);
11821 // address = if add then (R[n] + imm32) else (R[n] - imm32);
11824 address = Rn + imm32;
11826 address = Rn - imm32;
11828 const uint32_t addr_byte_size = GetAddressByteSize();
11829 uint32_t start_reg = single_reg ? dwarf_s0 : dwarf_d0;
11831 RegisterInfo data_reg;
11832 GetRegisterInfo(eRegisterKindDWARF, start_reg + d, data_reg);
11833 EmulateInstruction::Context context;
11834 context.type = eContextRegisterStore;
11835 context.SetRegisterToRegisterPlusOffset(data_reg, base_reg, address - Rn);
11838 // MemA[address,4] = S[d];
11840 ReadRegisterUnsigned(eRegisterKindDWARF, start_reg + d, 0, &success);
11844 if (!MemAWrite(context, address, data, addr_byte_size))
11847 // // Store as two word-aligned words in the correct order for current
11849 // MemA[address,4] = if BigEndian() then D[d]<63:32> else D[d]<31:0>;
11850 // MemA[address+4,4] = if BigEndian() then D[d]<31:0> else D[d]<63:32>;
11852 ReadRegisterUnsigned(eRegisterKindDWARF, start_reg + d, 0, &success);
11856 if (GetByteOrder() == eByteOrderBig) {
11857 if (!MemAWrite(context, address, Bits64(data, 63, 32), addr_byte_size))
11860 context.SetRegisterToRegisterPlusOffset(data_reg, base_reg,
11861 (address + 4) - Rn);
11862 if (!MemAWrite(context, address + 4, Bits64(data, 31, 0),
11866 if (!MemAWrite(context, address, Bits64(data, 31, 0), addr_byte_size))
11869 context.SetRegisterToRegisterPlusOffset(data_reg, base_reg,
11870 (address + 4) - Rn);
11871 if (!MemAWrite(context, address + 4, Bits64(data, 63, 32),
11880 // A8.6.307 VLDI1 (multiple single elements) This instruction loads elements
11881 // from memory into one, two, three or four registers, without de-interleaving.
11882 // Every element of each register is loaded.
11883 bool EmulateInstructionARM::EmulateVLD1Multiple(const uint32_t opcode,
11884 ARMEncoding encoding) {
11886 if ConditionPassed() then
11887 EncodingSpecificOperations(); CheckAdvSIMDEnabled(); NullCheckIfThumbEE(n);
11888 address = R[n]; if (address MOD alignment) != 0 then GenerateAlignmentException();
11889 if wback then R[n] = R[n] + (if register_index then R[m] else 8*regs);
11890 for r = 0 to regs-1
11891 for e = 0 to elements-1
11892 Elem[D[d+r],e,esize] = MemU[address,ebytes];
11893 address = address + ebytes;
11896 bool success = false;
11898 if (ConditionPassed(opcode)) {
11900 uint32_t alignment;
11908 bool register_index;
11910 switch (encoding) {
11912 case eEncodingA1: {
11915 // regs = 1; if align<1> == '1' then UNDEFINED;
11917 // regs = 2; if align == '11' then UNDEFINED;
11919 // regs = 3; if align<1> == '1' then UNDEFINED;
11923 // SEE 'Related encodings';
11924 uint32_t type = Bits32(opcode, 11, 8);
11925 uint32_t align = Bits32(opcode, 5, 4);
11926 if (type == 7) // '0111'
11929 if (BitIsSet(align, 1))
11931 } else if (type == 10) // '1010'
11937 } else if (type == 6) // '0110'
11940 if (BitIsSet(align, 1))
11942 } else if (type == 2) // '0010'
11948 // alignment = if align == '00' then 1 else 4 << UInt(align);
11952 alignment = 4 << align;
11954 // ebytes = 1 << UInt(size); esize = 8 * ebytes; elements = 8 DIV ebytes;
11955 ebytes = 1 << Bits32(opcode, 7, 6);
11956 esize = 8 * ebytes;
11957 elements = 8 / ebytes;
11959 // d = UInt(D:Vd); n = UInt(Rn); m = UInt(Rm);
11960 d = (Bit32(opcode, 22) << 4) | Bits32(opcode, 15, 12);
11961 n = Bits32(opcode, 19, 15);
11962 m = Bits32(opcode, 3, 0);
11964 // wback = (m != 15); register_index = (m != 15 && m != 13);
11966 register_index = ((m != 15) && (m != 13));
11968 // if d+regs > 32 then UNPREDICTABLE;
11969 if ((d + regs) > 32)
11977 RegisterInfo base_reg;
11978 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n, base_reg);
11980 uint32_t Rn = ReadCoreReg(n, &success);
11984 // address = R[n]; if (address MOD alignment) != 0 then
11985 // GenerateAlignmentException();
11986 addr_t address = Rn;
11987 if ((address % alignment) != 0)
11990 EmulateInstruction::Context context;
11991 // if wback then R[n] = R[n] + (if register_index then R[m] else 8*regs);
11993 uint32_t Rm = ReadCoreReg(m, &success);
11998 if (register_index)
12003 uint32_t value = Rn + offset;
12004 context.type = eContextAdjustBaseRegister;
12005 context.SetRegisterPlusOffset(base_reg, offset);
12007 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n,
12012 // for r = 0 to regs-1
12013 for (uint32_t r = 0; r < regs; ++r) {
12014 // for e = 0 to elements-1
12015 uint64_t assembled_data = 0;
12016 for (uint32_t e = 0; e < elements; ++e) {
12017 // Elem[D[d+r],e,esize] = MemU[address,ebytes];
12018 context.type = eContextRegisterLoad;
12019 context.SetRegisterPlusOffset(base_reg, address - Rn);
12020 uint64_t data = MemURead(context, address, ebytes, 0, &success);
12025 (data << (e * esize)) |
12026 assembled_data; // New data goes to the left of existing data
12028 // address = address + ebytes;
12029 address = address + ebytes;
12031 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_d0 + d + r,
12039 // A8.6.308 VLD1 (single element to one lane)
12041 bool EmulateInstructionARM::EmulateVLD1Single(const uint32_t opcode,
12042 const ARMEncoding encoding) {
12044 if ConditionPassed() then
12045 EncodingSpecificOperations(); CheckAdvSIMDEnabled(); NullCheckIfThumbEE(n);
12046 address = R[n]; if (address MOD alignment) != 0 then GenerateAlignmentException();
12047 if wback then R[n] = R[n] + (if register_index then R[m] else ebytes);
12048 Elem[D[d],index,esize] = MemU[address,ebytes];
12051 bool success = false;
12053 if (ConditionPassed(opcode)) {
12057 uint32_t alignment;
12062 bool register_index;
12064 switch (encoding) {
12066 case eEncodingA1: {
12067 uint32_t size = Bits32(opcode, 11, 10);
12068 uint32_t index_align = Bits32(opcode, 7, 4);
12069 // if size == '11' then SEE VLD1 (single element to all lanes);
12071 return EmulateVLD1SingleAll(opcode, encoding);
12073 if (size == 0) // when '00'
12075 // if index_align<0> != '0' then UNDEFINED;
12076 if (BitIsClear(index_align, 0))
12079 // ebytes = 1; esize = 8; index = UInt(index_align<3:1>); alignment = 1;
12082 index = Bits32(index_align, 3, 1);
12084 } else if (size == 1) // when '01'
12086 // if index_align<1> != '0' then UNDEFINED;
12087 if (BitIsClear(index_align, 1))
12090 // ebytes = 2; esize = 16; index = UInt(index_align<3:2>);
12093 index = Bits32(index_align, 3, 2);
12095 // alignment = if index_align<0> == '0' then 1 else 2;
12096 if (BitIsClear(index_align, 0))
12100 } else if (size == 2) // when '10'
12102 // if index_align<2> != '0' then UNDEFINED;
12103 if (BitIsClear(index_align, 2))
12106 // if index_align<1:0> != '00' && index_align<1:0> != '11' then
12108 if ((Bits32(index_align, 1, 0) != 0) &&
12109 (Bits32(index_align, 1, 0) != 3))
12112 // ebytes = 4; esize = 32; index = UInt(index_align<3>);
12115 index = Bit32(index_align, 3);
12117 // alignment = if index_align<1:0> == '00' then 1 else 4;
12118 if (Bits32(index_align, 1, 0) == 0)
12125 // d = UInt(D:Vd); n = UInt(Rn); m = UInt(Rm);
12126 d = (Bit32(opcode, 22) << 4) | Bits32(opcode, 15, 12);
12127 n = Bits32(opcode, 19, 16);
12128 m = Bits32(opcode, 3, 0);
12130 // wback = (m != 15); register_index = (m != 15 && m != 13); if n == 15
12131 // then UNPREDICTABLE;
12133 register_index = ((m != 15) && (m != 13));
12144 RegisterInfo base_reg;
12145 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n, base_reg);
12147 uint32_t Rn = ReadCoreReg(n, &success);
12151 // address = R[n]; if (address MOD alignment) != 0 then
12152 // GenerateAlignmentException();
12153 addr_t address = Rn;
12154 if ((address % alignment) != 0)
12157 EmulateInstruction::Context context;
12158 // if wback then R[n] = R[n] + (if register_index then R[m] else ebytes);
12160 uint32_t Rm = ReadCoreReg(m, &success);
12165 if (register_index)
12170 uint32_t value = Rn + offset;
12172 context.type = eContextAdjustBaseRegister;
12173 context.SetRegisterPlusOffset(base_reg, offset);
12175 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n,
12180 // Elem[D[d],index,esize] = MemU[address,ebytes];
12181 uint32_t element = MemURead(context, address, esize, 0, &success);
12185 element = element << (index * esize);
12187 uint64_t reg_data =
12188 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_d0 + d, 0, &success);
12192 uint64_t all_ones = -1;
12193 uint64_t mask = all_ones
12194 << ((index + 1) * esize); // mask is all 1's to left of
12195 // where 'element' goes, & all 0's
12196 // at element & to the right of element.
12198 mask = mask | Bits64(all_ones, (index * esize) - 1,
12199 0); // add 1's to the right of where 'element' goes.
12200 // now mask should be 0's where element goes & 1's everywhere else.
12202 uint64_t masked_reg =
12203 reg_data & mask; // Take original reg value & zero out 'element' bits
12205 masked_reg & element; // Put 'element' into those bits in reg_data.
12207 context.type = eContextRegisterLoad;
12208 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + d,
12215 // A8.6.391 VST1 (multiple single elements) Vector Store (multiple single
12216 // elements) stores elements to memory from one, two, three, or four registers,
12217 // without interleaving. Every element of each register is stored.
12218 bool EmulateInstructionARM::EmulateVST1Multiple(const uint32_t opcode,
12219 ARMEncoding encoding) {
12221 if ConditionPassed() then
12222 EncodingSpecificOperations(); CheckAdvSIMDEnabled(); NullCheckIfThumbEE(n);
12223 address = R[n]; if (address MOD alignment) != 0 then GenerateAlignmentException();
12224 if wback then R[n] = R[n] + (if register_index then R[m] else 8*regs);
12225 for r = 0 to regs-1
12226 for e = 0 to elements-1
12227 MemU[address,ebytes] = Elem[D[d+r],e,esize];
12228 address = address + ebytes;
12231 bool success = false;
12233 if (ConditionPassed(opcode)) {
12235 uint32_t alignment;
12243 bool register_index;
12245 switch (encoding) {
12247 case eEncodingA1: {
12248 uint32_t type = Bits32(opcode, 11, 8);
12249 uint32_t align = Bits32(opcode, 5, 4);
12252 if (type == 7) // when '0111'
12254 // regs = 1; if align<1> == '1' then UNDEFINED;
12256 if (BitIsSet(align, 1))
12258 } else if (type == 10) // when '1010'
12260 // regs = 2; if align == '11' then UNDEFINED;
12264 } else if (type == 6) // when '0110'
12266 // regs = 3; if align<1> == '1' then UNDEFINED;
12268 if (BitIsSet(align, 1))
12270 } else if (type == 2) // when '0010'
12274 // SEE 'Related encodings';
12277 // alignment = if align == '00' then 1 else 4 << UInt(align);
12281 alignment = 4 << align;
12283 // ebytes = 1 << UInt(size); esize = 8 * ebytes; elements = 8 DIV ebytes;
12284 ebytes = 1 << Bits32(opcode, 7, 6);
12285 esize = 8 * ebytes;
12286 elements = 8 / ebytes;
12288 // d = UInt(D:Vd); n = UInt(Rn); m = UInt(Rm);
12289 d = (Bit32(opcode, 22) << 4) | Bits32(opcode, 15, 12);
12290 n = Bits32(opcode, 19, 16);
12291 m = Bits32(opcode, 3, 0);
12293 // wback = (m != 15); register_index = (m != 15 && m != 13);
12295 register_index = ((m != 15) && (m != 13));
12297 // if d+regs > 32 then UNPREDICTABLE; if n == 15 then UNPREDICTABLE;
12298 if ((d + regs) > 32)
12310 RegisterInfo base_reg;
12311 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n, base_reg);
12313 uint32_t Rn = ReadCoreReg(n, &success);
12317 // address = R[n]; if (address MOD alignment) != 0 then
12318 // GenerateAlignmentException();
12319 addr_t address = Rn;
12320 if ((address % alignment) != 0)
12323 EmulateInstruction::Context context;
12324 // if wback then R[n] = R[n] + (if register_index then R[m] else 8*regs);
12326 uint32_t Rm = ReadCoreReg(m, &success);
12331 if (register_index)
12336 context.type = eContextAdjustBaseRegister;
12337 context.SetRegisterPlusOffset(base_reg, offset);
12339 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n,
12344 RegisterInfo data_reg;
12345 context.type = eContextRegisterStore;
12346 // for r = 0 to regs-1
12347 for (uint32_t r = 0; r < regs; ++r) {
12348 GetRegisterInfo(eRegisterKindDWARF, dwarf_d0 + d + r, data_reg);
12349 uint64_t register_data = ReadRegisterUnsigned(
12350 eRegisterKindDWARF, dwarf_d0 + d + r, 0, &success);
12354 // for e = 0 to elements-1
12355 for (uint32_t e = 0; e < elements; ++e) {
12356 // MemU[address,ebytes] = Elem[D[d+r],e,esize];
12357 uint64_t word = Bits64(register_data, ((e + 1) * esize) - 1, e * esize);
12359 context.SetRegisterToRegisterPlusOffset(data_reg, base_reg,
12361 if (!MemUWrite(context, address, word, ebytes))
12364 // address = address + ebytes;
12365 address = address + ebytes;
12372 // A8.6.392 VST1 (single element from one lane) This instruction stores one
12373 // element to memory from one element of a register.
12374 bool EmulateInstructionARM::EmulateVST1Single(const uint32_t opcode,
12375 ARMEncoding encoding) {
12377 if ConditionPassed() then
12378 EncodingSpecificOperations(); CheckAdvSIMDEnabled(); NullCheckIfThumbEE(n);
12379 address = R[n]; if (address MOD alignment) != 0 then GenerateAlignmentException();
12380 if wback then R[n] = R[n] + (if register_index then R[m] else ebytes);
12381 MemU[address,ebytes] = Elem[D[d],index,esize];
12384 bool success = false;
12386 if (ConditionPassed(opcode)) {
12390 uint32_t alignment;
12395 bool register_index;
12397 switch (encoding) {
12399 case eEncodingA1: {
12400 uint32_t size = Bits32(opcode, 11, 10);
12401 uint32_t index_align = Bits32(opcode, 7, 4);
12403 // if size == '11' then UNDEFINED;
12408 if (size == 0) // when '00'
12410 // if index_align<0> != '0' then UNDEFINED;
12411 if (BitIsClear(index_align, 0))
12413 // ebytes = 1; esize = 8; index = UInt(index_align<3:1>); alignment = 1;
12416 index = Bits32(index_align, 3, 1);
12418 } else if (size == 1) // when '01'
12420 // if index_align<1> != '0' then UNDEFINED;
12421 if (BitIsClear(index_align, 1))
12424 // ebytes = 2; esize = 16; index = UInt(index_align<3:2>);
12427 index = Bits32(index_align, 3, 2);
12429 // alignment = if index_align<0> == '0' then 1 else 2;
12430 if (BitIsClear(index_align, 0))
12434 } else if (size == 2) // when '10'
12436 // if index_align<2> != '0' then UNDEFINED;
12437 if (BitIsClear(index_align, 2))
12440 // if index_align<1:0> != '00' && index_align<1:0> != '11' then
12442 if ((Bits32(index_align, 1, 0) != 0) &&
12443 (Bits32(index_align, 1, 0) != 3))
12446 // ebytes = 4; esize = 32; index = UInt(index_align<3>);
12449 index = Bit32(index_align, 3);
12451 // alignment = if index_align<1:0> == '00' then 1 else 4;
12452 if (Bits32(index_align, 1, 0) == 0)
12459 // d = UInt(D:Vd); n = UInt(Rn); m = UInt(Rm);
12460 d = (Bit32(opcode, 22) << 4) | Bits32(opcode, 15, 12);
12461 n = Bits32(opcode, 19, 16);
12462 m = Bits32(opcode, 3, 0);
12464 // wback = (m != 15); register_index = (m != 15 && m != 13); if n == 15
12465 // then UNPREDICTABLE;
12467 register_index = ((m != 15) && (m != 13));
12477 RegisterInfo base_reg;
12478 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n, base_reg);
12480 uint32_t Rn = ReadCoreReg(n, &success);
12484 // address = R[n]; if (address MOD alignment) != 0 then
12485 // GenerateAlignmentException();
12486 addr_t address = Rn;
12487 if ((address % alignment) != 0)
12490 EmulateInstruction::Context context;
12491 // if wback then R[n] = R[n] + (if register_index then R[m] else ebytes);
12493 uint32_t Rm = ReadCoreReg(m, &success);
12498 if (register_index)
12503 context.type = eContextAdjustBaseRegister;
12504 context.SetRegisterPlusOffset(base_reg, offset);
12506 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n,
12511 // MemU[address,ebytes] = Elem[D[d],index,esize];
12512 uint64_t register_data =
12513 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_d0 + d, 0, &success);
12518 Bits64(register_data, ((index + 1) * esize) - 1, index * esize);
12520 RegisterInfo data_reg;
12521 GetRegisterInfo(eRegisterKindDWARF, dwarf_d0 + d, data_reg);
12522 context.type = eContextRegisterStore;
12523 context.SetRegisterToRegisterPlusOffset(data_reg, base_reg, address - Rn);
12525 if (!MemUWrite(context, address, word, ebytes))
12531 // A8.6.309 VLD1 (single element to all lanes) This instruction loads one
12532 // element from memory into every element of one or two vectors.
12533 bool EmulateInstructionARM::EmulateVLD1SingleAll(const uint32_t opcode,
12534 const ARMEncoding encoding) {
12536 if ConditionPassed() then
12537 EncodingSpecificOperations(); CheckAdvSIMDEnabled(); NullCheckIfThumbEE(n);
12538 address = R[n]; if (address MOD alignment) != 0 then GenerateAlignmentException();
12539 if wback then R[n] = R[n] + (if register_index then R[m] else ebytes);
12540 replicated_element = Replicate(MemU[address,ebytes], elements);
12541 for r = 0 to regs-1
12542 D[d+r] = replicated_element;
12545 bool success = false;
12547 if (ConditionPassed(opcode)) {
12551 uint32_t alignment;
12556 bool register_index;
12558 switch (encoding) {
12560 case eEncodingA1: {
12561 // if size == '11' || (size == '00' && a == '1') then UNDEFINED;
12562 uint32_t size = Bits32(opcode, 7, 6);
12563 if ((size == 3) || ((size == 0) && BitIsSet(opcode, 4)))
12566 // ebytes = 1 << UInt(size); elements = 8 DIV ebytes; regs = if T == '0'
12568 ebytes = 1 << size;
12569 elements = 8 / ebytes;
12570 if (BitIsClear(opcode, 5))
12575 // alignment = if a == '0' then 1 else ebytes;
12576 if (BitIsClear(opcode, 4))
12579 alignment = ebytes;
12581 // d = UInt(D:Vd); n = UInt(Rn); m = UInt(Rm);
12582 d = (Bit32(opcode, 22) << 4) | Bits32(opcode, 15, 12);
12583 n = Bits32(opcode, 19, 16);
12584 m = Bits32(opcode, 3, 0);
12586 // wback = (m != 15); register_index = (m != 15 && m != 13);
12588 register_index = ((m != 15) && (m != 13));
12590 // if d+regs > 32 then UNPREDICTABLE; if n == 15 then UNPREDICTABLE;
12591 if ((d + regs) > 32)
12602 RegisterInfo base_reg;
12603 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n, base_reg);
12605 uint32_t Rn = ReadCoreReg(n, &success);
12609 // address = R[n]; if (address MOD alignment) != 0 then
12610 // GenerateAlignmentException();
12611 addr_t address = Rn;
12612 if ((address % alignment) != 0)
12615 EmulateInstruction::Context context;
12616 // if wback then R[n] = R[n] + (if register_index then R[m] else ebytes);
12618 uint32_t Rm = ReadCoreReg(m, &success);
12623 if (register_index)
12628 context.type = eContextAdjustBaseRegister;
12629 context.SetRegisterPlusOffset(base_reg, offset);
12631 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n,
12636 // replicated_element = Replicate(MemU[address,ebytes], elements);
12638 context.type = eContextRegisterLoad;
12639 uint64_t word = MemURead(context, address, ebytes, 0, &success);
12643 uint64_t replicated_element = 0;
12644 uint32_t esize = ebytes * 8;
12645 for (uint32_t e = 0; e < elements; ++e)
12646 replicated_element =
12647 (replicated_element << esize) | Bits64(word, esize - 1, 0);
12649 // for r = 0 to regs-1
12650 for (uint32_t r = 0; r < regs; ++r) {
12651 // D[d+r] = replicated_element;
12652 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_d0 + d + r,
12653 replicated_element))
12660 // B6.2.13 SUBS PC, LR and related instructions The SUBS PC, LR, #<const?
12661 // instruction provides an exception return without the use of the stack. It
12662 // subtracts the immediate constant from the LR, branches to the resulting
12663 // address, and also copies the SPSR to the CPSR.
12664 bool EmulateInstructionARM::EmulateSUBSPcLrEtc(const uint32_t opcode,
12665 const ARMEncoding encoding) {
12667 if ConditionPassed() then
12668 EncodingSpecificOperations();
12669 if CurrentInstrSet() == InstrSet_ThumbEE then
12671 operand2 = if register_form then Shift(R[m], shift_t, shift_n, APSR.C) else imm32;
12673 when '0000' result = R[n] AND operand2; // AND
12674 when '0001' result = R[n] EOR operand2; // EOR
12675 when '0010' (result, -, -) = AddWithCarry(R[n], NOT(operand2), '1'); // SUB
12676 when '0011' (result, -, -) = AddWithCarry(NOT(R[n]), operand2, '1'); // RSB
12677 when '0100' (result, -, -) = AddWithCarry(R[n], operand2, '0'); // ADD
12678 when '0101' (result, -, -) = AddWithCarry(R[n], operand2, APSR.c); // ADC
12679 when '0110' (result, -, -) = AddWithCarry(R[n], NOT(operand2), APSR.C); // SBC
12680 when '0111' (result, -, -) = AddWithCarry(NOT(R[n]), operand2, APSR.C); // RSC
12681 when '1100' result = R[n] OR operand2; // ORR
12682 when '1101' result = operand2; // MOV
12683 when '1110' result = R[n] AND NOT(operand2); // BIC
12684 when '1111' result = NOT(operand2); // MVN
12685 CPSRWriteByInstr(SPSR[], '1111', TRUE);
12686 BranchWritePC(result);
12689 bool success = false;
12691 if (ConditionPassed(opcode)) {
12695 bool register_form;
12696 ARM_ShifterType shift_t;
12700 switch (encoding) {
12702 // if CurrentInstrSet() == InstrSet_ThumbEE then UNPREDICTABLE n = 14;
12703 // imm32 = ZeroExtend(imm8, 32); register_form = FALSE; opcode = '0010';
12706 imm32 = Bits32(opcode, 7, 0);
12707 register_form = false;
12710 // if InITBlock() && !LastInITBlock() then UNPREDICTABLE;
12711 if (InITBlock() && !LastInITBlock())
12717 // n = UInt(Rn); imm32 = ARMExpandImm(imm12); register_form = FALSE;
12718 n = Bits32(opcode, 19, 16);
12719 imm32 = ARMExpandImm(opcode);
12720 register_form = false;
12721 code = Bits32(opcode, 24, 21);
12726 // n = UInt(Rn); m = UInt(Rm); register_form = TRUE;
12727 n = Bits32(opcode, 19, 16);
12728 m = Bits32(opcode, 3, 0);
12729 register_form = true;
12731 // (shift_t, shift_n) = DecodeImmShift(type, imm5);
12732 shift_n = DecodeImmShiftARM(opcode, shift_t);
12740 // operand2 = if register_form then Shift(R[m], shift_t, shift_n, APSR.C)
12743 if (register_form) {
12744 uint32_t Rm = ReadCoreReg(m, &success);
12748 operand2 = Shift(Rm, shift_t, shift_n, APSR_C, &success);
12755 uint32_t Rn = ReadCoreReg(n, &success);
12759 AddWithCarryResult result;
12763 case 0: // when '0000'
12764 // result = R[n] AND operand2; // AND
12765 result.result = Rn & operand2;
12768 case 1: // when '0001'
12769 // result = R[n] EOR operand2; // EOR
12770 result.result = Rn ^ operand2;
12773 case 2: // when '0010'
12774 // (result, -, -) = AddWithCarry(R[n], NOT(operand2), '1'); // SUB
12775 result = AddWithCarry(Rn, ~(operand2), 1);
12778 case 3: // when '0011'
12779 // (result, -, -) = AddWithCarry(NOT(R[n]), operand2, '1'); // RSB
12780 result = AddWithCarry(~(Rn), operand2, 1);
12783 case 4: // when '0100'
12784 // (result, -, -) = AddWithCarry(R[n], operand2, '0'); // ADD
12785 result = AddWithCarry(Rn, operand2, 0);
12788 case 5: // when '0101'
12789 // (result, -, -) = AddWithCarry(R[n], operand2, APSR.c); // ADC
12790 result = AddWithCarry(Rn, operand2, APSR_C);
12793 case 6: // when '0110'
12794 // (result, -, -) = AddWithCarry(R[n], NOT(operand2), APSR.C); // SBC
12795 result = AddWithCarry(Rn, ~(operand2), APSR_C);
12798 case 7: // when '0111'
12799 // (result, -, -) = AddWithCarry(NOT(R[n]), operand2, APSR.C); // RSC
12800 result = AddWithCarry(~(Rn), operand2, APSR_C);
12803 case 10: // when '1100'
12804 // result = R[n] OR operand2; // ORR
12805 result.result = Rn | operand2;
12808 case 11: // when '1101'
12809 // result = operand2; // MOV
12810 result.result = operand2;
12813 case 12: // when '1110'
12814 // result = R[n] AND NOT(operand2); // BIC
12815 result.result = Rn & ~(operand2);
12818 case 15: // when '1111'
12819 // result = NOT(operand2); // MVN
12820 result.result = ~(operand2);
12826 // CPSRWriteByInstr(SPSR[], '1111', TRUE);
12828 // For now, in emulation mode, we don't have access to the SPSR, so we will
12829 // use the CPSR instead, and hope for the best.
12831 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_cpsr, 0, &success);
12835 CPSRWriteByInstr(spsr, 15, true);
12837 // BranchWritePC(result);
12838 EmulateInstruction::Context context;
12839 context.type = eContextAdjustPC;
12840 context.SetImmediate(result.result);
12842 BranchWritePC(context, result.result);
12847 EmulateInstructionARM::ARMOpcode *
12848 EmulateInstructionARM::GetARMOpcodeForInstruction(const uint32_t opcode,
12849 uint32_t arm_isa) {
12850 static ARMOpcode g_arm_opcodes[] = {
12851 // Prologue instructions
12853 // push register(s)
12854 {0x0fff0000, 0x092d0000, ARMvAll, eEncodingA1, No_VFP, eSize32,
12855 &EmulateInstructionARM::EmulatePUSH, "push <registers>"},
12856 {0x0fff0fff, 0x052d0004, ARMvAll, eEncodingA2, No_VFP, eSize32,
12857 &EmulateInstructionARM::EmulatePUSH, "push <register>"},
12859 // set r7 to point to a stack offset
12860 {0x0ffff000, 0x028d7000, ARMvAll, eEncodingA1, No_VFP, eSize32,
12861 &EmulateInstructionARM::EmulateADDRdSPImm, "add r7, sp, #<const>"},
12862 {0x0ffff000, 0x024c7000, ARMvAll, eEncodingA1, No_VFP, eSize32,
12863 &EmulateInstructionARM::EmulateSUBR7IPImm, "sub r7, ip, #<const>"},
12864 // copy the stack pointer to ip
12865 {0x0fffffff, 0x01a0c00d, ARMvAll, eEncodingA1, No_VFP, eSize32,
12866 &EmulateInstructionARM::EmulateMOVRdSP, "mov ip, sp"},
12867 {0x0ffff000, 0x028dc000, ARMvAll, eEncodingA1, No_VFP, eSize32,
12868 &EmulateInstructionARM::EmulateADDRdSPImm, "add ip, sp, #<const>"},
12869 {0x0ffff000, 0x024dc000, ARMvAll, eEncodingA1, No_VFP, eSize32,
12870 &EmulateInstructionARM::EmulateSUBIPSPImm, "sub ip, sp, #<const>"},
12872 // adjust the stack pointer
12873 {0x0ffff000, 0x024dd000, ARMvAll, eEncodingA1, No_VFP, eSize32,
12874 &EmulateInstructionARM::EmulateSUBSPImm, "sub sp, sp, #<const>"},
12875 {0x0fef0010, 0x004d0000, ARMvAll, eEncodingA1, No_VFP, eSize32,
12876 &EmulateInstructionARM::EmulateSUBSPReg,
12877 "sub{s}<c> <Rd>, sp, <Rm>{,<shift>}"},
12879 // push one register
12880 // if Rn == '1101' && imm12 == '000000000100' then SEE PUSH;
12881 {0x0e5f0000, 0x040d0000, ARMvAll, eEncodingA1, No_VFP, eSize32,
12882 &EmulateInstructionARM::EmulateSTRRtSP, "str Rt, [sp, #-imm12]!"},
12884 // vector push consecutive extension register(s)
12885 {0x0fbf0f00, 0x0d2d0b00, ARMV6T2_ABOVE, eEncodingA1, No_VFP, eSize32,
12886 &EmulateInstructionARM::EmulateVPUSH, "vpush.64 <list>"},
12887 {0x0fbf0f00, 0x0d2d0a00, ARMV6T2_ABOVE, eEncodingA2, No_VFP, eSize32,
12888 &EmulateInstructionARM::EmulateVPUSH, "vpush.32 <list>"},
12890 // Epilogue instructions
12892 {0x0fff0000, 0x08bd0000, ARMvAll, eEncodingA1, No_VFP, eSize32,
12893 &EmulateInstructionARM::EmulatePOP, "pop <registers>"},
12894 {0x0fff0fff, 0x049d0004, ARMvAll, eEncodingA2, No_VFP, eSize32,
12895 &EmulateInstructionARM::EmulatePOP, "pop <register>"},
12896 {0x0fbf0f00, 0x0cbd0b00, ARMV6T2_ABOVE, eEncodingA1, No_VFP, eSize32,
12897 &EmulateInstructionARM::EmulateVPOP, "vpop.64 <list>"},
12898 {0x0fbf0f00, 0x0cbd0a00, ARMV6T2_ABOVE, eEncodingA2, No_VFP, eSize32,
12899 &EmulateInstructionARM::EmulateVPOP, "vpop.32 <list>"},
12901 // Supervisor Call (previously Software Interrupt)
12902 {0x0f000000, 0x0f000000, ARMvAll, eEncodingA1, No_VFP, eSize32,
12903 &EmulateInstructionARM::EmulateSVC, "svc #imm24"},
12905 // Branch instructions
12906 // To resolve ambiguity, "blx <label>" should come before "b #imm24" and
12908 {0xfe000000, 0xfa000000, ARMV5_ABOVE, eEncodingA2, No_VFP, eSize32,
12909 &EmulateInstructionARM::EmulateBLXImmediate, "blx <label>"},
12910 {0x0f000000, 0x0a000000, ARMvAll, eEncodingA1, No_VFP, eSize32,
12911 &EmulateInstructionARM::EmulateB, "b #imm24"},
12912 {0x0f000000, 0x0b000000, ARMvAll, eEncodingA1, No_VFP, eSize32,
12913 &EmulateInstructionARM::EmulateBLXImmediate, "bl <label>"},
12914 {0x0ffffff0, 0x012fff30, ARMV5_ABOVE, eEncodingA1, No_VFP, eSize32,
12915 &EmulateInstructionARM::EmulateBLXRm, "blx <Rm>"},
12916 // for example, "bx lr"
12917 {0x0ffffff0, 0x012fff10, ARMvAll, eEncodingA1, No_VFP, eSize32,
12918 &EmulateInstructionARM::EmulateBXRm, "bx <Rm>"},
12920 {0x0ffffff0, 0x012fff20, ARMvAll, eEncodingA1, No_VFP, eSize32,
12921 &EmulateInstructionARM::EmulateBXJRm, "bxj <Rm>"},
12923 // Data-processing instructions
12925 {0x0fe00000, 0x02a00000, ARMvAll, eEncodingA1, No_VFP, eSize32,
12926 &EmulateInstructionARM::EmulateADCImm, "adc{s}<c> <Rd>, <Rn>, #const"},
12928 {0x0fe00010, 0x00a00000, ARMvAll, eEncodingA1, No_VFP, eSize32,
12929 &EmulateInstructionARM::EmulateADCReg,
12930 "adc{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
12932 {0x0fe00000, 0x02800000, ARMvAll, eEncodingA1, No_VFP, eSize32,
12933 &EmulateInstructionARM::EmulateADDImmARM,
12934 "add{s}<c> <Rd>, <Rn>, #const"},
12936 {0x0fe00010, 0x00800000, ARMvAll, eEncodingA1, No_VFP, eSize32,
12937 &EmulateInstructionARM::EmulateADDReg,
12938 "add{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
12939 // add (register-shifted register)
12940 {0x0fe00090, 0x00800010, ARMvAll, eEncodingA1, No_VFP, eSize32,
12941 &EmulateInstructionARM::EmulateADDRegShift,
12942 "add{s}<c> <Rd>, <Rn>, <Rm>, <type> <RS>"},
12944 {0x0fff0000, 0x028f0000, ARMvAll, eEncodingA1, No_VFP, eSize32,
12945 &EmulateInstructionARM::EmulateADR, "add<c> <Rd>, PC, #<const>"},
12946 {0x0fff0000, 0x024f0000, ARMvAll, eEncodingA2, No_VFP, eSize32,
12947 &EmulateInstructionARM::EmulateADR, "sub<c> <Rd>, PC, #<const>"},
12949 {0x0fe00000, 0x02000000, ARMvAll, eEncodingA1, No_VFP, eSize32,
12950 &EmulateInstructionARM::EmulateANDImm, "and{s}<c> <Rd>, <Rn>, #const"},
12952 {0x0fe00010, 0x00000000, ARMvAll, eEncodingA1, No_VFP, eSize32,
12953 &EmulateInstructionARM::EmulateANDReg,
12954 "and{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
12956 {0x0fe00000, 0x03c00000, ARMvAll, eEncodingA1, No_VFP, eSize32,
12957 &EmulateInstructionARM::EmulateBICImm, "bic{s}<c> <Rd>, <Rn>, #const"},
12959 {0x0fe00010, 0x01c00000, ARMvAll, eEncodingA1, No_VFP, eSize32,
12960 &EmulateInstructionARM::EmulateBICReg,
12961 "bic{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
12963 {0x0fe00000, 0x02200000, ARMvAll, eEncodingA1, No_VFP, eSize32,
12964 &EmulateInstructionARM::EmulateEORImm, "eor{s}<c> <Rd>, <Rn>, #const"},
12966 {0x0fe00010, 0x00200000, ARMvAll, eEncodingA1, No_VFP, eSize32,
12967 &EmulateInstructionARM::EmulateEORReg,
12968 "eor{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
12970 {0x0fe00000, 0x03800000, ARMvAll, eEncodingA1, No_VFP, eSize32,
12971 &EmulateInstructionARM::EmulateORRImm, "orr{s}<c> <Rd>, <Rn>, #const"},
12973 {0x0fe00010, 0x01800000, ARMvAll, eEncodingA1, No_VFP, eSize32,
12974 &EmulateInstructionARM::EmulateORRReg,
12975 "orr{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
12977 {0x0fe00000, 0x02600000, ARMvAll, eEncodingA1, No_VFP, eSize32,
12978 &EmulateInstructionARM::EmulateRSBImm, "rsb{s}<c> <Rd>, <Rn>, #<const>"},
12980 {0x0fe00010, 0x00600000, ARMvAll, eEncodingA1, No_VFP, eSize32,
12981 &EmulateInstructionARM::EmulateRSBReg,
12982 "rsb{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
12984 {0x0fe00000, 0x02e00000, ARMvAll, eEncodingA1, No_VFP, eSize32,
12985 &EmulateInstructionARM::EmulateRSCImm, "rsc{s}<c> <Rd>, <Rn>, #<const>"},
12987 {0x0fe00010, 0x00e00000, ARMvAll, eEncodingA1, No_VFP, eSize32,
12988 &EmulateInstructionARM::EmulateRSCReg,
12989 "rsc{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
12991 {0x0fe00000, 0x02c00000, ARMvAll, eEncodingA1, No_VFP, eSize32,
12992 &EmulateInstructionARM::EmulateSBCImm, "sbc{s}<c> <Rd>, <Rn>, #<const>"},
12994 {0x0fe00010, 0x00c00000, ARMvAll, eEncodingA1, No_VFP, eSize32,
12995 &EmulateInstructionARM::EmulateSBCReg,
12996 "sbc{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
12997 // sub (immediate, ARM)
12998 {0x0fe00000, 0x02400000, ARMvAll, eEncodingA1, No_VFP, eSize32,
12999 &EmulateInstructionARM::EmulateSUBImmARM,
13000 "sub{s}<c> <Rd>, <Rn>, #<const>"},
13001 // sub (sp minus immediate)
13002 {0x0fef0000, 0x024d0000, ARMvAll, eEncodingA1, No_VFP, eSize32,
13003 &EmulateInstructionARM::EmulateSUBSPImm, "sub{s}<c> <Rd>, sp, #<const>"},
13005 {0x0fe00010, 0x00400000, ARMvAll, eEncodingA1, No_VFP, eSize32,
13006 &EmulateInstructionARM::EmulateSUBReg,
13007 "sub{s}<c> <Rd>, <Rn>, <Rm>{,<shift>}"},
13009 {0x0ff0f000, 0x03300000, ARMvAll, eEncodingA1, No_VFP, eSize32,
13010 &EmulateInstructionARM::EmulateTEQImm, "teq<c> <Rn>, #const"},
13012 {0x0ff0f010, 0x01300000, ARMvAll, eEncodingA1, No_VFP, eSize32,
13013 &EmulateInstructionARM::EmulateTEQReg, "teq<c> <Rn>, <Rm> {,<shift>}"},
13015 {0x0ff0f000, 0x03100000, ARMvAll, eEncodingA1, No_VFP, eSize32,
13016 &EmulateInstructionARM::EmulateTSTImm, "tst<c> <Rn>, #const"},
13018 {0x0ff0f010, 0x01100000, ARMvAll, eEncodingA1, No_VFP, eSize32,
13019 &EmulateInstructionARM::EmulateTSTReg, "tst<c> <Rn>, <Rm> {,<shift>}"},
13022 {0x0fef0000, 0x03a00000, ARMvAll, eEncodingA1, No_VFP, eSize32,
13023 &EmulateInstructionARM::EmulateMOVRdImm, "mov{s}<c> <Rd>, #<const>"},
13024 {0x0ff00000, 0x03000000, ARMV6T2_ABOVE, eEncodingA2, No_VFP, eSize32,
13025 &EmulateInstructionARM::EmulateMOVRdImm, "movw<c> <Rd>, #<imm16>"},
13027 {0x0fef0ff0, 0x01a00000, ARMvAll, eEncodingA1, No_VFP, eSize32,
13028 &EmulateInstructionARM::EmulateMOVRdRm, "mov{s}<c> <Rd>, <Rm>"},
13030 {0x0fef0000, 0x03e00000, ARMvAll, eEncodingA1, No_VFP, eSize32,
13031 &EmulateInstructionARM::EmulateMVNImm, "mvn{s}<c> <Rd>, #<const>"},
13033 {0x0fef0010, 0x01e00000, ARMvAll, eEncodingA1, No_VFP, eSize32,
13034 &EmulateInstructionARM::EmulateMVNReg,
13035 "mvn{s}<c> <Rd>, <Rm> {,<shift>}"},
13037 {0x0ff0f000, 0x03700000, ARMvAll, eEncodingA1, No_VFP, eSize32,
13038 &EmulateInstructionARM::EmulateCMNImm, "cmn<c> <Rn>, #<const>"},
13040 {0x0ff0f010, 0x01700000, ARMvAll, eEncodingA1, No_VFP, eSize32,
13041 &EmulateInstructionARM::EmulateCMNReg, "cmn<c> <Rn>, <Rm> {,<shift>}"},
13043 {0x0ff0f000, 0x03500000, ARMvAll, eEncodingA1, No_VFP, eSize32,
13044 &EmulateInstructionARM::EmulateCMPImm, "cmp<c> <Rn>, #<const>"},
13046 {0x0ff0f010, 0x01500000, ARMvAll, eEncodingA1, No_VFP, eSize32,
13047 &EmulateInstructionARM::EmulateCMPReg, "cmp<c> <Rn>, <Rm> {,<shift>}"},
13049 {0x0fef0070, 0x01a00040, ARMvAll, eEncodingA1, No_VFP, eSize32,
13050 &EmulateInstructionARM::EmulateASRImm, "asr{s}<c> <Rd>, <Rm>, #imm"},
13052 {0x0fef00f0, 0x01a00050, ARMvAll, eEncodingA1, No_VFP, eSize32,
13053 &EmulateInstructionARM::EmulateASRReg, "asr{s}<c> <Rd>, <Rn>, <Rm>"},
13055 {0x0fef0070, 0x01a00000, ARMvAll, eEncodingA1, No_VFP, eSize32,
13056 &EmulateInstructionARM::EmulateLSLImm, "lsl{s}<c> <Rd>, <Rm>, #imm"},
13058 {0x0fef00f0, 0x01a00010, ARMvAll, eEncodingA1, No_VFP, eSize32,
13059 &EmulateInstructionARM::EmulateLSLReg, "lsl{s}<c> <Rd>, <Rn>, <Rm>"},
13061 {0x0fef0070, 0x01a00020, ARMvAll, eEncodingA1, No_VFP, eSize32,
13062 &EmulateInstructionARM::EmulateLSRImm, "lsr{s}<c> <Rd>, <Rm>, #imm"},
13064 {0x0fef00f0, 0x01a00050, ARMvAll, eEncodingA1, No_VFP, eSize32,
13065 &EmulateInstructionARM::EmulateLSRReg, "lsr{s}<c> <Rd>, <Rn>, <Rm>"},
13066 // rrx is a special case encoding of ror (immediate)
13067 {0x0fef0ff0, 0x01a00060, ARMvAll, eEncodingA1, No_VFP, eSize32,
13068 &EmulateInstructionARM::EmulateRRX, "rrx{s}<c> <Rd>, <Rm>"},
13070 {0x0fef0070, 0x01a00060, ARMvAll, eEncodingA1, No_VFP, eSize32,
13071 &EmulateInstructionARM::EmulateRORImm, "ror{s}<c> <Rd>, <Rm>, #imm"},
13073 {0x0fef00f0, 0x01a00070, ARMvAll, eEncodingA1, No_VFP, eSize32,
13074 &EmulateInstructionARM::EmulateRORReg, "ror{s}<c> <Rd>, <Rn>, <Rm>"},
13076 {0x0fe000f0, 0x00000090, ARMvAll, eEncodingA1, No_VFP, eSize32,
13077 &EmulateInstructionARM::EmulateMUL, "mul{s}<c> <Rd>,<R>,<Rm>"},
13079 // subs pc, lr and related instructions
13080 {0x0e10f000, 0x0210f000, ARMvAll, eEncodingA1, No_VFP, eSize32,
13081 &EmulateInstructionARM::EmulateSUBSPcLrEtc,
13082 "<opc>S<c> PC,#<const> | <Rn>,#<const>"},
13083 {0x0e10f010, 0x0010f000, ARMvAll, eEncodingA2, No_VFP, eSize32,
13084 &EmulateInstructionARM::EmulateSUBSPcLrEtc,
13085 "<opc>S<c> PC,<Rn>,<Rm{,<shift>}"},
13087 // Load instructions
13088 {0x0fd00000, 0x08900000, ARMvAll, eEncodingA1, No_VFP, eSize32,
13089 &EmulateInstructionARM::EmulateLDM, "ldm<c> <Rn>{!} <registers>"},
13090 {0x0fd00000, 0x08100000, ARMvAll, eEncodingA1, No_VFP, eSize32,
13091 &EmulateInstructionARM::EmulateLDMDA, "ldmda<c> <Rn>{!} <registers>"},
13092 {0x0fd00000, 0x09100000, ARMvAll, eEncodingA1, No_VFP, eSize32,
13093 &EmulateInstructionARM::EmulateLDMDB, "ldmdb<c> <Rn>{!} <registers>"},
13094 {0x0fd00000, 0x09900000, ARMvAll, eEncodingA1, No_VFP, eSize32,
13095 &EmulateInstructionARM::EmulateLDMIB, "ldmib<c> <Rn<{!} <registers>"},
13096 {0x0e500000, 0x04100000, ARMvAll, eEncodingA1, No_VFP, eSize32,
13097 &EmulateInstructionARM::EmulateLDRImmediateARM,
13098 "ldr<c> <Rt> [<Rn> {#+/-<imm12>}]"},
13099 {0x0e500010, 0x06100000, ARMvAll, eEncodingA1, No_VFP, eSize32,
13100 &EmulateInstructionARM::EmulateLDRRegister,
13101 "ldr<c> <Rt> [<Rn> +/-<Rm> {<shift>}] {!}"},
13102 {0x0e5f0000, 0x045f0000, ARMvAll, eEncodingA1, No_VFP, eSize32,
13103 &EmulateInstructionARM::EmulateLDRBLiteral, "ldrb<c> <Rt>, [...]"},
13104 {0xfe500010, 0x06500000, ARMvAll, eEncodingA1, No_VFP, eSize32,
13105 &EmulateInstructionARM::EmulateLDRBRegister,
13106 "ldrb<c> <Rt>, [<Rn>,+/-<Rm>{, <shift>}]{!}"},
13107 {0x0e5f00f0, 0x005f00b0, ARMvAll, eEncodingA1, No_VFP, eSize32,
13108 &EmulateInstructionARM::EmulateLDRHLiteral, "ldrh<c> <Rt>, <label>"},
13109 {0x0e5000f0, 0x001000b0, ARMvAll, eEncodingA1, No_VFP, eSize32,
13110 &EmulateInstructionARM::EmulateLDRHRegister,
13111 "ldrh<c> <Rt>,[<Rn>,+/-<Rm>]{!}"},
13112 {0x0e5000f0, 0x005000d0, ARMvAll, eEncodingA1, No_VFP, eSize32,
13113 &EmulateInstructionARM::EmulateLDRSBImmediate,
13114 "ldrsb<c> <Rt>, [<Rn>{,#+/-<imm8>}]"},
13115 {0x0e5f00f0, 0x005f00d0, ARMvAll, eEncodingA1, No_VFP, eSize32,
13116 &EmulateInstructionARM::EmulateLDRSBLiteral, "ldrsb<c> <Rt> <label>"},
13117 {0x0e5000f0, 0x001000d0, ARMvAll, eEncodingA1, No_VFP, eSize32,
13118 &EmulateInstructionARM::EmulateLDRSBRegister,
13119 "ldrsb<c> <Rt>,[<Rn>,+/-<Rm>]{!}"},
13120 {0x0e5000f0, 0x005000f0, ARMvAll, eEncodingA1, No_VFP, eSize32,
13121 &EmulateInstructionARM::EmulateLDRSHImmediate,
13122 "ldrsh<c> <Rt>,[<Rn>{,#+/-<imm8>}]"},
13123 {0x0e5f00f0, 0x005f00f0, ARMvAll, eEncodingA1, No_VFP, eSize32,
13124 &EmulateInstructionARM::EmulateLDRSHLiteral, "ldrsh<c> <Rt>,<label>"},
13125 {0x0e5000f0, 0x001000f0, ARMvAll, eEncodingA1, No_VFP, eSize32,
13126 &EmulateInstructionARM::EmulateLDRSHRegister,
13127 "ldrsh<c> <Rt>,[<Rn>,+/-<Rm>]{!}"},
13128 {0x0e5000f0, 0x004000d0, ARMV5TE_ABOVE, eEncodingA1, No_VFP, eSize32,
13129 &EmulateInstructionARM::EmulateLDRDImmediate,
13130 "ldrd<c> <Rt>, <Rt2>, [<Rn>,#+/-<imm8>]!"},
13131 {0x0e500ff0, 0x000000d0, ARMV5TE_ABOVE, eEncodingA1, No_VFP, eSize32,
13132 &EmulateInstructionARM::EmulateLDRDRegister,
13133 "ldrd<c> <Rt>, <Rt2>, [<Rn>, +/-<Rm>]{!}"},
13134 {0x0e100f00, 0x0c100b00, ARMvAll, eEncodingA1, VFPv2_ABOVE, eSize32,
13135 &EmulateInstructionARM::EmulateVLDM, "vldm{mode}<c> <Rn>{!}, <list>"},
13136 {0x0e100f00, 0x0c100a00, ARMvAll, eEncodingA2, VFPv2v3, eSize32,
13137 &EmulateInstructionARM::EmulateVLDM, "vldm{mode}<c> <Rn>{!}, <list>"},
13138 {0x0f300f00, 0x0d100b00, ARMvAll, eEncodingA1, VFPv2_ABOVE, eSize32,
13139 &EmulateInstructionARM::EmulateVLDR, "vldr<c> <Dd>, [<Rn>{,#+/-<imm>}]"},
13140 {0x0f300f00, 0x0d100a00, ARMvAll, eEncodingA2, VFPv2v3, eSize32,
13141 &EmulateInstructionARM::EmulateVLDR, "vldr<c> <Sd>, [<Rn>{,#+/-<imm>}]"},
13142 {0xffb00000, 0xf4200000, ARMvAll, eEncodingA1, AdvancedSIMD, eSize32,
13143 &EmulateInstructionARM::EmulateVLD1Multiple,
13144 "vld1<c>.<size> <list>, [<Rn>{@<align>}], <Rm>"},
13145 {0xffb00300, 0xf4a00000, ARMvAll, eEncodingA1, AdvancedSIMD, eSize32,
13146 &EmulateInstructionARM::EmulateVLD1Single,
13147 "vld1<c>.<size> <list>, [<Rn>{@<align>}], <Rm>"},
13148 {0xffb00f00, 0xf4a00c00, ARMvAll, eEncodingA1, AdvancedSIMD, eSize32,
13149 &EmulateInstructionARM::EmulateVLD1SingleAll,
13150 "vld1<c>.<size> <list>, [<Rn>{@<align>}], <Rm>"},
13152 // Store instructions
13153 {0x0fd00000, 0x08800000, ARMvAll, eEncodingA1, No_VFP, eSize32,
13154 &EmulateInstructionARM::EmulateSTM, "stm<c> <Rn>{!} <registers>"},
13155 {0x0fd00000, 0x08000000, ARMvAll, eEncodingA1, No_VFP, eSize32,
13156 &EmulateInstructionARM::EmulateSTMDA, "stmda<c> <Rn>{!} <registers>"},
13157 {0x0fd00000, 0x09000000, ARMvAll, eEncodingA1, No_VFP, eSize32,
13158 &EmulateInstructionARM::EmulateSTMDB, "stmdb<c> <Rn>{!} <registers>"},
13159 {0x0fd00000, 0x09800000, ARMvAll, eEncodingA1, No_VFP, eSize32,
13160 &EmulateInstructionARM::EmulateSTMIB, "stmib<c> <Rn>{!} <registers>"},
13161 {0x0e500010, 0x06000000, ARMvAll, eEncodingA1, No_VFP, eSize32,
13162 &EmulateInstructionARM::EmulateSTRRegister,
13163 "str<c> <Rt> [<Rn> +/-<Rm> {<shift>}]{!}"},
13164 {0x0e5000f0, 0x000000b0, ARMvAll, eEncodingA1, No_VFP, eSize32,
13165 &EmulateInstructionARM::EmulateSTRHRegister,
13166 "strh<c> <Rt>,[<Rn>,+/-<Rm>[{!}"},
13167 {0x0ff00ff0, 0x01800f90, ARMV6_ABOVE, eEncodingA1, No_VFP, eSize32,
13168 &EmulateInstructionARM::EmulateSTREX, "strex<c> <Rd>, <Rt>, [<Rn>]"},
13169 {0x0e500000, 0x04400000, ARMvAll, eEncodingA1, No_VFP, eSize32,
13170 &EmulateInstructionARM::EmulateSTRBImmARM,
13171 "strb<c> <Rt>,[<Rn>,#+/-<imm12>]!"},
13172 {0x0e500000, 0x04000000, ARMvAll, eEncodingA1, No_VFP, eSize32,
13173 &EmulateInstructionARM::EmulateSTRImmARM,
13174 "str<c> <Rt>,[<Rn>,#+/-<imm12>]!"},
13175 {0x0e5000f0, 0x004000f0, ARMV5TE_ABOVE, eEncodingA1, No_VFP, eSize32,
13176 &EmulateInstructionARM::EmulateSTRDImm,
13177 "strd<c> <Rt>, <Rt2>, [<Rn> #+/-<imm8>]!"},
13178 {0x0e500ff0, 0x000000f0, ARMV5TE_ABOVE, eEncodingA1, No_VFP, eSize32,
13179 &EmulateInstructionARM::EmulateSTRDReg,
13180 "strd<c> <Rt>, <Rt2>, [<Rn>, +/-<Rm>]{!}"},
13181 {0x0e100f00, 0x0c000b00, ARMvAll, eEncodingA1, VFPv2_ABOVE, eSize32,
13182 &EmulateInstructionARM::EmulateVSTM, "vstm{mode}<c> <Rn>{!} <list>"},
13183 {0x0e100f00, 0x0c000a00, ARMvAll, eEncodingA2, VFPv2v3, eSize32,
13184 &EmulateInstructionARM::EmulateVSTM, "vstm{mode}<c> <Rn>{!} <list>"},
13185 {0x0f300f00, 0x0d000b00, ARMvAll, eEncodingA1, VFPv2_ABOVE, eSize32,
13186 &EmulateInstructionARM::EmulateVSTR, "vstr<c> <Dd> [<Rn>{,#+/-<imm>}]"},
13187 {0x0f300f00, 0x0d000a00, ARMvAll, eEncodingA2, VFPv2v3, eSize32,
13188 &EmulateInstructionARM::EmulateVSTR, "vstr<c> <Sd> [<Rn>{,#+/-<imm>}]"},
13189 {0xffb00000, 0xf4000000, ARMvAll, eEncodingA1, AdvancedSIMD, eSize32,
13190 &EmulateInstructionARM::EmulateVST1Multiple,
13191 "vst1<c>.<size> <list>, [<Rn>{@<align>}], <Rm>"},
13192 {0xffb00300, 0xf4800000, ARMvAll, eEncodingA1, AdvancedSIMD, eSize32,
13193 &EmulateInstructionARM::EmulateVST1Single,
13194 "vst1<c>.<size> <list>, [<Rn>{@<align>}], <Rm>"},
13196 // Other instructions
13197 {0x0fff00f0, 0x06af00f0, ARMV6_ABOVE, eEncodingA1, No_VFP, eSize32,
13198 &EmulateInstructionARM::EmulateSXTB, "sxtb<c> <Rd>,<Rm>{,<rotation>}"},
13199 {0x0fff00f0, 0x06bf0070, ARMV6_ABOVE, eEncodingA1, No_VFP, eSize32,
13200 &EmulateInstructionARM::EmulateSXTH, "sxth<c> <Rd>,<Rm>{,<rotation>}"},
13201 {0x0fff00f0, 0x06ef0070, ARMV6_ABOVE, eEncodingA1, No_VFP, eSize32,
13202 &EmulateInstructionARM::EmulateUXTB, "uxtb<c> <Rd>,<Rm>{,<rotation>}"},
13203 {0x0fff00f0, 0x06ff0070, ARMV6_ABOVE, eEncodingA1, No_VFP, eSize32,
13204 &EmulateInstructionARM::EmulateUXTH, "uxth<c> <Rd>,<Rm>{,<rotation>}"},
13205 {0xfe500000, 0xf8100000, ARMV6_ABOVE, eEncodingA1, No_VFP, eSize32,
13206 &EmulateInstructionARM::EmulateRFE, "rfe{<amode>} <Rn>{!}"}
13209 static const size_t k_num_arm_opcodes = llvm::array_lengthof(g_arm_opcodes);
13211 for (size_t i = 0; i < k_num_arm_opcodes; ++i) {
13212 if ((g_arm_opcodes[i].mask & opcode) == g_arm_opcodes[i].value &&
13213 (g_arm_opcodes[i].variants & arm_isa) != 0)
13214 return &g_arm_opcodes[i];
13219 EmulateInstructionARM::ARMOpcode *
13220 EmulateInstructionARM::GetThumbOpcodeForInstruction(const uint32_t opcode,
13221 uint32_t arm_isa) {
13223 static ARMOpcode g_thumb_opcodes[] = {
13224 // Prologue instructions
13226 // push register(s)
13227 {0xfffffe00, 0x0000b400, ARMvAll, eEncodingT1, No_VFP, eSize16,
13228 &EmulateInstructionARM::EmulatePUSH, "push <registers>"},
13229 {0xffff0000, 0xe92d0000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
13230 &EmulateInstructionARM::EmulatePUSH, "push.w <registers>"},
13231 {0xffff0fff, 0xf84d0d04, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32,
13232 &EmulateInstructionARM::EmulatePUSH, "push.w <register>"},
13234 // set r7 to point to a stack offset
13235 {0xffffff00, 0x0000af00, ARMvAll, eEncodingT1, No_VFP, eSize16,
13236 &EmulateInstructionARM::EmulateADDRdSPImm, "add r7, sp, #imm"},
13237 // copy the stack pointer to r7
13238 {0xffffffff, 0x0000466f, ARMvAll, eEncodingT1, No_VFP, eSize16,
13239 &EmulateInstructionARM::EmulateMOVRdSP, "mov r7, sp"},
13240 // move from high register to low register (comes after "mov r7, sp" to
13241 // resolve ambiguity)
13242 {0xffffffc0, 0x00004640, ARMvAll, eEncodingT1, No_VFP, eSize16,
13243 &EmulateInstructionARM::EmulateMOVLowHigh, "mov r0-r7, r8-r15"},
13245 // PC-relative load into register (see also EmulateADDSPRm)
13246 {0xfffff800, 0x00004800, ARMvAll, eEncodingT1, No_VFP, eSize16,
13247 &EmulateInstructionARM::EmulateLDRRtPCRelative, "ldr <Rt>, [PC, #imm]"},
13249 // adjust the stack pointer
13250 {0xffffff87, 0x00004485, ARMvAll, eEncodingT2, No_VFP, eSize16,
13251 &EmulateInstructionARM::EmulateADDSPRm, "add sp, <Rm>"},
13252 {0xffffff80, 0x0000b080, ARMvAll, eEncodingT1, No_VFP, eSize16,
13253 &EmulateInstructionARM::EmulateSUBSPImm, "sub sp, sp, #imm"},
13254 {0xfbef8f00, 0xf1ad0d00, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
13255 &EmulateInstructionARM::EmulateSUBSPImm, "sub.w sp, sp, #<const>"},
13256 {0xfbff8f00, 0xf2ad0d00, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32,
13257 &EmulateInstructionARM::EmulateSUBSPImm, "subw sp, sp, #imm12"},
13258 {0xffef8000, 0xebad0000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32,
13259 &EmulateInstructionARM::EmulateSUBSPReg,
13260 "sub{s}<c> <Rd>, sp, <Rm>{,<shift>}"},
13262 // vector push consecutive extension register(s)
13263 {0xffbf0f00, 0xed2d0b00, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32,
13264 &EmulateInstructionARM::EmulateVPUSH, "vpush.64 <list>"},
13265 {0xffbf0f00, 0xed2d0a00, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
13266 &EmulateInstructionARM::EmulateVPUSH, "vpush.32 <list>"},
13268 // Epilogue instructions
13270 {0xfffff800, 0x0000a800, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16,
13271 &EmulateInstructionARM::EmulateADDSPImm, "add<c> <Rd>, sp, #imm"},
13272 {0xffffff80, 0x0000b000, ARMvAll, eEncodingT2, No_VFP, eSize16,
13273 &EmulateInstructionARM::EmulateADDSPImm, "add sp, #imm"},
13274 {0xfffffe00, 0x0000bc00, ARMvAll, eEncodingT1, No_VFP, eSize16,
13275 &EmulateInstructionARM::EmulatePOP, "pop <registers>"},
13276 {0xffff0000, 0xe8bd0000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
13277 &EmulateInstructionARM::EmulatePOP, "pop.w <registers>"},
13278 {0xffff0fff, 0xf85d0d04, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32,
13279 &EmulateInstructionARM::EmulatePOP, "pop.w <register>"},
13280 {0xffbf0f00, 0xecbd0b00, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32,
13281 &EmulateInstructionARM::EmulateVPOP, "vpop.64 <list>"},
13282 {0xffbf0f00, 0xecbd0a00, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
13283 &EmulateInstructionARM::EmulateVPOP, "vpop.32 <list>"},
13285 // Supervisor Call (previously Software Interrupt)
13286 {0xffffff00, 0x0000df00, ARMvAll, eEncodingT1, No_VFP, eSize16,
13287 &EmulateInstructionARM::EmulateSVC, "svc #imm8"},
13289 // If Then makes up to four following instructions conditional.
13290 // The next 5 opcode _must_ come before the if then instruction
13291 {0xffffffff, 0x0000bf00, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize16,
13292 &EmulateInstructionARM::EmulateNop, "nop"},
13293 {0xffffffff, 0x0000bf10, ARMV7_ABOVE, eEncodingT1, No_VFP, eSize16,
13294 &EmulateInstructionARM::EmulateNop, "nop YIELD (yield hint)"},
13295 {0xffffffff, 0x0000bf20, ARMV7_ABOVE, eEncodingT1, No_VFP, eSize16,
13296 &EmulateInstructionARM::EmulateNop, "nop WFE (wait for event hint)"},
13297 {0xffffffff, 0x0000bf30, ARMV7_ABOVE, eEncodingT1, No_VFP, eSize16,
13298 &EmulateInstructionARM::EmulateNop, "nop WFI (wait for interrupt hint)"},
13299 {0xffffffff, 0x0000bf40, ARMV7_ABOVE, eEncodingT1, No_VFP, eSize16,
13300 &EmulateInstructionARM::EmulateNop, "nop SEV (send event hint)"},
13301 {0xffffff00, 0x0000bf00, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize16,
13302 &EmulateInstructionARM::EmulateIT, "it{<x>{<y>{<z>}}} <firstcond>"},
13304 // Branch instructions
13305 // To resolve ambiguity, "b<c> #imm8" should come after "svc #imm8".
13306 {0xfffff000, 0x0000d000, ARMvAll, eEncodingT1, No_VFP, eSize16,
13307 &EmulateInstructionARM::EmulateB, "b<c> #imm8 (outside IT)"},
13308 {0xfffff800, 0x0000e000, ARMvAll, eEncodingT2, No_VFP, eSize16,
13309 &EmulateInstructionARM::EmulateB, "b<c> #imm11 (outside or last in IT)"},
13310 {0xf800d000, 0xf0008000, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32,
13311 &EmulateInstructionARM::EmulateB, "b<c>.w #imm8 (outside IT)"},
13312 {0xf800d000, 0xf0009000, ARMV6T2_ABOVE, eEncodingT4, No_VFP, eSize32,
13313 &EmulateInstructionARM::EmulateB,
13314 "b<c>.w #imm8 (outside or last in IT)"},
13316 {0xf800d000, 0xf000d000, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize32,
13317 &EmulateInstructionARM::EmulateBLXImmediate, "bl <label>"},
13319 {0xf800d001, 0xf000c000, ARMV5_ABOVE, eEncodingT2, No_VFP, eSize32,
13320 &EmulateInstructionARM::EmulateBLXImmediate, "blx <label>"},
13321 {0xffffff87, 0x00004780, ARMV5_ABOVE, eEncodingT1, No_VFP, eSize16,
13322 &EmulateInstructionARM::EmulateBLXRm, "blx <Rm>"},
13323 // for example, "bx lr"
13324 {0xffffff87, 0x00004700, ARMvAll, eEncodingT1, No_VFP, eSize32,
13325 &EmulateInstructionARM::EmulateBXRm, "bx <Rm>"},
13327 {0xfff0ffff, 0xf3c08f00, ARMV5J_ABOVE, eEncodingT1, No_VFP, eSize32,
13328 &EmulateInstructionARM::EmulateBXJRm, "bxj <Rm>"},
13329 // compare and branch
13330 {0xfffff500, 0x0000b100, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize16,
13331 &EmulateInstructionARM::EmulateCB, "cb{n}z <Rn>, <label>"},
13332 // table branch byte
13333 {0xfff0fff0, 0xe8d0f000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32,
13334 &EmulateInstructionARM::EmulateTB, "tbb<c> <Rn>, <Rm>"},
13335 // table branch halfword
13336 {0xfff0fff0, 0xe8d0f010, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32,
13337 &EmulateInstructionARM::EmulateTB, "tbh<c> <Rn>, <Rm>, lsl #1"},
13339 // Data-processing instructions
13341 {0xfbe08000, 0xf1400000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32,
13342 &EmulateInstructionARM::EmulateADCImm, "adc{s}<c> <Rd>, <Rn>, #<const>"},
13344 {0xffffffc0, 0x00004140, ARMvAll, eEncodingT1, No_VFP, eSize16,
13345 &EmulateInstructionARM::EmulateADCReg, "adcs|adc<c> <Rdn>, <Rm>"},
13346 {0xffe08000, 0xeb400000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
13347 &EmulateInstructionARM::EmulateADCReg,
13348 "adc{s}<c>.w <Rd>, <Rn>, <Rm> {,<shift>}"},
13350 {0xfffffe00, 0x00001800, ARMvAll, eEncodingT1, No_VFP, eSize16,
13351 &EmulateInstructionARM::EmulateADDReg, "adds|add<c> <Rd>, <Rn>, <Rm>"},
13352 // Make sure "add sp, <Rm>" comes before this instruction, so there's no
13353 // ambiguity decoding the two.
13354 {0xffffff00, 0x00004400, ARMvAll, eEncodingT2, No_VFP, eSize16,
13355 &EmulateInstructionARM::EmulateADDReg, "add<c> <Rdn>, <Rm>"},
13357 {0xfffff800, 0x0000a000, ARMvAll, eEncodingT1, No_VFP, eSize16,
13358 &EmulateInstructionARM::EmulateADR, "add<c> <Rd>, PC, #<const>"},
13359 {0xfbff8000, 0xf2af0000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
13360 &EmulateInstructionARM::EmulateADR, "sub<c> <Rd>, PC, #<const>"},
13361 {0xfbff8000, 0xf20f0000, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32,
13362 &EmulateInstructionARM::EmulateADR, "add<c> <Rd>, PC, #<const>"},
13364 {0xfbe08000, 0xf0000000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32,
13365 &EmulateInstructionARM::EmulateANDImm, "and{s}<c> <Rd>, <Rn>, #<const>"},
13367 {0xffffffc0, 0x00004000, ARMvAll, eEncodingT1, No_VFP, eSize16,
13368 &EmulateInstructionARM::EmulateANDReg, "ands|and<c> <Rdn>, <Rm>"},
13369 {0xffe08000, 0xea000000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
13370 &EmulateInstructionARM::EmulateANDReg,
13371 "and{s}<c>.w <Rd>, <Rn>, <Rm> {,<shift>}"},
13373 {0xfbe08000, 0xf0200000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32,
13374 &EmulateInstructionARM::EmulateBICImm, "bic{s}<c> <Rd>, <Rn>, #<const>"},
13376 {0xffffffc0, 0x00004380, ARMvAll, eEncodingT1, No_VFP, eSize16,
13377 &EmulateInstructionARM::EmulateBICReg, "bics|bic<c> <Rdn>, <Rm>"},
13378 {0xffe08000, 0xea200000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
13379 &EmulateInstructionARM::EmulateBICReg,
13380 "bic{s}<c>.w <Rd>, <Rn>, <Rm> {,<shift>}"},
13382 {0xfbe08000, 0xf0800000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32,
13383 &EmulateInstructionARM::EmulateEORImm, "eor{s}<c> <Rd>, <Rn>, #<const>"},
13385 {0xffffffc0, 0x00004040, ARMvAll, eEncodingT1, No_VFP, eSize16,
13386 &EmulateInstructionARM::EmulateEORReg, "eors|eor<c> <Rdn>, <Rm>"},
13387 {0xffe08000, 0xea800000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
13388 &EmulateInstructionARM::EmulateEORReg,
13389 "eor{s}<c>.w <Rd>, <Rn>, <Rm> {,<shift>}"},
13391 {0xfbe08000, 0xf0400000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32,
13392 &EmulateInstructionARM::EmulateORRImm, "orr{s}<c> <Rd>, <Rn>, #<const>"},
13394 {0xffffffc0, 0x00004300, ARMvAll, eEncodingT1, No_VFP, eSize16,
13395 &EmulateInstructionARM::EmulateORRReg, "orrs|orr<c> <Rdn>, <Rm>"},
13396 {0xffe08000, 0xea400000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
13397 &EmulateInstructionARM::EmulateORRReg,
13398 "orr{s}<c>.w <Rd>, <Rn>, <Rm> {,<shift>}"},
13400 {0xffffffc0, 0x00004240, ARMvAll, eEncodingT1, No_VFP, eSize16,
13401 &EmulateInstructionARM::EmulateRSBImm, "rsbs|rsb<c> <Rd>, <Rn>, #0"},
13402 {0xfbe08000, 0xf1c00000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
13403 &EmulateInstructionARM::EmulateRSBImm,
13404 "rsb{s}<c>.w <Rd>, <Rn>, #<const>"},
13406 {0xffe08000, 0xea400000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32,
13407 &EmulateInstructionARM::EmulateRSBReg,
13408 "rsb{s}<c>.w <Rd>, <Rn>, <Rm> {,<shift>}"},
13410 {0xfbe08000, 0xf1600000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32,
13411 &EmulateInstructionARM::EmulateSBCImm, "sbc{s}<c> <Rd>, <Rn>, #<const>"},
13413 {0xffffffc0, 0x00004180, ARMvAll, eEncodingT1, No_VFP, eSize16,
13414 &EmulateInstructionARM::EmulateSBCReg, "sbcs|sbc<c> <Rdn>, <Rm>"},
13415 {0xffe08000, 0xeb600000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
13416 &EmulateInstructionARM::EmulateSBCReg,
13417 "sbc{s}<c>.w <Rd>, <Rn>, <Rm> {,<shift>}"},
13418 // add (immediate, Thumb)
13419 {0xfffffe00, 0x00001c00, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16,
13420 &EmulateInstructionARM::EmulateADDImmThumb,
13421 "adds|add<c> <Rd>,<Rn>,#<imm3>"},
13422 {0xfffff800, 0x00003000, ARMV4T_ABOVE, eEncodingT2, No_VFP, eSize16,
13423 &EmulateInstructionARM::EmulateADDImmThumb, "adds|add<c> <Rdn>,#<imm8>"},
13424 {0xfbe08000, 0xf1000000, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32,
13425 &EmulateInstructionARM::EmulateADDImmThumb,
13426 "add{s}<c>.w <Rd>,<Rn>,#<const>"},
13427 {0xfbf08000, 0xf2000000, ARMV6T2_ABOVE, eEncodingT4, No_VFP, eSize32,
13428 &EmulateInstructionARM::EmulateADDImmThumb,
13429 "addw<c> <Rd>,<Rn>,#<imm12>"},
13430 // sub (immediate, Thumb)
13431 {0xfffffe00, 0x00001e00, ARMvAll, eEncodingT1, No_VFP, eSize16,
13432 &EmulateInstructionARM::EmulateSUBImmThumb,
13433 "subs|sub<c> <Rd>, <Rn> #imm3"},
13434 {0xfffff800, 0x00003800, ARMvAll, eEncodingT2, No_VFP, eSize16,
13435 &EmulateInstructionARM::EmulateSUBImmThumb, "subs|sub<c> <Rdn>, #imm8"},
13436 {0xfbe08000, 0xf1a00000, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32,
13437 &EmulateInstructionARM::EmulateSUBImmThumb,
13438 "sub{s}<c>.w <Rd>, <Rn>, #<const>"},
13439 {0xfbf08000, 0xf2a00000, ARMV6T2_ABOVE, eEncodingT4, No_VFP, eSize32,
13440 &EmulateInstructionARM::EmulateSUBImmThumb,
13441 "subw<c> <Rd>, <Rn>, #imm12"},
13442 // sub (sp minus immediate)
13443 {0xfbef8000, 0xf1ad0000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
13444 &EmulateInstructionARM::EmulateSUBSPImm, "sub{s}.w <Rd>, sp, #<const>"},
13445 {0xfbff8000, 0xf2ad0000, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32,
13446 &EmulateInstructionARM::EmulateSUBSPImm, "subw<c> <Rd>, sp, #imm12"},
13448 {0xfffffe00, 0x00001a00, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16,
13449 &EmulateInstructionARM::EmulateSUBReg, "subs|sub<c> <Rd>, <Rn>, <Rm>"},
13450 {0xffe08000, 0xeba00000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
13451 &EmulateInstructionARM::EmulateSUBReg,
13452 "sub{s}<c>.w <Rd>, <Rn>, <Rm>{,<shift>}"},
13454 {0xfbf08f00, 0xf0900f00, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32,
13455 &EmulateInstructionARM::EmulateTEQImm, "teq<c> <Rn>, #<const>"},
13457 {0xfff08f00, 0xea900f00, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32,
13458 &EmulateInstructionARM::EmulateTEQReg, "teq<c> <Rn>, <Rm> {,<shift>}"},
13460 {0xfbf08f00, 0xf0100f00, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32,
13461 &EmulateInstructionARM::EmulateTSTImm, "tst<c> <Rn>, #<const>"},
13463 {0xffffffc0, 0x00004200, ARMvAll, eEncodingT1, No_VFP, eSize16,
13464 &EmulateInstructionARM::EmulateTSTReg, "tst<c> <Rdn>, <Rm>"},
13465 {0xfff08f00, 0xea100f00, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
13466 &EmulateInstructionARM::EmulateTSTReg, "tst<c>.w <Rn>, <Rm> {,<shift>}"},
13468 // move from high register to high register
13469 {0xffffff00, 0x00004600, ARMvAll, eEncodingT1, No_VFP, eSize16,
13470 &EmulateInstructionARM::EmulateMOVRdRm, "mov<c> <Rd>, <Rm>"},
13471 // move from low register to low register
13472 {0xffffffc0, 0x00000000, ARMvAll, eEncodingT2, No_VFP, eSize16,
13473 &EmulateInstructionARM::EmulateMOVRdRm, "movs <Rd>, <Rm>"},
13474 // mov{s}<c>.w <Rd>, <Rm>
13475 {0xffeff0f0, 0xea4f0000, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32,
13476 &EmulateInstructionARM::EmulateMOVRdRm, "mov{s}<c>.w <Rd>, <Rm>"},
13478 {0xfffff800, 0x00002000, ARMvAll, eEncodingT1, No_VFP, eSize16,
13479 &EmulateInstructionARM::EmulateMOVRdImm, "movs|mov<c> <Rd>, #imm8"},
13480 {0xfbef8000, 0xf04f0000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
13481 &EmulateInstructionARM::EmulateMOVRdImm, "mov{s}<c>.w <Rd>, #<const>"},
13482 {0xfbf08000, 0xf2400000, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32,
13483 &EmulateInstructionARM::EmulateMOVRdImm, "movw<c> <Rd>,#<imm16>"},
13485 {0xfbef8000, 0xf06f0000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32,
13486 &EmulateInstructionARM::EmulateMVNImm, "mvn{s} <Rd>, #<const>"},
13488 {0xffffffc0, 0x000043c0, ARMvAll, eEncodingT1, No_VFP, eSize16,
13489 &EmulateInstructionARM::EmulateMVNReg, "mvns|mvn<c> <Rd>, <Rm>"},
13490 {0xffef8000, 0xea6f0000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
13491 &EmulateInstructionARM::EmulateMVNReg,
13492 "mvn{s}<c>.w <Rd>, <Rm> {,<shift>}"},
13494 {0xfbf08f00, 0xf1100f00, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32,
13495 &EmulateInstructionARM::EmulateCMNImm, "cmn<c> <Rn>, #<const>"},
13497 {0xffffffc0, 0x000042c0, ARMvAll, eEncodingT1, No_VFP, eSize16,
13498 &EmulateInstructionARM::EmulateCMNReg, "cmn<c> <Rn>, <Rm>"},
13499 {0xfff08f00, 0xeb100f00, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
13500 &EmulateInstructionARM::EmulateCMNReg, "cmn<c> <Rn>, <Rm> {,<shift>}"},
13502 {0xfffff800, 0x00002800, ARMvAll, eEncodingT1, No_VFP, eSize16,
13503 &EmulateInstructionARM::EmulateCMPImm, "cmp<c> <Rn>, #imm8"},
13504 {0xfbf08f00, 0xf1b00f00, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
13505 &EmulateInstructionARM::EmulateCMPImm, "cmp<c>.w <Rn>, #<const>"},
13506 // cmp (register) (Rn and Rm both from r0-r7)
13507 {0xffffffc0, 0x00004280, ARMvAll, eEncodingT1, No_VFP, eSize16,
13508 &EmulateInstructionARM::EmulateCMPReg, "cmp<c> <Rn>, <Rm>"},
13509 // cmp (register) (Rn and Rm not both from r0-r7)
13510 {0xffffff00, 0x00004500, ARMvAll, eEncodingT2, No_VFP, eSize16,
13511 &EmulateInstructionARM::EmulateCMPReg, "cmp<c> <Rn>, <Rm>"},
13512 {0xfff08f00, 0xebb00f00, ARMvAll, eEncodingT3, No_VFP, eSize16,
13513 &EmulateInstructionARM::EmulateCMPReg,
13514 "cmp<c>.w <Rn>, <Rm> {, <shift>}"},
13516 {0xfffff800, 0x00001000, ARMvAll, eEncodingT1, No_VFP, eSize16,
13517 &EmulateInstructionARM::EmulateASRImm, "asrs|asr<c> <Rd>, <Rm>, #imm"},
13518 {0xffef8030, 0xea4f0020, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
13519 &EmulateInstructionARM::EmulateASRImm, "asr{s}<c>.w <Rd>, <Rm>, #imm"},
13521 {0xffffffc0, 0x00004100, ARMvAll, eEncodingT1, No_VFP, eSize16,
13522 &EmulateInstructionARM::EmulateASRReg, "asrs|asr<c> <Rdn>, <Rm>"},
13523 {0xffe0f0f0, 0xfa40f000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
13524 &EmulateInstructionARM::EmulateASRReg, "asr{s}<c>.w <Rd>, <Rn>, <Rm>"},
13526 {0xfffff800, 0x00000000, ARMvAll, eEncodingT1, No_VFP, eSize16,
13527 &EmulateInstructionARM::EmulateLSLImm, "lsls|lsl<c> <Rd>, <Rm>, #imm"},
13528 {0xffef8030, 0xea4f0000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
13529 &EmulateInstructionARM::EmulateLSLImm, "lsl{s}<c>.w <Rd>, <Rm>, #imm"},
13531 {0xffffffc0, 0x00004080, ARMvAll, eEncodingT1, No_VFP, eSize16,
13532 &EmulateInstructionARM::EmulateLSLReg, "lsls|lsl<c> <Rdn>, <Rm>"},
13533 {0xffe0f0f0, 0xfa00f000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
13534 &EmulateInstructionARM::EmulateLSLReg, "lsl{s}<c>.w <Rd>, <Rn>, <Rm>"},
13536 {0xfffff800, 0x00000800, ARMvAll, eEncodingT1, No_VFP, eSize16,
13537 &EmulateInstructionARM::EmulateLSRImm, "lsrs|lsr<c> <Rd>, <Rm>, #imm"},
13538 {0xffef8030, 0xea4f0010, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
13539 &EmulateInstructionARM::EmulateLSRImm, "lsr{s}<c>.w <Rd>, <Rm>, #imm"},
13541 {0xffffffc0, 0x000040c0, ARMvAll, eEncodingT1, No_VFP, eSize16,
13542 &EmulateInstructionARM::EmulateLSRReg, "lsrs|lsr<c> <Rdn>, <Rm>"},
13543 {0xffe0f0f0, 0xfa20f000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
13544 &EmulateInstructionARM::EmulateLSRReg, "lsr{s}<c>.w <Rd>, <Rn>, <Rm>"},
13545 // rrx is a special case encoding of ror (immediate)
13546 {0xffeff0f0, 0xea4f0030, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32,
13547 &EmulateInstructionARM::EmulateRRX, "rrx{s}<c>.w <Rd>, <Rm>"},
13549 {0xffef8030, 0xea4f0030, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32,
13550 &EmulateInstructionARM::EmulateRORImm, "ror{s}<c>.w <Rd>, <Rm>, #imm"},
13552 {0xffffffc0, 0x000041c0, ARMvAll, eEncodingT1, No_VFP, eSize16,
13553 &EmulateInstructionARM::EmulateRORReg, "rors|ror<c> <Rdn>, <Rm>"},
13554 {0xffe0f0f0, 0xfa60f000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
13555 &EmulateInstructionARM::EmulateRORReg, "ror{s}<c>.w <Rd>, <Rn>, <Rm>"},
13557 {0xffffffc0, 0x00004340, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16,
13558 &EmulateInstructionARM::EmulateMUL, "muls <Rdm>,<Rn>,<Rdm>"},
13560 {0xfff0f0f0, 0xfb00f000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
13561 &EmulateInstructionARM::EmulateMUL, "mul<c> <Rd>,<Rn>,<Rm>"},
13563 // subs pc, lr and related instructions
13564 {0xffffff00, 0xf3de8f00, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32,
13565 &EmulateInstructionARM::EmulateSUBSPcLrEtc, "SUBS<c> PC, LR, #<imm8>"},
13567 // RFE instructions *** IMPORTANT *** THESE MUST BE LISTED **BEFORE** THE
13568 // LDM.. Instructions in this table;
13569 // otherwise the wrong instructions will be selected.
13571 {0xffd0ffff, 0xe810c000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32,
13572 &EmulateInstructionARM::EmulateRFE, "rfedb<c> <Rn>{!}"},
13573 {0xffd0ffff, 0xe990c000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
13574 &EmulateInstructionARM::EmulateRFE, "rfe{ia}<c> <Rn>{!}"},
13576 // Load instructions
13577 {0xfffff800, 0x0000c800, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16,
13578 &EmulateInstructionARM::EmulateLDM, "ldm<c> <Rn>{!} <registers>"},
13579 {0xffd02000, 0xe8900000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
13580 &EmulateInstructionARM::EmulateLDM, "ldm<c>.w <Rn>{!} <registers>"},
13581 {0xffd00000, 0xe9100000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32,
13582 &EmulateInstructionARM::EmulateLDMDB, "ldmdb<c> <Rn>{!} <registers>"},
13583 {0xfffff800, 0x00006800, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16,
13584 &EmulateInstructionARM::EmulateLDRRtRnImm, "ldr<c> <Rt>, [<Rn>{,#imm}]"},
13585 {0xfffff800, 0x00009800, ARMV4T_ABOVE, eEncodingT2, No_VFP, eSize16,
13586 &EmulateInstructionARM::EmulateLDRRtRnImm, "ldr<c> <Rt>, [SP{,#imm}]"},
13587 {0xfff00000, 0xf8d00000, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32,
13588 &EmulateInstructionARM::EmulateLDRRtRnImm,
13589 "ldr<c>.w <Rt>, [<Rn>{,#imm12}]"},
13590 {0xfff00800, 0xf8500800, ARMV6T2_ABOVE, eEncodingT4, No_VFP, eSize32,
13591 &EmulateInstructionARM::EmulateLDRRtRnImm,
13592 "ldr<c> <Rt>, [<Rn>{,#+/-<imm8>}]{!}"},
13593 // Thumb2 PC-relative load into register
13594 {0xff7f0000, 0xf85f0000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
13595 &EmulateInstructionARM::EmulateLDRRtPCRelative,
13596 "ldr<c>.w <Rt>, [PC, +/-#imm}]"},
13597 {0xfffffe00, 0x00005800, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16,
13598 &EmulateInstructionARM::EmulateLDRRegister, "ldr<c> <Rt>, [<Rn>, <Rm>]"},
13599 {0xfff00fc0, 0xf8500000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
13600 &EmulateInstructionARM::EmulateLDRRegister,
13601 "ldr<c>.w <Rt>, [<Rn>,<Rm>{,LSL #<imm2>}]"},
13602 {0xfffff800, 0x00007800, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16,
13603 &EmulateInstructionARM::EmulateLDRBImmediate,
13604 "ldrb<c> <Rt>,[<Rn>{,#<imm5>}]"},
13605 {0xfff00000, 0xf8900000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
13606 &EmulateInstructionARM::EmulateLDRBImmediate,
13607 "ldrb<c>.w <Rt>,[<Rn>{,#<imm12>}]"},
13608 {0xfff00800, 0xf8100800, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32,
13609 &EmulateInstructionARM::EmulateLDRBImmediate,
13610 "ldrb<c> <Rt>,[<Rn>, #+/-<imm8>]{!}"},
13611 {0xff7f0000, 0xf81f0000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32,
13612 &EmulateInstructionARM::EmulateLDRBLiteral, "ldrb<c> <Rt>,[...]"},
13613 {0xfffffe00, 0x00005c00, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize16,
13614 &EmulateInstructionARM::EmulateLDRBRegister, "ldrb<c> <Rt>,[<Rn>,<Rm>]"},
13615 {0xfff00fc0, 0xf8100000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
13616 &EmulateInstructionARM::EmulateLDRBRegister,
13617 "ldrb<c>.w <Rt>,[<Rn>,<Rm>{,LSL #imm2>}]"},
13618 {0xfffff800, 0x00008800, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16,
13619 &EmulateInstructionARM::EmulateLDRHImmediate,
13620 "ldrh<c> <Rt>, [<Rn>{,#<imm>}]"},
13621 {0xfff00000, 0xf8b00000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
13622 &EmulateInstructionARM::EmulateLDRHImmediate,
13623 "ldrh<c>.w <Rt>,[<Rn>{,#<imm12>}]"},
13624 {0xfff00800, 0xf8300800, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32,
13625 &EmulateInstructionARM::EmulateLDRHImmediate,
13626 "ldrh<c> <Rt>,[<Rn>,#+/-<imm8>]{!}"},
13627 {0xff7f0000, 0xf83f0000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32,
13628 &EmulateInstructionARM::EmulateLDRHLiteral, "ldrh<c> <Rt>, <label>"},
13629 {0xfffffe00, 0x00005a00, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16,
13630 &EmulateInstructionARM::EmulateLDRHRegister,
13631 "ldrh<c> <Rt>, [<Rn>,<Rm>]"},
13632 {0xfff00fc0, 0xf8300000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
13633 &EmulateInstructionARM::EmulateLDRHRegister,
13634 "ldrh<c>.w <Rt>,[<Rn>,<Rm>{,LSL #<imm2>}]"},
13635 {0xfff00000, 0xf9900000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32,
13636 &EmulateInstructionARM::EmulateLDRSBImmediate,
13637 "ldrsb<c> <Rt>,[<Rn>,#<imm12>]"},
13638 {0xfff00800, 0xf9100800, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
13639 &EmulateInstructionARM::EmulateLDRSBImmediate,
13640 "ldrsb<c> <Rt>,[<Rn>,#+/-<imm8>]"},
13641 {0xff7f0000, 0xf91f0000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32,
13642 &EmulateInstructionARM::EmulateLDRSBLiteral, "ldrsb<c> <Rt>, <label>"},
13643 {0xfffffe00, 0x00005600, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16,
13644 &EmulateInstructionARM::EmulateLDRSBRegister,
13645 "ldrsb<c> <Rt>,[<Rn>,<Rm>]"},
13646 {0xfff00fc0, 0xf9100000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
13647 &EmulateInstructionARM::EmulateLDRSBRegister,
13648 "ldrsb<c>.w <Rt>,[<Rn>,<Rm>{,LSL #imm2>}]"},
13649 {0xfff00000, 0xf9b00000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32,
13650 &EmulateInstructionARM::EmulateLDRSHImmediate,
13651 "ldrsh<c> <Rt>,[<Rn>,#<imm12>]"},
13652 {0xfff00800, 0xf9300800, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
13653 &EmulateInstructionARM::EmulateLDRSHImmediate,
13654 "ldrsh<c> <Rt>,[<Rn>,#+/-<imm8>]"},
13655 {0xff7f0000, 0xf93f0000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32,
13656 &EmulateInstructionARM::EmulateLDRSHLiteral, "ldrsh<c> <Rt>,<label>"},
13657 {0xfffffe00, 0x00005e00, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16,
13658 &EmulateInstructionARM::EmulateLDRSHRegister,
13659 "ldrsh<c> <Rt>,[<Rn>,<Rm>]"},
13660 {0xfff00fc0, 0xf9300000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
13661 &EmulateInstructionARM::EmulateLDRSHRegister,
13662 "ldrsh<c>.w <Rt>,[<Rn>,<Rm>{,LSL #<imm2>}]"},
13663 {0xfe500000, 0xe8500000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32,
13664 &EmulateInstructionARM::EmulateLDRDImmediate,
13665 "ldrd<c> <Rt>, <Rt2>, [<Rn>,#+/-<imm>]!"},
13666 {0xfe100f00, 0xec100b00, ARMvAll, eEncodingT1, VFPv2_ABOVE, eSize32,
13667 &EmulateInstructionARM::EmulateVLDM, "vldm{mode}<c> <Rn>{!}, <list>"},
13668 {0xfe100f00, 0xec100a00, ARMvAll, eEncodingT2, VFPv2v3, eSize32,
13669 &EmulateInstructionARM::EmulateVLDM, "vldm{mode}<c> <Rn>{!}, <list>"},
13670 {0xffe00f00, 0xed100b00, ARMvAll, eEncodingT1, VFPv2_ABOVE, eSize32,
13671 &EmulateInstructionARM::EmulateVLDR, "vldr<c> <Dd>, [<Rn>{,#+/-<imm>}]"},
13672 {0xff300f00, 0xed100a00, ARMvAll, eEncodingT2, VFPv2v3, eSize32,
13673 &EmulateInstructionARM::EmulateVLDR, "vldr<c> <Sd>, {<Rn>{,#+/-<imm>}]"},
13674 {0xffb00000, 0xf9200000, ARMvAll, eEncodingT1, AdvancedSIMD, eSize32,
13675 &EmulateInstructionARM::EmulateVLD1Multiple,
13676 "vld1<c>.<size> <list>, [<Rn>{@<align>}],<Rm>"},
13677 {0xffb00300, 0xf9a00000, ARMvAll, eEncodingT1, AdvancedSIMD, eSize32,
13678 &EmulateInstructionARM::EmulateVLD1Single,
13679 "vld1<c>.<size> <list>, [<Rn>{@<align>}],<Rm>"},
13680 {0xffb00f00, 0xf9a00c00, ARMvAll, eEncodingT1, AdvancedSIMD, eSize32,
13681 &EmulateInstructionARM::EmulateVLD1SingleAll,
13682 "vld1<c>.<size> <list>, [<Rn>{@<align>}], <Rm>"},
13684 // Store instructions
13685 {0xfffff800, 0x0000c000, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16,
13686 &EmulateInstructionARM::EmulateSTM, "stm<c> <Rn>{!} <registers>"},
13687 {0xffd00000, 0xe8800000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
13688 &EmulateInstructionARM::EmulateSTM, "stm<c>.w <Rn>{!} <registers>"},
13689 {0xffd00000, 0xe9000000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32,
13690 &EmulateInstructionARM::EmulateSTMDB, "stmdb<c> <Rn>{!} <registers>"},
13691 {0xfffff800, 0x00006000, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16,
13692 &EmulateInstructionARM::EmulateSTRThumb, "str<c> <Rt>, [<Rn>{,#<imm>}]"},
13693 {0xfffff800, 0x00009000, ARMV4T_ABOVE, eEncodingT2, No_VFP, eSize16,
13694 &EmulateInstructionARM::EmulateSTRThumb, "str<c> <Rt>, [SP,#<imm>]"},
13695 {0xfff00000, 0xf8c00000, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32,
13696 &EmulateInstructionARM::EmulateSTRThumb,
13697 "str<c>.w <Rt>, [<Rn>,#<imm12>]"},
13698 {0xfff00800, 0xf8400800, ARMV6T2_ABOVE, eEncodingT4, No_VFP, eSize32,
13699 &EmulateInstructionARM::EmulateSTRThumb,
13700 "str<c> <Rt>, [<Rn>,#+/-<imm8>]"},
13701 {0xfffffe00, 0x00005000, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16,
13702 &EmulateInstructionARM::EmulateSTRRegister, "str<c> <Rt> ,{<Rn>, <Rm>]"},
13703 {0xfff00fc0, 0xf8400000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
13704 &EmulateInstructionARM::EmulateSTRRegister,
13705 "str<c>.w <Rt>, [<Rn>, <Rm> {lsl #imm2>}]"},
13706 {0xfffff800, 0x00007000, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16,
13707 &EmulateInstructionARM::EmulateSTRBThumb,
13708 "strb<c> <Rt>, [<Rn>, #<imm5>]"},
13709 {0xfff00000, 0xf8800000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
13710 &EmulateInstructionARM::EmulateSTRBThumb,
13711 "strb<c>.w <Rt>, [<Rn>, #<imm12>]"},
13712 {0xfff00800, 0xf8000800, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32,
13713 &EmulateInstructionARM::EmulateSTRBThumb,
13714 "strb<c> <Rt> ,[<Rn>, #+/-<imm8>]{!}"},
13715 {0xfffffe00, 0x00005200, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16,
13716 &EmulateInstructionARM::EmulateSTRHRegister, "strh<c> <Rt>,[<Rn>,<Rm>]"},
13717 {0xfff00fc0, 0xf8200000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
13718 &EmulateInstructionARM::EmulateSTRHRegister,
13719 "strh<c>.w <Rt>,[<Rn>,<Rm>{,LSL #<imm2>}]"},
13720 {0xfff00000, 0xe8400000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32,
13721 &EmulateInstructionARM::EmulateSTREX,
13722 "strex<c> <Rd>, <Rt>, [<Rn{,#<imm>}]"},
13723 {0xfe500000, 0xe8400000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32,
13724 &EmulateInstructionARM::EmulateSTRDImm,
13725 "strd<c> <Rt>, <Rt2>, [<Rn>, #+/-<imm>]!"},
13726 {0xfe100f00, 0xec000b00, ARMvAll, eEncodingT1, VFPv2_ABOVE, eSize32,
13727 &EmulateInstructionARM::EmulateVSTM, "vstm{mode}<c> <Rn>{!}, <list>"},
13728 {0xfea00f00, 0xec000a00, ARMvAll, eEncodingT2, VFPv2v3, eSize32,
13729 &EmulateInstructionARM::EmulateVSTM, "vstm{mode}<c> <Rn>{!}, <list>"},
13730 {0xff300f00, 0xed000b00, ARMvAll, eEncodingT1, VFPv2_ABOVE, eSize32,
13731 &EmulateInstructionARM::EmulateVSTR, "vstr<c> <Dd>, [<Rn>{,#+/-<imm>}]"},
13732 {0xff300f00, 0xed000a00, ARMvAll, eEncodingT2, VFPv2v3, eSize32,
13733 &EmulateInstructionARM::EmulateVSTR, "vstr<c> <Sd>, [<Rn>{,#+/-<imm>}]"},
13734 {0xffb00000, 0xf9000000, ARMvAll, eEncodingT1, AdvancedSIMD, eSize32,
13735 &EmulateInstructionARM::EmulateVST1Multiple,
13736 "vst1<c>.<size> <list>, [<Rn>{@<align>}], <Rm>"},
13737 {0xffb00300, 0xf9800000, ARMvAll, eEncodingT1, AdvancedSIMD, eSize32,
13738 &EmulateInstructionARM::EmulateVST1Single,
13739 "vst1<c>.<size> <list>, [<Rn>{@<align>}], <Rm>"},
13741 // Other instructions
13742 {0xffffffc0, 0x0000b240, ARMV6_ABOVE, eEncodingT1, No_VFP, eSize16,
13743 &EmulateInstructionARM::EmulateSXTB, "sxtb<c> <Rd>,<Rm>"},
13744 {0xfffff080, 0xfa4ff080, ARMV6_ABOVE, eEncodingT2, No_VFP, eSize32,
13745 &EmulateInstructionARM::EmulateSXTB, "sxtb<c>.w <Rd>,<Rm>{,<rotation>}"},
13746 {0xffffffc0, 0x0000b200, ARMV6_ABOVE, eEncodingT1, No_VFP, eSize16,
13747 &EmulateInstructionARM::EmulateSXTH, "sxth<c> <Rd>,<Rm>"},
13748 {0xfffff080, 0xfa0ff080, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
13749 &EmulateInstructionARM::EmulateSXTH, "sxth<c>.w <Rd>,<Rm>{,<rotation>}"},
13750 {0xffffffc0, 0x0000b2c0, ARMV6_ABOVE, eEncodingT1, No_VFP, eSize16,
13751 &EmulateInstructionARM::EmulateUXTB, "uxtb<c> <Rd>,<Rm>"},
13752 {0xfffff080, 0xfa5ff080, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
13753 &EmulateInstructionARM::EmulateUXTB, "uxtb<c>.w <Rd>,<Rm>{,<rotation>}"},
13754 {0xffffffc0, 0x0000b280, ARMV6_ABOVE, eEncodingT1, No_VFP, eSize16,
13755 &EmulateInstructionARM::EmulateUXTH, "uxth<c> <Rd>,<Rm>"},
13756 {0xfffff080, 0xfa1ff080, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
13757 &EmulateInstructionARM::EmulateUXTH, "uxth<c>.w <Rd>,<Rm>{,<rotation>}"},
13760 const size_t k_num_thumb_opcodes = llvm::array_lengthof(g_thumb_opcodes);
13761 for (size_t i = 0; i < k_num_thumb_opcodes; ++i) {
13762 if ((g_thumb_opcodes[i].mask & opcode) == g_thumb_opcodes[i].value &&
13763 (g_thumb_opcodes[i].variants & arm_isa) != 0)
13764 return &g_thumb_opcodes[i];
13769 bool EmulateInstructionARM::SetArchitecture(const ArchSpec &arch) {
13772 const char *arch_cstr = arch.GetArchitectureName();
13774 if (0 == ::strcasecmp(arch_cstr, "armv4t"))
13775 m_arm_isa = ARMv4T;
13776 else if (0 == ::strcasecmp(arch_cstr, "armv5tej"))
13777 m_arm_isa = ARMv5TEJ;
13778 else if (0 == ::strcasecmp(arch_cstr, "armv5te"))
13779 m_arm_isa = ARMv5TE;
13780 else if (0 == ::strcasecmp(arch_cstr, "armv5t"))
13781 m_arm_isa = ARMv5T;
13782 else if (0 == ::strcasecmp(arch_cstr, "armv6k"))
13783 m_arm_isa = ARMv6K;
13784 else if (0 == ::strcasecmp(arch_cstr, "armv6t2"))
13785 m_arm_isa = ARMv6T2;
13786 else if (0 == ::strcasecmp(arch_cstr, "armv7s"))
13787 m_arm_isa = ARMv7S;
13788 else if (0 == ::strcasecmp(arch_cstr, "arm"))
13789 m_arm_isa = ARMvAll;
13790 else if (0 == ::strcasecmp(arch_cstr, "thumb"))
13791 m_arm_isa = ARMvAll;
13792 else if (0 == ::strncasecmp(arch_cstr, "armv4", 5))
13794 else if (0 == ::strncasecmp(arch_cstr, "armv6", 5))
13796 else if (0 == ::strncasecmp(arch_cstr, "armv7", 5))
13798 else if (0 == ::strncasecmp(arch_cstr, "armv8", 5))
13801 return m_arm_isa != 0;
13804 bool EmulateInstructionARM::SetInstruction(const Opcode &insn_opcode,
13805 const Address &inst_addr,
13807 if (EmulateInstruction::SetInstruction(insn_opcode, inst_addr, target)) {
13808 if (m_arch.GetTriple().getArch() == llvm::Triple::thumb ||
13809 m_arch.IsAlwaysThumbInstructions())
13810 m_opcode_mode = eModeThumb;
13812 AddressClass addr_class = inst_addr.GetAddressClass();
13814 if ((addr_class == AddressClass::eCode) ||
13815 (addr_class == AddressClass::eUnknown))
13816 m_opcode_mode = eModeARM;
13817 else if (addr_class == AddressClass::eCodeAlternateISA)
13818 m_opcode_mode = eModeThumb;
13822 if (m_opcode_mode == eModeThumb || m_arch.IsAlwaysThumbInstructions())
13823 m_opcode_cpsr = CPSR_MODE_USR | MASK_CPSR_T;
13825 m_opcode_cpsr = CPSR_MODE_USR;
13831 bool EmulateInstructionARM::ReadInstruction() {
13832 bool success = false;
13833 m_opcode_cpsr = ReadRegisterUnsigned(eRegisterKindGeneric,
13834 LLDB_REGNUM_GENERIC_FLAGS, 0, &success);
13837 ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC,
13838 LLDB_INVALID_ADDRESS, &success);
13840 Context read_inst_context;
13841 read_inst_context.type = eContextReadOpcode;
13842 read_inst_context.SetNoArgs();
13844 if ((m_opcode_cpsr & MASK_CPSR_T) || m_arch.IsAlwaysThumbInstructions()) {
13845 m_opcode_mode = eModeThumb;
13846 uint32_t thumb_opcode = MemARead(read_inst_context, pc, 2, 0, &success);
13849 if ((thumb_opcode & 0xe000) != 0xe000 ||
13850 ((thumb_opcode & 0x1800u) == 0)) {
13851 m_opcode.SetOpcode16(thumb_opcode, GetByteOrder());
13853 m_opcode.SetOpcode32(
13854 (thumb_opcode << 16) |
13855 MemARead(read_inst_context, pc + 2, 2, 0, &success),
13860 m_opcode_mode = eModeARM;
13861 m_opcode.SetOpcode32(MemARead(read_inst_context, pc, 4, 0, &success),
13865 if (!m_ignore_conditions) {
13866 // If we are not ignoreing the conditions then init the it session from
13867 // the current value of cpsr.
13868 uint32_t it = (Bits32(m_opcode_cpsr, 15, 10) << 2) |
13869 Bits32(m_opcode_cpsr, 26, 25);
13871 m_it_session.InitIT(it);
13876 m_opcode_mode = eModeInvalid;
13877 m_addr = LLDB_INVALID_ADDRESS;
13882 uint32_t EmulateInstructionARM::ArchVersion() { return m_arm_isa; }
13884 bool EmulateInstructionARM::ConditionPassed(const uint32_t opcode) {
13885 // If we are ignoring conditions, then always return true. this allows us to
13886 // iterate over disassembly code and still emulate an instruction even if we
13887 // don't have all the right bits set in the CPSR register...
13888 if (m_ignore_conditions)
13891 const uint32_t cond = CurrentCond(opcode);
13892 if (cond == UINT32_MAX)
13895 bool result = false;
13896 switch (UnsignedBits(cond, 3, 1)) {
13898 if (m_opcode_cpsr == 0)
13901 result = (m_opcode_cpsr & MASK_CPSR_Z) != 0;
13904 if (m_opcode_cpsr == 0)
13907 result = (m_opcode_cpsr & MASK_CPSR_C) != 0;
13910 if (m_opcode_cpsr == 0)
13913 result = (m_opcode_cpsr & MASK_CPSR_N) != 0;
13916 if (m_opcode_cpsr == 0)
13919 result = (m_opcode_cpsr & MASK_CPSR_V) != 0;
13922 if (m_opcode_cpsr == 0)
13925 result = ((m_opcode_cpsr & MASK_CPSR_C) != 0) &&
13926 ((m_opcode_cpsr & MASK_CPSR_Z) == 0);
13929 if (m_opcode_cpsr == 0)
13932 bool n = (m_opcode_cpsr & MASK_CPSR_N);
13933 bool v = (m_opcode_cpsr & MASK_CPSR_V);
13938 if (m_opcode_cpsr == 0)
13941 bool n = (m_opcode_cpsr & MASK_CPSR_N);
13942 bool v = (m_opcode_cpsr & MASK_CPSR_V);
13943 result = n == v && ((m_opcode_cpsr & MASK_CPSR_Z) == 0);
13947 // Always execute (cond == 0b1110, or the special 0b1111 which gives
13948 // opcodes different meanings, but always means execution happens.
13957 uint32_t EmulateInstructionARM::CurrentCond(const uint32_t opcode) {
13958 switch (m_opcode_mode) {
13963 return UnsignedBits(opcode, 31, 28);
13966 // For T1 and T3 encodings of the Branch instruction, it returns the 4-bit
13967 // 'cond' field of the encoding.
13969 const uint32_t byte_size = m_opcode.GetByteSize();
13970 if (byte_size == 2) {
13971 if (Bits32(opcode, 15, 12) == 0x0d && Bits32(opcode, 11, 8) != 0x0f)
13972 return Bits32(opcode, 11, 8);
13973 } else if (byte_size == 4) {
13974 if (Bits32(opcode, 31, 27) == 0x1e && Bits32(opcode, 15, 14) == 0x02 &&
13975 Bits32(opcode, 12, 12) == 0x00 && Bits32(opcode, 25, 22) <= 0x0d) {
13976 return Bits32(opcode, 25, 22);
13979 // We have an invalid thumb instruction, let's bail out.
13982 return m_it_session.GetCond();
13985 return UINT32_MAX; // Return invalid value
13988 bool EmulateInstructionARM::InITBlock() {
13989 return CurrentInstrSet() == eModeThumb && m_it_session.InITBlock();
13992 bool EmulateInstructionARM::LastInITBlock() {
13993 return CurrentInstrSet() == eModeThumb && m_it_session.LastInITBlock();
13996 bool EmulateInstructionARM::BadMode(uint32_t mode) {
14000 return false; // '10000'
14002 return false; // '10001'
14004 return false; // '10010'
14006 return false; // '10011'
14008 return false; // '10110'
14010 return false; // '10111'
14012 return false; // '11011'
14014 return false; // '11111'
14021 bool EmulateInstructionARM::CurrentModeIsPrivileged() {
14022 uint32_t mode = Bits32(m_opcode_cpsr, 4, 0);
14033 void EmulateInstructionARM::CPSRWriteByInstr(uint32_t value, uint32_t bytemask,
14034 bool affect_execstate) {
14035 bool privileged = CurrentModeIsPrivileged();
14037 uint32_t tmp_cpsr = Bits32(m_opcode_cpsr, 23, 20) << 20;
14039 if (BitIsSet(bytemask, 3)) {
14040 tmp_cpsr = tmp_cpsr | (Bits32(value, 31, 27) << 27);
14041 if (affect_execstate)
14042 tmp_cpsr = tmp_cpsr | (Bits32(value, 26, 24) << 24);
14045 if (BitIsSet(bytemask, 2)) {
14046 tmp_cpsr = tmp_cpsr | (Bits32(value, 19, 16) << 16);
14049 if (BitIsSet(bytemask, 1)) {
14050 if (affect_execstate)
14051 tmp_cpsr = tmp_cpsr | (Bits32(value, 15, 10) << 10);
14052 tmp_cpsr = tmp_cpsr | (Bit32(value, 9) << 9);
14054 tmp_cpsr = tmp_cpsr | (Bit32(value, 8) << 8);
14057 if (BitIsSet(bytemask, 0)) {
14059 tmp_cpsr = tmp_cpsr | (Bits32(value, 7, 6) << 6);
14060 if (affect_execstate)
14061 tmp_cpsr = tmp_cpsr | (Bit32(value, 5) << 5);
14063 tmp_cpsr = tmp_cpsr | Bits32(value, 4, 0);
14066 m_opcode_cpsr = tmp_cpsr;
14069 bool EmulateInstructionARM::BranchWritePC(const Context &context,
14073 // Check the current instruction set.
14074 if (CurrentInstrSet() == eModeARM)
14075 target = addr & 0xfffffffc;
14077 target = addr & 0xfffffffe;
14079 return WriteRegisterUnsigned(context, eRegisterKindGeneric,
14080 LLDB_REGNUM_GENERIC_PC, target);
14083 // As a side effect, BXWritePC sets context.arg2 to eModeARM or eModeThumb by
14084 // inspecting addr.
14085 bool EmulateInstructionARM::BXWritePC(Context &context, uint32_t addr) {
14087 // If the CPSR is changed due to switching between ARM and Thumb ISETSTATE,
14088 // we want to record it and issue a WriteRegister callback so the clients can
14089 // track the mode changes accordingly.
14090 bool cpsr_changed = false;
14092 if (BitIsSet(addr, 0)) {
14093 if (CurrentInstrSet() != eModeThumb) {
14094 SelectInstrSet(eModeThumb);
14095 cpsr_changed = true;
14097 target = addr & 0xfffffffe;
14098 context.SetISA(eModeThumb);
14099 } else if (BitIsClear(addr, 1)) {
14100 if (CurrentInstrSet() != eModeARM) {
14101 SelectInstrSet(eModeARM);
14102 cpsr_changed = true;
14104 target = addr & 0xfffffffc;
14105 context.SetISA(eModeARM);
14107 return false; // address<1:0> == '10' => UNPREDICTABLE
14109 if (cpsr_changed) {
14110 if (!WriteRegisterUnsigned(context, eRegisterKindGeneric,
14111 LLDB_REGNUM_GENERIC_FLAGS, m_new_inst_cpsr))
14114 return WriteRegisterUnsigned(context, eRegisterKindGeneric,
14115 LLDB_REGNUM_GENERIC_PC, target);
14118 // Dispatches to either BXWritePC or BranchWritePC based on architecture
14120 bool EmulateInstructionARM::LoadWritePC(Context &context, uint32_t addr) {
14121 if (ArchVersion() >= ARMv5T)
14122 return BXWritePC(context, addr);
14124 return BranchWritePC((const Context)context, addr);
14127 // Dispatches to either BXWritePC or BranchWritePC based on architecture
14128 // versions and current instruction set.
14129 bool EmulateInstructionARM::ALUWritePC(Context &context, uint32_t addr) {
14130 if (ArchVersion() >= ARMv7 && CurrentInstrSet() == eModeARM)
14131 return BXWritePC(context, addr);
14133 return BranchWritePC((const Context)context, addr);
14136 EmulateInstructionARM::Mode EmulateInstructionARM::CurrentInstrSet() {
14137 return m_opcode_mode;
14140 // Set the 'T' bit of our CPSR. The m_opcode_mode gets updated when the next
14141 // ReadInstruction() is performed. This function has a side effect of updating
14142 // the m_new_inst_cpsr member variable if necessary.
14143 bool EmulateInstructionARM::SelectInstrSet(Mode arm_or_thumb) {
14144 m_new_inst_cpsr = m_opcode_cpsr;
14145 switch (arm_or_thumb) {
14149 // Clear the T bit.
14150 m_new_inst_cpsr &= ~MASK_CPSR_T;
14154 m_new_inst_cpsr |= MASK_CPSR_T;
14160 // This function returns TRUE if the processor currently provides support for
14161 // unaligned memory accesses, or FALSE otherwise. This is always TRUE in ARMv7,
14162 // controllable by the SCTLR.U bit in ARMv6, and always FALSE before ARMv6.
14163 bool EmulateInstructionARM::UnalignedSupport() {
14164 return (ArchVersion() >= ARMv7);
14167 // The main addition and subtraction instructions can produce status
14168 // information about both unsigned carry and signed overflow conditions. This
14169 // status information can be used to synthesize multi-word additions and
14171 EmulateInstructionARM::AddWithCarryResult
14172 EmulateInstructionARM::AddWithCarry(uint32_t x, uint32_t y, uint8_t carry_in) {
14177 uint64_t unsigned_sum = x + y + carry_in;
14178 int64_t signed_sum = (int32_t)x + (int32_t)y + (int32_t)carry_in;
14180 result = UnsignedBits(unsigned_sum, 31, 0);
14181 // carry_out = (result == unsigned_sum ? 0 : 1);
14182 overflow = ((int32_t)result == signed_sum ? 0 : 1);
14185 carry_out = ((int32_t)x >= (int32_t)(~y)) ? 1 : 0;
14187 carry_out = ((int32_t)x > (int32_t)y) ? 1 : 0;
14189 AddWithCarryResult res = {result, carry_out, overflow};
14193 uint32_t EmulateInstructionARM::ReadCoreReg(uint32_t num, bool *success) {
14194 lldb::RegisterKind reg_kind;
14198 reg_kind = eRegisterKindGeneric;
14199 reg_num = LLDB_REGNUM_GENERIC_SP;
14202 reg_kind = eRegisterKindGeneric;
14203 reg_num = LLDB_REGNUM_GENERIC_RA;
14206 reg_kind = eRegisterKindGeneric;
14207 reg_num = LLDB_REGNUM_GENERIC_PC;
14210 if (num < SP_REG) {
14211 reg_kind = eRegisterKindDWARF;
14212 reg_num = dwarf_r0 + num;
14214 // assert(0 && "Invalid register number");
14221 // Read our register.
14222 uint32_t val = ReadRegisterUnsigned(reg_kind, reg_num, 0, success);
14224 // When executing an ARM instruction , PC reads as the address of the current
14225 // instruction plus 8. When executing a Thumb instruction , PC reads as the
14226 // address of the current instruction plus 4.
14228 if (CurrentInstrSet() == eModeARM)
14237 // Write the result to the ARM core register Rd, and optionally update the
14238 // condition flags based on the result.
14240 // This helper method tries to encapsulate the following pseudocode from the
14241 // ARM Architecture Reference Manual:
14243 // if d == 15 then // Can only occur for encoding A1
14244 // ALUWritePC(result); // setflags is always FALSE here
14247 // if setflags then
14248 // APSR.N = result<31>;
14249 // APSR.Z = IsZeroBit(result);
14251 // // APSR.V unchanged
14253 // In the above case, the API client does not pass in the overflow arg, which
14254 // defaults to ~0u.
14255 bool EmulateInstructionARM::WriteCoreRegOptionalFlags(
14256 Context &context, const uint32_t result, const uint32_t Rd, bool setflags,
14257 const uint32_t carry, const uint32_t overflow) {
14259 if (!ALUWritePC(context, result))
14262 lldb::RegisterKind reg_kind;
14266 reg_kind = eRegisterKindGeneric;
14267 reg_num = LLDB_REGNUM_GENERIC_SP;
14270 reg_kind = eRegisterKindGeneric;
14271 reg_num = LLDB_REGNUM_GENERIC_RA;
14274 reg_kind = eRegisterKindDWARF;
14275 reg_num = dwarf_r0 + Rd;
14277 if (!WriteRegisterUnsigned(context, reg_kind, reg_num, result))
14280 return WriteFlags(context, result, carry, overflow);
14285 // This helper method tries to encapsulate the following pseudocode from the
14286 // ARM Architecture Reference Manual:
14288 // APSR.N = result<31>;
14289 // APSR.Z = IsZeroBit(result);
14291 // APSR.V = overflow
14293 // Default arguments can be specified for carry and overflow parameters, which
14294 // means not to update the respective flags.
14295 bool EmulateInstructionARM::WriteFlags(Context &context, const uint32_t result,
14296 const uint32_t carry,
14297 const uint32_t overflow) {
14298 m_new_inst_cpsr = m_opcode_cpsr;
14299 SetBit32(m_new_inst_cpsr, CPSR_N_POS, Bit32(result, CPSR_N_POS));
14300 SetBit32(m_new_inst_cpsr, CPSR_Z_POS, result == 0 ? 1 : 0);
14302 SetBit32(m_new_inst_cpsr, CPSR_C_POS, carry);
14303 if (overflow != ~0u)
14304 SetBit32(m_new_inst_cpsr, CPSR_V_POS, overflow);
14305 if (m_new_inst_cpsr != m_opcode_cpsr) {
14306 if (!WriteRegisterUnsigned(context, eRegisterKindGeneric,
14307 LLDB_REGNUM_GENERIC_FLAGS, m_new_inst_cpsr))
14313 bool EmulateInstructionARM::EvaluateInstruction(uint32_t evaluate_options) {
14314 ARMOpcode *opcode_data = nullptr;
14316 if (m_opcode_mode == eModeThumb)
14318 GetThumbOpcodeForInstruction(m_opcode.GetOpcode32(), m_arm_isa);
14319 else if (m_opcode_mode == eModeARM)
14320 opcode_data = GetARMOpcodeForInstruction(m_opcode.GetOpcode32(), m_arm_isa);
14322 const bool auto_advance_pc =
14323 evaluate_options & eEmulateInstructionOptionAutoAdvancePC;
14324 m_ignore_conditions =
14325 evaluate_options & eEmulateInstructionOptionIgnoreConditions;
14327 bool success = false;
14328 if (m_opcode_cpsr == 0 || !m_ignore_conditions) {
14330 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_cpsr, 0, &success);
14333 // Only return false if we are unable to read the CPSR if we care about
14335 if (!success && !m_ignore_conditions)
14338 uint32_t orig_pc_value = 0;
14339 if (auto_advance_pc) {
14341 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc, 0, &success);
14346 // Call the Emulate... function if we managed to decode the opcode.
14348 success = (this->*opcode_data->callback)(m_opcode.GetOpcode32(),
14349 opcode_data->encoding);
14354 // Advance the ITSTATE bits to their values for the next instruction if we
14355 // haven't just executed an IT instruction what initialized it.
14356 if (m_opcode_mode == eModeThumb && m_it_session.InITBlock() &&
14357 (opcode_data == nullptr ||
14358 opcode_data->callback != &EmulateInstructionARM::EmulateIT))
14359 m_it_session.ITAdvance();
14361 if (auto_advance_pc) {
14362 uint32_t after_pc_value =
14363 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc, 0, &success);
14367 if (auto_advance_pc && (after_pc_value == orig_pc_value)) {
14368 after_pc_value += m_opcode.GetByteSize();
14370 EmulateInstruction::Context context;
14371 context.type = eContextAdvancePC;
14372 context.SetNoArgs();
14373 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc,
14381 EmulateInstruction::InstructionCondition
14382 EmulateInstructionARM::GetInstructionCondition() {
14383 const uint32_t cond = CurrentCond(m_opcode.GetOpcode32());
14384 if (cond == 0xe || cond == 0xf || cond == UINT32_MAX)
14385 return EmulateInstruction::UnconditionalCondition;
14389 bool EmulateInstructionARM::TestEmulation(Stream *out_stream, ArchSpec &arch,
14390 OptionValueDictionary *test_data) {
14392 out_stream->Printf("TestEmulation: Missing test data.\n");
14396 static ConstString opcode_key("opcode");
14397 static ConstString before_key("before_state");
14398 static ConstString after_key("after_state");
14400 OptionValueSP value_sp = test_data->GetValueForKey(opcode_key);
14402 uint32_t test_opcode;
14403 if ((value_sp.get() == nullptr) ||
14404 (value_sp->GetType() != OptionValue::eTypeUInt64)) {
14405 out_stream->Printf("TestEmulation: Error reading opcode from test file.\n");
14408 test_opcode = value_sp->GetUInt64Value();
14410 if (arch.GetTriple().getArch() == llvm::Triple::thumb ||
14411 arch.IsAlwaysThumbInstructions()) {
14412 m_opcode_mode = eModeThumb;
14413 if (test_opcode < 0x10000)
14414 m_opcode.SetOpcode16(test_opcode, endian::InlHostByteOrder());
14416 m_opcode.SetOpcode32(test_opcode, endian::InlHostByteOrder());
14417 } else if (arch.GetTriple().getArch() == llvm::Triple::arm) {
14418 m_opcode_mode = eModeARM;
14419 m_opcode.SetOpcode32(test_opcode, endian::InlHostByteOrder());
14421 out_stream->Printf("TestEmulation: Invalid arch.\n");
14425 EmulationStateARM before_state;
14426 EmulationStateARM after_state;
14428 value_sp = test_data->GetValueForKey(before_key);
14429 if ((value_sp.get() == nullptr) ||
14430 (value_sp->GetType() != OptionValue::eTypeDictionary)) {
14431 out_stream->Printf("TestEmulation: Failed to find 'before' state.\n");
14435 OptionValueDictionary *state_dictionary = value_sp->GetAsDictionary();
14436 if (!before_state.LoadStateFromDictionary(state_dictionary)) {
14437 out_stream->Printf("TestEmulation: Failed loading 'before' state.\n");
14441 value_sp = test_data->GetValueForKey(after_key);
14442 if ((value_sp.get() == nullptr) ||
14443 (value_sp->GetType() != OptionValue::eTypeDictionary)) {
14444 out_stream->Printf("TestEmulation: Failed to find 'after' state.\n");
14448 state_dictionary = value_sp->GetAsDictionary();
14449 if (!after_state.LoadStateFromDictionary(state_dictionary)) {
14450 out_stream->Printf("TestEmulation: Failed loading 'after' state.\n");
14454 SetBaton((void *)&before_state);
14455 SetCallbacks(&EmulationStateARM::ReadPseudoMemory,
14456 &EmulationStateARM::WritePseudoMemory,
14457 &EmulationStateARM::ReadPseudoRegister,
14458 &EmulationStateARM::WritePseudoRegister);
14460 bool success = EvaluateInstruction(eEmulateInstructionOptionAutoAdvancePC);
14462 out_stream->Printf("TestEmulation: EvaluateInstruction() failed.\n");
14466 success = before_state.CompareState(after_state);
14468 out_stream->Printf(
14469 "TestEmulation: 'before' and 'after' states do not match.\n");
14476 // EmulateInstructionARM::GetRegisterName (uint32_t reg_kind, uint32_t reg_num)
14478 // if (reg_kind == eRegisterKindGeneric)
14480 // switch (reg_num)
14482 // case LLDB_REGNUM_GENERIC_PC: return "pc";
14483 // case LLDB_REGNUM_GENERIC_SP: return "sp";
14484 // case LLDB_REGNUM_GENERIC_FP: return "fp";
14485 // case LLDB_REGNUM_GENERIC_RA: return "lr";
14486 // case LLDB_REGNUM_GENERIC_FLAGS: return "cpsr";
14487 // default: return NULL;
14490 // else if (reg_kind == eRegisterKindDWARF)
14492 // return GetARMDWARFRegisterName (reg_num);
14497 bool EmulateInstructionARM::CreateFunctionEntryUnwind(UnwindPlan &unwind_plan) {
14498 unwind_plan.Clear();
14499 unwind_plan.SetRegisterKind(eRegisterKindDWARF);
14501 UnwindPlan::RowSP row(new UnwindPlan::Row);
14503 // Our previous Call Frame Address is the stack pointer
14504 row->GetCFAValue().SetIsRegisterPlusOffset(dwarf_sp, 0);
14506 unwind_plan.AppendRow(row);
14507 unwind_plan.SetSourceName("EmulateInstructionARM");
14508 unwind_plan.SetSourcedFromCompiler(eLazyBoolNo);
14509 unwind_plan.SetUnwindPlanValidAtAllInstructions(eLazyBoolYes);
14510 unwind_plan.SetReturnAddressRegister(dwarf_lr);