1 //===-- RISCVInstPrinter.cpp - Convert RISC-V 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 RISC-V 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/MCInstPrinter.h" 20 #include "llvm/MC/MCRegisterInfo.h" 21 #include "llvm/MC/MCSubtargetInfo.h" 22 #include "llvm/MC/MCSymbol.h" 23 #include "llvm/Support/CommandLine.h" 24 #include "llvm/Support/ErrorHandling.h" 25 #include "llvm/Support/FormattedStream.h" 26 using namespace llvm; 27 28 #define DEBUG_TYPE "asm-printer" 29 30 // Include the auto-generated portion of the assembly writer. 31 #define PRINT_ALIAS_INSTR 32 #include "RISCVGenAsmWriter.inc" 33 34 static cl::opt<bool> 35 NoAliases("riscv-no-aliases", 36 cl::desc("Disable the emission of assembler pseudo instructions"), 37 cl::init(false), cl::Hidden); 38 39 // Print architectural register names rather than the ABI names (such as x2 40 // instead of sp). 41 // TODO: Make RISCVInstPrinter::getRegisterName non-static so that this can a 42 // member. 43 static bool ArchRegNames; 44 45 // The command-line flags above are used by llvm-mc and llc. They can be used by 46 // `llvm-objdump`, but we override their values here to handle options passed to 47 // `llvm-objdump` with `-M` (which matches GNU objdump). There did not seem to 48 // be an easier way to allow these options in all these tools, without doing it 49 // this way. 50 bool RISCVInstPrinter::applyTargetSpecificCLOption(StringRef Opt) { 51 if (Opt == "no-aliases") { 52 PrintAliases = false; 53 return true; 54 } 55 if (Opt == "numeric") { 56 ArchRegNames = true; 57 return true; 58 } 59 60 return false; 61 } 62 63 void RISCVInstPrinter::printInst(const MCInst *MI, uint64_t Address, 64 StringRef Annot, const MCSubtargetInfo &STI, 65 raw_ostream &O) { 66 bool Res = false; 67 const MCInst *NewMI = MI; 68 MCInst UncompressedMI; 69 if (PrintAliases && !NoAliases) 70 Res = RISCVRVC::uncompress(UncompressedMI, *MI, STI); 71 if (Res) 72 NewMI = const_cast<MCInst *>(&UncompressedMI); 73 if (!PrintAliases || NoAliases || !printAliasInstr(NewMI, Address, STI, O)) 74 printInstruction(NewMI, Address, STI, O); 75 printAnnotation(O, Annot); 76 } 77 78 void RISCVInstPrinter::printRegName(raw_ostream &O, MCRegister Reg) const { 79 markup(O, Markup::Register) << getRegisterName(Reg); 80 } 81 82 void RISCVInstPrinter::printOperand(const MCInst *MI, unsigned OpNo, 83 const MCSubtargetInfo &STI, raw_ostream &O, 84 const char *Modifier) { 85 assert((Modifier == nullptr || Modifier[0] == 0) && "No modifiers supported"); 86 const MCOperand &MO = MI->getOperand(OpNo); 87 88 if (MO.isReg()) { 89 printRegName(O, MO.getReg()); 90 return; 91 } 92 93 if (MO.isImm()) { 94 markup(O, Markup::Immediate) << formatImm(MO.getImm()); 95 return; 96 } 97 98 assert(MO.isExpr() && "Unknown operand kind in printOperand"); 99 MO.getExpr()->print(O, &MAI); 100 } 101 102 void RISCVInstPrinter::printBranchOperand(const MCInst *MI, uint64_t Address, 103 unsigned OpNo, 104 const MCSubtargetInfo &STI, 105 raw_ostream &O) { 106 const MCOperand &MO = MI->getOperand(OpNo); 107 if (!MO.isImm()) 108 return printOperand(MI, OpNo, STI, O); 109 110 if (PrintBranchImmAsAddress) { 111 uint64_t Target = Address + MO.getImm(); 112 if (!STI.hasFeature(RISCV::Feature64Bit)) 113 Target &= 0xffffffff; 114 markup(O, Markup::Target) << formatHex(Target); 115 } else { 116 markup(O, Markup::Target) << formatImm(MO.getImm()); 117 } 118 } 119 120 void RISCVInstPrinter::printCSRSystemRegister(const MCInst *MI, unsigned OpNo, 121 const MCSubtargetInfo &STI, 122 raw_ostream &O) { 123 unsigned Imm = MI->getOperand(OpNo).getImm(); 124 auto SysReg = RISCVSysReg::lookupSysRegByEncoding(Imm); 125 if (SysReg && SysReg->haveRequiredFeatures(STI.getFeatureBits())) 126 markup(O, Markup::Register) << SysReg->Name; 127 else 128 markup(O, Markup::Register) << formatImm(Imm); 129 } 130 131 void RISCVInstPrinter::printFenceArg(const MCInst *MI, unsigned OpNo, 132 const MCSubtargetInfo &STI, 133 raw_ostream &O) { 134 unsigned FenceArg = MI->getOperand(OpNo).getImm(); 135 assert (((FenceArg >> 4) == 0) && "Invalid immediate in printFenceArg"); 136 137 if ((FenceArg & RISCVFenceField::I) != 0) 138 O << 'i'; 139 if ((FenceArg & RISCVFenceField::O) != 0) 140 O << 'o'; 141 if ((FenceArg & RISCVFenceField::R) != 0) 142 O << 'r'; 143 if ((FenceArg & RISCVFenceField::W) != 0) 144 O << 'w'; 145 if (FenceArg == 0) 146 O << "0"; 147 } 148 149 void RISCVInstPrinter::printFRMArg(const MCInst *MI, unsigned OpNo, 150 const MCSubtargetInfo &STI, raw_ostream &O) { 151 auto FRMArg = 152 static_cast<RISCVFPRndMode::RoundingMode>(MI->getOperand(OpNo).getImm()); 153 if (PrintAliases && !NoAliases && FRMArg == RISCVFPRndMode::RoundingMode::DYN) 154 return; 155 O << ", " << RISCVFPRndMode::roundingModeToString(FRMArg); 156 } 157 158 void RISCVInstPrinter::printFRMArgLegacy(const MCInst *MI, unsigned OpNo, 159 const MCSubtargetInfo &STI, 160 raw_ostream &O) { 161 auto FRMArg = 162 static_cast<RISCVFPRndMode::RoundingMode>(MI->getOperand(OpNo).getImm()); 163 // Never print rounding mode if it's the default 'rne'. This ensures the 164 // output can still be parsed by older tools that erroneously failed to 165 // accept a rounding mode. 166 if (FRMArg == RISCVFPRndMode::RoundingMode::RNE) 167 return; 168 O << ", " << RISCVFPRndMode::roundingModeToString(FRMArg); 169 } 170 171 void RISCVInstPrinter::printFPImmOperand(const MCInst *MI, unsigned OpNo, 172 const MCSubtargetInfo &STI, 173 raw_ostream &O) { 174 unsigned Imm = MI->getOperand(OpNo).getImm(); 175 if (Imm == 1) { 176 markup(O, Markup::Immediate) << "min"; 177 } else if (Imm == 30) { 178 markup(O, Markup::Immediate) << "inf"; 179 } else if (Imm == 31) { 180 markup(O, Markup::Immediate) << "nan"; 181 } else { 182 float FPVal = RISCVLoadFPImm::getFPImm(Imm); 183 // If the value is an integer, print a .0 fraction. Otherwise, use %g to 184 // which will not print trailing zeros and will use scientific notation 185 // if it is shorter than printing as a decimal. The smallest value requires 186 // 12 digits of precision including the decimal. 187 if (FPVal == (int)(FPVal)) 188 markup(O, Markup::Immediate) << format("%.1f", FPVal); 189 else 190 markup(O, Markup::Immediate) << format("%.12g", FPVal); 191 } 192 } 193 194 void RISCVInstPrinter::printZeroOffsetMemOp(const MCInst *MI, unsigned OpNo, 195 const MCSubtargetInfo &STI, 196 raw_ostream &O) { 197 const MCOperand &MO = MI->getOperand(OpNo); 198 199 assert(MO.isReg() && "printZeroOffsetMemOp can only print register operands"); 200 O << "("; 201 printRegName(O, MO.getReg()); 202 O << ")"; 203 } 204 205 void RISCVInstPrinter::printVTypeI(const MCInst *MI, unsigned OpNo, 206 const MCSubtargetInfo &STI, raw_ostream &O) { 207 unsigned Imm = MI->getOperand(OpNo).getImm(); 208 // Print the raw immediate for reserved values: vlmul[2:0]=4, vsew[2:0]=0b1xx, 209 // or non-zero in bits 8 and above. 210 if (RISCVVType::getVLMUL(Imm) == RISCVII::VLMUL::LMUL_RESERVED || 211 RISCVVType::getSEW(Imm) > 64 || (Imm >> 8) != 0) { 212 O << formatImm(Imm); 213 return; 214 } 215 // Print the text form. 216 RISCVVType::printVType(Imm, O); 217 } 218 219 void RISCVInstPrinter::printRlist(const MCInst *MI, unsigned OpNo, 220 const MCSubtargetInfo &STI, raw_ostream &O) { 221 unsigned Imm = MI->getOperand(OpNo).getImm(); 222 O << "{"; 223 switch (Imm) { 224 case RISCVZC::RLISTENCODE::RA: 225 markup(O, Markup::Register) << (ArchRegNames ? "x1" : "ra"); 226 break; 227 case RISCVZC::RLISTENCODE::RA_S0: 228 markup(O, Markup::Register) << (ArchRegNames ? "x1" : "ra"); 229 O << ", "; 230 markup(O, Markup::Register) << (ArchRegNames ? "x8" : "s0"); 231 break; 232 case RISCVZC::RLISTENCODE::RA_S0_S1: 233 markup(O, Markup::Register) << (ArchRegNames ? "x1" : "ra"); 234 O << ", "; 235 markup(O, Markup::Register) << (ArchRegNames ? "x8" : "s0"); 236 O << '-'; 237 markup(O, Markup::Register) << (ArchRegNames ? "x9" : "s1"); 238 break; 239 case RISCVZC::RLISTENCODE::RA_S0_S2: 240 markup(O, Markup::Register) << (ArchRegNames ? "x1" : "ra"); 241 O << ", "; 242 markup(O, Markup::Register) << (ArchRegNames ? "x8" : "s0"); 243 O << '-'; 244 markup(O, Markup::Register) << (ArchRegNames ? "x9" : "s2"); 245 if (ArchRegNames) { 246 O << ", "; 247 markup(O, Markup::Register) << "x18"; 248 } 249 break; 250 case RISCVZC::RLISTENCODE::RA_S0_S3: 251 case RISCVZC::RLISTENCODE::RA_S0_S4: 252 case RISCVZC::RLISTENCODE::RA_S0_S5: 253 case RISCVZC::RLISTENCODE::RA_S0_S6: 254 case RISCVZC::RLISTENCODE::RA_S0_S7: 255 case RISCVZC::RLISTENCODE::RA_S0_S8: 256 case RISCVZC::RLISTENCODE::RA_S0_S9: 257 case RISCVZC::RLISTENCODE::RA_S0_S11: 258 markup(O, Markup::Register) << (ArchRegNames ? "x1" : "ra"); 259 O << ", "; 260 markup(O, Markup::Register) << (ArchRegNames ? "x8" : "s0"); 261 O << '-'; 262 if (ArchRegNames) { 263 markup(O, Markup::Register) << "x9"; 264 O << ", "; 265 markup(O, Markup::Register) << "x18"; 266 O << '-'; 267 } 268 markup(O, Markup::Register) << getRegisterName( 269 RISCV::X19 + (Imm == RISCVZC::RLISTENCODE::RA_S0_S11 270 ? 8 271 : Imm - RISCVZC::RLISTENCODE::RA_S0_S3)); 272 break; 273 default: 274 llvm_unreachable("invalid register list"); 275 } 276 O << "}"; 277 } 278 279 void RISCVInstPrinter::printRegReg(const MCInst *MI, unsigned OpNo, 280 const MCSubtargetInfo &STI, raw_ostream &O) { 281 const MCOperand &MO = MI->getOperand(OpNo); 282 283 assert(MO.isReg() && "printRegReg can only print register operands"); 284 if (MO.getReg() == RISCV::NoRegister) 285 return; 286 printRegName(O, MO.getReg()); 287 288 O << "("; 289 const MCOperand &MO1 = MI->getOperand(OpNo + 1); 290 assert(MO1.isReg() && "printRegReg can only print register operands"); 291 printRegName(O, MO1.getReg()); 292 O << ")"; 293 } 294 295 void RISCVInstPrinter::printSpimm(const MCInst *MI, unsigned OpNo, 296 const MCSubtargetInfo &STI, raw_ostream &O) { 297 int64_t Imm = MI->getOperand(OpNo).getImm(); 298 unsigned Opcode = MI->getOpcode(); 299 bool IsRV64 = STI.hasFeature(RISCV::Feature64Bit); 300 bool IsEABI = STI.hasFeature(RISCV::FeatureRVE); 301 int64_t Spimm = 0; 302 auto RlistVal = MI->getOperand(0).getImm(); 303 assert(RlistVal != 16 && "Incorrect rlist."); 304 auto Base = RISCVZC::getStackAdjBase(RlistVal, IsRV64, IsEABI); 305 Spimm = Imm + Base; 306 assert((Spimm >= Base && Spimm <= Base + 48) && "Incorrect spimm"); 307 if (Opcode == RISCV::CM_PUSH) 308 Spimm = -Spimm; 309 310 // RAII guard for ANSI color escape sequences 311 WithMarkup ScopedMarkup = markup(O, Markup::Immediate); 312 RISCVZC::printSpimm(Spimm, O); 313 } 314 315 void RISCVInstPrinter::printVMaskReg(const MCInst *MI, unsigned OpNo, 316 const MCSubtargetInfo &STI, 317 raw_ostream &O) { 318 const MCOperand &MO = MI->getOperand(OpNo); 319 320 assert(MO.isReg() && "printVMaskReg can only print register operands"); 321 if (MO.getReg() == RISCV::NoRegister) 322 return; 323 O << ", "; 324 printRegName(O, MO.getReg()); 325 O << ".t"; 326 } 327 328 const char *RISCVInstPrinter::getRegisterName(MCRegister Reg) { 329 return getRegisterName(Reg, ArchRegNames ? RISCV::NoRegAltName 330 : RISCV::ABIRegAltName); 331 } 332