AArch64AddressingModes.h revision 274955
1274955Ssvnmir//===- AArch64AddressingModes.h - AArch64 Addressing Modes ------*- C++ -*-===// 2274955Ssvnmir// 3274955Ssvnmir// The LLVM Compiler Infrastructure 4274955Ssvnmir// 5274955Ssvnmir// This file is distributed under the University of Illinois Open Source 6274955Ssvnmir// License. See LICENSE.TXT for details. 7274955Ssvnmir// 8274955Ssvnmir//===----------------------------------------------------------------------===// 9274955Ssvnmir// 10274955Ssvnmir// This file contains the AArch64 addressing mode implementation stuff. 11274955Ssvnmir// 12274955Ssvnmir//===----------------------------------------------------------------------===// 13274955Ssvnmir 14274955Ssvnmir#ifndef LLVM_TARGET_AArch64_AArch64ADDRESSINGMODES_H 15274955Ssvnmir#define LLVM_TARGET_AArch64_AArch64ADDRESSINGMODES_H 16274955Ssvnmir 17274955Ssvnmir#include "llvm/ADT/APFloat.h" 18274955Ssvnmir#include "llvm/ADT/APInt.h" 19274955Ssvnmir#include "llvm/Support/ErrorHandling.h" 20274955Ssvnmir#include "llvm/Support/MathExtras.h" 21274955Ssvnmir#include <cassert> 22274955Ssvnmir 23274955Ssvnmirnamespace llvm { 24274955Ssvnmir 25274955Ssvnmir/// AArch64_AM - AArch64 Addressing Mode Stuff 26274955Ssvnmirnamespace AArch64_AM { 27274955Ssvnmir 28274955Ssvnmir//===----------------------------------------------------------------------===// 29274955Ssvnmir// Shifts 30274955Ssvnmir// 31274955Ssvnmir 32274955Ssvnmirenum ShiftExtendType { 33274955Ssvnmir InvalidShiftExtend = -1, 34274955Ssvnmir LSL = 0, 35274955Ssvnmir LSR, 36274955Ssvnmir ASR, 37274955Ssvnmir ROR, 38274955Ssvnmir MSL, 39274955Ssvnmir 40274955Ssvnmir UXTB, 41274955Ssvnmir UXTH, 42274955Ssvnmir UXTW, 43274955Ssvnmir UXTX, 44274955Ssvnmir 45274955Ssvnmir SXTB, 46274955Ssvnmir SXTH, 47274955Ssvnmir SXTW, 48274955Ssvnmir SXTX, 49274955Ssvnmir}; 50274955Ssvnmir 51274955Ssvnmir/// getShiftName - Get the string encoding for the shift type. 52274955Ssvnmirstatic inline const char *getShiftExtendName(AArch64_AM::ShiftExtendType ST) { 53274955Ssvnmir switch (ST) { 54274955Ssvnmir default: assert(false && "unhandled shift type!"); 55274955Ssvnmir case AArch64_AM::LSL: return "lsl"; 56274955Ssvnmir case AArch64_AM::LSR: return "lsr"; 57274955Ssvnmir case AArch64_AM::ASR: return "asr"; 58274955Ssvnmir case AArch64_AM::ROR: return "ror"; 59274955Ssvnmir case AArch64_AM::MSL: return "msl"; 60274955Ssvnmir case AArch64_AM::UXTB: return "uxtb"; 61274955Ssvnmir case AArch64_AM::UXTH: return "uxth"; 62274955Ssvnmir case AArch64_AM::UXTW: return "uxtw"; 63274955Ssvnmir case AArch64_AM::UXTX: return "uxtx"; 64274955Ssvnmir case AArch64_AM::SXTB: return "sxtb"; 65274955Ssvnmir case AArch64_AM::SXTH: return "sxth"; 66274955Ssvnmir case AArch64_AM::SXTW: return "sxtw"; 67274955Ssvnmir case AArch64_AM::SXTX: return "sxtx"; 68274955Ssvnmir } 69274955Ssvnmir return nullptr; 70274955Ssvnmir} 71274955Ssvnmir 72274955Ssvnmir/// getShiftType - Extract the shift type. 73274955Ssvnmirstatic inline AArch64_AM::ShiftExtendType getShiftType(unsigned Imm) { 74274955Ssvnmir switch ((Imm >> 6) & 0x7) { 75274955Ssvnmir default: return AArch64_AM::InvalidShiftExtend; 76274955Ssvnmir case 0: return AArch64_AM::LSL; 77274955Ssvnmir case 1: return AArch64_AM::LSR; 78274955Ssvnmir case 2: return AArch64_AM::ASR; 79274955Ssvnmir case 3: return AArch64_AM::ROR; 80274955Ssvnmir case 4: return AArch64_AM::MSL; 81274955Ssvnmir } 82274955Ssvnmir} 83274955Ssvnmir 84274955Ssvnmir/// getShiftValue - Extract the shift value. 85274955Ssvnmirstatic inline unsigned getShiftValue(unsigned Imm) { 86274955Ssvnmir return Imm & 0x3f; 87274955Ssvnmir} 88274955Ssvnmir 89274955Ssvnmir/// getShifterImm - Encode the shift type and amount: 90274955Ssvnmir/// imm: 6-bit shift amount 91274955Ssvnmir/// shifter: 000 ==> lsl 92274955Ssvnmir/// 001 ==> lsr 93274955Ssvnmir/// 010 ==> asr 94274955Ssvnmir/// 011 ==> ror 95274955Ssvnmir/// 100 ==> msl 96274955Ssvnmir/// {8-6} = shifter 97274955Ssvnmir/// {5-0} = imm 98274955Ssvnmirstatic inline unsigned getShifterImm(AArch64_AM::ShiftExtendType ST, 99274955Ssvnmir unsigned Imm) { 100274955Ssvnmir assert((Imm & 0x3f) == Imm && "Illegal shifted immedate value!"); 101274955Ssvnmir unsigned STEnc = 0; 102274955Ssvnmir switch (ST) { 103274955Ssvnmir default: llvm_unreachable("Invalid shift requested"); 104274955Ssvnmir case AArch64_AM::LSL: STEnc = 0; break; 105274955Ssvnmir case AArch64_AM::LSR: STEnc = 1; break; 106274955Ssvnmir case AArch64_AM::ASR: STEnc = 2; break; 107274955Ssvnmir case AArch64_AM::ROR: STEnc = 3; break; 108274955Ssvnmir case AArch64_AM::MSL: STEnc = 4; break; 109274955Ssvnmir } 110274955Ssvnmir return (STEnc << 6) | (Imm & 0x3f); 111274955Ssvnmir} 112274955Ssvnmir 113274955Ssvnmir//===----------------------------------------------------------------------===// 114274955Ssvnmir// Extends 115274955Ssvnmir// 116274955Ssvnmir 117274955Ssvnmir/// getArithShiftValue - get the arithmetic shift value. 118274955Ssvnmirstatic inline unsigned getArithShiftValue(unsigned Imm) { 119274955Ssvnmir return Imm & 0x7; 120274955Ssvnmir} 121274955Ssvnmir 122274955Ssvnmir/// getExtendType - Extract the extend type for operands of arithmetic ops. 123274955Ssvnmirstatic inline AArch64_AM::ShiftExtendType getExtendType(unsigned Imm) { 124274955Ssvnmir assert((Imm & 0x7) == Imm && "invalid immediate!"); 125274955Ssvnmir switch (Imm) { 126274955Ssvnmir default: llvm_unreachable("Compiler bug!"); 127274955Ssvnmir case 0: return AArch64_AM::UXTB; 128274955Ssvnmir case 1: return AArch64_AM::UXTH; 129274955Ssvnmir case 2: return AArch64_AM::UXTW; 130274955Ssvnmir case 3: return AArch64_AM::UXTX; 131274955Ssvnmir case 4: return AArch64_AM::SXTB; 132274955Ssvnmir case 5: return AArch64_AM::SXTH; 133274955Ssvnmir case 6: return AArch64_AM::SXTW; 134274955Ssvnmir case 7: return AArch64_AM::SXTX; 135274955Ssvnmir } 136274955Ssvnmir} 137274955Ssvnmir 138274955Ssvnmirstatic inline AArch64_AM::ShiftExtendType getArithExtendType(unsigned Imm) { 139274955Ssvnmir return getExtendType((Imm >> 3) & 0x7); 140274955Ssvnmir} 141274955Ssvnmir 142274955Ssvnmir/// Mapping from extend bits to required operation: 143274955Ssvnmir/// shifter: 000 ==> uxtb 144274955Ssvnmir/// 001 ==> uxth 145274955Ssvnmir/// 010 ==> uxtw 146274955Ssvnmir/// 011 ==> uxtx 147274955Ssvnmir/// 100 ==> sxtb 148274955Ssvnmir/// 101 ==> sxth 149274955Ssvnmir/// 110 ==> sxtw 150274955Ssvnmir/// 111 ==> sxtx 151274955Ssvnmirinline unsigned getExtendEncoding(AArch64_AM::ShiftExtendType ET) { 152274955Ssvnmir switch (ET) { 153274955Ssvnmir default: llvm_unreachable("Invalid extend type requested"); 154274955Ssvnmir case AArch64_AM::UXTB: return 0; break; 155274955Ssvnmir case AArch64_AM::UXTH: return 1; break; 156274955Ssvnmir case AArch64_AM::UXTW: return 2; break; 157274955Ssvnmir case AArch64_AM::UXTX: return 3; break; 158274955Ssvnmir case AArch64_AM::SXTB: return 4; break; 159274955Ssvnmir case AArch64_AM::SXTH: return 5; break; 160274955Ssvnmir case AArch64_AM::SXTW: return 6; break; 161274955Ssvnmir case AArch64_AM::SXTX: return 7; break; 162274955Ssvnmir } 163274955Ssvnmir} 164274955Ssvnmir 165274955Ssvnmir/// getArithExtendImm - Encode the extend type and shift amount for an 166274955Ssvnmir/// arithmetic instruction: 167274955Ssvnmir/// imm: 3-bit extend amount 168274955Ssvnmir/// {5-3} = shifter 169274955Ssvnmir/// {2-0} = imm3 170274955Ssvnmirstatic inline unsigned getArithExtendImm(AArch64_AM::ShiftExtendType ET, 171274955Ssvnmir unsigned Imm) { 172274955Ssvnmir assert((Imm & 0x7) == Imm && "Illegal shifted immedate value!"); 173274955Ssvnmir return (getExtendEncoding(ET) << 3) | (Imm & 0x7); 174274955Ssvnmir} 175274955Ssvnmir 176274955Ssvnmir/// getMemDoShift - Extract the "do shift" flag value for load/store 177274955Ssvnmir/// instructions. 178274955Ssvnmirstatic inline bool getMemDoShift(unsigned Imm) { 179274955Ssvnmir return (Imm & 0x1) != 0; 180274955Ssvnmir} 181274955Ssvnmir 182274955Ssvnmir/// getExtendType - Extract the extend type for the offset operand of 183274955Ssvnmir/// loads/stores. 184274955Ssvnmirstatic inline AArch64_AM::ShiftExtendType getMemExtendType(unsigned Imm) { 185274955Ssvnmir return getExtendType((Imm >> 1) & 0x7); 186274955Ssvnmir} 187274955Ssvnmir 188274955Ssvnmir/// getExtendImm - Encode the extend type and amount for a load/store inst: 189274955Ssvnmir/// doshift: should the offset be scaled by the access size 190274955Ssvnmir/// shifter: 000 ==> uxtb 191274955Ssvnmir/// 001 ==> uxth 192274955Ssvnmir/// 010 ==> uxtw 193274955Ssvnmir/// 011 ==> uxtx 194274955Ssvnmir/// 100 ==> sxtb 195274955Ssvnmir/// 101 ==> sxth 196274955Ssvnmir/// 110 ==> sxtw 197274955Ssvnmir/// 111 ==> sxtx 198274955Ssvnmir/// {3-1} = shifter 199274955Ssvnmir/// {0} = doshift 200274955Ssvnmirstatic inline unsigned getMemExtendImm(AArch64_AM::ShiftExtendType ET, 201274955Ssvnmir bool DoShift) { 202274955Ssvnmir return (getExtendEncoding(ET) << 1) | unsigned(DoShift); 203274955Ssvnmir} 204274955Ssvnmir 205274955Ssvnmirstatic inline uint64_t ror(uint64_t elt, unsigned size) { 206274955Ssvnmir return ((elt & 1) << (size-1)) | (elt >> 1); 207274955Ssvnmir} 208274955Ssvnmir 209274955Ssvnmir/// processLogicalImmediate - Determine if an immediate value can be encoded 210274955Ssvnmir/// as the immediate operand of a logical instruction for the given register 211274955Ssvnmir/// size. If so, return true with "encoding" set to the encoded value in 212274955Ssvnmir/// the form N:immr:imms. 213274955Ssvnmirstatic inline bool processLogicalImmediate(uint64_t imm, unsigned regSize, 214274955Ssvnmir uint64_t &encoding) { 215274955Ssvnmir if (imm == 0ULL || imm == ~0ULL || 216274955Ssvnmir (regSize != 64 && (imm >> regSize != 0 || imm == ~0U))) 217274955Ssvnmir return false; 218274955Ssvnmir 219274955Ssvnmir unsigned size = 2; 220274955Ssvnmir uint64_t eltVal = imm; 221274955Ssvnmir 222274955Ssvnmir // First, determine the element size. 223274955Ssvnmir while (size < regSize) { 224274955Ssvnmir unsigned numElts = regSize / size; 225274955Ssvnmir unsigned mask = (1ULL << size) - 1; 226274955Ssvnmir uint64_t lowestEltVal = imm & mask; 227274955Ssvnmir 228274955Ssvnmir bool allMatched = true; 229274955Ssvnmir for (unsigned i = 1; i < numElts; ++i) { 230274955Ssvnmir uint64_t currEltVal = (imm >> (i*size)) & mask; 231274955Ssvnmir if (currEltVal != lowestEltVal) { 232274955Ssvnmir allMatched = false; 233274955Ssvnmir break; 234274955Ssvnmir } 235274955Ssvnmir } 236274955Ssvnmir 237274955Ssvnmir if (allMatched) { 238274955Ssvnmir eltVal = lowestEltVal; 239274955Ssvnmir break; 240274955Ssvnmir } 241274955Ssvnmir 242274955Ssvnmir size *= 2; 243274955Ssvnmir } 244274955Ssvnmir 245274955Ssvnmir // Second, determine the rotation to make the element be: 0^m 1^n. 246274955Ssvnmir for (unsigned i = 0; i < size; ++i) { 247274955Ssvnmir eltVal = ror(eltVal, size); 248274955Ssvnmir uint32_t clz = countLeadingZeros(eltVal) - (64 - size); 249274955Ssvnmir uint32_t cto = CountTrailingOnes_64(eltVal); 250274955Ssvnmir 251274955Ssvnmir if (clz + cto == size) { 252274955Ssvnmir // Encode in immr the number of RORs it would take to get *from* this 253274955Ssvnmir // element value to our target value, where i+1 is the number of RORs 254274955Ssvnmir // to go the opposite direction. 255274955Ssvnmir unsigned immr = size - (i + 1); 256274955Ssvnmir 257274955Ssvnmir // If size has a 1 in the n'th bit, create a value that has zeroes in 258274955Ssvnmir // bits [0, n] and ones above that. 259274955Ssvnmir uint64_t nimms = ~(size-1) << 1; 260274955Ssvnmir 261274955Ssvnmir // Or the CTO value into the low bits, which must be below the Nth bit 262274955Ssvnmir // bit mentioned above. 263274955Ssvnmir nimms |= (cto-1); 264274955Ssvnmir 265274955Ssvnmir // Extract the seventh bit and toggle it to create the N field. 266274955Ssvnmir unsigned N = ((nimms >> 6) & 1) ^ 1; 267274955Ssvnmir 268274955Ssvnmir encoding = (N << 12) | (immr << 6) | (nimms & 0x3f); 269274955Ssvnmir return true; 270274955Ssvnmir } 271274955Ssvnmir } 272274955Ssvnmir 273274955Ssvnmir return false; 274274955Ssvnmir} 275274955Ssvnmir 276274955Ssvnmir/// isLogicalImmediate - Return true if the immediate is valid for a logical 277274955Ssvnmir/// immediate instruction of the given register size. Return false otherwise. 278274955Ssvnmirstatic inline bool isLogicalImmediate(uint64_t imm, unsigned regSize) { 279274955Ssvnmir uint64_t encoding; 280274955Ssvnmir return processLogicalImmediate(imm, regSize, encoding); 281274955Ssvnmir} 282274955Ssvnmir 283274955Ssvnmir/// encodeLogicalImmediate - Return the encoded immediate value for a logical 284274955Ssvnmir/// immediate instruction of the given register size. 285274955Ssvnmirstatic inline uint64_t encodeLogicalImmediate(uint64_t imm, unsigned regSize) { 286274955Ssvnmir uint64_t encoding = 0; 287274955Ssvnmir bool res = processLogicalImmediate(imm, regSize, encoding); 288274955Ssvnmir assert(res && "invalid logical immediate"); 289274955Ssvnmir (void)res; 290274955Ssvnmir return encoding; 291274955Ssvnmir} 292274955Ssvnmir 293274955Ssvnmir/// decodeLogicalImmediate - Decode a logical immediate value in the form 294274955Ssvnmir/// "N:immr:imms" (where the immr and imms fields are each 6 bits) into the 295274955Ssvnmir/// integer value it represents with regSize bits. 296274955Ssvnmirstatic inline uint64_t decodeLogicalImmediate(uint64_t val, unsigned regSize) { 297274955Ssvnmir // Extract the N, imms, and immr fields. 298274955Ssvnmir unsigned N = (val >> 12) & 1; 299274955Ssvnmir unsigned immr = (val >> 6) & 0x3f; 300274955Ssvnmir unsigned imms = val & 0x3f; 301274955Ssvnmir 302274955Ssvnmir assert((regSize == 64 || N == 0) && "undefined logical immediate encoding"); 303274955Ssvnmir int len = 31 - countLeadingZeros((N << 6) | (~imms & 0x3f)); 304274955Ssvnmir assert(len >= 0 && "undefined logical immediate encoding"); 305274955Ssvnmir unsigned size = (1 << len); 306274955Ssvnmir unsigned R = immr & (size - 1); 307274955Ssvnmir unsigned S = imms & (size - 1); 308274955Ssvnmir assert(S != size - 1 && "undefined logical immediate encoding"); 309274955Ssvnmir uint64_t pattern = (1ULL << (S + 1)) - 1; 310274955Ssvnmir for (unsigned i = 0; i < R; ++i) 311274955Ssvnmir pattern = ror(pattern, size); 312274955Ssvnmir 313274955Ssvnmir // Replicate the pattern to fill the regSize. 314274955Ssvnmir while (size != regSize) { 315274955Ssvnmir pattern |= (pattern << size); 316274955Ssvnmir size *= 2; 317274955Ssvnmir } 318274955Ssvnmir return pattern; 319274955Ssvnmir} 320274955Ssvnmir 321274955Ssvnmir/// isValidDecodeLogicalImmediate - Check to see if the logical immediate value 322274955Ssvnmir/// in the form "N:immr:imms" (where the immr and imms fields are each 6 bits) 323274955Ssvnmir/// is a valid encoding for an integer value with regSize bits. 324274955Ssvnmirstatic inline bool isValidDecodeLogicalImmediate(uint64_t val, 325274955Ssvnmir unsigned regSize) { 326274955Ssvnmir // Extract the N and imms fields needed for checking. 327274955Ssvnmir unsigned N = (val >> 12) & 1; 328274955Ssvnmir unsigned imms = val & 0x3f; 329274955Ssvnmir 330274955Ssvnmir if (regSize == 32 && N != 0) // undefined logical immediate encoding 331274955Ssvnmir return false; 332274955Ssvnmir int len = 31 - countLeadingZeros((N << 6) | (~imms & 0x3f)); 333274955Ssvnmir if (len < 0) // undefined logical immediate encoding 334274955Ssvnmir return false; 335274955Ssvnmir unsigned size = (1 << len); 336274955Ssvnmir unsigned S = imms & (size - 1); 337274955Ssvnmir if (S == size - 1) // undefined logical immediate encoding 338274955Ssvnmir return false; 339274955Ssvnmir 340274955Ssvnmir return true; 341274955Ssvnmir} 342274955Ssvnmir 343274955Ssvnmir//===----------------------------------------------------------------------===// 344274955Ssvnmir// Floating-point Immediates 345274955Ssvnmir// 346274955Ssvnmirstatic inline float getFPImmFloat(unsigned Imm) { 347274955Ssvnmir // We expect an 8-bit binary encoding of a floating-point number here. 348274955Ssvnmir union { 349274955Ssvnmir uint32_t I; 350274955Ssvnmir float F; 351274955Ssvnmir } FPUnion; 352274955Ssvnmir 353274955Ssvnmir uint8_t Sign = (Imm >> 7) & 0x1; 354274955Ssvnmir uint8_t Exp = (Imm >> 4) & 0x7; 355274955Ssvnmir uint8_t Mantissa = Imm & 0xf; 356274955Ssvnmir 357274955Ssvnmir // 8-bit FP iEEEE Float Encoding 358274955Ssvnmir // abcd efgh aBbbbbbc defgh000 00000000 00000000 359274955Ssvnmir // 360274955Ssvnmir // where B = NOT(b); 361274955Ssvnmir 362274955Ssvnmir FPUnion.I = 0; 363274955Ssvnmir FPUnion.I |= Sign << 31; 364274955Ssvnmir FPUnion.I |= ((Exp & 0x4) != 0 ? 0 : 1) << 30; 365274955Ssvnmir FPUnion.I |= ((Exp & 0x4) != 0 ? 0x1f : 0) << 25; 366274955Ssvnmir FPUnion.I |= (Exp & 0x3) << 23; 367274955Ssvnmir FPUnion.I |= Mantissa << 19; 368274955Ssvnmir return FPUnion.F; 369274955Ssvnmir} 370274955Ssvnmir 371274955Ssvnmir/// getFP32Imm - Return an 8-bit floating-point version of the 32-bit 372274955Ssvnmir/// floating-point value. If the value cannot be represented as an 8-bit 373274955Ssvnmir/// floating-point value, then return -1. 374274955Ssvnmirstatic inline int getFP32Imm(const APInt &Imm) { 375274955Ssvnmir uint32_t Sign = Imm.lshr(31).getZExtValue() & 1; 376274955Ssvnmir int32_t Exp = (Imm.lshr(23).getSExtValue() & 0xff) - 127; // -126 to 127 377274955Ssvnmir int64_t Mantissa = Imm.getZExtValue() & 0x7fffff; // 23 bits 378274955Ssvnmir 379274955Ssvnmir // We can handle 4 bits of mantissa. 380274955Ssvnmir // mantissa = (16+UInt(e:f:g:h))/16. 381274955Ssvnmir if (Mantissa & 0x7ffff) 382274955Ssvnmir return -1; 383274955Ssvnmir Mantissa >>= 19; 384274955Ssvnmir if ((Mantissa & 0xf) != Mantissa) 385274955Ssvnmir return -1; 386274955Ssvnmir 387274955Ssvnmir // We can handle 3 bits of exponent: exp == UInt(NOT(b):c:d)-3 388274955Ssvnmir if (Exp < -3 || Exp > 4) 389274955Ssvnmir return -1; 390274955Ssvnmir Exp = ((Exp+3) & 0x7) ^ 4; 391274955Ssvnmir 392274955Ssvnmir return ((int)Sign << 7) | (Exp << 4) | Mantissa; 393274955Ssvnmir} 394274955Ssvnmir 395274955Ssvnmirstatic inline int getFP32Imm(const APFloat &FPImm) { 396274955Ssvnmir return getFP32Imm(FPImm.bitcastToAPInt()); 397274955Ssvnmir} 398274955Ssvnmir 399274955Ssvnmir/// getFP64Imm - Return an 8-bit floating-point version of the 64-bit 400274955Ssvnmir/// floating-point value. If the value cannot be represented as an 8-bit 401274955Ssvnmir/// floating-point value, then return -1. 402274955Ssvnmirstatic inline int getFP64Imm(const APInt &Imm) { 403274955Ssvnmir uint64_t Sign = Imm.lshr(63).getZExtValue() & 1; 404274955Ssvnmir int64_t Exp = (Imm.lshr(52).getSExtValue() & 0x7ff) - 1023; // -1022 to 1023 405274955Ssvnmir uint64_t Mantissa = Imm.getZExtValue() & 0xfffffffffffffULL; 406274955Ssvnmir 407274955Ssvnmir // We can handle 4 bits of mantissa. 408274955Ssvnmir // mantissa = (16+UInt(e:f:g:h))/16. 409274955Ssvnmir if (Mantissa & 0xffffffffffffULL) 410274955Ssvnmir return -1; 411274955Ssvnmir Mantissa >>= 48; 412274955Ssvnmir if ((Mantissa & 0xf) != Mantissa) 413274955Ssvnmir return -1; 414274955Ssvnmir 415274955Ssvnmir // We can handle 3 bits of exponent: exp == UInt(NOT(b):c:d)-3 416274955Ssvnmir if (Exp < -3 || Exp > 4) 417274955Ssvnmir return -1; 418274955Ssvnmir Exp = ((Exp+3) & 0x7) ^ 4; 419274955Ssvnmir 420274955Ssvnmir return ((int)Sign << 7) | (Exp << 4) | Mantissa; 421274955Ssvnmir} 422274955Ssvnmir 423274955Ssvnmirstatic inline int getFP64Imm(const APFloat &FPImm) { 424274955Ssvnmir return getFP64Imm(FPImm.bitcastToAPInt()); 425274955Ssvnmir} 426274955Ssvnmir 427274955Ssvnmir//===--------------------------------------------------------------------===// 428274955Ssvnmir// AdvSIMD Modified Immediates 429274955Ssvnmir//===--------------------------------------------------------------------===// 430274955Ssvnmir 431274955Ssvnmir// 0x00 0x00 0x00 abcdefgh 0x00 0x00 0x00 abcdefgh 432274955Ssvnmirstatic inline bool isAdvSIMDModImmType1(uint64_t Imm) { 433274955Ssvnmir return ((Imm >> 32) == (Imm & 0xffffffffULL)) && 434274955Ssvnmir ((Imm & 0xffffff00ffffff00ULL) == 0); 435274955Ssvnmir} 436274955Ssvnmir 437274955Ssvnmirstatic inline uint8_t encodeAdvSIMDModImmType1(uint64_t Imm) { 438274955Ssvnmir return (Imm & 0xffULL); 439274955Ssvnmir} 440274955Ssvnmir 441274955Ssvnmirstatic inline uint64_t decodeAdvSIMDModImmType1(uint8_t Imm) { 442274955Ssvnmir uint64_t EncVal = Imm; 443274955Ssvnmir return (EncVal << 32) | EncVal; 444274955Ssvnmir} 445274955Ssvnmir 446274955Ssvnmir// 0x00 0x00 abcdefgh 0x00 0x00 0x00 abcdefgh 0x00 447274955Ssvnmirstatic inline bool isAdvSIMDModImmType2(uint64_t Imm) { 448274955Ssvnmir return ((Imm >> 32) == (Imm & 0xffffffffULL)) && 449274955Ssvnmir ((Imm & 0xffff00ffffff00ffULL) == 0); 450274955Ssvnmir} 451274955Ssvnmir 452274955Ssvnmirstatic inline uint8_t encodeAdvSIMDModImmType2(uint64_t Imm) { 453274955Ssvnmir return (Imm & 0xff00ULL) >> 8; 454274955Ssvnmir} 455274955Ssvnmir 456274955Ssvnmirstatic inline uint64_t decodeAdvSIMDModImmType2(uint8_t Imm) { 457274955Ssvnmir uint64_t EncVal = Imm; 458274955Ssvnmir return (EncVal << 40) | (EncVal << 8); 459274955Ssvnmir} 460274955Ssvnmir 461274955Ssvnmir// 0x00 abcdefgh 0x00 0x00 0x00 abcdefgh 0x00 0x00 462274955Ssvnmirstatic inline bool isAdvSIMDModImmType3(uint64_t Imm) { 463274955Ssvnmir return ((Imm >> 32) == (Imm & 0xffffffffULL)) && 464274955Ssvnmir ((Imm & 0xff00ffffff00ffffULL) == 0); 465274955Ssvnmir} 466274955Ssvnmir 467274955Ssvnmirstatic inline uint8_t encodeAdvSIMDModImmType3(uint64_t Imm) { 468274955Ssvnmir return (Imm & 0xff0000ULL) >> 16; 469274955Ssvnmir} 470274955Ssvnmir 471274955Ssvnmirstatic inline uint64_t decodeAdvSIMDModImmType3(uint8_t Imm) { 472274955Ssvnmir uint64_t EncVal = Imm; 473274955Ssvnmir return (EncVal << 48) | (EncVal << 16); 474274955Ssvnmir} 475274955Ssvnmir 476274955Ssvnmir// abcdefgh 0x00 0x00 0x00 abcdefgh 0x00 0x00 0x00 477274955Ssvnmirstatic inline bool isAdvSIMDModImmType4(uint64_t Imm) { 478274955Ssvnmir return ((Imm >> 32) == (Imm & 0xffffffffULL)) && 479274955Ssvnmir ((Imm & 0x00ffffff00ffffffULL) == 0); 480274955Ssvnmir} 481274955Ssvnmir 482274955Ssvnmirstatic inline uint8_t encodeAdvSIMDModImmType4(uint64_t Imm) { 483274955Ssvnmir return (Imm & 0xff000000ULL) >> 24; 484274955Ssvnmir} 485274955Ssvnmir 486274955Ssvnmirstatic inline uint64_t decodeAdvSIMDModImmType4(uint8_t Imm) { 487274955Ssvnmir uint64_t EncVal = Imm; 488274955Ssvnmir return (EncVal << 56) | (EncVal << 24); 489274955Ssvnmir} 490274955Ssvnmir 491274955Ssvnmir// 0x00 abcdefgh 0x00 abcdefgh 0x00 abcdefgh 0x00 abcdefgh 492274955Ssvnmirstatic inline bool isAdvSIMDModImmType5(uint64_t Imm) { 493274955Ssvnmir return ((Imm >> 32) == (Imm & 0xffffffffULL)) && 494274955Ssvnmir (((Imm & 0x00ff0000ULL) >> 16) == (Imm & 0x000000ffULL)) && 495274955Ssvnmir ((Imm & 0xff00ff00ff00ff00ULL) == 0); 496274955Ssvnmir} 497274955Ssvnmir 498274955Ssvnmirstatic inline uint8_t encodeAdvSIMDModImmType5(uint64_t Imm) { 499274955Ssvnmir return (Imm & 0xffULL); 500274955Ssvnmir} 501274955Ssvnmir 502274955Ssvnmirstatic inline uint64_t decodeAdvSIMDModImmType5(uint8_t Imm) { 503274955Ssvnmir uint64_t EncVal = Imm; 504274955Ssvnmir return (EncVal << 48) | (EncVal << 32) | (EncVal << 16) | EncVal; 505274955Ssvnmir} 506274955Ssvnmir 507274955Ssvnmir// abcdefgh 0x00 abcdefgh 0x00 abcdefgh 0x00 abcdefgh 0x00 508274955Ssvnmirstatic inline bool isAdvSIMDModImmType6(uint64_t Imm) { 509274955Ssvnmir return ((Imm >> 32) == (Imm & 0xffffffffULL)) && 510274955Ssvnmir (((Imm & 0xff000000ULL) >> 16) == (Imm & 0x0000ff00ULL)) && 511274955Ssvnmir ((Imm & 0x00ff00ff00ff00ffULL) == 0); 512274955Ssvnmir} 513274955Ssvnmir 514274955Ssvnmirstatic inline uint8_t encodeAdvSIMDModImmType6(uint64_t Imm) { 515274955Ssvnmir return (Imm & 0xff00ULL) >> 8; 516274955Ssvnmir} 517274955Ssvnmir 518274955Ssvnmirstatic inline uint64_t decodeAdvSIMDModImmType6(uint8_t Imm) { 519274955Ssvnmir uint64_t EncVal = Imm; 520274955Ssvnmir return (EncVal << 56) | (EncVal << 40) | (EncVal << 24) | (EncVal << 8); 521274955Ssvnmir} 522274955Ssvnmir 523274955Ssvnmir// 0x00 0x00 abcdefgh 0xFF 0x00 0x00 abcdefgh 0xFF 524274955Ssvnmirstatic inline bool isAdvSIMDModImmType7(uint64_t Imm) { 525274955Ssvnmir return ((Imm >> 32) == (Imm & 0xffffffffULL)) && 526274955Ssvnmir ((Imm & 0xffff00ffffff00ffULL) == 0x000000ff000000ffULL); 527274955Ssvnmir} 528274955Ssvnmir 529274955Ssvnmirstatic inline uint8_t encodeAdvSIMDModImmType7(uint64_t Imm) { 530274955Ssvnmir return (Imm & 0xff00ULL) >> 8; 531274955Ssvnmir} 532274955Ssvnmir 533274955Ssvnmirstatic inline uint64_t decodeAdvSIMDModImmType7(uint8_t Imm) { 534274955Ssvnmir uint64_t EncVal = Imm; 535274955Ssvnmir return (EncVal << 40) | (EncVal << 8) | 0x000000ff000000ffULL; 536274955Ssvnmir} 537274955Ssvnmir 538274955Ssvnmir// 0x00 abcdefgh 0xFF 0xFF 0x00 abcdefgh 0xFF 0xFF 539274955Ssvnmirstatic inline bool isAdvSIMDModImmType8(uint64_t Imm) { 540274955Ssvnmir return ((Imm >> 32) == (Imm & 0xffffffffULL)) && 541274955Ssvnmir ((Imm & 0xff00ffffff00ffffULL) == 0x0000ffff0000ffffULL); 542274955Ssvnmir} 543274955Ssvnmir 544274955Ssvnmirstatic inline uint64_t decodeAdvSIMDModImmType8(uint8_t Imm) { 545274955Ssvnmir uint64_t EncVal = Imm; 546274955Ssvnmir return (EncVal << 48) | (EncVal << 16) | 0x0000ffff0000ffffULL; 547274955Ssvnmir} 548274955Ssvnmir 549274955Ssvnmirstatic inline uint8_t encodeAdvSIMDModImmType8(uint64_t Imm) { 550274955Ssvnmir return (Imm & 0x00ff0000ULL) >> 16; 551274955Ssvnmir} 552274955Ssvnmir 553274955Ssvnmir// abcdefgh abcdefgh abcdefgh abcdefgh abcdefgh abcdefgh abcdefgh abcdefgh 554274955Ssvnmirstatic inline bool isAdvSIMDModImmType9(uint64_t Imm) { 555274955Ssvnmir return ((Imm >> 32) == (Imm & 0xffffffffULL)) && 556274955Ssvnmir ((Imm >> 48) == (Imm & 0x0000ffffULL)) && 557274955Ssvnmir ((Imm >> 56) == (Imm & 0x000000ffULL)); 558274955Ssvnmir} 559274955Ssvnmir 560274955Ssvnmirstatic inline uint8_t encodeAdvSIMDModImmType9(uint64_t Imm) { 561274955Ssvnmir return (Imm & 0xffULL); 562274955Ssvnmir} 563274955Ssvnmir 564274955Ssvnmirstatic inline uint64_t decodeAdvSIMDModImmType9(uint8_t Imm) { 565274955Ssvnmir uint64_t EncVal = Imm; 566274955Ssvnmir EncVal |= (EncVal << 8); 567274955Ssvnmir EncVal |= (EncVal << 16); 568274955Ssvnmir EncVal |= (EncVal << 32); 569274955Ssvnmir return EncVal; 570274955Ssvnmir} 571274955Ssvnmir 572274955Ssvnmir// aaaaaaaa bbbbbbbb cccccccc dddddddd eeeeeeee ffffffff gggggggg hhhhhhhh 573274955Ssvnmir// cmode: 1110, op: 1 574274955Ssvnmirstatic inline bool isAdvSIMDModImmType10(uint64_t Imm) { 575274955Ssvnmir uint64_t ByteA = Imm & 0xff00000000000000ULL; 576274955Ssvnmir uint64_t ByteB = Imm & 0x00ff000000000000ULL; 577274955Ssvnmir uint64_t ByteC = Imm & 0x0000ff0000000000ULL; 578274955Ssvnmir uint64_t ByteD = Imm & 0x000000ff00000000ULL; 579274955Ssvnmir uint64_t ByteE = Imm & 0x00000000ff000000ULL; 580274955Ssvnmir uint64_t ByteF = Imm & 0x0000000000ff0000ULL; 581274955Ssvnmir uint64_t ByteG = Imm & 0x000000000000ff00ULL; 582274955Ssvnmir uint64_t ByteH = Imm & 0x00000000000000ffULL; 583274955Ssvnmir 584274955Ssvnmir return (ByteA == 0ULL || ByteA == 0xff00000000000000ULL) && 585274955Ssvnmir (ByteB == 0ULL || ByteB == 0x00ff000000000000ULL) && 586274955Ssvnmir (ByteC == 0ULL || ByteC == 0x0000ff0000000000ULL) && 587274955Ssvnmir (ByteD == 0ULL || ByteD == 0x000000ff00000000ULL) && 588274955Ssvnmir (ByteE == 0ULL || ByteE == 0x00000000ff000000ULL) && 589274955Ssvnmir (ByteF == 0ULL || ByteF == 0x0000000000ff0000ULL) && 590274955Ssvnmir (ByteG == 0ULL || ByteG == 0x000000000000ff00ULL) && 591274955Ssvnmir (ByteH == 0ULL || ByteH == 0x00000000000000ffULL); 592274955Ssvnmir} 593274955Ssvnmir 594274955Ssvnmirstatic inline uint8_t encodeAdvSIMDModImmType10(uint64_t Imm) { 595274955Ssvnmir uint8_t BitA = (Imm & 0xff00000000000000ULL) != 0; 596274955Ssvnmir uint8_t BitB = (Imm & 0x00ff000000000000ULL) != 0; 597274955Ssvnmir uint8_t BitC = (Imm & 0x0000ff0000000000ULL) != 0; 598274955Ssvnmir uint8_t BitD = (Imm & 0x000000ff00000000ULL) != 0; 599274955Ssvnmir uint8_t BitE = (Imm & 0x00000000ff000000ULL) != 0; 600274955Ssvnmir uint8_t BitF = (Imm & 0x0000000000ff0000ULL) != 0; 601274955Ssvnmir uint8_t BitG = (Imm & 0x000000000000ff00ULL) != 0; 602274955Ssvnmir uint8_t BitH = (Imm & 0x00000000000000ffULL) != 0; 603274955Ssvnmir 604274955Ssvnmir uint8_t EncVal = BitA; 605274955Ssvnmir EncVal <<= 1; 606274955Ssvnmir EncVal |= BitB; 607274955Ssvnmir EncVal <<= 1; 608274955Ssvnmir EncVal |= BitC; 609274955Ssvnmir EncVal <<= 1; 610274955Ssvnmir EncVal |= BitD; 611274955Ssvnmir EncVal <<= 1; 612274955Ssvnmir EncVal |= BitE; 613274955Ssvnmir EncVal <<= 1; 614274955Ssvnmir EncVal |= BitF; 615274955Ssvnmir EncVal <<= 1; 616274955Ssvnmir EncVal |= BitG; 617274955Ssvnmir EncVal <<= 1; 618274955Ssvnmir EncVal |= BitH; 619274955Ssvnmir return EncVal; 620274955Ssvnmir} 621274955Ssvnmir 622274955Ssvnmirstatic inline uint64_t decodeAdvSIMDModImmType10(uint8_t Imm) { 623274955Ssvnmir uint64_t EncVal = 0; 624274955Ssvnmir if (Imm & 0x80) EncVal |= 0xff00000000000000ULL; 625274955Ssvnmir if (Imm & 0x40) EncVal |= 0x00ff000000000000ULL; 626274955Ssvnmir if (Imm & 0x20) EncVal |= 0x0000ff0000000000ULL; 627274955Ssvnmir if (Imm & 0x10) EncVal |= 0x000000ff00000000ULL; 628274955Ssvnmir if (Imm & 0x08) EncVal |= 0x00000000ff000000ULL; 629274955Ssvnmir if (Imm & 0x04) EncVal |= 0x0000000000ff0000ULL; 630274955Ssvnmir if (Imm & 0x02) EncVal |= 0x000000000000ff00ULL; 631274955Ssvnmir if (Imm & 0x01) EncVal |= 0x00000000000000ffULL; 632274955Ssvnmir return EncVal; 633274955Ssvnmir} 634274955Ssvnmir 635274955Ssvnmir// aBbbbbbc defgh000 0x00 0x00 aBbbbbbc defgh000 0x00 0x00 636274955Ssvnmirstatic inline bool isAdvSIMDModImmType11(uint64_t Imm) { 637274955Ssvnmir uint64_t BString = (Imm & 0x7E000000ULL) >> 25; 638274955Ssvnmir return ((Imm >> 32) == (Imm & 0xffffffffULL)) && 639274955Ssvnmir (BString == 0x1f || BString == 0x20) && 640274955Ssvnmir ((Imm & 0x0007ffff0007ffffULL) == 0); 641274955Ssvnmir} 642274955Ssvnmir 643274955Ssvnmirstatic inline uint8_t encodeAdvSIMDModImmType11(uint64_t Imm) { 644274955Ssvnmir uint8_t BitA = (Imm & 0x80000000ULL) != 0; 645274955Ssvnmir uint8_t BitB = (Imm & 0x20000000ULL) != 0; 646274955Ssvnmir uint8_t BitC = (Imm & 0x01000000ULL) != 0; 647274955Ssvnmir uint8_t BitD = (Imm & 0x00800000ULL) != 0; 648274955Ssvnmir uint8_t BitE = (Imm & 0x00400000ULL) != 0; 649274955Ssvnmir uint8_t BitF = (Imm & 0x00200000ULL) != 0; 650274955Ssvnmir uint8_t BitG = (Imm & 0x00100000ULL) != 0; 651274955Ssvnmir uint8_t BitH = (Imm & 0x00080000ULL) != 0; 652274955Ssvnmir 653274955Ssvnmir uint8_t EncVal = BitA; 654274955Ssvnmir EncVal <<= 1; 655274955Ssvnmir EncVal |= BitB; 656274955Ssvnmir EncVal <<= 1; 657274955Ssvnmir EncVal |= BitC; 658274955Ssvnmir EncVal <<= 1; 659274955Ssvnmir EncVal |= BitD; 660274955Ssvnmir EncVal <<= 1; 661274955Ssvnmir EncVal |= BitE; 662274955Ssvnmir EncVal <<= 1; 663274955Ssvnmir EncVal |= BitF; 664274955Ssvnmir EncVal <<= 1; 665274955Ssvnmir EncVal |= BitG; 666274955Ssvnmir EncVal <<= 1; 667274955Ssvnmir EncVal |= BitH; 668274955Ssvnmir return EncVal; 669274955Ssvnmir} 670274955Ssvnmir 671274955Ssvnmirstatic inline uint64_t decodeAdvSIMDModImmType11(uint8_t Imm) { 672274955Ssvnmir uint64_t EncVal = 0; 673274955Ssvnmir if (Imm & 0x80) EncVal |= 0x80000000ULL; 674274955Ssvnmir if (Imm & 0x40) EncVal |= 0x3e000000ULL; 675274955Ssvnmir else EncVal |= 0x40000000ULL; 676274955Ssvnmir if (Imm & 0x20) EncVal |= 0x01000000ULL; 677274955Ssvnmir if (Imm & 0x10) EncVal |= 0x00800000ULL; 678274955Ssvnmir if (Imm & 0x08) EncVal |= 0x00400000ULL; 679274955Ssvnmir if (Imm & 0x04) EncVal |= 0x00200000ULL; 680274955Ssvnmir if (Imm & 0x02) EncVal |= 0x00100000ULL; 681274955Ssvnmir if (Imm & 0x01) EncVal |= 0x00080000ULL; 682274955Ssvnmir return (EncVal << 32) | EncVal; 683274955Ssvnmir} 684274955Ssvnmir 685274955Ssvnmir// aBbbbbbb bbcdefgh 0x00 0x00 0x00 0x00 0x00 0x00 686274955Ssvnmirstatic inline bool isAdvSIMDModImmType12(uint64_t Imm) { 687274955Ssvnmir uint64_t BString = (Imm & 0x7fc0000000000000ULL) >> 54; 688274955Ssvnmir return ((BString == 0xff || BString == 0x100) && 689274955Ssvnmir ((Imm & 0x0000ffffffffffffULL) == 0)); 690274955Ssvnmir} 691274955Ssvnmir 692274955Ssvnmirstatic inline uint8_t encodeAdvSIMDModImmType12(uint64_t Imm) { 693274955Ssvnmir uint8_t BitA = (Imm & 0x8000000000000000ULL) != 0; 694274955Ssvnmir uint8_t BitB = (Imm & 0x0040000000000000ULL) != 0; 695274955Ssvnmir uint8_t BitC = (Imm & 0x0020000000000000ULL) != 0; 696274955Ssvnmir uint8_t BitD = (Imm & 0x0010000000000000ULL) != 0; 697274955Ssvnmir uint8_t BitE = (Imm & 0x0008000000000000ULL) != 0; 698274955Ssvnmir uint8_t BitF = (Imm & 0x0004000000000000ULL) != 0; 699274955Ssvnmir uint8_t BitG = (Imm & 0x0002000000000000ULL) != 0; 700274955Ssvnmir uint8_t BitH = (Imm & 0x0001000000000000ULL) != 0; 701274955Ssvnmir 702274955Ssvnmir uint8_t EncVal = BitA; 703274955Ssvnmir EncVal <<= 1; 704274955Ssvnmir EncVal |= BitB; 705274955Ssvnmir EncVal <<= 1; 706274955Ssvnmir EncVal |= BitC; 707274955Ssvnmir EncVal <<= 1; 708274955Ssvnmir EncVal |= BitD; 709274955Ssvnmir EncVal <<= 1; 710274955Ssvnmir EncVal |= BitE; 711274955Ssvnmir EncVal <<= 1; 712274955Ssvnmir EncVal |= BitF; 713274955Ssvnmir EncVal <<= 1; 714274955Ssvnmir EncVal |= BitG; 715274955Ssvnmir EncVal <<= 1; 716274955Ssvnmir EncVal |= BitH; 717274955Ssvnmir return EncVal; 718274955Ssvnmir} 719274955Ssvnmir 720274955Ssvnmirstatic inline uint64_t decodeAdvSIMDModImmType12(uint8_t Imm) { 721274955Ssvnmir uint64_t EncVal = 0; 722274955Ssvnmir if (Imm & 0x80) EncVal |= 0x8000000000000000ULL; 723274955Ssvnmir if (Imm & 0x40) EncVal |= 0x3fc0000000000000ULL; 724274955Ssvnmir else EncVal |= 0x4000000000000000ULL; 725274955Ssvnmir if (Imm & 0x20) EncVal |= 0x0020000000000000ULL; 726274955Ssvnmir if (Imm & 0x10) EncVal |= 0x0010000000000000ULL; 727274955Ssvnmir if (Imm & 0x08) EncVal |= 0x0008000000000000ULL; 728274955Ssvnmir if (Imm & 0x04) EncVal |= 0x0004000000000000ULL; 729274955Ssvnmir if (Imm & 0x02) EncVal |= 0x0002000000000000ULL; 730274955Ssvnmir if (Imm & 0x01) EncVal |= 0x0001000000000000ULL; 731274955Ssvnmir return (EncVal << 32) | EncVal; 732274955Ssvnmir} 733274955Ssvnmir 734274955Ssvnmir} // end namespace AArch64_AM 735274955Ssvnmir 736274955Ssvnmir} // end namespace llvm 737274955Ssvnmir 738274955Ssvnmir#endif 739