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