Path: blob/main/contrib/llvm-project/llvm/lib/Target/RISCV/MCTargetDesc/RISCVInstPrinter.cpp
35294 views
//===-- RISCVInstPrinter.cpp - Convert RISC-V MCInst to asm syntax --------===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//7//8// This class prints an RISC-V MCInst to a .s file.9//10//===----------------------------------------------------------------------===//1112#include "RISCVInstPrinter.h"13#include "RISCVBaseInfo.h"14#include "RISCVMCExpr.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/MCRegisterInfo.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#include "llvm/Support/FormattedStream.h"25using namespace llvm;2627#define DEBUG_TYPE "asm-printer"2829// Include the auto-generated portion of the assembly writer.30#define PRINT_ALIAS_INSTR31#include "RISCVGenAsmWriter.inc"3233static cl::opt<bool>34NoAliases("riscv-no-aliases",35cl::desc("Disable the emission of assembler pseudo instructions"),36cl::init(false), cl::Hidden);3738// Print architectural register names rather than the ABI names (such as x239// instead of sp).40// TODO: Make RISCVInstPrinter::getRegisterName non-static so that this can a41// member.42static bool ArchRegNames;4344// The command-line flags above are used by llvm-mc and llc. They can be used by45// `llvm-objdump`, but we override their values here to handle options passed to46// `llvm-objdump` with `-M` (which matches GNU objdump). There did not seem to47// be an easier way to allow these options in all these tools, without doing it48// this way.49bool RISCVInstPrinter::applyTargetSpecificCLOption(StringRef Opt) {50if (Opt == "no-aliases") {51PrintAliases = false;52return true;53}54if (Opt == "numeric") {55ArchRegNames = true;56return true;57}5859return false;60}6162void RISCVInstPrinter::printInst(const MCInst *MI, uint64_t Address,63StringRef Annot, const MCSubtargetInfo &STI,64raw_ostream &O) {65bool Res = false;66const MCInst *NewMI = MI;67MCInst UncompressedMI;68if (PrintAliases && !NoAliases)69Res = RISCVRVC::uncompress(UncompressedMI, *MI, STI);70if (Res)71NewMI = const_cast<MCInst *>(&UncompressedMI);72if (!PrintAliases || NoAliases || !printAliasInstr(NewMI, Address, STI, O))73printInstruction(NewMI, Address, STI, O);74printAnnotation(O, Annot);75}7677void RISCVInstPrinter::printRegName(raw_ostream &O, MCRegister Reg) const {78markup(O, Markup::Register) << getRegisterName(Reg);79}8081void RISCVInstPrinter::printOperand(const MCInst *MI, unsigned OpNo,82const MCSubtargetInfo &STI, raw_ostream &O,83const char *Modifier) {84assert((Modifier == nullptr || Modifier[0] == 0) && "No modifiers supported");85const MCOperand &MO = MI->getOperand(OpNo);8687if (MO.isReg()) {88printRegName(O, MO.getReg());89return;90}9192if (MO.isImm()) {93markup(O, Markup::Immediate) << formatImm(MO.getImm());94return;95}9697assert(MO.isExpr() && "Unknown operand kind in printOperand");98MO.getExpr()->print(O, &MAI);99}100101void RISCVInstPrinter::printBranchOperand(const MCInst *MI, uint64_t Address,102unsigned OpNo,103const MCSubtargetInfo &STI,104raw_ostream &O) {105const MCOperand &MO = MI->getOperand(OpNo);106if (!MO.isImm())107return printOperand(MI, OpNo, STI, O);108109if (PrintBranchImmAsAddress) {110uint64_t Target = Address + MO.getImm();111if (!STI.hasFeature(RISCV::Feature64Bit))112Target &= 0xffffffff;113markup(O, Markup::Target) << formatHex(Target);114} else {115markup(O, Markup::Target) << formatImm(MO.getImm());116}117}118119void RISCVInstPrinter::printCSRSystemRegister(const MCInst *MI, unsigned OpNo,120const MCSubtargetInfo &STI,121raw_ostream &O) {122unsigned Imm = MI->getOperand(OpNo).getImm();123auto Range = RISCVSysReg::lookupSysRegByEncoding(Imm);124for (auto &Reg : Range) {125if (Reg.haveRequiredFeatures(STI.getFeatureBits())) {126markup(O, Markup::Register) << Reg.Name;127return;128}129}130markup(O, Markup::Register) << formatImm(Imm);131}132133void RISCVInstPrinter::printFenceArg(const MCInst *MI, unsigned OpNo,134const MCSubtargetInfo &STI,135raw_ostream &O) {136unsigned FenceArg = MI->getOperand(OpNo).getImm();137assert (((FenceArg >> 4) == 0) && "Invalid immediate in printFenceArg");138139if ((FenceArg & RISCVFenceField::I) != 0)140O << 'i';141if ((FenceArg & RISCVFenceField::O) != 0)142O << 'o';143if ((FenceArg & RISCVFenceField::R) != 0)144O << 'r';145if ((FenceArg & RISCVFenceField::W) != 0)146O << 'w';147if (FenceArg == 0)148O << "0";149}150151void RISCVInstPrinter::printFRMArg(const MCInst *MI, unsigned OpNo,152const MCSubtargetInfo &STI, raw_ostream &O) {153auto FRMArg =154static_cast<RISCVFPRndMode::RoundingMode>(MI->getOperand(OpNo).getImm());155if (PrintAliases && !NoAliases && FRMArg == RISCVFPRndMode::RoundingMode::DYN)156return;157O << ", " << RISCVFPRndMode::roundingModeToString(FRMArg);158}159160void RISCVInstPrinter::printFRMArgLegacy(const MCInst *MI, unsigned OpNo,161const MCSubtargetInfo &STI,162raw_ostream &O) {163auto FRMArg =164static_cast<RISCVFPRndMode::RoundingMode>(MI->getOperand(OpNo).getImm());165// Never print rounding mode if it's the default 'rne'. This ensures the166// output can still be parsed by older tools that erroneously failed to167// accept a rounding mode.168if (FRMArg == RISCVFPRndMode::RoundingMode::RNE)169return;170O << ", " << RISCVFPRndMode::roundingModeToString(FRMArg);171}172173void RISCVInstPrinter::printFPImmOperand(const MCInst *MI, unsigned OpNo,174const MCSubtargetInfo &STI,175raw_ostream &O) {176unsigned Imm = MI->getOperand(OpNo).getImm();177if (Imm == 1) {178markup(O, Markup::Immediate) << "min";179} else if (Imm == 30) {180markup(O, Markup::Immediate) << "inf";181} else if (Imm == 31) {182markup(O, Markup::Immediate) << "nan";183} else {184float FPVal = RISCVLoadFPImm::getFPImm(Imm);185// If the value is an integer, print a .0 fraction. Otherwise, use %g to186// which will not print trailing zeros and will use scientific notation187// if it is shorter than printing as a decimal. The smallest value requires188// 12 digits of precision including the decimal.189if (FPVal == (int)(FPVal))190markup(O, Markup::Immediate) << format("%.1f", FPVal);191else192markup(O, Markup::Immediate) << format("%.12g", FPVal);193}194}195196void RISCVInstPrinter::printZeroOffsetMemOp(const MCInst *MI, unsigned OpNo,197const MCSubtargetInfo &STI,198raw_ostream &O) {199const MCOperand &MO = MI->getOperand(OpNo);200201assert(MO.isReg() && "printZeroOffsetMemOp can only print register operands");202O << "(";203printRegName(O, MO.getReg());204O << ")";205}206207void RISCVInstPrinter::printVTypeI(const MCInst *MI, unsigned OpNo,208const MCSubtargetInfo &STI, raw_ostream &O) {209unsigned Imm = MI->getOperand(OpNo).getImm();210// Print the raw immediate for reserved values: vlmul[2:0]=4, vsew[2:0]=0b1xx,211// or non-zero in bits 8 and above.212if (RISCVVType::getVLMUL(Imm) == RISCVII::VLMUL::LMUL_RESERVED ||213RISCVVType::getSEW(Imm) > 64 || (Imm >> 8) != 0) {214O << formatImm(Imm);215return;216}217// Print the text form.218RISCVVType::printVType(Imm, O);219}220221// Print a Zcmp RList. If we are printing architectural register names rather222// than ABI register names, we need to print "{x1, x8-x9, x18-x27}" for all223// registers. Otherwise, we print "{ra, s0-s11}".224void RISCVInstPrinter::printRlist(const MCInst *MI, unsigned OpNo,225const MCSubtargetInfo &STI, raw_ostream &O) {226unsigned Imm = MI->getOperand(OpNo).getImm();227O << "{";228printRegName(O, RISCV::X1);229230if (Imm >= RISCVZC::RLISTENCODE::RA_S0) {231O << ", ";232printRegName(O, RISCV::X8);233}234235if (Imm >= RISCVZC::RLISTENCODE::RA_S0_S1) {236O << '-';237if (Imm == RISCVZC::RLISTENCODE::RA_S0_S1 || ArchRegNames)238printRegName(O, RISCV::X9);239}240241if (Imm >= RISCVZC::RLISTENCODE::RA_S0_S2) {242if (ArchRegNames)243O << ", ";244if (Imm == RISCVZC::RLISTENCODE::RA_S0_S2 || ArchRegNames)245printRegName(O, RISCV::X18);246}247248if (Imm >= RISCVZC::RLISTENCODE::RA_S0_S3) {249if (ArchRegNames)250O << '-';251unsigned Offset = (Imm - RISCVZC::RLISTENCODE::RA_S0_S3);252// Encodings for S3-S9 are contiguous. There is no encoding for S10, so we253// must skip to S11(X27).254if (Imm == RISCVZC::RLISTENCODE::RA_S0_S11)255++Offset;256printRegName(O, RISCV::X19 + Offset);257}258259O << "}";260}261262void RISCVInstPrinter::printRegReg(const MCInst *MI, unsigned OpNo,263const MCSubtargetInfo &STI, raw_ostream &O) {264const MCOperand &MO = MI->getOperand(OpNo);265266assert(MO.isReg() && "printRegReg can only print register operands");267if (MO.getReg() == RISCV::NoRegister)268return;269printRegName(O, MO.getReg());270271O << "(";272const MCOperand &MO1 = MI->getOperand(OpNo + 1);273assert(MO1.isReg() && "printRegReg can only print register operands");274printRegName(O, MO1.getReg());275O << ")";276}277278void RISCVInstPrinter::printStackAdj(const MCInst *MI, unsigned OpNo,279const MCSubtargetInfo &STI, raw_ostream &O,280bool Negate) {281int64_t Imm = MI->getOperand(OpNo).getImm();282bool IsRV64 = STI.hasFeature(RISCV::Feature64Bit);283int64_t StackAdj = 0;284auto RlistVal = MI->getOperand(0).getImm();285assert(RlistVal != 16 && "Incorrect rlist.");286auto Base = RISCVZC::getStackAdjBase(RlistVal, IsRV64);287StackAdj = Imm + Base;288assert((StackAdj >= Base && StackAdj <= Base + 48) &&289"Incorrect stack adjust");290if (Negate)291StackAdj = -StackAdj;292293// RAII guard for ANSI color escape sequences294WithMarkup ScopedMarkup = markup(O, Markup::Immediate);295O << StackAdj;296}297298void RISCVInstPrinter::printVMaskReg(const MCInst *MI, unsigned OpNo,299const MCSubtargetInfo &STI,300raw_ostream &O) {301const MCOperand &MO = MI->getOperand(OpNo);302303assert(MO.isReg() && "printVMaskReg can only print register operands");304if (MO.getReg() == RISCV::NoRegister)305return;306O << ", ";307printRegName(O, MO.getReg());308O << ".t";309}310311const char *RISCVInstPrinter::getRegisterName(MCRegister Reg) {312return getRegisterName(Reg, ArchRegNames ? RISCV::NoRegAltName313: RISCV::ABIRegAltName);314}315316317