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