xref: /llvm-project/llvm/lib/Target/Xtensa/MCTargetDesc/XtensaMCCodeEmitter.cpp (revision d064d3fc2cf8841963151f428988475aab09ff56)
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:
40   XtensaMCCodeEmitter(const MCInstrInfo &mcii, MCContext &ctx, bool isLE)
41       : MCII(mcii), Ctx(ctx), IsLittleEndian(isLE) {}
42 
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 getImm1n_15OpValue(const MCInst &MI, unsigned OpNo,
107                               SmallVectorImpl<MCFixup> &Fixups,
108                               const MCSubtargetInfo &STI) const;
109 
110   uint32_t getImm32n_95OpValue(const MCInst &MI, unsigned OpNo,
111                                SmallVectorImpl<MCFixup> &Fixups,
112                                const MCSubtargetInfo &STI) const;
113 
114   uint32_t getShimm1_31OpValue(const MCInst &MI, unsigned OpNo,
115                                SmallVectorImpl<MCFixup> &Fixups,
116                                const MCSubtargetInfo &STI) const;
117 
118   uint32_t getB4constOpValue(const MCInst &MI, unsigned OpNo,
119                              SmallVectorImpl<MCFixup> &Fixups,
120                              const MCSubtargetInfo &STI) const;
121 
122   uint32_t getB4constuOpValue(const MCInst &MI, unsigned OpNo,
123                               SmallVectorImpl<MCFixup> &Fixups,
124                               const MCSubtargetInfo &STI) const;
125 };
126 } // namespace
127 
128 MCCodeEmitter *llvm::createXtensaMCCodeEmitter(const MCInstrInfo &MCII,
129                                                MCContext &Ctx) {
130   return new XtensaMCCodeEmitter(MCII, Ctx, true);
131 }
132 
133 void XtensaMCCodeEmitter::encodeInstruction(const MCInst &MI,
134                                             SmallVectorImpl<char> &CB,
135                                             SmallVectorImpl<MCFixup> &Fixups,
136                                             const MCSubtargetInfo &STI) const {
137   uint64_t Bits = getBinaryCodeForInstr(MI, Fixups, STI);
138   unsigned Size = MCII.get(MI.getOpcode()).getSize();
139 
140   if (IsLittleEndian) {
141     // Little-endian insertion of Size bytes.
142     unsigned ShiftValue = 0;
143     for (unsigned I = 0; I != Size; ++I) {
144       CB.push_back(char(Bits >> ShiftValue));
145       ShiftValue += 8;
146     }
147   } else {
148     // TODO Big-endian insertion of Size bytes.
149     report_fatal_error("Big-endian mode currently is not supported!");
150   }
151 }
152 
153 uint32_t
154 XtensaMCCodeEmitter::getMachineOpValue(const MCInst &MI, const MCOperand &MO,
155                                        SmallVectorImpl<MCFixup> &Fixups,
156                                        const MCSubtargetInfo &STI) const {
157   if (MO.isReg())
158     return Ctx.getRegisterInfo()->getEncodingValue(MO.getReg());
159   if (MO.isImm()) {
160     uint32_t Res = static_cast<uint32_t>(MO.getImm());
161     return Res;
162   }
163 
164   report_fatal_error("Unhandled expression!");
165   return 0;
166 }
167 
168 uint32_t
169 XtensaMCCodeEmitter::getJumpTargetEncoding(const MCInst &MI, unsigned int OpNum,
170                                            SmallVectorImpl<MCFixup> &Fixups,
171                                            const MCSubtargetInfo &STI) const {
172   const MCOperand &MO = MI.getOperand(OpNum);
173 
174   if (MO.isImm())
175     return MO.getImm();
176 
177   const MCExpr *Expr = MO.getExpr();
178   Fixups.push_back(MCFixup::create(
179       0, Expr, MCFixupKind(Xtensa::fixup_xtensa_jump_18), MI.getLoc()));
180   return 0;
181 }
182 
183 uint32_t XtensaMCCodeEmitter::getBranchTargetEncoding(
184     const MCInst &MI, unsigned int OpNum, SmallVectorImpl<MCFixup> &Fixups,
185     const MCSubtargetInfo &STI) const {
186   const MCOperand &MO = MI.getOperand(OpNum);
187   if (MO.isImm())
188     return static_cast<uint32_t>(MO.getImm());
189 
190   const MCExpr *Expr = MO.getExpr();
191   switch (MI.getOpcode()) {
192   case Xtensa::BEQZ:
193   case Xtensa::BGEZ:
194   case Xtensa::BLTZ:
195   case Xtensa::BNEZ:
196     Fixups.push_back(MCFixup::create(
197         0, Expr, MCFixupKind(Xtensa::fixup_xtensa_branch_12), MI.getLoc()));
198     return 0;
199   case Xtensa::BEQZ_N:
200   case Xtensa::BNEZ_N:
201     Fixups.push_back(MCFixup::create(
202         0, Expr, MCFixupKind(Xtensa::fixup_xtensa_branch_6), MI.getLoc()));
203     return 0;
204   default:
205     Fixups.push_back(MCFixup::create(
206         0, Expr, MCFixupKind(Xtensa::fixup_xtensa_branch_8), MI.getLoc()));
207     return 0;
208   }
209 }
210 
211 uint32_t
212 XtensaMCCodeEmitter::getCallEncoding(const MCInst &MI, unsigned int OpNum,
213                                      SmallVectorImpl<MCFixup> &Fixups,
214                                      const MCSubtargetInfo &STI) const {
215   const MCOperand &MO = MI.getOperand(OpNum);
216   if (MO.isImm()) {
217     int32_t Res = MO.getImm();
218     if (Res & 0x3) {
219       llvm_unreachable("Unexpected operand value!");
220     }
221     Res >>= 2;
222     return Res;
223   }
224 
225   assert((MO.isExpr()) && "Unexpected operand value!");
226   const MCExpr *Expr = MO.getExpr();
227   Fixups.push_back(MCFixup::create(
228       0, Expr, MCFixupKind(Xtensa::fixup_xtensa_call_18), MI.getLoc()));
229   return 0;
230 }
231 
232 uint32_t
233 XtensaMCCodeEmitter::getL32RTargetEncoding(const MCInst &MI, unsigned OpNum,
234                                            SmallVectorImpl<MCFixup> &Fixups,
235                                            const MCSubtargetInfo &STI) const {
236   const MCOperand &MO = MI.getOperand(OpNum);
237   if (MO.isImm()) {
238     int32_t Res = MO.getImm();
239     // We don't check first 2 bits, because in these bits we could store first 2
240     // bits of instruction address
241     Res >>= 2;
242     return Res;
243   }
244 
245   assert((MO.isExpr()) && "Unexpected operand value!");
246 
247   Fixups.push_back(MCFixup::create(
248       0, MO.getExpr(), MCFixupKind(Xtensa::fixup_xtensa_l32r_16), MI.getLoc()));
249   return 0;
250 }
251 
252 uint32_t
253 XtensaMCCodeEmitter::getMemRegEncoding(const MCInst &MI, unsigned OpNo,
254                                        SmallVectorImpl<MCFixup> &Fixups,
255                                        const MCSubtargetInfo &STI) const {
256   assert(MI.getOperand(OpNo + 1).isImm());
257 
258   uint32_t Res = static_cast<uint32_t>(MI.getOperand(OpNo + 1).getImm());
259 
260   switch (MI.getOpcode()) {
261   case Xtensa::S16I:
262   case Xtensa::L16SI:
263   case Xtensa::L16UI:
264     if (Res & 0x1) {
265       report_fatal_error("Unexpected operand value!");
266     }
267     Res >>= 1;
268     break;
269   case Xtensa::S32I:
270   case Xtensa::L32I:
271   case Xtensa::S32I_N:
272   case Xtensa::L32I_N:
273     if (Res & 0x3) {
274       report_fatal_error("Unexpected operand value!");
275     }
276     Res >>= 2;
277     break;
278   }
279 
280   switch (MI.getOpcode()) {
281   case Xtensa::S32I_N:
282   case Xtensa::L32I_N:
283     assert((isUInt<4>(Res)) && "Unexpected operand value!");
284     break;
285   default:
286     assert((isUInt<8>(Res)) && "Unexpected operand value!");
287     break;
288   }
289 
290   uint32_t OffBits = Res << 4;
291   uint32_t RegBits = getMachineOpValue(MI, MI.getOperand(OpNo), Fixups, STI);
292 
293   return ((OffBits & 0xFF0) | RegBits);
294 }
295 
296 uint32_t XtensaMCCodeEmitter::getImm8OpValue(const MCInst &MI, unsigned OpNo,
297                                              SmallVectorImpl<MCFixup> &Fixups,
298                                              const MCSubtargetInfo &STI) const {
299   const MCOperand &MO = MI.getOperand(OpNo);
300   int32_t Res = MO.getImm();
301 
302   assert(((Res >= -128) && (Res <= 127)) && "Unexpected operand value!");
303 
304   return (Res & 0xff);
305 }
306 
307 uint32_t
308 XtensaMCCodeEmitter::getImm8_sh8OpValue(const MCInst &MI, unsigned OpNo,
309                                         SmallVectorImpl<MCFixup> &Fixups,
310                                         const MCSubtargetInfo &STI) const {
311   const MCOperand &MO = MI.getOperand(OpNo);
312   int32_t Res = MO.getImm();
313 
314   assert(((Res >= -32768) && (Res <= 32512) && ((Res & 0xff) == 0)) &&
315          "Unexpected operand value!");
316 
317   return (Res & 0xffff);
318 }
319 
320 uint32_t
321 XtensaMCCodeEmitter::getImm12OpValue(const MCInst &MI, unsigned OpNo,
322                                      SmallVectorImpl<MCFixup> &Fixups,
323                                      const MCSubtargetInfo &STI) const {
324   const MCOperand &MO = MI.getOperand(OpNo);
325   int32_t Res = MO.getImm();
326 
327   assert(((Res >= -2048) && (Res <= 2047)) && "Unexpected operand value!");
328 
329   return (Res & 0xfff);
330 }
331 
332 uint32_t
333 XtensaMCCodeEmitter::getUimm4OpValue(const MCInst &MI, unsigned OpNo,
334                                      SmallVectorImpl<MCFixup> &Fixups,
335                                      const MCSubtargetInfo &STI) const {
336   const MCOperand &MO = MI.getOperand(OpNo);
337   uint32_t Res = static_cast<uint32_t>(MO.getImm());
338 
339   assert((Res <= 15) && "Unexpected operand value!");
340 
341   return Res & 0xf;
342 }
343 
344 uint32_t
345 XtensaMCCodeEmitter::getUimm5OpValue(const MCInst &MI, unsigned OpNo,
346                                      SmallVectorImpl<MCFixup> &Fixups,
347                                      const MCSubtargetInfo &STI) const {
348   const MCOperand &MO = MI.getOperand(OpNo);
349   uint32_t Res = static_cast<uint32_t>(MO.getImm());
350 
351   assert((Res <= 31) && "Unexpected operand value!");
352 
353   return (Res & 0x1f);
354 }
355 
356 uint32_t
357 XtensaMCCodeEmitter::getShimm1_31OpValue(const MCInst &MI, unsigned OpNo,
358                                          SmallVectorImpl<MCFixup> &Fixups,
359                                          const MCSubtargetInfo &STI) const {
360   const MCOperand &MO = MI.getOperand(OpNo);
361   uint32_t Res = static_cast<uint32_t>(MO.getImm());
362 
363   assert(((Res >= 1) && (Res <= 31)) && "Unexpected operand value!");
364 
365   return ((32 - Res) & 0x1f);
366 }
367 
368 uint32_t
369 XtensaMCCodeEmitter::getImm1_16OpValue(const MCInst &MI, unsigned OpNo,
370                                        SmallVectorImpl<MCFixup> &Fixups,
371                                        const MCSubtargetInfo &STI) const {
372   const MCOperand &MO = MI.getOperand(OpNo);
373   uint32_t Res = static_cast<uint32_t>(MO.getImm());
374 
375   assert(((Res >= 1) && (Res <= 16)) && "Unexpected operand value!");
376 
377   return (Res - 1);
378 }
379 
380 uint32_t
381 XtensaMCCodeEmitter::getImm1n_15OpValue(const MCInst &MI, unsigned OpNo,
382                                         SmallVectorImpl<MCFixup> &Fixups,
383                                         const MCSubtargetInfo &STI) const {
384   const MCOperand &MO = MI.getOperand(OpNo);
385   int32_t Res = static_cast<int32_t>(MO.getImm());
386 
387   assert(((Res >= -1) && (Res <= 15) && (Res != 0)) &&
388          "Unexpected operand value!");
389 
390   if (Res < 0)
391     Res = 0;
392 
393   return Res;
394 }
395 
396 uint32_t
397 XtensaMCCodeEmitter::getImm32n_95OpValue(const MCInst &MI, unsigned OpNo,
398                                          SmallVectorImpl<MCFixup> &Fixups,
399                                          const MCSubtargetInfo &STI) const {
400   const MCOperand &MO = MI.getOperand(OpNo);
401   int32_t Res = static_cast<int32_t>(MO.getImm());
402 
403   assert(((Res >= -32) && (Res <= 95)) && "Unexpected operand value!");
404 
405   return Res;
406 }
407 
408 uint32_t
409 XtensaMCCodeEmitter::getB4constOpValue(const MCInst &MI, unsigned OpNo,
410                                        SmallVectorImpl<MCFixup> &Fixups,
411                                        const MCSubtargetInfo &STI) const {
412   const MCOperand &MO = MI.getOperand(OpNo);
413   uint32_t Res = static_cast<uint32_t>(MO.getImm());
414 
415   switch (Res) {
416   case 0xffffffff:
417     Res = 0;
418     break;
419   case 1:
420   case 2:
421   case 3:
422   case 4:
423   case 5:
424   case 6:
425   case 7:
426   case 8:
427     break;
428   case 10:
429     Res = 9;
430     break;
431   case 12:
432     Res = 10;
433     break;
434   case 16:
435     Res = 11;
436     break;
437   case 32:
438     Res = 12;
439     break;
440   case 64:
441     Res = 13;
442     break;
443   case 128:
444     Res = 14;
445     break;
446   case 256:
447     Res = 15;
448     break;
449   default:
450     llvm_unreachable("Unexpected operand value!");
451   }
452 
453   return Res;
454 }
455 
456 uint32_t
457 XtensaMCCodeEmitter::getB4constuOpValue(const MCInst &MI, unsigned OpNo,
458                                         SmallVectorImpl<MCFixup> &Fixups,
459                                         const MCSubtargetInfo &STI) const {
460   const MCOperand &MO = MI.getOperand(OpNo);
461   uint32_t Res = static_cast<uint32_t>(MO.getImm());
462 
463   switch (Res) {
464   case 32768:
465     Res = 0;
466     break;
467   case 65536:
468     Res = 1;
469     break;
470   case 2:
471   case 3:
472   case 4:
473   case 5:
474   case 6:
475   case 7:
476   case 8:
477     break;
478   case 10:
479     Res = 9;
480     break;
481   case 12:
482     Res = 10;
483     break;
484   case 16:
485     Res = 11;
486     break;
487   case 32:
488     Res = 12;
489     break;
490   case 64:
491     Res = 13;
492     break;
493   case 128:
494     Res = 14;
495     break;
496   case 256:
497     Res = 15;
498     break;
499   default:
500     llvm_unreachable("Unexpected operand value!");
501   }
502 
503   return Res;
504 }
505 #include "XtensaGenMCCodeEmitter.inc"
506