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