xref: /freebsd-src/contrib/llvm-project/llvm/lib/Target/CSKY/MCTargetDesc/CSKYMCCodeEmitter.cpp (revision 349cc55c9796c4596a5b9904cd3281af295f878f)
1e8d8bef9SDimitry Andric //===-- CSKYMCCodeEmitter.cpp - CSKY Code Emitter interface ---------------===//
2e8d8bef9SDimitry Andric //
3e8d8bef9SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4e8d8bef9SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5e8d8bef9SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6e8d8bef9SDimitry Andric //
7e8d8bef9SDimitry Andric //===----------------------------------------------------------------------===//
8e8d8bef9SDimitry Andric //
9e8d8bef9SDimitry Andric // This file implements the CSKYMCCodeEmitter class.
10e8d8bef9SDimitry Andric //
11e8d8bef9SDimitry Andric //===----------------------------------------------------------------------===//
12e8d8bef9SDimitry Andric 
13e8d8bef9SDimitry Andric #include "CSKYMCCodeEmitter.h"
14*349cc55cSDimitry Andric #include "CSKYMCExpr.h"
15e8d8bef9SDimitry Andric #include "MCTargetDesc/CSKYMCTargetDesc.h"
16e8d8bef9SDimitry Andric #include "llvm/ADT/Statistic.h"
17e8d8bef9SDimitry Andric #include "llvm/MC/MCInstBuilder.h"
18e8d8bef9SDimitry Andric #include "llvm/MC/MCInstrInfo.h"
19e8d8bef9SDimitry Andric #include "llvm/Support/EndianStream.h"
20e8d8bef9SDimitry Andric 
21e8d8bef9SDimitry Andric using namespace llvm;
22e8d8bef9SDimitry Andric 
23e8d8bef9SDimitry Andric #define DEBUG_TYPE "csky-mccode-emitter"
24e8d8bef9SDimitry Andric 
25e8d8bef9SDimitry Andric STATISTIC(MCNumEmitted, "Number of MC instructions emitted");
26e8d8bef9SDimitry Andric 
27e8d8bef9SDimitry Andric unsigned CSKYMCCodeEmitter::getOImmOpValue(const MCInst &MI, unsigned Idx,
28e8d8bef9SDimitry Andric                                            SmallVectorImpl<MCFixup> &Fixups,
29e8d8bef9SDimitry Andric                                            const MCSubtargetInfo &STI) const {
30e8d8bef9SDimitry Andric   const MCOperand &MO = MI.getOperand(Idx);
31e8d8bef9SDimitry Andric   assert(MO.isImm() && "Unexpected MO type.");
32e8d8bef9SDimitry Andric   return MO.getImm() - 1;
33e8d8bef9SDimitry Andric }
34e8d8bef9SDimitry Andric 
35*349cc55cSDimitry Andric unsigned
36*349cc55cSDimitry Andric CSKYMCCodeEmitter::getImmOpValueIDLY(const MCInst &MI, unsigned Idx,
37*349cc55cSDimitry Andric                                      SmallVectorImpl<MCFixup> &Fixups,
38*349cc55cSDimitry Andric                                      const MCSubtargetInfo &STI) const {
39*349cc55cSDimitry Andric   const MCOperand &MO = MI.getOperand(Idx);
40*349cc55cSDimitry Andric   assert(MO.isImm() && "Unexpected MO type.");
41*349cc55cSDimitry Andric 
42*349cc55cSDimitry Andric   auto V = (MO.getImm() <= 3) ? 4 : MO.getImm();
43*349cc55cSDimitry Andric   return V - 1;
44*349cc55cSDimitry Andric }
45*349cc55cSDimitry Andric 
46*349cc55cSDimitry Andric unsigned
47*349cc55cSDimitry Andric CSKYMCCodeEmitter::getImmOpValueMSBSize(const MCInst &MI, unsigned Idx,
48*349cc55cSDimitry Andric                                         SmallVectorImpl<MCFixup> &Fixups,
49*349cc55cSDimitry Andric                                         const MCSubtargetInfo &STI) const {
50*349cc55cSDimitry Andric   const MCOperand &MSB = MI.getOperand(Idx);
51*349cc55cSDimitry Andric   const MCOperand &LSB = MI.getOperand(Idx + 1);
52*349cc55cSDimitry Andric   assert(MSB.isImm() && LSB.isImm() && "Unexpected MO type.");
53*349cc55cSDimitry Andric 
54*349cc55cSDimitry Andric   return MSB.getImm() - LSB.getImm();
55*349cc55cSDimitry Andric }
56*349cc55cSDimitry Andric 
57*349cc55cSDimitry Andric static void writeData(uint32_t Bin, unsigned Size, raw_ostream &OS) {
58*349cc55cSDimitry Andric   uint16_t LO16 = static_cast<uint16_t>(Bin);
59*349cc55cSDimitry Andric   uint16_t HI16 = static_cast<uint16_t>(Bin >> 16);
60*349cc55cSDimitry Andric 
61*349cc55cSDimitry Andric   if (Size == 4)
62*349cc55cSDimitry Andric     support::endian::write<uint16_t>(OS, HI16, support::little);
63*349cc55cSDimitry Andric 
64*349cc55cSDimitry Andric   support::endian::write<uint16_t>(OS, LO16, support::little);
65*349cc55cSDimitry Andric }
66*349cc55cSDimitry Andric 
67e8d8bef9SDimitry Andric void CSKYMCCodeEmitter::encodeInstruction(const MCInst &MI, raw_ostream &OS,
68e8d8bef9SDimitry Andric                                           SmallVectorImpl<MCFixup> &Fixups,
69e8d8bef9SDimitry Andric                                           const MCSubtargetInfo &STI) const {
70e8d8bef9SDimitry Andric   const MCInstrDesc &Desc = MII.get(MI.getOpcode());
71e8d8bef9SDimitry Andric   unsigned Size = Desc.getSize();
72*349cc55cSDimitry Andric 
73*349cc55cSDimitry Andric   ++MCNumEmitted;
74*349cc55cSDimitry Andric 
75e8d8bef9SDimitry Andric   uint32_t Bin = getBinaryCodeForInstr(MI, Fixups, STI);
76e8d8bef9SDimitry Andric 
77e8d8bef9SDimitry Andric   uint16_t LO16 = static_cast<uint16_t>(Bin);
78e8d8bef9SDimitry Andric   uint16_t HI16 = static_cast<uint16_t>(Bin >> 16);
79e8d8bef9SDimitry Andric 
80e8d8bef9SDimitry Andric   if (Size == 4)
81e8d8bef9SDimitry Andric     support::endian::write<uint16_t>(OS, HI16, support::little);
82e8d8bef9SDimitry Andric 
83e8d8bef9SDimitry Andric   support::endian::write<uint16_t>(OS, LO16, support::little);
84e8d8bef9SDimitry Andric }
85e8d8bef9SDimitry Andric 
86e8d8bef9SDimitry Andric unsigned
87e8d8bef9SDimitry Andric CSKYMCCodeEmitter::getMachineOpValue(const MCInst &MI, const MCOperand &MO,
88e8d8bef9SDimitry Andric                                      SmallVectorImpl<MCFixup> &Fixups,
89e8d8bef9SDimitry Andric                                      const MCSubtargetInfo &STI) const {
90e8d8bef9SDimitry Andric   if (MO.isReg())
91e8d8bef9SDimitry Andric     return Ctx.getRegisterInfo()->getEncodingValue(MO.getReg());
92e8d8bef9SDimitry Andric 
93e8d8bef9SDimitry Andric   if (MO.isImm())
94e8d8bef9SDimitry Andric     return static_cast<unsigned>(MO.getImm());
95e8d8bef9SDimitry Andric 
96e8d8bef9SDimitry Andric   llvm_unreachable("Unhandled expression!");
97e8d8bef9SDimitry Andric   return 0;
98e8d8bef9SDimitry Andric }
99e8d8bef9SDimitry Andric 
100*349cc55cSDimitry Andric unsigned
101*349cc55cSDimitry Andric CSKYMCCodeEmitter::getRegSeqImmOpValue(const MCInst &MI, unsigned Idx,
102*349cc55cSDimitry Andric                                        SmallVectorImpl<MCFixup> &Fixups,
103*349cc55cSDimitry Andric                                        const MCSubtargetInfo &STI) const {
104*349cc55cSDimitry Andric   assert(MI.getOperand(Idx).isReg() && "Unexpected MO type.");
105*349cc55cSDimitry Andric   assert(MI.getOperand(Idx + 1).isImm() && "Unexpected MO type.");
106*349cc55cSDimitry Andric 
107*349cc55cSDimitry Andric   unsigned Ry = MI.getOperand(Idx).getReg();
108*349cc55cSDimitry Andric   unsigned Rz = MI.getOperand(Idx + 1).getImm();
109*349cc55cSDimitry Andric 
110*349cc55cSDimitry Andric   unsigned Imm = Ctx.getRegisterInfo()->getEncodingValue(Rz) -
111*349cc55cSDimitry Andric                  Ctx.getRegisterInfo()->getEncodingValue(Ry);
112*349cc55cSDimitry Andric 
113*349cc55cSDimitry Andric   return ((Ctx.getRegisterInfo()->getEncodingValue(Ry) << 5) | Imm);
114*349cc55cSDimitry Andric }
115*349cc55cSDimitry Andric 
116*349cc55cSDimitry Andric unsigned
117*349cc55cSDimitry Andric CSKYMCCodeEmitter::getRegisterSeqOpValue(const MCInst &MI, unsigned Op,
118*349cc55cSDimitry Andric                                          SmallVectorImpl<MCFixup> &Fixups,
119*349cc55cSDimitry Andric                                          const MCSubtargetInfo &STI) const {
120*349cc55cSDimitry Andric   unsigned Reg1 =
121*349cc55cSDimitry Andric       Ctx.getRegisterInfo()->getEncodingValue(MI.getOperand(Op).getReg());
122*349cc55cSDimitry Andric   unsigned Reg2 =
123*349cc55cSDimitry Andric       Ctx.getRegisterInfo()->getEncodingValue(MI.getOperand(Op + 1).getReg());
124*349cc55cSDimitry Andric 
125*349cc55cSDimitry Andric   unsigned Binary = ((Reg1 & 0x1f) << 5) | (Reg2 - Reg1);
126*349cc55cSDimitry Andric 
127*349cc55cSDimitry Andric   return Binary;
128*349cc55cSDimitry Andric }
129*349cc55cSDimitry Andric 
130*349cc55cSDimitry Andric unsigned CSKYMCCodeEmitter::getImmJMPIX(const MCInst &MI, unsigned Idx,
131*349cc55cSDimitry Andric                                         SmallVectorImpl<MCFixup> &Fixups,
132*349cc55cSDimitry Andric                                         const MCSubtargetInfo &STI) const {
133*349cc55cSDimitry Andric   if (MI.getOperand(Idx).getImm() == 16)
134*349cc55cSDimitry Andric     return 0;
135*349cc55cSDimitry Andric   else if (MI.getOperand(Idx).getImm() == 24)
136*349cc55cSDimitry Andric     return 1;
137*349cc55cSDimitry Andric   else if (MI.getOperand(Idx).getImm() == 32)
138*349cc55cSDimitry Andric     return 2;
139*349cc55cSDimitry Andric   else if (MI.getOperand(Idx).getImm() == 40)
140*349cc55cSDimitry Andric     return 3;
141*349cc55cSDimitry Andric   else
142*349cc55cSDimitry Andric     assert(0);
143*349cc55cSDimitry Andric }
144*349cc55cSDimitry Andric 
145fe6060f1SDimitry Andric MCFixupKind CSKYMCCodeEmitter::getTargetFixup(const MCExpr *Expr) const {
146fe6060f1SDimitry Andric   const CSKYMCExpr *CSKYExpr = cast<CSKYMCExpr>(Expr);
147fe6060f1SDimitry Andric 
148fe6060f1SDimitry Andric   switch (CSKYExpr->getKind()) {
149fe6060f1SDimitry Andric   default:
150fe6060f1SDimitry Andric     llvm_unreachable("Unhandled fixup kind!");
151fe6060f1SDimitry Andric   case CSKYMCExpr::VK_CSKY_ADDR:
152fe6060f1SDimitry Andric     return MCFixupKind(CSKY::fixup_csky_addr32);
153*349cc55cSDimitry Andric   case CSKYMCExpr::VK_CSKY_ADDR_HI16:
154*349cc55cSDimitry Andric     return MCFixupKind(CSKY::fixup_csky_addr_hi16);
155*349cc55cSDimitry Andric   case CSKYMCExpr::VK_CSKY_ADDR_LO16:
156*349cc55cSDimitry Andric     return MCFixupKind(CSKY::fixup_csky_addr_lo16);
157*349cc55cSDimitry Andric   case CSKYMCExpr::VK_CSKY_GOT:
158*349cc55cSDimitry Andric     return MCFixupKind(CSKY::fixup_csky_got32);
159*349cc55cSDimitry Andric   case CSKYMCExpr::VK_CSKY_GOTPC:
160*349cc55cSDimitry Andric     return MCFixupKind(CSKY::fixup_csky_gotpc);
161*349cc55cSDimitry Andric   case CSKYMCExpr::VK_CSKY_GOTOFF:
162*349cc55cSDimitry Andric     return MCFixupKind(CSKY::fixup_csky_gotoff);
163*349cc55cSDimitry Andric   case CSKYMCExpr::VK_CSKY_PLT:
164*349cc55cSDimitry Andric     return MCFixupKind(CSKY::fixup_csky_plt32);
165*349cc55cSDimitry Andric   case CSKYMCExpr::VK_CSKY_PLT_IMM18_BY4:
166*349cc55cSDimitry Andric     return MCFixupKind(CSKY::fixup_csky_plt_imm18_scale4);
167*349cc55cSDimitry Andric   case CSKYMCExpr::VK_CSKY_GOT_IMM18_BY4:
168*349cc55cSDimitry Andric     return MCFixupKind(CSKY::fixup_csky_got_imm18_scale4);
169fe6060f1SDimitry Andric   }
170fe6060f1SDimitry Andric }
171fe6060f1SDimitry Andric 
172e8d8bef9SDimitry Andric MCCodeEmitter *llvm::createCSKYMCCodeEmitter(const MCInstrInfo &MCII,
173e8d8bef9SDimitry Andric                                              const MCRegisterInfo &MRI,
174e8d8bef9SDimitry Andric                                              MCContext &Ctx) {
175e8d8bef9SDimitry Andric   return new CSKYMCCodeEmitter(Ctx, MCII);
176e8d8bef9SDimitry Andric }
177e8d8bef9SDimitry Andric 
178e8d8bef9SDimitry Andric #include "CSKYGenMCCodeEmitter.inc"
179