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 "MCTargetDesc/RISCVMCExpr.h" 15 #include "Utils/RISCVBaseInfo.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 static cl::opt<bool> 43 ArchRegNames("riscv-arch-reg-names", 44 cl::desc("Print architectural register names rather than the " 45 "ABI names (such as x2 instead of sp)"), 46 cl::init(false), cl::Hidden); 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 NoAliases = true; 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, raw_ostream &O, 67 StringRef Annot, const MCSubtargetInfo &STI) { 68 bool Res = false; 69 const MCInst *NewMI = MI; 70 MCInst UncompressedMI; 71 if (!NoAliases) 72 Res = uncompressInst(UncompressedMI, *MI, MRI, STI); 73 if (Res) 74 NewMI = const_cast<MCInst *>(&UncompressedMI); 75 if (NoAliases || !printAliasInstr(NewMI, STI, O)) 76 printInstruction(NewMI, STI, O); 77 printAnnotation(O, Annot); 78 } 79 80 void RISCVInstPrinter::printRegName(raw_ostream &O, unsigned RegNo) const { 81 O << getRegisterName(RegNo); 82 } 83 84 void RISCVInstPrinter::printOperand(const MCInst *MI, unsigned OpNo, 85 const MCSubtargetInfo &STI, raw_ostream &O, 86 const char *Modifier) { 87 assert((Modifier == 0 || Modifier[0] == 0) && "No modifiers supported"); 88 const MCOperand &MO = MI->getOperand(OpNo); 89 90 if (MO.isReg()) { 91 printRegName(O, MO.getReg()); 92 return; 93 } 94 95 if (MO.isImm()) { 96 O << MO.getImm(); 97 return; 98 } 99 100 assert(MO.isExpr() && "Unknown operand kind in printOperand"); 101 MO.getExpr()->print(O, &MAI); 102 } 103 104 void RISCVInstPrinter::printCSRSystemRegister(const MCInst *MI, unsigned OpNo, 105 const MCSubtargetInfo &STI, 106 raw_ostream &O) { 107 unsigned Imm = MI->getOperand(OpNo).getImm(); 108 auto SysReg = RISCVSysReg::lookupSysRegByEncoding(Imm); 109 if (SysReg && SysReg->haveRequiredFeatures(STI.getFeatureBits())) 110 O << SysReg->Name; 111 else 112 O << Imm; 113 } 114 115 void RISCVInstPrinter::printFenceArg(const MCInst *MI, unsigned OpNo, 116 const MCSubtargetInfo &STI, 117 raw_ostream &O) { 118 unsigned FenceArg = MI->getOperand(OpNo).getImm(); 119 assert (((FenceArg >> 4) == 0) && "Invalid immediate in printFenceArg"); 120 121 if ((FenceArg & RISCVFenceField::I) != 0) 122 O << 'i'; 123 if ((FenceArg & RISCVFenceField::O) != 0) 124 O << 'o'; 125 if ((FenceArg & RISCVFenceField::R) != 0) 126 O << 'r'; 127 if ((FenceArg & RISCVFenceField::W) != 0) 128 O << 'w'; 129 if (FenceArg == 0) 130 O << "unknown"; 131 } 132 133 void RISCVInstPrinter::printFRMArg(const MCInst *MI, unsigned OpNo, 134 const MCSubtargetInfo &STI, raw_ostream &O) { 135 auto FRMArg = 136 static_cast<RISCVFPRndMode::RoundingMode>(MI->getOperand(OpNo).getImm()); 137 O << RISCVFPRndMode::roundingModeToString(FRMArg); 138 } 139 140 void RISCVInstPrinter::printAtomicMemOp(const MCInst *MI, unsigned OpNo, 141 const MCSubtargetInfo &STI, 142 raw_ostream &O) { 143 const MCOperand &MO = MI->getOperand(OpNo); 144 145 assert(MO.isReg() && "printAtomicMemOp can only print register operands"); 146 O << "("; 147 printRegName(O, MO.getReg()); 148 O << ")"; 149 return; 150 } 151 152 const char *RISCVInstPrinter::getRegisterName(unsigned RegNo) { 153 return getRegisterName(RegNo, ArchRegNames ? RISCV::NoRegAltName 154 : RISCV::ABIRegAltName); 155 } 156