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