Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/contrib/llvm-project/llvm/lib/Target/RISCV/MCTargetDesc/RISCVInstPrinter.cpp
35294 views
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
317