annotate lld/ELF/Arch/RISCV.cpp @ 192:d7606dcf6fce

Added tag llvm10 for changeset 0572611fdcc8
author Shinji KONO <kono@ie.u-ryukyu.ac.jp>
date Mon, 14 Dec 2020 18:01:34 +0900
parents 0572611fdcc8
children 2e18cbf3894f
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
150
anatofuz
parents:
diff changeset
1 //===- RISCV.cpp ----------------------------------------------------------===//
anatofuz
parents:
diff changeset
2 //
anatofuz
parents:
diff changeset
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
anatofuz
parents:
diff changeset
4 // See https://llvm.org/LICENSE.txt for license information.
anatofuz
parents:
diff changeset
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
anatofuz
parents:
diff changeset
6 //
anatofuz
parents:
diff changeset
7 //===----------------------------------------------------------------------===//
anatofuz
parents:
diff changeset
8
anatofuz
parents:
diff changeset
9 #include "InputFiles.h"
anatofuz
parents:
diff changeset
10 #include "Symbols.h"
anatofuz
parents:
diff changeset
11 #include "SyntheticSections.h"
anatofuz
parents:
diff changeset
12 #include "Target.h"
anatofuz
parents:
diff changeset
13
anatofuz
parents:
diff changeset
14 using namespace llvm;
anatofuz
parents:
diff changeset
15 using namespace llvm::object;
anatofuz
parents:
diff changeset
16 using namespace llvm::support::endian;
anatofuz
parents:
diff changeset
17 using namespace llvm::ELF;
173
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 150
diff changeset
18 using namespace lld;
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 150
diff changeset
19 using namespace lld::elf;
150
anatofuz
parents:
diff changeset
20
anatofuz
parents:
diff changeset
21 namespace {
anatofuz
parents:
diff changeset
22
anatofuz
parents:
diff changeset
23 class RISCV final : public TargetInfo {
anatofuz
parents:
diff changeset
24 public:
anatofuz
parents:
diff changeset
25 RISCV();
anatofuz
parents:
diff changeset
26 uint32_t calcEFlags() const override;
anatofuz
parents:
diff changeset
27 void writeGotHeader(uint8_t *buf) const override;
anatofuz
parents:
diff changeset
28 void writeGotPlt(uint8_t *buf, const Symbol &s) const override;
anatofuz
parents:
diff changeset
29 void writePltHeader(uint8_t *buf) const override;
anatofuz
parents:
diff changeset
30 void writePlt(uint8_t *buf, const Symbol &sym,
anatofuz
parents:
diff changeset
31 uint64_t pltEntryAddr) const override;
anatofuz
parents:
diff changeset
32 RelType getDynRel(RelType type) const override;
anatofuz
parents:
diff changeset
33 RelExpr getRelExpr(RelType type, const Symbol &s,
anatofuz
parents:
diff changeset
34 const uint8_t *loc) const override;
anatofuz
parents:
diff changeset
35 void relocate(uint8_t *loc, const Relocation &rel,
anatofuz
parents:
diff changeset
36 uint64_t val) const override;
anatofuz
parents:
diff changeset
37 };
anatofuz
parents:
diff changeset
38
anatofuz
parents:
diff changeset
39 } // end anonymous namespace
anatofuz
parents:
diff changeset
40
anatofuz
parents:
diff changeset
41 const uint64_t dtpOffset = 0x800;
anatofuz
parents:
diff changeset
42
anatofuz
parents:
diff changeset
43 enum Op {
anatofuz
parents:
diff changeset
44 ADDI = 0x13,
anatofuz
parents:
diff changeset
45 AUIPC = 0x17,
anatofuz
parents:
diff changeset
46 JALR = 0x67,
anatofuz
parents:
diff changeset
47 LD = 0x3003,
anatofuz
parents:
diff changeset
48 LW = 0x2003,
anatofuz
parents:
diff changeset
49 SRLI = 0x5013,
anatofuz
parents:
diff changeset
50 SUB = 0x40000033,
anatofuz
parents:
diff changeset
51 };
anatofuz
parents:
diff changeset
52
anatofuz
parents:
diff changeset
53 enum Reg {
anatofuz
parents:
diff changeset
54 X_RA = 1,
anatofuz
parents:
diff changeset
55 X_T0 = 5,
anatofuz
parents:
diff changeset
56 X_T1 = 6,
anatofuz
parents:
diff changeset
57 X_T2 = 7,
anatofuz
parents:
diff changeset
58 X_T3 = 28,
anatofuz
parents:
diff changeset
59 };
anatofuz
parents:
diff changeset
60
anatofuz
parents:
diff changeset
61 static uint32_t hi20(uint32_t val) { return (val + 0x800) >> 12; }
anatofuz
parents:
diff changeset
62 static uint32_t lo12(uint32_t val) { return val & 4095; }
anatofuz
parents:
diff changeset
63
anatofuz
parents:
diff changeset
64 static uint32_t itype(uint32_t op, uint32_t rd, uint32_t rs1, uint32_t imm) {
anatofuz
parents:
diff changeset
65 return op | (rd << 7) | (rs1 << 15) | (imm << 20);
anatofuz
parents:
diff changeset
66 }
anatofuz
parents:
diff changeset
67 static uint32_t rtype(uint32_t op, uint32_t rd, uint32_t rs1, uint32_t rs2) {
anatofuz
parents:
diff changeset
68 return op | (rd << 7) | (rs1 << 15) | (rs2 << 20);
anatofuz
parents:
diff changeset
69 }
anatofuz
parents:
diff changeset
70 static uint32_t utype(uint32_t op, uint32_t rd, uint32_t imm) {
anatofuz
parents:
diff changeset
71 return op | (rd << 7) | (imm << 12);
anatofuz
parents:
diff changeset
72 }
anatofuz
parents:
diff changeset
73
anatofuz
parents:
diff changeset
74 RISCV::RISCV() {
anatofuz
parents:
diff changeset
75 copyRel = R_RISCV_COPY;
anatofuz
parents:
diff changeset
76 noneRel = R_RISCV_NONE;
anatofuz
parents:
diff changeset
77 pltRel = R_RISCV_JUMP_SLOT;
anatofuz
parents:
diff changeset
78 relativeRel = R_RISCV_RELATIVE;
anatofuz
parents:
diff changeset
79 iRelativeRel = R_RISCV_IRELATIVE;
anatofuz
parents:
diff changeset
80 if (config->is64) {
anatofuz
parents:
diff changeset
81 symbolicRel = R_RISCV_64;
anatofuz
parents:
diff changeset
82 tlsModuleIndexRel = R_RISCV_TLS_DTPMOD64;
anatofuz
parents:
diff changeset
83 tlsOffsetRel = R_RISCV_TLS_DTPREL64;
anatofuz
parents:
diff changeset
84 tlsGotRel = R_RISCV_TLS_TPREL64;
anatofuz
parents:
diff changeset
85 } else {
anatofuz
parents:
diff changeset
86 symbolicRel = R_RISCV_32;
anatofuz
parents:
diff changeset
87 tlsModuleIndexRel = R_RISCV_TLS_DTPMOD32;
anatofuz
parents:
diff changeset
88 tlsOffsetRel = R_RISCV_TLS_DTPREL32;
anatofuz
parents:
diff changeset
89 tlsGotRel = R_RISCV_TLS_TPREL32;
anatofuz
parents:
diff changeset
90 }
anatofuz
parents:
diff changeset
91 gotRel = symbolicRel;
anatofuz
parents:
diff changeset
92
anatofuz
parents:
diff changeset
93 // .got[0] = _DYNAMIC
anatofuz
parents:
diff changeset
94 gotBaseSymInGotPlt = false;
anatofuz
parents:
diff changeset
95 gotHeaderEntriesNum = 1;
anatofuz
parents:
diff changeset
96
anatofuz
parents:
diff changeset
97 // .got.plt[0] = _dl_runtime_resolve, .got.plt[1] = link_map
anatofuz
parents:
diff changeset
98 gotPltHeaderEntriesNum = 2;
anatofuz
parents:
diff changeset
99
anatofuz
parents:
diff changeset
100 pltHeaderSize = 32;
anatofuz
parents:
diff changeset
101 pltEntrySize = 16;
anatofuz
parents:
diff changeset
102 ipltEntrySize = 16;
anatofuz
parents:
diff changeset
103 }
anatofuz
parents:
diff changeset
104
anatofuz
parents:
diff changeset
105 static uint32_t getEFlags(InputFile *f) {
anatofuz
parents:
diff changeset
106 if (config->is64)
anatofuz
parents:
diff changeset
107 return cast<ObjFile<ELF64LE>>(f)->getObj().getHeader()->e_flags;
anatofuz
parents:
diff changeset
108 return cast<ObjFile<ELF32LE>>(f)->getObj().getHeader()->e_flags;
anatofuz
parents:
diff changeset
109 }
anatofuz
parents:
diff changeset
110
anatofuz
parents:
diff changeset
111 uint32_t RISCV::calcEFlags() const {
anatofuz
parents:
diff changeset
112 // If there are only binary input files (from -b binary), use a
anatofuz
parents:
diff changeset
113 // value of 0 for the ELF header flags.
anatofuz
parents:
diff changeset
114 if (objectFiles.empty())
anatofuz
parents:
diff changeset
115 return 0;
anatofuz
parents:
diff changeset
116
anatofuz
parents:
diff changeset
117 uint32_t target = getEFlags(objectFiles.front());
anatofuz
parents:
diff changeset
118
anatofuz
parents:
diff changeset
119 for (InputFile *f : objectFiles) {
anatofuz
parents:
diff changeset
120 uint32_t eflags = getEFlags(f);
anatofuz
parents:
diff changeset
121 if (eflags & EF_RISCV_RVC)
anatofuz
parents:
diff changeset
122 target |= EF_RISCV_RVC;
anatofuz
parents:
diff changeset
123
anatofuz
parents:
diff changeset
124 if ((eflags & EF_RISCV_FLOAT_ABI) != (target & EF_RISCV_FLOAT_ABI))
anatofuz
parents:
diff changeset
125 error(toString(f) +
anatofuz
parents:
diff changeset
126 ": cannot link object files with different floating-point ABI");
anatofuz
parents:
diff changeset
127
anatofuz
parents:
diff changeset
128 if ((eflags & EF_RISCV_RVE) != (target & EF_RISCV_RVE))
anatofuz
parents:
diff changeset
129 error(toString(f) +
anatofuz
parents:
diff changeset
130 ": cannot link object files with different EF_RISCV_RVE");
anatofuz
parents:
diff changeset
131 }
anatofuz
parents:
diff changeset
132
anatofuz
parents:
diff changeset
133 return target;
anatofuz
parents:
diff changeset
134 }
anatofuz
parents:
diff changeset
135
anatofuz
parents:
diff changeset
136 void RISCV::writeGotHeader(uint8_t *buf) const {
anatofuz
parents:
diff changeset
137 if (config->is64)
anatofuz
parents:
diff changeset
138 write64le(buf, mainPart->dynamic->getVA());
anatofuz
parents:
diff changeset
139 else
anatofuz
parents:
diff changeset
140 write32le(buf, mainPart->dynamic->getVA());
anatofuz
parents:
diff changeset
141 }
anatofuz
parents:
diff changeset
142
anatofuz
parents:
diff changeset
143 void RISCV::writeGotPlt(uint8_t *buf, const Symbol &s) const {
anatofuz
parents:
diff changeset
144 if (config->is64)
anatofuz
parents:
diff changeset
145 write64le(buf, in.plt->getVA());
anatofuz
parents:
diff changeset
146 else
anatofuz
parents:
diff changeset
147 write32le(buf, in.plt->getVA());
anatofuz
parents:
diff changeset
148 }
anatofuz
parents:
diff changeset
149
anatofuz
parents:
diff changeset
150 void RISCV::writePltHeader(uint8_t *buf) const {
anatofuz
parents:
diff changeset
151 // 1: auipc t2, %pcrel_hi(.got.plt)
anatofuz
parents:
diff changeset
152 // sub t1, t1, t3
anatofuz
parents:
diff changeset
153 // l[wd] t3, %pcrel_lo(1b)(t2); t3 = _dl_runtime_resolve
anatofuz
parents:
diff changeset
154 // addi t1, t1, -pltHeaderSize-12; t1 = &.plt[i] - &.plt[0]
anatofuz
parents:
diff changeset
155 // addi t0, t2, %pcrel_lo(1b)
anatofuz
parents:
diff changeset
156 // srli t1, t1, (rv64?1:2); t1 = &.got.plt[i] - &.got.plt[0]
anatofuz
parents:
diff changeset
157 // l[wd] t0, Wordsize(t0); t0 = link_map
anatofuz
parents:
diff changeset
158 // jr t3
anatofuz
parents:
diff changeset
159 uint32_t offset = in.gotPlt->getVA() - in.plt->getVA();
anatofuz
parents:
diff changeset
160 uint32_t load = config->is64 ? LD : LW;
anatofuz
parents:
diff changeset
161 write32le(buf + 0, utype(AUIPC, X_T2, hi20(offset)));
anatofuz
parents:
diff changeset
162 write32le(buf + 4, rtype(SUB, X_T1, X_T1, X_T3));
anatofuz
parents:
diff changeset
163 write32le(buf + 8, itype(load, X_T3, X_T2, lo12(offset)));
anatofuz
parents:
diff changeset
164 write32le(buf + 12, itype(ADDI, X_T1, X_T1, -target->pltHeaderSize - 12));
anatofuz
parents:
diff changeset
165 write32le(buf + 16, itype(ADDI, X_T0, X_T2, lo12(offset)));
anatofuz
parents:
diff changeset
166 write32le(buf + 20, itype(SRLI, X_T1, X_T1, config->is64 ? 1 : 2));
anatofuz
parents:
diff changeset
167 write32le(buf + 24, itype(load, X_T0, X_T0, config->wordsize));
anatofuz
parents:
diff changeset
168 write32le(buf + 28, itype(JALR, 0, X_T3, 0));
anatofuz
parents:
diff changeset
169 }
anatofuz
parents:
diff changeset
170
anatofuz
parents:
diff changeset
171 void RISCV::writePlt(uint8_t *buf, const Symbol &sym,
anatofuz
parents:
diff changeset
172 uint64_t pltEntryAddr) const {
anatofuz
parents:
diff changeset
173 // 1: auipc t3, %pcrel_hi(f@.got.plt)
anatofuz
parents:
diff changeset
174 // l[wd] t3, %pcrel_lo(1b)(t3)
anatofuz
parents:
diff changeset
175 // jalr t1, t3
anatofuz
parents:
diff changeset
176 // nop
anatofuz
parents:
diff changeset
177 uint32_t offset = sym.getGotPltVA() - pltEntryAddr;
anatofuz
parents:
diff changeset
178 write32le(buf + 0, utype(AUIPC, X_T3, hi20(offset)));
anatofuz
parents:
diff changeset
179 write32le(buf + 4, itype(config->is64 ? LD : LW, X_T3, X_T3, lo12(offset)));
anatofuz
parents:
diff changeset
180 write32le(buf + 8, itype(JALR, X_T1, X_T3, 0));
anatofuz
parents:
diff changeset
181 write32le(buf + 12, itype(ADDI, 0, 0, 0));
anatofuz
parents:
diff changeset
182 }
anatofuz
parents:
diff changeset
183
anatofuz
parents:
diff changeset
184 RelType RISCV::getDynRel(RelType type) const {
anatofuz
parents:
diff changeset
185 return type == target->symbolicRel ? type
anatofuz
parents:
diff changeset
186 : static_cast<RelType>(R_RISCV_NONE);
anatofuz
parents:
diff changeset
187 }
anatofuz
parents:
diff changeset
188
anatofuz
parents:
diff changeset
189 RelExpr RISCV::getRelExpr(const RelType type, const Symbol &s,
anatofuz
parents:
diff changeset
190 const uint8_t *loc) const {
anatofuz
parents:
diff changeset
191 switch (type) {
anatofuz
parents:
diff changeset
192 case R_RISCV_NONE:
anatofuz
parents:
diff changeset
193 return R_NONE;
anatofuz
parents:
diff changeset
194 case R_RISCV_32:
anatofuz
parents:
diff changeset
195 case R_RISCV_64:
anatofuz
parents:
diff changeset
196 case R_RISCV_HI20:
anatofuz
parents:
diff changeset
197 case R_RISCV_LO12_I:
anatofuz
parents:
diff changeset
198 case R_RISCV_LO12_S:
anatofuz
parents:
diff changeset
199 case R_RISCV_RVC_LUI:
anatofuz
parents:
diff changeset
200 return R_ABS;
anatofuz
parents:
diff changeset
201 case R_RISCV_ADD8:
anatofuz
parents:
diff changeset
202 case R_RISCV_ADD16:
anatofuz
parents:
diff changeset
203 case R_RISCV_ADD32:
anatofuz
parents:
diff changeset
204 case R_RISCV_ADD64:
anatofuz
parents:
diff changeset
205 case R_RISCV_SET6:
anatofuz
parents:
diff changeset
206 case R_RISCV_SET8:
anatofuz
parents:
diff changeset
207 case R_RISCV_SET16:
anatofuz
parents:
diff changeset
208 case R_RISCV_SET32:
anatofuz
parents:
diff changeset
209 case R_RISCV_SUB6:
anatofuz
parents:
diff changeset
210 case R_RISCV_SUB8:
anatofuz
parents:
diff changeset
211 case R_RISCV_SUB16:
anatofuz
parents:
diff changeset
212 case R_RISCV_SUB32:
anatofuz
parents:
diff changeset
213 case R_RISCV_SUB64:
anatofuz
parents:
diff changeset
214 return R_RISCV_ADD;
anatofuz
parents:
diff changeset
215 case R_RISCV_JAL:
anatofuz
parents:
diff changeset
216 case R_RISCV_BRANCH:
anatofuz
parents:
diff changeset
217 case R_RISCV_PCREL_HI20:
anatofuz
parents:
diff changeset
218 case R_RISCV_RVC_BRANCH:
anatofuz
parents:
diff changeset
219 case R_RISCV_RVC_JUMP:
anatofuz
parents:
diff changeset
220 case R_RISCV_32_PCREL:
anatofuz
parents:
diff changeset
221 return R_PC;
anatofuz
parents:
diff changeset
222 case R_RISCV_CALL:
anatofuz
parents:
diff changeset
223 case R_RISCV_CALL_PLT:
anatofuz
parents:
diff changeset
224 return R_PLT_PC;
anatofuz
parents:
diff changeset
225 case R_RISCV_GOT_HI20:
anatofuz
parents:
diff changeset
226 return R_GOT_PC;
anatofuz
parents:
diff changeset
227 case R_RISCV_PCREL_LO12_I:
anatofuz
parents:
diff changeset
228 case R_RISCV_PCREL_LO12_S:
anatofuz
parents:
diff changeset
229 return R_RISCV_PC_INDIRECT;
anatofuz
parents:
diff changeset
230 case R_RISCV_TLS_GD_HI20:
anatofuz
parents:
diff changeset
231 return R_TLSGD_PC;
anatofuz
parents:
diff changeset
232 case R_RISCV_TLS_GOT_HI20:
anatofuz
parents:
diff changeset
233 config->hasStaticTlsModel = true;
anatofuz
parents:
diff changeset
234 return R_GOT_PC;
anatofuz
parents:
diff changeset
235 case R_RISCV_TPREL_HI20:
anatofuz
parents:
diff changeset
236 case R_RISCV_TPREL_LO12_I:
anatofuz
parents:
diff changeset
237 case R_RISCV_TPREL_LO12_S:
anatofuz
parents:
diff changeset
238 return R_TLS;
anatofuz
parents:
diff changeset
239 case R_RISCV_RELAX:
anatofuz
parents:
diff changeset
240 case R_RISCV_TPREL_ADD:
anatofuz
parents:
diff changeset
241 return R_NONE;
anatofuz
parents:
diff changeset
242 case R_RISCV_ALIGN:
anatofuz
parents:
diff changeset
243 // Not just a hint; always padded to the worst-case number of NOPs, so may
anatofuz
parents:
diff changeset
244 // not currently be aligned, and without linker relaxation support we can't
anatofuz
parents:
diff changeset
245 // delete NOPs to realign.
anatofuz
parents:
diff changeset
246 errorOrWarn(getErrorLocation(loc) + "relocation R_RISCV_ALIGN requires "
anatofuz
parents:
diff changeset
247 "unimplemented linker relaxation; recompile with -mno-relax");
anatofuz
parents:
diff changeset
248 return R_NONE;
anatofuz
parents:
diff changeset
249 default:
anatofuz
parents:
diff changeset
250 error(getErrorLocation(loc) + "unknown relocation (" + Twine(type) +
anatofuz
parents:
diff changeset
251 ") against symbol " + toString(s));
anatofuz
parents:
diff changeset
252 return R_NONE;
anatofuz
parents:
diff changeset
253 }
anatofuz
parents:
diff changeset
254 }
anatofuz
parents:
diff changeset
255
anatofuz
parents:
diff changeset
256 // Extract bits V[Begin:End], where range is inclusive, and Begin must be < 63.
anatofuz
parents:
diff changeset
257 static uint32_t extractBits(uint64_t v, uint32_t begin, uint32_t end) {
anatofuz
parents:
diff changeset
258 return (v & ((1ULL << (begin + 1)) - 1)) >> end;
anatofuz
parents:
diff changeset
259 }
anatofuz
parents:
diff changeset
260
anatofuz
parents:
diff changeset
261 void RISCV::relocate(uint8_t *loc, const Relocation &rel, uint64_t val) const {
anatofuz
parents:
diff changeset
262 const unsigned bits = config->wordsize * 8;
anatofuz
parents:
diff changeset
263
anatofuz
parents:
diff changeset
264 switch (rel.type) {
anatofuz
parents:
diff changeset
265 case R_RISCV_32:
anatofuz
parents:
diff changeset
266 write32le(loc, val);
anatofuz
parents:
diff changeset
267 return;
anatofuz
parents:
diff changeset
268 case R_RISCV_64:
anatofuz
parents:
diff changeset
269 write64le(loc, val);
anatofuz
parents:
diff changeset
270 return;
anatofuz
parents:
diff changeset
271
anatofuz
parents:
diff changeset
272 case R_RISCV_RVC_BRANCH: {
anatofuz
parents:
diff changeset
273 checkInt(loc, static_cast<int64_t>(val) >> 1, 8, rel);
anatofuz
parents:
diff changeset
274 checkAlignment(loc, val, 2, rel);
anatofuz
parents:
diff changeset
275 uint16_t insn = read16le(loc) & 0xE383;
anatofuz
parents:
diff changeset
276 uint16_t imm8 = extractBits(val, 8, 8) << 12;
anatofuz
parents:
diff changeset
277 uint16_t imm4_3 = extractBits(val, 4, 3) << 10;
anatofuz
parents:
diff changeset
278 uint16_t imm7_6 = extractBits(val, 7, 6) << 5;
anatofuz
parents:
diff changeset
279 uint16_t imm2_1 = extractBits(val, 2, 1) << 3;
anatofuz
parents:
diff changeset
280 uint16_t imm5 = extractBits(val, 5, 5) << 2;
anatofuz
parents:
diff changeset
281 insn |= imm8 | imm4_3 | imm7_6 | imm2_1 | imm5;
anatofuz
parents:
diff changeset
282
anatofuz
parents:
diff changeset
283 write16le(loc, insn);
anatofuz
parents:
diff changeset
284 return;
anatofuz
parents:
diff changeset
285 }
anatofuz
parents:
diff changeset
286
anatofuz
parents:
diff changeset
287 case R_RISCV_RVC_JUMP: {
anatofuz
parents:
diff changeset
288 checkInt(loc, static_cast<int64_t>(val) >> 1, 11, rel);
anatofuz
parents:
diff changeset
289 checkAlignment(loc, val, 2, rel);
anatofuz
parents:
diff changeset
290 uint16_t insn = read16le(loc) & 0xE003;
anatofuz
parents:
diff changeset
291 uint16_t imm11 = extractBits(val, 11, 11) << 12;
anatofuz
parents:
diff changeset
292 uint16_t imm4 = extractBits(val, 4, 4) << 11;
anatofuz
parents:
diff changeset
293 uint16_t imm9_8 = extractBits(val, 9, 8) << 9;
anatofuz
parents:
diff changeset
294 uint16_t imm10 = extractBits(val, 10, 10) << 8;
anatofuz
parents:
diff changeset
295 uint16_t imm6 = extractBits(val, 6, 6) << 7;
anatofuz
parents:
diff changeset
296 uint16_t imm7 = extractBits(val, 7, 7) << 6;
anatofuz
parents:
diff changeset
297 uint16_t imm3_1 = extractBits(val, 3, 1) << 3;
anatofuz
parents:
diff changeset
298 uint16_t imm5 = extractBits(val, 5, 5) << 2;
anatofuz
parents:
diff changeset
299 insn |= imm11 | imm4 | imm9_8 | imm10 | imm6 | imm7 | imm3_1 | imm5;
anatofuz
parents:
diff changeset
300
anatofuz
parents:
diff changeset
301 write16le(loc, insn);
anatofuz
parents:
diff changeset
302 return;
anatofuz
parents:
diff changeset
303 }
anatofuz
parents:
diff changeset
304
anatofuz
parents:
diff changeset
305 case R_RISCV_RVC_LUI: {
anatofuz
parents:
diff changeset
306 int64_t imm = SignExtend64(val + 0x800, bits) >> 12;
anatofuz
parents:
diff changeset
307 checkInt(loc, imm, 6, rel);
anatofuz
parents:
diff changeset
308 if (imm == 0) { // `c.lui rd, 0` is illegal, convert to `c.li rd, 0`
anatofuz
parents:
diff changeset
309 write16le(loc, (read16le(loc) & 0x0F83) | 0x4000);
anatofuz
parents:
diff changeset
310 } else {
anatofuz
parents:
diff changeset
311 uint16_t imm17 = extractBits(val + 0x800, 17, 17) << 12;
anatofuz
parents:
diff changeset
312 uint16_t imm16_12 = extractBits(val + 0x800, 16, 12) << 2;
anatofuz
parents:
diff changeset
313 write16le(loc, (read16le(loc) & 0xEF83) | imm17 | imm16_12);
anatofuz
parents:
diff changeset
314 }
anatofuz
parents:
diff changeset
315 return;
anatofuz
parents:
diff changeset
316 }
anatofuz
parents:
diff changeset
317
anatofuz
parents:
diff changeset
318 case R_RISCV_JAL: {
anatofuz
parents:
diff changeset
319 checkInt(loc, static_cast<int64_t>(val) >> 1, 20, rel);
anatofuz
parents:
diff changeset
320 checkAlignment(loc, val, 2, rel);
anatofuz
parents:
diff changeset
321
anatofuz
parents:
diff changeset
322 uint32_t insn = read32le(loc) & 0xFFF;
anatofuz
parents:
diff changeset
323 uint32_t imm20 = extractBits(val, 20, 20) << 31;
anatofuz
parents:
diff changeset
324 uint32_t imm10_1 = extractBits(val, 10, 1) << 21;
anatofuz
parents:
diff changeset
325 uint32_t imm11 = extractBits(val, 11, 11) << 20;
anatofuz
parents:
diff changeset
326 uint32_t imm19_12 = extractBits(val, 19, 12) << 12;
anatofuz
parents:
diff changeset
327 insn |= imm20 | imm10_1 | imm11 | imm19_12;
anatofuz
parents:
diff changeset
328
anatofuz
parents:
diff changeset
329 write32le(loc, insn);
anatofuz
parents:
diff changeset
330 return;
anatofuz
parents:
diff changeset
331 }
anatofuz
parents:
diff changeset
332
anatofuz
parents:
diff changeset
333 case R_RISCV_BRANCH: {
anatofuz
parents:
diff changeset
334 checkInt(loc, static_cast<int64_t>(val) >> 1, 12, rel);
anatofuz
parents:
diff changeset
335 checkAlignment(loc, val, 2, rel);
anatofuz
parents:
diff changeset
336
anatofuz
parents:
diff changeset
337 uint32_t insn = read32le(loc) & 0x1FFF07F;
anatofuz
parents:
diff changeset
338 uint32_t imm12 = extractBits(val, 12, 12) << 31;
anatofuz
parents:
diff changeset
339 uint32_t imm10_5 = extractBits(val, 10, 5) << 25;
anatofuz
parents:
diff changeset
340 uint32_t imm4_1 = extractBits(val, 4, 1) << 8;
anatofuz
parents:
diff changeset
341 uint32_t imm11 = extractBits(val, 11, 11) << 7;
anatofuz
parents:
diff changeset
342 insn |= imm12 | imm10_5 | imm4_1 | imm11;
anatofuz
parents:
diff changeset
343
anatofuz
parents:
diff changeset
344 write32le(loc, insn);
anatofuz
parents:
diff changeset
345 return;
anatofuz
parents:
diff changeset
346 }
anatofuz
parents:
diff changeset
347
anatofuz
parents:
diff changeset
348 // auipc + jalr pair
anatofuz
parents:
diff changeset
349 case R_RISCV_CALL:
anatofuz
parents:
diff changeset
350 case R_RISCV_CALL_PLT: {
anatofuz
parents:
diff changeset
351 int64_t hi = SignExtend64(val + 0x800, bits) >> 12;
anatofuz
parents:
diff changeset
352 checkInt(loc, hi, 20, rel);
anatofuz
parents:
diff changeset
353 if (isInt<20>(hi)) {
anatofuz
parents:
diff changeset
354 relocateNoSym(loc, R_RISCV_PCREL_HI20, val);
anatofuz
parents:
diff changeset
355 relocateNoSym(loc + 4, R_RISCV_PCREL_LO12_I, val);
anatofuz
parents:
diff changeset
356 }
anatofuz
parents:
diff changeset
357 return;
anatofuz
parents:
diff changeset
358 }
anatofuz
parents:
diff changeset
359
anatofuz
parents:
diff changeset
360 case R_RISCV_GOT_HI20:
anatofuz
parents:
diff changeset
361 case R_RISCV_PCREL_HI20:
anatofuz
parents:
diff changeset
362 case R_RISCV_TLS_GD_HI20:
anatofuz
parents:
diff changeset
363 case R_RISCV_TLS_GOT_HI20:
anatofuz
parents:
diff changeset
364 case R_RISCV_TPREL_HI20:
anatofuz
parents:
diff changeset
365 case R_RISCV_HI20: {
anatofuz
parents:
diff changeset
366 uint64_t hi = val + 0x800;
anatofuz
parents:
diff changeset
367 checkInt(loc, SignExtend64(hi, bits) >> 12, 20, rel);
anatofuz
parents:
diff changeset
368 write32le(loc, (read32le(loc) & 0xFFF) | (hi & 0xFFFFF000));
anatofuz
parents:
diff changeset
369 return;
anatofuz
parents:
diff changeset
370 }
anatofuz
parents:
diff changeset
371
anatofuz
parents:
diff changeset
372 case R_RISCV_PCREL_LO12_I:
anatofuz
parents:
diff changeset
373 case R_RISCV_TPREL_LO12_I:
anatofuz
parents:
diff changeset
374 case R_RISCV_LO12_I: {
anatofuz
parents:
diff changeset
375 uint64_t hi = (val + 0x800) >> 12;
anatofuz
parents:
diff changeset
376 uint64_t lo = val - (hi << 12);
anatofuz
parents:
diff changeset
377 write32le(loc, (read32le(loc) & 0xFFFFF) | ((lo & 0xFFF) << 20));
anatofuz
parents:
diff changeset
378 return;
anatofuz
parents:
diff changeset
379 }
anatofuz
parents:
diff changeset
380
anatofuz
parents:
diff changeset
381 case R_RISCV_PCREL_LO12_S:
anatofuz
parents:
diff changeset
382 case R_RISCV_TPREL_LO12_S:
anatofuz
parents:
diff changeset
383 case R_RISCV_LO12_S: {
anatofuz
parents:
diff changeset
384 uint64_t hi = (val + 0x800) >> 12;
anatofuz
parents:
diff changeset
385 uint64_t lo = val - (hi << 12);
anatofuz
parents:
diff changeset
386 uint32_t imm11_5 = extractBits(lo, 11, 5) << 25;
anatofuz
parents:
diff changeset
387 uint32_t imm4_0 = extractBits(lo, 4, 0) << 7;
anatofuz
parents:
diff changeset
388 write32le(loc, (read32le(loc) & 0x1FFF07F) | imm11_5 | imm4_0);
anatofuz
parents:
diff changeset
389 return;
anatofuz
parents:
diff changeset
390 }
anatofuz
parents:
diff changeset
391
anatofuz
parents:
diff changeset
392 case R_RISCV_ADD8:
anatofuz
parents:
diff changeset
393 *loc += val;
anatofuz
parents:
diff changeset
394 return;
anatofuz
parents:
diff changeset
395 case R_RISCV_ADD16:
anatofuz
parents:
diff changeset
396 write16le(loc, read16le(loc) + val);
anatofuz
parents:
diff changeset
397 return;
anatofuz
parents:
diff changeset
398 case R_RISCV_ADD32:
anatofuz
parents:
diff changeset
399 write32le(loc, read32le(loc) + val);
anatofuz
parents:
diff changeset
400 return;
anatofuz
parents:
diff changeset
401 case R_RISCV_ADD64:
anatofuz
parents:
diff changeset
402 write64le(loc, read64le(loc) + val);
anatofuz
parents:
diff changeset
403 return;
anatofuz
parents:
diff changeset
404 case R_RISCV_SUB6:
anatofuz
parents:
diff changeset
405 *loc = (*loc & 0xc0) | (((*loc & 0x3f) - val) & 0x3f);
anatofuz
parents:
diff changeset
406 return;
anatofuz
parents:
diff changeset
407 case R_RISCV_SUB8:
anatofuz
parents:
diff changeset
408 *loc -= val;
anatofuz
parents:
diff changeset
409 return;
anatofuz
parents:
diff changeset
410 case R_RISCV_SUB16:
anatofuz
parents:
diff changeset
411 write16le(loc, read16le(loc) - val);
anatofuz
parents:
diff changeset
412 return;
anatofuz
parents:
diff changeset
413 case R_RISCV_SUB32:
anatofuz
parents:
diff changeset
414 write32le(loc, read32le(loc) - val);
anatofuz
parents:
diff changeset
415 return;
anatofuz
parents:
diff changeset
416 case R_RISCV_SUB64:
anatofuz
parents:
diff changeset
417 write64le(loc, read64le(loc) - val);
anatofuz
parents:
diff changeset
418 return;
anatofuz
parents:
diff changeset
419 case R_RISCV_SET6:
anatofuz
parents:
diff changeset
420 *loc = (*loc & 0xc0) | (val & 0x3f);
anatofuz
parents:
diff changeset
421 return;
anatofuz
parents:
diff changeset
422 case R_RISCV_SET8:
anatofuz
parents:
diff changeset
423 *loc = val;
anatofuz
parents:
diff changeset
424 return;
anatofuz
parents:
diff changeset
425 case R_RISCV_SET16:
anatofuz
parents:
diff changeset
426 write16le(loc, val);
anatofuz
parents:
diff changeset
427 return;
anatofuz
parents:
diff changeset
428 case R_RISCV_SET32:
anatofuz
parents:
diff changeset
429 case R_RISCV_32_PCREL:
anatofuz
parents:
diff changeset
430 write32le(loc, val);
anatofuz
parents:
diff changeset
431 return;
anatofuz
parents:
diff changeset
432
anatofuz
parents:
diff changeset
433 case R_RISCV_TLS_DTPREL32:
anatofuz
parents:
diff changeset
434 write32le(loc, val - dtpOffset);
anatofuz
parents:
diff changeset
435 break;
anatofuz
parents:
diff changeset
436 case R_RISCV_TLS_DTPREL64:
anatofuz
parents:
diff changeset
437 write64le(loc, val - dtpOffset);
anatofuz
parents:
diff changeset
438 break;
anatofuz
parents:
diff changeset
439
anatofuz
parents:
diff changeset
440 case R_RISCV_RELAX:
anatofuz
parents:
diff changeset
441 return; // Ignored (for now)
anatofuz
parents:
diff changeset
442
anatofuz
parents:
diff changeset
443 default:
anatofuz
parents:
diff changeset
444 llvm_unreachable("unknown relocation");
anatofuz
parents:
diff changeset
445 }
anatofuz
parents:
diff changeset
446 }
anatofuz
parents:
diff changeset
447
173
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 150
diff changeset
448 TargetInfo *elf::getRISCVTargetInfo() {
150
anatofuz
parents:
diff changeset
449 static RISCV target;
anatofuz
parents:
diff changeset
450 return &target;
anatofuz
parents:
diff changeset
451 }