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:
LoongArchMCCodeEmitter(MCContext & ctx,MCInstrInfo const & MCII)34 LoongArchMCCodeEmitter(MCContext &ctx, MCInstrInfo const &MCII)
35 : Ctx(ctx), MCII(MCII) {}
36
~LoongArchMCCodeEmitter()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
getMachineOpValue(const MCInst & MI,const MCOperand & MO,SmallVectorImpl<MCFixup> & Fixups,const MCSubtargetInfo & STI) const75 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
getImmOpValueSub1(const MCInst & MI,unsigned OpNo,SmallVectorImpl<MCFixup> & Fixups,const MCSubtargetInfo & STI) const89 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
getImmOpValueAsr2(const MCInst & MI,unsigned OpNo,SmallVectorImpl<MCFixup> & Fixups,const MCSubtargetInfo & STI) const96 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
encodeInstruction(const MCInst & MI,raw_ostream & OS,SmallVectorImpl<MCFixup> & Fixups,const MCSubtargetInfo & STI) const104 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
createLoongArchMCCodeEmitter(const MCInstrInfo & MCII,MCContext & Ctx)122 MCCodeEmitter *llvm::createLoongArchMCCodeEmitter(const MCInstrInfo &MCII,
123 MCContext &Ctx) {
124 return new LoongArchMCCodeEmitter(Ctx, MCII);
125 }
126
127 #include "LoongArchGenMCCodeEmitter.inc"
128