1 | //===-- EmulateInstructionARM64.h -------------------------------*- C++ -*-===// |
2 | // |
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 |
6 | // |
7 | //===----------------------------------------------------------------------===// |
8 | |
9 | #ifndef LLDB_SOURCE_PLUGINS_INSTRUCTION_ARM64_EMULATEINSTRUCTIONARM64_H |
10 | #define LLDB_SOURCE_PLUGINS_INSTRUCTION_ARM64_EMULATEINSTRUCTIONARM64_H |
11 | |
12 | #include "Plugins/Process/Utility/ARMDefines.h" |
13 | #include "lldb/Core/EmulateInstruction.h" |
14 | #include "lldb/Interpreter/OptionValue.h" |
15 | #include "lldb/Utility/Status.h" |
16 | #include <optional> |
17 | |
18 | class EmulateInstructionARM64 : public lldb_private::EmulateInstruction { |
19 | public: |
20 | EmulateInstructionARM64(const lldb_private::ArchSpec &arch) |
21 | : EmulateInstruction(arch), m_opcode_pstate(), m_emulated_pstate(), |
22 | m_ignore_conditions(false) {} |
23 | |
24 | static void Initialize(); |
25 | |
26 | static void Terminate(); |
27 | |
28 | static llvm::StringRef GetPluginNameStatic() { return "arm64" ; } |
29 | |
30 | static llvm::StringRef GetPluginDescriptionStatic(); |
31 | |
32 | static lldb_private::EmulateInstruction * |
33 | CreateInstance(const lldb_private::ArchSpec &arch, |
34 | lldb_private::InstructionType inst_type); |
35 | |
36 | static bool SupportsEmulatingInstructionsOfTypeStatic( |
37 | lldb_private::InstructionType inst_type) { |
38 | switch (inst_type) { |
39 | case lldb_private::eInstructionTypeAny: |
40 | case lldb_private::eInstructionTypePrologueEpilogue: |
41 | return true; |
42 | |
43 | case lldb_private::eInstructionTypePCModifying: |
44 | case lldb_private::eInstructionTypeAll: |
45 | return false; |
46 | } |
47 | return false; |
48 | } |
49 | |
50 | llvm::StringRef GetPluginName() override { return GetPluginNameStatic(); } |
51 | |
52 | bool SetTargetTriple(const lldb_private::ArchSpec &arch) override; |
53 | |
54 | bool SupportsEmulatingInstructionsOfType( |
55 | lldb_private::InstructionType inst_type) override { |
56 | return SupportsEmulatingInstructionsOfTypeStatic(inst_type); |
57 | } |
58 | |
59 | bool ReadInstruction() override; |
60 | |
61 | bool EvaluateInstruction(uint32_t evaluate_options) override; |
62 | |
63 | bool TestEmulation(lldb_private::Stream &out_stream, |
64 | lldb_private::ArchSpec &arch, |
65 | lldb_private::OptionValueDictionary *test_data) override { |
66 | return false; |
67 | } |
68 | |
69 | std::optional<lldb_private::RegisterInfo> |
70 | GetRegisterInfo(lldb::RegisterKind reg_kind, uint32_t reg_num) override; |
71 | |
72 | bool |
73 | CreateFunctionEntryUnwind(lldb_private::UnwindPlan &unwind_plan) override; |
74 | |
75 | enum AddrMode { AddrMode_OFF, AddrMode_PRE, AddrMode_POST }; |
76 | |
77 | enum BranchType { |
78 | BranchType_CALL, |
79 | BranchType_ERET, |
80 | BranchType_DRET, |
81 | BranchType_RET, |
82 | BranchType_JMP |
83 | }; |
84 | |
85 | enum CountOp { CountOp_CLZ, CountOp_CLS, CountOp_CNT }; |
86 | |
87 | enum RevOp { RevOp_RBIT, RevOp_REV16, RevOp_REV32, RevOp_REV64 }; |
88 | |
89 | enum BitwiseOp { BitwiseOp_NOT, BitwiseOp_RBIT }; |
90 | |
91 | enum ExceptionLevel { EL0 = 0, EL1 = 1, EL2 = 2, EL3 = 3 }; |
92 | |
93 | enum ExtendType { |
94 | ExtendType_SXTB, |
95 | ExtendType_SXTH, |
96 | ExtendType_SXTW, |
97 | ExtendType_SXTX, |
98 | ExtendType_UXTB, |
99 | ExtendType_UXTH, |
100 | ExtendType_UXTW, |
101 | ExtendType_UXTX |
102 | }; |
103 | |
104 | enum { , }; |
105 | |
106 | enum LogicalOp { LogicalOp_AND, LogicalOp_EOR, LogicalOp_ORR }; |
107 | |
108 | enum MemOp { MemOp_LOAD, MemOp_STORE, MemOp_PREFETCH, MemOp_NOP }; |
109 | |
110 | enum MoveWideOp { MoveWideOp_N, MoveWideOp_Z, MoveWideOp_K }; |
111 | |
112 | enum ShiftType { ShiftType_LSL, ShiftType_LSR, ShiftType_ASR, ShiftType_ROR }; |
113 | |
114 | enum StackPointerSelection { SP0 = 0, SPx = 1 }; |
115 | |
116 | enum Unpredictable { Unpredictable_WBOVERLAP, Unpredictable_LDPOVERLAP }; |
117 | |
118 | enum ConstraintType { |
119 | Constraint_NONE, |
120 | Constraint_UNKNOWN, |
121 | Constraint_SUPPRESSWB, |
122 | Constraint_NOP |
123 | }; |
124 | |
125 | enum AccType { |
126 | AccType_NORMAL, |
127 | AccType_UNPRIV, |
128 | AccType_STREAM, |
129 | AccType_ALIGNED, |
130 | AccType_ORDERED |
131 | }; |
132 | |
133 | typedef struct { |
134 | uint32_t N : 1, V : 1, C : 1, |
135 | Z : 1, // condition code flags – can also be accessed as |
136 | // PSTATE.[N,Z,C,V] |
137 | Q : 1, // AArch32 only – CSPR.Q bit |
138 | IT : 8, // AArch32 only – CPSR.IT bits |
139 | J : 1, // AArch32 only – CSPR.J bit |
140 | T : 1, // AArch32 only – CPSR.T bit |
141 | SS : 1, // Single step process state bit |
142 | IL : 1, // Illegal state bit |
143 | D : 1, A : 1, I : 1, |
144 | F : 1, // Interrupt masks – can also be accessed as PSTATE.[D,A,I,F] |
145 | E : 1, // AArch32 only – CSPR.E bit |
146 | M : 5, // AArch32 only – mode encodings |
147 | RW : 1, // Current register width – 0 is AArch64, 1 is AArch32 |
148 | EL : 2, // Current exception level (see ExceptionLevel enum) |
149 | SP : 1; // AArch64 only - Stack Pointer selection (see |
150 | // StackPointerSelection enum) |
151 | } ProcState; |
152 | |
153 | protected: |
154 | static uint64_t AddWithCarry(uint32_t N, uint64_t x, uint64_t y, bool carry_in, |
155 | EmulateInstructionARM64::ProcState &proc_state); |
156 | |
157 | typedef struct { |
158 | uint32_t mask; |
159 | uint32_t value; |
160 | uint32_t vfp_variants; |
161 | bool (EmulateInstructionARM64::*callback)(const uint32_t opcode); |
162 | const char *name; |
163 | } Opcode; |
164 | |
165 | static Opcode *GetOpcodeForInstruction(const uint32_t opcode); |
166 | |
167 | uint32_t GetFramePointerRegisterNumber() const; |
168 | |
169 | bool BranchTo(const Context &context, uint32_t N, lldb::addr_t target); |
170 | |
171 | bool ConditionHolds(const uint32_t cond); |
172 | |
173 | bool UsingAArch32(); |
174 | |
175 | bool EmulateADDSUBImm(const uint32_t opcode); |
176 | |
177 | template <AddrMode a_mode> bool EmulateLDPSTP(const uint32_t opcode); |
178 | |
179 | template <AddrMode a_mode> bool EmulateLDRSTRImm(const uint32_t opcode); |
180 | |
181 | bool EmulateB(const uint32_t opcode); |
182 | |
183 | bool EmulateBcond(const uint32_t opcode); |
184 | |
185 | bool EmulateCBZ(const uint32_t opcode); |
186 | |
187 | bool EmulateTBZ(const uint32_t opcode); |
188 | |
189 | ProcState m_opcode_pstate; |
190 | ProcState m_emulated_pstate; // This can get updated by the opcode. |
191 | bool m_ignore_conditions; |
192 | }; |
193 | |
194 | #endif // LLDB_SOURCE_PLUGINS_INSTRUCTION_ARM64_EMULATEINSTRUCTIONARM64_H |
195 | |