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 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 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 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 62bdd1243dSDimitry Andric void AArch64InstPrinter::printRegName(raw_ostream &OS, MCRegister Reg) const { 63*5f757f3fSDimitry Andric markup(OS, Markup::Register) << getRegisterName(Reg); 64bdd1243dSDimitry Andric } 65bdd1243dSDimitry Andric 66bdd1243dSDimitry Andric void AArch64InstPrinter::printRegName(raw_ostream &OS, MCRegister Reg, 67bdd1243dSDimitry Andric unsigned AltIdx) const { 68*5f757f3fSDimitry Andric markup(OS, Markup::Register) << getRegisterName(Reg, AltIdx); 69bdd1243dSDimitry Andric } 70bdd1243dSDimitry Andric 71bdd1243dSDimitry Andric StringRef AArch64InstPrinter::getRegName(MCRegister Reg) const { 72bdd1243dSDimitry Andric return getRegisterName(Reg); 730b57cec5SDimitry Andric } 740b57cec5SDimitry Andric 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()); 178*5f757f3fSDimitry Andric O << ", "; 179*5f757f3fSDimitry 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()); 191*5f757f3fSDimitry Andric O << ", "; 192*5f757f3fSDimitry Andric markup(O, Markup::Immediate) << "#" << (Is64Bit ? 64 : 32) - Op2.getImm(); 193*5f757f3fSDimitry Andric O << ", "; 194*5f757f3fSDimitry 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()); 204*5f757f3fSDimitry Andric O << ", "; 205*5f757f3fSDimitry Andric markup(O, Markup::Immediate) << "#" << Op2.getImm(); 206*5f757f3fSDimitry Andric O << ", "; 207*5f757f3fSDimitry 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()); 227*5f757f3fSDimitry Andric O << ", "; 228*5f757f3fSDimitry Andric markup(O, Markup::Immediate) << "#" << LSB; 229*5f757f3fSDimitry Andric O << ", "; 230*5f757f3fSDimitry 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()); 243*5f757f3fSDimitry Andric O << ", "; 244*5f757f3fSDimitry Andric markup(O, Markup::Immediate) << "#" << LSB; 245*5f757f3fSDimitry Andric O << ", "; 246*5f757f3fSDimitry 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()); 258*5f757f3fSDimitry Andric O << ", "; 259*5f757f3fSDimitry Andric markup(O, Markup::Immediate) << "#" << LSB; 260*5f757f3fSDimitry Andric O << ", "; 261*5f757f3fSDimitry 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()); 278*5f757f3fSDimitry Andric O << ", "; 279*5f757f3fSDimitry Andric { 280*5f757f3fSDimitry Andric WithMarkup M = markup(O, Markup::Immediate); 281*5f757f3fSDimitry Andric O << "#"; 2820b57cec5SDimitry Andric MI->getOperand(1).getExpr()->print(O, &MAI); 283*5f757f3fSDimitry 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()); 291*5f757f3fSDimitry Andric O << ", "; 292*5f757f3fSDimitry Andric { 293*5f757f3fSDimitry Andric WithMarkup M = markup(O, Markup::Immediate); 294*5f757f3fSDimitry Andric O << "#"; 2950b57cec5SDimitry Andric MI->getOperand(2).getExpr()->print(O, &MAI); 296*5f757f3fSDimitry 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()); 304*5f757f3fSDimitry Andric O << ", "; 305*5f757f3fSDimitry 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 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 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 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?"); 831*5f757f3fSDimitry Andric O << ", "; 832*5f757f3fSDimitry 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 843bdd1243dSDimitry Andric StringRef AArch64AppleInstPrinter::getRegName(MCRegister Reg) const { 844bdd1243dSDimitry Andric return getRegisterName(Reg); 845bdd1243dSDimitry Andric } 846bdd1243dSDimitry Andric 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 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 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> 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> 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 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 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 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 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); 1160*5f757f3fSDimitry Andric markup(O, Markup::Immediate) << "#" << formatImm(Op.getImm()); 11610b57cec5SDimitry Andric } 11620b57cec5SDimitry Andric 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); 1167*5f757f3fSDimitry Andric markup(O, Markup::Immediate) << format("#%#llx", Op.getImm()); 11680b57cec5SDimitry Andric } 11690b57cec5SDimitry Andric 11705ffd83dbSDimitry Andric template<int Size> 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) 1176*5f757f3fSDimitry Andric markup(O, Markup::Immediate) << "#" << formatImm((signed char)Op.getImm()); 11775ffd83dbSDimitry Andric else if (Size == 16) 1178*5f757f3fSDimitry Andric markup(O, Markup::Immediate) << "#" << formatImm((signed short)Op.getImm()); 11795ffd83dbSDimitry Andric else 1180*5f757f3fSDimitry Andric markup(O, Markup::Immediate) << "#" << formatImm(Op.getImm()); 11815ffd83dbSDimitry Andric } 11825ffd83dbSDimitry Andric 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) 1189*5f757f3fSDimitry 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 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 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 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()); 1222*5f757f3fSDimitry 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> 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(); 1240*5f757f3fSDimitry Andric WithMarkup M = markup(O, Markup::Immediate); 1241*5f757f3fSDimitry Andric O << "#0x"; 12420b57cec5SDimitry Andric O.write_hex(AArch64_AM::decodeLogicalImmediate(Val, 8 * sizeof(T))); 12430b57cec5SDimitry Andric } 12440b57cec5SDimitry Andric 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)) 1254*5f757f3fSDimitry Andric << " "; 1255*5f757f3fSDimitry Andric markup(O, Markup::Immediate) << "#" << AArch64_AM::getShiftValue(Val); 12560b57cec5SDimitry Andric } 12570b57cec5SDimitry Andric 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 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 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) ) { 1289*5f757f3fSDimitry Andric if (ShiftVal != 0) { 1290*5f757f3fSDimitry Andric O << ", lsl "; 1291*5f757f3fSDimitry Andric markup(O, Markup::Immediate) << "#" << ShiftVal; 1292*5f757f3fSDimitry Andric } 12930b57cec5SDimitry Andric return; 12940b57cec5SDimitry Andric } 12950b57cec5SDimitry Andric } 12960b57cec5SDimitry Andric O << ", " << AArch64_AM::getShiftExtendName(ExtType); 1297*5f757f3fSDimitry Andric if (ShiftVal != 0) { 1298*5f757f3fSDimitry Andric O << " "; 1299*5f757f3fSDimitry Andric markup(O, Markup::Immediate) << "#" << ShiftVal; 1300*5f757f3fSDimitry Andric } 13010b57cec5SDimitry Andric } 13020b57cec5SDimitry Andric 1303*5f757f3fSDimitry Andric void AArch64InstPrinter::printMemExtendImpl(bool SignExtend, bool DoShift, 1304*5f757f3fSDimitry Andric unsigned Width, char SrcRegKind, 1305*5f757f3fSDimitry 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 << " "; 1315*5f757f3fSDimitry Andric markup(O, Markup::Immediate) << "#" << Log2_32(Width / 8); 1316bdd1243dSDimitry Andric } 13170b57cec5SDimitry Andric } 13180b57cec5SDimitry Andric 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(); 1324*5f757f3fSDimitry Andric printMemExtendImpl(SignExtend, DoShift, Width, SrcRegKind, O); 13250b57cec5SDimitry Andric } 13260b57cec5SDimitry Andric 13270b57cec5SDimitry Andric template <bool SignExtend, int ExtWidth, char SrcRegKind, char Suffix> 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 << ", "; 1341*5f757f3fSDimitry Andric printMemExtendImpl(SignExtend, DoShift, ExtWidth, SrcRegKind, O); 1342bdd1243dSDimitry Andric } 1343bdd1243dSDimitry Andric } 1344bdd1243dSDimitry Andric 1345bdd1243dSDimitry Andric template <int EltSize> 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(); 1351*5f757f3fSDimitry Andric if (Reg < AArch64::PN0 || Reg > AArch64::PN15) 1352*5f757f3fSDimitry Andric llvm_unreachable("Unsupported predicate-as-counter register"); 1353*5f757f3fSDimitry 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 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 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 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> 13980b57cec5SDimitry Andric void AArch64InstPrinter::printImmScale(const MCInst *MI, unsigned OpNum, 13990b57cec5SDimitry Andric const MCSubtargetInfo &STI, 14000b57cec5SDimitry Andric raw_ostream &O) { 1401*5f757f3fSDimitry Andric markup(O, Markup::Immediate) 1402*5f757f3fSDimitry Andric << '#' << formatImm(Scale * MI->getOperand(OpNum).getImm()); 1403bdd1243dSDimitry Andric } 1404bdd1243dSDimitry Andric 1405bdd1243dSDimitry Andric template <int Scale, int Offset> 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 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()) { 1418*5f757f3fSDimitry 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 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()) { 1431*5f757f3fSDimitry Andric O << ", "; 1432*5f757f3fSDimitry 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 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> 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 1471*5f757f3fSDimitry Andric markup(O, Markup::Immediate) << '#' << formatImm(prfop); 14720b57cec5SDimitry Andric } 14730b57cec5SDimitry Andric 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 1482*5f757f3fSDimitry Andric markup(O, Markup::Immediate) << '#' << formatImm(psbhintop); 14830b57cec5SDimitry Andric } 14840b57cec5SDimitry Andric 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 1493*5f757f3fSDimitry Andric markup(O, Markup::Immediate) << '#' << formatImm(btihintop); 14940b57cec5SDimitry Andric } 14950b57cec5SDimitry Andric 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. 1504*5f757f3fSDimitry Andric markup(O, Markup::Immediate) << format("#%.8f", FPImm); 15050b57cec5SDimitry Andric } 15060b57cec5SDimitry Andric 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> 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 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 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 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> 17400b57cec5SDimitry Andric void AArch64InstPrinter::printTypedVectorList(const MCInst *MI, unsigned OpNum, 17410b57cec5SDimitry Andric const MCSubtargetInfo &STI, 17420b57cec5SDimitry Andric raw_ostream &O) { 1743*5f757f3fSDimitry Andric if (LaneKind == 0) { 1744*5f757f3fSDimitry Andric printVectorList(MI, OpNum, STI, O, ""); 1745*5f757f3fSDimitry Andric return; 1746*5f757f3fSDimitry 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> 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 1763*5f757f3fSDimitry Andric template <unsigned Scale> 1764349cc55cSDimitry Andric void AArch64InstPrinter::printMatrixIndex(const MCInst *MI, unsigned OpNum, 1765349cc55cSDimitry Andric const MCSubtargetInfo &STI, 1766349cc55cSDimitry Andric raw_ostream &O) { 1767*5f757f3fSDimitry Andric O << Scale * MI->getOperand(OpNum).getImm(); 1768349cc55cSDimitry Andric } 1769349cc55cSDimitry Andric 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) 1781*5f757f3fSDimitry Andric markup(O, Markup::Target) << formatHex(Address + Offset); 17825ffd83dbSDimitry Andric else 1783*5f757f3fSDimitry 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)) { 1792*5f757f3fSDimitry 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 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 } 1813*5f757f3fSDimitry Andric WithMarkup M = markup(O, Markup::Immediate); 1814e8d8bef9SDimitry Andric if (PrintBranchImmAsAddress) 1815*5f757f3fSDimitry Andric markup(O, Markup::Target) << formatHex(Address + Offset); 1816e8d8bef9SDimitry Andric else 1817*5f757f3fSDimitry 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 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 1845*5f757f3fSDimitry Andric markup(O, Markup::Immediate) << "#" << Val; 18460b57cec5SDimitry Andric } 18470b57cec5SDimitry Andric 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 1861*5f757f3fSDimitry Andric markup(O, Markup::Immediate) << "#" << Val; 1862e8d8bef9SDimitry Andric } 1863e8d8bef9SDimitry Andric 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. 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 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 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 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 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); 1960*5f757f3fSDimitry Andric markup(O, Markup::Immediate) << format("#%#016llx", Val); 19610b57cec5SDimitry Andric } 19620b57cec5SDimitry Andric 19630b57cec5SDimitry Andric template<int64_t Angle, int64_t Remainder> 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(); 1968*5f757f3fSDimitry Andric markup(O, Markup::Immediate) << "#" << (Val * Angle) + Remainder; 19690b57cec5SDimitry Andric } 19700b57cec5SDimitry Andric 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 1978*5f757f3fSDimitry Andric markup(O, Markup::Immediate) << '#' << formatImm(Val); 1979bdd1243dSDimitry Andric } 1980bdd1243dSDimitry Andric 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> 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> 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()) 2022*5f757f3fSDimitry Andric markup(O, Markup::Immediate) << '#' << formatHex((uint64_t)HexValue); 20230b57cec5SDimitry Andric else 2024*5f757f3fSDimitry 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> 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)) { 2046*5f757f3fSDimitry 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> 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 2076*5f757f3fSDimitry Andric markup(O, Markup::Immediate) << '#' << formatHex((uint64_t)PrintVal); 20770b57cec5SDimitry Andric } 20780b57cec5SDimitry Andric 20790b57cec5SDimitry Andric template <int Width> 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> 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(); 2104*5f757f3fSDimitry Andric markup(O, Markup::Immediate) 2105*5f757f3fSDimitry Andric << "#" << (Val ? Imm1Desc->Repr : Imm0Desc->Repr); 21060b57cec5SDimitry Andric } 21070b57cec5SDimitry Andric 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 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 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