AArch64AddressingModes.h revision 288943
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 14280031Sdim#ifndef LLVM_LIB_TARGET_AARCH64_MCTARGETDESC_AARCH64ADDRESSINGMODES_H 15280031Sdim#define LLVM_LIB_TARGET_AARCH64_MCTARGETDESC_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) { 54280031Sdim default: llvm_unreachable("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. 213280031Sdimstatic inline bool processLogicalImmediate(uint64_t Imm, unsigned RegSize, 214280031Sdim uint64_t &Encoding) { 215280031Sdim if (Imm == 0ULL || Imm == ~0ULL || 216280031Sdim (RegSize != 64 && (Imm >> RegSize != 0 || Imm == ~0U))) 217274955Ssvnmir return false; 218274955Ssvnmir 219274955Ssvnmir // First, determine the element size. 220280031Sdim unsigned Size = RegSize; 221274955Ssvnmir 222280031Sdim do { 223280031Sdim Size /= 2; 224280031Sdim uint64_t Mask = (1ULL << Size) - 1; 225274955Ssvnmir 226280031Sdim if ((Imm & Mask) != ((Imm >> Size) & Mask)) { 227280031Sdim Size *= 2; 228274955Ssvnmir break; 229274955Ssvnmir } 230280031Sdim } while (Size > 2); 231274955Ssvnmir 232274955Ssvnmir // Second, determine the rotation to make the element be: 0^m 1^n. 233280031Sdim uint32_t CTO, I; 234280031Sdim uint64_t Mask = ((uint64_t)-1LL) >> (64 - Size); 235280031Sdim Imm &= Mask; 236274955Ssvnmir 237280031Sdim if (isShiftedMask_64(Imm)) { 238280031Sdim I = countTrailingZeros(Imm); 239280031Sdim assert(I < 64 && "undefined behavior"); 240288943Sdim CTO = countTrailingOnes(Imm >> I); 241280031Sdim } else { 242280031Sdim Imm |= ~Mask; 243280031Sdim if (!isShiftedMask_64(~Imm)) 244280031Sdim return false; 245274955Ssvnmir 246288943Sdim unsigned CLO = countLeadingOnes(Imm); 247280031Sdim I = 64 - CLO; 248288943Sdim CTO = CLO + countTrailingOnes(Imm) - (64 - Size); 249280031Sdim } 250274955Ssvnmir 251280031Sdim // Encode in Immr the number of RORs it would take to get *from* 0^m 1^n 252280031Sdim // to our target value, where I is the number of RORs to go the opposite 253280031Sdim // direction. 254280031Sdim assert(Size > I && "I should be smaller than element size"); 255280031Sdim unsigned Immr = (Size - I) & (Size - 1); 256274955Ssvnmir 257280031Sdim // If size has a 1 in the n'th bit, create a value that has zeroes in 258280031Sdim // bits [0, n] and ones above that. 259280031Sdim uint64_t NImms = ~(Size-1) << 1; 260274955Ssvnmir 261280031Sdim // Or the CTO value into the low bits, which must be below the Nth bit 262280031Sdim // bit mentioned above. 263280031Sdim NImms |= (CTO-1); 264274955Ssvnmir 265280031Sdim // Extract the seventh bit and toggle it to create the N field. 266280031Sdim unsigned N = ((NImms >> 6) & 1) ^ 1; 267280031Sdim 268280031Sdim Encoding = (N << 12) | (Immr << 6) | (NImms & 0x3f); 269280031Sdim return true; 270274955Ssvnmir} 271274955Ssvnmir 272274955Ssvnmir/// isLogicalImmediate - Return true if the immediate is valid for a logical 273274955Ssvnmir/// immediate instruction of the given register size. Return false otherwise. 274274955Ssvnmirstatic inline bool isLogicalImmediate(uint64_t imm, unsigned regSize) { 275274955Ssvnmir uint64_t encoding; 276274955Ssvnmir return processLogicalImmediate(imm, regSize, encoding); 277274955Ssvnmir} 278274955Ssvnmir 279274955Ssvnmir/// encodeLogicalImmediate - Return the encoded immediate value for a logical 280274955Ssvnmir/// immediate instruction of the given register size. 281274955Ssvnmirstatic inline uint64_t encodeLogicalImmediate(uint64_t imm, unsigned regSize) { 282274955Ssvnmir uint64_t encoding = 0; 283274955Ssvnmir bool res = processLogicalImmediate(imm, regSize, encoding); 284274955Ssvnmir assert(res && "invalid logical immediate"); 285274955Ssvnmir (void)res; 286274955Ssvnmir return encoding; 287274955Ssvnmir} 288274955Ssvnmir 289274955Ssvnmir/// decodeLogicalImmediate - Decode a logical immediate value in the form 290274955Ssvnmir/// "N:immr:imms" (where the immr and imms fields are each 6 bits) into the 291274955Ssvnmir/// integer value it represents with regSize bits. 292274955Ssvnmirstatic inline uint64_t decodeLogicalImmediate(uint64_t val, unsigned regSize) { 293274955Ssvnmir // Extract the N, imms, and immr fields. 294274955Ssvnmir unsigned N = (val >> 12) & 1; 295274955Ssvnmir unsigned immr = (val >> 6) & 0x3f; 296274955Ssvnmir unsigned imms = val & 0x3f; 297274955Ssvnmir 298274955Ssvnmir assert((regSize == 64 || N == 0) && "undefined logical immediate encoding"); 299274955Ssvnmir int len = 31 - countLeadingZeros((N << 6) | (~imms & 0x3f)); 300274955Ssvnmir assert(len >= 0 && "undefined logical immediate encoding"); 301274955Ssvnmir unsigned size = (1 << len); 302274955Ssvnmir unsigned R = immr & (size - 1); 303274955Ssvnmir unsigned S = imms & (size - 1); 304274955Ssvnmir assert(S != size - 1 && "undefined logical immediate encoding"); 305274955Ssvnmir uint64_t pattern = (1ULL << (S + 1)) - 1; 306274955Ssvnmir for (unsigned i = 0; i < R; ++i) 307274955Ssvnmir pattern = ror(pattern, size); 308274955Ssvnmir 309274955Ssvnmir // Replicate the pattern to fill the regSize. 310274955Ssvnmir while (size != regSize) { 311274955Ssvnmir pattern |= (pattern << size); 312274955Ssvnmir size *= 2; 313274955Ssvnmir } 314274955Ssvnmir return pattern; 315274955Ssvnmir} 316274955Ssvnmir 317274955Ssvnmir/// isValidDecodeLogicalImmediate - Check to see if the logical immediate value 318274955Ssvnmir/// in the form "N:immr:imms" (where the immr and imms fields are each 6 bits) 319274955Ssvnmir/// is a valid encoding for an integer value with regSize bits. 320274955Ssvnmirstatic inline bool isValidDecodeLogicalImmediate(uint64_t val, 321274955Ssvnmir unsigned regSize) { 322274955Ssvnmir // Extract the N and imms fields needed for checking. 323274955Ssvnmir unsigned N = (val >> 12) & 1; 324274955Ssvnmir unsigned imms = val & 0x3f; 325274955Ssvnmir 326274955Ssvnmir if (regSize == 32 && N != 0) // undefined logical immediate encoding 327274955Ssvnmir return false; 328274955Ssvnmir int len = 31 - countLeadingZeros((N << 6) | (~imms & 0x3f)); 329274955Ssvnmir if (len < 0) // undefined logical immediate encoding 330274955Ssvnmir return false; 331274955Ssvnmir unsigned size = (1 << len); 332274955Ssvnmir unsigned S = imms & (size - 1); 333274955Ssvnmir if (S == size - 1) // undefined logical immediate encoding 334274955Ssvnmir return false; 335274955Ssvnmir 336274955Ssvnmir return true; 337274955Ssvnmir} 338274955Ssvnmir 339274955Ssvnmir//===----------------------------------------------------------------------===// 340274955Ssvnmir// Floating-point Immediates 341274955Ssvnmir// 342274955Ssvnmirstatic inline float getFPImmFloat(unsigned Imm) { 343274955Ssvnmir // We expect an 8-bit binary encoding of a floating-point number here. 344274955Ssvnmir union { 345274955Ssvnmir uint32_t I; 346274955Ssvnmir float F; 347274955Ssvnmir } FPUnion; 348274955Ssvnmir 349274955Ssvnmir uint8_t Sign = (Imm >> 7) & 0x1; 350274955Ssvnmir uint8_t Exp = (Imm >> 4) & 0x7; 351274955Ssvnmir uint8_t Mantissa = Imm & 0xf; 352274955Ssvnmir 353274955Ssvnmir // 8-bit FP iEEEE Float Encoding 354274955Ssvnmir // abcd efgh aBbbbbbc defgh000 00000000 00000000 355274955Ssvnmir // 356274955Ssvnmir // where B = NOT(b); 357274955Ssvnmir 358274955Ssvnmir FPUnion.I = 0; 359274955Ssvnmir FPUnion.I |= Sign << 31; 360274955Ssvnmir FPUnion.I |= ((Exp & 0x4) != 0 ? 0 : 1) << 30; 361274955Ssvnmir FPUnion.I |= ((Exp & 0x4) != 0 ? 0x1f : 0) << 25; 362274955Ssvnmir FPUnion.I |= (Exp & 0x3) << 23; 363274955Ssvnmir FPUnion.I |= Mantissa << 19; 364274955Ssvnmir return FPUnion.F; 365274955Ssvnmir} 366274955Ssvnmir 367274955Ssvnmir/// getFP32Imm - Return an 8-bit floating-point version of the 32-bit 368274955Ssvnmir/// floating-point value. If the value cannot be represented as an 8-bit 369274955Ssvnmir/// floating-point value, then return -1. 370274955Ssvnmirstatic inline int getFP32Imm(const APInt &Imm) { 371274955Ssvnmir uint32_t Sign = Imm.lshr(31).getZExtValue() & 1; 372274955Ssvnmir int32_t Exp = (Imm.lshr(23).getSExtValue() & 0xff) - 127; // -126 to 127 373274955Ssvnmir int64_t Mantissa = Imm.getZExtValue() & 0x7fffff; // 23 bits 374274955Ssvnmir 375274955Ssvnmir // We can handle 4 bits of mantissa. 376274955Ssvnmir // mantissa = (16+UInt(e:f:g:h))/16. 377274955Ssvnmir if (Mantissa & 0x7ffff) 378274955Ssvnmir return -1; 379274955Ssvnmir Mantissa >>= 19; 380274955Ssvnmir if ((Mantissa & 0xf) != Mantissa) 381274955Ssvnmir return -1; 382274955Ssvnmir 383274955Ssvnmir // We can handle 3 bits of exponent: exp == UInt(NOT(b):c:d)-3 384274955Ssvnmir if (Exp < -3 || Exp > 4) 385274955Ssvnmir return -1; 386274955Ssvnmir Exp = ((Exp+3) & 0x7) ^ 4; 387274955Ssvnmir 388274955Ssvnmir return ((int)Sign << 7) | (Exp << 4) | Mantissa; 389274955Ssvnmir} 390274955Ssvnmir 391274955Ssvnmirstatic inline int getFP32Imm(const APFloat &FPImm) { 392274955Ssvnmir return getFP32Imm(FPImm.bitcastToAPInt()); 393274955Ssvnmir} 394274955Ssvnmir 395274955Ssvnmir/// getFP64Imm - Return an 8-bit floating-point version of the 64-bit 396274955Ssvnmir/// floating-point value. If the value cannot be represented as an 8-bit 397274955Ssvnmir/// floating-point value, then return -1. 398274955Ssvnmirstatic inline int getFP64Imm(const APInt &Imm) { 399274955Ssvnmir uint64_t Sign = Imm.lshr(63).getZExtValue() & 1; 400274955Ssvnmir int64_t Exp = (Imm.lshr(52).getSExtValue() & 0x7ff) - 1023; // -1022 to 1023 401274955Ssvnmir uint64_t Mantissa = Imm.getZExtValue() & 0xfffffffffffffULL; 402274955Ssvnmir 403274955Ssvnmir // We can handle 4 bits of mantissa. 404274955Ssvnmir // mantissa = (16+UInt(e:f:g:h))/16. 405274955Ssvnmir if (Mantissa & 0xffffffffffffULL) 406274955Ssvnmir return -1; 407274955Ssvnmir Mantissa >>= 48; 408274955Ssvnmir if ((Mantissa & 0xf) != Mantissa) 409274955Ssvnmir return -1; 410274955Ssvnmir 411274955Ssvnmir // We can handle 3 bits of exponent: exp == UInt(NOT(b):c:d)-3 412274955Ssvnmir if (Exp < -3 || Exp > 4) 413274955Ssvnmir return -1; 414274955Ssvnmir Exp = ((Exp+3) & 0x7) ^ 4; 415274955Ssvnmir 416274955Ssvnmir return ((int)Sign << 7) | (Exp << 4) | Mantissa; 417274955Ssvnmir} 418274955Ssvnmir 419274955Ssvnmirstatic inline int getFP64Imm(const APFloat &FPImm) { 420274955Ssvnmir return getFP64Imm(FPImm.bitcastToAPInt()); 421274955Ssvnmir} 422274955Ssvnmir 423274955Ssvnmir//===--------------------------------------------------------------------===// 424274955Ssvnmir// AdvSIMD Modified Immediates 425274955Ssvnmir//===--------------------------------------------------------------------===// 426274955Ssvnmir 427274955Ssvnmir// 0x00 0x00 0x00 abcdefgh 0x00 0x00 0x00 abcdefgh 428274955Ssvnmirstatic inline bool isAdvSIMDModImmType1(uint64_t Imm) { 429274955Ssvnmir return ((Imm >> 32) == (Imm & 0xffffffffULL)) && 430274955Ssvnmir ((Imm & 0xffffff00ffffff00ULL) == 0); 431274955Ssvnmir} 432274955Ssvnmir 433274955Ssvnmirstatic inline uint8_t encodeAdvSIMDModImmType1(uint64_t Imm) { 434274955Ssvnmir return (Imm & 0xffULL); 435274955Ssvnmir} 436274955Ssvnmir 437274955Ssvnmirstatic inline uint64_t decodeAdvSIMDModImmType1(uint8_t Imm) { 438274955Ssvnmir uint64_t EncVal = Imm; 439274955Ssvnmir return (EncVal << 32) | EncVal; 440274955Ssvnmir} 441274955Ssvnmir 442274955Ssvnmir// 0x00 0x00 abcdefgh 0x00 0x00 0x00 abcdefgh 0x00 443274955Ssvnmirstatic inline bool isAdvSIMDModImmType2(uint64_t Imm) { 444274955Ssvnmir return ((Imm >> 32) == (Imm & 0xffffffffULL)) && 445274955Ssvnmir ((Imm & 0xffff00ffffff00ffULL) == 0); 446274955Ssvnmir} 447274955Ssvnmir 448274955Ssvnmirstatic inline uint8_t encodeAdvSIMDModImmType2(uint64_t Imm) { 449274955Ssvnmir return (Imm & 0xff00ULL) >> 8; 450274955Ssvnmir} 451274955Ssvnmir 452274955Ssvnmirstatic inline uint64_t decodeAdvSIMDModImmType2(uint8_t Imm) { 453274955Ssvnmir uint64_t EncVal = Imm; 454274955Ssvnmir return (EncVal << 40) | (EncVal << 8); 455274955Ssvnmir} 456274955Ssvnmir 457274955Ssvnmir// 0x00 abcdefgh 0x00 0x00 0x00 abcdefgh 0x00 0x00 458274955Ssvnmirstatic inline bool isAdvSIMDModImmType3(uint64_t Imm) { 459274955Ssvnmir return ((Imm >> 32) == (Imm & 0xffffffffULL)) && 460274955Ssvnmir ((Imm & 0xff00ffffff00ffffULL) == 0); 461274955Ssvnmir} 462274955Ssvnmir 463274955Ssvnmirstatic inline uint8_t encodeAdvSIMDModImmType3(uint64_t Imm) { 464274955Ssvnmir return (Imm & 0xff0000ULL) >> 16; 465274955Ssvnmir} 466274955Ssvnmir 467274955Ssvnmirstatic inline uint64_t decodeAdvSIMDModImmType3(uint8_t Imm) { 468274955Ssvnmir uint64_t EncVal = Imm; 469274955Ssvnmir return (EncVal << 48) | (EncVal << 16); 470274955Ssvnmir} 471274955Ssvnmir 472274955Ssvnmir// abcdefgh 0x00 0x00 0x00 abcdefgh 0x00 0x00 0x00 473274955Ssvnmirstatic inline bool isAdvSIMDModImmType4(uint64_t Imm) { 474274955Ssvnmir return ((Imm >> 32) == (Imm & 0xffffffffULL)) && 475274955Ssvnmir ((Imm & 0x00ffffff00ffffffULL) == 0); 476274955Ssvnmir} 477274955Ssvnmir 478274955Ssvnmirstatic inline uint8_t encodeAdvSIMDModImmType4(uint64_t Imm) { 479274955Ssvnmir return (Imm & 0xff000000ULL) >> 24; 480274955Ssvnmir} 481274955Ssvnmir 482274955Ssvnmirstatic inline uint64_t decodeAdvSIMDModImmType4(uint8_t Imm) { 483274955Ssvnmir uint64_t EncVal = Imm; 484274955Ssvnmir return (EncVal << 56) | (EncVal << 24); 485274955Ssvnmir} 486274955Ssvnmir 487274955Ssvnmir// 0x00 abcdefgh 0x00 abcdefgh 0x00 abcdefgh 0x00 abcdefgh 488274955Ssvnmirstatic inline bool isAdvSIMDModImmType5(uint64_t Imm) { 489274955Ssvnmir return ((Imm >> 32) == (Imm & 0xffffffffULL)) && 490274955Ssvnmir (((Imm & 0x00ff0000ULL) >> 16) == (Imm & 0x000000ffULL)) && 491274955Ssvnmir ((Imm & 0xff00ff00ff00ff00ULL) == 0); 492274955Ssvnmir} 493274955Ssvnmir 494274955Ssvnmirstatic inline uint8_t encodeAdvSIMDModImmType5(uint64_t Imm) { 495274955Ssvnmir return (Imm & 0xffULL); 496274955Ssvnmir} 497274955Ssvnmir 498274955Ssvnmirstatic inline uint64_t decodeAdvSIMDModImmType5(uint8_t Imm) { 499274955Ssvnmir uint64_t EncVal = Imm; 500274955Ssvnmir return (EncVal << 48) | (EncVal << 32) | (EncVal << 16) | EncVal; 501274955Ssvnmir} 502274955Ssvnmir 503274955Ssvnmir// abcdefgh 0x00 abcdefgh 0x00 abcdefgh 0x00 abcdefgh 0x00 504274955Ssvnmirstatic inline bool isAdvSIMDModImmType6(uint64_t Imm) { 505274955Ssvnmir return ((Imm >> 32) == (Imm & 0xffffffffULL)) && 506274955Ssvnmir (((Imm & 0xff000000ULL) >> 16) == (Imm & 0x0000ff00ULL)) && 507274955Ssvnmir ((Imm & 0x00ff00ff00ff00ffULL) == 0); 508274955Ssvnmir} 509274955Ssvnmir 510274955Ssvnmirstatic inline uint8_t encodeAdvSIMDModImmType6(uint64_t Imm) { 511274955Ssvnmir return (Imm & 0xff00ULL) >> 8; 512274955Ssvnmir} 513274955Ssvnmir 514274955Ssvnmirstatic inline uint64_t decodeAdvSIMDModImmType6(uint8_t Imm) { 515274955Ssvnmir uint64_t EncVal = Imm; 516274955Ssvnmir return (EncVal << 56) | (EncVal << 40) | (EncVal << 24) | (EncVal << 8); 517274955Ssvnmir} 518274955Ssvnmir 519274955Ssvnmir// 0x00 0x00 abcdefgh 0xFF 0x00 0x00 abcdefgh 0xFF 520274955Ssvnmirstatic inline bool isAdvSIMDModImmType7(uint64_t Imm) { 521274955Ssvnmir return ((Imm >> 32) == (Imm & 0xffffffffULL)) && 522274955Ssvnmir ((Imm & 0xffff00ffffff00ffULL) == 0x000000ff000000ffULL); 523274955Ssvnmir} 524274955Ssvnmir 525274955Ssvnmirstatic inline uint8_t encodeAdvSIMDModImmType7(uint64_t Imm) { 526274955Ssvnmir return (Imm & 0xff00ULL) >> 8; 527274955Ssvnmir} 528274955Ssvnmir 529274955Ssvnmirstatic inline uint64_t decodeAdvSIMDModImmType7(uint8_t Imm) { 530274955Ssvnmir uint64_t EncVal = Imm; 531274955Ssvnmir return (EncVal << 40) | (EncVal << 8) | 0x000000ff000000ffULL; 532274955Ssvnmir} 533274955Ssvnmir 534274955Ssvnmir// 0x00 abcdefgh 0xFF 0xFF 0x00 abcdefgh 0xFF 0xFF 535274955Ssvnmirstatic inline bool isAdvSIMDModImmType8(uint64_t Imm) { 536274955Ssvnmir return ((Imm >> 32) == (Imm & 0xffffffffULL)) && 537274955Ssvnmir ((Imm & 0xff00ffffff00ffffULL) == 0x0000ffff0000ffffULL); 538274955Ssvnmir} 539274955Ssvnmir 540274955Ssvnmirstatic inline uint64_t decodeAdvSIMDModImmType8(uint8_t Imm) { 541274955Ssvnmir uint64_t EncVal = Imm; 542274955Ssvnmir return (EncVal << 48) | (EncVal << 16) | 0x0000ffff0000ffffULL; 543274955Ssvnmir} 544274955Ssvnmir 545274955Ssvnmirstatic inline uint8_t encodeAdvSIMDModImmType8(uint64_t Imm) { 546274955Ssvnmir return (Imm & 0x00ff0000ULL) >> 16; 547274955Ssvnmir} 548274955Ssvnmir 549274955Ssvnmir// abcdefgh abcdefgh abcdefgh abcdefgh abcdefgh abcdefgh abcdefgh abcdefgh 550274955Ssvnmirstatic inline bool isAdvSIMDModImmType9(uint64_t Imm) { 551274955Ssvnmir return ((Imm >> 32) == (Imm & 0xffffffffULL)) && 552274955Ssvnmir ((Imm >> 48) == (Imm & 0x0000ffffULL)) && 553274955Ssvnmir ((Imm >> 56) == (Imm & 0x000000ffULL)); 554274955Ssvnmir} 555274955Ssvnmir 556274955Ssvnmirstatic inline uint8_t encodeAdvSIMDModImmType9(uint64_t Imm) { 557274955Ssvnmir return (Imm & 0xffULL); 558274955Ssvnmir} 559274955Ssvnmir 560274955Ssvnmirstatic inline uint64_t decodeAdvSIMDModImmType9(uint8_t Imm) { 561274955Ssvnmir uint64_t EncVal = Imm; 562274955Ssvnmir EncVal |= (EncVal << 8); 563274955Ssvnmir EncVal |= (EncVal << 16); 564274955Ssvnmir EncVal |= (EncVal << 32); 565274955Ssvnmir return EncVal; 566274955Ssvnmir} 567274955Ssvnmir 568274955Ssvnmir// aaaaaaaa bbbbbbbb cccccccc dddddddd eeeeeeee ffffffff gggggggg hhhhhhhh 569274955Ssvnmir// cmode: 1110, op: 1 570274955Ssvnmirstatic inline bool isAdvSIMDModImmType10(uint64_t Imm) { 571274955Ssvnmir uint64_t ByteA = Imm & 0xff00000000000000ULL; 572274955Ssvnmir uint64_t ByteB = Imm & 0x00ff000000000000ULL; 573274955Ssvnmir uint64_t ByteC = Imm & 0x0000ff0000000000ULL; 574274955Ssvnmir uint64_t ByteD = Imm & 0x000000ff00000000ULL; 575274955Ssvnmir uint64_t ByteE = Imm & 0x00000000ff000000ULL; 576274955Ssvnmir uint64_t ByteF = Imm & 0x0000000000ff0000ULL; 577274955Ssvnmir uint64_t ByteG = Imm & 0x000000000000ff00ULL; 578274955Ssvnmir uint64_t ByteH = Imm & 0x00000000000000ffULL; 579274955Ssvnmir 580274955Ssvnmir return (ByteA == 0ULL || ByteA == 0xff00000000000000ULL) && 581274955Ssvnmir (ByteB == 0ULL || ByteB == 0x00ff000000000000ULL) && 582274955Ssvnmir (ByteC == 0ULL || ByteC == 0x0000ff0000000000ULL) && 583274955Ssvnmir (ByteD == 0ULL || ByteD == 0x000000ff00000000ULL) && 584274955Ssvnmir (ByteE == 0ULL || ByteE == 0x00000000ff000000ULL) && 585274955Ssvnmir (ByteF == 0ULL || ByteF == 0x0000000000ff0000ULL) && 586274955Ssvnmir (ByteG == 0ULL || ByteG == 0x000000000000ff00ULL) && 587274955Ssvnmir (ByteH == 0ULL || ByteH == 0x00000000000000ffULL); 588274955Ssvnmir} 589274955Ssvnmir 590274955Ssvnmirstatic inline uint8_t encodeAdvSIMDModImmType10(uint64_t Imm) { 591274955Ssvnmir uint8_t BitA = (Imm & 0xff00000000000000ULL) != 0; 592274955Ssvnmir uint8_t BitB = (Imm & 0x00ff000000000000ULL) != 0; 593274955Ssvnmir uint8_t BitC = (Imm & 0x0000ff0000000000ULL) != 0; 594274955Ssvnmir uint8_t BitD = (Imm & 0x000000ff00000000ULL) != 0; 595274955Ssvnmir uint8_t BitE = (Imm & 0x00000000ff000000ULL) != 0; 596274955Ssvnmir uint8_t BitF = (Imm & 0x0000000000ff0000ULL) != 0; 597274955Ssvnmir uint8_t BitG = (Imm & 0x000000000000ff00ULL) != 0; 598274955Ssvnmir uint8_t BitH = (Imm & 0x00000000000000ffULL) != 0; 599274955Ssvnmir 600274955Ssvnmir uint8_t EncVal = BitA; 601274955Ssvnmir EncVal <<= 1; 602274955Ssvnmir EncVal |= BitB; 603274955Ssvnmir EncVal <<= 1; 604274955Ssvnmir EncVal |= BitC; 605274955Ssvnmir EncVal <<= 1; 606274955Ssvnmir EncVal |= BitD; 607274955Ssvnmir EncVal <<= 1; 608274955Ssvnmir EncVal |= BitE; 609274955Ssvnmir EncVal <<= 1; 610274955Ssvnmir EncVal |= BitF; 611274955Ssvnmir EncVal <<= 1; 612274955Ssvnmir EncVal |= BitG; 613274955Ssvnmir EncVal <<= 1; 614274955Ssvnmir EncVal |= BitH; 615274955Ssvnmir return EncVal; 616274955Ssvnmir} 617274955Ssvnmir 618274955Ssvnmirstatic inline uint64_t decodeAdvSIMDModImmType10(uint8_t Imm) { 619274955Ssvnmir uint64_t EncVal = 0; 620274955Ssvnmir if (Imm & 0x80) EncVal |= 0xff00000000000000ULL; 621274955Ssvnmir if (Imm & 0x40) EncVal |= 0x00ff000000000000ULL; 622274955Ssvnmir if (Imm & 0x20) EncVal |= 0x0000ff0000000000ULL; 623274955Ssvnmir if (Imm & 0x10) EncVal |= 0x000000ff00000000ULL; 624274955Ssvnmir if (Imm & 0x08) EncVal |= 0x00000000ff000000ULL; 625274955Ssvnmir if (Imm & 0x04) EncVal |= 0x0000000000ff0000ULL; 626274955Ssvnmir if (Imm & 0x02) EncVal |= 0x000000000000ff00ULL; 627274955Ssvnmir if (Imm & 0x01) EncVal |= 0x00000000000000ffULL; 628274955Ssvnmir return EncVal; 629274955Ssvnmir} 630274955Ssvnmir 631274955Ssvnmir// aBbbbbbc defgh000 0x00 0x00 aBbbbbbc defgh000 0x00 0x00 632274955Ssvnmirstatic inline bool isAdvSIMDModImmType11(uint64_t Imm) { 633274955Ssvnmir uint64_t BString = (Imm & 0x7E000000ULL) >> 25; 634274955Ssvnmir return ((Imm >> 32) == (Imm & 0xffffffffULL)) && 635274955Ssvnmir (BString == 0x1f || BString == 0x20) && 636274955Ssvnmir ((Imm & 0x0007ffff0007ffffULL) == 0); 637274955Ssvnmir} 638274955Ssvnmir 639274955Ssvnmirstatic inline uint8_t encodeAdvSIMDModImmType11(uint64_t Imm) { 640274955Ssvnmir uint8_t BitA = (Imm & 0x80000000ULL) != 0; 641274955Ssvnmir uint8_t BitB = (Imm & 0x20000000ULL) != 0; 642274955Ssvnmir uint8_t BitC = (Imm & 0x01000000ULL) != 0; 643274955Ssvnmir uint8_t BitD = (Imm & 0x00800000ULL) != 0; 644274955Ssvnmir uint8_t BitE = (Imm & 0x00400000ULL) != 0; 645274955Ssvnmir uint8_t BitF = (Imm & 0x00200000ULL) != 0; 646274955Ssvnmir uint8_t BitG = (Imm & 0x00100000ULL) != 0; 647274955Ssvnmir uint8_t BitH = (Imm & 0x00080000ULL) != 0; 648274955Ssvnmir 649274955Ssvnmir uint8_t EncVal = BitA; 650274955Ssvnmir EncVal <<= 1; 651274955Ssvnmir EncVal |= BitB; 652274955Ssvnmir EncVal <<= 1; 653274955Ssvnmir EncVal |= BitC; 654274955Ssvnmir EncVal <<= 1; 655274955Ssvnmir EncVal |= BitD; 656274955Ssvnmir EncVal <<= 1; 657274955Ssvnmir EncVal |= BitE; 658274955Ssvnmir EncVal <<= 1; 659274955Ssvnmir EncVal |= BitF; 660274955Ssvnmir EncVal <<= 1; 661274955Ssvnmir EncVal |= BitG; 662274955Ssvnmir EncVal <<= 1; 663274955Ssvnmir EncVal |= BitH; 664274955Ssvnmir return EncVal; 665274955Ssvnmir} 666274955Ssvnmir 667274955Ssvnmirstatic inline uint64_t decodeAdvSIMDModImmType11(uint8_t Imm) { 668274955Ssvnmir uint64_t EncVal = 0; 669274955Ssvnmir if (Imm & 0x80) EncVal |= 0x80000000ULL; 670274955Ssvnmir if (Imm & 0x40) EncVal |= 0x3e000000ULL; 671274955Ssvnmir else EncVal |= 0x40000000ULL; 672274955Ssvnmir if (Imm & 0x20) EncVal |= 0x01000000ULL; 673274955Ssvnmir if (Imm & 0x10) EncVal |= 0x00800000ULL; 674274955Ssvnmir if (Imm & 0x08) EncVal |= 0x00400000ULL; 675274955Ssvnmir if (Imm & 0x04) EncVal |= 0x00200000ULL; 676274955Ssvnmir if (Imm & 0x02) EncVal |= 0x00100000ULL; 677274955Ssvnmir if (Imm & 0x01) EncVal |= 0x00080000ULL; 678274955Ssvnmir return (EncVal << 32) | EncVal; 679274955Ssvnmir} 680274955Ssvnmir 681274955Ssvnmir// aBbbbbbb bbcdefgh 0x00 0x00 0x00 0x00 0x00 0x00 682274955Ssvnmirstatic inline bool isAdvSIMDModImmType12(uint64_t Imm) { 683274955Ssvnmir uint64_t BString = (Imm & 0x7fc0000000000000ULL) >> 54; 684274955Ssvnmir return ((BString == 0xff || BString == 0x100) && 685274955Ssvnmir ((Imm & 0x0000ffffffffffffULL) == 0)); 686274955Ssvnmir} 687274955Ssvnmir 688274955Ssvnmirstatic inline uint8_t encodeAdvSIMDModImmType12(uint64_t Imm) { 689274955Ssvnmir uint8_t BitA = (Imm & 0x8000000000000000ULL) != 0; 690274955Ssvnmir uint8_t BitB = (Imm & 0x0040000000000000ULL) != 0; 691274955Ssvnmir uint8_t BitC = (Imm & 0x0020000000000000ULL) != 0; 692274955Ssvnmir uint8_t BitD = (Imm & 0x0010000000000000ULL) != 0; 693274955Ssvnmir uint8_t BitE = (Imm & 0x0008000000000000ULL) != 0; 694274955Ssvnmir uint8_t BitF = (Imm & 0x0004000000000000ULL) != 0; 695274955Ssvnmir uint8_t BitG = (Imm & 0x0002000000000000ULL) != 0; 696274955Ssvnmir uint8_t BitH = (Imm & 0x0001000000000000ULL) != 0; 697274955Ssvnmir 698274955Ssvnmir uint8_t EncVal = BitA; 699274955Ssvnmir EncVal <<= 1; 700274955Ssvnmir EncVal |= BitB; 701274955Ssvnmir EncVal <<= 1; 702274955Ssvnmir EncVal |= BitC; 703274955Ssvnmir EncVal <<= 1; 704274955Ssvnmir EncVal |= BitD; 705274955Ssvnmir EncVal <<= 1; 706274955Ssvnmir EncVal |= BitE; 707274955Ssvnmir EncVal <<= 1; 708274955Ssvnmir EncVal |= BitF; 709274955Ssvnmir EncVal <<= 1; 710274955Ssvnmir EncVal |= BitG; 711274955Ssvnmir EncVal <<= 1; 712274955Ssvnmir EncVal |= BitH; 713274955Ssvnmir return EncVal; 714274955Ssvnmir} 715274955Ssvnmir 716274955Ssvnmirstatic inline uint64_t decodeAdvSIMDModImmType12(uint8_t Imm) { 717274955Ssvnmir uint64_t EncVal = 0; 718274955Ssvnmir if (Imm & 0x80) EncVal |= 0x8000000000000000ULL; 719274955Ssvnmir if (Imm & 0x40) EncVal |= 0x3fc0000000000000ULL; 720274955Ssvnmir else EncVal |= 0x4000000000000000ULL; 721274955Ssvnmir if (Imm & 0x20) EncVal |= 0x0020000000000000ULL; 722274955Ssvnmir if (Imm & 0x10) EncVal |= 0x0010000000000000ULL; 723274955Ssvnmir if (Imm & 0x08) EncVal |= 0x0008000000000000ULL; 724274955Ssvnmir if (Imm & 0x04) EncVal |= 0x0004000000000000ULL; 725274955Ssvnmir if (Imm & 0x02) EncVal |= 0x0002000000000000ULL; 726274955Ssvnmir if (Imm & 0x01) EncVal |= 0x0001000000000000ULL; 727274955Ssvnmir return (EncVal << 32) | EncVal; 728274955Ssvnmir} 729274955Ssvnmir 730274955Ssvnmir} // end namespace AArch64_AM 731274955Ssvnmir 732274955Ssvnmir} // end namespace llvm 733274955Ssvnmir 734274955Ssvnmir#endif 735