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    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
256MCAsmBackend *llvm::createSparcAsmBackend(const Target &T,
257                                          const MCRegisterInfo &MRI,
258                                          StringRef TT,
259                                          StringRef CPU) {
260  return new ELFSparcAsmBackend(T, Triple(TT).getOS());
261}
262