LLVM 20.0.0git
XtensaInstPrinter.cpp
Go to the documentation of this file.
1//===- XtensaInstPrinter.cpp - Convert Xtensa MCInst to asm syntax --------===//
2//
3// The LLVM Compiler Infrastructure
4//
5// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
6// See https://llvm.org/LICENSE.txt for license information.
7// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
8//
9//===----------------------------------------------------------------------===//
10//
11// This class prints an Xtensa MCInst to a .s file.
12//
13//===----------------------------------------------------------------------===//
14
15#include "XtensaInstPrinter.h"
17#include "llvm/MC/MCExpr.h"
18#include "llvm/MC/MCInstrInfo.h"
19#include "llvm/MC/MCRegister.h"
20#include "llvm/MC/MCSymbol.h"
23
24using namespace llvm;
25
26#define DEBUG_TYPE "asm-printer"
27
28#include "XtensaGenAsmWriter.inc"
29
30static void printExpr(const MCExpr *Expr, raw_ostream &OS) {
31 int Offset = 0;
32 const MCSymbolRefExpr *SRE;
33
34 if (!(SRE = cast<MCSymbolRefExpr>(Expr)))
35 assert(false && "Unexpected MCExpr type.");
36
38
39 switch (Kind) {
41 break;
42 // TODO
43 default:
44 report_fatal_error("Invalid kind!");
45 }
46
47 OS << SRE->getSymbol();
48
49 if (Offset) {
50 if (Offset > 0)
51 OS << '+';
52 OS << Offset;
53 }
54
55 if (Kind != MCSymbolRefExpr::VK_None)
56 OS << ')';
57}
58
60 if (MC.isReg())
61 O << getRegisterName(MC.getReg());
62 else if (MC.isImm())
63 O << MC.getImm();
64 else if (MC.isExpr())
65 printExpr(MC.getExpr(), O);
66 else
67 report_fatal_error("Invalid operand");
68}
69
71 StringRef Annot, const MCSubtargetInfo &STI,
72 raw_ostream &O) {
74 printAnnotation(O, Annot);
75}
76
78 O << getRegisterName(Reg);
79}
80
81void XtensaInstPrinter::printOperand(const MCInst *MI, int OpNum,
82 raw_ostream &O) {
83 printOperand(MI->getOperand(OpNum), O);
84}
85
86void XtensaInstPrinter::printMemOperand(const MCInst *MI, int OpNum,
87 raw_ostream &OS) {
88 OS << getRegisterName(MI->getOperand(OpNum).getReg());
89 OS << ", ";
90 printOperand(MI, OpNum + 1, OS);
91}
92
93void XtensaInstPrinter::printBranchTarget(const MCInst *MI, int OpNum,
94 raw_ostream &OS) {
95 const MCOperand &MC = MI->getOperand(OpNum);
96 if (MI->getOperand(OpNum).isImm()) {
97 int64_t Val = MC.getImm() + 4;
98 OS << ". ";
99 if (Val > 0)
100 OS << '+';
101 OS << Val;
102 } else if (MC.isExpr())
103 MC.getExpr()->print(OS, &MAI, true);
104 else
105 llvm_unreachable("Invalid operand");
106}
107
108void XtensaInstPrinter::printJumpTarget(const MCInst *MI, int OpNum,
109 raw_ostream &OS) {
110 const MCOperand &MC = MI->getOperand(OpNum);
111 if (MC.isImm()) {
112 int64_t Val = MC.getImm() + 4;
113 OS << ". ";
114 if (Val > 0)
115 OS << '+';
116 OS << Val;
117 } else if (MC.isExpr())
118 MC.getExpr()->print(OS, &MAI, true);
119 else
120 llvm_unreachable("Invalid operand");
121 ;
122}
123
124void XtensaInstPrinter::printCallOperand(const MCInst *MI, int OpNum,
125 raw_ostream &OS) {
126 const MCOperand &MC = MI->getOperand(OpNum);
127 if (MC.isImm()) {
128 int64_t Val = MC.getImm() + 4;
129 OS << ". ";
130 if (Val > 0)
131 OS << '+';
132 OS << Val;
133 } else if (MC.isExpr())
134 MC.getExpr()->print(OS, &MAI, true);
135 else
136 llvm_unreachable("Invalid operand");
137}
138
139void XtensaInstPrinter::printL32RTarget(const MCInst *MI, int OpNum,
140 raw_ostream &O) {
141 const MCOperand &MC = MI->getOperand(OpNum);
142 if (MC.isImm()) {
143 int64_t Value = MI->getOperand(OpNum).getImm();
144 int64_t InstrOff = Value & 0x3;
145 Value -= InstrOff;
146 assert((Value >= -262144 && Value <= -4) &&
147 "Invalid argument, value must be in ranges [-262144,-4]");
148 Value += ((InstrOff + 0x3) & 0x4) - InstrOff;
149 O << ". ";
150 O << Value;
151 } else if (MC.isExpr())
152 MC.getExpr()->print(O, &MAI, true);
153 else
154 llvm_unreachable("Invalid operand");
155}
156
157void XtensaInstPrinter::printImm8_AsmOperand(const MCInst *MI, int OpNum,
158 raw_ostream &O) {
159 if (MI->getOperand(OpNum).isImm()) {
160 int64_t Value = MI->getOperand(OpNum).getImm();
161 assert(isInt<8>(Value) &&
162 "Invalid argument, value must be in ranges [-128,127]");
163 O << Value;
164 } else {
165 printOperand(MI, OpNum, O);
166 }
167}
168
169void XtensaInstPrinter::printImm8_sh8_AsmOperand(const MCInst *MI, int OpNum,
170 raw_ostream &O) {
171 if (MI->getOperand(OpNum).isImm()) {
172 int64_t Value = MI->getOperand(OpNum).getImm();
173 assert((isInt<16>(Value) && ((Value & 0xFF) == 0)) &&
174 "Invalid argument, value must be multiples of 256 in range "
175 "[-32768,32512]");
176 O << Value;
177 } else
178 printOperand(MI, OpNum, O);
179}
180
181void XtensaInstPrinter::printImm12_AsmOperand(const MCInst *MI, int OpNum,
182 raw_ostream &O) {
183 if (MI->getOperand(OpNum).isImm()) {
184 int64_t Value = MI->getOperand(OpNum).getImm();
185 assert((Value >= -2048 && Value <= 2047) &&
186 "Invalid argument, value must be in ranges [-2048,2047]");
187 O << Value;
188 } else
189 printOperand(MI, OpNum, O);
190}
191
192void XtensaInstPrinter::printImm12m_AsmOperand(const MCInst *MI, int OpNum,
193 raw_ostream &O) {
194 if (MI->getOperand(OpNum).isImm()) {
195 int64_t Value = MI->getOperand(OpNum).getImm();
196 assert((Value >= -2048 && Value <= 2047) &&
197 "Invalid argument, value must be in ranges [-2048,2047]");
198 O << Value;
199 } else
200 printOperand(MI, OpNum, O);
201}
202
203void XtensaInstPrinter::printUimm4_AsmOperand(const MCInst *MI, int OpNum,
204 raw_ostream &O) {
205 if (MI->getOperand(OpNum).isImm()) {
206 int64_t Value = MI->getOperand(OpNum).getImm();
207 assert((Value >= 0 && Value <= 15) && "Invalid argument");
208 O << Value;
209 } else
210 printOperand(MI, OpNum, O);
211}
212
213void XtensaInstPrinter::printUimm5_AsmOperand(const MCInst *MI, int OpNum,
214 raw_ostream &O) {
215 if (MI->getOperand(OpNum).isImm()) {
216 int64_t Value = MI->getOperand(OpNum).getImm();
217 assert((Value >= 0 && Value <= 31) && "Invalid argument");
218 O << Value;
219 } else
220 printOperand(MI, OpNum, O);
221}
222
223void XtensaInstPrinter::printShimm1_31_AsmOperand(const MCInst *MI, int OpNum,
224 raw_ostream &O) {
225 if (MI->getOperand(OpNum).isImm()) {
226 int64_t Value = MI->getOperand(OpNum).getImm();
227 assert((Value >= 1 && Value <= 31) &&
228 "Invalid argument, value must be in range [1,31]");
229 O << Value;
230 } else
231 printOperand(MI, OpNum, O);
232}
233
234void XtensaInstPrinter::printImm1_16_AsmOperand(const MCInst *MI, int OpNum,
235 raw_ostream &O) {
236 if (MI->getOperand(OpNum).isImm()) {
237 int64_t Value = MI->getOperand(OpNum).getImm();
238 assert((Value >= 1 && Value <= 16) &&
239 "Invalid argument, value must be in range [1,16]");
240 O << Value;
241 } else
242 printOperand(MI, OpNum, O);
243}
244
245void XtensaInstPrinter::printImm1n_15_AsmOperand(const MCInst *MI, int OpNum,
246 raw_ostream &O) {
247 if (MI->getOperand(OpNum).isImm()) {
248 int64_t Value = MI->getOperand(OpNum).getImm();
249 assert((Value >= -1 && (Value != 0) && Value <= 15) &&
250 "Invalid argument, value must be in ranges <-1,-1> or <1,15>");
251 O << Value;
252 } else
253 printOperand(MI, OpNum, O);
254}
255
256void XtensaInstPrinter::printImm32n_95_AsmOperand(const MCInst *MI, int OpNum,
257 raw_ostream &O) {
258 if (MI->getOperand(OpNum).isImm()) {
259 int64_t Value = MI->getOperand(OpNum).getImm();
260 assert((Value >= -32 && Value <= 95) &&
261 "Invalid argument, value must be in ranges <-32,95>");
262 O << Value;
263 } else
264 printOperand(MI, OpNum, O);
265}
266
267void XtensaInstPrinter::printOffset8m8_AsmOperand(const MCInst *MI, int OpNum,
268 raw_ostream &O) {
269 if (MI->getOperand(OpNum).isImm()) {
270 int64_t Value = MI->getOperand(OpNum).getImm();
271 assert((Value >= 0 && Value <= 255) &&
272 "Invalid argument, value must be in range [0,255]");
273 O << Value;
274 } else
275 printOperand(MI, OpNum, O);
276}
277
278void XtensaInstPrinter::printOffset8m16_AsmOperand(const MCInst *MI, int OpNum,
279 raw_ostream &O) {
280 if (MI->getOperand(OpNum).isImm()) {
281 int64_t Value = MI->getOperand(OpNum).getImm();
282 assert((Value >= 0 && Value <= 510 && ((Value & 0x1) == 0)) &&
283 "Invalid argument, value must be multiples of two in range [0,510]");
284 O << Value;
285 } else
286 printOperand(MI, OpNum, O);
287}
288
289void XtensaInstPrinter::printOffset8m32_AsmOperand(const MCInst *MI, int OpNum,
290 raw_ostream &O) {
291 if (MI->getOperand(OpNum).isImm()) {
292 int64_t Value = MI->getOperand(OpNum).getImm();
293 assert(
294 (Value >= 0 && Value <= 1020 && ((Value & 0x3) == 0)) &&
295 "Invalid argument, value must be multiples of four in range [0,1020]");
296 O << Value;
297 } else
298 printOperand(MI, OpNum, O);
299}
300
301void XtensaInstPrinter::printOffset4m32_AsmOperand(const MCInst *MI, int OpNum,
302 raw_ostream &O) {
303 if (MI->getOperand(OpNum).isImm()) {
304 int64_t Value = MI->getOperand(OpNum).getImm();
305 assert((Value >= 0 && Value <= 60 && ((Value & 0x3) == 0)) &&
306 "Invalid argument, value must be multiples of four in range [0,60]");
307 O << Value;
308 } else
309 printOperand(MI, OpNum, O);
310}
311
312void XtensaInstPrinter::printB4const_AsmOperand(const MCInst *MI, int OpNum,
313 raw_ostream &O) {
314 if (MI->getOperand(OpNum).isImm()) {
315 int64_t Value = MI->getOperand(OpNum).getImm();
316
317 switch (Value) {
318 case -1:
319 case 1:
320 case 2:
321 case 3:
322 case 4:
323 case 5:
324 case 6:
325 case 7:
326 case 8:
327 case 10:
328 case 12:
329 case 16:
330 case 32:
331 case 64:
332 case 128:
333 case 256:
334 break;
335 default:
336 assert((0) && "Invalid B4const argument");
337 }
338 O << Value;
339 } else
340 printOperand(MI, OpNum, O);
341}
342
343void XtensaInstPrinter::printB4constu_AsmOperand(const MCInst *MI, int OpNum,
344 raw_ostream &O) {
345 if (MI->getOperand(OpNum).isImm()) {
346 int64_t Value = MI->getOperand(OpNum).getImm();
347
348 switch (Value) {
349 case 32768:
350 case 65536:
351 case 2:
352 case 3:
353 case 4:
354 case 5:
355 case 6:
356 case 7:
357 case 8:
358 case 10:
359 case 12:
360 case 16:
361 case 32:
362 case 64:
363 case 128:
364 case 256:
365 break;
366 default:
367 assert((0) && "Invalid B4constu argument");
368 }
369 O << Value;
370 } else
371 printOperand(MI, OpNum, O);
372}
static void printExpr(const MCExpr *Expr, const MCAsmInfo *MAI, raw_ostream &OS)
IRTranslator LLVM IR MI
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
raw_pwrite_stream & OS
static void printExpr(const MCExpr *Expr, raw_ostream &OS)
Base class for the full range of assembler expressions which are needed for parsing.
Definition: MCExpr.h:34
void print(raw_ostream &OS, const MCAsmInfo *MAI, bool InParens=false) const
Definition: MCExpr.cpp:40
void printAnnotation(raw_ostream &OS, StringRef Annot)
Utility function for printing annotations.
const MCAsmInfo & MAI
Definition: MCInstPrinter.h:52
Instances of this class represent a single low-level machine instruction.
Definition: MCInst.h:185
Instances of this class represent operands of the MCInst class.
Definition: MCInst.h:37
int64_t getImm() const
Definition: MCInst.h:81
bool isImm() const
Definition: MCInst.h:63
bool isReg() const
Definition: MCInst.h:62
MCRegister getReg() const
Returns the register number.
Definition: MCInst.h:70
const MCExpr * getExpr() const
Definition: MCInst.h:115
bool isExpr() const
Definition: MCInst.h:66
Wrapper class representing physical registers. Should be passed by value.
Definition: MCRegister.h:33
Generic base class for all target subtargets.
Represent a reference to a symbol from inside an expression.
Definition: MCExpr.h:192
const MCSymbol & getSymbol() const
Definition: MCExpr.h:411
VariantKind getKind() const
Definition: MCExpr.h:413
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:51
LLVM Value Representation.
Definition: Value.h:74
void printInst(const MCInst *MI, uint64_t Address, StringRef Annot, const MCSubtargetInfo &STI, raw_ostream &O) override
Print the specified MCInst to the specified raw_ostream.
void printInstruction(const MCInst *MI, uint64_t Address, raw_ostream &O)
static const char * getRegisterName(MCRegister Reg)
void printRegName(raw_ostream &O, MCRegister Reg) override
Print the assembler register name.
static void printOperand(const MCOperand &MO, raw_ostream &O)
This class implements an extremely fast bulk output stream that can only output to a stream.
Definition: raw_ostream.h:52
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
@ Offset
Definition: DWP.cpp:480
void report_fatal_error(Error Err, bool gen_crash_diag=true)
Report a serious error, calling any installed error handler.
Definition: Error.cpp:167