1 //===-- XtensaMCCodeEmitter.cpp - Convert Xtensa Code to Machine Code -----===//
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 file implements the XtensaMCCodeEmitter class.
12 //
13 //===----------------------------------------------------------------------===//
14
15 #include "MCTargetDesc/XtensaFixupKinds.h"
16 #include "MCTargetDesc/XtensaMCExpr.h"
17 #include "MCTargetDesc/XtensaMCTargetDesc.h"
18 #include "llvm/MC/MCCodeEmitter.h"
19 #include "llvm/MC/MCContext.h"
20 #include "llvm/MC/MCExpr.h"
21 #include "llvm/MC/MCInst.h"
22 #include "llvm/MC/MCInstrInfo.h"
23 #include "llvm/MC/MCRegisterInfo.h"
24
25 #define GET_INSTRMAP_INFO
26 #include "XtensaGenInstrInfo.inc"
27 #undef GET_INSTRMAP_INFO
28
29 using namespace llvm;
30
31 #define DEBUG_TYPE "mccodeemitter"
32
33 namespace {
34 class XtensaMCCodeEmitter : public MCCodeEmitter {
35 const MCInstrInfo &MCII;
36 MCContext &Ctx;
37 bool IsLittleEndian;
38
39 public:
XtensaMCCodeEmitter(const MCInstrInfo & mcii,MCContext & ctx,bool isLE)40 XtensaMCCodeEmitter(const MCInstrInfo &mcii, MCContext &ctx, bool isLE)
41 : MCII(mcii), Ctx(ctx), IsLittleEndian(isLE) {}
42
~XtensaMCCodeEmitter()43 ~XtensaMCCodeEmitter() {}
44
45 // OVerride MCCodeEmitter.
46 void encodeInstruction(const MCInst &MI, SmallVectorImpl<char> &CB,
47 SmallVectorImpl<MCFixup> &Fixups,
48 const MCSubtargetInfo &STI) const override;
49
50 private:
51 // Automatically generated by TableGen.
52 uint64_t getBinaryCodeForInstr(const MCInst &MI,
53 SmallVectorImpl<MCFixup> &Fixups,
54 const MCSubtargetInfo &STI) const;
55
56 // Called by the TableGen code to get the binary encoding of operand
57 // MO in MI. Fixups is the list of fixups against MI.
58 uint32_t getMachineOpValue(const MCInst &MI, const MCOperand &MO,
59 SmallVectorImpl<MCFixup> &Fixups,
60 const MCSubtargetInfo &STI) const;
61
62 uint32_t getJumpTargetEncoding(const MCInst &MI, unsigned int OpNum,
63 SmallVectorImpl<MCFixup> &Fixups,
64 const MCSubtargetInfo &STI) const;
65
66 uint32_t getBranchTargetEncoding(const MCInst &MI, unsigned int OpNum,
67 SmallVectorImpl<MCFixup> &Fixups,
68 const MCSubtargetInfo &STI) const;
69
70 uint32_t getCallEncoding(const MCInst &MI, unsigned int OpNum,
71 SmallVectorImpl<MCFixup> &Fixups,
72 const MCSubtargetInfo &STI) const;
73
74 uint32_t getL32RTargetEncoding(const MCInst &MI, unsigned OpNum,
75 SmallVectorImpl<MCFixup> &Fixups,
76 const MCSubtargetInfo &STI) const;
77
78 uint32_t getMemRegEncoding(const MCInst &MI, unsigned OpNo,
79 SmallVectorImpl<MCFixup> &Fixups,
80 const MCSubtargetInfo &STI) const;
81
82 uint32_t getImm8OpValue(const MCInst &MI, unsigned OpNo,
83 SmallVectorImpl<MCFixup> &Fixups,
84 const MCSubtargetInfo &STI) const;
85
86 uint32_t getImm8_sh8OpValue(const MCInst &MI, unsigned OpNo,
87 SmallVectorImpl<MCFixup> &Fixups,
88 const MCSubtargetInfo &STI) const;
89
90 uint32_t getImm12OpValue(const MCInst &MI, unsigned OpNo,
91 SmallVectorImpl<MCFixup> &Fixups,
92 const MCSubtargetInfo &STI) const;
93
94 uint32_t getUimm4OpValue(const MCInst &MI, unsigned OpNo,
95 SmallVectorImpl<MCFixup> &Fixups,
96 const MCSubtargetInfo &STI) const;
97
98 uint32_t getUimm5OpValue(const MCInst &MI, unsigned OpNo,
99 SmallVectorImpl<MCFixup> &Fixups,
100 const MCSubtargetInfo &STI) const;
101
102 uint32_t getImm1_16OpValue(const MCInst &MI, unsigned OpNo,
103 SmallVectorImpl<MCFixup> &Fixups,
104 const MCSubtargetInfo &STI) const;
105
106 uint32_t getShimm1_31OpValue(const MCInst &MI, unsigned OpNo,
107 SmallVectorImpl<MCFixup> &Fixups,
108 const MCSubtargetInfo &STI) const;
109
110 uint32_t getB4constOpValue(const MCInst &MI, unsigned OpNo,
111 SmallVectorImpl<MCFixup> &Fixups,
112 const MCSubtargetInfo &STI) const;
113
114 uint32_t getB4constuOpValue(const MCInst &MI, unsigned OpNo,
115 SmallVectorImpl<MCFixup> &Fixups,
116 const MCSubtargetInfo &STI) const;
117 };
118 } // namespace
119
createXtensaMCCodeEmitter(const MCInstrInfo & MCII,MCContext & Ctx)120 MCCodeEmitter *llvm::createXtensaMCCodeEmitter(const MCInstrInfo &MCII,
121 MCContext &Ctx) {
122 return new XtensaMCCodeEmitter(MCII, Ctx, true);
123 }
124
encodeInstruction(const MCInst & MI,SmallVectorImpl<char> & CB,SmallVectorImpl<MCFixup> & Fixups,const MCSubtargetInfo & STI) const125 void XtensaMCCodeEmitter::encodeInstruction(const MCInst &MI,
126 SmallVectorImpl<char> &CB,
127 SmallVectorImpl<MCFixup> &Fixups,
128 const MCSubtargetInfo &STI) const {
129 uint64_t Bits = getBinaryCodeForInstr(MI, Fixups, STI);
130 unsigned Size = MCII.get(MI.getOpcode()).getSize();
131
132 if (IsLittleEndian) {
133 // Little-endian insertion of Size bytes.
134 unsigned ShiftValue = 0;
135 for (unsigned I = 0; I != Size; ++I) {
136 CB.push_back(char(Bits >> ShiftValue));
137 ShiftValue += 8;
138 }
139 } else {
140 // TODO Big-endian insertion of Size bytes.
141 report_fatal_error("Big-endian mode currently is not supported!");
142 }
143 }
144
145 uint32_t
getMachineOpValue(const MCInst & MI,const MCOperand & MO,SmallVectorImpl<MCFixup> & Fixups,const MCSubtargetInfo & STI) const146 XtensaMCCodeEmitter::getMachineOpValue(const MCInst &MI, const MCOperand &MO,
147 SmallVectorImpl<MCFixup> &Fixups,
148 const MCSubtargetInfo &STI) const {
149 if (MO.isReg())
150 return Ctx.getRegisterInfo()->getEncodingValue(MO.getReg());
151 if (MO.isImm()) {
152 uint32_t Res = static_cast<uint32_t>(MO.getImm());
153 return Res;
154 }
155
156 report_fatal_error("Unhandled expression!");
157 return 0;
158 }
159
160 uint32_t
getJumpTargetEncoding(const MCInst & MI,unsigned int OpNum,SmallVectorImpl<MCFixup> & Fixups,const MCSubtargetInfo & STI) const161 XtensaMCCodeEmitter::getJumpTargetEncoding(const MCInst &MI, unsigned int OpNum,
162 SmallVectorImpl<MCFixup> &Fixups,
163 const MCSubtargetInfo &STI) const {
164 const MCOperand &MO = MI.getOperand(OpNum);
165
166 if (MO.isImm())
167 return MO.getImm();
168
169 const MCExpr *Expr = MO.getExpr();
170 Fixups.push_back(MCFixup::create(
171 0, Expr, MCFixupKind(Xtensa::fixup_xtensa_jump_18), MI.getLoc()));
172 return 0;
173 }
174
getBranchTargetEncoding(const MCInst & MI,unsigned int OpNum,SmallVectorImpl<MCFixup> & Fixups,const MCSubtargetInfo & STI) const175 uint32_t XtensaMCCodeEmitter::getBranchTargetEncoding(
176 const MCInst &MI, unsigned int OpNum, SmallVectorImpl<MCFixup> &Fixups,
177 const MCSubtargetInfo &STI) const {
178 const MCOperand &MO = MI.getOperand(OpNum);
179 if (MO.isImm())
180 return static_cast<uint32_t>(MO.getImm());
181
182 const MCExpr *Expr = MO.getExpr();
183 switch (MI.getOpcode()) {
184 case Xtensa::BEQZ:
185 case Xtensa::BGEZ:
186 case Xtensa::BLTZ:
187 case Xtensa::BNEZ:
188 Fixups.push_back(MCFixup::create(
189 0, Expr, MCFixupKind(Xtensa::fixup_xtensa_branch_12), MI.getLoc()));
190 return 0;
191 default:
192 Fixups.push_back(MCFixup::create(
193 0, Expr, MCFixupKind(Xtensa::fixup_xtensa_branch_8), MI.getLoc()));
194 return 0;
195 }
196 }
197
198 uint32_t
getCallEncoding(const MCInst & MI,unsigned int OpNum,SmallVectorImpl<MCFixup> & Fixups,const MCSubtargetInfo & STI) const199 XtensaMCCodeEmitter::getCallEncoding(const MCInst &MI, unsigned int OpNum,
200 SmallVectorImpl<MCFixup> &Fixups,
201 const MCSubtargetInfo &STI) const {
202 const MCOperand &MO = MI.getOperand(OpNum);
203 if (MO.isImm()) {
204 int32_t Res = MO.getImm();
205 if (Res & 0x3) {
206 llvm_unreachable("Unexpected operand value!");
207 }
208 Res >>= 2;
209 return Res;
210 }
211
212 assert((MO.isExpr()) && "Unexpected operand value!");
213 const MCExpr *Expr = MO.getExpr();
214 Fixups.push_back(MCFixup::create(
215 0, Expr, MCFixupKind(Xtensa::fixup_xtensa_call_18), MI.getLoc()));
216 return 0;
217 }
218
219 uint32_t
getL32RTargetEncoding(const MCInst & MI,unsigned OpNum,SmallVectorImpl<MCFixup> & Fixups,const MCSubtargetInfo & STI) const220 XtensaMCCodeEmitter::getL32RTargetEncoding(const MCInst &MI, unsigned OpNum,
221 SmallVectorImpl<MCFixup> &Fixups,
222 const MCSubtargetInfo &STI) const {
223 const MCOperand &MO = MI.getOperand(OpNum);
224 if (MO.isImm()) {
225 int32_t Res = MO.getImm();
226 // We don't check first 2 bits, because in these bits we could store first 2
227 // bits of instruction address
228 Res >>= 2;
229 return Res;
230 }
231
232 assert((MO.isExpr()) && "Unexpected operand value!");
233
234 Fixups.push_back(MCFixup::create(
235 0, MO.getExpr(), MCFixupKind(Xtensa::fixup_xtensa_l32r_16), MI.getLoc()));
236 return 0;
237 }
238
239 uint32_t
getMemRegEncoding(const MCInst & MI,unsigned OpNo,SmallVectorImpl<MCFixup> & Fixups,const MCSubtargetInfo & STI) const240 XtensaMCCodeEmitter::getMemRegEncoding(const MCInst &MI, unsigned OpNo,
241 SmallVectorImpl<MCFixup> &Fixups,
242 const MCSubtargetInfo &STI) const {
243 assert(MI.getOperand(OpNo + 1).isImm());
244
245 uint32_t Res = static_cast<uint32_t>(MI.getOperand(OpNo + 1).getImm());
246
247 switch (MI.getOpcode()) {
248 case Xtensa::S16I:
249 case Xtensa::L16SI:
250 case Xtensa::L16UI:
251 if (Res & 0x1) {
252 report_fatal_error("Unexpected operand value!");
253 }
254 Res >>= 1;
255 break;
256 case Xtensa::S32I:
257 case Xtensa::L32I:
258 if (Res & 0x3) {
259 report_fatal_error("Unexpected operand value!");
260 }
261 Res >>= 2;
262 break;
263 }
264
265 assert((isUInt<8>(Res)) && "Unexpected operand value!");
266
267 uint32_t OffBits = Res << 4;
268 uint32_t RegBits = getMachineOpValue(MI, MI.getOperand(OpNo), Fixups, STI);
269
270 return ((OffBits & 0xFF0) | RegBits);
271 }
272
getImm8OpValue(const MCInst & MI,unsigned OpNo,SmallVectorImpl<MCFixup> & Fixups,const MCSubtargetInfo & STI) const273 uint32_t XtensaMCCodeEmitter::getImm8OpValue(const MCInst &MI, unsigned OpNo,
274 SmallVectorImpl<MCFixup> &Fixups,
275 const MCSubtargetInfo &STI) const {
276 const MCOperand &MO = MI.getOperand(OpNo);
277 int32_t Res = MO.getImm();
278
279 assert(((Res >= -128) && (Res <= 127)) && "Unexpected operand value!");
280
281 return (Res & 0xff);
282 }
283
284 uint32_t
getImm8_sh8OpValue(const MCInst & MI,unsigned OpNo,SmallVectorImpl<MCFixup> & Fixups,const MCSubtargetInfo & STI) const285 XtensaMCCodeEmitter::getImm8_sh8OpValue(const MCInst &MI, unsigned OpNo,
286 SmallVectorImpl<MCFixup> &Fixups,
287 const MCSubtargetInfo &STI) const {
288 const MCOperand &MO = MI.getOperand(OpNo);
289 int32_t Res = MO.getImm();
290
291 assert(((Res >= -32768) && (Res <= 32512) && ((Res & 0xff) == 0)) &&
292 "Unexpected operand value!");
293
294 return (Res & 0xffff);
295 }
296
297 uint32_t
getImm12OpValue(const MCInst & MI,unsigned OpNo,SmallVectorImpl<MCFixup> & Fixups,const MCSubtargetInfo & STI) const298 XtensaMCCodeEmitter::getImm12OpValue(const MCInst &MI, unsigned OpNo,
299 SmallVectorImpl<MCFixup> &Fixups,
300 const MCSubtargetInfo &STI) const {
301 const MCOperand &MO = MI.getOperand(OpNo);
302 int32_t Res = MO.getImm();
303
304 assert(((Res >= -2048) && (Res <= 2047)) && "Unexpected operand value!");
305
306 return (Res & 0xfff);
307 }
308
309 uint32_t
getUimm4OpValue(const MCInst & MI,unsigned OpNo,SmallVectorImpl<MCFixup> & Fixups,const MCSubtargetInfo & STI) const310 XtensaMCCodeEmitter::getUimm4OpValue(const MCInst &MI, unsigned OpNo,
311 SmallVectorImpl<MCFixup> &Fixups,
312 const MCSubtargetInfo &STI) const {
313 const MCOperand &MO = MI.getOperand(OpNo);
314 uint32_t Res = static_cast<uint32_t>(MO.getImm());
315
316 assert((Res <= 15) && "Unexpected operand value!");
317
318 return Res & 0xf;
319 }
320
321 uint32_t
getUimm5OpValue(const MCInst & MI,unsigned OpNo,SmallVectorImpl<MCFixup> & Fixups,const MCSubtargetInfo & STI) const322 XtensaMCCodeEmitter::getUimm5OpValue(const MCInst &MI, unsigned OpNo,
323 SmallVectorImpl<MCFixup> &Fixups,
324 const MCSubtargetInfo &STI) const {
325 const MCOperand &MO = MI.getOperand(OpNo);
326 uint32_t Res = static_cast<uint32_t>(MO.getImm());
327
328 assert((Res <= 31) && "Unexpected operand value!");
329
330 return (Res & 0x1f);
331 }
332
333 uint32_t
getShimm1_31OpValue(const MCInst & MI,unsigned OpNo,SmallVectorImpl<MCFixup> & Fixups,const MCSubtargetInfo & STI) const334 XtensaMCCodeEmitter::getShimm1_31OpValue(const MCInst &MI, unsigned OpNo,
335 SmallVectorImpl<MCFixup> &Fixups,
336 const MCSubtargetInfo &STI) const {
337 const MCOperand &MO = MI.getOperand(OpNo);
338 uint32_t Res = static_cast<uint32_t>(MO.getImm());
339
340 assert(((Res >= 1) && (Res <= 31)) && "Unexpected operand value!");
341
342 return ((32 - Res) & 0x1f);
343 }
344
345 uint32_t
getImm1_16OpValue(const MCInst & MI,unsigned OpNo,SmallVectorImpl<MCFixup> & Fixups,const MCSubtargetInfo & STI) const346 XtensaMCCodeEmitter::getImm1_16OpValue(const MCInst &MI, unsigned OpNo,
347 SmallVectorImpl<MCFixup> &Fixups,
348 const MCSubtargetInfo &STI) const {
349 const MCOperand &MO = MI.getOperand(OpNo);
350 uint32_t Res = static_cast<uint32_t>(MO.getImm());
351
352 assert(((Res >= 1) && (Res <= 16)) && "Unexpected operand value!");
353
354 return (Res - 1);
355 }
356
357 uint32_t
getB4constOpValue(const MCInst & MI,unsigned OpNo,SmallVectorImpl<MCFixup> & Fixups,const MCSubtargetInfo & STI) const358 XtensaMCCodeEmitter::getB4constOpValue(const MCInst &MI, unsigned OpNo,
359 SmallVectorImpl<MCFixup> &Fixups,
360 const MCSubtargetInfo &STI) const {
361 const MCOperand &MO = MI.getOperand(OpNo);
362 uint32_t Res = static_cast<uint32_t>(MO.getImm());
363
364 switch (Res) {
365 case 0xffffffff:
366 Res = 0;
367 break;
368 case 1:
369 case 2:
370 case 3:
371 case 4:
372 case 5:
373 case 6:
374 case 7:
375 case 8:
376 break;
377 case 10:
378 Res = 9;
379 break;
380 case 12:
381 Res = 10;
382 break;
383 case 16:
384 Res = 11;
385 break;
386 case 32:
387 Res = 12;
388 break;
389 case 64:
390 Res = 13;
391 break;
392 case 128:
393 Res = 14;
394 break;
395 case 256:
396 Res = 15;
397 break;
398 default:
399 llvm_unreachable("Unexpected operand value!");
400 }
401
402 return Res;
403 }
404
405 uint32_t
getB4constuOpValue(const MCInst & MI,unsigned OpNo,SmallVectorImpl<MCFixup> & Fixups,const MCSubtargetInfo & STI) const406 XtensaMCCodeEmitter::getB4constuOpValue(const MCInst &MI, unsigned OpNo,
407 SmallVectorImpl<MCFixup> &Fixups,
408 const MCSubtargetInfo &STI) const {
409 const MCOperand &MO = MI.getOperand(OpNo);
410 uint32_t Res = static_cast<uint32_t>(MO.getImm());
411
412 switch (Res) {
413 case 32768:
414 Res = 0;
415 break;
416 case 65536:
417 Res = 1;
418 break;
419 case 2:
420 case 3:
421 case 4:
422 case 5:
423 case 6:
424 case 7:
425 case 8:
426 break;
427 case 10:
428 Res = 9;
429 break;
430 case 12:
431 Res = 10;
432 break;
433 case 16:
434 Res = 11;
435 break;
436 case 32:
437 Res = 12;
438 break;
439 case 64:
440 Res = 13;
441 break;
442 case 128:
443 Res = 14;
444 break;
445 case 256:
446 Res = 15;
447 break;
448 default:
449 llvm_unreachable("Unexpected operand value!");
450 }
451
452 return Res;
453 }
454 #include "XtensaGenMCCodeEmitter.inc"
455