1274955Ssvnmir//===- AArch64AddressingModes.h - AArch64 Addressing Modes ------*- C++ -*-===// 2274955Ssvnmir// 3353358Sdim// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4353358Sdim// See https://llvm.org/LICENSE.txt for license information. 5353358Sdim// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6274955Ssvnmir// 7274955Ssvnmir//===----------------------------------------------------------------------===// 8274955Ssvnmir// 9274955Ssvnmir// This file contains the AArch64 addressing mode implementation stuff. 10274955Ssvnmir// 11274955Ssvnmir//===----------------------------------------------------------------------===// 12274955Ssvnmir 13280031Sdim#ifndef LLVM_LIB_TARGET_AARCH64_MCTARGETDESC_AARCH64ADDRESSINGMODES_H 14280031Sdim#define LLVM_LIB_TARGET_AARCH64_MCTARGETDESC_AARCH64ADDRESSINGMODES_H 15274955Ssvnmir 16274955Ssvnmir#include "llvm/ADT/APFloat.h" 17274955Ssvnmir#include "llvm/ADT/APInt.h" 18344779Sdim#include "llvm/ADT/bit.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 || 216341825Sdim (RegSize != 64 && 217341825Sdim (Imm >> RegSize != 0 || Imm == (~0ULL >> (64 - RegSize))))) 218274955Ssvnmir return false; 219274955Ssvnmir 220274955Ssvnmir // First, determine the element size. 221280031Sdim unsigned Size = RegSize; 222274955Ssvnmir 223280031Sdim do { 224280031Sdim Size /= 2; 225280031Sdim uint64_t Mask = (1ULL << Size) - 1; 226274955Ssvnmir 227280031Sdim if ((Imm & Mask) != ((Imm >> Size) & Mask)) { 228280031Sdim Size *= 2; 229274955Ssvnmir break; 230274955Ssvnmir } 231280031Sdim } while (Size > 2); 232274955Ssvnmir 233274955Ssvnmir // Second, determine the rotation to make the element be: 0^m 1^n. 234280031Sdim uint32_t CTO, I; 235280031Sdim uint64_t Mask = ((uint64_t)-1LL) >> (64 - Size); 236280031Sdim Imm &= Mask; 237274955Ssvnmir 238280031Sdim if (isShiftedMask_64(Imm)) { 239280031Sdim I = countTrailingZeros(Imm); 240280031Sdim assert(I < 64 && "undefined behavior"); 241288943Sdim CTO = countTrailingOnes(Imm >> I); 242280031Sdim } else { 243280031Sdim Imm |= ~Mask; 244280031Sdim if (!isShiftedMask_64(~Imm)) 245280031Sdim return false; 246274955Ssvnmir 247288943Sdim unsigned CLO = countLeadingOnes(Imm); 248280031Sdim I = 64 - CLO; 249288943Sdim CTO = CLO + countTrailingOnes(Imm) - (64 - Size); 250280031Sdim } 251274955Ssvnmir 252280031Sdim // Encode in Immr the number of RORs it would take to get *from* 0^m 1^n 253280031Sdim // to our target value, where I is the number of RORs to go the opposite 254280031Sdim // direction. 255280031Sdim assert(Size > I && "I should be smaller than element size"); 256280031Sdim unsigned Immr = (Size - I) & (Size - 1); 257274955Ssvnmir 258280031Sdim // If size has a 1 in the n'th bit, create a value that has zeroes in 259280031Sdim // bits [0, n] and ones above that. 260280031Sdim uint64_t NImms = ~(Size-1) << 1; 261274955Ssvnmir 262280031Sdim // Or the CTO value into the low bits, which must be below the Nth bit 263280031Sdim // bit mentioned above. 264280031Sdim NImms |= (CTO-1); 265274955Ssvnmir 266280031Sdim // Extract the seventh bit and toggle it to create the N field. 267280031Sdim unsigned N = ((NImms >> 6) & 1) ^ 1; 268280031Sdim 269280031Sdim Encoding = (N << 12) | (Immr << 6) | (NImms & 0x3f); 270280031Sdim return true; 271274955Ssvnmir} 272274955Ssvnmir 273274955Ssvnmir/// isLogicalImmediate - Return true if the immediate is valid for a logical 274274955Ssvnmir/// immediate instruction of the given register size. Return false otherwise. 275274955Ssvnmirstatic inline bool isLogicalImmediate(uint64_t imm, unsigned regSize) { 276274955Ssvnmir uint64_t encoding; 277274955Ssvnmir return processLogicalImmediate(imm, regSize, encoding); 278274955Ssvnmir} 279274955Ssvnmir 280274955Ssvnmir/// encodeLogicalImmediate - Return the encoded immediate value for a logical 281274955Ssvnmir/// immediate instruction of the given register size. 282274955Ssvnmirstatic inline uint64_t encodeLogicalImmediate(uint64_t imm, unsigned regSize) { 283274955Ssvnmir uint64_t encoding = 0; 284274955Ssvnmir bool res = processLogicalImmediate(imm, regSize, encoding); 285274955Ssvnmir assert(res && "invalid logical immediate"); 286274955Ssvnmir (void)res; 287274955Ssvnmir return encoding; 288274955Ssvnmir} 289274955Ssvnmir 290274955Ssvnmir/// decodeLogicalImmediate - Decode a logical immediate value in the form 291274955Ssvnmir/// "N:immr:imms" (where the immr and imms fields are each 6 bits) into the 292274955Ssvnmir/// integer value it represents with regSize bits. 293274955Ssvnmirstatic inline uint64_t decodeLogicalImmediate(uint64_t val, unsigned regSize) { 294274955Ssvnmir // Extract the N, imms, and immr fields. 295274955Ssvnmir unsigned N = (val >> 12) & 1; 296274955Ssvnmir unsigned immr = (val >> 6) & 0x3f; 297274955Ssvnmir unsigned imms = val & 0x3f; 298274955Ssvnmir 299274955Ssvnmir assert((regSize == 64 || N == 0) && "undefined logical immediate encoding"); 300274955Ssvnmir int len = 31 - countLeadingZeros((N << 6) | (~imms & 0x3f)); 301274955Ssvnmir assert(len >= 0 && "undefined logical immediate encoding"); 302274955Ssvnmir unsigned size = (1 << len); 303274955Ssvnmir unsigned R = immr & (size - 1); 304274955Ssvnmir unsigned S = imms & (size - 1); 305274955Ssvnmir assert(S != size - 1 && "undefined logical immediate encoding"); 306274955Ssvnmir uint64_t pattern = (1ULL << (S + 1)) - 1; 307274955Ssvnmir for (unsigned i = 0; i < R; ++i) 308274955Ssvnmir pattern = ror(pattern, size); 309274955Ssvnmir 310274955Ssvnmir // Replicate the pattern to fill the regSize. 311274955Ssvnmir while (size != regSize) { 312274955Ssvnmir pattern |= (pattern << size); 313274955Ssvnmir size *= 2; 314274955Ssvnmir } 315274955Ssvnmir return pattern; 316274955Ssvnmir} 317274955Ssvnmir 318274955Ssvnmir/// isValidDecodeLogicalImmediate - Check to see if the logical immediate value 319274955Ssvnmir/// in the form "N:immr:imms" (where the immr and imms fields are each 6 bits) 320274955Ssvnmir/// is a valid encoding for an integer value with regSize bits. 321274955Ssvnmirstatic inline bool isValidDecodeLogicalImmediate(uint64_t val, 322274955Ssvnmir unsigned regSize) { 323274955Ssvnmir // Extract the N and imms fields needed for checking. 324274955Ssvnmir unsigned N = (val >> 12) & 1; 325274955Ssvnmir unsigned imms = val & 0x3f; 326274955Ssvnmir 327274955Ssvnmir if (regSize == 32 && N != 0) // undefined logical immediate encoding 328274955Ssvnmir return false; 329274955Ssvnmir int len = 31 - countLeadingZeros((N << 6) | (~imms & 0x3f)); 330274955Ssvnmir if (len < 0) // undefined logical immediate encoding 331274955Ssvnmir return false; 332274955Ssvnmir unsigned size = (1 << len); 333274955Ssvnmir unsigned S = imms & (size - 1); 334274955Ssvnmir if (S == size - 1) // undefined logical immediate encoding 335274955Ssvnmir return false; 336274955Ssvnmir 337274955Ssvnmir return true; 338274955Ssvnmir} 339274955Ssvnmir 340274955Ssvnmir//===----------------------------------------------------------------------===// 341274955Ssvnmir// Floating-point Immediates 342274955Ssvnmir// 343274955Ssvnmirstatic inline float getFPImmFloat(unsigned Imm) { 344274955Ssvnmir // We expect an 8-bit binary encoding of a floating-point number here. 345274955Ssvnmir 346274955Ssvnmir uint8_t Sign = (Imm >> 7) & 0x1; 347274955Ssvnmir uint8_t Exp = (Imm >> 4) & 0x7; 348274955Ssvnmir uint8_t Mantissa = Imm & 0xf; 349274955Ssvnmir 350344779Sdim // 8-bit FP IEEE Float Encoding 351274955Ssvnmir // abcd efgh aBbbbbbc defgh000 00000000 00000000 352274955Ssvnmir // 353274955Ssvnmir // where B = NOT(b); 354274955Ssvnmir 355344779Sdim uint32_t I = 0; 356344779Sdim I |= Sign << 31; 357344779Sdim I |= ((Exp & 0x4) != 0 ? 0 : 1) << 30; 358344779Sdim I |= ((Exp & 0x4) != 0 ? 0x1f : 0) << 25; 359344779Sdim I |= (Exp & 0x3) << 23; 360344779Sdim I |= Mantissa << 19; 361344779Sdim return bit_cast<float>(I); 362274955Ssvnmir} 363274955Ssvnmir 364296417Sdim/// getFP16Imm - Return an 8-bit floating-point version of the 16-bit 365296417Sdim/// floating-point value. If the value cannot be represented as an 8-bit 366296417Sdim/// floating-point value, then return -1. 367296417Sdimstatic inline int getFP16Imm(const APInt &Imm) { 368296417Sdim uint32_t Sign = Imm.lshr(15).getZExtValue() & 1; 369296417Sdim int32_t Exp = (Imm.lshr(10).getSExtValue() & 0x1f) - 15; // -14 to 15 370296417Sdim int32_t Mantissa = Imm.getZExtValue() & 0x3ff; // 10 bits 371296417Sdim 372296417Sdim // We can handle 4 bits of mantissa. 373296417Sdim // mantissa = (16+UInt(e:f:g:h))/16. 374296417Sdim if (Mantissa & 0x3f) 375296417Sdim return -1; 376296417Sdim Mantissa >>= 6; 377296417Sdim 378296417Sdim // We can handle 3 bits of exponent: exp == UInt(NOT(b):c:d)-3 379296417Sdim if (Exp < -3 || Exp > 4) 380296417Sdim return -1; 381296417Sdim Exp = ((Exp+3) & 0x7) ^ 4; 382296417Sdim 383296417Sdim return ((int)Sign << 7) | (Exp << 4) | Mantissa; 384296417Sdim} 385296417Sdim 386296417Sdimstatic inline int getFP16Imm(const APFloat &FPImm) { 387296417Sdim return getFP16Imm(FPImm.bitcastToAPInt()); 388296417Sdim} 389296417Sdim 390274955Ssvnmir/// getFP32Imm - Return an 8-bit floating-point version of the 32-bit 391274955Ssvnmir/// floating-point value. If the value cannot be represented as an 8-bit 392274955Ssvnmir/// floating-point value, then return -1. 393274955Ssvnmirstatic inline int getFP32Imm(const APInt &Imm) { 394274955Ssvnmir uint32_t Sign = Imm.lshr(31).getZExtValue() & 1; 395274955Ssvnmir int32_t Exp = (Imm.lshr(23).getSExtValue() & 0xff) - 127; // -126 to 127 396274955Ssvnmir int64_t Mantissa = Imm.getZExtValue() & 0x7fffff; // 23 bits 397274955Ssvnmir 398274955Ssvnmir // We can handle 4 bits of mantissa. 399274955Ssvnmir // mantissa = (16+UInt(e:f:g:h))/16. 400274955Ssvnmir if (Mantissa & 0x7ffff) 401274955Ssvnmir return -1; 402274955Ssvnmir Mantissa >>= 19; 403274955Ssvnmir if ((Mantissa & 0xf) != Mantissa) 404274955Ssvnmir return -1; 405274955Ssvnmir 406274955Ssvnmir // We can handle 3 bits of exponent: exp == UInt(NOT(b):c:d)-3 407274955Ssvnmir if (Exp < -3 || Exp > 4) 408274955Ssvnmir return -1; 409274955Ssvnmir Exp = ((Exp+3) & 0x7) ^ 4; 410274955Ssvnmir 411274955Ssvnmir return ((int)Sign << 7) | (Exp << 4) | Mantissa; 412274955Ssvnmir} 413274955Ssvnmir 414274955Ssvnmirstatic inline int getFP32Imm(const APFloat &FPImm) { 415274955Ssvnmir return getFP32Imm(FPImm.bitcastToAPInt()); 416274955Ssvnmir} 417274955Ssvnmir 418274955Ssvnmir/// getFP64Imm - Return an 8-bit floating-point version of the 64-bit 419274955Ssvnmir/// floating-point value. If the value cannot be represented as an 8-bit 420274955Ssvnmir/// floating-point value, then return -1. 421274955Ssvnmirstatic inline int getFP64Imm(const APInt &Imm) { 422274955Ssvnmir uint64_t Sign = Imm.lshr(63).getZExtValue() & 1; 423274955Ssvnmir int64_t Exp = (Imm.lshr(52).getSExtValue() & 0x7ff) - 1023; // -1022 to 1023 424274955Ssvnmir uint64_t Mantissa = Imm.getZExtValue() & 0xfffffffffffffULL; 425274955Ssvnmir 426274955Ssvnmir // We can handle 4 bits of mantissa. 427274955Ssvnmir // mantissa = (16+UInt(e:f:g:h))/16. 428274955Ssvnmir if (Mantissa & 0xffffffffffffULL) 429274955Ssvnmir return -1; 430274955Ssvnmir Mantissa >>= 48; 431274955Ssvnmir if ((Mantissa & 0xf) != Mantissa) 432274955Ssvnmir return -1; 433274955Ssvnmir 434274955Ssvnmir // We can handle 3 bits of exponent: exp == UInt(NOT(b):c:d)-3 435274955Ssvnmir if (Exp < -3 || Exp > 4) 436274955Ssvnmir return -1; 437274955Ssvnmir Exp = ((Exp+3) & 0x7) ^ 4; 438274955Ssvnmir 439274955Ssvnmir return ((int)Sign << 7) | (Exp << 4) | Mantissa; 440274955Ssvnmir} 441274955Ssvnmir 442274955Ssvnmirstatic inline int getFP64Imm(const APFloat &FPImm) { 443274955Ssvnmir return getFP64Imm(FPImm.bitcastToAPInt()); 444274955Ssvnmir} 445274955Ssvnmir 446274955Ssvnmir//===--------------------------------------------------------------------===// 447274955Ssvnmir// AdvSIMD Modified Immediates 448274955Ssvnmir//===--------------------------------------------------------------------===// 449274955Ssvnmir 450274955Ssvnmir// 0x00 0x00 0x00 abcdefgh 0x00 0x00 0x00 abcdefgh 451274955Ssvnmirstatic inline bool isAdvSIMDModImmType1(uint64_t Imm) { 452274955Ssvnmir return ((Imm >> 32) == (Imm & 0xffffffffULL)) && 453274955Ssvnmir ((Imm & 0xffffff00ffffff00ULL) == 0); 454274955Ssvnmir} 455274955Ssvnmir 456274955Ssvnmirstatic inline uint8_t encodeAdvSIMDModImmType1(uint64_t Imm) { 457274955Ssvnmir return (Imm & 0xffULL); 458274955Ssvnmir} 459274955Ssvnmir 460274955Ssvnmirstatic inline uint64_t decodeAdvSIMDModImmType1(uint8_t Imm) { 461274955Ssvnmir uint64_t EncVal = Imm; 462274955Ssvnmir return (EncVal << 32) | EncVal; 463274955Ssvnmir} 464274955Ssvnmir 465274955Ssvnmir// 0x00 0x00 abcdefgh 0x00 0x00 0x00 abcdefgh 0x00 466274955Ssvnmirstatic inline bool isAdvSIMDModImmType2(uint64_t Imm) { 467274955Ssvnmir return ((Imm >> 32) == (Imm & 0xffffffffULL)) && 468274955Ssvnmir ((Imm & 0xffff00ffffff00ffULL) == 0); 469274955Ssvnmir} 470274955Ssvnmir 471274955Ssvnmirstatic inline uint8_t encodeAdvSIMDModImmType2(uint64_t Imm) { 472274955Ssvnmir return (Imm & 0xff00ULL) >> 8; 473274955Ssvnmir} 474274955Ssvnmir 475274955Ssvnmirstatic inline uint64_t decodeAdvSIMDModImmType2(uint8_t Imm) { 476274955Ssvnmir uint64_t EncVal = Imm; 477274955Ssvnmir return (EncVal << 40) | (EncVal << 8); 478274955Ssvnmir} 479274955Ssvnmir 480274955Ssvnmir// 0x00 abcdefgh 0x00 0x00 0x00 abcdefgh 0x00 0x00 481274955Ssvnmirstatic inline bool isAdvSIMDModImmType3(uint64_t Imm) { 482274955Ssvnmir return ((Imm >> 32) == (Imm & 0xffffffffULL)) && 483274955Ssvnmir ((Imm & 0xff00ffffff00ffffULL) == 0); 484274955Ssvnmir} 485274955Ssvnmir 486274955Ssvnmirstatic inline uint8_t encodeAdvSIMDModImmType3(uint64_t Imm) { 487274955Ssvnmir return (Imm & 0xff0000ULL) >> 16; 488274955Ssvnmir} 489274955Ssvnmir 490274955Ssvnmirstatic inline uint64_t decodeAdvSIMDModImmType3(uint8_t Imm) { 491274955Ssvnmir uint64_t EncVal = Imm; 492274955Ssvnmir return (EncVal << 48) | (EncVal << 16); 493274955Ssvnmir} 494274955Ssvnmir 495274955Ssvnmir// abcdefgh 0x00 0x00 0x00 abcdefgh 0x00 0x00 0x00 496274955Ssvnmirstatic inline bool isAdvSIMDModImmType4(uint64_t Imm) { 497274955Ssvnmir return ((Imm >> 32) == (Imm & 0xffffffffULL)) && 498274955Ssvnmir ((Imm & 0x00ffffff00ffffffULL) == 0); 499274955Ssvnmir} 500274955Ssvnmir 501274955Ssvnmirstatic inline uint8_t encodeAdvSIMDModImmType4(uint64_t Imm) { 502274955Ssvnmir return (Imm & 0xff000000ULL) >> 24; 503274955Ssvnmir} 504274955Ssvnmir 505274955Ssvnmirstatic inline uint64_t decodeAdvSIMDModImmType4(uint8_t Imm) { 506274955Ssvnmir uint64_t EncVal = Imm; 507274955Ssvnmir return (EncVal << 56) | (EncVal << 24); 508274955Ssvnmir} 509274955Ssvnmir 510274955Ssvnmir// 0x00 abcdefgh 0x00 abcdefgh 0x00 abcdefgh 0x00 abcdefgh 511274955Ssvnmirstatic inline bool isAdvSIMDModImmType5(uint64_t Imm) { 512274955Ssvnmir return ((Imm >> 32) == (Imm & 0xffffffffULL)) && 513274955Ssvnmir (((Imm & 0x00ff0000ULL) >> 16) == (Imm & 0x000000ffULL)) && 514274955Ssvnmir ((Imm & 0xff00ff00ff00ff00ULL) == 0); 515274955Ssvnmir} 516274955Ssvnmir 517274955Ssvnmirstatic inline uint8_t encodeAdvSIMDModImmType5(uint64_t Imm) { 518274955Ssvnmir return (Imm & 0xffULL); 519274955Ssvnmir} 520274955Ssvnmir 521274955Ssvnmirstatic inline uint64_t decodeAdvSIMDModImmType5(uint8_t Imm) { 522274955Ssvnmir uint64_t EncVal = Imm; 523274955Ssvnmir return (EncVal << 48) | (EncVal << 32) | (EncVal << 16) | EncVal; 524274955Ssvnmir} 525274955Ssvnmir 526274955Ssvnmir// abcdefgh 0x00 abcdefgh 0x00 abcdefgh 0x00 abcdefgh 0x00 527274955Ssvnmirstatic inline bool isAdvSIMDModImmType6(uint64_t Imm) { 528274955Ssvnmir return ((Imm >> 32) == (Imm & 0xffffffffULL)) && 529274955Ssvnmir (((Imm & 0xff000000ULL) >> 16) == (Imm & 0x0000ff00ULL)) && 530274955Ssvnmir ((Imm & 0x00ff00ff00ff00ffULL) == 0); 531274955Ssvnmir} 532274955Ssvnmir 533274955Ssvnmirstatic inline uint8_t encodeAdvSIMDModImmType6(uint64_t Imm) { 534274955Ssvnmir return (Imm & 0xff00ULL) >> 8; 535274955Ssvnmir} 536274955Ssvnmir 537274955Ssvnmirstatic inline uint64_t decodeAdvSIMDModImmType6(uint8_t Imm) { 538274955Ssvnmir uint64_t EncVal = Imm; 539274955Ssvnmir return (EncVal << 56) | (EncVal << 40) | (EncVal << 24) | (EncVal << 8); 540274955Ssvnmir} 541274955Ssvnmir 542274955Ssvnmir// 0x00 0x00 abcdefgh 0xFF 0x00 0x00 abcdefgh 0xFF 543274955Ssvnmirstatic inline bool isAdvSIMDModImmType7(uint64_t Imm) { 544274955Ssvnmir return ((Imm >> 32) == (Imm & 0xffffffffULL)) && 545274955Ssvnmir ((Imm & 0xffff00ffffff00ffULL) == 0x000000ff000000ffULL); 546274955Ssvnmir} 547274955Ssvnmir 548274955Ssvnmirstatic inline uint8_t encodeAdvSIMDModImmType7(uint64_t Imm) { 549274955Ssvnmir return (Imm & 0xff00ULL) >> 8; 550274955Ssvnmir} 551274955Ssvnmir 552274955Ssvnmirstatic inline uint64_t decodeAdvSIMDModImmType7(uint8_t Imm) { 553274955Ssvnmir uint64_t EncVal = Imm; 554274955Ssvnmir return (EncVal << 40) | (EncVal << 8) | 0x000000ff000000ffULL; 555274955Ssvnmir} 556274955Ssvnmir 557274955Ssvnmir// 0x00 abcdefgh 0xFF 0xFF 0x00 abcdefgh 0xFF 0xFF 558274955Ssvnmirstatic inline bool isAdvSIMDModImmType8(uint64_t Imm) { 559274955Ssvnmir return ((Imm >> 32) == (Imm & 0xffffffffULL)) && 560274955Ssvnmir ((Imm & 0xff00ffffff00ffffULL) == 0x0000ffff0000ffffULL); 561274955Ssvnmir} 562274955Ssvnmir 563274955Ssvnmirstatic inline uint64_t decodeAdvSIMDModImmType8(uint8_t Imm) { 564274955Ssvnmir uint64_t EncVal = Imm; 565274955Ssvnmir return (EncVal << 48) | (EncVal << 16) | 0x0000ffff0000ffffULL; 566274955Ssvnmir} 567274955Ssvnmir 568274955Ssvnmirstatic inline uint8_t encodeAdvSIMDModImmType8(uint64_t Imm) { 569274955Ssvnmir return (Imm & 0x00ff0000ULL) >> 16; 570274955Ssvnmir} 571274955Ssvnmir 572274955Ssvnmir// abcdefgh abcdefgh abcdefgh abcdefgh abcdefgh abcdefgh abcdefgh abcdefgh 573274955Ssvnmirstatic inline bool isAdvSIMDModImmType9(uint64_t Imm) { 574274955Ssvnmir return ((Imm >> 32) == (Imm & 0xffffffffULL)) && 575274955Ssvnmir ((Imm >> 48) == (Imm & 0x0000ffffULL)) && 576274955Ssvnmir ((Imm >> 56) == (Imm & 0x000000ffULL)); 577274955Ssvnmir} 578274955Ssvnmir 579274955Ssvnmirstatic inline uint8_t encodeAdvSIMDModImmType9(uint64_t Imm) { 580274955Ssvnmir return (Imm & 0xffULL); 581274955Ssvnmir} 582274955Ssvnmir 583274955Ssvnmirstatic inline uint64_t decodeAdvSIMDModImmType9(uint8_t Imm) { 584274955Ssvnmir uint64_t EncVal = Imm; 585274955Ssvnmir EncVal |= (EncVal << 8); 586274955Ssvnmir EncVal |= (EncVal << 16); 587274955Ssvnmir EncVal |= (EncVal << 32); 588274955Ssvnmir return EncVal; 589274955Ssvnmir} 590274955Ssvnmir 591274955Ssvnmir// aaaaaaaa bbbbbbbb cccccccc dddddddd eeeeeeee ffffffff gggggggg hhhhhhhh 592274955Ssvnmir// cmode: 1110, op: 1 593274955Ssvnmirstatic inline bool isAdvSIMDModImmType10(uint64_t Imm) { 594274955Ssvnmir uint64_t ByteA = Imm & 0xff00000000000000ULL; 595274955Ssvnmir uint64_t ByteB = Imm & 0x00ff000000000000ULL; 596274955Ssvnmir uint64_t ByteC = Imm & 0x0000ff0000000000ULL; 597274955Ssvnmir uint64_t ByteD = Imm & 0x000000ff00000000ULL; 598274955Ssvnmir uint64_t ByteE = Imm & 0x00000000ff000000ULL; 599274955Ssvnmir uint64_t ByteF = Imm & 0x0000000000ff0000ULL; 600274955Ssvnmir uint64_t ByteG = Imm & 0x000000000000ff00ULL; 601274955Ssvnmir uint64_t ByteH = Imm & 0x00000000000000ffULL; 602274955Ssvnmir 603274955Ssvnmir return (ByteA == 0ULL || ByteA == 0xff00000000000000ULL) && 604274955Ssvnmir (ByteB == 0ULL || ByteB == 0x00ff000000000000ULL) && 605274955Ssvnmir (ByteC == 0ULL || ByteC == 0x0000ff0000000000ULL) && 606274955Ssvnmir (ByteD == 0ULL || ByteD == 0x000000ff00000000ULL) && 607274955Ssvnmir (ByteE == 0ULL || ByteE == 0x00000000ff000000ULL) && 608274955Ssvnmir (ByteF == 0ULL || ByteF == 0x0000000000ff0000ULL) && 609274955Ssvnmir (ByteG == 0ULL || ByteG == 0x000000000000ff00ULL) && 610274955Ssvnmir (ByteH == 0ULL || ByteH == 0x00000000000000ffULL); 611274955Ssvnmir} 612274955Ssvnmir 613274955Ssvnmirstatic inline uint8_t encodeAdvSIMDModImmType10(uint64_t Imm) { 614274955Ssvnmir uint8_t BitA = (Imm & 0xff00000000000000ULL) != 0; 615274955Ssvnmir uint8_t BitB = (Imm & 0x00ff000000000000ULL) != 0; 616274955Ssvnmir uint8_t BitC = (Imm & 0x0000ff0000000000ULL) != 0; 617274955Ssvnmir uint8_t BitD = (Imm & 0x000000ff00000000ULL) != 0; 618274955Ssvnmir uint8_t BitE = (Imm & 0x00000000ff000000ULL) != 0; 619274955Ssvnmir uint8_t BitF = (Imm & 0x0000000000ff0000ULL) != 0; 620274955Ssvnmir uint8_t BitG = (Imm & 0x000000000000ff00ULL) != 0; 621274955Ssvnmir uint8_t BitH = (Imm & 0x00000000000000ffULL) != 0; 622274955Ssvnmir 623274955Ssvnmir uint8_t EncVal = BitA; 624274955Ssvnmir EncVal <<= 1; 625274955Ssvnmir EncVal |= BitB; 626274955Ssvnmir EncVal <<= 1; 627274955Ssvnmir EncVal |= BitC; 628274955Ssvnmir EncVal <<= 1; 629274955Ssvnmir EncVal |= BitD; 630274955Ssvnmir EncVal <<= 1; 631274955Ssvnmir EncVal |= BitE; 632274955Ssvnmir EncVal <<= 1; 633274955Ssvnmir EncVal |= BitF; 634274955Ssvnmir EncVal <<= 1; 635274955Ssvnmir EncVal |= BitG; 636274955Ssvnmir EncVal <<= 1; 637274955Ssvnmir EncVal |= BitH; 638274955Ssvnmir return EncVal; 639274955Ssvnmir} 640274955Ssvnmir 641274955Ssvnmirstatic inline uint64_t decodeAdvSIMDModImmType10(uint8_t Imm) { 642274955Ssvnmir uint64_t EncVal = 0; 643274955Ssvnmir if (Imm & 0x80) EncVal |= 0xff00000000000000ULL; 644274955Ssvnmir if (Imm & 0x40) EncVal |= 0x00ff000000000000ULL; 645274955Ssvnmir if (Imm & 0x20) EncVal |= 0x0000ff0000000000ULL; 646274955Ssvnmir if (Imm & 0x10) EncVal |= 0x000000ff00000000ULL; 647274955Ssvnmir if (Imm & 0x08) EncVal |= 0x00000000ff000000ULL; 648274955Ssvnmir if (Imm & 0x04) EncVal |= 0x0000000000ff0000ULL; 649274955Ssvnmir if (Imm & 0x02) EncVal |= 0x000000000000ff00ULL; 650274955Ssvnmir if (Imm & 0x01) EncVal |= 0x00000000000000ffULL; 651274955Ssvnmir return EncVal; 652274955Ssvnmir} 653274955Ssvnmir 654274955Ssvnmir// aBbbbbbc defgh000 0x00 0x00 aBbbbbbc defgh000 0x00 0x00 655274955Ssvnmirstatic inline bool isAdvSIMDModImmType11(uint64_t Imm) { 656274955Ssvnmir uint64_t BString = (Imm & 0x7E000000ULL) >> 25; 657274955Ssvnmir return ((Imm >> 32) == (Imm & 0xffffffffULL)) && 658274955Ssvnmir (BString == 0x1f || BString == 0x20) && 659274955Ssvnmir ((Imm & 0x0007ffff0007ffffULL) == 0); 660274955Ssvnmir} 661274955Ssvnmir 662274955Ssvnmirstatic inline uint8_t encodeAdvSIMDModImmType11(uint64_t Imm) { 663274955Ssvnmir uint8_t BitA = (Imm & 0x80000000ULL) != 0; 664274955Ssvnmir uint8_t BitB = (Imm & 0x20000000ULL) != 0; 665274955Ssvnmir uint8_t BitC = (Imm & 0x01000000ULL) != 0; 666274955Ssvnmir uint8_t BitD = (Imm & 0x00800000ULL) != 0; 667274955Ssvnmir uint8_t BitE = (Imm & 0x00400000ULL) != 0; 668274955Ssvnmir uint8_t BitF = (Imm & 0x00200000ULL) != 0; 669274955Ssvnmir uint8_t BitG = (Imm & 0x00100000ULL) != 0; 670274955Ssvnmir uint8_t BitH = (Imm & 0x00080000ULL) != 0; 671274955Ssvnmir 672274955Ssvnmir uint8_t EncVal = BitA; 673274955Ssvnmir EncVal <<= 1; 674274955Ssvnmir EncVal |= BitB; 675274955Ssvnmir EncVal <<= 1; 676274955Ssvnmir EncVal |= BitC; 677274955Ssvnmir EncVal <<= 1; 678274955Ssvnmir EncVal |= BitD; 679274955Ssvnmir EncVal <<= 1; 680274955Ssvnmir EncVal |= BitE; 681274955Ssvnmir EncVal <<= 1; 682274955Ssvnmir EncVal |= BitF; 683274955Ssvnmir EncVal <<= 1; 684274955Ssvnmir EncVal |= BitG; 685274955Ssvnmir EncVal <<= 1; 686274955Ssvnmir EncVal |= BitH; 687274955Ssvnmir return EncVal; 688274955Ssvnmir} 689274955Ssvnmir 690274955Ssvnmirstatic inline uint64_t decodeAdvSIMDModImmType11(uint8_t Imm) { 691274955Ssvnmir uint64_t EncVal = 0; 692274955Ssvnmir if (Imm & 0x80) EncVal |= 0x80000000ULL; 693274955Ssvnmir if (Imm & 0x40) EncVal |= 0x3e000000ULL; 694274955Ssvnmir else EncVal |= 0x40000000ULL; 695274955Ssvnmir if (Imm & 0x20) EncVal |= 0x01000000ULL; 696274955Ssvnmir if (Imm & 0x10) EncVal |= 0x00800000ULL; 697274955Ssvnmir if (Imm & 0x08) EncVal |= 0x00400000ULL; 698274955Ssvnmir if (Imm & 0x04) EncVal |= 0x00200000ULL; 699274955Ssvnmir if (Imm & 0x02) EncVal |= 0x00100000ULL; 700274955Ssvnmir if (Imm & 0x01) EncVal |= 0x00080000ULL; 701274955Ssvnmir return (EncVal << 32) | EncVal; 702274955Ssvnmir} 703274955Ssvnmir 704274955Ssvnmir// aBbbbbbb bbcdefgh 0x00 0x00 0x00 0x00 0x00 0x00 705274955Ssvnmirstatic inline bool isAdvSIMDModImmType12(uint64_t Imm) { 706274955Ssvnmir uint64_t BString = (Imm & 0x7fc0000000000000ULL) >> 54; 707274955Ssvnmir return ((BString == 0xff || BString == 0x100) && 708274955Ssvnmir ((Imm & 0x0000ffffffffffffULL) == 0)); 709274955Ssvnmir} 710274955Ssvnmir 711274955Ssvnmirstatic inline uint8_t encodeAdvSIMDModImmType12(uint64_t Imm) { 712274955Ssvnmir uint8_t BitA = (Imm & 0x8000000000000000ULL) != 0; 713274955Ssvnmir uint8_t BitB = (Imm & 0x0040000000000000ULL) != 0; 714274955Ssvnmir uint8_t BitC = (Imm & 0x0020000000000000ULL) != 0; 715274955Ssvnmir uint8_t BitD = (Imm & 0x0010000000000000ULL) != 0; 716274955Ssvnmir uint8_t BitE = (Imm & 0x0008000000000000ULL) != 0; 717274955Ssvnmir uint8_t BitF = (Imm & 0x0004000000000000ULL) != 0; 718274955Ssvnmir uint8_t BitG = (Imm & 0x0002000000000000ULL) != 0; 719274955Ssvnmir uint8_t BitH = (Imm & 0x0001000000000000ULL) != 0; 720274955Ssvnmir 721274955Ssvnmir uint8_t EncVal = BitA; 722274955Ssvnmir EncVal <<= 1; 723274955Ssvnmir EncVal |= BitB; 724274955Ssvnmir EncVal <<= 1; 725274955Ssvnmir EncVal |= BitC; 726274955Ssvnmir EncVal <<= 1; 727274955Ssvnmir EncVal |= BitD; 728274955Ssvnmir EncVal <<= 1; 729274955Ssvnmir EncVal |= BitE; 730274955Ssvnmir EncVal <<= 1; 731274955Ssvnmir EncVal |= BitF; 732274955Ssvnmir EncVal <<= 1; 733274955Ssvnmir EncVal |= BitG; 734274955Ssvnmir EncVal <<= 1; 735274955Ssvnmir EncVal |= BitH; 736274955Ssvnmir return EncVal; 737274955Ssvnmir} 738274955Ssvnmir 739274955Ssvnmirstatic inline uint64_t decodeAdvSIMDModImmType12(uint8_t Imm) { 740274955Ssvnmir uint64_t EncVal = 0; 741274955Ssvnmir if (Imm & 0x80) EncVal |= 0x8000000000000000ULL; 742274955Ssvnmir if (Imm & 0x40) EncVal |= 0x3fc0000000000000ULL; 743274955Ssvnmir else EncVal |= 0x4000000000000000ULL; 744274955Ssvnmir if (Imm & 0x20) EncVal |= 0x0020000000000000ULL; 745274955Ssvnmir if (Imm & 0x10) EncVal |= 0x0010000000000000ULL; 746274955Ssvnmir if (Imm & 0x08) EncVal |= 0x0008000000000000ULL; 747274955Ssvnmir if (Imm & 0x04) EncVal |= 0x0004000000000000ULL; 748274955Ssvnmir if (Imm & 0x02) EncVal |= 0x0002000000000000ULL; 749274955Ssvnmir if (Imm & 0x01) EncVal |= 0x0001000000000000ULL; 750274955Ssvnmir return (EncVal << 32) | EncVal; 751274955Ssvnmir} 752274955Ssvnmir 753341825Sdim/// Returns true if Imm is the concatenation of a repeating pattern of type T. 754341825Sdimtemplate <typename T> 755341825Sdimstatic inline bool isSVEMaskOfIdenticalElements(int64_t Imm) { 756344779Sdim auto Parts = bit_cast<std::array<T, sizeof(int64_t) / sizeof(T)>>(Imm); 757344779Sdim return all_of(Parts, [&](T Elem) { return Elem == Parts[0]; }); 758341825Sdim} 759341825Sdim 760341825Sdim/// Returns true if Imm is valid for CPY/DUP. 761341825Sdimtemplate <typename T> 762341825Sdimstatic inline bool isSVECpyImm(int64_t Imm) { 763341825Sdim bool IsImm8 = int8_t(Imm) == Imm; 764341825Sdim bool IsImm16 = int16_t(Imm & ~0xff) == Imm; 765341825Sdim 766341825Sdim if (std::is_same<int8_t, typename std::make_signed<T>::type>::value) 767341825Sdim return IsImm8 || uint8_t(Imm) == Imm; 768341825Sdim 769341825Sdim if (std::is_same<int16_t, typename std::make_signed<T>::type>::value) 770341825Sdim return IsImm8 || IsImm16 || uint16_t(Imm & ~0xff) == Imm; 771341825Sdim 772341825Sdim return IsImm8 || IsImm16; 773341825Sdim} 774341825Sdim 775341825Sdim/// Returns true if Imm is valid for ADD/SUB. 776341825Sdimtemplate <typename T> 777341825Sdimstatic inline bool isSVEAddSubImm(int64_t Imm) { 778341825Sdim bool IsInt8t = 779341825Sdim std::is_same<int8_t, typename std::make_signed<T>::type>::value; 780341825Sdim return uint8_t(Imm) == Imm || (!IsInt8t && uint16_t(Imm & ~0xff) == Imm); 781341825Sdim} 782341825Sdim 783341825Sdim/// Return true if Imm is valid for DUPM and has no single CPY/DUP equivalent. 784341825Sdimstatic inline bool isSVEMoveMaskPreferredLogicalImmediate(int64_t Imm) { 785344779Sdim if (isSVECpyImm<int64_t>(Imm)) 786341825Sdim return false; 787341825Sdim 788344779Sdim auto S = bit_cast<std::array<int32_t, 2>>(Imm); 789344779Sdim auto H = bit_cast<std::array<int16_t, 4>>(Imm); 790344779Sdim auto B = bit_cast<std::array<int8_t, 8>>(Imm); 791341825Sdim 792344779Sdim if (isSVEMaskOfIdenticalElements<int32_t>(Imm) && isSVECpyImm<int32_t>(S[0])) 793341825Sdim return false; 794344779Sdim if (isSVEMaskOfIdenticalElements<int16_t>(Imm) && isSVECpyImm<int16_t>(H[0])) 795341825Sdim return false; 796344779Sdim if (isSVEMaskOfIdenticalElements<int8_t>(Imm) && isSVECpyImm<int8_t>(B[0])) 797344779Sdim return false; 798344779Sdim return isLogicalImmediate(Imm, 64); 799341825Sdim} 800341825Sdim 801309124Sdiminline static bool isAnyMOVZMovAlias(uint64_t Value, int RegWidth) { 802309124Sdim for (int Shift = 0; Shift <= RegWidth - 16; Shift += 16) 803309124Sdim if ((Value & ~(0xffffULL << Shift)) == 0) 804309124Sdim return true; 805309124Sdim 806309124Sdim return false; 807309124Sdim} 808309124Sdim 809309124Sdiminline static bool isMOVZMovAlias(uint64_t Value, int Shift, int RegWidth) { 810309124Sdim if (RegWidth == 32) 811309124Sdim Value &= 0xffffffffULL; 812309124Sdim 813309124Sdim // "lsl #0" takes precedence: in practice this only affects "#0, lsl #0". 814309124Sdim if (Value == 0 && Shift != 0) 815309124Sdim return false; 816309124Sdim 817309124Sdim return (Value & ~(0xffffULL << Shift)) == 0; 818309124Sdim} 819309124Sdim 820309124Sdiminline static bool isMOVNMovAlias(uint64_t Value, int Shift, int RegWidth) { 821309124Sdim // MOVZ takes precedence over MOVN. 822309124Sdim if (isAnyMOVZMovAlias(Value, RegWidth)) 823309124Sdim return false; 824309124Sdim 825309124Sdim Value = ~Value; 826309124Sdim if (RegWidth == 32) 827309124Sdim Value &= 0xffffffffULL; 828309124Sdim 829309124Sdim return isMOVZMovAlias(Value, Shift, RegWidth); 830309124Sdim} 831309124Sdim 832309124Sdiminline static bool isAnyMOVWMovAlias(uint64_t Value, int RegWidth) { 833309124Sdim if (isAnyMOVZMovAlias(Value, RegWidth)) 834309124Sdim return true; 835309124Sdim 836309124Sdim // It's not a MOVZ, but it might be a MOVN. 837309124Sdim Value = ~Value; 838309124Sdim if (RegWidth == 32) 839309124Sdim Value &= 0xffffffffULL; 840309124Sdim 841309124Sdim return isAnyMOVZMovAlias(Value, RegWidth); 842309124Sdim} 843309124Sdim 844274955Ssvnmir} // end namespace AArch64_AM 845274955Ssvnmir 846274955Ssvnmir} // end namespace llvm 847274955Ssvnmir 848274955Ssvnmir#endif 849