1734 lines · cpp
1//===-- ARMInstPrinter.cpp - Convert ARM MCInst to assembly syntax --------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8//9// This class prints an ARM MCInst to a .s file.10//11//===----------------------------------------------------------------------===//12 13#include "ARMInstPrinter.h"14#include "MCTargetDesc/ARMAddressingModes.h"15#include "MCTargetDesc/ARMBaseInfo.h"16#include "Utils/ARMBaseInfo.h"17#include "llvm/MC/MCAsmInfo.h"18#include "llvm/MC/MCExpr.h"19#include "llvm/MC/MCInst.h"20#include "llvm/MC/MCInstrAnalysis.h"21#include "llvm/MC/MCInstrInfo.h"22#include "llvm/MC/MCRegisterInfo.h"23#include "llvm/MC/MCSubtargetInfo.h"24#include "llvm/Support/Casting.h"25#include "llvm/Support/ErrorHandling.h"26#include "llvm/Support/raw_ostream.h"27#include "llvm/TargetParser/SubtargetFeature.h"28#include <cassert>29#include <cstdint>30 31using namespace llvm;32 33#define DEBUG_TYPE "asm-printer"34 35#define PRINT_ALIAS_INSTR36#include "ARMGenAsmWriter.inc"37 38/// translateShiftImm - Convert shift immediate from 0-31 to 1-32 for printing.39///40/// getSORegOffset returns an integer from 0-31, representing '32' as 0.41static unsigned translateShiftImm(unsigned imm) {42 // lsr #32 and asr #32 exist, but should be encoded as a 0.43 assert((imm & ~0x1f) == 0 && "Invalid shift encoding");44 45 if (imm == 0)46 return 32;47 return imm;48}49 50static void printRegImmShift(raw_ostream &O, ARM_AM::ShiftOpc ShOpc,51 unsigned ShImm, ARMInstPrinter &printer) {52 if (ShOpc == ARM_AM::no_shift || (ShOpc == ARM_AM::lsl && !ShImm))53 return;54 O << ", ";55 56 assert(!(ShOpc == ARM_AM::ror && !ShImm) && "Cannot have ror #0");57 O << getShiftOpcStr(ShOpc);58 59 if (ShOpc != ARM_AM::rrx) {60 O << " ";61 printer.markup(O, llvm::MCInstPrinter::Markup::Immediate)62 << "#" << translateShiftImm(ShImm);63 }64}65 66ARMInstPrinter::ARMInstPrinter(const MCAsmInfo &MAI, const MCInstrInfo &MII,67 const MCRegisterInfo &MRI)68 : MCInstPrinter(MAI, MII, MRI) {}69 70bool ARMInstPrinter::applyTargetSpecificCLOption(StringRef Opt) {71 if (Opt == "reg-names-std") {72 DefaultAltIdx = ARM::NoRegAltName;73 return true;74 }75 if (Opt == "reg-names-raw") {76 DefaultAltIdx = ARM::RegNamesRaw;77 return true;78 }79 return false;80}81 82void ARMInstPrinter::printRegName(raw_ostream &OS, MCRegister Reg) {83 markup(OS, Markup::Register) << getRegisterName(Reg, DefaultAltIdx);84}85 86void ARMInstPrinter::printInst(const MCInst *MI, uint64_t Address,87 StringRef Annot, const MCSubtargetInfo &STI,88 raw_ostream &O) {89 unsigned Opcode = MI->getOpcode();90 91 switch (Opcode) {92 case ARM::VLLDM: {93 const MCOperand &Reg = MI->getOperand(0);94 O << '\t' << "vlldm" << '\t';95 printRegName(O, Reg.getReg());96 O << ", "97 << "{d0 - d15}";98 return;99 }100 case ARM::VLLDM_T2: {101 const MCOperand &Reg = MI->getOperand(0);102 O << '\t' << "vlldm" << '\t';103 printRegName(O, Reg.getReg());104 O << ", "105 << "{d0 - d31}";106 return;107 }108 case ARM::VLSTM: {109 const MCOperand &Reg = MI->getOperand(0);110 O << '\t' << "vlstm" << '\t';111 printRegName(O, Reg.getReg());112 O << ", "113 << "{d0 - d15}";114 return;115 }116 case ARM::VLSTM_T2: {117 const MCOperand &Reg = MI->getOperand(0);118 O << '\t' << "vlstm" << '\t';119 printRegName(O, Reg.getReg());120 O << ", "121 << "{d0 - d31}";122 return;123 }124 // Check for MOVs and print canonical forms, instead.125 case ARM::MOVsr: {126 // FIXME: Thumb variants?127 const MCOperand &Dst = MI->getOperand(0);128 const MCOperand &MO1 = MI->getOperand(1);129 const MCOperand &MO2 = MI->getOperand(2);130 const MCOperand &MO3 = MI->getOperand(3);131 132 O << '\t' << ARM_AM::getShiftOpcStr(ARM_AM::getSORegShOp(MO3.getImm()));133 printSBitModifierOperand(MI, 6, STI, O);134 printPredicateOperand(MI, 4, STI, O);135 136 O << '\t';137 printRegName(O, Dst.getReg());138 O << ", ";139 printRegName(O, MO1.getReg());140 141 O << ", ";142 printRegName(O, MO2.getReg());143 assert(ARM_AM::getSORegOffset(MO3.getImm()) == 0);144 printAnnotation(O, Annot);145 return;146 }147 148 case ARM::MOVsi: {149 // FIXME: Thumb variants?150 const MCOperand &Dst = MI->getOperand(0);151 const MCOperand &MO1 = MI->getOperand(1);152 const MCOperand &MO2 = MI->getOperand(2);153 154 O << '\t' << ARM_AM::getShiftOpcStr(ARM_AM::getSORegShOp(MO2.getImm()));155 printSBitModifierOperand(MI, 5, STI, O);156 printPredicateOperand(MI, 3, STI, O);157 158 O << '\t';159 printRegName(O, Dst.getReg());160 O << ", ";161 printRegName(O, MO1.getReg());162 163 if (ARM_AM::getSORegShOp(MO2.getImm()) == ARM_AM::rrx) {164 printAnnotation(O, Annot);165 return;166 }167 168 O << ", ";169 markup(O, Markup::Immediate)170 << "#" << translateShiftImm(ARM_AM::getSORegOffset(MO2.getImm()));171 printAnnotation(O, Annot);172 return;173 }174 175 // A8.6.123 PUSH176 case ARM::STMDB_UPD:177 case ARM::t2STMDB_UPD:178 if (MI->getOperand(0).getReg() == ARM::SP && MI->getNumOperands() > 5) {179 // Should only print PUSH if there are at least two registers in the list.180 O << '\t' << "push";181 printPredicateOperand(MI, 2, STI, O);182 if (Opcode == ARM::t2STMDB_UPD)183 O << ".w";184 O << '\t';185 printRegisterList(MI, 4, STI, O);186 printAnnotation(O, Annot);187 return;188 } else189 break;190 191 case ARM::STR_PRE_IMM:192 if (MI->getOperand(2).getReg() == ARM::SP &&193 MI->getOperand(3).getImm() == -4) {194 O << '\t' << "push";195 printPredicateOperand(MI, 4, STI, O);196 O << "\t{";197 printRegName(O, MI->getOperand(1).getReg());198 O << "}";199 printAnnotation(O, Annot);200 return;201 } else202 break;203 204 // A8.6.122 POP205 case ARM::LDMIA_UPD:206 case ARM::t2LDMIA_UPD:207 if (MI->getOperand(0).getReg() == ARM::SP && MI->getNumOperands() > 5) {208 // Should only print POP if there are at least two registers in the list.209 O << '\t' << "pop";210 printPredicateOperand(MI, 2, STI, O);211 if (Opcode == ARM::t2LDMIA_UPD)212 O << ".w";213 O << '\t';214 printRegisterList(MI, 4, STI, O);215 printAnnotation(O, Annot);216 return;217 } else218 break;219 220 case ARM::LDR_POST_IMM:221 if (MI->getOperand(2).getReg() == ARM::SP &&222 MI->getOperand(4).getImm() == 4) {223 O << '\t' << "pop";224 printPredicateOperand(MI, 5, STI, O);225 O << "\t{";226 printRegName(O, MI->getOperand(0).getReg());227 O << "}";228 printAnnotation(O, Annot);229 return;230 } else231 break;232 233 // A8.6.355 VPUSH234 case ARM::VSTMSDB_UPD:235 case ARM::VSTMDDB_UPD:236 if (MI->getOperand(0).getReg() == ARM::SP) {237 O << '\t' << "vpush";238 printPredicateOperand(MI, 2, STI, O);239 O << '\t';240 printRegisterList(MI, 4, STI, O);241 printAnnotation(O, Annot);242 return;243 } else244 break;245 246 // A8.6.354 VPOP247 case ARM::VLDMSIA_UPD:248 case ARM::VLDMDIA_UPD:249 if (MI->getOperand(0).getReg() == ARM::SP) {250 O << '\t' << "vpop";251 printPredicateOperand(MI, 2, STI, O);252 O << '\t';253 printRegisterList(MI, 4, STI, O);254 printAnnotation(O, Annot);255 return;256 } else257 break;258 259 case ARM::tLDMIA: {260 bool Writeback = true;261 MCRegister BaseReg = MI->getOperand(0).getReg();262 for (unsigned i = 3; i < MI->getNumOperands(); ++i) {263 if (MI->getOperand(i).getReg() == BaseReg)264 Writeback = false;265 }266 267 O << "\tldm";268 269 printPredicateOperand(MI, 1, STI, O);270 O << '\t';271 printRegName(O, BaseReg);272 if (Writeback)273 O << "!";274 O << ", ";275 printRegisterList(MI, 3, STI, O);276 printAnnotation(O, Annot);277 return;278 }279 280 // Combine 2 GPRs from disassember into a GPRPair to match with instr def.281 // ldrexd/strexd require even/odd GPR pair. To enforce this constraint,282 // a single GPRPair reg operand is used in the .td file to replace the two283 // GPRs. However, when decoding them, the two GRPs cannot be automatically284 // expressed as a GPRPair, so we have to manually merge them.285 // FIXME: We would really like to be able to tablegen'erate this.286 case ARM::LDREXD:287 case ARM::STREXD:288 case ARM::LDAEXD:289 case ARM::STLEXD: {290 const MCRegisterClass &MRC = MRI.getRegClass(ARM::GPRRegClassID);291 bool isStore = Opcode == ARM::STREXD || Opcode == ARM::STLEXD;292 MCRegister Reg = MI->getOperand(isStore ? 1 : 0).getReg();293 if (MRC.contains(Reg)) {294 MCInst NewMI;295 MCOperand NewReg;296 NewMI.setOpcode(Opcode);297 298 if (isStore)299 NewMI.addOperand(MI->getOperand(0));300 NewReg = MCOperand::createReg(MRI.getMatchingSuperReg(301 Reg, ARM::gsub_0, &MRI.getRegClass(ARM::GPRPairRegClassID)));302 NewMI.addOperand(NewReg);303 304 // Copy the rest operands into NewMI.305 for (unsigned i = isStore ? 3 : 2; i < MI->getNumOperands(); ++i)306 NewMI.addOperand(MI->getOperand(i));307 printInstruction(&NewMI, Address, STI, O);308 return;309 }310 break;311 }312 case ARM::TSB:313 case ARM::t2TSB:314 O << "\ttsb\tcsync";315 return;316 case ARM::t2DSB:317 switch (MI->getOperand(0).getImm()) {318 default:319 if (!printAliasInstr(MI, Address, STI, O))320 printInstruction(MI, Address, STI, O);321 break;322 case 0:323 O << "\tssbb";324 break;325 case 4:326 O << "\tpssbb";327 break;328 }329 printAnnotation(O, Annot);330 return;331 }332 333 if (!printAliasInstr(MI, Address, STI, O))334 printInstruction(MI, Address, STI, O);335 336 printAnnotation(O, Annot);337}338 339void ARMInstPrinter::printOperand(const MCInst *MI, unsigned OpNo,340 const MCSubtargetInfo &STI, raw_ostream &O) {341 const MCOperand &Op = MI->getOperand(OpNo);342 if (Op.isReg()) {343 MCRegister Reg = Op.getReg();344 printRegName(O, Reg);345 } else if (Op.isImm()) {346 markup(O, Markup::Immediate) << '#' << formatImm(Op.getImm());347 } else {348 assert(Op.isExpr() && "unknown operand kind in printOperand");349 const MCExpr *Expr = Op.getExpr();350 switch (Expr->getKind()) {351 case MCExpr::Binary:352 O << '#';353 MAI.printExpr(O, *Expr);354 break;355 case MCExpr::Constant: {356 // If a symbolic branch target was added as a constant expression then357 // print that address in hex. And only print 32 unsigned bits for the358 // address.359 const MCConstantExpr *Constant = cast<MCConstantExpr>(Expr);360 int64_t TargetAddress;361 if (!Constant->evaluateAsAbsolute(TargetAddress)) {362 O << '#';363 MAI.printExpr(O, *Expr);364 } else {365 O << "0x";366 O.write_hex(static_cast<uint32_t>(TargetAddress));367 }368 break;369 }370 default:371 // FIXME: Should we always treat this as if it is a constant literal and372 // prefix it with '#'?373 MAI.printExpr(O, *Expr);374 break;375 }376 }377}378 379void ARMInstPrinter::printOperand(const MCInst *MI, uint64_t Address,380 unsigned OpNum, const MCSubtargetInfo &STI,381 raw_ostream &O) {382 const MCOperand &Op = MI->getOperand(OpNum);383 if (!Op.isImm() || !PrintBranchImmAsAddress || getUseMarkup())384 return printOperand(MI, OpNum, STI, O);385 uint64_t Target = ARM_MC::evaluateBranchTarget(MII.get(MI->getOpcode()),386 Address, Op.getImm());387 Target &= 0xffffffff;388 O << formatHex(Target);389 if (CommentStream)390 *CommentStream << "imm = #" << formatImm(Op.getImm()) << '\n';391}392 393void ARMInstPrinter::printThumbLdrLabelOperand(const MCInst *MI, unsigned OpNum,394 const MCSubtargetInfo &STI,395 raw_ostream &O) {396 const MCOperand &MO1 = MI->getOperand(OpNum);397 if (MO1.isExpr()) {398 MAI.printExpr(O, *MO1.getExpr());399 return;400 }401 402 WithMarkup ScopedMarkup = markup(O, Markup::Memory);403 O << "[pc, ";404 405 int32_t OffImm = (int32_t)MO1.getImm();406 bool isSub = OffImm < 0;407 408 // Special value for #-0. All others are normal.409 if (OffImm == INT32_MIN)410 OffImm = 0;411 if (isSub) {412 markup(O, Markup::Immediate) << "#-" << formatImm(-OffImm);413 } else {414 markup(O, Markup::Immediate) << "#" << formatImm(OffImm);415 }416 O << "]";417}418 419// so_reg is a 4-operand unit corresponding to register forms of the A5.1420// "Addressing Mode 1 - Data-processing operands" forms. This includes:421// REG 0 0 - e.g. R5422// REG REG 0,SH_OPC - e.g. R5, ROR R3423// REG 0 IMM,SH_OPC - e.g. R5, LSL #3424void ARMInstPrinter::printSORegRegOperand(const MCInst *MI, unsigned OpNum,425 const MCSubtargetInfo &STI,426 raw_ostream &O) {427 const MCOperand &MO1 = MI->getOperand(OpNum);428 const MCOperand &MO2 = MI->getOperand(OpNum + 1);429 const MCOperand &MO3 = MI->getOperand(OpNum + 2);430 431 printRegName(O, MO1.getReg());432 433 // Print the shift opc.434 ARM_AM::ShiftOpc ShOpc = ARM_AM::getSORegShOp(MO3.getImm());435 O << ", " << ARM_AM::getShiftOpcStr(ShOpc);436 if (ShOpc == ARM_AM::rrx)437 return;438 439 O << ' ';440 printRegName(O, MO2.getReg());441 assert(ARM_AM::getSORegOffset(MO3.getImm()) == 0);442}443 444void ARMInstPrinter::printSORegImmOperand(const MCInst *MI, unsigned OpNum,445 const MCSubtargetInfo &STI,446 raw_ostream &O) {447 const MCOperand &MO1 = MI->getOperand(OpNum);448 const MCOperand &MO2 = MI->getOperand(OpNum + 1);449 450 printRegName(O, MO1.getReg());451 452 // Print the shift opc.453 printRegImmShift(O, ARM_AM::getSORegShOp(MO2.getImm()),454 ARM_AM::getSORegOffset(MO2.getImm()), *this);455}456 457//===--------------------------------------------------------------------===//458// Addressing Mode #2459//===--------------------------------------------------------------------===//460 461void ARMInstPrinter::printAM2PreOrOffsetIndexOp(const MCInst *MI, unsigned Op,462 const MCSubtargetInfo &STI,463 raw_ostream &O) {464 const MCOperand &MO1 = MI->getOperand(Op);465 const MCOperand &MO2 = MI->getOperand(Op + 1);466 const MCOperand &MO3 = MI->getOperand(Op + 2);467 468 WithMarkup ScopedMarkup = markup(O, Markup::Memory);469 O << "[";470 printRegName(O, MO1.getReg());471 472 if (!MO2.getReg()) {473 if (ARM_AM::getAM2Offset(MO3.getImm())) { // Don't print +0.474 O << ", ";475 markup(O, Markup::Immediate)476 << "#" << ARM_AM::getAddrOpcStr(ARM_AM::getAM2Op(MO3.getImm()))477 << ARM_AM::getAM2Offset(MO3.getImm());478 }479 O << "]";480 return;481 }482 483 O << ", ";484 O << ARM_AM::getAddrOpcStr(ARM_AM::getAM2Op(MO3.getImm()));485 printRegName(O, MO2.getReg());486 487 printRegImmShift(O, ARM_AM::getAM2ShiftOpc(MO3.getImm()),488 ARM_AM::getAM2Offset(MO3.getImm()), *this);489 O << "]";490}491 492void ARMInstPrinter::printAddrModeTBB(const MCInst *MI, unsigned Op,493 const MCSubtargetInfo &STI,494 raw_ostream &O) {495 const MCOperand &MO1 = MI->getOperand(Op);496 const MCOperand &MO2 = MI->getOperand(Op + 1);497 498 WithMarkup ScopedMarkup = markup(O, Markup::Memory);499 O << "[";500 printRegName(O, MO1.getReg());501 O << ", ";502 printRegName(O, MO2.getReg());503 O << "]";504}505 506void ARMInstPrinter::printAddrModeTBH(const MCInst *MI, unsigned Op,507 const MCSubtargetInfo &STI,508 raw_ostream &O) {509 const MCOperand &MO1 = MI->getOperand(Op);510 const MCOperand &MO2 = MI->getOperand(Op + 1);511 WithMarkup ScopedMarkup = markup(O, Markup::Memory);512 O << "[";513 printRegName(O, MO1.getReg());514 O << ", ";515 printRegName(O, MO2.getReg());516 O << ", lsl ";517 markup(O, Markup::Immediate) << "#1";518 O << "]";519}520 521void ARMInstPrinter::printAddrMode2Operand(const MCInst *MI, unsigned Op,522 const MCSubtargetInfo &STI,523 raw_ostream &O) {524 const MCOperand &MO1 = MI->getOperand(Op);525 526 if (!MO1.isReg()) { // FIXME: This is for CP entries, but isn't right.527 printOperand(MI, Op, STI, O);528 return;529 }530 531#ifndef NDEBUG532 const MCOperand &MO3 = MI->getOperand(Op + 2);533 unsigned IdxMode = ARM_AM::getAM2IdxMode(MO3.getImm());534 assert(IdxMode != ARMII::IndexModePost && "Should be pre or offset index op");535#endif536 537 printAM2PreOrOffsetIndexOp(MI, Op, STI, O);538}539 540void ARMInstPrinter::printAddrMode2OffsetOperand(const MCInst *MI,541 unsigned OpNum,542 const MCSubtargetInfo &STI,543 raw_ostream &O) {544 const MCOperand &MO1 = MI->getOperand(OpNum);545 const MCOperand &MO2 = MI->getOperand(OpNum + 1);546 547 if (!MO1.getReg()) {548 unsigned ImmOffs = ARM_AM::getAM2Offset(MO2.getImm());549 markup(O, Markup::Immediate)550 << '#' << ARM_AM::getAddrOpcStr(ARM_AM::getAM2Op(MO2.getImm()))551 << ImmOffs;552 return;553 }554 555 O << ARM_AM::getAddrOpcStr(ARM_AM::getAM2Op(MO2.getImm()));556 printRegName(O, MO1.getReg());557 558 printRegImmShift(O, ARM_AM::getAM2ShiftOpc(MO2.getImm()),559 ARM_AM::getAM2Offset(MO2.getImm()), *this);560}561 562//===--------------------------------------------------------------------===//563// Addressing Mode #3564//===--------------------------------------------------------------------===//565 566void ARMInstPrinter::printAM3PreOrOffsetIndexOp(const MCInst *MI, unsigned Op,567 raw_ostream &O,568 bool AlwaysPrintImm0) {569 const MCOperand &MO1 = MI->getOperand(Op);570 const MCOperand &MO2 = MI->getOperand(Op + 1);571 const MCOperand &MO3 = MI->getOperand(Op + 2);572 573 WithMarkup ScopedMarkup = markup(O, Markup::Memory);574 O << '[';575 printRegName(O, MO1.getReg());576 577 if (MO2.getReg()) {578 O << ", " << getAddrOpcStr(ARM_AM::getAM3Op(MO3.getImm()));579 printRegName(O, MO2.getReg());580 O << ']';581 return;582 }583 584 // If the op is sub we have to print the immediate even if it is 0585 unsigned ImmOffs = ARM_AM::getAM3Offset(MO3.getImm());586 ARM_AM::AddrOpc op = ARM_AM::getAM3Op(MO3.getImm());587 588 if (AlwaysPrintImm0 || ImmOffs || (op == ARM_AM::sub)) {589 O << ", ";590 markup(O, Markup::Immediate) << "#" << ARM_AM::getAddrOpcStr(op) << ImmOffs;591 }592 O << ']';593}594 595template <bool AlwaysPrintImm0>596void ARMInstPrinter::printAddrMode3Operand(const MCInst *MI, unsigned Op,597 const MCSubtargetInfo &STI,598 raw_ostream &O) {599 const MCOperand &MO1 = MI->getOperand(Op);600 if (!MO1.isReg()) { // For label symbolic references.601 printOperand(MI, Op, STI, O);602 return;603 }604 605 assert(ARM_AM::getAM3IdxMode(MI->getOperand(Op + 2).getImm()) !=606 ARMII::IndexModePost &&607 "unexpected idxmode");608 printAM3PreOrOffsetIndexOp(MI, Op, O, AlwaysPrintImm0);609}610 611void ARMInstPrinter::printAddrMode3OffsetOperand(const MCInst *MI,612 unsigned OpNum,613 const MCSubtargetInfo &STI,614 raw_ostream &O) {615 const MCOperand &MO1 = MI->getOperand(OpNum);616 const MCOperand &MO2 = MI->getOperand(OpNum + 1);617 618 if (MO1.getReg()) {619 O << getAddrOpcStr(ARM_AM::getAM3Op(MO2.getImm()));620 printRegName(O, MO1.getReg());621 return;622 }623 624 unsigned ImmOffs = ARM_AM::getAM3Offset(MO2.getImm());625 markup(O, Markup::Immediate)626 << '#' << ARM_AM::getAddrOpcStr(ARM_AM::getAM3Op(MO2.getImm()))627 << ImmOffs;628}629 630void ARMInstPrinter::printPostIdxImm8Operand(const MCInst *MI, unsigned OpNum,631 const MCSubtargetInfo &STI,632 raw_ostream &O) {633 const MCOperand &MO = MI->getOperand(OpNum);634 unsigned Imm = MO.getImm();635 markup(O, Markup::Immediate)636 << '#' << ((Imm & 256) ? "" : "-") << (Imm & 0xff);637}638 639void ARMInstPrinter::printPostIdxRegOperand(const MCInst *MI, unsigned OpNum,640 const MCSubtargetInfo &STI,641 raw_ostream &O) {642 const MCOperand &MO1 = MI->getOperand(OpNum);643 const MCOperand &MO2 = MI->getOperand(OpNum + 1);644 645 O << (MO2.getImm() ? "" : "-");646 printRegName(O, MO1.getReg());647}648 649void ARMInstPrinter::printPostIdxImm8s4Operand(const MCInst *MI, unsigned OpNum,650 const MCSubtargetInfo &STI,651 raw_ostream &O) {652 const MCOperand &MO = MI->getOperand(OpNum);653 unsigned Imm = MO.getImm();654 markup(O, Markup::Immediate)655 << '#' << ((Imm & 256) ? "" : "-") << ((Imm & 0xff) << 2);656}657 658template<int shift>659void ARMInstPrinter::printMveAddrModeRQOperand(const MCInst *MI, unsigned OpNum,660 const MCSubtargetInfo &STI,661 raw_ostream &O) {662 const MCOperand &MO1 = MI->getOperand(OpNum);663 const MCOperand &MO2 = MI->getOperand(OpNum + 1);664 665 WithMarkup ScopedMarkup = markup(O, Markup::Memory);666 O << "[";667 printRegName(O, MO1.getReg());668 O << ", ";669 printRegName(O, MO2.getReg());670 671 if (shift > 0)672 printRegImmShift(O, ARM_AM::uxtw, shift, *this);673 674 O << "]";675}676 677void ARMInstPrinter::printLdStmModeOperand(const MCInst *MI, unsigned OpNum,678 const MCSubtargetInfo &STI,679 raw_ostream &O) {680 ARM_AM::AMSubMode Mode =681 ARM_AM::getAM4SubMode(MI->getOperand(OpNum).getImm());682 O << ARM_AM::getAMSubModeStr(Mode);683}684 685template <bool AlwaysPrintImm0>686void ARMInstPrinter::printAddrMode5Operand(const MCInst *MI, unsigned OpNum,687 const MCSubtargetInfo &STI,688 raw_ostream &O) {689 const MCOperand &MO1 = MI->getOperand(OpNum);690 const MCOperand &MO2 = MI->getOperand(OpNum + 1);691 692 if (!MO1.isReg()) { // FIXME: This is for CP entries, but isn't right.693 printOperand(MI, OpNum, STI, O);694 return;695 }696 697 WithMarkup ScopedMarkup = markup(O, Markup::Memory);698 O << "[";699 printRegName(O, MO1.getReg());700 701 unsigned ImmOffs = ARM_AM::getAM5Offset(MO2.getImm());702 ARM_AM::AddrOpc Op = ARM_AM::getAM5Op(MO2.getImm());703 if (AlwaysPrintImm0 || ImmOffs || Op == ARM_AM::sub) {704 O << ", ";705 markup(O, Markup::Immediate)706 << "#" << ARM_AM::getAddrOpcStr(Op) << ImmOffs * 4;707 }708 O << "]";709}710 711template <bool AlwaysPrintImm0>712void ARMInstPrinter::printAddrMode5FP16Operand(const MCInst *MI, unsigned OpNum,713 const MCSubtargetInfo &STI,714 raw_ostream &O) {715 const MCOperand &MO1 = MI->getOperand(OpNum);716 const MCOperand &MO2 = MI->getOperand(OpNum+1);717 718 if (!MO1.isReg()) { // FIXME: This is for CP entries, but isn't right.719 printOperand(MI, OpNum, STI, O);720 return;721 }722 723 WithMarkup ScopedMarkup = markup(O, Markup::Memory);724 O << "[";725 printRegName(O, MO1.getReg());726 727 unsigned ImmOffs = ARM_AM::getAM5FP16Offset(MO2.getImm());728 unsigned Op = ARM_AM::getAM5FP16Op(MO2.getImm());729 if (AlwaysPrintImm0 || ImmOffs || Op == ARM_AM::sub) {730 O << ", ";731 markup(O, Markup::Immediate)732 << "#" << ARM_AM::getAddrOpcStr(ARM_AM::getAM5FP16Op(MO2.getImm()))733 << ImmOffs * 2;734 }735 O << "]";736}737 738void ARMInstPrinter::printAddrMode6Operand(const MCInst *MI, unsigned OpNum,739 const MCSubtargetInfo &STI,740 raw_ostream &O) {741 const MCOperand &MO1 = MI->getOperand(OpNum);742 const MCOperand &MO2 = MI->getOperand(OpNum + 1);743 744 WithMarkup ScopedMarkup = markup(O, Markup::Memory);745 O << "[";746 printRegName(O, MO1.getReg());747 if (MO2.getImm()) {748 O << ":" << (MO2.getImm() << 3);749 }750 O << "]";751}752 753void ARMInstPrinter::printAddrMode7Operand(const MCInst *MI, unsigned OpNum,754 const MCSubtargetInfo &STI,755 raw_ostream &O) {756 const MCOperand &MO1 = MI->getOperand(OpNum);757 WithMarkup ScopedMarkup = markup(O, Markup::Memory);758 O << "[";759 printRegName(O, MO1.getReg());760 O << "]";761}762 763void ARMInstPrinter::printAddrMode6OffsetOperand(const MCInst *MI,764 unsigned OpNum,765 const MCSubtargetInfo &STI,766 raw_ostream &O) {767 const MCOperand &MO = MI->getOperand(OpNum);768 if (!MO.getReg())769 O << "!";770 else {771 O << ", ";772 printRegName(O, MO.getReg());773 }774}775 776void ARMInstPrinter::printBitfieldInvMaskImmOperand(const MCInst *MI,777 unsigned OpNum,778 const MCSubtargetInfo &STI,779 raw_ostream &O) {780 const MCOperand &MO = MI->getOperand(OpNum);781 uint32_t v = ~MO.getImm();782 int32_t lsb = llvm::countr_zero(v);783 int32_t width = llvm::bit_width(v) - lsb;784 assert(MO.isImm() && "Not a valid bf_inv_mask_imm value!");785 markup(O, Markup::Immediate) << '#' << lsb;786 O << ", ";787 markup(O, Markup::Immediate) << '#' << width;788}789 790void ARMInstPrinter::printMemBOption(const MCInst *MI, unsigned OpNum,791 const MCSubtargetInfo &STI,792 raw_ostream &O) {793 unsigned val = MI->getOperand(OpNum).getImm();794 O << ARM_MB::MemBOptToString(val, STI.hasFeature(ARM::HasV8Ops));795}796 797void ARMInstPrinter::printInstSyncBOption(const MCInst *MI, unsigned OpNum,798 const MCSubtargetInfo &STI,799 raw_ostream &O) {800 unsigned val = MI->getOperand(OpNum).getImm();801 O << ARM_ISB::InstSyncBOptToString(val);802}803 804void ARMInstPrinter::printTraceSyncBOption(const MCInst *MI, unsigned OpNum,805 const MCSubtargetInfo &STI,806 raw_ostream &O) {807 unsigned val = MI->getOperand(OpNum).getImm();808 O << ARM_TSB::TraceSyncBOptToString(val);809}810 811void ARMInstPrinter::printShiftImmOperand(const MCInst *MI, unsigned OpNum,812 const MCSubtargetInfo &STI,813 raw_ostream &O) {814 unsigned ShiftOp = MI->getOperand(OpNum).getImm();815 bool isASR = (ShiftOp & (1 << 5)) != 0;816 unsigned Amt = ShiftOp & 0x1f;817 if (isASR) {818 O << ", asr ";819 markup(O, Markup::Immediate) << "#" << (Amt == 0 ? 32 : Amt);820 } else if (Amt) {821 O << ", lsl ";822 markup(O, Markup::Immediate) << "#" << Amt;823 }824}825 826void ARMInstPrinter::printPKHLSLShiftImm(const MCInst *MI, unsigned OpNum,827 const MCSubtargetInfo &STI,828 raw_ostream &O) {829 unsigned Imm = MI->getOperand(OpNum).getImm();830 if (Imm == 0)831 return;832 assert(Imm > 0 && Imm < 32 && "Invalid PKH shift immediate value!");833 O << ", lsl ";834 markup(O, Markup::Immediate) << "#" << Imm;835}836 837void ARMInstPrinter::printPKHASRShiftImm(const MCInst *MI, unsigned OpNum,838 const MCSubtargetInfo &STI,839 raw_ostream &O) {840 unsigned Imm = MI->getOperand(OpNum).getImm();841 // A shift amount of 32 is encoded as 0.842 if (Imm == 0)843 Imm = 32;844 assert(Imm > 0 && Imm <= 32 && "Invalid PKH shift immediate value!");845 O << ", asr ";846 markup(O, Markup::Immediate) << "#" << Imm;847}848 849void ARMInstPrinter::printRegisterList(const MCInst *MI, unsigned OpNum,850 const MCSubtargetInfo &STI,851 raw_ostream &O) {852 if (MI->getOpcode() != ARM::t2CLRM && MI->getOpcode() != ARM::VSCCLRMS) {853 assert(is_sorted(drop_begin(*MI, OpNum),854 [&](const MCOperand &LHS, const MCOperand &RHS) {855 return MRI.getEncodingValue(LHS.getReg()) <856 MRI.getEncodingValue(RHS.getReg());857 }));858 }859 860 O << "{";861 for (unsigned i = OpNum, e = MI->getNumOperands(); i != e; ++i) {862 if (i != OpNum)863 O << ", ";864 printRegName(O, MI->getOperand(i).getReg());865 }866 O << "}";867}868 869void ARMInstPrinter::printGPRPairOperand(const MCInst *MI, unsigned OpNum,870 const MCSubtargetInfo &STI,871 raw_ostream &O) {872 MCRegister Reg = MI->getOperand(OpNum).getReg();873 printRegName(O, MRI.getSubReg(Reg, ARM::gsub_0));874 O << ", ";875 printRegName(O, MRI.getSubReg(Reg, ARM::gsub_1));876}877 878void ARMInstPrinter::printSetendOperand(const MCInst *MI, unsigned OpNum,879 const MCSubtargetInfo &STI,880 raw_ostream &O) {881 const MCOperand &Op = MI->getOperand(OpNum);882 if (Op.getImm())883 O << "be";884 else885 O << "le";886}887 888void ARMInstPrinter::printCPSIMod(const MCInst *MI, unsigned OpNum,889 const MCSubtargetInfo &STI, raw_ostream &O) {890 const MCOperand &Op = MI->getOperand(OpNum);891 O << ARM_PROC::IModToString(Op.getImm());892}893 894void ARMInstPrinter::printCPSIFlag(const MCInst *MI, unsigned OpNum,895 const MCSubtargetInfo &STI, raw_ostream &O) {896 const MCOperand &Op = MI->getOperand(OpNum);897 unsigned IFlags = Op.getImm();898 for (int i = 2; i >= 0; --i)899 if (IFlags & (1 << i))900 O << ARM_PROC::IFlagsToString(1 << i);901 902 if (IFlags == 0)903 O << "none";904}905 906void ARMInstPrinter::printMSRMaskOperand(const MCInst *MI, unsigned OpNum,907 const MCSubtargetInfo &STI,908 raw_ostream &O) {909 const MCOperand &Op = MI->getOperand(OpNum);910 const FeatureBitset &FeatureBits = STI.getFeatureBits();911 if (FeatureBits[ARM::FeatureMClass]) {912 913 unsigned SYSm = Op.getImm() & 0xFFF; // 12-bit SYSm914 unsigned Opcode = MI->getOpcode();915 916 // For writes, handle extended mask bits if the DSP extension is present.917 if (Opcode == ARM::t2MSR_M && FeatureBits[ARM::FeatureDSP]) {918 auto TheReg =ARMSysReg::lookupMClassSysRegBy12bitSYSmValue(SYSm);919 if (TheReg && TheReg->isInRequiredFeatures({ARM::FeatureDSP})) {920 O << TheReg->Name;921 return;922 }923 }924 925 // Handle the basic 8-bit mask.926 SYSm &= 0xff;927 if (Opcode == ARM::t2MSR_M && FeatureBits [ARM::HasV7Ops]) {928 // ARMv7-M deprecates using MSR APSR without a _<bits> qualifier as an929 // alias for MSR APSR_nzcvq.930 auto TheReg = ARMSysReg::lookupMClassSysRegAPSRNonDeprecated(SYSm);931 if (TheReg) {932 O << TheReg->Name;933 return;934 }935 }936 937 auto TheReg = ARMSysReg::lookupMClassSysRegBy8bitSYSmValue(SYSm);938 if (TheReg) {939 O << TheReg->Name;940 return;941 }942 943 O << SYSm;944 945 return;946 }947 948 // As special cases, CPSR_f, CPSR_s and CPSR_fs prefer printing as949 // APSR_nzcvq, APSR_g and APSRnzcvqg, respectively.950 unsigned SpecRegRBit = Op.getImm() >> 4;951 unsigned Mask = Op.getImm() & 0xf;952 953 if (!SpecRegRBit && (Mask == 8 || Mask == 4 || Mask == 12)) {954 O << "APSR_";955 switch (Mask) {956 default:957 llvm_unreachable("Unexpected mask value!");958 case 4:959 O << "g";960 return;961 case 8:962 O << "nzcvq";963 return;964 case 12:965 O << "nzcvqg";966 return;967 }968 }969 970 if (SpecRegRBit)971 O << "SPSR";972 else973 O << "CPSR";974 975 if (Mask) {976 O << '_';977 if (Mask & 8)978 O << 'f';979 if (Mask & 4)980 O << 's';981 if (Mask & 2)982 O << 'x';983 if (Mask & 1)984 O << 'c';985 }986}987 988void ARMInstPrinter::printBankedRegOperand(const MCInst *MI, unsigned OpNum,989 const MCSubtargetInfo &STI,990 raw_ostream &O) {991 uint32_t Banked = MI->getOperand(OpNum).getImm();992 auto TheReg = ARMBankedReg::lookupBankedRegByEncoding(Banked);993 assert(TheReg && "invalid banked register operand");994 std::string Name = TheReg->Name;995 996 uint32_t isSPSR = (Banked & 0x20) >> 5;997 if (isSPSR)998 Name.replace(0, 4, "SPSR"); // convert 'spsr_' to 'SPSR_'999 O << Name;1000}1001 1002void ARMInstPrinter::printPredicateOperand(const MCInst *MI, unsigned OpNum,1003 const MCSubtargetInfo &STI,1004 raw_ostream &O) {1005 ARMCC::CondCodes CC = (ARMCC::CondCodes)MI->getOperand(OpNum).getImm();1006 // Handle the undefined 15 CC value here for printing so we don't abort().1007 if ((unsigned)CC == 15)1008 O << "<und>";1009 else if (CC != ARMCC::AL)1010 O << ARMCondCodeToString(CC);1011}1012 1013void ARMInstPrinter::printMandatoryRestrictedPredicateOperand(1014 const MCInst *MI, unsigned OpNum, const MCSubtargetInfo &STI,1015 raw_ostream &O) {1016 if ((ARMCC::CondCodes)MI->getOperand(OpNum).getImm() == ARMCC::HS)1017 O << "cs";1018 else1019 printMandatoryPredicateOperand(MI, OpNum, STI, O);1020}1021 1022void ARMInstPrinter::printMandatoryPredicateOperand(const MCInst *MI,1023 unsigned OpNum,1024 const MCSubtargetInfo &STI,1025 raw_ostream &O) {1026 ARMCC::CondCodes CC = (ARMCC::CondCodes)MI->getOperand(OpNum).getImm();1027 O << ARMCondCodeToString(CC);1028}1029 1030void ARMInstPrinter::printMandatoryInvertedPredicateOperand(const MCInst *MI,1031 unsigned OpNum,1032 const MCSubtargetInfo &STI,1033 raw_ostream &O) {1034 ARMCC::CondCodes CC = (ARMCC::CondCodes)MI->getOperand(OpNum).getImm();1035 O << ARMCondCodeToString(ARMCC::getOppositeCondition(CC));1036}1037 1038void ARMInstPrinter::printSBitModifierOperand(const MCInst *MI, unsigned OpNum,1039 const MCSubtargetInfo &STI,1040 raw_ostream &O) {1041 if (MI->getOperand(OpNum).getReg()) {1042 assert(MI->getOperand(OpNum).getReg() == ARM::CPSR &&1043 "Expect ARM CPSR register!");1044 O << 's';1045 }1046}1047 1048void ARMInstPrinter::printNoHashImmediate(const MCInst *MI, unsigned OpNum,1049 const MCSubtargetInfo &STI,1050 raw_ostream &O) {1051 O << MI->getOperand(OpNum).getImm();1052}1053 1054void ARMInstPrinter::printPImmediate(const MCInst *MI, unsigned OpNum,1055 const MCSubtargetInfo &STI,1056 raw_ostream &O) {1057 O << "p" << MI->getOperand(OpNum).getImm();1058}1059 1060void ARMInstPrinter::printCImmediate(const MCInst *MI, unsigned OpNum,1061 const MCSubtargetInfo &STI,1062 raw_ostream &O) {1063 O << "c" << MI->getOperand(OpNum).getImm();1064}1065 1066void ARMInstPrinter::printCoprocOptionImm(const MCInst *MI, unsigned OpNum,1067 const MCSubtargetInfo &STI,1068 raw_ostream &O) {1069 O << "{" << MI->getOperand(OpNum).getImm() << "}";1070}1071 1072void ARMInstPrinter::printPCLabel(const MCInst *MI, unsigned OpNum,1073 const MCSubtargetInfo &STI, raw_ostream &O) {1074 llvm_unreachable("Unhandled PC-relative pseudo-instruction!");1075}1076 1077template <unsigned scale>1078void ARMInstPrinter::printAdrLabelOperand(const MCInst *MI, unsigned OpNum,1079 const MCSubtargetInfo &STI,1080 raw_ostream &O) {1081 const MCOperand &MO = MI->getOperand(OpNum);1082 1083 if (MO.isExpr()) {1084 MAI.printExpr(O, *MO.getExpr());1085 return;1086 }1087 1088 int32_t OffImm = (int32_t)MO.getImm() << scale;1089 1090 WithMarkup ScopedMarkup = markup(O, Markup::Immediate);1091 if (OffImm == INT32_MIN)1092 O << "#-0";1093 else if (OffImm < 0)1094 O << "#-" << -OffImm;1095 else1096 O << "#" << OffImm;1097}1098 1099void ARMInstPrinter::printThumbS4ImmOperand(const MCInst *MI, unsigned OpNum,1100 const MCSubtargetInfo &STI,1101 raw_ostream &O) {1102 markup(O, Markup::Immediate)1103 << "#" << formatImm(MI->getOperand(OpNum).getImm() * 4);1104}1105 1106void ARMInstPrinter::printThumbSRImm(const MCInst *MI, unsigned OpNum,1107 const MCSubtargetInfo &STI,1108 raw_ostream &O) {1109 unsigned Imm = MI->getOperand(OpNum).getImm();1110 markup(O, Markup::Immediate) << "#" << formatImm((Imm == 0 ? 32 : Imm));1111}1112 1113void ARMInstPrinter::printThumbITMask(const MCInst *MI, unsigned OpNum,1114 const MCSubtargetInfo &STI,1115 raw_ostream &O) {1116 // (3 - the number of trailing zeros) is the number of then / else.1117 unsigned Mask = MI->getOperand(OpNum).getImm();1118 unsigned NumTZ = llvm::countr_zero(Mask);1119 assert(NumTZ <= 3 && "Invalid IT mask!");1120 for (unsigned Pos = 3, e = NumTZ; Pos > e; --Pos) {1121 if ((Mask >> Pos) & 1)1122 O << 'e';1123 else1124 O << 't';1125 }1126}1127 1128void ARMInstPrinter::printThumbAddrModeRROperand(const MCInst *MI, unsigned Op,1129 const MCSubtargetInfo &STI,1130 raw_ostream &O) {1131 const MCOperand &MO1 = MI->getOperand(Op);1132 const MCOperand &MO2 = MI->getOperand(Op + 1);1133 1134 if (!MO1.isReg()) { // FIXME: This is for CP entries, but isn't right.1135 printOperand(MI, Op, STI, O);1136 return;1137 }1138 1139 WithMarkup ScopedMarkup = markup(O, Markup::Memory);1140 O << "[";1141 printRegName(O, MO1.getReg());1142 if (MCRegister RegNum = MO2.getReg()) {1143 O << ", ";1144 printRegName(O, RegNum);1145 }1146 O << "]";1147}1148 1149void ARMInstPrinter::printThumbAddrModeImm5SOperand(const MCInst *MI,1150 unsigned Op,1151 const MCSubtargetInfo &STI,1152 raw_ostream &O,1153 unsigned Scale) {1154 const MCOperand &MO1 = MI->getOperand(Op);1155 const MCOperand &MO2 = MI->getOperand(Op + 1);1156 1157 if (!MO1.isReg()) { // FIXME: This is for CP entries, but isn't right.1158 printOperand(MI, Op, STI, O);1159 return;1160 }1161 1162 WithMarkup ScopedMarkup = markup(O, Markup::Memory);1163 O << "[";1164 printRegName(O, MO1.getReg());1165 if (unsigned ImmOffs = MO2.getImm()) {1166 O << ", ";1167 markup(O, Markup::Immediate) << "#" << formatImm(ImmOffs * Scale);1168 }1169 O << "]";1170}1171 1172void ARMInstPrinter::printThumbAddrModeImm5S1Operand(const MCInst *MI,1173 unsigned Op,1174 const MCSubtargetInfo &STI,1175 raw_ostream &O) {1176 printThumbAddrModeImm5SOperand(MI, Op, STI, O, 1);1177}1178 1179void ARMInstPrinter::printThumbAddrModeImm5S2Operand(const MCInst *MI,1180 unsigned Op,1181 const MCSubtargetInfo &STI,1182 raw_ostream &O) {1183 printThumbAddrModeImm5SOperand(MI, Op, STI, O, 2);1184}1185 1186void ARMInstPrinter::printThumbAddrModeImm5S4Operand(const MCInst *MI,1187 unsigned Op,1188 const MCSubtargetInfo &STI,1189 raw_ostream &O) {1190 printThumbAddrModeImm5SOperand(MI, Op, STI, O, 4);1191}1192 1193void ARMInstPrinter::printThumbAddrModeSPOperand(const MCInst *MI, unsigned Op,1194 const MCSubtargetInfo &STI,1195 raw_ostream &O) {1196 printThumbAddrModeImm5SOperand(MI, Op, STI, O, 4);1197}1198 1199// Constant shifts t2_so_reg is a 2-operand unit corresponding to the Thumb21200// register with shift forms.1201// REG 0 0 - e.g. R51202// REG IMM, SH_OPC - e.g. R5, LSL #31203void ARMInstPrinter::printT2SOOperand(const MCInst *MI, unsigned OpNum,1204 const MCSubtargetInfo &STI,1205 raw_ostream &O) {1206 const MCOperand &MO1 = MI->getOperand(OpNum);1207 const MCOperand &MO2 = MI->getOperand(OpNum + 1);1208 1209 MCRegister Reg = MO1.getReg();1210 printRegName(O, Reg);1211 1212 // Print the shift opc.1213 assert(MO2.isImm() && "Not a valid t2_so_reg value!");1214 printRegImmShift(O, ARM_AM::getSORegShOp(MO2.getImm()),1215 ARM_AM::getSORegOffset(MO2.getImm()), *this);1216}1217 1218template <bool AlwaysPrintImm0>1219void ARMInstPrinter::printAddrModeImm12Operand(const MCInst *MI, unsigned OpNum,1220 const MCSubtargetInfo &STI,1221 raw_ostream &O) {1222 const MCOperand &MO1 = MI->getOperand(OpNum);1223 const MCOperand &MO2 = MI->getOperand(OpNum + 1);1224 1225 if (!MO1.isReg()) { // FIXME: This is for CP entries, but isn't right.1226 printOperand(MI, OpNum, STI, O);1227 return;1228 }1229 1230 WithMarkup ScopedMarkup = markup(O, Markup::Memory);1231 O << "[";1232 printRegName(O, MO1.getReg());1233 1234 int32_t OffImm = (int32_t)MO2.getImm();1235 bool isSub = OffImm < 0;1236 // Special value for #-0. All others are normal.1237 if (OffImm == INT32_MIN)1238 OffImm = 0;1239 if (isSub) {1240 O << ", ";1241 markup(O, Markup::Immediate) << "#-" << formatImm(-OffImm);1242 } else if (AlwaysPrintImm0 || OffImm > 0) {1243 O << ", ";1244 markup(O, Markup::Immediate) << "#" << formatImm(OffImm);1245 }1246 O << "]";1247}1248 1249template <bool AlwaysPrintImm0>1250void ARMInstPrinter::printT2AddrModeImm8Operand(const MCInst *MI,1251 unsigned OpNum,1252 const MCSubtargetInfo &STI,1253 raw_ostream &O) {1254 const MCOperand &MO1 = MI->getOperand(OpNum);1255 const MCOperand &MO2 = MI->getOperand(OpNum + 1);1256 1257 WithMarkup ScopedMarkup = markup(O, Markup::Memory);1258 O << "[";1259 printRegName(O, MO1.getReg());1260 1261 int32_t OffImm = (int32_t)MO2.getImm();1262 bool isSub = OffImm < 0;1263 // Don't print +0.1264 if (OffImm == INT32_MIN)1265 OffImm = 0;1266 if (isSub) {1267 O << ", ";1268 markup(O, Markup::Immediate) << "#-" << -OffImm;1269 } else if (AlwaysPrintImm0 || OffImm > 0) {1270 O << ", ";1271 markup(O, Markup::Immediate) << "#" << OffImm;1272 }1273 O << "]";1274}1275 1276template <bool AlwaysPrintImm0>1277void ARMInstPrinter::printT2AddrModeImm8s4Operand(const MCInst *MI,1278 unsigned OpNum,1279 const MCSubtargetInfo &STI,1280 raw_ostream &O) {1281 const MCOperand &MO1 = MI->getOperand(OpNum);1282 const MCOperand &MO2 = MI->getOperand(OpNum + 1);1283 1284 if (!MO1.isReg()) { // For label symbolic references.1285 printOperand(MI, OpNum, STI, O);1286 return;1287 }1288 1289 WithMarkup ScopedMarkup = markup(O, Markup::Memory);1290 O << "[";1291 printRegName(O, MO1.getReg());1292 1293 int32_t OffImm = (int32_t)MO2.getImm();1294 bool isSub = OffImm < 0;1295 1296 assert(((OffImm & 0x3) == 0) && "Not a valid immediate!");1297 1298 // Don't print +0.1299 if (OffImm == INT32_MIN)1300 OffImm = 0;1301 if (isSub) {1302 O << ", ";1303 markup(O, Markup::Immediate) << "#-" << -OffImm;1304 } else if (AlwaysPrintImm0 || OffImm > 0) {1305 O << ", ";1306 markup(O, Markup::Immediate) << "#" << OffImm;1307 }1308 O << "]";1309}1310 1311void ARMInstPrinter::printT2AddrModeImm0_1020s4Operand(1312 const MCInst *MI, unsigned OpNum, const MCSubtargetInfo &STI,1313 raw_ostream &O) {1314 const MCOperand &MO1 = MI->getOperand(OpNum);1315 const MCOperand &MO2 = MI->getOperand(OpNum + 1);1316 1317 WithMarkup ScopedMarkup = markup(O, Markup::Memory);1318 O << "[";1319 printRegName(O, MO1.getReg());1320 if (MO2.getImm()) {1321 O << ", ";1322 markup(O, Markup::Immediate) << "#" << formatImm(MO2.getImm() * 4);1323 }1324 O << "]";1325}1326 1327void ARMInstPrinter::printT2AddrModeImm8OffsetOperand(1328 const MCInst *MI, unsigned OpNum, const MCSubtargetInfo &STI,1329 raw_ostream &O) {1330 const MCOperand &MO1 = MI->getOperand(OpNum);1331 int32_t OffImm = (int32_t)MO1.getImm();1332 O << ", ";1333 WithMarkup ScopedMarkup = markup(O, Markup::Immediate);1334 if (OffImm == INT32_MIN)1335 O << "#-0";1336 else if (OffImm < 0)1337 O << "#-" << -OffImm;1338 else1339 O << "#" << OffImm;1340}1341 1342void ARMInstPrinter::printT2AddrModeImm8s4OffsetOperand(1343 const MCInst *MI, unsigned OpNum, const MCSubtargetInfo &STI,1344 raw_ostream &O) {1345 const MCOperand &MO1 = MI->getOperand(OpNum);1346 int32_t OffImm = (int32_t)MO1.getImm();1347 1348 assert(((OffImm & 0x3) == 0) && "Not a valid immediate!");1349 1350 O << ", ";1351 WithMarkup ScopedMarkup = markup(O, Markup::Immediate);1352 if (OffImm == INT32_MIN)1353 O << "#-0";1354 else if (OffImm < 0)1355 O << "#-" << -OffImm;1356 else1357 O << "#" << OffImm;1358}1359 1360void ARMInstPrinter::printT2AddrModeSoRegOperand(const MCInst *MI,1361 unsigned OpNum,1362 const MCSubtargetInfo &STI,1363 raw_ostream &O) {1364 const MCOperand &MO1 = MI->getOperand(OpNum);1365 const MCOperand &MO2 = MI->getOperand(OpNum + 1);1366 const MCOperand &MO3 = MI->getOperand(OpNum + 2);1367 1368 WithMarkup ScopedMarkup = markup(O, Markup::Memory);1369 O << "[";1370 printRegName(O, MO1.getReg());1371 1372 assert(MO2.getReg() && "Invalid so_reg load / store address!");1373 O << ", ";1374 printRegName(O, MO2.getReg());1375 1376 unsigned ShAmt = MO3.getImm();1377 if (ShAmt) {1378 assert(ShAmt <= 3 && "Not a valid Thumb2 addressing mode!");1379 O << ", lsl ";1380 markup(O, Markup::Immediate) << "#" << ShAmt;1381 }1382 O << "]";1383}1384 1385void ARMInstPrinter::printFPImmOperand(const MCInst *MI, unsigned OpNum,1386 const MCSubtargetInfo &STI,1387 raw_ostream &O) {1388 const MCOperand &MO = MI->getOperand(OpNum);1389 markup(O, Markup::Immediate) << '#' << ARM_AM::getFPImmFloat(MO.getImm());1390}1391 1392void ARMInstPrinter::printVMOVModImmOperand(const MCInst *MI, unsigned OpNum,1393 const MCSubtargetInfo &STI,1394 raw_ostream &O) {1395 unsigned EncodedImm = MI->getOperand(OpNum).getImm();1396 unsigned EltBits;1397 uint64_t Val = ARM_AM::decodeVMOVModImm(EncodedImm, EltBits);1398 1399 WithMarkup ScopedMarkup = markup(O, Markup::Immediate);1400 O << "#0x";1401 O.write_hex(Val);1402}1403 1404void ARMInstPrinter::printImmPlusOneOperand(const MCInst *MI, unsigned OpNum,1405 const MCSubtargetInfo &STI,1406 raw_ostream &O) {1407 unsigned Imm = MI->getOperand(OpNum).getImm();1408 markup(O, Markup::Immediate) << "#" << formatImm(Imm + 1);1409}1410 1411void ARMInstPrinter::printRotImmOperand(const MCInst *MI, unsigned OpNum,1412 const MCSubtargetInfo &STI,1413 raw_ostream &O) {1414 unsigned Imm = MI->getOperand(OpNum).getImm();1415 if (Imm == 0)1416 return;1417 assert(Imm <= 3 && "illegal ror immediate!");1418 O << ", ror ";1419 markup(O, Markup::Immediate) << "#" << 8 * Imm;1420}1421 1422void ARMInstPrinter::printModImmOperand(const MCInst *MI, unsigned OpNum,1423 const MCSubtargetInfo &STI,1424 raw_ostream &O) {1425 MCOperand Op = MI->getOperand(OpNum);1426 1427 // Support for fixups (MCFixup)1428 if (Op.isExpr())1429 return printOperand(MI, OpNum, STI, O);1430 1431 unsigned Bits = Op.getImm() & 0xFF;1432 unsigned Rot = (Op.getImm() & 0xF00) >> 7;1433 1434 bool PrintUnsigned = false;1435 switch (MI->getOpcode()) {1436 case ARM::MOVi:1437 // Movs to PC should be treated unsigned1438 PrintUnsigned = (MI->getOperand(OpNum - 1).getReg() == ARM::PC);1439 break;1440 case ARM::MSRi:1441 // Movs to special registers should be treated unsigned1442 PrintUnsigned = true;1443 break;1444 }1445 1446 int32_t Rotated = llvm::rotr<uint32_t>(Bits, Rot);1447 if (ARM_AM::getSOImmVal(Rotated) == Op.getImm()) {1448 // #rot has the least possible value1449 O << "#";1450 if (PrintUnsigned)1451 markup(O, Markup::Immediate) << static_cast<uint32_t>(Rotated);1452 else1453 markup(O, Markup::Immediate) << Rotated;1454 return;1455 }1456 1457 // Explicit #bits, #rot implied1458 O << "#";1459 markup(O, Markup::Immediate) << Bits;1460 O << ", #";1461 markup(O, Markup::Immediate) << Rot;1462}1463 1464void ARMInstPrinter::printFBits16(const MCInst *MI, unsigned OpNum,1465 const MCSubtargetInfo &STI, raw_ostream &O) {1466 markup(O, Markup::Immediate) << "#" << 16 - MI->getOperand(OpNum).getImm();1467}1468 1469void ARMInstPrinter::printFBits32(const MCInst *MI, unsigned OpNum,1470 const MCSubtargetInfo &STI, raw_ostream &O) {1471 markup(O, Markup::Immediate) << "#" << 32 - MI->getOperand(OpNum).getImm();1472}1473 1474void ARMInstPrinter::printVectorIndex(const MCInst *MI, unsigned OpNum,1475 const MCSubtargetInfo &STI,1476 raw_ostream &O) {1477 O << "[" << MI->getOperand(OpNum).getImm() << "]";1478}1479 1480void ARMInstPrinter::printVectorListOne(const MCInst *MI, unsigned OpNum,1481 const MCSubtargetInfo &STI,1482 raw_ostream &O) {1483 O << "{";1484 printRegName(O, MI->getOperand(OpNum).getReg());1485 O << "}";1486}1487 1488void ARMInstPrinter::printVectorListTwo(const MCInst *MI, unsigned OpNum,1489 const MCSubtargetInfo &STI,1490 raw_ostream &O) {1491 MCRegister Reg = MI->getOperand(OpNum).getReg();1492 MCRegister Reg0 = MRI.getSubReg(Reg, ARM::dsub_0);1493 MCRegister Reg1 = MRI.getSubReg(Reg, ARM::dsub_1);1494 O << "{";1495 printRegName(O, Reg0);1496 O << ", ";1497 printRegName(O, Reg1);1498 O << "}";1499}1500 1501void ARMInstPrinter::printVectorListTwoSpaced(const MCInst *MI, unsigned OpNum,1502 const MCSubtargetInfo &STI,1503 raw_ostream &O) {1504 MCRegister Reg = MI->getOperand(OpNum).getReg();1505 MCRegister Reg0 = MRI.getSubReg(Reg, ARM::dsub_0);1506 MCRegister Reg1 = MRI.getSubReg(Reg, ARM::dsub_2);1507 O << "{";1508 printRegName(O, Reg0);1509 O << ", ";1510 printRegName(O, Reg1);1511 O << "}";1512}1513 1514void ARMInstPrinter::printVectorListThree(const MCInst *MI, unsigned OpNum,1515 const MCSubtargetInfo &STI,1516 raw_ostream &O) {1517 // Normally, it's not safe to use register enum values directly with1518 // addition to get the next register, but for VFP registers, the1519 // sort order is guaranteed because they're all of the form D<n>.1520 O << "{";1521 printRegName(O, MI->getOperand(OpNum).getReg());1522 O << ", ";1523 printRegName(O, MI->getOperand(OpNum).getReg() + 1);1524 O << ", ";1525 printRegName(O, MI->getOperand(OpNum).getReg() + 2);1526 O << "}";1527}1528 1529void ARMInstPrinter::printVectorListFour(const MCInst *MI, unsigned OpNum,1530 const MCSubtargetInfo &STI,1531 raw_ostream &O) {1532 // Normally, it's not safe to use register enum values directly with1533 // addition to get the next register, but for VFP registers, the1534 // sort order is guaranteed because they're all of the form D<n>.1535 O << "{";1536 printRegName(O, MI->getOperand(OpNum).getReg());1537 O << ", ";1538 printRegName(O, MI->getOperand(OpNum).getReg() + 1);1539 O << ", ";1540 printRegName(O, MI->getOperand(OpNum).getReg() + 2);1541 O << ", ";1542 printRegName(O, MI->getOperand(OpNum).getReg() + 3);1543 O << "}";1544}1545 1546void ARMInstPrinter::printVectorListOneAllLanes(const MCInst *MI,1547 unsigned OpNum,1548 const MCSubtargetInfo &STI,1549 raw_ostream &O) {1550 O << "{";1551 printRegName(O, MI->getOperand(OpNum).getReg());1552 O << "[]}";1553}1554 1555void ARMInstPrinter::printVectorListTwoAllLanes(const MCInst *MI,1556 unsigned OpNum,1557 const MCSubtargetInfo &STI,1558 raw_ostream &O) {1559 MCRegister Reg = MI->getOperand(OpNum).getReg();1560 MCRegister Reg0 = MRI.getSubReg(Reg, ARM::dsub_0);1561 MCRegister Reg1 = MRI.getSubReg(Reg, ARM::dsub_1);1562 O << "{";1563 printRegName(O, Reg0);1564 O << "[], ";1565 printRegName(O, Reg1);1566 O << "[]}";1567}1568 1569void ARMInstPrinter::printVectorListThreeAllLanes(const MCInst *MI,1570 unsigned OpNum,1571 const MCSubtargetInfo &STI,1572 raw_ostream &O) {1573 // Normally, it's not safe to use register enum values directly with1574 // addition to get the next register, but for VFP registers, the1575 // sort order is guaranteed because they're all of the form D<n>.1576 O << "{";1577 printRegName(O, MI->getOperand(OpNum).getReg());1578 O << "[], ";1579 printRegName(O, MI->getOperand(OpNum).getReg() + 1);1580 O << "[], ";1581 printRegName(O, MI->getOperand(OpNum).getReg() + 2);1582 O << "[]}";1583}1584 1585void ARMInstPrinter::printVectorListFourAllLanes(const MCInst *MI,1586 unsigned OpNum,1587 const MCSubtargetInfo &STI,1588 raw_ostream &O) {1589 // Normally, it's not safe to use register enum values directly with1590 // addition to get the next register, but for VFP registers, the1591 // sort order is guaranteed because they're all of the form D<n>.1592 O << "{";1593 printRegName(O, MI->getOperand(OpNum).getReg());1594 O << "[], ";1595 printRegName(O, MI->getOperand(OpNum).getReg() + 1);1596 O << "[], ";1597 printRegName(O, MI->getOperand(OpNum).getReg() + 2);1598 O << "[], ";1599 printRegName(O, MI->getOperand(OpNum).getReg() + 3);1600 O << "[]}";1601}1602 1603void ARMInstPrinter::printVectorListTwoSpacedAllLanes(1604 const MCInst *MI, unsigned OpNum, const MCSubtargetInfo &STI,1605 raw_ostream &O) {1606 MCRegister Reg = MI->getOperand(OpNum).getReg();1607 MCRegister Reg0 = MRI.getSubReg(Reg, ARM::dsub_0);1608 MCRegister Reg1 = MRI.getSubReg(Reg, ARM::dsub_2);1609 O << "{";1610 printRegName(O, Reg0);1611 O << "[], ";1612 printRegName(O, Reg1);1613 O << "[]}";1614}1615 1616void ARMInstPrinter::printVectorListThreeSpacedAllLanes(1617 const MCInst *MI, unsigned OpNum, const MCSubtargetInfo &STI,1618 raw_ostream &O) {1619 // Normally, it's not safe to use register enum values directly with1620 // addition to get the next register, but for VFP registers, the1621 // sort order is guaranteed because they're all of the form D<n>.1622 O << "{";1623 printRegName(O, MI->getOperand(OpNum).getReg());1624 O << "[], ";1625 printRegName(O, MI->getOperand(OpNum).getReg() + 2);1626 O << "[], ";1627 printRegName(O, MI->getOperand(OpNum).getReg() + 4);1628 O << "[]}";1629}1630 1631void ARMInstPrinter::printVectorListFourSpacedAllLanes(1632 const MCInst *MI, unsigned OpNum, const MCSubtargetInfo &STI,1633 raw_ostream &O) {1634 // Normally, it's not safe to use register enum values directly with1635 // addition to get the next register, but for VFP registers, the1636 // sort order is guaranteed because they're all of the form D<n>.1637 O << "{";1638 printRegName(O, MI->getOperand(OpNum).getReg());1639 O << "[], ";1640 printRegName(O, MI->getOperand(OpNum).getReg() + 2);1641 O << "[], ";1642 printRegName(O, MI->getOperand(OpNum).getReg() + 4);1643 O << "[], ";1644 printRegName(O, MI->getOperand(OpNum).getReg() + 6);1645 O << "[]}";1646}1647 1648void ARMInstPrinter::printVectorListThreeSpaced(const MCInst *MI,1649 unsigned OpNum,1650 const MCSubtargetInfo &STI,1651 raw_ostream &O) {1652 // Normally, it's not safe to use register enum values directly with1653 // addition to get the next register, but for VFP registers, the1654 // sort order is guaranteed because they're all of the form D<n>.1655 O << "{";1656 printRegName(O, MI->getOperand(OpNum).getReg());1657 O << ", ";1658 printRegName(O, MI->getOperand(OpNum).getReg() + 2);1659 O << ", ";1660 printRegName(O, MI->getOperand(OpNum).getReg() + 4);1661 O << "}";1662}1663 1664void ARMInstPrinter::printVectorListFourSpaced(const MCInst *MI, unsigned OpNum,1665 const MCSubtargetInfo &STI,1666 raw_ostream &O) {1667 // Normally, it's not safe to use register enum values directly with1668 // addition to get the next register, but for VFP registers, the1669 // sort order is guaranteed because they're all of the form D<n>.1670 O << "{";1671 printRegName(O, MI->getOperand(OpNum).getReg());1672 O << ", ";1673 printRegName(O, MI->getOperand(OpNum).getReg() + 2);1674 O << ", ";1675 printRegName(O, MI->getOperand(OpNum).getReg() + 4);1676 O << ", ";1677 printRegName(O, MI->getOperand(OpNum).getReg() + 6);1678 O << "}";1679}1680 1681template<unsigned NumRegs>1682void ARMInstPrinter::printMVEVectorList(const MCInst *MI, unsigned OpNum,1683 const MCSubtargetInfo &STI,1684 raw_ostream &O) {1685 MCRegister Reg = MI->getOperand(OpNum).getReg();1686 const char *Prefix = "{";1687 for (unsigned i = 0; i < NumRegs; i++) {1688 O << Prefix;1689 printRegName(O, MRI.getSubReg(Reg, ARM::qsub_0 + i));1690 Prefix = ", ";1691 }1692 O << "}";1693}1694 1695template<int64_t Angle, int64_t Remainder>1696void ARMInstPrinter::printComplexRotationOp(const MCInst *MI, unsigned OpNo,1697 const MCSubtargetInfo &STI,1698 raw_ostream &O) {1699 unsigned Val = MI->getOperand(OpNo).getImm();1700 O << "#" << (Val * Angle) + Remainder;1701}1702 1703void ARMInstPrinter::printVPTPredicateOperand(const MCInst *MI, unsigned OpNum,1704 const MCSubtargetInfo &STI,1705 raw_ostream &O) {1706 ARMVCC::VPTCodes CC = (ARMVCC::VPTCodes)MI->getOperand(OpNum).getImm();1707 if (CC != ARMVCC::None)1708 O << ARMVPTPredToString(CC);1709}1710 1711void ARMInstPrinter::printVPTMask(const MCInst *MI, unsigned OpNum,1712 const MCSubtargetInfo &STI,1713 raw_ostream &O) {1714 // (3 - the number of trailing zeroes) is the number of them / else.1715 unsigned Mask = MI->getOperand(OpNum).getImm();1716 unsigned NumTZ = llvm::countr_zero(Mask);1717 assert(NumTZ <= 3 && "Invalid VPT mask!");1718 for (unsigned Pos = 3, e = NumTZ; Pos > e; --Pos) {1719 bool T = ((Mask >> Pos) & 1) == 0;1720 if (T)1721 O << 't';1722 else1723 O << 'e';1724 }1725}1726 1727void ARMInstPrinter::printMveSaturateOp(const MCInst *MI, unsigned OpNum,1728 const MCSubtargetInfo &STI,1729 raw_ostream &O) {1730 uint32_t Val = MI->getOperand(OpNum).getImm();1731 assert(Val <= 1 && "Invalid MVE saturate operand");1732 O << "#" << (Val == 1 ? 48 : 64);1733}1734