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