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