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
24using namespace llvm;
25
26#define DEBUG_TYPE "csky-mccode-emitter"
27
28STATISTIC(MCNumEmitted, "Number of MC instructions emitted");
29
30unsigned 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
38unsigned
39CSKYMCCodeEmitter::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
49unsigned
50CSKYMCCodeEmitter::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
60static 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
68void 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
94void 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
116void 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
138void 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
234unsigned
235CSKYMCCodeEmitter::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
248unsigned
249CSKYMCCodeEmitter::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
264unsigned
265CSKYMCCodeEmitter::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
278unsigned 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
293MCFixupKind 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
320MCCodeEmitter *llvm::createCSKYMCCodeEmitter(const MCInstrInfo &MCII,
321                                             MCContext &Ctx) {
322  return new CSKYMCCodeEmitter(Ctx, MCII);
323}
324
325#include "CSKYGenMCCodeEmitter.inc"
326