10b57cec5SDimitry Andric //==-- AArch64InstPrinter.cpp - Convert AArch64 MCInst to assembly syntax --==//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric //
90b57cec5SDimitry Andric // This class prints an AArch64 MCInst to a .s file.
100b57cec5SDimitry Andric //
110b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
120b57cec5SDimitry Andric 
130b57cec5SDimitry Andric #include "AArch64InstPrinter.h"
140b57cec5SDimitry Andric #include "MCTargetDesc/AArch64AddressingModes.h"
150b57cec5SDimitry Andric #include "Utils/AArch64BaseInfo.h"
160b57cec5SDimitry Andric #include "llvm/ADT/STLExtras.h"
170b57cec5SDimitry Andric #include "llvm/ADT/StringExtras.h"
180b57cec5SDimitry Andric #include "llvm/ADT/StringRef.h"
190b57cec5SDimitry Andric #include "llvm/MC/MCAsmInfo.h"
200b57cec5SDimitry Andric #include "llvm/MC/MCExpr.h"
210b57cec5SDimitry Andric #include "llvm/MC/MCInst.h"
220b57cec5SDimitry Andric #include "llvm/MC/MCRegisterInfo.h"
230b57cec5SDimitry Andric #include "llvm/MC/MCSubtargetInfo.h"
240b57cec5SDimitry Andric #include "llvm/Support/Casting.h"
250b57cec5SDimitry Andric #include "llvm/Support/ErrorHandling.h"
260b57cec5SDimitry Andric #include "llvm/Support/Format.h"
270b57cec5SDimitry Andric #include "llvm/Support/MathExtras.h"
280b57cec5SDimitry Andric #include "llvm/Support/raw_ostream.h"
290b57cec5SDimitry Andric #include <cassert>
300b57cec5SDimitry Andric #include <cstdint>
310b57cec5SDimitry Andric #include <string>
320b57cec5SDimitry Andric 
330b57cec5SDimitry Andric using namespace llvm;
340b57cec5SDimitry Andric 
350b57cec5SDimitry Andric #define DEBUG_TYPE "asm-printer"
360b57cec5SDimitry Andric 
370b57cec5SDimitry Andric #define GET_INSTRUCTION_NAME
380b57cec5SDimitry Andric #define PRINT_ALIAS_INSTR
390b57cec5SDimitry Andric #include "AArch64GenAsmWriter.inc"
400b57cec5SDimitry Andric #define GET_INSTRUCTION_NAME
410b57cec5SDimitry Andric #define PRINT_ALIAS_INSTR
420b57cec5SDimitry Andric #include "AArch64GenAsmWriter1.inc"
430b57cec5SDimitry Andric 
AArch64InstPrinter(const MCAsmInfo & MAI,const MCInstrInfo & MII,const MCRegisterInfo & MRI)440b57cec5SDimitry Andric AArch64InstPrinter::AArch64InstPrinter(const MCAsmInfo &MAI,
450b57cec5SDimitry Andric                                        const MCInstrInfo &MII,
460b57cec5SDimitry Andric                                        const MCRegisterInfo &MRI)
470b57cec5SDimitry Andric     : MCInstPrinter(MAI, MII, MRI) {}
480b57cec5SDimitry Andric 
AArch64AppleInstPrinter(const MCAsmInfo & MAI,const MCInstrInfo & MII,const MCRegisterInfo & MRI)490b57cec5SDimitry Andric AArch64AppleInstPrinter::AArch64AppleInstPrinter(const MCAsmInfo &MAI,
500b57cec5SDimitry Andric                                                  const MCInstrInfo &MII,
510b57cec5SDimitry Andric                                                  const MCRegisterInfo &MRI)
520b57cec5SDimitry Andric     : AArch64InstPrinter(MAI, MII, MRI) {}
530b57cec5SDimitry Andric 
applyTargetSpecificCLOption(StringRef Opt)54fe6060f1SDimitry Andric bool AArch64InstPrinter::applyTargetSpecificCLOption(StringRef Opt) {
55fe6060f1SDimitry Andric   if (Opt == "no-aliases") {
56fe6060f1SDimitry Andric     PrintAliases = false;
57fe6060f1SDimitry Andric     return true;
58fe6060f1SDimitry Andric   }
59fe6060f1SDimitry Andric   return false;
60fe6060f1SDimitry Andric }
61fe6060f1SDimitry Andric 
printRegName(raw_ostream & OS,MCRegister Reg) const62bdd1243dSDimitry Andric void AArch64InstPrinter::printRegName(raw_ostream &OS, MCRegister Reg) const {
635f757f3fSDimitry Andric   markup(OS, Markup::Register) << getRegisterName(Reg);
64bdd1243dSDimitry Andric }
65bdd1243dSDimitry Andric 
printRegName(raw_ostream & OS,MCRegister Reg,unsigned AltIdx) const66bdd1243dSDimitry Andric void AArch64InstPrinter::printRegName(raw_ostream &OS, MCRegister Reg,
67bdd1243dSDimitry Andric                                       unsigned AltIdx) const {
685f757f3fSDimitry Andric   markup(OS, Markup::Register) << getRegisterName(Reg, AltIdx);
69bdd1243dSDimitry Andric }
70bdd1243dSDimitry Andric 
getRegName(MCRegister Reg) const71bdd1243dSDimitry Andric StringRef AArch64InstPrinter::getRegName(MCRegister Reg) const {
72bdd1243dSDimitry Andric   return getRegisterName(Reg);
730b57cec5SDimitry Andric }
740b57cec5SDimitry Andric 
printInst(const MCInst * MI,uint64_t Address,StringRef Annot,const MCSubtargetInfo & STI,raw_ostream & O)75480093f4SDimitry Andric void AArch64InstPrinter::printInst(const MCInst *MI, uint64_t Address,
76480093f4SDimitry Andric                                    StringRef Annot, const MCSubtargetInfo &STI,
77480093f4SDimitry Andric                                    raw_ostream &O) {
780b57cec5SDimitry Andric   // Check for special encodings and print the canonical alias instead.
790b57cec5SDimitry Andric 
800b57cec5SDimitry Andric   unsigned Opcode = MI->getOpcode();
810b57cec5SDimitry Andric 
820b57cec5SDimitry Andric   if (Opcode == AArch64::SYSxt)
830b57cec5SDimitry Andric     if (printSysAlias(MI, STI, O)) {
840b57cec5SDimitry Andric       printAnnotation(O, Annot);
850b57cec5SDimitry Andric       return;
860b57cec5SDimitry Andric     }
870b57cec5SDimitry Andric 
88bdd1243dSDimitry Andric   if (Opcode == AArch64::SYSPxt || Opcode == AArch64::SYSPxt_XZR)
89bdd1243dSDimitry Andric     if (printSyspAlias(MI, STI, O)) {
90bdd1243dSDimitry Andric       printAnnotation(O, Annot);
91bdd1243dSDimitry Andric       return;
92bdd1243dSDimitry Andric     }
93bdd1243dSDimitry Andric 
94bdd1243dSDimitry Andric   // RPRFM overlaps PRFM (reg), so try to print it as RPRFM here.
95bdd1243dSDimitry Andric   if ((Opcode == AArch64::PRFMroX) || (Opcode == AArch64::PRFMroW)) {
96bdd1243dSDimitry Andric     if (printRangePrefetchAlias(MI, STI, O, Annot))
97bdd1243dSDimitry Andric       return;
98bdd1243dSDimitry Andric   }
99bdd1243dSDimitry Andric 
1000b57cec5SDimitry Andric   // SBFM/UBFM should print to a nicer aliased form if possible.
1010b57cec5SDimitry Andric   if (Opcode == AArch64::SBFMXri || Opcode == AArch64::SBFMWri ||
1020b57cec5SDimitry Andric       Opcode == AArch64::UBFMXri || Opcode == AArch64::UBFMWri) {
1030b57cec5SDimitry Andric     const MCOperand &Op0 = MI->getOperand(0);
1040b57cec5SDimitry Andric     const MCOperand &Op1 = MI->getOperand(1);
1050b57cec5SDimitry Andric     const MCOperand &Op2 = MI->getOperand(2);
1060b57cec5SDimitry Andric     const MCOperand &Op3 = MI->getOperand(3);
1070b57cec5SDimitry Andric 
1080b57cec5SDimitry Andric     bool IsSigned = (Opcode == AArch64::SBFMXri || Opcode == AArch64::SBFMWri);
1090b57cec5SDimitry Andric     bool Is64Bit = (Opcode == AArch64::SBFMXri || Opcode == AArch64::UBFMXri);
1100b57cec5SDimitry Andric     if (Op2.isImm() && Op2.getImm() == 0 && Op3.isImm()) {
1110b57cec5SDimitry Andric       const char *AsmMnemonic = nullptr;
1120b57cec5SDimitry Andric 
1130b57cec5SDimitry Andric       switch (Op3.getImm()) {
1140b57cec5SDimitry Andric       default:
1150b57cec5SDimitry Andric         break;
1160b57cec5SDimitry Andric       case 7:
1170b57cec5SDimitry Andric         if (IsSigned)
1180b57cec5SDimitry Andric           AsmMnemonic = "sxtb";
1190b57cec5SDimitry Andric         else if (!Is64Bit)
1200b57cec5SDimitry Andric           AsmMnemonic = "uxtb";
1210b57cec5SDimitry Andric         break;
1220b57cec5SDimitry Andric       case 15:
1230b57cec5SDimitry Andric         if (IsSigned)
1240b57cec5SDimitry Andric           AsmMnemonic = "sxth";
1250b57cec5SDimitry Andric         else if (!Is64Bit)
1260b57cec5SDimitry Andric           AsmMnemonic = "uxth";
1270b57cec5SDimitry Andric         break;
1280b57cec5SDimitry Andric       case 31:
1290b57cec5SDimitry Andric         // *xtw is only valid for signed 64-bit operations.
1300b57cec5SDimitry Andric         if (Is64Bit && IsSigned)
1310b57cec5SDimitry Andric           AsmMnemonic = "sxtw";
1320b57cec5SDimitry Andric         break;
1330b57cec5SDimitry Andric       }
1340b57cec5SDimitry Andric 
1350b57cec5SDimitry Andric       if (AsmMnemonic) {
136bdd1243dSDimitry Andric         O << '\t' << AsmMnemonic << '\t';
137bdd1243dSDimitry Andric         printRegName(O, Op0.getReg());
138bdd1243dSDimitry Andric         O << ", ";
139bdd1243dSDimitry Andric         printRegName(O, getWRegFromXReg(Op1.getReg()));
1400b57cec5SDimitry Andric         printAnnotation(O, Annot);
1410b57cec5SDimitry Andric         return;
1420b57cec5SDimitry Andric       }
1430b57cec5SDimitry Andric     }
1440b57cec5SDimitry Andric 
1450b57cec5SDimitry Andric     // All immediate shifts are aliases, implemented using the Bitfield
1460b57cec5SDimitry Andric     // instruction. In all cases the immediate shift amount shift must be in
1470b57cec5SDimitry Andric     // the range 0 to (reg.size -1).
1480b57cec5SDimitry Andric     if (Op2.isImm() && Op3.isImm()) {
1490b57cec5SDimitry Andric       const char *AsmMnemonic = nullptr;
1500b57cec5SDimitry Andric       int shift = 0;
1510b57cec5SDimitry Andric       int64_t immr = Op2.getImm();
1520b57cec5SDimitry Andric       int64_t imms = Op3.getImm();
1530b57cec5SDimitry Andric       if (Opcode == AArch64::UBFMWri && imms != 0x1F && ((imms + 1) == immr)) {
1540b57cec5SDimitry Andric         AsmMnemonic = "lsl";
1550b57cec5SDimitry Andric         shift = 31 - imms;
1560b57cec5SDimitry Andric       } else if (Opcode == AArch64::UBFMXri && imms != 0x3f &&
1570b57cec5SDimitry Andric                  ((imms + 1 == immr))) {
1580b57cec5SDimitry Andric         AsmMnemonic = "lsl";
1590b57cec5SDimitry Andric         shift = 63 - imms;
1600b57cec5SDimitry Andric       } else if (Opcode == AArch64::UBFMWri && imms == 0x1f) {
1610b57cec5SDimitry Andric         AsmMnemonic = "lsr";
1620b57cec5SDimitry Andric         shift = immr;
1630b57cec5SDimitry Andric       } else if (Opcode == AArch64::UBFMXri && imms == 0x3f) {
1640b57cec5SDimitry Andric         AsmMnemonic = "lsr";
1650b57cec5SDimitry Andric         shift = immr;
1660b57cec5SDimitry Andric       } else if (Opcode == AArch64::SBFMWri && imms == 0x1f) {
1670b57cec5SDimitry Andric         AsmMnemonic = "asr";
1680b57cec5SDimitry Andric         shift = immr;
1690b57cec5SDimitry Andric       } else if (Opcode == AArch64::SBFMXri && imms == 0x3f) {
1700b57cec5SDimitry Andric         AsmMnemonic = "asr";
1710b57cec5SDimitry Andric         shift = immr;
1720b57cec5SDimitry Andric       }
1730b57cec5SDimitry Andric       if (AsmMnemonic) {
174bdd1243dSDimitry Andric         O << '\t' << AsmMnemonic << '\t';
175bdd1243dSDimitry Andric         printRegName(O, Op0.getReg());
176bdd1243dSDimitry Andric         O << ", ";
177bdd1243dSDimitry Andric         printRegName(O, Op1.getReg());
1785f757f3fSDimitry Andric         O << ", ";
1795f757f3fSDimitry Andric         markup(O, Markup::Immediate) << "#" << shift;
1800b57cec5SDimitry Andric         printAnnotation(O, Annot);
1810b57cec5SDimitry Andric         return;
1820b57cec5SDimitry Andric       }
1830b57cec5SDimitry Andric     }
1840b57cec5SDimitry Andric 
1850b57cec5SDimitry Andric     // SBFIZ/UBFIZ aliases
1860b57cec5SDimitry Andric     if (Op2.getImm() > Op3.getImm()) {
187bdd1243dSDimitry Andric       O << '\t' << (IsSigned ? "sbfiz" : "ubfiz") << '\t';
188bdd1243dSDimitry Andric       printRegName(O, Op0.getReg());
189bdd1243dSDimitry Andric       O << ", ";
190bdd1243dSDimitry Andric       printRegName(O, Op1.getReg());
1915f757f3fSDimitry Andric       O << ", ";
1925f757f3fSDimitry Andric       markup(O, Markup::Immediate) << "#" << (Is64Bit ? 64 : 32) - Op2.getImm();
1935f757f3fSDimitry Andric       O << ", ";
1945f757f3fSDimitry Andric       markup(O, Markup::Immediate) << "#" << Op3.getImm() + 1;
1950b57cec5SDimitry Andric       printAnnotation(O, Annot);
1960b57cec5SDimitry Andric       return;
1970b57cec5SDimitry Andric     }
1980b57cec5SDimitry Andric 
1990b57cec5SDimitry Andric     // Otherwise SBFX/UBFX is the preferred form
200bdd1243dSDimitry Andric     O << '\t' << (IsSigned ? "sbfx" : "ubfx") << '\t';
201bdd1243dSDimitry Andric     printRegName(O, Op0.getReg());
202bdd1243dSDimitry Andric     O << ", ";
203bdd1243dSDimitry Andric     printRegName(O, Op1.getReg());
2045f757f3fSDimitry Andric     O << ", ";
2055f757f3fSDimitry Andric     markup(O, Markup::Immediate) << "#" << Op2.getImm();
2065f757f3fSDimitry Andric     O << ", ";
2075f757f3fSDimitry Andric     markup(O, Markup::Immediate) << "#" << Op3.getImm() - Op2.getImm() + 1;
2080b57cec5SDimitry Andric     printAnnotation(O, Annot);
2090b57cec5SDimitry Andric     return;
2100b57cec5SDimitry Andric   }
2110b57cec5SDimitry Andric 
2120b57cec5SDimitry Andric   if (Opcode == AArch64::BFMXri || Opcode == AArch64::BFMWri) {
2130b57cec5SDimitry Andric     const MCOperand &Op0 = MI->getOperand(0); // Op1 == Op0
2140b57cec5SDimitry Andric     const MCOperand &Op2 = MI->getOperand(2);
2150b57cec5SDimitry Andric     int ImmR = MI->getOperand(3).getImm();
2160b57cec5SDimitry Andric     int ImmS = MI->getOperand(4).getImm();
2170b57cec5SDimitry Andric 
2180b57cec5SDimitry Andric     if ((Op2.getReg() == AArch64::WZR || Op2.getReg() == AArch64::XZR) &&
21906c3fb27SDimitry Andric         (ImmR == 0 || ImmS < ImmR) && STI.hasFeature(AArch64::HasV8_2aOps)) {
2200b57cec5SDimitry Andric       // BFC takes precedence over its entire range, sligtly differently to BFI.
2210b57cec5SDimitry Andric       int BitWidth = Opcode == AArch64::BFMXri ? 64 : 32;
2220b57cec5SDimitry Andric       int LSB = (BitWidth - ImmR) % BitWidth;
2230b57cec5SDimitry Andric       int Width = ImmS + 1;
2240b57cec5SDimitry Andric 
225bdd1243dSDimitry Andric       O << "\tbfc\t";
226bdd1243dSDimitry Andric       printRegName(O, Op0.getReg());
2275f757f3fSDimitry Andric       O << ", ";
2285f757f3fSDimitry Andric       markup(O, Markup::Immediate) << "#" << LSB;
2295f757f3fSDimitry Andric       O << ", ";
2305f757f3fSDimitry Andric       markup(O, Markup::Immediate) << "#" << Width;
2310b57cec5SDimitry Andric       printAnnotation(O, Annot);
2320b57cec5SDimitry Andric       return;
2330b57cec5SDimitry Andric     } else if (ImmS < ImmR) {
2340b57cec5SDimitry Andric       // BFI alias
2350b57cec5SDimitry Andric       int BitWidth = Opcode == AArch64::BFMXri ? 64 : 32;
2360b57cec5SDimitry Andric       int LSB = (BitWidth - ImmR) % BitWidth;
2370b57cec5SDimitry Andric       int Width = ImmS + 1;
2380b57cec5SDimitry Andric 
239bdd1243dSDimitry Andric       O << "\tbfi\t";
240bdd1243dSDimitry Andric       printRegName(O, Op0.getReg());
241bdd1243dSDimitry Andric       O << ", ";
242bdd1243dSDimitry Andric       printRegName(O, Op2.getReg());
2435f757f3fSDimitry Andric       O << ", ";
2445f757f3fSDimitry Andric       markup(O, Markup::Immediate) << "#" << LSB;
2455f757f3fSDimitry Andric       O << ", ";
2465f757f3fSDimitry Andric       markup(O, Markup::Immediate) << "#" << Width;
2470b57cec5SDimitry Andric       printAnnotation(O, Annot);
2480b57cec5SDimitry Andric       return;
2490b57cec5SDimitry Andric     }
2500b57cec5SDimitry Andric 
2510b57cec5SDimitry Andric     int LSB = ImmR;
2520b57cec5SDimitry Andric     int Width = ImmS - ImmR + 1;
2530b57cec5SDimitry Andric     // Otherwise BFXIL the preferred form
254bdd1243dSDimitry Andric     O << "\tbfxil\t";
255bdd1243dSDimitry Andric     printRegName(O, Op0.getReg());
256bdd1243dSDimitry Andric     O << ", ";
257bdd1243dSDimitry Andric     printRegName(O, Op2.getReg());
2585f757f3fSDimitry Andric     O << ", ";
2595f757f3fSDimitry Andric     markup(O, Markup::Immediate) << "#" << LSB;
2605f757f3fSDimitry Andric     O << ", ";
2615f757f3fSDimitry Andric     markup(O, Markup::Immediate) << "#" << Width;
2620b57cec5SDimitry Andric     printAnnotation(O, Annot);
2630b57cec5SDimitry Andric     return;
2640b57cec5SDimitry Andric   }
2650b57cec5SDimitry Andric 
2660b57cec5SDimitry Andric   // Symbolic operands for MOVZ, MOVN and MOVK already imply a shift
2670b57cec5SDimitry Andric   // (e.g. :gottprel_g1: is always going to be "lsl #16") so it should not be
2680b57cec5SDimitry Andric   // printed.
2690b57cec5SDimitry Andric   if ((Opcode == AArch64::MOVZXi || Opcode == AArch64::MOVZWi ||
2700b57cec5SDimitry Andric        Opcode == AArch64::MOVNXi || Opcode == AArch64::MOVNWi) &&
2710b57cec5SDimitry Andric       MI->getOperand(1).isExpr()) {
2720b57cec5SDimitry Andric     if (Opcode == AArch64::MOVZXi || Opcode == AArch64::MOVZWi)
2730b57cec5SDimitry Andric       O << "\tmovz\t";
2740b57cec5SDimitry Andric     else
2750b57cec5SDimitry Andric       O << "\tmovn\t";
2760b57cec5SDimitry Andric 
277bdd1243dSDimitry Andric     printRegName(O, MI->getOperand(0).getReg());
2785f757f3fSDimitry Andric     O << ", ";
2795f757f3fSDimitry Andric     {
2805f757f3fSDimitry Andric       WithMarkup M = markup(O, Markup::Immediate);
2815f757f3fSDimitry Andric       O << "#";
2820b57cec5SDimitry Andric       MI->getOperand(1).getExpr()->print(O, &MAI);
2835f757f3fSDimitry Andric     }
2840b57cec5SDimitry Andric     return;
2850b57cec5SDimitry Andric   }
2860b57cec5SDimitry Andric 
2870b57cec5SDimitry Andric   if ((Opcode == AArch64::MOVKXi || Opcode == AArch64::MOVKWi) &&
2880b57cec5SDimitry Andric       MI->getOperand(2).isExpr()) {
289bdd1243dSDimitry Andric     O << "\tmovk\t";
290bdd1243dSDimitry Andric     printRegName(O, MI->getOperand(0).getReg());
2915f757f3fSDimitry Andric     O << ", ";
2925f757f3fSDimitry Andric     {
2935f757f3fSDimitry Andric       WithMarkup M = markup(O, Markup::Immediate);
2945f757f3fSDimitry Andric       O << "#";
2950b57cec5SDimitry Andric       MI->getOperand(2).getExpr()->print(O, &MAI);
2965f757f3fSDimitry Andric     }
2970b57cec5SDimitry Andric     return;
2980b57cec5SDimitry Andric   }
2990b57cec5SDimitry Andric 
30006c3fb27SDimitry Andric   auto PrintMovImm = [&](uint64_t Value, int RegWidth) {
30106c3fb27SDimitry Andric     int64_t SExtVal = SignExtend64(Value, RegWidth);
30206c3fb27SDimitry Andric     O << "\tmov\t";
30306c3fb27SDimitry Andric     printRegName(O, MI->getOperand(0).getReg());
3045f757f3fSDimitry Andric     O << ", ";
3055f757f3fSDimitry Andric     markup(O, Markup::Immediate) << "#" << formatImm(SExtVal);
30606c3fb27SDimitry Andric     if (CommentStream) {
30706c3fb27SDimitry Andric       // Do the opposite to that used for instruction operands.
30806c3fb27SDimitry Andric       if (getPrintImmHex())
30906c3fb27SDimitry Andric         *CommentStream << '=' << formatDec(SExtVal) << '\n';
31006c3fb27SDimitry Andric       else {
31106c3fb27SDimitry Andric         uint64_t Mask = maskTrailingOnes<uint64_t>(RegWidth);
31206c3fb27SDimitry Andric         *CommentStream << '=' << formatHex(SExtVal & Mask) << '\n';
31306c3fb27SDimitry Andric       }
31406c3fb27SDimitry Andric     }
31506c3fb27SDimitry Andric   };
31606c3fb27SDimitry Andric 
3170b57cec5SDimitry Andric   // MOVZ, MOVN and "ORR wzr, #imm" instructions are aliases for MOV, but their
3180b57cec5SDimitry Andric   // domains overlap so they need to be prioritized. The chain is "MOVZ lsl #0 >
3190b57cec5SDimitry Andric   // MOVZ lsl #N > MOVN lsl #0 > MOVN lsl #N > ORR". The highest instruction
3200b57cec5SDimitry Andric   // that can represent the move is the MOV alias, and the rest get printed
3210b57cec5SDimitry Andric   // normally.
3220b57cec5SDimitry Andric   if ((Opcode == AArch64::MOVZXi || Opcode == AArch64::MOVZWi) &&
3230b57cec5SDimitry Andric       MI->getOperand(1).isImm() && MI->getOperand(2).isImm()) {
3240b57cec5SDimitry Andric     int RegWidth = Opcode == AArch64::MOVZXi ? 64 : 32;
3250b57cec5SDimitry Andric     int Shift = MI->getOperand(2).getImm();
3260b57cec5SDimitry Andric     uint64_t Value = (uint64_t)MI->getOperand(1).getImm() << Shift;
3270b57cec5SDimitry Andric 
3280b57cec5SDimitry Andric     if (AArch64_AM::isMOVZMovAlias(Value, Shift,
3290b57cec5SDimitry Andric                                    Opcode == AArch64::MOVZXi ? 64 : 32)) {
33006c3fb27SDimitry Andric       PrintMovImm(Value, RegWidth);
3310b57cec5SDimitry Andric       return;
3320b57cec5SDimitry Andric     }
3330b57cec5SDimitry Andric   }
3340b57cec5SDimitry Andric 
3350b57cec5SDimitry Andric   if ((Opcode == AArch64::MOVNXi || Opcode == AArch64::MOVNWi) &&
3360b57cec5SDimitry Andric       MI->getOperand(1).isImm() && MI->getOperand(2).isImm()) {
3370b57cec5SDimitry Andric     int RegWidth = Opcode == AArch64::MOVNXi ? 64 : 32;
3380b57cec5SDimitry Andric     int Shift = MI->getOperand(2).getImm();
3390b57cec5SDimitry Andric     uint64_t Value = ~((uint64_t)MI->getOperand(1).getImm() << Shift);
3400b57cec5SDimitry Andric     if (RegWidth == 32)
3410b57cec5SDimitry Andric       Value = Value & 0xffffffff;
3420b57cec5SDimitry Andric 
3430b57cec5SDimitry Andric     if (AArch64_AM::isMOVNMovAlias(Value, Shift, RegWidth)) {
34406c3fb27SDimitry Andric       PrintMovImm(Value, RegWidth);
3450b57cec5SDimitry Andric       return;
3460b57cec5SDimitry Andric     }
3470b57cec5SDimitry Andric   }
3480b57cec5SDimitry Andric 
3490b57cec5SDimitry Andric   if ((Opcode == AArch64::ORRXri || Opcode == AArch64::ORRWri) &&
3500b57cec5SDimitry Andric       (MI->getOperand(1).getReg() == AArch64::XZR ||
3510b57cec5SDimitry Andric        MI->getOperand(1).getReg() == AArch64::WZR) &&
3520b57cec5SDimitry Andric       MI->getOperand(2).isImm()) {
3530b57cec5SDimitry Andric     int RegWidth = Opcode == AArch64::ORRXri ? 64 : 32;
3540b57cec5SDimitry Andric     uint64_t Value = AArch64_AM::decodeLogicalImmediate(
3550b57cec5SDimitry Andric         MI->getOperand(2).getImm(), RegWidth);
3560b57cec5SDimitry Andric     if (!AArch64_AM::isAnyMOVWMovAlias(Value, RegWidth)) {
35706c3fb27SDimitry Andric       PrintMovImm(Value, RegWidth);
3580b57cec5SDimitry Andric       return;
3590b57cec5SDimitry Andric     }
3600b57cec5SDimitry Andric   }
3610b57cec5SDimitry Andric 
362480093f4SDimitry Andric   if (Opcode == AArch64::SPACE) {
3635ffd83dbSDimitry Andric     O << '\t' << MAI.getCommentString() << " SPACE "
3645ffd83dbSDimitry Andric       << MI->getOperand(1).getImm();
365480093f4SDimitry Andric     printAnnotation(O, Annot);
366480093f4SDimitry Andric     return;
367480093f4SDimitry Andric   }
368480093f4SDimitry Andric 
3690b57cec5SDimitry Andric   // Instruction TSB is specified as a one operand instruction, but 'csync' is
3700b57cec5SDimitry Andric   // not encoded, so for printing it is treated as a special case here:
3710b57cec5SDimitry Andric   if (Opcode == AArch64::TSB) {
3720b57cec5SDimitry Andric     O << "\ttsb\tcsync";
3730b57cec5SDimitry Andric     return;
3740b57cec5SDimitry Andric   }
3750b57cec5SDimitry Andric 
376fe6060f1SDimitry Andric   if (!PrintAliases || !printAliasInstr(MI, Address, STI, O))
377480093f4SDimitry Andric     printInstruction(MI, Address, STI, O);
3780b57cec5SDimitry Andric 
3790b57cec5SDimitry Andric   printAnnotation(O, Annot);
3800b57cec5SDimitry Andric 
3810b57cec5SDimitry Andric   if (atomicBarrierDroppedOnZero(Opcode) &&
3820b57cec5SDimitry Andric       (MI->getOperand(0).getReg() == AArch64::XZR ||
3830b57cec5SDimitry Andric        MI->getOperand(0).getReg() == AArch64::WZR)) {
3840b57cec5SDimitry Andric     printAnnotation(O, "acquire semantics dropped since destination is zero");
3850b57cec5SDimitry Andric   }
3860b57cec5SDimitry Andric }
3870b57cec5SDimitry Andric 
isTblTbxInstruction(unsigned Opcode,StringRef & Layout,bool & IsTbx)3880b57cec5SDimitry Andric static bool isTblTbxInstruction(unsigned Opcode, StringRef &Layout,
3890b57cec5SDimitry Andric                                 bool &IsTbx) {
3900b57cec5SDimitry Andric   switch (Opcode) {
3910b57cec5SDimitry Andric   case AArch64::TBXv8i8One:
3920b57cec5SDimitry Andric   case AArch64::TBXv8i8Two:
3930b57cec5SDimitry Andric   case AArch64::TBXv8i8Three:
3940b57cec5SDimitry Andric   case AArch64::TBXv8i8Four:
3950b57cec5SDimitry Andric     IsTbx = true;
3960b57cec5SDimitry Andric     Layout = ".8b";
3970b57cec5SDimitry Andric     return true;
3980b57cec5SDimitry Andric   case AArch64::TBLv8i8One:
3990b57cec5SDimitry Andric   case AArch64::TBLv8i8Two:
4000b57cec5SDimitry Andric   case AArch64::TBLv8i8Three:
4010b57cec5SDimitry Andric   case AArch64::TBLv8i8Four:
4020b57cec5SDimitry Andric     IsTbx = false;
4030b57cec5SDimitry Andric     Layout = ".8b";
4040b57cec5SDimitry Andric     return true;
4050b57cec5SDimitry Andric   case AArch64::TBXv16i8One:
4060b57cec5SDimitry Andric   case AArch64::TBXv16i8Two:
4070b57cec5SDimitry Andric   case AArch64::TBXv16i8Three:
4080b57cec5SDimitry Andric   case AArch64::TBXv16i8Four:
4090b57cec5SDimitry Andric     IsTbx = true;
4100b57cec5SDimitry Andric     Layout = ".16b";
4110b57cec5SDimitry Andric     return true;
4120b57cec5SDimitry Andric   case AArch64::TBLv16i8One:
4130b57cec5SDimitry Andric   case AArch64::TBLv16i8Two:
4140b57cec5SDimitry Andric   case AArch64::TBLv16i8Three:
4150b57cec5SDimitry Andric   case AArch64::TBLv16i8Four:
4160b57cec5SDimitry Andric     IsTbx = false;
4170b57cec5SDimitry Andric     Layout = ".16b";
4180b57cec5SDimitry Andric     return true;
4190b57cec5SDimitry Andric   default:
4200b57cec5SDimitry Andric     return false;
4210b57cec5SDimitry Andric   }
4220b57cec5SDimitry Andric }
4230b57cec5SDimitry Andric 
4240b57cec5SDimitry Andric struct LdStNInstrDesc {
4250b57cec5SDimitry Andric   unsigned Opcode;
4260b57cec5SDimitry Andric   const char *Mnemonic;
4270b57cec5SDimitry Andric   const char *Layout;
4280b57cec5SDimitry Andric   int ListOperand;
4290b57cec5SDimitry Andric   bool HasLane;
4300b57cec5SDimitry Andric   int NaturalOffset;
4310b57cec5SDimitry Andric };
4320b57cec5SDimitry Andric 
4330b57cec5SDimitry Andric static const LdStNInstrDesc LdStNInstInfo[] = {
4340b57cec5SDimitry Andric   { AArch64::LD1i8,             "ld1",  ".b",     1, true,  0  },
4350b57cec5SDimitry Andric   { AArch64::LD1i16,            "ld1",  ".h",     1, true,  0  },
4360b57cec5SDimitry Andric   { AArch64::LD1i32,            "ld1",  ".s",     1, true,  0  },
4370b57cec5SDimitry Andric   { AArch64::LD1i64,            "ld1",  ".d",     1, true,  0  },
4380b57cec5SDimitry Andric   { AArch64::LD1i8_POST,        "ld1",  ".b",     2, true,  1  },
4390b57cec5SDimitry Andric   { AArch64::LD1i16_POST,       "ld1",  ".h",     2, true,  2  },
4400b57cec5SDimitry Andric   { AArch64::LD1i32_POST,       "ld1",  ".s",     2, true,  4  },
4410b57cec5SDimitry Andric   { AArch64::LD1i64_POST,       "ld1",  ".d",     2, true,  8  },
4420b57cec5SDimitry Andric   { AArch64::LD1Rv16b,          "ld1r", ".16b",   0, false, 0  },
4430b57cec5SDimitry Andric   { AArch64::LD1Rv8h,           "ld1r", ".8h",    0, false, 0  },
4440b57cec5SDimitry Andric   { AArch64::LD1Rv4s,           "ld1r", ".4s",    0, false, 0  },
4450b57cec5SDimitry Andric   { AArch64::LD1Rv2d,           "ld1r", ".2d",    0, false, 0  },
4460b57cec5SDimitry Andric   { AArch64::LD1Rv8b,           "ld1r", ".8b",    0, false, 0  },
4470b57cec5SDimitry Andric   { AArch64::LD1Rv4h,           "ld1r", ".4h",    0, false, 0  },
4480b57cec5SDimitry Andric   { AArch64::LD1Rv2s,           "ld1r", ".2s",    0, false, 0  },
4490b57cec5SDimitry Andric   { AArch64::LD1Rv1d,           "ld1r", ".1d",    0, false, 0  },
4500b57cec5SDimitry Andric   { AArch64::LD1Rv16b_POST,     "ld1r", ".16b",   1, false, 1  },
4510b57cec5SDimitry Andric   { AArch64::LD1Rv8h_POST,      "ld1r", ".8h",    1, false, 2  },
4520b57cec5SDimitry Andric   { AArch64::LD1Rv4s_POST,      "ld1r", ".4s",    1, false, 4  },
4530b57cec5SDimitry Andric   { AArch64::LD1Rv2d_POST,      "ld1r", ".2d",    1, false, 8  },
4540b57cec5SDimitry Andric   { AArch64::LD1Rv8b_POST,      "ld1r", ".8b",    1, false, 1  },
4550b57cec5SDimitry Andric   { AArch64::LD1Rv4h_POST,      "ld1r", ".4h",    1, false, 2  },
4560b57cec5SDimitry Andric   { AArch64::LD1Rv2s_POST,      "ld1r", ".2s",    1, false, 4  },
4570b57cec5SDimitry Andric   { AArch64::LD1Rv1d_POST,      "ld1r", ".1d",    1, false, 8  },
4580b57cec5SDimitry Andric   { AArch64::LD1Onev16b,        "ld1",  ".16b",   0, false, 0  },
4590b57cec5SDimitry Andric   { AArch64::LD1Onev8h,         "ld1",  ".8h",    0, false, 0  },
4600b57cec5SDimitry Andric   { AArch64::LD1Onev4s,         "ld1",  ".4s",    0, false, 0  },
4610b57cec5SDimitry Andric   { AArch64::LD1Onev2d,         "ld1",  ".2d",    0, false, 0  },
4620b57cec5SDimitry Andric   { AArch64::LD1Onev8b,         "ld1",  ".8b",    0, false, 0  },
4630b57cec5SDimitry Andric   { AArch64::LD1Onev4h,         "ld1",  ".4h",    0, false, 0  },
4640b57cec5SDimitry Andric   { AArch64::LD1Onev2s,         "ld1",  ".2s",    0, false, 0  },
4650b57cec5SDimitry Andric   { AArch64::LD1Onev1d,         "ld1",  ".1d",    0, false, 0  },
4660b57cec5SDimitry Andric   { AArch64::LD1Onev16b_POST,   "ld1",  ".16b",   1, false, 16 },
4670b57cec5SDimitry Andric   { AArch64::LD1Onev8h_POST,    "ld1",  ".8h",    1, false, 16 },
4680b57cec5SDimitry Andric   { AArch64::LD1Onev4s_POST,    "ld1",  ".4s",    1, false, 16 },
4690b57cec5SDimitry Andric   { AArch64::LD1Onev2d_POST,    "ld1",  ".2d",    1, false, 16 },
4700b57cec5SDimitry Andric   { AArch64::LD1Onev8b_POST,    "ld1",  ".8b",    1, false, 8  },
4710b57cec5SDimitry Andric   { AArch64::LD1Onev4h_POST,    "ld1",  ".4h",    1, false, 8  },
4720b57cec5SDimitry Andric   { AArch64::LD1Onev2s_POST,    "ld1",  ".2s",    1, false, 8  },
4730b57cec5SDimitry Andric   { AArch64::LD1Onev1d_POST,    "ld1",  ".1d",    1, false, 8  },
4740b57cec5SDimitry Andric   { AArch64::LD1Twov16b,        "ld1",  ".16b",   0, false, 0  },
4750b57cec5SDimitry Andric   { AArch64::LD1Twov8h,         "ld1",  ".8h",    0, false, 0  },
4760b57cec5SDimitry Andric   { AArch64::LD1Twov4s,         "ld1",  ".4s",    0, false, 0  },
4770b57cec5SDimitry Andric   { AArch64::LD1Twov2d,         "ld1",  ".2d",    0, false, 0  },
4780b57cec5SDimitry Andric   { AArch64::LD1Twov8b,         "ld1",  ".8b",    0, false, 0  },
4790b57cec5SDimitry Andric   { AArch64::LD1Twov4h,         "ld1",  ".4h",    0, false, 0  },
4800b57cec5SDimitry Andric   { AArch64::LD1Twov2s,         "ld1",  ".2s",    0, false, 0  },
4810b57cec5SDimitry Andric   { AArch64::LD1Twov1d,         "ld1",  ".1d",    0, false, 0  },
4820b57cec5SDimitry Andric   { AArch64::LD1Twov16b_POST,   "ld1",  ".16b",   1, false, 32 },
4830b57cec5SDimitry Andric   { AArch64::LD1Twov8h_POST,    "ld1",  ".8h",    1, false, 32 },
4840b57cec5SDimitry Andric   { AArch64::LD1Twov4s_POST,    "ld1",  ".4s",    1, false, 32 },
4850b57cec5SDimitry Andric   { AArch64::LD1Twov2d_POST,    "ld1",  ".2d",    1, false, 32 },
4860b57cec5SDimitry Andric   { AArch64::LD1Twov8b_POST,    "ld1",  ".8b",    1, false, 16 },
4870b57cec5SDimitry Andric   { AArch64::LD1Twov4h_POST,    "ld1",  ".4h",    1, false, 16 },
4880b57cec5SDimitry Andric   { AArch64::LD1Twov2s_POST,    "ld1",  ".2s",    1, false, 16 },
4890b57cec5SDimitry Andric   { AArch64::LD1Twov1d_POST,    "ld1",  ".1d",    1, false, 16 },
4900b57cec5SDimitry Andric   { AArch64::LD1Threev16b,      "ld1",  ".16b",   0, false, 0  },
4910b57cec5SDimitry Andric   { AArch64::LD1Threev8h,       "ld1",  ".8h",    0, false, 0  },
4920b57cec5SDimitry Andric   { AArch64::LD1Threev4s,       "ld1",  ".4s",    0, false, 0  },
4930b57cec5SDimitry Andric   { AArch64::LD1Threev2d,       "ld1",  ".2d",    0, false, 0  },
4940b57cec5SDimitry Andric   { AArch64::LD1Threev8b,       "ld1",  ".8b",    0, false, 0  },
4950b57cec5SDimitry Andric   { AArch64::LD1Threev4h,       "ld1",  ".4h",    0, false, 0  },
4960b57cec5SDimitry Andric   { AArch64::LD1Threev2s,       "ld1",  ".2s",    0, false, 0  },
4970b57cec5SDimitry Andric   { AArch64::LD1Threev1d,       "ld1",  ".1d",    0, false, 0  },
4980b57cec5SDimitry Andric   { AArch64::LD1Threev16b_POST, "ld1",  ".16b",   1, false, 48 },
4990b57cec5SDimitry Andric   { AArch64::LD1Threev8h_POST,  "ld1",  ".8h",    1, false, 48 },
5000b57cec5SDimitry Andric   { AArch64::LD1Threev4s_POST,  "ld1",  ".4s",    1, false, 48 },
5010b57cec5SDimitry Andric   { AArch64::LD1Threev2d_POST,  "ld1",  ".2d",    1, false, 48 },
5020b57cec5SDimitry Andric   { AArch64::LD1Threev8b_POST,  "ld1",  ".8b",    1, false, 24 },
5030b57cec5SDimitry Andric   { AArch64::LD1Threev4h_POST,  "ld1",  ".4h",    1, false, 24 },
5040b57cec5SDimitry Andric   { AArch64::LD1Threev2s_POST,  "ld1",  ".2s",    1, false, 24 },
5050b57cec5SDimitry Andric   { AArch64::LD1Threev1d_POST,  "ld1",  ".1d",    1, false, 24 },
5060b57cec5SDimitry Andric   { AArch64::LD1Fourv16b,       "ld1",  ".16b",   0, false, 0  },
5070b57cec5SDimitry Andric   { AArch64::LD1Fourv8h,        "ld1",  ".8h",    0, false, 0  },
5080b57cec5SDimitry Andric   { AArch64::LD1Fourv4s,        "ld1",  ".4s",    0, false, 0  },
5090b57cec5SDimitry Andric   { AArch64::LD1Fourv2d,        "ld1",  ".2d",    0, false, 0  },
5100b57cec5SDimitry Andric   { AArch64::LD1Fourv8b,        "ld1",  ".8b",    0, false, 0  },
5110b57cec5SDimitry Andric   { AArch64::LD1Fourv4h,        "ld1",  ".4h",    0, false, 0  },
5120b57cec5SDimitry Andric   { AArch64::LD1Fourv2s,        "ld1",  ".2s",    0, false, 0  },
5130b57cec5SDimitry Andric   { AArch64::LD1Fourv1d,        "ld1",  ".1d",    0, false, 0  },
5140b57cec5SDimitry Andric   { AArch64::LD1Fourv16b_POST,  "ld1",  ".16b",   1, false, 64 },
5150b57cec5SDimitry Andric   { AArch64::LD1Fourv8h_POST,   "ld1",  ".8h",    1, false, 64 },
5160b57cec5SDimitry Andric   { AArch64::LD1Fourv4s_POST,   "ld1",  ".4s",    1, false, 64 },
5170b57cec5SDimitry Andric   { AArch64::LD1Fourv2d_POST,   "ld1",  ".2d",    1, false, 64 },
5180b57cec5SDimitry Andric   { AArch64::LD1Fourv8b_POST,   "ld1",  ".8b",    1, false, 32 },
5190b57cec5SDimitry Andric   { AArch64::LD1Fourv4h_POST,   "ld1",  ".4h",    1, false, 32 },
5200b57cec5SDimitry Andric   { AArch64::LD1Fourv2s_POST,   "ld1",  ".2s",    1, false, 32 },
5210b57cec5SDimitry Andric   { AArch64::LD1Fourv1d_POST,   "ld1",  ".1d",    1, false, 32 },
5220b57cec5SDimitry Andric   { AArch64::LD2i8,             "ld2",  ".b",     1, true,  0  },
5230b57cec5SDimitry Andric   { AArch64::LD2i16,            "ld2",  ".h",     1, true,  0  },
5240b57cec5SDimitry Andric   { AArch64::LD2i32,            "ld2",  ".s",     1, true,  0  },
5250b57cec5SDimitry Andric   { AArch64::LD2i64,            "ld2",  ".d",     1, true,  0  },
5260b57cec5SDimitry Andric   { AArch64::LD2i8_POST,        "ld2",  ".b",     2, true,  2  },
5270b57cec5SDimitry Andric   { AArch64::LD2i16_POST,       "ld2",  ".h",     2, true,  4  },
5280b57cec5SDimitry Andric   { AArch64::LD2i32_POST,       "ld2",  ".s",     2, true,  8  },
5290b57cec5SDimitry Andric   { AArch64::LD2i64_POST,       "ld2",  ".d",     2, true,  16  },
5300b57cec5SDimitry Andric   { AArch64::LD2Rv16b,          "ld2r", ".16b",   0, false, 0  },
5310b57cec5SDimitry Andric   { AArch64::LD2Rv8h,           "ld2r", ".8h",    0, false, 0  },
5320b57cec5SDimitry Andric   { AArch64::LD2Rv4s,           "ld2r", ".4s",    0, false, 0  },
5330b57cec5SDimitry Andric   { AArch64::LD2Rv2d,           "ld2r", ".2d",    0, false, 0  },
5340b57cec5SDimitry Andric   { AArch64::LD2Rv8b,           "ld2r", ".8b",    0, false, 0  },
5350b57cec5SDimitry Andric   { AArch64::LD2Rv4h,           "ld2r", ".4h",    0, false, 0  },
5360b57cec5SDimitry Andric   { AArch64::LD2Rv2s,           "ld2r", ".2s",    0, false, 0  },
5370b57cec5SDimitry Andric   { AArch64::LD2Rv1d,           "ld2r", ".1d",    0, false, 0  },
5380b57cec5SDimitry Andric   { AArch64::LD2Rv16b_POST,     "ld2r", ".16b",   1, false, 2  },
5390b57cec5SDimitry Andric   { AArch64::LD2Rv8h_POST,      "ld2r", ".8h",    1, false, 4  },
5400b57cec5SDimitry Andric   { AArch64::LD2Rv4s_POST,      "ld2r", ".4s",    1, false, 8  },
5410b57cec5SDimitry Andric   { AArch64::LD2Rv2d_POST,      "ld2r", ".2d",    1, false, 16 },
5420b57cec5SDimitry Andric   { AArch64::LD2Rv8b_POST,      "ld2r", ".8b",    1, false, 2  },
5430b57cec5SDimitry Andric   { AArch64::LD2Rv4h_POST,      "ld2r", ".4h",    1, false, 4  },
5440b57cec5SDimitry Andric   { AArch64::LD2Rv2s_POST,      "ld2r", ".2s",    1, false, 8  },
5450b57cec5SDimitry Andric   { AArch64::LD2Rv1d_POST,      "ld2r", ".1d",    1, false, 16 },
5460b57cec5SDimitry Andric   { AArch64::LD2Twov16b,        "ld2",  ".16b",   0, false, 0  },
5470b57cec5SDimitry Andric   { AArch64::LD2Twov8h,         "ld2",  ".8h",    0, false, 0  },
5480b57cec5SDimitry Andric   { AArch64::LD2Twov4s,         "ld2",  ".4s",    0, false, 0  },
5490b57cec5SDimitry Andric   { AArch64::LD2Twov2d,         "ld2",  ".2d",    0, false, 0  },
5500b57cec5SDimitry Andric   { AArch64::LD2Twov8b,         "ld2",  ".8b",    0, false, 0  },
5510b57cec5SDimitry Andric   { AArch64::LD2Twov4h,         "ld2",  ".4h",    0, false, 0  },
5520b57cec5SDimitry Andric   { AArch64::LD2Twov2s,         "ld2",  ".2s",    0, false, 0  },
5530b57cec5SDimitry Andric   { AArch64::LD2Twov16b_POST,   "ld2",  ".16b",   1, false, 32 },
5540b57cec5SDimitry Andric   { AArch64::LD2Twov8h_POST,    "ld2",  ".8h",    1, false, 32 },
5550b57cec5SDimitry Andric   { AArch64::LD2Twov4s_POST,    "ld2",  ".4s",    1, false, 32 },
5560b57cec5SDimitry Andric   { AArch64::LD2Twov2d_POST,    "ld2",  ".2d",    1, false, 32 },
5570b57cec5SDimitry Andric   { AArch64::LD2Twov8b_POST,    "ld2",  ".8b",    1, false, 16 },
5580b57cec5SDimitry Andric   { AArch64::LD2Twov4h_POST,    "ld2",  ".4h",    1, false, 16 },
5590b57cec5SDimitry Andric   { AArch64::LD2Twov2s_POST,    "ld2",  ".2s",    1, false, 16 },
5600b57cec5SDimitry Andric   { AArch64::LD3i8,             "ld3",  ".b",     1, true,  0  },
5610b57cec5SDimitry Andric   { AArch64::LD3i16,            "ld3",  ".h",     1, true,  0  },
5620b57cec5SDimitry Andric   { AArch64::LD3i32,            "ld3",  ".s",     1, true,  0  },
5630b57cec5SDimitry Andric   { AArch64::LD3i64,            "ld3",  ".d",     1, true,  0  },
5640b57cec5SDimitry Andric   { AArch64::LD3i8_POST,        "ld3",  ".b",     2, true,  3  },
5650b57cec5SDimitry Andric   { AArch64::LD3i16_POST,       "ld3",  ".h",     2, true,  6  },
5660b57cec5SDimitry Andric   { AArch64::LD3i32_POST,       "ld3",  ".s",     2, true,  12 },
5670b57cec5SDimitry Andric   { AArch64::LD3i64_POST,       "ld3",  ".d",     2, true,  24 },
5680b57cec5SDimitry Andric   { AArch64::LD3Rv16b,          "ld3r", ".16b",   0, false, 0  },
5690b57cec5SDimitry Andric   { AArch64::LD3Rv8h,           "ld3r", ".8h",    0, false, 0  },
5700b57cec5SDimitry Andric   { AArch64::LD3Rv4s,           "ld3r", ".4s",    0, false, 0  },
5710b57cec5SDimitry Andric   { AArch64::LD3Rv2d,           "ld3r", ".2d",    0, false, 0  },
5720b57cec5SDimitry Andric   { AArch64::LD3Rv8b,           "ld3r", ".8b",    0, false, 0  },
5730b57cec5SDimitry Andric   { AArch64::LD3Rv4h,           "ld3r", ".4h",    0, false, 0  },
5740b57cec5SDimitry Andric   { AArch64::LD3Rv2s,           "ld3r", ".2s",    0, false, 0  },
5750b57cec5SDimitry Andric   { AArch64::LD3Rv1d,           "ld3r", ".1d",    0, false, 0  },
5760b57cec5SDimitry Andric   { AArch64::LD3Rv16b_POST,     "ld3r", ".16b",   1, false, 3  },
5770b57cec5SDimitry Andric   { AArch64::LD3Rv8h_POST,      "ld3r", ".8h",    1, false, 6  },
5780b57cec5SDimitry Andric   { AArch64::LD3Rv4s_POST,      "ld3r", ".4s",    1, false, 12 },
5790b57cec5SDimitry Andric   { AArch64::LD3Rv2d_POST,      "ld3r", ".2d",    1, false, 24 },
5800b57cec5SDimitry Andric   { AArch64::LD3Rv8b_POST,      "ld3r", ".8b",    1, false, 3  },
5810b57cec5SDimitry Andric   { AArch64::LD3Rv4h_POST,      "ld3r", ".4h",    1, false, 6  },
5820b57cec5SDimitry Andric   { AArch64::LD3Rv2s_POST,      "ld3r", ".2s",    1, false, 12 },
5830b57cec5SDimitry Andric   { AArch64::LD3Rv1d_POST,      "ld3r", ".1d",    1, false, 24 },
5840b57cec5SDimitry Andric   { AArch64::LD3Threev16b,      "ld3",  ".16b",   0, false, 0  },
5850b57cec5SDimitry Andric   { AArch64::LD3Threev8h,       "ld3",  ".8h",    0, false, 0  },
5860b57cec5SDimitry Andric   { AArch64::LD3Threev4s,       "ld3",  ".4s",    0, false, 0  },
5870b57cec5SDimitry Andric   { AArch64::LD3Threev2d,       "ld3",  ".2d",    0, false, 0  },
5880b57cec5SDimitry Andric   { AArch64::LD3Threev8b,       "ld3",  ".8b",    0, false, 0  },
5890b57cec5SDimitry Andric   { AArch64::LD3Threev4h,       "ld3",  ".4h",    0, false, 0  },
5900b57cec5SDimitry Andric   { AArch64::LD3Threev2s,       "ld3",  ".2s",    0, false, 0  },
5910b57cec5SDimitry Andric   { AArch64::LD3Threev16b_POST, "ld3",  ".16b",   1, false, 48 },
5920b57cec5SDimitry Andric   { AArch64::LD3Threev8h_POST,  "ld3",  ".8h",    1, false, 48 },
5930b57cec5SDimitry Andric   { AArch64::LD3Threev4s_POST,  "ld3",  ".4s",    1, false, 48 },
5940b57cec5SDimitry Andric   { AArch64::LD3Threev2d_POST,  "ld3",  ".2d",    1, false, 48 },
5950b57cec5SDimitry Andric   { AArch64::LD3Threev8b_POST,  "ld3",  ".8b",    1, false, 24 },
5960b57cec5SDimitry Andric   { AArch64::LD3Threev4h_POST,  "ld3",  ".4h",    1, false, 24 },
5970b57cec5SDimitry Andric   { AArch64::LD3Threev2s_POST,  "ld3",  ".2s",    1, false, 24 },
5980b57cec5SDimitry Andric   { AArch64::LD4i8,             "ld4",  ".b",     1, true,  0  },
5990b57cec5SDimitry Andric   { AArch64::LD4i16,            "ld4",  ".h",     1, true,  0  },
6000b57cec5SDimitry Andric   { AArch64::LD4i32,            "ld4",  ".s",     1, true,  0  },
6010b57cec5SDimitry Andric   { AArch64::LD4i64,            "ld4",  ".d",     1, true,  0  },
6020b57cec5SDimitry Andric   { AArch64::LD4i8_POST,        "ld4",  ".b",     2, true,  4  },
6030b57cec5SDimitry Andric   { AArch64::LD4i16_POST,       "ld4",  ".h",     2, true,  8  },
6040b57cec5SDimitry Andric   { AArch64::LD4i32_POST,       "ld4",  ".s",     2, true,  16 },
6050b57cec5SDimitry Andric   { AArch64::LD4i64_POST,       "ld4",  ".d",     2, true,  32 },
6060b57cec5SDimitry Andric   { AArch64::LD4Rv16b,          "ld4r", ".16b",   0, false, 0  },
6070b57cec5SDimitry Andric   { AArch64::LD4Rv8h,           "ld4r", ".8h",    0, false, 0  },
6080b57cec5SDimitry Andric   { AArch64::LD4Rv4s,           "ld4r", ".4s",    0, false, 0  },
6090b57cec5SDimitry Andric   { AArch64::LD4Rv2d,           "ld4r", ".2d",    0, false, 0  },
6100b57cec5SDimitry Andric   { AArch64::LD4Rv8b,           "ld4r", ".8b",    0, false, 0  },
6110b57cec5SDimitry Andric   { AArch64::LD4Rv4h,           "ld4r", ".4h",    0, false, 0  },
6120b57cec5SDimitry Andric   { AArch64::LD4Rv2s,           "ld4r", ".2s",    0, false, 0  },
6130b57cec5SDimitry Andric   { AArch64::LD4Rv1d,           "ld4r", ".1d",    0, false, 0  },
6140b57cec5SDimitry Andric   { AArch64::LD4Rv16b_POST,     "ld4r", ".16b",   1, false, 4  },
6150b57cec5SDimitry Andric   { AArch64::LD4Rv8h_POST,      "ld4r", ".8h",    1, false, 8  },
6160b57cec5SDimitry Andric   { AArch64::LD4Rv4s_POST,      "ld4r", ".4s",    1, false, 16 },
6170b57cec5SDimitry Andric   { AArch64::LD4Rv2d_POST,      "ld4r", ".2d",    1, false, 32 },
6180b57cec5SDimitry Andric   { AArch64::LD4Rv8b_POST,      "ld4r", ".8b",    1, false, 4  },
6190b57cec5SDimitry Andric   { AArch64::LD4Rv4h_POST,      "ld4r", ".4h",    1, false, 8  },
6200b57cec5SDimitry Andric   { AArch64::LD4Rv2s_POST,      "ld4r", ".2s",    1, false, 16 },
6210b57cec5SDimitry Andric   { AArch64::LD4Rv1d_POST,      "ld4r", ".1d",    1, false, 32 },
6220b57cec5SDimitry Andric   { AArch64::LD4Fourv16b,       "ld4",  ".16b",   0, false, 0  },
6230b57cec5SDimitry Andric   { AArch64::LD4Fourv8h,        "ld4",  ".8h",    0, false, 0  },
6240b57cec5SDimitry Andric   { AArch64::LD4Fourv4s,        "ld4",  ".4s",    0, false, 0  },
6250b57cec5SDimitry Andric   { AArch64::LD4Fourv2d,        "ld4",  ".2d",    0, false, 0  },
6260b57cec5SDimitry Andric   { AArch64::LD4Fourv8b,        "ld4",  ".8b",    0, false, 0  },
6270b57cec5SDimitry Andric   { AArch64::LD4Fourv4h,        "ld4",  ".4h",    0, false, 0  },
6280b57cec5SDimitry Andric   { AArch64::LD4Fourv2s,        "ld4",  ".2s",    0, false, 0  },
6290b57cec5SDimitry Andric   { AArch64::LD4Fourv16b_POST,  "ld4",  ".16b",   1, false, 64 },
6300b57cec5SDimitry Andric   { AArch64::LD4Fourv8h_POST,   "ld4",  ".8h",    1, false, 64 },
6310b57cec5SDimitry Andric   { AArch64::LD4Fourv4s_POST,   "ld4",  ".4s",    1, false, 64 },
6320b57cec5SDimitry Andric   { AArch64::LD4Fourv2d_POST,   "ld4",  ".2d",    1, false, 64 },
6330b57cec5SDimitry Andric   { AArch64::LD4Fourv8b_POST,   "ld4",  ".8b",    1, false, 32 },
6340b57cec5SDimitry Andric   { AArch64::LD4Fourv4h_POST,   "ld4",  ".4h",    1, false, 32 },
6350b57cec5SDimitry Andric   { AArch64::LD4Fourv2s_POST,   "ld4",  ".2s",    1, false, 32 },
6360b57cec5SDimitry Andric   { AArch64::ST1i8,             "st1",  ".b",     0, true,  0  },
6370b57cec5SDimitry Andric   { AArch64::ST1i16,            "st1",  ".h",     0, true,  0  },
6380b57cec5SDimitry Andric   { AArch64::ST1i32,            "st1",  ".s",     0, true,  0  },
6390b57cec5SDimitry Andric   { AArch64::ST1i64,            "st1",  ".d",     0, true,  0  },
6400b57cec5SDimitry Andric   { AArch64::ST1i8_POST,        "st1",  ".b",     1, true,  1  },
6410b57cec5SDimitry Andric   { AArch64::ST1i16_POST,       "st1",  ".h",     1, true,  2  },
6420b57cec5SDimitry Andric   { AArch64::ST1i32_POST,       "st1",  ".s",     1, true,  4  },
6430b57cec5SDimitry Andric   { AArch64::ST1i64_POST,       "st1",  ".d",     1, true,  8  },
6440b57cec5SDimitry Andric   { AArch64::ST1Onev16b,        "st1",  ".16b",   0, false, 0  },
6450b57cec5SDimitry Andric   { AArch64::ST1Onev8h,         "st1",  ".8h",    0, false, 0  },
6460b57cec5SDimitry Andric   { AArch64::ST1Onev4s,         "st1",  ".4s",    0, false, 0  },
6470b57cec5SDimitry Andric   { AArch64::ST1Onev2d,         "st1",  ".2d",    0, false, 0  },
6480b57cec5SDimitry Andric   { AArch64::ST1Onev8b,         "st1",  ".8b",    0, false, 0  },
6490b57cec5SDimitry Andric   { AArch64::ST1Onev4h,         "st1",  ".4h",    0, false, 0  },
6500b57cec5SDimitry Andric   { AArch64::ST1Onev2s,         "st1",  ".2s",    0, false, 0  },
6510b57cec5SDimitry Andric   { AArch64::ST1Onev1d,         "st1",  ".1d",    0, false, 0  },
6520b57cec5SDimitry Andric   { AArch64::ST1Onev16b_POST,   "st1",  ".16b",   1, false, 16 },
6530b57cec5SDimitry Andric   { AArch64::ST1Onev8h_POST,    "st1",  ".8h",    1, false, 16 },
6540b57cec5SDimitry Andric   { AArch64::ST1Onev4s_POST,    "st1",  ".4s",    1, false, 16 },
6550b57cec5SDimitry Andric   { AArch64::ST1Onev2d_POST,    "st1",  ".2d",    1, false, 16 },
6560b57cec5SDimitry Andric   { AArch64::ST1Onev8b_POST,    "st1",  ".8b",    1, false, 8  },
6570b57cec5SDimitry Andric   { AArch64::ST1Onev4h_POST,    "st1",  ".4h",    1, false, 8  },
6580b57cec5SDimitry Andric   { AArch64::ST1Onev2s_POST,    "st1",  ".2s",    1, false, 8  },
6590b57cec5SDimitry Andric   { AArch64::ST1Onev1d_POST,    "st1",  ".1d",    1, false, 8  },
6600b57cec5SDimitry Andric   { AArch64::ST1Twov16b,        "st1",  ".16b",   0, false, 0  },
6610b57cec5SDimitry Andric   { AArch64::ST1Twov8h,         "st1",  ".8h",    0, false, 0  },
6620b57cec5SDimitry Andric   { AArch64::ST1Twov4s,         "st1",  ".4s",    0, false, 0  },
6630b57cec5SDimitry Andric   { AArch64::ST1Twov2d,         "st1",  ".2d",    0, false, 0  },
6640b57cec5SDimitry Andric   { AArch64::ST1Twov8b,         "st1",  ".8b",    0, false, 0  },
6650b57cec5SDimitry Andric   { AArch64::ST1Twov4h,         "st1",  ".4h",    0, false, 0  },
6660b57cec5SDimitry Andric   { AArch64::ST1Twov2s,         "st1",  ".2s",    0, false, 0  },
6670b57cec5SDimitry Andric   { AArch64::ST1Twov1d,         "st1",  ".1d",    0, false, 0  },
6680b57cec5SDimitry Andric   { AArch64::ST1Twov16b_POST,   "st1",  ".16b",   1, false, 32 },
6690b57cec5SDimitry Andric   { AArch64::ST1Twov8h_POST,    "st1",  ".8h",    1, false, 32 },
6700b57cec5SDimitry Andric   { AArch64::ST1Twov4s_POST,    "st1",  ".4s",    1, false, 32 },
6710b57cec5SDimitry Andric   { AArch64::ST1Twov2d_POST,    "st1",  ".2d",    1, false, 32 },
6720b57cec5SDimitry Andric   { AArch64::ST1Twov8b_POST,    "st1",  ".8b",    1, false, 16 },
6730b57cec5SDimitry Andric   { AArch64::ST1Twov4h_POST,    "st1",  ".4h",    1, false, 16 },
6740b57cec5SDimitry Andric   { AArch64::ST1Twov2s_POST,    "st1",  ".2s",    1, false, 16 },
6750b57cec5SDimitry Andric   { AArch64::ST1Twov1d_POST,    "st1",  ".1d",    1, false, 16 },
6760b57cec5SDimitry Andric   { AArch64::ST1Threev16b,      "st1",  ".16b",   0, false, 0  },
6770b57cec5SDimitry Andric   { AArch64::ST1Threev8h,       "st1",  ".8h",    0, false, 0  },
6780b57cec5SDimitry Andric   { AArch64::ST1Threev4s,       "st1",  ".4s",    0, false, 0  },
6790b57cec5SDimitry Andric   { AArch64::ST1Threev2d,       "st1",  ".2d",    0, false, 0  },
6800b57cec5SDimitry Andric   { AArch64::ST1Threev8b,       "st1",  ".8b",    0, false, 0  },
6810b57cec5SDimitry Andric   { AArch64::ST1Threev4h,       "st1",  ".4h",    0, false, 0  },
6820b57cec5SDimitry Andric   { AArch64::ST1Threev2s,       "st1",  ".2s",    0, false, 0  },
6830b57cec5SDimitry Andric   { AArch64::ST1Threev1d,       "st1",  ".1d",    0, false, 0  },
6840b57cec5SDimitry Andric   { AArch64::ST1Threev16b_POST, "st1",  ".16b",   1, false, 48 },
6850b57cec5SDimitry Andric   { AArch64::ST1Threev8h_POST,  "st1",  ".8h",    1, false, 48 },
6860b57cec5SDimitry Andric   { AArch64::ST1Threev4s_POST,  "st1",  ".4s",    1, false, 48 },
6870b57cec5SDimitry Andric   { AArch64::ST1Threev2d_POST,  "st1",  ".2d",    1, false, 48 },
6880b57cec5SDimitry Andric   { AArch64::ST1Threev8b_POST,  "st1",  ".8b",    1, false, 24 },
6890b57cec5SDimitry Andric   { AArch64::ST1Threev4h_POST,  "st1",  ".4h",    1, false, 24 },
6900b57cec5SDimitry Andric   { AArch64::ST1Threev2s_POST,  "st1",  ".2s",    1, false, 24 },
6910b57cec5SDimitry Andric   { AArch64::ST1Threev1d_POST,  "st1",  ".1d",    1, false, 24 },
6920b57cec5SDimitry Andric   { AArch64::ST1Fourv16b,       "st1",  ".16b",   0, false, 0  },
6930b57cec5SDimitry Andric   { AArch64::ST1Fourv8h,        "st1",  ".8h",    0, false, 0  },
6940b57cec5SDimitry Andric   { AArch64::ST1Fourv4s,        "st1",  ".4s",    0, false, 0  },
6950b57cec5SDimitry Andric   { AArch64::ST1Fourv2d,        "st1",  ".2d",    0, false, 0  },
6960b57cec5SDimitry Andric   { AArch64::ST1Fourv8b,        "st1",  ".8b",    0, false, 0  },
6970b57cec5SDimitry Andric   { AArch64::ST1Fourv4h,        "st1",  ".4h",    0, false, 0  },
6980b57cec5SDimitry Andric   { AArch64::ST1Fourv2s,        "st1",  ".2s",    0, false, 0  },
6990b57cec5SDimitry Andric   { AArch64::ST1Fourv1d,        "st1",  ".1d",    0, false, 0  },
7000b57cec5SDimitry Andric   { AArch64::ST1Fourv16b_POST,  "st1",  ".16b",   1, false, 64 },
7010b57cec5SDimitry Andric   { AArch64::ST1Fourv8h_POST,   "st1",  ".8h",    1, false, 64 },
7020b57cec5SDimitry Andric   { AArch64::ST1Fourv4s_POST,   "st1",  ".4s",    1, false, 64 },
7030b57cec5SDimitry Andric   { AArch64::ST1Fourv2d_POST,   "st1",  ".2d",    1, false, 64 },
7040b57cec5SDimitry Andric   { AArch64::ST1Fourv8b_POST,   "st1",  ".8b",    1, false, 32 },
7050b57cec5SDimitry Andric   { AArch64::ST1Fourv4h_POST,   "st1",  ".4h",    1, false, 32 },
7060b57cec5SDimitry Andric   { AArch64::ST1Fourv2s_POST,   "st1",  ".2s",    1, false, 32 },
7070b57cec5SDimitry Andric   { AArch64::ST1Fourv1d_POST,   "st1",  ".1d",    1, false, 32 },
7080b57cec5SDimitry Andric   { AArch64::ST2i8,             "st2",  ".b",     0, true,  0  },
7090b57cec5SDimitry Andric   { AArch64::ST2i16,            "st2",  ".h",     0, true,  0  },
7100b57cec5SDimitry Andric   { AArch64::ST2i32,            "st2",  ".s",     0, true,  0  },
7110b57cec5SDimitry Andric   { AArch64::ST2i64,            "st2",  ".d",     0, true,  0  },
7120b57cec5SDimitry Andric   { AArch64::ST2i8_POST,        "st2",  ".b",     1, true,  2  },
7130b57cec5SDimitry Andric   { AArch64::ST2i16_POST,       "st2",  ".h",     1, true,  4  },
7140b57cec5SDimitry Andric   { AArch64::ST2i32_POST,       "st2",  ".s",     1, true,  8  },
7150b57cec5SDimitry Andric   { AArch64::ST2i64_POST,       "st2",  ".d",     1, true,  16 },
7160b57cec5SDimitry Andric   { AArch64::ST2Twov16b,        "st2",  ".16b",   0, false, 0  },
7170b57cec5SDimitry Andric   { AArch64::ST2Twov8h,         "st2",  ".8h",    0, false, 0  },
7180b57cec5SDimitry Andric   { AArch64::ST2Twov4s,         "st2",  ".4s",    0, false, 0  },
7190b57cec5SDimitry Andric   { AArch64::ST2Twov2d,         "st2",  ".2d",    0, false, 0  },
7200b57cec5SDimitry Andric   { AArch64::ST2Twov8b,         "st2",  ".8b",    0, false, 0  },
7210b57cec5SDimitry Andric   { AArch64::ST2Twov4h,         "st2",  ".4h",    0, false, 0  },
7220b57cec5SDimitry Andric   { AArch64::ST2Twov2s,         "st2",  ".2s",    0, false, 0  },
7230b57cec5SDimitry Andric   { AArch64::ST2Twov16b_POST,   "st2",  ".16b",   1, false, 32 },
7240b57cec5SDimitry Andric   { AArch64::ST2Twov8h_POST,    "st2",  ".8h",    1, false, 32 },
7250b57cec5SDimitry Andric   { AArch64::ST2Twov4s_POST,    "st2",  ".4s",    1, false, 32 },
7260b57cec5SDimitry Andric   { AArch64::ST2Twov2d_POST,    "st2",  ".2d",    1, false, 32 },
7270b57cec5SDimitry Andric   { AArch64::ST2Twov8b_POST,    "st2",  ".8b",    1, false, 16 },
7280b57cec5SDimitry Andric   { AArch64::ST2Twov4h_POST,    "st2",  ".4h",    1, false, 16 },
7290b57cec5SDimitry Andric   { AArch64::ST2Twov2s_POST,    "st2",  ".2s",    1, false, 16 },
7300b57cec5SDimitry Andric   { AArch64::ST3i8,             "st3",  ".b",     0, true,  0  },
7310b57cec5SDimitry Andric   { AArch64::ST3i16,            "st3",  ".h",     0, true,  0  },
7320b57cec5SDimitry Andric   { AArch64::ST3i32,            "st3",  ".s",     0, true,  0  },
7330b57cec5SDimitry Andric   { AArch64::ST3i64,            "st3",  ".d",     0, true,  0  },
7340b57cec5SDimitry Andric   { AArch64::ST3i8_POST,        "st3",  ".b",     1, true,  3  },
7350b57cec5SDimitry Andric   { AArch64::ST3i16_POST,       "st3",  ".h",     1, true,  6  },
7360b57cec5SDimitry Andric   { AArch64::ST3i32_POST,       "st3",  ".s",     1, true,  12 },
7370b57cec5SDimitry Andric   { AArch64::ST3i64_POST,       "st3",  ".d",     1, true,  24 },
7380b57cec5SDimitry Andric   { AArch64::ST3Threev16b,      "st3",  ".16b",   0, false, 0  },
7390b57cec5SDimitry Andric   { AArch64::ST3Threev8h,       "st3",  ".8h",    0, false, 0  },
7400b57cec5SDimitry Andric   { AArch64::ST3Threev4s,       "st3",  ".4s",    0, false, 0  },
7410b57cec5SDimitry Andric   { AArch64::ST3Threev2d,       "st3",  ".2d",    0, false, 0  },
7420b57cec5SDimitry Andric   { AArch64::ST3Threev8b,       "st3",  ".8b",    0, false, 0  },
7430b57cec5SDimitry Andric   { AArch64::ST3Threev4h,       "st3",  ".4h",    0, false, 0  },
7440b57cec5SDimitry Andric   { AArch64::ST3Threev2s,       "st3",  ".2s",    0, false, 0  },
7450b57cec5SDimitry Andric   { AArch64::ST3Threev16b_POST, "st3",  ".16b",   1, false, 48 },
7460b57cec5SDimitry Andric   { AArch64::ST3Threev8h_POST,  "st3",  ".8h",    1, false, 48 },
7470b57cec5SDimitry Andric   { AArch64::ST3Threev4s_POST,  "st3",  ".4s",    1, false, 48 },
7480b57cec5SDimitry Andric   { AArch64::ST3Threev2d_POST,  "st3",  ".2d",    1, false, 48 },
7490b57cec5SDimitry Andric   { AArch64::ST3Threev8b_POST,  "st3",  ".8b",    1, false, 24 },
7500b57cec5SDimitry Andric   { AArch64::ST3Threev4h_POST,  "st3",  ".4h",    1, false, 24 },
7510b57cec5SDimitry Andric   { AArch64::ST3Threev2s_POST,  "st3",  ".2s",    1, false, 24 },
7520b57cec5SDimitry Andric   { AArch64::ST4i8,             "st4",  ".b",     0, true,  0  },
7530b57cec5SDimitry Andric   { AArch64::ST4i16,            "st4",  ".h",     0, true,  0  },
7540b57cec5SDimitry Andric   { AArch64::ST4i32,            "st4",  ".s",     0, true,  0  },
7550b57cec5SDimitry Andric   { AArch64::ST4i64,            "st4",  ".d",     0, true,  0  },
7560b57cec5SDimitry Andric   { AArch64::ST4i8_POST,        "st4",  ".b",     1, true,  4  },
7570b57cec5SDimitry Andric   { AArch64::ST4i16_POST,       "st4",  ".h",     1, true,  8  },
7580b57cec5SDimitry Andric   { AArch64::ST4i32_POST,       "st4",  ".s",     1, true,  16 },
7590b57cec5SDimitry Andric   { AArch64::ST4i64_POST,       "st4",  ".d",     1, true,  32 },
7600b57cec5SDimitry Andric   { AArch64::ST4Fourv16b,       "st4",  ".16b",   0, false, 0  },
7610b57cec5SDimitry Andric   { AArch64::ST4Fourv8h,        "st4",  ".8h",    0, false, 0  },
7620b57cec5SDimitry Andric   { AArch64::ST4Fourv4s,        "st4",  ".4s",    0, false, 0  },
7630b57cec5SDimitry Andric   { AArch64::ST4Fourv2d,        "st4",  ".2d",    0, false, 0  },
7640b57cec5SDimitry Andric   { AArch64::ST4Fourv8b,        "st4",  ".8b",    0, false, 0  },
7650b57cec5SDimitry Andric   { AArch64::ST4Fourv4h,        "st4",  ".4h",    0, false, 0  },
7660b57cec5SDimitry Andric   { AArch64::ST4Fourv2s,        "st4",  ".2s",    0, false, 0  },
7670b57cec5SDimitry Andric   { AArch64::ST4Fourv16b_POST,  "st4",  ".16b",   1, false, 64 },
7680b57cec5SDimitry Andric   { AArch64::ST4Fourv8h_POST,   "st4",  ".8h",    1, false, 64 },
7690b57cec5SDimitry Andric   { AArch64::ST4Fourv4s_POST,   "st4",  ".4s",    1, false, 64 },
7700b57cec5SDimitry Andric   { AArch64::ST4Fourv2d_POST,   "st4",  ".2d",    1, false, 64 },
7710b57cec5SDimitry Andric   { AArch64::ST4Fourv8b_POST,   "st4",  ".8b",    1, false, 32 },
7720b57cec5SDimitry Andric   { AArch64::ST4Fourv4h_POST,   "st4",  ".4h",    1, false, 32 },
7730b57cec5SDimitry Andric   { AArch64::ST4Fourv2s_POST,   "st4",  ".2s",    1, false, 32 },
7740b57cec5SDimitry Andric };
7750b57cec5SDimitry Andric 
getLdStNInstrDesc(unsigned Opcode)7760b57cec5SDimitry Andric static const LdStNInstrDesc *getLdStNInstrDesc(unsigned Opcode) {
777bdd1243dSDimitry Andric   for (const auto &Info : LdStNInstInfo)
778bdd1243dSDimitry Andric     if (Info.Opcode == Opcode)
779bdd1243dSDimitry Andric       return &Info;
7800b57cec5SDimitry Andric 
7810b57cec5SDimitry Andric   return nullptr;
7820b57cec5SDimitry Andric }
7830b57cec5SDimitry Andric 
printInst(const MCInst * MI,uint64_t Address,StringRef Annot,const MCSubtargetInfo & STI,raw_ostream & O)784480093f4SDimitry Andric void AArch64AppleInstPrinter::printInst(const MCInst *MI, uint64_t Address,
7850b57cec5SDimitry Andric                                         StringRef Annot,
786480093f4SDimitry Andric                                         const MCSubtargetInfo &STI,
787480093f4SDimitry Andric                                         raw_ostream &O) {
7880b57cec5SDimitry Andric   unsigned Opcode = MI->getOpcode();
7890b57cec5SDimitry Andric   StringRef Layout;
7900b57cec5SDimitry Andric 
7910b57cec5SDimitry Andric   bool IsTbx;
7920b57cec5SDimitry Andric   if (isTblTbxInstruction(MI->getOpcode(), Layout, IsTbx)) {
793bdd1243dSDimitry Andric     O << "\t" << (IsTbx ? "tbx" : "tbl") << Layout << '\t';
794bdd1243dSDimitry Andric     printRegName(O, MI->getOperand(0).getReg(), AArch64::vreg);
795bdd1243dSDimitry Andric     O << ", ";
7960b57cec5SDimitry Andric 
7970b57cec5SDimitry Andric     unsigned ListOpNum = IsTbx ? 2 : 1;
7980b57cec5SDimitry Andric     printVectorList(MI, ListOpNum, STI, O, "");
7990b57cec5SDimitry Andric 
800bdd1243dSDimitry Andric     O << ", ";
801bdd1243dSDimitry Andric     printRegName(O, MI->getOperand(ListOpNum + 1).getReg(), AArch64::vreg);
8020b57cec5SDimitry Andric     printAnnotation(O, Annot);
8030b57cec5SDimitry Andric     return;
8040b57cec5SDimitry Andric   }
8050b57cec5SDimitry Andric 
8060b57cec5SDimitry Andric   if (const LdStNInstrDesc *LdStDesc = getLdStNInstrDesc(Opcode)) {
8070b57cec5SDimitry Andric     O << "\t" << LdStDesc->Mnemonic << LdStDesc->Layout << '\t';
8080b57cec5SDimitry Andric 
8090b57cec5SDimitry Andric     // Now onto the operands: first a vector list with possible lane
8100b57cec5SDimitry Andric     // specifier. E.g. { v0 }[2]
8110b57cec5SDimitry Andric     int OpNum = LdStDesc->ListOperand;
8120b57cec5SDimitry Andric     printVectorList(MI, OpNum++, STI, O, "");
8130b57cec5SDimitry Andric 
8140b57cec5SDimitry Andric     if (LdStDesc->HasLane)
8150b57cec5SDimitry Andric       O << '[' << MI->getOperand(OpNum++).getImm() << ']';
8160b57cec5SDimitry Andric 
8170b57cec5SDimitry Andric     // Next the address: [xN]
8180b57cec5SDimitry Andric     unsigned AddrReg = MI->getOperand(OpNum++).getReg();
819bdd1243dSDimitry Andric     O << ", [";
820bdd1243dSDimitry Andric     printRegName(O, AddrReg);
821bdd1243dSDimitry Andric     O << ']';
8220b57cec5SDimitry Andric 
8230b57cec5SDimitry Andric     // Finally, there might be a post-indexed offset.
8240b57cec5SDimitry Andric     if (LdStDesc->NaturalOffset != 0) {
8250b57cec5SDimitry Andric       unsigned Reg = MI->getOperand(OpNum++).getReg();
826bdd1243dSDimitry Andric       if (Reg != AArch64::XZR) {
827bdd1243dSDimitry Andric         O << ", ";
828bdd1243dSDimitry Andric         printRegName(O, Reg);
829bdd1243dSDimitry Andric       } else {
8300b57cec5SDimitry Andric         assert(LdStDesc->NaturalOffset && "no offset on post-inc instruction?");
8315f757f3fSDimitry Andric         O << ", ";
8325f757f3fSDimitry Andric         markup(O, Markup::Immediate) << "#" << LdStDesc->NaturalOffset;
8330b57cec5SDimitry Andric       }
8340b57cec5SDimitry Andric     }
8350b57cec5SDimitry Andric 
8360b57cec5SDimitry Andric     printAnnotation(O, Annot);
8370b57cec5SDimitry Andric     return;
8380b57cec5SDimitry Andric   }
8390b57cec5SDimitry Andric 
840480093f4SDimitry Andric   AArch64InstPrinter::printInst(MI, Address, Annot, STI, O);
8410b57cec5SDimitry Andric }
8420b57cec5SDimitry Andric 
getRegName(MCRegister Reg) const843bdd1243dSDimitry Andric StringRef AArch64AppleInstPrinter::getRegName(MCRegister Reg) const {
844bdd1243dSDimitry Andric   return getRegisterName(Reg);
845bdd1243dSDimitry Andric }
846bdd1243dSDimitry Andric 
printRangePrefetchAlias(const MCInst * MI,const MCSubtargetInfo & STI,raw_ostream & O,StringRef Annot)847bdd1243dSDimitry Andric bool AArch64InstPrinter::printRangePrefetchAlias(const MCInst *MI,
848bdd1243dSDimitry Andric                                                  const MCSubtargetInfo &STI,
849bdd1243dSDimitry Andric                                                  raw_ostream &O,
850bdd1243dSDimitry Andric                                                  StringRef Annot) {
851bdd1243dSDimitry Andric   unsigned Opcode = MI->getOpcode();
852bdd1243dSDimitry Andric 
853bdd1243dSDimitry Andric #ifndef NDEBUG
854bdd1243dSDimitry Andric   assert(((Opcode == AArch64::PRFMroX) || (Opcode == AArch64::PRFMroW)) &&
855bdd1243dSDimitry Andric          "Invalid opcode for RPRFM alias!");
856bdd1243dSDimitry Andric #endif
857bdd1243dSDimitry Andric 
858bdd1243dSDimitry Andric   unsigned PRFOp = MI->getOperand(0).getImm();
859bdd1243dSDimitry Andric   unsigned Mask = 0x18; // 0b11000
860bdd1243dSDimitry Andric   if ((PRFOp & Mask) != Mask)
861bdd1243dSDimitry Andric     return false; // Rt != '11xxx', it's a PRFM instruction.
862bdd1243dSDimitry Andric 
863bdd1243dSDimitry Andric   unsigned Rm = MI->getOperand(2).getReg();
864bdd1243dSDimitry Andric 
865bdd1243dSDimitry Andric   // "Rm" must be a 64-bit GPR for RPRFM.
866bdd1243dSDimitry Andric   if (MRI.getRegClass(AArch64::GPR32RegClassID).contains(Rm))
867bdd1243dSDimitry Andric     Rm = MRI.getMatchingSuperReg(Rm, AArch64::sub_32,
868bdd1243dSDimitry Andric                                  &MRI.getRegClass(AArch64::GPR64RegClassID));
869bdd1243dSDimitry Andric 
870bdd1243dSDimitry Andric   unsigned SignExtend = MI->getOperand(3).getImm(); // encoded in "option<2>".
871bdd1243dSDimitry Andric   unsigned Shift = MI->getOperand(4).getImm();      // encoded in "S".
872bdd1243dSDimitry Andric 
873bdd1243dSDimitry Andric   assert((SignExtend <= 1) && "sign extend should be a single bit!");
874bdd1243dSDimitry Andric   assert((Shift <= 1) && "Shift should be a single bit!");
875bdd1243dSDimitry Andric 
876bdd1243dSDimitry Andric   unsigned Option0 = (Opcode == AArch64::PRFMroX) ? 1 : 0;
877bdd1243dSDimitry Andric 
878bdd1243dSDimitry Andric   // encoded in "option<2>:option<0>:S:Rt<2:0>".
879bdd1243dSDimitry Andric   unsigned RPRFOp =
880bdd1243dSDimitry Andric       (SignExtend << 5) | (Option0 << 4) | (Shift << 3) | (PRFOp & 0x7);
881bdd1243dSDimitry Andric 
882bdd1243dSDimitry Andric   O << "\trprfm ";
883bdd1243dSDimitry Andric   if (auto RPRFM = AArch64RPRFM::lookupRPRFMByEncoding(RPRFOp))
884bdd1243dSDimitry Andric     O << RPRFM->Name << ", ";
885bdd1243dSDimitry Andric   else
886bdd1243dSDimitry Andric     O << "#" << formatImm(RPRFOp) << ", ";
887bdd1243dSDimitry Andric   O << getRegisterName(Rm);
888bdd1243dSDimitry Andric   O << ", [";
889bdd1243dSDimitry Andric   printOperand(MI, 1, STI, O); // "Rn".
890bdd1243dSDimitry Andric   O << "]";
891bdd1243dSDimitry Andric 
892bdd1243dSDimitry Andric   printAnnotation(O, Annot);
893bdd1243dSDimitry Andric 
894bdd1243dSDimitry Andric   return true;
895bdd1243dSDimitry Andric }
896bdd1243dSDimitry Andric 
printSysAlias(const MCInst * MI,const MCSubtargetInfo & STI,raw_ostream & O)8970b57cec5SDimitry Andric bool AArch64InstPrinter::printSysAlias(const MCInst *MI,
8980b57cec5SDimitry Andric                                        const MCSubtargetInfo &STI,
8990b57cec5SDimitry Andric                                        raw_ostream &O) {
9000b57cec5SDimitry Andric #ifndef NDEBUG
9010b57cec5SDimitry Andric   unsigned Opcode = MI->getOpcode();
9020b57cec5SDimitry Andric   assert(Opcode == AArch64::SYSxt && "Invalid opcode for SYS alias!");
9030b57cec5SDimitry Andric #endif
9040b57cec5SDimitry Andric 
9050b57cec5SDimitry Andric   const MCOperand &Op1 = MI->getOperand(0);
9060b57cec5SDimitry Andric   const MCOperand &Cn = MI->getOperand(1);
9070b57cec5SDimitry Andric   const MCOperand &Cm = MI->getOperand(2);
9080b57cec5SDimitry Andric   const MCOperand &Op2 = MI->getOperand(3);
9090b57cec5SDimitry Andric 
9100b57cec5SDimitry Andric   unsigned Op1Val = Op1.getImm();
9110b57cec5SDimitry Andric   unsigned CnVal = Cn.getImm();
9120b57cec5SDimitry Andric   unsigned CmVal = Cm.getImm();
9130b57cec5SDimitry Andric   unsigned Op2Val = Op2.getImm();
9140b57cec5SDimitry Andric 
9150b57cec5SDimitry Andric   uint16_t Encoding = Op2Val;
9160b57cec5SDimitry Andric   Encoding |= CmVal << 3;
9170b57cec5SDimitry Andric   Encoding |= CnVal << 7;
9180b57cec5SDimitry Andric   Encoding |= Op1Val << 11;
9190b57cec5SDimitry Andric 
9200b57cec5SDimitry Andric   bool NeedsReg;
9210b57cec5SDimitry Andric   std::string Ins;
9220b57cec5SDimitry Andric   std::string Name;
9230b57cec5SDimitry Andric 
9240b57cec5SDimitry Andric   if (CnVal == 7) {
9250b57cec5SDimitry Andric     switch (CmVal) {
9260b57cec5SDimitry Andric     default: return false;
9270b57cec5SDimitry Andric     // Maybe IC, maybe Prediction Restriction
9280b57cec5SDimitry Andric     case 1:
9290b57cec5SDimitry Andric       switch (Op1Val) {
9300b57cec5SDimitry Andric       default: return false;
9310b57cec5SDimitry Andric       case 0: goto Search_IC;
9320b57cec5SDimitry Andric       case 3: goto Search_PRCTX;
9330b57cec5SDimitry Andric       }
9340b57cec5SDimitry Andric     // Prediction Restriction aliases
9350b57cec5SDimitry Andric     case 3: {
9360b57cec5SDimitry Andric       Search_PRCTX:
937bdd1243dSDimitry Andric       if (Op1Val != 3 || CnVal != 7 || CmVal != 3)
9380b57cec5SDimitry Andric         return false;
9390b57cec5SDimitry Andric 
940bdd1243dSDimitry Andric       const auto Requires =
941bdd1243dSDimitry Andric           Op2Val == 6 ? AArch64::FeatureSPECRES2 : AArch64::FeaturePredRes;
942bdd1243dSDimitry Andric       if (!(STI.hasFeature(AArch64::FeatureAll) || STI.hasFeature(Requires)))
943bdd1243dSDimitry Andric         return false;
944bdd1243dSDimitry Andric 
945bdd1243dSDimitry Andric       NeedsReg = true;
9460b57cec5SDimitry Andric       switch (Op2Val) {
9470b57cec5SDimitry Andric       default: return false;
9480b57cec5SDimitry Andric       case 4: Ins = "cfp\t"; break;
9490b57cec5SDimitry Andric       case 5: Ins = "dvp\t"; break;
950bdd1243dSDimitry Andric       case 6: Ins = "cosp\t"; break;
9510b57cec5SDimitry Andric       case 7: Ins = "cpp\t"; break;
9520b57cec5SDimitry Andric       }
953bdd1243dSDimitry Andric       Name = "RCTX";
9540b57cec5SDimitry Andric     }
9550b57cec5SDimitry Andric     break;
9560b57cec5SDimitry Andric     // IC aliases
9570b57cec5SDimitry Andric     case 5: {
9580b57cec5SDimitry Andric       Search_IC:
9590b57cec5SDimitry Andric       const AArch64IC::IC *IC = AArch64IC::lookupICByEncoding(Encoding);
9600b57cec5SDimitry Andric       if (!IC || !IC->haveFeatures(STI.getFeatureBits()))
9610b57cec5SDimitry Andric         return false;
9620b57cec5SDimitry Andric 
9630b57cec5SDimitry Andric       NeedsReg = IC->NeedsReg;
9640b57cec5SDimitry Andric       Ins = "ic\t";
9650b57cec5SDimitry Andric       Name = std::string(IC->Name);
9660b57cec5SDimitry Andric     }
9670b57cec5SDimitry Andric     break;
9680b57cec5SDimitry Andric     // DC aliases
9690b57cec5SDimitry Andric     case 4: case 6: case 10: case 11: case 12: case 13: case 14:
9700b57cec5SDimitry Andric     {
9710b57cec5SDimitry Andric       const AArch64DC::DC *DC = AArch64DC::lookupDCByEncoding(Encoding);
9720b57cec5SDimitry Andric       if (!DC || !DC->haveFeatures(STI.getFeatureBits()))
9730b57cec5SDimitry Andric         return false;
9740b57cec5SDimitry Andric 
9750b57cec5SDimitry Andric       NeedsReg = true;
9760b57cec5SDimitry Andric       Ins = "dc\t";
9770b57cec5SDimitry Andric       Name = std::string(DC->Name);
9780b57cec5SDimitry Andric     }
9790b57cec5SDimitry Andric     break;
9800b57cec5SDimitry Andric     // AT aliases
9810b57cec5SDimitry Andric     case 8: case 9: {
9820b57cec5SDimitry Andric       const AArch64AT::AT *AT = AArch64AT::lookupATByEncoding(Encoding);
9830b57cec5SDimitry Andric       if (!AT || !AT->haveFeatures(STI.getFeatureBits()))
9840b57cec5SDimitry Andric         return false;
9850b57cec5SDimitry Andric 
9860b57cec5SDimitry Andric       NeedsReg = true;
9870b57cec5SDimitry Andric       Ins = "at\t";
9880b57cec5SDimitry Andric       Name = std::string(AT->Name);
9890b57cec5SDimitry Andric     }
9900b57cec5SDimitry Andric     break;
9910b57cec5SDimitry Andric     }
992e8d8bef9SDimitry Andric   } else if (CnVal == 8 || CnVal == 9) {
9930b57cec5SDimitry Andric     // TLBI aliases
9940b57cec5SDimitry Andric     const AArch64TLBI::TLBI *TLBI = AArch64TLBI::lookupTLBIByEncoding(Encoding);
9950b57cec5SDimitry Andric     if (!TLBI || !TLBI->haveFeatures(STI.getFeatureBits()))
9960b57cec5SDimitry Andric       return false;
9970b57cec5SDimitry Andric 
9980b57cec5SDimitry Andric     NeedsReg = TLBI->NeedsReg;
9990b57cec5SDimitry Andric     Ins = "tlbi\t";
10000b57cec5SDimitry Andric     Name = std::string(TLBI->Name);
10010b57cec5SDimitry Andric   }
10020b57cec5SDimitry Andric   else
10030b57cec5SDimitry Andric     return false;
10040b57cec5SDimitry Andric 
10050b57cec5SDimitry Andric   std::string Str = Ins + Name;
10060b57cec5SDimitry Andric   std::transform(Str.begin(), Str.end(), Str.begin(), ::tolower);
10070b57cec5SDimitry Andric 
10080b57cec5SDimitry Andric   O << '\t' << Str;
1009bdd1243dSDimitry Andric   if (NeedsReg) {
1010bdd1243dSDimitry Andric     O << ", ";
1011bdd1243dSDimitry Andric     printRegName(O, MI->getOperand(4).getReg());
1012bdd1243dSDimitry Andric   }
1013bdd1243dSDimitry Andric 
1014bdd1243dSDimitry Andric   return true;
1015bdd1243dSDimitry Andric }
1016bdd1243dSDimitry Andric 
printSyspAlias(const MCInst * MI,const MCSubtargetInfo & STI,raw_ostream & O)1017bdd1243dSDimitry Andric bool AArch64InstPrinter::printSyspAlias(const MCInst *MI,
1018bdd1243dSDimitry Andric                                         const MCSubtargetInfo &STI,
1019bdd1243dSDimitry Andric                                         raw_ostream &O) {
1020bdd1243dSDimitry Andric #ifndef NDEBUG
1021bdd1243dSDimitry Andric   unsigned Opcode = MI->getOpcode();
1022bdd1243dSDimitry Andric   assert((Opcode == AArch64::SYSPxt || Opcode == AArch64::SYSPxt_XZR) &&
1023bdd1243dSDimitry Andric          "Invalid opcode for SYSP alias!");
1024bdd1243dSDimitry Andric #endif
1025bdd1243dSDimitry Andric 
1026bdd1243dSDimitry Andric   const MCOperand &Op1 = MI->getOperand(0);
1027bdd1243dSDimitry Andric   const MCOperand &Cn = MI->getOperand(1);
1028bdd1243dSDimitry Andric   const MCOperand &Cm = MI->getOperand(2);
1029bdd1243dSDimitry Andric   const MCOperand &Op2 = MI->getOperand(3);
1030bdd1243dSDimitry Andric 
1031bdd1243dSDimitry Andric   unsigned Op1Val = Op1.getImm();
1032bdd1243dSDimitry Andric   unsigned CnVal = Cn.getImm();
1033bdd1243dSDimitry Andric   unsigned CmVal = Cm.getImm();
1034bdd1243dSDimitry Andric   unsigned Op2Val = Op2.getImm();
1035bdd1243dSDimitry Andric 
1036bdd1243dSDimitry Andric   uint16_t Encoding = Op2Val;
1037bdd1243dSDimitry Andric   Encoding |= CmVal << 3;
1038bdd1243dSDimitry Andric   Encoding |= CnVal << 7;
1039bdd1243dSDimitry Andric   Encoding |= Op1Val << 11;
1040bdd1243dSDimitry Andric 
1041bdd1243dSDimitry Andric   std::string Ins;
1042bdd1243dSDimitry Andric   std::string Name;
1043bdd1243dSDimitry Andric 
1044bdd1243dSDimitry Andric   if (CnVal == 8 || CnVal == 9) {
1045bdd1243dSDimitry Andric     // TLBIP aliases
1046bdd1243dSDimitry Andric 
1047bdd1243dSDimitry Andric     if (CnVal == 9) {
1048bdd1243dSDimitry Andric       if (!STI.hasFeature(AArch64::FeatureXS))
1049bdd1243dSDimitry Andric         return false;
1050bdd1243dSDimitry Andric       Encoding &= ~(1 << 7);
1051bdd1243dSDimitry Andric     }
1052bdd1243dSDimitry Andric 
1053bdd1243dSDimitry Andric     const AArch64TLBI::TLBI *TLBI = AArch64TLBI::lookupTLBIByEncoding(Encoding);
1054bdd1243dSDimitry Andric     if (!TLBI || !TLBI->haveFeatures(STI.getFeatureBits()))
1055bdd1243dSDimitry Andric       return false;
1056bdd1243dSDimitry Andric 
1057bdd1243dSDimitry Andric     Ins = "tlbip\t";
1058bdd1243dSDimitry Andric     Name = std::string(TLBI->Name);
1059bdd1243dSDimitry Andric     if (CnVal == 9)
1060bdd1243dSDimitry Andric       Name += "nXS";
1061bdd1243dSDimitry Andric   } else
1062bdd1243dSDimitry Andric     return false;
1063bdd1243dSDimitry Andric 
1064bdd1243dSDimitry Andric   std::string Str = Ins + Name;
1065bdd1243dSDimitry Andric   std::transform(Str.begin(), Str.end(), Str.begin(), ::tolower);
1066bdd1243dSDimitry Andric 
1067bdd1243dSDimitry Andric   O << '\t' << Str;
1068bdd1243dSDimitry Andric   O << ", ";
1069bdd1243dSDimitry Andric   if (MI->getOperand(4).getReg() == AArch64::XZR)
1070bdd1243dSDimitry Andric     printSyspXzrPair(MI, 4, STI, O);
1071bdd1243dSDimitry Andric   else
1072bdd1243dSDimitry Andric     printGPRSeqPairsClassOperand<64>(MI, 4, STI, O);
10730b57cec5SDimitry Andric 
10740b57cec5SDimitry Andric   return true;
10750b57cec5SDimitry Andric }
10760b57cec5SDimitry Andric 
1077fe6060f1SDimitry Andric template <int EltSize>
printMatrix(const MCInst * MI,unsigned OpNum,const MCSubtargetInfo & STI,raw_ostream & O)1078fe6060f1SDimitry Andric void AArch64InstPrinter::printMatrix(const MCInst *MI, unsigned OpNum,
1079fe6060f1SDimitry Andric                                      const MCSubtargetInfo &STI,
1080fe6060f1SDimitry Andric                                      raw_ostream &O) {
1081fe6060f1SDimitry Andric   const MCOperand &RegOp = MI->getOperand(OpNum);
1082fe6060f1SDimitry Andric   assert(RegOp.isReg() && "Unexpected operand type!");
1083fe6060f1SDimitry Andric 
1084bdd1243dSDimitry Andric   printRegName(O, RegOp.getReg());
1085fe6060f1SDimitry Andric   switch (EltSize) {
1086fe6060f1SDimitry Andric   case 0:
1087fe6060f1SDimitry Andric     break;
1088fe6060f1SDimitry Andric   case 8:
1089fe6060f1SDimitry Andric     O << ".b";
1090fe6060f1SDimitry Andric     break;
1091fe6060f1SDimitry Andric   case 16:
1092fe6060f1SDimitry Andric     O << ".h";
1093fe6060f1SDimitry Andric     break;
1094fe6060f1SDimitry Andric   case 32:
1095fe6060f1SDimitry Andric     O << ".s";
1096fe6060f1SDimitry Andric     break;
1097fe6060f1SDimitry Andric   case 64:
1098fe6060f1SDimitry Andric     O << ".d";
1099fe6060f1SDimitry Andric     break;
1100fe6060f1SDimitry Andric   case 128:
1101fe6060f1SDimitry Andric     O << ".q";
1102fe6060f1SDimitry Andric     break;
1103fe6060f1SDimitry Andric   default:
1104fe6060f1SDimitry Andric     llvm_unreachable("Unsupported element size");
1105fe6060f1SDimitry Andric   }
1106fe6060f1SDimitry Andric }
1107fe6060f1SDimitry Andric 
1108fe6060f1SDimitry Andric template <bool IsVertical>
printMatrixTileVector(const MCInst * MI,unsigned OpNum,const MCSubtargetInfo & STI,raw_ostream & O)1109fe6060f1SDimitry Andric void AArch64InstPrinter::printMatrixTileVector(const MCInst *MI, unsigned OpNum,
1110fe6060f1SDimitry Andric                                                const MCSubtargetInfo &STI,
1111fe6060f1SDimitry Andric                                                raw_ostream &O) {
1112fe6060f1SDimitry Andric   const MCOperand &RegOp = MI->getOperand(OpNum);
1113fe6060f1SDimitry Andric   assert(RegOp.isReg() && "Unexpected operand type!");
1114fe6060f1SDimitry Andric   StringRef RegName = getRegisterName(RegOp.getReg());
1115fe6060f1SDimitry Andric 
1116fe6060f1SDimitry Andric   // Insert the horizontal/vertical flag before the suffix.
1117fe6060f1SDimitry Andric   StringRef Base, Suffix;
1118fe6060f1SDimitry Andric   std::tie(Base, Suffix) = RegName.split('.');
1119fe6060f1SDimitry Andric   O << Base << (IsVertical ? "v" : "h") << '.' << Suffix;
1120fe6060f1SDimitry Andric }
1121fe6060f1SDimitry Andric 
printMatrixTile(const MCInst * MI,unsigned OpNum,const MCSubtargetInfo & STI,raw_ostream & O)1122fe6060f1SDimitry Andric void AArch64InstPrinter::printMatrixTile(const MCInst *MI, unsigned OpNum,
1123fe6060f1SDimitry Andric                                          const MCSubtargetInfo &STI,
1124fe6060f1SDimitry Andric                                          raw_ostream &O) {
1125fe6060f1SDimitry Andric   const MCOperand &RegOp = MI->getOperand(OpNum);
1126fe6060f1SDimitry Andric   assert(RegOp.isReg() && "Unexpected operand type!");
1127bdd1243dSDimitry Andric   printRegName(O, RegOp.getReg());
1128fe6060f1SDimitry Andric }
1129fe6060f1SDimitry Andric 
printSVCROp(const MCInst * MI,unsigned OpNum,const MCSubtargetInfo & STI,raw_ostream & O)1130fe6060f1SDimitry Andric void AArch64InstPrinter::printSVCROp(const MCInst *MI, unsigned OpNum,
1131fe6060f1SDimitry Andric                                      const MCSubtargetInfo &STI,
1132fe6060f1SDimitry Andric                                      raw_ostream &O) {
1133fe6060f1SDimitry Andric   const MCOperand &MO = MI->getOperand(OpNum);
1134fe6060f1SDimitry Andric   assert(MO.isImm() && "Unexpected operand type!");
1135fe6060f1SDimitry Andric   unsigned svcrop = MO.getImm();
1136fe6060f1SDimitry Andric   const auto *SVCR = AArch64SVCR::lookupSVCRByEncoding(svcrop);
1137fe6060f1SDimitry Andric   assert(SVCR && "Unexpected SVCR operand!");
1138fe6060f1SDimitry Andric   O << SVCR->Name;
1139fe6060f1SDimitry Andric }
1140fe6060f1SDimitry Andric 
printOperand(const MCInst * MI,unsigned OpNo,const MCSubtargetInfo & STI,raw_ostream & O)11410b57cec5SDimitry Andric void AArch64InstPrinter::printOperand(const MCInst *MI, unsigned OpNo,
11420b57cec5SDimitry Andric                                       const MCSubtargetInfo &STI,
11430b57cec5SDimitry Andric                                       raw_ostream &O) {
11440b57cec5SDimitry Andric   const MCOperand &Op = MI->getOperand(OpNo);
11450b57cec5SDimitry Andric   if (Op.isReg()) {
11460b57cec5SDimitry Andric     unsigned Reg = Op.getReg();
1147bdd1243dSDimitry Andric     printRegName(O, Reg);
11480b57cec5SDimitry Andric   } else if (Op.isImm()) {
11490b57cec5SDimitry Andric     printImm(MI, OpNo, STI, O);
11500b57cec5SDimitry Andric   } else {
11510b57cec5SDimitry Andric     assert(Op.isExpr() && "unknown operand kind in printOperand");
11520b57cec5SDimitry Andric     Op.getExpr()->print(O, &MAI);
11530b57cec5SDimitry Andric   }
11540b57cec5SDimitry Andric }
11550b57cec5SDimitry Andric 
printImm(const MCInst * MI,unsigned OpNo,const MCSubtargetInfo & STI,raw_ostream & O)11560b57cec5SDimitry Andric void AArch64InstPrinter::printImm(const MCInst *MI, unsigned OpNo,
11570b57cec5SDimitry Andric                                      const MCSubtargetInfo &STI,
11580b57cec5SDimitry Andric                                      raw_ostream &O) {
11590b57cec5SDimitry Andric   const MCOperand &Op = MI->getOperand(OpNo);
11605f757f3fSDimitry Andric   markup(O, Markup::Immediate) << "#" << formatImm(Op.getImm());
11610b57cec5SDimitry Andric }
11620b57cec5SDimitry Andric 
printImmHex(const MCInst * MI,unsigned OpNo,const MCSubtargetInfo & STI,raw_ostream & O)11630b57cec5SDimitry Andric void AArch64InstPrinter::printImmHex(const MCInst *MI, unsigned OpNo,
11640b57cec5SDimitry Andric                                      const MCSubtargetInfo &STI,
11650b57cec5SDimitry Andric                                      raw_ostream &O) {
11660b57cec5SDimitry Andric   const MCOperand &Op = MI->getOperand(OpNo);
11675f757f3fSDimitry Andric   markup(O, Markup::Immediate) << format("#%#llx", Op.getImm());
11680b57cec5SDimitry Andric }
11690b57cec5SDimitry Andric 
11705ffd83dbSDimitry Andric template<int Size>
printSImm(const MCInst * MI,unsigned OpNo,const MCSubtargetInfo & STI,raw_ostream & O)11715ffd83dbSDimitry Andric void AArch64InstPrinter::printSImm(const MCInst *MI, unsigned OpNo,
11725ffd83dbSDimitry Andric                                   const MCSubtargetInfo &STI,
11735ffd83dbSDimitry Andric                                   raw_ostream &O) {
11745ffd83dbSDimitry Andric   const MCOperand &Op = MI->getOperand(OpNo);
11755ffd83dbSDimitry Andric   if (Size == 8)
11765f757f3fSDimitry Andric     markup(O, Markup::Immediate) << "#" << formatImm((signed char)Op.getImm());
11775ffd83dbSDimitry Andric   else if (Size == 16)
11785f757f3fSDimitry Andric     markup(O, Markup::Immediate) << "#" << formatImm((signed short)Op.getImm());
11795ffd83dbSDimitry Andric   else
11805f757f3fSDimitry Andric     markup(O, Markup::Immediate) << "#" << formatImm(Op.getImm());
11815ffd83dbSDimitry Andric }
11825ffd83dbSDimitry Andric 
printPostIncOperand(const MCInst * MI,unsigned OpNo,unsigned Imm,raw_ostream & O)11830b57cec5SDimitry Andric void AArch64InstPrinter::printPostIncOperand(const MCInst *MI, unsigned OpNo,
11840b57cec5SDimitry Andric                                              unsigned Imm, raw_ostream &O) {
11850b57cec5SDimitry Andric   const MCOperand &Op = MI->getOperand(OpNo);
11860b57cec5SDimitry Andric   if (Op.isReg()) {
11870b57cec5SDimitry Andric     unsigned Reg = Op.getReg();
11880b57cec5SDimitry Andric     if (Reg == AArch64::XZR)
11895f757f3fSDimitry Andric       markup(O, Markup::Immediate) << "#" << Imm;
11900b57cec5SDimitry Andric     else
1191bdd1243dSDimitry Andric       printRegName(O, Reg);
11920b57cec5SDimitry Andric   } else
11930b57cec5SDimitry Andric     llvm_unreachable("unknown operand kind in printPostIncOperand64");
11940b57cec5SDimitry Andric }
11950b57cec5SDimitry Andric 
printVRegOperand(const MCInst * MI,unsigned OpNo,const MCSubtargetInfo & STI,raw_ostream & O)11960b57cec5SDimitry Andric void AArch64InstPrinter::printVRegOperand(const MCInst *MI, unsigned OpNo,
11970b57cec5SDimitry Andric                                           const MCSubtargetInfo &STI,
11980b57cec5SDimitry Andric                                           raw_ostream &O) {
11990b57cec5SDimitry Andric   const MCOperand &Op = MI->getOperand(OpNo);
12000b57cec5SDimitry Andric   assert(Op.isReg() && "Non-register vreg operand!");
12010b57cec5SDimitry Andric   unsigned Reg = Op.getReg();
1202bdd1243dSDimitry Andric   printRegName(O, Reg, AArch64::vreg);
12030b57cec5SDimitry Andric }
12040b57cec5SDimitry Andric 
printSysCROperand(const MCInst * MI,unsigned OpNo,const MCSubtargetInfo & STI,raw_ostream & O)12050b57cec5SDimitry Andric void AArch64InstPrinter::printSysCROperand(const MCInst *MI, unsigned OpNo,
12060b57cec5SDimitry Andric                                            const MCSubtargetInfo &STI,
12070b57cec5SDimitry Andric                                            raw_ostream &O) {
12080b57cec5SDimitry Andric   const MCOperand &Op = MI->getOperand(OpNo);
12090b57cec5SDimitry Andric   assert(Op.isImm() && "System instruction C[nm] operands must be immediates!");
12100b57cec5SDimitry Andric   O << "c" << Op.getImm();
12110b57cec5SDimitry Andric }
12120b57cec5SDimitry Andric 
printAddSubImm(const MCInst * MI,unsigned OpNum,const MCSubtargetInfo & STI,raw_ostream & O)12130b57cec5SDimitry Andric void AArch64InstPrinter::printAddSubImm(const MCInst *MI, unsigned OpNum,
12140b57cec5SDimitry Andric                                         const MCSubtargetInfo &STI,
12150b57cec5SDimitry Andric                                         raw_ostream &O) {
12160b57cec5SDimitry Andric   const MCOperand &MO = MI->getOperand(OpNum);
12170b57cec5SDimitry Andric   if (MO.isImm()) {
12180b57cec5SDimitry Andric     unsigned Val = (MO.getImm() & 0xfff);
12190b57cec5SDimitry Andric     assert(Val == MO.getImm() && "Add/sub immediate out of range!");
12200b57cec5SDimitry Andric     unsigned Shift =
12210b57cec5SDimitry Andric         AArch64_AM::getShiftValue(MI->getOperand(OpNum + 1).getImm());
12225f757f3fSDimitry Andric     markup(O, Markup::Immediate) << '#' << formatImm(Val);
1223349cc55cSDimitry Andric     if (Shift != 0) {
12240b57cec5SDimitry Andric       printShifter(MI, OpNum + 1, STI, O);
12250b57cec5SDimitry Andric       if (CommentStream)
12260b57cec5SDimitry Andric         *CommentStream << '=' << formatImm(Val << Shift) << '\n';
1227349cc55cSDimitry Andric     }
12280b57cec5SDimitry Andric   } else {
12290b57cec5SDimitry Andric     assert(MO.isExpr() && "Unexpected operand type!");
12300b57cec5SDimitry Andric     MO.getExpr()->print(O, &MAI);
12310b57cec5SDimitry Andric     printShifter(MI, OpNum + 1, STI, O);
12320b57cec5SDimitry Andric   }
12330b57cec5SDimitry Andric }
12340b57cec5SDimitry Andric 
12350b57cec5SDimitry Andric template <typename T>
printLogicalImm(const MCInst * MI,unsigned OpNum,const MCSubtargetInfo & STI,raw_ostream & O)12360b57cec5SDimitry Andric void AArch64InstPrinter::printLogicalImm(const MCInst *MI, unsigned OpNum,
12370b57cec5SDimitry Andric                                          const MCSubtargetInfo &STI,
12380b57cec5SDimitry Andric                                          raw_ostream &O) {
12390b57cec5SDimitry Andric   uint64_t Val = MI->getOperand(OpNum).getImm();
12405f757f3fSDimitry Andric   WithMarkup M = markup(O, Markup::Immediate);
12415f757f3fSDimitry Andric   O << "#0x";
12420b57cec5SDimitry Andric   O.write_hex(AArch64_AM::decodeLogicalImmediate(Val, 8 * sizeof(T)));
12430b57cec5SDimitry Andric }
12440b57cec5SDimitry Andric 
printShifter(const MCInst * MI,unsigned OpNum,const MCSubtargetInfo & STI,raw_ostream & O)12450b57cec5SDimitry Andric void AArch64InstPrinter::printShifter(const MCInst *MI, unsigned OpNum,
12460b57cec5SDimitry Andric                                       const MCSubtargetInfo &STI,
12470b57cec5SDimitry Andric                                       raw_ostream &O) {
12480b57cec5SDimitry Andric   unsigned Val = MI->getOperand(OpNum).getImm();
12490b57cec5SDimitry Andric   // LSL #0 should not be printed.
12500b57cec5SDimitry Andric   if (AArch64_AM::getShiftType(Val) == AArch64_AM::LSL &&
12510b57cec5SDimitry Andric       AArch64_AM::getShiftValue(Val) == 0)
12520b57cec5SDimitry Andric     return;
12530b57cec5SDimitry Andric   O << ", " << AArch64_AM::getShiftExtendName(AArch64_AM::getShiftType(Val))
12545f757f3fSDimitry Andric     << " ";
12555f757f3fSDimitry Andric   markup(O, Markup::Immediate) << "#" << AArch64_AM::getShiftValue(Val);
12560b57cec5SDimitry Andric }
12570b57cec5SDimitry Andric 
printShiftedRegister(const MCInst * MI,unsigned OpNum,const MCSubtargetInfo & STI,raw_ostream & O)12580b57cec5SDimitry Andric void AArch64InstPrinter::printShiftedRegister(const MCInst *MI, unsigned OpNum,
12590b57cec5SDimitry Andric                                               const MCSubtargetInfo &STI,
12600b57cec5SDimitry Andric                                               raw_ostream &O) {
1261bdd1243dSDimitry Andric   printRegName(O, MI->getOperand(OpNum).getReg());
12620b57cec5SDimitry Andric   printShifter(MI, OpNum + 1, STI, O);
12630b57cec5SDimitry Andric }
12640b57cec5SDimitry Andric 
printExtendedRegister(const MCInst * MI,unsigned OpNum,const MCSubtargetInfo & STI,raw_ostream & O)12650b57cec5SDimitry Andric void AArch64InstPrinter::printExtendedRegister(const MCInst *MI, unsigned OpNum,
12660b57cec5SDimitry Andric                                                const MCSubtargetInfo &STI,
12670b57cec5SDimitry Andric                                                raw_ostream &O) {
1268bdd1243dSDimitry Andric   printRegName(O, MI->getOperand(OpNum).getReg());
12690b57cec5SDimitry Andric   printArithExtend(MI, OpNum + 1, STI, O);
12700b57cec5SDimitry Andric }
12710b57cec5SDimitry Andric 
printArithExtend(const MCInst * MI,unsigned OpNum,const MCSubtargetInfo & STI,raw_ostream & O)12720b57cec5SDimitry Andric void AArch64InstPrinter::printArithExtend(const MCInst *MI, unsigned OpNum,
12730b57cec5SDimitry Andric                                           const MCSubtargetInfo &STI,
12740b57cec5SDimitry Andric                                           raw_ostream &O) {
12750b57cec5SDimitry Andric   unsigned Val = MI->getOperand(OpNum).getImm();
12760b57cec5SDimitry Andric   AArch64_AM::ShiftExtendType ExtType = AArch64_AM::getArithExtendType(Val);
12770b57cec5SDimitry Andric   unsigned ShiftVal = AArch64_AM::getArithShiftValue(Val);
12780b57cec5SDimitry Andric 
12790b57cec5SDimitry Andric   // If the destination or first source register operand is [W]SP, print
12800b57cec5SDimitry Andric   // UXTW/UXTX as LSL, and if the shift amount is also zero, print nothing at
12810b57cec5SDimitry Andric   // all.
12820b57cec5SDimitry Andric   if (ExtType == AArch64_AM::UXTW || ExtType == AArch64_AM::UXTX) {
12830b57cec5SDimitry Andric     unsigned Dest = MI->getOperand(0).getReg();
12840b57cec5SDimitry Andric     unsigned Src1 = MI->getOperand(1).getReg();
12850b57cec5SDimitry Andric     if ( ((Dest == AArch64::SP || Src1 == AArch64::SP) &&
12860b57cec5SDimitry Andric           ExtType == AArch64_AM::UXTX) ||
12870b57cec5SDimitry Andric          ((Dest == AArch64::WSP || Src1 == AArch64::WSP) &&
12880b57cec5SDimitry Andric           ExtType == AArch64_AM::UXTW) ) {
12895f757f3fSDimitry Andric       if (ShiftVal != 0) {
12905f757f3fSDimitry Andric         O << ", lsl ";
12915f757f3fSDimitry Andric         markup(O, Markup::Immediate) << "#" << ShiftVal;
12925f757f3fSDimitry Andric       }
12930b57cec5SDimitry Andric       return;
12940b57cec5SDimitry Andric     }
12950b57cec5SDimitry Andric   }
12960b57cec5SDimitry Andric   O << ", " << AArch64_AM::getShiftExtendName(ExtType);
12975f757f3fSDimitry Andric   if (ShiftVal != 0) {
12985f757f3fSDimitry Andric     O << " ";
12995f757f3fSDimitry Andric     markup(O, Markup::Immediate) << "#" << ShiftVal;
13005f757f3fSDimitry Andric   }
13010b57cec5SDimitry Andric }
13020b57cec5SDimitry Andric 
printMemExtendImpl(bool SignExtend,bool DoShift,unsigned Width,char SrcRegKind,raw_ostream & O)13035f757f3fSDimitry Andric void AArch64InstPrinter::printMemExtendImpl(bool SignExtend, bool DoShift,
13045f757f3fSDimitry Andric                                             unsigned Width, char SrcRegKind,
13055f757f3fSDimitry Andric                                             raw_ostream &O) {
13060b57cec5SDimitry Andric   // sxtw, sxtx, uxtw or lsl (== uxtx)
13070b57cec5SDimitry Andric   bool IsLSL = !SignExtend && SrcRegKind == 'x';
13080b57cec5SDimitry Andric   if (IsLSL)
13090b57cec5SDimitry Andric     O << "lsl";
13100b57cec5SDimitry Andric   else
13110b57cec5SDimitry Andric     O << (SignExtend ? 's' : 'u') << "xt" << SrcRegKind;
13120b57cec5SDimitry Andric 
1313bdd1243dSDimitry Andric   if (DoShift || IsLSL) {
1314bdd1243dSDimitry Andric     O << " ";
13155f757f3fSDimitry Andric     markup(O, Markup::Immediate) << "#" << Log2_32(Width / 8);
1316bdd1243dSDimitry Andric   }
13170b57cec5SDimitry Andric }
13180b57cec5SDimitry Andric 
printMemExtend(const MCInst * MI,unsigned OpNum,raw_ostream & O,char SrcRegKind,unsigned Width)13190b57cec5SDimitry Andric void AArch64InstPrinter::printMemExtend(const MCInst *MI, unsigned OpNum,
13200b57cec5SDimitry Andric                                         raw_ostream &O, char SrcRegKind,
13210b57cec5SDimitry Andric                                         unsigned Width) {
13220b57cec5SDimitry Andric   bool SignExtend = MI->getOperand(OpNum).getImm();
13230b57cec5SDimitry Andric   bool DoShift = MI->getOperand(OpNum + 1).getImm();
13245f757f3fSDimitry Andric   printMemExtendImpl(SignExtend, DoShift, Width, SrcRegKind, O);
13250b57cec5SDimitry Andric }
13260b57cec5SDimitry Andric 
13270b57cec5SDimitry Andric template <bool SignExtend, int ExtWidth, char SrcRegKind, char Suffix>
printRegWithShiftExtend(const MCInst * MI,unsigned OpNum,const MCSubtargetInfo & STI,raw_ostream & O)13280b57cec5SDimitry Andric void AArch64InstPrinter::printRegWithShiftExtend(const MCInst *MI,
13290b57cec5SDimitry Andric                                                  unsigned OpNum,
13300b57cec5SDimitry Andric                                                  const MCSubtargetInfo &STI,
13310b57cec5SDimitry Andric                                                  raw_ostream &O) {
13320b57cec5SDimitry Andric   printOperand(MI, OpNum, STI, O);
13330b57cec5SDimitry Andric   if (Suffix == 's' || Suffix == 'd')
13340b57cec5SDimitry Andric     O << '.' << Suffix;
13350b57cec5SDimitry Andric   else
13360b57cec5SDimitry Andric     assert(Suffix == 0 && "Unsupported suffix size");
13370b57cec5SDimitry Andric 
13380b57cec5SDimitry Andric   bool DoShift = ExtWidth != 8;
13390b57cec5SDimitry Andric   if (SignExtend || DoShift || SrcRegKind == 'w') {
13400b57cec5SDimitry Andric     O << ", ";
13415f757f3fSDimitry Andric     printMemExtendImpl(SignExtend, DoShift, ExtWidth, SrcRegKind, O);
1342bdd1243dSDimitry Andric   }
1343bdd1243dSDimitry Andric }
1344bdd1243dSDimitry Andric 
1345bdd1243dSDimitry Andric template <int EltSize>
printPredicateAsCounter(const MCInst * MI,unsigned OpNum,const MCSubtargetInfo & STI,raw_ostream & O)1346bdd1243dSDimitry Andric void AArch64InstPrinter::printPredicateAsCounter(const MCInst *MI,
1347bdd1243dSDimitry Andric                                                  unsigned OpNum,
1348bdd1243dSDimitry Andric                                                  const MCSubtargetInfo &STI,
1349bdd1243dSDimitry Andric                                                  raw_ostream &O) {
1350bdd1243dSDimitry Andric   unsigned Reg = MI->getOperand(OpNum).getReg();
13515f757f3fSDimitry Andric   if (Reg < AArch64::PN0 || Reg > AArch64::PN15)
13525f757f3fSDimitry Andric     llvm_unreachable("Unsupported predicate-as-counter register");
13535f757f3fSDimitry Andric   O << "pn" << Reg - AArch64::PN0;
1354bdd1243dSDimitry Andric 
1355bdd1243dSDimitry Andric   switch (EltSize) {
1356bdd1243dSDimitry Andric   case 0:
1357bdd1243dSDimitry Andric     break;
1358bdd1243dSDimitry Andric   case 8:
1359bdd1243dSDimitry Andric     O << ".b";
1360bdd1243dSDimitry Andric     break;
1361bdd1243dSDimitry Andric   case 16:
1362bdd1243dSDimitry Andric     O << ".h";
1363bdd1243dSDimitry Andric     break;
1364bdd1243dSDimitry Andric   case 32:
1365bdd1243dSDimitry Andric     O << ".s";
1366bdd1243dSDimitry Andric     break;
1367bdd1243dSDimitry Andric   case 64:
1368bdd1243dSDimitry Andric     O << ".d";
1369bdd1243dSDimitry Andric     break;
1370bdd1243dSDimitry Andric   default:
1371bdd1243dSDimitry Andric     llvm_unreachable("Unsupported element size");
13720b57cec5SDimitry Andric   }
13730b57cec5SDimitry Andric }
13740b57cec5SDimitry Andric 
printCondCode(const MCInst * MI,unsigned OpNum,const MCSubtargetInfo & STI,raw_ostream & O)13750b57cec5SDimitry Andric void AArch64InstPrinter::printCondCode(const MCInst *MI, unsigned OpNum,
13760b57cec5SDimitry Andric                                        const MCSubtargetInfo &STI,
13770b57cec5SDimitry Andric                                        raw_ostream &O) {
13780b57cec5SDimitry Andric   AArch64CC::CondCode CC = (AArch64CC::CondCode)MI->getOperand(OpNum).getImm();
13790b57cec5SDimitry Andric   O << AArch64CC::getCondCodeName(CC);
13800b57cec5SDimitry Andric }
13810b57cec5SDimitry Andric 
printInverseCondCode(const MCInst * MI,unsigned OpNum,const MCSubtargetInfo & STI,raw_ostream & O)13820b57cec5SDimitry Andric void AArch64InstPrinter::printInverseCondCode(const MCInst *MI, unsigned OpNum,
13830b57cec5SDimitry Andric                                               const MCSubtargetInfo &STI,
13840b57cec5SDimitry Andric                                               raw_ostream &O) {
13850b57cec5SDimitry Andric   AArch64CC::CondCode CC = (AArch64CC::CondCode)MI->getOperand(OpNum).getImm();
13860b57cec5SDimitry Andric   O << AArch64CC::getCondCodeName(AArch64CC::getInvertedCondCode(CC));
13870b57cec5SDimitry Andric }
13880b57cec5SDimitry Andric 
printAMNoIndex(const MCInst * MI,unsigned OpNum,const MCSubtargetInfo & STI,raw_ostream & O)13890b57cec5SDimitry Andric void AArch64InstPrinter::printAMNoIndex(const MCInst *MI, unsigned OpNum,
13900b57cec5SDimitry Andric                                         const MCSubtargetInfo &STI,
13910b57cec5SDimitry Andric                                         raw_ostream &O) {
1392bdd1243dSDimitry Andric   O << '[';
1393bdd1243dSDimitry Andric   printRegName(O, MI->getOperand(OpNum).getReg());
1394bdd1243dSDimitry Andric   O << ']';
13950b57cec5SDimitry Andric }
13960b57cec5SDimitry Andric 
13970b57cec5SDimitry Andric template <int Scale>
printImmScale(const MCInst * MI,unsigned OpNum,const MCSubtargetInfo & STI,raw_ostream & O)13980b57cec5SDimitry Andric void AArch64InstPrinter::printImmScale(const MCInst *MI, unsigned OpNum,
13990b57cec5SDimitry Andric                                        const MCSubtargetInfo &STI,
14000b57cec5SDimitry Andric                                        raw_ostream &O) {
14015f757f3fSDimitry Andric   markup(O, Markup::Immediate)
14025f757f3fSDimitry Andric       << '#' << formatImm(Scale * MI->getOperand(OpNum).getImm());
1403bdd1243dSDimitry Andric }
1404bdd1243dSDimitry Andric 
1405bdd1243dSDimitry Andric template <int Scale, int Offset>
printImmRangeScale(const MCInst * MI,unsigned OpNum,const MCSubtargetInfo & STI,raw_ostream & O)1406bdd1243dSDimitry Andric void AArch64InstPrinter::printImmRangeScale(const MCInst *MI, unsigned OpNum,
1407bdd1243dSDimitry Andric                                             const MCSubtargetInfo &STI,
1408bdd1243dSDimitry Andric                                             raw_ostream &O) {
1409bdd1243dSDimitry Andric   unsigned FirstImm = Scale * MI->getOperand(OpNum).getImm();
1410bdd1243dSDimitry Andric   O << formatImm(FirstImm);
1411bdd1243dSDimitry Andric   O << ":" << formatImm(FirstImm + Offset);
14120b57cec5SDimitry Andric }
14130b57cec5SDimitry Andric 
printUImm12Offset(const MCInst * MI,unsigned OpNum,unsigned Scale,raw_ostream & O)14140b57cec5SDimitry Andric void AArch64InstPrinter::printUImm12Offset(const MCInst *MI, unsigned OpNum,
14150b57cec5SDimitry Andric                                            unsigned Scale, raw_ostream &O) {
14160b57cec5SDimitry Andric   const MCOperand MO = MI->getOperand(OpNum);
14170b57cec5SDimitry Andric   if (MO.isImm()) {
14185f757f3fSDimitry Andric     markup(O, Markup::Immediate) << '#' << formatImm(MO.getImm() * Scale);
14190b57cec5SDimitry Andric   } else {
14200b57cec5SDimitry Andric     assert(MO.isExpr() && "Unexpected operand type!");
14210b57cec5SDimitry Andric     MO.getExpr()->print(O, &MAI);
14220b57cec5SDimitry Andric   }
14230b57cec5SDimitry Andric }
14240b57cec5SDimitry Andric 
printAMIndexedWB(const MCInst * MI,unsigned OpNum,unsigned Scale,raw_ostream & O)14250b57cec5SDimitry Andric void AArch64InstPrinter::printAMIndexedWB(const MCInst *MI, unsigned OpNum,
14260b57cec5SDimitry Andric                                           unsigned Scale, raw_ostream &O) {
14270b57cec5SDimitry Andric   const MCOperand MO1 = MI->getOperand(OpNum + 1);
1428bdd1243dSDimitry Andric   O << '[';
1429bdd1243dSDimitry Andric   printRegName(O, MI->getOperand(OpNum).getReg());
14300b57cec5SDimitry Andric   if (MO1.isImm()) {
14315f757f3fSDimitry Andric     O << ", ";
14325f757f3fSDimitry Andric     markup(O, Markup::Immediate) << "#" << formatImm(MO1.getImm() * Scale);
14330b57cec5SDimitry Andric   } else {
14340b57cec5SDimitry Andric     assert(MO1.isExpr() && "Unexpected operand type!");
14350b57cec5SDimitry Andric     O << ", ";
14360b57cec5SDimitry Andric     MO1.getExpr()->print(O, &MAI);
14370b57cec5SDimitry Andric   }
14380b57cec5SDimitry Andric   O << ']';
14390b57cec5SDimitry Andric }
14400b57cec5SDimitry Andric 
printRPRFMOperand(const MCInst * MI,unsigned OpNum,const MCSubtargetInfo & STI,raw_ostream & O)1441bdd1243dSDimitry Andric void AArch64InstPrinter::printRPRFMOperand(const MCInst *MI, unsigned OpNum,
1442bdd1243dSDimitry Andric                                            const MCSubtargetInfo &STI,
1443bdd1243dSDimitry Andric                                            raw_ostream &O) {
1444bdd1243dSDimitry Andric   unsigned prfop = MI->getOperand(OpNum).getImm();
1445bdd1243dSDimitry Andric   if (auto PRFM = AArch64RPRFM::lookupRPRFMByEncoding(prfop)) {
1446bdd1243dSDimitry Andric     O << PRFM->Name;
1447bdd1243dSDimitry Andric     return;
1448bdd1243dSDimitry Andric   }
1449bdd1243dSDimitry Andric 
1450bdd1243dSDimitry Andric   O << '#' << formatImm(prfop);
1451bdd1243dSDimitry Andric }
1452bdd1243dSDimitry Andric 
14530b57cec5SDimitry Andric template <bool IsSVEPrefetch>
printPrefetchOp(const MCInst * MI,unsigned OpNum,const MCSubtargetInfo & STI,raw_ostream & O)14540b57cec5SDimitry Andric void AArch64InstPrinter::printPrefetchOp(const MCInst *MI, unsigned OpNum,
14550b57cec5SDimitry Andric                                          const MCSubtargetInfo &STI,
14560b57cec5SDimitry Andric                                          raw_ostream &O) {
14570b57cec5SDimitry Andric   unsigned prfop = MI->getOperand(OpNum).getImm();
14580b57cec5SDimitry Andric   if (IsSVEPrefetch) {
14590b57cec5SDimitry Andric     if (auto PRFM = AArch64SVEPRFM::lookupSVEPRFMByEncoding(prfop)) {
14600b57cec5SDimitry Andric       O << PRFM->Name;
14610b57cec5SDimitry Andric       return;
14620b57cec5SDimitry Andric     }
1463bdd1243dSDimitry Andric   } else {
1464bdd1243dSDimitry Andric     auto PRFM = AArch64PRFM::lookupPRFMByEncoding(prfop);
1465bdd1243dSDimitry Andric     if (PRFM && PRFM->haveFeatures(STI.getFeatureBits())) {
14660b57cec5SDimitry Andric       O << PRFM->Name;
14670b57cec5SDimitry Andric       return;
14680b57cec5SDimitry Andric     }
1469bdd1243dSDimitry Andric   }
14700b57cec5SDimitry Andric 
14715f757f3fSDimitry Andric   markup(O, Markup::Immediate) << '#' << formatImm(prfop);
14720b57cec5SDimitry Andric }
14730b57cec5SDimitry Andric 
printPSBHintOp(const MCInst * MI,unsigned OpNum,const MCSubtargetInfo & STI,raw_ostream & O)14740b57cec5SDimitry Andric void AArch64InstPrinter::printPSBHintOp(const MCInst *MI, unsigned OpNum,
14750b57cec5SDimitry Andric                                         const MCSubtargetInfo &STI,
14760b57cec5SDimitry Andric                                         raw_ostream &O) {
14770b57cec5SDimitry Andric   unsigned psbhintop = MI->getOperand(OpNum).getImm();
14780b57cec5SDimitry Andric   auto PSB = AArch64PSBHint::lookupPSBByEncoding(psbhintop);
14790b57cec5SDimitry Andric   if (PSB)
14800b57cec5SDimitry Andric     O << PSB->Name;
14810b57cec5SDimitry Andric   else
14825f757f3fSDimitry Andric     markup(O, Markup::Immediate) << '#' << formatImm(psbhintop);
14830b57cec5SDimitry Andric }
14840b57cec5SDimitry Andric 
printBTIHintOp(const MCInst * MI,unsigned OpNum,const MCSubtargetInfo & STI,raw_ostream & O)14850b57cec5SDimitry Andric void AArch64InstPrinter::printBTIHintOp(const MCInst *MI, unsigned OpNum,
14860b57cec5SDimitry Andric                                         const MCSubtargetInfo &STI,
14870b57cec5SDimitry Andric                                         raw_ostream &O) {
1488fe6060f1SDimitry Andric   unsigned btihintop = MI->getOperand(OpNum).getImm() ^ 32;
14890b57cec5SDimitry Andric   auto BTI = AArch64BTIHint::lookupBTIByEncoding(btihintop);
14900b57cec5SDimitry Andric   if (BTI)
14910b57cec5SDimitry Andric     O << BTI->Name;
14920b57cec5SDimitry Andric   else
14935f757f3fSDimitry Andric     markup(O, Markup::Immediate) << '#' << formatImm(btihintop);
14940b57cec5SDimitry Andric }
14950b57cec5SDimitry Andric 
printFPImmOperand(const MCInst * MI,unsigned OpNum,const MCSubtargetInfo & STI,raw_ostream & O)14960b57cec5SDimitry Andric void AArch64InstPrinter::printFPImmOperand(const MCInst *MI, unsigned OpNum,
14970b57cec5SDimitry Andric                                            const MCSubtargetInfo &STI,
14980b57cec5SDimitry Andric                                            raw_ostream &O) {
14990b57cec5SDimitry Andric   const MCOperand &MO = MI->getOperand(OpNum);
1500fe6060f1SDimitry Andric   float FPImm = MO.isDFPImm() ? bit_cast<double>(MO.getDFPImm())
1501fe6060f1SDimitry Andric                               : AArch64_AM::getFPImmFloat(MO.getImm());
15020b57cec5SDimitry Andric 
15030b57cec5SDimitry Andric   // 8 decimal places are enough to perfectly represent permitted floats.
15045f757f3fSDimitry Andric   markup(O, Markup::Immediate) << format("#%.8f", FPImm);
15050b57cec5SDimitry Andric }
15060b57cec5SDimitry Andric 
getNextVectorRegister(unsigned Reg,unsigned Stride=1)15070b57cec5SDimitry Andric static unsigned getNextVectorRegister(unsigned Reg, unsigned Stride = 1) {
15080b57cec5SDimitry Andric   while (Stride--) {
15090b57cec5SDimitry Andric     switch (Reg) {
15100b57cec5SDimitry Andric     default:
15110b57cec5SDimitry Andric       llvm_unreachable("Vector register expected!");
15120b57cec5SDimitry Andric     case AArch64::Q0:  Reg = AArch64::Q1;  break;
15130b57cec5SDimitry Andric     case AArch64::Q1:  Reg = AArch64::Q2;  break;
15140b57cec5SDimitry Andric     case AArch64::Q2:  Reg = AArch64::Q3;  break;
15150b57cec5SDimitry Andric     case AArch64::Q3:  Reg = AArch64::Q4;  break;
15160b57cec5SDimitry Andric     case AArch64::Q4:  Reg = AArch64::Q5;  break;
15170b57cec5SDimitry Andric     case AArch64::Q5:  Reg = AArch64::Q6;  break;
15180b57cec5SDimitry Andric     case AArch64::Q6:  Reg = AArch64::Q7;  break;
15190b57cec5SDimitry Andric     case AArch64::Q7:  Reg = AArch64::Q8;  break;
15200b57cec5SDimitry Andric     case AArch64::Q8:  Reg = AArch64::Q9;  break;
15210b57cec5SDimitry Andric     case AArch64::Q9:  Reg = AArch64::Q10; break;
15220b57cec5SDimitry Andric     case AArch64::Q10: Reg = AArch64::Q11; break;
15230b57cec5SDimitry Andric     case AArch64::Q11: Reg = AArch64::Q12; break;
15240b57cec5SDimitry Andric     case AArch64::Q12: Reg = AArch64::Q13; break;
15250b57cec5SDimitry Andric     case AArch64::Q13: Reg = AArch64::Q14; break;
15260b57cec5SDimitry Andric     case AArch64::Q14: Reg = AArch64::Q15; break;
15270b57cec5SDimitry Andric     case AArch64::Q15: Reg = AArch64::Q16; break;
15280b57cec5SDimitry Andric     case AArch64::Q16: Reg = AArch64::Q17; break;
15290b57cec5SDimitry Andric     case AArch64::Q17: Reg = AArch64::Q18; break;
15300b57cec5SDimitry Andric     case AArch64::Q18: Reg = AArch64::Q19; break;
15310b57cec5SDimitry Andric     case AArch64::Q19: Reg = AArch64::Q20; break;
15320b57cec5SDimitry Andric     case AArch64::Q20: Reg = AArch64::Q21; break;
15330b57cec5SDimitry Andric     case AArch64::Q21: Reg = AArch64::Q22; break;
15340b57cec5SDimitry Andric     case AArch64::Q22: Reg = AArch64::Q23; break;
15350b57cec5SDimitry Andric     case AArch64::Q23: Reg = AArch64::Q24; break;
15360b57cec5SDimitry Andric     case AArch64::Q24: Reg = AArch64::Q25; break;
15370b57cec5SDimitry Andric     case AArch64::Q25: Reg = AArch64::Q26; break;
15380b57cec5SDimitry Andric     case AArch64::Q26: Reg = AArch64::Q27; break;
15390b57cec5SDimitry Andric     case AArch64::Q27: Reg = AArch64::Q28; break;
15400b57cec5SDimitry Andric     case AArch64::Q28: Reg = AArch64::Q29; break;
15410b57cec5SDimitry Andric     case AArch64::Q29: Reg = AArch64::Q30; break;
15420b57cec5SDimitry Andric     case AArch64::Q30: Reg = AArch64::Q31; break;
15430b57cec5SDimitry Andric     // Vector lists can wrap around.
15440b57cec5SDimitry Andric     case AArch64::Q31:
15450b57cec5SDimitry Andric       Reg = AArch64::Q0;
15460b57cec5SDimitry Andric       break;
15470b57cec5SDimitry Andric     case AArch64::Z0:  Reg = AArch64::Z1;  break;
15480b57cec5SDimitry Andric     case AArch64::Z1:  Reg = AArch64::Z2;  break;
15490b57cec5SDimitry Andric     case AArch64::Z2:  Reg = AArch64::Z3;  break;
15500b57cec5SDimitry Andric     case AArch64::Z3:  Reg = AArch64::Z4;  break;
15510b57cec5SDimitry Andric     case AArch64::Z4:  Reg = AArch64::Z5;  break;
15520b57cec5SDimitry Andric     case AArch64::Z5:  Reg = AArch64::Z6;  break;
15530b57cec5SDimitry Andric     case AArch64::Z6:  Reg = AArch64::Z7;  break;
15540b57cec5SDimitry Andric     case AArch64::Z7:  Reg = AArch64::Z8;  break;
15550b57cec5SDimitry Andric     case AArch64::Z8:  Reg = AArch64::Z9;  break;
15560b57cec5SDimitry Andric     case AArch64::Z9:  Reg = AArch64::Z10; break;
15570b57cec5SDimitry Andric     case AArch64::Z10: Reg = AArch64::Z11; break;
15580b57cec5SDimitry Andric     case AArch64::Z11: Reg = AArch64::Z12; break;
15590b57cec5SDimitry Andric     case AArch64::Z12: Reg = AArch64::Z13; break;
15600b57cec5SDimitry Andric     case AArch64::Z13: Reg = AArch64::Z14; break;
15610b57cec5SDimitry Andric     case AArch64::Z14: Reg = AArch64::Z15; break;
15620b57cec5SDimitry Andric     case AArch64::Z15: Reg = AArch64::Z16; break;
15630b57cec5SDimitry Andric     case AArch64::Z16: Reg = AArch64::Z17; break;
15640b57cec5SDimitry Andric     case AArch64::Z17: Reg = AArch64::Z18; break;
15650b57cec5SDimitry Andric     case AArch64::Z18: Reg = AArch64::Z19; break;
15660b57cec5SDimitry Andric     case AArch64::Z19: Reg = AArch64::Z20; break;
15670b57cec5SDimitry Andric     case AArch64::Z20: Reg = AArch64::Z21; break;
15680b57cec5SDimitry Andric     case AArch64::Z21: Reg = AArch64::Z22; break;
15690b57cec5SDimitry Andric     case AArch64::Z22: Reg = AArch64::Z23; break;
15700b57cec5SDimitry Andric     case AArch64::Z23: Reg = AArch64::Z24; break;
15710b57cec5SDimitry Andric     case AArch64::Z24: Reg = AArch64::Z25; break;
15720b57cec5SDimitry Andric     case AArch64::Z25: Reg = AArch64::Z26; break;
15730b57cec5SDimitry Andric     case AArch64::Z26: Reg = AArch64::Z27; break;
15740b57cec5SDimitry Andric     case AArch64::Z27: Reg = AArch64::Z28; break;
15750b57cec5SDimitry Andric     case AArch64::Z28: Reg = AArch64::Z29; break;
15760b57cec5SDimitry Andric     case AArch64::Z29: Reg = AArch64::Z30; break;
15770b57cec5SDimitry Andric     case AArch64::Z30: Reg = AArch64::Z31; break;
15780b57cec5SDimitry Andric     // Vector lists can wrap around.
15790b57cec5SDimitry Andric     case AArch64::Z31:
15800b57cec5SDimitry Andric       Reg = AArch64::Z0;
15810b57cec5SDimitry Andric       break;
1582bdd1243dSDimitry Andric     case AArch64::P0:  Reg = AArch64::P1;  break;
1583bdd1243dSDimitry Andric     case AArch64::P1:  Reg = AArch64::P2;  break;
1584bdd1243dSDimitry Andric     case AArch64::P2:  Reg = AArch64::P3;  break;
1585bdd1243dSDimitry Andric     case AArch64::P3:  Reg = AArch64::P4;  break;
1586bdd1243dSDimitry Andric     case AArch64::P4:  Reg = AArch64::P5;  break;
1587bdd1243dSDimitry Andric     case AArch64::P5:  Reg = AArch64::P6;  break;
1588bdd1243dSDimitry Andric     case AArch64::P6:  Reg = AArch64::P7;  break;
1589bdd1243dSDimitry Andric     case AArch64::P7:  Reg = AArch64::P8;  break;
1590bdd1243dSDimitry Andric     case AArch64::P8:  Reg = AArch64::P9;  break;
1591bdd1243dSDimitry Andric     case AArch64::P9:  Reg = AArch64::P10; break;
1592bdd1243dSDimitry Andric     case AArch64::P10: Reg = AArch64::P11; break;
1593bdd1243dSDimitry Andric     case AArch64::P11: Reg = AArch64::P12; break;
1594bdd1243dSDimitry Andric     case AArch64::P12: Reg = AArch64::P13; break;
1595bdd1243dSDimitry Andric     case AArch64::P13: Reg = AArch64::P14; break;
1596bdd1243dSDimitry Andric     case AArch64::P14: Reg = AArch64::P15; break;
1597bdd1243dSDimitry Andric     // Vector lists can wrap around.
1598bdd1243dSDimitry Andric     case AArch64::P15: Reg = AArch64::P0; break;
15990b57cec5SDimitry Andric     }
16000b57cec5SDimitry Andric   }
16010b57cec5SDimitry Andric   return Reg;
16020b57cec5SDimitry Andric }
16030b57cec5SDimitry Andric 
16040b57cec5SDimitry Andric template<unsigned size>
printGPRSeqPairsClassOperand(const MCInst * MI,unsigned OpNum,const MCSubtargetInfo & STI,raw_ostream & O)16050b57cec5SDimitry Andric void AArch64InstPrinter::printGPRSeqPairsClassOperand(const MCInst *MI,
16060b57cec5SDimitry Andric                                                    unsigned OpNum,
16070b57cec5SDimitry Andric                                                    const MCSubtargetInfo &STI,
16080b57cec5SDimitry Andric                                                    raw_ostream &O) {
16090b57cec5SDimitry Andric   static_assert(size == 64 || size == 32,
16100b57cec5SDimitry Andric                 "Template parameter must be either 32 or 64");
16110b57cec5SDimitry Andric   unsigned Reg = MI->getOperand(OpNum).getReg();
16120b57cec5SDimitry Andric 
16130b57cec5SDimitry Andric   unsigned Sube = (size == 32) ? AArch64::sube32 : AArch64::sube64;
16140b57cec5SDimitry Andric   unsigned Subo = (size == 32) ? AArch64::subo32 : AArch64::subo64;
16150b57cec5SDimitry Andric 
16160b57cec5SDimitry Andric   unsigned Even = MRI.getSubReg(Reg,  Sube);
16170b57cec5SDimitry Andric   unsigned Odd = MRI.getSubReg(Reg,  Subo);
1618bdd1243dSDimitry Andric   printRegName(O, Even);
1619bdd1243dSDimitry Andric   O << ", ";
1620bdd1243dSDimitry Andric   printRegName(O, Odd);
16210b57cec5SDimitry Andric }
16220b57cec5SDimitry Andric 
printMatrixTileList(const MCInst * MI,unsigned OpNum,const MCSubtargetInfo & STI,raw_ostream & O)1623fe6060f1SDimitry Andric void AArch64InstPrinter::printMatrixTileList(const MCInst *MI, unsigned OpNum,
1624fe6060f1SDimitry Andric                                              const MCSubtargetInfo &STI,
1625fe6060f1SDimitry Andric                                              raw_ostream &O) {
1626fe6060f1SDimitry Andric   unsigned MaxRegs = 8;
1627fe6060f1SDimitry Andric   unsigned RegMask = MI->getOperand(OpNum).getImm();
1628fe6060f1SDimitry Andric 
1629fe6060f1SDimitry Andric   unsigned NumRegs = 0;
1630fe6060f1SDimitry Andric   for (unsigned I = 0; I < MaxRegs; ++I)
1631fe6060f1SDimitry Andric     if ((RegMask & (1 << I)) != 0)
1632fe6060f1SDimitry Andric       ++NumRegs;
1633fe6060f1SDimitry Andric 
1634fe6060f1SDimitry Andric   O << "{";
1635fe6060f1SDimitry Andric   unsigned Printed = 0;
1636fe6060f1SDimitry Andric   for (unsigned I = 0; I < MaxRegs; ++I) {
1637fe6060f1SDimitry Andric     unsigned Reg = RegMask & (1 << I);
1638fe6060f1SDimitry Andric     if (Reg == 0)
1639fe6060f1SDimitry Andric       continue;
1640bdd1243dSDimitry Andric     printRegName(O, AArch64::ZAD0 + I);
1641fe6060f1SDimitry Andric     if (Printed + 1 != NumRegs)
1642fe6060f1SDimitry Andric       O << ", ";
1643fe6060f1SDimitry Andric     ++Printed;
1644fe6060f1SDimitry Andric   }
1645fe6060f1SDimitry Andric   O << "}";
1646fe6060f1SDimitry Andric }
1647fe6060f1SDimitry Andric 
printVectorList(const MCInst * MI,unsigned OpNum,const MCSubtargetInfo & STI,raw_ostream & O,StringRef LayoutSuffix)16480b57cec5SDimitry Andric void AArch64InstPrinter::printVectorList(const MCInst *MI, unsigned OpNum,
16490b57cec5SDimitry Andric                                          const MCSubtargetInfo &STI,
16500b57cec5SDimitry Andric                                          raw_ostream &O,
16510b57cec5SDimitry Andric                                          StringRef LayoutSuffix) {
16520b57cec5SDimitry Andric   unsigned Reg = MI->getOperand(OpNum).getReg();
16530b57cec5SDimitry Andric 
16540b57cec5SDimitry Andric   O << "{ ";
16550b57cec5SDimitry Andric 
16560b57cec5SDimitry Andric   // Work out how many registers there are in the list (if there is an actual
16570b57cec5SDimitry Andric   // list).
16580b57cec5SDimitry Andric   unsigned NumRegs = 1;
16590b57cec5SDimitry Andric   if (MRI.getRegClass(AArch64::DDRegClassID).contains(Reg) ||
16600b57cec5SDimitry Andric       MRI.getRegClass(AArch64::ZPR2RegClassID).contains(Reg) ||
1661bdd1243dSDimitry Andric       MRI.getRegClass(AArch64::QQRegClassID).contains(Reg) ||
1662bdd1243dSDimitry Andric       MRI.getRegClass(AArch64::PPR2RegClassID).contains(Reg) ||
1663bdd1243dSDimitry Andric       MRI.getRegClass(AArch64::ZPR2StridedRegClassID).contains(Reg))
16640b57cec5SDimitry Andric     NumRegs = 2;
16650b57cec5SDimitry Andric   else if (MRI.getRegClass(AArch64::DDDRegClassID).contains(Reg) ||
16660b57cec5SDimitry Andric            MRI.getRegClass(AArch64::ZPR3RegClassID).contains(Reg) ||
16670b57cec5SDimitry Andric            MRI.getRegClass(AArch64::QQQRegClassID).contains(Reg))
16680b57cec5SDimitry Andric     NumRegs = 3;
16690b57cec5SDimitry Andric   else if (MRI.getRegClass(AArch64::DDDDRegClassID).contains(Reg) ||
16700b57cec5SDimitry Andric            MRI.getRegClass(AArch64::ZPR4RegClassID).contains(Reg) ||
1671bdd1243dSDimitry Andric            MRI.getRegClass(AArch64::QQQQRegClassID).contains(Reg) ||
1672bdd1243dSDimitry Andric            MRI.getRegClass(AArch64::ZPR4StridedRegClassID).contains(Reg))
16730b57cec5SDimitry Andric     NumRegs = 4;
16740b57cec5SDimitry Andric 
1675bdd1243dSDimitry Andric   unsigned Stride = 1;
1676bdd1243dSDimitry Andric   if (MRI.getRegClass(AArch64::ZPR2StridedRegClassID).contains(Reg))
1677bdd1243dSDimitry Andric     Stride = 8;
1678bdd1243dSDimitry Andric   else if (MRI.getRegClass(AArch64::ZPR4StridedRegClassID).contains(Reg))
1679bdd1243dSDimitry Andric     Stride = 4;
1680bdd1243dSDimitry Andric 
16810b57cec5SDimitry Andric   // Now forget about the list and find out what the first register is.
16820b57cec5SDimitry Andric   if (unsigned FirstReg = MRI.getSubReg(Reg, AArch64::dsub0))
16830b57cec5SDimitry Andric     Reg = FirstReg;
16840b57cec5SDimitry Andric   else if (unsigned FirstReg = MRI.getSubReg(Reg, AArch64::qsub0))
16850b57cec5SDimitry Andric     Reg = FirstReg;
16860b57cec5SDimitry Andric   else if (unsigned FirstReg = MRI.getSubReg(Reg, AArch64::zsub0))
16870b57cec5SDimitry Andric     Reg = FirstReg;
1688bdd1243dSDimitry Andric   else if (unsigned FirstReg = MRI.getSubReg(Reg, AArch64::psub0))
1689bdd1243dSDimitry Andric     Reg = FirstReg;
16900b57cec5SDimitry Andric 
16910b57cec5SDimitry Andric   // If it's a D-reg, we need to promote it to the equivalent Q-reg before
16920b57cec5SDimitry Andric   // printing (otherwise getRegisterName fails).
16930b57cec5SDimitry Andric   if (MRI.getRegClass(AArch64::FPR64RegClassID).contains(Reg)) {
16940b57cec5SDimitry Andric     const MCRegisterClass &FPR128RC =
16950b57cec5SDimitry Andric         MRI.getRegClass(AArch64::FPR128RegClassID);
16960b57cec5SDimitry Andric     Reg = MRI.getMatchingSuperReg(Reg, AArch64::dsub, &FPR128RC);
16970b57cec5SDimitry Andric   }
16980b57cec5SDimitry Andric 
1699bdd1243dSDimitry Andric   if ((MRI.getRegClass(AArch64::ZPRRegClassID).contains(Reg) ||
1700bdd1243dSDimitry Andric        MRI.getRegClass(AArch64::PPRRegClassID).contains(Reg)) &&
1701bdd1243dSDimitry Andric       NumRegs > 1 && Stride == 1 &&
1702bdd1243dSDimitry Andric       // Do not print the range when the last register is lower than the first.
1703bdd1243dSDimitry Andric       // Because it is a wrap-around register.
1704bdd1243dSDimitry Andric       Reg < getNextVectorRegister(Reg, NumRegs - 1)) {
1705bdd1243dSDimitry Andric     printRegName(O, Reg);
1706bdd1243dSDimitry Andric     O << LayoutSuffix;
1707bdd1243dSDimitry Andric     if (NumRegs > 1) {
1708bdd1243dSDimitry Andric       // Set of two sve registers should be separated by ','
1709bdd1243dSDimitry Andric       StringRef split_char = NumRegs == 2 ? ", " : " - ";
1710bdd1243dSDimitry Andric       O << split_char;
1711bdd1243dSDimitry Andric       printRegName(O, (getNextVectorRegister(Reg, NumRegs - 1)));
1712bdd1243dSDimitry Andric       O << LayoutSuffix;
1713bdd1243dSDimitry Andric     }
1714bdd1243dSDimitry Andric   } else {
1715bdd1243dSDimitry Andric     for (unsigned i = 0; i < NumRegs;
1716bdd1243dSDimitry Andric          ++i, Reg = getNextVectorRegister(Reg, Stride)) {
1717bdd1243dSDimitry Andric       // wrap-around sve register
1718bdd1243dSDimitry Andric       if (MRI.getRegClass(AArch64::ZPRRegClassID).contains(Reg) ||
1719bdd1243dSDimitry Andric           MRI.getRegClass(AArch64::PPRRegClassID).contains(Reg))
1720bdd1243dSDimitry Andric         printRegName(O, Reg);
17210b57cec5SDimitry Andric       else
1722bdd1243dSDimitry Andric         printRegName(O, Reg, AArch64::vreg);
1723bdd1243dSDimitry Andric       O << LayoutSuffix;
17240b57cec5SDimitry Andric       if (i + 1 != NumRegs)
17250b57cec5SDimitry Andric         O << ", ";
17260b57cec5SDimitry Andric     }
1727bdd1243dSDimitry Andric   }
17280b57cec5SDimitry Andric   O << " }";
17290b57cec5SDimitry Andric }
17300b57cec5SDimitry Andric 
17310b57cec5SDimitry Andric void
printImplicitlyTypedVectorList(const MCInst * MI,unsigned OpNum,const MCSubtargetInfo & STI,raw_ostream & O)17320b57cec5SDimitry Andric AArch64InstPrinter::printImplicitlyTypedVectorList(const MCInst *MI,
17330b57cec5SDimitry Andric                                                    unsigned OpNum,
17340b57cec5SDimitry Andric                                                    const MCSubtargetInfo &STI,
17350b57cec5SDimitry Andric                                                    raw_ostream &O) {
17360b57cec5SDimitry Andric   printVectorList(MI, OpNum, STI, O, "");
17370b57cec5SDimitry Andric }
17380b57cec5SDimitry Andric 
17390b57cec5SDimitry Andric template <unsigned NumLanes, char LaneKind>
printTypedVectorList(const MCInst * MI,unsigned OpNum,const MCSubtargetInfo & STI,raw_ostream & O)17400b57cec5SDimitry Andric void AArch64InstPrinter::printTypedVectorList(const MCInst *MI, unsigned OpNum,
17410b57cec5SDimitry Andric                                               const MCSubtargetInfo &STI,
17420b57cec5SDimitry Andric                                               raw_ostream &O) {
17435f757f3fSDimitry Andric   if (LaneKind == 0) {
17445f757f3fSDimitry Andric     printVectorList(MI, OpNum, STI, O, "");
17455f757f3fSDimitry Andric     return;
17465f757f3fSDimitry Andric   }
17470b57cec5SDimitry Andric   std::string Suffix(".");
17480b57cec5SDimitry Andric   if (NumLanes)
17490b57cec5SDimitry Andric     Suffix += itostr(NumLanes) + LaneKind;
17500b57cec5SDimitry Andric   else
17510b57cec5SDimitry Andric     Suffix += LaneKind;
17520b57cec5SDimitry Andric 
17530b57cec5SDimitry Andric   printVectorList(MI, OpNum, STI, O, Suffix);
17540b57cec5SDimitry Andric }
17550b57cec5SDimitry Andric 
1756bdd1243dSDimitry Andric template <unsigned Scale>
printVectorIndex(const MCInst * MI,unsigned OpNum,const MCSubtargetInfo & STI,raw_ostream & O)17570b57cec5SDimitry Andric void AArch64InstPrinter::printVectorIndex(const MCInst *MI, unsigned OpNum,
17580b57cec5SDimitry Andric                                           const MCSubtargetInfo &STI,
17590b57cec5SDimitry Andric                                           raw_ostream &O) {
1760bdd1243dSDimitry Andric   O << "[" << Scale * MI->getOperand(OpNum).getImm() << "]";
17610b57cec5SDimitry Andric }
17620b57cec5SDimitry Andric 
17635f757f3fSDimitry Andric template <unsigned Scale>
printMatrixIndex(const MCInst * MI,unsigned OpNum,const MCSubtargetInfo & STI,raw_ostream & O)1764349cc55cSDimitry Andric void AArch64InstPrinter::printMatrixIndex(const MCInst *MI, unsigned OpNum,
1765349cc55cSDimitry Andric                                           const MCSubtargetInfo &STI,
1766349cc55cSDimitry Andric                                           raw_ostream &O) {
17675f757f3fSDimitry Andric   O << Scale * MI->getOperand(OpNum).getImm();
1768349cc55cSDimitry Andric }
1769349cc55cSDimitry Andric 
printAlignedLabel(const MCInst * MI,uint64_t Address,unsigned OpNum,const MCSubtargetInfo & STI,raw_ostream & O)17705ffd83dbSDimitry Andric void AArch64InstPrinter::printAlignedLabel(const MCInst *MI, uint64_t Address,
17715ffd83dbSDimitry Andric                                            unsigned OpNum,
17720b57cec5SDimitry Andric                                            const MCSubtargetInfo &STI,
17730b57cec5SDimitry Andric                                            raw_ostream &O) {
17740b57cec5SDimitry Andric   const MCOperand &Op = MI->getOperand(OpNum);
17750b57cec5SDimitry Andric 
17760b57cec5SDimitry Andric   // If the label has already been resolved to an immediate offset (say, when
17770b57cec5SDimitry Andric   // we're running the disassembler), just print the immediate.
17780b57cec5SDimitry Andric   if (Op.isImm()) {
17795ffd83dbSDimitry Andric     int64_t Offset = Op.getImm() * 4;
17805ffd83dbSDimitry Andric     if (PrintBranchImmAsAddress)
17815f757f3fSDimitry Andric       markup(O, Markup::Target) << formatHex(Address + Offset);
17825ffd83dbSDimitry Andric     else
17835f757f3fSDimitry Andric       markup(O, Markup::Immediate) << "#" << formatImm(Offset);
17840b57cec5SDimitry Andric     return;
17850b57cec5SDimitry Andric   }
17860b57cec5SDimitry Andric 
17870b57cec5SDimitry Andric   // If the branch target is simply an address then print it in hex.
17880b57cec5SDimitry Andric   const MCConstantExpr *BranchTarget =
17890b57cec5SDimitry Andric       dyn_cast<MCConstantExpr>(MI->getOperand(OpNum).getExpr());
17905ffd83dbSDimitry Andric   int64_t TargetAddress;
17915ffd83dbSDimitry Andric   if (BranchTarget && BranchTarget->evaluateAsAbsolute(TargetAddress)) {
17925f757f3fSDimitry Andric     markup(O, Markup::Target) << formatHex((uint64_t)TargetAddress);
17930b57cec5SDimitry Andric   } else {
17940b57cec5SDimitry Andric     // Otherwise, just print the expression.
17950b57cec5SDimitry Andric     MI->getOperand(OpNum).getExpr()->print(O, &MAI);
17960b57cec5SDimitry Andric   }
17970b57cec5SDimitry Andric }
17980b57cec5SDimitry Andric 
printAdrAdrpLabel(const MCInst * MI,uint64_t Address,unsigned OpNum,const MCSubtargetInfo & STI,raw_ostream & O)179906c3fb27SDimitry Andric void AArch64InstPrinter::printAdrAdrpLabel(const MCInst *MI, uint64_t Address,
1800e8d8bef9SDimitry Andric                                            unsigned OpNum,
18010b57cec5SDimitry Andric                                            const MCSubtargetInfo &STI,
18020b57cec5SDimitry Andric                                            raw_ostream &O) {
18030b57cec5SDimitry Andric   const MCOperand &Op = MI->getOperand(OpNum);
18040b57cec5SDimitry Andric 
18050b57cec5SDimitry Andric   // If the label has already been resolved to an immediate offset (say, when
18060b57cec5SDimitry Andric   // we're running the disassembler), just print the immediate.
18070b57cec5SDimitry Andric   if (Op.isImm()) {
180806c3fb27SDimitry Andric     int64_t Offset = Op.getImm();
180906c3fb27SDimitry Andric     if (MI->getOpcode() == AArch64::ADRP) {
181006c3fb27SDimitry Andric       Offset = Offset * 4096;
181106c3fb27SDimitry Andric       Address = Address & -4096;
181206c3fb27SDimitry Andric     }
18135f757f3fSDimitry Andric     WithMarkup M = markup(O, Markup::Immediate);
1814e8d8bef9SDimitry Andric     if (PrintBranchImmAsAddress)
18155f757f3fSDimitry Andric       markup(O, Markup::Target) << formatHex(Address + Offset);
1816e8d8bef9SDimitry Andric     else
18175f757f3fSDimitry Andric       markup(O, Markup::Immediate) << "#" << Offset;
18180b57cec5SDimitry Andric     return;
18190b57cec5SDimitry Andric   }
18200b57cec5SDimitry Andric 
18210b57cec5SDimitry Andric   // Otherwise, just print the expression.
18220b57cec5SDimitry Andric   MI->getOperand(OpNum).getExpr()->print(O, &MAI);
18230b57cec5SDimitry Andric }
18240b57cec5SDimitry Andric 
printBarrierOption(const MCInst * MI,unsigned OpNo,const MCSubtargetInfo & STI,raw_ostream & O)18250b57cec5SDimitry Andric void AArch64InstPrinter::printBarrierOption(const MCInst *MI, unsigned OpNo,
18260b57cec5SDimitry Andric                                             const MCSubtargetInfo &STI,
18270b57cec5SDimitry Andric                                             raw_ostream &O) {
18280b57cec5SDimitry Andric   unsigned Val = MI->getOperand(OpNo).getImm();
18290b57cec5SDimitry Andric   unsigned Opcode = MI->getOpcode();
18300b57cec5SDimitry Andric 
18310b57cec5SDimitry Andric   StringRef Name;
18320b57cec5SDimitry Andric   if (Opcode == AArch64::ISB) {
18330b57cec5SDimitry Andric     auto ISB = AArch64ISB::lookupISBByEncoding(Val);
18340b57cec5SDimitry Andric     Name = ISB ? ISB->Name : "";
18350b57cec5SDimitry Andric   } else if (Opcode == AArch64::TSB) {
18360b57cec5SDimitry Andric     auto TSB = AArch64TSB::lookupTSBByEncoding(Val);
18370b57cec5SDimitry Andric     Name = TSB ? TSB->Name : "";
18380b57cec5SDimitry Andric   } else {
18390b57cec5SDimitry Andric     auto DB = AArch64DB::lookupDBByEncoding(Val);
18400b57cec5SDimitry Andric     Name = DB ? DB->Name : "";
18410b57cec5SDimitry Andric   }
18420b57cec5SDimitry Andric   if (!Name.empty())
18430b57cec5SDimitry Andric     O << Name;
18440b57cec5SDimitry Andric   else
18455f757f3fSDimitry Andric     markup(O, Markup::Immediate) << "#" << Val;
18460b57cec5SDimitry Andric }
18470b57cec5SDimitry Andric 
printBarriernXSOption(const MCInst * MI,unsigned OpNo,const MCSubtargetInfo & STI,raw_ostream & O)1848e8d8bef9SDimitry Andric void AArch64InstPrinter::printBarriernXSOption(const MCInst *MI, unsigned OpNo,
1849e8d8bef9SDimitry Andric                                                const MCSubtargetInfo &STI,
1850e8d8bef9SDimitry Andric                                                raw_ostream &O) {
1851e8d8bef9SDimitry Andric   unsigned Val = MI->getOperand(OpNo).getImm();
1852e8d8bef9SDimitry Andric   assert(MI->getOpcode() == AArch64::DSBnXS);
1853e8d8bef9SDimitry Andric 
1854e8d8bef9SDimitry Andric   StringRef Name;
1855e8d8bef9SDimitry Andric   auto DB = AArch64DBnXS::lookupDBnXSByEncoding(Val);
1856e8d8bef9SDimitry Andric   Name = DB ? DB->Name : "";
1857e8d8bef9SDimitry Andric 
1858e8d8bef9SDimitry Andric   if (!Name.empty())
1859e8d8bef9SDimitry Andric     O << Name;
1860e8d8bef9SDimitry Andric   else
18615f757f3fSDimitry Andric     markup(O, Markup::Immediate) << "#" << Val;
1862e8d8bef9SDimitry Andric }
1863e8d8bef9SDimitry Andric 
isValidSysReg(const AArch64SysReg::SysReg * Reg,bool Read,const MCSubtargetInfo & STI)1864349cc55cSDimitry Andric static bool isValidSysReg(const AArch64SysReg::SysReg *Reg, bool Read,
1865349cc55cSDimitry Andric                           const MCSubtargetInfo &STI) {
1866349cc55cSDimitry Andric   return (Reg && (Read ? Reg->Readable : Reg->Writeable) &&
1867349cc55cSDimitry Andric           Reg->haveFeatures(STI.getFeatureBits()));
1868349cc55cSDimitry Andric }
1869349cc55cSDimitry Andric 
1870349cc55cSDimitry Andric // Looks up a system register either by encoding or by name. Some system
1871349cc55cSDimitry Andric // registers share the same encoding between different architectures,
1872349cc55cSDimitry Andric // therefore a tablegen lookup by encoding will return an entry regardless
1873349cc55cSDimitry Andric // of the register's predication on a specific subtarget feature. To work
1874349cc55cSDimitry Andric // around this problem we keep an alternative name for such registers and
1875349cc55cSDimitry Andric // look them up by that name if the first lookup was unsuccessful.
lookupSysReg(unsigned Val,bool Read,const MCSubtargetInfo & STI)1876349cc55cSDimitry Andric static const AArch64SysReg::SysReg *lookupSysReg(unsigned Val, bool Read,
1877349cc55cSDimitry Andric                                                  const MCSubtargetInfo &STI) {
1878349cc55cSDimitry Andric   const AArch64SysReg::SysReg *Reg = AArch64SysReg::lookupSysRegByEncoding(Val);
1879349cc55cSDimitry Andric 
1880349cc55cSDimitry Andric   if (Reg && !isValidSysReg(Reg, Read, STI))
1881349cc55cSDimitry Andric     Reg = AArch64SysReg::lookupSysRegByName(Reg->AltName);
1882349cc55cSDimitry Andric 
1883349cc55cSDimitry Andric   return Reg;
1884349cc55cSDimitry Andric }
1885349cc55cSDimitry Andric 
printMRSSystemRegister(const MCInst * MI,unsigned OpNo,const MCSubtargetInfo & STI,raw_ostream & O)18860b57cec5SDimitry Andric void AArch64InstPrinter::printMRSSystemRegister(const MCInst *MI, unsigned OpNo,
18870b57cec5SDimitry Andric                                                 const MCSubtargetInfo &STI,
18880b57cec5SDimitry Andric                                                 raw_ostream &O) {
18890b57cec5SDimitry Andric   unsigned Val = MI->getOperand(OpNo).getImm();
18900b57cec5SDimitry Andric 
18910b57cec5SDimitry Andric   // Horrible hack for the one register that has identical encodings but
18920b57cec5SDimitry Andric   // different names in MSR and MRS. Because of this, one of MRS and MSR is
18930b57cec5SDimitry Andric   // going to get the wrong entry
18940b57cec5SDimitry Andric   if (Val == AArch64SysReg::DBGDTRRX_EL0) {
18950b57cec5SDimitry Andric     O << "DBGDTRRX_EL0";
18960b57cec5SDimitry Andric     return;
18970b57cec5SDimitry Andric   }
18980b57cec5SDimitry Andric 
18995ffd83dbSDimitry Andric   // Horrible hack for two different registers having the same encoding.
19005ffd83dbSDimitry Andric   if (Val == AArch64SysReg::TRCEXTINSELR) {
19015ffd83dbSDimitry Andric     O << "TRCEXTINSELR";
19025ffd83dbSDimitry Andric     return;
19035ffd83dbSDimitry Andric   }
19045ffd83dbSDimitry Andric 
1905349cc55cSDimitry Andric   const AArch64SysReg::SysReg *Reg = lookupSysReg(Val, true /*Read*/, STI);
1906349cc55cSDimitry Andric 
1907349cc55cSDimitry Andric   if (isValidSysReg(Reg, true /*Read*/, STI))
19080b57cec5SDimitry Andric     O << Reg->Name;
19090b57cec5SDimitry Andric   else
19100b57cec5SDimitry Andric     O << AArch64SysReg::genericRegisterString(Val);
19110b57cec5SDimitry Andric }
19120b57cec5SDimitry Andric 
printMSRSystemRegister(const MCInst * MI,unsigned OpNo,const MCSubtargetInfo & STI,raw_ostream & O)19130b57cec5SDimitry Andric void AArch64InstPrinter::printMSRSystemRegister(const MCInst *MI, unsigned OpNo,
19140b57cec5SDimitry Andric                                                 const MCSubtargetInfo &STI,
19150b57cec5SDimitry Andric                                                 raw_ostream &O) {
19160b57cec5SDimitry Andric   unsigned Val = MI->getOperand(OpNo).getImm();
19170b57cec5SDimitry Andric 
19180b57cec5SDimitry Andric   // Horrible hack for the one register that has identical encodings but
19190b57cec5SDimitry Andric   // different names in MSR and MRS. Because of this, one of MRS and MSR is
19200b57cec5SDimitry Andric   // going to get the wrong entry
19210b57cec5SDimitry Andric   if (Val == AArch64SysReg::DBGDTRTX_EL0) {
19220b57cec5SDimitry Andric     O << "DBGDTRTX_EL0";
19230b57cec5SDimitry Andric     return;
19240b57cec5SDimitry Andric   }
19250b57cec5SDimitry Andric 
19265ffd83dbSDimitry Andric   // Horrible hack for two different registers having the same encoding.
19275ffd83dbSDimitry Andric   if (Val == AArch64SysReg::TRCEXTINSELR) {
19285ffd83dbSDimitry Andric     O << "TRCEXTINSELR";
19295ffd83dbSDimitry Andric     return;
19305ffd83dbSDimitry Andric   }
19315ffd83dbSDimitry Andric 
1932349cc55cSDimitry Andric   const AArch64SysReg::SysReg *Reg = lookupSysReg(Val, false /*Read*/, STI);
1933349cc55cSDimitry Andric 
1934349cc55cSDimitry Andric   if (isValidSysReg(Reg, false /*Read*/, STI))
19350b57cec5SDimitry Andric     O << Reg->Name;
19360b57cec5SDimitry Andric   else
19370b57cec5SDimitry Andric     O << AArch64SysReg::genericRegisterString(Val);
19380b57cec5SDimitry Andric }
19390b57cec5SDimitry Andric 
printSystemPStateField(const MCInst * MI,unsigned OpNo,const MCSubtargetInfo & STI,raw_ostream & O)19400b57cec5SDimitry Andric void AArch64InstPrinter::printSystemPStateField(const MCInst *MI, unsigned OpNo,
19410b57cec5SDimitry Andric                                                 const MCSubtargetInfo &STI,
19420b57cec5SDimitry Andric                                                 raw_ostream &O) {
19430b57cec5SDimitry Andric   unsigned Val = MI->getOperand(OpNo).getImm();
19440b57cec5SDimitry Andric 
1945bdd1243dSDimitry Andric   auto PStateImm15 = AArch64PState::lookupPStateImm0_15ByEncoding(Val);
1946bdd1243dSDimitry Andric   auto PStateImm1 = AArch64PState::lookupPStateImm0_1ByEncoding(Val);
1947bdd1243dSDimitry Andric   if (PStateImm15 && PStateImm15->haveFeatures(STI.getFeatureBits()))
1948bdd1243dSDimitry Andric     O << PStateImm15->Name;
1949bdd1243dSDimitry Andric   else if (PStateImm1 && PStateImm1->haveFeatures(STI.getFeatureBits()))
1950bdd1243dSDimitry Andric     O << PStateImm1->Name;
19510b57cec5SDimitry Andric   else
19520b57cec5SDimitry Andric     O << "#" << formatImm(Val);
19530b57cec5SDimitry Andric }
19540b57cec5SDimitry Andric 
printSIMDType10Operand(const MCInst * MI,unsigned OpNo,const MCSubtargetInfo & STI,raw_ostream & O)19550b57cec5SDimitry Andric void AArch64InstPrinter::printSIMDType10Operand(const MCInst *MI, unsigned OpNo,
19560b57cec5SDimitry Andric                                                 const MCSubtargetInfo &STI,
19570b57cec5SDimitry Andric                                                 raw_ostream &O) {
19580b57cec5SDimitry Andric   unsigned RawVal = MI->getOperand(OpNo).getImm();
19590b57cec5SDimitry Andric   uint64_t Val = AArch64_AM::decodeAdvSIMDModImmType10(RawVal);
19605f757f3fSDimitry Andric   markup(O, Markup::Immediate) << format("#%#016llx", Val);
19610b57cec5SDimitry Andric }
19620b57cec5SDimitry Andric 
19630b57cec5SDimitry Andric template<int64_t Angle, int64_t Remainder>
printComplexRotationOp(const MCInst * MI,unsigned OpNo,const MCSubtargetInfo & STI,raw_ostream & O)19640b57cec5SDimitry Andric void AArch64InstPrinter::printComplexRotationOp(const MCInst *MI, unsigned OpNo,
19650b57cec5SDimitry Andric                                                 const MCSubtargetInfo &STI,
19660b57cec5SDimitry Andric                                                 raw_ostream &O) {
19670b57cec5SDimitry Andric   unsigned Val = MI->getOperand(OpNo).getImm();
19685f757f3fSDimitry Andric   markup(O, Markup::Immediate) << "#" << (Val * Angle) + Remainder;
19690b57cec5SDimitry Andric }
19700b57cec5SDimitry Andric 
printSVEPattern(const MCInst * MI,unsigned OpNum,const MCSubtargetInfo & STI,raw_ostream & O)19710b57cec5SDimitry Andric void AArch64InstPrinter::printSVEPattern(const MCInst *MI, unsigned OpNum,
19720b57cec5SDimitry Andric                                          const MCSubtargetInfo &STI,
19730b57cec5SDimitry Andric                                          raw_ostream &O) {
19740b57cec5SDimitry Andric   unsigned Val = MI->getOperand(OpNum).getImm();
19750b57cec5SDimitry Andric   if (auto Pat = AArch64SVEPredPattern::lookupSVEPREDPATByEncoding(Val))
19760b57cec5SDimitry Andric     O << Pat->Name;
19770b57cec5SDimitry Andric   else
19785f757f3fSDimitry Andric     markup(O, Markup::Immediate) << '#' << formatImm(Val);
1979bdd1243dSDimitry Andric }
1980bdd1243dSDimitry Andric 
printSVEVecLenSpecifier(const MCInst * MI,unsigned OpNum,const MCSubtargetInfo & STI,raw_ostream & O)1981bdd1243dSDimitry Andric void AArch64InstPrinter::printSVEVecLenSpecifier(const MCInst *MI,
1982bdd1243dSDimitry Andric                                                  unsigned OpNum,
1983bdd1243dSDimitry Andric                                                  const MCSubtargetInfo &STI,
1984bdd1243dSDimitry Andric                                                  raw_ostream &O) {
1985bdd1243dSDimitry Andric   unsigned Val = MI->getOperand(OpNum).getImm();
1986bdd1243dSDimitry Andric   // Pattern has only 1 bit
1987bdd1243dSDimitry Andric   if (Val > 1)
1988bdd1243dSDimitry Andric     llvm_unreachable("Invalid vector length specifier");
1989bdd1243dSDimitry Andric   if (auto Pat =
1990bdd1243dSDimitry Andric           AArch64SVEVecLenSpecifier::lookupSVEVECLENSPECIFIERByEncoding(Val))
1991bdd1243dSDimitry Andric     O << Pat->Name;
1992bdd1243dSDimitry Andric   else
1993bdd1243dSDimitry Andric     llvm_unreachable("Invalid vector length specifier");
19940b57cec5SDimitry Andric }
19950b57cec5SDimitry Andric 
19960b57cec5SDimitry Andric template <char suffix>
printSVERegOp(const MCInst * MI,unsigned OpNum,const MCSubtargetInfo & STI,raw_ostream & O)19970b57cec5SDimitry Andric void AArch64InstPrinter::printSVERegOp(const MCInst *MI, unsigned OpNum,
19980b57cec5SDimitry Andric                                        const MCSubtargetInfo &STI,
19990b57cec5SDimitry Andric                                        raw_ostream &O) {
20000b57cec5SDimitry Andric   switch (suffix) {
20010b57cec5SDimitry Andric   case 0:
20020b57cec5SDimitry Andric   case 'b':
20030b57cec5SDimitry Andric   case 'h':
20040b57cec5SDimitry Andric   case 's':
20050b57cec5SDimitry Andric   case 'd':
20060b57cec5SDimitry Andric   case 'q':
20070b57cec5SDimitry Andric     break;
20080b57cec5SDimitry Andric   default: llvm_unreachable("Invalid kind specifier.");
20090b57cec5SDimitry Andric   }
20100b57cec5SDimitry Andric 
20110b57cec5SDimitry Andric   unsigned Reg = MI->getOperand(OpNum).getReg();
2012bdd1243dSDimitry Andric   printRegName(O, Reg);
20130b57cec5SDimitry Andric   if (suffix != 0)
20140b57cec5SDimitry Andric     O << '.' << suffix;
20150b57cec5SDimitry Andric }
20160b57cec5SDimitry Andric 
20170b57cec5SDimitry Andric template <typename T>
printImmSVE(T Value,raw_ostream & O)20180b57cec5SDimitry Andric void AArch64InstPrinter::printImmSVE(T Value, raw_ostream &O) {
20195ffd83dbSDimitry Andric   std::make_unsigned_t<T> HexValue = Value;
20200b57cec5SDimitry Andric 
20210b57cec5SDimitry Andric   if (getPrintImmHex())
20225f757f3fSDimitry Andric     markup(O, Markup::Immediate) << '#' << formatHex((uint64_t)HexValue);
20230b57cec5SDimitry Andric   else
20245f757f3fSDimitry Andric     markup(O, Markup::Immediate) << '#' << formatDec(Value);
20250b57cec5SDimitry Andric 
20260b57cec5SDimitry Andric   if (CommentStream) {
20270b57cec5SDimitry Andric     // Do the opposite to that used for instruction operands.
20280b57cec5SDimitry Andric     if (getPrintImmHex())
20290b57cec5SDimitry Andric       *CommentStream << '=' << formatDec(HexValue) << '\n';
20300b57cec5SDimitry Andric     else
20310b57cec5SDimitry Andric       *CommentStream << '=' << formatHex((uint64_t)Value) << '\n';
20320b57cec5SDimitry Andric   }
20330b57cec5SDimitry Andric }
20340b57cec5SDimitry Andric 
20350b57cec5SDimitry Andric template <typename T>
printImm8OptLsl(const MCInst * MI,unsigned OpNum,const MCSubtargetInfo & STI,raw_ostream & O)20360b57cec5SDimitry Andric void AArch64InstPrinter::printImm8OptLsl(const MCInst *MI, unsigned OpNum,
20370b57cec5SDimitry Andric                                          const MCSubtargetInfo &STI,
20380b57cec5SDimitry Andric                                          raw_ostream &O) {
20390b57cec5SDimitry Andric   unsigned UnscaledVal = MI->getOperand(OpNum).getImm();
20400b57cec5SDimitry Andric   unsigned Shift = MI->getOperand(OpNum + 1).getImm();
20410b57cec5SDimitry Andric   assert(AArch64_AM::getShiftType(Shift) == AArch64_AM::LSL &&
20420b57cec5SDimitry Andric          "Unexepected shift type!");
20430b57cec5SDimitry Andric 
20440b57cec5SDimitry Andric   // #0 lsl #8 is never pretty printed
20450b57cec5SDimitry Andric   if ((UnscaledVal == 0) && (AArch64_AM::getShiftValue(Shift) != 0)) {
20465f757f3fSDimitry Andric     markup(O, Markup::Immediate) << '#' << formatImm(UnscaledVal);
20470b57cec5SDimitry Andric     printShifter(MI, OpNum + 1, STI, O);
20480b57cec5SDimitry Andric     return;
20490b57cec5SDimitry Andric   }
20500b57cec5SDimitry Andric 
20510b57cec5SDimitry Andric   T Val;
20520b57cec5SDimitry Andric   if (std::is_signed<T>())
20530b57cec5SDimitry Andric     Val = (int8_t)UnscaledVal * (1 << AArch64_AM::getShiftValue(Shift));
20540b57cec5SDimitry Andric   else
20550b57cec5SDimitry Andric     Val = (uint8_t)UnscaledVal * (1 << AArch64_AM::getShiftValue(Shift));
20560b57cec5SDimitry Andric 
20570b57cec5SDimitry Andric   printImmSVE(Val, O);
20580b57cec5SDimitry Andric }
20590b57cec5SDimitry Andric 
20600b57cec5SDimitry Andric template <typename T>
printSVELogicalImm(const MCInst * MI,unsigned OpNum,const MCSubtargetInfo & STI,raw_ostream & O)20610b57cec5SDimitry Andric void AArch64InstPrinter::printSVELogicalImm(const MCInst *MI, unsigned OpNum,
20620b57cec5SDimitry Andric                                             const MCSubtargetInfo &STI,
20630b57cec5SDimitry Andric                                             raw_ostream &O) {
20645ffd83dbSDimitry Andric   typedef std::make_signed_t<T> SignedT;
20655ffd83dbSDimitry Andric   typedef std::make_unsigned_t<T> UnsignedT;
20660b57cec5SDimitry Andric 
20670b57cec5SDimitry Andric   uint64_t Val = MI->getOperand(OpNum).getImm();
20680b57cec5SDimitry Andric   UnsignedT PrintVal = AArch64_AM::decodeLogicalImmediate(Val, 64);
20690b57cec5SDimitry Andric 
20700b57cec5SDimitry Andric   // Prefer the default format for 16bit values, hex otherwise.
20710b57cec5SDimitry Andric   if ((int16_t)PrintVal == (SignedT)PrintVal)
20720b57cec5SDimitry Andric     printImmSVE((T)PrintVal, O);
20730b57cec5SDimitry Andric   else if ((uint16_t)PrintVal == PrintVal)
20740b57cec5SDimitry Andric     printImmSVE(PrintVal, O);
20750b57cec5SDimitry Andric   else
20765f757f3fSDimitry Andric     markup(O, Markup::Immediate) << '#' << formatHex((uint64_t)PrintVal);
20770b57cec5SDimitry Andric }
20780b57cec5SDimitry Andric 
20790b57cec5SDimitry Andric template <int Width>
printZPRasFPR(const MCInst * MI,unsigned OpNum,const MCSubtargetInfo & STI,raw_ostream & O)20800b57cec5SDimitry Andric void AArch64InstPrinter::printZPRasFPR(const MCInst *MI, unsigned OpNum,
20810b57cec5SDimitry Andric                                        const MCSubtargetInfo &STI,
20820b57cec5SDimitry Andric                                        raw_ostream &O) {
20830b57cec5SDimitry Andric   unsigned Base;
20840b57cec5SDimitry Andric   switch (Width) {
20850b57cec5SDimitry Andric   case 8:   Base = AArch64::B0; break;
20860b57cec5SDimitry Andric   case 16:  Base = AArch64::H0; break;
20870b57cec5SDimitry Andric   case 32:  Base = AArch64::S0; break;
20880b57cec5SDimitry Andric   case 64:  Base = AArch64::D0; break;
20890b57cec5SDimitry Andric   case 128: Base = AArch64::Q0; break;
20900b57cec5SDimitry Andric   default:
20910b57cec5SDimitry Andric     llvm_unreachable("Unsupported width");
20920b57cec5SDimitry Andric   }
20930b57cec5SDimitry Andric   unsigned Reg = MI->getOperand(OpNum).getReg();
2094bdd1243dSDimitry Andric   printRegName(O, Reg - AArch64::Z0 + Base);
20950b57cec5SDimitry Andric }
20960b57cec5SDimitry Andric 
20970b57cec5SDimitry Andric template <unsigned ImmIs0, unsigned ImmIs1>
printExactFPImm(const MCInst * MI,unsigned OpNum,const MCSubtargetInfo & STI,raw_ostream & O)20980b57cec5SDimitry Andric void AArch64InstPrinter::printExactFPImm(const MCInst *MI, unsigned OpNum,
20990b57cec5SDimitry Andric                                          const MCSubtargetInfo &STI,
21000b57cec5SDimitry Andric                                          raw_ostream  &O) {
21010b57cec5SDimitry Andric   auto *Imm0Desc = AArch64ExactFPImm::lookupExactFPImmByEnum(ImmIs0);
21020b57cec5SDimitry Andric   auto *Imm1Desc = AArch64ExactFPImm::lookupExactFPImmByEnum(ImmIs1);
21030b57cec5SDimitry Andric   unsigned Val = MI->getOperand(OpNum).getImm();
21045f757f3fSDimitry Andric   markup(O, Markup::Immediate)
21055f757f3fSDimitry Andric       << "#" << (Val ? Imm1Desc->Repr : Imm0Desc->Repr);
21060b57cec5SDimitry Andric }
21070b57cec5SDimitry Andric 
printGPR64as32(const MCInst * MI,unsigned OpNum,const MCSubtargetInfo & STI,raw_ostream & O)21080b57cec5SDimitry Andric void AArch64InstPrinter::printGPR64as32(const MCInst *MI, unsigned OpNum,
21090b57cec5SDimitry Andric                                         const MCSubtargetInfo &STI,
21100b57cec5SDimitry Andric                                         raw_ostream &O) {
21110b57cec5SDimitry Andric   unsigned Reg = MI->getOperand(OpNum).getReg();
2112bdd1243dSDimitry Andric   printRegName(O, getWRegFromXReg(Reg));
21130b57cec5SDimitry Andric }
2114e8d8bef9SDimitry Andric 
printGPR64x8(const MCInst * MI,unsigned OpNum,const MCSubtargetInfo & STI,raw_ostream & O)2115e8d8bef9SDimitry Andric void AArch64InstPrinter::printGPR64x8(const MCInst *MI, unsigned OpNum,
2116e8d8bef9SDimitry Andric                                       const MCSubtargetInfo &STI,
2117e8d8bef9SDimitry Andric                                       raw_ostream &O) {
2118e8d8bef9SDimitry Andric   unsigned Reg = MI->getOperand(OpNum).getReg();
2119bdd1243dSDimitry Andric   printRegName(O, MRI.getSubReg(Reg, AArch64::x8sub_0));
2120bdd1243dSDimitry Andric }
2121bdd1243dSDimitry Andric 
printSyspXzrPair(const MCInst * MI,unsigned OpNum,const MCSubtargetInfo & STI,raw_ostream & O)2122bdd1243dSDimitry Andric void AArch64InstPrinter::printSyspXzrPair(const MCInst *MI, unsigned OpNum,
2123bdd1243dSDimitry Andric                                           const MCSubtargetInfo &STI,
2124bdd1243dSDimitry Andric                                           raw_ostream &O) {
2125bdd1243dSDimitry Andric   unsigned Reg = MI->getOperand(OpNum).getReg();
2126bdd1243dSDimitry Andric   assert(Reg == AArch64::XZR &&
2127bdd1243dSDimitry Andric          "MC representation of SyspXzrPair should be XZR");
2128bdd1243dSDimitry Andric   O << getRegisterName(Reg) << ", " << getRegisterName(Reg);
2129e8d8bef9SDimitry Andric }
2130