LCOV - code coverage report
Current view: top level - lib/Target/ARM/MCTargetDesc - ARMAddressingModes.h (source / functions) Hit Total Coverage
Test: llvm-toolchain.info Lines: 173 181 95.6 %
Date: 2017-09-14 15:23:50 Functions: 13 13 100.0 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.13