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