LLVM 22.0.0git
CSKYMCCodeEmitter.cpp
Go to the documentation of this file.
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"
17#include "llvm/ADT/Statistic.h"
19#include "llvm/MC/MCContext.h"
21#include "llvm/MC/MCInstrInfo.h"
26
27using namespace llvm;
28
29#define DEBUG_TYPE "csky-mccode-emitter"
30
31STATISTIC(MCNumEmitted, "Number of MC instructions emitted");
32
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
50namespace {
51class CSKYMCCodeEmitter : public MCCodeEmitter {
52 MCContext &Ctx;
53 const MCInstrInfo &MII;
54
55public:
56 CSKYMCCodeEmitter(MCContext &Ctx, const MCInstrInfo &MII)
57 : Ctx(Ctx), MII(MII) {}
58
59 ~CSKYMCCodeEmitter() {}
60
63 const MCSubtargetInfo &STI) const override;
64
65 // Generated by tablegen.
66 uint64_t getBinaryCodeForInstr(const MCInst &MI,
68 const MCSubtargetInfo &STI) const;
69
70 // Default encoding method used by tablegen.
71 unsigned getMachineOpValue(const MCInst &MI, const MCOperand &MO,
73 const MCSubtargetInfo &STI) const;
74
75 template <int shift = 0>
76 unsigned getImmOpValue(const MCInst &MI, unsigned Idx,
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,
92 const MCSubtargetInfo &STI) const;
93
94 unsigned getRegisterSeqOpValue(const MCInst &MI, unsigned Op,
96 const MCSubtargetInfo &STI) const;
97
98 unsigned getOImmOpValue(const MCInst &MI, unsigned Idx,
100 const MCSubtargetInfo &STI) const;
101
102 unsigned getImmOpValueIDLY(const MCInst &MI, unsigned Idx,
104 const MCSubtargetInfo &STI) const;
105
106 unsigned getImmJMPIX(const MCInst &MI, unsigned Idx,
108 const MCSubtargetInfo &STI) const;
109
110 unsigned getImmOpValueMSBSize(const MCInst &MI, unsigned Idx,
112 const MCSubtargetInfo &STI) const;
113
114 unsigned getImmShiftOpValue(const MCInst &MI, unsigned Idx,
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,
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
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,
146 const MCSubtargetInfo &STI) const {
147 const MCOperand &MO = MI.getOperand(Idx);
148 assert(MO.isExpr() && "Unexpected MO type.");
149
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,
161 const MCSubtargetInfo &STI) const {
162 const MCOperand &MO = MI.getOperand(Idx);
163 assert(MO.isExpr() && "Unexpected MO type.");
164
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,
175 const MCSubtargetInfo &STI) const {
176 const MCOperand &MO = MI.getOperand(Idx);
177 assert(MO.isExpr() && "Unexpected MO type.");
178
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,
189 const MCSubtargetInfo &STI) const {
190 const MCOperand &MO = MI.getOperand(Idx);
191 assert(MO.isExpr() && "Unexpected MO type.");
192
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,
203 const MCSubtargetInfo &STI) const;
204 void expandNEG(const MCInst &MI, SmallVectorImpl<char> &CB,
206 const MCSubtargetInfo &STI) const;
207 void expandRSUBI(const MCInst &MI, SmallVectorImpl<char> &CB,
209 const MCSubtargetInfo &STI) const;
210};
211} // namespace
212
213unsigned CSKYMCCodeEmitter::getOImmOpValue(const MCInst &MI, unsigned Idx,
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
221unsigned
222CSKYMCCodeEmitter::getImmOpValueIDLY(const MCInst &MI, unsigned Idx,
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
232unsigned
233CSKYMCCodeEmitter::getImmOpValueMSBSize(const MCInst &MI, unsigned Idx,
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
243static 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),
247 support::endian::write(CB, static_cast<uint16_t>(Bin),
249}
250
251void CSKYMCCodeEmitter::expandJBTF(const MCInst &MI, SmallVectorImpl<char> &CB,
253 const MCSubtargetInfo &STI) const {
254
255 MCInst TmpInst;
256
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
277void CSKYMCCodeEmitter::expandNEG(const MCInst &MI, SmallVectorImpl<char> &CB,
279 const MCSubtargetInfo &STI) const {
280
281 MCInst TmpInst;
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
299void CSKYMCCodeEmitter::expandRSUBI(const MCInst &MI, SmallVectorImpl<char> &CB,
301 const MCSubtargetInfo &STI) const {
302
303 MCInst TmpInst;
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
321void CSKYMCCodeEmitter::encodeInstruction(const MCInst &MI,
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
417unsigned
418CSKYMCCodeEmitter::getMachineOpValue(const MCInst &MI, const MCOperand &MO,
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
431unsigned
432CSKYMCCodeEmitter::getRegSeqImmOpValue(const MCInst &MI, unsigned Idx,
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) -
443
444 return ((Ctx.getRegisterInfo()->getEncodingValue(Ry) << 5) | Imm);
445}
446
447unsigned
448CSKYMCCodeEmitter::getRegisterSeqOpValue(const MCInst &MI, unsigned Op,
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
461unsigned CSKYMCCodeEmitter::getImmJMPIX(const MCInst &MI, unsigned Idx,
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
478MCFixupKind 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:
489 case CSKY::S_GOT:
491 case CSKY::S_GOTPC:
493 case CSKY::S_GOTOFF:
495 case CSKY::S_PLT:
501 }
502}
503
505 MCContext &Ctx) {
506 return new CSKYMCCodeEmitter(Ctx, MCII);
507}
508
509#include "CSKYGenMCCodeEmitter.inc"
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static void writeData(uint32_t Bin, unsigned Size, SmallVectorImpl< char > &CB)
static void addFixup(SmallVectorImpl< MCFixup > &Fixups, uint32_t Offset, const MCExpr *Value, uint16_t Kind)
Returns the sub type a function will return at a given Idx Should correspond to the result type of an ExtractValue instruction executed with just that one unsigned Idx
uint64_t Size
IRTranslator LLVM IR MI
This file defines the 'Statistic' class, which is designed to be an easy way to expose various metric...
#define STATISTIC(VARNAME, DESC)
Definition: Statistic.h:167
This class represents an Operation in the Expression.
MCCodeEmitter - Generic instruction encoding interface.
Definition: MCCodeEmitter.h:23
virtual void encodeInstruction(const MCInst &Inst, SmallVectorImpl< char > &CB, SmallVectorImpl< MCFixup > &Fixups, const MCSubtargetInfo &STI) const =0
Encode the given Inst to bytes and append to CB.
Context object for machine code objects.
Definition: MCContext.h:83
const MCRegisterInfo * getRegisterInfo() const
Definition: MCContext.h:414
Base class for the full range of assembler expressions which are needed for parsing.
Definition: MCExpr.h:34
@ Specifier
Expression with a relocation specifier.
Definition: MCExpr.h:45
ExprKind getKind() const
Definition: MCExpr.h:85
static MCFixup create(uint32_t Offset, const MCExpr *Value, MCFixupKind Kind, bool PCRel=false)
Consider bit fields if we need more flags.
Definition: MCFixup.h:86
MCInstBuilder & addOperand(const MCOperand &Op)
Add an operand.
Definition: MCInstBuilder.h:73
MCInstBuilder & addImm(int64_t Val)
Add a new integer immediate operand.
Definition: MCInstBuilder.h:43
Instances of this class represent a single low-level machine instruction.
Definition: MCInst.h:188
Describe properties that are true of each instruction in the target description file.
Definition: MCInstrDesc.h:199
Interface to description of machine instruction set.
Definition: MCInstrInfo.h:27
const MCInstrDesc & get(unsigned Opcode) const
Return the machine instruction descriptor that corresponds to the specified instruction opcode.
Definition: MCInstrInfo.h:64
Instances of this class represent operands of the MCInst class.
Definition: MCInst.h:40
int64_t getImm() const
Definition: MCInst.h:84
bool isImm() const
Definition: MCInst.h:66
bool isReg() const
Definition: MCInst.h:65
MCRegister getReg() const
Returns the register number.
Definition: MCInst.h:73
const MCExpr * getExpr() const
Definition: MCInst.h:118
bool isExpr() const
Definition: MCInst.h:69
uint16_t getEncodingValue(MCRegister Reg) const
Returns the encoding for Reg.
Generic base class for all target subtargets.
bool hasFeature(unsigned Feature) const
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
Definition: SmallVector.h:574
LLVM Value Representation.
Definition: Value.h:75
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
@ fixup_csky_pcrel_imm18_scale2
@ fixup_csky_plt_imm18_scale4
@ fixup_csky_pcrel_imm26_scale2
@ fixup_csky_got_imm18_scale4
@ fixup_csky_addr_hi16
@ fixup_csky_addr_lo16
void write(void *memory, value_type value, endianness endian)
Write a value to memory with a particular endianness.
Definition: Endian.h:92
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
@ Offset
Definition: DWP.cpp:477
uint16_t MCFixupKind
Extensible enumeration to represent the type of a fixup.
Definition: MCFixup.h:22
static void addFixup(SmallVectorImpl< MCFixup > &Fixups, uint32_t Offset, const MCExpr *Value, uint16_t Kind)
MCCodeEmitter * createCSKYMCCodeEmitter(const MCInstrInfo &MCII, MCContext &Ctx)
Description of the encoding of one expression Op.