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 } // end anonymous namespace
56 
57 unsigned
58 LoongArchMCCodeEmitter::getMachineOpValue(const MCInst &MI, const MCOperand &MO,
59                                           SmallVectorImpl<MCFixup> &Fixups,
60                                           const MCSubtargetInfo &STI) const {
61 
62   if (MO.isReg())
63     return Ctx.getRegisterInfo()->getEncodingValue(MO.getReg());
64 
65   if (MO.isImm())
66     return static_cast<unsigned>(MO.getImm());
67 
68   llvm_unreachable("Unhandled expression!");
69   return 0;
70 }
71 
72 void LoongArchMCCodeEmitter::encodeInstruction(
73     const MCInst &MI, raw_ostream &OS, SmallVectorImpl<MCFixup> &Fixups,
74     const MCSubtargetInfo &STI) const {
75   const MCInstrDesc &Desc = MCII.get(MI.getOpcode());
76   // Get byte count of instruction.
77   unsigned Size = Desc.getSize();
78 
79   switch (Size) {
80   default:
81     llvm_unreachable("Unhandled encodeInstruction length!");
82   case 4: {
83     uint32_t Bits = getBinaryCodeForInstr(MI, Fixups, STI);
84     support::endian::write(OS, Bits, support::little);
85     break;
86   }
87   }
88 }
89 
90 MCCodeEmitter *llvm::createLoongArchMCCodeEmitter(const MCInstrInfo &MCII,
91                                                   MCContext &Ctx) {
92   return new LoongArchMCCodeEmitter(Ctx, MCII);
93 }
94 
95 #include "LoongArchGenMCCodeEmitter.inc"
96