]>
Commit | Line | Data |
---|---|---|
1a4d82fc JJ |
1 | //===-- SparcAsmBackend.cpp - Sparc Assembler Backend ---------------------===// |
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 | #include "llvm/MC/MCAsmBackend.h" | |
11 | #include "MCTargetDesc/SparcFixupKinds.h" | |
12 | #include "MCTargetDesc/SparcMCTargetDesc.h" | |
13 | #include "llvm/MC/MCELFObjectWriter.h" | |
14 | #include "llvm/MC/MCExpr.h" | |
15 | #include "llvm/MC/MCFixupKindInfo.h" | |
16 | #include "llvm/MC/MCObjectWriter.h" | |
17 | #include "llvm/MC/MCValue.h" | |
18 | #include "llvm/Support/TargetRegistry.h" | |
19 | ||
20 | using namespace llvm; | |
21 | ||
22 | static unsigned adjustFixupValue(unsigned Kind, uint64_t Value) { | |
23 | switch (Kind) { | |
24 | default: | |
25 | llvm_unreachable("Unknown fixup kind!"); | |
26 | case FK_Data_1: | |
27 | case FK_Data_2: | |
28 | case FK_Data_4: | |
29 | case FK_Data_8: | |
30 | return Value; | |
31 | ||
32 | case Sparc::fixup_sparc_wplt30: | |
33 | case Sparc::fixup_sparc_call30: | |
34 | return (Value >> 2) & 0x3fffffff; | |
35 | ||
36 | case Sparc::fixup_sparc_br22: | |
37 | return (Value >> 2) & 0x3fffff; | |
38 | ||
39 | case Sparc::fixup_sparc_br19: | |
40 | return (Value >> 2) & 0x7ffff; | |
41 | ||
42 | case Sparc::fixup_sparc_br16_2: | |
43 | return (Value >> 2) & 0xc000; | |
44 | ||
45 | case Sparc::fixup_sparc_br16_14: | |
46 | return (Value >> 2) & 0x3fff; | |
47 | ||
48 | case Sparc::fixup_sparc_pc22: | |
49 | case Sparc::fixup_sparc_got22: | |
50 | case Sparc::fixup_sparc_tls_gd_hi22: | |
51 | case Sparc::fixup_sparc_tls_ldm_hi22: | |
52 | case Sparc::fixup_sparc_tls_ie_hi22: | |
53 | case Sparc::fixup_sparc_hi22: | |
54 | return (Value >> 10) & 0x3fffff; | |
55 | ||
56 | case Sparc::fixup_sparc_pc10: | |
57 | case Sparc::fixup_sparc_got10: | |
58 | case Sparc::fixup_sparc_tls_gd_lo10: | |
59 | case Sparc::fixup_sparc_tls_ldm_lo10: | |
60 | case Sparc::fixup_sparc_tls_ie_lo10: | |
61 | case Sparc::fixup_sparc_lo10: | |
62 | return Value & 0x3ff; | |
63 | ||
64 | case Sparc::fixup_sparc_tls_ldo_hix22: | |
65 | case Sparc::fixup_sparc_tls_le_hix22: | |
66 | return (~Value >> 10) & 0x3fffff; | |
67 | ||
68 | case Sparc::fixup_sparc_tls_ldo_lox10: | |
69 | case Sparc::fixup_sparc_tls_le_lox10: | |
70 | return (~(~Value & 0x3ff)) & 0x1fff; | |
71 | ||
72 | case Sparc::fixup_sparc_h44: | |
73 | return (Value >> 22) & 0x3fffff; | |
74 | ||
75 | case Sparc::fixup_sparc_m44: | |
76 | return (Value >> 12) & 0x3ff; | |
77 | ||
78 | case Sparc::fixup_sparc_l44: | |
79 | return Value & 0xfff; | |
80 | ||
81 | case Sparc::fixup_sparc_hh: | |
82 | return (Value >> 42) & 0x3fffff; | |
83 | ||
84 | case Sparc::fixup_sparc_hm: | |
85 | return (Value >> 32) & 0x3ff; | |
86 | ||
87 | case Sparc::fixup_sparc_tls_gd_add: | |
88 | case Sparc::fixup_sparc_tls_gd_call: | |
89 | case Sparc::fixup_sparc_tls_ldm_add: | |
90 | case Sparc::fixup_sparc_tls_ldm_call: | |
91 | case Sparc::fixup_sparc_tls_ldo_add: | |
92 | case Sparc::fixup_sparc_tls_ie_ld: | |
93 | case Sparc::fixup_sparc_tls_ie_ldx: | |
94 | case Sparc::fixup_sparc_tls_ie_add: | |
95 | return 0; | |
96 | } | |
97 | } | |
98 | ||
99 | namespace { | |
100 | class SparcAsmBackend : public MCAsmBackend { | |
101 | const Target &TheTarget; | |
102 | public: | |
103 | SparcAsmBackend(const Target &T) : MCAsmBackend(), TheTarget(T) {} | |
104 | ||
105 | unsigned getNumFixupKinds() const override { | |
106 | return Sparc::NumTargetFixupKinds; | |
107 | } | |
108 | ||
109 | const MCFixupKindInfo &getFixupKindInfo(MCFixupKind Kind) const override { | |
110 | const static MCFixupKindInfo Infos[Sparc::NumTargetFixupKinds] = { | |
111 | // name offset bits flags | |
112 | { "fixup_sparc_call30", 2, 30, MCFixupKindInfo::FKF_IsPCRel }, | |
113 | { "fixup_sparc_br22", 10, 22, MCFixupKindInfo::FKF_IsPCRel }, | |
114 | { "fixup_sparc_br19", 13, 19, MCFixupKindInfo::FKF_IsPCRel }, | |
115 | { "fixup_sparc_br16_2", 10, 2, MCFixupKindInfo::FKF_IsPCRel }, | |
116 | { "fixup_sparc_br16_14", 18, 14, MCFixupKindInfo::FKF_IsPCRel }, | |
117 | { "fixup_sparc_hi22", 10, 22, 0 }, | |
118 | { "fixup_sparc_lo10", 22, 10, 0 }, | |
119 | { "fixup_sparc_h44", 10, 22, 0 }, | |
120 | { "fixup_sparc_m44", 22, 10, 0 }, | |
121 | { "fixup_sparc_l44", 20, 12, 0 }, | |
122 | { "fixup_sparc_hh", 10, 22, 0 }, | |
123 | { "fixup_sparc_hm", 22, 10, 0 }, | |
124 | { "fixup_sparc_pc22", 10, 22, MCFixupKindInfo::FKF_IsPCRel }, | |
125 | { "fixup_sparc_pc10", 22, 10, MCFixupKindInfo::FKF_IsPCRel }, | |
126 | { "fixup_sparc_got22", 10, 22, 0 }, | |
127 | { "fixup_sparc_got10", 22, 10, 0 }, | |
128 | { "fixup_sparc_wplt30", 2, 30, MCFixupKindInfo::FKF_IsPCRel }, | |
129 | { "fixup_sparc_tls_gd_hi22", 10, 22, 0 }, | |
130 | { "fixup_sparc_tls_gd_lo10", 22, 10, 0 }, | |
131 | { "fixup_sparc_tls_gd_add", 0, 0, 0 }, | |
132 | { "fixup_sparc_tls_gd_call", 0, 0, 0 }, | |
133 | { "fixup_sparc_tls_ldm_hi22", 10, 22, 0 }, | |
134 | { "fixup_sparc_tls_ldm_lo10", 22, 10, 0 }, | |
135 | { "fixup_sparc_tls_ldm_add", 0, 0, 0 }, | |
136 | { "fixup_sparc_tls_ldm_call", 0, 0, 0 }, | |
137 | { "fixup_sparc_tls_ldo_hix22", 10, 22, 0 }, | |
138 | { "fixup_sparc_tls_ldo_lox10", 22, 10, 0 }, | |
139 | { "fixup_sparc_tls_ldo_add", 0, 0, 0 }, | |
140 | { "fixup_sparc_tls_ie_hi22", 10, 22, 0 }, | |
141 | { "fixup_sparc_tls_ie_lo10", 22, 10, 0 }, | |
142 | { "fixup_sparc_tls_ie_ld", 0, 0, 0 }, | |
143 | { "fixup_sparc_tls_ie_ldx", 0, 0, 0 }, | |
144 | { "fixup_sparc_tls_ie_add", 0, 0, 0 }, | |
145 | { "fixup_sparc_tls_le_hix22", 0, 0, 0 }, | |
146 | { "fixup_sparc_tls_le_lox10", 0, 0, 0 } | |
147 | }; | |
148 | ||
149 | if (Kind < FirstTargetFixupKind) | |
150 | return MCAsmBackend::getFixupKindInfo(Kind); | |
151 | ||
152 | assert(unsigned(Kind - FirstTargetFixupKind) < getNumFixupKinds() && | |
153 | "Invalid kind!"); | |
154 | return Infos[Kind - FirstTargetFixupKind]; | |
155 | } | |
156 | ||
157 | void processFixupValue(const MCAssembler &Asm, const MCAsmLayout &Layout, | |
158 | const MCFixup &Fixup, const MCFragment *DF, | |
159 | const MCValue &Target, uint64_t &Value, | |
160 | bool &IsResolved) override { | |
161 | switch ((Sparc::Fixups)Fixup.getKind()) { | |
162 | default: break; | |
163 | case Sparc::fixup_sparc_wplt30: | |
164 | if (Target.getSymA()->getSymbol().isTemporary()) | |
165 | return; | |
166 | case Sparc::fixup_sparc_tls_gd_hi22: | |
167 | case Sparc::fixup_sparc_tls_gd_lo10: | |
168 | case Sparc::fixup_sparc_tls_gd_add: | |
169 | case Sparc::fixup_sparc_tls_gd_call: | |
170 | case Sparc::fixup_sparc_tls_ldm_hi22: | |
171 | case Sparc::fixup_sparc_tls_ldm_lo10: | |
172 | case Sparc::fixup_sparc_tls_ldm_add: | |
173 | case Sparc::fixup_sparc_tls_ldm_call: | |
174 | case Sparc::fixup_sparc_tls_ldo_hix22: | |
175 | case Sparc::fixup_sparc_tls_ldo_lox10: | |
176 | case Sparc::fixup_sparc_tls_ldo_add: | |
177 | case Sparc::fixup_sparc_tls_ie_hi22: | |
178 | case Sparc::fixup_sparc_tls_ie_lo10: | |
179 | case Sparc::fixup_sparc_tls_ie_ld: | |
180 | case Sparc::fixup_sparc_tls_ie_ldx: | |
181 | case Sparc::fixup_sparc_tls_ie_add: | |
182 | case Sparc::fixup_sparc_tls_le_hix22: | |
183 | case Sparc::fixup_sparc_tls_le_lox10: IsResolved = false; break; | |
184 | } | |
185 | } | |
186 | ||
187 | bool mayNeedRelaxation(const MCInst &Inst) const override { | |
188 | // FIXME. | |
189 | return false; | |
190 | } | |
191 | ||
192 | /// fixupNeedsRelaxation - Target specific predicate for whether a given | |
193 | /// fixup requires the associated instruction to be relaxed. | |
194 | bool fixupNeedsRelaxation(const MCFixup &Fixup, | |
195 | uint64_t Value, | |
196 | const MCRelaxableFragment *DF, | |
197 | const MCAsmLayout &Layout) const override { | |
198 | // FIXME. | |
199 | llvm_unreachable("fixupNeedsRelaxation() unimplemented"); | |
200 | return false; | |
201 | } | |
202 | void relaxInstruction(const MCInst &Inst, MCInst &Res) const override { | |
203 | // FIXME. | |
204 | llvm_unreachable("relaxInstruction() unimplemented"); | |
205 | } | |
206 | ||
207 | bool writeNopData(uint64_t Count, MCObjectWriter *OW) const override { | |
208 | // Cannot emit NOP with size not multiple of 32 bits. | |
209 | if (Count % 4 != 0) | |
210 | return false; | |
211 | ||
212 | uint64_t NumNops = Count / 4; | |
213 | for (uint64_t i = 0; i != NumNops; ++i) | |
214 | OW->Write32(0x01000000); | |
215 | ||
216 | return true; | |
217 | } | |
218 | ||
219 | bool is64Bit() const { | |
220 | StringRef name = TheTarget.getName(); | |
221 | return name == "sparcv9"; | |
222 | } | |
223 | }; | |
224 | ||
225 | class ELFSparcAsmBackend : public SparcAsmBackend { | |
226 | Triple::OSType OSType; | |
227 | public: | |
228 | ELFSparcAsmBackend(const Target &T, Triple::OSType OSType) : | |
229 | SparcAsmBackend(T), OSType(OSType) { } | |
230 | ||
231 | void applyFixup(const MCFixup &Fixup, char *Data, unsigned DataSize, | |
232 | uint64_t Value, bool IsPCRel) const override { | |
233 | ||
234 | Value = adjustFixupValue(Fixup.getKind(), Value); | |
235 | if (!Value) return; // Doesn't change encoding. | |
236 | ||
237 | unsigned Offset = Fixup.getOffset(); | |
238 | ||
239 | // For each byte of the fragment that the fixup touches, mask in the bits | |
240 | // from the fixup value. The Value has been "split up" into the | |
241 | // appropriate bitfields above. | |
242 | for (unsigned i = 0; i != 4; ++i) | |
243 | Data[Offset + i] |= uint8_t((Value >> ((4 - i - 1)*8)) & 0xff); | |
244 | ||
245 | } | |
246 | ||
247 | MCObjectWriter *createObjectWriter(raw_ostream &OS) const override { | |
248 | uint8_t OSABI = MCELFObjectTargetWriter::getOSABI(OSType); | |
249 | return createSparcELFObjectWriter(OS, is64Bit(), OSABI); | |
250 | } | |
251 | }; | |
252 | ||
253 | } // end anonymous namespace | |
254 | ||
255 | ||
256 | MCAsmBackend *llvm::createSparcAsmBackend(const Target &T, | |
257 | const MCRegisterInfo &MRI, | |
258 | StringRef TT, | |
259 | StringRef CPU) { | |
260 | return new ELFSparcAsmBackend(T, Triple(TT).getOS()); | |
261 | } |