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 "CSKYMCCodeEmitter.h"
14 #include "CSKYMCExpr.h"
15 #include "MCTargetDesc/CSKYMCTargetDesc.h"
16 #include "llvm/ADT/Statistic.h"
17 #include "llvm/MC/MCInstBuilder.h"
18 #include "llvm/MC/MCInstrInfo.h"
19 #include "llvm/MC/MCRegisterInfo.h"
20 #include "llvm/MC/MCSubtargetInfo.h"
21 #include "llvm/Support/Casting.h"
22 #include "llvm/Support/EndianStream.h"
23 
24 using namespace llvm;
25 
26 #define DEBUG_TYPE "csky-mccode-emitter"
27 
28 STATISTIC(MCNumEmitted, "Number of MC instructions emitted");
29 
getOImmOpValue(const MCInst & MI,unsigned Idx,SmallVectorImpl<MCFixup> & Fixups,const MCSubtargetInfo & STI) const30 unsigned CSKYMCCodeEmitter::getOImmOpValue(const MCInst &MI, unsigned Idx,
31                                            SmallVectorImpl<MCFixup> &Fixups,
32                                            const MCSubtargetInfo &STI) const {
33   const MCOperand &MO = MI.getOperand(Idx);
34   assert(MO.isImm() && "Unexpected MO type.");
35   return MO.getImm() - 1;
36 }
37 
38 unsigned
getImmOpValueIDLY(const MCInst & MI,unsigned Idx,SmallVectorImpl<MCFixup> & Fixups,const MCSubtargetInfo & STI) const39 CSKYMCCodeEmitter::getImmOpValueIDLY(const MCInst &MI, unsigned Idx,
40                                      SmallVectorImpl<MCFixup> &Fixups,
41                                      const MCSubtargetInfo &STI) const {
42   const MCOperand &MO = MI.getOperand(Idx);
43   assert(MO.isImm() && "Unexpected MO type.");
44 
45   auto V = (MO.getImm() <= 3) ? 4 : MO.getImm();
46   return V - 1;
47 }
48 
49 unsigned
getImmOpValueMSBSize(const MCInst & MI,unsigned Idx,SmallVectorImpl<MCFixup> & Fixups,const MCSubtargetInfo & STI) const50 CSKYMCCodeEmitter::getImmOpValueMSBSize(const MCInst &MI, unsigned Idx,
51                                         SmallVectorImpl<MCFixup> &Fixups,
52                                         const MCSubtargetInfo &STI) const {
53   const MCOperand &MSB = MI.getOperand(Idx);
54   const MCOperand &LSB = MI.getOperand(Idx + 1);
55   assert(MSB.isImm() && LSB.isImm() && "Unexpected MO type.");
56 
57   return MSB.getImm() - LSB.getImm();
58 }
59 
writeData(uint32_t Bin,unsigned Size,raw_ostream & OS)60 static void writeData(uint32_t Bin, unsigned Size, raw_ostream &OS) {
61   uint16_t LO16 = static_cast<uint16_t>(Bin);
62   uint16_t HI16 = static_cast<uint16_t>(Bin >> 16);
63 
64   if (Size == 4)
65     support::endian::write<uint16_t>(OS, HI16, support::little);
66 
67   support::endian::write<uint16_t>(OS, LO16, support::little);
68 }
69 
expandJBTF(const MCInst & MI,raw_ostream & OS,SmallVectorImpl<MCFixup> & Fixups,const MCSubtargetInfo & STI) const70 void CSKYMCCodeEmitter::expandJBTF(const MCInst &MI, raw_ostream &OS,
71                                    SmallVectorImpl<MCFixup> &Fixups,
72                                    const MCSubtargetInfo &STI) const {
73 
74   MCInst TmpInst;
75 
76   uint32_t Binary;
77 
78   TmpInst =
79       MCInstBuilder(MI.getOpcode() == CSKY::JBT_E ? CSKY::BF16 : CSKY::BT16)
80           .addOperand(MI.getOperand(0))
81           .addImm(6);
82   Binary = getBinaryCodeForInstr(TmpInst, Fixups, STI);
83   writeData(Binary, 2, OS);
84 
85   if (!STI.getFeatureBits()[CSKY::Has2E3])
86     TmpInst = MCInstBuilder(CSKY::BR32)
87                   .addOperand(MI.getOperand(1))
88                   .addOperand(MI.getOperand(2));
89   else
90     TmpInst = MCInstBuilder(CSKY::JMPI32).addOperand(MI.getOperand(2));
91   Binary = getBinaryCodeForInstr(TmpInst, Fixups, STI);
92   Fixups[Fixups.size() - 1].setOffset(2);
93   writeData(Binary, 4, OS);
94 }
95 
expandNEG(const MCInst & MI,raw_ostream & OS,SmallVectorImpl<MCFixup> & Fixups,const MCSubtargetInfo & STI) const96 void CSKYMCCodeEmitter::expandNEG(const MCInst &MI, raw_ostream &OS,
97                                   SmallVectorImpl<MCFixup> &Fixups,
98                                   const MCSubtargetInfo &STI) const {
99 
100   MCInst TmpInst;
101   uint32_t Binary;
102   unsigned Size = MI.getOpcode() == CSKY::NEG32 ? 4 : 2;
103 
104   TmpInst = MCInstBuilder(Size == 4 ? CSKY::NOT32 : CSKY::NOT16)
105                 .addOperand(MI.getOperand(0))
106                 .addOperand(MI.getOperand(1));
107   Binary = getBinaryCodeForInstr(TmpInst, Fixups, STI);
108   writeData(Binary, Size, OS);
109 
110   TmpInst = MCInstBuilder(Size == 4 ? CSKY::ADDI32 : CSKY::ADDI16)
111                 .addOperand(MI.getOperand(0))
112                 .addOperand(MI.getOperand(0))
113                 .addImm(1);
114   Binary = getBinaryCodeForInstr(TmpInst, Fixups, STI);
115   writeData(Binary, Size, OS);
116 }
117 
expandRSUBI(const MCInst & MI,raw_ostream & OS,SmallVectorImpl<MCFixup> & Fixups,const MCSubtargetInfo & STI) const118 void CSKYMCCodeEmitter::expandRSUBI(const MCInst &MI, raw_ostream &OS,
119                                     SmallVectorImpl<MCFixup> &Fixups,
120                                     const MCSubtargetInfo &STI) const {
121 
122   MCInst TmpInst;
123   uint32_t Binary;
124   unsigned Size = MI.getOpcode() == CSKY::RSUBI32 ? 4 : 2;
125 
126   TmpInst = MCInstBuilder(Size == 4 ? CSKY::NOT32 : CSKY::NOT16)
127                 .addOperand(MI.getOperand(0))
128                 .addOperand(MI.getOperand(1));
129   Binary = getBinaryCodeForInstr(TmpInst, Fixups, STI);
130   writeData(Binary, Size, OS);
131 
132   TmpInst = MCInstBuilder(Size == 4 ? CSKY::ADDI32 : CSKY::ADDI16)
133                 .addOperand(MI.getOperand(0))
134                 .addOperand(MI.getOperand(0))
135                 .addImm(MI.getOperand(2).getImm() + 1);
136   Binary = getBinaryCodeForInstr(TmpInst, Fixups, STI);
137   writeData(Binary, Size, OS);
138 }
139 
encodeInstruction(const MCInst & MI,raw_ostream & OS,SmallVectorImpl<MCFixup> & Fixups,const MCSubtargetInfo & STI) const140 void CSKYMCCodeEmitter::encodeInstruction(const MCInst &MI, raw_ostream &OS,
141                                           SmallVectorImpl<MCFixup> &Fixups,
142                                           const MCSubtargetInfo &STI) const {
143   const MCInstrDesc &Desc = MII.get(MI.getOpcode());
144   unsigned Size = Desc.getSize();
145 
146   MCInst TmpInst;
147 
148   switch (MI.getOpcode()) {
149   default:
150     TmpInst = MI;
151     break;
152   case CSKY::JBT_E:
153   case CSKY::JBF_E:
154     expandJBTF(MI, OS, Fixups, STI);
155     MCNumEmitted += 2;
156     return;
157   case CSKY::NEG32:
158   case CSKY::NEG16:
159     expandNEG(MI, OS, Fixups, STI);
160     MCNumEmitted += 2;
161     return;
162   case CSKY::RSUBI32:
163   case CSKY::RSUBI16:
164     expandRSUBI(MI, OS, Fixups, STI);
165     MCNumEmitted += 2;
166     return;
167   case CSKY::JBSR32:
168     TmpInst = MCInstBuilder(CSKY::BSR32).addOperand(MI.getOperand(0));
169     break;
170   case CSKY::JBR16:
171     TmpInst = MCInstBuilder(CSKY::BR16).addOperand(MI.getOperand(0));
172     break;
173   case CSKY::JBR32:
174     TmpInst = MCInstBuilder(CSKY::BR32).addOperand(MI.getOperand(0));
175     break;
176   case CSKY::JBT16:
177     TmpInst = MCInstBuilder(CSKY::BT16)
178                   .addOperand(MI.getOperand(0))
179                   .addOperand(MI.getOperand(1));
180     break;
181   case CSKY::JBT32:
182     TmpInst = MCInstBuilder(CSKY::BT32)
183                   .addOperand(MI.getOperand(0))
184                   .addOperand(MI.getOperand(1));
185     break;
186   case CSKY::JBF16:
187     TmpInst = MCInstBuilder(CSKY::BF16)
188                   .addOperand(MI.getOperand(0))
189                   .addOperand(MI.getOperand(1));
190     break;
191   case CSKY::JBF32:
192     TmpInst = MCInstBuilder(CSKY::BF32)
193                   .addOperand(MI.getOperand(0))
194                   .addOperand(MI.getOperand(1));
195     break;
196   case CSKY::LRW32_Gen:
197     TmpInst = MCInstBuilder(CSKY::LRW32)
198                   .addOperand(MI.getOperand(0))
199                   .addOperand(MI.getOperand(2));
200     break;
201   case CSKY::LRW16_Gen:
202     TmpInst = MCInstBuilder(CSKY::LRW16)
203                   .addOperand(MI.getOperand(0))
204                   .addOperand(MI.getOperand(2));
205     break;
206   case CSKY::CMPLEI32:
207     TmpInst = MCInstBuilder(CSKY::CMPLTI32)
208                   .addOperand(MI.getOperand(0))
209                   .addOperand(MI.getOperand(1))
210                   .addImm(MI.getOperand(2).getImm() + 1);
211     break;
212   case CSKY::CMPLEI16:
213     TmpInst = MCInstBuilder(CSKY::CMPLTI16)
214                   .addOperand(MI.getOperand(0))
215                   .addOperand(MI.getOperand(1))
216                   .addImm(MI.getOperand(2).getImm() + 1);
217     break;
218   case CSKY::ROTRI32:
219     TmpInst = MCInstBuilder(CSKY::ROTLI32)
220                   .addOperand(MI.getOperand(0))
221                   .addOperand(MI.getOperand(1))
222                   .addImm(32 - MI.getOperand(2).getImm());
223     break;
224   case CSKY::BGENI:
225     auto V = 1 << MI.getOperand(1).getImm();
226     TmpInst =
227         MCInstBuilder(CSKY::MOVI32).addOperand(MI.getOperand(0)).addImm(V);
228     break;
229   }
230 
231   ++MCNumEmitted;
232 
233   uint32_t Bin = getBinaryCodeForInstr(TmpInst, Fixups, STI);
234 
235   uint16_t LO16 = static_cast<uint16_t>(Bin);
236   uint16_t HI16 = static_cast<uint16_t>(Bin >> 16);
237 
238   if (Size == 4)
239     support::endian::write<uint16_t>(OS, HI16, support::little);
240 
241   support::endian::write<uint16_t>(OS, LO16, support::little);
242 }
243 
244 unsigned
getMachineOpValue(const MCInst & MI,const MCOperand & MO,SmallVectorImpl<MCFixup> & Fixups,const MCSubtargetInfo & STI) const245 CSKYMCCodeEmitter::getMachineOpValue(const MCInst &MI, const MCOperand &MO,
246                                      SmallVectorImpl<MCFixup> &Fixups,
247                                      const MCSubtargetInfo &STI) const {
248   if (MO.isReg())
249     return Ctx.getRegisterInfo()->getEncodingValue(MO.getReg());
250 
251   if (MO.isImm())
252     return static_cast<unsigned>(MO.getImm());
253 
254   llvm_unreachable("Unhandled expression!");
255   return 0;
256 }
257 
258 unsigned
getRegSeqImmOpValue(const MCInst & MI,unsigned Idx,SmallVectorImpl<MCFixup> & Fixups,const MCSubtargetInfo & STI) const259 CSKYMCCodeEmitter::getRegSeqImmOpValue(const MCInst &MI, unsigned Idx,
260                                        SmallVectorImpl<MCFixup> &Fixups,
261                                        const MCSubtargetInfo &STI) const {
262   assert(MI.getOperand(Idx).isReg() && "Unexpected MO type.");
263   assert(MI.getOperand(Idx + 1).isImm() && "Unexpected MO type.");
264 
265   unsigned Ry = MI.getOperand(Idx).getReg();
266   unsigned Rz = MI.getOperand(Idx + 1).getImm();
267 
268   unsigned Imm = Ctx.getRegisterInfo()->getEncodingValue(Rz) -
269                  Ctx.getRegisterInfo()->getEncodingValue(Ry);
270 
271   return ((Ctx.getRegisterInfo()->getEncodingValue(Ry) << 5) | Imm);
272 }
273 
274 unsigned
getRegisterSeqOpValue(const MCInst & MI,unsigned Op,SmallVectorImpl<MCFixup> & Fixups,const MCSubtargetInfo & STI) const275 CSKYMCCodeEmitter::getRegisterSeqOpValue(const MCInst &MI, unsigned Op,
276                                          SmallVectorImpl<MCFixup> &Fixups,
277                                          const MCSubtargetInfo &STI) const {
278   unsigned Reg1 =
279       Ctx.getRegisterInfo()->getEncodingValue(MI.getOperand(Op).getReg());
280   unsigned Reg2 =
281       Ctx.getRegisterInfo()->getEncodingValue(MI.getOperand(Op + 1).getReg());
282 
283   unsigned Binary = ((Reg1 & 0x1f) << 5) | (Reg2 - Reg1);
284 
285   return Binary;
286 }
287 
getImmJMPIX(const MCInst & MI,unsigned Idx,SmallVectorImpl<MCFixup> & Fixups,const MCSubtargetInfo & STI) const288 unsigned CSKYMCCodeEmitter::getImmJMPIX(const MCInst &MI, unsigned Idx,
289                                         SmallVectorImpl<MCFixup> &Fixups,
290                                         const MCSubtargetInfo &STI) const {
291   if (MI.getOperand(Idx).getImm() == 16)
292     return 0;
293   else if (MI.getOperand(Idx).getImm() == 24)
294     return 1;
295   else if (MI.getOperand(Idx).getImm() == 32)
296     return 2;
297   else if (MI.getOperand(Idx).getImm() == 40)
298     return 3;
299   else
300     assert(0);
301 }
302 
getTargetFixup(const MCExpr * Expr) const303 MCFixupKind CSKYMCCodeEmitter::getTargetFixup(const MCExpr *Expr) const {
304   const CSKYMCExpr *CSKYExpr = cast<CSKYMCExpr>(Expr);
305 
306   switch (CSKYExpr->getKind()) {
307   default:
308     llvm_unreachable("Unhandled fixup kind!");
309   case CSKYMCExpr::VK_CSKY_ADDR:
310     return MCFixupKind(CSKY::fixup_csky_addr32);
311   case CSKYMCExpr::VK_CSKY_ADDR_HI16:
312     return MCFixupKind(CSKY::fixup_csky_addr_hi16);
313   case CSKYMCExpr::VK_CSKY_ADDR_LO16:
314     return MCFixupKind(CSKY::fixup_csky_addr_lo16);
315   case CSKYMCExpr::VK_CSKY_GOT:
316     return MCFixupKind(CSKY::fixup_csky_got32);
317   case CSKYMCExpr::VK_CSKY_GOTPC:
318     return MCFixupKind(CSKY::fixup_csky_gotpc);
319   case CSKYMCExpr::VK_CSKY_GOTOFF:
320     return MCFixupKind(CSKY::fixup_csky_gotoff);
321   case CSKYMCExpr::VK_CSKY_PLT:
322     return MCFixupKind(CSKY::fixup_csky_plt32);
323   case CSKYMCExpr::VK_CSKY_PLT_IMM18_BY4:
324     return MCFixupKind(CSKY::fixup_csky_plt_imm18_scale4);
325   case CSKYMCExpr::VK_CSKY_GOT_IMM18_BY4:
326     return MCFixupKind(CSKY::fixup_csky_got_imm18_scale4);
327   }
328 }
329 
createCSKYMCCodeEmitter(const MCInstrInfo & MCII,MCContext & Ctx)330 MCCodeEmitter *llvm::createCSKYMCCodeEmitter(const MCInstrInfo &MCII,
331                                              MCContext &Ctx) {
332   return new CSKYMCCodeEmitter(Ctx, MCII);
333 }
334 
335 #include "CSKYGenMCCodeEmitter.inc"
336