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 | |
36 | using namespace llvm; |
37 | |
38 | #define DEBUG_TYPE "mccodeemitter" |
39 | |
40 | STATISTIC(MCNumEmitted, "Number of MC instructions emitted" ); |
41 | |
42 | namespace { |
43 | |
44 | class SparcMCCodeEmitter : public MCCodeEmitter { |
45 | MCContext &Ctx; |
46 | |
47 | public: |
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 | |
94 | void 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 | |
125 | unsigned SparcMCCodeEmitter:: |
126 | getMachineOpValue(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 | |
150 | unsigned 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 | |
175 | unsigned |
176 | SparcMCCodeEmitter::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 | |
201 | unsigned SparcMCCodeEmitter:: |
202 | getCallTargetOpValue(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 | |
216 | unsigned SparcMCCodeEmitter:: |
217 | getBranchTargetOpValue(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 | |
228 | unsigned 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 | |
239 | unsigned 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 | |
251 | unsigned 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 | |
265 | MCCodeEmitter *llvm::createSparcMCCodeEmitter(const MCInstrInfo &MCII, |
266 | MCContext &Ctx) { |
267 | return new SparcMCCodeEmitter(MCII, Ctx); |
268 | } |
269 | |