brintos

brintos / llvm-project-archived public Read only

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