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