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
20using namespace llvm;
21
22static 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
99namespace {
100  class SparcAsmBackend : public MCAsmBackend {
101  protected:
102    const Target &TheTarget;
103    bool IsLittleEndian;
104    bool Is64Bit;
105
106  public:
107    SparcAsmBackend(const Target &T)
108        : MCAsmBackend(), TheTarget(T),
109          IsLittleEndian(StringRef(TheTarget.getName()) == "sparcel"),
110          Is64Bit(StringRef(TheTarget.getName()) == "sparcv9") {}
111
112    unsigned getNumFixupKinds() const override {
113      return Sparc::NumTargetFixupKinds;
114    }
115
116    const MCFixupKindInfo &getFixupKindInfo(MCFixupKind Kind) const override {
117      const static MCFixupKindInfo InfosBE[Sparc::NumTargetFixupKinds] = {
118        // name                    offset bits  flags
119        { "fixup_sparc_call30",     2,     30,  MCFixupKindInfo::FKF_IsPCRel },
120        { "fixup_sparc_br22",      10,     22,  MCFixupKindInfo::FKF_IsPCRel },
121        { "fixup_sparc_br19",      13,     19,  MCFixupKindInfo::FKF_IsPCRel },
122        { "fixup_sparc_br16_2",    10,      2,  MCFixupKindInfo::FKF_IsPCRel },
123        { "fixup_sparc_br16_14",   18,     14,  MCFixupKindInfo::FKF_IsPCRel },
124        { "fixup_sparc_hi22",      10,     22,  0 },
125        { "fixup_sparc_lo10",      22,     10,  0 },
126        { "fixup_sparc_h44",       10,     22,  0 },
127        { "fixup_sparc_m44",       22,     10,  0 },
128        { "fixup_sparc_l44",       20,     12,  0 },
129        { "fixup_sparc_hh",        10,     22,  0 },
130        { "fixup_sparc_hm",        22,     10,  0 },
131        { "fixup_sparc_pc22",      10,     22,  MCFixupKindInfo::FKF_IsPCRel },
132        { "fixup_sparc_pc10",      22,     10,  MCFixupKindInfo::FKF_IsPCRel },
133        { "fixup_sparc_got22",     10,     22,  0 },
134        { "fixup_sparc_got10",     22,     10,  0 },
135        { "fixup_sparc_wplt30",     2,     30,  MCFixupKindInfo::FKF_IsPCRel },
136        { "fixup_sparc_tls_gd_hi22",   10, 22,  0 },
137        { "fixup_sparc_tls_gd_lo10",   22, 10,  0 },
138        { "fixup_sparc_tls_gd_add",     0,  0,  0 },
139        { "fixup_sparc_tls_gd_call",    0,  0,  0 },
140        { "fixup_sparc_tls_ldm_hi22",  10, 22,  0 },
141        { "fixup_sparc_tls_ldm_lo10",  22, 10,  0 },
142        { "fixup_sparc_tls_ldm_add",    0,  0,  0 },
143        { "fixup_sparc_tls_ldm_call",   0,  0,  0 },
144        { "fixup_sparc_tls_ldo_hix22", 10, 22,  0 },
145        { "fixup_sparc_tls_ldo_lox10", 22, 10,  0 },
146        { "fixup_sparc_tls_ldo_add",    0,  0,  0 },
147        { "fixup_sparc_tls_ie_hi22",   10, 22,  0 },
148        { "fixup_sparc_tls_ie_lo10",   22, 10,  0 },
149        { "fixup_sparc_tls_ie_ld",      0,  0,  0 },
150        { "fixup_sparc_tls_ie_ldx",     0,  0,  0 },
151        { "fixup_sparc_tls_ie_add",     0,  0,  0 },
152        { "fixup_sparc_tls_le_hix22",   0,  0,  0 },
153        { "fixup_sparc_tls_le_lox10",   0,  0,  0 }
154      };
155
156      const static MCFixupKindInfo InfosLE[Sparc::NumTargetFixupKinds] = {
157        // name                    offset bits  flags
158        { "fixup_sparc_call30",     0,     30,  MCFixupKindInfo::FKF_IsPCRel },
159        { "fixup_sparc_br22",       0,     22,  MCFixupKindInfo::FKF_IsPCRel },
160        { "fixup_sparc_br19",       0,     19,  MCFixupKindInfo::FKF_IsPCRel },
161        { "fixup_sparc_br16_2",    20,      2,  MCFixupKindInfo::FKF_IsPCRel },
162        { "fixup_sparc_br16_14",    0,     14,  MCFixupKindInfo::FKF_IsPCRel },
163        { "fixup_sparc_hi22",       0,     22,  0 },
164        { "fixup_sparc_lo10",       0,     10,  0 },
165        { "fixup_sparc_h44",        0,     22,  0 },
166        { "fixup_sparc_m44",        0,     10,  0 },
167        { "fixup_sparc_l44",        0,     12,  0 },
168        { "fixup_sparc_hh",         0,     22,  0 },
169        { "fixup_sparc_hm",         0,     10,  0 },
170        { "fixup_sparc_pc22",       0,     22,  MCFixupKindInfo::FKF_IsPCRel },
171        { "fixup_sparc_pc10",       0,     10,  MCFixupKindInfo::FKF_IsPCRel },
172        { "fixup_sparc_got22",      0,     22,  0 },
173        { "fixup_sparc_got10",      0,     10,  0 },
174        { "fixup_sparc_wplt30",      0,     30,  MCFixupKindInfo::FKF_IsPCRel },
175        { "fixup_sparc_tls_gd_hi22",    0, 22,  0 },
176        { "fixup_sparc_tls_gd_lo10",    0, 10,  0 },
177        { "fixup_sparc_tls_gd_add",     0,  0,  0 },
178        { "fixup_sparc_tls_gd_call",    0,  0,  0 },
179        { "fixup_sparc_tls_ldm_hi22",   0, 22,  0 },
180        { "fixup_sparc_tls_ldm_lo10",   0, 10,  0 },
181        { "fixup_sparc_tls_ldm_add",    0,  0,  0 },
182        { "fixup_sparc_tls_ldm_call",   0,  0,  0 },
183        { "fixup_sparc_tls_ldo_hix22",  0, 22,  0 },
184        { "fixup_sparc_tls_ldo_lox10",  0, 10,  0 },
185        { "fixup_sparc_tls_ldo_add",    0,  0,  0 },
186        { "fixup_sparc_tls_ie_hi22",    0, 22,  0 },
187        { "fixup_sparc_tls_ie_lo10",    0, 10,  0 },
188        { "fixup_sparc_tls_ie_ld",      0,  0,  0 },
189        { "fixup_sparc_tls_ie_ldx",     0,  0,  0 },
190        { "fixup_sparc_tls_ie_add",     0,  0,  0 },
191        { "fixup_sparc_tls_le_hix22",   0,  0,  0 },
192        { "fixup_sparc_tls_le_lox10",   0,  0,  0 }
193      };
194
195      if (Kind < FirstTargetFixupKind)
196        return MCAsmBackend::getFixupKindInfo(Kind);
197
198      assert(unsigned(Kind - FirstTargetFixupKind) < getNumFixupKinds() &&
199             "Invalid kind!");
200      if (IsLittleEndian)
201        return InfosLE[Kind - FirstTargetFixupKind];
202
203      return InfosBE[Kind - FirstTargetFixupKind];
204    }
205
206    void processFixupValue(const MCAssembler &Asm, const MCAsmLayout &Layout,
207                           const MCFixup &Fixup, const MCFragment *DF,
208                           const MCValue &Target, uint64_t &Value,
209                           bool &IsResolved) override {
210      switch ((Sparc::Fixups)Fixup.getKind()) {
211      default: break;
212      case Sparc::fixup_sparc_wplt30:
213        if (Target.getSymA()->getSymbol().isTemporary())
214          return;
215      case Sparc::fixup_sparc_tls_gd_hi22:
216      case Sparc::fixup_sparc_tls_gd_lo10:
217      case Sparc::fixup_sparc_tls_gd_add:
218      case Sparc::fixup_sparc_tls_gd_call:
219      case Sparc::fixup_sparc_tls_ldm_hi22:
220      case Sparc::fixup_sparc_tls_ldm_lo10:
221      case Sparc::fixup_sparc_tls_ldm_add:
222      case Sparc::fixup_sparc_tls_ldm_call:
223      case Sparc::fixup_sparc_tls_ldo_hix22:
224      case Sparc::fixup_sparc_tls_ldo_lox10:
225      case Sparc::fixup_sparc_tls_ldo_add:
226      case Sparc::fixup_sparc_tls_ie_hi22:
227      case Sparc::fixup_sparc_tls_ie_lo10:
228      case Sparc::fixup_sparc_tls_ie_ld:
229      case Sparc::fixup_sparc_tls_ie_ldx:
230      case Sparc::fixup_sparc_tls_ie_add:
231      case Sparc::fixup_sparc_tls_le_hix22:
232      case Sparc::fixup_sparc_tls_le_lox10:  IsResolved = false; break;
233      }
234    }
235
236    bool mayNeedRelaxation(const MCInst &Inst) const override {
237      // FIXME.
238      return false;
239    }
240
241    /// fixupNeedsRelaxation - Target specific predicate for whether a given
242    /// fixup requires the associated instruction to be relaxed.
243    bool fixupNeedsRelaxation(const MCFixup &Fixup,
244                              uint64_t Value,
245                              const MCRelaxableFragment *DF,
246                              const MCAsmLayout &Layout) const override {
247      // FIXME.
248      llvm_unreachable("fixupNeedsRelaxation() unimplemented");
249      return false;
250    }
251    void relaxInstruction(const MCInst &Inst, MCInst &Res) const override {
252      // FIXME.
253      llvm_unreachable("relaxInstruction() unimplemented");
254    }
255
256    bool writeNopData(uint64_t Count, MCObjectWriter *OW) const override {
257      // Cannot emit NOP with size not multiple of 32 bits.
258      if (Count % 4 != 0)
259        return false;
260
261      uint64_t NumNops = Count / 4;
262      for (uint64_t i = 0; i != NumNops; ++i)
263        OW->write32(0x01000000);
264
265      return true;
266    }
267  };
268
269  class ELFSparcAsmBackend : public SparcAsmBackend {
270    Triple::OSType OSType;
271  public:
272    ELFSparcAsmBackend(const Target &T, Triple::OSType OSType) :
273      SparcAsmBackend(T), OSType(OSType) { }
274
275    void applyFixup(const MCFixup &Fixup, char *Data, unsigned DataSize,
276                    uint64_t Value, bool IsPCRel) const override {
277
278      Value = adjustFixupValue(Fixup.getKind(), Value);
279      if (!Value) return;           // Doesn't change encoding.
280
281      unsigned Offset = Fixup.getOffset();
282
283      // For each byte of the fragment that the fixup touches, mask in the bits
284      // from the fixup value. The Value has been "split up" into the
285      // appropriate bitfields above.
286      for (unsigned i = 0; i != 4; ++i) {
287        unsigned Idx = IsLittleEndian ? i : 3 - i;
288        Data[Offset + Idx] |= uint8_t((Value >> (i * 8)) & 0xff);
289      }
290    }
291
292    MCObjectWriter *createObjectWriter(raw_pwrite_stream &OS) const override {
293      uint8_t OSABI = MCELFObjectTargetWriter::getOSABI(OSType);
294      return createSparcELFObjectWriter(OS, Is64Bit, IsLittleEndian, OSABI);
295    }
296  };
297
298} // end anonymous namespace
299
300MCAsmBackend *llvm::createSparcAsmBackend(const Target &T,
301                                          const MCRegisterInfo &MRI,
302                                          const Triple &TT, StringRef CPU) {
303  return new ELFSparcAsmBackend(T, TT.getOS());
304}
305