xref: /freebsd/contrib/llvm-project/llvm/lib/Target/CSKY/MCTargetDesc/CSKYMCCodeEmitter.cpp (revision 1342eb5a832fa10e689a29faab3acb6054e4778c)
1 //===-- CSKYMCCodeEmitter.cpp - CSKY Code Emitter interface ---------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // This file implements the CSKYMCCodeEmitter class.
10 //
11 //===----------------------------------------------------------------------===//
12 
13 #include "CSKYMCAsmInfo.h"
14 #include "MCTargetDesc/CSKYFixupKinds.h"
15 #include "MCTargetDesc/CSKYMCAsmInfo.h"
16 #include "MCTargetDesc/CSKYMCTargetDesc.h"
17 #include "llvm/ADT/Statistic.h"
18 #include "llvm/MC/MCCodeEmitter.h"
19 #include "llvm/MC/MCContext.h"
20 #include "llvm/MC/MCInstBuilder.h"
21 #include "llvm/MC/MCInstrInfo.h"
22 #include "llvm/MC/MCRegisterInfo.h"
23 #include "llvm/MC/MCSubtargetInfo.h"
24 #include "llvm/Support/Casting.h"
25 #include "llvm/Support/EndianStream.h"
26 
27 using namespace llvm;
28 
29 #define DEBUG_TYPE "csky-mccode-emitter"
30 
31 STATISTIC(MCNumEmitted, "Number of MC instructions emitted");
32 
33 static void addFixup(SmallVectorImpl<MCFixup> &Fixups, uint32_t Offset,
34                      const MCExpr *Value, uint16_t Kind) {
35   bool PCRel = false;
36   switch (Kind) {
37   case CSKY::Fixups::fixup_csky_pcrel_imm16_scale2:
38   case CSKY::Fixups::fixup_csky_pcrel_uimm16_scale4:
39   case CSKY::Fixups::fixup_csky_pcrel_imm26_scale2:
40   case CSKY::Fixups::fixup_csky_pcrel_imm18_scale2:
41   case CSKY::Fixups::fixup_csky_gotpc:
42   case CSKY::Fixups::fixup_csky_pcrel_imm10_scale2:
43   case CSKY::Fixups::fixup_csky_pcrel_uimm7_scale4:
44   case CSKY::Fixups::fixup_csky_pcrel_uimm8_scale4:
45     PCRel = true;
46   }
47   Fixups.push_back(MCFixup::create(Offset, Value, Kind, PCRel));
48 }
49 
50 namespace {
51 class CSKYMCCodeEmitter : public MCCodeEmitter {
52   MCContext &Ctx;
53   const MCInstrInfo &MII;
54 
55 public:
56   CSKYMCCodeEmitter(MCContext &Ctx, const MCInstrInfo &MII)
57       : Ctx(Ctx), MII(MII) {}
58 
59   ~CSKYMCCodeEmitter() {}
60 
61   void encodeInstruction(const MCInst &Inst, SmallVectorImpl<char> &CB,
62                          SmallVectorImpl<MCFixup> &Fixups,
63                          const MCSubtargetInfo &STI) const override;
64 
65   // Generated by tablegen.
66   uint64_t getBinaryCodeForInstr(const MCInst &MI,
67                                  SmallVectorImpl<MCFixup> &Fixups,
68                                  const MCSubtargetInfo &STI) const;
69 
70   // Default encoding method used by tablegen.
71   unsigned getMachineOpValue(const MCInst &MI, const MCOperand &MO,
72                              SmallVectorImpl<MCFixup> &Fixups,
73                              const MCSubtargetInfo &STI) const;
74 
75   template <int shift = 0>
76   unsigned getImmOpValue(const MCInst &MI, unsigned Idx,
77                          SmallVectorImpl<MCFixup> &Fixups,
78                          const MCSubtargetInfo &STI) const {
79     const MCOperand &MO = MI.getOperand(Idx);
80     if (MO.isImm())
81       return (MO.getImm() >> shift);
82 
83     assert(MO.isExpr() && "Unexpected MO type.");
84 
85     MCFixupKind Kind = getTargetFixup(MO.getExpr());
86     addFixup(Fixups, 0, MO.getExpr(), Kind);
87     return 0;
88   }
89 
90   unsigned getRegSeqImmOpValue(const MCInst &MI, unsigned Idx,
91                                SmallVectorImpl<MCFixup> &Fixups,
92                                const MCSubtargetInfo &STI) const;
93 
94   unsigned getRegisterSeqOpValue(const MCInst &MI, unsigned Op,
95                                  SmallVectorImpl<MCFixup> &Fixups,
96                                  const MCSubtargetInfo &STI) const;
97 
98   unsigned getOImmOpValue(const MCInst &MI, unsigned Idx,
99                           SmallVectorImpl<MCFixup> &Fixups,
100                           const MCSubtargetInfo &STI) const;
101 
102   unsigned getImmOpValueIDLY(const MCInst &MI, unsigned Idx,
103                              SmallVectorImpl<MCFixup> &Fixups,
104                              const MCSubtargetInfo &STI) const;
105 
106   unsigned getImmJMPIX(const MCInst &MI, unsigned Idx,
107                        SmallVectorImpl<MCFixup> &Fixups,
108                        const MCSubtargetInfo &STI) const;
109 
110   unsigned getImmOpValueMSBSize(const MCInst &MI, unsigned Idx,
111                                 SmallVectorImpl<MCFixup> &Fixups,
112                                 const MCSubtargetInfo &STI) const;
113 
114   unsigned getImmShiftOpValue(const MCInst &MI, unsigned Idx,
115                               SmallVectorImpl<MCFixup> &Fixups,
116                               const MCSubtargetInfo &STI) const {
117     const MCOperand &MO = MI.getOperand(Idx);
118     assert(MO.isImm() && "Unexpected MO type.");
119     return 1 << MO.getImm();
120   }
121 
122   MCFixupKind getTargetFixup(const MCExpr *Expr) const;
123 
124   template <llvm::CSKY::Fixups FIXUP>
125   unsigned getBranchSymbolOpValue(const MCInst &MI, unsigned Idx,
126                                   SmallVectorImpl<MCFixup> &Fixups,
127                                   const MCSubtargetInfo &STI) const {
128     const MCOperand &MO = MI.getOperand(Idx);
129 
130     if (MO.isImm())
131       return MO.getImm() >> 1;
132 
133     assert(MO.isExpr() && "Unexpected MO type.");
134 
135     MCFixupKind Kind = MCFixupKind(FIXUP);
136     if (MO.getExpr()->getKind() == MCExpr::Specifier)
137       Kind = getTargetFixup(MO.getExpr());
138 
139     addFixup(Fixups, 0, MO.getExpr(), Kind);
140     return 0;
141   }
142 
143   template <llvm::CSKY::Fixups FIXUP>
144   unsigned getConstpoolSymbolOpValue(const MCInst &MI, unsigned Idx,
145                                      SmallVectorImpl<MCFixup> &Fixups,
146                                      const MCSubtargetInfo &STI) const {
147     const MCOperand &MO = MI.getOperand(Idx);
148     assert(MO.isExpr() && "Unexpected MO type.");
149 
150     MCFixupKind Kind = MCFixupKind(FIXUP);
151     if (MO.getExpr()->getKind() == MCExpr::Specifier)
152       Kind = getTargetFixup(MO.getExpr());
153 
154     addFixup(Fixups, 0, MO.getExpr(), Kind);
155     return 0;
156   }
157 
158   template <llvm::CSKY::Fixups FIXUP>
159   unsigned getDataSymbolOpValue(const MCInst &MI, unsigned Idx,
160                                 SmallVectorImpl<MCFixup> &Fixups,
161                                 const MCSubtargetInfo &STI) const {
162     const MCOperand &MO = MI.getOperand(Idx);
163     assert(MO.isExpr() && "Unexpected MO type.");
164 
165     MCFixupKind Kind = MCFixupKind(FIXUP);
166     if (MO.getExpr()->getKind() == MCExpr::Specifier)
167       Kind = getTargetFixup(MO.getExpr());
168 
169     addFixup(Fixups, 0, MO.getExpr(), Kind);
170     return 0;
171   }
172 
173   unsigned getCallSymbolOpValue(const MCInst &MI, unsigned Idx,
174                                 SmallVectorImpl<MCFixup> &Fixups,
175                                 const MCSubtargetInfo &STI) const {
176     const MCOperand &MO = MI.getOperand(Idx);
177     assert(MO.isExpr() && "Unexpected MO type.");
178 
179     MCFixupKind Kind = CSKY::fixup_csky_pcrel_imm26_scale2;
180     if (MO.getExpr()->getKind() == MCExpr::Specifier)
181       Kind = getTargetFixup(MO.getExpr());
182 
183     addFixup(Fixups, 0, MO.getExpr(), Kind);
184     return 0;
185   }
186 
187   unsigned getBareSymbolOpValue(const MCInst &MI, unsigned Idx,
188                                 SmallVectorImpl<MCFixup> &Fixups,
189                                 const MCSubtargetInfo &STI) const {
190     const MCOperand &MO = MI.getOperand(Idx);
191     assert(MO.isExpr() && "Unexpected MO type.");
192 
193     MCFixupKind Kind = CSKY::fixup_csky_pcrel_imm18_scale2;
194     if (MO.getExpr()->getKind() == MCExpr::Specifier)
195       Kind = getTargetFixup(MO.getExpr());
196 
197     addFixup(Fixups, 0, MO.getExpr(), Kind);
198     return 0;
199   }
200 
201   void expandJBTF(const MCInst &MI, SmallVectorImpl<char> &CB,
202                   SmallVectorImpl<MCFixup> &Fixups,
203                   const MCSubtargetInfo &STI) const;
204   void expandNEG(const MCInst &MI, SmallVectorImpl<char> &CB,
205                  SmallVectorImpl<MCFixup> &Fixups,
206                  const MCSubtargetInfo &STI) const;
207   void expandRSUBI(const MCInst &MI, SmallVectorImpl<char> &CB,
208                    SmallVectorImpl<MCFixup> &Fixups,
209                    const MCSubtargetInfo &STI) const;
210 };
211 } // namespace
212 
213 unsigned CSKYMCCodeEmitter::getOImmOpValue(const MCInst &MI, unsigned Idx,
214                                            SmallVectorImpl<MCFixup> &Fixups,
215                                            const MCSubtargetInfo &STI) const {
216   const MCOperand &MO = MI.getOperand(Idx);
217   assert(MO.isImm() && "Unexpected MO type.");
218   return MO.getImm() - 1;
219 }
220 
221 unsigned
222 CSKYMCCodeEmitter::getImmOpValueIDLY(const MCInst &MI, unsigned Idx,
223                                      SmallVectorImpl<MCFixup> &Fixups,
224                                      const MCSubtargetInfo &STI) const {
225   const MCOperand &MO = MI.getOperand(Idx);
226   assert(MO.isImm() && "Unexpected MO type.");
227 
228   auto V = (MO.getImm() <= 3) ? 4 : MO.getImm();
229   return V - 1;
230 }
231 
232 unsigned
233 CSKYMCCodeEmitter::getImmOpValueMSBSize(const MCInst &MI, unsigned Idx,
234                                         SmallVectorImpl<MCFixup> &Fixups,
235                                         const MCSubtargetInfo &STI) const {
236   const MCOperand &MSB = MI.getOperand(Idx);
237   const MCOperand &LSB = MI.getOperand(Idx + 1);
238   assert(MSB.isImm() && LSB.isImm() && "Unexpected MO type.");
239 
240   return MSB.getImm() - LSB.getImm();
241 }
242 
243 static void writeData(uint32_t Bin, unsigned Size, SmallVectorImpl<char> &CB) {
244   if (Size == 4)
245     support::endian::write(CB, static_cast<uint16_t>(Bin >> 16),
246                            llvm::endianness::little);
247   support::endian::write(CB, static_cast<uint16_t>(Bin),
248                          llvm::endianness::little);
249 }
250 
251 void CSKYMCCodeEmitter::expandJBTF(const MCInst &MI, SmallVectorImpl<char> &CB,
252                                    SmallVectorImpl<MCFixup> &Fixups,
253                                    const MCSubtargetInfo &STI) const {
254 
255   MCInst TmpInst;
256 
257   uint32_t Binary;
258 
259   TmpInst =
260       MCInstBuilder(MI.getOpcode() == CSKY::JBT_E ? CSKY::BF16 : CSKY::BT16)
261           .addOperand(MI.getOperand(0))
262           .addImm(6);
263   Binary = getBinaryCodeForInstr(TmpInst, Fixups, STI);
264   writeData(Binary, 2, CB);
265 
266   if (!STI.hasFeature(CSKY::Has2E3))
267     TmpInst = MCInstBuilder(CSKY::BR32)
268                   .addOperand(MI.getOperand(1))
269                   .addOperand(MI.getOperand(2));
270   else
271     TmpInst = MCInstBuilder(CSKY::JMPI32).addOperand(MI.getOperand(2));
272   Binary = getBinaryCodeForInstr(TmpInst, Fixups, STI);
273   Fixups[Fixups.size() - 1].setOffset(2);
274   writeData(Binary, 4, CB);
275 }
276 
277 void CSKYMCCodeEmitter::expandNEG(const MCInst &MI, SmallVectorImpl<char> &CB,
278                                   SmallVectorImpl<MCFixup> &Fixups,
279                                   const MCSubtargetInfo &STI) const {
280 
281   MCInst TmpInst;
282   uint32_t Binary;
283   unsigned Size = MI.getOpcode() == CSKY::NEG32 ? 4 : 2;
284 
285   TmpInst = MCInstBuilder(Size == 4 ? CSKY::NOT32 : CSKY::NOT16)
286                 .addOperand(MI.getOperand(0))
287                 .addOperand(MI.getOperand(1));
288   Binary = getBinaryCodeForInstr(TmpInst, Fixups, STI);
289   writeData(Binary, Size, CB);
290 
291   TmpInst = MCInstBuilder(Size == 4 ? CSKY::ADDI32 : CSKY::ADDI16)
292                 .addOperand(MI.getOperand(0))
293                 .addOperand(MI.getOperand(0))
294                 .addImm(1);
295   Binary = getBinaryCodeForInstr(TmpInst, Fixups, STI);
296   writeData(Binary, Size, CB);
297 }
298 
299 void CSKYMCCodeEmitter::expandRSUBI(const MCInst &MI, SmallVectorImpl<char> &CB,
300                                     SmallVectorImpl<MCFixup> &Fixups,
301                                     const MCSubtargetInfo &STI) const {
302 
303   MCInst TmpInst;
304   uint32_t Binary;
305   unsigned Size = MI.getOpcode() == CSKY::RSUBI32 ? 4 : 2;
306 
307   TmpInst = MCInstBuilder(Size == 4 ? CSKY::NOT32 : CSKY::NOT16)
308                 .addOperand(MI.getOperand(0))
309                 .addOperand(MI.getOperand(1));
310   Binary = getBinaryCodeForInstr(TmpInst, Fixups, STI);
311   writeData(Binary, Size, CB);
312 
313   TmpInst = MCInstBuilder(Size == 4 ? CSKY::ADDI32 : CSKY::ADDI16)
314                 .addOperand(MI.getOperand(0))
315                 .addOperand(MI.getOperand(0))
316                 .addImm(MI.getOperand(2).getImm() + 1);
317   Binary = getBinaryCodeForInstr(TmpInst, Fixups, STI);
318   writeData(Binary, Size, CB);
319 }
320 
321 void CSKYMCCodeEmitter::encodeInstruction(const MCInst &MI,
322                                           SmallVectorImpl<char> &CB,
323                                           SmallVectorImpl<MCFixup> &Fixups,
324                                           const MCSubtargetInfo &STI) const {
325   const MCInstrDesc &Desc = MII.get(MI.getOpcode());
326   unsigned Size = Desc.getSize();
327 
328   MCInst TmpInst;
329 
330   switch (MI.getOpcode()) {
331   default:
332     TmpInst = MI;
333     break;
334   case CSKY::JBT_E:
335   case CSKY::JBF_E:
336     expandJBTF(MI, CB, Fixups, STI);
337     MCNumEmitted += 2;
338     return;
339   case CSKY::NEG32:
340   case CSKY::NEG16:
341     expandNEG(MI, CB, Fixups, STI);
342     MCNumEmitted += 2;
343     return;
344   case CSKY::RSUBI32:
345   case CSKY::RSUBI16:
346     expandRSUBI(MI, CB, Fixups, STI);
347     MCNumEmitted += 2;
348     return;
349   case CSKY::JBSR32:
350     TmpInst = MCInstBuilder(CSKY::BSR32).addOperand(MI.getOperand(0));
351     break;
352   case CSKY::JBR16:
353     TmpInst = MCInstBuilder(CSKY::BR16).addOperand(MI.getOperand(0));
354     break;
355   case CSKY::JBR32:
356     TmpInst = MCInstBuilder(CSKY::BR32).addOperand(MI.getOperand(0));
357     break;
358   case CSKY::JBT16:
359     TmpInst = MCInstBuilder(CSKY::BT16)
360                   .addOperand(MI.getOperand(0))
361                   .addOperand(MI.getOperand(1));
362     break;
363   case CSKY::JBT32:
364     TmpInst = MCInstBuilder(CSKY::BT32)
365                   .addOperand(MI.getOperand(0))
366                   .addOperand(MI.getOperand(1));
367     break;
368   case CSKY::JBF16:
369     TmpInst = MCInstBuilder(CSKY::BF16)
370                   .addOperand(MI.getOperand(0))
371                   .addOperand(MI.getOperand(1));
372     break;
373   case CSKY::JBF32:
374     TmpInst = MCInstBuilder(CSKY::BF32)
375                   .addOperand(MI.getOperand(0))
376                   .addOperand(MI.getOperand(1));
377     break;
378   case CSKY::LRW32_Gen:
379     TmpInst = MCInstBuilder(CSKY::LRW32)
380                   .addOperand(MI.getOperand(0))
381                   .addOperand(MI.getOperand(2));
382     break;
383   case CSKY::LRW16_Gen:
384     TmpInst = MCInstBuilder(CSKY::LRW16)
385                   .addOperand(MI.getOperand(0))
386                   .addOperand(MI.getOperand(2));
387     break;
388   case CSKY::CMPLEI32:
389     TmpInst = MCInstBuilder(CSKY::CMPLTI32)
390                   .addOperand(MI.getOperand(0))
391                   .addOperand(MI.getOperand(1))
392                   .addImm(MI.getOperand(2).getImm() + 1);
393     break;
394   case CSKY::CMPLEI16:
395     TmpInst = MCInstBuilder(CSKY::CMPLTI16)
396                   .addOperand(MI.getOperand(0))
397                   .addOperand(MI.getOperand(1))
398                   .addImm(MI.getOperand(2).getImm() + 1);
399     break;
400   case CSKY::ROTRI32:
401     TmpInst = MCInstBuilder(CSKY::ROTLI32)
402                   .addOperand(MI.getOperand(0))
403                   .addOperand(MI.getOperand(1))
404                   .addImm(32 - MI.getOperand(2).getImm());
405     break;
406   case CSKY::BGENI:
407     auto V = 1 << MI.getOperand(1).getImm();
408     TmpInst =
409         MCInstBuilder(CSKY::MOVI32).addOperand(MI.getOperand(0)).addImm(V);
410     break;
411   }
412 
413   ++MCNumEmitted;
414   writeData(getBinaryCodeForInstr(TmpInst, Fixups, STI), Size, CB);
415 }
416 
417 unsigned
418 CSKYMCCodeEmitter::getMachineOpValue(const MCInst &MI, const MCOperand &MO,
419                                      SmallVectorImpl<MCFixup> &Fixups,
420                                      const MCSubtargetInfo &STI) const {
421   if (MO.isReg())
422     return Ctx.getRegisterInfo()->getEncodingValue(MO.getReg());
423 
424   if (MO.isImm())
425     return static_cast<unsigned>(MO.getImm());
426 
427   llvm_unreachable("Unhandled expression!");
428   return 0;
429 }
430 
431 unsigned
432 CSKYMCCodeEmitter::getRegSeqImmOpValue(const MCInst &MI, unsigned Idx,
433                                        SmallVectorImpl<MCFixup> &Fixups,
434                                        const MCSubtargetInfo &STI) const {
435   assert(MI.getOperand(Idx).isReg() && "Unexpected MO type.");
436   assert(MI.getOperand(Idx + 1).isImm() && "Unexpected MO type.");
437 
438   unsigned Ry = MI.getOperand(Idx).getReg();
439   unsigned Rz = MI.getOperand(Idx + 1).getImm();
440 
441   unsigned Imm = Ctx.getRegisterInfo()->getEncodingValue(Rz) -
442                  Ctx.getRegisterInfo()->getEncodingValue(Ry);
443 
444   return ((Ctx.getRegisterInfo()->getEncodingValue(Ry) << 5) | Imm);
445 }
446 
447 unsigned
448 CSKYMCCodeEmitter::getRegisterSeqOpValue(const MCInst &MI, unsigned Op,
449                                          SmallVectorImpl<MCFixup> &Fixups,
450                                          const MCSubtargetInfo &STI) const {
451   unsigned Reg1 =
452       Ctx.getRegisterInfo()->getEncodingValue(MI.getOperand(Op).getReg());
453   unsigned Reg2 =
454       Ctx.getRegisterInfo()->getEncodingValue(MI.getOperand(Op + 1).getReg());
455 
456   unsigned Binary = ((Reg1 & 0x1f) << 5) | (Reg2 - Reg1);
457 
458   return Binary;
459 }
460 
461 unsigned CSKYMCCodeEmitter::getImmJMPIX(const MCInst &MI, unsigned Idx,
462                                         SmallVectorImpl<MCFixup> &Fixups,
463                                         const MCSubtargetInfo &STI) const {
464   switch (MI.getOperand(Idx).getImm()) {
465   default:
466     llvm_unreachable("Unhandled jmpix imm!");
467   case 16:
468     return 0;
469   case 24:
470     return 1;
471   case 32:
472     return 2;
473   case 40:
474     return 3;
475   }
476 }
477 
478 MCFixupKind CSKYMCCodeEmitter::getTargetFixup(const MCExpr *Expr) const {
479   const auto *CSKYExpr = cast<MCSpecifierExpr>(Expr);
480   switch (CSKYExpr->getSpecifier()) {
481   default:
482     llvm_unreachable("Unhandled fixup kind!");
483   case CSKY::S_ADDR:
484     return CSKY::fixup_csky_addr32;
485   case CSKY::S_ADDR_HI16:
486     return CSKY::fixup_csky_addr_hi16;
487   case CSKY::S_ADDR_LO16:
488     return CSKY::fixup_csky_addr_lo16;
489   case CSKY::S_GOT:
490     return CSKY::fixup_csky_got32;
491   case CSKY::S_GOTPC:
492     return CSKY::fixup_csky_gotpc;
493   case CSKY::S_GOTOFF:
494     return CSKY::fixup_csky_gotoff;
495   case CSKY::S_PLT:
496     return CSKY::fixup_csky_plt32;
497   case CSKY::S_PLT_IMM18_BY4:
498     return CSKY::fixup_csky_plt_imm18_scale4;
499   case CSKY::S_GOT_IMM18_BY4:
500     return CSKY::fixup_csky_got_imm18_scale4;
501   }
502 }
503 
504 MCCodeEmitter *llvm::createCSKYMCCodeEmitter(const MCInstrInfo &MCII,
505                                              MCContext &Ctx) {
506   return new CSKYMCCodeEmitter(Ctx, MCII);
507 }
508 
509 #include "CSKYGenMCCodeEmitter.inc"
510