1 /* RISC-V-specific support for ELF.
2 Copyright (C) 2011-2024 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"
33 #define MINUS_ONE ((bfd_vma)0 - 1)
35 /* Special handler for ADD/SUB relocations that allows them to be filled out
36 both in the pre-linked and post-linked file. This is necessary to make
37 pre-linked debug info work, as due to linker relaxations we need to emit
38 relocations for the debug info. */
39 static bfd_reloc_status_type riscv_elf_add_sub_reloc
40 (bfd
*, arelent
*, asymbol
*, void *, asection
*, bfd
*, char **);
41 static bfd_reloc_status_type riscv_elf_ignore_reloc
42 (bfd
*, arelent
*, asymbol
*, void *, asection
*, bfd
*, char **);
44 /* The relocation table used for SHT_RELA sections. */
46 static reloc_howto_type howto_table
[] =
49 HOWTO (R_RISCV_NONE
, /* type */
53 false, /* pc_relative */
55 complain_overflow_dont
, /* complain_on_overflow */
56 bfd_elf_generic_reloc
, /* special_function */
57 "R_RISCV_NONE", /* name */
58 false, /* partial_inplace */
61 false), /* pcrel_offset */
63 /* 32 bit relocation. */
64 HOWTO (R_RISCV_32
, /* type */
68 false, /* pc_relative */
70 complain_overflow_dont
, /* complain_on_overflow */
71 bfd_elf_generic_reloc
, /* special_function */
72 "R_RISCV_32", /* name */
73 false, /* partial_inplace */
75 0xffffffff, /* dst_mask */
76 false), /* pcrel_offset */
78 /* 64 bit relocation. */
79 HOWTO (R_RISCV_64
, /* type */
83 false, /* pc_relative */
85 complain_overflow_dont
, /* complain_on_overflow */
86 bfd_elf_generic_reloc
, /* special_function */
87 "R_RISCV_64", /* name */
88 false, /* partial_inplace */
90 MINUS_ONE
, /* dst_mask */
91 false), /* pcrel_offset */
93 /* Relocation against a local symbol in a shared object. */
94 HOWTO (R_RISCV_RELATIVE
, /* type */
98 false, /* pc_relative */
100 complain_overflow_dont
, /* complain_on_overflow */
101 bfd_elf_generic_reloc
, /* special_function */
102 "R_RISCV_RELATIVE", /* name */
103 false, /* partial_inplace */
105 0xffffffff, /* dst_mask */
106 false), /* pcrel_offset */
108 HOWTO (R_RISCV_COPY
, /* type */
110 0, /* this one is variable size */
112 false, /* pc_relative */
114 complain_overflow_bitfield
, /* complain_on_overflow */
115 bfd_elf_generic_reloc
, /* special_function */
116 "R_RISCV_COPY", /* name */
117 false, /* partial_inplace */
120 false), /* pcrel_offset */
122 HOWTO (R_RISCV_JUMP_SLOT
, /* type */
126 false, /* pc_relative */
128 complain_overflow_bitfield
, /* complain_on_overflow */
129 bfd_elf_generic_reloc
, /* special_function */
130 "R_RISCV_JUMP_SLOT", /* name */
131 false, /* partial_inplace */
134 false), /* pcrel_offset */
136 /* Dynamic TLS relocations. */
137 HOWTO (R_RISCV_TLS_DTPMOD32
, /* type */
141 false, /* pc_relative */
143 complain_overflow_dont
, /* complain_on_overflow */
144 bfd_elf_generic_reloc
, /* special_function */
145 "R_RISCV_TLS_DTPMOD32", /* name */
146 false, /* partial_inplace */
148 0xffffffff, /* dst_mask */
149 false), /* pcrel_offset */
151 HOWTO (R_RISCV_TLS_DTPMOD64
, /* type */
155 false, /* pc_relative */
157 complain_overflow_dont
, /* complain_on_overflow */
158 bfd_elf_generic_reloc
, /* special_function */
159 "R_RISCV_TLS_DTPMOD64", /* name */
160 false, /* partial_inplace */
162 MINUS_ONE
, /* dst_mask */
163 false), /* pcrel_offset */
165 HOWTO (R_RISCV_TLS_DTPREL32
, /* type */
169 false, /* pc_relative */
171 complain_overflow_dont
, /* complain_on_overflow */
172 bfd_elf_generic_reloc
, /* special_function */
173 "R_RISCV_TLS_DTPREL32", /* name */
174 true, /* partial_inplace */
176 0xffffffff, /* dst_mask */
177 false), /* pcrel_offset */
179 HOWTO (R_RISCV_TLS_DTPREL64
, /* type */
183 false, /* pc_relative */
185 complain_overflow_dont
, /* complain_on_overflow */
186 bfd_elf_generic_reloc
, /* special_function */
187 "R_RISCV_TLS_DTPREL64", /* name */
188 true, /* partial_inplace */
190 MINUS_ONE
, /* dst_mask */
191 false), /* pcrel_offset */
193 HOWTO (R_RISCV_TLS_TPREL32
, /* type */
197 false, /* pc_relative */
199 complain_overflow_dont
, /* complain_on_overflow */
200 bfd_elf_generic_reloc
, /* special_function */
201 "R_RISCV_TLS_TPREL32", /* name */
202 false, /* partial_inplace */
204 0xffffffff, /* dst_mask */
205 false), /* pcrel_offset */
207 HOWTO (R_RISCV_TLS_TPREL64
, /* type */
211 false, /* pc_relative */
213 complain_overflow_dont
, /* complain_on_overflow */
214 bfd_elf_generic_reloc
, /* special_function */
215 "R_RISCV_TLS_TPREL64", /* name */
216 false, /* partial_inplace */
218 MINUS_ONE
, /* dst_mask */
219 false), /* pcrel_offset */
221 HOWTO (R_RISCV_TLSDESC
, /* type */
223 0, /* size is handled by dynamic linker */
225 false, /* pc_relative */
227 complain_overflow_dont
, /* complain_on_overflow */
228 bfd_elf_generic_reloc
, /* special_function */
229 "R_RISCV_TLSDESC", /* name */
230 false, /* partial_inplace */
232 MINUS_ONE
, /* dst_mask */
233 false), /* pcrel_offset */
239 /* 12-bit PC-relative branch offset. */
240 HOWTO (R_RISCV_BRANCH
, /* type */
244 true, /* pc_relative */
246 complain_overflow_signed
, /* complain_on_overflow */
247 bfd_elf_generic_reloc
, /* special_function */
248 "R_RISCV_BRANCH", /* name */
249 false, /* partial_inplace */
251 ENCODE_BTYPE_IMM (-1U), /* dst_mask */
252 true), /* pcrel_offset */
254 /* 20-bit PC-relative jump offset. */
255 HOWTO (R_RISCV_JAL
, /* type */
259 true, /* pc_relative */
261 complain_overflow_dont
, /* complain_on_overflow */
262 bfd_elf_generic_reloc
, /* special_function */
263 "R_RISCV_JAL", /* name */
264 false, /* partial_inplace */
266 ENCODE_JTYPE_IMM (-1U), /* dst_mask */
267 true), /* pcrel_offset */
269 /* 32-bit PC-relative function call (AUIPC/JALR). */
270 HOWTO (R_RISCV_CALL
, /* type */
274 true, /* pc_relative */
276 complain_overflow_dont
, /* complain_on_overflow */
277 bfd_elf_generic_reloc
, /* special_function */
278 "R_RISCV_CALL", /* name */
279 false, /* partial_inplace */
281 ENCODE_UTYPE_IMM (-1U) | ((bfd_vma
) ENCODE_ITYPE_IMM (-1U) << 32),
283 true), /* pcrel_offset */
285 /* Like R_RISCV_CALL, but not locally binding. */
286 HOWTO (R_RISCV_CALL_PLT
, /* type */
290 true, /* pc_relative */
292 complain_overflow_dont
, /* complain_on_overflow */
293 bfd_elf_generic_reloc
, /* special_function */
294 "R_RISCV_CALL_PLT", /* name */
295 false, /* partial_inplace */
297 ENCODE_UTYPE_IMM (-1U) | ((bfd_vma
) ENCODE_ITYPE_IMM (-1U) << 32),
299 true), /* pcrel_offset */
301 /* High 20 bits of 32-bit PC-relative GOT access. */
302 HOWTO (R_RISCV_GOT_HI20
, /* type */
306 true, /* pc_relative */
308 complain_overflow_dont
, /* complain_on_overflow */
309 bfd_elf_generic_reloc
, /* special_function */
310 "R_RISCV_GOT_HI20", /* name */
311 false, /* partial_inplace */
313 ENCODE_UTYPE_IMM (-1U), /* dst_mask */
314 false), /* pcrel_offset */
316 /* High 20 bits of 32-bit PC-relative TLS IE GOT access. */
317 HOWTO (R_RISCV_TLS_GOT_HI20
, /* type */
321 true, /* pc_relative */
323 complain_overflow_dont
, /* complain_on_overflow */
324 bfd_elf_generic_reloc
, /* special_function */
325 "R_RISCV_TLS_GOT_HI20", /* name */
326 false, /* partial_inplace */
328 ENCODE_UTYPE_IMM (-1U), /* dst_mask */
329 false), /* pcrel_offset */
331 /* High 20 bits of 32-bit PC-relative TLS GD GOT reference. */
332 HOWTO (R_RISCV_TLS_GD_HI20
, /* type */
336 true, /* pc_relative */
338 complain_overflow_dont
, /* complain_on_overflow */
339 bfd_elf_generic_reloc
, /* special_function */
340 "R_RISCV_TLS_GD_HI20", /* name */
341 false, /* partial_inplace */
343 ENCODE_UTYPE_IMM (-1U), /* dst_mask */
344 false), /* pcrel_offset */
346 /* High 20 bits of 32-bit PC-relative reference. */
347 HOWTO (R_RISCV_PCREL_HI20
, /* type */
351 true, /* pc_relative */
353 complain_overflow_dont
, /* complain_on_overflow */
354 bfd_elf_generic_reloc
, /* special_function */
355 "R_RISCV_PCREL_HI20", /* name */
356 false, /* partial_inplace */
358 ENCODE_UTYPE_IMM (-1U), /* dst_mask */
359 true), /* pcrel_offset */
361 /* Low 12 bits of a 32-bit PC-relative load or add. */
362 HOWTO (R_RISCV_PCREL_LO12_I
, /* type */
366 false, /* pc_relative */
368 complain_overflow_dont
, /* complain_on_overflow */
369 bfd_elf_generic_reloc
, /* special_function */
370 "R_RISCV_PCREL_LO12_I", /* name */
371 false, /* partial_inplace */
373 ENCODE_ITYPE_IMM (-1U), /* dst_mask */
374 false), /* pcrel_offset */
376 /* Low 12 bits of a 32-bit PC-relative store. */
377 HOWTO (R_RISCV_PCREL_LO12_S
, /* type */
381 false, /* pc_relative */
383 complain_overflow_dont
, /* complain_on_overflow */
384 bfd_elf_generic_reloc
, /* special_function */
385 "R_RISCV_PCREL_LO12_S", /* name */
386 false, /* partial_inplace */
388 ENCODE_STYPE_IMM (-1U), /* dst_mask */
389 false), /* pcrel_offset */
391 /* High 20 bits of 32-bit absolute address. */
392 HOWTO (R_RISCV_HI20
, /* type */
396 false, /* pc_relative */
398 complain_overflow_dont
, /* complain_on_overflow */
399 bfd_elf_generic_reloc
, /* special_function */
400 "R_RISCV_HI20", /* name */
401 false, /* partial_inplace */
403 ENCODE_UTYPE_IMM (-1U), /* dst_mask */
404 false), /* pcrel_offset */
406 /* High 12 bits of 32-bit load or add. */
407 HOWTO (R_RISCV_LO12_I
, /* type */
411 false, /* pc_relative */
413 complain_overflow_dont
, /* complain_on_overflow */
414 bfd_elf_generic_reloc
, /* special_function */
415 "R_RISCV_LO12_I", /* name */
416 false, /* partial_inplace */
418 ENCODE_ITYPE_IMM (-1U), /* dst_mask */
419 false), /* pcrel_offset */
421 /* High 12 bits of 32-bit store. */
422 HOWTO (R_RISCV_LO12_S
, /* type */
426 false, /* pc_relative */
428 complain_overflow_dont
, /* complain_on_overflow */
429 bfd_elf_generic_reloc
, /* special_function */
430 "R_RISCV_LO12_S", /* name */
431 false, /* partial_inplace */
433 ENCODE_STYPE_IMM (-1U), /* dst_mask */
434 false), /* pcrel_offset */
436 /* High 20 bits of TLS LE thread pointer offset. */
437 HOWTO (R_RISCV_TPREL_HI20
, /* type */
441 false, /* pc_relative */
443 complain_overflow_signed
, /* complain_on_overflow */
444 bfd_elf_generic_reloc
, /* special_function */
445 "R_RISCV_TPREL_HI20", /* name */
446 true, /* partial_inplace */
448 ENCODE_UTYPE_IMM (-1U), /* dst_mask */
449 false), /* pcrel_offset */
451 /* Low 12 bits of TLS LE thread pointer offset for loads and adds. */
452 HOWTO (R_RISCV_TPREL_LO12_I
, /* type */
456 false, /* pc_relative */
458 complain_overflow_signed
, /* complain_on_overflow */
459 bfd_elf_generic_reloc
, /* special_function */
460 "R_RISCV_TPREL_LO12_I", /* name */
461 false, /* partial_inplace */
463 ENCODE_ITYPE_IMM (-1U), /* dst_mask */
464 false), /* pcrel_offset */
466 /* Low 12 bits of TLS LE thread pointer offset for stores. */
467 HOWTO (R_RISCV_TPREL_LO12_S
, /* type */
471 false, /* pc_relative */
473 complain_overflow_signed
, /* complain_on_overflow */
474 bfd_elf_generic_reloc
, /* special_function */
475 "R_RISCV_TPREL_LO12_S", /* name */
476 false, /* partial_inplace */
478 ENCODE_STYPE_IMM (-1U), /* dst_mask */
479 false), /* pcrel_offset */
481 /* TLS LE thread pointer usage. May be relaxed. */
482 HOWTO (R_RISCV_TPREL_ADD
, /* type */
486 false, /* pc_relative */
488 complain_overflow_dont
, /* complain_on_overflow */
489 bfd_elf_generic_reloc
, /* special_function */
490 "R_RISCV_TPREL_ADD", /* name */
491 false, /* partial_inplace */
494 false), /* pcrel_offset */
496 /* 8-bit in-place addition, for local label subtraction. */
497 HOWTO (R_RISCV_ADD8
, /* type */
501 false, /* pc_relative */
503 complain_overflow_dont
, /* complain_on_overflow */
504 riscv_elf_add_sub_reloc
, /* special_function */
505 "R_RISCV_ADD8", /* name */
506 false, /* partial_inplace */
509 false), /* pcrel_offset */
511 /* 16-bit in-place addition, for local label subtraction. */
512 HOWTO (R_RISCV_ADD16
, /* type */
516 false, /* pc_relative */
518 complain_overflow_dont
, /* complain_on_overflow */
519 riscv_elf_add_sub_reloc
, /* special_function */
520 "R_RISCV_ADD16", /* name */
521 false, /* partial_inplace */
523 0xffff, /* dst_mask */
524 false), /* pcrel_offset */
526 /* 32-bit in-place addition, for local label subtraction. */
527 HOWTO (R_RISCV_ADD32
, /* type */
531 false, /* pc_relative */
533 complain_overflow_dont
, /* complain_on_overflow */
534 riscv_elf_add_sub_reloc
, /* special_function */
535 "R_RISCV_ADD32", /* name */
536 false, /* partial_inplace */
538 0xffffffff, /* dst_mask */
539 false), /* pcrel_offset */
541 /* 64-bit in-place addition, for local label subtraction. */
542 HOWTO (R_RISCV_ADD64
, /* type */
546 false, /* pc_relative */
548 complain_overflow_dont
, /* complain_on_overflow */
549 riscv_elf_add_sub_reloc
, /* special_function */
550 "R_RISCV_ADD64", /* name */
551 false, /* partial_inplace */
553 MINUS_ONE
, /* dst_mask */
554 false), /* pcrel_offset */
556 /* 8-bit in-place addition, for local label subtraction. */
557 HOWTO (R_RISCV_SUB8
, /* type */
561 false, /* pc_relative */
563 complain_overflow_dont
, /* complain_on_overflow */
564 riscv_elf_add_sub_reloc
, /* special_function */
565 "R_RISCV_SUB8", /* name */
566 false, /* partial_inplace */
569 false), /* pcrel_offset */
571 /* 16-bit in-place addition, for local label subtraction. */
572 HOWTO (R_RISCV_SUB16
, /* type */
576 false, /* pc_relative */
578 complain_overflow_dont
, /* complain_on_overflow */
579 riscv_elf_add_sub_reloc
, /* special_function */
580 "R_RISCV_SUB16", /* name */
581 false, /* partial_inplace */
583 0xffff, /* dst_mask */
584 false), /* pcrel_offset */
586 /* 32-bit in-place addition, for local label subtraction. */
587 HOWTO (R_RISCV_SUB32
, /* type */
591 false, /* pc_relative */
593 complain_overflow_dont
, /* complain_on_overflow */
594 riscv_elf_add_sub_reloc
, /* special_function */
595 "R_RISCV_SUB32", /* name */
596 false, /* partial_inplace */
598 0xffffffff, /* dst_mask */
599 false), /* pcrel_offset */
601 /* 64-bit in-place addition, for local label subtraction. */
602 HOWTO (R_RISCV_SUB64
, /* type */
606 false, /* pc_relative */
608 complain_overflow_dont
, /* complain_on_overflow */
609 riscv_elf_add_sub_reloc
, /* special_function */
610 "R_RISCV_SUB64", /* name */
611 false, /* partial_inplace */
613 MINUS_ONE
, /* dst_mask */
614 false), /* pcrel_offset */
619 /* Indicates an alignment statement. The addend field encodes how many
620 bytes of NOPs follow the statement. The desired alignment is the
621 addend rounded up to the next power of two. */
622 HOWTO (R_RISCV_ALIGN
, /* type */
626 false, /* pc_relative */
628 complain_overflow_dont
, /* complain_on_overflow */
629 bfd_elf_generic_reloc
, /* special_function */
630 "R_RISCV_ALIGN", /* name */
631 false, /* partial_inplace */
634 false), /* pcrel_offset */
636 /* 8-bit PC-relative branch offset. */
637 HOWTO (R_RISCV_RVC_BRANCH
, /* type */
641 true, /* pc_relative */
643 complain_overflow_signed
, /* complain_on_overflow */
644 bfd_elf_generic_reloc
, /* special_function */
645 "R_RISCV_RVC_BRANCH", /* name */
646 false, /* partial_inplace */
648 ENCODE_CBTYPE_IMM (-1U), /* dst_mask */
649 true), /* pcrel_offset */
651 /* 11-bit PC-relative jump offset. */
652 HOWTO (R_RISCV_RVC_JUMP
, /* type */
656 true, /* pc_relative */
658 complain_overflow_dont
, /* complain_on_overflow */
659 bfd_elf_generic_reloc
, /* special_function */
660 "R_RISCV_RVC_JUMP", /* name */
661 false, /* partial_inplace */
663 ENCODE_CJTYPE_IMM (-1U), /* dst_mask */
664 true), /* pcrel_offset */
672 /* The paired relocation may be relaxed. */
673 HOWTO (R_RISCV_RELAX
, /* type */
677 false, /* pc_relative */
679 complain_overflow_dont
, /* complain_on_overflow */
680 bfd_elf_generic_reloc
, /* special_function */
681 "R_RISCV_RELAX", /* name */
682 false, /* partial_inplace */
685 false), /* pcrel_offset */
687 /* 6-bit in-place addition, for local label subtraction. */
688 HOWTO (R_RISCV_SUB6
, /* type */
692 false, /* pc_relative */
694 complain_overflow_dont
, /* complain_on_overflow */
695 riscv_elf_add_sub_reloc
, /* special_function */
696 "R_RISCV_SUB6", /* name */
697 false, /* partial_inplace */
700 false), /* pcrel_offset */
702 /* 6-bit in-place setting, for local label subtraction. */
703 HOWTO (R_RISCV_SET6
, /* type */
707 false, /* pc_relative */
709 complain_overflow_dont
, /* complain_on_overflow */
710 bfd_elf_generic_reloc
, /* special_function */
711 "R_RISCV_SET6", /* name */
712 false, /* partial_inplace */
715 false), /* pcrel_offset */
717 /* 8-bit in-place setting, for local label subtraction. */
718 HOWTO (R_RISCV_SET8
, /* type */
722 false, /* pc_relative */
724 complain_overflow_dont
, /* complain_on_overflow */
725 bfd_elf_generic_reloc
, /* special_function */
726 "R_RISCV_SET8", /* name */
727 false, /* partial_inplace */
730 false), /* pcrel_offset */
732 /* 16-bit in-place setting, for local label subtraction. */
733 HOWTO (R_RISCV_SET16
, /* type */
737 false, /* pc_relative */
739 complain_overflow_dont
, /* complain_on_overflow */
740 bfd_elf_generic_reloc
, /* special_function */
741 "R_RISCV_SET16", /* name */
742 false, /* partial_inplace */
744 0xffff, /* dst_mask */
745 false), /* pcrel_offset */
747 /* 32-bit in-place setting, for local label subtraction. */
748 HOWTO (R_RISCV_SET32
, /* type */
752 false, /* pc_relative */
754 complain_overflow_dont
, /* complain_on_overflow */
755 bfd_elf_generic_reloc
, /* special_function */
756 "R_RISCV_SET32", /* name */
757 false, /* partial_inplace */
759 0xffffffff, /* dst_mask */
760 false), /* pcrel_offset */
762 /* 32-bit PC relative. */
763 HOWTO (R_RISCV_32_PCREL
, /* type */
767 true, /* pc_relative */
769 complain_overflow_dont
, /* complain_on_overflow */
770 bfd_elf_generic_reloc
, /* special_function */
771 "R_RISCV_32_PCREL", /* name */
772 false, /* partial_inplace */
774 0xffffffff, /* dst_mask */
775 false), /* pcrel_offset */
777 /* Relocation against a local ifunc symbol in a shared object. */
778 HOWTO (R_RISCV_IRELATIVE
, /* type */
782 false, /* pc_relative */
784 complain_overflow_dont
, /* complain_on_overflow */
785 bfd_elf_generic_reloc
, /* special_function */
786 "R_RISCV_IRELATIVE", /* name */
787 false, /* partial_inplace */
789 0xffffffff, /* dst_mask */
790 false), /* pcrel_offset */
792 /* Reserved for R_RISCV_PLT32. */
795 /* N-bit in-place setting, for unsigned-leb128 local label subtraction. */
796 HOWTO (R_RISCV_SET_ULEB128
, /* type */
800 false, /* pc_relative */
802 complain_overflow_dont
, /* complain_on_overflow */
803 riscv_elf_ignore_reloc
, /* special_function */
804 "R_RISCV_SET_ULEB128", /* name */
805 false, /* partial_inplace */
808 false), /* pcrel_offset */
810 /* N-bit in-place addition, for unsigned-leb128 local label subtraction. */
811 HOWTO (R_RISCV_SUB_ULEB128
, /* type */
815 false, /* pc_relative */
817 complain_overflow_dont
, /* complain_on_overflow */
818 riscv_elf_ignore_reloc
, /* special_function */
819 "R_RISCV_SUB_ULEB128", /* name */
820 false, /* partial_inplace */
823 false), /* pcrel_offset */
825 HOWTO (R_RISCV_TLSDESC_HI20
, /* type */
829 true, /* pc_relative */
831 complain_overflow_dont
, /* complain_on_overflow */
832 bfd_elf_generic_reloc
, /* special_function */
833 "R_RISCV_TLSDESC_HI20", /* name */
834 true, /* partial_inplace */
836 ENCODE_UTYPE_IMM (-1U), /* dst_mask */
837 false), /* pcrel_offset */
839 HOWTO (R_RISCV_TLSDESC_LOAD_LO12
, /* type */
843 false, /* pc_relative */
845 complain_overflow_dont
, /* complain_on_overflow */
846 bfd_elf_generic_reloc
, /* special_function */
847 "R_RISCV_TLSDESC_LOAD_LO12", /* name */
848 false, /* partial_inplace */
850 ENCODE_ITYPE_IMM (-1U), /* dst_mask */
851 false), /* pcrel_offset */
853 HOWTO (R_RISCV_TLSDESC_ADD_LO12
, /* type */
857 false, /* pc_relative */
859 complain_overflow_dont
, /* complain_on_overflow */
860 bfd_elf_generic_reloc
, /* special_function */
861 "R_RISCV_TLSDESC_ADD_LO12", /* name */
862 false, /* partial_inplace */
864 ENCODE_ITYPE_IMM (-1U), /* dst_mask */
865 false), /* pcrel_offset */
867 HOWTO (R_RISCV_TLSDESC_CALL
, /* type */
871 false, /* pc_relative */
873 complain_overflow_dont
, /* complain_on_overflow */
874 bfd_elf_generic_reloc
, /* special_function */
875 "R_RISCV_TLSDESC_CALL", /* name */
876 false, /* partial_inplace */
878 ENCODE_ITYPE_IMM (-1U), /* dst_mask */
879 false) /* pcrel_offset */
882 static reloc_howto_type howto_table_internal
[] =
884 /* R_RISCV_DELETE. */
887 /* High 6 bits of 18-bit absolute address. */
888 HOWTO (R_RISCV_RVC_LUI
, /* type */
892 false, /* pc_relative */
894 complain_overflow_dont
, /* complain_on_overflow */
895 bfd_elf_generic_reloc
, /* special_function */
896 "R_RISCV_RVC_LUI", /* name */
897 false, /* partial_inplace */
899 ENCODE_CITYPE_IMM (-1U), /* dst_mask */
900 false), /* pcrel_offset */
902 /* GP-relative load. */
903 HOWTO (R_RISCV_GPREL_I
, /* type */
907 false, /* pc_relative */
909 complain_overflow_dont
, /* complain_on_overflow */
910 bfd_elf_generic_reloc
, /* special_function */
911 "R_RISCV_GPREL_I", /* name */
912 false, /* partial_inplace */
914 ENCODE_ITYPE_IMM (-1U), /* dst_mask */
915 false), /* pcrel_offset */
917 /* GP-relative store. */
918 HOWTO (R_RISCV_GPREL_S
, /* type */
922 false, /* pc_relative */
924 complain_overflow_dont
, /* complain_on_overflow */
925 bfd_elf_generic_reloc
, /* special_function */
926 "R_RISCV_GPREL_S", /* name */
927 false, /* partial_inplace */
929 ENCODE_STYPE_IMM (-1U), /* dst_mask */
930 false), /* pcrel_offset */
932 /* TP-relative TLS LE load. */
933 HOWTO (R_RISCV_TPREL_I
, /* type */
937 false, /* pc_relative */
939 complain_overflow_signed
, /* complain_on_overflow */
940 bfd_elf_generic_reloc
, /* special_function */
941 "R_RISCV_TPREL_I", /* name */
942 false, /* partial_inplace */
944 ENCODE_ITYPE_IMM (-1U), /* dst_mask */
945 false), /* pcrel_offset */
947 /* TP-relative TLS LE store. */
948 HOWTO (R_RISCV_TPREL_S
, /* type */
952 false, /* pc_relative */
954 complain_overflow_signed
, /* complain_on_overflow */
955 bfd_elf_generic_reloc
, /* special_function */
956 "R_RISCV_TPREL_S", /* name */
957 false, /* partial_inplace */
959 ENCODE_STYPE_IMM (-1U), /* dst_mask */
960 false), /* pcrel_offset */
963 /* A mapping from BFD reloc types to RISC-V ELF reloc types. */
966 bfd_reloc_code_real_type bfd_val
;
967 enum elf_riscv_reloc_type elf_val
;
970 static const struct elf_reloc_map riscv_reloc_map
[] =
972 { BFD_RELOC_NONE
, R_RISCV_NONE
},
973 { BFD_RELOC_32
, R_RISCV_32
},
974 { BFD_RELOC_64
, R_RISCV_64
},
975 { BFD_RELOC_RISCV_ADD8
, R_RISCV_ADD8
},
976 { BFD_RELOC_RISCV_ADD16
, R_RISCV_ADD16
},
977 { BFD_RELOC_RISCV_ADD32
, R_RISCV_ADD32
},
978 { BFD_RELOC_RISCV_ADD64
, R_RISCV_ADD64
},
979 { BFD_RELOC_RISCV_SUB8
, R_RISCV_SUB8
},
980 { BFD_RELOC_RISCV_SUB16
, R_RISCV_SUB16
},
981 { BFD_RELOC_RISCV_SUB32
, R_RISCV_SUB32
},
982 { BFD_RELOC_RISCV_SUB64
, R_RISCV_SUB64
},
983 { BFD_RELOC_CTOR
, R_RISCV_64
},
984 { BFD_RELOC_12_PCREL
, R_RISCV_BRANCH
},
985 { BFD_RELOC_RISCV_HI20
, R_RISCV_HI20
},
986 { BFD_RELOC_RISCV_LO12_I
, R_RISCV_LO12_I
},
987 { BFD_RELOC_RISCV_LO12_S
, R_RISCV_LO12_S
},
988 { BFD_RELOC_RISCV_PCREL_LO12_I
, R_RISCV_PCREL_LO12_I
},
989 { BFD_RELOC_RISCV_PCREL_LO12_S
, R_RISCV_PCREL_LO12_S
},
990 { BFD_RELOC_RISCV_CALL
, R_RISCV_CALL
},
991 { BFD_RELOC_RISCV_CALL_PLT
, R_RISCV_CALL_PLT
},
992 { BFD_RELOC_RISCV_PCREL_HI20
, R_RISCV_PCREL_HI20
},
993 { BFD_RELOC_RISCV_JMP
, R_RISCV_JAL
},
994 { BFD_RELOC_RISCV_GOT_HI20
, R_RISCV_GOT_HI20
},
995 { BFD_RELOC_RISCV_TLS_DTPMOD32
, R_RISCV_TLS_DTPMOD32
},
996 { BFD_RELOC_RISCV_TLS_DTPREL32
, R_RISCV_TLS_DTPREL32
},
997 { BFD_RELOC_RISCV_TLS_DTPMOD64
, R_RISCV_TLS_DTPMOD64
},
998 { BFD_RELOC_RISCV_TLS_DTPREL64
, R_RISCV_TLS_DTPREL64
},
999 { BFD_RELOC_RISCV_TLS_TPREL32
, R_RISCV_TLS_TPREL32
},
1000 { BFD_RELOC_RISCV_TLS_TPREL64
, R_RISCV_TLS_TPREL64
},
1001 { BFD_RELOC_RISCV_TPREL_HI20
, R_RISCV_TPREL_HI20
},
1002 { BFD_RELOC_RISCV_TPREL_ADD
, R_RISCV_TPREL_ADD
},
1003 { BFD_RELOC_RISCV_TPREL_LO12_S
, R_RISCV_TPREL_LO12_S
},
1004 { BFD_RELOC_RISCV_TPREL_LO12_I
, R_RISCV_TPREL_LO12_I
},
1005 { BFD_RELOC_RISCV_TLS_GOT_HI20
, R_RISCV_TLS_GOT_HI20
},
1006 { BFD_RELOC_RISCV_TLS_GD_HI20
, R_RISCV_TLS_GD_HI20
},
1007 { BFD_RELOC_RISCV_TLSDESC_HI20
, R_RISCV_TLSDESC_HI20
},
1008 { BFD_RELOC_RISCV_TLSDESC_LOAD_LO12
, R_RISCV_TLSDESC_LOAD_LO12
},
1009 { BFD_RELOC_RISCV_TLSDESC_ADD_LO12
, R_RISCV_TLSDESC_ADD_LO12
},
1010 { BFD_RELOC_RISCV_TLSDESC_CALL
, R_RISCV_TLSDESC_CALL
},
1011 { BFD_RELOC_RISCV_ALIGN
, R_RISCV_ALIGN
},
1012 { BFD_RELOC_RISCV_RVC_BRANCH
, R_RISCV_RVC_BRANCH
},
1013 { BFD_RELOC_RISCV_RVC_JUMP
, R_RISCV_RVC_JUMP
},
1014 { BFD_RELOC_RISCV_RELAX
, R_RISCV_RELAX
},
1015 { BFD_RELOC_RISCV_SUB6
, R_RISCV_SUB6
},
1016 { BFD_RELOC_RISCV_SET6
, R_RISCV_SET6
},
1017 { BFD_RELOC_RISCV_SET8
, R_RISCV_SET8
},
1018 { BFD_RELOC_RISCV_SET16
, R_RISCV_SET16
},
1019 { BFD_RELOC_RISCV_SET32
, R_RISCV_SET32
},
1020 { BFD_RELOC_RISCV_32_PCREL
, R_RISCV_32_PCREL
},
1021 { BFD_RELOC_RISCV_SET_ULEB128
, R_RISCV_SET_ULEB128
},
1022 { BFD_RELOC_RISCV_SUB_ULEB128
, R_RISCV_SUB_ULEB128
},
1025 /* Given a BFD reloc type, return a howto structure. */
1028 riscv_reloc_type_lookup (bfd
*abfd ATTRIBUTE_UNUSED
,
1029 bfd_reloc_code_real_type code
)
1033 for (i
= 0; i
< ARRAY_SIZE (riscv_reloc_map
); i
++)
1034 if (riscv_reloc_map
[i
].bfd_val
== code
)
1035 return &howto_table
[(int) riscv_reloc_map
[i
].elf_val
];
1037 bfd_set_error (bfd_error_bad_value
);
1042 riscv_reloc_name_lookup (bfd
*abfd ATTRIBUTE_UNUSED
, const char *r_name
)
1046 for (i
= 0; i
< ARRAY_SIZE (howto_table
); i
++)
1047 if (howto_table
[i
].name
&& strcasecmp (howto_table
[i
].name
, r_name
) == 0)
1048 return &howto_table
[i
];
1054 riscv_elf_rtype_to_howto (bfd
*abfd
, unsigned int r_type
)
1056 if (r_type
< ARRAY_SIZE (howto_table
))
1057 return &howto_table
[r_type
];
1058 else if (r_type
< R_RISCV_max
+ ARRAY_SIZE (howto_table_internal
))
1059 return &howto_table_internal
[r_type
- R_RISCV_max
];
1062 (*_bfd_error_handler
) (_("%pB: unsupported relocation type %#x"),
1064 bfd_set_error (bfd_error_bad_value
);
1069 /* Special_function of RISCV_ADD and RISCV_SUB relocations. */
1071 static bfd_reloc_status_type
1072 riscv_elf_add_sub_reloc (bfd
*abfd
,
1073 arelent
*reloc_entry
,
1076 asection
*input_section
,
1078 char **error_message ATTRIBUTE_UNUSED
)
1080 reloc_howto_type
*howto
= reloc_entry
->howto
;
1083 if (output_bfd
!= NULL
1084 && (symbol
->flags
& BSF_SECTION_SYM
) == 0
1085 && (!reloc_entry
->howto
->partial_inplace
|| reloc_entry
->addend
== 0))
1087 reloc_entry
->address
+= input_section
->output_offset
;
1088 return bfd_reloc_ok
;
1091 if (output_bfd
!= NULL
)
1092 return bfd_reloc_continue
;
1094 relocation
= symbol
->value
+ symbol
->section
->output_section
->vma
1095 + symbol
->section
->output_offset
+ reloc_entry
->addend
;
1097 bfd_size_type octets
= reloc_entry
->address
1098 * bfd_octets_per_byte (abfd
, input_section
);
1099 if (!bfd_reloc_offset_in_range (reloc_entry
->howto
, abfd
,
1100 input_section
, octets
))
1101 return bfd_reloc_outofrange
;
1103 bfd_vma old_value
= bfd_get (howto
->bitsize
, abfd
,
1104 data
+ reloc_entry
->address
);
1106 switch (howto
->type
)
1112 relocation
= old_value
+ relocation
;
1115 relocation
= (old_value
& ~howto
->dst_mask
)
1116 | (((old_value
& howto
->dst_mask
) - relocation
)
1123 relocation
= old_value
- relocation
;
1126 bfd_put (howto
->bitsize
, abfd
, relocation
, data
+ reloc_entry
->address
);
1128 return bfd_reloc_ok
;
1131 /* Special handler for relocations which don't have to be relocated.
1132 This function just simply return bfd_reloc_ok. */
1134 static bfd_reloc_status_type
1135 riscv_elf_ignore_reloc (bfd
*abfd ATTRIBUTE_UNUSED
,
1136 arelent
*reloc_entry
,
1137 asymbol
*symbol ATTRIBUTE_UNUSED
,
1138 void *data ATTRIBUTE_UNUSED
,
1139 asection
*input_section
,
1141 char **error_message ATTRIBUTE_UNUSED
)
1143 if (output_bfd
!= NULL
)
1144 reloc_entry
->address
+= input_section
->output_offset
;
1145 return bfd_reloc_ok
;
1148 /* Always add the IMPLICIT for the SUBSET. */
1151 check_implicit_always (const char *implicit ATTRIBUTE_UNUSED
,
1152 riscv_subset_t
*subset ATTRIBUTE_UNUSED
)
1157 /* Add the IMPLICIT only when the version of SUBSET less than 2.1. */
1160 check_implicit_for_i (const char *implicit ATTRIBUTE_UNUSED
,
1161 riscv_subset_t
*subset
)
1163 return (subset
->major_version
< 2
1164 || (subset
->major_version
== 2
1165 && subset
->minor_version
< 1));
1168 /* Record all implicit information for the subsets. */
1169 struct riscv_implicit_subset
1171 const char *subset_name
;
1172 const char *implicit_name
;
1173 /* A function to determine if we need to add the implicit subset. */
1174 bool (*check_func
) (const char *, riscv_subset_t
*);
1176 static struct riscv_implicit_subset riscv_implicit_subsets
[] =
1178 {"e", "i", check_implicit_always
},
1179 {"i", "zicsr", check_implicit_for_i
},
1180 {"i", "zifencei", check_implicit_for_i
},
1181 {"g", "i", check_implicit_always
},
1182 {"g", "m", check_implicit_always
},
1183 {"g", "a", check_implicit_always
},
1184 {"g", "f", check_implicit_always
},
1185 {"g", "d", check_implicit_always
},
1186 {"g", "zicsr", check_implicit_always
},
1187 {"g", "zifencei", check_implicit_always
},
1188 {"m", "zmmul", check_implicit_always
},
1189 {"h", "zicsr", check_implicit_always
},
1190 {"q", "d", check_implicit_always
},
1191 {"v", "d", check_implicit_always
},
1192 {"v", "zve64d", check_implicit_always
},
1193 {"v", "zvl128b", check_implicit_always
},
1194 {"zabha", "a", check_implicit_always
},
1195 {"zvfh", "zvfhmin", check_implicit_always
},
1196 {"zvfh", "zfhmin", check_implicit_always
},
1197 {"zvfhmin", "zve32f", check_implicit_always
},
1198 {"zve64d", "d", check_implicit_always
},
1199 {"zve64d", "zve64f", check_implicit_always
},
1200 {"zve64f", "zve32f", check_implicit_always
},
1201 {"zve64f", "zve64x", check_implicit_always
},
1202 {"zve64f", "zvl64b", check_implicit_always
},
1203 {"zve32f", "f", check_implicit_always
},
1204 {"zve32f", "zvl32b", check_implicit_always
},
1205 {"zve32f", "zve32x", check_implicit_always
},
1206 {"zve64x", "zve32x", check_implicit_always
},
1207 {"zve64x", "zvl64b", check_implicit_always
},
1208 {"zve32x", "zvl32b", check_implicit_always
},
1209 {"zve32x", "zicsr", check_implicit_always
},
1210 {"zvl65536b", "zvl32768b", check_implicit_always
},
1211 {"zvl32768b", "zvl16384b", check_implicit_always
},
1212 {"zvl16384b", "zvl8192b", check_implicit_always
},
1213 {"zvl8192b", "zvl4096b", check_implicit_always
},
1214 {"zvl4096b", "zvl2048b", check_implicit_always
},
1215 {"zvl2048b", "zvl1024b", check_implicit_always
},
1216 {"zvl1024b", "zvl512b", check_implicit_always
},
1217 {"zvl512b", "zvl256b", check_implicit_always
},
1218 {"zvl256b", "zvl128b", check_implicit_always
},
1219 {"zvl128b", "zvl64b", check_implicit_always
},
1220 {"zvl64b", "zvl32b", check_implicit_always
},
1221 {"zicntr", "zicsr", check_implicit_always
},
1222 {"zihpm", "zicsr", check_implicit_always
},
1223 {"zcd", "d", check_implicit_always
},
1224 {"zcf", "f", check_implicit_always
},
1225 {"zfa", "f", check_implicit_always
},
1226 {"d", "f", check_implicit_always
},
1227 {"zfh", "zfhmin", check_implicit_always
},
1228 {"zfhmin", "f", check_implicit_always
},
1229 {"f", "zicsr", check_implicit_always
},
1230 {"zqinx", "zdinx", check_implicit_always
},
1231 {"zdinx", "zfinx", check_implicit_always
},
1232 {"zhinx", "zhinxmin", check_implicit_always
},
1233 {"zhinxmin", "zfinx", check_implicit_always
},
1234 {"zfinx", "zicsr", check_implicit_always
},
1235 {"zk", "zkn", check_implicit_always
},
1236 {"zk", "zkr", check_implicit_always
},
1237 {"zk", "zkt", check_implicit_always
},
1238 {"zkn", "zbkb", check_implicit_always
},
1239 {"zkn", "zbkc", check_implicit_always
},
1240 {"zkn", "zbkx", check_implicit_always
},
1241 {"zkn", "zkne", check_implicit_always
},
1242 {"zkn", "zknd", check_implicit_always
},
1243 {"zkn", "zknh", check_implicit_always
},
1244 {"zks", "zbkb", check_implicit_always
},
1245 {"zks", "zbkc", check_implicit_always
},
1246 {"zks", "zbkx", check_implicit_always
},
1247 {"zks", "zksed", check_implicit_always
},
1248 {"zks", "zksh", check_implicit_always
},
1249 {"zvbb", "zvkb", check_implicit_always
},
1250 {"zvkn", "zvkned", check_implicit_always
},
1251 {"zvkn", "zvknha", check_implicit_always
},
1252 {"zvkn", "zvknhb", check_implicit_always
},
1253 {"zvkn", "zvkb", check_implicit_always
},
1254 {"zvkn", "zvkt", check_implicit_always
},
1255 {"zvkng", "zvkn", check_implicit_always
},
1256 {"zvkng", "zvkg", check_implicit_always
},
1257 {"zvknc", "zvkn", check_implicit_always
},
1258 {"zvknc", "zvbc", check_implicit_always
},
1259 {"zvks", "zvksed", check_implicit_always
},
1260 {"zvks", "zvksh", check_implicit_always
},
1261 {"zvks", "zvkb", check_implicit_always
},
1262 {"zvks", "zvkt", check_implicit_always
},
1263 {"zvksg", "zvks", check_implicit_always
},
1264 {"zvksg", "zvkg", check_implicit_always
},
1265 {"zvksc", "zvks", check_implicit_always
},
1266 {"zvksc", "zvbc", check_implicit_always
},
1267 {"zcf", "zca", check_implicit_always
},
1268 {"zcd", "zca", check_implicit_always
},
1269 {"zcb", "zca", check_implicit_always
},
1270 {"zcmp", "zca", check_implicit_always
},
1271 {"smaia", "ssaia", check_implicit_always
},
1272 {"smcntrpmf", "zicsr", check_implicit_always
},
1273 {"smstateen", "ssstateen", check_implicit_always
},
1274 {"smepmp", "zicsr", check_implicit_always
},
1275 {"ssaia", "zicsr", check_implicit_always
},
1276 {"sscofpmf", "zicsr", check_implicit_always
},
1277 {"ssstateen", "zicsr", check_implicit_always
},
1278 {"sstc", "zicsr", check_implicit_always
},
1279 {"svadu", "zicsr", check_implicit_always
},
1280 {"b", "zba", check_implicit_always
},
1281 {"b", "zbb", check_implicit_always
},
1282 {"b", "zbs", check_implicit_always
},
1283 {"a", "zaamo", check_implicit_always
},
1284 {"a", "zalrsc", check_implicit_always
},
1286 {"xsfvcp", "zve32x", check_implicit_always
},
1290 /* For default_enable field, decide if the extension should
1291 be enbaled by default. */
1293 #define EXT_DEFAULT 0x1
1295 /* List all extensions that binutils should know about. */
1297 struct riscv_supported_ext
1300 enum riscv_spec_class isa_spec_class
;
1303 unsigned long default_enable
;
1306 /* The standard extensions must be added in canonical order. */
1308 static struct riscv_supported_ext riscv_supported_std_ext
[] =
1310 {"e", ISA_SPEC_CLASS_20191213
, 1, 9, 0 },
1311 {"e", ISA_SPEC_CLASS_20190608
, 1, 9, 0 },
1312 {"e", ISA_SPEC_CLASS_2P2
, 1, 9, 0 },
1313 {"i", ISA_SPEC_CLASS_20191213
, 2, 1, 0 },
1314 {"i", ISA_SPEC_CLASS_20190608
, 2, 1, 0 },
1315 {"i", ISA_SPEC_CLASS_2P2
, 2, 0, 0 },
1316 /* The g is a special case which we don't want to output it,
1317 but still need it when adding implicit extensions. */
1318 {"g", ISA_SPEC_CLASS_NONE
, RISCV_UNKNOWN_VERSION
, RISCV_UNKNOWN_VERSION
, EXT_DEFAULT
},
1319 {"m", ISA_SPEC_CLASS_20191213
, 2, 0, 0 },
1320 {"m", ISA_SPEC_CLASS_20190608
, 2, 0, 0 },
1321 {"m", ISA_SPEC_CLASS_2P2
, 2, 0, 0 },
1322 {"a", ISA_SPEC_CLASS_20191213
, 2, 1, 0 },
1323 {"a", ISA_SPEC_CLASS_20190608
, 2, 0, 0 },
1324 {"a", ISA_SPEC_CLASS_2P2
, 2, 0, 0 },
1325 {"f", ISA_SPEC_CLASS_20191213
, 2, 2, 0 },
1326 {"f", ISA_SPEC_CLASS_20190608
, 2, 2, 0 },
1327 {"f", ISA_SPEC_CLASS_2P2
, 2, 0, 0 },
1328 {"d", ISA_SPEC_CLASS_20191213
, 2, 2, 0 },
1329 {"d", ISA_SPEC_CLASS_20190608
, 2, 2, 0 },
1330 {"d", ISA_SPEC_CLASS_2P2
, 2, 0, 0 },
1331 {"q", ISA_SPEC_CLASS_20191213
, 2, 2, 0 },
1332 {"q", ISA_SPEC_CLASS_20190608
, 2, 2, 0 },
1333 {"q", ISA_SPEC_CLASS_2P2
, 2, 0, 0 },
1334 {"c", ISA_SPEC_CLASS_20191213
, 2, 0, 0 },
1335 {"c", ISA_SPEC_CLASS_20190608
, 2, 0, 0 },
1336 {"c", ISA_SPEC_CLASS_2P2
, 2, 0, 0 },
1337 {"b", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1338 {"v", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1339 {"h", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1343 static struct riscv_supported_ext riscv_supported_std_z_ext
[] =
1345 {"zicbom", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1346 {"zicbop", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1347 {"zicboz", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1348 {"zicond", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1349 {"zicntr", ISA_SPEC_CLASS_DRAFT
, 2, 0, 0 },
1350 {"zicsr", ISA_SPEC_CLASS_20191213
, 2, 0, 0 },
1351 {"zicsr", ISA_SPEC_CLASS_20190608
, 2, 0, 0 },
1352 {"zifencei", ISA_SPEC_CLASS_20191213
, 2, 0, 0 },
1353 {"zifencei", ISA_SPEC_CLASS_20190608
, 2, 0, 0 },
1354 {"zihintntl", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1355 {"zihintpause", ISA_SPEC_CLASS_DRAFT
, 2, 0, 0 },
1356 {"zihpm", ISA_SPEC_CLASS_DRAFT
, 2, 0, 0 },
1357 {"zmmul", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1358 {"zaamo", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1359 {"zabha", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1360 {"zalrsc", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1361 {"zawrs", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1362 {"zfa", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1363 {"zfh", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1364 {"zfhmin", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1365 {"zfinx", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1366 {"zdinx", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1367 {"zqinx", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1368 {"zhinx", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1369 {"zhinxmin", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1370 {"zbb", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1371 {"zba", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1372 {"zbc", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1373 {"zbs", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1374 {"zbkb", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1375 {"zbkc", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1376 {"zbkx", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1377 {"zk", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1378 {"zkn", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1379 {"zknd", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1380 {"zkne", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1381 {"zknh", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1382 {"zkr", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1383 {"zks", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1384 {"zksed", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1385 {"zksh", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1386 {"zkt", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1387 {"zve32x", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1388 {"zve32f", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1389 {"zve64x", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1390 {"zve64f", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1391 {"zve64d", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1392 {"zvbb", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1393 {"zvbc", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1394 {"zvfh", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1395 {"zvfhmin", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1396 {"zvkb", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1397 {"zvkg", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1398 {"zvkn", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1399 {"zvkng", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1400 {"zvknc", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1401 {"zvkned", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1402 {"zvknha", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1403 {"zvknhb", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1404 {"zvksed", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1405 {"zvksh", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1406 {"zvks", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1407 {"zvksg", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1408 {"zvksc", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1409 {"zvkt", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1410 {"zvl32b", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1411 {"zvl64b", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1412 {"zvl128b", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1413 {"zvl256b", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1414 {"zvl512b", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1415 {"zvl1024b", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1416 {"zvl2048b", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1417 {"zvl4096b", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1418 {"zvl8192b", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1419 {"zvl16384b", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1420 {"zvl32768b", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1421 {"zvl65536b", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1422 {"ztso", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1423 {"zca", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1424 {"zcb", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1425 {"zcf", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1426 {"zcd", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1427 {"zcmp", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1431 static struct riscv_supported_ext riscv_supported_std_s_ext
[] =
1433 {"smaia", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1434 {"smcntrpmf", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1435 {"smepmp", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1436 {"smstateen", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1437 {"ssaia", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1438 {"sscofpmf", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1439 {"ssstateen", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1440 {"sstc", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1441 {"svadu", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1442 {"svinval", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1443 {"svnapot", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1444 {"svpbmt", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1448 static struct riscv_supported_ext riscv_supported_std_zxm_ext
[] =
1453 static struct riscv_supported_ext riscv_supported_vendor_x_ext
[] =
1455 {"xcvmac", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1456 {"xcvalu", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1457 {"xtheadba", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1458 {"xtheadbb", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1459 {"xtheadbs", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1460 {"xtheadcmo", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1461 {"xtheadcondmov", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1462 {"xtheadfmemidx", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1463 {"xtheadfmv", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1464 {"xtheadint", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1465 {"xtheadmac", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1466 {"xtheadmemidx", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1467 {"xtheadmempair", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1468 {"xtheadsync", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1469 {"xtheadvector", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1470 {"xtheadzvamo", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1471 {"xventanacondops", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1472 {"xsfvcp", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0},
1476 const struct riscv_supported_ext
*riscv_all_supported_ext
[] =
1478 riscv_supported_std_ext
,
1479 riscv_supported_std_z_ext
,
1480 riscv_supported_std_s_ext
,
1481 riscv_supported_std_zxm_ext
,
1482 riscv_supported_vendor_x_ext
,
1486 /* ISA extension prefixed name class. Must define them in parsing order. */
1487 enum riscv_prefix_ext_class
1496 /* Record the strings of the prefixed extensions, and their corresponding
1497 classes. The more letters of the prefix string, the more forward it must
1498 be defined. Otherwise, the riscv_get_prefix_class will map it to the
1500 struct riscv_parse_prefix_config
1502 /* Class of the extension. */
1503 enum riscv_prefix_ext_class
class;
1505 /* Prefix string for error printing and internal parser usage. */
1508 static const struct riscv_parse_prefix_config parse_config
[] =
1510 {RV_ISA_CLASS_ZXM
, "zxm"},
1511 {RV_ISA_CLASS_Z
, "z"},
1512 {RV_ISA_CLASS_S
, "s"},
1513 {RV_ISA_CLASS_X
, "x"},
1514 {RV_ISA_CLASS_SINGLE
, NULL
}
1517 /* Get the prefixed name class for the extensions, the class also
1518 means the order of the prefixed extensions. */
1520 static enum riscv_prefix_ext_class
1521 riscv_get_prefix_class (const char *arch
)
1524 while (parse_config
[i
].class != RV_ISA_CLASS_SINGLE
)
1526 if (strncmp (arch
, parse_config
[i
].prefix
,
1527 strlen (parse_config
[i
].prefix
)) == 0)
1528 return parse_config
[i
].class;
1531 return RV_ISA_CLASS_SINGLE
;
1534 /* Check KNOWN_EXTS to see if the EXT is supported. */
1537 riscv_known_prefixed_ext (const char *ext
,
1538 struct riscv_supported_ext
*known_exts
)
1541 for (i
= 0; known_exts
[i
].name
!= NULL
; ++i
)
1542 if (strcmp (ext
, known_exts
[i
].name
) == 0)
1547 /* Check whether the prefixed extension is recognized or not. Return
1548 true if recognized, otehrwise return false. */
1551 riscv_recognized_prefixed_ext (const char *ext
)
1553 enum riscv_prefix_ext_class
class = riscv_get_prefix_class (ext
);
1556 case RV_ISA_CLASS_Z
:
1557 return riscv_known_prefixed_ext (ext
, riscv_supported_std_z_ext
);
1558 case RV_ISA_CLASS_ZXM
:
1559 return riscv_known_prefixed_ext (ext
, riscv_supported_std_zxm_ext
);
1560 case RV_ISA_CLASS_S
:
1561 return riscv_known_prefixed_ext (ext
, riscv_supported_std_s_ext
);
1562 case RV_ISA_CLASS_X
:
1563 /* Only the single x is unrecognized. */
1564 if (strcmp (ext
, "x") != 0)
1572 /* Canonical order for single letter extensions. */
1573 static const char riscv_ext_canonical_order
[] = "eigmafdqlcbkjtpvnh";
1575 /* Array is used to compare the orders of standard extensions quickly. */
1576 static int riscv_ext_order
[26] = {0};
1578 /* Init the riscv_ext_order array. */
1581 riscv_init_ext_order (void)
1583 static bool inited
= false;
1587 /* The orders of all standard extensions are positive. */
1590 for (const char *ext
= &riscv_ext_canonical_order
[0]; *ext
; ++ext
)
1591 riscv_ext_order
[(*ext
- 'a')] = order
++;
1593 /* Some of the prefixed keyword are not single letter, so we set
1594 their prefixed orders in the riscv_compare_subsets directly,
1595 not through the riscv_ext_order. */
1600 /* Similar to the strcmp. It returns an integer less than, equal to,
1601 or greater than zero if `subset2` is found, respectively, to be less
1602 than, to match, or be greater than `subset1`.
1605 Zero: Preserved keywords.
1606 Positive number: Standard extensions.
1607 Negative number: Prefixed keywords. */
1610 riscv_compare_subsets (const char *subset1
, const char *subset2
)
1612 int order1
= riscv_ext_order
[(*subset1
- 'a')];
1613 int order2
= riscv_ext_order
[(*subset2
- 'a')];
1615 /* Compare the standard extension first. */
1616 if (order1
> 0 && order2
> 0)
1617 return order1
- order2
;
1619 /* Set the prefixed orders to negative numbers. */
1620 enum riscv_prefix_ext_class class1
= riscv_get_prefix_class (subset1
);
1621 enum riscv_prefix_ext_class class2
= riscv_get_prefix_class (subset2
);
1623 if (class1
!= RV_ISA_CLASS_SINGLE
)
1624 order1
= - (int) class1
;
1625 if (class2
!= RV_ISA_CLASS_SINGLE
)
1626 order2
= - (int) class2
;
1628 if (order1
== order2
)
1630 /* Compare the standard addition z extensions. */
1631 if (class1
== RV_ISA_CLASS_Z
)
1633 order1
= riscv_ext_order
[(*++subset1
- 'a')];
1634 order2
= riscv_ext_order
[(*++subset2
- 'a')];
1635 if (order1
!= order2
)
1636 return order1
- order2
;
1638 return strcasecmp (++subset1
, ++subset2
);
1641 return order2
- order1
;
1644 /* Find subset in the list. Return TRUE and set `current` to the subset
1645 if it is found. Otherwise, return FALSE and set `current` to the place
1646 where we should insert the subset. However, return FALSE with the NULL
1647 `current` means we should insert the subset at the head of subset list,
1651 riscv_lookup_subset (const riscv_subset_list_t
*subset_list
,
1653 riscv_subset_t
**current
)
1655 riscv_subset_t
*s
, *pre_s
= NULL
;
1657 /* If the subset is added in order, then just add it at the tail. */
1658 if (subset_list
->tail
!= NULL
1659 && riscv_compare_subsets (subset_list
->tail
->name
, subset
) < 0)
1661 *current
= subset_list
->tail
;
1665 for (s
= subset_list
->head
;
1667 pre_s
= s
, s
= s
->next
)
1669 int cmp
= riscv_compare_subsets (s
->name
, subset
);
1683 /* Add the extension to the subset list. Search the
1684 list first, and then find the right place to add. */
1687 riscv_add_subset (riscv_subset_list_t
*subset_list
,
1692 riscv_subset_t
*current
, *new;
1694 if (riscv_lookup_subset (subset_list
, subset
, ¤t
))
1697 new = xmalloc (sizeof *new);
1698 new->name
= xstrdup (subset
);
1699 new->major_version
= major
;
1700 new->minor_version
= minor
;
1703 if (current
!= NULL
)
1705 new->next
= current
->next
;
1706 current
->next
= new;
1710 new->next
= subset_list
->head
;
1711 subset_list
->head
= new;
1714 if (new->next
== NULL
)
1715 subset_list
->tail
= new;
1718 /* Get the default versions from the riscv_supported_*ext tables. */
1721 riscv_get_default_ext_version (enum riscv_spec_class
*default_isa_spec
,
1727 || default_isa_spec
== NULL
1728 || *default_isa_spec
== ISA_SPEC_CLASS_NONE
)
1731 struct riscv_supported_ext
*table
= NULL
;
1732 enum riscv_prefix_ext_class
class = riscv_get_prefix_class (name
);
1735 case RV_ISA_CLASS_ZXM
: table
= riscv_supported_std_zxm_ext
; break;
1736 case RV_ISA_CLASS_Z
: table
= riscv_supported_std_z_ext
; break;
1737 case RV_ISA_CLASS_S
: table
= riscv_supported_std_s_ext
; break;
1738 case RV_ISA_CLASS_X
: table
= riscv_supported_vendor_x_ext
; break;
1740 table
= riscv_supported_std_ext
;
1744 while (table
!= NULL
&& table
[i
].name
!= NULL
)
1746 if (strcmp (table
[i
].name
, name
) == 0
1747 && (table
[i
].isa_spec_class
== ISA_SPEC_CLASS_DRAFT
1748 || table
[i
].isa_spec_class
== *default_isa_spec
))
1750 *major_version
= table
[i
].major_version
;
1751 *minor_version
= table
[i
].minor_version
;
1758 /* Find the default versions for the extension before adding them to
1759 the subset list, if their versions are RISCV_UNKNOWN_VERSION.
1760 Afterwards, report errors if we can not find their default versions. */
1763 riscv_parse_add_subset (riscv_parse_subset_t
*rps
,
1769 int major_version
= major
;
1770 int minor_version
= minor
;
1772 if (major_version
== RISCV_UNKNOWN_VERSION
1773 || minor_version
== RISCV_UNKNOWN_VERSION
)
1774 riscv_get_default_ext_version (rps
->isa_spec
, subset
,
1775 &major_version
, &minor_version
);
1777 /* We don't care the versions of the implicit extensions. */
1779 && (major_version
== RISCV_UNKNOWN_VERSION
1780 || minor_version
== RISCV_UNKNOWN_VERSION
))
1782 if (subset
[0] == 'x')
1784 (_("x ISA extension `%s' must be set with the versions"),
1786 /* Allow old ISA spec can recognize zicsr and zifencei. */
1787 else if (strcmp (subset
, "zicsr") != 0
1788 && strcmp (subset
, "zifencei") != 0)
1790 (_("cannot find default versions of the ISA extension `%s'"),
1795 riscv_add_subset (rps
->subset_list
, subset
,
1796 major_version
, minor_version
);
1799 /* Release subset list. */
1802 riscv_release_subset_list (riscv_subset_list_t
*subset_list
)
1804 while (subset_list
->head
!= NULL
)
1806 riscv_subset_t
*next
= subset_list
->head
->next
;
1807 free ((void *)subset_list
->head
->name
);
1808 free (subset_list
->head
);
1809 subset_list
->head
= next
;
1812 subset_list
->tail
= NULL
;
1814 if (subset_list
->arch_str
!= NULL
)
1816 free ((void*) subset_list
->arch_str
);
1817 subset_list
->arch_str
= NULL
;
1821 /* Parsing extension version.
1824 Points to the end of version
1827 `p`: Curent parsing position.
1828 `major_version`: Parsed major version.
1829 `minor_version`: Parsed minor version. */
1832 riscv_parsing_subset_version (const char *p
,
1836 bool major_p
= true;
1848 /* Might be beginning of `p` extension. */
1852 *major_version
= version
;
1856 else if (ISDIGIT (*p
))
1857 version
= (version
* 10) + (*p
- '0');
1863 *major_version
= version
;
1865 *minor_version
= version
;
1867 /* We can not find any version in string. */
1868 if (*major_version
== 0 && *minor_version
== 0)
1870 *major_version
= RISCV_UNKNOWN_VERSION
;
1871 *minor_version
= RISCV_UNKNOWN_VERSION
;
1877 /* Parsing function for both standard and prefixed extensions.
1880 Points to the end of extensions.
1883 `rps`: Hooks and status for parsing extensions.
1884 `arch`: Full ISA string.
1885 `p`: Curent parsing position. */
1888 riscv_parse_extensions (riscv_parse_subset_t
*rps
,
1892 /* First letter must start with i, e or g. */
1893 if (*p
!= 'e' && *p
!= 'i' && *p
!= 'g')
1896 (_("%s: first ISA extension must be `e', `i' or `g'"),
1909 char *subset
= xstrdup (p
);
1910 char *q
= subset
; /* Start of version. */
1911 const char *end_of_version
;
1912 bool implicit
= false;
1914 enum riscv_prefix_ext_class
class = riscv_get_prefix_class (p
);
1915 if (class == RV_ISA_CLASS_SINGLE
)
1917 if (riscv_ext_order
[(*subset
- 'a')] == 0)
1920 (_("%s: unknown standard ISA extension or prefix class `%c'"),
1929 /* Extract the whole prefixed extension by '_'. */
1930 while (*++q
!= '\0' && *q
!= '_')
1932 /* Look forward to the first letter which is not <major>p<minor>. */
1933 bool find_any_version
= false;
1934 bool find_minor_version
= false;
1939 find_any_version
= true;
1940 else if (find_any_version
1941 && !find_minor_version
1943 && ISDIGIT (*(q
- 1)))
1944 find_minor_version
= true;
1950 /* Check if the end of extension is 'p' or not. If yes, then
1951 the second letter from the end cannot be number. */
1952 if (*(q
- 1) == 'p' && ISDIGIT (*(q
- 2)))
1956 (_("%s: invalid prefixed ISA extension `%s' ends with <number>p"),
1963 int major_version
= RISCV_UNKNOWN_VERSION
;
1964 int minor_version
= RISCV_UNKNOWN_VERSION
;
1966 riscv_parsing_subset_version (q
, &major_version
, &minor_version
);
1968 if (end_of_version
== NULL
)
1974 /* Check if the prefixed extension name is well-formed. */
1975 if (class != RV_ISA_CLASS_SINGLE
1976 && rps
->check_unknown_prefixed_ext
1977 && !riscv_recognized_prefixed_ext (subset
))
1980 (_("%s: unknown prefixed ISA extension `%s'"),
1986 /* Added g as an implicit extension. */
1987 if (class == RV_ISA_CLASS_SINGLE
1988 && strcmp (subset
, "g") == 0)
1991 major_version
= RISCV_UNKNOWN_VERSION
;
1992 minor_version
= RISCV_UNKNOWN_VERSION
;
1994 riscv_parse_add_subset (rps
, subset
,
1996 minor_version
, implicit
);
1997 p
+= end_of_version
- subset
;
2000 if (class != RV_ISA_CLASS_SINGLE
2001 && *p
!= '\0' && *p
!= '_')
2004 (_("%s: prefixed ISA extension must separate with _"),
2013 /* Add the implicit extensions. */
2016 riscv_parse_add_implicit_subsets (riscv_parse_subset_t
*rps
)
2018 struct riscv_implicit_subset
*t
= riscv_implicit_subsets
;
2019 bool finished
= false;
2023 for (; t
->subset_name
; t
++)
2025 riscv_subset_t
*subset
= NULL
;
2026 riscv_subset_t
*implicit_subset
= NULL
;
2027 if (riscv_lookup_subset (rps
->subset_list
, t
->subset_name
, &subset
)
2028 && !riscv_lookup_subset (rps
->subset_list
, t
->implicit_name
,
2030 && t
->check_func (t
->implicit_name
, subset
))
2032 riscv_parse_add_subset (rps
, t
->implicit_name
,
2033 RISCV_UNKNOWN_VERSION
,
2034 RISCV_UNKNOWN_VERSION
, true);
2036 /* Restart the loop and pick up any new implications. */
2038 t
= riscv_implicit_subsets
;
2045 /* Check extensions conflicts. */
2048 riscv_parse_check_conflicts (riscv_parse_subset_t
*rps
)
2050 riscv_subset_t
*subset
= NULL
;
2051 int xlen
= *rps
->xlen
;
2052 bool no_conflict
= true;
2054 if (riscv_subset_supports (rps
, "e")
2055 && riscv_subset_supports (rps
, "h"))
2058 (_("rv%de does not support the `h' extension"), xlen
);
2059 no_conflict
= false;
2061 if (riscv_lookup_subset (rps
->subset_list
, "q", &subset
)
2062 && (subset
->major_version
< 2 || (subset
->major_version
== 2
2063 && subset
->minor_version
< 2))
2066 rps
->error_handler (_("rv%d does not support the `q' extension"), xlen
);
2067 no_conflict
= false;
2069 if (riscv_subset_supports (rps
, "zcmp")
2070 && riscv_subset_supports (rps
, "zcd"))
2073 (_("zcmp' is incompatible with `d/zcd' extension"));
2074 no_conflict
= false;
2076 if (riscv_lookup_subset (rps
->subset_list
, "zcf", &subset
)
2080 (_("rv%d does not support the `zcf' extension"), xlen
);
2081 no_conflict
= false;
2083 if (riscv_lookup_subset (rps
->subset_list
, "zfinx", &subset
)
2084 && riscv_lookup_subset (rps
->subset_list
, "f", &subset
))
2087 (_("`zfinx' is conflict with the `f/d/q/zfh/zfhmin' extension"));
2088 no_conflict
= false;
2090 if (riscv_lookup_subset (rps
->subset_list
, "xtheadvector", &subset
)
2091 && riscv_lookup_subset (rps
->subset_list
, "v", &subset
))
2094 (_("`xtheadvector' is conflict with the `v' extension"));
2095 no_conflict
= false;
2098 bool support_zve
= false;
2099 bool support_zvl
= false;
2100 riscv_subset_t
*s
= rps
->subset_list
->head
;
2101 for (; s
!= NULL
; s
= s
->next
)
2104 && strncmp (s
->name
, "zve", 3) == 0)
2107 && strncmp (s
->name
, "zvl", 3) == 0)
2109 if (support_zve
&& support_zvl
)
2112 if (support_zvl
&& !support_zve
)
2115 (_("zvl*b extensions need to enable either `v' or `zve' extension"));
2116 no_conflict
= false;
2122 /* Set the default subset list according to the default_enable field
2123 of riscv_supported_*ext tables. */
2126 riscv_set_default_arch (riscv_parse_subset_t
*rps
)
2128 unsigned long enable
= EXT_DEFAULT
;
2130 for (i
= 0; riscv_all_supported_ext
[i
] != NULL
; i
++)
2132 const struct riscv_supported_ext
*table
= riscv_all_supported_ext
[i
];
2133 for (j
= 0; table
[j
].name
!= NULL
; j
++)
2135 bool implicit
= false;
2136 if (strcmp (table
[j
].name
, "g") == 0)
2138 if (table
[j
].default_enable
& enable
)
2139 riscv_parse_add_subset (rps
, table
[j
].name
,
2140 RISCV_UNKNOWN_VERSION
,
2141 RISCV_UNKNOWN_VERSION
, implicit
);
2146 /* Function for parsing ISA string.
2149 Return TRUE on success.
2152 `rps`: Hooks and status for parsing extensions.
2153 `arch`: Full ISA string. */
2156 riscv_parse_subset (riscv_parse_subset_t
*rps
,
2161 /* Init the riscv_ext_order array to compare the order of extensions
2163 riscv_init_ext_order ();
2167 riscv_set_default_arch (rps
);
2168 riscv_parse_add_implicit_subsets (rps
);
2169 return riscv_parse_check_conflicts (rps
);
2172 for (p
= arch
; *p
!= '\0'; p
++)
2177 (_("%s: ISA string cannot contain uppercase letters"),
2184 if (startswith (p
, "rv32"))
2189 else if (startswith (p
, "rv64"))
2196 /* ISA string shouldn't be NULL or empty here. For linker,
2197 it might be empty when we failed to merge the ISA string
2198 in the riscv_merge_attributes. For assembler, we might
2199 give an empty string by .attribute arch, "" or -march=.
2200 However, We have already issued the correct error message
2201 in another side, so do not issue this error when the ISA
2204 rps
->error_handler (
2205 _("%s: ISA string must begin with rv32 or rv64"),
2210 /* Parse single standard and prefixed extensions. */
2211 if (riscv_parse_extensions (rps
, arch
, p
) == NULL
)
2214 /* Finally add implicit extensions according to the current
2216 riscv_parse_add_implicit_subsets (rps
);
2218 /* Check the conflicts. */
2219 return riscv_parse_check_conflicts (rps
);
2222 /* Return the number of digits for the input. */
2225 riscv_estimate_digit (unsigned num
)
2231 for (digit
= 0; num
; num
/= 10)
2237 /* Auxiliary function to estimate string length of subset list. */
2240 riscv_estimate_arch_strlen1 (const riscv_subset_t
*subset
)
2243 return 6; /* For rv32/rv64/rv128 and string terminator. */
2245 return riscv_estimate_arch_strlen1 (subset
->next
)
2246 + strlen (subset
->name
)
2247 + riscv_estimate_digit (subset
->major_version
)
2248 + 1 /* For version seperator 'p'. */
2249 + riscv_estimate_digit (subset
->minor_version
)
2250 + 1 /* For underscore. */;
2253 /* Estimate the string length of this subset list. */
2256 riscv_estimate_arch_strlen (const riscv_subset_list_t
*subset_list
)
2258 return riscv_estimate_arch_strlen1 (subset_list
->head
);
2261 /* Auxiliary function to convert subset info to string. */
2264 riscv_arch_str1 (riscv_subset_t
*subset
,
2265 char *attr_str
, char *buf
, size_t bufsz
)
2267 const char *underline
= "_";
2268 riscv_subset_t
*subset_t
= subset
;
2270 if (subset_t
== NULL
)
2273 /* No underline between rvXX and i/e. */
2274 if ((strcasecmp (subset_t
->name
, "i") == 0)
2275 || (strcasecmp (subset_t
->name
, "e") == 0))
2278 snprintf (buf
, bufsz
, "%s%s%dp%d",
2281 subset_t
->major_version
,
2282 subset_t
->minor_version
);
2284 strncat (attr_str
, buf
, bufsz
);
2286 /* Skip 'i' extension after 'e', or skip extensions which
2287 versions are unknown. */
2288 while (subset_t
->next
2289 && ((strcmp (subset_t
->name
, "e") == 0
2290 && strcmp (subset_t
->next
->name
, "i") == 0)
2291 || subset_t
->next
->major_version
== RISCV_UNKNOWN_VERSION
2292 || subset_t
->next
->minor_version
== RISCV_UNKNOWN_VERSION
))
2293 subset_t
= subset_t
->next
;
2295 riscv_arch_str1 (subset_t
->next
, attr_str
, buf
, bufsz
);
2298 /* Convert subset information into string with explicit versions. */
2301 riscv_arch_str (unsigned xlen
, const riscv_subset_list_t
*subset
)
2303 size_t arch_str_len
= riscv_estimate_arch_strlen (subset
);
2304 char *attr_str
= xmalloc (arch_str_len
);
2305 char *buf
= xmalloc (arch_str_len
);
2307 snprintf (attr_str
, arch_str_len
, "rv%u", xlen
);
2309 riscv_arch_str1 (subset
->head
, attr_str
, buf
, arch_str_len
);
2315 /* Copy the subset in the subset list. */
2317 static struct riscv_subset_t
*
2318 riscv_copy_subset (riscv_subset_list_t
*subset_list
,
2319 riscv_subset_t
*subset
)
2324 riscv_subset_t
*new = xmalloc (sizeof *new);
2325 new->name
= xstrdup (subset
->name
);
2326 new->major_version
= subset
->major_version
;
2327 new->minor_version
= subset
->minor_version
;
2328 new->next
= riscv_copy_subset (subset_list
, subset
->next
);
2330 if (subset
->next
== NULL
)
2331 subset_list
->tail
= new;
2336 /* Copy the subset list. */
2338 riscv_subset_list_t
*
2339 riscv_copy_subset_list (riscv_subset_list_t
*subset_list
)
2341 riscv_subset_list_t
*new = xmalloc (sizeof *new);
2342 new->head
= riscv_copy_subset (new, subset_list
->head
);
2343 new->arch_str
= strdup (subset_list
->arch_str
);
2347 /* Remove the SUBSET from the subset list. */
2350 riscv_remove_subset (riscv_subset_list_t
*subset_list
,
2353 riscv_subset_t
*current
= subset_list
->head
;
2354 riscv_subset_t
*pre
= NULL
;
2355 for (; current
!= NULL
; pre
= current
, current
= current
->next
)
2357 if (strcmp (current
->name
, subset
) == 0)
2360 subset_list
->head
= current
->next
;
2362 pre
->next
= current
->next
;
2363 if (current
->next
== NULL
)
2364 subset_list
->tail
= pre
;
2365 free ((void *) current
->name
);
2372 /* Add/Remove an extension to/from the subset list. This is used for
2373 the .option rvc or norvc, and .option arch directives. */
2376 riscv_update_subset (riscv_parse_subset_t
*rps
,
2379 const char *p
= str
;
2383 int major_version
= RISCV_UNKNOWN_VERSION
;
2384 int minor_version
= RISCV_UNKNOWN_VERSION
;
2386 bool removed
= false;
2389 case '+': removed
= false; break;
2390 case '-': removed
= true; break;
2392 riscv_release_subset_list (rps
->subset_list
);
2393 return riscv_parse_subset (rps
, p
);
2397 char *subset
= xstrdup (p
);
2399 const char *end_of_version
;
2400 /* Extract the whole prefixed extension by ','. */
2401 while (*q
!= '\0' && *q
!= ',')
2404 /* Look forward to the first letter which is not <major>p<minor>. */
2405 bool find_any_version
= false;
2406 bool find_minor_version
= false;
2407 size_t len
= q
- subset
;
2409 for (i
= len
; i
> 0; i
--)
2413 find_any_version
= true;
2414 else if (find_any_version
2415 && !find_minor_version
2417 && ISDIGIT (*(q
- 1)))
2418 find_minor_version
= true;
2425 /* Check if the end of extension is 'p' or not. If yes, then
2426 the second letter from the end cannot be number. */
2427 if (len
> 1 && *(q
- 1) == 'p' && ISDIGIT (*(q
- 2)))
2431 (_("invalid ISA extension ends with <number>p "
2432 "in .option arch `%s'"), str
);
2438 riscv_parsing_subset_version (q
, &major_version
, &minor_version
);
2440 if (end_of_version
== NULL
)
2446 if (strlen (subset
) == 0
2447 || (strlen (subset
) == 1
2448 && riscv_ext_order
[(*subset
- 'a')] == 0)
2449 || (strlen (subset
) > 1
2450 && rps
->check_unknown_prefixed_ext
2451 && !riscv_recognized_prefixed_ext (subset
)))
2454 (_("unknown ISA extension `%s' in .option arch `%s'"),
2460 if (strcmp (subset
, "i") == 0
2461 || strcmp (subset
, "e") == 0
2462 || strcmp (subset
, "g") == 0)
2465 (_("cannot + or - base extension `%s' in .option "
2466 "arch `%s'"), subset
, str
);
2472 riscv_remove_subset (rps
->subset_list
, subset
);
2474 riscv_parse_add_subset (rps
, subset
, major_version
, minor_version
, true);
2475 p
+= end_of_version
- subset
;
2478 while (*p
++ == ',');
2480 riscv_parse_add_implicit_subsets (rps
);
2481 return riscv_parse_check_conflicts (rps
);
2484 /* Check if the FEATURE subset is supported or not in the subset list.
2485 Return true if it is supported; Otherwise, return false. */
2488 riscv_subset_supports (riscv_parse_subset_t
*rps
,
2489 const char *feature
)
2491 struct riscv_subset_t
*subset
;
2492 return riscv_lookup_subset (rps
->subset_list
, feature
, &subset
);
2495 /* Each instuction is belonged to an instruction class INSN_CLASS_*.
2496 Call riscv_subset_supports to make sure if the instuction is valid. */
2499 riscv_multi_subset_supports (riscv_parse_subset_t
*rps
,
2500 enum riscv_insn_class insn_class
)
2505 return riscv_subset_supports (rps
, "i");
2506 case INSN_CLASS_ZICBOM
:
2507 return riscv_subset_supports (rps
, "zicbom");
2508 case INSN_CLASS_ZICBOP
:
2509 return riscv_subset_supports (rps
, "zicbop");
2510 case INSN_CLASS_ZICBOZ
:
2511 return riscv_subset_supports (rps
, "zicboz");
2512 case INSN_CLASS_ZICOND
:
2513 return riscv_subset_supports (rps
, "zicond");
2514 case INSN_CLASS_ZICSR
:
2515 return riscv_subset_supports (rps
, "zicsr");
2516 case INSN_CLASS_ZIFENCEI
:
2517 return riscv_subset_supports (rps
, "zifencei");
2518 case INSN_CLASS_ZIHINTNTL
:
2519 return riscv_subset_supports (rps
, "zihintntl");
2520 case INSN_CLASS_ZIHINTNTL_AND_C
:
2521 return (riscv_subset_supports (rps
, "zihintntl")
2522 && (riscv_subset_supports (rps
, "c")
2523 || riscv_subset_supports (rps
, "zca")));
2524 case INSN_CLASS_ZIHINTPAUSE
:
2525 return riscv_subset_supports (rps
, "zihintpause");
2527 return riscv_subset_supports (rps
, "m");
2528 case INSN_CLASS_ZMMUL
:
2529 return riscv_subset_supports (rps
, "zmmul");
2530 case INSN_CLASS_ZAAMO
:
2531 return riscv_subset_supports (rps
, "zaamo");
2532 case INSN_CLASS_ZABHA
:
2533 return riscv_subset_supports (rps
, "zabha");
2534 case INSN_CLASS_ZALRSC
:
2535 return riscv_subset_supports (rps
, "zalrsc");
2536 case INSN_CLASS_ZAWRS
:
2537 return riscv_subset_supports (rps
, "zawrs");
2539 return riscv_subset_supports (rps
, "f");
2541 return riscv_subset_supports (rps
, "d");
2543 return riscv_subset_supports (rps
, "q");
2545 return (riscv_subset_supports (rps
, "c")
2546 || riscv_subset_supports (rps
, "zca"));
2547 case INSN_CLASS_F_AND_C
:
2548 return (riscv_subset_supports (rps
, "f")
2549 && (riscv_subset_supports (rps
, "c")
2550 || riscv_subset_supports (rps
, "zcf")));
2551 case INSN_CLASS_D_AND_C
:
2552 return (riscv_subset_supports (rps
, "d")
2553 && (riscv_subset_supports (rps
, "c")
2554 || riscv_subset_supports (rps
, "zcd")));
2555 case INSN_CLASS_F_INX
:
2556 return (riscv_subset_supports (rps
, "f")
2557 || riscv_subset_supports (rps
, "zfinx"));
2558 case INSN_CLASS_D_INX
:
2559 return (riscv_subset_supports (rps
, "d")
2560 || riscv_subset_supports (rps
, "zdinx"));
2561 case INSN_CLASS_Q_INX
:
2562 return (riscv_subset_supports (rps
, "q")
2563 || riscv_subset_supports (rps
, "zqinx"));
2564 case INSN_CLASS_ZFH_INX
:
2565 return (riscv_subset_supports (rps
, "zfh")
2566 || riscv_subset_supports (rps
, "zhinx"));
2567 case INSN_CLASS_ZFHMIN
:
2568 return riscv_subset_supports (rps
, "zfhmin");
2569 case INSN_CLASS_ZFHMIN_INX
:
2570 return (riscv_subset_supports (rps
, "zfhmin")
2571 || riscv_subset_supports (rps
, "zhinxmin"));
2572 case INSN_CLASS_ZFHMIN_AND_D_INX
:
2573 return ((riscv_subset_supports (rps
, "zfhmin")
2574 && riscv_subset_supports (rps
, "d"))
2575 || (riscv_subset_supports (rps
, "zhinxmin")
2576 && riscv_subset_supports (rps
, "zdinx")));
2577 case INSN_CLASS_ZFHMIN_AND_Q_INX
:
2578 return ((riscv_subset_supports (rps
, "zfhmin")
2579 && riscv_subset_supports (rps
, "q"))
2580 || (riscv_subset_supports (rps
, "zhinxmin")
2581 && riscv_subset_supports (rps
, "zqinx")));
2582 case INSN_CLASS_ZFA
:
2583 return riscv_subset_supports (rps
, "zfa");
2584 case INSN_CLASS_D_AND_ZFA
:
2585 return riscv_subset_supports (rps
, "d")
2586 && riscv_subset_supports (rps
, "zfa");
2587 case INSN_CLASS_Q_AND_ZFA
:
2588 return riscv_subset_supports (rps
, "q")
2589 && riscv_subset_supports (rps
, "zfa");
2590 case INSN_CLASS_ZFH_AND_ZFA
:
2591 return riscv_subset_supports (rps
, "zfh")
2592 && riscv_subset_supports (rps
, "zfa");
2593 case INSN_CLASS_ZFH_OR_ZVFH_AND_ZFA
:
2594 return (riscv_subset_supports (rps
, "zfh")
2595 || riscv_subset_supports (rps
, "zvfh"))
2596 && riscv_subset_supports (rps
, "zfa");
2597 case INSN_CLASS_ZBA
:
2598 return riscv_subset_supports (rps
, "zba");
2599 case INSN_CLASS_ZBB
:
2600 return riscv_subset_supports (rps
, "zbb");
2601 case INSN_CLASS_ZBC
:
2602 return riscv_subset_supports (rps
, "zbc");
2603 case INSN_CLASS_ZBS
:
2604 return riscv_subset_supports (rps
, "zbs");
2605 case INSN_CLASS_ZBKB
:
2606 return riscv_subset_supports (rps
, "zbkb");
2607 case INSN_CLASS_ZBKC
:
2608 return riscv_subset_supports (rps
, "zbkc");
2609 case INSN_CLASS_ZBKX
:
2610 return riscv_subset_supports (rps
, "zbkx");
2611 case INSN_CLASS_ZBB_OR_ZBKB
:
2612 return (riscv_subset_supports (rps
, "zbb")
2613 || riscv_subset_supports (rps
, "zbkb"));
2614 case INSN_CLASS_ZBC_OR_ZBKC
:
2615 return (riscv_subset_supports (rps
, "zbc")
2616 || riscv_subset_supports (rps
, "zbkc"));
2617 case INSN_CLASS_ZKND
:
2618 return riscv_subset_supports (rps
, "zknd");
2619 case INSN_CLASS_ZKNE
:
2620 return riscv_subset_supports (rps
, "zkne");
2621 case INSN_CLASS_ZKNH
:
2622 return riscv_subset_supports (rps
, "zknh");
2623 case INSN_CLASS_ZKND_OR_ZKNE
:
2624 return (riscv_subset_supports (rps
, "zknd")
2625 || riscv_subset_supports (rps
, "zkne"));
2626 case INSN_CLASS_ZKSED
:
2627 return riscv_subset_supports (rps
, "zksed");
2628 case INSN_CLASS_ZKSH
:
2629 return riscv_subset_supports (rps
, "zksh");
2631 return (riscv_subset_supports (rps
, "v")
2632 || riscv_subset_supports (rps
, "zve64x")
2633 || riscv_subset_supports (rps
, "zve32x"));
2634 case INSN_CLASS_ZVEF
:
2635 return (riscv_subset_supports (rps
, "v")
2636 || riscv_subset_supports (rps
, "zve64d")
2637 || riscv_subset_supports (rps
, "zve64f")
2638 || riscv_subset_supports (rps
, "zve32f"));
2639 case INSN_CLASS_ZVBB
:
2640 return riscv_subset_supports (rps
, "zvbb");
2641 case INSN_CLASS_ZVBC
:
2642 return riscv_subset_supports (rps
, "zvbc");
2643 case INSN_CLASS_ZVKB
:
2644 return riscv_subset_supports (rps
, "zvkb");
2645 case INSN_CLASS_ZVKG
:
2646 return riscv_subset_supports (rps
, "zvkg");
2647 case INSN_CLASS_ZVKNED
:
2648 return riscv_subset_supports (rps
, "zvkned");
2649 case INSN_CLASS_ZVKNHA_OR_ZVKNHB
:
2650 return (riscv_subset_supports (rps
, "zvknha")
2651 || riscv_subset_supports (rps
, "zvknhb"));
2652 case INSN_CLASS_ZVKSED
:
2653 return riscv_subset_supports (rps
, "zvksed");
2654 case INSN_CLASS_ZVKSH
:
2655 return riscv_subset_supports (rps
, "zvksh");
2656 case INSN_CLASS_ZCB
:
2657 return riscv_subset_supports (rps
, "zcb");
2658 case INSN_CLASS_ZCB_AND_ZBB
:
2659 return (riscv_subset_supports (rps
, "zcb")
2660 && riscv_subset_supports (rps
, "zbb"));
2661 case INSN_CLASS_ZCB_AND_ZBA
:
2662 return (riscv_subset_supports (rps
, "zcb")
2663 && riscv_subset_supports (rps
, "zba"));
2664 case INSN_CLASS_ZCB_AND_ZMMUL
:
2665 return (riscv_subset_supports (rps
, "zcb")
2666 && riscv_subset_supports (rps
, "zmmul"));
2667 case INSN_CLASS_ZCMP
:
2668 return riscv_subset_supports (rps
, "zcmp");
2669 case INSN_CLASS_SVINVAL
:
2670 return riscv_subset_supports (rps
, "svinval");
2672 return riscv_subset_supports (rps
, "h");
2673 case INSN_CLASS_XCVMAC
:
2674 return riscv_subset_supports (rps
, "xcvmac");
2675 case INSN_CLASS_XCVALU
:
2676 return riscv_subset_supports (rps
, "xcvalu");
2677 case INSN_CLASS_XTHEADBA
:
2678 return riscv_subset_supports (rps
, "xtheadba");
2679 case INSN_CLASS_XTHEADBB
:
2680 return riscv_subset_supports (rps
, "xtheadbb");
2681 case INSN_CLASS_XTHEADBS
:
2682 return riscv_subset_supports (rps
, "xtheadbs");
2683 case INSN_CLASS_XTHEADCMO
:
2684 return riscv_subset_supports (rps
, "xtheadcmo");
2685 case INSN_CLASS_XTHEADCONDMOV
:
2686 return riscv_subset_supports (rps
, "xtheadcondmov");
2687 case INSN_CLASS_XTHEADFMEMIDX
:
2688 return riscv_subset_supports (rps
, "xtheadfmemidx");
2689 case INSN_CLASS_XTHEADFMV
:
2690 return riscv_subset_supports (rps
, "xtheadfmv");
2691 case INSN_CLASS_XTHEADINT
:
2692 return riscv_subset_supports (rps
, "xtheadint");
2693 case INSN_CLASS_XTHEADMAC
:
2694 return riscv_subset_supports (rps
, "xtheadmac");
2695 case INSN_CLASS_XTHEADMEMIDX
:
2696 return riscv_subset_supports (rps
, "xtheadmemidx");
2697 case INSN_CLASS_XTHEADMEMPAIR
:
2698 return riscv_subset_supports (rps
, "xtheadmempair");
2699 case INSN_CLASS_XTHEADSYNC
:
2700 return riscv_subset_supports (rps
, "xtheadsync");
2701 case INSN_CLASS_XTHEADVECTOR
:
2702 return riscv_subset_supports (rps
, "xtheadvector");
2703 case INSN_CLASS_XTHEADZVAMO
:
2704 return riscv_subset_supports (rps
, "xtheadzvamo");
2705 case INSN_CLASS_XVENTANACONDOPS
:
2706 return riscv_subset_supports (rps
, "xventanacondops");
2707 case INSN_CLASS_XSFVCP
:
2708 return riscv_subset_supports (rps
, "xsfvcp");
2711 (_("internal: unreachable INSN_CLASS_*"));
2716 /* Each instuction is belonged to an instruction class INSN_CLASS_*.
2717 Call riscv_subset_supports_ext to determine the missing extension. */
2720 riscv_multi_subset_supports_ext (riscv_parse_subset_t
*rps
,
2721 enum riscv_insn_class insn_class
)
2727 case INSN_CLASS_ZICBOM
:
2729 case INSN_CLASS_ZICBOP
:
2731 case INSN_CLASS_ZICBOZ
:
2733 case INSN_CLASS_ZICOND
:
2735 case INSN_CLASS_ZICSR
:
2737 case INSN_CLASS_ZIFENCEI
:
2739 case INSN_CLASS_ZIHINTNTL
:
2741 case INSN_CLASS_ZIHINTNTL_AND_C
:
2742 if (!riscv_subset_supports (rps
, "zihintntl"))
2744 if (!riscv_subset_supports (rps
, "c")
2745 && !riscv_subset_supports (rps
, "zca"))
2746 return _("zihintntl' and `c', or `zihintntl' and `zca");
2751 return _("c' or `zca");
2752 case INSN_CLASS_ZIHINTPAUSE
:
2753 return "zihintpause";
2756 case INSN_CLASS_ZMMUL
:
2757 return _ ("m' or `zmmul");
2758 case INSN_CLASS_ZAAMO
:
2760 case INSN_CLASS_ZABHA
:
2762 case INSN_CLASS_ZALRSC
:
2764 case INSN_CLASS_ZAWRS
:
2773 return _("c' or `zca");
2774 case INSN_CLASS_F_AND_C
:
2775 if (!riscv_subset_supports (rps
, "f"))
2777 if (!riscv_subset_supports (rps
, "c")
2778 && !riscv_subset_supports (rps
, "zcf"))
2779 return _("f' and `c', or `f' and `zcf");
2784 return _("c' or `zcf");
2785 case INSN_CLASS_D_AND_C
:
2786 if (!riscv_subset_supports (rps
, "d"))
2788 if (!riscv_subset_supports (rps
, "c")
2789 && !riscv_subset_supports (rps
, "zcd"))
2790 return _("d' and `c', or `d' and `zcd");
2795 return _("c' or `zcd");
2796 case INSN_CLASS_F_INX
:
2797 return _("f' or `zfinx");
2798 case INSN_CLASS_D_INX
:
2799 return _("d' or `zdinx");
2800 case INSN_CLASS_Q_INX
:
2801 return _("q' or `zqinx");
2802 case INSN_CLASS_ZFH_INX
:
2803 return _("zfh' or `zhinx");
2804 case INSN_CLASS_ZFHMIN
:
2806 case INSN_CLASS_ZFHMIN_INX
:
2807 return _("zfhmin' or `zhinxmin");
2808 case INSN_CLASS_ZFHMIN_AND_D_INX
:
2809 if (riscv_subset_supports (rps
, "zfhmin"))
2811 else if (riscv_subset_supports (rps
, "d"))
2813 else if (riscv_subset_supports (rps
, "zhinxmin"))
2815 else if (riscv_subset_supports (rps
, "zdinx"))
2818 return _("zfhmin' and `d', or `zhinxmin' and `zdinx");
2819 case INSN_CLASS_ZFHMIN_AND_Q_INX
:
2820 if (riscv_subset_supports (rps
, "zfhmin"))
2822 else if (riscv_subset_supports (rps
, "q"))
2824 else if (riscv_subset_supports (rps
, "zhinxmin"))
2826 else if (riscv_subset_supports (rps
, "zqinx"))
2829 return _("zfhmin' and `q', or `zhinxmin' and `zqinx");
2830 case INSN_CLASS_ZFA
:
2832 case INSN_CLASS_D_AND_ZFA
:
2833 if (!riscv_subset_supports (rps
, "d")
2834 && !riscv_subset_supports (rps
, "zfa"))
2835 return _("d' and `zfa");
2836 else if (!riscv_subset_supports (rps
, "d"))
2840 case INSN_CLASS_Q_AND_ZFA
:
2841 if (!riscv_subset_supports (rps
, "q")
2842 && !riscv_subset_supports (rps
, "zfa"))
2843 return _("q' and `zfa");
2844 else if (!riscv_subset_supports (rps
, "q"))
2848 case INSN_CLASS_ZFH_AND_ZFA
:
2849 if (!riscv_subset_supports (rps
, "zfh")
2850 && !riscv_subset_supports (rps
, "zfa"))
2851 return _("zfh' and `zfa");
2852 else if (!riscv_subset_supports (rps
, "zfh"))
2856 case INSN_CLASS_ZFH_OR_ZVFH_AND_ZFA
:
2857 if (!riscv_subset_supports (rps
, "zfa"))
2859 if (!riscv_subset_supports (rps
, "zfh")
2860 && !riscv_subset_supports (rps
, "zvfh"))
2861 return _("zfh' and `zfa', or `zvfh' and `zfa");
2866 return _("zfh' or `zvfh");
2867 case INSN_CLASS_ZBA
:
2869 case INSN_CLASS_ZBB
:
2871 case INSN_CLASS_ZBC
:
2873 case INSN_CLASS_ZBS
:
2875 case INSN_CLASS_ZBKB
:
2877 case INSN_CLASS_ZBKC
:
2879 case INSN_CLASS_ZBKX
:
2881 case INSN_CLASS_ZBB_OR_ZBKB
:
2882 return _("zbb' or `zbkb");
2883 case INSN_CLASS_ZBC_OR_ZBKC
:
2884 return _("zbc' or `zbkc");
2885 case INSN_CLASS_ZKND
:
2887 case INSN_CLASS_ZKNE
:
2889 case INSN_CLASS_ZKNH
:
2891 case INSN_CLASS_ZKND_OR_ZKNE
:
2892 return _("zknd' or `zkne");
2893 case INSN_CLASS_ZKSED
:
2895 case INSN_CLASS_ZKSH
:
2898 return _("v' or `zve64x' or `zve32x");
2899 case INSN_CLASS_ZVEF
:
2900 return _("v' or `zve64d' or `zve64f' or `zve32f");
2901 case INSN_CLASS_ZVBB
:
2903 case INSN_CLASS_ZVBC
:
2905 case INSN_CLASS_ZVKB
:
2907 case INSN_CLASS_ZVKG
:
2909 case INSN_CLASS_ZVKNED
:
2911 case INSN_CLASS_ZVKNHA_OR_ZVKNHB
:
2912 return _("zvknha' or `zvknhb");
2913 case INSN_CLASS_ZVKSED
:
2915 case INSN_CLASS_ZVKSH
:
2917 case INSN_CLASS_ZCB
:
2919 case INSN_CLASS_ZCB_AND_ZBA
:
2920 return _("zcb' and `zba");
2921 case INSN_CLASS_ZCB_AND_ZBB
:
2922 return _("zcb' and `zbb");
2923 case INSN_CLASS_ZCB_AND_ZMMUL
:
2924 return _("zcb' and `zmmul', or `zcb' and `m");
2925 case INSN_CLASS_ZCMP
:
2927 case INSN_CLASS_SVINVAL
:
2931 case INSN_CLASS_XCVMAC
:
2933 case INSN_CLASS_XCVALU
:
2935 case INSN_CLASS_XTHEADBA
:
2937 case INSN_CLASS_XTHEADBB
:
2939 case INSN_CLASS_XTHEADBS
:
2941 case INSN_CLASS_XTHEADCMO
:
2943 case INSN_CLASS_XTHEADCONDMOV
:
2944 return "xtheadcondmov";
2945 case INSN_CLASS_XTHEADFMEMIDX
:
2946 return "xtheadfmemidx";
2947 case INSN_CLASS_XTHEADFMV
:
2949 case INSN_CLASS_XTHEADINT
:
2951 case INSN_CLASS_XTHEADMAC
:
2953 case INSN_CLASS_XTHEADMEMIDX
:
2954 return "xtheadmemidx";
2955 case INSN_CLASS_XTHEADMEMPAIR
:
2956 return "xtheadmempair";
2957 case INSN_CLASS_XTHEADSYNC
:
2958 return "xtheadsync";
2959 case INSN_CLASS_XTHEADVECTOR
:
2960 return "xtheadvector";
2961 case INSN_CLASS_XTHEADZVAMO
:
2962 return "xtheadzvamo";
2965 (_("internal: unreachable INSN_CLASS_*"));
2970 /* Print supported extensions with versions if -march=help. */
2973 riscv_print_extensions (void)
2975 /* Record the previous printed extension.
2976 Print the current one if they are not the same. */
2977 const struct riscv_supported_ext
*cur
= NULL
, *prev
= NULL
;
2980 printf ("All available -march extensions for RISC-V:");
2982 for (i
= 0; riscv_all_supported_ext
[i
] != NULL
; i
++)
2984 const struct riscv_supported_ext
*exts
= riscv_all_supported_ext
[i
];
2986 for (j
= 0; exts
[j
].name
!= NULL
; j
++)
2989 /* Unclear version information, skip. */
2990 if (cur
->isa_spec_class
== ISA_SPEC_CLASS_NONE
2991 || cur
->major_version
== RISCV_UNKNOWN_VERSION
2992 || cur
->minor_version
== RISCV_UNKNOWN_VERSION
)
2995 /* Same extension. */
2996 if (prev
&& strcmp (prev
->name
, cur
->name
) == 0)
2998 /* Same version, skip. */
2999 if (prev
->major_version
== cur
->major_version
3000 && prev
->minor_version
== cur
->minor_version
)
3002 /* Different version, print version with comma. */
3004 printf (", %d.%d", cur
->major_version
, cur
->minor_version
);
3006 /* Different extension, print extension and version with newline. */
3008 printf ("\n\t%-40s%d.%d", cur
->name
, cur
->major_version
,
3009 cur
->minor_version
);