1//===-- SparcMCCodeEmitter.cpp - Convert Sparc 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 SparcMCCodeEmitter class.
10//
11//===----------------------------------------------------------------------===//
12
13#include "MCTargetDesc/SparcFixupKinds.h"
14#include "MCTargetDesc/SparcMCAsmInfo.h"
15#include "SparcMCTargetDesc.h"
16#include "llvm/ADT/SmallVector.h"
17#include "llvm/ADT/Statistic.h"
18#include "llvm/BinaryFormat/ELF.h"
19#include "llvm/MC/MCAsmInfo.h"
20#include "llvm/MC/MCCodeEmitter.h"
21#include "llvm/MC/MCContext.h"
22#include "llvm/MC/MCExpr.h"
23#include "llvm/MC/MCFixup.h"
24#include "llvm/MC/MCInst.h"
25#include "llvm/MC/MCInstrInfo.h"
26#include "llvm/MC/MCObjectFileInfo.h"
27#include "llvm/MC/MCRegisterInfo.h"
28#include "llvm/MC/MCSubtargetInfo.h"
29#include "llvm/MC/MCSymbol.h"
30#include "llvm/Support/Casting.h"
31#include "llvm/Support/EndianStream.h"
32#include "llvm/Support/ErrorHandling.h"
33#include <cassert>
34#include <cstdint>
35
36using namespace llvm;
37
38#define DEBUG_TYPE "mccodeemitter"
39
40STATISTIC(MCNumEmitted, "Number of MC instructions emitted");
41
42namespace {
43
44class SparcMCCodeEmitter : public MCCodeEmitter {
45 MCContext &Ctx;
46
47public:
48 SparcMCCodeEmitter(const MCInstrInfo &, MCContext &ctx)
49 : Ctx(ctx) {}
50 SparcMCCodeEmitter(const SparcMCCodeEmitter &) = delete;
51 SparcMCCodeEmitter &operator=(const SparcMCCodeEmitter &) = delete;
52 ~SparcMCCodeEmitter() override = default;
53
54 void encodeInstruction(const MCInst &MI, SmallVectorImpl<char> &CB,
55 SmallVectorImpl<MCFixup> &Fixups,
56 const MCSubtargetInfo &STI) const override;
57
58 // getBinaryCodeForInstr - TableGen'erated function for getting the
59 // binary encoding for an instruction.
60 uint64_t getBinaryCodeForInstr(const MCInst &MI,
61 SmallVectorImpl<MCFixup> &Fixups,
62 const MCSubtargetInfo &STI) const;
63
64 /// getMachineOpValue - Return binary encoding of operand. If the machine
65 /// operand requires relocation, record the relocation and return zero.
66 unsigned getMachineOpValue(const MCInst &MI, const MCOperand &MO,
67 SmallVectorImpl<MCFixup> &Fixups,
68 const MCSubtargetInfo &STI) const;
69 unsigned getCallTargetOpValue(const MCInst &MI, unsigned OpNo,
70 SmallVectorImpl<MCFixup> &Fixups,
71 const MCSubtargetInfo &STI) const;
72 unsigned getBranchTargetOpValue(const MCInst &MI, unsigned OpNo,
73 SmallVectorImpl<MCFixup> &Fixups,
74 const MCSubtargetInfo &STI) const;
75 unsigned getSImm5OpValue(const MCInst &MI, unsigned OpNo,
76 SmallVectorImpl<MCFixup> &Fixups,
77 const MCSubtargetInfo &STI) const;
78 unsigned getSImm13OpValue(const MCInst &MI, unsigned OpNo,
79 SmallVectorImpl<MCFixup> &Fixups,
80 const MCSubtargetInfo &STI) const;
81 unsigned getBranchPredTargetOpValue(const MCInst &MI, unsigned OpNo,
82 SmallVectorImpl<MCFixup> &Fixups,
83 const MCSubtargetInfo &STI) const;
84 unsigned getBranchOnRegTargetOpValue(const MCInst &MI, unsigned OpNo,
85 SmallVectorImpl<MCFixup> &Fixups,
86 const MCSubtargetInfo &STI) const;
87 unsigned getCompareAndBranchTargetOpValue(const MCInst &MI, unsigned OpNo,
88 SmallVectorImpl<MCFixup> &Fixups,
89 const MCSubtargetInfo &STI) const;
90};
91
92} // end anonymous namespace
93
94void SparcMCCodeEmitter::encodeInstruction(const MCInst &MI,
95 SmallVectorImpl<char> &CB,
96 SmallVectorImpl<MCFixup> &Fixups,
97 const MCSubtargetInfo &STI) const {
98 unsigned Bits = getBinaryCodeForInstr(MI, Fixups, STI);
99 support::endian::write(Out&: CB, V: Bits,
100 E: Ctx.getAsmInfo()->isLittleEndian()
101 ? llvm::endianness::little
102 : llvm::endianness::big);
103
104 // Some instructions have phantom operands that only contribute a fixup entry.
105 unsigned SymOpNo = 0;
106 switch (MI.getOpcode()) {
107 default: break;
108 case SP::TLS_CALL: SymOpNo = 1; break;
109 case SP::GDOP_LDrr:
110 case SP::GDOP_LDXrr:
111 case SP::TLS_ADDrr:
112 case SP::TLS_LDrr:
113 case SP::TLS_LDXrr: SymOpNo = 3; break;
114 }
115 if (SymOpNo != 0) {
116 const MCOperand &MO = MI.getOperand(i: SymOpNo);
117 uint64_t op = getMachineOpValue(MI, MO, Fixups, STI);
118 assert(op == 0 && "Unexpected operand value!");
119 (void)op; // suppress warning.
120 }
121
122 ++MCNumEmitted; // Keep track of the # of mi's emitted.
123}
124
125unsigned SparcMCCodeEmitter::
126getMachineOpValue(const MCInst &MI, const MCOperand &MO,
127 SmallVectorImpl<MCFixup> &Fixups,
128 const MCSubtargetInfo &STI) const {
129 if (MO.isReg())
130 return Ctx.getRegisterInfo()->getEncodingValue(Reg: MO.getReg());
131
132 if (MO.isImm())
133 return MO.getImm();
134
135 assert(MO.isExpr());
136 const MCExpr *Expr = MO.getExpr();
137 if (auto *SExpr = dyn_cast<MCSpecifierExpr>(Val: Expr)) {
138 Fixups.push_back(Elt: MCFixup::create(Offset: 0, Value: Expr, Kind: SExpr->getSpecifier()));
139 return 0;
140 }
141
142 int64_t Res;
143 if (Expr->evaluateAsAbsolute(Res))
144 return Res;
145
146 llvm_unreachable("Unhandled expression!");
147 return 0;
148}
149
150unsigned SparcMCCodeEmitter::getSImm5OpValue(const MCInst &MI, unsigned OpNo,
151 SmallVectorImpl<MCFixup> &Fixups,
152 const MCSubtargetInfo &STI) const {
153 const MCOperand &MO = MI.getOperand(i: OpNo);
154
155 if (MO.isImm())
156 return MO.getImm();
157
158 assert(MO.isExpr() &&
159 "getSImm5OpValue expects only expressions or an immediate");
160
161 const MCExpr *Expr = MO.getExpr();
162
163 // Constant value, no fixup is needed
164 if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Val: Expr))
165 return CE->getValue();
166
167 if (auto *SExpr = dyn_cast<MCSpecifierExpr>(Val: Expr)) {
168 Fixups.push_back(Elt: MCFixup::create(Offset: 0, Value: Expr, Kind: SExpr->getSpecifier()));
169 return 0;
170 }
171 Fixups.push_back(Elt: MCFixup::create(Offset: 0, Value: Expr, Kind: ELF::R_SPARC_5));
172 return 0;
173}
174
175unsigned
176SparcMCCodeEmitter::getSImm13OpValue(const MCInst &MI, unsigned OpNo,
177 SmallVectorImpl<MCFixup> &Fixups,
178 const MCSubtargetInfo &STI) const {
179 const MCOperand &MO = MI.getOperand(i: OpNo);
180
181 if (MO.isImm())
182 return MO.getImm();
183
184 assert(MO.isExpr() &&
185 "getSImm13OpValue expects only expressions or an immediate");
186
187 const MCExpr *Expr = MO.getExpr();
188
189 // Constant value, no fixup is needed
190 if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Val: Expr))
191 return CE->getValue();
192
193 if (auto *SExpr = dyn_cast<MCSpecifierExpr>(Val: Expr)) {
194 Fixups.push_back(Elt: MCFixup::create(Offset: 0, Value: Expr, Kind: SExpr->getSpecifier()));
195 return 0;
196 }
197 Fixups.push_back(Elt: MCFixup::create(Offset: 0, Value: Expr, Kind: Sparc::fixup_sparc_13));
198 return 0;
199}
200
201unsigned SparcMCCodeEmitter::
202getCallTargetOpValue(const MCInst &MI, unsigned OpNo,
203 SmallVectorImpl<MCFixup> &Fixups,
204 const MCSubtargetInfo &STI) const {
205 if (MI.getOpcode() == SP::TLS_CALL) {
206 // No fixups for __tls_get_addr. Will emit for fixups for tls_symbol in
207 // encodeInstruction.
208 return 0;
209 }
210
211 const MCOperand &MO = MI.getOperand(i: OpNo);
212 Fixups.push_back(Elt: MCFixup::create(Offset: 0, Value: MO.getExpr(), Kind: Sparc::fixup_sparc_call30));
213 return 0;
214}
215
216unsigned SparcMCCodeEmitter::
217getBranchTargetOpValue(const MCInst &MI, unsigned OpNo,
218 SmallVectorImpl<MCFixup> &Fixups,
219 const MCSubtargetInfo &STI) const {
220 const MCOperand &MO = MI.getOperand(i: OpNo);
221 if (MO.isReg() || MO.isImm())
222 return getMachineOpValue(MI, MO, Fixups, STI);
223
224 Fixups.push_back(Elt: MCFixup::create(Offset: 0, Value: MO.getExpr(), Kind: ELF::R_SPARC_WDISP22));
225 return 0;
226}
227
228unsigned SparcMCCodeEmitter::getBranchPredTargetOpValue(
229 const MCInst &MI, unsigned OpNo, SmallVectorImpl<MCFixup> &Fixups,
230 const MCSubtargetInfo &STI) const {
231 const MCOperand &MO = MI.getOperand(i: OpNo);
232 if (MO.isReg() || MO.isImm())
233 return getMachineOpValue(MI, MO, Fixups, STI);
234
235 Fixups.push_back(Elt: MCFixup::create(Offset: 0, Value: MO.getExpr(), Kind: ELF::R_SPARC_WDISP19));
236 return 0;
237}
238
239unsigned SparcMCCodeEmitter::getBranchOnRegTargetOpValue(
240 const MCInst &MI, unsigned OpNo, SmallVectorImpl<MCFixup> &Fixups,
241 const MCSubtargetInfo &STI) const {
242 const MCOperand &MO = MI.getOperand(i: OpNo);
243 if (MO.isReg() || MO.isImm())
244 return getMachineOpValue(MI, MO, Fixups, STI);
245
246 Fixups.push_back(Elt: MCFixup::create(Offset: 0, Value: MO.getExpr(), Kind: ELF::R_SPARC_WDISP16));
247
248 return 0;
249}
250
251unsigned SparcMCCodeEmitter::getCompareAndBranchTargetOpValue(
252 const MCInst &MI, unsigned OpNo, SmallVectorImpl<MCFixup> &Fixups,
253 const MCSubtargetInfo &STI) const {
254 const MCOperand &MO = MI.getOperand(i: OpNo);
255 if (MO.isImm())
256 return getMachineOpValue(MI, MO, Fixups, STI);
257
258 Fixups.push_back(Elt: MCFixup::create(Offset: 0, Value: MO.getExpr(), Kind: ELF::R_SPARC_WDISP10));
259
260 return 0;
261}
262
263#include "SparcGenMCCodeEmitter.inc"
264
265MCCodeEmitter *llvm::createSparcMCCodeEmitter(const MCInstrInfo &MCII,
266 MCContext &Ctx) {
267 return new SparcMCCodeEmitter(MCII, Ctx);
268}
269