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