1249259Sdim//==-- AArch64InstPrinter.cpp - Convert AArch64 MCInst to assembly syntax --==// 2249259Sdim// 3249259Sdim// The LLVM Compiler Infrastructure 4249259Sdim// 5249259Sdim// This file is distributed under the University of Illinois Open Source 6249259Sdim// License. See LICENSE.TXT for details. 7249259Sdim// 8249259Sdim//===----------------------------------------------------------------------===// 9249259Sdim// 10249259Sdim// This class prints an AArch64 MCInst to a .s file. 11249259Sdim// 12249259Sdim//===----------------------------------------------------------------------===// 13249259Sdim 14249259Sdim#define DEBUG_TYPE "asm-printer" 15249259Sdim#include "AArch64InstPrinter.h" 16249259Sdim#include "MCTargetDesc/AArch64MCTargetDesc.h" 17249259Sdim#include "Utils/AArch64BaseInfo.h" 18249259Sdim#include "llvm/MC/MCInst.h" 19249259Sdim#include "llvm/MC/MCExpr.h" 20249259Sdim#include "llvm/MC/MCRegisterInfo.h" 21249259Sdim#include "llvm/Support/ErrorHandling.h" 22249259Sdim#include "llvm/Support/Format.h" 23249259Sdim#include "llvm/Support/raw_ostream.h" 24249259Sdim 25249259Sdimusing namespace llvm; 26249259Sdim 27249259Sdim#define GET_INSTRUCTION_NAME 28249259Sdim#define PRINT_ALIAS_INSTR 29249259Sdim#include "AArch64GenAsmWriter.inc" 30249259Sdim 31249259Sdimstatic int64_t unpackSignedImm(int BitWidth, uint64_t Value) { 32249259Sdim assert(!(Value & ~((1ULL << BitWidth)-1)) && "immediate not n-bit"); 33249259Sdim if (Value & (1ULL << (BitWidth - 1))) 34249259Sdim return static_cast<int64_t>(Value) - (1LL << BitWidth); 35249259Sdim else 36249259Sdim return Value; 37249259Sdim} 38249259Sdim 39249259SdimAArch64InstPrinter::AArch64InstPrinter(const MCAsmInfo &MAI, 40249259Sdim const MCInstrInfo &MII, 41249259Sdim const MCRegisterInfo &MRI, 42249259Sdim const MCSubtargetInfo &STI) : 43249259Sdim MCInstPrinter(MAI, MII, MRI) { 44249259Sdim // Initialize the set of available features. 45249259Sdim setAvailableFeatures(STI.getFeatureBits()); 46249259Sdim} 47249259Sdim 48249259Sdimvoid AArch64InstPrinter::printRegName(raw_ostream &OS, unsigned RegNo) const { 49249259Sdim OS << getRegisterName(RegNo); 50249259Sdim} 51249259Sdim 52249259Sdimvoid 53249259SdimAArch64InstPrinter::printOffsetSImm9Operand(const MCInst *MI, 54249259Sdim unsigned OpNum, raw_ostream &O) { 55249259Sdim const MCOperand &MOImm = MI->getOperand(OpNum); 56249259Sdim int32_t Imm = unpackSignedImm(9, MOImm.getImm()); 57249259Sdim 58249259Sdim O << '#' << Imm; 59249259Sdim} 60249259Sdim 61249259Sdimvoid 62249259SdimAArch64InstPrinter::printAddrRegExtendOperand(const MCInst *MI, unsigned OpNum, 63249259Sdim raw_ostream &O, unsigned MemSize, 64249259Sdim unsigned RmSize) { 65249259Sdim unsigned ExtImm = MI->getOperand(OpNum).getImm(); 66249259Sdim unsigned OptionHi = ExtImm >> 1; 67249259Sdim unsigned S = ExtImm & 1; 68249259Sdim bool IsLSL = OptionHi == 1 && RmSize == 64; 69249259Sdim 70249259Sdim const char *Ext; 71249259Sdim switch (OptionHi) { 72249259Sdim case 1: 73249259Sdim Ext = (RmSize == 32) ? "uxtw" : "lsl"; 74249259Sdim break; 75249259Sdim case 3: 76249259Sdim Ext = (RmSize == 32) ? "sxtw" : "sxtx"; 77249259Sdim break; 78249259Sdim default: 79249259Sdim llvm_unreachable("Incorrect Option on load/store (reg offset)"); 80249259Sdim } 81249259Sdim O << Ext; 82249259Sdim 83249259Sdim if (S) { 84249259Sdim unsigned ShiftAmt = Log2_32(MemSize); 85249259Sdim O << " #" << ShiftAmt; 86249259Sdim } else if (IsLSL) { 87249259Sdim O << " #0"; 88249259Sdim } 89249259Sdim} 90249259Sdim 91249259Sdimvoid 92249259SdimAArch64InstPrinter::printAddSubImmLSL0Operand(const MCInst *MI, 93249259Sdim unsigned OpNum, raw_ostream &O) { 94249259Sdim const MCOperand &Imm12Op = MI->getOperand(OpNum); 95249259Sdim 96249259Sdim if (Imm12Op.isImm()) { 97249259Sdim int64_t Imm12 = Imm12Op.getImm(); 98249259Sdim assert(Imm12 >= 0 && "Invalid immediate for add/sub imm"); 99249259Sdim O << "#" << Imm12; 100249259Sdim } else { 101249259Sdim assert(Imm12Op.isExpr() && "Unexpected shift operand type"); 102249259Sdim O << "#" << *Imm12Op.getExpr(); 103249259Sdim } 104249259Sdim} 105249259Sdim 106249259Sdimvoid 107249259SdimAArch64InstPrinter::printAddSubImmLSL12Operand(const MCInst *MI, unsigned OpNum, 108249259Sdim raw_ostream &O) { 109249259Sdim 110249259Sdim printAddSubImmLSL0Operand(MI, OpNum, O); 111249259Sdim 112249259Sdim O << ", lsl #12"; 113249259Sdim} 114249259Sdim 115249259Sdimvoid 116249259SdimAArch64InstPrinter::printBareImmOperand(const MCInst *MI, unsigned OpNum, 117249259Sdim raw_ostream &O) { 118249259Sdim const MCOperand &MO = MI->getOperand(OpNum); 119249259Sdim O << MO.getImm(); 120249259Sdim} 121249259Sdim 122249259Sdimtemplate<unsigned RegWidth> void 123249259SdimAArch64InstPrinter::printBFILSBOperand(const MCInst *MI, unsigned OpNum, 124249259Sdim raw_ostream &O) { 125249259Sdim const MCOperand &ImmROp = MI->getOperand(OpNum); 126249259Sdim unsigned LSB = ImmROp.getImm() == 0 ? 0 : RegWidth - ImmROp.getImm(); 127249259Sdim 128249259Sdim O << '#' << LSB; 129249259Sdim} 130249259Sdim 131249259Sdimvoid AArch64InstPrinter::printBFIWidthOperand(const MCInst *MI, unsigned OpNum, 132249259Sdim raw_ostream &O) { 133249259Sdim const MCOperand &ImmSOp = MI->getOperand(OpNum); 134249259Sdim unsigned Width = ImmSOp.getImm() + 1; 135249259Sdim 136249259Sdim O << '#' << Width; 137249259Sdim} 138249259Sdim 139249259Sdimvoid 140249259SdimAArch64InstPrinter::printBFXWidthOperand(const MCInst *MI, unsigned OpNum, 141249259Sdim raw_ostream &O) { 142249259Sdim const MCOperand &ImmSOp = MI->getOperand(OpNum); 143249259Sdim const MCOperand &ImmROp = MI->getOperand(OpNum - 1); 144249259Sdim 145249259Sdim unsigned ImmR = ImmROp.getImm(); 146249259Sdim unsigned ImmS = ImmSOp.getImm(); 147249259Sdim 148249259Sdim assert(ImmS >= ImmR && "Invalid ImmR, ImmS combination for bitfield extract"); 149249259Sdim 150249259Sdim O << '#' << (ImmS - ImmR + 1); 151249259Sdim} 152249259Sdim 153249259Sdimvoid 154249259SdimAArch64InstPrinter::printCRxOperand(const MCInst *MI, unsigned OpNum, 155249259Sdim raw_ostream &O) { 156249259Sdim const MCOperand &CRx = MI->getOperand(OpNum); 157249259Sdim 158249259Sdim O << 'c' << CRx.getImm(); 159249259Sdim} 160249259Sdim 161249259Sdim 162249259Sdimvoid 163249259SdimAArch64InstPrinter::printCVTFixedPosOperand(const MCInst *MI, unsigned OpNum, 164249259Sdim raw_ostream &O) { 165249259Sdim const MCOperand &ScaleOp = MI->getOperand(OpNum); 166249259Sdim 167249259Sdim O << '#' << (64 - ScaleOp.getImm()); 168249259Sdim} 169249259Sdim 170249259Sdim 171249259Sdimvoid AArch64InstPrinter::printFPImmOperand(const MCInst *MI, unsigned OpNum, 172249259Sdim raw_ostream &o) { 173249259Sdim const MCOperand &MOImm8 = MI->getOperand(OpNum); 174249259Sdim 175249259Sdim assert(MOImm8.isImm() 176249259Sdim && "Immediate operand required for floating-point immediate inst"); 177249259Sdim 178249259Sdim uint32_t Imm8 = MOImm8.getImm(); 179249259Sdim uint32_t Fraction = Imm8 & 0xf; 180249259Sdim uint32_t Exponent = (Imm8 >> 4) & 0x7; 181249259Sdim uint32_t Negative = (Imm8 >> 7) & 0x1; 182249259Sdim 183249259Sdim float Val = 1.0f + Fraction / 16.0f; 184249259Sdim 185249259Sdim // That is: 186249259Sdim // 000 -> 2^1, 001 -> 2^2, 010 -> 2^3, 011 -> 2^4, 187249259Sdim // 100 -> 2^-3, 101 -> 2^-2, 110 -> 2^-1, 111 -> 2^0 188249259Sdim if (Exponent & 0x4) { 189249259Sdim Val /= 1 << (7 - Exponent); 190249259Sdim } else { 191249259Sdim Val *= 1 << (Exponent + 1); 192249259Sdim } 193249259Sdim 194249259Sdim Val = Negative ? -Val : Val; 195249259Sdim 196249259Sdim o << '#' << format("%.8f", Val); 197249259Sdim} 198249259Sdim 199249259Sdimvoid AArch64InstPrinter::printFPZeroOperand(const MCInst *MI, unsigned OpNum, 200249259Sdim raw_ostream &o) { 201249259Sdim o << "#0.0"; 202249259Sdim} 203249259Sdim 204249259Sdimvoid 205249259SdimAArch64InstPrinter::printCondCodeOperand(const MCInst *MI, unsigned OpNum, 206249259Sdim raw_ostream &O) { 207249259Sdim const MCOperand &MO = MI->getOperand(OpNum); 208249259Sdim 209249259Sdim O << A64CondCodeToString(static_cast<A64CC::CondCodes>(MO.getImm())); 210249259Sdim} 211249259Sdim 212249259Sdimtemplate <unsigned field_width, unsigned scale> void 213249259SdimAArch64InstPrinter::printLabelOperand(const MCInst *MI, unsigned OpNum, 214249259Sdim raw_ostream &O) { 215249259Sdim const MCOperand &MO = MI->getOperand(OpNum); 216249259Sdim 217249259Sdim if (!MO.isImm()) { 218249259Sdim printOperand(MI, OpNum, O); 219249259Sdim return; 220249259Sdim } 221249259Sdim 222249259Sdim // The immediate of LDR (lit) instructions is a signed 19-bit immediate, which 223249259Sdim // is multiplied by 4 (because all A64 instructions are 32-bits wide). 224249259Sdim uint64_t UImm = MO.getImm(); 225249259Sdim uint64_t Sign = UImm & (1LL << (field_width - 1)); 226249259Sdim int64_t SImm = scale * ((UImm & ~Sign) - Sign); 227249259Sdim 228249259Sdim O << "#" << SImm; 229249259Sdim} 230249259Sdim 231249259Sdimtemplate<unsigned RegWidth> void 232249259SdimAArch64InstPrinter::printLogicalImmOperand(const MCInst *MI, unsigned OpNum, 233249259Sdim raw_ostream &O) { 234249259Sdim const MCOperand &MO = MI->getOperand(OpNum); 235249259Sdim uint64_t Val; 236249259Sdim A64Imms::isLogicalImmBits(RegWidth, MO.getImm(), Val); 237249259Sdim O << "#0x"; 238249259Sdim O.write_hex(Val); 239249259Sdim} 240249259Sdim 241249259Sdimvoid 242249259SdimAArch64InstPrinter::printOffsetUImm12Operand(const MCInst *MI, unsigned OpNum, 243249259Sdim raw_ostream &O, int MemSize) { 244249259Sdim const MCOperand &MOImm = MI->getOperand(OpNum); 245249259Sdim 246249259Sdim if (MOImm.isImm()) { 247249259Sdim uint32_t Imm = MOImm.getImm() * MemSize; 248249259Sdim 249249259Sdim O << "#" << Imm; 250249259Sdim } else { 251249259Sdim O << "#" << *MOImm.getExpr(); 252249259Sdim } 253249259Sdim} 254249259Sdim 255249259Sdimvoid 256249259SdimAArch64InstPrinter::printShiftOperand(const MCInst *MI, unsigned OpNum, 257249259Sdim raw_ostream &O, 258249259Sdim A64SE::ShiftExtSpecifiers Shift) { 259249259Sdim const MCOperand &MO = MI->getOperand(OpNum); 260249259Sdim 261249259Sdim // LSL #0 is not printed 262249259Sdim if (Shift == A64SE::LSL && MO.isImm() && MO.getImm() == 0) 263249259Sdim return; 264249259Sdim 265249259Sdim switch (Shift) { 266249259Sdim case A64SE::LSL: O << "lsl"; break; 267249259Sdim case A64SE::LSR: O << "lsr"; break; 268249259Sdim case A64SE::ASR: O << "asr"; break; 269249259Sdim case A64SE::ROR: O << "ror"; break; 270249259Sdim default: llvm_unreachable("Invalid shift specifier in logical instruction"); 271249259Sdim } 272249259Sdim 273249259Sdim O << " #" << MO.getImm(); 274249259Sdim} 275249259Sdim 276249259Sdimvoid 277249259SdimAArch64InstPrinter::printMoveWideImmOperand(const MCInst *MI, unsigned OpNum, 278249259Sdim raw_ostream &O) { 279249259Sdim const MCOperand &UImm16MO = MI->getOperand(OpNum); 280249259Sdim const MCOperand &ShiftMO = MI->getOperand(OpNum + 1); 281249259Sdim 282249259Sdim if (UImm16MO.isImm()) { 283249259Sdim O << '#' << UImm16MO.getImm(); 284249259Sdim 285249259Sdim if (ShiftMO.getImm() != 0) 286249259Sdim O << ", lsl #" << (ShiftMO.getImm() * 16); 287249259Sdim 288249259Sdim return; 289249259Sdim } 290249259Sdim 291249259Sdim O << "#" << *UImm16MO.getExpr(); 292249259Sdim} 293249259Sdim 294249259Sdimvoid AArch64InstPrinter::printNamedImmOperand(const NamedImmMapper &Mapper, 295249259Sdim const MCInst *MI, unsigned OpNum, 296249259Sdim raw_ostream &O) { 297249259Sdim bool ValidName; 298249259Sdim const MCOperand &MO = MI->getOperand(OpNum); 299249259Sdim StringRef Name = Mapper.toString(MO.getImm(), ValidName); 300249259Sdim 301249259Sdim if (ValidName) 302249259Sdim O << Name; 303249259Sdim else 304249259Sdim O << '#' << MO.getImm(); 305249259Sdim} 306249259Sdim 307249259Sdimvoid 308249259SdimAArch64InstPrinter::printSysRegOperand(const A64SysReg::SysRegMapper &Mapper, 309249259Sdim const MCInst *MI, unsigned OpNum, 310249259Sdim raw_ostream &O) { 311249259Sdim const MCOperand &MO = MI->getOperand(OpNum); 312249259Sdim 313249259Sdim bool ValidName; 314249259Sdim std::string Name = Mapper.toString(MO.getImm(), ValidName); 315249259Sdim if (ValidName) { 316249259Sdim O << Name; 317249259Sdim return; 318249259Sdim } 319249259Sdim} 320249259Sdim 321249259Sdim 322249259Sdimvoid AArch64InstPrinter::printRegExtendOperand(const MCInst *MI, 323249259Sdim unsigned OpNum, 324249259Sdim raw_ostream &O, 325249259Sdim A64SE::ShiftExtSpecifiers Ext) { 326249259Sdim // FIXME: In principle TableGen should be able to detect this itself far more 327249259Sdim // easily. We will only accumulate more of these hacks. 328249259Sdim unsigned Reg0 = MI->getOperand(0).getReg(); 329249259Sdim unsigned Reg1 = MI->getOperand(1).getReg(); 330249259Sdim 331249259Sdim if (isStackReg(Reg0) || isStackReg(Reg1)) { 332249259Sdim A64SE::ShiftExtSpecifiers LSLEquiv; 333249259Sdim 334249259Sdim if (Reg0 == AArch64::XSP || Reg1 == AArch64::XSP) 335249259Sdim LSLEquiv = A64SE::UXTX; 336249259Sdim else 337249259Sdim LSLEquiv = A64SE::UXTW; 338249259Sdim 339249259Sdim if (Ext == LSLEquiv) { 340249259Sdim O << "lsl #" << MI->getOperand(OpNum).getImm(); 341249259Sdim return; 342249259Sdim } 343249259Sdim } 344249259Sdim 345249259Sdim switch (Ext) { 346249259Sdim case A64SE::UXTB: O << "uxtb"; break; 347249259Sdim case A64SE::UXTH: O << "uxth"; break; 348249259Sdim case A64SE::UXTW: O << "uxtw"; break; 349249259Sdim case A64SE::UXTX: O << "uxtx"; break; 350249259Sdim case A64SE::SXTB: O << "sxtb"; break; 351249259Sdim case A64SE::SXTH: O << "sxth"; break; 352249259Sdim case A64SE::SXTW: O << "sxtw"; break; 353249259Sdim case A64SE::SXTX: O << "sxtx"; break; 354249259Sdim default: llvm_unreachable("Unexpected shift type for printing"); 355249259Sdim } 356249259Sdim 357249259Sdim const MCOperand &MO = MI->getOperand(OpNum); 358249259Sdim if (MO.getImm() != 0) 359249259Sdim O << " #" << MO.getImm(); 360249259Sdim} 361249259Sdim 362249259Sdimtemplate<int MemScale> void 363249259SdimAArch64InstPrinter::printSImm7ScaledOperand(const MCInst *MI, unsigned OpNum, 364249259Sdim raw_ostream &O) { 365249259Sdim const MCOperand &MOImm = MI->getOperand(OpNum); 366249259Sdim int32_t Imm = unpackSignedImm(7, MOImm.getImm()); 367249259Sdim 368249259Sdim O << "#" << (Imm * MemScale); 369249259Sdim} 370249259Sdim 371263508Sdimvoid AArch64InstPrinter::printVPRRegister(const MCInst *MI, unsigned OpNo, 372263508Sdim raw_ostream &O) { 373263508Sdim unsigned Reg = MI->getOperand(OpNo).getReg(); 374263508Sdim std::string Name = getRegisterName(Reg); 375263508Sdim Name[0] = 'v'; 376263508Sdim O << Name; 377263508Sdim} 378263508Sdim 379249259Sdimvoid AArch64InstPrinter::printOperand(const MCInst *MI, unsigned OpNo, 380249259Sdim raw_ostream &O) { 381249259Sdim const MCOperand &Op = MI->getOperand(OpNo); 382249259Sdim if (Op.isReg()) { 383249259Sdim unsigned Reg = Op.getReg(); 384249259Sdim O << getRegisterName(Reg); 385249259Sdim } else if (Op.isImm()) { 386249259Sdim O << '#' << Op.getImm(); 387249259Sdim } else { 388249259Sdim assert(Op.isExpr() && "unknown operand kind in printOperand"); 389249259Sdim // If a symbolic branch target was added as a constant expression then print 390249259Sdim // that address in hex. 391249259Sdim const MCConstantExpr *BranchTarget = dyn_cast<MCConstantExpr>(Op.getExpr()); 392249259Sdim int64_t Address; 393249259Sdim if (BranchTarget && BranchTarget->EvaluateAsAbsolute(Address)) { 394249259Sdim O << "0x"; 395249259Sdim O.write_hex(Address); 396249259Sdim } 397249259Sdim else { 398249259Sdim // Otherwise, just print the expression. 399249259Sdim O << *Op.getExpr(); 400249259Sdim } 401249259Sdim } 402249259Sdim} 403249259Sdim 404249259Sdim 405249259Sdimvoid AArch64InstPrinter::printInst(const MCInst *MI, raw_ostream &O, 406249259Sdim StringRef Annot) { 407249259Sdim if (MI->getOpcode() == AArch64::TLSDESCCALL) { 408249259Sdim // This is a special assembler directive which applies an 409249259Sdim // R_AARCH64_TLSDESC_CALL to the following (BLR) instruction. It has a fixed 410249259Sdim // form outside the normal TableGenerated scheme. 411249259Sdim O << "\t.tlsdesccall " << *MI->getOperand(0).getExpr(); 412249259Sdim } else if (!printAliasInstr(MI, O)) 413249259Sdim printInstruction(MI, O); 414249259Sdim 415249259Sdim printAnnotation(O, Annot); 416249259Sdim} 417263508Sdim 418263508Sdimtemplate <A64SE::ShiftExtSpecifiers Ext, bool isHalf> 419263508Sdimvoid AArch64InstPrinter::printNeonMovImmShiftOperand(const MCInst *MI, 420263508Sdim unsigned OpNum, 421263508Sdim raw_ostream &O) { 422263508Sdim const MCOperand &MO = MI->getOperand(OpNum); 423263508Sdim 424263508Sdim assert(MO.isImm() && 425263508Sdim "Immediate operand required for Neon vector immediate inst."); 426263508Sdim 427263508Sdim bool IsLSL = false; 428263508Sdim if (Ext == A64SE::LSL) 429263508Sdim IsLSL = true; 430263508Sdim else if (Ext != A64SE::MSL) 431263508Sdim llvm_unreachable("Invalid shift specifier in movi instruction"); 432263508Sdim 433263508Sdim int64_t Imm = MO.getImm(); 434263508Sdim 435263508Sdim // MSL and LSLH accepts encoded shift amount 0 or 1. 436263508Sdim if ((!IsLSL || (IsLSL && isHalf)) && Imm != 0 && Imm != 1) 437263508Sdim llvm_unreachable("Invalid shift amount in movi instruction"); 438263508Sdim 439263508Sdim // LSH accepts encoded shift amount 0, 1, 2 or 3. 440263508Sdim if (IsLSL && (Imm < 0 || Imm > 3)) 441263508Sdim llvm_unreachable("Invalid shift amount in movi instruction"); 442263508Sdim 443263508Sdim // Print shift amount as multiple of 8 with MSL encoded shift amount 444263508Sdim // 0 and 1 printed as 8 and 16. 445263508Sdim if (!IsLSL) 446263508Sdim Imm++; 447263508Sdim Imm *= 8; 448263508Sdim 449263508Sdim // LSL #0 is not printed 450263508Sdim if (IsLSL) { 451263508Sdim if (Imm == 0) 452263508Sdim return; 453263508Sdim O << ", lsl"; 454263508Sdim } else 455263508Sdim O << ", msl"; 456263508Sdim 457263508Sdim O << " #" << Imm; 458263508Sdim} 459263508Sdim 460263508Sdimvoid AArch64InstPrinter::printNeonUImm0Operand(const MCInst *MI, unsigned OpNum, 461263508Sdim raw_ostream &o) { 462263508Sdim o << "#0x0"; 463263508Sdim} 464263508Sdim 465263508Sdimvoid AArch64InstPrinter::printUImmHexOperand(const MCInst *MI, unsigned OpNum, 466263508Sdim raw_ostream &O) { 467263508Sdim const MCOperand &MOUImm = MI->getOperand(OpNum); 468263508Sdim 469263508Sdim assert(MOUImm.isImm() && 470263508Sdim "Immediate operand required for Neon vector immediate inst."); 471263508Sdim 472263508Sdim unsigned Imm = MOUImm.getImm(); 473263508Sdim 474263508Sdim O << "#0x"; 475263508Sdim O.write_hex(Imm); 476263508Sdim} 477263508Sdim 478263508Sdimvoid AArch64InstPrinter::printUImmBareOperand(const MCInst *MI, 479263508Sdim unsigned OpNum, 480263508Sdim raw_ostream &O) { 481263508Sdim const MCOperand &MOUImm = MI->getOperand(OpNum); 482263508Sdim 483263508Sdim assert(MOUImm.isImm() 484263508Sdim && "Immediate operand required for Neon vector immediate inst."); 485263508Sdim 486263508Sdim unsigned Imm = MOUImm.getImm(); 487263508Sdim O << Imm; 488263508Sdim} 489263508Sdim 490263508Sdimvoid AArch64InstPrinter::printNeonUImm64MaskOperand(const MCInst *MI, 491263508Sdim unsigned OpNum, 492263508Sdim raw_ostream &O) { 493263508Sdim const MCOperand &MOUImm8 = MI->getOperand(OpNum); 494263508Sdim 495263508Sdim assert(MOUImm8.isImm() && 496263508Sdim "Immediate operand required for Neon vector immediate bytemask inst."); 497263508Sdim 498263508Sdim uint32_t UImm8 = MOUImm8.getImm(); 499263508Sdim uint64_t Mask = 0; 500263508Sdim 501263508Sdim // Replicates 0x00 or 0xff byte in a 64-bit vector 502263508Sdim for (unsigned ByteNum = 0; ByteNum < 8; ++ByteNum) { 503263508Sdim if ((UImm8 >> ByteNum) & 1) 504263508Sdim Mask |= (uint64_t)0xff << (8 * ByteNum); 505263508Sdim } 506263508Sdim 507263508Sdim O << "#0x"; 508263508Sdim O.write_hex(Mask); 509263508Sdim} 510263508Sdim 511263508Sdim// If Count > 1, there are two valid kinds of vector list: 512263508Sdim// (1) {Vn.layout, Vn+1.layout, ... , Vm.layout} 513263508Sdim// (2) {Vn.layout - Vm.layout} 514263508Sdim// We choose the first kind as output. 515263508Sdimtemplate <A64Layout::VectorLayout Layout, unsigned Count> 516263508Sdimvoid AArch64InstPrinter::printVectorList(const MCInst *MI, unsigned OpNum, 517263508Sdim raw_ostream &O) { 518263508Sdim assert(Count >= 1 && Count <= 4 && "Invalid Number of Vectors"); 519263508Sdim 520263508Sdim unsigned Reg = MI->getOperand(OpNum).getReg(); 521263508Sdim std::string LayoutStr = A64VectorLayoutToString(Layout); 522263508Sdim O << "{"; 523263508Sdim if (Count > 1) { // Print sub registers separately 524263508Sdim bool IsVec64 = (Layout < A64Layout::VL_16B); 525263508Sdim unsigned SubRegIdx = IsVec64 ? AArch64::dsub_0 : AArch64::qsub_0; 526263508Sdim for (unsigned I = 0; I < Count; I++) { 527263508Sdim std::string Name = getRegisterName(MRI.getSubReg(Reg, SubRegIdx++)); 528263508Sdim Name[0] = 'v'; 529263508Sdim O << Name << LayoutStr; 530263508Sdim if (I != Count - 1) 531263508Sdim O << ", "; 532263508Sdim } 533263508Sdim } else { // Print the register directly when NumVecs is 1. 534263508Sdim std::string Name = getRegisterName(Reg); 535263508Sdim Name[0] = 'v'; 536263508Sdim O << Name << LayoutStr; 537263508Sdim } 538263508Sdim O << "}"; 539263508Sdim} 540