1 //===- AArch64AddressingModes.h - AArch64 Addressing Modes ------*- 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 the AArch64 addressing mode implementation stuff.
11 //
12 //===----------------------------------------------------------------------===//
13 
14 #ifndef CS_AARCH64_ADDRESSINGMODES_H
15 #define CS_AARCH64_ADDRESSINGMODES_H
16 
17 /* Capstone Disassembly Engine */
18 /* By Nguyen Anh Quynh <aquynh@gmail.com>, 2013-2015 */
19 
20 #include "../../MathExtras.h"
21 
22 /// AArch64_AM - AArch64 Addressing Mode Stuff
23 
24 //===----------------------------------------------------------------------===//
25 // Shifts
26 //
27 
28 typedef enum AArch64_AM_ShiftExtendType {
29 	AArch64_AM_InvalidShiftExtend = -1,
30 	AArch64_AM_LSL = 0,
31 	AArch64_AM_LSR,
32 	AArch64_AM_ASR,
33 	AArch64_AM_ROR,
34 	AArch64_AM_MSL,
35 
36 	AArch64_AM_UXTB,
37 	AArch64_AM_UXTH,
38 	AArch64_AM_UXTW,
39 	AArch64_AM_UXTX,
40 
41 	AArch64_AM_SXTB,
42 	AArch64_AM_SXTH,
43 	AArch64_AM_SXTW,
44 	AArch64_AM_SXTX,
45 } AArch64_AM_ShiftExtendType;
46 
47 /// getShiftName - Get the string encoding for the shift type.
AArch64_AM_getShiftExtendName(AArch64_AM_ShiftExtendType ST)48 static inline const char *AArch64_AM_getShiftExtendName(AArch64_AM_ShiftExtendType ST)
49 {
50 	switch (ST) {
51 		default: return NULL; // never reach
52 		case AArch64_AM_LSL: return "lsl";
53 		case AArch64_AM_LSR: return "lsr";
54 		case AArch64_AM_ASR: return "asr";
55 		case AArch64_AM_ROR: return "ror";
56 		case AArch64_AM_MSL: return "msl";
57 		case AArch64_AM_UXTB: return "uxtb";
58 		case AArch64_AM_UXTH: return "uxth";
59 		case AArch64_AM_UXTW: return "uxtw";
60 		case AArch64_AM_UXTX: return "uxtx";
61 		case AArch64_AM_SXTB: return "sxtb";
62 		case AArch64_AM_SXTH: return "sxth";
63 		case AArch64_AM_SXTW: return "sxtw";
64 		case AArch64_AM_SXTX: return "sxtx";
65 	}
66 }
67 
68 /// getShiftType - Extract the shift type.
AArch64_AM_getShiftType(unsigned Imm)69 static inline AArch64_AM_ShiftExtendType AArch64_AM_getShiftType(unsigned Imm)
70 {
71 	switch ((Imm >> 6) & 0x7) {
72 		default: return AArch64_AM_InvalidShiftExtend;
73 		case 0: return AArch64_AM_LSL;
74 		case 1: return AArch64_AM_LSR;
75 		case 2: return AArch64_AM_ASR;
76 		case 3: return AArch64_AM_ROR;
77 		case 4: return AArch64_AM_MSL;
78 	}
79 }
80 
81 /// getShiftValue - Extract the shift value.
AArch64_AM_getShiftValue(unsigned Imm)82 static inline unsigned AArch64_AM_getShiftValue(unsigned Imm)
83 {
84 	return Imm & 0x3f;
85 }
86 
87 //===----------------------------------------------------------------------===//
88 // Extends
89 //
90 
91 /// getArithShiftValue - get the arithmetic shift value.
AArch64_AM_getArithShiftValue(unsigned Imm)92 static inline unsigned AArch64_AM_getArithShiftValue(unsigned Imm)
93 {
94 	return Imm & 0x7;
95 }
96 
97 /// getExtendType - Extract the extend type for operands of arithmetic ops.
AArch64_AM_getExtendType(unsigned Imm)98 static inline AArch64_AM_ShiftExtendType AArch64_AM_getExtendType(unsigned Imm)
99 {
100 	// assert((Imm & 0x7) == Imm && "invalid immediate!");
101 	switch (Imm) {
102 		default: // llvm_unreachable("Compiler bug!");
103 		case 0: return AArch64_AM_UXTB;
104 		case 1: return AArch64_AM_UXTH;
105 		case 2: return AArch64_AM_UXTW;
106 		case 3: return AArch64_AM_UXTX;
107 		case 4: return AArch64_AM_SXTB;
108 		case 5: return AArch64_AM_SXTH;
109 		case 6: return AArch64_AM_SXTW;
110 		case 7: return AArch64_AM_SXTX;
111 	}
112 }
113 
AArch64_AM_getArithExtendType(unsigned Imm)114 static inline AArch64_AM_ShiftExtendType AArch64_AM_getArithExtendType(unsigned Imm)
115 {
116 	return AArch64_AM_getExtendType((Imm >> 3) & 0x7);
117 }
118 
ror(uint64_t elt,unsigned size)119 static inline uint64_t ror(uint64_t elt, unsigned size)
120 {
121 	return ((elt & 1) << (size-1)) | (elt >> 1);
122 }
123 
124 /// decodeLogicalImmediate - Decode a logical immediate value in the form
125 /// "N:immr:imms" (where the immr and imms fields are each 6 bits) into the
126 /// integer value it represents with regSize bits.
AArch64_AM_decodeLogicalImmediate(uint64_t val,unsigned regSize)127 static inline uint64_t AArch64_AM_decodeLogicalImmediate(uint64_t val, unsigned regSize)
128 {
129 	// Extract the N, imms, and immr fields.
130 	unsigned N = (val >> 12) & 1;
131 	unsigned immr = (val >> 6) & 0x3f;
132 	unsigned imms = val & 0x3f;
133 	unsigned i;
134 
135 	// assert((regSize == 64 || N == 0) && "undefined logical immediate encoding");
136 	int len = 31 - countLeadingZeros((N << 6) | (~imms & 0x3f));
137 	// assert(len >= 0 && "undefined logical immediate encoding");
138 	unsigned size = (1 << len);
139 	unsigned R = immr & (size - 1);
140 	unsigned S = imms & (size - 1);
141 	// assert(S != size - 1 && "undefined logical immediate encoding");
142 	uint64_t pattern = (1ULL << (S + 1)) - 1;
143 	for (i = 0; i < R; ++i)
144 		pattern = ror(pattern, size);
145 
146 	// Replicate the pattern to fill the regSize.
147 	while (size != regSize) {
148 		pattern |= (pattern << size);
149 		size *= 2;
150 	}
151 
152 	return pattern;
153 }
154 
155 /// isValidDecodeLogicalImmediate - Check to see if the logical immediate value
156 /// in the form "N:immr:imms" (where the immr and imms fields are each 6 bits)
157 /// is a valid encoding for an integer value with regSize bits.
AArch64_AM_isValidDecodeLogicalImmediate(uint64_t val,unsigned regSize)158 static inline bool AArch64_AM_isValidDecodeLogicalImmediate(uint64_t val, unsigned regSize)
159 {
160 	unsigned size;
161 	unsigned S;
162 	int len;
163 	// Extract the N and imms fields needed for checking.
164 	unsigned N = (val >> 12) & 1;
165 	unsigned imms = val & 0x3f;
166 
167 	if (regSize == 32 && N != 0) // undefined logical immediate encoding
168 		return false;
169 	len = 31 - countLeadingZeros((N << 6) | (~imms & 0x3f));
170 	if (len < 0) // undefined logical immediate encoding
171 		return false;
172 	size = (1 << len);
173 	S = imms & (size - 1);
174 	if (S == size - 1) // undefined logical immediate encoding
175 		return false;
176 
177 	return true;
178 }
179 
180 //===----------------------------------------------------------------------===//
181 // Floating-point Immediates
182 //
AArch64_AM_getFPImmFloat(unsigned Imm)183 static inline float AArch64_AM_getFPImmFloat(unsigned Imm)
184 {
185 	// We expect an 8-bit binary encoding of a floating-point number here.
186 	union {
187 		uint32_t I;
188 		float F;
189 	} FPUnion;
190 
191 	uint8_t Sign = (Imm >> 7) & 0x1;
192 	uint8_t Exp = (Imm >> 4) & 0x7;
193 	uint8_t Mantissa = Imm & 0xf;
194 
195 	//   8-bit FP    iEEEE Float Encoding
196 	//   abcd efgh   aBbbbbbc defgh000 00000000 00000000
197 	//
198 	// where B = NOT(b);
199 
200 	FPUnion.I = 0;
201 	FPUnion.I |= ((uint32_t)Sign) << 31;
202 	FPUnion.I |= ((Exp & 0x4) != 0 ? 0 : 1) << 30;
203 	FPUnion.I |= ((Exp & 0x4) != 0 ? 0x1f : 0) << 25;
204 	FPUnion.I |= (Exp & 0x3) << 23;
205 	FPUnion.I |= Mantissa << 19;
206 
207 	return FPUnion.F;
208 }
209 
210 //===--------------------------------------------------------------------===//
211 // AdvSIMD Modified Immediates
212 //===--------------------------------------------------------------------===//
213 
AArch64_AM_decodeAdvSIMDModImmType10(uint8_t Imm)214 static inline uint64_t AArch64_AM_decodeAdvSIMDModImmType10(uint8_t Imm)
215 {
216 	static const uint32_t lookup[16] = {
217 		0x00000000, 0x000000ff, 0x0000ff00, 0x0000ffff,
218 		0x00ff0000, 0x00ff00ff, 0x00ffff00, 0x00ffffff,
219 		0xff000000, 0xff0000ff, 0xff00ff00, 0xff00ffff,
220 		0xffff0000, 0xffff00ff, 0xffffff00, 0xffffffff
221         };
222 	return lookup[Imm & 0x0f] | ((uint64_t)lookup[Imm >> 4] << 32);
223 }
224 
225 #endif
226