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