Home | History | Annotate | Download | only in AArch64
      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 (at) gmail.com>, 2014 */
     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.
     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.
     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.
     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.
     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.
     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 
    114 static inline AArch64_AM_ShiftExtendType AArch64_AM_getArithExtendType(unsigned Imm)
    115 {
    116 	return AArch64_AM_getExtendType((Imm >> 3) & 0x7);
    117 }
    118 
    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.
    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.
    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 //
    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 |= 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 
    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