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 // NEED_BRIDGEOS_TRIPLE case llvm::Triple::BridgeOS:
840 /* On Apple iOS et al, the frame pointer register is always r7.
841 * Typically on other ARM systems, thumb code uses r7; arm code uses r11.
842 * Windows on ARM, which is in thumb mode, uses r11 though.
845 uint32_t fp_regnum
= 11;
850 if (m_opcode_mode
== eModeThumb
&& !m_arch
.GetTriple().isOSWindows())
856 uint32_t EmulateInstructionARM::GetFramePointerDWARFRegisterNumber() const {
857 bool is_apple
= false;
858 if (m_arch
.GetTriple().getVendor() == llvm::Triple::Apple
)
860 switch (m_arch
.GetTriple().getOS()) {
861 case llvm::Triple::Darwin
:
862 case llvm::Triple::MacOSX
:
863 case llvm::Triple::IOS
:
870 /* On Apple iOS et al, the frame pointer register is always r7.
871 * Typically on other ARM systems, thumb code uses r7; arm code uses r11.
872 * Windows on ARM, which is in thumb mode, uses r11 though.
875 uint32_t fp_regnum
= dwarf_r11
;
878 fp_regnum
= dwarf_r7
;
880 if (m_opcode_mode
== eModeThumb
&& !m_arch
.GetTriple().isOSWindows())
881 fp_regnum
= dwarf_r7
;
886 // Push Multiple Registers stores multiple registers to the stack, storing to
887 // consecutive memory locations ending just below the address in SP, and
889 // SP to point to the start of the stored data.
890 bool EmulateInstructionARM::EmulatePUSH(const uint32_t opcode
,
891 const ARMEncoding encoding
) {
893 // ARM pseudo code...
894 if (ConditionPassed())
896 EncodingSpecificOperations();
897 NullCheckIfThumbEE(13);
898 address
= SP
- 4*BitCount(registers
);
902 if (registers
<i
> == '1')
904 if i
== 13 && i
!= LowestSetBit(registers
) // Only possible for encoding A1
905 MemA
[address
,4] = bits(32) UNKNOWN
;
907 MemA
[address
,4] = R
[i
];
908 address
= address
+ 4;
912 if (registers
<15> == '1') // Only possible for encoding A1 or A2
913 MemA
[address
,4] = PCStoreValue();
915 SP
= SP
- 4*BitCount(registers
);
919 bool success
= false;
920 if (ConditionPassed(opcode
)) {
921 const uint32_t addr_byte_size
= GetAddressByteSize();
922 const addr_t sp
= ReadCoreReg(SP_REG
, &success
);
925 uint32_t registers
= 0;
926 uint32_t Rt
; // the source register
929 registers
= Bits32(opcode
, 7, 0);
930 // The M bit represents LR.
931 if (Bit32(opcode
, 8))
932 registers
|= (1u << 14);
933 // if BitCount(registers) < 1 then UNPREDICTABLE;
934 if (BitCount(registers
) < 1)
938 // Ignore bits 15 & 13.
939 registers
= Bits32(opcode
, 15, 0) & ~0xa000;
940 // if BitCount(registers) < 2 then UNPREDICTABLE;
941 if (BitCount(registers
) < 2)
945 Rt
= Bits32(opcode
, 15, 12);
946 // if BadReg(t) then UNPREDICTABLE;
949 registers
= (1u << Rt
);
952 registers
= Bits32(opcode
, 15, 0);
953 // Instead of return false, let's handle the following case as well,
954 // which amounts to pushing one reg onto the full descending stacks.
955 // if BitCount(register_list) < 2 then SEE STMDB / STMFD;
958 Rt
= Bits32(opcode
, 15, 12);
959 // if t == 13 then UNPREDICTABLE;
962 registers
= (1u << Rt
);
967 addr_t sp_offset
= addr_byte_size
* BitCount(registers
);
968 addr_t addr
= sp
- sp_offset
;
971 EmulateInstruction::Context context
;
972 context
.type
= EmulateInstruction::eContextPushRegisterOnStack
;
973 std::optional
<RegisterInfo
> sp_reg
=
974 GetRegisterInfo(eRegisterKindDWARF
, dwarf_sp
);
975 for (i
= 0; i
< 15; ++i
) {
976 if (BitIsSet(registers
, i
)) {
977 std::optional
<RegisterInfo
> reg_info
=
978 GetRegisterInfo(eRegisterKindDWARF
, dwarf_r0
+ i
);
979 context
.SetRegisterToRegisterPlusOffset(*reg_info
, *sp_reg
, addr
- sp
);
980 uint32_t reg_value
= ReadCoreReg(i
, &success
);
983 if (!MemAWrite(context
, addr
, reg_value
, addr_byte_size
))
985 addr
+= addr_byte_size
;
989 if (BitIsSet(registers
, 15)) {
990 std::optional
<RegisterInfo
> reg_info
=
991 GetRegisterInfo(eRegisterKindDWARF
, dwarf_pc
);
992 context
.SetRegisterToRegisterPlusOffset(*reg_info
, *sp_reg
, addr
- sp
);
993 const uint32_t pc
= ReadCoreReg(PC_REG
, &success
);
996 if (!MemAWrite(context
, addr
, pc
, addr_byte_size
))
1000 context
.type
= EmulateInstruction::eContextAdjustStackPointer
;
1001 context
.SetImmediateSigned(-sp_offset
);
1003 if (!WriteRegisterUnsigned(context
, eRegisterKindGeneric
,
1004 LLDB_REGNUM_GENERIC_SP
, sp
- sp_offset
))
1010 // Pop Multiple Registers loads multiple registers from the stack, loading from
1011 // consecutive memory locations staring at the address in SP, and updates
1012 // SP to point just above the loaded data.
1013 bool EmulateInstructionARM::EmulatePOP(const uint32_t opcode
,
1014 const ARMEncoding encoding
) {
1016 // ARM pseudo code...
1017 if (ConditionPassed())
1019 EncodingSpecificOperations(); NullCheckIfThumbEE(13);
1022 if registers
<i
> == '1' then
1023 R
[i
] = if UnalignedAllowed then MemU
[address
,4] else MemA
[address
,4]; address
= address
+ 4;
1024 if registers
<15> == '1' then
1025 if UnalignedAllowed then
1026 LoadWritePC(MemU
[address
,4]);
1028 LoadWritePC(MemA
[address
,4]);
1029 if registers
<13> == '0' then SP
= SP
+ 4*BitCount(registers
);
1030 if registers
<13> == '1' then SP
= bits(32) UNKNOWN
;
1034 bool success
= false;
1036 if (ConditionPassed(opcode
)) {
1037 const uint32_t addr_byte_size
= GetAddressByteSize();
1038 const addr_t sp
= ReadCoreReg(SP_REG
, &success
);
1041 uint32_t registers
= 0;
1042 uint32_t Rt
; // the destination register
1045 registers
= Bits32(opcode
, 7, 0);
1046 // The P bit represents PC.
1047 if (Bit32(opcode
, 8))
1048 registers
|= (1u << 15);
1049 // if BitCount(registers) < 1 then UNPREDICTABLE;
1050 if (BitCount(registers
) < 1)
1055 registers
= Bits32(opcode
, 15, 0) & ~0x2000;
1056 // if BitCount(registers) < 2 || (P == '1' && M == '1') then
1058 if (BitCount(registers
) < 2 || (Bit32(opcode
, 15) && Bit32(opcode
, 14)))
1060 // if registers<15> == '1' && InITBlock() && !LastInITBlock() then
1062 if (BitIsSet(registers
, 15) && InITBlock() && !LastInITBlock())
1066 Rt
= Bits32(opcode
, 15, 12);
1067 // if t == 13 || (t == 15 && InITBlock() && !LastInITBlock()) then
1071 if (Rt
== 15 && InITBlock() && !LastInITBlock())
1073 registers
= (1u << Rt
);
1076 registers
= Bits32(opcode
, 15, 0);
1077 // Instead of return false, let's handle the following case as well,
1078 // which amounts to popping one reg from the full descending stacks.
1079 // if BitCount(register_list) < 2 then SEE LDM / LDMIA / LDMFD;
1081 // if registers<13> == '1' && ArchVersion() >= 7 then UNPREDICTABLE;
1082 if (BitIsSet(opcode
, 13) && ArchVersion() >= ARMv7
)
1086 Rt
= Bits32(opcode
, 15, 12);
1087 // if t == 13 then UNPREDICTABLE;
1090 registers
= (1u << Rt
);
1095 addr_t sp_offset
= addr_byte_size
* BitCount(registers
);
1099 EmulateInstruction::Context context
;
1100 context
.type
= EmulateInstruction::eContextPopRegisterOffStack
;
1102 std::optional
<RegisterInfo
> sp_reg
=
1103 GetRegisterInfo(eRegisterKindDWARF
, dwarf_sp
);
1105 for (i
= 0; i
< 15; ++i
) {
1106 if (BitIsSet(registers
, i
)) {
1107 context
.SetAddress(addr
);
1108 data
= MemARead(context
, addr
, 4, 0, &success
);
1111 if (!WriteRegisterUnsigned(context
, eRegisterKindDWARF
, dwarf_r0
+ i
,
1114 addr
+= addr_byte_size
;
1118 if (BitIsSet(registers
, 15)) {
1119 context
.SetRegisterPlusOffset(*sp_reg
, addr
- sp
);
1120 data
= MemARead(context
, addr
, 4, 0, &success
);
1123 // In ARMv5T and above, this is an interworking branch.
1124 if (!LoadWritePC(context
, data
))
1126 // addr += addr_byte_size;
1129 context
.type
= EmulateInstruction::eContextAdjustStackPointer
;
1130 context
.SetImmediateSigned(sp_offset
);
1132 if (!WriteRegisterUnsigned(context
, eRegisterKindGeneric
,
1133 LLDB_REGNUM_GENERIC_SP
, sp
+ sp_offset
))
1139 // Set r7 or ip to point to saved value residing within the stack.
1140 // ADD (SP plus immediate)
1141 bool EmulateInstructionARM::EmulateADDRdSPImm(const uint32_t opcode
,
1142 const ARMEncoding encoding
) {
1144 // ARM pseudo code...
1145 if (ConditionPassed())
1147 EncodingSpecificOperations();
1148 (result
, carry
, overflow
) = AddWithCarry(SP
, imm32
, '0');
1150 ALUWritePC(result
); // setflags is always FALSE here
1154 APSR
.N
= result
<31>;
1155 APSR
.Z
= IsZeroBit(result
);
1161 bool success
= false;
1163 if (ConditionPassed(opcode
)) {
1164 const addr_t sp
= ReadCoreReg(SP_REG
, &success
);
1167 uint32_t Rd
; // the destination register
1172 imm32
= Bits32(opcode
, 7, 0) << 2; // imm32 = ZeroExtend(imm8:'00', 32)
1175 Rd
= Bits32(opcode
, 15, 12);
1176 imm32
= ARMExpandImm(opcode
); // imm32 = ARMExpandImm(imm12)
1181 addr_t sp_offset
= imm32
;
1182 addr_t addr
= sp
+ sp_offset
; // a pointer to the stack area
1184 EmulateInstruction::Context context
;
1185 if (Rd
== GetFramePointerRegisterNumber())
1186 context
.type
= eContextSetFramePointer
;
1188 context
.type
= EmulateInstruction::eContextRegisterPlusOffset
;
1189 std::optional
<RegisterInfo
> sp_reg
=
1190 GetRegisterInfo(eRegisterKindDWARF
, dwarf_sp
);
1191 context
.SetRegisterPlusOffset(*sp_reg
, sp_offset
);
1193 if (!WriteRegisterUnsigned(context
, eRegisterKindDWARF
, dwarf_r0
+ Rd
,
1200 // Set r7 or ip to the current stack pointer.
1202 bool EmulateInstructionARM::EmulateMOVRdSP(const uint32_t opcode
,
1203 const ARMEncoding encoding
) {
1205 // ARM pseudo code...
1206 if (ConditionPassed())
1208 EncodingSpecificOperations();
1211 ALUWritePC(result
); // setflags is always FALSE here
1215 APSR
.N
= result
<31>;
1216 APSR
.Z
= IsZeroBit(result
);
1222 bool success
= false;
1224 if (ConditionPassed(opcode
)) {
1225 const addr_t sp
= ReadCoreReg(SP_REG
, &success
);
1228 uint32_t Rd
; // the destination register
1240 EmulateInstruction::Context context
;
1241 if (Rd
== GetFramePointerRegisterNumber())
1242 context
.type
= EmulateInstruction::eContextSetFramePointer
;
1244 context
.type
= EmulateInstruction::eContextRegisterPlusOffset
;
1245 std::optional
<RegisterInfo
> sp_reg
=
1246 GetRegisterInfo(eRegisterKindDWARF
, dwarf_sp
);
1247 context
.SetRegisterPlusOffset(*sp_reg
, 0);
1249 if (!WriteRegisterUnsigned(context
, eRegisterKindDWARF
, dwarf_r0
+ Rd
, sp
))
1255 // Move from high register (r8-r15) to low register (r0-r7).
1257 bool EmulateInstructionARM::EmulateMOVLowHigh(const uint32_t opcode
,
1258 const ARMEncoding encoding
) {
1259 return EmulateMOVRdRm(opcode
, encoding
);
1262 // Move from register to register.
1264 bool EmulateInstructionARM::EmulateMOVRdRm(const uint32_t opcode
,
1265 const ARMEncoding encoding
) {
1267 // ARM pseudo code...
1268 if (ConditionPassed())
1270 EncodingSpecificOperations();
1273 ALUWritePC(result
); // setflags is always FALSE here
1277 APSR
.N
= result
<31>;
1278 APSR
.Z
= IsZeroBit(result
);
1284 bool success
= false;
1286 if (ConditionPassed(opcode
)) {
1287 uint32_t Rm
; // the source register
1288 uint32_t Rd
; // the destination register
1292 Rd
= Bit32(opcode
, 7) << 3 | Bits32(opcode
, 2, 0);
1293 Rm
= Bits32(opcode
, 6, 3);
1295 if (Rd
== 15 && InITBlock() && !LastInITBlock())
1299 Rd
= Bits32(opcode
, 2, 0);
1300 Rm
= Bits32(opcode
, 5, 3);
1306 Rd
= Bits32(opcode
, 11, 8);
1307 Rm
= Bits32(opcode
, 3, 0);
1308 setflags
= BitIsSet(opcode
, 20);
1309 // if setflags && (BadReg(d) || BadReg(m)) then UNPREDICTABLE;
1310 if (setflags
&& (BadReg(Rd
) || BadReg(Rm
)))
1312 // if !setflags && (d == 15 || m == 15 || (d == 13 && m == 13)) then
1314 if (!setflags
&& (Rd
== 15 || Rm
== 15 || (Rd
== 13 && Rm
== 13)))
1318 Rd
= Bits32(opcode
, 15, 12);
1319 Rm
= Bits32(opcode
, 3, 0);
1320 setflags
= BitIsSet(opcode
, 20);
1322 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related
1324 if (Rd
== 15 && setflags
)
1325 return EmulateSUBSPcLrEtc(opcode
, encoding
);
1330 uint32_t result
= ReadCoreReg(Rm
, &success
);
1334 // The context specifies that Rm is to be moved into Rd.
1335 EmulateInstruction::Context context
;
1337 context
.type
= EmulateInstruction::eContextAdjustStackPointer
;
1338 else if (Rd
== GetFramePointerRegisterNumber() && Rm
== 13)
1339 context
.type
= EmulateInstruction::eContextSetFramePointer
;
1341 context
.type
= EmulateInstruction::eContextRegisterPlusOffset
;
1342 std::optional
<RegisterInfo
> dwarf_reg
=
1343 GetRegisterInfo(eRegisterKindDWARF
, dwarf_r0
+ Rm
);
1344 context
.SetRegisterPlusOffset(*dwarf_reg
, 0);
1346 if (!WriteCoreRegOptionalFlags(context
, result
, Rd
, setflags
))
1352 // Move (immediate) writes an immediate value to the destination register. It
1353 // can optionally update the condition flags based on the value.
1355 bool EmulateInstructionARM::EmulateMOVRdImm(const uint32_t opcode
,
1356 const ARMEncoding encoding
) {
1358 // ARM pseudo code...
1359 if (ConditionPassed())
1361 EncodingSpecificOperations();
1363 if d
== 15 then
// Can only occur for ARM encoding
1364 ALUWritePC(result
); // setflags is always FALSE here
1368 APSR
.N
= result
<31>;
1369 APSR
.Z
= IsZeroBit(result
);
1375 if (ConditionPassed(opcode
)) {
1376 uint32_t Rd
; // the destination register
1377 uint32_t imm32
; // the immediate value to be written to Rd
1379 0; // the carry bit after ThumbExpandImm_C or ARMExpandImm_C.
1380 // for setflags == false, this value is a don't care initialized to
1381 // 0 to silence the static analyzer
1385 Rd
= Bits32(opcode
, 10, 8);
1386 setflags
= !InITBlock();
1387 imm32
= Bits32(opcode
, 7, 0); // imm32 = ZeroExtend(imm8, 32)
1393 Rd
= Bits32(opcode
, 11, 8);
1394 setflags
= BitIsSet(opcode
, 20);
1395 imm32
= ThumbExpandImm_C(opcode
, APSR_C
, carry
);
1402 // d = UInt(Rd); setflags = FALSE; imm32 = ZeroExtend(imm4:i:imm3:imm8,
1404 Rd
= Bits32(opcode
, 11, 8);
1406 uint32_t imm4
= Bits32(opcode
, 19, 16);
1407 uint32_t imm3
= Bits32(opcode
, 14, 12);
1408 uint32_t i
= Bit32(opcode
, 26);
1409 uint32_t imm8
= Bits32(opcode
, 7, 0);
1410 imm32
= (imm4
<< 12) | (i
<< 11) | (imm3
<< 8) | imm8
;
1412 // if BadReg(d) then UNPREDICTABLE;
1418 // d = UInt(Rd); setflags = (S == '1'); (imm32, carry) =
1419 // ARMExpandImm_C(imm12, APSR.C);
1420 Rd
= Bits32(opcode
, 15, 12);
1421 setflags
= BitIsSet(opcode
, 20);
1422 imm32
= ARMExpandImm_C(opcode
, APSR_C
, carry
);
1424 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related
1426 if ((Rd
== 15) && setflags
)
1427 return EmulateSUBSPcLrEtc(opcode
, encoding
);
1432 // d = UInt(Rd); setflags = FALSE; imm32 = ZeroExtend(imm4:imm12, 32);
1433 Rd
= Bits32(opcode
, 15, 12);
1435 uint32_t imm4
= Bits32(opcode
, 19, 16);
1436 uint32_t imm12
= Bits32(opcode
, 11, 0);
1437 imm32
= (imm4
<< 12) | imm12
;
1439 // if d == 15 then UNPREDICTABLE;
1447 uint32_t result
= imm32
;
1449 // The context specifies that an immediate is to be moved into Rd.
1450 EmulateInstruction::Context context
;
1451 context
.type
= EmulateInstruction::eContextImmediate
;
1452 context
.SetNoArgs();
1454 if (!WriteCoreRegOptionalFlags(context
, result
, Rd
, setflags
, carry
))
1460 // MUL multiplies two register values. The least significant 32 bits of the
1461 // result are written to the destination
1462 // register. These 32 bits do not depend on whether the source register values
1463 // are considered to be signed values or unsigned values.
1465 // Optionally, it can update the condition flags based on the result. In the
1466 // Thumb instruction set, this option is limited to only a few forms of the
1468 bool EmulateInstructionARM::EmulateMUL(const uint32_t opcode
,
1469 const ARMEncoding encoding
) {
1471 if ConditionPassed() then
1472 EncodingSpecificOperations();
1473 operand1
= SInt(R
[n
]); // operand1 = UInt(R[n]) produces the same final results
1474 operand2
= SInt(R
[m
]); // operand2 = UInt(R[m]) produces the same final results
1475 result
= operand1
* operand2
;
1476 R
[d
] = result
<31:0>;
1478 APSR
.N
= result
<31>;
1479 APSR
.Z
= IsZeroBit(result
);
1480 if ArchVersion() == 4 then
1481 APSR
.C
= bit UNKNOWN
;
1482 // else APSR.C unchanged
1483 // APSR.V always unchanged
1486 if (ConditionPassed(opcode
)) {
1492 // EncodingSpecificOperations();
1495 // d = UInt(Rdm); n = UInt(Rn); m = UInt(Rdm); setflags = !InITBlock();
1496 d
= Bits32(opcode
, 2, 0);
1497 n
= Bits32(opcode
, 5, 3);
1498 m
= Bits32(opcode
, 2, 0);
1499 setflags
= !InITBlock();
1501 // if ArchVersion() < 6 && d == n then UNPREDICTABLE;
1502 if ((ArchVersion() < ARMv6
) && (d
== n
))
1508 // d = UInt(Rd); n = UInt(Rn); m = UInt(Rm); setflags = FALSE;
1509 d
= Bits32(opcode
, 11, 8);
1510 n
= Bits32(opcode
, 19, 16);
1511 m
= Bits32(opcode
, 3, 0);
1514 // if BadReg(d) || BadReg(n) || BadReg(m) then UNPREDICTABLE;
1515 if (BadReg(d
) || BadReg(n
) || BadReg(m
))
1521 // d = UInt(Rd); n = UInt(Rn); m = UInt(Rm); setflags = (S == '1');
1522 d
= Bits32(opcode
, 19, 16);
1523 n
= Bits32(opcode
, 3, 0);
1524 m
= Bits32(opcode
, 11, 8);
1525 setflags
= BitIsSet(opcode
, 20);
1527 // if d == 15 || n == 15 || m == 15 then UNPREDICTABLE;
1528 if ((d
== 15) || (n
== 15) || (m
== 15))
1531 // if ArchVersion() < 6 && d == n then UNPREDICTABLE;
1532 if ((ArchVersion() < ARMv6
) && (d
== n
))
1541 bool success
= false;
1543 // operand1 = SInt(R[n]); // operand1 = UInt(R[n]) produces the same final
1546 ReadRegisterUnsigned(eRegisterKindDWARF
, dwarf_r0
+ n
, 0, &success
);
1550 // operand2 = SInt(R[m]); // operand2 = UInt(R[m]) produces the same final
1553 ReadRegisterUnsigned(eRegisterKindDWARF
, dwarf_r0
+ m
, 0, &success
);
1557 // result = operand1 * operand2;
1558 uint64_t result
= operand1
* operand2
;
1560 // R[d] = result<31:0>;
1561 std::optional
<RegisterInfo
> op1_reg
=
1562 GetRegisterInfo(eRegisterKindDWARF
, dwarf_r0
+ n
);
1563 std::optional
<RegisterInfo
> op2_reg
=
1564 GetRegisterInfo(eRegisterKindDWARF
, dwarf_r0
+ m
);
1566 EmulateInstruction::Context context
;
1567 context
.type
= eContextArithmetic
;
1568 context
.SetRegisterRegisterOperands(*op1_reg
, *op2_reg
);
1570 if (!WriteRegisterUnsigned(context
, eRegisterKindDWARF
, dwarf_r0
+ d
,
1571 (0x0000ffff & result
)))
1576 // APSR.N = result<31>;
1577 // APSR.Z = IsZeroBit(result);
1578 m_new_inst_cpsr
= m_opcode_cpsr
;
1579 SetBit32(m_new_inst_cpsr
, CPSR_N_POS
, Bit32(result
, 31));
1580 SetBit32(m_new_inst_cpsr
, CPSR_Z_POS
, result
== 0 ? 1 : 0);
1581 if (m_new_inst_cpsr
!= m_opcode_cpsr
) {
1582 if (!WriteRegisterUnsigned(context
, eRegisterKindGeneric
,
1583 LLDB_REGNUM_GENERIC_FLAGS
, m_new_inst_cpsr
))
1587 // if ArchVersion() == 4 then
1588 // APSR.C = bit UNKNOWN;
1594 // Bitwise NOT (immediate) writes the bitwise inverse of an immediate value to
1595 // the destination register. It can optionally update the condition flags based
1597 bool EmulateInstructionARM::EmulateMVNImm(const uint32_t opcode
,
1598 const ARMEncoding encoding
) {
1600 // ARM pseudo code...
1601 if (ConditionPassed())
1603 EncodingSpecificOperations();
1604 result
= NOT(imm32
);
1605 if d
== 15 then
// Can only occur for ARM encoding
1606 ALUWritePC(result
); // setflags is always FALSE here
1610 APSR
.N
= result
<31>;
1611 APSR
.Z
= IsZeroBit(result
);
1617 if (ConditionPassed(opcode
)) {
1618 uint32_t Rd
; // the destination register
1619 uint32_t imm32
; // the output after ThumbExpandImm_C or ARMExpandImm_C
1620 uint32_t carry
; // the carry bit after ThumbExpandImm_C or ARMExpandImm_C
1624 Rd
= Bits32(opcode
, 11, 8);
1625 setflags
= BitIsSet(opcode
, 20);
1626 imm32
= ThumbExpandImm_C(opcode
, APSR_C
, carry
);
1629 Rd
= Bits32(opcode
, 15, 12);
1630 setflags
= BitIsSet(opcode
, 20);
1631 imm32
= ARMExpandImm_C(opcode
, APSR_C
, carry
);
1633 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related
1635 if (Rd
== 15 && setflags
)
1636 return EmulateSUBSPcLrEtc(opcode
, encoding
);
1641 uint32_t result
= ~imm32
;
1643 // The context specifies that an immediate is to be moved into Rd.
1644 EmulateInstruction::Context context
;
1645 context
.type
= EmulateInstruction::eContextImmediate
;
1646 context
.SetNoArgs();
1648 if (!WriteCoreRegOptionalFlags(context
, result
, Rd
, setflags
, carry
))
1654 // Bitwise NOT (register) writes the bitwise inverse of a register value to the
1655 // destination register. It can optionally update the condition flags based on
1657 bool EmulateInstructionARM::EmulateMVNReg(const uint32_t opcode
,
1658 const ARMEncoding encoding
) {
1660 // ARM pseudo code...
1661 if (ConditionPassed())
1663 EncodingSpecificOperations();
1664 (shifted
, carry
) = Shift_C(R
[m
], shift_t
, shift_n
, APSR
.C
);
1665 result
= NOT(shifted
);
1666 if d
== 15 then
// Can only occur for ARM encoding
1667 ALUWritePC(result
); // setflags is always FALSE here
1671 APSR
.N
= result
<31>;
1672 APSR
.Z
= IsZeroBit(result
);
1678 if (ConditionPassed(opcode
)) {
1679 uint32_t Rm
; // the source register
1680 uint32_t Rd
; // the destination register
1681 ARM_ShifterType shift_t
;
1682 uint32_t shift_n
; // the shift applied to the value read from Rm
1684 uint32_t carry
; // the carry bit after the shift operation
1687 Rd
= Bits32(opcode
, 2, 0);
1688 Rm
= Bits32(opcode
, 5, 3);
1689 setflags
= !InITBlock();
1690 shift_t
= SRType_LSL
;
1696 Rd
= Bits32(opcode
, 11, 8);
1697 Rm
= Bits32(opcode
, 3, 0);
1698 setflags
= BitIsSet(opcode
, 20);
1699 shift_n
= DecodeImmShiftThumb(opcode
, shift_t
);
1700 // if (BadReg(d) || BadReg(m)) then UNPREDICTABLE;
1701 if (BadReg(Rd
) || BadReg(Rm
))
1705 Rd
= Bits32(opcode
, 15, 12);
1706 Rm
= Bits32(opcode
, 3, 0);
1707 setflags
= BitIsSet(opcode
, 20);
1708 shift_n
= DecodeImmShiftARM(opcode
, shift_t
);
1713 bool success
= false;
1714 uint32_t value
= ReadCoreReg(Rm
, &success
);
1719 Shift_C(value
, shift_t
, shift_n
, APSR_C
, carry
, &success
);
1722 uint32_t result
= ~shifted
;
1724 // The context specifies that an immediate is to be moved into Rd.
1725 EmulateInstruction::Context context
;
1726 context
.type
= EmulateInstruction::eContextImmediate
;
1727 context
.SetNoArgs();
1729 if (!WriteCoreRegOptionalFlags(context
, result
, Rd
, setflags
, carry
))
1735 // PC relative immediate load into register, possibly followed by ADD (SP plus
1738 bool EmulateInstructionARM::EmulateLDRRtPCRelative(const uint32_t opcode
,
1739 const ARMEncoding encoding
) {
1741 // ARM pseudo code...
1742 if (ConditionPassed())
1744 EncodingSpecificOperations(); NullCheckIfThumbEE(15);
1746 address
= if add
then (base
+ imm32
) else (base
- imm32
);
1747 data
= MemU
[address
,4];
1749 if address
<1:0> == '00' then
LoadWritePC(data
); else UNPREDICTABLE
;
1750 elsif
UnalignedSupport() || address
<1:0> = '00' then
1752 else // Can only apply before ARMv7
1753 if CurrentInstrSet() == InstrSet_ARM then
1754 R
[t
] = ROR(data
, 8*UInt(address
<1:0>));
1756 R
[t
] = bits(32) UNKNOWN
;
1760 if (ConditionPassed(opcode
)) {
1761 bool success
= false;
1762 const uint32_t pc
= ReadCoreReg(PC_REG
, &success
);
1766 // PC relative immediate load context
1767 EmulateInstruction::Context context
;
1768 context
.type
= EmulateInstruction::eContextRegisterPlusOffset
;
1769 std::optional
<RegisterInfo
> pc_reg
=
1770 GetRegisterInfo(eRegisterKindDWARF
, dwarf_pc
);
1771 context
.SetRegisterPlusOffset(*pc_reg
, 0);
1773 uint32_t Rt
; // the destination register
1774 uint32_t imm32
; // immediate offset from the PC
1775 bool add
; // +imm32 or -imm32?
1776 addr_t base
; // the base address
1777 addr_t address
; // the PC relative address
1778 uint32_t data
; // the literal data value from the PC relative load
1781 Rt
= Bits32(opcode
, 10, 8);
1782 imm32
= Bits32(opcode
, 7, 0) << 2; // imm32 = ZeroExtend(imm8:'00', 32);
1786 Rt
= Bits32(opcode
, 15, 12);
1787 imm32
= Bits32(opcode
, 11, 0) << 2; // imm32 = ZeroExtend(imm12, 32);
1788 add
= BitIsSet(opcode
, 23);
1789 if (Rt
== 15 && InITBlock() && !LastInITBlock())
1796 base
= Align(pc
, 4);
1798 address
= base
+ imm32
;
1800 address
= base
- imm32
;
1802 context
.SetRegisterPlusOffset(*pc_reg
, address
- base
);
1803 data
= MemURead(context
, address
, 4, 0, &success
);
1808 if (Bits32(address
, 1, 0) == 0) {
1809 // In ARMv5T and above, this is an interworking branch.
1810 if (!LoadWritePC(context
, data
))
1814 } else if (UnalignedSupport() || Bits32(address
, 1, 0) == 0) {
1815 if (!WriteRegisterUnsigned(context
, eRegisterKindDWARF
, dwarf_r0
+ Rt
,
1818 } else // We don't handle ARM for now.
1824 // An add operation to adjust the SP.
1825 // ADD (SP plus immediate)
1826 bool EmulateInstructionARM::EmulateADDSPImm(const uint32_t opcode
,
1827 const ARMEncoding encoding
) {
1829 // ARM pseudo code...
1830 if (ConditionPassed())
1832 EncodingSpecificOperations();
1833 (result
, carry
, overflow
) = AddWithCarry(SP
, imm32
, '0');
1834 if d
== 15 then
// Can only occur for ARM encoding
1835 ALUWritePC(result
); // setflags is always FALSE here
1839 APSR
.N
= result
<31>;
1840 APSR
.Z
= IsZeroBit(result
);
1846 bool success
= false;
1848 if (ConditionPassed(opcode
)) {
1849 const addr_t sp
= ReadCoreReg(SP_REG
, &success
);
1852 uint32_t imm32
; // the immediate operand
1857 // d = UInt(Rd); setflags = FALSE; imm32 = ZeroExtend(imm8:'00', 32);
1858 d
= Bits32(opcode
, 10, 8);
1859 imm32
= (Bits32(opcode
, 7, 0) << 2);
1864 // d = 13; setflags = FALSE; imm32 = ZeroExtend(imm7:'00', 32);
1866 imm32
= ThumbImm7Scaled(opcode
); // imm32 = ZeroExtend(imm7:'00', 32)
1871 // d = UInt(Rd); setflags = (S == "1"); imm32 =
1872 // ThumbExpandImm(i:imm3:imm8);
1873 d
= Bits32(opcode
, 11, 8);
1874 imm32
= ThumbExpandImm(opcode
);
1875 setflags
= Bit32(opcode
, 20);
1877 // if Rd == "1111" && S == "1" then SEE CMN (immediate);
1878 if (d
== 15 && setflags
== 1)
1879 return false; // CMN (immediate) not yet supported
1881 // if d == 15 && S == "0" then UNPREDICTABLE;
1882 if (d
== 15 && setflags
== 0)
1887 // if Rn == '1111' then SEE ADR;
1888 // d = UInt(Rd); setflags = FALSE; imm32 = ZeroExtend(i:imm3:imm8, 32);
1889 d
= Bits32(opcode
, 11, 8);
1891 uint32_t i
= Bit32(opcode
, 26);
1892 uint32_t imm3
= Bits32(opcode
, 14, 12);
1893 uint32_t imm8
= Bits32(opcode
, 7, 0);
1894 imm32
= (i
<< 11) | (imm3
<< 8) | imm8
;
1896 // if d == 15 then UNPREDICTABLE;
1904 // (result, carry, overflow) = AddWithCarry(R[n], imm32, '0');
1905 AddWithCarryResult res
= AddWithCarry(sp
, imm32
, 0);
1907 EmulateInstruction::Context context
;
1909 context
.type
= EmulateInstruction::eContextAdjustStackPointer
;
1911 context
.type
= EmulateInstruction::eContextRegisterPlusOffset
;
1913 std::optional
<RegisterInfo
> sp_reg
=
1914 GetRegisterInfo(eRegisterKindDWARF
, dwarf_sp
);
1915 context
.SetRegisterPlusOffset(*sp_reg
, res
.result
- sp
);
1918 if (!ALUWritePC(context
, res
.result
))
1923 // APSR.N = result<31>;
1924 // APSR.Z = IsZeroBit(result);
1926 // APSR.V = overflow;
1927 if (!WriteCoreRegOptionalFlags(context
, res
.result
, d
, setflags
,
1928 res
.carry_out
, res
.overflow
))
1935 // An add operation to adjust the SP.
1936 // ADD (SP plus register)
1937 bool EmulateInstructionARM::EmulateADDSPRm(const uint32_t opcode
,
1938 const ARMEncoding encoding
) {
1940 // ARM pseudo code...
1941 if (ConditionPassed())
1943 EncodingSpecificOperations();
1944 shifted
= Shift(R
[m
], shift_t
, shift_n
, APSR
.C
);
1945 (result
, carry
, overflow
) = AddWithCarry(SP
, shifted
, '0');
1947 ALUWritePC(result
); // setflags is always FALSE here
1951 APSR
.N
= result
<31>;
1952 APSR
.Z
= IsZeroBit(result
);
1958 bool success
= false;
1960 if (ConditionPassed(opcode
)) {
1961 const addr_t sp
= ReadCoreReg(SP_REG
, &success
);
1964 uint32_t Rm
; // the second operand
1967 Rm
= Bits32(opcode
, 6, 3);
1972 int32_t reg_value
= ReadCoreReg(Rm
, &success
);
1976 addr_t addr
= (int32_t)sp
+ reg_value
; // the adjusted stack pointer value
1978 EmulateInstruction::Context context
;
1979 context
.type
= eContextArithmetic
;
1980 std::optional
<RegisterInfo
> sp_reg
=
1981 GetRegisterInfo(eRegisterKindDWARF
, dwarf_sp
);
1982 std::optional
<RegisterInfo
> other_reg
=
1983 GetRegisterInfo(eRegisterKindDWARF
, dwarf_r0
+ Rm
);
1984 context
.SetRegisterRegisterOperands(*sp_reg
, *other_reg
);
1986 if (!WriteRegisterUnsigned(context
, eRegisterKindGeneric
,
1987 LLDB_REGNUM_GENERIC_SP
, addr
))
1993 // Branch with Link and Exchange Instruction Sets (immediate) calls a
1994 // subroutine at a PC-relative address, and changes instruction set from ARM to
1995 // Thumb, or from Thumb to ARM.
1997 bool EmulateInstructionARM::EmulateBLXImmediate(const uint32_t opcode
,
1998 const ARMEncoding encoding
) {
2000 // ARM pseudo code...
2001 if (ConditionPassed())
2003 EncodingSpecificOperations();
2004 if CurrentInstrSet() == InstrSet_ARM then
2007 LR
= PC
<31:1> : '1';
2008 if targetInstrSet
== InstrSet_ARM then
2009 targetAddress
= Align(PC
,4) + imm32
;
2011 targetAddress
= PC
+ imm32
;
2012 SelectInstrSet(targetInstrSet
);
2013 BranchWritePC(targetAddress
);
2017 bool success
= true;
2019 if (ConditionPassed(opcode
)) {
2020 EmulateInstruction::Context context
;
2021 context
.type
= EmulateInstruction::eContextRelativeBranchImmediate
;
2022 const uint32_t pc
= ReadCoreReg(PC_REG
, &success
);
2025 addr_t lr
; // next instruction address
2026 addr_t target
; // target address
2027 int32_t imm32
; // PC-relative offset
2030 lr
= pc
| 1u; // return address
2031 uint32_t S
= Bit32(opcode
, 26);
2032 uint32_t imm10
= Bits32(opcode
, 25, 16);
2033 uint32_t J1
= Bit32(opcode
, 13);
2034 uint32_t J2
= Bit32(opcode
, 11);
2035 uint32_t imm11
= Bits32(opcode
, 10, 0);
2036 uint32_t I1
= !(J1
^ S
);
2037 uint32_t I2
= !(J2
^ S
);
2039 (S
<< 24) | (I1
<< 23) | (I2
<< 22) | (imm10
<< 12) | (imm11
<< 1);
2040 imm32
= llvm::SignExtend32
<25>(imm25
);
2041 target
= pc
+ imm32
;
2042 SelectInstrSet(eModeThumb
);
2043 context
.SetISAAndImmediateSigned(eModeThumb
, 4 + imm32
);
2044 if (InITBlock() && !LastInITBlock())
2049 lr
= pc
| 1u; // return address
2050 uint32_t S
= Bit32(opcode
, 26);
2051 uint32_t imm10H
= Bits32(opcode
, 25, 16);
2052 uint32_t J1
= Bit32(opcode
, 13);
2053 uint32_t J2
= Bit32(opcode
, 11);
2054 uint32_t imm10L
= Bits32(opcode
, 10, 1);
2055 uint32_t I1
= !(J1
^ S
);
2056 uint32_t I2
= !(J2
^ S
);
2058 (S
<< 24) | (I1
<< 23) | (I2
<< 22) | (imm10H
<< 12) | (imm10L
<< 2);
2059 imm32
= llvm::SignExtend32
<25>(imm25
);
2060 target
= Align(pc
, 4) + imm32
;
2061 SelectInstrSet(eModeARM
);
2062 context
.SetISAAndImmediateSigned(eModeARM
, 4 + imm32
);
2063 if (InITBlock() && !LastInITBlock())
2068 lr
= pc
- 4; // return address
2069 imm32
= llvm::SignExtend32
<26>(Bits32(opcode
, 23, 0) << 2);
2070 target
= Align(pc
, 4) + imm32
;
2071 SelectInstrSet(eModeARM
);
2072 context
.SetISAAndImmediateSigned(eModeARM
, 8 + imm32
);
2075 lr
= pc
- 4; // return address
2076 imm32
= llvm::SignExtend32
<26>(Bits32(opcode
, 23, 0) << 2 |
2077 Bits32(opcode
, 24, 24) << 1);
2078 target
= pc
+ imm32
;
2079 SelectInstrSet(eModeThumb
);
2080 context
.SetISAAndImmediateSigned(eModeThumb
, 8 + imm32
);
2085 if (!WriteRegisterUnsigned(context
, eRegisterKindGeneric
,
2086 LLDB_REGNUM_GENERIC_RA
, lr
))
2088 if (!BranchWritePC(context
, target
))
2090 if (m_opcode_cpsr
!= m_new_inst_cpsr
)
2091 if (!WriteRegisterUnsigned(context
, eRegisterKindGeneric
,
2092 LLDB_REGNUM_GENERIC_FLAGS
, m_new_inst_cpsr
))
2098 // Branch with Link and Exchange (register) calls a subroutine at an address
2099 // and instruction set specified by a register.
2101 bool EmulateInstructionARM::EmulateBLXRm(const uint32_t opcode
,
2102 const ARMEncoding encoding
) {
2104 // ARM pseudo code...
2105 if (ConditionPassed())
2107 EncodingSpecificOperations();
2109 if CurrentInstrSet() == InstrSet_ARM then
2110 next_instr_addr
= PC
- 4;
2111 LR
= next_instr_addr
;
2113 next_instr_addr
= PC
- 2;
2114 LR
= next_instr_addr
<31:1> : '1';
2119 bool success
= false;
2121 if (ConditionPassed(opcode
)) {
2122 EmulateInstruction::Context context
;
2123 context
.type
= EmulateInstruction::eContextAbsoluteBranchRegister
;
2124 const uint32_t pc
= ReadCoreReg(PC_REG
, &success
);
2125 addr_t lr
; // next instruction address
2128 uint32_t Rm
; // the register with the target address
2131 lr
= (pc
- 2) | 1u; // return address
2132 Rm
= Bits32(opcode
, 6, 3);
2133 // if m == 15 then UNPREDICTABLE;
2136 if (InITBlock() && !LastInITBlock())
2140 lr
= pc
- 4; // return address
2141 Rm
= Bits32(opcode
, 3, 0);
2142 // if m == 15 then UNPREDICTABLE;
2149 addr_t target
= ReadCoreReg(Rm
, &success
);
2152 std::optional
<RegisterInfo
> dwarf_reg
=
2153 GetRegisterInfo(eRegisterKindDWARF
, dwarf_r0
+ Rm
);
2154 context
.SetRegister(*dwarf_reg
);
2155 if (!WriteRegisterUnsigned(context
, eRegisterKindGeneric
,
2156 LLDB_REGNUM_GENERIC_RA
, lr
))
2158 if (!BXWritePC(context
, target
))
2164 // Branch and Exchange causes a branch to an address and instruction set
2165 // specified by a register.
2166 bool EmulateInstructionARM::EmulateBXRm(const uint32_t opcode
,
2167 const ARMEncoding encoding
) {
2169 // ARM pseudo code...
2170 if (ConditionPassed())
2172 EncodingSpecificOperations();
2177 if (ConditionPassed(opcode
)) {
2178 EmulateInstruction::Context context
;
2179 context
.type
= EmulateInstruction::eContextAbsoluteBranchRegister
;
2180 uint32_t Rm
; // the register with the target address
2183 Rm
= Bits32(opcode
, 6, 3);
2184 if (InITBlock() && !LastInITBlock())
2188 Rm
= Bits32(opcode
, 3, 0);
2193 bool success
= false;
2194 addr_t target
= ReadCoreReg(Rm
, &success
);
2198 std::optional
<RegisterInfo
> dwarf_reg
=
2199 GetRegisterInfo(eRegisterKindDWARF
, dwarf_r0
+ Rm
);
2200 context
.SetRegister(*dwarf_reg
);
2201 if (!BXWritePC(context
, target
))
2207 // Branch and Exchange Jazelle attempts to change to Jazelle state. If the
2208 // attempt fails, it branches to an address and instruction set specified by a
2209 // register as though it were a BX instruction.
2211 // TODO: Emulate Jazelle architecture?
2212 // We currently assume that switching to Jazelle state fails, thus
2213 // treating BXJ as a BX operation.
2214 bool EmulateInstructionARM::EmulateBXJRm(const uint32_t opcode
,
2215 const ARMEncoding encoding
) {
2217 // ARM pseudo code...
2218 if (ConditionPassed())
2220 EncodingSpecificOperations();
2221 if JMCR
.JE
== '0' || CurrentInstrSet() == InstrSet_ThumbEE then
2224 if JazelleAcceptsExecution() then
2225 SwitchToJazelleExecution();
2227 SUBARCHITECTURE_DEFINED handler call
;
2231 if (ConditionPassed(opcode
)) {
2232 EmulateInstruction::Context context
;
2233 context
.type
= EmulateInstruction::eContextAbsoluteBranchRegister
;
2234 uint32_t Rm
; // the register with the target address
2237 Rm
= Bits32(opcode
, 19, 16);
2240 if (InITBlock() && !LastInITBlock())
2244 Rm
= Bits32(opcode
, 3, 0);
2251 bool success
= false;
2252 addr_t target
= ReadCoreReg(Rm
, &success
);
2256 std::optional
<RegisterInfo
> dwarf_reg
=
2257 GetRegisterInfo(eRegisterKindDWARF
, dwarf_r0
+ Rm
);
2258 context
.SetRegister(*dwarf_reg
);
2259 if (!BXWritePC(context
, target
))
2265 // Set r7 to point to some ip offset.
2267 bool EmulateInstructionARM::EmulateSUBR7IPImm(const uint32_t opcode
,
2268 const ARMEncoding encoding
) {
2270 // ARM pseudo code...
2271 if (ConditionPassed())
2273 EncodingSpecificOperations();
2274 (result
, carry
, overflow
) = AddWithCarry(SP
, NOT(imm32
), '1');
2275 if d
== 15 then
// Can only occur for ARM encoding
2276 ALUWritePC(result
); // setflags is always FALSE here
2280 APSR
.N
= result
<31>;
2281 APSR
.Z
= IsZeroBit(result
);
2287 if (ConditionPassed(opcode
)) {
2288 bool success
= false;
2289 const addr_t ip
= ReadCoreReg(12, &success
);
2295 imm32
= ARMExpandImm(opcode
); // imm32 = ARMExpandImm(imm12)
2300 addr_t ip_offset
= imm32
;
2301 addr_t addr
= ip
- ip_offset
; // the adjusted ip value
2303 EmulateInstruction::Context context
;
2304 context
.type
= EmulateInstruction::eContextRegisterPlusOffset
;
2305 std::optional
<RegisterInfo
> dwarf_reg
=
2306 GetRegisterInfo(eRegisterKindDWARF
, dwarf_r12
);
2307 context
.SetRegisterPlusOffset(*dwarf_reg
, -ip_offset
);
2309 if (!WriteRegisterUnsigned(context
, eRegisterKindDWARF
, dwarf_r7
, addr
))
2315 // Set ip to point to some stack offset.
2316 // SUB (SP minus immediate)
2317 bool EmulateInstructionARM::EmulateSUBIPSPImm(const uint32_t opcode
,
2318 const ARMEncoding encoding
) {
2320 // ARM pseudo code...
2321 if (ConditionPassed())
2323 EncodingSpecificOperations();
2324 (result
, carry
, overflow
) = AddWithCarry(SP
, NOT(imm32
), '1');
2325 if d
== 15 then
// Can only occur for ARM encoding
2326 ALUWritePC(result
); // setflags is always FALSE here
2330 APSR
.N
= result
<31>;
2331 APSR
.Z
= IsZeroBit(result
);
2337 if (ConditionPassed(opcode
)) {
2338 bool success
= false;
2339 const addr_t sp
= ReadCoreReg(SP_REG
, &success
);
2345 imm32
= ARMExpandImm(opcode
); // imm32 = ARMExpandImm(imm12)
2350 addr_t sp_offset
= imm32
;
2351 addr_t addr
= sp
- sp_offset
; // the adjusted stack pointer value
2353 EmulateInstruction::Context context
;
2354 context
.type
= EmulateInstruction::eContextRegisterPlusOffset
;
2355 std::optional
<RegisterInfo
> dwarf_reg
=
2356 GetRegisterInfo(eRegisterKindGeneric
, LLDB_REGNUM_GENERIC_SP
);
2357 context
.SetRegisterPlusOffset(*dwarf_reg
, -sp_offset
);
2359 if (!WriteRegisterUnsigned(context
, eRegisterKindDWARF
, dwarf_r12
, addr
))
2365 // This instruction subtracts an immediate value from the SP value, and writes
2366 // the result to the destination register.
2368 // If Rd == 13 => A sub operation to adjust the SP -- allocate space for local
2370 bool EmulateInstructionARM::EmulateSUBSPImm(const uint32_t opcode
,
2371 const ARMEncoding encoding
) {
2373 // ARM pseudo code...
2374 if (ConditionPassed())
2376 EncodingSpecificOperations();
2377 (result
, carry
, overflow
) = AddWithCarry(SP
, NOT(imm32
), '1');
2378 if d
== 15 then
// Can only occur for ARM encoding
2379 ALUWritePC(result
); // setflags is always FALSE here
2383 APSR
.N
= result
<31>;
2384 APSR
.Z
= IsZeroBit(result
);
2390 bool success
= false;
2391 if (ConditionPassed(opcode
)) {
2392 const addr_t sp
= ReadCoreReg(SP_REG
, &success
);
2403 imm32
= ThumbImm7Scaled(opcode
); // imm32 = ZeroExtend(imm7:'00', 32)
2406 Rd
= Bits32(opcode
, 11, 8);
2407 setflags
= BitIsSet(opcode
, 20);
2408 imm32
= ThumbExpandImm(opcode
); // imm32 = ThumbExpandImm(i:imm3:imm8)
2409 if (Rd
== 15 && setflags
)
2410 return EmulateCMPImm(opcode
, eEncodingT2
);
2411 if (Rd
== 15 && !setflags
)
2415 Rd
= Bits32(opcode
, 11, 8);
2417 imm32
= ThumbImm12(opcode
); // imm32 = ZeroExtend(i:imm3:imm8, 32)
2422 Rd
= Bits32(opcode
, 15, 12);
2423 setflags
= BitIsSet(opcode
, 20);
2424 imm32
= ARMExpandImm(opcode
); // imm32 = ARMExpandImm(imm12)
2426 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related
2428 if (Rd
== 15 && setflags
)
2429 return EmulateSUBSPcLrEtc(opcode
, encoding
);
2434 AddWithCarryResult res
= AddWithCarry(sp
, ~imm32
, 1);
2436 EmulateInstruction::Context context
;
2438 uint64_t imm64
= imm32
; // Need to expand it to 64 bits before attempting
2439 // to negate it, or the wrong
2440 // value gets passed down to context.SetImmediateSigned.
2441 context
.type
= EmulateInstruction::eContextAdjustStackPointer
;
2442 context
.SetImmediateSigned(-imm64
); // the stack pointer offset
2444 context
.type
= EmulateInstruction::eContextImmediate
;
2445 context
.SetNoArgs();
2448 if (!WriteCoreRegOptionalFlags(context
, res
.result
, Rd
, setflags
,
2449 res
.carry_out
, res
.overflow
))
2455 // A store operation to the stack that also updates the SP.
2456 bool EmulateInstructionARM::EmulateSTRRtSP(const uint32_t opcode
,
2457 const ARMEncoding encoding
) {
2459 // ARM pseudo code...
2460 if (ConditionPassed())
2462 EncodingSpecificOperations();
2463 offset_addr
= if add
then (R
[n
] + imm32
) else (R
[n
] - imm32
);
2464 address
= if index then offset_addr
else R
[n
];
2465 MemU
[address
,4] = if t
== 15 then
PCStoreValue() else R
[t
];
2466 if wback then R
[n
] = offset_addr
;
2470 bool success
= false;
2471 if (ConditionPassed(opcode
)) {
2472 const uint32_t addr_byte_size
= GetAddressByteSize();
2473 const addr_t sp
= ReadCoreReg(SP_REG
, &success
);
2476 uint32_t Rt
; // the source register
2479 Rn
; // This function assumes Rn is the SP, but we should verify that.
2486 Rt
= Bits32(opcode
, 15, 12);
2487 imm12
= Bits32(opcode
, 11, 0);
2488 Rn
= Bits32(opcode
, 19, 16);
2490 if (Rn
!= 13) // 13 is the SP reg on ARM. Verify that Rn == SP.
2493 index
= BitIsSet(opcode
, 24);
2494 add
= BitIsSet(opcode
, 23);
2495 wback
= (BitIsClear(opcode
, 24) || BitIsSet(opcode
, 21));
2497 if (wback
&& ((Rn
== 15) || (Rn
== Rt
)))
2505 offset_addr
= sp
+ imm12
;
2507 offset_addr
= sp
- imm12
;
2515 EmulateInstruction::Context context
;
2516 context
.type
= EmulateInstruction::eContextPushRegisterOnStack
;
2517 std::optional
<RegisterInfo
> sp_reg
=
2518 GetRegisterInfo(eRegisterKindDWARF
, dwarf_sp
);
2519 std::optional
<RegisterInfo
> dwarf_reg
=
2520 GetRegisterInfo(eRegisterKindDWARF
, dwarf_r0
+ Rt
);
2522 context
.SetRegisterToRegisterPlusOffset(*dwarf_reg
, *sp_reg
, addr
- sp
);
2524 uint32_t reg_value
= ReadCoreReg(Rt
, &success
);
2527 if (!MemUWrite(context
, addr
, reg_value
, addr_byte_size
))
2530 const uint32_t pc
= ReadCoreReg(PC_REG
, &success
);
2533 if (!MemUWrite(context
, addr
, pc
, addr_byte_size
))
2538 context
.type
= EmulateInstruction::eContextAdjustStackPointer
;
2539 context
.SetImmediateSigned(addr
- sp
);
2540 if (!WriteRegisterUnsigned(context
, eRegisterKindGeneric
,
2541 LLDB_REGNUM_GENERIC_SP
, offset_addr
))
2548 // Vector Push stores multiple extension registers to the stack. It also
2549 // updates SP to point to the start of the stored data.
2550 bool EmulateInstructionARM::EmulateVPUSH(const uint32_t opcode
,
2551 const ARMEncoding encoding
) {
2553 // ARM pseudo code...
2554 if (ConditionPassed())
2556 EncodingSpecificOperations(); CheckVFPEnabled(TRUE
); NullCheckIfThumbEE(13);
2557 address
= SP
- imm32
;
2561 MemA
[address
,4] = S
[d
+r
]; address
= address
+4;
2564 // Store as two word-aligned words in the correct order for
2565 // current endianness.
2566 MemA
[address
,4] = if BigEndian() then D
[d
+r
]<63:32> else D
[d
+r
]<31:0>;
2567 MemA
[address
+4,4] = if BigEndian() then D
[d
+r
]<31:0> else D
[d
+r
]<63:32>;
2568 address
= address
+8;
2572 bool success
= false;
2573 if (ConditionPassed(opcode
)) {
2574 const uint32_t addr_byte_size
= GetAddressByteSize();
2575 const addr_t sp
= ReadCoreReg(SP_REG
, &success
);
2579 uint32_t d
; // UInt(D:Vd) or UInt(Vd:D) starting register
2580 uint32_t imm32
; // stack offset
2581 uint32_t regs
; // number of registers
2585 single_regs
= false;
2586 d
= Bit32(opcode
, 22) << 4 | Bits32(opcode
, 15, 12);
2587 imm32
= Bits32(opcode
, 7, 0) * addr_byte_size
;
2588 // If UInt(imm8) is odd, see "FSTMX".
2589 regs
= Bits32(opcode
, 7, 0) / 2;
2590 // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE;
2591 if (regs
== 0 || regs
> 16 || (d
+ regs
) > 32)
2597 d
= Bits32(opcode
, 15, 12) << 1 | Bit32(opcode
, 22);
2598 imm32
= Bits32(opcode
, 7, 0) * addr_byte_size
;
2599 regs
= Bits32(opcode
, 7, 0);
2600 // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE;
2601 if (regs
== 0 || regs
> 16 || (d
+ regs
) > 32)
2607 uint32_t start_reg
= single_regs
? dwarf_s0
: dwarf_d0
;
2608 uint32_t reg_byte_size
= single_regs
? addr_byte_size
: addr_byte_size
* 2;
2609 addr_t sp_offset
= imm32
;
2610 addr_t addr
= sp
- sp_offset
;
2613 EmulateInstruction::Context context
;
2614 context
.type
= EmulateInstruction::eContextPushRegisterOnStack
;
2616 std::optional
<RegisterInfo
> sp_reg
=
2617 GetRegisterInfo(eRegisterKindDWARF
, dwarf_sp
);
2618 for (i
= 0; i
< regs
; ++i
) {
2619 std::optional
<RegisterInfo
> dwarf_reg
=
2620 GetRegisterInfo(eRegisterKindDWARF
, start_reg
+ d
+ i
);
2621 context
.SetRegisterToRegisterPlusOffset(*dwarf_reg
, *sp_reg
, addr
- sp
);
2622 // uint64_t to accommodate 64-bit registers.
2623 uint64_t reg_value
= ReadRegisterUnsigned(*dwarf_reg
, 0, &success
);
2626 if (!MemAWrite(context
, addr
, reg_value
, reg_byte_size
))
2628 addr
+= reg_byte_size
;
2631 context
.type
= EmulateInstruction::eContextAdjustStackPointer
;
2632 context
.SetImmediateSigned(-sp_offset
);
2634 if (!WriteRegisterUnsigned(context
, eRegisterKindGeneric
,
2635 LLDB_REGNUM_GENERIC_SP
, sp
- sp_offset
))
2641 // Vector Pop loads multiple extension registers from the stack. It also
2642 // updates SP to point just above the loaded data.
2643 bool EmulateInstructionARM::EmulateVPOP(const uint32_t opcode
,
2644 const ARMEncoding encoding
) {
2646 // ARM pseudo code...
2647 if (ConditionPassed())
2649 EncodingSpecificOperations(); CheckVFPEnabled(TRUE
); NullCheckIfThumbEE(13);
2654 S
[d
+r
] = MemA
[address
,4]; address
= address
+4;
2657 word1
= MemA
[address
,4]; word2
= MemA
[address
+4,4]; address
= address
+8;
2658 // Combine the word-aligned words in the correct order for
2659 // current endianness.
2660 D
[d
+r
] = if BigEndian() then word1
:word2
else word2
:word1
;
2664 bool success
= false;
2665 if (ConditionPassed(opcode
)) {
2666 const uint32_t addr_byte_size
= GetAddressByteSize();
2667 const addr_t sp
= ReadCoreReg(SP_REG
, &success
);
2671 uint32_t d
; // UInt(D:Vd) or UInt(Vd:D) starting register
2672 uint32_t imm32
; // stack offset
2673 uint32_t regs
; // number of registers
2677 single_regs
= false;
2678 d
= Bit32(opcode
, 22) << 4 | Bits32(opcode
, 15, 12);
2679 imm32
= Bits32(opcode
, 7, 0) * addr_byte_size
;
2680 // If UInt(imm8) is odd, see "FLDMX".
2681 regs
= Bits32(opcode
, 7, 0) / 2;
2682 // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE;
2683 if (regs
== 0 || regs
> 16 || (d
+ regs
) > 32)
2689 d
= Bits32(opcode
, 15, 12) << 1 | Bit32(opcode
, 22);
2690 imm32
= Bits32(opcode
, 7, 0) * addr_byte_size
;
2691 regs
= Bits32(opcode
, 7, 0);
2692 // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE;
2693 if (regs
== 0 || regs
> 16 || (d
+ regs
) > 32)
2699 uint32_t start_reg
= single_regs
? dwarf_s0
: dwarf_d0
;
2700 uint32_t reg_byte_size
= single_regs
? addr_byte_size
: addr_byte_size
* 2;
2701 addr_t sp_offset
= imm32
;
2704 uint64_t data
; // uint64_t to accommodate 64-bit registers.
2706 EmulateInstruction::Context context
;
2707 context
.type
= EmulateInstruction::eContextPopRegisterOffStack
;
2709 for (i
= 0; i
< regs
; ++i
) {
2710 std::optional
<RegisterInfo
> dwarf_reg
=
2711 GetRegisterInfo(eRegisterKindDWARF
, start_reg
+ d
+ i
);
2712 context
.SetAddress(addr
);
2713 data
= MemARead(context
, addr
, reg_byte_size
, 0, &success
);
2716 if (!WriteRegisterUnsigned(context
, *dwarf_reg
, data
))
2718 addr
+= reg_byte_size
;
2721 context
.type
= EmulateInstruction::eContextAdjustStackPointer
;
2722 context
.SetImmediateSigned(sp_offset
);
2724 if (!WriteRegisterUnsigned(context
, eRegisterKindGeneric
,
2725 LLDB_REGNUM_GENERIC_SP
, sp
+ sp_offset
))
2731 // SVC (previously SWI)
2732 bool EmulateInstructionARM::EmulateSVC(const uint32_t opcode
,
2733 const ARMEncoding encoding
) {
2735 // ARM pseudo code...
2736 if (ConditionPassed())
2738 EncodingSpecificOperations();
2743 bool success
= false;
2745 if (ConditionPassed(opcode
)) {
2746 const uint32_t pc
= ReadCoreReg(PC_REG
, &success
);
2747 addr_t lr
; // next instruction address
2750 uint32_t imm32
; // the immediate constant
2751 uint32_t mode
; // ARM or Thumb mode
2754 lr
= (pc
+ 2) | 1u; // return address
2755 imm32
= Bits32(opcode
, 7, 0);
2759 lr
= pc
+ 4; // return address
2760 imm32
= Bits32(opcode
, 23, 0);
2767 EmulateInstruction::Context context
;
2768 context
.type
= EmulateInstruction::eContextSupervisorCall
;
2769 context
.SetISAAndImmediate(mode
, imm32
);
2770 if (!WriteRegisterUnsigned(context
, eRegisterKindGeneric
,
2771 LLDB_REGNUM_GENERIC_RA
, lr
))
2777 // If Then makes up to four following instructions (the IT block) conditional.
2778 bool EmulateInstructionARM::EmulateIT(const uint32_t opcode
,
2779 const ARMEncoding encoding
) {
2781 // ARM pseudo code...
2782 EncodingSpecificOperations();
2783 ITSTATE
.IT
<7:0> = firstcond
:mask
;
2786 m_it_session
.InitIT(Bits32(opcode
, 7, 0));
2790 bool EmulateInstructionARM::EmulateNop(const uint32_t opcode
,
2791 const ARMEncoding encoding
) {
2792 // NOP, nothing to do...
2796 // Branch causes a branch to a target address.
2797 bool EmulateInstructionARM::EmulateB(const uint32_t opcode
,
2798 const ARMEncoding encoding
) {
2800 // ARM pseudo code...
2801 if (ConditionPassed())
2803 EncodingSpecificOperations();
2804 BranchWritePC(PC
+ imm32
);
2808 bool success
= false;
2810 if (ConditionPassed(opcode
)) {
2811 EmulateInstruction::Context context
;
2812 context
.type
= EmulateInstruction::eContextRelativeBranchImmediate
;
2813 const uint32_t pc
= ReadCoreReg(PC_REG
, &success
);
2816 addr_t target
; // target address
2817 int32_t imm32
; // PC-relative offset
2820 // The 'cond' field is handled in EmulateInstructionARM::CurrentCond().
2821 imm32
= llvm::SignExtend32
<9>(Bits32(opcode
, 7, 0) << 1);
2822 target
= pc
+ imm32
;
2823 context
.SetISAAndImmediateSigned(eModeThumb
, 4 + imm32
);
2826 imm32
= llvm::SignExtend32
<12>(Bits32(opcode
, 10, 0) << 1);
2827 target
= pc
+ imm32
;
2828 context
.SetISAAndImmediateSigned(eModeThumb
, 4 + imm32
);
2831 // The 'cond' field is handled in EmulateInstructionARM::CurrentCond().
2833 if (Bits32(opcode
, 25, 23) == 7)
2834 return false; // See Branches and miscellaneous control on page
2837 uint32_t S
= Bit32(opcode
, 26);
2838 uint32_t imm6
= Bits32(opcode
, 21, 16);
2839 uint32_t J1
= Bit32(opcode
, 13);
2840 uint32_t J2
= Bit32(opcode
, 11);
2841 uint32_t imm11
= Bits32(opcode
, 10, 0);
2843 (S
<< 20) | (J2
<< 19) | (J1
<< 18) | (imm6
<< 12) | (imm11
<< 1);
2844 imm32
= llvm::SignExtend32
<21>(imm21
);
2845 target
= pc
+ imm32
;
2846 context
.SetISAAndImmediateSigned(eModeThumb
, 4 + imm32
);
2850 uint32_t S
= Bit32(opcode
, 26);
2851 uint32_t imm10
= Bits32(opcode
, 25, 16);
2852 uint32_t J1
= Bit32(opcode
, 13);
2853 uint32_t J2
= Bit32(opcode
, 11);
2854 uint32_t imm11
= Bits32(opcode
, 10, 0);
2855 uint32_t I1
= !(J1
^ S
);
2856 uint32_t I2
= !(J2
^ S
);
2858 (S
<< 24) | (I1
<< 23) | (I2
<< 22) | (imm10
<< 12) | (imm11
<< 1);
2859 imm32
= llvm::SignExtend32
<25>(imm25
);
2860 target
= pc
+ imm32
;
2861 context
.SetISAAndImmediateSigned(eModeThumb
, 4 + imm32
);
2865 imm32
= llvm::SignExtend32
<26>(Bits32(opcode
, 23, 0) << 2);
2866 target
= pc
+ imm32
;
2867 context
.SetISAAndImmediateSigned(eModeARM
, 8 + imm32
);
2872 if (!BranchWritePC(context
, target
))
2878 // Compare and Branch on Nonzero and Compare and Branch on Zero compare the
2879 // value in a register with zero and conditionally branch forward a constant
2880 // value. They do not affect the condition flags. CBNZ, CBZ
2881 bool EmulateInstructionARM::EmulateCB(const uint32_t opcode
,
2882 const ARMEncoding encoding
) {
2884 // ARM pseudo code...
2885 EncodingSpecificOperations();
2886 if nonzero
^ IsZero(R
[n
]) then
2887 BranchWritePC(PC
+ imm32
);
2890 bool success
= false;
2892 // Read the register value from the operand register Rn.
2893 uint32_t reg_val
= ReadCoreReg(Bits32(opcode
, 2, 0), &success
);
2897 EmulateInstruction::Context context
;
2898 context
.type
= EmulateInstruction::eContextRelativeBranchImmediate
;
2899 const uint32_t pc
= ReadCoreReg(PC_REG
, &success
);
2903 addr_t target
; // target address
2904 uint32_t imm32
; // PC-relative offset to branch forward
2908 imm32
= Bit32(opcode
, 9) << 6 | Bits32(opcode
, 7, 3) << 1;
2909 nonzero
= BitIsSet(opcode
, 11);
2910 target
= pc
+ imm32
;
2911 context
.SetISAAndImmediateSigned(eModeThumb
, 4 + imm32
);
2916 if (m_ignore_conditions
|| (nonzero
^ (reg_val
== 0)))
2917 if (!BranchWritePC(context
, target
))
2923 // Table Branch Byte causes a PC-relative forward branch using a table of
2924 // single byte offsets.
2925 // A base register provides a pointer to the table, and a second register
2926 // supplies an index into the table.
2927 // The branch length is twice the value of the byte returned from the table.
2929 // Table Branch Halfword causes a PC-relative forward branch using a table of
2930 // single halfword offsets.
2931 // A base register provides a pointer to the table, and a second register
2932 // supplies an index into the table.
2933 // The branch length is twice the value of the halfword returned from the
2935 bool EmulateInstructionARM::EmulateTB(const uint32_t opcode
,
2936 const ARMEncoding encoding
) {
2938 // ARM pseudo code...
2939 EncodingSpecificOperations(); NullCheckIfThumbEE(n
);
2941 halfwords
= UInt(MemU
[R
[n
]+LSL(R
[m
],1), 2]);
2943 halfwords
= UInt(MemU
[R
[n
]+R
[m
], 1]);
2944 BranchWritePC(PC
+ 2*halfwords
);
2947 bool success
= false;
2949 if (ConditionPassed(opcode
)) {
2950 uint32_t Rn
; // the base register which contains the address of the table of
2952 uint32_t Rm
; // the index register which contains an integer pointing to a
2953 // byte/halfword in the table
2954 bool is_tbh
; // true if table branch halfword
2957 Rn
= Bits32(opcode
, 19, 16);
2958 Rm
= Bits32(opcode
, 3, 0);
2959 is_tbh
= BitIsSet(opcode
, 4);
2960 if (Rn
== 13 || BadReg(Rm
))
2962 if (InITBlock() && !LastInITBlock())
2969 // Read the address of the table from the operand register Rn. The PC can
2970 // be used, in which case the table immediately follows this instruction.
2971 uint32_t base
= ReadCoreReg(Rn
, &success
);
2976 uint32_t index
= ReadCoreReg(Rm
, &success
);
2980 // the offsetted table address
2981 addr_t addr
= base
+ (is_tbh
? index
* 2 : index
);
2983 // PC-relative offset to branch forward
2984 EmulateInstruction::Context context
;
2985 context
.type
= EmulateInstruction::eContextTableBranchReadMemory
;
2986 uint32_t offset
= MemURead(context
, addr
, is_tbh
? 2 : 1, 0, &success
) * 2;
2990 const uint32_t pc
= ReadCoreReg(PC_REG
, &success
);
2995 addr_t target
= pc
+ offset
;
2996 context
.type
= EmulateInstruction::eContextRelativeBranchImmediate
;
2997 context
.SetISAAndImmediateSigned(eModeThumb
, 4 + offset
);
2999 if (!BranchWritePC(context
, target
))
3006 // This instruction adds an immediate value to a register value, and writes the
3007 // result to the destination register. It can optionally update the condition
3008 // flags based on the result.
3009 bool EmulateInstructionARM::EmulateADDImmThumb(const uint32_t opcode
,
3010 const ARMEncoding encoding
) {
3012 if ConditionPassed() then
3013 EncodingSpecificOperations();
3014 (result
, carry
, overflow
) = AddWithCarry(R
[n
], imm32
, '0');
3017 APSR
.N
= result
<31>;
3018 APSR
.Z
= IsZeroBit(result
);
3023 bool success
= false;
3025 if (ConditionPassed(opcode
)) {
3032 // EncodingSpecificOperations();
3035 // d = UInt(Rd); n = UInt(Rn); setflags = !InITBlock(); imm32 =
3036 // ZeroExtend(imm3, 32);
3037 d
= Bits32(opcode
, 2, 0);
3038 n
= Bits32(opcode
, 5, 3);
3039 setflags
= !InITBlock();
3040 imm32
= Bits32(opcode
, 8, 6);
3045 // d = UInt(Rdn); n = UInt(Rdn); setflags = !InITBlock(); imm32 =
3046 // ZeroExtend(imm8, 32);
3047 d
= Bits32(opcode
, 10, 8);
3048 n
= Bits32(opcode
, 10, 8);
3049 setflags
= !InITBlock();
3050 imm32
= Bits32(opcode
, 7, 0);
3055 // if Rd == '1111' && S == '1' then SEE CMN (immediate);
3056 // d = UInt(Rd); n = UInt(Rn); setflags = (S == '1'); imm32 =
3057 // ThumbExpandImm(i:imm3:imm8);
3058 d
= Bits32(opcode
, 11, 8);
3059 n
= Bits32(opcode
, 19, 16);
3060 setflags
= BitIsSet(opcode
, 20);
3061 imm32
= ThumbExpandImm_C(opcode
, APSR_C
, carry_out
);
3063 // if Rn == '1101' then SEE ADD (SP plus immediate);
3065 return EmulateADDSPImm(opcode
, eEncodingT3
);
3067 // if BadReg(d) || n == 15 then UNPREDICTABLE;
3068 if (BadReg(d
) || (n
== 15))
3074 // if Rn == '1111' then SEE ADR;
3075 // d = UInt(Rd); n = UInt(Rn); setflags = FALSE; imm32 =
3076 // ZeroExtend(i:imm3:imm8, 32);
3077 d
= Bits32(opcode
, 11, 8);
3078 n
= Bits32(opcode
, 19, 16);
3080 uint32_t i
= Bit32(opcode
, 26);
3081 uint32_t imm3
= Bits32(opcode
, 14, 12);
3082 uint32_t imm8
= Bits32(opcode
, 7, 0);
3083 imm32
= (i
<< 11) | (imm3
<< 8) | imm8
;
3085 // if Rn == '1101' then SEE ADD (SP plus immediate);
3087 return EmulateADDSPImm(opcode
, eEncodingT4
);
3089 // if BadReg(d) then UNPREDICTABLE;
3101 ReadRegisterUnsigned(eRegisterKindDWARF
, dwarf_r0
+ n
, 0, &success
);
3105 //(result, carry, overflow) = AddWithCarry(R[n], imm32, '0');
3106 AddWithCarryResult res
= AddWithCarry(Rn
, imm32
, 0);
3108 std::optional
<RegisterInfo
> reg_n
=
3109 GetRegisterInfo(eRegisterKindDWARF
, dwarf_r0
+ n
);
3110 EmulateInstruction::Context context
;
3111 context
.type
= eContextArithmetic
;
3112 context
.SetRegisterPlusOffset(*reg_n
, imm32
);
3116 // APSR.N = result<31>;
3117 // APSR.Z = IsZeroBit(result);
3119 // APSR.V = overflow;
3120 if (!WriteCoreRegOptionalFlags(context
, res
.result
, d
, setflags
,
3121 res
.carry_out
, res
.overflow
))
3127 // This instruction adds an immediate value to a register value, and writes the
3128 // result to the destination register. It can optionally update the condition
3129 // flags based on the result.
3130 bool EmulateInstructionARM::EmulateADDImmARM(const uint32_t opcode
,
3131 const ARMEncoding encoding
) {
3133 // ARM pseudo code...
3134 if ConditionPassed() then
3135 EncodingSpecificOperations();
3136 (result
, carry
, overflow
) = AddWithCarry(R
[n
], imm32
, '0');
3138 ALUWritePC(result
); // setflags is always FALSE here
3142 APSR
.N
= result
<31>;
3143 APSR
.Z
= IsZeroBit(result
);
3148 bool success
= false;
3150 if (ConditionPassed(opcode
)) {
3153 imm32
; // the immediate value to be added to the value obtained from Rn
3157 Rd
= Bits32(opcode
, 15, 12);
3158 Rn
= Bits32(opcode
, 19, 16);
3159 setflags
= BitIsSet(opcode
, 20);
3160 imm32
= ARMExpandImm(opcode
); // imm32 = ARMExpandImm(imm12)
3166 // Read the first operand.
3167 uint32_t val1
= ReadCoreReg(Rn
, &success
);
3171 AddWithCarryResult res
= AddWithCarry(val1
, imm32
, 0);
3173 EmulateInstruction::Context context
;
3175 context
.type
= EmulateInstruction::eContextAdjustStackPointer
;
3176 else if (Rd
== GetFramePointerRegisterNumber())
3177 context
.type
= EmulateInstruction::eContextSetFramePointer
;
3179 context
.type
= EmulateInstruction::eContextRegisterPlusOffset
;
3181 std::optional
<RegisterInfo
> dwarf_reg
=
3182 GetRegisterInfo(eRegisterKindDWARF
, Rn
);
3183 context
.SetRegisterPlusOffset(*dwarf_reg
, imm32
);
3185 if (!WriteCoreRegOptionalFlags(context
, res
.result
, Rd
, setflags
,
3186 res
.carry_out
, res
.overflow
))
3192 // This instruction adds a register value and an optionally-shifted register
3193 // value, and writes the result to the destination register. It can optionally
3194 // update the condition flags based on the result.
3195 bool EmulateInstructionARM::EmulateADDReg(const uint32_t opcode
,
3196 const ARMEncoding encoding
) {
3198 // ARM pseudo code...
3199 if ConditionPassed() then
3200 EncodingSpecificOperations();
3201 shifted
= Shift(R
[m
], shift_t
, shift_n
, APSR
.C
);
3202 (result
, carry
, overflow
) = AddWithCarry(R
[n
], shifted
, '0');
3204 ALUWritePC(result
); // setflags is always FALSE here
3208 APSR
.N
= result
<31>;
3209 APSR
.Z
= IsZeroBit(result
);
3214 bool success
= false;
3216 if (ConditionPassed(opcode
)) {
3217 uint32_t Rd
, Rn
, Rm
;
3218 ARM_ShifterType shift_t
;
3219 uint32_t shift_n
; // the shift applied to the value read from Rm
3223 Rd
= Bits32(opcode
, 2, 0);
3224 Rn
= Bits32(opcode
, 5, 3);
3225 Rm
= Bits32(opcode
, 8, 6);
3226 setflags
= !InITBlock();
3227 shift_t
= SRType_LSL
;
3231 Rd
= Rn
= Bit32(opcode
, 7) << 3 | Bits32(opcode
, 2, 0);
3232 Rm
= Bits32(opcode
, 6, 3);
3234 shift_t
= SRType_LSL
;
3236 if (Rn
== 15 && Rm
== 15)
3238 if (Rd
== 15 && InITBlock() && !LastInITBlock())
3242 Rd
= Bits32(opcode
, 15, 12);
3243 Rn
= Bits32(opcode
, 19, 16);
3244 Rm
= Bits32(opcode
, 3, 0);
3245 setflags
= BitIsSet(opcode
, 20);
3246 shift_n
= DecodeImmShiftARM(opcode
, shift_t
);
3252 // Read the first operand.
3253 uint32_t val1
= ReadCoreReg(Rn
, &success
);
3257 // Read the second operand.
3258 uint32_t val2
= ReadCoreReg(Rm
, &success
);
3262 uint32_t shifted
= Shift(val2
, shift_t
, shift_n
, APSR_C
, &success
);
3265 AddWithCarryResult res
= AddWithCarry(val1
, shifted
, 0);
3267 EmulateInstruction::Context context
;
3268 context
.type
= eContextArithmetic
;
3269 std::optional
<RegisterInfo
> op1_reg
=
3270 GetRegisterInfo(eRegisterKindDWARF
, dwarf_r0
+ Rn
);
3271 std::optional
<RegisterInfo
> op2_reg
=
3272 GetRegisterInfo(eRegisterKindDWARF
, dwarf_r0
+ Rm
);
3273 context
.SetRegisterRegisterOperands(*op1_reg
, *op2_reg
);
3275 if (!WriteCoreRegOptionalFlags(context
, res
.result
, Rd
, setflags
,
3276 res
.carry_out
, res
.overflow
))
3282 // Compare Negative (immediate) adds a register value and an immediate value.
3283 // It updates the condition flags based on the result, and discards the result.
3284 bool EmulateInstructionARM::EmulateCMNImm(const uint32_t opcode
,
3285 const ARMEncoding encoding
) {
3287 // ARM pseudo code...
3288 if ConditionPassed() then
3289 EncodingSpecificOperations();
3290 (result
, carry
, overflow
) = AddWithCarry(R
[n
], imm32
, '0');
3291 APSR
.N
= result
<31>;
3292 APSR
.Z
= IsZeroBit(result
);
3297 bool success
= false;
3299 uint32_t Rn
; // the first operand
3300 uint32_t imm32
; // the immediate value to be compared with
3303 Rn
= Bits32(opcode
, 19, 16);
3304 imm32
= ThumbExpandImm(opcode
); // imm32 = ThumbExpandImm(i:imm3:imm8)
3309 Rn
= Bits32(opcode
, 19, 16);
3310 imm32
= ARMExpandImm(opcode
); // imm32 = ARMExpandImm(imm12)
3315 // Read the register value from the operand register Rn.
3316 uint32_t reg_val
= ReadCoreReg(Rn
, &success
);
3320 AddWithCarryResult res
= AddWithCarry(reg_val
, imm32
, 0);
3322 EmulateInstruction::Context context
;
3323 context
.type
= EmulateInstruction::eContextImmediate
;
3324 context
.SetNoArgs();
3325 return WriteFlags(context
, res
.result
, res
.carry_out
, res
.overflow
);
3328 // Compare Negative (register) adds a register value and an optionally-shifted
3329 // register value. It updates the condition flags based on the result, and
3330 // discards the result.
3331 bool EmulateInstructionARM::EmulateCMNReg(const uint32_t opcode
,
3332 const ARMEncoding encoding
) {
3334 // ARM pseudo code...
3335 if ConditionPassed() then
3336 EncodingSpecificOperations();
3337 shifted
= Shift(R
[m
], shift_t
, shift_n
, APSR
.C
);
3338 (result
, carry
, overflow
) = AddWithCarry(R
[n
], shifted
, '0');
3339 APSR
.N
= result
<31>;
3340 APSR
.Z
= IsZeroBit(result
);
3345 bool success
= false;
3347 uint32_t Rn
; // the first operand
3348 uint32_t Rm
; // the second operand
3349 ARM_ShifterType shift_t
;
3350 uint32_t shift_n
; // the shift applied to the value read from Rm
3353 Rn
= Bits32(opcode
, 2, 0);
3354 Rm
= Bits32(opcode
, 5, 3);
3355 shift_t
= SRType_LSL
;
3359 Rn
= Bits32(opcode
, 19, 16);
3360 Rm
= Bits32(opcode
, 3, 0);
3361 shift_n
= DecodeImmShiftThumb(opcode
, shift_t
);
3362 // if n == 15 || BadReg(m) then UNPREDICTABLE;
3363 if (Rn
== 15 || BadReg(Rm
))
3367 Rn
= Bits32(opcode
, 19, 16);
3368 Rm
= Bits32(opcode
, 3, 0);
3369 shift_n
= DecodeImmShiftARM(opcode
, shift_t
);
3374 // Read the register value from register Rn.
3375 uint32_t val1
= ReadCoreReg(Rn
, &success
);
3379 // Read the register value from register Rm.
3380 uint32_t val2
= ReadCoreReg(Rm
, &success
);
3384 uint32_t shifted
= Shift(val2
, shift_t
, shift_n
, APSR_C
, &success
);
3387 AddWithCarryResult res
= AddWithCarry(val1
, shifted
, 0);
3389 EmulateInstruction::Context context
;
3390 context
.type
= EmulateInstruction::eContextImmediate
;
3391 context
.SetNoArgs();
3392 return WriteFlags(context
, res
.result
, res
.carry_out
, res
.overflow
);
3395 // Compare (immediate) subtracts an immediate value from a register value. It
3396 // updates the condition flags based on the result, and discards the result.
3397 bool EmulateInstructionARM::EmulateCMPImm(const uint32_t opcode
,
3398 const ARMEncoding encoding
) {
3400 // ARM pseudo code...
3401 if ConditionPassed() then
3402 EncodingSpecificOperations();
3403 (result
, carry
, overflow
) = AddWithCarry(R
[n
], NOT(imm32
), '1');
3404 APSR
.N
= result
<31>;
3405 APSR
.Z
= IsZeroBit(result
);
3410 bool success
= false;
3412 uint32_t Rn
; // the first operand
3413 uint32_t imm32
; // the immediate value to be compared with
3416 Rn
= Bits32(opcode
, 10, 8);
3417 imm32
= Bits32(opcode
, 7, 0);
3420 Rn
= Bits32(opcode
, 19, 16);
3421 imm32
= ThumbExpandImm(opcode
); // imm32 = ThumbExpandImm(i:imm3:imm8)
3426 Rn
= Bits32(opcode
, 19, 16);
3427 imm32
= ARMExpandImm(opcode
); // imm32 = ARMExpandImm(imm12)
3432 // Read the register value from the operand register Rn.
3433 uint32_t reg_val
= ReadCoreReg(Rn
, &success
);
3437 AddWithCarryResult res
= AddWithCarry(reg_val
, ~imm32
, 1);
3439 EmulateInstruction::Context context
;
3440 context
.type
= EmulateInstruction::eContextImmediate
;
3441 context
.SetNoArgs();
3442 return WriteFlags(context
, res
.result
, res
.carry_out
, res
.overflow
);
3445 // Compare (register) subtracts an optionally-shifted register value from a
3446 // register value. It updates the condition flags based on the result, and
3447 // discards the result.
3448 bool EmulateInstructionARM::EmulateCMPReg(const uint32_t opcode
,
3449 const ARMEncoding encoding
) {
3451 // ARM pseudo code...
3452 if ConditionPassed() then
3453 EncodingSpecificOperations();
3454 shifted
= Shift(R
[m
], shift_t
, shift_n
, APSR
.C
);
3455 (result
, carry
, overflow
) = AddWithCarry(R
[n
], NOT(shifted
), '1');
3456 APSR
.N
= result
<31>;
3457 APSR
.Z
= IsZeroBit(result
);
3462 bool success
= false;
3464 uint32_t Rn
; // the first operand
3465 uint32_t Rm
; // the second operand
3466 ARM_ShifterType shift_t
;
3467 uint32_t shift_n
; // the shift applied to the value read from Rm
3470 Rn
= Bits32(opcode
, 2, 0);
3471 Rm
= Bits32(opcode
, 5, 3);
3472 shift_t
= SRType_LSL
;
3476 Rn
= Bit32(opcode
, 7) << 3 | Bits32(opcode
, 2, 0);
3477 Rm
= Bits32(opcode
, 6, 3);
3478 shift_t
= SRType_LSL
;
3480 if (Rn
< 8 && Rm
< 8)
3482 if (Rn
== 15 || Rm
== 15)
3486 Rn
= Bits32(opcode
, 19, 16);
3487 Rm
= Bits32(opcode
, 3, 0);
3488 shift_n
= DecodeImmShiftThumb(opcode
, shift_t
);
3489 if (Rn
== 15 || BadReg(Rm
))
3493 Rn
= Bits32(opcode
, 19, 16);
3494 Rm
= Bits32(opcode
, 3, 0);
3495 shift_n
= DecodeImmShiftARM(opcode
, shift_t
);
3500 // Read the register value from register Rn.
3501 uint32_t val1
= ReadCoreReg(Rn
, &success
);
3505 // Read the register value from register Rm.
3506 uint32_t val2
= ReadCoreReg(Rm
, &success
);
3510 uint32_t shifted
= Shift(val2
, shift_t
, shift_n
, APSR_C
, &success
);
3513 AddWithCarryResult res
= AddWithCarry(val1
, ~shifted
, 1);
3515 EmulateInstruction::Context context
;
3516 context
.type
= EmulateInstruction::eContextImmediate
;
3517 context
.SetNoArgs();
3518 return WriteFlags(context
, res
.result
, res
.carry_out
, res
.overflow
);
3521 // Arithmetic Shift Right (immediate) shifts a register value right by an
3522 // immediate number of bits, shifting in copies of its sign bit, and writes the
3523 // result to the destination register. It can optionally update the condition
3524 // flags based on the result.
3525 bool EmulateInstructionARM::EmulateASRImm(const uint32_t opcode
,
3526 const ARMEncoding encoding
) {
3528 // ARM pseudo code...
3529 if ConditionPassed() then
3530 EncodingSpecificOperations();
3531 (result
, carry
) = Shift_C(R
[m
], SRType_ASR
, shift_n
, APSR
.C
);
3532 if d
== 15 then
// Can only occur for ARM encoding
3533 ALUWritePC(result
); // setflags is always FALSE here
3537 APSR
.N
= result
<31>;
3538 APSR
.Z
= IsZeroBit(result
);
3543 return EmulateShiftImm(opcode
, encoding
, SRType_ASR
);
3546 // Arithmetic Shift Right (register) shifts a register value right by a
3547 // variable number of bits, shifting in copies of its sign bit, and writes the
3548 // result to the destination register. The variable number of bits is read from
3549 // the bottom byte of a register. It can optionally update the condition flags
3550 // based on the result.
3551 bool EmulateInstructionARM::EmulateASRReg(const uint32_t opcode
,
3552 const ARMEncoding encoding
) {
3554 // ARM pseudo code...
3555 if ConditionPassed() then
3556 EncodingSpecificOperations();
3557 shift_n
= UInt(R
[m
]<7:0>);
3558 (result
, carry
) = Shift_C(R
[m
], SRType_ASR
, shift_n
, APSR
.C
);
3561 APSR
.N
= result
<31>;
3562 APSR
.Z
= IsZeroBit(result
);
3567 return EmulateShiftReg(opcode
, encoding
, SRType_ASR
);
3570 // Logical Shift Left (immediate) shifts a register value left by an immediate
3571 // number of bits, shifting in zeros, and writes the result to the destination
3572 // register. It can optionally update the condition flags based on the result.
3573 bool EmulateInstructionARM::EmulateLSLImm(const uint32_t opcode
,
3574 const ARMEncoding encoding
) {
3576 // ARM pseudo code...
3577 if ConditionPassed() then
3578 EncodingSpecificOperations();
3579 (result
, carry
) = Shift_C(R
[m
], SRType_LSL
, shift_n
, APSR
.C
);
3580 if d
== 15 then
// Can only occur for ARM encoding
3581 ALUWritePC(result
); // setflags is always FALSE here
3585 APSR
.N
= result
<31>;
3586 APSR
.Z
= IsZeroBit(result
);
3591 return EmulateShiftImm(opcode
, encoding
, SRType_LSL
);
3594 // Logical Shift Left (register) shifts a register value left by a variable
3595 // number of bits, shifting in zeros, and writes the result to the destination
3596 // register. The variable number of bits is read from the bottom byte of a
3597 // register. It can optionally update the condition flags based on the result.
3598 bool EmulateInstructionARM::EmulateLSLReg(const uint32_t opcode
,
3599 const ARMEncoding encoding
) {
3601 // ARM pseudo code...
3602 if ConditionPassed() then
3603 EncodingSpecificOperations();
3604 shift_n
= UInt(R
[m
]<7:0>);
3605 (result
, carry
) = Shift_C(R
[m
], SRType_LSL
, shift_n
, APSR
.C
);
3608 APSR
.N
= result
<31>;
3609 APSR
.Z
= IsZeroBit(result
);
3614 return EmulateShiftReg(opcode
, encoding
, SRType_LSL
);
3617 // Logical Shift Right (immediate) shifts a register value right by an
3618 // immediate number of bits, shifting in zeros, and writes the result to the
3619 // destination register. It can optionally update the condition flags based on
3621 bool EmulateInstructionARM::EmulateLSRImm(const uint32_t opcode
,
3622 const ARMEncoding encoding
) {
3624 // ARM pseudo code...
3625 if ConditionPassed() then
3626 EncodingSpecificOperations();
3627 (result
, carry
) = Shift_C(R
[m
], SRType_LSR
, shift_n
, APSR
.C
);
3628 if d
== 15 then
// Can only occur for ARM encoding
3629 ALUWritePC(result
); // setflags is always FALSE here
3633 APSR
.N
= result
<31>;
3634 APSR
.Z
= IsZeroBit(result
);
3639 return EmulateShiftImm(opcode
, encoding
, SRType_LSR
);
3642 // Logical Shift Right (register) shifts a register value right by a variable
3643 // number of bits, shifting in zeros, and writes the result to the destination
3644 // register. The variable number of bits is read from the bottom byte of a
3645 // register. It can optionally update the condition flags based on the result.
3646 bool EmulateInstructionARM::EmulateLSRReg(const uint32_t opcode
,
3647 const ARMEncoding encoding
) {
3649 // ARM pseudo code...
3650 if ConditionPassed() then
3651 EncodingSpecificOperations();
3652 shift_n
= UInt(R
[m
]<7:0>);
3653 (result
, carry
) = Shift_C(R
[m
], SRType_LSR
, shift_n
, APSR
.C
);
3656 APSR
.N
= result
<31>;
3657 APSR
.Z
= IsZeroBit(result
);
3662 return EmulateShiftReg(opcode
, encoding
, SRType_LSR
);
3665 // Rotate Right (immediate) provides the value of the contents of a register
3666 // rotated by a constant value. The bits that are rotated off the right end are
3667 // inserted into the vacated bit positions on the left. It can optionally
3668 // update the condition flags based on the result.
3669 bool EmulateInstructionARM::EmulateRORImm(const uint32_t opcode
,
3670 const ARMEncoding encoding
) {
3672 // ARM pseudo code...
3673 if ConditionPassed() then
3674 EncodingSpecificOperations();
3675 (result
, carry
) = Shift_C(R
[m
], SRType_ROR
, shift_n
, APSR
.C
);
3676 if d
== 15 then
// Can only occur for ARM encoding
3677 ALUWritePC(result
); // setflags is always FALSE here
3681 APSR
.N
= result
<31>;
3682 APSR
.Z
= IsZeroBit(result
);
3687 return EmulateShiftImm(opcode
, encoding
, SRType_ROR
);
3690 // Rotate Right (register) provides the value of the contents of a register
3691 // rotated by a variable number of bits. The bits that are rotated off the
3692 // right end are inserted into the vacated bit positions on the left. The
3693 // variable number of bits is read from the bottom byte of a register. It can
3694 // optionally update the condition flags based on the result.
3695 bool EmulateInstructionARM::EmulateRORReg(const uint32_t opcode
,
3696 const ARMEncoding encoding
) {
3698 // ARM pseudo code...
3699 if ConditionPassed() then
3700 EncodingSpecificOperations();
3701 shift_n
= UInt(R
[m
]<7:0>);
3702 (result
, carry
) = Shift_C(R
[m
], SRType_ROR
, shift_n
, APSR
.C
);
3705 APSR
.N
= result
<31>;
3706 APSR
.Z
= IsZeroBit(result
);
3711 return EmulateShiftReg(opcode
, encoding
, SRType_ROR
);
3714 // Rotate Right with Extend provides the value of the contents of a register
3715 // shifted right by one place, with the carry flag shifted into bit [31].
3717 // RRX can optionally update the condition flags based on the result.
3718 // In that case, bit [0] is shifted into the carry flag.
3719 bool EmulateInstructionARM::EmulateRRX(const uint32_t opcode
,
3720 const ARMEncoding encoding
) {
3722 // ARM pseudo code...
3723 if ConditionPassed() then
3724 EncodingSpecificOperations();
3725 (result
, carry
) = Shift_C(R
[m
], SRType_RRX
, 1, APSR
.C
);
3726 if d
== 15 then
// Can only occur for ARM encoding
3727 ALUWritePC(result
); // setflags is always FALSE here
3731 APSR
.N
= result
<31>;
3732 APSR
.Z
= IsZeroBit(result
);
3737 return EmulateShiftImm(opcode
, encoding
, SRType_RRX
);
3740 bool EmulateInstructionARM::EmulateShiftImm(const uint32_t opcode
,
3741 const ARMEncoding encoding
,
3742 ARM_ShifterType shift_type
) {
3743 // assert(shift_type == SRType_ASR
3744 // || shift_type == SRType_LSL
3745 // || shift_type == SRType_LSR
3746 // || shift_type == SRType_ROR
3747 // || shift_type == SRType_RRX);
3749 bool success
= false;
3751 if (ConditionPassed(opcode
)) {
3752 uint32_t Rd
; // the destination register
3753 uint32_t Rm
; // the first operand register
3754 uint32_t imm5
; // encoding for the shift amount
3755 uint32_t carry
; // the carry bit after the shift operation
3758 // Special case handling!
3759 // A8.6.139 ROR (immediate) -- Encoding T1
3760 ARMEncoding use_encoding
= encoding
;
3761 if (shift_type
== SRType_ROR
&& use_encoding
== eEncodingT1
) {
3762 // Morph the T1 encoding from the ARM Architecture Manual into T2
3763 // encoding to have the same decoding of bit fields as the other Thumb2
3764 // shift operations.
3765 use_encoding
= eEncodingT2
;
3768 switch (use_encoding
) {
3770 Rd
= Bits32(opcode
, 2, 0);
3771 Rm
= Bits32(opcode
, 5, 3);
3772 setflags
= !InITBlock();
3773 imm5
= Bits32(opcode
, 10, 6);
3777 // There's no imm form of RRX instructions.
3778 if (shift_type
== SRType_RRX
)
3781 Rd
= Bits32(opcode
, 11, 8);
3782 Rm
= Bits32(opcode
, 3, 0);
3783 setflags
= BitIsSet(opcode
, 20);
3784 imm5
= Bits32(opcode
, 14, 12) << 2 | Bits32(opcode
, 7, 6);
3785 if (BadReg(Rd
) || BadReg(Rm
))
3789 Rd
= Bits32(opcode
, 15, 12);
3790 Rm
= Bits32(opcode
, 3, 0);
3791 setflags
= BitIsSet(opcode
, 20);
3792 imm5
= Bits32(opcode
, 11, 7);
3798 // A8.6.139 ROR (immediate)
3799 if (shift_type
== SRType_ROR
&& imm5
== 0)
3800 shift_type
= SRType_RRX
;
3802 // Get the first operand.
3803 uint32_t value
= ReadCoreReg(Rm
, &success
);
3807 // Decode the shift amount if not RRX.
3809 (shift_type
== SRType_RRX
? 1 : DecodeImmShift(shift_type
, imm5
));
3811 uint32_t result
= Shift_C(value
, shift_type
, amt
, APSR_C
, carry
, &success
);
3815 // The context specifies that an immediate is to be moved into Rd.
3816 EmulateInstruction::Context context
;
3817 context
.type
= EmulateInstruction::eContextImmediate
;
3818 context
.SetNoArgs();
3820 if (!WriteCoreRegOptionalFlags(context
, result
, Rd
, setflags
, carry
))
3826 bool EmulateInstructionARM::EmulateShiftReg(const uint32_t opcode
,
3827 const ARMEncoding encoding
,
3828 ARM_ShifterType shift_type
) {
3829 // assert(shift_type == SRType_ASR
3830 // || shift_type == SRType_LSL
3831 // || shift_type == SRType_LSR
3832 // || shift_type == SRType_ROR);
3834 bool success
= false;
3836 if (ConditionPassed(opcode
)) {
3837 uint32_t Rd
; // the destination register
3838 uint32_t Rn
; // the first operand register
3840 Rm
; // the register whose bottom byte contains the amount to shift by
3841 uint32_t carry
; // the carry bit after the shift operation
3845 Rd
= Bits32(opcode
, 2, 0);
3847 Rm
= Bits32(opcode
, 5, 3);
3848 setflags
= !InITBlock();
3851 Rd
= Bits32(opcode
, 11, 8);
3852 Rn
= Bits32(opcode
, 19, 16);
3853 Rm
= Bits32(opcode
, 3, 0);
3854 setflags
= BitIsSet(opcode
, 20);
3855 if (BadReg(Rd
) || BadReg(Rn
) || BadReg(Rm
))
3859 Rd
= Bits32(opcode
, 15, 12);
3860 Rn
= Bits32(opcode
, 3, 0);
3861 Rm
= Bits32(opcode
, 11, 8);
3862 setflags
= BitIsSet(opcode
, 20);
3863 if (Rd
== 15 || Rn
== 15 || Rm
== 15)
3870 // Get the first operand.
3871 uint32_t value
= ReadCoreReg(Rn
, &success
);
3874 // Get the Rm register content.
3875 uint32_t val
= ReadCoreReg(Rm
, &success
);
3879 // Get the shift amount.
3880 uint32_t amt
= Bits32(val
, 7, 0);
3882 uint32_t result
= Shift_C(value
, shift_type
, amt
, APSR_C
, carry
, &success
);
3886 // The context specifies that an immediate is to be moved into Rd.
3887 EmulateInstruction::Context context
;
3888 context
.type
= EmulateInstruction::eContextImmediate
;
3889 context
.SetNoArgs();
3891 if (!WriteCoreRegOptionalFlags(context
, result
, Rd
, setflags
, carry
))
3897 // LDM loads multiple registers from consecutive memory locations, using an
3898 // address from a base register. Optionally the address just above the highest
3899 // of those locations can be written back to the base register.
3900 bool EmulateInstructionARM::EmulateLDM(const uint32_t opcode
,
3901 const ARMEncoding encoding
) {
3903 // ARM pseudo code...
3904 if ConditionPassed()
3905 EncodingSpecificOperations(); NullCheckIfThumbEE (n
);
3909 if registers
<i
> == '1' then
3910 R
[i
] = MemA
[address
, 4]; address
= address
+ 4;
3911 if registers
<15> == '1' then
3912 LoadWritePC (MemA
[address
, 4]);
3914 if wback
&& registers
<n
> == '0' then R
[n
] = R
[n
] + 4 * BitCount (registers
);
3915 if wback
&& registers
<n
> == '1' then R
[n
] = bits(32) UNKNOWN
; // Only possible for encoding A1
3919 bool success
= false;
3920 if (ConditionPassed(opcode
)) {
3922 uint32_t registers
= 0;
3924 const uint32_t addr_byte_size
= GetAddressByteSize();
3927 // n = UInt(Rn); registers = '00000000':register_list; wback =
3928 // (registers<n> == '0');
3929 n
= Bits32(opcode
, 10, 8);
3930 registers
= Bits32(opcode
, 7, 0);
3931 registers
= registers
& 0x00ff; // Make sure the top 8 bits are zeros.
3932 wback
= BitIsClear(registers
, n
);
3933 // if BitCount(registers) < 1 then UNPREDICTABLE;
3934 if (BitCount(registers
) < 1)
3938 // if W == '1' && Rn == '1101' then SEE POP;
3939 // n = UInt(Rn); registers = P:M:'0':register_list; wback = (W == '1');
3940 n
= Bits32(opcode
, 19, 16);
3941 registers
= Bits32(opcode
, 15, 0);
3942 registers
= registers
& 0xdfff; // Make sure bit 13 is zero.
3943 wback
= BitIsSet(opcode
, 21);
3945 // if n == 15 || BitCount(registers) < 2 || (P == '1' && M == '1') then
3947 if ((n
== 15) || (BitCount(registers
) < 2) ||
3948 (BitIsSet(opcode
, 14) && BitIsSet(opcode
, 15)))
3951 // if registers<15> == '1' && InITBlock() && !LastInITBlock() then
3953 if (BitIsSet(registers
, 15) && InITBlock() && !LastInITBlock())
3956 // if wback && registers<n> == '1' then UNPREDICTABLE;
3957 if (wback
&& BitIsSet(registers
, n
))
3962 n
= Bits32(opcode
, 19, 16);
3963 registers
= Bits32(opcode
, 15, 0);
3964 wback
= BitIsSet(opcode
, 21);
3965 if ((n
== 15) || (BitCount(registers
) < 1))
3973 const addr_t base_address
=
3974 ReadRegisterUnsigned(eRegisterKindDWARF
, dwarf_r0
+ n
, 0, &success
);
3978 EmulateInstruction::Context context
;
3979 context
.type
= EmulateInstruction::eContextRegisterPlusOffset
;
3980 std::optional
<RegisterInfo
> dwarf_reg
=
3981 GetRegisterInfo(eRegisterKindDWARF
, dwarf_r0
+ n
);
3982 context
.SetRegisterPlusOffset(*dwarf_reg
, offset
);
3984 for (int i
= 0; i
< 14; ++i
) {
3985 if (BitIsSet(registers
, i
)) {
3986 context
.type
= EmulateInstruction::eContextRegisterPlusOffset
;
3987 context
.SetRegisterPlusOffset(*dwarf_reg
, offset
);
3988 if (wback
&& (n
== 13)) // Pop Instruction
3990 context
.type
= EmulateInstruction::eContextPopRegisterOffStack
;
3991 context
.SetAddress(base_address
+ offset
);
3994 // R[i] = MemA [address, 4]; address = address + 4;
3995 uint32_t data
= MemARead(context
, base_address
+ offset
, addr_byte_size
,
4000 if (!WriteRegisterUnsigned(context
, eRegisterKindDWARF
, dwarf_r0
+ i
,
4004 offset
+= addr_byte_size
;
4008 if (BitIsSet(registers
, 15)) {
4009 // LoadWritePC (MemA [address, 4]);
4010 context
.type
= EmulateInstruction::eContextRegisterPlusOffset
;
4011 context
.SetRegisterPlusOffset(*dwarf_reg
, offset
);
4013 MemARead(context
, base_address
+ offset
, addr_byte_size
, 0, &success
);
4016 // In ARMv5T and above, this is an interworking branch.
4017 if (!LoadWritePC(context
, data
))
4021 if (wback
&& BitIsClear(registers
, n
)) {
4022 // R[n] = R[n] + 4 * BitCount (registers)
4023 int32_t offset
= addr_byte_size
* BitCount(registers
);
4024 context
.type
= EmulateInstruction::eContextAdjustBaseRegister
;
4025 context
.SetRegisterPlusOffset(*dwarf_reg
, offset
);
4027 if (!WriteRegisterUnsigned(context
, eRegisterKindDWARF
, dwarf_r0
+ n
,
4028 base_address
+ offset
))
4031 if (wback
&& BitIsSet(registers
, n
))
4032 // R[n] bits(32) UNKNOWN;
4033 return WriteBits32Unknown(n
);
4038 // LDMDA loads multiple registers from consecutive memory locations using an
4039 // address from a base register.
4040 // The consecutive memory locations end at this address and the address just
4041 // below the lowest of those locations can optionally be written back to the
4043 bool EmulateInstructionARM::EmulateLDMDA(const uint32_t opcode
,
4044 const ARMEncoding encoding
) {
4046 // ARM pseudo code...
4047 if ConditionPassed() then
4048 EncodingSpecificOperations();
4049 address
= R
[n
] - 4*BitCount(registers
) + 4;
4052 if registers
<i
> == '1' then
4053 R
[i
] = MemA
[address
,4]; address
= address
+ 4;
4055 if registers
<15> == '1' then
4056 LoadWritePC(MemA
[address
,4]);
4058 if wback
&& registers
<n
> == '0' then R
[n
] = R
[n
] - 4*BitCount(registers
);
4059 if wback
&& registers
<n
> == '1' then R
[n
] = bits(32) UNKNOWN
;
4062 bool success
= false;
4064 if (ConditionPassed(opcode
)) {
4066 uint32_t registers
= 0;
4068 const uint32_t addr_byte_size
= GetAddressByteSize();
4070 // EncodingSpecificOperations();
4073 // n = UInt(Rn); registers = register_list; wback = (W == '1');
4074 n
= Bits32(opcode
, 19, 16);
4075 registers
= Bits32(opcode
, 15, 0);
4076 wback
= BitIsSet(opcode
, 21);
4078 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
4079 if ((n
== 15) || (BitCount(registers
) < 1))
4087 // address = R[n] - 4*BitCount(registers) + 4;
4090 addr_t Rn
= ReadCoreReg(n
, &success
);
4096 Rn
- (addr_byte_size
* BitCount(registers
)) + addr_byte_size
;
4098 EmulateInstruction::Context context
;
4099 context
.type
= EmulateInstruction::eContextRegisterPlusOffset
;
4100 std::optional
<RegisterInfo
> dwarf_reg
=
4101 GetRegisterInfo(eRegisterKindDWARF
, dwarf_r0
+ n
);
4102 context
.SetRegisterPlusOffset(*dwarf_reg
, offset
);
4105 for (int i
= 0; i
< 14; ++i
) {
4106 // if registers<i> == '1' then
4107 if (BitIsSet(registers
, i
)) {
4108 // R[i] = MemA[address,4]; address = address + 4;
4109 context
.SetRegisterPlusOffset(*dwarf_reg
, Rn
- (address
+ offset
));
4111 MemARead(context
, address
+ offset
, addr_byte_size
, 0, &success
);
4114 if (!WriteRegisterUnsigned(context
, eRegisterKindDWARF
, dwarf_r0
+ i
,
4117 offset
+= addr_byte_size
;
4121 // if registers<15> == '1' then
4122 // LoadWritePC(MemA[address,4]);
4123 if (BitIsSet(registers
, 15)) {
4124 context
.SetRegisterPlusOffset(*dwarf_reg
, offset
);
4126 MemARead(context
, address
+ offset
, addr_byte_size
, 0, &success
);
4129 // In ARMv5T and above, this is an interworking branch.
4130 if (!LoadWritePC(context
, data
))
4134 // if wback && registers<n> == '0' then R[n] = R[n] - 4*BitCount(registers);
4135 if (wback
&& BitIsClear(registers
, n
)) {
4137 offset
= (addr_byte_size
* BitCount(registers
)) * -1;
4138 context
.type
= EmulateInstruction::eContextAdjustBaseRegister
;
4139 context
.SetImmediateSigned(offset
);
4140 addr_t addr
= Rn
+ offset
;
4141 if (!WriteRegisterUnsigned(context
, eRegisterKindDWARF
, dwarf_r0
+ n
,
4146 // if wback && registers<n> == '1' then R[n] = bits(32) UNKNOWN;
4147 if (wback
&& BitIsSet(registers
, n
))
4148 return WriteBits32Unknown(n
);
4153 // LDMDB loads multiple registers from consecutive memory locations using an
4154 // address from a base register. The
4155 // consecutive memory locations end just below this address, and the address of
4156 // the lowest of those locations can be optionally written back to the base
4158 bool EmulateInstructionARM::EmulateLDMDB(const uint32_t opcode
,
4159 const ARMEncoding encoding
) {
4161 // ARM pseudo code...
4162 if ConditionPassed() then
4163 EncodingSpecificOperations(); NullCheckIfThumbEE(n
);
4164 address
= R
[n
] - 4*BitCount(registers
);
4167 if registers
<i
> == '1' then
4168 R
[i
] = MemA
[address
,4]; address
= address
+ 4;
4169 if registers
<15> == '1' then
4170 LoadWritePC(MemA
[address
,4]);
4172 if wback
&& registers
<n
> == '0' then R
[n
] = R
[n
] - 4*BitCount(registers
);
4173 if wback
&& registers
<n
> == '1' then R
[n
] = bits(32) UNKNOWN
; // Only possible for encoding A1
4176 bool success
= false;
4178 if (ConditionPassed(opcode
)) {
4180 uint32_t registers
= 0;
4182 const uint32_t addr_byte_size
= GetAddressByteSize();
4185 // n = UInt(Rn); registers = P:M:'0':register_list; wback = (W == '1');
4186 n
= Bits32(opcode
, 19, 16);
4187 registers
= Bits32(opcode
, 15, 0);
4188 registers
= registers
& 0xdfff; // Make sure bit 13 is a zero.
4189 wback
= BitIsSet(opcode
, 21);
4191 // if n == 15 || BitCount(registers) < 2 || (P == '1' && M == '1') then
4193 if ((n
== 15) || (BitCount(registers
) < 2) ||
4194 (BitIsSet(opcode
, 14) && BitIsSet(opcode
, 15)))
4197 // if registers<15> == '1' && InITBlock() && !LastInITBlock() then
4199 if (BitIsSet(registers
, 15) && InITBlock() && !LastInITBlock())
4202 // if wback && registers<n> == '1' then UNPREDICTABLE;
4203 if (wback
&& BitIsSet(registers
, n
))
4209 // n = UInt(Rn); registers = register_list; wback = (W == '1');
4210 n
= Bits32(opcode
, 19, 16);
4211 registers
= Bits32(opcode
, 15, 0);
4212 wback
= BitIsSet(opcode
, 21);
4214 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
4215 if ((n
== 15) || (BitCount(registers
) < 1))
4224 // address = R[n] - 4*BitCount(registers);
4228 ReadRegisterUnsigned(eRegisterKindDWARF
, dwarf_r0
+ n
, 0, &success
);
4233 addr_t address
= Rn
- (addr_byte_size
* BitCount(registers
));
4234 EmulateInstruction::Context context
;
4235 context
.type
= EmulateInstruction::eContextRegisterPlusOffset
;
4236 std::optional
<RegisterInfo
> dwarf_reg
=
4237 GetRegisterInfo(eRegisterKindDWARF
, dwarf_r0
+ n
);
4238 context
.SetRegisterPlusOffset(*dwarf_reg
, Rn
- address
);
4240 for (int i
= 0; i
< 14; ++i
) {
4241 if (BitIsSet(registers
, i
)) {
4242 // R[i] = MemA[address,4]; address = address + 4;
4243 context
.SetRegisterPlusOffset(*dwarf_reg
, Rn
- (address
+ offset
));
4245 MemARead(context
, address
+ offset
, addr_byte_size
, 0, &success
);
4249 if (!WriteRegisterUnsigned(context
, eRegisterKindDWARF
, dwarf_r0
+ i
,
4253 offset
+= addr_byte_size
;
4257 // if registers<15> == '1' then
4258 // LoadWritePC(MemA[address,4]);
4259 if (BitIsSet(registers
, 15)) {
4260 context
.SetRegisterPlusOffset(*dwarf_reg
, offset
);
4262 MemARead(context
, address
+ offset
, addr_byte_size
, 0, &success
);
4265 // In ARMv5T and above, this is an interworking branch.
4266 if (!LoadWritePC(context
, data
))
4270 // if wback && registers<n> == '0' then R[n] = R[n] - 4*BitCount(registers);
4271 if (wback
&& BitIsClear(registers
, n
)) {
4273 offset
= (addr_byte_size
* BitCount(registers
)) * -1;
4274 context
.type
= EmulateInstruction::eContextAdjustBaseRegister
;
4275 context
.SetImmediateSigned(offset
);
4276 addr_t addr
= Rn
+ offset
;
4277 if (!WriteRegisterUnsigned(context
, eRegisterKindDWARF
, dwarf_r0
+ n
,
4282 // if wback && registers<n> == '1' then R[n] = bits(32) UNKNOWN; // Only
4283 // possible for encoding A1
4284 if (wback
&& BitIsSet(registers
, n
))
4285 return WriteBits32Unknown(n
);
4290 // LDMIB loads multiple registers from consecutive memory locations using an
4291 // address from a base register. The
4292 // consecutive memory locations start just above this address, and thea ddress
4293 // of the last of those locations can optinoally be written back to the base
4295 bool EmulateInstructionARM::EmulateLDMIB(const uint32_t opcode
,
4296 const ARMEncoding encoding
) {
4298 if ConditionPassed() then
4299 EncodingSpecificOperations();
4303 if registers
<i
> == '1' then
4304 R
[i
] = MemA
[address
,4]; address
= address
+ 4;
4305 if registers
<15> == '1' then
4306 LoadWritePC(MemA
[address
,4]);
4308 if wback
&& registers
<n
> == '0' then R
[n
] = R
[n
] + 4*BitCount(registers
);
4309 if wback
&& registers
<n
> == '1' then R
[n
] = bits(32) UNKNOWN
;
4312 bool success
= false;
4314 if (ConditionPassed(opcode
)) {
4316 uint32_t registers
= 0;
4318 const uint32_t addr_byte_size
= GetAddressByteSize();
4321 // n = UInt(Rn); registers = register_list; wback = (W == '1');
4322 n
= Bits32(opcode
, 19, 16);
4323 registers
= Bits32(opcode
, 15, 0);
4324 wback
= BitIsSet(opcode
, 21);
4326 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
4327 if ((n
== 15) || (BitCount(registers
) < 1))
4334 // address = R[n] + 4;
4338 ReadRegisterUnsigned(eRegisterKindDWARF
, dwarf_r0
+ n
, 0, &success
);
4343 addr_t address
= Rn
+ addr_byte_size
;
4345 EmulateInstruction::Context context
;
4346 context
.type
= EmulateInstruction::eContextRegisterPlusOffset
;
4347 std::optional
<RegisterInfo
> dwarf_reg
=
4348 GetRegisterInfo(eRegisterKindDWARF
, dwarf_r0
+ n
);
4349 context
.SetRegisterPlusOffset(*dwarf_reg
, offset
);
4351 for (int i
= 0; i
< 14; ++i
) {
4352 if (BitIsSet(registers
, i
)) {
4353 // R[i] = MemA[address,4]; address = address + 4;
4355 context
.SetRegisterPlusOffset(*dwarf_reg
, offset
+ addr_byte_size
);
4357 MemARead(context
, address
+ offset
, addr_byte_size
, 0, &success
);
4361 if (!WriteRegisterUnsigned(context
, eRegisterKindDWARF
, dwarf_r0
+ i
,
4365 offset
+= addr_byte_size
;
4369 // if registers<15> == '1' then
4370 // LoadWritePC(MemA[address,4]);
4371 if (BitIsSet(registers
, 15)) {
4372 context
.SetRegisterPlusOffset(*dwarf_reg
, offset
);
4374 MemARead(context
, address
+ offset
, addr_byte_size
, 0, &success
);
4377 // In ARMv5T and above, this is an interworking branch.
4378 if (!LoadWritePC(context
, data
))
4382 // if wback && registers<n> == '0' then R[n] = R[n] + 4*BitCount(registers);
4383 if (wback
&& BitIsClear(registers
, n
)) {
4385 offset
= addr_byte_size
* BitCount(registers
);
4386 context
.type
= EmulateInstruction::eContextAdjustBaseRegister
;
4387 context
.SetImmediateSigned(offset
);
4388 addr_t addr
= Rn
+ offset
;
4389 if (!WriteRegisterUnsigned(context
, eRegisterKindDWARF
, dwarf_r0
+ n
,
4394 // if wback && registers<n> == '1' then R[n] = bits(32) UNKNOWN; // Only
4395 // possible for encoding A1
4396 if (wback
&& BitIsSet(registers
, n
))
4397 return WriteBits32Unknown(n
);
4402 // Load Register (immediate) calculates an address from a base register value
4403 // and an immediate offset, loads a word from memory, and writes to a register.
4404 // LDR (immediate, Thumb)
4405 bool EmulateInstructionARM::EmulateLDRRtRnImm(const uint32_t opcode
,
4406 const ARMEncoding encoding
) {
4408 // ARM pseudo code...
4409 if (ConditionPassed())
4411 EncodingSpecificOperations(); NullCheckIfThumbEE(15);
4412 offset_addr
= if add
then (R
[n
] + imm32
) else (R
[n
] - imm32
);
4413 address
= if index then offset_addr
else R
[n
];
4414 data
= MemU
[address
,4];
4415 if wback then R
[n
] = offset_addr
;
4417 if address
<1:0> == '00' then
LoadWritePC(data
); else UNPREDICTABLE
;
4418 elsif
UnalignedSupport() || address
<1:0> = '00' then
4420 else R
[t
] = bits(32) UNKNOWN
; // Can only apply before ARMv7
4424 bool success
= false;
4426 if (ConditionPassed(opcode
)) {
4427 uint32_t Rt
; // the destination register
4428 uint32_t Rn
; // the base register
4429 uint32_t imm32
; // the immediate offset used to form the address
4430 addr_t offset_addr
; // the offset address
4431 addr_t address
; // the calculated address
4432 uint32_t data
; // the literal data value from memory load
4433 bool add
, index
, wback
;
4436 Rt
= Bits32(opcode
, 2, 0);
4437 Rn
= Bits32(opcode
, 5, 3);
4438 imm32
= Bits32(opcode
, 10, 6) << 2; // imm32 = ZeroExtend(imm5:'00', 32);
4439 // index = TRUE; add = TRUE; wback = FALSE
4447 // t = UInt(Rt); n = 13; imm32 = ZeroExtend(imm8:'00', 32);
4448 Rt
= Bits32(opcode
, 10, 8);
4450 imm32
= Bits32(opcode
, 7, 0) << 2;
4452 // index = TRUE; add = TRUE; wback = FALSE;
4460 // if Rn == '1111' then SEE LDR (literal);
4461 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
4462 Rt
= Bits32(opcode
, 15, 12);
4463 Rn
= Bits32(opcode
, 19, 16);
4464 imm32
= Bits32(opcode
, 11, 0);
4466 // index = TRUE; add = TRUE; wback = FALSE;
4471 // if t == 15 && InITBlock() && !LastInITBlock() then UNPREDICTABLE;
4472 if ((Rt
== 15) && InITBlock() && !LastInITBlock())
4478 // if Rn == '1111' then SEE LDR (literal);
4479 // if P == '1' && U == '1' && W == '0' then SEE LDRT;
4480 // if Rn == '1101' && P == '0' && U == '1' && W == '1' && imm8 ==
4481 // '00000100' then SEE POP;
4482 // if P == '0' && W == '0' then UNDEFINED;
4483 if (BitIsClear(opcode
, 10) && BitIsClear(opcode
, 8))
4486 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32);
4487 Rt
= Bits32(opcode
, 15, 12);
4488 Rn
= Bits32(opcode
, 19, 16);
4489 imm32
= Bits32(opcode
, 7, 0);
4491 // index = (P == '1'); add = (U == '1'); wback = (W == '1');
4492 index
= BitIsSet(opcode
, 10);
4493 add
= BitIsSet(opcode
, 9);
4494 wback
= BitIsSet(opcode
, 8);
4496 // if (wback && n == t) || (t == 15 && InITBlock() && !LastInITBlock())
4497 // then UNPREDICTABLE;
4498 if ((wback
&& (Rn
== Rt
)) ||
4499 ((Rt
== 15) && InITBlock() && !LastInITBlock()))
4507 uint32_t base
= ReadCoreReg(Rn
, &success
);
4511 offset_addr
= base
+ imm32
;
4513 offset_addr
= base
- imm32
;
4515 address
= (index
? offset_addr
: base
);
4517 std::optional
<RegisterInfo
> base_reg
=
4518 GetRegisterInfo(eRegisterKindDWARF
, dwarf_r0
+ Rn
);
4520 EmulateInstruction::Context ctx
;
4522 ctx
.type
= eContextAdjustStackPointer
;
4523 ctx
.SetImmediateSigned((int32_t)(offset_addr
- base
));
4524 } else if (Rn
== GetFramePointerRegisterNumber()) {
4525 ctx
.type
= eContextSetFramePointer
;
4526 ctx
.SetRegisterPlusOffset(*base_reg
, (int32_t)(offset_addr
- base
));
4528 ctx
.type
= EmulateInstruction::eContextAdjustBaseRegister
;
4529 ctx
.SetRegisterPlusOffset(*base_reg
, (int32_t)(offset_addr
- base
));
4532 if (!WriteRegisterUnsigned(ctx
, eRegisterKindDWARF
, dwarf_r0
+ Rn
,
4537 // Prepare to write to the Rt register.
4538 EmulateInstruction::Context context
;
4539 context
.type
= EmulateInstruction::eContextRegisterLoad
;
4540 context
.SetRegisterPlusOffset(*base_reg
, (int32_t)(offset_addr
- base
));
4542 // Read memory from the address.
4543 data
= MemURead(context
, address
, 4, 0, &success
);
4548 if (Bits32(address
, 1, 0) == 0) {
4549 if (!LoadWritePC(context
, data
))
4553 } else if (UnalignedSupport() || Bits32(address
, 1, 0) == 0) {
4554 if (!WriteRegisterUnsigned(context
, eRegisterKindDWARF
, dwarf_r0
+ Rt
,
4558 WriteBits32Unknown(Rt
);
4563 // STM (Store Multiple Increment After) stores multiple registers to consecutive
4564 // memory locations using an address
4565 // from a base register. The consecutive memory locations start at this
4566 // address, and the address just above the last of those locations can
4567 // optionally be written back to the base register.
4568 bool EmulateInstructionARM::EmulateSTM(const uint32_t opcode
,
4569 const ARMEncoding encoding
) {
4571 if ConditionPassed() then
4572 EncodingSpecificOperations(); NullCheckIfThumbEE(n
);
4576 if registers
<i
> == '1' then
4577 if i
== n
&& wback
&& i
!= LowestSetBit(registers
) then
4578 MemA
[address
,4] = bits(32) UNKNOWN
; // Only possible for encodings T1 and A1
4580 MemA
[address
,4] = R
[i
];
4581 address
= address
+ 4;
4583 if registers
<15> == '1' then
// Only possible for encoding A1
4584 MemA
[address
,4] = PCStoreValue();
4585 if wback then R
[n
] = R
[n
] + 4*BitCount(registers
);
4588 bool success
= false;
4590 if (ConditionPassed(opcode
)) {
4592 uint32_t registers
= 0;
4594 const uint32_t addr_byte_size
= GetAddressByteSize();
4596 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
4599 // n = UInt(Rn); registers = '00000000':register_list; wback = TRUE;
4600 n
= Bits32(opcode
, 10, 8);
4601 registers
= Bits32(opcode
, 7, 0);
4602 registers
= registers
& 0x00ff; // Make sure the top 8 bits are zeros.
4605 // if BitCount(registers) < 1 then UNPREDICTABLE;
4606 if (BitCount(registers
) < 1)
4612 // n = UInt(Rn); registers = '0':M:'0':register_list; wback = (W == '1');
4613 n
= Bits32(opcode
, 19, 16);
4614 registers
= Bits32(opcode
, 15, 0);
4615 registers
= registers
& 0x5fff; // Make sure bits 15 & 13 are zeros.
4616 wback
= BitIsSet(opcode
, 21);
4618 // if n == 15 || BitCount(registers) < 2 then UNPREDICTABLE;
4619 if ((n
== 15) || (BitCount(registers
) < 2))
4622 // if wback && registers<n> == '1' then UNPREDICTABLE;
4623 if (wback
&& BitIsSet(registers
, n
))
4629 // n = UInt(Rn); registers = register_list; wback = (W == '1');
4630 n
= Bits32(opcode
, 19, 16);
4631 registers
= Bits32(opcode
, 15, 0);
4632 wback
= BitIsSet(opcode
, 21);
4634 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
4635 if ((n
== 15) || (BitCount(registers
) < 1))
4646 const addr_t address
=
4647 ReadRegisterUnsigned(eRegisterKindDWARF
, dwarf_r0
+ n
, 0, &success
);
4651 EmulateInstruction::Context context
;
4652 context
.type
= EmulateInstruction::eContextRegisterStore
;
4653 std::optional
<RegisterInfo
> base_reg
=
4654 GetRegisterInfo(eRegisterKindDWARF
, dwarf_r0
+ n
);
4657 uint32_t lowest_set_bit
= 14;
4658 for (uint32_t i
= 0; i
< 14; ++i
) {
4659 // if registers<i> == '1' then
4660 if (BitIsSet(registers
, i
)) {
4661 if (i
< lowest_set_bit
)
4663 // if i == n && wback && i != LowestSetBit(registers) then
4664 if ((i
== n
) && wback
&& (i
!= lowest_set_bit
))
4665 // MemA[address,4] = bits(32) UNKNOWN; // Only possible for encodings
4667 WriteBits32UnknownToMemory(address
+ offset
);
4669 // MemA[address,4] = R[i];
4670 uint32_t data
= ReadRegisterUnsigned(eRegisterKindDWARF
, dwarf_r0
+ i
,
4675 std::optional
<RegisterInfo
> data_reg
=
4676 GetRegisterInfo(eRegisterKindDWARF
, dwarf_r0
+ i
);
4677 context
.SetRegisterToRegisterPlusOffset(*data_reg
, *base_reg
, offset
);
4678 if (!MemAWrite(context
, address
+ offset
, data
, addr_byte_size
))
4682 // address = address + 4;
4683 offset
+= addr_byte_size
;
4687 // if registers<15> == '1' then // Only possible for encoding A1
4688 // MemA[address,4] = PCStoreValue();
4689 if (BitIsSet(registers
, 15)) {
4690 std::optional
<RegisterInfo
> pc_reg
=
4691 GetRegisterInfo(eRegisterKindDWARF
, dwarf_pc
);
4692 context
.SetRegisterPlusOffset(*pc_reg
, 8);
4693 const uint32_t pc
= ReadCoreReg(PC_REG
, &success
);
4697 if (!MemAWrite(context
, address
+ offset
, pc
, addr_byte_size
))
4701 // if wback then R[n] = R[n] + 4*BitCount(registers);
4703 offset
= addr_byte_size
* BitCount(registers
);
4704 context
.type
= EmulateInstruction::eContextAdjustBaseRegister
;
4705 context
.SetImmediateSigned(offset
);
4706 addr_t data
= address
+ offset
;
4707 if (!WriteRegisterUnsigned(context
, eRegisterKindDWARF
, dwarf_r0
+ n
,
4715 // STMDA (Store Multiple Decrement After) stores multiple registers to
4716 // consecutive memory locations using an address from a base register. The
4717 // consecutive memory locations end at this address, and the address just below
4718 // the lowest of those locations can optionally be written back to the base
4720 bool EmulateInstructionARM::EmulateSTMDA(const uint32_t opcode
,
4721 const ARMEncoding encoding
) {
4723 if ConditionPassed() then
4724 EncodingSpecificOperations();
4725 address
= R
[n
] - 4*BitCount(registers
) + 4;
4728 if registers
<i
> == '1' then
4729 if i
== n
&& wback
&& i
!= LowestSetBit(registers
) then
4730 MemA
[address
,4] = bits(32) UNKNOWN
;
4732 MemA
[address
,4] = R
[i
];
4733 address
= address
+ 4;
4735 if registers
<15> == '1' then
4736 MemA
[address
,4] = PCStoreValue();
4738 if wback then R
[n
] = R
[n
] - 4*BitCount(registers
);
4741 bool success
= false;
4743 if (ConditionPassed(opcode
)) {
4745 uint32_t registers
= 0;
4747 const uint32_t addr_byte_size
= GetAddressByteSize();
4749 // EncodingSpecificOperations();
4752 // n = UInt(Rn); registers = register_list; wback = (W == '1');
4753 n
= Bits32(opcode
, 19, 16);
4754 registers
= Bits32(opcode
, 15, 0);
4755 wback
= BitIsSet(opcode
, 21);
4757 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
4758 if ((n
== 15) || (BitCount(registers
) < 1))
4765 // address = R[n] - 4*BitCount(registers) + 4;
4767 addr_t Rn
= ReadCoreReg(n
, &success
);
4771 addr_t address
= Rn
- (addr_byte_size
* BitCount(registers
)) + 4;
4773 EmulateInstruction::Context context
;
4774 context
.type
= EmulateInstruction::eContextRegisterStore
;
4775 std::optional
<RegisterInfo
> base_reg
=
4776 GetRegisterInfo(eRegisterKindDWARF
, dwarf_r0
+ n
);
4779 uint32_t lowest_bit_set
= 14;
4780 for (uint32_t i
= 0; i
< 14; ++i
) {
4781 // if registers<i> == '1' then
4782 if (BitIsSet(registers
, i
)) {
4783 if (i
< lowest_bit_set
)
4785 // if i == n && wback && i != LowestSetBit(registers) then
4786 if ((i
== n
) && wback
&& (i
!= lowest_bit_set
))
4787 // MemA[address,4] = bits(32) UNKNOWN;
4788 WriteBits32UnknownToMemory(address
+ offset
);
4790 // MemA[address,4] = R[i];
4791 uint32_t data
= ReadRegisterUnsigned(eRegisterKindDWARF
, dwarf_r0
+ i
,
4796 std::optional
<RegisterInfo
> data_reg
=
4797 GetRegisterInfo(eRegisterKindDWARF
, dwarf_r0
+ i
);
4798 context
.SetRegisterToRegisterPlusOffset(*data_reg
, *base_reg
,
4799 Rn
- (address
+ offset
));
4800 if (!MemAWrite(context
, address
+ offset
, data
, addr_byte_size
))
4804 // address = address + 4;
4805 offset
+= addr_byte_size
;
4809 // if registers<15> == '1' then
4810 // MemA[address,4] = PCStoreValue();
4811 if (BitIsSet(registers
, 15)) {
4812 std::optional
<RegisterInfo
> pc_reg
=
4813 GetRegisterInfo(eRegisterKindDWARF
, dwarf_pc
);
4814 context
.SetRegisterPlusOffset(*pc_reg
, 8);
4815 const uint32_t pc
= ReadCoreReg(PC_REG
, &success
);
4819 if (!MemAWrite(context
, address
+ offset
, pc
, addr_byte_size
))
4823 // if wback then R[n] = R[n] - 4*BitCount(registers);
4825 offset
= (addr_byte_size
* BitCount(registers
)) * -1;
4826 context
.type
= EmulateInstruction::eContextAdjustBaseRegister
;
4827 context
.SetImmediateSigned(offset
);
4828 addr_t data
= Rn
+ offset
;
4829 if (!WriteRegisterUnsigned(context
, eRegisterKindDWARF
, dwarf_r0
+ n
,
4837 // STMDB (Store Multiple Decrement Before) stores multiple registers to
4838 // consecutive memory locations using an address from a base register. The
4839 // consecutive memory locations end just below this address, and the address of
4840 // the first of those locations can optionally be written back to the base
4842 bool EmulateInstructionARM::EmulateSTMDB(const uint32_t opcode
,
4843 const ARMEncoding encoding
) {
4845 if ConditionPassed() then
4846 EncodingSpecificOperations(); NullCheckIfThumbEE(n
);
4847 address
= R
[n
] - 4*BitCount(registers
);
4850 if registers
<i
> == '1' then
4851 if i
== n
&& wback
&& i
!= LowestSetBit(registers
) then
4852 MemA
[address
,4] = bits(32) UNKNOWN
; // Only possible for encoding A1
4854 MemA
[address
,4] = R
[i
];
4855 address
= address
+ 4;
4857 if registers
<15> == '1' then
// Only possible for encoding A1
4858 MemA
[address
,4] = PCStoreValue();
4860 if wback then R
[n
] = R
[n
] - 4*BitCount(registers
);
4863 bool success
= false;
4865 if (ConditionPassed(opcode
)) {
4867 uint32_t registers
= 0;
4869 const uint32_t addr_byte_size
= GetAddressByteSize();
4871 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
4874 // if W == '1' && Rn == '1101' then SEE PUSH;
4875 if ((BitIsSet(opcode
, 21)) && (Bits32(opcode
, 19, 16) == 13)) {
4878 // n = UInt(Rn); registers = '0':M:'0':register_list; wback = (W == '1');
4879 n
= Bits32(opcode
, 19, 16);
4880 registers
= Bits32(opcode
, 15, 0);
4881 registers
= registers
& 0x5fff; // Make sure bits 15 & 13 are zeros.
4882 wback
= BitIsSet(opcode
, 21);
4883 // if n == 15 || BitCount(registers) < 2 then UNPREDICTABLE;
4884 if ((n
== 15) || BitCount(registers
) < 2)
4886 // if wback && registers<n> == '1' then UNPREDICTABLE;
4887 if (wback
&& BitIsSet(registers
, n
))
4892 // if W == '1' && Rn == '1101' && BitCount(register_list) >= 2 then SEE
4894 if (BitIsSet(opcode
, 21) && (Bits32(opcode
, 19, 16) == 13) &&
4895 BitCount(Bits32(opcode
, 15, 0)) >= 2) {
4898 // n = UInt(Rn); registers = register_list; wback = (W == '1');
4899 n
= Bits32(opcode
, 19, 16);
4900 registers
= Bits32(opcode
, 15, 0);
4901 wback
= BitIsSet(opcode
, 21);
4902 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
4903 if ((n
== 15) || BitCount(registers
) < 1)
4911 // address = R[n] - 4*BitCount(registers);
4915 ReadRegisterUnsigned(eRegisterKindDWARF
, dwarf_r0
+ n
, 0, &success
);
4919 addr_t address
= Rn
- (addr_byte_size
* BitCount(registers
));
4921 EmulateInstruction::Context context
;
4922 context
.type
= EmulateInstruction::eContextRegisterStore
;
4923 std::optional
<RegisterInfo
> base_reg
=
4924 GetRegisterInfo(eRegisterKindDWARF
, dwarf_r0
+ n
);
4927 uint32_t lowest_set_bit
= 14;
4928 for (uint32_t i
= 0; i
< 14; ++i
) {
4929 // if registers<i> == '1' then
4930 if (BitIsSet(registers
, i
)) {
4931 if (i
< lowest_set_bit
)
4933 // if i == n && wback && i != LowestSetBit(registers) then
4934 if ((i
== n
) && wback
&& (i
!= lowest_set_bit
))
4935 // MemA[address,4] = bits(32) UNKNOWN; // Only possible for encoding
4937 WriteBits32UnknownToMemory(address
+ offset
);
4939 // MemA[address,4] = R[i];
4940 uint32_t data
= ReadRegisterUnsigned(eRegisterKindDWARF
, dwarf_r0
+ i
,
4945 std::optional
<RegisterInfo
> data_reg
=
4946 GetRegisterInfo(eRegisterKindDWARF
, dwarf_r0
+ i
);
4947 context
.SetRegisterToRegisterPlusOffset(*data_reg
, *base_reg
,
4948 Rn
- (address
+ offset
));
4949 if (!MemAWrite(context
, address
+ offset
, data
, addr_byte_size
))
4953 // address = address + 4;
4954 offset
+= addr_byte_size
;
4958 // if registers<15> == '1' then // Only possible for encoding A1
4959 // MemA[address,4] = PCStoreValue();
4960 if (BitIsSet(registers
, 15)) {
4961 std::optional
<RegisterInfo
> pc_reg
=
4962 GetRegisterInfo(eRegisterKindDWARF
, dwarf_pc
);
4963 context
.SetRegisterPlusOffset(*pc_reg
, 8);
4964 const uint32_t pc
= ReadCoreReg(PC_REG
, &success
);
4968 if (!MemAWrite(context
, address
+ offset
, pc
, addr_byte_size
))
4972 // if wback then R[n] = R[n] - 4*BitCount(registers);
4974 offset
= (addr_byte_size
* BitCount(registers
)) * -1;
4975 context
.type
= EmulateInstruction::eContextAdjustBaseRegister
;
4976 context
.SetImmediateSigned(offset
);
4977 addr_t data
= Rn
+ offset
;
4978 if (!WriteRegisterUnsigned(context
, eRegisterKindDWARF
, dwarf_r0
+ n
,
4986 // STMIB (Store Multiple Increment Before) stores multiple registers to
4987 // consecutive memory locations using an address from a base register. The
4988 // consecutive memory locations start just above this address, and the address
4989 // of the last of those locations can optionally be written back to the base
4991 bool EmulateInstructionARM::EmulateSTMIB(const uint32_t opcode
,
4992 const ARMEncoding encoding
) {
4994 if ConditionPassed() then
4995 EncodingSpecificOperations();
4999 if registers
<i
> == '1' then
5000 if i
== n
&& wback
&& i
!= LowestSetBit(registers
) then
5001 MemA
[address
,4] = bits(32) UNKNOWN
;
5003 MemA
[address
,4] = R
[i
];
5004 address
= address
+ 4;
5006 if registers
<15> == '1' then
5007 MemA
[address
,4] = PCStoreValue();
5009 if wback then R
[n
] = R
[n
] + 4*BitCount(registers
);
5012 bool success
= false;
5014 if (ConditionPassed(opcode
)) {
5016 uint32_t registers
= 0;
5018 const uint32_t addr_byte_size
= GetAddressByteSize();
5020 // EncodingSpecificOperations();
5023 // n = UInt(Rn); registers = register_list; wback = (W == '1');
5024 n
= Bits32(opcode
, 19, 16);
5025 registers
= Bits32(opcode
, 15, 0);
5026 wback
= BitIsSet(opcode
, 21);
5028 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
5029 if ((n
== 15) && (BitCount(registers
) < 1))
5035 // address = R[n] + 4;
5038 addr_t Rn
= ReadCoreReg(n
, &success
);
5042 addr_t address
= Rn
+ addr_byte_size
;
5044 EmulateInstruction::Context context
;
5045 context
.type
= EmulateInstruction::eContextRegisterStore
;
5046 std::optional
<RegisterInfo
> base_reg
=
5047 GetRegisterInfo(eRegisterKindDWARF
, dwarf_r0
+ n
);
5049 uint32_t lowest_set_bit
= 14;
5051 for (uint32_t i
= 0; i
< 14; ++i
) {
5052 // if registers<i> == '1' then
5053 if (BitIsSet(registers
, i
)) {
5054 if (i
< lowest_set_bit
)
5056 // if i == n && wback && i != LowestSetBit(registers) then
5057 if ((i
== n
) && wback
&& (i
!= lowest_set_bit
))
5058 // MemA[address,4] = bits(32) UNKNOWN;
5059 WriteBits32UnknownToMemory(address
+ offset
);
5062 // MemA[address,4] = R[i];
5063 uint32_t data
= ReadRegisterUnsigned(eRegisterKindDWARF
, dwarf_r0
+ i
,
5068 std::optional
<RegisterInfo
> data_reg
=
5069 GetRegisterInfo(eRegisterKindDWARF
, dwarf_r0
+ i
);
5070 context
.SetRegisterToRegisterPlusOffset(*data_reg
, *base_reg
,
5071 offset
+ addr_byte_size
);
5072 if (!MemAWrite(context
, address
+ offset
, data
, addr_byte_size
))
5076 // address = address + 4;
5077 offset
+= addr_byte_size
;
5081 // if registers<15> == '1' then
5082 // MemA[address,4] = PCStoreValue();
5083 if (BitIsSet(registers
, 15)) {
5084 std::optional
<RegisterInfo
> pc_reg
=
5085 GetRegisterInfo(eRegisterKindDWARF
, dwarf_pc
);
5086 context
.SetRegisterPlusOffset(*pc_reg
, 8);
5087 const uint32_t pc
= ReadCoreReg(PC_REG
, &success
);
5091 if (!MemAWrite(context
, address
+ offset
, pc
, addr_byte_size
))
5095 // if wback then R[n] = R[n] + 4*BitCount(registers);
5097 offset
= addr_byte_size
* BitCount(registers
);
5098 context
.type
= EmulateInstruction::eContextAdjustBaseRegister
;
5099 context
.SetImmediateSigned(offset
);
5100 addr_t data
= Rn
+ offset
;
5101 if (!WriteRegisterUnsigned(context
, eRegisterKindDWARF
, dwarf_r0
+ n
,
5109 // STR (store immediate) calculates an address from a base register value and an
5110 // immediate offset, and stores a word
5111 // from a register to memory. It can use offset, post-indexed, or pre-indexed
5113 bool EmulateInstructionARM::EmulateSTRThumb(const uint32_t opcode
,
5114 const ARMEncoding encoding
) {
5116 if ConditionPassed() then
5117 EncodingSpecificOperations(); NullCheckIfThumbEE(n
);
5118 offset_addr
= if add
then (R
[n
] + imm32
) else (R
[n
] - imm32
);
5119 address
= if index then offset_addr
else R
[n
];
5120 if UnalignedSupport() || address
<1:0> == '00' then
5121 MemU
[address
,4] = R
[t
];
5122 else // Can only occur before ARMv7
5123 MemU
[address
,4] = bits(32) UNKNOWN
;
5124 if wback then R
[n
] = offset_addr
;
5127 bool success
= false;
5129 if (ConditionPassed(opcode
)) {
5130 const uint32_t addr_byte_size
= GetAddressByteSize();
5138 // EncodingSpecificOperations (); NullCheckIfThumbEE(n);
5141 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm5:'00', 32);
5142 t
= Bits32(opcode
, 2, 0);
5143 n
= Bits32(opcode
, 5, 3);
5144 imm32
= Bits32(opcode
, 10, 6) << 2;
5146 // index = TRUE; add = TRUE; wback = FALSE;
5153 // t = UInt(Rt); n = 13; imm32 = ZeroExtend(imm8:'00', 32);
5154 t
= Bits32(opcode
, 10, 8);
5156 imm32
= Bits32(opcode
, 7, 0) << 2;
5158 // index = TRUE; add = TRUE; wback = FALSE;
5165 // if Rn == '1111' then UNDEFINED;
5166 if (Bits32(opcode
, 19, 16) == 15)
5169 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
5170 t
= Bits32(opcode
, 15, 12);
5171 n
= Bits32(opcode
, 19, 16);
5172 imm32
= Bits32(opcode
, 11, 0);
5174 // index = TRUE; add = TRUE; wback = FALSE;
5179 // if t == 15 then UNPREDICTABLE;
5185 // if P == '1' && U == '1' && W == '0' then SEE STRT;
5186 // if Rn == '1101' && P == '1' && U == '0' && W == '1' && imm8 ==
5187 // '00000100' then SEE PUSH;
5188 // if Rn == '1111' || (P == '0' && W == '0') then UNDEFINED;
5189 if ((Bits32(opcode
, 19, 16) == 15) ||
5190 (BitIsClear(opcode
, 10) && BitIsClear(opcode
, 8)))
5193 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32);
5194 t
= Bits32(opcode
, 15, 12);
5195 n
= Bits32(opcode
, 19, 16);
5196 imm32
= Bits32(opcode
, 7, 0);
5198 // index = (P == '1'); add = (U == '1'); wback = (W == '1');
5199 index
= BitIsSet(opcode
, 10);
5200 add
= BitIsSet(opcode
, 9);
5201 wback
= BitIsSet(opcode
, 8);
5203 // if t == 15 || (wback && n == t) then UNPREDICTABLE;
5204 if ((t
== 15) || (wback
&& (n
== t
)))
5215 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
5216 uint32_t base_address
= ReadCoreReg(n
, &success
);
5221 offset_addr
= base_address
+ imm32
;
5223 offset_addr
= base_address
- imm32
;
5225 // address = if index then offset_addr else R[n];
5227 address
= offset_addr
;
5229 address
= base_address
;
5231 EmulateInstruction::Context context
;
5233 context
.type
= eContextPushRegisterOnStack
;
5235 context
.type
= eContextRegisterStore
;
5237 std::optional
<RegisterInfo
> base_reg
=
5238 GetRegisterInfo(eRegisterKindDWARF
, dwarf_r0
+ n
);
5240 // if UnalignedSupport() || address<1:0> == '00' then
5241 if (UnalignedSupport() ||
5242 (BitIsClear(address
, 1) && BitIsClear(address
, 0))) {
5243 // MemU[address,4] = R[t];
5245 ReadRegisterUnsigned(eRegisterKindDWARF
, dwarf_r0
+ t
, 0, &success
);
5249 std::optional
<RegisterInfo
> data_reg
=
5250 GetRegisterInfo(eRegisterKindDWARF
, dwarf_r0
+ t
);
5251 int32_t offset
= address
- base_address
;
5252 context
.SetRegisterToRegisterPlusOffset(*data_reg
, *base_reg
, offset
);
5253 if (!MemUWrite(context
, address
, data
, addr_byte_size
))
5256 // MemU[address,4] = bits(32) UNKNOWN;
5257 WriteBits32UnknownToMemory(address
);
5260 // if wback then R[n] = offset_addr;
5263 context
.type
= eContextAdjustStackPointer
;
5265 context
.type
= eContextAdjustBaseRegister
;
5266 context
.SetAddress(offset_addr
);
5268 if (!WriteRegisterUnsigned(context
, eRegisterKindDWARF
, dwarf_r0
+ n
,
5276 // STR (Store Register) calculates an address from a base register value and an
5277 // offset register value, stores a
5278 // word from a register to memory. The offset register value can optionally
5280 bool EmulateInstructionARM::EmulateSTRRegister(const uint32_t opcode
,
5281 const ARMEncoding encoding
) {
5283 if ConditionPassed() then
5284 EncodingSpecificOperations(); NullCheckIfThumbEE(n
);
5285 offset
= Shift(R
[m
], shift_t
, shift_n
, APSR
.C
);
5286 offset_addr
= if add
then (R
[n
] + offset
) else (R
[n
] - offset
);
5287 address
= if index then offset_addr
else R
[n
];
5288 if t
== 15 then
// Only possible for encoding A1
5289 data
= PCStoreValue();
5292 if UnalignedSupport() || address
<1:0> == '00' || CurrentInstrSet() == InstrSet_ARM then
5293 MemU
[address
,4] = data
;
5294 else // Can only occur before ARMv7
5295 MemU
[address
,4] = bits(32) UNKNOWN
;
5296 if wback then R
[n
] = offset_addr
;
5299 bool success
= false;
5301 if (ConditionPassed(opcode
)) {
5302 const uint32_t addr_byte_size
= GetAddressByteSize();
5307 ARM_ShifterType shift_t
;
5313 // EncodingSpecificOperations (); NullCheckIfThumbEE(n);
5316 // if CurrentInstrSet() == InstrSet_ThumbEE then SEE "Modified operation
5318 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
5319 t
= Bits32(opcode
, 2, 0);
5320 n
= Bits32(opcode
, 5, 3);
5321 m
= Bits32(opcode
, 8, 6);
5323 // index = TRUE; add = TRUE; wback = FALSE;
5328 // (shift_t, shift_n) = (SRType_LSL, 0);
5329 shift_t
= SRType_LSL
;
5334 // if Rn == '1111' then UNDEFINED;
5335 if (Bits32(opcode
, 19, 16) == 15)
5338 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
5339 t
= Bits32(opcode
, 15, 12);
5340 n
= Bits32(opcode
, 19, 16);
5341 m
= Bits32(opcode
, 3, 0);
5343 // index = TRUE; add = TRUE; wback = FALSE;
5348 // (shift_t, shift_n) = (SRType_LSL, UInt(imm2));
5349 shift_t
= SRType_LSL
;
5350 shift_n
= Bits32(opcode
, 5, 4);
5352 // if t == 15 || BadReg(m) then UNPREDICTABLE;
5353 if ((t
== 15) || (BadReg(m
)))
5358 // if P == '0' && W == '1' then SEE STRT;
5359 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
5360 t
= Bits32(opcode
, 15, 12);
5361 n
= Bits32(opcode
, 19, 16);
5362 m
= Bits32(opcode
, 3, 0);
5364 // index = (P == '1'); add = (U == '1'); wback = (P == '0') ||
5366 index
= BitIsSet(opcode
, 24);
5367 add
= BitIsSet(opcode
, 23);
5368 wback
= (BitIsClear(opcode
, 24) || BitIsSet(opcode
, 21));
5370 // (shift_t, shift_n) = DecodeImmShift(type, imm5);
5371 uint32_t typ
= Bits32(opcode
, 6, 5);
5372 uint32_t imm5
= Bits32(opcode
, 11, 7);
5373 shift_n
= DecodeImmShift(typ
, imm5
, shift_t
);
5375 // if m == 15 then UNPREDICTABLE;
5379 // if wback && (n == 15 || n == t) then UNPREDICTABLE;
5380 if (wback
&& ((n
== 15) || (n
== t
)))
5393 addr_t base_address
=
5394 ReadRegisterUnsigned(eRegisterKindDWARF
, dwarf_r0
+ n
, 0, &success
);
5399 ReadRegisterUnsigned(eRegisterKindDWARF
, dwarf_r0
+ m
, 0, &success
);
5403 // offset = Shift(R[m], shift_t, shift_n, APSR.C);
5404 offset
= Shift(Rm_data
, shift_t
, shift_n
, APSR_C
, &success
);
5408 // offset_addr = if add then (R[n] + offset) else (R[n] - offset);
5410 offset_addr
= base_address
+ offset
;
5412 offset_addr
= base_address
- offset
;
5414 // address = if index then offset_addr else R[n];
5416 address
= offset_addr
;
5418 address
= base_address
;
5421 // if t == 15 then // Only possible for encoding A1
5423 // data = PCStoreValue();
5424 data
= ReadCoreReg(PC_REG
, &success
);
5428 ReadRegisterUnsigned(eRegisterKindDWARF
, dwarf_r0
+ t
, 0, &success
);
5433 EmulateInstruction::Context context
;
5434 context
.type
= eContextRegisterStore
;
5436 // if UnalignedSupport() || address<1:0> == '00' || CurrentInstrSet() ==
5437 // InstrSet_ARM then
5438 if (UnalignedSupport() ||
5439 (BitIsClear(address
, 1) && BitIsClear(address
, 0)) ||
5440 CurrentInstrSet() == eModeARM
) {
5441 // MemU[address,4] = data;
5443 std::optional
<RegisterInfo
> base_reg
=
5444 GetRegisterInfo(eRegisterKindDWARF
, dwarf_r0
+ n
);
5445 std::optional
<RegisterInfo
> data_reg
=
5446 GetRegisterInfo(eRegisterKindDWARF
, dwarf_r0
+ t
);
5448 context
.SetRegisterToRegisterPlusOffset(*data_reg
, *base_reg
,
5449 address
- base_address
);
5450 if (!MemUWrite(context
, address
, data
, addr_byte_size
))
5454 // MemU[address,4] = bits(32) UNKNOWN;
5455 WriteBits32UnknownToMemory(address
);
5457 // if wback then R[n] = offset_addr;
5459 context
.type
= eContextRegisterLoad
;
5460 context
.SetAddress(offset_addr
);
5461 if (!WriteRegisterUnsigned(context
, eRegisterKindDWARF
, dwarf_r0
+ n
,
5469 bool EmulateInstructionARM::EmulateSTRBThumb(const uint32_t opcode
,
5470 const ARMEncoding encoding
) {
5472 if ConditionPassed() then
5473 EncodingSpecificOperations(); NullCheckIfThumbEE(n
);
5474 offset_addr
= if add
then (R
[n
] + imm32
) else (R
[n
] - imm32
);
5475 address
= if index then offset_addr
else R
[n
];
5476 MemU
[address
,1] = R
[t
]<7:0>;
5477 if wback then R
[n
] = offset_addr
;
5480 bool success
= false;
5482 if (ConditionPassed(opcode
)) {
5489 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
5492 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm5, 32);
5493 t
= Bits32(opcode
, 2, 0);
5494 n
= Bits32(opcode
, 5, 3);
5495 imm32
= Bits32(opcode
, 10, 6);
5497 // index = TRUE; add = TRUE; wback = FALSE;
5504 // if Rn == '1111' then UNDEFINED;
5505 if (Bits32(opcode
, 19, 16) == 15)
5508 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
5509 t
= Bits32(opcode
, 15, 12);
5510 n
= Bits32(opcode
, 19, 16);
5511 imm32
= Bits32(opcode
, 11, 0);
5513 // index = TRUE; add = TRUE; wback = FALSE;
5518 // if BadReg(t) then UNPREDICTABLE;
5524 // if P == '1' && U == '1' && W == '0' then SEE STRBT;
5525 // if Rn == '1111' || (P == '0' && W == '0') then UNDEFINED;
5526 if (Bits32(opcode
, 19, 16) == 15)
5529 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32);
5530 t
= Bits32(opcode
, 15, 12);
5531 n
= Bits32(opcode
, 19, 16);
5532 imm32
= Bits32(opcode
, 7, 0);
5534 // index = (P == '1'); add = (U == '1'); wback = (W == '1');
5535 index
= BitIsSet(opcode
, 10);
5536 add
= BitIsSet(opcode
, 9);
5537 wback
= BitIsSet(opcode
, 8);
5539 // if BadReg(t) || (wback && n == t) then UNPREDICTABLE
5540 if ((BadReg(t
)) || (wback
&& (n
== t
)))
5550 addr_t base_address
=
5551 ReadRegisterUnsigned(eRegisterKindDWARF
, dwarf_r0
+ n
, 0, &success
);
5555 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
5557 offset_addr
= base_address
+ imm32
;
5559 offset_addr
= base_address
- imm32
;
5561 // address = if index then offset_addr else R[n];
5563 address
= offset_addr
;
5565 address
= base_address
;
5567 // MemU[address,1] = R[t]<7:0>
5568 std::optional
<RegisterInfo
> base_reg
=
5569 GetRegisterInfo(eRegisterKindDWARF
, dwarf_r0
+ n
);
5570 std::optional
<RegisterInfo
> data_reg
=
5571 GetRegisterInfo(eRegisterKindDWARF
, dwarf_r0
+ t
);
5573 EmulateInstruction::Context context
;
5574 context
.type
= eContextRegisterStore
;
5575 context
.SetRegisterToRegisterPlusOffset(*data_reg
, *base_reg
,
5576 address
- base_address
);
5579 ReadRegisterUnsigned(eRegisterKindDWARF
, dwarf_r0
+ t
, 0, &success
);
5583 data
= Bits32(data
, 7, 0);
5585 if (!MemUWrite(context
, address
, data
, 1))
5588 // if wback then R[n] = offset_addr;
5590 context
.type
= eContextRegisterLoad
;
5591 context
.SetAddress(offset_addr
);
5592 if (!WriteRegisterUnsigned(context
, eRegisterKindDWARF
, dwarf_r0
+ n
,
5601 // STRH (register) calculates an address from a base register value and an
5602 // offset register value, and stores a
5603 // halfword from a register to memory. The offset register value can be
5604 // shifted left by 0, 1, 2, or 3 bits.
5605 bool EmulateInstructionARM::EmulateSTRHRegister(const uint32_t opcode
,
5606 const ARMEncoding encoding
) {
5608 if ConditionPassed() then
5609 EncodingSpecificOperations(); NullCheckIfThumbEE(n
);
5610 offset
= Shift(R
[m
], shift_t
, shift_n
, APSR
.C
);
5611 offset_addr
= if add
then (R
[n
] + offset
) else (R
[n
] - offset
);
5612 address
= if index then offset_addr
else R
[n
];
5613 if UnalignedSupport() || address
<0> == '0' then
5614 MemU
[address
,2] = R
[t
]<15:0>;
5615 else // Can only occur before ARMv7
5616 MemU
[address
,2] = bits(16) UNKNOWN
;
5617 if wback then R
[n
] = offset_addr
;
5620 bool success
= false;
5622 if (ConditionPassed(opcode
)) {
5629 ARM_ShifterType shift_t
;
5632 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
5635 // if CurrentInstrSet() == InstrSet_ThumbEE then SEE "Modified operation
5637 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
5638 t
= Bits32(opcode
, 2, 0);
5639 n
= Bits32(opcode
, 5, 3);
5640 m
= Bits32(opcode
, 8, 6);
5642 // index = TRUE; add = TRUE; wback = FALSE;
5647 // (shift_t, shift_n) = (SRType_LSL, 0);
5648 shift_t
= SRType_LSL
;
5654 // if Rn == '1111' then UNDEFINED;
5655 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
5656 t
= Bits32(opcode
, 15, 12);
5657 n
= Bits32(opcode
, 19, 16);
5658 m
= Bits32(opcode
, 3, 0);
5662 // index = TRUE; add = TRUE; wback = FALSE;
5667 // (shift_t, shift_n) = (SRType_LSL, UInt(imm2));
5668 shift_t
= SRType_LSL
;
5669 shift_n
= Bits32(opcode
, 5, 4);
5671 // if BadReg(t) || BadReg(m) then UNPREDICTABLE;
5672 if (BadReg(t
) || BadReg(m
))
5678 // if P == '0' && W == '1' then SEE STRHT;
5679 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
5680 t
= Bits32(opcode
, 15, 12);
5681 n
= Bits32(opcode
, 19, 16);
5682 m
= Bits32(opcode
, 3, 0);
5684 // index = (P == '1'); add = (U == '1'); wback = (P == '0') ||
5686 index
= BitIsSet(opcode
, 24);
5687 add
= BitIsSet(opcode
, 23);
5688 wback
= (BitIsClear(opcode
, 24) || BitIsSet(opcode
, 21));
5690 // (shift_t, shift_n) = (SRType_LSL, 0);
5691 shift_t
= SRType_LSL
;
5694 // if t == 15 || m == 15 then UNPREDICTABLE;
5695 if ((t
== 15) || (m
== 15))
5698 // if wback && (n == 15 || n == t) then UNPREDICTABLE;
5699 if (wback
&& ((n
== 15) || (n
== t
)))
5708 uint32_t Rm
= ReadCoreReg(m
, &success
);
5712 uint32_t Rn
= ReadCoreReg(n
, &success
);
5716 // offset = Shift(R[m], shift_t, shift_n, APSR.C);
5717 uint32_t offset
= Shift(Rm
, shift_t
, shift_n
, APSR_C
, &success
);
5721 // offset_addr = if add then (R[n] + offset) else (R[n] - offset);
5724 offset_addr
= Rn
+ offset
;
5726 offset_addr
= Rn
- offset
;
5728 // address = if index then offset_addr else R[n];
5731 address
= offset_addr
;
5735 EmulateInstruction::Context context
;
5736 context
.type
= eContextRegisterStore
;
5738 // if UnalignedSupport() || address<0> == '0' then
5739 if (UnalignedSupport() || BitIsClear(address
, 0)) {
5740 // MemU[address,2] = R[t]<15:0>;
5741 uint32_t Rt
= ReadCoreReg(t
, &success
);
5745 EmulateInstruction::Context context
;
5746 context
.type
= eContextRegisterStore
;
5747 std::optional
<RegisterInfo
> base_reg
=
5748 GetRegisterInfo(eRegisterKindDWARF
, dwarf_r0
+ n
);
5749 std::optional
<RegisterInfo
> offset_reg
=
5750 GetRegisterInfo(eRegisterKindDWARF
, dwarf_r0
+ m
);
5751 std::optional
<RegisterInfo
> data_reg
=
5752 GetRegisterInfo(eRegisterKindDWARF
, dwarf_r0
+ t
);
5753 context
.SetRegisterToRegisterPlusIndirectOffset(*base_reg
, *offset_reg
,
5756 if (!MemUWrite(context
, address
, Bits32(Rt
, 15, 0), 2))
5758 } else // Can only occur before ARMv7
5760 // MemU[address,2] = bits(16) UNKNOWN;
5763 // if wback then R[n] = offset_addr;
5765 context
.type
= eContextAdjustBaseRegister
;
5766 context
.SetAddress(offset_addr
);
5767 if (!WriteRegisterUnsigned(context
, eRegisterKindDWARF
, dwarf_r0
+ n
,
5776 // Add with Carry (immediate) adds an immediate value and the carry flag value
5777 // to a register value, and writes the result to the destination register. It
5778 // can optionally update the condition flags based on the result.
5779 bool EmulateInstructionARM::EmulateADCImm(const uint32_t opcode
,
5780 const ARMEncoding encoding
) {
5782 // ARM pseudo code...
5783 if ConditionPassed() then
5784 EncodingSpecificOperations();
5785 (result
, carry
, overflow
) = AddWithCarry(R
[n
], imm32
, APSR
.C
);
5786 if d
== 15 then
// Can only occur for ARM encoding
5787 ALUWritePC(result
); // setflags is always FALSE here
5791 APSR
.N
= result
<31>;
5792 APSR
.Z
= IsZeroBit(result
);
5797 bool success
= false;
5799 if (ConditionPassed(opcode
)) {
5802 imm32
; // the immediate value to be added to the value obtained from Rn
5806 Rd
= Bits32(opcode
, 11, 8);
5807 Rn
= Bits32(opcode
, 19, 16);
5808 setflags
= BitIsSet(opcode
, 20);
5809 imm32
= ThumbExpandImm(opcode
); // imm32 = ThumbExpandImm(i:imm3:imm8)
5810 if (BadReg(Rd
) || BadReg(Rn
))
5814 Rd
= Bits32(opcode
, 15, 12);
5815 Rn
= Bits32(opcode
, 19, 16);
5816 setflags
= BitIsSet(opcode
, 20);
5817 imm32
= ARMExpandImm(opcode
); // imm32 = ARMExpandImm(imm12)
5819 if (Rd
== 15 && setflags
)
5820 return EmulateSUBSPcLrEtc(opcode
, encoding
);
5826 // Read the first operand.
5827 int32_t val1
= ReadCoreReg(Rn
, &success
);
5831 AddWithCarryResult res
= AddWithCarry(val1
, imm32
, APSR_C
);
5833 EmulateInstruction::Context context
;
5834 context
.type
= EmulateInstruction::eContextImmediate
;
5835 context
.SetNoArgs();
5837 if (!WriteCoreRegOptionalFlags(context
, res
.result
, Rd
, setflags
,
5838 res
.carry_out
, res
.overflow
))
5844 // Add with Carry (register) adds a register value, the carry flag value, and
5845 // an optionally-shifted register value, and writes the result to the
5846 // destination register. It can optionally update the condition flags based on
5848 bool EmulateInstructionARM::EmulateADCReg(const uint32_t opcode
,
5849 const ARMEncoding encoding
) {
5851 // ARM pseudo code...
5852 if ConditionPassed() then
5853 EncodingSpecificOperations();
5854 shifted
= Shift(R
[m
], shift_t
, shift_n
, APSR
.C
);
5855 (result
, carry
, overflow
) = AddWithCarry(R
[n
], shifted
, APSR
.C
);
5856 if d
== 15 then
// Can only occur for ARM encoding
5857 ALUWritePC(result
); // setflags is always FALSE here
5861 APSR
.N
= result
<31>;
5862 APSR
.Z
= IsZeroBit(result
);
5867 bool success
= false;
5869 if (ConditionPassed(opcode
)) {
5870 uint32_t Rd
, Rn
, Rm
;
5871 ARM_ShifterType shift_t
;
5872 uint32_t shift_n
; // the shift applied to the value read from Rm
5876 Rd
= Rn
= Bits32(opcode
, 2, 0);
5877 Rm
= Bits32(opcode
, 5, 3);
5878 setflags
= !InITBlock();
5879 shift_t
= SRType_LSL
;
5883 Rd
= Bits32(opcode
, 11, 8);
5884 Rn
= Bits32(opcode
, 19, 16);
5885 Rm
= Bits32(opcode
, 3, 0);
5886 setflags
= BitIsSet(opcode
, 20);
5887 shift_n
= DecodeImmShiftThumb(opcode
, shift_t
);
5888 if (BadReg(Rd
) || BadReg(Rn
) || BadReg(Rm
))
5892 Rd
= Bits32(opcode
, 15, 12);
5893 Rn
= Bits32(opcode
, 19, 16);
5894 Rm
= Bits32(opcode
, 3, 0);
5895 setflags
= BitIsSet(opcode
, 20);
5896 shift_n
= DecodeImmShiftARM(opcode
, shift_t
);
5898 if (Rd
== 15 && setflags
)
5899 return EmulateSUBSPcLrEtc(opcode
, encoding
);
5905 // Read the first operand.
5906 int32_t val1
= ReadCoreReg(Rn
, &success
);
5910 // Read the second operand.
5911 int32_t val2
= ReadCoreReg(Rm
, &success
);
5915 uint32_t shifted
= Shift(val2
, shift_t
, shift_n
, APSR_C
, &success
);
5918 AddWithCarryResult res
= AddWithCarry(val1
, shifted
, APSR_C
);
5920 EmulateInstruction::Context context
;
5921 context
.type
= EmulateInstruction::eContextImmediate
;
5922 context
.SetNoArgs();
5924 if (!WriteCoreRegOptionalFlags(context
, res
.result
, Rd
, setflags
,
5925 res
.carry_out
, res
.overflow
))
5931 // This instruction adds an immediate value to the PC value to form a PC-
5932 // relative address, and writes the result to the destination register.
5933 bool EmulateInstructionARM::EmulateADR(const uint32_t opcode
,
5934 const ARMEncoding encoding
) {
5936 // ARM pseudo code...
5937 if ConditionPassed() then
5938 EncodingSpecificOperations();
5939 result
= if add
then (Align(PC
,4) + imm32
) else (Align(PC
,4) - imm32
);
5940 if d
== 15 then
// Can only occur for ARM encodings
5946 bool success
= false;
5948 if (ConditionPassed(opcode
)) {
5950 uint32_t imm32
; // the immediate value to be added/subtracted to/from the PC
5954 Rd
= Bits32(opcode
, 10, 8);
5955 imm32
= ThumbImm8Scaled(opcode
); // imm32 = ZeroExtend(imm8:'00', 32)
5960 Rd
= Bits32(opcode
, 11, 8);
5961 imm32
= ThumbImm12(opcode
); // imm32 = ZeroExtend(i:imm3:imm8, 32)
5962 add
= (Bits32(opcode
, 24, 21) == 0); // 0b0000 => ADD; 0b0101 => SUB
5968 Rd
= Bits32(opcode
, 15, 12);
5969 imm32
= ARMExpandImm(opcode
); // imm32 = ARMExpandImm(imm12)
5970 add
= (Bits32(opcode
, 24, 21) == 0x4); // 0b0100 => ADD; 0b0010 => SUB
5976 // Read the PC value.
5977 uint32_t pc
= ReadCoreReg(PC_REG
, &success
);
5981 uint32_t result
= (add
? Align(pc
, 4) + imm32
: Align(pc
, 4) - imm32
);
5983 EmulateInstruction::Context context
;
5984 context
.type
= EmulateInstruction::eContextImmediate
;
5985 context
.SetNoArgs();
5987 if (!WriteCoreReg(context
, result
, Rd
))
5993 // This instruction performs a bitwise AND of a register value and an immediate
5994 // value, and writes the result to the destination register. It can optionally
5995 // update the condition flags based on the result.
5996 bool EmulateInstructionARM::EmulateANDImm(const uint32_t opcode
,
5997 const ARMEncoding encoding
) {
5999 // ARM pseudo code...
6000 if ConditionPassed() then
6001 EncodingSpecificOperations();
6002 result
= R
[n
] AND imm32
;
6003 if d
== 15 then
// Can only occur for ARM encoding
6004 ALUWritePC(result
); // setflags is always FALSE here
6008 APSR
.N
= result
<31>;
6009 APSR
.Z
= IsZeroBit(result
);
6014 bool success
= false;
6016 if (ConditionPassed(opcode
)) {
6019 imm32
; // the immediate value to be ANDed to the value obtained from Rn
6021 uint32_t carry
; // the carry bit after ARM/Thumb Expand operation
6024 Rd
= Bits32(opcode
, 11, 8);
6025 Rn
= Bits32(opcode
, 19, 16);
6026 setflags
= BitIsSet(opcode
, 20);
6027 imm32
= ThumbExpandImm_C(
6029 carry
); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C)
6030 // if Rd == '1111' && S == '1' then SEE TST (immediate);
6031 if (Rd
== 15 && setflags
)
6032 return EmulateTSTImm(opcode
, eEncodingT1
);
6033 if (Rd
== 13 || (Rd
== 15 && !setflags
) || BadReg(Rn
))
6037 Rd
= Bits32(opcode
, 15, 12);
6038 Rn
= Bits32(opcode
, 19, 16);
6039 setflags
= BitIsSet(opcode
, 20);
6041 ARMExpandImm_C(opcode
, APSR_C
,
6042 carry
); // (imm32, carry) = ARMExpandImm(imm12, APSR.C)
6044 if (Rd
== 15 && setflags
)
6045 return EmulateSUBSPcLrEtc(opcode
, encoding
);
6051 // Read the first operand.
6052 uint32_t val1
= ReadCoreReg(Rn
, &success
);
6056 uint32_t result
= val1
& imm32
;
6058 EmulateInstruction::Context context
;
6059 context
.type
= EmulateInstruction::eContextImmediate
;
6060 context
.SetNoArgs();
6062 if (!WriteCoreRegOptionalFlags(context
, result
, Rd
, setflags
, carry
))
6068 // This instruction performs a bitwise AND of a register value and an
6069 // optionally-shifted register value, and writes the result to the destination
6070 // register. It can optionally update the condition flags based on the result.
6071 bool EmulateInstructionARM::EmulateANDReg(const uint32_t opcode
,
6072 const ARMEncoding encoding
) {
6074 // ARM pseudo code...
6075 if ConditionPassed() then
6076 EncodingSpecificOperations();
6077 (shifted
, carry
) = Shift_C(R
[m
], shift_t
, shift_n
, APSR
.C
);
6078 result
= R
[n
] AND shifted
;
6079 if d
== 15 then
// Can only occur for ARM encoding
6080 ALUWritePC(result
); // setflags is always FALSE here
6084 APSR
.N
= result
<31>;
6085 APSR
.Z
= IsZeroBit(result
);
6090 bool success
= false;
6092 if (ConditionPassed(opcode
)) {
6093 uint32_t Rd
, Rn
, Rm
;
6094 ARM_ShifterType shift_t
;
6095 uint32_t shift_n
; // the shift applied to the value read from Rm
6100 Rd
= Rn
= Bits32(opcode
, 2, 0);
6101 Rm
= Bits32(opcode
, 5, 3);
6102 setflags
= !InITBlock();
6103 shift_t
= SRType_LSL
;
6107 Rd
= Bits32(opcode
, 11, 8);
6108 Rn
= Bits32(opcode
, 19, 16);
6109 Rm
= Bits32(opcode
, 3, 0);
6110 setflags
= BitIsSet(opcode
, 20);
6111 shift_n
= DecodeImmShiftThumb(opcode
, shift_t
);
6112 // if Rd == '1111' && S == '1' then SEE TST (register);
6113 if (Rd
== 15 && setflags
)
6114 return EmulateTSTReg(opcode
, eEncodingT2
);
6115 if (Rd
== 13 || (Rd
== 15 && !setflags
) || BadReg(Rn
) || BadReg(Rm
))
6119 Rd
= Bits32(opcode
, 15, 12);
6120 Rn
= Bits32(opcode
, 19, 16);
6121 Rm
= Bits32(opcode
, 3, 0);
6122 setflags
= BitIsSet(opcode
, 20);
6123 shift_n
= DecodeImmShiftARM(opcode
, shift_t
);
6125 if (Rd
== 15 && setflags
)
6126 return EmulateSUBSPcLrEtc(opcode
, encoding
);
6132 // Read the first operand.
6133 uint32_t val1
= ReadCoreReg(Rn
, &success
);
6137 // Read the second operand.
6138 uint32_t val2
= ReadCoreReg(Rm
, &success
);
6142 uint32_t shifted
= Shift_C(val2
, shift_t
, shift_n
, APSR_C
, carry
, &success
);
6145 uint32_t result
= val1
& shifted
;
6147 EmulateInstruction::Context context
;
6148 context
.type
= EmulateInstruction::eContextImmediate
;
6149 context
.SetNoArgs();
6151 if (!WriteCoreRegOptionalFlags(context
, result
, Rd
, setflags
, carry
))
6157 // Bitwise Bit Clear (immediate) performs a bitwise AND of a register value and
6158 // the complement of an immediate value, and writes the result to the
6159 // destination register. It can optionally update the condition flags based on
6161 bool EmulateInstructionARM::EmulateBICImm(const uint32_t opcode
,
6162 const ARMEncoding encoding
) {
6164 // ARM pseudo code...
6165 if ConditionPassed() then
6166 EncodingSpecificOperations();
6167 result
= R
[n
] AND
NOT(imm32
);
6168 if d
== 15 then
// Can only occur for ARM encoding
6169 ALUWritePC(result
); // setflags is always FALSE here
6173 APSR
.N
= result
<31>;
6174 APSR
.Z
= IsZeroBit(result
);
6179 bool success
= false;
6181 if (ConditionPassed(opcode
)) {
6183 uint32_t imm32
; // the immediate value to be bitwise inverted and ANDed to
6184 // the value obtained from Rn
6186 uint32_t carry
; // the carry bit after ARM/Thumb Expand operation
6189 Rd
= Bits32(opcode
, 11, 8);
6190 Rn
= Bits32(opcode
, 19, 16);
6191 setflags
= BitIsSet(opcode
, 20);
6192 imm32
= ThumbExpandImm_C(
6194 carry
); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C)
6195 if (BadReg(Rd
) || BadReg(Rn
))
6199 Rd
= Bits32(opcode
, 15, 12);
6200 Rn
= Bits32(opcode
, 19, 16);
6201 setflags
= BitIsSet(opcode
, 20);
6203 ARMExpandImm_C(opcode
, APSR_C
,
6204 carry
); // (imm32, carry) = ARMExpandImm(imm12, APSR.C)
6206 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related
6208 if (Rd
== 15 && setflags
)
6209 return EmulateSUBSPcLrEtc(opcode
, encoding
);
6215 // Read the first operand.
6216 uint32_t val1
= ReadCoreReg(Rn
, &success
);
6220 uint32_t result
= val1
& ~imm32
;
6222 EmulateInstruction::Context context
;
6223 context
.type
= EmulateInstruction::eContextImmediate
;
6224 context
.SetNoArgs();
6226 if (!WriteCoreRegOptionalFlags(context
, result
, Rd
, setflags
, carry
))
6232 // Bitwise Bit Clear (register) performs a bitwise AND of a register value and
6233 // the complement of an optionally-shifted register value, and writes the
6234 // result to the destination register. It can optionally update the condition
6235 // flags based on the result.
6236 bool EmulateInstructionARM::EmulateBICReg(const uint32_t opcode
,
6237 const ARMEncoding encoding
) {
6239 // ARM pseudo code...
6240 if ConditionPassed() then
6241 EncodingSpecificOperations();
6242 (shifted
, carry
) = Shift_C(R
[m
], shift_t
, shift_n
, APSR
.C
);
6243 result
= R
[n
] AND
NOT(shifted
);
6244 if d
== 15 then
// Can only occur for ARM encoding
6245 ALUWritePC(result
); // setflags is always FALSE here
6249 APSR
.N
= result
<31>;
6250 APSR
.Z
= IsZeroBit(result
);
6255 bool success
= false;
6257 if (ConditionPassed(opcode
)) {
6258 uint32_t Rd
, Rn
, Rm
;
6259 ARM_ShifterType shift_t
;
6260 uint32_t shift_n
; // the shift applied to the value read from Rm
6265 Rd
= Rn
= Bits32(opcode
, 2, 0);
6266 Rm
= Bits32(opcode
, 5, 3);
6267 setflags
= !InITBlock();
6268 shift_t
= SRType_LSL
;
6272 Rd
= Bits32(opcode
, 11, 8);
6273 Rn
= Bits32(opcode
, 19, 16);
6274 Rm
= Bits32(opcode
, 3, 0);
6275 setflags
= BitIsSet(opcode
, 20);
6276 shift_n
= DecodeImmShiftThumb(opcode
, shift_t
);
6277 if (BadReg(Rd
) || BadReg(Rn
) || BadReg(Rm
))
6281 Rd
= Bits32(opcode
, 15, 12);
6282 Rn
= Bits32(opcode
, 19, 16);
6283 Rm
= Bits32(opcode
, 3, 0);
6284 setflags
= BitIsSet(opcode
, 20);
6285 shift_n
= DecodeImmShiftARM(opcode
, shift_t
);
6287 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related
6289 if (Rd
== 15 && setflags
)
6290 return EmulateSUBSPcLrEtc(opcode
, encoding
);
6296 // Read the first operand.
6297 uint32_t val1
= ReadCoreReg(Rn
, &success
);
6301 // Read the second operand.
6302 uint32_t val2
= ReadCoreReg(Rm
, &success
);
6306 uint32_t shifted
= Shift_C(val2
, shift_t
, shift_n
, APSR_C
, carry
, &success
);
6309 uint32_t result
= val1
& ~shifted
;
6311 EmulateInstruction::Context context
;
6312 context
.type
= EmulateInstruction::eContextImmediate
;
6313 context
.SetNoArgs();
6315 if (!WriteCoreRegOptionalFlags(context
, result
, Rd
, setflags
, carry
))
6321 // LDR (immediate, ARM) calculates an address from a base register value and an
6322 // immediate offset, loads a word
6323 // from memory, and writes it to a register. It can use offset, post-indexed,
6324 // or pre-indexed addressing.
6325 bool EmulateInstructionARM::EmulateLDRImmediateARM(const uint32_t opcode
,
6326 const ARMEncoding encoding
) {
6328 if ConditionPassed() then
6329 EncodingSpecificOperations();
6330 offset_addr
= if add
then (R
[n
] + imm32
) else (R
[n
] - imm32
);
6331 address
= if index then offset_addr
else R
[n
];
6332 data
= MemU
[address
,4];
6333 if wback then R
[n
] = offset_addr
;
6335 if address
<1:0> == '00' then
LoadWritePC(data
); else UNPREDICTABLE
;
6336 elsif
UnalignedSupport() || address
<1:0> = '00' then
6338 else // Can only apply before ARMv7
6339 R
[t
] = ROR(data
, 8*UInt(address
<1:0>));
6342 bool success
= false;
6344 if (ConditionPassed(opcode
)) {
6345 const uint32_t addr_byte_size
= GetAddressByteSize();
6356 // if Rn == '1111' then SEE LDR (literal);
6357 // if P == '0' && W == '1' then SEE LDRT;
6358 // if Rn == '1101' && P == '0' && U == '1' && W == '0' && imm12 ==
6359 // '000000000100' then SEE POP;
6360 // t == UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
6361 t
= Bits32(opcode
, 15, 12);
6362 n
= Bits32(opcode
, 19, 16);
6363 imm32
= Bits32(opcode
, 11, 0);
6365 // index = (P == '1'); add = (U == '1'); wback = (P == '0') ||
6367 index
= BitIsSet(opcode
, 24);
6368 add
= BitIsSet(opcode
, 23);
6369 wback
= (BitIsClear(opcode
, 24) || BitIsSet(opcode
, 21));
6371 // if wback && n == t then UNPREDICTABLE;
6372 if (wback
&& (n
== t
))
6383 addr_t base_address
= ReadCoreReg(n
, &success
);
6387 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
6389 offset_addr
= base_address
+ imm32
;
6391 offset_addr
= base_address
- imm32
;
6393 // address = if index then offset_addr else R[n];
6395 address
= offset_addr
;
6397 address
= base_address
;
6399 // data = MemU[address,4];
6401 std::optional
<RegisterInfo
> base_reg
=
6402 GetRegisterInfo(eRegisterKindDWARF
, dwarf_r0
+ n
);
6403 EmulateInstruction::Context context
;
6404 context
.type
= eContextRegisterLoad
;
6405 context
.SetRegisterPlusOffset(*base_reg
, address
- base_address
);
6407 uint64_t data
= MemURead(context
, address
, addr_byte_size
, 0, &success
);
6411 // if wback then R[n] = offset_addr;
6413 context
.type
= eContextAdjustBaseRegister
;
6414 context
.SetAddress(offset_addr
);
6415 if (!WriteRegisterUnsigned(context
, eRegisterKindDWARF
, dwarf_r0
+ n
,
6422 // if address<1:0> == '00' then LoadWritePC(data); else UNPREDICTABLE;
6423 if (BitIsClear(address
, 1) && BitIsClear(address
, 0)) {
6424 // LoadWritePC (data);
6425 context
.type
= eContextRegisterLoad
;
6426 context
.SetRegisterPlusOffset(*base_reg
, address
- base_address
);
6427 LoadWritePC(context
, data
);
6431 // elsif UnalignedSupport() || address<1:0> = '00' then
6432 else if (UnalignedSupport() ||
6433 (BitIsClear(address
, 1) && BitIsClear(address
, 0))) {
6435 context
.type
= eContextRegisterLoad
;
6436 context
.SetRegisterPlusOffset(*base_reg
, address
- base_address
);
6437 if (!WriteRegisterUnsigned(context
, eRegisterKindDWARF
, dwarf_r0
+ t
,
6441 // else // Can only apply before ARMv7
6443 // R[t] = ROR(data, 8*UInt(address<1:0>));
6444 data
= ROR(data
, Bits32(address
, 1, 0), &success
);
6447 context
.type
= eContextRegisterLoad
;
6448 context
.SetImmediate(data
);
6449 if (!WriteRegisterUnsigned(context
, eRegisterKindDWARF
, dwarf_r0
+ t
,
6457 // LDR (register) calculates an address from a base register value and an offset
6458 // register value, loads a word
6459 // from memory, and writes it to a register. The offset register value can
6460 // optionally be shifted.
6461 bool EmulateInstructionARM::EmulateLDRRegister(const uint32_t opcode
,
6462 const ARMEncoding encoding
) {
6464 if ConditionPassed() then
6465 EncodingSpecificOperations(); NullCheckIfThumbEE(n
);
6466 offset
= Shift(R
[m
], shift_t
, shift_n
, APSR
.C
);
6467 offset_addr
= if add
then (R
[n
] + offset
) else (R
[n
] - offset
);
6468 address
= if index then offset_addr
else R
[n
];
6469 data
= MemU
[address
,4];
6470 if wback then R
[n
] = offset_addr
;
6472 if address
<1:0> == '00' then
LoadWritePC(data
); else UNPREDICTABLE
;
6473 elsif
UnalignedSupport() || address
<1:0> = '00' then
6475 else // Can only apply before ARMv7
6476 if CurrentInstrSet() == InstrSet_ARM then
6477 R
[t
] = ROR(data
, 8*UInt(address
<1:0>));
6479 R
[t
] = bits(32) UNKNOWN
;
6482 bool success
= false;
6484 if (ConditionPassed(opcode
)) {
6485 const uint32_t addr_byte_size
= GetAddressByteSize();
6493 ARM_ShifterType shift_t
;
6498 // if CurrentInstrSet() == InstrSet_ThumbEE then SEE "Modified operation
6500 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
6501 t
= Bits32(opcode
, 2, 0);
6502 n
= Bits32(opcode
, 5, 3);
6503 m
= Bits32(opcode
, 8, 6);
6505 // index = TRUE; add = TRUE; wback = FALSE;
6510 // (shift_t, shift_n) = (SRType_LSL, 0);
6511 shift_t
= SRType_LSL
;
6517 // if Rn == '1111' then SEE LDR (literal);
6518 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
6519 t
= Bits32(opcode
, 15, 12);
6520 n
= Bits32(opcode
, 19, 16);
6521 m
= Bits32(opcode
, 3, 0);
6523 // index = TRUE; add = TRUE; wback = FALSE;
6528 // (shift_t, shift_n) = (SRType_LSL, UInt(imm2));
6529 shift_t
= SRType_LSL
;
6530 shift_n
= Bits32(opcode
, 5, 4);
6532 // if BadReg(m) then UNPREDICTABLE;
6536 // if t == 15 && InITBlock() && !LastInITBlock() then UNPREDICTABLE;
6537 if ((t
== 15) && InITBlock() && !LastInITBlock())
6543 // if P == '0' && W == '1' then SEE LDRT;
6544 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
6545 t
= Bits32(opcode
, 15, 12);
6546 n
= Bits32(opcode
, 19, 16);
6547 m
= Bits32(opcode
, 3, 0);
6549 // index = (P == '1'); add = (U == '1'); wback = (P == '0') ||
6551 index
= BitIsSet(opcode
, 24);
6552 add
= BitIsSet(opcode
, 23);
6553 wback
= (BitIsClear(opcode
, 24) || BitIsSet(opcode
, 21));
6555 // (shift_t, shift_n) = DecodeImmShift(type, imm5);
6556 uint32_t type
= Bits32(opcode
, 6, 5);
6557 uint32_t imm5
= Bits32(opcode
, 11, 7);
6558 shift_n
= DecodeImmShift(type
, imm5
, shift_t
);
6560 // if m == 15 then UNPREDICTABLE;
6564 // if wback && (n == 15 || n == t) then UNPREDICTABLE;
6565 if (wback
&& ((n
== 15) || (n
== t
)))
6574 ReadRegisterUnsigned(eRegisterKindDWARF
, dwarf_r0
+ m
, 0, &success
);
6579 ReadRegisterUnsigned(eRegisterKindDWARF
, dwarf_r0
+ n
, 0, &success
);
6586 // offset = Shift(R[m], shift_t, shift_n, APSR.C); -- Note "The APSR is
6587 // an application level alias for the CPSR".
6589 Shift(Rm
, shift_t
, shift_n
, Bit32(m_opcode_cpsr
, APSR_C
), &success
);
6593 // offset_addr = if add then (R[n] + offset) else (R[n] - offset);
6595 offset_addr
= Rn
+ offset
;
6597 offset_addr
= Rn
- offset
;
6599 // address = if index then offset_addr else R[n];
6601 address
= offset_addr
;
6605 // data = MemU[address,4];
6606 std::optional
<RegisterInfo
> base_reg
=
6607 GetRegisterInfo(eRegisterKindDWARF
, dwarf_r0
+ n
);
6608 EmulateInstruction::Context context
;
6609 context
.type
= eContextRegisterLoad
;
6610 context
.SetRegisterPlusOffset(*base_reg
, address
- Rn
);
6612 uint64_t data
= MemURead(context
, address
, addr_byte_size
, 0, &success
);
6616 // if wback then R[n] = offset_addr;
6618 context
.type
= eContextAdjustBaseRegister
;
6619 context
.SetAddress(offset_addr
);
6620 if (!WriteRegisterUnsigned(context
, eRegisterKindDWARF
, dwarf_r0
+ n
,
6627 // if address<1:0> == '00' then LoadWritePC(data); else UNPREDICTABLE;
6628 if (BitIsClear(address
, 1) && BitIsClear(address
, 0)) {
6629 context
.type
= eContextRegisterLoad
;
6630 context
.SetRegisterPlusOffset(*base_reg
, address
- Rn
);
6631 LoadWritePC(context
, data
);
6635 // elsif UnalignedSupport() || address<1:0> = '00' then
6636 else if (UnalignedSupport() ||
6637 (BitIsClear(address
, 1) && BitIsClear(address
, 0))) {
6639 context
.type
= eContextRegisterLoad
;
6640 context
.SetRegisterPlusOffset(*base_reg
, address
- Rn
);
6641 if (!WriteRegisterUnsigned(context
, eRegisterKindDWARF
, dwarf_r0
+ t
,
6644 } else // Can only apply before ARMv7
6646 // if CurrentInstrSet() == InstrSet_ARM then
6647 if (CurrentInstrSet() == eModeARM
) {
6648 // R[t] = ROR(data, 8*UInt(address<1:0>));
6649 data
= ROR(data
, Bits32(address
, 1, 0), &success
);
6652 context
.type
= eContextRegisterLoad
;
6653 context
.SetImmediate(data
);
6654 if (!WriteRegisterUnsigned(context
, eRegisterKindDWARF
, dwarf_r0
+ t
,
6658 // R[t] = bits(32) UNKNOWN;
6659 WriteBits32Unknown(t
);
6666 // LDRB (immediate, Thumb)
6667 bool EmulateInstructionARM::EmulateLDRBImmediate(const uint32_t opcode
,
6668 const ARMEncoding encoding
) {
6670 if ConditionPassed() then
6671 EncodingSpecificOperations(); NullCheckIfThumbEE(n
);
6672 offset_addr
= if add
then (R
[n
] + imm32
) else (R
[n
] - imm32
);
6673 address
= if index then offset_addr
else R
[n
];
6674 R
[t
] = ZeroExtend(MemU
[address
,1], 32);
6675 if wback then R
[n
] = offset_addr
;
6678 bool success
= false;
6680 if (ConditionPassed(opcode
)) {
6688 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
6691 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm5, 32);
6692 t
= Bits32(opcode
, 2, 0);
6693 n
= Bits32(opcode
, 5, 3);
6694 imm32
= Bits32(opcode
, 10, 6);
6696 // index = TRUE; add = TRUE; wback = FALSE;
6704 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
6705 t
= Bits32(opcode
, 15, 12);
6706 n
= Bits32(opcode
, 19, 16);
6707 imm32
= Bits32(opcode
, 11, 0);
6709 // index = TRUE; add = TRUE; wback = FALSE;
6714 // if Rt == '1111' then SEE PLD;
6716 return false; // PLD is not implemented yet
6718 // if Rn == '1111' then SEE LDRB (literal);
6720 return EmulateLDRBLiteral(opcode
, eEncodingT1
);
6722 // if t == 13 then UNPREDICTABLE;
6729 // if P == '1' && U == '1' && W == '0' then SEE LDRBT;
6730 // if P == '0' && W == '0' then UNDEFINED;
6731 if (BitIsClear(opcode
, 10) && BitIsClear(opcode
, 8))
6734 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32);
6735 t
= Bits32(opcode
, 15, 12);
6736 n
= Bits32(opcode
, 19, 16);
6737 imm32
= Bits32(opcode
, 7, 0);
6739 // index = (P == '1'); add = (U == '1'); wback = (W == '1');
6740 index
= BitIsSet(opcode
, 10);
6741 add
= BitIsSet(opcode
, 9);
6742 wback
= BitIsSet(opcode
, 8);
6744 // if Rt == '1111' && P == '1' && U == '0' && W == '0' then SEE PLD;
6746 return false; // PLD is not implemented yet
6748 // if Rn == '1111' then SEE LDRB (literal);
6750 return EmulateLDRBLiteral(opcode
, eEncodingT1
);
6752 // if BadReg(t) || (wback && n == t) then UNPREDICTABLE;
6753 if (BadReg(t
) || (wback
&& (n
== t
)))
6763 ReadRegisterUnsigned(eRegisterKindDWARF
, dwarf_r0
+ n
, 0, &success
);
6770 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
6772 offset_addr
= Rn
+ imm32
;
6774 offset_addr
= Rn
- imm32
;
6776 // address = if index then offset_addr else R[n];
6778 address
= offset_addr
;
6782 // R[t] = ZeroExtend(MemU[address,1], 32);
6783 std::optional
<RegisterInfo
> base_reg
=
6784 GetRegisterInfo(eRegisterKindDWARF
, dwarf_r0
+ n
);
6785 std::optional
<RegisterInfo
> data_reg
=
6786 GetRegisterInfo(eRegisterKindDWARF
, dwarf_r0
+ t
);
6788 EmulateInstruction::Context context
;
6789 context
.type
= eContextRegisterLoad
;
6790 context
.SetRegisterToRegisterPlusOffset(*data_reg
, *base_reg
, address
- Rn
);
6792 uint64_t data
= MemURead(context
, address
, 1, 0, &success
);
6796 if (!WriteRegisterUnsigned(context
, eRegisterKindDWARF
, dwarf_r0
+ t
, data
))
6799 // if wback then R[n] = offset_addr;
6801 context
.type
= eContextAdjustBaseRegister
;
6802 context
.SetAddress(offset_addr
);
6803 if (!WriteRegisterUnsigned(context
, eRegisterKindDWARF
, dwarf_r0
+ n
,
6811 // LDRB (literal) calculates an address from the PC value and an immediate
6812 // offset, loads a byte from memory,
6813 // zero-extends it to form a 32-bit word and writes it to a register.
6814 bool EmulateInstructionARM::EmulateLDRBLiteral(const uint32_t opcode
,
6815 const ARMEncoding encoding
) {
6817 if ConditionPassed() then
6818 EncodingSpecificOperations(); NullCheckIfThumbEE(15);
6820 address
= if add
then (base
+ imm32
) else (base
- imm32
);
6821 R
[t
] = ZeroExtend(MemU
[address
,1], 32);
6824 bool success
= false;
6826 if (ConditionPassed(opcode
)) {
6832 // t = UInt(Rt); imm32 = ZeroExtend(imm12, 32); add = (U == '1');
6833 t
= Bits32(opcode
, 15, 12);
6834 imm32
= Bits32(opcode
, 11, 0);
6835 add
= BitIsSet(opcode
, 23);
6837 // if Rt == '1111' then SEE PLD;
6839 return false; // PLD is not implemented yet
6841 // if t == 13 then UNPREDICTABLE;
6848 // t == UInt(Rt); imm32 = ZeroExtend(imm12, 32); add = (U == '1');
6849 t
= Bits32(opcode
, 15, 12);
6850 imm32
= Bits32(opcode
, 11, 0);
6851 add
= BitIsSet(opcode
, 23);
6853 // if t == 15 then UNPREDICTABLE;
6862 // base = Align(PC,4);
6863 uint32_t pc_val
= ReadCoreReg(PC_REG
, &success
);
6867 uint32_t base
= AlignPC(pc_val
);
6870 // address = if add then (base + imm32) else (base - imm32);
6872 address
= base
+ imm32
;
6874 address
= base
- imm32
;
6876 // R[t] = ZeroExtend(MemU[address,1], 32);
6877 EmulateInstruction::Context context
;
6878 context
.type
= eContextRelativeBranchImmediate
;
6879 context
.SetImmediate(address
- base
);
6881 uint64_t data
= MemURead(context
, address
, 1, 0, &success
);
6885 if (!WriteRegisterUnsigned(context
, eRegisterKindDWARF
, dwarf_r0
+ t
, data
))
6891 // LDRB (register) calculates an address from a base register value and an
6892 // offset rigister value, loads a byte from memory, zero-extends it to form a
6893 // 32-bit word, and writes it to a register. The offset register value can
6894 // optionally be shifted.
6895 bool EmulateInstructionARM::EmulateLDRBRegister(const uint32_t opcode
,
6896 const ARMEncoding encoding
) {
6898 if ConditionPassed() then
6899 EncodingSpecificOperations(); NullCheckIfThumbEE(n
);
6900 offset
= Shift(R
[m
], shift_t
, shift_n
, APSR
.C
);
6901 offset_addr
= if add
then (R
[n
] + offset
) else (R
[n
] - offset
);
6902 address
= if index then offset_addr
else R
[n
];
6903 R
[t
] = ZeroExtend(MemU
[address
,1],32);
6904 if wback then R
[n
] = offset_addr
;
6907 bool success
= false;
6909 if (ConditionPassed(opcode
)) {
6916 ARM_ShifterType shift_t
;
6919 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
6922 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
6923 t
= Bits32(opcode
, 2, 0);
6924 n
= Bits32(opcode
, 5, 3);
6925 m
= Bits32(opcode
, 8, 6);
6927 // index = TRUE; add = TRUE; wback = FALSE;
6932 // (shift_t, shift_n) = (SRType_LSL, 0);
6933 shift_t
= SRType_LSL
;
6938 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
6939 t
= Bits32(opcode
, 15, 12);
6940 n
= Bits32(opcode
, 19, 16);
6941 m
= Bits32(opcode
, 3, 0);
6943 // index = TRUE; add = TRUE; wback = FALSE;
6948 // (shift_t, shift_n) = (SRType_LSL, UInt(imm2));
6949 shift_t
= SRType_LSL
;
6950 shift_n
= Bits32(opcode
, 5, 4);
6952 // if Rt == '1111' then SEE PLD;
6954 return false; // PLD is not implemented yet
6956 // if Rn == '1111' then SEE LDRB (literal);
6958 return EmulateLDRBLiteral(opcode
, eEncodingT1
);
6960 // if t == 13 || BadReg(m) then UNPREDICTABLE;
6961 if ((t
== 13) || BadReg(m
))
6966 // if P == '0' && W == '1' then SEE LDRBT;
6967 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
6968 t
= Bits32(opcode
, 15, 12);
6969 n
= Bits32(opcode
, 19, 16);
6970 m
= Bits32(opcode
, 3, 0);
6972 // index = (P == '1'); add = (U == '1'); wback = (P == '0') ||
6974 index
= BitIsSet(opcode
, 24);
6975 add
= BitIsSet(opcode
, 23);
6976 wback
= (BitIsClear(opcode
, 24) || BitIsSet(opcode
, 21));
6978 // (shift_t, shift_n) = DecodeImmShift(type, imm5);
6979 uint32_t type
= Bits32(opcode
, 6, 5);
6980 uint32_t imm5
= Bits32(opcode
, 11, 7);
6981 shift_n
= DecodeImmShift(type
, imm5
, shift_t
);
6983 // if t == 15 || m == 15 then UNPREDICTABLE;
6984 if ((t
== 15) || (m
== 15))
6987 // if wback && (n == 15 || n == t) then UNPREDICTABLE;
6988 if (wback
&& ((n
== 15) || (n
== t
)))
6999 // offset = Shift(R[m], shift_t, shift_n, APSR.C);
7001 ReadRegisterUnsigned(eRegisterKindDWARF
, dwarf_r0
+ m
, 0, &success
);
7005 addr_t offset
= Shift(Rm
, shift_t
, shift_n
, APSR_C
, &success
);
7009 // offset_addr = if add then (R[n] + offset) else (R[n] - offset);
7011 ReadRegisterUnsigned(eRegisterKindDWARF
, dwarf_r0
+ n
, 0, &success
);
7016 offset_addr
= Rn
+ offset
;
7018 offset_addr
= Rn
- offset
;
7020 // address = if index then offset_addr else R[n];
7022 address
= offset_addr
;
7026 // R[t] = ZeroExtend(MemU[address,1],32);
7027 std::optional
<RegisterInfo
> base_reg
=
7028 GetRegisterInfo(eRegisterKindDWARF
, dwarf_r0
+ n
);
7030 EmulateInstruction::Context context
;
7031 context
.type
= eContextRegisterLoad
;
7032 context
.SetRegisterPlusOffset(*base_reg
, address
- Rn
);
7034 uint64_t data
= MemURead(context
, address
, 1, 0, &success
);
7038 if (!WriteRegisterUnsigned(context
, eRegisterKindDWARF
, dwarf_r0
+ t
, data
))
7041 // if wback then R[n] = offset_addr;
7043 context
.type
= eContextAdjustBaseRegister
;
7044 context
.SetAddress(offset_addr
);
7045 if (!WriteRegisterUnsigned(context
, eRegisterKindDWARF
, dwarf_r0
+ n
,
7053 // LDRH (immediate, Thumb) calculates an address from a base register value and
7054 // an immediate offset, loads a
7055 // halfword from memory, zero-extends it to form a 32-bit word, and writes it
7056 // to a register. It can use offset, post-indexed, or pre-indexed addressing.
7057 bool EmulateInstructionARM::EmulateLDRHImmediate(const uint32_t opcode
,
7058 const ARMEncoding encoding
) {
7060 if ConditionPassed() then
7061 EncodingSpecificOperations(); NullCheckIfThumbEE(n
);
7062 offset_addr
= if add
then (R
[n
] + imm32
) else (R
[n
] - imm32
);
7063 address
= if index then offset_addr
else R
[n
];
7064 data
= MemU
[address
,2];
7065 if wback then R
[n
] = offset_addr
;
7066 if UnalignedSupport() || address
<0> = '0' then
7067 R
[t
] = ZeroExtend(data
, 32);
7068 else // Can only apply before ARMv7
7069 R
[t
] = bits(32) UNKNOWN
;
7072 bool success
= false;
7074 if (ConditionPassed(opcode
)) {
7082 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
7085 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm5:'0', 32);
7086 t
= Bits32(opcode
, 2, 0);
7087 n
= Bits32(opcode
, 5, 3);
7088 imm32
= Bits32(opcode
, 10, 6) << 1;
7090 // index = TRUE; add = TRUE; wback = FALSE;
7098 // if Rt == '1111' then SEE "Unallocated memory hints";
7099 // if Rn == '1111' then SEE LDRH (literal);
7100 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
7101 t
= Bits32(opcode
, 15, 12);
7102 n
= Bits32(opcode
, 19, 16);
7103 imm32
= Bits32(opcode
, 11, 0);
7105 // index = TRUE; add = TRUE; wback = FALSE;
7110 // if t == 13 then UNPREDICTABLE;
7116 // if Rn == '1111' then SEE LDRH (literal);
7117 // if Rt == '1111' && P == '1' && U == '0' && W == '0' then SEE
7118 // "Unallocated memory hints";
7119 // if P == '1' && U == '1' && W == '0' then SEE LDRHT;
7120 // if P == '0' && W == '0' then UNDEFINED;
7121 if (BitIsClear(opcode
, 10) && BitIsClear(opcode
, 8))
7124 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32);
7125 t
= Bits32(opcode
, 15, 12);
7126 n
= Bits32(opcode
, 19, 16);
7127 imm32
= Bits32(opcode
, 7, 0);
7129 // index = (P == '1'); add = (U == '1'); wback = (W == '1');
7130 index
= BitIsSet(opcode
, 10);
7131 add
= BitIsSet(opcode
, 9);
7132 wback
= BitIsSet(opcode
, 8);
7134 // if BadReg(t) || (wback && n == t) then UNPREDICTABLE;
7135 if (BadReg(t
) || (wback
&& (n
== t
)))
7143 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
7145 ReadRegisterUnsigned(eRegisterKindDWARF
, dwarf_r0
+ n
, 0, &success
);
7153 offset_addr
= Rn
+ imm32
;
7155 offset_addr
= Rn
- imm32
;
7157 // address = if index then offset_addr else R[n];
7159 address
= offset_addr
;
7163 // data = MemU[address,2];
7164 std::optional
<RegisterInfo
> base_reg
=
7165 GetRegisterInfo(eRegisterKindDWARF
, dwarf_r0
+ n
);
7167 EmulateInstruction::Context context
;
7168 context
.type
= eContextRegisterLoad
;
7169 context
.SetRegisterPlusOffset(*base_reg
, address
- Rn
);
7171 uint64_t data
= MemURead(context
, address
, 2, 0, &success
);
7175 // if wback then R[n] = offset_addr;
7177 context
.type
= eContextAdjustBaseRegister
;
7178 context
.SetAddress(offset_addr
);
7179 if (!WriteRegisterUnsigned(context
, eRegisterKindDWARF
, dwarf_r0
+ n
,
7184 // if UnalignedSupport() || address<0> = '0' then
7185 if (UnalignedSupport() || BitIsClear(address
, 0)) {
7186 // R[t] = ZeroExtend(data, 32);
7187 context
.type
= eContextRegisterLoad
;
7188 context
.SetRegisterPlusOffset(*base_reg
, address
- Rn
);
7189 if (!WriteRegisterUnsigned(context
, eRegisterKindDWARF
, dwarf_r0
+ t
,
7192 } else // Can only apply before ARMv7
7194 // R[t] = bits(32) UNKNOWN;
7195 WriteBits32Unknown(t
);
7201 // LDRH (literal) calculates an address from the PC value and an immediate
7202 // offset, loads a halfword from memory,
7203 // zero-extends it to form a 32-bit word, and writes it to a register.
7204 bool EmulateInstructionARM::EmulateLDRHLiteral(const uint32_t opcode
,
7205 const ARMEncoding encoding
) {
7207 if ConditionPassed() then
7208 EncodingSpecificOperations(); NullCheckIfThumbEE(15);
7210 address
= if add
then (base
+ imm32
) else (base
- imm32
);
7211 data
= MemU
[address
,2];
7212 if UnalignedSupport() || address
<0> = '0' then
7213 R
[t
] = ZeroExtend(data
, 32);
7214 else // Can only apply before ARMv7
7215 R
[t
] = bits(32) UNKNOWN
;
7218 bool success
= false;
7220 if (ConditionPassed(opcode
)) {
7225 // EncodingSpecificOperations(); NullCheckIfThumbEE(15);
7228 // if Rt == '1111' then SEE "Unallocated memory hints";
7229 // t = UInt(Rt); imm32 = ZeroExtend(imm12, 32); add = (U == '1');
7230 t
= Bits32(opcode
, 15, 12);
7231 imm32
= Bits32(opcode
, 11, 0);
7232 add
= BitIsSet(opcode
, 23);
7234 // if t == 13 then UNPREDICTABLE;
7241 uint32_t imm4H
= Bits32(opcode
, 11, 8);
7242 uint32_t imm4L
= Bits32(opcode
, 3, 0);
7244 // t == UInt(Rt); imm32 = ZeroExtend(imm4H:imm4L, 32); add = (U == '1');
7245 t
= Bits32(opcode
, 15, 12);
7246 imm32
= (imm4H
<< 4) | imm4L
;
7247 add
= BitIsSet(opcode
, 23);
7249 // if t == 15 then UNPREDICTABLE;
7259 // base = Align(PC,4);
7260 uint64_t pc_value
= ReadCoreReg(PC_REG
, &success
);
7264 addr_t base
= AlignPC(pc_value
);
7267 // address = if add then (base + imm32) else (base - imm32);
7269 address
= base
+ imm32
;
7271 address
= base
- imm32
;
7273 // data = MemU[address,2];
7274 std::optional
<RegisterInfo
> base_reg
=
7275 GetRegisterInfo(eRegisterKindGeneric
, LLDB_REGNUM_GENERIC_PC
);
7277 EmulateInstruction::Context context
;
7278 context
.type
= eContextRegisterLoad
;
7279 context
.SetRegisterPlusOffset(*base_reg
, address
- base
);
7281 uint64_t data
= MemURead(context
, address
, 2, 0, &success
);
7285 // if UnalignedSupport() || address<0> = '0' then
7286 if (UnalignedSupport() || BitIsClear(address
, 0)) {
7287 // R[t] = ZeroExtend(data, 32);
7288 context
.type
= eContextRegisterLoad
;
7289 context
.SetRegisterPlusOffset(*base_reg
, address
- base
);
7290 if (!WriteRegisterUnsigned(context
, eRegisterKindDWARF
, dwarf_r0
+ t
,
7294 } else // Can only apply before ARMv7
7296 // R[t] = bits(32) UNKNOWN;
7297 WriteBits32Unknown(t
);
7303 // LDRH (literal) calculates an address from a base register value and an offset
7304 // register value, loads a halfword
7305 // from memory, zero-extends it to form a 32-bit word, and writes it to a
7306 // register. The offset register value can be shifted left by 0, 1, 2, or 3
7308 bool EmulateInstructionARM::EmulateLDRHRegister(const uint32_t opcode
,
7309 const ARMEncoding encoding
) {
7311 if ConditionPassed() then
7312 EncodingSpecificOperations(); NullCheckIfThumbEE(n
);
7313 offset
= Shift(R
[m
], shift_t
, shift_n
, APSR
.C
);
7314 offset_addr
= if add
then (R
[n
] + offset
) else (R
[n
] - offset
);
7315 address
= if index then offset_addr
else R
[n
];
7316 data
= MemU
[address
,2];
7317 if wback then R
[n
] = offset_addr
;
7318 if UnalignedSupport() || address
<0> = '0' then
7319 R
[t
] = ZeroExtend(data
, 32);
7320 else // Can only apply before ARMv7
7321 R
[t
] = bits(32) UNKNOWN
;
7324 bool success
= false;
7326 if (ConditionPassed(opcode
)) {
7333 ARM_ShifterType shift_t
;
7336 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
7339 // if CurrentInstrSet() == InstrSet_ThumbEE then SEE "Modified operation
7341 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
7342 t
= Bits32(opcode
, 2, 0);
7343 n
= Bits32(opcode
, 5, 3);
7344 m
= Bits32(opcode
, 8, 6);
7346 // index = TRUE; add = TRUE; wback = FALSE;
7351 // (shift_t, shift_n) = (SRType_LSL, 0);
7352 shift_t
= SRType_LSL
;
7358 // if Rn == '1111' then SEE LDRH (literal);
7359 // if Rt == '1111' then SEE "Unallocated memory hints";
7360 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
7361 t
= Bits32(opcode
, 15, 12);
7362 n
= Bits32(opcode
, 19, 16);
7363 m
= Bits32(opcode
, 3, 0);
7365 // index = TRUE; add = TRUE; wback = FALSE;
7370 // (shift_t, shift_n) = (SRType_LSL, UInt(imm2));
7371 shift_t
= SRType_LSL
;
7372 shift_n
= Bits32(opcode
, 5, 4);
7374 // if t == 13 || BadReg(m) then UNPREDICTABLE;
7375 if ((t
== 13) || BadReg(m
))
7380 // if P == '0' && W == '1' then SEE LDRHT;
7381 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
7382 t
= Bits32(opcode
, 15, 12);
7383 n
= Bits32(opcode
, 19, 16);
7384 m
= Bits32(opcode
, 3, 0);
7386 // index = (P == '1'); add = (U == '1'); wback = (P == '0') ||
7388 index
= BitIsSet(opcode
, 24);
7389 add
= BitIsSet(opcode
, 23);
7390 wback
= (BitIsClear(opcode
, 24) || BitIsSet(opcode
, 21));
7392 // (shift_t, shift_n) = (SRType_LSL, 0);
7393 shift_t
= SRType_LSL
;
7396 // if t == 15 || m == 15 then UNPREDICTABLE;
7397 if ((t
== 15) || (m
== 15))
7400 // if wback && (n == 15 || n == t) then UNPREDICTABLE;
7401 if (wback
&& ((n
== 15) || (n
== t
)))
7410 // offset = Shift(R[m], shift_t, shift_n, APSR.C);
7413 ReadRegisterUnsigned(eRegisterKindDWARF
, dwarf_r0
+ m
, 0, &success
);
7417 addr_t offset
= Shift(Rm
, shift_t
, shift_n
, APSR_C
, &success
);
7424 // offset_addr = if add then (R[n] + offset) else (R[n] - offset);
7426 ReadRegisterUnsigned(eRegisterKindDWARF
, dwarf_r0
+ n
, 0, &success
);
7431 offset_addr
= Rn
+ offset
;
7433 offset_addr
= Rn
- offset
;
7435 // address = if index then offset_addr else R[n];
7437 address
= offset_addr
;
7441 // data = MemU[address,2];
7442 std::optional
<RegisterInfo
> base_reg
=
7443 GetRegisterInfo(eRegisterKindDWARF
, dwarf_r0
+ n
);
7444 std::optional
<RegisterInfo
> offset_reg
=
7445 GetRegisterInfo(eRegisterKindDWARF
, dwarf_r0
+ m
);
7447 EmulateInstruction::Context context
;
7448 context
.type
= eContextRegisterLoad
;
7449 context
.SetRegisterPlusIndirectOffset(*base_reg
, *offset_reg
);
7450 uint64_t data
= MemURead(context
, address
, 2, 0, &success
);
7454 // if wback then R[n] = offset_addr;
7456 context
.type
= eContextAdjustBaseRegister
;
7457 context
.SetAddress(offset_addr
);
7458 if (!WriteRegisterUnsigned(context
, eRegisterKindDWARF
, dwarf_r0
+ n
,
7463 // if UnalignedSupport() || address<0> = '0' then
7464 if (UnalignedSupport() || BitIsClear(address
, 0)) {
7465 // R[t] = ZeroExtend(data, 32);
7466 context
.type
= eContextRegisterLoad
;
7467 context
.SetRegisterPlusIndirectOffset(*base_reg
, *offset_reg
);
7468 if (!WriteRegisterUnsigned(context
, eRegisterKindDWARF
, dwarf_r0
+ t
,
7471 } else // Can only apply before ARMv7
7473 // R[t] = bits(32) UNKNOWN;
7474 WriteBits32Unknown(t
);
7480 // LDRSB (immediate) calculates an address from a base register value and an
7481 // immediate offset, loads a byte from
7482 // memory, sign-extends it to form a 32-bit word, and writes it to a register.
7483 // It can use offset, post-indexed, or pre-indexed addressing.
7484 bool EmulateInstructionARM::EmulateLDRSBImmediate(const uint32_t opcode
,
7485 const ARMEncoding encoding
) {
7487 if ConditionPassed() then
7488 EncodingSpecificOperations(); NullCheckIfThumbEE(n
);
7489 offset_addr
= if add
then (R
[n
] + imm32
) else (R
[n
] - imm32
);
7490 address
= if index then offset_addr
else R
[n
];
7491 R
[t
] = SignExtend(MemU
[address
,1], 32);
7492 if wback then R
[n
] = offset_addr
;
7495 bool success
= false;
7497 if (ConditionPassed(opcode
)) {
7505 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
7508 // if Rt == '1111' then SEE PLI;
7509 // if Rn == '1111' then SEE LDRSB (literal);
7510 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
7511 t
= Bits32(opcode
, 15, 12);
7512 n
= Bits32(opcode
, 19, 16);
7513 imm32
= Bits32(opcode
, 11, 0);
7515 // index = TRUE; add = TRUE; wback = FALSE;
7520 // if t == 13 then UNPREDICTABLE;
7527 // if Rt == '1111' && P == '1' && U == '0' && W == '0' then SEE PLI;
7528 // if Rn == '1111' then SEE LDRSB (literal);
7529 // if P == '1' && U == '1' && W == '0' then SEE LDRSBT;
7530 // if P == '0' && W == '0' then UNDEFINED;
7531 if (BitIsClear(opcode
, 10) && BitIsClear(opcode
, 8))
7534 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32);
7535 t
= Bits32(opcode
, 15, 12);
7536 n
= Bits32(opcode
, 19, 16);
7537 imm32
= Bits32(opcode
, 7, 0);
7539 // index = (P == '1'); add = (U == '1'); wback = (W == '1');
7540 index
= BitIsSet(opcode
, 10);
7541 add
= BitIsSet(opcode
, 9);
7542 wback
= BitIsSet(opcode
, 8);
7544 // if BadReg(t) || (wback && n == t) then UNPREDICTABLE;
7546 ((t
== 15) && (BitIsClear(opcode
, 10) || BitIsSet(opcode
, 9) ||
7547 BitIsSet(opcode
, 8)))) ||
7548 (wback
&& (n
== t
)))
7554 // if Rn == '1111' then SEE LDRSB (literal);
7555 // if P == '0' && W == '1' then SEE LDRSBT;
7556 // t == UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm4H:imm4L, 32);
7557 t
= Bits32(opcode
, 15, 12);
7558 n
= Bits32(opcode
, 19, 16);
7560 uint32_t imm4H
= Bits32(opcode
, 11, 8);
7561 uint32_t imm4L
= Bits32(opcode
, 3, 0);
7562 imm32
= (imm4H
<< 4) | imm4L
;
7564 // index = (P == '1'); add = (U == '1'); wback = (P == '0') ||
7566 index
= BitIsSet(opcode
, 24);
7567 add
= BitIsSet(opcode
, 23);
7568 wback
= (BitIsClear(opcode
, 24) || BitIsSet(opcode
, 21));
7570 // if t == 15 || (wback && n == t) then UNPREDICTABLE;
7571 if ((t
== 15) || (wback
&& (n
== t
)))
7581 uint64_t Rn
= ReadCoreReg(n
, &success
);
7588 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
7590 offset_addr
= Rn
+ imm32
;
7592 offset_addr
= Rn
- imm32
;
7594 // address = if index then offset_addr else R[n];
7596 address
= offset_addr
;
7600 // R[t] = SignExtend(MemU[address,1], 32);
7601 std::optional
<RegisterInfo
> base_reg
=
7602 GetRegisterInfo(eRegisterKindDWARF
, dwarf_r0
+ n
);
7604 EmulateInstruction::Context context
;
7605 context
.type
= eContextRegisterLoad
;
7606 context
.SetRegisterPlusOffset(*base_reg
, address
- Rn
);
7608 uint64_t unsigned_data
= MemURead(context
, address
, 1, 0, &success
);
7612 int64_t signed_data
= llvm::SignExtend64
<8>(unsigned_data
);
7613 if (!WriteRegisterUnsigned(context
, eRegisterKindDWARF
, dwarf_r0
+ t
,
7614 (uint64_t)signed_data
))
7617 // if wback then R[n] = offset_addr;
7619 context
.type
= eContextAdjustBaseRegister
;
7620 context
.SetAddress(offset_addr
);
7621 if (!WriteRegisterUnsigned(context
, eRegisterKindDWARF
, dwarf_r0
+ n
,
7630 // LDRSB (literal) calculates an address from the PC value and an immediate
7631 // offset, loads a byte from memory,
7632 // sign-extends it to form a 32-bit word, and writes tit to a register.
7633 bool EmulateInstructionARM::EmulateLDRSBLiteral(const uint32_t opcode
,
7634 const ARMEncoding encoding
) {
7636 if ConditionPassed() then
7637 EncodingSpecificOperations(); NullCheckIfThumbEE(15);
7639 address
= if add
then (base
+ imm32
) else (base
- imm32
);
7640 R
[t
] = SignExtend(MemU
[address
,1], 32);
7643 bool success
= false;
7645 if (ConditionPassed(opcode
)) {
7650 // EncodingSpecificOperations(); NullCheckIfThumbEE(15);
7653 // if Rt == '1111' then SEE PLI;
7654 // t = UInt(Rt); imm32 = ZeroExtend(imm12, 32); add = (U == '1');
7655 t
= Bits32(opcode
, 15, 12);
7656 imm32
= Bits32(opcode
, 11, 0);
7657 add
= BitIsSet(opcode
, 23);
7659 // if t == 13 then UNPREDICTABLE;
7666 // t == UInt(Rt); imm32 = ZeroExtend(imm4H:imm4L, 32); add = (U == '1');
7667 t
= Bits32(opcode
, 15, 12);
7668 uint32_t imm4H
= Bits32(opcode
, 11, 8);
7669 uint32_t imm4L
= Bits32(opcode
, 3, 0);
7670 imm32
= (imm4H
<< 4) | imm4L
;
7671 add
= BitIsSet(opcode
, 23);
7673 // if t == 15 then UNPREDICTABLE;
7684 // base = Align(PC,4);
7685 uint64_t pc_value
= ReadCoreReg(PC_REG
, &success
);
7688 uint64_t base
= AlignPC(pc_value
);
7690 // address = if add then (base + imm32) else (base - imm32);
7693 address
= base
+ imm32
;
7695 address
= base
- imm32
;
7697 // R[t] = SignExtend(MemU[address,1], 32);
7698 std::optional
<RegisterInfo
> base_reg
=
7699 GetRegisterInfo(eRegisterKindGeneric
, LLDB_REGNUM_GENERIC_PC
);
7701 EmulateInstruction::Context context
;
7702 context
.type
= eContextRegisterLoad
;
7703 context
.SetRegisterPlusOffset(*base_reg
, address
- base
);
7705 uint64_t unsigned_data
= MemURead(context
, address
, 1, 0, &success
);
7709 int64_t signed_data
= llvm::SignExtend64
<8>(unsigned_data
);
7710 if (!WriteRegisterUnsigned(context
, eRegisterKindDWARF
, dwarf_r0
+ t
,
7711 (uint64_t)signed_data
))
7717 // LDRSB (register) calculates an address from a base register value and an
7718 // offset register value, loadsa byte from
7719 // memory, sign-extends it to form a 32-bit word, and writes it to a register.
7720 // The offset register value can be shifted left by 0, 1, 2, or 3 bits.
7721 bool EmulateInstructionARM::EmulateLDRSBRegister(const uint32_t opcode
,
7722 const ARMEncoding encoding
) {
7724 if ConditionPassed() then
7725 EncodingSpecificOperations(); NullCheckIfThumbEE(n
);
7726 offset
= Shift(R
[m
], shift_t
, shift_n
, APSR
.C
);
7727 offset_addr
= if add
then (R
[n
] + offset
) else (R
[n
] - offset
);
7728 address
= if index then offset_addr
else R
[n
];
7729 R
[t
] = SignExtend(MemU
[address
,1], 32);
7730 if wback then R
[n
] = offset_addr
;
7733 bool success
= false;
7735 if (ConditionPassed(opcode
)) {
7742 ARM_ShifterType shift_t
;
7745 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
7748 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
7749 t
= Bits32(opcode
, 2, 0);
7750 n
= Bits32(opcode
, 5, 3);
7751 m
= Bits32(opcode
, 8, 6);
7753 // index = TRUE; add = TRUE; wback = FALSE;
7758 // (shift_t, shift_n) = (SRType_LSL, 0);
7759 shift_t
= SRType_LSL
;
7765 // if Rt == '1111' then SEE PLI;
7766 // if Rn == '1111' then SEE LDRSB (literal);
7767 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
7768 t
= Bits32(opcode
, 15, 12);
7769 n
= Bits32(opcode
, 19, 16);
7770 m
= Bits32(opcode
, 3, 0);
7772 // index = TRUE; add = TRUE; wback = FALSE;
7777 // (shift_t, shift_n) = (SRType_LSL, UInt(imm2));
7778 shift_t
= SRType_LSL
;
7779 shift_n
= Bits32(opcode
, 5, 4);
7781 // if t == 13 || BadReg(m) then UNPREDICTABLE;
7782 if ((t
== 13) || BadReg(m
))
7787 // if P == '0' && W == '1' then SEE LDRSBT;
7788 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
7789 t
= Bits32(opcode
, 15, 12);
7790 n
= Bits32(opcode
, 19, 16);
7791 m
= Bits32(opcode
, 3, 0);
7793 // index = (P == '1'); add = (U == '1'); wback = (P == '0') ||
7795 index
= BitIsSet(opcode
, 24);
7796 add
= BitIsSet(opcode
, 23);
7797 wback
= BitIsClear(opcode
, 24) || BitIsSet(opcode
, 21);
7799 // (shift_t, shift_n) = (SRType_LSL, 0);
7800 shift_t
= SRType_LSL
;
7803 // if t == 15 || m == 15 then UNPREDICTABLE;
7804 if ((t
== 15) || (m
== 15))
7807 // if wback && (n == 15 || n == t) then UNPREDICTABLE;
7808 if (wback
&& ((n
== 15) || (n
== t
)))
7817 ReadRegisterUnsigned(eRegisterKindDWARF
, dwarf_r0
+ m
, 0, &success
);
7821 // offset = Shift(R[m], shift_t, shift_n, APSR.C);
7822 addr_t offset
= Shift(Rm
, shift_t
, shift_n
, APSR_C
, &success
);
7829 // offset_addr = if add then (R[n] + offset) else (R[n] - offset);
7831 ReadRegisterUnsigned(eRegisterKindDWARF
, dwarf_r0
+ n
, 0, &success
);
7836 offset_addr
= Rn
+ offset
;
7838 offset_addr
= Rn
- offset
;
7840 // address = if index then offset_addr else R[n];
7842 address
= offset_addr
;
7846 // R[t] = SignExtend(MemU[address,1], 32);
7847 std::optional
<RegisterInfo
> base_reg
=
7848 GetRegisterInfo(eRegisterKindDWARF
, dwarf_r0
+ n
);
7849 std::optional
<RegisterInfo
> offset_reg
=
7850 GetRegisterInfo(eRegisterKindDWARF
, dwarf_r0
+ m
);
7852 EmulateInstruction::Context context
;
7853 context
.type
= eContextRegisterLoad
;
7854 context
.SetRegisterPlusIndirectOffset(*base_reg
, *offset_reg
);
7856 uint64_t unsigned_data
= MemURead(context
, address
, 1, 0, &success
);
7860 int64_t signed_data
= llvm::SignExtend64
<8>(unsigned_data
);
7861 if (!WriteRegisterUnsigned(context
, eRegisterKindDWARF
, dwarf_r0
+ t
,
7862 (uint64_t)signed_data
))
7865 // if wback then R[n] = offset_addr;
7867 context
.type
= eContextAdjustBaseRegister
;
7868 context
.SetAddress(offset_addr
);
7869 if (!WriteRegisterUnsigned(context
, eRegisterKindDWARF
, dwarf_r0
+ n
,
7877 // LDRSH (immediate) calculates an address from a base register value and an
7878 // immediate offset, loads a halfword from
7879 // memory, sign-extends it to form a 32-bit word, and writes it to a register.
7880 // It can use offset, post-indexed, or pre-indexed addressing.
7881 bool EmulateInstructionARM::EmulateLDRSHImmediate(const uint32_t opcode
,
7882 const ARMEncoding encoding
) {
7884 if ConditionPassed() then
7885 EncodingSpecificOperations(); NullCheckIfThumbEE(n
);
7886 offset_addr
= if add
then (R
[n
] + imm32
) else (R
[n
] - imm32
);
7887 address
= if index then offset_addr
else R
[n
];
7888 data
= MemU
[address
,2];
7889 if wback then R
[n
] = offset_addr
;
7890 if UnalignedSupport() || address
<0> = '0' then
7891 R
[t
] = SignExtend(data
, 32);
7892 else // Can only apply before ARMv7
7893 R
[t
] = bits(32) UNKNOWN
;
7896 bool success
= false;
7898 if (ConditionPassed(opcode
)) {
7906 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
7909 // if Rn == '1111' then SEE LDRSH (literal);
7910 // if Rt == '1111' then SEE "Unallocated memory hints";
7911 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
7912 t
= Bits32(opcode
, 15, 12);
7913 n
= Bits32(opcode
, 19, 16);
7914 imm32
= Bits32(opcode
, 11, 0);
7916 // index = TRUE; add = TRUE; wback = FALSE;
7921 // if t == 13 then UNPREDICTABLE;
7928 // if Rn == '1111' then SEE LDRSH (literal);
7929 // if Rt == '1111' && P == '1' && U == '0' && W == '0' then SEE
7930 // "Unallocated memory hints";
7931 // if P == '1' && U == '1' && W == '0' then SEE LDRSHT;
7932 // if P == '0' && W == '0' then UNDEFINED;
7933 if (BitIsClear(opcode
, 10) && BitIsClear(opcode
, 8))
7936 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32);
7937 t
= Bits32(opcode
, 15, 12);
7938 n
= Bits32(opcode
, 19, 16);
7939 imm32
= Bits32(opcode
, 7, 0);
7941 // index = (P == '1'); add = (U == '1'); wback = (W == '1');
7942 index
= BitIsSet(opcode
, 10);
7943 add
= BitIsSet(opcode
, 9);
7944 wback
= BitIsSet(opcode
, 8);
7946 // if BadReg(t) || (wback && n == t) then UNPREDICTABLE;
7947 if (BadReg(t
) || (wback
&& (n
== t
)))
7953 // if Rn == '1111' then SEE LDRSH (literal);
7954 // if P == '0' && W == '1' then SEE LDRSHT;
7955 // t == UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm4H:imm4L, 32);
7956 t
= Bits32(opcode
, 15, 12);
7957 n
= Bits32(opcode
, 19, 16);
7958 uint32_t imm4H
= Bits32(opcode
, 11, 8);
7959 uint32_t imm4L
= Bits32(opcode
, 3, 0);
7960 imm32
= (imm4H
<< 4) | imm4L
;
7962 // index = (P == '1'); add = (U == '1'); wback = (P == '0') ||
7964 index
= BitIsSet(opcode
, 24);
7965 add
= BitIsSet(opcode
, 23);
7966 wback
= BitIsClear(opcode
, 24) || BitIsSet(opcode
, 21);
7968 // if t == 15 || (wback && n == t) then UNPREDICTABLE;
7969 if ((t
== 15) || (wback
&& (n
== t
)))
7979 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
7981 ReadRegisterUnsigned(eRegisterKindDWARF
, dwarf_r0
+ n
, 0, &success
);
7987 offset_addr
= Rn
+ imm32
;
7989 offset_addr
= Rn
- imm32
;
7991 // address = if index then offset_addr else R[n];
7994 address
= offset_addr
;
7998 // data = MemU[address,2];
7999 std::optional
<RegisterInfo
> base_reg
=
8000 GetRegisterInfo(eRegisterKindDWARF
, dwarf_r0
+ n
);
8002 EmulateInstruction::Context context
;
8003 context
.type
= eContextRegisterLoad
;
8004 context
.SetRegisterPlusOffset(*base_reg
, address
- Rn
);
8006 uint64_t data
= MemURead(context
, address
, 2, 0, &success
);
8010 // if wback then R[n] = offset_addr;
8012 context
.type
= eContextAdjustBaseRegister
;
8013 context
.SetAddress(offset_addr
);
8014 if (!WriteRegisterUnsigned(context
, eRegisterKindDWARF
, dwarf_r0
+ n
,
8019 // if UnalignedSupport() || address<0> = '0' then
8020 if (UnalignedSupport() || BitIsClear(address
, 0)) {
8021 // R[t] = SignExtend(data, 32);
8022 int64_t signed_data
= llvm::SignExtend64
<16>(data
);
8023 context
.type
= eContextRegisterLoad
;
8024 context
.SetRegisterPlusOffset(*base_reg
, address
- Rn
);
8025 if (!WriteRegisterUnsigned(context
, eRegisterKindDWARF
, dwarf_r0
+ t
,
8026 (uint64_t)signed_data
))
8028 } else // Can only apply before ARMv7
8030 // R[t] = bits(32) UNKNOWN;
8031 WriteBits32Unknown(t
);
8037 // LDRSH (literal) calculates an address from the PC value and an immediate
8038 // offset, loads a halfword from memory,
8039 // sign-extends it to from a 32-bit word, and writes it to a register.
8040 bool EmulateInstructionARM::EmulateLDRSHLiteral(const uint32_t opcode
,
8041 const ARMEncoding encoding
) {
8043 if ConditionPassed() then
8044 EncodingSpecificOperations(); NullCheckIfThumbEE(15);
8046 address
= if add
then (base
+ imm32
) else (base
- imm32
);
8047 data
= MemU
[address
,2];
8048 if UnalignedSupport() || address
<0> = '0' then
8049 R
[t
] = SignExtend(data
, 32);
8050 else // Can only apply before ARMv7
8051 R
[t
] = bits(32) UNKNOWN
;
8054 bool success
= false;
8056 if (ConditionPassed(opcode
)) {
8061 // EncodingSpecificOperations(); NullCheckIfThumbEE(15);
8064 // if Rt == '1111' then SEE "Unallocated memory hints";
8065 // t = UInt(Rt); imm32 = ZeroExtend(imm12, 32); add = (U == '1');
8066 t
= Bits32(opcode
, 15, 12);
8067 imm32
= Bits32(opcode
, 11, 0);
8068 add
= BitIsSet(opcode
, 23);
8070 // if t == 13 then UNPREDICTABLE;
8077 // t == UInt(Rt); imm32 = ZeroExtend(imm4H:imm4L, 32); add = (U == '1');
8078 t
= Bits32(opcode
, 15, 12);
8079 uint32_t imm4H
= Bits32(opcode
, 11, 8);
8080 uint32_t imm4L
= Bits32(opcode
, 3, 0);
8081 imm32
= (imm4H
<< 4) | imm4L
;
8082 add
= BitIsSet(opcode
, 23);
8084 // if t == 15 then UNPREDICTABLE;
8094 // base = Align(PC,4);
8095 uint64_t pc_value
= ReadCoreReg(PC_REG
, &success
);
8099 uint64_t base
= AlignPC(pc_value
);
8102 // address = if add then (base + imm32) else (base - imm32);
8104 address
= base
+ imm32
;
8106 address
= base
- imm32
;
8108 // data = MemU[address,2];
8109 std::optional
<RegisterInfo
> base_reg
=
8110 GetRegisterInfo(eRegisterKindGeneric
, LLDB_REGNUM_GENERIC_PC
);
8112 EmulateInstruction::Context context
;
8113 context
.type
= eContextRegisterLoad
;
8114 context
.SetRegisterPlusOffset(*base_reg
, imm32
);
8116 uint64_t data
= MemURead(context
, address
, 2, 0, &success
);
8120 // if UnalignedSupport() || address<0> = '0' then
8121 if (UnalignedSupport() || BitIsClear(address
, 0)) {
8122 // R[t] = SignExtend(data, 32);
8123 int64_t signed_data
= llvm::SignExtend64
<16>(data
);
8124 if (!WriteRegisterUnsigned(context
, eRegisterKindDWARF
, dwarf_r0
+ t
,
8125 (uint64_t)signed_data
))
8127 } else // Can only apply before ARMv7
8129 // R[t] = bits(32) UNKNOWN;
8130 WriteBits32Unknown(t
);
8136 // LDRSH (register) calculates an address from a base register value and an
8137 // offset register value, loads a halfword
8138 // from memory, sign-extends it to form a 32-bit word, and writes it to a
8139 // register. The offset register value can be shifted left by 0, 1, 2, or 3
8141 bool EmulateInstructionARM::EmulateLDRSHRegister(const uint32_t opcode
,
8142 const ARMEncoding encoding
) {
8144 if ConditionPassed() then
8145 EncodingSpecificOperations(); NullCheckIfThumbEE(n
);
8146 offset
= Shift(R
[m
], shift_t
, shift_n
, APSR
.C
);
8147 offset_addr
= if add
then (R
[n
] + offset
) else (R
[n
] - offset
);
8148 address
= if index then offset_addr
else R
[n
];
8149 data
= MemU
[address
,2];
8150 if wback then R
[n
] = offset_addr
;
8151 if UnalignedSupport() || address
<0> = '0' then
8152 R
[t
] = SignExtend(data
, 32);
8153 else // Can only apply before ARMv7
8154 R
[t
] = bits(32) UNKNOWN
;
8157 bool success
= false;
8159 if (ConditionPassed(opcode
)) {
8166 ARM_ShifterType shift_t
;
8169 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
8172 // if CurrentInstrSet() == InstrSet_ThumbEE then SEE "Modified operation
8174 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
8175 t
= Bits32(opcode
, 2, 0);
8176 n
= Bits32(opcode
, 5, 3);
8177 m
= Bits32(opcode
, 8, 6);
8179 // index = TRUE; add = TRUE; wback = FALSE;
8184 // (shift_t, shift_n) = (SRType_LSL, 0);
8185 shift_t
= SRType_LSL
;
8191 // if Rn == '1111' then SEE LDRSH (literal);
8192 // if Rt == '1111' then SEE "Unallocated memory hints";
8193 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
8194 t
= Bits32(opcode
, 15, 12);
8195 n
= Bits32(opcode
, 19, 16);
8196 m
= Bits32(opcode
, 3, 0);
8198 // index = TRUE; add = TRUE; wback = FALSE;
8203 // (shift_t, shift_n) = (SRType_LSL, UInt(imm2));
8204 shift_t
= SRType_LSL
;
8205 shift_n
= Bits32(opcode
, 5, 4);
8207 // if t == 13 || BadReg(m) then UNPREDICTABLE;
8208 if ((t
== 13) || BadReg(m
))
8214 // if P == '0' && W == '1' then SEE LDRSHT;
8215 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
8216 t
= Bits32(opcode
, 15, 12);
8217 n
= Bits32(opcode
, 19, 16);
8218 m
= Bits32(opcode
, 3, 0);
8220 // index = (P == '1'); add = (U == '1'); wback = (P == '0') ||
8222 index
= BitIsSet(opcode
, 24);
8223 add
= BitIsSet(opcode
, 23);
8224 wback
= BitIsClear(opcode
, 24) || BitIsSet(opcode
, 21);
8226 // (shift_t, shift_n) = (SRType_LSL, 0);
8227 shift_t
= SRType_LSL
;
8230 // if t == 15 || m == 15 then UNPREDICTABLE;
8231 if ((t
== 15) || (m
== 15))
8234 // if wback && (n == 15 || n == t) then UNPREDICTABLE;
8235 if (wback
&& ((n
== 15) || (n
== t
)))
8245 ReadRegisterUnsigned(eRegisterKindDWARF
, dwarf_r0
+ m
, 0, &success
);
8250 ReadRegisterUnsigned(eRegisterKindDWARF
, dwarf_r0
+ n
, 0, &success
);
8254 // offset = Shift(R[m], shift_t, shift_n, APSR.C);
8255 addr_t offset
= Shift(Rm
, shift_t
, shift_n
, APSR_C
, &success
);
8262 // offset_addr = if add then (R[n] + offset) else (R[n] - offset);
8264 offset_addr
= Rn
+ offset
;
8266 offset_addr
= Rn
- offset
;
8268 // address = if index then offset_addr else R[n];
8270 address
= offset_addr
;
8274 // data = MemU[address,2];
8275 std::optional
<RegisterInfo
> base_reg
=
8276 GetRegisterInfo(eRegisterKindDWARF
, dwarf_r0
+ n
);
8277 std::optional
<RegisterInfo
> offset_reg
=
8278 GetRegisterInfo(eRegisterKindDWARF
, dwarf_r0
+ m
);
8280 EmulateInstruction::Context context
;
8281 context
.type
= eContextRegisterLoad
;
8282 context
.SetRegisterPlusIndirectOffset(*base_reg
, *offset_reg
);
8284 uint64_t data
= MemURead(context
, address
, 2, 0, &success
);
8288 // if wback then R[n] = offset_addr;
8290 context
.type
= eContextAdjustBaseRegister
;
8291 context
.SetAddress(offset_addr
);
8292 if (!WriteRegisterUnsigned(context
, eRegisterKindDWARF
, dwarf_r0
+ n
,
8297 // if UnalignedSupport() || address<0> = '0' then
8298 if (UnalignedSupport() || BitIsClear(address
, 0)) {
8299 // R[t] = SignExtend(data, 32);
8300 context
.type
= eContextRegisterLoad
;
8301 context
.SetRegisterPlusIndirectOffset(*base_reg
, *offset_reg
);
8303 int64_t signed_data
= llvm::SignExtend64
<16>(data
);
8304 if (!WriteRegisterUnsigned(context
, eRegisterKindDWARF
, dwarf_r0
+ t
,
8305 (uint64_t)signed_data
))
8307 } else // Can only apply before ARMv7
8309 // R[t] = bits(32) UNKNOWN;
8310 WriteBits32Unknown(t
);
8316 // SXTB extracts an 8-bit value from a register, sign-extends it to 32 bits, and
8317 // writes the result to the destination
8318 // register. You can specifiy a rotation by 0, 8, 16, or 24 bits before
8319 // extracting the 8-bit value.
8320 bool EmulateInstructionARM::EmulateSXTB(const uint32_t opcode
,
8321 const ARMEncoding encoding
) {
8323 if ConditionPassed() then
8324 EncodingSpecificOperations();
8325 rotated
= ROR(R
[m
], rotation
);
8326 R
[d
] = SignExtend(rotated
<7:0>, 32);
8329 bool success
= false;
8331 if (ConditionPassed(opcode
)) {
8336 // EncodingSpecificOperations();
8339 // d = UInt(Rd); m = UInt(Rm); rotation = 0;
8340 d
= Bits32(opcode
, 2, 0);
8341 m
= Bits32(opcode
, 5, 3);
8347 // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:'000');
8348 d
= Bits32(opcode
, 11, 8);
8349 m
= Bits32(opcode
, 3, 0);
8350 rotation
= Bits32(opcode
, 5, 4) << 3;
8352 // if BadReg(d) || BadReg(m) then UNPREDICTABLE;
8353 if (BadReg(d
) || BadReg(m
))
8359 // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:'000');
8360 d
= Bits32(opcode
, 15, 12);
8361 m
= Bits32(opcode
, 3, 0);
8362 rotation
= Bits32(opcode
, 11, 10) << 3;
8364 // if d == 15 || m == 15 then UNPREDICTABLE;
8365 if ((d
== 15) || (m
== 15))
8375 ReadRegisterUnsigned(eRegisterKindDWARF
, dwarf_r0
+ m
, 0, &success
);
8379 // rotated = ROR(R[m], rotation);
8380 uint64_t rotated
= ROR(Rm
, rotation
, &success
);
8384 // R[d] = SignExtend(rotated<7:0>, 32);
8385 int64_t data
= llvm::SignExtend64
<8>(rotated
);
8387 std::optional
<RegisterInfo
> source_reg
=
8388 GetRegisterInfo(eRegisterKindDWARF
, dwarf_r0
+ m
);
8390 EmulateInstruction::Context context
;
8391 context
.type
= eContextRegisterLoad
;
8392 context
.SetRegister(*source_reg
);
8394 if (!WriteRegisterUnsigned(context
, eRegisterKindDWARF
, dwarf_r0
+ d
,
8401 // SXTH extracts a 16-bit value from a register, sign-extends it to 32 bits, and
8402 // writes the result to the destination
8403 // register. You can specify a rotation by 0, 8, 16, or 24 bits before
8404 // extracting the 16-bit value.
8405 bool EmulateInstructionARM::EmulateSXTH(const uint32_t opcode
,
8406 const ARMEncoding encoding
) {
8408 if ConditionPassed() then
8409 EncodingSpecificOperations();
8410 rotated
= ROR(R
[m
], rotation
);
8411 R
[d
] = SignExtend(rotated
<15:0>, 32);
8414 bool success
= false;
8416 if (ConditionPassed(opcode
)) {
8421 // EncodingSpecificOperations();
8424 // d = UInt(Rd); m = UInt(Rm); rotation = 0;
8425 d
= Bits32(opcode
, 2, 0);
8426 m
= Bits32(opcode
, 5, 3);
8432 // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:'000');
8433 d
= Bits32(opcode
, 11, 8);
8434 m
= Bits32(opcode
, 3, 0);
8435 rotation
= Bits32(opcode
, 5, 4) << 3;
8437 // if BadReg(d) || BadReg(m) then UNPREDICTABLE;
8438 if (BadReg(d
) || BadReg(m
))
8444 // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:'000');
8445 d
= Bits32(opcode
, 15, 12);
8446 m
= Bits32(opcode
, 3, 0);
8447 rotation
= Bits32(opcode
, 11, 10) << 3;
8449 // if d == 15 || m == 15 then UNPREDICTABLE;
8450 if ((d
== 15) || (m
== 15))
8460 ReadRegisterUnsigned(eRegisterKindDWARF
, dwarf_r0
+ m
, 0, &success
);
8464 // rotated = ROR(R[m], rotation);
8465 uint64_t rotated
= ROR(Rm
, rotation
, &success
);
8469 // R[d] = SignExtend(rotated<15:0>, 32);
8470 std::optional
<RegisterInfo
> source_reg
=
8471 GetRegisterInfo(eRegisterKindDWARF
, dwarf_r0
+ m
);
8473 EmulateInstruction::Context context
;
8474 context
.type
= eContextRegisterLoad
;
8475 context
.SetRegister(*source_reg
);
8477 int64_t data
= llvm::SignExtend64
<16>(rotated
);
8478 if (!WriteRegisterUnsigned(context
, eRegisterKindDWARF
, dwarf_r0
+ d
,
8486 // UXTB extracts an 8-bit value from a register, zero-extends it to 32 bits, and
8487 // writes the result to the destination
8488 // register. You can specify a rotation by 0, 8, 16, or 24 bits before
8489 // extracting the 8-bit value.
8490 bool EmulateInstructionARM::EmulateUXTB(const uint32_t opcode
,
8491 const ARMEncoding encoding
) {
8493 if ConditionPassed() then
8494 EncodingSpecificOperations();
8495 rotated
= ROR(R
[m
], rotation
);
8496 R
[d
] = ZeroExtend(rotated
<7:0>, 32);
8499 bool success
= false;
8501 if (ConditionPassed(opcode
)) {
8506 // EncodingSpecificOperations();
8509 // d = UInt(Rd); m = UInt(Rm); rotation = 0;
8510 d
= Bits32(opcode
, 2, 0);
8511 m
= Bits32(opcode
, 5, 3);
8517 // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:'000');
8518 d
= Bits32(opcode
, 11, 8);
8519 m
= Bits32(opcode
, 3, 0);
8520 rotation
= Bits32(opcode
, 5, 4) << 3;
8522 // if BadReg(d) || BadReg(m) then UNPREDICTABLE;
8523 if (BadReg(d
) || BadReg(m
))
8529 // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:'000');
8530 d
= Bits32(opcode
, 15, 12);
8531 m
= Bits32(opcode
, 3, 0);
8532 rotation
= Bits32(opcode
, 11, 10) << 3;
8534 // if d == 15 || m == 15 then UNPREDICTABLE;
8535 if ((d
== 15) || (m
== 15))
8545 ReadRegisterUnsigned(eRegisterKindDWARF
, dwarf_r0
+ m
, 0, &success
);
8549 // rotated = ROR(R[m], rotation);
8550 uint64_t rotated
= ROR(Rm
, rotation
, &success
);
8554 // R[d] = ZeroExtend(rotated<7:0>, 32);
8555 std::optional
<RegisterInfo
> source_reg
=
8556 GetRegisterInfo(eRegisterKindDWARF
, dwarf_r0
+ m
);
8558 EmulateInstruction::Context context
;
8559 context
.type
= eContextRegisterLoad
;
8560 context
.SetRegister(*source_reg
);
8562 if (!WriteRegisterUnsigned(context
, eRegisterKindDWARF
, dwarf_r0
+ d
,
8563 Bits32(rotated
, 7, 0)))
8569 // UXTH extracts a 16-bit value from a register, zero-extends it to 32 bits, and
8570 // writes the result to the destination
8571 // register. You can specify a rotation by 0, 8, 16, or 24 bits before
8572 // extracting the 16-bit value.
8573 bool EmulateInstructionARM::EmulateUXTH(const uint32_t opcode
,
8574 const ARMEncoding encoding
) {
8576 if ConditionPassed() then
8577 EncodingSpecificOperations();
8578 rotated
= ROR(R
[m
], rotation
);
8579 R
[d
] = ZeroExtend(rotated
<15:0>, 32);
8582 bool success
= false;
8584 if (ConditionPassed(opcode
)) {
8591 // d = UInt(Rd); m = UInt(Rm); rotation = 0;
8592 d
= Bits32(opcode
, 2, 0);
8593 m
= Bits32(opcode
, 5, 3);
8599 // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:'000');
8600 d
= Bits32(opcode
, 11, 8);
8601 m
= Bits32(opcode
, 3, 0);
8602 rotation
= Bits32(opcode
, 5, 4) << 3;
8604 // if BadReg(d) || BadReg(m) then UNPREDICTABLE;
8605 if (BadReg(d
) || BadReg(m
))
8611 // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:'000');
8612 d
= Bits32(opcode
, 15, 12);
8613 m
= Bits32(opcode
, 3, 0);
8614 rotation
= Bits32(opcode
, 11, 10) << 3;
8616 // if d == 15 || m == 15 then UNPREDICTABLE;
8617 if ((d
== 15) || (m
== 15))
8627 ReadRegisterUnsigned(eRegisterKindDWARF
, dwarf_r0
+ m
, 0, &success
);
8631 // rotated = ROR(R[m], rotation);
8632 uint64_t rotated
= ROR(Rm
, rotation
, &success
);
8636 // R[d] = ZeroExtend(rotated<15:0>, 32);
8637 std::optional
<RegisterInfo
> source_reg
=
8638 GetRegisterInfo(eRegisterKindDWARF
, dwarf_r0
+ m
);
8640 EmulateInstruction::Context context
;
8641 context
.type
= eContextRegisterLoad
;
8642 context
.SetRegister(*source_reg
);
8644 if (!WriteRegisterUnsigned(context
, eRegisterKindDWARF
, dwarf_r0
+ d
,
8645 Bits32(rotated
, 15, 0)))
8651 // RFE (Return From Exception) loads the PC and the CPSR from the word at the
8652 // specified address and the following
8653 // word respectively.
8654 bool EmulateInstructionARM::EmulateRFE(const uint32_t opcode
,
8655 const ARMEncoding encoding
) {
8657 if ConditionPassed() then
8658 EncodingSpecificOperations();
8659 if !CurrentModeIsPrivileged() || CurrentInstrSet() == InstrSet_ThumbEE then
8662 address
= if increment then R
[n
] else R
[n
]-8;
8663 if wordhigher then address
= address
+4;
8664 CPSRWriteByInstr(MemA
[address
+4,4], '1111', TRUE
);
8665 BranchWritePC(MemA
[address
,4]);
8666 if wback then R
[n
] = if increment then R
[n
]+8 else R
[n
]-8;
8669 bool success
= false;
8671 if (ConditionPassed(opcode
)) {
8677 // EncodingSpecificOperations();
8680 // n = UInt(Rn); wback = (W == '1'); increment = FALSE; wordhigher =
8682 n
= Bits32(opcode
, 19, 16);
8683 wback
= BitIsSet(opcode
, 21);
8687 // if n == 15 then UNPREDICTABLE;
8691 // if InITBlock() && !LastInITBlock() then UNPREDICTABLE;
8692 if (InITBlock() && !LastInITBlock())
8698 // n = UInt(Rn); wback = (W == '1'); increment = TRUE; wordhigher = FALSE;
8699 n
= Bits32(opcode
, 19, 16);
8700 wback
= BitIsSet(opcode
, 21);
8704 // if n == 15 then UNPREDICTABLE;
8708 // if InITBlock() && !LastInITBlock() then UNPREDICTABLE;
8709 if (InITBlock() && !LastInITBlock())
8716 n
= Bits32(opcode
, 19, 16);
8718 // wback = (W == '1'); inc = (U == '1'); wordhigher = (P == U);
8719 wback
= BitIsSet(opcode
, 21);
8720 increment
= BitIsSet(opcode
, 23);
8721 wordhigher
= (Bit32(opcode
, 24) == Bit32(opcode
, 23));
8723 // if n == 15 then UNPREDICTABLE;
8733 // if !CurrentModeIsPrivileged() || CurrentInstrSet() == InstrSet_ThumbEE
8735 if (!CurrentModeIsPrivileged())
8740 ReadRegisterUnsigned(eRegisterKindDWARF
, dwarf_r0
+ n
, 0, &success
);
8745 // address = if increment then R[n] else R[n]-8;
8751 // if wordhigher then address = address+4;
8753 address
= address
+ 4;
8755 // CPSRWriteByInstr(MemA[address+4,4], '1111', TRUE);
8756 std::optional
<RegisterInfo
> base_reg
=
8757 GetRegisterInfo(eRegisterKindDWARF
, dwarf_r0
+ n
);
8759 EmulateInstruction::Context context
;
8760 context
.type
= eContextReturnFromException
;
8761 context
.SetRegisterPlusOffset(*base_reg
, address
- Rn
);
8763 uint64_t data
= MemARead(context
, address
+ 4, 4, 0, &success
);
8767 CPSRWriteByInstr(data
, 15, true);
8769 // BranchWritePC(MemA[address,4]);
8770 uint64_t data2
= MemARead(context
, address
, 4, 0, &success
);
8774 BranchWritePC(context
, data2
);
8776 // if wback then R[n] = if increment then R[n]+8 else R[n]-8;
8778 context
.type
= eContextAdjustBaseRegister
;
8780 context
.SetOffset(8);
8781 if (!WriteRegisterUnsigned(context
, eRegisterKindDWARF
, dwarf_r0
+ n
,
8785 context
.SetOffset(-8);
8786 if (!WriteRegisterUnsigned(context
, eRegisterKindDWARF
, dwarf_r0
+ n
,
8792 } // if ConditionPassed()
8796 // Bitwise Exclusive OR (immediate) performs a bitwise exclusive OR of a
8797 // register value and an immediate value, and writes the result to the
8798 // destination register. It can optionally update the condition flags based on
8800 bool EmulateInstructionARM::EmulateEORImm(const uint32_t opcode
,
8801 const ARMEncoding encoding
) {
8803 // ARM pseudo code...
8804 if ConditionPassed() then
8805 EncodingSpecificOperations();
8806 result
= R
[n
] EOR imm32
;
8807 if d
== 15 then
// Can only occur for ARM encoding
8808 ALUWritePC(result
); // setflags is always FALSE here
8812 APSR
.N
= result
<31>;
8813 APSR
.Z
= IsZeroBit(result
);
8818 bool success
= false;
8820 if (ConditionPassed(opcode
)) {
8823 imm32
; // the immediate value to be ORed to the value obtained from Rn
8825 uint32_t carry
; // the carry bit after ARM/Thumb Expand operation
8828 Rd
= Bits32(opcode
, 11, 8);
8829 Rn
= Bits32(opcode
, 19, 16);
8830 setflags
= BitIsSet(opcode
, 20);
8831 imm32
= ThumbExpandImm_C(
8833 carry
); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C)
8834 // if Rd == '1111' && S == '1' then SEE TEQ (immediate);
8835 if (Rd
== 15 && setflags
)
8836 return EmulateTEQImm(opcode
, eEncodingT1
);
8837 if (Rd
== 13 || (Rd
== 15 && !setflags
) || BadReg(Rn
))
8841 Rd
= Bits32(opcode
, 15, 12);
8842 Rn
= Bits32(opcode
, 19, 16);
8843 setflags
= BitIsSet(opcode
, 20);
8845 ARMExpandImm_C(opcode
, APSR_C
,
8846 carry
); // (imm32, carry) = ARMExpandImm(imm12, APSR.C)
8848 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related
8850 if (Rd
== 15 && setflags
)
8851 return EmulateSUBSPcLrEtc(opcode
, encoding
);
8857 // Read the first operand.
8858 uint32_t val1
= ReadCoreReg(Rn
, &success
);
8862 uint32_t result
= val1
^ imm32
;
8864 EmulateInstruction::Context context
;
8865 context
.type
= EmulateInstruction::eContextImmediate
;
8866 context
.SetNoArgs();
8868 if (!WriteCoreRegOptionalFlags(context
, result
, Rd
, setflags
, carry
))
8874 // Bitwise Exclusive OR (register) performs a bitwise exclusive OR of a
8875 // register value and an optionally-shifted register value, and writes the
8876 // result to the destination register. It can optionally update the condition
8877 // flags based on the result.
8878 bool EmulateInstructionARM::EmulateEORReg(const uint32_t opcode
,
8879 const ARMEncoding encoding
) {
8881 // ARM pseudo code...
8882 if ConditionPassed() then
8883 EncodingSpecificOperations();
8884 (shifted
, carry
) = Shift_C(R
[m
], shift_t
, shift_n
, APSR
.C
);
8885 result
= R
[n
] EOR shifted
;
8886 if d
== 15 then
// Can only occur for ARM encoding
8887 ALUWritePC(result
); // setflags is always FALSE here
8891 APSR
.N
= result
<31>;
8892 APSR
.Z
= IsZeroBit(result
);
8897 bool success
= false;
8899 if (ConditionPassed(opcode
)) {
8900 uint32_t Rd
, Rn
, Rm
;
8901 ARM_ShifterType shift_t
;
8902 uint32_t shift_n
; // the shift applied to the value read from Rm
8907 Rd
= Rn
= Bits32(opcode
, 2, 0);
8908 Rm
= Bits32(opcode
, 5, 3);
8909 setflags
= !InITBlock();
8910 shift_t
= SRType_LSL
;
8914 Rd
= Bits32(opcode
, 11, 8);
8915 Rn
= Bits32(opcode
, 19, 16);
8916 Rm
= Bits32(opcode
, 3, 0);
8917 setflags
= BitIsSet(opcode
, 20);
8918 shift_n
= DecodeImmShiftThumb(opcode
, shift_t
);
8919 // if Rd == '1111' && S == '1' then SEE TEQ (register);
8920 if (Rd
== 15 && setflags
)
8921 return EmulateTEQReg(opcode
, eEncodingT1
);
8922 if (Rd
== 13 || (Rd
== 15 && !setflags
) || BadReg(Rn
) || BadReg(Rm
))
8926 Rd
= Bits32(opcode
, 15, 12);
8927 Rn
= Bits32(opcode
, 19, 16);
8928 Rm
= Bits32(opcode
, 3, 0);
8929 setflags
= BitIsSet(opcode
, 20);
8930 shift_n
= DecodeImmShiftARM(opcode
, shift_t
);
8932 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related
8934 if (Rd
== 15 && setflags
)
8935 return EmulateSUBSPcLrEtc(opcode
, encoding
);
8941 // Read the first operand.
8942 uint32_t val1
= ReadCoreReg(Rn
, &success
);
8946 // Read the second operand.
8947 uint32_t val2
= ReadCoreReg(Rm
, &success
);
8951 uint32_t shifted
= Shift_C(val2
, shift_t
, shift_n
, APSR_C
, carry
, &success
);
8954 uint32_t result
= val1
^ shifted
;
8956 EmulateInstruction::Context context
;
8957 context
.type
= EmulateInstruction::eContextImmediate
;
8958 context
.SetNoArgs();
8960 if (!WriteCoreRegOptionalFlags(context
, result
, Rd
, setflags
, carry
))
8966 // Bitwise OR (immediate) performs a bitwise (inclusive) OR of a register value
8967 // and an immediate value, and writes the result to the destination register.
8968 // It can optionally update the condition flags based on the result.
8969 bool EmulateInstructionARM::EmulateORRImm(const uint32_t opcode
,
8970 const ARMEncoding encoding
) {
8972 // ARM pseudo code...
8973 if ConditionPassed() then
8974 EncodingSpecificOperations();
8975 result
= R
[n
] OR imm32
;
8976 if d
== 15 then
// Can only occur for ARM encoding
8977 ALUWritePC(result
); // setflags is always FALSE here
8981 APSR
.N
= result
<31>;
8982 APSR
.Z
= IsZeroBit(result
);
8987 bool success
= false;
8989 if (ConditionPassed(opcode
)) {
8992 imm32
; // the immediate value to be ORed to the value obtained from Rn
8994 uint32_t carry
; // the carry bit after ARM/Thumb Expand operation
8997 Rd
= Bits32(opcode
, 11, 8);
8998 Rn
= Bits32(opcode
, 19, 16);
8999 setflags
= BitIsSet(opcode
, 20);
9000 imm32
= ThumbExpandImm_C(
9002 carry
); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C)
9003 // if Rn == '1111' then SEE MOV (immediate);
9005 return EmulateMOVRdImm(opcode
, eEncodingT2
);
9006 if (BadReg(Rd
) || Rn
== 13)
9010 Rd
= Bits32(opcode
, 15, 12);
9011 Rn
= Bits32(opcode
, 19, 16);
9012 setflags
= BitIsSet(opcode
, 20);
9014 ARMExpandImm_C(opcode
, APSR_C
,
9015 carry
); // (imm32, carry) = ARMExpandImm(imm12, APSR.C)
9017 if (Rd
== 15 && setflags
)
9018 return EmulateSUBSPcLrEtc(opcode
, encoding
);
9024 // Read the first operand.
9025 uint32_t val1
= ReadCoreReg(Rn
, &success
);
9029 uint32_t result
= val1
| imm32
;
9031 EmulateInstruction::Context context
;
9032 context
.type
= EmulateInstruction::eContextImmediate
;
9033 context
.SetNoArgs();
9035 if (!WriteCoreRegOptionalFlags(context
, result
, Rd
, setflags
, carry
))
9041 // Bitwise OR (register) performs a bitwise (inclusive) OR of a register value
9042 // and an optionally-shifted register value, and writes the result to the
9043 // destination register. It can optionally update the condition flags based on
9045 bool EmulateInstructionARM::EmulateORRReg(const uint32_t opcode
,
9046 const ARMEncoding encoding
) {
9048 // ARM pseudo code...
9049 if ConditionPassed() then
9050 EncodingSpecificOperations();
9051 (shifted
, carry
) = Shift_C(R
[m
], shift_t
, shift_n
, APSR
.C
);
9052 result
= R
[n
] OR shifted
;
9053 if d
== 15 then
// Can only occur for ARM encoding
9054 ALUWritePC(result
); // setflags is always FALSE here
9058 APSR
.N
= result
<31>;
9059 APSR
.Z
= IsZeroBit(result
);
9064 bool success
= false;
9066 if (ConditionPassed(opcode
)) {
9067 uint32_t Rd
, Rn
, Rm
;
9068 ARM_ShifterType shift_t
;
9069 uint32_t shift_n
; // the shift applied to the value read from Rm
9074 Rd
= Rn
= Bits32(opcode
, 2, 0);
9075 Rm
= Bits32(opcode
, 5, 3);
9076 setflags
= !InITBlock();
9077 shift_t
= SRType_LSL
;
9081 Rd
= Bits32(opcode
, 11, 8);
9082 Rn
= Bits32(opcode
, 19, 16);
9083 Rm
= Bits32(opcode
, 3, 0);
9084 setflags
= BitIsSet(opcode
, 20);
9085 shift_n
= DecodeImmShiftThumb(opcode
, shift_t
);
9086 // if Rn == '1111' then SEE MOV (register);
9088 return EmulateMOVRdRm(opcode
, eEncodingT3
);
9089 if (BadReg(Rd
) || Rn
== 13 || BadReg(Rm
))
9093 Rd
= Bits32(opcode
, 15, 12);
9094 Rn
= Bits32(opcode
, 19, 16);
9095 Rm
= Bits32(opcode
, 3, 0);
9096 setflags
= BitIsSet(opcode
, 20);
9097 shift_n
= DecodeImmShiftARM(opcode
, shift_t
);
9099 if (Rd
== 15 && setflags
)
9100 return EmulateSUBSPcLrEtc(opcode
, encoding
);
9106 // Read the first operand.
9107 uint32_t val1
= ReadCoreReg(Rn
, &success
);
9111 // Read the second operand.
9112 uint32_t val2
= ReadCoreReg(Rm
, &success
);
9116 uint32_t shifted
= Shift_C(val2
, shift_t
, shift_n
, APSR_C
, carry
, &success
);
9119 uint32_t result
= val1
| shifted
;
9121 EmulateInstruction::Context context
;
9122 context
.type
= EmulateInstruction::eContextImmediate
;
9123 context
.SetNoArgs();
9125 if (!WriteCoreRegOptionalFlags(context
, result
, Rd
, setflags
, carry
))
9131 // Reverse Subtract (immediate) subtracts a register value from an immediate
9132 // value, and writes the result to the destination register. It can optionally
9133 // update the condition flags based on the result.
9134 bool EmulateInstructionARM::EmulateRSBImm(const uint32_t opcode
,
9135 const ARMEncoding encoding
) {
9137 // ARM pseudo code...
9138 if ConditionPassed() then
9139 EncodingSpecificOperations();
9140 (result
, carry
, overflow
) = AddWithCarry(NOT(R
[n
]), imm32
, '1');
9141 if d
== 15 then
// Can only occur for ARM encoding
9142 ALUWritePC(result
); // setflags is always FALSE here
9146 APSR
.N
= result
<31>;
9147 APSR
.Z
= IsZeroBit(result
);
9152 bool success
= false;
9154 uint32_t Rd
; // the destination register
9155 uint32_t Rn
; // the first operand
9158 imm32
; // the immediate value to be added to the value obtained from Rn
9161 Rd
= Bits32(opcode
, 2, 0);
9162 Rn
= Bits32(opcode
, 5, 3);
9163 setflags
= !InITBlock();
9167 Rd
= Bits32(opcode
, 11, 8);
9168 Rn
= Bits32(opcode
, 19, 16);
9169 setflags
= BitIsSet(opcode
, 20);
9170 imm32
= ThumbExpandImm(opcode
); // imm32 = ThumbExpandImm(i:imm3:imm8)
9171 if (BadReg(Rd
) || BadReg(Rn
))
9175 Rd
= Bits32(opcode
, 15, 12);
9176 Rn
= Bits32(opcode
, 19, 16);
9177 setflags
= BitIsSet(opcode
, 20);
9178 imm32
= ARMExpandImm(opcode
); // imm32 = ARMExpandImm(imm12)
9180 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related
9182 if (Rd
== 15 && setflags
)
9183 return EmulateSUBSPcLrEtc(opcode
, encoding
);
9188 // Read the register value from the operand register Rn.
9189 uint32_t reg_val
= ReadCoreReg(Rn
, &success
);
9193 AddWithCarryResult res
= AddWithCarry(~reg_val
, imm32
, 1);
9195 EmulateInstruction::Context context
;
9196 context
.type
= EmulateInstruction::eContextImmediate
;
9197 context
.SetNoArgs();
9199 return WriteCoreRegOptionalFlags(context
, res
.result
, Rd
, setflags
,
9200 res
.carry_out
, res
.overflow
);
9203 // Reverse Subtract (register) subtracts a register value from an optionally-
9204 // shifted register value, and writes the result to the destination register.
9205 // It can optionally update the condition flags based on the result.
9206 bool EmulateInstructionARM::EmulateRSBReg(const uint32_t opcode
,
9207 const ARMEncoding encoding
) {
9209 // ARM pseudo code...
9210 if ConditionPassed() then
9211 EncodingSpecificOperations();
9212 shifted
= Shift(R
[m
], shift_t
, shift_n
, APSR
.C
);
9213 (result
, carry
, overflow
) = AddWithCarry(NOT(R
[n
]), shifted
, '1');
9214 if d
== 15 then
// Can only occur for ARM encoding
9215 ALUWritePC(result
); // setflags is always FALSE here
9219 APSR
.N
= result
<31>;
9220 APSR
.Z
= IsZeroBit(result
);
9225 bool success
= false;
9227 uint32_t Rd
; // the destination register
9228 uint32_t Rn
; // the first operand
9229 uint32_t Rm
; // the second operand
9231 ARM_ShifterType shift_t
;
9232 uint32_t shift_n
; // the shift applied to the value read from Rm
9235 Rd
= Bits32(opcode
, 11, 8);
9236 Rn
= Bits32(opcode
, 19, 16);
9237 Rm
= Bits32(opcode
, 3, 0);
9238 setflags
= BitIsSet(opcode
, 20);
9239 shift_n
= DecodeImmShiftThumb(opcode
, shift_t
);
9240 // if (BadReg(d) || BadReg(m)) then UNPREDICTABLE;
9241 if (BadReg(Rd
) || BadReg(Rn
) || BadReg(Rm
))
9245 Rd
= Bits32(opcode
, 15, 12);
9246 Rn
= Bits32(opcode
, 19, 16);
9247 Rm
= Bits32(opcode
, 3, 0);
9248 setflags
= BitIsSet(opcode
, 20);
9249 shift_n
= DecodeImmShiftARM(opcode
, shift_t
);
9251 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related
9253 if (Rd
== 15 && setflags
)
9254 return EmulateSUBSPcLrEtc(opcode
, encoding
);
9259 // Read the register value from register Rn.
9260 uint32_t val1
= ReadCoreReg(Rn
, &success
);
9264 // Read the register value from register Rm.
9265 uint32_t val2
= ReadCoreReg(Rm
, &success
);
9269 uint32_t shifted
= Shift(val2
, shift_t
, shift_n
, APSR_C
, &success
);
9272 AddWithCarryResult res
= AddWithCarry(~val1
, shifted
, 1);
9274 EmulateInstruction::Context context
;
9275 context
.type
= EmulateInstruction::eContextImmediate
;
9276 context
.SetNoArgs();
9277 return WriteCoreRegOptionalFlags(context
, res
.result
, Rd
, setflags
,
9278 res
.carry_out
, res
.overflow
);
9281 // Reverse Subtract with Carry (immediate) subtracts a register value and the
9282 // value of NOT (Carry flag) from an immediate value, and writes the result to
9283 // the destination register. It can optionally update the condition flags based
9285 bool EmulateInstructionARM::EmulateRSCImm(const uint32_t opcode
,
9286 const ARMEncoding encoding
) {
9288 // ARM pseudo code...
9289 if ConditionPassed() then
9290 EncodingSpecificOperations();
9291 (result
, carry
, overflow
) = AddWithCarry(NOT(R
[n
]), imm32
, APSR
.C
);
9293 ALUWritePC(result
); // setflags is always FALSE here
9297 APSR
.N
= result
<31>;
9298 APSR
.Z
= IsZeroBit(result
);
9303 bool success
= false;
9305 uint32_t Rd
; // the destination register
9306 uint32_t Rn
; // the first operand
9309 imm32
; // the immediate value to be added to the value obtained from Rn
9312 Rd
= Bits32(opcode
, 15, 12);
9313 Rn
= Bits32(opcode
, 19, 16);
9314 setflags
= BitIsSet(opcode
, 20);
9315 imm32
= ARMExpandImm(opcode
); // imm32 = ARMExpandImm(imm12)
9317 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related
9319 if (Rd
== 15 && setflags
)
9320 return EmulateSUBSPcLrEtc(opcode
, encoding
);
9325 // Read the register value from the operand register Rn.
9326 uint32_t reg_val
= ReadCoreReg(Rn
, &success
);
9330 AddWithCarryResult res
= AddWithCarry(~reg_val
, imm32
, APSR_C
);
9332 EmulateInstruction::Context context
;
9333 context
.type
= EmulateInstruction::eContextImmediate
;
9334 context
.SetNoArgs();
9336 return WriteCoreRegOptionalFlags(context
, res
.result
, Rd
, setflags
,
9337 res
.carry_out
, res
.overflow
);
9340 // Reverse Subtract with Carry (register) subtracts a register value and the
9341 // value of NOT (Carry flag) from an optionally-shifted register value, and
9342 // writes the result to the destination register. It can optionally update the
9343 // condition flags based on the result.
9344 bool EmulateInstructionARM::EmulateRSCReg(const uint32_t opcode
,
9345 const ARMEncoding encoding
) {
9347 // ARM pseudo code...
9348 if ConditionPassed() then
9349 EncodingSpecificOperations();
9350 shifted
= Shift(R
[m
], shift_t
, shift_n
, APSR
.C
);
9351 (result
, carry
, overflow
) = AddWithCarry(NOT(R
[n
]), shifted
, APSR
.C
);
9353 ALUWritePC(result
); // setflags is always FALSE here
9357 APSR
.N
= result
<31>;
9358 APSR
.Z
= IsZeroBit(result
);
9363 bool success
= false;
9365 uint32_t Rd
; // the destination register
9366 uint32_t Rn
; // the first operand
9367 uint32_t Rm
; // the second operand
9369 ARM_ShifterType shift_t
;
9370 uint32_t shift_n
; // the shift applied to the value read from Rm
9373 Rd
= Bits32(opcode
, 15, 12);
9374 Rn
= Bits32(opcode
, 19, 16);
9375 Rm
= Bits32(opcode
, 3, 0);
9376 setflags
= BitIsSet(opcode
, 20);
9377 shift_n
= DecodeImmShiftARM(opcode
, shift_t
);
9379 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related
9381 if (Rd
== 15 && setflags
)
9382 return EmulateSUBSPcLrEtc(opcode
, encoding
);
9387 // Read the register value from register Rn.
9388 uint32_t val1
= ReadCoreReg(Rn
, &success
);
9392 // Read the register value from register Rm.
9393 uint32_t val2
= ReadCoreReg(Rm
, &success
);
9397 uint32_t shifted
= Shift(val2
, shift_t
, shift_n
, APSR_C
, &success
);
9400 AddWithCarryResult res
= AddWithCarry(~val1
, shifted
, APSR_C
);
9402 EmulateInstruction::Context context
;
9403 context
.type
= EmulateInstruction::eContextImmediate
;
9404 context
.SetNoArgs();
9405 return WriteCoreRegOptionalFlags(context
, res
.result
, Rd
, setflags
,
9406 res
.carry_out
, res
.overflow
);
9409 // Subtract with Carry (immediate) subtracts an immediate value and the value
9411 // NOT (Carry flag) from a register value, and writes the result to the
9412 // destination register.
9413 // It can optionally update the condition flags based on the result.
9414 bool EmulateInstructionARM::EmulateSBCImm(const uint32_t opcode
,
9415 const ARMEncoding encoding
) {
9417 // ARM pseudo code...
9418 if ConditionPassed() then
9419 EncodingSpecificOperations();
9420 (result
, carry
, overflow
) = AddWithCarry(R
[n
], NOT(imm32
), APSR
.C
);
9421 if d
== 15 then
// Can only occur for ARM encoding
9422 ALUWritePC(result
); // setflags is always FALSE here
9426 APSR
.N
= result
<31>;
9427 APSR
.Z
= IsZeroBit(result
);
9432 bool success
= false;
9434 uint32_t Rd
; // the destination register
9435 uint32_t Rn
; // the first operand
9438 imm32
; // the immediate value to be added to the value obtained from Rn
9441 Rd
= Bits32(opcode
, 11, 8);
9442 Rn
= Bits32(opcode
, 19, 16);
9443 setflags
= BitIsSet(opcode
, 20);
9444 imm32
= ThumbExpandImm(opcode
); // imm32 = ThumbExpandImm(i:imm3:imm8)
9445 if (BadReg(Rd
) || BadReg(Rn
))
9449 Rd
= Bits32(opcode
, 15, 12);
9450 Rn
= Bits32(opcode
, 19, 16);
9451 setflags
= BitIsSet(opcode
, 20);
9452 imm32
= ARMExpandImm(opcode
); // imm32 = ARMExpandImm(imm12)
9454 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related
9456 if (Rd
== 15 && setflags
)
9457 return EmulateSUBSPcLrEtc(opcode
, encoding
);
9462 // Read the register value from the operand register Rn.
9463 uint32_t reg_val
= ReadCoreReg(Rn
, &success
);
9467 AddWithCarryResult res
= AddWithCarry(reg_val
, ~imm32
, APSR_C
);
9469 EmulateInstruction::Context context
;
9470 context
.type
= EmulateInstruction::eContextImmediate
;
9471 context
.SetNoArgs();
9473 return WriteCoreRegOptionalFlags(context
, res
.result
, Rd
, setflags
,
9474 res
.carry_out
, res
.overflow
);
9477 // Subtract with Carry (register) subtracts an optionally-shifted register
9478 // value and the value of
9479 // NOT (Carry flag) from a register value, and writes the result to the
9480 // destination register.
9481 // It can optionally update the condition flags based on the result.
9482 bool EmulateInstructionARM::EmulateSBCReg(const uint32_t opcode
,
9483 const ARMEncoding encoding
) {
9485 // ARM pseudo code...
9486 if ConditionPassed() then
9487 EncodingSpecificOperations();
9488 shifted
= Shift(R
[m
], shift_t
, shift_n
, APSR
.C
);
9489 (result
, carry
, overflow
) = AddWithCarry(R
[n
], NOT(shifted
), APSR
.C
);
9490 if d
== 15 then
// Can only occur for ARM encoding
9491 ALUWritePC(result
); // setflags is always FALSE here
9495 APSR
.N
= result
<31>;
9496 APSR
.Z
= IsZeroBit(result
);
9501 bool success
= false;
9503 uint32_t Rd
; // the destination register
9504 uint32_t Rn
; // the first operand
9505 uint32_t Rm
; // the second operand
9507 ARM_ShifterType shift_t
;
9508 uint32_t shift_n
; // the shift applied to the value read from Rm
9511 Rd
= Rn
= Bits32(opcode
, 2, 0);
9512 Rm
= Bits32(opcode
, 5, 3);
9513 setflags
= !InITBlock();
9514 shift_t
= SRType_LSL
;
9518 Rd
= Bits32(opcode
, 11, 8);
9519 Rn
= Bits32(opcode
, 19, 16);
9520 Rm
= Bits32(opcode
, 3, 0);
9521 setflags
= BitIsSet(opcode
, 20);
9522 shift_n
= DecodeImmShiftThumb(opcode
, shift_t
);
9523 if (BadReg(Rd
) || BadReg(Rn
) || BadReg(Rm
))
9527 Rd
= Bits32(opcode
, 15, 12);
9528 Rn
= Bits32(opcode
, 19, 16);
9529 Rm
= Bits32(opcode
, 3, 0);
9530 setflags
= BitIsSet(opcode
, 20);
9531 shift_n
= DecodeImmShiftARM(opcode
, shift_t
);
9533 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related
9535 if (Rd
== 15 && setflags
)
9536 return EmulateSUBSPcLrEtc(opcode
, encoding
);
9541 // Read the register value from register Rn.
9542 uint32_t val1
= ReadCoreReg(Rn
, &success
);
9546 // Read the register value from register Rm.
9547 uint32_t val2
= ReadCoreReg(Rm
, &success
);
9551 uint32_t shifted
= Shift(val2
, shift_t
, shift_n
, APSR_C
, &success
);
9554 AddWithCarryResult res
= AddWithCarry(val1
, ~shifted
, APSR_C
);
9556 EmulateInstruction::Context context
;
9557 context
.type
= EmulateInstruction::eContextImmediate
;
9558 context
.SetNoArgs();
9559 return WriteCoreRegOptionalFlags(context
, res
.result
, Rd
, setflags
,
9560 res
.carry_out
, res
.overflow
);
9563 // This instruction subtracts an immediate value from a register value, and
9564 // writes the result to the destination register. It can optionally update the
9565 // condition flags based on the result.
9566 bool EmulateInstructionARM::EmulateSUBImmThumb(const uint32_t opcode
,
9567 const ARMEncoding encoding
) {
9569 // ARM pseudo code...
9570 if ConditionPassed() then
9571 EncodingSpecificOperations();
9572 (result
, carry
, overflow
) = AddWithCarry(R
[n
], NOT(imm32
), '1');
9575 APSR
.N
= result
<31>;
9576 APSR
.Z
= IsZeroBit(result
);
9581 bool success
= false;
9583 uint32_t Rd
; // the destination register
9584 uint32_t Rn
; // the first operand
9586 uint32_t imm32
; // the immediate value to be subtracted from the value
9590 Rd
= Bits32(opcode
, 2, 0);
9591 Rn
= Bits32(opcode
, 5, 3);
9592 setflags
= !InITBlock();
9593 imm32
= Bits32(opcode
, 8, 6); // imm32 = ZeroExtend(imm3, 32)
9596 Rd
= Rn
= Bits32(opcode
, 10, 8);
9597 setflags
= !InITBlock();
9598 imm32
= Bits32(opcode
, 7, 0); // imm32 = ZeroExtend(imm8, 32)
9601 Rd
= Bits32(opcode
, 11, 8);
9602 Rn
= Bits32(opcode
, 19, 16);
9603 setflags
= BitIsSet(opcode
, 20);
9604 imm32
= ThumbExpandImm(opcode
); // imm32 = ThumbExpandImm(i:imm3:imm8)
9606 // if Rd == '1111' && S == '1' then SEE CMP (immediate);
9607 if (Rd
== 15 && setflags
)
9608 return EmulateCMPImm(opcode
, eEncodingT2
);
9610 // if Rn == '1101' then SEE SUB (SP minus immediate);
9612 return EmulateSUBSPImm(opcode
, eEncodingT2
);
9614 // if d == 13 || (d == 15 && S == '0') || n == 15 then UNPREDICTABLE;
9615 if (Rd
== 13 || (Rd
== 15 && !setflags
) || Rn
== 15)
9619 Rd
= Bits32(opcode
, 11, 8);
9620 Rn
= Bits32(opcode
, 19, 16);
9621 setflags
= BitIsSet(opcode
, 20);
9622 imm32
= ThumbImm12(opcode
); // imm32 = ZeroExtend(i:imm3:imm8, 32)
9624 // if Rn == '1111' then SEE ADR;
9626 return EmulateADR(opcode
, eEncodingT2
);
9628 // if Rn == '1101' then SEE SUB (SP minus immediate);
9630 return EmulateSUBSPImm(opcode
, eEncodingT3
);
9638 // Read the register value from the operand register Rn.
9639 uint32_t reg_val
= ReadCoreReg(Rn
, &success
);
9643 AddWithCarryResult res
= AddWithCarry(reg_val
, ~imm32
, 1);
9645 EmulateInstruction::Context context
;
9646 context
.type
= EmulateInstruction::eContextImmediate
;
9647 context
.SetNoArgs();
9649 return WriteCoreRegOptionalFlags(context
, res
.result
, Rd
, setflags
,
9650 res
.carry_out
, res
.overflow
);
9653 // This instruction subtracts an immediate value from a register value, and
9654 // writes the result to the destination register. It can optionally update the
9655 // condition flags based on the result.
9656 bool EmulateInstructionARM::EmulateSUBImmARM(const uint32_t opcode
,
9657 const ARMEncoding encoding
) {
9659 // ARM pseudo code...
9660 if ConditionPassed() then
9661 EncodingSpecificOperations();
9662 (result
, carry
, overflow
) = AddWithCarry(R
[n
], NOT(imm32
), '1');
9664 ALUWritePC(result
); // setflags is always FALSE here
9668 APSR
.N
= result
<31>;
9669 APSR
.Z
= IsZeroBit(result
);
9674 bool success
= false;
9676 if (ConditionPassed(opcode
)) {
9677 uint32_t Rd
; // the destination register
9678 uint32_t Rn
; // the first operand
9680 uint32_t imm32
; // the immediate value to be subtracted from the value
9684 Rd
= Bits32(opcode
, 15, 12);
9685 Rn
= Bits32(opcode
, 19, 16);
9686 setflags
= BitIsSet(opcode
, 20);
9687 imm32
= ARMExpandImm(opcode
); // imm32 = ARMExpandImm(imm12)
9689 // if Rn == '1111' && S == '0' then SEE ADR;
9690 if (Rn
== 15 && !setflags
)
9691 return EmulateADR(opcode
, eEncodingA2
);
9693 // if Rn == '1101' then SEE SUB (SP minus immediate);
9695 return EmulateSUBSPImm(opcode
, eEncodingA1
);
9697 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related
9699 if (Rd
== 15 && setflags
)
9700 return EmulateSUBSPcLrEtc(opcode
, encoding
);
9705 // Read the register value from the operand register Rn.
9706 uint32_t reg_val
= ReadCoreReg(Rn
, &success
);
9710 AddWithCarryResult res
= AddWithCarry(reg_val
, ~imm32
, 1);
9712 EmulateInstruction::Context context
;
9714 context
.type
= EmulateInstruction::eContextAdjustStackPointer
;
9716 context
.type
= EmulateInstruction::eContextRegisterPlusOffset
;
9718 std::optional
<RegisterInfo
> dwarf_reg
=
9719 GetRegisterInfo(eRegisterKindDWARF
, Rn
);
9720 int64_t imm32_signed
= imm32
;
9721 context
.SetRegisterPlusOffset(*dwarf_reg
, -imm32_signed
);
9723 if (!WriteCoreRegOptionalFlags(context
, res
.result
, Rd
, setflags
,
9724 res
.carry_out
, res
.overflow
))
9730 // Test Equivalence (immediate) performs a bitwise exclusive OR operation on a
9731 // register value and an immediate value. It updates the condition flags based
9732 // on the result, and discards the result.
9733 bool EmulateInstructionARM::EmulateTEQImm(const uint32_t opcode
,
9734 const ARMEncoding encoding
) {
9736 // ARM pseudo code...
9737 if ConditionPassed() then
9738 EncodingSpecificOperations();
9739 result
= R
[n
] EOR imm32
;
9740 APSR
.N
= result
<31>;
9741 APSR
.Z
= IsZeroBit(result
);
9746 bool success
= false;
9748 if (ConditionPassed(opcode
)) {
9751 imm32
; // the immediate value to be ANDed to the value obtained from Rn
9752 uint32_t carry
; // the carry bit after ARM/Thumb Expand operation
9755 Rn
= Bits32(opcode
, 19, 16);
9756 imm32
= ThumbExpandImm_C(
9758 carry
); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C)
9763 Rn
= Bits32(opcode
, 19, 16);
9765 ARMExpandImm_C(opcode
, APSR_C
,
9766 carry
); // (imm32, carry) = ARMExpandImm(imm12, APSR.C)
9772 // Read the first operand.
9773 uint32_t val1
= ReadCoreReg(Rn
, &success
);
9777 uint32_t result
= val1
^ imm32
;
9779 EmulateInstruction::Context context
;
9780 context
.type
= EmulateInstruction::eContextImmediate
;
9781 context
.SetNoArgs();
9783 if (!WriteFlags(context
, result
, carry
))
9789 // Test Equivalence (register) performs a bitwise exclusive OR operation on a
9790 // register value and an optionally-shifted register value. It updates the
9791 // condition flags based on the result, and discards the result.
9792 bool EmulateInstructionARM::EmulateTEQReg(const uint32_t opcode
,
9793 const ARMEncoding encoding
) {
9795 // ARM pseudo code...
9796 if ConditionPassed() then
9797 EncodingSpecificOperations();
9798 (shifted
, carry
) = Shift_C(R
[m
], shift_t
, shift_n
, APSR
.C
);
9799 result
= R
[n
] EOR shifted
;
9800 APSR
.N
= result
<31>;
9801 APSR
.Z
= IsZeroBit(result
);
9806 bool success
= false;
9808 if (ConditionPassed(opcode
)) {
9810 ARM_ShifterType shift_t
;
9811 uint32_t shift_n
; // the shift applied to the value read from Rm
9815 Rn
= Bits32(opcode
, 19, 16);
9816 Rm
= Bits32(opcode
, 3, 0);
9817 shift_n
= DecodeImmShiftThumb(opcode
, shift_t
);
9818 if (BadReg(Rn
) || BadReg(Rm
))
9822 Rn
= Bits32(opcode
, 19, 16);
9823 Rm
= Bits32(opcode
, 3, 0);
9824 shift_n
= DecodeImmShiftARM(opcode
, shift_t
);
9830 // Read the first operand.
9831 uint32_t val1
= ReadCoreReg(Rn
, &success
);
9835 // Read the second operand.
9836 uint32_t val2
= ReadCoreReg(Rm
, &success
);
9840 uint32_t shifted
= Shift_C(val2
, shift_t
, shift_n
, APSR_C
, carry
, &success
);
9843 uint32_t result
= val1
^ shifted
;
9845 EmulateInstruction::Context context
;
9846 context
.type
= EmulateInstruction::eContextImmediate
;
9847 context
.SetNoArgs();
9849 if (!WriteFlags(context
, result
, carry
))
9855 // Test (immediate) performs a bitwise AND operation on a register value and an
9856 // immediate value. It updates the condition flags based on the result, and
9857 // discards the result.
9858 bool EmulateInstructionARM::EmulateTSTImm(const uint32_t opcode
,
9859 const ARMEncoding encoding
) {
9861 // ARM pseudo code...
9862 if ConditionPassed() then
9863 EncodingSpecificOperations();
9864 result
= R
[n
] AND imm32
;
9865 APSR
.N
= result
<31>;
9866 APSR
.Z
= IsZeroBit(result
);
9871 bool success
= false;
9873 if (ConditionPassed(opcode
)) {
9876 imm32
; // the immediate value to be ANDed to the value obtained from Rn
9877 uint32_t carry
; // the carry bit after ARM/Thumb Expand operation
9880 Rn
= Bits32(opcode
, 19, 16);
9881 imm32
= ThumbExpandImm_C(
9883 carry
); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C)
9888 Rn
= Bits32(opcode
, 19, 16);
9890 ARMExpandImm_C(opcode
, APSR_C
,
9891 carry
); // (imm32, carry) = ARMExpandImm(imm12, APSR.C)
9897 // Read the first operand.
9898 uint32_t val1
= ReadCoreReg(Rn
, &success
);
9902 uint32_t result
= val1
& imm32
;
9904 EmulateInstruction::Context context
;
9905 context
.type
= EmulateInstruction::eContextImmediate
;
9906 context
.SetNoArgs();
9908 if (!WriteFlags(context
, result
, carry
))
9914 // Test (register) performs a bitwise AND operation on a register value and an
9915 // optionally-shifted register value. It updates the condition flags based on
9916 // the result, and discards the result.
9917 bool EmulateInstructionARM::EmulateTSTReg(const uint32_t opcode
,
9918 const ARMEncoding encoding
) {
9920 // ARM pseudo code...
9921 if ConditionPassed() then
9922 EncodingSpecificOperations();
9923 (shifted
, carry
) = Shift_C(R
[m
], shift_t
, shift_n
, APSR
.C
);
9924 result
= R
[n
] AND shifted
;
9925 APSR
.N
= result
<31>;
9926 APSR
.Z
= IsZeroBit(result
);
9931 bool success
= false;
9933 if (ConditionPassed(opcode
)) {
9935 ARM_ShifterType shift_t
;
9936 uint32_t shift_n
; // the shift applied to the value read from Rm
9940 Rn
= Bits32(opcode
, 2, 0);
9941 Rm
= Bits32(opcode
, 5, 3);
9942 shift_t
= SRType_LSL
;
9946 Rn
= Bits32(opcode
, 19, 16);
9947 Rm
= Bits32(opcode
, 3, 0);
9948 shift_n
= DecodeImmShiftThumb(opcode
, shift_t
);
9949 if (BadReg(Rn
) || BadReg(Rm
))
9953 Rn
= Bits32(opcode
, 19, 16);
9954 Rm
= Bits32(opcode
, 3, 0);
9955 shift_n
= DecodeImmShiftARM(opcode
, shift_t
);
9961 // Read the first operand.
9962 uint32_t val1
= ReadCoreReg(Rn
, &success
);
9966 // Read the second operand.
9967 uint32_t val2
= ReadCoreReg(Rm
, &success
);
9971 uint32_t shifted
= Shift_C(val2
, shift_t
, shift_n
, APSR_C
, carry
, &success
);
9974 uint32_t result
= val1
& shifted
;
9976 EmulateInstruction::Context context
;
9977 context
.type
= EmulateInstruction::eContextImmediate
;
9978 context
.SetNoArgs();
9980 if (!WriteFlags(context
, result
, carry
))
9986 // A8.6.216 SUB (SP minus register)
9987 bool EmulateInstructionARM::EmulateSUBSPReg(const uint32_t opcode
,
9988 const ARMEncoding encoding
) {
9990 if ConditionPassed() then
9991 EncodingSpecificOperations();
9992 shifted
= Shift(R
[m
], shift_t
, shift_n
, APSR
.C
);
9993 (result
, carry
, overflow
) = AddWithCarry(SP
, NOT(shifted
), '1');
9994 if d
== 15 then
// Can only occur for ARM encoding
9995 ALUWritePC(result
); // setflags is always FALSE here
9999 APSR
.N
= result
<31>;
10000 APSR
.Z
= IsZeroBit(result
);
10005 bool success
= false;
10007 if (ConditionPassed(opcode
)) {
10011 ARM_ShifterType shift_t
;
10014 switch (encoding
) {
10016 // d = UInt(Rd); m = UInt(Rm); setflags = (S == '1');
10017 d
= Bits32(opcode
, 11, 8);
10018 m
= Bits32(opcode
, 3, 0);
10019 setflags
= BitIsSet(opcode
, 20);
10021 // (shift_t, shift_n) = DecodeImmShift(type, imm3:imm2);
10022 shift_n
= DecodeImmShiftThumb(opcode
, shift_t
);
10024 // if d == 13 && (shift_t != SRType_LSL || shift_n > 3) then
10026 if ((d
== 13) && ((shift_t
!= SRType_LSL
) || (shift_n
> 3)))
10029 // if d == 15 || BadReg(m) then UNPREDICTABLE;
10030 if ((d
== 15) || BadReg(m
))
10035 // d = UInt(Rd); m = UInt(Rm); setflags = (S == '1');
10036 d
= Bits32(opcode
, 15, 12);
10037 m
= Bits32(opcode
, 3, 0);
10038 setflags
= BitIsSet(opcode
, 20);
10040 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related
10042 if (d
== 15 && setflags
)
10043 EmulateSUBSPcLrEtc(opcode
, encoding
);
10045 // (shift_t, shift_n) = DecodeImmShift(type, imm5);
10046 shift_n
= DecodeImmShiftARM(opcode
, shift_t
);
10053 // shifted = Shift(R[m], shift_t, shift_n, APSR.C);
10054 uint32_t Rm
= ReadCoreReg(m
, &success
);
10058 uint32_t shifted
= Shift(Rm
, shift_t
, shift_n
, APSR_C
, &success
);
10062 // (result, carry, overflow) = AddWithCarry(SP, NOT(shifted), '1');
10063 uint32_t sp_val
= ReadCoreReg(SP_REG
, &success
);
10067 AddWithCarryResult res
= AddWithCarry(sp_val
, ~shifted
, 1);
10069 EmulateInstruction::Context context
;
10070 context
.type
= eContextArithmetic
;
10071 std::optional
<RegisterInfo
> sp_reg
=
10072 GetRegisterInfo(eRegisterKindDWARF
, dwarf_sp
);
10073 std::optional
<RegisterInfo
> dwarf_reg
=
10074 GetRegisterInfo(eRegisterKindDWARF
, dwarf_r0
+ m
);
10075 context
.SetRegisterRegisterOperands(*sp_reg
, *dwarf_reg
);
10077 if (!WriteCoreRegOptionalFlags(context
, res
.result
, dwarf_r0
+ d
, setflags
,
10078 res
.carry_out
, res
.overflow
))
10084 // A8.6.7 ADD (register-shifted register)
10085 bool EmulateInstructionARM::EmulateADDRegShift(const uint32_t opcode
,
10086 const ARMEncoding encoding
) {
10088 if ConditionPassed() then
10089 EncodingSpecificOperations();
10090 shift_n
= UInt(R
[s
]<7:0>);
10091 shifted
= Shift(R
[m
], shift_t
, shift_n
, APSR
.C
);
10092 (result
, carry
, overflow
) = AddWithCarry(R
[n
], shifted
, '0');
10095 APSR
.N
= result
<31>;
10096 APSR
.Z
= IsZeroBit(result
);
10101 bool success
= false;
10103 if (ConditionPassed(opcode
)) {
10109 ARM_ShifterType shift_t
;
10111 switch (encoding
) {
10113 // d = UInt(Rd); n = UInt(Rn); m = UInt(Rm); s = UInt(Rs);
10114 d
= Bits32(opcode
, 15, 12);
10115 n
= Bits32(opcode
, 19, 16);
10116 m
= Bits32(opcode
, 3, 0);
10117 s
= Bits32(opcode
, 11, 8);
10119 // setflags = (S == '1'); shift_t = DecodeRegShift(type);
10120 setflags
= BitIsSet(opcode
, 20);
10121 shift_t
= DecodeRegShift(Bits32(opcode
, 6, 5));
10123 // if d == 15 || n == 15 || m == 15 || s == 15 then UNPREDICTABLE;
10124 if ((d
== 15) || (n
== 15) || (m
== 15) || (s
== 15))
10132 // shift_n = UInt(R[s]<7:0>);
10133 uint32_t Rs
= ReadCoreReg(s
, &success
);
10137 uint32_t shift_n
= Bits32(Rs
, 7, 0);
10139 // shifted = Shift(R[m], shift_t, shift_n, APSR.C);
10140 uint32_t Rm
= ReadCoreReg(m
, &success
);
10144 uint32_t shifted
= Shift(Rm
, shift_t
, shift_n
, APSR_C
, &success
);
10148 // (result, carry, overflow) = AddWithCarry(R[n], shifted, '0');
10149 uint32_t Rn
= ReadCoreReg(n
, &success
);
10153 AddWithCarryResult res
= AddWithCarry(Rn
, shifted
, 0);
10156 EmulateInstruction::Context context
;
10157 context
.type
= eContextArithmetic
;
10158 std::optional
<RegisterInfo
> reg_n
=
10159 GetRegisterInfo(eRegisterKindDWARF
, dwarf_r0
+ n
);
10160 std::optional
<RegisterInfo
> reg_m
=
10161 GetRegisterInfo(eRegisterKindDWARF
, dwarf_r0
+ m
);
10163 context
.SetRegisterRegisterOperands(*reg_n
, *reg_m
);
10165 if (!WriteRegisterUnsigned(context
, eRegisterKindDWARF
, dwarf_r0
+ d
,
10169 // if setflags then
10170 // APSR.N = result<31>;
10171 // APSR.Z = IsZeroBit(result);
10173 // APSR.V = overflow;
10175 return WriteFlags(context
, res
.result
, res
.carry_out
, res
.overflow
);
10180 // A8.6.213 SUB (register)
10181 bool EmulateInstructionARM::EmulateSUBReg(const uint32_t opcode
,
10182 const ARMEncoding encoding
) {
10184 if ConditionPassed() then
10185 EncodingSpecificOperations();
10186 shifted
= Shift(R
[m
], shift_t
, shift_n
, APSR
.C
);
10187 (result
, carry
, overflow
) = AddWithCarry(R
[n
], NOT(shifted
), '1');
10188 if d
== 15 then
// Can only occur for ARM encoding
10189 ALUWritePC(result
); // setflags is always FALSE here
10193 APSR
.N
= result
<31>;
10194 APSR
.Z
= IsZeroBit(result
);
10199 bool success
= false;
10201 if (ConditionPassed(opcode
)) {
10206 ARM_ShifterType shift_t
;
10209 switch (encoding
) {
10211 // d = UInt(Rd); n = UInt(Rn); m = UInt(Rm); setflags = !InITBlock();
10212 d
= Bits32(opcode
, 2, 0);
10213 n
= Bits32(opcode
, 5, 3);
10214 m
= Bits32(opcode
, 8, 6);
10215 setflags
= !InITBlock();
10217 // (shift_t, shift_n) = (SRType_LSL, 0);
10218 shift_t
= SRType_LSL
;
10224 // d = UInt(Rd); n = UInt(Rn); m = UInt(Rm); setflags = (S =="1");
10225 d
= Bits32(opcode
, 11, 8);
10226 n
= Bits32(opcode
, 19, 16);
10227 m
= Bits32(opcode
, 3, 0);
10228 setflags
= BitIsSet(opcode
, 20);
10230 // if Rd == "1111" && S == "1" then SEE CMP (register);
10231 if (d
== 15 && setflags
== 1)
10232 return EmulateCMPImm(opcode
, eEncodingT3
);
10234 // if Rn == "1101" then SEE SUB (SP minus register);
10236 return EmulateSUBSPReg(opcode
, eEncodingT1
);
10238 // (shift_t, shift_n) = DecodeImmShift(type, imm3:imm2);
10239 shift_n
= DecodeImmShiftThumb(opcode
, shift_t
);
10241 // if d == 13 || (d == 15 && S == '0') || n == 15 || BadReg(m) then
10243 if ((d
== 13) || ((d
== 15) && BitIsClear(opcode
, 20)) || (n
== 15) ||
10250 // if Rn == '1101' then SEE SUB (SP minus register);
10251 // d = UInt(Rd); n = UInt(Rn); m = UInt(Rm); setflags = (S == '1');
10252 d
= Bits32(opcode
, 15, 12);
10253 n
= Bits32(opcode
, 19, 16);
10254 m
= Bits32(opcode
, 3, 0);
10255 setflags
= BitIsSet(opcode
, 20);
10257 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related
10259 if ((d
== 15) && setflags
)
10260 EmulateSUBSPcLrEtc(opcode
, encoding
);
10262 // (shift_t, shift_n) = DecodeImmShift(type, imm5);
10263 shift_n
= DecodeImmShiftARM(opcode
, shift_t
);
10271 // shifted = Shift(R[m], shift_t, shift_n, APSR.C);
10272 uint32_t Rm
= ReadCoreReg(m
, &success
);
10276 uint32_t shifted
= Shift(Rm
, shift_t
, shift_n
, APSR_C
, &success
);
10280 // (result, carry, overflow) = AddWithCarry(R[n], NOT(shifted), '1');
10281 uint32_t Rn
= ReadCoreReg(n
, &success
);
10285 AddWithCarryResult res
= AddWithCarry(Rn
, ~shifted
, 1);
10287 // if d == 15 then // Can only occur for ARM encoding ALUWritePC(result);
10288 // // setflags is always FALSE here else
10290 // if setflags then
10291 // APSR.N = result<31>;
10292 // APSR.Z = IsZeroBit(result);
10294 // APSR.V = overflow;
10296 EmulateInstruction::Context context
;
10297 context
.type
= eContextArithmetic
;
10298 std::optional
<RegisterInfo
> reg_n
=
10299 GetRegisterInfo(eRegisterKindDWARF
, dwarf_r0
+ n
);
10300 std::optional
<RegisterInfo
> reg_m
=
10301 GetRegisterInfo(eRegisterKindDWARF
, dwarf_r0
+ m
);
10302 context
.SetRegisterRegisterOperands(*reg_n
, *reg_m
);
10304 if (!WriteCoreRegOptionalFlags(context
, res
.result
, dwarf_r0
+ d
, setflags
,
10305 res
.carry_out
, res
.overflow
))
10312 // Store Register Exclusive calculates an address from a base register value
10313 // and an immediate offset, and stores a word from a register to memory if the
10314 // executing processor has exclusive access to the memory addressed.
10315 bool EmulateInstructionARM::EmulateSTREX(const uint32_t opcode
,
10316 const ARMEncoding encoding
) {
10318 if ConditionPassed() then
10319 EncodingSpecificOperations(); NullCheckIfThumbEE(n
);
10320 address
= R
[n
] + imm32
;
10321 if ExclusiveMonitorsPass(address
,4) then
10322 MemA
[address
,4] = R
[t
];
10328 bool success
= false;
10330 if (ConditionPassed(opcode
)) {
10335 const uint32_t addr_byte_size
= GetAddressByteSize();
10337 switch (encoding
) {
10339 // d = UInt(Rd); t = UInt(Rt); n = UInt(Rn); imm32 =
10340 // ZeroExtend(imm8:'00',
10342 d
= Bits32(opcode
, 11, 8);
10343 t
= Bits32(opcode
, 15, 12);
10344 n
= Bits32(opcode
, 19, 16);
10345 imm32
= Bits32(opcode
, 7, 0) << 2;
10347 // if BadReg(d) || BadReg(t) || n == 15 then UNPREDICTABLE;
10348 if (BadReg(d
) || BadReg(t
) || (n
== 15))
10351 // if d == n || d == t then UNPREDICTABLE;
10352 if ((d
== n
) || (d
== t
))
10358 // d = UInt(Rd); t = UInt(Rt); n = UInt(Rn); imm32 = Zeros(32); // Zero
10360 d
= Bits32(opcode
, 15, 12);
10361 t
= Bits32(opcode
, 3, 0);
10362 n
= Bits32(opcode
, 19, 16);
10365 // if d == 15 || t == 15 || n == 15 then UNPREDICTABLE;
10366 if ((d
== 15) || (t
== 15) || (n
== 15))
10369 // if d == n || d == t then UNPREDICTABLE;
10370 if ((d
== n
) || (d
== t
))
10379 // address = R[n] + imm32;
10380 uint32_t Rn
= ReadCoreReg(n
, &success
);
10384 addr_t address
= Rn
+ imm32
;
10386 std::optional
<RegisterInfo
> base_reg
=
10387 GetRegisterInfo(eRegisterKindDWARF
, dwarf_r0
+ n
);
10388 std::optional
<RegisterInfo
> data_reg
=
10389 GetRegisterInfo(eRegisterKindDWARF
, dwarf_r0
+ t
);
10390 EmulateInstruction::Context context
;
10391 context
.type
= eContextRegisterStore
;
10392 context
.SetRegisterToRegisterPlusOffset(*data_reg
, *base_reg
, imm32
);
10394 // if ExclusiveMonitorsPass(address,4) then if (ExclusiveMonitorsPass
10395 // (address, addr_byte_size)) -- For now, for the sake of emulation, we
10400 // MemA[address,4] = R[t];
10402 ReadRegisterUnsigned(eRegisterKindDWARF
, dwarf_r0
+ t
, 0, &success
);
10406 if (!MemAWrite(context
, address
, Rt
, addr_byte_size
))
10410 if (!WriteRegisterUnsigned(context
, eRegisterKindDWARF
, dwarf_r0
+ t
, 0))
10413 #if 0 // unreachable because if true
10417 if (!WriteRegisterUnsigned (context
, eRegisterKindDWARF
, dwarf_r0
+ t
, 1))
10420 #endif // unreachable because if true
10425 // A8.6.197 STRB (immediate, ARM)
10426 bool EmulateInstructionARM::EmulateSTRBImmARM(const uint32_t opcode
,
10427 const ARMEncoding encoding
) {
10429 if ConditionPassed() then
10430 EncodingSpecificOperations();
10431 offset_addr
= if add
then (R
[n
] + imm32
) else (R
[n
] - imm32
);
10432 address
= if index then offset_addr
else R
[n
];
10433 MemU
[address
,1] = R
[t
]<7:0>;
10434 if wback then R
[n
] = offset_addr
;
10437 bool success
= false;
10439 if (ConditionPassed(opcode
)) {
10447 switch (encoding
) {
10449 // if P == '0' && W == '1' then SEE STRBT;
10450 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
10451 t
= Bits32(opcode
, 15, 12);
10452 n
= Bits32(opcode
, 19, 16);
10453 imm32
= Bits32(opcode
, 11, 0);
10455 // index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1');
10456 index
= BitIsSet(opcode
, 24);
10457 add
= BitIsSet(opcode
, 23);
10458 wback
= BitIsClear(opcode
, 24) || BitIsSet(opcode
, 21);
10460 // if t == 15 then UNPREDICTABLE;
10464 // if wback && (n == 15 || n == t) then UNPREDICTABLE;
10465 if (wback
&& ((n
== 15) || (n
== t
)))
10474 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
10475 uint32_t Rn
= ReadCoreReg(n
, &success
);
10479 addr_t offset_addr
;
10481 offset_addr
= Rn
+ imm32
;
10483 offset_addr
= Rn
- imm32
;
10485 // address = if index then offset_addr else R[n];
10488 address
= offset_addr
;
10492 // MemU[address,1] = R[t]<7:0>;
10493 uint32_t Rt
= ReadCoreReg(t
, &success
);
10497 std::optional
<RegisterInfo
> base_reg
=
10498 GetRegisterInfo(eRegisterKindDWARF
, dwarf_r0
+ n
);
10499 std::optional
<RegisterInfo
> data_reg
=
10500 GetRegisterInfo(eRegisterKindDWARF
, dwarf_r0
+ t
);
10501 EmulateInstruction::Context context
;
10502 context
.type
= eContextRegisterStore
;
10503 context
.SetRegisterToRegisterPlusOffset(*data_reg
, *base_reg
, address
- Rn
);
10505 if (!MemUWrite(context
, address
, Bits32(Rt
, 7, 0), 1))
10508 // if wback then R[n] = offset_addr;
10510 if (!WriteRegisterUnsigned(context
, eRegisterKindDWARF
, dwarf_r0
+ n
,
10518 // A8.6.194 STR (immediate, ARM)
10519 bool EmulateInstructionARM::EmulateSTRImmARM(const uint32_t opcode
,
10520 const ARMEncoding encoding
) {
10522 if ConditionPassed() then
10523 EncodingSpecificOperations();
10524 offset_addr
= if add
then (R
[n
] + imm32
) else (R
[n
] - imm32
);
10525 address
= if index then offset_addr
else R
[n
];
10526 MemU
[address
,4] = if t
== 15 then
PCStoreValue() else R
[t
];
10527 if wback then R
[n
] = offset_addr
;
10530 bool success
= false;
10532 if (ConditionPassed(opcode
)) {
10540 const uint32_t addr_byte_size
= GetAddressByteSize();
10542 switch (encoding
) {
10544 // if P == '0' && W == '1' then SEE STRT;
10545 // if Rn == '1101' && P == '1' && U == '0' && W == '1' && imm12 ==
10546 // '000000000100' then SEE PUSH;
10547 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
10548 t
= Bits32(opcode
, 15, 12);
10549 n
= Bits32(opcode
, 19, 16);
10550 imm32
= Bits32(opcode
, 11, 0);
10552 // index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1');
10553 index
= BitIsSet(opcode
, 24);
10554 add
= BitIsSet(opcode
, 23);
10555 wback
= BitIsClear(opcode
, 24) || BitIsSet(opcode
, 21);
10557 // if wback && (n == 15 || n == t) then UNPREDICTABLE;
10558 if (wback
&& ((n
== 15) || (n
== t
)))
10567 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
10568 uint32_t Rn
= ReadCoreReg(n
, &success
);
10572 addr_t offset_addr
;
10574 offset_addr
= Rn
+ imm32
;
10576 offset_addr
= Rn
- imm32
;
10578 // address = if index then offset_addr else R[n];
10581 address
= offset_addr
;
10585 std::optional
<RegisterInfo
> base_reg
=
10586 GetRegisterInfo(eRegisterKindDWARF
, dwarf_r0
+ n
);
10587 std::optional
<RegisterInfo
> data_reg
=
10588 GetRegisterInfo(eRegisterKindDWARF
, dwarf_r0
+ t
);
10589 EmulateInstruction::Context context
;
10590 context
.type
= eContextRegisterStore
;
10591 context
.SetRegisterToRegisterPlusOffset(*data_reg
, *base_reg
, address
- Rn
);
10593 // MemU[address,4] = if t == 15 then PCStoreValue() else R[t];
10594 uint32_t Rt
= ReadCoreReg(t
, &success
);
10599 uint32_t pc_value
= ReadCoreReg(PC_REG
, &success
);
10603 if (!MemUWrite(context
, address
, pc_value
, addr_byte_size
))
10606 if (!MemUWrite(context
, address
, Rt
, addr_byte_size
))
10610 // if wback then R[n] = offset_addr;
10612 context
.type
= eContextAdjustBaseRegister
;
10613 context
.SetImmediate(offset_addr
);
10615 if (!WriteRegisterUnsigned(context
, eRegisterKindDWARF
, dwarf_r0
+ n
,
10623 // A8.6.66 LDRD (immediate)
10624 // Load Register Dual (immediate) calculates an address from a base register
10625 // value and an immediate offset, loads two words from memory, and writes them
10626 // to two registers. It can use offset, post-indexed, or pre-indexed
10628 bool EmulateInstructionARM::EmulateLDRDImmediate(const uint32_t opcode
,
10629 const ARMEncoding encoding
) {
10631 if ConditionPassed() then
10632 EncodingSpecificOperations(); NullCheckIfThumbEE(n
);
10633 offset_addr
= if add
then (R
[n
] + imm32
) else (R
[n
] - imm32
);
10634 address
= if index then offset_addr
else R
[n
];
10635 R
[t
] = MemA
[address
,4];
10636 R
[t2
] = MemA
[address
+4,4];
10637 if wback then R
[n
] = offset_addr
;
10640 bool success
= false;
10642 if (ConditionPassed(opcode
)) {
10651 switch (encoding
) {
10653 // if P == '0' && W == '0' then SEE 'Related encodings';
10654 // if Rn == '1111' then SEE LDRD (literal);
10655 // t = UInt(Rt); t2 = UInt(Rt2); n = UInt(Rn); imm32 =
10656 // ZeroExtend(imm8:'00', 32);
10657 t
= Bits32(opcode
, 15, 12);
10658 t2
= Bits32(opcode
, 11, 8);
10659 n
= Bits32(opcode
, 19, 16);
10660 imm32
= Bits32(opcode
, 7, 0) << 2;
10662 // index = (P == '1'); add = (U == '1'); wback = (W == '1');
10663 index
= BitIsSet(opcode
, 24);
10664 add
= BitIsSet(opcode
, 23);
10665 wback
= BitIsSet(opcode
, 21);
10667 // if wback && (n == t || n == t2) then UNPREDICTABLE;
10668 if (wback
&& ((n
== t
) || (n
== t2
)))
10671 // if BadReg(t) || BadReg(t2) || t == t2 then UNPREDICTABLE;
10672 if (BadReg(t
) || BadReg(t2
) || (t
== t2
))
10678 // if Rn == '1111' then SEE LDRD (literal);
10679 // if Rt<0> == '1' then UNPREDICTABLE;
10680 // t = UInt(Rt); t2 = t+1; n = UInt(Rn); imm32 = ZeroExtend(imm4H:imm4L,
10682 t
= Bits32(opcode
, 15, 12);
10683 if (BitIsSet(t
, 0))
10686 n
= Bits32(opcode
, 19, 16);
10687 imm32
= (Bits32(opcode
, 11, 8) << 4) | Bits32(opcode
, 3, 0);
10689 // index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1');
10690 index
= BitIsSet(opcode
, 24);
10691 add
= BitIsSet(opcode
, 23);
10692 wback
= BitIsClear(opcode
, 24) || BitIsSet(opcode
, 21);
10694 // if P == '0' && W == '1' then UNPREDICTABLE;
10695 if (BitIsClear(opcode
, 24) && BitIsSet(opcode
, 21))
10698 // if wback && (n == t || n == t2) then UNPREDICTABLE;
10699 if (wback
&& ((n
== t
) || (n
== t2
)))
10702 // if t2 == 15 then UNPREDICTABLE;
10712 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
10713 uint32_t Rn
= ReadCoreReg(n
, &success
);
10717 addr_t offset_addr
;
10719 offset_addr
= Rn
+ imm32
;
10721 offset_addr
= Rn
- imm32
;
10723 // address = if index then offset_addr else R[n];
10726 address
= offset_addr
;
10730 // R[t] = MemA[address,4];
10732 EmulateInstruction::Context context
;
10734 context
.type
= eContextPopRegisterOffStack
;
10736 context
.type
= eContextRegisterLoad
;
10737 context
.SetAddress(address
);
10739 const uint32_t addr_byte_size
= GetAddressByteSize();
10740 uint32_t data
= MemARead(context
, address
, addr_byte_size
, 0, &success
);
10744 if (!WriteRegisterUnsigned(context
, eRegisterKindDWARF
, dwarf_r0
+ t
, data
))
10747 // R[t2] = MemA[address+4,4];
10748 context
.SetAddress(address
+ 4);
10749 data
= MemARead(context
, address
+ 4, addr_byte_size
, 0, &success
);
10753 if (!WriteRegisterUnsigned(context
, eRegisterKindDWARF
, dwarf_r0
+ t2
,
10757 // if wback then R[n] = offset_addr;
10759 context
.type
= eContextAdjustBaseRegister
;
10760 context
.SetAddress(offset_addr
);
10762 if (!WriteRegisterUnsigned(context
, eRegisterKindDWARF
, dwarf_r0
+ n
,
10770 // A8.6.68 LDRD (register)
10771 // Load Register Dual (register) calculates an address from a base register
10772 // value and a register offset, loads two words from memory, and writes them to
10773 // two registers. It can use offset, post-indexed or pre-indexed addressing.
10774 bool EmulateInstructionARM::EmulateLDRDRegister(const uint32_t opcode
,
10775 const ARMEncoding encoding
) {
10777 if ConditionPassed() then
10778 EncodingSpecificOperations();
10779 offset_addr
= if add
then (R
[n
] + R
[m
]) else (R
[n
] - R
[m
]);
10780 address
= if index then offset_addr
else R
[n
];
10781 R
[t
] = MemA
[address
,4];
10782 R
[t2
] = MemA
[address
+4,4];
10783 if wback then R
[n
] = offset_addr
;
10786 bool success
= false;
10788 if (ConditionPassed(opcode
)) {
10797 switch (encoding
) {
10799 // if Rt<0> == '1' then UNPREDICTABLE;
10800 // t = UInt(Rt); t2 = t+1; n = UInt(Rn); m = UInt(Rm);
10801 t
= Bits32(opcode
, 15, 12);
10802 if (BitIsSet(t
, 0))
10805 n
= Bits32(opcode
, 19, 16);
10806 m
= Bits32(opcode
, 3, 0);
10808 // index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1');
10809 index
= BitIsSet(opcode
, 24);
10810 add
= BitIsSet(opcode
, 23);
10811 wback
= BitIsClear(opcode
, 24) || BitIsSet(opcode
, 21);
10813 // if P == '0' && W == '1' then UNPREDICTABLE;
10814 if (BitIsClear(opcode
, 24) && BitIsSet(opcode
, 21))
10817 // if t2 == 15 || m == 15 || m == t || m == t2 then UNPREDICTABLE;
10818 if ((t2
== 15) || (m
== 15) || (m
== t
) || (m
== t2
))
10821 // if wback && (n == 15 || n == t || n == t2) then UNPREDICTABLE;
10822 if (wback
&& ((n
== 15) || (n
== t
) || (n
== t2
)))
10825 // if ArchVersion() < 6 && wback && m == n then UNPREDICTABLE;
10826 if ((ArchVersion() < 6) && wback
&& (m
== n
))
10834 uint32_t Rn
= ReadCoreReg(n
, &success
);
10838 uint32_t Rm
= ReadCoreReg(m
, &success
);
10842 // offset_addr = if add then (R[n] + R[m]) else (R[n] - R[m]);
10843 addr_t offset_addr
;
10845 offset_addr
= Rn
+ Rm
;
10847 offset_addr
= Rn
- Rm
;
10849 // address = if index then offset_addr else R[n];
10852 address
= offset_addr
;
10856 EmulateInstruction::Context context
;
10858 context
.type
= eContextPopRegisterOffStack
;
10860 context
.type
= eContextRegisterLoad
;
10861 context
.SetAddress(address
);
10863 // R[t] = MemA[address,4];
10864 const uint32_t addr_byte_size
= GetAddressByteSize();
10865 uint32_t data
= MemARead(context
, address
, addr_byte_size
, 0, &success
);
10869 if (!WriteRegisterUnsigned(context
, eRegisterKindDWARF
, dwarf_r0
+ t
, data
))
10872 // R[t2] = MemA[address+4,4];
10874 data
= MemARead(context
, address
+ 4, addr_byte_size
, 0, &success
);
10878 if (!WriteRegisterUnsigned(context
, eRegisterKindDWARF
, dwarf_r0
+ t2
,
10882 // if wback then R[n] = offset_addr;
10884 context
.type
= eContextAdjustBaseRegister
;
10885 context
.SetAddress(offset_addr
);
10887 if (!WriteRegisterUnsigned(context
, eRegisterKindDWARF
, dwarf_r0
+ n
,
10895 // A8.6.200 STRD (immediate)
10896 // Store Register Dual (immediate) calculates an address from a base register
10897 // value and an immediate offset, and stores two words from two registers to
10898 // memory. It can use offset, post-indexed, or pre-indexed addressing.
10899 bool EmulateInstructionARM::EmulateSTRDImm(const uint32_t opcode
,
10900 const ARMEncoding encoding
) {
10902 if ConditionPassed() then
10903 EncodingSpecificOperations(); NullCheckIfThumbEE(n
);
10904 offset_addr
= if add
then (R
[n
] + imm32
) else (R
[n
] - imm32
);
10905 address
= if index then offset_addr
else R
[n
];
10906 MemA
[address
,4] = R
[t
];
10907 MemA
[address
+4,4] = R
[t2
];
10908 if wback then R
[n
] = offset_addr
;
10911 bool success
= false;
10913 if (ConditionPassed(opcode
)) {
10922 switch (encoding
) {
10924 // if P == '0' && W == '0' then SEE 'Related encodings';
10925 // t = UInt(Rt); t2 = UInt(Rt2); n = UInt(Rn); imm32 =
10926 // ZeroExtend(imm8:'00', 32);
10927 t
= Bits32(opcode
, 15, 12);
10928 t2
= Bits32(opcode
, 11, 8);
10929 n
= Bits32(opcode
, 19, 16);
10930 imm32
= Bits32(opcode
, 7, 0) << 2;
10932 // index = (P == '1'); add = (U == '1'); wback = (W == '1');
10933 index
= BitIsSet(opcode
, 24);
10934 add
= BitIsSet(opcode
, 23);
10935 wback
= BitIsSet(opcode
, 21);
10937 // if wback && (n == t || n == t2) then UNPREDICTABLE;
10938 if (wback
&& ((n
== t
) || (n
== t2
)))
10941 // if n == 15 || BadReg(t) || BadReg(t2) then UNPREDICTABLE;
10942 if ((n
== 15) || BadReg(t
) || BadReg(t2
))
10948 // if Rt<0> == '1' then UNPREDICTABLE;
10949 // t = UInt(Rt); t2 = t+1; n = UInt(Rn); imm32 = ZeroExtend(imm4H:imm4L,
10951 t
= Bits32(opcode
, 15, 12);
10952 if (BitIsSet(t
, 0))
10956 n
= Bits32(opcode
, 19, 16);
10957 imm32
= (Bits32(opcode
, 11, 8) << 4) | Bits32(opcode
, 3, 0);
10959 // index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1');
10960 index
= BitIsSet(opcode
, 24);
10961 add
= BitIsSet(opcode
, 23);
10962 wback
= BitIsClear(opcode
, 24) || BitIsSet(opcode
, 21);
10964 // if P == '0' && W == '1' then UNPREDICTABLE;
10965 if (BitIsClear(opcode
, 24) && BitIsSet(opcode
, 21))
10968 // if wback && (n == 15 || n == t || n == t2) then UNPREDICTABLE;
10969 if (wback
&& ((n
== 15) || (n
== t
) || (n
== t2
)))
10972 // if t2 == 15 then UNPREDICTABLE;
10982 std::optional
<RegisterInfo
> base_reg
=
10983 GetRegisterInfo(eRegisterKindDWARF
, dwarf_r0
+ n
);
10985 uint32_t Rn
= ReadCoreReg(n
, &success
);
10989 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
10990 addr_t offset_addr
;
10992 offset_addr
= Rn
+ imm32
;
10994 offset_addr
= Rn
- imm32
;
10996 // address = if index then offset_addr else R[n];
10999 address
= offset_addr
;
11003 // MemA[address,4] = R[t];
11004 std::optional
<RegisterInfo
> data_reg
=
11005 GetRegisterInfo(eRegisterKindDWARF
, dwarf_r0
+ t
);
11007 uint32_t data
= ReadCoreReg(t
, &success
);
11011 EmulateInstruction::Context context
;
11013 context
.type
= eContextPushRegisterOnStack
;
11015 context
.type
= eContextRegisterStore
;
11016 context
.SetRegisterToRegisterPlusOffset(*data_reg
, *base_reg
, address
- Rn
);
11018 const uint32_t addr_byte_size
= GetAddressByteSize();
11020 if (!MemAWrite(context
, address
, data
, addr_byte_size
))
11023 // MemA[address+4,4] = R[t2];
11024 data_reg
= GetRegisterInfo(eRegisterKindDWARF
, dwarf_r0
+ t2
);
11025 context
.SetRegisterToRegisterPlusOffset(*data_reg
, *base_reg
,
11026 (address
+ 4) - Rn
);
11028 data
= ReadCoreReg(t2
, &success
);
11032 if (!MemAWrite(context
, address
+ 4, data
, addr_byte_size
))
11035 // if wback then R[n] = offset_addr;
11038 context
.type
= eContextAdjustStackPointer
;
11040 context
.type
= eContextAdjustBaseRegister
;
11041 context
.SetAddress(offset_addr
);
11043 if (!WriteRegisterUnsigned(context
, eRegisterKindDWARF
, dwarf_r0
+ n
,
11051 // A8.6.201 STRD (register)
11052 bool EmulateInstructionARM::EmulateSTRDReg(const uint32_t opcode
,
11053 const ARMEncoding encoding
) {
11055 if ConditionPassed() then
11056 EncodingSpecificOperations();
11057 offset_addr
= if add
then (R
[n
] + R
[m
]) else (R
[n
] - R
[m
]);
11058 address
= if index then offset_addr
else R
[n
];
11059 MemA
[address
,4] = R
[t
];
11060 MemA
[address
+4,4] = R
[t2
];
11061 if wback then R
[n
] = offset_addr
;
11064 bool success
= false;
11066 if (ConditionPassed(opcode
)) {
11075 switch (encoding
) {
11077 // if Rt<0> == '1' then UNPREDICTABLE;
11078 // t = UInt(Rt); t2 = t+1; n = UInt(Rn); m = UInt(Rm);
11079 t
= Bits32(opcode
, 15, 12);
11080 if (BitIsSet(t
, 0))
11084 n
= Bits32(opcode
, 19, 16);
11085 m
= Bits32(opcode
, 3, 0);
11087 // index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1');
11088 index
= BitIsSet(opcode
, 24);
11089 add
= BitIsSet(opcode
, 23);
11090 wback
= BitIsClear(opcode
, 24) || BitIsSet(opcode
, 21);
11092 // if P == '0' && W == '1' then UNPREDICTABLE;
11093 if (BitIsClear(opcode
, 24) && BitIsSet(opcode
, 21))
11096 // if t2 == 15 || m == 15 then UNPREDICTABLE;
11097 if ((t2
== 15) || (m
== 15))
11100 // if wback && (n == 15 || n == t || n == t2) then UNPREDICTABLE;
11101 if (wback
&& ((n
== 15) || (n
== t
) || (n
== t2
)))
11104 // if ArchVersion() < 6 && wback && m == n then UNPREDICTABLE;
11105 if ((ArchVersion() < 6) && wback
&& (m
== n
))
11114 uint32_t Rn
= ReadCoreReg(n
, &success
);
11118 uint32_t Rm
= ReadCoreReg(m
, &success
);
11122 // offset_addr = if add then (R[n] + R[m]) else (R[n] - R[m]);
11123 addr_t offset_addr
;
11125 offset_addr
= Rn
+ Rm
;
11127 offset_addr
= Rn
- Rm
;
11129 // address = if index then offset_addr else R[n];
11132 address
= offset_addr
;
11135 // MemA[address,4] = R[t];
11136 uint32_t Rt
= ReadCoreReg(t
, &success
);
11140 EmulateInstruction::Context context
;
11142 context
.type
= eContextPushRegisterOnStack
;
11144 context
.type
= eContextRegisterStore
;
11146 std::optional
<RegisterInfo
> base_reg
=
11147 GetRegisterInfo(eRegisterKindDWARF
, dwarf_r0
+ n
);
11148 std::optional
<RegisterInfo
> offset_reg
=
11149 GetRegisterInfo(eRegisterKindDWARF
, dwarf_r0
+ m
);
11150 std::optional
<RegisterInfo
> data_reg
=
11151 GetRegisterInfo(eRegisterKindDWARF
, dwarf_r0
+ t
);
11152 context
.SetRegisterToRegisterPlusIndirectOffset(*base_reg
, *offset_reg
,
11155 const uint32_t addr_byte_size
= GetAddressByteSize();
11157 if (!MemAWrite(context
, address
, Rt
, addr_byte_size
))
11160 // MemA[address+4,4] = R[t2];
11161 uint32_t Rt2
= ReadCoreReg(t2
, &success
);
11165 data_reg
= GetRegisterInfo(eRegisterKindDWARF
, dwarf_r0
+ t2
);
11167 context
.SetRegisterToRegisterPlusIndirectOffset(*base_reg
, *offset_reg
,
11170 if (!MemAWrite(context
, address
+ 4, Rt2
, addr_byte_size
))
11173 // if wback then R[n] = offset_addr;
11175 context
.type
= eContextAdjustBaseRegister
;
11176 context
.SetAddress(offset_addr
);
11178 if (!WriteRegisterUnsigned(context
, eRegisterKindDWARF
, dwarf_r0
+ n
,
11187 // Vector Load Multiple loads multiple extension registers from consecutive
11188 // memory locations using an address from an ARM core register.
11189 bool EmulateInstructionARM::EmulateVLDM(const uint32_t opcode
,
11190 const ARMEncoding encoding
) {
11192 if ConditionPassed() then
11193 EncodingSpecificOperations(); CheckVFPEnabled(TRUE
); NullCheckIfThumbEE(n
);
11194 address
= if add then R
[n
] else R
[n
]-imm32
;
11195 if wback then R
[n
] = if add then R
[n
]+imm32
else R
[n
]-imm32
;
11196 for r
= 0 to regs
-1
11197 if single_regs then
11198 S
[d
+r
] = MemA
[address
,4]; address
= address
+4;
11200 word1
= MemA
[address
,4]; word2
= MemA
[address
+4,4]; address
= address
+8;
11201 // Combine the word-aligned words in the correct order for
11202 // current endianness.
11203 D
[d
+r
] = if BigEndian() then word1
:word2
else word2
:word1
;
11206 bool success
= false;
11208 if (ConditionPassed(opcode
)) {
11217 switch (encoding
) {
11220 // if P == '0' && U == '0' && W == '0' then SEE 'Related encodings';
11221 // if P == '0' && U == '1' && W == '1' && Rn == '1101' then SEE VPOP;
11222 // if P == '1' && W == '0' then SEE VLDR;
11223 // if P == U && W == '1' then UNDEFINED;
11224 if ((Bit32(opcode
, 24) == Bit32(opcode
, 23)) && BitIsSet(opcode
, 21))
11227 // // Remaining combinations are PUW = 010 (IA without !), 011 (IA with
11228 // !), 101 (DB with !)
11229 // single_regs = FALSE; add = (U == '1'); wback = (W == '1');
11230 single_regs
= false;
11231 add
= BitIsSet(opcode
, 23);
11232 wback
= BitIsSet(opcode
, 21);
11234 // d = UInt(D:Vd); n = UInt(Rn); imm32 = ZeroExtend(imm8:'00', 32);
11235 d
= (Bit32(opcode
, 22) << 4) | Bits32(opcode
, 15, 12);
11236 n
= Bits32(opcode
, 19, 16);
11237 imm32
= Bits32(opcode
, 7, 0) << 2;
11239 // regs = UInt(imm8) DIV 2; // If UInt(imm8) is odd, see 'FLDMX'.
11240 regs
= Bits32(opcode
, 7, 0) / 2;
11242 // if n == 15 && (wback || CurrentInstrSet() != InstrSet_ARM) then
11244 if (n
== 15 && (wback
|| CurrentInstrSet() != eModeARM
))
11247 // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE;
11248 if ((regs
== 0) || (regs
> 16) || ((d
+ regs
) > 32))
11255 // if P == '0' && U == '0' && W == '0' then SEE 'Related encodings';
11256 // if P == '0' && U == '1' && W == '1' && Rn == '1101' then SEE VPOP;
11257 // if P == '1' && W == '0' then SEE VLDR;
11258 // if P == U && W == '1' then UNDEFINED;
11259 if ((Bit32(opcode
, 24) == Bit32(opcode
, 23)) && BitIsSet(opcode
, 21))
11262 // // Remaining combinations are PUW = 010 (IA without !), 011 (IA with
11263 // !), 101 (DB with !) single_regs = TRUE; add = (U == '1'); wback = (W
11265 // UInt(Vd:D); n = UInt(Rn);
11266 single_regs
= true;
11267 add
= BitIsSet(opcode
, 23);
11268 wback
= BitIsSet(opcode
, 21);
11269 d
= (Bits32(opcode
, 15, 12) << 1) | Bit32(opcode
, 22);
11270 n
= Bits32(opcode
, 19, 16);
11272 // imm32 = ZeroExtend(imm8:'00', 32); regs = UInt(imm8);
11273 imm32
= Bits32(opcode
, 7, 0) << 2;
11274 regs
= Bits32(opcode
, 7, 0);
11276 // if n == 15 && (wback || CurrentInstrSet() != InstrSet_ARM) then
11278 if ((n
== 15) && (wback
|| (CurrentInstrSet() != eModeARM
)))
11281 // if regs == 0 || (d+regs) > 32 then UNPREDICTABLE;
11282 if ((regs
== 0) || ((d
+ regs
) > 32))
11290 uint32_t Rn
= ReadCoreReg(n
, &success
);
11294 // address = if add then R[n] else R[n]-imm32;
11299 address
= Rn
- imm32
;
11301 // if wback then R[n] = if add then R[n]+imm32 else R[n]-imm32;
11302 EmulateInstruction::Context context
;
11307 value
= Rn
+ imm32
;
11309 value
= Rn
- imm32
;
11311 context
.type
= eContextAdjustBaseRegister
;
11312 context
.SetImmediateSigned(value
- Rn
);
11313 if (!WriteRegisterUnsigned(context
, eRegisterKindDWARF
, dwarf_r0
+ n
,
11318 const uint32_t addr_byte_size
= GetAddressByteSize();
11319 uint32_t start_reg
= single_regs
? dwarf_s0
: dwarf_d0
;
11321 context
.type
= eContextRegisterLoad
;
11323 std::optional
<RegisterInfo
> base_reg
=
11324 GetRegisterInfo(eRegisterKindDWARF
, dwarf_r0
+ n
);
11326 // for r = 0 to regs-1
11327 for (uint32_t r
= 0; r
< regs
; ++r
) {
11329 // S[d+r] = MemA[address,4]; address = address+4;
11330 context
.SetRegisterPlusOffset(*base_reg
, address
- Rn
);
11332 uint32_t data
= MemARead(context
, address
, addr_byte_size
, 0, &success
);
11336 if (!WriteRegisterUnsigned(context
, eRegisterKindDWARF
,
11337 start_reg
+ d
+ r
, data
))
11340 address
= address
+ 4;
11342 // word1 = MemA[address,4]; word2 = MemA[address+4,4]; address =
11344 context
.SetRegisterPlusOffset(*base_reg
, address
- Rn
);
11346 MemARead(context
, address
, addr_byte_size
, 0, &success
);
11350 context
.SetRegisterPlusOffset(*base_reg
, (address
+ 4) - Rn
);
11352 MemARead(context
, address
+ 4, addr_byte_size
, 0, &success
);
11356 address
= address
+ 8;
11357 // // Combine the word-aligned words in the correct order for current
11359 // D[d+r] = if BigEndian() then word1:word2 else word2:word1;
11361 if (GetByteOrder() == eByteOrderBig
) {
11363 data
= (data
<< 32) | word2
;
11366 data
= (data
<< 32) | word1
;
11369 if (!WriteRegisterUnsigned(context
, eRegisterKindDWARF
,
11370 start_reg
+ d
+ r
, data
))
11379 // Vector Store Multiple stores multiple extension registers to consecutive
11380 // memory locations using an address from an
11381 // ARM core register.
11382 bool EmulateInstructionARM::EmulateVSTM(const uint32_t opcode
,
11383 const ARMEncoding encoding
) {
11385 if ConditionPassed() then
11386 EncodingSpecificOperations(); CheckVFPEnabled(TRUE
); NullCheckIfThumbEE(n
);
11387 address
= if add then R
[n
] else R
[n
]-imm32
;
11388 if wback then R
[n
] = if add then R
[n
]+imm32
else R
[n
]-imm32
;
11389 for r
= 0 to regs
-1
11390 if single_regs then
11391 MemA
[address
,4] = S
[d
+r
]; address
= address
+4;
11393 // Store as two word-aligned words in the correct order for
11394 // current endianness.
11395 MemA
[address
,4] = if BigEndian() then D
[d
+r
]<63:32> else D
[d
+r
]<31:0>;
11396 MemA
[address
+4,4] = if BigEndian() then D
[d
+r
]<31:0> else D
[d
+r
]<63:32>;
11397 address
= address
+8;
11400 bool success
= false;
11402 if (ConditionPassed(opcode
)) {
11411 switch (encoding
) {
11414 // if P == '0' && U == '0' && W == '0' then SEE 'Related encodings';
11415 // if P == '1' && U == '0' && W == '1' && Rn == '1101' then SEE VPUSH;
11416 // if P == '1' && W == '0' then SEE VSTR;
11417 // if P == U && W == '1' then UNDEFINED;
11418 if ((Bit32(opcode
, 24) == Bit32(opcode
, 23)) && BitIsSet(opcode
, 21))
11421 // // Remaining combinations are PUW = 010 (IA without !), 011 (IA with
11422 // !), 101 (DB with !)
11423 // single_regs = FALSE; add = (U == '1'); wback = (W == '1');
11424 single_regs
= false;
11425 add
= BitIsSet(opcode
, 23);
11426 wback
= BitIsSet(opcode
, 21);
11428 // d = UInt(D:Vd); n = UInt(Rn); imm32 = ZeroExtend(imm8:'00', 32);
11429 d
= (Bit32(opcode
, 22) << 4) | Bits32(opcode
, 15, 12);
11430 n
= Bits32(opcode
, 19, 16);
11431 imm32
= Bits32(opcode
, 7, 0) << 2;
11433 // regs = UInt(imm8) DIV 2; // If UInt(imm8) is odd, see 'FSTMX'.
11434 regs
= Bits32(opcode
, 7, 0) / 2;
11436 // if n == 15 && (wback || CurrentInstrSet() != InstrSet_ARM) then
11438 if ((n
== 15) && (wback
|| (CurrentInstrSet() != eModeARM
)))
11441 // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE;
11442 if ((regs
== 0) || (regs
> 16) || ((d
+ regs
) > 32))
11449 // if P == '0' && U == '0' && W == '0' then SEE 'Related encodings';
11450 // if P == '1' && U == '0' && W == '1' && Rn == '1101' then SEE VPUSH;
11451 // if P == '1' && W == '0' then SEE VSTR;
11452 // if P == U && W == '1' then UNDEFINED;
11453 if ((Bit32(opcode
, 24) == Bit32(opcode
, 23)) && BitIsSet(opcode
, 21))
11456 // // Remaining combinations are PUW = 010 (IA without !), 011 (IA with
11457 // !), 101 (DB with !) single_regs = TRUE; add = (U == '1'); wback = (W
11459 // UInt(Vd:D); n = UInt(Rn);
11460 single_regs
= true;
11461 add
= BitIsSet(opcode
, 23);
11462 wback
= BitIsSet(opcode
, 21);
11463 d
= (Bits32(opcode
, 15, 12) << 1) | Bit32(opcode
, 22);
11464 n
= Bits32(opcode
, 19, 16);
11466 // imm32 = ZeroExtend(imm8:'00', 32); regs = UInt(imm8);
11467 imm32
= Bits32(opcode
, 7, 0) << 2;
11468 regs
= Bits32(opcode
, 7, 0);
11470 // if n == 15 && (wback || CurrentInstrSet() != InstrSet_ARM) then
11472 if ((n
== 15) && (wback
|| (CurrentInstrSet() != eModeARM
)))
11475 // if regs == 0 || (d+regs) > 32 then UNPREDICTABLE;
11476 if ((regs
== 0) || ((d
+ regs
) > 32))
11485 std::optional
<RegisterInfo
> base_reg
=
11486 GetRegisterInfo(eRegisterKindDWARF
, dwarf_r0
+ n
);
11488 uint32_t Rn
= ReadCoreReg(n
, &success
);
11492 // address = if add then R[n] else R[n]-imm32;
11497 address
= Rn
- imm32
;
11499 EmulateInstruction::Context context
;
11500 // if wback then R[n] = if add then R[n]+imm32 else R[n]-imm32;
11504 value
= Rn
+ imm32
;
11506 value
= Rn
- imm32
;
11508 context
.type
= eContextAdjustBaseRegister
;
11509 context
.SetRegisterPlusOffset(*base_reg
, value
- Rn
);
11511 if (!WriteRegisterUnsigned(context
, eRegisterKindDWARF
, dwarf_r0
+ n
,
11516 const uint32_t addr_byte_size
= GetAddressByteSize();
11517 uint32_t start_reg
= single_regs
? dwarf_s0
: dwarf_d0
;
11519 context
.type
= eContextRegisterStore
;
11520 // for r = 0 to regs-1
11521 for (uint32_t r
= 0; r
< regs
; ++r
) {
11524 // MemA[address,4] = S[d+r]; address = address+4;
11525 uint32_t data
= ReadRegisterUnsigned(eRegisterKindDWARF
,
11526 start_reg
+ d
+ r
, 0, &success
);
11530 std::optional
<RegisterInfo
> data_reg
=
11531 GetRegisterInfo(eRegisterKindDWARF
, start_reg
+ d
+ r
);
11532 context
.SetRegisterToRegisterPlusOffset(*data_reg
, *base_reg
,
11534 if (!MemAWrite(context
, address
, data
, addr_byte_size
))
11537 address
= address
+ 4;
11539 // // Store as two word-aligned words in the correct order for current
11540 // endianness. MemA[address,4] = if BigEndian() then D[d+r]<63:32> else
11542 // MemA[address+4,4] = if BigEndian() then D[d+r]<31:0> else
11544 uint64_t data
= ReadRegisterUnsigned(eRegisterKindDWARF
,
11545 start_reg
+ d
+ r
, 0, &success
);
11549 std::optional
<RegisterInfo
> data_reg
=
11550 GetRegisterInfo(eRegisterKindDWARF
, start_reg
+ d
+ r
);
11552 if (GetByteOrder() == eByteOrderBig
) {
11553 context
.SetRegisterToRegisterPlusOffset(*data_reg
, *base_reg
,
11555 if (!MemAWrite(context
, address
, Bits64(data
, 63, 32),
11559 context
.SetRegisterToRegisterPlusOffset(*data_reg
, *base_reg
,
11560 (address
+ 4) - Rn
);
11561 if (!MemAWrite(context
, address
+ 4, Bits64(data
, 31, 0),
11565 context
.SetRegisterToRegisterPlusOffset(*data_reg
, *base_reg
,
11567 if (!MemAWrite(context
, address
, Bits64(data
, 31, 0), addr_byte_size
))
11570 context
.SetRegisterToRegisterPlusOffset(*data_reg
, *base_reg
,
11571 (address
+ 4) - Rn
);
11572 if (!MemAWrite(context
, address
+ 4, Bits64(data
, 63, 32),
11576 // address = address+8;
11577 address
= address
+ 8;
11585 // This instruction loads a single extension register from memory, using an
11586 // address from an ARM core register, with an optional offset.
11587 bool EmulateInstructionARM::EmulateVLDR(const uint32_t opcode
,
11588 ARMEncoding encoding
) {
11590 if ConditionPassed() then
11591 EncodingSpecificOperations(); CheckVFPEnabled(TRUE
); NullCheckIfThumbEE(n
);
11592 base
= if n
== 15 then
Align(PC
,4) else R
[n
];
11593 address
= if add
then (base
+ imm32
) else (base
- imm32
);
11595 S
[d
] = MemA
[address
,4];
11597 word1
= MemA
[address
,4]; word2
= MemA
[address
+4,4];
11598 // Combine the word-aligned words in the correct order for current
11600 D
[d
] = if BigEndian() then word1
:word2
else word2
:word1
;
11603 bool success
= false;
11605 if (ConditionPassed(opcode
)) {
11612 switch (encoding
) {
11615 // single_reg = FALSE; add = (U == '1'); imm32 = ZeroExtend(imm8:'00',
11617 single_reg
= false;
11618 add
= BitIsSet(opcode
, 23);
11619 imm32
= Bits32(opcode
, 7, 0) << 2;
11621 // d = UInt(D:Vd); n = UInt(Rn);
11622 d
= (Bit32(opcode
, 22) << 4) | Bits32(opcode
, 15, 12);
11623 n
= Bits32(opcode
, 19, 16);
11629 // single_reg = TRUE; add = (U == '1'); imm32 = ZeroExtend(imm8:'00', 32);
11631 add
= BitIsSet(opcode
, 23);
11632 imm32
= Bits32(opcode
, 7, 0) << 2;
11634 // d = UInt(Vd:D); n = UInt(Rn);
11635 d
= (Bits32(opcode
, 15, 12) << 1) | Bit32(opcode
, 22);
11636 n
= Bits32(opcode
, 19, 16);
11643 std::optional
<RegisterInfo
> base_reg
=
11644 GetRegisterInfo(eRegisterKindDWARF
, dwarf_r0
+ n
);
11646 uint32_t Rn
= ReadCoreReg(n
, &success
);
11650 // base = if n == 15 then Align(PC,4) else R[n];
11653 base
= AlignPC(Rn
);
11657 // address = if add then (base + imm32) else (base - imm32);
11660 address
= base
+ imm32
;
11662 address
= base
- imm32
;
11664 const uint32_t addr_byte_size
= GetAddressByteSize();
11665 uint32_t start_reg
= single_reg
? dwarf_s0
: dwarf_d0
;
11667 EmulateInstruction::Context context
;
11668 context
.type
= eContextRegisterLoad
;
11669 context
.SetRegisterPlusOffset(*base_reg
, address
- base
);
11672 // S[d] = MemA[address,4];
11673 uint32_t data
= MemARead(context
, address
, addr_byte_size
, 0, &success
);
11677 if (!WriteRegisterUnsigned(context
, eRegisterKindDWARF
, start_reg
+ d
,
11681 // word1 = MemA[address,4]; word2 = MemA[address+4,4];
11682 uint32_t word1
= MemARead(context
, address
, addr_byte_size
, 0, &success
);
11686 context
.SetRegisterPlusOffset(*base_reg
, (address
+ 4) - base
);
11688 MemARead(context
, address
+ 4, addr_byte_size
, 0, &success
);
11691 // // Combine the word-aligned words in the correct order for current
11693 // D[d] = if BigEndian() then word1:word2 else word2:word1;
11695 if (GetByteOrder() == eByteOrderBig
) {
11697 data64
= (data64
<< 32) | word2
;
11700 data64
= (data64
<< 32) | word1
;
11703 if (!WriteRegisterUnsigned(context
, eRegisterKindDWARF
, start_reg
+ d
,
11712 // This instruction stores a signle extension register to memory, using an
11713 // address from an ARM core register, with an optional offset.
11714 bool EmulateInstructionARM::EmulateVSTR(const uint32_t opcode
,
11715 ARMEncoding encoding
) {
11717 if ConditionPassed() then
11718 EncodingSpecificOperations(); CheckVFPEnabled(TRUE
); NullCheckIfThumbEE(n
);
11719 address
= if add
then (R
[n
] + imm32
) else (R
[n
] - imm32
);
11721 MemA
[address
,4] = S
[d
];
11723 // Store as two word-aligned words in the correct order for current
11725 MemA
[address
,4] = if BigEndian() then D
[d
]<63:32> else D
[d
]<31:0>;
11726 MemA
[address
+4,4] = if BigEndian() then D
[d
]<31:0> else D
[d
]<63:32>;
11729 bool success
= false;
11731 if (ConditionPassed(opcode
)) {
11738 switch (encoding
) {
11741 // single_reg = FALSE; add = (U == '1'); imm32 = ZeroExtend(imm8:'00',
11743 single_reg
= false;
11744 add
= BitIsSet(opcode
, 23);
11745 imm32
= Bits32(opcode
, 7, 0) << 2;
11747 // d = UInt(D:Vd); n = UInt(Rn);
11748 d
= (Bit32(opcode
, 22) << 4) | Bits32(opcode
, 15, 12);
11749 n
= Bits32(opcode
, 19, 16);
11751 // if n == 15 && CurrentInstrSet() != InstrSet_ARM then UNPREDICTABLE;
11752 if ((n
== 15) && (CurrentInstrSet() != eModeARM
))
11759 // single_reg = TRUE; add = (U == '1'); imm32 = ZeroExtend(imm8:'00', 32);
11761 add
= BitIsSet(opcode
, 23);
11762 imm32
= Bits32(opcode
, 7, 0) << 2;
11764 // d = UInt(Vd:D); n = UInt(Rn);
11765 d
= (Bits32(opcode
, 15, 12) << 1) | Bit32(opcode
, 22);
11766 n
= Bits32(opcode
, 19, 16);
11768 // if n == 15 && CurrentInstrSet() != InstrSet_ARM then UNPREDICTABLE;
11769 if ((n
== 15) && (CurrentInstrSet() != eModeARM
))
11778 uint32_t Rn
= ReadCoreReg(n
, &success
);
11782 // address = if add then (R[n] + imm32) else (R[n] - imm32);
11785 address
= Rn
+ imm32
;
11787 address
= Rn
- imm32
;
11789 const uint32_t addr_byte_size
= GetAddressByteSize();
11790 uint32_t start_reg
= single_reg
? dwarf_s0
: dwarf_d0
;
11792 std::optional
<RegisterInfo
> base_reg
=
11793 GetRegisterInfo(eRegisterKindDWARF
, dwarf_r0
+ n
);
11794 std::optional
<RegisterInfo
> data_reg
=
11795 GetRegisterInfo(eRegisterKindDWARF
, start_reg
+ d
);
11796 EmulateInstruction::Context context
;
11797 context
.type
= eContextRegisterStore
;
11798 context
.SetRegisterToRegisterPlusOffset(*data_reg
, *base_reg
, address
- Rn
);
11801 // MemA[address,4] = S[d];
11803 ReadRegisterUnsigned(eRegisterKindDWARF
, start_reg
+ d
, 0, &success
);
11807 if (!MemAWrite(context
, address
, data
, addr_byte_size
))
11810 // // Store as two word-aligned words in the correct order for current
11812 // MemA[address,4] = if BigEndian() then D[d]<63:32> else D[d]<31:0>;
11813 // MemA[address+4,4] = if BigEndian() then D[d]<31:0> else D[d]<63:32>;
11815 ReadRegisterUnsigned(eRegisterKindDWARF
, start_reg
+ d
, 0, &success
);
11819 if (GetByteOrder() == eByteOrderBig
) {
11820 if (!MemAWrite(context
, address
, Bits64(data
, 63, 32), addr_byte_size
))
11823 context
.SetRegisterToRegisterPlusOffset(*data_reg
, *base_reg
,
11824 (address
+ 4) - Rn
);
11825 if (!MemAWrite(context
, address
+ 4, Bits64(data
, 31, 0),
11829 if (!MemAWrite(context
, address
, Bits64(data
, 31, 0), addr_byte_size
))
11832 context
.SetRegisterToRegisterPlusOffset(*data_reg
, *base_reg
,
11833 (address
+ 4) - Rn
);
11834 if (!MemAWrite(context
, address
+ 4, Bits64(data
, 63, 32),
11843 // A8.6.307 VLDI1 (multiple single elements) This instruction loads elements
11844 // from memory into one, two, three or four registers, without de-interleaving.
11845 // Every element of each register is loaded.
11846 bool EmulateInstructionARM::EmulateVLD1Multiple(const uint32_t opcode
,
11847 ARMEncoding encoding
) {
11849 if ConditionPassed() then
11850 EncodingSpecificOperations(); CheckAdvSIMDEnabled(); NullCheckIfThumbEE(n
);
11851 address
= R
[n
]; if (address MOD alignment
) != 0 then
GenerateAlignmentException();
11852 if wback then R
[n
] = R
[n
] + (if register_index then R
[m
] else 8*regs
);
11853 for r
= 0 to regs
-1
11854 for e
= 0 to elements
-1
11855 Elem
[D
[d
+r
],e
,esize
] = MemU
[address
,ebytes
];
11856 address
= address
+ ebytes
;
11859 bool success
= false;
11861 if (ConditionPassed(opcode
)) {
11863 uint32_t alignment
;
11871 bool register_index
;
11873 switch (encoding
) {
11875 case eEncodingA1
: {
11878 // regs = 1; if align<1> == '1' then UNDEFINED;
11880 // regs = 2; if align == '11' then UNDEFINED;
11882 // regs = 3; if align<1> == '1' then UNDEFINED;
11886 // SEE 'Related encodings';
11887 uint32_t type
= Bits32(opcode
, 11, 8);
11888 uint32_t align
= Bits32(opcode
, 5, 4);
11889 if (type
== 7) // '0111'
11892 if (BitIsSet(align
, 1))
11894 } else if (type
== 10) // '1010'
11900 } else if (type
== 6) // '0110'
11903 if (BitIsSet(align
, 1))
11905 } else if (type
== 2) // '0010'
11911 // alignment = if align == '00' then 1 else 4 << UInt(align);
11915 alignment
= 4 << align
;
11917 // ebytes = 1 << UInt(size); esize = 8 * ebytes; elements = 8 DIV ebytes;
11918 ebytes
= 1 << Bits32(opcode
, 7, 6);
11919 esize
= 8 * ebytes
;
11920 elements
= 8 / ebytes
;
11922 // d = UInt(D:Vd); n = UInt(Rn); m = UInt(Rm);
11923 d
= (Bit32(opcode
, 22) << 4) | Bits32(opcode
, 15, 12);
11924 n
= Bits32(opcode
, 19, 15);
11925 m
= Bits32(opcode
, 3, 0);
11927 // wback = (m != 15); register_index = (m != 15 && m != 13);
11929 register_index
= ((m
!= 15) && (m
!= 13));
11931 // if d+regs > 32 then UNPREDICTABLE;
11932 if ((d
+ regs
) > 32)
11940 std::optional
<RegisterInfo
> base_reg
=
11941 GetRegisterInfo(eRegisterKindDWARF
, dwarf_r0
+ n
);
11943 uint32_t Rn
= ReadCoreReg(n
, &success
);
11947 // address = R[n]; if (address MOD alignment) != 0 then
11948 // GenerateAlignmentException();
11949 addr_t address
= Rn
;
11950 if ((address
% alignment
) != 0)
11953 EmulateInstruction::Context context
;
11954 // if wback then R[n] = R[n] + (if register_index then R[m] else 8*regs);
11956 uint32_t Rm
= ReadCoreReg(m
, &success
);
11961 if (register_index
)
11966 uint32_t value
= Rn
+ offset
;
11967 context
.type
= eContextAdjustBaseRegister
;
11968 context
.SetRegisterPlusOffset(*base_reg
, offset
);
11970 if (!WriteRegisterUnsigned(context
, eRegisterKindDWARF
, dwarf_r0
+ n
,
11975 // for r = 0 to regs-1
11976 for (uint32_t r
= 0; r
< regs
; ++r
) {
11977 // for e = 0 to elements-1
11978 uint64_t assembled_data
= 0;
11979 for (uint32_t e
= 0; e
< elements
; ++e
) {
11980 // Elem[D[d+r],e,esize] = MemU[address,ebytes];
11981 context
.type
= eContextRegisterLoad
;
11982 context
.SetRegisterPlusOffset(*base_reg
, address
- Rn
);
11983 uint64_t data
= MemURead(context
, address
, ebytes
, 0, &success
);
11988 (data
<< (e
* esize
)) |
11989 assembled_data
; // New data goes to the left of existing data
11991 // address = address + ebytes;
11992 address
= address
+ ebytes
;
11994 if (!WriteRegisterUnsigned(context
, eRegisterKindDWARF
, dwarf_d0
+ d
+ r
,
12002 // A8.6.308 VLD1 (single element to one lane)
12004 bool EmulateInstructionARM::EmulateVLD1Single(const uint32_t opcode
,
12005 const ARMEncoding encoding
) {
12007 if ConditionPassed() then
12008 EncodingSpecificOperations(); CheckAdvSIMDEnabled(); NullCheckIfThumbEE(n
);
12009 address
= R
[n
]; if (address MOD alignment
) != 0 then
GenerateAlignmentException();
12010 if wback then R
[n
] = R
[n
] + (if register_index then R
[m
] else ebytes
);
12011 Elem
[D
[d
],index
,esize
] = MemU
[address
,ebytes
];
12014 bool success
= false;
12016 if (ConditionPassed(opcode
)) {
12020 uint32_t alignment
;
12025 bool register_index
;
12027 switch (encoding
) {
12029 case eEncodingA1
: {
12030 uint32_t size
= Bits32(opcode
, 11, 10);
12031 uint32_t index_align
= Bits32(opcode
, 7, 4);
12032 // if size == '11' then SEE VLD1 (single element to all lanes);
12034 return EmulateVLD1SingleAll(opcode
, encoding
);
12036 if (size
== 0) // when '00'
12038 // if index_align<0> != '0' then UNDEFINED;
12039 if (BitIsClear(index_align
, 0))
12042 // ebytes = 1; esize = 8; index = UInt(index_align<3:1>); alignment = 1;
12045 index
= Bits32(index_align
, 3, 1);
12047 } else if (size
== 1) // when '01'
12049 // if index_align<1> != '0' then UNDEFINED;
12050 if (BitIsClear(index_align
, 1))
12053 // ebytes = 2; esize = 16; index = UInt(index_align<3:2>);
12056 index
= Bits32(index_align
, 3, 2);
12058 // alignment = if index_align<0> == '0' then 1 else 2;
12059 if (BitIsClear(index_align
, 0))
12063 } else if (size
== 2) // when '10'
12065 // if index_align<2> != '0' then UNDEFINED;
12066 if (BitIsClear(index_align
, 2))
12069 // if index_align<1:0> != '00' && index_align<1:0> != '11' then
12071 if ((Bits32(index_align
, 1, 0) != 0) &&
12072 (Bits32(index_align
, 1, 0) != 3))
12075 // ebytes = 4; esize = 32; index = UInt(index_align<3>);
12078 index
= Bit32(index_align
, 3);
12080 // alignment = if index_align<1:0> == '00' then 1 else 4;
12081 if (Bits32(index_align
, 1, 0) == 0)
12088 // d = UInt(D:Vd); n = UInt(Rn); m = UInt(Rm);
12089 d
= (Bit32(opcode
, 22) << 4) | Bits32(opcode
, 15, 12);
12090 n
= Bits32(opcode
, 19, 16);
12091 m
= Bits32(opcode
, 3, 0);
12093 // wback = (m != 15); register_index = (m != 15 && m != 13); if n == 15
12094 // then UNPREDICTABLE;
12096 register_index
= ((m
!= 15) && (m
!= 13));
12107 uint32_t Rn
= ReadCoreReg(n
, &success
);
12111 // address = R[n]; if (address MOD alignment) != 0 then
12112 // GenerateAlignmentException();
12113 addr_t address
= Rn
;
12114 if ((address
% alignment
) != 0)
12117 EmulateInstruction::Context context
;
12118 // if wback then R[n] = R[n] + (if register_index then R[m] else ebytes);
12120 uint32_t Rm
= ReadCoreReg(m
, &success
);
12125 if (register_index
)
12130 uint32_t value
= Rn
+ offset
;
12132 context
.type
= eContextAdjustBaseRegister
;
12133 std::optional
<RegisterInfo
> base_reg
=
12134 GetRegisterInfo(eRegisterKindDWARF
, dwarf_r0
+ n
);
12135 context
.SetRegisterPlusOffset(*base_reg
, offset
);
12137 if (!WriteRegisterUnsigned(context
, eRegisterKindDWARF
, dwarf_r0
+ n
,
12142 // Elem[D[d],index,esize] = MemU[address,ebytes];
12143 uint32_t element
= MemURead(context
, address
, esize
, 0, &success
);
12147 element
= element
<< (index
* esize
);
12149 uint64_t reg_data
=
12150 ReadRegisterUnsigned(eRegisterKindDWARF
, dwarf_d0
+ d
, 0, &success
);
12154 uint64_t all_ones
= -1;
12155 uint64_t mask
= all_ones
12156 << ((index
+ 1) * esize
); // mask is all 1's to left of
12157 // where 'element' goes, & all 0's
12158 // at element & to the right of element.
12160 mask
= mask
| Bits64(all_ones
, (index
* esize
) - 1,
12161 0); // add 1's to the right of where 'element' goes.
12162 // now mask should be 0's where element goes & 1's everywhere else.
12164 uint64_t masked_reg
=
12165 reg_data
& mask
; // Take original reg value & zero out 'element' bits
12167 masked_reg
& element
; // Put 'element' into those bits in reg_data.
12169 context
.type
= eContextRegisterLoad
;
12170 if (!WriteRegisterUnsigned(context
, eRegisterKindDWARF
, dwarf_r0
+ d
,
12177 // A8.6.391 VST1 (multiple single elements) Vector Store (multiple single
12178 // elements) stores elements to memory from one, two, three, or four registers,
12179 // without interleaving. Every element of each register is stored.
12180 bool EmulateInstructionARM::EmulateVST1Multiple(const uint32_t opcode
,
12181 ARMEncoding encoding
) {
12183 if ConditionPassed() then
12184 EncodingSpecificOperations(); CheckAdvSIMDEnabled(); NullCheckIfThumbEE(n
);
12185 address
= R
[n
]; if (address MOD alignment
) != 0 then
GenerateAlignmentException();
12186 if wback then R
[n
] = R
[n
] + (if register_index then R
[m
] else 8*regs
);
12187 for r
= 0 to regs
-1
12188 for e
= 0 to elements
-1
12189 MemU
[address
,ebytes
] = Elem
[D
[d
+r
],e
,esize
];
12190 address
= address
+ ebytes
;
12193 bool success
= false;
12195 if (ConditionPassed(opcode
)) {
12197 uint32_t alignment
;
12205 bool register_index
;
12207 switch (encoding
) {
12209 case eEncodingA1
: {
12210 uint32_t type
= Bits32(opcode
, 11, 8);
12211 uint32_t align
= Bits32(opcode
, 5, 4);
12214 if (type
== 7) // when '0111'
12216 // regs = 1; if align<1> == '1' then UNDEFINED;
12218 if (BitIsSet(align
, 1))
12220 } else if (type
== 10) // when '1010'
12222 // regs = 2; if align == '11' then UNDEFINED;
12226 } else if (type
== 6) // when '0110'
12228 // regs = 3; if align<1> == '1' then UNDEFINED;
12230 if (BitIsSet(align
, 1))
12232 } else if (type
== 2) // when '0010'
12236 // SEE 'Related encodings';
12239 // alignment = if align == '00' then 1 else 4 << UInt(align);
12243 alignment
= 4 << align
;
12245 // ebytes = 1 << UInt(size); esize = 8 * ebytes; elements = 8 DIV ebytes;
12246 ebytes
= 1 << Bits32(opcode
, 7, 6);
12247 esize
= 8 * ebytes
;
12248 elements
= 8 / ebytes
;
12250 // d = UInt(D:Vd); n = UInt(Rn); m = UInt(Rm);
12251 d
= (Bit32(opcode
, 22) << 4) | Bits32(opcode
, 15, 12);
12252 n
= Bits32(opcode
, 19, 16);
12253 m
= Bits32(opcode
, 3, 0);
12255 // wback = (m != 15); register_index = (m != 15 && m != 13);
12257 register_index
= ((m
!= 15) && (m
!= 13));
12259 // if d+regs > 32 then UNPREDICTABLE; if n == 15 then UNPREDICTABLE;
12260 if ((d
+ regs
) > 32)
12272 std::optional
<RegisterInfo
> base_reg
=
12273 GetRegisterInfo(eRegisterKindDWARF
, dwarf_r0
+ n
);
12275 uint32_t Rn
= ReadCoreReg(n
, &success
);
12279 // address = R[n]; if (address MOD alignment) != 0 then
12280 // GenerateAlignmentException();
12281 addr_t address
= Rn
;
12282 if ((address
% alignment
) != 0)
12285 EmulateInstruction::Context context
;
12286 // if wback then R[n] = R[n] + (if register_index then R[m] else 8*regs);
12288 uint32_t Rm
= ReadCoreReg(m
, &success
);
12293 if (register_index
)
12298 context
.type
= eContextAdjustBaseRegister
;
12299 context
.SetRegisterPlusOffset(*base_reg
, offset
);
12301 if (!WriteRegisterUnsigned(context
, eRegisterKindDWARF
, dwarf_r0
+ n
,
12306 context
.type
= eContextRegisterStore
;
12307 // for r = 0 to regs-1
12308 for (uint32_t r
= 0; r
< regs
; ++r
) {
12309 std::optional
<RegisterInfo
> data_reg
=
12310 GetRegisterInfo(eRegisterKindDWARF
, dwarf_d0
+ d
+ r
);
12311 uint64_t register_data
= ReadRegisterUnsigned(
12312 eRegisterKindDWARF
, dwarf_d0
+ d
+ r
, 0, &success
);
12316 // for e = 0 to elements-1
12317 for (uint32_t e
= 0; e
< elements
; ++e
) {
12318 // MemU[address,ebytes] = Elem[D[d+r],e,esize];
12319 uint64_t word
= Bits64(register_data
, ((e
+ 1) * esize
) - 1, e
* esize
);
12321 context
.SetRegisterToRegisterPlusOffset(*data_reg
, *base_reg
,
12323 if (!MemUWrite(context
, address
, word
, ebytes
))
12326 // address = address + ebytes;
12327 address
= address
+ ebytes
;
12334 // A8.6.392 VST1 (single element from one lane) This instruction stores one
12335 // element to memory from one element of a register.
12336 bool EmulateInstructionARM::EmulateVST1Single(const uint32_t opcode
,
12337 ARMEncoding encoding
) {
12339 if ConditionPassed() then
12340 EncodingSpecificOperations(); CheckAdvSIMDEnabled(); NullCheckIfThumbEE(n
);
12341 address
= R
[n
]; if (address MOD alignment
) != 0 then
GenerateAlignmentException();
12342 if wback then R
[n
] = R
[n
] + (if register_index then R
[m
] else ebytes
);
12343 MemU
[address
,ebytes
] = Elem
[D
[d
],index
,esize
];
12346 bool success
= false;
12348 if (ConditionPassed(opcode
)) {
12352 uint32_t alignment
;
12357 bool register_index
;
12359 switch (encoding
) {
12361 case eEncodingA1
: {
12362 uint32_t size
= Bits32(opcode
, 11, 10);
12363 uint32_t index_align
= Bits32(opcode
, 7, 4);
12365 // if size == '11' then UNDEFINED;
12370 if (size
== 0) // when '00'
12372 // if index_align<0> != '0' then UNDEFINED;
12373 if (BitIsClear(index_align
, 0))
12375 // ebytes = 1; esize = 8; index = UInt(index_align<3:1>); alignment = 1;
12378 index
= Bits32(index_align
, 3, 1);
12380 } else if (size
== 1) // when '01'
12382 // if index_align<1> != '0' then UNDEFINED;
12383 if (BitIsClear(index_align
, 1))
12386 // ebytes = 2; esize = 16; index = UInt(index_align<3:2>);
12389 index
= Bits32(index_align
, 3, 2);
12391 // alignment = if index_align<0> == '0' then 1 else 2;
12392 if (BitIsClear(index_align
, 0))
12396 } else if (size
== 2) // when '10'
12398 // if index_align<2> != '0' then UNDEFINED;
12399 if (BitIsClear(index_align
, 2))
12402 // if index_align<1:0> != '00' && index_align<1:0> != '11' then
12404 if ((Bits32(index_align
, 1, 0) != 0) &&
12405 (Bits32(index_align
, 1, 0) != 3))
12408 // ebytes = 4; esize = 32; index = UInt(index_align<3>);
12411 index
= Bit32(index_align
, 3);
12413 // alignment = if index_align<1:0> == '00' then 1 else 4;
12414 if (Bits32(index_align
, 1, 0) == 0)
12421 // d = UInt(D:Vd); n = UInt(Rn); m = UInt(Rm);
12422 d
= (Bit32(opcode
, 22) << 4) | Bits32(opcode
, 15, 12);
12423 n
= Bits32(opcode
, 19, 16);
12424 m
= Bits32(opcode
, 3, 0);
12426 // wback = (m != 15); register_index = (m != 15 && m != 13); if n == 15
12427 // then UNPREDICTABLE;
12429 register_index
= ((m
!= 15) && (m
!= 13));
12439 std::optional
<RegisterInfo
> base_reg
=
12440 GetRegisterInfo(eRegisterKindDWARF
, dwarf_r0
+ n
);
12442 uint32_t Rn
= ReadCoreReg(n
, &success
);
12446 // address = R[n]; if (address MOD alignment) != 0 then
12447 // GenerateAlignmentException();
12448 addr_t address
= Rn
;
12449 if ((address
% alignment
) != 0)
12452 EmulateInstruction::Context context
;
12453 // if wback then R[n] = R[n] + (if register_index then R[m] else ebytes);
12455 uint32_t Rm
= ReadCoreReg(m
, &success
);
12460 if (register_index
)
12465 context
.type
= eContextAdjustBaseRegister
;
12466 context
.SetRegisterPlusOffset(*base_reg
, offset
);
12468 if (!WriteRegisterUnsigned(context
, eRegisterKindDWARF
, dwarf_r0
+ n
,
12473 // MemU[address,ebytes] = Elem[D[d],index,esize];
12474 uint64_t register_data
=
12475 ReadRegisterUnsigned(eRegisterKindDWARF
, dwarf_d0
+ d
, 0, &success
);
12480 Bits64(register_data
, ((index
+ 1) * esize
) - 1, index
* esize
);
12482 std::optional
<RegisterInfo
> data_reg
=
12483 GetRegisterInfo(eRegisterKindDWARF
, dwarf_d0
+ d
);
12484 context
.type
= eContextRegisterStore
;
12485 context
.SetRegisterToRegisterPlusOffset(*data_reg
, *base_reg
, address
- Rn
);
12487 if (!MemUWrite(context
, address
, word
, ebytes
))
12493 // A8.6.309 VLD1 (single element to all lanes) This instruction loads one
12494 // element from memory into every element of one or two vectors.
12495 bool EmulateInstructionARM::EmulateVLD1SingleAll(const uint32_t opcode
,
12496 const ARMEncoding encoding
) {
12498 if ConditionPassed() then
12499 EncodingSpecificOperations(); CheckAdvSIMDEnabled(); NullCheckIfThumbEE(n
);
12500 address
= R
[n
]; if (address MOD alignment
) != 0 then
GenerateAlignmentException();
12501 if wback then R
[n
] = R
[n
] + (if register_index then R
[m
] else ebytes
);
12502 replicated_element
= Replicate(MemU
[address
,ebytes
], elements
);
12503 for r
= 0 to regs
-1
12504 D
[d
+r
] = replicated_element
;
12507 bool success
= false;
12509 if (ConditionPassed(opcode
)) {
12513 uint32_t alignment
;
12518 bool register_index
;
12520 switch (encoding
) {
12522 case eEncodingA1
: {
12523 // if size == '11' || (size == '00' && a == '1') then UNDEFINED;
12524 uint32_t size
= Bits32(opcode
, 7, 6);
12525 if ((size
== 3) || ((size
== 0) && BitIsSet(opcode
, 4)))
12528 // ebytes = 1 << UInt(size); elements = 8 DIV ebytes; regs = if T == '0'
12530 ebytes
= 1 << size
;
12531 elements
= 8 / ebytes
;
12532 if (BitIsClear(opcode
, 5))
12537 // alignment = if a == '0' then 1 else ebytes;
12538 if (BitIsClear(opcode
, 4))
12541 alignment
= ebytes
;
12543 // d = UInt(D:Vd); n = UInt(Rn); m = UInt(Rm);
12544 d
= (Bit32(opcode
, 22) << 4) | Bits32(opcode
, 15, 12);
12545 n
= Bits32(opcode
, 19, 16);
12546 m
= Bits32(opcode
, 3, 0);
12548 // wback = (m != 15); register_index = (m != 15 && m != 13);
12550 register_index
= ((m
!= 15) && (m
!= 13));
12552 // if d+regs > 32 then UNPREDICTABLE; if n == 15 then UNPREDICTABLE;
12553 if ((d
+ regs
) > 32)
12564 uint32_t Rn
= ReadCoreReg(n
, &success
);
12568 // address = R[n]; if (address MOD alignment) != 0 then
12569 // GenerateAlignmentException();
12570 addr_t address
= Rn
;
12571 if ((address
% alignment
) != 0)
12574 EmulateInstruction::Context context
;
12575 // if wback then R[n] = R[n] + (if register_index then R[m] else ebytes);
12577 uint32_t Rm
= ReadCoreReg(m
, &success
);
12582 if (register_index
)
12587 context
.type
= eContextAdjustBaseRegister
;
12588 std::optional
<RegisterInfo
> base_reg
=
12589 GetRegisterInfo(eRegisterKindDWARF
, dwarf_r0
+ n
);
12590 context
.SetRegisterPlusOffset(*base_reg
, offset
);
12592 if (!WriteRegisterUnsigned(context
, eRegisterKindDWARF
, dwarf_r0
+ n
,
12597 // replicated_element = Replicate(MemU[address,ebytes], elements);
12599 context
.type
= eContextRegisterLoad
;
12600 uint64_t word
= MemURead(context
, address
, ebytes
, 0, &success
);
12604 uint64_t replicated_element
= 0;
12605 uint32_t esize
= ebytes
* 8;
12606 for (uint32_t e
= 0; e
< elements
; ++e
)
12607 replicated_element
=
12608 (replicated_element
<< esize
) | Bits64(word
, esize
- 1, 0);
12610 // for r = 0 to regs-1
12611 for (uint32_t r
= 0; r
< regs
; ++r
) {
12612 // D[d+r] = replicated_element;
12613 if (!WriteRegisterUnsigned(context
, eRegisterKindDWARF
, dwarf_d0
+ d
+ r
,
12614 replicated_element
))
12621 // B6.2.13 SUBS PC, LR and related instructions The SUBS PC, LR, #<const?
12622 // instruction provides an exception return without the use of the stack. It
12623 // subtracts the immediate constant from the LR, branches to the resulting
12624 // address, and also copies the SPSR to the CPSR.
12625 bool EmulateInstructionARM::EmulateSUBSPcLrEtc(const uint32_t opcode
,
12626 const ARMEncoding encoding
) {
12628 if ConditionPassed() then
12629 EncodingSpecificOperations();
12630 if CurrentInstrSet() == InstrSet_ThumbEE then
12632 operand2
= if register_form then
Shift(R
[m
], shift_t
, shift_n
, APSR
.C
) else imm32
;
12634 when
'0000' result
= R
[n
] AND operand2
; // AND
12635 when
'0001' result
= R
[n
] EOR operand2
; // EOR
12636 when
'0010' (result
, -, -) = AddWithCarry(R
[n
], NOT(operand2
), '1'); // SUB
12637 when
'0011' (result
, -, -) = AddWithCarry(NOT(R
[n
]), operand2
, '1'); // RSB
12638 when
'0100' (result
, -, -) = AddWithCarry(R
[n
], operand2
, '0'); // ADD
12639 when
'0101' (result
, -, -) = AddWithCarry(R
[n
], operand2
, APSR
.c
); // ADC
12640 when
'0110' (result
, -, -) = AddWithCarry(R
[n
], NOT(operand2
), APSR
.C
); // SBC
12641 when
'0111' (result
, -, -) = AddWithCarry(NOT(R
[n
]), operand2
, APSR
.C
); // RSC
12642 when
'1100' result
= R
[n
] OR operand2
; // ORR
12643 when
'1101' result
= operand2
; // MOV
12644 when
'1110' result
= R
[n
] AND
NOT(operand2
); // BIC
12645 when
'1111' result
= NOT(operand2
); // MVN
12646 CPSRWriteByInstr(SPSR
[], '1111', TRUE
);
12647 BranchWritePC(result
);
12650 bool success
= false;
12652 if (ConditionPassed(opcode
)) {
12656 bool register_form
;
12657 ARM_ShifterType shift_t
;
12661 switch (encoding
) {
12663 // if CurrentInstrSet() == InstrSet_ThumbEE then UNPREDICTABLE n = 14;
12664 // imm32 = ZeroExtend(imm8, 32); register_form = FALSE; opcode = '0010';
12667 imm32
= Bits32(opcode
, 7, 0);
12668 register_form
= false;
12671 // if InITBlock() && !LastInITBlock() then UNPREDICTABLE;
12672 if (InITBlock() && !LastInITBlock())
12678 // n = UInt(Rn); imm32 = ARMExpandImm(imm12); register_form = FALSE;
12679 n
= Bits32(opcode
, 19, 16);
12680 imm32
= ARMExpandImm(opcode
);
12681 register_form
= false;
12682 code
= Bits32(opcode
, 24, 21);
12687 // n = UInt(Rn); m = UInt(Rm); register_form = TRUE;
12688 n
= Bits32(opcode
, 19, 16);
12689 m
= Bits32(opcode
, 3, 0);
12690 register_form
= true;
12692 // (shift_t, shift_n) = DecodeImmShift(type, imm5);
12693 shift_n
= DecodeImmShiftARM(opcode
, shift_t
);
12701 // operand2 = if register_form then Shift(R[m], shift_t, shift_n, APSR.C)
12704 if (register_form
) {
12705 uint32_t Rm
= ReadCoreReg(m
, &success
);
12709 operand2
= Shift(Rm
, shift_t
, shift_n
, APSR_C
, &success
);
12716 uint32_t Rn
= ReadCoreReg(n
, &success
);
12720 AddWithCarryResult result
;
12724 case 0: // when '0000'
12725 // result = R[n] AND operand2; // AND
12726 result
.result
= Rn
& operand2
;
12729 case 1: // when '0001'
12730 // result = R[n] EOR operand2; // EOR
12731 result
.result
= Rn
^ operand2
;
12734 case 2: // when '0010'
12735 // (result, -, -) = AddWithCarry(R[n], NOT(operand2), '1'); // SUB
12736 result
= AddWithCarry(Rn
, ~(operand2
), 1);
12739 case 3: // when '0011'
12740 // (result, -, -) = AddWithCarry(NOT(R[n]), operand2, '1'); // RSB
12741 result
= AddWithCarry(~(Rn
), operand2
, 1);
12744 case 4: // when '0100'
12745 // (result, -, -) = AddWithCarry(R[n], operand2, '0'); // ADD
12746 result
= AddWithCarry(Rn
, operand2
, 0);
12749 case 5: // when '0101'
12750 // (result, -, -) = AddWithCarry(R[n], operand2, APSR.c); // ADC
12751 result
= AddWithCarry(Rn
, operand2
, APSR_C
);
12754 case 6: // when '0110'
12755 // (result, -, -) = AddWithCarry(R[n], NOT(operand2), APSR.C); // SBC
12756 result
= AddWithCarry(Rn
, ~(operand2
), APSR_C
);
12759 case 7: // when '0111'
12760 // (result, -, -) = AddWithCarry(NOT(R[n]), operand2, APSR.C); // RSC
12761 result
= AddWithCarry(~(Rn
), operand2
, APSR_C
);
12764 case 10: // when '1100'
12765 // result = R[n] OR operand2; // ORR
12766 result
.result
= Rn
| operand2
;
12769 case 11: // when '1101'
12770 // result = operand2; // MOV
12771 result
.result
= operand2
;
12774 case 12: // when '1110'
12775 // result = R[n] AND NOT(operand2); // BIC
12776 result
.result
= Rn
& ~(operand2
);
12779 case 15: // when '1111'
12780 // result = NOT(operand2); // MVN
12781 result
.result
= ~(operand2
);
12787 // CPSRWriteByInstr(SPSR[], '1111', TRUE);
12789 // For now, in emulation mode, we don't have access to the SPSR, so we will
12790 // use the CPSR instead, and hope for the best.
12792 ReadRegisterUnsigned(eRegisterKindDWARF
, dwarf_cpsr
, 0, &success
);
12796 CPSRWriteByInstr(spsr
, 15, true);
12798 // BranchWritePC(result);
12799 EmulateInstruction::Context context
;
12800 context
.type
= eContextAdjustPC
;
12801 context
.SetImmediate(result
.result
);
12803 BranchWritePC(context
, result
.result
);
12808 EmulateInstructionARM::ARMOpcode
*
12809 EmulateInstructionARM::GetARMOpcodeForInstruction(const uint32_t opcode
,
12810 uint32_t arm_isa
) {
12811 static ARMOpcode g_arm_opcodes
[] = {
12812 // Prologue instructions
12814 // push register(s)
12815 {0x0fff0000, 0x092d0000, ARMvAll
, eEncodingA1
, No_VFP
, eSize32
,
12816 &EmulateInstructionARM::EmulatePUSH
, "push <registers>"},
12817 {0x0fff0fff, 0x052d0004, ARMvAll
, eEncodingA2
, No_VFP
, eSize32
,
12818 &EmulateInstructionARM::EmulatePUSH
, "push <register>"},
12820 // set r7 to point to a stack offset
12821 {0x0ffff000, 0x028d7000, ARMvAll
, eEncodingA1
, No_VFP
, eSize32
,
12822 &EmulateInstructionARM::EmulateADDRdSPImm
, "add r7, sp, #<const>"},
12823 {0x0ffff000, 0x024c7000, ARMvAll
, eEncodingA1
, No_VFP
, eSize32
,
12824 &EmulateInstructionARM::EmulateSUBR7IPImm
, "sub r7, ip, #<const>"},
12825 // copy the stack pointer to ip
12826 {0x0fffffff, 0x01a0c00d, ARMvAll
, eEncodingA1
, No_VFP
, eSize32
,
12827 &EmulateInstructionARM::EmulateMOVRdSP
, "mov ip, sp"},
12828 {0x0ffff000, 0x028dc000, ARMvAll
, eEncodingA1
, No_VFP
, eSize32
,
12829 &EmulateInstructionARM::EmulateADDRdSPImm
, "add ip, sp, #<const>"},
12830 {0x0ffff000, 0x024dc000, ARMvAll
, eEncodingA1
, No_VFP
, eSize32
,
12831 &EmulateInstructionARM::EmulateSUBIPSPImm
, "sub ip, sp, #<const>"},
12833 // adjust the stack pointer
12834 {0x0ffff000, 0x024dd000, ARMvAll
, eEncodingA1
, No_VFP
, eSize32
,
12835 &EmulateInstructionARM::EmulateSUBSPImm
, "sub sp, sp, #<const>"},
12836 {0x0fef0010, 0x004d0000, ARMvAll
, eEncodingA1
, No_VFP
, eSize32
,
12837 &EmulateInstructionARM::EmulateSUBSPReg
,
12838 "sub{s}<c> <Rd>, sp, <Rm>{,<shift>}"},
12840 // push one register
12841 // if Rn == '1101' && imm12 == '000000000100' then SEE PUSH;
12842 {0x0e5f0000, 0x040d0000, ARMvAll
, eEncodingA1
, No_VFP
, eSize32
,
12843 &EmulateInstructionARM::EmulateSTRRtSP
, "str Rt, [sp, #-imm12]!"},
12845 // vector push consecutive extension register(s)
12846 {0x0fbf0f00, 0x0d2d0b00, ARMV6T2_ABOVE
, eEncodingA1
, No_VFP
, eSize32
,
12847 &EmulateInstructionARM::EmulateVPUSH
, "vpush.64 <list>"},
12848 {0x0fbf0f00, 0x0d2d0a00, ARMV6T2_ABOVE
, eEncodingA2
, No_VFP
, eSize32
,
12849 &EmulateInstructionARM::EmulateVPUSH
, "vpush.32 <list>"},
12851 // Epilogue instructions
12853 {0x0fff0000, 0x08bd0000, ARMvAll
, eEncodingA1
, No_VFP
, eSize32
,
12854 &EmulateInstructionARM::EmulatePOP
, "pop <registers>"},
12855 {0x0fff0fff, 0x049d0004, ARMvAll
, eEncodingA2
, No_VFP
, eSize32
,
12856 &EmulateInstructionARM::EmulatePOP
, "pop <register>"},
12857 {0x0fbf0f00, 0x0cbd0b00, ARMV6T2_ABOVE
, eEncodingA1
, No_VFP
, eSize32
,
12858 &EmulateInstructionARM::EmulateVPOP
, "vpop.64 <list>"},
12859 {0x0fbf0f00, 0x0cbd0a00, ARMV6T2_ABOVE
, eEncodingA2
, No_VFP
, eSize32
,
12860 &EmulateInstructionARM::EmulateVPOP
, "vpop.32 <list>"},
12862 // Supervisor Call (previously Software Interrupt)
12863 {0x0f000000, 0x0f000000, ARMvAll
, eEncodingA1
, No_VFP
, eSize32
,
12864 &EmulateInstructionARM::EmulateSVC
, "svc #imm24"},
12866 // Branch instructions
12867 // To resolve ambiguity, "blx <label>" should come before "b #imm24" and
12869 {0xfe000000, 0xfa000000, ARMV5_ABOVE
, eEncodingA2
, No_VFP
, eSize32
,
12870 &EmulateInstructionARM::EmulateBLXImmediate
, "blx <label>"},
12871 {0x0f000000, 0x0a000000, ARMvAll
, eEncodingA1
, No_VFP
, eSize32
,
12872 &EmulateInstructionARM::EmulateB
, "b #imm24"},
12873 {0x0f000000, 0x0b000000, ARMvAll
, eEncodingA1
, No_VFP
, eSize32
,
12874 &EmulateInstructionARM::EmulateBLXImmediate
, "bl <label>"},
12875 {0x0ffffff0, 0x012fff30, ARMV5_ABOVE
, eEncodingA1
, No_VFP
, eSize32
,
12876 &EmulateInstructionARM::EmulateBLXRm
, "blx <Rm>"},
12877 // for example, "bx lr"
12878 {0x0ffffff0, 0x012fff10, ARMvAll
, eEncodingA1
, No_VFP
, eSize32
,
12879 &EmulateInstructionARM::EmulateBXRm
, "bx <Rm>"},
12881 {0x0ffffff0, 0x012fff20, ARMvAll
, eEncodingA1
, No_VFP
, eSize32
,
12882 &EmulateInstructionARM::EmulateBXJRm
, "bxj <Rm>"},
12884 // Data-processing instructions
12886 {0x0fe00000, 0x02a00000, ARMvAll
, eEncodingA1
, No_VFP
, eSize32
,
12887 &EmulateInstructionARM::EmulateADCImm
, "adc{s}<c> <Rd>, <Rn>, #const"},
12889 {0x0fe00010, 0x00a00000, ARMvAll
, eEncodingA1
, No_VFP
, eSize32
,
12890 &EmulateInstructionARM::EmulateADCReg
,
12891 "adc{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
12893 {0x0fe00000, 0x02800000, ARMvAll
, eEncodingA1
, No_VFP
, eSize32
,
12894 &EmulateInstructionARM::EmulateADDImmARM
,
12895 "add{s}<c> <Rd>, <Rn>, #const"},
12897 {0x0fe00010, 0x00800000, ARMvAll
, eEncodingA1
, No_VFP
, eSize32
,
12898 &EmulateInstructionARM::EmulateADDReg
,
12899 "add{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
12900 // add (register-shifted register)
12901 {0x0fe00090, 0x00800010, ARMvAll
, eEncodingA1
, No_VFP
, eSize32
,
12902 &EmulateInstructionARM::EmulateADDRegShift
,
12903 "add{s}<c> <Rd>, <Rn>, <Rm>, <type> <RS>"},
12905 {0x0fff0000, 0x028f0000, ARMvAll
, eEncodingA1
, No_VFP
, eSize32
,
12906 &EmulateInstructionARM::EmulateADR
, "add<c> <Rd>, PC, #<const>"},
12907 {0x0fff0000, 0x024f0000, ARMvAll
, eEncodingA2
, No_VFP
, eSize32
,
12908 &EmulateInstructionARM::EmulateADR
, "sub<c> <Rd>, PC, #<const>"},
12910 {0x0fe00000, 0x02000000, ARMvAll
, eEncodingA1
, No_VFP
, eSize32
,
12911 &EmulateInstructionARM::EmulateANDImm
, "and{s}<c> <Rd>, <Rn>, #const"},
12913 {0x0fe00010, 0x00000000, ARMvAll
, eEncodingA1
, No_VFP
, eSize32
,
12914 &EmulateInstructionARM::EmulateANDReg
,
12915 "and{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
12917 {0x0fe00000, 0x03c00000, ARMvAll
, eEncodingA1
, No_VFP
, eSize32
,
12918 &EmulateInstructionARM::EmulateBICImm
, "bic{s}<c> <Rd>, <Rn>, #const"},
12920 {0x0fe00010, 0x01c00000, ARMvAll
, eEncodingA1
, No_VFP
, eSize32
,
12921 &EmulateInstructionARM::EmulateBICReg
,
12922 "bic{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
12924 {0x0fe00000, 0x02200000, ARMvAll
, eEncodingA1
, No_VFP
, eSize32
,
12925 &EmulateInstructionARM::EmulateEORImm
, "eor{s}<c> <Rd>, <Rn>, #const"},
12927 {0x0fe00010, 0x00200000, ARMvAll
, eEncodingA1
, No_VFP
, eSize32
,
12928 &EmulateInstructionARM::EmulateEORReg
,
12929 "eor{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
12931 {0x0fe00000, 0x03800000, ARMvAll
, eEncodingA1
, No_VFP
, eSize32
,
12932 &EmulateInstructionARM::EmulateORRImm
, "orr{s}<c> <Rd>, <Rn>, #const"},
12934 {0x0fe00010, 0x01800000, ARMvAll
, eEncodingA1
, No_VFP
, eSize32
,
12935 &EmulateInstructionARM::EmulateORRReg
,
12936 "orr{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
12938 {0x0fe00000, 0x02600000, ARMvAll
, eEncodingA1
, No_VFP
, eSize32
,
12939 &EmulateInstructionARM::EmulateRSBImm
, "rsb{s}<c> <Rd>, <Rn>, #<const>"},
12941 {0x0fe00010, 0x00600000, ARMvAll
, eEncodingA1
, No_VFP
, eSize32
,
12942 &EmulateInstructionARM::EmulateRSBReg
,
12943 "rsb{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
12945 {0x0fe00000, 0x02e00000, ARMvAll
, eEncodingA1
, No_VFP
, eSize32
,
12946 &EmulateInstructionARM::EmulateRSCImm
, "rsc{s}<c> <Rd>, <Rn>, #<const>"},
12948 {0x0fe00010, 0x00e00000, ARMvAll
, eEncodingA1
, No_VFP
, eSize32
,
12949 &EmulateInstructionARM::EmulateRSCReg
,
12950 "rsc{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
12952 {0x0fe00000, 0x02c00000, ARMvAll
, eEncodingA1
, No_VFP
, eSize32
,
12953 &EmulateInstructionARM::EmulateSBCImm
, "sbc{s}<c> <Rd>, <Rn>, #<const>"},
12955 {0x0fe00010, 0x00c00000, ARMvAll
, eEncodingA1
, No_VFP
, eSize32
,
12956 &EmulateInstructionARM::EmulateSBCReg
,
12957 "sbc{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
12958 // sub (immediate, ARM)
12959 {0x0fe00000, 0x02400000, ARMvAll
, eEncodingA1
, No_VFP
, eSize32
,
12960 &EmulateInstructionARM::EmulateSUBImmARM
,
12961 "sub{s}<c> <Rd>, <Rn>, #<const>"},
12962 // sub (sp minus immediate)
12963 {0x0fef0000, 0x024d0000, ARMvAll
, eEncodingA1
, No_VFP
, eSize32
,
12964 &EmulateInstructionARM::EmulateSUBSPImm
, "sub{s}<c> <Rd>, sp, #<const>"},
12966 {0x0fe00010, 0x00400000, ARMvAll
, eEncodingA1
, No_VFP
, eSize32
,
12967 &EmulateInstructionARM::EmulateSUBReg
,
12968 "sub{s}<c> <Rd>, <Rn>, <Rm>{,<shift>}"},
12970 {0x0ff0f000, 0x03300000, ARMvAll
, eEncodingA1
, No_VFP
, eSize32
,
12971 &EmulateInstructionARM::EmulateTEQImm
, "teq<c> <Rn>, #const"},
12973 {0x0ff0f010, 0x01300000, ARMvAll
, eEncodingA1
, No_VFP
, eSize32
,
12974 &EmulateInstructionARM::EmulateTEQReg
, "teq<c> <Rn>, <Rm> {,<shift>}"},
12976 {0x0ff0f000, 0x03100000, ARMvAll
, eEncodingA1
, No_VFP
, eSize32
,
12977 &EmulateInstructionARM::EmulateTSTImm
, "tst<c> <Rn>, #const"},
12979 {0x0ff0f010, 0x01100000, ARMvAll
, eEncodingA1
, No_VFP
, eSize32
,
12980 &EmulateInstructionARM::EmulateTSTReg
, "tst<c> <Rn>, <Rm> {,<shift>}"},
12983 {0x0fef0000, 0x03a00000, ARMvAll
, eEncodingA1
, No_VFP
, eSize32
,
12984 &EmulateInstructionARM::EmulateMOVRdImm
, "mov{s}<c> <Rd>, #<const>"},
12985 {0x0ff00000, 0x03000000, ARMV6T2_ABOVE
, eEncodingA2
, No_VFP
, eSize32
,
12986 &EmulateInstructionARM::EmulateMOVRdImm
, "movw<c> <Rd>, #<imm16>"},
12988 {0x0fef0ff0, 0x01a00000, ARMvAll
, eEncodingA1
, No_VFP
, eSize32
,
12989 &EmulateInstructionARM::EmulateMOVRdRm
, "mov{s}<c> <Rd>, <Rm>"},
12991 {0x0fef0000, 0x03e00000, ARMvAll
, eEncodingA1
, No_VFP
, eSize32
,
12992 &EmulateInstructionARM::EmulateMVNImm
, "mvn{s}<c> <Rd>, #<const>"},
12994 {0x0fef0010, 0x01e00000, ARMvAll
, eEncodingA1
, No_VFP
, eSize32
,
12995 &EmulateInstructionARM::EmulateMVNReg
,
12996 "mvn{s}<c> <Rd>, <Rm> {,<shift>}"},
12998 {0x0ff0f000, 0x03700000, ARMvAll
, eEncodingA1
, No_VFP
, eSize32
,
12999 &EmulateInstructionARM::EmulateCMNImm
, "cmn<c> <Rn>, #<const>"},
13001 {0x0ff0f010, 0x01700000, ARMvAll
, eEncodingA1
, No_VFP
, eSize32
,
13002 &EmulateInstructionARM::EmulateCMNReg
, "cmn<c> <Rn>, <Rm> {,<shift>}"},
13004 {0x0ff0f000, 0x03500000, ARMvAll
, eEncodingA1
, No_VFP
, eSize32
,
13005 &EmulateInstructionARM::EmulateCMPImm
, "cmp<c> <Rn>, #<const>"},
13007 {0x0ff0f010, 0x01500000, ARMvAll
, eEncodingA1
, No_VFP
, eSize32
,
13008 &EmulateInstructionARM::EmulateCMPReg
, "cmp<c> <Rn>, <Rm> {,<shift>}"},
13010 {0x0fef0070, 0x01a00040, ARMvAll
, eEncodingA1
, No_VFP
, eSize32
,
13011 &EmulateInstructionARM::EmulateASRImm
, "asr{s}<c> <Rd>, <Rm>, #imm"},
13013 {0x0fef00f0, 0x01a00050, ARMvAll
, eEncodingA1
, No_VFP
, eSize32
,
13014 &EmulateInstructionARM::EmulateASRReg
, "asr{s}<c> <Rd>, <Rn>, <Rm>"},
13016 {0x0fef0070, 0x01a00000, ARMvAll
, eEncodingA1
, No_VFP
, eSize32
,
13017 &EmulateInstructionARM::EmulateLSLImm
, "lsl{s}<c> <Rd>, <Rm>, #imm"},
13019 {0x0fef00f0, 0x01a00010, ARMvAll
, eEncodingA1
, No_VFP
, eSize32
,
13020 &EmulateInstructionARM::EmulateLSLReg
, "lsl{s}<c> <Rd>, <Rn>, <Rm>"},
13022 {0x0fef0070, 0x01a00020, ARMvAll
, eEncodingA1
, No_VFP
, eSize32
,
13023 &EmulateInstructionARM::EmulateLSRImm
, "lsr{s}<c> <Rd>, <Rm>, #imm"},
13025 {0x0fef00f0, 0x01a00050, ARMvAll
, eEncodingA1
, No_VFP
, eSize32
,
13026 &EmulateInstructionARM::EmulateLSRReg
, "lsr{s}<c> <Rd>, <Rn>, <Rm>"},
13027 // rrx is a special case encoding of ror (immediate)
13028 {0x0fef0ff0, 0x01a00060, ARMvAll
, eEncodingA1
, No_VFP
, eSize32
,
13029 &EmulateInstructionARM::EmulateRRX
, "rrx{s}<c> <Rd>, <Rm>"},
13031 {0x0fef0070, 0x01a00060, ARMvAll
, eEncodingA1
, No_VFP
, eSize32
,
13032 &EmulateInstructionARM::EmulateRORImm
, "ror{s}<c> <Rd>, <Rm>, #imm"},
13034 {0x0fef00f0, 0x01a00070, ARMvAll
, eEncodingA1
, No_VFP
, eSize32
,
13035 &EmulateInstructionARM::EmulateRORReg
, "ror{s}<c> <Rd>, <Rn>, <Rm>"},
13037 {0x0fe000f0, 0x00000090, ARMvAll
, eEncodingA1
, No_VFP
, eSize32
,
13038 &EmulateInstructionARM::EmulateMUL
, "mul{s}<c> <Rd>,<R>,<Rm>"},
13040 // subs pc, lr and related instructions
13041 {0x0e10f000, 0x0210f000, ARMvAll
, eEncodingA1
, No_VFP
, eSize32
,
13042 &EmulateInstructionARM::EmulateSUBSPcLrEtc
,
13043 "<opc>S<c> PC,#<const> | <Rn>,#<const>"},
13044 {0x0e10f010, 0x0010f000, ARMvAll
, eEncodingA2
, No_VFP
, eSize32
,
13045 &EmulateInstructionARM::EmulateSUBSPcLrEtc
,
13046 "<opc>S<c> PC,<Rn>,<Rm{,<shift>}"},
13048 // Load instructions
13049 {0x0fd00000, 0x08900000, ARMvAll
, eEncodingA1
, No_VFP
, eSize32
,
13050 &EmulateInstructionARM::EmulateLDM
, "ldm<c> <Rn>{!} <registers>"},
13051 {0x0fd00000, 0x08100000, ARMvAll
, eEncodingA1
, No_VFP
, eSize32
,
13052 &EmulateInstructionARM::EmulateLDMDA
, "ldmda<c> <Rn>{!} <registers>"},
13053 {0x0fd00000, 0x09100000, ARMvAll
, eEncodingA1
, No_VFP
, eSize32
,
13054 &EmulateInstructionARM::EmulateLDMDB
, "ldmdb<c> <Rn>{!} <registers>"},
13055 {0x0fd00000, 0x09900000, ARMvAll
, eEncodingA1
, No_VFP
, eSize32
,
13056 &EmulateInstructionARM::EmulateLDMIB
, "ldmib<c> <Rn<{!} <registers>"},
13057 {0x0e500000, 0x04100000, ARMvAll
, eEncodingA1
, No_VFP
, eSize32
,
13058 &EmulateInstructionARM::EmulateLDRImmediateARM
,
13059 "ldr<c> <Rt> [<Rn> {#+/-<imm12>}]"},
13060 {0x0e500010, 0x06100000, ARMvAll
, eEncodingA1
, No_VFP
, eSize32
,
13061 &EmulateInstructionARM::EmulateLDRRegister
,
13062 "ldr<c> <Rt> [<Rn> +/-<Rm> {<shift>}] {!}"},
13063 {0x0e5f0000, 0x045f0000, ARMvAll
, eEncodingA1
, No_VFP
, eSize32
,
13064 &EmulateInstructionARM::EmulateLDRBLiteral
, "ldrb<c> <Rt>, [...]"},
13065 {0xfe500010, 0x06500000, ARMvAll
, eEncodingA1
, No_VFP
, eSize32
,
13066 &EmulateInstructionARM::EmulateLDRBRegister
,
13067 "ldrb<c> <Rt>, [<Rn>,+/-<Rm>{, <shift>}]{!}"},
13068 {0x0e5f00f0, 0x005f00b0, ARMvAll
, eEncodingA1
, No_VFP
, eSize32
,
13069 &EmulateInstructionARM::EmulateLDRHLiteral
, "ldrh<c> <Rt>, <label>"},
13070 {0x0e5000f0, 0x001000b0, ARMvAll
, eEncodingA1
, No_VFP
, eSize32
,
13071 &EmulateInstructionARM::EmulateLDRHRegister
,
13072 "ldrh<c> <Rt>,[<Rn>,+/-<Rm>]{!}"},
13073 {0x0e5000f0, 0x005000d0, ARMvAll
, eEncodingA1
, No_VFP
, eSize32
,
13074 &EmulateInstructionARM::EmulateLDRSBImmediate
,
13075 "ldrsb<c> <Rt>, [<Rn>{,#+/-<imm8>}]"},
13076 {0x0e5f00f0, 0x005f00d0, ARMvAll
, eEncodingA1
, No_VFP
, eSize32
,
13077 &EmulateInstructionARM::EmulateLDRSBLiteral
, "ldrsb<c> <Rt> <label>"},
13078 {0x0e5000f0, 0x001000d0, ARMvAll
, eEncodingA1
, No_VFP
, eSize32
,
13079 &EmulateInstructionARM::EmulateLDRSBRegister
,
13080 "ldrsb<c> <Rt>,[<Rn>,+/-<Rm>]{!}"},
13081 {0x0e5000f0, 0x005000f0, ARMvAll
, eEncodingA1
, No_VFP
, eSize32
,
13082 &EmulateInstructionARM::EmulateLDRSHImmediate
,
13083 "ldrsh<c> <Rt>,[<Rn>{,#+/-<imm8>}]"},
13084 {0x0e5f00f0, 0x005f00f0, ARMvAll
, eEncodingA1
, No_VFP
, eSize32
,
13085 &EmulateInstructionARM::EmulateLDRSHLiteral
, "ldrsh<c> <Rt>,<label>"},
13086 {0x0e5000f0, 0x001000f0, ARMvAll
, eEncodingA1
, No_VFP
, eSize32
,
13087 &EmulateInstructionARM::EmulateLDRSHRegister
,
13088 "ldrsh<c> <Rt>,[<Rn>,+/-<Rm>]{!}"},
13089 {0x0e5000f0, 0x004000d0, ARMV5TE_ABOVE
, eEncodingA1
, No_VFP
, eSize32
,
13090 &EmulateInstructionARM::EmulateLDRDImmediate
,
13091 "ldrd<c> <Rt>, <Rt2>, [<Rn>,#+/-<imm8>]!"},
13092 {0x0e500ff0, 0x000000d0, ARMV5TE_ABOVE
, eEncodingA1
, No_VFP
, eSize32
,
13093 &EmulateInstructionARM::EmulateLDRDRegister
,
13094 "ldrd<c> <Rt>, <Rt2>, [<Rn>, +/-<Rm>]{!}"},
13095 {0x0e100f00, 0x0c100b00, ARMvAll
, eEncodingA1
, VFPv2_ABOVE
, eSize32
,
13096 &EmulateInstructionARM::EmulateVLDM
, "vldm{mode}<c> <Rn>{!}, <list>"},
13097 {0x0e100f00, 0x0c100a00, ARMvAll
, eEncodingA2
, VFPv2v3
, eSize32
,
13098 &EmulateInstructionARM::EmulateVLDM
, "vldm{mode}<c> <Rn>{!}, <list>"},
13099 {0x0f300f00, 0x0d100b00, ARMvAll
, eEncodingA1
, VFPv2_ABOVE
, eSize32
,
13100 &EmulateInstructionARM::EmulateVLDR
, "vldr<c> <Dd>, [<Rn>{,#+/-<imm>}]"},
13101 {0x0f300f00, 0x0d100a00, ARMvAll
, eEncodingA2
, VFPv2v3
, eSize32
,
13102 &EmulateInstructionARM::EmulateVLDR
, "vldr<c> <Sd>, [<Rn>{,#+/-<imm>}]"},
13103 {0xffb00000, 0xf4200000, ARMvAll
, eEncodingA1
, AdvancedSIMD
, eSize32
,
13104 &EmulateInstructionARM::EmulateVLD1Multiple
,
13105 "vld1<c>.<size> <list>, [<Rn>{@<align>}], <Rm>"},
13106 {0xffb00300, 0xf4a00000, ARMvAll
, eEncodingA1
, AdvancedSIMD
, eSize32
,
13107 &EmulateInstructionARM::EmulateVLD1Single
,
13108 "vld1<c>.<size> <list>, [<Rn>{@<align>}], <Rm>"},
13109 {0xffb00f00, 0xf4a00c00, ARMvAll
, eEncodingA1
, AdvancedSIMD
, eSize32
,
13110 &EmulateInstructionARM::EmulateVLD1SingleAll
,
13111 "vld1<c>.<size> <list>, [<Rn>{@<align>}], <Rm>"},
13113 // Store instructions
13114 {0x0fd00000, 0x08800000, ARMvAll
, eEncodingA1
, No_VFP
, eSize32
,
13115 &EmulateInstructionARM::EmulateSTM
, "stm<c> <Rn>{!} <registers>"},
13116 {0x0fd00000, 0x08000000, ARMvAll
, eEncodingA1
, No_VFP
, eSize32
,
13117 &EmulateInstructionARM::EmulateSTMDA
, "stmda<c> <Rn>{!} <registers>"},
13118 {0x0fd00000, 0x09000000, ARMvAll
, eEncodingA1
, No_VFP
, eSize32
,
13119 &EmulateInstructionARM::EmulateSTMDB
, "stmdb<c> <Rn>{!} <registers>"},
13120 {0x0fd00000, 0x09800000, ARMvAll
, eEncodingA1
, No_VFP
, eSize32
,
13121 &EmulateInstructionARM::EmulateSTMIB
, "stmib<c> <Rn>{!} <registers>"},
13122 {0x0e500010, 0x06000000, ARMvAll
, eEncodingA1
, No_VFP
, eSize32
,
13123 &EmulateInstructionARM::EmulateSTRRegister
,
13124 "str<c> <Rt> [<Rn> +/-<Rm> {<shift>}]{!}"},
13125 {0x0e5000f0, 0x000000b0, ARMvAll
, eEncodingA1
, No_VFP
, eSize32
,
13126 &EmulateInstructionARM::EmulateSTRHRegister
,
13127 "strh<c> <Rt>,[<Rn>,+/-<Rm>[{!}"},
13128 {0x0ff00ff0, 0x01800f90, ARMV6_ABOVE
, eEncodingA1
, No_VFP
, eSize32
,
13129 &EmulateInstructionARM::EmulateSTREX
, "strex<c> <Rd>, <Rt>, [<Rn>]"},
13130 {0x0e500000, 0x04400000, ARMvAll
, eEncodingA1
, No_VFP
, eSize32
,
13131 &EmulateInstructionARM::EmulateSTRBImmARM
,
13132 "strb<c> <Rt>,[<Rn>,#+/-<imm12>]!"},
13133 {0x0e500000, 0x04000000, ARMvAll
, eEncodingA1
, No_VFP
, eSize32
,
13134 &EmulateInstructionARM::EmulateSTRImmARM
,
13135 "str<c> <Rt>,[<Rn>,#+/-<imm12>]!"},
13136 {0x0e5000f0, 0x004000f0, ARMV5TE_ABOVE
, eEncodingA1
, No_VFP
, eSize32
,
13137 &EmulateInstructionARM::EmulateSTRDImm
,
13138 "strd<c> <Rt>, <Rt2>, [<Rn> #+/-<imm8>]!"},
13139 {0x0e500ff0, 0x000000f0, ARMV5TE_ABOVE
, eEncodingA1
, No_VFP
, eSize32
,
13140 &EmulateInstructionARM::EmulateSTRDReg
,
13141 "strd<c> <Rt>, <Rt2>, [<Rn>, +/-<Rm>]{!}"},
13142 {0x0e100f00, 0x0c000b00, ARMvAll
, eEncodingA1
, VFPv2_ABOVE
, eSize32
,
13143 &EmulateInstructionARM::EmulateVSTM
, "vstm{mode}<c> <Rn>{!} <list>"},
13144 {0x0e100f00, 0x0c000a00, ARMvAll
, eEncodingA2
, VFPv2v3
, eSize32
,
13145 &EmulateInstructionARM::EmulateVSTM
, "vstm{mode}<c> <Rn>{!} <list>"},
13146 {0x0f300f00, 0x0d000b00, ARMvAll
, eEncodingA1
, VFPv2_ABOVE
, eSize32
,
13147 &EmulateInstructionARM::EmulateVSTR
, "vstr<c> <Dd> [<Rn>{,#+/-<imm>}]"},
13148 {0x0f300f00, 0x0d000a00, ARMvAll
, eEncodingA2
, VFPv2v3
, eSize32
,
13149 &EmulateInstructionARM::EmulateVSTR
, "vstr<c> <Sd> [<Rn>{,#+/-<imm>}]"},
13150 {0xffb00000, 0xf4000000, ARMvAll
, eEncodingA1
, AdvancedSIMD
, eSize32
,
13151 &EmulateInstructionARM::EmulateVST1Multiple
,
13152 "vst1<c>.<size> <list>, [<Rn>{@<align>}], <Rm>"},
13153 {0xffb00300, 0xf4800000, ARMvAll
, eEncodingA1
, AdvancedSIMD
, eSize32
,
13154 &EmulateInstructionARM::EmulateVST1Single
,
13155 "vst1<c>.<size> <list>, [<Rn>{@<align>}], <Rm>"},
13157 // Other instructions
13158 {0x0fff00f0, 0x06af00f0, ARMV6_ABOVE
, eEncodingA1
, No_VFP
, eSize32
,
13159 &EmulateInstructionARM::EmulateSXTB
, "sxtb<c> <Rd>,<Rm>{,<rotation>}"},
13160 {0x0fff00f0, 0x06bf0070, ARMV6_ABOVE
, eEncodingA1
, No_VFP
, eSize32
,
13161 &EmulateInstructionARM::EmulateSXTH
, "sxth<c> <Rd>,<Rm>{,<rotation>}"},
13162 {0x0fff00f0, 0x06ef0070, ARMV6_ABOVE
, eEncodingA1
, No_VFP
, eSize32
,
13163 &EmulateInstructionARM::EmulateUXTB
, "uxtb<c> <Rd>,<Rm>{,<rotation>}"},
13164 {0x0fff00f0, 0x06ff0070, ARMV6_ABOVE
, eEncodingA1
, No_VFP
, eSize32
,
13165 &EmulateInstructionARM::EmulateUXTH
, "uxth<c> <Rd>,<Rm>{,<rotation>}"},
13166 {0xfe500000, 0xf8100000, ARMV6_ABOVE
, eEncodingA1
, No_VFP
, eSize32
,
13167 &EmulateInstructionARM::EmulateRFE
, "rfe{<amode>} <Rn>{!}"}
13170 static const size_t k_num_arm_opcodes
= std::size(g_arm_opcodes
);
13172 for (size_t i
= 0; i
< k_num_arm_opcodes
; ++i
) {
13173 if ((g_arm_opcodes
[i
].mask
& opcode
) == g_arm_opcodes
[i
].value
&&
13174 (g_arm_opcodes
[i
].variants
& arm_isa
) != 0)
13175 return &g_arm_opcodes
[i
];
13180 EmulateInstructionARM::ARMOpcode
*
13181 EmulateInstructionARM::GetThumbOpcodeForInstruction(const uint32_t opcode
,
13182 uint32_t arm_isa
) {
13184 static ARMOpcode g_thumb_opcodes
[] = {
13185 // Prologue instructions
13187 // push register(s)
13188 {0xfffffe00, 0x0000b400, ARMvAll
, eEncodingT1
, No_VFP
, eSize16
,
13189 &EmulateInstructionARM::EmulatePUSH
, "push <registers>"},
13190 {0xffff0000, 0xe92d0000, ARMV6T2_ABOVE
, eEncodingT2
, No_VFP
, eSize32
,
13191 &EmulateInstructionARM::EmulatePUSH
, "push.w <registers>"},
13192 {0xffff0fff, 0xf84d0d04, ARMV6T2_ABOVE
, eEncodingT3
, No_VFP
, eSize32
,
13193 &EmulateInstructionARM::EmulatePUSH
, "push.w <register>"},
13195 // set r7 to point to a stack offset
13196 {0xffffff00, 0x0000af00, ARMvAll
, eEncodingT1
, No_VFP
, eSize16
,
13197 &EmulateInstructionARM::EmulateADDRdSPImm
, "add r7, sp, #imm"},
13198 // copy the stack pointer to r7
13199 {0xffffffff, 0x0000466f, ARMvAll
, eEncodingT1
, No_VFP
, eSize16
,
13200 &EmulateInstructionARM::EmulateMOVRdSP
, "mov r7, sp"},
13201 // move from high register to low register (comes after "mov r7, sp" to
13202 // resolve ambiguity)
13203 {0xffffffc0, 0x00004640, ARMvAll
, eEncodingT1
, No_VFP
, eSize16
,
13204 &EmulateInstructionARM::EmulateMOVLowHigh
, "mov r0-r7, r8-r15"},
13206 // PC-relative load into register (see also EmulateADDSPRm)
13207 {0xfffff800, 0x00004800, ARMvAll
, eEncodingT1
, No_VFP
, eSize16
,
13208 &EmulateInstructionARM::EmulateLDRRtPCRelative
, "ldr <Rt>, [PC, #imm]"},
13210 // adjust the stack pointer
13211 {0xffffff87, 0x00004485, ARMvAll
, eEncodingT2
, No_VFP
, eSize16
,
13212 &EmulateInstructionARM::EmulateADDSPRm
, "add sp, <Rm>"},
13213 {0xffffff80, 0x0000b080, ARMvAll
, eEncodingT1
, No_VFP
, eSize16
,
13214 &EmulateInstructionARM::EmulateSUBSPImm
, "sub sp, sp, #imm"},
13215 {0xfbef8f00, 0xf1ad0d00, ARMV6T2_ABOVE
, eEncodingT2
, No_VFP
, eSize32
,
13216 &EmulateInstructionARM::EmulateSUBSPImm
, "sub.w sp, sp, #<const>"},
13217 {0xfbff8f00, 0xf2ad0d00, ARMV6T2_ABOVE
, eEncodingT3
, No_VFP
, eSize32
,
13218 &EmulateInstructionARM::EmulateSUBSPImm
, "subw sp, sp, #imm12"},
13219 {0xffef8000, 0xebad0000, ARMV6T2_ABOVE
, eEncodingT1
, No_VFP
, eSize32
,
13220 &EmulateInstructionARM::EmulateSUBSPReg
,
13221 "sub{s}<c> <Rd>, sp, <Rm>{,<shift>}"},
13223 // vector push consecutive extension register(s)
13224 {0xffbf0f00, 0xed2d0b00, ARMV6T2_ABOVE
, eEncodingT1
, No_VFP
, eSize32
,
13225 &EmulateInstructionARM::EmulateVPUSH
, "vpush.64 <list>"},
13226 {0xffbf0f00, 0xed2d0a00, ARMV6T2_ABOVE
, eEncodingT2
, No_VFP
, eSize32
,
13227 &EmulateInstructionARM::EmulateVPUSH
, "vpush.32 <list>"},
13229 // Epilogue instructions
13231 {0xfffff800, 0x0000a800, ARMV4T_ABOVE
, eEncodingT1
, No_VFP
, eSize16
,
13232 &EmulateInstructionARM::EmulateADDSPImm
, "add<c> <Rd>, sp, #imm"},
13233 {0xffffff80, 0x0000b000, ARMvAll
, eEncodingT2
, No_VFP
, eSize16
,
13234 &EmulateInstructionARM::EmulateADDSPImm
, "add sp, #imm"},
13235 {0xfffffe00, 0x0000bc00, ARMvAll
, eEncodingT1
, No_VFP
, eSize16
,
13236 &EmulateInstructionARM::EmulatePOP
, "pop <registers>"},
13237 {0xffff0000, 0xe8bd0000, ARMV6T2_ABOVE
, eEncodingT2
, No_VFP
, eSize32
,
13238 &EmulateInstructionARM::EmulatePOP
, "pop.w <registers>"},
13239 {0xffff0fff, 0xf85d0d04, ARMV6T2_ABOVE
, eEncodingT3
, No_VFP
, eSize32
,
13240 &EmulateInstructionARM::EmulatePOP
, "pop.w <register>"},
13241 {0xffbf0f00, 0xecbd0b00, ARMV6T2_ABOVE
, eEncodingT1
, No_VFP
, eSize32
,
13242 &EmulateInstructionARM::EmulateVPOP
, "vpop.64 <list>"},
13243 {0xffbf0f00, 0xecbd0a00, ARMV6T2_ABOVE
, eEncodingT2
, No_VFP
, eSize32
,
13244 &EmulateInstructionARM::EmulateVPOP
, "vpop.32 <list>"},
13246 // Supervisor Call (previously Software Interrupt)
13247 {0xffffff00, 0x0000df00, ARMvAll
, eEncodingT1
, No_VFP
, eSize16
,
13248 &EmulateInstructionARM::EmulateSVC
, "svc #imm8"},
13250 // If Then makes up to four following instructions conditional.
13251 // The next 5 opcode _must_ come before the if then instruction
13252 {0xffffffff, 0x0000bf00, ARMV6T2_ABOVE
, eEncodingT1
, No_VFP
, eSize16
,
13253 &EmulateInstructionARM::EmulateNop
, "nop"},
13254 {0xffffffff, 0x0000bf10, ARMV7_ABOVE
, eEncodingT1
, No_VFP
, eSize16
,
13255 &EmulateInstructionARM::EmulateNop
, "nop YIELD (yield hint)"},
13256 {0xffffffff, 0x0000bf20, ARMV7_ABOVE
, eEncodingT1
, No_VFP
, eSize16
,
13257 &EmulateInstructionARM::EmulateNop
, "nop WFE (wait for event hint)"},
13258 {0xffffffff, 0x0000bf30, ARMV7_ABOVE
, eEncodingT1
, No_VFP
, eSize16
,
13259 &EmulateInstructionARM::EmulateNop
, "nop WFI (wait for interrupt hint)"},
13260 {0xffffffff, 0x0000bf40, ARMV7_ABOVE
, eEncodingT1
, No_VFP
, eSize16
,
13261 &EmulateInstructionARM::EmulateNop
, "nop SEV (send event hint)"},
13262 {0xffffff00, 0x0000bf00, ARMV6T2_ABOVE
, eEncodingT1
, No_VFP
, eSize16
,
13263 &EmulateInstructionARM::EmulateIT
, "it{<x>{<y>{<z>}}} <firstcond>"},
13265 // Branch instructions
13266 // To resolve ambiguity, "b<c> #imm8" should come after "svc #imm8".
13267 {0xfffff000, 0x0000d000, ARMvAll
, eEncodingT1
, No_VFP
, eSize16
,
13268 &EmulateInstructionARM::EmulateB
, "b<c> #imm8 (outside IT)"},
13269 {0xfffff800, 0x0000e000, ARMvAll
, eEncodingT2
, No_VFP
, eSize16
,
13270 &EmulateInstructionARM::EmulateB
, "b<c> #imm11 (outside or last in IT)"},
13271 {0xf800d000, 0xf0008000, ARMV6T2_ABOVE
, eEncodingT3
, No_VFP
, eSize32
,
13272 &EmulateInstructionARM::EmulateB
, "b<c>.w #imm8 (outside IT)"},
13273 {0xf800d000, 0xf0009000, ARMV6T2_ABOVE
, eEncodingT4
, No_VFP
, eSize32
,
13274 &EmulateInstructionARM::EmulateB
,
13275 "b<c>.w #imm8 (outside or last in IT)"},
13277 {0xf800d000, 0xf000d000, ARMV4T_ABOVE
, eEncodingT1
, No_VFP
, eSize32
,
13278 &EmulateInstructionARM::EmulateBLXImmediate
, "bl <label>"},
13280 {0xf800d001, 0xf000c000, ARMV5_ABOVE
, eEncodingT2
, No_VFP
, eSize32
,
13281 &EmulateInstructionARM::EmulateBLXImmediate
, "blx <label>"},
13282 {0xffffff87, 0x00004780, ARMV5_ABOVE
, eEncodingT1
, No_VFP
, eSize16
,
13283 &EmulateInstructionARM::EmulateBLXRm
, "blx <Rm>"},
13284 // for example, "bx lr"
13285 {0xffffff87, 0x00004700, ARMvAll
, eEncodingT1
, No_VFP
, eSize32
,
13286 &EmulateInstructionARM::EmulateBXRm
, "bx <Rm>"},
13288 {0xfff0ffff, 0xf3c08f00, ARMV5J_ABOVE
, eEncodingT1
, No_VFP
, eSize32
,
13289 &EmulateInstructionARM::EmulateBXJRm
, "bxj <Rm>"},
13290 // compare and branch
13291 {0xfffff500, 0x0000b100, ARMV6T2_ABOVE
, eEncodingT1
, No_VFP
, eSize16
,
13292 &EmulateInstructionARM::EmulateCB
, "cb{n}z <Rn>, <label>"},
13293 // table branch byte
13294 {0xfff0fff0, 0xe8d0f000, ARMV6T2_ABOVE
, eEncodingT1
, No_VFP
, eSize32
,
13295 &EmulateInstructionARM::EmulateTB
, "tbb<c> <Rn>, <Rm>"},
13296 // table branch halfword
13297 {0xfff0fff0, 0xe8d0f010, ARMV6T2_ABOVE
, eEncodingT1
, No_VFP
, eSize32
,
13298 &EmulateInstructionARM::EmulateTB
, "tbh<c> <Rn>, <Rm>, lsl #1"},
13300 // Data-processing instructions
13302 {0xfbe08000, 0xf1400000, ARMV6T2_ABOVE
, eEncodingT1
, No_VFP
, eSize32
,
13303 &EmulateInstructionARM::EmulateADCImm
, "adc{s}<c> <Rd>, <Rn>, #<const>"},
13305 {0xffffffc0, 0x00004140, ARMvAll
, eEncodingT1
, No_VFP
, eSize16
,
13306 &EmulateInstructionARM::EmulateADCReg
, "adcs|adc<c> <Rdn>, <Rm>"},
13307 {0xffe08000, 0xeb400000, ARMV6T2_ABOVE
, eEncodingT2
, No_VFP
, eSize32
,
13308 &EmulateInstructionARM::EmulateADCReg
,
13309 "adc{s}<c>.w <Rd>, <Rn>, <Rm> {,<shift>}"},
13311 {0xfffffe00, 0x00001800, ARMvAll
, eEncodingT1
, No_VFP
, eSize16
,
13312 &EmulateInstructionARM::EmulateADDReg
, "adds|add<c> <Rd>, <Rn>, <Rm>"},
13313 // Make sure "add sp, <Rm>" comes before this instruction, so there's no
13314 // ambiguity decoding the two.
13315 {0xffffff00, 0x00004400, ARMvAll
, eEncodingT2
, No_VFP
, eSize16
,
13316 &EmulateInstructionARM::EmulateADDReg
, "add<c> <Rdn>, <Rm>"},
13318 {0xfffff800, 0x0000a000, ARMvAll
, eEncodingT1
, No_VFP
, eSize16
,
13319 &EmulateInstructionARM::EmulateADR
, "add<c> <Rd>, PC, #<const>"},
13320 {0xfbff8000, 0xf2af0000, ARMV6T2_ABOVE
, eEncodingT2
, No_VFP
, eSize32
,
13321 &EmulateInstructionARM::EmulateADR
, "sub<c> <Rd>, PC, #<const>"},
13322 {0xfbff8000, 0xf20f0000, ARMV6T2_ABOVE
, eEncodingT3
, No_VFP
, eSize32
,
13323 &EmulateInstructionARM::EmulateADR
, "add<c> <Rd>, PC, #<const>"},
13325 {0xfbe08000, 0xf0000000, ARMV6T2_ABOVE
, eEncodingT1
, No_VFP
, eSize32
,
13326 &EmulateInstructionARM::EmulateANDImm
, "and{s}<c> <Rd>, <Rn>, #<const>"},
13328 {0xffffffc0, 0x00004000, ARMvAll
, eEncodingT1
, No_VFP
, eSize16
,
13329 &EmulateInstructionARM::EmulateANDReg
, "ands|and<c> <Rdn>, <Rm>"},
13330 {0xffe08000, 0xea000000, ARMV6T2_ABOVE
, eEncodingT2
, No_VFP
, eSize32
,
13331 &EmulateInstructionARM::EmulateANDReg
,
13332 "and{s}<c>.w <Rd>, <Rn>, <Rm> {,<shift>}"},
13334 {0xfbe08000, 0xf0200000, ARMV6T2_ABOVE
, eEncodingT1
, No_VFP
, eSize32
,
13335 &EmulateInstructionARM::EmulateBICImm
, "bic{s}<c> <Rd>, <Rn>, #<const>"},
13337 {0xffffffc0, 0x00004380, ARMvAll
, eEncodingT1
, No_VFP
, eSize16
,
13338 &EmulateInstructionARM::EmulateBICReg
, "bics|bic<c> <Rdn>, <Rm>"},
13339 {0xffe08000, 0xea200000, ARMV6T2_ABOVE
, eEncodingT2
, No_VFP
, eSize32
,
13340 &EmulateInstructionARM::EmulateBICReg
,
13341 "bic{s}<c>.w <Rd>, <Rn>, <Rm> {,<shift>}"},
13343 {0xfbe08000, 0xf0800000, ARMV6T2_ABOVE
, eEncodingT1
, No_VFP
, eSize32
,
13344 &EmulateInstructionARM::EmulateEORImm
, "eor{s}<c> <Rd>, <Rn>, #<const>"},
13346 {0xffffffc0, 0x00004040, ARMvAll
, eEncodingT1
, No_VFP
, eSize16
,
13347 &EmulateInstructionARM::EmulateEORReg
, "eors|eor<c> <Rdn>, <Rm>"},
13348 {0xffe08000, 0xea800000, ARMV6T2_ABOVE
, eEncodingT2
, No_VFP
, eSize32
,
13349 &EmulateInstructionARM::EmulateEORReg
,
13350 "eor{s}<c>.w <Rd>, <Rn>, <Rm> {,<shift>}"},
13352 {0xfbe08000, 0xf0400000, ARMV6T2_ABOVE
, eEncodingT1
, No_VFP
, eSize32
,
13353 &EmulateInstructionARM::EmulateORRImm
, "orr{s}<c> <Rd>, <Rn>, #<const>"},
13355 {0xffffffc0, 0x00004300, ARMvAll
, eEncodingT1
, No_VFP
, eSize16
,
13356 &EmulateInstructionARM::EmulateORRReg
, "orrs|orr<c> <Rdn>, <Rm>"},
13357 {0xffe08000, 0xea400000, ARMV6T2_ABOVE
, eEncodingT2
, No_VFP
, eSize32
,
13358 &EmulateInstructionARM::EmulateORRReg
,
13359 "orr{s}<c>.w <Rd>, <Rn>, <Rm> {,<shift>}"},
13361 {0xffffffc0, 0x00004240, ARMvAll
, eEncodingT1
, No_VFP
, eSize16
,
13362 &EmulateInstructionARM::EmulateRSBImm
, "rsbs|rsb<c> <Rd>, <Rn>, #0"},
13363 {0xfbe08000, 0xf1c00000, ARMV6T2_ABOVE
, eEncodingT2
, No_VFP
, eSize32
,
13364 &EmulateInstructionARM::EmulateRSBImm
,
13365 "rsb{s}<c>.w <Rd>, <Rn>, #<const>"},
13367 {0xffe08000, 0xea400000, ARMV6T2_ABOVE
, eEncodingT1
, No_VFP
, eSize32
,
13368 &EmulateInstructionARM::EmulateRSBReg
,
13369 "rsb{s}<c>.w <Rd>, <Rn>, <Rm> {,<shift>}"},
13371 {0xfbe08000, 0xf1600000, ARMV6T2_ABOVE
, eEncodingT1
, No_VFP
, eSize32
,
13372 &EmulateInstructionARM::EmulateSBCImm
, "sbc{s}<c> <Rd>, <Rn>, #<const>"},
13374 {0xffffffc0, 0x00004180, ARMvAll
, eEncodingT1
, No_VFP
, eSize16
,
13375 &EmulateInstructionARM::EmulateSBCReg
, "sbcs|sbc<c> <Rdn>, <Rm>"},
13376 {0xffe08000, 0xeb600000, ARMV6T2_ABOVE
, eEncodingT2
, No_VFP
, eSize32
,
13377 &EmulateInstructionARM::EmulateSBCReg
,
13378 "sbc{s}<c>.w <Rd>, <Rn>, <Rm> {,<shift>}"},
13379 // add (immediate, Thumb)
13380 {0xfffffe00, 0x00001c00, ARMV4T_ABOVE
, eEncodingT1
, No_VFP
, eSize16
,
13381 &EmulateInstructionARM::EmulateADDImmThumb
,
13382 "adds|add<c> <Rd>,<Rn>,#<imm3>"},
13383 {0xfffff800, 0x00003000, ARMV4T_ABOVE
, eEncodingT2
, No_VFP
, eSize16
,
13384 &EmulateInstructionARM::EmulateADDImmThumb
, "adds|add<c> <Rdn>,#<imm8>"},
13385 {0xfbe08000, 0xf1000000, ARMV6T2_ABOVE
, eEncodingT3
, No_VFP
, eSize32
,
13386 &EmulateInstructionARM::EmulateADDImmThumb
,
13387 "add{s}<c>.w <Rd>,<Rn>,#<const>"},
13388 {0xfbf08000, 0xf2000000, ARMV6T2_ABOVE
, eEncodingT4
, No_VFP
, eSize32
,
13389 &EmulateInstructionARM::EmulateADDImmThumb
,
13390 "addw<c> <Rd>,<Rn>,#<imm12>"},
13391 // sub (immediate, Thumb)
13392 {0xfffffe00, 0x00001e00, ARMvAll
, eEncodingT1
, No_VFP
, eSize16
,
13393 &EmulateInstructionARM::EmulateSUBImmThumb
,
13394 "subs|sub<c> <Rd>, <Rn> #imm3"},
13395 {0xfffff800, 0x00003800, ARMvAll
, eEncodingT2
, No_VFP
, eSize16
,
13396 &EmulateInstructionARM::EmulateSUBImmThumb
, "subs|sub<c> <Rdn>, #imm8"},
13397 {0xfbe08000, 0xf1a00000, ARMV6T2_ABOVE
, eEncodingT3
, No_VFP
, eSize32
,
13398 &EmulateInstructionARM::EmulateSUBImmThumb
,
13399 "sub{s}<c>.w <Rd>, <Rn>, #<const>"},
13400 {0xfbf08000, 0xf2a00000, ARMV6T2_ABOVE
, eEncodingT4
, No_VFP
, eSize32
,
13401 &EmulateInstructionARM::EmulateSUBImmThumb
,
13402 "subw<c> <Rd>, <Rn>, #imm12"},
13403 // sub (sp minus immediate)
13404 {0xfbef8000, 0xf1ad0000, ARMV6T2_ABOVE
, eEncodingT2
, No_VFP
, eSize32
,
13405 &EmulateInstructionARM::EmulateSUBSPImm
, "sub{s}.w <Rd>, sp, #<const>"},
13406 {0xfbff8000, 0xf2ad0000, ARMV6T2_ABOVE
, eEncodingT3
, No_VFP
, eSize32
,
13407 &EmulateInstructionARM::EmulateSUBSPImm
, "subw<c> <Rd>, sp, #imm12"},
13409 {0xfffffe00, 0x00001a00, ARMV4T_ABOVE
, eEncodingT1
, No_VFP
, eSize16
,
13410 &EmulateInstructionARM::EmulateSUBReg
, "subs|sub<c> <Rd>, <Rn>, <Rm>"},
13411 {0xffe08000, 0xeba00000, ARMV6T2_ABOVE
, eEncodingT2
, No_VFP
, eSize32
,
13412 &EmulateInstructionARM::EmulateSUBReg
,
13413 "sub{s}<c>.w <Rd>, <Rn>, <Rm>{,<shift>}"},
13415 {0xfbf08f00, 0xf0900f00, ARMV6T2_ABOVE
, eEncodingT1
, No_VFP
, eSize32
,
13416 &EmulateInstructionARM::EmulateTEQImm
, "teq<c> <Rn>, #<const>"},
13418 {0xfff08f00, 0xea900f00, ARMV6T2_ABOVE
, eEncodingT1
, No_VFP
, eSize32
,
13419 &EmulateInstructionARM::EmulateTEQReg
, "teq<c> <Rn>, <Rm> {,<shift>}"},
13421 {0xfbf08f00, 0xf0100f00, ARMV6T2_ABOVE
, eEncodingT1
, No_VFP
, eSize32
,
13422 &EmulateInstructionARM::EmulateTSTImm
, "tst<c> <Rn>, #<const>"},
13424 {0xffffffc0, 0x00004200, ARMvAll
, eEncodingT1
, No_VFP
, eSize16
,
13425 &EmulateInstructionARM::EmulateTSTReg
, "tst<c> <Rdn>, <Rm>"},
13426 {0xfff08f00, 0xea100f00, ARMV6T2_ABOVE
, eEncodingT2
, No_VFP
, eSize32
,
13427 &EmulateInstructionARM::EmulateTSTReg
, "tst<c>.w <Rn>, <Rm> {,<shift>}"},
13429 // move from high register to high register
13430 {0xffffff00, 0x00004600, ARMvAll
, eEncodingT1
, No_VFP
, eSize16
,
13431 &EmulateInstructionARM::EmulateMOVRdRm
, "mov<c> <Rd>, <Rm>"},
13432 // move from low register to low register
13433 {0xffffffc0, 0x00000000, ARMvAll
, eEncodingT2
, No_VFP
, eSize16
,
13434 &EmulateInstructionARM::EmulateMOVRdRm
, "movs <Rd>, <Rm>"},
13435 // mov{s}<c>.w <Rd>, <Rm>
13436 {0xffeff0f0, 0xea4f0000, ARMV6T2_ABOVE
, eEncodingT3
, No_VFP
, eSize32
,
13437 &EmulateInstructionARM::EmulateMOVRdRm
, "mov{s}<c>.w <Rd>, <Rm>"},
13439 {0xfffff800, 0x00002000, ARMvAll
, eEncodingT1
, No_VFP
, eSize16
,
13440 &EmulateInstructionARM::EmulateMOVRdImm
, "movs|mov<c> <Rd>, #imm8"},
13441 {0xfbef8000, 0xf04f0000, ARMV6T2_ABOVE
, eEncodingT2
, No_VFP
, eSize32
,
13442 &EmulateInstructionARM::EmulateMOVRdImm
, "mov{s}<c>.w <Rd>, #<const>"},
13443 {0xfbf08000, 0xf2400000, ARMV6T2_ABOVE
, eEncodingT3
, No_VFP
, eSize32
,
13444 &EmulateInstructionARM::EmulateMOVRdImm
, "movw<c> <Rd>,#<imm16>"},
13446 {0xfbef8000, 0xf06f0000, ARMV6T2_ABOVE
, eEncodingT1
, No_VFP
, eSize32
,
13447 &EmulateInstructionARM::EmulateMVNImm
, "mvn{s} <Rd>, #<const>"},
13449 {0xffffffc0, 0x000043c0, ARMvAll
, eEncodingT1
, No_VFP
, eSize16
,
13450 &EmulateInstructionARM::EmulateMVNReg
, "mvns|mvn<c> <Rd>, <Rm>"},
13451 {0xffef8000, 0xea6f0000, ARMV6T2_ABOVE
, eEncodingT2
, No_VFP
, eSize32
,
13452 &EmulateInstructionARM::EmulateMVNReg
,
13453 "mvn{s}<c>.w <Rd>, <Rm> {,<shift>}"},
13455 {0xfbf08f00, 0xf1100f00, ARMV6T2_ABOVE
, eEncodingT1
, No_VFP
, eSize32
,
13456 &EmulateInstructionARM::EmulateCMNImm
, "cmn<c> <Rn>, #<const>"},
13458 {0xffffffc0, 0x000042c0, ARMvAll
, eEncodingT1
, No_VFP
, eSize16
,
13459 &EmulateInstructionARM::EmulateCMNReg
, "cmn<c> <Rn>, <Rm>"},
13460 {0xfff08f00, 0xeb100f00, ARMV6T2_ABOVE
, eEncodingT2
, No_VFP
, eSize32
,
13461 &EmulateInstructionARM::EmulateCMNReg
, "cmn<c> <Rn>, <Rm> {,<shift>}"},
13463 {0xfffff800, 0x00002800, ARMvAll
, eEncodingT1
, No_VFP
, eSize16
,
13464 &EmulateInstructionARM::EmulateCMPImm
, "cmp<c> <Rn>, #imm8"},
13465 {0xfbf08f00, 0xf1b00f00, ARMV6T2_ABOVE
, eEncodingT2
, No_VFP
, eSize32
,
13466 &EmulateInstructionARM::EmulateCMPImm
, "cmp<c>.w <Rn>, #<const>"},
13467 // cmp (register) (Rn and Rm both from r0-r7)
13468 {0xffffffc0, 0x00004280, ARMvAll
, eEncodingT1
, No_VFP
, eSize16
,
13469 &EmulateInstructionARM::EmulateCMPReg
, "cmp<c> <Rn>, <Rm>"},
13470 // cmp (register) (Rn and Rm not both from r0-r7)
13471 {0xffffff00, 0x00004500, ARMvAll
, eEncodingT2
, No_VFP
, eSize16
,
13472 &EmulateInstructionARM::EmulateCMPReg
, "cmp<c> <Rn>, <Rm>"},
13473 {0xfff08f00, 0xebb00f00, ARMvAll
, eEncodingT3
, No_VFP
, eSize16
,
13474 &EmulateInstructionARM::EmulateCMPReg
,
13475 "cmp<c>.w <Rn>, <Rm> {, <shift>}"},
13477 {0xfffff800, 0x00001000, ARMvAll
, eEncodingT1
, No_VFP
, eSize16
,
13478 &EmulateInstructionARM::EmulateASRImm
, "asrs|asr<c> <Rd>, <Rm>, #imm"},
13479 {0xffef8030, 0xea4f0020, ARMV6T2_ABOVE
, eEncodingT2
, No_VFP
, eSize32
,
13480 &EmulateInstructionARM::EmulateASRImm
, "asr{s}<c>.w <Rd>, <Rm>, #imm"},
13482 {0xffffffc0, 0x00004100, ARMvAll
, eEncodingT1
, No_VFP
, eSize16
,
13483 &EmulateInstructionARM::EmulateASRReg
, "asrs|asr<c> <Rdn>, <Rm>"},
13484 {0xffe0f0f0, 0xfa40f000, ARMV6T2_ABOVE
, eEncodingT2
, No_VFP
, eSize32
,
13485 &EmulateInstructionARM::EmulateASRReg
, "asr{s}<c>.w <Rd>, <Rn>, <Rm>"},
13487 {0xfffff800, 0x00000000, ARMvAll
, eEncodingT1
, No_VFP
, eSize16
,
13488 &EmulateInstructionARM::EmulateLSLImm
, "lsls|lsl<c> <Rd>, <Rm>, #imm"},
13489 {0xffef8030, 0xea4f0000, ARMV6T2_ABOVE
, eEncodingT2
, No_VFP
, eSize32
,
13490 &EmulateInstructionARM::EmulateLSLImm
, "lsl{s}<c>.w <Rd>, <Rm>, #imm"},
13492 {0xffffffc0, 0x00004080, ARMvAll
, eEncodingT1
, No_VFP
, eSize16
,
13493 &EmulateInstructionARM::EmulateLSLReg
, "lsls|lsl<c> <Rdn>, <Rm>"},
13494 {0xffe0f0f0, 0xfa00f000, ARMV6T2_ABOVE
, eEncodingT2
, No_VFP
, eSize32
,
13495 &EmulateInstructionARM::EmulateLSLReg
, "lsl{s}<c>.w <Rd>, <Rn>, <Rm>"},
13497 {0xfffff800, 0x00000800, ARMvAll
, eEncodingT1
, No_VFP
, eSize16
,
13498 &EmulateInstructionARM::EmulateLSRImm
, "lsrs|lsr<c> <Rd>, <Rm>, #imm"},
13499 {0xffef8030, 0xea4f0010, ARMV6T2_ABOVE
, eEncodingT2
, No_VFP
, eSize32
,
13500 &EmulateInstructionARM::EmulateLSRImm
, "lsr{s}<c>.w <Rd>, <Rm>, #imm"},
13502 {0xffffffc0, 0x000040c0, ARMvAll
, eEncodingT1
, No_VFP
, eSize16
,
13503 &EmulateInstructionARM::EmulateLSRReg
, "lsrs|lsr<c> <Rdn>, <Rm>"},
13504 {0xffe0f0f0, 0xfa20f000, ARMV6T2_ABOVE
, eEncodingT2
, No_VFP
, eSize32
,
13505 &EmulateInstructionARM::EmulateLSRReg
, "lsr{s}<c>.w <Rd>, <Rn>, <Rm>"},
13506 // rrx is a special case encoding of ror (immediate)
13507 {0xffeff0f0, 0xea4f0030, ARMV6T2_ABOVE
, eEncodingT1
, No_VFP
, eSize32
,
13508 &EmulateInstructionARM::EmulateRRX
, "rrx{s}<c>.w <Rd>, <Rm>"},
13510 {0xffef8030, 0xea4f0030, ARMV6T2_ABOVE
, eEncodingT1
, No_VFP
, eSize32
,
13511 &EmulateInstructionARM::EmulateRORImm
, "ror{s}<c>.w <Rd>, <Rm>, #imm"},
13513 {0xffffffc0, 0x000041c0, ARMvAll
, eEncodingT1
, No_VFP
, eSize16
,
13514 &EmulateInstructionARM::EmulateRORReg
, "rors|ror<c> <Rdn>, <Rm>"},
13515 {0xffe0f0f0, 0xfa60f000, ARMV6T2_ABOVE
, eEncodingT2
, No_VFP
, eSize32
,
13516 &EmulateInstructionARM::EmulateRORReg
, "ror{s}<c>.w <Rd>, <Rn>, <Rm>"},
13518 {0xffffffc0, 0x00004340, ARMV4T_ABOVE
, eEncodingT1
, No_VFP
, eSize16
,
13519 &EmulateInstructionARM::EmulateMUL
, "muls <Rdm>,<Rn>,<Rdm>"},
13521 {0xfff0f0f0, 0xfb00f000, ARMV6T2_ABOVE
, eEncodingT2
, No_VFP
, eSize32
,
13522 &EmulateInstructionARM::EmulateMUL
, "mul<c> <Rd>,<Rn>,<Rm>"},
13524 // subs pc, lr and related instructions
13525 {0xffffff00, 0xf3de8f00, ARMV6T2_ABOVE
, eEncodingT1
, No_VFP
, eSize32
,
13526 &EmulateInstructionARM::EmulateSUBSPcLrEtc
, "SUBS<c> PC, LR, #<imm8>"},
13528 // RFE instructions *** IMPORTANT *** THESE MUST BE LISTED **BEFORE** THE
13529 // LDM.. Instructions in this table;
13530 // otherwise the wrong instructions will be selected.
13532 {0xffd0ffff, 0xe810c000, ARMV6T2_ABOVE
, eEncodingT1
, No_VFP
, eSize32
,
13533 &EmulateInstructionARM::EmulateRFE
, "rfedb<c> <Rn>{!}"},
13534 {0xffd0ffff, 0xe990c000, ARMV6T2_ABOVE
, eEncodingT2
, No_VFP
, eSize32
,
13535 &EmulateInstructionARM::EmulateRFE
, "rfe{ia}<c> <Rn>{!}"},
13537 // Load instructions
13538 {0xfffff800, 0x0000c800, ARMV4T_ABOVE
, eEncodingT1
, No_VFP
, eSize16
,
13539 &EmulateInstructionARM::EmulateLDM
, "ldm<c> <Rn>{!} <registers>"},
13540 {0xffd02000, 0xe8900000, ARMV6T2_ABOVE
, eEncodingT2
, No_VFP
, eSize32
,
13541 &EmulateInstructionARM::EmulateLDM
, "ldm<c>.w <Rn>{!} <registers>"},
13542 {0xffd00000, 0xe9100000, ARMV6T2_ABOVE
, eEncodingT1
, No_VFP
, eSize32
,
13543 &EmulateInstructionARM::EmulateLDMDB
, "ldmdb<c> <Rn>{!} <registers>"},
13544 {0xfffff800, 0x00006800, ARMV4T_ABOVE
, eEncodingT1
, No_VFP
, eSize16
,
13545 &EmulateInstructionARM::EmulateLDRRtRnImm
, "ldr<c> <Rt>, [<Rn>{,#imm}]"},
13546 {0xfffff800, 0x00009800, ARMV4T_ABOVE
, eEncodingT2
, No_VFP
, eSize16
,
13547 &EmulateInstructionARM::EmulateLDRRtRnImm
, "ldr<c> <Rt>, [SP{,#imm}]"},
13548 {0xfff00000, 0xf8d00000, ARMV6T2_ABOVE
, eEncodingT3
, No_VFP
, eSize32
,
13549 &EmulateInstructionARM::EmulateLDRRtRnImm
,
13550 "ldr<c>.w <Rt>, [<Rn>{,#imm12}]"},
13551 {0xfff00800, 0xf8500800, ARMV6T2_ABOVE
, eEncodingT4
, No_VFP
, eSize32
,
13552 &EmulateInstructionARM::EmulateLDRRtRnImm
,
13553 "ldr<c> <Rt>, [<Rn>{,#+/-<imm8>}]{!}"},
13554 // Thumb2 PC-relative load into register
13555 {0xff7f0000, 0xf85f0000, ARMV6T2_ABOVE
, eEncodingT2
, No_VFP
, eSize32
,
13556 &EmulateInstructionARM::EmulateLDRRtPCRelative
,
13557 "ldr<c>.w <Rt>, [PC, +/-#imm}]"},
13558 {0xfffffe00, 0x00005800, ARMV4T_ABOVE
, eEncodingT1
, No_VFP
, eSize16
,
13559 &EmulateInstructionARM::EmulateLDRRegister
, "ldr<c> <Rt>, [<Rn>, <Rm>]"},
13560 {0xfff00fc0, 0xf8500000, ARMV6T2_ABOVE
, eEncodingT2
, No_VFP
, eSize32
,
13561 &EmulateInstructionARM::EmulateLDRRegister
,
13562 "ldr<c>.w <Rt>, [<Rn>,<Rm>{,LSL #<imm2>}]"},
13563 {0xfffff800, 0x00007800, ARMV4T_ABOVE
, eEncodingT1
, No_VFP
, eSize16
,
13564 &EmulateInstructionARM::EmulateLDRBImmediate
,
13565 "ldrb<c> <Rt>,[<Rn>{,#<imm5>}]"},
13566 {0xfff00000, 0xf8900000, ARMV6T2_ABOVE
, eEncodingT2
, No_VFP
, eSize32
,
13567 &EmulateInstructionARM::EmulateLDRBImmediate
,
13568 "ldrb<c>.w <Rt>,[<Rn>{,#<imm12>}]"},
13569 {0xfff00800, 0xf8100800, ARMV6T2_ABOVE
, eEncodingT3
, No_VFP
, eSize32
,
13570 &EmulateInstructionARM::EmulateLDRBImmediate
,
13571 "ldrb<c> <Rt>,[<Rn>, #+/-<imm8>]{!}"},
13572 {0xff7f0000, 0xf81f0000, ARMV6T2_ABOVE
, eEncodingT1
, No_VFP
, eSize32
,
13573 &EmulateInstructionARM::EmulateLDRBLiteral
, "ldrb<c> <Rt>,[...]"},
13574 {0xfffffe00, 0x00005c00, ARMV6T2_ABOVE
, eEncodingT1
, No_VFP
, eSize16
,
13575 &EmulateInstructionARM::EmulateLDRBRegister
, "ldrb<c> <Rt>,[<Rn>,<Rm>]"},
13576 {0xfff00fc0, 0xf8100000, ARMV6T2_ABOVE
, eEncodingT2
, No_VFP
, eSize32
,
13577 &EmulateInstructionARM::EmulateLDRBRegister
,
13578 "ldrb<c>.w <Rt>,[<Rn>,<Rm>{,LSL #imm2>}]"},
13579 {0xfffff800, 0x00008800, ARMV4T_ABOVE
, eEncodingT1
, No_VFP
, eSize16
,
13580 &EmulateInstructionARM::EmulateLDRHImmediate
,
13581 "ldrh<c> <Rt>, [<Rn>{,#<imm>}]"},
13582 {0xfff00000, 0xf8b00000, ARMV6T2_ABOVE
, eEncodingT2
, No_VFP
, eSize32
,
13583 &EmulateInstructionARM::EmulateLDRHImmediate
,
13584 "ldrh<c>.w <Rt>,[<Rn>{,#<imm12>}]"},
13585 {0xfff00800, 0xf8300800, ARMV6T2_ABOVE
, eEncodingT3
, No_VFP
, eSize32
,
13586 &EmulateInstructionARM::EmulateLDRHImmediate
,
13587 "ldrh<c> <Rt>,[<Rn>,#+/-<imm8>]{!}"},
13588 {0xff7f0000, 0xf83f0000, ARMV6T2_ABOVE
, eEncodingT1
, No_VFP
, eSize32
,
13589 &EmulateInstructionARM::EmulateLDRHLiteral
, "ldrh<c> <Rt>, <label>"},
13590 {0xfffffe00, 0x00005a00, ARMV4T_ABOVE
, eEncodingT1
, No_VFP
, eSize16
,
13591 &EmulateInstructionARM::EmulateLDRHRegister
,
13592 "ldrh<c> <Rt>, [<Rn>,<Rm>]"},
13593 {0xfff00fc0, 0xf8300000, ARMV6T2_ABOVE
, eEncodingT2
, No_VFP
, eSize32
,
13594 &EmulateInstructionARM::EmulateLDRHRegister
,
13595 "ldrh<c>.w <Rt>,[<Rn>,<Rm>{,LSL #<imm2>}]"},
13596 {0xfff00000, 0xf9900000, ARMV6T2_ABOVE
, eEncodingT1
, No_VFP
, eSize32
,
13597 &EmulateInstructionARM::EmulateLDRSBImmediate
,
13598 "ldrsb<c> <Rt>,[<Rn>,#<imm12>]"},
13599 {0xfff00800, 0xf9100800, ARMV6T2_ABOVE
, eEncodingT2
, No_VFP
, eSize32
,
13600 &EmulateInstructionARM::EmulateLDRSBImmediate
,
13601 "ldrsb<c> <Rt>,[<Rn>,#+/-<imm8>]"},
13602 {0xff7f0000, 0xf91f0000, ARMV6T2_ABOVE
, eEncodingT1
, No_VFP
, eSize32
,
13603 &EmulateInstructionARM::EmulateLDRSBLiteral
, "ldrsb<c> <Rt>, <label>"},
13604 {0xfffffe00, 0x00005600, ARMV4T_ABOVE
, eEncodingT1
, No_VFP
, eSize16
,
13605 &EmulateInstructionARM::EmulateLDRSBRegister
,
13606 "ldrsb<c> <Rt>,[<Rn>,<Rm>]"},
13607 {0xfff00fc0, 0xf9100000, ARMV6T2_ABOVE
, eEncodingT2
, No_VFP
, eSize32
,
13608 &EmulateInstructionARM::EmulateLDRSBRegister
,
13609 "ldrsb<c>.w <Rt>,[<Rn>,<Rm>{,LSL #imm2>}]"},
13610 {0xfff00000, 0xf9b00000, ARMV6T2_ABOVE
, eEncodingT1
, No_VFP
, eSize32
,
13611 &EmulateInstructionARM::EmulateLDRSHImmediate
,
13612 "ldrsh<c> <Rt>,[<Rn>,#<imm12>]"},
13613 {0xfff00800, 0xf9300800, ARMV6T2_ABOVE
, eEncodingT2
, No_VFP
, eSize32
,
13614 &EmulateInstructionARM::EmulateLDRSHImmediate
,
13615 "ldrsh<c> <Rt>,[<Rn>,#+/-<imm8>]"},
13616 {0xff7f0000, 0xf93f0000, ARMV6T2_ABOVE
, eEncodingT1
, No_VFP
, eSize32
,
13617 &EmulateInstructionARM::EmulateLDRSHLiteral
, "ldrsh<c> <Rt>,<label>"},
13618 {0xfffffe00, 0x00005e00, ARMV4T_ABOVE
, eEncodingT1
, No_VFP
, eSize16
,
13619 &EmulateInstructionARM::EmulateLDRSHRegister
,
13620 "ldrsh<c> <Rt>,[<Rn>,<Rm>]"},
13621 {0xfff00fc0, 0xf9300000, ARMV6T2_ABOVE
, eEncodingT2
, No_VFP
, eSize32
,
13622 &EmulateInstructionARM::EmulateLDRSHRegister
,
13623 "ldrsh<c>.w <Rt>,[<Rn>,<Rm>{,LSL #<imm2>}]"},
13624 {0xfe500000, 0xe8500000, ARMV6T2_ABOVE
, eEncodingT1
, No_VFP
, eSize32
,
13625 &EmulateInstructionARM::EmulateLDRDImmediate
,
13626 "ldrd<c> <Rt>, <Rt2>, [<Rn>,#+/-<imm>]!"},
13627 {0xfe100f00, 0xec100b00, ARMvAll
, eEncodingT1
, VFPv2_ABOVE
, eSize32
,
13628 &EmulateInstructionARM::EmulateVLDM
, "vldm{mode}<c> <Rn>{!}, <list>"},
13629 {0xfe100f00, 0xec100a00, ARMvAll
, eEncodingT2
, VFPv2v3
, eSize32
,
13630 &EmulateInstructionARM::EmulateVLDM
, "vldm{mode}<c> <Rn>{!}, <list>"},
13631 {0xffe00f00, 0xed100b00, ARMvAll
, eEncodingT1
, VFPv2_ABOVE
, eSize32
,
13632 &EmulateInstructionARM::EmulateVLDR
, "vldr<c> <Dd>, [<Rn>{,#+/-<imm>}]"},
13633 {0xff300f00, 0xed100a00, ARMvAll
, eEncodingT2
, VFPv2v3
, eSize32
,
13634 &EmulateInstructionARM::EmulateVLDR
, "vldr<c> <Sd>, {<Rn>{,#+/-<imm>}]"},
13635 {0xffb00000, 0xf9200000, ARMvAll
, eEncodingT1
, AdvancedSIMD
, eSize32
,
13636 &EmulateInstructionARM::EmulateVLD1Multiple
,
13637 "vld1<c>.<size> <list>, [<Rn>{@<align>}],<Rm>"},
13638 {0xffb00300, 0xf9a00000, ARMvAll
, eEncodingT1
, AdvancedSIMD
, eSize32
,
13639 &EmulateInstructionARM::EmulateVLD1Single
,
13640 "vld1<c>.<size> <list>, [<Rn>{@<align>}],<Rm>"},
13641 {0xffb00f00, 0xf9a00c00, ARMvAll
, eEncodingT1
, AdvancedSIMD
, eSize32
,
13642 &EmulateInstructionARM::EmulateVLD1SingleAll
,
13643 "vld1<c>.<size> <list>, [<Rn>{@<align>}], <Rm>"},
13645 // Store instructions
13646 {0xfffff800, 0x0000c000, ARMV4T_ABOVE
, eEncodingT1
, No_VFP
, eSize16
,
13647 &EmulateInstructionARM::EmulateSTM
, "stm<c> <Rn>{!} <registers>"},
13648 {0xffd00000, 0xe8800000, ARMV6T2_ABOVE
, eEncodingT2
, No_VFP
, eSize32
,
13649 &EmulateInstructionARM::EmulateSTM
, "stm<c>.w <Rn>{!} <registers>"},
13650 {0xffd00000, 0xe9000000, ARMV6T2_ABOVE
, eEncodingT1
, No_VFP
, eSize32
,
13651 &EmulateInstructionARM::EmulateSTMDB
, "stmdb<c> <Rn>{!} <registers>"},
13652 {0xfffff800, 0x00006000, ARMV4T_ABOVE
, eEncodingT1
, No_VFP
, eSize16
,
13653 &EmulateInstructionARM::EmulateSTRThumb
, "str<c> <Rt>, [<Rn>{,#<imm>}]"},
13654 {0xfffff800, 0x00009000, ARMV4T_ABOVE
, eEncodingT2
, No_VFP
, eSize16
,
13655 &EmulateInstructionARM::EmulateSTRThumb
, "str<c> <Rt>, [SP,#<imm>]"},
13656 {0xfff00000, 0xf8c00000, ARMV6T2_ABOVE
, eEncodingT3
, No_VFP
, eSize32
,
13657 &EmulateInstructionARM::EmulateSTRThumb
,
13658 "str<c>.w <Rt>, [<Rn>,#<imm12>]"},
13659 {0xfff00800, 0xf8400800, ARMV6T2_ABOVE
, eEncodingT4
, No_VFP
, eSize32
,
13660 &EmulateInstructionARM::EmulateSTRThumb
,
13661 "str<c> <Rt>, [<Rn>,#+/-<imm8>]"},
13662 {0xfffffe00, 0x00005000, ARMV4T_ABOVE
, eEncodingT1
, No_VFP
, eSize16
,
13663 &EmulateInstructionARM::EmulateSTRRegister
, "str<c> <Rt> ,{<Rn>, <Rm>]"},
13664 {0xfff00fc0, 0xf8400000, ARMV6T2_ABOVE
, eEncodingT2
, No_VFP
, eSize32
,
13665 &EmulateInstructionARM::EmulateSTRRegister
,
13666 "str<c>.w <Rt>, [<Rn>, <Rm> {lsl #imm2>}]"},
13667 {0xfffff800, 0x00007000, ARMV4T_ABOVE
, eEncodingT1
, No_VFP
, eSize16
,
13668 &EmulateInstructionARM::EmulateSTRBThumb
,
13669 "strb<c> <Rt>, [<Rn>, #<imm5>]"},
13670 {0xfff00000, 0xf8800000, ARMV6T2_ABOVE
, eEncodingT2
, No_VFP
, eSize32
,
13671 &EmulateInstructionARM::EmulateSTRBThumb
,
13672 "strb<c>.w <Rt>, [<Rn>, #<imm12>]"},
13673 {0xfff00800, 0xf8000800, ARMV6T2_ABOVE
, eEncodingT3
, No_VFP
, eSize32
,
13674 &EmulateInstructionARM::EmulateSTRBThumb
,
13675 "strb<c> <Rt> ,[<Rn>, #+/-<imm8>]{!}"},
13676 {0xfffffe00, 0x00005200, ARMV4T_ABOVE
, eEncodingT1
, No_VFP
, eSize16
,
13677 &EmulateInstructionARM::EmulateSTRHRegister
, "strh<c> <Rt>,[<Rn>,<Rm>]"},
13678 {0xfff00fc0, 0xf8200000, ARMV6T2_ABOVE
, eEncodingT2
, No_VFP
, eSize32
,
13679 &EmulateInstructionARM::EmulateSTRHRegister
,
13680 "strh<c>.w <Rt>,[<Rn>,<Rm>{,LSL #<imm2>}]"},
13681 {0xfff00000, 0xe8400000, ARMV6T2_ABOVE
, eEncodingT1
, No_VFP
, eSize32
,
13682 &EmulateInstructionARM::EmulateSTREX
,
13683 "strex<c> <Rd>, <Rt>, [<Rn{,#<imm>}]"},
13684 {0xfe500000, 0xe8400000, ARMV6T2_ABOVE
, eEncodingT1
, No_VFP
, eSize32
,
13685 &EmulateInstructionARM::EmulateSTRDImm
,
13686 "strd<c> <Rt>, <Rt2>, [<Rn>, #+/-<imm>]!"},
13687 {0xfe100f00, 0xec000b00, ARMvAll
, eEncodingT1
, VFPv2_ABOVE
, eSize32
,
13688 &EmulateInstructionARM::EmulateVSTM
, "vstm{mode}<c> <Rn>{!}, <list>"},
13689 {0xfea00f00, 0xec000a00, ARMvAll
, eEncodingT2
, VFPv2v3
, eSize32
,
13690 &EmulateInstructionARM::EmulateVSTM
, "vstm{mode}<c> <Rn>{!}, <list>"},
13691 {0xff300f00, 0xed000b00, ARMvAll
, eEncodingT1
, VFPv2_ABOVE
, eSize32
,
13692 &EmulateInstructionARM::EmulateVSTR
, "vstr<c> <Dd>, [<Rn>{,#+/-<imm>}]"},
13693 {0xff300f00, 0xed000a00, ARMvAll
, eEncodingT2
, VFPv2v3
, eSize32
,
13694 &EmulateInstructionARM::EmulateVSTR
, "vstr<c> <Sd>, [<Rn>{,#+/-<imm>}]"},
13695 {0xffb00000, 0xf9000000, ARMvAll
, eEncodingT1
, AdvancedSIMD
, eSize32
,
13696 &EmulateInstructionARM::EmulateVST1Multiple
,
13697 "vst1<c>.<size> <list>, [<Rn>{@<align>}], <Rm>"},
13698 {0xffb00300, 0xf9800000, ARMvAll
, eEncodingT1
, AdvancedSIMD
, eSize32
,
13699 &EmulateInstructionARM::EmulateVST1Single
,
13700 "vst1<c>.<size> <list>, [<Rn>{@<align>}], <Rm>"},
13702 // Other instructions
13703 {0xffffffc0, 0x0000b240, ARMV6_ABOVE
, eEncodingT1
, No_VFP
, eSize16
,
13704 &EmulateInstructionARM::EmulateSXTB
, "sxtb<c> <Rd>,<Rm>"},
13705 {0xfffff080, 0xfa4ff080, ARMV6_ABOVE
, eEncodingT2
, No_VFP
, eSize32
,
13706 &EmulateInstructionARM::EmulateSXTB
, "sxtb<c>.w <Rd>,<Rm>{,<rotation>}"},
13707 {0xffffffc0, 0x0000b200, ARMV6_ABOVE
, eEncodingT1
, No_VFP
, eSize16
,
13708 &EmulateInstructionARM::EmulateSXTH
, "sxth<c> <Rd>,<Rm>"},
13709 {0xfffff080, 0xfa0ff080, ARMV6T2_ABOVE
, eEncodingT2
, No_VFP
, eSize32
,
13710 &EmulateInstructionARM::EmulateSXTH
, "sxth<c>.w <Rd>,<Rm>{,<rotation>}"},
13711 {0xffffffc0, 0x0000b2c0, ARMV6_ABOVE
, eEncodingT1
, No_VFP
, eSize16
,
13712 &EmulateInstructionARM::EmulateUXTB
, "uxtb<c> <Rd>,<Rm>"},
13713 {0xfffff080, 0xfa5ff080, ARMV6T2_ABOVE
, eEncodingT2
, No_VFP
, eSize32
,
13714 &EmulateInstructionARM::EmulateUXTB
, "uxtb<c>.w <Rd>,<Rm>{,<rotation>}"},
13715 {0xffffffc0, 0x0000b280, ARMV6_ABOVE
, eEncodingT1
, No_VFP
, eSize16
,
13716 &EmulateInstructionARM::EmulateUXTH
, "uxth<c> <Rd>,<Rm>"},
13717 {0xfffff080, 0xfa1ff080, ARMV6T2_ABOVE
, eEncodingT2
, No_VFP
, eSize32
,
13718 &EmulateInstructionARM::EmulateUXTH
, "uxth<c>.w <Rd>,<Rm>{,<rotation>}"},
13721 const size_t k_num_thumb_opcodes
= std::size(g_thumb_opcodes
);
13722 for (size_t i
= 0; i
< k_num_thumb_opcodes
; ++i
) {
13723 if ((g_thumb_opcodes
[i
].mask
& opcode
) == g_thumb_opcodes
[i
].value
&&
13724 (g_thumb_opcodes
[i
].variants
& arm_isa
) != 0)
13725 return &g_thumb_opcodes
[i
];
13730 bool EmulateInstructionARM::SetArchitecture(const ArchSpec
&arch
) {
13733 llvm::StringRef arch_cstr
= arch
.GetArchitectureName();
13734 if (arch_cstr
.equals_insensitive("armv4t"))
13735 m_arm_isa
= ARMv4T
;
13736 else if (arch_cstr
.equals_insensitive("armv5tej"))
13737 m_arm_isa
= ARMv5TEJ
;
13738 else if (arch_cstr
.equals_insensitive("armv5te"))
13739 m_arm_isa
= ARMv5TE
;
13740 else if (arch_cstr
.equals_insensitive("armv5t"))
13741 m_arm_isa
= ARMv5T
;
13742 else if (arch_cstr
.equals_insensitive("armv6k"))
13743 m_arm_isa
= ARMv6K
;
13744 else if (arch_cstr
.equals_insensitive("armv6t2"))
13745 m_arm_isa
= ARMv6T2
;
13746 else if (arch_cstr
.equals_insensitive("armv7s"))
13747 m_arm_isa
= ARMv7S
;
13748 else if (arch_cstr
.equals_insensitive("arm"))
13749 m_arm_isa
= ARMvAll
;
13750 else if (arch_cstr
.equals_insensitive("thumb"))
13751 m_arm_isa
= ARMvAll
;
13752 else if (arch_cstr
.starts_with_insensitive("armv4"))
13754 else if (arch_cstr
.starts_with_insensitive("armv6"))
13756 else if (arch_cstr
.starts_with_insensitive("armv7"))
13758 else if (arch_cstr
.starts_with_insensitive("armv8"))
13760 return m_arm_isa
!= 0;
13763 bool EmulateInstructionARM::SetInstruction(const Opcode
&insn_opcode
,
13764 const Address
&inst_addr
,
13766 if (EmulateInstruction::SetInstruction(insn_opcode
, inst_addr
, target
)) {
13767 if (m_arch
.GetTriple().getArch() == llvm::Triple::thumb
||
13768 m_arch
.IsAlwaysThumbInstructions())
13769 m_opcode_mode
= eModeThumb
;
13771 AddressClass addr_class
= inst_addr
.GetAddressClass();
13773 if ((addr_class
== AddressClass::eCode
) ||
13774 (addr_class
== AddressClass::eUnknown
))
13775 m_opcode_mode
= eModeARM
;
13776 else if (addr_class
== AddressClass::eCodeAlternateISA
)
13777 m_opcode_mode
= eModeThumb
;
13781 if (m_opcode_mode
== eModeThumb
|| m_arch
.IsAlwaysThumbInstructions())
13782 m_opcode_cpsr
= CPSR_MODE_USR
| MASK_CPSR_T
;
13784 m_opcode_cpsr
= CPSR_MODE_USR
;
13790 bool EmulateInstructionARM::ReadInstruction() {
13791 bool success
= false;
13792 m_opcode_cpsr
= ReadRegisterUnsigned(eRegisterKindGeneric
,
13793 LLDB_REGNUM_GENERIC_FLAGS
, 0, &success
);
13796 ReadRegisterUnsigned(eRegisterKindGeneric
, LLDB_REGNUM_GENERIC_PC
,
13797 LLDB_INVALID_ADDRESS
, &success
);
13799 Context read_inst_context
;
13800 read_inst_context
.type
= eContextReadOpcode
;
13801 read_inst_context
.SetNoArgs();
13803 if ((m_opcode_cpsr
& MASK_CPSR_T
) || m_arch
.IsAlwaysThumbInstructions()) {
13804 m_opcode_mode
= eModeThumb
;
13805 uint32_t thumb_opcode
= MemARead(read_inst_context
, pc
, 2, 0, &success
);
13808 if ((thumb_opcode
& 0xe000) != 0xe000 ||
13809 ((thumb_opcode
& 0x1800u
) == 0)) {
13810 m_opcode
.SetOpcode16(thumb_opcode
, GetByteOrder());
13812 m_opcode
.SetOpcode32(
13813 (thumb_opcode
<< 16) |
13814 MemARead(read_inst_context
, pc
+ 2, 2, 0, &success
),
13819 m_opcode_mode
= eModeARM
;
13820 m_opcode
.SetOpcode32(MemARead(read_inst_context
, pc
, 4, 0, &success
),
13824 if (!m_ignore_conditions
) {
13825 // If we are not ignoreing the conditions then init the it session from
13826 // the current value of cpsr.
13827 uint32_t it
= (Bits32(m_opcode_cpsr
, 15, 10) << 2) |
13828 Bits32(m_opcode_cpsr
, 26, 25);
13830 m_it_session
.InitIT(it
);
13835 m_opcode_mode
= eModeInvalid
;
13836 m_addr
= LLDB_INVALID_ADDRESS
;
13841 uint32_t EmulateInstructionARM::ArchVersion() { return m_arm_isa
; }
13843 bool EmulateInstructionARM::ConditionPassed(const uint32_t opcode
) {
13844 // If we are ignoring conditions, then always return true. this allows us to
13845 // iterate over disassembly code and still emulate an instruction even if we
13846 // don't have all the right bits set in the CPSR register...
13847 if (m_ignore_conditions
)
13850 const uint32_t cond
= CurrentCond(opcode
);
13851 if (cond
== UINT32_MAX
)
13854 bool result
= false;
13855 switch (UnsignedBits(cond
, 3, 1)) {
13857 if (m_opcode_cpsr
== 0)
13860 result
= (m_opcode_cpsr
& MASK_CPSR_Z
) != 0;
13863 if (m_opcode_cpsr
== 0)
13866 result
= (m_opcode_cpsr
& MASK_CPSR_C
) != 0;
13869 if (m_opcode_cpsr
== 0)
13872 result
= (m_opcode_cpsr
& MASK_CPSR_N
) != 0;
13875 if (m_opcode_cpsr
== 0)
13878 result
= (m_opcode_cpsr
& MASK_CPSR_V
) != 0;
13881 if (m_opcode_cpsr
== 0)
13884 result
= ((m_opcode_cpsr
& MASK_CPSR_C
) != 0) &&
13885 ((m_opcode_cpsr
& MASK_CPSR_Z
) == 0);
13888 if (m_opcode_cpsr
== 0)
13891 bool n
= (m_opcode_cpsr
& MASK_CPSR_N
);
13892 bool v
= (m_opcode_cpsr
& MASK_CPSR_V
);
13897 if (m_opcode_cpsr
== 0)
13900 bool n
= (m_opcode_cpsr
& MASK_CPSR_N
);
13901 bool v
= (m_opcode_cpsr
& MASK_CPSR_V
);
13902 result
= n
== v
&& ((m_opcode_cpsr
& MASK_CPSR_Z
) == 0);
13906 // Always execute (cond == 0b1110, or the special 0b1111 which gives
13907 // opcodes different meanings, but always means execution happens.
13916 uint32_t EmulateInstructionARM::CurrentCond(const uint32_t opcode
) {
13917 switch (m_opcode_mode
) {
13922 return UnsignedBits(opcode
, 31, 28);
13925 // For T1 and T3 encodings of the Branch instruction, it returns the 4-bit
13926 // 'cond' field of the encoding.
13928 const uint32_t byte_size
= m_opcode
.GetByteSize();
13929 if (byte_size
== 2) {
13930 if (Bits32(opcode
, 15, 12) == 0x0d && Bits32(opcode
, 11, 8) != 0x0f)
13931 return Bits32(opcode
, 11, 8);
13932 } else if (byte_size
== 4) {
13933 if (Bits32(opcode
, 31, 27) == 0x1e && Bits32(opcode
, 15, 14) == 0x02 &&
13934 Bits32(opcode
, 12, 12) == 0x00 && Bits32(opcode
, 25, 22) <= 0x0d) {
13935 return Bits32(opcode
, 25, 22);
13938 // We have an invalid thumb instruction, let's bail out.
13941 return m_it_session
.GetCond();
13944 return UINT32_MAX
; // Return invalid value
13947 bool EmulateInstructionARM::InITBlock() {
13948 return CurrentInstrSet() == eModeThumb
&& m_it_session
.InITBlock();
13951 bool EmulateInstructionARM::LastInITBlock() {
13952 return CurrentInstrSet() == eModeThumb
&& m_it_session
.LastInITBlock();
13955 bool EmulateInstructionARM::BadMode(uint32_t mode
) {
13959 return false; // '10000'
13961 return false; // '10001'
13963 return false; // '10010'
13965 return false; // '10011'
13967 return false; // '10110'
13969 return false; // '10111'
13971 return false; // '11011'
13973 return false; // '11111'
13980 bool EmulateInstructionARM::CurrentModeIsPrivileged() {
13981 uint32_t mode
= Bits32(m_opcode_cpsr
, 4, 0);
13992 void EmulateInstructionARM::CPSRWriteByInstr(uint32_t value
, uint32_t bytemask
,
13993 bool affect_execstate
) {
13994 bool privileged
= CurrentModeIsPrivileged();
13996 uint32_t tmp_cpsr
= Bits32(m_opcode_cpsr
, 23, 20) << 20;
13998 if (BitIsSet(bytemask
, 3)) {
13999 tmp_cpsr
= tmp_cpsr
| (Bits32(value
, 31, 27) << 27);
14000 if (affect_execstate
)
14001 tmp_cpsr
= tmp_cpsr
| (Bits32(value
, 26, 24) << 24);
14004 if (BitIsSet(bytemask
, 2)) {
14005 tmp_cpsr
= tmp_cpsr
| (Bits32(value
, 19, 16) << 16);
14008 if (BitIsSet(bytemask
, 1)) {
14009 if (affect_execstate
)
14010 tmp_cpsr
= tmp_cpsr
| (Bits32(value
, 15, 10) << 10);
14011 tmp_cpsr
= tmp_cpsr
| (Bit32(value
, 9) << 9);
14013 tmp_cpsr
= tmp_cpsr
| (Bit32(value
, 8) << 8);
14016 if (BitIsSet(bytemask
, 0)) {
14018 tmp_cpsr
= tmp_cpsr
| (Bits32(value
, 7, 6) << 6);
14019 if (affect_execstate
)
14020 tmp_cpsr
= tmp_cpsr
| (Bit32(value
, 5) << 5);
14022 tmp_cpsr
= tmp_cpsr
| Bits32(value
, 4, 0);
14025 m_opcode_cpsr
= tmp_cpsr
;
14028 bool EmulateInstructionARM::BranchWritePC(const Context
&context
,
14032 // Check the current instruction set.
14033 if (CurrentInstrSet() == eModeARM
)
14034 target
= addr
& 0xfffffffc;
14036 target
= addr
& 0xfffffffe;
14038 return WriteRegisterUnsigned(context
, eRegisterKindGeneric
,
14039 LLDB_REGNUM_GENERIC_PC
, target
);
14042 // As a side effect, BXWritePC sets context.arg2 to eModeARM or eModeThumb by
14043 // inspecting addr.
14044 bool EmulateInstructionARM::BXWritePC(Context
&context
, uint32_t addr
) {
14046 // If the CPSR is changed due to switching between ARM and Thumb ISETSTATE,
14047 // we want to record it and issue a WriteRegister callback so the clients can
14048 // track the mode changes accordingly.
14049 bool cpsr_changed
= false;
14051 if (BitIsSet(addr
, 0)) {
14052 if (CurrentInstrSet() != eModeThumb
) {
14053 SelectInstrSet(eModeThumb
);
14054 cpsr_changed
= true;
14056 target
= addr
& 0xfffffffe;
14057 context
.SetISA(eModeThumb
);
14058 } else if (BitIsClear(addr
, 1)) {
14059 if (CurrentInstrSet() != eModeARM
) {
14060 SelectInstrSet(eModeARM
);
14061 cpsr_changed
= true;
14063 target
= addr
& 0xfffffffc;
14064 context
.SetISA(eModeARM
);
14066 return false; // address<1:0> == '10' => UNPREDICTABLE
14068 if (cpsr_changed
) {
14069 if (!WriteRegisterUnsigned(context
, eRegisterKindGeneric
,
14070 LLDB_REGNUM_GENERIC_FLAGS
, m_new_inst_cpsr
))
14073 return WriteRegisterUnsigned(context
, eRegisterKindGeneric
,
14074 LLDB_REGNUM_GENERIC_PC
, target
);
14077 // Dispatches to either BXWritePC or BranchWritePC based on architecture
14079 bool EmulateInstructionARM::LoadWritePC(Context
&context
, uint32_t addr
) {
14080 if (ArchVersion() >= ARMv5T
)
14081 return BXWritePC(context
, addr
);
14083 return BranchWritePC((const Context
)context
, addr
);
14086 // Dispatches to either BXWritePC or BranchWritePC based on architecture
14087 // versions and current instruction set.
14088 bool EmulateInstructionARM::ALUWritePC(Context
&context
, uint32_t addr
) {
14089 if (ArchVersion() >= ARMv7
&& CurrentInstrSet() == eModeARM
)
14090 return BXWritePC(context
, addr
);
14092 return BranchWritePC((const Context
)context
, addr
);
14095 EmulateInstructionARM::Mode
EmulateInstructionARM::CurrentInstrSet() {
14096 return m_opcode_mode
;
14099 // Set the 'T' bit of our CPSR. The m_opcode_mode gets updated when the next
14100 // ReadInstruction() is performed. This function has a side effect of updating
14101 // the m_new_inst_cpsr member variable if necessary.
14102 bool EmulateInstructionARM::SelectInstrSet(Mode arm_or_thumb
) {
14103 m_new_inst_cpsr
= m_opcode_cpsr
;
14104 switch (arm_or_thumb
) {
14108 // Clear the T bit.
14109 m_new_inst_cpsr
&= ~MASK_CPSR_T
;
14113 m_new_inst_cpsr
|= MASK_CPSR_T
;
14119 // This function returns TRUE if the processor currently provides support for
14120 // unaligned memory accesses, or FALSE otherwise. This is always TRUE in ARMv7,
14121 // controllable by the SCTLR.U bit in ARMv6, and always FALSE before ARMv6.
14122 bool EmulateInstructionARM::UnalignedSupport() {
14123 return (ArchVersion() >= ARMv7
);
14126 // The main addition and subtraction instructions can produce status
14127 // information about both unsigned carry and signed overflow conditions. This
14128 // status information can be used to synthesize multi-word additions and
14130 EmulateInstructionARM::AddWithCarryResult
14131 EmulateInstructionARM::AddWithCarry(uint32_t x
, uint32_t y
, uint8_t carry_in
) {
14136 uint64_t unsigned_sum
= x
+ y
+ carry_in
;
14137 int64_t signed_sum
= (int32_t)x
+ (int32_t)y
+ (int32_t)carry_in
;
14139 result
= UnsignedBits(unsigned_sum
, 31, 0);
14140 // carry_out = (result == unsigned_sum ? 0 : 1);
14141 overflow
= ((int32_t)result
== signed_sum
? 0 : 1);
14144 carry_out
= ((int32_t)x
>= (int32_t)(~y
)) ? 1 : 0;
14146 carry_out
= ((int32_t)x
> (int32_t)y
) ? 1 : 0;
14148 AddWithCarryResult res
= {result
, carry_out
, overflow
};
14152 uint32_t EmulateInstructionARM::ReadCoreReg(uint32_t num
, bool *success
) {
14153 lldb::RegisterKind reg_kind
;
14157 reg_kind
= eRegisterKindGeneric
;
14158 reg_num
= LLDB_REGNUM_GENERIC_SP
;
14161 reg_kind
= eRegisterKindGeneric
;
14162 reg_num
= LLDB_REGNUM_GENERIC_RA
;
14165 reg_kind
= eRegisterKindGeneric
;
14166 reg_num
= LLDB_REGNUM_GENERIC_PC
;
14169 if (num
< SP_REG
) {
14170 reg_kind
= eRegisterKindDWARF
;
14171 reg_num
= dwarf_r0
+ num
;
14173 // assert(0 && "Invalid register number");
14180 // Read our register.
14181 uint32_t val
= ReadRegisterUnsigned(reg_kind
, reg_num
, 0, success
);
14183 // When executing an ARM instruction , PC reads as the address of the current
14184 // instruction plus 8. When executing a Thumb instruction , PC reads as the
14185 // address of the current instruction plus 4.
14187 if (CurrentInstrSet() == eModeARM
)
14196 // Write the result to the ARM core register Rd, and optionally update the
14197 // condition flags based on the result.
14199 // This helper method tries to encapsulate the following pseudocode from the
14200 // ARM Architecture Reference Manual:
14202 // if d == 15 then // Can only occur for encoding A1
14203 // ALUWritePC(result); // setflags is always FALSE here
14206 // if setflags then
14207 // APSR.N = result<31>;
14208 // APSR.Z = IsZeroBit(result);
14210 // // APSR.V unchanged
14212 // In the above case, the API client does not pass in the overflow arg, which
14213 // defaults to ~0u.
14214 bool EmulateInstructionARM::WriteCoreRegOptionalFlags(
14215 Context
&context
, const uint32_t result
, const uint32_t Rd
, bool setflags
,
14216 const uint32_t carry
, const uint32_t overflow
) {
14218 if (!ALUWritePC(context
, result
))
14221 lldb::RegisterKind reg_kind
;
14225 reg_kind
= eRegisterKindGeneric
;
14226 reg_num
= LLDB_REGNUM_GENERIC_SP
;
14229 reg_kind
= eRegisterKindGeneric
;
14230 reg_num
= LLDB_REGNUM_GENERIC_RA
;
14233 reg_kind
= eRegisterKindDWARF
;
14234 reg_num
= dwarf_r0
+ Rd
;
14236 if (!WriteRegisterUnsigned(context
, reg_kind
, reg_num
, result
))
14239 return WriteFlags(context
, result
, carry
, overflow
);
14244 // This helper method tries to encapsulate the following pseudocode from the
14245 // ARM Architecture Reference Manual:
14247 // APSR.N = result<31>;
14248 // APSR.Z = IsZeroBit(result);
14250 // APSR.V = overflow
14252 // Default arguments can be specified for carry and overflow parameters, which
14253 // means not to update the respective flags.
14254 bool EmulateInstructionARM::WriteFlags(Context
&context
, const uint32_t result
,
14255 const uint32_t carry
,
14256 const uint32_t overflow
) {
14257 m_new_inst_cpsr
= m_opcode_cpsr
;
14258 SetBit32(m_new_inst_cpsr
, CPSR_N_POS
, Bit32(result
, CPSR_N_POS
));
14259 SetBit32(m_new_inst_cpsr
, CPSR_Z_POS
, result
== 0 ? 1 : 0);
14261 SetBit32(m_new_inst_cpsr
, CPSR_C_POS
, carry
);
14262 if (overflow
!= ~0u)
14263 SetBit32(m_new_inst_cpsr
, CPSR_V_POS
, overflow
);
14264 if (m_new_inst_cpsr
!= m_opcode_cpsr
) {
14265 if (!WriteRegisterUnsigned(context
, eRegisterKindGeneric
,
14266 LLDB_REGNUM_GENERIC_FLAGS
, m_new_inst_cpsr
))
14272 bool EmulateInstructionARM::EvaluateInstruction(uint32_t evaluate_options
) {
14273 ARMOpcode
*opcode_data
= nullptr;
14275 if (m_opcode_mode
== eModeThumb
)
14277 GetThumbOpcodeForInstruction(m_opcode
.GetOpcode32(), m_arm_isa
);
14278 else if (m_opcode_mode
== eModeARM
)
14279 opcode_data
= GetARMOpcodeForInstruction(m_opcode
.GetOpcode32(), m_arm_isa
);
14281 const bool auto_advance_pc
=
14282 evaluate_options
& eEmulateInstructionOptionAutoAdvancePC
;
14283 m_ignore_conditions
=
14284 evaluate_options
& eEmulateInstructionOptionIgnoreConditions
;
14286 bool success
= false;
14287 if (m_opcode_cpsr
== 0 || !m_ignore_conditions
) {
14289 ReadRegisterUnsigned(eRegisterKindDWARF
, dwarf_cpsr
, 0, &success
);
14292 // Only return false if we are unable to read the CPSR if we care about
14294 if (!success
&& !m_ignore_conditions
)
14297 uint32_t orig_pc_value
= 0;
14298 if (auto_advance_pc
) {
14300 ReadRegisterUnsigned(eRegisterKindDWARF
, dwarf_pc
, 0, &success
);
14305 // Call the Emulate... function if we managed to decode the opcode.
14307 success
= (this->*opcode_data
->callback
)(m_opcode
.GetOpcode32(),
14308 opcode_data
->encoding
);
14313 // Advance the ITSTATE bits to their values for the next instruction if we
14314 // haven't just executed an IT instruction what initialized it.
14315 if (m_opcode_mode
== eModeThumb
&& m_it_session
.InITBlock() &&
14316 (opcode_data
== nullptr ||
14317 opcode_data
->callback
!= &EmulateInstructionARM::EmulateIT
))
14318 m_it_session
.ITAdvance();
14320 if (auto_advance_pc
) {
14321 uint32_t after_pc_value
=
14322 ReadRegisterUnsigned(eRegisterKindDWARF
, dwarf_pc
, 0, &success
);
14326 if (after_pc_value
== orig_pc_value
) {
14327 after_pc_value
+= m_opcode
.GetByteSize();
14329 EmulateInstruction::Context context
;
14330 context
.type
= eContextAdvancePC
;
14331 context
.SetNoArgs();
14332 if (!WriteRegisterUnsigned(context
, eRegisterKindDWARF
, dwarf_pc
,
14340 EmulateInstruction::InstructionCondition
14341 EmulateInstructionARM::GetInstructionCondition() {
14342 const uint32_t cond
= CurrentCond(m_opcode
.GetOpcode32());
14343 if (cond
== 0xe || cond
== 0xf || cond
== UINT32_MAX
)
14344 return EmulateInstruction::UnconditionalCondition
;
14348 bool EmulateInstructionARM::TestEmulation(Stream
&out_stream
, ArchSpec
&arch
,
14349 OptionValueDictionary
*test_data
) {
14351 out_stream
.Printf("TestEmulation: Missing test data.\n");
14355 static constexpr llvm::StringLiteral
opcode_key("opcode");
14356 static constexpr llvm::StringLiteral
before_key("before_state");
14357 static constexpr llvm::StringLiteral
after_key("after_state");
14359 OptionValueSP value_sp
= test_data
->GetValueForKey(opcode_key
);
14361 uint32_t test_opcode
;
14362 if ((value_sp
.get() == nullptr) ||
14363 (value_sp
->GetType() != OptionValue::eTypeUInt64
)) {
14364 out_stream
.Printf("TestEmulation: Error reading opcode from test file.\n");
14367 test_opcode
= value_sp
->GetValueAs
<uint64_t>().value_or(0);
14369 if (arch
.GetTriple().getArch() == llvm::Triple::thumb
||
14370 arch
.IsAlwaysThumbInstructions()) {
14371 m_opcode_mode
= eModeThumb
;
14372 if (test_opcode
< 0x10000)
14373 m_opcode
.SetOpcode16(test_opcode
, endian::InlHostByteOrder());
14375 m_opcode
.SetOpcode32(test_opcode
, endian::InlHostByteOrder());
14376 } else if (arch
.GetTriple().getArch() == llvm::Triple::arm
) {
14377 m_opcode_mode
= eModeARM
;
14378 m_opcode
.SetOpcode32(test_opcode
, endian::InlHostByteOrder());
14380 out_stream
.Printf("TestEmulation: Invalid arch.\n");
14384 EmulationStateARM before_state
;
14385 EmulationStateARM after_state
;
14387 value_sp
= test_data
->GetValueForKey(before_key
);
14388 if ((value_sp
.get() == nullptr) ||
14389 (value_sp
->GetType() != OptionValue::eTypeDictionary
)) {
14390 out_stream
.Printf("TestEmulation: Failed to find 'before' state.\n");
14394 OptionValueDictionary
*state_dictionary
= value_sp
->GetAsDictionary();
14395 if (!before_state
.LoadStateFromDictionary(state_dictionary
)) {
14396 out_stream
.Printf("TestEmulation: Failed loading 'before' state.\n");
14400 value_sp
= test_data
->GetValueForKey(after_key
);
14401 if ((value_sp
.get() == nullptr) ||
14402 (value_sp
->GetType() != OptionValue::eTypeDictionary
)) {
14403 out_stream
.Printf("TestEmulation: Failed to find 'after' state.\n");
14407 state_dictionary
= value_sp
->GetAsDictionary();
14408 if (!after_state
.LoadStateFromDictionary(state_dictionary
)) {
14409 out_stream
.Printf("TestEmulation: Failed loading 'after' state.\n");
14413 SetBaton((void *)&before_state
);
14414 SetCallbacks(&EmulationStateARM::ReadPseudoMemory
,
14415 &EmulationStateARM::WritePseudoMemory
,
14416 &EmulationStateARM::ReadPseudoRegister
,
14417 &EmulationStateARM::WritePseudoRegister
);
14419 bool success
= EvaluateInstruction(eEmulateInstructionOptionAutoAdvancePC
);
14421 out_stream
.Printf("TestEmulation: EvaluateInstruction() failed.\n");
14425 success
= before_state
.CompareState(after_state
, out_stream
);
14427 out_stream
.Printf("TestEmulation: State after emulation does not match "
14428 "'after' state.\n");
14435 // EmulateInstructionARM::GetRegisterName (uint32_t reg_kind, uint32_t reg_num)
14437 // if (reg_kind == eRegisterKindGeneric)
14439 // switch (reg_num)
14441 // case LLDB_REGNUM_GENERIC_PC: return "pc";
14442 // case LLDB_REGNUM_GENERIC_SP: return "sp";
14443 // case LLDB_REGNUM_GENERIC_FP: return "fp";
14444 // case LLDB_REGNUM_GENERIC_RA: return "lr";
14445 // case LLDB_REGNUM_GENERIC_FLAGS: return "cpsr";
14446 // default: return NULL;
14449 // else if (reg_kind == eRegisterKindDWARF)
14451 // return GetARMDWARFRegisterName (reg_num);
14456 bool EmulateInstructionARM::CreateFunctionEntryUnwind(UnwindPlan
&unwind_plan
) {
14457 unwind_plan
.Clear();
14458 unwind_plan
.SetRegisterKind(eRegisterKindDWARF
);
14460 UnwindPlan::RowSP
row(new UnwindPlan::Row
);
14462 // Our previous Call Frame Address is the stack pointer
14463 row
->GetCFAValue().SetIsRegisterPlusOffset(dwarf_sp
, 0);
14465 unwind_plan
.AppendRow(row
);
14466 unwind_plan
.SetSourceName("EmulateInstructionARM");
14467 unwind_plan
.SetSourcedFromCompiler(eLazyBoolNo
);
14468 unwind_plan
.SetUnwindPlanValidAtAllInstructions(eLazyBoolYes
);
14469 unwind_plan
.SetUnwindPlanForSignalTrap(eLazyBoolNo
);
14470 unwind_plan
.SetReturnAddressRegister(dwarf_lr
);