1 //===-- LanaiMCCodeEmitter.cpp - Convert Lanai code to machine code -------===//
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
7 //===----------------------------------------------------------------------===//
9 // This file implements the LanaiMCCodeEmitter class.
11 //===----------------------------------------------------------------------===//
13 #include "LanaiAluCode.h"
14 #include "MCTargetDesc/LanaiBaseInfo.h"
15 #include "MCTargetDesc/LanaiFixupKinds.h"
16 #include "MCTargetDesc/LanaiMCExpr.h"
17 #include "llvm/ADT/SmallVector.h"
18 #include "llvm/ADT/Statistic.h"
19 #include "llvm/MC/MCCodeEmitter.h"
20 #include "llvm/MC/MCExpr.h"
21 #include "llvm/MC/MCFixup.h"
22 #include "llvm/MC/MCInst.h"
23 #include "llvm/MC/MCInstrInfo.h"
24 #include "llvm/MC/MCRegisterInfo.h"
25 #include "llvm/MC/MCSubtargetInfo.h"
26 #include "llvm/Support/Casting.h"
27 #include "llvm/Support/raw_ostream.h"
31 #define DEBUG_TYPE "mccodeemitter"
33 STATISTIC(MCNumEmitted
, "Number of MC instructions emitted");
39 class LanaiMCCodeEmitter
: public MCCodeEmitter
{
41 LanaiMCCodeEmitter(const MCInstrInfo
&MCII
, MCContext
&C
) {}
42 LanaiMCCodeEmitter(const LanaiMCCodeEmitter
&) = delete;
43 void operator=(const LanaiMCCodeEmitter
&) = delete;
44 ~LanaiMCCodeEmitter() override
= default;
46 // The functions below are called by TableGen generated functions for getting
47 // the binary encoding of instructions/opereands.
49 // getBinaryCodeForInstr - TableGen'erated function for getting the
50 // binary encoding for an instruction.
51 uint64_t getBinaryCodeForInstr(const MCInst
&Inst
,
52 SmallVectorImpl
<MCFixup
> &Fixups
,
53 const MCSubtargetInfo
&SubtargetInfo
) const;
55 // getMachineOpValue - Return binary encoding of operand. If the machine
56 // operand requires relocation, record the relocation and return zero.
57 unsigned getMachineOpValue(const MCInst
&Inst
, const MCOperand
&MCOp
,
58 SmallVectorImpl
<MCFixup
> &Fixups
,
59 const MCSubtargetInfo
&SubtargetInfo
) const;
61 unsigned getRiMemoryOpValue(const MCInst
&Inst
, unsigned OpNo
,
62 SmallVectorImpl
<MCFixup
> &Fixups
,
63 const MCSubtargetInfo
&SubtargetInfo
) const;
65 unsigned getRrMemoryOpValue(const MCInst
&Inst
, unsigned OpNo
,
66 SmallVectorImpl
<MCFixup
> &Fixups
,
67 const MCSubtargetInfo
&SubtargetInfo
) const;
69 unsigned getSplsOpValue(const MCInst
&Inst
, unsigned OpNo
,
70 SmallVectorImpl
<MCFixup
> &Fixups
,
71 const MCSubtargetInfo
&SubtargetInfo
) const;
73 unsigned getBranchTargetOpValue(const MCInst
&Inst
, unsigned OpNo
,
74 SmallVectorImpl
<MCFixup
> &Fixups
,
75 const MCSubtargetInfo
&SubtargetInfo
) const;
77 void encodeInstruction(const MCInst
&Inst
, raw_ostream
&Ostream
,
78 SmallVectorImpl
<MCFixup
> &Fixups
,
79 const MCSubtargetInfo
&SubtargetInfo
) const override
;
81 unsigned adjustPqBitsRmAndRrm(const MCInst
&Inst
, unsigned Value
,
82 const MCSubtargetInfo
&STI
) const;
84 unsigned adjustPqBitsSpls(const MCInst
&Inst
, unsigned Value
,
85 const MCSubtargetInfo
&STI
) const;
88 } // end anonymous namespace
90 static Lanai::Fixups
FixupKind(const MCExpr
*Expr
) {
91 if (isa
<MCSymbolRefExpr
>(Expr
))
92 return Lanai::FIXUP_LANAI_21
;
93 if (const LanaiMCExpr
*McExpr
= dyn_cast
<LanaiMCExpr
>(Expr
)) {
94 LanaiMCExpr::VariantKind ExprKind
= McExpr
->getKind();
96 case LanaiMCExpr::VK_Lanai_None
:
97 return Lanai::FIXUP_LANAI_21
;
98 case LanaiMCExpr::VK_Lanai_ABS_HI
:
99 return Lanai::FIXUP_LANAI_HI16
;
100 case LanaiMCExpr::VK_Lanai_ABS_LO
:
101 return Lanai::FIXUP_LANAI_LO16
;
104 return Lanai::Fixups(0);
107 // getMachineOpValue - Return binary encoding of operand. If the machine
108 // operand requires relocation, record the relocation and return zero.
109 unsigned LanaiMCCodeEmitter::getMachineOpValue(
110 const MCInst
&Inst
, const MCOperand
&MCOp
, SmallVectorImpl
<MCFixup
> &Fixups
,
111 const MCSubtargetInfo
&SubtargetInfo
) const {
113 return getLanaiRegisterNumbering(MCOp
.getReg());
115 return static_cast<unsigned>(MCOp
.getImm());
117 // MCOp must be an expression
118 assert(MCOp
.isExpr());
119 const MCExpr
*Expr
= MCOp
.getExpr();
121 // Extract the symbolic reference side of a binary expression.
122 if (Expr
->getKind() == MCExpr::Binary
) {
123 const MCBinaryExpr
*BinaryExpr
= static_cast<const MCBinaryExpr
*>(Expr
);
124 Expr
= BinaryExpr
->getLHS();
127 assert(isa
<LanaiMCExpr
>(Expr
) || Expr
->getKind() == MCExpr::SymbolRef
);
128 // Push fixup (all info is contained within)
130 MCFixup::create(0, MCOp
.getExpr(), MCFixupKind(FixupKind(Expr
))));
134 // Helper function to adjust P and Q bits on load and store instructions.
135 static unsigned adjustPqBits(const MCInst
&Inst
, unsigned Value
,
136 unsigned PBitShift
, unsigned QBitShift
) {
137 const MCOperand AluOp
= Inst
.getOperand(3);
138 unsigned AluCode
= AluOp
.getImm();
140 // Set the P bit to one iff the immediate is nonzero and not a post-op
142 const MCOperand Op2
= Inst
.getOperand(2);
143 Value
&= ~(1 << PBitShift
);
144 if (!LPAC::isPostOp(AluCode
) &&
145 ((Op2
.isImm() && Op2
.getImm() != 0) ||
146 (Op2
.isReg() && Op2
.getReg() != Lanai::R0
) || (Op2
.isExpr())))
147 Value
|= (1 << PBitShift
);
149 // Set the Q bit to one iff it is a post- or pre-op instruction.
150 assert(Inst
.getOperand(0).isReg() && Inst
.getOperand(1).isReg() &&
151 "Expected register operand.");
152 Value
&= ~(1 << QBitShift
);
153 if (LPAC::modifiesOp(AluCode
) && ((Op2
.isImm() && Op2
.getImm() != 0) ||
154 (Op2
.isReg() && Op2
.getReg() != Lanai::R0
)))
155 Value
|= (1 << QBitShift
);
161 LanaiMCCodeEmitter::adjustPqBitsRmAndRrm(const MCInst
&Inst
, unsigned Value
,
162 const MCSubtargetInfo
&STI
) const {
163 return adjustPqBits(Inst
, Value
, 17, 16);
167 LanaiMCCodeEmitter::adjustPqBitsSpls(const MCInst
&Inst
, unsigned Value
,
168 const MCSubtargetInfo
&STI
) const {
169 return adjustPqBits(Inst
, Value
, 11, 10);
172 void LanaiMCCodeEmitter::encodeInstruction(
173 const MCInst
&Inst
, raw_ostream
&Ostream
, SmallVectorImpl
<MCFixup
> &Fixups
,
174 const MCSubtargetInfo
&SubtargetInfo
) const {
175 // Get instruction encoding and emit it
176 unsigned Value
= getBinaryCodeForInstr(Inst
, Fixups
, SubtargetInfo
);
177 ++MCNumEmitted
; // Keep track of the number of emitted insns.
179 // Emit bytes in big-endian
180 for (int i
= (4 - 1) * 8; i
>= 0; i
-= 8)
181 Ostream
<< static_cast<char>((Value
>> i
) & 0xff);
184 // Encode Lanai Memory Operand
185 unsigned LanaiMCCodeEmitter::getRiMemoryOpValue(
186 const MCInst
&Inst
, unsigned OpNo
, SmallVectorImpl
<MCFixup
> &Fixups
,
187 const MCSubtargetInfo
&SubtargetInfo
) const {
189 const MCOperand Op1
= Inst
.getOperand(OpNo
+ 0);
190 const MCOperand Op2
= Inst
.getOperand(OpNo
+ 1);
191 const MCOperand AluOp
= Inst
.getOperand(OpNo
+ 2);
193 assert(Op1
.isReg() && "First operand is not register.");
194 assert((Op2
.isImm() || Op2
.isExpr()) &&
195 "Second operand is neither an immediate nor an expression.");
196 assert((LPAC::getAluOp(AluOp
.getImm()) == LPAC::ADD
) &&
197 "Register immediate only supports addition operator");
199 Encoding
= (getLanaiRegisterNumbering(Op1
.getReg()) << 18);
201 assert(isInt
<16>(Op2
.getImm()) &&
202 "Constant value truncated (limited to 16-bit)");
204 Encoding
|= (Op2
.getImm() & 0xffff);
205 if (Op2
.getImm() != 0) {
206 if (LPAC::isPreOp(AluOp
.getImm()))
207 Encoding
|= (0x3 << 16);
208 if (LPAC::isPostOp(AluOp
.getImm()))
209 Encoding
|= (0x1 << 16);
212 getMachineOpValue(Inst
, Op2
, Fixups
, SubtargetInfo
);
217 unsigned LanaiMCCodeEmitter::getRrMemoryOpValue(
218 const MCInst
&Inst
, unsigned OpNo
, SmallVectorImpl
<MCFixup
> &Fixups
,
219 const MCSubtargetInfo
&SubtargetInfo
) const {
221 const MCOperand Op1
= Inst
.getOperand(OpNo
+ 0);
222 const MCOperand Op2
= Inst
.getOperand(OpNo
+ 1);
223 const MCOperand AluMCOp
= Inst
.getOperand(OpNo
+ 2);
225 assert(Op1
.isReg() && "First operand is not register.");
226 Encoding
= (getLanaiRegisterNumbering(Op1
.getReg()) << 15);
227 assert(Op2
.isReg() && "Second operand is not register.");
228 Encoding
|= (getLanaiRegisterNumbering(Op2
.getReg()) << 10);
230 assert(AluMCOp
.isImm() && "Third operator is not immediate.");
232 unsigned AluOp
= AluMCOp
.getImm();
233 Encoding
|= LPAC::encodeLanaiAluCode(AluOp
) << 5;
235 if (LPAC::isPreOp(AluOp
))
236 Encoding
|= (0x3 << 8);
237 if (LPAC::isPostOp(AluOp
))
238 Encoding
|= (0x1 << 8);
240 switch (LPAC::getAluOp(AluOp
)) {
256 LanaiMCCodeEmitter::getSplsOpValue(const MCInst
&Inst
, unsigned OpNo
,
257 SmallVectorImpl
<MCFixup
> &Fixups
,
258 const MCSubtargetInfo
&SubtargetInfo
) const {
260 const MCOperand Op1
= Inst
.getOperand(OpNo
+ 0);
261 const MCOperand Op2
= Inst
.getOperand(OpNo
+ 1);
262 const MCOperand AluOp
= Inst
.getOperand(OpNo
+ 2);
264 assert(Op1
.isReg() && "First operand is not register.");
265 assert((Op2
.isImm() || Op2
.isExpr()) &&
266 "Second operand is neither an immediate nor an expression.");
267 assert((LPAC::getAluOp(AluOp
.getImm()) == LPAC::ADD
) &&
268 "Register immediate only supports addition operator");
270 Encoding
= (getLanaiRegisterNumbering(Op1
.getReg()) << 12);
272 assert(isInt
<10>(Op2
.getImm()) &&
273 "Constant value truncated (limited to 10-bit)");
275 Encoding
|= (Op2
.getImm() & 0x3ff);
276 if (Op2
.getImm() != 0) {
277 if (LPAC::isPreOp(AluOp
.getImm()))
278 Encoding
|= (0x3 << 10);
279 if (LPAC::isPostOp(AluOp
.getImm()))
280 Encoding
|= (0x1 << 10);
283 getMachineOpValue(Inst
, Op2
, Fixups
, SubtargetInfo
);
288 unsigned LanaiMCCodeEmitter::getBranchTargetOpValue(
289 const MCInst
&Inst
, unsigned OpNo
, SmallVectorImpl
<MCFixup
> &Fixups
,
290 const MCSubtargetInfo
&SubtargetInfo
) const {
291 const MCOperand
&MCOp
= Inst
.getOperand(OpNo
);
292 if (MCOp
.isReg() || MCOp
.isImm())
293 return getMachineOpValue(Inst
, MCOp
, Fixups
, SubtargetInfo
);
295 Fixups
.push_back(MCFixup::create(
296 0, MCOp
.getExpr(), static_cast<MCFixupKind
>(Lanai::FIXUP_LANAI_25
)));
301 #include "LanaiGenMCCodeEmitter.inc"
303 } // end namespace llvm
305 llvm::MCCodeEmitter
*
306 llvm::createLanaiMCCodeEmitter(const MCInstrInfo
&InstrInfo
,
307 const MCRegisterInfo
& /*MRI*/,
308 MCContext
&context
) {
309 return new LanaiMCCodeEmitter(InstrInfo
, context
);