1 //===- ARMDisassemblerCore.h - ARM disassembler helpers ----*- C++ -*-===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 // This file is part of the ARM Disassembler.
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.
16 // It also contains code to represent the concepts of Builder, Builder Factory,
17 // as well as the Algorithm to solve the problem of disassembling an ARM instr.
19 //===----------------------------------------------------------------------===//
21 #ifndef ARMDISASSEMBLERCORE_H
22 #define ARMDISASSEMBLERCORE_H
24 #include "llvm/MC/MCInst.h"
25 #include "llvm/Target/TargetInstrInfo.h"
26 #include "ARMInstrInfo.h"
32 static const char *OpcodeName(unsigned Opcode);
36 ENTRY(ARM_FORMAT_PSEUDO, 0) \
37 ENTRY(ARM_FORMAT_MULFRM, 1) \
38 ENTRY(ARM_FORMAT_BRFRM, 2) \
39 ENTRY(ARM_FORMAT_BRMISCFRM, 3) \
40 ENTRY(ARM_FORMAT_DPFRM, 4) \
41 ENTRY(ARM_FORMAT_DPSOREGFRM, 5) \
42 ENTRY(ARM_FORMAT_LDFRM, 6) \
43 ENTRY(ARM_FORMAT_STFRM, 7) \
44 ENTRY(ARM_FORMAT_LDMISCFRM, 8) \
45 ENTRY(ARM_FORMAT_STMISCFRM, 9) \
46 ENTRY(ARM_FORMAT_LDSTMULFRM, 10) \
47 ENTRY(ARM_FORMAT_ARITHMISCFRM, 11) \
48 ENTRY(ARM_FORMAT_EXTFRM, 12) \
49 ENTRY(ARM_FORMAT_VFPUNARYFRM, 13) \
50 ENTRY(ARM_FORMAT_VFPBINARYFRM, 14) \
51 ENTRY(ARM_FORMAT_VFPCONV1FRM, 15) \
52 ENTRY(ARM_FORMAT_VFPCONV2FRM, 16) \
53 ENTRY(ARM_FORMAT_VFPCONV3FRM, 17) \
54 ENTRY(ARM_FORMAT_VFPCONV4FRM, 18) \
55 ENTRY(ARM_FORMAT_VFPCONV5FRM, 19) \
56 ENTRY(ARM_FORMAT_VFPLDSTFRM, 20) \
57 ENTRY(ARM_FORMAT_VFPLDSTMULFRM, 21) \
58 ENTRY(ARM_FORMAT_VFPMISCFRM, 22) \
59 ENTRY(ARM_FORMAT_THUMBFRM, 23) \
60 ENTRY(ARM_FORMAT_NEONFRM, 24) \
61 ENTRY(ARM_FORMAT_NEONGETLNFRM, 25) \
62 ENTRY(ARM_FORMAT_NEONSETLNFRM, 26) \
63 ENTRY(ARM_FORMAT_NEONDUPFRM, 27) \
64 ENTRY(ARM_FORMAT_LDSTEXFRM, 28) \
65 ENTRY(ARM_FORMAT_MISCFRM, 29) \
66 ENTRY(ARM_FORMAT_THUMBMISCFRM, 30)
68 // ARM instruction format specifies the encoding used by the instruction.
69 #define ENTRY(n, v) n = v,
76 // Converts enum to const char*.
77 static const inline char *stringForARMFormat(ARMFormat form) {
78 #define ENTRY(n, v) case n: return #n;
89 ENTRY(NS_FORMAT_NONE, 0) \
90 ENTRY(NS_FORMAT_VLDSTLane, 1) \
91 ENTRY(NS_FORMAT_VLDSTLaneDbl, 2) \
92 ENTRY(NS_FORMAT_VLDSTRQ, 3) \
93 ENTRY(NS_FORMAT_NVdImm, 4) \
94 ENTRY(NS_FORMAT_NVdVmImm, 5) \
95 ENTRY(NS_FORMAT_NVdVmImmVCVT, 6) \
96 ENTRY(NS_FORMAT_NVdVmImmVDupLane, 7) \
97 ENTRY(NS_FORMAT_NVdVmImmVSHLL, 8) \
98 ENTRY(NS_FORMAT_NVectorShuffle, 9) \
99 ENTRY(NS_FORMAT_NVectorShift, 10) \
100 ENTRY(NS_FORMAT_NVectorShift2, 11) \
101 ENTRY(NS_FORMAT_NVdVnVmImm, 12) \
102 ENTRY(NS_FORMAT_NVdVnVmImmVectorShift, 13) \
103 ENTRY(NS_FORMAT_NVdVnVmImmVectorExtract, 14) \
104 ENTRY(NS_FORMAT_NVdVnVmImmMulScalar, 15) \
105 ENTRY(NS_FORMAT_VTBL, 16)
107 // NEON instruction sub-format further classify the NEONFrm instruction.
108 #define ENTRY(n, v) n = v,
115 // Converts enum to const char*.
116 static const inline char *stringForNSFormat(NSFormat form) {
117 #define ENTRY(n, v) case n: return #n;
128 /// Expands on the enum definitions from ARMBaseInstrInfo.h.
129 /// They are being used by the disassembler implementation.
134 NEON_RegRdShift = 12,
135 NEON_D_BitShift = 22,
136 NEON_RegRnShift = 16,
143 /// Utility function for extracting [From, To] bits from a uint32_t.
144 static inline unsigned slice(uint32_t Bits, unsigned From, unsigned To) {
145 assert(From < 32 && To < 32 && From >= To);
146 return (Bits >> To) & ((1 << (From - To + 1)) - 1);
149 /// Utility function for setting [From, To] bits to Val for a uint32_t.
150 static inline void setSlice(uint32_t &Bits, unsigned From, unsigned To,
152 assert(From < 32 && To < 32 && From >= To);
153 uint32_t Mask = ((1 << (From - To + 1)) - 1);
154 Bits &= ~(Mask << To);
155 Bits |= (Val & Mask) << To;
158 /// Various utilities for checking the target specific flags.
160 /// A unary data processing instruction doesn't have an Rn operand.
161 static inline bool isUnaryDP(unsigned TSFlags) {
162 return (TSFlags & ARMII::UnaryDP);
165 /// This four-bit field describes the addressing mode used.
166 /// See also ARMBaseInstrInfo.h.
167 static inline unsigned getAddrMode(unsigned TSFlags) {
168 return (TSFlags & ARMII::AddrModeMask);
171 /// {IndexModePre, IndexModePost}
172 /// Only valid for load and store ops.
173 /// See also ARMBaseInstrInfo.h.
174 static inline unsigned getIndexMode(unsigned TSFlags) {
175 return (TSFlags & ARMII::IndexModeMask) >> ARMII::IndexModeShift;
178 /// Pre-/post-indexed operations define an extra $base_wb in the OutOperandList.
179 static inline bool isPrePostLdSt(unsigned TSFlags) {
180 return (TSFlags & ARMII::IndexModeMask) != 0;
183 /// AbstractARMMCBuilder - AbstractARMMCBuilder represents an interface of ARM
184 /// MCInst builder that knows how to build up the MCOperand list.
185 class AbstractARMMCBuilder {
187 /// Build - Build the MCInst fully and return true. Return false if any
189 virtual bool Build(MCInst &MI, uint32_t insn) { return false; }
192 /// ARMDisassemblyAlgorithm - ARMDisassemblyAlgorithm represents an interface of
193 /// ARM disassembly algorithm that relies on the entries of target operand info,
194 /// among other things, to solve the problem of disassembling an ARM machine
196 class ARMDisassemblyAlgorithm {
198 /// Return true if this algorithm successfully disassembles the instruction.
199 /// NumOpsAdded is updated to reflect the number of operands added by the
200 /// algorithm. NumOpsAdded may be less than NumOps, in which case, there are
201 /// operands unaccounted for which need to be dealt with by the API client.
202 virtual bool Solve(MCInst& MI, unsigned Opcode, uint32_t insn,
203 unsigned short NumOps, unsigned &NumOpsAdded) const
207 /// ARMBasicMCBuilder - ARMBasicMCBuilder represents a concrete subclass of
208 /// ARMAbstractMCBuilder.
209 class ARMBasicMCBuilder : public AbstractARMMCBuilder {
213 unsigned short NumOps;
214 const ARMDisassemblyAlgorithm &Algo;
215 static unsigned ITCounter; // Possible values: 0, 1, 2, 3, 4.
216 static unsigned ITState; // A2.5.2 Consists of IT[7:5] and IT[4:0] initially.
219 ARMBasicMCBuilder(ARMBasicMCBuilder &MCB) : AbstractARMMCBuilder(),
220 Opcode(MCB.Opcode), Format(MCB.Format), NSF(MCB.NSF), NumOps(MCB.NumOps),
223 /// Opcode, Format, NSF, NumOperands, and Algo make an ARM Basic MCBuilder.
224 ARMBasicMCBuilder(unsigned opc, ARMFormat format, NSFormat NSF,
225 unsigned short num, const ARMDisassemblyAlgorithm &algo)
226 : AbstractARMMCBuilder(), Opcode(opc), Format(format), NumOps(num),
229 /// TryPredicateAndSBitModifier - TryPredicateAndSBitModifier tries to process
230 /// the possible Predicate and SBitModifier, to build the remaining MCOperand
232 static bool TryPredicateAndSBitModifier(MCInst& MI, unsigned Opcode,
233 uint32_t insn, unsigned short NumOpsRemaning);
235 /// InITBlock - InITBlock returns true if we are inside an IT block.
236 static bool InITBlock() {
237 return ITCounter > 0;
240 /// Build - Build delegates to BuildIt to perform the heavy liftling. After
241 /// that, it invokes RunBuildAfterHook where some housekeepings can be done.
242 virtual bool Build(MCInst &MI, uint32_t insn) {
243 bool Status = BuildIt(MI, insn);
244 return RunBuildAfterHook(Status, MI, insn);
247 /// BuildIt - BuildIt performs the build step for this ARM Basic MC Builder.
248 /// The general idea is to set the Opcode for the MCInst, followed by adding
249 /// the appropriate MCOperands to the MCInst. ARM Basic MC Builder delegates
250 /// to the Algo (ARM Disassemble Algorithm) object to perform Format-specific
251 /// disassembly, followed by class method TryPredicateAndSBitModifier() to do
252 /// PredicateOperand and OptionalDefOperand which follow the Dst/Src Operands.
253 virtual bool BuildIt(MCInst &MI, uint32_t insn);
255 /// RunBuildAfterHook - RunBuildAfterHook performs operations deemed necessary
256 /// after BuildIt is finished.
257 virtual bool RunBuildAfterHook(bool Status, MCInst &MI, uint32_t insn);
260 /// Get condition of the current IT instruction.
261 static unsigned GetITCond() {
262 return slice(ITState, 7, 4);
266 static void InitITState(unsigned short bits7_0) {
270 /// Update ITState if necessary.
271 static void UpdateITState() {
277 unsigned short NewITState4_0 = slice(ITState, 4, 0) << 1;
278 setSlice(ITState, 4, 0, NewITState4_0);
283 /// ARMMCBuilderFactory - ARMMCBuilderFactory represents the factory class that
284 /// vends out ARMAbstractMCBuilder instances through its class method.
285 class ARMMCBuilderFactory {
287 ARMMCBuilderFactory(); // DO NOT IMPLEMENT.
290 /// CreateMCBuilder - Return an AbstractARMMCBuilder that can build up the MC
291 /// infrastructure of an MCInst given the Opcode and Format of the instr.
292 /// Return NULL if it fails to create/return a proper builder. API clients
293 /// are responsible for freeing up of the allocated memory. Cacheing can be
294 /// performed by the API clients to improve performance.
295 static AbstractARMMCBuilder *CreateMCBuilder(unsigned Opcode,
296 ARMFormat Format, NSFormat NSF);