1
//===-- SparcMCCodeEmitter.cpp - Convert Sparc code to machine code -------===//
3
// The LLVM Compiler Infrastructure
5
// This file is distributed under the University of Illinois Open Source
6
// License. See LICENSE.TXT for details.
8
//===----------------------------------------------------------------------===//
10
// This file implements the SparcMCCodeEmitter class.
12
//===----------------------------------------------------------------------===//
14
#include "SparcMCExpr.h"
15
#include "MCTargetDesc/SparcFixupKinds.h"
16
#include "SparcMCTargetDesc.h"
17
#include "llvm/ADT/Statistic.h"
18
#include "llvm/MC/MCCodeEmitter.h"
19
#include "llvm/MC/MCContext.h"
20
#include "llvm/MC/MCExpr.h"
21
#include "llvm/MC/MCInst.h"
22
#include "llvm/MC/MCRegisterInfo.h"
23
#include "llvm/MC/MCSymbol.h"
24
#include "llvm/MC/MCAsmInfo.h"
25
#include "llvm/Support/raw_ostream.h"
29
#define DEBUG_TYPE "mccodeemitter"
31
STATISTIC(MCNumEmitted, "Number of MC instructions emitted");
34
class SparcMCCodeEmitter : public MCCodeEmitter {
35
SparcMCCodeEmitter(const SparcMCCodeEmitter &) = delete;
36
void operator=(const SparcMCCodeEmitter &) = delete;
40
SparcMCCodeEmitter(MCContext &ctx): Ctx(ctx) {}
42
~SparcMCCodeEmitter() override {}
44
void encodeInstruction(const MCInst &MI, raw_ostream &OS,
45
SmallVectorImpl<MCFixup> &Fixups,
46
const MCSubtargetInfo &STI) const override;
48
// getBinaryCodeForInstr - TableGen'erated function for getting the
49
// binary encoding for an instruction.
50
uint64_t getBinaryCodeForInstr(const MCInst &MI,
51
SmallVectorImpl<MCFixup> &Fixups,
52
const MCSubtargetInfo &STI) const;
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 &MI, const MCOperand &MO,
57
SmallVectorImpl<MCFixup> &Fixups,
58
const MCSubtargetInfo &STI) const;
60
unsigned getCallTargetOpValue(const MCInst &MI, unsigned OpNo,
61
SmallVectorImpl<MCFixup> &Fixups,
62
const MCSubtargetInfo &STI) const;
63
unsigned getBranchTargetOpValue(const MCInst &MI, unsigned OpNo,
64
SmallVectorImpl<MCFixup> &Fixups,
65
const MCSubtargetInfo &STI) const;
66
unsigned getBranchPredTargetOpValue(const MCInst &MI, unsigned OpNo,
67
SmallVectorImpl<MCFixup> &Fixups,
68
const MCSubtargetInfo &STI) const;
69
unsigned getBranchOnRegTargetOpValue(const MCInst &MI, unsigned OpNo,
70
SmallVectorImpl<MCFixup> &Fixups,
71
const MCSubtargetInfo &STI) const;
74
} // end anonymous namespace
76
MCCodeEmitter *llvm::createSparcMCCodeEmitter(const MCInstrInfo &MCII,
77
const MCRegisterInfo &MRI,
79
return new SparcMCCodeEmitter(Ctx);
82
void SparcMCCodeEmitter::encodeInstruction(const MCInst &MI, raw_ostream &OS,
83
SmallVectorImpl<MCFixup> &Fixups,
84
const MCSubtargetInfo &STI) const {
85
unsigned Bits = getBinaryCodeForInstr(MI, Fixups, STI);
87
if (Ctx.getAsmInfo()->isLittleEndian()) {
88
// Output the bits in little-endian byte order.
89
support::endian::Writer<support::little>(OS).write<uint32_t>(Bits);
91
// Output the bits in big-endian byte order.
92
support::endian::Writer<support::big>(OS).write<uint32_t>(Bits);
95
switch (MI.getOpcode()) {
97
case SP::TLS_CALL: tlsOpNo = 1; break;
101
case SP::TLS_LDXrr: tlsOpNo = 3; break;
104
const MCOperand &MO = MI.getOperand(tlsOpNo);
105
uint64_t op = getMachineOpValue(MI, MO, Fixups, STI);
106
assert(op == 0 && "Unexpected operand value!");
107
(void)op; // suppress warning.
110
++MCNumEmitted; // Keep track of the # of mi's emitted.
114
unsigned SparcMCCodeEmitter::
115
getMachineOpValue(const MCInst &MI, const MCOperand &MO,
116
SmallVectorImpl<MCFixup> &Fixups,
117
const MCSubtargetInfo &STI) const {
120
return Ctx.getRegisterInfo()->getEncodingValue(MO.getReg());
126
const MCExpr *Expr = MO.getExpr();
127
if (const SparcMCExpr *SExpr = dyn_cast<SparcMCExpr>(Expr)) {
128
MCFixupKind Kind = (MCFixupKind)SExpr->getFixupKind();
129
Fixups.push_back(MCFixup::create(0, Expr, Kind));
134
if (Expr->evaluateAsAbsolute(Res))
137
llvm_unreachable("Unhandled expression!");
141
unsigned SparcMCCodeEmitter::
142
getCallTargetOpValue(const MCInst &MI, unsigned OpNo,
143
SmallVectorImpl<MCFixup> &Fixups,
144
const MCSubtargetInfo &STI) const {
145
const MCOperand &MO = MI.getOperand(OpNo);
146
if (MO.isReg() || MO.isImm())
147
return getMachineOpValue(MI, MO, Fixups, STI);
149
if (MI.getOpcode() == SP::TLS_CALL) {
150
// No fixups for __tls_get_addr. Will emit for fixups for tls_symbol in
151
// encodeInstruction.
153
// Verify that the callee is actually __tls_get_addr.
154
const SparcMCExpr *SExpr = dyn_cast<SparcMCExpr>(MO.getExpr());
155
assert(SExpr && SExpr->getSubExpr()->getKind() == MCExpr::SymbolRef &&
156
"Unexpected expression in TLS_CALL");
157
const MCSymbolRefExpr *SymExpr = cast<MCSymbolRefExpr>(SExpr->getSubExpr());
158
assert(SymExpr->getSymbol().getName() == "__tls_get_addr" &&
159
"Unexpected function for TLS_CALL");
164
MCFixupKind fixupKind = (MCFixupKind)Sparc::fixup_sparc_call30;
166
if (const SparcMCExpr *SExpr = dyn_cast<SparcMCExpr>(MO.getExpr())) {
167
if (SExpr->getKind() == SparcMCExpr::VK_Sparc_WPLT30)
168
fixupKind = (MCFixupKind)Sparc::fixup_sparc_wplt30;
171
Fixups.push_back(MCFixup::create(0, MO.getExpr(), fixupKind));
176
unsigned SparcMCCodeEmitter::
177
getBranchTargetOpValue(const MCInst &MI, unsigned OpNo,
178
SmallVectorImpl<MCFixup> &Fixups,
179
const MCSubtargetInfo &STI) const {
180
const MCOperand &MO = MI.getOperand(OpNo);
181
if (MO.isReg() || MO.isImm())
182
return getMachineOpValue(MI, MO, Fixups, STI);
184
Fixups.push_back(MCFixup::create(0, MO.getExpr(),
185
(MCFixupKind)Sparc::fixup_sparc_br22));
189
unsigned SparcMCCodeEmitter::
190
getBranchPredTargetOpValue(const MCInst &MI, unsigned OpNo,
191
SmallVectorImpl<MCFixup> &Fixups,
192
const MCSubtargetInfo &STI) const {
193
const MCOperand &MO = MI.getOperand(OpNo);
194
if (MO.isReg() || MO.isImm())
195
return getMachineOpValue(MI, MO, Fixups, STI);
197
Fixups.push_back(MCFixup::create(0, MO.getExpr(),
198
(MCFixupKind)Sparc::fixup_sparc_br19));
201
unsigned SparcMCCodeEmitter::
202
getBranchOnRegTargetOpValue(const MCInst &MI, unsigned OpNo,
203
SmallVectorImpl<MCFixup> &Fixups,
204
const MCSubtargetInfo &STI) const {
205
const MCOperand &MO = MI.getOperand(OpNo);
206
if (MO.isReg() || MO.isImm())
207
return getMachineOpValue(MI, MO, Fixups, STI);
209
Fixups.push_back(MCFixup::create(0, MO.getExpr(),
210
(MCFixupKind)Sparc::fixup_sparc_br16_2));
211
Fixups.push_back(MCFixup::create(0, MO.getExpr(),
212
(MCFixupKind)Sparc::fixup_sparc_br16_14));
219
#include "SparcGenMCCodeEmitter.inc"