Home | History | Annotate | Line # | Download | only in MCTargetDesc
      1 //===-- ARMAddressingModes.h - ARM 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-exception
      6 //
      7 //===----------------------------------------------------------------------===//
      8 //
      9 // This file contains the ARM addressing mode implementation stuff.
     10 //
     11 //===----------------------------------------------------------------------===//
     12 
     13 #ifndef LLVM_LIB_TARGET_ARM_MCTARGETDESC_ARMADDRESSINGMODES_H
     14 #define LLVM_LIB_TARGET_ARM_MCTARGETDESC_ARMADDRESSINGMODES_H
     15 
     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 
     23 namespace llvm {
     24 
     25 /// ARM_AM - ARM Addressing Mode Stuff
     26 namespace ARM_AM {
     27   enum ShiftOpc {
     28     no_shift = 0,
     29     asr,
     30     lsl,
     31     lsr,
     32     ror,
     33     rrx,
     34     uxtw
     35   };
     36 
     37   enum AddrOpc {
     38     sub = 0,
     39     add
     40   };
     41 
     42   inline const char *getAddrOpcStr(AddrOpc Op) { return Op == sub ? "-" : ""; }
     43 
     44   inline const char *getShiftOpcStr(ShiftOpc Op) {
     45     switch (Op) {
     46     default: llvm_unreachable("Unknown shift opc!");
     47     case ARM_AM::asr: return "asr";
     48     case ARM_AM::lsl: return "lsl";
     49     case ARM_AM::lsr: return "lsr";
     50     case ARM_AM::ror: return "ror";
     51     case ARM_AM::rrx: return "rrx";
     52     case ARM_AM::uxtw: return "uxtw";
     53     }
     54   }
     55 
     56   inline unsigned getShiftOpcEncoding(ShiftOpc Op) {
     57     switch (Op) {
     58     default: llvm_unreachable("Unknown shift opc!");
     59     case ARM_AM::asr: return 2;
     60     case ARM_AM::lsl: return 0;
     61     case ARM_AM::lsr: return 1;
     62     case ARM_AM::ror: return 3;
     63     }
     64   }
     65 
     66   enum AMSubMode {
     67     bad_am_submode = 0,
     68     ia,
     69     ib,
     70     da,
     71     db
     72   };
     73 
     74   inline const char *getAMSubModeStr(AMSubMode Mode) {
     75     switch (Mode) {
     76     default: llvm_unreachable("Unknown addressing sub-mode!");
     77     case ARM_AM::ia: return "ia";
     78     case ARM_AM::ib: return "ib";
     79     case ARM_AM::da: return "da";
     80     case ARM_AM::db: return "db";
     81     }
     82   }
     83 
     84   /// rotr32 - Rotate a 32-bit unsigned value right by a specified # bits.
     85   ///
     86   inline unsigned rotr32(unsigned Val, unsigned Amt) {
     87     assert(Amt < 32 && "Invalid rotate amount");
     88     return (Val >> Amt) | (Val << ((32-Amt)&31));
     89   }
     90 
     91   /// rotl32 - Rotate a 32-bit unsigned value left by a specified # bits.
     92   ///
     93   inline unsigned rotl32(unsigned Val, unsigned Amt) {
     94     assert(Amt < 32 && "Invalid rotate amount");
     95     return (Val << Amt) | (Val >> ((32-Amt)&31));
     96   }
     97 
     98   //===--------------------------------------------------------------------===//
     99   // Addressing Mode #1: shift_operand with registers
    100   //===--------------------------------------------------------------------===//
    101   //
    102   // This 'addressing mode' is used for arithmetic instructions.  It can
    103   // represent things like:
    104   //   reg
    105   //   reg [asr|lsl|lsr|ror|rrx] reg
    106   //   reg [asr|lsl|lsr|ror|rrx] imm
    107   //
    108   // This is stored three operands [rega, regb, opc].  The first is the base
    109   // reg, the second is the shift amount (or reg0 if not present or imm).  The
    110   // third operand encodes the shift opcode and the imm if a reg isn't present.
    111   //
    112   inline unsigned getSORegOpc(ShiftOpc ShOp, unsigned Imm) {
    113     return ShOp | (Imm << 3);
    114   }
    115   inline unsigned getSORegOffset(unsigned Op) { return Op >> 3; }
    116   inline ShiftOpc getSORegShOp(unsigned Op) { return (ShiftOpc)(Op & 7); }
    117 
    118   /// getSOImmValImm - Given an encoded imm field for the reg/imm form, return
    119   /// the 8-bit imm value.
    120   inline unsigned getSOImmValImm(unsigned Imm) { return Imm & 0xFF; }
    121   /// getSOImmValRot - Given an encoded imm field for the reg/imm form, return
    122   /// the rotate amount.
    123   inline unsigned getSOImmValRot(unsigned Imm) { return (Imm >> 8) * 2; }
    124 
    125   /// getSOImmValRotate - Try to handle Imm with an immediate shifter operand,
    126   /// computing the rotate amount to use.  If this immediate value cannot be
    127   /// handled with a single shifter-op, determine a good rotate amount that will
    128   /// take a maximal chunk of bits out of the immediate.
    129   inline unsigned getSOImmValRotate(unsigned Imm) {
    130     // 8-bit (or less) immediates are trivially shifter_operands with a rotate
    131     // of zero.
    132     if ((Imm & ~255U) == 0) return 0;
    133 
    134     // Use CTZ to compute the rotate amount.
    135     unsigned TZ = countTrailingZeros(Imm);
    136 
    137     // Rotate amount must be even.  Something like 0x200 must be rotated 8 bits,
    138     // not 9.
    139     unsigned RotAmt = TZ & ~1;
    140 
    141     // If we can handle this spread, return it.
    142     if ((rotr32(Imm, RotAmt) & ~255U) == 0)
    143       return (32-RotAmt)&31;  // HW rotates right, not left.
    144 
    145     // For values like 0xF000000F, we should ignore the low 6 bits, then
    146     // retry the hunt.
    147     if (Imm & 63U) {
    148       unsigned TZ2 = countTrailingZeros(Imm & ~63U);
    149       unsigned RotAmt2 = TZ2 & ~1;
    150       if ((rotr32(Imm, RotAmt2) & ~255U) == 0)
    151         return (32-RotAmt2)&31;  // HW rotates right, not left.
    152     }
    153 
    154     // Otherwise, we have no way to cover this span of bits with a single
    155     // shifter_op immediate.  Return a chunk of bits that will be useful to
    156     // handle.
    157     return (32-RotAmt)&31;  // HW rotates right, not left.
    158   }
    159 
    160   /// getSOImmVal - Given a 32-bit immediate, if it is something that can fit
    161   /// into an shifter_operand immediate operand, return the 12-bit encoding for
    162   /// it.  If not, return -1.
    163   inline int getSOImmVal(unsigned Arg) {
    164     // 8-bit (or less) immediates are trivially shifter_operands with a rotate
    165     // of zero.
    166     if ((Arg & ~255U) == 0) return Arg;
    167 
    168     unsigned RotAmt = getSOImmValRotate(Arg);
    169 
    170     // If this cannot be handled with a single shifter_op, bail out.
    171     if (rotr32(~255U, RotAmt) & Arg)
    172       return -1;
    173 
    174     // Encode this correctly.
    175     return rotl32(Arg, RotAmt) | ((RotAmt>>1) << 8);
    176   }
    177 
    178   /// isSOImmTwoPartVal - Return true if the specified value can be obtained by
    179   /// or'ing together two SOImmVal's.
    180   inline bool isSOImmTwoPartVal(unsigned V) {
    181     // If this can be handled with a single shifter_op, bail out.
    182     V = rotr32(~255U, getSOImmValRotate(V)) & V;
    183     if (V == 0)
    184       return false;
    185 
    186     // If this can be handled with two shifter_op's, accept.
    187     V = rotr32(~255U, getSOImmValRotate(V)) & V;
    188     return V == 0;
    189   }
    190 
    191   /// getSOImmTwoPartFirst - If V is a value that satisfies isSOImmTwoPartVal,
    192   /// return the first chunk of it.
    193   inline unsigned getSOImmTwoPartFirst(unsigned V) {
    194     return rotr32(255U, getSOImmValRotate(V)) & V;
    195   }
    196 
    197   /// getSOImmTwoPartSecond - If V is a value that satisfies isSOImmTwoPartVal,
    198   /// return the second chunk of it.
    199   inline unsigned getSOImmTwoPartSecond(unsigned V) {
    200     // Mask out the first hunk.
    201     V = rotr32(~255U, getSOImmValRotate(V)) & V;
    202 
    203     // Take what's left.
    204     assert(V == (rotr32(255U, getSOImmValRotate(V)) & V));
    205     return V;
    206   }
    207 
    208   /// isSOImmTwoPartValNeg - Return true if the specified value can be obtained
    209   /// by two SOImmVal, that -V = First + Second.
    210   /// "R+V" can be optimized to (sub (sub R, First), Second).
    211   /// "R=V" can be optimized to (sub (mvn R, ~(-First)), Second).
    212   inline bool isSOImmTwoPartValNeg(unsigned V) {
    213     unsigned First;
    214     if (!isSOImmTwoPartVal(-V))
    215       return false;
    216     // Return false if ~(-First) is not a SoImmval.
    217     First = getSOImmTwoPartFirst(-V);
    218     First = ~(-First);
    219     return !(rotr32(~255U, getSOImmValRotate(First)) & First);
    220   }
    221 
    222   /// getThumbImmValShift - Try to handle Imm with a 8-bit immediate followed
    223   /// by a left shift. Returns the shift amount to use.
    224   inline unsigned getThumbImmValShift(unsigned Imm) {
    225     // 8-bit (or less) immediates are trivially immediate operand with a shift
    226     // of zero.
    227     if ((Imm & ~255U) == 0) return 0;
    228 
    229     // Use CTZ to compute the shift amount.
    230     return countTrailingZeros(Imm);
    231   }
    232 
    233   /// isThumbImmShiftedVal - Return true if the specified value can be obtained
    234   /// by left shifting a 8-bit immediate.
    235   inline bool isThumbImmShiftedVal(unsigned V) {
    236     // If this can be handled with
    237     V = (~255U << getThumbImmValShift(V)) & V;
    238     return V == 0;
    239   }
    240 
    241   /// getThumbImm16ValShift - Try to handle Imm with a 16-bit immediate followed
    242   /// by a left shift. Returns the shift amount to use.
    243   inline unsigned getThumbImm16ValShift(unsigned Imm) {
    244     // 16-bit (or less) immediates are trivially immediate operand with a shift
    245     // of zero.
    246     if ((Imm & ~65535U) == 0) return 0;
    247 
    248     // Use CTZ to compute the shift amount.
    249     return countTrailingZeros(Imm);
    250   }
    251 
    252   /// isThumbImm16ShiftedVal - Return true if the specified value can be
    253   /// obtained by left shifting a 16-bit immediate.
    254   inline bool isThumbImm16ShiftedVal(unsigned V) {
    255     // If this can be handled with
    256     V = (~65535U << getThumbImm16ValShift(V)) & V;
    257     return V == 0;
    258   }
    259 
    260   /// getThumbImmNonShiftedVal - If V is a value that satisfies
    261   /// isThumbImmShiftedVal, return the non-shiftd value.
    262   inline unsigned getThumbImmNonShiftedVal(unsigned V) {
    263     return V >> getThumbImmValShift(V);
    264   }
    265 
    266 
    267   /// getT2SOImmValSplat - Return the 12-bit encoded representation
    268   /// if the specified value can be obtained by splatting the low 8 bits
    269   /// into every other byte or every byte of a 32-bit value. i.e.,
    270   ///     00000000 00000000 00000000 abcdefgh    control = 0
    271   ///     00000000 abcdefgh 00000000 abcdefgh    control = 1
    272   ///     abcdefgh 00000000 abcdefgh 00000000    control = 2
    273   ///     abcdefgh abcdefgh abcdefgh abcdefgh    control = 3
    274   /// Return -1 if none of the above apply.
    275   /// See ARM Reference Manual A6.3.2.
    276   inline int getT2SOImmValSplatVal(unsigned V) {
    277     unsigned u, Vs, Imm;
    278     // control = 0
    279     if ((V & 0xffffff00) == 0)
    280       return V;
    281 
    282     // If the value is zeroes in the first byte, just shift those off
    283     Vs = ((V & 0xff) == 0) ? V >> 8 : V;
    284     // Any passing value only has 8 bits of payload, splatted across the word
    285     Imm = Vs & 0xff;
    286     // Likewise, any passing values have the payload splatted into the 3rd byte
    287     u = Imm | (Imm << 16);
    288 
    289     // control = 1 or 2
    290     if (Vs == u)
    291       return (((Vs == V) ? 1 : 2) << 8) | Imm;
    292 
    293     // control = 3
    294     if (Vs == (u | (u << 8)))
    295       return (3 << 8) | Imm;
    296 
    297     return -1;
    298   }
    299 
    300   /// getT2SOImmValRotateVal - Return the 12-bit encoded representation if the
    301   /// specified value is a rotated 8-bit value. Return -1 if no rotation
    302   /// encoding is possible.
    303   /// See ARM Reference Manual A6.3.2.
    304   inline int getT2SOImmValRotateVal(unsigned V) {
    305     unsigned RotAmt = countLeadingZeros(V);
    306     if (RotAmt >= 24)
    307       return -1;
    308 
    309     // If 'Arg' can be handled with a single shifter_op return the value.
    310     if ((rotr32(0xff000000U, RotAmt) & V) == V)
    311       return (rotr32(V, 24 - RotAmt) & 0x7f) | ((RotAmt + 8) << 7);
    312 
    313     return -1;
    314   }
    315 
    316   /// getT2SOImmVal - Given a 32-bit immediate, if it is something that can fit
    317   /// into a Thumb-2 shifter_operand immediate operand, return the 12-bit
    318   /// encoding for it.  If not, return -1.
    319   /// See ARM Reference Manual A6.3.2.
    320   inline int getT2SOImmVal(unsigned Arg) {
    321     // If 'Arg' is an 8-bit splat, then get the encoded value.
    322     int Splat = getT2SOImmValSplatVal(Arg);
    323     if (Splat != -1)
    324       return Splat;
    325 
    326     // If 'Arg' can be handled with a single shifter_op return the value.
    327     int Rot = getT2SOImmValRotateVal(Arg);
    328     if (Rot != -1)
    329       return Rot;
    330 
    331     return -1;
    332   }
    333 
    334   inline unsigned getT2SOImmValRotate(unsigned V) {
    335     if ((V & ~255U) == 0) return 0;
    336     // Use CTZ to compute the rotate amount.
    337     unsigned RotAmt = countTrailingZeros(V);
    338     return (32 - RotAmt) & 31;
    339   }
    340 
    341   inline bool isT2SOImmTwoPartVal(unsigned Imm) {
    342     unsigned V = Imm;
    343     // Passing values can be any combination of splat values and shifter
    344     // values. If this can be handled with a single shifter or splat, bail
    345     // out. Those should be handled directly, not with a two-part val.
    346     if (getT2SOImmValSplatVal(V) != -1)
    347       return false;
    348     V = rotr32 (~255U, getT2SOImmValRotate(V)) & V;
    349     if (V == 0)
    350       return false;
    351 
    352     // If this can be handled as an immediate, accept.
    353     if (getT2SOImmVal(V) != -1) return true;
    354 
    355     // Likewise, try masking out a splat value first.
    356     V = Imm;
    357     if (getT2SOImmValSplatVal(V & 0xff00ff00U) != -1)
    358       V &= ~0xff00ff00U;
    359     else if (getT2SOImmValSplatVal(V & 0x00ff00ffU) != -1)
    360       V &= ~0x00ff00ffU;
    361     // If what's left can be handled as an immediate, accept.
    362     if (getT2SOImmVal(V) != -1) return true;
    363 
    364     // Otherwise, do not accept.
    365     return false;
    366   }
    367 
    368   inline unsigned getT2SOImmTwoPartFirst(unsigned Imm) {
    369     assert (isT2SOImmTwoPartVal(Imm) &&
    370             "Immedate cannot be encoded as two part immediate!");
    371     // Try a shifter operand as one part
    372     unsigned V = rotr32 (~255, getT2SOImmValRotate(Imm)) & Imm;
    373     // If the rest is encodable as an immediate, then return it.
    374     if (getT2SOImmVal(V) != -1) return V;
    375 
    376     // Try masking out a splat value first.
    377     if (getT2SOImmValSplatVal(Imm & 0xff00ff00U) != -1)
    378       return Imm & 0xff00ff00U;
    379 
    380     // The other splat is all that's left as an option.
    381     assert (getT2SOImmValSplatVal(Imm & 0x00ff00ffU) != -1);
    382     return Imm & 0x00ff00ffU;
    383   }
    384 
    385   inline unsigned getT2SOImmTwoPartSecond(unsigned Imm) {
    386     // Mask out the first hunk
    387     Imm ^= getT2SOImmTwoPartFirst(Imm);
    388     // Return what's left
    389     assert (getT2SOImmVal(Imm) != -1 &&
    390             "Unable to encode second part of T2 two part SO immediate");
    391     return Imm;
    392   }
    393 
    394 
    395   //===--------------------------------------------------------------------===//
    396   // Addressing Mode #2
    397   //===--------------------------------------------------------------------===//
    398   //
    399   // This is used for most simple load/store instructions.
    400   //
    401   // addrmode2 := reg +/- reg shop imm
    402   // addrmode2 := reg +/- imm12
    403   //
    404   // The first operand is always a Reg.  The second operand is a reg if in
    405   // reg/reg form, otherwise it's reg#0.  The third field encodes the operation
    406   // in bit 12, the immediate in bits 0-11, and the shift op in 13-15. The
    407   // fourth operand 16-17 encodes the index mode.
    408   //
    409   // If this addressing mode is a frame index (before prolog/epilog insertion
    410   // and code rewriting), this operand will have the form:  FI#, reg0, <offs>
    411   // with no shift amount for the frame offset.
    412   //
    413   inline unsigned getAM2Opc(AddrOpc Opc, unsigned Imm12, ShiftOpc SO,
    414                             unsigned IdxMode = 0) {
    415     assert(Imm12 < (1 << 12) && "Imm too large!");
    416     bool isSub = Opc == sub;
    417     return Imm12 | ((int)isSub << 12) | (SO << 13) | (IdxMode << 16) ;
    418   }
    419   inline unsigned getAM2Offset(unsigned AM2Opc) {
    420     return AM2Opc & ((1 << 12)-1);
    421   }
    422   inline AddrOpc getAM2Op(unsigned AM2Opc) {
    423     return ((AM2Opc >> 12) & 1) ? sub : add;
    424   }
    425   inline ShiftOpc getAM2ShiftOpc(unsigned AM2Opc) {
    426     return (ShiftOpc)((AM2Opc >> 13) & 7);
    427   }
    428   inline unsigned getAM2IdxMode(unsigned AM2Opc) { return (AM2Opc >> 16); }
    429 
    430   //===--------------------------------------------------------------------===//
    431   // Addressing Mode #3
    432   //===--------------------------------------------------------------------===//
    433   //
    434   // This is used for sign-extending loads, and load/store-pair instructions.
    435   //
    436   // addrmode3 := reg +/- reg
    437   // addrmode3 := reg +/- imm8
    438   //
    439   // The first operand is always a Reg.  The second operand is a reg if in
    440   // reg/reg form, otherwise it's reg#0.  The third field encodes the operation
    441   // in bit 8, the immediate in bits 0-7. The fourth operand 9-10 encodes the
    442   // index mode.
    443 
    444   /// getAM3Opc - This function encodes the addrmode3 opc field.
    445   inline unsigned getAM3Opc(AddrOpc Opc, unsigned char Offset,
    446                             unsigned IdxMode = 0) {
    447     bool isSub = Opc == sub;
    448     return ((int)isSub << 8) | Offset | (IdxMode << 9);
    449   }
    450   inline unsigned char getAM3Offset(unsigned AM3Opc) { return AM3Opc & 0xFF; }
    451   inline AddrOpc getAM3Op(unsigned AM3Opc) {
    452     return ((AM3Opc >> 8) & 1) ? sub : add;
    453   }
    454   inline unsigned getAM3IdxMode(unsigned AM3Opc) { return (AM3Opc >> 9); }
    455 
    456   //===--------------------------------------------------------------------===//
    457   // Addressing Mode #4
    458   //===--------------------------------------------------------------------===//
    459   //
    460   // This is used for load / store multiple instructions.
    461   //
    462   // addrmode4 := reg, <mode>
    463   //
    464   // The four modes are:
    465   //    IA - Increment after
    466   //    IB - Increment before
    467   //    DA - Decrement after
    468   //    DB - Decrement before
    469   // For VFP instructions, only the IA and DB modes are valid.
    470 
    471   inline AMSubMode getAM4SubMode(unsigned Mode) {
    472     return (AMSubMode)(Mode & 0x7);
    473   }
    474 
    475   inline unsigned getAM4ModeImm(AMSubMode SubMode) { return (int)SubMode; }
    476 
    477   //===--------------------------------------------------------------------===//
    478   // Addressing Mode #5
    479   //===--------------------------------------------------------------------===//
    480   //
    481   // This is used for coprocessor instructions, such as FP load/stores.
    482   //
    483   // addrmode5 := reg +/- imm8*4
    484   //
    485   // The first operand is always a Reg.  The second operand encodes the
    486   // operation (add or subtract) in bit 8 and the immediate in bits 0-7.
    487 
    488   /// getAM5Opc - This function encodes the addrmode5 opc field.
    489   inline unsigned getAM5Opc(AddrOpc Opc, unsigned char Offset) {
    490     bool isSub = Opc == sub;
    491     return ((int)isSub << 8) | Offset;
    492   }
    493   inline unsigned char getAM5Offset(unsigned AM5Opc) { return AM5Opc & 0xFF; }
    494   inline AddrOpc getAM5Op(unsigned AM5Opc) {
    495     return ((AM5Opc >> 8) & 1) ? sub : add;
    496   }
    497 
    498   //===--------------------------------------------------------------------===//
    499   // Addressing Mode #5 FP16
    500   //===--------------------------------------------------------------------===//
    501   //
    502   // This is used for coprocessor instructions, such as 16-bit FP load/stores.
    503   //
    504   // addrmode5fp16 := reg +/- imm8*2
    505   //
    506   // The first operand is always a Reg.  The second operand encodes the
    507   // operation (add or subtract) in bit 8 and the immediate in bits 0-7.
    508 
    509   /// getAM5FP16Opc - This function encodes the addrmode5fp16 opc field.
    510   inline unsigned getAM5FP16Opc(AddrOpc Opc, unsigned char Offset) {
    511     bool isSub = Opc == sub;
    512     return ((int)isSub << 8) | Offset;
    513   }
    514   inline unsigned char getAM5FP16Offset(unsigned AM5Opc) {
    515     return AM5Opc & 0xFF;
    516   }
    517   inline AddrOpc getAM5FP16Op(unsigned AM5Opc) {
    518     return ((AM5Opc >> 8) & 1) ? sub : add;
    519   }
    520 
    521   //===--------------------------------------------------------------------===//
    522   // Addressing Mode #6
    523   //===--------------------------------------------------------------------===//
    524   //
    525   // This is used for NEON load / store instructions.
    526   //
    527   // addrmode6 := reg with optional alignment
    528   //
    529   // This is stored in two operands [regaddr, align].  The first is the
    530   // address register.  The second operand is the value of the alignment
    531   // specifier in bytes or zero if no explicit alignment.
    532   // Valid alignments depend on the specific instruction.
    533 
    534   //===--------------------------------------------------------------------===//
    535   // NEON/MVE Modified Immediates
    536   //===--------------------------------------------------------------------===//
    537   //
    538   // Several NEON and MVE instructions (e.g., VMOV) take a "modified immediate"
    539   // vector operand, where a small immediate encoded in the instruction
    540   // specifies a full NEON vector value.  These modified immediates are
    541   // represented here as encoded integers.  The low 8 bits hold the immediate
    542   // value; bit 12 holds the "Op" field of the instruction, and bits 11-8 hold
    543   // the "Cmode" field of the instruction.  The interfaces below treat the
    544   // Op and Cmode values as a single 5-bit value.
    545 
    546   inline unsigned createVMOVModImm(unsigned OpCmode, unsigned Val) {
    547     return (OpCmode << 8) | Val;
    548   }
    549   inline unsigned getVMOVModImmOpCmode(unsigned ModImm) {
    550     return (ModImm >> 8) & 0x1f;
    551   }
    552   inline unsigned getVMOVModImmVal(unsigned ModImm) { return ModImm & 0xff; }
    553 
    554   /// decodeVMOVModImm - Decode a NEON/MVE modified immediate value into the
    555   /// element value and the element size in bits.  (If the element size is
    556   /// smaller than the vector, it is splatted into all the elements.)
    557   inline uint64_t decodeVMOVModImm(unsigned ModImm, unsigned &EltBits) {
    558     unsigned OpCmode = getVMOVModImmOpCmode(ModImm);
    559     unsigned Imm8 = getVMOVModImmVal(ModImm);
    560     uint64_t Val = 0;
    561 
    562     if (OpCmode == 0xe) {
    563       // 8-bit vector elements
    564       Val = Imm8;
    565       EltBits = 8;
    566     } else if ((OpCmode & 0xc) == 0x8) {
    567       // 16-bit vector elements
    568       unsigned ByteNum = (OpCmode & 0x6) >> 1;
    569       Val = Imm8 << (8 * ByteNum);
    570       EltBits = 16;
    571     } else if ((OpCmode & 0x8) == 0) {
    572       // 32-bit vector elements, zero with one byte set
    573       unsigned ByteNum = (OpCmode & 0x6) >> 1;
    574       Val = Imm8 << (8 * ByteNum);
    575       EltBits = 32;
    576     } else if ((OpCmode & 0xe) == 0xc) {
    577       // 32-bit vector elements, one byte with low bits set
    578       unsigned ByteNum = 1 + (OpCmode & 0x1);
    579       Val = (Imm8 << (8 * ByteNum)) | (0xffff >> (8 * (2 - ByteNum)));
    580       EltBits = 32;
    581     } else if (OpCmode == 0x1e) {
    582       // 64-bit vector elements
    583       for (unsigned ByteNum = 0; ByteNum < 8; ++ByteNum) {
    584         if ((ModImm >> ByteNum) & 1)
    585           Val |= (uint64_t)0xff << (8 * ByteNum);
    586       }
    587       EltBits = 64;
    588     } else {
    589       llvm_unreachable("Unsupported VMOV immediate");
    590     }
    591     return Val;
    592   }
    593 
    594   // Generic validation for single-byte immediate (0X00, 00X0, etc).
    595   inline bool isNEONBytesplat(unsigned Value, unsigned Size) {
    596     assert(Size >= 1 && Size <= 4 && "Invalid size");
    597     unsigned count = 0;
    598     for (unsigned i = 0; i < Size; ++i) {
    599       if (Value & 0xff) count++;
    600       Value >>= 8;
    601     }
    602     return count == 1;
    603   }
    604 
    605   /// Checks if Value is a correct immediate for instructions like VBIC/VORR.
    606   inline bool isNEONi16splat(unsigned Value) {
    607     if (Value > 0xffff)
    608       return false;
    609     // i16 value with set bits only in one byte X0 or 0X.
    610     return Value == 0 || isNEONBytesplat(Value, 2);
    611   }
    612 
    613   // Encode NEON 16 bits Splat immediate for instructions like VBIC/VORR
    614   inline unsigned encodeNEONi16splat(unsigned Value) {
    615     assert(isNEONi16splat(Value) && "Invalid NEON splat value");
    616     if (Value >= 0x100)
    617       Value = (Value >> 8) | 0xa00;
    618     else
    619       Value |= 0x800;
    620     return Value;
    621   }
    622 
    623   /// Checks if Value is a correct immediate for instructions like VBIC/VORR.
    624   inline bool isNEONi32splat(unsigned Value) {
    625     // i32 value with set bits only in one byte X000, 0X00, 00X0, or 000X.
    626     return Value == 0 || isNEONBytesplat(Value, 4);
    627   }
    628 
    629   /// Encode NEON 32 bits Splat immediate for instructions like VBIC/VORR.
    630   inline unsigned encodeNEONi32splat(unsigned Value) {
    631     assert(isNEONi32splat(Value) && "Invalid NEON splat value");
    632     if (Value >= 0x100 && Value <= 0xff00)
    633       Value = (Value >> 8) | 0x200;
    634     else if (Value > 0xffff && Value <= 0xff0000)
    635       Value = (Value >> 16) | 0x400;
    636     else if (Value > 0xffffff)
    637       Value = (Value >> 24) | 0x600;
    638     return Value;
    639   }
    640 
    641   //===--------------------------------------------------------------------===//
    642   // Floating-point Immediates
    643   //
    644   inline float getFPImmFloat(unsigned Imm) {
    645     // We expect an 8-bit binary encoding of a floating-point number here.
    646 
    647     uint8_t Sign = (Imm >> 7) & 0x1;
    648     uint8_t Exp = (Imm >> 4) & 0x7;
    649     uint8_t Mantissa = Imm & 0xf;
    650 
    651     //   8-bit FP    IEEE Float Encoding
    652     //   abcd efgh   aBbbbbbc defgh000 00000000 00000000
    653     //
    654     // where B = NOT(b);
    655     uint32_t I = 0;
    656     I |= Sign << 31;
    657     I |= ((Exp & 0x4) != 0 ? 0 : 1) << 30;
    658     I |= ((Exp & 0x4) != 0 ? 0x1f : 0) << 25;
    659     I |= (Exp & 0x3) << 23;
    660     I |= Mantissa << 19;
    661     return bit_cast<float>(I);
    662   }
    663 
    664   /// getFP16Imm - Return an 8-bit floating-point version of the 16-bit
    665   /// floating-point value. If the value cannot be represented as an 8-bit
    666   /// floating-point value, then return -1.
    667   inline int getFP16Imm(const APInt &Imm) {
    668     uint32_t Sign = Imm.lshr(15).getZExtValue() & 1;
    669     int32_t Exp = (Imm.lshr(10).getSExtValue() & 0x1f) - 15;  // -14 to 15
    670     int64_t Mantissa = Imm.getZExtValue() & 0x3ff;  // 10 bits
    671 
    672     // We can handle 4 bits of mantissa.
    673     // mantissa = (16+UInt(e:f:g:h))/16.
    674     if (Mantissa & 0x3f)
    675       return -1;
    676     Mantissa >>= 6;
    677 
    678     // We can handle 3 bits of exponent: exp == UInt(NOT(b):c:d)-3
    679     if (Exp < -3 || Exp > 4)
    680       return -1;
    681     Exp = ((Exp+3) & 0x7) ^ 4;
    682 
    683     return ((int)Sign << 7) | (Exp << 4) | Mantissa;
    684   }
    685 
    686   inline int getFP16Imm(const APFloat &FPImm) {
    687     return getFP16Imm(FPImm.bitcastToAPInt());
    688   }
    689 
    690   /// If this is a FP16Imm encoded as a fp32 value, return the 8-bit encoding
    691   /// for it. Otherwise return -1 like getFP16Imm.
    692   inline int getFP32FP16Imm(const APInt &Imm) {
    693     if (Imm.getActiveBits() > 16)
    694       return -1;
    695     return ARM_AM::getFP16Imm(Imm.trunc(16));
    696   }
    697 
    698   inline int getFP32FP16Imm(const APFloat &FPImm) {
    699     return getFP32FP16Imm(FPImm.bitcastToAPInt());
    700   }
    701 
    702   /// getFP32Imm - Return an 8-bit floating-point version of the 32-bit
    703   /// floating-point value. If the value cannot be represented as an 8-bit
    704   /// floating-point value, then return -1.
    705   inline int getFP32Imm(const APInt &Imm) {
    706     uint32_t Sign = Imm.lshr(31).getZExtValue() & 1;
    707     int32_t Exp = (Imm.lshr(23).getSExtValue() & 0xff) - 127;  // -126 to 127
    708     int64_t Mantissa = Imm.getZExtValue() & 0x7fffff;  // 23 bits
    709 
    710     // We can handle 4 bits of mantissa.
    711     // mantissa = (16+UInt(e:f:g:h))/16.
    712     if (Mantissa & 0x7ffff)
    713       return -1;
    714     Mantissa >>= 19;
    715     if ((Mantissa & 0xf) != Mantissa)
    716       return -1;
    717 
    718     // We can handle 3 bits of exponent: exp == UInt(NOT(b):c:d)-3
    719     if (Exp < -3 || Exp > 4)
    720       return -1;
    721     Exp = ((Exp+3) & 0x7) ^ 4;
    722 
    723     return ((int)Sign << 7) | (Exp << 4) | Mantissa;
    724   }
    725 
    726   inline int getFP32Imm(const APFloat &FPImm) {
    727     return getFP32Imm(FPImm.bitcastToAPInt());
    728   }
    729 
    730   /// getFP64Imm - Return an 8-bit floating-point version of the 64-bit
    731   /// floating-point value. If the value cannot be represented as an 8-bit
    732   /// floating-point value, then return -1.
    733   inline int getFP64Imm(const APInt &Imm) {
    734     uint64_t Sign = Imm.lshr(63).getZExtValue() & 1;
    735     int64_t Exp = (Imm.lshr(52).getSExtValue() & 0x7ff) - 1023; // -1022 to 1023
    736     uint64_t Mantissa = Imm.getZExtValue() & 0xfffffffffffffULL;
    737 
    738     // We can handle 4 bits of mantissa.
    739     // mantissa = (16+UInt(e:f:g:h))/16.
    740     if (Mantissa & 0xffffffffffffULL)
    741       return -1;
    742     Mantissa >>= 48;
    743     if ((Mantissa & 0xf) != Mantissa)
    744       return -1;
    745 
    746     // We can handle 3 bits of exponent: exp == UInt(NOT(b):c:d)-3
    747     if (Exp < -3 || Exp > 4)
    748       return -1;
    749     Exp = ((Exp+3) & 0x7) ^ 4;
    750 
    751     return ((int)Sign << 7) | (Exp << 4) | Mantissa;
    752   }
    753 
    754   inline int getFP64Imm(const APFloat &FPImm) {
    755     return getFP64Imm(FPImm.bitcastToAPInt());
    756   }
    757 
    758 } // end namespace ARM_AM
    759 } // end namespace llvm
    760 
    761 #endif
    762 
    763