File: | lib/Target/AArch64/InstPrinter/AArch64InstPrinter.cpp |
Warning: | line 327, column 8 Excessive padding in 'struct LdStNInstrDesc' (11 padding bytes, where 3 is optimal). Optimal fields order: Mnemonic, Layout, Opcode, ListOperand, NaturalOffset, HasLane, consider reordering the fields or adding explicit padding members |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
1 | //==-- AArch64InstPrinter.cpp - Convert AArch64 MCInst to assembly syntax --==// |
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 class prints an AArch64 MCInst to a .s file. |
11 | // |
12 | //===----------------------------------------------------------------------===// |
13 | |
14 | #include "AArch64InstPrinter.h" |
15 | #include "MCTargetDesc/AArch64AddressingModes.h" |
16 | #include "Utils/AArch64BaseInfo.h" |
17 | #include "llvm/ADT/STLExtras.h" |
18 | #include "llvm/ADT/StringExtras.h" |
19 | #include "llvm/ADT/StringRef.h" |
20 | #include "llvm/MC/MCAsmInfo.h" |
21 | #include "llvm/MC/MCExpr.h" |
22 | #include "llvm/MC/MCInst.h" |
23 | #include "llvm/MC/MCRegisterInfo.h" |
24 | #include "llvm/MC/MCSubtargetInfo.h" |
25 | #include "llvm/Support/Casting.h" |
26 | #include "llvm/Support/ErrorHandling.h" |
27 | #include "llvm/Support/Format.h" |
28 | #include "llvm/Support/MathExtras.h" |
29 | #include "llvm/Support/raw_ostream.h" |
30 | #include <cassert> |
31 | #include <cstdint> |
32 | #include <string> |
33 | |
34 | using namespace llvm; |
35 | |
36 | #define DEBUG_TYPE"asm-printer" "asm-printer" |
37 | |
38 | #define GET_INSTRUCTION_NAME |
39 | #define PRINT_ALIAS_INSTR |
40 | #include "AArch64GenAsmWriter.inc" |
41 | #define GET_INSTRUCTION_NAME |
42 | #define PRINT_ALIAS_INSTR |
43 | #include "AArch64GenAsmWriter1.inc" |
44 | |
45 | AArch64InstPrinter::AArch64InstPrinter(const MCAsmInfo &MAI, |
46 | const MCInstrInfo &MII, |
47 | const MCRegisterInfo &MRI) |
48 | : MCInstPrinter(MAI, MII, MRI) {} |
49 | |
50 | AArch64AppleInstPrinter::AArch64AppleInstPrinter(const MCAsmInfo &MAI, |
51 | const MCInstrInfo &MII, |
52 | const MCRegisterInfo &MRI) |
53 | : AArch64InstPrinter(MAI, MII, MRI) {} |
54 | |
55 | void AArch64InstPrinter::printRegName(raw_ostream &OS, unsigned RegNo) const { |
56 | // This is for .cfi directives. |
57 | OS << getRegisterName(RegNo); |
58 | } |
59 | |
60 | void AArch64InstPrinter::printInst(const MCInst *MI, raw_ostream &O, |
61 | StringRef Annot, |
62 | const MCSubtargetInfo &STI) { |
63 | // Check for special encodings and print the canonical alias instead. |
64 | |
65 | unsigned Opcode = MI->getOpcode(); |
66 | |
67 | if (Opcode == AArch64::SYSxt) |
68 | if (printSysAlias(MI, STI, O)) { |
69 | printAnnotation(O, Annot); |
70 | return; |
71 | } |
72 | |
73 | // SBFM/UBFM should print to a nicer aliased form if possible. |
74 | if (Opcode == AArch64::SBFMXri || Opcode == AArch64::SBFMWri || |
75 | Opcode == AArch64::UBFMXri || Opcode == AArch64::UBFMWri) { |
76 | const MCOperand &Op0 = MI->getOperand(0); |
77 | const MCOperand &Op1 = MI->getOperand(1); |
78 | const MCOperand &Op2 = MI->getOperand(2); |
79 | const MCOperand &Op3 = MI->getOperand(3); |
80 | |
81 | bool IsSigned = (Opcode == AArch64::SBFMXri || Opcode == AArch64::SBFMWri); |
82 | bool Is64Bit = (Opcode == AArch64::SBFMXri || Opcode == AArch64::UBFMXri); |
83 | if (Op2.isImm() && Op2.getImm() == 0 && Op3.isImm()) { |
84 | const char *AsmMnemonic = nullptr; |
85 | |
86 | switch (Op3.getImm()) { |
87 | default: |
88 | break; |
89 | case 7: |
90 | if (IsSigned) |
91 | AsmMnemonic = "sxtb"; |
92 | else if (!Is64Bit) |
93 | AsmMnemonic = "uxtb"; |
94 | break; |
95 | case 15: |
96 | if (IsSigned) |
97 | AsmMnemonic = "sxth"; |
98 | else if (!Is64Bit) |
99 | AsmMnemonic = "uxth"; |
100 | break; |
101 | case 31: |
102 | // *xtw is only valid for signed 64-bit operations. |
103 | if (Is64Bit && IsSigned) |
104 | AsmMnemonic = "sxtw"; |
105 | break; |
106 | } |
107 | |
108 | if (AsmMnemonic) { |
109 | O << '\t' << AsmMnemonic << '\t' << getRegisterName(Op0.getReg()) |
110 | << ", " << getRegisterName(getWRegFromXReg(Op1.getReg())); |
111 | printAnnotation(O, Annot); |
112 | return; |
113 | } |
114 | } |
115 | |
116 | // All immediate shifts are aliases, implemented using the Bitfield |
117 | // instruction. In all cases the immediate shift amount shift must be in |
118 | // the range 0 to (reg.size -1). |
119 | if (Op2.isImm() && Op3.isImm()) { |
120 | const char *AsmMnemonic = nullptr; |
121 | int shift = 0; |
122 | int64_t immr = Op2.getImm(); |
123 | int64_t imms = Op3.getImm(); |
124 | if (Opcode == AArch64::UBFMWri && imms != 0x1F && ((imms + 1) == immr)) { |
125 | AsmMnemonic = "lsl"; |
126 | shift = 31 - imms; |
127 | } else if (Opcode == AArch64::UBFMXri && imms != 0x3f && |
128 | ((imms + 1 == immr))) { |
129 | AsmMnemonic = "lsl"; |
130 | shift = 63 - imms; |
131 | } else if (Opcode == AArch64::UBFMWri && imms == 0x1f) { |
132 | AsmMnemonic = "lsr"; |
133 | shift = immr; |
134 | } else if (Opcode == AArch64::UBFMXri && imms == 0x3f) { |
135 | AsmMnemonic = "lsr"; |
136 | shift = immr; |
137 | } else if (Opcode == AArch64::SBFMWri && imms == 0x1f) { |
138 | AsmMnemonic = "asr"; |
139 | shift = immr; |
140 | } else if (Opcode == AArch64::SBFMXri && imms == 0x3f) { |
141 | AsmMnemonic = "asr"; |
142 | shift = immr; |
143 | } |
144 | if (AsmMnemonic) { |
145 | O << '\t' << AsmMnemonic << '\t' << getRegisterName(Op0.getReg()) |
146 | << ", " << getRegisterName(Op1.getReg()) << ", #" << shift; |
147 | printAnnotation(O, Annot); |
148 | return; |
149 | } |
150 | } |
151 | |
152 | // SBFIZ/UBFIZ aliases |
153 | if (Op2.getImm() > Op3.getImm()) { |
154 | O << '\t' << (IsSigned ? "sbfiz" : "ubfiz") << '\t' |
155 | << getRegisterName(Op0.getReg()) << ", " << getRegisterName(Op1.getReg()) |
156 | << ", #" << (Is64Bit ? 64 : 32) - Op2.getImm() << ", #" << Op3.getImm() + 1; |
157 | printAnnotation(O, Annot); |
158 | return; |
159 | } |
160 | |
161 | // Otherwise SBFX/UBFX is the preferred form |
162 | O << '\t' << (IsSigned ? "sbfx" : "ubfx") << '\t' |
163 | << getRegisterName(Op0.getReg()) << ", " << getRegisterName(Op1.getReg()) |
164 | << ", #" << Op2.getImm() << ", #" << Op3.getImm() - Op2.getImm() + 1; |
165 | printAnnotation(O, Annot); |
166 | return; |
167 | } |
168 | |
169 | if (Opcode == AArch64::BFMXri || Opcode == AArch64::BFMWri) { |
170 | const MCOperand &Op0 = MI->getOperand(0); // Op1 == Op0 |
171 | const MCOperand &Op2 = MI->getOperand(2); |
172 | int ImmR = MI->getOperand(3).getImm(); |
173 | int ImmS = MI->getOperand(4).getImm(); |
174 | |
175 | if ((Op2.getReg() == AArch64::WZR || Op2.getReg() == AArch64::XZR) && |
176 | (ImmR == 0 || ImmS < ImmR)) { |
177 | // BFC takes precedence over its entire range, sligtly differently to BFI. |
178 | int BitWidth = Opcode == AArch64::BFMXri ? 64 : 32; |
179 | int LSB = (BitWidth - ImmR) % BitWidth; |
180 | int Width = ImmS + 1; |
181 | |
182 | O << "\tbfc\t" << getRegisterName(Op0.getReg()) |
183 | << ", #" << LSB << ", #" << Width; |
184 | printAnnotation(O, Annot); |
185 | return; |
186 | } else if (ImmS < ImmR) { |
187 | // BFI alias |
188 | int BitWidth = Opcode == AArch64::BFMXri ? 64 : 32; |
189 | int LSB = (BitWidth - ImmR) % BitWidth; |
190 | int Width = ImmS + 1; |
191 | |
192 | O << "\tbfi\t" << getRegisterName(Op0.getReg()) << ", " |
193 | << getRegisterName(Op2.getReg()) << ", #" << LSB << ", #" << Width; |
194 | printAnnotation(O, Annot); |
195 | return; |
196 | } |
197 | |
198 | int LSB = ImmR; |
199 | int Width = ImmS - ImmR + 1; |
200 | // Otherwise BFXIL the preferred form |
201 | O << "\tbfxil\t" |
202 | << getRegisterName(Op0.getReg()) << ", " << getRegisterName(Op2.getReg()) |
203 | << ", #" << LSB << ", #" << Width; |
204 | printAnnotation(O, Annot); |
205 | return; |
206 | } |
207 | |
208 | // Symbolic operands for MOVZ, MOVN and MOVK already imply a shift |
209 | // (e.g. :gottprel_g1: is always going to be "lsl #16") so it should not be |
210 | // printed. |
211 | if ((Opcode == AArch64::MOVZXi || Opcode == AArch64::MOVZWi || |
212 | Opcode == AArch64::MOVNXi || Opcode == AArch64::MOVNWi) && |
213 | MI->getOperand(1).isExpr()) { |
214 | if (Opcode == AArch64::MOVZXi || Opcode == AArch64::MOVZWi) |
215 | O << "\tmovz\t"; |
216 | else |
217 | O << "\tmovn\t"; |
218 | |
219 | O << getRegisterName(MI->getOperand(0).getReg()) << ", #"; |
220 | MI->getOperand(1).getExpr()->print(O, &MAI); |
221 | return; |
222 | } |
223 | |
224 | if ((Opcode == AArch64::MOVKXi || Opcode == AArch64::MOVKWi) && |
225 | MI->getOperand(2).isExpr()) { |
226 | O << "\tmovk\t" << getRegisterName(MI->getOperand(0).getReg()) << ", #"; |
227 | MI->getOperand(2).getExpr()->print(O, &MAI); |
228 | return; |
229 | } |
230 | |
231 | // MOVZ, MOVN and "ORR wzr, #imm" instructions are aliases for MOV, but their |
232 | // domains overlap so they need to be prioritized. The chain is "MOVZ lsl #0 > |
233 | // MOVZ lsl #N > MOVN lsl #0 > MOVN lsl #N > ORR". The highest instruction |
234 | // that can represent the move is the MOV alias, and the rest get printed |
235 | // normally. |
236 | if ((Opcode == AArch64::MOVZXi || Opcode == AArch64::MOVZWi) && |
237 | MI->getOperand(1).isImm() && MI->getOperand(2).isImm()) { |
238 | int RegWidth = Opcode == AArch64::MOVZXi ? 64 : 32; |
239 | int Shift = MI->getOperand(2).getImm(); |
240 | uint64_t Value = (uint64_t)MI->getOperand(1).getImm() << Shift; |
241 | |
242 | if (AArch64_AM::isMOVZMovAlias(Value, Shift, |
243 | Opcode == AArch64::MOVZXi ? 64 : 32)) { |
244 | O << "\tmov\t" << getRegisterName(MI->getOperand(0).getReg()) << ", #" |
245 | << formatImm(SignExtend64(Value, RegWidth)); |
246 | return; |
247 | } |
248 | } |
249 | |
250 | if ((Opcode == AArch64::MOVNXi || Opcode == AArch64::MOVNWi) && |
251 | MI->getOperand(1).isImm() && MI->getOperand(2).isImm()) { |
252 | int RegWidth = Opcode == AArch64::MOVNXi ? 64 : 32; |
253 | int Shift = MI->getOperand(2).getImm(); |
254 | uint64_t Value = ~((uint64_t)MI->getOperand(1).getImm() << Shift); |
255 | if (RegWidth == 32) |
256 | Value = Value & 0xffffffff; |
257 | |
258 | if (AArch64_AM::isMOVNMovAlias(Value, Shift, RegWidth)) { |
259 | O << "\tmov\t" << getRegisterName(MI->getOperand(0).getReg()) << ", #" |
260 | << formatImm(SignExtend64(Value, RegWidth)); |
261 | return; |
262 | } |
263 | } |
264 | |
265 | if ((Opcode == AArch64::ORRXri || Opcode == AArch64::ORRWri) && |
266 | (MI->getOperand(1).getReg() == AArch64::XZR || |
267 | MI->getOperand(1).getReg() == AArch64::WZR) && |
268 | MI->getOperand(2).isImm()) { |
269 | int RegWidth = Opcode == AArch64::ORRXri ? 64 : 32; |
270 | uint64_t Value = AArch64_AM::decodeLogicalImmediate( |
271 | MI->getOperand(2).getImm(), RegWidth); |
272 | if (!AArch64_AM::isAnyMOVWMovAlias(Value, RegWidth)) { |
273 | O << "\tmov\t" << getRegisterName(MI->getOperand(0).getReg()) << ", #" |
274 | << formatImm(SignExtend64(Value, RegWidth)); |
275 | return; |
276 | } |
277 | } |
278 | |
279 | if (Opcode == AArch64::CompilerBarrier) { |
280 | O << '\t' << MAI.getCommentString() << " COMPILER BARRIER"; |
281 | printAnnotation(O, Annot); |
282 | return; |
283 | } |
284 | |
285 | if (!printAliasInstr(MI, STI, O)) |
286 | printInstruction(MI, STI, O); |
287 | |
288 | printAnnotation(O, Annot); |
289 | } |
290 | |
291 | static bool isTblTbxInstruction(unsigned Opcode, StringRef &Layout, |
292 | bool &IsTbx) { |
293 | switch (Opcode) { |
294 | case AArch64::TBXv8i8One: |
295 | case AArch64::TBXv8i8Two: |
296 | case AArch64::TBXv8i8Three: |
297 | case AArch64::TBXv8i8Four: |
298 | IsTbx = true; |
299 | Layout = ".8b"; |
300 | return true; |
301 | case AArch64::TBLv8i8One: |
302 | case AArch64::TBLv8i8Two: |
303 | case AArch64::TBLv8i8Three: |
304 | case AArch64::TBLv8i8Four: |
305 | IsTbx = false; |
306 | Layout = ".8b"; |
307 | return true; |
308 | case AArch64::TBXv16i8One: |
309 | case AArch64::TBXv16i8Two: |
310 | case AArch64::TBXv16i8Three: |
311 | case AArch64::TBXv16i8Four: |
312 | IsTbx = true; |
313 | Layout = ".16b"; |
314 | return true; |
315 | case AArch64::TBLv16i8One: |
316 | case AArch64::TBLv16i8Two: |
317 | case AArch64::TBLv16i8Three: |
318 | case AArch64::TBLv16i8Four: |
319 | IsTbx = false; |
320 | Layout = ".16b"; |
321 | return true; |
322 | default: |
323 | return false; |
324 | } |
325 | } |
326 | |
327 | struct LdStNInstrDesc { |
Excessive padding in 'struct LdStNInstrDesc' (11 padding bytes, where 3 is optimal).
Optimal fields order:
Mnemonic,
Layout,
Opcode,
ListOperand,
NaturalOffset,
HasLane,
consider reordering the fields or adding explicit padding members | |
328 | unsigned Opcode; |
329 | const char *Mnemonic; |
330 | const char *Layout; |
331 | int ListOperand; |
332 | bool HasLane; |
333 | int NaturalOffset; |
334 | }; |
335 | |
336 | static const LdStNInstrDesc LdStNInstInfo[] = { |
337 | { AArch64::LD1i8, "ld1", ".b", 1, true, 0 }, |
338 | { AArch64::LD1i16, "ld1", ".h", 1, true, 0 }, |
339 | { AArch64::LD1i32, "ld1", ".s", 1, true, 0 }, |
340 | { AArch64::LD1i64, "ld1", ".d", 1, true, 0 }, |
341 | { AArch64::LD1i8_POST, "ld1", ".b", 2, true, 1 }, |
342 | { AArch64::LD1i16_POST, "ld1", ".h", 2, true, 2 }, |
343 | { AArch64::LD1i32_POST, "ld1", ".s", 2, true, 4 }, |
344 | { AArch64::LD1i64_POST, "ld1", ".d", 2, true, 8 }, |
345 | { AArch64::LD1Rv16b, "ld1r", ".16b", 0, false, 0 }, |
346 | { AArch64::LD1Rv8h, "ld1r", ".8h", 0, false, 0 }, |
347 | { AArch64::LD1Rv4s, "ld1r", ".4s", 0, false, 0 }, |
348 | { AArch64::LD1Rv2d, "ld1r", ".2d", 0, false, 0 }, |
349 | { AArch64::LD1Rv8b, "ld1r", ".8b", 0, false, 0 }, |
350 | { AArch64::LD1Rv4h, "ld1r", ".4h", 0, false, 0 }, |
351 | { AArch64::LD1Rv2s, "ld1r", ".2s", 0, false, 0 }, |
352 | { AArch64::LD1Rv1d, "ld1r", ".1d", 0, false, 0 }, |
353 | { AArch64::LD1Rv16b_POST, "ld1r", ".16b", 1, false, 1 }, |
354 | { AArch64::LD1Rv8h_POST, "ld1r", ".8h", 1, false, 2 }, |
355 | { AArch64::LD1Rv4s_POST, "ld1r", ".4s", 1, false, 4 }, |
356 | { AArch64::LD1Rv2d_POST, "ld1r", ".2d", 1, false, 8 }, |
357 | { AArch64::LD1Rv8b_POST, "ld1r", ".8b", 1, false, 1 }, |
358 | { AArch64::LD1Rv4h_POST, "ld1r", ".4h", 1, false, 2 }, |
359 | { AArch64::LD1Rv2s_POST, "ld1r", ".2s", 1, false, 4 }, |
360 | { AArch64::LD1Rv1d_POST, "ld1r", ".1d", 1, false, 8 }, |
361 | { AArch64::LD1Onev16b, "ld1", ".16b", 0, false, 0 }, |
362 | { AArch64::LD1Onev8h, "ld1", ".8h", 0, false, 0 }, |
363 | { AArch64::LD1Onev4s, "ld1", ".4s", 0, false, 0 }, |
364 | { AArch64::LD1Onev2d, "ld1", ".2d", 0, false, 0 }, |
365 | { AArch64::LD1Onev8b, "ld1", ".8b", 0, false, 0 }, |
366 | { AArch64::LD1Onev4h, "ld1", ".4h", 0, false, 0 }, |
367 | { AArch64::LD1Onev2s, "ld1", ".2s", 0, false, 0 }, |
368 | { AArch64::LD1Onev1d, "ld1", ".1d", 0, false, 0 }, |
369 | { AArch64::LD1Onev16b_POST, "ld1", ".16b", 1, false, 16 }, |
370 | { AArch64::LD1Onev8h_POST, "ld1", ".8h", 1, false, 16 }, |
371 | { AArch64::LD1Onev4s_POST, "ld1", ".4s", 1, false, 16 }, |
372 | { AArch64::LD1Onev2d_POST, "ld1", ".2d", 1, false, 16 }, |
373 | { AArch64::LD1Onev8b_POST, "ld1", ".8b", 1, false, 8 }, |
374 | { AArch64::LD1Onev4h_POST, "ld1", ".4h", 1, false, 8 }, |
375 | { AArch64::LD1Onev2s_POST, "ld1", ".2s", 1, false, 8 }, |
376 | { AArch64::LD1Onev1d_POST, "ld1", ".1d", 1, false, 8 }, |
377 | { AArch64::LD1Twov16b, "ld1", ".16b", 0, false, 0 }, |
378 | { AArch64::LD1Twov8h, "ld1", ".8h", 0, false, 0 }, |
379 | { AArch64::LD1Twov4s, "ld1", ".4s", 0, false, 0 }, |
380 | { AArch64::LD1Twov2d, "ld1", ".2d", 0, false, 0 }, |
381 | { AArch64::LD1Twov8b, "ld1", ".8b", 0, false, 0 }, |
382 | { AArch64::LD1Twov4h, "ld1", ".4h", 0, false, 0 }, |
383 | { AArch64::LD1Twov2s, "ld1", ".2s", 0, false, 0 }, |
384 | { AArch64::LD1Twov1d, "ld1", ".1d", 0, false, 0 }, |
385 | { AArch64::LD1Twov16b_POST, "ld1", ".16b", 1, false, 32 }, |
386 | { AArch64::LD1Twov8h_POST, "ld1", ".8h", 1, false, 32 }, |
387 | { AArch64::LD1Twov4s_POST, "ld1", ".4s", 1, false, 32 }, |
388 | { AArch64::LD1Twov2d_POST, "ld1", ".2d", 1, false, 32 }, |
389 | { AArch64::LD1Twov8b_POST, "ld1", ".8b", 1, false, 16 }, |
390 | { AArch64::LD1Twov4h_POST, "ld1", ".4h", 1, false, 16 }, |
391 | { AArch64::LD1Twov2s_POST, "ld1", ".2s", 1, false, 16 }, |
392 | { AArch64::LD1Twov1d_POST, "ld1", ".1d", 1, false, 16 }, |
393 | { AArch64::LD1Threev16b, "ld1", ".16b", 0, false, 0 }, |
394 | { AArch64::LD1Threev8h, "ld1", ".8h", 0, false, 0 }, |
395 | { AArch64::LD1Threev4s, "ld1", ".4s", 0, false, 0 }, |
396 | { AArch64::LD1Threev2d, "ld1", ".2d", 0, false, 0 }, |
397 | { AArch64::LD1Threev8b, "ld1", ".8b", 0, false, 0 }, |
398 | { AArch64::LD1Threev4h, "ld1", ".4h", 0, false, 0 }, |
399 | { AArch64::LD1Threev2s, "ld1", ".2s", 0, false, 0 }, |
400 | { AArch64::LD1Threev1d, "ld1", ".1d", 0, false, 0 }, |
401 | { AArch64::LD1Threev16b_POST, "ld1", ".16b", 1, false, 48 }, |
402 | { AArch64::LD1Threev8h_POST, "ld1", ".8h", 1, false, 48 }, |
403 | { AArch64::LD1Threev4s_POST, "ld1", ".4s", 1, false, 48 }, |
404 | { AArch64::LD1Threev2d_POST, "ld1", ".2d", 1, false, 48 }, |
405 | { AArch64::LD1Threev8b_POST, "ld1", ".8b", 1, false, 24 }, |
406 | { AArch64::LD1Threev4h_POST, "ld1", ".4h", 1, false, 24 }, |
407 | { AArch64::LD1Threev2s_POST, "ld1", ".2s", 1, false, 24 }, |
408 | { AArch64::LD1Threev1d_POST, "ld1", ".1d", 1, false, 24 }, |
409 | { AArch64::LD1Fourv16b, "ld1", ".16b", 0, false, 0 }, |
410 | { AArch64::LD1Fourv8h, "ld1", ".8h", 0, false, 0 }, |
411 | { AArch64::LD1Fourv4s, "ld1", ".4s", 0, false, 0 }, |
412 | { AArch64::LD1Fourv2d, "ld1", ".2d", 0, false, 0 }, |
413 | { AArch64::LD1Fourv8b, "ld1", ".8b", 0, false, 0 }, |
414 | { AArch64::LD1Fourv4h, "ld1", ".4h", 0, false, 0 }, |
415 | { AArch64::LD1Fourv2s, "ld1", ".2s", 0, false, 0 }, |
416 | { AArch64::LD1Fourv1d, "ld1", ".1d", 0, false, 0 }, |
417 | { AArch64::LD1Fourv16b_POST, "ld1", ".16b", 1, false, 64 }, |
418 | { AArch64::LD1Fourv8h_POST, "ld1", ".8h", 1, false, 64 }, |
419 | { AArch64::LD1Fourv4s_POST, "ld1", ".4s", 1, false, 64 }, |
420 | { AArch64::LD1Fourv2d_POST, "ld1", ".2d", 1, false, 64 }, |
421 | { AArch64::LD1Fourv8b_POST, "ld1", ".8b", 1, false, 32 }, |
422 | { AArch64::LD1Fourv4h_POST, "ld1", ".4h", 1, false, 32 }, |
423 | { AArch64::LD1Fourv2s_POST, "ld1", ".2s", 1, false, 32 }, |
424 | { AArch64::LD1Fourv1d_POST, "ld1", ".1d", 1, false, 32 }, |
425 | { AArch64::LD2i8, "ld2", ".b", 1, true, 0 }, |
426 | { AArch64::LD2i16, "ld2", ".h", 1, true, 0 }, |
427 | { AArch64::LD2i32, "ld2", ".s", 1, true, 0 }, |
428 | { AArch64::LD2i64, "ld2", ".d", 1, true, 0 }, |
429 | { AArch64::LD2i8_POST, "ld2", ".b", 2, true, 2 }, |
430 | { AArch64::LD2i16_POST, "ld2", ".h", 2, true, 4 }, |
431 | { AArch64::LD2i32_POST, "ld2", ".s", 2, true, 8 }, |
432 | { AArch64::LD2i64_POST, "ld2", ".d", 2, true, 16 }, |
433 | { AArch64::LD2Rv16b, "ld2r", ".16b", 0, false, 0 }, |
434 | { AArch64::LD2Rv8h, "ld2r", ".8h", 0, false, 0 }, |
435 | { AArch64::LD2Rv4s, "ld2r", ".4s", 0, false, 0 }, |
436 | { AArch64::LD2Rv2d, "ld2r", ".2d", 0, false, 0 }, |
437 | { AArch64::LD2Rv8b, "ld2r", ".8b", 0, false, 0 }, |
438 | { AArch64::LD2Rv4h, "ld2r", ".4h", 0, false, 0 }, |
439 | { AArch64::LD2Rv2s, "ld2r", ".2s", 0, false, 0 }, |
440 | { AArch64::LD2Rv1d, "ld2r", ".1d", 0, false, 0 }, |
441 | { AArch64::LD2Rv16b_POST, "ld2r", ".16b", 1, false, 2 }, |
442 | { AArch64::LD2Rv8h_POST, "ld2r", ".8h", 1, false, 4 }, |
443 | { AArch64::LD2Rv4s_POST, "ld2r", ".4s", 1, false, 8 }, |
444 | { AArch64::LD2Rv2d_POST, "ld2r", ".2d", 1, false, 16 }, |
445 | { AArch64::LD2Rv8b_POST, "ld2r", ".8b", 1, false, 2 }, |
446 | { AArch64::LD2Rv4h_POST, "ld2r", ".4h", 1, false, 4 }, |
447 | { AArch64::LD2Rv2s_POST, "ld2r", ".2s", 1, false, 8 }, |
448 | { AArch64::LD2Rv1d_POST, "ld2r", ".1d", 1, false, 16 }, |
449 | { AArch64::LD2Twov16b, "ld2", ".16b", 0, false, 0 }, |
450 | { AArch64::LD2Twov8h, "ld2", ".8h", 0, false, 0 }, |
451 | { AArch64::LD2Twov4s, "ld2", ".4s", 0, false, 0 }, |
452 | { AArch64::LD2Twov2d, "ld2", ".2d", 0, false, 0 }, |
453 | { AArch64::LD2Twov8b, "ld2", ".8b", 0, false, 0 }, |
454 | { AArch64::LD2Twov4h, "ld2", ".4h", 0, false, 0 }, |
455 | { AArch64::LD2Twov2s, "ld2", ".2s", 0, false, 0 }, |
456 | { AArch64::LD2Twov16b_POST, "ld2", ".16b", 1, false, 32 }, |
457 | { AArch64::LD2Twov8h_POST, "ld2", ".8h", 1, false, 32 }, |
458 | { AArch64::LD2Twov4s_POST, "ld2", ".4s", 1, false, 32 }, |
459 | { AArch64::LD2Twov2d_POST, "ld2", ".2d", 1, false, 32 }, |
460 | { AArch64::LD2Twov8b_POST, "ld2", ".8b", 1, false, 16 }, |
461 | { AArch64::LD2Twov4h_POST, "ld2", ".4h", 1, false, 16 }, |
462 | { AArch64::LD2Twov2s_POST, "ld2", ".2s", 1, false, 16 }, |
463 | { AArch64::LD3i8, "ld3", ".b", 1, true, 0 }, |
464 | { AArch64::LD3i16, "ld3", ".h", 1, true, 0 }, |
465 | { AArch64::LD3i32, "ld3", ".s", 1, true, 0 }, |
466 | { AArch64::LD3i64, "ld3", ".d", 1, true, 0 }, |
467 | { AArch64::LD3i8_POST, "ld3", ".b", 2, true, 3 }, |
468 | { AArch64::LD3i16_POST, "ld3", ".h", 2, true, 6 }, |
469 | { AArch64::LD3i32_POST, "ld3", ".s", 2, true, 12 }, |
470 | { AArch64::LD3i64_POST, "ld3", ".d", 2, true, 24 }, |
471 | { AArch64::LD3Rv16b, "ld3r", ".16b", 0, false, 0 }, |
472 | { AArch64::LD3Rv8h, "ld3r", ".8h", 0, false, 0 }, |
473 | { AArch64::LD3Rv4s, "ld3r", ".4s", 0, false, 0 }, |
474 | { AArch64::LD3Rv2d, "ld3r", ".2d", 0, false, 0 }, |
475 | { AArch64::LD3Rv8b, "ld3r", ".8b", 0, false, 0 }, |
476 | { AArch64::LD3Rv4h, "ld3r", ".4h", 0, false, 0 }, |
477 | { AArch64::LD3Rv2s, "ld3r", ".2s", 0, false, 0 }, |
478 | { AArch64::LD3Rv1d, "ld3r", ".1d", 0, false, 0 }, |
479 | { AArch64::LD3Rv16b_POST, "ld3r", ".16b", 1, false, 3 }, |
480 | { AArch64::LD3Rv8h_POST, "ld3r", ".8h", 1, false, 6 }, |
481 | { AArch64::LD3Rv4s_POST, "ld3r", ".4s", 1, false, 12 }, |
482 | { AArch64::LD3Rv2d_POST, "ld3r", ".2d", 1, false, 24 }, |
483 | { AArch64::LD3Rv8b_POST, "ld3r", ".8b", 1, false, 3 }, |
484 | { AArch64::LD3Rv4h_POST, "ld3r", ".4h", 1, false, 6 }, |
485 | { AArch64::LD3Rv2s_POST, "ld3r", ".2s", 1, false, 12 }, |
486 | { AArch64::LD3Rv1d_POST, "ld3r", ".1d", 1, false, 24 }, |
487 | { AArch64::LD3Threev16b, "ld3", ".16b", 0, false, 0 }, |
488 | { AArch64::LD3Threev8h, "ld3", ".8h", 0, false, 0 }, |
489 | { AArch64::LD3Threev4s, "ld3", ".4s", 0, false, 0 }, |
490 | { AArch64::LD3Threev2d, "ld3", ".2d", 0, false, 0 }, |
491 | { AArch64::LD3Threev8b, "ld3", ".8b", 0, false, 0 }, |
492 | { AArch64::LD3Threev4h, "ld3", ".4h", 0, false, 0 }, |
493 | { AArch64::LD3Threev2s, "ld3", ".2s", 0, false, 0 }, |
494 | { AArch64::LD3Threev16b_POST, "ld3", ".16b", 1, false, 48 }, |
495 | { AArch64::LD3Threev8h_POST, "ld3", ".8h", 1, false, 48 }, |
496 | { AArch64::LD3Threev4s_POST, "ld3", ".4s", 1, false, 48 }, |
497 | { AArch64::LD3Threev2d_POST, "ld3", ".2d", 1, false, 48 }, |
498 | { AArch64::LD3Threev8b_POST, "ld3", ".8b", 1, false, 24 }, |
499 | { AArch64::LD3Threev4h_POST, "ld3", ".4h", 1, false, 24 }, |
500 | { AArch64::LD3Threev2s_POST, "ld3", ".2s", 1, false, 24 }, |
501 | { AArch64::LD4i8, "ld4", ".b", 1, true, 0 }, |
502 | { AArch64::LD4i16, "ld4", ".h", 1, true, 0 }, |
503 | { AArch64::LD4i32, "ld4", ".s", 1, true, 0 }, |
504 | { AArch64::LD4i64, "ld4", ".d", 1, true, 0 }, |
505 | { AArch64::LD4i8_POST, "ld4", ".b", 2, true, 4 }, |
506 | { AArch64::LD4i16_POST, "ld4", ".h", 2, true, 8 }, |
507 | { AArch64::LD4i32_POST, "ld4", ".s", 2, true, 16 }, |
508 | { AArch64::LD4i64_POST, "ld4", ".d", 2, true, 32 }, |
509 | { AArch64::LD4Rv16b, "ld4r", ".16b", 0, false, 0 }, |
510 | { AArch64::LD4Rv8h, "ld4r", ".8h", 0, false, 0 }, |
511 | { AArch64::LD4Rv4s, "ld4r", ".4s", 0, false, 0 }, |
512 | { AArch64::LD4Rv2d, "ld4r", ".2d", 0, false, 0 }, |
513 | { AArch64::LD4Rv8b, "ld4r", ".8b", 0, false, 0 }, |
514 | { AArch64::LD4Rv4h, "ld4r", ".4h", 0, false, 0 }, |
515 | { AArch64::LD4Rv2s, "ld4r", ".2s", 0, false, 0 }, |
516 | { AArch64::LD4Rv1d, "ld4r", ".1d", 0, false, 0 }, |
517 | { AArch64::LD4Rv16b_POST, "ld4r", ".16b", 1, false, 4 }, |
518 | { AArch64::LD4Rv8h_POST, "ld4r", ".8h", 1, false, 8 }, |
519 | { AArch64::LD4Rv4s_POST, "ld4r", ".4s", 1, false, 16 }, |
520 | { AArch64::LD4Rv2d_POST, "ld4r", ".2d", 1, false, 32 }, |
521 | { AArch64::LD4Rv8b_POST, "ld4r", ".8b", 1, false, 4 }, |
522 | { AArch64::LD4Rv4h_POST, "ld4r", ".4h", 1, false, 8 }, |
523 | { AArch64::LD4Rv2s_POST, "ld4r", ".2s", 1, false, 16 }, |
524 | { AArch64::LD4Rv1d_POST, "ld4r", ".1d", 1, false, 32 }, |
525 | { AArch64::LD4Fourv16b, "ld4", ".16b", 0, false, 0 }, |
526 | { AArch64::LD4Fourv8h, "ld4", ".8h", 0, false, 0 }, |
527 | { AArch64::LD4Fourv4s, "ld4", ".4s", 0, false, 0 }, |
528 | { AArch64::LD4Fourv2d, "ld4", ".2d", 0, false, 0 }, |
529 | { AArch64::LD4Fourv8b, "ld4", ".8b", 0, false, 0 }, |
530 | { AArch64::LD4Fourv4h, "ld4", ".4h", 0, false, 0 }, |
531 | { AArch64::LD4Fourv2s, "ld4", ".2s", 0, false, 0 }, |
532 | { AArch64::LD4Fourv16b_POST, "ld4", ".16b", 1, false, 64 }, |
533 | { AArch64::LD4Fourv8h_POST, "ld4", ".8h", 1, false, 64 }, |
534 | { AArch64::LD4Fourv4s_POST, "ld4", ".4s", 1, false, 64 }, |
535 | { AArch64::LD4Fourv2d_POST, "ld4", ".2d", 1, false, 64 }, |
536 | { AArch64::LD4Fourv8b_POST, "ld4", ".8b", 1, false, 32 }, |
537 | { AArch64::LD4Fourv4h_POST, "ld4", ".4h", 1, false, 32 }, |
538 | { AArch64::LD4Fourv2s_POST, "ld4", ".2s", 1, false, 32 }, |
539 | { AArch64::ST1i8, "st1", ".b", 0, true, 0 }, |
540 | { AArch64::ST1i16, "st1", ".h", 0, true, 0 }, |
541 | { AArch64::ST1i32, "st1", ".s", 0, true, 0 }, |
542 | { AArch64::ST1i64, "st1", ".d", 0, true, 0 }, |
543 | { AArch64::ST1i8_POST, "st1", ".b", 1, true, 1 }, |
544 | { AArch64::ST1i16_POST, "st1", ".h", 1, true, 2 }, |
545 | { AArch64::ST1i32_POST, "st1", ".s", 1, true, 4 }, |
546 | { AArch64::ST1i64_POST, "st1", ".d", 1, true, 8 }, |
547 | { AArch64::ST1Onev16b, "st1", ".16b", 0, false, 0 }, |
548 | { AArch64::ST1Onev8h, "st1", ".8h", 0, false, 0 }, |
549 | { AArch64::ST1Onev4s, "st1", ".4s", 0, false, 0 }, |
550 | { AArch64::ST1Onev2d, "st1", ".2d", 0, false, 0 }, |
551 | { AArch64::ST1Onev8b, "st1", ".8b", 0, false, 0 }, |
552 | { AArch64::ST1Onev4h, "st1", ".4h", 0, false, 0 }, |
553 | { AArch64::ST1Onev2s, "st1", ".2s", 0, false, 0 }, |
554 | { AArch64::ST1Onev1d, "st1", ".1d", 0, false, 0 }, |
555 | { AArch64::ST1Onev16b_POST, "st1", ".16b", 1, false, 16 }, |
556 | { AArch64::ST1Onev8h_POST, "st1", ".8h", 1, false, 16 }, |
557 | { AArch64::ST1Onev4s_POST, "st1", ".4s", 1, false, 16 }, |
558 | { AArch64::ST1Onev2d_POST, "st1", ".2d", 1, false, 16 }, |
559 | { AArch64::ST1Onev8b_POST, "st1", ".8b", 1, false, 8 }, |
560 | { AArch64::ST1Onev4h_POST, "st1", ".4h", 1, false, 8 }, |
561 | { AArch64::ST1Onev2s_POST, "st1", ".2s", 1, false, 8 }, |
562 | { AArch64::ST1Onev1d_POST, "st1", ".1d", 1, false, 8 }, |
563 | { AArch64::ST1Twov16b, "st1", ".16b", 0, false, 0 }, |
564 | { AArch64::ST1Twov8h, "st1", ".8h", 0, false, 0 }, |
565 | { AArch64::ST1Twov4s, "st1", ".4s", 0, false, 0 }, |
566 | { AArch64::ST1Twov2d, "st1", ".2d", 0, false, 0 }, |
567 | { AArch64::ST1Twov8b, "st1", ".8b", 0, false, 0 }, |
568 | { AArch64::ST1Twov4h, "st1", ".4h", 0, false, 0 }, |
569 | { AArch64::ST1Twov2s, "st1", ".2s", 0, false, 0 }, |
570 | { AArch64::ST1Twov1d, "st1", ".1d", 0, false, 0 }, |
571 | { AArch64::ST1Twov16b_POST, "st1", ".16b", 1, false, 32 }, |
572 | { AArch64::ST1Twov8h_POST, "st1", ".8h", 1, false, 32 }, |
573 | { AArch64::ST1Twov4s_POST, "st1", ".4s", 1, false, 32 }, |
574 | { AArch64::ST1Twov2d_POST, "st1", ".2d", 1, false, 32 }, |
575 | { AArch64::ST1Twov8b_POST, "st1", ".8b", 1, false, 16 }, |
576 | { AArch64::ST1Twov4h_POST, "st1", ".4h", 1, false, 16 }, |
577 | { AArch64::ST1Twov2s_POST, "st1", ".2s", 1, false, 16 }, |
578 | { AArch64::ST1Twov1d_POST, "st1", ".1d", 1, false, 16 }, |
579 | { AArch64::ST1Threev16b, "st1", ".16b", 0, false, 0 }, |
580 | { AArch64::ST1Threev8h, "st1", ".8h", 0, false, 0 }, |
581 | { AArch64::ST1Threev4s, "st1", ".4s", 0, false, 0 }, |
582 | { AArch64::ST1Threev2d, "st1", ".2d", 0, false, 0 }, |
583 | { AArch64::ST1Threev8b, "st1", ".8b", 0, false, 0 }, |
584 | { AArch64::ST1Threev4h, "st1", ".4h", 0, false, 0 }, |
585 | { AArch64::ST1Threev2s, "st1", ".2s", 0, false, 0 }, |
586 | { AArch64::ST1Threev1d, "st1", ".1d", 0, false, 0 }, |
587 | { AArch64::ST1Threev16b_POST, "st1", ".16b", 1, false, 48 }, |
588 | { AArch64::ST1Threev8h_POST, "st1", ".8h", 1, false, 48 }, |
589 | { AArch64::ST1Threev4s_POST, "st1", ".4s", 1, false, 48 }, |
590 | { AArch64::ST1Threev2d_POST, "st1", ".2d", 1, false, 48 }, |
591 | { AArch64::ST1Threev8b_POST, "st1", ".8b", 1, false, 24 }, |
592 | { AArch64::ST1Threev4h_POST, "st1", ".4h", 1, false, 24 }, |
593 | { AArch64::ST1Threev2s_POST, "st1", ".2s", 1, false, 24 }, |
594 | { AArch64::ST1Threev1d_POST, "st1", ".1d", 1, false, 24 }, |
595 | { AArch64::ST1Fourv16b, "st1", ".16b", 0, false, 0 }, |
596 | { AArch64::ST1Fourv8h, "st1", ".8h", 0, false, 0 }, |
597 | { AArch64::ST1Fourv4s, "st1", ".4s", 0, false, 0 }, |
598 | { AArch64::ST1Fourv2d, "st1", ".2d", 0, false, 0 }, |
599 | { AArch64::ST1Fourv8b, "st1", ".8b", 0, false, 0 }, |
600 | { AArch64::ST1Fourv4h, "st1", ".4h", 0, false, 0 }, |
601 | { AArch64::ST1Fourv2s, "st1", ".2s", 0, false, 0 }, |
602 | { AArch64::ST1Fourv1d, "st1", ".1d", 0, false, 0 }, |
603 | { AArch64::ST1Fourv16b_POST, "st1", ".16b", 1, false, 64 }, |
604 | { AArch64::ST1Fourv8h_POST, "st1", ".8h", 1, false, 64 }, |
605 | { AArch64::ST1Fourv4s_POST, "st1", ".4s", 1, false, 64 }, |
606 | { AArch64::ST1Fourv2d_POST, "st1", ".2d", 1, false, 64 }, |
607 | { AArch64::ST1Fourv8b_POST, "st1", ".8b", 1, false, 32 }, |
608 | { AArch64::ST1Fourv4h_POST, "st1", ".4h", 1, false, 32 }, |
609 | { AArch64::ST1Fourv2s_POST, "st1", ".2s", 1, false, 32 }, |
610 | { AArch64::ST1Fourv1d_POST, "st1", ".1d", 1, false, 32 }, |
611 | { AArch64::ST2i8, "st2", ".b", 0, true, 0 }, |
612 | { AArch64::ST2i16, "st2", ".h", 0, true, 0 }, |
613 | { AArch64::ST2i32, "st2", ".s", 0, true, 0 }, |
614 | { AArch64::ST2i64, "st2", ".d", 0, true, 0 }, |
615 | { AArch64::ST2i8_POST, "st2", ".b", 1, true, 2 }, |
616 | { AArch64::ST2i16_POST, "st2", ".h", 1, true, 4 }, |
617 | { AArch64::ST2i32_POST, "st2", ".s", 1, true, 8 }, |
618 | { AArch64::ST2i64_POST, "st2", ".d", 1, true, 16 }, |
619 | { AArch64::ST2Twov16b, "st2", ".16b", 0, false, 0 }, |
620 | { AArch64::ST2Twov8h, "st2", ".8h", 0, false, 0 }, |
621 | { AArch64::ST2Twov4s, "st2", ".4s", 0, false, 0 }, |
622 | { AArch64::ST2Twov2d, "st2", ".2d", 0, false, 0 }, |
623 | { AArch64::ST2Twov8b, "st2", ".8b", 0, false, 0 }, |
624 | { AArch64::ST2Twov4h, "st2", ".4h", 0, false, 0 }, |
625 | { AArch64::ST2Twov2s, "st2", ".2s", 0, false, 0 }, |
626 | { AArch64::ST2Twov16b_POST, "st2", ".16b", 1, false, 32 }, |
627 | { AArch64::ST2Twov8h_POST, "st2", ".8h", 1, false, 32 }, |
628 | { AArch64::ST2Twov4s_POST, "st2", ".4s", 1, false, 32 }, |
629 | { AArch64::ST2Twov2d_POST, "st2", ".2d", 1, false, 32 }, |
630 | { AArch64::ST2Twov8b_POST, "st2", ".8b", 1, false, 16 }, |
631 | { AArch64::ST2Twov4h_POST, "st2", ".4h", 1, false, 16 }, |
632 | { AArch64::ST2Twov2s_POST, "st2", ".2s", 1, false, 16 }, |
633 | { AArch64::ST3i8, "st3", ".b", 0, true, 0 }, |
634 | { AArch64::ST3i16, "st3", ".h", 0, true, 0 }, |
635 | { AArch64::ST3i32, "st3", ".s", 0, true, 0 }, |
636 | { AArch64::ST3i64, "st3", ".d", 0, true, 0 }, |
637 | { AArch64::ST3i8_POST, "st3", ".b", 1, true, 3 }, |
638 | { AArch64::ST3i16_POST, "st3", ".h", 1, true, 6 }, |
639 | { AArch64::ST3i32_POST, "st3", ".s", 1, true, 12 }, |
640 | { AArch64::ST3i64_POST, "st3", ".d", 1, true, 24 }, |
641 | { AArch64::ST3Threev16b, "st3", ".16b", 0, false, 0 }, |
642 | { AArch64::ST3Threev8h, "st3", ".8h", 0, false, 0 }, |
643 | { AArch64::ST3Threev4s, "st3", ".4s", 0, false, 0 }, |
644 | { AArch64::ST3Threev2d, "st3", ".2d", 0, false, 0 }, |
645 | { AArch64::ST3Threev8b, "st3", ".8b", 0, false, 0 }, |
646 | { AArch64::ST3Threev4h, "st3", ".4h", 0, false, 0 }, |
647 | { AArch64::ST3Threev2s, "st3", ".2s", 0, false, 0 }, |
648 | { AArch64::ST3Threev16b_POST, "st3", ".16b", 1, false, 48 }, |
649 | { AArch64::ST3Threev8h_POST, "st3", ".8h", 1, false, 48 }, |
650 | { AArch64::ST3Threev4s_POST, "st3", ".4s", 1, false, 48 }, |
651 | { AArch64::ST3Threev2d_POST, "st3", ".2d", 1, false, 48 }, |
652 | { AArch64::ST3Threev8b_POST, "st3", ".8b", 1, false, 24 }, |
653 | { AArch64::ST3Threev4h_POST, "st3", ".4h", 1, false, 24 }, |
654 | { AArch64::ST3Threev2s_POST, "st3", ".2s", 1, false, 24 }, |
655 | { AArch64::ST4i8, "st4", ".b", 0, true, 0 }, |
656 | { AArch64::ST4i16, "st4", ".h", 0, true, 0 }, |
657 | { AArch64::ST4i32, "st4", ".s", 0, true, 0 }, |
658 | { AArch64::ST4i64, "st4", ".d", 0, true, 0 }, |
659 | { AArch64::ST4i8_POST, "st4", ".b", 1, true, 4 }, |
660 | { AArch64::ST4i16_POST, "st4", ".h", 1, true, 8 }, |
661 | { AArch64::ST4i32_POST, "st4", ".s", 1, true, 16 }, |
662 | { AArch64::ST4i64_POST, "st4", ".d", 1, true, 32 }, |
663 | { AArch64::ST4Fourv16b, "st4", ".16b", 0, false, 0 }, |
664 | { AArch64::ST4Fourv8h, "st4", ".8h", 0, false, 0 }, |
665 | { AArch64::ST4Fourv4s, "st4", ".4s", 0, false, 0 }, |
666 | { AArch64::ST4Fourv2d, "st4", ".2d", 0, false, 0 }, |
667 | { AArch64::ST4Fourv8b, "st4", ".8b", 0, false, 0 }, |
668 | { AArch64::ST4Fourv4h, "st4", ".4h", 0, false, 0 }, |
669 | { AArch64::ST4Fourv2s, "st4", ".2s", 0, false, 0 }, |
670 | { AArch64::ST4Fourv16b_POST, "st4", ".16b", 1, false, 64 }, |
671 | { AArch64::ST4Fourv8h_POST, "st4", ".8h", 1, false, 64 }, |
672 | { AArch64::ST4Fourv4s_POST, "st4", ".4s", 1, false, 64 }, |
673 | { AArch64::ST4Fourv2d_POST, "st4", ".2d", 1, false, 64 }, |
674 | { AArch64::ST4Fourv8b_POST, "st4", ".8b", 1, false, 32 }, |
675 | { AArch64::ST4Fourv4h_POST, "st4", ".4h", 1, false, 32 }, |
676 | { AArch64::ST4Fourv2s_POST, "st4", ".2s", 1, false, 32 }, |
677 | }; |
678 | |
679 | static const LdStNInstrDesc *getLdStNInstrDesc(unsigned Opcode) { |
680 | unsigned Idx; |
681 | for (Idx = 0; Idx != array_lengthof(LdStNInstInfo); ++Idx) |
682 | if (LdStNInstInfo[Idx].Opcode == Opcode) |
683 | return &LdStNInstInfo[Idx]; |
684 | |
685 | return nullptr; |
686 | } |
687 | |
688 | void AArch64AppleInstPrinter::printInst(const MCInst *MI, raw_ostream &O, |
689 | StringRef Annot, |
690 | const MCSubtargetInfo &STI) { |
691 | unsigned Opcode = MI->getOpcode(); |
692 | StringRef Layout; |
693 | |
694 | bool IsTbx; |
695 | if (isTblTbxInstruction(MI->getOpcode(), Layout, IsTbx)) { |
696 | O << "\t" << (IsTbx ? "tbx" : "tbl") << Layout << '\t' |
697 | << getRegisterName(MI->getOperand(0).getReg(), AArch64::vreg) << ", "; |
698 | |
699 | unsigned ListOpNum = IsTbx ? 2 : 1; |
700 | printVectorList(MI, ListOpNum, STI, O, ""); |
701 | |
702 | O << ", " |
703 | << getRegisterName(MI->getOperand(ListOpNum + 1).getReg(), AArch64::vreg); |
704 | printAnnotation(O, Annot); |
705 | return; |
706 | } |
707 | |
708 | if (const LdStNInstrDesc *LdStDesc = getLdStNInstrDesc(Opcode)) { |
709 | O << "\t" << LdStDesc->Mnemonic << LdStDesc->Layout << '\t'; |
710 | |
711 | // Now onto the operands: first a vector list with possible lane |
712 | // specifier. E.g. { v0 }[2] |
713 | int OpNum = LdStDesc->ListOperand; |
714 | printVectorList(MI, OpNum++, STI, O, ""); |
715 | |
716 | if (LdStDesc->HasLane) |
717 | O << '[' << MI->getOperand(OpNum++).getImm() << ']'; |
718 | |
719 | // Next the address: [xN] |
720 | unsigned AddrReg = MI->getOperand(OpNum++).getReg(); |
721 | O << ", [" << getRegisterName(AddrReg) << ']'; |
722 | |
723 | // Finally, there might be a post-indexed offset. |
724 | if (LdStDesc->NaturalOffset != 0) { |
725 | unsigned Reg = MI->getOperand(OpNum++).getReg(); |
726 | if (Reg != AArch64::XZR) |
727 | O << ", " << getRegisterName(Reg); |
728 | else { |
729 | assert(LdStDesc->NaturalOffset && "no offset on post-inc instruction?")(static_cast <bool> (LdStDesc->NaturalOffset && "no offset on post-inc instruction?") ? void (0) : __assert_fail ("LdStDesc->NaturalOffset && \"no offset on post-inc instruction?\"" , "/build/llvm-toolchain-snapshot-7~svn329677/lib/Target/AArch64/InstPrinter/AArch64InstPrinter.cpp" , 729, __extension__ __PRETTY_FUNCTION__)); |
730 | O << ", #" << LdStDesc->NaturalOffset; |
731 | } |
732 | } |
733 | |
734 | printAnnotation(O, Annot); |
735 | return; |
736 | } |
737 | |
738 | AArch64InstPrinter::printInst(MI, O, Annot, STI); |
739 | } |
740 | |
741 | bool AArch64InstPrinter::printSysAlias(const MCInst *MI, |
742 | const MCSubtargetInfo &STI, |
743 | raw_ostream &O) { |
744 | #ifndef NDEBUG |
745 | unsigned Opcode = MI->getOpcode(); |
746 | assert(Opcode == AArch64::SYSxt && "Invalid opcode for SYS alias!")(static_cast <bool> (Opcode == AArch64::SYSxt && "Invalid opcode for SYS alias!") ? void (0) : __assert_fail ( "Opcode == AArch64::SYSxt && \"Invalid opcode for SYS alias!\"" , "/build/llvm-toolchain-snapshot-7~svn329677/lib/Target/AArch64/InstPrinter/AArch64InstPrinter.cpp" , 746, __extension__ __PRETTY_FUNCTION__)); |
747 | #endif |
748 | |
749 | const MCOperand &Op1 = MI->getOperand(0); |
750 | const MCOperand &Cn = MI->getOperand(1); |
751 | const MCOperand &Cm = MI->getOperand(2); |
752 | const MCOperand &Op2 = MI->getOperand(3); |
753 | |
754 | unsigned Op1Val = Op1.getImm(); |
755 | unsigned CnVal = Cn.getImm(); |
756 | unsigned CmVal = Cm.getImm(); |
757 | unsigned Op2Val = Op2.getImm(); |
758 | |
759 | uint16_t Encoding = Op2Val; |
760 | Encoding |= CmVal << 3; |
761 | Encoding |= CnVal << 7; |
762 | Encoding |= Op1Val << 11; |
763 | |
764 | bool NeedsReg; |
765 | std::string Ins; |
766 | std::string Name; |
767 | |
768 | if (CnVal == 7) { |
769 | switch (CmVal) { |
770 | default: return false; |
771 | // IC aliases |
772 | case 1: case 5: { |
773 | const AArch64IC::IC *IC = AArch64IC::lookupICByEncoding(Encoding); |
774 | if (!IC || !IC->haveFeatures(STI.getFeatureBits())) |
775 | return false; |
776 | |
777 | NeedsReg = IC->NeedsReg; |
778 | Ins = "ic\t"; |
779 | Name = std::string(IC->Name); |
780 | } |
781 | break; |
782 | // DC aliases |
783 | case 4: case 6: case 10: case 11: case 12: case 14: |
784 | { |
785 | const AArch64DC::DC *DC = AArch64DC::lookupDCByEncoding(Encoding); |
786 | if (!DC || !DC->haveFeatures(STI.getFeatureBits())) |
787 | return false; |
788 | |
789 | NeedsReg = true; |
790 | Ins = "dc\t"; |
791 | Name = std::string(DC->Name); |
792 | } |
793 | break; |
794 | // AT aliases |
795 | case 8: case 9: { |
796 | const AArch64AT::AT *AT = AArch64AT::lookupATByEncoding(Encoding); |
797 | if (!AT || !AT->haveFeatures(STI.getFeatureBits())) |
798 | return false; |
799 | |
800 | NeedsReg = true; |
801 | Ins = "at\t"; |
802 | Name = std::string(AT->Name); |
803 | } |
804 | break; |
805 | } |
806 | } else if (CnVal == 8) { |
807 | // TLBI aliases |
808 | const AArch64TLBI::TLBI *TLBI = AArch64TLBI::lookupTLBIByEncoding(Encoding); |
809 | if (!TLBI || !TLBI->haveFeatures(STI.getFeatureBits())) |
810 | return false; |
811 | |
812 | NeedsReg = TLBI->NeedsReg; |
813 | Ins = "tlbi\t"; |
814 | Name = std::string(TLBI->Name); |
815 | } |
816 | else |
817 | return false; |
818 | |
819 | std::string Str = Ins + Name; |
820 | std::transform(Str.begin(), Str.end(), Str.begin(), ::tolower); |
821 | |
822 | O << '\t' << Str; |
823 | if (NeedsReg) |
824 | O << ", " << getRegisterName(MI->getOperand(4).getReg()); |
825 | |
826 | return true; |
827 | } |
828 | |
829 | void AArch64InstPrinter::printOperand(const MCInst *MI, unsigned OpNo, |
830 | const MCSubtargetInfo &STI, |
831 | raw_ostream &O) { |
832 | const MCOperand &Op = MI->getOperand(OpNo); |
833 | if (Op.isReg()) { |
834 | unsigned Reg = Op.getReg(); |
835 | O << getRegisterName(Reg); |
836 | } else if (Op.isImm()) { |
837 | printImm(MI, OpNo, STI, O); |
838 | } else { |
839 | assert(Op.isExpr() && "unknown operand kind in printOperand")(static_cast <bool> (Op.isExpr() && "unknown operand kind in printOperand" ) ? void (0) : __assert_fail ("Op.isExpr() && \"unknown operand kind in printOperand\"" , "/build/llvm-toolchain-snapshot-7~svn329677/lib/Target/AArch64/InstPrinter/AArch64InstPrinter.cpp" , 839, __extension__ __PRETTY_FUNCTION__)); |
840 | Op.getExpr()->print(O, &MAI); |
841 | } |
842 | } |
843 | |
844 | void AArch64InstPrinter::printImm(const MCInst *MI, unsigned OpNo, |
845 | const MCSubtargetInfo &STI, |
846 | raw_ostream &O) { |
847 | const MCOperand &Op = MI->getOperand(OpNo); |
848 | O << "#" << formatImm(Op.getImm()); |
849 | } |
850 | |
851 | void AArch64InstPrinter::printImmHex(const MCInst *MI, unsigned OpNo, |
852 | const MCSubtargetInfo &STI, |
853 | raw_ostream &O) { |
854 | const MCOperand &Op = MI->getOperand(OpNo); |
855 | O << format("#%#llx", Op.getImm()); |
856 | } |
857 | |
858 | void AArch64InstPrinter::printPostIncOperand(const MCInst *MI, unsigned OpNo, |
859 | unsigned Imm, raw_ostream &O) { |
860 | const MCOperand &Op = MI->getOperand(OpNo); |
861 | if (Op.isReg()) { |
862 | unsigned Reg = Op.getReg(); |
863 | if (Reg == AArch64::XZR) |
864 | O << "#" << Imm; |
865 | else |
866 | O << getRegisterName(Reg); |
867 | } else |
868 | llvm_unreachable("unknown operand kind in printPostIncOperand64")::llvm::llvm_unreachable_internal("unknown operand kind in printPostIncOperand64" , "/build/llvm-toolchain-snapshot-7~svn329677/lib/Target/AArch64/InstPrinter/AArch64InstPrinter.cpp" , 868); |
869 | } |
870 | |
871 | void AArch64InstPrinter::printVRegOperand(const MCInst *MI, unsigned OpNo, |
872 | const MCSubtargetInfo &STI, |
873 | raw_ostream &O) { |
874 | const MCOperand &Op = MI->getOperand(OpNo); |
875 | assert(Op.isReg() && "Non-register vreg operand!")(static_cast <bool> (Op.isReg() && "Non-register vreg operand!" ) ? void (0) : __assert_fail ("Op.isReg() && \"Non-register vreg operand!\"" , "/build/llvm-toolchain-snapshot-7~svn329677/lib/Target/AArch64/InstPrinter/AArch64InstPrinter.cpp" , 875, __extension__ __PRETTY_FUNCTION__)); |
876 | unsigned Reg = Op.getReg(); |
877 | O << getRegisterName(Reg, AArch64::vreg); |
878 | } |
879 | |
880 | void AArch64InstPrinter::printSysCROperand(const MCInst *MI, unsigned OpNo, |
881 | const MCSubtargetInfo &STI, |
882 | raw_ostream &O) { |
883 | const MCOperand &Op = MI->getOperand(OpNo); |
884 | assert(Op.isImm() && "System instruction C[nm] operands must be immediates!")(static_cast <bool> (Op.isImm() && "System instruction C[nm] operands must be immediates!" ) ? void (0) : __assert_fail ("Op.isImm() && \"System instruction C[nm] operands must be immediates!\"" , "/build/llvm-toolchain-snapshot-7~svn329677/lib/Target/AArch64/InstPrinter/AArch64InstPrinter.cpp" , 884, __extension__ __PRETTY_FUNCTION__)); |
885 | O << "c" << Op.getImm(); |
886 | } |
887 | |
888 | void AArch64InstPrinter::printAddSubImm(const MCInst *MI, unsigned OpNum, |
889 | const MCSubtargetInfo &STI, |
890 | raw_ostream &O) { |
891 | const MCOperand &MO = MI->getOperand(OpNum); |
892 | if (MO.isImm()) { |
893 | unsigned Val = (MO.getImm() & 0xfff); |
894 | assert(Val == MO.getImm() && "Add/sub immediate out of range!")(static_cast <bool> (Val == MO.getImm() && "Add/sub immediate out of range!" ) ? void (0) : __assert_fail ("Val == MO.getImm() && \"Add/sub immediate out of range!\"" , "/build/llvm-toolchain-snapshot-7~svn329677/lib/Target/AArch64/InstPrinter/AArch64InstPrinter.cpp" , 894, __extension__ __PRETTY_FUNCTION__)); |
895 | unsigned Shift = |
896 | AArch64_AM::getShiftValue(MI->getOperand(OpNum + 1).getImm()); |
897 | O << '#' << formatImm(Val); |
898 | if (Shift != 0) |
899 | printShifter(MI, OpNum + 1, STI, O); |
900 | |
901 | if (CommentStream) |
902 | *CommentStream << '=' << formatImm(Val << Shift) << '\n'; |
903 | } else { |
904 | assert(MO.isExpr() && "Unexpected operand type!")(static_cast <bool> (MO.isExpr() && "Unexpected operand type!" ) ? void (0) : __assert_fail ("MO.isExpr() && \"Unexpected operand type!\"" , "/build/llvm-toolchain-snapshot-7~svn329677/lib/Target/AArch64/InstPrinter/AArch64InstPrinter.cpp" , 904, __extension__ __PRETTY_FUNCTION__)); |
905 | MO.getExpr()->print(O, &MAI); |
906 | printShifter(MI, OpNum + 1, STI, O); |
907 | } |
908 | } |
909 | |
910 | template <typename T> |
911 | void AArch64InstPrinter::printLogicalImm(const MCInst *MI, unsigned OpNum, |
912 | const MCSubtargetInfo &STI, |
913 | raw_ostream &O) { |
914 | uint64_t Val = MI->getOperand(OpNum).getImm(); |
915 | O << "#0x"; |
916 | O.write_hex(AArch64_AM::decodeLogicalImmediate(Val, 8 * sizeof(T))); |
917 | } |
918 | |
919 | void AArch64InstPrinter::printShifter(const MCInst *MI, unsigned OpNum, |
920 | const MCSubtargetInfo &STI, |
921 | raw_ostream &O) { |
922 | unsigned Val = MI->getOperand(OpNum).getImm(); |
923 | // LSL #0 should not be printed. |
924 | if (AArch64_AM::getShiftType(Val) == AArch64_AM::LSL && |
925 | AArch64_AM::getShiftValue(Val) == 0) |
926 | return; |
927 | O << ", " << AArch64_AM::getShiftExtendName(AArch64_AM::getShiftType(Val)) |
928 | << " #" << AArch64_AM::getShiftValue(Val); |
929 | } |
930 | |
931 | void AArch64InstPrinter::printShiftedRegister(const MCInst *MI, unsigned OpNum, |
932 | const MCSubtargetInfo &STI, |
933 | raw_ostream &O) { |
934 | O << getRegisterName(MI->getOperand(OpNum).getReg()); |
935 | printShifter(MI, OpNum + 1, STI, O); |
936 | } |
937 | |
938 | void AArch64InstPrinter::printExtendedRegister(const MCInst *MI, unsigned OpNum, |
939 | const MCSubtargetInfo &STI, |
940 | raw_ostream &O) { |
941 | O << getRegisterName(MI->getOperand(OpNum).getReg()); |
942 | printArithExtend(MI, OpNum + 1, STI, O); |
943 | } |
944 | |
945 | void AArch64InstPrinter::printArithExtend(const MCInst *MI, unsigned OpNum, |
946 | const MCSubtargetInfo &STI, |
947 | raw_ostream &O) { |
948 | unsigned Val = MI->getOperand(OpNum).getImm(); |
949 | AArch64_AM::ShiftExtendType ExtType = AArch64_AM::getArithExtendType(Val); |
950 | unsigned ShiftVal = AArch64_AM::getArithShiftValue(Val); |
951 | |
952 | // If the destination or first source register operand is [W]SP, print |
953 | // UXTW/UXTX as LSL, and if the shift amount is also zero, print nothing at |
954 | // all. |
955 | if (ExtType == AArch64_AM::UXTW || ExtType == AArch64_AM::UXTX) { |
956 | unsigned Dest = MI->getOperand(0).getReg(); |
957 | unsigned Src1 = MI->getOperand(1).getReg(); |
958 | if ( ((Dest == AArch64::SP || Src1 == AArch64::SP) && |
959 | ExtType == AArch64_AM::UXTX) || |
960 | ((Dest == AArch64::WSP || Src1 == AArch64::WSP) && |
961 | ExtType == AArch64_AM::UXTW) ) { |
962 | if (ShiftVal != 0) |
963 | O << ", lsl #" << ShiftVal; |
964 | return; |
965 | } |
966 | } |
967 | O << ", " << AArch64_AM::getShiftExtendName(ExtType); |
968 | if (ShiftVal != 0) |
969 | O << " #" << ShiftVal; |
970 | } |
971 | |
972 | void AArch64InstPrinter::printMemExtend(const MCInst *MI, unsigned OpNum, |
973 | raw_ostream &O, char SrcRegKind, |
974 | unsigned Width) { |
975 | unsigned SignExtend = MI->getOperand(OpNum).getImm(); |
976 | unsigned DoShift = MI->getOperand(OpNum + 1).getImm(); |
977 | |
978 | // sxtw, sxtx, uxtw or lsl (== uxtx) |
979 | bool IsLSL = !SignExtend && SrcRegKind == 'x'; |
980 | if (IsLSL) |
981 | O << "lsl"; |
982 | else |
983 | O << (SignExtend ? 's' : 'u') << "xt" << SrcRegKind; |
984 | |
985 | if (DoShift || IsLSL) |
986 | O << " #" << Log2_32(Width / 8); |
987 | } |
988 | |
989 | void AArch64InstPrinter::printCondCode(const MCInst *MI, unsigned OpNum, |
990 | const MCSubtargetInfo &STI, |
991 | raw_ostream &O) { |
992 | AArch64CC::CondCode CC = (AArch64CC::CondCode)MI->getOperand(OpNum).getImm(); |
993 | O << AArch64CC::getCondCodeName(CC); |
994 | } |
995 | |
996 | void AArch64InstPrinter::printInverseCondCode(const MCInst *MI, unsigned OpNum, |
997 | const MCSubtargetInfo &STI, |
998 | raw_ostream &O) { |
999 | AArch64CC::CondCode CC = (AArch64CC::CondCode)MI->getOperand(OpNum).getImm(); |
1000 | O << AArch64CC::getCondCodeName(AArch64CC::getInvertedCondCode(CC)); |
1001 | } |
1002 | |
1003 | void AArch64InstPrinter::printAMNoIndex(const MCInst *MI, unsigned OpNum, |
1004 | const MCSubtargetInfo &STI, |
1005 | raw_ostream &O) { |
1006 | O << '[' << getRegisterName(MI->getOperand(OpNum).getReg()) << ']'; |
1007 | } |
1008 | |
1009 | template<int Scale> |
1010 | void AArch64InstPrinter::printImmScale(const MCInst *MI, unsigned OpNum, |
1011 | const MCSubtargetInfo &STI, |
1012 | raw_ostream &O) { |
1013 | O << '#' << formatImm(Scale * MI->getOperand(OpNum).getImm()); |
1014 | } |
1015 | |
1016 | void AArch64InstPrinter::printUImm12Offset(const MCInst *MI, unsigned OpNum, |
1017 | unsigned Scale, raw_ostream &O) { |
1018 | const MCOperand MO = MI->getOperand(OpNum); |
1019 | if (MO.isImm()) { |
1020 | O << "#" << formatImm(MO.getImm() * Scale); |
1021 | } else { |
1022 | assert(MO.isExpr() && "Unexpected operand type!")(static_cast <bool> (MO.isExpr() && "Unexpected operand type!" ) ? void (0) : __assert_fail ("MO.isExpr() && \"Unexpected operand type!\"" , "/build/llvm-toolchain-snapshot-7~svn329677/lib/Target/AArch64/InstPrinter/AArch64InstPrinter.cpp" , 1022, __extension__ __PRETTY_FUNCTION__)); |
1023 | MO.getExpr()->print(O, &MAI); |
1024 | } |
1025 | } |
1026 | |
1027 | void AArch64InstPrinter::printAMIndexedWB(const MCInst *MI, unsigned OpNum, |
1028 | unsigned Scale, raw_ostream &O) { |
1029 | const MCOperand MO1 = MI->getOperand(OpNum + 1); |
1030 | O << '[' << getRegisterName(MI->getOperand(OpNum).getReg()); |
1031 | if (MO1.isImm()) { |
1032 | O << ", #" << formatImm(MO1.getImm() * Scale); |
1033 | } else { |
1034 | assert(MO1.isExpr() && "Unexpected operand type!")(static_cast <bool> (MO1.isExpr() && "Unexpected operand type!" ) ? void (0) : __assert_fail ("MO1.isExpr() && \"Unexpected operand type!\"" , "/build/llvm-toolchain-snapshot-7~svn329677/lib/Target/AArch64/InstPrinter/AArch64InstPrinter.cpp" , 1034, __extension__ __PRETTY_FUNCTION__)); |
1035 | O << ", "; |
1036 | MO1.getExpr()->print(O, &MAI); |
1037 | } |
1038 | O << ']'; |
1039 | } |
1040 | |
1041 | void AArch64InstPrinter::printPrefetchOp(const MCInst *MI, unsigned OpNum, |
1042 | const MCSubtargetInfo &STI, |
1043 | raw_ostream &O) { |
1044 | unsigned prfop = MI->getOperand(OpNum).getImm(); |
1045 | auto PRFM = AArch64PRFM::lookupPRFMByEncoding(prfop); |
1046 | if (PRFM) |
1047 | O << PRFM->Name; |
1048 | else |
1049 | O << '#' << formatImm(prfop); |
1050 | } |
1051 | |
1052 | void AArch64InstPrinter::printPSBHintOp(const MCInst *MI, unsigned OpNum, |
1053 | const MCSubtargetInfo &STI, |
1054 | raw_ostream &O) { |
1055 | unsigned psbhintop = MI->getOperand(OpNum).getImm(); |
1056 | auto PSB = AArch64PSBHint::lookupPSBByEncoding(psbhintop); |
1057 | if (PSB) |
1058 | O << PSB->Name; |
1059 | else |
1060 | O << '#' << formatImm(psbhintop); |
1061 | } |
1062 | |
1063 | void AArch64InstPrinter::printFPImmOperand(const MCInst *MI, unsigned OpNum, |
1064 | const MCSubtargetInfo &STI, |
1065 | raw_ostream &O) { |
1066 | const MCOperand &MO = MI->getOperand(OpNum); |
1067 | float FPImm = |
1068 | MO.isFPImm() ? MO.getFPImm() : AArch64_AM::getFPImmFloat(MO.getImm()); |
1069 | |
1070 | // 8 decimal places are enough to perfectly represent permitted floats. |
1071 | O << format("#%.8f", FPImm); |
1072 | } |
1073 | |
1074 | static unsigned getNextVectorRegister(unsigned Reg, unsigned Stride = 1) { |
1075 | while (Stride--) { |
1076 | switch (Reg) { |
1077 | default: |
1078 | llvm_unreachable("Vector register expected!")::llvm::llvm_unreachable_internal("Vector register expected!" , "/build/llvm-toolchain-snapshot-7~svn329677/lib/Target/AArch64/InstPrinter/AArch64InstPrinter.cpp" , 1078); |
1079 | case AArch64::Q0: Reg = AArch64::Q1; break; |
1080 | case AArch64::Q1: Reg = AArch64::Q2; break; |
1081 | case AArch64::Q2: Reg = AArch64::Q3; break; |
1082 | case AArch64::Q3: Reg = AArch64::Q4; break; |
1083 | case AArch64::Q4: Reg = AArch64::Q5; break; |
1084 | case AArch64::Q5: Reg = AArch64::Q6; break; |
1085 | case AArch64::Q6: Reg = AArch64::Q7; break; |
1086 | case AArch64::Q7: Reg = AArch64::Q8; break; |
1087 | case AArch64::Q8: Reg = AArch64::Q9; break; |
1088 | case AArch64::Q9: Reg = AArch64::Q10; break; |
1089 | case AArch64::Q10: Reg = AArch64::Q11; break; |
1090 | case AArch64::Q11: Reg = AArch64::Q12; break; |
1091 | case AArch64::Q12: Reg = AArch64::Q13; break; |
1092 | case AArch64::Q13: Reg = AArch64::Q14; break; |
1093 | case AArch64::Q14: Reg = AArch64::Q15; break; |
1094 | case AArch64::Q15: Reg = AArch64::Q16; break; |
1095 | case AArch64::Q16: Reg = AArch64::Q17; break; |
1096 | case AArch64::Q17: Reg = AArch64::Q18; break; |
1097 | case AArch64::Q18: Reg = AArch64::Q19; break; |
1098 | case AArch64::Q19: Reg = AArch64::Q20; break; |
1099 | case AArch64::Q20: Reg = AArch64::Q21; break; |
1100 | case AArch64::Q21: Reg = AArch64::Q22; break; |
1101 | case AArch64::Q22: Reg = AArch64::Q23; break; |
1102 | case AArch64::Q23: Reg = AArch64::Q24; break; |
1103 | case AArch64::Q24: Reg = AArch64::Q25; break; |
1104 | case AArch64::Q25: Reg = AArch64::Q26; break; |
1105 | case AArch64::Q26: Reg = AArch64::Q27; break; |
1106 | case AArch64::Q27: Reg = AArch64::Q28; break; |
1107 | case AArch64::Q28: Reg = AArch64::Q29; break; |
1108 | case AArch64::Q29: Reg = AArch64::Q30; break; |
1109 | case AArch64::Q30: Reg = AArch64::Q31; break; |
1110 | // Vector lists can wrap around. |
1111 | case AArch64::Q31: |
1112 | Reg = AArch64::Q0; |
1113 | break; |
1114 | } |
1115 | } |
1116 | return Reg; |
1117 | } |
1118 | |
1119 | template<unsigned size> |
1120 | void AArch64InstPrinter::printGPRSeqPairsClassOperand(const MCInst *MI, |
1121 | unsigned OpNum, |
1122 | const MCSubtargetInfo &STI, |
1123 | raw_ostream &O) { |
1124 | static_assert(size == 64 || size == 32, |
1125 | "Template parameter must be either 32 or 64"); |
1126 | unsigned Reg = MI->getOperand(OpNum).getReg(); |
1127 | |
1128 | unsigned Sube = (size == 32) ? AArch64::sube32 : AArch64::sube64; |
1129 | unsigned Subo = (size == 32) ? AArch64::subo32 : AArch64::subo64; |
1130 | |
1131 | unsigned Even = MRI.getSubReg(Reg, Sube); |
1132 | unsigned Odd = MRI.getSubReg(Reg, Subo); |
1133 | O << getRegisterName(Even) << ", " << getRegisterName(Odd); |
1134 | } |
1135 | |
1136 | void AArch64InstPrinter::printVectorList(const MCInst *MI, unsigned OpNum, |
1137 | const MCSubtargetInfo &STI, |
1138 | raw_ostream &O, |
1139 | StringRef LayoutSuffix) { |
1140 | unsigned Reg = MI->getOperand(OpNum).getReg(); |
1141 | |
1142 | O << "{ "; |
1143 | |
1144 | // Work out how many registers there are in the list (if there is an actual |
1145 | // list). |
1146 | unsigned NumRegs = 1; |
1147 | if (MRI.getRegClass(AArch64::DDRegClassID).contains(Reg) || |
1148 | MRI.getRegClass(AArch64::QQRegClassID).contains(Reg)) |
1149 | NumRegs = 2; |
1150 | else if (MRI.getRegClass(AArch64::DDDRegClassID).contains(Reg) || |
1151 | MRI.getRegClass(AArch64::QQQRegClassID).contains(Reg)) |
1152 | NumRegs = 3; |
1153 | else if (MRI.getRegClass(AArch64::DDDDRegClassID).contains(Reg) || |
1154 | MRI.getRegClass(AArch64::QQQQRegClassID).contains(Reg)) |
1155 | NumRegs = 4; |
1156 | |
1157 | // Now forget about the list and find out what the first register is. |
1158 | if (unsigned FirstReg = MRI.getSubReg(Reg, AArch64::dsub0)) |
1159 | Reg = FirstReg; |
1160 | else if (unsigned FirstReg = MRI.getSubReg(Reg, AArch64::qsub0)) |
1161 | Reg = FirstReg; |
1162 | |
1163 | // If it's a D-reg, we need to promote it to the equivalent Q-reg before |
1164 | // printing (otherwise getRegisterName fails). |
1165 | if (MRI.getRegClass(AArch64::FPR64RegClassID).contains(Reg)) { |
1166 | const MCRegisterClass &FPR128RC = |
1167 | MRI.getRegClass(AArch64::FPR128RegClassID); |
1168 | Reg = MRI.getMatchingSuperReg(Reg, AArch64::dsub, &FPR128RC); |
1169 | } |
1170 | |
1171 | for (unsigned i = 0; i < NumRegs; ++i, Reg = getNextVectorRegister(Reg)) { |
1172 | O << getRegisterName(Reg, AArch64::vreg) << LayoutSuffix; |
1173 | if (i + 1 != NumRegs) |
1174 | O << ", "; |
1175 | } |
1176 | |
1177 | O << " }"; |
1178 | } |
1179 | |
1180 | void |
1181 | AArch64InstPrinter::printImplicitlyTypedVectorList(const MCInst *MI, |
1182 | unsigned OpNum, |
1183 | const MCSubtargetInfo &STI, |
1184 | raw_ostream &O) { |
1185 | printVectorList(MI, OpNum, STI, O, ""); |
1186 | } |
1187 | |
1188 | template <unsigned NumLanes, char LaneKind> |
1189 | void AArch64InstPrinter::printTypedVectorList(const MCInst *MI, unsigned OpNum, |
1190 | const MCSubtargetInfo &STI, |
1191 | raw_ostream &O) { |
1192 | std::string Suffix("."); |
1193 | if (NumLanes) |
1194 | Suffix += itostr(NumLanes) + LaneKind; |
1195 | else |
1196 | Suffix += LaneKind; |
1197 | |
1198 | printVectorList(MI, OpNum, STI, O, Suffix); |
1199 | } |
1200 | |
1201 | void AArch64InstPrinter::printVectorIndex(const MCInst *MI, unsigned OpNum, |
1202 | const MCSubtargetInfo &STI, |
1203 | raw_ostream &O) { |
1204 | O << "[" << MI->getOperand(OpNum).getImm() << "]"; |
1205 | } |
1206 | |
1207 | void AArch64InstPrinter::printAlignedLabel(const MCInst *MI, unsigned OpNum, |
1208 | const MCSubtargetInfo &STI, |
1209 | raw_ostream &O) { |
1210 | const MCOperand &Op = MI->getOperand(OpNum); |
1211 | |
1212 | // If the label has already been resolved to an immediate offset (say, when |
1213 | // we're running the disassembler), just print the immediate. |
1214 | if (Op.isImm()) { |
1215 | O << "#" << formatImm(Op.getImm() * 4); |
1216 | return; |
1217 | } |
1218 | |
1219 | // If the branch target is simply an address then print it in hex. |
1220 | const MCConstantExpr *BranchTarget = |
1221 | dyn_cast<MCConstantExpr>(MI->getOperand(OpNum).getExpr()); |
1222 | int64_t Address; |
1223 | if (BranchTarget && BranchTarget->evaluateAsAbsolute(Address)) { |
1224 | O << "0x"; |
1225 | O.write_hex(Address); |
1226 | } else { |
1227 | // Otherwise, just print the expression. |
1228 | MI->getOperand(OpNum).getExpr()->print(O, &MAI); |
1229 | } |
1230 | } |
1231 | |
1232 | void AArch64InstPrinter::printAdrpLabel(const MCInst *MI, unsigned OpNum, |
1233 | const MCSubtargetInfo &STI, |
1234 | raw_ostream &O) { |
1235 | const MCOperand &Op = MI->getOperand(OpNum); |
1236 | |
1237 | // If the label has already been resolved to an immediate offset (say, when |
1238 | // we're running the disassembler), just print the immediate. |
1239 | if (Op.isImm()) { |
1240 | O << "#" << formatImm(Op.getImm() * (1 << 12)); |
1241 | return; |
1242 | } |
1243 | |
1244 | // Otherwise, just print the expression. |
1245 | MI->getOperand(OpNum).getExpr()->print(O, &MAI); |
1246 | } |
1247 | |
1248 | void AArch64InstPrinter::printBarrierOption(const MCInst *MI, unsigned OpNo, |
1249 | const MCSubtargetInfo &STI, |
1250 | raw_ostream &O) { |
1251 | unsigned Val = MI->getOperand(OpNo).getImm(); |
1252 | unsigned Opcode = MI->getOpcode(); |
1253 | |
1254 | StringRef Name; |
1255 | if (Opcode == AArch64::ISB) { |
1256 | auto ISB = AArch64ISB::lookupISBByEncoding(Val); |
1257 | Name = ISB ? ISB->Name : ""; |
1258 | } else { |
1259 | auto DB = AArch64DB::lookupDBByEncoding(Val); |
1260 | Name = DB ? DB->Name : ""; |
1261 | } |
1262 | if (!Name.empty()) |
1263 | O << Name; |
1264 | else |
1265 | O << "#" << Val; |
1266 | } |
1267 | |
1268 | void AArch64InstPrinter::printMRSSystemRegister(const MCInst *MI, unsigned OpNo, |
1269 | const MCSubtargetInfo &STI, |
1270 | raw_ostream &O) { |
1271 | unsigned Val = MI->getOperand(OpNo).getImm(); |
1272 | |
1273 | // Horrible hack for the one register that has identical encodings but |
1274 | // different names in MSR and MRS. Because of this, one of MRS and MSR is |
1275 | // going to get the wrong entry |
1276 | if (Val == AArch64SysReg::DBGDTRRX_EL0) { |
1277 | O << "DBGDTRRX_EL0"; |
1278 | return; |
1279 | } |
1280 | |
1281 | const AArch64SysReg::SysReg *Reg = AArch64SysReg::lookupSysRegByEncoding(Val); |
1282 | if (Reg && Reg->Readable && Reg->haveFeatures(STI.getFeatureBits())) |
1283 | O << Reg->Name; |
1284 | else |
1285 | O << AArch64SysReg::genericRegisterString(Val); |
1286 | } |
1287 | |
1288 | void AArch64InstPrinter::printMSRSystemRegister(const MCInst *MI, unsigned OpNo, |
1289 | const MCSubtargetInfo &STI, |
1290 | raw_ostream &O) { |
1291 | unsigned Val = MI->getOperand(OpNo).getImm(); |
1292 | |
1293 | // Horrible hack for the one register that has identical encodings but |
1294 | // different names in MSR and MRS. Because of this, one of MRS and MSR is |
1295 | // going to get the wrong entry |
1296 | if (Val == AArch64SysReg::DBGDTRTX_EL0) { |
1297 | O << "DBGDTRTX_EL0"; |
1298 | return; |
1299 | } |
1300 | |
1301 | const AArch64SysReg::SysReg *Reg = AArch64SysReg::lookupSysRegByEncoding(Val); |
1302 | if (Reg && Reg->Writeable && Reg->haveFeatures(STI.getFeatureBits())) |
1303 | O << Reg->Name; |
1304 | else |
1305 | O << AArch64SysReg::genericRegisterString(Val); |
1306 | } |
1307 | |
1308 | void AArch64InstPrinter::printSystemPStateField(const MCInst *MI, unsigned OpNo, |
1309 | const MCSubtargetInfo &STI, |
1310 | raw_ostream &O) { |
1311 | unsigned Val = MI->getOperand(OpNo).getImm(); |
1312 | |
1313 | auto PState = AArch64PState::lookupPStateByEncoding(Val); |
1314 | if (PState && PState->haveFeatures(STI.getFeatureBits())) |
1315 | O << PState->Name; |
1316 | else |
1317 | O << "#" << formatImm(Val); |
1318 | } |
1319 | |
1320 | void AArch64InstPrinter::printSIMDType10Operand(const MCInst *MI, unsigned OpNo, |
1321 | const MCSubtargetInfo &STI, |
1322 | raw_ostream &O) { |
1323 | unsigned RawVal = MI->getOperand(OpNo).getImm(); |
1324 | uint64_t Val = AArch64_AM::decodeAdvSIMDModImmType10(RawVal); |
1325 | O << format("#%#016llx", Val); |
1326 | } |
1327 | |
1328 | template<int64_t Angle, int64_t Remainder> |
1329 | void AArch64InstPrinter::printComplexRotationOp(const MCInst *MI, unsigned OpNo, |
1330 | const MCSubtargetInfo &STI, |
1331 | raw_ostream &O) { |
1332 | unsigned Val = MI->getOperand(OpNo).getImm(); |
1333 | O << "#" << (Val * Angle) + Remainder; |
1334 | } |
1335 | |
1336 | void AArch64InstPrinter::printSVEPattern(const MCInst *MI, unsigned OpNum, |
1337 | const MCSubtargetInfo &STI, |
1338 | raw_ostream &O) { |
1339 | unsigned Val = MI->getOperand(OpNum).getImm(); |
1340 | if (auto Pat = AArch64SVEPredPattern::lookupSVEPREDPATByEncoding(Val)) |
1341 | O << Pat->Name; |
1342 | else |
1343 | O << '#' << formatImm(Val); |
1344 | } |
1345 | |
1346 | template <char suffix> |
1347 | void AArch64InstPrinter::printSVERegOp(const MCInst *MI, unsigned OpNum, |
1348 | const MCSubtargetInfo &STI, |
1349 | raw_ostream &O) { |
1350 | switch (suffix) { |
1351 | case 0: |
1352 | case 'b': |
1353 | case 'h': |
1354 | case 's': |
1355 | case 'd': |
1356 | case 'q': |
1357 | break; |
1358 | default: llvm_unreachable("Invalid kind specifier.")::llvm::llvm_unreachable_internal("Invalid kind specifier.", "/build/llvm-toolchain-snapshot-7~svn329677/lib/Target/AArch64/InstPrinter/AArch64InstPrinter.cpp" , 1358); |
1359 | } |
1360 | |
1361 | unsigned Reg = MI->getOperand(OpNum).getReg(); |
1362 | O << getRegisterName(Reg); |
1363 | if (suffix != 0) |
1364 | O << '.' << suffix; |
1365 | } |