1 //===-- RISCVInstPrinter.cpp - Convert RISCV MCInst to asm syntax ---------===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 // 9 // This class prints an RISCV MCInst to a .s file. 10 // 11 //===----------------------------------------------------------------------===// 12 13 #include "RISCVInstPrinter.h" 14 #include "RISCVBaseInfo.h" 15 #include "RISCVMCExpr.h" 16 #include "llvm/MC/MCAsmInfo.h" 17 #include "llvm/MC/MCExpr.h" 18 #include "llvm/MC/MCInst.h" 19 #include "llvm/MC/MCRegisterInfo.h" 20 #include "llvm/MC/MCSubtargetInfo.h" 21 #include "llvm/MC/MCSymbol.h" 22 #include "llvm/Support/CommandLine.h" 23 #include "llvm/Support/ErrorHandling.h" 24 #include "llvm/Support/FormattedStream.h" 25 using namespace llvm; 26 27 #define DEBUG_TYPE "asm-printer" 28 29 // Include the auto-generated portion of the assembly writer. 30 #define PRINT_ALIAS_INSTR 31 #include "RISCVGenAsmWriter.inc" 32 33 // Include the auto-generated portion of the compress emitter. 34 #define GEN_UNCOMPRESS_INSTR 35 #include "RISCVGenCompressInstEmitter.inc" 36 37 static cl::opt<bool> 38 NoAliases("riscv-no-aliases", 39 cl::desc("Disable the emission of assembler pseudo instructions"), 40 cl::init(false), cl::Hidden); 41 42 // Print architectural register names rather than the ABI names (such as x2 43 // instead of sp). 44 // TODO: Make RISCVInstPrinter::getRegisterName non-static so that this can a 45 // member. 46 static bool ArchRegNames; 47 48 // The command-line flags above are used by llvm-mc and llc. They can be used by 49 // `llvm-objdump`, but we override their values here to handle options passed to 50 // `llvm-objdump` with `-M` (which matches GNU objdump). There did not seem to 51 // be an easier way to allow these options in all these tools, without doing it 52 // this way. 53 bool RISCVInstPrinter::applyTargetSpecificCLOption(StringRef Opt) { 54 if (Opt == "no-aliases") { 55 PrintAliases = false; 56 return true; 57 } 58 if (Opt == "numeric") { 59 ArchRegNames = true; 60 return true; 61 } 62 63 return false; 64 } 65 66 void RISCVInstPrinter::printInst(const MCInst *MI, uint64_t Address, 67 StringRef Annot, const MCSubtargetInfo &STI, 68 raw_ostream &O) { 69 bool Res = false; 70 const MCInst *NewMI = MI; 71 MCInst UncompressedMI; 72 if (PrintAliases && !NoAliases) 73 Res = uncompressInst(UncompressedMI, *MI, MRI, STI); 74 if (Res) 75 NewMI = const_cast<MCInst *>(&UncompressedMI); 76 if (!PrintAliases || NoAliases || !printAliasInstr(NewMI, Address, STI, O)) 77 printInstruction(NewMI, Address, STI, O); 78 printAnnotation(O, Annot); 79 } 80 81 void RISCVInstPrinter::printRegName(raw_ostream &O, unsigned RegNo) const { 82 O << getRegisterName(RegNo); 83 } 84 85 void RISCVInstPrinter::printOperand(const MCInst *MI, unsigned OpNo, 86 const MCSubtargetInfo &STI, raw_ostream &O, 87 const char *Modifier) { 88 assert((Modifier == 0 || Modifier[0] == 0) && "No modifiers supported"); 89 const MCOperand &MO = MI->getOperand(OpNo); 90 91 if (MO.isReg()) { 92 printRegName(O, MO.getReg()); 93 return; 94 } 95 96 if (MO.isImm()) { 97 O << MO.getImm(); 98 return; 99 } 100 101 assert(MO.isExpr() && "Unknown operand kind in printOperand"); 102 MO.getExpr()->print(O, &MAI); 103 } 104 105 void RISCVInstPrinter::printBranchOperand(const MCInst *MI, uint64_t Address, 106 unsigned OpNo, 107 const MCSubtargetInfo &STI, 108 raw_ostream &O) { 109 const MCOperand &MO = MI->getOperand(OpNo); 110 if (!MO.isImm()) 111 return printOperand(MI, OpNo, STI, O); 112 113 if (PrintBranchImmAsAddress) { 114 uint64_t Target = Address + MO.getImm(); 115 if (!STI.hasFeature(RISCV::Feature64Bit)) 116 Target &= 0xffffffff; 117 O << formatHex(Target); 118 } else { 119 O << MO.getImm(); 120 } 121 } 122 123 void RISCVInstPrinter::printCSRSystemRegister(const MCInst *MI, unsigned OpNo, 124 const MCSubtargetInfo &STI, 125 raw_ostream &O) { 126 unsigned Imm = MI->getOperand(OpNo).getImm(); 127 auto SysReg = RISCVSysReg::lookupSysRegByEncoding(Imm); 128 if (SysReg && SysReg->haveRequiredFeatures(STI.getFeatureBits())) 129 O << SysReg->Name; 130 else 131 O << Imm; 132 } 133 134 void RISCVInstPrinter::printFenceArg(const MCInst *MI, unsigned OpNo, 135 const MCSubtargetInfo &STI, 136 raw_ostream &O) { 137 unsigned FenceArg = MI->getOperand(OpNo).getImm(); 138 assert (((FenceArg >> 4) == 0) && "Invalid immediate in printFenceArg"); 139 140 if ((FenceArg & RISCVFenceField::I) != 0) 141 O << 'i'; 142 if ((FenceArg & RISCVFenceField::O) != 0) 143 O << 'o'; 144 if ((FenceArg & RISCVFenceField::R) != 0) 145 O << 'r'; 146 if ((FenceArg & RISCVFenceField::W) != 0) 147 O << 'w'; 148 if (FenceArg == 0) 149 O << "unknown"; 150 } 151 152 void RISCVInstPrinter::printFRMArg(const MCInst *MI, unsigned OpNo, 153 const MCSubtargetInfo &STI, raw_ostream &O) { 154 auto FRMArg = 155 static_cast<RISCVFPRndMode::RoundingMode>(MI->getOperand(OpNo).getImm()); 156 O << RISCVFPRndMode::roundingModeToString(FRMArg); 157 } 158 159 void RISCVInstPrinter::printAtomicMemOp(const MCInst *MI, unsigned OpNo, 160 const MCSubtargetInfo &STI, 161 raw_ostream &O) { 162 const MCOperand &MO = MI->getOperand(OpNo); 163 164 assert(MO.isReg() && "printAtomicMemOp can only print register operands"); 165 O << "("; 166 printRegName(O, MO.getReg()); 167 O << ")"; 168 } 169 170 void RISCVInstPrinter::printVTypeI(const MCInst *MI, unsigned OpNo, 171 const MCSubtargetInfo &STI, raw_ostream &O) { 172 unsigned Imm = MI->getOperand(OpNo).getImm(); 173 RISCVVType::printVType(Imm, O); 174 } 175 176 void RISCVInstPrinter::printVMaskReg(const MCInst *MI, unsigned OpNo, 177 const MCSubtargetInfo &STI, 178 raw_ostream &O) { 179 const MCOperand &MO = MI->getOperand(OpNo); 180 181 assert(MO.isReg() && "printVMaskReg can only print register operands"); 182 if (MO.getReg() == RISCV::NoRegister) 183 return; 184 O << ", "; 185 printRegName(O, MO.getReg()); 186 O << ".t"; 187 } 188 189 const char *RISCVInstPrinter::getRegisterName(unsigned RegNo) { 190 return getRegisterName(RegNo, ArchRegNames ? RISCV::NoRegAltName 191 : RISCV::ABIRegAltName); 192 } 193