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