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