15e3ee4b8SRichard Trieu //===-- ARMInstPrinter.cpp - Convert ARM MCInst to assembly syntax --------===//
25e3ee4b8SRichard Trieu //
35e3ee4b8SRichard Trieu // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
45e3ee4b8SRichard Trieu // See https://llvm.org/LICENSE.txt for license information.
55e3ee4b8SRichard Trieu // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
65e3ee4b8SRichard Trieu //
75e3ee4b8SRichard Trieu //===----------------------------------------------------------------------===//
85e3ee4b8SRichard Trieu //
95e3ee4b8SRichard Trieu // This class prints an ARM MCInst to a .s file.
105e3ee4b8SRichard Trieu //
115e3ee4b8SRichard Trieu //===----------------------------------------------------------------------===//
125e3ee4b8SRichard Trieu 
135e3ee4b8SRichard Trieu #include "ARMInstPrinter.h"
145e3ee4b8SRichard Trieu #include "Utils/ARMBaseInfo.h"
155e3ee4b8SRichard Trieu #include "MCTargetDesc/ARMAddressingModes.h"
165e3ee4b8SRichard Trieu #include "MCTargetDesc/ARMBaseInfo.h"
175e3ee4b8SRichard Trieu #include "llvm/MC/MCAsmInfo.h"
185e3ee4b8SRichard Trieu #include "llvm/MC/MCExpr.h"
195e3ee4b8SRichard Trieu #include "llvm/MC/MCInst.h"
20*657e067bSIgor Kudrin #include "llvm/MC/MCInstrAnalysis.h"
215e3ee4b8SRichard Trieu #include "llvm/MC/MCInstrInfo.h"
225e3ee4b8SRichard Trieu #include "llvm/MC/MCRegisterInfo.h"
235e3ee4b8SRichard Trieu #include "llvm/MC/MCSubtargetInfo.h"
245e3ee4b8SRichard Trieu #include "llvm/MC/SubtargetFeature.h"
255e3ee4b8SRichard Trieu #include "llvm/Support/Casting.h"
265e3ee4b8SRichard Trieu #include "llvm/Support/ErrorHandling.h"
275e3ee4b8SRichard Trieu #include "llvm/Support/MathExtras.h"
285e3ee4b8SRichard Trieu #include "llvm/Support/raw_ostream.h"
295e3ee4b8SRichard Trieu #include <algorithm>
305e3ee4b8SRichard Trieu #include <cassert>
315e3ee4b8SRichard Trieu #include <cstdint>
325e3ee4b8SRichard Trieu 
335e3ee4b8SRichard Trieu using namespace llvm;
345e3ee4b8SRichard Trieu 
355e3ee4b8SRichard Trieu #define DEBUG_TYPE "asm-printer"
365e3ee4b8SRichard Trieu 
375e3ee4b8SRichard Trieu #define PRINT_ALIAS_INSTR
385e3ee4b8SRichard Trieu #include "ARMGenAsmWriter.inc"
395e3ee4b8SRichard Trieu 
405e3ee4b8SRichard Trieu /// translateShiftImm - Convert shift immediate from 0-31 to 1-32 for printing.
415e3ee4b8SRichard Trieu ///
425e3ee4b8SRichard Trieu /// getSORegOffset returns an integer from 0-31, representing '32' as 0.
translateShiftImm(unsigned imm)435e3ee4b8SRichard Trieu static unsigned translateShiftImm(unsigned imm) {
445e3ee4b8SRichard Trieu   // lsr #32 and asr #32 exist, but should be encoded as a 0.
455e3ee4b8SRichard Trieu   assert((imm & ~0x1f) == 0 && "Invalid shift encoding");
465e3ee4b8SRichard Trieu 
475e3ee4b8SRichard Trieu   if (imm == 0)
485e3ee4b8SRichard Trieu     return 32;
495e3ee4b8SRichard Trieu   return imm;
505e3ee4b8SRichard Trieu }
515e3ee4b8SRichard Trieu 
525e3ee4b8SRichard Trieu /// Prints the shift value with an immediate value.
printRegImmShift(raw_ostream & O,ARM_AM::ShiftOpc ShOpc,unsigned ShImm,bool UseMarkup)535e3ee4b8SRichard Trieu static void printRegImmShift(raw_ostream &O, ARM_AM::ShiftOpc ShOpc,
545e3ee4b8SRichard Trieu                              unsigned ShImm, bool UseMarkup) {
555e3ee4b8SRichard Trieu   if (ShOpc == ARM_AM::no_shift || (ShOpc == ARM_AM::lsl && !ShImm))
565e3ee4b8SRichard Trieu     return;
575e3ee4b8SRichard Trieu   O << ", ";
585e3ee4b8SRichard Trieu 
595e3ee4b8SRichard Trieu   assert(!(ShOpc == ARM_AM::ror && !ShImm) && "Cannot have ror #0");
605e3ee4b8SRichard Trieu   O << getShiftOpcStr(ShOpc);
615e3ee4b8SRichard Trieu 
625e3ee4b8SRichard Trieu   if (ShOpc != ARM_AM::rrx) {
635e3ee4b8SRichard Trieu     O << " ";
645e3ee4b8SRichard Trieu     if (UseMarkup)
655e3ee4b8SRichard Trieu       O << "<imm:";
665e3ee4b8SRichard Trieu     O << "#" << translateShiftImm(ShImm);
675e3ee4b8SRichard Trieu     if (UseMarkup)
685e3ee4b8SRichard Trieu       O << ">";
695e3ee4b8SRichard Trieu   }
705e3ee4b8SRichard Trieu }
715e3ee4b8SRichard Trieu 
ARMInstPrinter(const MCAsmInfo & MAI,const MCInstrInfo & MII,const MCRegisterInfo & MRI)725e3ee4b8SRichard Trieu ARMInstPrinter::ARMInstPrinter(const MCAsmInfo &MAI, const MCInstrInfo &MII,
735e3ee4b8SRichard Trieu                                const MCRegisterInfo &MRI)
745e3ee4b8SRichard Trieu     : MCInstPrinter(MAI, MII, MRI) {}
755e3ee4b8SRichard Trieu 
applyTargetSpecificCLOption(StringRef Opt)765e3ee4b8SRichard Trieu bool ARMInstPrinter::applyTargetSpecificCLOption(StringRef Opt) {
775e3ee4b8SRichard Trieu   if (Opt == "reg-names-std") {
785e3ee4b8SRichard Trieu     DefaultAltIdx = ARM::NoRegAltName;
795e3ee4b8SRichard Trieu     return true;
805e3ee4b8SRichard Trieu   }
815e3ee4b8SRichard Trieu   if (Opt == "reg-names-raw") {
825e3ee4b8SRichard Trieu     DefaultAltIdx = ARM::RegNamesRaw;
835e3ee4b8SRichard Trieu     return true;
845e3ee4b8SRichard Trieu   }
855e3ee4b8SRichard Trieu   return false;
865e3ee4b8SRichard Trieu }
875e3ee4b8SRichard Trieu 
printRegName(raw_ostream & OS,unsigned RegNo) const885e3ee4b8SRichard Trieu void ARMInstPrinter::printRegName(raw_ostream &OS, unsigned RegNo) const {
895e3ee4b8SRichard Trieu   OS << markup("<reg:") << getRegisterName(RegNo, DefaultAltIdx) << markup(">");
905e3ee4b8SRichard Trieu }
915e3ee4b8SRichard Trieu 
printInst(const MCInst * MI,uint64_t Address,StringRef Annot,const MCSubtargetInfo & STI,raw_ostream & O)92aa708763SFangrui Song void ARMInstPrinter::printInst(const MCInst *MI, uint64_t Address,
93aa708763SFangrui Song                                StringRef Annot, const MCSubtargetInfo &STI,
94aa708763SFangrui Song                                raw_ostream &O) {
955e3ee4b8SRichard Trieu   unsigned Opcode = MI->getOpcode();
965e3ee4b8SRichard Trieu 
975e3ee4b8SRichard Trieu   switch (Opcode) {
985e3ee4b8SRichard Trieu   // Check for MOVs and print canonical forms, instead.
995e3ee4b8SRichard Trieu   case ARM::MOVsr: {
1005e3ee4b8SRichard Trieu     // FIXME: Thumb variants?
1015e3ee4b8SRichard Trieu     const MCOperand &Dst = MI->getOperand(0);
1025e3ee4b8SRichard Trieu     const MCOperand &MO1 = MI->getOperand(1);
1035e3ee4b8SRichard Trieu     const MCOperand &MO2 = MI->getOperand(2);
1045e3ee4b8SRichard Trieu     const MCOperand &MO3 = MI->getOperand(3);
1055e3ee4b8SRichard Trieu 
1065e3ee4b8SRichard Trieu     O << '\t' << ARM_AM::getShiftOpcStr(ARM_AM::getSORegShOp(MO3.getImm()));
1075e3ee4b8SRichard Trieu     printSBitModifierOperand(MI, 6, STI, O);
1085e3ee4b8SRichard Trieu     printPredicateOperand(MI, 4, STI, O);
1095e3ee4b8SRichard Trieu 
1105e3ee4b8SRichard Trieu     O << '\t';
1115e3ee4b8SRichard Trieu     printRegName(O, Dst.getReg());
1125e3ee4b8SRichard Trieu     O << ", ";
1135e3ee4b8SRichard Trieu     printRegName(O, MO1.getReg());
1145e3ee4b8SRichard Trieu 
1155e3ee4b8SRichard Trieu     O << ", ";
1165e3ee4b8SRichard Trieu     printRegName(O, MO2.getReg());
1175e3ee4b8SRichard Trieu     assert(ARM_AM::getSORegOffset(MO3.getImm()) == 0);
1185e3ee4b8SRichard Trieu     printAnnotation(O, Annot);
1195e3ee4b8SRichard Trieu     return;
1205e3ee4b8SRichard Trieu   }
1215e3ee4b8SRichard Trieu 
1225e3ee4b8SRichard Trieu   case ARM::MOVsi: {
1235e3ee4b8SRichard Trieu     // FIXME: Thumb variants?
1245e3ee4b8SRichard Trieu     const MCOperand &Dst = MI->getOperand(0);
1255e3ee4b8SRichard Trieu     const MCOperand &MO1 = MI->getOperand(1);
1265e3ee4b8SRichard Trieu     const MCOperand &MO2 = MI->getOperand(2);
1275e3ee4b8SRichard Trieu 
1285e3ee4b8SRichard Trieu     O << '\t' << ARM_AM::getShiftOpcStr(ARM_AM::getSORegShOp(MO2.getImm()));
1295e3ee4b8SRichard Trieu     printSBitModifierOperand(MI, 5, STI, O);
1305e3ee4b8SRichard Trieu     printPredicateOperand(MI, 3, STI, O);
1315e3ee4b8SRichard Trieu 
1325e3ee4b8SRichard Trieu     O << '\t';
1335e3ee4b8SRichard Trieu     printRegName(O, Dst.getReg());
1345e3ee4b8SRichard Trieu     O << ", ";
1355e3ee4b8SRichard Trieu     printRegName(O, MO1.getReg());
1365e3ee4b8SRichard Trieu 
1375e3ee4b8SRichard Trieu     if (ARM_AM::getSORegShOp(MO2.getImm()) == ARM_AM::rrx) {
1385e3ee4b8SRichard Trieu       printAnnotation(O, Annot);
1395e3ee4b8SRichard Trieu       return;
1405e3ee4b8SRichard Trieu     }
1415e3ee4b8SRichard Trieu 
1425e3ee4b8SRichard Trieu     O << ", " << markup("<imm:") << "#"
1435e3ee4b8SRichard Trieu       << translateShiftImm(ARM_AM::getSORegOffset(MO2.getImm())) << markup(">");
1445e3ee4b8SRichard Trieu     printAnnotation(O, Annot);
1455e3ee4b8SRichard Trieu     return;
1465e3ee4b8SRichard Trieu   }
1475e3ee4b8SRichard Trieu 
1485e3ee4b8SRichard Trieu   // A8.6.123 PUSH
1495e3ee4b8SRichard Trieu   case ARM::STMDB_UPD:
1505e3ee4b8SRichard Trieu   case ARM::t2STMDB_UPD:
1515e3ee4b8SRichard Trieu     if (MI->getOperand(0).getReg() == ARM::SP && MI->getNumOperands() > 5) {
1525e3ee4b8SRichard Trieu       // Should only print PUSH if there are at least two registers in the list.
1535e3ee4b8SRichard Trieu       O << '\t' << "push";
1545e3ee4b8SRichard Trieu       printPredicateOperand(MI, 2, STI, O);
1555e3ee4b8SRichard Trieu       if (Opcode == ARM::t2STMDB_UPD)
1565e3ee4b8SRichard Trieu         O << ".w";
1575e3ee4b8SRichard Trieu       O << '\t';
1585e3ee4b8SRichard Trieu       printRegisterList(MI, 4, STI, O);
1595e3ee4b8SRichard Trieu       printAnnotation(O, Annot);
1605e3ee4b8SRichard Trieu       return;
1615e3ee4b8SRichard Trieu     } else
1625e3ee4b8SRichard Trieu       break;
1635e3ee4b8SRichard Trieu 
1645e3ee4b8SRichard Trieu   case ARM::STR_PRE_IMM:
1655e3ee4b8SRichard Trieu     if (MI->getOperand(2).getReg() == ARM::SP &&
1665e3ee4b8SRichard Trieu         MI->getOperand(3).getImm() == -4) {
1675e3ee4b8SRichard Trieu       O << '\t' << "push";
1685e3ee4b8SRichard Trieu       printPredicateOperand(MI, 4, STI, O);
1695e3ee4b8SRichard Trieu       O << "\t{";
1705e3ee4b8SRichard Trieu       printRegName(O, MI->getOperand(1).getReg());
1715e3ee4b8SRichard Trieu       O << "}";
1725e3ee4b8SRichard Trieu       printAnnotation(O, Annot);
1735e3ee4b8SRichard Trieu       return;
1745e3ee4b8SRichard Trieu     } else
1755e3ee4b8SRichard Trieu       break;
1765e3ee4b8SRichard Trieu 
1775e3ee4b8SRichard Trieu   // A8.6.122 POP
1785e3ee4b8SRichard Trieu   case ARM::LDMIA_UPD:
1795e3ee4b8SRichard Trieu   case ARM::t2LDMIA_UPD:
1805e3ee4b8SRichard Trieu     if (MI->getOperand(0).getReg() == ARM::SP && MI->getNumOperands() > 5) {
1815e3ee4b8SRichard Trieu       // Should only print POP if there are at least two registers in the list.
1825e3ee4b8SRichard Trieu       O << '\t' << "pop";
1835e3ee4b8SRichard Trieu       printPredicateOperand(MI, 2, STI, O);
1845e3ee4b8SRichard Trieu       if (Opcode == ARM::t2LDMIA_UPD)
1855e3ee4b8SRichard Trieu         O << ".w";
1865e3ee4b8SRichard Trieu       O << '\t';
1875e3ee4b8SRichard Trieu       printRegisterList(MI, 4, STI, O);
1885e3ee4b8SRichard Trieu       printAnnotation(O, Annot);
1895e3ee4b8SRichard Trieu       return;
1905e3ee4b8SRichard Trieu     } else
1915e3ee4b8SRichard Trieu       break;
1925e3ee4b8SRichard Trieu 
1935e3ee4b8SRichard Trieu   case ARM::LDR_POST_IMM:
1945e3ee4b8SRichard Trieu     if (MI->getOperand(2).getReg() == ARM::SP &&
1955e3ee4b8SRichard Trieu         MI->getOperand(4).getImm() == 4) {
1965e3ee4b8SRichard Trieu       O << '\t' << "pop";
1975e3ee4b8SRichard Trieu       printPredicateOperand(MI, 5, STI, O);
1985e3ee4b8SRichard Trieu       O << "\t{";
1995e3ee4b8SRichard Trieu       printRegName(O, MI->getOperand(0).getReg());
2005e3ee4b8SRichard Trieu       O << "}";
2015e3ee4b8SRichard Trieu       printAnnotation(O, Annot);
2025e3ee4b8SRichard Trieu       return;
2035e3ee4b8SRichard Trieu     } else
2045e3ee4b8SRichard Trieu       break;
2055e3ee4b8SRichard Trieu 
2065e3ee4b8SRichard Trieu   // A8.6.355 VPUSH
2075e3ee4b8SRichard Trieu   case ARM::VSTMSDB_UPD:
2085e3ee4b8SRichard Trieu   case ARM::VSTMDDB_UPD:
2095e3ee4b8SRichard Trieu     if (MI->getOperand(0).getReg() == ARM::SP) {
2105e3ee4b8SRichard Trieu       O << '\t' << "vpush";
2115e3ee4b8SRichard Trieu       printPredicateOperand(MI, 2, STI, O);
2125e3ee4b8SRichard Trieu       O << '\t';
2135e3ee4b8SRichard Trieu       printRegisterList(MI, 4, STI, O);
2145e3ee4b8SRichard Trieu       printAnnotation(O, Annot);
2155e3ee4b8SRichard Trieu       return;
2165e3ee4b8SRichard Trieu     } else
2175e3ee4b8SRichard Trieu       break;
2185e3ee4b8SRichard Trieu 
2195e3ee4b8SRichard Trieu   // A8.6.354 VPOP
2205e3ee4b8SRichard Trieu   case ARM::VLDMSIA_UPD:
2215e3ee4b8SRichard Trieu   case ARM::VLDMDIA_UPD:
2225e3ee4b8SRichard Trieu     if (MI->getOperand(0).getReg() == ARM::SP) {
2235e3ee4b8SRichard Trieu       O << '\t' << "vpop";
2245e3ee4b8SRichard Trieu       printPredicateOperand(MI, 2, STI, O);
2255e3ee4b8SRichard Trieu       O << '\t';
2265e3ee4b8SRichard Trieu       printRegisterList(MI, 4, STI, O);
2275e3ee4b8SRichard Trieu       printAnnotation(O, Annot);
2285e3ee4b8SRichard Trieu       return;
2295e3ee4b8SRichard Trieu     } else
2305e3ee4b8SRichard Trieu       break;
2315e3ee4b8SRichard Trieu 
2325e3ee4b8SRichard Trieu   case ARM::tLDMIA: {
2335e3ee4b8SRichard Trieu     bool Writeback = true;
2345e3ee4b8SRichard Trieu     unsigned BaseReg = MI->getOperand(0).getReg();
2355e3ee4b8SRichard Trieu     for (unsigned i = 3; i < MI->getNumOperands(); ++i) {
2365e3ee4b8SRichard Trieu       if (MI->getOperand(i).getReg() == BaseReg)
2375e3ee4b8SRichard Trieu         Writeback = false;
2385e3ee4b8SRichard Trieu     }
2395e3ee4b8SRichard Trieu 
2405e3ee4b8SRichard Trieu     O << "\tldm";
2415e3ee4b8SRichard Trieu 
2425e3ee4b8SRichard Trieu     printPredicateOperand(MI, 1, STI, O);
2435e3ee4b8SRichard Trieu     O << '\t';
2445e3ee4b8SRichard Trieu     printRegName(O, BaseReg);
2455e3ee4b8SRichard Trieu     if (Writeback)
2465e3ee4b8SRichard Trieu       O << "!";
2475e3ee4b8SRichard Trieu     O << ", ";
2485e3ee4b8SRichard Trieu     printRegisterList(MI, 3, STI, O);
2495e3ee4b8SRichard Trieu     printAnnotation(O, Annot);
2505e3ee4b8SRichard Trieu     return;
2515e3ee4b8SRichard Trieu   }
2525e3ee4b8SRichard Trieu 
2535e3ee4b8SRichard Trieu   // Combine 2 GPRs from disassember into a GPRPair to match with instr def.
2545e3ee4b8SRichard Trieu   // ldrexd/strexd require even/odd GPR pair. To enforce this constraint,
2555e3ee4b8SRichard Trieu   // a single GPRPair reg operand is used in the .td file to replace the two
2565e3ee4b8SRichard Trieu   // GPRs. However, when decoding them, the two GRPs cannot be automatically
2575e3ee4b8SRichard Trieu   // expressed as a GPRPair, so we have to manually merge them.
2585e3ee4b8SRichard Trieu   // FIXME: We would really like to be able to tablegen'erate this.
2595e3ee4b8SRichard Trieu   case ARM::LDREXD:
2605e3ee4b8SRichard Trieu   case ARM::STREXD:
2615e3ee4b8SRichard Trieu   case ARM::LDAEXD:
2625e3ee4b8SRichard Trieu   case ARM::STLEXD: {
2635e3ee4b8SRichard Trieu     const MCRegisterClass &MRC = MRI.getRegClass(ARM::GPRRegClassID);
2645e3ee4b8SRichard Trieu     bool isStore = Opcode == ARM::STREXD || Opcode == ARM::STLEXD;
2655e3ee4b8SRichard Trieu     unsigned Reg = MI->getOperand(isStore ? 1 : 0).getReg();
2665e3ee4b8SRichard Trieu     if (MRC.contains(Reg)) {
2675e3ee4b8SRichard Trieu       MCInst NewMI;
2685e3ee4b8SRichard Trieu       MCOperand NewReg;
2695e3ee4b8SRichard Trieu       NewMI.setOpcode(Opcode);
2705e3ee4b8SRichard Trieu 
2715e3ee4b8SRichard Trieu       if (isStore)
2725e3ee4b8SRichard Trieu         NewMI.addOperand(MI->getOperand(0));
2735e3ee4b8SRichard Trieu       NewReg = MCOperand::createReg(MRI.getMatchingSuperReg(
2745e3ee4b8SRichard Trieu           Reg, ARM::gsub_0, &MRI.getRegClass(ARM::GPRPairRegClassID)));
2755e3ee4b8SRichard Trieu       NewMI.addOperand(NewReg);
2765e3ee4b8SRichard Trieu 
2775e3ee4b8SRichard Trieu       // Copy the rest operands into NewMI.
2785e3ee4b8SRichard Trieu       for (unsigned i = isStore ? 3 : 2; i < MI->getNumOperands(); ++i)
2795e3ee4b8SRichard Trieu         NewMI.addOperand(MI->getOperand(i));
2803d87d0b9SFangrui Song       printInstruction(&NewMI, Address, STI, O);
2815e3ee4b8SRichard Trieu       return;
2825e3ee4b8SRichard Trieu     }
2835e3ee4b8SRichard Trieu     break;
2845e3ee4b8SRichard Trieu   }
2855e3ee4b8SRichard Trieu   case ARM::TSB:
2865e3ee4b8SRichard Trieu   case ARM::t2TSB:
2875e3ee4b8SRichard Trieu     O << "\ttsb\tcsync";
2885e3ee4b8SRichard Trieu     return;
2895e3ee4b8SRichard Trieu   case ARM::t2DSB:
2905e3ee4b8SRichard Trieu     switch (MI->getOperand(0).getImm()) {
2915e3ee4b8SRichard Trieu     default:
292b3cc5dceSFangrui Song       if (!printAliasInstr(MI, Address, STI, O))
2933d87d0b9SFangrui Song         printInstruction(MI, Address, STI, O);
2945e3ee4b8SRichard Trieu       break;
2955e3ee4b8SRichard Trieu     case 0:
2965e3ee4b8SRichard Trieu       O << "\tssbb";
2975e3ee4b8SRichard Trieu       break;
2985e3ee4b8SRichard Trieu     case 4:
2995e3ee4b8SRichard Trieu       O << "\tpssbb";
3005e3ee4b8SRichard Trieu       break;
3015e3ee4b8SRichard Trieu     }
3025e3ee4b8SRichard Trieu     printAnnotation(O, Annot);
3035e3ee4b8SRichard Trieu     return;
3045e3ee4b8SRichard Trieu   }
3055e3ee4b8SRichard Trieu 
306b3cc5dceSFangrui Song   if (!printAliasInstr(MI, Address, STI, O))
3073d87d0b9SFangrui Song     printInstruction(MI, Address, STI, O);
3085e3ee4b8SRichard Trieu 
3095e3ee4b8SRichard Trieu   printAnnotation(O, Annot);
3105e3ee4b8SRichard Trieu }
3115e3ee4b8SRichard Trieu 
printOperand(const MCInst * MI,unsigned OpNo,const MCSubtargetInfo & STI,raw_ostream & O)3125e3ee4b8SRichard Trieu void ARMInstPrinter::printOperand(const MCInst *MI, unsigned OpNo,
3135e3ee4b8SRichard Trieu                                   const MCSubtargetInfo &STI, raw_ostream &O) {
3145e3ee4b8SRichard Trieu   const MCOperand &Op = MI->getOperand(OpNo);
3155e3ee4b8SRichard Trieu   if (Op.isReg()) {
3165e3ee4b8SRichard Trieu     unsigned Reg = Op.getReg();
3175e3ee4b8SRichard Trieu     printRegName(O, Reg);
3185e3ee4b8SRichard Trieu   } else if (Op.isImm()) {
3195e3ee4b8SRichard Trieu     O << markup("<imm:") << '#' << formatImm(Op.getImm()) << markup(">");
3205e3ee4b8SRichard Trieu   } else {
3215e3ee4b8SRichard Trieu     assert(Op.isExpr() && "unknown operand kind in printOperand");
3225e3ee4b8SRichard Trieu     const MCExpr *Expr = Op.getExpr();
3235e3ee4b8SRichard Trieu     switch (Expr->getKind()) {
3245e3ee4b8SRichard Trieu     case MCExpr::Binary:
3255e3ee4b8SRichard Trieu       O << '#';
3265e3ee4b8SRichard Trieu       Expr->print(O, &MAI);
3275e3ee4b8SRichard Trieu       break;
3285e3ee4b8SRichard Trieu     case MCExpr::Constant: {
3295e3ee4b8SRichard Trieu       // If a symbolic branch target was added as a constant expression then
3305e3ee4b8SRichard Trieu       // print that address in hex. And only print 32 unsigned bits for the
3315e3ee4b8SRichard Trieu       // address.
3325e3ee4b8SRichard Trieu       const MCConstantExpr *Constant = cast<MCConstantExpr>(Expr);
3335e3ee4b8SRichard Trieu       int64_t TargetAddress;
3345e3ee4b8SRichard Trieu       if (!Constant->evaluateAsAbsolute(TargetAddress)) {
3355e3ee4b8SRichard Trieu         O << '#';
3365e3ee4b8SRichard Trieu         Expr->print(O, &MAI);
3375e3ee4b8SRichard Trieu       } else {
3385e3ee4b8SRichard Trieu         O << "0x";
3395e3ee4b8SRichard Trieu         O.write_hex(static_cast<uint32_t>(TargetAddress));
3405e3ee4b8SRichard Trieu       }
3415e3ee4b8SRichard Trieu       break;
3425e3ee4b8SRichard Trieu     }
3435e3ee4b8SRichard Trieu     default:
3445e3ee4b8SRichard Trieu       // FIXME: Should we always treat this as if it is a constant literal and
3455e3ee4b8SRichard Trieu       // prefix it with '#'?
3465e3ee4b8SRichard Trieu       Expr->print(O, &MAI);
3475e3ee4b8SRichard Trieu       break;
3485e3ee4b8SRichard Trieu     }
3495e3ee4b8SRichard Trieu   }
3505e3ee4b8SRichard Trieu }
3515e3ee4b8SRichard Trieu 
printOperand(const MCInst * MI,uint64_t Address,unsigned OpNum,const MCSubtargetInfo & STI,raw_ostream & O)352*657e067bSIgor Kudrin void ARMInstPrinter::printOperand(const MCInst *MI, uint64_t Address,
353*657e067bSIgor Kudrin                                   unsigned OpNum, const MCSubtargetInfo &STI,
354*657e067bSIgor Kudrin                                   raw_ostream &O) {
355*657e067bSIgor Kudrin   const MCOperand &Op = MI->getOperand(OpNum);
356*657e067bSIgor Kudrin   if (!Op.isImm() || !PrintBranchImmAsAddress || getUseMarkup())
357*657e067bSIgor Kudrin     return printOperand(MI, OpNum, STI, O);
358*657e067bSIgor Kudrin   uint64_t Target = ARM_MC::evaluateBranchTarget(MII.get(MI->getOpcode()),
359*657e067bSIgor Kudrin                                                  Address, Op.getImm());
360*657e067bSIgor Kudrin   Target &= 0xffffffff;
361*657e067bSIgor Kudrin   O << formatHex(Target);
362*657e067bSIgor Kudrin   if (CommentStream)
363*657e067bSIgor Kudrin     *CommentStream << "imm = #" << formatImm(Op.getImm()) << '\n';
364*657e067bSIgor Kudrin }
365*657e067bSIgor Kudrin 
printThumbLdrLabelOperand(const MCInst * MI,unsigned OpNum,const MCSubtargetInfo & STI,raw_ostream & O)3665e3ee4b8SRichard Trieu void ARMInstPrinter::printThumbLdrLabelOperand(const MCInst *MI, unsigned OpNum,
3675e3ee4b8SRichard Trieu                                                const MCSubtargetInfo &STI,
3685e3ee4b8SRichard Trieu                                                raw_ostream &O) {
3695e3ee4b8SRichard Trieu   const MCOperand &MO1 = MI->getOperand(OpNum);
3705e3ee4b8SRichard Trieu   if (MO1.isExpr()) {
3715e3ee4b8SRichard Trieu     MO1.getExpr()->print(O, &MAI);
3725e3ee4b8SRichard Trieu     return;
3735e3ee4b8SRichard Trieu   }
3745e3ee4b8SRichard Trieu 
3755e3ee4b8SRichard Trieu   O << markup("<mem:") << "[pc, ";
3765e3ee4b8SRichard Trieu 
3775e3ee4b8SRichard Trieu   int32_t OffImm = (int32_t)MO1.getImm();
3785e3ee4b8SRichard Trieu   bool isSub = OffImm < 0;
3795e3ee4b8SRichard Trieu 
3805e3ee4b8SRichard Trieu   // Special value for #-0. All others are normal.
3815e3ee4b8SRichard Trieu   if (OffImm == INT32_MIN)
3825e3ee4b8SRichard Trieu     OffImm = 0;
3835e3ee4b8SRichard Trieu   if (isSub) {
3845e3ee4b8SRichard Trieu     O << markup("<imm:") << "#-" << formatImm(-OffImm) << markup(">");
3855e3ee4b8SRichard Trieu   } else {
3865e3ee4b8SRichard Trieu     O << markup("<imm:") << "#" << formatImm(OffImm) << markup(">");
3875e3ee4b8SRichard Trieu   }
3885e3ee4b8SRichard Trieu   O << "]" << markup(">");
3895e3ee4b8SRichard Trieu }
3905e3ee4b8SRichard Trieu 
3915e3ee4b8SRichard Trieu // so_reg is a 4-operand unit corresponding to register forms of the A5.1
3925e3ee4b8SRichard Trieu // "Addressing Mode 1 - Data-processing operands" forms.  This includes:
3935e3ee4b8SRichard Trieu //    REG 0   0           - e.g. R5
3945e3ee4b8SRichard Trieu //    REG REG 0,SH_OPC    - e.g. R5, ROR R3
3955e3ee4b8SRichard Trieu //    REG 0   IMM,SH_OPC  - e.g. R5, LSL #3
printSORegRegOperand(const MCInst * MI,unsigned OpNum,const MCSubtargetInfo & STI,raw_ostream & O)3965e3ee4b8SRichard Trieu void ARMInstPrinter::printSORegRegOperand(const MCInst *MI, unsigned OpNum,
3975e3ee4b8SRichard Trieu                                           const MCSubtargetInfo &STI,
3985e3ee4b8SRichard Trieu                                           raw_ostream &O) {
3995e3ee4b8SRichard Trieu   const MCOperand &MO1 = MI->getOperand(OpNum);
4005e3ee4b8SRichard Trieu   const MCOperand &MO2 = MI->getOperand(OpNum + 1);
4015e3ee4b8SRichard Trieu   const MCOperand &MO3 = MI->getOperand(OpNum + 2);
4025e3ee4b8SRichard Trieu 
4035e3ee4b8SRichard Trieu   printRegName(O, MO1.getReg());
4045e3ee4b8SRichard Trieu 
4055e3ee4b8SRichard Trieu   // Print the shift opc.
4065e3ee4b8SRichard Trieu   ARM_AM::ShiftOpc ShOpc = ARM_AM::getSORegShOp(MO3.getImm());
4075e3ee4b8SRichard Trieu   O << ", " << ARM_AM::getShiftOpcStr(ShOpc);
4085e3ee4b8SRichard Trieu   if (ShOpc == ARM_AM::rrx)
4095e3ee4b8SRichard Trieu     return;
4105e3ee4b8SRichard Trieu 
4115e3ee4b8SRichard Trieu   O << ' ';
4125e3ee4b8SRichard Trieu   printRegName(O, MO2.getReg());
4135e3ee4b8SRichard Trieu   assert(ARM_AM::getSORegOffset(MO3.getImm()) == 0);
4145e3ee4b8SRichard Trieu }
4155e3ee4b8SRichard Trieu 
printSORegImmOperand(const MCInst * MI,unsigned OpNum,const MCSubtargetInfo & STI,raw_ostream & O)4165e3ee4b8SRichard Trieu void ARMInstPrinter::printSORegImmOperand(const MCInst *MI, unsigned OpNum,
4175e3ee4b8SRichard Trieu                                           const MCSubtargetInfo &STI,
4185e3ee4b8SRichard Trieu                                           raw_ostream &O) {
4195e3ee4b8SRichard Trieu   const MCOperand &MO1 = MI->getOperand(OpNum);
4205e3ee4b8SRichard Trieu   const MCOperand &MO2 = MI->getOperand(OpNum + 1);
4215e3ee4b8SRichard Trieu 
4225e3ee4b8SRichard Trieu   printRegName(O, MO1.getReg());
4235e3ee4b8SRichard Trieu 
4245e3ee4b8SRichard Trieu   // Print the shift opc.
4255e3ee4b8SRichard Trieu   printRegImmShift(O, ARM_AM::getSORegShOp(MO2.getImm()),
4265e3ee4b8SRichard Trieu                    ARM_AM::getSORegOffset(MO2.getImm()), UseMarkup);
4275e3ee4b8SRichard Trieu }
4285e3ee4b8SRichard Trieu 
4295e3ee4b8SRichard Trieu //===--------------------------------------------------------------------===//
4305e3ee4b8SRichard Trieu // Addressing Mode #2
4315e3ee4b8SRichard Trieu //===--------------------------------------------------------------------===//
4325e3ee4b8SRichard Trieu 
printAM2PreOrOffsetIndexOp(const MCInst * MI,unsigned Op,const MCSubtargetInfo & STI,raw_ostream & O)4335e3ee4b8SRichard Trieu void ARMInstPrinter::printAM2PreOrOffsetIndexOp(const MCInst *MI, unsigned Op,
4345e3ee4b8SRichard Trieu                                                 const MCSubtargetInfo &STI,
4355e3ee4b8SRichard Trieu                                                 raw_ostream &O) {
4365e3ee4b8SRichard Trieu   const MCOperand &MO1 = MI->getOperand(Op);
4375e3ee4b8SRichard Trieu   const MCOperand &MO2 = MI->getOperand(Op + 1);
4385e3ee4b8SRichard Trieu   const MCOperand &MO3 = MI->getOperand(Op + 2);
4395e3ee4b8SRichard Trieu 
4405e3ee4b8SRichard Trieu   O << markup("<mem:") << "[";
4415e3ee4b8SRichard Trieu   printRegName(O, MO1.getReg());
4425e3ee4b8SRichard Trieu 
4435e3ee4b8SRichard Trieu   if (!MO2.getReg()) {
4445e3ee4b8SRichard Trieu     if (ARM_AM::getAM2Offset(MO3.getImm())) { // Don't print +0.
4455e3ee4b8SRichard Trieu       O << ", " << markup("<imm:") << "#"
4465e3ee4b8SRichard Trieu         << ARM_AM::getAddrOpcStr(ARM_AM::getAM2Op(MO3.getImm()))
4475e3ee4b8SRichard Trieu         << ARM_AM::getAM2Offset(MO3.getImm()) << markup(">");
4485e3ee4b8SRichard Trieu     }
4495e3ee4b8SRichard Trieu     O << "]" << markup(">");
4505e3ee4b8SRichard Trieu     return;
4515e3ee4b8SRichard Trieu   }
4525e3ee4b8SRichard Trieu 
4535e3ee4b8SRichard Trieu   O << ", ";
4545e3ee4b8SRichard Trieu   O << ARM_AM::getAddrOpcStr(ARM_AM::getAM2Op(MO3.getImm()));
4555e3ee4b8SRichard Trieu   printRegName(O, MO2.getReg());
4565e3ee4b8SRichard Trieu 
4575e3ee4b8SRichard Trieu   printRegImmShift(O, ARM_AM::getAM2ShiftOpc(MO3.getImm()),
4585e3ee4b8SRichard Trieu                    ARM_AM::getAM2Offset(MO3.getImm()), UseMarkup);
4595e3ee4b8SRichard Trieu   O << "]" << markup(">");
4605e3ee4b8SRichard Trieu }
4615e3ee4b8SRichard Trieu 
printAddrModeTBB(const MCInst * MI,unsigned Op,const MCSubtargetInfo & STI,raw_ostream & O)4625e3ee4b8SRichard Trieu void ARMInstPrinter::printAddrModeTBB(const MCInst *MI, unsigned Op,
4635e3ee4b8SRichard Trieu                                       const MCSubtargetInfo &STI,
4645e3ee4b8SRichard Trieu                                       raw_ostream &O) {
4655e3ee4b8SRichard Trieu   const MCOperand &MO1 = MI->getOperand(Op);
4665e3ee4b8SRichard Trieu   const MCOperand &MO2 = MI->getOperand(Op + 1);
4675e3ee4b8SRichard Trieu   O << markup("<mem:") << "[";
4685e3ee4b8SRichard Trieu   printRegName(O, MO1.getReg());
4695e3ee4b8SRichard Trieu   O << ", ";
4705e3ee4b8SRichard Trieu   printRegName(O, MO2.getReg());
4715e3ee4b8SRichard Trieu   O << "]" << markup(">");
4725e3ee4b8SRichard Trieu }
4735e3ee4b8SRichard Trieu 
printAddrModeTBH(const MCInst * MI,unsigned Op,const MCSubtargetInfo & STI,raw_ostream & O)4745e3ee4b8SRichard Trieu void ARMInstPrinter::printAddrModeTBH(const MCInst *MI, unsigned Op,
4755e3ee4b8SRichard Trieu                                       const MCSubtargetInfo &STI,
4765e3ee4b8SRichard Trieu                                       raw_ostream &O) {
4775e3ee4b8SRichard Trieu   const MCOperand &MO1 = MI->getOperand(Op);
4785e3ee4b8SRichard Trieu   const MCOperand &MO2 = MI->getOperand(Op + 1);
4795e3ee4b8SRichard Trieu   O << markup("<mem:") << "[";
4805e3ee4b8SRichard Trieu   printRegName(O, MO1.getReg());
4815e3ee4b8SRichard Trieu   O << ", ";
4825e3ee4b8SRichard Trieu   printRegName(O, MO2.getReg());
4835e3ee4b8SRichard Trieu   O << ", lsl " << markup("<imm:") << "#1" << markup(">") << "]" << markup(">");
4845e3ee4b8SRichard Trieu }
4855e3ee4b8SRichard Trieu 
printAddrMode2Operand(const MCInst * MI,unsigned Op,const MCSubtargetInfo & STI,raw_ostream & O)4865e3ee4b8SRichard Trieu void ARMInstPrinter::printAddrMode2Operand(const MCInst *MI, unsigned Op,
4875e3ee4b8SRichard Trieu                                            const MCSubtargetInfo &STI,
4885e3ee4b8SRichard Trieu                                            raw_ostream &O) {
4895e3ee4b8SRichard Trieu   const MCOperand &MO1 = MI->getOperand(Op);
4905e3ee4b8SRichard Trieu 
4915e3ee4b8SRichard Trieu   if (!MO1.isReg()) { // FIXME: This is for CP entries, but isn't right.
4925e3ee4b8SRichard Trieu     printOperand(MI, Op, STI, O);
4935e3ee4b8SRichard Trieu     return;
4945e3ee4b8SRichard Trieu   }
4955e3ee4b8SRichard Trieu 
4965e3ee4b8SRichard Trieu #ifndef NDEBUG
4975e3ee4b8SRichard Trieu   const MCOperand &MO3 = MI->getOperand(Op + 2);
4985e3ee4b8SRichard Trieu   unsigned IdxMode = ARM_AM::getAM2IdxMode(MO3.getImm());
4995e3ee4b8SRichard Trieu   assert(IdxMode != ARMII::IndexModePost && "Should be pre or offset index op");
5005e3ee4b8SRichard Trieu #endif
5015e3ee4b8SRichard Trieu 
5025e3ee4b8SRichard Trieu   printAM2PreOrOffsetIndexOp(MI, Op, STI, O);
5035e3ee4b8SRichard Trieu }
5045e3ee4b8SRichard Trieu 
printAddrMode2OffsetOperand(const MCInst * MI,unsigned OpNum,const MCSubtargetInfo & STI,raw_ostream & O)5055e3ee4b8SRichard Trieu void ARMInstPrinter::printAddrMode2OffsetOperand(const MCInst *MI,
5065e3ee4b8SRichard Trieu                                                  unsigned OpNum,
5075e3ee4b8SRichard Trieu                                                  const MCSubtargetInfo &STI,
5085e3ee4b8SRichard Trieu                                                  raw_ostream &O) {
5095e3ee4b8SRichard Trieu   const MCOperand &MO1 = MI->getOperand(OpNum);
5105e3ee4b8SRichard Trieu   const MCOperand &MO2 = MI->getOperand(OpNum + 1);
5115e3ee4b8SRichard Trieu 
5125e3ee4b8SRichard Trieu   if (!MO1.getReg()) {
5135e3ee4b8SRichard Trieu     unsigned ImmOffs = ARM_AM::getAM2Offset(MO2.getImm());
5145e3ee4b8SRichard Trieu     O << markup("<imm:") << '#'
5155e3ee4b8SRichard Trieu       << ARM_AM::getAddrOpcStr(ARM_AM::getAM2Op(MO2.getImm())) << ImmOffs
5165e3ee4b8SRichard Trieu       << markup(">");
5175e3ee4b8SRichard Trieu     return;
5185e3ee4b8SRichard Trieu   }
5195e3ee4b8SRichard Trieu 
5205e3ee4b8SRichard Trieu   O << ARM_AM::getAddrOpcStr(ARM_AM::getAM2Op(MO2.getImm()));
5215e3ee4b8SRichard Trieu   printRegName(O, MO1.getReg());
5225e3ee4b8SRichard Trieu 
5235e3ee4b8SRichard Trieu   printRegImmShift(O, ARM_AM::getAM2ShiftOpc(MO2.getImm()),
5245e3ee4b8SRichard Trieu                    ARM_AM::getAM2Offset(MO2.getImm()), UseMarkup);
5255e3ee4b8SRichard Trieu }
5265e3ee4b8SRichard Trieu 
5275e3ee4b8SRichard Trieu //===--------------------------------------------------------------------===//
5285e3ee4b8SRichard Trieu // Addressing Mode #3
5295e3ee4b8SRichard Trieu //===--------------------------------------------------------------------===//
5305e3ee4b8SRichard Trieu 
printAM3PreOrOffsetIndexOp(const MCInst * MI,unsigned Op,raw_ostream & O,bool AlwaysPrintImm0)5315e3ee4b8SRichard Trieu void ARMInstPrinter::printAM3PreOrOffsetIndexOp(const MCInst *MI, unsigned Op,
5325e3ee4b8SRichard Trieu                                                 raw_ostream &O,
5335e3ee4b8SRichard Trieu                                                 bool AlwaysPrintImm0) {
5345e3ee4b8SRichard Trieu   const MCOperand &MO1 = MI->getOperand(Op);
5355e3ee4b8SRichard Trieu   const MCOperand &MO2 = MI->getOperand(Op + 1);
5365e3ee4b8SRichard Trieu   const MCOperand &MO3 = MI->getOperand(Op + 2);
5375e3ee4b8SRichard Trieu 
5385e3ee4b8SRichard Trieu   O << markup("<mem:") << '[';
5395e3ee4b8SRichard Trieu   printRegName(O, MO1.getReg());
5405e3ee4b8SRichard Trieu 
5415e3ee4b8SRichard Trieu   if (MO2.getReg()) {
5425e3ee4b8SRichard Trieu     O << ", " << getAddrOpcStr(ARM_AM::getAM3Op(MO3.getImm()));
5435e3ee4b8SRichard Trieu     printRegName(O, MO2.getReg());
5445e3ee4b8SRichard Trieu     O << ']' << markup(">");
5455e3ee4b8SRichard Trieu     return;
5465e3ee4b8SRichard Trieu   }
5475e3ee4b8SRichard Trieu 
5485e3ee4b8SRichard Trieu   // If the op is sub we have to print the immediate even if it is 0
5495e3ee4b8SRichard Trieu   unsigned ImmOffs = ARM_AM::getAM3Offset(MO3.getImm());
5505e3ee4b8SRichard Trieu   ARM_AM::AddrOpc op = ARM_AM::getAM3Op(MO3.getImm());
5515e3ee4b8SRichard Trieu 
5525e3ee4b8SRichard Trieu   if (AlwaysPrintImm0 || ImmOffs || (op == ARM_AM::sub)) {
5535e3ee4b8SRichard Trieu     O << ", " << markup("<imm:") << "#" << ARM_AM::getAddrOpcStr(op) << ImmOffs
5545e3ee4b8SRichard Trieu       << markup(">");
5555e3ee4b8SRichard Trieu   }
5565e3ee4b8SRichard Trieu   O << ']' << markup(">");
5575e3ee4b8SRichard Trieu }
5585e3ee4b8SRichard Trieu 
5595e3ee4b8SRichard Trieu template <bool AlwaysPrintImm0>
printAddrMode3Operand(const MCInst * MI,unsigned Op,const MCSubtargetInfo & STI,raw_ostream & O)5605e3ee4b8SRichard Trieu void ARMInstPrinter::printAddrMode3Operand(const MCInst *MI, unsigned Op,
5615e3ee4b8SRichard Trieu                                            const MCSubtargetInfo &STI,
5625e3ee4b8SRichard Trieu                                            raw_ostream &O) {
5635e3ee4b8SRichard Trieu   const MCOperand &MO1 = MI->getOperand(Op);
5645e3ee4b8SRichard Trieu   if (!MO1.isReg()) { //  For label symbolic references.
5655e3ee4b8SRichard Trieu     printOperand(MI, Op, STI, O);
5665e3ee4b8SRichard Trieu     return;
5675e3ee4b8SRichard Trieu   }
5685e3ee4b8SRichard Trieu 
5695e3ee4b8SRichard Trieu   assert(ARM_AM::getAM3IdxMode(MI->getOperand(Op + 2).getImm()) !=
5705e3ee4b8SRichard Trieu              ARMII::IndexModePost &&
5715e3ee4b8SRichard Trieu          "unexpected idxmode");
5725e3ee4b8SRichard Trieu   printAM3PreOrOffsetIndexOp(MI, Op, O, AlwaysPrintImm0);
5735e3ee4b8SRichard Trieu }
5745e3ee4b8SRichard Trieu 
printAddrMode3OffsetOperand(const MCInst * MI,unsigned OpNum,const MCSubtargetInfo & STI,raw_ostream & O)5755e3ee4b8SRichard Trieu void ARMInstPrinter::printAddrMode3OffsetOperand(const MCInst *MI,
5765e3ee4b8SRichard Trieu                                                  unsigned OpNum,
5775e3ee4b8SRichard Trieu                                                  const MCSubtargetInfo &STI,
5785e3ee4b8SRichard Trieu                                                  raw_ostream &O) {
5795e3ee4b8SRichard Trieu   const MCOperand &MO1 = MI->getOperand(OpNum);
5805e3ee4b8SRichard Trieu   const MCOperand &MO2 = MI->getOperand(OpNum + 1);
5815e3ee4b8SRichard Trieu 
5825e3ee4b8SRichard Trieu   if (MO1.getReg()) {
5835e3ee4b8SRichard Trieu     O << getAddrOpcStr(ARM_AM::getAM3Op(MO2.getImm()));
5845e3ee4b8SRichard Trieu     printRegName(O, MO1.getReg());
5855e3ee4b8SRichard Trieu     return;
5865e3ee4b8SRichard Trieu   }
5875e3ee4b8SRichard Trieu 
5885e3ee4b8SRichard Trieu   unsigned ImmOffs = ARM_AM::getAM3Offset(MO2.getImm());
5895e3ee4b8SRichard Trieu   O << markup("<imm:") << '#'
5905e3ee4b8SRichard Trieu     << ARM_AM::getAddrOpcStr(ARM_AM::getAM3Op(MO2.getImm())) << ImmOffs
5915e3ee4b8SRichard Trieu     << markup(">");
5925e3ee4b8SRichard Trieu }
5935e3ee4b8SRichard Trieu 
printPostIdxImm8Operand(const MCInst * MI,unsigned OpNum,const MCSubtargetInfo & STI,raw_ostream & O)5945e3ee4b8SRichard Trieu void ARMInstPrinter::printPostIdxImm8Operand(const MCInst *MI, unsigned OpNum,
5955e3ee4b8SRichard Trieu                                              const MCSubtargetInfo &STI,
5965e3ee4b8SRichard Trieu                                              raw_ostream &O) {
5975e3ee4b8SRichard Trieu   const MCOperand &MO = MI->getOperand(OpNum);
5985e3ee4b8SRichard Trieu   unsigned Imm = MO.getImm();
5995e3ee4b8SRichard Trieu   O << markup("<imm:") << '#' << ((Imm & 256) ? "" : "-") << (Imm & 0xff)
6005e3ee4b8SRichard Trieu     << markup(">");
6015e3ee4b8SRichard Trieu }
6025e3ee4b8SRichard Trieu 
printPostIdxRegOperand(const MCInst * MI,unsigned OpNum,const MCSubtargetInfo & STI,raw_ostream & O)6035e3ee4b8SRichard Trieu void ARMInstPrinter::printPostIdxRegOperand(const MCInst *MI, unsigned OpNum,
6045e3ee4b8SRichard Trieu                                             const MCSubtargetInfo &STI,
6055e3ee4b8SRichard Trieu                                             raw_ostream &O) {
6065e3ee4b8SRichard Trieu   const MCOperand &MO1 = MI->getOperand(OpNum);
6075e3ee4b8SRichard Trieu   const MCOperand &MO2 = MI->getOperand(OpNum + 1);
6085e3ee4b8SRichard Trieu 
6095e3ee4b8SRichard Trieu   O << (MO2.getImm() ? "" : "-");
6105e3ee4b8SRichard Trieu   printRegName(O, MO1.getReg());
6115e3ee4b8SRichard Trieu }
6125e3ee4b8SRichard Trieu 
printPostIdxImm8s4Operand(const MCInst * MI,unsigned OpNum,const MCSubtargetInfo & STI,raw_ostream & O)6135e3ee4b8SRichard Trieu void ARMInstPrinter::printPostIdxImm8s4Operand(const MCInst *MI, unsigned OpNum,
6145e3ee4b8SRichard Trieu                                                const MCSubtargetInfo &STI,
6155e3ee4b8SRichard Trieu                                                raw_ostream &O) {
6165e3ee4b8SRichard Trieu   const MCOperand &MO = MI->getOperand(OpNum);
6175e3ee4b8SRichard Trieu   unsigned Imm = MO.getImm();
6185e3ee4b8SRichard Trieu   O << markup("<imm:") << '#' << ((Imm & 256) ? "" : "-") << ((Imm & 0xff) << 2)
6195e3ee4b8SRichard Trieu     << markup(">");
6205e3ee4b8SRichard Trieu }
6215e3ee4b8SRichard Trieu 
622e6824160SSimon Tatham template<int shift>
printMveAddrModeRQOperand(const MCInst * MI,unsigned OpNum,const MCSubtargetInfo & STI,raw_ostream & O)623e6824160SSimon Tatham void ARMInstPrinter::printMveAddrModeRQOperand(const MCInst *MI, unsigned OpNum,
624e6824160SSimon Tatham                                                const MCSubtargetInfo &STI,
625e6824160SSimon Tatham                                                raw_ostream &O) {
626e6824160SSimon Tatham   const MCOperand &MO1 = MI->getOperand(OpNum);
627e6824160SSimon Tatham   const MCOperand &MO2 = MI->getOperand(OpNum + 1);
628e6824160SSimon Tatham 
629e6824160SSimon Tatham   O << markup("<mem:") << "[";
630e6824160SSimon Tatham   printRegName(O, MO1.getReg());
631e6824160SSimon Tatham   O << ", ";
632e6824160SSimon Tatham   printRegName(O, MO2.getReg());
633e6824160SSimon Tatham 
634e6824160SSimon Tatham   if (shift > 0)
635e6824160SSimon Tatham     printRegImmShift(O, ARM_AM::uxtw, shift, UseMarkup);
636e6824160SSimon Tatham 
637e6824160SSimon Tatham   O << "]" << markup(">");
638e6824160SSimon Tatham }
639e6824160SSimon Tatham 
printLdStmModeOperand(const MCInst * MI,unsigned OpNum,const MCSubtargetInfo & STI,raw_ostream & O)6405e3ee4b8SRichard Trieu void ARMInstPrinter::printLdStmModeOperand(const MCInst *MI, unsigned OpNum,
6415e3ee4b8SRichard Trieu                                            const MCSubtargetInfo &STI,
6425e3ee4b8SRichard Trieu                                            raw_ostream &O) {
6435e3ee4b8SRichard Trieu   ARM_AM::AMSubMode Mode =
6445e3ee4b8SRichard Trieu       ARM_AM::getAM4SubMode(MI->getOperand(OpNum).getImm());
6455e3ee4b8SRichard Trieu   O << ARM_AM::getAMSubModeStr(Mode);
6465e3ee4b8SRichard Trieu }
6475e3ee4b8SRichard Trieu 
6485e3ee4b8SRichard Trieu template <bool AlwaysPrintImm0>
printAddrMode5Operand(const MCInst * MI,unsigned OpNum,const MCSubtargetInfo & STI,raw_ostream & O)6495e3ee4b8SRichard Trieu void ARMInstPrinter::printAddrMode5Operand(const MCInst *MI, unsigned OpNum,
6505e3ee4b8SRichard Trieu                                            const MCSubtargetInfo &STI,
6515e3ee4b8SRichard Trieu                                            raw_ostream &O) {
6525e3ee4b8SRichard Trieu   const MCOperand &MO1 = MI->getOperand(OpNum);
6535e3ee4b8SRichard Trieu   const MCOperand &MO2 = MI->getOperand(OpNum + 1);
6545e3ee4b8SRichard Trieu 
6555e3ee4b8SRichard Trieu   if (!MO1.isReg()) { // FIXME: This is for CP entries, but isn't right.
6565e3ee4b8SRichard Trieu     printOperand(MI, OpNum, STI, O);
6575e3ee4b8SRichard Trieu     return;
6585e3ee4b8SRichard Trieu   }
6595e3ee4b8SRichard Trieu 
6605e3ee4b8SRichard Trieu   O << markup("<mem:") << "[";
6615e3ee4b8SRichard Trieu   printRegName(O, MO1.getReg());
6625e3ee4b8SRichard Trieu 
6635e3ee4b8SRichard Trieu   unsigned ImmOffs = ARM_AM::getAM5Offset(MO2.getImm());
6645e3ee4b8SRichard Trieu   ARM_AM::AddrOpc Op = ARM_AM::getAM5Op(MO2.getImm());
6655e3ee4b8SRichard Trieu   if (AlwaysPrintImm0 || ImmOffs || Op == ARM_AM::sub) {
6665e3ee4b8SRichard Trieu     O << ", " << markup("<imm:") << "#" << ARM_AM::getAddrOpcStr(Op)
6675e3ee4b8SRichard Trieu       << ImmOffs * 4 << markup(">");
6685e3ee4b8SRichard Trieu   }
6695e3ee4b8SRichard Trieu   O << "]" << markup(">");
6705e3ee4b8SRichard Trieu }
6715e3ee4b8SRichard Trieu 
6725e3ee4b8SRichard Trieu template <bool AlwaysPrintImm0>
printAddrMode5FP16Operand(const MCInst * MI,unsigned OpNum,const MCSubtargetInfo & STI,raw_ostream & O)6735e3ee4b8SRichard Trieu void ARMInstPrinter::printAddrMode5FP16Operand(const MCInst *MI, unsigned OpNum,
6745e3ee4b8SRichard Trieu                                                const MCSubtargetInfo &STI,
6755e3ee4b8SRichard Trieu                                                raw_ostream &O) {
6765e3ee4b8SRichard Trieu   const MCOperand &MO1 = MI->getOperand(OpNum);
6775e3ee4b8SRichard Trieu   const MCOperand &MO2 = MI->getOperand(OpNum+1);
6785e3ee4b8SRichard Trieu 
6795e3ee4b8SRichard Trieu   if (!MO1.isReg()) {   // FIXME: This is for CP entries, but isn't right.
6805e3ee4b8SRichard Trieu     printOperand(MI, OpNum, STI, O);
6815e3ee4b8SRichard Trieu     return;
6825e3ee4b8SRichard Trieu   }
6835e3ee4b8SRichard Trieu 
6845e3ee4b8SRichard Trieu   O << markup("<mem:") << "[";
6855e3ee4b8SRichard Trieu   printRegName(O, MO1.getReg());
6865e3ee4b8SRichard Trieu 
6875e3ee4b8SRichard Trieu   unsigned ImmOffs = ARM_AM::getAM5FP16Offset(MO2.getImm());
6885e3ee4b8SRichard Trieu   unsigned Op = ARM_AM::getAM5FP16Op(MO2.getImm());
6895e3ee4b8SRichard Trieu   if (AlwaysPrintImm0 || ImmOffs || Op == ARM_AM::sub) {
6905e3ee4b8SRichard Trieu     O << ", "
6915e3ee4b8SRichard Trieu       << markup("<imm:")
6925e3ee4b8SRichard Trieu       << "#"
6935e3ee4b8SRichard Trieu       << ARM_AM::getAddrOpcStr(ARM_AM::getAM5FP16Op(MO2.getImm()))
6945e3ee4b8SRichard Trieu       << ImmOffs * 2
6955e3ee4b8SRichard Trieu       << markup(">");
6965e3ee4b8SRichard Trieu   }
6975e3ee4b8SRichard Trieu   O << "]" << markup(">");
6985e3ee4b8SRichard Trieu }
6995e3ee4b8SRichard Trieu 
printAddrMode6Operand(const MCInst * MI,unsigned OpNum,const MCSubtargetInfo & STI,raw_ostream & O)7005e3ee4b8SRichard Trieu void ARMInstPrinter::printAddrMode6Operand(const MCInst *MI, unsigned OpNum,
7015e3ee4b8SRichard Trieu                                            const MCSubtargetInfo &STI,
7025e3ee4b8SRichard Trieu                                            raw_ostream &O) {
7035e3ee4b8SRichard Trieu   const MCOperand &MO1 = MI->getOperand(OpNum);
7045e3ee4b8SRichard Trieu   const MCOperand &MO2 = MI->getOperand(OpNum + 1);
7055e3ee4b8SRichard Trieu 
7065e3ee4b8SRichard Trieu   O << markup("<mem:") << "[";
7075e3ee4b8SRichard Trieu   printRegName(O, MO1.getReg());
7085e3ee4b8SRichard Trieu   if (MO2.getImm()) {
7095e3ee4b8SRichard Trieu     O << ":" << (MO2.getImm() << 3);
7105e3ee4b8SRichard Trieu   }
7115e3ee4b8SRichard Trieu   O << "]" << markup(">");
7125e3ee4b8SRichard Trieu }
7135e3ee4b8SRichard Trieu 
printAddrMode7Operand(const MCInst * MI,unsigned OpNum,const MCSubtargetInfo & STI,raw_ostream & O)7145e3ee4b8SRichard Trieu void ARMInstPrinter::printAddrMode7Operand(const MCInst *MI, unsigned OpNum,
7155e3ee4b8SRichard Trieu                                            const MCSubtargetInfo &STI,
7165e3ee4b8SRichard Trieu                                            raw_ostream &O) {
7175e3ee4b8SRichard Trieu   const MCOperand &MO1 = MI->getOperand(OpNum);
7185e3ee4b8SRichard Trieu   O << markup("<mem:") << "[";
7195e3ee4b8SRichard Trieu   printRegName(O, MO1.getReg());
7205e3ee4b8SRichard Trieu   O << "]" << markup(">");
7215e3ee4b8SRichard Trieu }
7225e3ee4b8SRichard Trieu 
printAddrMode6OffsetOperand(const MCInst * MI,unsigned OpNum,const MCSubtargetInfo & STI,raw_ostream & O)7235e3ee4b8SRichard Trieu void ARMInstPrinter::printAddrMode6OffsetOperand(const MCInst *MI,
7245e3ee4b8SRichard Trieu                                                  unsigned OpNum,
7255e3ee4b8SRichard Trieu                                                  const MCSubtargetInfo &STI,
7265e3ee4b8SRichard Trieu                                                  raw_ostream &O) {
7275e3ee4b8SRichard Trieu   const MCOperand &MO = MI->getOperand(OpNum);
7285e3ee4b8SRichard Trieu   if (MO.getReg() == 0)
7295e3ee4b8SRichard Trieu     O << "!";
7305e3ee4b8SRichard Trieu   else {
7315e3ee4b8SRichard Trieu     O << ", ";
7325e3ee4b8SRichard Trieu     printRegName(O, MO.getReg());
7335e3ee4b8SRichard Trieu   }
7345e3ee4b8SRichard Trieu }
7355e3ee4b8SRichard Trieu 
printBitfieldInvMaskImmOperand(const MCInst * MI,unsigned OpNum,const MCSubtargetInfo & STI,raw_ostream & O)7365e3ee4b8SRichard Trieu void ARMInstPrinter::printBitfieldInvMaskImmOperand(const MCInst *MI,
7375e3ee4b8SRichard Trieu                                                     unsigned OpNum,
7385e3ee4b8SRichard Trieu                                                     const MCSubtargetInfo &STI,
7395e3ee4b8SRichard Trieu                                                     raw_ostream &O) {
7405e3ee4b8SRichard Trieu   const MCOperand &MO = MI->getOperand(OpNum);
7415e3ee4b8SRichard Trieu   uint32_t v = ~MO.getImm();
7425e3ee4b8SRichard Trieu   int32_t lsb = countTrailingZeros(v);
7435e3ee4b8SRichard Trieu   int32_t width = (32 - countLeadingZeros(v)) - lsb;
7445e3ee4b8SRichard Trieu   assert(MO.isImm() && "Not a valid bf_inv_mask_imm value!");
7455e3ee4b8SRichard Trieu   O << markup("<imm:") << '#' << lsb << markup(">") << ", " << markup("<imm:")
7465e3ee4b8SRichard Trieu     << '#' << width << markup(">");
7475e3ee4b8SRichard Trieu }
7485e3ee4b8SRichard Trieu 
printMemBOption(const MCInst * MI,unsigned OpNum,const MCSubtargetInfo & STI,raw_ostream & O)7495e3ee4b8SRichard Trieu void ARMInstPrinter::printMemBOption(const MCInst *MI, unsigned OpNum,
7505e3ee4b8SRichard Trieu                                      const MCSubtargetInfo &STI,
7515e3ee4b8SRichard Trieu                                      raw_ostream &O) {
7525e3ee4b8SRichard Trieu   unsigned val = MI->getOperand(OpNum).getImm();
7535e3ee4b8SRichard Trieu   O << ARM_MB::MemBOptToString(val, STI.getFeatureBits()[ARM::HasV8Ops]);
7545e3ee4b8SRichard Trieu }
7555e3ee4b8SRichard Trieu 
printInstSyncBOption(const MCInst * MI,unsigned OpNum,const MCSubtargetInfo & STI,raw_ostream & O)7565e3ee4b8SRichard Trieu void ARMInstPrinter::printInstSyncBOption(const MCInst *MI, unsigned OpNum,
7575e3ee4b8SRichard Trieu                                           const MCSubtargetInfo &STI,
7585e3ee4b8SRichard Trieu                                           raw_ostream &O) {
7595e3ee4b8SRichard Trieu   unsigned val = MI->getOperand(OpNum).getImm();
7605e3ee4b8SRichard Trieu   O << ARM_ISB::InstSyncBOptToString(val);
7615e3ee4b8SRichard Trieu }
7625e3ee4b8SRichard Trieu 
printTraceSyncBOption(const MCInst * MI,unsigned OpNum,const MCSubtargetInfo & STI,raw_ostream & O)7635e3ee4b8SRichard Trieu void ARMInstPrinter::printTraceSyncBOption(const MCInst *MI, unsigned OpNum,
7645e3ee4b8SRichard Trieu                                           const MCSubtargetInfo &STI,
7655e3ee4b8SRichard Trieu                                           raw_ostream &O) {
7665e3ee4b8SRichard Trieu   unsigned val = MI->getOperand(OpNum).getImm();
7675e3ee4b8SRichard Trieu   O << ARM_TSB::TraceSyncBOptToString(val);
7685e3ee4b8SRichard Trieu }
7695e3ee4b8SRichard Trieu 
printShiftImmOperand(const MCInst * MI,unsigned OpNum,const MCSubtargetInfo & STI,raw_ostream & O)7705e3ee4b8SRichard Trieu void ARMInstPrinter::printShiftImmOperand(const MCInst *MI, unsigned OpNum,
7715e3ee4b8SRichard Trieu                                           const MCSubtargetInfo &STI,
7725e3ee4b8SRichard Trieu                                           raw_ostream &O) {
7735e3ee4b8SRichard Trieu   unsigned ShiftOp = MI->getOperand(OpNum).getImm();
7745e3ee4b8SRichard Trieu   bool isASR = (ShiftOp & (1 << 5)) != 0;
7755e3ee4b8SRichard Trieu   unsigned Amt = ShiftOp & 0x1f;
7765e3ee4b8SRichard Trieu   if (isASR) {
7775e3ee4b8SRichard Trieu     O << ", asr " << markup("<imm:") << "#" << (Amt == 0 ? 32 : Amt)
7785e3ee4b8SRichard Trieu       << markup(">");
7795e3ee4b8SRichard Trieu   } else if (Amt) {
7805e3ee4b8SRichard Trieu     O << ", lsl " << markup("<imm:") << "#" << Amt << markup(">");
7815e3ee4b8SRichard Trieu   }
7825e3ee4b8SRichard Trieu }
7835e3ee4b8SRichard Trieu 
printPKHLSLShiftImm(const MCInst * MI,unsigned OpNum,const MCSubtargetInfo & STI,raw_ostream & O)7845e3ee4b8SRichard Trieu void ARMInstPrinter::printPKHLSLShiftImm(const MCInst *MI, unsigned OpNum,
7855e3ee4b8SRichard Trieu                                          const MCSubtargetInfo &STI,
7865e3ee4b8SRichard Trieu                                          raw_ostream &O) {
7875e3ee4b8SRichard Trieu   unsigned Imm = MI->getOperand(OpNum).getImm();
7885e3ee4b8SRichard Trieu   if (Imm == 0)
7895e3ee4b8SRichard Trieu     return;
7905e3ee4b8SRichard Trieu   assert(Imm > 0 && Imm < 32 && "Invalid PKH shift immediate value!");
7915e3ee4b8SRichard Trieu   O << ", lsl " << markup("<imm:") << "#" << Imm << markup(">");
7925e3ee4b8SRichard Trieu }
7935e3ee4b8SRichard Trieu 
printPKHASRShiftImm(const MCInst * MI,unsigned OpNum,const MCSubtargetInfo & STI,raw_ostream & O)7945e3ee4b8SRichard Trieu void ARMInstPrinter::printPKHASRShiftImm(const MCInst *MI, unsigned OpNum,
7955e3ee4b8SRichard Trieu                                          const MCSubtargetInfo &STI,
7965e3ee4b8SRichard Trieu                                          raw_ostream &O) {
7975e3ee4b8SRichard Trieu   unsigned Imm = MI->getOperand(OpNum).getImm();
7985e3ee4b8SRichard Trieu   // A shift amount of 32 is encoded as 0.
7995e3ee4b8SRichard Trieu   if (Imm == 0)
8005e3ee4b8SRichard Trieu     Imm = 32;
8015e3ee4b8SRichard Trieu   assert(Imm > 0 && Imm <= 32 && "Invalid PKH shift immediate value!");
8025e3ee4b8SRichard Trieu   O << ", asr " << markup("<imm:") << "#" << Imm << markup(">");
8035e3ee4b8SRichard Trieu }
8045e3ee4b8SRichard Trieu 
printRegisterList(const MCInst * MI,unsigned OpNum,const MCSubtargetInfo & STI,raw_ostream & O)8055e3ee4b8SRichard Trieu void ARMInstPrinter::printRegisterList(const MCInst *MI, unsigned OpNum,
8065e3ee4b8SRichard Trieu                                        const MCSubtargetInfo &STI,
8075e3ee4b8SRichard Trieu                                        raw_ostream &O) {
8088c865cacSSimon Tatham   if (MI->getOpcode() != ARM::t2CLRM) {
809f890fd5fSKazu Hirata     assert(is_sorted(drop_begin(*MI, OpNum),
8105e3ee4b8SRichard Trieu                      [&](const MCOperand &LHS, const MCOperand &RHS) {
8115e3ee4b8SRichard Trieu                        return MRI.getEncodingValue(LHS.getReg()) <
8125e3ee4b8SRichard Trieu                               MRI.getEncodingValue(RHS.getReg());
8135e3ee4b8SRichard Trieu                      }));
8148c865cacSSimon Tatham   }
8155e3ee4b8SRichard Trieu 
8165e3ee4b8SRichard Trieu   O << "{";
8175e3ee4b8SRichard Trieu   for (unsigned i = OpNum, e = MI->getNumOperands(); i != e; ++i) {
8185e3ee4b8SRichard Trieu     if (i != OpNum)
8195e3ee4b8SRichard Trieu       O << ", ";
8205e3ee4b8SRichard Trieu     printRegName(O, MI->getOperand(i).getReg());
8215e3ee4b8SRichard Trieu   }
8225e3ee4b8SRichard Trieu   O << "}";
8235e3ee4b8SRichard Trieu }
8245e3ee4b8SRichard Trieu 
printGPRPairOperand(const MCInst * MI,unsigned OpNum,const MCSubtargetInfo & STI,raw_ostream & O)8255e3ee4b8SRichard Trieu void ARMInstPrinter::printGPRPairOperand(const MCInst *MI, unsigned OpNum,
8265e3ee4b8SRichard Trieu                                          const MCSubtargetInfo &STI,
8275e3ee4b8SRichard Trieu                                          raw_ostream &O) {
8285e3ee4b8SRichard Trieu   unsigned Reg = MI->getOperand(OpNum).getReg();
8295e3ee4b8SRichard Trieu   printRegName(O, MRI.getSubReg(Reg, ARM::gsub_0));
8305e3ee4b8SRichard Trieu   O << ", ";
8315e3ee4b8SRichard Trieu   printRegName(O, MRI.getSubReg(Reg, ARM::gsub_1));
8325e3ee4b8SRichard Trieu }
8335e3ee4b8SRichard Trieu 
printSetendOperand(const MCInst * MI,unsigned OpNum,const MCSubtargetInfo & STI,raw_ostream & O)8345e3ee4b8SRichard Trieu void ARMInstPrinter::printSetendOperand(const MCInst *MI, unsigned OpNum,
8355e3ee4b8SRichard Trieu                                         const MCSubtargetInfo &STI,
8365e3ee4b8SRichard Trieu                                         raw_ostream &O) {
8375e3ee4b8SRichard Trieu   const MCOperand &Op = MI->getOperand(OpNum);
8385e3ee4b8SRichard Trieu   if (Op.getImm())
8395e3ee4b8SRichard Trieu     O << "be";
8405e3ee4b8SRichard Trieu   else
8415e3ee4b8SRichard Trieu     O << "le";
8425e3ee4b8SRichard Trieu }
8435e3ee4b8SRichard Trieu 
printCPSIMod(const MCInst * MI,unsigned OpNum,const MCSubtargetInfo & STI,raw_ostream & O)8445e3ee4b8SRichard Trieu void ARMInstPrinter::printCPSIMod(const MCInst *MI, unsigned OpNum,
8455e3ee4b8SRichard Trieu                                   const MCSubtargetInfo &STI, raw_ostream &O) {
8465e3ee4b8SRichard Trieu   const MCOperand &Op = MI->getOperand(OpNum);
8475e3ee4b8SRichard Trieu   O << ARM_PROC::IModToString(Op.getImm());
8485e3ee4b8SRichard Trieu }
8495e3ee4b8SRichard Trieu 
printCPSIFlag(const MCInst * MI,unsigned OpNum,const MCSubtargetInfo & STI,raw_ostream & O)8505e3ee4b8SRichard Trieu void ARMInstPrinter::printCPSIFlag(const MCInst *MI, unsigned OpNum,
8515e3ee4b8SRichard Trieu                                    const MCSubtargetInfo &STI, raw_ostream &O) {
8525e3ee4b8SRichard Trieu   const MCOperand &Op = MI->getOperand(OpNum);
8535e3ee4b8SRichard Trieu   unsigned IFlags = Op.getImm();
8545e3ee4b8SRichard Trieu   for (int i = 2; i >= 0; --i)
8555e3ee4b8SRichard Trieu     if (IFlags & (1 << i))
8565e3ee4b8SRichard Trieu       O << ARM_PROC::IFlagsToString(1 << i);
8575e3ee4b8SRichard Trieu 
8585e3ee4b8SRichard Trieu   if (IFlags == 0)
8595e3ee4b8SRichard Trieu     O << "none";
8605e3ee4b8SRichard Trieu }
8615e3ee4b8SRichard Trieu 
printMSRMaskOperand(const MCInst * MI,unsigned OpNum,const MCSubtargetInfo & STI,raw_ostream & O)8625e3ee4b8SRichard Trieu void ARMInstPrinter::printMSRMaskOperand(const MCInst *MI, unsigned OpNum,
8635e3ee4b8SRichard Trieu                                          const MCSubtargetInfo &STI,
8645e3ee4b8SRichard Trieu                                          raw_ostream &O) {
8655e3ee4b8SRichard Trieu   const MCOperand &Op = MI->getOperand(OpNum);
8665e3ee4b8SRichard Trieu   const FeatureBitset &FeatureBits = STI.getFeatureBits();
8675e3ee4b8SRichard Trieu   if (FeatureBits[ARM::FeatureMClass]) {
8685e3ee4b8SRichard Trieu 
8695e3ee4b8SRichard Trieu     unsigned SYSm = Op.getImm() & 0xFFF; // 12-bit SYSm
8705e3ee4b8SRichard Trieu     unsigned Opcode = MI->getOpcode();
8715e3ee4b8SRichard Trieu 
8725e3ee4b8SRichard Trieu     // For writes, handle extended mask bits if the DSP extension is present.
8735e3ee4b8SRichard Trieu     if (Opcode == ARM::t2MSR_M && FeatureBits[ARM::FeatureDSP]) {
8745e3ee4b8SRichard Trieu       auto TheReg =ARMSysReg::lookupMClassSysRegBy12bitSYSmValue(SYSm);
8755e3ee4b8SRichard Trieu       if (TheReg && TheReg->isInRequiredFeatures({ARM::FeatureDSP})) {
8765e3ee4b8SRichard Trieu           O << TheReg->Name;
8775e3ee4b8SRichard Trieu           return;
8785e3ee4b8SRichard Trieu       }
8795e3ee4b8SRichard Trieu     }
8805e3ee4b8SRichard Trieu 
8815e3ee4b8SRichard Trieu     // Handle the basic 8-bit mask.
8825e3ee4b8SRichard Trieu     SYSm &= 0xff;
8835e3ee4b8SRichard Trieu     if (Opcode == ARM::t2MSR_M && FeatureBits [ARM::HasV7Ops]) {
8845e3ee4b8SRichard Trieu       // ARMv7-M deprecates using MSR APSR without a _<bits> qualifier as an
8855e3ee4b8SRichard Trieu       // alias for MSR APSR_nzcvq.
8865e3ee4b8SRichard Trieu       auto TheReg = ARMSysReg::lookupMClassSysRegAPSRNonDeprecated(SYSm);
8875e3ee4b8SRichard Trieu       if (TheReg) {
8885e3ee4b8SRichard Trieu           O << TheReg->Name;
8895e3ee4b8SRichard Trieu           return;
8905e3ee4b8SRichard Trieu       }
8915e3ee4b8SRichard Trieu     }
8925e3ee4b8SRichard Trieu 
8935e3ee4b8SRichard Trieu     auto TheReg = ARMSysReg::lookupMClassSysRegBy8bitSYSmValue(SYSm);
8945e3ee4b8SRichard Trieu     if (TheReg) {
8955e3ee4b8SRichard Trieu       O << TheReg->Name;
8965e3ee4b8SRichard Trieu       return;
8975e3ee4b8SRichard Trieu     }
8985e3ee4b8SRichard Trieu 
8995e3ee4b8SRichard Trieu     O << SYSm;
9005e3ee4b8SRichard Trieu 
9015e3ee4b8SRichard Trieu     return;
9025e3ee4b8SRichard Trieu   }
9035e3ee4b8SRichard Trieu 
9045e3ee4b8SRichard Trieu   // As special cases, CPSR_f, CPSR_s and CPSR_fs prefer printing as
9055e3ee4b8SRichard Trieu   // APSR_nzcvq, APSR_g and APSRnzcvqg, respectively.
9065e3ee4b8SRichard Trieu   unsigned SpecRegRBit = Op.getImm() >> 4;
9075e3ee4b8SRichard Trieu   unsigned Mask = Op.getImm() & 0xf;
9085e3ee4b8SRichard Trieu 
9095e3ee4b8SRichard Trieu   if (!SpecRegRBit && (Mask == 8 || Mask == 4 || Mask == 12)) {
9105e3ee4b8SRichard Trieu     O << "APSR_";
9115e3ee4b8SRichard Trieu     switch (Mask) {
9125e3ee4b8SRichard Trieu     default:
9135e3ee4b8SRichard Trieu       llvm_unreachable("Unexpected mask value!");
9145e3ee4b8SRichard Trieu     case 4:
9155e3ee4b8SRichard Trieu       O << "g";
9165e3ee4b8SRichard Trieu       return;
9175e3ee4b8SRichard Trieu     case 8:
9185e3ee4b8SRichard Trieu       O << "nzcvq";
9195e3ee4b8SRichard Trieu       return;
9205e3ee4b8SRichard Trieu     case 12:
9215e3ee4b8SRichard Trieu       O << "nzcvqg";
9225e3ee4b8SRichard Trieu       return;
9235e3ee4b8SRichard Trieu     }
9245e3ee4b8SRichard Trieu   }
9255e3ee4b8SRichard Trieu 
9265e3ee4b8SRichard Trieu   if (SpecRegRBit)
9275e3ee4b8SRichard Trieu     O << "SPSR";
9285e3ee4b8SRichard Trieu   else
9295e3ee4b8SRichard Trieu     O << "CPSR";
9305e3ee4b8SRichard Trieu 
9315e3ee4b8SRichard Trieu   if (Mask) {
9325e3ee4b8SRichard Trieu     O << '_';
9335e3ee4b8SRichard Trieu     if (Mask & 8)
9345e3ee4b8SRichard Trieu       O << 'f';
9355e3ee4b8SRichard Trieu     if (Mask & 4)
9365e3ee4b8SRichard Trieu       O << 's';
9375e3ee4b8SRichard Trieu     if (Mask & 2)
9385e3ee4b8SRichard Trieu       O << 'x';
9395e3ee4b8SRichard Trieu     if (Mask & 1)
9405e3ee4b8SRichard Trieu       O << 'c';
9415e3ee4b8SRichard Trieu   }
9425e3ee4b8SRichard Trieu }
9435e3ee4b8SRichard Trieu 
printBankedRegOperand(const MCInst * MI,unsigned OpNum,const MCSubtargetInfo & STI,raw_ostream & O)9445e3ee4b8SRichard Trieu void ARMInstPrinter::printBankedRegOperand(const MCInst *MI, unsigned OpNum,
9455e3ee4b8SRichard Trieu                                            const MCSubtargetInfo &STI,
9465e3ee4b8SRichard Trieu                                            raw_ostream &O) {
9475e3ee4b8SRichard Trieu   uint32_t Banked = MI->getOperand(OpNum).getImm();
9485e3ee4b8SRichard Trieu   auto TheReg = ARMBankedReg::lookupBankedRegByEncoding(Banked);
9495e3ee4b8SRichard Trieu   assert(TheReg && "invalid banked register operand");
9505e3ee4b8SRichard Trieu   std::string Name = TheReg->Name;
9515e3ee4b8SRichard Trieu 
9525e3ee4b8SRichard Trieu   uint32_t isSPSR = (Banked & 0x20) >> 5;
9535e3ee4b8SRichard Trieu   if (isSPSR)
9545e3ee4b8SRichard Trieu     Name.replace(0, 4, "SPSR"); // convert 'spsr_' to 'SPSR_'
9555e3ee4b8SRichard Trieu   O << Name;
9565e3ee4b8SRichard Trieu }
9575e3ee4b8SRichard Trieu 
printPredicateOperand(const MCInst * MI,unsigned OpNum,const MCSubtargetInfo & STI,raw_ostream & O)9585e3ee4b8SRichard Trieu void ARMInstPrinter::printPredicateOperand(const MCInst *MI, unsigned OpNum,
9595e3ee4b8SRichard Trieu                                            const MCSubtargetInfo &STI,
9605e3ee4b8SRichard Trieu                                            raw_ostream &O) {
9615e3ee4b8SRichard Trieu   ARMCC::CondCodes CC = (ARMCC::CondCodes)MI->getOperand(OpNum).getImm();
9625e3ee4b8SRichard Trieu   // Handle the undefined 15 CC value here for printing so we don't abort().
9635e3ee4b8SRichard Trieu   if ((unsigned)CC == 15)
9645e3ee4b8SRichard Trieu     O << "<und>";
9655e3ee4b8SRichard Trieu   else if (CC != ARMCC::AL)
9665e3ee4b8SRichard Trieu     O << ARMCondCodeToString(CC);
9675e3ee4b8SRichard Trieu }
9685e3ee4b8SRichard Trieu 
printMandatoryRestrictedPredicateOperand(const MCInst * MI,unsigned OpNum,const MCSubtargetInfo & STI,raw_ostream & O)9698c865cacSSimon Tatham void ARMInstPrinter::printMandatoryRestrictedPredicateOperand(
9708c865cacSSimon Tatham     const MCInst *MI, unsigned OpNum, const MCSubtargetInfo &STI,
9718c865cacSSimon Tatham     raw_ostream &O) {
9728c865cacSSimon Tatham   if ((ARMCC::CondCodes)MI->getOperand(OpNum).getImm() == ARMCC::HS)
9738c865cacSSimon Tatham     O << "cs";
9748c865cacSSimon Tatham   else
9758c865cacSSimon Tatham     printMandatoryPredicateOperand(MI, OpNum, STI, O);
9768c865cacSSimon Tatham }
9778c865cacSSimon Tatham 
printMandatoryPredicateOperand(const MCInst * MI,unsigned OpNum,const MCSubtargetInfo & STI,raw_ostream & O)9785e3ee4b8SRichard Trieu void ARMInstPrinter::printMandatoryPredicateOperand(const MCInst *MI,
9795e3ee4b8SRichard Trieu                                                     unsigned OpNum,
9805e3ee4b8SRichard Trieu                                                     const MCSubtargetInfo &STI,
9815e3ee4b8SRichard Trieu                                                     raw_ostream &O) {
9825e3ee4b8SRichard Trieu   ARMCC::CondCodes CC = (ARMCC::CondCodes)MI->getOperand(OpNum).getImm();
9835e3ee4b8SRichard Trieu   O << ARMCondCodeToString(CC);
9845e3ee4b8SRichard Trieu }
9855e3ee4b8SRichard Trieu 
printMandatoryInvertedPredicateOperand(const MCInst * MI,unsigned OpNum,const MCSubtargetInfo & STI,raw_ostream & O)9868c865cacSSimon Tatham void ARMInstPrinter::printMandatoryInvertedPredicateOperand(const MCInst *MI,
9878c865cacSSimon Tatham                                                             unsigned OpNum,
9888c865cacSSimon Tatham                                                             const MCSubtargetInfo &STI,
9898c865cacSSimon Tatham                                                             raw_ostream &O) {
9908c865cacSSimon Tatham   ARMCC::CondCodes CC = (ARMCC::CondCodes)MI->getOperand(OpNum).getImm();
9918c865cacSSimon Tatham   O << ARMCondCodeToString(ARMCC::getOppositeCondition(CC));
9928c865cacSSimon Tatham }
9938c865cacSSimon Tatham 
printSBitModifierOperand(const MCInst * MI,unsigned OpNum,const MCSubtargetInfo & STI,raw_ostream & O)9945e3ee4b8SRichard Trieu void ARMInstPrinter::printSBitModifierOperand(const MCInst *MI, unsigned OpNum,
9955e3ee4b8SRichard Trieu                                               const MCSubtargetInfo &STI,
9965e3ee4b8SRichard Trieu                                               raw_ostream &O) {
9975e3ee4b8SRichard Trieu   if (MI->getOperand(OpNum).getReg()) {
9985e3ee4b8SRichard Trieu     assert(MI->getOperand(OpNum).getReg() == ARM::CPSR &&
9995e3ee4b8SRichard Trieu            "Expect ARM CPSR register!");
10005e3ee4b8SRichard Trieu     O << 's';
10015e3ee4b8SRichard Trieu   }
10025e3ee4b8SRichard Trieu }
10035e3ee4b8SRichard Trieu 
printNoHashImmediate(const MCInst * MI,unsigned OpNum,const MCSubtargetInfo & STI,raw_ostream & O)10045e3ee4b8SRichard Trieu void ARMInstPrinter::printNoHashImmediate(const MCInst *MI, unsigned OpNum,
10055e3ee4b8SRichard Trieu                                           const MCSubtargetInfo &STI,
10065e3ee4b8SRichard Trieu                                           raw_ostream &O) {
10075e3ee4b8SRichard Trieu   O << MI->getOperand(OpNum).getImm();
10085e3ee4b8SRichard Trieu }
10095e3ee4b8SRichard Trieu 
printPImmediate(const MCInst * MI,unsigned OpNum,const MCSubtargetInfo & STI,raw_ostream & O)10105e3ee4b8SRichard Trieu void ARMInstPrinter::printPImmediate(const MCInst *MI, unsigned OpNum,
10115e3ee4b8SRichard Trieu                                      const MCSubtargetInfo &STI,
10125e3ee4b8SRichard Trieu                                      raw_ostream &O) {
10135e3ee4b8SRichard Trieu   O << "p" << MI->getOperand(OpNum).getImm();
10145e3ee4b8SRichard Trieu }
10155e3ee4b8SRichard Trieu 
printCImmediate(const MCInst * MI,unsigned OpNum,const MCSubtargetInfo & STI,raw_ostream & O)10165e3ee4b8SRichard Trieu void ARMInstPrinter::printCImmediate(const MCInst *MI, unsigned OpNum,
10175e3ee4b8SRichard Trieu                                      const MCSubtargetInfo &STI,
10185e3ee4b8SRichard Trieu                                      raw_ostream &O) {
10195e3ee4b8SRichard Trieu   O << "c" << MI->getOperand(OpNum).getImm();
10205e3ee4b8SRichard Trieu }
10215e3ee4b8SRichard Trieu 
printCoprocOptionImm(const MCInst * MI,unsigned OpNum,const MCSubtargetInfo & STI,raw_ostream & O)10225e3ee4b8SRichard Trieu void ARMInstPrinter::printCoprocOptionImm(const MCInst *MI, unsigned OpNum,
10235e3ee4b8SRichard Trieu                                           const MCSubtargetInfo &STI,
10245e3ee4b8SRichard Trieu                                           raw_ostream &O) {
10255e3ee4b8SRichard Trieu   O << "{" << MI->getOperand(OpNum).getImm() << "}";
10265e3ee4b8SRichard Trieu }
10275e3ee4b8SRichard Trieu 
printPCLabel(const MCInst * MI,unsigned OpNum,const MCSubtargetInfo & STI,raw_ostream & O)10285e3ee4b8SRichard Trieu void ARMInstPrinter::printPCLabel(const MCInst *MI, unsigned OpNum,
10295e3ee4b8SRichard Trieu                                   const MCSubtargetInfo &STI, raw_ostream &O) {
10305e3ee4b8SRichard Trieu   llvm_unreachable("Unhandled PC-relative pseudo-instruction!");
10315e3ee4b8SRichard Trieu }
10325e3ee4b8SRichard Trieu 
10335e3ee4b8SRichard Trieu template <unsigned scale>
printAdrLabelOperand(const MCInst * MI,unsigned OpNum,const MCSubtargetInfo & STI,raw_ostream & O)10345e3ee4b8SRichard Trieu void ARMInstPrinter::printAdrLabelOperand(const MCInst *MI, unsigned OpNum,
10355e3ee4b8SRichard Trieu                                           const MCSubtargetInfo &STI,
10365e3ee4b8SRichard Trieu                                           raw_ostream &O) {
10375e3ee4b8SRichard Trieu   const MCOperand &MO = MI->getOperand(OpNum);
10385e3ee4b8SRichard Trieu 
10395e3ee4b8SRichard Trieu   if (MO.isExpr()) {
10405e3ee4b8SRichard Trieu     MO.getExpr()->print(O, &MAI);
10415e3ee4b8SRichard Trieu     return;
10425e3ee4b8SRichard Trieu   }
10435e3ee4b8SRichard Trieu 
10445e3ee4b8SRichard Trieu   int32_t OffImm = (int32_t)MO.getImm() << scale;
10455e3ee4b8SRichard Trieu 
10465e3ee4b8SRichard Trieu   O << markup("<imm:");
10475e3ee4b8SRichard Trieu   if (OffImm == INT32_MIN)
10485e3ee4b8SRichard Trieu     O << "#-0";
10495e3ee4b8SRichard Trieu   else if (OffImm < 0)
10505e3ee4b8SRichard Trieu     O << "#-" << -OffImm;
10515e3ee4b8SRichard Trieu   else
10525e3ee4b8SRichard Trieu     O << "#" << OffImm;
10535e3ee4b8SRichard Trieu   O << markup(">");
10545e3ee4b8SRichard Trieu }
10555e3ee4b8SRichard Trieu 
printThumbS4ImmOperand(const MCInst * MI,unsigned OpNum,const MCSubtargetInfo & STI,raw_ostream & O)10565e3ee4b8SRichard Trieu void ARMInstPrinter::printThumbS4ImmOperand(const MCInst *MI, unsigned OpNum,
10575e3ee4b8SRichard Trieu                                             const MCSubtargetInfo &STI,
10585e3ee4b8SRichard Trieu                                             raw_ostream &O) {
10595e3ee4b8SRichard Trieu   O << markup("<imm:") << "#" << formatImm(MI->getOperand(OpNum).getImm() * 4)
10605e3ee4b8SRichard Trieu     << markup(">");
10615e3ee4b8SRichard Trieu }
10625e3ee4b8SRichard Trieu 
printThumbSRImm(const MCInst * MI,unsigned OpNum,const MCSubtargetInfo & STI,raw_ostream & O)10635e3ee4b8SRichard Trieu void ARMInstPrinter::printThumbSRImm(const MCInst *MI, unsigned OpNum,
10645e3ee4b8SRichard Trieu                                      const MCSubtargetInfo &STI,
10655e3ee4b8SRichard Trieu                                      raw_ostream &O) {
10665e3ee4b8SRichard Trieu   unsigned Imm = MI->getOperand(OpNum).getImm();
10675e3ee4b8SRichard Trieu   O << markup("<imm:") << "#" << formatImm((Imm == 0 ? 32 : Imm))
10685e3ee4b8SRichard Trieu     << markup(">");
10695e3ee4b8SRichard Trieu }
10705e3ee4b8SRichard Trieu 
printThumbITMask(const MCInst * MI,unsigned OpNum,const MCSubtargetInfo & STI,raw_ostream & O)10715e3ee4b8SRichard Trieu void ARMInstPrinter::printThumbITMask(const MCInst *MI, unsigned OpNum,
10725e3ee4b8SRichard Trieu                                       const MCSubtargetInfo &STI,
10735e3ee4b8SRichard Trieu                                       raw_ostream &O) {
10745e3ee4b8SRichard Trieu   // (3 - the number of trailing zeros) is the number of then / else.
10755e3ee4b8SRichard Trieu   unsigned Mask = MI->getOperand(OpNum).getImm();
10765e3ee4b8SRichard Trieu   unsigned NumTZ = countTrailingZeros(Mask);
10775e3ee4b8SRichard Trieu   assert(NumTZ <= 3 && "Invalid IT mask!");
10785e3ee4b8SRichard Trieu   for (unsigned Pos = 3, e = NumTZ; Pos > e; --Pos) {
1079848d3d0dSSimon Tatham     if ((Mask >> Pos) & 1)
10805e3ee4b8SRichard Trieu       O << 'e';
1081848d3d0dSSimon Tatham     else
1082848d3d0dSSimon Tatham       O << 't';
10835e3ee4b8SRichard Trieu   }
10845e3ee4b8SRichard Trieu }
10855e3ee4b8SRichard Trieu 
printThumbAddrModeRROperand(const MCInst * MI,unsigned Op,const MCSubtargetInfo & STI,raw_ostream & O)10865e3ee4b8SRichard Trieu void ARMInstPrinter::printThumbAddrModeRROperand(const MCInst *MI, unsigned Op,
10875e3ee4b8SRichard Trieu                                                  const MCSubtargetInfo &STI,
10885e3ee4b8SRichard Trieu                                                  raw_ostream &O) {
10895e3ee4b8SRichard Trieu   const MCOperand &MO1 = MI->getOperand(Op);
10905e3ee4b8SRichard Trieu   const MCOperand &MO2 = MI->getOperand(Op + 1);
10915e3ee4b8SRichard Trieu 
10925e3ee4b8SRichard Trieu   if (!MO1.isReg()) { // FIXME: This is for CP entries, but isn't right.
10935e3ee4b8SRichard Trieu     printOperand(MI, Op, STI, O);
10945e3ee4b8SRichard Trieu     return;
10955e3ee4b8SRichard Trieu   }
10965e3ee4b8SRichard Trieu 
10975e3ee4b8SRichard Trieu   O << markup("<mem:") << "[";
10985e3ee4b8SRichard Trieu   printRegName(O, MO1.getReg());
10995e3ee4b8SRichard Trieu   if (unsigned RegNum = MO2.getReg()) {
11005e3ee4b8SRichard Trieu     O << ", ";
11015e3ee4b8SRichard Trieu     printRegName(O, RegNum);
11025e3ee4b8SRichard Trieu   }
11035e3ee4b8SRichard Trieu   O << "]" << markup(">");
11045e3ee4b8SRichard Trieu }
11055e3ee4b8SRichard Trieu 
printThumbAddrModeImm5SOperand(const MCInst * MI,unsigned Op,const MCSubtargetInfo & STI,raw_ostream & O,unsigned Scale)11065e3ee4b8SRichard Trieu void ARMInstPrinter::printThumbAddrModeImm5SOperand(const MCInst *MI,
11075e3ee4b8SRichard Trieu                                                     unsigned Op,
11085e3ee4b8SRichard Trieu                                                     const MCSubtargetInfo &STI,
11095e3ee4b8SRichard Trieu                                                     raw_ostream &O,
11105e3ee4b8SRichard Trieu                                                     unsigned Scale) {
11115e3ee4b8SRichard Trieu   const MCOperand &MO1 = MI->getOperand(Op);
11125e3ee4b8SRichard Trieu   const MCOperand &MO2 = MI->getOperand(Op + 1);
11135e3ee4b8SRichard Trieu 
11145e3ee4b8SRichard Trieu   if (!MO1.isReg()) { // FIXME: This is for CP entries, but isn't right.
11155e3ee4b8SRichard Trieu     printOperand(MI, Op, STI, O);
11165e3ee4b8SRichard Trieu     return;
11175e3ee4b8SRichard Trieu   }
11185e3ee4b8SRichard Trieu 
11195e3ee4b8SRichard Trieu   O << markup("<mem:") << "[";
11205e3ee4b8SRichard Trieu   printRegName(O, MO1.getReg());
11215e3ee4b8SRichard Trieu   if (unsigned ImmOffs = MO2.getImm()) {
11225e3ee4b8SRichard Trieu     O << ", " << markup("<imm:") << "#" << formatImm(ImmOffs * Scale)
11235e3ee4b8SRichard Trieu       << markup(">");
11245e3ee4b8SRichard Trieu   }
11255e3ee4b8SRichard Trieu   O << "]" << markup(">");
11265e3ee4b8SRichard Trieu }
11275e3ee4b8SRichard Trieu 
printThumbAddrModeImm5S1Operand(const MCInst * MI,unsigned Op,const MCSubtargetInfo & STI,raw_ostream & O)11285e3ee4b8SRichard Trieu void ARMInstPrinter::printThumbAddrModeImm5S1Operand(const MCInst *MI,
11295e3ee4b8SRichard Trieu                                                      unsigned Op,
11305e3ee4b8SRichard Trieu                                                      const MCSubtargetInfo &STI,
11315e3ee4b8SRichard Trieu                                                      raw_ostream &O) {
11325e3ee4b8SRichard Trieu   printThumbAddrModeImm5SOperand(MI, Op, STI, O, 1);
11335e3ee4b8SRichard Trieu }
11345e3ee4b8SRichard Trieu 
printThumbAddrModeImm5S2Operand(const MCInst * MI,unsigned Op,const MCSubtargetInfo & STI,raw_ostream & O)11355e3ee4b8SRichard Trieu void ARMInstPrinter::printThumbAddrModeImm5S2Operand(const MCInst *MI,
11365e3ee4b8SRichard Trieu                                                      unsigned Op,
11375e3ee4b8SRichard Trieu                                                      const MCSubtargetInfo &STI,
11385e3ee4b8SRichard Trieu                                                      raw_ostream &O) {
11395e3ee4b8SRichard Trieu   printThumbAddrModeImm5SOperand(MI, Op, STI, O, 2);
11405e3ee4b8SRichard Trieu }
11415e3ee4b8SRichard Trieu 
printThumbAddrModeImm5S4Operand(const MCInst * MI,unsigned Op,const MCSubtargetInfo & STI,raw_ostream & O)11425e3ee4b8SRichard Trieu void ARMInstPrinter::printThumbAddrModeImm5S4Operand(const MCInst *MI,
11435e3ee4b8SRichard Trieu                                                      unsigned Op,
11445e3ee4b8SRichard Trieu                                                      const MCSubtargetInfo &STI,
11455e3ee4b8SRichard Trieu                                                      raw_ostream &O) {
11465e3ee4b8SRichard Trieu   printThumbAddrModeImm5SOperand(MI, Op, STI, O, 4);
11475e3ee4b8SRichard Trieu }
11485e3ee4b8SRichard Trieu 
printThumbAddrModeSPOperand(const MCInst * MI,unsigned Op,const MCSubtargetInfo & STI,raw_ostream & O)11495e3ee4b8SRichard Trieu void ARMInstPrinter::printThumbAddrModeSPOperand(const MCInst *MI, unsigned Op,
11505e3ee4b8SRichard Trieu                                                  const MCSubtargetInfo &STI,
11515e3ee4b8SRichard Trieu                                                  raw_ostream &O) {
11525e3ee4b8SRichard Trieu   printThumbAddrModeImm5SOperand(MI, Op, STI, O, 4);
11535e3ee4b8SRichard Trieu }
11545e3ee4b8SRichard Trieu 
11555e3ee4b8SRichard Trieu // Constant shifts t2_so_reg is a 2-operand unit corresponding to the Thumb2
11565e3ee4b8SRichard Trieu // register with shift forms.
11575e3ee4b8SRichard Trieu // REG 0   0           - e.g. R5
11585e3ee4b8SRichard Trieu // REG IMM, SH_OPC     - e.g. R5, LSL #3
printT2SOOperand(const MCInst * MI,unsigned OpNum,const MCSubtargetInfo & STI,raw_ostream & O)11595e3ee4b8SRichard Trieu void ARMInstPrinter::printT2SOOperand(const MCInst *MI, unsigned OpNum,
11605e3ee4b8SRichard Trieu                                       const MCSubtargetInfo &STI,
11615e3ee4b8SRichard Trieu                                       raw_ostream &O) {
11625e3ee4b8SRichard Trieu   const MCOperand &MO1 = MI->getOperand(OpNum);
11635e3ee4b8SRichard Trieu   const MCOperand &MO2 = MI->getOperand(OpNum + 1);
11645e3ee4b8SRichard Trieu 
11655e3ee4b8SRichard Trieu   unsigned Reg = MO1.getReg();
11665e3ee4b8SRichard Trieu   printRegName(O, Reg);
11675e3ee4b8SRichard Trieu 
11685e3ee4b8SRichard Trieu   // Print the shift opc.
11695e3ee4b8SRichard Trieu   assert(MO2.isImm() && "Not a valid t2_so_reg value!");
11705e3ee4b8SRichard Trieu   printRegImmShift(O, ARM_AM::getSORegShOp(MO2.getImm()),
11715e3ee4b8SRichard Trieu                    ARM_AM::getSORegOffset(MO2.getImm()), UseMarkup);
11725e3ee4b8SRichard Trieu }
11735e3ee4b8SRichard Trieu 
11745e3ee4b8SRichard Trieu template <bool AlwaysPrintImm0>
printAddrModeImm12Operand(const MCInst * MI,unsigned OpNum,const MCSubtargetInfo & STI,raw_ostream & O)11755e3ee4b8SRichard Trieu void ARMInstPrinter::printAddrModeImm12Operand(const MCInst *MI, unsigned OpNum,
11765e3ee4b8SRichard Trieu                                                const MCSubtargetInfo &STI,
11775e3ee4b8SRichard Trieu                                                raw_ostream &O) {
11785e3ee4b8SRichard Trieu   const MCOperand &MO1 = MI->getOperand(OpNum);
11795e3ee4b8SRichard Trieu   const MCOperand &MO2 = MI->getOperand(OpNum + 1);
11805e3ee4b8SRichard Trieu 
11815e3ee4b8SRichard Trieu   if (!MO1.isReg()) { // FIXME: This is for CP entries, but isn't right.
11825e3ee4b8SRichard Trieu     printOperand(MI, OpNum, STI, O);
11835e3ee4b8SRichard Trieu     return;
11845e3ee4b8SRichard Trieu   }
11855e3ee4b8SRichard Trieu 
11865e3ee4b8SRichard Trieu   O << markup("<mem:") << "[";
11875e3ee4b8SRichard Trieu   printRegName(O, MO1.getReg());
11885e3ee4b8SRichard Trieu 
11895e3ee4b8SRichard Trieu   int32_t OffImm = (int32_t)MO2.getImm();
11905e3ee4b8SRichard Trieu   bool isSub = OffImm < 0;
11915e3ee4b8SRichard Trieu   // Special value for #-0. All others are normal.
11925e3ee4b8SRichard Trieu   if (OffImm == INT32_MIN)
11935e3ee4b8SRichard Trieu     OffImm = 0;
11945e3ee4b8SRichard Trieu   if (isSub) {
11955e3ee4b8SRichard Trieu     O << ", " << markup("<imm:") << "#-" << formatImm(-OffImm) << markup(">");
11965e3ee4b8SRichard Trieu   } else if (AlwaysPrintImm0 || OffImm > 0) {
11975e3ee4b8SRichard Trieu     O << ", " << markup("<imm:") << "#" << formatImm(OffImm) << markup(">");
11985e3ee4b8SRichard Trieu   }
11995e3ee4b8SRichard Trieu   O << "]" << markup(">");
12005e3ee4b8SRichard Trieu }
12015e3ee4b8SRichard Trieu 
12025e3ee4b8SRichard Trieu template <bool AlwaysPrintImm0>
printT2AddrModeImm8Operand(const MCInst * MI,unsigned OpNum,const MCSubtargetInfo & STI,raw_ostream & O)12035e3ee4b8SRichard Trieu void ARMInstPrinter::printT2AddrModeImm8Operand(const MCInst *MI,
12045e3ee4b8SRichard Trieu                                                 unsigned OpNum,
12055e3ee4b8SRichard Trieu                                                 const MCSubtargetInfo &STI,
12065e3ee4b8SRichard Trieu                                                 raw_ostream &O) {
12075e3ee4b8SRichard Trieu   const MCOperand &MO1 = MI->getOperand(OpNum);
12085e3ee4b8SRichard Trieu   const MCOperand &MO2 = MI->getOperand(OpNum + 1);
12095e3ee4b8SRichard Trieu 
12105e3ee4b8SRichard Trieu   O << markup("<mem:") << "[";
12115e3ee4b8SRichard Trieu   printRegName(O, MO1.getReg());
12125e3ee4b8SRichard Trieu 
12135e3ee4b8SRichard Trieu   int32_t OffImm = (int32_t)MO2.getImm();
12145e3ee4b8SRichard Trieu   bool isSub = OffImm < 0;
12155e3ee4b8SRichard Trieu   // Don't print +0.
12165e3ee4b8SRichard Trieu   if (OffImm == INT32_MIN)
12175e3ee4b8SRichard Trieu     OffImm = 0;
12185e3ee4b8SRichard Trieu   if (isSub) {
12195e3ee4b8SRichard Trieu     O << ", " << markup("<imm:") << "#-" << -OffImm << markup(">");
12205e3ee4b8SRichard Trieu   } else if (AlwaysPrintImm0 || OffImm > 0) {
12215e3ee4b8SRichard Trieu     O << ", " << markup("<imm:") << "#" << OffImm << markup(">");
12225e3ee4b8SRichard Trieu   }
12235e3ee4b8SRichard Trieu   O << "]" << markup(">");
12245e3ee4b8SRichard Trieu }
12255e3ee4b8SRichard Trieu 
12265e3ee4b8SRichard Trieu template <bool AlwaysPrintImm0>
printT2AddrModeImm8s4Operand(const MCInst * MI,unsigned OpNum,const MCSubtargetInfo & STI,raw_ostream & O)12275e3ee4b8SRichard Trieu void ARMInstPrinter::printT2AddrModeImm8s4Operand(const MCInst *MI,
12285e3ee4b8SRichard Trieu                                                   unsigned OpNum,
12295e3ee4b8SRichard Trieu                                                   const MCSubtargetInfo &STI,
12305e3ee4b8SRichard Trieu                                                   raw_ostream &O) {
12315e3ee4b8SRichard Trieu   const MCOperand &MO1 = MI->getOperand(OpNum);
12325e3ee4b8SRichard Trieu   const MCOperand &MO2 = MI->getOperand(OpNum + 1);
12335e3ee4b8SRichard Trieu 
12345e3ee4b8SRichard Trieu   if (!MO1.isReg()) { //  For label symbolic references.
12355e3ee4b8SRichard Trieu     printOperand(MI, OpNum, STI, O);
12365e3ee4b8SRichard Trieu     return;
12375e3ee4b8SRichard Trieu   }
12385e3ee4b8SRichard Trieu 
12395e3ee4b8SRichard Trieu   O << markup("<mem:") << "[";
12405e3ee4b8SRichard Trieu   printRegName(O, MO1.getReg());
12415e3ee4b8SRichard Trieu 
12425e3ee4b8SRichard Trieu   int32_t OffImm = (int32_t)MO2.getImm();
12435e3ee4b8SRichard Trieu   bool isSub = OffImm < 0;
12445e3ee4b8SRichard Trieu 
12455e3ee4b8SRichard Trieu   assert(((OffImm & 0x3) == 0) && "Not a valid immediate!");
12465e3ee4b8SRichard Trieu 
12475e3ee4b8SRichard Trieu   // Don't print +0.
12485e3ee4b8SRichard Trieu   if (OffImm == INT32_MIN)
12495e3ee4b8SRichard Trieu     OffImm = 0;
12505e3ee4b8SRichard Trieu   if (isSub) {
12515e3ee4b8SRichard Trieu     O << ", " << markup("<imm:") << "#-" << -OffImm << markup(">");
12525e3ee4b8SRichard Trieu   } else if (AlwaysPrintImm0 || OffImm > 0) {
12535e3ee4b8SRichard Trieu     O << ", " << markup("<imm:") << "#" << OffImm << markup(">");
12545e3ee4b8SRichard Trieu   }
12555e3ee4b8SRichard Trieu   O << "]" << markup(">");
12565e3ee4b8SRichard Trieu }
12575e3ee4b8SRichard Trieu 
printT2AddrModeImm0_1020s4Operand(const MCInst * MI,unsigned OpNum,const MCSubtargetInfo & STI,raw_ostream & O)12585e3ee4b8SRichard Trieu void ARMInstPrinter::printT2AddrModeImm0_1020s4Operand(
12595e3ee4b8SRichard Trieu     const MCInst *MI, unsigned OpNum, const MCSubtargetInfo &STI,
12605e3ee4b8SRichard Trieu     raw_ostream &O) {
12615e3ee4b8SRichard Trieu   const MCOperand &MO1 = MI->getOperand(OpNum);
12625e3ee4b8SRichard Trieu   const MCOperand &MO2 = MI->getOperand(OpNum + 1);
12635e3ee4b8SRichard Trieu 
12645e3ee4b8SRichard Trieu   O << markup("<mem:") << "[";
12655e3ee4b8SRichard Trieu   printRegName(O, MO1.getReg());
12665e3ee4b8SRichard Trieu   if (MO2.getImm()) {
12675e3ee4b8SRichard Trieu     O << ", " << markup("<imm:") << "#" << formatImm(MO2.getImm() * 4)
12685e3ee4b8SRichard Trieu       << markup(">");
12695e3ee4b8SRichard Trieu   }
12705e3ee4b8SRichard Trieu   O << "]" << markup(">");
12715e3ee4b8SRichard Trieu }
12725e3ee4b8SRichard Trieu 
printT2AddrModeImm8OffsetOperand(const MCInst * MI,unsigned OpNum,const MCSubtargetInfo & STI,raw_ostream & O)12735e3ee4b8SRichard Trieu void ARMInstPrinter::printT2AddrModeImm8OffsetOperand(
12745e3ee4b8SRichard Trieu     const MCInst *MI, unsigned OpNum, const MCSubtargetInfo &STI,
12755e3ee4b8SRichard Trieu     raw_ostream &O) {
12765e3ee4b8SRichard Trieu   const MCOperand &MO1 = MI->getOperand(OpNum);
12775e3ee4b8SRichard Trieu   int32_t OffImm = (int32_t)MO1.getImm();
12785e3ee4b8SRichard Trieu   O << ", " << markup("<imm:");
12795e3ee4b8SRichard Trieu   if (OffImm == INT32_MIN)
12805e3ee4b8SRichard Trieu     O << "#-0";
12815e3ee4b8SRichard Trieu   else if (OffImm < 0)
12825e3ee4b8SRichard Trieu     O << "#-" << -OffImm;
12835e3ee4b8SRichard Trieu   else
12845e3ee4b8SRichard Trieu     O << "#" << OffImm;
12855e3ee4b8SRichard Trieu   O << markup(">");
12865e3ee4b8SRichard Trieu }
12875e3ee4b8SRichard Trieu 
printT2AddrModeImm8s4OffsetOperand(const MCInst * MI,unsigned OpNum,const MCSubtargetInfo & STI,raw_ostream & O)12885e3ee4b8SRichard Trieu void ARMInstPrinter::printT2AddrModeImm8s4OffsetOperand(
12895e3ee4b8SRichard Trieu     const MCInst *MI, unsigned OpNum, const MCSubtargetInfo &STI,
12905e3ee4b8SRichard Trieu     raw_ostream &O) {
12915e3ee4b8SRichard Trieu   const MCOperand &MO1 = MI->getOperand(OpNum);
12925e3ee4b8SRichard Trieu   int32_t OffImm = (int32_t)MO1.getImm();
12935e3ee4b8SRichard Trieu 
12945e3ee4b8SRichard Trieu   assert(((OffImm & 0x3) == 0) && "Not a valid immediate!");
12955e3ee4b8SRichard Trieu 
12965e3ee4b8SRichard Trieu   O << ", " << markup("<imm:");
12975e3ee4b8SRichard Trieu   if (OffImm == INT32_MIN)
12985e3ee4b8SRichard Trieu     O << "#-0";
12995e3ee4b8SRichard Trieu   else if (OffImm < 0)
13005e3ee4b8SRichard Trieu     O << "#-" << -OffImm;
13015e3ee4b8SRichard Trieu   else
13025e3ee4b8SRichard Trieu     O << "#" << OffImm;
13035e3ee4b8SRichard Trieu   O << markup(">");
13045e3ee4b8SRichard Trieu }
13055e3ee4b8SRichard Trieu 
printT2AddrModeSoRegOperand(const MCInst * MI,unsigned OpNum,const MCSubtargetInfo & STI,raw_ostream & O)13065e3ee4b8SRichard Trieu void ARMInstPrinter::printT2AddrModeSoRegOperand(const MCInst *MI,
13075e3ee4b8SRichard Trieu                                                  unsigned OpNum,
13085e3ee4b8SRichard Trieu                                                  const MCSubtargetInfo &STI,
13095e3ee4b8SRichard Trieu                                                  raw_ostream &O) {
13105e3ee4b8SRichard Trieu   const MCOperand &MO1 = MI->getOperand(OpNum);
13115e3ee4b8SRichard Trieu   const MCOperand &MO2 = MI->getOperand(OpNum + 1);
13125e3ee4b8SRichard Trieu   const MCOperand &MO3 = MI->getOperand(OpNum + 2);
13135e3ee4b8SRichard Trieu 
13145e3ee4b8SRichard Trieu   O << markup("<mem:") << "[";
13155e3ee4b8SRichard Trieu   printRegName(O, MO1.getReg());
13165e3ee4b8SRichard Trieu 
13175e3ee4b8SRichard Trieu   assert(MO2.getReg() && "Invalid so_reg load / store address!");
13185e3ee4b8SRichard Trieu   O << ", ";
13195e3ee4b8SRichard Trieu   printRegName(O, MO2.getReg());
13205e3ee4b8SRichard Trieu 
13215e3ee4b8SRichard Trieu   unsigned ShAmt = MO3.getImm();
13225e3ee4b8SRichard Trieu   if (ShAmt) {
13235e3ee4b8SRichard Trieu     assert(ShAmt <= 3 && "Not a valid Thumb2 addressing mode!");
13245e3ee4b8SRichard Trieu     O << ", lsl " << markup("<imm:") << "#" << ShAmt << markup(">");
13255e3ee4b8SRichard Trieu   }
13265e3ee4b8SRichard Trieu   O << "]" << markup(">");
13275e3ee4b8SRichard Trieu }
13285e3ee4b8SRichard Trieu 
printFPImmOperand(const MCInst * MI,unsigned OpNum,const MCSubtargetInfo & STI,raw_ostream & O)13295e3ee4b8SRichard Trieu void ARMInstPrinter::printFPImmOperand(const MCInst *MI, unsigned OpNum,
13305e3ee4b8SRichard Trieu                                        const MCSubtargetInfo &STI,
13315e3ee4b8SRichard Trieu                                        raw_ostream &O) {
13325e3ee4b8SRichard Trieu   const MCOperand &MO = MI->getOperand(OpNum);
13335e3ee4b8SRichard Trieu   O << markup("<imm:") << '#' << ARM_AM::getFPImmFloat(MO.getImm())
13345e3ee4b8SRichard Trieu     << markup(">");
13355e3ee4b8SRichard Trieu }
13365e3ee4b8SRichard Trieu 
printVMOVModImmOperand(const MCInst * MI,unsigned OpNum,const MCSubtargetInfo & STI,raw_ostream & O)1337fdedf240SDavid Green void ARMInstPrinter::printVMOVModImmOperand(const MCInst *MI, unsigned OpNum,
13385e3ee4b8SRichard Trieu                                             const MCSubtargetInfo &STI,
13395e3ee4b8SRichard Trieu                                             raw_ostream &O) {
13405e3ee4b8SRichard Trieu   unsigned EncodedImm = MI->getOperand(OpNum).getImm();
13415e3ee4b8SRichard Trieu   unsigned EltBits;
1342fdedf240SDavid Green   uint64_t Val = ARM_AM::decodeVMOVModImm(EncodedImm, EltBits);
13435e3ee4b8SRichard Trieu   O << markup("<imm:") << "#0x";
13445e3ee4b8SRichard Trieu   O.write_hex(Val);
13455e3ee4b8SRichard Trieu   O << markup(">");
13465e3ee4b8SRichard Trieu }
13475e3ee4b8SRichard Trieu 
printImmPlusOneOperand(const MCInst * MI,unsigned OpNum,const MCSubtargetInfo & STI,raw_ostream & O)13485e3ee4b8SRichard Trieu void ARMInstPrinter::printImmPlusOneOperand(const MCInst *MI, unsigned OpNum,
13495e3ee4b8SRichard Trieu                                             const MCSubtargetInfo &STI,
13505e3ee4b8SRichard Trieu                                             raw_ostream &O) {
13515e3ee4b8SRichard Trieu   unsigned Imm = MI->getOperand(OpNum).getImm();
13525e3ee4b8SRichard Trieu   O << markup("<imm:") << "#" << formatImm(Imm + 1) << markup(">");
13535e3ee4b8SRichard Trieu }
13545e3ee4b8SRichard Trieu 
printRotImmOperand(const MCInst * MI,unsigned OpNum,const MCSubtargetInfo & STI,raw_ostream & O)13555e3ee4b8SRichard Trieu void ARMInstPrinter::printRotImmOperand(const MCInst *MI, unsigned OpNum,
13565e3ee4b8SRichard Trieu                                         const MCSubtargetInfo &STI,
13575e3ee4b8SRichard Trieu                                         raw_ostream &O) {
13585e3ee4b8SRichard Trieu   unsigned Imm = MI->getOperand(OpNum).getImm();
13595e3ee4b8SRichard Trieu   if (Imm == 0)
13605e3ee4b8SRichard Trieu     return;
13615e3ee4b8SRichard Trieu   assert(Imm <= 3 && "illegal ror immediate!");
13625e3ee4b8SRichard Trieu   O << ", ror " << markup("<imm:") << "#" << 8 * Imm << markup(">");
13635e3ee4b8SRichard Trieu }
13645e3ee4b8SRichard Trieu 
printModImmOperand(const MCInst * MI,unsigned OpNum,const MCSubtargetInfo & STI,raw_ostream & O)13655e3ee4b8SRichard Trieu void ARMInstPrinter::printModImmOperand(const MCInst *MI, unsigned OpNum,
13665e3ee4b8SRichard Trieu                                         const MCSubtargetInfo &STI,
13675e3ee4b8SRichard Trieu                                         raw_ostream &O) {
13685e3ee4b8SRichard Trieu   MCOperand Op = MI->getOperand(OpNum);
13695e3ee4b8SRichard Trieu 
13705e3ee4b8SRichard Trieu   // Support for fixups (MCFixup)
13715e3ee4b8SRichard Trieu   if (Op.isExpr())
13725e3ee4b8SRichard Trieu     return printOperand(MI, OpNum, STI, O);
13735e3ee4b8SRichard Trieu 
13745e3ee4b8SRichard Trieu   unsigned Bits = Op.getImm() & 0xFF;
13755e3ee4b8SRichard Trieu   unsigned Rot = (Op.getImm() & 0xF00) >> 7;
13765e3ee4b8SRichard Trieu 
13775e3ee4b8SRichard Trieu   bool PrintUnsigned = false;
13785e3ee4b8SRichard Trieu   switch (MI->getOpcode()) {
13795e3ee4b8SRichard Trieu   case ARM::MOVi:
13805e3ee4b8SRichard Trieu     // Movs to PC should be treated unsigned
13815e3ee4b8SRichard Trieu     PrintUnsigned = (MI->getOperand(OpNum - 1).getReg() == ARM::PC);
13825e3ee4b8SRichard Trieu     break;
13835e3ee4b8SRichard Trieu   case ARM::MSRi:
13845e3ee4b8SRichard Trieu     // Movs to special registers should be treated unsigned
13855e3ee4b8SRichard Trieu     PrintUnsigned = true;
13865e3ee4b8SRichard Trieu     break;
13875e3ee4b8SRichard Trieu   }
13885e3ee4b8SRichard Trieu 
13895e3ee4b8SRichard Trieu   int32_t Rotated = ARM_AM::rotr32(Bits, Rot);
13905e3ee4b8SRichard Trieu   if (ARM_AM::getSOImmVal(Rotated) == Op.getImm()) {
13915e3ee4b8SRichard Trieu     // #rot has the least possible value
13925e3ee4b8SRichard Trieu     O << "#" << markup("<imm:");
13935e3ee4b8SRichard Trieu     if (PrintUnsigned)
13945e3ee4b8SRichard Trieu       O << static_cast<uint32_t>(Rotated);
13955e3ee4b8SRichard Trieu     else
13965e3ee4b8SRichard Trieu       O << Rotated;
13975e3ee4b8SRichard Trieu     O << markup(">");
13985e3ee4b8SRichard Trieu     return;
13995e3ee4b8SRichard Trieu   }
14005e3ee4b8SRichard Trieu 
14015e3ee4b8SRichard Trieu   // Explicit #bits, #rot implied
14025e3ee4b8SRichard Trieu   O << "#" << markup("<imm:") << Bits << markup(">") << ", #" << markup("<imm:")
14035e3ee4b8SRichard Trieu     << Rot << markup(">");
14045e3ee4b8SRichard Trieu }
14055e3ee4b8SRichard Trieu 
printFBits16(const MCInst * MI,unsigned OpNum,const MCSubtargetInfo & STI,raw_ostream & O)14065e3ee4b8SRichard Trieu void ARMInstPrinter::printFBits16(const MCInst *MI, unsigned OpNum,
14075e3ee4b8SRichard Trieu                                   const MCSubtargetInfo &STI, raw_ostream &O) {
14085e3ee4b8SRichard Trieu   O << markup("<imm:") << "#" << 16 - MI->getOperand(OpNum).getImm()
14095e3ee4b8SRichard Trieu     << markup(">");
14105e3ee4b8SRichard Trieu }
14115e3ee4b8SRichard Trieu 
printFBits32(const MCInst * MI,unsigned OpNum,const MCSubtargetInfo & STI,raw_ostream & O)14125e3ee4b8SRichard Trieu void ARMInstPrinter::printFBits32(const MCInst *MI, unsigned OpNum,
14135e3ee4b8SRichard Trieu                                   const MCSubtargetInfo &STI, raw_ostream &O) {
14145e3ee4b8SRichard Trieu   O << markup("<imm:") << "#" << 32 - MI->getOperand(OpNum).getImm()
14155e3ee4b8SRichard Trieu     << markup(">");
14165e3ee4b8SRichard Trieu }
14175e3ee4b8SRichard Trieu 
printVectorIndex(const MCInst * MI,unsigned OpNum,const MCSubtargetInfo & STI,raw_ostream & O)14185e3ee4b8SRichard Trieu void ARMInstPrinter::printVectorIndex(const MCInst *MI, unsigned OpNum,
14195e3ee4b8SRichard Trieu                                       const MCSubtargetInfo &STI,
14205e3ee4b8SRichard Trieu                                       raw_ostream &O) {
14215e3ee4b8SRichard Trieu   O << "[" << MI->getOperand(OpNum).getImm() << "]";
14225e3ee4b8SRichard Trieu }
14235e3ee4b8SRichard Trieu 
printVectorListOne(const MCInst * MI,unsigned OpNum,const MCSubtargetInfo & STI,raw_ostream & O)14245e3ee4b8SRichard Trieu void ARMInstPrinter::printVectorListOne(const MCInst *MI, unsigned OpNum,
14255e3ee4b8SRichard Trieu                                         const MCSubtargetInfo &STI,
14265e3ee4b8SRichard Trieu                                         raw_ostream &O) {
14275e3ee4b8SRichard Trieu   O << "{";
14285e3ee4b8SRichard Trieu   printRegName(O, MI->getOperand(OpNum).getReg());
14295e3ee4b8SRichard Trieu   O << "}";
14305e3ee4b8SRichard Trieu }
14315e3ee4b8SRichard Trieu 
printVectorListTwo(const MCInst * MI,unsigned OpNum,const MCSubtargetInfo & STI,raw_ostream & O)14325e3ee4b8SRichard Trieu void ARMInstPrinter::printVectorListTwo(const MCInst *MI, unsigned OpNum,
14335e3ee4b8SRichard Trieu                                         const MCSubtargetInfo &STI,
14345e3ee4b8SRichard Trieu                                         raw_ostream &O) {
14355e3ee4b8SRichard Trieu   unsigned Reg = MI->getOperand(OpNum).getReg();
14365e3ee4b8SRichard Trieu   unsigned Reg0 = MRI.getSubReg(Reg, ARM::dsub_0);
14375e3ee4b8SRichard Trieu   unsigned Reg1 = MRI.getSubReg(Reg, ARM::dsub_1);
14385e3ee4b8SRichard Trieu   O << "{";
14395e3ee4b8SRichard Trieu   printRegName(O, Reg0);
14405e3ee4b8SRichard Trieu   O << ", ";
14415e3ee4b8SRichard Trieu   printRegName(O, Reg1);
14425e3ee4b8SRichard Trieu   O << "}";
14435e3ee4b8SRichard Trieu }
14445e3ee4b8SRichard Trieu 
printVectorListTwoSpaced(const MCInst * MI,unsigned OpNum,const MCSubtargetInfo & STI,raw_ostream & O)14455e3ee4b8SRichard Trieu void ARMInstPrinter::printVectorListTwoSpaced(const MCInst *MI, unsigned OpNum,
14465e3ee4b8SRichard Trieu                                               const MCSubtargetInfo &STI,
14475e3ee4b8SRichard Trieu                                               raw_ostream &O) {
14485e3ee4b8SRichard Trieu   unsigned Reg = MI->getOperand(OpNum).getReg();
14495e3ee4b8SRichard Trieu   unsigned Reg0 = MRI.getSubReg(Reg, ARM::dsub_0);
14505e3ee4b8SRichard Trieu   unsigned Reg1 = MRI.getSubReg(Reg, ARM::dsub_2);
14515e3ee4b8SRichard Trieu   O << "{";
14525e3ee4b8SRichard Trieu   printRegName(O, Reg0);
14535e3ee4b8SRichard Trieu   O << ", ";
14545e3ee4b8SRichard Trieu   printRegName(O, Reg1);
14555e3ee4b8SRichard Trieu   O << "}";
14565e3ee4b8SRichard Trieu }
14575e3ee4b8SRichard Trieu 
printVectorListThree(const MCInst * MI,unsigned OpNum,const MCSubtargetInfo & STI,raw_ostream & O)14585e3ee4b8SRichard Trieu void ARMInstPrinter::printVectorListThree(const MCInst *MI, unsigned OpNum,
14595e3ee4b8SRichard Trieu                                           const MCSubtargetInfo &STI,
14605e3ee4b8SRichard Trieu                                           raw_ostream &O) {
14615e3ee4b8SRichard Trieu   // Normally, it's not safe to use register enum values directly with
14625e3ee4b8SRichard Trieu   // addition to get the next register, but for VFP registers, the
14635e3ee4b8SRichard Trieu   // sort order is guaranteed because they're all of the form D<n>.
14645e3ee4b8SRichard Trieu   O << "{";
14655e3ee4b8SRichard Trieu   printRegName(O, MI->getOperand(OpNum).getReg());
14665e3ee4b8SRichard Trieu   O << ", ";
14675e3ee4b8SRichard Trieu   printRegName(O, MI->getOperand(OpNum).getReg() + 1);
14685e3ee4b8SRichard Trieu   O << ", ";
14695e3ee4b8SRichard Trieu   printRegName(O, MI->getOperand(OpNum).getReg() + 2);
14705e3ee4b8SRichard Trieu   O << "}";
14715e3ee4b8SRichard Trieu }
14725e3ee4b8SRichard Trieu 
printVectorListFour(const MCInst * MI,unsigned OpNum,const MCSubtargetInfo & STI,raw_ostream & O)14735e3ee4b8SRichard Trieu void ARMInstPrinter::printVectorListFour(const MCInst *MI, unsigned OpNum,
14745e3ee4b8SRichard Trieu                                          const MCSubtargetInfo &STI,
14755e3ee4b8SRichard Trieu                                          raw_ostream &O) {
14765e3ee4b8SRichard Trieu   // Normally, it's not safe to use register enum values directly with
14775e3ee4b8SRichard Trieu   // addition to get the next register, but for VFP registers, the
14785e3ee4b8SRichard Trieu   // sort order is guaranteed because they're all of the form D<n>.
14795e3ee4b8SRichard Trieu   O << "{";
14805e3ee4b8SRichard Trieu   printRegName(O, MI->getOperand(OpNum).getReg());
14815e3ee4b8SRichard Trieu   O << ", ";
14825e3ee4b8SRichard Trieu   printRegName(O, MI->getOperand(OpNum).getReg() + 1);
14835e3ee4b8SRichard Trieu   O << ", ";
14845e3ee4b8SRichard Trieu   printRegName(O, MI->getOperand(OpNum).getReg() + 2);
14855e3ee4b8SRichard Trieu   O << ", ";
14865e3ee4b8SRichard Trieu   printRegName(O, MI->getOperand(OpNum).getReg() + 3);
14875e3ee4b8SRichard Trieu   O << "}";
14885e3ee4b8SRichard Trieu }
14895e3ee4b8SRichard Trieu 
printVectorListOneAllLanes(const MCInst * MI,unsigned OpNum,const MCSubtargetInfo & STI,raw_ostream & O)14905e3ee4b8SRichard Trieu void ARMInstPrinter::printVectorListOneAllLanes(const MCInst *MI,
14915e3ee4b8SRichard Trieu                                                 unsigned OpNum,
14925e3ee4b8SRichard Trieu                                                 const MCSubtargetInfo &STI,
14935e3ee4b8SRichard Trieu                                                 raw_ostream &O) {
14945e3ee4b8SRichard Trieu   O << "{";
14955e3ee4b8SRichard Trieu   printRegName(O, MI->getOperand(OpNum).getReg());
14965e3ee4b8SRichard Trieu   O << "[]}";
14975e3ee4b8SRichard Trieu }
14985e3ee4b8SRichard Trieu 
printVectorListTwoAllLanes(const MCInst * MI,unsigned OpNum,const MCSubtargetInfo & STI,raw_ostream & O)14995e3ee4b8SRichard Trieu void ARMInstPrinter::printVectorListTwoAllLanes(const MCInst *MI,
15005e3ee4b8SRichard Trieu                                                 unsigned OpNum,
15015e3ee4b8SRichard Trieu                                                 const MCSubtargetInfo &STI,
15025e3ee4b8SRichard Trieu                                                 raw_ostream &O) {
15035e3ee4b8SRichard Trieu   unsigned Reg = MI->getOperand(OpNum).getReg();
15045e3ee4b8SRichard Trieu   unsigned Reg0 = MRI.getSubReg(Reg, ARM::dsub_0);
15055e3ee4b8SRichard Trieu   unsigned Reg1 = MRI.getSubReg(Reg, ARM::dsub_1);
15065e3ee4b8SRichard Trieu   O << "{";
15075e3ee4b8SRichard Trieu   printRegName(O, Reg0);
15085e3ee4b8SRichard Trieu   O << "[], ";
15095e3ee4b8SRichard Trieu   printRegName(O, Reg1);
15105e3ee4b8SRichard Trieu   O << "[]}";
15115e3ee4b8SRichard Trieu }
15125e3ee4b8SRichard Trieu 
printVectorListThreeAllLanes(const MCInst * MI,unsigned OpNum,const MCSubtargetInfo & STI,raw_ostream & O)15135e3ee4b8SRichard Trieu void ARMInstPrinter::printVectorListThreeAllLanes(const MCInst *MI,
15145e3ee4b8SRichard Trieu                                                   unsigned OpNum,
15155e3ee4b8SRichard Trieu                                                   const MCSubtargetInfo &STI,
15165e3ee4b8SRichard Trieu                                                   raw_ostream &O) {
15175e3ee4b8SRichard Trieu   // Normally, it's not safe to use register enum values directly with
15185e3ee4b8SRichard Trieu   // addition to get the next register, but for VFP registers, the
15195e3ee4b8SRichard Trieu   // sort order is guaranteed because they're all of the form D<n>.
15205e3ee4b8SRichard Trieu   O << "{";
15215e3ee4b8SRichard Trieu   printRegName(O, MI->getOperand(OpNum).getReg());
15225e3ee4b8SRichard Trieu   O << "[], ";
15235e3ee4b8SRichard Trieu   printRegName(O, MI->getOperand(OpNum).getReg() + 1);
15245e3ee4b8SRichard Trieu   O << "[], ";
15255e3ee4b8SRichard Trieu   printRegName(O, MI->getOperand(OpNum).getReg() + 2);
15265e3ee4b8SRichard Trieu   O << "[]}";
15275e3ee4b8SRichard Trieu }
15285e3ee4b8SRichard Trieu 
printVectorListFourAllLanes(const MCInst * MI,unsigned OpNum,const MCSubtargetInfo & STI,raw_ostream & O)15295e3ee4b8SRichard Trieu void ARMInstPrinter::printVectorListFourAllLanes(const MCInst *MI,
15305e3ee4b8SRichard Trieu                                                  unsigned OpNum,
15315e3ee4b8SRichard Trieu                                                  const MCSubtargetInfo &STI,
15325e3ee4b8SRichard Trieu                                                  raw_ostream &O) {
15335e3ee4b8SRichard Trieu   // Normally, it's not safe to use register enum values directly with
15345e3ee4b8SRichard Trieu   // addition to get the next register, but for VFP registers, the
15355e3ee4b8SRichard Trieu   // sort order is guaranteed because they're all of the form D<n>.
15365e3ee4b8SRichard Trieu   O << "{";
15375e3ee4b8SRichard Trieu   printRegName(O, MI->getOperand(OpNum).getReg());
15385e3ee4b8SRichard Trieu   O << "[], ";
15395e3ee4b8SRichard Trieu   printRegName(O, MI->getOperand(OpNum).getReg() + 1);
15405e3ee4b8SRichard Trieu   O << "[], ";
15415e3ee4b8SRichard Trieu   printRegName(O, MI->getOperand(OpNum).getReg() + 2);
15425e3ee4b8SRichard Trieu   O << "[], ";
15435e3ee4b8SRichard Trieu   printRegName(O, MI->getOperand(OpNum).getReg() + 3);
15445e3ee4b8SRichard Trieu   O << "[]}";
15455e3ee4b8SRichard Trieu }
15465e3ee4b8SRichard Trieu 
printVectorListTwoSpacedAllLanes(const MCInst * MI,unsigned OpNum,const MCSubtargetInfo & STI,raw_ostream & O)15475e3ee4b8SRichard Trieu void ARMInstPrinter::printVectorListTwoSpacedAllLanes(
15485e3ee4b8SRichard Trieu     const MCInst *MI, unsigned OpNum, const MCSubtargetInfo &STI,
15495e3ee4b8SRichard Trieu     raw_ostream &O) {
15505e3ee4b8SRichard Trieu   unsigned Reg = MI->getOperand(OpNum).getReg();
15515e3ee4b8SRichard Trieu   unsigned Reg0 = MRI.getSubReg(Reg, ARM::dsub_0);
15525e3ee4b8SRichard Trieu   unsigned Reg1 = MRI.getSubReg(Reg, ARM::dsub_2);
15535e3ee4b8SRichard Trieu   O << "{";
15545e3ee4b8SRichard Trieu   printRegName(O, Reg0);
15555e3ee4b8SRichard Trieu   O << "[], ";
15565e3ee4b8SRichard Trieu   printRegName(O, Reg1);
15575e3ee4b8SRichard Trieu   O << "[]}";
15585e3ee4b8SRichard Trieu }
15595e3ee4b8SRichard Trieu 
printVectorListThreeSpacedAllLanes(const MCInst * MI,unsigned OpNum,const MCSubtargetInfo & STI,raw_ostream & O)15605e3ee4b8SRichard Trieu void ARMInstPrinter::printVectorListThreeSpacedAllLanes(
15615e3ee4b8SRichard Trieu     const MCInst *MI, unsigned OpNum, const MCSubtargetInfo &STI,
15625e3ee4b8SRichard Trieu     raw_ostream &O) {
15635e3ee4b8SRichard Trieu   // Normally, it's not safe to use register enum values directly with
15645e3ee4b8SRichard Trieu   // addition to get the next register, but for VFP registers, the
15655e3ee4b8SRichard Trieu   // sort order is guaranteed because they're all of the form D<n>.
15665e3ee4b8SRichard Trieu   O << "{";
15675e3ee4b8SRichard Trieu   printRegName(O, MI->getOperand(OpNum).getReg());
15685e3ee4b8SRichard Trieu   O << "[], ";
15695e3ee4b8SRichard Trieu   printRegName(O, MI->getOperand(OpNum).getReg() + 2);
15705e3ee4b8SRichard Trieu   O << "[], ";
15715e3ee4b8SRichard Trieu   printRegName(O, MI->getOperand(OpNum).getReg() + 4);
15725e3ee4b8SRichard Trieu   O << "[]}";
15735e3ee4b8SRichard Trieu }
15745e3ee4b8SRichard Trieu 
printVectorListFourSpacedAllLanes(const MCInst * MI,unsigned OpNum,const MCSubtargetInfo & STI,raw_ostream & O)15755e3ee4b8SRichard Trieu void ARMInstPrinter::printVectorListFourSpacedAllLanes(
15765e3ee4b8SRichard Trieu     const MCInst *MI, unsigned OpNum, const MCSubtargetInfo &STI,
15775e3ee4b8SRichard Trieu     raw_ostream &O) {
15785e3ee4b8SRichard Trieu   // Normally, it's not safe to use register enum values directly with
15795e3ee4b8SRichard Trieu   // addition to get the next register, but for VFP registers, the
15805e3ee4b8SRichard Trieu   // sort order is guaranteed because they're all of the form D<n>.
15815e3ee4b8SRichard Trieu   O << "{";
15825e3ee4b8SRichard Trieu   printRegName(O, MI->getOperand(OpNum).getReg());
15835e3ee4b8SRichard Trieu   O << "[], ";
15845e3ee4b8SRichard Trieu   printRegName(O, MI->getOperand(OpNum).getReg() + 2);
15855e3ee4b8SRichard Trieu   O << "[], ";
15865e3ee4b8SRichard Trieu   printRegName(O, MI->getOperand(OpNum).getReg() + 4);
15875e3ee4b8SRichard Trieu   O << "[], ";
15885e3ee4b8SRichard Trieu   printRegName(O, MI->getOperand(OpNum).getReg() + 6);
15895e3ee4b8SRichard Trieu   O << "[]}";
15905e3ee4b8SRichard Trieu }
15915e3ee4b8SRichard Trieu 
printVectorListThreeSpaced(const MCInst * MI,unsigned OpNum,const MCSubtargetInfo & STI,raw_ostream & O)15925e3ee4b8SRichard Trieu void ARMInstPrinter::printVectorListThreeSpaced(const MCInst *MI,
15935e3ee4b8SRichard Trieu                                                 unsigned OpNum,
15945e3ee4b8SRichard Trieu                                                 const MCSubtargetInfo &STI,
15955e3ee4b8SRichard Trieu                                                 raw_ostream &O) {
15965e3ee4b8SRichard Trieu   // Normally, it's not safe to use register enum values directly with
15975e3ee4b8SRichard Trieu   // addition to get the next register, but for VFP registers, the
15985e3ee4b8SRichard Trieu   // sort order is guaranteed because they're all of the form D<n>.
15995e3ee4b8SRichard Trieu   O << "{";
16005e3ee4b8SRichard Trieu   printRegName(O, MI->getOperand(OpNum).getReg());
16015e3ee4b8SRichard Trieu   O << ", ";
16025e3ee4b8SRichard Trieu   printRegName(O, MI->getOperand(OpNum).getReg() + 2);
16035e3ee4b8SRichard Trieu   O << ", ";
16045e3ee4b8SRichard Trieu   printRegName(O, MI->getOperand(OpNum).getReg() + 4);
16055e3ee4b8SRichard Trieu   O << "}";
16065e3ee4b8SRichard Trieu }
16075e3ee4b8SRichard Trieu 
printVectorListFourSpaced(const MCInst * MI,unsigned OpNum,const MCSubtargetInfo & STI,raw_ostream & O)16085e3ee4b8SRichard Trieu void ARMInstPrinter::printVectorListFourSpaced(const MCInst *MI, unsigned OpNum,
16095e3ee4b8SRichard Trieu                                                const MCSubtargetInfo &STI,
16105e3ee4b8SRichard Trieu                                                raw_ostream &O) {
16115e3ee4b8SRichard Trieu   // Normally, it's not safe to use register enum values directly with
16125e3ee4b8SRichard Trieu   // addition to get the next register, but for VFP registers, the
16135e3ee4b8SRichard Trieu   // sort order is guaranteed because they're all of the form D<n>.
16145e3ee4b8SRichard Trieu   O << "{";
16155e3ee4b8SRichard Trieu   printRegName(O, MI->getOperand(OpNum).getReg());
16165e3ee4b8SRichard Trieu   O << ", ";
16175e3ee4b8SRichard Trieu   printRegName(O, MI->getOperand(OpNum).getReg() + 2);
16185e3ee4b8SRichard Trieu   O << ", ";
16195e3ee4b8SRichard Trieu   printRegName(O, MI->getOperand(OpNum).getReg() + 4);
16205e3ee4b8SRichard Trieu   O << ", ";
16215e3ee4b8SRichard Trieu   printRegName(O, MI->getOperand(OpNum).getReg() + 6);
16225e3ee4b8SRichard Trieu   O << "}";
16235e3ee4b8SRichard Trieu }
16245e3ee4b8SRichard Trieu 
1625fe801762SSimon Tatham template<unsigned NumRegs>
printMVEVectorList(const MCInst * MI,unsigned OpNum,const MCSubtargetInfo & STI,raw_ostream & O)1626fe801762SSimon Tatham void ARMInstPrinter::printMVEVectorList(const MCInst *MI, unsigned OpNum,
1627fe801762SSimon Tatham                                         const MCSubtargetInfo &STI,
1628fe801762SSimon Tatham                                         raw_ostream &O) {
1629fe801762SSimon Tatham   unsigned Reg = MI->getOperand(OpNum).getReg();
1630fe801762SSimon Tatham   const char *Prefix = "{";
1631fe801762SSimon Tatham   for (unsigned i = 0; i < NumRegs; i++) {
1632fe801762SSimon Tatham     O << Prefix;
1633fe801762SSimon Tatham     printRegName(O, MRI.getSubReg(Reg, ARM::qsub_0 + i));
1634fe801762SSimon Tatham     Prefix = ", ";
1635fe801762SSimon Tatham   }
1636fe801762SSimon Tatham   O << "}";
1637fe801762SSimon Tatham }
1638fe801762SSimon Tatham 
16395e3ee4b8SRichard Trieu template<int64_t Angle, int64_t Remainder>
printComplexRotationOp(const MCInst * MI,unsigned OpNo,const MCSubtargetInfo & STI,raw_ostream & O)16405e3ee4b8SRichard Trieu void ARMInstPrinter::printComplexRotationOp(const MCInst *MI, unsigned OpNo,
16415e3ee4b8SRichard Trieu                                             const MCSubtargetInfo &STI,
16425e3ee4b8SRichard Trieu                                             raw_ostream &O) {
16435e3ee4b8SRichard Trieu   unsigned Val = MI->getOperand(OpNo).getImm();
16445e3ee4b8SRichard Trieu   O << "#" << (Val * Angle) + Remainder;
16455e3ee4b8SRichard Trieu }
16465e3ee4b8SRichard Trieu 
printVPTPredicateOperand(const MCInst * MI,unsigned OpNum,const MCSubtargetInfo & STI,raw_ostream & O)1647286e1d2cSSimon Tatham void ARMInstPrinter::printVPTPredicateOperand(const MCInst *MI, unsigned OpNum,
1648286e1d2cSSimon Tatham                                               const MCSubtargetInfo &STI,
1649286e1d2cSSimon Tatham                                               raw_ostream &O) {
1650286e1d2cSSimon Tatham   ARMVCC::VPTCodes CC = (ARMVCC::VPTCodes)MI->getOperand(OpNum).getImm();
1651286e1d2cSSimon Tatham   if (CC != ARMVCC::None)
1652286e1d2cSSimon Tatham     O << ARMVPTPredToString(CC);
1653286e1d2cSSimon Tatham }
1654286e1d2cSSimon Tatham 
printVPTMask(const MCInst * MI,unsigned OpNum,const MCSubtargetInfo & STI,raw_ostream & O)1655286e1d2cSSimon Tatham void ARMInstPrinter::printVPTMask(const MCInst *MI, unsigned OpNum,
1656286e1d2cSSimon Tatham                                   const MCSubtargetInfo &STI,
1657286e1d2cSSimon Tatham                                   raw_ostream &O) {
1658286e1d2cSSimon Tatham   // (3 - the number of trailing zeroes) is the number of them / else.
1659286e1d2cSSimon Tatham   unsigned Mask = MI->getOperand(OpNum).getImm();
1660286e1d2cSSimon Tatham   unsigned NumTZ = countTrailingZeros(Mask);
1661286e1d2cSSimon Tatham   assert(NumTZ <= 3 && "Invalid VPT mask!");
1662286e1d2cSSimon Tatham   for (unsigned Pos = 3, e = NumTZ; Pos > e; --Pos) {
1663286e1d2cSSimon Tatham     bool T = ((Mask >> Pos) & 1) == 0;
1664286e1d2cSSimon Tatham     if (T)
1665286e1d2cSSimon Tatham       O << 't';
1666286e1d2cSSimon Tatham     else
1667286e1d2cSSimon Tatham       O << 'e';
1668286e1d2cSSimon Tatham   }
1669286e1d2cSSimon Tatham }
1670286e1d2cSSimon Tatham 
printMveSaturateOp(const MCInst * MI,unsigned OpNum,const MCSubtargetInfo & STI,raw_ostream & O)16710b001f94SMikhail Maltsev void ARMInstPrinter::printMveSaturateOp(const MCInst *MI, unsigned OpNum,
16720b001f94SMikhail Maltsev                                         const MCSubtargetInfo &STI,
16730b001f94SMikhail Maltsev                                         raw_ostream &O) {
16740b001f94SMikhail Maltsev   uint32_t Val = MI->getOperand(OpNum).getImm();
16750b001f94SMikhail Maltsev   assert(Val <= 1 && "Invalid MVE saturate operand");
16760b001f94SMikhail Maltsev   O << "#" << (Val == 1 ? 48 : 64);
16770b001f94SMikhail Maltsev }
1678