brintos

brintos / llvm-project-archived public Read only

0
0
Text · 28.7 KiB · 4ae5d04 Raw
909 lines · c
1//===- AArch64AddressingModes.h - AArch64 Addressing Modes ------*- C++ -*-===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8//9// This file contains the AArch64 addressing mode implementation stuff.10//11//===----------------------------------------------------------------------===//12 13#ifndef LLVM_LIB_TARGET_AARCH64_MCTARGETDESC_AARCH64ADDRESSINGMODES_H14#define LLVM_LIB_TARGET_AARCH64_MCTARGETDESC_AARCH64ADDRESSINGMODES_H15 16#include "llvm/ADT/APFloat.h"17#include "llvm/ADT/APInt.h"18#include "llvm/ADT/bit.h"19#include "llvm/Support/ErrorHandling.h"20#include "llvm/Support/MathExtras.h"21#include <cassert>22 23namespace llvm {24 25/// AArch64_AM - AArch64 Addressing Mode Stuff26namespace AArch64_AM {27 28//===----------------------------------------------------------------------===//29// Shifts30//31 32enum ShiftExtendType {33  InvalidShiftExtend = -1,34  LSL = 0,35  LSR,36  ASR,37  ROR,38  MSL,39 40  UXTB,41  UXTH,42  UXTW,43  UXTX,44 45  SXTB,46  SXTH,47  SXTW,48  SXTX,49};50 51/// getShiftName - Get the string encoding for the shift type.52static inline const char *getShiftExtendName(AArch64_AM::ShiftExtendType ST) {53  switch (ST) {54  default: llvm_unreachable("unhandled shift type!");55  case AArch64_AM::LSL: return "lsl";56  case AArch64_AM::LSR: return "lsr";57  case AArch64_AM::ASR: return "asr";58  case AArch64_AM::ROR: return "ror";59  case AArch64_AM::MSL: return "msl";60  case AArch64_AM::UXTB: return "uxtb";61  case AArch64_AM::UXTH: return "uxth";62  case AArch64_AM::UXTW: return "uxtw";63  case AArch64_AM::UXTX: return "uxtx";64  case AArch64_AM::SXTB: return "sxtb";65  case AArch64_AM::SXTH: return "sxth";66  case AArch64_AM::SXTW: return "sxtw";67  case AArch64_AM::SXTX: return "sxtx";68  }69  return nullptr;70}71 72/// getShiftType - Extract the shift type.73static inline AArch64_AM::ShiftExtendType getShiftType(unsigned Imm) {74  switch ((Imm >> 6) & 0x7) {75  default: return AArch64_AM::InvalidShiftExtend;76  case 0: return AArch64_AM::LSL;77  case 1: return AArch64_AM::LSR;78  case 2: return AArch64_AM::ASR;79  case 3: return AArch64_AM::ROR;80  case 4: return AArch64_AM::MSL;81  }82}83 84/// getShiftValue - Extract the shift value.85static inline unsigned getShiftValue(unsigned Imm) {86  return Imm & 0x3f;87}88 89/// getShifterImm - Encode the shift type and amount:90///   imm:     6-bit shift amount91///   shifter: 000 ==> lsl92///            001 ==> lsr93///            010 ==> asr94///            011 ==> ror95///            100 ==> msl96///   {8-6}  = shifter97///   {5-0}  = imm98static inline unsigned getShifterImm(AArch64_AM::ShiftExtendType ST,99                                     unsigned Imm) {100  assert((Imm & 0x3f) == Imm && "Illegal shifted immediate value!");101  unsigned STEnc = 0;102  switch (ST) {103  default:  llvm_unreachable("Invalid shift requested");104  case AArch64_AM::LSL: STEnc = 0; break;105  case AArch64_AM::LSR: STEnc = 1; break;106  case AArch64_AM::ASR: STEnc = 2; break;107  case AArch64_AM::ROR: STEnc = 3; break;108  case AArch64_AM::MSL: STEnc = 4; break;109  }110  return (STEnc << 6) | (Imm & 0x3f);111}112 113//===----------------------------------------------------------------------===//114// Extends115//116 117/// getArithShiftValue - get the arithmetic shift value.118static inline unsigned getArithShiftValue(unsigned Imm) {119  return Imm & 0x7;120}121 122/// getExtendType - Extract the extend type for operands of arithmetic ops.123static inline AArch64_AM::ShiftExtendType getExtendType(unsigned Imm) {124  assert((Imm & 0x7) == Imm && "invalid immediate!");125  switch (Imm) {126  default: llvm_unreachable("Compiler bug!");127  case 0: return AArch64_AM::UXTB;128  case 1: return AArch64_AM::UXTH;129  case 2: return AArch64_AM::UXTW;130  case 3: return AArch64_AM::UXTX;131  case 4: return AArch64_AM::SXTB;132  case 5: return AArch64_AM::SXTH;133  case 6: return AArch64_AM::SXTW;134  case 7: return AArch64_AM::SXTX;135  }136}137 138static inline AArch64_AM::ShiftExtendType getArithExtendType(unsigned Imm) {139  return getExtendType((Imm >> 3) & 0x7);140}141 142/// Mapping from extend bits to required operation:143///   shifter: 000 ==> uxtb144///            001 ==> uxth145///            010 ==> uxtw146///            011 ==> uxtx147///            100 ==> sxtb148///            101 ==> sxth149///            110 ==> sxtw150///            111 ==> sxtx151inline unsigned getExtendEncoding(AArch64_AM::ShiftExtendType ET) {152  switch (ET) {153  default: llvm_unreachable("Invalid extend type requested");154  case AArch64_AM::UXTB: return 0; break;155  case AArch64_AM::UXTH: return 1; break;156  case AArch64_AM::UXTW: return 2; break;157  case AArch64_AM::UXTX: return 3; break;158  case AArch64_AM::SXTB: return 4; break;159  case AArch64_AM::SXTH: return 5; break;160  case AArch64_AM::SXTW: return 6; break;161  case AArch64_AM::SXTX: return 7; break;162  }163}164 165/// getArithExtendImm - Encode the extend type and shift amount for an166///                     arithmetic instruction:167///   imm:     3-bit extend amount168///   {5-3}  = shifter169///   {2-0}  = imm3170static inline unsigned getArithExtendImm(AArch64_AM::ShiftExtendType ET,171                                         unsigned Imm) {172  assert((Imm & 0x7) == Imm && "Illegal shifted immediate value!");173  return (getExtendEncoding(ET) << 3) | (Imm & 0x7);174}175 176/// getMemDoShift - Extract the "do shift" flag value for load/store177/// instructions.178static inline bool getMemDoShift(unsigned Imm) {179  return (Imm & 0x1) != 0;180}181 182/// getExtendType - Extract the extend type for the offset operand of183/// loads/stores.184static inline AArch64_AM::ShiftExtendType getMemExtendType(unsigned Imm) {185  return getExtendType((Imm >> 1) & 0x7);186}187 188/// getExtendImm - Encode the extend type and amount for a load/store inst:189///   doshift:     should the offset be scaled by the access size190///   shifter: 000 ==> uxtb191///            001 ==> uxth192///            010 ==> uxtw193///            011 ==> uxtx194///            100 ==> sxtb195///            101 ==> sxth196///            110 ==> sxtw197///            111 ==> sxtx198///   {3-1}  = shifter199///   {0}  = doshift200static inline unsigned getMemExtendImm(AArch64_AM::ShiftExtendType ET,201                                       bool DoShift) {202  return (getExtendEncoding(ET) << 1) | unsigned(DoShift);203}204 205static inline uint64_t ror(uint64_t elt, unsigned size) {206  return ((elt & 1) << (size-1)) | (elt >> 1);207}208 209/// processLogicalImmediate - Determine if an immediate value can be encoded210/// as the immediate operand of a logical instruction for the given register211/// size.  If so, return true with "encoding" set to the encoded value in212/// the form N:immr:imms.213static inline bool processLogicalImmediate(uint64_t Imm, unsigned RegSize,214                                           uint64_t &Encoding) {215  if (Imm == 0ULL || Imm == ~0ULL ||216      (RegSize != 64 &&217        (Imm >> RegSize != 0 || Imm == (~0ULL >> (64 - RegSize)))))218    return false;219 220  // First, determine the element size.221  unsigned Size = RegSize;222 223  do {224    Size /= 2;225    uint64_t Mask = (1ULL << Size) - 1;226 227    if ((Imm & Mask) != ((Imm >> Size) & Mask)) {228      Size *= 2;229      break;230    }231  } while (Size > 2);232 233  // Second, determine the rotation to make the element be: 0^m 1^n.234  uint32_t CTO, I;235  uint64_t Mask = ((uint64_t)-1LL) >> (64 - Size);236  Imm &= Mask;237 238  if (isShiftedMask_64(Imm)) {239    I = llvm::countr_zero(Imm);240    assert(I < 64 && "undefined behavior");241    CTO = llvm::countr_one(Imm >> I);242  } else {243    Imm |= ~Mask;244    if (!isShiftedMask_64(~Imm))245      return false;246 247    unsigned CLO = llvm::countl_one(Imm);248    I = 64 - CLO;249    CTO = CLO + llvm::countr_one(Imm) - (64 - Size);250  }251 252  // Encode in Immr the number of RORs it would take to get *from* 0^m 1^n253  // to our target value, where I is the number of RORs to go the opposite254  // direction.255  assert(Size > I && "I should be smaller than element size");256  unsigned Immr = (Size - I) & (Size - 1);257 258  // If size has a 1 in the n'th bit, create a value that has zeroes in259  // bits [0, n] and ones above that.260  uint64_t NImms = ~(Size-1) << 1;261 262  // Or the CTO value into the low bits, which must be below the Nth bit263  // bit mentioned above.264  NImms |= (CTO-1);265 266  // Extract the seventh bit and toggle it to create the N field.267  unsigned N = ((NImms >> 6) & 1) ^ 1;268 269  Encoding = (N << 12) | (Immr << 6) | (NImms & 0x3f);270  return true;271}272 273/// isLogicalImmediate - Return true if the immediate is valid for a logical274/// immediate instruction of the given register size. Return false otherwise.275static inline bool isLogicalImmediate(uint64_t imm, unsigned regSize) {276  uint64_t encoding;277  return processLogicalImmediate(imm, regSize, encoding);278}279 280/// encodeLogicalImmediate - Return the encoded immediate value for a logical281/// immediate instruction of the given register size.282static inline uint64_t encodeLogicalImmediate(uint64_t imm, unsigned regSize) {283  uint64_t encoding = 0;284  bool res = processLogicalImmediate(imm, regSize, encoding);285  assert(res && "invalid logical immediate");286  (void)res;287  return encoding;288}289 290/// decodeLogicalImmediate - Decode a logical immediate value in the form291/// "N:immr:imms" (where the immr and imms fields are each 6 bits) into the292/// integer value it represents with regSize bits.293static inline uint64_t decodeLogicalImmediate(uint64_t val, unsigned regSize) {294  // Extract the N, imms, and immr fields.295  unsigned N = (val >> 12) & 1;296  unsigned immr = (val >> 6) & 0x3f;297  unsigned imms = val & 0x3f;298 299  assert((regSize == 64 || N == 0) && "undefined logical immediate encoding");300  int len = 31 - llvm::countl_zero((N << 6) | (~imms & 0x3f));301  assert(len >= 0 && "undefined logical immediate encoding");302  unsigned size = (1 << len);303  unsigned R = immr & (size - 1);304  unsigned S = imms & (size - 1);305  assert(S != size - 1 && "undefined logical immediate encoding");306  uint64_t pattern = (1ULL << (S + 1)) - 1;307  for (unsigned i = 0; i < R; ++i)308    pattern = ror(pattern, size);309 310  // Replicate the pattern to fill the regSize.311  while (size != regSize) {312    pattern |= (pattern << size);313    size *= 2;314  }315  return pattern;316}317 318/// isValidDecodeLogicalImmediate - Check to see if the logical immediate value319/// in the form "N:immr:imms" (where the immr and imms fields are each 6 bits)320/// is a valid encoding for an integer value with regSize bits.321static inline bool isValidDecodeLogicalImmediate(uint64_t val,322                                                 unsigned regSize) {323  // Extract the N and imms fields needed for checking.324  unsigned N = (val >> 12) & 1;325  unsigned imms = val & 0x3f;326 327  if (regSize == 32 && N != 0) // undefined logical immediate encoding328    return false;329  int len = 31 - llvm::countl_zero((N << 6) | (~imms & 0x3f));330  if (len < 0) // undefined logical immediate encoding331    return false;332  unsigned size = (1 << len);333  unsigned S = imms & (size - 1);334  if (S == size - 1) // undefined logical immediate encoding335    return false;336 337  return true;338}339 340//===----------------------------------------------------------------------===//341// Floating-point Immediates342//343static inline float getFPImmFloat(unsigned Imm) {344  // We expect an 8-bit binary encoding of a floating-point number here.345 346  uint8_t Sign = (Imm >> 7) & 0x1;347  uint8_t Exp = (Imm >> 4) & 0x7;348  uint8_t Mantissa = Imm & 0xf;349 350  //   8-bit FP    IEEE Float Encoding351  //   abcd efgh   aBbbbbbc defgh000 00000000 00000000352  //353  // where B = NOT(b);354 355  uint32_t I = 0;356  I |= Sign << 31;357  I |= ((Exp & 0x4) != 0 ? 0 : 1) << 30;358  I |= ((Exp & 0x4) != 0 ? 0x1f : 0) << 25;359  I |= (Exp & 0x3) << 23;360  I |= Mantissa << 19;361  return bit_cast<float>(I);362}363 364/// getFP16Imm - Return an 8-bit floating-point version of the 16-bit365/// floating-point value. If the value cannot be represented as an 8-bit366/// floating-point value, then return -1.367static inline int getFP16Imm(const APInt &Imm) {368  uint32_t Sign = Imm.lshr(15).getZExtValue() & 1;369  int32_t Exp = (Imm.lshr(10).getSExtValue() & 0x1f) - 15;  // -14 to 15370  int32_t Mantissa = Imm.getZExtValue() & 0x3ff;  // 10 bits371 372  // We can handle 4 bits of mantissa.373  // mantissa = (16+UInt(e:f:g:h))/16.374  if (Mantissa & 0x3f)375    return -1;376  Mantissa >>= 6;377 378  // We can handle 3 bits of exponent: exp == UInt(NOT(b):c:d)-3379  if (Exp < -3 || Exp > 4)380    return -1;381  Exp = ((Exp+3) & 0x7) ^ 4;382 383  return ((int)Sign << 7) | (Exp << 4) | Mantissa;384}385 386static inline int getFP16Imm(const APFloat &FPImm) {387  return getFP16Imm(FPImm.bitcastToAPInt());388}389 390/// getFP32Imm - Return an 8-bit floating-point version of the 32-bit391/// floating-point value. If the value cannot be represented as an 8-bit392/// floating-point value, then return -1.393static inline int getFP32Imm(const APInt &Imm) {394  uint32_t Sign = Imm.lshr(31).getZExtValue() & 1;395  int32_t Exp = (Imm.lshr(23).getSExtValue() & 0xff) - 127;  // -126 to 127396  int64_t Mantissa = Imm.getZExtValue() & 0x7fffff;  // 23 bits397 398  // We can handle 4 bits of mantissa.399  // mantissa = (16+UInt(e:f:g:h))/16.400  if (Mantissa & 0x7ffff)401    return -1;402  Mantissa >>= 19;403  if ((Mantissa & 0xf) != Mantissa)404    return -1;405 406  // We can handle 3 bits of exponent: exp == UInt(NOT(b):c:d)-3407  if (Exp < -3 || Exp > 4)408    return -1;409  Exp = ((Exp+3) & 0x7) ^ 4;410 411  return ((int)Sign << 7) | (Exp << 4) | Mantissa;412}413 414static inline int getFP32Imm(const APFloat &FPImm) {415  return getFP32Imm(FPImm.bitcastToAPInt());416}417 418/// getFP64Imm - Return an 8-bit floating-point version of the 64-bit419/// floating-point value. If the value cannot be represented as an 8-bit420/// floating-point value, then return -1.421static inline int getFP64Imm(const APInt &Imm) {422  uint64_t Sign = Imm.lshr(63).getZExtValue() & 1;423  int64_t Exp = (Imm.lshr(52).getSExtValue() & 0x7ff) - 1023;   // -1022 to 1023424  uint64_t Mantissa = Imm.getZExtValue() & 0xfffffffffffffULL;425 426  // We can handle 4 bits of mantissa.427  // mantissa = (16+UInt(e:f:g:h))/16.428  if (Mantissa & 0xffffffffffffULL)429    return -1;430  Mantissa >>= 48;431  if ((Mantissa & 0xf) != Mantissa)432    return -1;433 434  // We can handle 3 bits of exponent: exp == UInt(NOT(b):c:d)-3435  if (Exp < -3 || Exp > 4)436    return -1;437  Exp = ((Exp+3) & 0x7) ^ 4;438 439  return ((int)Sign << 7) | (Exp << 4) | Mantissa;440}441 442static inline int getFP64Imm(const APFloat &FPImm) {443  return getFP64Imm(FPImm.bitcastToAPInt());444}445 446//===--------------------------------------------------------------------===//447// AdvSIMD Modified Immediates448//===--------------------------------------------------------------------===//449 450// 0x00 0x00 0x00 abcdefgh 0x00 0x00 0x00 abcdefgh451static inline bool isAdvSIMDModImmType1(uint64_t Imm) {452  return ((Imm >> 32) == (Imm & 0xffffffffULL)) &&453         ((Imm & 0xffffff00ffffff00ULL) == 0);454}455 456static inline uint8_t encodeAdvSIMDModImmType1(uint64_t Imm) {457  return (Imm & 0xffULL);458}459 460static inline uint64_t decodeAdvSIMDModImmType1(uint8_t Imm) {461  uint64_t EncVal = Imm;462  return (EncVal << 32) | EncVal;463}464 465// 0x00 0x00 abcdefgh 0x00 0x00 0x00 abcdefgh 0x00466static inline bool isAdvSIMDModImmType2(uint64_t Imm) {467  return ((Imm >> 32) == (Imm & 0xffffffffULL)) &&468         ((Imm & 0xffff00ffffff00ffULL) == 0);469}470 471static inline uint8_t encodeAdvSIMDModImmType2(uint64_t Imm) {472  return (Imm & 0xff00ULL) >> 8;473}474 475static inline uint64_t decodeAdvSIMDModImmType2(uint8_t Imm) {476  uint64_t EncVal = Imm;477  return (EncVal << 40) | (EncVal << 8);478}479 480// 0x00 abcdefgh 0x00 0x00 0x00 abcdefgh 0x00 0x00481static inline bool isAdvSIMDModImmType3(uint64_t Imm) {482  return ((Imm >> 32) == (Imm & 0xffffffffULL)) &&483         ((Imm & 0xff00ffffff00ffffULL) == 0);484}485 486static inline uint8_t encodeAdvSIMDModImmType3(uint64_t Imm) {487  return (Imm & 0xff0000ULL) >> 16;488}489 490static inline uint64_t decodeAdvSIMDModImmType3(uint8_t Imm) {491  uint64_t EncVal = Imm;492  return (EncVal << 48) | (EncVal << 16);493}494 495// abcdefgh 0x00 0x00 0x00 abcdefgh 0x00 0x00 0x00496static inline bool isAdvSIMDModImmType4(uint64_t Imm) {497  return ((Imm >> 32) == (Imm & 0xffffffffULL)) &&498         ((Imm & 0x00ffffff00ffffffULL) == 0);499}500 501static inline uint8_t encodeAdvSIMDModImmType4(uint64_t Imm) {502  return (Imm & 0xff000000ULL) >> 24;503}504 505static inline uint64_t decodeAdvSIMDModImmType4(uint8_t Imm) {506  uint64_t EncVal = Imm;507  return (EncVal << 56) | (EncVal << 24);508}509 510// 0x00 abcdefgh 0x00 abcdefgh 0x00 abcdefgh 0x00 abcdefgh511static inline bool isAdvSIMDModImmType5(uint64_t Imm) {512  return ((Imm >> 32) == (Imm & 0xffffffffULL)) &&513         (((Imm & 0x00ff0000ULL) >> 16) == (Imm & 0x000000ffULL)) &&514         ((Imm & 0xff00ff00ff00ff00ULL) == 0);515}516 517static inline uint8_t encodeAdvSIMDModImmType5(uint64_t Imm) {518  return (Imm & 0xffULL);519}520 521static inline uint64_t decodeAdvSIMDModImmType5(uint8_t Imm) {522  uint64_t EncVal = Imm;523  return (EncVal << 48) | (EncVal << 32) | (EncVal << 16) | EncVal;524}525 526// abcdefgh 0x00 abcdefgh 0x00 abcdefgh 0x00 abcdefgh 0x00527static inline bool isAdvSIMDModImmType6(uint64_t Imm) {528  return ((Imm >> 32) == (Imm & 0xffffffffULL)) &&529         (((Imm & 0xff000000ULL) >> 16) == (Imm & 0x0000ff00ULL)) &&530         ((Imm & 0x00ff00ff00ff00ffULL) == 0);531}532 533static inline uint8_t encodeAdvSIMDModImmType6(uint64_t Imm) {534  return (Imm & 0xff00ULL) >> 8;535}536 537static inline uint64_t decodeAdvSIMDModImmType6(uint8_t Imm) {538  uint64_t EncVal = Imm;539  return (EncVal << 56) | (EncVal << 40) | (EncVal << 24) | (EncVal << 8);540}541 542// 0x00 0x00 abcdefgh 0xFF 0x00 0x00 abcdefgh 0xFF543static inline bool isAdvSIMDModImmType7(uint64_t Imm) {544  return ((Imm >> 32) == (Imm & 0xffffffffULL)) &&545         ((Imm & 0xffff00ffffff00ffULL) == 0x000000ff000000ffULL);546}547 548static inline uint8_t encodeAdvSIMDModImmType7(uint64_t Imm) {549  return (Imm & 0xff00ULL) >> 8;550}551 552static inline uint64_t decodeAdvSIMDModImmType7(uint8_t Imm) {553  uint64_t EncVal = Imm;554  return (EncVal << 40) | (EncVal << 8) | 0x000000ff000000ffULL;555}556 557// 0x00 abcdefgh 0xFF 0xFF 0x00 abcdefgh 0xFF 0xFF558static inline bool isAdvSIMDModImmType8(uint64_t Imm) {559  return ((Imm >> 32) == (Imm & 0xffffffffULL)) &&560         ((Imm & 0xff00ffffff00ffffULL) == 0x0000ffff0000ffffULL);561}562 563static inline uint64_t decodeAdvSIMDModImmType8(uint8_t Imm) {564  uint64_t EncVal = Imm;565  return (EncVal << 48) | (EncVal << 16) | 0x0000ffff0000ffffULL;566}567 568static inline uint8_t encodeAdvSIMDModImmType8(uint64_t Imm) {569  return (Imm & 0x00ff0000ULL) >> 16;570}571 572// abcdefgh abcdefgh abcdefgh abcdefgh abcdefgh abcdefgh abcdefgh abcdefgh573static inline bool isAdvSIMDModImmType9(uint64_t Imm) {574  return ((Imm >> 32) == (Imm & 0xffffffffULL)) &&575         ((Imm >> 48) == (Imm & 0x0000ffffULL)) &&576         ((Imm >> 56) == (Imm & 0x000000ffULL));577}578 579static inline uint8_t encodeAdvSIMDModImmType9(uint64_t Imm) {580  return (Imm & 0xffULL);581}582 583static inline uint64_t decodeAdvSIMDModImmType9(uint8_t Imm) {584  uint64_t EncVal = Imm;585  EncVal |= (EncVal << 8);586  EncVal |= (EncVal << 16);587  EncVal |= (EncVal << 32);588  return EncVal;589}590 591// aaaaaaaa bbbbbbbb cccccccc dddddddd eeeeeeee ffffffff gggggggg hhhhhhhh592// cmode: 1110, op: 1593static inline bool isAdvSIMDModImmType10(uint64_t Imm) {594#if defined(_MSC_VER) && _MSC_VER == 1937 && !defined(__clang__) &&            \595    defined(_M_ARM64)596  // The MSVC compiler 19.37 for ARM64 has an optimization bug that597  // causes an incorrect behavior with the original version. Work around598  // by using a slightly different variation.599  // https://developercommunity.visualstudio.com/t/C-ARM64-compiler-optimization-bug/10481261600  constexpr uint64_t Mask = 0xFFULL;601  uint64_t ByteA = (Imm >> 56) & Mask;602  uint64_t ByteB = (Imm >> 48) & Mask;603  uint64_t ByteC = (Imm >> 40) & Mask;604  uint64_t ByteD = (Imm >> 32) & Mask;605  uint64_t ByteE = (Imm >> 24) & Mask;606  uint64_t ByteF = (Imm >> 16) & Mask;607  uint64_t ByteG = (Imm >> 8) & Mask;608  uint64_t ByteH = Imm & Mask;609 610  return (ByteA == 0ULL || ByteA == Mask) && (ByteB == 0ULL || ByteB == Mask) &&611         (ByteC == 0ULL || ByteC == Mask) && (ByteD == 0ULL || ByteD == Mask) &&612         (ByteE == 0ULL || ByteE == Mask) && (ByteF == 0ULL || ByteF == Mask) &&613         (ByteG == 0ULL || ByteG == Mask) && (ByteH == 0ULL || ByteH == Mask);614#else615  uint64_t ByteA = Imm & 0xff00000000000000ULL;616  uint64_t ByteB = Imm & 0x00ff000000000000ULL;617  uint64_t ByteC = Imm & 0x0000ff0000000000ULL;618  uint64_t ByteD = Imm & 0x000000ff00000000ULL;619  uint64_t ByteE = Imm & 0x00000000ff000000ULL;620  uint64_t ByteF = Imm & 0x0000000000ff0000ULL;621  uint64_t ByteG = Imm & 0x000000000000ff00ULL;622  uint64_t ByteH = Imm & 0x00000000000000ffULL;623 624  return (ByteA == 0ULL || ByteA == 0xff00000000000000ULL) &&625         (ByteB == 0ULL || ByteB == 0x00ff000000000000ULL) &&626         (ByteC == 0ULL || ByteC == 0x0000ff0000000000ULL) &&627         (ByteD == 0ULL || ByteD == 0x000000ff00000000ULL) &&628         (ByteE == 0ULL || ByteE == 0x00000000ff000000ULL) &&629         (ByteF == 0ULL || ByteF == 0x0000000000ff0000ULL) &&630         (ByteG == 0ULL || ByteG == 0x000000000000ff00ULL) &&631         (ByteH == 0ULL || ByteH == 0x00000000000000ffULL);632#endif633}634 635static inline uint8_t encodeAdvSIMDModImmType10(uint64_t Imm) {636  uint8_t BitA = (Imm & 0xff00000000000000ULL) != 0;637  uint8_t BitB = (Imm & 0x00ff000000000000ULL) != 0;638  uint8_t BitC = (Imm & 0x0000ff0000000000ULL) != 0;639  uint8_t BitD = (Imm & 0x000000ff00000000ULL) != 0;640  uint8_t BitE = (Imm & 0x00000000ff000000ULL) != 0;641  uint8_t BitF = (Imm & 0x0000000000ff0000ULL) != 0;642  uint8_t BitG = (Imm & 0x000000000000ff00ULL) != 0;643  uint8_t BitH = (Imm & 0x00000000000000ffULL) != 0;644 645  uint8_t EncVal = BitA;646  EncVal <<= 1;647  EncVal |= BitB;648  EncVal <<= 1;649  EncVal |= BitC;650  EncVal <<= 1;651  EncVal |= BitD;652  EncVal <<= 1;653  EncVal |= BitE;654  EncVal <<= 1;655  EncVal |= BitF;656  EncVal <<= 1;657  EncVal |= BitG;658  EncVal <<= 1;659  EncVal |= BitH;660  return EncVal;661}662 663static inline uint64_t decodeAdvSIMDModImmType10(uint8_t Imm) {664  uint64_t EncVal = 0;665  if (Imm & 0x80) EncVal |= 0xff00000000000000ULL;666  if (Imm & 0x40) EncVal |= 0x00ff000000000000ULL;667  if (Imm & 0x20) EncVal |= 0x0000ff0000000000ULL;668  if (Imm & 0x10) EncVal |= 0x000000ff00000000ULL;669  if (Imm & 0x08) EncVal |= 0x00000000ff000000ULL;670  if (Imm & 0x04) EncVal |= 0x0000000000ff0000ULL;671  if (Imm & 0x02) EncVal |= 0x000000000000ff00ULL;672  if (Imm & 0x01) EncVal |= 0x00000000000000ffULL;673  return EncVal;674}675 676// aBbbbbbc defgh000 0x00 0x00 aBbbbbbc defgh000 0x00 0x00677static inline bool isAdvSIMDModImmType11(uint64_t Imm) {678  uint64_t BString = (Imm & 0x7E000000ULL) >> 25;679  return ((Imm >> 32) == (Imm & 0xffffffffULL)) &&680         (BString == 0x1f || BString == 0x20) &&681         ((Imm & 0x0007ffff0007ffffULL) == 0);682}683 684static inline uint8_t encodeAdvSIMDModImmType11(uint64_t Imm) {685  uint8_t BitA = (Imm & 0x80000000ULL) != 0;686  uint8_t BitB = (Imm & 0x20000000ULL) != 0;687  uint8_t BitC = (Imm & 0x01000000ULL) != 0;688  uint8_t BitD = (Imm & 0x00800000ULL) != 0;689  uint8_t BitE = (Imm & 0x00400000ULL) != 0;690  uint8_t BitF = (Imm & 0x00200000ULL) != 0;691  uint8_t BitG = (Imm & 0x00100000ULL) != 0;692  uint8_t BitH = (Imm & 0x00080000ULL) != 0;693 694  uint8_t EncVal = BitA;695  EncVal <<= 1;696  EncVal |= BitB;697  EncVal <<= 1;698  EncVal |= BitC;699  EncVal <<= 1;700  EncVal |= BitD;701  EncVal <<= 1;702  EncVal |= BitE;703  EncVal <<= 1;704  EncVal |= BitF;705  EncVal <<= 1;706  EncVal |= BitG;707  EncVal <<= 1;708  EncVal |= BitH;709  return EncVal;710}711 712static inline uint64_t decodeAdvSIMDModImmType11(uint8_t Imm) {713  uint64_t EncVal = 0;714  if (Imm & 0x80) EncVal |= 0x80000000ULL;715  if (Imm & 0x40) EncVal |= 0x3e000000ULL;716  else            EncVal |= 0x40000000ULL;717  if (Imm & 0x20) EncVal |= 0x01000000ULL;718  if (Imm & 0x10) EncVal |= 0x00800000ULL;719  if (Imm & 0x08) EncVal |= 0x00400000ULL;720  if (Imm & 0x04) EncVal |= 0x00200000ULL;721  if (Imm & 0x02) EncVal |= 0x00100000ULL;722  if (Imm & 0x01) EncVal |= 0x00080000ULL;723  return (EncVal << 32) | EncVal;724}725 726// aBbbbbbb bbcdefgh 0x00 0x00 0x00 0x00 0x00 0x00727static inline bool isAdvSIMDModImmType12(uint64_t Imm) {728  uint64_t BString = (Imm & 0x7fc0000000000000ULL) >> 54;729  return ((BString == 0xff || BString == 0x100) &&730         ((Imm & 0x0000ffffffffffffULL) == 0));731}732 733static inline uint8_t encodeAdvSIMDModImmType12(uint64_t Imm) {734  uint8_t BitA = (Imm & 0x8000000000000000ULL) != 0;735  uint8_t BitB = (Imm & 0x0040000000000000ULL) != 0;736  uint8_t BitC = (Imm & 0x0020000000000000ULL) != 0;737  uint8_t BitD = (Imm & 0x0010000000000000ULL) != 0;738  uint8_t BitE = (Imm & 0x0008000000000000ULL) != 0;739  uint8_t BitF = (Imm & 0x0004000000000000ULL) != 0;740  uint8_t BitG = (Imm & 0x0002000000000000ULL) != 0;741  uint8_t BitH = (Imm & 0x0001000000000000ULL) != 0;742 743  uint8_t EncVal = BitA;744  EncVal <<= 1;745  EncVal |= BitB;746  EncVal <<= 1;747  EncVal |= BitC;748  EncVal <<= 1;749  EncVal |= BitD;750  EncVal <<= 1;751  EncVal |= BitE;752  EncVal <<= 1;753  EncVal |= BitF;754  EncVal <<= 1;755  EncVal |= BitG;756  EncVal <<= 1;757  EncVal |= BitH;758  return EncVal;759}760 761static inline uint64_t decodeAdvSIMDModImmType12(uint8_t Imm) {762  uint64_t EncVal = 0;763  if (Imm & 0x80) EncVal |= 0x8000000000000000ULL;764  if (Imm & 0x40) EncVal |= 0x3fc0000000000000ULL;765  else            EncVal |= 0x4000000000000000ULL;766  if (Imm & 0x20) EncVal |= 0x0020000000000000ULL;767  if (Imm & 0x10) EncVal |= 0x0010000000000000ULL;768  if (Imm & 0x08) EncVal |= 0x0008000000000000ULL;769  if (Imm & 0x04) EncVal |= 0x0004000000000000ULL;770  if (Imm & 0x02) EncVal |= 0x0002000000000000ULL;771  if (Imm & 0x01) EncVal |= 0x0001000000000000ULL;772  return (EncVal << 32) | EncVal;773}774 775/// Returns true if Imm is the concatenation of a repeating pattern of type T.776template <typename T>777static inline bool isSVEMaskOfIdenticalElements(int64_t Imm) {778  auto Parts = bit_cast<std::array<T, sizeof(int64_t) / sizeof(T)>>(Imm);779  return llvm::all_equal(Parts);780}781 782/// Returns true if Imm is valid for CPY/DUP.783template <typename T>784static inline bool isSVECpyImm(int64_t Imm) {785  // Imm is interpreted as a signed value, which means top bits must be all ones786  // (sign bits if the immediate value is negative and passed in a larger787  // container), or all zeroes.788  int64_t Mask = ~int64_t(std::numeric_limits<std::make_unsigned_t<T>>::max());789  if ((Imm & Mask) != 0 && (Imm & Mask) != Mask)790    return false;791 792  // Imm is a signed 8-bit value.793  // Top bits must be zeroes or sign bits.794  if (Imm & 0xff)795    return int8_t(Imm) == T(Imm);796 797  // Imm is a signed 16-bit value and multiple of 256.798  // Top bits must be zeroes or sign bits.799  if (Imm & 0xff00)800    return int16_t(Imm) == T(Imm);801 802  return Imm == 0;803}804 805/// Returns true if Imm is valid for ADD/SUB.806template <typename T>807static inline bool isSVEAddSubImm(int64_t Imm) {808  bool IsInt8t = std::is_same<int8_t, std::make_signed_t<T>>::value ||809                 std::is_same<int8_t, T>::value;810  return uint8_t(Imm) == Imm || (!IsInt8t && uint16_t(Imm & ~0xff) == Imm);811}812 813/// Return true if Imm is valid for DUPM and has no single CPY/DUP equivalent.814static inline bool isSVEMoveMaskPreferredLogicalImmediate(int64_t Imm) {815  if (isSVECpyImm<int64_t>(Imm))816    return false;817 818  auto S = bit_cast<std::array<int32_t, 2>>(Imm);819  auto H = bit_cast<std::array<int16_t, 4>>(Imm);820  auto B = bit_cast<std::array<int8_t, 8>>(Imm);821 822  if (isSVEMaskOfIdenticalElements<int32_t>(Imm) && isSVECpyImm<int32_t>(S[0]))823    return false;824  if (isSVEMaskOfIdenticalElements<int16_t>(Imm) && isSVECpyImm<int16_t>(H[0]))825    return false;826  if (isSVEMaskOfIdenticalElements<int8_t>(Imm) && isSVECpyImm<int8_t>(B[0]))827    return false;828  return isLogicalImmediate(Imm, 64);829}830 831inline static bool isAnyMOVZMovAlias(uint64_t Value, int RegWidth) {832  for (int Shift = 0; Shift <= RegWidth - 16; Shift += 16)833    if ((Value & ~(0xffffULL << Shift)) == 0)834      return true;835 836  return false;837}838 839inline static bool isMOVZMovAlias(uint64_t Value, int Shift, int RegWidth) {840  if (RegWidth == 32)841    Value &= 0xffffffffULL;842 843  // "lsl #0" takes precedence: in practice this only affects "#0, lsl #0".844  if (Value == 0 && Shift != 0)845    return false;846 847  return (Value & ~(0xffffULL << Shift)) == 0;848}849 850inline static bool isMOVNMovAlias(uint64_t Value, int Shift, int RegWidth) {851  // MOVZ takes precedence over MOVN.852  if (isAnyMOVZMovAlias(Value, RegWidth))853    return false;854 855  Value = ~Value;856  if (RegWidth == 32)857    Value &= 0xffffffffULL;858 859  return isMOVZMovAlias(Value, Shift, RegWidth);860}861 862inline static bool isAnyMOVWMovAlias(uint64_t Value, int RegWidth) {863  if (isAnyMOVZMovAlias(Value, RegWidth))864    return true;865 866  // It's not a MOVZ, but it might be a MOVN.867  Value = ~Value;868  if (RegWidth == 32)869    Value &= 0xffffffffULL;870 871  return isAnyMOVZMovAlias(Value, RegWidth);872}873 874static inline bool isSVECpyDupImm(int SizeInBits, int64_t Val, int32_t &Imm,875                                  int32_t &Shift) {876  switch (SizeInBits) {877  case 8:878    // All immediates are supported.879    Shift = 0;880    Imm = Val & 0xFF;881    return true;882  case 16:883  case 32:884  case 64:885    // Support 8bit signed immediates.886    if (Val >= -128 && Val <= 127) {887      Shift = 0;888      Imm = Val & 0xFF;889      return true;890    }891    // Support 16bit signed immediates that are a multiple of 256.892    if (Val >= -32768 && Val <= 32512 && Val % 256 == 0) {893      Shift = 8;894      Imm = (Val >> 8) & 0xFF;895      return true;896    }897    break;898  default:899    break;900  }901  return false;902}903 904} // end namespace AArch64_AM905 906} // end namespace llvm907 908#endif909