1 /* RISC-V-specific support for ELF.
2 Copyright (C) 2011-2021 Free Software Foundation, Inc.
4 Contributed by Andrew Waterman (andrew@sifive.com).
5 Based on TILE-Gx and MIPS targets.
7 This file is part of BFD, the Binary File Descriptor library.
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.
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.
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/>. */
27 #include "elf/riscv.h"
28 #include "opcode/riscv.h"
29 #include "libiberty.h"
30 #include "elfxx-riscv.h"
31 #include "safe-ctype.h"
32 #include "cpu-riscv.h"
34 #define MINUS_ONE ((bfd_vma)0 - 1)
36 /* Special handler for ADD/SUB relocations that allows them to be filled out
37 both in the pre-linked and post-linked file. This is necessary to make
38 pre-linked debug info work, as due to linker relaxations we need to emit
39 relocations for the debug info. */
40 static bfd_reloc_status_type riscv_elf_add_sub_reloc
41 (bfd
*, arelent
*, asymbol
*, void *, asection
*, bfd
*, char **);
43 /* The relocation table used for SHT_RELA sections. */
45 static reloc_howto_type howto_table
[] =
48 HOWTO (R_RISCV_NONE
, /* type */
52 false, /* pc_relative */
54 complain_overflow_dont
, /* complain_on_overflow */
55 bfd_elf_generic_reloc
, /* special_function */
56 "R_RISCV_NONE", /* name */
57 false, /* partial_inplace */
60 false), /* pcrel_offset */
62 /* 32 bit relocation. */
63 HOWTO (R_RISCV_32
, /* type */
67 false, /* pc_relative */
69 complain_overflow_dont
, /* complain_on_overflow */
70 bfd_elf_generic_reloc
, /* special_function */
71 "R_RISCV_32", /* name */
72 false, /* partial_inplace */
74 0xffffffff, /* dst_mask */
75 false), /* pcrel_offset */
77 /* 64 bit relocation. */
78 HOWTO (R_RISCV_64
, /* type */
82 false, /* pc_relative */
84 complain_overflow_dont
, /* complain_on_overflow */
85 bfd_elf_generic_reloc
, /* special_function */
86 "R_RISCV_64", /* name */
87 false, /* partial_inplace */
89 MINUS_ONE
, /* dst_mask */
90 false), /* pcrel_offset */
92 /* Relocation against a local symbol in a shared object. */
93 HOWTO (R_RISCV_RELATIVE
, /* type */
97 false, /* pc_relative */
99 complain_overflow_dont
, /* complain_on_overflow */
100 bfd_elf_generic_reloc
, /* special_function */
101 "R_RISCV_RELATIVE", /* name */
102 false, /* partial_inplace */
104 0xffffffff, /* dst_mask */
105 false), /* pcrel_offset */
107 HOWTO (R_RISCV_COPY
, /* type */
109 0, /* this one is variable size */
111 false, /* pc_relative */
113 complain_overflow_bitfield
, /* complain_on_overflow */
114 bfd_elf_generic_reloc
, /* special_function */
115 "R_RISCV_COPY", /* name */
116 false, /* partial_inplace */
119 false), /* pcrel_offset */
121 HOWTO (R_RISCV_JUMP_SLOT
, /* type */
125 false, /* pc_relative */
127 complain_overflow_bitfield
, /* complain_on_overflow */
128 bfd_elf_generic_reloc
, /* special_function */
129 "R_RISCV_JUMP_SLOT", /* name */
130 false, /* partial_inplace */
133 false), /* pcrel_offset */
135 /* Dynamic TLS relocations. */
136 HOWTO (R_RISCV_TLS_DTPMOD32
, /* type */
140 false, /* pc_relative */
142 complain_overflow_dont
, /* complain_on_overflow */
143 bfd_elf_generic_reloc
, /* special_function */
144 "R_RISCV_TLS_DTPMOD32", /* name */
145 false, /* partial_inplace */
147 0xffffffff, /* dst_mask */
148 false), /* pcrel_offset */
150 HOWTO (R_RISCV_TLS_DTPMOD64
, /* type */
154 false, /* pc_relative */
156 complain_overflow_dont
, /* complain_on_overflow */
157 bfd_elf_generic_reloc
, /* special_function */
158 "R_RISCV_TLS_DTPMOD64", /* name */
159 false, /* partial_inplace */
161 MINUS_ONE
, /* dst_mask */
162 false), /* pcrel_offset */
164 HOWTO (R_RISCV_TLS_DTPREL32
, /* type */
168 false, /* pc_relative */
170 complain_overflow_dont
, /* complain_on_overflow */
171 bfd_elf_generic_reloc
, /* special_function */
172 "R_RISCV_TLS_DTPREL32", /* name */
173 true, /* partial_inplace */
175 0xffffffff, /* dst_mask */
176 false), /* pcrel_offset */
178 HOWTO (R_RISCV_TLS_DTPREL64
, /* type */
182 false, /* pc_relative */
184 complain_overflow_dont
, /* complain_on_overflow */
185 bfd_elf_generic_reloc
, /* special_function */
186 "R_RISCV_TLS_DTPREL64", /* name */
187 true, /* partial_inplace */
189 MINUS_ONE
, /* dst_mask */
190 false), /* pcrel_offset */
192 HOWTO (R_RISCV_TLS_TPREL32
, /* type */
196 false, /* pc_relative */
198 complain_overflow_dont
, /* complain_on_overflow */
199 bfd_elf_generic_reloc
, /* special_function */
200 "R_RISCV_TLS_TPREL32", /* name */
201 false, /* partial_inplace */
203 0xffffffff, /* dst_mask */
204 false), /* pcrel_offset */
206 HOWTO (R_RISCV_TLS_TPREL64
, /* type */
210 false, /* pc_relative */
212 complain_overflow_dont
, /* complain_on_overflow */
213 bfd_elf_generic_reloc
, /* special_function */
214 "R_RISCV_TLS_TPREL64", /* name */
215 false, /* partial_inplace */
217 MINUS_ONE
, /* dst_mask */
218 false), /* pcrel_offset */
220 /* Reserved for future relocs that the dynamic linker must understand. */
226 /* 12-bit PC-relative branch offset. */
227 HOWTO (R_RISCV_BRANCH
, /* type */
231 true, /* pc_relative */
233 complain_overflow_signed
, /* complain_on_overflow */
234 bfd_elf_generic_reloc
, /* special_function */
235 "R_RISCV_BRANCH", /* name */
236 false, /* partial_inplace */
238 ENCODE_BTYPE_IMM (-1U), /* dst_mask */
239 true), /* pcrel_offset */
241 /* 20-bit PC-relative jump offset. */
242 HOWTO (R_RISCV_JAL
, /* type */
246 true, /* pc_relative */
248 complain_overflow_dont
, /* complain_on_overflow */
249 bfd_elf_generic_reloc
, /* special_function */
250 "R_RISCV_JAL", /* name */
251 false, /* partial_inplace */
253 ENCODE_JTYPE_IMM (-1U), /* dst_mask */
254 true), /* pcrel_offset */
256 /* 32-bit PC-relative function call (AUIPC/JALR). */
257 HOWTO (R_RISCV_CALL
, /* type */
261 true, /* pc_relative */
263 complain_overflow_dont
, /* complain_on_overflow */
264 bfd_elf_generic_reloc
, /* special_function */
265 "R_RISCV_CALL", /* name */
266 false, /* partial_inplace */
268 ENCODE_UTYPE_IMM (-1U) | ((bfd_vma
) ENCODE_ITYPE_IMM (-1U) << 32),
270 true), /* pcrel_offset */
272 /* Like R_RISCV_CALL, but not locally binding. */
273 HOWTO (R_RISCV_CALL_PLT
, /* type */
277 true, /* pc_relative */
279 complain_overflow_dont
, /* complain_on_overflow */
280 bfd_elf_generic_reloc
, /* special_function */
281 "R_RISCV_CALL_PLT", /* name */
282 false, /* partial_inplace */
284 ENCODE_UTYPE_IMM (-1U) | ((bfd_vma
) ENCODE_ITYPE_IMM (-1U) << 32),
286 true), /* pcrel_offset */
288 /* High 20 bits of 32-bit PC-relative GOT access. */
289 HOWTO (R_RISCV_GOT_HI20
, /* type */
293 true, /* pc_relative */
295 complain_overflow_dont
, /* complain_on_overflow */
296 bfd_elf_generic_reloc
, /* special_function */
297 "R_RISCV_GOT_HI20", /* name */
298 false, /* partial_inplace */
300 ENCODE_UTYPE_IMM (-1U), /* dst_mask */
301 false), /* pcrel_offset */
303 /* High 20 bits of 32-bit PC-relative TLS IE GOT access. */
304 HOWTO (R_RISCV_TLS_GOT_HI20
, /* type */
308 true, /* pc_relative */
310 complain_overflow_dont
, /* complain_on_overflow */
311 bfd_elf_generic_reloc
, /* special_function */
312 "R_RISCV_TLS_GOT_HI20", /* name */
313 false, /* partial_inplace */
315 ENCODE_UTYPE_IMM (-1U), /* dst_mask */
316 false), /* pcrel_offset */
318 /* High 20 bits of 32-bit PC-relative TLS GD GOT reference. */
319 HOWTO (R_RISCV_TLS_GD_HI20
, /* type */
323 true, /* pc_relative */
325 complain_overflow_dont
, /* complain_on_overflow */
326 bfd_elf_generic_reloc
, /* special_function */
327 "R_RISCV_TLS_GD_HI20", /* name */
328 false, /* partial_inplace */
330 ENCODE_UTYPE_IMM (-1U), /* dst_mask */
331 false), /* pcrel_offset */
333 /* High 20 bits of 32-bit PC-relative reference. */
334 HOWTO (R_RISCV_PCREL_HI20
, /* type */
338 true, /* pc_relative */
340 complain_overflow_dont
, /* complain_on_overflow */
341 bfd_elf_generic_reloc
, /* special_function */
342 "R_RISCV_PCREL_HI20", /* name */
343 false, /* partial_inplace */
345 ENCODE_UTYPE_IMM (-1U), /* dst_mask */
346 true), /* pcrel_offset */
348 /* Low 12 bits of a 32-bit PC-relative load or add. */
349 HOWTO (R_RISCV_PCREL_LO12_I
, /* type */
353 false, /* pc_relative */
355 complain_overflow_dont
, /* complain_on_overflow */
356 bfd_elf_generic_reloc
, /* special_function */
357 "R_RISCV_PCREL_LO12_I", /* name */
358 false, /* partial_inplace */
360 ENCODE_ITYPE_IMM (-1U), /* dst_mask */
361 false), /* pcrel_offset */
363 /* Low 12 bits of a 32-bit PC-relative store. */
364 HOWTO (R_RISCV_PCREL_LO12_S
, /* type */
368 false, /* pc_relative */
370 complain_overflow_dont
, /* complain_on_overflow */
371 bfd_elf_generic_reloc
, /* special_function */
372 "R_RISCV_PCREL_LO12_S", /* name */
373 false, /* partial_inplace */
375 ENCODE_STYPE_IMM (-1U), /* dst_mask */
376 false), /* pcrel_offset */
378 /* High 20 bits of 32-bit absolute address. */
379 HOWTO (R_RISCV_HI20
, /* type */
383 false, /* pc_relative */
385 complain_overflow_dont
, /* complain_on_overflow */
386 bfd_elf_generic_reloc
, /* special_function */
387 "R_RISCV_HI20", /* name */
388 false, /* partial_inplace */
390 ENCODE_UTYPE_IMM (-1U), /* dst_mask */
391 false), /* pcrel_offset */
393 /* High 12 bits of 32-bit load or add. */
394 HOWTO (R_RISCV_LO12_I
, /* type */
398 false, /* pc_relative */
400 complain_overflow_dont
, /* complain_on_overflow */
401 bfd_elf_generic_reloc
, /* special_function */
402 "R_RISCV_LO12_I", /* name */
403 false, /* partial_inplace */
405 ENCODE_ITYPE_IMM (-1U), /* dst_mask */
406 false), /* pcrel_offset */
408 /* High 12 bits of 32-bit store. */
409 HOWTO (R_RISCV_LO12_S
, /* type */
413 false, /* pc_relative */
415 complain_overflow_dont
, /* complain_on_overflow */
416 bfd_elf_generic_reloc
, /* special_function */
417 "R_RISCV_LO12_S", /* name */
418 false, /* partial_inplace */
420 ENCODE_STYPE_IMM (-1U), /* dst_mask */
421 false), /* pcrel_offset */
423 /* High 20 bits of TLS LE thread pointer offset. */
424 HOWTO (R_RISCV_TPREL_HI20
, /* type */
428 false, /* pc_relative */
430 complain_overflow_signed
, /* complain_on_overflow */
431 bfd_elf_generic_reloc
, /* special_function */
432 "R_RISCV_TPREL_HI20", /* name */
433 true, /* partial_inplace */
435 ENCODE_UTYPE_IMM (-1U), /* dst_mask */
436 false), /* pcrel_offset */
438 /* Low 12 bits of TLS LE thread pointer offset for loads and adds. */
439 HOWTO (R_RISCV_TPREL_LO12_I
, /* type */
443 false, /* pc_relative */
445 complain_overflow_signed
, /* complain_on_overflow */
446 bfd_elf_generic_reloc
, /* special_function */
447 "R_RISCV_TPREL_LO12_I", /* name */
448 false, /* partial_inplace */
450 ENCODE_ITYPE_IMM (-1U), /* dst_mask */
451 false), /* pcrel_offset */
453 /* Low 12 bits of TLS LE thread pointer offset for stores. */
454 HOWTO (R_RISCV_TPREL_LO12_S
, /* type */
458 false, /* pc_relative */
460 complain_overflow_signed
, /* complain_on_overflow */
461 bfd_elf_generic_reloc
, /* special_function */
462 "R_RISCV_TPREL_LO12_S", /* name */
463 false, /* partial_inplace */
465 ENCODE_STYPE_IMM (-1U), /* dst_mask */
466 false), /* pcrel_offset */
468 /* TLS LE thread pointer usage. May be relaxed. */
469 HOWTO (R_RISCV_TPREL_ADD
, /* type */
473 false, /* pc_relative */
475 complain_overflow_dont
, /* complain_on_overflow */
476 bfd_elf_generic_reloc
, /* special_function */
477 "R_RISCV_TPREL_ADD", /* name */
478 false, /* partial_inplace */
481 false), /* pcrel_offset */
483 /* 8-bit in-place addition, for local label subtraction. */
484 HOWTO (R_RISCV_ADD8
, /* type */
488 false, /* pc_relative */
490 complain_overflow_dont
, /* complain_on_overflow */
491 riscv_elf_add_sub_reloc
, /* special_function */
492 "R_RISCV_ADD8", /* name */
493 false, /* partial_inplace */
496 false), /* pcrel_offset */
498 /* 16-bit in-place addition, for local label subtraction. */
499 HOWTO (R_RISCV_ADD16
, /* type */
503 false, /* pc_relative */
505 complain_overflow_dont
, /* complain_on_overflow */
506 riscv_elf_add_sub_reloc
, /* special_function */
507 "R_RISCV_ADD16", /* name */
508 false, /* partial_inplace */
510 0xffff, /* dst_mask */
511 false), /* pcrel_offset */
513 /* 32-bit in-place addition, for local label subtraction. */
514 HOWTO (R_RISCV_ADD32
, /* type */
518 false, /* pc_relative */
520 complain_overflow_dont
, /* complain_on_overflow */
521 riscv_elf_add_sub_reloc
, /* special_function */
522 "R_RISCV_ADD32", /* name */
523 false, /* partial_inplace */
525 0xffffffff, /* dst_mask */
526 false), /* pcrel_offset */
528 /* 64-bit in-place addition, for local label subtraction. */
529 HOWTO (R_RISCV_ADD64
, /* type */
533 false, /* pc_relative */
535 complain_overflow_dont
, /* complain_on_overflow */
536 riscv_elf_add_sub_reloc
, /* special_function */
537 "R_RISCV_ADD64", /* name */
538 false, /* partial_inplace */
540 MINUS_ONE
, /* dst_mask */
541 false), /* pcrel_offset */
543 /* 8-bit in-place addition, for local label subtraction. */
544 HOWTO (R_RISCV_SUB8
, /* type */
548 false, /* pc_relative */
550 complain_overflow_dont
, /* complain_on_overflow */
551 riscv_elf_add_sub_reloc
, /* special_function */
552 "R_RISCV_SUB8", /* name */
553 false, /* partial_inplace */
556 false), /* pcrel_offset */
558 /* 16-bit in-place addition, for local label subtraction. */
559 HOWTO (R_RISCV_SUB16
, /* type */
563 false, /* pc_relative */
565 complain_overflow_dont
, /* complain_on_overflow */
566 riscv_elf_add_sub_reloc
, /* special_function */
567 "R_RISCV_SUB16", /* name */
568 false, /* partial_inplace */
570 0xffff, /* dst_mask */
571 false), /* pcrel_offset */
573 /* 32-bit in-place addition, for local label subtraction. */
574 HOWTO (R_RISCV_SUB32
, /* type */
578 false, /* pc_relative */
580 complain_overflow_dont
, /* complain_on_overflow */
581 riscv_elf_add_sub_reloc
, /* special_function */
582 "R_RISCV_SUB32", /* name */
583 false, /* partial_inplace */
585 0xffffffff, /* dst_mask */
586 false), /* pcrel_offset */
588 /* 64-bit in-place addition, for local label subtraction. */
589 HOWTO (R_RISCV_SUB64
, /* type */
593 false, /* pc_relative */
595 complain_overflow_dont
, /* complain_on_overflow */
596 riscv_elf_add_sub_reloc
, /* special_function */
597 "R_RISCV_SUB64", /* name */
598 false, /* partial_inplace */
600 MINUS_ONE
, /* dst_mask */
601 false), /* pcrel_offset */
603 /* GNU extension to record C++ vtable hierarchy */
604 HOWTO (R_RISCV_GNU_VTINHERIT
, /* type */
608 false, /* pc_relative */
610 complain_overflow_dont
, /* complain_on_overflow */
611 NULL
, /* special_function */
612 "R_RISCV_GNU_VTINHERIT", /* name */
613 false, /* partial_inplace */
616 false), /* pcrel_offset */
618 /* GNU extension to record C++ vtable member usage */
619 HOWTO (R_RISCV_GNU_VTENTRY
, /* type */
623 false, /* pc_relative */
625 complain_overflow_dont
, /* complain_on_overflow */
626 _bfd_elf_rel_vtable_reloc_fn
, /* special_function */
627 "R_RISCV_GNU_VTENTRY", /* name */
628 false, /* partial_inplace */
631 false), /* pcrel_offset */
633 /* Indicates an alignment statement. The addend field encodes how many
634 bytes of NOPs follow the statement. The desired alignment is the
635 addend rounded up to the next power of two. */
636 HOWTO (R_RISCV_ALIGN
, /* type */
640 false, /* pc_relative */
642 complain_overflow_dont
, /* complain_on_overflow */
643 bfd_elf_generic_reloc
, /* special_function */
644 "R_RISCV_ALIGN", /* name */
645 false, /* partial_inplace */
648 false), /* pcrel_offset */
650 /* 8-bit PC-relative branch offset. */
651 HOWTO (R_RISCV_RVC_BRANCH
, /* type */
655 true, /* pc_relative */
657 complain_overflow_signed
, /* complain_on_overflow */
658 bfd_elf_generic_reloc
, /* special_function */
659 "R_RISCV_RVC_BRANCH", /* name */
660 false, /* partial_inplace */
662 ENCODE_CBTYPE_IMM (-1U), /* dst_mask */
663 true), /* pcrel_offset */
665 /* 11-bit PC-relative jump offset. */
666 HOWTO (R_RISCV_RVC_JUMP
, /* type */
670 true, /* pc_relative */
672 complain_overflow_dont
, /* complain_on_overflow */
673 bfd_elf_generic_reloc
, /* special_function */
674 "R_RISCV_RVC_JUMP", /* name */
675 false, /* partial_inplace */
677 ENCODE_CJTYPE_IMM (-1U), /* dst_mask */
678 true), /* pcrel_offset */
680 /* High 6 bits of 18-bit absolute address. */
681 HOWTO (R_RISCV_RVC_LUI
, /* type */
685 false, /* pc_relative */
687 complain_overflow_dont
, /* complain_on_overflow */
688 bfd_elf_generic_reloc
, /* special_function */
689 "R_RISCV_RVC_LUI", /* name */
690 false, /* partial_inplace */
692 ENCODE_CITYPE_IMM (-1U), /* dst_mask */
693 false), /* pcrel_offset */
695 /* GP-relative load. */
696 HOWTO (R_RISCV_GPREL_I
, /* type */
700 false, /* pc_relative */
702 complain_overflow_dont
, /* complain_on_overflow */
703 bfd_elf_generic_reloc
, /* special_function */
704 "R_RISCV_GPREL_I", /* name */
705 false, /* partial_inplace */
707 ENCODE_ITYPE_IMM (-1U), /* dst_mask */
708 false), /* pcrel_offset */
710 /* GP-relative store. */
711 HOWTO (R_RISCV_GPREL_S
, /* type */
715 false, /* pc_relative */
717 complain_overflow_dont
, /* complain_on_overflow */
718 bfd_elf_generic_reloc
, /* special_function */
719 "R_RISCV_GPREL_S", /* name */
720 false, /* partial_inplace */
722 ENCODE_STYPE_IMM (-1U), /* dst_mask */
723 false), /* pcrel_offset */
725 /* TP-relative TLS LE load. */
726 HOWTO (R_RISCV_TPREL_I
, /* type */
730 false, /* pc_relative */
732 complain_overflow_signed
, /* complain_on_overflow */
733 bfd_elf_generic_reloc
, /* special_function */
734 "R_RISCV_TPREL_I", /* name */
735 false, /* partial_inplace */
737 ENCODE_ITYPE_IMM (-1U), /* dst_mask */
738 false), /* pcrel_offset */
740 /* TP-relative TLS LE store. */
741 HOWTO (R_RISCV_TPREL_S
, /* type */
745 false, /* pc_relative */
747 complain_overflow_signed
, /* complain_on_overflow */
748 bfd_elf_generic_reloc
, /* special_function */
749 "R_RISCV_TPREL_S", /* name */
750 false, /* partial_inplace */
752 ENCODE_STYPE_IMM (-1U), /* dst_mask */
753 false), /* pcrel_offset */
755 /* The paired relocation may be relaxed. */
756 HOWTO (R_RISCV_RELAX
, /* type */
760 false, /* pc_relative */
762 complain_overflow_dont
, /* complain_on_overflow */
763 bfd_elf_generic_reloc
, /* special_function */
764 "R_RISCV_RELAX", /* name */
765 false, /* partial_inplace */
768 false), /* pcrel_offset */
770 /* 6-bit in-place addition, for local label subtraction. */
771 HOWTO (R_RISCV_SUB6
, /* type */
775 false, /* pc_relative */
777 complain_overflow_dont
, /* complain_on_overflow */
778 riscv_elf_add_sub_reloc
, /* special_function */
779 "R_RISCV_SUB6", /* name */
780 false, /* partial_inplace */
783 false), /* pcrel_offset */
785 /* 6-bit in-place setting, for local label subtraction. */
786 HOWTO (R_RISCV_SET6
, /* type */
790 false, /* pc_relative */
792 complain_overflow_dont
, /* complain_on_overflow */
793 bfd_elf_generic_reloc
, /* special_function */
794 "R_RISCV_SET6", /* name */
795 false, /* partial_inplace */
798 false), /* pcrel_offset */
800 /* 8-bit in-place setting, for local label subtraction. */
801 HOWTO (R_RISCV_SET8
, /* type */
805 false, /* pc_relative */
807 complain_overflow_dont
, /* complain_on_overflow */
808 bfd_elf_generic_reloc
, /* special_function */
809 "R_RISCV_SET8", /* name */
810 false, /* partial_inplace */
813 false), /* pcrel_offset */
815 /* 16-bit in-place setting, for local label subtraction. */
816 HOWTO (R_RISCV_SET16
, /* type */
820 false, /* pc_relative */
822 complain_overflow_dont
, /* complain_on_overflow */
823 bfd_elf_generic_reloc
, /* special_function */
824 "R_RISCV_SET16", /* name */
825 false, /* partial_inplace */
827 0xffff, /* dst_mask */
828 false), /* pcrel_offset */
830 /* 32-bit in-place setting, for local label subtraction. */
831 HOWTO (R_RISCV_SET32
, /* type */
835 false, /* pc_relative */
837 complain_overflow_dont
, /* complain_on_overflow */
838 bfd_elf_generic_reloc
, /* special_function */
839 "R_RISCV_SET32", /* name */
840 false, /* partial_inplace */
842 0xffffffff, /* dst_mask */
843 false), /* pcrel_offset */
845 /* 32-bit PC relative. */
846 HOWTO (R_RISCV_32_PCREL
, /* type */
850 true, /* pc_relative */
852 complain_overflow_dont
, /* complain_on_overflow */
853 bfd_elf_generic_reloc
, /* special_function */
854 "R_RISCV_32_PCREL", /* name */
855 false, /* partial_inplace */
857 0xffffffff, /* dst_mask */
858 false), /* pcrel_offset */
860 /* Relocation against a local ifunc symbol in a shared object. */
861 HOWTO (R_RISCV_IRELATIVE
, /* type */
865 false, /* pc_relative */
867 complain_overflow_dont
, /* complain_on_overflow */
868 bfd_elf_generic_reloc
, /* special_function */
869 "R_RISCV_IRELATIVE", /* name */
870 false, /* partial_inplace */
872 0xffffffff, /* dst_mask */
873 false), /* pcrel_offset */
876 /* A mapping from BFD reloc types to RISC-V ELF reloc types. */
879 bfd_reloc_code_real_type bfd_val
;
880 enum elf_riscv_reloc_type elf_val
;
883 static const struct elf_reloc_map riscv_reloc_map
[] =
885 { BFD_RELOC_NONE
, R_RISCV_NONE
},
886 { BFD_RELOC_32
, R_RISCV_32
},
887 { BFD_RELOC_64
, R_RISCV_64
},
888 { BFD_RELOC_RISCV_ADD8
, R_RISCV_ADD8
},
889 { BFD_RELOC_RISCV_ADD16
, R_RISCV_ADD16
},
890 { BFD_RELOC_RISCV_ADD32
, R_RISCV_ADD32
},
891 { BFD_RELOC_RISCV_ADD64
, R_RISCV_ADD64
},
892 { BFD_RELOC_RISCV_SUB8
, R_RISCV_SUB8
},
893 { BFD_RELOC_RISCV_SUB16
, R_RISCV_SUB16
},
894 { BFD_RELOC_RISCV_SUB32
, R_RISCV_SUB32
},
895 { BFD_RELOC_RISCV_SUB64
, R_RISCV_SUB64
},
896 { BFD_RELOC_CTOR
, R_RISCV_64
},
897 { BFD_RELOC_12_PCREL
, R_RISCV_BRANCH
},
898 { BFD_RELOC_RISCV_HI20
, R_RISCV_HI20
},
899 { BFD_RELOC_RISCV_LO12_I
, R_RISCV_LO12_I
},
900 { BFD_RELOC_RISCV_LO12_S
, R_RISCV_LO12_S
},
901 { BFD_RELOC_RISCV_PCREL_LO12_I
, R_RISCV_PCREL_LO12_I
},
902 { BFD_RELOC_RISCV_PCREL_LO12_S
, R_RISCV_PCREL_LO12_S
},
903 { BFD_RELOC_RISCV_CALL
, R_RISCV_CALL
},
904 { BFD_RELOC_RISCV_CALL_PLT
, R_RISCV_CALL_PLT
},
905 { BFD_RELOC_RISCV_PCREL_HI20
, R_RISCV_PCREL_HI20
},
906 { BFD_RELOC_RISCV_JMP
, R_RISCV_JAL
},
907 { BFD_RELOC_RISCV_GOT_HI20
, R_RISCV_GOT_HI20
},
908 { BFD_RELOC_RISCV_TLS_DTPMOD32
, R_RISCV_TLS_DTPMOD32
},
909 { BFD_RELOC_RISCV_TLS_DTPREL32
, R_RISCV_TLS_DTPREL32
},
910 { BFD_RELOC_RISCV_TLS_DTPMOD64
, R_RISCV_TLS_DTPMOD64
},
911 { BFD_RELOC_RISCV_TLS_DTPREL64
, R_RISCV_TLS_DTPREL64
},
912 { BFD_RELOC_RISCV_TLS_TPREL32
, R_RISCV_TLS_TPREL32
},
913 { BFD_RELOC_RISCV_TLS_TPREL64
, R_RISCV_TLS_TPREL64
},
914 { BFD_RELOC_RISCV_TPREL_HI20
, R_RISCV_TPREL_HI20
},
915 { BFD_RELOC_RISCV_TPREL_ADD
, R_RISCV_TPREL_ADD
},
916 { BFD_RELOC_RISCV_TPREL_LO12_S
, R_RISCV_TPREL_LO12_S
},
917 { BFD_RELOC_RISCV_TPREL_LO12_I
, R_RISCV_TPREL_LO12_I
},
918 { BFD_RELOC_RISCV_TLS_GOT_HI20
, R_RISCV_TLS_GOT_HI20
},
919 { BFD_RELOC_RISCV_TLS_GD_HI20
, R_RISCV_TLS_GD_HI20
},
920 { BFD_RELOC_RISCV_ALIGN
, R_RISCV_ALIGN
},
921 { BFD_RELOC_RISCV_RVC_BRANCH
, R_RISCV_RVC_BRANCH
},
922 { BFD_RELOC_RISCV_RVC_JUMP
, R_RISCV_RVC_JUMP
},
923 { BFD_RELOC_RISCV_RVC_LUI
, R_RISCV_RVC_LUI
},
924 { BFD_RELOC_RISCV_GPREL_I
, R_RISCV_GPREL_I
},
925 { BFD_RELOC_RISCV_GPREL_S
, R_RISCV_GPREL_S
},
926 { BFD_RELOC_RISCV_TPREL_I
, R_RISCV_TPREL_I
},
927 { BFD_RELOC_RISCV_TPREL_S
, R_RISCV_TPREL_S
},
928 { BFD_RELOC_RISCV_RELAX
, R_RISCV_RELAX
},
929 { BFD_RELOC_RISCV_SUB6
, R_RISCV_SUB6
},
930 { BFD_RELOC_RISCV_SET6
, R_RISCV_SET6
},
931 { BFD_RELOC_RISCV_SET8
, R_RISCV_SET8
},
932 { BFD_RELOC_RISCV_SET16
, R_RISCV_SET16
},
933 { BFD_RELOC_RISCV_SET32
, R_RISCV_SET32
},
934 { BFD_RELOC_RISCV_32_PCREL
, R_RISCV_32_PCREL
},
937 /* Given a BFD reloc type, return a howto structure. */
940 riscv_reloc_type_lookup (bfd
*abfd ATTRIBUTE_UNUSED
,
941 bfd_reloc_code_real_type code
)
945 for (i
= 0; i
< ARRAY_SIZE (riscv_reloc_map
); i
++)
946 if (riscv_reloc_map
[i
].bfd_val
== code
)
947 return &howto_table
[(int) riscv_reloc_map
[i
].elf_val
];
949 bfd_set_error (bfd_error_bad_value
);
954 riscv_reloc_name_lookup (bfd
*abfd ATTRIBUTE_UNUSED
, const char *r_name
)
958 for (i
= 0; i
< ARRAY_SIZE (howto_table
); i
++)
959 if (howto_table
[i
].name
&& strcasecmp (howto_table
[i
].name
, r_name
) == 0)
960 return &howto_table
[i
];
966 riscv_elf_rtype_to_howto (bfd
*abfd
, unsigned int r_type
)
968 if (r_type
>= ARRAY_SIZE (howto_table
))
970 (*_bfd_error_handler
) (_("%pB: unsupported relocation type %#x"),
972 bfd_set_error (bfd_error_bad_value
);
975 return &howto_table
[r_type
];
978 /* Special_function of RISCV_ADD and RISCV_SUB relocations. */
980 static bfd_reloc_status_type
981 riscv_elf_add_sub_reloc (bfd
*abfd
,
982 arelent
*reloc_entry
,
985 asection
*input_section
,
987 char **error_message ATTRIBUTE_UNUSED
)
989 reloc_howto_type
*howto
= reloc_entry
->howto
;
992 if (output_bfd
!= NULL
993 && (symbol
->flags
& BSF_SECTION_SYM
) == 0
994 && (!reloc_entry
->howto
->partial_inplace
|| reloc_entry
->addend
== 0))
996 reloc_entry
->address
+= input_section
->output_offset
;
1000 if (output_bfd
!= NULL
)
1001 return bfd_reloc_continue
;
1003 relocation
= symbol
->value
+ symbol
->section
->output_section
->vma
1004 + symbol
->section
->output_offset
+ reloc_entry
->addend
;
1005 bfd_vma old_value
= bfd_get (howto
->bitsize
, abfd
,
1006 data
+ reloc_entry
->address
);
1008 switch (howto
->type
)
1014 relocation
= old_value
+ relocation
;
1021 relocation
= old_value
- relocation
;
1024 bfd_put (howto
->bitsize
, abfd
, relocation
, data
+ reloc_entry
->address
);
1026 return bfd_reloc_ok
;
1029 #define RISCV_UNKNOWN_VERSION -1
1031 /* Array is used to compare the orders of all extensions quickly.
1033 Zero value: Preserved keyword.
1034 Negative value: Prefixed keyword (s, h, x, z).
1035 Positive value: Standard extension. */
1036 static int riscv_ext_order
[26] = {0};
1038 /* Similar to the strcmp. It returns an integer less than, equal to,
1039 or greater than zero if `subset2` is found, respectively, to be less
1040 than, to match, or be greater than `subset1`. */
1043 riscv_compare_subsets (const char *subset1
, const char *subset2
)
1045 int order1
= riscv_ext_order
[(*subset1
- 'a')];
1046 int order2
= riscv_ext_order
[(*subset2
- 'a')];
1048 /* Compare the standard extension first. */
1049 if (order1
> 0 && order2
> 0)
1050 return order1
- order2
;
1052 if (order1
== order2
&& order1
< 0)
1054 /* Compare the standard addition z extensions. */
1055 if (*subset1
== 'z')
1057 order1
= riscv_ext_order
[(*++subset1
- 'a')];
1058 order2
= riscv_ext_order
[(*++subset2
- 'a')];
1059 if (order1
!= order2
)
1060 return order1
- order2
;
1062 return strcasecmp (++subset1
, ++subset2
);
1065 return order2
- order1
;
1068 /* Find subset in the list. Return TRUE and set `current` to the subset
1069 if it is found. Otherwise, return FALSE and set `current` to the place
1070 where we should insert the subset. However, return FALSE with the NULL
1071 `current` means we should insert the subset at the head of subset list,
1075 riscv_lookup_subset (const riscv_subset_list_t
*subset_list
,
1077 riscv_subset_t
**current
)
1079 riscv_subset_t
*s
, *pre_s
= NULL
;
1081 for (s
= subset_list
->head
;
1083 pre_s
= s
, s
= s
->next
)
1085 int cmp
= riscv_compare_subsets (s
->name
, subset
);
1098 /* Add extension from ISA string to the last of the subset list. */
1101 riscv_add_subset (riscv_subset_list_t
*subset_list
,
1106 riscv_subset_t
*s
= xmalloc (sizeof *s
);
1108 if (subset_list
->head
== NULL
)
1109 subset_list
->head
= s
;
1111 s
->name
= xstrdup (subset
);
1112 s
->major_version
= major
;
1113 s
->minor_version
= minor
;
1116 if (subset_list
->tail
!= NULL
)
1117 subset_list
->tail
->next
= s
;
1118 subset_list
->tail
= s
;
1121 /* Add the implicit extension to the subset list. Search the
1122 list first, and then find the right place to add. */
1125 riscv_add_implicit_subset (riscv_subset_list_t
*subset_list
,
1130 riscv_subset_t
*current
, *new;
1132 if (riscv_lookup_subset (subset_list
, subset
, ¤t
))
1135 new = xmalloc (sizeof *new);
1136 new->name
= xstrdup (subset
);
1137 new->major_version
= major
;
1138 new->minor_version
= minor
;
1141 if (current
!= NULL
)
1143 new->next
= current
->next
;
1144 current
->next
= new;
1148 new->next
= subset_list
->head
;
1149 subset_list
->head
= new;
1153 /* These extensions are added to the subset list for special purposes,
1154 with the explicit versions or the RISCV_UNKNOWN_VERSION versions.
1155 Therefore, we won't output them to the output ISA string in the
1156 riscv_arch_str1, if the versions are unknown. */
1159 riscv_ext_dont_care_version (const char *subset
)
1161 if (strcmp (subset
, "g") == 0
1162 || strcmp (subset
, "zicsr") == 0
1163 || strcmp (subset
, "zifencei") == 0)
1168 /* We have to add all extensions from ISA string first, and then start to
1169 add their implicit extensions. The extensions from ISA string must be
1170 set in order, so we can add them to the last of the subset list
1171 directly, without searching.
1173 Find the default versions for the extension before adding them to
1174 the subset list, if their versions are RISCV_UNKNOWN_VERSION.
1175 Afterwards, report errors if we can not find their default versions. */
1178 riscv_parse_add_subset (riscv_parse_subset_t
*rps
,
1184 int major_version
= major
;
1185 int minor_version
= minor
;
1187 if ((major_version
== RISCV_UNKNOWN_VERSION
1188 || minor_version
== RISCV_UNKNOWN_VERSION
)
1189 && rps
->get_default_version
!= NULL
)
1190 rps
->get_default_version (subset
, &major_version
, &minor_version
);
1192 if (!riscv_ext_dont_care_version (subset
)
1193 && (major_version
== RISCV_UNKNOWN_VERSION
1194 || minor_version
== RISCV_UNKNOWN_VERSION
))
1196 /* We only add the implicit extension if it is supported in the
1201 if (subset
[0] == 'x')
1203 (_("x ISA extension `%s' must be set with the versions"),
1207 (_("cannot find default versions of the ISA extension `%s'"),
1213 riscv_add_subset (rps
->subset_list
, subset
,
1214 major_version
, minor_version
);
1216 riscv_add_implicit_subset (rps
->subset_list
, subset
,
1217 major_version
, minor_version
);
1220 /* Release subset list. */
1223 riscv_release_subset_list (riscv_subset_list_t
*subset_list
)
1225 while (subset_list
->head
!= NULL
)
1227 riscv_subset_t
*next
= subset_list
->head
->next
;
1228 free ((void *)subset_list
->head
->name
);
1229 free (subset_list
->head
);
1230 subset_list
->head
= next
;
1233 subset_list
->tail
= NULL
;
1236 /* Parsing extension version.
1239 Points to the end of version
1242 `rps`: Hooks and status for parsing extensions.
1243 `march`: Full ISA string.
1244 `p`: Curent parsing position.
1245 `major_version`: Parsed major version.
1246 `minor_version`: Parsed minor version.
1247 `std_ext_p`: True if parsing standard extension. */
1250 riscv_parsing_subset_version (riscv_parse_subset_t
*rps
,
1257 bool major_p
= true;
1271 /* Might be beginning of `p` extension. */
1274 *major_version
= version
;
1281 (_("-march=%s: expect number after `%dp'"),
1287 *major_version
= version
;
1291 else if (ISDIGIT (*p
))
1292 version
= (version
* 10) + (*p
- '0');
1298 *major_version
= version
;
1300 *minor_version
= version
;
1302 /* We can not find any version in string. */
1303 if (*major_version
== 0 && *minor_version
== 0)
1305 *major_version
= RISCV_UNKNOWN_VERSION
;
1306 *minor_version
= RISCV_UNKNOWN_VERSION
;
1312 /* Return string which contain all supported standard extensions in
1316 riscv_supported_std_ext (void)
1318 return "mafdqlcbjtpvn";
1321 /* Parsing function for standard extensions.
1324 Points to the end of extensions.
1327 `rps`: Hooks and status for parsing extensions.
1328 `march`: Full ISA string.
1329 `p`: Curent parsing position. */
1332 riscv_parse_std_ext (riscv_parse_subset_t
*rps
,
1336 const char *all_std_exts
= riscv_supported_std_ext ();
1337 const char *std_exts
= all_std_exts
;
1340 char subset
[2] = {0, 0};
1342 /* First letter must start with i, e or g. */
1346 p
= riscv_parsing_subset_version (rps
, march
, ++p
,
1348 &minor_version
, true);
1349 riscv_parse_add_subset (rps
, "i",
1351 minor_version
, false);
1355 p
= riscv_parsing_subset_version (rps
, march
, ++p
,
1357 &minor_version
, true);
1358 riscv_parse_add_subset (rps
, "e",
1360 minor_version
, false);
1361 /* i-ext must be enabled. */
1362 riscv_parse_add_subset (rps
, "i",
1363 RISCV_UNKNOWN_VERSION
,
1364 RISCV_UNKNOWN_VERSION
, false);
1366 if (*rps
->xlen
> 32)
1369 (_("-march=%s: rv%de is not a valid base ISA"),
1376 p
= riscv_parsing_subset_version (rps
, march
, ++p
,
1378 &minor_version
, true);
1379 /* i-ext must be enabled. */
1380 riscv_parse_add_subset (rps
, "i",
1381 RISCV_UNKNOWN_VERSION
,
1382 RISCV_UNKNOWN_VERSION
, false);
1383 /* g-ext is used to add the implicit extensions, but will
1384 not be output to the ISA string. */
1385 riscv_parse_add_subset (rps
, "g",
1387 minor_version
, false);
1388 for ( ; *std_exts
!= 'q'; std_exts
++)
1390 subset
[0] = *std_exts
;
1391 riscv_parse_add_subset (rps
, subset
,
1392 RISCV_UNKNOWN_VERSION
,
1393 RISCV_UNKNOWN_VERSION
, false);
1399 (_("-march=%s: first ISA extension must be `e', `i' or `g'"),
1404 while (p
!= NULL
&& *p
!= '\0')
1406 if (*p
== 'x' || *p
== 's' || *p
== 'h' || *p
== 'z')
1415 /* Checking canonical order. */
1417 while (*std_exts
&& std_ext
!= *std_exts
)
1420 if (std_ext
!= *std_exts
)
1422 if (strchr (all_std_exts
, std_ext
) == NULL
)
1424 (_("-march=%s: unknown standard ISA extension `%c'"),
1428 (_("-march=%s: standard ISA extension `%c' is not "
1429 "in canonical order"), march
, std_ext
);
1434 subset
[0] = std_ext
;
1435 p
= riscv_parsing_subset_version (rps
, march
, ++p
,
1437 &minor_version
, true);
1438 riscv_parse_add_subset (rps
, subset
,
1440 minor_version
, false);
1446 /* Classify ARCH into one of riscv_isa_ext_class_t. */
1448 riscv_isa_ext_class_t
1449 riscv_get_prefix_class (const char *arch
)
1453 case 's': return RV_ISA_CLASS_S
;
1454 case 'h': return RV_ISA_CLASS_H
;
1455 case 'x': return RV_ISA_CLASS_X
;
1456 case 'z': return RV_ISA_CLASS_Z
;
1457 default: return RV_ISA_CLASS_UNKNOWN
;
1461 /* Structure describing parameters to use when parsing a particular
1462 riscv_isa_ext_class_t. One of these should be provided for each
1463 possible class, except RV_ISA_CLASS_UNKNOWN. */
1464 typedef struct riscv_parse_config
1466 /* Class of the extension. */
1467 riscv_isa_ext_class_t
class;
1469 /* Prefix string for error printing and internal parser usage. */
1472 /* Predicate which is used for checking whether this is a "known"
1473 extension. For 'x', it always returns true since they are by
1474 definition non-standard and cannot be known. */
1475 bool (*ext_valid_p
) (const char *);
1476 } riscv_parse_config_t
;
1478 /* Parsing function for prefixed extensions.
1481 Points to the end of extension.
1484 `rps`: Hooks and status for parsing extensions.
1485 `march`: Full ISA string.
1486 `p`: Curent parsing position.
1487 `config`: What class and predicate function to use for the
1491 riscv_parse_prefixed_ext (riscv_parse_subset_t
*rps
,
1494 const riscv_parse_config_t
*config
)
1498 const char *last_name
;
1499 riscv_isa_ext_class_t
class;
1509 /* Assert that the current extension specifier matches our parsing
1511 class = riscv_get_prefix_class (p
);
1512 if (class != config
->class
1513 || class == RV_ISA_CLASS_UNKNOWN
)
1516 char *subset
= xstrdup (p
);
1518 const char *end_of_version
;
1520 while (*++q
!= '\0' && *q
!= '_' && !ISDIGIT (*q
))
1524 riscv_parsing_subset_version (rps
, march
, q
,
1526 &minor_version
, false);
1529 if (end_of_version
== NULL
)
1535 /* Check that the prefix extension is known.
1536 For 'x', anything goes but it cannot simply be 'x'.
1537 For 's', it must be known from a list and cannot simply be 's'.
1538 For 'h', it must be known from a list and cannot simply be 'h'.
1539 For 'z', it must be known from a list and cannot simply be 'z'. */
1541 /* Check that the extension name is well-formed. */
1542 if (!config
->ext_valid_p (subset
))
1545 (_("-march=%s: unknown %s ISA extension `%s'"),
1546 march
, config
->prefix
, subset
);
1551 /* Check that the extension isn't duplicate. */
1552 last_name
= rps
->subset_list
->tail
->name
;
1553 if (!strcasecmp (last_name
, subset
))
1556 (_("-march=%s: duplicate %s ISA extension `%s'"),
1557 march
, config
->prefix
, subset
);
1562 /* Check that the extension is in alphabetical order. */
1563 if (riscv_compare_subsets (last_name
, subset
) > 0)
1566 (_("-march=%s: %s ISA extension `%s' is not in alphabetical "
1567 "order. It must come before `%s'"),
1568 march
, config
->prefix
, subset
, last_name
);
1573 riscv_parse_add_subset (rps
, subset
,
1575 minor_version
, false);
1576 p
+= end_of_version
- subset
;
1579 if (*p
!= '\0' && *p
!= '_')
1582 (_("-march=%s: %s ISA extension must separate with _"),
1583 march
, config
->prefix
);
1591 /* Lists of prefixed class extensions that binutils should know about.
1592 Whether or not a particular entry is in these lists will dictate if
1593 gas/ld will accept its presence in the architecture string.
1595 Please add the extensions to the lists in lower case. However, keep
1596 these subsets in alphabetical order in these tables is recommended,
1597 although there is no impact on the current implementation. */
1599 static const char * const riscv_std_z_ext_strtab
[] =
1601 "zba", "zbb", "zbc", "zicsr", "zifencei", "zihintpause", NULL
1604 static const char * const riscv_std_s_ext_strtab
[] =
1609 static const char * const riscv_std_h_ext_strtab
[] =
1614 /* For the extension `ext`, search through the list of known extensions
1615 `known_exts` for a match, and return TRUE if found. */
1618 riscv_multi_letter_ext_valid_p (const char *ext
,
1619 const char *const *known_exts
)
1623 for (i
= 0; known_exts
[i
]; ++i
)
1624 if (!strcmp (ext
, known_exts
[i
]))
1630 /* Predicator function for x-prefixed extensions.
1631 Anything goes, except the literal 'x'. */
1634 riscv_ext_x_valid_p (const char *arg
)
1636 if (!strcasecmp (arg
, "x"))
1642 /* Predicator functions for z-prefixed extensions.
1643 Only known z-extensions are permitted. */
1646 riscv_ext_z_valid_p (const char *arg
)
1648 return riscv_multi_letter_ext_valid_p (arg
, riscv_std_z_ext_strtab
);
1651 /* Predicator function for 's' prefixed extensions.
1652 Only known s-extensions are permitted. */
1655 riscv_ext_s_valid_p (const char *arg
)
1657 return riscv_multi_letter_ext_valid_p (arg
, riscv_std_s_ext_strtab
);
1660 /* Predicator function for 'h' prefixed extensions.
1661 Only known h-extensions are permitted. */
1664 riscv_ext_h_valid_p (const char *arg
)
1666 return riscv_multi_letter_ext_valid_p (arg
, riscv_std_h_ext_strtab
);
1669 /* Parsing order of the prefixed extensions that is specified by
1671 static const riscv_parse_config_t parse_config
[] =
1673 {RV_ISA_CLASS_S
, "s", riscv_ext_s_valid_p
},
1674 {RV_ISA_CLASS_H
, "h", riscv_ext_h_valid_p
},
1675 {RV_ISA_CLASS_Z
, "z", riscv_ext_z_valid_p
},
1676 {RV_ISA_CLASS_X
, "x", riscv_ext_x_valid_p
},
1677 {RV_ISA_CLASS_UNKNOWN
, NULL
, NULL
}
1680 /* Init the riscv_ext_order array. */
1683 riscv_init_ext_order (void)
1685 static bool inited
= false;
1686 const char *std_base_exts
= "eig";
1687 const char *std_remain_exts
= riscv_supported_std_ext ();
1695 /* The orders of all standard extensions are positive. */
1698 /* Init the standard base extensions first. */
1699 for (ext
= std_base_exts
; *ext
; ext
++)
1700 riscv_ext_order
[(*ext
- 'a')] = order
++;
1702 /* Init the standard remaining extensions. */
1703 for (ext
= std_remain_exts
; *ext
; ext
++)
1704 riscv_ext_order
[(*ext
- 'a')] = order
++;
1706 /* Init the order for prefixed keywords. The orders are negative. */
1708 for (i
= 0; parse_config
[i
].class != RV_ISA_CLASS_UNKNOWN
; i
++)
1710 ext
= parse_config
[i
].prefix
;
1711 riscv_ext_order
[(*ext
- 'a')] = order
--;
1717 /* Add the implicit extensions. */
1720 riscv_parse_add_implicit_subsets (riscv_parse_subset_t
*rps
)
1722 riscv_subset_t
*subset
= NULL
;
1724 /* Add the zicsr and zifencei only when the i's version less than 2.1. */
1725 if ((riscv_lookup_subset (rps
->subset_list
, "i", &subset
))
1726 && (subset
->major_version
< 2
1727 || (subset
->major_version
== 2
1728 && subset
->minor_version
< 1)))
1730 riscv_parse_add_subset (rps
, "zicsr",
1731 RISCV_UNKNOWN_VERSION
,
1732 RISCV_UNKNOWN_VERSION
, true);
1733 riscv_parse_add_subset (rps
, "zifencei",
1734 RISCV_UNKNOWN_VERSION
,
1735 RISCV_UNKNOWN_VERSION
, true);
1738 if ((riscv_lookup_subset (rps
->subset_list
, "q", &subset
)))
1740 riscv_parse_add_subset (rps
, "d",
1741 RISCV_UNKNOWN_VERSION
,
1742 RISCV_UNKNOWN_VERSION
, true);
1743 riscv_parse_add_subset (rps
, "f",
1744 RISCV_UNKNOWN_VERSION
,
1745 RISCV_UNKNOWN_VERSION
, true);
1746 riscv_parse_add_subset (rps
, "zicsr",
1747 RISCV_UNKNOWN_VERSION
,
1748 RISCV_UNKNOWN_VERSION
, true);
1750 else if ((riscv_lookup_subset (rps
->subset_list
, "d", &subset
)))
1752 riscv_parse_add_subset (rps
, "f",
1753 RISCV_UNKNOWN_VERSION
,
1754 RISCV_UNKNOWN_VERSION
, true);
1755 riscv_parse_add_subset (rps
, "zicsr",
1756 RISCV_UNKNOWN_VERSION
,
1757 RISCV_UNKNOWN_VERSION
, true);
1759 else if ((riscv_lookup_subset (rps
->subset_list
, "f", &subset
)))
1760 riscv_parse_add_subset (rps
, "zicsr",
1761 RISCV_UNKNOWN_VERSION
,
1762 RISCV_UNKNOWN_VERSION
, true);
1764 if ((riscv_lookup_subset (rps
->subset_list
, "g", &subset
)))
1766 riscv_parse_add_subset (rps
, "zicsr",
1767 RISCV_UNKNOWN_VERSION
,
1768 RISCV_UNKNOWN_VERSION
, true);
1769 riscv_parse_add_subset (rps
, "zifencei",
1770 RISCV_UNKNOWN_VERSION
,
1771 RISCV_UNKNOWN_VERSION
, true);
1775 /* Function for parsing ISA string.
1778 Return TRUE on success.
1781 `rps`: Hooks and status for parsing extensions.
1782 `arch`: Full ISA string. */
1785 riscv_parse_subset (riscv_parse_subset_t
*rps
,
1788 riscv_subset_t
*subset
= NULL
;
1791 bool no_conflict
= true;
1793 for (p
= arch
; *p
!= '\0'; p
++)
1798 (_("-march=%s: ISA string cannot contain uppercase letters"),
1805 if (startswith (p
, "rv32"))
1810 else if (startswith (p
, "rv64"))
1817 /* ISA string shouldn't be NULL or empty here. However,
1818 it might be empty only when we failed to merge the ISA
1819 string in the riscv_merge_attributes. We have already
1820 issued the correct error message in another side, so do
1821 not issue this error when the ISA string is empty. */
1823 rps
->error_handler (
1824 _("-march=%s: ISA string must begin with rv32 or rv64"),
1829 /* Init the riscv_ext_order array to compare the order of extensions
1831 riscv_init_ext_order ();
1833 /* Parsing standard extension. */
1834 p
= riscv_parse_std_ext (rps
, arch
, p
);
1839 /* Parse the different classes of extensions in the specified order. */
1840 for (i
= 0; i
< ARRAY_SIZE (parse_config
); ++i
)
1842 p
= riscv_parse_prefixed_ext (rps
, arch
, p
, &parse_config
[i
]);
1850 rps
->error_handler (_("-march=%s: unexpected ISA string at end: %s"),
1855 /* Finally add implicit extensions according to the current
1857 riscv_parse_add_implicit_subsets (rps
);
1859 /* Check the conflicts. */
1860 if (riscv_lookup_subset (rps
->subset_list
, "e", &subset
)
1861 && riscv_lookup_subset (rps
->subset_list
, "f", &subset
))
1864 (_("-march=%s: rv32e does not support the `f' extension"),
1866 no_conflict
= false;
1868 if (riscv_lookup_subset (rps
->subset_list
, "q", &subset
)
1872 (_("-march=%s: rv32 does not support the `q' extension"),
1874 no_conflict
= false;
1879 /* Return the number of digits for the input. */
1882 riscv_estimate_digit (unsigned num
)
1888 for (digit
= 0; num
; num
/= 10)
1894 /* Auxiliary function to estimate string length of subset list. */
1897 riscv_estimate_arch_strlen1 (const riscv_subset_t
*subset
)
1900 return 6; /* For rv32/rv64/rv128 and string terminator. */
1902 return riscv_estimate_arch_strlen1 (subset
->next
)
1903 + strlen (subset
->name
)
1904 + riscv_estimate_digit (subset
->major_version
)
1905 + 1 /* For version seperator 'p'. */
1906 + riscv_estimate_digit (subset
->minor_version
)
1907 + 1 /* For underscore. */;
1910 /* Estimate the string length of this subset list. */
1913 riscv_estimate_arch_strlen (const riscv_subset_list_t
*subset_list
)
1915 return riscv_estimate_arch_strlen1 (subset_list
->head
);
1918 /* Auxiliary function to convert subset info to string. */
1921 riscv_arch_str1 (riscv_subset_t
*subset
,
1922 char *attr_str
, char *buf
, size_t bufsz
)
1924 const char *underline
= "_";
1925 riscv_subset_t
*subset_t
= subset
;
1927 if (subset_t
== NULL
)
1930 /* No underline between rvXX and i/e. */
1931 if ((strcasecmp (subset_t
->name
, "i") == 0)
1932 || (strcasecmp (subset_t
->name
, "e") == 0))
1935 snprintf (buf
, bufsz
, "%s%s%dp%d",
1938 subset_t
->major_version
,
1939 subset_t
->minor_version
);
1941 strncat (attr_str
, buf
, bufsz
);
1943 /* Skip 'i' extension after 'e', or skip extensions which
1944 versions are unknown. */
1945 while (subset_t
->next
1946 && ((strcmp (subset_t
->name
, "e") == 0
1947 && strcmp (subset_t
->next
->name
, "i") == 0)
1948 || subset_t
->next
->major_version
== RISCV_UNKNOWN_VERSION
1949 || subset_t
->next
->minor_version
== RISCV_UNKNOWN_VERSION
))
1950 subset_t
= subset_t
->next
;
1952 riscv_arch_str1 (subset_t
->next
, attr_str
, buf
, bufsz
);
1955 /* Convert subset information into string with explicit versions. */
1958 riscv_arch_str (unsigned xlen
, const riscv_subset_list_t
*subset
)
1960 size_t arch_str_len
= riscv_estimate_arch_strlen (subset
);
1961 char *attr_str
= xmalloc (arch_str_len
);
1962 char *buf
= xmalloc (arch_str_len
);
1964 snprintf (attr_str
, arch_str_len
, "rv%u", xlen
);
1966 riscv_arch_str1 (subset
->head
, attr_str
, buf
, arch_str_len
);