Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/contrib/llvm-project/llvm/lib/Target/CSKY/MCTargetDesc/CSKYAsmBackend.cpp
35294 views
1
//===-- CSKYAsmBackend.cpp - CSKY Assembler Backend -----------------------===//
2
//
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
6
//
7
//===----------------------------------------------------------------------===//
8
9
#include "CSKYAsmBackend.h"
10
#include "MCTargetDesc/CSKYMCTargetDesc.h"
11
#include "llvm/ADT/DenseMap.h"
12
#include "llvm/MC/MCAssembler.h"
13
#include "llvm/MC/MCContext.h"
14
#include "llvm/MC/MCFixupKindInfo.h"
15
#include "llvm/MC/MCObjectWriter.h"
16
#include "llvm/Support/Debug.h"
17
18
#define DEBUG_TYPE "csky-asmbackend"
19
20
using namespace llvm;
21
22
std::unique_ptr<MCObjectTargetWriter>
23
CSKYAsmBackend::createObjectTargetWriter() const {
24
return createCSKYELFObjectWriter();
25
}
26
27
const MCFixupKindInfo &
28
CSKYAsmBackend::getFixupKindInfo(MCFixupKind Kind) const {
29
30
static llvm::DenseMap<unsigned, MCFixupKindInfo> Infos = {
31
{CSKY::Fixups::fixup_csky_addr32, {"fixup_csky_addr32", 0, 32, 0}},
32
{CSKY::Fixups::fixup_csky_addr_hi16, {"fixup_csky_addr_hi16", 0, 32, 0}},
33
{CSKY::Fixups::fixup_csky_addr_lo16, {"fixup_csky_addr_lo16", 0, 32, 0}},
34
{CSKY::Fixups::fixup_csky_pcrel_imm16_scale2,
35
{"fixup_csky_pcrel_imm16_scale2", 0, 32, MCFixupKindInfo::FKF_IsPCRel}},
36
{CSKY::Fixups::fixup_csky_pcrel_uimm16_scale4,
37
{"fixup_csky_pcrel_uimm16_scale4", 0, 32,
38
MCFixupKindInfo::FKF_IsPCRel |
39
MCFixupKindInfo::FKF_IsAlignedDownTo32Bits}},
40
{CSKY::Fixups::fixup_csky_pcrel_uimm8_scale4,
41
{"fixup_csky_pcrel_uimm8_scale4", 0, 32,
42
MCFixupKindInfo::FKF_IsPCRel |
43
MCFixupKindInfo::FKF_IsAlignedDownTo32Bits}},
44
{CSKY::Fixups::fixup_csky_pcrel_imm26_scale2,
45
{"fixup_csky_pcrel_imm26_scale2", 0, 32, MCFixupKindInfo::FKF_IsPCRel}},
46
{CSKY::Fixups::fixup_csky_pcrel_imm18_scale2,
47
{"fixup_csky_pcrel_imm18_scale2", 0, 32, MCFixupKindInfo::FKF_IsPCRel}},
48
{CSKY::Fixups::fixup_csky_got32, {"fixup_csky_got32", 0, 32, 0}},
49
{CSKY::Fixups::fixup_csky_got_imm18_scale4,
50
{"fixup_csky_got_imm18_scale4", 0, 32, 0}},
51
{CSKY::Fixups::fixup_csky_gotoff, {"fixup_csky_gotoff", 0, 32, 0}},
52
{CSKY::Fixups::fixup_csky_gotpc,
53
{"fixup_csky_gotpc", 0, 32, MCFixupKindInfo::FKF_IsPCRel}},
54
{CSKY::Fixups::fixup_csky_plt32, {"fixup_csky_plt32", 0, 32, 0}},
55
{CSKY::Fixups::fixup_csky_plt_imm18_scale4,
56
{"fixup_csky_plt_imm18_scale4", 0, 32, 0}},
57
{CSKY::Fixups::fixup_csky_pcrel_imm10_scale2,
58
{"fixup_csky_pcrel_imm10_scale2", 0, 16, MCFixupKindInfo::FKF_IsPCRel}},
59
{CSKY::Fixups::fixup_csky_pcrel_uimm7_scale4,
60
{"fixup_csky_pcrel_uimm7_scale4", 0, 16,
61
MCFixupKindInfo::FKF_IsPCRel |
62
MCFixupKindInfo::FKF_IsAlignedDownTo32Bits}},
63
{CSKY::Fixups::fixup_csky_doffset_imm18,
64
{"fixup_csky_doffset_imm18", 0, 18, 0}},
65
{CSKY::Fixups::fixup_csky_doffset_imm18_scale2,
66
{"fixup_csky_doffset_imm18_scale2", 0, 18, 0}},
67
{CSKY::Fixups::fixup_csky_doffset_imm18_scale4,
68
{"fixup_csky_doffset_imm18_scale4", 0, 18, 0}}};
69
70
assert(Infos.size() == CSKY::NumTargetFixupKinds &&
71
"Not all fixup kinds added to Infos array");
72
73
if (FirstTargetFixupKind <= Kind && Kind < FirstLiteralRelocationKind) {
74
assert(unsigned(Kind - FirstTargetFixupKind) < getNumFixupKinds() &&
75
"Invalid kind!");
76
77
return Infos[Kind];
78
} else if (Kind < FirstTargetFixupKind) {
79
return MCAsmBackend::getFixupKindInfo(Kind);
80
} else {
81
return MCAsmBackend::getFixupKindInfo(FK_NONE);
82
}
83
}
84
85
static uint64_t adjustFixupValue(const MCFixup &Fixup, uint64_t Value,
86
MCContext &Ctx) {
87
switch (Fixup.getTargetKind()) {
88
default:
89
llvm_unreachable("Unknown fixup kind!");
90
case CSKY::fixup_csky_got32:
91
case CSKY::fixup_csky_got_imm18_scale4:
92
case CSKY::fixup_csky_gotoff:
93
case CSKY::fixup_csky_gotpc:
94
case CSKY::fixup_csky_plt32:
95
case CSKY::fixup_csky_plt_imm18_scale4:
96
llvm_unreachable("Relocation should be unconditionally forced\n");
97
case FK_Data_1:
98
case FK_Data_2:
99
case FK_Data_4:
100
case FK_Data_8:
101
return Value;
102
case CSKY::fixup_csky_addr32:
103
return Value & 0xffffffff;
104
case CSKY::fixup_csky_pcrel_imm16_scale2:
105
if (!isIntN(17, Value))
106
Ctx.reportError(Fixup.getLoc(), "out of range pc-relative fixup value.");
107
if (Value & 0x1)
108
Ctx.reportError(Fixup.getLoc(), "fixup value must be 2-byte aligned.");
109
110
return (Value >> 1) & 0xffff;
111
case CSKY::fixup_csky_pcrel_uimm16_scale4:
112
if (!isUIntN(18, Value))
113
Ctx.reportError(Fixup.getLoc(), "out of range pc-relative fixup value.");
114
if (Value & 0x3)
115
Ctx.reportError(Fixup.getLoc(), "fixup value must be 4-byte aligned.");
116
117
return (Value >> 2) & 0xffff;
118
case CSKY::fixup_csky_pcrel_imm26_scale2:
119
if (!isIntN(27, Value))
120
Ctx.reportError(Fixup.getLoc(), "out of range pc-relative fixup value.");
121
if (Value & 0x1)
122
Ctx.reportError(Fixup.getLoc(), "fixup value must be 2-byte aligned.");
123
124
return (Value >> 1) & 0x3ffffff;
125
case CSKY::fixup_csky_pcrel_imm18_scale2:
126
if (!isIntN(19, Value))
127
Ctx.reportError(Fixup.getLoc(), "out of range pc-relative fixup value.");
128
if (Value & 0x1)
129
Ctx.reportError(Fixup.getLoc(), "fixup value must be 2-byte aligned.");
130
131
return (Value >> 1) & 0x3ffff;
132
case CSKY::fixup_csky_pcrel_uimm8_scale4: {
133
if (!isUIntN(10, Value))
134
Ctx.reportError(Fixup.getLoc(), "out of range pc-relative fixup value.");
135
if (Value & 0x3)
136
Ctx.reportError(Fixup.getLoc(), "fixup value must be 4-byte aligned.");
137
138
unsigned IMM4L = (Value >> 2) & 0xf;
139
unsigned IMM4H = (Value >> 6) & 0xf;
140
141
Value = (IMM4H << 21) | (IMM4L << 4);
142
return Value;
143
}
144
case CSKY::fixup_csky_pcrel_imm10_scale2:
145
if (!isIntN(11, Value))
146
Ctx.reportError(Fixup.getLoc(), "out of range pc-relative fixup value.");
147
if (Value & 0x1)
148
Ctx.reportError(Fixup.getLoc(), "fixup value must be 2-byte aligned.");
149
150
return (Value >> 1) & 0x3ff;
151
case CSKY::fixup_csky_pcrel_uimm7_scale4:
152
if ((Value >> 2) > 0xfe)
153
Ctx.reportError(Fixup.getLoc(), "out of range pc-relative fixup value.");
154
if (Value & 0x3)
155
Ctx.reportError(Fixup.getLoc(), "fixup value must be 4-byte aligned.");
156
157
if ((Value >> 2) <= 0x7f) {
158
unsigned IMM5L = (Value >> 2) & 0x1f;
159
unsigned IMM2H = (Value >> 7) & 0x3;
160
161
Value = (1 << 12) | (IMM2H << 8) | IMM5L;
162
} else {
163
unsigned IMM5L = (~Value >> 2) & 0x1f;
164
unsigned IMM2H = (~Value >> 7) & 0x3;
165
166
Value = (IMM2H << 8) | IMM5L;
167
}
168
169
return Value;
170
}
171
}
172
173
bool CSKYAsmBackend::fixupNeedsRelaxationAdvanced(const MCAssembler &Asm,
174
const MCFixup &Fixup,
175
bool Resolved, uint64_t Value,
176
const MCRelaxableFragment *DF,
177
const bool WasForced) const {
178
// Return true if the symbol is actually unresolved.
179
// Resolved could be always false when shouldForceRelocation return true.
180
// We use !WasForced to indicate that the symbol is unresolved and not forced
181
// by shouldForceRelocation.
182
if (!Resolved && !WasForced)
183
return true;
184
185
int64_t Offset = int64_t(Value);
186
switch (Fixup.getTargetKind()) {
187
default:
188
return false;
189
case CSKY::fixup_csky_pcrel_imm10_scale2:
190
return !isShiftedInt<10, 1>(Offset);
191
case CSKY::fixup_csky_pcrel_imm16_scale2:
192
return !isShiftedInt<16, 1>(Offset);
193
case CSKY::fixup_csky_pcrel_imm26_scale2:
194
return !isShiftedInt<26, 1>(Offset);
195
case CSKY::fixup_csky_pcrel_uimm7_scale4:
196
return ((Value >> 2) > 0xfe) || (Value & 0x3);
197
}
198
}
199
200
void CSKYAsmBackend::applyFixup(const MCAssembler &Asm, const MCFixup &Fixup,
201
const MCValue &Target,
202
MutableArrayRef<char> Data, uint64_t Value,
203
bool IsResolved,
204
const MCSubtargetInfo *STI) const {
205
MCFixupKind Kind = Fixup.getKind();
206
if (Kind >= FirstLiteralRelocationKind)
207
return;
208
MCContext &Ctx = Asm.getContext();
209
MCFixupKindInfo Info = getFixupKindInfo(Kind);
210
if (!Value)
211
return; // Doesn't change encoding.
212
// Apply any target-specific value adjustments.
213
Value = adjustFixupValue(Fixup, Value, Ctx);
214
215
// Shift the value into position.
216
Value <<= Info.TargetOffset;
217
218
unsigned Offset = Fixup.getOffset();
219
unsigned NumBytes = alignTo(Info.TargetSize + Info.TargetOffset, 8) / 8;
220
221
assert(Offset + NumBytes <= Data.size() && "Invalid fixup offset!");
222
223
// For each byte of the fragment that the fixup touches, mask in the
224
// bits from the fixup value.
225
bool IsLittleEndian = (Endian == llvm::endianness::little);
226
bool IsInstFixup = (Kind >= FirstTargetFixupKind);
227
228
if (IsLittleEndian && IsInstFixup && (NumBytes == 4)) {
229
Data[Offset + 0] |= uint8_t((Value >> 16) & 0xff);
230
Data[Offset + 1] |= uint8_t((Value >> 24) & 0xff);
231
Data[Offset + 2] |= uint8_t(Value & 0xff);
232
Data[Offset + 3] |= uint8_t((Value >> 8) & 0xff);
233
} else {
234
for (unsigned I = 0; I != NumBytes; I++) {
235
unsigned Idx = IsLittleEndian ? I : (NumBytes - 1 - I);
236
Data[Offset + Idx] |= uint8_t((Value >> (I * 8)) & 0xff);
237
}
238
}
239
}
240
241
bool CSKYAsmBackend::mayNeedRelaxation(const MCInst &Inst,
242
const MCSubtargetInfo &STI) const {
243
switch (Inst.getOpcode()) {
244
default:
245
return false;
246
case CSKY::JBR32:
247
case CSKY::JBT32:
248
case CSKY::JBF32:
249
case CSKY::JBSR32:
250
if (!STI.hasFeature(CSKY::Has2E3))
251
return false;
252
return true;
253
case CSKY::JBR16:
254
case CSKY::JBT16:
255
case CSKY::JBF16:
256
case CSKY::LRW16:
257
case CSKY::BR16:
258
return true;
259
}
260
}
261
262
bool CSKYAsmBackend::shouldForceRelocation(const MCAssembler &Asm,
263
const MCFixup &Fixup,
264
const MCValue &Target,
265
const MCSubtargetInfo * /*STI*/) {
266
if (Fixup.getKind() >= FirstLiteralRelocationKind)
267
return true;
268
switch (Fixup.getTargetKind()) {
269
default:
270
break;
271
case CSKY::fixup_csky_got32:
272
case CSKY::fixup_csky_got_imm18_scale4:
273
case CSKY::fixup_csky_gotoff:
274
case CSKY::fixup_csky_gotpc:
275
case CSKY::fixup_csky_plt32:
276
case CSKY::fixup_csky_plt_imm18_scale4:
277
case CSKY::fixup_csky_doffset_imm18:
278
case CSKY::fixup_csky_doffset_imm18_scale2:
279
case CSKY::fixup_csky_doffset_imm18_scale4:
280
return true;
281
}
282
283
return false;
284
}
285
286
bool CSKYAsmBackend::fixupNeedsRelaxation(const MCFixup &Fixup,
287
uint64_t Value) const {
288
return false;
289
}
290
291
void CSKYAsmBackend::relaxInstruction(MCInst &Inst,
292
const MCSubtargetInfo &STI) const {
293
MCInst Res;
294
295
switch (Inst.getOpcode()) {
296
default:
297
LLVM_DEBUG(Inst.dump());
298
llvm_unreachable("Opcode not expected!");
299
case CSKY::LRW16:
300
Res.setOpcode(CSKY::LRW32);
301
Res.addOperand(Inst.getOperand(0));
302
Res.addOperand(Inst.getOperand(1));
303
break;
304
case CSKY::BR16:
305
Res.setOpcode(CSKY::BR32);
306
Res.addOperand(Inst.getOperand(0));
307
break;
308
case CSKY::JBSR32:
309
Res.setOpcode(CSKY::JSRI32);
310
Res.addOperand(Inst.getOperand(1));
311
break;
312
case CSKY::JBR32:
313
Res.setOpcode(CSKY::JMPI32);
314
Res.addOperand(Inst.getOperand(1));
315
break;
316
case CSKY::JBT32:
317
case CSKY::JBF32:
318
Res.setOpcode(Inst.getOpcode() == CSKY::JBT32 ? CSKY::JBT_E : CSKY::JBF_E);
319
Res.addOperand(Inst.getOperand(0));
320
Res.addOperand(Inst.getOperand(1));
321
Res.addOperand(Inst.getOperand(2));
322
break;
323
case CSKY::JBR16:
324
Res.setOpcode(CSKY::JBR32);
325
Res.addOperand(Inst.getOperand(0));
326
Res.addOperand(Inst.getOperand(1));
327
break;
328
case CSKY::JBT16:
329
case CSKY::JBF16:
330
// ck801
331
unsigned opcode;
332
if (STI.hasFeature(CSKY::HasE2))
333
opcode = Inst.getOpcode() == CSKY::JBT16 ? CSKY::JBT32 : CSKY::JBF32;
334
else
335
opcode = Inst.getOpcode() == CSKY::JBT16 ? CSKY::JBT_E : CSKY::JBF_E;
336
337
Res.setOpcode(opcode);
338
Res.addOperand(Inst.getOperand(0));
339
Res.addOperand(Inst.getOperand(1));
340
Res.addOperand(Inst.getOperand(2));
341
break;
342
}
343
Inst = std::move(Res);
344
}
345
346
bool CSKYAsmBackend::writeNopData(raw_ostream &OS, uint64_t Count,
347
const MCSubtargetInfo *STI) const {
348
OS.write_zeros(Count);
349
return true;
350
}
351
352
MCAsmBackend *llvm::createCSKYAsmBackend(const Target &T,
353
const MCSubtargetInfo &STI,
354
const MCRegisterInfo &MRI,
355
const MCTargetOptions &Options) {
356
return new CSKYAsmBackend(STI, Options);
357
}
358
359