xref: /freebsd-src/contrib/llvm-project/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchMCCodeEmitter.cpp (revision 81ad626541db97eb356e2c1d4a20eb2a26a766ab)
1*81ad6265SDimitry Andric //=- LoongArchMCCodeEmitter.cpp - Convert LoongArch code to machine code --===//
2*81ad6265SDimitry Andric //
3*81ad6265SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4*81ad6265SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5*81ad6265SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6*81ad6265SDimitry Andric //
7*81ad6265SDimitry Andric //===----------------------------------------------------------------------===//
8*81ad6265SDimitry Andric //
9*81ad6265SDimitry Andric // This file implements the LoongArchMCCodeEmitter class.
10*81ad6265SDimitry Andric //
11*81ad6265SDimitry Andric //===----------------------------------------------------------------------===//
12*81ad6265SDimitry Andric 
13*81ad6265SDimitry Andric #include "MCTargetDesc/LoongArchBaseInfo.h"
14*81ad6265SDimitry Andric #include "MCTargetDesc/LoongArchMCTargetDesc.h"
15*81ad6265SDimitry Andric #include "llvm/MC/MCCodeEmitter.h"
16*81ad6265SDimitry Andric #include "llvm/MC/MCContext.h"
17*81ad6265SDimitry Andric #include "llvm/MC/MCInstBuilder.h"
18*81ad6265SDimitry Andric #include "llvm/MC/MCInstrInfo.h"
19*81ad6265SDimitry Andric #include "llvm/MC/MCRegisterInfo.h"
20*81ad6265SDimitry Andric #include "llvm/Support/EndianStream.h"
21*81ad6265SDimitry Andric 
22*81ad6265SDimitry Andric using namespace llvm;
23*81ad6265SDimitry Andric 
24*81ad6265SDimitry Andric #define DEBUG_TYPE "mccodeemitter"
25*81ad6265SDimitry Andric 
26*81ad6265SDimitry Andric namespace {
27*81ad6265SDimitry Andric class LoongArchMCCodeEmitter : public MCCodeEmitter {
28*81ad6265SDimitry Andric   LoongArchMCCodeEmitter(const LoongArchMCCodeEmitter &) = delete;
29*81ad6265SDimitry Andric   void operator=(const LoongArchMCCodeEmitter &) = delete;
30*81ad6265SDimitry Andric   MCContext &Ctx;
31*81ad6265SDimitry Andric   MCInstrInfo const &MCII;
32*81ad6265SDimitry Andric 
33*81ad6265SDimitry Andric public:
34*81ad6265SDimitry Andric   LoongArchMCCodeEmitter(MCContext &ctx, MCInstrInfo const &MCII)
35*81ad6265SDimitry Andric       : Ctx(ctx), MCII(MCII) {}
36*81ad6265SDimitry Andric 
37*81ad6265SDimitry Andric   ~LoongArchMCCodeEmitter() override {}
38*81ad6265SDimitry Andric 
39*81ad6265SDimitry Andric   void encodeInstruction(const MCInst &MI, raw_ostream &OS,
40*81ad6265SDimitry Andric                          SmallVectorImpl<MCFixup> &Fixups,
41*81ad6265SDimitry Andric                          const MCSubtargetInfo &STI) const override;
42*81ad6265SDimitry Andric 
43*81ad6265SDimitry Andric   /// TableGen'erated function for getting the binary encoding for an
44*81ad6265SDimitry Andric   /// instruction.
45*81ad6265SDimitry Andric   uint64_t getBinaryCodeForInstr(const MCInst &MI,
46*81ad6265SDimitry Andric                                  SmallVectorImpl<MCFixup> &Fixups,
47*81ad6265SDimitry Andric                                  const MCSubtargetInfo &STI) const;
48*81ad6265SDimitry Andric 
49*81ad6265SDimitry Andric   /// Return binary encoding of operand. If the machine operand requires
50*81ad6265SDimitry Andric   /// relocation, record the relocation and return zero.
51*81ad6265SDimitry Andric   unsigned getMachineOpValue(const MCInst &MI, const MCOperand &MO,
52*81ad6265SDimitry Andric                              SmallVectorImpl<MCFixup> &Fixups,
53*81ad6265SDimitry Andric                              const MCSubtargetInfo &STI) const;
54*81ad6265SDimitry Andric 
55*81ad6265SDimitry Andric   /// Return binary encoding of an immediate operand specified by OpNo.
56*81ad6265SDimitry Andric   /// The value returned is the value of the immediate minus 1.
57*81ad6265SDimitry Andric   /// Note that this function is dedicated to specific immediate types,
58*81ad6265SDimitry Andric   /// e.g. uimm2_plus1.
59*81ad6265SDimitry Andric   unsigned getImmOpValueSub1(const MCInst &MI, unsigned OpNo,
60*81ad6265SDimitry Andric                              SmallVectorImpl<MCFixup> &Fixups,
61*81ad6265SDimitry Andric                              const MCSubtargetInfo &STI) const;
62*81ad6265SDimitry Andric 
63*81ad6265SDimitry Andric   /// Return binary encoding of an immediate operand specified by OpNo.
64*81ad6265SDimitry Andric   /// The value returned is the value of the immediate shifted right
65*81ad6265SDimitry Andric   //  arithmetically by 2.
66*81ad6265SDimitry Andric   /// Note that this function is dedicated to specific immediate types,
67*81ad6265SDimitry Andric   /// e.g. simm14_lsl2, simm16_lsl2, simm21_lsl2 and simm26_lsl2.
68*81ad6265SDimitry Andric   unsigned getImmOpValueAsr2(const MCInst &MI, unsigned OpNo,
69*81ad6265SDimitry Andric                              SmallVectorImpl<MCFixup> &Fixups,
70*81ad6265SDimitry Andric                              const MCSubtargetInfo &STI) const;
71*81ad6265SDimitry Andric };
72*81ad6265SDimitry Andric } // end anonymous namespace
73*81ad6265SDimitry Andric 
74*81ad6265SDimitry Andric unsigned
75*81ad6265SDimitry Andric LoongArchMCCodeEmitter::getMachineOpValue(const MCInst &MI, const MCOperand &MO,
76*81ad6265SDimitry Andric                                           SmallVectorImpl<MCFixup> &Fixups,
77*81ad6265SDimitry Andric                                           const MCSubtargetInfo &STI) const {
78*81ad6265SDimitry Andric 
79*81ad6265SDimitry Andric   if (MO.isReg())
80*81ad6265SDimitry Andric     return Ctx.getRegisterInfo()->getEncodingValue(MO.getReg());
81*81ad6265SDimitry Andric 
82*81ad6265SDimitry Andric   if (MO.isImm())
83*81ad6265SDimitry Andric     return static_cast<unsigned>(MO.getImm());
84*81ad6265SDimitry Andric 
85*81ad6265SDimitry Andric   llvm_unreachable("Unhandled expression!");
86*81ad6265SDimitry Andric }
87*81ad6265SDimitry Andric 
88*81ad6265SDimitry Andric unsigned
89*81ad6265SDimitry Andric LoongArchMCCodeEmitter::getImmOpValueSub1(const MCInst &MI, unsigned OpNo,
90*81ad6265SDimitry Andric                                           SmallVectorImpl<MCFixup> &Fixups,
91*81ad6265SDimitry Andric                                           const MCSubtargetInfo &STI) const {
92*81ad6265SDimitry Andric   return MI.getOperand(OpNo).getImm() - 1;
93*81ad6265SDimitry Andric }
94*81ad6265SDimitry Andric 
95*81ad6265SDimitry Andric unsigned
96*81ad6265SDimitry Andric LoongArchMCCodeEmitter::getImmOpValueAsr2(const MCInst &MI, unsigned OpNo,
97*81ad6265SDimitry Andric                                           SmallVectorImpl<MCFixup> &Fixups,
98*81ad6265SDimitry Andric                                           const MCSubtargetInfo &STI) const {
99*81ad6265SDimitry Andric   unsigned Res = MI.getOperand(OpNo).getImm();
100*81ad6265SDimitry Andric   assert((Res & 3) == 0 && "lowest 2 bits are non-zero");
101*81ad6265SDimitry Andric   return Res >> 2;
102*81ad6265SDimitry Andric }
103*81ad6265SDimitry Andric 
104*81ad6265SDimitry Andric void LoongArchMCCodeEmitter::encodeInstruction(
105*81ad6265SDimitry Andric     const MCInst &MI, raw_ostream &OS, SmallVectorImpl<MCFixup> &Fixups,
106*81ad6265SDimitry Andric     const MCSubtargetInfo &STI) const {
107*81ad6265SDimitry Andric   const MCInstrDesc &Desc = MCII.get(MI.getOpcode());
108*81ad6265SDimitry Andric   // Get byte count of instruction.
109*81ad6265SDimitry Andric   unsigned Size = Desc.getSize();
110*81ad6265SDimitry Andric 
111*81ad6265SDimitry Andric   switch (Size) {
112*81ad6265SDimitry Andric   default:
113*81ad6265SDimitry Andric     llvm_unreachable("Unhandled encodeInstruction length!");
114*81ad6265SDimitry Andric   case 4: {
115*81ad6265SDimitry Andric     uint32_t Bits = getBinaryCodeForInstr(MI, Fixups, STI);
116*81ad6265SDimitry Andric     support::endian::write(OS, Bits, support::little);
117*81ad6265SDimitry Andric     break;
118*81ad6265SDimitry Andric   }
119*81ad6265SDimitry Andric   }
120*81ad6265SDimitry Andric }
121*81ad6265SDimitry Andric 
122*81ad6265SDimitry Andric MCCodeEmitter *llvm::createLoongArchMCCodeEmitter(const MCInstrInfo &MCII,
123*81ad6265SDimitry Andric                                                   MCContext &Ctx) {
124*81ad6265SDimitry Andric   return new LoongArchMCCodeEmitter(Ctx, MCII);
125*81ad6265SDimitry Andric }
126*81ad6265SDimitry Andric 
127*81ad6265SDimitry Andric #include "LoongArchGenMCCodeEmitter.inc"
128