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 getBits(InsnType insn,int pos,int l)25 static unsigned getBits(InsnType insn, int pos, int l) { 26 return (insn >> pos) & ((1 << l) - 1); 27 } 28 getRt(InsnType insn)29 static unsigned getRt(InsnType insn) { 30 return getBits(insn, 0, 5); 31 } 32 getRt2(InsnType insn)33 static unsigned getRt2(InsnType insn) { 34 return getBits(insn, 10, 5); 35 } 36 getRa(InsnType insn)37 static unsigned getRa(InsnType insn) { 38 return getBits(insn, 10, 5); 39 } 40 getRd(InsnType insn)41 static unsigned getRd(InsnType insn) { 42 return getBits(insn, 0, 5); 43 } 44 getRn(InsnType insn)45 static unsigned getRn(InsnType insn) { 46 return getBits(insn, 5, 5); 47 } 48 getRm(InsnType insn)49 static unsigned getRm(InsnType insn) { 50 return getBits(insn, 16, 5); 51 } 52 getBit(InsnType insn,int pos)53 static unsigned getBit(InsnType insn, int pos) { 54 return getBits(insn, pos, 1); 55 } 56 getOp31(InsnType insn)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. isLD(InsnType insn)63 static bool isLD(InsnType insn) { 64 return (getBit(insn, 22) == 1); 65 } 66 isLDST(InsnType insn)67 static bool isLDST(InsnType insn) { 68 return (((insn) & 0x0a000000) == 0x08000000); 69 } 70 isLDSTEX(InsnType insn)71 static bool isLDSTEX(InsnType insn) { 72 return (((insn) & 0x3f000000) == 0x08000000); 73 } 74 isLDSTPCREL(InsnType insn)75 static bool isLDSTPCREL(InsnType insn) { 76 return (((insn) & 0x3b000000) == 0x18000000); 77 } 78 isLDSTNAP(InsnType insn)79 static bool isLDSTNAP(InsnType insn) { 80 return (((insn) & 0x3b800000) == 0x28000000); 81 } 82 isLDSTPPI(InsnType insn)83 static bool isLDSTPPI(InsnType insn) { 84 return (((insn) & 0x3b800000) == 0x28800000); 85 } 86 isLDSTPO(InsnType insn)87 static bool isLDSTPO(InsnType insn) { 88 return (((insn) & 0x3b800000) == 0x29000000); 89 } 90 isLDSTPPRE(InsnType insn)91 static bool isLDSTPPRE(InsnType insn) { 92 return (((insn) & 0x3b800000) == 0x29800000); 93 } 94 isLDSTUI(InsnType insn)95 static bool isLDSTUI(InsnType insn) { 96 return (((insn) & 0x3b200c00) == 0x38000000); 97 } 98 isLDSTPIIMM(InsnType insn)99 static bool isLDSTPIIMM(InsnType insn) { 100 return (((insn) & 0x3b200c00) == 0x38000400); 101 } 102 isLDSTU(InsnType insn)103 static bool isLDSTU(InsnType insn) { 104 return (((insn) & 0x3b200c00) == 0x38000800); 105 } 106 isLDSTPREIMM(InsnType insn)107 static bool isLDSTPREIMM(InsnType insn) { 108 return (((insn) & 0x3b200c00) == 0x38000c00); 109 } 110 isLDSTRO(InsnType insn)111 static bool isLDSTRO(InsnType insn) { 112 return (((insn) & 0x3b200c00) == 0x38200800); 113 } 114 isLDSTUIMM(InsnType insn)115 static bool isLDSTUIMM(InsnType insn) { 116 return (((insn) & 0x3b000000) == 0x39000000); 117 } 118 isLDSTSIMDM(InsnType insn)119 static bool isLDSTSIMDM(InsnType insn) { 120 return (((insn) & 0xbfbf0000) == 0x0c000000); 121 } 122 isLDSTSIMDMPI(InsnType insn)123 static bool isLDSTSIMDMPI(InsnType insn) { 124 return (((insn) & 0xbfa00000) == 0x0c800000); 125 } 126 isLDSTSIMDS(InsnType insn)127 static bool isLDSTSIMDS(InsnType insn) { 128 return (((insn) & 0xbf9f0000) == 0x0d000000); 129 } 130 isLDSTSIMDSPI(InsnType insn)131 static bool isLDSTSIMDSPI(InsnType insn) { 132 return (((insn) & 0xbf800000) == 0x0d800000); 133 } 134 135 // Return true if INSN is a mac insn. isMAC(InsnType insn)136 static bool isMAC(InsnType insn) { 137 return (insn & 0xff000000) == 0x9b000000; 138 } 139 140 // Return true if INSN is multiply-accumulate isMLXL(InsnType insn)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. isMemOp(InsnType insn,unsigned & rt,unsigned & rt2,bool & is_pair,bool & is_load)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 buildBranchInsn()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