1 //===-- VEAsmBackend.cpp - VE Assembler Backend ---------------------------===//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
9 #include "MCTargetDesc/VEFixupKinds.h"
10 #include "MCTargetDesc/VEMCTargetDesc.h"
11 #include "llvm/MC/MCAsmBackend.h"
12 #include "llvm/MC/MCELFObjectWriter.h"
13 #include "llvm/MC/MCExpr.h"
14 #include "llvm/MC/MCFixupKindInfo.h"
15 #include "llvm/MC/MCObjectWriter.h"
16 #include "llvm/MC/MCSubtargetInfo.h"
17 #include "llvm/MC/MCValue.h"
18 #include "llvm/MC/TargetRegistry.h"
19 #include "llvm/Support/EndianStream.h"
23 static uint64_t adjustFixupValue(unsigned Kind
, uint64_t Value
) {
26 llvm_unreachable("Unknown fixup kind!");
36 case VE::fixup_ve_hi32
:
37 case VE::fixup_ve_pc_hi32
:
38 case VE::fixup_ve_got_hi32
:
39 case VE::fixup_ve_gotoff_hi32
:
40 case VE::fixup_ve_plt_hi32
:
41 case VE::fixup_ve_tls_gd_hi32
:
42 case VE::fixup_ve_tpoff_hi32
:
43 return (Value
>> 32) & 0xffffffff;
44 case VE::fixup_ve_reflong
:
45 case VE::fixup_ve_srel32
:
46 case VE::fixup_ve_lo32
:
47 case VE::fixup_ve_pc_lo32
:
48 case VE::fixup_ve_got_lo32
:
49 case VE::fixup_ve_gotoff_lo32
:
50 case VE::fixup_ve_plt_lo32
:
51 case VE::fixup_ve_tls_gd_lo32
:
52 case VE::fixup_ve_tpoff_lo32
:
53 return Value
& 0xffffffff;
57 /// getFixupKindNumBytes - The number of bytes the fixup may change.
58 static unsigned getFixupKindNumBytes(unsigned Kind
) {
61 llvm_unreachable("Unknown fixup kind!");
71 case VE::fixup_ve_reflong
:
72 case VE::fixup_ve_srel32
:
73 case VE::fixup_ve_hi32
:
74 case VE::fixup_ve_lo32
:
75 case VE::fixup_ve_pc_hi32
:
76 case VE::fixup_ve_pc_lo32
:
77 case VE::fixup_ve_got_hi32
:
78 case VE::fixup_ve_got_lo32
:
79 case VE::fixup_ve_gotoff_hi32
:
80 case VE::fixup_ve_gotoff_lo32
:
81 case VE::fixup_ve_plt_hi32
:
82 case VE::fixup_ve_plt_lo32
:
83 case VE::fixup_ve_tls_gd_hi32
:
84 case VE::fixup_ve_tls_gd_lo32
:
85 case VE::fixup_ve_tpoff_hi32
:
86 case VE::fixup_ve_tpoff_lo32
:
95 class VEAsmBackend
: public MCAsmBackend
{
97 const Target
&TheTarget
;
100 VEAsmBackend(const Target
&T
)
101 : MCAsmBackend(llvm::endianness::little
), TheTarget(T
) {}
103 unsigned getNumFixupKinds() const override
{ return VE::NumTargetFixupKinds
; }
105 const MCFixupKindInfo
&getFixupKindInfo(MCFixupKind Kind
) const override
{
106 const static MCFixupKindInfo Infos
[VE::NumTargetFixupKinds
] = {
107 // name, offset, bits, flags
108 {"fixup_ve_reflong", 0, 32, 0},
109 {"fixup_ve_srel32", 0, 32, MCFixupKindInfo::FKF_IsPCRel
},
110 {"fixup_ve_hi32", 0, 32, 0},
111 {"fixup_ve_lo32", 0, 32, 0},
112 {"fixup_ve_pc_hi32", 0, 32, MCFixupKindInfo::FKF_IsPCRel
},
113 {"fixup_ve_pc_lo32", 0, 32, MCFixupKindInfo::FKF_IsPCRel
},
114 {"fixup_ve_got_hi32", 0, 32, 0},
115 {"fixup_ve_got_lo32", 0, 32, 0},
116 {"fixup_ve_gotoff_hi32", 0, 32, 0},
117 {"fixup_ve_gotoff_lo32", 0, 32, 0},
118 {"fixup_ve_plt_hi32", 0, 32, 0},
119 {"fixup_ve_plt_lo32", 0, 32, 0},
120 {"fixup_ve_tls_gd_hi32", 0, 32, 0},
121 {"fixup_ve_tls_gd_lo32", 0, 32, 0},
122 {"fixup_ve_tpoff_hi32", 0, 32, 0},
123 {"fixup_ve_tpoff_lo32", 0, 32, 0},
126 if (Kind
< FirstTargetFixupKind
)
127 return MCAsmBackend::getFixupKindInfo(Kind
);
129 assert(unsigned(Kind
- FirstTargetFixupKind
) < getNumFixupKinds() &&
131 return Infos
[Kind
- FirstTargetFixupKind
];
134 bool shouldForceRelocation(const MCAssembler
&Asm
, const MCFixup
&Fixup
,
135 const MCValue
&Target
,
136 const MCSubtargetInfo
*STI
) override
{
137 switch ((VE::Fixups
)Fixup
.getKind()) {
140 case VE::fixup_ve_tls_gd_hi32
:
141 case VE::fixup_ve_tls_gd_lo32
:
142 case VE::fixup_ve_tpoff_hi32
:
143 case VE::fixup_ve_tpoff_lo32
:
148 bool mayNeedRelaxation(const MCInst
&Inst
,
149 const MCSubtargetInfo
&STI
) const override
{
150 // Not implemented yet. For example, if we have a branch with
151 // lager than SIMM32 immediate value, we want to relaxation such
152 // branch instructions.
156 /// fixupNeedsRelaxation - Target specific predicate for whether a given
157 /// fixup requires the associated instruction to be relaxed.
158 bool fixupNeedsRelaxation(const MCFixup
&Fixup
, uint64_t Value
,
159 const MCRelaxableFragment
*DF
,
160 const MCAsmLayout
&Layout
) const override
{
161 // Not implemented yet. For example, if we have a branch with
162 // lager than SIMM32 immediate value, we want to relaxation such
163 // branch instructions.
166 void relaxInstruction(MCInst
&Inst
,
167 const MCSubtargetInfo
&STI
) const override
{
168 // Aurora VE doesn't support relaxInstruction yet.
169 llvm_unreachable("relaxInstruction() should not be called");
172 bool writeNopData(raw_ostream
&OS
, uint64_t Count
,
173 const MCSubtargetInfo
*STI
) const override
{
174 if ((Count
% 8) != 0)
177 for (uint64_t i
= 0; i
< Count
; i
+= 8)
178 support::endian::write
<uint64_t>(OS
, 0x7900000000000000ULL
,
179 llvm::endianness::little
);
185 class ELFVEAsmBackend
: public VEAsmBackend
{
186 Triple::OSType OSType
;
189 ELFVEAsmBackend(const Target
&T
, Triple::OSType OSType
)
190 : VEAsmBackend(T
), OSType(OSType
) {}
192 void applyFixup(const MCAssembler
&Asm
, const MCFixup
&Fixup
,
193 const MCValue
&Target
, MutableArrayRef
<char> Data
,
194 uint64_t Value
, bool IsResolved
,
195 const MCSubtargetInfo
*STI
) const override
{
196 Value
= adjustFixupValue(Fixup
.getKind(), Value
);
198 return; // Doesn't change encoding.
200 MCFixupKindInfo Info
= getFixupKindInfo(Fixup
.getKind());
202 // Shift the value into position.
203 Value
<<= Info
.TargetOffset
;
205 unsigned NumBytes
= getFixupKindNumBytes(Fixup
.getKind());
206 unsigned Offset
= Fixup
.getOffset();
207 assert(Offset
+ NumBytes
<= Data
.size() && "Invalid fixup offset!");
208 // For each byte of the fragment that the fixup touches, mask in the bits
209 // from the fixup value. The Value has been "split up" into the
210 // appropriate bitfields above.
211 for (unsigned i
= 0; i
!= NumBytes
; ++i
) {
213 Endian
== llvm::endianness::little
? i
: (NumBytes
- 1) - i
;
214 Data
[Offset
+ Idx
] |= static_cast<uint8_t>((Value
>> (i
* 8)) & 0xff);
218 std::unique_ptr
<MCObjectTargetWriter
>
219 createObjectTargetWriter() const override
{
220 uint8_t OSABI
= MCELFObjectTargetWriter::getOSABI(OSType
);
221 return createVEELFObjectWriter(OSABI
);
224 } // end anonymous namespace
226 MCAsmBackend
*llvm::createVEAsmBackend(const Target
&T
,
227 const MCSubtargetInfo
&STI
,
228 const MCRegisterInfo
&MRI
,
229 const MCTargetOptions
&Options
) {
230 return new ELFVEAsmBackend(T
, STI
.getTargetTriple().getOS());