1 //===-- ARMBaseInfo.h - Top level definitions for ARM -------- --*- 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 contains small standalone helper functions and enum definitions for
11 // the ARM target useful for the compiler back-end and the MC libraries.
12 // As such, it deliberately does not include references to LLVM core
13 // code gen types, passes, etc..
14 //
15 //===----------------------------------------------------------------------===//
16 
17 /* Capstone Disassembly Engine */
18 /* By Nguyen Anh Quynh <aquynh@gmail.com>, 2013-2015 */
19 
20 #ifndef CS_ARMBASEINFO_H
21 #define CS_ARMBASEINFO_H
22 
23 #include "capstone/arm.h"
24 
25 // Defines symbolic names for ARM registers.  This defines a mapping from
26 // register name to register number.
27 //
28 #define GET_REGINFO_ENUM
29 #include "ARMGenRegisterInfo.inc"
30 
31 // Enums corresponding to ARM condition codes
32 // The CondCodes constants map directly to the 4-bit encoding of the
33 // condition field for predicated instructions.
34 typedef enum ARMCC_CondCodes { // Meaning (integer)          Meaning (floating-point)
35 	ARMCC_EQ,            // Equal                      Equal
36 	ARMCC_NE,            // Not equal                  Not equal, or unordered
37 	ARMCC_HS,            // Carry set                  >, ==, or unordered
38 	ARMCC_LO,            // Carry clear                Less than
39 	ARMCC_MI,            // Minus, negative            Less than
40 	ARMCC_PL,            // Plus, positive or zero     >, ==, or unordered
41 	ARMCC_VS,            // Overflow                   Unordered
42 	ARMCC_VC,            // No overflow                Not unordered
43 	ARMCC_HI,            // Unsigned higher            Greater than, or unordered
44 	ARMCC_LS,            // Unsigned lower or same     Less than or equal
45 	ARMCC_GE,            // Greater than or equal      Greater than or equal
46 	ARMCC_LT,            // Less than                  Less than, or unordered
47 	ARMCC_GT,            // Greater than               Greater than
48 	ARMCC_LE,            // Less than or equal         <, ==, or unordered
49 	ARMCC_AL             // Always (unconditional)     Always (unconditional)
50 } ARMCC_CondCodes;
51 
ARMCC_getOppositeCondition(ARMCC_CondCodes CC)52 inline static ARMCC_CondCodes ARMCC_getOppositeCondition(ARMCC_CondCodes CC)
53 {
54 	switch (CC) {
55 		case ARMCC_EQ: return ARMCC_NE;
56 		case ARMCC_NE: return ARMCC_EQ;
57 		case ARMCC_HS: return ARMCC_LO;
58 		case ARMCC_LO: return ARMCC_HS;
59 		case ARMCC_MI: return ARMCC_PL;
60 		case ARMCC_PL: return ARMCC_MI;
61 		case ARMCC_VS: return ARMCC_VC;
62 		case ARMCC_VC: return ARMCC_VS;
63 		case ARMCC_HI: return ARMCC_LS;
64 		case ARMCC_LS: return ARMCC_HI;
65 		case ARMCC_GE: return ARMCC_LT;
66 		case ARMCC_LT: return ARMCC_GE;
67 		case ARMCC_GT: return ARMCC_LE;
68 		case ARMCC_LE: return ARMCC_GT;
69 		default: return ARMCC_AL;
70 	}
71 }
72 
ARMCC_ARMCondCodeToString(ARMCC_CondCodes CC)73 inline static const char *ARMCC_ARMCondCodeToString(ARMCC_CondCodes CC)
74 {
75 	switch (CC) {
76 		case ARMCC_EQ:  return "eq";
77 		case ARMCC_NE:  return "ne";
78 		case ARMCC_HS:  return "hs";
79 		case ARMCC_LO:  return "lo";
80 		case ARMCC_MI:  return "mi";
81 		case ARMCC_PL:  return "pl";
82 		case ARMCC_VS:  return "vs";
83 		case ARMCC_VC:  return "vc";
84 		case ARMCC_HI:  return "hi";
85 		case ARMCC_LS:  return "ls";
86 		case ARMCC_GE:  return "ge";
87 		case ARMCC_LT:  return "lt";
88 		case ARMCC_GT:  return "gt";
89 		case ARMCC_LE:  return "le";
90 		case ARMCC_AL:  return "al";
91 		default: return "";
92 	}
93 }
94 
ARM_PROC_IFlagsToString(unsigned val)95 inline static const char *ARM_PROC_IFlagsToString(unsigned val)
96 {
97 	switch (val) {
98 		case ARM_CPSFLAG_F: return "f";
99 		case ARM_CPSFLAG_I: return "i";
100 		case ARM_CPSFLAG_A: return "a";
101 		default: return "";
102 	}
103 }
104 
ARM_PROC_IModToString(unsigned val)105 inline static const char *ARM_PROC_IModToString(unsigned val)
106 {
107 	switch (val) {
108 		case ARM_CPSMODE_IE: return "ie";
109 		case ARM_CPSMODE_ID: return "id";
110 		default: return "";
111 	}
112 }
113 
ARM_MB_MemBOptToString(unsigned val,bool HasV8)114 inline static const char *ARM_MB_MemBOptToString(unsigned val, bool HasV8)
115 {
116 	switch (val) {
117 		default: return "BUGBUG";
118 		case ARM_MB_SY:    return "sy";
119 		case ARM_MB_ST:    return "st";
120 		case ARM_MB_LD: return HasV8 ? "ld" : "#0xd";
121 		case ARM_MB_RESERVED_12: return "#0xc";
122 		case ARM_MB_ISH:   return "ish";
123 		case ARM_MB_ISHST: return "ishst";
124 		case ARM_MB_ISHLD: return HasV8 ?  "ishld" : "#0x9";
125 		case ARM_MB_RESERVED_8: return "#0x8";
126 		case ARM_MB_NSH:   return "nsh";
127 		case ARM_MB_NSHST: return "nshst";
128 		case ARM_MB_NSHLD: return HasV8 ? "nshld" : "#0x5";
129 		case ARM_MB_RESERVED_4: return "#0x4";
130 		case ARM_MB_OSH:   return "osh";
131 		case ARM_MB_OSHST: return "oshst";
132 		case ARM_MB_OSHLD: return HasV8 ? "oshld" : "#0x1";
133 		case ARM_MB_RESERVED_0: return "#0x0";
134 	}
135 }
136 
137 enum ARM_ISB_InstSyncBOpt {
138     ARM_ISB_RESERVED_0 = 0,
139     ARM_ISB_RESERVED_1 = 1,
140     ARM_ISB_RESERVED_2 = 2,
141     ARM_ISB_RESERVED_3 = 3,
142     ARM_ISB_RESERVED_4 = 4,
143     ARM_ISB_RESERVED_5 = 5,
144     ARM_ISB_RESERVED_6 = 6,
145     ARM_ISB_RESERVED_7 = 7,
146     ARM_ISB_RESERVED_8 = 8,
147     ARM_ISB_RESERVED_9 = 9,
148     ARM_ISB_RESERVED_10 = 10,
149     ARM_ISB_RESERVED_11 = 11,
150     ARM_ISB_RESERVED_12 = 12,
151     ARM_ISB_RESERVED_13 = 13,
152     ARM_ISB_RESERVED_14 = 14,
153     ARM_ISB_SY = 15
154 };
155 
ARM_ISB_InstSyncBOptToString(unsigned val)156 inline static const char *ARM_ISB_InstSyncBOptToString(unsigned val)
157 {
158 	switch (val) {
159 		default: // never reach
160 		case ARM_ISB_RESERVED_0:  return "#0x0";
161 		case ARM_ISB_RESERVED_1:  return "#0x1";
162 		case ARM_ISB_RESERVED_2:  return "#0x2";
163 		case ARM_ISB_RESERVED_3:  return "#0x3";
164 		case ARM_ISB_RESERVED_4:  return "#0x4";
165 		case ARM_ISB_RESERVED_5:  return "#0x5";
166 		case ARM_ISB_RESERVED_6:  return "#0x6";
167 		case ARM_ISB_RESERVED_7:  return "#0x7";
168 		case ARM_ISB_RESERVED_8:  return "#0x8";
169 		case ARM_ISB_RESERVED_9:  return "#0x9";
170 		case ARM_ISB_RESERVED_10: return "#0xa";
171 		case ARM_ISB_RESERVED_11: return "#0xb";
172 		case ARM_ISB_RESERVED_12: return "#0xc";
173 		case ARM_ISB_RESERVED_13: return "#0xd";
174 		case ARM_ISB_RESERVED_14: return "#0xe";
175 		case ARM_ISB_SY:          return "sy";
176 	}
177 }
178 
179 /// isARMLowRegister - Returns true if the register is a low register (r0-r7).
180 ///
isARMLowRegister(unsigned Reg)181 static inline bool isARMLowRegister(unsigned Reg)
182 {
183 	//using namespace ARM;
184 	switch (Reg) {
185 		case ARM_R0:  case ARM_R1:  case ARM_R2:  case ARM_R3:
186 		case ARM_R4:  case ARM_R5:  case ARM_R6:  case ARM_R7:
187 			return true;
188 		default:
189 			return false;
190 	}
191 }
192 
193 /// ARMII - This namespace holds all of the target specific flags that
194 /// instruction info tracks.
195 ///
196 /// ARM Index Modes
197 enum ARMII_IndexMode {
198 	ARMII_IndexModeNone  = 0,
199 	ARMII_IndexModePre   = 1,
200 	ARMII_IndexModePost  = 2,
201 	ARMII_IndexModeUpd   = 3
202 };
203 
204 /// ARM Addressing Modes
205 typedef enum ARMII_AddrMode {
206 	ARMII_AddrModeNone    = 0,
207 	ARMII_AddrMode1       = 1,
208 	ARMII_AddrMode2       = 2,
209 	ARMII_AddrMode3       = 3,
210 	ARMII_AddrMode4       = 4,
211 	ARMII_AddrMode5       = 5,
212 	ARMII_AddrMode6       = 6,
213 	ARMII_AddrModeT1_1    = 7,
214 	ARMII_AddrModeT1_2    = 8,
215 	ARMII_AddrModeT1_4    = 9,
216 	ARMII_AddrModeT1_s    = 10, // i8 * 4 for pc and sp relative data
217 	ARMII_AddrModeT2_i12  = 11,
218 	ARMII_AddrModeT2_i8   = 12,
219 	ARMII_AddrModeT2_so   = 13,
220 	ARMII_AddrModeT2_pc   = 14, // +/- i12 for pc relative data
221 	ARMII_AddrModeT2_i8s4 = 15, // i8 * 4
222 	ARMII_AddrMode_i12    = 16
223 } ARMII_AddrMode;
224 
ARMII_AddrModeToString(ARMII_AddrMode addrmode)225 inline static const char *ARMII_AddrModeToString(ARMII_AddrMode addrmode)
226 {
227 	switch (addrmode) {
228 		case ARMII_AddrModeNone:    return "AddrModeNone";
229 		case ARMII_AddrMode1:       return "AddrMode1";
230 		case ARMII_AddrMode2:       return "AddrMode2";
231 		case ARMII_AddrMode3:       return "AddrMode3";
232 		case ARMII_AddrMode4:       return "AddrMode4";
233 		case ARMII_AddrMode5:       return "AddrMode5";
234 		case ARMII_AddrMode6:       return "AddrMode6";
235 		case ARMII_AddrModeT1_1:    return "AddrModeT1_1";
236 		case ARMII_AddrModeT1_2:    return "AddrModeT1_2";
237 		case ARMII_AddrModeT1_4:    return "AddrModeT1_4";
238 		case ARMII_AddrModeT1_s:    return "AddrModeT1_s";
239 		case ARMII_AddrModeT2_i12:  return "AddrModeT2_i12";
240 		case ARMII_AddrModeT2_i8:   return "AddrModeT2_i8";
241 		case ARMII_AddrModeT2_so:   return "AddrModeT2_so";
242 		case ARMII_AddrModeT2_pc:   return "AddrModeT2_pc";
243 		case ARMII_AddrModeT2_i8s4: return "AddrModeT2_i8s4";
244 		case ARMII_AddrMode_i12:    return "AddrMode_i12";
245 	}
246 }
247 
248 /// Target Operand Flag enum.
249 enum ARMII_TOF {
250 	//===------------------------------------------------------------------===//
251 	// ARM Specific MachineOperand flags.
252 
253 	ARMII_MO_NO_FLAG,
254 
255 	/// MO_LO16 - On a symbol operand, this represents a relocation containing
256 	/// lower 16 bit of the address. Used only via movw instruction.
257 	ARMII_MO_LO16,
258 
259 	/// MO_HI16 - On a symbol operand, this represents a relocation containing
260 	/// higher 16 bit of the address. Used only via movt instruction.
261 	ARMII_MO_HI16,
262 
263 	/// MO_LO16_NONLAZY - On a symbol operand "FOO", this represents a
264 	/// relocation containing lower 16 bit of the non-lazy-ptr indirect symbol,
265 	/// i.e. "FOO$non_lazy_ptr".
266 	/// Used only via movw instruction.
267 	ARMII_MO_LO16_NONLAZY,
268 
269 	/// MO_HI16_NONLAZY - On a symbol operand "FOO", this represents a
270 	/// relocation containing lower 16 bit of the non-lazy-ptr indirect symbol,
271 	/// i.e. "FOO$non_lazy_ptr". Used only via movt instruction.
272 	ARMII_MO_HI16_NONLAZY,
273 
274 	/// MO_LO16_NONLAZY_PIC - On a symbol operand "FOO", this represents a
275 	/// relocation containing lower 16 bit of the PC relative address of the
276 	/// non-lazy-ptr indirect symbol, i.e. "FOO$non_lazy_ptr - LABEL".
277 	/// Used only via movw instruction.
278 	ARMII_MO_LO16_NONLAZY_PIC,
279 
280 	/// MO_HI16_NONLAZY_PIC - On a symbol operand "FOO", this represents a
281 	/// relocation containing lower 16 bit of the PC relative address of the
282 	/// non-lazy-ptr indirect symbol, i.e. "FOO$non_lazy_ptr - LABEL".
283 	/// Used only via movt instruction.
284 	ARMII_MO_HI16_NONLAZY_PIC,
285 
286 	/// MO_PLT - On a symbol operand, this represents an ELF PLT reference on a
287 	/// call operand.
288 	ARMII_MO_PLT
289 };
290 
291 enum {
292 	//===------------------------------------------------------------------===//
293 	// Instruction Flags.
294 
295 	//===------------------------------------------------------------------===//
296 	// This four-bit field describes the addressing mode used.
297 	ARMII_AddrModeMask  = 0x1f, // The AddrMode enums are declared in ARMBaseInfo.h
298 
299 	// IndexMode - Unindex, pre-indexed, or post-indexed are valid for load
300 	// and store ops only.  Generic "updating" flag is used for ld/st multiple.
301 	// The index mode enums are declared in ARMBaseInfo.h
302 	ARMII_IndexModeShift = 5,
303 	ARMII_IndexModeMask  = 3 << ARMII_IndexModeShift,
304 
305 	//===------------------------------------------------------------------===//
306 	// Instruction encoding formats.
307 	//
308 	ARMII_FormShift     = 7,
309 	ARMII_FormMask      = 0x3f << ARMII_FormShift,
310 
311 	// Pseudo instructions
312 	ARMII_Pseudo        = 0  << ARMII_FormShift,
313 
314 	// Multiply instructions
315 	ARMII_MulFrm        = 1  << ARMII_FormShift,
316 
317 	// Branch instructions
318 	ARMII_BrFrm         = 2  << ARMII_FormShift,
319 	ARMII_BrMiscFrm     = 3  << ARMII_FormShift,
320 
321 	// Data Processing instructions
322 	ARMII_DPFrm         = 4  << ARMII_FormShift,
323 	ARMII_DPSoRegFrm    = 5  << ARMII_FormShift,
324 
325 	// Load and Store
326 	ARMII_LdFrm         = 6  << ARMII_FormShift,
327 	ARMII_StFrm         = 7  << ARMII_FormShift,
328 	ARMII_LdMiscFrm     = 8  << ARMII_FormShift,
329 	ARMII_StMiscFrm     = 9  << ARMII_FormShift,
330 	ARMII_LdStMulFrm    = 10 << ARMII_FormShift,
331 
332 	ARMII_LdStExFrm     = 11 << ARMII_FormShift,
333 
334 	// Miscellaneous arithmetic instructions
335 	ARMII_ArithMiscFrm  = 12 << ARMII_FormShift,
336 	ARMII_SatFrm        = 13 << ARMII_FormShift,
337 
338 	// Extend instructions
339 	ARMII_ExtFrm        = 14 << ARMII_FormShift,
340 
341 	// VFP formats
342 	ARMII_VFPUnaryFrm   = 15 << ARMII_FormShift,
343 	ARMII_VFPBinaryFrm  = 16 << ARMII_FormShift,
344 	ARMII_VFPConv1Frm   = 17 << ARMII_FormShift,
345 	ARMII_VFPConv2Frm   = 18 << ARMII_FormShift,
346 	ARMII_VFPConv3Frm   = 19 << ARMII_FormShift,
347 	ARMII_VFPConv4Frm   = 20 << ARMII_FormShift,
348 	ARMII_VFPConv5Frm   = 21 << ARMII_FormShift,
349 	ARMII_VFPLdStFrm    = 22 << ARMII_FormShift,
350 	ARMII_VFPLdStMulFrm = 23 << ARMII_FormShift,
351 	ARMII_VFPMiscFrm    = 24 << ARMII_FormShift,
352 
353 	// Thumb format
354 	ARMII_ThumbFrm      = 25 << ARMII_FormShift,
355 
356 	// Miscelleaneous format
357 	ARMII_MiscFrm       = 26 << ARMII_FormShift,
358 
359 	// NEON formats
360 	ARMII_NGetLnFrm     = 27 << ARMII_FormShift,
361 	ARMII_NSetLnFrm     = 28 << ARMII_FormShift,
362 	ARMII_NDupFrm       = 29 << ARMII_FormShift,
363 	ARMII_NLdStFrm      = 30 << ARMII_FormShift,
364 	ARMII_N1RegModImmFrm= 31 << ARMII_FormShift,
365 	ARMII_N2RegFrm      = 32 << ARMII_FormShift,
366 	ARMII_NVCVTFrm      = 33 << ARMII_FormShift,
367 	ARMII_NVDupLnFrm    = 34 << ARMII_FormShift,
368 	ARMII_N2RegVShLFrm  = 35 << ARMII_FormShift,
369 	ARMII_N2RegVShRFrm  = 36 << ARMII_FormShift,
370 	ARMII_N3RegFrm      = 37 << ARMII_FormShift,
371 	ARMII_N3RegVShFrm   = 38 << ARMII_FormShift,
372 	ARMII_NVExtFrm      = 39 << ARMII_FormShift,
373 	ARMII_NVMulSLFrm    = 40 << ARMII_FormShift,
374 	ARMII_NVTBLFrm      = 41 << ARMII_FormShift,
375 
376 	//===------------------------------------------------------------------===//
377 	// Misc flags.
378 
379 	// UnaryDP - Indicates this is a unary data processing instruction, i.e.
380 	// it doesn't have a Rn operand.
381 	ARMII_UnaryDP       = 1 << 13,
382 
383 	// Xform16Bit - Indicates this Thumb2 instruction may be transformed into
384 	// a 16-bit Thumb instruction if certain conditions are met.
385 	ARMII_Xform16Bit    = 1 << 14,
386 
387 	// ThumbArithFlagSetting - The instruction is a 16-bit flag setting Thumb
388 	// instruction. Used by the parser to determine whether to require the 'S'
389 	// suffix on the mnemonic (when not in an IT block) or preclude it (when
390 	// in an IT block).
391 	ARMII_ThumbArithFlagSetting = 1 << 18,
392 
393 	//===------------------------------------------------------------------===//
394 	// Code domain.
395 	ARMII_DomainShift   = 15,
396 	ARMII_DomainMask    = 7 << ARMII_DomainShift,
397 	ARMII_DomainGeneral = 0 << ARMII_DomainShift,
398 	ARMII_DomainVFP     = 1 << ARMII_DomainShift,
399 	ARMII_DomainNEON    = 2 << ARMII_DomainShift,
400 	ARMII_DomainNEONA8  = 4 << ARMII_DomainShift,
401 
402 	//===------------------------------------------------------------------===//
403 	// Field shifts - such shifts are used to set field while generating
404 	// machine instructions.
405 	//
406 	// FIXME: This list will need adjusting/fixing as the MC code emitter
407 	// takes shape and the ARMCodeEmitter.cpp bits go away.
408 	ARMII_ShiftTypeShift = 4,
409 
410 	ARMII_M_BitShift     = 5,
411 	ARMII_ShiftImmShift  = 5,
412 	ARMII_ShiftShift     = 7,
413 	ARMII_N_BitShift     = 7,
414 	ARMII_ImmHiShift     = 8,
415 	ARMII_SoRotImmShift  = 8,
416 	ARMII_RegRsShift     = 8,
417 	ARMII_ExtRotImmShift = 10,
418 	ARMII_RegRdLoShift   = 12,
419 	ARMII_RegRdShift     = 12,
420 	ARMII_RegRdHiShift   = 16,
421 	ARMII_RegRnShift     = 16,
422 	ARMII_S_BitShift     = 20,
423 	ARMII_W_BitShift     = 21,
424 	ARMII_AM3_I_BitShift = 22,
425 	ARMII_D_BitShift     = 22,
426 	ARMII_U_BitShift     = 23,
427 	ARMII_P_BitShift     = 24,
428 	ARMII_I_BitShift     = 25,
429 	ARMII_CondShift      = 28
430 };
431 
432 #endif
433