xref: /freebsd/contrib/llvm-project/llvm/lib/Target/Xtensa/MCTargetDesc/XtensaMCCodeEmitter.cpp (revision 06c3fb2749bda94cb5201f81ffdb8fa6c3161b2e)
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