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 Range = RISCVSysReg::lookupSysRegByEncoding(Imm); 125 for (auto &Reg : Range) { 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 if (MO.getReg() == RISCV::NoRegister) 269 return; 270 printRegName(O, MO.getReg()); 271 272 O << "("; 273 const MCOperand &MO1 = MI->getOperand(OpNo + 1); 274 assert(MO1.isReg() && "printRegReg can only print register operands"); 275 printRegName(O, MO1.getReg()); 276 O << ")"; 277 } 278 279 void RISCVInstPrinter::printStackAdj(const MCInst *MI, unsigned OpNo, 280 const MCSubtargetInfo &STI, raw_ostream &O, 281 bool Negate) { 282 int64_t Imm = MI->getOperand(OpNo).getImm(); 283 bool IsRV64 = STI.hasFeature(RISCV::Feature64Bit); 284 int64_t StackAdj = 0; 285 auto RlistVal = MI->getOperand(0).getImm(); 286 assert(RlistVal != 16 && "Incorrect rlist."); 287 auto Base = RISCVZC::getStackAdjBase(RlistVal, IsRV64); 288 StackAdj = Imm + Base; 289 assert((StackAdj >= Base && StackAdj <= Base + 48) && 290 "Incorrect stack adjust"); 291 if (Negate) 292 StackAdj = -StackAdj; 293 294 // RAII guard for ANSI color escape sequences 295 WithMarkup ScopedMarkup = markup(O, Markup::Immediate); 296 O << StackAdj; 297 } 298 299 void RISCVInstPrinter::printVMaskReg(const MCInst *MI, unsigned OpNo, 300 const MCSubtargetInfo &STI, 301 raw_ostream &O) { 302 const MCOperand &MO = MI->getOperand(OpNo); 303 304 assert(MO.isReg() && "printVMaskReg can only print register operands"); 305 if (MO.getReg() == RISCV::NoRegister) 306 return; 307 O << ", "; 308 printRegName(O, MO.getReg()); 309 O << ".t"; 310 } 311 312 const char *RISCVInstPrinter::getRegisterName(MCRegister Reg) { 313 return getRegisterName(Reg, ArchRegNames ? RISCV::NoRegAltName 314 : RISCV::ABIRegAltName); 315 } 316