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

Generated by: LCOV version 1.13