1//===-- RISCVInstPrinter.cpp - Convert RISCV 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 RISCV MCInst to a .s file.
10//
11//===----------------------------------------------------------------------===//
12
13#include "RISCVInstPrinter.h"
14#include "MCTargetDesc/RISCVMCExpr.h"
15#include "Utils/RISCVBaseInfo.h"
16#include "llvm/MC/MCAsmInfo.h"
17#include "llvm/MC/MCExpr.h"
18#include "llvm/MC/MCInst.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;
26
27#define DEBUG_TYPE "asm-printer"
28
29// Include the auto-generated portion of the assembly writer.
30#define PRINT_ALIAS_INSTR
31#include "RISCVGenAsmWriter.inc"
32
33// Include the auto-generated portion of the compress emitter.
34#define GEN_UNCOMPRESS_INSTR
35#include "RISCVGenCompressInstEmitter.inc"
36
37static cl::opt<bool>
38    NoAliases("riscv-no-aliases",
39              cl::desc("Disable the emission of assembler pseudo instructions"),
40              cl::init(false), cl::Hidden);
41
42static cl::opt<bool>
43    ArchRegNames("riscv-arch-reg-names",
44                 cl::desc("Print architectural register names rather than the "
45                          "ABI names (such as x2 instead of sp)"),
46                 cl::init(false), cl::Hidden);
47
48// The command-line flags above are used by llvm-mc and llc. They can be used by
49// `llvm-objdump`, but we override their values here to handle options passed to
50// `llvm-objdump` with `-M` (which matches GNU objdump). There did not seem to
51// be an easier way to allow these options in all these tools, without doing it
52// this way.
53bool RISCVInstPrinter::applyTargetSpecificCLOption(StringRef Opt) {
54  if (Opt == "no-aliases") {
55    NoAliases = true;
56    return true;
57  }
58  if (Opt == "numeric") {
59    ArchRegNames = true;
60    return true;
61  }
62
63  return false;
64}
65
66void RISCVInstPrinter::printInst(const MCInst *MI, uint64_t Address,
67                                 StringRef Annot, const MCSubtargetInfo &STI,
68                                 raw_ostream &O) {
69  bool Res = false;
70  const MCInst *NewMI = MI;
71  MCInst UncompressedMI;
72  if (!NoAliases)
73    Res = uncompressInst(UncompressedMI, *MI, MRI, STI);
74  if (Res)
75    NewMI = const_cast<MCInst *>(&UncompressedMI);
76  if (NoAliases || !printAliasInstr(NewMI, STI, O))
77    printInstruction(NewMI, Address, STI, O);
78  printAnnotation(O, Annot);
79}
80
81void RISCVInstPrinter::printRegName(raw_ostream &O, unsigned RegNo) const {
82  O << getRegisterName(RegNo);
83}
84
85void RISCVInstPrinter::printOperand(const MCInst *MI, unsigned OpNo,
86                                    const MCSubtargetInfo &STI, raw_ostream &O,
87                                    const char *Modifier) {
88  assert((Modifier == 0 || Modifier[0] == 0) && "No modifiers supported");
89  const MCOperand &MO = MI->getOperand(OpNo);
90
91  if (MO.isReg()) {
92    printRegName(O, MO.getReg());
93    return;
94  }
95
96  if (MO.isImm()) {
97    O << MO.getImm();
98    return;
99  }
100
101  assert(MO.isExpr() && "Unknown operand kind in printOperand");
102  MO.getExpr()->print(O, &MAI);
103}
104
105void RISCVInstPrinter::printCSRSystemRegister(const MCInst *MI, unsigned OpNo,
106                                              const MCSubtargetInfo &STI,
107                                              raw_ostream &O) {
108  unsigned Imm = MI->getOperand(OpNo).getImm();
109  auto SysReg = RISCVSysReg::lookupSysRegByEncoding(Imm);
110  if (SysReg && SysReg->haveRequiredFeatures(STI.getFeatureBits()))
111    O << SysReg->Name;
112  else
113    O << Imm;
114}
115
116void RISCVInstPrinter::printFenceArg(const MCInst *MI, unsigned OpNo,
117                                     const MCSubtargetInfo &STI,
118                                     raw_ostream &O) {
119  unsigned FenceArg = MI->getOperand(OpNo).getImm();
120  assert (((FenceArg >> 4) == 0) && "Invalid immediate in printFenceArg");
121
122  if ((FenceArg & RISCVFenceField::I) != 0)
123    O << 'i';
124  if ((FenceArg & RISCVFenceField::O) != 0)
125    O << 'o';
126  if ((FenceArg & RISCVFenceField::R) != 0)
127    O << 'r';
128  if ((FenceArg & RISCVFenceField::W) != 0)
129    O << 'w';
130  if (FenceArg == 0)
131    O << "unknown";
132}
133
134void RISCVInstPrinter::printFRMArg(const MCInst *MI, unsigned OpNo,
135                                   const MCSubtargetInfo &STI, raw_ostream &O) {
136  auto FRMArg =
137      static_cast<RISCVFPRndMode::RoundingMode>(MI->getOperand(OpNo).getImm());
138  O << RISCVFPRndMode::roundingModeToString(FRMArg);
139}
140
141void RISCVInstPrinter::printAtomicMemOp(const MCInst *MI, unsigned OpNo,
142                                        const MCSubtargetInfo &STI,
143                                        raw_ostream &O) {
144  const MCOperand &MO = MI->getOperand(OpNo);
145
146  assert(MO.isReg() && "printAtomicMemOp can only print register operands");
147  O << "(";
148  printRegName(O, MO.getReg());
149  O << ")";
150  return;
151}
152
153const char *RISCVInstPrinter::getRegisterName(unsigned RegNo) {
154  return getRegisterName(RegNo, ArchRegNames ? RISCV::NoRegAltName
155                                             : RISCV::ABIRegAltName);
156}
157