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