1 //===- ARMDisassemblerCore.h - ARM disassembler helpers ---------*- C++ -*-===//
2 //
3 // The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 // This file is part of the ARM Disassembler.
11 //
12 // The first part defines the enumeration type of ARM instruction format, which
13 // specifies the encoding used by the instruction, as well as a helper function
14 // to convert the enums to printable char strings.
15 //
16 // It also contains code to represent the concepts of Builder and DisassembleFP
17 // to solve the problem of disassembling an ARM instr.
18 //
19 //===----------------------------------------------------------------------===//
20
21 #ifndef ARMDISASSEMBLERCORE_H
22 #define ARMDISASSEMBLERCORE_H
23
24 #include "llvm/MC/MCInst.h"
25 #include "llvm/MC/MCSymbol.h"
26 #include "llvm/MC/MCExpr.h"
27 #include "llvm/MC/MCContext.h"
28 #include "llvm/Target/TargetInstrInfo.h"
29 #include "llvm-c/Disassembler.h"
30 #include "ARMBaseInstrInfo.h"
31 #include "ARMRegisterInfo.h"
32 #include "ARMDisassembler.h"
33
34 namespace llvm {
35 class MCContext;
36
37 class ARMUtils {
38 public:
39 static const char *OpcodeName(unsigned Opcode);
40 };
41
42 /////////////////////////////////////////////////////
43 // //
44 // Enums and Utilities for ARM Instruction Format //
45 // //
46 /////////////////////////////////////////////////////
47
48 #define ARM_FORMATS \
49 ENTRY(ARM_FORMAT_PSEUDO, 0) \
50 ENTRY(ARM_FORMAT_MULFRM, 1) \
51 ENTRY(ARM_FORMAT_BRFRM, 2) \
52 ENTRY(ARM_FORMAT_BRMISCFRM, 3) \
53 ENTRY(ARM_FORMAT_DPFRM, 4) \
54 ENTRY(ARM_FORMAT_DPSOREGFRM, 5) \
55 ENTRY(ARM_FORMAT_LDFRM, 6) \
56 ENTRY(ARM_FORMAT_STFRM, 7) \
57 ENTRY(ARM_FORMAT_LDMISCFRM, 8) \
58 ENTRY(ARM_FORMAT_STMISCFRM, 9) \
59 ENTRY(ARM_FORMAT_LDSTMULFRM, 10) \
60 ENTRY(ARM_FORMAT_LDSTEXFRM, 11) \
61 ENTRY(ARM_FORMAT_ARITHMISCFRM, 12) \
62 ENTRY(ARM_FORMAT_SATFRM, 13) \
63 ENTRY(ARM_FORMAT_EXTFRM, 14) \
64 ENTRY(ARM_FORMAT_VFPUNARYFRM, 15) \
65 ENTRY(ARM_FORMAT_VFPBINARYFRM, 16) \
66 ENTRY(ARM_FORMAT_VFPCONV1FRM, 17) \
67 ENTRY(ARM_FORMAT_VFPCONV2FRM, 18) \
68 ENTRY(ARM_FORMAT_VFPCONV3FRM, 19) \
69 ENTRY(ARM_FORMAT_VFPCONV4FRM, 20) \
70 ENTRY(ARM_FORMAT_VFPCONV5FRM, 21) \
71 ENTRY(ARM_FORMAT_VFPLDSTFRM, 22) \
72 ENTRY(ARM_FORMAT_VFPLDSTMULFRM, 23) \
73 ENTRY(ARM_FORMAT_VFPMISCFRM, 24) \
74 ENTRY(ARM_FORMAT_THUMBFRM, 25) \
75 ENTRY(ARM_FORMAT_MISCFRM, 26) \
76 ENTRY(ARM_FORMAT_NEONGETLNFRM, 27) \
77 ENTRY(ARM_FORMAT_NEONSETLNFRM, 28) \
78 ENTRY(ARM_FORMAT_NEONDUPFRM, 29) \
79 ENTRY(ARM_FORMAT_NLdSt, 30) \
80 ENTRY(ARM_FORMAT_N1RegModImm, 31) \
81 ENTRY(ARM_FORMAT_N2Reg, 32) \
82 ENTRY(ARM_FORMAT_NVCVT, 33) \
83 ENTRY(ARM_FORMAT_NVecDupLn, 34) \
84 ENTRY(ARM_FORMAT_N2RegVecShL, 35) \
85 ENTRY(ARM_FORMAT_N2RegVecShR, 36) \
86 ENTRY(ARM_FORMAT_N3Reg, 37) \
87 ENTRY(ARM_FORMAT_N3RegVecSh, 38) \
88 ENTRY(ARM_FORMAT_NVecExtract, 39) \
89 ENTRY(ARM_FORMAT_NVecMulScalar, 40) \
90 ENTRY(ARM_FORMAT_NVTBL, 41)
91
92 // ARM instruction format specifies the encoding used by the instruction.
93 #define ENTRY(n, v) n = v,
94 typedef enum {
95 ARM_FORMATS
96 ARM_FORMAT_NA
97 } ARMFormat;
98 #undef ENTRY
99
100 // Converts enum to const char*.
stringForARMFormat(ARMFormat form)101 static const inline char *stringForARMFormat(ARMFormat form) {
102 #define ENTRY(n, v) case n: return #n;
103 switch(form) {
104 ARM_FORMATS
105 case ARM_FORMAT_NA:
106 default:
107 return "";
108 }
109 #undef ENTRY
110 }
111
112 /// Expands on the enum definitions from ARMBaseInstrInfo.h.
113 /// They are being used by the disassembler implementation.
114 namespace ARMII {
115 enum {
116 NEONRegMask = 15,
117 GPRRegMask = 15,
118 NEON_RegRdShift = 12,
119 NEON_D_BitShift = 22,
120 NEON_RegRnShift = 16,
121 NEON_N_BitShift = 7,
122 NEON_RegRmShift = 0,
123 NEON_M_BitShift = 5
124 };
125 }
126
127 /// Utility function for extracting [From, To] bits from a uint32_t.
slice(uint32_t Bits,unsigned From,unsigned To)128 static inline unsigned slice(uint32_t Bits, unsigned From, unsigned To) {
129 assert(From < 32 && To < 32 && From >= To);
130 return (Bits >> To) & ((1 << (From - To + 1)) - 1);
131 }
132
133 /// Utility function for setting [From, To] bits to Val for a uint32_t.
setSlice(unsigned & Bits,unsigned From,unsigned To,unsigned Val)134 static inline void setSlice(unsigned &Bits, unsigned From, unsigned To,
135 unsigned Val) {
136 assert(From < 32 && To < 32 && From >= To);
137 uint32_t Mask = ((1 << (From - To + 1)) - 1);
138 Bits &= ~(Mask << To);
139 Bits |= (Val & Mask) << To;
140 }
141
142 // Return an integer result equal to the number of bits of x that are ones.
143 static inline uint32_t
BitCount(uint64_t x)144 BitCount (uint64_t x)
145 {
146 // c accumulates the total bits set in x
147 uint32_t c;
148 for (c = 0; x; ++c)
149 {
150 x &= x - 1; // clear the least significant bit set
151 }
152 return c;
153 }
154
155 static inline bool
BitIsSet(const uint64_t value,const uint64_t bit)156 BitIsSet (const uint64_t value, const uint64_t bit)
157 {
158 return (value & (1ull << bit)) != 0;
159 }
160
161 static inline bool
BitIsClear(const uint64_t value,const uint64_t bit)162 BitIsClear (const uint64_t value, const uint64_t bit)
163 {
164 return (value & (1ull << bit)) == 0;
165 }
166
167 /// Various utilities for checking the target specific flags.
168
169 /// A unary data processing instruction doesn't have an Rn operand.
isUnaryDP(uint64_t TSFlags)170 static inline bool isUnaryDP(uint64_t TSFlags) {
171 return (TSFlags & ARMII::UnaryDP);
172 }
173
174 /// A NEON Domain instruction has cond field (Inst{31-28}) as 0b1111.
isNEONDomain(uint64_t TSFlags)175 static inline bool isNEONDomain(uint64_t TSFlags) {
176 return (TSFlags & ARMII::DomainNEON) ||
177 (TSFlags & ARMII::DomainNEONA8);
178 }
179
180 /// This four-bit field describes the addressing mode used.
181 /// See also ARMBaseInstrInfo.h.
getAddrMode(uint64_t TSFlags)182 static inline unsigned getAddrMode(uint64_t TSFlags) {
183 return (TSFlags & ARMII::AddrModeMask);
184 }
185
186 /// {IndexModePre, IndexModePost}
187 /// Only valid for load and store ops.
188 /// See also ARMBaseInstrInfo.h.
getIndexMode(uint64_t TSFlags)189 static inline unsigned getIndexMode(uint64_t TSFlags) {
190 return (TSFlags & ARMII::IndexModeMask) >> ARMII::IndexModeShift;
191 }
192
193 /// Pre-/post-indexed operations define an extra $base_wb in the OutOperandList.
isPrePostLdSt(uint64_t TSFlags)194 static inline bool isPrePostLdSt(uint64_t TSFlags) {
195 return (TSFlags & ARMII::IndexModeMask) != 0;
196 }
197
198 // Forward declaration.
199 class ARMBasicMCBuilder;
200
201 // Builder Object is mostly ignored except in some Thumb disassemble functions.
202 typedef ARMBasicMCBuilder *BO;
203
204 /// DisassembleFP - DisassembleFP points to a function that disassembles an insn
205 /// and builds the MCOperand list upon disassembly. It returns false on failure
206 /// or true on success. The number of operands added is updated upon success.
207 typedef bool (*DisassembleFP)(MCInst &MI, unsigned Opcode, uint32_t insn,
208 unsigned short NumOps, unsigned &NumOpsAdded, BO Builder);
209
210 /// CreateMCBuilder - Return an ARMBasicMCBuilder that can build up the MC
211 /// infrastructure of an MCInst given the Opcode and Format of the instr.
212 /// Return NULL if it fails to create/return a proper builder. API clients
213 /// are responsible for freeing up of the allocated memory. Cacheing can be
214 /// performed by the API clients to improve performance.
215 extern ARMBasicMCBuilder *CreateMCBuilder(unsigned Opcode, ARMFormat Format);
216
217 /// ARMBasicMCBuilder - ARMBasicMCBuilder represents an ARM MCInst builder that
218 /// knows how to build up the MCOperand list.
219 class ARMBasicMCBuilder {
220 friend ARMBasicMCBuilder *CreateMCBuilder(unsigned Opcode, ARMFormat Format);
221 unsigned Opcode;
222 ARMFormat Format;
223 unsigned short NumOps;
224 DisassembleFP Disasm;
225 Session *SP;
226 int Err; // !=0 if the builder encounters some error condition during build.
227
228 private:
229 /// Opcode, Format, and NumOperands make up an ARM Basic MCBuilder.
230 ARMBasicMCBuilder(unsigned opc, ARMFormat format, unsigned short num);
231
232 public:
ARMBasicMCBuilder(ARMBasicMCBuilder & B)233 ARMBasicMCBuilder(ARMBasicMCBuilder &B)
234 : Opcode(B.Opcode), Format(B.Format), NumOps(B.NumOps), Disasm(B.Disasm),
235 SP(B.SP), GetOpInfo(0), DisInfo(0), Ctx(0) {
236 Err = 0;
237 }
238
~ARMBasicMCBuilder()239 virtual ~ARMBasicMCBuilder() {}
240
SetSession(Session * sp)241 void SetSession(Session *sp) {
242 SP = sp;
243 }
244
SetErr(int ErrCode)245 void SetErr(int ErrCode) {
246 Err = ErrCode;
247 }
248
249 /// DoPredicateOperands - DoPredicateOperands process the predicate operands
250 /// of some Thumb instructions which come before the reglist operands. It
251 /// returns true if the two predicate operands have been processed.
252 bool DoPredicateOperands(MCInst& MI, unsigned Opcode,
253 uint32_t insn, unsigned short NumOpsRemaning);
254
255 /// TryPredicateAndSBitModifier - TryPredicateAndSBitModifier tries to process
256 /// the possible Predicate and SBitModifier, to build the remaining MCOperand
257 /// constituents.
258 bool TryPredicateAndSBitModifier(MCInst& MI, unsigned Opcode,
259 uint32_t insn, unsigned short NumOpsRemaning);
260
261 /// InITBlock - InITBlock returns true if we are inside an IT block.
InITBlock()262 bool InITBlock() {
263 if (SP)
264 return SP->ITCounter > 0;
265
266 return false;
267 }
268
269 /// Build - Build delegates to BuildIt to perform the heavy liftling. After
270 /// that, it invokes RunBuildAfterHook where some housekeepings can be done.
Build(MCInst & MI,uint32_t insn)271 virtual bool Build(MCInst &MI, uint32_t insn) {
272 bool Status = BuildIt(MI, insn);
273 return RunBuildAfterHook(Status, MI, insn);
274 }
275
276 /// BuildIt - BuildIt performs the build step for this ARM Basic MC Builder.
277 /// The general idea is to set the Opcode for the MCInst, followed by adding
278 /// the appropriate MCOperands to the MCInst. ARM Basic MC Builder delegates
279 /// to the Format-specific disassemble function for disassembly, followed by
280 /// TryPredicateAndSBitModifier() for PredicateOperand and OptionalDefOperand
281 /// which follow the Dst/Src Operands.
282 virtual bool BuildIt(MCInst &MI, uint32_t insn);
283
284 /// RunBuildAfterHook - RunBuildAfterHook performs operations deemed necessary
285 /// after BuildIt is finished.
286 virtual bool RunBuildAfterHook(bool Status, MCInst &MI, uint32_t insn);
287
288 private:
289 /// Get condition of the current IT instruction.
GetITCond()290 unsigned GetITCond() {
291 assert(SP);
292 return slice(SP->ITState, 7, 4);
293 }
294
295 private:
296 //
297 // Hooks for symbolic disassembly via the public 'C' interface.
298 //
299 // The function to get the symbolic information for operands.
300 LLVMOpInfoCallback GetOpInfo;
301 // The pointer to the block of symbolic information for above call back.
302 void *DisInfo;
303 // The assembly context for creating symbols and MCExprs in place of
304 // immediate operands when there is symbolic information.
305 MCContext *Ctx;
306 // The address of the instruction being disassembled.
307 uint64_t Address;
308
309 public:
setupBuilderForSymbolicDisassembly(LLVMOpInfoCallback getOpInfo,void * disInfo,MCContext * ctx,uint64_t address)310 void setupBuilderForSymbolicDisassembly(LLVMOpInfoCallback getOpInfo,
311 void *disInfo, MCContext *ctx,
312 uint64_t address) {
313 GetOpInfo = getOpInfo;
314 DisInfo = disInfo;
315 Ctx = ctx;
316 Address = address;
317 }
318
getBuilderAddress()319 uint64_t getBuilderAddress() const { return Address; }
320
321 /// tryAddingSymbolicOperand - tryAddingSymbolicOperand trys to add a symbolic
322 /// operand in place of the immediate Value in the MCInst. The immediate
323 /// Value has had any PC adjustment made by the caller. If the getOpInfo()
324 /// function was set as part of the setupBuilderForSymbolicDisassembly() call
325 /// then that function is called to get any symbolic information at the
326 /// builder's Address for this instrution. If that returns non-zero then the
327 /// symbolic information it returns is used to create an MCExpr and that is
328 /// added as an operand to the MCInst. This function returns true if it adds
329 /// an operand to the MCInst and false otherwise.
330 bool tryAddingSymbolicOperand(uint64_t Value, uint64_t InstSize, MCInst &MI);
331
332 };
333
334 } // namespace llvm
335
336 #endif
337