elfxx-riscv.c revision 1.1.1.3 1 1.1 christos /* RISC-V-specific support for ELF.
2 1.1.1.3 christos Copyright (C) 2011-2020 Free Software Foundation, Inc.
3 1.1 christos
4 1.1 christos Contributed by Andrew Waterman (andrew (at) sifive.com).
5 1.1 christos Based on TILE-Gx and MIPS targets.
6 1.1 christos
7 1.1 christos This file is part of BFD, the Binary File Descriptor library.
8 1.1 christos
9 1.1 christos This program is free software; you can redistribute it and/or modify
10 1.1 christos it under the terms of the GNU General Public License as published by
11 1.1 christos the Free Software Foundation; either version 3 of the License, or
12 1.1 christos (at your option) any later version.
13 1.1 christos
14 1.1 christos This program is distributed in the hope that it will be useful,
15 1.1 christos but WITHOUT ANY WARRANTY; without even the implied warranty of
16 1.1 christos MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 1.1 christos GNU General Public License for more details.
18 1.1 christos
19 1.1 christos You should have received a copy of the GNU General Public License
20 1.1 christos along with this program; see the file COPYING3. If not,
21 1.1 christos see <http://www.gnu.org/licenses/>. */
22 1.1 christos
23 1.1 christos #include "sysdep.h"
24 1.1 christos #include "bfd.h"
25 1.1 christos #include "libbfd.h"
26 1.1 christos #include "elf-bfd.h"
27 1.1 christos #include "elf/riscv.h"
28 1.1 christos #include "libiberty.h"
29 1.1 christos #include "elfxx-riscv.h"
30 1.1.1.2 christos #include "safe-ctype.h"
31 1.1 christos
32 1.1 christos #define MINUS_ONE ((bfd_vma)0 - 1)
33 1.1 christos
34 1.1.1.2 christos /* Special handler for ADD/SUB relocations that allows them to be filled out
35 1.1.1.2 christos both in the pre-linked and post-linked file. This is necessary to make
36 1.1.1.2 christos pre-linked debug info work, as due to linker relaxations we need to emit
37 1.1.1.2 christos relocations for the debug info. */
38 1.1.1.2 christos static bfd_reloc_status_type riscv_elf_add_sub_reloc
39 1.1.1.2 christos (bfd *, arelent *, asymbol *, void *, asection *, bfd *, char **);
40 1.1.1.2 christos
41 1.1 christos /* The relocation table used for SHT_RELA sections. */
42 1.1 christos
43 1.1 christos static reloc_howto_type howto_table[] =
44 1.1 christos {
45 1.1 christos /* No relocation. */
46 1.1 christos HOWTO (R_RISCV_NONE, /* type */
47 1.1 christos 0, /* rightshift */
48 1.1 christos 3, /* size */
49 1.1 christos 0, /* bitsize */
50 1.1 christos FALSE, /* pc_relative */
51 1.1 christos 0, /* bitpos */
52 1.1 christos complain_overflow_dont, /* complain_on_overflow */
53 1.1 christos bfd_elf_generic_reloc, /* special_function */
54 1.1 christos "R_RISCV_NONE", /* name */
55 1.1 christos FALSE, /* partial_inplace */
56 1.1 christos 0, /* src_mask */
57 1.1 christos 0, /* dst_mask */
58 1.1 christos FALSE), /* pcrel_offset */
59 1.1 christos
60 1.1 christos /* 32 bit relocation. */
61 1.1 christos HOWTO (R_RISCV_32, /* type */
62 1.1 christos 0, /* rightshift */
63 1.1 christos 2, /* size */
64 1.1 christos 32, /* bitsize */
65 1.1 christos FALSE, /* pc_relative */
66 1.1 christos 0, /* bitpos */
67 1.1 christos complain_overflow_dont, /* complain_on_overflow */
68 1.1 christos bfd_elf_generic_reloc, /* special_function */
69 1.1 christos "R_RISCV_32", /* name */
70 1.1 christos FALSE, /* partial_inplace */
71 1.1 christos 0, /* src_mask */
72 1.1 christos MINUS_ONE, /* dst_mask */
73 1.1 christos FALSE), /* pcrel_offset */
74 1.1 christos
75 1.1 christos /* 64 bit relocation. */
76 1.1 christos HOWTO (R_RISCV_64, /* type */
77 1.1 christos 0, /* rightshift */
78 1.1 christos 4, /* size */
79 1.1 christos 64, /* bitsize */
80 1.1 christos FALSE, /* pc_relative */
81 1.1 christos 0, /* bitpos */
82 1.1 christos complain_overflow_dont, /* complain_on_overflow */
83 1.1 christos bfd_elf_generic_reloc, /* special_function */
84 1.1 christos "R_RISCV_64", /* name */
85 1.1 christos FALSE, /* partial_inplace */
86 1.1 christos 0, /* src_mask */
87 1.1 christos MINUS_ONE, /* dst_mask */
88 1.1 christos FALSE), /* pcrel_offset */
89 1.1 christos
90 1.1 christos /* Relocation against a local symbol in a shared object. */
91 1.1 christos HOWTO (R_RISCV_RELATIVE, /* type */
92 1.1 christos 0, /* rightshift */
93 1.1 christos 2, /* size */
94 1.1 christos 32, /* bitsize */
95 1.1 christos FALSE, /* pc_relative */
96 1.1 christos 0, /* bitpos */
97 1.1 christos complain_overflow_dont, /* complain_on_overflow */
98 1.1 christos bfd_elf_generic_reloc, /* special_function */
99 1.1 christos "R_RISCV_RELATIVE", /* name */
100 1.1 christos FALSE, /* partial_inplace */
101 1.1 christos 0, /* src_mask */
102 1.1 christos MINUS_ONE, /* dst_mask */
103 1.1 christos FALSE), /* pcrel_offset */
104 1.1 christos
105 1.1 christos HOWTO (R_RISCV_COPY, /* type */
106 1.1 christos 0, /* rightshift */
107 1.1 christos 0, /* this one is variable size */
108 1.1 christos 0, /* bitsize */
109 1.1 christos FALSE, /* pc_relative */
110 1.1 christos 0, /* bitpos */
111 1.1 christos complain_overflow_bitfield, /* complain_on_overflow */
112 1.1 christos bfd_elf_generic_reloc, /* special_function */
113 1.1 christos "R_RISCV_COPY", /* name */
114 1.1 christos FALSE, /* partial_inplace */
115 1.1.1.2 christos 0, /* src_mask */
116 1.1.1.2 christos 0, /* dst_mask */
117 1.1 christos FALSE), /* pcrel_offset */
118 1.1 christos
119 1.1 christos HOWTO (R_RISCV_JUMP_SLOT, /* type */
120 1.1 christos 0, /* rightshift */
121 1.1 christos 4, /* size */
122 1.1 christos 64, /* bitsize */
123 1.1 christos FALSE, /* pc_relative */
124 1.1 christos 0, /* bitpos */
125 1.1 christos complain_overflow_bitfield, /* complain_on_overflow */
126 1.1 christos bfd_elf_generic_reloc, /* special_function */
127 1.1 christos "R_RISCV_JUMP_SLOT", /* name */
128 1.1 christos FALSE, /* partial_inplace */
129 1.1.1.2 christos 0, /* src_mask */
130 1.1.1.2 christos 0, /* dst_mask */
131 1.1 christos FALSE), /* pcrel_offset */
132 1.1 christos
133 1.1 christos /* Dynamic TLS relocations. */
134 1.1 christos HOWTO (R_RISCV_TLS_DTPMOD32, /* type */
135 1.1 christos 0, /* rightshift */
136 1.1 christos 4, /* size */
137 1.1 christos 32, /* bitsize */
138 1.1 christos FALSE, /* pc_relative */
139 1.1 christos 0, /* bitpos */
140 1.1 christos complain_overflow_dont, /* complain_on_overflow */
141 1.1.1.2 christos bfd_elf_generic_reloc, /* special_function */
142 1.1 christos "R_RISCV_TLS_DTPMOD32", /* name */
143 1.1 christos FALSE, /* partial_inplace */
144 1.1 christos 0, /* src_mask */
145 1.1 christos MINUS_ONE, /* dst_mask */
146 1.1 christos FALSE), /* pcrel_offset */
147 1.1 christos
148 1.1 christos HOWTO (R_RISCV_TLS_DTPMOD64, /* type */
149 1.1 christos 0, /* rightshift */
150 1.1 christos 4, /* size */
151 1.1 christos 64, /* bitsize */
152 1.1 christos FALSE, /* pc_relative */
153 1.1 christos 0, /* bitpos */
154 1.1 christos complain_overflow_dont, /* complain_on_overflow */
155 1.1.1.2 christos bfd_elf_generic_reloc, /* special_function */
156 1.1 christos "R_RISCV_TLS_DTPMOD64", /* name */
157 1.1 christos FALSE, /* partial_inplace */
158 1.1 christos 0, /* src_mask */
159 1.1 christos MINUS_ONE, /* dst_mask */
160 1.1 christos FALSE), /* pcrel_offset */
161 1.1 christos
162 1.1 christos HOWTO (R_RISCV_TLS_DTPREL32, /* type */
163 1.1 christos 0, /* rightshift */
164 1.1 christos 4, /* size */
165 1.1 christos 32, /* bitsize */
166 1.1 christos FALSE, /* pc_relative */
167 1.1 christos 0, /* bitpos */
168 1.1 christos complain_overflow_dont, /* complain_on_overflow */
169 1.1.1.2 christos bfd_elf_generic_reloc, /* special_function */
170 1.1 christos "R_RISCV_TLS_DTPREL32", /* name */
171 1.1 christos TRUE, /* partial_inplace */
172 1.1 christos 0, /* src_mask */
173 1.1 christos MINUS_ONE, /* dst_mask */
174 1.1 christos FALSE), /* pcrel_offset */
175 1.1 christos
176 1.1 christos HOWTO (R_RISCV_TLS_DTPREL64, /* type */
177 1.1 christos 0, /* rightshift */
178 1.1 christos 4, /* size */
179 1.1 christos 64, /* bitsize */
180 1.1 christos FALSE, /* pc_relative */
181 1.1 christos 0, /* bitpos */
182 1.1 christos complain_overflow_dont, /* complain_on_overflow */
183 1.1.1.2 christos bfd_elf_generic_reloc, /* special_function */
184 1.1 christos "R_RISCV_TLS_DTPREL64", /* name */
185 1.1 christos TRUE, /* partial_inplace */
186 1.1 christos 0, /* src_mask */
187 1.1 christos MINUS_ONE, /* dst_mask */
188 1.1 christos FALSE), /* pcrel_offset */
189 1.1 christos
190 1.1 christos HOWTO (R_RISCV_TLS_TPREL32, /* type */
191 1.1 christos 0, /* rightshift */
192 1.1 christos 2, /* size */
193 1.1 christos 32, /* bitsize */
194 1.1 christos FALSE, /* pc_relative */
195 1.1 christos 0, /* bitpos */
196 1.1 christos complain_overflow_dont, /* complain_on_overflow */
197 1.1.1.2 christos bfd_elf_generic_reloc, /* special_function */
198 1.1 christos "R_RISCV_TLS_TPREL32", /* name */
199 1.1 christos FALSE, /* partial_inplace */
200 1.1 christos 0, /* src_mask */
201 1.1 christos MINUS_ONE, /* dst_mask */
202 1.1 christos FALSE), /* pcrel_offset */
203 1.1 christos
204 1.1 christos HOWTO (R_RISCV_TLS_TPREL64, /* type */
205 1.1 christos 0, /* rightshift */
206 1.1 christos 4, /* size */
207 1.1 christos 64, /* bitsize */
208 1.1 christos FALSE, /* pc_relative */
209 1.1 christos 0, /* bitpos */
210 1.1 christos complain_overflow_dont, /* complain_on_overflow */
211 1.1.1.2 christos bfd_elf_generic_reloc, /* special_function */
212 1.1 christos "R_RISCV_TLS_TPREL64", /* name */
213 1.1 christos FALSE, /* partial_inplace */
214 1.1 christos 0, /* src_mask */
215 1.1 christos MINUS_ONE, /* dst_mask */
216 1.1 christos FALSE), /* pcrel_offset */
217 1.1 christos
218 1.1 christos /* Reserved for future relocs that the dynamic linker must understand. */
219 1.1 christos EMPTY_HOWTO (12),
220 1.1 christos EMPTY_HOWTO (13),
221 1.1 christos EMPTY_HOWTO (14),
222 1.1 christos EMPTY_HOWTO (15),
223 1.1 christos
224 1.1 christos /* 12-bit PC-relative branch offset. */
225 1.1 christos HOWTO (R_RISCV_BRANCH, /* type */
226 1.1 christos 0, /* rightshift */
227 1.1 christos 2, /* size */
228 1.1 christos 32, /* bitsize */
229 1.1 christos TRUE, /* pc_relative */
230 1.1 christos 0, /* bitpos */
231 1.1 christos complain_overflow_signed, /* complain_on_overflow */
232 1.1 christos bfd_elf_generic_reloc, /* special_function */
233 1.1 christos "R_RISCV_BRANCH", /* name */
234 1.1 christos FALSE, /* partial_inplace */
235 1.1 christos 0, /* src_mask */
236 1.1 christos ENCODE_SBTYPE_IMM (-1U), /* dst_mask */
237 1.1 christos TRUE), /* pcrel_offset */
238 1.1 christos
239 1.1 christos /* 20-bit PC-relative jump offset. */
240 1.1 christos HOWTO (R_RISCV_JAL, /* type */
241 1.1 christos 0, /* rightshift */
242 1.1 christos 2, /* size */
243 1.1 christos 32, /* bitsize */
244 1.1 christos TRUE, /* pc_relative */
245 1.1 christos 0, /* bitpos */
246 1.1 christos complain_overflow_dont, /* complain_on_overflow */
247 1.1 christos bfd_elf_generic_reloc, /* special_function */
248 1.1 christos "R_RISCV_JAL", /* name */
249 1.1 christos FALSE, /* partial_inplace */
250 1.1 christos 0, /* src_mask */
251 1.1 christos ENCODE_UJTYPE_IMM (-1U), /* dst_mask */
252 1.1 christos TRUE), /* pcrel_offset */
253 1.1 christos
254 1.1 christos /* 32-bit PC-relative function call (AUIPC/JALR). */
255 1.1 christos HOWTO (R_RISCV_CALL, /* type */
256 1.1 christos 0, /* rightshift */
257 1.1 christos 2, /* size */
258 1.1 christos 64, /* bitsize */
259 1.1 christos TRUE, /* pc_relative */
260 1.1 christos 0, /* bitpos */
261 1.1 christos complain_overflow_dont, /* complain_on_overflow */
262 1.1 christos bfd_elf_generic_reloc, /* special_function */
263 1.1 christos "R_RISCV_CALL", /* name */
264 1.1 christos FALSE, /* partial_inplace */
265 1.1 christos 0, /* src_mask */
266 1.1 christos ENCODE_UTYPE_IMM (-1U) | ((bfd_vma) ENCODE_ITYPE_IMM (-1U) << 32),
267 1.1 christos /* dst_mask */
268 1.1 christos TRUE), /* pcrel_offset */
269 1.1 christos
270 1.1 christos /* Like R_RISCV_CALL, but not locally binding. */
271 1.1 christos HOWTO (R_RISCV_CALL_PLT, /* type */
272 1.1 christos 0, /* rightshift */
273 1.1 christos 2, /* size */
274 1.1 christos 64, /* bitsize */
275 1.1 christos TRUE, /* pc_relative */
276 1.1 christos 0, /* bitpos */
277 1.1 christos complain_overflow_dont, /* complain_on_overflow */
278 1.1 christos bfd_elf_generic_reloc, /* special_function */
279 1.1 christos "R_RISCV_CALL_PLT", /* name */
280 1.1 christos FALSE, /* partial_inplace */
281 1.1 christos 0, /* src_mask */
282 1.1 christos ENCODE_UTYPE_IMM (-1U) | ((bfd_vma) ENCODE_ITYPE_IMM (-1U) << 32),
283 1.1 christos /* dst_mask */
284 1.1 christos TRUE), /* pcrel_offset */
285 1.1 christos
286 1.1 christos /* High 20 bits of 32-bit PC-relative GOT access. */
287 1.1 christos HOWTO (R_RISCV_GOT_HI20, /* type */
288 1.1 christos 0, /* rightshift */
289 1.1 christos 2, /* size */
290 1.1 christos 32, /* bitsize */
291 1.1 christos TRUE, /* pc_relative */
292 1.1 christos 0, /* bitpos */
293 1.1 christos complain_overflow_dont, /* complain_on_overflow */
294 1.1 christos bfd_elf_generic_reloc, /* special_function */
295 1.1 christos "R_RISCV_GOT_HI20", /* name */
296 1.1 christos FALSE, /* partial_inplace */
297 1.1 christos 0, /* src_mask */
298 1.1 christos ENCODE_UTYPE_IMM (-1U), /* dst_mask */
299 1.1 christos FALSE), /* pcrel_offset */
300 1.1 christos
301 1.1 christos /* High 20 bits of 32-bit PC-relative TLS IE GOT access. */
302 1.1 christos HOWTO (R_RISCV_TLS_GOT_HI20, /* type */
303 1.1 christos 0, /* rightshift */
304 1.1 christos 2, /* size */
305 1.1 christos 32, /* bitsize */
306 1.1 christos TRUE, /* pc_relative */
307 1.1 christos 0, /* bitpos */
308 1.1 christos complain_overflow_dont, /* complain_on_overflow */
309 1.1 christos bfd_elf_generic_reloc, /* special_function */
310 1.1 christos "R_RISCV_TLS_GOT_HI20", /* name */
311 1.1 christos FALSE, /* partial_inplace */
312 1.1 christos 0, /* src_mask */
313 1.1 christos ENCODE_UTYPE_IMM (-1U), /* dst_mask */
314 1.1 christos FALSE), /* pcrel_offset */
315 1.1 christos
316 1.1 christos /* High 20 bits of 32-bit PC-relative TLS GD GOT reference. */
317 1.1 christos HOWTO (R_RISCV_TLS_GD_HI20, /* type */
318 1.1 christos 0, /* rightshift */
319 1.1 christos 2, /* size */
320 1.1 christos 32, /* bitsize */
321 1.1 christos TRUE, /* pc_relative */
322 1.1 christos 0, /* bitpos */
323 1.1 christos complain_overflow_dont, /* complain_on_overflow */
324 1.1 christos bfd_elf_generic_reloc, /* special_function */
325 1.1 christos "R_RISCV_TLS_GD_HI20", /* name */
326 1.1 christos FALSE, /* partial_inplace */
327 1.1 christos 0, /* src_mask */
328 1.1 christos ENCODE_UTYPE_IMM (-1U), /* dst_mask */
329 1.1 christos FALSE), /* pcrel_offset */
330 1.1 christos
331 1.1 christos /* High 20 bits of 32-bit PC-relative reference. */
332 1.1 christos HOWTO (R_RISCV_PCREL_HI20, /* type */
333 1.1 christos 0, /* rightshift */
334 1.1 christos 2, /* size */
335 1.1 christos 32, /* bitsize */
336 1.1 christos TRUE, /* pc_relative */
337 1.1 christos 0, /* bitpos */
338 1.1 christos complain_overflow_dont, /* complain_on_overflow */
339 1.1 christos bfd_elf_generic_reloc, /* special_function */
340 1.1 christos "R_RISCV_PCREL_HI20", /* name */
341 1.1 christos FALSE, /* partial_inplace */
342 1.1 christos 0, /* src_mask */
343 1.1 christos ENCODE_UTYPE_IMM (-1U), /* dst_mask */
344 1.1 christos TRUE), /* pcrel_offset */
345 1.1 christos
346 1.1 christos /* Low 12 bits of a 32-bit PC-relative load or add. */
347 1.1 christos HOWTO (R_RISCV_PCREL_LO12_I, /* type */
348 1.1 christos 0, /* rightshift */
349 1.1 christos 2, /* size */
350 1.1 christos 32, /* bitsize */
351 1.1 christos FALSE, /* pc_relative */
352 1.1 christos 0, /* bitpos */
353 1.1 christos complain_overflow_dont, /* complain_on_overflow */
354 1.1 christos bfd_elf_generic_reloc, /* special_function */
355 1.1 christos "R_RISCV_PCREL_LO12_I", /* name */
356 1.1 christos FALSE, /* partial_inplace */
357 1.1 christos 0, /* src_mask */
358 1.1 christos ENCODE_ITYPE_IMM (-1U), /* dst_mask */
359 1.1 christos FALSE), /* pcrel_offset */
360 1.1 christos
361 1.1 christos /* Low 12 bits of a 32-bit PC-relative store. */
362 1.1 christos HOWTO (R_RISCV_PCREL_LO12_S, /* type */
363 1.1 christos 0, /* rightshift */
364 1.1 christos 2, /* size */
365 1.1 christos 32, /* bitsize */
366 1.1 christos FALSE, /* pc_relative */
367 1.1 christos 0, /* bitpos */
368 1.1 christos complain_overflow_dont, /* complain_on_overflow */
369 1.1 christos bfd_elf_generic_reloc, /* special_function */
370 1.1 christos "R_RISCV_PCREL_LO12_S", /* name */
371 1.1 christos FALSE, /* partial_inplace */
372 1.1 christos 0, /* src_mask */
373 1.1 christos ENCODE_STYPE_IMM (-1U), /* dst_mask */
374 1.1 christos FALSE), /* pcrel_offset */
375 1.1 christos
376 1.1 christos /* High 20 bits of 32-bit absolute address. */
377 1.1 christos HOWTO (R_RISCV_HI20, /* type */
378 1.1 christos 0, /* rightshift */
379 1.1 christos 2, /* size */
380 1.1 christos 32, /* bitsize */
381 1.1 christos FALSE, /* pc_relative */
382 1.1 christos 0, /* bitpos */
383 1.1 christos complain_overflow_dont, /* complain_on_overflow */
384 1.1 christos bfd_elf_generic_reloc, /* special_function */
385 1.1 christos "R_RISCV_HI20", /* name */
386 1.1 christos FALSE, /* partial_inplace */
387 1.1 christos 0, /* src_mask */
388 1.1 christos ENCODE_UTYPE_IMM (-1U), /* dst_mask */
389 1.1 christos FALSE), /* pcrel_offset */
390 1.1 christos
391 1.1 christos /* High 12 bits of 32-bit load or add. */
392 1.1 christos HOWTO (R_RISCV_LO12_I, /* type */
393 1.1 christos 0, /* rightshift */
394 1.1 christos 2, /* size */
395 1.1 christos 32, /* bitsize */
396 1.1 christos FALSE, /* pc_relative */
397 1.1 christos 0, /* bitpos */
398 1.1 christos complain_overflow_dont, /* complain_on_overflow */
399 1.1 christos bfd_elf_generic_reloc, /* special_function */
400 1.1 christos "R_RISCV_LO12_I", /* name */
401 1.1 christos FALSE, /* partial_inplace */
402 1.1 christos 0, /* src_mask */
403 1.1 christos ENCODE_ITYPE_IMM (-1U), /* dst_mask */
404 1.1 christos FALSE), /* pcrel_offset */
405 1.1 christos
406 1.1 christos /* High 12 bits of 32-bit store. */
407 1.1 christos HOWTO (R_RISCV_LO12_S, /* type */
408 1.1 christos 0, /* rightshift */
409 1.1 christos 2, /* size */
410 1.1 christos 32, /* bitsize */
411 1.1 christos FALSE, /* pc_relative */
412 1.1 christos 0, /* bitpos */
413 1.1 christos complain_overflow_dont, /* complain_on_overflow */
414 1.1 christos bfd_elf_generic_reloc, /* special_function */
415 1.1 christos "R_RISCV_LO12_S", /* name */
416 1.1 christos FALSE, /* partial_inplace */
417 1.1 christos 0, /* src_mask */
418 1.1 christos ENCODE_STYPE_IMM (-1U), /* dst_mask */
419 1.1 christos FALSE), /* pcrel_offset */
420 1.1 christos
421 1.1 christos /* High 20 bits of TLS LE thread pointer offset. */
422 1.1 christos HOWTO (R_RISCV_TPREL_HI20, /* type */
423 1.1 christos 0, /* rightshift */
424 1.1 christos 2, /* size */
425 1.1 christos 32, /* bitsize */
426 1.1 christos FALSE, /* pc_relative */
427 1.1 christos 0, /* bitpos */
428 1.1 christos complain_overflow_signed, /* complain_on_overflow */
429 1.1 christos bfd_elf_generic_reloc, /* special_function */
430 1.1 christos "R_RISCV_TPREL_HI20", /* name */
431 1.1 christos TRUE, /* partial_inplace */
432 1.1 christos 0, /* src_mask */
433 1.1 christos ENCODE_UTYPE_IMM (-1U), /* dst_mask */
434 1.1 christos FALSE), /* pcrel_offset */
435 1.1 christos
436 1.1 christos /* Low 12 bits of TLS LE thread pointer offset for loads and adds. */
437 1.1 christos HOWTO (R_RISCV_TPREL_LO12_I, /* type */
438 1.1 christos 0, /* rightshift */
439 1.1 christos 2, /* size */
440 1.1 christos 32, /* bitsize */
441 1.1 christos FALSE, /* pc_relative */
442 1.1 christos 0, /* bitpos */
443 1.1 christos complain_overflow_signed, /* complain_on_overflow */
444 1.1 christos bfd_elf_generic_reloc, /* special_function */
445 1.1 christos "R_RISCV_TPREL_LO12_I", /* name */
446 1.1 christos FALSE, /* partial_inplace */
447 1.1 christos 0, /* src_mask */
448 1.1 christos ENCODE_ITYPE_IMM (-1U), /* dst_mask */
449 1.1 christos FALSE), /* pcrel_offset */
450 1.1 christos
451 1.1 christos /* Low 12 bits of TLS LE thread pointer offset for stores. */
452 1.1 christos HOWTO (R_RISCV_TPREL_LO12_S, /* type */
453 1.1 christos 0, /* rightshift */
454 1.1 christos 2, /* size */
455 1.1 christos 32, /* bitsize */
456 1.1 christos FALSE, /* pc_relative */
457 1.1 christos 0, /* bitpos */
458 1.1 christos complain_overflow_signed, /* complain_on_overflow */
459 1.1 christos bfd_elf_generic_reloc, /* special_function */
460 1.1 christos "R_RISCV_TPREL_LO12_S", /* name */
461 1.1 christos FALSE, /* partial_inplace */
462 1.1 christos 0, /* src_mask */
463 1.1 christos ENCODE_STYPE_IMM (-1U), /* dst_mask */
464 1.1 christos FALSE), /* pcrel_offset */
465 1.1 christos
466 1.1 christos /* TLS LE thread pointer usage. May be relaxed. */
467 1.1 christos HOWTO (R_RISCV_TPREL_ADD, /* type */
468 1.1 christos 0, /* rightshift */
469 1.1 christos 2, /* size */
470 1.1 christos 32, /* bitsize */
471 1.1 christos FALSE, /* pc_relative */
472 1.1 christos 0, /* bitpos */
473 1.1 christos complain_overflow_dont, /* complain_on_overflow */
474 1.1 christos bfd_elf_generic_reloc, /* special_function */
475 1.1 christos "R_RISCV_TPREL_ADD", /* name */
476 1.1 christos TRUE, /* partial_inplace */
477 1.1 christos 0, /* src_mask */
478 1.1 christos 0, /* dst_mask */
479 1.1 christos FALSE), /* pcrel_offset */
480 1.1 christos
481 1.1 christos /* 8-bit in-place addition, for local label subtraction. */
482 1.1 christos HOWTO (R_RISCV_ADD8, /* type */
483 1.1 christos 0, /* rightshift */
484 1.1 christos 0, /* size */
485 1.1 christos 8, /* bitsize */
486 1.1 christos FALSE, /* pc_relative */
487 1.1 christos 0, /* bitpos */
488 1.1 christos complain_overflow_dont, /* complain_on_overflow */
489 1.1.1.2 christos riscv_elf_add_sub_reloc, /* special_function */
490 1.1 christos "R_RISCV_ADD8", /* name */
491 1.1 christos FALSE, /* partial_inplace */
492 1.1 christos 0, /* src_mask */
493 1.1 christos MINUS_ONE, /* dst_mask */
494 1.1 christos FALSE), /* pcrel_offset */
495 1.1 christos
496 1.1 christos /* 16-bit in-place addition, for local label subtraction. */
497 1.1 christos HOWTO (R_RISCV_ADD16, /* type */
498 1.1 christos 0, /* rightshift */
499 1.1 christos 1, /* size */
500 1.1 christos 16, /* bitsize */
501 1.1 christos FALSE, /* pc_relative */
502 1.1 christos 0, /* bitpos */
503 1.1 christos complain_overflow_dont, /* complain_on_overflow */
504 1.1.1.2 christos riscv_elf_add_sub_reloc, /* special_function */
505 1.1 christos "R_RISCV_ADD16", /* name */
506 1.1 christos FALSE, /* partial_inplace */
507 1.1 christos 0, /* src_mask */
508 1.1 christos MINUS_ONE, /* dst_mask */
509 1.1 christos FALSE), /* pcrel_offset */
510 1.1 christos
511 1.1 christos /* 32-bit in-place addition, for local label subtraction. */
512 1.1 christos HOWTO (R_RISCV_ADD32, /* type */
513 1.1 christos 0, /* rightshift */
514 1.1 christos 2, /* size */
515 1.1 christos 32, /* bitsize */
516 1.1 christos FALSE, /* pc_relative */
517 1.1 christos 0, /* bitpos */
518 1.1 christos complain_overflow_dont, /* complain_on_overflow */
519 1.1.1.2 christos riscv_elf_add_sub_reloc, /* special_function */
520 1.1 christos "R_RISCV_ADD32", /* name */
521 1.1 christos FALSE, /* partial_inplace */
522 1.1 christos 0, /* src_mask */
523 1.1 christos MINUS_ONE, /* dst_mask */
524 1.1 christos FALSE), /* pcrel_offset */
525 1.1 christos
526 1.1 christos /* 64-bit in-place addition, for local label subtraction. */
527 1.1 christos HOWTO (R_RISCV_ADD64, /* type */
528 1.1 christos 0, /* rightshift */
529 1.1 christos 4, /* size */
530 1.1 christos 64, /* bitsize */
531 1.1 christos FALSE, /* pc_relative */
532 1.1 christos 0, /* bitpos */
533 1.1 christos complain_overflow_dont, /* complain_on_overflow */
534 1.1.1.2 christos riscv_elf_add_sub_reloc, /* special_function */
535 1.1 christos "R_RISCV_ADD64", /* name */
536 1.1 christos FALSE, /* partial_inplace */
537 1.1 christos 0, /* src_mask */
538 1.1 christos MINUS_ONE, /* dst_mask */
539 1.1 christos FALSE), /* pcrel_offset */
540 1.1 christos
541 1.1 christos /* 8-bit in-place addition, for local label subtraction. */
542 1.1 christos HOWTO (R_RISCV_SUB8, /* type */
543 1.1 christos 0, /* rightshift */
544 1.1 christos 0, /* size */
545 1.1 christos 8, /* bitsize */
546 1.1 christos FALSE, /* pc_relative */
547 1.1 christos 0, /* bitpos */
548 1.1 christos complain_overflow_dont, /* complain_on_overflow */
549 1.1.1.2 christos riscv_elf_add_sub_reloc, /* special_function */
550 1.1 christos "R_RISCV_SUB8", /* name */
551 1.1 christos FALSE, /* partial_inplace */
552 1.1 christos 0, /* src_mask */
553 1.1 christos MINUS_ONE, /* dst_mask */
554 1.1 christos FALSE), /* pcrel_offset */
555 1.1 christos
556 1.1 christos /* 16-bit in-place addition, for local label subtraction. */
557 1.1 christos HOWTO (R_RISCV_SUB16, /* type */
558 1.1 christos 0, /* rightshift */
559 1.1 christos 1, /* size */
560 1.1 christos 16, /* bitsize */
561 1.1 christos FALSE, /* pc_relative */
562 1.1 christos 0, /* bitpos */
563 1.1 christos complain_overflow_dont, /* complain_on_overflow */
564 1.1.1.2 christos riscv_elf_add_sub_reloc, /* special_function */
565 1.1 christos "R_RISCV_SUB16", /* name */
566 1.1 christos FALSE, /* partial_inplace */
567 1.1 christos 0, /* src_mask */
568 1.1 christos MINUS_ONE, /* dst_mask */
569 1.1 christos FALSE), /* pcrel_offset */
570 1.1 christos
571 1.1 christos /* 32-bit in-place addition, for local label subtraction. */
572 1.1 christos HOWTO (R_RISCV_SUB32, /* type */
573 1.1 christos 0, /* rightshift */
574 1.1 christos 2, /* size */
575 1.1 christos 32, /* bitsize */
576 1.1 christos FALSE, /* pc_relative */
577 1.1 christos 0, /* bitpos */
578 1.1 christos complain_overflow_dont, /* complain_on_overflow */
579 1.1.1.2 christos riscv_elf_add_sub_reloc, /* special_function */
580 1.1 christos "R_RISCV_SUB32", /* name */
581 1.1 christos FALSE, /* partial_inplace */
582 1.1 christos 0, /* src_mask */
583 1.1 christos MINUS_ONE, /* dst_mask */
584 1.1 christos FALSE), /* pcrel_offset */
585 1.1 christos
586 1.1 christos /* 64-bit in-place addition, for local label subtraction. */
587 1.1 christos HOWTO (R_RISCV_SUB64, /* type */
588 1.1 christos 0, /* rightshift */
589 1.1 christos 4, /* size */
590 1.1 christos 64, /* bitsize */
591 1.1 christos FALSE, /* pc_relative */
592 1.1 christos 0, /* bitpos */
593 1.1 christos complain_overflow_dont, /* complain_on_overflow */
594 1.1.1.2 christos riscv_elf_add_sub_reloc, /* special_function */
595 1.1 christos "R_RISCV_SUB64", /* name */
596 1.1 christos FALSE, /* partial_inplace */
597 1.1 christos 0, /* src_mask */
598 1.1 christos MINUS_ONE, /* dst_mask */
599 1.1 christos FALSE), /* pcrel_offset */
600 1.1 christos
601 1.1 christos /* GNU extension to record C++ vtable hierarchy */
602 1.1 christos HOWTO (R_RISCV_GNU_VTINHERIT, /* type */
603 1.1 christos 0, /* rightshift */
604 1.1 christos 4, /* size */
605 1.1 christos 0, /* bitsize */
606 1.1 christos FALSE, /* pc_relative */
607 1.1 christos 0, /* bitpos */
608 1.1 christos complain_overflow_dont, /* complain_on_overflow */
609 1.1 christos NULL, /* special_function */
610 1.1 christos "R_RISCV_GNU_VTINHERIT", /* name */
611 1.1 christos FALSE, /* partial_inplace */
612 1.1 christos 0, /* src_mask */
613 1.1 christos 0, /* dst_mask */
614 1.1 christos FALSE), /* pcrel_offset */
615 1.1 christos
616 1.1 christos /* GNU extension to record C++ vtable member usage */
617 1.1 christos HOWTO (R_RISCV_GNU_VTENTRY, /* type */
618 1.1 christos 0, /* rightshift */
619 1.1 christos 4, /* size */
620 1.1 christos 0, /* bitsize */
621 1.1 christos FALSE, /* pc_relative */
622 1.1 christos 0, /* bitpos */
623 1.1 christos complain_overflow_dont, /* complain_on_overflow */
624 1.1 christos _bfd_elf_rel_vtable_reloc_fn, /* special_function */
625 1.1 christos "R_RISCV_GNU_VTENTRY", /* name */
626 1.1 christos FALSE, /* partial_inplace */
627 1.1 christos 0, /* src_mask */
628 1.1 christos 0, /* dst_mask */
629 1.1 christos FALSE), /* pcrel_offset */
630 1.1 christos
631 1.1 christos /* Indicates an alignment statement. The addend field encodes how many
632 1.1 christos bytes of NOPs follow the statement. The desired alignment is the
633 1.1 christos addend rounded up to the next power of two. */
634 1.1 christos HOWTO (R_RISCV_ALIGN, /* type */
635 1.1 christos 0, /* rightshift */
636 1.1 christos 2, /* size */
637 1.1 christos 0, /* bitsize */
638 1.1 christos FALSE, /* pc_relative */
639 1.1 christos 0, /* bitpos */
640 1.1 christos complain_overflow_dont, /* complain_on_overflow */
641 1.1 christos bfd_elf_generic_reloc, /* special_function */
642 1.1 christos "R_RISCV_ALIGN", /* name */
643 1.1 christos FALSE, /* partial_inplace */
644 1.1 christos 0, /* src_mask */
645 1.1 christos 0, /* dst_mask */
646 1.1 christos TRUE), /* pcrel_offset */
647 1.1 christos
648 1.1 christos /* 8-bit PC-relative branch offset. */
649 1.1 christos HOWTO (R_RISCV_RVC_BRANCH, /* type */
650 1.1 christos 0, /* rightshift */
651 1.1 christos 2, /* size */
652 1.1 christos 32, /* bitsize */
653 1.1 christos TRUE, /* pc_relative */
654 1.1 christos 0, /* bitpos */
655 1.1 christos complain_overflow_signed, /* complain_on_overflow */
656 1.1 christos bfd_elf_generic_reloc, /* special_function */
657 1.1 christos "R_RISCV_RVC_BRANCH", /* name */
658 1.1 christos FALSE, /* partial_inplace */
659 1.1 christos 0, /* src_mask */
660 1.1 christos ENCODE_RVC_B_IMM (-1U), /* dst_mask */
661 1.1 christos TRUE), /* pcrel_offset */
662 1.1 christos
663 1.1 christos /* 11-bit PC-relative jump offset. */
664 1.1 christos HOWTO (R_RISCV_RVC_JUMP, /* type */
665 1.1 christos 0, /* rightshift */
666 1.1 christos 2, /* size */
667 1.1 christos 32, /* bitsize */
668 1.1 christos TRUE, /* pc_relative */
669 1.1 christos 0, /* bitpos */
670 1.1 christos complain_overflow_dont, /* complain_on_overflow */
671 1.1 christos bfd_elf_generic_reloc, /* special_function */
672 1.1 christos "R_RISCV_RVC_JUMP", /* name */
673 1.1 christos FALSE, /* partial_inplace */
674 1.1 christos 0, /* src_mask */
675 1.1 christos ENCODE_RVC_J_IMM (-1U), /* dst_mask */
676 1.1 christos TRUE), /* pcrel_offset */
677 1.1 christos
678 1.1 christos /* High 6 bits of 18-bit absolute address. */
679 1.1 christos HOWTO (R_RISCV_RVC_LUI, /* type */
680 1.1 christos 0, /* rightshift */
681 1.1 christos 2, /* size */
682 1.1 christos 32, /* bitsize */
683 1.1 christos FALSE, /* pc_relative */
684 1.1 christos 0, /* bitpos */
685 1.1 christos complain_overflow_dont, /* complain_on_overflow */
686 1.1 christos bfd_elf_generic_reloc, /* special_function */
687 1.1 christos "R_RISCV_RVC_LUI", /* name */
688 1.1 christos FALSE, /* partial_inplace */
689 1.1 christos 0, /* src_mask */
690 1.1 christos ENCODE_RVC_IMM (-1U), /* dst_mask */
691 1.1 christos FALSE), /* pcrel_offset */
692 1.1 christos
693 1.1 christos /* GP-relative load. */
694 1.1 christos HOWTO (R_RISCV_GPREL_I, /* type */
695 1.1 christos 0, /* rightshift */
696 1.1 christos 2, /* size */
697 1.1 christos 32, /* bitsize */
698 1.1 christos FALSE, /* pc_relative */
699 1.1 christos 0, /* bitpos */
700 1.1 christos complain_overflow_dont, /* complain_on_overflow */
701 1.1 christos bfd_elf_generic_reloc, /* special_function */
702 1.1 christos "R_RISCV_GPREL_I", /* name */
703 1.1 christos FALSE, /* partial_inplace */
704 1.1 christos 0, /* src_mask */
705 1.1 christos ENCODE_ITYPE_IMM (-1U), /* dst_mask */
706 1.1 christos FALSE), /* pcrel_offset */
707 1.1 christos
708 1.1 christos /* GP-relative store. */
709 1.1 christos HOWTO (R_RISCV_GPREL_S, /* type */
710 1.1 christos 0, /* rightshift */
711 1.1 christos 2, /* size */
712 1.1 christos 32, /* bitsize */
713 1.1 christos FALSE, /* pc_relative */
714 1.1 christos 0, /* bitpos */
715 1.1 christos complain_overflow_dont, /* complain_on_overflow */
716 1.1 christos bfd_elf_generic_reloc, /* special_function */
717 1.1 christos "R_RISCV_GPREL_S", /* name */
718 1.1 christos FALSE, /* partial_inplace */
719 1.1 christos 0, /* src_mask */
720 1.1 christos ENCODE_STYPE_IMM (-1U), /* dst_mask */
721 1.1 christos FALSE), /* pcrel_offset */
722 1.1 christos
723 1.1 christos /* TP-relative TLS LE load. */
724 1.1 christos HOWTO (R_RISCV_TPREL_I, /* type */
725 1.1 christos 0, /* rightshift */
726 1.1 christos 2, /* size */
727 1.1 christos 32, /* bitsize */
728 1.1 christos FALSE, /* pc_relative */
729 1.1 christos 0, /* bitpos */
730 1.1 christos complain_overflow_signed, /* complain_on_overflow */
731 1.1 christos bfd_elf_generic_reloc, /* special_function */
732 1.1 christos "R_RISCV_TPREL_I", /* name */
733 1.1 christos FALSE, /* partial_inplace */
734 1.1 christos 0, /* src_mask */
735 1.1 christos ENCODE_ITYPE_IMM (-1U), /* dst_mask */
736 1.1 christos FALSE), /* pcrel_offset */
737 1.1 christos
738 1.1 christos /* TP-relative TLS LE store. */
739 1.1 christos HOWTO (R_RISCV_TPREL_S, /* type */
740 1.1 christos 0, /* rightshift */
741 1.1 christos 2, /* size */
742 1.1 christos 32, /* bitsize */
743 1.1 christos FALSE, /* pc_relative */
744 1.1 christos 0, /* bitpos */
745 1.1 christos complain_overflow_signed, /* complain_on_overflow */
746 1.1 christos bfd_elf_generic_reloc, /* special_function */
747 1.1 christos "R_RISCV_TPREL_S", /* name */
748 1.1 christos FALSE, /* partial_inplace */
749 1.1 christos 0, /* src_mask */
750 1.1 christos ENCODE_STYPE_IMM (-1U), /* dst_mask */
751 1.1 christos FALSE), /* pcrel_offset */
752 1.1 christos
753 1.1 christos /* The paired relocation may be relaxed. */
754 1.1 christos HOWTO (R_RISCV_RELAX, /* type */
755 1.1 christos 0, /* rightshift */
756 1.1 christos 3, /* size */
757 1.1 christos 0, /* bitsize */
758 1.1 christos FALSE, /* pc_relative */
759 1.1 christos 0, /* bitpos */
760 1.1 christos complain_overflow_dont, /* complain_on_overflow */
761 1.1 christos bfd_elf_generic_reloc, /* special_function */
762 1.1 christos "R_RISCV_RELAX", /* name */
763 1.1 christos FALSE, /* partial_inplace */
764 1.1 christos 0, /* src_mask */
765 1.1 christos 0, /* dst_mask */
766 1.1 christos FALSE), /* pcrel_offset */
767 1.1 christos
768 1.1 christos /* 6-bit in-place addition, for local label subtraction. */
769 1.1 christos HOWTO (R_RISCV_SUB6, /* type */
770 1.1 christos 0, /* rightshift */
771 1.1 christos 0, /* size */
772 1.1 christos 8, /* bitsize */
773 1.1 christos FALSE, /* pc_relative */
774 1.1 christos 0, /* bitpos */
775 1.1 christos complain_overflow_dont, /* complain_on_overflow */
776 1.1.1.2 christos riscv_elf_add_sub_reloc, /* special_function */
777 1.1 christos "R_RISCV_SUB6", /* name */
778 1.1 christos FALSE, /* partial_inplace */
779 1.1 christos 0, /* src_mask */
780 1.1 christos 0x3f, /* dst_mask */
781 1.1 christos FALSE), /* pcrel_offset */
782 1.1 christos
783 1.1 christos /* 6-bit in-place setting, for local label subtraction. */
784 1.1 christos HOWTO (R_RISCV_SET6, /* type */
785 1.1 christos 0, /* rightshift */
786 1.1 christos 0, /* size */
787 1.1 christos 8, /* bitsize */
788 1.1 christos FALSE, /* pc_relative */
789 1.1 christos 0, /* bitpos */
790 1.1 christos complain_overflow_dont, /* complain_on_overflow */
791 1.1 christos bfd_elf_generic_reloc, /* special_function */
792 1.1 christos "R_RISCV_SET6", /* name */
793 1.1 christos FALSE, /* partial_inplace */
794 1.1 christos 0, /* src_mask */
795 1.1 christos 0x3f, /* dst_mask */
796 1.1 christos FALSE), /* pcrel_offset */
797 1.1 christos
798 1.1 christos /* 8-bit in-place setting, for local label subtraction. */
799 1.1 christos HOWTO (R_RISCV_SET8, /* type */
800 1.1 christos 0, /* rightshift */
801 1.1 christos 0, /* size */
802 1.1 christos 8, /* bitsize */
803 1.1 christos FALSE, /* pc_relative */
804 1.1 christos 0, /* bitpos */
805 1.1 christos complain_overflow_dont, /* complain_on_overflow */
806 1.1 christos bfd_elf_generic_reloc, /* special_function */
807 1.1 christos "R_RISCV_SET8", /* name */
808 1.1 christos FALSE, /* partial_inplace */
809 1.1 christos 0, /* src_mask */
810 1.1 christos MINUS_ONE, /* dst_mask */
811 1.1 christos FALSE), /* pcrel_offset */
812 1.1 christos
813 1.1 christos /* 16-bit in-place setting, for local label subtraction. */
814 1.1 christos HOWTO (R_RISCV_SET16, /* type */
815 1.1 christos 0, /* rightshift */
816 1.1 christos 1, /* size */
817 1.1 christos 16, /* bitsize */
818 1.1 christos FALSE, /* pc_relative */
819 1.1 christos 0, /* bitpos */
820 1.1 christos complain_overflow_dont, /* complain_on_overflow */
821 1.1 christos bfd_elf_generic_reloc, /* special_function */
822 1.1 christos "R_RISCV_SET16", /* name */
823 1.1 christos FALSE, /* partial_inplace */
824 1.1 christos 0, /* src_mask */
825 1.1 christos MINUS_ONE, /* dst_mask */
826 1.1 christos FALSE), /* pcrel_offset */
827 1.1 christos
828 1.1 christos /* 32-bit in-place setting, for local label subtraction. */
829 1.1 christos HOWTO (R_RISCV_SET32, /* type */
830 1.1 christos 0, /* rightshift */
831 1.1 christos 2, /* size */
832 1.1 christos 32, /* bitsize */
833 1.1 christos FALSE, /* pc_relative */
834 1.1 christos 0, /* bitpos */
835 1.1 christos complain_overflow_dont, /* complain_on_overflow */
836 1.1 christos bfd_elf_generic_reloc, /* special_function */
837 1.1 christos "R_RISCV_SET32", /* name */
838 1.1 christos FALSE, /* partial_inplace */
839 1.1 christos 0, /* src_mask */
840 1.1 christos MINUS_ONE, /* dst_mask */
841 1.1 christos FALSE), /* pcrel_offset */
842 1.1.1.2 christos
843 1.1.1.2 christos /* 32-bit PC relative. */
844 1.1.1.2 christos HOWTO (R_RISCV_32_PCREL, /* type */
845 1.1.1.2 christos 0, /* rightshift */
846 1.1.1.2 christos 2, /* size */
847 1.1.1.2 christos 32, /* bitsize */
848 1.1.1.2 christos TRUE, /* pc_relative */
849 1.1.1.2 christos 0, /* bitpos */
850 1.1.1.2 christos complain_overflow_dont, /* complain_on_overflow */
851 1.1.1.2 christos bfd_elf_generic_reloc, /* special_function */
852 1.1.1.2 christos "R_RISCV_32_PCREL", /* name */
853 1.1.1.2 christos FALSE, /* partial_inplace */
854 1.1.1.2 christos 0, /* src_mask */
855 1.1.1.2 christos MINUS_ONE, /* dst_mask */
856 1.1.1.2 christos FALSE), /* pcrel_offset */
857 1.1 christos };
858 1.1 christos
859 1.1 christos /* A mapping from BFD reloc types to RISC-V ELF reloc types. */
860 1.1 christos
861 1.1 christos struct elf_reloc_map
862 1.1 christos {
863 1.1 christos bfd_reloc_code_real_type bfd_val;
864 1.1 christos enum elf_riscv_reloc_type elf_val;
865 1.1 christos };
866 1.1 christos
867 1.1 christos static const struct elf_reloc_map riscv_reloc_map[] =
868 1.1 christos {
869 1.1 christos { BFD_RELOC_NONE, R_RISCV_NONE },
870 1.1 christos { BFD_RELOC_32, R_RISCV_32 },
871 1.1 christos { BFD_RELOC_64, R_RISCV_64 },
872 1.1 christos { BFD_RELOC_RISCV_ADD8, R_RISCV_ADD8 },
873 1.1 christos { BFD_RELOC_RISCV_ADD16, R_RISCV_ADD16 },
874 1.1 christos { BFD_RELOC_RISCV_ADD32, R_RISCV_ADD32 },
875 1.1 christos { BFD_RELOC_RISCV_ADD64, R_RISCV_ADD64 },
876 1.1 christos { BFD_RELOC_RISCV_SUB8, R_RISCV_SUB8 },
877 1.1 christos { BFD_RELOC_RISCV_SUB16, R_RISCV_SUB16 },
878 1.1 christos { BFD_RELOC_RISCV_SUB32, R_RISCV_SUB32 },
879 1.1 christos { BFD_RELOC_RISCV_SUB64, R_RISCV_SUB64 },
880 1.1 christos { BFD_RELOC_CTOR, R_RISCV_64 },
881 1.1 christos { BFD_RELOC_12_PCREL, R_RISCV_BRANCH },
882 1.1 christos { BFD_RELOC_RISCV_HI20, R_RISCV_HI20 },
883 1.1 christos { BFD_RELOC_RISCV_LO12_I, R_RISCV_LO12_I },
884 1.1 christos { BFD_RELOC_RISCV_LO12_S, R_RISCV_LO12_S },
885 1.1 christos { BFD_RELOC_RISCV_PCREL_LO12_I, R_RISCV_PCREL_LO12_I },
886 1.1 christos { BFD_RELOC_RISCV_PCREL_LO12_S, R_RISCV_PCREL_LO12_S },
887 1.1 christos { BFD_RELOC_RISCV_CALL, R_RISCV_CALL },
888 1.1 christos { BFD_RELOC_RISCV_CALL_PLT, R_RISCV_CALL_PLT },
889 1.1 christos { BFD_RELOC_RISCV_PCREL_HI20, R_RISCV_PCREL_HI20 },
890 1.1 christos { BFD_RELOC_RISCV_JMP, R_RISCV_JAL },
891 1.1 christos { BFD_RELOC_RISCV_GOT_HI20, R_RISCV_GOT_HI20 },
892 1.1 christos { BFD_RELOC_RISCV_TLS_DTPMOD32, R_RISCV_TLS_DTPMOD32 },
893 1.1 christos { BFD_RELOC_RISCV_TLS_DTPREL32, R_RISCV_TLS_DTPREL32 },
894 1.1 christos { BFD_RELOC_RISCV_TLS_DTPMOD64, R_RISCV_TLS_DTPMOD64 },
895 1.1 christos { BFD_RELOC_RISCV_TLS_DTPREL64, R_RISCV_TLS_DTPREL64 },
896 1.1 christos { BFD_RELOC_RISCV_TLS_TPREL32, R_RISCV_TLS_TPREL32 },
897 1.1 christos { BFD_RELOC_RISCV_TLS_TPREL64, R_RISCV_TLS_TPREL64 },
898 1.1 christos { BFD_RELOC_RISCV_TPREL_HI20, R_RISCV_TPREL_HI20 },
899 1.1 christos { BFD_RELOC_RISCV_TPREL_ADD, R_RISCV_TPREL_ADD },
900 1.1 christos { BFD_RELOC_RISCV_TPREL_LO12_S, R_RISCV_TPREL_LO12_S },
901 1.1 christos { BFD_RELOC_RISCV_TPREL_LO12_I, R_RISCV_TPREL_LO12_I },
902 1.1 christos { BFD_RELOC_RISCV_TLS_GOT_HI20, R_RISCV_TLS_GOT_HI20 },
903 1.1 christos { BFD_RELOC_RISCV_TLS_GD_HI20, R_RISCV_TLS_GD_HI20 },
904 1.1 christos { BFD_RELOC_RISCV_ALIGN, R_RISCV_ALIGN },
905 1.1 christos { BFD_RELOC_RISCV_RVC_BRANCH, R_RISCV_RVC_BRANCH },
906 1.1 christos { BFD_RELOC_RISCV_RVC_JUMP, R_RISCV_RVC_JUMP },
907 1.1 christos { BFD_RELOC_RISCV_RVC_LUI, R_RISCV_RVC_LUI },
908 1.1 christos { BFD_RELOC_RISCV_GPREL_I, R_RISCV_GPREL_I },
909 1.1 christos { BFD_RELOC_RISCV_GPREL_S, R_RISCV_GPREL_S },
910 1.1 christos { BFD_RELOC_RISCV_TPREL_I, R_RISCV_TPREL_I },
911 1.1 christos { BFD_RELOC_RISCV_TPREL_S, R_RISCV_TPREL_S },
912 1.1 christos { BFD_RELOC_RISCV_RELAX, R_RISCV_RELAX },
913 1.1 christos { BFD_RELOC_RISCV_SUB6, R_RISCV_SUB6 },
914 1.1 christos { BFD_RELOC_RISCV_SET6, R_RISCV_SET6 },
915 1.1 christos { BFD_RELOC_RISCV_SET8, R_RISCV_SET8 },
916 1.1 christos { BFD_RELOC_RISCV_SET16, R_RISCV_SET16 },
917 1.1 christos { BFD_RELOC_RISCV_SET32, R_RISCV_SET32 },
918 1.1.1.2 christos { BFD_RELOC_RISCV_32_PCREL, R_RISCV_32_PCREL },
919 1.1 christos };
920 1.1 christos
921 1.1 christos /* Given a BFD reloc type, return a howto structure. */
922 1.1 christos
923 1.1 christos reloc_howto_type *
924 1.1 christos riscv_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED,
925 1.1 christos bfd_reloc_code_real_type code)
926 1.1 christos {
927 1.1 christos unsigned int i;
928 1.1 christos
929 1.1 christos for (i = 0; i < ARRAY_SIZE (riscv_reloc_map); i++)
930 1.1 christos if (riscv_reloc_map[i].bfd_val == code)
931 1.1 christos return &howto_table[(int) riscv_reloc_map[i].elf_val];
932 1.1 christos
933 1.1 christos bfd_set_error (bfd_error_bad_value);
934 1.1 christos return NULL;
935 1.1 christos }
936 1.1 christos
937 1.1 christos reloc_howto_type *
938 1.1 christos riscv_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED, const char *r_name)
939 1.1 christos {
940 1.1 christos unsigned int i;
941 1.1 christos
942 1.1 christos for (i = 0; i < ARRAY_SIZE (howto_table); i++)
943 1.1 christos if (howto_table[i].name && strcasecmp (howto_table[i].name, r_name) == 0)
944 1.1 christos return &howto_table[i];
945 1.1 christos
946 1.1 christos return NULL;
947 1.1 christos }
948 1.1 christos
949 1.1 christos reloc_howto_type *
950 1.1.1.2 christos riscv_elf_rtype_to_howto (bfd *abfd, unsigned int r_type)
951 1.1 christos {
952 1.1 christos if (r_type >= ARRAY_SIZE (howto_table))
953 1.1 christos {
954 1.1.1.2 christos (*_bfd_error_handler) (_("%pB: unsupported relocation type %#x"),
955 1.1.1.2 christos abfd, r_type);
956 1.1 christos bfd_set_error (bfd_error_bad_value);
957 1.1 christos return NULL;
958 1.1 christos }
959 1.1 christos return &howto_table[r_type];
960 1.1 christos }
961 1.1.1.2 christos
962 1.1.1.2 christos /* Special_function of RISCV_ADD and RISCV_SUB relocations. */
963 1.1.1.2 christos
964 1.1.1.2 christos static bfd_reloc_status_type
965 1.1.1.2 christos riscv_elf_add_sub_reloc (bfd *abfd,
966 1.1.1.2 christos arelent *reloc_entry,
967 1.1.1.2 christos asymbol *symbol,
968 1.1.1.2 christos void *data,
969 1.1.1.2 christos asection *input_section,
970 1.1.1.2 christos bfd *output_bfd,
971 1.1.1.2 christos char **error_message ATTRIBUTE_UNUSED)
972 1.1.1.2 christos {
973 1.1.1.2 christos reloc_howto_type *howto = reloc_entry->howto;
974 1.1.1.2 christos bfd_vma relocation;
975 1.1.1.2 christos
976 1.1.1.2 christos if (output_bfd != NULL
977 1.1.1.2 christos && (symbol->flags & BSF_SECTION_SYM) == 0
978 1.1.1.2 christos && (!reloc_entry->howto->partial_inplace || reloc_entry->addend == 0))
979 1.1.1.2 christos {
980 1.1.1.2 christos reloc_entry->address += input_section->output_offset;
981 1.1.1.2 christos return bfd_reloc_ok;
982 1.1.1.2 christos }
983 1.1.1.2 christos
984 1.1.1.2 christos if (output_bfd != NULL)
985 1.1.1.2 christos return bfd_reloc_continue;
986 1.1.1.2 christos
987 1.1.1.2 christos relocation = symbol->value + symbol->section->output_section->vma
988 1.1.1.2 christos + symbol->section->output_offset + reloc_entry->addend;
989 1.1.1.2 christos bfd_vma old_value = bfd_get (howto->bitsize, abfd,
990 1.1.1.2 christos data + reloc_entry->address);
991 1.1.1.2 christos
992 1.1.1.2 christos switch (howto->type)
993 1.1.1.2 christos {
994 1.1.1.2 christos case R_RISCV_ADD8:
995 1.1.1.2 christos case R_RISCV_ADD16:
996 1.1.1.2 christos case R_RISCV_ADD32:
997 1.1.1.2 christos case R_RISCV_ADD64:
998 1.1.1.2 christos relocation = old_value + relocation;
999 1.1.1.2 christos break;
1000 1.1.1.2 christos case R_RISCV_SUB6:
1001 1.1.1.2 christos case R_RISCV_SUB8:
1002 1.1.1.2 christos case R_RISCV_SUB16:
1003 1.1.1.2 christos case R_RISCV_SUB32:
1004 1.1.1.2 christos case R_RISCV_SUB64:
1005 1.1.1.2 christos relocation = old_value - relocation;
1006 1.1.1.2 christos break;
1007 1.1.1.2 christos }
1008 1.1.1.2 christos bfd_put (howto->bitsize, abfd, relocation, data + reloc_entry->address);
1009 1.1.1.2 christos
1010 1.1.1.2 christos return bfd_reloc_ok;
1011 1.1.1.2 christos }
1012 1.1.1.2 christos
1013 1.1.1.2 christos /* Parsing subset version.
1014 1.1.1.2 christos
1015 1.1.1.2 christos Return Value:
1016 1.1.1.2 christos Points to the end of version
1017 1.1.1.2 christos
1018 1.1.1.2 christos Arguments:
1019 1.1.1.2 christos `rps`: Hooks and status for parsing subset.
1020 1.1.1.2 christos `march`: Full arch string.
1021 1.1.1.2 christos `p`: Curent parsing position.
1022 1.1.1.2 christos `major_version`: Parsing result of major version, using
1023 1.1.1.2 christos default_major_version if version is not present in arch string.
1024 1.1.1.2 christos `minor_version`: Parsing result of minor version, set to 0 if version is
1025 1.1.1.2 christos not present in arch string, but set to `default_minor_version` if
1026 1.1.1.2 christos `major_version` using default_major_version.
1027 1.1.1.3 christos `std_ext_p`: True if parsing std extension.
1028 1.1.1.3 christos `use_default_version`: Set it to True if we need the default version. */
1029 1.1.1.2 christos
1030 1.1.1.2 christos static const char *
1031 1.1.1.2 christos riscv_parsing_subset_version (riscv_parse_subset_t *rps,
1032 1.1.1.2 christos const char *march,
1033 1.1.1.2 christos const char *p,
1034 1.1.1.2 christos unsigned *major_version,
1035 1.1.1.2 christos unsigned *minor_version,
1036 1.1.1.3 christos bfd_boolean std_ext_p,
1037 1.1.1.3 christos bfd_boolean *use_default_version)
1038 1.1.1.2 christos {
1039 1.1.1.2 christos bfd_boolean major_p = TRUE;
1040 1.1.1.2 christos unsigned version = 0;
1041 1.1.1.2 christos char np;
1042 1.1.1.2 christos
1043 1.1.1.3 christos *major_version = 0;
1044 1.1.1.3 christos *minor_version = 0;
1045 1.1.1.3 christos for (; *p; ++p)
1046 1.1.1.2 christos {
1047 1.1.1.2 christos if (*p == 'p')
1048 1.1.1.2 christos {
1049 1.1.1.2 christos np = *(p + 1);
1050 1.1.1.2 christos
1051 1.1.1.2 christos if (!ISDIGIT (np))
1052 1.1.1.2 christos {
1053 1.1.1.2 christos /* Might be beginning of `p` extension. */
1054 1.1.1.2 christos if (std_ext_p)
1055 1.1.1.2 christos {
1056 1.1.1.2 christos *major_version = version;
1057 1.1.1.2 christos *minor_version = 0;
1058 1.1.1.2 christos return p;
1059 1.1.1.2 christos }
1060 1.1.1.2 christos else
1061 1.1.1.2 christos {
1062 1.1.1.3 christos rps->error_handler
1063 1.1.1.3 christos (_("-march=%s: Expect number after `%dp'."),
1064 1.1.1.3 christos march, version);
1065 1.1.1.2 christos return NULL;
1066 1.1.1.2 christos }
1067 1.1.1.2 christos }
1068 1.1.1.2 christos
1069 1.1.1.3 christos *major_version = version;
1070 1.1.1.2 christos major_p = FALSE;
1071 1.1.1.2 christos version = 0;
1072 1.1.1.2 christos }
1073 1.1.1.2 christos else if (ISDIGIT (*p))
1074 1.1.1.2 christos version = (version * 10) + (*p - '0');
1075 1.1.1.2 christos else
1076 1.1.1.2 christos break;
1077 1.1.1.2 christos }
1078 1.1.1.2 christos
1079 1.1.1.2 christos if (major_p)
1080 1.1.1.3 christos *major_version = version;
1081 1.1.1.2 christos else
1082 1.1.1.3 christos *minor_version = version;
1083 1.1.1.2 christos
1084 1.1.1.3 christos /* We can not find any version in string, need to parse default version. */
1085 1.1.1.3 christos if (use_default_version != NULL
1086 1.1.1.3 christos && *major_version == 0
1087 1.1.1.3 christos && *minor_version == 0)
1088 1.1.1.3 christos *use_default_version = TRUE;
1089 1.1.1.2 christos return p;
1090 1.1.1.2 christos }
1091 1.1.1.2 christos
1092 1.1.1.2 christos /* Return string which contain all supported standard extensions in
1093 1.1.1.2 christos canonical order. */
1094 1.1.1.2 christos
1095 1.1.1.2 christos const char *
1096 1.1.1.2 christos riscv_supported_std_ext (void)
1097 1.1.1.2 christos {
1098 1.1.1.2 christos return "mafdqlcbjtpvn";
1099 1.1.1.2 christos }
1100 1.1.1.2 christos
1101 1.1.1.2 christos /* Parsing function for standard extensions.
1102 1.1.1.2 christos
1103 1.1.1.2 christos Return Value:
1104 1.1.1.2 christos Points to the end of extensions.
1105 1.1.1.2 christos
1106 1.1.1.2 christos Arguments:
1107 1.1.1.2 christos `rps`: Hooks and status for parsing subset.
1108 1.1.1.2 christos `march`: Full arch string.
1109 1.1.1.2 christos `p`: Curent parsing position. */
1110 1.1.1.2 christos
1111 1.1.1.2 christos static const char *
1112 1.1.1.2 christos riscv_parse_std_ext (riscv_parse_subset_t *rps,
1113 1.1.1.3 christos const char *march,
1114 1.1.1.3 christos const char *p)
1115 1.1.1.2 christos {
1116 1.1.1.2 christos const char *all_std_exts = riscv_supported_std_ext ();
1117 1.1.1.2 christos const char *std_exts = all_std_exts;
1118 1.1.1.2 christos unsigned major_version = 0;
1119 1.1.1.2 christos unsigned minor_version = 0;
1120 1.1.1.2 christos char std_ext = '\0';
1121 1.1.1.3 christos bfd_boolean use_default_version = FALSE;
1122 1.1.1.2 christos
1123 1.1.1.2 christos /* First letter must start with i, e or g. */
1124 1.1.1.2 christos switch (*p)
1125 1.1.1.2 christos {
1126 1.1.1.2 christos case 'i':
1127 1.1.1.3 christos p = riscv_parsing_subset_version (rps,
1128 1.1.1.3 christos march,
1129 1.1.1.3 christos ++p,
1130 1.1.1.3 christos &major_version,
1131 1.1.1.3 christos &minor_version,
1132 1.1.1.3 christos /* std_ext_p= */TRUE,
1133 1.1.1.3 christos &use_default_version);
1134 1.1.1.3 christos
1135 1.1.1.3 christos /* Find the default version if needed. */
1136 1.1.1.3 christos if (use_default_version
1137 1.1.1.3 christos && rps->get_default_version != NULL)
1138 1.1.1.3 christos rps->get_default_version ("i",
1139 1.1.1.3 christos &major_version,
1140 1.1.1.3 christos &minor_version);
1141 1.1.1.3 christos riscv_add_subset (rps->subset_list, "i",
1142 1.1.1.3 christos major_version, minor_version);
1143 1.1.1.2 christos break;
1144 1.1.1.2 christos
1145 1.1.1.2 christos case 'e':
1146 1.1.1.3 christos p = riscv_parsing_subset_version (rps,
1147 1.1.1.3 christos march,
1148 1.1.1.3 christos ++p,
1149 1.1.1.3 christos &major_version,
1150 1.1.1.3 christos &minor_version,
1151 1.1.1.3 christos /* std_ext_p= */TRUE,
1152 1.1.1.3 christos &use_default_version);
1153 1.1.1.3 christos
1154 1.1.1.3 christos /* Find the default version if needed. */
1155 1.1.1.3 christos if (use_default_version
1156 1.1.1.3 christos && rps->get_default_version != NULL)
1157 1.1.1.3 christos rps->get_default_version ("e",
1158 1.1.1.3 christos &major_version,
1159 1.1.1.3 christos &minor_version);
1160 1.1.1.3 christos riscv_add_subset (rps->subset_list, "e",
1161 1.1.1.3 christos major_version, minor_version);
1162 1.1.1.3 christos
1163 1.1.1.3 christos /* i-ext must be enabled. */
1164 1.1.1.3 christos if (rps->get_default_version != NULL)
1165 1.1.1.3 christos rps->get_default_version ("i",
1166 1.1.1.3 christos &major_version,
1167 1.1.1.3 christos &minor_version);
1168 1.1.1.3 christos riscv_add_subset (rps->subset_list, "i",
1169 1.1.1.3 christos major_version, minor_version);
1170 1.1.1.2 christos
1171 1.1.1.2 christos if (*rps->xlen > 32)
1172 1.1.1.2 christos {
1173 1.1.1.3 christos rps->error_handler
1174 1.1.1.3 christos (_("-march=%s: rv%de is not a valid base ISA"),
1175 1.1.1.3 christos march, *rps->xlen);
1176 1.1.1.2 christos return NULL;
1177 1.1.1.2 christos }
1178 1.1.1.2 christos break;
1179 1.1.1.2 christos
1180 1.1.1.2 christos case 'g':
1181 1.1.1.3 christos /* The g-ext shouldn't has the version, so we just
1182 1.1.1.3 christos skip the setting if user set a version to it. */
1183 1.1.1.3 christos p = riscv_parsing_subset_version (rps,
1184 1.1.1.3 christos march,
1185 1.1.1.3 christos ++p,
1186 1.1.1.3 christos &major_version,
1187 1.1.1.3 christos &minor_version,
1188 1.1.1.3 christos TRUE,
1189 1.1.1.3 christos &use_default_version);
1190 1.1.1.3 christos
1191 1.1.1.3 christos /* i-ext must be enabled. */
1192 1.1.1.3 christos if (rps->get_default_version != NULL)
1193 1.1.1.3 christos rps->get_default_version ("i",
1194 1.1.1.3 christos &major_version,
1195 1.1.1.3 christos &minor_version);
1196 1.1.1.3 christos riscv_add_subset (rps->subset_list, "i",
1197 1.1.1.3 christos major_version, minor_version);
1198 1.1.1.2 christos
1199 1.1.1.2 christos for ( ; *std_exts != 'q'; std_exts++)
1200 1.1.1.2 christos {
1201 1.1.1.2 christos const char subset[] = {*std_exts, '\0'};
1202 1.1.1.3 christos
1203 1.1.1.3 christos if (rps->get_default_version != NULL)
1204 1.1.1.3 christos rps->get_default_version (subset,
1205 1.1.1.3 christos &major_version,
1206 1.1.1.3 christos &minor_version);
1207 1.1.1.3 christos riscv_add_subset (rps->subset_list, subset,
1208 1.1.1.3 christos major_version, minor_version);
1209 1.1.1.2 christos }
1210 1.1.1.2 christos break;
1211 1.1.1.2 christos
1212 1.1.1.2 christos default:
1213 1.1.1.3 christos rps->error_handler
1214 1.1.1.3 christos (_("-march=%s: first ISA subset must be `e', `i' or `g'"), march);
1215 1.1.1.2 christos return NULL;
1216 1.1.1.2 christos }
1217 1.1.1.2 christos
1218 1.1.1.3 christos /* The riscv_parsing_subset_version may set `p` to NULL, so I think we should
1219 1.1.1.3 christos skip parsing the string if `p` is NULL or value of `p` is `\0`. */
1220 1.1.1.3 christos while (p != NULL && *p != '\0')
1221 1.1.1.2 christos {
1222 1.1.1.2 christos char subset[2] = {0, 0};
1223 1.1.1.2 christos
1224 1.1.1.3 christos if (*p == 'x' || *p == 's' || *p == 'z')
1225 1.1.1.2 christos break;
1226 1.1.1.2 christos
1227 1.1.1.2 christos if (*p == '_')
1228 1.1.1.2 christos {
1229 1.1.1.2 christos p++;
1230 1.1.1.2 christos continue;
1231 1.1.1.2 christos }
1232 1.1.1.2 christos
1233 1.1.1.2 christos std_ext = *p;
1234 1.1.1.2 christos
1235 1.1.1.2 christos /* Checking canonical order. */
1236 1.1.1.2 christos while (*std_exts && std_ext != *std_exts) std_exts++;
1237 1.1.1.2 christos
1238 1.1.1.2 christos if (std_ext != *std_exts)
1239 1.1.1.2 christos {
1240 1.1.1.2 christos if (strchr (all_std_exts, std_ext) == NULL)
1241 1.1.1.3 christos rps->error_handler
1242 1.1.1.3 christos (_("-march=%s: unsupported ISA subset `%c'"), march, *p);
1243 1.1.1.2 christos else
1244 1.1.1.3 christos rps->error_handler
1245 1.1.1.3 christos (_("-march=%s: ISA string is not in canonical order. `%c'"),
1246 1.1.1.3 christos march, *p);
1247 1.1.1.2 christos return NULL;
1248 1.1.1.2 christos }
1249 1.1.1.2 christos
1250 1.1.1.2 christos std_exts++;
1251 1.1.1.2 christos
1252 1.1.1.3 christos use_default_version = FALSE;
1253 1.1.1.2 christos subset[0] = std_ext;
1254 1.1.1.3 christos p = riscv_parsing_subset_version (rps,
1255 1.1.1.3 christos march,
1256 1.1.1.3 christos ++p,
1257 1.1.1.3 christos &major_version,
1258 1.1.1.3 christos &minor_version,
1259 1.1.1.3 christos TRUE,
1260 1.1.1.3 christos &use_default_version);
1261 1.1.1.3 christos
1262 1.1.1.3 christos /* Find the default version if needed. */
1263 1.1.1.3 christos if (use_default_version
1264 1.1.1.3 christos && rps->get_default_version != NULL)
1265 1.1.1.3 christos rps->get_default_version (subset,
1266 1.1.1.3 christos &major_version,
1267 1.1.1.3 christos &minor_version);
1268 1.1.1.3 christos riscv_add_subset (rps->subset_list, subset,
1269 1.1.1.3 christos major_version, minor_version);
1270 1.1.1.2 christos }
1271 1.1.1.2 christos return p;
1272 1.1.1.2 christos }
1273 1.1.1.2 christos
1274 1.1.1.3 christos /* Classify the argument 'arch' into one of riscv_isa_ext_class_t. */
1275 1.1.1.2 christos
1276 1.1.1.3 christos riscv_isa_ext_class_t
1277 1.1.1.3 christos riscv_get_prefix_class (const char *arch)
1278 1.1.1.3 christos {
1279 1.1.1.3 christos switch (*arch)
1280 1.1.1.3 christos {
1281 1.1.1.3 christos case 's': return RV_ISA_CLASS_S;
1282 1.1.1.3 christos case 'x': return RV_ISA_CLASS_X;
1283 1.1.1.3 christos case 'z': return RV_ISA_CLASS_Z;
1284 1.1.1.3 christos default: return RV_ISA_CLASS_UNKNOWN;
1285 1.1.1.3 christos }
1286 1.1.1.3 christos }
1287 1.1.1.2 christos
1288 1.1.1.3 christos /* Structure describing parameters to use when parsing a particular
1289 1.1.1.3 christos riscv_isa_ext_class_t. One of these should be provided for each
1290 1.1.1.3 christos possible class, except RV_ISA_CLASS_UNKNOWN. */
1291 1.1.1.3 christos
1292 1.1.1.3 christos typedef struct riscv_parse_config
1293 1.1.1.3 christos {
1294 1.1.1.3 christos /* Class of the extension. */
1295 1.1.1.3 christos riscv_isa_ext_class_t class;
1296 1.1.1.3 christos
1297 1.1.1.3 christos /* Lower-case prefix string for error printing
1298 1.1.1.3 christos and internal parser usage, e.g. "z", "x". */
1299 1.1.1.3 christos const char *prefix;
1300 1.1.1.3 christos
1301 1.1.1.3 christos /* Predicate which is used for checking whether
1302 1.1.1.3 christos this is a "known" extension. For 'x',
1303 1.1.1.3 christos it always returns true (since they are by
1304 1.1.1.3 christos definition non-standard and cannot be known. */
1305 1.1.1.3 christos bfd_boolean (*ext_valid_p) (const char *);
1306 1.1.1.3 christos } riscv_parse_config_t;
1307 1.1.1.3 christos
1308 1.1.1.3 christos /* Parse a generic prefixed extension.
1309 1.1.1.3 christos `rps`: Hooks and status for parsing subset.
1310 1.1.1.3 christos `march`: The full architecture string as passed in by "-march=...".
1311 1.1.1.3 christos `p`: Point from which to start parsing the -march string.
1312 1.1.1.3 christos `config`: What class of extensions to parse, predicate funcs,
1313 1.1.1.3 christos and strings to use in error reporting. */
1314 1.1.1.2 christos
1315 1.1.1.2 christos static const char *
1316 1.1.1.3 christos riscv_parse_prefixed_ext (riscv_parse_subset_t *rps,
1317 1.1.1.3 christos const char *march,
1318 1.1.1.3 christos const char *p,
1319 1.1.1.3 christos const riscv_parse_config_t *config)
1320 1.1.1.2 christos {
1321 1.1.1.2 christos unsigned major_version = 0;
1322 1.1.1.2 christos unsigned minor_version = 0;
1323 1.1.1.3 christos const char *last_name;
1324 1.1.1.3 christos riscv_isa_ext_class_t class;
1325 1.1.1.3 christos bfd_boolean use_default_version;
1326 1.1.1.2 christos
1327 1.1.1.2 christos while (*p)
1328 1.1.1.2 christos {
1329 1.1.1.2 christos if (*p == '_')
1330 1.1.1.2 christos {
1331 1.1.1.2 christos p++;
1332 1.1.1.2 christos continue;
1333 1.1.1.2 christos }
1334 1.1.1.2 christos
1335 1.1.1.3 christos /* Assert that the current extension specifier matches our parsing
1336 1.1.1.3 christos class. */
1337 1.1.1.3 christos class = riscv_get_prefix_class (p);
1338 1.1.1.3 christos if (class != config->class)
1339 1.1.1.2 christos break;
1340 1.1.1.2 christos
1341 1.1.1.2 christos char *subset = xstrdup (p);
1342 1.1.1.2 christos char *q = subset;
1343 1.1.1.2 christos const char *end_of_version;
1344 1.1.1.2 christos
1345 1.1.1.2 christos while (*++q != '\0' && *q != '_' && !ISDIGIT (*q))
1346 1.1.1.2 christos ;
1347 1.1.1.2 christos
1348 1.1.1.3 christos use_default_version = FALSE;
1349 1.1.1.2 christos end_of_version =
1350 1.1.1.3 christos riscv_parsing_subset_version (rps, march, q, &major_version,
1351 1.1.1.3 christos &minor_version, FALSE,
1352 1.1.1.3 christos &use_default_version);
1353 1.1.1.2 christos *q = '\0';
1354 1.1.1.2 christos
1355 1.1.1.3 christos /* Check that the name is valid.
1356 1.1.1.3 christos For 'x', anything goes but it cannot simply be 'x'.
1357 1.1.1.3 christos For 's', it must be known from a list and cannot simply be 's'.
1358 1.1.1.3 christos For 'z', it must be known from a list and cannot simply be 'z'. */
1359 1.1.1.3 christos
1360 1.1.1.3 christos /* Check that the extension name is well-formed. */
1361 1.1.1.3 christos if (!config->ext_valid_p (subset))
1362 1.1.1.3 christos {
1363 1.1.1.3 christos rps->error_handler
1364 1.1.1.3 christos (_("-march=%s: Invalid or unknown %s ISA extension: '%s'"),
1365 1.1.1.3 christos march, config->prefix, subset);
1366 1.1.1.3 christos free (subset);
1367 1.1.1.3 christos return NULL;
1368 1.1.1.3 christos }
1369 1.1.1.3 christos
1370 1.1.1.3 christos /* Check that the last item is not the same as this. */
1371 1.1.1.3 christos last_name = rps->subset_list->tail->name;
1372 1.1.1.3 christos if (!strcasecmp (last_name, subset))
1373 1.1.1.3 christos {
1374 1.1.1.3 christos rps->error_handler
1375 1.1.1.3 christos (_("-march=%s: Duplicate %s ISA extension: \'%s\'"),
1376 1.1.1.3 christos march, config->prefix, subset);
1377 1.1.1.3 christos free (subset);
1378 1.1.1.3 christos return NULL;
1379 1.1.1.3 christos }
1380 1.1.1.3 christos
1381 1.1.1.3 christos /* Check that we are in alphabetical order within the subset. */
1382 1.1.1.3 christos if (!strncasecmp (last_name, config->prefix, 1)
1383 1.1.1.3 christos && strcasecmp (last_name, subset) > 0)
1384 1.1.1.3 christos {
1385 1.1.1.3 christos rps->error_handler
1386 1.1.1.3 christos (_("\
1387 1.1.1.3 christos -march=%s: %s ISA extension not in alphabetical order: \'%s\' must come before \'%s\'."),
1388 1.1.1.3 christos march, config->prefix, subset, last_name);
1389 1.1.1.3 christos free (subset);
1390 1.1.1.3 christos return NULL;
1391 1.1.1.3 christos }
1392 1.1.1.3 christos
1393 1.1.1.3 christos /* Find the default version if needed. */
1394 1.1.1.3 christos if (use_default_version
1395 1.1.1.3 christos && rps->get_default_version != NULL)
1396 1.1.1.3 christos rps->get_default_version (subset,
1397 1.1.1.3 christos &major_version,
1398 1.1.1.3 christos &minor_version);
1399 1.1.1.3 christos riscv_add_subset (rps->subset_list, subset,
1400 1.1.1.3 christos major_version, minor_version);
1401 1.1.1.3 christos
1402 1.1.1.2 christos free (subset);
1403 1.1.1.2 christos p += end_of_version - subset;
1404 1.1.1.2 christos
1405 1.1.1.2 christos if (*p != '\0' && *p != '_')
1406 1.1.1.2 christos {
1407 1.1.1.3 christos rps->error_handler (_("-march=%s: %s must separate with _"),
1408 1.1.1.3 christos march, config->prefix);
1409 1.1.1.2 christos return NULL;
1410 1.1.1.2 christos }
1411 1.1.1.2 christos }
1412 1.1.1.2 christos
1413 1.1.1.2 christos return p;
1414 1.1.1.2 christos }
1415 1.1.1.2 christos
1416 1.1.1.3 christos /* List of Z-class extensions that binutils should know about.
1417 1.1.1.3 christos Whether or not a particular entry is in this list will
1418 1.1.1.3 christos dictate if gas/ld will accept its presence in the -march
1419 1.1.1.3 christos string.
1420 1.1.1.3 christos
1421 1.1.1.3 christos Example: To add an extension called "Zbb" (bitmanip base extension),
1422 1.1.1.3 christos add "zbb" string to the list (all lowercase).
1423 1.1.1.3 christos
1424 1.1.1.3 christos Keep this list alphabetically ordered. */
1425 1.1.1.3 christos
1426 1.1.1.3 christos static const char * const riscv_std_z_ext_strtab[] =
1427 1.1.1.3 christos {
1428 1.1.1.3 christos "zicsr", NULL
1429 1.1.1.3 christos };
1430 1.1.1.3 christos
1431 1.1.1.3 christos /* Same as `riscv_std_z_ext_strtab', but for S-class extensions. */
1432 1.1.1.3 christos
1433 1.1.1.3 christos static const char * const riscv_std_s_ext_strtab[] =
1434 1.1.1.3 christos {
1435 1.1.1.3 christos NULL
1436 1.1.1.3 christos };
1437 1.1.1.3 christos
1438 1.1.1.3 christos /* For the extension EXT, search through the list of known extensions
1439 1.1.1.3 christos KNOWN_EXTS for a match, and return TRUE if found. */
1440 1.1.1.3 christos
1441 1.1.1.3 christos static bfd_boolean
1442 1.1.1.3 christos riscv_multi_letter_ext_valid_p (const char *ext,
1443 1.1.1.3 christos const char *const *known_exts)
1444 1.1.1.3 christos {
1445 1.1.1.3 christos size_t i;
1446 1.1.1.3 christos
1447 1.1.1.3 christos for (i = 0; known_exts[i]; ++i)
1448 1.1.1.3 christos if (!strcmp (ext, known_exts[i]))
1449 1.1.1.3 christos return TRUE;
1450 1.1.1.3 christos
1451 1.1.1.3 christos return FALSE;
1452 1.1.1.3 christos }
1453 1.1.1.3 christos
1454 1.1.1.3 christos /* Predicator function for x-prefixed extensions.
1455 1.1.1.3 christos Anything goes, except the literal 'x'. */
1456 1.1.1.3 christos
1457 1.1.1.3 christos static bfd_boolean
1458 1.1.1.3 christos riscv_ext_x_valid_p (const char *arg)
1459 1.1.1.3 christos {
1460 1.1.1.3 christos if (!strcasecmp (arg, "x"))
1461 1.1.1.3 christos return FALSE;
1462 1.1.1.3 christos
1463 1.1.1.3 christos return TRUE;
1464 1.1.1.3 christos }
1465 1.1.1.3 christos
1466 1.1.1.3 christos /* Predicator functions for z-prefixed extensions.
1467 1.1.1.3 christos Only known z-extensions are permitted. */
1468 1.1.1.3 christos
1469 1.1.1.3 christos static bfd_boolean
1470 1.1.1.3 christos riscv_ext_z_valid_p (const char *arg)
1471 1.1.1.3 christos {
1472 1.1.1.3 christos return riscv_multi_letter_ext_valid_p (arg, riscv_std_z_ext_strtab);
1473 1.1.1.3 christos }
1474 1.1.1.3 christos
1475 1.1.1.3 christos /* Predicator function for 's' prefixed extensions.
1476 1.1.1.3 christos Must be either literal 's', or a known s-prefixed extension. */
1477 1.1.1.3 christos
1478 1.1.1.3 christos static bfd_boolean
1479 1.1.1.3 christos riscv_ext_s_valid_p (const char *arg)
1480 1.1.1.3 christos {
1481 1.1.1.3 christos return riscv_multi_letter_ext_valid_p (arg, riscv_std_s_ext_strtab);
1482 1.1.1.3 christos }
1483 1.1.1.3 christos
1484 1.1.1.3 christos /* Parsing order that is specified by the ISA manual. */
1485 1.1.1.3 christos
1486 1.1.1.3 christos static const riscv_parse_config_t parse_config[] =
1487 1.1.1.3 christos {
1488 1.1.1.3 christos {RV_ISA_CLASS_S, "s", riscv_ext_s_valid_p},
1489 1.1.1.3 christos {RV_ISA_CLASS_Z, "z", riscv_ext_z_valid_p},
1490 1.1.1.3 christos {RV_ISA_CLASS_X, "x", riscv_ext_x_valid_p},
1491 1.1.1.3 christos {RV_ISA_CLASS_UNKNOWN, NULL, NULL}
1492 1.1.1.3 christos };
1493 1.1.1.3 christos
1494 1.1.1.2 christos /* Function for parsing arch string.
1495 1.1.1.2 christos
1496 1.1.1.2 christos Return Value:
1497 1.1.1.2 christos Return TRUE on success.
1498 1.1.1.2 christos
1499 1.1.1.2 christos Arguments:
1500 1.1.1.2 christos `rps`: Hooks and status for parsing subset.
1501 1.1.1.2 christos `arch`: Arch string. */
1502 1.1.1.2 christos
1503 1.1.1.2 christos bfd_boolean
1504 1.1.1.2 christos riscv_parse_subset (riscv_parse_subset_t *rps,
1505 1.1.1.2 christos const char *arch)
1506 1.1.1.2 christos {
1507 1.1.1.2 christos const char *p = arch;
1508 1.1.1.3 christos size_t i;
1509 1.1.1.2 christos
1510 1.1.1.2 christos if (strncmp (p, "rv32", 4) == 0)
1511 1.1.1.2 christos {
1512 1.1.1.2 christos *rps->xlen = 32;
1513 1.1.1.2 christos p += 4;
1514 1.1.1.2 christos }
1515 1.1.1.2 christos else if (strncmp (p, "rv64", 4) == 0)
1516 1.1.1.2 christos {
1517 1.1.1.2 christos *rps->xlen = 64;
1518 1.1.1.2 christos p += 4;
1519 1.1.1.2 christos }
1520 1.1.1.2 christos else
1521 1.1.1.2 christos {
1522 1.1.1.3 christos /* Arch string shouldn't be NULL or empty here. However,
1523 1.1.1.3 christos it might be empty only when we failed to merge the arch
1524 1.1.1.3 christos string in the riscv_merge_attributes. We have already
1525 1.1.1.3 christos issued the correct error message in another side, so do
1526 1.1.1.3 christos not issue this error when the arch string is empty. */
1527 1.1.1.3 christos if (strlen (arch))
1528 1.1.1.3 christos rps->error_handler (
1529 1.1.1.3 christos _("-march=%s: ISA string must begin with rv32 or rv64"),
1530 1.1.1.3 christos arch);
1531 1.1.1.2 christos return FALSE;
1532 1.1.1.2 christos }
1533 1.1.1.2 christos
1534 1.1.1.2 christos /* Parsing standard extension. */
1535 1.1.1.2 christos p = riscv_parse_std_ext (rps, arch, p);
1536 1.1.1.2 christos
1537 1.1.1.2 christos if (p == NULL)
1538 1.1.1.2 christos return FALSE;
1539 1.1.1.2 christos
1540 1.1.1.3 christos /* Parse the different classes of extensions in the specified order. */
1541 1.1.1.3 christos for (i = 0; i < ARRAY_SIZE (parse_config); ++i) {
1542 1.1.1.3 christos p = riscv_parse_prefixed_ext (rps, arch, p, &parse_config[i]);
1543 1.1.1.2 christos
1544 1.1.1.3 christos if (p == NULL)
1545 1.1.1.3 christos return FALSE;
1546 1.1.1.3 christos }
1547 1.1.1.2 christos
1548 1.1.1.2 christos if (*p != '\0')
1549 1.1.1.2 christos {
1550 1.1.1.3 christos rps->error_handler (_("-march=%s: unexpected ISA string at end: %s"),
1551 1.1.1.2 christos arch, p);
1552 1.1.1.2 christos return FALSE;
1553 1.1.1.2 christos }
1554 1.1.1.2 christos
1555 1.1.1.2 christos if (riscv_lookup_subset (rps->subset_list, "e")
1556 1.1.1.2 christos && riscv_lookup_subset (rps->subset_list, "f"))
1557 1.1.1.2 christos {
1558 1.1.1.3 christos rps->error_handler
1559 1.1.1.3 christos (_("-march=%s: rv32e does not support the `f' extension"),
1560 1.1.1.3 christos arch);
1561 1.1.1.2 christos return FALSE;
1562 1.1.1.2 christos }
1563 1.1.1.2 christos
1564 1.1.1.2 christos if (riscv_lookup_subset (rps->subset_list, "d")
1565 1.1.1.2 christos && !riscv_lookup_subset (rps->subset_list, "f"))
1566 1.1.1.2 christos {
1567 1.1.1.3 christos rps->error_handler
1568 1.1.1.3 christos (_("-march=%s: `d' extension requires `f' extension"),
1569 1.1.1.3 christos arch);
1570 1.1.1.2 christos return FALSE;
1571 1.1.1.2 christos }
1572 1.1.1.2 christos
1573 1.1.1.2 christos if (riscv_lookup_subset (rps->subset_list, "q")
1574 1.1.1.2 christos && !riscv_lookup_subset (rps->subset_list, "d"))
1575 1.1.1.2 christos {
1576 1.1.1.3 christos rps->error_handler
1577 1.1.1.3 christos (_("-march=%s: `q' extension requires `d' extension"),
1578 1.1.1.3 christos arch);
1579 1.1.1.2 christos return FALSE;
1580 1.1.1.2 christos }
1581 1.1.1.2 christos
1582 1.1.1.2 christos if (riscv_lookup_subset (rps->subset_list, "q") && *rps->xlen < 64)
1583 1.1.1.2 christos {
1584 1.1.1.3 christos rps->error_handler
1585 1.1.1.3 christos (_("-march=%s: rv32 does not support the `q' extension"),
1586 1.1.1.3 christos arch);
1587 1.1.1.2 christos return FALSE;
1588 1.1.1.2 christos }
1589 1.1.1.2 christos return TRUE;
1590 1.1.1.2 christos }
1591 1.1.1.2 christos
1592 1.1.1.2 christos /* Add new subset to list. */
1593 1.1.1.2 christos
1594 1.1.1.2 christos void
1595 1.1.1.2 christos riscv_add_subset (riscv_subset_list_t *subset_list,
1596 1.1.1.2 christos const char *subset,
1597 1.1.1.3 christos int major,
1598 1.1.1.3 christos int minor)
1599 1.1.1.2 christos {
1600 1.1.1.2 christos riscv_subset_t *s = xmalloc (sizeof *s);
1601 1.1.1.2 christos
1602 1.1.1.2 christos if (subset_list->head == NULL)
1603 1.1.1.2 christos subset_list->head = s;
1604 1.1.1.2 christos
1605 1.1.1.2 christos s->name = xstrdup (subset);
1606 1.1.1.2 christos s->major_version = major;
1607 1.1.1.2 christos s->minor_version = minor;
1608 1.1.1.2 christos s->next = NULL;
1609 1.1.1.2 christos
1610 1.1.1.2 christos if (subset_list->tail != NULL)
1611 1.1.1.2 christos subset_list->tail->next = s;
1612 1.1.1.2 christos
1613 1.1.1.2 christos subset_list->tail = s;
1614 1.1.1.2 christos }
1615 1.1.1.2 christos
1616 1.1.1.2 christos /* Find subset in list without version checking, return NULL if not found. */
1617 1.1.1.2 christos
1618 1.1.1.2 christos riscv_subset_t *
1619 1.1.1.2 christos riscv_lookup_subset (const riscv_subset_list_t *subset_list,
1620 1.1.1.2 christos const char *subset)
1621 1.1.1.2 christos {
1622 1.1.1.3 christos return riscv_lookup_subset_version
1623 1.1.1.3 christos (subset_list, subset,
1624 1.1.1.3 christos RISCV_DONT_CARE_VERSION,
1625 1.1.1.3 christos RISCV_DONT_CARE_VERSION);
1626 1.1.1.2 christos }
1627 1.1.1.2 christos
1628 1.1.1.2 christos /* Find subset in list with version checking, return NULL if not found. */
1629 1.1.1.2 christos
1630 1.1.1.2 christos riscv_subset_t *
1631 1.1.1.2 christos riscv_lookup_subset_version (const riscv_subset_list_t *subset_list,
1632 1.1.1.2 christos const char *subset,
1633 1.1.1.2 christos int major, int minor)
1634 1.1.1.2 christos {
1635 1.1.1.2 christos riscv_subset_t *s;
1636 1.1.1.2 christos
1637 1.1.1.2 christos for (s = subset_list->head; s != NULL; s = s->next)
1638 1.1.1.2 christos if (strcasecmp (s->name, subset) == 0)
1639 1.1.1.2 christos {
1640 1.1.1.2 christos if ((major != RISCV_DONT_CARE_VERSION)
1641 1.1.1.2 christos && (s->major_version != major))
1642 1.1.1.2 christos return NULL;
1643 1.1.1.2 christos
1644 1.1.1.2 christos if ((minor != RISCV_DONT_CARE_VERSION)
1645 1.1.1.2 christos && (s->minor_version != minor))
1646 1.1.1.2 christos return NULL;
1647 1.1.1.2 christos
1648 1.1.1.2 christos return s;
1649 1.1.1.2 christos }
1650 1.1.1.2 christos
1651 1.1.1.2 christos return NULL;
1652 1.1.1.2 christos }
1653 1.1.1.2 christos
1654 1.1.1.2 christos /* Release subset list. */
1655 1.1.1.2 christos
1656 1.1.1.2 christos void
1657 1.1.1.2 christos riscv_release_subset_list (riscv_subset_list_t *subset_list)
1658 1.1.1.2 christos {
1659 1.1.1.2 christos while (subset_list->head != NULL)
1660 1.1.1.2 christos {
1661 1.1.1.2 christos riscv_subset_t *next = subset_list->head->next;
1662 1.1.1.2 christos free ((void *)subset_list->head->name);
1663 1.1.1.2 christos free (subset_list->head);
1664 1.1.1.2 christos subset_list->head = next;
1665 1.1.1.2 christos }
1666 1.1.1.2 christos
1667 1.1.1.2 christos subset_list->tail = NULL;
1668 1.1.1.2 christos }
1669 1.1.1.2 christos
1670 1.1.1.2 christos /* Return the number of digits for the input. */
1671 1.1.1.2 christos
1672 1.1.1.3 christos size_t
1673 1.1.1.2 christos riscv_estimate_digit (unsigned num)
1674 1.1.1.2 christos {
1675 1.1.1.2 christos size_t digit = 0;
1676 1.1.1.2 christos if (num == 0)
1677 1.1.1.2 christos return 1;
1678 1.1.1.2 christos
1679 1.1.1.2 christos for (digit = 0; num ; num /= 10)
1680 1.1.1.2 christos digit++;
1681 1.1.1.2 christos
1682 1.1.1.2 christos return digit;
1683 1.1.1.2 christos }
1684 1.1.1.2 christos
1685 1.1.1.2 christos /* Auxiliary function to estimate string length of subset list. */
1686 1.1.1.2 christos
1687 1.1.1.2 christos static size_t
1688 1.1.1.2 christos riscv_estimate_arch_strlen1 (const riscv_subset_t *subset)
1689 1.1.1.2 christos {
1690 1.1.1.2 christos if (subset == NULL)
1691 1.1.1.2 christos return 6; /* For rv32/rv64/rv128 and string terminator. */
1692 1.1.1.2 christos
1693 1.1.1.2 christos return riscv_estimate_arch_strlen1 (subset->next)
1694 1.1.1.2 christos + strlen (subset->name)
1695 1.1.1.2 christos + riscv_estimate_digit (subset->major_version)
1696 1.1.1.2 christos + 1 /* For version seperator: 'p'. */
1697 1.1.1.2 christos + riscv_estimate_digit (subset->minor_version)
1698 1.1.1.2 christos + 1 /* For underscore. */;
1699 1.1.1.2 christos }
1700 1.1.1.2 christos
1701 1.1.1.2 christos /* Estimate the string length of this subset list. */
1702 1.1.1.2 christos
1703 1.1.1.2 christos static size_t
1704 1.1.1.2 christos riscv_estimate_arch_strlen (const riscv_subset_list_t *subset_list)
1705 1.1.1.2 christos {
1706 1.1.1.2 christos return riscv_estimate_arch_strlen1 (subset_list->head);
1707 1.1.1.2 christos }
1708 1.1.1.2 christos
1709 1.1.1.2 christos /* Auxiliary function to convert subset info to string. */
1710 1.1.1.2 christos
1711 1.1.1.2 christos static void
1712 1.1.1.2 christos riscv_arch_str1 (riscv_subset_t *subset,
1713 1.1.1.2 christos char *attr_str, char *buf, size_t bufsz)
1714 1.1.1.2 christos {
1715 1.1.1.2 christos const char *underline = "_";
1716 1.1.1.2 christos
1717 1.1.1.2 christos if (subset == NULL)
1718 1.1.1.2 christos return;
1719 1.1.1.2 christos
1720 1.1.1.2 christos /* No underline between rvXX and i/e. */
1721 1.1.1.2 christos if ((strcasecmp (subset->name, "i") == 0)
1722 1.1.1.2 christos || (strcasecmp (subset->name, "e") == 0))
1723 1.1.1.2 christos underline = "";
1724 1.1.1.2 christos
1725 1.1.1.2 christos snprintf (buf, bufsz, "%s%s%dp%d",
1726 1.1.1.2 christos underline,
1727 1.1.1.3 christos subset->name,
1728 1.1.1.3 christos subset->major_version,
1729 1.1.1.3 christos subset->minor_version);
1730 1.1.1.2 christos
1731 1.1.1.2 christos strncat (attr_str, buf, bufsz);
1732 1.1.1.2 christos
1733 1.1.1.2 christos /* Skip 'i' extension after 'e'. */
1734 1.1.1.2 christos if ((strcasecmp (subset->name, "e") == 0)
1735 1.1.1.2 christos && subset->next
1736 1.1.1.2 christos && (strcasecmp (subset->next->name, "i") == 0))
1737 1.1.1.2 christos riscv_arch_str1 (subset->next->next, attr_str, buf, bufsz);
1738 1.1.1.2 christos else
1739 1.1.1.2 christos riscv_arch_str1 (subset->next, attr_str, buf, bufsz);
1740 1.1.1.2 christos }
1741 1.1.1.2 christos
1742 1.1.1.2 christos /* Convert subset info to string with explicit version info. */
1743 1.1.1.2 christos
1744 1.1.1.2 christos char *
1745 1.1.1.2 christos riscv_arch_str (unsigned xlen, const riscv_subset_list_t *subset)
1746 1.1.1.2 christos {
1747 1.1.1.2 christos size_t arch_str_len = riscv_estimate_arch_strlen (subset);
1748 1.1.1.2 christos char *attr_str = xmalloc (arch_str_len);
1749 1.1.1.2 christos char *buf = xmalloc (arch_str_len);
1750 1.1.1.2 christos
1751 1.1.1.2 christos snprintf (attr_str, arch_str_len, "rv%u", xlen);
1752 1.1.1.2 christos
1753 1.1.1.2 christos riscv_arch_str1 (subset->head, attr_str, buf, arch_str_len);
1754 1.1.1.2 christos free (buf);
1755 1.1.1.2 christos
1756 1.1.1.2 christos return attr_str;
1757 1.1.1.2 christos }
1758