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,SmallVectorImpl<char> & CB)60 static void writeData(uint32_t Bin, unsigned Size, SmallVectorImpl<char> &CB) {
61   if (Size == 4)
62     support::endian::write(CB, static_cast<uint16_t>(Bin >> 16),
63                            llvm::endianness::little);
64   support::endian::write(CB, static_cast<uint16_t>(Bin),
65                          llvm::endianness::little);
66 }
67 
expandJBTF(const MCInst & MI,SmallVectorImpl<char> & CB,SmallVectorImpl<MCFixup> & Fixups,const MCSubtargetInfo & STI) const68 void CSKYMCCodeEmitter::expandJBTF(const MCInst &MI, SmallVectorImpl<char> &CB,
69                                    SmallVectorImpl<MCFixup> &Fixups,
70                                    const MCSubtargetInfo &STI) const {
71 
72   MCInst TmpInst;
73 
74   uint32_t Binary;
75 
76   TmpInst =
77       MCInstBuilder(MI.getOpcode() == CSKY::JBT_E ? CSKY::BF16 : CSKY::BT16)
78           .addOperand(MI.getOperand(0))
79           .addImm(6);
80   Binary = getBinaryCodeForInstr(TmpInst, Fixups, STI);
81   writeData(Binary, 2, CB);
82 
83   if (!STI.hasFeature(CSKY::Has2E3))
84     TmpInst = MCInstBuilder(CSKY::BR32)
85                   .addOperand(MI.getOperand(1))
86                   .addOperand(MI.getOperand(2));
87   else
88     TmpInst = MCInstBuilder(CSKY::JMPI32).addOperand(MI.getOperand(2));
89   Binary = getBinaryCodeForInstr(TmpInst, Fixups, STI);
90   Fixups[Fixups.size() - 1].setOffset(2);
91   writeData(Binary, 4, CB);
92 }
93 
expandNEG(const MCInst & MI,SmallVectorImpl<char> & CB,SmallVectorImpl<MCFixup> & Fixups,const MCSubtargetInfo & STI) const94 void CSKYMCCodeEmitter::expandNEG(const MCInst &MI, SmallVectorImpl<char> &CB,
95                                   SmallVectorImpl<MCFixup> &Fixups,
96                                   const MCSubtargetInfo &STI) const {
97 
98   MCInst TmpInst;
99   uint32_t Binary;
100   unsigned Size = MI.getOpcode() == CSKY::NEG32 ? 4 : 2;
101 
102   TmpInst = MCInstBuilder(Size == 4 ? CSKY::NOT32 : CSKY::NOT16)
103                 .addOperand(MI.getOperand(0))
104                 .addOperand(MI.getOperand(1));
105   Binary = getBinaryCodeForInstr(TmpInst, Fixups, STI);
106   writeData(Binary, Size, CB);
107 
108   TmpInst = MCInstBuilder(Size == 4 ? CSKY::ADDI32 : CSKY::ADDI16)
109                 .addOperand(MI.getOperand(0))
110                 .addOperand(MI.getOperand(0))
111                 .addImm(1);
112   Binary = getBinaryCodeForInstr(TmpInst, Fixups, STI);
113   writeData(Binary, Size, CB);
114 }
115 
expandRSUBI(const MCInst & MI,SmallVectorImpl<char> & CB,SmallVectorImpl<MCFixup> & Fixups,const MCSubtargetInfo & STI) const116 void CSKYMCCodeEmitter::expandRSUBI(const MCInst &MI, SmallVectorImpl<char> &CB,
117                                     SmallVectorImpl<MCFixup> &Fixups,
118                                     const MCSubtargetInfo &STI) const {
119 
120   MCInst TmpInst;
121   uint32_t Binary;
122   unsigned Size = MI.getOpcode() == CSKY::RSUBI32 ? 4 : 2;
123 
124   TmpInst = MCInstBuilder(Size == 4 ? CSKY::NOT32 : CSKY::NOT16)
125                 .addOperand(MI.getOperand(0))
126                 .addOperand(MI.getOperand(1));
127   Binary = getBinaryCodeForInstr(TmpInst, Fixups, STI);
128   writeData(Binary, Size, CB);
129 
130   TmpInst = MCInstBuilder(Size == 4 ? CSKY::ADDI32 : CSKY::ADDI16)
131                 .addOperand(MI.getOperand(0))
132                 .addOperand(MI.getOperand(0))
133                 .addImm(MI.getOperand(2).getImm() + 1);
134   Binary = getBinaryCodeForInstr(TmpInst, Fixups, STI);
135   writeData(Binary, Size, CB);
136 }
137 
encodeInstruction(const MCInst & MI,SmallVectorImpl<char> & CB,SmallVectorImpl<MCFixup> & Fixups,const MCSubtargetInfo & STI) const138 void CSKYMCCodeEmitter::encodeInstruction(const MCInst &MI,
139                                           SmallVectorImpl<char> &CB,
140                                           SmallVectorImpl<MCFixup> &Fixups,
141                                           const MCSubtargetInfo &STI) const {
142   const MCInstrDesc &Desc = MII.get(MI.getOpcode());
143   unsigned Size = Desc.getSize();
144 
145   MCInst TmpInst;
146 
147   switch (MI.getOpcode()) {
148   default:
149     TmpInst = MI;
150     break;
151   case CSKY::JBT_E:
152   case CSKY::JBF_E:
153     expandJBTF(MI, CB, Fixups, STI);
154     MCNumEmitted += 2;
155     return;
156   case CSKY::NEG32:
157   case CSKY::NEG16:
158     expandNEG(MI, CB, Fixups, STI);
159     MCNumEmitted += 2;
160     return;
161   case CSKY::RSUBI32:
162   case CSKY::RSUBI16:
163     expandRSUBI(MI, CB, Fixups, STI);
164     MCNumEmitted += 2;
165     return;
166   case CSKY::JBSR32:
167     TmpInst = MCInstBuilder(CSKY::BSR32).addOperand(MI.getOperand(0));
168     break;
169   case CSKY::JBR16:
170     TmpInst = MCInstBuilder(CSKY::BR16).addOperand(MI.getOperand(0));
171     break;
172   case CSKY::JBR32:
173     TmpInst = MCInstBuilder(CSKY::BR32).addOperand(MI.getOperand(0));
174     break;
175   case CSKY::JBT16:
176     TmpInst = MCInstBuilder(CSKY::BT16)
177                   .addOperand(MI.getOperand(0))
178                   .addOperand(MI.getOperand(1));
179     break;
180   case CSKY::JBT32:
181     TmpInst = MCInstBuilder(CSKY::BT32)
182                   .addOperand(MI.getOperand(0))
183                   .addOperand(MI.getOperand(1));
184     break;
185   case CSKY::JBF16:
186     TmpInst = MCInstBuilder(CSKY::BF16)
187                   .addOperand(MI.getOperand(0))
188                   .addOperand(MI.getOperand(1));
189     break;
190   case CSKY::JBF32:
191     TmpInst = MCInstBuilder(CSKY::BF32)
192                   .addOperand(MI.getOperand(0))
193                   .addOperand(MI.getOperand(1));
194     break;
195   case CSKY::LRW32_Gen:
196     TmpInst = MCInstBuilder(CSKY::LRW32)
197                   .addOperand(MI.getOperand(0))
198                   .addOperand(MI.getOperand(2));
199     break;
200   case CSKY::LRW16_Gen:
201     TmpInst = MCInstBuilder(CSKY::LRW16)
202                   .addOperand(MI.getOperand(0))
203                   .addOperand(MI.getOperand(2));
204     break;
205   case CSKY::CMPLEI32:
206     TmpInst = MCInstBuilder(CSKY::CMPLTI32)
207                   .addOperand(MI.getOperand(0))
208                   .addOperand(MI.getOperand(1))
209                   .addImm(MI.getOperand(2).getImm() + 1);
210     break;
211   case CSKY::CMPLEI16:
212     TmpInst = MCInstBuilder(CSKY::CMPLTI16)
213                   .addOperand(MI.getOperand(0))
214                   .addOperand(MI.getOperand(1))
215                   .addImm(MI.getOperand(2).getImm() + 1);
216     break;
217   case CSKY::ROTRI32:
218     TmpInst = MCInstBuilder(CSKY::ROTLI32)
219                   .addOperand(MI.getOperand(0))
220                   .addOperand(MI.getOperand(1))
221                   .addImm(32 - MI.getOperand(2).getImm());
222     break;
223   case CSKY::BGENI:
224     auto V = 1 << MI.getOperand(1).getImm();
225     TmpInst =
226         MCInstBuilder(CSKY::MOVI32).addOperand(MI.getOperand(0)).addImm(V);
227     break;
228   }
229 
230   ++MCNumEmitted;
231   writeData(getBinaryCodeForInstr(TmpInst, Fixups, STI), Size, CB);
232 }
233 
234 unsigned
getMachineOpValue(const MCInst & MI,const MCOperand & MO,SmallVectorImpl<MCFixup> & Fixups,const MCSubtargetInfo & STI) const235 CSKYMCCodeEmitter::getMachineOpValue(const MCInst &MI, const MCOperand &MO,
236                                      SmallVectorImpl<MCFixup> &Fixups,
237                                      const MCSubtargetInfo &STI) const {
238   if (MO.isReg())
239     return Ctx.getRegisterInfo()->getEncodingValue(MO.getReg());
240 
241   if (MO.isImm())
242     return static_cast<unsigned>(MO.getImm());
243 
244   llvm_unreachable("Unhandled expression!");
245   return 0;
246 }
247 
248 unsigned
getRegSeqImmOpValue(const MCInst & MI,unsigned Idx,SmallVectorImpl<MCFixup> & Fixups,const MCSubtargetInfo & STI) const249 CSKYMCCodeEmitter::getRegSeqImmOpValue(const MCInst &MI, unsigned Idx,
250                                        SmallVectorImpl<MCFixup> &Fixups,
251                                        const MCSubtargetInfo &STI) const {
252   assert(MI.getOperand(Idx).isReg() && "Unexpected MO type.");
253   assert(MI.getOperand(Idx + 1).isImm() && "Unexpected MO type.");
254 
255   unsigned Ry = MI.getOperand(Idx).getReg();
256   unsigned Rz = MI.getOperand(Idx + 1).getImm();
257 
258   unsigned Imm = Ctx.getRegisterInfo()->getEncodingValue(Rz) -
259                  Ctx.getRegisterInfo()->getEncodingValue(Ry);
260 
261   return ((Ctx.getRegisterInfo()->getEncodingValue(Ry) << 5) | Imm);
262 }
263 
264 unsigned
getRegisterSeqOpValue(const MCInst & MI,unsigned Op,SmallVectorImpl<MCFixup> & Fixups,const MCSubtargetInfo & STI) const265 CSKYMCCodeEmitter::getRegisterSeqOpValue(const MCInst &MI, unsigned Op,
266                                          SmallVectorImpl<MCFixup> &Fixups,
267                                          const MCSubtargetInfo &STI) const {
268   unsigned Reg1 =
269       Ctx.getRegisterInfo()->getEncodingValue(MI.getOperand(Op).getReg());
270   unsigned Reg2 =
271       Ctx.getRegisterInfo()->getEncodingValue(MI.getOperand(Op + 1).getReg());
272 
273   unsigned Binary = ((Reg1 & 0x1f) << 5) | (Reg2 - Reg1);
274 
275   return Binary;
276 }
277 
getImmJMPIX(const MCInst & MI,unsigned Idx,SmallVectorImpl<MCFixup> & Fixups,const MCSubtargetInfo & STI) const278 unsigned CSKYMCCodeEmitter::getImmJMPIX(const MCInst &MI, unsigned Idx,
279                                         SmallVectorImpl<MCFixup> &Fixups,
280                                         const MCSubtargetInfo &STI) const {
281   if (MI.getOperand(Idx).getImm() == 16)
282     return 0;
283   else if (MI.getOperand(Idx).getImm() == 24)
284     return 1;
285   else if (MI.getOperand(Idx).getImm() == 32)
286     return 2;
287   else if (MI.getOperand(Idx).getImm() == 40)
288     return 3;
289   else
290     assert(0);
291 }
292 
getTargetFixup(const MCExpr * Expr) const293 MCFixupKind CSKYMCCodeEmitter::getTargetFixup(const MCExpr *Expr) const {
294   const CSKYMCExpr *CSKYExpr = cast<CSKYMCExpr>(Expr);
295 
296   switch (CSKYExpr->getKind()) {
297   default:
298     llvm_unreachable("Unhandled fixup kind!");
299   case CSKYMCExpr::VK_CSKY_ADDR:
300     return MCFixupKind(CSKY::fixup_csky_addr32);
301   case CSKYMCExpr::VK_CSKY_ADDR_HI16:
302     return MCFixupKind(CSKY::fixup_csky_addr_hi16);
303   case CSKYMCExpr::VK_CSKY_ADDR_LO16:
304     return MCFixupKind(CSKY::fixup_csky_addr_lo16);
305   case CSKYMCExpr::VK_CSKY_GOT:
306     return MCFixupKind(CSKY::fixup_csky_got32);
307   case CSKYMCExpr::VK_CSKY_GOTPC:
308     return MCFixupKind(CSKY::fixup_csky_gotpc);
309   case CSKYMCExpr::VK_CSKY_GOTOFF:
310     return MCFixupKind(CSKY::fixup_csky_gotoff);
311   case CSKYMCExpr::VK_CSKY_PLT:
312     return MCFixupKind(CSKY::fixup_csky_plt32);
313   case CSKYMCExpr::VK_CSKY_PLT_IMM18_BY4:
314     return MCFixupKind(CSKY::fixup_csky_plt_imm18_scale4);
315   case CSKYMCExpr::VK_CSKY_GOT_IMM18_BY4:
316     return MCFixupKind(CSKY::fixup_csky_got_imm18_scale4);
317   }
318 }
319 
createCSKYMCCodeEmitter(const MCInstrInfo & MCII,MCContext & Ctx)320 MCCodeEmitter *llvm::createCSKYMCCodeEmitter(const MCInstrInfo &MCII,
321                                              MCContext &Ctx) {
322   return new CSKYMCCodeEmitter(Ctx, MCII);
323 }
324 
325 #include "CSKYGenMCCodeEmitter.inc"
326