1*9880d681SAndroid Build Coastguard Worker //===-- SparcMCCodeEmitter.cpp - Convert Sparc code to machine code -------===//
2*9880d681SAndroid Build Coastguard Worker //
3*9880d681SAndroid Build Coastguard Worker // The LLVM Compiler Infrastructure
4*9880d681SAndroid Build Coastguard Worker //
5*9880d681SAndroid Build Coastguard Worker // This file is distributed under the University of Illinois Open Source
6*9880d681SAndroid Build Coastguard Worker // License. See LICENSE.TXT for details.
7*9880d681SAndroid Build Coastguard Worker //
8*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
9*9880d681SAndroid Build Coastguard Worker //
10*9880d681SAndroid Build Coastguard Worker // This file implements the SparcMCCodeEmitter class.
11*9880d681SAndroid Build Coastguard Worker //
12*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
13*9880d681SAndroid Build Coastguard Worker
14*9880d681SAndroid Build Coastguard Worker #include "SparcMCExpr.h"
15*9880d681SAndroid Build Coastguard Worker #include "MCTargetDesc/SparcFixupKinds.h"
16*9880d681SAndroid Build Coastguard Worker #include "SparcMCTargetDesc.h"
17*9880d681SAndroid Build Coastguard Worker #include "llvm/ADT/Statistic.h"
18*9880d681SAndroid Build Coastguard Worker #include "llvm/MC/MCCodeEmitter.h"
19*9880d681SAndroid Build Coastguard Worker #include "llvm/MC/MCContext.h"
20*9880d681SAndroid Build Coastguard Worker #include "llvm/MC/MCExpr.h"
21*9880d681SAndroid Build Coastguard Worker #include "llvm/MC/MCInst.h"
22*9880d681SAndroid Build Coastguard Worker #include "llvm/MC/MCRegisterInfo.h"
23*9880d681SAndroid Build Coastguard Worker #include "llvm/MC/MCSymbol.h"
24*9880d681SAndroid Build Coastguard Worker #include "llvm/MC/MCAsmInfo.h"
25*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/EndianStream.h"
26*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/raw_ostream.h"
27*9880d681SAndroid Build Coastguard Worker
28*9880d681SAndroid Build Coastguard Worker using namespace llvm;
29*9880d681SAndroid Build Coastguard Worker
30*9880d681SAndroid Build Coastguard Worker #define DEBUG_TYPE "mccodeemitter"
31*9880d681SAndroid Build Coastguard Worker
32*9880d681SAndroid Build Coastguard Worker STATISTIC(MCNumEmitted, "Number of MC instructions emitted");
33*9880d681SAndroid Build Coastguard Worker
34*9880d681SAndroid Build Coastguard Worker namespace {
35*9880d681SAndroid Build Coastguard Worker class SparcMCCodeEmitter : public MCCodeEmitter {
36*9880d681SAndroid Build Coastguard Worker SparcMCCodeEmitter(const SparcMCCodeEmitter &) = delete;
37*9880d681SAndroid Build Coastguard Worker void operator=(const SparcMCCodeEmitter &) = delete;
38*9880d681SAndroid Build Coastguard Worker MCContext &Ctx;
39*9880d681SAndroid Build Coastguard Worker
40*9880d681SAndroid Build Coastguard Worker public:
SparcMCCodeEmitter(MCContext & ctx)41*9880d681SAndroid Build Coastguard Worker SparcMCCodeEmitter(MCContext &ctx): Ctx(ctx) {}
42*9880d681SAndroid Build Coastguard Worker
~SparcMCCodeEmitter()43*9880d681SAndroid Build Coastguard Worker ~SparcMCCodeEmitter() override {}
44*9880d681SAndroid Build Coastguard Worker
45*9880d681SAndroid Build Coastguard Worker void encodeInstruction(const MCInst &MI, raw_ostream &OS,
46*9880d681SAndroid Build Coastguard Worker SmallVectorImpl<MCFixup> &Fixups,
47*9880d681SAndroid Build Coastguard Worker const MCSubtargetInfo &STI) const override;
48*9880d681SAndroid Build Coastguard Worker
49*9880d681SAndroid Build Coastguard Worker // getBinaryCodeForInstr - TableGen'erated function for getting the
50*9880d681SAndroid Build Coastguard Worker // binary encoding for an instruction.
51*9880d681SAndroid Build Coastguard Worker uint64_t getBinaryCodeForInstr(const MCInst &MI,
52*9880d681SAndroid Build Coastguard Worker SmallVectorImpl<MCFixup> &Fixups,
53*9880d681SAndroid Build Coastguard Worker const MCSubtargetInfo &STI) const;
54*9880d681SAndroid Build Coastguard Worker
55*9880d681SAndroid Build Coastguard Worker /// getMachineOpValue - Return binary encoding of operand. If the machine
56*9880d681SAndroid Build Coastguard Worker /// operand requires relocation, record the relocation and return zero.
57*9880d681SAndroid Build Coastguard Worker unsigned getMachineOpValue(const MCInst &MI, const MCOperand &MO,
58*9880d681SAndroid Build Coastguard Worker SmallVectorImpl<MCFixup> &Fixups,
59*9880d681SAndroid Build Coastguard Worker const MCSubtargetInfo &STI) const;
60*9880d681SAndroid Build Coastguard Worker
61*9880d681SAndroid Build Coastguard Worker unsigned getCallTargetOpValue(const MCInst &MI, unsigned OpNo,
62*9880d681SAndroid Build Coastguard Worker SmallVectorImpl<MCFixup> &Fixups,
63*9880d681SAndroid Build Coastguard Worker const MCSubtargetInfo &STI) const;
64*9880d681SAndroid Build Coastguard Worker unsigned getBranchTargetOpValue(const MCInst &MI, unsigned OpNo,
65*9880d681SAndroid Build Coastguard Worker SmallVectorImpl<MCFixup> &Fixups,
66*9880d681SAndroid Build Coastguard Worker const MCSubtargetInfo &STI) const;
67*9880d681SAndroid Build Coastguard Worker unsigned getBranchPredTargetOpValue(const MCInst &MI, unsigned OpNo,
68*9880d681SAndroid Build Coastguard Worker SmallVectorImpl<MCFixup> &Fixups,
69*9880d681SAndroid Build Coastguard Worker const MCSubtargetInfo &STI) const;
70*9880d681SAndroid Build Coastguard Worker unsigned getBranchOnRegTargetOpValue(const MCInst &MI, unsigned OpNo,
71*9880d681SAndroid Build Coastguard Worker SmallVectorImpl<MCFixup> &Fixups,
72*9880d681SAndroid Build Coastguard Worker const MCSubtargetInfo &STI) const;
73*9880d681SAndroid Build Coastguard Worker
74*9880d681SAndroid Build Coastguard Worker };
75*9880d681SAndroid Build Coastguard Worker } // end anonymous namespace
76*9880d681SAndroid Build Coastguard Worker
createSparcMCCodeEmitter(const MCInstrInfo & MCII,const MCRegisterInfo & MRI,MCContext & Ctx)77*9880d681SAndroid Build Coastguard Worker MCCodeEmitter *llvm::createSparcMCCodeEmitter(const MCInstrInfo &MCII,
78*9880d681SAndroid Build Coastguard Worker const MCRegisterInfo &MRI,
79*9880d681SAndroid Build Coastguard Worker MCContext &Ctx) {
80*9880d681SAndroid Build Coastguard Worker return new SparcMCCodeEmitter(Ctx);
81*9880d681SAndroid Build Coastguard Worker }
82*9880d681SAndroid Build Coastguard Worker
encodeInstruction(const MCInst & MI,raw_ostream & OS,SmallVectorImpl<MCFixup> & Fixups,const MCSubtargetInfo & STI) const83*9880d681SAndroid Build Coastguard Worker void SparcMCCodeEmitter::encodeInstruction(const MCInst &MI, raw_ostream &OS,
84*9880d681SAndroid Build Coastguard Worker SmallVectorImpl<MCFixup> &Fixups,
85*9880d681SAndroid Build Coastguard Worker const MCSubtargetInfo &STI) const {
86*9880d681SAndroid Build Coastguard Worker unsigned Bits = getBinaryCodeForInstr(MI, Fixups, STI);
87*9880d681SAndroid Build Coastguard Worker
88*9880d681SAndroid Build Coastguard Worker if (Ctx.getAsmInfo()->isLittleEndian()) {
89*9880d681SAndroid Build Coastguard Worker // Output the bits in little-endian byte order.
90*9880d681SAndroid Build Coastguard Worker support::endian::Writer<support::little>(OS).write<uint32_t>(Bits);
91*9880d681SAndroid Build Coastguard Worker } else {
92*9880d681SAndroid Build Coastguard Worker // Output the bits in big-endian byte order.
93*9880d681SAndroid Build Coastguard Worker support::endian::Writer<support::big>(OS).write<uint32_t>(Bits);
94*9880d681SAndroid Build Coastguard Worker }
95*9880d681SAndroid Build Coastguard Worker unsigned tlsOpNo = 0;
96*9880d681SAndroid Build Coastguard Worker switch (MI.getOpcode()) {
97*9880d681SAndroid Build Coastguard Worker default: break;
98*9880d681SAndroid Build Coastguard Worker case SP::TLS_CALL: tlsOpNo = 1; break;
99*9880d681SAndroid Build Coastguard Worker case SP::TLS_ADDrr:
100*9880d681SAndroid Build Coastguard Worker case SP::TLS_ADDXrr:
101*9880d681SAndroid Build Coastguard Worker case SP::TLS_LDrr:
102*9880d681SAndroid Build Coastguard Worker case SP::TLS_LDXrr: tlsOpNo = 3; break;
103*9880d681SAndroid Build Coastguard Worker }
104*9880d681SAndroid Build Coastguard Worker if (tlsOpNo != 0) {
105*9880d681SAndroid Build Coastguard Worker const MCOperand &MO = MI.getOperand(tlsOpNo);
106*9880d681SAndroid Build Coastguard Worker uint64_t op = getMachineOpValue(MI, MO, Fixups, STI);
107*9880d681SAndroid Build Coastguard Worker assert(op == 0 && "Unexpected operand value!");
108*9880d681SAndroid Build Coastguard Worker (void)op; // suppress warning.
109*9880d681SAndroid Build Coastguard Worker }
110*9880d681SAndroid Build Coastguard Worker
111*9880d681SAndroid Build Coastguard Worker ++MCNumEmitted; // Keep track of the # of mi's emitted.
112*9880d681SAndroid Build Coastguard Worker }
113*9880d681SAndroid Build Coastguard Worker
114*9880d681SAndroid Build Coastguard Worker
115*9880d681SAndroid Build Coastguard Worker unsigned SparcMCCodeEmitter::
getMachineOpValue(const MCInst & MI,const MCOperand & MO,SmallVectorImpl<MCFixup> & Fixups,const MCSubtargetInfo & STI) const116*9880d681SAndroid Build Coastguard Worker getMachineOpValue(const MCInst &MI, const MCOperand &MO,
117*9880d681SAndroid Build Coastguard Worker SmallVectorImpl<MCFixup> &Fixups,
118*9880d681SAndroid Build Coastguard Worker const MCSubtargetInfo &STI) const {
119*9880d681SAndroid Build Coastguard Worker
120*9880d681SAndroid Build Coastguard Worker if (MO.isReg())
121*9880d681SAndroid Build Coastguard Worker return Ctx.getRegisterInfo()->getEncodingValue(MO.getReg());
122*9880d681SAndroid Build Coastguard Worker
123*9880d681SAndroid Build Coastguard Worker if (MO.isImm())
124*9880d681SAndroid Build Coastguard Worker return MO.getImm();
125*9880d681SAndroid Build Coastguard Worker
126*9880d681SAndroid Build Coastguard Worker assert(MO.isExpr());
127*9880d681SAndroid Build Coastguard Worker const MCExpr *Expr = MO.getExpr();
128*9880d681SAndroid Build Coastguard Worker if (const SparcMCExpr *SExpr = dyn_cast<SparcMCExpr>(Expr)) {
129*9880d681SAndroid Build Coastguard Worker MCFixupKind Kind = (MCFixupKind)SExpr->getFixupKind();
130*9880d681SAndroid Build Coastguard Worker Fixups.push_back(MCFixup::create(0, Expr, Kind));
131*9880d681SAndroid Build Coastguard Worker return 0;
132*9880d681SAndroid Build Coastguard Worker }
133*9880d681SAndroid Build Coastguard Worker
134*9880d681SAndroid Build Coastguard Worker int64_t Res;
135*9880d681SAndroid Build Coastguard Worker if (Expr->evaluateAsAbsolute(Res))
136*9880d681SAndroid Build Coastguard Worker return Res;
137*9880d681SAndroid Build Coastguard Worker
138*9880d681SAndroid Build Coastguard Worker llvm_unreachable("Unhandled expression!");
139*9880d681SAndroid Build Coastguard Worker return 0;
140*9880d681SAndroid Build Coastguard Worker }
141*9880d681SAndroid Build Coastguard Worker
142*9880d681SAndroid Build Coastguard Worker unsigned SparcMCCodeEmitter::
getCallTargetOpValue(const MCInst & MI,unsigned OpNo,SmallVectorImpl<MCFixup> & Fixups,const MCSubtargetInfo & STI) const143*9880d681SAndroid Build Coastguard Worker getCallTargetOpValue(const MCInst &MI, unsigned OpNo,
144*9880d681SAndroid Build Coastguard Worker SmallVectorImpl<MCFixup> &Fixups,
145*9880d681SAndroid Build Coastguard Worker const MCSubtargetInfo &STI) const {
146*9880d681SAndroid Build Coastguard Worker const MCOperand &MO = MI.getOperand(OpNo);
147*9880d681SAndroid Build Coastguard Worker if (MO.isReg() || MO.isImm())
148*9880d681SAndroid Build Coastguard Worker return getMachineOpValue(MI, MO, Fixups, STI);
149*9880d681SAndroid Build Coastguard Worker
150*9880d681SAndroid Build Coastguard Worker if (MI.getOpcode() == SP::TLS_CALL) {
151*9880d681SAndroid Build Coastguard Worker // No fixups for __tls_get_addr. Will emit for fixups for tls_symbol in
152*9880d681SAndroid Build Coastguard Worker // encodeInstruction.
153*9880d681SAndroid Build Coastguard Worker #ifndef NDEBUG
154*9880d681SAndroid Build Coastguard Worker // Verify that the callee is actually __tls_get_addr.
155*9880d681SAndroid Build Coastguard Worker const SparcMCExpr *SExpr = dyn_cast<SparcMCExpr>(MO.getExpr());
156*9880d681SAndroid Build Coastguard Worker assert(SExpr && SExpr->getSubExpr()->getKind() == MCExpr::SymbolRef &&
157*9880d681SAndroid Build Coastguard Worker "Unexpected expression in TLS_CALL");
158*9880d681SAndroid Build Coastguard Worker const MCSymbolRefExpr *SymExpr = cast<MCSymbolRefExpr>(SExpr->getSubExpr());
159*9880d681SAndroid Build Coastguard Worker assert(SymExpr->getSymbol().getName() == "__tls_get_addr" &&
160*9880d681SAndroid Build Coastguard Worker "Unexpected function for TLS_CALL");
161*9880d681SAndroid Build Coastguard Worker #endif
162*9880d681SAndroid Build Coastguard Worker return 0;
163*9880d681SAndroid Build Coastguard Worker }
164*9880d681SAndroid Build Coastguard Worker
165*9880d681SAndroid Build Coastguard Worker MCFixupKind fixupKind = (MCFixupKind)Sparc::fixup_sparc_call30;
166*9880d681SAndroid Build Coastguard Worker
167*9880d681SAndroid Build Coastguard Worker if (const SparcMCExpr *SExpr = dyn_cast<SparcMCExpr>(MO.getExpr())) {
168*9880d681SAndroid Build Coastguard Worker if (SExpr->getKind() == SparcMCExpr::VK_Sparc_WPLT30)
169*9880d681SAndroid Build Coastguard Worker fixupKind = (MCFixupKind)Sparc::fixup_sparc_wplt30;
170*9880d681SAndroid Build Coastguard Worker }
171*9880d681SAndroid Build Coastguard Worker
172*9880d681SAndroid Build Coastguard Worker Fixups.push_back(MCFixup::create(0, MO.getExpr(), fixupKind));
173*9880d681SAndroid Build Coastguard Worker
174*9880d681SAndroid Build Coastguard Worker return 0;
175*9880d681SAndroid Build Coastguard Worker }
176*9880d681SAndroid Build Coastguard Worker
177*9880d681SAndroid Build Coastguard Worker unsigned SparcMCCodeEmitter::
getBranchTargetOpValue(const MCInst & MI,unsigned OpNo,SmallVectorImpl<MCFixup> & Fixups,const MCSubtargetInfo & STI) const178*9880d681SAndroid Build Coastguard Worker getBranchTargetOpValue(const MCInst &MI, unsigned OpNo,
179*9880d681SAndroid Build Coastguard Worker SmallVectorImpl<MCFixup> &Fixups,
180*9880d681SAndroid Build Coastguard Worker const MCSubtargetInfo &STI) const {
181*9880d681SAndroid Build Coastguard Worker const MCOperand &MO = MI.getOperand(OpNo);
182*9880d681SAndroid Build Coastguard Worker if (MO.isReg() || MO.isImm())
183*9880d681SAndroid Build Coastguard Worker return getMachineOpValue(MI, MO, Fixups, STI);
184*9880d681SAndroid Build Coastguard Worker
185*9880d681SAndroid Build Coastguard Worker Fixups.push_back(MCFixup::create(0, MO.getExpr(),
186*9880d681SAndroid Build Coastguard Worker (MCFixupKind)Sparc::fixup_sparc_br22));
187*9880d681SAndroid Build Coastguard Worker return 0;
188*9880d681SAndroid Build Coastguard Worker }
189*9880d681SAndroid Build Coastguard Worker
190*9880d681SAndroid Build Coastguard Worker unsigned SparcMCCodeEmitter::
getBranchPredTargetOpValue(const MCInst & MI,unsigned OpNo,SmallVectorImpl<MCFixup> & Fixups,const MCSubtargetInfo & STI) const191*9880d681SAndroid Build Coastguard Worker getBranchPredTargetOpValue(const MCInst &MI, unsigned OpNo,
192*9880d681SAndroid Build Coastguard Worker SmallVectorImpl<MCFixup> &Fixups,
193*9880d681SAndroid Build Coastguard Worker const MCSubtargetInfo &STI) const {
194*9880d681SAndroid Build Coastguard Worker const MCOperand &MO = MI.getOperand(OpNo);
195*9880d681SAndroid Build Coastguard Worker if (MO.isReg() || MO.isImm())
196*9880d681SAndroid Build Coastguard Worker return getMachineOpValue(MI, MO, Fixups, STI);
197*9880d681SAndroid Build Coastguard Worker
198*9880d681SAndroid Build Coastguard Worker Fixups.push_back(MCFixup::create(0, MO.getExpr(),
199*9880d681SAndroid Build Coastguard Worker (MCFixupKind)Sparc::fixup_sparc_br19));
200*9880d681SAndroid Build Coastguard Worker return 0;
201*9880d681SAndroid Build Coastguard Worker }
202*9880d681SAndroid Build Coastguard Worker unsigned SparcMCCodeEmitter::
getBranchOnRegTargetOpValue(const MCInst & MI,unsigned OpNo,SmallVectorImpl<MCFixup> & Fixups,const MCSubtargetInfo & STI) const203*9880d681SAndroid Build Coastguard Worker getBranchOnRegTargetOpValue(const MCInst &MI, unsigned OpNo,
204*9880d681SAndroid Build Coastguard Worker SmallVectorImpl<MCFixup> &Fixups,
205*9880d681SAndroid Build Coastguard Worker const MCSubtargetInfo &STI) const {
206*9880d681SAndroid Build Coastguard Worker const MCOperand &MO = MI.getOperand(OpNo);
207*9880d681SAndroid Build Coastguard Worker if (MO.isReg() || MO.isImm())
208*9880d681SAndroid Build Coastguard Worker return getMachineOpValue(MI, MO, Fixups, STI);
209*9880d681SAndroid Build Coastguard Worker
210*9880d681SAndroid Build Coastguard Worker Fixups.push_back(MCFixup::create(0, MO.getExpr(),
211*9880d681SAndroid Build Coastguard Worker (MCFixupKind)Sparc::fixup_sparc_br16_2));
212*9880d681SAndroid Build Coastguard Worker Fixups.push_back(MCFixup::create(0, MO.getExpr(),
213*9880d681SAndroid Build Coastguard Worker (MCFixupKind)Sparc::fixup_sparc_br16_14));
214*9880d681SAndroid Build Coastguard Worker
215*9880d681SAndroid Build Coastguard Worker return 0;
216*9880d681SAndroid Build Coastguard Worker }
217*9880d681SAndroid Build Coastguard Worker
218*9880d681SAndroid Build Coastguard Worker
219*9880d681SAndroid Build Coastguard Worker
220*9880d681SAndroid Build Coastguard Worker #include "SparcGenMCCodeEmitter.inc"
221