LLVM 22.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"
18#include "llvm/MC/MCAsmInfo.h"
19#include "llvm/MC/MCExpr.h"
20#include "llvm/MC/MCInstrInfo.h"
21#include "llvm/MC/MCRegister.h"
22#include "llvm/MC/MCSymbol.h"
25
26using namespace llvm;
27
28#define DEBUG_TYPE "asm-printer"
29
30#include "XtensaGenAsmWriter.inc"
31
32static void printExpr(const MCExpr *Expr, raw_ostream &OS) {
33 int Offset = 0;
34 const MCSymbolRefExpr *SRE;
35
36 if (!(SRE = cast<MCSymbolRefExpr>(Expr)))
37 assert(false && "Unexpected MCExpr type.");
38
39 assert(SRE->getSpecifier() == 0);
40
41 OS << SRE->getSymbol();
42
43 if (Offset) {
44 if (Offset > 0)
45 OS << '+';
46 OS << Offset;
47 }
48}
49
51 if (MC.isReg())
52 O << getRegisterName(MC.getReg());
53 else if (MC.isImm())
54 O << MC.getImm();
55 else if (MC.isExpr())
56 printExpr(MC.getExpr(), O);
57 else
58 report_fatal_error("Invalid operand");
59}
60
67
71
72void XtensaInstPrinter::printOperand(const MCInst *MI, int OpNum,
73 raw_ostream &O) {
74 printOperand(MI->getOperand(OpNum), O);
75}
76
77void XtensaInstPrinter::printMemOperand(const MCInst *MI, int OpNum,
78 raw_ostream &OS) {
79 OS << getRegisterName(MI->getOperand(OpNum).getReg());
80 OS << ", ";
81 printOperand(MI, OpNum + 1, OS);
82}
83
84void XtensaInstPrinter::printBranchTarget(const MCInst *MI, uint64_t Address,
85 int OpNum, raw_ostream &O) {
86 const MCOperand &MC = MI->getOperand(OpNum);
87 if (MI->getOperand(OpNum).isImm()) {
88 int64_t Val = MC.getImm() + 4;
89 printPCRelImm(Address, Val, O);
90 } else if (MC.isExpr())
91 MAI.printExpr(O, *MC.getExpr());
92 else
93 llvm_unreachable("Invalid operand");
94}
95
96void XtensaInstPrinter::printLoopTarget(const MCInst *MI, uint64_t Address,
97 int OpNum, raw_ostream &O) {
98 const MCOperand &MC = MI->getOperand(OpNum);
99 if (MI->getOperand(OpNum).isImm()) {
100 int64_t Val = MC.getImm() + 4;
101 printPCRelImm(Address, Val, O);
102 } else if (MC.isExpr())
103 MAI.printExpr(O, *MC.getExpr());
104 else
105 llvm_unreachable("Invalid operand");
106}
107
108void XtensaInstPrinter::printJumpTarget(const MCInst *MI, uint64_t Address,
109 int OpNum, raw_ostream &O) {
110 const MCOperand &MC = MI->getOperand(OpNum);
111 if (MC.isImm()) {
112 int64_t Val = MC.getImm() + 4;
113 printPCRelImm(Address, Val, O);
114 } else if (MC.isExpr())
115 MAI.printExpr(O, *MC.getExpr());
116 else
117 llvm_unreachable("Invalid operand");
118 ;
119}
120
121void XtensaInstPrinter::printCallOperand(const MCInst *MI, uint64_t Address,
122 int OpNum, raw_ostream &O) {
123 const MCOperand &MC = MI->getOperand(OpNum);
124 if (MC.isImm()) {
125 int64_t Val = MC.getImm() + 4;
127 uint64_t Target = Address;
128 Target &= ~0x3;
129 Target += Val & (~0x3);
130 O << formatHex(Target);
131 } else {
132 O << ". ";
133 if (Val > 0)
134 O << '+';
135 O << Val;
136 }
137 } else if (MC.isExpr())
138 MAI.printExpr(O, *MC.getExpr());
139 else
140 llvm_unreachable("Invalid operand");
141}
142
143void XtensaInstPrinter::printL32RTarget(const MCInst *MI, uint64_t Address,
144 int OpNum, raw_ostream &O) {
145 const MCOperand &MC = MI->getOperand(OpNum);
146 if (MC.isImm()) {
147 int64_t Value = MI->getOperand(OpNum).getImm();
149 uint64_t Target = (Address + 0x3) & (~0x3);
150 Value &= ~0x3;
151 Target += Value;
152 O << formatHex(Target);
153 } else {
154 int64_t InstrOff = Value & 0x3;
155 Value -= InstrOff;
156 assert((Value >= -262144 && Value <= -4) &&
157 "Invalid argument, value must be in ranges [-262144,-4]");
158 Value += ((InstrOff + 0x3) & 0x4) - InstrOff;
159 printPCRelImm(Address, Value, O);
160 }
161 } else if (MC.isExpr())
162 MAI.printExpr(O, *MC.getExpr());
163 else
164 llvm_unreachable("Invalid operand");
165}
166
167void XtensaInstPrinter::printPCRelImm(uint64_t Address, int64_t Offset,
168 raw_ostream &O) {
170 uint64_t Target = Address + Offset;
171 Target &= 0xffffffff;
172 O << formatHex(Target);
173 } else {
174 O << ". ";
175 if (Offset > 0)
176 O << '+';
177 O << Offset;
178 }
179}
180
181void XtensaInstPrinter::printImm8_AsmOperand(const MCInst *MI, int OpNum,
182 raw_ostream &O) {
183 if (MI->getOperand(OpNum).isImm()) {
184 int64_t Value = MI->getOperand(OpNum).getImm();
186 "Invalid argument, value must be in ranges [-128,127]");
187 O << Value;
188 } else {
189 printOperand(MI, OpNum, O);
190 }
191}
192
193void XtensaInstPrinter::printImm8_sh8_AsmOperand(const MCInst *MI, int OpNum,
194 raw_ostream &O) {
195 if (MI->getOperand(OpNum).isImm()) {
196 int64_t Value = MI->getOperand(OpNum).getImm();
197 assert((isInt<16>(Value) && ((Value & 0xFF) == 0)) &&
198 "Invalid argument, value must be multiples of 256 in range "
199 "[-32768,32512]");
200 O << Value;
201 } else
202 printOperand(MI, OpNum, O);
203}
204
205void XtensaInstPrinter::printImm12_AsmOperand(const MCInst *MI, int OpNum,
206 raw_ostream &O) {
207 if (MI->getOperand(OpNum).isImm()) {
208 int64_t Value = MI->getOperand(OpNum).getImm();
209 assert((Value >= -2048 && Value <= 2047) &&
210 "Invalid argument, value must be in ranges [-2048,2047]");
211 O << Value;
212 } else
213 printOperand(MI, OpNum, O);
214}
215
216void XtensaInstPrinter::printImm12m_AsmOperand(const MCInst *MI, int OpNum,
217 raw_ostream &O) {
218 if (MI->getOperand(OpNum).isImm()) {
219 int64_t Value = MI->getOperand(OpNum).getImm();
220 assert((Value >= -2048 && Value <= 2047) &&
221 "Invalid argument, value must be in ranges [-2048,2047]");
222 O << Value;
223 } else
224 printOperand(MI, OpNum, O);
225}
226
227void XtensaInstPrinter::printUimm4_AsmOperand(const MCInst *MI, int OpNum,
228 raw_ostream &O) {
229 if (MI->getOperand(OpNum).isImm()) {
230 int64_t Value = MI->getOperand(OpNum).getImm();
231 assert((Value >= 0 && Value <= 15) && "Invalid argument");
232 O << Value;
233 } else
234 printOperand(MI, OpNum, O);
235}
236
237void XtensaInstPrinter::printUimm5_AsmOperand(const MCInst *MI, int OpNum,
238 raw_ostream &O) {
239 if (MI->getOperand(OpNum).isImm()) {
240 int64_t Value = MI->getOperand(OpNum).getImm();
241 assert((Value >= 0 && Value <= 31) && "Invalid argument");
242 O << Value;
243 } else
244 printOperand(MI, OpNum, O);
245}
246
247void XtensaInstPrinter::printShimm1_31_AsmOperand(const MCInst *MI, int OpNum,
248 raw_ostream &O) {
249 if (MI->getOperand(OpNum).isImm()) {
250 int64_t Value = MI->getOperand(OpNum).getImm();
251 assert((Value >= 1 && Value <= 31) &&
252 "Invalid argument, value must be in range [1,31]");
253 O << Value;
254 } else
255 printOperand(MI, OpNum, O);
256}
257
258void XtensaInstPrinter::printImm1_16_AsmOperand(const MCInst *MI, int OpNum,
259 raw_ostream &O) {
260 if (MI->getOperand(OpNum).isImm()) {
261 int64_t Value = MI->getOperand(OpNum).getImm();
262 assert((Value >= 1 && Value <= 16) &&
263 "Invalid argument, value must be in range [1,16]");
264 O << Value;
265 } else
266 printOperand(MI, OpNum, O);
267}
268
269void XtensaInstPrinter::printImm1n_15_AsmOperand(const MCInst *MI, int OpNum,
270 raw_ostream &O) {
271 if (MI->getOperand(OpNum).isImm()) {
272 int64_t Value = MI->getOperand(OpNum).getImm();
273 assert((Value >= -1 && (Value != 0) && Value <= 15) &&
274 "Invalid argument, value must be in ranges <-1,-1> or <1,15>");
275 O << Value;
276 } else
277 printOperand(MI, OpNum, O);
278}
279
280void XtensaInstPrinter::printImm32n_95_AsmOperand(const MCInst *MI, int OpNum,
281 raw_ostream &O) {
282 if (MI->getOperand(OpNum).isImm()) {
283 int64_t Value = MI->getOperand(OpNum).getImm();
284 assert((Value >= -32 && Value <= 95) &&
285 "Invalid argument, value must be in ranges <-32,95>");
286 O << Value;
287 } else
288 printOperand(MI, OpNum, O);
289}
290
291void XtensaInstPrinter::printImm8n_7_AsmOperand(const MCInst *MI, int OpNum,
292 raw_ostream &O) {
293 if (MI->getOperand(OpNum).isImm()) {
294 int64_t Value = MI->getOperand(OpNum).getImm();
295 assert((Value >= -8 && Value <= 7) &&
296 "Invalid argument, value must be in ranges <-8,7>");
297 O << Value;
298 } else
299 printOperand(MI, OpNum, O);
300}
301
302void XtensaInstPrinter::printImm64n_4n_AsmOperand(const MCInst *MI, int OpNum,
303 raw_ostream &O) {
304 if (MI->getOperand(OpNum).isImm()) {
305 int64_t Value = MI->getOperand(OpNum).getImm();
306 assert((Value >= -64 && Value <= -4) & ((Value & 0x3) == 0) &&
307 "Invalid argument, value must be in ranges <-64,-4>");
308 O << Value;
309 } else
310 printOperand(MI, OpNum, O);
311}
312
313void XtensaInstPrinter::printOffset8m8_AsmOperand(const MCInst *MI, int OpNum,
314 raw_ostream &O) {
315 if (MI->getOperand(OpNum).isImm()) {
316 int64_t Value = MI->getOperand(OpNum).getImm();
317 assert((Value >= 0 && Value <= 255) &&
318 "Invalid argument, value must be in range [0,255]");
319 O << Value;
320 } else
321 printOperand(MI, OpNum, O);
322}
323
324void XtensaInstPrinter::printOffset8m16_AsmOperand(const MCInst *MI, int OpNum,
325 raw_ostream &O) {
326 if (MI->getOperand(OpNum).isImm()) {
327 int64_t Value = MI->getOperand(OpNum).getImm();
328 assert((Value >= 0 && Value <= 510 && ((Value & 0x1) == 0)) &&
329 "Invalid argument, value must be multiples of two in range [0,510]");
330 O << Value;
331 } else
332 printOperand(MI, OpNum, O);
333}
334
335void XtensaInstPrinter::printOffset8m32_AsmOperand(const MCInst *MI, int OpNum,
336 raw_ostream &O) {
337 if (MI->getOperand(OpNum).isImm()) {
338 int64_t Value = MI->getOperand(OpNum).getImm();
339 assert(
340 (Value >= 0 && Value <= 1020 && ((Value & 0x3) == 0)) &&
341 "Invalid argument, value must be multiples of four in range [0,1020]");
342 O << Value;
343 } else
344 printOperand(MI, OpNum, O);
345}
346
347void XtensaInstPrinter::printOffset4m32_AsmOperand(const MCInst *MI, int OpNum,
348 raw_ostream &O) {
349 if (MI->getOperand(OpNum).isImm()) {
350 int64_t Value = MI->getOperand(OpNum).getImm();
351 assert((Value >= 0 && Value <= 60 && ((Value & 0x3) == 0)) &&
352 "Invalid argument, value must be multiples of four in range [0,60]");
353 O << Value;
354 } else
355 printOperand(MI, OpNum, O);
356}
357
358void XtensaInstPrinter::printEntry_Imm12_AsmOperand(const MCInst *MI, int OpNum,
359 raw_ostream &O) {
360 if (MI->getOperand(OpNum).isImm()) {
361 int64_t Value = MI->getOperand(OpNum).getImm();
362 assert((Value >= 0 && Value <= 32760) &&
363 "Invalid argument, value must be multiples of eight in range "
364 "<0,32760>");
365 O << Value;
366 } else
367 printOperand(MI, OpNum, O);
368}
369
370void XtensaInstPrinter::printB4const_AsmOperand(const MCInst *MI, int OpNum,
371 raw_ostream &O) {
372 if (MI->getOperand(OpNum).isImm()) {
373 int64_t Value = MI->getOperand(OpNum).getImm();
374
375 switch (Value) {
376 case -1:
377 case 1:
378 case 2:
379 case 3:
380 case 4:
381 case 5:
382 case 6:
383 case 7:
384 case 8:
385 case 10:
386 case 12:
387 case 16:
388 case 32:
389 case 64:
390 case 128:
391 case 256:
392 break;
393 default:
394 assert((0) && "Invalid B4const argument");
395 }
396 O << Value;
397 } else
398 printOperand(MI, OpNum, O);
399}
400
401void XtensaInstPrinter::printB4constu_AsmOperand(const MCInst *MI, int OpNum,
402 raw_ostream &O) {
403 if (MI->getOperand(OpNum).isImm()) {
404 int64_t Value = MI->getOperand(OpNum).getImm();
405
406 switch (Value) {
407 case 32768:
408 case 65536:
409 case 2:
410 case 3:
411 case 4:
412 case 5:
413 case 6:
414 case 7:
415 case 8:
416 case 10:
417 case 12:
418 case 16:
419 case 32:
420 case 64:
421 case 128:
422 case 256:
423 break;
424 default:
425 assert((0) && "Invalid B4constu argument");
426 }
427 O << Value;
428 } else
429 printOperand(MI, OpNum, O);
430}
431
432void XtensaInstPrinter::printImm7_22_AsmOperand(const MCInst *MI, int OpNum,
433 raw_ostream &O) {
434 if (MI->getOperand(OpNum).isImm()) {
435 int64_t Value = MI->getOperand(OpNum).getImm();
436 assert((Value >= 7 && Value <= 22) &&
437 "Invalid argument, value must be in range <7,22>");
438 O << Value;
439 } else
440 printOperand(MI, OpNum, O);
441}
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static void printExpr(const MCExpr *Expr, const MCAsmInfo *MAI, raw_ostream &OS)
IRTranslator LLVM IR MI
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
format_object< int64_t > formatHex(int64_t Value) const
void printAnnotation(raw_ostream &OS, StringRef Annot)
Utility function for printing annotations.
const MCAsmInfo & MAI
bool PrintBranchImmAsAddress
If true, a branch immediate (e.g.
Instances of this class represent a single low-level machine instruction.
Definition MCInst.h:188
Instances of this class represent operands of the MCInst class.
Definition MCInst.h:40
int64_t getImm() const
Definition MCInst.h:84
bool isImm() const
Definition MCInst.h:66
bool isReg() const
Definition MCInst.h:65
MCRegister getReg() const
Returns the register number.
Definition MCInst.h:73
const MCExpr * getExpr() const
Definition MCInst.h:118
bool isExpr() const
Definition MCInst.h:69
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:190
const MCSymbol & getSymbol() const
Definition MCExpr.h:227
uint16_t getSpecifier() const
Definition MCExpr.h:233
StringRef - Represent a constant reference to a string, i.e.
Definition StringRef.h:55
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:53
#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.
@ Offset
Definition DWP.cpp:477
FunctionAddr VTableAddr Value
Definition InstrProf.h:137
constexpr bool isInt(int64_t x)
Checks if an integer fits into the given bit width.
Definition MathExtras.h:174
LLVM_ABI void report_fatal_error(Error Err, bool gen_crash_diag=true)
Definition Error.cpp:167
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:565