Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/contrib/llvm-project/llvm/lib/Target/Xtensa/MCTargetDesc/XtensaAsmBackend.cpp
35295 views
1
//===-- XtensaMCAsmBackend.cpp - Xtensa assembler backend -----------------===//
2
//
3
// The LLVM Compiler Infrastructure
4
//
5
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
6
// See https://llvm.org/LICENSE.txt for license information.
7
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
8
//
9
//===----------------------------------------------------------------------===//
10
11
#include "MCTargetDesc/XtensaFixupKinds.h"
12
#include "MCTargetDesc/XtensaMCTargetDesc.h"
13
#include "llvm/MC/MCAsmBackend.h"
14
#include "llvm/MC/MCAssembler.h"
15
#include "llvm/MC/MCContext.h"
16
#include "llvm/MC/MCELFObjectWriter.h"
17
#include "llvm/MC/MCFixupKindInfo.h"
18
#include "llvm/MC/MCInst.h"
19
#include "llvm/MC/MCObjectWriter.h"
20
#include "llvm/MC/MCSubtargetInfo.h"
21
#include "llvm/Support/raw_ostream.h"
22
23
using namespace llvm;
24
25
namespace llvm {
26
class MCObjectTargetWriter;
27
class XtensaMCAsmBackend : public MCAsmBackend {
28
uint8_t OSABI;
29
bool IsLittleEndian;
30
31
public:
32
XtensaMCAsmBackend(uint8_t osABI, bool isLE)
33
: MCAsmBackend(llvm::endianness::little), OSABI(osABI),
34
IsLittleEndian(isLE) {}
35
36
unsigned getNumFixupKinds() const override {
37
return Xtensa::NumTargetFixupKinds;
38
}
39
const MCFixupKindInfo &getFixupKindInfo(MCFixupKind Kind) const override;
40
void applyFixup(const MCAssembler &Asm, const MCFixup &Fixup,
41
const MCValue &Target, MutableArrayRef<char> Data,
42
uint64_t Value, bool IsResolved,
43
const MCSubtargetInfo *STI) const override;
44
bool mayNeedRelaxation(const MCInst &Inst,
45
const MCSubtargetInfo &STI) const override;
46
void relaxInstruction(MCInst &Inst,
47
const MCSubtargetInfo &STI) const override;
48
bool writeNopData(raw_ostream &OS, uint64_t Count,
49
const MCSubtargetInfo *STI) const override;
50
51
std::unique_ptr<MCObjectTargetWriter> createObjectTargetWriter() const override {
52
return createXtensaObjectWriter(OSABI, IsLittleEndian);
53
}
54
};
55
} // namespace llvm
56
57
const MCFixupKindInfo &
58
XtensaMCAsmBackend::getFixupKindInfo(MCFixupKind Kind) const {
59
const static MCFixupKindInfo Infos[Xtensa::NumTargetFixupKinds] = {
60
// name offset bits flags
61
{"fixup_xtensa_branch_6", 0, 16, MCFixupKindInfo::FKF_IsPCRel},
62
{"fixup_xtensa_branch_8", 16, 8, MCFixupKindInfo::FKF_IsPCRel},
63
{"fixup_xtensa_branch_12", 12, 12, MCFixupKindInfo::FKF_IsPCRel},
64
{"fixup_xtensa_jump_18", 6, 18, MCFixupKindInfo::FKF_IsPCRel},
65
{"fixup_xtensa_call_18", 6, 18,
66
MCFixupKindInfo::FKF_IsPCRel |
67
MCFixupKindInfo::FKF_IsAlignedDownTo32Bits},
68
{"fixup_xtensa_l32r_16", 8, 16,
69
MCFixupKindInfo::FKF_IsPCRel |
70
MCFixupKindInfo::FKF_IsAlignedDownTo32Bits}};
71
72
if (Kind < FirstTargetFixupKind)
73
return MCAsmBackend::getFixupKindInfo(Kind);
74
assert(unsigned(Kind - FirstTargetFixupKind) < getNumFixupKinds() &&
75
"Invalid kind!");
76
return Infos[Kind - FirstTargetFixupKind];
77
}
78
79
static uint64_t adjustFixupValue(const MCFixup &Fixup, uint64_t Value,
80
MCContext &Ctx) {
81
unsigned Kind = Fixup.getKind();
82
switch (Kind) {
83
default:
84
llvm_unreachable("Unknown fixup kind!");
85
case FK_Data_1:
86
case FK_Data_2:
87
case FK_Data_4:
88
case FK_Data_8:
89
return Value;
90
case Xtensa::fixup_xtensa_branch_6: {
91
Value -= 4;
92
if (!isInt<6>(Value))
93
Ctx.reportError(Fixup.getLoc(), "fixup value out of range");
94
unsigned Hi2 = (Value >> 4) & 0x3;
95
unsigned Lo4 = Value & 0xf;
96
return (Hi2 << 4) | (Lo4 << 12);
97
}
98
case Xtensa::fixup_xtensa_branch_8:
99
Value -= 4;
100
if (!isInt<8>(Value))
101
Ctx.reportError(Fixup.getLoc(), "fixup value out of range");
102
return (Value & 0xff);
103
case Xtensa::fixup_xtensa_branch_12:
104
Value -= 4;
105
if (!isInt<12>(Value))
106
Ctx.reportError(Fixup.getLoc(), "fixup value out of range");
107
return (Value & 0xfff);
108
case Xtensa::fixup_xtensa_jump_18:
109
Value -= 4;
110
if (!isInt<18>(Value))
111
Ctx.reportError(Fixup.getLoc(), "fixup value out of range");
112
return (Value & 0x3ffff);
113
case Xtensa::fixup_xtensa_call_18:
114
Value -= 4;
115
if (!isInt<20>(Value))
116
Ctx.reportError(Fixup.getLoc(), "fixup value out of range");
117
if (Value & 0x3)
118
Ctx.reportError(Fixup.getLoc(), "fixup value must be 4-byte aligned");
119
return (Value & 0xffffc) >> 2;
120
case Xtensa::fixup_xtensa_l32r_16:
121
unsigned Offset = Fixup.getOffset();
122
if (Offset & 0x3)
123
Value -= 4;
124
if (!isInt<18>(Value) && (Value & 0x20000))
125
Ctx.reportError(Fixup.getLoc(), "fixup value out of range");
126
if (Value & 0x3)
127
Ctx.reportError(Fixup.getLoc(), "fixup value must be 4-byte aligned");
128
return (Value & 0x3fffc) >> 2;
129
}
130
}
131
132
static unsigned getSize(unsigned Kind) {
133
switch (Kind) {
134
default:
135
return 3;
136
case MCFixupKind::FK_Data_4:
137
return 4;
138
case Xtensa::fixup_xtensa_branch_6:
139
return 2;
140
}
141
}
142
143
void XtensaMCAsmBackend::applyFixup(const MCAssembler &Asm,
144
const MCFixup &Fixup, const MCValue &Target,
145
MutableArrayRef<char> Data, uint64_t Value,
146
bool IsResolved,
147
const MCSubtargetInfo *STI) const {
148
MCContext &Ctx = Asm.getContext();
149
MCFixupKindInfo Info = getFixupKindInfo(Fixup.getKind());
150
151
Value = adjustFixupValue(Fixup, Value, Ctx);
152
153
// Shift the value into position.
154
Value <<= Info.TargetOffset;
155
156
if (!Value)
157
return; // Doesn't change encoding.
158
159
unsigned Offset = Fixup.getOffset();
160
unsigned FullSize = getSize(Fixup.getKind());
161
162
for (unsigned i = 0; i != FullSize; ++i) {
163
Data[Offset + i] |= uint8_t((Value >> (i * 8)) & 0xff);
164
}
165
}
166
167
bool XtensaMCAsmBackend::mayNeedRelaxation(const MCInst &Inst,
168
const MCSubtargetInfo &STI) const {
169
return false;
170
}
171
172
void XtensaMCAsmBackend::relaxInstruction(MCInst &Inst,
173
const MCSubtargetInfo &STI) const {}
174
175
bool XtensaMCAsmBackend::writeNopData(raw_ostream &OS, uint64_t Count,
176
const MCSubtargetInfo *STI) const {
177
uint64_t NumNops24b = Count / 3;
178
179
for (uint64_t i = 0; i != NumNops24b; ++i) {
180
// Currently just little-endian machine supported,
181
// but probably big-endian will be also implemented in future
182
if (IsLittleEndian) {
183
OS.write("\xf0", 1);
184
OS.write("\x20", 1);
185
OS.write("\0x00", 1);
186
} else {
187
report_fatal_error("Big-endian mode currently is not supported!");
188
}
189
Count -= 3;
190
}
191
192
// TODO maybe function should return error if (Count > 0)
193
switch (Count) {
194
default:
195
break;
196
case 1:
197
OS.write("\0", 1);
198
break;
199
case 2:
200
// NOP.N instruction
201
OS.write("\x3d", 1);
202
OS.write("\xf0", 1);
203
break;
204
}
205
206
return true;
207
}
208
209
MCAsmBackend *llvm::createXtensaMCAsmBackend(const Target &T,
210
const MCSubtargetInfo &STI,
211
const MCRegisterInfo &MRI,
212
const MCTargetOptions &Options) {
213
uint8_t OSABI =
214
MCELFObjectTargetWriter::getOSABI(STI.getTargetTriple().getOS());
215
return new llvm::XtensaMCAsmBackend(OSABI, true);
216
}
217
218