1 //===-- EmulateInstructionARM.cpp -----------------------------------------===//
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 //===----------------------------------------------------------------------===//
12 #include "EmulateInstructionARM.h"
13 #include "EmulationStateARM.h"
14 #include "lldb/Core/Address.h"
15 #include "lldb/Core/PluginManager.h"
16 #include "lldb/Host/PosixApi.h"
17 #include "lldb/Interpreter/OptionValueArray.h"
18 #include "lldb/Interpreter/OptionValueDictionary.h"
19 #include "lldb/Symbol/UnwindPlan.h"
20 #include "lldb/Utility/ArchSpec.h"
21 #include "lldb/Utility/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 LLDB_PLUGIN_DEFINE_ADV(EmulateInstructionARM
, InstructionARM
)
35 // Convenient macro definitions.
36 #define APSR_C Bit32(m_opcode_cpsr, CPSR_C_POS)
37 #define APSR_V Bit32(m_opcode_cpsr, CPSR_V_POS)
39 #define AlignPC(pc_val) (pc_val & 0xFFFFFFFC)
42 // ITSession implementation
45 static std::optional
<RegisterInfo
> GetARMDWARFRegisterInfo(unsigned reg_num
) {
46 RegisterInfo reg_info
;
47 ::memset(®_info
, 0, sizeof(RegisterInfo
));
48 ::memset(reg_info
.kinds
, LLDB_INVALID_REGNUM
, sizeof(reg_info
.kinds
));
50 if (reg_num
>= dwarf_q0
&& reg_num
<= dwarf_q15
) {
51 reg_info
.byte_size
= 16;
52 reg_info
.format
= eFormatVectorOfUInt8
;
53 reg_info
.encoding
= eEncodingVector
;
56 if (reg_num
>= dwarf_d0
&& reg_num
<= dwarf_d31
) {
57 reg_info
.byte_size
= 8;
58 reg_info
.format
= eFormatFloat
;
59 reg_info
.encoding
= eEncodingIEEE754
;
60 } else if (reg_num
>= dwarf_s0
&& reg_num
<= dwarf_s31
) {
61 reg_info
.byte_size
= 4;
62 reg_info
.format
= eFormatFloat
;
63 reg_info
.encoding
= eEncodingIEEE754
;
64 } else if (reg_num
>= dwarf_f0
&& reg_num
<= dwarf_f7
) {
65 reg_info
.byte_size
= 12;
66 reg_info
.format
= eFormatFloat
;
67 reg_info
.encoding
= eEncodingIEEE754
;
69 reg_info
.byte_size
= 4;
70 reg_info
.format
= eFormatHex
;
71 reg_info
.encoding
= eEncodingUint
;
74 reg_info
.kinds
[eRegisterKindDWARF
] = reg_num
;
100 reg_info
.kinds
[eRegisterKindGeneric
] = LLDB_REGNUM_GENERIC_FP
;
103 reg_info
.name
= "r8";
106 reg_info
.name
= "r9";
109 reg_info
.name
= "r10";
112 reg_info
.name
= "r11";
115 reg_info
.name
= "r12";
118 reg_info
.name
= "sp";
119 reg_info
.alt_name
= "r13";
120 reg_info
.kinds
[eRegisterKindGeneric
] = LLDB_REGNUM_GENERIC_SP
;
123 reg_info
.name
= "lr";
124 reg_info
.alt_name
= "r14";
125 reg_info
.kinds
[eRegisterKindGeneric
] = LLDB_REGNUM_GENERIC_RA
;
128 reg_info
.name
= "pc";
129 reg_info
.alt_name
= "r15";
130 reg_info
.kinds
[eRegisterKindGeneric
] = LLDB_REGNUM_GENERIC_PC
;
133 reg_info
.name
= "cpsr";
134 reg_info
.kinds
[eRegisterKindGeneric
] = LLDB_REGNUM_GENERIC_FLAGS
;
138 reg_info
.name
= "s0";
141 reg_info
.name
= "s1";
144 reg_info
.name
= "s2";
147 reg_info
.name
= "s3";
150 reg_info
.name
= "s4";
153 reg_info
.name
= "s5";
156 reg_info
.name
= "s6";
159 reg_info
.name
= "s7";
162 reg_info
.name
= "s8";
165 reg_info
.name
= "s9";
168 reg_info
.name
= "s10";
171 reg_info
.name
= "s11";
174 reg_info
.name
= "s12";
177 reg_info
.name
= "s13";
180 reg_info
.name
= "s14";
183 reg_info
.name
= "s15";
186 reg_info
.name
= "s16";
189 reg_info
.name
= "s17";
192 reg_info
.name
= "s18";
195 reg_info
.name
= "s19";
198 reg_info
.name
= "s20";
201 reg_info
.name
= "s21";
204 reg_info
.name
= "s22";
207 reg_info
.name
= "s23";
210 reg_info
.name
= "s24";
213 reg_info
.name
= "s25";
216 reg_info
.name
= "s26";
219 reg_info
.name
= "s27";
222 reg_info
.name
= "s28";
225 reg_info
.name
= "s29";
228 reg_info
.name
= "s30";
231 reg_info
.name
= "s31";
236 reg_info
.name
= "f0";
239 reg_info
.name
= "f1";
242 reg_info
.name
= "f2";
245 reg_info
.name
= "f3";
248 reg_info
.name
= "f4";
251 reg_info
.name
= "f5";
254 reg_info
.name
= "f6";
257 reg_info
.name
= "f7";
260 // Intel wireless MMX general purpose registers 0 - 7 XScale accumulator
261 // register 0 - 7 (they do overlap with wCGR0 - wCGR7)
263 reg_info
.name
= "wCGR0/ACC0";
266 reg_info
.name
= "wCGR1/ACC1";
269 reg_info
.name
= "wCGR2/ACC2";
272 reg_info
.name
= "wCGR3/ACC3";
275 reg_info
.name
= "wCGR4/ACC4";
278 reg_info
.name
= "wCGR5/ACC5";
281 reg_info
.name
= "wCGR6/ACC6";
284 reg_info
.name
= "wCGR7/ACC7";
287 // Intel wireless MMX data registers 0 - 15
289 reg_info
.name
= "wR0";
292 reg_info
.name
= "wR1";
295 reg_info
.name
= "wR2";
298 reg_info
.name
= "wR3";
301 reg_info
.name
= "wR4";
304 reg_info
.name
= "wR5";
307 reg_info
.name
= "wR6";
310 reg_info
.name
= "wR7";
313 reg_info
.name
= "wR8";
316 reg_info
.name
= "wR9";
319 reg_info
.name
= "wR10";
322 reg_info
.name
= "wR11";
325 reg_info
.name
= "wR12";
328 reg_info
.name
= "wR13";
331 reg_info
.name
= "wR14";
334 reg_info
.name
= "wR15";
338 reg_info
.name
= "spsr";
341 reg_info
.name
= "spsr_fiq";
344 reg_info
.name
= "spsr_irq";
347 reg_info
.name
= "spsr_abt";
350 reg_info
.name
= "spsr_und";
353 reg_info
.name
= "spsr_svc";
357 reg_info
.name
= "r8_usr";
360 reg_info
.name
= "r9_usr";
363 reg_info
.name
= "r10_usr";
366 reg_info
.name
= "r11_usr";
369 reg_info
.name
= "r12_usr";
372 reg_info
.name
= "r13_usr";
375 reg_info
.name
= "r14_usr";
378 reg_info
.name
= "r8_fiq";
381 reg_info
.name
= "r9_fiq";
384 reg_info
.name
= "r10_fiq";
387 reg_info
.name
= "r11_fiq";
390 reg_info
.name
= "r12_fiq";
393 reg_info
.name
= "r13_fiq";
396 reg_info
.name
= "r14_fiq";
399 reg_info
.name
= "r13_irq";
402 reg_info
.name
= "r14_irq";
405 reg_info
.name
= "r13_abt";
408 reg_info
.name
= "r14_abt";
411 reg_info
.name
= "r13_und";
414 reg_info
.name
= "r14_und";
417 reg_info
.name
= "r13_svc";
420 reg_info
.name
= "r14_svc";
423 // Intel wireless MMX control register in co-processor 0 - 7
425 reg_info
.name
= "wC0";
428 reg_info
.name
= "wC1";
431 reg_info
.name
= "wC2";
434 reg_info
.name
= "wC3";
437 reg_info
.name
= "wC4";
440 reg_info
.name
= "wC5";
443 reg_info
.name
= "wC6";
446 reg_info
.name
= "wC7";
451 reg_info
.name
= "d0";
454 reg_info
.name
= "d1";
457 reg_info
.name
= "d2";
460 reg_info
.name
= "d3";
463 reg_info
.name
= "d4";
466 reg_info
.name
= "d5";
469 reg_info
.name
= "d6";
472 reg_info
.name
= "d7";
475 reg_info
.name
= "d8";
478 reg_info
.name
= "d9";
481 reg_info
.name
= "d10";
484 reg_info
.name
= "d11";
487 reg_info
.name
= "d12";
490 reg_info
.name
= "d13";
493 reg_info
.name
= "d14";
496 reg_info
.name
= "d15";
499 reg_info
.name
= "d16";
502 reg_info
.name
= "d17";
505 reg_info
.name
= "d18";
508 reg_info
.name
= "d19";
511 reg_info
.name
= "d20";
514 reg_info
.name
= "d21";
517 reg_info
.name
= "d22";
520 reg_info
.name
= "d23";
523 reg_info
.name
= "d24";
526 reg_info
.name
= "d25";
529 reg_info
.name
= "d26";
532 reg_info
.name
= "d27";
535 reg_info
.name
= "d28";
538 reg_info
.name
= "d29";
541 reg_info
.name
= "d30";
544 reg_info
.name
= "d31";
547 // NEON 128-bit vector registers (overlays the d registers)
549 reg_info
.name
= "q0";
552 reg_info
.name
= "q1";
555 reg_info
.name
= "q2";
558 reg_info
.name
= "q3";
561 reg_info
.name
= "q4";
564 reg_info
.name
= "q5";
567 reg_info
.name
= "q6";
570 reg_info
.name
= "q7";
573 reg_info
.name
= "q8";
576 reg_info
.name
= "q9";
579 reg_info
.name
= "q10";
582 reg_info
.name
= "q11";
585 reg_info
.name
= "q12";
588 reg_info
.name
= "q13";
591 reg_info
.name
= "q14";
594 reg_info
.name
= "q15";
604 // Valid return values are {1, 2, 3, 4}, with 0 signifying an error condition.
605 static uint32_t CountITSize(uint32_t ITMask
) {
606 // First count the trailing zeros of the IT mask.
607 uint32_t TZ
= llvm::countr_zero(ITMask
);
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) {
625 if (FirstCond
== 0xE && ITCounter
!= 1) {
633 // Update ITState if necessary.
634 void ITSession::ITAdvance() {
635 // assert(ITCounter);
640 unsigned short NewITState4_0
= Bits32(ITState
, 4, 0) << 1;
641 SetBits32(ITState
, 4, 0, NewITState4_0
);
645 // Return true if we're inside an IT Block.
646 bool ITSession::InITBlock() { return ITCounter
!= 0; }
648 // Return true if we're the last instruction inside an IT Block.
649 bool ITSession::LastInITBlock() { return ITCounter
== 1; }
651 // Get condition bits for the current thumb instruction.
652 uint32_t ITSession::GetCond() {
654 return Bits32(ITState
, 7, 4);
659 // ARM constants used during decoding
661 #define LDM_REGLIST 1
665 #define PC_REGLIST_BIT 0x8000
667 #define ARMv4 (1u << 0)
668 #define ARMv4T (1u << 1)
669 #define ARMv5T (1u << 2)
670 #define ARMv5TE (1u << 3)
671 #define ARMv5TEJ (1u << 4)
672 #define ARMv6 (1u << 5)
673 #define ARMv6K (1u << 6)
674 #define ARMv6T2 (1u << 7)
675 #define ARMv7 (1u << 8)
676 #define ARMv7S (1u << 9)
677 #define ARMv8 (1u << 10)
678 #define ARMvAll (0xffffffffu)
680 #define ARMV4T_ABOVE \
681 (ARMv4T | ARMv5T | ARMv5TE | ARMv5TEJ | ARMv6 | ARMv6K | ARMv6T2 | ARMv7 | \
683 #define ARMV5_ABOVE \
684 (ARMv5T | ARMv5TE | ARMv5TEJ | ARMv6 | ARMv6K | ARMv6T2 | ARMv7 | ARMv7S | \
686 #define ARMV5TE_ABOVE \
687 (ARMv5TE | ARMv5TEJ | ARMv6 | ARMv6K | ARMv6T2 | ARMv7 | ARMv7S | ARMv8)
688 #define ARMV5J_ABOVE \
689 (ARMv5TEJ | ARMv6 | ARMv6K | ARMv6T2 | ARMv7 | ARMv7S | ARMv8)
690 #define ARMV6_ABOVE (ARMv6 | ARMv6K | ARMv6T2 | ARMv7 | ARMv7S | ARMv8)
691 #define ARMV6T2_ABOVE (ARMv6T2 | ARMv7 | ARMv7S | ARMv8)
692 #define ARMV7_ABOVE (ARMv7 | ARMv7S | ARMv8)
695 #define VFPv1 (1u << 1)
696 #define VFPv2 (1u << 2)
697 #define VFPv3 (1u << 3)
698 #define AdvancedSIMD (1u << 4)
700 #define VFPv1_ABOVE (VFPv1 | VFPv2 | VFPv3 | AdvancedSIMD)
701 #define VFPv2_ABOVE (VFPv2 | VFPv3 | AdvancedSIMD)
702 #define VFPv2v3 (VFPv2 | VFPv3)
705 // EmulateInstructionARM implementation
708 void EmulateInstructionARM::Initialize() {
709 PluginManager::RegisterPlugin(GetPluginNameStatic(),
710 GetPluginDescriptionStatic(), CreateInstance
);
713 void EmulateInstructionARM::Terminate() {
714 PluginManager::UnregisterPlugin(CreateInstance
);
717 llvm::StringRef
EmulateInstructionARM::GetPluginDescriptionStatic() {
718 return "Emulate instructions for the ARM architecture.";
722 EmulateInstructionARM::CreateInstance(const ArchSpec
&arch
,
723 InstructionType inst_type
) {
724 if (EmulateInstructionARM::SupportsEmulatingInstructionsOfTypeStatic(
726 if (arch
.GetTriple().getArch() == llvm::Triple::arm
) {
727 std::unique_ptr
<EmulateInstructionARM
> emulate_insn_up(
728 new EmulateInstructionARM(arch
));
731 return emulate_insn_up
.release();
732 } else if (arch
.GetTriple().getArch() == llvm::Triple::thumb
) {
733 std::unique_ptr
<EmulateInstructionARM
> emulate_insn_up(
734 new EmulateInstructionARM(arch
));
737 return emulate_insn_up
.release();
744 bool EmulateInstructionARM::SetTargetTriple(const ArchSpec
&arch
) {
745 if (arch
.GetTriple().getArch() == llvm::Triple::arm
)
747 else if (arch
.GetTriple().getArch() == llvm::Triple::thumb
)
753 // Write "bits (32) UNKNOWN" to memory address "address". Helper function for
754 // many ARM instructions.
755 bool EmulateInstructionARM::WriteBits32UnknownToMemory(addr_t address
) {
756 EmulateInstruction::Context context
;
757 context
.type
= EmulateInstruction::eContextWriteMemoryRandomBits
;
760 uint32_t random_data
= rand();
761 const uint32_t addr_byte_size
= GetAddressByteSize();
763 return MemAWrite(context
, address
, random_data
, addr_byte_size
);
766 // Write "bits (32) UNKNOWN" to register n. Helper function for many ARM
768 bool EmulateInstructionARM::WriteBits32Unknown(int n
) {
769 EmulateInstruction::Context context
;
770 context
.type
= EmulateInstruction::eContextWriteRegisterRandomBits
;
775 ReadRegisterUnsigned(eRegisterKindDWARF
, dwarf_r0
+ n
, 0, &success
);
780 if (!WriteRegisterUnsigned(context
, eRegisterKindDWARF
, dwarf_r0
+ n
, data
))
786 std::optional
<RegisterInfo
>
787 EmulateInstructionARM::GetRegisterInfo(lldb::RegisterKind reg_kind
,
789 if (reg_kind
== eRegisterKindGeneric
) {
791 case LLDB_REGNUM_GENERIC_PC
:
792 reg_kind
= eRegisterKindDWARF
;
795 case LLDB_REGNUM_GENERIC_SP
:
796 reg_kind
= eRegisterKindDWARF
;
799 case LLDB_REGNUM_GENERIC_FP
:
800 reg_kind
= eRegisterKindDWARF
;
803 case LLDB_REGNUM_GENERIC_RA
:
804 reg_kind
= eRegisterKindDWARF
;
807 case LLDB_REGNUM_GENERIC_FLAGS
:
808 reg_kind
= eRegisterKindDWARF
;
809 reg_num
= dwarf_cpsr
;
816 if (reg_kind
== eRegisterKindDWARF
)
817 return GetARMDWARFRegisterInfo(reg_num
);
821 uint32_t EmulateInstructionARM::GetFramePointerRegisterNumber() const {
822 if (m_arch
.GetTriple().isAndroid())
823 return LLDB_INVALID_REGNUM
; // Don't use frame pointer on android
824 bool is_apple
= false;
825 if (m_arch
.GetTriple().getVendor() == llvm::Triple::Apple
)
827 switch (m_arch
.GetTriple().getOS()) {
828 case llvm::Triple::Darwin
:
829 case llvm::Triple::MacOSX
:
830 case llvm::Triple::IOS
:
831 case llvm::Triple::TvOS
:
832 case llvm::Triple::WatchOS
:
833 case llvm::Triple::XROS
:
834 case llvm::Triple::BridgeOS
:
841 /* On Apple iOS et al, the frame pointer register is always r7.
842 * Typically on other ARM systems, thumb code uses r7; arm code uses r11.
843 * Windows on ARM, which is in thumb mode, uses r11 though.
846 uint32_t fp_regnum
= 11;
851 if (m_opcode_mode
== eModeThumb
&& !m_arch
.GetTriple().isOSWindows())
857 uint32_t EmulateInstructionARM::GetFramePointerDWARFRegisterNumber() const {
858 bool is_apple
= false;
859 if (m_arch
.GetTriple().getVendor() == llvm::Triple::Apple
)
861 switch (m_arch
.GetTriple().getOS()) {
862 case llvm::Triple::Darwin
:
863 case llvm::Triple::MacOSX
:
864 case llvm::Triple::IOS
:
871 /* On Apple iOS et al, the frame pointer register is always r7.
872 * Typically on other ARM systems, thumb code uses r7; arm code uses r11.
873 * Windows on ARM, which is in thumb mode, uses r11 though.
876 uint32_t fp_regnum
= dwarf_r11
;
879 fp_regnum
= dwarf_r7
;
881 if (m_opcode_mode
== eModeThumb
&& !m_arch
.GetTriple().isOSWindows())
882 fp_regnum
= dwarf_r7
;
887 // Push Multiple Registers stores multiple registers to the stack, storing to
888 // consecutive memory locations ending just below the address in SP, and
890 // SP to point to the start of the stored data.
891 bool EmulateInstructionARM::EmulatePUSH(const uint32_t opcode
,
892 const ARMEncoding encoding
) {
894 // ARM pseudo code...
895 if (ConditionPassed())
897 EncodingSpecificOperations();
898 NullCheckIfThumbEE(13);
899 address
= SP
- 4*BitCount(registers
);
903 if (registers
<i
> == '1')
905 if i
== 13 && i
!= LowestSetBit(registers
) // Only possible for encoding A1
906 MemA
[address
,4] = bits(32) UNKNOWN
;
908 MemA
[address
,4] = R
[i
];
909 address
= address
+ 4;
913 if (registers
<15> == '1') // Only possible for encoding A1 or A2
914 MemA
[address
,4] = PCStoreValue();
916 SP
= SP
- 4*BitCount(registers
);
920 bool success
= false;
921 if (ConditionPassed(opcode
)) {
922 const uint32_t addr_byte_size
= GetAddressByteSize();
923 const addr_t sp
= ReadCoreReg(SP_REG
, &success
);
926 uint32_t registers
= 0;
927 uint32_t Rt
; // the source register
930 registers
= Bits32(opcode
, 7, 0);
931 // The M bit represents LR.
932 if (Bit32(opcode
, 8))
933 registers
|= (1u << 14);
934 // if BitCount(registers) < 1 then UNPREDICTABLE;
935 if (BitCount(registers
) < 1)
939 // Ignore bits 15 & 13.
940 registers
= Bits32(opcode
, 15, 0) & ~0xa000;
941 // if BitCount(registers) < 2 then UNPREDICTABLE;
942 if (BitCount(registers
) < 2)
946 Rt
= Bits32(opcode
, 15, 12);
947 // if BadReg(t) then UNPREDICTABLE;
950 registers
= (1u << Rt
);
953 registers
= Bits32(opcode
, 15, 0);
954 // Instead of return false, let's handle the following case as well,
955 // which amounts to pushing one reg onto the full descending stacks.
956 // if BitCount(register_list) < 2 then SEE STMDB / STMFD;
959 Rt
= Bits32(opcode
, 15, 12);
960 // if t == 13 then UNPREDICTABLE;
963 registers
= (1u << Rt
);
968 addr_t sp_offset
= addr_byte_size
* BitCount(registers
);
969 addr_t addr
= sp
- sp_offset
;
972 EmulateInstruction::Context context
;
973 context
.type
= EmulateInstruction::eContextPushRegisterOnStack
;
974 std::optional
<RegisterInfo
> sp_reg
=
975 GetRegisterInfo(eRegisterKindDWARF
, dwarf_sp
);
976 for (i
= 0; i
< 15; ++i
) {
977 if (BitIsSet(registers
, i
)) {
978 std::optional
<RegisterInfo
> reg_info
=
979 GetRegisterInfo(eRegisterKindDWARF
, dwarf_r0
+ i
);
980 context
.SetRegisterToRegisterPlusOffset(*reg_info
, *sp_reg
, addr
- sp
);
981 uint32_t reg_value
= ReadCoreReg(i
, &success
);
984 if (!MemAWrite(context
, addr
, reg_value
, addr_byte_size
))
986 addr
+= addr_byte_size
;
990 if (BitIsSet(registers
, 15)) {
991 std::optional
<RegisterInfo
> reg_info
=
992 GetRegisterInfo(eRegisterKindDWARF
, dwarf_pc
);
993 context
.SetRegisterToRegisterPlusOffset(*reg_info
, *sp_reg
, addr
- sp
);
994 const uint32_t pc
= ReadCoreReg(PC_REG
, &success
);
997 if (!MemAWrite(context
, addr
, pc
, addr_byte_size
))
1001 context
.type
= EmulateInstruction::eContextAdjustStackPointer
;
1002 context
.SetImmediateSigned(-sp_offset
);
1004 if (!WriteRegisterUnsigned(context
, eRegisterKindGeneric
,
1005 LLDB_REGNUM_GENERIC_SP
, sp
- sp_offset
))
1011 // Pop Multiple Registers loads multiple registers from the stack, loading from
1012 // consecutive memory locations staring at the address in SP, and updates
1013 // SP to point just above the loaded data.
1014 bool EmulateInstructionARM::EmulatePOP(const uint32_t opcode
,
1015 const ARMEncoding encoding
) {
1017 // ARM pseudo code...
1018 if (ConditionPassed())
1020 EncodingSpecificOperations(); NullCheckIfThumbEE(13);
1023 if registers
<i
> == '1' then
1024 R
[i
] = if UnalignedAllowed then MemU
[address
,4] else MemA
[address
,4]; address
= address
+ 4;
1025 if registers
<15> == '1' then
1026 if UnalignedAllowed then
1027 LoadWritePC(MemU
[address
,4]);
1029 LoadWritePC(MemA
[address
,4]);
1030 if registers
<13> == '0' then SP
= SP
+ 4*BitCount(registers
);
1031 if registers
<13> == '1' then SP
= bits(32) UNKNOWN
;
1035 bool success
= false;
1037 if (ConditionPassed(opcode
)) {
1038 const uint32_t addr_byte_size
= GetAddressByteSize();
1039 const addr_t sp
= ReadCoreReg(SP_REG
, &success
);
1042 uint32_t registers
= 0;
1043 uint32_t Rt
; // the destination register
1046 registers
= Bits32(opcode
, 7, 0);
1047 // The P bit represents PC.
1048 if (Bit32(opcode
, 8))
1049 registers
|= (1u << 15);
1050 // if BitCount(registers) < 1 then UNPREDICTABLE;
1051 if (BitCount(registers
) < 1)
1056 registers
= Bits32(opcode
, 15, 0) & ~0x2000;
1057 // if BitCount(registers) < 2 || (P == '1' && M == '1') then
1059 if (BitCount(registers
) < 2 || (Bit32(opcode
, 15) && Bit32(opcode
, 14)))
1061 // if registers<15> == '1' && InITBlock() && !LastInITBlock() then
1063 if (BitIsSet(registers
, 15) && InITBlock() && !LastInITBlock())
1067 Rt
= Bits32(opcode
, 15, 12);
1068 // if t == 13 || (t == 15 && InITBlock() && !LastInITBlock()) then
1072 if (Rt
== 15 && InITBlock() && !LastInITBlock())
1074 registers
= (1u << Rt
);
1077 registers
= Bits32(opcode
, 15, 0);
1078 // Instead of return false, let's handle the following case as well,
1079 // which amounts to popping one reg from the full descending stacks.
1080 // if BitCount(register_list) < 2 then SEE LDM / LDMIA / LDMFD;
1082 // if registers<13> == '1' && ArchVersion() >= 7 then UNPREDICTABLE;
1083 if (BitIsSet(opcode
, 13) && ArchVersion() >= ARMv7
)
1087 Rt
= Bits32(opcode
, 15, 12);
1088 // if t == 13 then UNPREDICTABLE;
1091 registers
= (1u << Rt
);
1096 addr_t sp_offset
= addr_byte_size
* BitCount(registers
);
1100 EmulateInstruction::Context context
;
1101 context
.type
= EmulateInstruction::eContextPopRegisterOffStack
;
1103 std::optional
<RegisterInfo
> sp_reg
=
1104 GetRegisterInfo(eRegisterKindDWARF
, dwarf_sp
);
1106 for (i
= 0; i
< 15; ++i
) {
1107 if (BitIsSet(registers
, i
)) {
1108 context
.SetAddress(addr
);
1109 data
= MemARead(context
, addr
, 4, 0, &success
);
1112 if (!WriteRegisterUnsigned(context
, eRegisterKindDWARF
, dwarf_r0
+ i
,
1115 addr
+= addr_byte_size
;
1119 if (BitIsSet(registers
, 15)) {
1120 context
.SetRegisterPlusOffset(*sp_reg
, addr
- sp
);
1121 data
= MemARead(context
, addr
, 4, 0, &success
);
1124 // In ARMv5T and above, this is an interworking branch.
1125 if (!LoadWritePC(context
, data
))
1127 // addr += addr_byte_size;
1130 context
.type
= EmulateInstruction::eContextAdjustStackPointer
;
1131 context
.SetImmediateSigned(sp_offset
);
1133 if (!WriteRegisterUnsigned(context
, eRegisterKindGeneric
,
1134 LLDB_REGNUM_GENERIC_SP
, sp
+ sp_offset
))
1140 // Set r7 or ip to point to saved value residing within the stack.
1141 // ADD (SP plus immediate)
1142 bool EmulateInstructionARM::EmulateADDRdSPImm(const uint32_t opcode
,
1143 const ARMEncoding encoding
) {
1145 // ARM pseudo code...
1146 if (ConditionPassed())
1148 EncodingSpecificOperations();
1149 (result
, carry
, overflow
) = AddWithCarry(SP
, imm32
, '0');
1151 ALUWritePC(result
); // setflags is always FALSE here
1155 APSR
.N
= result
<31>;
1156 APSR
.Z
= IsZeroBit(result
);
1162 bool success
= false;
1164 if (ConditionPassed(opcode
)) {
1165 const addr_t sp
= ReadCoreReg(SP_REG
, &success
);
1168 uint32_t Rd
; // the destination register
1173 imm32
= Bits32(opcode
, 7, 0) << 2; // imm32 = ZeroExtend(imm8:'00', 32)
1176 Rd
= Bits32(opcode
, 15, 12);
1177 imm32
= ARMExpandImm(opcode
); // imm32 = ARMExpandImm(imm12)
1182 addr_t sp_offset
= imm32
;
1183 addr_t addr
= sp
+ sp_offset
; // a pointer to the stack area
1185 EmulateInstruction::Context context
;
1186 if (Rd
== GetFramePointerRegisterNumber())
1187 context
.type
= eContextSetFramePointer
;
1189 context
.type
= EmulateInstruction::eContextRegisterPlusOffset
;
1190 std::optional
<RegisterInfo
> sp_reg
=
1191 GetRegisterInfo(eRegisterKindDWARF
, dwarf_sp
);
1192 context
.SetRegisterPlusOffset(*sp_reg
, sp_offset
);
1194 if (!WriteRegisterUnsigned(context
, eRegisterKindDWARF
, dwarf_r0
+ Rd
,
1201 // Set r7 or ip to the current stack pointer.
1203 bool EmulateInstructionARM::EmulateMOVRdSP(const uint32_t opcode
,
1204 const ARMEncoding encoding
) {
1206 // ARM pseudo code...
1207 if (ConditionPassed())
1209 EncodingSpecificOperations();
1212 ALUWritePC(result
); // setflags is always FALSE here
1216 APSR
.N
= result
<31>;
1217 APSR
.Z
= IsZeroBit(result
);
1223 bool success
= false;
1225 if (ConditionPassed(opcode
)) {
1226 const addr_t sp
= ReadCoreReg(SP_REG
, &success
);
1229 uint32_t Rd
; // the destination register
1241 EmulateInstruction::Context context
;
1242 if (Rd
== GetFramePointerRegisterNumber())
1243 context
.type
= EmulateInstruction::eContextSetFramePointer
;
1245 context
.type
= EmulateInstruction::eContextRegisterPlusOffset
;
1246 std::optional
<RegisterInfo
> sp_reg
=
1247 GetRegisterInfo(eRegisterKindDWARF
, dwarf_sp
);
1248 context
.SetRegisterPlusOffset(*sp_reg
, 0);
1250 if (!WriteRegisterUnsigned(context
, eRegisterKindDWARF
, dwarf_r0
+ Rd
, sp
))
1256 // Move from high register (r8-r15) to low register (r0-r7).
1258 bool EmulateInstructionARM::EmulateMOVLowHigh(const uint32_t opcode
,
1259 const ARMEncoding encoding
) {
1260 return EmulateMOVRdRm(opcode
, encoding
);
1263 // Move from register to register.
1265 bool EmulateInstructionARM::EmulateMOVRdRm(const uint32_t opcode
,
1266 const ARMEncoding encoding
) {
1268 // ARM pseudo code...
1269 if (ConditionPassed())
1271 EncodingSpecificOperations();
1274 ALUWritePC(result
); // setflags is always FALSE here
1278 APSR
.N
= result
<31>;
1279 APSR
.Z
= IsZeroBit(result
);
1285 bool success
= false;
1287 if (ConditionPassed(opcode
)) {
1288 uint32_t Rm
; // the source register
1289 uint32_t Rd
; // the destination register
1293 Rd
= Bit32(opcode
, 7) << 3 | Bits32(opcode
, 2, 0);
1294 Rm
= Bits32(opcode
, 6, 3);
1296 if (Rd
== 15 && InITBlock() && !LastInITBlock())
1300 Rd
= Bits32(opcode
, 2, 0);
1301 Rm
= Bits32(opcode
, 5, 3);
1307 Rd
= Bits32(opcode
, 11, 8);
1308 Rm
= Bits32(opcode
, 3, 0);
1309 setflags
= BitIsSet(opcode
, 20);
1310 // if setflags && (BadReg(d) || BadReg(m)) then UNPREDICTABLE;
1311 if (setflags
&& (BadReg(Rd
) || BadReg(Rm
)))
1313 // if !setflags && (d == 15 || m == 15 || (d == 13 && m == 13)) then
1315 if (!setflags
&& (Rd
== 15 || Rm
== 15 || (Rd
== 13 && Rm
== 13)))
1319 Rd
= Bits32(opcode
, 15, 12);
1320 Rm
= Bits32(opcode
, 3, 0);
1321 setflags
= BitIsSet(opcode
, 20);
1323 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related
1325 if (Rd
== 15 && setflags
)
1326 return EmulateSUBSPcLrEtc(opcode
, encoding
);
1331 uint32_t result
= ReadCoreReg(Rm
, &success
);
1335 // The context specifies that Rm is to be moved into Rd.
1336 EmulateInstruction::Context context
;
1338 context
.type
= EmulateInstruction::eContextAdjustStackPointer
;
1339 else if (Rd
== GetFramePointerRegisterNumber() && Rm
== 13)
1340 context
.type
= EmulateInstruction::eContextSetFramePointer
;
1342 context
.type
= EmulateInstruction::eContextRegisterPlusOffset
;
1343 std::optional
<RegisterInfo
> dwarf_reg
=
1344 GetRegisterInfo(eRegisterKindDWARF
, dwarf_r0
+ Rm
);
1345 context
.SetRegisterPlusOffset(*dwarf_reg
, 0);
1347 if (!WriteCoreRegOptionalFlags(context
, result
, Rd
, setflags
))
1353 // Move (immediate) writes an immediate value to the destination register. It
1354 // can optionally update the condition flags based on the value.
1356 bool EmulateInstructionARM::EmulateMOVRdImm(const uint32_t opcode
,
1357 const ARMEncoding encoding
) {
1359 // ARM pseudo code...
1360 if (ConditionPassed())
1362 EncodingSpecificOperations();
1364 if d
== 15 then
// Can only occur for ARM encoding
1365 ALUWritePC(result
); // setflags is always FALSE here
1369 APSR
.N
= result
<31>;
1370 APSR
.Z
= IsZeroBit(result
);
1376 if (ConditionPassed(opcode
)) {
1377 uint32_t Rd
; // the destination register
1378 uint32_t imm32
; // the immediate value to be written to Rd
1380 0; // the carry bit after ThumbExpandImm_C or ARMExpandImm_C.
1381 // for setflags == false, this value is a don't care initialized to
1382 // 0 to silence the static analyzer
1386 Rd
= Bits32(opcode
, 10, 8);
1387 setflags
= !InITBlock();
1388 imm32
= Bits32(opcode
, 7, 0); // imm32 = ZeroExtend(imm8, 32)
1394 Rd
= Bits32(opcode
, 11, 8);
1395 setflags
= BitIsSet(opcode
, 20);
1396 imm32
= ThumbExpandImm_C(opcode
, APSR_C
, carry
);
1403 // d = UInt(Rd); setflags = FALSE; imm32 = ZeroExtend(imm4:i:imm3:imm8,
1405 Rd
= Bits32(opcode
, 11, 8);
1407 uint32_t imm4
= Bits32(opcode
, 19, 16);
1408 uint32_t imm3
= Bits32(opcode
, 14, 12);
1409 uint32_t i
= Bit32(opcode
, 26);
1410 uint32_t imm8
= Bits32(opcode
, 7, 0);
1411 imm32
= (imm4
<< 12) | (i
<< 11) | (imm3
<< 8) | imm8
;
1413 // if BadReg(d) then UNPREDICTABLE;
1419 // d = UInt(Rd); setflags = (S == '1'); (imm32, carry) =
1420 // ARMExpandImm_C(imm12, APSR.C);
1421 Rd
= Bits32(opcode
, 15, 12);
1422 setflags
= BitIsSet(opcode
, 20);
1423 imm32
= ARMExpandImm_C(opcode
, APSR_C
, carry
);
1425 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related
1427 if ((Rd
== 15) && setflags
)
1428 return EmulateSUBSPcLrEtc(opcode
, encoding
);
1433 // d = UInt(Rd); setflags = FALSE; imm32 = ZeroExtend(imm4:imm12, 32);
1434 Rd
= Bits32(opcode
, 15, 12);
1436 uint32_t imm4
= Bits32(opcode
, 19, 16);
1437 uint32_t imm12
= Bits32(opcode
, 11, 0);
1438 imm32
= (imm4
<< 12) | imm12
;
1440 // if d == 15 then UNPREDICTABLE;
1448 uint32_t result
= imm32
;
1450 // The context specifies that an immediate is to be moved into Rd.
1451 EmulateInstruction::Context context
;
1452 context
.type
= EmulateInstruction::eContextImmediate
;
1453 context
.SetNoArgs();
1455 if (!WriteCoreRegOptionalFlags(context
, result
, Rd
, setflags
, carry
))
1461 // MUL multiplies two register values. The least significant 32 bits of the
1462 // result are written to the destination
1463 // register. These 32 bits do not depend on whether the source register values
1464 // are considered to be signed values or unsigned values.
1466 // Optionally, it can update the condition flags based on the result. In the
1467 // Thumb instruction set, this option is limited to only a few forms of the
1469 bool EmulateInstructionARM::EmulateMUL(const uint32_t opcode
,
1470 const ARMEncoding encoding
) {
1472 if ConditionPassed() then
1473 EncodingSpecificOperations();
1474 operand1
= SInt(R
[n
]); // operand1 = UInt(R[n]) produces the same final results
1475 operand2
= SInt(R
[m
]); // operand2 = UInt(R[m]) produces the same final results
1476 result
= operand1
* operand2
;
1477 R
[d
] = result
<31:0>;
1479 APSR
.N
= result
<31>;
1480 APSR
.Z
= IsZeroBit(result
);
1481 if ArchVersion() == 4 then
1482 APSR
.C
= bit UNKNOWN
;
1483 // else APSR.C unchanged
1484 // APSR.V always unchanged
1487 if (ConditionPassed(opcode
)) {
1493 // EncodingSpecificOperations();
1496 // d = UInt(Rdm); n = UInt(Rn); m = UInt(Rdm); setflags = !InITBlock();
1497 d
= Bits32(opcode
, 2, 0);
1498 n
= Bits32(opcode
, 5, 3);
1499 m
= Bits32(opcode
, 2, 0);
1500 setflags
= !InITBlock();
1502 // if ArchVersion() < 6 && d == n then UNPREDICTABLE;
1503 if ((ArchVersion() < ARMv6
) && (d
== n
))
1509 // d = UInt(Rd); n = UInt(Rn); m = UInt(Rm); setflags = FALSE;
1510 d
= Bits32(opcode
, 11, 8);
1511 n
= Bits32(opcode
, 19, 16);
1512 m
= Bits32(opcode
, 3, 0);
1515 // if BadReg(d) || BadReg(n) || BadReg(m) then UNPREDICTABLE;
1516 if (BadReg(d
) || BadReg(n
) || BadReg(m
))
1522 // d = UInt(Rd); n = UInt(Rn); m = UInt(Rm); setflags = (S == '1');
1523 d
= Bits32(opcode
, 19, 16);
1524 n
= Bits32(opcode
, 3, 0);
1525 m
= Bits32(opcode
, 11, 8);
1526 setflags
= BitIsSet(opcode
, 20);
1528 // if d == 15 || n == 15 || m == 15 then UNPREDICTABLE;
1529 if ((d
== 15) || (n
== 15) || (m
== 15))
1532 // if ArchVersion() < 6 && d == n then UNPREDICTABLE;
1533 if ((ArchVersion() < ARMv6
) && (d
== n
))
1542 bool success
= false;
1544 // operand1 = SInt(R[n]); // operand1 = UInt(R[n]) produces the same final
1547 ReadRegisterUnsigned(eRegisterKindDWARF
, dwarf_r0
+ n
, 0, &success
);
1551 // operand2 = SInt(R[m]); // operand2 = UInt(R[m]) produces the same final
1554 ReadRegisterUnsigned(eRegisterKindDWARF
, dwarf_r0
+ m
, 0, &success
);
1558 // result = operand1 * operand2;
1559 uint64_t result
= operand1
* operand2
;
1561 // R[d] = result<31:0>;
1562 std::optional
<RegisterInfo
> op1_reg
=
1563 GetRegisterInfo(eRegisterKindDWARF
, dwarf_r0
+ n
);
1564 std::optional
<RegisterInfo
> op2_reg
=
1565 GetRegisterInfo(eRegisterKindDWARF
, dwarf_r0
+ m
);
1567 EmulateInstruction::Context context
;
1568 context
.type
= eContextArithmetic
;
1569 context
.SetRegisterRegisterOperands(*op1_reg
, *op2_reg
);
1571 if (!WriteRegisterUnsigned(context
, eRegisterKindDWARF
, dwarf_r0
+ d
,
1572 (0x0000ffff & result
)))
1577 // APSR.N = result<31>;
1578 // APSR.Z = IsZeroBit(result);
1579 m_new_inst_cpsr
= m_opcode_cpsr
;
1580 SetBit32(m_new_inst_cpsr
, CPSR_N_POS
, Bit32(result
, 31));
1581 SetBit32(m_new_inst_cpsr
, CPSR_Z_POS
, result
== 0 ? 1 : 0);
1582 if (m_new_inst_cpsr
!= m_opcode_cpsr
) {
1583 if (!WriteRegisterUnsigned(context
, eRegisterKindGeneric
,
1584 LLDB_REGNUM_GENERIC_FLAGS
, m_new_inst_cpsr
))
1588 // if ArchVersion() == 4 then
1589 // APSR.C = bit UNKNOWN;
1595 // Bitwise NOT (immediate) writes the bitwise inverse of an immediate value to
1596 // the destination register. It can optionally update the condition flags based
1598 bool EmulateInstructionARM::EmulateMVNImm(const uint32_t opcode
,
1599 const ARMEncoding encoding
) {
1601 // ARM pseudo code...
1602 if (ConditionPassed())
1604 EncodingSpecificOperations();
1605 result
= NOT(imm32
);
1606 if d
== 15 then
// Can only occur for ARM encoding
1607 ALUWritePC(result
); // setflags is always FALSE here
1611 APSR
.N
= result
<31>;
1612 APSR
.Z
= IsZeroBit(result
);
1618 if (ConditionPassed(opcode
)) {
1619 uint32_t Rd
; // the destination register
1620 uint32_t imm32
; // the output after ThumbExpandImm_C or ARMExpandImm_C
1621 uint32_t carry
; // the carry bit after ThumbExpandImm_C or ARMExpandImm_C
1625 Rd
= Bits32(opcode
, 11, 8);
1626 setflags
= BitIsSet(opcode
, 20);
1627 imm32
= ThumbExpandImm_C(opcode
, APSR_C
, carry
);
1630 Rd
= Bits32(opcode
, 15, 12);
1631 setflags
= BitIsSet(opcode
, 20);
1632 imm32
= ARMExpandImm_C(opcode
, APSR_C
, carry
);
1634 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related
1636 if (Rd
== 15 && setflags
)
1637 return EmulateSUBSPcLrEtc(opcode
, encoding
);
1642 uint32_t result
= ~imm32
;
1644 // The context specifies that an immediate is to be moved into Rd.
1645 EmulateInstruction::Context context
;
1646 context
.type
= EmulateInstruction::eContextImmediate
;
1647 context
.SetNoArgs();
1649 if (!WriteCoreRegOptionalFlags(context
, result
, Rd
, setflags
, carry
))
1655 // Bitwise NOT (register) writes the bitwise inverse of a register value to the
1656 // destination register. It can optionally update the condition flags based on
1658 bool EmulateInstructionARM::EmulateMVNReg(const uint32_t opcode
,
1659 const ARMEncoding encoding
) {
1661 // ARM pseudo code...
1662 if (ConditionPassed())
1664 EncodingSpecificOperations();
1665 (shifted
, carry
) = Shift_C(R
[m
], shift_t
, shift_n
, APSR
.C
);
1666 result
= NOT(shifted
);
1667 if d
== 15 then
// Can only occur for ARM encoding
1668 ALUWritePC(result
); // setflags is always FALSE here
1672 APSR
.N
= result
<31>;
1673 APSR
.Z
= IsZeroBit(result
);
1679 if (ConditionPassed(opcode
)) {
1680 uint32_t Rm
; // the source register
1681 uint32_t Rd
; // the destination register
1682 ARM_ShifterType shift_t
;
1683 uint32_t shift_n
; // the shift applied to the value read from Rm
1685 uint32_t carry
; // the carry bit after the shift operation
1688 Rd
= Bits32(opcode
, 2, 0);
1689 Rm
= Bits32(opcode
, 5, 3);
1690 setflags
= !InITBlock();
1691 shift_t
= SRType_LSL
;
1697 Rd
= Bits32(opcode
, 11, 8);
1698 Rm
= Bits32(opcode
, 3, 0);
1699 setflags
= BitIsSet(opcode
, 20);
1700 shift_n
= DecodeImmShiftThumb(opcode
, shift_t
);
1701 // if (BadReg(d) || BadReg(m)) then UNPREDICTABLE;
1702 if (BadReg(Rd
) || BadReg(Rm
))
1706 Rd
= Bits32(opcode
, 15, 12);
1707 Rm
= Bits32(opcode
, 3, 0);
1708 setflags
= BitIsSet(opcode
, 20);
1709 shift_n
= DecodeImmShiftARM(opcode
, shift_t
);
1714 bool success
= false;
1715 uint32_t value
= ReadCoreReg(Rm
, &success
);
1720 Shift_C(value
, shift_t
, shift_n
, APSR_C
, carry
, &success
);
1723 uint32_t result
= ~shifted
;
1725 // The context specifies that an immediate is to be moved into Rd.
1726 EmulateInstruction::Context context
;
1727 context
.type
= EmulateInstruction::eContextImmediate
;
1728 context
.SetNoArgs();
1730 if (!WriteCoreRegOptionalFlags(context
, result
, Rd
, setflags
, carry
))
1736 // PC relative immediate load into register, possibly followed by ADD (SP plus
1739 bool EmulateInstructionARM::EmulateLDRRtPCRelative(const uint32_t opcode
,
1740 const ARMEncoding encoding
) {
1742 // ARM pseudo code...
1743 if (ConditionPassed())
1745 EncodingSpecificOperations(); NullCheckIfThumbEE(15);
1747 address
= if add
then (base
+ imm32
) else (base
- imm32
);
1748 data
= MemU
[address
,4];
1750 if address
<1:0> == '00' then
LoadWritePC(data
); else UNPREDICTABLE
;
1751 elsif
UnalignedSupport() || address
<1:0> = '00' then
1753 else // Can only apply before ARMv7
1754 if CurrentInstrSet() == InstrSet_ARM then
1755 R
[t
] = ROR(data
, 8*UInt(address
<1:0>));
1757 R
[t
] = bits(32) UNKNOWN
;
1761 if (ConditionPassed(opcode
)) {
1762 bool success
= false;
1763 const uint32_t pc
= ReadCoreReg(PC_REG
, &success
);
1767 // PC relative immediate load context
1768 EmulateInstruction::Context context
;
1769 context
.type
= EmulateInstruction::eContextRegisterPlusOffset
;
1770 std::optional
<RegisterInfo
> pc_reg
=
1771 GetRegisterInfo(eRegisterKindDWARF
, dwarf_pc
);
1772 context
.SetRegisterPlusOffset(*pc_reg
, 0);
1774 uint32_t Rt
; // the destination register
1775 uint32_t imm32
; // immediate offset from the PC
1776 bool add
; // +imm32 or -imm32?
1777 addr_t base
; // the base address
1778 addr_t address
; // the PC relative address
1779 uint32_t data
; // the literal data value from the PC relative load
1782 Rt
= Bits32(opcode
, 10, 8);
1783 imm32
= Bits32(opcode
, 7, 0) << 2; // imm32 = ZeroExtend(imm8:'00', 32);
1787 Rt
= Bits32(opcode
, 15, 12);
1788 imm32
= Bits32(opcode
, 11, 0) << 2; // imm32 = ZeroExtend(imm12, 32);
1789 add
= BitIsSet(opcode
, 23);
1790 if (Rt
== 15 && InITBlock() && !LastInITBlock())
1797 base
= Align(pc
, 4);
1799 address
= base
+ imm32
;
1801 address
= base
- imm32
;
1803 context
.SetRegisterPlusOffset(*pc_reg
, address
- base
);
1804 data
= MemURead(context
, address
, 4, 0, &success
);
1809 if (Bits32(address
, 1, 0) == 0) {
1810 // In ARMv5T and above, this is an interworking branch.
1811 if (!LoadWritePC(context
, data
))
1815 } else if (UnalignedSupport() || Bits32(address
, 1, 0) == 0) {
1816 if (!WriteRegisterUnsigned(context
, eRegisterKindDWARF
, dwarf_r0
+ Rt
,
1819 } else // We don't handle ARM for now.
1825 // An add operation to adjust the SP.
1826 // ADD (SP plus immediate)
1827 bool EmulateInstructionARM::EmulateADDSPImm(const uint32_t opcode
,
1828 const ARMEncoding encoding
) {
1830 // ARM pseudo code...
1831 if (ConditionPassed())
1833 EncodingSpecificOperations();
1834 (result
, carry
, overflow
) = AddWithCarry(SP
, imm32
, '0');
1835 if d
== 15 then
// Can only occur for ARM encoding
1836 ALUWritePC(result
); // setflags is always FALSE here
1840 APSR
.N
= result
<31>;
1841 APSR
.Z
= IsZeroBit(result
);
1847 bool success
= false;
1849 if (ConditionPassed(opcode
)) {
1850 const addr_t sp
= ReadCoreReg(SP_REG
, &success
);
1853 uint32_t imm32
; // the immediate operand
1858 // d = UInt(Rd); setflags = FALSE; imm32 = ZeroExtend(imm8:'00', 32);
1859 d
= Bits32(opcode
, 10, 8);
1860 imm32
= (Bits32(opcode
, 7, 0) << 2);
1865 // d = 13; setflags = FALSE; imm32 = ZeroExtend(imm7:'00', 32);
1867 imm32
= ThumbImm7Scaled(opcode
); // imm32 = ZeroExtend(imm7:'00', 32)
1872 // d = UInt(Rd); setflags = (S == "1"); imm32 =
1873 // ThumbExpandImm(i:imm3:imm8);
1874 d
= Bits32(opcode
, 11, 8);
1875 imm32
= ThumbExpandImm(opcode
);
1876 setflags
= Bit32(opcode
, 20);
1878 // if Rd == "1111" && S == "1" then SEE CMN (immediate);
1879 if (d
== 15 && setflags
== 1)
1880 return false; // CMN (immediate) not yet supported
1882 // if d == 15 && S == "0" then UNPREDICTABLE;
1883 if (d
== 15 && setflags
== 0)
1888 // if Rn == '1111' then SEE ADR;
1889 // d = UInt(Rd); setflags = FALSE; imm32 = ZeroExtend(i:imm3:imm8, 32);
1890 d
= Bits32(opcode
, 11, 8);
1892 uint32_t i
= Bit32(opcode
, 26);
1893 uint32_t imm3
= Bits32(opcode
, 14, 12);
1894 uint32_t imm8
= Bits32(opcode
, 7, 0);
1895 imm32
= (i
<< 11) | (imm3
<< 8) | imm8
;
1897 // if d == 15 then UNPREDICTABLE;
1905 // (result, carry, overflow) = AddWithCarry(R[n], imm32, '0');
1906 AddWithCarryResult res
= AddWithCarry(sp
, imm32
, 0);
1908 EmulateInstruction::Context context
;
1910 context
.type
= EmulateInstruction::eContextAdjustStackPointer
;
1912 context
.type
= EmulateInstruction::eContextRegisterPlusOffset
;
1914 std::optional
<RegisterInfo
> sp_reg
=
1915 GetRegisterInfo(eRegisterKindDWARF
, dwarf_sp
);
1916 context
.SetRegisterPlusOffset(*sp_reg
, res
.result
- sp
);
1919 if (!ALUWritePC(context
, res
.result
))
1924 // APSR.N = result<31>;
1925 // APSR.Z = IsZeroBit(result);
1927 // APSR.V = overflow;
1928 if (!WriteCoreRegOptionalFlags(context
, res
.result
, d
, setflags
,
1929 res
.carry_out
, res
.overflow
))
1936 // An add operation to adjust the SP.
1937 // ADD (SP plus register)
1938 bool EmulateInstructionARM::EmulateADDSPRm(const uint32_t opcode
,
1939 const ARMEncoding encoding
) {
1941 // ARM pseudo code...
1942 if (ConditionPassed())
1944 EncodingSpecificOperations();
1945 shifted
= Shift(R
[m
], shift_t
, shift_n
, APSR
.C
);
1946 (result
, carry
, overflow
) = AddWithCarry(SP
, shifted
, '0');
1948 ALUWritePC(result
); // setflags is always FALSE here
1952 APSR
.N
= result
<31>;
1953 APSR
.Z
= IsZeroBit(result
);
1959 bool success
= false;
1961 if (ConditionPassed(opcode
)) {
1962 const addr_t sp
= ReadCoreReg(SP_REG
, &success
);
1965 uint32_t Rm
; // the second operand
1968 Rm
= Bits32(opcode
, 6, 3);
1973 int32_t reg_value
= ReadCoreReg(Rm
, &success
);
1977 addr_t addr
= (int32_t)sp
+ reg_value
; // the adjusted stack pointer value
1979 EmulateInstruction::Context context
;
1980 context
.type
= eContextArithmetic
;
1981 std::optional
<RegisterInfo
> sp_reg
=
1982 GetRegisterInfo(eRegisterKindDWARF
, dwarf_sp
);
1983 std::optional
<RegisterInfo
> other_reg
=
1984 GetRegisterInfo(eRegisterKindDWARF
, dwarf_r0
+ Rm
);
1985 context
.SetRegisterRegisterOperands(*sp_reg
, *other_reg
);
1987 if (!WriteRegisterUnsigned(context
, eRegisterKindGeneric
,
1988 LLDB_REGNUM_GENERIC_SP
, addr
))
1994 // Branch with Link and Exchange Instruction Sets (immediate) calls a
1995 // subroutine at a PC-relative address, and changes instruction set from ARM to
1996 // Thumb, or from Thumb to ARM.
1998 bool EmulateInstructionARM::EmulateBLXImmediate(const uint32_t opcode
,
1999 const ARMEncoding encoding
) {
2001 // ARM pseudo code...
2002 if (ConditionPassed())
2004 EncodingSpecificOperations();
2005 if CurrentInstrSet() == InstrSet_ARM then
2008 LR
= PC
<31:1> : '1';
2009 if targetInstrSet
== InstrSet_ARM then
2010 targetAddress
= Align(PC
,4) + imm32
;
2012 targetAddress
= PC
+ imm32
;
2013 SelectInstrSet(targetInstrSet
);
2014 BranchWritePC(targetAddress
);
2018 bool success
= true;
2020 if (ConditionPassed(opcode
)) {
2021 EmulateInstruction::Context context
;
2022 context
.type
= EmulateInstruction::eContextRelativeBranchImmediate
;
2023 const uint32_t pc
= ReadCoreReg(PC_REG
, &success
);
2026 addr_t lr
; // next instruction address
2027 addr_t target
; // target address
2028 int32_t imm32
; // PC-relative offset
2031 lr
= pc
| 1u; // return address
2032 uint32_t S
= Bit32(opcode
, 26);
2033 uint32_t imm10
= Bits32(opcode
, 25, 16);
2034 uint32_t J1
= Bit32(opcode
, 13);
2035 uint32_t J2
= Bit32(opcode
, 11);
2036 uint32_t imm11
= Bits32(opcode
, 10, 0);
2037 uint32_t I1
= !(J1
^ S
);
2038 uint32_t I2
= !(J2
^ S
);
2040 (S
<< 24) | (I1
<< 23) | (I2
<< 22) | (imm10
<< 12) | (imm11
<< 1);
2041 imm32
= llvm::SignExtend32
<25>(imm25
);
2042 target
= pc
+ imm32
;
2043 SelectInstrSet(eModeThumb
);
2044 context
.SetISAAndImmediateSigned(eModeThumb
, 4 + imm32
);
2045 if (InITBlock() && !LastInITBlock())
2050 lr
= pc
| 1u; // return address
2051 uint32_t S
= Bit32(opcode
, 26);
2052 uint32_t imm10H
= Bits32(opcode
, 25, 16);
2053 uint32_t J1
= Bit32(opcode
, 13);
2054 uint32_t J2
= Bit32(opcode
, 11);
2055 uint32_t imm10L
= Bits32(opcode
, 10, 1);
2056 uint32_t I1
= !(J1
^ S
);
2057 uint32_t I2
= !(J2
^ S
);
2059 (S
<< 24) | (I1
<< 23) | (I2
<< 22) | (imm10H
<< 12) | (imm10L
<< 2);
2060 imm32
= llvm::SignExtend32
<25>(imm25
);
2061 target
= Align(pc
, 4) + imm32
;
2062 SelectInstrSet(eModeARM
);
2063 context
.SetISAAndImmediateSigned(eModeARM
, 4 + imm32
);
2064 if (InITBlock() && !LastInITBlock())
2069 lr
= pc
- 4; // return address
2070 imm32
= llvm::SignExtend32
<26>(Bits32(opcode
, 23, 0) << 2);
2071 target
= Align(pc
, 4) + imm32
;
2072 SelectInstrSet(eModeARM
);
2073 context
.SetISAAndImmediateSigned(eModeARM
, 8 + imm32
);
2076 lr
= pc
- 4; // return address
2077 imm32
= llvm::SignExtend32
<26>(Bits32(opcode
, 23, 0) << 2 |
2078 Bits32(opcode
, 24, 24) << 1);
2079 target
= pc
+ imm32
;
2080 SelectInstrSet(eModeThumb
);
2081 context
.SetISAAndImmediateSigned(eModeThumb
, 8 + imm32
);
2086 if (!WriteRegisterUnsigned(context
, eRegisterKindGeneric
,
2087 LLDB_REGNUM_GENERIC_RA
, lr
))
2089 if (!BranchWritePC(context
, target
))
2091 if (m_opcode_cpsr
!= m_new_inst_cpsr
)
2092 if (!WriteRegisterUnsigned(context
, eRegisterKindGeneric
,
2093 LLDB_REGNUM_GENERIC_FLAGS
, m_new_inst_cpsr
))
2099 // Branch with Link and Exchange (register) calls a subroutine at an address
2100 // and instruction set specified by a register.
2102 bool EmulateInstructionARM::EmulateBLXRm(const uint32_t opcode
,
2103 const ARMEncoding encoding
) {
2105 // ARM pseudo code...
2106 if (ConditionPassed())
2108 EncodingSpecificOperations();
2110 if CurrentInstrSet() == InstrSet_ARM then
2111 next_instr_addr
= PC
- 4;
2112 LR
= next_instr_addr
;
2114 next_instr_addr
= PC
- 2;
2115 LR
= next_instr_addr
<31:1> : '1';
2120 bool success
= false;
2122 if (ConditionPassed(opcode
)) {
2123 EmulateInstruction::Context context
;
2124 context
.type
= EmulateInstruction::eContextAbsoluteBranchRegister
;
2125 const uint32_t pc
= ReadCoreReg(PC_REG
, &success
);
2126 addr_t lr
; // next instruction address
2129 uint32_t Rm
; // the register with the target address
2132 lr
= (pc
- 2) | 1u; // return address
2133 Rm
= Bits32(opcode
, 6, 3);
2134 // if m == 15 then UNPREDICTABLE;
2137 if (InITBlock() && !LastInITBlock())
2141 lr
= pc
- 4; // return address
2142 Rm
= Bits32(opcode
, 3, 0);
2143 // if m == 15 then UNPREDICTABLE;
2150 addr_t target
= ReadCoreReg(Rm
, &success
);
2153 std::optional
<RegisterInfo
> dwarf_reg
=
2154 GetRegisterInfo(eRegisterKindDWARF
, dwarf_r0
+ Rm
);
2155 context
.SetRegister(*dwarf_reg
);
2156 if (!WriteRegisterUnsigned(context
, eRegisterKindGeneric
,
2157 LLDB_REGNUM_GENERIC_RA
, lr
))
2159 if (!BXWritePC(context
, target
))
2165 // Branch and Exchange causes a branch to an address and instruction set
2166 // specified by a register.
2167 bool EmulateInstructionARM::EmulateBXRm(const uint32_t opcode
,
2168 const ARMEncoding encoding
) {
2170 // ARM pseudo code...
2171 if (ConditionPassed())
2173 EncodingSpecificOperations();
2178 if (ConditionPassed(opcode
)) {
2179 EmulateInstruction::Context context
;
2180 context
.type
= EmulateInstruction::eContextAbsoluteBranchRegister
;
2181 uint32_t Rm
; // the register with the target address
2184 Rm
= Bits32(opcode
, 6, 3);
2185 if (InITBlock() && !LastInITBlock())
2189 Rm
= Bits32(opcode
, 3, 0);
2194 bool success
= false;
2195 addr_t target
= ReadCoreReg(Rm
, &success
);
2199 std::optional
<RegisterInfo
> dwarf_reg
=
2200 GetRegisterInfo(eRegisterKindDWARF
, dwarf_r0
+ Rm
);
2201 context
.SetRegister(*dwarf_reg
);
2202 if (!BXWritePC(context
, target
))
2208 // Branch and Exchange Jazelle attempts to change to Jazelle state. If the
2209 // attempt fails, it branches to an address and instruction set specified by a
2210 // register as though it were a BX instruction.
2212 // TODO: Emulate Jazelle architecture?
2213 // We currently assume that switching to Jazelle state fails, thus
2214 // treating BXJ as a BX operation.
2215 bool EmulateInstructionARM::EmulateBXJRm(const uint32_t opcode
,
2216 const ARMEncoding encoding
) {
2218 // ARM pseudo code...
2219 if (ConditionPassed())
2221 EncodingSpecificOperations();
2222 if JMCR
.JE
== '0' || CurrentInstrSet() == InstrSet_ThumbEE then
2225 if JazelleAcceptsExecution() then
2226 SwitchToJazelleExecution();
2228 SUBARCHITECTURE_DEFINED handler call
;
2232 if (ConditionPassed(opcode
)) {
2233 EmulateInstruction::Context context
;
2234 context
.type
= EmulateInstruction::eContextAbsoluteBranchRegister
;
2235 uint32_t Rm
; // the register with the target address
2238 Rm
= Bits32(opcode
, 19, 16);
2241 if (InITBlock() && !LastInITBlock())
2245 Rm
= Bits32(opcode
, 3, 0);
2252 bool success
= false;
2253 addr_t target
= ReadCoreReg(Rm
, &success
);
2257 std::optional
<RegisterInfo
> dwarf_reg
=
2258 GetRegisterInfo(eRegisterKindDWARF
, dwarf_r0
+ Rm
);
2259 context
.SetRegister(*dwarf_reg
);
2260 if (!BXWritePC(context
, target
))
2266 // Set r7 to point to some ip offset.
2268 bool EmulateInstructionARM::EmulateSUBR7IPImm(const uint32_t opcode
,
2269 const ARMEncoding encoding
) {
2271 // ARM pseudo code...
2272 if (ConditionPassed())
2274 EncodingSpecificOperations();
2275 (result
, carry
, overflow
) = AddWithCarry(SP
, NOT(imm32
), '1');
2276 if d
== 15 then
// Can only occur for ARM encoding
2277 ALUWritePC(result
); // setflags is always FALSE here
2281 APSR
.N
= result
<31>;
2282 APSR
.Z
= IsZeroBit(result
);
2288 if (ConditionPassed(opcode
)) {
2289 bool success
= false;
2290 const addr_t ip
= ReadCoreReg(12, &success
);
2296 imm32
= ARMExpandImm(opcode
); // imm32 = ARMExpandImm(imm12)
2301 addr_t ip_offset
= imm32
;
2302 addr_t addr
= ip
- ip_offset
; // the adjusted ip value
2304 EmulateInstruction::Context context
;
2305 context
.type
= EmulateInstruction::eContextRegisterPlusOffset
;
2306 std::optional
<RegisterInfo
> dwarf_reg
=
2307 GetRegisterInfo(eRegisterKindDWARF
, dwarf_r12
);
2308 context
.SetRegisterPlusOffset(*dwarf_reg
, -ip_offset
);
2310 if (!WriteRegisterUnsigned(context
, eRegisterKindDWARF
, dwarf_r7
, addr
))
2316 // Set ip to point to some stack offset.
2317 // SUB (SP minus immediate)
2318 bool EmulateInstructionARM::EmulateSUBIPSPImm(const uint32_t opcode
,
2319 const ARMEncoding encoding
) {
2321 // ARM pseudo code...
2322 if (ConditionPassed())
2324 EncodingSpecificOperations();
2325 (result
, carry
, overflow
) = AddWithCarry(SP
, NOT(imm32
), '1');
2326 if d
== 15 then
// Can only occur for ARM encoding
2327 ALUWritePC(result
); // setflags is always FALSE here
2331 APSR
.N
= result
<31>;
2332 APSR
.Z
= IsZeroBit(result
);
2338 if (ConditionPassed(opcode
)) {
2339 bool success
= false;
2340 const addr_t sp
= ReadCoreReg(SP_REG
, &success
);
2346 imm32
= ARMExpandImm(opcode
); // imm32 = ARMExpandImm(imm12)
2351 addr_t sp_offset
= imm32
;
2352 addr_t addr
= sp
- sp_offset
; // the adjusted stack pointer value
2354 EmulateInstruction::Context context
;
2355 context
.type
= EmulateInstruction::eContextRegisterPlusOffset
;
2356 std::optional
<RegisterInfo
> dwarf_reg
=
2357 GetRegisterInfo(eRegisterKindGeneric
, LLDB_REGNUM_GENERIC_SP
);
2358 context
.SetRegisterPlusOffset(*dwarf_reg
, -sp_offset
);
2360 if (!WriteRegisterUnsigned(context
, eRegisterKindDWARF
, dwarf_r12
, addr
))
2366 // This instruction subtracts an immediate value from the SP value, and writes
2367 // the result to the destination register.
2369 // If Rd == 13 => A sub operation to adjust the SP -- allocate space for local
2371 bool EmulateInstructionARM::EmulateSUBSPImm(const uint32_t opcode
,
2372 const ARMEncoding encoding
) {
2374 // ARM pseudo code...
2375 if (ConditionPassed())
2377 EncodingSpecificOperations();
2378 (result
, carry
, overflow
) = AddWithCarry(SP
, NOT(imm32
), '1');
2379 if d
== 15 then
// Can only occur for ARM encoding
2380 ALUWritePC(result
); // setflags is always FALSE here
2384 APSR
.N
= result
<31>;
2385 APSR
.Z
= IsZeroBit(result
);
2391 bool success
= false;
2392 if (ConditionPassed(opcode
)) {
2393 const addr_t sp
= ReadCoreReg(SP_REG
, &success
);
2404 imm32
= ThumbImm7Scaled(opcode
); // imm32 = ZeroExtend(imm7:'00', 32)
2407 Rd
= Bits32(opcode
, 11, 8);
2408 setflags
= BitIsSet(opcode
, 20);
2409 imm32
= ThumbExpandImm(opcode
); // imm32 = ThumbExpandImm(i:imm3:imm8)
2410 if (Rd
== 15 && setflags
)
2411 return EmulateCMPImm(opcode
, eEncodingT2
);
2412 if (Rd
== 15 && !setflags
)
2416 Rd
= Bits32(opcode
, 11, 8);
2418 imm32
= ThumbImm12(opcode
); // imm32 = ZeroExtend(i:imm3:imm8, 32)
2423 Rd
= Bits32(opcode
, 15, 12);
2424 setflags
= BitIsSet(opcode
, 20);
2425 imm32
= ARMExpandImm(opcode
); // imm32 = ARMExpandImm(imm12)
2427 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related
2429 if (Rd
== 15 && setflags
)
2430 return EmulateSUBSPcLrEtc(opcode
, encoding
);
2435 AddWithCarryResult res
= AddWithCarry(sp
, ~imm32
, 1);
2437 EmulateInstruction::Context context
;
2439 uint64_t imm64
= imm32
; // Need to expand it to 64 bits before attempting
2440 // to negate it, or the wrong
2441 // value gets passed down to context.SetImmediateSigned.
2442 context
.type
= EmulateInstruction::eContextAdjustStackPointer
;
2443 context
.SetImmediateSigned(-imm64
); // the stack pointer offset
2445 context
.type
= EmulateInstruction::eContextImmediate
;
2446 context
.SetNoArgs();
2449 if (!WriteCoreRegOptionalFlags(context
, res
.result
, Rd
, setflags
,
2450 res
.carry_out
, res
.overflow
))
2456 // A store operation to the stack that also updates the SP.
2457 bool EmulateInstructionARM::EmulateSTRRtSP(const uint32_t opcode
,
2458 const ARMEncoding encoding
) {
2460 // ARM pseudo code...
2461 if (ConditionPassed())
2463 EncodingSpecificOperations();
2464 offset_addr
= if add
then (R
[n
] + imm32
) else (R
[n
] - imm32
);
2465 address
= if index then offset_addr
else R
[n
];
2466 MemU
[address
,4] = if t
== 15 then
PCStoreValue() else R
[t
];
2467 if wback then R
[n
] = offset_addr
;
2471 bool success
= false;
2472 if (ConditionPassed(opcode
)) {
2473 const uint32_t addr_byte_size
= GetAddressByteSize();
2474 const addr_t sp
= ReadCoreReg(SP_REG
, &success
);
2477 uint32_t Rt
; // the source register
2480 Rn
; // This function assumes Rn is the SP, but we should verify that.
2487 Rt
= Bits32(opcode
, 15, 12);
2488 imm12
= Bits32(opcode
, 11, 0);
2489 Rn
= Bits32(opcode
, 19, 16);
2491 if (Rn
!= 13) // 13 is the SP reg on ARM. Verify that Rn == SP.
2494 index
= BitIsSet(opcode
, 24);
2495 add
= BitIsSet(opcode
, 23);
2496 wback
= (BitIsClear(opcode
, 24) || BitIsSet(opcode
, 21));
2498 if (wback
&& ((Rn
== 15) || (Rn
== Rt
)))
2506 offset_addr
= sp
+ imm12
;
2508 offset_addr
= sp
- imm12
;
2516 EmulateInstruction::Context context
;
2517 context
.type
= EmulateInstruction::eContextPushRegisterOnStack
;
2518 std::optional
<RegisterInfo
> sp_reg
=
2519 GetRegisterInfo(eRegisterKindDWARF
, dwarf_sp
);
2520 std::optional
<RegisterInfo
> dwarf_reg
=
2521 GetRegisterInfo(eRegisterKindDWARF
, dwarf_r0
+ Rt
);
2523 context
.SetRegisterToRegisterPlusOffset(*dwarf_reg
, *sp_reg
, addr
- sp
);
2525 uint32_t reg_value
= ReadCoreReg(Rt
, &success
);
2528 if (!MemUWrite(context
, addr
, reg_value
, addr_byte_size
))
2531 const uint32_t pc
= ReadCoreReg(PC_REG
, &success
);
2534 if (!MemUWrite(context
, addr
, pc
, addr_byte_size
))
2539 context
.type
= EmulateInstruction::eContextAdjustStackPointer
;
2540 context
.SetImmediateSigned(addr
- sp
);
2541 if (!WriteRegisterUnsigned(context
, eRegisterKindGeneric
,
2542 LLDB_REGNUM_GENERIC_SP
, offset_addr
))
2549 // Vector Push stores multiple extension registers to the stack. It also
2550 // updates SP to point to the start of the stored data.
2551 bool EmulateInstructionARM::EmulateVPUSH(const uint32_t opcode
,
2552 const ARMEncoding encoding
) {
2554 // ARM pseudo code...
2555 if (ConditionPassed())
2557 EncodingSpecificOperations(); CheckVFPEnabled(TRUE
); NullCheckIfThumbEE(13);
2558 address
= SP
- imm32
;
2562 MemA
[address
,4] = S
[d
+r
]; address
= address
+4;
2565 // Store as two word-aligned words in the correct order for
2566 // current endianness.
2567 MemA
[address
,4] = if BigEndian() then D
[d
+r
]<63:32> else D
[d
+r
]<31:0>;
2568 MemA
[address
+4,4] = if BigEndian() then D
[d
+r
]<31:0> else D
[d
+r
]<63:32>;
2569 address
= address
+8;
2573 bool success
= false;
2574 if (ConditionPassed(opcode
)) {
2575 const uint32_t addr_byte_size
= GetAddressByteSize();
2576 const addr_t sp
= ReadCoreReg(SP_REG
, &success
);
2580 uint32_t d
; // UInt(D:Vd) or UInt(Vd:D) starting register
2581 uint32_t imm32
; // stack offset
2582 uint32_t regs
; // number of registers
2586 single_regs
= false;
2587 d
= Bit32(opcode
, 22) << 4 | Bits32(opcode
, 15, 12);
2588 imm32
= Bits32(opcode
, 7, 0) * addr_byte_size
;
2589 // If UInt(imm8) is odd, see "FSTMX".
2590 regs
= Bits32(opcode
, 7, 0) / 2;
2591 // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE;
2592 if (regs
== 0 || regs
> 16 || (d
+ regs
) > 32)
2598 d
= Bits32(opcode
, 15, 12) << 1 | Bit32(opcode
, 22);
2599 imm32
= Bits32(opcode
, 7, 0) * addr_byte_size
;
2600 regs
= Bits32(opcode
, 7, 0);
2601 // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE;
2602 if (regs
== 0 || regs
> 16 || (d
+ regs
) > 32)
2608 uint32_t start_reg
= single_regs
? dwarf_s0
: dwarf_d0
;
2609 uint32_t reg_byte_size
= single_regs
? addr_byte_size
: addr_byte_size
* 2;
2610 addr_t sp_offset
= imm32
;
2611 addr_t addr
= sp
- sp_offset
;
2614 EmulateInstruction::Context context
;
2615 context
.type
= EmulateInstruction::eContextPushRegisterOnStack
;
2617 std::optional
<RegisterInfo
> sp_reg
=
2618 GetRegisterInfo(eRegisterKindDWARF
, dwarf_sp
);
2619 for (i
= 0; i
< regs
; ++i
) {
2620 std::optional
<RegisterInfo
> dwarf_reg
=
2621 GetRegisterInfo(eRegisterKindDWARF
, start_reg
+ d
+ i
);
2622 context
.SetRegisterToRegisterPlusOffset(*dwarf_reg
, *sp_reg
, addr
- sp
);
2623 // uint64_t to accommodate 64-bit registers.
2624 uint64_t reg_value
= ReadRegisterUnsigned(*dwarf_reg
, 0, &success
);
2627 if (!MemAWrite(context
, addr
, reg_value
, reg_byte_size
))
2629 addr
+= reg_byte_size
;
2632 context
.type
= EmulateInstruction::eContextAdjustStackPointer
;
2633 context
.SetImmediateSigned(-sp_offset
);
2635 if (!WriteRegisterUnsigned(context
, eRegisterKindGeneric
,
2636 LLDB_REGNUM_GENERIC_SP
, sp
- sp_offset
))
2642 // Vector Pop loads multiple extension registers from the stack. It also
2643 // updates SP to point just above the loaded data.
2644 bool EmulateInstructionARM::EmulateVPOP(const uint32_t opcode
,
2645 const ARMEncoding encoding
) {
2647 // ARM pseudo code...
2648 if (ConditionPassed())
2650 EncodingSpecificOperations(); CheckVFPEnabled(TRUE
); NullCheckIfThumbEE(13);
2655 S
[d
+r
] = MemA
[address
,4]; address
= address
+4;
2658 word1
= MemA
[address
,4]; word2
= MemA
[address
+4,4]; address
= address
+8;
2659 // Combine the word-aligned words in the correct order for
2660 // current endianness.
2661 D
[d
+r
] = if BigEndian() then word1
:word2
else word2
:word1
;
2665 bool success
= false;
2666 if (ConditionPassed(opcode
)) {
2667 const uint32_t addr_byte_size
= GetAddressByteSize();
2668 const addr_t sp
= ReadCoreReg(SP_REG
, &success
);
2672 uint32_t d
; // UInt(D:Vd) or UInt(Vd:D) starting register
2673 uint32_t imm32
; // stack offset
2674 uint32_t regs
; // number of registers
2678 single_regs
= false;
2679 d
= Bit32(opcode
, 22) << 4 | Bits32(opcode
, 15, 12);
2680 imm32
= Bits32(opcode
, 7, 0) * addr_byte_size
;
2681 // If UInt(imm8) is odd, see "FLDMX".
2682 regs
= Bits32(opcode
, 7, 0) / 2;
2683 // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE;
2684 if (regs
== 0 || regs
> 16 || (d
+ regs
) > 32)
2690 d
= Bits32(opcode
, 15, 12) << 1 | Bit32(opcode
, 22);
2691 imm32
= Bits32(opcode
, 7, 0) * addr_byte_size
;
2692 regs
= Bits32(opcode
, 7, 0);
2693 // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE;
2694 if (regs
== 0 || regs
> 16 || (d
+ regs
) > 32)
2700 uint32_t start_reg
= single_regs
? dwarf_s0
: dwarf_d0
;
2701 uint32_t reg_byte_size
= single_regs
? addr_byte_size
: addr_byte_size
* 2;
2702 addr_t sp_offset
= imm32
;
2705 uint64_t data
; // uint64_t to accommodate 64-bit registers.
2707 EmulateInstruction::Context context
;
2708 context
.type
= EmulateInstruction::eContextPopRegisterOffStack
;
2710 for (i
= 0; i
< regs
; ++i
) {
2711 std::optional
<RegisterInfo
> dwarf_reg
=
2712 GetRegisterInfo(eRegisterKindDWARF
, start_reg
+ d
+ i
);
2713 context
.SetAddress(addr
);
2714 data
= MemARead(context
, addr
, reg_byte_size
, 0, &success
);
2717 if (!WriteRegisterUnsigned(context
, *dwarf_reg
, data
))
2719 addr
+= reg_byte_size
;
2722 context
.type
= EmulateInstruction::eContextAdjustStackPointer
;
2723 context
.SetImmediateSigned(sp_offset
);
2725 if (!WriteRegisterUnsigned(context
, eRegisterKindGeneric
,
2726 LLDB_REGNUM_GENERIC_SP
, sp
+ sp_offset
))
2732 // SVC (previously SWI)
2733 bool EmulateInstructionARM::EmulateSVC(const uint32_t opcode
,
2734 const ARMEncoding encoding
) {
2736 // ARM pseudo code...
2737 if (ConditionPassed())
2739 EncodingSpecificOperations();
2744 bool success
= false;
2746 if (ConditionPassed(opcode
)) {
2747 const uint32_t pc
= ReadCoreReg(PC_REG
, &success
);
2748 addr_t lr
; // next instruction address
2751 uint32_t imm32
; // the immediate constant
2752 uint32_t mode
; // ARM or Thumb mode
2755 lr
= (pc
+ 2) | 1u; // return address
2756 imm32
= Bits32(opcode
, 7, 0);
2760 lr
= pc
+ 4; // return address
2761 imm32
= Bits32(opcode
, 23, 0);
2768 EmulateInstruction::Context context
;
2769 context
.type
= EmulateInstruction::eContextSupervisorCall
;
2770 context
.SetISAAndImmediate(mode
, imm32
);
2771 if (!WriteRegisterUnsigned(context
, eRegisterKindGeneric
,
2772 LLDB_REGNUM_GENERIC_RA
, lr
))
2778 // If Then makes up to four following instructions (the IT block) conditional.
2779 bool EmulateInstructionARM::EmulateIT(const uint32_t opcode
,
2780 const ARMEncoding encoding
) {
2782 // ARM pseudo code...
2783 EncodingSpecificOperations();
2784 ITSTATE
.IT
<7:0> = firstcond
:mask
;
2787 m_it_session
.InitIT(Bits32(opcode
, 7, 0));
2791 bool EmulateInstructionARM::EmulateNop(const uint32_t opcode
,
2792 const ARMEncoding encoding
) {
2793 // NOP, nothing to do...
2797 // Branch causes a branch to a target address.
2798 bool EmulateInstructionARM::EmulateB(const uint32_t opcode
,
2799 const ARMEncoding encoding
) {
2801 // ARM pseudo code...
2802 if (ConditionPassed())
2804 EncodingSpecificOperations();
2805 BranchWritePC(PC
+ imm32
);
2809 bool success
= false;
2811 if (ConditionPassed(opcode
)) {
2812 EmulateInstruction::Context context
;
2813 context
.type
= EmulateInstruction::eContextRelativeBranchImmediate
;
2814 const uint32_t pc
= ReadCoreReg(PC_REG
, &success
);
2817 addr_t target
; // target address
2818 int32_t imm32
; // PC-relative offset
2821 // The 'cond' field is handled in EmulateInstructionARM::CurrentCond().
2822 imm32
= llvm::SignExtend32
<9>(Bits32(opcode
, 7, 0) << 1);
2823 target
= pc
+ imm32
;
2824 context
.SetISAAndImmediateSigned(eModeThumb
, 4 + imm32
);
2827 imm32
= llvm::SignExtend32
<12>(Bits32(opcode
, 10, 0) << 1);
2828 target
= pc
+ imm32
;
2829 context
.SetISAAndImmediateSigned(eModeThumb
, 4 + imm32
);
2832 // The 'cond' field is handled in EmulateInstructionARM::CurrentCond().
2834 if (Bits32(opcode
, 25, 23) == 7)
2835 return false; // See Branches and miscellaneous control on page
2838 uint32_t S
= Bit32(opcode
, 26);
2839 uint32_t imm6
= Bits32(opcode
, 21, 16);
2840 uint32_t J1
= Bit32(opcode
, 13);
2841 uint32_t J2
= Bit32(opcode
, 11);
2842 uint32_t imm11
= Bits32(opcode
, 10, 0);
2844 (S
<< 20) | (J2
<< 19) | (J1
<< 18) | (imm6
<< 12) | (imm11
<< 1);
2845 imm32
= llvm::SignExtend32
<21>(imm21
);
2846 target
= pc
+ imm32
;
2847 context
.SetISAAndImmediateSigned(eModeThumb
, 4 + imm32
);
2851 uint32_t S
= Bit32(opcode
, 26);
2852 uint32_t imm10
= Bits32(opcode
, 25, 16);
2853 uint32_t J1
= Bit32(opcode
, 13);
2854 uint32_t J2
= Bit32(opcode
, 11);
2855 uint32_t imm11
= Bits32(opcode
, 10, 0);
2856 uint32_t I1
= !(J1
^ S
);
2857 uint32_t I2
= !(J2
^ S
);
2859 (S
<< 24) | (I1
<< 23) | (I2
<< 22) | (imm10
<< 12) | (imm11
<< 1);
2860 imm32
= llvm::SignExtend32
<25>(imm25
);
2861 target
= pc
+ imm32
;
2862 context
.SetISAAndImmediateSigned(eModeThumb
, 4 + imm32
);
2866 imm32
= llvm::SignExtend32
<26>(Bits32(opcode
, 23, 0) << 2);
2867 target
= pc
+ imm32
;
2868 context
.SetISAAndImmediateSigned(eModeARM
, 8 + imm32
);
2873 if (!BranchWritePC(context
, target
))
2879 // Compare and Branch on Nonzero and Compare and Branch on Zero compare the
2880 // value in a register with zero and conditionally branch forward a constant
2881 // value. They do not affect the condition flags. CBNZ, CBZ
2882 bool EmulateInstructionARM::EmulateCB(const uint32_t opcode
,
2883 const ARMEncoding encoding
) {
2885 // ARM pseudo code...
2886 EncodingSpecificOperations();
2887 if nonzero
^ IsZero(R
[n
]) then
2888 BranchWritePC(PC
+ imm32
);
2891 bool success
= false;
2893 // Read the register value from the operand register Rn.
2894 uint32_t reg_val
= ReadCoreReg(Bits32(opcode
, 2, 0), &success
);
2898 EmulateInstruction::Context context
;
2899 context
.type
= EmulateInstruction::eContextRelativeBranchImmediate
;
2900 const uint32_t pc
= ReadCoreReg(PC_REG
, &success
);
2904 addr_t target
; // target address
2905 uint32_t imm32
; // PC-relative offset to branch forward
2909 imm32
= Bit32(opcode
, 9) << 6 | Bits32(opcode
, 7, 3) << 1;
2910 nonzero
= BitIsSet(opcode
, 11);
2911 target
= pc
+ imm32
;
2912 context
.SetISAAndImmediateSigned(eModeThumb
, 4 + imm32
);
2917 if (m_ignore_conditions
|| (nonzero
^ (reg_val
== 0)))
2918 if (!BranchWritePC(context
, target
))
2924 // Table Branch Byte causes a PC-relative forward branch using a table of
2925 // single byte offsets.
2926 // A base register provides a pointer to the table, and a second register
2927 // supplies an index into the table.
2928 // The branch length is twice the value of the byte returned from the table.
2930 // Table Branch Halfword causes a PC-relative forward branch using a table of
2931 // single halfword offsets.
2932 // A base register provides a pointer to the table, and a second register
2933 // supplies an index into the table.
2934 // The branch length is twice the value of the halfword returned from the
2936 bool EmulateInstructionARM::EmulateTB(const uint32_t opcode
,
2937 const ARMEncoding encoding
) {
2939 // ARM pseudo code...
2940 EncodingSpecificOperations(); NullCheckIfThumbEE(n
);
2942 halfwords
= UInt(MemU
[R
[n
]+LSL(R
[m
],1), 2]);
2944 halfwords
= UInt(MemU
[R
[n
]+R
[m
], 1]);
2945 BranchWritePC(PC
+ 2*halfwords
);
2948 bool success
= false;
2950 if (ConditionPassed(opcode
)) {
2951 uint32_t Rn
; // the base register which contains the address of the table of
2953 uint32_t Rm
; // the index register which contains an integer pointing to a
2954 // byte/halfword in the table
2955 bool is_tbh
; // true if table branch halfword
2958 Rn
= Bits32(opcode
, 19, 16);
2959 Rm
= Bits32(opcode
, 3, 0);
2960 is_tbh
= BitIsSet(opcode
, 4);
2961 if (Rn
== 13 || BadReg(Rm
))
2963 if (InITBlock() && !LastInITBlock())
2970 // Read the address of the table from the operand register Rn. The PC can
2971 // be used, in which case the table immediately follows this instruction.
2972 uint32_t base
= ReadCoreReg(Rn
, &success
);
2977 uint32_t index
= ReadCoreReg(Rm
, &success
);
2981 // the offsetted table address
2982 addr_t addr
= base
+ (is_tbh
? index
* 2 : index
);
2984 // PC-relative offset to branch forward
2985 EmulateInstruction::Context context
;
2986 context
.type
= EmulateInstruction::eContextTableBranchReadMemory
;
2987 uint32_t offset
= MemURead(context
, addr
, is_tbh
? 2 : 1, 0, &success
) * 2;
2991 const uint32_t pc
= ReadCoreReg(PC_REG
, &success
);
2996 addr_t target
= pc
+ offset
;
2997 context
.type
= EmulateInstruction::eContextRelativeBranchImmediate
;
2998 context
.SetISAAndImmediateSigned(eModeThumb
, 4 + offset
);
3000 if (!BranchWritePC(context
, target
))
3007 // This instruction adds an immediate value to a register value, and writes the
3008 // result to the destination register. It can optionally update the condition
3009 // flags based on the result.
3010 bool EmulateInstructionARM::EmulateADDImmThumb(const uint32_t opcode
,
3011 const ARMEncoding encoding
) {
3013 if ConditionPassed() then
3014 EncodingSpecificOperations();
3015 (result
, carry
, overflow
) = AddWithCarry(R
[n
], imm32
, '0');
3018 APSR
.N
= result
<31>;
3019 APSR
.Z
= IsZeroBit(result
);
3024 bool success
= false;
3026 if (ConditionPassed(opcode
)) {
3033 // EncodingSpecificOperations();
3036 // d = UInt(Rd); n = UInt(Rn); setflags = !InITBlock(); imm32 =
3037 // ZeroExtend(imm3, 32);
3038 d
= Bits32(opcode
, 2, 0);
3039 n
= Bits32(opcode
, 5, 3);
3040 setflags
= !InITBlock();
3041 imm32
= Bits32(opcode
, 8, 6);
3046 // d = UInt(Rdn); n = UInt(Rdn); setflags = !InITBlock(); imm32 =
3047 // ZeroExtend(imm8, 32);
3048 d
= Bits32(opcode
, 10, 8);
3049 n
= Bits32(opcode
, 10, 8);
3050 setflags
= !InITBlock();
3051 imm32
= Bits32(opcode
, 7, 0);
3056 // if Rd == '1111' && S == '1' then SEE CMN (immediate);
3057 // d = UInt(Rd); n = UInt(Rn); setflags = (S == '1'); imm32 =
3058 // ThumbExpandImm(i:imm3:imm8);
3059 d
= Bits32(opcode
, 11, 8);
3060 n
= Bits32(opcode
, 19, 16);
3061 setflags
= BitIsSet(opcode
, 20);
3062 imm32
= ThumbExpandImm_C(opcode
, APSR_C
, carry_out
);
3064 // if Rn == '1101' then SEE ADD (SP plus immediate);
3066 return EmulateADDSPImm(opcode
, eEncodingT3
);
3068 // if BadReg(d) || n == 15 then UNPREDICTABLE;
3069 if (BadReg(d
) || (n
== 15))
3075 // if Rn == '1111' then SEE ADR;
3076 // d = UInt(Rd); n = UInt(Rn); setflags = FALSE; imm32 =
3077 // ZeroExtend(i:imm3:imm8, 32);
3078 d
= Bits32(opcode
, 11, 8);
3079 n
= Bits32(opcode
, 19, 16);
3081 uint32_t i
= Bit32(opcode
, 26);
3082 uint32_t imm3
= Bits32(opcode
, 14, 12);
3083 uint32_t imm8
= Bits32(opcode
, 7, 0);
3084 imm32
= (i
<< 11) | (imm3
<< 8) | imm8
;
3086 // if Rn == '1101' then SEE ADD (SP plus immediate);
3088 return EmulateADDSPImm(opcode
, eEncodingT4
);
3090 // if BadReg(d) then UNPREDICTABLE;
3102 ReadRegisterUnsigned(eRegisterKindDWARF
, dwarf_r0
+ n
, 0, &success
);
3106 //(result, carry, overflow) = AddWithCarry(R[n], imm32, '0');
3107 AddWithCarryResult res
= AddWithCarry(Rn
, imm32
, 0);
3109 std::optional
<RegisterInfo
> reg_n
=
3110 GetRegisterInfo(eRegisterKindDWARF
, dwarf_r0
+ n
);
3111 EmulateInstruction::Context context
;
3112 context
.type
= eContextArithmetic
;
3113 context
.SetRegisterPlusOffset(*reg_n
, imm32
);
3117 // APSR.N = result<31>;
3118 // APSR.Z = IsZeroBit(result);
3120 // APSR.V = overflow;
3121 if (!WriteCoreRegOptionalFlags(context
, res
.result
, d
, setflags
,
3122 res
.carry_out
, res
.overflow
))
3128 // This instruction adds an immediate value to a register value, and writes the
3129 // result to the destination register. It can optionally update the condition
3130 // flags based on the result.
3131 bool EmulateInstructionARM::EmulateADDImmARM(const uint32_t opcode
,
3132 const ARMEncoding encoding
) {
3134 // ARM pseudo code...
3135 if ConditionPassed() then
3136 EncodingSpecificOperations();
3137 (result
, carry
, overflow
) = AddWithCarry(R
[n
], imm32
, '0');
3139 ALUWritePC(result
); // setflags is always FALSE here
3143 APSR
.N
= result
<31>;
3144 APSR
.Z
= IsZeroBit(result
);
3149 bool success
= false;
3151 if (ConditionPassed(opcode
)) {
3154 imm32
; // the immediate value to be added to the value obtained from Rn
3158 Rd
= Bits32(opcode
, 15, 12);
3159 Rn
= Bits32(opcode
, 19, 16);
3160 setflags
= BitIsSet(opcode
, 20);
3161 imm32
= ARMExpandImm(opcode
); // imm32 = ARMExpandImm(imm12)
3167 // Read the first operand.
3168 uint32_t val1
= ReadCoreReg(Rn
, &success
);
3172 AddWithCarryResult res
= AddWithCarry(val1
, imm32
, 0);
3174 EmulateInstruction::Context context
;
3176 context
.type
= EmulateInstruction::eContextAdjustStackPointer
;
3177 else if (Rd
== GetFramePointerRegisterNumber())
3178 context
.type
= EmulateInstruction::eContextSetFramePointer
;
3180 context
.type
= EmulateInstruction::eContextRegisterPlusOffset
;
3182 std::optional
<RegisterInfo
> dwarf_reg
=
3183 GetRegisterInfo(eRegisterKindDWARF
, Rn
);
3184 context
.SetRegisterPlusOffset(*dwarf_reg
, imm32
);
3186 if (!WriteCoreRegOptionalFlags(context
, res
.result
, Rd
, setflags
,
3187 res
.carry_out
, res
.overflow
))
3193 // This instruction adds a register value and an optionally-shifted register
3194 // value, and writes the result to the destination register. It can optionally
3195 // update the condition flags based on the result.
3196 bool EmulateInstructionARM::EmulateADDReg(const uint32_t opcode
,
3197 const ARMEncoding encoding
) {
3199 // ARM pseudo code...
3200 if ConditionPassed() then
3201 EncodingSpecificOperations();
3202 shifted
= Shift(R
[m
], shift_t
, shift_n
, APSR
.C
);
3203 (result
, carry
, overflow
) = AddWithCarry(R
[n
], shifted
, '0');
3205 ALUWritePC(result
); // setflags is always FALSE here
3209 APSR
.N
= result
<31>;
3210 APSR
.Z
= IsZeroBit(result
);
3215 bool success
= false;
3217 if (ConditionPassed(opcode
)) {
3218 uint32_t Rd
, Rn
, Rm
;
3219 ARM_ShifterType shift_t
;
3220 uint32_t shift_n
; // the shift applied to the value read from Rm
3224 Rd
= Bits32(opcode
, 2, 0);
3225 Rn
= Bits32(opcode
, 5, 3);
3226 Rm
= Bits32(opcode
, 8, 6);
3227 setflags
= !InITBlock();
3228 shift_t
= SRType_LSL
;
3232 Rd
= Rn
= Bit32(opcode
, 7) << 3 | Bits32(opcode
, 2, 0);
3233 Rm
= Bits32(opcode
, 6, 3);
3235 shift_t
= SRType_LSL
;
3237 if (Rn
== 15 && Rm
== 15)
3239 if (Rd
== 15 && InITBlock() && !LastInITBlock())
3243 Rd
= Bits32(opcode
, 15, 12);
3244 Rn
= Bits32(opcode
, 19, 16);
3245 Rm
= Bits32(opcode
, 3, 0);
3246 setflags
= BitIsSet(opcode
, 20);
3247 shift_n
= DecodeImmShiftARM(opcode
, shift_t
);
3253 // Read the first operand.
3254 uint32_t val1
= ReadCoreReg(Rn
, &success
);
3258 // Read the second operand.
3259 uint32_t val2
= ReadCoreReg(Rm
, &success
);
3263 uint32_t shifted
= Shift(val2
, shift_t
, shift_n
, APSR_C
, &success
);
3266 AddWithCarryResult res
= AddWithCarry(val1
, shifted
, 0);
3268 EmulateInstruction::Context context
;
3269 context
.type
= eContextArithmetic
;
3270 std::optional
<RegisterInfo
> op1_reg
=
3271 GetRegisterInfo(eRegisterKindDWARF
, dwarf_r0
+ Rn
);
3272 std::optional
<RegisterInfo
> op2_reg
=
3273 GetRegisterInfo(eRegisterKindDWARF
, dwarf_r0
+ Rm
);
3274 context
.SetRegisterRegisterOperands(*op1_reg
, *op2_reg
);
3276 if (!WriteCoreRegOptionalFlags(context
, res
.result
, Rd
, setflags
,
3277 res
.carry_out
, res
.overflow
))
3283 // Compare Negative (immediate) adds a register value and an immediate value.
3284 // It updates the condition flags based on the result, and discards the result.
3285 bool EmulateInstructionARM::EmulateCMNImm(const uint32_t opcode
,
3286 const ARMEncoding encoding
) {
3288 // ARM pseudo code...
3289 if ConditionPassed() then
3290 EncodingSpecificOperations();
3291 (result
, carry
, overflow
) = AddWithCarry(R
[n
], imm32
, '0');
3292 APSR
.N
= result
<31>;
3293 APSR
.Z
= IsZeroBit(result
);
3298 bool success
= false;
3300 uint32_t Rn
; // the first operand
3301 uint32_t imm32
; // the immediate value to be compared with
3304 Rn
= Bits32(opcode
, 19, 16);
3305 imm32
= ThumbExpandImm(opcode
); // imm32 = ThumbExpandImm(i:imm3:imm8)
3310 Rn
= Bits32(opcode
, 19, 16);
3311 imm32
= ARMExpandImm(opcode
); // imm32 = ARMExpandImm(imm12)
3316 // Read the register value from the operand register Rn.
3317 uint32_t reg_val
= ReadCoreReg(Rn
, &success
);
3321 AddWithCarryResult res
= AddWithCarry(reg_val
, imm32
, 0);
3323 EmulateInstruction::Context context
;
3324 context
.type
= EmulateInstruction::eContextImmediate
;
3325 context
.SetNoArgs();
3326 return WriteFlags(context
, res
.result
, res
.carry_out
, res
.overflow
);
3329 // Compare Negative (register) adds a register value and an optionally-shifted
3330 // register value. It updates the condition flags based on the result, and
3331 // discards the result.
3332 bool EmulateInstructionARM::EmulateCMNReg(const uint32_t opcode
,
3333 const ARMEncoding encoding
) {
3335 // ARM pseudo code...
3336 if ConditionPassed() then
3337 EncodingSpecificOperations();
3338 shifted
= Shift(R
[m
], shift_t
, shift_n
, APSR
.C
);
3339 (result
, carry
, overflow
) = AddWithCarry(R
[n
], shifted
, '0');
3340 APSR
.N
= result
<31>;
3341 APSR
.Z
= IsZeroBit(result
);
3346 bool success
= false;
3348 uint32_t Rn
; // the first operand
3349 uint32_t Rm
; // the second operand
3350 ARM_ShifterType shift_t
;
3351 uint32_t shift_n
; // the shift applied to the value read from Rm
3354 Rn
= Bits32(opcode
, 2, 0);
3355 Rm
= Bits32(opcode
, 5, 3);
3356 shift_t
= SRType_LSL
;
3360 Rn
= Bits32(opcode
, 19, 16);
3361 Rm
= Bits32(opcode
, 3, 0);
3362 shift_n
= DecodeImmShiftThumb(opcode
, shift_t
);
3363 // if n == 15 || BadReg(m) then UNPREDICTABLE;
3364 if (Rn
== 15 || BadReg(Rm
))
3368 Rn
= Bits32(opcode
, 19, 16);
3369 Rm
= Bits32(opcode
, 3, 0);
3370 shift_n
= DecodeImmShiftARM(opcode
, shift_t
);
3375 // Read the register value from register Rn.
3376 uint32_t val1
= ReadCoreReg(Rn
, &success
);
3380 // Read the register value from register Rm.
3381 uint32_t val2
= ReadCoreReg(Rm
, &success
);
3385 uint32_t shifted
= Shift(val2
, shift_t
, shift_n
, APSR_C
, &success
);
3388 AddWithCarryResult res
= AddWithCarry(val1
, shifted
, 0);
3390 EmulateInstruction::Context context
;
3391 context
.type
= EmulateInstruction::eContextImmediate
;
3392 context
.SetNoArgs();
3393 return WriteFlags(context
, res
.result
, res
.carry_out
, res
.overflow
);
3396 // Compare (immediate) subtracts an immediate value from a register value. It
3397 // updates the condition flags based on the result, and discards the result.
3398 bool EmulateInstructionARM::EmulateCMPImm(const uint32_t opcode
,
3399 const ARMEncoding encoding
) {
3401 // ARM pseudo code...
3402 if ConditionPassed() then
3403 EncodingSpecificOperations();
3404 (result
, carry
, overflow
) = AddWithCarry(R
[n
], NOT(imm32
), '1');
3405 APSR
.N
= result
<31>;
3406 APSR
.Z
= IsZeroBit(result
);
3411 bool success
= false;
3413 uint32_t Rn
; // the first operand
3414 uint32_t imm32
; // the immediate value to be compared with
3417 Rn
= Bits32(opcode
, 10, 8);
3418 imm32
= Bits32(opcode
, 7, 0);
3421 Rn
= Bits32(opcode
, 19, 16);
3422 imm32
= ThumbExpandImm(opcode
); // imm32 = ThumbExpandImm(i:imm3:imm8)
3427 Rn
= Bits32(opcode
, 19, 16);
3428 imm32
= ARMExpandImm(opcode
); // imm32 = ARMExpandImm(imm12)
3433 // Read the register value from the operand register Rn.
3434 uint32_t reg_val
= ReadCoreReg(Rn
, &success
);
3438 AddWithCarryResult res
= AddWithCarry(reg_val
, ~imm32
, 1);
3440 EmulateInstruction::Context context
;
3441 context
.type
= EmulateInstruction::eContextImmediate
;
3442 context
.SetNoArgs();
3443 return WriteFlags(context
, res
.result
, res
.carry_out
, res
.overflow
);
3446 // Compare (register) subtracts an optionally-shifted register value from a
3447 // register value. It updates the condition flags based on the result, and
3448 // discards the result.
3449 bool EmulateInstructionARM::EmulateCMPReg(const uint32_t opcode
,
3450 const ARMEncoding encoding
) {
3452 // ARM pseudo code...
3453 if ConditionPassed() then
3454 EncodingSpecificOperations();
3455 shifted
= Shift(R
[m
], shift_t
, shift_n
, APSR
.C
);
3456 (result
, carry
, overflow
) = AddWithCarry(R
[n
], NOT(shifted
), '1');
3457 APSR
.N
= result
<31>;
3458 APSR
.Z
= IsZeroBit(result
);
3463 bool success
= false;
3465 uint32_t Rn
; // the first operand
3466 uint32_t Rm
; // the second operand
3467 ARM_ShifterType shift_t
;
3468 uint32_t shift_n
; // the shift applied to the value read from Rm
3471 Rn
= Bits32(opcode
, 2, 0);
3472 Rm
= Bits32(opcode
, 5, 3);
3473 shift_t
= SRType_LSL
;
3477 Rn
= Bit32(opcode
, 7) << 3 | Bits32(opcode
, 2, 0);
3478 Rm
= Bits32(opcode
, 6, 3);
3479 shift_t
= SRType_LSL
;
3481 if (Rn
< 8 && Rm
< 8)
3483 if (Rn
== 15 || Rm
== 15)
3487 Rn
= Bits32(opcode
, 19, 16);
3488 Rm
= Bits32(opcode
, 3, 0);
3489 shift_n
= DecodeImmShiftThumb(opcode
, shift_t
);
3490 if (Rn
== 15 || BadReg(Rm
))
3494 Rn
= Bits32(opcode
, 19, 16);
3495 Rm
= Bits32(opcode
, 3, 0);
3496 shift_n
= DecodeImmShiftARM(opcode
, shift_t
);
3501 // Read the register value from register Rn.
3502 uint32_t val1
= ReadCoreReg(Rn
, &success
);
3506 // Read the register value from register Rm.
3507 uint32_t val2
= ReadCoreReg(Rm
, &success
);
3511 uint32_t shifted
= Shift(val2
, shift_t
, shift_n
, APSR_C
, &success
);
3514 AddWithCarryResult res
= AddWithCarry(val1
, ~shifted
, 1);
3516 EmulateInstruction::Context context
;
3517 context
.type
= EmulateInstruction::eContextImmediate
;
3518 context
.SetNoArgs();
3519 return WriteFlags(context
, res
.result
, res
.carry_out
, res
.overflow
);
3522 // Arithmetic Shift Right (immediate) shifts a register value right by an
3523 // immediate number of bits, shifting in copies of its sign bit, and writes the
3524 // result to the destination register. It can optionally update the condition
3525 // flags based on the result.
3526 bool EmulateInstructionARM::EmulateASRImm(const uint32_t opcode
,
3527 const ARMEncoding encoding
) {
3529 // ARM pseudo code...
3530 if ConditionPassed() then
3531 EncodingSpecificOperations();
3532 (result
, carry
) = Shift_C(R
[m
], SRType_ASR
, shift_n
, APSR
.C
);
3533 if d
== 15 then
// Can only occur for ARM encoding
3534 ALUWritePC(result
); // setflags is always FALSE here
3538 APSR
.N
= result
<31>;
3539 APSR
.Z
= IsZeroBit(result
);
3544 return EmulateShiftImm(opcode
, encoding
, SRType_ASR
);
3547 // Arithmetic Shift Right (register) shifts a register value right by a
3548 // variable number of bits, shifting in copies of its sign bit, and writes the
3549 // result to the destination register. The variable number of bits is read from
3550 // the bottom byte of a register. It can optionally update the condition flags
3551 // based on the result.
3552 bool EmulateInstructionARM::EmulateASRReg(const uint32_t opcode
,
3553 const ARMEncoding encoding
) {
3555 // ARM pseudo code...
3556 if ConditionPassed() then
3557 EncodingSpecificOperations();
3558 shift_n
= UInt(R
[m
]<7:0>);
3559 (result
, carry
) = Shift_C(R
[m
], SRType_ASR
, shift_n
, APSR
.C
);
3562 APSR
.N
= result
<31>;
3563 APSR
.Z
= IsZeroBit(result
);
3568 return EmulateShiftReg(opcode
, encoding
, SRType_ASR
);
3571 // Logical Shift Left (immediate) shifts a register value left by an immediate
3572 // number of bits, shifting in zeros, and writes the result to the destination
3573 // register. It can optionally update the condition flags based on the result.
3574 bool EmulateInstructionARM::EmulateLSLImm(const uint32_t opcode
,
3575 const ARMEncoding encoding
) {
3577 // ARM pseudo code...
3578 if ConditionPassed() then
3579 EncodingSpecificOperations();
3580 (result
, carry
) = Shift_C(R
[m
], SRType_LSL
, shift_n
, APSR
.C
);
3581 if d
== 15 then
// Can only occur for ARM encoding
3582 ALUWritePC(result
); // setflags is always FALSE here
3586 APSR
.N
= result
<31>;
3587 APSR
.Z
= IsZeroBit(result
);
3592 return EmulateShiftImm(opcode
, encoding
, SRType_LSL
);
3595 // Logical Shift Left (register) shifts a register value left by a variable
3596 // number of bits, shifting in zeros, and writes the result to the destination
3597 // register. The variable number of bits is read from the bottom byte of a
3598 // register. It can optionally update the condition flags based on the result.
3599 bool EmulateInstructionARM::EmulateLSLReg(const uint32_t opcode
,
3600 const ARMEncoding encoding
) {
3602 // ARM pseudo code...
3603 if ConditionPassed() then
3604 EncodingSpecificOperations();
3605 shift_n
= UInt(R
[m
]<7:0>);
3606 (result
, carry
) = Shift_C(R
[m
], SRType_LSL
, shift_n
, APSR
.C
);
3609 APSR
.N
= result
<31>;
3610 APSR
.Z
= IsZeroBit(result
);
3615 return EmulateShiftReg(opcode
, encoding
, SRType_LSL
);
3618 // Logical Shift Right (immediate) shifts a register value right by an
3619 // immediate number of bits, shifting in zeros, and writes the result to the
3620 // destination register. It can optionally update the condition flags based on
3622 bool EmulateInstructionARM::EmulateLSRImm(const uint32_t opcode
,
3623 const ARMEncoding encoding
) {
3625 // ARM pseudo code...
3626 if ConditionPassed() then
3627 EncodingSpecificOperations();
3628 (result
, carry
) = Shift_C(R
[m
], SRType_LSR
, shift_n
, APSR
.C
);
3629 if d
== 15 then
// Can only occur for ARM encoding
3630 ALUWritePC(result
); // setflags is always FALSE here
3634 APSR
.N
= result
<31>;
3635 APSR
.Z
= IsZeroBit(result
);
3640 return EmulateShiftImm(opcode
, encoding
, SRType_LSR
);
3643 // Logical Shift Right (register) shifts a register value right by a variable
3644 // number of bits, shifting in zeros, and writes the result to the destination
3645 // register. The variable number of bits is read from the bottom byte of a
3646 // register. It can optionally update the condition flags based on the result.
3647 bool EmulateInstructionARM::EmulateLSRReg(const uint32_t opcode
,
3648 const ARMEncoding encoding
) {
3650 // ARM pseudo code...
3651 if ConditionPassed() then
3652 EncodingSpecificOperations();
3653 shift_n
= UInt(R
[m
]<7:0>);
3654 (result
, carry
) = Shift_C(R
[m
], SRType_LSR
, shift_n
, APSR
.C
);
3657 APSR
.N
= result
<31>;
3658 APSR
.Z
= IsZeroBit(result
);
3663 return EmulateShiftReg(opcode
, encoding
, SRType_LSR
);
3666 // Rotate Right (immediate) provides the value of the contents of a register
3667 // rotated by a constant value. The bits that are rotated off the right end are
3668 // inserted into the vacated bit positions on the left. It can optionally
3669 // update the condition flags based on the result.
3670 bool EmulateInstructionARM::EmulateRORImm(const uint32_t opcode
,
3671 const ARMEncoding encoding
) {
3673 // ARM pseudo code...
3674 if ConditionPassed() then
3675 EncodingSpecificOperations();
3676 (result
, carry
) = Shift_C(R
[m
], SRType_ROR
, shift_n
, APSR
.C
);
3677 if d
== 15 then
// Can only occur for ARM encoding
3678 ALUWritePC(result
); // setflags is always FALSE here
3682 APSR
.N
= result
<31>;
3683 APSR
.Z
= IsZeroBit(result
);
3688 return EmulateShiftImm(opcode
, encoding
, SRType_ROR
);
3691 // Rotate Right (register) provides the value of the contents of a register
3692 // rotated by a variable number of bits. The bits that are rotated off the
3693 // right end are inserted into the vacated bit positions on the left. The
3694 // variable number of bits is read from the bottom byte of a register. It can
3695 // optionally update the condition flags based on the result.
3696 bool EmulateInstructionARM::EmulateRORReg(const uint32_t opcode
,
3697 const ARMEncoding encoding
) {
3699 // ARM pseudo code...
3700 if ConditionPassed() then
3701 EncodingSpecificOperations();
3702 shift_n
= UInt(R
[m
]<7:0>);
3703 (result
, carry
) = Shift_C(R
[m
], SRType_ROR
, shift_n
, APSR
.C
);
3706 APSR
.N
= result
<31>;
3707 APSR
.Z
= IsZeroBit(result
);
3712 return EmulateShiftReg(opcode
, encoding
, SRType_ROR
);
3715 // Rotate Right with Extend provides the value of the contents of a register
3716 // shifted right by one place, with the carry flag shifted into bit [31].
3718 // RRX can optionally update the condition flags based on the result.
3719 // In that case, bit [0] is shifted into the carry flag.
3720 bool EmulateInstructionARM::EmulateRRX(const uint32_t opcode
,
3721 const ARMEncoding encoding
) {
3723 // ARM pseudo code...
3724 if ConditionPassed() then
3725 EncodingSpecificOperations();
3726 (result
, carry
) = Shift_C(R
[m
], SRType_RRX
, 1, APSR
.C
);
3727 if d
== 15 then
// Can only occur for ARM encoding
3728 ALUWritePC(result
); // setflags is always FALSE here
3732 APSR
.N
= result
<31>;
3733 APSR
.Z
= IsZeroBit(result
);
3738 return EmulateShiftImm(opcode
, encoding
, SRType_RRX
);
3741 bool EmulateInstructionARM::EmulateShiftImm(const uint32_t opcode
,
3742 const ARMEncoding encoding
,
3743 ARM_ShifterType shift_type
) {
3744 // assert(shift_type == SRType_ASR
3745 // || shift_type == SRType_LSL
3746 // || shift_type == SRType_LSR
3747 // || shift_type == SRType_ROR
3748 // || shift_type == SRType_RRX);
3750 bool success
= false;
3752 if (ConditionPassed(opcode
)) {
3753 uint32_t Rd
; // the destination register
3754 uint32_t Rm
; // the first operand register
3755 uint32_t imm5
; // encoding for the shift amount
3756 uint32_t carry
; // the carry bit after the shift operation
3759 // Special case handling!
3760 // A8.6.139 ROR (immediate) -- Encoding T1
3761 ARMEncoding use_encoding
= encoding
;
3762 if (shift_type
== SRType_ROR
&& use_encoding
== eEncodingT1
) {
3763 // Morph the T1 encoding from the ARM Architecture Manual into T2
3764 // encoding to have the same decoding of bit fields as the other Thumb2
3765 // shift operations.
3766 use_encoding
= eEncodingT2
;
3769 switch (use_encoding
) {
3771 Rd
= Bits32(opcode
, 2, 0);
3772 Rm
= Bits32(opcode
, 5, 3);
3773 setflags
= !InITBlock();
3774 imm5
= Bits32(opcode
, 10, 6);
3778 // There's no imm form of RRX instructions.
3779 if (shift_type
== SRType_RRX
)
3782 Rd
= Bits32(opcode
, 11, 8);
3783 Rm
= Bits32(opcode
, 3, 0);
3784 setflags
= BitIsSet(opcode
, 20);
3785 imm5
= Bits32(opcode
, 14, 12) << 2 | Bits32(opcode
, 7, 6);
3786 if (BadReg(Rd
) || BadReg(Rm
))
3790 Rd
= Bits32(opcode
, 15, 12);
3791 Rm
= Bits32(opcode
, 3, 0);
3792 setflags
= BitIsSet(opcode
, 20);
3793 imm5
= Bits32(opcode
, 11, 7);
3799 // A8.6.139 ROR (immediate)
3800 if (shift_type
== SRType_ROR
&& imm5
== 0)
3801 shift_type
= SRType_RRX
;
3803 // Get the first operand.
3804 uint32_t value
= ReadCoreReg(Rm
, &success
);
3808 // Decode the shift amount if not RRX.
3810 (shift_type
== SRType_RRX
? 1 : DecodeImmShift(shift_type
, imm5
));
3812 uint32_t result
= Shift_C(value
, shift_type
, amt
, APSR_C
, carry
, &success
);
3816 // The context specifies that an immediate is to be moved into Rd.
3817 EmulateInstruction::Context context
;
3818 context
.type
= EmulateInstruction::eContextImmediate
;
3819 context
.SetNoArgs();
3821 if (!WriteCoreRegOptionalFlags(context
, result
, Rd
, setflags
, carry
))
3827 bool EmulateInstructionARM::EmulateShiftReg(const uint32_t opcode
,
3828 const ARMEncoding encoding
,
3829 ARM_ShifterType shift_type
) {
3830 // assert(shift_type == SRType_ASR
3831 // || shift_type == SRType_LSL
3832 // || shift_type == SRType_LSR
3833 // || shift_type == SRType_ROR);
3835 bool success
= false;
3837 if (ConditionPassed(opcode
)) {
3838 uint32_t Rd
; // the destination register
3839 uint32_t Rn
; // the first operand register
3841 Rm
; // the register whose bottom byte contains the amount to shift by
3842 uint32_t carry
; // the carry bit after the shift operation
3846 Rd
= Bits32(opcode
, 2, 0);
3848 Rm
= Bits32(opcode
, 5, 3);
3849 setflags
= !InITBlock();
3852 Rd
= Bits32(opcode
, 11, 8);
3853 Rn
= Bits32(opcode
, 19, 16);
3854 Rm
= Bits32(opcode
, 3, 0);
3855 setflags
= BitIsSet(opcode
, 20);
3856 if (BadReg(Rd
) || BadReg(Rn
) || BadReg(Rm
))
3860 Rd
= Bits32(opcode
, 15, 12);
3861 Rn
= Bits32(opcode
, 3, 0);
3862 Rm
= Bits32(opcode
, 11, 8);
3863 setflags
= BitIsSet(opcode
, 20);
3864 if (Rd
== 15 || Rn
== 15 || Rm
== 15)
3871 // Get the first operand.
3872 uint32_t value
= ReadCoreReg(Rn
, &success
);
3875 // Get the Rm register content.
3876 uint32_t val
= ReadCoreReg(Rm
, &success
);
3880 // Get the shift amount.
3881 uint32_t amt
= Bits32(val
, 7, 0);
3883 uint32_t result
= Shift_C(value
, shift_type
, amt
, APSR_C
, carry
, &success
);
3887 // The context specifies that an immediate is to be moved into Rd.
3888 EmulateInstruction::Context context
;
3889 context
.type
= EmulateInstruction::eContextImmediate
;
3890 context
.SetNoArgs();
3892 if (!WriteCoreRegOptionalFlags(context
, result
, Rd
, setflags
, carry
))
3898 // LDM loads multiple registers from consecutive memory locations, using an
3899 // address from a base register. Optionally the address just above the highest
3900 // of those locations can be written back to the base register.
3901 bool EmulateInstructionARM::EmulateLDM(const uint32_t opcode
,
3902 const ARMEncoding encoding
) {
3904 // ARM pseudo code...
3905 if ConditionPassed()
3906 EncodingSpecificOperations(); NullCheckIfThumbEE (n
);
3910 if registers
<i
> == '1' then
3911 R
[i
] = MemA
[address
, 4]; address
= address
+ 4;
3912 if registers
<15> == '1' then
3913 LoadWritePC (MemA
[address
, 4]);
3915 if wback
&& registers
<n
> == '0' then R
[n
] = R
[n
] + 4 * BitCount (registers
);
3916 if wback
&& registers
<n
> == '1' then R
[n
] = bits(32) UNKNOWN
; // Only possible for encoding A1
3920 bool success
= false;
3921 if (ConditionPassed(opcode
)) {
3923 uint32_t registers
= 0;
3925 const uint32_t addr_byte_size
= GetAddressByteSize();
3928 // n = UInt(Rn); registers = '00000000':register_list; wback =
3929 // (registers<n> == '0');
3930 n
= Bits32(opcode
, 10, 8);
3931 registers
= Bits32(opcode
, 7, 0);
3932 registers
= registers
& 0x00ff; // Make sure the top 8 bits are zeros.
3933 wback
= BitIsClear(registers
, n
);
3934 // if BitCount(registers) < 1 then UNPREDICTABLE;
3935 if (BitCount(registers
) < 1)
3939 // if W == '1' && Rn == '1101' then SEE POP;
3940 // n = UInt(Rn); registers = P:M:'0':register_list; wback = (W == '1');
3941 n
= Bits32(opcode
, 19, 16);
3942 registers
= Bits32(opcode
, 15, 0);
3943 registers
= registers
& 0xdfff; // Make sure bit 13 is zero.
3944 wback
= BitIsSet(opcode
, 21);
3946 // if n == 15 || BitCount(registers) < 2 || (P == '1' && M == '1') then
3948 if ((n
== 15) || (BitCount(registers
) < 2) ||
3949 (BitIsSet(opcode
, 14) && BitIsSet(opcode
, 15)))
3952 // if registers<15> == '1' && InITBlock() && !LastInITBlock() then
3954 if (BitIsSet(registers
, 15) && InITBlock() && !LastInITBlock())
3957 // if wback && registers<n> == '1' then UNPREDICTABLE;
3958 if (wback
&& BitIsSet(registers
, n
))
3963 n
= Bits32(opcode
, 19, 16);
3964 registers
= Bits32(opcode
, 15, 0);
3965 wback
= BitIsSet(opcode
, 21);
3966 if ((n
== 15) || (BitCount(registers
) < 1))
3974 const addr_t base_address
=
3975 ReadRegisterUnsigned(eRegisterKindDWARF
, dwarf_r0
+ n
, 0, &success
);
3979 EmulateInstruction::Context context
;
3980 context
.type
= EmulateInstruction::eContextRegisterPlusOffset
;
3981 std::optional
<RegisterInfo
> dwarf_reg
=
3982 GetRegisterInfo(eRegisterKindDWARF
, dwarf_r0
+ n
);
3983 context
.SetRegisterPlusOffset(*dwarf_reg
, offset
);
3985 for (int i
= 0; i
< 14; ++i
) {
3986 if (BitIsSet(registers
, i
)) {
3987 context
.type
= EmulateInstruction::eContextRegisterPlusOffset
;
3988 context
.SetRegisterPlusOffset(*dwarf_reg
, offset
);
3989 if (wback
&& (n
== 13)) // Pop Instruction
3991 context
.type
= EmulateInstruction::eContextPopRegisterOffStack
;
3992 context
.SetAddress(base_address
+ offset
);
3995 // R[i] = MemA [address, 4]; address = address + 4;
3996 uint32_t data
= MemARead(context
, base_address
+ offset
, addr_byte_size
,
4001 if (!WriteRegisterUnsigned(context
, eRegisterKindDWARF
, dwarf_r0
+ i
,
4005 offset
+= addr_byte_size
;
4009 if (BitIsSet(registers
, 15)) {
4010 // LoadWritePC (MemA [address, 4]);
4011 context
.type
= EmulateInstruction::eContextRegisterPlusOffset
;
4012 context
.SetRegisterPlusOffset(*dwarf_reg
, offset
);
4014 MemARead(context
, base_address
+ offset
, addr_byte_size
, 0, &success
);
4017 // In ARMv5T and above, this is an interworking branch.
4018 if (!LoadWritePC(context
, data
))
4022 if (wback
&& BitIsClear(registers
, n
)) {
4023 // R[n] = R[n] + 4 * BitCount (registers)
4024 int32_t offset
= addr_byte_size
* BitCount(registers
);
4025 context
.type
= EmulateInstruction::eContextAdjustBaseRegister
;
4026 context
.SetRegisterPlusOffset(*dwarf_reg
, offset
);
4028 if (!WriteRegisterUnsigned(context
, eRegisterKindDWARF
, dwarf_r0
+ n
,
4029 base_address
+ offset
))
4032 if (wback
&& BitIsSet(registers
, n
))
4033 // R[n] bits(32) UNKNOWN;
4034 return WriteBits32Unknown(n
);
4039 // LDMDA loads multiple registers from consecutive memory locations using an
4040 // address from a base register.
4041 // The consecutive memory locations end at this address and the address just
4042 // below the lowest of those locations can optionally be written back to the
4044 bool EmulateInstructionARM::EmulateLDMDA(const uint32_t opcode
,
4045 const ARMEncoding encoding
) {
4047 // ARM pseudo code...
4048 if ConditionPassed() then
4049 EncodingSpecificOperations();
4050 address
= R
[n
] - 4*BitCount(registers
) + 4;
4053 if registers
<i
> == '1' then
4054 R
[i
] = MemA
[address
,4]; address
= address
+ 4;
4056 if registers
<15> == '1' then
4057 LoadWritePC(MemA
[address
,4]);
4059 if wback
&& registers
<n
> == '0' then R
[n
] = R
[n
] - 4*BitCount(registers
);
4060 if wback
&& registers
<n
> == '1' then R
[n
] = bits(32) UNKNOWN
;
4063 bool success
= false;
4065 if (ConditionPassed(opcode
)) {
4067 uint32_t registers
= 0;
4069 const uint32_t addr_byte_size
= GetAddressByteSize();
4071 // EncodingSpecificOperations();
4074 // n = UInt(Rn); registers = register_list; wback = (W == '1');
4075 n
= Bits32(opcode
, 19, 16);
4076 registers
= Bits32(opcode
, 15, 0);
4077 wback
= BitIsSet(opcode
, 21);
4079 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
4080 if ((n
== 15) || (BitCount(registers
) < 1))
4088 // address = R[n] - 4*BitCount(registers) + 4;
4091 addr_t Rn
= ReadCoreReg(n
, &success
);
4097 Rn
- (addr_byte_size
* BitCount(registers
)) + addr_byte_size
;
4099 EmulateInstruction::Context context
;
4100 context
.type
= EmulateInstruction::eContextRegisterPlusOffset
;
4101 std::optional
<RegisterInfo
> dwarf_reg
=
4102 GetRegisterInfo(eRegisterKindDWARF
, dwarf_r0
+ n
);
4103 context
.SetRegisterPlusOffset(*dwarf_reg
, offset
);
4106 for (int i
= 0; i
< 14; ++i
) {
4107 // if registers<i> == '1' then
4108 if (BitIsSet(registers
, i
)) {
4109 // R[i] = MemA[address,4]; address = address + 4;
4110 context
.SetRegisterPlusOffset(*dwarf_reg
, Rn
- (address
+ offset
));
4112 MemARead(context
, address
+ offset
, addr_byte_size
, 0, &success
);
4115 if (!WriteRegisterUnsigned(context
, eRegisterKindDWARF
, dwarf_r0
+ i
,
4118 offset
+= addr_byte_size
;
4122 // if registers<15> == '1' then
4123 // LoadWritePC(MemA[address,4]);
4124 if (BitIsSet(registers
, 15)) {
4125 context
.SetRegisterPlusOffset(*dwarf_reg
, offset
);
4127 MemARead(context
, address
+ offset
, addr_byte_size
, 0, &success
);
4130 // In ARMv5T and above, this is an interworking branch.
4131 if (!LoadWritePC(context
, data
))
4135 // if wback && registers<n> == '0' then R[n] = R[n] - 4*BitCount(registers);
4136 if (wback
&& BitIsClear(registers
, n
)) {
4138 offset
= (addr_byte_size
* BitCount(registers
)) * -1;
4139 context
.type
= EmulateInstruction::eContextAdjustBaseRegister
;
4140 context
.SetImmediateSigned(offset
);
4141 addr_t addr
= Rn
+ offset
;
4142 if (!WriteRegisterUnsigned(context
, eRegisterKindDWARF
, dwarf_r0
+ n
,
4147 // if wback && registers<n> == '1' then R[n] = bits(32) UNKNOWN;
4148 if (wback
&& BitIsSet(registers
, n
))
4149 return WriteBits32Unknown(n
);
4154 // LDMDB loads multiple registers from consecutive memory locations using an
4155 // address from a base register. The
4156 // consecutive memory locations end just below this address, and the address of
4157 // the lowest of those locations can be optionally written back to the base
4159 bool EmulateInstructionARM::EmulateLDMDB(const uint32_t opcode
,
4160 const ARMEncoding encoding
) {
4162 // ARM pseudo code...
4163 if ConditionPassed() then
4164 EncodingSpecificOperations(); NullCheckIfThumbEE(n
);
4165 address
= R
[n
] - 4*BitCount(registers
);
4168 if registers
<i
> == '1' then
4169 R
[i
] = MemA
[address
,4]; address
= address
+ 4;
4170 if registers
<15> == '1' then
4171 LoadWritePC(MemA
[address
,4]);
4173 if wback
&& registers
<n
> == '0' then R
[n
] = R
[n
] - 4*BitCount(registers
);
4174 if wback
&& registers
<n
> == '1' then R
[n
] = bits(32) UNKNOWN
; // Only possible for encoding A1
4177 bool success
= false;
4179 if (ConditionPassed(opcode
)) {
4181 uint32_t registers
= 0;
4183 const uint32_t addr_byte_size
= GetAddressByteSize();
4186 // n = UInt(Rn); registers = P:M:'0':register_list; wback = (W == '1');
4187 n
= Bits32(opcode
, 19, 16);
4188 registers
= Bits32(opcode
, 15, 0);
4189 registers
= registers
& 0xdfff; // Make sure bit 13 is a zero.
4190 wback
= BitIsSet(opcode
, 21);
4192 // if n == 15 || BitCount(registers) < 2 || (P == '1' && M == '1') then
4194 if ((n
== 15) || (BitCount(registers
) < 2) ||
4195 (BitIsSet(opcode
, 14) && BitIsSet(opcode
, 15)))
4198 // if registers<15> == '1' && InITBlock() && !LastInITBlock() then
4200 if (BitIsSet(registers
, 15) && InITBlock() && !LastInITBlock())
4203 // if wback && registers<n> == '1' then UNPREDICTABLE;
4204 if (wback
&& BitIsSet(registers
, n
))
4210 // n = UInt(Rn); registers = register_list; wback = (W == '1');
4211 n
= Bits32(opcode
, 19, 16);
4212 registers
= Bits32(opcode
, 15, 0);
4213 wback
= BitIsSet(opcode
, 21);
4215 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
4216 if ((n
== 15) || (BitCount(registers
) < 1))
4225 // address = R[n] - 4*BitCount(registers);
4229 ReadRegisterUnsigned(eRegisterKindDWARF
, dwarf_r0
+ n
, 0, &success
);
4234 addr_t address
= Rn
- (addr_byte_size
* BitCount(registers
));
4235 EmulateInstruction::Context context
;
4236 context
.type
= EmulateInstruction::eContextRegisterPlusOffset
;
4237 std::optional
<RegisterInfo
> dwarf_reg
=
4238 GetRegisterInfo(eRegisterKindDWARF
, dwarf_r0
+ n
);
4239 context
.SetRegisterPlusOffset(*dwarf_reg
, Rn
- address
);
4241 for (int i
= 0; i
< 14; ++i
) {
4242 if (BitIsSet(registers
, i
)) {
4243 // R[i] = MemA[address,4]; address = address + 4;
4244 context
.SetRegisterPlusOffset(*dwarf_reg
, Rn
- (address
+ offset
));
4246 MemARead(context
, address
+ offset
, addr_byte_size
, 0, &success
);
4250 if (!WriteRegisterUnsigned(context
, eRegisterKindDWARF
, dwarf_r0
+ i
,
4254 offset
+= addr_byte_size
;
4258 // if registers<15> == '1' then
4259 // LoadWritePC(MemA[address,4]);
4260 if (BitIsSet(registers
, 15)) {
4261 context
.SetRegisterPlusOffset(*dwarf_reg
, offset
);
4263 MemARead(context
, address
+ offset
, addr_byte_size
, 0, &success
);
4266 // In ARMv5T and above, this is an interworking branch.
4267 if (!LoadWritePC(context
, data
))
4271 // if wback && registers<n> == '0' then R[n] = R[n] - 4*BitCount(registers);
4272 if (wback
&& BitIsClear(registers
, n
)) {
4274 offset
= (addr_byte_size
* BitCount(registers
)) * -1;
4275 context
.type
= EmulateInstruction::eContextAdjustBaseRegister
;
4276 context
.SetImmediateSigned(offset
);
4277 addr_t addr
= Rn
+ offset
;
4278 if (!WriteRegisterUnsigned(context
, eRegisterKindDWARF
, dwarf_r0
+ n
,
4283 // if wback && registers<n> == '1' then R[n] = bits(32) UNKNOWN; // Only
4284 // possible for encoding A1
4285 if (wback
&& BitIsSet(registers
, n
))
4286 return WriteBits32Unknown(n
);
4291 // LDMIB loads multiple registers from consecutive memory locations using an
4292 // address from a base register. The
4293 // consecutive memory locations start just above this address, and thea ddress
4294 // of the last of those locations can optinoally be written back to the base
4296 bool EmulateInstructionARM::EmulateLDMIB(const uint32_t opcode
,
4297 const ARMEncoding encoding
) {
4299 if ConditionPassed() then
4300 EncodingSpecificOperations();
4304 if registers
<i
> == '1' then
4305 R
[i
] = MemA
[address
,4]; address
= address
+ 4;
4306 if registers
<15> == '1' then
4307 LoadWritePC(MemA
[address
,4]);
4309 if wback
&& registers
<n
> == '0' then R
[n
] = R
[n
] + 4*BitCount(registers
);
4310 if wback
&& registers
<n
> == '1' then R
[n
] = bits(32) UNKNOWN
;
4313 bool success
= false;
4315 if (ConditionPassed(opcode
)) {
4317 uint32_t registers
= 0;
4319 const uint32_t addr_byte_size
= GetAddressByteSize();
4322 // n = UInt(Rn); registers = register_list; wback = (W == '1');
4323 n
= Bits32(opcode
, 19, 16);
4324 registers
= Bits32(opcode
, 15, 0);
4325 wback
= BitIsSet(opcode
, 21);
4327 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
4328 if ((n
== 15) || (BitCount(registers
) < 1))
4335 // address = R[n] + 4;
4339 ReadRegisterUnsigned(eRegisterKindDWARF
, dwarf_r0
+ n
, 0, &success
);
4344 addr_t address
= Rn
+ addr_byte_size
;
4346 EmulateInstruction::Context context
;
4347 context
.type
= EmulateInstruction::eContextRegisterPlusOffset
;
4348 std::optional
<RegisterInfo
> dwarf_reg
=
4349 GetRegisterInfo(eRegisterKindDWARF
, dwarf_r0
+ n
);
4350 context
.SetRegisterPlusOffset(*dwarf_reg
, offset
);
4352 for (int i
= 0; i
< 14; ++i
) {
4353 if (BitIsSet(registers
, i
)) {
4354 // R[i] = MemA[address,4]; address = address + 4;
4356 context
.SetRegisterPlusOffset(*dwarf_reg
, offset
+ addr_byte_size
);
4358 MemARead(context
, address
+ offset
, addr_byte_size
, 0, &success
);
4362 if (!WriteRegisterUnsigned(context
, eRegisterKindDWARF
, dwarf_r0
+ i
,
4366 offset
+= addr_byte_size
;
4370 // if registers<15> == '1' then
4371 // LoadWritePC(MemA[address,4]);
4372 if (BitIsSet(registers
, 15)) {
4373 context
.SetRegisterPlusOffset(*dwarf_reg
, offset
);
4375 MemARead(context
, address
+ offset
, addr_byte_size
, 0, &success
);
4378 // In ARMv5T and above, this is an interworking branch.
4379 if (!LoadWritePC(context
, data
))
4383 // if wback && registers<n> == '0' then R[n] = R[n] + 4*BitCount(registers);
4384 if (wback
&& BitIsClear(registers
, n
)) {
4386 offset
= addr_byte_size
* BitCount(registers
);
4387 context
.type
= EmulateInstruction::eContextAdjustBaseRegister
;
4388 context
.SetImmediateSigned(offset
);
4389 addr_t addr
= Rn
+ offset
;
4390 if (!WriteRegisterUnsigned(context
, eRegisterKindDWARF
, dwarf_r0
+ n
,
4395 // if wback && registers<n> == '1' then R[n] = bits(32) UNKNOWN; // Only
4396 // possible for encoding A1
4397 if (wback
&& BitIsSet(registers
, n
))
4398 return WriteBits32Unknown(n
);
4403 // Load Register (immediate) calculates an address from a base register value
4404 // and an immediate offset, loads a word from memory, and writes to a register.
4405 // LDR (immediate, Thumb)
4406 bool EmulateInstructionARM::EmulateLDRRtRnImm(const uint32_t opcode
,
4407 const ARMEncoding encoding
) {
4409 // ARM pseudo code...
4410 if (ConditionPassed())
4412 EncodingSpecificOperations(); NullCheckIfThumbEE(15);
4413 offset_addr
= if add
then (R
[n
] + imm32
) else (R
[n
] - imm32
);
4414 address
= if index then offset_addr
else R
[n
];
4415 data
= MemU
[address
,4];
4416 if wback then R
[n
] = offset_addr
;
4418 if address
<1:0> == '00' then
LoadWritePC(data
); else UNPREDICTABLE
;
4419 elsif
UnalignedSupport() || address
<1:0> = '00' then
4421 else R
[t
] = bits(32) UNKNOWN
; // Can only apply before ARMv7
4425 bool success
= false;
4427 if (ConditionPassed(opcode
)) {
4428 uint32_t Rt
; // the destination register
4429 uint32_t Rn
; // the base register
4430 uint32_t imm32
; // the immediate offset used to form the address
4431 addr_t offset_addr
; // the offset address
4432 addr_t address
; // the calculated address
4433 uint32_t data
; // the literal data value from memory load
4434 bool add
, index
, wback
;
4437 Rt
= Bits32(opcode
, 2, 0);
4438 Rn
= Bits32(opcode
, 5, 3);
4439 imm32
= Bits32(opcode
, 10, 6) << 2; // imm32 = ZeroExtend(imm5:'00', 32);
4440 // index = TRUE; add = TRUE; wback = FALSE
4448 // t = UInt(Rt); n = 13; imm32 = ZeroExtend(imm8:'00', 32);
4449 Rt
= Bits32(opcode
, 10, 8);
4451 imm32
= Bits32(opcode
, 7, 0) << 2;
4453 // index = TRUE; add = TRUE; wback = FALSE;
4461 // if Rn == '1111' then SEE LDR (literal);
4462 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
4463 Rt
= Bits32(opcode
, 15, 12);
4464 Rn
= Bits32(opcode
, 19, 16);
4465 imm32
= Bits32(opcode
, 11, 0);
4467 // index = TRUE; add = TRUE; wback = FALSE;
4472 // if t == 15 && InITBlock() && !LastInITBlock() then UNPREDICTABLE;
4473 if ((Rt
== 15) && InITBlock() && !LastInITBlock())
4479 // if Rn == '1111' then SEE LDR (literal);
4480 // if P == '1' && U == '1' && W == '0' then SEE LDRT;
4481 // if Rn == '1101' && P == '0' && U == '1' && W == '1' && imm8 ==
4482 // '00000100' then SEE POP;
4483 // if P == '0' && W == '0' then UNDEFINED;
4484 if (BitIsClear(opcode
, 10) && BitIsClear(opcode
, 8))
4487 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32);
4488 Rt
= Bits32(opcode
, 15, 12);
4489 Rn
= Bits32(opcode
, 19, 16);
4490 imm32
= Bits32(opcode
, 7, 0);
4492 // index = (P == '1'); add = (U == '1'); wback = (W == '1');
4493 index
= BitIsSet(opcode
, 10);
4494 add
= BitIsSet(opcode
, 9);
4495 wback
= BitIsSet(opcode
, 8);
4497 // if (wback && n == t) || (t == 15 && InITBlock() && !LastInITBlock())
4498 // then UNPREDICTABLE;
4499 if ((wback
&& (Rn
== Rt
)) ||
4500 ((Rt
== 15) && InITBlock() && !LastInITBlock()))
4508 uint32_t base
= ReadCoreReg(Rn
, &success
);
4512 offset_addr
= base
+ imm32
;
4514 offset_addr
= base
- imm32
;
4516 address
= (index
? offset_addr
: base
);
4518 std::optional
<RegisterInfo
> base_reg
=
4519 GetRegisterInfo(eRegisterKindDWARF
, dwarf_r0
+ Rn
);
4521 EmulateInstruction::Context ctx
;
4523 ctx
.type
= eContextAdjustStackPointer
;
4524 ctx
.SetImmediateSigned((int32_t)(offset_addr
- base
));
4525 } else if (Rn
== GetFramePointerRegisterNumber()) {
4526 ctx
.type
= eContextSetFramePointer
;
4527 ctx
.SetRegisterPlusOffset(*base_reg
, (int32_t)(offset_addr
- base
));
4529 ctx
.type
= EmulateInstruction::eContextAdjustBaseRegister
;
4530 ctx
.SetRegisterPlusOffset(*base_reg
, (int32_t)(offset_addr
- base
));
4533 if (!WriteRegisterUnsigned(ctx
, eRegisterKindDWARF
, dwarf_r0
+ Rn
,
4538 // Prepare to write to the Rt register.
4539 EmulateInstruction::Context context
;
4540 context
.type
= EmulateInstruction::eContextRegisterLoad
;
4541 context
.SetRegisterPlusOffset(*base_reg
, (int32_t)(offset_addr
- base
));
4543 // Read memory from the address.
4544 data
= MemURead(context
, address
, 4, 0, &success
);
4549 if (Bits32(address
, 1, 0) == 0) {
4550 if (!LoadWritePC(context
, data
))
4554 } else if (UnalignedSupport() || Bits32(address
, 1, 0) == 0) {
4555 if (!WriteRegisterUnsigned(context
, eRegisterKindDWARF
, dwarf_r0
+ Rt
,
4559 WriteBits32Unknown(Rt
);
4564 // STM (Store Multiple Increment After) stores multiple registers to consecutive
4565 // memory locations using an address
4566 // from a base register. The consecutive memory locations start at this
4567 // address, and the address just above the last of those locations can
4568 // optionally be written back to the base register.
4569 bool EmulateInstructionARM::EmulateSTM(const uint32_t opcode
,
4570 const ARMEncoding encoding
) {
4572 if ConditionPassed() then
4573 EncodingSpecificOperations(); NullCheckIfThumbEE(n
);
4577 if registers
<i
> == '1' then
4578 if i
== n
&& wback
&& i
!= LowestSetBit(registers
) then
4579 MemA
[address
,4] = bits(32) UNKNOWN
; // Only possible for encodings T1 and A1
4581 MemA
[address
,4] = R
[i
];
4582 address
= address
+ 4;
4584 if registers
<15> == '1' then
// Only possible for encoding A1
4585 MemA
[address
,4] = PCStoreValue();
4586 if wback then R
[n
] = R
[n
] + 4*BitCount(registers
);
4589 bool success
= false;
4591 if (ConditionPassed(opcode
)) {
4593 uint32_t registers
= 0;
4595 const uint32_t addr_byte_size
= GetAddressByteSize();
4597 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
4600 // n = UInt(Rn); registers = '00000000':register_list; wback = TRUE;
4601 n
= Bits32(opcode
, 10, 8);
4602 registers
= Bits32(opcode
, 7, 0);
4603 registers
= registers
& 0x00ff; // Make sure the top 8 bits are zeros.
4606 // if BitCount(registers) < 1 then UNPREDICTABLE;
4607 if (BitCount(registers
) < 1)
4613 // n = UInt(Rn); registers = '0':M:'0':register_list; wback = (W == '1');
4614 n
= Bits32(opcode
, 19, 16);
4615 registers
= Bits32(opcode
, 15, 0);
4616 registers
= registers
& 0x5fff; // Make sure bits 15 & 13 are zeros.
4617 wback
= BitIsSet(opcode
, 21);
4619 // if n == 15 || BitCount(registers) < 2 then UNPREDICTABLE;
4620 if ((n
== 15) || (BitCount(registers
) < 2))
4623 // if wback && registers<n> == '1' then UNPREDICTABLE;
4624 if (wback
&& BitIsSet(registers
, n
))
4630 // n = UInt(Rn); registers = register_list; wback = (W == '1');
4631 n
= Bits32(opcode
, 19, 16);
4632 registers
= Bits32(opcode
, 15, 0);
4633 wback
= BitIsSet(opcode
, 21);
4635 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
4636 if ((n
== 15) || (BitCount(registers
) < 1))
4647 const addr_t address
=
4648 ReadRegisterUnsigned(eRegisterKindDWARF
, dwarf_r0
+ n
, 0, &success
);
4652 EmulateInstruction::Context context
;
4653 context
.type
= EmulateInstruction::eContextRegisterStore
;
4654 std::optional
<RegisterInfo
> base_reg
=
4655 GetRegisterInfo(eRegisterKindDWARF
, dwarf_r0
+ n
);
4658 uint32_t lowest_set_bit
= 14;
4659 for (uint32_t i
= 0; i
< 14; ++i
) {
4660 // if registers<i> == '1' then
4661 if (BitIsSet(registers
, i
)) {
4662 if (i
< lowest_set_bit
)
4664 // if i == n && wback && i != LowestSetBit(registers) then
4665 if ((i
== n
) && wback
&& (i
!= lowest_set_bit
))
4666 // MemA[address,4] = bits(32) UNKNOWN; // Only possible for encodings
4668 WriteBits32UnknownToMemory(address
+ offset
);
4670 // MemA[address,4] = R[i];
4671 uint32_t data
= ReadRegisterUnsigned(eRegisterKindDWARF
, dwarf_r0
+ i
,
4676 std::optional
<RegisterInfo
> data_reg
=
4677 GetRegisterInfo(eRegisterKindDWARF
, dwarf_r0
+ i
);
4678 context
.SetRegisterToRegisterPlusOffset(*data_reg
, *base_reg
, offset
);
4679 if (!MemAWrite(context
, address
+ offset
, data
, addr_byte_size
))
4683 // address = address + 4;
4684 offset
+= addr_byte_size
;
4688 // if registers<15> == '1' then // Only possible for encoding A1
4689 // MemA[address,4] = PCStoreValue();
4690 if (BitIsSet(registers
, 15)) {
4691 std::optional
<RegisterInfo
> pc_reg
=
4692 GetRegisterInfo(eRegisterKindDWARF
, dwarf_pc
);
4693 context
.SetRegisterPlusOffset(*pc_reg
, 8);
4694 const uint32_t pc
= ReadCoreReg(PC_REG
, &success
);
4698 if (!MemAWrite(context
, address
+ offset
, pc
, addr_byte_size
))
4702 // if wback then R[n] = R[n] + 4*BitCount(registers);
4704 offset
= addr_byte_size
* BitCount(registers
);
4705 context
.type
= EmulateInstruction::eContextAdjustBaseRegister
;
4706 context
.SetImmediateSigned(offset
);
4707 addr_t data
= address
+ offset
;
4708 if (!WriteRegisterUnsigned(context
, eRegisterKindDWARF
, dwarf_r0
+ n
,
4716 // STMDA (Store Multiple Decrement After) stores multiple registers to
4717 // consecutive memory locations using an address from a base register. The
4718 // consecutive memory locations end at this address, and the address just below
4719 // the lowest of those locations can optionally be written back to the base
4721 bool EmulateInstructionARM::EmulateSTMDA(const uint32_t opcode
,
4722 const ARMEncoding encoding
) {
4724 if ConditionPassed() then
4725 EncodingSpecificOperations();
4726 address
= R
[n
] - 4*BitCount(registers
) + 4;
4729 if registers
<i
> == '1' then
4730 if i
== n
&& wback
&& i
!= LowestSetBit(registers
) then
4731 MemA
[address
,4] = bits(32) UNKNOWN
;
4733 MemA
[address
,4] = R
[i
];
4734 address
= address
+ 4;
4736 if registers
<15> == '1' then
4737 MemA
[address
,4] = PCStoreValue();
4739 if wback then R
[n
] = R
[n
] - 4*BitCount(registers
);
4742 bool success
= false;
4744 if (ConditionPassed(opcode
)) {
4746 uint32_t registers
= 0;
4748 const uint32_t addr_byte_size
= GetAddressByteSize();
4750 // EncodingSpecificOperations();
4753 // n = UInt(Rn); registers = register_list; wback = (W == '1');
4754 n
= Bits32(opcode
, 19, 16);
4755 registers
= Bits32(opcode
, 15, 0);
4756 wback
= BitIsSet(opcode
, 21);
4758 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
4759 if ((n
== 15) || (BitCount(registers
) < 1))
4766 // address = R[n] - 4*BitCount(registers) + 4;
4768 addr_t Rn
= ReadCoreReg(n
, &success
);
4772 addr_t address
= Rn
- (addr_byte_size
* BitCount(registers
)) + 4;
4774 EmulateInstruction::Context context
;
4775 context
.type
= EmulateInstruction::eContextRegisterStore
;
4776 std::optional
<RegisterInfo
> base_reg
=
4777 GetRegisterInfo(eRegisterKindDWARF
, dwarf_r0
+ n
);
4780 uint32_t lowest_bit_set
= 14;
4781 for (uint32_t i
= 0; i
< 14; ++i
) {
4782 // if registers<i> == '1' then
4783 if (BitIsSet(registers
, i
)) {
4784 if (i
< lowest_bit_set
)
4786 // if i == n && wback && i != LowestSetBit(registers) then
4787 if ((i
== n
) && wback
&& (i
!= lowest_bit_set
))
4788 // MemA[address,4] = bits(32) UNKNOWN;
4789 WriteBits32UnknownToMemory(address
+ offset
);
4791 // MemA[address,4] = R[i];
4792 uint32_t data
= ReadRegisterUnsigned(eRegisterKindDWARF
, dwarf_r0
+ i
,
4797 std::optional
<RegisterInfo
> data_reg
=
4798 GetRegisterInfo(eRegisterKindDWARF
, dwarf_r0
+ i
);
4799 context
.SetRegisterToRegisterPlusOffset(*data_reg
, *base_reg
,
4800 Rn
- (address
+ offset
));
4801 if (!MemAWrite(context
, address
+ offset
, data
, addr_byte_size
))
4805 // address = address + 4;
4806 offset
+= addr_byte_size
;
4810 // if registers<15> == '1' then
4811 // MemA[address,4] = PCStoreValue();
4812 if (BitIsSet(registers
, 15)) {
4813 std::optional
<RegisterInfo
> pc_reg
=
4814 GetRegisterInfo(eRegisterKindDWARF
, dwarf_pc
);
4815 context
.SetRegisterPlusOffset(*pc_reg
, 8);
4816 const uint32_t pc
= ReadCoreReg(PC_REG
, &success
);
4820 if (!MemAWrite(context
, address
+ offset
, pc
, addr_byte_size
))
4824 // if wback then R[n] = R[n] - 4*BitCount(registers);
4826 offset
= (addr_byte_size
* BitCount(registers
)) * -1;
4827 context
.type
= EmulateInstruction::eContextAdjustBaseRegister
;
4828 context
.SetImmediateSigned(offset
);
4829 addr_t data
= Rn
+ offset
;
4830 if (!WriteRegisterUnsigned(context
, eRegisterKindDWARF
, dwarf_r0
+ n
,
4838 // STMDB (Store Multiple Decrement Before) stores multiple registers to
4839 // consecutive memory locations using an address from a base register. The
4840 // consecutive memory locations end just below this address, and the address of
4841 // the first of those locations can optionally be written back to the base
4843 bool EmulateInstructionARM::EmulateSTMDB(const uint32_t opcode
,
4844 const ARMEncoding encoding
) {
4846 if ConditionPassed() then
4847 EncodingSpecificOperations(); NullCheckIfThumbEE(n
);
4848 address
= R
[n
] - 4*BitCount(registers
);
4851 if registers
<i
> == '1' then
4852 if i
== n
&& wback
&& i
!= LowestSetBit(registers
) then
4853 MemA
[address
,4] = bits(32) UNKNOWN
; // Only possible for encoding A1
4855 MemA
[address
,4] = R
[i
];
4856 address
= address
+ 4;
4858 if registers
<15> == '1' then
// Only possible for encoding A1
4859 MemA
[address
,4] = PCStoreValue();
4861 if wback then R
[n
] = R
[n
] - 4*BitCount(registers
);
4864 bool success
= false;
4866 if (ConditionPassed(opcode
)) {
4868 uint32_t registers
= 0;
4870 const uint32_t addr_byte_size
= GetAddressByteSize();
4872 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
4875 // if W == '1' && Rn == '1101' then SEE PUSH;
4876 if ((BitIsSet(opcode
, 21)) && (Bits32(opcode
, 19, 16) == 13)) {
4879 // n = UInt(Rn); registers = '0':M:'0':register_list; wback = (W == '1');
4880 n
= Bits32(opcode
, 19, 16);
4881 registers
= Bits32(opcode
, 15, 0);
4882 registers
= registers
& 0x5fff; // Make sure bits 15 & 13 are zeros.
4883 wback
= BitIsSet(opcode
, 21);
4884 // if n == 15 || BitCount(registers) < 2 then UNPREDICTABLE;
4885 if ((n
== 15) || BitCount(registers
) < 2)
4887 // if wback && registers<n> == '1' then UNPREDICTABLE;
4888 if (wback
&& BitIsSet(registers
, n
))
4893 // if W == '1' && Rn == '1101' && BitCount(register_list) >= 2 then SEE
4895 if (BitIsSet(opcode
, 21) && (Bits32(opcode
, 19, 16) == 13) &&
4896 BitCount(Bits32(opcode
, 15, 0)) >= 2) {
4899 // n = UInt(Rn); registers = register_list; wback = (W == '1');
4900 n
= Bits32(opcode
, 19, 16);
4901 registers
= Bits32(opcode
, 15, 0);
4902 wback
= BitIsSet(opcode
, 21);
4903 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
4904 if ((n
== 15) || BitCount(registers
) < 1)
4912 // address = R[n] - 4*BitCount(registers);
4916 ReadRegisterUnsigned(eRegisterKindDWARF
, dwarf_r0
+ n
, 0, &success
);
4920 addr_t address
= Rn
- (addr_byte_size
* BitCount(registers
));
4922 EmulateInstruction::Context context
;
4923 context
.type
= EmulateInstruction::eContextRegisterStore
;
4924 std::optional
<RegisterInfo
> base_reg
=
4925 GetRegisterInfo(eRegisterKindDWARF
, dwarf_r0
+ n
);
4928 uint32_t lowest_set_bit
= 14;
4929 for (uint32_t i
= 0; i
< 14; ++i
) {
4930 // if registers<i> == '1' then
4931 if (BitIsSet(registers
, i
)) {
4932 if (i
< lowest_set_bit
)
4934 // if i == n && wback && i != LowestSetBit(registers) then
4935 if ((i
== n
) && wback
&& (i
!= lowest_set_bit
))
4936 // MemA[address,4] = bits(32) UNKNOWN; // Only possible for encoding
4938 WriteBits32UnknownToMemory(address
+ offset
);
4940 // MemA[address,4] = R[i];
4941 uint32_t data
= ReadRegisterUnsigned(eRegisterKindDWARF
, dwarf_r0
+ i
,
4946 std::optional
<RegisterInfo
> data_reg
=
4947 GetRegisterInfo(eRegisterKindDWARF
, dwarf_r0
+ i
);
4948 context
.SetRegisterToRegisterPlusOffset(*data_reg
, *base_reg
,
4949 Rn
- (address
+ offset
));
4950 if (!MemAWrite(context
, address
+ offset
, data
, addr_byte_size
))
4954 // address = address + 4;
4955 offset
+= addr_byte_size
;
4959 // if registers<15> == '1' then // Only possible for encoding A1
4960 // MemA[address,4] = PCStoreValue();
4961 if (BitIsSet(registers
, 15)) {
4962 std::optional
<RegisterInfo
> pc_reg
=
4963 GetRegisterInfo(eRegisterKindDWARF
, dwarf_pc
);
4964 context
.SetRegisterPlusOffset(*pc_reg
, 8);
4965 const uint32_t pc
= ReadCoreReg(PC_REG
, &success
);
4969 if (!MemAWrite(context
, address
+ offset
, pc
, addr_byte_size
))
4973 // if wback then R[n] = R[n] - 4*BitCount(registers);
4975 offset
= (addr_byte_size
* BitCount(registers
)) * -1;
4976 context
.type
= EmulateInstruction::eContextAdjustBaseRegister
;
4977 context
.SetImmediateSigned(offset
);
4978 addr_t data
= Rn
+ offset
;
4979 if (!WriteRegisterUnsigned(context
, eRegisterKindDWARF
, dwarf_r0
+ n
,
4987 // STMIB (Store Multiple Increment Before) stores multiple registers to
4988 // consecutive memory locations using an address from a base register. The
4989 // consecutive memory locations start just above this address, and the address
4990 // of the last of those locations can optionally be written back to the base
4992 bool EmulateInstructionARM::EmulateSTMIB(const uint32_t opcode
,
4993 const ARMEncoding encoding
) {
4995 if ConditionPassed() then
4996 EncodingSpecificOperations();
5000 if registers
<i
> == '1' then
5001 if i
== n
&& wback
&& i
!= LowestSetBit(registers
) then
5002 MemA
[address
,4] = bits(32) UNKNOWN
;
5004 MemA
[address
,4] = R
[i
];
5005 address
= address
+ 4;
5007 if registers
<15> == '1' then
5008 MemA
[address
,4] = PCStoreValue();
5010 if wback then R
[n
] = R
[n
] + 4*BitCount(registers
);
5013 bool success
= false;
5015 if (ConditionPassed(opcode
)) {
5017 uint32_t registers
= 0;
5019 const uint32_t addr_byte_size
= GetAddressByteSize();
5021 // EncodingSpecificOperations();
5024 // n = UInt(Rn); registers = register_list; wback = (W == '1');
5025 n
= Bits32(opcode
, 19, 16);
5026 registers
= Bits32(opcode
, 15, 0);
5027 wback
= BitIsSet(opcode
, 21);
5029 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
5030 if ((n
== 15) && (BitCount(registers
) < 1))
5036 // address = R[n] + 4;
5039 addr_t Rn
= ReadCoreReg(n
, &success
);
5043 addr_t address
= Rn
+ addr_byte_size
;
5045 EmulateInstruction::Context context
;
5046 context
.type
= EmulateInstruction::eContextRegisterStore
;
5047 std::optional
<RegisterInfo
> base_reg
=
5048 GetRegisterInfo(eRegisterKindDWARF
, dwarf_r0
+ n
);
5050 uint32_t lowest_set_bit
= 14;
5052 for (uint32_t i
= 0; i
< 14; ++i
) {
5053 // if registers<i> == '1' then
5054 if (BitIsSet(registers
, i
)) {
5055 if (i
< lowest_set_bit
)
5057 // if i == n && wback && i != LowestSetBit(registers) then
5058 if ((i
== n
) && wback
&& (i
!= lowest_set_bit
))
5059 // MemA[address,4] = bits(32) UNKNOWN;
5060 WriteBits32UnknownToMemory(address
+ offset
);
5063 // MemA[address,4] = R[i];
5064 uint32_t data
= ReadRegisterUnsigned(eRegisterKindDWARF
, dwarf_r0
+ i
,
5069 std::optional
<RegisterInfo
> data_reg
=
5070 GetRegisterInfo(eRegisterKindDWARF
, dwarf_r0
+ i
);
5071 context
.SetRegisterToRegisterPlusOffset(*data_reg
, *base_reg
,
5072 offset
+ addr_byte_size
);
5073 if (!MemAWrite(context
, address
+ offset
, data
, addr_byte_size
))
5077 // address = address + 4;
5078 offset
+= addr_byte_size
;
5082 // if registers<15> == '1' then
5083 // MemA[address,4] = PCStoreValue();
5084 if (BitIsSet(registers
, 15)) {
5085 std::optional
<RegisterInfo
> pc_reg
=
5086 GetRegisterInfo(eRegisterKindDWARF
, dwarf_pc
);
5087 context
.SetRegisterPlusOffset(*pc_reg
, 8);
5088 const uint32_t pc
= ReadCoreReg(PC_REG
, &success
);
5092 if (!MemAWrite(context
, address
+ offset
, pc
, addr_byte_size
))
5096 // if wback then R[n] = R[n] + 4*BitCount(registers);
5098 offset
= addr_byte_size
* BitCount(registers
);
5099 context
.type
= EmulateInstruction::eContextAdjustBaseRegister
;
5100 context
.SetImmediateSigned(offset
);
5101 addr_t data
= Rn
+ offset
;
5102 if (!WriteRegisterUnsigned(context
, eRegisterKindDWARF
, dwarf_r0
+ n
,
5110 // STR (store immediate) calculates an address from a base register value and an
5111 // immediate offset, and stores a word
5112 // from a register to memory. It can use offset, post-indexed, or pre-indexed
5114 bool EmulateInstructionARM::EmulateSTRThumb(const uint32_t opcode
,
5115 const ARMEncoding encoding
) {
5117 if ConditionPassed() then
5118 EncodingSpecificOperations(); NullCheckIfThumbEE(n
);
5119 offset_addr
= if add
then (R
[n
] + imm32
) else (R
[n
] - imm32
);
5120 address
= if index then offset_addr
else R
[n
];
5121 if UnalignedSupport() || address
<1:0> == '00' then
5122 MemU
[address
,4] = R
[t
];
5123 else // Can only occur before ARMv7
5124 MemU
[address
,4] = bits(32) UNKNOWN
;
5125 if wback then R
[n
] = offset_addr
;
5128 bool success
= false;
5130 if (ConditionPassed(opcode
)) {
5131 const uint32_t addr_byte_size
= GetAddressByteSize();
5139 // EncodingSpecificOperations (); NullCheckIfThumbEE(n);
5142 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm5:'00', 32);
5143 t
= Bits32(opcode
, 2, 0);
5144 n
= Bits32(opcode
, 5, 3);
5145 imm32
= Bits32(opcode
, 10, 6) << 2;
5147 // index = TRUE; add = TRUE; wback = FALSE;
5154 // t = UInt(Rt); n = 13; imm32 = ZeroExtend(imm8:'00', 32);
5155 t
= Bits32(opcode
, 10, 8);
5157 imm32
= Bits32(opcode
, 7, 0) << 2;
5159 // index = TRUE; add = TRUE; wback = FALSE;
5166 // if Rn == '1111' then UNDEFINED;
5167 if (Bits32(opcode
, 19, 16) == 15)
5170 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
5171 t
= Bits32(opcode
, 15, 12);
5172 n
= Bits32(opcode
, 19, 16);
5173 imm32
= Bits32(opcode
, 11, 0);
5175 // index = TRUE; add = TRUE; wback = FALSE;
5180 // if t == 15 then UNPREDICTABLE;
5186 // if P == '1' && U == '1' && W == '0' then SEE STRT;
5187 // if Rn == '1101' && P == '1' && U == '0' && W == '1' && imm8 ==
5188 // '00000100' then SEE PUSH;
5189 // if Rn == '1111' || (P == '0' && W == '0') then UNDEFINED;
5190 if ((Bits32(opcode
, 19, 16) == 15) ||
5191 (BitIsClear(opcode
, 10) && BitIsClear(opcode
, 8)))
5194 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32);
5195 t
= Bits32(opcode
, 15, 12);
5196 n
= Bits32(opcode
, 19, 16);
5197 imm32
= Bits32(opcode
, 7, 0);
5199 // index = (P == '1'); add = (U == '1'); wback = (W == '1');
5200 index
= BitIsSet(opcode
, 10);
5201 add
= BitIsSet(opcode
, 9);
5202 wback
= BitIsSet(opcode
, 8);
5204 // if t == 15 || (wback && n == t) then UNPREDICTABLE;
5205 if ((t
== 15) || (wback
&& (n
== t
)))
5216 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
5217 uint32_t base_address
= ReadCoreReg(n
, &success
);
5222 offset_addr
= base_address
+ imm32
;
5224 offset_addr
= base_address
- imm32
;
5226 // address = if index then offset_addr else R[n];
5228 address
= offset_addr
;
5230 address
= base_address
;
5232 EmulateInstruction::Context context
;
5234 context
.type
= eContextPushRegisterOnStack
;
5236 context
.type
= eContextRegisterStore
;
5238 std::optional
<RegisterInfo
> base_reg
=
5239 GetRegisterInfo(eRegisterKindDWARF
, dwarf_r0
+ n
);
5241 // if UnalignedSupport() || address<1:0> == '00' then
5242 if (UnalignedSupport() ||
5243 (BitIsClear(address
, 1) && BitIsClear(address
, 0))) {
5244 // MemU[address,4] = R[t];
5246 ReadRegisterUnsigned(eRegisterKindDWARF
, dwarf_r0
+ t
, 0, &success
);
5250 std::optional
<RegisterInfo
> data_reg
=
5251 GetRegisterInfo(eRegisterKindDWARF
, dwarf_r0
+ t
);
5252 int32_t offset
= address
- base_address
;
5253 context
.SetRegisterToRegisterPlusOffset(*data_reg
, *base_reg
, offset
);
5254 if (!MemUWrite(context
, address
, data
, addr_byte_size
))
5257 // MemU[address,4] = bits(32) UNKNOWN;
5258 WriteBits32UnknownToMemory(address
);
5261 // if wback then R[n] = offset_addr;
5264 context
.type
= eContextAdjustStackPointer
;
5266 context
.type
= eContextAdjustBaseRegister
;
5267 context
.SetAddress(offset_addr
);
5269 if (!WriteRegisterUnsigned(context
, eRegisterKindDWARF
, dwarf_r0
+ n
,
5277 // STR (Store Register) calculates an address from a base register value and an
5278 // offset register value, stores a
5279 // word from a register to memory. The offset register value can optionally
5281 bool EmulateInstructionARM::EmulateSTRRegister(const uint32_t opcode
,
5282 const ARMEncoding encoding
) {
5284 if ConditionPassed() then
5285 EncodingSpecificOperations(); NullCheckIfThumbEE(n
);
5286 offset
= Shift(R
[m
], shift_t
, shift_n
, APSR
.C
);
5287 offset_addr
= if add
then (R
[n
] + offset
) else (R
[n
] - offset
);
5288 address
= if index then offset_addr
else R
[n
];
5289 if t
== 15 then
// Only possible for encoding A1
5290 data
= PCStoreValue();
5293 if UnalignedSupport() || address
<1:0> == '00' || CurrentInstrSet() == InstrSet_ARM then
5294 MemU
[address
,4] = data
;
5295 else // Can only occur before ARMv7
5296 MemU
[address
,4] = bits(32) UNKNOWN
;
5297 if wback then R
[n
] = offset_addr
;
5300 bool success
= false;
5302 if (ConditionPassed(opcode
)) {
5303 const uint32_t addr_byte_size
= GetAddressByteSize();
5308 ARM_ShifterType shift_t
;
5314 // EncodingSpecificOperations (); NullCheckIfThumbEE(n);
5317 // if CurrentInstrSet() == InstrSet_ThumbEE then SEE "Modified operation
5319 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
5320 t
= Bits32(opcode
, 2, 0);
5321 n
= Bits32(opcode
, 5, 3);
5322 m
= Bits32(opcode
, 8, 6);
5324 // index = TRUE; add = TRUE; wback = FALSE;
5329 // (shift_t, shift_n) = (SRType_LSL, 0);
5330 shift_t
= SRType_LSL
;
5335 // if Rn == '1111' then UNDEFINED;
5336 if (Bits32(opcode
, 19, 16) == 15)
5339 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
5340 t
= Bits32(opcode
, 15, 12);
5341 n
= Bits32(opcode
, 19, 16);
5342 m
= Bits32(opcode
, 3, 0);
5344 // index = TRUE; add = TRUE; wback = FALSE;
5349 // (shift_t, shift_n) = (SRType_LSL, UInt(imm2));
5350 shift_t
= SRType_LSL
;
5351 shift_n
= Bits32(opcode
, 5, 4);
5353 // if t == 15 || BadReg(m) then UNPREDICTABLE;
5354 if ((t
== 15) || (BadReg(m
)))
5359 // if P == '0' && W == '1' then SEE STRT;
5360 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
5361 t
= Bits32(opcode
, 15, 12);
5362 n
= Bits32(opcode
, 19, 16);
5363 m
= Bits32(opcode
, 3, 0);
5365 // index = (P == '1'); add = (U == '1'); wback = (P == '0') ||
5367 index
= BitIsSet(opcode
, 24);
5368 add
= BitIsSet(opcode
, 23);
5369 wback
= (BitIsClear(opcode
, 24) || BitIsSet(opcode
, 21));
5371 // (shift_t, shift_n) = DecodeImmShift(type, imm5);
5372 uint32_t typ
= Bits32(opcode
, 6, 5);
5373 uint32_t imm5
= Bits32(opcode
, 11, 7);
5374 shift_n
= DecodeImmShift(typ
, imm5
, shift_t
);
5376 // if m == 15 then UNPREDICTABLE;
5380 // if wback && (n == 15 || n == t) then UNPREDICTABLE;
5381 if (wback
&& ((n
== 15) || (n
== t
)))
5394 addr_t base_address
=
5395 ReadRegisterUnsigned(eRegisterKindDWARF
, dwarf_r0
+ n
, 0, &success
);
5400 ReadRegisterUnsigned(eRegisterKindDWARF
, dwarf_r0
+ m
, 0, &success
);
5404 // offset = Shift(R[m], shift_t, shift_n, APSR.C);
5405 offset
= Shift(Rm_data
, shift_t
, shift_n
, APSR_C
, &success
);
5409 // offset_addr = if add then (R[n] + offset) else (R[n] - offset);
5411 offset_addr
= base_address
+ offset
;
5413 offset_addr
= base_address
- offset
;
5415 // address = if index then offset_addr else R[n];
5417 address
= offset_addr
;
5419 address
= base_address
;
5422 // if t == 15 then // Only possible for encoding A1
5424 // data = PCStoreValue();
5425 data
= ReadCoreReg(PC_REG
, &success
);
5429 ReadRegisterUnsigned(eRegisterKindDWARF
, dwarf_r0
+ t
, 0, &success
);
5434 EmulateInstruction::Context context
;
5435 context
.type
= eContextRegisterStore
;
5437 // if UnalignedSupport() || address<1:0> == '00' || CurrentInstrSet() ==
5438 // InstrSet_ARM then
5439 if (UnalignedSupport() ||
5440 (BitIsClear(address
, 1) && BitIsClear(address
, 0)) ||
5441 CurrentInstrSet() == eModeARM
) {
5442 // MemU[address,4] = data;
5444 std::optional
<RegisterInfo
> base_reg
=
5445 GetRegisterInfo(eRegisterKindDWARF
, dwarf_r0
+ n
);
5446 std::optional
<RegisterInfo
> data_reg
=
5447 GetRegisterInfo(eRegisterKindDWARF
, dwarf_r0
+ t
);
5449 context
.SetRegisterToRegisterPlusOffset(*data_reg
, *base_reg
,
5450 address
- base_address
);
5451 if (!MemUWrite(context
, address
, data
, addr_byte_size
))
5455 // MemU[address,4] = bits(32) UNKNOWN;
5456 WriteBits32UnknownToMemory(address
);
5458 // if wback then R[n] = offset_addr;
5460 context
.type
= eContextRegisterLoad
;
5461 context
.SetAddress(offset_addr
);
5462 if (!WriteRegisterUnsigned(context
, eRegisterKindDWARF
, dwarf_r0
+ n
,
5470 bool EmulateInstructionARM::EmulateSTRBThumb(const uint32_t opcode
,
5471 const ARMEncoding encoding
) {
5473 if ConditionPassed() then
5474 EncodingSpecificOperations(); NullCheckIfThumbEE(n
);
5475 offset_addr
= if add
then (R
[n
] + imm32
) else (R
[n
] - imm32
);
5476 address
= if index then offset_addr
else R
[n
];
5477 MemU
[address
,1] = R
[t
]<7:0>;
5478 if wback then R
[n
] = offset_addr
;
5481 bool success
= false;
5483 if (ConditionPassed(opcode
)) {
5490 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
5493 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm5, 32);
5494 t
= Bits32(opcode
, 2, 0);
5495 n
= Bits32(opcode
, 5, 3);
5496 imm32
= Bits32(opcode
, 10, 6);
5498 // index = TRUE; add = TRUE; wback = FALSE;
5505 // if Rn == '1111' then UNDEFINED;
5506 if (Bits32(opcode
, 19, 16) == 15)
5509 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
5510 t
= Bits32(opcode
, 15, 12);
5511 n
= Bits32(opcode
, 19, 16);
5512 imm32
= Bits32(opcode
, 11, 0);
5514 // index = TRUE; add = TRUE; wback = FALSE;
5519 // if BadReg(t) then UNPREDICTABLE;
5525 // if P == '1' && U == '1' && W == '0' then SEE STRBT;
5526 // if Rn == '1111' || (P == '0' && W == '0') then UNDEFINED;
5527 if (Bits32(opcode
, 19, 16) == 15)
5530 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32);
5531 t
= Bits32(opcode
, 15, 12);
5532 n
= Bits32(opcode
, 19, 16);
5533 imm32
= Bits32(opcode
, 7, 0);
5535 // index = (P == '1'); add = (U == '1'); wback = (W == '1');
5536 index
= BitIsSet(opcode
, 10);
5537 add
= BitIsSet(opcode
, 9);
5538 wback
= BitIsSet(opcode
, 8);
5540 // if BadReg(t) || (wback && n == t) then UNPREDICTABLE
5541 if ((BadReg(t
)) || (wback
&& (n
== t
)))
5551 addr_t base_address
=
5552 ReadRegisterUnsigned(eRegisterKindDWARF
, dwarf_r0
+ n
, 0, &success
);
5556 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
5558 offset_addr
= base_address
+ imm32
;
5560 offset_addr
= base_address
- imm32
;
5562 // address = if index then offset_addr else R[n];
5564 address
= offset_addr
;
5566 address
= base_address
;
5568 // MemU[address,1] = R[t]<7:0>
5569 std::optional
<RegisterInfo
> base_reg
=
5570 GetRegisterInfo(eRegisterKindDWARF
, dwarf_r0
+ n
);
5571 std::optional
<RegisterInfo
> data_reg
=
5572 GetRegisterInfo(eRegisterKindDWARF
, dwarf_r0
+ t
);
5574 EmulateInstruction::Context context
;
5575 context
.type
= eContextRegisterStore
;
5576 context
.SetRegisterToRegisterPlusOffset(*data_reg
, *base_reg
,
5577 address
- base_address
);
5580 ReadRegisterUnsigned(eRegisterKindDWARF
, dwarf_r0
+ t
, 0, &success
);
5584 data
= Bits32(data
, 7, 0);
5586 if (!MemUWrite(context
, address
, data
, 1))
5589 // if wback then R[n] = offset_addr;
5591 context
.type
= eContextRegisterLoad
;
5592 context
.SetAddress(offset_addr
);
5593 if (!WriteRegisterUnsigned(context
, eRegisterKindDWARF
, dwarf_r0
+ n
,
5602 // STRH (register) calculates an address from a base register value and an
5603 // offset register value, and stores a
5604 // halfword from a register to memory. The offset register value can be
5605 // shifted left by 0, 1, 2, or 3 bits.
5606 bool EmulateInstructionARM::EmulateSTRHRegister(const uint32_t opcode
,
5607 const ARMEncoding encoding
) {
5609 if ConditionPassed() then
5610 EncodingSpecificOperations(); NullCheckIfThumbEE(n
);
5611 offset
= Shift(R
[m
], shift_t
, shift_n
, APSR
.C
);
5612 offset_addr
= if add
then (R
[n
] + offset
) else (R
[n
] - offset
);
5613 address
= if index then offset_addr
else R
[n
];
5614 if UnalignedSupport() || address
<0> == '0' then
5615 MemU
[address
,2] = R
[t
]<15:0>;
5616 else // Can only occur before ARMv7
5617 MemU
[address
,2] = bits(16) UNKNOWN
;
5618 if wback then R
[n
] = offset_addr
;
5621 bool success
= false;
5623 if (ConditionPassed(opcode
)) {
5630 ARM_ShifterType shift_t
;
5633 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
5636 // if CurrentInstrSet() == InstrSet_ThumbEE then SEE "Modified operation
5638 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
5639 t
= Bits32(opcode
, 2, 0);
5640 n
= Bits32(opcode
, 5, 3);
5641 m
= Bits32(opcode
, 8, 6);
5643 // index = TRUE; add = TRUE; wback = FALSE;
5648 // (shift_t, shift_n) = (SRType_LSL, 0);
5649 shift_t
= SRType_LSL
;
5655 // if Rn == '1111' then UNDEFINED;
5656 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
5657 t
= Bits32(opcode
, 15, 12);
5658 n
= Bits32(opcode
, 19, 16);
5659 m
= Bits32(opcode
, 3, 0);
5663 // index = TRUE; add = TRUE; wback = FALSE;
5668 // (shift_t, shift_n) = (SRType_LSL, UInt(imm2));
5669 shift_t
= SRType_LSL
;
5670 shift_n
= Bits32(opcode
, 5, 4);
5672 // if BadReg(t) || BadReg(m) then UNPREDICTABLE;
5673 if (BadReg(t
) || BadReg(m
))
5679 // if P == '0' && W == '1' then SEE STRHT;
5680 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
5681 t
= Bits32(opcode
, 15, 12);
5682 n
= Bits32(opcode
, 19, 16);
5683 m
= Bits32(opcode
, 3, 0);
5685 // index = (P == '1'); add = (U == '1'); wback = (P == '0') ||
5687 index
= BitIsSet(opcode
, 24);
5688 add
= BitIsSet(opcode
, 23);
5689 wback
= (BitIsClear(opcode
, 24) || BitIsSet(opcode
, 21));
5691 // (shift_t, shift_n) = (SRType_LSL, 0);
5692 shift_t
= SRType_LSL
;
5695 // if t == 15 || m == 15 then UNPREDICTABLE;
5696 if ((t
== 15) || (m
== 15))
5699 // if wback && (n == 15 || n == t) then UNPREDICTABLE;
5700 if (wback
&& ((n
== 15) || (n
== t
)))
5709 uint32_t Rm
= ReadCoreReg(m
, &success
);
5713 uint32_t Rn
= ReadCoreReg(n
, &success
);
5717 // offset = Shift(R[m], shift_t, shift_n, APSR.C);
5718 uint32_t offset
= Shift(Rm
, shift_t
, shift_n
, APSR_C
, &success
);
5722 // offset_addr = if add then (R[n] + offset) else (R[n] - offset);
5725 offset_addr
= Rn
+ offset
;
5727 offset_addr
= Rn
- offset
;
5729 // address = if index then offset_addr else R[n];
5732 address
= offset_addr
;
5736 EmulateInstruction::Context context
;
5737 context
.type
= eContextRegisterStore
;
5739 // if UnalignedSupport() || address<0> == '0' then
5740 if (UnalignedSupport() || BitIsClear(address
, 0)) {
5741 // MemU[address,2] = R[t]<15:0>;
5742 uint32_t Rt
= ReadCoreReg(t
, &success
);
5746 EmulateInstruction::Context context
;
5747 context
.type
= eContextRegisterStore
;
5748 std::optional
<RegisterInfo
> base_reg
=
5749 GetRegisterInfo(eRegisterKindDWARF
, dwarf_r0
+ n
);
5750 std::optional
<RegisterInfo
> offset_reg
=
5751 GetRegisterInfo(eRegisterKindDWARF
, dwarf_r0
+ m
);
5752 std::optional
<RegisterInfo
> data_reg
=
5753 GetRegisterInfo(eRegisterKindDWARF
, dwarf_r0
+ t
);
5754 context
.SetRegisterToRegisterPlusIndirectOffset(*base_reg
, *offset_reg
,
5757 if (!MemUWrite(context
, address
, Bits32(Rt
, 15, 0), 2))
5759 } else // Can only occur before ARMv7
5761 // MemU[address,2] = bits(16) UNKNOWN;
5764 // if wback then R[n] = offset_addr;
5766 context
.type
= eContextAdjustBaseRegister
;
5767 context
.SetAddress(offset_addr
);
5768 if (!WriteRegisterUnsigned(context
, eRegisterKindDWARF
, dwarf_r0
+ n
,
5777 // Add with Carry (immediate) adds an immediate value and the carry flag value
5778 // to a register value, and writes the result to the destination register. It
5779 // can optionally update the condition flags based on the result.
5780 bool EmulateInstructionARM::EmulateADCImm(const uint32_t opcode
,
5781 const ARMEncoding encoding
) {
5783 // ARM pseudo code...
5784 if ConditionPassed() then
5785 EncodingSpecificOperations();
5786 (result
, carry
, overflow
) = AddWithCarry(R
[n
], imm32
, APSR
.C
);
5787 if d
== 15 then
// Can only occur for ARM encoding
5788 ALUWritePC(result
); // setflags is always FALSE here
5792 APSR
.N
= result
<31>;
5793 APSR
.Z
= IsZeroBit(result
);
5798 bool success
= false;
5800 if (ConditionPassed(opcode
)) {
5803 imm32
; // the immediate value to be added to the value obtained from Rn
5807 Rd
= Bits32(opcode
, 11, 8);
5808 Rn
= Bits32(opcode
, 19, 16);
5809 setflags
= BitIsSet(opcode
, 20);
5810 imm32
= ThumbExpandImm(opcode
); // imm32 = ThumbExpandImm(i:imm3:imm8)
5811 if (BadReg(Rd
) || BadReg(Rn
))
5815 Rd
= Bits32(opcode
, 15, 12);
5816 Rn
= Bits32(opcode
, 19, 16);
5817 setflags
= BitIsSet(opcode
, 20);
5818 imm32
= ARMExpandImm(opcode
); // imm32 = ARMExpandImm(imm12)
5820 if (Rd
== 15 && setflags
)
5821 return EmulateSUBSPcLrEtc(opcode
, encoding
);
5827 // Read the first operand.
5828 int32_t val1
= ReadCoreReg(Rn
, &success
);
5832 AddWithCarryResult res
= AddWithCarry(val1
, imm32
, APSR_C
);
5834 EmulateInstruction::Context context
;
5835 context
.type
= EmulateInstruction::eContextImmediate
;
5836 context
.SetNoArgs();
5838 if (!WriteCoreRegOptionalFlags(context
, res
.result
, Rd
, setflags
,
5839 res
.carry_out
, res
.overflow
))
5845 // Add with Carry (register) adds a register value, the carry flag value, and
5846 // an optionally-shifted register value, and writes the result to the
5847 // destination register. It can optionally update the condition flags based on
5849 bool EmulateInstructionARM::EmulateADCReg(const uint32_t opcode
,
5850 const ARMEncoding encoding
) {
5852 // ARM pseudo code...
5853 if ConditionPassed() then
5854 EncodingSpecificOperations();
5855 shifted
= Shift(R
[m
], shift_t
, shift_n
, APSR
.C
);
5856 (result
, carry
, overflow
) = AddWithCarry(R
[n
], shifted
, APSR
.C
);
5857 if d
== 15 then
// Can only occur for ARM encoding
5858 ALUWritePC(result
); // setflags is always FALSE here
5862 APSR
.N
= result
<31>;
5863 APSR
.Z
= IsZeroBit(result
);
5868 bool success
= false;
5870 if (ConditionPassed(opcode
)) {
5871 uint32_t Rd
, Rn
, Rm
;
5872 ARM_ShifterType shift_t
;
5873 uint32_t shift_n
; // the shift applied to the value read from Rm
5877 Rd
= Rn
= Bits32(opcode
, 2, 0);
5878 Rm
= Bits32(opcode
, 5, 3);
5879 setflags
= !InITBlock();
5880 shift_t
= SRType_LSL
;
5884 Rd
= Bits32(opcode
, 11, 8);
5885 Rn
= Bits32(opcode
, 19, 16);
5886 Rm
= Bits32(opcode
, 3, 0);
5887 setflags
= BitIsSet(opcode
, 20);
5888 shift_n
= DecodeImmShiftThumb(opcode
, shift_t
);
5889 if (BadReg(Rd
) || BadReg(Rn
) || BadReg(Rm
))
5893 Rd
= Bits32(opcode
, 15, 12);
5894 Rn
= Bits32(opcode
, 19, 16);
5895 Rm
= Bits32(opcode
, 3, 0);
5896 setflags
= BitIsSet(opcode
, 20);
5897 shift_n
= DecodeImmShiftARM(opcode
, shift_t
);
5899 if (Rd
== 15 && setflags
)
5900 return EmulateSUBSPcLrEtc(opcode
, encoding
);
5906 // Read the first operand.
5907 int32_t val1
= ReadCoreReg(Rn
, &success
);
5911 // Read the second operand.
5912 int32_t val2
= ReadCoreReg(Rm
, &success
);
5916 uint32_t shifted
= Shift(val2
, shift_t
, shift_n
, APSR_C
, &success
);
5919 AddWithCarryResult res
= AddWithCarry(val1
, shifted
, APSR_C
);
5921 EmulateInstruction::Context context
;
5922 context
.type
= EmulateInstruction::eContextImmediate
;
5923 context
.SetNoArgs();
5925 if (!WriteCoreRegOptionalFlags(context
, res
.result
, Rd
, setflags
,
5926 res
.carry_out
, res
.overflow
))
5932 // This instruction adds an immediate value to the PC value to form a PC-
5933 // relative address, and writes the result to the destination register.
5934 bool EmulateInstructionARM::EmulateADR(const uint32_t opcode
,
5935 const ARMEncoding encoding
) {
5937 // ARM pseudo code...
5938 if ConditionPassed() then
5939 EncodingSpecificOperations();
5940 result
= if add
then (Align(PC
,4) + imm32
) else (Align(PC
,4) - imm32
);
5941 if d
== 15 then
// Can only occur for ARM encodings
5947 bool success
= false;
5949 if (ConditionPassed(opcode
)) {
5951 uint32_t imm32
; // the immediate value to be added/subtracted to/from the PC
5955 Rd
= Bits32(opcode
, 10, 8);
5956 imm32
= ThumbImm8Scaled(opcode
); // imm32 = ZeroExtend(imm8:'00', 32)
5961 Rd
= Bits32(opcode
, 11, 8);
5962 imm32
= ThumbImm12(opcode
); // imm32 = ZeroExtend(i:imm3:imm8, 32)
5963 add
= (Bits32(opcode
, 24, 21) == 0); // 0b0000 => ADD; 0b0101 => SUB
5969 Rd
= Bits32(opcode
, 15, 12);
5970 imm32
= ARMExpandImm(opcode
); // imm32 = ARMExpandImm(imm12)
5971 add
= (Bits32(opcode
, 24, 21) == 0x4); // 0b0100 => ADD; 0b0010 => SUB
5977 // Read the PC value.
5978 uint32_t pc
= ReadCoreReg(PC_REG
, &success
);
5982 uint32_t result
= (add
? Align(pc
, 4) + imm32
: Align(pc
, 4) - imm32
);
5984 EmulateInstruction::Context context
;
5985 context
.type
= EmulateInstruction::eContextImmediate
;
5986 context
.SetNoArgs();
5988 if (!WriteCoreReg(context
, result
, Rd
))
5994 // This instruction performs a bitwise AND of a register value and an immediate
5995 // value, and writes the result to the destination register. It can optionally
5996 // update the condition flags based on the result.
5997 bool EmulateInstructionARM::EmulateANDImm(const uint32_t opcode
,
5998 const ARMEncoding encoding
) {
6000 // ARM pseudo code...
6001 if ConditionPassed() then
6002 EncodingSpecificOperations();
6003 result
= R
[n
] AND imm32
;
6004 if d
== 15 then
// Can only occur for ARM encoding
6005 ALUWritePC(result
); // setflags is always FALSE here
6009 APSR
.N
= result
<31>;
6010 APSR
.Z
= IsZeroBit(result
);
6015 bool success
= false;
6017 if (ConditionPassed(opcode
)) {
6020 imm32
; // the immediate value to be ANDed to the value obtained from Rn
6022 uint32_t carry
; // the carry bit after ARM/Thumb Expand operation
6025 Rd
= Bits32(opcode
, 11, 8);
6026 Rn
= Bits32(opcode
, 19, 16);
6027 setflags
= BitIsSet(opcode
, 20);
6028 imm32
= ThumbExpandImm_C(
6030 carry
); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C)
6031 // if Rd == '1111' && S == '1' then SEE TST (immediate);
6032 if (Rd
== 15 && setflags
)
6033 return EmulateTSTImm(opcode
, eEncodingT1
);
6034 if (Rd
== 13 || (Rd
== 15 && !setflags
) || BadReg(Rn
))
6038 Rd
= Bits32(opcode
, 15, 12);
6039 Rn
= Bits32(opcode
, 19, 16);
6040 setflags
= BitIsSet(opcode
, 20);
6042 ARMExpandImm_C(opcode
, APSR_C
,
6043 carry
); // (imm32, carry) = ARMExpandImm(imm12, APSR.C)
6045 if (Rd
== 15 && setflags
)
6046 return EmulateSUBSPcLrEtc(opcode
, encoding
);
6052 // Read the first operand.
6053 uint32_t val1
= ReadCoreReg(Rn
, &success
);
6057 uint32_t result
= val1
& imm32
;
6059 EmulateInstruction::Context context
;
6060 context
.type
= EmulateInstruction::eContextImmediate
;
6061 context
.SetNoArgs();
6063 if (!WriteCoreRegOptionalFlags(context
, result
, Rd
, setflags
, carry
))
6069 // This instruction performs a bitwise AND of a register value and an
6070 // optionally-shifted register value, and writes the result to the destination
6071 // register. It can optionally update the condition flags based on the result.
6072 bool EmulateInstructionARM::EmulateANDReg(const uint32_t opcode
,
6073 const ARMEncoding encoding
) {
6075 // ARM pseudo code...
6076 if ConditionPassed() then
6077 EncodingSpecificOperations();
6078 (shifted
, carry
) = Shift_C(R
[m
], shift_t
, shift_n
, APSR
.C
);
6079 result
= R
[n
] AND shifted
;
6080 if d
== 15 then
// Can only occur for ARM encoding
6081 ALUWritePC(result
); // setflags is always FALSE here
6085 APSR
.N
= result
<31>;
6086 APSR
.Z
= IsZeroBit(result
);
6091 bool success
= false;
6093 if (ConditionPassed(opcode
)) {
6094 uint32_t Rd
, Rn
, Rm
;
6095 ARM_ShifterType shift_t
;
6096 uint32_t shift_n
; // the shift applied to the value read from Rm
6101 Rd
= Rn
= Bits32(opcode
, 2, 0);
6102 Rm
= Bits32(opcode
, 5, 3);
6103 setflags
= !InITBlock();
6104 shift_t
= SRType_LSL
;
6108 Rd
= Bits32(opcode
, 11, 8);
6109 Rn
= Bits32(opcode
, 19, 16);
6110 Rm
= Bits32(opcode
, 3, 0);
6111 setflags
= BitIsSet(opcode
, 20);
6112 shift_n
= DecodeImmShiftThumb(opcode
, shift_t
);
6113 // if Rd == '1111' && S == '1' then SEE TST (register);
6114 if (Rd
== 15 && setflags
)
6115 return EmulateTSTReg(opcode
, eEncodingT2
);
6116 if (Rd
== 13 || (Rd
== 15 && !setflags
) || BadReg(Rn
) || BadReg(Rm
))
6120 Rd
= Bits32(opcode
, 15, 12);
6121 Rn
= Bits32(opcode
, 19, 16);
6122 Rm
= Bits32(opcode
, 3, 0);
6123 setflags
= BitIsSet(opcode
, 20);
6124 shift_n
= DecodeImmShiftARM(opcode
, shift_t
);
6126 if (Rd
== 15 && setflags
)
6127 return EmulateSUBSPcLrEtc(opcode
, encoding
);
6133 // Read the first operand.
6134 uint32_t val1
= ReadCoreReg(Rn
, &success
);
6138 // Read the second operand.
6139 uint32_t val2
= ReadCoreReg(Rm
, &success
);
6143 uint32_t shifted
= Shift_C(val2
, shift_t
, shift_n
, APSR_C
, carry
, &success
);
6146 uint32_t result
= val1
& shifted
;
6148 EmulateInstruction::Context context
;
6149 context
.type
= EmulateInstruction::eContextImmediate
;
6150 context
.SetNoArgs();
6152 if (!WriteCoreRegOptionalFlags(context
, result
, Rd
, setflags
, carry
))
6158 // Bitwise Bit Clear (immediate) performs a bitwise AND of a register value and
6159 // the complement of an immediate value, and writes the result to the
6160 // destination register. It can optionally update the condition flags based on
6162 bool EmulateInstructionARM::EmulateBICImm(const uint32_t opcode
,
6163 const ARMEncoding encoding
) {
6165 // ARM pseudo code...
6166 if ConditionPassed() then
6167 EncodingSpecificOperations();
6168 result
= R
[n
] AND
NOT(imm32
);
6169 if d
== 15 then
// Can only occur for ARM encoding
6170 ALUWritePC(result
); // setflags is always FALSE here
6174 APSR
.N
= result
<31>;
6175 APSR
.Z
= IsZeroBit(result
);
6180 bool success
= false;
6182 if (ConditionPassed(opcode
)) {
6184 uint32_t imm32
; // the immediate value to be bitwise inverted and ANDed to
6185 // the value obtained from Rn
6187 uint32_t carry
; // the carry bit after ARM/Thumb Expand operation
6190 Rd
= Bits32(opcode
, 11, 8);
6191 Rn
= Bits32(opcode
, 19, 16);
6192 setflags
= BitIsSet(opcode
, 20);
6193 imm32
= ThumbExpandImm_C(
6195 carry
); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C)
6196 if (BadReg(Rd
) || BadReg(Rn
))
6200 Rd
= Bits32(opcode
, 15, 12);
6201 Rn
= Bits32(opcode
, 19, 16);
6202 setflags
= BitIsSet(opcode
, 20);
6204 ARMExpandImm_C(opcode
, APSR_C
,
6205 carry
); // (imm32, carry) = ARMExpandImm(imm12, APSR.C)
6207 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related
6209 if (Rd
== 15 && setflags
)
6210 return EmulateSUBSPcLrEtc(opcode
, encoding
);
6216 // Read the first operand.
6217 uint32_t val1
= ReadCoreReg(Rn
, &success
);
6221 uint32_t result
= val1
& ~imm32
;
6223 EmulateInstruction::Context context
;
6224 context
.type
= EmulateInstruction::eContextImmediate
;
6225 context
.SetNoArgs();
6227 if (!WriteCoreRegOptionalFlags(context
, result
, Rd
, setflags
, carry
))
6233 // Bitwise Bit Clear (register) performs a bitwise AND of a register value and
6234 // the complement of an optionally-shifted register value, and writes the
6235 // result to the destination register. It can optionally update the condition
6236 // flags based on the result.
6237 bool EmulateInstructionARM::EmulateBICReg(const uint32_t opcode
,
6238 const ARMEncoding encoding
) {
6240 // ARM pseudo code...
6241 if ConditionPassed() then
6242 EncodingSpecificOperations();
6243 (shifted
, carry
) = Shift_C(R
[m
], shift_t
, shift_n
, APSR
.C
);
6244 result
= R
[n
] AND
NOT(shifted
);
6245 if d
== 15 then
// Can only occur for ARM encoding
6246 ALUWritePC(result
); // setflags is always FALSE here
6250 APSR
.N
= result
<31>;
6251 APSR
.Z
= IsZeroBit(result
);
6256 bool success
= false;
6258 if (ConditionPassed(opcode
)) {
6259 uint32_t Rd
, Rn
, Rm
;
6260 ARM_ShifterType shift_t
;
6261 uint32_t shift_n
; // the shift applied to the value read from Rm
6266 Rd
= Rn
= Bits32(opcode
, 2, 0);
6267 Rm
= Bits32(opcode
, 5, 3);
6268 setflags
= !InITBlock();
6269 shift_t
= SRType_LSL
;
6273 Rd
= Bits32(opcode
, 11, 8);
6274 Rn
= Bits32(opcode
, 19, 16);
6275 Rm
= Bits32(opcode
, 3, 0);
6276 setflags
= BitIsSet(opcode
, 20);
6277 shift_n
= DecodeImmShiftThumb(opcode
, shift_t
);
6278 if (BadReg(Rd
) || BadReg(Rn
) || BadReg(Rm
))
6282 Rd
= Bits32(opcode
, 15, 12);
6283 Rn
= Bits32(opcode
, 19, 16);
6284 Rm
= Bits32(opcode
, 3, 0);
6285 setflags
= BitIsSet(opcode
, 20);
6286 shift_n
= DecodeImmShiftARM(opcode
, shift_t
);
6288 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related
6290 if (Rd
== 15 && setflags
)
6291 return EmulateSUBSPcLrEtc(opcode
, encoding
);
6297 // Read the first operand.
6298 uint32_t val1
= ReadCoreReg(Rn
, &success
);
6302 // Read the second operand.
6303 uint32_t val2
= ReadCoreReg(Rm
, &success
);
6307 uint32_t shifted
= Shift_C(val2
, shift_t
, shift_n
, APSR_C
, carry
, &success
);
6310 uint32_t result
= val1
& ~shifted
;
6312 EmulateInstruction::Context context
;
6313 context
.type
= EmulateInstruction::eContextImmediate
;
6314 context
.SetNoArgs();
6316 if (!WriteCoreRegOptionalFlags(context
, result
, Rd
, setflags
, carry
))
6322 // LDR (immediate, ARM) calculates an address from a base register value and an
6323 // immediate offset, loads a word
6324 // from memory, and writes it to a register. It can use offset, post-indexed,
6325 // or pre-indexed addressing.
6326 bool EmulateInstructionARM::EmulateLDRImmediateARM(const uint32_t opcode
,
6327 const ARMEncoding encoding
) {
6329 if ConditionPassed() then
6330 EncodingSpecificOperations();
6331 offset_addr
= if add
then (R
[n
] + imm32
) else (R
[n
] - imm32
);
6332 address
= if index then offset_addr
else R
[n
];
6333 data
= MemU
[address
,4];
6334 if wback then R
[n
] = offset_addr
;
6336 if address
<1:0> == '00' then
LoadWritePC(data
); else UNPREDICTABLE
;
6337 elsif
UnalignedSupport() || address
<1:0> = '00' then
6339 else // Can only apply before ARMv7
6340 R
[t
] = ROR(data
, 8*UInt(address
<1:0>));
6343 bool success
= false;
6345 if (ConditionPassed(opcode
)) {
6346 const uint32_t addr_byte_size
= GetAddressByteSize();
6357 // if Rn == '1111' then SEE LDR (literal);
6358 // if P == '0' && W == '1' then SEE LDRT;
6359 // if Rn == '1101' && P == '0' && U == '1' && W == '0' && imm12 ==
6360 // '000000000100' then SEE POP;
6361 // t == UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
6362 t
= Bits32(opcode
, 15, 12);
6363 n
= Bits32(opcode
, 19, 16);
6364 imm32
= Bits32(opcode
, 11, 0);
6366 // index = (P == '1'); add = (U == '1'); wback = (P == '0') ||
6368 index
= BitIsSet(opcode
, 24);
6369 add
= BitIsSet(opcode
, 23);
6370 wback
= (BitIsClear(opcode
, 24) || BitIsSet(opcode
, 21));
6372 // if wback && n == t then UNPREDICTABLE;
6373 if (wback
&& (n
== t
))
6384 addr_t base_address
= ReadCoreReg(n
, &success
);
6388 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
6390 offset_addr
= base_address
+ imm32
;
6392 offset_addr
= base_address
- imm32
;
6394 // address = if index then offset_addr else R[n];
6396 address
= offset_addr
;
6398 address
= base_address
;
6400 // data = MemU[address,4];
6402 std::optional
<RegisterInfo
> base_reg
=
6403 GetRegisterInfo(eRegisterKindDWARF
, dwarf_r0
+ n
);
6404 EmulateInstruction::Context context
;
6405 context
.type
= eContextRegisterLoad
;
6406 context
.SetRegisterPlusOffset(*base_reg
, address
- base_address
);
6408 uint64_t data
= MemURead(context
, address
, addr_byte_size
, 0, &success
);
6412 // if wback then R[n] = offset_addr;
6414 context
.type
= eContextAdjustBaseRegister
;
6415 context
.SetAddress(offset_addr
);
6416 if (!WriteRegisterUnsigned(context
, eRegisterKindDWARF
, dwarf_r0
+ n
,
6423 // if address<1:0> == '00' then LoadWritePC(data); else UNPREDICTABLE;
6424 if (BitIsClear(address
, 1) && BitIsClear(address
, 0)) {
6425 // LoadWritePC (data);
6426 context
.type
= eContextRegisterLoad
;
6427 context
.SetRegisterPlusOffset(*base_reg
, address
- base_address
);
6428 LoadWritePC(context
, data
);
6432 // elsif UnalignedSupport() || address<1:0> = '00' then
6433 else if (UnalignedSupport() ||
6434 (BitIsClear(address
, 1) && BitIsClear(address
, 0))) {
6436 context
.type
= eContextRegisterLoad
;
6437 context
.SetRegisterPlusOffset(*base_reg
, address
- base_address
);
6438 if (!WriteRegisterUnsigned(context
, eRegisterKindDWARF
, dwarf_r0
+ t
,
6442 // else // Can only apply before ARMv7
6444 // R[t] = ROR(data, 8*UInt(address<1:0>));
6445 data
= ROR(data
, Bits32(address
, 1, 0), &success
);
6448 context
.type
= eContextRegisterLoad
;
6449 context
.SetImmediate(data
);
6450 if (!WriteRegisterUnsigned(context
, eRegisterKindDWARF
, dwarf_r0
+ t
,
6458 // LDR (register) calculates an address from a base register value and an offset
6459 // register value, loads a word
6460 // from memory, and writes it to a register. The offset register value can
6461 // optionally be shifted.
6462 bool EmulateInstructionARM::EmulateLDRRegister(const uint32_t opcode
,
6463 const ARMEncoding encoding
) {
6465 if ConditionPassed() then
6466 EncodingSpecificOperations(); NullCheckIfThumbEE(n
);
6467 offset
= Shift(R
[m
], shift_t
, shift_n
, APSR
.C
);
6468 offset_addr
= if add
then (R
[n
] + offset
) else (R
[n
] - offset
);
6469 address
= if index then offset_addr
else R
[n
];
6470 data
= MemU
[address
,4];
6471 if wback then R
[n
] = offset_addr
;
6473 if address
<1:0> == '00' then
LoadWritePC(data
); else UNPREDICTABLE
;
6474 elsif
UnalignedSupport() || address
<1:0> = '00' then
6476 else // Can only apply before ARMv7
6477 if CurrentInstrSet() == InstrSet_ARM then
6478 R
[t
] = ROR(data
, 8*UInt(address
<1:0>));
6480 R
[t
] = bits(32) UNKNOWN
;
6483 bool success
= false;
6485 if (ConditionPassed(opcode
)) {
6486 const uint32_t addr_byte_size
= GetAddressByteSize();
6494 ARM_ShifterType shift_t
;
6499 // if CurrentInstrSet() == InstrSet_ThumbEE then SEE "Modified operation
6501 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
6502 t
= Bits32(opcode
, 2, 0);
6503 n
= Bits32(opcode
, 5, 3);
6504 m
= Bits32(opcode
, 8, 6);
6506 // index = TRUE; add = TRUE; wback = FALSE;
6511 // (shift_t, shift_n) = (SRType_LSL, 0);
6512 shift_t
= SRType_LSL
;
6518 // if Rn == '1111' then SEE LDR (literal);
6519 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
6520 t
= Bits32(opcode
, 15, 12);
6521 n
= Bits32(opcode
, 19, 16);
6522 m
= Bits32(opcode
, 3, 0);
6524 // index = TRUE; add = TRUE; wback = FALSE;
6529 // (shift_t, shift_n) = (SRType_LSL, UInt(imm2));
6530 shift_t
= SRType_LSL
;
6531 shift_n
= Bits32(opcode
, 5, 4);
6533 // if BadReg(m) then UNPREDICTABLE;
6537 // if t == 15 && InITBlock() && !LastInITBlock() then UNPREDICTABLE;
6538 if ((t
== 15) && InITBlock() && !LastInITBlock())
6544 // if P == '0' && W == '1' then SEE LDRT;
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 = (P == '1'); add = (U == '1'); wback = (P == '0') ||
6552 index
= BitIsSet(opcode
, 24);
6553 add
= BitIsSet(opcode
, 23);
6554 wback
= (BitIsClear(opcode
, 24) || BitIsSet(opcode
, 21));
6556 // (shift_t, shift_n) = DecodeImmShift(type, imm5);
6557 uint32_t type
= Bits32(opcode
, 6, 5);
6558 uint32_t imm5
= Bits32(opcode
, 11, 7);
6559 shift_n
= DecodeImmShift(type
, imm5
, shift_t
);
6561 // if m == 15 then UNPREDICTABLE;
6565 // if wback && (n == 15 || n == t) then UNPREDICTABLE;
6566 if (wback
&& ((n
== 15) || (n
== t
)))
6575 ReadRegisterUnsigned(eRegisterKindDWARF
, dwarf_r0
+ m
, 0, &success
);
6580 ReadRegisterUnsigned(eRegisterKindDWARF
, dwarf_r0
+ n
, 0, &success
);
6587 // offset = Shift(R[m], shift_t, shift_n, APSR.C); -- Note "The APSR is
6588 // an application level alias for the CPSR".
6590 Shift(Rm
, shift_t
, shift_n
, Bit32(m_opcode_cpsr
, APSR_C
), &success
);
6594 // offset_addr = if add then (R[n] + offset) else (R[n] - offset);
6596 offset_addr
= Rn
+ offset
;
6598 offset_addr
= Rn
- offset
;
6600 // address = if index then offset_addr else R[n];
6602 address
= offset_addr
;
6606 // data = MemU[address,4];
6607 std::optional
<RegisterInfo
> base_reg
=
6608 GetRegisterInfo(eRegisterKindDWARF
, dwarf_r0
+ n
);
6609 EmulateInstruction::Context context
;
6610 context
.type
= eContextRegisterLoad
;
6611 context
.SetRegisterPlusOffset(*base_reg
, address
- Rn
);
6613 uint64_t data
= MemURead(context
, address
, addr_byte_size
, 0, &success
);
6617 // if wback then R[n] = offset_addr;
6619 context
.type
= eContextAdjustBaseRegister
;
6620 context
.SetAddress(offset_addr
);
6621 if (!WriteRegisterUnsigned(context
, eRegisterKindDWARF
, dwarf_r0
+ n
,
6628 // if address<1:0> == '00' then LoadWritePC(data); else UNPREDICTABLE;
6629 if (BitIsClear(address
, 1) && BitIsClear(address
, 0)) {
6630 context
.type
= eContextRegisterLoad
;
6631 context
.SetRegisterPlusOffset(*base_reg
, address
- Rn
);
6632 LoadWritePC(context
, data
);
6636 // elsif UnalignedSupport() || address<1:0> = '00' then
6637 else if (UnalignedSupport() ||
6638 (BitIsClear(address
, 1) && BitIsClear(address
, 0))) {
6640 context
.type
= eContextRegisterLoad
;
6641 context
.SetRegisterPlusOffset(*base_reg
, address
- Rn
);
6642 if (!WriteRegisterUnsigned(context
, eRegisterKindDWARF
, dwarf_r0
+ t
,
6645 } else // Can only apply before ARMv7
6647 // if CurrentInstrSet() == InstrSet_ARM then
6648 if (CurrentInstrSet() == eModeARM
) {
6649 // R[t] = ROR(data, 8*UInt(address<1:0>));
6650 data
= ROR(data
, Bits32(address
, 1, 0), &success
);
6653 context
.type
= eContextRegisterLoad
;
6654 context
.SetImmediate(data
);
6655 if (!WriteRegisterUnsigned(context
, eRegisterKindDWARF
, dwarf_r0
+ t
,
6659 // R[t] = bits(32) UNKNOWN;
6660 WriteBits32Unknown(t
);
6667 // LDRB (immediate, Thumb)
6668 bool EmulateInstructionARM::EmulateLDRBImmediate(const uint32_t opcode
,
6669 const ARMEncoding encoding
) {
6671 if ConditionPassed() then
6672 EncodingSpecificOperations(); NullCheckIfThumbEE(n
);
6673 offset_addr
= if add
then (R
[n
] + imm32
) else (R
[n
] - imm32
);
6674 address
= if index then offset_addr
else R
[n
];
6675 R
[t
] = ZeroExtend(MemU
[address
,1], 32);
6676 if wback then R
[n
] = offset_addr
;
6679 bool success
= false;
6681 if (ConditionPassed(opcode
)) {
6689 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
6692 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm5, 32);
6693 t
= Bits32(opcode
, 2, 0);
6694 n
= Bits32(opcode
, 5, 3);
6695 imm32
= Bits32(opcode
, 10, 6);
6697 // index = TRUE; add = TRUE; wback = FALSE;
6705 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
6706 t
= Bits32(opcode
, 15, 12);
6707 n
= Bits32(opcode
, 19, 16);
6708 imm32
= Bits32(opcode
, 11, 0);
6710 // index = TRUE; add = TRUE; wback = FALSE;
6715 // if Rt == '1111' then SEE PLD;
6717 return false; // PLD is not implemented yet
6719 // if Rn == '1111' then SEE LDRB (literal);
6721 return EmulateLDRBLiteral(opcode
, eEncodingT1
);
6723 // if t == 13 then UNPREDICTABLE;
6730 // if P == '1' && U == '1' && W == '0' then SEE LDRBT;
6731 // if P == '0' && W == '0' then UNDEFINED;
6732 if (BitIsClear(opcode
, 10) && BitIsClear(opcode
, 8))
6735 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32);
6736 t
= Bits32(opcode
, 15, 12);
6737 n
= Bits32(opcode
, 19, 16);
6738 imm32
= Bits32(opcode
, 7, 0);
6740 // index = (P == '1'); add = (U == '1'); wback = (W == '1');
6741 index
= BitIsSet(opcode
, 10);
6742 add
= BitIsSet(opcode
, 9);
6743 wback
= BitIsSet(opcode
, 8);
6745 // if Rt == '1111' && P == '1' && U == '0' && W == '0' then SEE PLD;
6747 return false; // PLD is not implemented yet
6749 // if Rn == '1111' then SEE LDRB (literal);
6751 return EmulateLDRBLiteral(opcode
, eEncodingT1
);
6753 // if BadReg(t) || (wback && n == t) then UNPREDICTABLE;
6754 if (BadReg(t
) || (wback
&& (n
== t
)))
6764 ReadRegisterUnsigned(eRegisterKindDWARF
, dwarf_r0
+ n
, 0, &success
);
6771 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
6773 offset_addr
= Rn
+ imm32
;
6775 offset_addr
= Rn
- imm32
;
6777 // address = if index then offset_addr else R[n];
6779 address
= offset_addr
;
6783 // R[t] = ZeroExtend(MemU[address,1], 32);
6784 std::optional
<RegisterInfo
> base_reg
=
6785 GetRegisterInfo(eRegisterKindDWARF
, dwarf_r0
+ n
);
6786 std::optional
<RegisterInfo
> data_reg
=
6787 GetRegisterInfo(eRegisterKindDWARF
, dwarf_r0
+ t
);
6789 EmulateInstruction::Context context
;
6790 context
.type
= eContextRegisterLoad
;
6791 context
.SetRegisterToRegisterPlusOffset(*data_reg
, *base_reg
, address
- Rn
);
6793 uint64_t data
= MemURead(context
, address
, 1, 0, &success
);
6797 if (!WriteRegisterUnsigned(context
, eRegisterKindDWARF
, dwarf_r0
+ t
, data
))
6800 // if wback then R[n] = offset_addr;
6802 context
.type
= eContextAdjustBaseRegister
;
6803 context
.SetAddress(offset_addr
);
6804 if (!WriteRegisterUnsigned(context
, eRegisterKindDWARF
, dwarf_r0
+ n
,
6812 // LDRB (literal) calculates an address from the PC value and an immediate
6813 // offset, loads a byte from memory,
6814 // zero-extends it to form a 32-bit word and writes it to a register.
6815 bool EmulateInstructionARM::EmulateLDRBLiteral(const uint32_t opcode
,
6816 const ARMEncoding encoding
) {
6818 if ConditionPassed() then
6819 EncodingSpecificOperations(); NullCheckIfThumbEE(15);
6821 address
= if add
then (base
+ imm32
) else (base
- imm32
);
6822 R
[t
] = ZeroExtend(MemU
[address
,1], 32);
6825 bool success
= false;
6827 if (ConditionPassed(opcode
)) {
6833 // t = UInt(Rt); imm32 = ZeroExtend(imm12, 32); add = (U == '1');
6834 t
= Bits32(opcode
, 15, 12);
6835 imm32
= Bits32(opcode
, 11, 0);
6836 add
= BitIsSet(opcode
, 23);
6838 // if Rt == '1111' then SEE PLD;
6840 return false; // PLD is not implemented yet
6842 // if t == 13 then UNPREDICTABLE;
6849 // t == UInt(Rt); imm32 = ZeroExtend(imm12, 32); add = (U == '1');
6850 t
= Bits32(opcode
, 15, 12);
6851 imm32
= Bits32(opcode
, 11, 0);
6852 add
= BitIsSet(opcode
, 23);
6854 // if t == 15 then UNPREDICTABLE;
6863 // base = Align(PC,4);
6864 uint32_t pc_val
= ReadCoreReg(PC_REG
, &success
);
6868 uint32_t base
= AlignPC(pc_val
);
6871 // address = if add then (base + imm32) else (base - imm32);
6873 address
= base
+ imm32
;
6875 address
= base
- imm32
;
6877 // R[t] = ZeroExtend(MemU[address,1], 32);
6878 EmulateInstruction::Context context
;
6879 context
.type
= eContextRelativeBranchImmediate
;
6880 context
.SetImmediate(address
- base
);
6882 uint64_t data
= MemURead(context
, address
, 1, 0, &success
);
6886 if (!WriteRegisterUnsigned(context
, eRegisterKindDWARF
, dwarf_r0
+ t
, data
))
6892 // LDRB (register) calculates an address from a base register value and an
6893 // offset rigister value, loads a byte from memory, zero-extends it to form a
6894 // 32-bit word, and writes it to a register. The offset register value can
6895 // optionally be shifted.
6896 bool EmulateInstructionARM::EmulateLDRBRegister(const uint32_t opcode
,
6897 const ARMEncoding encoding
) {
6899 if ConditionPassed() then
6900 EncodingSpecificOperations(); NullCheckIfThumbEE(n
);
6901 offset
= Shift(R
[m
], shift_t
, shift_n
, APSR
.C
);
6902 offset_addr
= if add
then (R
[n
] + offset
) else (R
[n
] - offset
);
6903 address
= if index then offset_addr
else R
[n
];
6904 R
[t
] = ZeroExtend(MemU
[address
,1],32);
6905 if wback then R
[n
] = offset_addr
;
6908 bool success
= false;
6910 if (ConditionPassed(opcode
)) {
6917 ARM_ShifterType shift_t
;
6920 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
6923 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
6924 t
= Bits32(opcode
, 2, 0);
6925 n
= Bits32(opcode
, 5, 3);
6926 m
= Bits32(opcode
, 8, 6);
6928 // index = TRUE; add = TRUE; wback = FALSE;
6933 // (shift_t, shift_n) = (SRType_LSL, 0);
6934 shift_t
= SRType_LSL
;
6939 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
6940 t
= Bits32(opcode
, 15, 12);
6941 n
= Bits32(opcode
, 19, 16);
6942 m
= Bits32(opcode
, 3, 0);
6944 // index = TRUE; add = TRUE; wback = FALSE;
6949 // (shift_t, shift_n) = (SRType_LSL, UInt(imm2));
6950 shift_t
= SRType_LSL
;
6951 shift_n
= Bits32(opcode
, 5, 4);
6953 // if Rt == '1111' then SEE PLD;
6955 return false; // PLD is not implemented yet
6957 // if Rn == '1111' then SEE LDRB (literal);
6959 return EmulateLDRBLiteral(opcode
, eEncodingT1
);
6961 // if t == 13 || BadReg(m) then UNPREDICTABLE;
6962 if ((t
== 13) || BadReg(m
))
6967 // if P == '0' && W == '1' then SEE LDRBT;
6968 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
6969 t
= Bits32(opcode
, 15, 12);
6970 n
= Bits32(opcode
, 19, 16);
6971 m
= Bits32(opcode
, 3, 0);
6973 // index = (P == '1'); add = (U == '1'); wback = (P == '0') ||
6975 index
= BitIsSet(opcode
, 24);
6976 add
= BitIsSet(opcode
, 23);
6977 wback
= (BitIsClear(opcode
, 24) || BitIsSet(opcode
, 21));
6979 // (shift_t, shift_n) = DecodeImmShift(type, imm5);
6980 uint32_t type
= Bits32(opcode
, 6, 5);
6981 uint32_t imm5
= Bits32(opcode
, 11, 7);
6982 shift_n
= DecodeImmShift(type
, imm5
, shift_t
);
6984 // if t == 15 || m == 15 then UNPREDICTABLE;
6985 if ((t
== 15) || (m
== 15))
6988 // if wback && (n == 15 || n == t) then UNPREDICTABLE;
6989 if (wback
&& ((n
== 15) || (n
== t
)))
7000 // offset = Shift(R[m], shift_t, shift_n, APSR.C);
7002 ReadRegisterUnsigned(eRegisterKindDWARF
, dwarf_r0
+ m
, 0, &success
);
7006 addr_t offset
= Shift(Rm
, shift_t
, shift_n
, APSR_C
, &success
);
7010 // offset_addr = if add then (R[n] + offset) else (R[n] - offset);
7012 ReadRegisterUnsigned(eRegisterKindDWARF
, dwarf_r0
+ n
, 0, &success
);
7017 offset_addr
= Rn
+ offset
;
7019 offset_addr
= Rn
- offset
;
7021 // address = if index then offset_addr else R[n];
7023 address
= offset_addr
;
7027 // R[t] = ZeroExtend(MemU[address,1],32);
7028 std::optional
<RegisterInfo
> base_reg
=
7029 GetRegisterInfo(eRegisterKindDWARF
, dwarf_r0
+ n
);
7031 EmulateInstruction::Context context
;
7032 context
.type
= eContextRegisterLoad
;
7033 context
.SetRegisterPlusOffset(*base_reg
, address
- Rn
);
7035 uint64_t data
= MemURead(context
, address
, 1, 0, &success
);
7039 if (!WriteRegisterUnsigned(context
, eRegisterKindDWARF
, dwarf_r0
+ t
, data
))
7042 // if wback then R[n] = offset_addr;
7044 context
.type
= eContextAdjustBaseRegister
;
7045 context
.SetAddress(offset_addr
);
7046 if (!WriteRegisterUnsigned(context
, eRegisterKindDWARF
, dwarf_r0
+ n
,
7054 // LDRH (immediate, Thumb) calculates an address from a base register value and
7055 // an immediate offset, loads a
7056 // halfword from memory, zero-extends it to form a 32-bit word, and writes it
7057 // to a register. It can use offset, post-indexed, or pre-indexed addressing.
7058 bool EmulateInstructionARM::EmulateLDRHImmediate(const uint32_t opcode
,
7059 const ARMEncoding encoding
) {
7061 if ConditionPassed() then
7062 EncodingSpecificOperations(); NullCheckIfThumbEE(n
);
7063 offset_addr
= if add
then (R
[n
] + imm32
) else (R
[n
] - imm32
);
7064 address
= if index then offset_addr
else R
[n
];
7065 data
= MemU
[address
,2];
7066 if wback then R
[n
] = offset_addr
;
7067 if UnalignedSupport() || address
<0> = '0' then
7068 R
[t
] = ZeroExtend(data
, 32);
7069 else // Can only apply before ARMv7
7070 R
[t
] = bits(32) UNKNOWN
;
7073 bool success
= false;
7075 if (ConditionPassed(opcode
)) {
7083 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
7086 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm5:'0', 32);
7087 t
= Bits32(opcode
, 2, 0);
7088 n
= Bits32(opcode
, 5, 3);
7089 imm32
= Bits32(opcode
, 10, 6) << 1;
7091 // index = TRUE; add = TRUE; wback = FALSE;
7099 // if Rt == '1111' then SEE "Unallocated memory hints";
7100 // if Rn == '1111' then SEE LDRH (literal);
7101 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
7102 t
= Bits32(opcode
, 15, 12);
7103 n
= Bits32(opcode
, 19, 16);
7104 imm32
= Bits32(opcode
, 11, 0);
7106 // index = TRUE; add = TRUE; wback = FALSE;
7111 // if t == 13 then UNPREDICTABLE;
7117 // if Rn == '1111' then SEE LDRH (literal);
7118 // if Rt == '1111' && P == '1' && U == '0' && W == '0' then SEE
7119 // "Unallocated memory hints";
7120 // if P == '1' && U == '1' && W == '0' then SEE LDRHT;
7121 // if P == '0' && W == '0' then UNDEFINED;
7122 if (BitIsClear(opcode
, 10) && BitIsClear(opcode
, 8))
7125 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32);
7126 t
= Bits32(opcode
, 15, 12);
7127 n
= Bits32(opcode
, 19, 16);
7128 imm32
= Bits32(opcode
, 7, 0);
7130 // index = (P == '1'); add = (U == '1'); wback = (W == '1');
7131 index
= BitIsSet(opcode
, 10);
7132 add
= BitIsSet(opcode
, 9);
7133 wback
= BitIsSet(opcode
, 8);
7135 // if BadReg(t) || (wback && n == t) then UNPREDICTABLE;
7136 if (BadReg(t
) || (wback
&& (n
== t
)))
7144 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
7146 ReadRegisterUnsigned(eRegisterKindDWARF
, dwarf_r0
+ n
, 0, &success
);
7154 offset_addr
= Rn
+ imm32
;
7156 offset_addr
= Rn
- imm32
;
7158 // address = if index then offset_addr else R[n];
7160 address
= offset_addr
;
7164 // data = MemU[address,2];
7165 std::optional
<RegisterInfo
> base_reg
=
7166 GetRegisterInfo(eRegisterKindDWARF
, dwarf_r0
+ n
);
7168 EmulateInstruction::Context context
;
7169 context
.type
= eContextRegisterLoad
;
7170 context
.SetRegisterPlusOffset(*base_reg
, address
- Rn
);
7172 uint64_t data
= MemURead(context
, address
, 2, 0, &success
);
7176 // if wback then R[n] = offset_addr;
7178 context
.type
= eContextAdjustBaseRegister
;
7179 context
.SetAddress(offset_addr
);
7180 if (!WriteRegisterUnsigned(context
, eRegisterKindDWARF
, dwarf_r0
+ n
,
7185 // if UnalignedSupport() || address<0> = '0' then
7186 if (UnalignedSupport() || BitIsClear(address
, 0)) {
7187 // R[t] = ZeroExtend(data, 32);
7188 context
.type
= eContextRegisterLoad
;
7189 context
.SetRegisterPlusOffset(*base_reg
, address
- Rn
);
7190 if (!WriteRegisterUnsigned(context
, eRegisterKindDWARF
, dwarf_r0
+ t
,
7193 } else // Can only apply before ARMv7
7195 // R[t] = bits(32) UNKNOWN;
7196 WriteBits32Unknown(t
);
7202 // LDRH (literal) calculates an address from the PC value and an immediate
7203 // offset, loads a halfword from memory,
7204 // zero-extends it to form a 32-bit word, and writes it to a register.
7205 bool EmulateInstructionARM::EmulateLDRHLiteral(const uint32_t opcode
,
7206 const ARMEncoding encoding
) {
7208 if ConditionPassed() then
7209 EncodingSpecificOperations(); NullCheckIfThumbEE(15);
7211 address
= if add
then (base
+ imm32
) else (base
- imm32
);
7212 data
= MemU
[address
,2];
7213 if UnalignedSupport() || address
<0> = '0' then
7214 R
[t
] = ZeroExtend(data
, 32);
7215 else // Can only apply before ARMv7
7216 R
[t
] = bits(32) UNKNOWN
;
7219 bool success
= false;
7221 if (ConditionPassed(opcode
)) {
7226 // EncodingSpecificOperations(); NullCheckIfThumbEE(15);
7229 // if Rt == '1111' then SEE "Unallocated memory hints";
7230 // t = UInt(Rt); imm32 = ZeroExtend(imm12, 32); add = (U == '1');
7231 t
= Bits32(opcode
, 15, 12);
7232 imm32
= Bits32(opcode
, 11, 0);
7233 add
= BitIsSet(opcode
, 23);
7235 // if t == 13 then UNPREDICTABLE;
7242 uint32_t imm4H
= Bits32(opcode
, 11, 8);
7243 uint32_t imm4L
= Bits32(opcode
, 3, 0);
7245 // t == UInt(Rt); imm32 = ZeroExtend(imm4H:imm4L, 32); add = (U == '1');
7246 t
= Bits32(opcode
, 15, 12);
7247 imm32
= (imm4H
<< 4) | imm4L
;
7248 add
= BitIsSet(opcode
, 23);
7250 // if t == 15 then UNPREDICTABLE;
7260 // base = Align(PC,4);
7261 uint64_t pc_value
= ReadCoreReg(PC_REG
, &success
);
7265 addr_t base
= AlignPC(pc_value
);
7268 // address = if add then (base + imm32) else (base - imm32);
7270 address
= base
+ imm32
;
7272 address
= base
- imm32
;
7274 // data = MemU[address,2];
7275 std::optional
<RegisterInfo
> base_reg
=
7276 GetRegisterInfo(eRegisterKindGeneric
, LLDB_REGNUM_GENERIC_PC
);
7278 EmulateInstruction::Context context
;
7279 context
.type
= eContextRegisterLoad
;
7280 context
.SetRegisterPlusOffset(*base_reg
, address
- base
);
7282 uint64_t data
= MemURead(context
, address
, 2, 0, &success
);
7286 // if UnalignedSupport() || address<0> = '0' then
7287 if (UnalignedSupport() || BitIsClear(address
, 0)) {
7288 // R[t] = ZeroExtend(data, 32);
7289 context
.type
= eContextRegisterLoad
;
7290 context
.SetRegisterPlusOffset(*base_reg
, address
- base
);
7291 if (!WriteRegisterUnsigned(context
, eRegisterKindDWARF
, dwarf_r0
+ t
,
7295 } else // Can only apply before ARMv7
7297 // R[t] = bits(32) UNKNOWN;
7298 WriteBits32Unknown(t
);
7304 // LDRH (literal) calculates an address from a base register value and an offset
7305 // register value, loads a halfword
7306 // from memory, zero-extends it to form a 32-bit word, and writes it to a
7307 // register. The offset register value can be shifted left by 0, 1, 2, or 3
7309 bool EmulateInstructionARM::EmulateLDRHRegister(const uint32_t opcode
,
7310 const ARMEncoding encoding
) {
7312 if ConditionPassed() then
7313 EncodingSpecificOperations(); NullCheckIfThumbEE(n
);
7314 offset
= Shift(R
[m
], shift_t
, shift_n
, APSR
.C
);
7315 offset_addr
= if add
then (R
[n
] + offset
) else (R
[n
] - offset
);
7316 address
= if index then offset_addr
else R
[n
];
7317 data
= MemU
[address
,2];
7318 if wback then R
[n
] = offset_addr
;
7319 if UnalignedSupport() || address
<0> = '0' then
7320 R
[t
] = ZeroExtend(data
, 32);
7321 else // Can only apply before ARMv7
7322 R
[t
] = bits(32) UNKNOWN
;
7325 bool success
= false;
7327 if (ConditionPassed(opcode
)) {
7334 ARM_ShifterType shift_t
;
7337 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
7340 // if CurrentInstrSet() == InstrSet_ThumbEE then SEE "Modified operation
7342 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
7343 t
= Bits32(opcode
, 2, 0);
7344 n
= Bits32(opcode
, 5, 3);
7345 m
= Bits32(opcode
, 8, 6);
7347 // index = TRUE; add = TRUE; wback = FALSE;
7352 // (shift_t, shift_n) = (SRType_LSL, 0);
7353 shift_t
= SRType_LSL
;
7359 // if Rn == '1111' then SEE LDRH (literal);
7360 // if Rt == '1111' then SEE "Unallocated memory hints";
7361 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
7362 t
= Bits32(opcode
, 15, 12);
7363 n
= Bits32(opcode
, 19, 16);
7364 m
= Bits32(opcode
, 3, 0);
7366 // index = TRUE; add = TRUE; wback = FALSE;
7371 // (shift_t, shift_n) = (SRType_LSL, UInt(imm2));
7372 shift_t
= SRType_LSL
;
7373 shift_n
= Bits32(opcode
, 5, 4);
7375 // if t == 13 || BadReg(m) then UNPREDICTABLE;
7376 if ((t
== 13) || BadReg(m
))
7381 // if P == '0' && W == '1' then SEE LDRHT;
7382 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
7383 t
= Bits32(opcode
, 15, 12);
7384 n
= Bits32(opcode
, 19, 16);
7385 m
= Bits32(opcode
, 3, 0);
7387 // index = (P == '1'); add = (U == '1'); wback = (P == '0') ||
7389 index
= BitIsSet(opcode
, 24);
7390 add
= BitIsSet(opcode
, 23);
7391 wback
= (BitIsClear(opcode
, 24) || BitIsSet(opcode
, 21));
7393 // (shift_t, shift_n) = (SRType_LSL, 0);
7394 shift_t
= SRType_LSL
;
7397 // if t == 15 || m == 15 then UNPREDICTABLE;
7398 if ((t
== 15) || (m
== 15))
7401 // if wback && (n == 15 || n == t) then UNPREDICTABLE;
7402 if (wback
&& ((n
== 15) || (n
== t
)))
7411 // offset = Shift(R[m], shift_t, shift_n, APSR.C);
7414 ReadRegisterUnsigned(eRegisterKindDWARF
, dwarf_r0
+ m
, 0, &success
);
7418 addr_t offset
= Shift(Rm
, shift_t
, shift_n
, APSR_C
, &success
);
7425 // offset_addr = if add then (R[n] + offset) else (R[n] - offset);
7427 ReadRegisterUnsigned(eRegisterKindDWARF
, dwarf_r0
+ n
, 0, &success
);
7432 offset_addr
= Rn
+ offset
;
7434 offset_addr
= Rn
- offset
;
7436 // address = if index then offset_addr else R[n];
7438 address
= offset_addr
;
7442 // data = MemU[address,2];
7443 std::optional
<RegisterInfo
> base_reg
=
7444 GetRegisterInfo(eRegisterKindDWARF
, dwarf_r0
+ n
);
7445 std::optional
<RegisterInfo
> offset_reg
=
7446 GetRegisterInfo(eRegisterKindDWARF
, dwarf_r0
+ m
);
7448 EmulateInstruction::Context context
;
7449 context
.type
= eContextRegisterLoad
;
7450 context
.SetRegisterPlusIndirectOffset(*base_reg
, *offset_reg
);
7451 uint64_t data
= MemURead(context
, address
, 2, 0, &success
);
7455 // if wback then R[n] = offset_addr;
7457 context
.type
= eContextAdjustBaseRegister
;
7458 context
.SetAddress(offset_addr
);
7459 if (!WriteRegisterUnsigned(context
, eRegisterKindDWARF
, dwarf_r0
+ n
,
7464 // if UnalignedSupport() || address<0> = '0' then
7465 if (UnalignedSupport() || BitIsClear(address
, 0)) {
7466 // R[t] = ZeroExtend(data, 32);
7467 context
.type
= eContextRegisterLoad
;
7468 context
.SetRegisterPlusIndirectOffset(*base_reg
, *offset_reg
);
7469 if (!WriteRegisterUnsigned(context
, eRegisterKindDWARF
, dwarf_r0
+ t
,
7472 } else // Can only apply before ARMv7
7474 // R[t] = bits(32) UNKNOWN;
7475 WriteBits32Unknown(t
);
7481 // LDRSB (immediate) calculates an address from a base register value and an
7482 // immediate offset, loads a byte from
7483 // memory, sign-extends it to form a 32-bit word, and writes it to a register.
7484 // It can use offset, post-indexed, or pre-indexed addressing.
7485 bool EmulateInstructionARM::EmulateLDRSBImmediate(const uint32_t opcode
,
7486 const ARMEncoding encoding
) {
7488 if ConditionPassed() then
7489 EncodingSpecificOperations(); NullCheckIfThumbEE(n
);
7490 offset_addr
= if add
then (R
[n
] + imm32
) else (R
[n
] - imm32
);
7491 address
= if index then offset_addr
else R
[n
];
7492 R
[t
] = SignExtend(MemU
[address
,1], 32);
7493 if wback then R
[n
] = offset_addr
;
7496 bool success
= false;
7498 if (ConditionPassed(opcode
)) {
7506 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
7509 // if Rt == '1111' then SEE PLI;
7510 // if Rn == '1111' then SEE LDRSB (literal);
7511 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
7512 t
= Bits32(opcode
, 15, 12);
7513 n
= Bits32(opcode
, 19, 16);
7514 imm32
= Bits32(opcode
, 11, 0);
7516 // index = TRUE; add = TRUE; wback = FALSE;
7521 // if t == 13 then UNPREDICTABLE;
7528 // if Rt == '1111' && P == '1' && U == '0' && W == '0' then SEE PLI;
7529 // if Rn == '1111' then SEE LDRSB (literal);
7530 // if P == '1' && U == '1' && W == '0' then SEE LDRSBT;
7531 // if P == '0' && W == '0' then UNDEFINED;
7532 if (BitIsClear(opcode
, 10) && BitIsClear(opcode
, 8))
7535 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32);
7536 t
= Bits32(opcode
, 15, 12);
7537 n
= Bits32(opcode
, 19, 16);
7538 imm32
= Bits32(opcode
, 7, 0);
7540 // index = (P == '1'); add = (U == '1'); wback = (W == '1');
7541 index
= BitIsSet(opcode
, 10);
7542 add
= BitIsSet(opcode
, 9);
7543 wback
= BitIsSet(opcode
, 8);
7545 // if BadReg(t) || (wback && n == t) then UNPREDICTABLE;
7547 ((t
== 15) && (BitIsClear(opcode
, 10) || BitIsSet(opcode
, 9) ||
7548 BitIsSet(opcode
, 8)))) ||
7549 (wback
&& (n
== t
)))
7555 // if Rn == '1111' then SEE LDRSB (literal);
7556 // if P == '0' && W == '1' then SEE LDRSBT;
7557 // t == UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm4H:imm4L, 32);
7558 t
= Bits32(opcode
, 15, 12);
7559 n
= Bits32(opcode
, 19, 16);
7561 uint32_t imm4H
= Bits32(opcode
, 11, 8);
7562 uint32_t imm4L
= Bits32(opcode
, 3, 0);
7563 imm32
= (imm4H
<< 4) | imm4L
;
7565 // index = (P == '1'); add = (U == '1'); wback = (P == '0') ||
7567 index
= BitIsSet(opcode
, 24);
7568 add
= BitIsSet(opcode
, 23);
7569 wback
= (BitIsClear(opcode
, 24) || BitIsSet(opcode
, 21));
7571 // if t == 15 || (wback && n == t) then UNPREDICTABLE;
7572 if ((t
== 15) || (wback
&& (n
== t
)))
7582 uint64_t Rn
= ReadCoreReg(n
, &success
);
7589 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
7591 offset_addr
= Rn
+ imm32
;
7593 offset_addr
= Rn
- imm32
;
7595 // address = if index then offset_addr else R[n];
7597 address
= offset_addr
;
7601 // R[t] = SignExtend(MemU[address,1], 32);
7602 std::optional
<RegisterInfo
> base_reg
=
7603 GetRegisterInfo(eRegisterKindDWARF
, dwarf_r0
+ n
);
7605 EmulateInstruction::Context context
;
7606 context
.type
= eContextRegisterLoad
;
7607 context
.SetRegisterPlusOffset(*base_reg
, address
- Rn
);
7609 uint64_t unsigned_data
= MemURead(context
, address
, 1, 0, &success
);
7613 int64_t signed_data
= llvm::SignExtend64
<8>(unsigned_data
);
7614 if (!WriteRegisterUnsigned(context
, eRegisterKindDWARF
, dwarf_r0
+ t
,
7615 (uint64_t)signed_data
))
7618 // if wback then R[n] = offset_addr;
7620 context
.type
= eContextAdjustBaseRegister
;
7621 context
.SetAddress(offset_addr
);
7622 if (!WriteRegisterUnsigned(context
, eRegisterKindDWARF
, dwarf_r0
+ n
,
7631 // LDRSB (literal) calculates an address from the PC value and an immediate
7632 // offset, loads a byte from memory,
7633 // sign-extends it to form a 32-bit word, and writes tit to a register.
7634 bool EmulateInstructionARM::EmulateLDRSBLiteral(const uint32_t opcode
,
7635 const ARMEncoding encoding
) {
7637 if ConditionPassed() then
7638 EncodingSpecificOperations(); NullCheckIfThumbEE(15);
7640 address
= if add
then (base
+ imm32
) else (base
- imm32
);
7641 R
[t
] = SignExtend(MemU
[address
,1], 32);
7644 bool success
= false;
7646 if (ConditionPassed(opcode
)) {
7651 // EncodingSpecificOperations(); NullCheckIfThumbEE(15);
7654 // if Rt == '1111' then SEE PLI;
7655 // t = UInt(Rt); imm32 = ZeroExtend(imm12, 32); add = (U == '1');
7656 t
= Bits32(opcode
, 15, 12);
7657 imm32
= Bits32(opcode
, 11, 0);
7658 add
= BitIsSet(opcode
, 23);
7660 // if t == 13 then UNPREDICTABLE;
7667 // t == UInt(Rt); imm32 = ZeroExtend(imm4H:imm4L, 32); add = (U == '1');
7668 t
= Bits32(opcode
, 15, 12);
7669 uint32_t imm4H
= Bits32(opcode
, 11, 8);
7670 uint32_t imm4L
= Bits32(opcode
, 3, 0);
7671 imm32
= (imm4H
<< 4) | imm4L
;
7672 add
= BitIsSet(opcode
, 23);
7674 // if t == 15 then UNPREDICTABLE;
7685 // base = Align(PC,4);
7686 uint64_t pc_value
= ReadCoreReg(PC_REG
, &success
);
7689 uint64_t base
= AlignPC(pc_value
);
7691 // address = if add then (base + imm32) else (base - imm32);
7694 address
= base
+ imm32
;
7696 address
= base
- imm32
;
7698 // R[t] = SignExtend(MemU[address,1], 32);
7699 std::optional
<RegisterInfo
> base_reg
=
7700 GetRegisterInfo(eRegisterKindGeneric
, LLDB_REGNUM_GENERIC_PC
);
7702 EmulateInstruction::Context context
;
7703 context
.type
= eContextRegisterLoad
;
7704 context
.SetRegisterPlusOffset(*base_reg
, address
- base
);
7706 uint64_t unsigned_data
= MemURead(context
, address
, 1, 0, &success
);
7710 int64_t signed_data
= llvm::SignExtend64
<8>(unsigned_data
);
7711 if (!WriteRegisterUnsigned(context
, eRegisterKindDWARF
, dwarf_r0
+ t
,
7712 (uint64_t)signed_data
))
7718 // LDRSB (register) calculates an address from a base register value and an
7719 // offset register value, loadsa byte from
7720 // memory, sign-extends it to form a 32-bit word, and writes it to a register.
7721 // The offset register value can be shifted left by 0, 1, 2, or 3 bits.
7722 bool EmulateInstructionARM::EmulateLDRSBRegister(const uint32_t opcode
,
7723 const ARMEncoding encoding
) {
7725 if ConditionPassed() then
7726 EncodingSpecificOperations(); NullCheckIfThumbEE(n
);
7727 offset
= Shift(R
[m
], shift_t
, shift_n
, APSR
.C
);
7728 offset_addr
= if add
then (R
[n
] + offset
) else (R
[n
] - offset
);
7729 address
= if index then offset_addr
else R
[n
];
7730 R
[t
] = SignExtend(MemU
[address
,1], 32);
7731 if wback then R
[n
] = offset_addr
;
7734 bool success
= false;
7736 if (ConditionPassed(opcode
)) {
7743 ARM_ShifterType shift_t
;
7746 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
7749 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
7750 t
= Bits32(opcode
, 2, 0);
7751 n
= Bits32(opcode
, 5, 3);
7752 m
= Bits32(opcode
, 8, 6);
7754 // index = TRUE; add = TRUE; wback = FALSE;
7759 // (shift_t, shift_n) = (SRType_LSL, 0);
7760 shift_t
= SRType_LSL
;
7766 // if Rt == '1111' then SEE PLI;
7767 // if Rn == '1111' then SEE LDRSB (literal);
7768 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
7769 t
= Bits32(opcode
, 15, 12);
7770 n
= Bits32(opcode
, 19, 16);
7771 m
= Bits32(opcode
, 3, 0);
7773 // index = TRUE; add = TRUE; wback = FALSE;
7778 // (shift_t, shift_n) = (SRType_LSL, UInt(imm2));
7779 shift_t
= SRType_LSL
;
7780 shift_n
= Bits32(opcode
, 5, 4);
7782 // if t == 13 || BadReg(m) then UNPREDICTABLE;
7783 if ((t
== 13) || BadReg(m
))
7788 // if P == '0' && W == '1' then SEE LDRSBT;
7789 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
7790 t
= Bits32(opcode
, 15, 12);
7791 n
= Bits32(opcode
, 19, 16);
7792 m
= Bits32(opcode
, 3, 0);
7794 // index = (P == '1'); add = (U == '1'); wback = (P == '0') ||
7796 index
= BitIsSet(opcode
, 24);
7797 add
= BitIsSet(opcode
, 23);
7798 wback
= BitIsClear(opcode
, 24) || BitIsSet(opcode
, 21);
7800 // (shift_t, shift_n) = (SRType_LSL, 0);
7801 shift_t
= SRType_LSL
;
7804 // if t == 15 || m == 15 then UNPREDICTABLE;
7805 if ((t
== 15) || (m
== 15))
7808 // if wback && (n == 15 || n == t) then UNPREDICTABLE;
7809 if (wback
&& ((n
== 15) || (n
== t
)))
7818 ReadRegisterUnsigned(eRegisterKindDWARF
, dwarf_r0
+ m
, 0, &success
);
7822 // offset = Shift(R[m], shift_t, shift_n, APSR.C);
7823 addr_t offset
= Shift(Rm
, shift_t
, shift_n
, APSR_C
, &success
);
7830 // offset_addr = if add then (R[n] + offset) else (R[n] - offset);
7832 ReadRegisterUnsigned(eRegisterKindDWARF
, dwarf_r0
+ n
, 0, &success
);
7837 offset_addr
= Rn
+ offset
;
7839 offset_addr
= Rn
- offset
;
7841 // address = if index then offset_addr else R[n];
7843 address
= offset_addr
;
7847 // R[t] = SignExtend(MemU[address,1], 32);
7848 std::optional
<RegisterInfo
> base_reg
=
7849 GetRegisterInfo(eRegisterKindDWARF
, dwarf_r0
+ n
);
7850 std::optional
<RegisterInfo
> offset_reg
=
7851 GetRegisterInfo(eRegisterKindDWARF
, dwarf_r0
+ m
);
7853 EmulateInstruction::Context context
;
7854 context
.type
= eContextRegisterLoad
;
7855 context
.SetRegisterPlusIndirectOffset(*base_reg
, *offset_reg
);
7857 uint64_t unsigned_data
= MemURead(context
, address
, 1, 0, &success
);
7861 int64_t signed_data
= llvm::SignExtend64
<8>(unsigned_data
);
7862 if (!WriteRegisterUnsigned(context
, eRegisterKindDWARF
, dwarf_r0
+ t
,
7863 (uint64_t)signed_data
))
7866 // if wback then R[n] = offset_addr;
7868 context
.type
= eContextAdjustBaseRegister
;
7869 context
.SetAddress(offset_addr
);
7870 if (!WriteRegisterUnsigned(context
, eRegisterKindDWARF
, dwarf_r0
+ n
,
7878 // LDRSH (immediate) calculates an address from a base register value and an
7879 // immediate offset, loads a halfword from
7880 // memory, sign-extends it to form a 32-bit word, and writes it to a register.
7881 // It can use offset, post-indexed, or pre-indexed addressing.
7882 bool EmulateInstructionARM::EmulateLDRSHImmediate(const uint32_t opcode
,
7883 const ARMEncoding encoding
) {
7885 if ConditionPassed() then
7886 EncodingSpecificOperations(); NullCheckIfThumbEE(n
);
7887 offset_addr
= if add
then (R
[n
] + imm32
) else (R
[n
] - imm32
);
7888 address
= if index then offset_addr
else R
[n
];
7889 data
= MemU
[address
,2];
7890 if wback then R
[n
] = offset_addr
;
7891 if UnalignedSupport() || address
<0> = '0' then
7892 R
[t
] = SignExtend(data
, 32);
7893 else // Can only apply before ARMv7
7894 R
[t
] = bits(32) UNKNOWN
;
7897 bool success
= false;
7899 if (ConditionPassed(opcode
)) {
7907 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
7910 // if Rn == '1111' then SEE LDRSH (literal);
7911 // if Rt == '1111' then SEE "Unallocated memory hints";
7912 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
7913 t
= Bits32(opcode
, 15, 12);
7914 n
= Bits32(opcode
, 19, 16);
7915 imm32
= Bits32(opcode
, 11, 0);
7917 // index = TRUE; add = TRUE; wback = FALSE;
7922 // if t == 13 then UNPREDICTABLE;
7929 // if Rn == '1111' then SEE LDRSH (literal);
7930 // if Rt == '1111' && P == '1' && U == '0' && W == '0' then SEE
7931 // "Unallocated memory hints";
7932 // if P == '1' && U == '1' && W == '0' then SEE LDRSHT;
7933 // if P == '0' && W == '0' then UNDEFINED;
7934 if (BitIsClear(opcode
, 10) && BitIsClear(opcode
, 8))
7937 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32);
7938 t
= Bits32(opcode
, 15, 12);
7939 n
= Bits32(opcode
, 19, 16);
7940 imm32
= Bits32(opcode
, 7, 0);
7942 // index = (P == '1'); add = (U == '1'); wback = (W == '1');
7943 index
= BitIsSet(opcode
, 10);
7944 add
= BitIsSet(opcode
, 9);
7945 wback
= BitIsSet(opcode
, 8);
7947 // if BadReg(t) || (wback && n == t) then UNPREDICTABLE;
7948 if (BadReg(t
) || (wback
&& (n
== t
)))
7954 // if Rn == '1111' then SEE LDRSH (literal);
7955 // if P == '0' && W == '1' then SEE LDRSHT;
7956 // t == UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm4H:imm4L, 32);
7957 t
= Bits32(opcode
, 15, 12);
7958 n
= Bits32(opcode
, 19, 16);
7959 uint32_t imm4H
= Bits32(opcode
, 11, 8);
7960 uint32_t imm4L
= Bits32(opcode
, 3, 0);
7961 imm32
= (imm4H
<< 4) | imm4L
;
7963 // index = (P == '1'); add = (U == '1'); wback = (P == '0') ||
7965 index
= BitIsSet(opcode
, 24);
7966 add
= BitIsSet(opcode
, 23);
7967 wback
= BitIsClear(opcode
, 24) || BitIsSet(opcode
, 21);
7969 // if t == 15 || (wback && n == t) then UNPREDICTABLE;
7970 if ((t
== 15) || (wback
&& (n
== t
)))
7980 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
7982 ReadRegisterUnsigned(eRegisterKindDWARF
, dwarf_r0
+ n
, 0, &success
);
7988 offset_addr
= Rn
+ imm32
;
7990 offset_addr
= Rn
- imm32
;
7992 // address = if index then offset_addr else R[n];
7995 address
= offset_addr
;
7999 // data = MemU[address,2];
8000 std::optional
<RegisterInfo
> base_reg
=
8001 GetRegisterInfo(eRegisterKindDWARF
, dwarf_r0
+ n
);
8003 EmulateInstruction::Context context
;
8004 context
.type
= eContextRegisterLoad
;
8005 context
.SetRegisterPlusOffset(*base_reg
, address
- Rn
);
8007 uint64_t data
= MemURead(context
, address
, 2, 0, &success
);
8011 // if wback then R[n] = offset_addr;
8013 context
.type
= eContextAdjustBaseRegister
;
8014 context
.SetAddress(offset_addr
);
8015 if (!WriteRegisterUnsigned(context
, eRegisterKindDWARF
, dwarf_r0
+ n
,
8020 // if UnalignedSupport() || address<0> = '0' then
8021 if (UnalignedSupport() || BitIsClear(address
, 0)) {
8022 // R[t] = SignExtend(data, 32);
8023 int64_t signed_data
= llvm::SignExtend64
<16>(data
);
8024 context
.type
= eContextRegisterLoad
;
8025 context
.SetRegisterPlusOffset(*base_reg
, address
- Rn
);
8026 if (!WriteRegisterUnsigned(context
, eRegisterKindDWARF
, dwarf_r0
+ t
,
8027 (uint64_t)signed_data
))
8029 } else // Can only apply before ARMv7
8031 // R[t] = bits(32) UNKNOWN;
8032 WriteBits32Unknown(t
);
8038 // LDRSH (literal) calculates an address from the PC value and an immediate
8039 // offset, loads a halfword from memory,
8040 // sign-extends it to from a 32-bit word, and writes it to a register.
8041 bool EmulateInstructionARM::EmulateLDRSHLiteral(const uint32_t opcode
,
8042 const ARMEncoding encoding
) {
8044 if ConditionPassed() then
8045 EncodingSpecificOperations(); NullCheckIfThumbEE(15);
8047 address
= if add
then (base
+ imm32
) else (base
- imm32
);
8048 data
= MemU
[address
,2];
8049 if UnalignedSupport() || address
<0> = '0' then
8050 R
[t
] = SignExtend(data
, 32);
8051 else // Can only apply before ARMv7
8052 R
[t
] = bits(32) UNKNOWN
;
8055 bool success
= false;
8057 if (ConditionPassed(opcode
)) {
8062 // EncodingSpecificOperations(); NullCheckIfThumbEE(15);
8065 // if Rt == '1111' then SEE "Unallocated memory hints";
8066 // t = UInt(Rt); imm32 = ZeroExtend(imm12, 32); add = (U == '1');
8067 t
= Bits32(opcode
, 15, 12);
8068 imm32
= Bits32(opcode
, 11, 0);
8069 add
= BitIsSet(opcode
, 23);
8071 // if t == 13 then UNPREDICTABLE;
8078 // t == UInt(Rt); imm32 = ZeroExtend(imm4H:imm4L, 32); add = (U == '1');
8079 t
= Bits32(opcode
, 15, 12);
8080 uint32_t imm4H
= Bits32(opcode
, 11, 8);
8081 uint32_t imm4L
= Bits32(opcode
, 3, 0);
8082 imm32
= (imm4H
<< 4) | imm4L
;
8083 add
= BitIsSet(opcode
, 23);
8085 // if t == 15 then UNPREDICTABLE;
8095 // base = Align(PC,4);
8096 uint64_t pc_value
= ReadCoreReg(PC_REG
, &success
);
8100 uint64_t base
= AlignPC(pc_value
);
8103 // address = if add then (base + imm32) else (base - imm32);
8105 address
= base
+ imm32
;
8107 address
= base
- imm32
;
8109 // data = MemU[address,2];
8110 std::optional
<RegisterInfo
> base_reg
=
8111 GetRegisterInfo(eRegisterKindGeneric
, LLDB_REGNUM_GENERIC_PC
);
8113 EmulateInstruction::Context context
;
8114 context
.type
= eContextRegisterLoad
;
8115 context
.SetRegisterPlusOffset(*base_reg
, imm32
);
8117 uint64_t data
= MemURead(context
, address
, 2, 0, &success
);
8121 // if UnalignedSupport() || address<0> = '0' then
8122 if (UnalignedSupport() || BitIsClear(address
, 0)) {
8123 // R[t] = SignExtend(data, 32);
8124 int64_t signed_data
= llvm::SignExtend64
<16>(data
);
8125 if (!WriteRegisterUnsigned(context
, eRegisterKindDWARF
, dwarf_r0
+ t
,
8126 (uint64_t)signed_data
))
8128 } else // Can only apply before ARMv7
8130 // R[t] = bits(32) UNKNOWN;
8131 WriteBits32Unknown(t
);
8137 // LDRSH (register) calculates an address from a base register value and an
8138 // offset register value, loads a halfword
8139 // from memory, sign-extends it to form a 32-bit word, and writes it to a
8140 // register. The offset register value can be shifted left by 0, 1, 2, or 3
8142 bool EmulateInstructionARM::EmulateLDRSHRegister(const uint32_t opcode
,
8143 const ARMEncoding encoding
) {
8145 if ConditionPassed() then
8146 EncodingSpecificOperations(); NullCheckIfThumbEE(n
);
8147 offset
= Shift(R
[m
], shift_t
, shift_n
, APSR
.C
);
8148 offset_addr
= if add
then (R
[n
] + offset
) else (R
[n
] - offset
);
8149 address
= if index then offset_addr
else R
[n
];
8150 data
= MemU
[address
,2];
8151 if wback then R
[n
] = offset_addr
;
8152 if UnalignedSupport() || address
<0> = '0' then
8153 R
[t
] = SignExtend(data
, 32);
8154 else // Can only apply before ARMv7
8155 R
[t
] = bits(32) UNKNOWN
;
8158 bool success
= false;
8160 if (ConditionPassed(opcode
)) {
8167 ARM_ShifterType shift_t
;
8170 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
8173 // if CurrentInstrSet() == InstrSet_ThumbEE then SEE "Modified operation
8175 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
8176 t
= Bits32(opcode
, 2, 0);
8177 n
= Bits32(opcode
, 5, 3);
8178 m
= Bits32(opcode
, 8, 6);
8180 // index = TRUE; add = TRUE; wback = FALSE;
8185 // (shift_t, shift_n) = (SRType_LSL, 0);
8186 shift_t
= SRType_LSL
;
8192 // if Rn == '1111' then SEE LDRSH (literal);
8193 // if Rt == '1111' then SEE "Unallocated memory hints";
8194 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
8195 t
= Bits32(opcode
, 15, 12);
8196 n
= Bits32(opcode
, 19, 16);
8197 m
= Bits32(opcode
, 3, 0);
8199 // index = TRUE; add = TRUE; wback = FALSE;
8204 // (shift_t, shift_n) = (SRType_LSL, UInt(imm2));
8205 shift_t
= SRType_LSL
;
8206 shift_n
= Bits32(opcode
, 5, 4);
8208 // if t == 13 || BadReg(m) then UNPREDICTABLE;
8209 if ((t
== 13) || BadReg(m
))
8215 // if P == '0' && W == '1' then SEE LDRSHT;
8216 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
8217 t
= Bits32(opcode
, 15, 12);
8218 n
= Bits32(opcode
, 19, 16);
8219 m
= Bits32(opcode
, 3, 0);
8221 // index = (P == '1'); add = (U == '1'); wback = (P == '0') ||
8223 index
= BitIsSet(opcode
, 24);
8224 add
= BitIsSet(opcode
, 23);
8225 wback
= BitIsClear(opcode
, 24) || BitIsSet(opcode
, 21);
8227 // (shift_t, shift_n) = (SRType_LSL, 0);
8228 shift_t
= SRType_LSL
;
8231 // if t == 15 || m == 15 then UNPREDICTABLE;
8232 if ((t
== 15) || (m
== 15))
8235 // if wback && (n == 15 || n == t) then UNPREDICTABLE;
8236 if (wback
&& ((n
== 15) || (n
== t
)))
8246 ReadRegisterUnsigned(eRegisterKindDWARF
, dwarf_r0
+ m
, 0, &success
);
8251 ReadRegisterUnsigned(eRegisterKindDWARF
, dwarf_r0
+ n
, 0, &success
);
8255 // offset = Shift(R[m], shift_t, shift_n, APSR.C);
8256 addr_t offset
= Shift(Rm
, shift_t
, shift_n
, APSR_C
, &success
);
8263 // offset_addr = if add then (R[n] + offset) else (R[n] - offset);
8265 offset_addr
= Rn
+ offset
;
8267 offset_addr
= Rn
- offset
;
8269 // address = if index then offset_addr else R[n];
8271 address
= offset_addr
;
8275 // data = MemU[address,2];
8276 std::optional
<RegisterInfo
> base_reg
=
8277 GetRegisterInfo(eRegisterKindDWARF
, dwarf_r0
+ n
);
8278 std::optional
<RegisterInfo
> offset_reg
=
8279 GetRegisterInfo(eRegisterKindDWARF
, dwarf_r0
+ m
);
8281 EmulateInstruction::Context context
;
8282 context
.type
= eContextRegisterLoad
;
8283 context
.SetRegisterPlusIndirectOffset(*base_reg
, *offset_reg
);
8285 uint64_t data
= MemURead(context
, address
, 2, 0, &success
);
8289 // if wback then R[n] = offset_addr;
8291 context
.type
= eContextAdjustBaseRegister
;
8292 context
.SetAddress(offset_addr
);
8293 if (!WriteRegisterUnsigned(context
, eRegisterKindDWARF
, dwarf_r0
+ n
,
8298 // if UnalignedSupport() || address<0> = '0' then
8299 if (UnalignedSupport() || BitIsClear(address
, 0)) {
8300 // R[t] = SignExtend(data, 32);
8301 context
.type
= eContextRegisterLoad
;
8302 context
.SetRegisterPlusIndirectOffset(*base_reg
, *offset_reg
);
8304 int64_t signed_data
= llvm::SignExtend64
<16>(data
);
8305 if (!WriteRegisterUnsigned(context
, eRegisterKindDWARF
, dwarf_r0
+ t
,
8306 (uint64_t)signed_data
))
8308 } else // Can only apply before ARMv7
8310 // R[t] = bits(32) UNKNOWN;
8311 WriteBits32Unknown(t
);
8317 // SXTB extracts an 8-bit value from a register, sign-extends it to 32 bits, and
8318 // writes the result to the destination
8319 // register. You can specifiy a rotation by 0, 8, 16, or 24 bits before
8320 // extracting the 8-bit value.
8321 bool EmulateInstructionARM::EmulateSXTB(const uint32_t opcode
,
8322 const ARMEncoding encoding
) {
8324 if ConditionPassed() then
8325 EncodingSpecificOperations();
8326 rotated
= ROR(R
[m
], rotation
);
8327 R
[d
] = SignExtend(rotated
<7:0>, 32);
8330 bool success
= false;
8332 if (ConditionPassed(opcode
)) {
8337 // EncodingSpecificOperations();
8340 // d = UInt(Rd); m = UInt(Rm); rotation = 0;
8341 d
= Bits32(opcode
, 2, 0);
8342 m
= Bits32(opcode
, 5, 3);
8348 // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:'000');
8349 d
= Bits32(opcode
, 11, 8);
8350 m
= Bits32(opcode
, 3, 0);
8351 rotation
= Bits32(opcode
, 5, 4) << 3;
8353 // if BadReg(d) || BadReg(m) then UNPREDICTABLE;
8354 if (BadReg(d
) || BadReg(m
))
8360 // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:'000');
8361 d
= Bits32(opcode
, 15, 12);
8362 m
= Bits32(opcode
, 3, 0);
8363 rotation
= Bits32(opcode
, 11, 10) << 3;
8365 // if d == 15 || m == 15 then UNPREDICTABLE;
8366 if ((d
== 15) || (m
== 15))
8376 ReadRegisterUnsigned(eRegisterKindDWARF
, dwarf_r0
+ m
, 0, &success
);
8380 // rotated = ROR(R[m], rotation);
8381 uint64_t rotated
= ROR(Rm
, rotation
, &success
);
8385 // R[d] = SignExtend(rotated<7:0>, 32);
8386 int64_t data
= llvm::SignExtend64
<8>(rotated
);
8388 std::optional
<RegisterInfo
> source_reg
=
8389 GetRegisterInfo(eRegisterKindDWARF
, dwarf_r0
+ m
);
8391 EmulateInstruction::Context context
;
8392 context
.type
= eContextRegisterLoad
;
8393 context
.SetRegister(*source_reg
);
8395 if (!WriteRegisterUnsigned(context
, eRegisterKindDWARF
, dwarf_r0
+ d
,
8402 // SXTH extracts a 16-bit value from a register, sign-extends it to 32 bits, and
8403 // writes the result to the destination
8404 // register. You can specify a rotation by 0, 8, 16, or 24 bits before
8405 // extracting the 16-bit value.
8406 bool EmulateInstructionARM::EmulateSXTH(const uint32_t opcode
,
8407 const ARMEncoding encoding
) {
8409 if ConditionPassed() then
8410 EncodingSpecificOperations();
8411 rotated
= ROR(R
[m
], rotation
);
8412 R
[d
] = SignExtend(rotated
<15:0>, 32);
8415 bool success
= false;
8417 if (ConditionPassed(opcode
)) {
8422 // EncodingSpecificOperations();
8425 // d = UInt(Rd); m = UInt(Rm); rotation = 0;
8426 d
= Bits32(opcode
, 2, 0);
8427 m
= Bits32(opcode
, 5, 3);
8433 // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:'000');
8434 d
= Bits32(opcode
, 11, 8);
8435 m
= Bits32(opcode
, 3, 0);
8436 rotation
= Bits32(opcode
, 5, 4) << 3;
8438 // if BadReg(d) || BadReg(m) then UNPREDICTABLE;
8439 if (BadReg(d
) || BadReg(m
))
8445 // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:'000');
8446 d
= Bits32(opcode
, 15, 12);
8447 m
= Bits32(opcode
, 3, 0);
8448 rotation
= Bits32(opcode
, 11, 10) << 3;
8450 // if d == 15 || m == 15 then UNPREDICTABLE;
8451 if ((d
== 15) || (m
== 15))
8461 ReadRegisterUnsigned(eRegisterKindDWARF
, dwarf_r0
+ m
, 0, &success
);
8465 // rotated = ROR(R[m], rotation);
8466 uint64_t rotated
= ROR(Rm
, rotation
, &success
);
8470 // R[d] = SignExtend(rotated<15:0>, 32);
8471 std::optional
<RegisterInfo
> source_reg
=
8472 GetRegisterInfo(eRegisterKindDWARF
, dwarf_r0
+ m
);
8474 EmulateInstruction::Context context
;
8475 context
.type
= eContextRegisterLoad
;
8476 context
.SetRegister(*source_reg
);
8478 int64_t data
= llvm::SignExtend64
<16>(rotated
);
8479 if (!WriteRegisterUnsigned(context
, eRegisterKindDWARF
, dwarf_r0
+ d
,
8487 // UXTB extracts an 8-bit value from a register, zero-extends it to 32 bits, and
8488 // writes the result to the destination
8489 // register. You can specify a rotation by 0, 8, 16, or 24 bits before
8490 // extracting the 8-bit value.
8491 bool EmulateInstructionARM::EmulateUXTB(const uint32_t opcode
,
8492 const ARMEncoding encoding
) {
8494 if ConditionPassed() then
8495 EncodingSpecificOperations();
8496 rotated
= ROR(R
[m
], rotation
);
8497 R
[d
] = ZeroExtend(rotated
<7:0>, 32);
8500 bool success
= false;
8502 if (ConditionPassed(opcode
)) {
8507 // EncodingSpecificOperations();
8510 // d = UInt(Rd); m = UInt(Rm); rotation = 0;
8511 d
= Bits32(opcode
, 2, 0);
8512 m
= Bits32(opcode
, 5, 3);
8518 // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:'000');
8519 d
= Bits32(opcode
, 11, 8);
8520 m
= Bits32(opcode
, 3, 0);
8521 rotation
= Bits32(opcode
, 5, 4) << 3;
8523 // if BadReg(d) || BadReg(m) then UNPREDICTABLE;
8524 if (BadReg(d
) || BadReg(m
))
8530 // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:'000');
8531 d
= Bits32(opcode
, 15, 12);
8532 m
= Bits32(opcode
, 3, 0);
8533 rotation
= Bits32(opcode
, 11, 10) << 3;
8535 // if d == 15 || m == 15 then UNPREDICTABLE;
8536 if ((d
== 15) || (m
== 15))
8546 ReadRegisterUnsigned(eRegisterKindDWARF
, dwarf_r0
+ m
, 0, &success
);
8550 // rotated = ROR(R[m], rotation);
8551 uint64_t rotated
= ROR(Rm
, rotation
, &success
);
8555 // R[d] = ZeroExtend(rotated<7:0>, 32);
8556 std::optional
<RegisterInfo
> source_reg
=
8557 GetRegisterInfo(eRegisterKindDWARF
, dwarf_r0
+ m
);
8559 EmulateInstruction::Context context
;
8560 context
.type
= eContextRegisterLoad
;
8561 context
.SetRegister(*source_reg
);
8563 if (!WriteRegisterUnsigned(context
, eRegisterKindDWARF
, dwarf_r0
+ d
,
8564 Bits32(rotated
, 7, 0)))
8570 // UXTH extracts a 16-bit value from a register, zero-extends it to 32 bits, and
8571 // writes the result to the destination
8572 // register. You can specify a rotation by 0, 8, 16, or 24 bits before
8573 // extracting the 16-bit value.
8574 bool EmulateInstructionARM::EmulateUXTH(const uint32_t opcode
,
8575 const ARMEncoding encoding
) {
8577 if ConditionPassed() then
8578 EncodingSpecificOperations();
8579 rotated
= ROR(R
[m
], rotation
);
8580 R
[d
] = ZeroExtend(rotated
<15:0>, 32);
8583 bool success
= false;
8585 if (ConditionPassed(opcode
)) {
8592 // d = UInt(Rd); m = UInt(Rm); rotation = 0;
8593 d
= Bits32(opcode
, 2, 0);
8594 m
= Bits32(opcode
, 5, 3);
8600 // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:'000');
8601 d
= Bits32(opcode
, 11, 8);
8602 m
= Bits32(opcode
, 3, 0);
8603 rotation
= Bits32(opcode
, 5, 4) << 3;
8605 // if BadReg(d) || BadReg(m) then UNPREDICTABLE;
8606 if (BadReg(d
) || BadReg(m
))
8612 // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:'000');
8613 d
= Bits32(opcode
, 15, 12);
8614 m
= Bits32(opcode
, 3, 0);
8615 rotation
= Bits32(opcode
, 11, 10) << 3;
8617 // if d == 15 || m == 15 then UNPREDICTABLE;
8618 if ((d
== 15) || (m
== 15))
8628 ReadRegisterUnsigned(eRegisterKindDWARF
, dwarf_r0
+ m
, 0, &success
);
8632 // rotated = ROR(R[m], rotation);
8633 uint64_t rotated
= ROR(Rm
, rotation
, &success
);
8637 // R[d] = ZeroExtend(rotated<15:0>, 32);
8638 std::optional
<RegisterInfo
> source_reg
=
8639 GetRegisterInfo(eRegisterKindDWARF
, dwarf_r0
+ m
);
8641 EmulateInstruction::Context context
;
8642 context
.type
= eContextRegisterLoad
;
8643 context
.SetRegister(*source_reg
);
8645 if (!WriteRegisterUnsigned(context
, eRegisterKindDWARF
, dwarf_r0
+ d
,
8646 Bits32(rotated
, 15, 0)))
8652 // RFE (Return From Exception) loads the PC and the CPSR from the word at the
8653 // specified address and the following
8654 // word respectively.
8655 bool EmulateInstructionARM::EmulateRFE(const uint32_t opcode
,
8656 const ARMEncoding encoding
) {
8658 if ConditionPassed() then
8659 EncodingSpecificOperations();
8660 if !CurrentModeIsPrivileged() || CurrentInstrSet() == InstrSet_ThumbEE then
8663 address
= if increment then R
[n
] else R
[n
]-8;
8664 if wordhigher then address
= address
+4;
8665 CPSRWriteByInstr(MemA
[address
+4,4], '1111', TRUE
);
8666 BranchWritePC(MemA
[address
,4]);
8667 if wback then R
[n
] = if increment then R
[n
]+8 else R
[n
]-8;
8670 bool success
= false;
8672 if (ConditionPassed(opcode
)) {
8678 // EncodingSpecificOperations();
8681 // n = UInt(Rn); wback = (W == '1'); increment = FALSE; wordhigher =
8683 n
= Bits32(opcode
, 19, 16);
8684 wback
= BitIsSet(opcode
, 21);
8688 // if n == 15 then UNPREDICTABLE;
8692 // if InITBlock() && !LastInITBlock() then UNPREDICTABLE;
8693 if (InITBlock() && !LastInITBlock())
8699 // n = UInt(Rn); wback = (W == '1'); increment = TRUE; wordhigher = FALSE;
8700 n
= Bits32(opcode
, 19, 16);
8701 wback
= BitIsSet(opcode
, 21);
8705 // if n == 15 then UNPREDICTABLE;
8709 // if InITBlock() && !LastInITBlock() then UNPREDICTABLE;
8710 if (InITBlock() && !LastInITBlock())
8717 n
= Bits32(opcode
, 19, 16);
8719 // wback = (W == '1'); inc = (U == '1'); wordhigher = (P == U);
8720 wback
= BitIsSet(opcode
, 21);
8721 increment
= BitIsSet(opcode
, 23);
8722 wordhigher
= (Bit32(opcode
, 24) == Bit32(opcode
, 23));
8724 // if n == 15 then UNPREDICTABLE;
8734 // if !CurrentModeIsPrivileged() || CurrentInstrSet() == InstrSet_ThumbEE
8736 if (!CurrentModeIsPrivileged())
8741 ReadRegisterUnsigned(eRegisterKindDWARF
, dwarf_r0
+ n
, 0, &success
);
8746 // address = if increment then R[n] else R[n]-8;
8752 // if wordhigher then address = address+4;
8754 address
= address
+ 4;
8756 // CPSRWriteByInstr(MemA[address+4,4], '1111', TRUE);
8757 std::optional
<RegisterInfo
> base_reg
=
8758 GetRegisterInfo(eRegisterKindDWARF
, dwarf_r0
+ n
);
8760 EmulateInstruction::Context context
;
8761 context
.type
= eContextReturnFromException
;
8762 context
.SetRegisterPlusOffset(*base_reg
, address
- Rn
);
8764 uint64_t data
= MemARead(context
, address
+ 4, 4, 0, &success
);
8768 CPSRWriteByInstr(data
, 15, true);
8770 // BranchWritePC(MemA[address,4]);
8771 uint64_t data2
= MemARead(context
, address
, 4, 0, &success
);
8775 BranchWritePC(context
, data2
);
8777 // if wback then R[n] = if increment then R[n]+8 else R[n]-8;
8779 context
.type
= eContextAdjustBaseRegister
;
8781 context
.SetOffset(8);
8782 if (!WriteRegisterUnsigned(context
, eRegisterKindDWARF
, dwarf_r0
+ n
,
8786 context
.SetOffset(-8);
8787 if (!WriteRegisterUnsigned(context
, eRegisterKindDWARF
, dwarf_r0
+ n
,
8793 } // if ConditionPassed()
8797 // Bitwise Exclusive OR (immediate) performs a bitwise exclusive OR of a
8798 // register value and an immediate value, and writes the result to the
8799 // destination register. It can optionally update the condition flags based on
8801 bool EmulateInstructionARM::EmulateEORImm(const uint32_t opcode
,
8802 const ARMEncoding encoding
) {
8804 // ARM pseudo code...
8805 if ConditionPassed() then
8806 EncodingSpecificOperations();
8807 result
= R
[n
] EOR imm32
;
8808 if d
== 15 then
// Can only occur for ARM encoding
8809 ALUWritePC(result
); // setflags is always FALSE here
8813 APSR
.N
= result
<31>;
8814 APSR
.Z
= IsZeroBit(result
);
8819 bool success
= false;
8821 if (ConditionPassed(opcode
)) {
8824 imm32
; // the immediate value to be ORed to the value obtained from Rn
8826 uint32_t carry
; // the carry bit after ARM/Thumb Expand operation
8829 Rd
= Bits32(opcode
, 11, 8);
8830 Rn
= Bits32(opcode
, 19, 16);
8831 setflags
= BitIsSet(opcode
, 20);
8832 imm32
= ThumbExpandImm_C(
8834 carry
); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C)
8835 // if Rd == '1111' && S == '1' then SEE TEQ (immediate);
8836 if (Rd
== 15 && setflags
)
8837 return EmulateTEQImm(opcode
, eEncodingT1
);
8838 if (Rd
== 13 || (Rd
== 15 && !setflags
) || BadReg(Rn
))
8842 Rd
= Bits32(opcode
, 15, 12);
8843 Rn
= Bits32(opcode
, 19, 16);
8844 setflags
= BitIsSet(opcode
, 20);
8846 ARMExpandImm_C(opcode
, APSR_C
,
8847 carry
); // (imm32, carry) = ARMExpandImm(imm12, APSR.C)
8849 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related
8851 if (Rd
== 15 && setflags
)
8852 return EmulateSUBSPcLrEtc(opcode
, encoding
);
8858 // Read the first operand.
8859 uint32_t val1
= ReadCoreReg(Rn
, &success
);
8863 uint32_t result
= val1
^ imm32
;
8865 EmulateInstruction::Context context
;
8866 context
.type
= EmulateInstruction::eContextImmediate
;
8867 context
.SetNoArgs();
8869 if (!WriteCoreRegOptionalFlags(context
, result
, Rd
, setflags
, carry
))
8875 // Bitwise Exclusive OR (register) performs a bitwise exclusive OR of a
8876 // register value and an optionally-shifted register value, and writes the
8877 // result to the destination register. It can optionally update the condition
8878 // flags based on the result.
8879 bool EmulateInstructionARM::EmulateEORReg(const uint32_t opcode
,
8880 const ARMEncoding encoding
) {
8882 // ARM pseudo code...
8883 if ConditionPassed() then
8884 EncodingSpecificOperations();
8885 (shifted
, carry
) = Shift_C(R
[m
], shift_t
, shift_n
, APSR
.C
);
8886 result
= R
[n
] EOR shifted
;
8887 if d
== 15 then
// Can only occur for ARM encoding
8888 ALUWritePC(result
); // setflags is always FALSE here
8892 APSR
.N
= result
<31>;
8893 APSR
.Z
= IsZeroBit(result
);
8898 bool success
= false;
8900 if (ConditionPassed(opcode
)) {
8901 uint32_t Rd
, Rn
, Rm
;
8902 ARM_ShifterType shift_t
;
8903 uint32_t shift_n
; // the shift applied to the value read from Rm
8908 Rd
= Rn
= Bits32(opcode
, 2, 0);
8909 Rm
= Bits32(opcode
, 5, 3);
8910 setflags
= !InITBlock();
8911 shift_t
= SRType_LSL
;
8915 Rd
= Bits32(opcode
, 11, 8);
8916 Rn
= Bits32(opcode
, 19, 16);
8917 Rm
= Bits32(opcode
, 3, 0);
8918 setflags
= BitIsSet(opcode
, 20);
8919 shift_n
= DecodeImmShiftThumb(opcode
, shift_t
);
8920 // if Rd == '1111' && S == '1' then SEE TEQ (register);
8921 if (Rd
== 15 && setflags
)
8922 return EmulateTEQReg(opcode
, eEncodingT1
);
8923 if (Rd
== 13 || (Rd
== 15 && !setflags
) || BadReg(Rn
) || BadReg(Rm
))
8927 Rd
= Bits32(opcode
, 15, 12);
8928 Rn
= Bits32(opcode
, 19, 16);
8929 Rm
= Bits32(opcode
, 3, 0);
8930 setflags
= BitIsSet(opcode
, 20);
8931 shift_n
= DecodeImmShiftARM(opcode
, shift_t
);
8933 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related
8935 if (Rd
== 15 && setflags
)
8936 return EmulateSUBSPcLrEtc(opcode
, encoding
);
8942 // Read the first operand.
8943 uint32_t val1
= ReadCoreReg(Rn
, &success
);
8947 // Read the second operand.
8948 uint32_t val2
= ReadCoreReg(Rm
, &success
);
8952 uint32_t shifted
= Shift_C(val2
, shift_t
, shift_n
, APSR_C
, carry
, &success
);
8955 uint32_t result
= val1
^ shifted
;
8957 EmulateInstruction::Context context
;
8958 context
.type
= EmulateInstruction::eContextImmediate
;
8959 context
.SetNoArgs();
8961 if (!WriteCoreRegOptionalFlags(context
, result
, Rd
, setflags
, carry
))
8967 // Bitwise OR (immediate) performs a bitwise (inclusive) OR of a register value
8968 // and an immediate value, and writes the result to the destination register.
8969 // It can optionally update the condition flags based on the result.
8970 bool EmulateInstructionARM::EmulateORRImm(const uint32_t opcode
,
8971 const ARMEncoding encoding
) {
8973 // ARM pseudo code...
8974 if ConditionPassed() then
8975 EncodingSpecificOperations();
8976 result
= R
[n
] OR imm32
;
8977 if d
== 15 then
// Can only occur for ARM encoding
8978 ALUWritePC(result
); // setflags is always FALSE here
8982 APSR
.N
= result
<31>;
8983 APSR
.Z
= IsZeroBit(result
);
8988 bool success
= false;
8990 if (ConditionPassed(opcode
)) {
8993 imm32
; // the immediate value to be ORed to the value obtained from Rn
8995 uint32_t carry
; // the carry bit after ARM/Thumb Expand operation
8998 Rd
= Bits32(opcode
, 11, 8);
8999 Rn
= Bits32(opcode
, 19, 16);
9000 setflags
= BitIsSet(opcode
, 20);
9001 imm32
= ThumbExpandImm_C(
9003 carry
); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C)
9004 // if Rn == '1111' then SEE MOV (immediate);
9006 return EmulateMOVRdImm(opcode
, eEncodingT2
);
9007 if (BadReg(Rd
) || Rn
== 13)
9011 Rd
= Bits32(opcode
, 15, 12);
9012 Rn
= Bits32(opcode
, 19, 16);
9013 setflags
= BitIsSet(opcode
, 20);
9015 ARMExpandImm_C(opcode
, APSR_C
,
9016 carry
); // (imm32, carry) = ARMExpandImm(imm12, APSR.C)
9018 if (Rd
== 15 && setflags
)
9019 return EmulateSUBSPcLrEtc(opcode
, encoding
);
9025 // Read the first operand.
9026 uint32_t val1
= ReadCoreReg(Rn
, &success
);
9030 uint32_t result
= val1
| imm32
;
9032 EmulateInstruction::Context context
;
9033 context
.type
= EmulateInstruction::eContextImmediate
;
9034 context
.SetNoArgs();
9036 if (!WriteCoreRegOptionalFlags(context
, result
, Rd
, setflags
, carry
))
9042 // Bitwise OR (register) performs a bitwise (inclusive) OR of a register value
9043 // and an optionally-shifted register value, and writes the result to the
9044 // destination register. It can optionally update the condition flags based on
9046 bool EmulateInstructionARM::EmulateORRReg(const uint32_t opcode
,
9047 const ARMEncoding encoding
) {
9049 // ARM pseudo code...
9050 if ConditionPassed() then
9051 EncodingSpecificOperations();
9052 (shifted
, carry
) = Shift_C(R
[m
], shift_t
, shift_n
, APSR
.C
);
9053 result
= R
[n
] OR shifted
;
9054 if d
== 15 then
// Can only occur for ARM encoding
9055 ALUWritePC(result
); // setflags is always FALSE here
9059 APSR
.N
= result
<31>;
9060 APSR
.Z
= IsZeroBit(result
);
9065 bool success
= false;
9067 if (ConditionPassed(opcode
)) {
9068 uint32_t Rd
, Rn
, Rm
;
9069 ARM_ShifterType shift_t
;
9070 uint32_t shift_n
; // the shift applied to the value read from Rm
9075 Rd
= Rn
= Bits32(opcode
, 2, 0);
9076 Rm
= Bits32(opcode
, 5, 3);
9077 setflags
= !InITBlock();
9078 shift_t
= SRType_LSL
;
9082 Rd
= Bits32(opcode
, 11, 8);
9083 Rn
= Bits32(opcode
, 19, 16);
9084 Rm
= Bits32(opcode
, 3, 0);
9085 setflags
= BitIsSet(opcode
, 20);
9086 shift_n
= DecodeImmShiftThumb(opcode
, shift_t
);
9087 // if Rn == '1111' then SEE MOV (register);
9089 return EmulateMOVRdRm(opcode
, eEncodingT3
);
9090 if (BadReg(Rd
) || Rn
== 13 || BadReg(Rm
))
9094 Rd
= Bits32(opcode
, 15, 12);
9095 Rn
= Bits32(opcode
, 19, 16);
9096 Rm
= Bits32(opcode
, 3, 0);
9097 setflags
= BitIsSet(opcode
, 20);
9098 shift_n
= DecodeImmShiftARM(opcode
, shift_t
);
9100 if (Rd
== 15 && setflags
)
9101 return EmulateSUBSPcLrEtc(opcode
, encoding
);
9107 // Read the first operand.
9108 uint32_t val1
= ReadCoreReg(Rn
, &success
);
9112 // Read the second operand.
9113 uint32_t val2
= ReadCoreReg(Rm
, &success
);
9117 uint32_t shifted
= Shift_C(val2
, shift_t
, shift_n
, APSR_C
, carry
, &success
);
9120 uint32_t result
= val1
| shifted
;
9122 EmulateInstruction::Context context
;
9123 context
.type
= EmulateInstruction::eContextImmediate
;
9124 context
.SetNoArgs();
9126 if (!WriteCoreRegOptionalFlags(context
, result
, Rd
, setflags
, carry
))
9132 // Reverse Subtract (immediate) subtracts a register value from an immediate
9133 // value, and writes the result to the destination register. It can optionally
9134 // update the condition flags based on the result.
9135 bool EmulateInstructionARM::EmulateRSBImm(const uint32_t opcode
,
9136 const ARMEncoding encoding
) {
9138 // ARM pseudo code...
9139 if ConditionPassed() then
9140 EncodingSpecificOperations();
9141 (result
, carry
, overflow
) = AddWithCarry(NOT(R
[n
]), imm32
, '1');
9142 if d
== 15 then
// Can only occur for ARM encoding
9143 ALUWritePC(result
); // setflags is always FALSE here
9147 APSR
.N
= result
<31>;
9148 APSR
.Z
= IsZeroBit(result
);
9153 bool success
= false;
9155 uint32_t Rd
; // the destination register
9156 uint32_t Rn
; // the first operand
9159 imm32
; // the immediate value to be added to the value obtained from Rn
9162 Rd
= Bits32(opcode
, 2, 0);
9163 Rn
= Bits32(opcode
, 5, 3);
9164 setflags
= !InITBlock();
9168 Rd
= Bits32(opcode
, 11, 8);
9169 Rn
= Bits32(opcode
, 19, 16);
9170 setflags
= BitIsSet(opcode
, 20);
9171 imm32
= ThumbExpandImm(opcode
); // imm32 = ThumbExpandImm(i:imm3:imm8)
9172 if (BadReg(Rd
) || BadReg(Rn
))
9176 Rd
= Bits32(opcode
, 15, 12);
9177 Rn
= Bits32(opcode
, 19, 16);
9178 setflags
= BitIsSet(opcode
, 20);
9179 imm32
= ARMExpandImm(opcode
); // imm32 = ARMExpandImm(imm12)
9181 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related
9183 if (Rd
== 15 && setflags
)
9184 return EmulateSUBSPcLrEtc(opcode
, encoding
);
9189 // Read the register value from the operand register Rn.
9190 uint32_t reg_val
= ReadCoreReg(Rn
, &success
);
9194 AddWithCarryResult res
= AddWithCarry(~reg_val
, imm32
, 1);
9196 EmulateInstruction::Context context
;
9197 context
.type
= EmulateInstruction::eContextImmediate
;
9198 context
.SetNoArgs();
9200 return WriteCoreRegOptionalFlags(context
, res
.result
, Rd
, setflags
,
9201 res
.carry_out
, res
.overflow
);
9204 // Reverse Subtract (register) subtracts a register value from an optionally-
9205 // shifted register value, and writes the result to the destination register.
9206 // It can optionally update the condition flags based on the result.
9207 bool EmulateInstructionARM::EmulateRSBReg(const uint32_t opcode
,
9208 const ARMEncoding encoding
) {
9210 // ARM pseudo code...
9211 if ConditionPassed() then
9212 EncodingSpecificOperations();
9213 shifted
= Shift(R
[m
], shift_t
, shift_n
, APSR
.C
);
9214 (result
, carry
, overflow
) = AddWithCarry(NOT(R
[n
]), shifted
, '1');
9215 if d
== 15 then
// Can only occur for ARM encoding
9216 ALUWritePC(result
); // setflags is always FALSE here
9220 APSR
.N
= result
<31>;
9221 APSR
.Z
= IsZeroBit(result
);
9226 bool success
= false;
9228 uint32_t Rd
; // the destination register
9229 uint32_t Rn
; // the first operand
9230 uint32_t Rm
; // the second operand
9232 ARM_ShifterType shift_t
;
9233 uint32_t shift_n
; // the shift applied to the value read from Rm
9236 Rd
= Bits32(opcode
, 11, 8);
9237 Rn
= Bits32(opcode
, 19, 16);
9238 Rm
= Bits32(opcode
, 3, 0);
9239 setflags
= BitIsSet(opcode
, 20);
9240 shift_n
= DecodeImmShiftThumb(opcode
, shift_t
);
9241 // if (BadReg(d) || BadReg(m)) then UNPREDICTABLE;
9242 if (BadReg(Rd
) || BadReg(Rn
) || BadReg(Rm
))
9246 Rd
= Bits32(opcode
, 15, 12);
9247 Rn
= Bits32(opcode
, 19, 16);
9248 Rm
= Bits32(opcode
, 3, 0);
9249 setflags
= BitIsSet(opcode
, 20);
9250 shift_n
= DecodeImmShiftARM(opcode
, shift_t
);
9252 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related
9254 if (Rd
== 15 && setflags
)
9255 return EmulateSUBSPcLrEtc(opcode
, encoding
);
9260 // Read the register value from register Rn.
9261 uint32_t val1
= ReadCoreReg(Rn
, &success
);
9265 // Read the register value from register Rm.
9266 uint32_t val2
= ReadCoreReg(Rm
, &success
);
9270 uint32_t shifted
= Shift(val2
, shift_t
, shift_n
, APSR_C
, &success
);
9273 AddWithCarryResult res
= AddWithCarry(~val1
, shifted
, 1);
9275 EmulateInstruction::Context context
;
9276 context
.type
= EmulateInstruction::eContextImmediate
;
9277 context
.SetNoArgs();
9278 return WriteCoreRegOptionalFlags(context
, res
.result
, Rd
, setflags
,
9279 res
.carry_out
, res
.overflow
);
9282 // Reverse Subtract with Carry (immediate) subtracts a register value and the
9283 // value of NOT (Carry flag) from an immediate value, and writes the result to
9284 // the destination register. It can optionally update the condition flags based
9286 bool EmulateInstructionARM::EmulateRSCImm(const uint32_t opcode
,
9287 const ARMEncoding encoding
) {
9289 // ARM pseudo code...
9290 if ConditionPassed() then
9291 EncodingSpecificOperations();
9292 (result
, carry
, overflow
) = AddWithCarry(NOT(R
[n
]), imm32
, APSR
.C
);
9294 ALUWritePC(result
); // setflags is always FALSE here
9298 APSR
.N
= result
<31>;
9299 APSR
.Z
= IsZeroBit(result
);
9304 bool success
= false;
9306 uint32_t Rd
; // the destination register
9307 uint32_t Rn
; // the first operand
9310 imm32
; // the immediate value to be added to the value obtained from Rn
9313 Rd
= Bits32(opcode
, 15, 12);
9314 Rn
= Bits32(opcode
, 19, 16);
9315 setflags
= BitIsSet(opcode
, 20);
9316 imm32
= ARMExpandImm(opcode
); // imm32 = ARMExpandImm(imm12)
9318 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related
9320 if (Rd
== 15 && setflags
)
9321 return EmulateSUBSPcLrEtc(opcode
, encoding
);
9326 // Read the register value from the operand register Rn.
9327 uint32_t reg_val
= ReadCoreReg(Rn
, &success
);
9331 AddWithCarryResult res
= AddWithCarry(~reg_val
, imm32
, APSR_C
);
9333 EmulateInstruction::Context context
;
9334 context
.type
= EmulateInstruction::eContextImmediate
;
9335 context
.SetNoArgs();
9337 return WriteCoreRegOptionalFlags(context
, res
.result
, Rd
, setflags
,
9338 res
.carry_out
, res
.overflow
);
9341 // Reverse Subtract with Carry (register) subtracts a register value and the
9342 // value of NOT (Carry flag) from an optionally-shifted register value, and
9343 // writes the result to the destination register. It can optionally update the
9344 // condition flags based on the result.
9345 bool EmulateInstructionARM::EmulateRSCReg(const uint32_t opcode
,
9346 const ARMEncoding encoding
) {
9348 // ARM pseudo code...
9349 if ConditionPassed() then
9350 EncodingSpecificOperations();
9351 shifted
= Shift(R
[m
], shift_t
, shift_n
, APSR
.C
);
9352 (result
, carry
, overflow
) = AddWithCarry(NOT(R
[n
]), shifted
, APSR
.C
);
9354 ALUWritePC(result
); // setflags is always FALSE here
9358 APSR
.N
= result
<31>;
9359 APSR
.Z
= IsZeroBit(result
);
9364 bool success
= false;
9366 uint32_t Rd
; // the destination register
9367 uint32_t Rn
; // the first operand
9368 uint32_t Rm
; // the second operand
9370 ARM_ShifterType shift_t
;
9371 uint32_t shift_n
; // the shift applied to the value read from Rm
9374 Rd
= Bits32(opcode
, 15, 12);
9375 Rn
= Bits32(opcode
, 19, 16);
9376 Rm
= Bits32(opcode
, 3, 0);
9377 setflags
= BitIsSet(opcode
, 20);
9378 shift_n
= DecodeImmShiftARM(opcode
, shift_t
);
9380 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related
9382 if (Rd
== 15 && setflags
)
9383 return EmulateSUBSPcLrEtc(opcode
, encoding
);
9388 // Read the register value from register Rn.
9389 uint32_t val1
= ReadCoreReg(Rn
, &success
);
9393 // Read the register value from register Rm.
9394 uint32_t val2
= ReadCoreReg(Rm
, &success
);
9398 uint32_t shifted
= Shift(val2
, shift_t
, shift_n
, APSR_C
, &success
);
9401 AddWithCarryResult res
= AddWithCarry(~val1
, shifted
, APSR_C
);
9403 EmulateInstruction::Context context
;
9404 context
.type
= EmulateInstruction::eContextImmediate
;
9405 context
.SetNoArgs();
9406 return WriteCoreRegOptionalFlags(context
, res
.result
, Rd
, setflags
,
9407 res
.carry_out
, res
.overflow
);
9410 // Subtract with Carry (immediate) subtracts an immediate value and the value
9412 // NOT (Carry flag) from a register value, and writes the result to the
9413 // destination register.
9414 // It can optionally update the condition flags based on the result.
9415 bool EmulateInstructionARM::EmulateSBCImm(const uint32_t opcode
,
9416 const ARMEncoding encoding
) {
9418 // ARM pseudo code...
9419 if ConditionPassed() then
9420 EncodingSpecificOperations();
9421 (result
, carry
, overflow
) = AddWithCarry(R
[n
], NOT(imm32
), APSR
.C
);
9422 if d
== 15 then
// Can only occur for ARM encoding
9423 ALUWritePC(result
); // setflags is always FALSE here
9427 APSR
.N
= result
<31>;
9428 APSR
.Z
= IsZeroBit(result
);
9433 bool success
= false;
9435 uint32_t Rd
; // the destination register
9436 uint32_t Rn
; // the first operand
9439 imm32
; // the immediate value to be added to the value obtained from Rn
9442 Rd
= Bits32(opcode
, 11, 8);
9443 Rn
= Bits32(opcode
, 19, 16);
9444 setflags
= BitIsSet(opcode
, 20);
9445 imm32
= ThumbExpandImm(opcode
); // imm32 = ThumbExpandImm(i:imm3:imm8)
9446 if (BadReg(Rd
) || BadReg(Rn
))
9450 Rd
= Bits32(opcode
, 15, 12);
9451 Rn
= Bits32(opcode
, 19, 16);
9452 setflags
= BitIsSet(opcode
, 20);
9453 imm32
= ARMExpandImm(opcode
); // imm32 = ARMExpandImm(imm12)
9455 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related
9457 if (Rd
== 15 && setflags
)
9458 return EmulateSUBSPcLrEtc(opcode
, encoding
);
9463 // Read the register value from the operand register Rn.
9464 uint32_t reg_val
= ReadCoreReg(Rn
, &success
);
9468 AddWithCarryResult res
= AddWithCarry(reg_val
, ~imm32
, APSR_C
);
9470 EmulateInstruction::Context context
;
9471 context
.type
= EmulateInstruction::eContextImmediate
;
9472 context
.SetNoArgs();
9474 return WriteCoreRegOptionalFlags(context
, res
.result
, Rd
, setflags
,
9475 res
.carry_out
, res
.overflow
);
9478 // Subtract with Carry (register) subtracts an optionally-shifted register
9479 // value and the value of
9480 // NOT (Carry flag) from a register value, and writes the result to the
9481 // destination register.
9482 // It can optionally update the condition flags based on the result.
9483 bool EmulateInstructionARM::EmulateSBCReg(const uint32_t opcode
,
9484 const ARMEncoding encoding
) {
9486 // ARM pseudo code...
9487 if ConditionPassed() then
9488 EncodingSpecificOperations();
9489 shifted
= Shift(R
[m
], shift_t
, shift_n
, APSR
.C
);
9490 (result
, carry
, overflow
) = AddWithCarry(R
[n
], NOT(shifted
), APSR
.C
);
9491 if d
== 15 then
// Can only occur for ARM encoding
9492 ALUWritePC(result
); // setflags is always FALSE here
9496 APSR
.N
= result
<31>;
9497 APSR
.Z
= IsZeroBit(result
);
9502 bool success
= false;
9504 uint32_t Rd
; // the destination register
9505 uint32_t Rn
; // the first operand
9506 uint32_t Rm
; // the second operand
9508 ARM_ShifterType shift_t
;
9509 uint32_t shift_n
; // the shift applied to the value read from Rm
9512 Rd
= Rn
= Bits32(opcode
, 2, 0);
9513 Rm
= Bits32(opcode
, 5, 3);
9514 setflags
= !InITBlock();
9515 shift_t
= SRType_LSL
;
9519 Rd
= Bits32(opcode
, 11, 8);
9520 Rn
= Bits32(opcode
, 19, 16);
9521 Rm
= Bits32(opcode
, 3, 0);
9522 setflags
= BitIsSet(opcode
, 20);
9523 shift_n
= DecodeImmShiftThumb(opcode
, shift_t
);
9524 if (BadReg(Rd
) || BadReg(Rn
) || BadReg(Rm
))
9528 Rd
= Bits32(opcode
, 15, 12);
9529 Rn
= Bits32(opcode
, 19, 16);
9530 Rm
= Bits32(opcode
, 3, 0);
9531 setflags
= BitIsSet(opcode
, 20);
9532 shift_n
= DecodeImmShiftARM(opcode
, shift_t
);
9534 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related
9536 if (Rd
== 15 && setflags
)
9537 return EmulateSUBSPcLrEtc(opcode
, encoding
);
9542 // Read the register value from register Rn.
9543 uint32_t val1
= ReadCoreReg(Rn
, &success
);
9547 // Read the register value from register Rm.
9548 uint32_t val2
= ReadCoreReg(Rm
, &success
);
9552 uint32_t shifted
= Shift(val2
, shift_t
, shift_n
, APSR_C
, &success
);
9555 AddWithCarryResult res
= AddWithCarry(val1
, ~shifted
, APSR_C
);
9557 EmulateInstruction::Context context
;
9558 context
.type
= EmulateInstruction::eContextImmediate
;
9559 context
.SetNoArgs();
9560 return WriteCoreRegOptionalFlags(context
, res
.result
, Rd
, setflags
,
9561 res
.carry_out
, res
.overflow
);
9564 // This instruction subtracts an immediate value from a register value, and
9565 // writes the result to the destination register. It can optionally update the
9566 // condition flags based on the result.
9567 bool EmulateInstructionARM::EmulateSUBImmThumb(const uint32_t opcode
,
9568 const ARMEncoding encoding
) {
9570 // ARM pseudo code...
9571 if ConditionPassed() then
9572 EncodingSpecificOperations();
9573 (result
, carry
, overflow
) = AddWithCarry(R
[n
], NOT(imm32
), '1');
9576 APSR
.N
= result
<31>;
9577 APSR
.Z
= IsZeroBit(result
);
9582 bool success
= false;
9584 uint32_t Rd
; // the destination register
9585 uint32_t Rn
; // the first operand
9587 uint32_t imm32
; // the immediate value to be subtracted from the value
9591 Rd
= Bits32(opcode
, 2, 0);
9592 Rn
= Bits32(opcode
, 5, 3);
9593 setflags
= !InITBlock();
9594 imm32
= Bits32(opcode
, 8, 6); // imm32 = ZeroExtend(imm3, 32)
9597 Rd
= Rn
= Bits32(opcode
, 10, 8);
9598 setflags
= !InITBlock();
9599 imm32
= Bits32(opcode
, 7, 0); // imm32 = ZeroExtend(imm8, 32)
9602 Rd
= Bits32(opcode
, 11, 8);
9603 Rn
= Bits32(opcode
, 19, 16);
9604 setflags
= BitIsSet(opcode
, 20);
9605 imm32
= ThumbExpandImm(opcode
); // imm32 = ThumbExpandImm(i:imm3:imm8)
9607 // if Rd == '1111' && S == '1' then SEE CMP (immediate);
9608 if (Rd
== 15 && setflags
)
9609 return EmulateCMPImm(opcode
, eEncodingT2
);
9611 // if Rn == '1101' then SEE SUB (SP minus immediate);
9613 return EmulateSUBSPImm(opcode
, eEncodingT2
);
9615 // if d == 13 || (d == 15 && S == '0') || n == 15 then UNPREDICTABLE;
9616 if (Rd
== 13 || (Rd
== 15 && !setflags
) || Rn
== 15)
9620 Rd
= Bits32(opcode
, 11, 8);
9621 Rn
= Bits32(opcode
, 19, 16);
9622 setflags
= BitIsSet(opcode
, 20);
9623 imm32
= ThumbImm12(opcode
); // imm32 = ZeroExtend(i:imm3:imm8, 32)
9625 // if Rn == '1111' then SEE ADR;
9627 return EmulateADR(opcode
, eEncodingT2
);
9629 // if Rn == '1101' then SEE SUB (SP minus immediate);
9631 return EmulateSUBSPImm(opcode
, eEncodingT3
);
9639 // Read the register value from the operand register Rn.
9640 uint32_t reg_val
= ReadCoreReg(Rn
, &success
);
9644 AddWithCarryResult res
= AddWithCarry(reg_val
, ~imm32
, 1);
9646 EmulateInstruction::Context context
;
9647 context
.type
= EmulateInstruction::eContextImmediate
;
9648 context
.SetNoArgs();
9650 return WriteCoreRegOptionalFlags(context
, res
.result
, Rd
, setflags
,
9651 res
.carry_out
, res
.overflow
);
9654 // This instruction subtracts an immediate value from a register value, and
9655 // writes the result to the destination register. It can optionally update the
9656 // condition flags based on the result.
9657 bool EmulateInstructionARM::EmulateSUBImmARM(const uint32_t opcode
,
9658 const ARMEncoding encoding
) {
9660 // ARM pseudo code...
9661 if ConditionPassed() then
9662 EncodingSpecificOperations();
9663 (result
, carry
, overflow
) = AddWithCarry(R
[n
], NOT(imm32
), '1');
9665 ALUWritePC(result
); // setflags is always FALSE here
9669 APSR
.N
= result
<31>;
9670 APSR
.Z
= IsZeroBit(result
);
9675 bool success
= false;
9677 if (ConditionPassed(opcode
)) {
9678 uint32_t Rd
; // the destination register
9679 uint32_t Rn
; // the first operand
9681 uint32_t imm32
; // the immediate value to be subtracted from the value
9685 Rd
= Bits32(opcode
, 15, 12);
9686 Rn
= Bits32(opcode
, 19, 16);
9687 setflags
= BitIsSet(opcode
, 20);
9688 imm32
= ARMExpandImm(opcode
); // imm32 = ARMExpandImm(imm12)
9690 // if Rn == '1111' && S == '0' then SEE ADR;
9691 if (Rn
== 15 && !setflags
)
9692 return EmulateADR(opcode
, eEncodingA2
);
9694 // if Rn == '1101' then SEE SUB (SP minus immediate);
9696 return EmulateSUBSPImm(opcode
, eEncodingA1
);
9698 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related
9700 if (Rd
== 15 && setflags
)
9701 return EmulateSUBSPcLrEtc(opcode
, encoding
);
9706 // Read the register value from the operand register Rn.
9707 uint32_t reg_val
= ReadCoreReg(Rn
, &success
);
9711 AddWithCarryResult res
= AddWithCarry(reg_val
, ~imm32
, 1);
9713 EmulateInstruction::Context context
;
9715 context
.type
= EmulateInstruction::eContextAdjustStackPointer
;
9717 context
.type
= EmulateInstruction::eContextRegisterPlusOffset
;
9719 std::optional
<RegisterInfo
> dwarf_reg
=
9720 GetRegisterInfo(eRegisterKindDWARF
, Rn
);
9721 int64_t imm32_signed
= imm32
;
9722 context
.SetRegisterPlusOffset(*dwarf_reg
, -imm32_signed
);
9724 if (!WriteCoreRegOptionalFlags(context
, res
.result
, Rd
, setflags
,
9725 res
.carry_out
, res
.overflow
))
9731 // Test Equivalence (immediate) performs a bitwise exclusive OR operation on a
9732 // register value and an immediate value. It updates the condition flags based
9733 // on the result, and discards the result.
9734 bool EmulateInstructionARM::EmulateTEQImm(const uint32_t opcode
,
9735 const ARMEncoding encoding
) {
9737 // ARM pseudo code...
9738 if ConditionPassed() then
9739 EncodingSpecificOperations();
9740 result
= R
[n
] EOR imm32
;
9741 APSR
.N
= result
<31>;
9742 APSR
.Z
= IsZeroBit(result
);
9747 bool success
= false;
9749 if (ConditionPassed(opcode
)) {
9752 imm32
; // the immediate value to be ANDed to the value obtained from Rn
9753 uint32_t carry
; // the carry bit after ARM/Thumb Expand operation
9756 Rn
= Bits32(opcode
, 19, 16);
9757 imm32
= ThumbExpandImm_C(
9759 carry
); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C)
9764 Rn
= Bits32(opcode
, 19, 16);
9766 ARMExpandImm_C(opcode
, APSR_C
,
9767 carry
); // (imm32, carry) = ARMExpandImm(imm12, APSR.C)
9773 // Read the first operand.
9774 uint32_t val1
= ReadCoreReg(Rn
, &success
);
9778 uint32_t result
= val1
^ imm32
;
9780 EmulateInstruction::Context context
;
9781 context
.type
= EmulateInstruction::eContextImmediate
;
9782 context
.SetNoArgs();
9784 if (!WriteFlags(context
, result
, carry
))
9790 // Test Equivalence (register) performs a bitwise exclusive OR operation on a
9791 // register value and an optionally-shifted register value. It updates the
9792 // condition flags based on the result, and discards the result.
9793 bool EmulateInstructionARM::EmulateTEQReg(const uint32_t opcode
,
9794 const ARMEncoding encoding
) {
9796 // ARM pseudo code...
9797 if ConditionPassed() then
9798 EncodingSpecificOperations();
9799 (shifted
, carry
) = Shift_C(R
[m
], shift_t
, shift_n
, APSR
.C
);
9800 result
= R
[n
] EOR shifted
;
9801 APSR
.N
= result
<31>;
9802 APSR
.Z
= IsZeroBit(result
);
9807 bool success
= false;
9809 if (ConditionPassed(opcode
)) {
9811 ARM_ShifterType shift_t
;
9812 uint32_t shift_n
; // the shift applied to the value read from Rm
9816 Rn
= Bits32(opcode
, 19, 16);
9817 Rm
= Bits32(opcode
, 3, 0);
9818 shift_n
= DecodeImmShiftThumb(opcode
, shift_t
);
9819 if (BadReg(Rn
) || BadReg(Rm
))
9823 Rn
= Bits32(opcode
, 19, 16);
9824 Rm
= Bits32(opcode
, 3, 0);
9825 shift_n
= DecodeImmShiftARM(opcode
, shift_t
);
9831 // Read the first operand.
9832 uint32_t val1
= ReadCoreReg(Rn
, &success
);
9836 // Read the second operand.
9837 uint32_t val2
= ReadCoreReg(Rm
, &success
);
9841 uint32_t shifted
= Shift_C(val2
, shift_t
, shift_n
, APSR_C
, carry
, &success
);
9844 uint32_t result
= val1
^ shifted
;
9846 EmulateInstruction::Context context
;
9847 context
.type
= EmulateInstruction::eContextImmediate
;
9848 context
.SetNoArgs();
9850 if (!WriteFlags(context
, result
, carry
))
9856 // Test (immediate) performs a bitwise AND operation on a register value and an
9857 // immediate value. It updates the condition flags based on the result, and
9858 // discards the result.
9859 bool EmulateInstructionARM::EmulateTSTImm(const uint32_t opcode
,
9860 const ARMEncoding encoding
) {
9862 // ARM pseudo code...
9863 if ConditionPassed() then
9864 EncodingSpecificOperations();
9865 result
= R
[n
] AND imm32
;
9866 APSR
.N
= result
<31>;
9867 APSR
.Z
= IsZeroBit(result
);
9872 bool success
= false;
9874 if (ConditionPassed(opcode
)) {
9877 imm32
; // the immediate value to be ANDed to the value obtained from Rn
9878 uint32_t carry
; // the carry bit after ARM/Thumb Expand operation
9881 Rn
= Bits32(opcode
, 19, 16);
9882 imm32
= ThumbExpandImm_C(
9884 carry
); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C)
9889 Rn
= Bits32(opcode
, 19, 16);
9891 ARMExpandImm_C(opcode
, APSR_C
,
9892 carry
); // (imm32, carry) = ARMExpandImm(imm12, APSR.C)
9898 // Read the first operand.
9899 uint32_t val1
= ReadCoreReg(Rn
, &success
);
9903 uint32_t result
= val1
& imm32
;
9905 EmulateInstruction::Context context
;
9906 context
.type
= EmulateInstruction::eContextImmediate
;
9907 context
.SetNoArgs();
9909 if (!WriteFlags(context
, result
, carry
))
9915 // Test (register) performs a bitwise AND operation on a register value and an
9916 // optionally-shifted register value. It updates the condition flags based on
9917 // the result, and discards the result.
9918 bool EmulateInstructionARM::EmulateTSTReg(const uint32_t opcode
,
9919 const ARMEncoding encoding
) {
9921 // ARM pseudo code...
9922 if ConditionPassed() then
9923 EncodingSpecificOperations();
9924 (shifted
, carry
) = Shift_C(R
[m
], shift_t
, shift_n
, APSR
.C
);
9925 result
= R
[n
] AND shifted
;
9926 APSR
.N
= result
<31>;
9927 APSR
.Z
= IsZeroBit(result
);
9932 bool success
= false;
9934 if (ConditionPassed(opcode
)) {
9936 ARM_ShifterType shift_t
;
9937 uint32_t shift_n
; // the shift applied to the value read from Rm
9941 Rn
= Bits32(opcode
, 2, 0);
9942 Rm
= Bits32(opcode
, 5, 3);
9943 shift_t
= SRType_LSL
;
9947 Rn
= Bits32(opcode
, 19, 16);
9948 Rm
= Bits32(opcode
, 3, 0);
9949 shift_n
= DecodeImmShiftThumb(opcode
, shift_t
);
9950 if (BadReg(Rn
) || BadReg(Rm
))
9954 Rn
= Bits32(opcode
, 19, 16);
9955 Rm
= Bits32(opcode
, 3, 0);
9956 shift_n
= DecodeImmShiftARM(opcode
, shift_t
);
9962 // Read the first operand.
9963 uint32_t val1
= ReadCoreReg(Rn
, &success
);
9967 // Read the second operand.
9968 uint32_t val2
= ReadCoreReg(Rm
, &success
);
9972 uint32_t shifted
= Shift_C(val2
, shift_t
, shift_n
, APSR_C
, carry
, &success
);
9975 uint32_t result
= val1
& shifted
;
9977 EmulateInstruction::Context context
;
9978 context
.type
= EmulateInstruction::eContextImmediate
;
9979 context
.SetNoArgs();
9981 if (!WriteFlags(context
, result
, carry
))
9987 // A8.6.216 SUB (SP minus register)
9988 bool EmulateInstructionARM::EmulateSUBSPReg(const uint32_t opcode
,
9989 const ARMEncoding encoding
) {
9991 if ConditionPassed() then
9992 EncodingSpecificOperations();
9993 shifted
= Shift(R
[m
], shift_t
, shift_n
, APSR
.C
);
9994 (result
, carry
, overflow
) = AddWithCarry(SP
, NOT(shifted
), '1');
9995 if d
== 15 then
// Can only occur for ARM encoding
9996 ALUWritePC(result
); // setflags is always FALSE here
10000 APSR
.N
= result
<31>;
10001 APSR
.Z
= IsZeroBit(result
);
10006 bool success
= false;
10008 if (ConditionPassed(opcode
)) {
10012 ARM_ShifterType shift_t
;
10015 switch (encoding
) {
10017 // d = UInt(Rd); m = UInt(Rm); setflags = (S == '1');
10018 d
= Bits32(opcode
, 11, 8);
10019 m
= Bits32(opcode
, 3, 0);
10020 setflags
= BitIsSet(opcode
, 20);
10022 // (shift_t, shift_n) = DecodeImmShift(type, imm3:imm2);
10023 shift_n
= DecodeImmShiftThumb(opcode
, shift_t
);
10025 // if d == 13 && (shift_t != SRType_LSL || shift_n > 3) then
10027 if ((d
== 13) && ((shift_t
!= SRType_LSL
) || (shift_n
> 3)))
10030 // if d == 15 || BadReg(m) then UNPREDICTABLE;
10031 if ((d
== 15) || BadReg(m
))
10036 // d = UInt(Rd); m = UInt(Rm); setflags = (S == '1');
10037 d
= Bits32(opcode
, 15, 12);
10038 m
= Bits32(opcode
, 3, 0);
10039 setflags
= BitIsSet(opcode
, 20);
10041 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related
10043 if (d
== 15 && setflags
)
10044 EmulateSUBSPcLrEtc(opcode
, encoding
);
10046 // (shift_t, shift_n) = DecodeImmShift(type, imm5);
10047 shift_n
= DecodeImmShiftARM(opcode
, shift_t
);
10054 // shifted = Shift(R[m], shift_t, shift_n, APSR.C);
10055 uint32_t Rm
= ReadCoreReg(m
, &success
);
10059 uint32_t shifted
= Shift(Rm
, shift_t
, shift_n
, APSR_C
, &success
);
10063 // (result, carry, overflow) = AddWithCarry(SP, NOT(shifted), '1');
10064 uint32_t sp_val
= ReadCoreReg(SP_REG
, &success
);
10068 AddWithCarryResult res
= AddWithCarry(sp_val
, ~shifted
, 1);
10070 EmulateInstruction::Context context
;
10071 context
.type
= eContextArithmetic
;
10072 std::optional
<RegisterInfo
> sp_reg
=
10073 GetRegisterInfo(eRegisterKindDWARF
, dwarf_sp
);
10074 std::optional
<RegisterInfo
> dwarf_reg
=
10075 GetRegisterInfo(eRegisterKindDWARF
, dwarf_r0
+ m
);
10076 context
.SetRegisterRegisterOperands(*sp_reg
, *dwarf_reg
);
10078 if (!WriteCoreRegOptionalFlags(context
, res
.result
, dwarf_r0
+ d
, setflags
,
10079 res
.carry_out
, res
.overflow
))
10085 // A8.6.7 ADD (register-shifted register)
10086 bool EmulateInstructionARM::EmulateADDRegShift(const uint32_t opcode
,
10087 const ARMEncoding encoding
) {
10089 if ConditionPassed() then
10090 EncodingSpecificOperations();
10091 shift_n
= UInt(R
[s
]<7:0>);
10092 shifted
= Shift(R
[m
], shift_t
, shift_n
, APSR
.C
);
10093 (result
, carry
, overflow
) = AddWithCarry(R
[n
], shifted
, '0');
10096 APSR
.N
= result
<31>;
10097 APSR
.Z
= IsZeroBit(result
);
10102 bool success
= false;
10104 if (ConditionPassed(opcode
)) {
10110 ARM_ShifterType shift_t
;
10112 switch (encoding
) {
10114 // d = UInt(Rd); n = UInt(Rn); m = UInt(Rm); s = UInt(Rs);
10115 d
= Bits32(opcode
, 15, 12);
10116 n
= Bits32(opcode
, 19, 16);
10117 m
= Bits32(opcode
, 3, 0);
10118 s
= Bits32(opcode
, 11, 8);
10120 // setflags = (S == '1'); shift_t = DecodeRegShift(type);
10121 setflags
= BitIsSet(opcode
, 20);
10122 shift_t
= DecodeRegShift(Bits32(opcode
, 6, 5));
10124 // if d == 15 || n == 15 || m == 15 || s == 15 then UNPREDICTABLE;
10125 if ((d
== 15) || (n
== 15) || (m
== 15) || (s
== 15))
10133 // shift_n = UInt(R[s]<7:0>);
10134 uint32_t Rs
= ReadCoreReg(s
, &success
);
10138 uint32_t shift_n
= Bits32(Rs
, 7, 0);
10140 // shifted = Shift(R[m], shift_t, shift_n, APSR.C);
10141 uint32_t Rm
= ReadCoreReg(m
, &success
);
10145 uint32_t shifted
= Shift(Rm
, shift_t
, shift_n
, APSR_C
, &success
);
10149 // (result, carry, overflow) = AddWithCarry(R[n], shifted, '0');
10150 uint32_t Rn
= ReadCoreReg(n
, &success
);
10154 AddWithCarryResult res
= AddWithCarry(Rn
, shifted
, 0);
10157 EmulateInstruction::Context context
;
10158 context
.type
= eContextArithmetic
;
10159 std::optional
<RegisterInfo
> reg_n
=
10160 GetRegisterInfo(eRegisterKindDWARF
, dwarf_r0
+ n
);
10161 std::optional
<RegisterInfo
> reg_m
=
10162 GetRegisterInfo(eRegisterKindDWARF
, dwarf_r0
+ m
);
10164 context
.SetRegisterRegisterOperands(*reg_n
, *reg_m
);
10166 if (!WriteRegisterUnsigned(context
, eRegisterKindDWARF
, dwarf_r0
+ d
,
10170 // if setflags then
10171 // APSR.N = result<31>;
10172 // APSR.Z = IsZeroBit(result);
10174 // APSR.V = overflow;
10176 return WriteFlags(context
, res
.result
, res
.carry_out
, res
.overflow
);
10181 // A8.6.213 SUB (register)
10182 bool EmulateInstructionARM::EmulateSUBReg(const uint32_t opcode
,
10183 const ARMEncoding encoding
) {
10185 if ConditionPassed() then
10186 EncodingSpecificOperations();
10187 shifted
= Shift(R
[m
], shift_t
, shift_n
, APSR
.C
);
10188 (result
, carry
, overflow
) = AddWithCarry(R
[n
], NOT(shifted
), '1');
10189 if d
== 15 then
// Can only occur for ARM encoding
10190 ALUWritePC(result
); // setflags is always FALSE here
10194 APSR
.N
= result
<31>;
10195 APSR
.Z
= IsZeroBit(result
);
10200 bool success
= false;
10202 if (ConditionPassed(opcode
)) {
10207 ARM_ShifterType shift_t
;
10210 switch (encoding
) {
10212 // d = UInt(Rd); n = UInt(Rn); m = UInt(Rm); setflags = !InITBlock();
10213 d
= Bits32(opcode
, 2, 0);
10214 n
= Bits32(opcode
, 5, 3);
10215 m
= Bits32(opcode
, 8, 6);
10216 setflags
= !InITBlock();
10218 // (shift_t, shift_n) = (SRType_LSL, 0);
10219 shift_t
= SRType_LSL
;
10225 // d = UInt(Rd); n = UInt(Rn); m = UInt(Rm); setflags = (S =="1");
10226 d
= Bits32(opcode
, 11, 8);
10227 n
= Bits32(opcode
, 19, 16);
10228 m
= Bits32(opcode
, 3, 0);
10229 setflags
= BitIsSet(opcode
, 20);
10231 // if Rd == "1111" && S == "1" then SEE CMP (register);
10232 if (d
== 15 && setflags
== 1)
10233 return EmulateCMPImm(opcode
, eEncodingT3
);
10235 // if Rn == "1101" then SEE SUB (SP minus register);
10237 return EmulateSUBSPReg(opcode
, eEncodingT1
);
10239 // (shift_t, shift_n) = DecodeImmShift(type, imm3:imm2);
10240 shift_n
= DecodeImmShiftThumb(opcode
, shift_t
);
10242 // if d == 13 || (d == 15 && S == '0') || n == 15 || BadReg(m) then
10244 if ((d
== 13) || ((d
== 15) && BitIsClear(opcode
, 20)) || (n
== 15) ||
10251 // if Rn == '1101' then SEE SUB (SP minus register);
10252 // d = UInt(Rd); n = UInt(Rn); m = UInt(Rm); setflags = (S == '1');
10253 d
= Bits32(opcode
, 15, 12);
10254 n
= Bits32(opcode
, 19, 16);
10255 m
= Bits32(opcode
, 3, 0);
10256 setflags
= BitIsSet(opcode
, 20);
10258 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related
10260 if ((d
== 15) && setflags
)
10261 EmulateSUBSPcLrEtc(opcode
, encoding
);
10263 // (shift_t, shift_n) = DecodeImmShift(type, imm5);
10264 shift_n
= DecodeImmShiftARM(opcode
, shift_t
);
10272 // shifted = Shift(R[m], shift_t, shift_n, APSR.C);
10273 uint32_t Rm
= ReadCoreReg(m
, &success
);
10277 uint32_t shifted
= Shift(Rm
, shift_t
, shift_n
, APSR_C
, &success
);
10281 // (result, carry, overflow) = AddWithCarry(R[n], NOT(shifted), '1');
10282 uint32_t Rn
= ReadCoreReg(n
, &success
);
10286 AddWithCarryResult res
= AddWithCarry(Rn
, ~shifted
, 1);
10288 // if d == 15 then // Can only occur for ARM encoding ALUWritePC(result);
10289 // // setflags is always FALSE here else
10291 // if setflags then
10292 // APSR.N = result<31>;
10293 // APSR.Z = IsZeroBit(result);
10295 // APSR.V = overflow;
10297 EmulateInstruction::Context context
;
10298 context
.type
= eContextArithmetic
;
10299 std::optional
<RegisterInfo
> reg_n
=
10300 GetRegisterInfo(eRegisterKindDWARF
, dwarf_r0
+ n
);
10301 std::optional
<RegisterInfo
> reg_m
=
10302 GetRegisterInfo(eRegisterKindDWARF
, dwarf_r0
+ m
);
10303 context
.SetRegisterRegisterOperands(*reg_n
, *reg_m
);
10305 if (!WriteCoreRegOptionalFlags(context
, res
.result
, dwarf_r0
+ d
, setflags
,
10306 res
.carry_out
, res
.overflow
))
10313 // Store Register Exclusive calculates an address from a base register value
10314 // and an immediate offset, and stores a word from a register to memory if the
10315 // executing processor has exclusive access to the memory addressed.
10316 bool EmulateInstructionARM::EmulateSTREX(const uint32_t opcode
,
10317 const ARMEncoding encoding
) {
10319 if ConditionPassed() then
10320 EncodingSpecificOperations(); NullCheckIfThumbEE(n
);
10321 address
= R
[n
] + imm32
;
10322 if ExclusiveMonitorsPass(address
,4) then
10323 MemA
[address
,4] = R
[t
];
10329 bool success
= false;
10331 if (ConditionPassed(opcode
)) {
10336 const uint32_t addr_byte_size
= GetAddressByteSize();
10338 switch (encoding
) {
10340 // d = UInt(Rd); t = UInt(Rt); n = UInt(Rn); imm32 =
10341 // ZeroExtend(imm8:'00',
10343 d
= Bits32(opcode
, 11, 8);
10344 t
= Bits32(opcode
, 15, 12);
10345 n
= Bits32(opcode
, 19, 16);
10346 imm32
= Bits32(opcode
, 7, 0) << 2;
10348 // if BadReg(d) || BadReg(t) || n == 15 then UNPREDICTABLE;
10349 if (BadReg(d
) || BadReg(t
) || (n
== 15))
10352 // if d == n || d == t then UNPREDICTABLE;
10353 if ((d
== n
) || (d
== t
))
10359 // d = UInt(Rd); t = UInt(Rt); n = UInt(Rn); imm32 = Zeros(32); // Zero
10361 d
= Bits32(opcode
, 15, 12);
10362 t
= Bits32(opcode
, 3, 0);
10363 n
= Bits32(opcode
, 19, 16);
10366 // if d == 15 || t == 15 || n == 15 then UNPREDICTABLE;
10367 if ((d
== 15) || (t
== 15) || (n
== 15))
10370 // if d == n || d == t then UNPREDICTABLE;
10371 if ((d
== n
) || (d
== t
))
10380 // address = R[n] + imm32;
10381 uint32_t Rn
= ReadCoreReg(n
, &success
);
10385 addr_t address
= Rn
+ imm32
;
10387 std::optional
<RegisterInfo
> base_reg
=
10388 GetRegisterInfo(eRegisterKindDWARF
, dwarf_r0
+ n
);
10389 std::optional
<RegisterInfo
> data_reg
=
10390 GetRegisterInfo(eRegisterKindDWARF
, dwarf_r0
+ t
);
10391 EmulateInstruction::Context context
;
10392 context
.type
= eContextRegisterStore
;
10393 context
.SetRegisterToRegisterPlusOffset(*data_reg
, *base_reg
, imm32
);
10395 // if ExclusiveMonitorsPass(address,4) then if (ExclusiveMonitorsPass
10396 // (address, addr_byte_size)) -- For now, for the sake of emulation, we
10401 // MemA[address,4] = R[t];
10403 ReadRegisterUnsigned(eRegisterKindDWARF
, dwarf_r0
+ t
, 0, &success
);
10407 if (!MemAWrite(context
, address
, Rt
, addr_byte_size
))
10411 if (!WriteRegisterUnsigned(context
, eRegisterKindDWARF
, dwarf_r0
+ t
, 0))
10414 #if 0 // unreachable because if true
10418 if (!WriteRegisterUnsigned (context
, eRegisterKindDWARF
, dwarf_r0
+ t
, 1))
10421 #endif // unreachable because if true
10426 // A8.6.197 STRB (immediate, ARM)
10427 bool EmulateInstructionARM::EmulateSTRBImmARM(const uint32_t opcode
,
10428 const ARMEncoding encoding
) {
10430 if ConditionPassed() then
10431 EncodingSpecificOperations();
10432 offset_addr
= if add
then (R
[n
] + imm32
) else (R
[n
] - imm32
);
10433 address
= if index then offset_addr
else R
[n
];
10434 MemU
[address
,1] = R
[t
]<7:0>;
10435 if wback then R
[n
] = offset_addr
;
10438 bool success
= false;
10440 if (ConditionPassed(opcode
)) {
10448 switch (encoding
) {
10450 // if P == '0' && W == '1' then SEE STRBT;
10451 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
10452 t
= Bits32(opcode
, 15, 12);
10453 n
= Bits32(opcode
, 19, 16);
10454 imm32
= Bits32(opcode
, 11, 0);
10456 // index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1');
10457 index
= BitIsSet(opcode
, 24);
10458 add
= BitIsSet(opcode
, 23);
10459 wback
= BitIsClear(opcode
, 24) || BitIsSet(opcode
, 21);
10461 // if t == 15 then UNPREDICTABLE;
10465 // if wback && (n == 15 || n == t) then UNPREDICTABLE;
10466 if (wback
&& ((n
== 15) || (n
== t
)))
10475 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
10476 uint32_t Rn
= ReadCoreReg(n
, &success
);
10480 addr_t offset_addr
;
10482 offset_addr
= Rn
+ imm32
;
10484 offset_addr
= Rn
- imm32
;
10486 // address = if index then offset_addr else R[n];
10489 address
= offset_addr
;
10493 // MemU[address,1] = R[t]<7:0>;
10494 uint32_t Rt
= ReadCoreReg(t
, &success
);
10498 std::optional
<RegisterInfo
> base_reg
=
10499 GetRegisterInfo(eRegisterKindDWARF
, dwarf_r0
+ n
);
10500 std::optional
<RegisterInfo
> data_reg
=
10501 GetRegisterInfo(eRegisterKindDWARF
, dwarf_r0
+ t
);
10502 EmulateInstruction::Context context
;
10503 context
.type
= eContextRegisterStore
;
10504 context
.SetRegisterToRegisterPlusOffset(*data_reg
, *base_reg
, address
- Rn
);
10506 if (!MemUWrite(context
, address
, Bits32(Rt
, 7, 0), 1))
10509 // if wback then R[n] = offset_addr;
10511 if (!WriteRegisterUnsigned(context
, eRegisterKindDWARF
, dwarf_r0
+ n
,
10519 // A8.6.194 STR (immediate, ARM)
10520 bool EmulateInstructionARM::EmulateSTRImmARM(const uint32_t opcode
,
10521 const ARMEncoding encoding
) {
10523 if ConditionPassed() then
10524 EncodingSpecificOperations();
10525 offset_addr
= if add
then (R
[n
] + imm32
) else (R
[n
] - imm32
);
10526 address
= if index then offset_addr
else R
[n
];
10527 MemU
[address
,4] = if t
== 15 then
PCStoreValue() else R
[t
];
10528 if wback then R
[n
] = offset_addr
;
10531 bool success
= false;
10533 if (ConditionPassed(opcode
)) {
10541 const uint32_t addr_byte_size
= GetAddressByteSize();
10543 switch (encoding
) {
10545 // if P == '0' && W == '1' then SEE STRT;
10546 // if Rn == '1101' && P == '1' && U == '0' && W == '1' && imm12 ==
10547 // '000000000100' then SEE PUSH;
10548 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
10549 t
= Bits32(opcode
, 15, 12);
10550 n
= Bits32(opcode
, 19, 16);
10551 imm32
= Bits32(opcode
, 11, 0);
10553 // index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1');
10554 index
= BitIsSet(opcode
, 24);
10555 add
= BitIsSet(opcode
, 23);
10556 wback
= BitIsClear(opcode
, 24) || BitIsSet(opcode
, 21);
10558 // if wback && (n == 15 || n == t) then UNPREDICTABLE;
10559 if (wback
&& ((n
== 15) || (n
== t
)))
10568 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
10569 uint32_t Rn
= ReadCoreReg(n
, &success
);
10573 addr_t offset_addr
;
10575 offset_addr
= Rn
+ imm32
;
10577 offset_addr
= Rn
- imm32
;
10579 // address = if index then offset_addr else R[n];
10582 address
= offset_addr
;
10586 std::optional
<RegisterInfo
> base_reg
=
10587 GetRegisterInfo(eRegisterKindDWARF
, dwarf_r0
+ n
);
10588 std::optional
<RegisterInfo
> data_reg
=
10589 GetRegisterInfo(eRegisterKindDWARF
, dwarf_r0
+ t
);
10590 EmulateInstruction::Context context
;
10591 context
.type
= eContextRegisterStore
;
10592 context
.SetRegisterToRegisterPlusOffset(*data_reg
, *base_reg
, address
- Rn
);
10594 // MemU[address,4] = if t == 15 then PCStoreValue() else R[t];
10595 uint32_t Rt
= ReadCoreReg(t
, &success
);
10600 uint32_t pc_value
= ReadCoreReg(PC_REG
, &success
);
10604 if (!MemUWrite(context
, address
, pc_value
, addr_byte_size
))
10607 if (!MemUWrite(context
, address
, Rt
, addr_byte_size
))
10611 // if wback then R[n] = offset_addr;
10613 context
.type
= eContextAdjustBaseRegister
;
10614 context
.SetImmediate(offset_addr
);
10616 if (!WriteRegisterUnsigned(context
, eRegisterKindDWARF
, dwarf_r0
+ n
,
10624 // A8.6.66 LDRD (immediate)
10625 // Load Register Dual (immediate) calculates an address from a base register
10626 // value and an immediate offset, loads two words from memory, and writes them
10627 // to two registers. It can use offset, post-indexed, or pre-indexed
10629 bool EmulateInstructionARM::EmulateLDRDImmediate(const uint32_t opcode
,
10630 const ARMEncoding encoding
) {
10632 if ConditionPassed() then
10633 EncodingSpecificOperations(); NullCheckIfThumbEE(n
);
10634 offset_addr
= if add
then (R
[n
] + imm32
) else (R
[n
] - imm32
);
10635 address
= if index then offset_addr
else R
[n
];
10636 R
[t
] = MemA
[address
,4];
10637 R
[t2
] = MemA
[address
+4,4];
10638 if wback then R
[n
] = offset_addr
;
10641 bool success
= false;
10643 if (ConditionPassed(opcode
)) {
10652 switch (encoding
) {
10654 // if P == '0' && W == '0' then SEE 'Related encodings';
10655 // if Rn == '1111' then SEE LDRD (literal);
10656 // t = UInt(Rt); t2 = UInt(Rt2); n = UInt(Rn); imm32 =
10657 // ZeroExtend(imm8:'00', 32);
10658 t
= Bits32(opcode
, 15, 12);
10659 t2
= Bits32(opcode
, 11, 8);
10660 n
= Bits32(opcode
, 19, 16);
10661 imm32
= Bits32(opcode
, 7, 0) << 2;
10663 // index = (P == '1'); add = (U == '1'); wback = (W == '1');
10664 index
= BitIsSet(opcode
, 24);
10665 add
= BitIsSet(opcode
, 23);
10666 wback
= BitIsSet(opcode
, 21);
10668 // if wback && (n == t || n == t2) then UNPREDICTABLE;
10669 if (wback
&& ((n
== t
) || (n
== t2
)))
10672 // if BadReg(t) || BadReg(t2) || t == t2 then UNPREDICTABLE;
10673 if (BadReg(t
) || BadReg(t2
) || (t
== t2
))
10679 // if Rn == '1111' then SEE LDRD (literal);
10680 // if Rt<0> == '1' then UNPREDICTABLE;
10681 // t = UInt(Rt); t2 = t+1; n = UInt(Rn); imm32 = ZeroExtend(imm4H:imm4L,
10683 t
= Bits32(opcode
, 15, 12);
10684 if (BitIsSet(t
, 0))
10687 n
= Bits32(opcode
, 19, 16);
10688 imm32
= (Bits32(opcode
, 11, 8) << 4) | Bits32(opcode
, 3, 0);
10690 // index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1');
10691 index
= BitIsSet(opcode
, 24);
10692 add
= BitIsSet(opcode
, 23);
10693 wback
= BitIsClear(opcode
, 24) || BitIsSet(opcode
, 21);
10695 // if P == '0' && W == '1' then UNPREDICTABLE;
10696 if (BitIsClear(opcode
, 24) && BitIsSet(opcode
, 21))
10699 // if wback && (n == t || n == t2) then UNPREDICTABLE;
10700 if (wback
&& ((n
== t
) || (n
== t2
)))
10703 // if t2 == 15 then UNPREDICTABLE;
10713 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
10714 uint32_t Rn
= ReadCoreReg(n
, &success
);
10718 addr_t offset_addr
;
10720 offset_addr
= Rn
+ imm32
;
10722 offset_addr
= Rn
- imm32
;
10724 // address = if index then offset_addr else R[n];
10727 address
= offset_addr
;
10731 // R[t] = MemA[address,4];
10733 EmulateInstruction::Context context
;
10735 context
.type
= eContextPopRegisterOffStack
;
10737 context
.type
= eContextRegisterLoad
;
10738 context
.SetAddress(address
);
10740 const uint32_t addr_byte_size
= GetAddressByteSize();
10741 uint32_t data
= MemARead(context
, address
, addr_byte_size
, 0, &success
);
10745 if (!WriteRegisterUnsigned(context
, eRegisterKindDWARF
, dwarf_r0
+ t
, data
))
10748 // R[t2] = MemA[address+4,4];
10749 context
.SetAddress(address
+ 4);
10750 data
= MemARead(context
, address
+ 4, addr_byte_size
, 0, &success
);
10754 if (!WriteRegisterUnsigned(context
, eRegisterKindDWARF
, dwarf_r0
+ t2
,
10758 // if wback then R[n] = offset_addr;
10760 context
.type
= eContextAdjustBaseRegister
;
10761 context
.SetAddress(offset_addr
);
10763 if (!WriteRegisterUnsigned(context
, eRegisterKindDWARF
, dwarf_r0
+ n
,
10771 // A8.6.68 LDRD (register)
10772 // Load Register Dual (register) calculates an address from a base register
10773 // value and a register offset, loads two words from memory, and writes them to
10774 // two registers. It can use offset, post-indexed or pre-indexed addressing.
10775 bool EmulateInstructionARM::EmulateLDRDRegister(const uint32_t opcode
,
10776 const ARMEncoding encoding
) {
10778 if ConditionPassed() then
10779 EncodingSpecificOperations();
10780 offset_addr
= if add
then (R
[n
] + R
[m
]) else (R
[n
] - R
[m
]);
10781 address
= if index then offset_addr
else R
[n
];
10782 R
[t
] = MemA
[address
,4];
10783 R
[t2
] = MemA
[address
+4,4];
10784 if wback then R
[n
] = offset_addr
;
10787 bool success
= false;
10789 if (ConditionPassed(opcode
)) {
10798 switch (encoding
) {
10800 // if Rt<0> == '1' then UNPREDICTABLE;
10801 // t = UInt(Rt); t2 = t+1; n = UInt(Rn); m = UInt(Rm);
10802 t
= Bits32(opcode
, 15, 12);
10803 if (BitIsSet(t
, 0))
10806 n
= Bits32(opcode
, 19, 16);
10807 m
= Bits32(opcode
, 3, 0);
10809 // index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1');
10810 index
= BitIsSet(opcode
, 24);
10811 add
= BitIsSet(opcode
, 23);
10812 wback
= BitIsClear(opcode
, 24) || BitIsSet(opcode
, 21);
10814 // if P == '0' && W == '1' then UNPREDICTABLE;
10815 if (BitIsClear(opcode
, 24) && BitIsSet(opcode
, 21))
10818 // if t2 == 15 || m == 15 || m == t || m == t2 then UNPREDICTABLE;
10819 if ((t2
== 15) || (m
== 15) || (m
== t
) || (m
== t2
))
10822 // if wback && (n == 15 || n == t || n == t2) then UNPREDICTABLE;
10823 if (wback
&& ((n
== 15) || (n
== t
) || (n
== t2
)))
10826 // if ArchVersion() < 6 && wback && m == n then UNPREDICTABLE;
10827 if ((ArchVersion() < 6) && wback
&& (m
== n
))
10835 uint32_t Rn
= ReadCoreReg(n
, &success
);
10839 uint32_t Rm
= ReadCoreReg(m
, &success
);
10843 // offset_addr = if add then (R[n] + R[m]) else (R[n] - R[m]);
10844 addr_t offset_addr
;
10846 offset_addr
= Rn
+ Rm
;
10848 offset_addr
= Rn
- Rm
;
10850 // address = if index then offset_addr else R[n];
10853 address
= offset_addr
;
10857 EmulateInstruction::Context context
;
10859 context
.type
= eContextPopRegisterOffStack
;
10861 context
.type
= eContextRegisterLoad
;
10862 context
.SetAddress(address
);
10864 // R[t] = MemA[address,4];
10865 const uint32_t addr_byte_size
= GetAddressByteSize();
10866 uint32_t data
= MemARead(context
, address
, addr_byte_size
, 0, &success
);
10870 if (!WriteRegisterUnsigned(context
, eRegisterKindDWARF
, dwarf_r0
+ t
, data
))
10873 // R[t2] = MemA[address+4,4];
10875 data
= MemARead(context
, address
+ 4, addr_byte_size
, 0, &success
);
10879 if (!WriteRegisterUnsigned(context
, eRegisterKindDWARF
, dwarf_r0
+ t2
,
10883 // if wback then R[n] = offset_addr;
10885 context
.type
= eContextAdjustBaseRegister
;
10886 context
.SetAddress(offset_addr
);
10888 if (!WriteRegisterUnsigned(context
, eRegisterKindDWARF
, dwarf_r0
+ n
,
10896 // A8.6.200 STRD (immediate)
10897 // Store Register Dual (immediate) calculates an address from a base register
10898 // value and an immediate offset, and stores two words from two registers to
10899 // memory. It can use offset, post-indexed, or pre-indexed addressing.
10900 bool EmulateInstructionARM::EmulateSTRDImm(const uint32_t opcode
,
10901 const ARMEncoding encoding
) {
10903 if ConditionPassed() then
10904 EncodingSpecificOperations(); NullCheckIfThumbEE(n
);
10905 offset_addr
= if add
then (R
[n
] + imm32
) else (R
[n
] - imm32
);
10906 address
= if index then offset_addr
else R
[n
];
10907 MemA
[address
,4] = R
[t
];
10908 MemA
[address
+4,4] = R
[t2
];
10909 if wback then R
[n
] = offset_addr
;
10912 bool success
= false;
10914 if (ConditionPassed(opcode
)) {
10923 switch (encoding
) {
10925 // if P == '0' && W == '0' then SEE 'Related encodings';
10926 // t = UInt(Rt); t2 = UInt(Rt2); n = UInt(Rn); imm32 =
10927 // ZeroExtend(imm8:'00', 32);
10928 t
= Bits32(opcode
, 15, 12);
10929 t2
= Bits32(opcode
, 11, 8);
10930 n
= Bits32(opcode
, 19, 16);
10931 imm32
= Bits32(opcode
, 7, 0) << 2;
10933 // index = (P == '1'); add = (U == '1'); wback = (W == '1');
10934 index
= BitIsSet(opcode
, 24);
10935 add
= BitIsSet(opcode
, 23);
10936 wback
= BitIsSet(opcode
, 21);
10938 // if wback && (n == t || n == t2) then UNPREDICTABLE;
10939 if (wback
&& ((n
== t
) || (n
== t2
)))
10942 // if n == 15 || BadReg(t) || BadReg(t2) then UNPREDICTABLE;
10943 if ((n
== 15) || BadReg(t
) || BadReg(t2
))
10949 // if Rt<0> == '1' then UNPREDICTABLE;
10950 // t = UInt(Rt); t2 = t+1; n = UInt(Rn); imm32 = ZeroExtend(imm4H:imm4L,
10952 t
= Bits32(opcode
, 15, 12);
10953 if (BitIsSet(t
, 0))
10957 n
= Bits32(opcode
, 19, 16);
10958 imm32
= (Bits32(opcode
, 11, 8) << 4) | Bits32(opcode
, 3, 0);
10960 // index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1');
10961 index
= BitIsSet(opcode
, 24);
10962 add
= BitIsSet(opcode
, 23);
10963 wback
= BitIsClear(opcode
, 24) || BitIsSet(opcode
, 21);
10965 // if P == '0' && W == '1' then UNPREDICTABLE;
10966 if (BitIsClear(opcode
, 24) && BitIsSet(opcode
, 21))
10969 // if wback && (n == 15 || n == t || n == t2) then UNPREDICTABLE;
10970 if (wback
&& ((n
== 15) || (n
== t
) || (n
== t2
)))
10973 // if t2 == 15 then UNPREDICTABLE;
10983 std::optional
<RegisterInfo
> base_reg
=
10984 GetRegisterInfo(eRegisterKindDWARF
, dwarf_r0
+ n
);
10986 uint32_t Rn
= ReadCoreReg(n
, &success
);
10990 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
10991 addr_t offset_addr
;
10993 offset_addr
= Rn
+ imm32
;
10995 offset_addr
= Rn
- imm32
;
10997 // address = if index then offset_addr else R[n];
11000 address
= offset_addr
;
11004 // MemA[address,4] = R[t];
11005 std::optional
<RegisterInfo
> data_reg
=
11006 GetRegisterInfo(eRegisterKindDWARF
, dwarf_r0
+ t
);
11008 uint32_t data
= ReadCoreReg(t
, &success
);
11012 EmulateInstruction::Context context
;
11014 context
.type
= eContextPushRegisterOnStack
;
11016 context
.type
= eContextRegisterStore
;
11017 context
.SetRegisterToRegisterPlusOffset(*data_reg
, *base_reg
, address
- Rn
);
11019 const uint32_t addr_byte_size
= GetAddressByteSize();
11021 if (!MemAWrite(context
, address
, data
, addr_byte_size
))
11024 // MemA[address+4,4] = R[t2];
11025 data_reg
= GetRegisterInfo(eRegisterKindDWARF
, dwarf_r0
+ t2
);
11026 context
.SetRegisterToRegisterPlusOffset(*data_reg
, *base_reg
,
11027 (address
+ 4) - Rn
);
11029 data
= ReadCoreReg(t2
, &success
);
11033 if (!MemAWrite(context
, address
+ 4, data
, addr_byte_size
))
11036 // if wback then R[n] = offset_addr;
11039 context
.type
= eContextAdjustStackPointer
;
11041 context
.type
= eContextAdjustBaseRegister
;
11042 context
.SetAddress(offset_addr
);
11044 if (!WriteRegisterUnsigned(context
, eRegisterKindDWARF
, dwarf_r0
+ n
,
11052 // A8.6.201 STRD (register)
11053 bool EmulateInstructionARM::EmulateSTRDReg(const uint32_t opcode
,
11054 const ARMEncoding encoding
) {
11056 if ConditionPassed() then
11057 EncodingSpecificOperations();
11058 offset_addr
= if add
then (R
[n
] + R
[m
]) else (R
[n
] - R
[m
]);
11059 address
= if index then offset_addr
else R
[n
];
11060 MemA
[address
,4] = R
[t
];
11061 MemA
[address
+4,4] = R
[t2
];
11062 if wback then R
[n
] = offset_addr
;
11065 bool success
= false;
11067 if (ConditionPassed(opcode
)) {
11076 switch (encoding
) {
11078 // if Rt<0> == '1' then UNPREDICTABLE;
11079 // t = UInt(Rt); t2 = t+1; n = UInt(Rn); m = UInt(Rm);
11080 t
= Bits32(opcode
, 15, 12);
11081 if (BitIsSet(t
, 0))
11085 n
= Bits32(opcode
, 19, 16);
11086 m
= Bits32(opcode
, 3, 0);
11088 // index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1');
11089 index
= BitIsSet(opcode
, 24);
11090 add
= BitIsSet(opcode
, 23);
11091 wback
= BitIsClear(opcode
, 24) || BitIsSet(opcode
, 21);
11093 // if P == '0' && W == '1' then UNPREDICTABLE;
11094 if (BitIsClear(opcode
, 24) && BitIsSet(opcode
, 21))
11097 // if t2 == 15 || m == 15 then UNPREDICTABLE;
11098 if ((t2
== 15) || (m
== 15))
11101 // if wback && (n == 15 || n == t || n == t2) then UNPREDICTABLE;
11102 if (wback
&& ((n
== 15) || (n
== t
) || (n
== t2
)))
11105 // if ArchVersion() < 6 && wback && m == n then UNPREDICTABLE;
11106 if ((ArchVersion() < 6) && wback
&& (m
== n
))
11115 uint32_t Rn
= ReadCoreReg(n
, &success
);
11119 uint32_t Rm
= ReadCoreReg(m
, &success
);
11123 // offset_addr = if add then (R[n] + R[m]) else (R[n] - R[m]);
11124 addr_t offset_addr
;
11126 offset_addr
= Rn
+ Rm
;
11128 offset_addr
= Rn
- Rm
;
11130 // address = if index then offset_addr else R[n];
11133 address
= offset_addr
;
11136 // MemA[address,4] = R[t];
11137 uint32_t Rt
= ReadCoreReg(t
, &success
);
11141 EmulateInstruction::Context context
;
11143 context
.type
= eContextPushRegisterOnStack
;
11145 context
.type
= eContextRegisterStore
;
11147 std::optional
<RegisterInfo
> base_reg
=
11148 GetRegisterInfo(eRegisterKindDWARF
, dwarf_r0
+ n
);
11149 std::optional
<RegisterInfo
> offset_reg
=
11150 GetRegisterInfo(eRegisterKindDWARF
, dwarf_r0
+ m
);
11151 std::optional
<RegisterInfo
> data_reg
=
11152 GetRegisterInfo(eRegisterKindDWARF
, dwarf_r0
+ t
);
11153 context
.SetRegisterToRegisterPlusIndirectOffset(*base_reg
, *offset_reg
,
11156 const uint32_t addr_byte_size
= GetAddressByteSize();
11158 if (!MemAWrite(context
, address
, Rt
, addr_byte_size
))
11161 // MemA[address+4,4] = R[t2];
11162 uint32_t Rt2
= ReadCoreReg(t2
, &success
);
11166 data_reg
= GetRegisterInfo(eRegisterKindDWARF
, dwarf_r0
+ t2
);
11168 context
.SetRegisterToRegisterPlusIndirectOffset(*base_reg
, *offset_reg
,
11171 if (!MemAWrite(context
, address
+ 4, Rt2
, addr_byte_size
))
11174 // if wback then R[n] = offset_addr;
11176 context
.type
= eContextAdjustBaseRegister
;
11177 context
.SetAddress(offset_addr
);
11179 if (!WriteRegisterUnsigned(context
, eRegisterKindDWARF
, dwarf_r0
+ n
,
11188 // Vector Load Multiple loads multiple extension registers from consecutive
11189 // memory locations using an address from an ARM core register.
11190 bool EmulateInstructionARM::EmulateVLDM(const uint32_t opcode
,
11191 const ARMEncoding encoding
) {
11193 if ConditionPassed() then
11194 EncodingSpecificOperations(); CheckVFPEnabled(TRUE
); NullCheckIfThumbEE(n
);
11195 address
= if add then R
[n
] else R
[n
]-imm32
;
11196 if wback then R
[n
] = if add then R
[n
]+imm32
else R
[n
]-imm32
;
11197 for r
= 0 to regs
-1
11198 if single_regs then
11199 S
[d
+r
] = MemA
[address
,4]; address
= address
+4;
11201 word1
= MemA
[address
,4]; word2
= MemA
[address
+4,4]; address
= address
+8;
11202 // Combine the word-aligned words in the correct order for
11203 // current endianness.
11204 D
[d
+r
] = if BigEndian() then word1
:word2
else word2
:word1
;
11207 bool success
= false;
11209 if (ConditionPassed(opcode
)) {
11218 switch (encoding
) {
11221 // if P == '0' && U == '0' && W == '0' then SEE 'Related encodings';
11222 // if P == '0' && U == '1' && W == '1' && Rn == '1101' then SEE VPOP;
11223 // if P == '1' && W == '0' then SEE VLDR;
11224 // if P == U && W == '1' then UNDEFINED;
11225 if ((Bit32(opcode
, 24) == Bit32(opcode
, 23)) && BitIsSet(opcode
, 21))
11228 // // Remaining combinations are PUW = 010 (IA without !), 011 (IA with
11229 // !), 101 (DB with !)
11230 // single_regs = FALSE; add = (U == '1'); wback = (W == '1');
11231 single_regs
= false;
11232 add
= BitIsSet(opcode
, 23);
11233 wback
= BitIsSet(opcode
, 21);
11235 // d = UInt(D:Vd); n = UInt(Rn); imm32 = ZeroExtend(imm8:'00', 32);
11236 d
= (Bit32(opcode
, 22) << 4) | Bits32(opcode
, 15, 12);
11237 n
= Bits32(opcode
, 19, 16);
11238 imm32
= Bits32(opcode
, 7, 0) << 2;
11240 // regs = UInt(imm8) DIV 2; // If UInt(imm8) is odd, see 'FLDMX'.
11241 regs
= Bits32(opcode
, 7, 0) / 2;
11243 // if n == 15 && (wback || CurrentInstrSet() != InstrSet_ARM) then
11245 if (n
== 15 && (wback
|| CurrentInstrSet() != eModeARM
))
11248 // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE;
11249 if ((regs
== 0) || (regs
> 16) || ((d
+ regs
) > 32))
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 !) single_regs = TRUE; add = (U == '1'); wback = (W
11266 // UInt(Vd:D); n = UInt(Rn);
11267 single_regs
= true;
11268 add
= BitIsSet(opcode
, 23);
11269 wback
= BitIsSet(opcode
, 21);
11270 d
= (Bits32(opcode
, 15, 12) << 1) | Bit32(opcode
, 22);
11271 n
= Bits32(opcode
, 19, 16);
11273 // imm32 = ZeroExtend(imm8:'00', 32); regs = UInt(imm8);
11274 imm32
= Bits32(opcode
, 7, 0) << 2;
11275 regs
= Bits32(opcode
, 7, 0);
11277 // if n == 15 && (wback || CurrentInstrSet() != InstrSet_ARM) then
11279 if ((n
== 15) && (wback
|| (CurrentInstrSet() != eModeARM
)))
11282 // if regs == 0 || (d+regs) > 32 then UNPREDICTABLE;
11283 if ((regs
== 0) || ((d
+ regs
) > 32))
11291 uint32_t Rn
= ReadCoreReg(n
, &success
);
11295 // address = if add then R[n] else R[n]-imm32;
11300 address
= Rn
- imm32
;
11302 // if wback then R[n] = if add then R[n]+imm32 else R[n]-imm32;
11303 EmulateInstruction::Context context
;
11308 value
= Rn
+ imm32
;
11310 value
= Rn
- imm32
;
11312 context
.type
= eContextAdjustBaseRegister
;
11313 context
.SetImmediateSigned(value
- Rn
);
11314 if (!WriteRegisterUnsigned(context
, eRegisterKindDWARF
, dwarf_r0
+ n
,
11319 const uint32_t addr_byte_size
= GetAddressByteSize();
11320 uint32_t start_reg
= single_regs
? dwarf_s0
: dwarf_d0
;
11322 context
.type
= eContextRegisterLoad
;
11324 std::optional
<RegisterInfo
> base_reg
=
11325 GetRegisterInfo(eRegisterKindDWARF
, dwarf_r0
+ n
);
11327 // for r = 0 to regs-1
11328 for (uint32_t r
= 0; r
< regs
; ++r
) {
11330 // S[d+r] = MemA[address,4]; address = address+4;
11331 context
.SetRegisterPlusOffset(*base_reg
, address
- Rn
);
11333 uint32_t data
= MemARead(context
, address
, addr_byte_size
, 0, &success
);
11337 if (!WriteRegisterUnsigned(context
, eRegisterKindDWARF
,
11338 start_reg
+ d
+ r
, data
))
11341 address
= address
+ 4;
11343 // word1 = MemA[address,4]; word2 = MemA[address+4,4]; address =
11345 context
.SetRegisterPlusOffset(*base_reg
, address
- Rn
);
11347 MemARead(context
, address
, addr_byte_size
, 0, &success
);
11351 context
.SetRegisterPlusOffset(*base_reg
, (address
+ 4) - Rn
);
11353 MemARead(context
, address
+ 4, addr_byte_size
, 0, &success
);
11357 address
= address
+ 8;
11358 // // Combine the word-aligned words in the correct order for current
11360 // D[d+r] = if BigEndian() then word1:word2 else word2:word1;
11362 if (GetByteOrder() == eByteOrderBig
) {
11364 data
= (data
<< 32) | word2
;
11367 data
= (data
<< 32) | word1
;
11370 if (!WriteRegisterUnsigned(context
, eRegisterKindDWARF
,
11371 start_reg
+ d
+ r
, data
))
11380 // Vector Store Multiple stores multiple extension registers to consecutive
11381 // memory locations using an address from an
11382 // ARM core register.
11383 bool EmulateInstructionARM::EmulateVSTM(const uint32_t opcode
,
11384 const ARMEncoding encoding
) {
11386 if ConditionPassed() then
11387 EncodingSpecificOperations(); CheckVFPEnabled(TRUE
); NullCheckIfThumbEE(n
);
11388 address
= if add then R
[n
] else R
[n
]-imm32
;
11389 if wback then R
[n
] = if add then R
[n
]+imm32
else R
[n
]-imm32
;
11390 for r
= 0 to regs
-1
11391 if single_regs then
11392 MemA
[address
,4] = S
[d
+r
]; address
= address
+4;
11394 // Store as two word-aligned words in the correct order for
11395 // current endianness.
11396 MemA
[address
,4] = if BigEndian() then D
[d
+r
]<63:32> else D
[d
+r
]<31:0>;
11397 MemA
[address
+4,4] = if BigEndian() then D
[d
+r
]<31:0> else D
[d
+r
]<63:32>;
11398 address
= address
+8;
11401 bool success
= false;
11403 if (ConditionPassed(opcode
)) {
11412 switch (encoding
) {
11415 // if P == '0' && U == '0' && W == '0' then SEE 'Related encodings';
11416 // if P == '1' && U == '0' && W == '1' && Rn == '1101' then SEE VPUSH;
11417 // if P == '1' && W == '0' then SEE VSTR;
11418 // if P == U && W == '1' then UNDEFINED;
11419 if ((Bit32(opcode
, 24) == Bit32(opcode
, 23)) && BitIsSet(opcode
, 21))
11422 // // Remaining combinations are PUW = 010 (IA without !), 011 (IA with
11423 // !), 101 (DB with !)
11424 // single_regs = FALSE; add = (U == '1'); wback = (W == '1');
11425 single_regs
= false;
11426 add
= BitIsSet(opcode
, 23);
11427 wback
= BitIsSet(opcode
, 21);
11429 // d = UInt(D:Vd); n = UInt(Rn); imm32 = ZeroExtend(imm8:'00', 32);
11430 d
= (Bit32(opcode
, 22) << 4) | Bits32(opcode
, 15, 12);
11431 n
= Bits32(opcode
, 19, 16);
11432 imm32
= Bits32(opcode
, 7, 0) << 2;
11434 // regs = UInt(imm8) DIV 2; // If UInt(imm8) is odd, see 'FSTMX'.
11435 regs
= Bits32(opcode
, 7, 0) / 2;
11437 // if n == 15 && (wback || CurrentInstrSet() != InstrSet_ARM) then
11439 if ((n
== 15) && (wback
|| (CurrentInstrSet() != eModeARM
)))
11442 // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE;
11443 if ((regs
== 0) || (regs
> 16) || ((d
+ regs
) > 32))
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 !) single_regs = TRUE; add = (U == '1'); wback = (W
11460 // UInt(Vd:D); n = UInt(Rn);
11461 single_regs
= true;
11462 add
= BitIsSet(opcode
, 23);
11463 wback
= BitIsSet(opcode
, 21);
11464 d
= (Bits32(opcode
, 15, 12) << 1) | Bit32(opcode
, 22);
11465 n
= Bits32(opcode
, 19, 16);
11467 // imm32 = ZeroExtend(imm8:'00', 32); regs = UInt(imm8);
11468 imm32
= Bits32(opcode
, 7, 0) << 2;
11469 regs
= Bits32(opcode
, 7, 0);
11471 // if n == 15 && (wback || CurrentInstrSet() != InstrSet_ARM) then
11473 if ((n
== 15) && (wback
|| (CurrentInstrSet() != eModeARM
)))
11476 // if regs == 0 || (d+regs) > 32 then UNPREDICTABLE;
11477 if ((regs
== 0) || ((d
+ regs
) > 32))
11486 std::optional
<RegisterInfo
> base_reg
=
11487 GetRegisterInfo(eRegisterKindDWARF
, dwarf_r0
+ n
);
11489 uint32_t Rn
= ReadCoreReg(n
, &success
);
11493 // address = if add then R[n] else R[n]-imm32;
11498 address
= Rn
- imm32
;
11500 EmulateInstruction::Context context
;
11501 // if wback then R[n] = if add then R[n]+imm32 else R[n]-imm32;
11505 value
= Rn
+ imm32
;
11507 value
= Rn
- imm32
;
11509 context
.type
= eContextAdjustBaseRegister
;
11510 context
.SetRegisterPlusOffset(*base_reg
, value
- Rn
);
11512 if (!WriteRegisterUnsigned(context
, eRegisterKindDWARF
, dwarf_r0
+ n
,
11517 const uint32_t addr_byte_size
= GetAddressByteSize();
11518 uint32_t start_reg
= single_regs
? dwarf_s0
: dwarf_d0
;
11520 context
.type
= eContextRegisterStore
;
11521 // for r = 0 to regs-1
11522 for (uint32_t r
= 0; r
< regs
; ++r
) {
11525 // MemA[address,4] = S[d+r]; address = address+4;
11526 uint32_t data
= ReadRegisterUnsigned(eRegisterKindDWARF
,
11527 start_reg
+ d
+ r
, 0, &success
);
11531 std::optional
<RegisterInfo
> data_reg
=
11532 GetRegisterInfo(eRegisterKindDWARF
, start_reg
+ d
+ r
);
11533 context
.SetRegisterToRegisterPlusOffset(*data_reg
, *base_reg
,
11535 if (!MemAWrite(context
, address
, data
, addr_byte_size
))
11538 address
= address
+ 4;
11540 // // Store as two word-aligned words in the correct order for current
11541 // endianness. MemA[address,4] = if BigEndian() then D[d+r]<63:32> else
11543 // MemA[address+4,4] = if BigEndian() then D[d+r]<31:0> else
11545 uint64_t data
= ReadRegisterUnsigned(eRegisterKindDWARF
,
11546 start_reg
+ d
+ r
, 0, &success
);
11550 std::optional
<RegisterInfo
> data_reg
=
11551 GetRegisterInfo(eRegisterKindDWARF
, start_reg
+ d
+ r
);
11553 if (GetByteOrder() == eByteOrderBig
) {
11554 context
.SetRegisterToRegisterPlusOffset(*data_reg
, *base_reg
,
11556 if (!MemAWrite(context
, address
, Bits64(data
, 63, 32),
11560 context
.SetRegisterToRegisterPlusOffset(*data_reg
, *base_reg
,
11561 (address
+ 4) - Rn
);
11562 if (!MemAWrite(context
, address
+ 4, Bits64(data
, 31, 0),
11566 context
.SetRegisterToRegisterPlusOffset(*data_reg
, *base_reg
,
11568 if (!MemAWrite(context
, address
, Bits64(data
, 31, 0), addr_byte_size
))
11571 context
.SetRegisterToRegisterPlusOffset(*data_reg
, *base_reg
,
11572 (address
+ 4) - Rn
);
11573 if (!MemAWrite(context
, address
+ 4, Bits64(data
, 63, 32),
11577 // address = address+8;
11578 address
= address
+ 8;
11586 // This instruction loads a single extension register from memory, using an
11587 // address from an ARM core register, with an optional offset.
11588 bool EmulateInstructionARM::EmulateVLDR(const uint32_t opcode
,
11589 ARMEncoding encoding
) {
11591 if ConditionPassed() then
11592 EncodingSpecificOperations(); CheckVFPEnabled(TRUE
); NullCheckIfThumbEE(n
);
11593 base
= if n
== 15 then
Align(PC
,4) else R
[n
];
11594 address
= if add
then (base
+ imm32
) else (base
- imm32
);
11596 S
[d
] = MemA
[address
,4];
11598 word1
= MemA
[address
,4]; word2
= MemA
[address
+4,4];
11599 // Combine the word-aligned words in the correct order for current
11601 D
[d
] = if BigEndian() then word1
:word2
else word2
:word1
;
11604 bool success
= false;
11606 if (ConditionPassed(opcode
)) {
11613 switch (encoding
) {
11616 // single_reg = FALSE; add = (U == '1'); imm32 = ZeroExtend(imm8:'00',
11618 single_reg
= false;
11619 add
= BitIsSet(opcode
, 23);
11620 imm32
= Bits32(opcode
, 7, 0) << 2;
11622 // d = UInt(D:Vd); n = UInt(Rn);
11623 d
= (Bit32(opcode
, 22) << 4) | Bits32(opcode
, 15, 12);
11624 n
= Bits32(opcode
, 19, 16);
11630 // single_reg = TRUE; add = (U == '1'); imm32 = ZeroExtend(imm8:'00', 32);
11632 add
= BitIsSet(opcode
, 23);
11633 imm32
= Bits32(opcode
, 7, 0) << 2;
11635 // d = UInt(Vd:D); n = UInt(Rn);
11636 d
= (Bits32(opcode
, 15, 12) << 1) | Bit32(opcode
, 22);
11637 n
= Bits32(opcode
, 19, 16);
11644 std::optional
<RegisterInfo
> base_reg
=
11645 GetRegisterInfo(eRegisterKindDWARF
, dwarf_r0
+ n
);
11647 uint32_t Rn
= ReadCoreReg(n
, &success
);
11651 // base = if n == 15 then Align(PC,4) else R[n];
11654 base
= AlignPC(Rn
);
11658 // address = if add then (base + imm32) else (base - imm32);
11661 address
= base
+ imm32
;
11663 address
= base
- imm32
;
11665 const uint32_t addr_byte_size
= GetAddressByteSize();
11666 uint32_t start_reg
= single_reg
? dwarf_s0
: dwarf_d0
;
11668 EmulateInstruction::Context context
;
11669 context
.type
= eContextRegisterLoad
;
11670 context
.SetRegisterPlusOffset(*base_reg
, address
- base
);
11673 // S[d] = MemA[address,4];
11674 uint32_t data
= MemARead(context
, address
, addr_byte_size
, 0, &success
);
11678 if (!WriteRegisterUnsigned(context
, eRegisterKindDWARF
, start_reg
+ d
,
11682 // word1 = MemA[address,4]; word2 = MemA[address+4,4];
11683 uint32_t word1
= MemARead(context
, address
, addr_byte_size
, 0, &success
);
11687 context
.SetRegisterPlusOffset(*base_reg
, (address
+ 4) - base
);
11689 MemARead(context
, address
+ 4, addr_byte_size
, 0, &success
);
11692 // // Combine the word-aligned words in the correct order for current
11694 // D[d] = if BigEndian() then word1:word2 else word2:word1;
11696 if (GetByteOrder() == eByteOrderBig
) {
11698 data64
= (data64
<< 32) | word2
;
11701 data64
= (data64
<< 32) | word1
;
11704 if (!WriteRegisterUnsigned(context
, eRegisterKindDWARF
, start_reg
+ d
,
11713 // This instruction stores a signle extension register to memory, using an
11714 // address from an ARM core register, with an optional offset.
11715 bool EmulateInstructionARM::EmulateVSTR(const uint32_t opcode
,
11716 ARMEncoding encoding
) {
11718 if ConditionPassed() then
11719 EncodingSpecificOperations(); CheckVFPEnabled(TRUE
); NullCheckIfThumbEE(n
);
11720 address
= if add
then (R
[n
] + imm32
) else (R
[n
] - imm32
);
11722 MemA
[address
,4] = S
[d
];
11724 // Store as two word-aligned words in the correct order for current
11726 MemA
[address
,4] = if BigEndian() then D
[d
]<63:32> else D
[d
]<31:0>;
11727 MemA
[address
+4,4] = if BigEndian() then D
[d
]<31:0> else D
[d
]<63:32>;
11730 bool success
= false;
11732 if (ConditionPassed(opcode
)) {
11739 switch (encoding
) {
11742 // single_reg = FALSE; add = (U == '1'); imm32 = ZeroExtend(imm8:'00',
11744 single_reg
= false;
11745 add
= BitIsSet(opcode
, 23);
11746 imm32
= Bits32(opcode
, 7, 0) << 2;
11748 // d = UInt(D:Vd); n = UInt(Rn);
11749 d
= (Bit32(opcode
, 22) << 4) | Bits32(opcode
, 15, 12);
11750 n
= Bits32(opcode
, 19, 16);
11752 // if n == 15 && CurrentInstrSet() != InstrSet_ARM then UNPREDICTABLE;
11753 if ((n
== 15) && (CurrentInstrSet() != eModeARM
))
11760 // single_reg = TRUE; add = (U == '1'); imm32 = ZeroExtend(imm8:'00', 32);
11762 add
= BitIsSet(opcode
, 23);
11763 imm32
= Bits32(opcode
, 7, 0) << 2;
11765 // d = UInt(Vd:D); n = UInt(Rn);
11766 d
= (Bits32(opcode
, 15, 12) << 1) | Bit32(opcode
, 22);
11767 n
= Bits32(opcode
, 19, 16);
11769 // if n == 15 && CurrentInstrSet() != InstrSet_ARM then UNPREDICTABLE;
11770 if ((n
== 15) && (CurrentInstrSet() != eModeARM
))
11779 uint32_t Rn
= ReadCoreReg(n
, &success
);
11783 // address = if add then (R[n] + imm32) else (R[n] - imm32);
11786 address
= Rn
+ imm32
;
11788 address
= Rn
- imm32
;
11790 const uint32_t addr_byte_size
= GetAddressByteSize();
11791 uint32_t start_reg
= single_reg
? dwarf_s0
: dwarf_d0
;
11793 std::optional
<RegisterInfo
> base_reg
=
11794 GetRegisterInfo(eRegisterKindDWARF
, dwarf_r0
+ n
);
11795 std::optional
<RegisterInfo
> data_reg
=
11796 GetRegisterInfo(eRegisterKindDWARF
, start_reg
+ d
);
11797 EmulateInstruction::Context context
;
11798 context
.type
= eContextRegisterStore
;
11799 context
.SetRegisterToRegisterPlusOffset(*data_reg
, *base_reg
, address
- Rn
);
11802 // MemA[address,4] = S[d];
11804 ReadRegisterUnsigned(eRegisterKindDWARF
, start_reg
+ d
, 0, &success
);
11808 if (!MemAWrite(context
, address
, data
, addr_byte_size
))
11811 // // Store as two word-aligned words in the correct order for current
11813 // MemA[address,4] = if BigEndian() then D[d]<63:32> else D[d]<31:0>;
11814 // MemA[address+4,4] = if BigEndian() then D[d]<31:0> else D[d]<63:32>;
11816 ReadRegisterUnsigned(eRegisterKindDWARF
, start_reg
+ d
, 0, &success
);
11820 if (GetByteOrder() == eByteOrderBig
) {
11821 if (!MemAWrite(context
, address
, Bits64(data
, 63, 32), addr_byte_size
))
11824 context
.SetRegisterToRegisterPlusOffset(*data_reg
, *base_reg
,
11825 (address
+ 4) - Rn
);
11826 if (!MemAWrite(context
, address
+ 4, Bits64(data
, 31, 0),
11830 if (!MemAWrite(context
, address
, Bits64(data
, 31, 0), addr_byte_size
))
11833 context
.SetRegisterToRegisterPlusOffset(*data_reg
, *base_reg
,
11834 (address
+ 4) - Rn
);
11835 if (!MemAWrite(context
, address
+ 4, Bits64(data
, 63, 32),
11844 // A8.6.307 VLDI1 (multiple single elements) This instruction loads elements
11845 // from memory into one, two, three or four registers, without de-interleaving.
11846 // Every element of each register is loaded.
11847 bool EmulateInstructionARM::EmulateVLD1Multiple(const uint32_t opcode
,
11848 ARMEncoding encoding
) {
11850 if ConditionPassed() then
11851 EncodingSpecificOperations(); CheckAdvSIMDEnabled(); NullCheckIfThumbEE(n
);
11852 address
= R
[n
]; if (address MOD alignment
) != 0 then
GenerateAlignmentException();
11853 if wback then R
[n
] = R
[n
] + (if register_index then R
[m
] else 8*regs
);
11854 for r
= 0 to regs
-1
11855 for e
= 0 to elements
-1
11856 Elem
[D
[d
+r
],e
,esize
] = MemU
[address
,ebytes
];
11857 address
= address
+ ebytes
;
11860 bool success
= false;
11862 if (ConditionPassed(opcode
)) {
11864 uint32_t alignment
;
11872 bool register_index
;
11874 switch (encoding
) {
11876 case eEncodingA1
: {
11879 // regs = 1; if align<1> == '1' then UNDEFINED;
11881 // regs = 2; if align == '11' then UNDEFINED;
11883 // regs = 3; if align<1> == '1' then UNDEFINED;
11887 // SEE 'Related encodings';
11888 uint32_t type
= Bits32(opcode
, 11, 8);
11889 uint32_t align
= Bits32(opcode
, 5, 4);
11890 if (type
== 7) // '0111'
11893 if (BitIsSet(align
, 1))
11895 } else if (type
== 10) // '1010'
11901 } else if (type
== 6) // '0110'
11904 if (BitIsSet(align
, 1))
11906 } else if (type
== 2) // '0010'
11912 // alignment = if align == '00' then 1 else 4 << UInt(align);
11916 alignment
= 4 << align
;
11918 // ebytes = 1 << UInt(size); esize = 8 * ebytes; elements = 8 DIV ebytes;
11919 ebytes
= 1 << Bits32(opcode
, 7, 6);
11920 esize
= 8 * ebytes
;
11921 elements
= 8 / ebytes
;
11923 // d = UInt(D:Vd); n = UInt(Rn); m = UInt(Rm);
11924 d
= (Bit32(opcode
, 22) << 4) | Bits32(opcode
, 15, 12);
11925 n
= Bits32(opcode
, 19, 15);
11926 m
= Bits32(opcode
, 3, 0);
11928 // wback = (m != 15); register_index = (m != 15 && m != 13);
11930 register_index
= ((m
!= 15) && (m
!= 13));
11932 // if d+regs > 32 then UNPREDICTABLE;
11933 if ((d
+ regs
) > 32)
11941 std::optional
<RegisterInfo
> base_reg
=
11942 GetRegisterInfo(eRegisterKindDWARF
, dwarf_r0
+ n
);
11944 uint32_t Rn
= ReadCoreReg(n
, &success
);
11948 // address = R[n]; if (address MOD alignment) != 0 then
11949 // GenerateAlignmentException();
11950 addr_t address
= Rn
;
11951 if ((address
% alignment
) != 0)
11954 EmulateInstruction::Context context
;
11955 // if wback then R[n] = R[n] + (if register_index then R[m] else 8*regs);
11957 uint32_t Rm
= ReadCoreReg(m
, &success
);
11962 if (register_index
)
11967 uint32_t value
= Rn
+ offset
;
11968 context
.type
= eContextAdjustBaseRegister
;
11969 context
.SetRegisterPlusOffset(*base_reg
, offset
);
11971 if (!WriteRegisterUnsigned(context
, eRegisterKindDWARF
, dwarf_r0
+ n
,
11976 // for r = 0 to regs-1
11977 for (uint32_t r
= 0; r
< regs
; ++r
) {
11978 // for e = 0 to elements-1
11979 uint64_t assembled_data
= 0;
11980 for (uint32_t e
= 0; e
< elements
; ++e
) {
11981 // Elem[D[d+r],e,esize] = MemU[address,ebytes];
11982 context
.type
= eContextRegisterLoad
;
11983 context
.SetRegisterPlusOffset(*base_reg
, address
- Rn
);
11984 uint64_t data
= MemURead(context
, address
, ebytes
, 0, &success
);
11989 (data
<< (e
* esize
)) |
11990 assembled_data
; // New data goes to the left of existing data
11992 // address = address + ebytes;
11993 address
= address
+ ebytes
;
11995 if (!WriteRegisterUnsigned(context
, eRegisterKindDWARF
, dwarf_d0
+ d
+ r
,
12003 // A8.6.308 VLD1 (single element to one lane)
12005 bool EmulateInstructionARM::EmulateVLD1Single(const uint32_t opcode
,
12006 const ARMEncoding encoding
) {
12008 if ConditionPassed() then
12009 EncodingSpecificOperations(); CheckAdvSIMDEnabled(); NullCheckIfThumbEE(n
);
12010 address
= R
[n
]; if (address MOD alignment
) != 0 then
GenerateAlignmentException();
12011 if wback then R
[n
] = R
[n
] + (if register_index then R
[m
] else ebytes
);
12012 Elem
[D
[d
],index
,esize
] = MemU
[address
,ebytes
];
12015 bool success
= false;
12017 if (ConditionPassed(opcode
)) {
12021 uint32_t alignment
;
12026 bool register_index
;
12028 switch (encoding
) {
12030 case eEncodingA1
: {
12031 uint32_t size
= Bits32(opcode
, 11, 10);
12032 uint32_t index_align
= Bits32(opcode
, 7, 4);
12033 // if size == '11' then SEE VLD1 (single element to all lanes);
12035 return EmulateVLD1SingleAll(opcode
, encoding
);
12037 if (size
== 0) // when '00'
12039 // if index_align<0> != '0' then UNDEFINED;
12040 if (BitIsClear(index_align
, 0))
12043 // ebytes = 1; esize = 8; index = UInt(index_align<3:1>); alignment = 1;
12046 index
= Bits32(index_align
, 3, 1);
12048 } else if (size
== 1) // when '01'
12050 // if index_align<1> != '0' then UNDEFINED;
12051 if (BitIsClear(index_align
, 1))
12054 // ebytes = 2; esize = 16; index = UInt(index_align<3:2>);
12057 index
= Bits32(index_align
, 3, 2);
12059 // alignment = if index_align<0> == '0' then 1 else 2;
12060 if (BitIsClear(index_align
, 0))
12064 } else if (size
== 2) // when '10'
12066 // if index_align<2> != '0' then UNDEFINED;
12067 if (BitIsClear(index_align
, 2))
12070 // if index_align<1:0> != '00' && index_align<1:0> != '11' then
12072 if ((Bits32(index_align
, 1, 0) != 0) &&
12073 (Bits32(index_align
, 1, 0) != 3))
12076 // ebytes = 4; esize = 32; index = UInt(index_align<3>);
12079 index
= Bit32(index_align
, 3);
12081 // alignment = if index_align<1:0> == '00' then 1 else 4;
12082 if (Bits32(index_align
, 1, 0) == 0)
12089 // d = UInt(D:Vd); n = UInt(Rn); m = UInt(Rm);
12090 d
= (Bit32(opcode
, 22) << 4) | Bits32(opcode
, 15, 12);
12091 n
= Bits32(opcode
, 19, 16);
12092 m
= Bits32(opcode
, 3, 0);
12094 // wback = (m != 15); register_index = (m != 15 && m != 13); if n == 15
12095 // then UNPREDICTABLE;
12097 register_index
= ((m
!= 15) && (m
!= 13));
12108 uint32_t Rn
= ReadCoreReg(n
, &success
);
12112 // address = R[n]; if (address MOD alignment) != 0 then
12113 // GenerateAlignmentException();
12114 addr_t address
= Rn
;
12115 if ((address
% alignment
) != 0)
12118 EmulateInstruction::Context context
;
12119 // if wback then R[n] = R[n] + (if register_index then R[m] else ebytes);
12121 uint32_t Rm
= ReadCoreReg(m
, &success
);
12126 if (register_index
)
12131 uint32_t value
= Rn
+ offset
;
12133 context
.type
= eContextAdjustBaseRegister
;
12134 std::optional
<RegisterInfo
> base_reg
=
12135 GetRegisterInfo(eRegisterKindDWARF
, dwarf_r0
+ n
);
12136 context
.SetRegisterPlusOffset(*base_reg
, offset
);
12138 if (!WriteRegisterUnsigned(context
, eRegisterKindDWARF
, dwarf_r0
+ n
,
12143 // Elem[D[d],index,esize] = MemU[address,ebytes];
12144 uint32_t element
= MemURead(context
, address
, esize
, 0, &success
);
12148 element
= element
<< (index
* esize
);
12150 uint64_t reg_data
=
12151 ReadRegisterUnsigned(eRegisterKindDWARF
, dwarf_d0
+ d
, 0, &success
);
12155 uint64_t all_ones
= -1;
12156 uint64_t mask
= all_ones
12157 << ((index
+ 1) * esize
); // mask is all 1's to left of
12158 // where 'element' goes, & all 0's
12159 // at element & to the right of element.
12161 mask
= mask
| Bits64(all_ones
, (index
* esize
) - 1,
12162 0); // add 1's to the right of where 'element' goes.
12163 // now mask should be 0's where element goes & 1's everywhere else.
12165 uint64_t masked_reg
=
12166 reg_data
& mask
; // Take original reg value & zero out 'element' bits
12168 masked_reg
& element
; // Put 'element' into those bits in reg_data.
12170 context
.type
= eContextRegisterLoad
;
12171 if (!WriteRegisterUnsigned(context
, eRegisterKindDWARF
, dwarf_r0
+ d
,
12178 // A8.6.391 VST1 (multiple single elements) Vector Store (multiple single
12179 // elements) stores elements to memory from one, two, three, or four registers,
12180 // without interleaving. Every element of each register is stored.
12181 bool EmulateInstructionARM::EmulateVST1Multiple(const uint32_t opcode
,
12182 ARMEncoding encoding
) {
12184 if ConditionPassed() then
12185 EncodingSpecificOperations(); CheckAdvSIMDEnabled(); NullCheckIfThumbEE(n
);
12186 address
= R
[n
]; if (address MOD alignment
) != 0 then
GenerateAlignmentException();
12187 if wback then R
[n
] = R
[n
] + (if register_index then R
[m
] else 8*regs
);
12188 for r
= 0 to regs
-1
12189 for e
= 0 to elements
-1
12190 MemU
[address
,ebytes
] = Elem
[D
[d
+r
],e
,esize
];
12191 address
= address
+ ebytes
;
12194 bool success
= false;
12196 if (ConditionPassed(opcode
)) {
12198 uint32_t alignment
;
12206 bool register_index
;
12208 switch (encoding
) {
12210 case eEncodingA1
: {
12211 uint32_t type
= Bits32(opcode
, 11, 8);
12212 uint32_t align
= Bits32(opcode
, 5, 4);
12215 if (type
== 7) // when '0111'
12217 // regs = 1; if align<1> == '1' then UNDEFINED;
12219 if (BitIsSet(align
, 1))
12221 } else if (type
== 10) // when '1010'
12223 // regs = 2; if align == '11' then UNDEFINED;
12227 } else if (type
== 6) // when '0110'
12229 // regs = 3; if align<1> == '1' then UNDEFINED;
12231 if (BitIsSet(align
, 1))
12233 } else if (type
== 2) // when '0010'
12237 // SEE 'Related encodings';
12240 // alignment = if align == '00' then 1 else 4 << UInt(align);
12244 alignment
= 4 << align
;
12246 // ebytes = 1 << UInt(size); esize = 8 * ebytes; elements = 8 DIV ebytes;
12247 ebytes
= 1 << Bits32(opcode
, 7, 6);
12248 esize
= 8 * ebytes
;
12249 elements
= 8 / ebytes
;
12251 // d = UInt(D:Vd); n = UInt(Rn); m = UInt(Rm);
12252 d
= (Bit32(opcode
, 22) << 4) | Bits32(opcode
, 15, 12);
12253 n
= Bits32(opcode
, 19, 16);
12254 m
= Bits32(opcode
, 3, 0);
12256 // wback = (m != 15); register_index = (m != 15 && m != 13);
12258 register_index
= ((m
!= 15) && (m
!= 13));
12260 // if d+regs > 32 then UNPREDICTABLE; if n == 15 then UNPREDICTABLE;
12261 if ((d
+ regs
) > 32)
12273 std::optional
<RegisterInfo
> base_reg
=
12274 GetRegisterInfo(eRegisterKindDWARF
, dwarf_r0
+ n
);
12276 uint32_t Rn
= ReadCoreReg(n
, &success
);
12280 // address = R[n]; if (address MOD alignment) != 0 then
12281 // GenerateAlignmentException();
12282 addr_t address
= Rn
;
12283 if ((address
% alignment
) != 0)
12286 EmulateInstruction::Context context
;
12287 // if wback then R[n] = R[n] + (if register_index then R[m] else 8*regs);
12289 uint32_t Rm
= ReadCoreReg(m
, &success
);
12294 if (register_index
)
12299 context
.type
= eContextAdjustBaseRegister
;
12300 context
.SetRegisterPlusOffset(*base_reg
, offset
);
12302 if (!WriteRegisterUnsigned(context
, eRegisterKindDWARF
, dwarf_r0
+ n
,
12307 context
.type
= eContextRegisterStore
;
12308 // for r = 0 to regs-1
12309 for (uint32_t r
= 0; r
< regs
; ++r
) {
12310 std::optional
<RegisterInfo
> data_reg
=
12311 GetRegisterInfo(eRegisterKindDWARF
, dwarf_d0
+ d
+ r
);
12312 uint64_t register_data
= ReadRegisterUnsigned(
12313 eRegisterKindDWARF
, dwarf_d0
+ d
+ r
, 0, &success
);
12317 // for e = 0 to elements-1
12318 for (uint32_t e
= 0; e
< elements
; ++e
) {
12319 // MemU[address,ebytes] = Elem[D[d+r],e,esize];
12320 uint64_t word
= Bits64(register_data
, ((e
+ 1) * esize
) - 1, e
* esize
);
12322 context
.SetRegisterToRegisterPlusOffset(*data_reg
, *base_reg
,
12324 if (!MemUWrite(context
, address
, word
, ebytes
))
12327 // address = address + ebytes;
12328 address
= address
+ ebytes
;
12335 // A8.6.392 VST1 (single element from one lane) This instruction stores one
12336 // element to memory from one element of a register.
12337 bool EmulateInstructionARM::EmulateVST1Single(const uint32_t opcode
,
12338 ARMEncoding encoding
) {
12340 if ConditionPassed() then
12341 EncodingSpecificOperations(); CheckAdvSIMDEnabled(); NullCheckIfThumbEE(n
);
12342 address
= R
[n
]; if (address MOD alignment
) != 0 then
GenerateAlignmentException();
12343 if wback then R
[n
] = R
[n
] + (if register_index then R
[m
] else ebytes
);
12344 MemU
[address
,ebytes
] = Elem
[D
[d
],index
,esize
];
12347 bool success
= false;
12349 if (ConditionPassed(opcode
)) {
12353 uint32_t alignment
;
12358 bool register_index
;
12360 switch (encoding
) {
12362 case eEncodingA1
: {
12363 uint32_t size
= Bits32(opcode
, 11, 10);
12364 uint32_t index_align
= Bits32(opcode
, 7, 4);
12366 // if size == '11' then UNDEFINED;
12371 if (size
== 0) // when '00'
12373 // if index_align<0> != '0' then UNDEFINED;
12374 if (BitIsClear(index_align
, 0))
12376 // ebytes = 1; esize = 8; index = UInt(index_align<3:1>); alignment = 1;
12379 index
= Bits32(index_align
, 3, 1);
12381 } else if (size
== 1) // when '01'
12383 // if index_align<1> != '0' then UNDEFINED;
12384 if (BitIsClear(index_align
, 1))
12387 // ebytes = 2; esize = 16; index = UInt(index_align<3:2>);
12390 index
= Bits32(index_align
, 3, 2);
12392 // alignment = if index_align<0> == '0' then 1 else 2;
12393 if (BitIsClear(index_align
, 0))
12397 } else if (size
== 2) // when '10'
12399 // if index_align<2> != '0' then UNDEFINED;
12400 if (BitIsClear(index_align
, 2))
12403 // if index_align<1:0> != '00' && index_align<1:0> != '11' then
12405 if ((Bits32(index_align
, 1, 0) != 0) &&
12406 (Bits32(index_align
, 1, 0) != 3))
12409 // ebytes = 4; esize = 32; index = UInt(index_align<3>);
12412 index
= Bit32(index_align
, 3);
12414 // alignment = if index_align<1:0> == '00' then 1 else 4;
12415 if (Bits32(index_align
, 1, 0) == 0)
12422 // d = UInt(D:Vd); n = UInt(Rn); m = UInt(Rm);
12423 d
= (Bit32(opcode
, 22) << 4) | Bits32(opcode
, 15, 12);
12424 n
= Bits32(opcode
, 19, 16);
12425 m
= Bits32(opcode
, 3, 0);
12427 // wback = (m != 15); register_index = (m != 15 && m != 13); if n == 15
12428 // then UNPREDICTABLE;
12430 register_index
= ((m
!= 15) && (m
!= 13));
12440 std::optional
<RegisterInfo
> base_reg
=
12441 GetRegisterInfo(eRegisterKindDWARF
, dwarf_r0
+ n
);
12443 uint32_t Rn
= ReadCoreReg(n
, &success
);
12447 // address = R[n]; if (address MOD alignment) != 0 then
12448 // GenerateAlignmentException();
12449 addr_t address
= Rn
;
12450 if ((address
% alignment
) != 0)
12453 EmulateInstruction::Context context
;
12454 // if wback then R[n] = R[n] + (if register_index then R[m] else ebytes);
12456 uint32_t Rm
= ReadCoreReg(m
, &success
);
12461 if (register_index
)
12466 context
.type
= eContextAdjustBaseRegister
;
12467 context
.SetRegisterPlusOffset(*base_reg
, offset
);
12469 if (!WriteRegisterUnsigned(context
, eRegisterKindDWARF
, dwarf_r0
+ n
,
12474 // MemU[address,ebytes] = Elem[D[d],index,esize];
12475 uint64_t register_data
=
12476 ReadRegisterUnsigned(eRegisterKindDWARF
, dwarf_d0
+ d
, 0, &success
);
12481 Bits64(register_data
, ((index
+ 1) * esize
) - 1, index
* esize
);
12483 std::optional
<RegisterInfo
> data_reg
=
12484 GetRegisterInfo(eRegisterKindDWARF
, dwarf_d0
+ d
);
12485 context
.type
= eContextRegisterStore
;
12486 context
.SetRegisterToRegisterPlusOffset(*data_reg
, *base_reg
, address
- Rn
);
12488 if (!MemUWrite(context
, address
, word
, ebytes
))
12494 // A8.6.309 VLD1 (single element to all lanes) This instruction loads one
12495 // element from memory into every element of one or two vectors.
12496 bool EmulateInstructionARM::EmulateVLD1SingleAll(const uint32_t opcode
,
12497 const ARMEncoding encoding
) {
12499 if ConditionPassed() then
12500 EncodingSpecificOperations(); CheckAdvSIMDEnabled(); NullCheckIfThumbEE(n
);
12501 address
= R
[n
]; if (address MOD alignment
) != 0 then
GenerateAlignmentException();
12502 if wback then R
[n
] = R
[n
] + (if register_index then R
[m
] else ebytes
);
12503 replicated_element
= Replicate(MemU
[address
,ebytes
], elements
);
12504 for r
= 0 to regs
-1
12505 D
[d
+r
] = replicated_element
;
12508 bool success
= false;
12510 if (ConditionPassed(opcode
)) {
12514 uint32_t alignment
;
12519 bool register_index
;
12521 switch (encoding
) {
12523 case eEncodingA1
: {
12524 // if size == '11' || (size == '00' && a == '1') then UNDEFINED;
12525 uint32_t size
= Bits32(opcode
, 7, 6);
12526 if ((size
== 3) || ((size
== 0) && BitIsSet(opcode
, 4)))
12529 // ebytes = 1 << UInt(size); elements = 8 DIV ebytes; regs = if T == '0'
12531 ebytes
= 1 << size
;
12532 elements
= 8 / ebytes
;
12533 if (BitIsClear(opcode
, 5))
12538 // alignment = if a == '0' then 1 else ebytes;
12539 if (BitIsClear(opcode
, 4))
12542 alignment
= ebytes
;
12544 // d = UInt(D:Vd); n = UInt(Rn); m = UInt(Rm);
12545 d
= (Bit32(opcode
, 22) << 4) | Bits32(opcode
, 15, 12);
12546 n
= Bits32(opcode
, 19, 16);
12547 m
= Bits32(opcode
, 3, 0);
12549 // wback = (m != 15); register_index = (m != 15 && m != 13);
12551 register_index
= ((m
!= 15) && (m
!= 13));
12553 // if d+regs > 32 then UNPREDICTABLE; if n == 15 then UNPREDICTABLE;
12554 if ((d
+ regs
) > 32)
12565 uint32_t Rn
= ReadCoreReg(n
, &success
);
12569 // address = R[n]; if (address MOD alignment) != 0 then
12570 // GenerateAlignmentException();
12571 addr_t address
= Rn
;
12572 if ((address
% alignment
) != 0)
12575 EmulateInstruction::Context context
;
12576 // if wback then R[n] = R[n] + (if register_index then R[m] else ebytes);
12578 uint32_t Rm
= ReadCoreReg(m
, &success
);
12583 if (register_index
)
12588 context
.type
= eContextAdjustBaseRegister
;
12589 std::optional
<RegisterInfo
> base_reg
=
12590 GetRegisterInfo(eRegisterKindDWARF
, dwarf_r0
+ n
);
12591 context
.SetRegisterPlusOffset(*base_reg
, offset
);
12593 if (!WriteRegisterUnsigned(context
, eRegisterKindDWARF
, dwarf_r0
+ n
,
12598 // replicated_element = Replicate(MemU[address,ebytes], elements);
12600 context
.type
= eContextRegisterLoad
;
12601 uint64_t word
= MemURead(context
, address
, ebytes
, 0, &success
);
12605 uint64_t replicated_element
= 0;
12606 uint32_t esize
= ebytes
* 8;
12607 for (uint32_t e
= 0; e
< elements
; ++e
)
12608 replicated_element
=
12609 (replicated_element
<< esize
) | Bits64(word
, esize
- 1, 0);
12611 // for r = 0 to regs-1
12612 for (uint32_t r
= 0; r
< regs
; ++r
) {
12613 // D[d+r] = replicated_element;
12614 if (!WriteRegisterUnsigned(context
, eRegisterKindDWARF
, dwarf_d0
+ d
+ r
,
12615 replicated_element
))
12622 // B6.2.13 SUBS PC, LR and related instructions The SUBS PC, LR, #<const?
12623 // instruction provides an exception return without the use of the stack. It
12624 // subtracts the immediate constant from the LR, branches to the resulting
12625 // address, and also copies the SPSR to the CPSR.
12626 bool EmulateInstructionARM::EmulateSUBSPcLrEtc(const uint32_t opcode
,
12627 const ARMEncoding encoding
) {
12629 if ConditionPassed() then
12630 EncodingSpecificOperations();
12631 if CurrentInstrSet() == InstrSet_ThumbEE then
12633 operand2
= if register_form then
Shift(R
[m
], shift_t
, shift_n
, APSR
.C
) else imm32
;
12635 when
'0000' result
= R
[n
] AND operand2
; // AND
12636 when
'0001' result
= R
[n
] EOR operand2
; // EOR
12637 when
'0010' (result
, -, -) = AddWithCarry(R
[n
], NOT(operand2
), '1'); // SUB
12638 when
'0011' (result
, -, -) = AddWithCarry(NOT(R
[n
]), operand2
, '1'); // RSB
12639 when
'0100' (result
, -, -) = AddWithCarry(R
[n
], operand2
, '0'); // ADD
12640 when
'0101' (result
, -, -) = AddWithCarry(R
[n
], operand2
, APSR
.c
); // ADC
12641 when
'0110' (result
, -, -) = AddWithCarry(R
[n
], NOT(operand2
), APSR
.C
); // SBC
12642 when
'0111' (result
, -, -) = AddWithCarry(NOT(R
[n
]), operand2
, APSR
.C
); // RSC
12643 when
'1100' result
= R
[n
] OR operand2
; // ORR
12644 when
'1101' result
= operand2
; // MOV
12645 when
'1110' result
= R
[n
] AND
NOT(operand2
); // BIC
12646 when
'1111' result
= NOT(operand2
); // MVN
12647 CPSRWriteByInstr(SPSR
[], '1111', TRUE
);
12648 BranchWritePC(result
);
12651 bool success
= false;
12653 if (ConditionPassed(opcode
)) {
12657 bool register_form
;
12658 ARM_ShifterType shift_t
;
12662 switch (encoding
) {
12664 // if CurrentInstrSet() == InstrSet_ThumbEE then UNPREDICTABLE n = 14;
12665 // imm32 = ZeroExtend(imm8, 32); register_form = FALSE; opcode = '0010';
12668 imm32
= Bits32(opcode
, 7, 0);
12669 register_form
= false;
12672 // if InITBlock() && !LastInITBlock() then UNPREDICTABLE;
12673 if (InITBlock() && !LastInITBlock())
12679 // n = UInt(Rn); imm32 = ARMExpandImm(imm12); register_form = FALSE;
12680 n
= Bits32(opcode
, 19, 16);
12681 imm32
= ARMExpandImm(opcode
);
12682 register_form
= false;
12683 code
= Bits32(opcode
, 24, 21);
12688 // n = UInt(Rn); m = UInt(Rm); register_form = TRUE;
12689 n
= Bits32(opcode
, 19, 16);
12690 m
= Bits32(opcode
, 3, 0);
12691 register_form
= true;
12693 // (shift_t, shift_n) = DecodeImmShift(type, imm5);
12694 shift_n
= DecodeImmShiftARM(opcode
, shift_t
);
12702 // operand2 = if register_form then Shift(R[m], shift_t, shift_n, APSR.C)
12705 if (register_form
) {
12706 uint32_t Rm
= ReadCoreReg(m
, &success
);
12710 operand2
= Shift(Rm
, shift_t
, shift_n
, APSR_C
, &success
);
12717 uint32_t Rn
= ReadCoreReg(n
, &success
);
12721 AddWithCarryResult result
;
12725 case 0: // when '0000'
12726 // result = R[n] AND operand2; // AND
12727 result
.result
= Rn
& operand2
;
12730 case 1: // when '0001'
12731 // result = R[n] EOR operand2; // EOR
12732 result
.result
= Rn
^ operand2
;
12735 case 2: // when '0010'
12736 // (result, -, -) = AddWithCarry(R[n], NOT(operand2), '1'); // SUB
12737 result
= AddWithCarry(Rn
, ~(operand2
), 1);
12740 case 3: // when '0011'
12741 // (result, -, -) = AddWithCarry(NOT(R[n]), operand2, '1'); // RSB
12742 result
= AddWithCarry(~(Rn
), operand2
, 1);
12745 case 4: // when '0100'
12746 // (result, -, -) = AddWithCarry(R[n], operand2, '0'); // ADD
12747 result
= AddWithCarry(Rn
, operand2
, 0);
12750 case 5: // when '0101'
12751 // (result, -, -) = AddWithCarry(R[n], operand2, APSR.c); // ADC
12752 result
= AddWithCarry(Rn
, operand2
, APSR_C
);
12755 case 6: // when '0110'
12756 // (result, -, -) = AddWithCarry(R[n], NOT(operand2), APSR.C); // SBC
12757 result
= AddWithCarry(Rn
, ~(operand2
), APSR_C
);
12760 case 7: // when '0111'
12761 // (result, -, -) = AddWithCarry(NOT(R[n]), operand2, APSR.C); // RSC
12762 result
= AddWithCarry(~(Rn
), operand2
, APSR_C
);
12765 case 10: // when '1100'
12766 // result = R[n] OR operand2; // ORR
12767 result
.result
= Rn
| operand2
;
12770 case 11: // when '1101'
12771 // result = operand2; // MOV
12772 result
.result
= operand2
;
12775 case 12: // when '1110'
12776 // result = R[n] AND NOT(operand2); // BIC
12777 result
.result
= Rn
& ~(operand2
);
12780 case 15: // when '1111'
12781 // result = NOT(operand2); // MVN
12782 result
.result
= ~(operand2
);
12788 // CPSRWriteByInstr(SPSR[], '1111', TRUE);
12790 // For now, in emulation mode, we don't have access to the SPSR, so we will
12791 // use the CPSR instead, and hope for the best.
12793 ReadRegisterUnsigned(eRegisterKindDWARF
, dwarf_cpsr
, 0, &success
);
12797 CPSRWriteByInstr(spsr
, 15, true);
12799 // BranchWritePC(result);
12800 EmulateInstruction::Context context
;
12801 context
.type
= eContextAdjustPC
;
12802 context
.SetImmediate(result
.result
);
12804 BranchWritePC(context
, result
.result
);
12809 EmulateInstructionARM::ARMOpcode
*
12810 EmulateInstructionARM::GetARMOpcodeForInstruction(const uint32_t opcode
,
12811 uint32_t arm_isa
) {
12812 static ARMOpcode g_arm_opcodes
[] = {
12813 // Prologue instructions
12815 // push register(s)
12816 {0x0fff0000, 0x092d0000, ARMvAll
, eEncodingA1
, No_VFP
, eSize32
,
12817 &EmulateInstructionARM::EmulatePUSH
, "push <registers>"},
12818 {0x0fff0fff, 0x052d0004, ARMvAll
, eEncodingA2
, No_VFP
, eSize32
,
12819 &EmulateInstructionARM::EmulatePUSH
, "push <register>"},
12821 // set r7 to point to a stack offset
12822 {0x0ffff000, 0x028d7000, ARMvAll
, eEncodingA1
, No_VFP
, eSize32
,
12823 &EmulateInstructionARM::EmulateADDRdSPImm
, "add r7, sp, #<const>"},
12824 {0x0ffff000, 0x024c7000, ARMvAll
, eEncodingA1
, No_VFP
, eSize32
,
12825 &EmulateInstructionARM::EmulateSUBR7IPImm
, "sub r7, ip, #<const>"},
12826 // copy the stack pointer to ip
12827 {0x0fffffff, 0x01a0c00d, ARMvAll
, eEncodingA1
, No_VFP
, eSize32
,
12828 &EmulateInstructionARM::EmulateMOVRdSP
, "mov ip, sp"},
12829 {0x0ffff000, 0x028dc000, ARMvAll
, eEncodingA1
, No_VFP
, eSize32
,
12830 &EmulateInstructionARM::EmulateADDRdSPImm
, "add ip, sp, #<const>"},
12831 {0x0ffff000, 0x024dc000, ARMvAll
, eEncodingA1
, No_VFP
, eSize32
,
12832 &EmulateInstructionARM::EmulateSUBIPSPImm
, "sub ip, sp, #<const>"},
12834 // adjust the stack pointer
12835 {0x0ffff000, 0x024dd000, ARMvAll
, eEncodingA1
, No_VFP
, eSize32
,
12836 &EmulateInstructionARM::EmulateSUBSPImm
, "sub sp, sp, #<const>"},
12837 {0x0fef0010, 0x004d0000, ARMvAll
, eEncodingA1
, No_VFP
, eSize32
,
12838 &EmulateInstructionARM::EmulateSUBSPReg
,
12839 "sub{s}<c> <Rd>, sp, <Rm>{,<shift>}"},
12841 // push one register
12842 // if Rn == '1101' && imm12 == '000000000100' then SEE PUSH;
12843 {0x0e5f0000, 0x040d0000, ARMvAll
, eEncodingA1
, No_VFP
, eSize32
,
12844 &EmulateInstructionARM::EmulateSTRRtSP
, "str Rt, [sp, #-imm12]!"},
12846 // vector push consecutive extension register(s)
12847 {0x0fbf0f00, 0x0d2d0b00, ARMV6T2_ABOVE
, eEncodingA1
, No_VFP
, eSize32
,
12848 &EmulateInstructionARM::EmulateVPUSH
, "vpush.64 <list>"},
12849 {0x0fbf0f00, 0x0d2d0a00, ARMV6T2_ABOVE
, eEncodingA2
, No_VFP
, eSize32
,
12850 &EmulateInstructionARM::EmulateVPUSH
, "vpush.32 <list>"},
12852 // Epilogue instructions
12854 {0x0fff0000, 0x08bd0000, ARMvAll
, eEncodingA1
, No_VFP
, eSize32
,
12855 &EmulateInstructionARM::EmulatePOP
, "pop <registers>"},
12856 {0x0fff0fff, 0x049d0004, ARMvAll
, eEncodingA2
, No_VFP
, eSize32
,
12857 &EmulateInstructionARM::EmulatePOP
, "pop <register>"},
12858 {0x0fbf0f00, 0x0cbd0b00, ARMV6T2_ABOVE
, eEncodingA1
, No_VFP
, eSize32
,
12859 &EmulateInstructionARM::EmulateVPOP
, "vpop.64 <list>"},
12860 {0x0fbf0f00, 0x0cbd0a00, ARMV6T2_ABOVE
, eEncodingA2
, No_VFP
, eSize32
,
12861 &EmulateInstructionARM::EmulateVPOP
, "vpop.32 <list>"},
12863 // Supervisor Call (previously Software Interrupt)
12864 {0x0f000000, 0x0f000000, ARMvAll
, eEncodingA1
, No_VFP
, eSize32
,
12865 &EmulateInstructionARM::EmulateSVC
, "svc #imm24"},
12867 // Branch instructions
12868 // To resolve ambiguity, "blx <label>" should come before "b #imm24" and
12870 {0xfe000000, 0xfa000000, ARMV5_ABOVE
, eEncodingA2
, No_VFP
, eSize32
,
12871 &EmulateInstructionARM::EmulateBLXImmediate
, "blx <label>"},
12872 {0x0f000000, 0x0a000000, ARMvAll
, eEncodingA1
, No_VFP
, eSize32
,
12873 &EmulateInstructionARM::EmulateB
, "b #imm24"},
12874 {0x0f000000, 0x0b000000, ARMvAll
, eEncodingA1
, No_VFP
, eSize32
,
12875 &EmulateInstructionARM::EmulateBLXImmediate
, "bl <label>"},
12876 {0x0ffffff0, 0x012fff30, ARMV5_ABOVE
, eEncodingA1
, No_VFP
, eSize32
,
12877 &EmulateInstructionARM::EmulateBLXRm
, "blx <Rm>"},
12878 // for example, "bx lr"
12879 {0x0ffffff0, 0x012fff10, ARMvAll
, eEncodingA1
, No_VFP
, eSize32
,
12880 &EmulateInstructionARM::EmulateBXRm
, "bx <Rm>"},
12882 {0x0ffffff0, 0x012fff20, ARMvAll
, eEncodingA1
, No_VFP
, eSize32
,
12883 &EmulateInstructionARM::EmulateBXJRm
, "bxj <Rm>"},
12885 // Data-processing instructions
12887 {0x0fe00000, 0x02a00000, ARMvAll
, eEncodingA1
, No_VFP
, eSize32
,
12888 &EmulateInstructionARM::EmulateADCImm
, "adc{s}<c> <Rd>, <Rn>, #const"},
12890 {0x0fe00010, 0x00a00000, ARMvAll
, eEncodingA1
, No_VFP
, eSize32
,
12891 &EmulateInstructionARM::EmulateADCReg
,
12892 "adc{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
12894 {0x0fe00000, 0x02800000, ARMvAll
, eEncodingA1
, No_VFP
, eSize32
,
12895 &EmulateInstructionARM::EmulateADDImmARM
,
12896 "add{s}<c> <Rd>, <Rn>, #const"},
12898 {0x0fe00010, 0x00800000, ARMvAll
, eEncodingA1
, No_VFP
, eSize32
,
12899 &EmulateInstructionARM::EmulateADDReg
,
12900 "add{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
12901 // add (register-shifted register)
12902 {0x0fe00090, 0x00800010, ARMvAll
, eEncodingA1
, No_VFP
, eSize32
,
12903 &EmulateInstructionARM::EmulateADDRegShift
,
12904 "add{s}<c> <Rd>, <Rn>, <Rm>, <type> <RS>"},
12906 {0x0fff0000, 0x028f0000, ARMvAll
, eEncodingA1
, No_VFP
, eSize32
,
12907 &EmulateInstructionARM::EmulateADR
, "add<c> <Rd>, PC, #<const>"},
12908 {0x0fff0000, 0x024f0000, ARMvAll
, eEncodingA2
, No_VFP
, eSize32
,
12909 &EmulateInstructionARM::EmulateADR
, "sub<c> <Rd>, PC, #<const>"},
12911 {0x0fe00000, 0x02000000, ARMvAll
, eEncodingA1
, No_VFP
, eSize32
,
12912 &EmulateInstructionARM::EmulateANDImm
, "and{s}<c> <Rd>, <Rn>, #const"},
12914 {0x0fe00010, 0x00000000, ARMvAll
, eEncodingA1
, No_VFP
, eSize32
,
12915 &EmulateInstructionARM::EmulateANDReg
,
12916 "and{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
12918 {0x0fe00000, 0x03c00000, ARMvAll
, eEncodingA1
, No_VFP
, eSize32
,
12919 &EmulateInstructionARM::EmulateBICImm
, "bic{s}<c> <Rd>, <Rn>, #const"},
12921 {0x0fe00010, 0x01c00000, ARMvAll
, eEncodingA1
, No_VFP
, eSize32
,
12922 &EmulateInstructionARM::EmulateBICReg
,
12923 "bic{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
12925 {0x0fe00000, 0x02200000, ARMvAll
, eEncodingA1
, No_VFP
, eSize32
,
12926 &EmulateInstructionARM::EmulateEORImm
, "eor{s}<c> <Rd>, <Rn>, #const"},
12928 {0x0fe00010, 0x00200000, ARMvAll
, eEncodingA1
, No_VFP
, eSize32
,
12929 &EmulateInstructionARM::EmulateEORReg
,
12930 "eor{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
12932 {0x0fe00000, 0x03800000, ARMvAll
, eEncodingA1
, No_VFP
, eSize32
,
12933 &EmulateInstructionARM::EmulateORRImm
, "orr{s}<c> <Rd>, <Rn>, #const"},
12935 {0x0fe00010, 0x01800000, ARMvAll
, eEncodingA1
, No_VFP
, eSize32
,
12936 &EmulateInstructionARM::EmulateORRReg
,
12937 "orr{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
12939 {0x0fe00000, 0x02600000, ARMvAll
, eEncodingA1
, No_VFP
, eSize32
,
12940 &EmulateInstructionARM::EmulateRSBImm
, "rsb{s}<c> <Rd>, <Rn>, #<const>"},
12942 {0x0fe00010, 0x00600000, ARMvAll
, eEncodingA1
, No_VFP
, eSize32
,
12943 &EmulateInstructionARM::EmulateRSBReg
,
12944 "rsb{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
12946 {0x0fe00000, 0x02e00000, ARMvAll
, eEncodingA1
, No_VFP
, eSize32
,
12947 &EmulateInstructionARM::EmulateRSCImm
, "rsc{s}<c> <Rd>, <Rn>, #<const>"},
12949 {0x0fe00010, 0x00e00000, ARMvAll
, eEncodingA1
, No_VFP
, eSize32
,
12950 &EmulateInstructionARM::EmulateRSCReg
,
12951 "rsc{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
12953 {0x0fe00000, 0x02c00000, ARMvAll
, eEncodingA1
, No_VFP
, eSize32
,
12954 &EmulateInstructionARM::EmulateSBCImm
, "sbc{s}<c> <Rd>, <Rn>, #<const>"},
12956 {0x0fe00010, 0x00c00000, ARMvAll
, eEncodingA1
, No_VFP
, eSize32
,
12957 &EmulateInstructionARM::EmulateSBCReg
,
12958 "sbc{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
12959 // sub (immediate, ARM)
12960 {0x0fe00000, 0x02400000, ARMvAll
, eEncodingA1
, No_VFP
, eSize32
,
12961 &EmulateInstructionARM::EmulateSUBImmARM
,
12962 "sub{s}<c> <Rd>, <Rn>, #<const>"},
12963 // sub (sp minus immediate)
12964 {0x0fef0000, 0x024d0000, ARMvAll
, eEncodingA1
, No_VFP
, eSize32
,
12965 &EmulateInstructionARM::EmulateSUBSPImm
, "sub{s}<c> <Rd>, sp, #<const>"},
12967 {0x0fe00010, 0x00400000, ARMvAll
, eEncodingA1
, No_VFP
, eSize32
,
12968 &EmulateInstructionARM::EmulateSUBReg
,
12969 "sub{s}<c> <Rd>, <Rn>, <Rm>{,<shift>}"},
12971 {0x0ff0f000, 0x03300000, ARMvAll
, eEncodingA1
, No_VFP
, eSize32
,
12972 &EmulateInstructionARM::EmulateTEQImm
, "teq<c> <Rn>, #const"},
12974 {0x0ff0f010, 0x01300000, ARMvAll
, eEncodingA1
, No_VFP
, eSize32
,
12975 &EmulateInstructionARM::EmulateTEQReg
, "teq<c> <Rn>, <Rm> {,<shift>}"},
12977 {0x0ff0f000, 0x03100000, ARMvAll
, eEncodingA1
, No_VFP
, eSize32
,
12978 &EmulateInstructionARM::EmulateTSTImm
, "tst<c> <Rn>, #const"},
12980 {0x0ff0f010, 0x01100000, ARMvAll
, eEncodingA1
, No_VFP
, eSize32
,
12981 &EmulateInstructionARM::EmulateTSTReg
, "tst<c> <Rn>, <Rm> {,<shift>}"},
12984 {0x0fef0000, 0x03a00000, ARMvAll
, eEncodingA1
, No_VFP
, eSize32
,
12985 &EmulateInstructionARM::EmulateMOVRdImm
, "mov{s}<c> <Rd>, #<const>"},
12986 {0x0ff00000, 0x03000000, ARMV6T2_ABOVE
, eEncodingA2
, No_VFP
, eSize32
,
12987 &EmulateInstructionARM::EmulateMOVRdImm
, "movw<c> <Rd>, #<imm16>"},
12989 {0x0fef0ff0, 0x01a00000, ARMvAll
, eEncodingA1
, No_VFP
, eSize32
,
12990 &EmulateInstructionARM::EmulateMOVRdRm
, "mov{s}<c> <Rd>, <Rm>"},
12992 {0x0fef0000, 0x03e00000, ARMvAll
, eEncodingA1
, No_VFP
, eSize32
,
12993 &EmulateInstructionARM::EmulateMVNImm
, "mvn{s}<c> <Rd>, #<const>"},
12995 {0x0fef0010, 0x01e00000, ARMvAll
, eEncodingA1
, No_VFP
, eSize32
,
12996 &EmulateInstructionARM::EmulateMVNReg
,
12997 "mvn{s}<c> <Rd>, <Rm> {,<shift>}"},
12999 {0x0ff0f000, 0x03700000, ARMvAll
, eEncodingA1
, No_VFP
, eSize32
,
13000 &EmulateInstructionARM::EmulateCMNImm
, "cmn<c> <Rn>, #<const>"},
13002 {0x0ff0f010, 0x01700000, ARMvAll
, eEncodingA1
, No_VFP
, eSize32
,
13003 &EmulateInstructionARM::EmulateCMNReg
, "cmn<c> <Rn>, <Rm> {,<shift>}"},
13005 {0x0ff0f000, 0x03500000, ARMvAll
, eEncodingA1
, No_VFP
, eSize32
,
13006 &EmulateInstructionARM::EmulateCMPImm
, "cmp<c> <Rn>, #<const>"},
13008 {0x0ff0f010, 0x01500000, ARMvAll
, eEncodingA1
, No_VFP
, eSize32
,
13009 &EmulateInstructionARM::EmulateCMPReg
, "cmp<c> <Rn>, <Rm> {,<shift>}"},
13011 {0x0fef0070, 0x01a00040, ARMvAll
, eEncodingA1
, No_VFP
, eSize32
,
13012 &EmulateInstructionARM::EmulateASRImm
, "asr{s}<c> <Rd>, <Rm>, #imm"},
13014 {0x0fef00f0, 0x01a00050, ARMvAll
, eEncodingA1
, No_VFP
, eSize32
,
13015 &EmulateInstructionARM::EmulateASRReg
, "asr{s}<c> <Rd>, <Rn>, <Rm>"},
13017 {0x0fef0070, 0x01a00000, ARMvAll
, eEncodingA1
, No_VFP
, eSize32
,
13018 &EmulateInstructionARM::EmulateLSLImm
, "lsl{s}<c> <Rd>, <Rm>, #imm"},
13020 {0x0fef00f0, 0x01a00010, ARMvAll
, eEncodingA1
, No_VFP
, eSize32
,
13021 &EmulateInstructionARM::EmulateLSLReg
, "lsl{s}<c> <Rd>, <Rn>, <Rm>"},
13023 {0x0fef0070, 0x01a00020, ARMvAll
, eEncodingA1
, No_VFP
, eSize32
,
13024 &EmulateInstructionARM::EmulateLSRImm
, "lsr{s}<c> <Rd>, <Rm>, #imm"},
13026 {0x0fef00f0, 0x01a00050, ARMvAll
, eEncodingA1
, No_VFP
, eSize32
,
13027 &EmulateInstructionARM::EmulateLSRReg
, "lsr{s}<c> <Rd>, <Rn>, <Rm>"},
13028 // rrx is a special case encoding of ror (immediate)
13029 {0x0fef0ff0, 0x01a00060, ARMvAll
, eEncodingA1
, No_VFP
, eSize32
,
13030 &EmulateInstructionARM::EmulateRRX
, "rrx{s}<c> <Rd>, <Rm>"},
13032 {0x0fef0070, 0x01a00060, ARMvAll
, eEncodingA1
, No_VFP
, eSize32
,
13033 &EmulateInstructionARM::EmulateRORImm
, "ror{s}<c> <Rd>, <Rm>, #imm"},
13035 {0x0fef00f0, 0x01a00070, ARMvAll
, eEncodingA1
, No_VFP
, eSize32
,
13036 &EmulateInstructionARM::EmulateRORReg
, "ror{s}<c> <Rd>, <Rn>, <Rm>"},
13038 {0x0fe000f0, 0x00000090, ARMvAll
, eEncodingA1
, No_VFP
, eSize32
,
13039 &EmulateInstructionARM::EmulateMUL
, "mul{s}<c> <Rd>,<R>,<Rm>"},
13041 // subs pc, lr and related instructions
13042 {0x0e10f000, 0x0210f000, ARMvAll
, eEncodingA1
, No_VFP
, eSize32
,
13043 &EmulateInstructionARM::EmulateSUBSPcLrEtc
,
13044 "<opc>S<c> PC,#<const> | <Rn>,#<const>"},
13045 {0x0e10f010, 0x0010f000, ARMvAll
, eEncodingA2
, No_VFP
, eSize32
,
13046 &EmulateInstructionARM::EmulateSUBSPcLrEtc
,
13047 "<opc>S<c> PC,<Rn>,<Rm{,<shift>}"},
13049 // Load instructions
13050 {0x0fd00000, 0x08900000, ARMvAll
, eEncodingA1
, No_VFP
, eSize32
,
13051 &EmulateInstructionARM::EmulateLDM
, "ldm<c> <Rn>{!} <registers>"},
13052 {0x0fd00000, 0x08100000, ARMvAll
, eEncodingA1
, No_VFP
, eSize32
,
13053 &EmulateInstructionARM::EmulateLDMDA
, "ldmda<c> <Rn>{!} <registers>"},
13054 {0x0fd00000, 0x09100000, ARMvAll
, eEncodingA1
, No_VFP
, eSize32
,
13055 &EmulateInstructionARM::EmulateLDMDB
, "ldmdb<c> <Rn>{!} <registers>"},
13056 {0x0fd00000, 0x09900000, ARMvAll
, eEncodingA1
, No_VFP
, eSize32
,
13057 &EmulateInstructionARM::EmulateLDMIB
, "ldmib<c> <Rn<{!} <registers>"},
13058 {0x0e500000, 0x04100000, ARMvAll
, eEncodingA1
, No_VFP
, eSize32
,
13059 &EmulateInstructionARM::EmulateLDRImmediateARM
,
13060 "ldr<c> <Rt> [<Rn> {#+/-<imm12>}]"},
13061 {0x0e500010, 0x06100000, ARMvAll
, eEncodingA1
, No_VFP
, eSize32
,
13062 &EmulateInstructionARM::EmulateLDRRegister
,
13063 "ldr<c> <Rt> [<Rn> +/-<Rm> {<shift>}] {!}"},
13064 {0x0e5f0000, 0x045f0000, ARMvAll
, eEncodingA1
, No_VFP
, eSize32
,
13065 &EmulateInstructionARM::EmulateLDRBLiteral
, "ldrb<c> <Rt>, [...]"},
13066 {0xfe500010, 0x06500000, ARMvAll
, eEncodingA1
, No_VFP
, eSize32
,
13067 &EmulateInstructionARM::EmulateLDRBRegister
,
13068 "ldrb<c> <Rt>, [<Rn>,+/-<Rm>{, <shift>}]{!}"},
13069 {0x0e5f00f0, 0x005f00b0, ARMvAll
, eEncodingA1
, No_VFP
, eSize32
,
13070 &EmulateInstructionARM::EmulateLDRHLiteral
, "ldrh<c> <Rt>, <label>"},
13071 {0x0e5000f0, 0x001000b0, ARMvAll
, eEncodingA1
, No_VFP
, eSize32
,
13072 &EmulateInstructionARM::EmulateLDRHRegister
,
13073 "ldrh<c> <Rt>,[<Rn>,+/-<Rm>]{!}"},
13074 {0x0e5000f0, 0x005000d0, ARMvAll
, eEncodingA1
, No_VFP
, eSize32
,
13075 &EmulateInstructionARM::EmulateLDRSBImmediate
,
13076 "ldrsb<c> <Rt>, [<Rn>{,#+/-<imm8>}]"},
13077 {0x0e5f00f0, 0x005f00d0, ARMvAll
, eEncodingA1
, No_VFP
, eSize32
,
13078 &EmulateInstructionARM::EmulateLDRSBLiteral
, "ldrsb<c> <Rt> <label>"},
13079 {0x0e5000f0, 0x001000d0, ARMvAll
, eEncodingA1
, No_VFP
, eSize32
,
13080 &EmulateInstructionARM::EmulateLDRSBRegister
,
13081 "ldrsb<c> <Rt>,[<Rn>,+/-<Rm>]{!}"},
13082 {0x0e5000f0, 0x005000f0, ARMvAll
, eEncodingA1
, No_VFP
, eSize32
,
13083 &EmulateInstructionARM::EmulateLDRSHImmediate
,
13084 "ldrsh<c> <Rt>,[<Rn>{,#+/-<imm8>}]"},
13085 {0x0e5f00f0, 0x005f00f0, ARMvAll
, eEncodingA1
, No_VFP
, eSize32
,
13086 &EmulateInstructionARM::EmulateLDRSHLiteral
, "ldrsh<c> <Rt>,<label>"},
13087 {0x0e5000f0, 0x001000f0, ARMvAll
, eEncodingA1
, No_VFP
, eSize32
,
13088 &EmulateInstructionARM::EmulateLDRSHRegister
,
13089 "ldrsh<c> <Rt>,[<Rn>,+/-<Rm>]{!}"},
13090 {0x0e5000f0, 0x004000d0, ARMV5TE_ABOVE
, eEncodingA1
, No_VFP
, eSize32
,
13091 &EmulateInstructionARM::EmulateLDRDImmediate
,
13092 "ldrd<c> <Rt>, <Rt2>, [<Rn>,#+/-<imm8>]!"},
13093 {0x0e500ff0, 0x000000d0, ARMV5TE_ABOVE
, eEncodingA1
, No_VFP
, eSize32
,
13094 &EmulateInstructionARM::EmulateLDRDRegister
,
13095 "ldrd<c> <Rt>, <Rt2>, [<Rn>, +/-<Rm>]{!}"},
13096 {0x0e100f00, 0x0c100b00, ARMvAll
, eEncodingA1
, VFPv2_ABOVE
, eSize32
,
13097 &EmulateInstructionARM::EmulateVLDM
, "vldm{mode}<c> <Rn>{!}, <list>"},
13098 {0x0e100f00, 0x0c100a00, ARMvAll
, eEncodingA2
, VFPv2v3
, eSize32
,
13099 &EmulateInstructionARM::EmulateVLDM
, "vldm{mode}<c> <Rn>{!}, <list>"},
13100 {0x0f300f00, 0x0d100b00, ARMvAll
, eEncodingA1
, VFPv2_ABOVE
, eSize32
,
13101 &EmulateInstructionARM::EmulateVLDR
, "vldr<c> <Dd>, [<Rn>{,#+/-<imm>}]"},
13102 {0x0f300f00, 0x0d100a00, ARMvAll
, eEncodingA2
, VFPv2v3
, eSize32
,
13103 &EmulateInstructionARM::EmulateVLDR
, "vldr<c> <Sd>, [<Rn>{,#+/-<imm>}]"},
13104 {0xffb00000, 0xf4200000, ARMvAll
, eEncodingA1
, AdvancedSIMD
, eSize32
,
13105 &EmulateInstructionARM::EmulateVLD1Multiple
,
13106 "vld1<c>.<size> <list>, [<Rn>{@<align>}], <Rm>"},
13107 {0xffb00300, 0xf4a00000, ARMvAll
, eEncodingA1
, AdvancedSIMD
, eSize32
,
13108 &EmulateInstructionARM::EmulateVLD1Single
,
13109 "vld1<c>.<size> <list>, [<Rn>{@<align>}], <Rm>"},
13110 {0xffb00f00, 0xf4a00c00, ARMvAll
, eEncodingA1
, AdvancedSIMD
, eSize32
,
13111 &EmulateInstructionARM::EmulateVLD1SingleAll
,
13112 "vld1<c>.<size> <list>, [<Rn>{@<align>}], <Rm>"},
13114 // Store instructions
13115 {0x0fd00000, 0x08800000, ARMvAll
, eEncodingA1
, No_VFP
, eSize32
,
13116 &EmulateInstructionARM::EmulateSTM
, "stm<c> <Rn>{!} <registers>"},
13117 {0x0fd00000, 0x08000000, ARMvAll
, eEncodingA1
, No_VFP
, eSize32
,
13118 &EmulateInstructionARM::EmulateSTMDA
, "stmda<c> <Rn>{!} <registers>"},
13119 {0x0fd00000, 0x09000000, ARMvAll
, eEncodingA1
, No_VFP
, eSize32
,
13120 &EmulateInstructionARM::EmulateSTMDB
, "stmdb<c> <Rn>{!} <registers>"},
13121 {0x0fd00000, 0x09800000, ARMvAll
, eEncodingA1
, No_VFP
, eSize32
,
13122 &EmulateInstructionARM::EmulateSTMIB
, "stmib<c> <Rn>{!} <registers>"},
13123 {0x0e500010, 0x06000000, ARMvAll
, eEncodingA1
, No_VFP
, eSize32
,
13124 &EmulateInstructionARM::EmulateSTRRegister
,
13125 "str<c> <Rt> [<Rn> +/-<Rm> {<shift>}]{!}"},
13126 {0x0e5000f0, 0x000000b0, ARMvAll
, eEncodingA1
, No_VFP
, eSize32
,
13127 &EmulateInstructionARM::EmulateSTRHRegister
,
13128 "strh<c> <Rt>,[<Rn>,+/-<Rm>[{!}"},
13129 {0x0ff00ff0, 0x01800f90, ARMV6_ABOVE
, eEncodingA1
, No_VFP
, eSize32
,
13130 &EmulateInstructionARM::EmulateSTREX
, "strex<c> <Rd>, <Rt>, [<Rn>]"},
13131 {0x0e500000, 0x04400000, ARMvAll
, eEncodingA1
, No_VFP
, eSize32
,
13132 &EmulateInstructionARM::EmulateSTRBImmARM
,
13133 "strb<c> <Rt>,[<Rn>,#+/-<imm12>]!"},
13134 {0x0e500000, 0x04000000, ARMvAll
, eEncodingA1
, No_VFP
, eSize32
,
13135 &EmulateInstructionARM::EmulateSTRImmARM
,
13136 "str<c> <Rt>,[<Rn>,#+/-<imm12>]!"},
13137 {0x0e5000f0, 0x004000f0, ARMV5TE_ABOVE
, eEncodingA1
, No_VFP
, eSize32
,
13138 &EmulateInstructionARM::EmulateSTRDImm
,
13139 "strd<c> <Rt>, <Rt2>, [<Rn> #+/-<imm8>]!"},
13140 {0x0e500ff0, 0x000000f0, ARMV5TE_ABOVE
, eEncodingA1
, No_VFP
, eSize32
,
13141 &EmulateInstructionARM::EmulateSTRDReg
,
13142 "strd<c> <Rt>, <Rt2>, [<Rn>, +/-<Rm>]{!}"},
13143 {0x0e100f00, 0x0c000b00, ARMvAll
, eEncodingA1
, VFPv2_ABOVE
, eSize32
,
13144 &EmulateInstructionARM::EmulateVSTM
, "vstm{mode}<c> <Rn>{!} <list>"},
13145 {0x0e100f00, 0x0c000a00, ARMvAll
, eEncodingA2
, VFPv2v3
, eSize32
,
13146 &EmulateInstructionARM::EmulateVSTM
, "vstm{mode}<c> <Rn>{!} <list>"},
13147 {0x0f300f00, 0x0d000b00, ARMvAll
, eEncodingA1
, VFPv2_ABOVE
, eSize32
,
13148 &EmulateInstructionARM::EmulateVSTR
, "vstr<c> <Dd> [<Rn>{,#+/-<imm>}]"},
13149 {0x0f300f00, 0x0d000a00, ARMvAll
, eEncodingA2
, VFPv2v3
, eSize32
,
13150 &EmulateInstructionARM::EmulateVSTR
, "vstr<c> <Sd> [<Rn>{,#+/-<imm>}]"},
13151 {0xffb00000, 0xf4000000, ARMvAll
, eEncodingA1
, AdvancedSIMD
, eSize32
,
13152 &EmulateInstructionARM::EmulateVST1Multiple
,
13153 "vst1<c>.<size> <list>, [<Rn>{@<align>}], <Rm>"},
13154 {0xffb00300, 0xf4800000, ARMvAll
, eEncodingA1
, AdvancedSIMD
, eSize32
,
13155 &EmulateInstructionARM::EmulateVST1Single
,
13156 "vst1<c>.<size> <list>, [<Rn>{@<align>}], <Rm>"},
13158 // Other instructions
13159 {0x0fff00f0, 0x06af00f0, ARMV6_ABOVE
, eEncodingA1
, No_VFP
, eSize32
,
13160 &EmulateInstructionARM::EmulateSXTB
, "sxtb<c> <Rd>,<Rm>{,<rotation>}"},
13161 {0x0fff00f0, 0x06bf0070, ARMV6_ABOVE
, eEncodingA1
, No_VFP
, eSize32
,
13162 &EmulateInstructionARM::EmulateSXTH
, "sxth<c> <Rd>,<Rm>{,<rotation>}"},
13163 {0x0fff00f0, 0x06ef0070, ARMV6_ABOVE
, eEncodingA1
, No_VFP
, eSize32
,
13164 &EmulateInstructionARM::EmulateUXTB
, "uxtb<c> <Rd>,<Rm>{,<rotation>}"},
13165 {0x0fff00f0, 0x06ff0070, ARMV6_ABOVE
, eEncodingA1
, No_VFP
, eSize32
,
13166 &EmulateInstructionARM::EmulateUXTH
, "uxth<c> <Rd>,<Rm>{,<rotation>}"},
13167 {0xfe500000, 0xf8100000, ARMV6_ABOVE
, eEncodingA1
, No_VFP
, eSize32
,
13168 &EmulateInstructionARM::EmulateRFE
, "rfe{<amode>} <Rn>{!}"}
13171 static const size_t k_num_arm_opcodes
= std::size(g_arm_opcodes
);
13173 for (size_t i
= 0; i
< k_num_arm_opcodes
; ++i
) {
13174 if ((g_arm_opcodes
[i
].mask
& opcode
) == g_arm_opcodes
[i
].value
&&
13175 (g_arm_opcodes
[i
].variants
& arm_isa
) != 0)
13176 return &g_arm_opcodes
[i
];
13181 EmulateInstructionARM::ARMOpcode
*
13182 EmulateInstructionARM::GetThumbOpcodeForInstruction(const uint32_t opcode
,
13183 uint32_t arm_isa
) {
13185 static ARMOpcode g_thumb_opcodes
[] = {
13186 // Prologue instructions
13188 // push register(s)
13189 {0xfffffe00, 0x0000b400, ARMvAll
, eEncodingT1
, No_VFP
, eSize16
,
13190 &EmulateInstructionARM::EmulatePUSH
, "push <registers>"},
13191 {0xffff0000, 0xe92d0000, ARMV6T2_ABOVE
, eEncodingT2
, No_VFP
, eSize32
,
13192 &EmulateInstructionARM::EmulatePUSH
, "push.w <registers>"},
13193 {0xffff0fff, 0xf84d0d04, ARMV6T2_ABOVE
, eEncodingT3
, No_VFP
, eSize32
,
13194 &EmulateInstructionARM::EmulatePUSH
, "push.w <register>"},
13196 // set r7 to point to a stack offset
13197 {0xffffff00, 0x0000af00, ARMvAll
, eEncodingT1
, No_VFP
, eSize16
,
13198 &EmulateInstructionARM::EmulateADDRdSPImm
, "add r7, sp, #imm"},
13199 // copy the stack pointer to r7
13200 {0xffffffff, 0x0000466f, ARMvAll
, eEncodingT1
, No_VFP
, eSize16
,
13201 &EmulateInstructionARM::EmulateMOVRdSP
, "mov r7, sp"},
13202 // move from high register to low register (comes after "mov r7, sp" to
13203 // resolve ambiguity)
13204 {0xffffffc0, 0x00004640, ARMvAll
, eEncodingT1
, No_VFP
, eSize16
,
13205 &EmulateInstructionARM::EmulateMOVLowHigh
, "mov r0-r7, r8-r15"},
13207 // PC-relative load into register (see also EmulateADDSPRm)
13208 {0xfffff800, 0x00004800, ARMvAll
, eEncodingT1
, No_VFP
, eSize16
,
13209 &EmulateInstructionARM::EmulateLDRRtPCRelative
, "ldr <Rt>, [PC, #imm]"},
13211 // adjust the stack pointer
13212 {0xffffff87, 0x00004485, ARMvAll
, eEncodingT2
, No_VFP
, eSize16
,
13213 &EmulateInstructionARM::EmulateADDSPRm
, "add sp, <Rm>"},
13214 {0xffffff80, 0x0000b080, ARMvAll
, eEncodingT1
, No_VFP
, eSize16
,
13215 &EmulateInstructionARM::EmulateSUBSPImm
, "sub sp, sp, #imm"},
13216 {0xfbef8f00, 0xf1ad0d00, ARMV6T2_ABOVE
, eEncodingT2
, No_VFP
, eSize32
,
13217 &EmulateInstructionARM::EmulateSUBSPImm
, "sub.w sp, sp, #<const>"},
13218 {0xfbff8f00, 0xf2ad0d00, ARMV6T2_ABOVE
, eEncodingT3
, No_VFP
, eSize32
,
13219 &EmulateInstructionARM::EmulateSUBSPImm
, "subw sp, sp, #imm12"},
13220 {0xffef8000, 0xebad0000, ARMV6T2_ABOVE
, eEncodingT1
, No_VFP
, eSize32
,
13221 &EmulateInstructionARM::EmulateSUBSPReg
,
13222 "sub{s}<c> <Rd>, sp, <Rm>{,<shift>}"},
13224 // vector push consecutive extension register(s)
13225 {0xffbf0f00, 0xed2d0b00, ARMV6T2_ABOVE
, eEncodingT1
, No_VFP
, eSize32
,
13226 &EmulateInstructionARM::EmulateVPUSH
, "vpush.64 <list>"},
13227 {0xffbf0f00, 0xed2d0a00, ARMV6T2_ABOVE
, eEncodingT2
, No_VFP
, eSize32
,
13228 &EmulateInstructionARM::EmulateVPUSH
, "vpush.32 <list>"},
13230 // Epilogue instructions
13232 {0xfffff800, 0x0000a800, ARMV4T_ABOVE
, eEncodingT1
, No_VFP
, eSize16
,
13233 &EmulateInstructionARM::EmulateADDSPImm
, "add<c> <Rd>, sp, #imm"},
13234 {0xffffff80, 0x0000b000, ARMvAll
, eEncodingT2
, No_VFP
, eSize16
,
13235 &EmulateInstructionARM::EmulateADDSPImm
, "add sp, #imm"},
13236 {0xfffffe00, 0x0000bc00, ARMvAll
, eEncodingT1
, No_VFP
, eSize16
,
13237 &EmulateInstructionARM::EmulatePOP
, "pop <registers>"},
13238 {0xffff0000, 0xe8bd0000, ARMV6T2_ABOVE
, eEncodingT2
, No_VFP
, eSize32
,
13239 &EmulateInstructionARM::EmulatePOP
, "pop.w <registers>"},
13240 {0xffff0fff, 0xf85d0d04, ARMV6T2_ABOVE
, eEncodingT3
, No_VFP
, eSize32
,
13241 &EmulateInstructionARM::EmulatePOP
, "pop.w <register>"},
13242 {0xffbf0f00, 0xecbd0b00, ARMV6T2_ABOVE
, eEncodingT1
, No_VFP
, eSize32
,
13243 &EmulateInstructionARM::EmulateVPOP
, "vpop.64 <list>"},
13244 {0xffbf0f00, 0xecbd0a00, ARMV6T2_ABOVE
, eEncodingT2
, No_VFP
, eSize32
,
13245 &EmulateInstructionARM::EmulateVPOP
, "vpop.32 <list>"},
13247 // Supervisor Call (previously Software Interrupt)
13248 {0xffffff00, 0x0000df00, ARMvAll
, eEncodingT1
, No_VFP
, eSize16
,
13249 &EmulateInstructionARM::EmulateSVC
, "svc #imm8"},
13251 // If Then makes up to four following instructions conditional.
13252 // The next 5 opcode _must_ come before the if then instruction
13253 {0xffffffff, 0x0000bf00, ARMV6T2_ABOVE
, eEncodingT1
, No_VFP
, eSize16
,
13254 &EmulateInstructionARM::EmulateNop
, "nop"},
13255 {0xffffffff, 0x0000bf10, ARMV7_ABOVE
, eEncodingT1
, No_VFP
, eSize16
,
13256 &EmulateInstructionARM::EmulateNop
, "nop YIELD (yield hint)"},
13257 {0xffffffff, 0x0000bf20, ARMV7_ABOVE
, eEncodingT1
, No_VFP
, eSize16
,
13258 &EmulateInstructionARM::EmulateNop
, "nop WFE (wait for event hint)"},
13259 {0xffffffff, 0x0000bf30, ARMV7_ABOVE
, eEncodingT1
, No_VFP
, eSize16
,
13260 &EmulateInstructionARM::EmulateNop
, "nop WFI (wait for interrupt hint)"},
13261 {0xffffffff, 0x0000bf40, ARMV7_ABOVE
, eEncodingT1
, No_VFP
, eSize16
,
13262 &EmulateInstructionARM::EmulateNop
, "nop SEV (send event hint)"},
13263 {0xffffff00, 0x0000bf00, ARMV6T2_ABOVE
, eEncodingT1
, No_VFP
, eSize16
,
13264 &EmulateInstructionARM::EmulateIT
, "it{<x>{<y>{<z>}}} <firstcond>"},
13266 // Branch instructions
13267 // To resolve ambiguity, "b<c> #imm8" should come after "svc #imm8".
13268 {0xfffff000, 0x0000d000, ARMvAll
, eEncodingT1
, No_VFP
, eSize16
,
13269 &EmulateInstructionARM::EmulateB
, "b<c> #imm8 (outside IT)"},
13270 {0xfffff800, 0x0000e000, ARMvAll
, eEncodingT2
, No_VFP
, eSize16
,
13271 &EmulateInstructionARM::EmulateB
, "b<c> #imm11 (outside or last in IT)"},
13272 {0xf800d000, 0xf0008000, ARMV6T2_ABOVE
, eEncodingT3
, No_VFP
, eSize32
,
13273 &EmulateInstructionARM::EmulateB
, "b<c>.w #imm8 (outside IT)"},
13274 {0xf800d000, 0xf0009000, ARMV6T2_ABOVE
, eEncodingT4
, No_VFP
, eSize32
,
13275 &EmulateInstructionARM::EmulateB
,
13276 "b<c>.w #imm8 (outside or last in IT)"},
13278 {0xf800d000, 0xf000d000, ARMV4T_ABOVE
, eEncodingT1
, No_VFP
, eSize32
,
13279 &EmulateInstructionARM::EmulateBLXImmediate
, "bl <label>"},
13281 {0xf800d001, 0xf000c000, ARMV5_ABOVE
, eEncodingT2
, No_VFP
, eSize32
,
13282 &EmulateInstructionARM::EmulateBLXImmediate
, "blx <label>"},
13283 {0xffffff87, 0x00004780, ARMV5_ABOVE
, eEncodingT1
, No_VFP
, eSize16
,
13284 &EmulateInstructionARM::EmulateBLXRm
, "blx <Rm>"},
13285 // for example, "bx lr"
13286 {0xffffff87, 0x00004700, ARMvAll
, eEncodingT1
, No_VFP
, eSize32
,
13287 &EmulateInstructionARM::EmulateBXRm
, "bx <Rm>"},
13289 {0xfff0ffff, 0xf3c08f00, ARMV5J_ABOVE
, eEncodingT1
, No_VFP
, eSize32
,
13290 &EmulateInstructionARM::EmulateBXJRm
, "bxj <Rm>"},
13291 // compare and branch
13292 {0xfffff500, 0x0000b100, ARMV6T2_ABOVE
, eEncodingT1
, No_VFP
, eSize16
,
13293 &EmulateInstructionARM::EmulateCB
, "cb{n}z <Rn>, <label>"},
13294 // table branch byte
13295 {0xfff0fff0, 0xe8d0f000, ARMV6T2_ABOVE
, eEncodingT1
, No_VFP
, eSize32
,
13296 &EmulateInstructionARM::EmulateTB
, "tbb<c> <Rn>, <Rm>"},
13297 // table branch halfword
13298 {0xfff0fff0, 0xe8d0f010, ARMV6T2_ABOVE
, eEncodingT1
, No_VFP
, eSize32
,
13299 &EmulateInstructionARM::EmulateTB
, "tbh<c> <Rn>, <Rm>, lsl #1"},
13301 // Data-processing instructions
13303 {0xfbe08000, 0xf1400000, ARMV6T2_ABOVE
, eEncodingT1
, No_VFP
, eSize32
,
13304 &EmulateInstructionARM::EmulateADCImm
, "adc{s}<c> <Rd>, <Rn>, #<const>"},
13306 {0xffffffc0, 0x00004140, ARMvAll
, eEncodingT1
, No_VFP
, eSize16
,
13307 &EmulateInstructionARM::EmulateADCReg
, "adcs|adc<c> <Rdn>, <Rm>"},
13308 {0xffe08000, 0xeb400000, ARMV6T2_ABOVE
, eEncodingT2
, No_VFP
, eSize32
,
13309 &EmulateInstructionARM::EmulateADCReg
,
13310 "adc{s}<c>.w <Rd>, <Rn>, <Rm> {,<shift>}"},
13312 {0xfffffe00, 0x00001800, ARMvAll
, eEncodingT1
, No_VFP
, eSize16
,
13313 &EmulateInstructionARM::EmulateADDReg
, "adds|add<c> <Rd>, <Rn>, <Rm>"},
13314 // Make sure "add sp, <Rm>" comes before this instruction, so there's no
13315 // ambiguity decoding the two.
13316 {0xffffff00, 0x00004400, ARMvAll
, eEncodingT2
, No_VFP
, eSize16
,
13317 &EmulateInstructionARM::EmulateADDReg
, "add<c> <Rdn>, <Rm>"},
13319 {0xfffff800, 0x0000a000, ARMvAll
, eEncodingT1
, No_VFP
, eSize16
,
13320 &EmulateInstructionARM::EmulateADR
, "add<c> <Rd>, PC, #<const>"},
13321 {0xfbff8000, 0xf2af0000, ARMV6T2_ABOVE
, eEncodingT2
, No_VFP
, eSize32
,
13322 &EmulateInstructionARM::EmulateADR
, "sub<c> <Rd>, PC, #<const>"},
13323 {0xfbff8000, 0xf20f0000, ARMV6T2_ABOVE
, eEncodingT3
, No_VFP
, eSize32
,
13324 &EmulateInstructionARM::EmulateADR
, "add<c> <Rd>, PC, #<const>"},
13326 {0xfbe08000, 0xf0000000, ARMV6T2_ABOVE
, eEncodingT1
, No_VFP
, eSize32
,
13327 &EmulateInstructionARM::EmulateANDImm
, "and{s}<c> <Rd>, <Rn>, #<const>"},
13329 {0xffffffc0, 0x00004000, ARMvAll
, eEncodingT1
, No_VFP
, eSize16
,
13330 &EmulateInstructionARM::EmulateANDReg
, "ands|and<c> <Rdn>, <Rm>"},
13331 {0xffe08000, 0xea000000, ARMV6T2_ABOVE
, eEncodingT2
, No_VFP
, eSize32
,
13332 &EmulateInstructionARM::EmulateANDReg
,
13333 "and{s}<c>.w <Rd>, <Rn>, <Rm> {,<shift>}"},
13335 {0xfbe08000, 0xf0200000, ARMV6T2_ABOVE
, eEncodingT1
, No_VFP
, eSize32
,
13336 &EmulateInstructionARM::EmulateBICImm
, "bic{s}<c> <Rd>, <Rn>, #<const>"},
13338 {0xffffffc0, 0x00004380, ARMvAll
, eEncodingT1
, No_VFP
, eSize16
,
13339 &EmulateInstructionARM::EmulateBICReg
, "bics|bic<c> <Rdn>, <Rm>"},
13340 {0xffe08000, 0xea200000, ARMV6T2_ABOVE
, eEncodingT2
, No_VFP
, eSize32
,
13341 &EmulateInstructionARM::EmulateBICReg
,
13342 "bic{s}<c>.w <Rd>, <Rn>, <Rm> {,<shift>}"},
13344 {0xfbe08000, 0xf0800000, ARMV6T2_ABOVE
, eEncodingT1
, No_VFP
, eSize32
,
13345 &EmulateInstructionARM::EmulateEORImm
, "eor{s}<c> <Rd>, <Rn>, #<const>"},
13347 {0xffffffc0, 0x00004040, ARMvAll
, eEncodingT1
, No_VFP
, eSize16
,
13348 &EmulateInstructionARM::EmulateEORReg
, "eors|eor<c> <Rdn>, <Rm>"},
13349 {0xffe08000, 0xea800000, ARMV6T2_ABOVE
, eEncodingT2
, No_VFP
, eSize32
,
13350 &EmulateInstructionARM::EmulateEORReg
,
13351 "eor{s}<c>.w <Rd>, <Rn>, <Rm> {,<shift>}"},
13353 {0xfbe08000, 0xf0400000, ARMV6T2_ABOVE
, eEncodingT1
, No_VFP
, eSize32
,
13354 &EmulateInstructionARM::EmulateORRImm
, "orr{s}<c> <Rd>, <Rn>, #<const>"},
13356 {0xffffffc0, 0x00004300, ARMvAll
, eEncodingT1
, No_VFP
, eSize16
,
13357 &EmulateInstructionARM::EmulateORRReg
, "orrs|orr<c> <Rdn>, <Rm>"},
13358 {0xffe08000, 0xea400000, ARMV6T2_ABOVE
, eEncodingT2
, No_VFP
, eSize32
,
13359 &EmulateInstructionARM::EmulateORRReg
,
13360 "orr{s}<c>.w <Rd>, <Rn>, <Rm> {,<shift>}"},
13362 {0xffffffc0, 0x00004240, ARMvAll
, eEncodingT1
, No_VFP
, eSize16
,
13363 &EmulateInstructionARM::EmulateRSBImm
, "rsbs|rsb<c> <Rd>, <Rn>, #0"},
13364 {0xfbe08000, 0xf1c00000, ARMV6T2_ABOVE
, eEncodingT2
, No_VFP
, eSize32
,
13365 &EmulateInstructionARM::EmulateRSBImm
,
13366 "rsb{s}<c>.w <Rd>, <Rn>, #<const>"},
13368 {0xffe08000, 0xea400000, ARMV6T2_ABOVE
, eEncodingT1
, No_VFP
, eSize32
,
13369 &EmulateInstructionARM::EmulateRSBReg
,
13370 "rsb{s}<c>.w <Rd>, <Rn>, <Rm> {,<shift>}"},
13372 {0xfbe08000, 0xf1600000, ARMV6T2_ABOVE
, eEncodingT1
, No_VFP
, eSize32
,
13373 &EmulateInstructionARM::EmulateSBCImm
, "sbc{s}<c> <Rd>, <Rn>, #<const>"},
13375 {0xffffffc0, 0x00004180, ARMvAll
, eEncodingT1
, No_VFP
, eSize16
,
13376 &EmulateInstructionARM::EmulateSBCReg
, "sbcs|sbc<c> <Rdn>, <Rm>"},
13377 {0xffe08000, 0xeb600000, ARMV6T2_ABOVE
, eEncodingT2
, No_VFP
, eSize32
,
13378 &EmulateInstructionARM::EmulateSBCReg
,
13379 "sbc{s}<c>.w <Rd>, <Rn>, <Rm> {,<shift>}"},
13380 // add (immediate, Thumb)
13381 {0xfffffe00, 0x00001c00, ARMV4T_ABOVE
, eEncodingT1
, No_VFP
, eSize16
,
13382 &EmulateInstructionARM::EmulateADDImmThumb
,
13383 "adds|add<c> <Rd>,<Rn>,#<imm3>"},
13384 {0xfffff800, 0x00003000, ARMV4T_ABOVE
, eEncodingT2
, No_VFP
, eSize16
,
13385 &EmulateInstructionARM::EmulateADDImmThumb
, "adds|add<c> <Rdn>,#<imm8>"},
13386 {0xfbe08000, 0xf1000000, ARMV6T2_ABOVE
, eEncodingT3
, No_VFP
, eSize32
,
13387 &EmulateInstructionARM::EmulateADDImmThumb
,
13388 "add{s}<c>.w <Rd>,<Rn>,#<const>"},
13389 {0xfbf08000, 0xf2000000, ARMV6T2_ABOVE
, eEncodingT4
, No_VFP
, eSize32
,
13390 &EmulateInstructionARM::EmulateADDImmThumb
,
13391 "addw<c> <Rd>,<Rn>,#<imm12>"},
13392 // sub (immediate, Thumb)
13393 {0xfffffe00, 0x00001e00, ARMvAll
, eEncodingT1
, No_VFP
, eSize16
,
13394 &EmulateInstructionARM::EmulateSUBImmThumb
,
13395 "subs|sub<c> <Rd>, <Rn> #imm3"},
13396 {0xfffff800, 0x00003800, ARMvAll
, eEncodingT2
, No_VFP
, eSize16
,
13397 &EmulateInstructionARM::EmulateSUBImmThumb
, "subs|sub<c> <Rdn>, #imm8"},
13398 {0xfbe08000, 0xf1a00000, ARMV6T2_ABOVE
, eEncodingT3
, No_VFP
, eSize32
,
13399 &EmulateInstructionARM::EmulateSUBImmThumb
,
13400 "sub{s}<c>.w <Rd>, <Rn>, #<const>"},
13401 {0xfbf08000, 0xf2a00000, ARMV6T2_ABOVE
, eEncodingT4
, No_VFP
, eSize32
,
13402 &EmulateInstructionARM::EmulateSUBImmThumb
,
13403 "subw<c> <Rd>, <Rn>, #imm12"},
13404 // sub (sp minus immediate)
13405 {0xfbef8000, 0xf1ad0000, ARMV6T2_ABOVE
, eEncodingT2
, No_VFP
, eSize32
,
13406 &EmulateInstructionARM::EmulateSUBSPImm
, "sub{s}.w <Rd>, sp, #<const>"},
13407 {0xfbff8000, 0xf2ad0000, ARMV6T2_ABOVE
, eEncodingT3
, No_VFP
, eSize32
,
13408 &EmulateInstructionARM::EmulateSUBSPImm
, "subw<c> <Rd>, sp, #imm12"},
13410 {0xfffffe00, 0x00001a00, ARMV4T_ABOVE
, eEncodingT1
, No_VFP
, eSize16
,
13411 &EmulateInstructionARM::EmulateSUBReg
, "subs|sub<c> <Rd>, <Rn>, <Rm>"},
13412 {0xffe08000, 0xeba00000, ARMV6T2_ABOVE
, eEncodingT2
, No_VFP
, eSize32
,
13413 &EmulateInstructionARM::EmulateSUBReg
,
13414 "sub{s}<c>.w <Rd>, <Rn>, <Rm>{,<shift>}"},
13416 {0xfbf08f00, 0xf0900f00, ARMV6T2_ABOVE
, eEncodingT1
, No_VFP
, eSize32
,
13417 &EmulateInstructionARM::EmulateTEQImm
, "teq<c> <Rn>, #<const>"},
13419 {0xfff08f00, 0xea900f00, ARMV6T2_ABOVE
, eEncodingT1
, No_VFP
, eSize32
,
13420 &EmulateInstructionARM::EmulateTEQReg
, "teq<c> <Rn>, <Rm> {,<shift>}"},
13422 {0xfbf08f00, 0xf0100f00, ARMV6T2_ABOVE
, eEncodingT1
, No_VFP
, eSize32
,
13423 &EmulateInstructionARM::EmulateTSTImm
, "tst<c> <Rn>, #<const>"},
13425 {0xffffffc0, 0x00004200, ARMvAll
, eEncodingT1
, No_VFP
, eSize16
,
13426 &EmulateInstructionARM::EmulateTSTReg
, "tst<c> <Rdn>, <Rm>"},
13427 {0xfff08f00, 0xea100f00, ARMV6T2_ABOVE
, eEncodingT2
, No_VFP
, eSize32
,
13428 &EmulateInstructionARM::EmulateTSTReg
, "tst<c>.w <Rn>, <Rm> {,<shift>}"},
13430 // move from high register to high register
13431 {0xffffff00, 0x00004600, ARMvAll
, eEncodingT1
, No_VFP
, eSize16
,
13432 &EmulateInstructionARM::EmulateMOVRdRm
, "mov<c> <Rd>, <Rm>"},
13433 // move from low register to low register
13434 {0xffffffc0, 0x00000000, ARMvAll
, eEncodingT2
, No_VFP
, eSize16
,
13435 &EmulateInstructionARM::EmulateMOVRdRm
, "movs <Rd>, <Rm>"},
13436 // mov{s}<c>.w <Rd>, <Rm>
13437 {0xffeff0f0, 0xea4f0000, ARMV6T2_ABOVE
, eEncodingT3
, No_VFP
, eSize32
,
13438 &EmulateInstructionARM::EmulateMOVRdRm
, "mov{s}<c>.w <Rd>, <Rm>"},
13440 {0xfffff800, 0x00002000, ARMvAll
, eEncodingT1
, No_VFP
, eSize16
,
13441 &EmulateInstructionARM::EmulateMOVRdImm
, "movs|mov<c> <Rd>, #imm8"},
13442 {0xfbef8000, 0xf04f0000, ARMV6T2_ABOVE
, eEncodingT2
, No_VFP
, eSize32
,
13443 &EmulateInstructionARM::EmulateMOVRdImm
, "mov{s}<c>.w <Rd>, #<const>"},
13444 {0xfbf08000, 0xf2400000, ARMV6T2_ABOVE
, eEncodingT3
, No_VFP
, eSize32
,
13445 &EmulateInstructionARM::EmulateMOVRdImm
, "movw<c> <Rd>,#<imm16>"},
13447 {0xfbef8000, 0xf06f0000, ARMV6T2_ABOVE
, eEncodingT1
, No_VFP
, eSize32
,
13448 &EmulateInstructionARM::EmulateMVNImm
, "mvn{s} <Rd>, #<const>"},
13450 {0xffffffc0, 0x000043c0, ARMvAll
, eEncodingT1
, No_VFP
, eSize16
,
13451 &EmulateInstructionARM::EmulateMVNReg
, "mvns|mvn<c> <Rd>, <Rm>"},
13452 {0xffef8000, 0xea6f0000, ARMV6T2_ABOVE
, eEncodingT2
, No_VFP
, eSize32
,
13453 &EmulateInstructionARM::EmulateMVNReg
,
13454 "mvn{s}<c>.w <Rd>, <Rm> {,<shift>}"},
13456 {0xfbf08f00, 0xf1100f00, ARMV6T2_ABOVE
, eEncodingT1
, No_VFP
, eSize32
,
13457 &EmulateInstructionARM::EmulateCMNImm
, "cmn<c> <Rn>, #<const>"},
13459 {0xffffffc0, 0x000042c0, ARMvAll
, eEncodingT1
, No_VFP
, eSize16
,
13460 &EmulateInstructionARM::EmulateCMNReg
, "cmn<c> <Rn>, <Rm>"},
13461 {0xfff08f00, 0xeb100f00, ARMV6T2_ABOVE
, eEncodingT2
, No_VFP
, eSize32
,
13462 &EmulateInstructionARM::EmulateCMNReg
, "cmn<c> <Rn>, <Rm> {,<shift>}"},
13464 {0xfffff800, 0x00002800, ARMvAll
, eEncodingT1
, No_VFP
, eSize16
,
13465 &EmulateInstructionARM::EmulateCMPImm
, "cmp<c> <Rn>, #imm8"},
13466 {0xfbf08f00, 0xf1b00f00, ARMV6T2_ABOVE
, eEncodingT2
, No_VFP
, eSize32
,
13467 &EmulateInstructionARM::EmulateCMPImm
, "cmp<c>.w <Rn>, #<const>"},
13468 // cmp (register) (Rn and Rm both from r0-r7)
13469 {0xffffffc0, 0x00004280, ARMvAll
, eEncodingT1
, No_VFP
, eSize16
,
13470 &EmulateInstructionARM::EmulateCMPReg
, "cmp<c> <Rn>, <Rm>"},
13471 // cmp (register) (Rn and Rm not both from r0-r7)
13472 {0xffffff00, 0x00004500, ARMvAll
, eEncodingT2
, No_VFP
, eSize16
,
13473 &EmulateInstructionARM::EmulateCMPReg
, "cmp<c> <Rn>, <Rm>"},
13474 {0xfff08f00, 0xebb00f00, ARMvAll
, eEncodingT3
, No_VFP
, eSize16
,
13475 &EmulateInstructionARM::EmulateCMPReg
,
13476 "cmp<c>.w <Rn>, <Rm> {, <shift>}"},
13478 {0xfffff800, 0x00001000, ARMvAll
, eEncodingT1
, No_VFP
, eSize16
,
13479 &EmulateInstructionARM::EmulateASRImm
, "asrs|asr<c> <Rd>, <Rm>, #imm"},
13480 {0xffef8030, 0xea4f0020, ARMV6T2_ABOVE
, eEncodingT2
, No_VFP
, eSize32
,
13481 &EmulateInstructionARM::EmulateASRImm
, "asr{s}<c>.w <Rd>, <Rm>, #imm"},
13483 {0xffffffc0, 0x00004100, ARMvAll
, eEncodingT1
, No_VFP
, eSize16
,
13484 &EmulateInstructionARM::EmulateASRReg
, "asrs|asr<c> <Rdn>, <Rm>"},
13485 {0xffe0f0f0, 0xfa40f000, ARMV6T2_ABOVE
, eEncodingT2
, No_VFP
, eSize32
,
13486 &EmulateInstructionARM::EmulateASRReg
, "asr{s}<c>.w <Rd>, <Rn>, <Rm>"},
13488 {0xfffff800, 0x00000000, ARMvAll
, eEncodingT1
, No_VFP
, eSize16
,
13489 &EmulateInstructionARM::EmulateLSLImm
, "lsls|lsl<c> <Rd>, <Rm>, #imm"},
13490 {0xffef8030, 0xea4f0000, ARMV6T2_ABOVE
, eEncodingT2
, No_VFP
, eSize32
,
13491 &EmulateInstructionARM::EmulateLSLImm
, "lsl{s}<c>.w <Rd>, <Rm>, #imm"},
13493 {0xffffffc0, 0x00004080, ARMvAll
, eEncodingT1
, No_VFP
, eSize16
,
13494 &EmulateInstructionARM::EmulateLSLReg
, "lsls|lsl<c> <Rdn>, <Rm>"},
13495 {0xffe0f0f0, 0xfa00f000, ARMV6T2_ABOVE
, eEncodingT2
, No_VFP
, eSize32
,
13496 &EmulateInstructionARM::EmulateLSLReg
, "lsl{s}<c>.w <Rd>, <Rn>, <Rm>"},
13498 {0xfffff800, 0x00000800, ARMvAll
, eEncodingT1
, No_VFP
, eSize16
,
13499 &EmulateInstructionARM::EmulateLSRImm
, "lsrs|lsr<c> <Rd>, <Rm>, #imm"},
13500 {0xffef8030, 0xea4f0010, ARMV6T2_ABOVE
, eEncodingT2
, No_VFP
, eSize32
,
13501 &EmulateInstructionARM::EmulateLSRImm
, "lsr{s}<c>.w <Rd>, <Rm>, #imm"},
13503 {0xffffffc0, 0x000040c0, ARMvAll
, eEncodingT1
, No_VFP
, eSize16
,
13504 &EmulateInstructionARM::EmulateLSRReg
, "lsrs|lsr<c> <Rdn>, <Rm>"},
13505 {0xffe0f0f0, 0xfa20f000, ARMV6T2_ABOVE
, eEncodingT2
, No_VFP
, eSize32
,
13506 &EmulateInstructionARM::EmulateLSRReg
, "lsr{s}<c>.w <Rd>, <Rn>, <Rm>"},
13507 // rrx is a special case encoding of ror (immediate)
13508 {0xffeff0f0, 0xea4f0030, ARMV6T2_ABOVE
, eEncodingT1
, No_VFP
, eSize32
,
13509 &EmulateInstructionARM::EmulateRRX
, "rrx{s}<c>.w <Rd>, <Rm>"},
13511 {0xffef8030, 0xea4f0030, ARMV6T2_ABOVE
, eEncodingT1
, No_VFP
, eSize32
,
13512 &EmulateInstructionARM::EmulateRORImm
, "ror{s}<c>.w <Rd>, <Rm>, #imm"},
13514 {0xffffffc0, 0x000041c0, ARMvAll
, eEncodingT1
, No_VFP
, eSize16
,
13515 &EmulateInstructionARM::EmulateRORReg
, "rors|ror<c> <Rdn>, <Rm>"},
13516 {0xffe0f0f0, 0xfa60f000, ARMV6T2_ABOVE
, eEncodingT2
, No_VFP
, eSize32
,
13517 &EmulateInstructionARM::EmulateRORReg
, "ror{s}<c>.w <Rd>, <Rn>, <Rm>"},
13519 {0xffffffc0, 0x00004340, ARMV4T_ABOVE
, eEncodingT1
, No_VFP
, eSize16
,
13520 &EmulateInstructionARM::EmulateMUL
, "muls <Rdm>,<Rn>,<Rdm>"},
13522 {0xfff0f0f0, 0xfb00f000, ARMV6T2_ABOVE
, eEncodingT2
, No_VFP
, eSize32
,
13523 &EmulateInstructionARM::EmulateMUL
, "mul<c> <Rd>,<Rn>,<Rm>"},
13525 // subs pc, lr and related instructions
13526 {0xffffff00, 0xf3de8f00, ARMV6T2_ABOVE
, eEncodingT1
, No_VFP
, eSize32
,
13527 &EmulateInstructionARM::EmulateSUBSPcLrEtc
, "SUBS<c> PC, LR, #<imm8>"},
13529 // RFE instructions *** IMPORTANT *** THESE MUST BE LISTED **BEFORE** THE
13530 // LDM.. Instructions in this table;
13531 // otherwise the wrong instructions will be selected.
13533 {0xffd0ffff, 0xe810c000, ARMV6T2_ABOVE
, eEncodingT1
, No_VFP
, eSize32
,
13534 &EmulateInstructionARM::EmulateRFE
, "rfedb<c> <Rn>{!}"},
13535 {0xffd0ffff, 0xe990c000, ARMV6T2_ABOVE
, eEncodingT2
, No_VFP
, eSize32
,
13536 &EmulateInstructionARM::EmulateRFE
, "rfe{ia}<c> <Rn>{!}"},
13538 // Load instructions
13539 {0xfffff800, 0x0000c800, ARMV4T_ABOVE
, eEncodingT1
, No_VFP
, eSize16
,
13540 &EmulateInstructionARM::EmulateLDM
, "ldm<c> <Rn>{!} <registers>"},
13541 {0xffd02000, 0xe8900000, ARMV6T2_ABOVE
, eEncodingT2
, No_VFP
, eSize32
,
13542 &EmulateInstructionARM::EmulateLDM
, "ldm<c>.w <Rn>{!} <registers>"},
13543 {0xffd00000, 0xe9100000, ARMV6T2_ABOVE
, eEncodingT1
, No_VFP
, eSize32
,
13544 &EmulateInstructionARM::EmulateLDMDB
, "ldmdb<c> <Rn>{!} <registers>"},
13545 {0xfffff800, 0x00006800, ARMV4T_ABOVE
, eEncodingT1
, No_VFP
, eSize16
,
13546 &EmulateInstructionARM::EmulateLDRRtRnImm
, "ldr<c> <Rt>, [<Rn>{,#imm}]"},
13547 {0xfffff800, 0x00009800, ARMV4T_ABOVE
, eEncodingT2
, No_VFP
, eSize16
,
13548 &EmulateInstructionARM::EmulateLDRRtRnImm
, "ldr<c> <Rt>, [SP{,#imm}]"},
13549 {0xfff00000, 0xf8d00000, ARMV6T2_ABOVE
, eEncodingT3
, No_VFP
, eSize32
,
13550 &EmulateInstructionARM::EmulateLDRRtRnImm
,
13551 "ldr<c>.w <Rt>, [<Rn>{,#imm12}]"},
13552 {0xfff00800, 0xf8500800, ARMV6T2_ABOVE
, eEncodingT4
, No_VFP
, eSize32
,
13553 &EmulateInstructionARM::EmulateLDRRtRnImm
,
13554 "ldr<c> <Rt>, [<Rn>{,#+/-<imm8>}]{!}"},
13555 // Thumb2 PC-relative load into register
13556 {0xff7f0000, 0xf85f0000, ARMV6T2_ABOVE
, eEncodingT2
, No_VFP
, eSize32
,
13557 &EmulateInstructionARM::EmulateLDRRtPCRelative
,
13558 "ldr<c>.w <Rt>, [PC, +/-#imm}]"},
13559 {0xfffffe00, 0x00005800, ARMV4T_ABOVE
, eEncodingT1
, No_VFP
, eSize16
,
13560 &EmulateInstructionARM::EmulateLDRRegister
, "ldr<c> <Rt>, [<Rn>, <Rm>]"},
13561 {0xfff00fc0, 0xf8500000, ARMV6T2_ABOVE
, eEncodingT2
, No_VFP
, eSize32
,
13562 &EmulateInstructionARM::EmulateLDRRegister
,
13563 "ldr<c>.w <Rt>, [<Rn>,<Rm>{,LSL #<imm2>}]"},
13564 {0xfffff800, 0x00007800, ARMV4T_ABOVE
, eEncodingT1
, No_VFP
, eSize16
,
13565 &EmulateInstructionARM::EmulateLDRBImmediate
,
13566 "ldrb<c> <Rt>,[<Rn>{,#<imm5>}]"},
13567 {0xfff00000, 0xf8900000, ARMV6T2_ABOVE
, eEncodingT2
, No_VFP
, eSize32
,
13568 &EmulateInstructionARM::EmulateLDRBImmediate
,
13569 "ldrb<c>.w <Rt>,[<Rn>{,#<imm12>}]"},
13570 {0xfff00800, 0xf8100800, ARMV6T2_ABOVE
, eEncodingT3
, No_VFP
, eSize32
,
13571 &EmulateInstructionARM::EmulateLDRBImmediate
,
13572 "ldrb<c> <Rt>,[<Rn>, #+/-<imm8>]{!}"},
13573 {0xff7f0000, 0xf81f0000, ARMV6T2_ABOVE
, eEncodingT1
, No_VFP
, eSize32
,
13574 &EmulateInstructionARM::EmulateLDRBLiteral
, "ldrb<c> <Rt>,[...]"},
13575 {0xfffffe00, 0x00005c00, ARMV6T2_ABOVE
, eEncodingT1
, No_VFP
, eSize16
,
13576 &EmulateInstructionARM::EmulateLDRBRegister
, "ldrb<c> <Rt>,[<Rn>,<Rm>]"},
13577 {0xfff00fc0, 0xf8100000, ARMV6T2_ABOVE
, eEncodingT2
, No_VFP
, eSize32
,
13578 &EmulateInstructionARM::EmulateLDRBRegister
,
13579 "ldrb<c>.w <Rt>,[<Rn>,<Rm>{,LSL #imm2>}]"},
13580 {0xfffff800, 0x00008800, ARMV4T_ABOVE
, eEncodingT1
, No_VFP
, eSize16
,
13581 &EmulateInstructionARM::EmulateLDRHImmediate
,
13582 "ldrh<c> <Rt>, [<Rn>{,#<imm>}]"},
13583 {0xfff00000, 0xf8b00000, ARMV6T2_ABOVE
, eEncodingT2
, No_VFP
, eSize32
,
13584 &EmulateInstructionARM::EmulateLDRHImmediate
,
13585 "ldrh<c>.w <Rt>,[<Rn>{,#<imm12>}]"},
13586 {0xfff00800, 0xf8300800, ARMV6T2_ABOVE
, eEncodingT3
, No_VFP
, eSize32
,
13587 &EmulateInstructionARM::EmulateLDRHImmediate
,
13588 "ldrh<c> <Rt>,[<Rn>,#+/-<imm8>]{!}"},
13589 {0xff7f0000, 0xf83f0000, ARMV6T2_ABOVE
, eEncodingT1
, No_VFP
, eSize32
,
13590 &EmulateInstructionARM::EmulateLDRHLiteral
, "ldrh<c> <Rt>, <label>"},
13591 {0xfffffe00, 0x00005a00, ARMV4T_ABOVE
, eEncodingT1
, No_VFP
, eSize16
,
13592 &EmulateInstructionARM::EmulateLDRHRegister
,
13593 "ldrh<c> <Rt>, [<Rn>,<Rm>]"},
13594 {0xfff00fc0, 0xf8300000, ARMV6T2_ABOVE
, eEncodingT2
, No_VFP
, eSize32
,
13595 &EmulateInstructionARM::EmulateLDRHRegister
,
13596 "ldrh<c>.w <Rt>,[<Rn>,<Rm>{,LSL #<imm2>}]"},
13597 {0xfff00000, 0xf9900000, ARMV6T2_ABOVE
, eEncodingT1
, No_VFP
, eSize32
,
13598 &EmulateInstructionARM::EmulateLDRSBImmediate
,
13599 "ldrsb<c> <Rt>,[<Rn>,#<imm12>]"},
13600 {0xfff00800, 0xf9100800, ARMV6T2_ABOVE
, eEncodingT2
, No_VFP
, eSize32
,
13601 &EmulateInstructionARM::EmulateLDRSBImmediate
,
13602 "ldrsb<c> <Rt>,[<Rn>,#+/-<imm8>]"},
13603 {0xff7f0000, 0xf91f0000, ARMV6T2_ABOVE
, eEncodingT1
, No_VFP
, eSize32
,
13604 &EmulateInstructionARM::EmulateLDRSBLiteral
, "ldrsb<c> <Rt>, <label>"},
13605 {0xfffffe00, 0x00005600, ARMV4T_ABOVE
, eEncodingT1
, No_VFP
, eSize16
,
13606 &EmulateInstructionARM::EmulateLDRSBRegister
,
13607 "ldrsb<c> <Rt>,[<Rn>,<Rm>]"},
13608 {0xfff00fc0, 0xf9100000, ARMV6T2_ABOVE
, eEncodingT2
, No_VFP
, eSize32
,
13609 &EmulateInstructionARM::EmulateLDRSBRegister
,
13610 "ldrsb<c>.w <Rt>,[<Rn>,<Rm>{,LSL #imm2>}]"},
13611 {0xfff00000, 0xf9b00000, ARMV6T2_ABOVE
, eEncodingT1
, No_VFP
, eSize32
,
13612 &EmulateInstructionARM::EmulateLDRSHImmediate
,
13613 "ldrsh<c> <Rt>,[<Rn>,#<imm12>]"},
13614 {0xfff00800, 0xf9300800, ARMV6T2_ABOVE
, eEncodingT2
, No_VFP
, eSize32
,
13615 &EmulateInstructionARM::EmulateLDRSHImmediate
,
13616 "ldrsh<c> <Rt>,[<Rn>,#+/-<imm8>]"},
13617 {0xff7f0000, 0xf93f0000, ARMV6T2_ABOVE
, eEncodingT1
, No_VFP
, eSize32
,
13618 &EmulateInstructionARM::EmulateLDRSHLiteral
, "ldrsh<c> <Rt>,<label>"},
13619 {0xfffffe00, 0x00005e00, ARMV4T_ABOVE
, eEncodingT1
, No_VFP
, eSize16
,
13620 &EmulateInstructionARM::EmulateLDRSHRegister
,
13621 "ldrsh<c> <Rt>,[<Rn>,<Rm>]"},
13622 {0xfff00fc0, 0xf9300000, ARMV6T2_ABOVE
, eEncodingT2
, No_VFP
, eSize32
,
13623 &EmulateInstructionARM::EmulateLDRSHRegister
,
13624 "ldrsh<c>.w <Rt>,[<Rn>,<Rm>{,LSL #<imm2>}]"},
13625 {0xfe500000, 0xe8500000, ARMV6T2_ABOVE
, eEncodingT1
, No_VFP
, eSize32
,
13626 &EmulateInstructionARM::EmulateLDRDImmediate
,
13627 "ldrd<c> <Rt>, <Rt2>, [<Rn>,#+/-<imm>]!"},
13628 {0xfe100f00, 0xec100b00, ARMvAll
, eEncodingT1
, VFPv2_ABOVE
, eSize32
,
13629 &EmulateInstructionARM::EmulateVLDM
, "vldm{mode}<c> <Rn>{!}, <list>"},
13630 {0xfe100f00, 0xec100a00, ARMvAll
, eEncodingT2
, VFPv2v3
, eSize32
,
13631 &EmulateInstructionARM::EmulateVLDM
, "vldm{mode}<c> <Rn>{!}, <list>"},
13632 {0xffe00f00, 0xed100b00, ARMvAll
, eEncodingT1
, VFPv2_ABOVE
, eSize32
,
13633 &EmulateInstructionARM::EmulateVLDR
, "vldr<c> <Dd>, [<Rn>{,#+/-<imm>}]"},
13634 {0xff300f00, 0xed100a00, ARMvAll
, eEncodingT2
, VFPv2v3
, eSize32
,
13635 &EmulateInstructionARM::EmulateVLDR
, "vldr<c> <Sd>, {<Rn>{,#+/-<imm>}]"},
13636 {0xffb00000, 0xf9200000, ARMvAll
, eEncodingT1
, AdvancedSIMD
, eSize32
,
13637 &EmulateInstructionARM::EmulateVLD1Multiple
,
13638 "vld1<c>.<size> <list>, [<Rn>{@<align>}],<Rm>"},
13639 {0xffb00300, 0xf9a00000, ARMvAll
, eEncodingT1
, AdvancedSIMD
, eSize32
,
13640 &EmulateInstructionARM::EmulateVLD1Single
,
13641 "vld1<c>.<size> <list>, [<Rn>{@<align>}],<Rm>"},
13642 {0xffb00f00, 0xf9a00c00, ARMvAll
, eEncodingT1
, AdvancedSIMD
, eSize32
,
13643 &EmulateInstructionARM::EmulateVLD1SingleAll
,
13644 "vld1<c>.<size> <list>, [<Rn>{@<align>}], <Rm>"},
13646 // Store instructions
13647 {0xfffff800, 0x0000c000, ARMV4T_ABOVE
, eEncodingT1
, No_VFP
, eSize16
,
13648 &EmulateInstructionARM::EmulateSTM
, "stm<c> <Rn>{!} <registers>"},
13649 {0xffd00000, 0xe8800000, ARMV6T2_ABOVE
, eEncodingT2
, No_VFP
, eSize32
,
13650 &EmulateInstructionARM::EmulateSTM
, "stm<c>.w <Rn>{!} <registers>"},
13651 {0xffd00000, 0xe9000000, ARMV6T2_ABOVE
, eEncodingT1
, No_VFP
, eSize32
,
13652 &EmulateInstructionARM::EmulateSTMDB
, "stmdb<c> <Rn>{!} <registers>"},
13653 {0xfffff800, 0x00006000, ARMV4T_ABOVE
, eEncodingT1
, No_VFP
, eSize16
,
13654 &EmulateInstructionARM::EmulateSTRThumb
, "str<c> <Rt>, [<Rn>{,#<imm>}]"},
13655 {0xfffff800, 0x00009000, ARMV4T_ABOVE
, eEncodingT2
, No_VFP
, eSize16
,
13656 &EmulateInstructionARM::EmulateSTRThumb
, "str<c> <Rt>, [SP,#<imm>]"},
13657 {0xfff00000, 0xf8c00000, ARMV6T2_ABOVE
, eEncodingT3
, No_VFP
, eSize32
,
13658 &EmulateInstructionARM::EmulateSTRThumb
,
13659 "str<c>.w <Rt>, [<Rn>,#<imm12>]"},
13660 {0xfff00800, 0xf8400800, ARMV6T2_ABOVE
, eEncodingT4
, No_VFP
, eSize32
,
13661 &EmulateInstructionARM::EmulateSTRThumb
,
13662 "str<c> <Rt>, [<Rn>,#+/-<imm8>]"},
13663 {0xfffffe00, 0x00005000, ARMV4T_ABOVE
, eEncodingT1
, No_VFP
, eSize16
,
13664 &EmulateInstructionARM::EmulateSTRRegister
, "str<c> <Rt> ,{<Rn>, <Rm>]"},
13665 {0xfff00fc0, 0xf8400000, ARMV6T2_ABOVE
, eEncodingT2
, No_VFP
, eSize32
,
13666 &EmulateInstructionARM::EmulateSTRRegister
,
13667 "str<c>.w <Rt>, [<Rn>, <Rm> {lsl #imm2>}]"},
13668 {0xfffff800, 0x00007000, ARMV4T_ABOVE
, eEncodingT1
, No_VFP
, eSize16
,
13669 &EmulateInstructionARM::EmulateSTRBThumb
,
13670 "strb<c> <Rt>, [<Rn>, #<imm5>]"},
13671 {0xfff00000, 0xf8800000, ARMV6T2_ABOVE
, eEncodingT2
, No_VFP
, eSize32
,
13672 &EmulateInstructionARM::EmulateSTRBThumb
,
13673 "strb<c>.w <Rt>, [<Rn>, #<imm12>]"},
13674 {0xfff00800, 0xf8000800, ARMV6T2_ABOVE
, eEncodingT3
, No_VFP
, eSize32
,
13675 &EmulateInstructionARM::EmulateSTRBThumb
,
13676 "strb<c> <Rt> ,[<Rn>, #+/-<imm8>]{!}"},
13677 {0xfffffe00, 0x00005200, ARMV4T_ABOVE
, eEncodingT1
, No_VFP
, eSize16
,
13678 &EmulateInstructionARM::EmulateSTRHRegister
, "strh<c> <Rt>,[<Rn>,<Rm>]"},
13679 {0xfff00fc0, 0xf8200000, ARMV6T2_ABOVE
, eEncodingT2
, No_VFP
, eSize32
,
13680 &EmulateInstructionARM::EmulateSTRHRegister
,
13681 "strh<c>.w <Rt>,[<Rn>,<Rm>{,LSL #<imm2>}]"},
13682 {0xfff00000, 0xe8400000, ARMV6T2_ABOVE
, eEncodingT1
, No_VFP
, eSize32
,
13683 &EmulateInstructionARM::EmulateSTREX
,
13684 "strex<c> <Rd>, <Rt>, [<Rn{,#<imm>}]"},
13685 {0xfe500000, 0xe8400000, ARMV6T2_ABOVE
, eEncodingT1
, No_VFP
, eSize32
,
13686 &EmulateInstructionARM::EmulateSTRDImm
,
13687 "strd<c> <Rt>, <Rt2>, [<Rn>, #+/-<imm>]!"},
13688 {0xfe100f00, 0xec000b00, ARMvAll
, eEncodingT1
, VFPv2_ABOVE
, eSize32
,
13689 &EmulateInstructionARM::EmulateVSTM
, "vstm{mode}<c> <Rn>{!}, <list>"},
13690 {0xfea00f00, 0xec000a00, ARMvAll
, eEncodingT2
, VFPv2v3
, eSize32
,
13691 &EmulateInstructionARM::EmulateVSTM
, "vstm{mode}<c> <Rn>{!}, <list>"},
13692 {0xff300f00, 0xed000b00, ARMvAll
, eEncodingT1
, VFPv2_ABOVE
, eSize32
,
13693 &EmulateInstructionARM::EmulateVSTR
, "vstr<c> <Dd>, [<Rn>{,#+/-<imm>}]"},
13694 {0xff300f00, 0xed000a00, ARMvAll
, eEncodingT2
, VFPv2v3
, eSize32
,
13695 &EmulateInstructionARM::EmulateVSTR
, "vstr<c> <Sd>, [<Rn>{,#+/-<imm>}]"},
13696 {0xffb00000, 0xf9000000, ARMvAll
, eEncodingT1
, AdvancedSIMD
, eSize32
,
13697 &EmulateInstructionARM::EmulateVST1Multiple
,
13698 "vst1<c>.<size> <list>, [<Rn>{@<align>}], <Rm>"},
13699 {0xffb00300, 0xf9800000, ARMvAll
, eEncodingT1
, AdvancedSIMD
, eSize32
,
13700 &EmulateInstructionARM::EmulateVST1Single
,
13701 "vst1<c>.<size> <list>, [<Rn>{@<align>}], <Rm>"},
13703 // Other instructions
13704 {0xffffffc0, 0x0000b240, ARMV6_ABOVE
, eEncodingT1
, No_VFP
, eSize16
,
13705 &EmulateInstructionARM::EmulateSXTB
, "sxtb<c> <Rd>,<Rm>"},
13706 {0xfffff080, 0xfa4ff080, ARMV6_ABOVE
, eEncodingT2
, No_VFP
, eSize32
,
13707 &EmulateInstructionARM::EmulateSXTB
, "sxtb<c>.w <Rd>,<Rm>{,<rotation>}"},
13708 {0xffffffc0, 0x0000b200, ARMV6_ABOVE
, eEncodingT1
, No_VFP
, eSize16
,
13709 &EmulateInstructionARM::EmulateSXTH
, "sxth<c> <Rd>,<Rm>"},
13710 {0xfffff080, 0xfa0ff080, ARMV6T2_ABOVE
, eEncodingT2
, No_VFP
, eSize32
,
13711 &EmulateInstructionARM::EmulateSXTH
, "sxth<c>.w <Rd>,<Rm>{,<rotation>}"},
13712 {0xffffffc0, 0x0000b2c0, ARMV6_ABOVE
, eEncodingT1
, No_VFP
, eSize16
,
13713 &EmulateInstructionARM::EmulateUXTB
, "uxtb<c> <Rd>,<Rm>"},
13714 {0xfffff080, 0xfa5ff080, ARMV6T2_ABOVE
, eEncodingT2
, No_VFP
, eSize32
,
13715 &EmulateInstructionARM::EmulateUXTB
, "uxtb<c>.w <Rd>,<Rm>{,<rotation>}"},
13716 {0xffffffc0, 0x0000b280, ARMV6_ABOVE
, eEncodingT1
, No_VFP
, eSize16
,
13717 &EmulateInstructionARM::EmulateUXTH
, "uxth<c> <Rd>,<Rm>"},
13718 {0xfffff080, 0xfa1ff080, ARMV6T2_ABOVE
, eEncodingT2
, No_VFP
, eSize32
,
13719 &EmulateInstructionARM::EmulateUXTH
, "uxth<c>.w <Rd>,<Rm>{,<rotation>}"},
13722 const size_t k_num_thumb_opcodes
= std::size(g_thumb_opcodes
);
13723 for (size_t i
= 0; i
< k_num_thumb_opcodes
; ++i
) {
13724 if ((g_thumb_opcodes
[i
].mask
& opcode
) == g_thumb_opcodes
[i
].value
&&
13725 (g_thumb_opcodes
[i
].variants
& arm_isa
) != 0)
13726 return &g_thumb_opcodes
[i
];
13731 bool EmulateInstructionARM::SetArchitecture(const ArchSpec
&arch
) {
13734 llvm::StringRef arch_cstr
= arch
.GetArchitectureName();
13735 if (arch_cstr
.equals_insensitive("armv4t"))
13736 m_arm_isa
= ARMv4T
;
13737 else if (arch_cstr
.equals_insensitive("armv5tej"))
13738 m_arm_isa
= ARMv5TEJ
;
13739 else if (arch_cstr
.equals_insensitive("armv5te"))
13740 m_arm_isa
= ARMv5TE
;
13741 else if (arch_cstr
.equals_insensitive("armv5t"))
13742 m_arm_isa
= ARMv5T
;
13743 else if (arch_cstr
.equals_insensitive("armv6k"))
13744 m_arm_isa
= ARMv6K
;
13745 else if (arch_cstr
.equals_insensitive("armv6t2"))
13746 m_arm_isa
= ARMv6T2
;
13747 else if (arch_cstr
.equals_insensitive("armv7s"))
13748 m_arm_isa
= ARMv7S
;
13749 else if (arch_cstr
.equals_insensitive("arm"))
13750 m_arm_isa
= ARMvAll
;
13751 else if (arch_cstr
.equals_insensitive("thumb"))
13752 m_arm_isa
= ARMvAll
;
13753 else if (arch_cstr
.starts_with_insensitive("armv4"))
13755 else if (arch_cstr
.starts_with_insensitive("armv6"))
13757 else if (arch_cstr
.starts_with_insensitive("armv7"))
13759 else if (arch_cstr
.starts_with_insensitive("armv8"))
13761 return m_arm_isa
!= 0;
13764 bool EmulateInstructionARM::SetInstruction(const Opcode
&insn_opcode
,
13765 const Address
&inst_addr
,
13767 if (EmulateInstruction::SetInstruction(insn_opcode
, inst_addr
, target
)) {
13768 if (m_arch
.GetTriple().getArch() == llvm::Triple::thumb
||
13769 m_arch
.IsAlwaysThumbInstructions())
13770 m_opcode_mode
= eModeThumb
;
13772 AddressClass addr_class
= inst_addr
.GetAddressClass();
13774 if ((addr_class
== AddressClass::eCode
) ||
13775 (addr_class
== AddressClass::eUnknown
))
13776 m_opcode_mode
= eModeARM
;
13777 else if (addr_class
== AddressClass::eCodeAlternateISA
)
13778 m_opcode_mode
= eModeThumb
;
13782 if (m_opcode_mode
== eModeThumb
|| m_arch
.IsAlwaysThumbInstructions())
13783 m_opcode_cpsr
= CPSR_MODE_USR
| MASK_CPSR_T
;
13785 m_opcode_cpsr
= CPSR_MODE_USR
;
13791 bool EmulateInstructionARM::ReadInstruction() {
13792 bool success
= false;
13793 m_opcode_cpsr
= ReadRegisterUnsigned(eRegisterKindGeneric
,
13794 LLDB_REGNUM_GENERIC_FLAGS
, 0, &success
);
13797 ReadRegisterUnsigned(eRegisterKindGeneric
, LLDB_REGNUM_GENERIC_PC
,
13798 LLDB_INVALID_ADDRESS
, &success
);
13800 Context read_inst_context
;
13801 read_inst_context
.type
= eContextReadOpcode
;
13802 read_inst_context
.SetNoArgs();
13804 if ((m_opcode_cpsr
& MASK_CPSR_T
) || m_arch
.IsAlwaysThumbInstructions()) {
13805 m_opcode_mode
= eModeThumb
;
13806 uint32_t thumb_opcode
= MemARead(read_inst_context
, pc
, 2, 0, &success
);
13809 if ((thumb_opcode
& 0xe000) != 0xe000 ||
13810 ((thumb_opcode
& 0x1800u
) == 0)) {
13811 m_opcode
.SetOpcode16(thumb_opcode
, GetByteOrder());
13813 m_opcode
.SetOpcode32(
13814 (thumb_opcode
<< 16) |
13815 MemARead(read_inst_context
, pc
+ 2, 2, 0, &success
),
13820 m_opcode_mode
= eModeARM
;
13821 m_opcode
.SetOpcode32(MemARead(read_inst_context
, pc
, 4, 0, &success
),
13825 if (!m_ignore_conditions
) {
13826 // If we are not ignoreing the conditions then init the it session from
13827 // the current value of cpsr.
13828 uint32_t it
= (Bits32(m_opcode_cpsr
, 15, 10) << 2) |
13829 Bits32(m_opcode_cpsr
, 26, 25);
13831 m_it_session
.InitIT(it
);
13836 m_opcode_mode
= eModeInvalid
;
13837 m_addr
= LLDB_INVALID_ADDRESS
;
13842 uint32_t EmulateInstructionARM::ArchVersion() { return m_arm_isa
; }
13844 bool EmulateInstructionARM::ConditionPassed(const uint32_t opcode
) {
13845 // If we are ignoring conditions, then always return true. this allows us to
13846 // iterate over disassembly code and still emulate an instruction even if we
13847 // don't have all the right bits set in the CPSR register...
13848 if (m_ignore_conditions
)
13851 const uint32_t cond
= CurrentCond(opcode
);
13852 if (cond
== UINT32_MAX
)
13855 bool result
= false;
13856 switch (UnsignedBits(cond
, 3, 1)) {
13858 if (m_opcode_cpsr
== 0)
13861 result
= (m_opcode_cpsr
& MASK_CPSR_Z
) != 0;
13864 if (m_opcode_cpsr
== 0)
13867 result
= (m_opcode_cpsr
& MASK_CPSR_C
) != 0;
13870 if (m_opcode_cpsr
== 0)
13873 result
= (m_opcode_cpsr
& MASK_CPSR_N
) != 0;
13876 if (m_opcode_cpsr
== 0)
13879 result
= (m_opcode_cpsr
& MASK_CPSR_V
) != 0;
13882 if (m_opcode_cpsr
== 0)
13885 result
= ((m_opcode_cpsr
& MASK_CPSR_C
) != 0) &&
13886 ((m_opcode_cpsr
& MASK_CPSR_Z
) == 0);
13889 if (m_opcode_cpsr
== 0)
13892 bool n
= (m_opcode_cpsr
& MASK_CPSR_N
);
13893 bool v
= (m_opcode_cpsr
& MASK_CPSR_V
);
13898 if (m_opcode_cpsr
== 0)
13901 bool n
= (m_opcode_cpsr
& MASK_CPSR_N
);
13902 bool v
= (m_opcode_cpsr
& MASK_CPSR_V
);
13903 result
= n
== v
&& ((m_opcode_cpsr
& MASK_CPSR_Z
) == 0);
13907 // Always execute (cond == 0b1110, or the special 0b1111 which gives
13908 // opcodes different meanings, but always means execution happens.
13917 uint32_t EmulateInstructionARM::CurrentCond(const uint32_t opcode
) {
13918 switch (m_opcode_mode
) {
13923 return UnsignedBits(opcode
, 31, 28);
13926 // For T1 and T3 encodings of the Branch instruction, it returns the 4-bit
13927 // 'cond' field of the encoding.
13929 const uint32_t byte_size
= m_opcode
.GetByteSize();
13930 if (byte_size
== 2) {
13931 if (Bits32(opcode
, 15, 12) == 0x0d && Bits32(opcode
, 11, 8) != 0x0f)
13932 return Bits32(opcode
, 11, 8);
13933 } else if (byte_size
== 4) {
13934 if (Bits32(opcode
, 31, 27) == 0x1e && Bits32(opcode
, 15, 14) == 0x02 &&
13935 Bits32(opcode
, 12, 12) == 0x00 && Bits32(opcode
, 25, 22) <= 0x0d) {
13936 return Bits32(opcode
, 25, 22);
13939 // We have an invalid thumb instruction, let's bail out.
13942 return m_it_session
.GetCond();
13945 return UINT32_MAX
; // Return invalid value
13948 bool EmulateInstructionARM::InITBlock() {
13949 return CurrentInstrSet() == eModeThumb
&& m_it_session
.InITBlock();
13952 bool EmulateInstructionARM::LastInITBlock() {
13953 return CurrentInstrSet() == eModeThumb
&& m_it_session
.LastInITBlock();
13956 bool EmulateInstructionARM::BadMode(uint32_t mode
) {
13960 return false; // '10000'
13962 return false; // '10001'
13964 return false; // '10010'
13966 return false; // '10011'
13968 return false; // '10110'
13970 return false; // '10111'
13972 return false; // '11011'
13974 return false; // '11111'
13981 bool EmulateInstructionARM::CurrentModeIsPrivileged() {
13982 uint32_t mode
= Bits32(m_opcode_cpsr
, 4, 0);
13993 void EmulateInstructionARM::CPSRWriteByInstr(uint32_t value
, uint32_t bytemask
,
13994 bool affect_execstate
) {
13995 bool privileged
= CurrentModeIsPrivileged();
13997 uint32_t tmp_cpsr
= Bits32(m_opcode_cpsr
, 23, 20) << 20;
13999 if (BitIsSet(bytemask
, 3)) {
14000 tmp_cpsr
= tmp_cpsr
| (Bits32(value
, 31, 27) << 27);
14001 if (affect_execstate
)
14002 tmp_cpsr
= tmp_cpsr
| (Bits32(value
, 26, 24) << 24);
14005 if (BitIsSet(bytemask
, 2)) {
14006 tmp_cpsr
= tmp_cpsr
| (Bits32(value
, 19, 16) << 16);
14009 if (BitIsSet(bytemask
, 1)) {
14010 if (affect_execstate
)
14011 tmp_cpsr
= tmp_cpsr
| (Bits32(value
, 15, 10) << 10);
14012 tmp_cpsr
= tmp_cpsr
| (Bit32(value
, 9) << 9);
14014 tmp_cpsr
= tmp_cpsr
| (Bit32(value
, 8) << 8);
14017 if (BitIsSet(bytemask
, 0)) {
14019 tmp_cpsr
= tmp_cpsr
| (Bits32(value
, 7, 6) << 6);
14020 if (affect_execstate
)
14021 tmp_cpsr
= tmp_cpsr
| (Bit32(value
, 5) << 5);
14023 tmp_cpsr
= tmp_cpsr
| Bits32(value
, 4, 0);
14026 m_opcode_cpsr
= tmp_cpsr
;
14029 bool EmulateInstructionARM::BranchWritePC(const Context
&context
,
14033 // Check the current instruction set.
14034 if (CurrentInstrSet() == eModeARM
)
14035 target
= addr
& 0xfffffffc;
14037 target
= addr
& 0xfffffffe;
14039 return WriteRegisterUnsigned(context
, eRegisterKindGeneric
,
14040 LLDB_REGNUM_GENERIC_PC
, target
);
14043 // As a side effect, BXWritePC sets context.arg2 to eModeARM or eModeThumb by
14044 // inspecting addr.
14045 bool EmulateInstructionARM::BXWritePC(Context
&context
, uint32_t addr
) {
14047 // If the CPSR is changed due to switching between ARM and Thumb ISETSTATE,
14048 // we want to record it and issue a WriteRegister callback so the clients can
14049 // track the mode changes accordingly.
14050 bool cpsr_changed
= false;
14052 if (BitIsSet(addr
, 0)) {
14053 if (CurrentInstrSet() != eModeThumb
) {
14054 SelectInstrSet(eModeThumb
);
14055 cpsr_changed
= true;
14057 target
= addr
& 0xfffffffe;
14058 context
.SetISA(eModeThumb
);
14059 } else if (BitIsClear(addr
, 1)) {
14060 if (CurrentInstrSet() != eModeARM
) {
14061 SelectInstrSet(eModeARM
);
14062 cpsr_changed
= true;
14064 target
= addr
& 0xfffffffc;
14065 context
.SetISA(eModeARM
);
14067 return false; // address<1:0> == '10' => UNPREDICTABLE
14069 if (cpsr_changed
) {
14070 if (!WriteRegisterUnsigned(context
, eRegisterKindGeneric
,
14071 LLDB_REGNUM_GENERIC_FLAGS
, m_new_inst_cpsr
))
14074 return WriteRegisterUnsigned(context
, eRegisterKindGeneric
,
14075 LLDB_REGNUM_GENERIC_PC
, target
);
14078 // Dispatches to either BXWritePC or BranchWritePC based on architecture
14080 bool EmulateInstructionARM::LoadWritePC(Context
&context
, uint32_t addr
) {
14081 if (ArchVersion() >= ARMv5T
)
14082 return BXWritePC(context
, addr
);
14084 return BranchWritePC((const Context
)context
, addr
);
14087 // Dispatches to either BXWritePC or BranchWritePC based on architecture
14088 // versions and current instruction set.
14089 bool EmulateInstructionARM::ALUWritePC(Context
&context
, uint32_t addr
) {
14090 if (ArchVersion() >= ARMv7
&& CurrentInstrSet() == eModeARM
)
14091 return BXWritePC(context
, addr
);
14093 return BranchWritePC((const Context
)context
, addr
);
14096 EmulateInstructionARM::Mode
EmulateInstructionARM::CurrentInstrSet() {
14097 return m_opcode_mode
;
14100 // Set the 'T' bit of our CPSR. The m_opcode_mode gets updated when the next
14101 // ReadInstruction() is performed. This function has a side effect of updating
14102 // the m_new_inst_cpsr member variable if necessary.
14103 bool EmulateInstructionARM::SelectInstrSet(Mode arm_or_thumb
) {
14104 m_new_inst_cpsr
= m_opcode_cpsr
;
14105 switch (arm_or_thumb
) {
14109 // Clear the T bit.
14110 m_new_inst_cpsr
&= ~MASK_CPSR_T
;
14114 m_new_inst_cpsr
|= MASK_CPSR_T
;
14120 // This function returns TRUE if the processor currently provides support for
14121 // unaligned memory accesses, or FALSE otherwise. This is always TRUE in ARMv7,
14122 // controllable by the SCTLR.U bit in ARMv6, and always FALSE before ARMv6.
14123 bool EmulateInstructionARM::UnalignedSupport() {
14124 return (ArchVersion() >= ARMv7
);
14127 // The main addition and subtraction instructions can produce status
14128 // information about both unsigned carry and signed overflow conditions. This
14129 // status information can be used to synthesize multi-word additions and
14131 EmulateInstructionARM::AddWithCarryResult
14132 EmulateInstructionARM::AddWithCarry(uint32_t x
, uint32_t y
, uint8_t carry_in
) {
14137 uint64_t unsigned_sum
= x
+ y
+ carry_in
;
14138 int64_t signed_sum
= (int32_t)x
+ (int32_t)y
+ (int32_t)carry_in
;
14140 result
= UnsignedBits(unsigned_sum
, 31, 0);
14141 // carry_out = (result == unsigned_sum ? 0 : 1);
14142 overflow
= ((int32_t)result
== signed_sum
? 0 : 1);
14145 carry_out
= ((int32_t)x
>= (int32_t)(~y
)) ? 1 : 0;
14147 carry_out
= ((int32_t)x
> (int32_t)y
) ? 1 : 0;
14149 AddWithCarryResult res
= {result
, carry_out
, overflow
};
14153 uint32_t EmulateInstructionARM::ReadCoreReg(uint32_t num
, bool *success
) {
14154 lldb::RegisterKind reg_kind
;
14158 reg_kind
= eRegisterKindGeneric
;
14159 reg_num
= LLDB_REGNUM_GENERIC_SP
;
14162 reg_kind
= eRegisterKindGeneric
;
14163 reg_num
= LLDB_REGNUM_GENERIC_RA
;
14166 reg_kind
= eRegisterKindGeneric
;
14167 reg_num
= LLDB_REGNUM_GENERIC_PC
;
14170 if (num
< SP_REG
) {
14171 reg_kind
= eRegisterKindDWARF
;
14172 reg_num
= dwarf_r0
+ num
;
14174 // assert(0 && "Invalid register number");
14181 // Read our register.
14182 uint32_t val
= ReadRegisterUnsigned(reg_kind
, reg_num
, 0, success
);
14184 // When executing an ARM instruction , PC reads as the address of the current
14185 // instruction plus 8. When executing a Thumb instruction , PC reads as the
14186 // address of the current instruction plus 4.
14188 if (CurrentInstrSet() == eModeARM
)
14197 // Write the result to the ARM core register Rd, and optionally update the
14198 // condition flags based on the result.
14200 // This helper method tries to encapsulate the following pseudocode from the
14201 // ARM Architecture Reference Manual:
14203 // if d == 15 then // Can only occur for encoding A1
14204 // ALUWritePC(result); // setflags is always FALSE here
14207 // if setflags then
14208 // APSR.N = result<31>;
14209 // APSR.Z = IsZeroBit(result);
14211 // // APSR.V unchanged
14213 // In the above case, the API client does not pass in the overflow arg, which
14214 // defaults to ~0u.
14215 bool EmulateInstructionARM::WriteCoreRegOptionalFlags(
14216 Context
&context
, const uint32_t result
, const uint32_t Rd
, bool setflags
,
14217 const uint32_t carry
, const uint32_t overflow
) {
14219 if (!ALUWritePC(context
, result
))
14222 lldb::RegisterKind reg_kind
;
14226 reg_kind
= eRegisterKindGeneric
;
14227 reg_num
= LLDB_REGNUM_GENERIC_SP
;
14230 reg_kind
= eRegisterKindGeneric
;
14231 reg_num
= LLDB_REGNUM_GENERIC_RA
;
14234 reg_kind
= eRegisterKindDWARF
;
14235 reg_num
= dwarf_r0
+ Rd
;
14237 if (!WriteRegisterUnsigned(context
, reg_kind
, reg_num
, result
))
14240 return WriteFlags(context
, result
, carry
, overflow
);
14245 // This helper method tries to encapsulate the following pseudocode from the
14246 // ARM Architecture Reference Manual:
14248 // APSR.N = result<31>;
14249 // APSR.Z = IsZeroBit(result);
14251 // APSR.V = overflow
14253 // Default arguments can be specified for carry and overflow parameters, which
14254 // means not to update the respective flags.
14255 bool EmulateInstructionARM::WriteFlags(Context
&context
, const uint32_t result
,
14256 const uint32_t carry
,
14257 const uint32_t overflow
) {
14258 m_new_inst_cpsr
= m_opcode_cpsr
;
14259 SetBit32(m_new_inst_cpsr
, CPSR_N_POS
, Bit32(result
, CPSR_N_POS
));
14260 SetBit32(m_new_inst_cpsr
, CPSR_Z_POS
, result
== 0 ? 1 : 0);
14262 SetBit32(m_new_inst_cpsr
, CPSR_C_POS
, carry
);
14263 if (overflow
!= ~0u)
14264 SetBit32(m_new_inst_cpsr
, CPSR_V_POS
, overflow
);
14265 if (m_new_inst_cpsr
!= m_opcode_cpsr
) {
14266 if (!WriteRegisterUnsigned(context
, eRegisterKindGeneric
,
14267 LLDB_REGNUM_GENERIC_FLAGS
, m_new_inst_cpsr
))
14273 bool EmulateInstructionARM::EvaluateInstruction(uint32_t evaluate_options
) {
14274 ARMOpcode
*opcode_data
= nullptr;
14276 if (m_opcode_mode
== eModeThumb
)
14278 GetThumbOpcodeForInstruction(m_opcode
.GetOpcode32(), m_arm_isa
);
14279 else if (m_opcode_mode
== eModeARM
)
14280 opcode_data
= GetARMOpcodeForInstruction(m_opcode
.GetOpcode32(), m_arm_isa
);
14282 const bool auto_advance_pc
=
14283 evaluate_options
& eEmulateInstructionOptionAutoAdvancePC
;
14284 m_ignore_conditions
=
14285 evaluate_options
& eEmulateInstructionOptionIgnoreConditions
;
14287 bool success
= false;
14288 if (m_opcode_cpsr
== 0 || !m_ignore_conditions
) {
14290 ReadRegisterUnsigned(eRegisterKindDWARF
, dwarf_cpsr
, 0, &success
);
14293 // Only return false if we are unable to read the CPSR if we care about
14295 if (!success
&& !m_ignore_conditions
)
14298 uint32_t orig_pc_value
= 0;
14299 if (auto_advance_pc
) {
14301 ReadRegisterUnsigned(eRegisterKindDWARF
, dwarf_pc
, 0, &success
);
14306 // Call the Emulate... function if we managed to decode the opcode.
14308 success
= (this->*opcode_data
->callback
)(m_opcode
.GetOpcode32(),
14309 opcode_data
->encoding
);
14314 // Advance the ITSTATE bits to their values for the next instruction if we
14315 // haven't just executed an IT instruction what initialized it.
14316 if (m_opcode_mode
== eModeThumb
&& m_it_session
.InITBlock() &&
14317 (opcode_data
== nullptr ||
14318 opcode_data
->callback
!= &EmulateInstructionARM::EmulateIT
))
14319 m_it_session
.ITAdvance();
14321 if (auto_advance_pc
) {
14322 uint32_t after_pc_value
=
14323 ReadRegisterUnsigned(eRegisterKindDWARF
, dwarf_pc
, 0, &success
);
14327 if (after_pc_value
== orig_pc_value
) {
14328 after_pc_value
+= m_opcode
.GetByteSize();
14330 EmulateInstruction::Context context
;
14331 context
.type
= eContextAdvancePC
;
14332 context
.SetNoArgs();
14333 if (!WriteRegisterUnsigned(context
, eRegisterKindDWARF
, dwarf_pc
,
14341 EmulateInstruction::InstructionCondition
14342 EmulateInstructionARM::GetInstructionCondition() {
14343 const uint32_t cond
= CurrentCond(m_opcode
.GetOpcode32());
14344 if (cond
== 0xe || cond
== 0xf || cond
== UINT32_MAX
)
14345 return EmulateInstruction::UnconditionalCondition
;
14349 bool EmulateInstructionARM::TestEmulation(Stream
&out_stream
, ArchSpec
&arch
,
14350 OptionValueDictionary
*test_data
) {
14352 out_stream
.Printf("TestEmulation: Missing test data.\n");
14356 static constexpr llvm::StringLiteral
opcode_key("opcode");
14357 static constexpr llvm::StringLiteral
before_key("before_state");
14358 static constexpr llvm::StringLiteral
after_key("after_state");
14360 OptionValueSP value_sp
= test_data
->GetValueForKey(opcode_key
);
14362 uint32_t test_opcode
;
14363 if ((value_sp
.get() == nullptr) ||
14364 (value_sp
->GetType() != OptionValue::eTypeUInt64
)) {
14365 out_stream
.Printf("TestEmulation: Error reading opcode from test file.\n");
14368 test_opcode
= value_sp
->GetValueAs
<uint64_t>().value_or(0);
14370 if (arch
.GetTriple().getArch() == llvm::Triple::thumb
||
14371 arch
.IsAlwaysThumbInstructions()) {
14372 m_opcode_mode
= eModeThumb
;
14373 if (test_opcode
< 0x10000)
14374 m_opcode
.SetOpcode16(test_opcode
, endian::InlHostByteOrder());
14376 m_opcode
.SetOpcode32(test_opcode
, endian::InlHostByteOrder());
14377 } else if (arch
.GetTriple().getArch() == llvm::Triple::arm
) {
14378 m_opcode_mode
= eModeARM
;
14379 m_opcode
.SetOpcode32(test_opcode
, endian::InlHostByteOrder());
14381 out_stream
.Printf("TestEmulation: Invalid arch.\n");
14385 EmulationStateARM before_state
;
14386 EmulationStateARM after_state
;
14388 value_sp
= test_data
->GetValueForKey(before_key
);
14389 if ((value_sp
.get() == nullptr) ||
14390 (value_sp
->GetType() != OptionValue::eTypeDictionary
)) {
14391 out_stream
.Printf("TestEmulation: Failed to find 'before' state.\n");
14395 OptionValueDictionary
*state_dictionary
= value_sp
->GetAsDictionary();
14396 if (!before_state
.LoadStateFromDictionary(state_dictionary
)) {
14397 out_stream
.Printf("TestEmulation: Failed loading 'before' state.\n");
14401 value_sp
= test_data
->GetValueForKey(after_key
);
14402 if ((value_sp
.get() == nullptr) ||
14403 (value_sp
->GetType() != OptionValue::eTypeDictionary
)) {
14404 out_stream
.Printf("TestEmulation: Failed to find 'after' state.\n");
14408 state_dictionary
= value_sp
->GetAsDictionary();
14409 if (!after_state
.LoadStateFromDictionary(state_dictionary
)) {
14410 out_stream
.Printf("TestEmulation: Failed loading 'after' state.\n");
14414 SetBaton((void *)&before_state
);
14415 SetCallbacks(&EmulationStateARM::ReadPseudoMemory
,
14416 &EmulationStateARM::WritePseudoMemory
,
14417 &EmulationStateARM::ReadPseudoRegister
,
14418 &EmulationStateARM::WritePseudoRegister
);
14420 bool success
= EvaluateInstruction(eEmulateInstructionOptionAutoAdvancePC
);
14422 out_stream
.Printf("TestEmulation: EvaluateInstruction() failed.\n");
14426 success
= before_state
.CompareState(after_state
, out_stream
);
14428 out_stream
.Printf("TestEmulation: State after emulation does not match "
14429 "'after' state.\n");
14436 // EmulateInstructionARM::GetRegisterName (uint32_t reg_kind, uint32_t reg_num)
14438 // if (reg_kind == eRegisterKindGeneric)
14440 // switch (reg_num)
14442 // case LLDB_REGNUM_GENERIC_PC: return "pc";
14443 // case LLDB_REGNUM_GENERIC_SP: return "sp";
14444 // case LLDB_REGNUM_GENERIC_FP: return "fp";
14445 // case LLDB_REGNUM_GENERIC_RA: return "lr";
14446 // case LLDB_REGNUM_GENERIC_FLAGS: return "cpsr";
14447 // default: return NULL;
14450 // else if (reg_kind == eRegisterKindDWARF)
14452 // return GetARMDWARFRegisterName (reg_num);
14457 bool EmulateInstructionARM::CreateFunctionEntryUnwind(UnwindPlan
&unwind_plan
) {
14458 unwind_plan
.Clear();
14459 unwind_plan
.SetRegisterKind(eRegisterKindDWARF
);
14461 UnwindPlan::RowSP
row(new UnwindPlan::Row
);
14463 // Our previous Call Frame Address is the stack pointer
14464 row
->GetCFAValue().SetIsRegisterPlusOffset(dwarf_sp
, 0);
14466 unwind_plan
.AppendRow(row
);
14467 unwind_plan
.SetSourceName("EmulateInstructionARM");
14468 unwind_plan
.SetSourcedFromCompiler(eLazyBoolNo
);
14469 unwind_plan
.SetUnwindPlanValidAtAllInstructions(eLazyBoolYes
);
14470 unwind_plan
.SetUnwindPlanForSignalTrap(eLazyBoolNo
);
14471 unwind_plan
.SetReturnAddressRegister(dwarf_lr
);