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 ExtractType { ExtractType_LEFT, ExtractType_RIGHT };
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