LLVM 17.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 "CSKYMCCodeEmitter.h"
14#include "CSKYMCExpr.h"
16#include "llvm/ADT/Statistic.h"
18#include "llvm/MC/MCInstrInfo.h"
23
24using namespace llvm;
25
26#define DEBUG_TYPE "csky-mccode-emitter"
27
28STATISTIC(MCNumEmitted, "Number of MC instructions emitted");
29
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
38unsigned
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
49unsigned
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
60static 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
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.hasFeature(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
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
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
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
244unsigned
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
258unsigned
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) -
270
271 return ((Ctx.getRegisterInfo()->getEncodingValue(Ry) << 5) | Imm);
272}
273
274unsigned
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
288unsigned CSKYMCCodeEmitter::getImmJMPIX(const MCInst &MI, unsigned Idx,
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
304 const CSKYMCExpr *CSKYExpr = cast<CSKYMCExpr>(Expr);
305
306 switch (CSKYExpr->getKind()) {
307 default:
308 llvm_unreachable("Unhandled fixup kind!");
327 }
328}
329
331 MCContext &Ctx) {
332 return new CSKYMCCodeEmitter(Ctx, MCII);
333}
334
335#include "CSKYGenMCCodeEmitter.inc"
static void writeData(uint32_t Bin, unsigned Size, raw_ostream &OS)
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
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
raw_pwrite_stream & OS
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
unsigned getRegisterSeqOpValue(const MCInst &MI, unsigned Op, SmallVectorImpl< MCFixup > &Fixups, const MCSubtargetInfo &STI) const
unsigned getOImmOpValue(const MCInst &MI, unsigned Idx, SmallVectorImpl< MCFixup > &Fixups, const MCSubtargetInfo &STI) const
unsigned getMachineOpValue(const MCInst &MI, const MCOperand &MO, SmallVectorImpl< MCFixup > &Fixups, const MCSubtargetInfo &STI) const
uint64_t getBinaryCodeForInstr(const MCInst &MI, SmallVectorImpl< MCFixup > &Fixups, const MCSubtargetInfo &STI) const
void expandJBTF(const MCInst &MI, raw_ostream &OS, SmallVectorImpl< MCFixup > &Fixups, const MCSubtargetInfo &STI) const
unsigned getImmOpValueMSBSize(const MCInst &MI, unsigned Idx, SmallVectorImpl< MCFixup > &Fixups, const MCSubtargetInfo &STI) const
void expandRSUBI(const MCInst &MI, raw_ostream &OS, SmallVectorImpl< MCFixup > &Fixups, const MCSubtargetInfo &STI) const
MCFixupKind getTargetFixup(const MCExpr *Expr) const
unsigned getRegSeqImmOpValue(const MCInst &MI, unsigned Idx, SmallVectorImpl< MCFixup > &Fixups, const MCSubtargetInfo &STI) const
unsigned getImmOpValueIDLY(const MCInst &MI, unsigned Idx, SmallVectorImpl< MCFixup > &Fixups, const MCSubtargetInfo &STI) const
unsigned getImmJMPIX(const MCInst &MI, unsigned Idx, SmallVectorImpl< MCFixup > &Fixups, const MCSubtargetInfo &STI) const
void expandNEG(const MCInst &MI, raw_ostream &OS, SmallVectorImpl< MCFixup > &Fixups, const MCSubtargetInfo &STI) const
void encodeInstruction(const MCInst &Inst, raw_ostream &OS, SmallVectorImpl< MCFixup > &Fixups, const MCSubtargetInfo &STI) const override
EncodeInstruction - Encode the given Inst to bytes on the output stream OS.
VariantKind getKind() const
Definition: CSKYMCExpr.h:51
MCCodeEmitter - Generic instruction encoding interface.
Definition: MCCodeEmitter.h:21
Context object for machine code objects.
Definition: MCContext.h:76
const MCRegisterInfo * getRegisterInfo() const
Definition: MCContext.h:448
Base class for the full range of assembler expressions which are needed for parsing.
Definition: MCExpr.h:35
MCInstBuilder & addOperand(const MCOperand &Op)
Add an operand.
Definition: MCInstBuilder.h:67
MCInstBuilder & addImm(int64_t Val)
Add a new integer immediate operand.
Definition: MCInstBuilder.h:37
Instances of this class represent a single low-level machine instruction.
Definition: MCInst.h:184
Describe properties that are true of each instruction in the target description file.
Definition: MCInstrDesc.h:198
unsigned getSize() const
Return the number of bytes in the encoding of this instruction, or zero if the encoding size cannot b...
Definition: MCInstrDesc.h:605
Interface to description of machine instruction set.
Definition: MCInstrInfo.h:26
const MCInstrDesc & get(unsigned Opcode) const
Return the machine instruction descriptor that corresponds to the specified instruction opcode.
Definition: MCInstrInfo.h:63
Instances of this class represent operands of the MCInst class.
Definition: MCInst.h:36
int64_t getImm() const
Definition: MCInst.h:80
bool isImm() const
Definition: MCInst.h:62
unsigned getReg() const
Returns the register number.
Definition: MCInst.h:69
bool isReg() const
Definition: MCInst.h:61
uint16_t getEncodingValue(MCRegister RegNo) const
Returns the encoding for RegNo.
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:577
This class implements an extremely fast bulk output stream that can only output to a stream.
Definition: raw_ostream.h:52
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
@ fixup_csky_plt_imm18_scale4
@ fixup_csky_got_imm18_scale4
@ fixup_csky_addr_hi16
@ fixup_csky_addr_lo16
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
MCFixupKind
Extensible enumeration to represent the type of a fixup.
Definition: MCFixup.h:21
MCCodeEmitter * createCSKYMCCodeEmitter(const MCInstrInfo &MCII, MCContext &Ctx)