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.IsAltName || Reg.IsDeprecatedName) 125 continue; 126 if (Reg.haveRequiredFeatures(STI.getFeatureBits())) { 127 markup(O, Markup::Register) << Reg.Name; 128 return; 129 } 130 } 131 markup(O, Markup::Register) << formatImm(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 << "0"; 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 if (PrintAliases && !NoAliases && FRMArg == RISCVFPRndMode::RoundingMode::DYN) 157 return; 158 O << ", " << RISCVFPRndMode::roundingModeToString(FRMArg); 159 } 160 161 void RISCVInstPrinter::printFRMArgLegacy(const MCInst *MI, unsigned OpNo, 162 const MCSubtargetInfo &STI, 163 raw_ostream &O) { 164 auto FRMArg = 165 static_cast<RISCVFPRndMode::RoundingMode>(MI->getOperand(OpNo).getImm()); 166 // Never print rounding mode if it's the default 'rne'. This ensures the 167 // output can still be parsed by older tools that erroneously failed to 168 // accept a rounding mode. 169 if (FRMArg == RISCVFPRndMode::RoundingMode::RNE) 170 return; 171 O << ", " << RISCVFPRndMode::roundingModeToString(FRMArg); 172 } 173 174 void RISCVInstPrinter::printFPImmOperand(const MCInst *MI, unsigned OpNo, 175 const MCSubtargetInfo &STI, 176 raw_ostream &O) { 177 unsigned Imm = MI->getOperand(OpNo).getImm(); 178 if (Imm == 1) { 179 markup(O, Markup::Immediate) << "min"; 180 } else if (Imm == 30) { 181 markup(O, Markup::Immediate) << "inf"; 182 } else if (Imm == 31) { 183 markup(O, Markup::Immediate) << "nan"; 184 } else { 185 float FPVal = RISCVLoadFPImm::getFPImm(Imm); 186 // If the value is an integer, print a .0 fraction. Otherwise, use %g to 187 // which will not print trailing zeros and will use scientific notation 188 // if it is shorter than printing as a decimal. The smallest value requires 189 // 12 digits of precision including the decimal. 190 if (FPVal == (int)(FPVal)) 191 markup(O, Markup::Immediate) << format("%.1f", FPVal); 192 else 193 markup(O, Markup::Immediate) << format("%.12g", FPVal); 194 } 195 } 196 197 void RISCVInstPrinter::printZeroOffsetMemOp(const MCInst *MI, unsigned OpNo, 198 const MCSubtargetInfo &STI, 199 raw_ostream &O) { 200 const MCOperand &MO = MI->getOperand(OpNo); 201 202 assert(MO.isReg() && "printZeroOffsetMemOp can only print register operands"); 203 O << "("; 204 printRegName(O, MO.getReg()); 205 O << ")"; 206 } 207 208 void RISCVInstPrinter::printVTypeI(const MCInst *MI, unsigned OpNo, 209 const MCSubtargetInfo &STI, raw_ostream &O) { 210 unsigned Imm = MI->getOperand(OpNo).getImm(); 211 // Print the raw immediate for reserved values: vlmul[2:0]=4, vsew[2:0]=0b1xx, 212 // or non-zero in bits 8 and above. 213 if (RISCVVType::getVLMUL(Imm) == RISCVII::VLMUL::LMUL_RESERVED || 214 RISCVVType::getSEW(Imm) > 64 || (Imm >> 8) != 0) { 215 O << formatImm(Imm); 216 return; 217 } 218 // Print the text form. 219 RISCVVType::printVType(Imm, O); 220 } 221 222 // Print a Zcmp RList. If we are printing architectural register names rather 223 // than ABI register names, we need to print "{x1, x8-x9, x18-x27}" for all 224 // registers. Otherwise, we print "{ra, s0-s11}". 225 void RISCVInstPrinter::printRlist(const MCInst *MI, unsigned OpNo, 226 const MCSubtargetInfo &STI, raw_ostream &O) { 227 unsigned Imm = MI->getOperand(OpNo).getImm(); 228 O << "{"; 229 printRegName(O, RISCV::X1); 230 231 if (Imm >= RISCVZC::RLISTENCODE::RA_S0) { 232 O << ", "; 233 printRegName(O, RISCV::X8); 234 } 235 236 if (Imm >= RISCVZC::RLISTENCODE::RA_S0_S1) { 237 O << '-'; 238 if (Imm == RISCVZC::RLISTENCODE::RA_S0_S1 || ArchRegNames) 239 printRegName(O, RISCV::X9); 240 } 241 242 if (Imm >= RISCVZC::RLISTENCODE::RA_S0_S2) { 243 if (ArchRegNames) 244 O << ", "; 245 if (Imm == RISCVZC::RLISTENCODE::RA_S0_S2 || ArchRegNames) 246 printRegName(O, RISCV::X18); 247 } 248 249 if (Imm >= RISCVZC::RLISTENCODE::RA_S0_S3) { 250 if (ArchRegNames) 251 O << '-'; 252 unsigned Offset = (Imm - RISCVZC::RLISTENCODE::RA_S0_S3); 253 // Encodings for S3-S9 are contiguous. There is no encoding for S10, so we 254 // must skip to S11(X27). 255 if (Imm == RISCVZC::RLISTENCODE::RA_S0_S11) 256 ++Offset; 257 printRegName(O, RISCV::X19 + Offset); 258 } 259 260 O << "}"; 261 } 262 263 void RISCVInstPrinter::printRegReg(const MCInst *MI, unsigned OpNo, 264 const MCSubtargetInfo &STI, raw_ostream &O) { 265 const MCOperand &MO = MI->getOperand(OpNo); 266 267 assert(MO.isReg() && "printRegReg can only print register operands"); 268 printRegName(O, MO.getReg()); 269 270 O << "("; 271 const MCOperand &MO1 = MI->getOperand(OpNo + 1); 272 assert(MO1.isReg() && "printRegReg can only print register operands"); 273 printRegName(O, MO1.getReg()); 274 O << ")"; 275 } 276 277 void RISCVInstPrinter::printStackAdj(const MCInst *MI, unsigned OpNo, 278 const MCSubtargetInfo &STI, raw_ostream &O, 279 bool Negate) { 280 int64_t Imm = MI->getOperand(OpNo).getImm(); 281 bool IsRV64 = STI.hasFeature(RISCV::Feature64Bit); 282 int64_t StackAdj = 0; 283 auto RlistVal = MI->getOperand(0).getImm(); 284 assert(RlistVal != 16 && "Incorrect rlist."); 285 auto Base = RISCVZC::getStackAdjBase(RlistVal, IsRV64); 286 StackAdj = Imm + Base; 287 assert((StackAdj >= Base && StackAdj <= Base + 48) && 288 "Incorrect stack adjust"); 289 if (Negate) 290 StackAdj = -StackAdj; 291 292 // RAII guard for ANSI color escape sequences 293 WithMarkup ScopedMarkup = markup(O, Markup::Immediate); 294 O << StackAdj; 295 } 296 297 void RISCVInstPrinter::printVMaskReg(const MCInst *MI, unsigned OpNo, 298 const MCSubtargetInfo &STI, 299 raw_ostream &O) { 300 const MCOperand &MO = MI->getOperand(OpNo); 301 302 assert(MO.isReg() && "printVMaskReg can only print register operands"); 303 if (MO.getReg() == RISCV::NoRegister) 304 return; 305 O << ", "; 306 printRegName(O, MO.getReg()); 307 O << ".t"; 308 } 309 310 const char *RISCVInstPrinter::getRegisterName(MCRegister Reg) { 311 return getRegisterName(Reg, ArchRegNames ? RISCV::NoRegAltName 312 : RISCV::ABIRegAltName); 313 } 314