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