xref: /freebsd/contrib/llvm-project/llvm/lib/Target/ARM/MCTargetDesc/ARMInstPrinter.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
10b57cec5SDimitry Andric //===-- ARMInstPrinter.cpp - Convert ARM MCInst to assembly syntax --------===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric //
90b57cec5SDimitry Andric // This class prints an ARM MCInst to a .s file.
100b57cec5SDimitry Andric //
110b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
120b57cec5SDimitry Andric 
130b57cec5SDimitry Andric #include "ARMInstPrinter.h"
140b57cec5SDimitry Andric #include "Utils/ARMBaseInfo.h"
150b57cec5SDimitry Andric #include "MCTargetDesc/ARMAddressingModes.h"
160b57cec5SDimitry Andric #include "MCTargetDesc/ARMBaseInfo.h"
170b57cec5SDimitry Andric #include "llvm/MC/MCAsmInfo.h"
180b57cec5SDimitry Andric #include "llvm/MC/MCExpr.h"
190b57cec5SDimitry Andric #include "llvm/MC/MCInst.h"
20fe6060f1SDimitry Andric #include "llvm/MC/MCInstrAnalysis.h"
210b57cec5SDimitry Andric #include "llvm/MC/MCInstrInfo.h"
220b57cec5SDimitry Andric #include "llvm/MC/MCRegisterInfo.h"
230b57cec5SDimitry Andric #include "llvm/MC/MCSubtargetInfo.h"
240b57cec5SDimitry Andric #include "llvm/Support/Casting.h"
250b57cec5SDimitry Andric #include "llvm/Support/ErrorHandling.h"
260b57cec5SDimitry Andric #include "llvm/Support/MathExtras.h"
270b57cec5SDimitry Andric #include "llvm/Support/raw_ostream.h"
2806c3fb27SDimitry Andric #include "llvm/TargetParser/SubtargetFeature.h"
290b57cec5SDimitry Andric #include <algorithm>
300b57cec5SDimitry Andric #include <cassert>
310b57cec5SDimitry Andric #include <cstdint>
320b57cec5SDimitry Andric 
330b57cec5SDimitry Andric using namespace llvm;
340b57cec5SDimitry Andric 
350b57cec5SDimitry Andric #define DEBUG_TYPE "asm-printer"
360b57cec5SDimitry Andric 
370b57cec5SDimitry Andric #define PRINT_ALIAS_INSTR
380b57cec5SDimitry Andric #include "ARMGenAsmWriter.inc"
390b57cec5SDimitry Andric 
400b57cec5SDimitry Andric /// translateShiftImm - Convert shift immediate from 0-31 to 1-32 for printing.
410b57cec5SDimitry Andric ///
420b57cec5SDimitry Andric /// getSORegOffset returns an integer from 0-31, representing '32' as 0.
translateShiftImm(unsigned imm)430b57cec5SDimitry Andric static unsigned translateShiftImm(unsigned imm) {
440b57cec5SDimitry Andric   // lsr #32 and asr #32 exist, but should be encoded as a 0.
450b57cec5SDimitry Andric   assert((imm & ~0x1f) == 0 && "Invalid shift encoding");
460b57cec5SDimitry Andric 
470b57cec5SDimitry Andric   if (imm == 0)
480b57cec5SDimitry Andric     return 32;
490b57cec5SDimitry Andric   return imm;
500b57cec5SDimitry Andric }
510b57cec5SDimitry Andric 
printRegImmShift(raw_ostream & O,ARM_AM::ShiftOpc ShOpc,unsigned ShImm,const ARMInstPrinter & printer)520b57cec5SDimitry Andric static void printRegImmShift(raw_ostream &O, ARM_AM::ShiftOpc ShOpc,
535f757f3fSDimitry Andric                              unsigned ShImm, const ARMInstPrinter &printer) {
540b57cec5SDimitry Andric   if (ShOpc == ARM_AM::no_shift || (ShOpc == ARM_AM::lsl && !ShImm))
550b57cec5SDimitry Andric     return;
560b57cec5SDimitry Andric   O << ", ";
570b57cec5SDimitry Andric 
580b57cec5SDimitry Andric   assert(!(ShOpc == ARM_AM::ror && !ShImm) && "Cannot have ror #0");
590b57cec5SDimitry Andric   O << getShiftOpcStr(ShOpc);
600b57cec5SDimitry Andric 
610b57cec5SDimitry Andric   if (ShOpc != ARM_AM::rrx) {
620b57cec5SDimitry Andric     O << " ";
635f757f3fSDimitry Andric     printer.markup(O, llvm::MCInstPrinter::Markup::Immediate)
645f757f3fSDimitry Andric         << "#" << translateShiftImm(ShImm);
650b57cec5SDimitry Andric   }
660b57cec5SDimitry Andric }
670b57cec5SDimitry Andric 
ARMInstPrinter(const MCAsmInfo & MAI,const MCInstrInfo & MII,const MCRegisterInfo & MRI)680b57cec5SDimitry Andric ARMInstPrinter::ARMInstPrinter(const MCAsmInfo &MAI, const MCInstrInfo &MII,
690b57cec5SDimitry Andric                                const MCRegisterInfo &MRI)
700b57cec5SDimitry Andric     : MCInstPrinter(MAI, MII, MRI) {}
710b57cec5SDimitry Andric 
applyTargetSpecificCLOption(StringRef Opt)720b57cec5SDimitry Andric bool ARMInstPrinter::applyTargetSpecificCLOption(StringRef Opt) {
730b57cec5SDimitry Andric   if (Opt == "reg-names-std") {
740b57cec5SDimitry Andric     DefaultAltIdx = ARM::NoRegAltName;
750b57cec5SDimitry Andric     return true;
760b57cec5SDimitry Andric   }
770b57cec5SDimitry Andric   if (Opt == "reg-names-raw") {
780b57cec5SDimitry Andric     DefaultAltIdx = ARM::RegNamesRaw;
790b57cec5SDimitry Andric     return true;
800b57cec5SDimitry Andric   }
810b57cec5SDimitry Andric   return false;
820b57cec5SDimitry Andric }
830b57cec5SDimitry Andric 
printRegName(raw_ostream & OS,MCRegister Reg) const84bdd1243dSDimitry Andric void ARMInstPrinter::printRegName(raw_ostream &OS, MCRegister Reg) const {
855f757f3fSDimitry Andric   markup(OS, Markup::Register) << getRegisterName(Reg, DefaultAltIdx);
860b57cec5SDimitry Andric }
870b57cec5SDimitry Andric 
printInst(const MCInst * MI,uint64_t Address,StringRef Annot,const MCSubtargetInfo & STI,raw_ostream & O)88480093f4SDimitry Andric void ARMInstPrinter::printInst(const MCInst *MI, uint64_t Address,
89480093f4SDimitry Andric                                StringRef Annot, const MCSubtargetInfo &STI,
90480093f4SDimitry Andric                                raw_ostream &O) {
910b57cec5SDimitry Andric   unsigned Opcode = MI->getOpcode();
920b57cec5SDimitry Andric 
930b57cec5SDimitry Andric   switch (Opcode) {
94*0fca6ea1SDimitry Andric   case ARM::VLLDM: {
95*0fca6ea1SDimitry Andric     const MCOperand &Reg = MI->getOperand(0);
96*0fca6ea1SDimitry Andric     O << '\t' << "vlldm" << '\t';
97*0fca6ea1SDimitry Andric     printRegName(O, Reg.getReg());
98*0fca6ea1SDimitry Andric     O << ", "
99*0fca6ea1SDimitry Andric       << "{d0 - d15}";
100*0fca6ea1SDimitry Andric     return;
101*0fca6ea1SDimitry Andric   }
102*0fca6ea1SDimitry Andric   case ARM::VLLDM_T2: {
103*0fca6ea1SDimitry Andric     const MCOperand &Reg = MI->getOperand(0);
104*0fca6ea1SDimitry Andric     O << '\t' << "vlldm" << '\t';
105*0fca6ea1SDimitry Andric     printRegName(O, Reg.getReg());
106*0fca6ea1SDimitry Andric     O << ", "
107*0fca6ea1SDimitry Andric       << "{d0 - d31}";
108*0fca6ea1SDimitry Andric     return;
109*0fca6ea1SDimitry Andric   }
110*0fca6ea1SDimitry Andric   case ARM::VLSTM: {
111*0fca6ea1SDimitry Andric     const MCOperand &Reg = MI->getOperand(0);
112*0fca6ea1SDimitry Andric     O << '\t' << "vlstm" << '\t';
113*0fca6ea1SDimitry Andric     printRegName(O, Reg.getReg());
114*0fca6ea1SDimitry Andric     O << ", "
115*0fca6ea1SDimitry Andric       << "{d0 - d15}";
116*0fca6ea1SDimitry Andric     return;
117*0fca6ea1SDimitry Andric   }
118*0fca6ea1SDimitry Andric   case ARM::VLSTM_T2: {
119*0fca6ea1SDimitry Andric     const MCOperand &Reg = MI->getOperand(0);
120*0fca6ea1SDimitry Andric     O << '\t' << "vlstm" << '\t';
121*0fca6ea1SDimitry Andric     printRegName(O, Reg.getReg());
122*0fca6ea1SDimitry Andric     O << ", "
123*0fca6ea1SDimitry Andric       << "{d0 - d31}";
124*0fca6ea1SDimitry Andric     return;
125*0fca6ea1SDimitry Andric   }
1260b57cec5SDimitry Andric   // Check for MOVs and print canonical forms, instead.
1270b57cec5SDimitry Andric   case ARM::MOVsr: {
1280b57cec5SDimitry Andric     // FIXME: Thumb variants?
1290b57cec5SDimitry Andric     const MCOperand &Dst = MI->getOperand(0);
1300b57cec5SDimitry Andric     const MCOperand &MO1 = MI->getOperand(1);
1310b57cec5SDimitry Andric     const MCOperand &MO2 = MI->getOperand(2);
1320b57cec5SDimitry Andric     const MCOperand &MO3 = MI->getOperand(3);
1330b57cec5SDimitry Andric 
1340b57cec5SDimitry Andric     O << '\t' << ARM_AM::getShiftOpcStr(ARM_AM::getSORegShOp(MO3.getImm()));
1350b57cec5SDimitry Andric     printSBitModifierOperand(MI, 6, STI, O);
1360b57cec5SDimitry Andric     printPredicateOperand(MI, 4, STI, O);
1370b57cec5SDimitry Andric 
1380b57cec5SDimitry Andric     O << '\t';
1390b57cec5SDimitry Andric     printRegName(O, Dst.getReg());
1400b57cec5SDimitry Andric     O << ", ";
1410b57cec5SDimitry Andric     printRegName(O, MO1.getReg());
1420b57cec5SDimitry Andric 
1430b57cec5SDimitry Andric     O << ", ";
1440b57cec5SDimitry Andric     printRegName(O, MO2.getReg());
1450b57cec5SDimitry Andric     assert(ARM_AM::getSORegOffset(MO3.getImm()) == 0);
1460b57cec5SDimitry Andric     printAnnotation(O, Annot);
1470b57cec5SDimitry Andric     return;
1480b57cec5SDimitry Andric   }
1490b57cec5SDimitry Andric 
1500b57cec5SDimitry Andric   case ARM::MOVsi: {
1510b57cec5SDimitry Andric     // FIXME: Thumb variants?
1520b57cec5SDimitry Andric     const MCOperand &Dst = MI->getOperand(0);
1530b57cec5SDimitry Andric     const MCOperand &MO1 = MI->getOperand(1);
1540b57cec5SDimitry Andric     const MCOperand &MO2 = MI->getOperand(2);
1550b57cec5SDimitry Andric 
1560b57cec5SDimitry Andric     O << '\t' << ARM_AM::getShiftOpcStr(ARM_AM::getSORegShOp(MO2.getImm()));
1570b57cec5SDimitry Andric     printSBitModifierOperand(MI, 5, STI, O);
1580b57cec5SDimitry Andric     printPredicateOperand(MI, 3, STI, O);
1590b57cec5SDimitry Andric 
1600b57cec5SDimitry Andric     O << '\t';
1610b57cec5SDimitry Andric     printRegName(O, Dst.getReg());
1620b57cec5SDimitry Andric     O << ", ";
1630b57cec5SDimitry Andric     printRegName(O, MO1.getReg());
1640b57cec5SDimitry Andric 
1650b57cec5SDimitry Andric     if (ARM_AM::getSORegShOp(MO2.getImm()) == ARM_AM::rrx) {
1660b57cec5SDimitry Andric       printAnnotation(O, Annot);
1670b57cec5SDimitry Andric       return;
1680b57cec5SDimitry Andric     }
1690b57cec5SDimitry Andric 
1705f757f3fSDimitry Andric     O << ", ";
1715f757f3fSDimitry Andric     markup(O, Markup::Immediate)
1725f757f3fSDimitry Andric         << "#" << translateShiftImm(ARM_AM::getSORegOffset(MO2.getImm()));
1730b57cec5SDimitry Andric     printAnnotation(O, Annot);
1740b57cec5SDimitry Andric     return;
1750b57cec5SDimitry Andric   }
1760b57cec5SDimitry Andric 
1770b57cec5SDimitry Andric   // A8.6.123 PUSH
1780b57cec5SDimitry Andric   case ARM::STMDB_UPD:
1790b57cec5SDimitry Andric   case ARM::t2STMDB_UPD:
1800b57cec5SDimitry Andric     if (MI->getOperand(0).getReg() == ARM::SP && MI->getNumOperands() > 5) {
1810b57cec5SDimitry Andric       // Should only print PUSH if there are at least two registers in the list.
1820b57cec5SDimitry Andric       O << '\t' << "push";
1830b57cec5SDimitry Andric       printPredicateOperand(MI, 2, STI, O);
1840b57cec5SDimitry Andric       if (Opcode == ARM::t2STMDB_UPD)
1850b57cec5SDimitry Andric         O << ".w";
1860b57cec5SDimitry Andric       O << '\t';
1870b57cec5SDimitry Andric       printRegisterList(MI, 4, STI, O);
1880b57cec5SDimitry Andric       printAnnotation(O, Annot);
1890b57cec5SDimitry Andric       return;
1900b57cec5SDimitry Andric     } else
1910b57cec5SDimitry Andric       break;
1920b57cec5SDimitry Andric 
1930b57cec5SDimitry Andric   case ARM::STR_PRE_IMM:
1940b57cec5SDimitry Andric     if (MI->getOperand(2).getReg() == ARM::SP &&
1950b57cec5SDimitry Andric         MI->getOperand(3).getImm() == -4) {
1960b57cec5SDimitry Andric       O << '\t' << "push";
1970b57cec5SDimitry Andric       printPredicateOperand(MI, 4, STI, O);
1980b57cec5SDimitry Andric       O << "\t{";
1990b57cec5SDimitry Andric       printRegName(O, MI->getOperand(1).getReg());
2000b57cec5SDimitry Andric       O << "}";
2010b57cec5SDimitry Andric       printAnnotation(O, Annot);
2020b57cec5SDimitry Andric       return;
2030b57cec5SDimitry Andric     } else
2040b57cec5SDimitry Andric       break;
2050b57cec5SDimitry Andric 
2060b57cec5SDimitry Andric   // A8.6.122 POP
2070b57cec5SDimitry Andric   case ARM::LDMIA_UPD:
2080b57cec5SDimitry Andric   case ARM::t2LDMIA_UPD:
2090b57cec5SDimitry Andric     if (MI->getOperand(0).getReg() == ARM::SP && MI->getNumOperands() > 5) {
2100b57cec5SDimitry Andric       // Should only print POP if there are at least two registers in the list.
2110b57cec5SDimitry Andric       O << '\t' << "pop";
2120b57cec5SDimitry Andric       printPredicateOperand(MI, 2, STI, O);
2130b57cec5SDimitry Andric       if (Opcode == ARM::t2LDMIA_UPD)
2140b57cec5SDimitry Andric         O << ".w";
2150b57cec5SDimitry Andric       O << '\t';
2160b57cec5SDimitry Andric       printRegisterList(MI, 4, STI, O);
2170b57cec5SDimitry Andric       printAnnotation(O, Annot);
2180b57cec5SDimitry Andric       return;
2190b57cec5SDimitry Andric     } else
2200b57cec5SDimitry Andric       break;
2210b57cec5SDimitry Andric 
2220b57cec5SDimitry Andric   case ARM::LDR_POST_IMM:
2230b57cec5SDimitry Andric     if (MI->getOperand(2).getReg() == ARM::SP &&
2240b57cec5SDimitry Andric         MI->getOperand(4).getImm() == 4) {
2250b57cec5SDimitry Andric       O << '\t' << "pop";
2260b57cec5SDimitry Andric       printPredicateOperand(MI, 5, STI, O);
2270b57cec5SDimitry Andric       O << "\t{";
2280b57cec5SDimitry Andric       printRegName(O, MI->getOperand(0).getReg());
2290b57cec5SDimitry Andric       O << "}";
2300b57cec5SDimitry Andric       printAnnotation(O, Annot);
2310b57cec5SDimitry Andric       return;
2320b57cec5SDimitry Andric     } else
2330b57cec5SDimitry Andric       break;
2340b57cec5SDimitry Andric 
2350b57cec5SDimitry Andric   // A8.6.355 VPUSH
2360b57cec5SDimitry Andric   case ARM::VSTMSDB_UPD:
2370b57cec5SDimitry Andric   case ARM::VSTMDDB_UPD:
2380b57cec5SDimitry Andric     if (MI->getOperand(0).getReg() == ARM::SP) {
2390b57cec5SDimitry Andric       O << '\t' << "vpush";
2400b57cec5SDimitry Andric       printPredicateOperand(MI, 2, STI, O);
2410b57cec5SDimitry Andric       O << '\t';
2420b57cec5SDimitry Andric       printRegisterList(MI, 4, STI, O);
2430b57cec5SDimitry Andric       printAnnotation(O, Annot);
2440b57cec5SDimitry Andric       return;
2450b57cec5SDimitry Andric     } else
2460b57cec5SDimitry Andric       break;
2470b57cec5SDimitry Andric 
2480b57cec5SDimitry Andric   // A8.6.354 VPOP
2490b57cec5SDimitry Andric   case ARM::VLDMSIA_UPD:
2500b57cec5SDimitry Andric   case ARM::VLDMDIA_UPD:
2510b57cec5SDimitry Andric     if (MI->getOperand(0).getReg() == ARM::SP) {
2520b57cec5SDimitry Andric       O << '\t' << "vpop";
2530b57cec5SDimitry Andric       printPredicateOperand(MI, 2, STI, O);
2540b57cec5SDimitry Andric       O << '\t';
2550b57cec5SDimitry Andric       printRegisterList(MI, 4, STI, O);
2560b57cec5SDimitry Andric       printAnnotation(O, Annot);
2570b57cec5SDimitry Andric       return;
2580b57cec5SDimitry Andric     } else
2590b57cec5SDimitry Andric       break;
2600b57cec5SDimitry Andric 
2610b57cec5SDimitry Andric   case ARM::tLDMIA: {
2620b57cec5SDimitry Andric     bool Writeback = true;
2630b57cec5SDimitry Andric     unsigned BaseReg = MI->getOperand(0).getReg();
2640b57cec5SDimitry Andric     for (unsigned i = 3; i < MI->getNumOperands(); ++i) {
2650b57cec5SDimitry Andric       if (MI->getOperand(i).getReg() == BaseReg)
2660b57cec5SDimitry Andric         Writeback = false;
2670b57cec5SDimitry Andric     }
2680b57cec5SDimitry Andric 
2690b57cec5SDimitry Andric     O << "\tldm";
2700b57cec5SDimitry Andric 
2710b57cec5SDimitry Andric     printPredicateOperand(MI, 1, STI, O);
2720b57cec5SDimitry Andric     O << '\t';
2730b57cec5SDimitry Andric     printRegName(O, BaseReg);
2740b57cec5SDimitry Andric     if (Writeback)
2750b57cec5SDimitry Andric       O << "!";
2760b57cec5SDimitry Andric     O << ", ";
2770b57cec5SDimitry Andric     printRegisterList(MI, 3, STI, O);
2780b57cec5SDimitry Andric     printAnnotation(O, Annot);
2790b57cec5SDimitry Andric     return;
2800b57cec5SDimitry Andric   }
2810b57cec5SDimitry Andric 
2820b57cec5SDimitry Andric   // Combine 2 GPRs from disassember into a GPRPair to match with instr def.
2830b57cec5SDimitry Andric   // ldrexd/strexd require even/odd GPR pair. To enforce this constraint,
2840b57cec5SDimitry Andric   // a single GPRPair reg operand is used in the .td file to replace the two
2850b57cec5SDimitry Andric   // GPRs. However, when decoding them, the two GRPs cannot be automatically
2860b57cec5SDimitry Andric   // expressed as a GPRPair, so we have to manually merge them.
2870b57cec5SDimitry Andric   // FIXME: We would really like to be able to tablegen'erate this.
2880b57cec5SDimitry Andric   case ARM::LDREXD:
2890b57cec5SDimitry Andric   case ARM::STREXD:
2900b57cec5SDimitry Andric   case ARM::LDAEXD:
2910b57cec5SDimitry Andric   case ARM::STLEXD: {
2920b57cec5SDimitry Andric     const MCRegisterClass &MRC = MRI.getRegClass(ARM::GPRRegClassID);
2930b57cec5SDimitry Andric     bool isStore = Opcode == ARM::STREXD || Opcode == ARM::STLEXD;
2940b57cec5SDimitry Andric     unsigned Reg = MI->getOperand(isStore ? 1 : 0).getReg();
2950b57cec5SDimitry Andric     if (MRC.contains(Reg)) {
2960b57cec5SDimitry Andric       MCInst NewMI;
2970b57cec5SDimitry Andric       MCOperand NewReg;
2980b57cec5SDimitry Andric       NewMI.setOpcode(Opcode);
2990b57cec5SDimitry Andric 
3000b57cec5SDimitry Andric       if (isStore)
3010b57cec5SDimitry Andric         NewMI.addOperand(MI->getOperand(0));
3020b57cec5SDimitry Andric       NewReg = MCOperand::createReg(MRI.getMatchingSuperReg(
3030b57cec5SDimitry Andric           Reg, ARM::gsub_0, &MRI.getRegClass(ARM::GPRPairRegClassID)));
3040b57cec5SDimitry Andric       NewMI.addOperand(NewReg);
3050b57cec5SDimitry Andric 
3060b57cec5SDimitry Andric       // Copy the rest operands into NewMI.
3070b57cec5SDimitry Andric       for (unsigned i = isStore ? 3 : 2; i < MI->getNumOperands(); ++i)
3080b57cec5SDimitry Andric         NewMI.addOperand(MI->getOperand(i));
309480093f4SDimitry Andric       printInstruction(&NewMI, Address, STI, O);
3100b57cec5SDimitry Andric       return;
3110b57cec5SDimitry Andric     }
3120b57cec5SDimitry Andric     break;
3130b57cec5SDimitry Andric   }
3140b57cec5SDimitry Andric   case ARM::TSB:
3150b57cec5SDimitry Andric   case ARM::t2TSB:
3160b57cec5SDimitry Andric     O << "\ttsb\tcsync";
3170b57cec5SDimitry Andric     return;
3180b57cec5SDimitry Andric   case ARM::t2DSB:
3190b57cec5SDimitry Andric     switch (MI->getOperand(0).getImm()) {
3200b57cec5SDimitry Andric     default:
3215ffd83dbSDimitry Andric       if (!printAliasInstr(MI, Address, STI, O))
322480093f4SDimitry Andric         printInstruction(MI, Address, STI, O);
3230b57cec5SDimitry Andric       break;
3240b57cec5SDimitry Andric     case 0:
3250b57cec5SDimitry Andric       O << "\tssbb";
3260b57cec5SDimitry Andric       break;
3270b57cec5SDimitry Andric     case 4:
3280b57cec5SDimitry Andric       O << "\tpssbb";
3290b57cec5SDimitry Andric       break;
3300b57cec5SDimitry Andric     }
3310b57cec5SDimitry Andric     printAnnotation(O, Annot);
3320b57cec5SDimitry Andric     return;
3330b57cec5SDimitry Andric   }
3340b57cec5SDimitry Andric 
3355ffd83dbSDimitry Andric   if (!printAliasInstr(MI, Address, STI, O))
336480093f4SDimitry Andric     printInstruction(MI, Address, STI, O);
3370b57cec5SDimitry Andric 
3380b57cec5SDimitry Andric   printAnnotation(O, Annot);
3390b57cec5SDimitry Andric }
3400b57cec5SDimitry Andric 
printOperand(const MCInst * MI,unsigned OpNo,const MCSubtargetInfo & STI,raw_ostream & O)3410b57cec5SDimitry Andric void ARMInstPrinter::printOperand(const MCInst *MI, unsigned OpNo,
3420b57cec5SDimitry Andric                                   const MCSubtargetInfo &STI, raw_ostream &O) {
3430b57cec5SDimitry Andric   const MCOperand &Op = MI->getOperand(OpNo);
3440b57cec5SDimitry Andric   if (Op.isReg()) {
3450b57cec5SDimitry Andric     unsigned Reg = Op.getReg();
3460b57cec5SDimitry Andric     printRegName(O, Reg);
3470b57cec5SDimitry Andric   } else if (Op.isImm()) {
3485f757f3fSDimitry Andric     markup(O, Markup::Immediate) << '#' << formatImm(Op.getImm());
3490b57cec5SDimitry Andric   } else {
3500b57cec5SDimitry Andric     assert(Op.isExpr() && "unknown operand kind in printOperand");
3510b57cec5SDimitry Andric     const MCExpr *Expr = Op.getExpr();
3520b57cec5SDimitry Andric     switch (Expr->getKind()) {
3530b57cec5SDimitry Andric     case MCExpr::Binary:
3540b57cec5SDimitry Andric       O << '#';
3550b57cec5SDimitry Andric       Expr->print(O, &MAI);
3560b57cec5SDimitry Andric       break;
3570b57cec5SDimitry Andric     case MCExpr::Constant: {
3580b57cec5SDimitry Andric       // If a symbolic branch target was added as a constant expression then
3590b57cec5SDimitry Andric       // print that address in hex. And only print 32 unsigned bits for the
3600b57cec5SDimitry Andric       // address.
3610b57cec5SDimitry Andric       const MCConstantExpr *Constant = cast<MCConstantExpr>(Expr);
3620b57cec5SDimitry Andric       int64_t TargetAddress;
3630b57cec5SDimitry Andric       if (!Constant->evaluateAsAbsolute(TargetAddress)) {
3640b57cec5SDimitry Andric         O << '#';
3650b57cec5SDimitry Andric         Expr->print(O, &MAI);
3660b57cec5SDimitry Andric       } else {
3670b57cec5SDimitry Andric         O << "0x";
3680b57cec5SDimitry Andric         O.write_hex(static_cast<uint32_t>(TargetAddress));
3690b57cec5SDimitry Andric       }
3700b57cec5SDimitry Andric       break;
3710b57cec5SDimitry Andric     }
3720b57cec5SDimitry Andric     default:
3730b57cec5SDimitry Andric       // FIXME: Should we always treat this as if it is a constant literal and
3740b57cec5SDimitry Andric       // prefix it with '#'?
3750b57cec5SDimitry Andric       Expr->print(O, &MAI);
3760b57cec5SDimitry Andric       break;
3770b57cec5SDimitry Andric     }
3780b57cec5SDimitry Andric   }
3790b57cec5SDimitry Andric }
3800b57cec5SDimitry Andric 
printOperand(const MCInst * MI,uint64_t Address,unsigned OpNum,const MCSubtargetInfo & STI,raw_ostream & O)381fe6060f1SDimitry Andric void ARMInstPrinter::printOperand(const MCInst *MI, uint64_t Address,
382fe6060f1SDimitry Andric                                   unsigned OpNum, const MCSubtargetInfo &STI,
383fe6060f1SDimitry Andric                                   raw_ostream &O) {
384fe6060f1SDimitry Andric   const MCOperand &Op = MI->getOperand(OpNum);
385fe6060f1SDimitry Andric   if (!Op.isImm() || !PrintBranchImmAsAddress || getUseMarkup())
386fe6060f1SDimitry Andric     return printOperand(MI, OpNum, STI, O);
387fe6060f1SDimitry Andric   uint64_t Target = ARM_MC::evaluateBranchTarget(MII.get(MI->getOpcode()),
388fe6060f1SDimitry Andric                                                  Address, Op.getImm());
389fe6060f1SDimitry Andric   Target &= 0xffffffff;
390fe6060f1SDimitry Andric   O << formatHex(Target);
391fe6060f1SDimitry Andric   if (CommentStream)
392fe6060f1SDimitry Andric     *CommentStream << "imm = #" << formatImm(Op.getImm()) << '\n';
393fe6060f1SDimitry Andric }
394fe6060f1SDimitry Andric 
printThumbLdrLabelOperand(const MCInst * MI,unsigned OpNum,const MCSubtargetInfo & STI,raw_ostream & O)3950b57cec5SDimitry Andric void ARMInstPrinter::printThumbLdrLabelOperand(const MCInst *MI, unsigned OpNum,
3960b57cec5SDimitry Andric                                                const MCSubtargetInfo &STI,
3970b57cec5SDimitry Andric                                                raw_ostream &O) {
3980b57cec5SDimitry Andric   const MCOperand &MO1 = MI->getOperand(OpNum);
3990b57cec5SDimitry Andric   if (MO1.isExpr()) {
4000b57cec5SDimitry Andric     MO1.getExpr()->print(O, &MAI);
4010b57cec5SDimitry Andric     return;
4020b57cec5SDimitry Andric   }
4030b57cec5SDimitry Andric 
4045f757f3fSDimitry Andric   WithMarkup ScopedMarkup = markup(O, Markup::Memory);
4055f757f3fSDimitry Andric   O << "[pc, ";
4060b57cec5SDimitry Andric 
4070b57cec5SDimitry Andric   int32_t OffImm = (int32_t)MO1.getImm();
4080b57cec5SDimitry Andric   bool isSub = OffImm < 0;
4090b57cec5SDimitry Andric 
4100b57cec5SDimitry Andric   // Special value for #-0. All others are normal.
4110b57cec5SDimitry Andric   if (OffImm == INT32_MIN)
4120b57cec5SDimitry Andric     OffImm = 0;
4130b57cec5SDimitry Andric   if (isSub) {
4145f757f3fSDimitry Andric     markup(O, Markup::Immediate) << "#-" << formatImm(-OffImm);
4150b57cec5SDimitry Andric   } else {
4165f757f3fSDimitry Andric     markup(O, Markup::Immediate) << "#" << formatImm(OffImm);
4170b57cec5SDimitry Andric   }
4185f757f3fSDimitry Andric   O << "]";
4190b57cec5SDimitry Andric }
4200b57cec5SDimitry Andric 
4210b57cec5SDimitry Andric // so_reg is a 4-operand unit corresponding to register forms of the A5.1
4220b57cec5SDimitry Andric // "Addressing Mode 1 - Data-processing operands" forms.  This includes:
4230b57cec5SDimitry Andric //    REG 0   0           - e.g. R5
4240b57cec5SDimitry Andric //    REG REG 0,SH_OPC    - e.g. R5, ROR R3
4250b57cec5SDimitry Andric //    REG 0   IMM,SH_OPC  - e.g. R5, LSL #3
printSORegRegOperand(const MCInst * MI,unsigned OpNum,const MCSubtargetInfo & STI,raw_ostream & O)4260b57cec5SDimitry Andric void ARMInstPrinter::printSORegRegOperand(const MCInst *MI, unsigned OpNum,
4270b57cec5SDimitry Andric                                           const MCSubtargetInfo &STI,
4280b57cec5SDimitry Andric                                           raw_ostream &O) {
4290b57cec5SDimitry Andric   const MCOperand &MO1 = MI->getOperand(OpNum);
4300b57cec5SDimitry Andric   const MCOperand &MO2 = MI->getOperand(OpNum + 1);
4310b57cec5SDimitry Andric   const MCOperand &MO3 = MI->getOperand(OpNum + 2);
4320b57cec5SDimitry Andric 
4330b57cec5SDimitry Andric   printRegName(O, MO1.getReg());
4340b57cec5SDimitry Andric 
4350b57cec5SDimitry Andric   // Print the shift opc.
4360b57cec5SDimitry Andric   ARM_AM::ShiftOpc ShOpc = ARM_AM::getSORegShOp(MO3.getImm());
4370b57cec5SDimitry Andric   O << ", " << ARM_AM::getShiftOpcStr(ShOpc);
4380b57cec5SDimitry Andric   if (ShOpc == ARM_AM::rrx)
4390b57cec5SDimitry Andric     return;
4400b57cec5SDimitry Andric 
4410b57cec5SDimitry Andric   O << ' ';
4420b57cec5SDimitry Andric   printRegName(O, MO2.getReg());
4430b57cec5SDimitry Andric   assert(ARM_AM::getSORegOffset(MO3.getImm()) == 0);
4440b57cec5SDimitry Andric }
4450b57cec5SDimitry Andric 
printSORegImmOperand(const MCInst * MI,unsigned OpNum,const MCSubtargetInfo & STI,raw_ostream & O)4460b57cec5SDimitry Andric void ARMInstPrinter::printSORegImmOperand(const MCInst *MI, unsigned OpNum,
4470b57cec5SDimitry Andric                                           const MCSubtargetInfo &STI,
4480b57cec5SDimitry Andric                                           raw_ostream &O) {
4490b57cec5SDimitry Andric   const MCOperand &MO1 = MI->getOperand(OpNum);
4500b57cec5SDimitry Andric   const MCOperand &MO2 = MI->getOperand(OpNum + 1);
4510b57cec5SDimitry Andric 
4520b57cec5SDimitry Andric   printRegName(O, MO1.getReg());
4530b57cec5SDimitry Andric 
4540b57cec5SDimitry Andric   // Print the shift opc.
4550b57cec5SDimitry Andric   printRegImmShift(O, ARM_AM::getSORegShOp(MO2.getImm()),
4565f757f3fSDimitry Andric                    ARM_AM::getSORegOffset(MO2.getImm()), *this);
4570b57cec5SDimitry Andric }
4580b57cec5SDimitry Andric 
4590b57cec5SDimitry Andric //===--------------------------------------------------------------------===//
4600b57cec5SDimitry Andric // Addressing Mode #2
4610b57cec5SDimitry Andric //===--------------------------------------------------------------------===//
4620b57cec5SDimitry Andric 
printAM2PreOrOffsetIndexOp(const MCInst * MI,unsigned Op,const MCSubtargetInfo & STI,raw_ostream & O)4630b57cec5SDimitry Andric void ARMInstPrinter::printAM2PreOrOffsetIndexOp(const MCInst *MI, unsigned Op,
4640b57cec5SDimitry Andric                                                 const MCSubtargetInfo &STI,
4650b57cec5SDimitry Andric                                                 raw_ostream &O) {
4660b57cec5SDimitry Andric   const MCOperand &MO1 = MI->getOperand(Op);
4670b57cec5SDimitry Andric   const MCOperand &MO2 = MI->getOperand(Op + 1);
4680b57cec5SDimitry Andric   const MCOperand &MO3 = MI->getOperand(Op + 2);
4690b57cec5SDimitry Andric 
4705f757f3fSDimitry Andric   WithMarkup ScopedMarkup = markup(O, Markup::Memory);
4715f757f3fSDimitry Andric   O << "[";
4720b57cec5SDimitry Andric   printRegName(O, MO1.getReg());
4730b57cec5SDimitry Andric 
4740b57cec5SDimitry Andric   if (!MO2.getReg()) {
4750b57cec5SDimitry Andric     if (ARM_AM::getAM2Offset(MO3.getImm())) { // Don't print +0.
4765f757f3fSDimitry Andric       O << ", ";
4775f757f3fSDimitry Andric       markup(O, Markup::Immediate)
4785f757f3fSDimitry Andric           << "#" << ARM_AM::getAddrOpcStr(ARM_AM::getAM2Op(MO3.getImm()))
4795f757f3fSDimitry Andric           << ARM_AM::getAM2Offset(MO3.getImm());
4800b57cec5SDimitry Andric     }
4815f757f3fSDimitry Andric     O << "]";
4820b57cec5SDimitry Andric     return;
4830b57cec5SDimitry Andric   }
4840b57cec5SDimitry Andric 
4850b57cec5SDimitry Andric   O << ", ";
4860b57cec5SDimitry Andric   O << ARM_AM::getAddrOpcStr(ARM_AM::getAM2Op(MO3.getImm()));
4870b57cec5SDimitry Andric   printRegName(O, MO2.getReg());
4880b57cec5SDimitry Andric 
4890b57cec5SDimitry Andric   printRegImmShift(O, ARM_AM::getAM2ShiftOpc(MO3.getImm()),
4905f757f3fSDimitry Andric                    ARM_AM::getAM2Offset(MO3.getImm()), *this);
4915f757f3fSDimitry Andric   O << "]";
4920b57cec5SDimitry Andric }
4930b57cec5SDimitry Andric 
printAddrModeTBB(const MCInst * MI,unsigned Op,const MCSubtargetInfo & STI,raw_ostream & O)4940b57cec5SDimitry Andric void ARMInstPrinter::printAddrModeTBB(const MCInst *MI, unsigned Op,
4950b57cec5SDimitry Andric                                       const MCSubtargetInfo &STI,
4960b57cec5SDimitry Andric                                       raw_ostream &O) {
4970b57cec5SDimitry Andric   const MCOperand &MO1 = MI->getOperand(Op);
4980b57cec5SDimitry Andric   const MCOperand &MO2 = MI->getOperand(Op + 1);
4995f757f3fSDimitry Andric 
5005f757f3fSDimitry Andric   WithMarkup ScopedMarkup = markup(O, Markup::Memory);
5015f757f3fSDimitry Andric   O << "[";
5020b57cec5SDimitry Andric   printRegName(O, MO1.getReg());
5030b57cec5SDimitry Andric   O << ", ";
5040b57cec5SDimitry Andric   printRegName(O, MO2.getReg());
5055f757f3fSDimitry Andric   O << "]";
5060b57cec5SDimitry Andric }
5070b57cec5SDimitry Andric 
printAddrModeTBH(const MCInst * MI,unsigned Op,const MCSubtargetInfo & STI,raw_ostream & O)5080b57cec5SDimitry Andric void ARMInstPrinter::printAddrModeTBH(const MCInst *MI, unsigned Op,
5090b57cec5SDimitry Andric                                       const MCSubtargetInfo &STI,
5100b57cec5SDimitry Andric                                       raw_ostream &O) {
5110b57cec5SDimitry Andric   const MCOperand &MO1 = MI->getOperand(Op);
5120b57cec5SDimitry Andric   const MCOperand &MO2 = MI->getOperand(Op + 1);
5135f757f3fSDimitry Andric   WithMarkup ScopedMarkup = markup(O, Markup::Memory);
5145f757f3fSDimitry Andric   O << "[";
5150b57cec5SDimitry Andric   printRegName(O, MO1.getReg());
5160b57cec5SDimitry Andric   O << ", ";
5170b57cec5SDimitry Andric   printRegName(O, MO2.getReg());
5185f757f3fSDimitry Andric   O << ", lsl ";
5195f757f3fSDimitry Andric   markup(O, Markup::Immediate) << "#1";
5205f757f3fSDimitry Andric   O << "]";
5210b57cec5SDimitry Andric }
5220b57cec5SDimitry Andric 
printAddrMode2Operand(const MCInst * MI,unsigned Op,const MCSubtargetInfo & STI,raw_ostream & O)5230b57cec5SDimitry Andric void ARMInstPrinter::printAddrMode2Operand(const MCInst *MI, unsigned Op,
5240b57cec5SDimitry Andric                                            const MCSubtargetInfo &STI,
5250b57cec5SDimitry Andric                                            raw_ostream &O) {
5260b57cec5SDimitry Andric   const MCOperand &MO1 = MI->getOperand(Op);
5270b57cec5SDimitry Andric 
5280b57cec5SDimitry Andric   if (!MO1.isReg()) { // FIXME: This is for CP entries, but isn't right.
5290b57cec5SDimitry Andric     printOperand(MI, Op, STI, O);
5300b57cec5SDimitry Andric     return;
5310b57cec5SDimitry Andric   }
5320b57cec5SDimitry Andric 
5330b57cec5SDimitry Andric #ifndef NDEBUG
5340b57cec5SDimitry Andric   const MCOperand &MO3 = MI->getOperand(Op + 2);
5350b57cec5SDimitry Andric   unsigned IdxMode = ARM_AM::getAM2IdxMode(MO3.getImm());
5360b57cec5SDimitry Andric   assert(IdxMode != ARMII::IndexModePost && "Should be pre or offset index op");
5370b57cec5SDimitry Andric #endif
5380b57cec5SDimitry Andric 
5390b57cec5SDimitry Andric   printAM2PreOrOffsetIndexOp(MI, Op, STI, O);
5400b57cec5SDimitry Andric }
5410b57cec5SDimitry Andric 
printAddrMode2OffsetOperand(const MCInst * MI,unsigned OpNum,const MCSubtargetInfo & STI,raw_ostream & O)5420b57cec5SDimitry Andric void ARMInstPrinter::printAddrMode2OffsetOperand(const MCInst *MI,
5430b57cec5SDimitry Andric                                                  unsigned OpNum,
5440b57cec5SDimitry Andric                                                  const MCSubtargetInfo &STI,
5450b57cec5SDimitry Andric                                                  raw_ostream &O) {
5460b57cec5SDimitry Andric   const MCOperand &MO1 = MI->getOperand(OpNum);
5470b57cec5SDimitry Andric   const MCOperand &MO2 = MI->getOperand(OpNum + 1);
5480b57cec5SDimitry Andric 
5490b57cec5SDimitry Andric   if (!MO1.getReg()) {
5500b57cec5SDimitry Andric     unsigned ImmOffs = ARM_AM::getAM2Offset(MO2.getImm());
5515f757f3fSDimitry Andric     markup(O, Markup::Immediate)
5525f757f3fSDimitry Andric         << '#' << ARM_AM::getAddrOpcStr(ARM_AM::getAM2Op(MO2.getImm()))
5535f757f3fSDimitry Andric         << ImmOffs;
5540b57cec5SDimitry Andric     return;
5550b57cec5SDimitry Andric   }
5560b57cec5SDimitry Andric 
5570b57cec5SDimitry Andric   O << ARM_AM::getAddrOpcStr(ARM_AM::getAM2Op(MO2.getImm()));
5580b57cec5SDimitry Andric   printRegName(O, MO1.getReg());
5590b57cec5SDimitry Andric 
5600b57cec5SDimitry Andric   printRegImmShift(O, ARM_AM::getAM2ShiftOpc(MO2.getImm()),
5615f757f3fSDimitry Andric                    ARM_AM::getAM2Offset(MO2.getImm()), *this);
5620b57cec5SDimitry Andric }
5630b57cec5SDimitry Andric 
5640b57cec5SDimitry Andric //===--------------------------------------------------------------------===//
5650b57cec5SDimitry Andric // Addressing Mode #3
5660b57cec5SDimitry Andric //===--------------------------------------------------------------------===//
5670b57cec5SDimitry Andric 
printAM3PreOrOffsetIndexOp(const MCInst * MI,unsigned Op,raw_ostream & O,bool AlwaysPrintImm0)5680b57cec5SDimitry Andric void ARMInstPrinter::printAM3PreOrOffsetIndexOp(const MCInst *MI, unsigned Op,
5690b57cec5SDimitry Andric                                                 raw_ostream &O,
5700b57cec5SDimitry Andric                                                 bool AlwaysPrintImm0) {
5710b57cec5SDimitry Andric   const MCOperand &MO1 = MI->getOperand(Op);
5720b57cec5SDimitry Andric   const MCOperand &MO2 = MI->getOperand(Op + 1);
5730b57cec5SDimitry Andric   const MCOperand &MO3 = MI->getOperand(Op + 2);
5740b57cec5SDimitry Andric 
5755f757f3fSDimitry Andric   WithMarkup ScopedMarkup = markup(O, Markup::Memory);
5765f757f3fSDimitry Andric   O << '[';
5770b57cec5SDimitry Andric   printRegName(O, MO1.getReg());
5780b57cec5SDimitry Andric 
5790b57cec5SDimitry Andric   if (MO2.getReg()) {
5800b57cec5SDimitry Andric     O << ", " << getAddrOpcStr(ARM_AM::getAM3Op(MO3.getImm()));
5810b57cec5SDimitry Andric     printRegName(O, MO2.getReg());
5825f757f3fSDimitry Andric     O << ']';
5830b57cec5SDimitry Andric     return;
5840b57cec5SDimitry Andric   }
5850b57cec5SDimitry Andric 
5860b57cec5SDimitry Andric   // If the op is sub we have to print the immediate even if it is 0
5870b57cec5SDimitry Andric   unsigned ImmOffs = ARM_AM::getAM3Offset(MO3.getImm());
5880b57cec5SDimitry Andric   ARM_AM::AddrOpc op = ARM_AM::getAM3Op(MO3.getImm());
5890b57cec5SDimitry Andric 
5900b57cec5SDimitry Andric   if (AlwaysPrintImm0 || ImmOffs || (op == ARM_AM::sub)) {
5915f757f3fSDimitry Andric     O << ", ";
5925f757f3fSDimitry Andric     markup(O, Markup::Immediate) << "#" << ARM_AM::getAddrOpcStr(op) << ImmOffs;
5930b57cec5SDimitry Andric   }
5945f757f3fSDimitry Andric   O << ']';
5950b57cec5SDimitry Andric }
5960b57cec5SDimitry Andric 
5970b57cec5SDimitry Andric template <bool AlwaysPrintImm0>
printAddrMode3Operand(const MCInst * MI,unsigned Op,const MCSubtargetInfo & STI,raw_ostream & O)5980b57cec5SDimitry Andric void ARMInstPrinter::printAddrMode3Operand(const MCInst *MI, unsigned Op,
5990b57cec5SDimitry Andric                                            const MCSubtargetInfo &STI,
6000b57cec5SDimitry Andric                                            raw_ostream &O) {
6010b57cec5SDimitry Andric   const MCOperand &MO1 = MI->getOperand(Op);
6020b57cec5SDimitry Andric   if (!MO1.isReg()) { //  For label symbolic references.
6030b57cec5SDimitry Andric     printOperand(MI, Op, STI, O);
6040b57cec5SDimitry Andric     return;
6050b57cec5SDimitry Andric   }
6060b57cec5SDimitry Andric 
6070b57cec5SDimitry Andric   assert(ARM_AM::getAM3IdxMode(MI->getOperand(Op + 2).getImm()) !=
6080b57cec5SDimitry Andric              ARMII::IndexModePost &&
6090b57cec5SDimitry Andric          "unexpected idxmode");
6100b57cec5SDimitry Andric   printAM3PreOrOffsetIndexOp(MI, Op, O, AlwaysPrintImm0);
6110b57cec5SDimitry Andric }
6120b57cec5SDimitry Andric 
printAddrMode3OffsetOperand(const MCInst * MI,unsigned OpNum,const MCSubtargetInfo & STI,raw_ostream & O)6130b57cec5SDimitry Andric void ARMInstPrinter::printAddrMode3OffsetOperand(const MCInst *MI,
6140b57cec5SDimitry Andric                                                  unsigned OpNum,
6150b57cec5SDimitry Andric                                                  const MCSubtargetInfo &STI,
6160b57cec5SDimitry Andric                                                  raw_ostream &O) {
6170b57cec5SDimitry Andric   const MCOperand &MO1 = MI->getOperand(OpNum);
6180b57cec5SDimitry Andric   const MCOperand &MO2 = MI->getOperand(OpNum + 1);
6190b57cec5SDimitry Andric 
6200b57cec5SDimitry Andric   if (MO1.getReg()) {
6210b57cec5SDimitry Andric     O << getAddrOpcStr(ARM_AM::getAM3Op(MO2.getImm()));
6220b57cec5SDimitry Andric     printRegName(O, MO1.getReg());
6230b57cec5SDimitry Andric     return;
6240b57cec5SDimitry Andric   }
6250b57cec5SDimitry Andric 
6260b57cec5SDimitry Andric   unsigned ImmOffs = ARM_AM::getAM3Offset(MO2.getImm());
6275f757f3fSDimitry Andric   markup(O, Markup::Immediate)
6285f757f3fSDimitry Andric       << '#' << ARM_AM::getAddrOpcStr(ARM_AM::getAM3Op(MO2.getImm()))
6295f757f3fSDimitry Andric       << ImmOffs;
6300b57cec5SDimitry Andric }
6310b57cec5SDimitry Andric 
printPostIdxImm8Operand(const MCInst * MI,unsigned OpNum,const MCSubtargetInfo & STI,raw_ostream & O)6320b57cec5SDimitry Andric void ARMInstPrinter::printPostIdxImm8Operand(const MCInst *MI, unsigned OpNum,
6330b57cec5SDimitry Andric                                              const MCSubtargetInfo &STI,
6340b57cec5SDimitry Andric                                              raw_ostream &O) {
6350b57cec5SDimitry Andric   const MCOperand &MO = MI->getOperand(OpNum);
6360b57cec5SDimitry Andric   unsigned Imm = MO.getImm();
6375f757f3fSDimitry Andric   markup(O, Markup::Immediate)
6385f757f3fSDimitry Andric       << '#' << ((Imm & 256) ? "" : "-") << (Imm & 0xff);
6390b57cec5SDimitry Andric }
6400b57cec5SDimitry Andric 
printPostIdxRegOperand(const MCInst * MI,unsigned OpNum,const MCSubtargetInfo & STI,raw_ostream & O)6410b57cec5SDimitry Andric void ARMInstPrinter::printPostIdxRegOperand(const MCInst *MI, unsigned OpNum,
6420b57cec5SDimitry Andric                                             const MCSubtargetInfo &STI,
6430b57cec5SDimitry Andric                                             raw_ostream &O) {
6440b57cec5SDimitry Andric   const MCOperand &MO1 = MI->getOperand(OpNum);
6450b57cec5SDimitry Andric   const MCOperand &MO2 = MI->getOperand(OpNum + 1);
6460b57cec5SDimitry Andric 
6470b57cec5SDimitry Andric   O << (MO2.getImm() ? "" : "-");
6480b57cec5SDimitry Andric   printRegName(O, MO1.getReg());
6490b57cec5SDimitry Andric }
6500b57cec5SDimitry Andric 
printPostIdxImm8s4Operand(const MCInst * MI,unsigned OpNum,const MCSubtargetInfo & STI,raw_ostream & O)6510b57cec5SDimitry Andric void ARMInstPrinter::printPostIdxImm8s4Operand(const MCInst *MI, unsigned OpNum,
6520b57cec5SDimitry Andric                                                const MCSubtargetInfo &STI,
6530b57cec5SDimitry Andric                                                raw_ostream &O) {
6540b57cec5SDimitry Andric   const MCOperand &MO = MI->getOperand(OpNum);
6550b57cec5SDimitry Andric   unsigned Imm = MO.getImm();
6565f757f3fSDimitry Andric   markup(O, Markup::Immediate)
6575f757f3fSDimitry Andric       << '#' << ((Imm & 256) ? "" : "-") << ((Imm & 0xff) << 2);
6580b57cec5SDimitry Andric }
6590b57cec5SDimitry Andric 
6600b57cec5SDimitry Andric template<int shift>
printMveAddrModeRQOperand(const MCInst * MI,unsigned OpNum,const MCSubtargetInfo & STI,raw_ostream & O)6610b57cec5SDimitry Andric void ARMInstPrinter::printMveAddrModeRQOperand(const MCInst *MI, unsigned OpNum,
6620b57cec5SDimitry Andric                                                const MCSubtargetInfo &STI,
6630b57cec5SDimitry Andric                                                raw_ostream &O) {
6640b57cec5SDimitry Andric   const MCOperand &MO1 = MI->getOperand(OpNum);
6650b57cec5SDimitry Andric   const MCOperand &MO2 = MI->getOperand(OpNum + 1);
6660b57cec5SDimitry Andric 
6675f757f3fSDimitry Andric   WithMarkup ScopedMarkup = markup(O, Markup::Memory);
6685f757f3fSDimitry Andric   O << "[";
6690b57cec5SDimitry Andric   printRegName(O, MO1.getReg());
6700b57cec5SDimitry Andric   O << ", ";
6710b57cec5SDimitry Andric   printRegName(O, MO2.getReg());
6720b57cec5SDimitry Andric 
6730b57cec5SDimitry Andric   if (shift > 0)
6745f757f3fSDimitry Andric     printRegImmShift(O, ARM_AM::uxtw, shift, *this);
6750b57cec5SDimitry Andric 
6765f757f3fSDimitry Andric   O << "]";
6770b57cec5SDimitry Andric }
6780b57cec5SDimitry Andric 
printLdStmModeOperand(const MCInst * MI,unsigned OpNum,const MCSubtargetInfo & STI,raw_ostream & O)6790b57cec5SDimitry Andric void ARMInstPrinter::printLdStmModeOperand(const MCInst *MI, unsigned OpNum,
6800b57cec5SDimitry Andric                                            const MCSubtargetInfo &STI,
6810b57cec5SDimitry Andric                                            raw_ostream &O) {
6820b57cec5SDimitry Andric   ARM_AM::AMSubMode Mode =
6830b57cec5SDimitry Andric       ARM_AM::getAM4SubMode(MI->getOperand(OpNum).getImm());
6840b57cec5SDimitry Andric   O << ARM_AM::getAMSubModeStr(Mode);
6850b57cec5SDimitry Andric }
6860b57cec5SDimitry Andric 
6870b57cec5SDimitry Andric template <bool AlwaysPrintImm0>
printAddrMode5Operand(const MCInst * MI,unsigned OpNum,const MCSubtargetInfo & STI,raw_ostream & O)6880b57cec5SDimitry Andric void ARMInstPrinter::printAddrMode5Operand(const MCInst *MI, unsigned OpNum,
6890b57cec5SDimitry Andric                                            const MCSubtargetInfo &STI,
6900b57cec5SDimitry Andric                                            raw_ostream &O) {
6910b57cec5SDimitry Andric   const MCOperand &MO1 = MI->getOperand(OpNum);
6920b57cec5SDimitry Andric   const MCOperand &MO2 = MI->getOperand(OpNum + 1);
6930b57cec5SDimitry Andric 
6940b57cec5SDimitry Andric   if (!MO1.isReg()) { // FIXME: This is for CP entries, but isn't right.
6950b57cec5SDimitry Andric     printOperand(MI, OpNum, STI, O);
6960b57cec5SDimitry Andric     return;
6970b57cec5SDimitry Andric   }
6980b57cec5SDimitry Andric 
6995f757f3fSDimitry Andric   WithMarkup ScopedMarkup = markup(O, Markup::Memory);
7005f757f3fSDimitry Andric   O << "[";
7010b57cec5SDimitry Andric   printRegName(O, MO1.getReg());
7020b57cec5SDimitry Andric 
7030b57cec5SDimitry Andric   unsigned ImmOffs = ARM_AM::getAM5Offset(MO2.getImm());
7040b57cec5SDimitry Andric   ARM_AM::AddrOpc Op = ARM_AM::getAM5Op(MO2.getImm());
7050b57cec5SDimitry Andric   if (AlwaysPrintImm0 || ImmOffs || Op == ARM_AM::sub) {
7065f757f3fSDimitry Andric     O << ", ";
7075f757f3fSDimitry Andric     markup(O, Markup::Immediate)
7085f757f3fSDimitry Andric         << "#" << ARM_AM::getAddrOpcStr(Op) << ImmOffs * 4;
7090b57cec5SDimitry Andric   }
7105f757f3fSDimitry Andric   O << "]";
7110b57cec5SDimitry Andric }
7120b57cec5SDimitry Andric 
7130b57cec5SDimitry Andric template <bool AlwaysPrintImm0>
printAddrMode5FP16Operand(const MCInst * MI,unsigned OpNum,const MCSubtargetInfo & STI,raw_ostream & O)7140b57cec5SDimitry Andric void ARMInstPrinter::printAddrMode5FP16Operand(const MCInst *MI, unsigned OpNum,
7150b57cec5SDimitry Andric                                                const MCSubtargetInfo &STI,
7160b57cec5SDimitry Andric                                                raw_ostream &O) {
7170b57cec5SDimitry Andric   const MCOperand &MO1 = MI->getOperand(OpNum);
7180b57cec5SDimitry Andric   const MCOperand &MO2 = MI->getOperand(OpNum+1);
7190b57cec5SDimitry Andric 
7200b57cec5SDimitry Andric   if (!MO1.isReg()) {   // FIXME: This is for CP entries, but isn't right.
7210b57cec5SDimitry Andric     printOperand(MI, OpNum, STI, O);
7220b57cec5SDimitry Andric     return;
7230b57cec5SDimitry Andric   }
7240b57cec5SDimitry Andric 
7255f757f3fSDimitry Andric   WithMarkup ScopedMarkup = markup(O, Markup::Memory);
7265f757f3fSDimitry Andric   O << "[";
7270b57cec5SDimitry Andric   printRegName(O, MO1.getReg());
7280b57cec5SDimitry Andric 
7290b57cec5SDimitry Andric   unsigned ImmOffs = ARM_AM::getAM5FP16Offset(MO2.getImm());
7300b57cec5SDimitry Andric   unsigned Op = ARM_AM::getAM5FP16Op(MO2.getImm());
7310b57cec5SDimitry Andric   if (AlwaysPrintImm0 || ImmOffs || Op == ARM_AM::sub) {
7325f757f3fSDimitry Andric     O << ", ";
7335f757f3fSDimitry Andric     markup(O, Markup::Immediate)
7345f757f3fSDimitry Andric         << "#" << ARM_AM::getAddrOpcStr(ARM_AM::getAM5FP16Op(MO2.getImm()))
7355f757f3fSDimitry Andric         << ImmOffs * 2;
7360b57cec5SDimitry Andric   }
7375f757f3fSDimitry Andric   O << "]";
7380b57cec5SDimitry Andric }
7390b57cec5SDimitry Andric 
printAddrMode6Operand(const MCInst * MI,unsigned OpNum,const MCSubtargetInfo & STI,raw_ostream & O)7400b57cec5SDimitry Andric void ARMInstPrinter::printAddrMode6Operand(const MCInst *MI, unsigned OpNum,
7410b57cec5SDimitry Andric                                            const MCSubtargetInfo &STI,
7420b57cec5SDimitry Andric                                            raw_ostream &O) {
7430b57cec5SDimitry Andric   const MCOperand &MO1 = MI->getOperand(OpNum);
7440b57cec5SDimitry Andric   const MCOperand &MO2 = MI->getOperand(OpNum + 1);
7450b57cec5SDimitry Andric 
7465f757f3fSDimitry Andric   WithMarkup ScopedMarkup = markup(O, Markup::Memory);
7475f757f3fSDimitry Andric   O << "[";
7480b57cec5SDimitry Andric   printRegName(O, MO1.getReg());
7490b57cec5SDimitry Andric   if (MO2.getImm()) {
7500b57cec5SDimitry Andric     O << ":" << (MO2.getImm() << 3);
7510b57cec5SDimitry Andric   }
7525f757f3fSDimitry Andric   O << "]";
7530b57cec5SDimitry Andric }
7540b57cec5SDimitry Andric 
printAddrMode7Operand(const MCInst * MI,unsigned OpNum,const MCSubtargetInfo & STI,raw_ostream & O)7550b57cec5SDimitry Andric void ARMInstPrinter::printAddrMode7Operand(const MCInst *MI, unsigned OpNum,
7560b57cec5SDimitry Andric                                            const MCSubtargetInfo &STI,
7570b57cec5SDimitry Andric                                            raw_ostream &O) {
7580b57cec5SDimitry Andric   const MCOperand &MO1 = MI->getOperand(OpNum);
7595f757f3fSDimitry Andric   WithMarkup ScopedMarkup = markup(O, Markup::Memory);
7605f757f3fSDimitry Andric   O << "[";
7610b57cec5SDimitry Andric   printRegName(O, MO1.getReg());
7625f757f3fSDimitry Andric   O << "]";
7630b57cec5SDimitry Andric }
7640b57cec5SDimitry Andric 
printAddrMode6OffsetOperand(const MCInst * MI,unsigned OpNum,const MCSubtargetInfo & STI,raw_ostream & O)7650b57cec5SDimitry Andric void ARMInstPrinter::printAddrMode6OffsetOperand(const MCInst *MI,
7660b57cec5SDimitry Andric                                                  unsigned OpNum,
7670b57cec5SDimitry Andric                                                  const MCSubtargetInfo &STI,
7680b57cec5SDimitry Andric                                                  raw_ostream &O) {
7690b57cec5SDimitry Andric   const MCOperand &MO = MI->getOperand(OpNum);
7700b57cec5SDimitry Andric   if (MO.getReg() == 0)
7710b57cec5SDimitry Andric     O << "!";
7720b57cec5SDimitry Andric   else {
7730b57cec5SDimitry Andric     O << ", ";
7740b57cec5SDimitry Andric     printRegName(O, MO.getReg());
7750b57cec5SDimitry Andric   }
7760b57cec5SDimitry Andric }
7770b57cec5SDimitry Andric 
printBitfieldInvMaskImmOperand(const MCInst * MI,unsigned OpNum,const MCSubtargetInfo & STI,raw_ostream & O)7780b57cec5SDimitry Andric void ARMInstPrinter::printBitfieldInvMaskImmOperand(const MCInst *MI,
7790b57cec5SDimitry Andric                                                     unsigned OpNum,
7800b57cec5SDimitry Andric                                                     const MCSubtargetInfo &STI,
7810b57cec5SDimitry Andric                                                     raw_ostream &O) {
7820b57cec5SDimitry Andric   const MCOperand &MO = MI->getOperand(OpNum);
7830b57cec5SDimitry Andric   uint32_t v = ~MO.getImm();
78406c3fb27SDimitry Andric   int32_t lsb = llvm::countr_zero(v);
785bdd1243dSDimitry Andric   int32_t width = llvm::bit_width(v) - lsb;
7860b57cec5SDimitry Andric   assert(MO.isImm() && "Not a valid bf_inv_mask_imm value!");
7875f757f3fSDimitry Andric   markup(O, Markup::Immediate) << '#' << lsb;
7885f757f3fSDimitry Andric   O << ", ";
7895f757f3fSDimitry Andric   markup(O, Markup::Immediate) << '#' << width;
7900b57cec5SDimitry Andric }
7910b57cec5SDimitry Andric 
printMemBOption(const MCInst * MI,unsigned OpNum,const MCSubtargetInfo & STI,raw_ostream & O)7920b57cec5SDimitry Andric void ARMInstPrinter::printMemBOption(const MCInst *MI, unsigned OpNum,
7930b57cec5SDimitry Andric                                      const MCSubtargetInfo &STI,
7940b57cec5SDimitry Andric                                      raw_ostream &O) {
7950b57cec5SDimitry Andric   unsigned val = MI->getOperand(OpNum).getImm();
79606c3fb27SDimitry Andric   O << ARM_MB::MemBOptToString(val, STI.hasFeature(ARM::HasV8Ops));
7970b57cec5SDimitry Andric }
7980b57cec5SDimitry Andric 
printInstSyncBOption(const MCInst * MI,unsigned OpNum,const MCSubtargetInfo & STI,raw_ostream & O)7990b57cec5SDimitry Andric void ARMInstPrinter::printInstSyncBOption(const MCInst *MI, unsigned OpNum,
8000b57cec5SDimitry Andric                                           const MCSubtargetInfo &STI,
8010b57cec5SDimitry Andric                                           raw_ostream &O) {
8020b57cec5SDimitry Andric   unsigned val = MI->getOperand(OpNum).getImm();
8030b57cec5SDimitry Andric   O << ARM_ISB::InstSyncBOptToString(val);
8040b57cec5SDimitry Andric }
8050b57cec5SDimitry Andric 
printTraceSyncBOption(const MCInst * MI,unsigned OpNum,const MCSubtargetInfo & STI,raw_ostream & O)8060b57cec5SDimitry Andric void ARMInstPrinter::printTraceSyncBOption(const MCInst *MI, unsigned OpNum,
8070b57cec5SDimitry Andric                                           const MCSubtargetInfo &STI,
8080b57cec5SDimitry Andric                                           raw_ostream &O) {
8090b57cec5SDimitry Andric   unsigned val = MI->getOperand(OpNum).getImm();
8100b57cec5SDimitry Andric   O << ARM_TSB::TraceSyncBOptToString(val);
8110b57cec5SDimitry Andric }
8120b57cec5SDimitry Andric 
printShiftImmOperand(const MCInst * MI,unsigned OpNum,const MCSubtargetInfo & STI,raw_ostream & O)8130b57cec5SDimitry Andric void ARMInstPrinter::printShiftImmOperand(const MCInst *MI, unsigned OpNum,
8140b57cec5SDimitry Andric                                           const MCSubtargetInfo &STI,
8150b57cec5SDimitry Andric                                           raw_ostream &O) {
8160b57cec5SDimitry Andric   unsigned ShiftOp = MI->getOperand(OpNum).getImm();
8170b57cec5SDimitry Andric   bool isASR = (ShiftOp & (1 << 5)) != 0;
8180b57cec5SDimitry Andric   unsigned Amt = ShiftOp & 0x1f;
8190b57cec5SDimitry Andric   if (isASR) {
8205f757f3fSDimitry Andric     O << ", asr ";
8215f757f3fSDimitry Andric     markup(O, Markup::Immediate) << "#" << (Amt == 0 ? 32 : Amt);
8220b57cec5SDimitry Andric   } else if (Amt) {
8235f757f3fSDimitry Andric     O << ", lsl ";
8245f757f3fSDimitry Andric     markup(O, Markup::Immediate) << "#" << Amt;
8250b57cec5SDimitry Andric   }
8260b57cec5SDimitry Andric }
8270b57cec5SDimitry Andric 
printPKHLSLShiftImm(const MCInst * MI,unsigned OpNum,const MCSubtargetInfo & STI,raw_ostream & O)8280b57cec5SDimitry Andric void ARMInstPrinter::printPKHLSLShiftImm(const MCInst *MI, unsigned OpNum,
8290b57cec5SDimitry Andric                                          const MCSubtargetInfo &STI,
8300b57cec5SDimitry Andric                                          raw_ostream &O) {
8310b57cec5SDimitry Andric   unsigned Imm = MI->getOperand(OpNum).getImm();
8320b57cec5SDimitry Andric   if (Imm == 0)
8330b57cec5SDimitry Andric     return;
8340b57cec5SDimitry Andric   assert(Imm > 0 && Imm < 32 && "Invalid PKH shift immediate value!");
8355f757f3fSDimitry Andric   O << ", lsl ";
8365f757f3fSDimitry Andric   markup(O, Markup::Immediate) << "#" << Imm;
8370b57cec5SDimitry Andric }
8380b57cec5SDimitry Andric 
printPKHASRShiftImm(const MCInst * MI,unsigned OpNum,const MCSubtargetInfo & STI,raw_ostream & O)8390b57cec5SDimitry Andric void ARMInstPrinter::printPKHASRShiftImm(const MCInst *MI, unsigned OpNum,
8400b57cec5SDimitry Andric                                          const MCSubtargetInfo &STI,
8410b57cec5SDimitry Andric                                          raw_ostream &O) {
8420b57cec5SDimitry Andric   unsigned Imm = MI->getOperand(OpNum).getImm();
8430b57cec5SDimitry Andric   // A shift amount of 32 is encoded as 0.
8440b57cec5SDimitry Andric   if (Imm == 0)
8450b57cec5SDimitry Andric     Imm = 32;
8460b57cec5SDimitry Andric   assert(Imm > 0 && Imm <= 32 && "Invalid PKH shift immediate value!");
8475f757f3fSDimitry Andric   O << ", asr ";
8485f757f3fSDimitry Andric   markup(O, Markup::Immediate) << "#" << Imm;
8490b57cec5SDimitry Andric }
8500b57cec5SDimitry Andric 
printRegisterList(const MCInst * MI,unsigned OpNum,const MCSubtargetInfo & STI,raw_ostream & O)8510b57cec5SDimitry Andric void ARMInstPrinter::printRegisterList(const MCInst *MI, unsigned OpNum,
8520b57cec5SDimitry Andric                                        const MCSubtargetInfo &STI,
8530b57cec5SDimitry Andric                                        raw_ostream &O) {
8540b57cec5SDimitry Andric   if (MI->getOpcode() != ARM::t2CLRM) {
855fe6060f1SDimitry Andric     assert(is_sorted(drop_begin(*MI, OpNum),
8560b57cec5SDimitry Andric                      [&](const MCOperand &LHS, const MCOperand &RHS) {
8570b57cec5SDimitry Andric                        return MRI.getEncodingValue(LHS.getReg()) <
8580b57cec5SDimitry Andric                               MRI.getEncodingValue(RHS.getReg());
8590b57cec5SDimitry Andric                      }));
8600b57cec5SDimitry Andric   }
8610b57cec5SDimitry Andric 
8620b57cec5SDimitry Andric   O << "{";
8630b57cec5SDimitry Andric   for (unsigned i = OpNum, e = MI->getNumOperands(); i != e; ++i) {
8640b57cec5SDimitry Andric     if (i != OpNum)
8650b57cec5SDimitry Andric       O << ", ";
8660b57cec5SDimitry Andric     printRegName(O, MI->getOperand(i).getReg());
8670b57cec5SDimitry Andric   }
8680b57cec5SDimitry Andric   O << "}";
8690b57cec5SDimitry Andric }
8700b57cec5SDimitry Andric 
printGPRPairOperand(const MCInst * MI,unsigned OpNum,const MCSubtargetInfo & STI,raw_ostream & O)8710b57cec5SDimitry Andric void ARMInstPrinter::printGPRPairOperand(const MCInst *MI, unsigned OpNum,
8720b57cec5SDimitry Andric                                          const MCSubtargetInfo &STI,
8730b57cec5SDimitry Andric                                          raw_ostream &O) {
8740b57cec5SDimitry Andric   unsigned Reg = MI->getOperand(OpNum).getReg();
8750b57cec5SDimitry Andric   printRegName(O, MRI.getSubReg(Reg, ARM::gsub_0));
8760b57cec5SDimitry Andric   O << ", ";
8770b57cec5SDimitry Andric   printRegName(O, MRI.getSubReg(Reg, ARM::gsub_1));
8780b57cec5SDimitry Andric }
8790b57cec5SDimitry Andric 
printSetendOperand(const MCInst * MI,unsigned OpNum,const MCSubtargetInfo & STI,raw_ostream & O)8800b57cec5SDimitry Andric void ARMInstPrinter::printSetendOperand(const MCInst *MI, unsigned OpNum,
8810b57cec5SDimitry Andric                                         const MCSubtargetInfo &STI,
8820b57cec5SDimitry Andric                                         raw_ostream &O) {
8830b57cec5SDimitry Andric   const MCOperand &Op = MI->getOperand(OpNum);
8840b57cec5SDimitry Andric   if (Op.getImm())
8850b57cec5SDimitry Andric     O << "be";
8860b57cec5SDimitry Andric   else
8870b57cec5SDimitry Andric     O << "le";
8880b57cec5SDimitry Andric }
8890b57cec5SDimitry Andric 
printCPSIMod(const MCInst * MI,unsigned OpNum,const MCSubtargetInfo & STI,raw_ostream & O)8900b57cec5SDimitry Andric void ARMInstPrinter::printCPSIMod(const MCInst *MI, unsigned OpNum,
8910b57cec5SDimitry Andric                                   const MCSubtargetInfo &STI, raw_ostream &O) {
8920b57cec5SDimitry Andric   const MCOperand &Op = MI->getOperand(OpNum);
8930b57cec5SDimitry Andric   O << ARM_PROC::IModToString(Op.getImm());
8940b57cec5SDimitry Andric }
8950b57cec5SDimitry Andric 
printCPSIFlag(const MCInst * MI,unsigned OpNum,const MCSubtargetInfo & STI,raw_ostream & O)8960b57cec5SDimitry Andric void ARMInstPrinter::printCPSIFlag(const MCInst *MI, unsigned OpNum,
8970b57cec5SDimitry Andric                                    const MCSubtargetInfo &STI, raw_ostream &O) {
8980b57cec5SDimitry Andric   const MCOperand &Op = MI->getOperand(OpNum);
8990b57cec5SDimitry Andric   unsigned IFlags = Op.getImm();
9000b57cec5SDimitry Andric   for (int i = 2; i >= 0; --i)
9010b57cec5SDimitry Andric     if (IFlags & (1 << i))
9020b57cec5SDimitry Andric       O << ARM_PROC::IFlagsToString(1 << i);
9030b57cec5SDimitry Andric 
9040b57cec5SDimitry Andric   if (IFlags == 0)
9050b57cec5SDimitry Andric     O << "none";
9060b57cec5SDimitry Andric }
9070b57cec5SDimitry Andric 
printMSRMaskOperand(const MCInst * MI,unsigned OpNum,const MCSubtargetInfo & STI,raw_ostream & O)9080b57cec5SDimitry Andric void ARMInstPrinter::printMSRMaskOperand(const MCInst *MI, unsigned OpNum,
9090b57cec5SDimitry Andric                                          const MCSubtargetInfo &STI,
9100b57cec5SDimitry Andric                                          raw_ostream &O) {
9110b57cec5SDimitry Andric   const MCOperand &Op = MI->getOperand(OpNum);
9120b57cec5SDimitry Andric   const FeatureBitset &FeatureBits = STI.getFeatureBits();
9130b57cec5SDimitry Andric   if (FeatureBits[ARM::FeatureMClass]) {
9140b57cec5SDimitry Andric 
9150b57cec5SDimitry Andric     unsigned SYSm = Op.getImm() & 0xFFF; // 12-bit SYSm
9160b57cec5SDimitry Andric     unsigned Opcode = MI->getOpcode();
9170b57cec5SDimitry Andric 
9180b57cec5SDimitry Andric     // For writes, handle extended mask bits if the DSP extension is present.
9190b57cec5SDimitry Andric     if (Opcode == ARM::t2MSR_M && FeatureBits[ARM::FeatureDSP]) {
9200b57cec5SDimitry Andric       auto TheReg =ARMSysReg::lookupMClassSysRegBy12bitSYSmValue(SYSm);
9210b57cec5SDimitry Andric       if (TheReg && TheReg->isInRequiredFeatures({ARM::FeatureDSP})) {
9220b57cec5SDimitry Andric           O << TheReg->Name;
9230b57cec5SDimitry Andric           return;
9240b57cec5SDimitry Andric       }
9250b57cec5SDimitry Andric     }
9260b57cec5SDimitry Andric 
9270b57cec5SDimitry Andric     // Handle the basic 8-bit mask.
9280b57cec5SDimitry Andric     SYSm &= 0xff;
9290b57cec5SDimitry Andric     if (Opcode == ARM::t2MSR_M && FeatureBits [ARM::HasV7Ops]) {
9300b57cec5SDimitry Andric       // ARMv7-M deprecates using MSR APSR without a _<bits> qualifier as an
9310b57cec5SDimitry Andric       // alias for MSR APSR_nzcvq.
9320b57cec5SDimitry Andric       auto TheReg = ARMSysReg::lookupMClassSysRegAPSRNonDeprecated(SYSm);
9330b57cec5SDimitry Andric       if (TheReg) {
9340b57cec5SDimitry Andric           O << TheReg->Name;
9350b57cec5SDimitry Andric           return;
9360b57cec5SDimitry Andric       }
9370b57cec5SDimitry Andric     }
9380b57cec5SDimitry Andric 
9390b57cec5SDimitry Andric     auto TheReg = ARMSysReg::lookupMClassSysRegBy8bitSYSmValue(SYSm);
9400b57cec5SDimitry Andric     if (TheReg) {
9410b57cec5SDimitry Andric       O << TheReg->Name;
9420b57cec5SDimitry Andric       return;
9430b57cec5SDimitry Andric     }
9440b57cec5SDimitry Andric 
9450b57cec5SDimitry Andric     O << SYSm;
9460b57cec5SDimitry Andric 
9470b57cec5SDimitry Andric     return;
9480b57cec5SDimitry Andric   }
9490b57cec5SDimitry Andric 
9500b57cec5SDimitry Andric   // As special cases, CPSR_f, CPSR_s and CPSR_fs prefer printing as
9510b57cec5SDimitry Andric   // APSR_nzcvq, APSR_g and APSRnzcvqg, respectively.
9520b57cec5SDimitry Andric   unsigned SpecRegRBit = Op.getImm() >> 4;
9530b57cec5SDimitry Andric   unsigned Mask = Op.getImm() & 0xf;
9540b57cec5SDimitry Andric 
9550b57cec5SDimitry Andric   if (!SpecRegRBit && (Mask == 8 || Mask == 4 || Mask == 12)) {
9560b57cec5SDimitry Andric     O << "APSR_";
9570b57cec5SDimitry Andric     switch (Mask) {
9580b57cec5SDimitry Andric     default:
9590b57cec5SDimitry Andric       llvm_unreachable("Unexpected mask value!");
9600b57cec5SDimitry Andric     case 4:
9610b57cec5SDimitry Andric       O << "g";
9620b57cec5SDimitry Andric       return;
9630b57cec5SDimitry Andric     case 8:
9640b57cec5SDimitry Andric       O << "nzcvq";
9650b57cec5SDimitry Andric       return;
9660b57cec5SDimitry Andric     case 12:
9670b57cec5SDimitry Andric       O << "nzcvqg";
9680b57cec5SDimitry Andric       return;
9690b57cec5SDimitry Andric     }
9700b57cec5SDimitry Andric   }
9710b57cec5SDimitry Andric 
9720b57cec5SDimitry Andric   if (SpecRegRBit)
9730b57cec5SDimitry Andric     O << "SPSR";
9740b57cec5SDimitry Andric   else
9750b57cec5SDimitry Andric     O << "CPSR";
9760b57cec5SDimitry Andric 
9770b57cec5SDimitry Andric   if (Mask) {
9780b57cec5SDimitry Andric     O << '_';
9790b57cec5SDimitry Andric     if (Mask & 8)
9800b57cec5SDimitry Andric       O << 'f';
9810b57cec5SDimitry Andric     if (Mask & 4)
9820b57cec5SDimitry Andric       O << 's';
9830b57cec5SDimitry Andric     if (Mask & 2)
9840b57cec5SDimitry Andric       O << 'x';
9850b57cec5SDimitry Andric     if (Mask & 1)
9860b57cec5SDimitry Andric       O << 'c';
9870b57cec5SDimitry Andric   }
9880b57cec5SDimitry Andric }
9890b57cec5SDimitry Andric 
printBankedRegOperand(const MCInst * MI,unsigned OpNum,const MCSubtargetInfo & STI,raw_ostream & O)9900b57cec5SDimitry Andric void ARMInstPrinter::printBankedRegOperand(const MCInst *MI, unsigned OpNum,
9910b57cec5SDimitry Andric                                            const MCSubtargetInfo &STI,
9920b57cec5SDimitry Andric                                            raw_ostream &O) {
9930b57cec5SDimitry Andric   uint32_t Banked = MI->getOperand(OpNum).getImm();
9940b57cec5SDimitry Andric   auto TheReg = ARMBankedReg::lookupBankedRegByEncoding(Banked);
9950b57cec5SDimitry Andric   assert(TheReg && "invalid banked register operand");
9960b57cec5SDimitry Andric   std::string Name = TheReg->Name;
9970b57cec5SDimitry Andric 
9980b57cec5SDimitry Andric   uint32_t isSPSR = (Banked & 0x20) >> 5;
9990b57cec5SDimitry Andric   if (isSPSR)
10000b57cec5SDimitry Andric     Name.replace(0, 4, "SPSR"); // convert 'spsr_' to 'SPSR_'
10010b57cec5SDimitry Andric   O << Name;
10020b57cec5SDimitry Andric }
10030b57cec5SDimitry Andric 
printPredicateOperand(const MCInst * MI,unsigned OpNum,const MCSubtargetInfo & STI,raw_ostream & O)10040b57cec5SDimitry Andric void ARMInstPrinter::printPredicateOperand(const MCInst *MI, unsigned OpNum,
10050b57cec5SDimitry Andric                                            const MCSubtargetInfo &STI,
10060b57cec5SDimitry Andric                                            raw_ostream &O) {
10070b57cec5SDimitry Andric   ARMCC::CondCodes CC = (ARMCC::CondCodes)MI->getOperand(OpNum).getImm();
10080b57cec5SDimitry Andric   // Handle the undefined 15 CC value here for printing so we don't abort().
10090b57cec5SDimitry Andric   if ((unsigned)CC == 15)
10100b57cec5SDimitry Andric     O << "<und>";
10110b57cec5SDimitry Andric   else if (CC != ARMCC::AL)
10120b57cec5SDimitry Andric     O << ARMCondCodeToString(CC);
10130b57cec5SDimitry Andric }
10140b57cec5SDimitry Andric 
printMandatoryRestrictedPredicateOperand(const MCInst * MI,unsigned OpNum,const MCSubtargetInfo & STI,raw_ostream & O)10150b57cec5SDimitry Andric void ARMInstPrinter::printMandatoryRestrictedPredicateOperand(
10160b57cec5SDimitry Andric     const MCInst *MI, unsigned OpNum, const MCSubtargetInfo &STI,
10170b57cec5SDimitry Andric     raw_ostream &O) {
10180b57cec5SDimitry Andric   if ((ARMCC::CondCodes)MI->getOperand(OpNum).getImm() == ARMCC::HS)
10190b57cec5SDimitry Andric     O << "cs";
10200b57cec5SDimitry Andric   else
10210b57cec5SDimitry Andric     printMandatoryPredicateOperand(MI, OpNum, STI, O);
10220b57cec5SDimitry Andric }
10230b57cec5SDimitry Andric 
printMandatoryPredicateOperand(const MCInst * MI,unsigned OpNum,const MCSubtargetInfo & STI,raw_ostream & O)10240b57cec5SDimitry Andric void ARMInstPrinter::printMandatoryPredicateOperand(const MCInst *MI,
10250b57cec5SDimitry Andric                                                     unsigned OpNum,
10260b57cec5SDimitry Andric                                                     const MCSubtargetInfo &STI,
10270b57cec5SDimitry Andric                                                     raw_ostream &O) {
10280b57cec5SDimitry Andric   ARMCC::CondCodes CC = (ARMCC::CondCodes)MI->getOperand(OpNum).getImm();
10290b57cec5SDimitry Andric   O << ARMCondCodeToString(CC);
10300b57cec5SDimitry Andric }
10310b57cec5SDimitry Andric 
printMandatoryInvertedPredicateOperand(const MCInst * MI,unsigned OpNum,const MCSubtargetInfo & STI,raw_ostream & O)10320b57cec5SDimitry Andric void ARMInstPrinter::printMandatoryInvertedPredicateOperand(const MCInst *MI,
10330b57cec5SDimitry Andric                                                             unsigned OpNum,
10340b57cec5SDimitry Andric                                                             const MCSubtargetInfo &STI,
10350b57cec5SDimitry Andric                                                             raw_ostream &O) {
10360b57cec5SDimitry Andric   ARMCC::CondCodes CC = (ARMCC::CondCodes)MI->getOperand(OpNum).getImm();
10370b57cec5SDimitry Andric   O << ARMCondCodeToString(ARMCC::getOppositeCondition(CC));
10380b57cec5SDimitry Andric }
10390b57cec5SDimitry Andric 
printSBitModifierOperand(const MCInst * MI,unsigned OpNum,const MCSubtargetInfo & STI,raw_ostream & O)10400b57cec5SDimitry Andric void ARMInstPrinter::printSBitModifierOperand(const MCInst *MI, unsigned OpNum,
10410b57cec5SDimitry Andric                                               const MCSubtargetInfo &STI,
10420b57cec5SDimitry Andric                                               raw_ostream &O) {
10430b57cec5SDimitry Andric   if (MI->getOperand(OpNum).getReg()) {
10440b57cec5SDimitry Andric     assert(MI->getOperand(OpNum).getReg() == ARM::CPSR &&
10450b57cec5SDimitry Andric            "Expect ARM CPSR register!");
10460b57cec5SDimitry Andric     O << 's';
10470b57cec5SDimitry Andric   }
10480b57cec5SDimitry Andric }
10490b57cec5SDimitry Andric 
printNoHashImmediate(const MCInst * MI,unsigned OpNum,const MCSubtargetInfo & STI,raw_ostream & O)10500b57cec5SDimitry Andric void ARMInstPrinter::printNoHashImmediate(const MCInst *MI, unsigned OpNum,
10510b57cec5SDimitry Andric                                           const MCSubtargetInfo &STI,
10520b57cec5SDimitry Andric                                           raw_ostream &O) {
10530b57cec5SDimitry Andric   O << MI->getOperand(OpNum).getImm();
10540b57cec5SDimitry Andric }
10550b57cec5SDimitry Andric 
printPImmediate(const MCInst * MI,unsigned OpNum,const MCSubtargetInfo & STI,raw_ostream & O)10560b57cec5SDimitry Andric void ARMInstPrinter::printPImmediate(const MCInst *MI, unsigned OpNum,
10570b57cec5SDimitry Andric                                      const MCSubtargetInfo &STI,
10580b57cec5SDimitry Andric                                      raw_ostream &O) {
10590b57cec5SDimitry Andric   O << "p" << MI->getOperand(OpNum).getImm();
10600b57cec5SDimitry Andric }
10610b57cec5SDimitry Andric 
printCImmediate(const MCInst * MI,unsigned OpNum,const MCSubtargetInfo & STI,raw_ostream & O)10620b57cec5SDimitry Andric void ARMInstPrinter::printCImmediate(const MCInst *MI, unsigned OpNum,
10630b57cec5SDimitry Andric                                      const MCSubtargetInfo &STI,
10640b57cec5SDimitry Andric                                      raw_ostream &O) {
10650b57cec5SDimitry Andric   O << "c" << MI->getOperand(OpNum).getImm();
10660b57cec5SDimitry Andric }
10670b57cec5SDimitry Andric 
printCoprocOptionImm(const MCInst * MI,unsigned OpNum,const MCSubtargetInfo & STI,raw_ostream & O)10680b57cec5SDimitry Andric void ARMInstPrinter::printCoprocOptionImm(const MCInst *MI, unsigned OpNum,
10690b57cec5SDimitry Andric                                           const MCSubtargetInfo &STI,
10700b57cec5SDimitry Andric                                           raw_ostream &O) {
10710b57cec5SDimitry Andric   O << "{" << MI->getOperand(OpNum).getImm() << "}";
10720b57cec5SDimitry Andric }
10730b57cec5SDimitry Andric 
printPCLabel(const MCInst * MI,unsigned OpNum,const MCSubtargetInfo & STI,raw_ostream & O)10740b57cec5SDimitry Andric void ARMInstPrinter::printPCLabel(const MCInst *MI, unsigned OpNum,
10750b57cec5SDimitry Andric                                   const MCSubtargetInfo &STI, raw_ostream &O) {
10760b57cec5SDimitry Andric   llvm_unreachable("Unhandled PC-relative pseudo-instruction!");
10770b57cec5SDimitry Andric }
10780b57cec5SDimitry Andric 
10790b57cec5SDimitry Andric template <unsigned scale>
printAdrLabelOperand(const MCInst * MI,unsigned OpNum,const MCSubtargetInfo & STI,raw_ostream & O)10800b57cec5SDimitry Andric void ARMInstPrinter::printAdrLabelOperand(const MCInst *MI, unsigned OpNum,
10810b57cec5SDimitry Andric                                           const MCSubtargetInfo &STI,
10820b57cec5SDimitry Andric                                           raw_ostream &O) {
10830b57cec5SDimitry Andric   const MCOperand &MO = MI->getOperand(OpNum);
10840b57cec5SDimitry Andric 
10850b57cec5SDimitry Andric   if (MO.isExpr()) {
10860b57cec5SDimitry Andric     MO.getExpr()->print(O, &MAI);
10870b57cec5SDimitry Andric     return;
10880b57cec5SDimitry Andric   }
10890b57cec5SDimitry Andric 
10900b57cec5SDimitry Andric   int32_t OffImm = (int32_t)MO.getImm() << scale;
10910b57cec5SDimitry Andric 
10925f757f3fSDimitry Andric   WithMarkup ScopedMarkup = markup(O, Markup::Immediate);
10930b57cec5SDimitry Andric   if (OffImm == INT32_MIN)
10940b57cec5SDimitry Andric     O << "#-0";
10950b57cec5SDimitry Andric   else if (OffImm < 0)
10960b57cec5SDimitry Andric     O << "#-" << -OffImm;
10970b57cec5SDimitry Andric   else
10980b57cec5SDimitry Andric     O << "#" << OffImm;
10990b57cec5SDimitry Andric }
11000b57cec5SDimitry Andric 
printThumbS4ImmOperand(const MCInst * MI,unsigned OpNum,const MCSubtargetInfo & STI,raw_ostream & O)11010b57cec5SDimitry Andric void ARMInstPrinter::printThumbS4ImmOperand(const MCInst *MI, unsigned OpNum,
11020b57cec5SDimitry Andric                                             const MCSubtargetInfo &STI,
11030b57cec5SDimitry Andric                                             raw_ostream &O) {
11045f757f3fSDimitry Andric   markup(O, Markup::Immediate)
11055f757f3fSDimitry Andric       << "#" << formatImm(MI->getOperand(OpNum).getImm() * 4);
11060b57cec5SDimitry Andric }
11070b57cec5SDimitry Andric 
printThumbSRImm(const MCInst * MI,unsigned OpNum,const MCSubtargetInfo & STI,raw_ostream & O)11080b57cec5SDimitry Andric void ARMInstPrinter::printThumbSRImm(const MCInst *MI, unsigned OpNum,
11090b57cec5SDimitry Andric                                      const MCSubtargetInfo &STI,
11100b57cec5SDimitry Andric                                      raw_ostream &O) {
11110b57cec5SDimitry Andric   unsigned Imm = MI->getOperand(OpNum).getImm();
11125f757f3fSDimitry Andric   markup(O, Markup::Immediate) << "#" << formatImm((Imm == 0 ? 32 : Imm));
11130b57cec5SDimitry Andric }
11140b57cec5SDimitry Andric 
printThumbITMask(const MCInst * MI,unsigned OpNum,const MCSubtargetInfo & STI,raw_ostream & O)11150b57cec5SDimitry Andric void ARMInstPrinter::printThumbITMask(const MCInst *MI, unsigned OpNum,
11160b57cec5SDimitry Andric                                       const MCSubtargetInfo &STI,
11170b57cec5SDimitry Andric                                       raw_ostream &O) {
11180b57cec5SDimitry Andric   // (3 - the number of trailing zeros) is the number of then / else.
11190b57cec5SDimitry Andric   unsigned Mask = MI->getOperand(OpNum).getImm();
112006c3fb27SDimitry Andric   unsigned NumTZ = llvm::countr_zero(Mask);
11210b57cec5SDimitry Andric   assert(NumTZ <= 3 && "Invalid IT mask!");
11220b57cec5SDimitry Andric   for (unsigned Pos = 3, e = NumTZ; Pos > e; --Pos) {
11230b57cec5SDimitry Andric     if ((Mask >> Pos) & 1)
11240b57cec5SDimitry Andric       O << 'e';
11250b57cec5SDimitry Andric     else
11260b57cec5SDimitry Andric       O << 't';
11270b57cec5SDimitry Andric   }
11280b57cec5SDimitry Andric }
11290b57cec5SDimitry Andric 
printThumbAddrModeRROperand(const MCInst * MI,unsigned Op,const MCSubtargetInfo & STI,raw_ostream & O)11300b57cec5SDimitry Andric void ARMInstPrinter::printThumbAddrModeRROperand(const MCInst *MI, unsigned Op,
11310b57cec5SDimitry Andric                                                  const MCSubtargetInfo &STI,
11320b57cec5SDimitry Andric                                                  raw_ostream &O) {
11330b57cec5SDimitry Andric   const MCOperand &MO1 = MI->getOperand(Op);
11340b57cec5SDimitry Andric   const MCOperand &MO2 = MI->getOperand(Op + 1);
11350b57cec5SDimitry Andric 
11360b57cec5SDimitry Andric   if (!MO1.isReg()) { // FIXME: This is for CP entries, but isn't right.
11370b57cec5SDimitry Andric     printOperand(MI, Op, STI, O);
11380b57cec5SDimitry Andric     return;
11390b57cec5SDimitry Andric   }
11400b57cec5SDimitry Andric 
11415f757f3fSDimitry Andric   WithMarkup ScopedMarkup = markup(O, Markup::Memory);
11425f757f3fSDimitry Andric   O << "[";
11430b57cec5SDimitry Andric   printRegName(O, MO1.getReg());
11440b57cec5SDimitry Andric   if (unsigned RegNum = MO2.getReg()) {
11450b57cec5SDimitry Andric     O << ", ";
11460b57cec5SDimitry Andric     printRegName(O, RegNum);
11470b57cec5SDimitry Andric   }
11485f757f3fSDimitry Andric   O << "]";
11490b57cec5SDimitry Andric }
11500b57cec5SDimitry Andric 
printThumbAddrModeImm5SOperand(const MCInst * MI,unsigned Op,const MCSubtargetInfo & STI,raw_ostream & O,unsigned Scale)11510b57cec5SDimitry Andric void ARMInstPrinter::printThumbAddrModeImm5SOperand(const MCInst *MI,
11520b57cec5SDimitry Andric                                                     unsigned Op,
11530b57cec5SDimitry Andric                                                     const MCSubtargetInfo &STI,
11540b57cec5SDimitry Andric                                                     raw_ostream &O,
11550b57cec5SDimitry Andric                                                     unsigned Scale) {
11560b57cec5SDimitry Andric   const MCOperand &MO1 = MI->getOperand(Op);
11570b57cec5SDimitry Andric   const MCOperand &MO2 = MI->getOperand(Op + 1);
11580b57cec5SDimitry Andric 
11590b57cec5SDimitry Andric   if (!MO1.isReg()) { // FIXME: This is for CP entries, but isn't right.
11600b57cec5SDimitry Andric     printOperand(MI, Op, STI, O);
11610b57cec5SDimitry Andric     return;
11620b57cec5SDimitry Andric   }
11630b57cec5SDimitry Andric 
11645f757f3fSDimitry Andric   WithMarkup ScopedMarkup = markup(O, Markup::Memory);
11655f757f3fSDimitry Andric   O << "[";
11660b57cec5SDimitry Andric   printRegName(O, MO1.getReg());
11670b57cec5SDimitry Andric   if (unsigned ImmOffs = MO2.getImm()) {
11685f757f3fSDimitry Andric     O << ", ";
11695f757f3fSDimitry Andric     markup(O, Markup::Immediate) << "#" << formatImm(ImmOffs * Scale);
11700b57cec5SDimitry Andric   }
11715f757f3fSDimitry Andric   O << "]";
11720b57cec5SDimitry Andric }
11730b57cec5SDimitry Andric 
printThumbAddrModeImm5S1Operand(const MCInst * MI,unsigned Op,const MCSubtargetInfo & STI,raw_ostream & O)11740b57cec5SDimitry Andric void ARMInstPrinter::printThumbAddrModeImm5S1Operand(const MCInst *MI,
11750b57cec5SDimitry Andric                                                      unsigned Op,
11760b57cec5SDimitry Andric                                                      const MCSubtargetInfo &STI,
11770b57cec5SDimitry Andric                                                      raw_ostream &O) {
11780b57cec5SDimitry Andric   printThumbAddrModeImm5SOperand(MI, Op, STI, O, 1);
11790b57cec5SDimitry Andric }
11800b57cec5SDimitry Andric 
printThumbAddrModeImm5S2Operand(const MCInst * MI,unsigned Op,const MCSubtargetInfo & STI,raw_ostream & O)11810b57cec5SDimitry Andric void ARMInstPrinter::printThumbAddrModeImm5S2Operand(const MCInst *MI,
11820b57cec5SDimitry Andric                                                      unsigned Op,
11830b57cec5SDimitry Andric                                                      const MCSubtargetInfo &STI,
11840b57cec5SDimitry Andric                                                      raw_ostream &O) {
11850b57cec5SDimitry Andric   printThumbAddrModeImm5SOperand(MI, Op, STI, O, 2);
11860b57cec5SDimitry Andric }
11870b57cec5SDimitry Andric 
printThumbAddrModeImm5S4Operand(const MCInst * MI,unsigned Op,const MCSubtargetInfo & STI,raw_ostream & O)11880b57cec5SDimitry Andric void ARMInstPrinter::printThumbAddrModeImm5S4Operand(const MCInst *MI,
11890b57cec5SDimitry Andric                                                      unsigned Op,
11900b57cec5SDimitry Andric                                                      const MCSubtargetInfo &STI,
11910b57cec5SDimitry Andric                                                      raw_ostream &O) {
11920b57cec5SDimitry Andric   printThumbAddrModeImm5SOperand(MI, Op, STI, O, 4);
11930b57cec5SDimitry Andric }
11940b57cec5SDimitry Andric 
printThumbAddrModeSPOperand(const MCInst * MI,unsigned Op,const MCSubtargetInfo & STI,raw_ostream & O)11950b57cec5SDimitry Andric void ARMInstPrinter::printThumbAddrModeSPOperand(const MCInst *MI, unsigned Op,
11960b57cec5SDimitry Andric                                                  const MCSubtargetInfo &STI,
11970b57cec5SDimitry Andric                                                  raw_ostream &O) {
11980b57cec5SDimitry Andric   printThumbAddrModeImm5SOperand(MI, Op, STI, O, 4);
11990b57cec5SDimitry Andric }
12000b57cec5SDimitry Andric 
12010b57cec5SDimitry Andric // Constant shifts t2_so_reg is a 2-operand unit corresponding to the Thumb2
12020b57cec5SDimitry Andric // register with shift forms.
12030b57cec5SDimitry Andric // REG 0   0           - e.g. R5
12040b57cec5SDimitry Andric // REG IMM, SH_OPC     - e.g. R5, LSL #3
printT2SOOperand(const MCInst * MI,unsigned OpNum,const MCSubtargetInfo & STI,raw_ostream & O)12050b57cec5SDimitry Andric void ARMInstPrinter::printT2SOOperand(const MCInst *MI, unsigned OpNum,
12060b57cec5SDimitry Andric                                       const MCSubtargetInfo &STI,
12070b57cec5SDimitry Andric                                       raw_ostream &O) {
12080b57cec5SDimitry Andric   const MCOperand &MO1 = MI->getOperand(OpNum);
12090b57cec5SDimitry Andric   const MCOperand &MO2 = MI->getOperand(OpNum + 1);
12100b57cec5SDimitry Andric 
12110b57cec5SDimitry Andric   unsigned Reg = MO1.getReg();
12120b57cec5SDimitry Andric   printRegName(O, Reg);
12130b57cec5SDimitry Andric 
12140b57cec5SDimitry Andric   // Print the shift opc.
12150b57cec5SDimitry Andric   assert(MO2.isImm() && "Not a valid t2_so_reg value!");
12160b57cec5SDimitry Andric   printRegImmShift(O, ARM_AM::getSORegShOp(MO2.getImm()),
12175f757f3fSDimitry Andric                    ARM_AM::getSORegOffset(MO2.getImm()), *this);
12180b57cec5SDimitry Andric }
12190b57cec5SDimitry Andric 
12200b57cec5SDimitry Andric template <bool AlwaysPrintImm0>
printAddrModeImm12Operand(const MCInst * MI,unsigned OpNum,const MCSubtargetInfo & STI,raw_ostream & O)12210b57cec5SDimitry Andric void ARMInstPrinter::printAddrModeImm12Operand(const MCInst *MI, unsigned OpNum,
12220b57cec5SDimitry Andric                                                const MCSubtargetInfo &STI,
12230b57cec5SDimitry Andric                                                raw_ostream &O) {
12240b57cec5SDimitry Andric   const MCOperand &MO1 = MI->getOperand(OpNum);
12250b57cec5SDimitry Andric   const MCOperand &MO2 = MI->getOperand(OpNum + 1);
12260b57cec5SDimitry Andric 
12270b57cec5SDimitry Andric   if (!MO1.isReg()) { // FIXME: This is for CP entries, but isn't right.
12280b57cec5SDimitry Andric     printOperand(MI, OpNum, STI, O);
12290b57cec5SDimitry Andric     return;
12300b57cec5SDimitry Andric   }
12310b57cec5SDimitry Andric 
12325f757f3fSDimitry Andric   WithMarkup ScopedMarkup = markup(O, Markup::Memory);
12335f757f3fSDimitry Andric   O << "[";
12340b57cec5SDimitry Andric   printRegName(O, MO1.getReg());
12350b57cec5SDimitry Andric 
12360b57cec5SDimitry Andric   int32_t OffImm = (int32_t)MO2.getImm();
12370b57cec5SDimitry Andric   bool isSub = OffImm < 0;
12380b57cec5SDimitry Andric   // Special value for #-0. All others are normal.
12390b57cec5SDimitry Andric   if (OffImm == INT32_MIN)
12400b57cec5SDimitry Andric     OffImm = 0;
12410b57cec5SDimitry Andric   if (isSub) {
12425f757f3fSDimitry Andric     O << ", ";
12435f757f3fSDimitry Andric     markup(O, Markup::Immediate) << "#-" << formatImm(-OffImm);
12440b57cec5SDimitry Andric   } else if (AlwaysPrintImm0 || OffImm > 0) {
12455f757f3fSDimitry Andric     O << ", ";
12465f757f3fSDimitry Andric     markup(O, Markup::Immediate) << "#" << formatImm(OffImm);
12470b57cec5SDimitry Andric   }
12485f757f3fSDimitry Andric   O << "]";
12490b57cec5SDimitry Andric }
12500b57cec5SDimitry Andric 
12510b57cec5SDimitry Andric template <bool AlwaysPrintImm0>
printT2AddrModeImm8Operand(const MCInst * MI,unsigned OpNum,const MCSubtargetInfo & STI,raw_ostream & O)12520b57cec5SDimitry Andric void ARMInstPrinter::printT2AddrModeImm8Operand(const MCInst *MI,
12530b57cec5SDimitry Andric                                                 unsigned OpNum,
12540b57cec5SDimitry Andric                                                 const MCSubtargetInfo &STI,
12550b57cec5SDimitry Andric                                                 raw_ostream &O) {
12560b57cec5SDimitry Andric   const MCOperand &MO1 = MI->getOperand(OpNum);
12570b57cec5SDimitry Andric   const MCOperand &MO2 = MI->getOperand(OpNum + 1);
12580b57cec5SDimitry Andric 
12595f757f3fSDimitry Andric   WithMarkup ScopedMarkup = markup(O, Markup::Memory);
12605f757f3fSDimitry Andric   O << "[";
12610b57cec5SDimitry Andric   printRegName(O, MO1.getReg());
12620b57cec5SDimitry Andric 
12630b57cec5SDimitry Andric   int32_t OffImm = (int32_t)MO2.getImm();
12640b57cec5SDimitry Andric   bool isSub = OffImm < 0;
12650b57cec5SDimitry Andric   // Don't print +0.
12660b57cec5SDimitry Andric   if (OffImm == INT32_MIN)
12670b57cec5SDimitry Andric     OffImm = 0;
12680b57cec5SDimitry Andric   if (isSub) {
12695f757f3fSDimitry Andric     O << ", ";
12705f757f3fSDimitry Andric     markup(O, Markup::Immediate) << "#-" << -OffImm;
12710b57cec5SDimitry Andric   } else if (AlwaysPrintImm0 || OffImm > 0) {
12725f757f3fSDimitry Andric     O << ", ";
12735f757f3fSDimitry Andric     markup(O, Markup::Immediate) << "#" << OffImm;
12740b57cec5SDimitry Andric   }
12755f757f3fSDimitry Andric   O << "]";
12760b57cec5SDimitry Andric }
12770b57cec5SDimitry Andric 
12780b57cec5SDimitry Andric template <bool AlwaysPrintImm0>
printT2AddrModeImm8s4Operand(const MCInst * MI,unsigned OpNum,const MCSubtargetInfo & STI,raw_ostream & O)12790b57cec5SDimitry Andric void ARMInstPrinter::printT2AddrModeImm8s4Operand(const MCInst *MI,
12800b57cec5SDimitry Andric                                                   unsigned OpNum,
12810b57cec5SDimitry Andric                                                   const MCSubtargetInfo &STI,
12820b57cec5SDimitry Andric                                                   raw_ostream &O) {
12830b57cec5SDimitry Andric   const MCOperand &MO1 = MI->getOperand(OpNum);
12840b57cec5SDimitry Andric   const MCOperand &MO2 = MI->getOperand(OpNum + 1);
12850b57cec5SDimitry Andric 
12860b57cec5SDimitry Andric   if (!MO1.isReg()) { //  For label symbolic references.
12870b57cec5SDimitry Andric     printOperand(MI, OpNum, STI, O);
12880b57cec5SDimitry Andric     return;
12890b57cec5SDimitry Andric   }
12900b57cec5SDimitry Andric 
12915f757f3fSDimitry Andric   WithMarkup ScopedMarkup = markup(O, Markup::Memory);
12925f757f3fSDimitry Andric   O << "[";
12930b57cec5SDimitry Andric   printRegName(O, MO1.getReg());
12940b57cec5SDimitry Andric 
12950b57cec5SDimitry Andric   int32_t OffImm = (int32_t)MO2.getImm();
12960b57cec5SDimitry Andric   bool isSub = OffImm < 0;
12970b57cec5SDimitry Andric 
12980b57cec5SDimitry Andric   assert(((OffImm & 0x3) == 0) && "Not a valid immediate!");
12990b57cec5SDimitry Andric 
13000b57cec5SDimitry Andric   // Don't print +0.
13010b57cec5SDimitry Andric   if (OffImm == INT32_MIN)
13020b57cec5SDimitry Andric     OffImm = 0;
13030b57cec5SDimitry Andric   if (isSub) {
13045f757f3fSDimitry Andric     O << ", ";
13055f757f3fSDimitry Andric     markup(O, Markup::Immediate) << "#-" << -OffImm;
13060b57cec5SDimitry Andric   } else if (AlwaysPrintImm0 || OffImm > 0) {
13075f757f3fSDimitry Andric     O << ", ";
13085f757f3fSDimitry Andric     markup(O, Markup::Immediate) << "#" << OffImm;
13090b57cec5SDimitry Andric   }
13105f757f3fSDimitry Andric   O << "]";
13110b57cec5SDimitry Andric }
13120b57cec5SDimitry Andric 
printT2AddrModeImm0_1020s4Operand(const MCInst * MI,unsigned OpNum,const MCSubtargetInfo & STI,raw_ostream & O)13130b57cec5SDimitry Andric void ARMInstPrinter::printT2AddrModeImm0_1020s4Operand(
13140b57cec5SDimitry Andric     const MCInst *MI, unsigned OpNum, const MCSubtargetInfo &STI,
13150b57cec5SDimitry Andric     raw_ostream &O) {
13160b57cec5SDimitry Andric   const MCOperand &MO1 = MI->getOperand(OpNum);
13170b57cec5SDimitry Andric   const MCOperand &MO2 = MI->getOperand(OpNum + 1);
13180b57cec5SDimitry Andric 
13195f757f3fSDimitry Andric   WithMarkup ScopedMarkup = markup(O, Markup::Memory);
13205f757f3fSDimitry Andric   O << "[";
13210b57cec5SDimitry Andric   printRegName(O, MO1.getReg());
13220b57cec5SDimitry Andric   if (MO2.getImm()) {
13235f757f3fSDimitry Andric     O << ", ";
13245f757f3fSDimitry Andric     markup(O, Markup::Immediate) << "#" << formatImm(MO2.getImm() * 4);
13250b57cec5SDimitry Andric   }
13265f757f3fSDimitry Andric   O << "]";
13270b57cec5SDimitry Andric }
13280b57cec5SDimitry Andric 
printT2AddrModeImm8OffsetOperand(const MCInst * MI,unsigned OpNum,const MCSubtargetInfo & STI,raw_ostream & O)13290b57cec5SDimitry Andric void ARMInstPrinter::printT2AddrModeImm8OffsetOperand(
13300b57cec5SDimitry Andric     const MCInst *MI, unsigned OpNum, const MCSubtargetInfo &STI,
13310b57cec5SDimitry Andric     raw_ostream &O) {
13320b57cec5SDimitry Andric   const MCOperand &MO1 = MI->getOperand(OpNum);
13330b57cec5SDimitry Andric   int32_t OffImm = (int32_t)MO1.getImm();
13345f757f3fSDimitry Andric   O << ", ";
13355f757f3fSDimitry Andric   WithMarkup ScopedMarkup = markup(O, Markup::Immediate);
13360b57cec5SDimitry Andric   if (OffImm == INT32_MIN)
13370b57cec5SDimitry Andric     O << "#-0";
13380b57cec5SDimitry Andric   else if (OffImm < 0)
13390b57cec5SDimitry Andric     O << "#-" << -OffImm;
13400b57cec5SDimitry Andric   else
13410b57cec5SDimitry Andric     O << "#" << OffImm;
13420b57cec5SDimitry Andric }
13430b57cec5SDimitry Andric 
printT2AddrModeImm8s4OffsetOperand(const MCInst * MI,unsigned OpNum,const MCSubtargetInfo & STI,raw_ostream & O)13440b57cec5SDimitry Andric void ARMInstPrinter::printT2AddrModeImm8s4OffsetOperand(
13450b57cec5SDimitry Andric     const MCInst *MI, unsigned OpNum, const MCSubtargetInfo &STI,
13460b57cec5SDimitry Andric     raw_ostream &O) {
13470b57cec5SDimitry Andric   const MCOperand &MO1 = MI->getOperand(OpNum);
13480b57cec5SDimitry Andric   int32_t OffImm = (int32_t)MO1.getImm();
13490b57cec5SDimitry Andric 
13500b57cec5SDimitry Andric   assert(((OffImm & 0x3) == 0) && "Not a valid immediate!");
13510b57cec5SDimitry Andric 
13525f757f3fSDimitry Andric   O << ", ";
13535f757f3fSDimitry Andric   WithMarkup ScopedMarkup = markup(O, Markup::Immediate);
13540b57cec5SDimitry Andric   if (OffImm == INT32_MIN)
13550b57cec5SDimitry Andric     O << "#-0";
13560b57cec5SDimitry Andric   else if (OffImm < 0)
13570b57cec5SDimitry Andric     O << "#-" << -OffImm;
13580b57cec5SDimitry Andric   else
13590b57cec5SDimitry Andric     O << "#" << OffImm;
13600b57cec5SDimitry Andric }
13610b57cec5SDimitry Andric 
printT2AddrModeSoRegOperand(const MCInst * MI,unsigned OpNum,const MCSubtargetInfo & STI,raw_ostream & O)13620b57cec5SDimitry Andric void ARMInstPrinter::printT2AddrModeSoRegOperand(const MCInst *MI,
13630b57cec5SDimitry Andric                                                  unsigned OpNum,
13640b57cec5SDimitry Andric                                                  const MCSubtargetInfo &STI,
13650b57cec5SDimitry Andric                                                  raw_ostream &O) {
13660b57cec5SDimitry Andric   const MCOperand &MO1 = MI->getOperand(OpNum);
13670b57cec5SDimitry Andric   const MCOperand &MO2 = MI->getOperand(OpNum + 1);
13680b57cec5SDimitry Andric   const MCOperand &MO3 = MI->getOperand(OpNum + 2);
13690b57cec5SDimitry Andric 
13705f757f3fSDimitry Andric   WithMarkup ScopedMarkup = markup(O, Markup::Memory);
13715f757f3fSDimitry Andric   O << "[";
13720b57cec5SDimitry Andric   printRegName(O, MO1.getReg());
13730b57cec5SDimitry Andric 
13740b57cec5SDimitry Andric   assert(MO2.getReg() && "Invalid so_reg load / store address!");
13750b57cec5SDimitry Andric   O << ", ";
13760b57cec5SDimitry Andric   printRegName(O, MO2.getReg());
13770b57cec5SDimitry Andric 
13780b57cec5SDimitry Andric   unsigned ShAmt = MO3.getImm();
13790b57cec5SDimitry Andric   if (ShAmt) {
13800b57cec5SDimitry Andric     assert(ShAmt <= 3 && "Not a valid Thumb2 addressing mode!");
13815f757f3fSDimitry Andric     O << ", lsl ";
13825f757f3fSDimitry Andric     markup(O, Markup::Immediate) << "#" << ShAmt;
13830b57cec5SDimitry Andric   }
13845f757f3fSDimitry Andric   O << "]";
13850b57cec5SDimitry Andric }
13860b57cec5SDimitry Andric 
printFPImmOperand(const MCInst * MI,unsigned OpNum,const MCSubtargetInfo & STI,raw_ostream & O)13870b57cec5SDimitry Andric void ARMInstPrinter::printFPImmOperand(const MCInst *MI, unsigned OpNum,
13880b57cec5SDimitry Andric                                        const MCSubtargetInfo &STI,
13890b57cec5SDimitry Andric                                        raw_ostream &O) {
13900b57cec5SDimitry Andric   const MCOperand &MO = MI->getOperand(OpNum);
13915f757f3fSDimitry Andric   markup(O, Markup::Immediate) << '#' << ARM_AM::getFPImmFloat(MO.getImm());
13920b57cec5SDimitry Andric }
13930b57cec5SDimitry Andric 
printVMOVModImmOperand(const MCInst * MI,unsigned OpNum,const MCSubtargetInfo & STI,raw_ostream & O)13948bcb0991SDimitry Andric void ARMInstPrinter::printVMOVModImmOperand(const MCInst *MI, unsigned OpNum,
13950b57cec5SDimitry Andric                                             const MCSubtargetInfo &STI,
13960b57cec5SDimitry Andric                                             raw_ostream &O) {
13970b57cec5SDimitry Andric   unsigned EncodedImm = MI->getOperand(OpNum).getImm();
13980b57cec5SDimitry Andric   unsigned EltBits;
13998bcb0991SDimitry Andric   uint64_t Val = ARM_AM::decodeVMOVModImm(EncodedImm, EltBits);
14005f757f3fSDimitry Andric 
14015f757f3fSDimitry Andric   WithMarkup ScopedMarkup = markup(O, Markup::Immediate);
14025f757f3fSDimitry Andric   O << "#0x";
14030b57cec5SDimitry Andric   O.write_hex(Val);
14040b57cec5SDimitry Andric }
14050b57cec5SDimitry Andric 
printImmPlusOneOperand(const MCInst * MI,unsigned OpNum,const MCSubtargetInfo & STI,raw_ostream & O)14060b57cec5SDimitry Andric void ARMInstPrinter::printImmPlusOneOperand(const MCInst *MI, unsigned OpNum,
14070b57cec5SDimitry Andric                                             const MCSubtargetInfo &STI,
14080b57cec5SDimitry Andric                                             raw_ostream &O) {
14090b57cec5SDimitry Andric   unsigned Imm = MI->getOperand(OpNum).getImm();
14105f757f3fSDimitry Andric   markup(O, Markup::Immediate) << "#" << formatImm(Imm + 1);
14110b57cec5SDimitry Andric }
14120b57cec5SDimitry Andric 
printRotImmOperand(const MCInst * MI,unsigned OpNum,const MCSubtargetInfo & STI,raw_ostream & O)14130b57cec5SDimitry Andric void ARMInstPrinter::printRotImmOperand(const MCInst *MI, unsigned OpNum,
14140b57cec5SDimitry Andric                                         const MCSubtargetInfo &STI,
14150b57cec5SDimitry Andric                                         raw_ostream &O) {
14160b57cec5SDimitry Andric   unsigned Imm = MI->getOperand(OpNum).getImm();
14170b57cec5SDimitry Andric   if (Imm == 0)
14180b57cec5SDimitry Andric     return;
14190b57cec5SDimitry Andric   assert(Imm <= 3 && "illegal ror immediate!");
14205f757f3fSDimitry Andric   O << ", ror ";
14215f757f3fSDimitry Andric   markup(O, Markup::Immediate) << "#" << 8 * Imm;
14220b57cec5SDimitry Andric }
14230b57cec5SDimitry Andric 
printModImmOperand(const MCInst * MI,unsigned OpNum,const MCSubtargetInfo & STI,raw_ostream & O)14240b57cec5SDimitry Andric void ARMInstPrinter::printModImmOperand(const MCInst *MI, unsigned OpNum,
14250b57cec5SDimitry Andric                                         const MCSubtargetInfo &STI,
14260b57cec5SDimitry Andric                                         raw_ostream &O) {
14270b57cec5SDimitry Andric   MCOperand Op = MI->getOperand(OpNum);
14280b57cec5SDimitry Andric 
14290b57cec5SDimitry Andric   // Support for fixups (MCFixup)
14300b57cec5SDimitry Andric   if (Op.isExpr())
14310b57cec5SDimitry Andric     return printOperand(MI, OpNum, STI, O);
14320b57cec5SDimitry Andric 
14330b57cec5SDimitry Andric   unsigned Bits = Op.getImm() & 0xFF;
14340b57cec5SDimitry Andric   unsigned Rot = (Op.getImm() & 0xF00) >> 7;
14350b57cec5SDimitry Andric 
14360b57cec5SDimitry Andric   bool PrintUnsigned = false;
14370b57cec5SDimitry Andric   switch (MI->getOpcode()) {
14380b57cec5SDimitry Andric   case ARM::MOVi:
14390b57cec5SDimitry Andric     // Movs to PC should be treated unsigned
14400b57cec5SDimitry Andric     PrintUnsigned = (MI->getOperand(OpNum - 1).getReg() == ARM::PC);
14410b57cec5SDimitry Andric     break;
14420b57cec5SDimitry Andric   case ARM::MSRi:
14430b57cec5SDimitry Andric     // Movs to special registers should be treated unsigned
14440b57cec5SDimitry Andric     PrintUnsigned = true;
14450b57cec5SDimitry Andric     break;
14460b57cec5SDimitry Andric   }
14470b57cec5SDimitry Andric 
144806c3fb27SDimitry Andric   int32_t Rotated = llvm::rotr<uint32_t>(Bits, Rot);
14490b57cec5SDimitry Andric   if (ARM_AM::getSOImmVal(Rotated) == Op.getImm()) {
14500b57cec5SDimitry Andric     // #rot has the least possible value
14515f757f3fSDimitry Andric     O << "#";
14520b57cec5SDimitry Andric     if (PrintUnsigned)
14535f757f3fSDimitry Andric       markup(O, Markup::Immediate) << static_cast<uint32_t>(Rotated);
14540b57cec5SDimitry Andric     else
14555f757f3fSDimitry Andric       markup(O, Markup::Immediate) << Rotated;
14560b57cec5SDimitry Andric     return;
14570b57cec5SDimitry Andric   }
14580b57cec5SDimitry Andric 
14590b57cec5SDimitry Andric   // Explicit #bits, #rot implied
14605f757f3fSDimitry Andric   O << "#";
14615f757f3fSDimitry Andric   markup(O, Markup::Immediate) << Bits;
14625f757f3fSDimitry Andric   O << ", #";
14635f757f3fSDimitry Andric   markup(O, Markup::Immediate) << Rot;
14640b57cec5SDimitry Andric }
14650b57cec5SDimitry Andric 
printFBits16(const MCInst * MI,unsigned OpNum,const MCSubtargetInfo & STI,raw_ostream & O)14660b57cec5SDimitry Andric void ARMInstPrinter::printFBits16(const MCInst *MI, unsigned OpNum,
14670b57cec5SDimitry Andric                                   const MCSubtargetInfo &STI, raw_ostream &O) {
14685f757f3fSDimitry Andric   markup(O, Markup::Immediate) << "#" << 16 - MI->getOperand(OpNum).getImm();
14690b57cec5SDimitry Andric }
14700b57cec5SDimitry Andric 
printFBits32(const MCInst * MI,unsigned OpNum,const MCSubtargetInfo & STI,raw_ostream & O)14710b57cec5SDimitry Andric void ARMInstPrinter::printFBits32(const MCInst *MI, unsigned OpNum,
14720b57cec5SDimitry Andric                                   const MCSubtargetInfo &STI, raw_ostream &O) {
14735f757f3fSDimitry Andric   markup(O, Markup::Immediate) << "#" << 32 - MI->getOperand(OpNum).getImm();
14740b57cec5SDimitry Andric }
14750b57cec5SDimitry Andric 
printVectorIndex(const MCInst * MI,unsigned OpNum,const MCSubtargetInfo & STI,raw_ostream & O)14760b57cec5SDimitry Andric void ARMInstPrinter::printVectorIndex(const MCInst *MI, unsigned OpNum,
14770b57cec5SDimitry Andric                                       const MCSubtargetInfo &STI,
14780b57cec5SDimitry Andric                                       raw_ostream &O) {
14790b57cec5SDimitry Andric   O << "[" << MI->getOperand(OpNum).getImm() << "]";
14800b57cec5SDimitry Andric }
14810b57cec5SDimitry Andric 
printVectorListOne(const MCInst * MI,unsigned OpNum,const MCSubtargetInfo & STI,raw_ostream & O)14820b57cec5SDimitry Andric void ARMInstPrinter::printVectorListOne(const MCInst *MI, unsigned OpNum,
14830b57cec5SDimitry Andric                                         const MCSubtargetInfo &STI,
14840b57cec5SDimitry Andric                                         raw_ostream &O) {
14850b57cec5SDimitry Andric   O << "{";
14860b57cec5SDimitry Andric   printRegName(O, MI->getOperand(OpNum).getReg());
14870b57cec5SDimitry Andric   O << "}";
14880b57cec5SDimitry Andric }
14890b57cec5SDimitry Andric 
printVectorListTwo(const MCInst * MI,unsigned OpNum,const MCSubtargetInfo & STI,raw_ostream & O)14900b57cec5SDimitry Andric void ARMInstPrinter::printVectorListTwo(const MCInst *MI, unsigned OpNum,
14910b57cec5SDimitry Andric                                         const MCSubtargetInfo &STI,
14920b57cec5SDimitry Andric                                         raw_ostream &O) {
14930b57cec5SDimitry Andric   unsigned Reg = MI->getOperand(OpNum).getReg();
14940b57cec5SDimitry Andric   unsigned Reg0 = MRI.getSubReg(Reg, ARM::dsub_0);
14950b57cec5SDimitry Andric   unsigned Reg1 = MRI.getSubReg(Reg, ARM::dsub_1);
14960b57cec5SDimitry Andric   O << "{";
14970b57cec5SDimitry Andric   printRegName(O, Reg0);
14980b57cec5SDimitry Andric   O << ", ";
14990b57cec5SDimitry Andric   printRegName(O, Reg1);
15000b57cec5SDimitry Andric   O << "}";
15010b57cec5SDimitry Andric }
15020b57cec5SDimitry Andric 
printVectorListTwoSpaced(const MCInst * MI,unsigned OpNum,const MCSubtargetInfo & STI,raw_ostream & O)15030b57cec5SDimitry Andric void ARMInstPrinter::printVectorListTwoSpaced(const MCInst *MI, unsigned OpNum,
15040b57cec5SDimitry Andric                                               const MCSubtargetInfo &STI,
15050b57cec5SDimitry Andric                                               raw_ostream &O) {
15060b57cec5SDimitry Andric   unsigned Reg = MI->getOperand(OpNum).getReg();
15070b57cec5SDimitry Andric   unsigned Reg0 = MRI.getSubReg(Reg, ARM::dsub_0);
15080b57cec5SDimitry Andric   unsigned Reg1 = MRI.getSubReg(Reg, ARM::dsub_2);
15090b57cec5SDimitry Andric   O << "{";
15100b57cec5SDimitry Andric   printRegName(O, Reg0);
15110b57cec5SDimitry Andric   O << ", ";
15120b57cec5SDimitry Andric   printRegName(O, Reg1);
15130b57cec5SDimitry Andric   O << "}";
15140b57cec5SDimitry Andric }
15150b57cec5SDimitry Andric 
printVectorListThree(const MCInst * MI,unsigned OpNum,const MCSubtargetInfo & STI,raw_ostream & O)15160b57cec5SDimitry Andric void ARMInstPrinter::printVectorListThree(const MCInst *MI, unsigned OpNum,
15170b57cec5SDimitry Andric                                           const MCSubtargetInfo &STI,
15180b57cec5SDimitry Andric                                           raw_ostream &O) {
15190b57cec5SDimitry Andric   // Normally, it's not safe to use register enum values directly with
15200b57cec5SDimitry Andric   // addition to get the next register, but for VFP registers, the
15210b57cec5SDimitry Andric   // sort order is guaranteed because they're all of the form D<n>.
15220b57cec5SDimitry Andric   O << "{";
15230b57cec5SDimitry Andric   printRegName(O, MI->getOperand(OpNum).getReg());
15240b57cec5SDimitry Andric   O << ", ";
15250b57cec5SDimitry Andric   printRegName(O, MI->getOperand(OpNum).getReg() + 1);
15260b57cec5SDimitry Andric   O << ", ";
15270b57cec5SDimitry Andric   printRegName(O, MI->getOperand(OpNum).getReg() + 2);
15280b57cec5SDimitry Andric   O << "}";
15290b57cec5SDimitry Andric }
15300b57cec5SDimitry Andric 
printVectorListFour(const MCInst * MI,unsigned OpNum,const MCSubtargetInfo & STI,raw_ostream & O)15310b57cec5SDimitry Andric void ARMInstPrinter::printVectorListFour(const MCInst *MI, unsigned OpNum,
15320b57cec5SDimitry Andric                                          const MCSubtargetInfo &STI,
15330b57cec5SDimitry Andric                                          raw_ostream &O) {
15340b57cec5SDimitry Andric   // Normally, it's not safe to use register enum values directly with
15350b57cec5SDimitry Andric   // addition to get the next register, but for VFP registers, the
15360b57cec5SDimitry Andric   // sort order is guaranteed because they're all of the form D<n>.
15370b57cec5SDimitry Andric   O << "{";
15380b57cec5SDimitry Andric   printRegName(O, MI->getOperand(OpNum).getReg());
15390b57cec5SDimitry Andric   O << ", ";
15400b57cec5SDimitry Andric   printRegName(O, MI->getOperand(OpNum).getReg() + 1);
15410b57cec5SDimitry Andric   O << ", ";
15420b57cec5SDimitry Andric   printRegName(O, MI->getOperand(OpNum).getReg() + 2);
15430b57cec5SDimitry Andric   O << ", ";
15440b57cec5SDimitry Andric   printRegName(O, MI->getOperand(OpNum).getReg() + 3);
15450b57cec5SDimitry Andric   O << "}";
15460b57cec5SDimitry Andric }
15470b57cec5SDimitry Andric 
printVectorListOneAllLanes(const MCInst * MI,unsigned OpNum,const MCSubtargetInfo & STI,raw_ostream & O)15480b57cec5SDimitry Andric void ARMInstPrinter::printVectorListOneAllLanes(const MCInst *MI,
15490b57cec5SDimitry Andric                                                 unsigned OpNum,
15500b57cec5SDimitry Andric                                                 const MCSubtargetInfo &STI,
15510b57cec5SDimitry Andric                                                 raw_ostream &O) {
15520b57cec5SDimitry Andric   O << "{";
15530b57cec5SDimitry Andric   printRegName(O, MI->getOperand(OpNum).getReg());
15540b57cec5SDimitry Andric   O << "[]}";
15550b57cec5SDimitry Andric }
15560b57cec5SDimitry Andric 
printVectorListTwoAllLanes(const MCInst * MI,unsigned OpNum,const MCSubtargetInfo & STI,raw_ostream & O)15570b57cec5SDimitry Andric void ARMInstPrinter::printVectorListTwoAllLanes(const MCInst *MI,
15580b57cec5SDimitry Andric                                                 unsigned OpNum,
15590b57cec5SDimitry Andric                                                 const MCSubtargetInfo &STI,
15600b57cec5SDimitry Andric                                                 raw_ostream &O) {
15610b57cec5SDimitry Andric   unsigned Reg = MI->getOperand(OpNum).getReg();
15620b57cec5SDimitry Andric   unsigned Reg0 = MRI.getSubReg(Reg, ARM::dsub_0);
15630b57cec5SDimitry Andric   unsigned Reg1 = MRI.getSubReg(Reg, ARM::dsub_1);
15640b57cec5SDimitry Andric   O << "{";
15650b57cec5SDimitry Andric   printRegName(O, Reg0);
15660b57cec5SDimitry Andric   O << "[], ";
15670b57cec5SDimitry Andric   printRegName(O, Reg1);
15680b57cec5SDimitry Andric   O << "[]}";
15690b57cec5SDimitry Andric }
15700b57cec5SDimitry Andric 
printVectorListThreeAllLanes(const MCInst * MI,unsigned OpNum,const MCSubtargetInfo & STI,raw_ostream & O)15710b57cec5SDimitry Andric void ARMInstPrinter::printVectorListThreeAllLanes(const MCInst *MI,
15720b57cec5SDimitry Andric                                                   unsigned OpNum,
15730b57cec5SDimitry Andric                                                   const MCSubtargetInfo &STI,
15740b57cec5SDimitry Andric                                                   raw_ostream &O) {
15750b57cec5SDimitry Andric   // Normally, it's not safe to use register enum values directly with
15760b57cec5SDimitry Andric   // addition to get the next register, but for VFP registers, the
15770b57cec5SDimitry Andric   // sort order is guaranteed because they're all of the form D<n>.
15780b57cec5SDimitry Andric   O << "{";
15790b57cec5SDimitry Andric   printRegName(O, MI->getOperand(OpNum).getReg());
15800b57cec5SDimitry Andric   O << "[], ";
15810b57cec5SDimitry Andric   printRegName(O, MI->getOperand(OpNum).getReg() + 1);
15820b57cec5SDimitry Andric   O << "[], ";
15830b57cec5SDimitry Andric   printRegName(O, MI->getOperand(OpNum).getReg() + 2);
15840b57cec5SDimitry Andric   O << "[]}";
15850b57cec5SDimitry Andric }
15860b57cec5SDimitry Andric 
printVectorListFourAllLanes(const MCInst * MI,unsigned OpNum,const MCSubtargetInfo & STI,raw_ostream & O)15870b57cec5SDimitry Andric void ARMInstPrinter::printVectorListFourAllLanes(const MCInst *MI,
15880b57cec5SDimitry Andric                                                  unsigned OpNum,
15890b57cec5SDimitry Andric                                                  const MCSubtargetInfo &STI,
15900b57cec5SDimitry Andric                                                  raw_ostream &O) {
15910b57cec5SDimitry Andric   // Normally, it's not safe to use register enum values directly with
15920b57cec5SDimitry Andric   // addition to get the next register, but for VFP registers, the
15930b57cec5SDimitry Andric   // sort order is guaranteed because they're all of the form D<n>.
15940b57cec5SDimitry Andric   O << "{";
15950b57cec5SDimitry Andric   printRegName(O, MI->getOperand(OpNum).getReg());
15960b57cec5SDimitry Andric   O << "[], ";
15970b57cec5SDimitry Andric   printRegName(O, MI->getOperand(OpNum).getReg() + 1);
15980b57cec5SDimitry Andric   O << "[], ";
15990b57cec5SDimitry Andric   printRegName(O, MI->getOperand(OpNum).getReg() + 2);
16000b57cec5SDimitry Andric   O << "[], ";
16010b57cec5SDimitry Andric   printRegName(O, MI->getOperand(OpNum).getReg() + 3);
16020b57cec5SDimitry Andric   O << "[]}";
16030b57cec5SDimitry Andric }
16040b57cec5SDimitry Andric 
printVectorListTwoSpacedAllLanes(const MCInst * MI,unsigned OpNum,const MCSubtargetInfo & STI,raw_ostream & O)16050b57cec5SDimitry Andric void ARMInstPrinter::printVectorListTwoSpacedAllLanes(
16060b57cec5SDimitry Andric     const MCInst *MI, unsigned OpNum, const MCSubtargetInfo &STI,
16070b57cec5SDimitry Andric     raw_ostream &O) {
16080b57cec5SDimitry Andric   unsigned Reg = MI->getOperand(OpNum).getReg();
16090b57cec5SDimitry Andric   unsigned Reg0 = MRI.getSubReg(Reg, ARM::dsub_0);
16100b57cec5SDimitry Andric   unsigned Reg1 = MRI.getSubReg(Reg, ARM::dsub_2);
16110b57cec5SDimitry Andric   O << "{";
16120b57cec5SDimitry Andric   printRegName(O, Reg0);
16130b57cec5SDimitry Andric   O << "[], ";
16140b57cec5SDimitry Andric   printRegName(O, Reg1);
16150b57cec5SDimitry Andric   O << "[]}";
16160b57cec5SDimitry Andric }
16170b57cec5SDimitry Andric 
printVectorListThreeSpacedAllLanes(const MCInst * MI,unsigned OpNum,const MCSubtargetInfo & STI,raw_ostream & O)16180b57cec5SDimitry Andric void ARMInstPrinter::printVectorListThreeSpacedAllLanes(
16190b57cec5SDimitry Andric     const MCInst *MI, unsigned OpNum, const MCSubtargetInfo &STI,
16200b57cec5SDimitry Andric     raw_ostream &O) {
16210b57cec5SDimitry Andric   // Normally, it's not safe to use register enum values directly with
16220b57cec5SDimitry Andric   // addition to get the next register, but for VFP registers, the
16230b57cec5SDimitry Andric   // sort order is guaranteed because they're all of the form D<n>.
16240b57cec5SDimitry Andric   O << "{";
16250b57cec5SDimitry Andric   printRegName(O, MI->getOperand(OpNum).getReg());
16260b57cec5SDimitry Andric   O << "[], ";
16270b57cec5SDimitry Andric   printRegName(O, MI->getOperand(OpNum).getReg() + 2);
16280b57cec5SDimitry Andric   O << "[], ";
16290b57cec5SDimitry Andric   printRegName(O, MI->getOperand(OpNum).getReg() + 4);
16300b57cec5SDimitry Andric   O << "[]}";
16310b57cec5SDimitry Andric }
16320b57cec5SDimitry Andric 
printVectorListFourSpacedAllLanes(const MCInst * MI,unsigned OpNum,const MCSubtargetInfo & STI,raw_ostream & O)16330b57cec5SDimitry Andric void ARMInstPrinter::printVectorListFourSpacedAllLanes(
16340b57cec5SDimitry Andric     const MCInst *MI, unsigned OpNum, const MCSubtargetInfo &STI,
16350b57cec5SDimitry Andric     raw_ostream &O) {
16360b57cec5SDimitry Andric   // Normally, it's not safe to use register enum values directly with
16370b57cec5SDimitry Andric   // addition to get the next register, but for VFP registers, the
16380b57cec5SDimitry Andric   // sort order is guaranteed because they're all of the form D<n>.
16390b57cec5SDimitry Andric   O << "{";
16400b57cec5SDimitry Andric   printRegName(O, MI->getOperand(OpNum).getReg());
16410b57cec5SDimitry Andric   O << "[], ";
16420b57cec5SDimitry Andric   printRegName(O, MI->getOperand(OpNum).getReg() + 2);
16430b57cec5SDimitry Andric   O << "[], ";
16440b57cec5SDimitry Andric   printRegName(O, MI->getOperand(OpNum).getReg() + 4);
16450b57cec5SDimitry Andric   O << "[], ";
16460b57cec5SDimitry Andric   printRegName(O, MI->getOperand(OpNum).getReg() + 6);
16470b57cec5SDimitry Andric   O << "[]}";
16480b57cec5SDimitry Andric }
16490b57cec5SDimitry Andric 
printVectorListThreeSpaced(const MCInst * MI,unsigned OpNum,const MCSubtargetInfo & STI,raw_ostream & O)16500b57cec5SDimitry Andric void ARMInstPrinter::printVectorListThreeSpaced(const MCInst *MI,
16510b57cec5SDimitry Andric                                                 unsigned OpNum,
16520b57cec5SDimitry Andric                                                 const MCSubtargetInfo &STI,
16530b57cec5SDimitry Andric                                                 raw_ostream &O) {
16540b57cec5SDimitry Andric   // Normally, it's not safe to use register enum values directly with
16550b57cec5SDimitry Andric   // addition to get the next register, but for VFP registers, the
16560b57cec5SDimitry Andric   // sort order is guaranteed because they're all of the form D<n>.
16570b57cec5SDimitry Andric   O << "{";
16580b57cec5SDimitry Andric   printRegName(O, MI->getOperand(OpNum).getReg());
16590b57cec5SDimitry Andric   O << ", ";
16600b57cec5SDimitry Andric   printRegName(O, MI->getOperand(OpNum).getReg() + 2);
16610b57cec5SDimitry Andric   O << ", ";
16620b57cec5SDimitry Andric   printRegName(O, MI->getOperand(OpNum).getReg() + 4);
16630b57cec5SDimitry Andric   O << "}";
16640b57cec5SDimitry Andric }
16650b57cec5SDimitry Andric 
printVectorListFourSpaced(const MCInst * MI,unsigned OpNum,const MCSubtargetInfo & STI,raw_ostream & O)16660b57cec5SDimitry Andric void ARMInstPrinter::printVectorListFourSpaced(const MCInst *MI, unsigned OpNum,
16670b57cec5SDimitry Andric                                                const MCSubtargetInfo &STI,
16680b57cec5SDimitry Andric                                                raw_ostream &O) {
16690b57cec5SDimitry Andric   // Normally, it's not safe to use register enum values directly with
16700b57cec5SDimitry Andric   // addition to get the next register, but for VFP registers, the
16710b57cec5SDimitry Andric   // sort order is guaranteed because they're all of the form D<n>.
16720b57cec5SDimitry Andric   O << "{";
16730b57cec5SDimitry Andric   printRegName(O, MI->getOperand(OpNum).getReg());
16740b57cec5SDimitry Andric   O << ", ";
16750b57cec5SDimitry Andric   printRegName(O, MI->getOperand(OpNum).getReg() + 2);
16760b57cec5SDimitry Andric   O << ", ";
16770b57cec5SDimitry Andric   printRegName(O, MI->getOperand(OpNum).getReg() + 4);
16780b57cec5SDimitry Andric   O << ", ";
16790b57cec5SDimitry Andric   printRegName(O, MI->getOperand(OpNum).getReg() + 6);
16800b57cec5SDimitry Andric   O << "}";
16810b57cec5SDimitry Andric }
16820b57cec5SDimitry Andric 
16830b57cec5SDimitry Andric template<unsigned NumRegs>
printMVEVectorList(const MCInst * MI,unsigned OpNum,const MCSubtargetInfo & STI,raw_ostream & O)16840b57cec5SDimitry Andric void ARMInstPrinter::printMVEVectorList(const MCInst *MI, unsigned OpNum,
16850b57cec5SDimitry Andric                                         const MCSubtargetInfo &STI,
16860b57cec5SDimitry Andric                                         raw_ostream &O) {
16870b57cec5SDimitry Andric   unsigned Reg = MI->getOperand(OpNum).getReg();
16880b57cec5SDimitry Andric   const char *Prefix = "{";
16890b57cec5SDimitry Andric   for (unsigned i = 0; i < NumRegs; i++) {
16900b57cec5SDimitry Andric     O << Prefix;
16910b57cec5SDimitry Andric     printRegName(O, MRI.getSubReg(Reg, ARM::qsub_0 + i));
16920b57cec5SDimitry Andric     Prefix = ", ";
16930b57cec5SDimitry Andric   }
16940b57cec5SDimitry Andric   O << "}";
16950b57cec5SDimitry Andric }
16960b57cec5SDimitry Andric 
16970b57cec5SDimitry Andric template<int64_t Angle, int64_t Remainder>
printComplexRotationOp(const MCInst * MI,unsigned OpNo,const MCSubtargetInfo & STI,raw_ostream & O)16980b57cec5SDimitry Andric void ARMInstPrinter::printComplexRotationOp(const MCInst *MI, unsigned OpNo,
16990b57cec5SDimitry Andric                                             const MCSubtargetInfo &STI,
17000b57cec5SDimitry Andric                                             raw_ostream &O) {
17010b57cec5SDimitry Andric   unsigned Val = MI->getOperand(OpNo).getImm();
17020b57cec5SDimitry Andric   O << "#" << (Val * Angle) + Remainder;
17030b57cec5SDimitry Andric }
17040b57cec5SDimitry Andric 
printVPTPredicateOperand(const MCInst * MI,unsigned OpNum,const MCSubtargetInfo & STI,raw_ostream & O)17050b57cec5SDimitry Andric void ARMInstPrinter::printVPTPredicateOperand(const MCInst *MI, unsigned OpNum,
17060b57cec5SDimitry Andric                                               const MCSubtargetInfo &STI,
17070b57cec5SDimitry Andric                                               raw_ostream &O) {
17080b57cec5SDimitry Andric   ARMVCC::VPTCodes CC = (ARMVCC::VPTCodes)MI->getOperand(OpNum).getImm();
17090b57cec5SDimitry Andric   if (CC != ARMVCC::None)
17100b57cec5SDimitry Andric     O << ARMVPTPredToString(CC);
17110b57cec5SDimitry Andric }
17120b57cec5SDimitry Andric 
printVPTMask(const MCInst * MI,unsigned OpNum,const MCSubtargetInfo & STI,raw_ostream & O)17130b57cec5SDimitry Andric void ARMInstPrinter::printVPTMask(const MCInst *MI, unsigned OpNum,
17140b57cec5SDimitry Andric                                   const MCSubtargetInfo &STI,
17150b57cec5SDimitry Andric                                   raw_ostream &O) {
17160b57cec5SDimitry Andric   // (3 - the number of trailing zeroes) is the number of them / else.
17170b57cec5SDimitry Andric   unsigned Mask = MI->getOperand(OpNum).getImm();
171806c3fb27SDimitry Andric   unsigned NumTZ = llvm::countr_zero(Mask);
17190b57cec5SDimitry Andric   assert(NumTZ <= 3 && "Invalid VPT mask!");
17200b57cec5SDimitry Andric   for (unsigned Pos = 3, e = NumTZ; Pos > e; --Pos) {
17210b57cec5SDimitry Andric     bool T = ((Mask >> Pos) & 1) == 0;
17220b57cec5SDimitry Andric     if (T)
17230b57cec5SDimitry Andric       O << 't';
17240b57cec5SDimitry Andric     else
17250b57cec5SDimitry Andric       O << 'e';
17260b57cec5SDimitry Andric   }
17270b57cec5SDimitry Andric }
17280b57cec5SDimitry Andric 
printMveSaturateOp(const MCInst * MI,unsigned OpNum,const MCSubtargetInfo & STI,raw_ostream & O)17298bcb0991SDimitry Andric void ARMInstPrinter::printMveSaturateOp(const MCInst *MI, unsigned OpNum,
17308bcb0991SDimitry Andric                                         const MCSubtargetInfo &STI,
17318bcb0991SDimitry Andric                                         raw_ostream &O) {
17328bcb0991SDimitry Andric   uint32_t Val = MI->getOperand(OpNum).getImm();
17338bcb0991SDimitry Andric   assert(Val <= 1 && "Invalid MVE saturate operand");
17348bcb0991SDimitry Andric   O << "#" << (Val == 1 ? 48 : 64);
17358bcb0991SDimitry Andric }
1736