xref: /aosp_15_r20/external/capstone/arch/AArch64/AArch64AddressingModes.h (revision 9a0e4156d50a75a99ec4f1653a0e9602a5d45c18)
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