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::printOffset8m8_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 >= 0 && Value <= 255) &&
250 "Invalid argument, value must be in range [0,255]");
251 O << Value;
252 } else
253 printOperand(MI, OpNum, O);
254}
255
256void XtensaInstPrinter::printOffset8m16_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 >= 0 && Value <= 510 && ((Value & 0x1) == 0)) &&
261 "Invalid argument, value must be multiples of two in range [0,510]");
262 O << Value;
263 } else
264 printOperand(MI, OpNum, O);
265}
266
267void XtensaInstPrinter::printOffset8m32_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(
272 (Value >= 0 && Value <= 1020 && ((Value & 0x3) == 0)) &&
273 "Invalid argument, value must be multiples of four in range [0,1020]");
274 O << Value;
275 } else
276 printOperand(MI, OpNum, O);
277}
278
279void XtensaInstPrinter::printOffset4m32_AsmOperand(const MCInst *MI, int OpNum,
280 raw_ostream &O) {
281 if (MI->getOperand(OpNum).isImm()) {
282 int64_t Value = MI->getOperand(OpNum).getImm();
283 assert((Value >= 0 && Value <= 60 && ((Value & 0x3) == 0)) &&
284 "Invalid argument, value must be multiples of four in range [0,60]");
285 O << Value;
286 } else
287 printOperand(MI, OpNum, O);
288}
289
290void XtensaInstPrinter::printB4const_AsmOperand(const MCInst *MI, int OpNum,
291 raw_ostream &O) {
292 if (MI->getOperand(OpNum).isImm()) {
293 int64_t Value = MI->getOperand(OpNum).getImm();
294
295 switch (Value) {
296 case -1:
297 case 1:
298 case 2:
299 case 3:
300 case 4:
301 case 5:
302 case 6:
303 case 7:
304 case 8:
305 case 10:
306 case 12:
307 case 16:
308 case 32:
309 case 64:
310 case 128:
311 case 256:
312 break;
313 default:
314 assert((0) && "Invalid B4const argument");
315 }
316 O << Value;
317 } else
318 printOperand(MI, OpNum, O);
319}
320
321void XtensaInstPrinter::printB4constu_AsmOperand(const MCInst *MI, int OpNum,
322 raw_ostream &O) {
323 if (MI->getOperand(OpNum).isImm()) {
324 int64_t Value = MI->getOperand(OpNum).getImm();
325
326 switch (Value) {
327 case 32768:
328 case 65536:
329 case 2:
330 case 3:
331 case 4:
332 case 5:
333 case 6:
334 case 7:
335 case 8:
336 case 10:
337 case 12:
338 case 16:
339 case 32:
340 case 64:
341 case 128:
342 case 256:
343 break;
344 default:
345 assert((0) && "Invalid B4constu argument");
346 }
347 O << Value;
348 } else
349 printOperand(MI, OpNum, O);
350}
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:51
Instances of this class represent a single low-level machine instruction.
Definition: MCInst.h:184
Instances of this class represent operands of the MCInst class.
Definition: MCInst.h:36
int64_t getImm() const
Definition: MCInst.h:80
bool isImm() const
Definition: MCInst.h:62
unsigned getReg() const
Returns the register number.
Definition: MCInst.h:69
bool isReg() const
Definition: MCInst.h:61
const MCExpr * getExpr() const
Definition: MCInst.h:114
bool isExpr() const
Definition: MCInst.h:65
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:188
const MCSymbol & getSymbol() const
Definition: MCExpr.h:406
VariantKind getKind() const
Definition: MCExpr.h:408
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:50
LLVM Value Representation.
Definition: Value.h:74
void printRegName(raw_ostream &O, MCRegister Reg) const override
Print the assembler register name.
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)
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