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