brintos

brintos / llvm-project-archived public Read only

0
0
Text · 58.2 KiB · ad00b17 Raw
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