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