AArch64InsnHelpers.h revision cfcb22478ca64c308df58f9abe6fa2dedb213c16
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
14namespace mcld {
15
16class 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