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"
16 #include "llvm/CodeGen/MachineOperand.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"
21 #include "llvm/Support/Casting.h"
22 #include "llvm/Support/raw_ostream.h"
23
24 using namespace llvm;
25
26 #define DEBUG_TYPE "asm-printer"
27
28 #include "XtensaGenAsmWriter.inc"
29
printExpr(const MCExpr * Expr,raw_ostream & OS)30 static 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
37 MCSymbolRefExpr::VariantKind Kind = SRE->getKind();
38
39 switch (Kind) {
40 case MCSymbolRefExpr::VK_None:
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
printOperand(const MCOperand & MC,raw_ostream & O)59 void XtensaInstPrinter::printOperand(const MCOperand &MC, raw_ostream &O) {
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
printInst(const MCInst * MI,uint64_t Address,StringRef Annot,const MCSubtargetInfo & STI,raw_ostream & O)70 void XtensaInstPrinter::printInst(const MCInst *MI, uint64_t Address,
71 StringRef Annot, const MCSubtargetInfo &STI,
72 raw_ostream &O) {
73 printInstruction(MI, Address, O);
74 printAnnotation(O, Annot);
75 }
76
printRegName(raw_ostream & O,MCRegister Reg) const77 void XtensaInstPrinter::printRegName(raw_ostream &O, MCRegister Reg) const {
78 O << getRegisterName(Reg);
79 }
80
printOperand(const MCInst * MI,int OpNum,raw_ostream & O)81 void XtensaInstPrinter::printOperand(const MCInst *MI, int OpNum,
82 raw_ostream &O) {
83 printOperand(MI->getOperand(OpNum), O);
84 }
85
printMemOperand(const MCInst * MI,int OpNum,raw_ostream & OS)86 void 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
printBranchTarget(const MCInst * MI,int OpNum,raw_ostream & OS)93 void 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
printJumpTarget(const MCInst * MI,int OpNum,raw_ostream & OS)108 void 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
printCallOperand(const MCInst * MI,int OpNum,raw_ostream & OS)124 void 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
printL32RTarget(const MCInst * MI,int OpNum,raw_ostream & O)139 void 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
printImm8_AsmOperand(const MCInst * MI,int OpNum,raw_ostream & O)157 void 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
printImm8_sh8_AsmOperand(const MCInst * MI,int OpNum,raw_ostream & O)169 void 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
printImm12_AsmOperand(const MCInst * MI,int OpNum,raw_ostream & O)181 void 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
printImm12m_AsmOperand(const MCInst * MI,int OpNum,raw_ostream & O)192 void 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
printUimm4_AsmOperand(const MCInst * MI,int OpNum,raw_ostream & O)203 void 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
printUimm5_AsmOperand(const MCInst * MI,int OpNum,raw_ostream & O)213 void 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
printShimm1_31_AsmOperand(const MCInst * MI,int OpNum,raw_ostream & O)223 void 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
printImm1_16_AsmOperand(const MCInst * MI,int OpNum,raw_ostream & O)234 void 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
printOffset8m8_AsmOperand(const MCInst * MI,int OpNum,raw_ostream & O)245 void 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
printOffset8m16_AsmOperand(const MCInst * MI,int OpNum,raw_ostream & O)256 void 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
printOffset8m32_AsmOperand(const MCInst * MI,int OpNum,raw_ostream & O)267 void 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
printOffset4m32_AsmOperand(const MCInst * MI,int OpNum,raw_ostream & O)279 void 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
printB4const_AsmOperand(const MCInst * MI,int OpNum,raw_ostream & O)290 void 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
printB4constu_AsmOperand(const MCInst * MI,int OpNum,raw_ostream & O)321 void 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 }
351