Home | History | Annotate | Download | only in AArch64
      1 //===- AArch64InsnHelpers.h -----------------------------------------------===//
      2 //
      3 //                     The MCLinker Project
      4 //
      5 // This file is distributed under the University of Illinois Open Source
      6 // License. See LICENSE.TXT for details.
      7 //
      8 //===----------------------------------------------------------------------===//
      9 #ifndef TARGET_AARCH64_AARCH64INSNHELPERS_H_
     10 #define TARGET_AARCH64_AARCH64INSNHELPERS_H_
     11 
     12 #include "mcld/Support/Compiler.h"
     13 
     14 namespace mcld {
     15 
     16 class AArch64InsnHelpers {
     17  public:
     18   typedef uint32_t InsnType;
     19 
     20   static constexpr unsigned InsnSize = 4;
     21 
     22   // Zero register encoding - 31.
     23   static constexpr unsigned ZR = 31;
     24 
     25   static unsigned getBits(InsnType insn, int pos, int l) {
     26     return (insn >> pos) & ((1 << l) - 1);
     27   }
     28 
     29   static unsigned getRt(InsnType insn) {
     30     return getBits(insn, 0, 5);
     31   }
     32 
     33   static unsigned getRt2(InsnType insn) {
     34     return getBits(insn, 10, 5);
     35   }
     36 
     37   static unsigned getRa(InsnType insn) {
     38     return getBits(insn, 10, 5);
     39   }
     40 
     41   static unsigned getRd(InsnType insn) {
     42     return getBits(insn, 0, 5);
     43   }
     44 
     45   static unsigned getRn(InsnType insn) {
     46     return getBits(insn, 5, 5);
     47   }
     48 
     49   static unsigned getRm(InsnType insn) {
     50     return getBits(insn, 16, 5);
     51   }
     52 
     53   static unsigned getBit(InsnType insn, int pos) {
     54     return getBits(insn, pos, 1);
     55   }
     56 
     57   static unsigned getOp31(InsnType insn) {
     58     return getBits(insn, 21, 3);
     59   }
     60 
     61   // All ld/st ops. See C4-182 of the ARM ARM. The encoding space for LD_PCREL,
     62   // LDST_RO, LDST_UI and LDST_UIMM cover prefetch ops.
     63   static bool isLD(InsnType insn) {
     64     return (getBit(insn, 22) == 1);
     65   }
     66 
     67   static bool isLDST(InsnType insn) {
     68     return (((insn) & 0x0a000000) == 0x08000000);
     69   }
     70 
     71   static bool isLDSTEX(InsnType insn) {
     72     return (((insn) & 0x3f000000) == 0x08000000);
     73   }
     74 
     75   static bool isLDSTPCREL(InsnType insn) {
     76     return (((insn) & 0x3b000000) == 0x18000000);
     77   }
     78 
     79   static bool isLDSTNAP(InsnType insn) {
     80     return (((insn) & 0x3b800000) == 0x28000000);
     81   }
     82 
     83   static bool isLDSTPPI(InsnType insn) {
     84     return (((insn) & 0x3b800000) == 0x28800000);
     85   }
     86 
     87   static bool isLDSTPO(InsnType insn) {
     88     return (((insn) & 0x3b800000) == 0x29000000);
     89   }
     90 
     91   static bool isLDSTPPRE(InsnType insn) {
     92     return (((insn) & 0x3b800000) == 0x29800000);
     93   }
     94 
     95   static bool isLDSTUI(InsnType insn) {
     96     return (((insn) & 0x3b200c00) == 0x38000000);
     97   }
     98 
     99   static bool isLDSTPIIMM(InsnType insn) {
    100     return (((insn) & 0x3b200c00) == 0x38000400);
    101   }
    102 
    103   static bool isLDSTU(InsnType insn) {
    104     return (((insn) & 0x3b200c00) == 0x38000800);
    105   }
    106 
    107   static bool isLDSTPREIMM(InsnType insn) {
    108     return (((insn) & 0x3b200c00) == 0x38000c00);
    109   }
    110 
    111   static bool isLDSTRO(InsnType insn) {
    112     return (((insn) & 0x3b200c00) == 0x38200800);
    113   }
    114 
    115   static bool isLDSTUIMM(InsnType insn) {
    116     return (((insn) & 0x3b000000) == 0x39000000);
    117   }
    118 
    119   static bool isLDSTSIMDM(InsnType insn) {
    120     return (((insn) & 0xbfbf0000) == 0x0c000000);
    121   }
    122 
    123   static bool isLDSTSIMDMPI(InsnType insn) {
    124     return (((insn) & 0xbfa00000) == 0x0c800000);
    125   }
    126 
    127   static bool isLDSTSIMDS(InsnType insn) {
    128     return (((insn) & 0xbf9f0000) == 0x0d000000);
    129   }
    130 
    131   static bool isLDSTSIMDSPI(InsnType insn) {
    132     return (((insn) & 0xbf800000) == 0x0d800000);
    133   }
    134 
    135   // Return true if INSN is a mac insn.
    136   static bool isMAC(InsnType insn) {
    137     return (insn & 0xff000000) == 0x9b000000;
    138   }
    139 
    140   // Return true if INSN is multiply-accumulate
    141   static bool isMLXL(InsnType insn) {
    142     unsigned op31 = getOp31(insn);
    143     // Exclude MUL instructions which are encoded as a multiple-accumulate with
    144     // RA = XZR
    145     if (isMAC(insn) &&
    146         ((op31 == 0) || (op31 == 1) || (op31 == 5)) &&
    147         getRa(insn) != ZR) {
    148       return true;
    149     }
    150     return false;
    151   }
    152 
    153   // Classify an INSN if it is indeed a load/store.
    154   //
    155   // Return true if INSN is a LD/ST instruction otherwise return false. For
    156   // scalar LD/ST instructions is_pair is false, rt is returned and rt2 is set
    157   // equal to rt. For LD/ST pair instructions is_pair is true, rt and rt2 are
    158   // returned.
    159   static bool isMemOp(InsnType insn,
    160                       unsigned& rt,
    161                       unsigned& rt2,
    162                       bool& is_pair,
    163                       bool& is_load) {
    164     // Bail out quickly if INSN doesn't fall into the the load-store encoding
    165     // space.
    166     if (!isLDST(insn)) {
    167       return false;
    168     }
    169 
    170     is_pair = false;
    171     is_load = false;
    172 
    173     if (isLDSTEX(insn)) {
    174       rt = getRt(insn);
    175       rt2 = rt;
    176       if (getBit(insn, 21) == 1) {
    177         is_pair = true;
    178         rt2 = getRt2(insn);
    179       }
    180       is_load = isLD(insn);
    181       return true;
    182     } else if (isLDSTNAP(insn) ||
    183                isLDSTPPI(insn) ||
    184                isLDSTPO(insn) ||
    185                isLDSTPPRE(insn)) {
    186       rt = getRt(insn);
    187       rt2 = getRt2(insn);
    188       is_pair = true;
    189       is_load = isLD(insn);
    190     } else if (isLDSTPCREL(insn) ||
    191                isLDSTUI(insn) ||
    192                isLDSTPIIMM(insn) ||
    193                isLDSTU(insn) ||
    194                isLDSTPREIMM(insn) ||
    195                isLDSTRO(insn) ||
    196                isLDSTUIMM(insn)) {
    197       rt = getRt(insn);
    198       rt2 = rt;
    199       unsigned opc = getBits(insn, 22, 2);
    200       unsigned v = getBit(insn, 26);
    201       unsigned opc_v = opc | (v << 2);
    202       if (isLDSTPCREL(insn) ||
    203           ((opc_v == 1) ||
    204            (opc_v == 2) ||
    205            (opc_v == 3) ||
    206            (opc_v == 5) ||
    207            (opc_v == 7))) {
    208         is_load = true;
    209       }
    210       return true;
    211     } else if (isLDSTSIMDM(insn) || isLDSTSIMDMPI(insn)) {
    212       unsigned opcode = (insn >> 12) & 0xf;
    213       rt = getRt(insn);
    214       is_load = (getBit(insn, 22) != 0);
    215       switch (opcode) {
    216         case 0:
    217         case 2: {
    218           rt2 = rt + 3;
    219           return true;
    220         }
    221         case 4:
    222         case 6: {
    223           rt2 = rt + 2;
    224           return true;
    225         }
    226         case 7: {
    227           rt2 = rt;
    228           return true;
    229         }
    230         case 8:
    231         case 10: {
    232           rt2 = rt + 1;
    233           return true;
    234         }
    235         default: {
    236           return false;
    237         }
    238       }  // switch (opcode)
    239     } else if (isLDSTSIMDS(insn) || isLDSTSIMDSPI(insn)) {
    240       unsigned r = (insn >> 21) & 1;
    241       unsigned opcode = (insn >> 13) & 0x7;
    242       rt = getRt(insn);
    243       is_load = (getBit(insn, 22) != 0);
    244       switch (opcode) {
    245         case 0:
    246         case 2:
    247         case 4:
    248         case 6: {
    249           rt2 = rt + r;
    250           return true;
    251         }
    252         case 1:
    253         case 3:
    254         case 5:
    255         case 7: {
    256           rt2 = rt + ((r == 0) ? 2 : 3);
    257           return true;
    258         }
    259         default: {
    260           return false;
    261         }
    262       }  // switch (opcode)
    263     }
    264 
    265     return false;
    266   }
    267 
    268   static InsnType buildBranchInsn() {
    269     return 0x14000000;
    270   }
    271 
    272  private:
    273   DISALLOW_IMPLICIT_CONSTRUCTORS(AArch64InsnHelpers);
    274 };
    275 
    276 }  // namespace mcld
    277 
    278 #endif  // TARGET_AARCH64_AARCH64INSNHELPERS_H_
    279