LLVM 22.0.0git
LanaiMCCodeEmitter.cpp
Go to the documentation of this file.
1//===-- LanaiMCCodeEmitter.cpp - Convert Lanai 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 LanaiMCCodeEmitter class.
10//
11//===----------------------------------------------------------------------===//
12
13#include "LanaiAluCode.h"
18#include "llvm/ADT/Statistic.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"
27#include <cassert>
28#include <cstdint>
29
30#define DEBUG_TYPE "mccodeemitter"
31
32STATISTIC(MCNumEmitted, "Number of MC instructions emitted");
33
34namespace llvm {
35
36namespace {
37
38class LanaiMCCodeEmitter : public MCCodeEmitter {
39public:
40 LanaiMCCodeEmitter(const MCInstrInfo &MCII, MCContext &C) {}
41 LanaiMCCodeEmitter(const LanaiMCCodeEmitter &) = delete;
42 void operator=(const LanaiMCCodeEmitter &) = delete;
43 ~LanaiMCCodeEmitter() override = default;
44
45 // The functions below are called by TableGen generated functions for getting
46 // the binary encoding of instructions/opereands.
47
48 // getBinaryCodeForInstr - TableGen'erated function for getting the
49 // binary encoding for an instruction.
50 uint64_t getBinaryCodeForInstr(const MCInst &Inst,
51 SmallVectorImpl<MCFixup> &Fixups,
52 const MCSubtargetInfo &SubtargetInfo) const;
53
54 // getMachineOpValue - Return binary encoding of operand. If the machine
55 // operand requires relocation, record the relocation and return zero.
56 unsigned getMachineOpValue(const MCInst &Inst, const MCOperand &MCOp,
57 SmallVectorImpl<MCFixup> &Fixups,
58 const MCSubtargetInfo &SubtargetInfo) const;
59
60 unsigned getRiMemoryOpValue(const MCInst &Inst, unsigned OpNo,
61 SmallVectorImpl<MCFixup> &Fixups,
62 const MCSubtargetInfo &SubtargetInfo) const;
63
64 unsigned getRrMemoryOpValue(const MCInst &Inst, unsigned OpNo,
65 SmallVectorImpl<MCFixup> &Fixups,
66 const MCSubtargetInfo &SubtargetInfo) const;
67
68 unsigned getSplsOpValue(const MCInst &Inst, unsigned OpNo,
69 SmallVectorImpl<MCFixup> &Fixups,
70 const MCSubtargetInfo &SubtargetInfo) const;
71
72 unsigned getBranchTargetOpValue(const MCInst &Inst, unsigned OpNo,
73 SmallVectorImpl<MCFixup> &Fixups,
74 const MCSubtargetInfo &SubtargetInfo) const;
75
76 void encodeInstruction(const MCInst &Inst, SmallVectorImpl<char> &CB,
77 SmallVectorImpl<MCFixup> &Fixups,
78 const MCSubtargetInfo &SubtargetInfo) const override;
79
80 unsigned adjustPqBitsRmAndRrm(const MCInst &Inst, unsigned Value,
81 const MCSubtargetInfo &STI) const;
82
83 unsigned adjustPqBitsSpls(const MCInst &Inst, unsigned Value,
84 const MCSubtargetInfo &STI) const;
85};
86
87} // end anonymous namespace
88
89static Lanai::Fixups FixupKind(const MCExpr *Expr) {
90 if (isa<MCSymbolRefExpr>(Expr))
92 if (const MCSpecifierExpr *McExpr = dyn_cast<MCSpecifierExpr>(Expr)) {
93 Lanai::Specifier ExprKind = McExpr->getSpecifier();
94 switch (ExprKind) {
95 case Lanai::S_None:
97 case Lanai::S_ABS_HI:
99 case Lanai::S_ABS_LO:
101 }
102 }
103 return Lanai::Fixups(0);
104}
105
106// getMachineOpValue - Return binary encoding of operand. If the machine
107// operand requires relocation, record the relocation and return zero.
108unsigned LanaiMCCodeEmitter::getMachineOpValue(
109 const MCInst &Inst, const MCOperand &MCOp, SmallVectorImpl<MCFixup> &Fixups,
110 const MCSubtargetInfo &SubtargetInfo) const {
111 if (MCOp.isReg())
112 return getLanaiRegisterNumbering(MCOp.getReg());
113 if (MCOp.isImm())
114 return static_cast<unsigned>(MCOp.getImm());
115
116 // MCOp must be an expression
117 assert(MCOp.isExpr());
118 const MCExpr *Expr = MCOp.getExpr();
119
120 // Extract the symbolic reference side of a binary expression.
121 if (Expr->getKind() == MCExpr::Binary) {
122 const MCBinaryExpr *BinaryExpr = static_cast<const MCBinaryExpr *>(Expr);
123 Expr = BinaryExpr->getLHS();
124 }
125
126 assert(isa<MCSpecifierExpr>(Expr) || Expr->getKind() == MCExpr::SymbolRef);
127 // Push fixup (all info is contained within)
128 Fixups.push_back(
129 MCFixup::create(0, MCOp.getExpr(), MCFixupKind(FixupKind(Expr))));
130 return 0;
131}
132
133// Helper function to adjust P and Q bits on load and store instructions.
134static unsigned adjustPqBits(const MCInst &Inst, unsigned Value,
135 unsigned PBitShift, unsigned QBitShift) {
136 const MCOperand AluOp = Inst.getOperand(3);
137 unsigned AluCode = AluOp.getImm();
138
139 // Set the P bit to one iff the immediate is nonzero and not a post-op
140 // instruction.
141 const MCOperand Op2 = Inst.getOperand(2);
142 Value &= ~(1 << PBitShift);
143 if (!LPAC::isPostOp(AluCode) &&
144 ((Op2.isImm() && Op2.getImm() != 0) ||
145 (Op2.isReg() && Op2.getReg() != Lanai::R0) || (Op2.isExpr())))
146 Value |= (1 << PBitShift);
147
148 // Set the Q bit to one iff it is a post- or pre-op instruction.
149 assert(Inst.getOperand(0).isReg() && Inst.getOperand(1).isReg() &&
150 "Expected register operand.");
151 Value &= ~(1 << QBitShift);
152 if (LPAC::modifiesOp(AluCode) && ((Op2.isImm() && Op2.getImm() != 0) ||
153 (Op2.isReg() && Op2.getReg() != Lanai::R0)))
154 Value |= (1 << QBitShift);
155
156 return Value;
157}
158
159unsigned
160LanaiMCCodeEmitter::adjustPqBitsRmAndRrm(const MCInst &Inst, unsigned Value,
161 const MCSubtargetInfo &STI) const {
162 return adjustPqBits(Inst, Value, 17, 16);
163}
164
165unsigned
166LanaiMCCodeEmitter::adjustPqBitsSpls(const MCInst &Inst, unsigned Value,
167 const MCSubtargetInfo &STI) const {
168 return adjustPqBits(Inst, Value, 11, 10);
169}
170
171void LanaiMCCodeEmitter::encodeInstruction(
172 const MCInst &Inst, SmallVectorImpl<char> &CB,
173 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.
178
179 support::endian::write<uint32_t>(CB, Value, llvm::endianness::big);
180}
181
182// Encode Lanai Memory Operand
183unsigned LanaiMCCodeEmitter::getRiMemoryOpValue(
184 const MCInst &Inst, unsigned OpNo, SmallVectorImpl<MCFixup> &Fixups,
185 const MCSubtargetInfo &SubtargetInfo) const {
186 unsigned Encoding;
187 const MCOperand Op1 = Inst.getOperand(OpNo + 0);
188 const MCOperand Op2 = Inst.getOperand(OpNo + 1);
189 const MCOperand AluOp = Inst.getOperand(OpNo + 2);
190
191 assert(Op1.isReg() && "First operand is not register.");
192 assert((Op2.isImm() || Op2.isExpr()) &&
193 "Second operand is neither an immediate nor an expression.");
194 assert((LPAC::getAluOp(AluOp.getImm()) == LPAC::ADD) &&
195 "Register immediate only supports addition operator");
196
197 Encoding = (getLanaiRegisterNumbering(Op1.getReg()) << 18);
198 if (Op2.isImm()) {
199 assert(isInt<16>(Op2.getImm()) &&
200 "Constant value truncated (limited to 16-bit)");
201
202 Encoding |= (Op2.getImm() & 0xffff);
203 if (Op2.getImm() != 0) {
204 if (LPAC::isPreOp(AluOp.getImm()))
205 Encoding |= (0x3 << 16);
206 if (LPAC::isPostOp(AluOp.getImm()))
207 Encoding |= (0x1 << 16);
208 }
209 } else
210 getMachineOpValue(Inst, Op2, Fixups, SubtargetInfo);
211
212 return Encoding;
213}
214
215unsigned LanaiMCCodeEmitter::getRrMemoryOpValue(
216 const MCInst &Inst, unsigned OpNo, SmallVectorImpl<MCFixup> &Fixups,
217 const MCSubtargetInfo &SubtargetInfo) const {
218 unsigned Encoding;
219 const MCOperand Op1 = Inst.getOperand(OpNo + 0);
220 const MCOperand Op2 = Inst.getOperand(OpNo + 1);
221 const MCOperand AluMCOp = Inst.getOperand(OpNo + 2);
222
223 assert(Op1.isReg() && "First operand is not register.");
224 Encoding = (getLanaiRegisterNumbering(Op1.getReg()) << 15);
225 assert(Op2.isReg() && "Second operand is not register.");
226 Encoding |= (getLanaiRegisterNumbering(Op2.getReg()) << 10);
227
228 assert(AluMCOp.isImm() && "Third operator is not immediate.");
229 // Set BBB
230 unsigned AluOp = AluMCOp.getImm();
231 Encoding |= LPAC::encodeLanaiAluCode(AluOp) << 5;
232 // Set P and Q
233 if (LPAC::isPreOp(AluOp))
234 Encoding |= (0x3 << 8);
235 if (LPAC::isPostOp(AluOp))
236 Encoding |= (0x1 << 8);
237 // Set JJJJ
238 switch (LPAC::getAluOp(AluOp)) {
239 case LPAC::SHL:
240 case LPAC::SRL:
241 Encoding |= 0x10;
242 break;
243 case LPAC::SRA:
244 Encoding |= 0x18;
245 break;
246 default:
247 break;
248 }
249
250 return Encoding;
251}
252
253unsigned
254LanaiMCCodeEmitter::getSplsOpValue(const MCInst &Inst, unsigned OpNo,
255 SmallVectorImpl<MCFixup> &Fixups,
256 const MCSubtargetInfo &SubtargetInfo) const {
257 unsigned Encoding;
258 const MCOperand Op1 = Inst.getOperand(OpNo + 0);
259 const MCOperand Op2 = Inst.getOperand(OpNo + 1);
260 const MCOperand AluOp = Inst.getOperand(OpNo + 2);
261
262 assert(Op1.isReg() && "First operand is not register.");
263 assert((Op2.isImm() || Op2.isExpr()) &&
264 "Second operand is neither an immediate nor an expression.");
265 assert((LPAC::getAluOp(AluOp.getImm()) == LPAC::ADD) &&
266 "Register immediate only supports addition operator");
267
268 Encoding = (getLanaiRegisterNumbering(Op1.getReg()) << 12);
269 if (Op2.isImm()) {
270 assert(isInt<10>(Op2.getImm()) &&
271 "Constant value truncated (limited to 10-bit)");
272
273 Encoding |= (Op2.getImm() & 0x3ff);
274 if (Op2.getImm() != 0) {
275 if (LPAC::isPreOp(AluOp.getImm()))
276 Encoding |= (0x3 << 10);
277 if (LPAC::isPostOp(AluOp.getImm()))
278 Encoding |= (0x1 << 10);
279 }
280 } else
281 getMachineOpValue(Inst, Op2, Fixups, SubtargetInfo);
282
283 return Encoding;
284}
285
286unsigned LanaiMCCodeEmitter::getBranchTargetOpValue(
287 const MCInst &Inst, unsigned OpNo, SmallVectorImpl<MCFixup> &Fixups,
288 const MCSubtargetInfo &SubtargetInfo) const {
289 const MCOperand &MCOp = Inst.getOperand(OpNo);
290 if (MCOp.isReg() || MCOp.isImm())
291 return getMachineOpValue(Inst, MCOp, Fixups, SubtargetInfo);
292
293 Fixups.push_back(MCFixup::create(0, MCOp.getExpr(), Lanai::FIXUP_LANAI_25));
294
295 return 0;
296}
297
298#include "LanaiGenMCCodeEmitter.inc"
299
300} // end namespace llvm
301
304 MCContext &context) {
305 return new LanaiMCCodeEmitter(InstrInfo, context);
306}
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static uint32_t getBranchTargetOpValue(const MCInst &MI, unsigned OpIdx, unsigned FixupKind, SmallVectorImpl< MCFixup > &Fixups, const MCSubtargetInfo &STI)
getBranchTargetOpValue - Helper function to get the branch target operand, which is either an immedia...
This file defines the SmallVector class.
This file defines the 'Statistic' class, which is designed to be an easy way to expose various metric...
#define STATISTIC(VARNAME, DESC)
Definition: Statistic.h:167
MCCodeEmitter - Generic instruction encoding interface.
Definition: MCCodeEmitter.h:23
Context object for machine code objects.
Definition: MCContext.h:83
Base class for the full range of assembler expressions which are needed for parsing.
Definition: MCExpr.h:34
@ SymbolRef
References to labels and assigned expressions.
Definition: MCExpr.h:43
@ Binary
Binary expressions.
Definition: MCExpr.h:41
static MCFixup create(uint32_t Offset, const MCExpr *Value, MCFixupKind Kind, bool PCRel=false)
Consider bit fields if we need more flags.
Definition: MCFixup.h:86
Instances of this class represent a single low-level machine instruction.
Definition: MCInst.h:188
const MCOperand & getOperand(unsigned i) const
Definition: MCInst.h:210
Interface to description of machine instruction set.
Definition: MCInstrInfo.h:27
Instances of this class represent operands of the MCInst class.
Definition: MCInst.h:40
int64_t getImm() const
Definition: MCInst.h:84
bool isImm() const
Definition: MCInst.h:66
bool isReg() const
Definition: MCInst.h:65
MCRegister getReg() const
Returns the register number.
Definition: MCInst.h:73
bool isExpr() const
Definition: MCInst.h:69
Extension point for target-specific MCExpr subclasses with a relocation specifier,...
Definition: MCExpr.h:495
LLVM Value Representation.
Definition: Value.h:75
@ C
The default llvm calling convention, compatible with C.
Definition: CallingConv.h:34
static bool isPreOp(unsigned AluOp)
Definition: LanaiAluCode.h:57
static unsigned getAluOp(unsigned AluOp)
Definition: LanaiAluCode.h:52
static unsigned encodeLanaiAluCode(unsigned AluOp)
Definition: LanaiAluCode.h:47
static bool isPostOp(unsigned AluOp)
Definition: LanaiAluCode.h:59
static bool modifiesOp(unsigned AluOp)
Definition: LanaiAluCode.h:71
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
MCCodeEmitter * createLanaiMCCodeEmitter(const MCInstrInfo &MCII, MCContext &Ctx)
uint16_t MCFixupKind
Extensible enumeration to represent the type of a fixup.
Definition: MCFixup.h:22
static unsigned adjustPqBits(const MCInst &Inst, unsigned Value, unsigned PBitShift, unsigned QBitShift)
static unsigned getLanaiRegisterNumbering(MCRegister Reg)
Definition: LanaiBaseInfo.h:40