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

Generated by: LCOV version 1.13