1262261Sdim//===-- SparcAsmBackend.cpp - Sparc Assembler Backend ---------------------===//
2262261Sdim//
3262261Sdim//                     The LLVM Compiler Infrastructure
4262261Sdim//
5262261Sdim// This file is distributed under the University of Illinois Open Source
6262261Sdim// License. See LICENSE.TXT for details.
7262261Sdim//
8262261Sdim//===----------------------------------------------------------------------===//
9262261Sdim
10262261Sdim#include "llvm/MC/MCAsmBackend.h"
11262261Sdim#include "MCTargetDesc/SparcMCTargetDesc.h"
12262261Sdim#include "MCTargetDesc/SparcFixupKinds.h"
13262261Sdim#include "llvm/MC/MCELFObjectWriter.h"
14262261Sdim#include "llvm/MC/MCFixupKindInfo.h"
15262261Sdim#include "llvm/MC/MCObjectWriter.h"
16262261Sdim#include "llvm/Support/TargetRegistry.h"
17262261Sdim
18262261Sdimusing namespace llvm;
19262261Sdim
20262261Sdimstatic unsigned adjustFixupValue(unsigned Kind, uint64_t Value) {
21262261Sdim  switch (Kind) {
22262261Sdim  default:
23262261Sdim    llvm_unreachable("Unknown fixup kind!");
24262261Sdim  case FK_Data_1:
25262261Sdim  case FK_Data_2:
26262261Sdim  case FK_Data_4:
27262261Sdim  case FK_Data_8:
28262261Sdim    return Value;
29262261Sdim
30262261Sdim  case Sparc::fixup_sparc_wplt30:
31262261Sdim  case Sparc::fixup_sparc_call30:
32262261Sdim    return (Value >> 2) & 0x3fffffff;
33262261Sdim
34262261Sdim  case Sparc::fixup_sparc_br22:
35262261Sdim    return (Value >> 2) & 0x3fffff;
36262261Sdim
37262261Sdim  case Sparc::fixup_sparc_br19:
38262261Sdim    return (Value >> 2) & 0x7ffff;
39262261Sdim
40262261Sdim  case Sparc::fixup_sparc_pc22:
41262261Sdim  case Sparc::fixup_sparc_got22:
42262261Sdim  case Sparc::fixup_sparc_tls_gd_hi22:
43262261Sdim  case Sparc::fixup_sparc_tls_ldm_hi22:
44262261Sdim  case Sparc::fixup_sparc_tls_ie_hi22:
45262261Sdim  case Sparc::fixup_sparc_hi22:
46262261Sdim    return (Value >> 10) & 0x3fffff;
47262261Sdim
48262261Sdim  case Sparc::fixup_sparc_pc10:
49262261Sdim  case Sparc::fixup_sparc_got10:
50262261Sdim  case Sparc::fixup_sparc_tls_gd_lo10:
51262261Sdim  case Sparc::fixup_sparc_tls_ldm_lo10:
52262261Sdim  case Sparc::fixup_sparc_tls_ie_lo10:
53262261Sdim  case Sparc::fixup_sparc_lo10:
54262261Sdim    return Value & 0x3ff;
55262261Sdim
56262261Sdim  case Sparc::fixup_sparc_tls_ldo_hix22:
57262261Sdim  case Sparc::fixup_sparc_tls_le_hix22:
58262261Sdim    return (~Value >> 10) & 0x3fffff;
59262261Sdim
60262261Sdim  case Sparc::fixup_sparc_tls_ldo_lox10:
61262261Sdim  case Sparc::fixup_sparc_tls_le_lox10:
62262261Sdim    return (~(~Value & 0x3ff)) & 0x1fff;
63262261Sdim
64262261Sdim  case Sparc::fixup_sparc_h44:
65262261Sdim    return (Value >> 22) & 0x3fffff;
66262261Sdim
67262261Sdim  case Sparc::fixup_sparc_m44:
68262261Sdim    return (Value >> 12) & 0x3ff;
69262261Sdim
70262261Sdim  case Sparc::fixup_sparc_l44:
71262261Sdim    return Value & 0xfff;
72262261Sdim
73262261Sdim  case Sparc::fixup_sparc_hh:
74262261Sdim    return (Value >> 42) & 0x3fffff;
75262261Sdim
76262261Sdim  case Sparc::fixup_sparc_hm:
77262261Sdim    return (Value >> 32) & 0x3ff;
78262261Sdim
79262261Sdim  case Sparc::fixup_sparc_tls_gd_add:
80262261Sdim  case Sparc::fixup_sparc_tls_gd_call:
81262261Sdim  case Sparc::fixup_sparc_tls_ldm_add:
82262261Sdim  case Sparc::fixup_sparc_tls_ldm_call:
83262261Sdim  case Sparc::fixup_sparc_tls_ldo_add:
84262261Sdim  case Sparc::fixup_sparc_tls_ie_ld:
85262261Sdim  case Sparc::fixup_sparc_tls_ie_ldx:
86262261Sdim  case Sparc::fixup_sparc_tls_ie_add:
87262261Sdim    return 0;
88262261Sdim  }
89262261Sdim}
90262261Sdim
91262261Sdimnamespace {
92262261Sdim  class SparcAsmBackend : public MCAsmBackend {
93262261Sdim    const Target &TheTarget;
94262261Sdim  public:
95262261Sdim    SparcAsmBackend(const Target &T) : MCAsmBackend(), TheTarget(T) {}
96262261Sdim
97262261Sdim    unsigned getNumFixupKinds() const {
98262261Sdim      return Sparc::NumTargetFixupKinds;
99262261Sdim    }
100262261Sdim
101262261Sdim    const MCFixupKindInfo &getFixupKindInfo(MCFixupKind Kind) const {
102262261Sdim      const static MCFixupKindInfo Infos[Sparc::NumTargetFixupKinds] = {
103262261Sdim        // name                    offset bits  flags
104262261Sdim        { "fixup_sparc_call30",     2,     30,  MCFixupKindInfo::FKF_IsPCRel },
105262261Sdim        { "fixup_sparc_br22",      10,     22,  MCFixupKindInfo::FKF_IsPCRel },
106262261Sdim        { "fixup_sparc_br19",      13,     19,  MCFixupKindInfo::FKF_IsPCRel },
107262261Sdim        { "fixup_sparc_hi22",      10,     22,  0 },
108262261Sdim        { "fixup_sparc_lo10",      22,     10,  0 },
109262261Sdim        { "fixup_sparc_h44",       10,     22,  0 },
110262261Sdim        { "fixup_sparc_m44",       22,     10,  0 },
111262261Sdim        { "fixup_sparc_l44",       20,     12,  0 },
112262261Sdim        { "fixup_sparc_hh",        10,     22,  0 },
113262261Sdim        { "fixup_sparc_hm",        22,     10,  0 },
114262261Sdim        { "fixup_sparc_pc22",      10,     22,  MCFixupKindInfo::FKF_IsPCRel },
115262261Sdim        { "fixup_sparc_pc10",      22,     10,  MCFixupKindInfo::FKF_IsPCRel },
116262261Sdim        { "fixup_sparc_got22",     10,     22,  0 },
117262261Sdim        { "fixup_sparc_got10",     22,     10,  0 },
118262261Sdim        { "fixup_sparc_wplt30",     2,     30,  MCFixupKindInfo::FKF_IsPCRel },
119262261Sdim        { "fixup_sparc_tls_gd_hi22",   10, 22,  0 },
120262261Sdim        { "fixup_sparc_tls_gd_lo10",   22, 10,  0 },
121262261Sdim        { "fixup_sparc_tls_gd_add",     0,  0,  0 },
122262261Sdim        { "fixup_sparc_tls_gd_call",    0,  0,  0 },
123262261Sdim        { "fixup_sparc_tls_ldm_hi22",  10, 22,  0 },
124262261Sdim        { "fixup_sparc_tls_ldm_lo10",  22, 10,  0 },
125262261Sdim        { "fixup_sparc_tls_ldm_add",    0,  0,  0 },
126262261Sdim        { "fixup_sparc_tls_ldm_call",   0,  0,  0 },
127262261Sdim        { "fixup_sparc_tls_ldo_hix22", 10, 22,  0 },
128262261Sdim        { "fixup_sparc_tls_ldo_lox10", 22, 10,  0 },
129262261Sdim        { "fixup_sparc_tls_ldo_add",    0,  0,  0 },
130262261Sdim        { "fixup_sparc_tls_ie_hi22",   10, 22,  0 },
131262261Sdim        { "fixup_sparc_tls_ie_lo10",   22, 10,  0 },
132262261Sdim        { "fixup_sparc_tls_ie_ld",      0,  0,  0 },
133262261Sdim        { "fixup_sparc_tls_ie_ldx",     0,  0,  0 },
134262261Sdim        { "fixup_sparc_tls_ie_add",     0,  0,  0 },
135262261Sdim        { "fixup_sparc_tls_le_hix22",   0,  0,  0 },
136262261Sdim        { "fixup_sparc_tls_le_lox10",   0,  0,  0 }
137262261Sdim      };
138262261Sdim
139262261Sdim      if (Kind < FirstTargetFixupKind)
140262261Sdim        return MCAsmBackend::getFixupKindInfo(Kind);
141262261Sdim
142262261Sdim      assert(unsigned(Kind - FirstTargetFixupKind) < getNumFixupKinds() &&
143262261Sdim             "Invalid kind!");
144262261Sdim      return Infos[Kind - FirstTargetFixupKind];
145262261Sdim    }
146262261Sdim
147262261Sdim    void processFixupValue(const MCAssembler &Asm,
148262261Sdim                           const MCAsmLayout &Layout,
149262261Sdim                           const MCFixup &Fixup,
150262261Sdim                           const MCFragment *DF,
151262261Sdim                           MCValue &  Target,
152262261Sdim                           uint64_t &Value,
153262261Sdim                           bool &IsResolved) {
154262261Sdim      switch ((Sparc::Fixups)Fixup.getKind()) {
155262261Sdim      default: break;
156262261Sdim      case Sparc::fixup_sparc_wplt30:
157262261Sdim      case Sparc::fixup_sparc_tls_gd_hi22:
158262261Sdim      case Sparc::fixup_sparc_tls_gd_lo10:
159262261Sdim      case Sparc::fixup_sparc_tls_gd_add:
160262261Sdim      case Sparc::fixup_sparc_tls_gd_call:
161262261Sdim      case Sparc::fixup_sparc_tls_ldm_hi22:
162262261Sdim      case Sparc::fixup_sparc_tls_ldm_lo10:
163262261Sdim      case Sparc::fixup_sparc_tls_ldm_add:
164262261Sdim      case Sparc::fixup_sparc_tls_ldm_call:
165262261Sdim      case Sparc::fixup_sparc_tls_ldo_hix22:
166262261Sdim      case Sparc::fixup_sparc_tls_ldo_lox10:
167262261Sdim      case Sparc::fixup_sparc_tls_ldo_add:
168262261Sdim      case Sparc::fixup_sparc_tls_ie_hi22:
169262261Sdim      case Sparc::fixup_sparc_tls_ie_lo10:
170262261Sdim      case Sparc::fixup_sparc_tls_ie_ld:
171262261Sdim      case Sparc::fixup_sparc_tls_ie_ldx:
172262261Sdim      case Sparc::fixup_sparc_tls_ie_add:
173262261Sdim      case Sparc::fixup_sparc_tls_le_hix22:
174262261Sdim      case Sparc::fixup_sparc_tls_le_lox10:  IsResolved = false; break;
175262261Sdim      }
176262261Sdim    }
177262261Sdim
178262261Sdim    bool mayNeedRelaxation(const MCInst &Inst) const {
179262261Sdim      // FIXME.
180262261Sdim      return false;
181262261Sdim    }
182262261Sdim
183262261Sdim    /// fixupNeedsRelaxation - Target specific predicate for whether a given
184262261Sdim    /// fixup requires the associated instruction to be relaxed.
185262261Sdim    bool fixupNeedsRelaxation(const MCFixup &Fixup,
186262261Sdim                              uint64_t Value,
187262261Sdim                              const MCRelaxableFragment *DF,
188262261Sdim                              const MCAsmLayout &Layout) const {
189262261Sdim      // FIXME.
190262261Sdim      assert(0 && "fixupNeedsRelaxation() unimplemented");
191262261Sdim      return false;
192262261Sdim    }
193262261Sdim    void relaxInstruction(const MCInst &Inst, MCInst &Res) const {
194262261Sdim      // FIXME.
195262261Sdim      assert(0 && "relaxInstruction() unimplemented");
196262261Sdim    }
197262261Sdim
198262261Sdim    bool writeNopData(uint64_t Count, MCObjectWriter *OW) const {
199262261Sdim      // FIXME: Zero fill for now.
200262261Sdim      for (uint64_t i = 0; i != Count; ++i)
201262261Sdim        OW->Write8(0);
202262261Sdim      return true;
203262261Sdim    }
204262261Sdim
205262261Sdim    bool is64Bit() const {
206262261Sdim      StringRef name = TheTarget.getName();
207262261Sdim      return name == "sparcv9";
208262261Sdim    }
209262261Sdim  };
210262261Sdim
211262261Sdim  class ELFSparcAsmBackend : public SparcAsmBackend {
212262261Sdim    Triple::OSType OSType;
213262261Sdim  public:
214262261Sdim    ELFSparcAsmBackend(const Target &T, Triple::OSType OSType) :
215262261Sdim      SparcAsmBackend(T), OSType(OSType) { }
216262261Sdim
217262261Sdim    void applyFixup(const MCFixup &Fixup, char *Data, unsigned DataSize,
218262261Sdim                    uint64_t Value) const {
219262261Sdim
220262261Sdim      Value = adjustFixupValue(Fixup.getKind(), Value);
221262261Sdim      if (!Value) return;           // Doesn't change encoding.
222262261Sdim
223262261Sdim      unsigned Offset = Fixup.getOffset();
224262261Sdim
225262261Sdim      // For each byte of the fragment that the fixup touches, mask in the bits
226262261Sdim      // from the fixup value. The Value has been "split up" into the
227262261Sdim      // appropriate bitfields above.
228262261Sdim      for (unsigned i = 0; i != 4; ++i)
229262261Sdim        Data[Offset + i] |= uint8_t((Value >> ((4 - i - 1)*8)) & 0xff);
230262261Sdim
231262261Sdim    }
232262261Sdim
233262261Sdim    MCObjectWriter *createObjectWriter(raw_ostream &OS) const {
234262261Sdim      uint8_t OSABI = MCELFObjectTargetWriter::getOSABI(OSType);
235262261Sdim      return createSparcELFObjectWriter(OS, is64Bit(), OSABI);
236262261Sdim    }
237262261Sdim
238262261Sdim    virtual bool doesSectionRequireSymbols(const MCSection &Section) const {
239262261Sdim      return false;
240262261Sdim    }
241262261Sdim  };
242262261Sdim
243262261Sdim} // end anonymous namespace
244262261Sdim
245262261Sdim
246262261SdimMCAsmBackend *llvm::createSparcAsmBackend(const Target &T,
247262261Sdim                                          const MCRegisterInfo &MRI,
248262261Sdim                                          StringRef TT,
249262261Sdim                                          StringRef CPU) {
250262261Sdim  return new ELFSparcAsmBackend(T, Triple(TT).getOS());
251262261Sdim}
252