LCOV - code coverage report
Current view: top level - lib/Target/AArch64/MCTargetDesc - AArch64AddressingModes.h (source / functions) Hit Total Coverage
Test: llvm-toolchain.info Lines: 305 310 98.4 %
Date: 2018-07-13 00:08:38 Functions: 25 25 100.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : //===- AArch64AddressingModes.h - AArch64 Addressing Modes ------*- C++ -*-===//
       2             : //
       3             : //                     The LLVM Compiler Infrastructure
       4             : //
       5             : // This file is distributed under the University of Illinois Open Source
       6             : // License. See LICENSE.TXT for details.
       7             : //
       8             : //===----------------------------------------------------------------------===//
       9             : //
      10             : // This file contains the AArch64 addressing mode implementation stuff.
      11             : //
      12             : //===----------------------------------------------------------------------===//
      13             : 
      14             : #ifndef LLVM_LIB_TARGET_AARCH64_MCTARGETDESC_AARCH64ADDRESSINGMODES_H
      15             : #define LLVM_LIB_TARGET_AARCH64_MCTARGETDESC_AARCH64ADDRESSINGMODES_H
      16             : 
      17             : #include "llvm/ADT/APFloat.h"
      18             : #include "llvm/ADT/APInt.h"
      19             : #include "llvm/Support/ErrorHandling.h"
      20             : #include "llvm/Support/MathExtras.h"
      21             : #include <cassert>
      22             : 
      23             : namespace llvm {
      24             : 
      25             : /// AArch64_AM - AArch64 Addressing Mode Stuff
      26             : namespace AArch64_AM {
      27             : 
      28             : //===----------------------------------------------------------------------===//
      29             : // Shifts
      30             : //
      31             : 
      32             : enum 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.
      52        2374 : static inline const char *getShiftExtendName(AArch64_AM::ShiftExtendType ST) {
      53        2374 :   switch (ST) {
      54           0 :   default: llvm_unreachable("unhandled shift type!");
      55             :   case AArch64_AM::LSL: return "lsl";
      56         331 :   case AArch64_AM::LSR: return "lsr";
      57         378 :   case AArch64_AM::ASR: return "asr";
      58          51 :   case AArch64_AM::ROR: return "ror";
      59          54 :   case AArch64_AM::MSL: return "msl";
      60          54 :   case AArch64_AM::UXTB: return "uxtb";
      61          56 :   case AArch64_AM::UXTH: return "uxth";
      62          64 :   case AArch64_AM::UXTW: return "uxtw";
      63          27 :   case AArch64_AM::UXTX: return "uxtx";
      64          47 :   case AArch64_AM::SXTB: return "sxtb";
      65          56 :   case AArch64_AM::SXTH: return "sxth";
      66          82 :   case AArch64_AM::SXTW: return "sxtw";
      67          23 :   case AArch64_AM::SXTX: return "sxtx";
      68             :   }
      69             :   return nullptr;
      70             : }
      71             : 
      72             : /// getShiftType - Extract the shift type.
      73             : static inline AArch64_AM::ShiftExtendType getShiftType(unsigned Imm) {
      74        4723 :   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.
      85             : static inline unsigned getShiftValue(unsigned Imm) {
      86       12196 :   return Imm & 0x3f;
      87             : }
      88             : 
      89             : /// getShifterImm - Encode the shift type and amount:
      90             : ///   imm:     6-bit shift amount
      91             : ///   shifter: 000 ==> lsl
      92             : ///            001 ==> lsr
      93             : ///            010 ==> asr
      94             : ///            011 ==> ror
      95             : ///            100 ==> msl
      96             : ///   {8-6}  = shifter
      97             : ///   {5-0}  = imm
      98             : static inline unsigned getShifterImm(AArch64_AM::ShiftExtendType ST,
      99             :                                      unsigned Imm) {
     100             :   assert((Imm & 0x3f) == Imm && "Illegal shifted immedate value!");
     101             :   unsigned STEnc = 0;
     102         641 :   switch (ST) {
     103           0 :   default:  llvm_unreachable("Invalid shift requested");
     104             :   case AArch64_AM::LSL: STEnc = 0; break;
     105         113 :   case AArch64_AM::LSR: STEnc = 1; break;
     106         138 :   case AArch64_AM::ASR: STEnc = 2; break;
     107          23 :   case AArch64_AM::ROR: STEnc = 3; break;
     108          16 :   case AArch64_AM::MSL: STEnc = 4; break;
     109             :   }
     110        1431 :   return (STEnc << 6) | (Imm & 0x3f);
     111             : }
     112             : 
     113             : //===----------------------------------------------------------------------===//
     114             : // Extends
     115             : //
     116             : 
     117             : /// getArithShiftValue - get the arithmetic shift value.
     118             : static inline unsigned getArithShiftValue(unsigned Imm) {
     119         516 :   return Imm & 0x7;
     120             : }
     121             : 
     122             : /// getExtendType - Extract the extend type for operands of arithmetic ops.
     123        1380 : static inline AArch64_AM::ShiftExtendType getExtendType(unsigned Imm) {
     124             :   assert((Imm & 0x7) == Imm && "invalid immediate!");
     125        1380 :   switch (Imm) {
     126           0 :   default: llvm_unreachable("Compiler bug!");
     127             :   case 0: return AArch64_AM::UXTB;
     128          66 :   case 1: return AArch64_AM::UXTH;
     129          95 :   case 2: return AArch64_AM::UXTW;
     130          33 :   case 3: return AArch64_AM::UXTX;
     131          47 :   case 4: return AArch64_AM::SXTB;
     132          56 :   case 5: return AArch64_AM::SXTH;
     133         132 :   case 6: return AArch64_AM::SXTW;
     134          23 :   case 7: return AArch64_AM::SXTX;
     135             :   }
     136             : }
     137             : 
     138             : static inline AArch64_AM::ShiftExtendType getArithExtendType(unsigned Imm) {
     139         516 :   return getExtendType((Imm >> 3) & 0x7);
     140             : }
     141             : 
     142             : /// Mapping from extend bits to required operation:
     143             : ///   shifter: 000 ==> uxtb
     144             : ///            001 ==> uxth
     145             : ///            010 ==> uxtw
     146             : ///            011 ==> uxtx
     147             : ///            100 ==> sxtb
     148             : ///            101 ==> sxth
     149             : ///            110 ==> sxtw
     150             : ///            111 ==> sxtx
     151         390 : inline unsigned getExtendEncoding(AArch64_AM::ShiftExtendType ET) {
     152         390 :   switch (ET) {
     153           0 :   default: llvm_unreachable("Invalid extend type requested");
     154             :   case AArch64_AM::UXTB: return 0; break;
     155          49 :   case AArch64_AM::UXTH: return 1; break;
     156          66 :   case AArch64_AM::UXTW: return 2; break;
     157          32 :   case AArch64_AM::UXTX: return 3; break;
     158          43 :   case AArch64_AM::SXTB: return 4; break;
     159          52 :   case AArch64_AM::SXTH: return 5; break;
     160          83 :   case AArch64_AM::SXTW: return 6; break;
     161          19 :   case AArch64_AM::SXTX: return 7; break;
     162             :   }
     163             : }
     164             : 
     165             : /// getArithExtendImm - Encode the extend type and shift amount for an
     166             : ///                     arithmetic instruction:
     167             : ///   imm:     3-bit extend amount
     168             : ///   {5-3}  = shifter
     169             : ///   {2-0}  = imm3
     170             : static inline unsigned getArithExtendImm(AArch64_AM::ShiftExtendType ET,
     171             :                                          unsigned Imm) {
     172             :   assert((Imm & 0x7) == Imm && "Illegal shifted immedate value!");
     173         390 :   return (getExtendEncoding(ET) << 3) | (Imm & 0x7);
     174             : }
     175             : 
     176             : /// getMemDoShift - Extract the "do shift" flag value for load/store
     177             : /// instructions.
     178             : static inline bool getMemDoShift(unsigned Imm) {
     179           0 :   return (Imm & 0x1) != 0;
     180             : }
     181             : 
     182             : /// getExtendType - Extract the extend type for the offset operand of
     183             : /// loads/stores.
     184             : static inline AArch64_AM::ShiftExtendType getMemExtendType(unsigned Imm) {
     185         864 :   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 size
     190             : ///   shifter: 000 ==> uxtb
     191             : ///            001 ==> uxth
     192             : ///            010 ==> uxtw
     193             : ///            011 ==> uxtx
     194             : ///            100 ==> sxtb
     195             : ///            101 ==> sxth
     196             : ///            110 ==> sxtw
     197             : ///            111 ==> sxtx
     198             : ///   {3-1}  = shifter
     199             : ///   {0}  = doshift
     200             : static inline unsigned getMemExtendImm(AArch64_AM::ShiftExtendType ET,
     201             :                                        bool DoShift) {
     202             :   return (getExtendEncoding(ET) << 1) | unsigned(DoShift);
     203             : }
     204             : 
     205             : static inline uint64_t ror(uint64_t elt, unsigned size) {
     206       52531 :   return ((elt & 1) << (size-1)) | (elt >> 1);
     207             : }
     208             : 
     209             : /// processLogicalImmediate - Determine if an immediate value can be encoded
     210             : /// as the immediate operand of a logical instruction for the given register
     211             : /// size.  If so, return true with "encoding" set to the encoded value in
     212             : /// the form N:immr:imms.
     213        8273 : static inline bool processLogicalImmediate(uint64_t Imm, unsigned RegSize,
     214             :                                            uint64_t &Encoding) {
     215        8273 :   if (Imm == 0ULL || Imm == ~0ULL ||
     216        3517 :       (RegSize != 64 &&
     217        6944 :         (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        8484 :     Size /= 2;
     225             :     uint64_t Mask = (1ULL << Size) - 1;
     226             : 
     227        8484 :     if ((Imm & Mask) != ((Imm >> Size) & Mask)) {
     228        7439 :       Size *= 2;
     229        7439 :       break;
     230             :     }
     231        1045 :   } while (Size > 2);
     232             : 
     233             :   // Second, determine the rotation to make the element be: 0^m 1^n.
     234             :   uint32_t CTO, I;
     235        7524 :   uint64_t Mask = ((uint64_t)-1LL) >> (64 - Size);
     236        7524 :   Imm &= Mask;
     237             : 
     238             :   if (isShiftedMask_64(Imm)) {
     239        5103 :     I = countTrailingZeros(Imm);
     240             :     assert(I < 64 && "undefined behavior");
     241       10206 :     CTO = countTrailingOnes(Imm >> I);
     242             :   } else {
     243        2421 :     Imm |= ~Mask;
     244        2421 :     if (!isShiftedMask_64(~Imm))
     245             :       return false;
     246             : 
     247         481 :     unsigned CLO = countLeadingOnes(Imm);
     248         481 :     I = 64 - CLO;
     249         481 :     CTO = CLO + countTrailingOnes(Imm) - (64 - Size);
     250             :   }
     251             : 
     252             :   // Encode in Immr the number of RORs it would take to get *from* 0^m 1^n
     253             :   // to our target value, where I is the number of RORs to go the opposite
     254             :   // direction.
     255             :   assert(Size > I && "I should be smaller than element size");
     256        5584 :   unsigned Immr = (Size - I) & (Size - 1);
     257             : 
     258             :   // If size has a 1 in the n'th bit, create a value that has zeroes in
     259             :   // bits [0, n] and ones above that.
     260        5584 :   uint64_t NImms = ~(Size-1) << 1;
     261             : 
     262             :   // Or the CTO value into the low bits, which must be below the Nth bit
     263             :   // bit mentioned above.
     264        5584 :   NImms |= (CTO-1);
     265             : 
     266             :   // Extract the seventh bit and toggle it to create the N field.
     267        5584 :   unsigned N = ((NImms >> 6) & 1) ^ 1;
     268             : 
     269        5584 :   Encoding = (N << 12) | (Immr << 6) | (NImms & 0x3f);
     270        5584 :   return true;
     271             : }
     272             : 
     273             : /// isLogicalImmediate - Return true if the immediate is valid for a logical
     274             : /// immediate instruction of the given register size. Return false otherwise.
     275             : static inline bool isLogicalImmediate(uint64_t imm, unsigned regSize) {
     276             :   uint64_t encoding;
     277        5152 :   return processLogicalImmediate(imm, regSize, encoding);
     278             : }
     279             : 
     280             : /// encodeLogicalImmediate - Return the encoded immediate value for a logical
     281             : /// immediate instruction of the given register size.
     282             : static inline uint64_t encodeLogicalImmediate(uint64_t imm, unsigned regSize) {
     283         884 :   uint64_t encoding = 0;
     284         884 :   bool res = processLogicalImmediate(imm, regSize, encoding);
     285             :   assert(res && "invalid logical immediate");
     286             :   (void)res;
     287         884 :   return encoding;
     288             : }
     289             : 
     290             : /// decodeLogicalImmediate - Decode a logical immediate value in the form
     291             : /// "N:immr:imms" (where the immr and imms fields are each 6 bits) into the
     292             : /// integer value it represents with regSize bits.
     293        3434 : static inline uint64_t decodeLogicalImmediate(uint64_t val, unsigned regSize) {
     294             :   // Extract the N, imms, and immr fields.
     295        3434 :   unsigned N = (val >> 12) & 1;
     296        3434 :   unsigned immr = (val >> 6) & 0x3f;
     297        3434 :   unsigned imms = val & 0x3f;
     298             : 
     299             :   assert((regSize == 64 || N == 0) && "undefined logical immediate encoding");
     300        6868 :   int len = 31 - countLeadingZeros((N << 6) | (~imms & 0x3f));
     301             :   assert(len >= 0 && "undefined logical immediate encoding");
     302        3434 :   unsigned size = (1 << len);
     303        3434 :   unsigned R = immr & (size - 1);
     304        3434 :   unsigned S = imms & (size - 1);
     305             :   assert(S != size - 1 && "undefined logical immediate encoding");
     306        3434 :   uint64_t pattern = (1ULL << (S + 1)) - 1;
     307      108496 :   for (unsigned i = 0; i < R; ++i)
     308             :     pattern = ror(pattern, size);
     309             : 
     310             :   // Replicate the pattern to fill the regSize.
     311        5656 :   while (size != regSize) {
     312        1111 :     pattern |= (pattern << size);
     313        1111 :     size *= 2;
     314             :   }
     315        3434 :   return pattern;
     316             : }
     317             : 
     318             : /// isValidDecodeLogicalImmediate - Check to see if the logical immediate value
     319             : /// 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.
     321         228 : static inline bool isValidDecodeLogicalImmediate(uint64_t val,
     322             :                                                  unsigned regSize) {
     323             :   // Extract the N and imms fields needed for checking.
     324         228 :   unsigned N = (val >> 12) & 1;
     325         228 :   unsigned imms = val & 0x3f;
     326             : 
     327         228 :   if (regSize == 32 && N != 0) // undefined logical immediate encoding
     328             :     return false;
     329         456 :   int len = 31 - countLeadingZeros((N << 6) | (~imms & 0x3f));
     330         228 :   if (len < 0) // undefined logical immediate encoding
     331             :     return false;
     332         228 :   unsigned size = (1 << len);
     333         228 :   unsigned S = imms & (size - 1);
     334         228 :   if (S == size - 1) // undefined logical immediate encoding
     335             :     return false;
     336             : 
     337         227 :   return true;
     338             : }
     339             : 
     340             : //===----------------------------------------------------------------------===//
     341             : // Floating-point Immediates
     342             : //
     343        1800 : static inline float getFPImmFloat(unsigned Imm) {
     344             :   // We expect an 8-bit binary encoding of a floating-point number here.
     345             :   union {
     346             :     uint32_t I;
     347             :     float F;
     348             :   } FPUnion;
     349             : 
     350        1800 :   uint8_t Sign = (Imm >> 7) & 0x1;
     351        1800 :   uint8_t Exp = (Imm >> 4) & 0x7;
     352        1800 :   uint8_t Mantissa = Imm & 0xf;
     353             : 
     354             :   //   8-bit FP    iEEEE Float Encoding
     355             :   //   abcd efgh   aBbbbbbc defgh000 00000000 00000000
     356             :   //
     357             :   // where B = NOT(b);
     358             : 
     359             :   FPUnion.I = 0;
     360        1800 :   FPUnion.I |= Sign << 31;
     361        1800 :   FPUnion.I |= ((Exp & 0x4) != 0 ? 0 : 1) << 30;
     362        1800 :   FPUnion.I |= ((Exp & 0x4) != 0 ? 0x1f : 0) << 25;
     363        1800 :   FPUnion.I |= (Exp & 0x3) << 23;
     364        1800 :   FPUnion.I |= Mantissa << 19;
     365        1800 :   return FPUnion.F;
     366             : }
     367             : 
     368             : /// getFP16Imm - Return an 8-bit floating-point version of the 16-bit
     369             : /// floating-point value. If the value cannot be represented as an 8-bit
     370             : /// floating-point value, then return -1.
     371          38 : static inline int getFP16Imm(const APInt &Imm) {
     372          76 :   uint32_t Sign = Imm.lshr(15).getZExtValue() & 1;
     373         114 :   int32_t Exp = (Imm.lshr(10).getSExtValue() & 0x1f) - 15;  // -14 to 15
     374          38 :   int32_t Mantissa = Imm.getZExtValue() & 0x3ff;  // 10 bits
     375             : 
     376             :   // We can handle 4 bits of mantissa.
     377             :   // mantissa = (16+UInt(e:f:g:h))/16.
     378          38 :   if (Mantissa & 0x3f)
     379             :     return -1;
     380          34 :   Mantissa >>= 6;
     381             : 
     382             :   // We can handle 3 bits of exponent: exp == UInt(NOT(b):c:d)-3
     383          34 :   if (Exp < -3 || Exp > 4)
     384             :     return -1;
     385          32 :   Exp = ((Exp+3) & 0x7) ^ 4;
     386             : 
     387          32 :   return ((int)Sign << 7) | (Exp << 4) | Mantissa;
     388             : }
     389             : 
     390          38 : static inline int getFP16Imm(const APFloat &FPImm) {
     391          76 :   return getFP16Imm(FPImm.bitcastToAPInt());
     392             : }
     393             : 
     394             : /// getFP32Imm - Return an 8-bit floating-point version of the 32-bit
     395             : /// floating-point value. If the value cannot be represented as an 8-bit
     396             : /// floating-point value, then return -1.
     397         373 : static inline int getFP32Imm(const APInt &Imm) {
     398         746 :   uint32_t Sign = Imm.lshr(31).getZExtValue() & 1;
     399        1119 :   int32_t Exp = (Imm.lshr(23).getSExtValue() & 0xff) - 127;  // -126 to 127
     400         373 :   int64_t Mantissa = Imm.getZExtValue() & 0x7fffff;  // 23 bits
     401             : 
     402             :   // We can handle 4 bits of mantissa.
     403             :   // mantissa = (16+UInt(e:f:g:h))/16.
     404         373 :   if (Mantissa & 0x7ffff)
     405             :     return -1;
     406         363 :   Mantissa >>= 19;
     407             :   if ((Mantissa & 0xf) != Mantissa)
     408             :     return -1;
     409             : 
     410             :   // We can handle 3 bits of exponent: exp == UInt(NOT(b):c:d)-3
     411         363 :   if (Exp < -3 || Exp > 4)
     412             :     return -1;
     413         341 :   Exp = ((Exp+3) & 0x7) ^ 4;
     414             : 
     415         341 :   return ((int)Sign << 7) | (Exp << 4) | Mantissa;
     416             : }
     417             : 
     418         373 : static inline int getFP32Imm(const APFloat &FPImm) {
     419         746 :   return getFP32Imm(FPImm.bitcastToAPInt());
     420             : }
     421             : 
     422             : /// getFP64Imm - Return an 8-bit floating-point version of the 64-bit
     423             : /// floating-point value. If the value cannot be represented as an 8-bit
     424             : /// floating-point value, then return -1.
     425        6589 : static inline int getFP64Imm(const APInt &Imm) {
     426       19767 :   uint64_t Sign = Imm.lshr(63).getZExtValue() & 1;
     427       19767 :   int64_t Exp = (Imm.lshr(52).getSExtValue() & 0x7ff) - 1023;   // -1022 to 1023
     428             :   uint64_t Mantissa = Imm.getZExtValue() & 0xfffffffffffffULL;
     429             : 
     430             :   // We can handle 4 bits of mantissa.
     431             :   // mantissa = (16+UInt(e:f:g:h))/16.
     432        6589 :   if (Mantissa & 0xffffffffffffULL)
     433             :     return -1;
     434        6570 :   Mantissa >>= 48;
     435             :   if ((Mantissa & 0xf) != Mantissa)
     436             :     return -1;
     437             : 
     438             :   // We can handle 3 bits of exponent: exp == UInt(NOT(b):c:d)-3
     439        6570 :   if (Exp < -3 || Exp > 4)
     440             :     return -1;
     441        6445 :   Exp = ((Exp+3) & 0x7) ^ 4;
     442             : 
     443        6445 :   return ((int)Sign << 7) | (Exp << 4) | Mantissa;
     444             : }
     445             : 
     446         187 : static inline int getFP64Imm(const APFloat &FPImm) {
     447         374 :   return getFP64Imm(FPImm.bitcastToAPInt());
     448             : }
     449             : 
     450             : //===--------------------------------------------------------------------===//
     451             : // AdvSIMD Modified Immediates
     452             : //===--------------------------------------------------------------------===//
     453             : 
     454             : // 0x00 0x00 0x00 abcdefgh 0x00 0x00 0x00 abcdefgh
     455             : static inline bool isAdvSIMDModImmType1(uint64_t Imm) {
     456        1589 :   return ((Imm >> 32) == (Imm & 0xffffffffULL)) &&
     457         707 :          ((Imm & 0xffffff00ffffff00ULL) == 0);
     458             : }
     459             : 
     460             : static inline uint8_t encodeAdvSIMDModImmType1(uint64_t Imm) {
     461             :   return (Imm & 0xffULL);
     462             : }
     463             : 
     464             : static inline uint64_t decodeAdvSIMDModImmType1(uint8_t Imm) {
     465             :   uint64_t EncVal = Imm;
     466             :   return (EncVal << 32) | EncVal;
     467             : }
     468             : 
     469             : // 0x00 0x00 abcdefgh 0x00 0x00 0x00 abcdefgh 0x00
     470             : static inline bool isAdvSIMDModImmType2(uint64_t Imm) {
     471        1449 :   return ((Imm >> 32) == (Imm & 0xffffffffULL)) &&
     472         637 :          ((Imm & 0xffff00ffffff00ffULL) == 0);
     473             : }
     474             : 
     475             : static inline uint8_t encodeAdvSIMDModImmType2(uint64_t Imm) {
     476          31 :   return (Imm & 0xff00ULL) >> 8;
     477             : }
     478             : 
     479             : static inline uint64_t decodeAdvSIMDModImmType2(uint8_t Imm) {
     480             :   uint64_t EncVal = Imm;
     481             :   return (EncVal << 40) | (EncVal << 8);
     482             : }
     483             : 
     484             : // 0x00 abcdefgh 0x00 0x00 0x00 abcdefgh 0x00 0x00
     485             : static inline bool isAdvSIMDModImmType3(uint64_t Imm) {
     486        1387 :   return ((Imm >> 32) == (Imm & 0xffffffffULL)) &&
     487         606 :          ((Imm & 0xff00ffffff00ffffULL) == 0);
     488             : }
     489             : 
     490             : static inline uint8_t encodeAdvSIMDModImmType3(uint64_t Imm) {
     491          34 :   return (Imm & 0xff0000ULL) >> 16;
     492             : }
     493             : 
     494             : static inline uint64_t decodeAdvSIMDModImmType3(uint8_t Imm) {
     495             :   uint64_t EncVal = Imm;
     496             :   return (EncVal << 48) | (EncVal << 16);
     497             : }
     498             : 
     499             : // abcdefgh 0x00 0x00 0x00 abcdefgh 0x00 0x00 0x00
     500             : static inline bool isAdvSIMDModImmType4(uint64_t Imm) {
     501        1319 :   return ((Imm >> 32) == (Imm & 0xffffffffULL)) &&
     502         572 :          ((Imm & 0x00ffffff00ffffffULL) == 0);
     503             : }
     504             : 
     505             : static inline uint8_t encodeAdvSIMDModImmType4(uint64_t Imm) {
     506          52 :   return (Imm & 0xff000000ULL) >> 24;
     507             : }
     508             : 
     509             : static inline uint64_t decodeAdvSIMDModImmType4(uint8_t Imm) {
     510             :   uint64_t EncVal = Imm;
     511             :   return (EncVal << 56) | (EncVal << 24);
     512             : }
     513             : 
     514             : // 0x00 abcdefgh 0x00 abcdefgh 0x00 abcdefgh 0x00 abcdefgh
     515             : static inline bool isAdvSIMDModImmType5(uint64_t Imm) {
     516        1155 :   return ((Imm >> 32) == (Imm & 0xffffffffULL)) &&
     517         966 :          (((Imm & 0x00ff0000ULL) >> 16) == (Imm & 0x000000ffULL)) &&
     518         301 :          ((Imm & 0xff00ff00ff00ff00ULL) == 0);
     519             : }
     520             : 
     521             : static inline uint8_t encodeAdvSIMDModImmType5(uint64_t Imm) {
     522             :   return (Imm & 0xffULL);
     523             : }
     524             : 
     525             : static inline uint64_t decodeAdvSIMDModImmType5(uint8_t Imm) {
     526             :   uint64_t EncVal = Imm;
     527             :   return (EncVal << 48) | (EncVal << 32) | (EncVal << 16) | EncVal;
     528             : }
     529             : 
     530             : // abcdefgh 0x00 abcdefgh 0x00 abcdefgh 0x00 abcdefgh 0x00
     531             : static inline bool isAdvSIMDModImmType6(uint64_t Imm) {
     532         427 :   return ((Imm >> 32) == (Imm & 0xffffffffULL)) &&
     533         916 :          (((Imm & 0xff000000ULL) >> 16) == (Imm & 0x0000ff00ULL)) &&
     534         314 :          ((Imm & 0x00ff00ff00ff00ffULL) == 0);
     535             : }
     536             : 
     537             : static inline uint8_t encodeAdvSIMDModImmType6(uint64_t Imm) {
     538          48 :   return (Imm & 0xff00ULL) >> 8;
     539             : }
     540             : 
     541             : static inline uint64_t decodeAdvSIMDModImmType6(uint8_t Imm) {
     542             :   uint64_t EncVal = Imm;
     543             :   return (EncVal << 56) | (EncVal << 40) | (EncVal << 24) | (EncVal << 8);
     544             : }
     545             : 
     546             : // 0x00 0x00 abcdefgh 0xFF 0x00 0x00 abcdefgh 0xFF
     547             : static inline bool isAdvSIMDModImmType7(uint64_t Imm) {
     548         795 :   return ((Imm >> 32) == (Imm & 0xffffffffULL)) &&
     549         318 :          ((Imm & 0xffff00ffffff00ffULL) == 0x000000ff000000ffULL);
     550             : }
     551             : 
     552             : static inline uint8_t encodeAdvSIMDModImmType7(uint64_t Imm) {
     553          15 :   return (Imm & 0xff00ULL) >> 8;
     554             : }
     555             : 
     556             : static inline uint64_t decodeAdvSIMDModImmType7(uint8_t Imm) {
     557             :   uint64_t EncVal = Imm;
     558             :   return (EncVal << 40) | (EncVal << 8) | 0x000000ff000000ffULL;
     559             : }
     560             : 
     561             : // 0x00 abcdefgh 0xFF 0xFF 0x00 abcdefgh 0xFF 0xFF
     562             : static inline bool isAdvSIMDModImmType8(uint64_t Imm) {
     563         765 :   return ((Imm >> 32) == (Imm & 0xffffffffULL)) &&
     564         303 :          ((Imm & 0xff00ffffff00ffffULL) == 0x0000ffff0000ffffULL);
     565             : }
     566             : 
     567             : static inline uint64_t decodeAdvSIMDModImmType8(uint8_t Imm) {
     568             :   uint64_t EncVal = Imm;
     569             :   return (EncVal << 48) | (EncVal << 16) | 0x0000ffff0000ffffULL;
     570             : }
     571             : 
     572             : static inline uint8_t encodeAdvSIMDModImmType8(uint64_t Imm) {
     573          15 :   return (Imm & 0x00ff0000ULL) >> 16;
     574             : }
     575             : 
     576             : // abcdefgh abcdefgh abcdefgh abcdefgh abcdefgh abcdefgh abcdefgh abcdefgh
     577             : static inline bool isAdvSIMDModImmType9(uint64_t Imm) {
     578         409 :   return ((Imm >> 32) == (Imm & 0xffffffffULL)) &&
     579         336 :          ((Imm >> 48) == (Imm & 0x0000ffffULL)) &&
     580          88 :          ((Imm >> 56) == (Imm & 0x000000ffULL));
     581             : }
     582             : 
     583             : static inline uint8_t encodeAdvSIMDModImmType9(uint64_t Imm) {
     584             :   return (Imm & 0xffULL);
     585             : }
     586             : 
     587             : static inline uint64_t decodeAdvSIMDModImmType9(uint8_t Imm) {
     588             :   uint64_t EncVal = Imm;
     589             :   EncVal |= (EncVal << 8);
     590             :   EncVal |= (EncVal << 16);
     591             :   EncVal |= (EncVal << 32);
     592             :   return EncVal;
     593             : }
     594             : 
     595             : // aaaaaaaa bbbbbbbb cccccccc dddddddd eeeeeeee ffffffff gggggggg hhhhhhhh
     596             : // cmode: 1110, op: 1
     597         508 : static inline bool isAdvSIMDModImmType10(uint64_t Imm) {
     598         508 :   uint64_t ByteA = Imm & 0xff00000000000000ULL;
     599         508 :   uint64_t ByteB = Imm & 0x00ff000000000000ULL;
     600         508 :   uint64_t ByteC = Imm & 0x0000ff0000000000ULL;
     601         508 :   uint64_t ByteD = Imm & 0x000000ff00000000ULL;
     602         508 :   uint64_t ByteE = Imm & 0x00000000ff000000ULL;
     603         508 :   uint64_t ByteF = Imm & 0x0000000000ff0000ULL;
     604         508 :   uint64_t ByteG = Imm & 0x000000000000ff00ULL;
     605         508 :   uint64_t ByteH = Imm & 0x00000000000000ffULL;
     606             : 
     607         795 :   return (ByteA == 0ULL || ByteA == 0xff00000000000000ULL) &&
     608         498 :          (ByteB == 0ULL || ByteB == 0x00ff000000000000ULL) &&
     609         386 :          (ByteC == 0ULL || ByteC == 0x0000ff0000000000ULL) &&
     610         296 :          (ByteD == 0ULL || ByteD == 0x000000ff00000000ULL) &&
     611         240 :          (ByteE == 0ULL || ByteE == 0x00000000ff000000ULL) &&
     612         237 :          (ByteF == 0ULL || ByteF == 0x0000000000ff0000ULL) &&
     613         742 :          (ByteG == 0ULL || ByteG == 0x000000000000ff00ULL) &&
     614         624 :          (ByteH == 0ULL || ByteH == 0x00000000000000ffULL);
     615             : }
     616             : 
     617          82 : static inline uint8_t encodeAdvSIMDModImmType10(uint64_t Imm) {
     618          82 :   uint8_t BitA = (Imm & 0xff00000000000000ULL) != 0;
     619          82 :   uint8_t BitB = (Imm & 0x00ff000000000000ULL) != 0;
     620          82 :   uint8_t BitC = (Imm & 0x0000ff0000000000ULL) != 0;
     621          82 :   uint8_t BitD = (Imm & 0x000000ff00000000ULL) != 0;
     622          82 :   uint8_t BitE = (Imm & 0x00000000ff000000ULL) != 0;
     623          82 :   uint8_t BitF = (Imm & 0x0000000000ff0000ULL) != 0;
     624          82 :   uint8_t BitG = (Imm & 0x000000000000ff00ULL) != 0;
     625          82 :   uint8_t BitH = (Imm & 0x00000000000000ffULL) != 0;
     626             : 
     627             :   uint8_t EncVal = BitA;
     628          82 :   EncVal <<= 1;
     629          82 :   EncVal |= BitB;
     630          82 :   EncVal <<= 1;
     631          82 :   EncVal |= BitC;
     632          82 :   EncVal <<= 1;
     633          82 :   EncVal |= BitD;
     634          82 :   EncVal <<= 1;
     635          82 :   EncVal |= BitE;
     636          82 :   EncVal <<= 1;
     637          82 :   EncVal |= BitF;
     638          82 :   EncVal <<= 1;
     639          82 :   EncVal |= BitG;
     640          82 :   EncVal <<= 1;
     641          82 :   EncVal |= BitH;
     642          82 :   return EncVal;
     643             : }
     644             : 
     645         189 : static inline uint64_t decodeAdvSIMDModImmType10(uint8_t Imm) {
     646             :   uint64_t EncVal = 0;
     647         189 :   if (Imm & 0x80) EncVal |= 0xff00000000000000ULL;
     648         189 :   if (Imm & 0x40) EncVal |= 0x00ff000000000000ULL;
     649         189 :   if (Imm & 0x20) EncVal |= 0x0000ff0000000000ULL;
     650         189 :   if (Imm & 0x10) EncVal |= 0x000000ff00000000ULL;
     651         189 :   if (Imm & 0x08) EncVal |= 0x00000000ff000000ULL;
     652         189 :   if (Imm & 0x04) EncVal |= 0x0000000000ff0000ULL;
     653         189 :   if (Imm & 0x02) EncVal |= 0x000000000000ff00ULL;
     654         189 :   if (Imm & 0x01) EncVal |= 0x00000000000000ffULL;
     655         189 :   return EncVal;
     656             : }
     657             : 
     658             : // aBbbbbbc defgh000 0x00 0x00 aBbbbbbc defgh000 0x00 0x00
     659             : static inline bool isAdvSIMDModImmType11(uint64_t Imm) {
     660         203 :   uint64_t BString = (Imm & 0x7E000000ULL) >> 25;
     661         319 :   return ((Imm >> 32) == (Imm & 0xffffffffULL)) &&
     662         231 :          (BString == 0x1f || BString == 0x20) &&
     663          28 :          ((Imm & 0x0007ffff0007ffffULL) == 0);
     664             : }
     665             : 
     666          24 : static inline uint8_t encodeAdvSIMDModImmType11(uint64_t Imm) {
     667          24 :   uint8_t BitA = (Imm & 0x80000000ULL) != 0;
     668          24 :   uint8_t BitB = (Imm & 0x20000000ULL) != 0;
     669          24 :   uint8_t BitC = (Imm & 0x01000000ULL) != 0;
     670          24 :   uint8_t BitD = (Imm & 0x00800000ULL) != 0;
     671          24 :   uint8_t BitE = (Imm & 0x00400000ULL) != 0;
     672          24 :   uint8_t BitF = (Imm & 0x00200000ULL) != 0;
     673          24 :   uint8_t BitG = (Imm & 0x00100000ULL) != 0;
     674          24 :   uint8_t BitH = (Imm & 0x00080000ULL) != 0;
     675             : 
     676             :   uint8_t EncVal = BitA;
     677          24 :   EncVal <<= 1;
     678          24 :   EncVal |= BitB;
     679          24 :   EncVal <<= 1;
     680          24 :   EncVal |= BitC;
     681          24 :   EncVal <<= 1;
     682          24 :   EncVal |= BitD;
     683          24 :   EncVal <<= 1;
     684          24 :   EncVal |= BitE;
     685          24 :   EncVal <<= 1;
     686          24 :   EncVal |= BitF;
     687          24 :   EncVal <<= 1;
     688          24 :   EncVal |= BitG;
     689          24 :   EncVal <<= 1;
     690          24 :   EncVal |= BitH;
     691          24 :   return EncVal;
     692             : }
     693             : 
     694             : static inline uint64_t decodeAdvSIMDModImmType11(uint8_t Imm) {
     695             :   uint64_t EncVal = 0;
     696             :   if (Imm & 0x80) EncVal |= 0x80000000ULL;
     697             :   if (Imm & 0x40) EncVal |= 0x3e000000ULL;
     698             :   else            EncVal |= 0x40000000ULL;
     699             :   if (Imm & 0x20) EncVal |= 0x01000000ULL;
     700             :   if (Imm & 0x10) EncVal |= 0x00800000ULL;
     701             :   if (Imm & 0x08) EncVal |= 0x00400000ULL;
     702             :   if (Imm & 0x04) EncVal |= 0x00200000ULL;
     703             :   if (Imm & 0x02) EncVal |= 0x00100000ULL;
     704             :   if (Imm & 0x01) EncVal |= 0x00080000ULL;
     705             :   return (EncVal << 32) | EncVal;
     706             : }
     707             : 
     708             : // aBbbbbbb bbcdefgh 0x00 0x00 0x00 0x00 0x00 0x00
     709             : static inline bool isAdvSIMDModImmType12(uint64_t Imm) {
     710          92 :   uint64_t BString = (Imm & 0x7fc0000000000000ULL) >> 54;
     711         107 :   return ((BString == 0xff || BString == 0x100) &&
     712          15 :          ((Imm & 0x0000ffffffffffffULL) == 0));
     713             : }
     714             : 
     715          15 : static inline uint8_t encodeAdvSIMDModImmType12(uint64_t Imm) {
     716          15 :   uint8_t BitA = (Imm & 0x8000000000000000ULL) != 0;
     717          15 :   uint8_t BitB = (Imm & 0x0040000000000000ULL) != 0;
     718          15 :   uint8_t BitC = (Imm & 0x0020000000000000ULL) != 0;
     719          15 :   uint8_t BitD = (Imm & 0x0010000000000000ULL) != 0;
     720          15 :   uint8_t BitE = (Imm & 0x0008000000000000ULL) != 0;
     721          15 :   uint8_t BitF = (Imm & 0x0004000000000000ULL) != 0;
     722          15 :   uint8_t BitG = (Imm & 0x0002000000000000ULL) != 0;
     723          15 :   uint8_t BitH = (Imm & 0x0001000000000000ULL) != 0;
     724             : 
     725             :   uint8_t EncVal = BitA;
     726          15 :   EncVal <<= 1;
     727          15 :   EncVal |= BitB;
     728          15 :   EncVal <<= 1;
     729          15 :   EncVal |= BitC;
     730          15 :   EncVal <<= 1;
     731          15 :   EncVal |= BitD;
     732          15 :   EncVal <<= 1;
     733          15 :   EncVal |= BitE;
     734          15 :   EncVal <<= 1;
     735          15 :   EncVal |= BitF;
     736          15 :   EncVal <<= 1;
     737          15 :   EncVal |= BitG;
     738          15 :   EncVal <<= 1;
     739          15 :   EncVal |= BitH;
     740          15 :   return EncVal;
     741             : }
     742             : 
     743             : static inline uint64_t decodeAdvSIMDModImmType12(uint8_t Imm) {
     744             :   uint64_t EncVal = 0;
     745             :   if (Imm & 0x80) EncVal |= 0x8000000000000000ULL;
     746             :   if (Imm & 0x40) EncVal |= 0x3fc0000000000000ULL;
     747             :   else            EncVal |= 0x4000000000000000ULL;
     748             :   if (Imm & 0x20) EncVal |= 0x0020000000000000ULL;
     749             :   if (Imm & 0x10) EncVal |= 0x0010000000000000ULL;
     750             :   if (Imm & 0x08) EncVal |= 0x0008000000000000ULL;
     751             :   if (Imm & 0x04) EncVal |= 0x0004000000000000ULL;
     752             :   if (Imm & 0x02) EncVal |= 0x0002000000000000ULL;
     753             :   if (Imm & 0x01) EncVal |= 0x0001000000000000ULL;
     754             :   return (EncVal << 32) | EncVal;
     755             : }
     756             : 
     757             : /// Returns true if Imm is the concatenation of a repeating pattern of type T.
     758             : template <typename T>
     759         486 : static inline bool isSVEMaskOfIdenticalElements(int64_t Imm) {
     760             :   union {
     761             :     int64_t Whole;
     762             :     T Parts[sizeof(int64_t)/sizeof(T)];
     763         486 :   } Vec { Imm };
     764             : 
     765         972 :   return all_of(Vec.Parts, [Vec](T Elem) { return Elem == Vec.Parts[0]; });
     766             : }
     767             : 
     768             : /// Returns true if Imm is valid for CPY/DUP.
     769             : template <typename T>
     770             : static inline bool isSVECpyImm(int64_t Imm) {
     771         888 :   bool IsImm8 = int8_t(Imm) == Imm;
     772         808 :   bool IsImm16 = int16_t(Imm & ~0xff) == Imm;
     773             : 
     774             :   if (std::is_same<int8_t, typename std::make_signed<T>::type>::value)
     775          80 :     return IsImm8 || uint8_t(Imm) == Imm;
     776             : 
     777             :   if (std::is_same<int16_t, typename std::make_signed<T>::type>::value)
     778         254 :     return IsImm8 || IsImm16 || uint16_t(Imm & ~0xff) == Imm;
     779             : 
     780         554 :   return IsImm8 || IsImm16;
     781             : }
     782             : 
     783             : /// Returns true if Imm is valid for ADD/SUB.
     784             : template <typename T>
     785             : static inline bool isSVEAddSubImm(int64_t Imm) {
     786             :   bool IsInt8t =
     787             :       std::is_same<int8_t, typename std::make_signed<T>::type>::value;
     788         630 :   return uint8_t(Imm) == Imm || (!IsInt8t && uint16_t(Imm & ~0xff) == Imm);
     789             : }
     790             : 
     791             : /// Return true if Imm is valid for DUPM and has no single CPY/DUP equivalent.
     792          62 : static inline bool isSVEMoveMaskPreferredLogicalImmediate(int64_t Imm) {
     793             :   union {
     794             :     int64_t D;
     795             :     int32_t S[2];
     796             :     int16_t H[4];
     797             :     int8_t  B[8];
     798             :   } Vec = { Imm };
     799             : 
     800          62 :   if (isSVECpyImm<int64_t>(Vec.D))
     801             :     return false;
     802             : 
     803         114 :   if (isSVEMaskOfIdenticalElements<int32_t>(Imm) &&
     804          54 :       isSVECpyImm<int32_t>(Vec.S[0]))
     805             :     return false;
     806             : 
     807          52 :   if (isSVEMaskOfIdenticalElements<int16_t>(Imm) &&
     808          42 :       isSVECpyImm<int16_t>(Vec.H[0]))
     809             :     return false;
     810             : 
     811          34 :   if (isSVEMaskOfIdenticalElements<int8_t>(Imm) &&
     812             :       isSVECpyImm<int8_t>(Vec.B[0]))
     813             :     return false;
     814             : 
     815          20 :   return isLogicalImmediate(Vec.D, 64);
     816             : }
     817             : 
     818             : inline static bool isAnyMOVZMovAlias(uint64_t Value, int RegWidth) {
     819        2849 :   for (int Shift = 0; Shift <= RegWidth - 16; Shift += 16)
     820        1825 :     if ((Value & ~(0xffffULL << Shift)) == 0)
     821             :       return true;
     822             : 
     823             :   return false;
     824             : }
     825             : 
     826             : inline static bool isMOVZMovAlias(uint64_t Value, int Shift, int RegWidth) {
     827          86 :   if (RegWidth == 32)
     828         583 :     Value &= 0xffffffffULL;
     829             : 
     830             :   // "lsl #0" takes precedence: in practice this only affects "#0, lsl #0".
     831         808 :   if (Value == 0 && Shift != 0)
     832             :     return false;
     833             : 
     834         803 :   return (Value & ~(0xffffULL << Shift)) == 0;
     835             : }
     836             : 
     837          88 : inline static bool isMOVNMovAlias(uint64_t Value, int Shift, int RegWidth) {
     838             :   // MOVZ takes precedence over MOVN.
     839          99 :   if (isAnyMOVZMovAlias(Value, RegWidth))
     840             :     return false;
     841             : 
     842          97 :   Value = ~Value;
     843          86 :   if (RegWidth == 32)
     844          49 :     Value &= 0xffffffffULL;
     845             : 
     846             :   return isMOVZMovAlias(Value, Shift, RegWidth);
     847             : }
     848             : 
     849        1082 : inline static bool isAnyMOVWMovAlias(uint64_t Value, int RegWidth) {
     850        1082 :   if (isAnyMOVZMovAlias(Value, RegWidth))
     851             :     return true;
     852             : 
     853             :   // It's not a MOVZ, but it might be a MOVN.
     854          74 :   Value = ~Value;
     855          74 :   if (RegWidth == 32)
     856          21 :     Value &= 0xffffffffULL;
     857             : 
     858             :   return isAnyMOVZMovAlias(Value, RegWidth);
     859             : }
     860             : 
     861             : } // end namespace AArch64_AM
     862             : 
     863             : } // end namespace llvm
     864             : 
     865             : #endif

Generated by: LCOV version 1.13