23b309cd4f481e9a629e058168a6be669234c4db
[oota-llvm.git] / lib / Target / ARM / Disassembler / ARMDisassemblerCore.h
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, Builder Factory,
17 // as well as the Algorithm 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/Target/TargetInstrInfo.h"
26 #include "ARMInstrInfo.h"
27
28 namespace llvm {
29
30 class ARMUtils {
31 public:
32   static const char *OpcodeName(unsigned Opcode);
33 };
34
35 #define ARM_FORMATS                   \
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)
67
68 // ARM instruction format specifies the encoding used by the instruction.
69 #define ENTRY(n, v) n = v,
70 typedef enum {
71   ARM_FORMATS
72   ARM_FORMAT_NA
73 } ARMFormat;
74 #undef ENTRY
75
76 // Converts enum to const char*.
77 static const inline char *stringForARMFormat(ARMFormat form) {
78 #define ENTRY(n, v) case n: return #n;
79   switch(form) {
80     ARM_FORMATS
81   case ARM_FORMAT_NA:
82   default:
83     return "";
84   }
85 #undef ENTRY
86 }
87
88 #define NS_FORMATS                              \
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)
106
107 // NEON instruction sub-format further classify the NEONFrm instruction.
108 #define ENTRY(n, v) n = v,
109 typedef enum {
110   NS_FORMATS
111   NS_FORMAT_NA
112 } NSFormat;
113 #undef ENTRY
114
115 // Converts enum to const char*.
116 static const inline char *stringForNSFormat(NSFormat form) {
117 #define ENTRY(n, v) case n: return #n;
118   switch(form) {
119     NS_FORMATS
120   case NS_FORMAT_NA:
121     return "NA";
122   default:
123     return "";
124   }
125 #undef ENTRY
126 }
127
128 /// Expands on the enum definitions from ARMBaseInstrInfo.h.
129 /// They are being used by the disassembler implementation.
130 namespace ARMII {
131   enum {
132     NEONRegMask = 15,
133     GPRRegMask = 15,
134     NEON_RegRdShift = 12,
135     NEON_D_BitShift = 22,
136     NEON_RegRnShift = 16,
137     NEON_N_BitShift = 7,
138     NEON_RegRmShift = 0,
139     NEON_M_BitShift = 5
140   };
141 }
142
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);
147 }
148
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,
151                             uint32_t Val) {
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;
156 }
157
158 /// Various utilities for checking the target specific flags.
159
160 /// A unary data processing instruction doesn't have an Rn operand.
161 static inline bool isUnaryDP(unsigned TSFlags) {
162   return (TSFlags & ARMII::UnaryDP);
163 }
164
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);
169 }
170
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;
176 }
177
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;
181 }
182
183 /// AbstractARMMCBuilder - AbstractARMMCBuilder represents an interface of ARM
184 /// MCInst builder that knows how to build up the MCOperand list.
185 class AbstractARMMCBuilder {
186 public:
187   /// Build - Build the MCInst fully and return true.  Return false if any
188   /// failure occurs.
189   virtual bool Build(MCInst &MI, uint32_t insn) { return false; }
190 };
191
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
195 /// instruction.
196 class ARMDisassemblyAlgorithm {
197 public:
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
204     = 0;
205 };
206
207 /// ARMBasicMCBuilder - ARMBasicMCBuilder represents a concrete subclass of
208 /// ARMAbstractMCBuilder.
209 class ARMBasicMCBuilder : public AbstractARMMCBuilder {
210   unsigned Opcode;
211   ARMFormat Format;
212   NSFormat NSF;
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.
217
218 public:
219   ARMBasicMCBuilder(ARMBasicMCBuilder &MCB) : AbstractARMMCBuilder(),
220     Opcode(MCB.Opcode), Format(MCB.Format), NSF(MCB.NSF), NumOps(MCB.NumOps),
221     Algo(MCB.Algo) {}
222
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),
227       Algo(algo) {}
228
229   /// TryPredicateAndSBitModifier - TryPredicateAndSBitModifier tries to process
230   /// the possible Predicate and SBitModifier, to build the remaining MCOperand
231   /// constituents.
232   static bool TryPredicateAndSBitModifier(MCInst& MI, unsigned Opcode,
233       uint32_t insn, unsigned short NumOpsRemaning);
234
235   /// InITBlock - InITBlock returns true if we are inside an IT block.
236   static bool InITBlock() {
237     return ITCounter > 0;
238   }
239
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);
245   }
246
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);
254
255   /// RunBuildAfterHook - RunBuildAfterHook performs operations deemed necessary
256   /// after BuildIt is finished.
257   virtual bool RunBuildAfterHook(bool Status, MCInst &MI, uint32_t insn);
258
259 private:
260   /// Get condition of the current IT instruction.
261   static unsigned GetITCond() {
262     return slice(ITState, 7, 4);
263   }
264
265   /// Init ITState.
266   static void InitITState(unsigned short bits7_0) {
267     ITState = bits7_0;
268   }
269
270   /// Update ITState if necessary.
271   static void UpdateITState() {
272     assert(ITCounter);
273     --ITCounter;
274     if (ITCounter == 0)
275       ITState = 0;
276     else {
277       unsigned short NewITState4_0 = slice(ITState, 4, 0) << 1;
278       setSlice(ITState, 4, 0, NewITState4_0);
279     }
280   }
281 };
282
283 /// ARMMCBuilderFactory - ARMMCBuilderFactory represents the factory class that
284 /// vends out ARMAbstractMCBuilder instances through its class method.
285 class ARMMCBuilderFactory {
286 private:
287   ARMMCBuilderFactory(); // DO NOT IMPLEMENT.
288
289 public:
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);
297 };
298
299 } // namespace llvm
300
301 #endif