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