1 //===-- SparcMCCodeEmitter.cpp - Convert Sparc 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 SparcMCCodeEmitter class.
11 //===----------------------------------------------------------------------===//
13 #include "MCTargetDesc/SparcFixupKinds.h"
14 #include "SparcMCExpr.h"
15 #include "SparcMCTargetDesc.h"
16 #include "llvm/ADT/SmallVector.h"
17 #include "llvm/ADT/Statistic.h"
18 #include "llvm/MC/MCAsmInfo.h"
19 #include "llvm/MC/MCCodeEmitter.h"
20 #include "llvm/MC/MCContext.h"
21 #include "llvm/MC/MCExpr.h"
22 #include "llvm/MC/MCFixup.h"
23 #include "llvm/MC/MCInst.h"
24 #include "llvm/MC/MCInstrInfo.h"
25 #include "llvm/MC/MCRegisterInfo.h"
26 #include "llvm/MC/MCSubtargetInfo.h"
27 #include "llvm/MC/MCSymbol.h"
28 #include "llvm/MC/SubtargetFeature.h"
29 #include "llvm/Support/Casting.h"
30 #include "llvm/Support/Endian.h"
31 #include "llvm/Support/EndianStream.h"
32 #include "llvm/Support/ErrorHandling.h"
33 #include "llvm/Support/raw_ostream.h"
39 #define DEBUG_TYPE "mccodeemitter"
41 STATISTIC(MCNumEmitted
, "Number of MC instructions emitted");
45 class SparcMCCodeEmitter
: public MCCodeEmitter
{
46 const MCInstrInfo
&MCII
;
50 SparcMCCodeEmitter(const MCInstrInfo
&mcii
, MCContext
&ctx
)
51 : MCII(mcii
), Ctx(ctx
) {}
52 SparcMCCodeEmitter(const SparcMCCodeEmitter
&) = delete;
53 SparcMCCodeEmitter
&operator=(const SparcMCCodeEmitter
&) = delete;
54 ~SparcMCCodeEmitter() override
= default;
56 void encodeInstruction(const MCInst
&MI
, raw_ostream
&OS
,
57 SmallVectorImpl
<MCFixup
> &Fixups
,
58 const MCSubtargetInfo
&STI
) const override
;
60 // getBinaryCodeForInstr - TableGen'erated function for getting the
61 // binary encoding for an instruction.
62 uint64_t getBinaryCodeForInstr(const MCInst
&MI
,
63 SmallVectorImpl
<MCFixup
> &Fixups
,
64 const MCSubtargetInfo
&STI
) const;
66 /// getMachineOpValue - Return binary encoding of operand. If the machine
67 /// operand requires relocation, record the relocation and return zero.
68 unsigned getMachineOpValue(const MCInst
&MI
, const MCOperand
&MO
,
69 SmallVectorImpl
<MCFixup
> &Fixups
,
70 const MCSubtargetInfo
&STI
) const;
72 unsigned getCallTargetOpValue(const MCInst
&MI
, unsigned OpNo
,
73 SmallVectorImpl
<MCFixup
> &Fixups
,
74 const MCSubtargetInfo
&STI
) const;
75 unsigned getBranchTargetOpValue(const MCInst
&MI
, unsigned OpNo
,
76 SmallVectorImpl
<MCFixup
> &Fixups
,
77 const MCSubtargetInfo
&STI
) const;
78 unsigned getBranchPredTargetOpValue(const MCInst
&MI
, unsigned OpNo
,
79 SmallVectorImpl
<MCFixup
> &Fixups
,
80 const MCSubtargetInfo
&STI
) const;
81 unsigned getBranchOnRegTargetOpValue(const MCInst
&MI
, unsigned OpNo
,
82 SmallVectorImpl
<MCFixup
> &Fixups
,
83 const MCSubtargetInfo
&STI
) const;
86 FeatureBitset
computeAvailableFeatures(const FeatureBitset
&FB
) const;
88 verifyInstructionPredicates(const MCInst
&MI
,
89 const FeatureBitset
&AvailableFeatures
) const;
92 } // end anonymous namespace
94 void SparcMCCodeEmitter::encodeInstruction(const MCInst
&MI
, raw_ostream
&OS
,
95 SmallVectorImpl
<MCFixup
> &Fixups
,
96 const MCSubtargetInfo
&STI
) const {
97 verifyInstructionPredicates(MI
,
98 computeAvailableFeatures(STI
.getFeatureBits()));
100 unsigned Bits
= getBinaryCodeForInstr(MI
, Fixups
, STI
);
101 support::endian::write(OS
, Bits
,
102 Ctx
.getAsmInfo()->isLittleEndian() ? support::little
104 unsigned tlsOpNo
= 0;
105 switch (MI
.getOpcode()) {
107 case SP::TLS_CALL
: tlsOpNo
= 1; break;
111 case SP::TLS_LDXrr
: tlsOpNo
= 3; break;
114 const MCOperand
&MO
= MI
.getOperand(tlsOpNo
);
115 uint64_t op
= getMachineOpValue(MI
, MO
, Fixups
, STI
);
116 assert(op
== 0 && "Unexpected operand value!");
117 (void)op
; // suppress warning.
120 ++MCNumEmitted
; // Keep track of the # of mi's emitted.
123 unsigned SparcMCCodeEmitter::
124 getMachineOpValue(const MCInst
&MI
, const MCOperand
&MO
,
125 SmallVectorImpl
<MCFixup
> &Fixups
,
126 const MCSubtargetInfo
&STI
) const {
128 return Ctx
.getRegisterInfo()->getEncodingValue(MO
.getReg());
134 const MCExpr
*Expr
= MO
.getExpr();
135 if (const SparcMCExpr
*SExpr
= dyn_cast
<SparcMCExpr
>(Expr
)) {
136 MCFixupKind Kind
= (MCFixupKind
)SExpr
->getFixupKind();
137 Fixups
.push_back(MCFixup::create(0, Expr
, Kind
));
142 if (Expr
->evaluateAsAbsolute(Res
))
145 llvm_unreachable("Unhandled expression!");
149 unsigned SparcMCCodeEmitter::
150 getCallTargetOpValue(const MCInst
&MI
, unsigned OpNo
,
151 SmallVectorImpl
<MCFixup
> &Fixups
,
152 const MCSubtargetInfo
&STI
) const {
153 const MCOperand
&MO
= MI
.getOperand(OpNo
);
154 if (MO
.isReg() || MO
.isImm())
155 return getMachineOpValue(MI
, MO
, Fixups
, STI
);
157 if (MI
.getOpcode() == SP::TLS_CALL
) {
158 // No fixups for __tls_get_addr. Will emit for fixups for tls_symbol in
159 // encodeInstruction.
161 // Verify that the callee is actually __tls_get_addr.
162 const SparcMCExpr
*SExpr
= dyn_cast
<SparcMCExpr
>(MO
.getExpr());
163 assert(SExpr
&& SExpr
->getSubExpr()->getKind() == MCExpr::SymbolRef
&&
164 "Unexpected expression in TLS_CALL");
165 const MCSymbolRefExpr
*SymExpr
= cast
<MCSymbolRefExpr
>(SExpr
->getSubExpr());
166 assert(SymExpr
->getSymbol().getName() == "__tls_get_addr" &&
167 "Unexpected function for TLS_CALL");
172 MCFixupKind fixupKind
= (MCFixupKind
)Sparc::fixup_sparc_call30
;
174 if (const SparcMCExpr
*SExpr
= dyn_cast
<SparcMCExpr
>(MO
.getExpr())) {
175 if (SExpr
->getKind() == SparcMCExpr::VK_Sparc_WPLT30
)
176 fixupKind
= (MCFixupKind
)Sparc::fixup_sparc_wplt30
;
179 Fixups
.push_back(MCFixup::create(0, MO
.getExpr(), fixupKind
));
184 unsigned SparcMCCodeEmitter::
185 getBranchTargetOpValue(const MCInst
&MI
, unsigned OpNo
,
186 SmallVectorImpl
<MCFixup
> &Fixups
,
187 const MCSubtargetInfo
&STI
) const {
188 const MCOperand
&MO
= MI
.getOperand(OpNo
);
189 if (MO
.isReg() || MO
.isImm())
190 return getMachineOpValue(MI
, MO
, Fixups
, STI
);
192 Fixups
.push_back(MCFixup::create(0, MO
.getExpr(),
193 (MCFixupKind
)Sparc::fixup_sparc_br22
));
197 unsigned SparcMCCodeEmitter::
198 getBranchPredTargetOpValue(const MCInst
&MI
, unsigned OpNo
,
199 SmallVectorImpl
<MCFixup
> &Fixups
,
200 const MCSubtargetInfo
&STI
) const {
201 const MCOperand
&MO
= MI
.getOperand(OpNo
);
202 if (MO
.isReg() || MO
.isImm())
203 return getMachineOpValue(MI
, MO
, Fixups
, STI
);
205 Fixups
.push_back(MCFixup::create(0, MO
.getExpr(),
206 (MCFixupKind
)Sparc::fixup_sparc_br19
));
210 unsigned SparcMCCodeEmitter::
211 getBranchOnRegTargetOpValue(const MCInst
&MI
, unsigned OpNo
,
212 SmallVectorImpl
<MCFixup
> &Fixups
,
213 const MCSubtargetInfo
&STI
) const {
214 const MCOperand
&MO
= MI
.getOperand(OpNo
);
215 if (MO
.isReg() || MO
.isImm())
216 return getMachineOpValue(MI
, MO
, Fixups
, STI
);
218 Fixups
.push_back(MCFixup::create(0, MO
.getExpr(),
219 (MCFixupKind
)Sparc::fixup_sparc_br16_2
));
220 Fixups
.push_back(MCFixup::create(0, MO
.getExpr(),
221 (MCFixupKind
)Sparc::fixup_sparc_br16_14
));
226 #define ENABLE_INSTR_PREDICATE_VERIFIER
227 #include "SparcGenMCCodeEmitter.inc"
229 MCCodeEmitter
*llvm::createSparcMCCodeEmitter(const MCInstrInfo
&MCII
,
230 const MCRegisterInfo
&MRI
,
232 return new SparcMCCodeEmitter(MCII
, Ctx
);