1 //===-- SparcAsmBackend.cpp - Sparc Assembler Backend ---------------------===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
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"
22 static unsigned adjustFixupValue(unsigned Kind
, uint64_t Value
) {
25 llvm_unreachable("Unknown fixup kind!");
32 case Sparc::fixup_sparc_wplt30
:
33 case Sparc::fixup_sparc_call30
:
34 return (Value
>> 2) & 0x3fffffff;
36 case Sparc::fixup_sparc_br22
:
37 return (Value
>> 2) & 0x3fffff;
39 case Sparc::fixup_sparc_br19
:
40 return (Value
>> 2) & 0x7ffff;
42 case Sparc::fixup_sparc_br16_2
:
43 return (Value
>> 2) & 0xc000;
45 case Sparc::fixup_sparc_br16_14
:
46 return (Value
>> 2) & 0x3fff;
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;
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
:
64 case Sparc::fixup_sparc_tls_ldo_hix22
:
65 case Sparc::fixup_sparc_tls_le_hix22
:
66 return (~Value
>> 10) & 0x3fffff;
68 case Sparc::fixup_sparc_tls_ldo_lox10
:
69 case Sparc::fixup_sparc_tls_le_lox10
:
70 return (~(~Value
& 0x3ff)) & 0x1fff;
72 case Sparc::fixup_sparc_h44
:
73 return (Value
>> 22) & 0x3fffff;
75 case Sparc::fixup_sparc_m44
:
76 return (Value
>> 12) & 0x3ff;
78 case Sparc::fixup_sparc_l44
:
81 case Sparc::fixup_sparc_hh
:
82 return (Value
>> 42) & 0x3fffff;
84 case Sparc::fixup_sparc_hm
:
85 return (Value
>> 32) & 0x3ff;
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
:
100 class SparcAsmBackend
: public MCAsmBackend
{
101 const Target
&TheTarget
;
103 SparcAsmBackend(const Target
&T
) : MCAsmBackend(), TheTarget(T
) {}
105 unsigned getNumFixupKinds() const override
{
106 return Sparc::NumTargetFixupKinds
;
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 }
149 if (Kind
< FirstTargetFixupKind
)
150 return MCAsmBackend::getFixupKindInfo(Kind
);
152 assert(unsigned(Kind
- FirstTargetFixupKind
) < getNumFixupKinds() &&
154 return Infos
[Kind
- FirstTargetFixupKind
];
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()) {
163 case Sparc::fixup_sparc_wplt30
:
164 if (Target
.getSymA()->getSymbol().isTemporary())
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;
187 bool mayNeedRelaxation(const MCInst
&Inst
) const override
{
192 /// fixupNeedsRelaxation - Target specific predicate for whether a given
193 /// fixup requires the associated instruction to be relaxed.
194 bool fixupNeedsRelaxation(const MCFixup
&Fixup
,
196 const MCRelaxableFragment
*DF
,
197 const MCAsmLayout
&Layout
) const override
{
199 llvm_unreachable("fixupNeedsRelaxation() unimplemented");
202 void relaxInstruction(const MCInst
&Inst
, MCInst
&Res
) const override
{
204 llvm_unreachable("relaxInstruction() unimplemented");
207 bool writeNopData(uint64_t Count
, MCObjectWriter
*OW
) const override
{
208 // Cannot emit NOP with size not multiple of 32 bits.
212 uint64_t NumNops
= Count
/ 4;
213 for (uint64_t i
= 0; i
!= NumNops
; ++i
)
214 OW
->Write32(0x01000000);
219 bool is64Bit() const {
220 StringRef name
= TheTarget
.getName();
221 return name
== "sparcv9";
225 class ELFSparcAsmBackend
: public SparcAsmBackend
{
226 Triple::OSType OSType
;
228 ELFSparcAsmBackend(const Target
&T
, Triple::OSType OSType
) :
229 SparcAsmBackend(T
), OSType(OSType
) { }
231 void applyFixup(const MCFixup
&Fixup
, char *Data
, unsigned DataSize
,
232 uint64_t Value
, bool IsPCRel
) const override
{
234 Value
= adjustFixupValue(Fixup
.getKind(), Value
);
235 if (!Value
) return; // Doesn't change encoding.
237 unsigned Offset
= Fixup
.getOffset();
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);
247 MCObjectWriter
*createObjectWriter(raw_ostream
&OS
) const override
{
248 uint8_t OSABI
= MCELFObjectTargetWriter::getOSABI(OSType
);
249 return createSparcELFObjectWriter(OS
, is64Bit(), OSABI
);
253 } // end anonymous namespace
256 MCAsmBackend
*llvm::createSparcAsmBackend(const Target
&T
,
257 const MCRegisterInfo
&MRI
,
260 return new ELFSparcAsmBackend(T
, Triple(TT
).getOS());