1 /* RISC-V-specific support for ELF.
2 Copyright (C) 2011-2025 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 implicit extensions for the SUBSET. */
1151 check_implicit_always (riscv_subset_t
*subset ATTRIBUTE_UNUSED
)
1156 /* Add implicit extensions only when the version of SUBSET less than 2.1. */
1159 check_implicit_for_i (riscv_subset_t
*subset
)
1161 return (subset
->major_version
< 2
1162 || (subset
->major_version
== 2
1163 && subset
->minor_version
< 1));
1166 /* Record all implicit information for the subsets. */
1167 struct riscv_implicit_subset
1170 const char *implicit_exts
;
1171 /* A function to determine if we need to add the implicit subsets. */
1172 bool (*check_func
) (riscv_subset_t
*);
1174 /* Please added in order since this table is only run once time. */
1175 static struct riscv_implicit_subset riscv_implicit_subsets
[] =
1177 {"g", "+i,+m,+a,+f,+d,+zicsr,+zifencei", check_implicit_always
},
1178 {"e", "+i", check_implicit_always
},
1179 {"i", "+zicsr,+zifencei", check_implicit_for_i
},
1180 {"zicntr", "+zicsr", check_implicit_always
},
1181 {"zihpm", "+zicsr", check_implicit_always
},
1183 {"m", "+zmmul", check_implicit_always
},
1185 {"zabha", "+zaamo", check_implicit_always
},
1186 {"zacas", "+zaamo", check_implicit_always
},
1187 {"a", "+zaamo,+zalrsc", check_implicit_always
},
1189 {"xsfvcp", "+zve32x", check_implicit_always
},
1190 {"xsfvqmaccqoq", "+zve32x,+zvl256b", check_implicit_always
},
1191 {"xsfvqmaccdod", "+zve32x,+zvl128b", check_implicit_always
},
1192 {"xsfvfnrclipxfqf", "+zve32f", check_implicit_always
},
1194 {"v", "+zve64d,+zvl128b", check_implicit_always
},
1195 {"zvfh", "+zvfhmin,+zfhmin", check_implicit_always
},
1196 {"zvfhmin", "+zve32f", check_implicit_always
},
1197 {"zvfbfwma", "+zve32f,+zfbfmin", check_implicit_always
},
1198 {"zvfbfmin", "+zve32f", check_implicit_always
},
1199 {"zve64d", "+d,+zve64f", check_implicit_always
},
1200 {"zve64f", "+zve32f,+zve64x,+zvl64b", check_implicit_always
},
1201 {"zve32f", "+f,+zve32x,+zvl32b", check_implicit_always
},
1202 {"zve64x", "+zve32x,+zvl64b", check_implicit_always
},
1203 {"zve32x", "+zvl32b,+zicsr", check_implicit_always
},
1204 {"zvl65536b", "+zvl32768b", check_implicit_always
},
1205 {"zvl32768b", "+zvl16384b", check_implicit_always
},
1206 {"zvl16384b", "+zvl8192b", check_implicit_always
},
1207 {"zvl8192b", "+zvl4096b", check_implicit_always
},
1208 {"zvl4096b", "+zvl2048b", check_implicit_always
},
1209 {"zvl2048b", "+zvl1024b", check_implicit_always
},
1210 {"zvl1024b", "+zvl512b", check_implicit_always
},
1211 {"zvl512b", "+zvl256b", check_implicit_always
},
1212 {"zvl256b", "+zvl128b", check_implicit_always
},
1213 {"zvl128b", "+zvl64b", check_implicit_always
},
1214 {"zvl64b", "+zvl32b", check_implicit_always
},
1216 {"zcb", "+zca", check_implicit_always
},
1217 {"zcd", "+d,+zca", check_implicit_always
},
1218 {"zcf", "+f,+zca", check_implicit_always
},
1219 {"zcmp", "+zca", check_implicit_always
},
1220 {"zcmop", "+zca", check_implicit_always
},
1221 {"zcmt", "+zca,+zicsr", check_implicit_always
},
1223 {"zicfilp", "+zicsr", check_implicit_always
},
1224 {"zicfiss", "+zimop,+zicsr", check_implicit_always
},
1226 {"shcounterenw", "+h", check_implicit_always
},
1227 {"shgatpa", "+h", check_implicit_always
},
1228 {"shtvala", "+h", check_implicit_always
},
1229 {"shvsatpa", "+h", check_implicit_always
},
1230 {"shvstvala", "+h", check_implicit_always
},
1231 {"shvstvecd", "+h", check_implicit_always
},
1232 {"h", "+zicsr", check_implicit_always
},
1233 {"zhinx", "+zhinxmin", check_implicit_always
},
1234 {"zhinxmin", "+zfinx", check_implicit_always
},
1236 {"q", "+d", check_implicit_always
},
1237 {"zqinx", "+zdinx", check_implicit_always
},
1239 {"d", "+f", check_implicit_always
},
1240 {"zdinx", "+zfinx", check_implicit_always
},
1242 {"zfa", "+f", check_implicit_always
},
1243 {"zfbfmin", "+zfhmin", check_implicit_always
},
1244 {"zfh", "+zfhmin", check_implicit_always
},
1245 {"zfhmin", "+f", check_implicit_always
},
1246 {"zfinx", "+zicsr", check_implicit_always
},
1247 {"f", "+zicsr", check_implicit_always
},
1249 {"b", "+zba,+zbb,+zbs", check_implicit_always
},
1251 {"zk", "+zkn,+zkr,+zkt", check_implicit_always
},
1252 {"zkn", "+zbkb,+zbkc,+zbkx,+zkne,+zknd,+zknh", check_implicit_always
},
1253 {"zks", "+zbkb,+zbkc,+zbkx,+zksed,+zksh", check_implicit_always
},
1254 {"zvbb", "+zvkb", check_implicit_always
},
1255 {"zvkng", "+zvkn,+zvkg", check_implicit_always
},
1256 {"zvknc", "+zvkn,+zvbc", check_implicit_always
},
1257 {"zvkn", "+zvkned,+zvknhb,+zvkb,+zvkt", check_implicit_always
},
1258 {"zvksg", "+zvks,+zvkg", check_implicit_always
},
1259 {"zvksc", "+zvks,+zvbc", check_implicit_always
},
1260 {"zvks", "+zvksed,+zvksh,+zvkb,+zvkt", check_implicit_always
},
1262 {"smaia", "+ssaia", check_implicit_always
},
1263 {"smcsrind", "+sscsrind", check_implicit_always
},
1264 {"smcntrpmf", "+zicsr", check_implicit_always
},
1265 {"smctr", "+zicsr", check_implicit_always
},
1266 {"smstateen", "+ssstateen", check_implicit_always
},
1267 {"smepmp", "+zicsr", check_implicit_always
},
1268 {"smdbltrp", "+zicsr", check_implicit_always
},
1270 {"ssaia", "+zicsr", check_implicit_always
},
1271 {"sscsrind", "+zicsr", check_implicit_always
},
1272 {"sscofpmf", "+zicsr", check_implicit_always
},
1273 {"sscounterenw", "+zicsr", check_implicit_always
},
1274 {"ssctr", "+zicsr", check_implicit_always
},
1275 {"ssstateen", "+zicsr", check_implicit_always
},
1276 {"sstc", "+zicsr", check_implicit_always
},
1277 {"sstvala", "+zicsr", check_implicit_always
},
1278 {"sstvecd", "+zicsr", check_implicit_always
},
1279 {"ssu64xl", "+zicsr", check_implicit_always
},
1280 {"ssdbltrp", "+zicsr", check_implicit_always
},
1282 {"svade", "+zicsr", check_implicit_always
},
1283 {"svadu", "+zicsr", check_implicit_always
},
1284 {"svbare", "+zicsr", check_implicit_always
},
1288 /* For default_enable field, decide if the extension should
1289 be enbaled by default. */
1291 #define EXT_DEFAULT 0x1
1293 /* List all extensions that binutils should know about. */
1295 struct riscv_supported_ext
1298 enum riscv_spec_class isa_spec_class
;
1301 unsigned long default_enable
;
1304 /* The standard extensions must be added in canonical order. */
1306 static struct riscv_supported_ext riscv_supported_std_ext
[] =
1308 {"e", ISA_SPEC_CLASS_20191213
, 1, 9, 0 },
1309 {"e", ISA_SPEC_CLASS_20190608
, 1, 9, 0 },
1310 {"e", ISA_SPEC_CLASS_2P2
, 1, 9, 0 },
1311 {"i", ISA_SPEC_CLASS_20191213
, 2, 1, 0 },
1312 {"i", ISA_SPEC_CLASS_20190608
, 2, 1, 0 },
1313 {"i", ISA_SPEC_CLASS_2P2
, 2, 0, 0 },
1314 /* The g is a special case which we don't want to output it,
1315 but still need it when adding implicit extensions. */
1316 {"g", ISA_SPEC_CLASS_NONE
, RISCV_UNKNOWN_VERSION
, RISCV_UNKNOWN_VERSION
, EXT_DEFAULT
},
1317 {"m", ISA_SPEC_CLASS_20191213
, 2, 0, 0 },
1318 {"m", ISA_SPEC_CLASS_20190608
, 2, 0, 0 },
1319 {"m", ISA_SPEC_CLASS_2P2
, 2, 0, 0 },
1320 {"a", ISA_SPEC_CLASS_20191213
, 2, 1, 0 },
1321 {"a", ISA_SPEC_CLASS_20190608
, 2, 0, 0 },
1322 {"a", ISA_SPEC_CLASS_2P2
, 2, 0, 0 },
1323 {"f", ISA_SPEC_CLASS_20191213
, 2, 2, 0 },
1324 {"f", ISA_SPEC_CLASS_20190608
, 2, 2, 0 },
1325 {"f", ISA_SPEC_CLASS_2P2
, 2, 0, 0 },
1326 {"d", ISA_SPEC_CLASS_20191213
, 2, 2, 0 },
1327 {"d", ISA_SPEC_CLASS_20190608
, 2, 2, 0 },
1328 {"d", ISA_SPEC_CLASS_2P2
, 2, 0, 0 },
1329 {"q", ISA_SPEC_CLASS_20191213
, 2, 2, 0 },
1330 {"q", ISA_SPEC_CLASS_20190608
, 2, 2, 0 },
1331 {"q", ISA_SPEC_CLASS_2P2
, 2, 0, 0 },
1332 {"c", ISA_SPEC_CLASS_20191213
, 2, 0, 0 },
1333 {"c", ISA_SPEC_CLASS_20190608
, 2, 0, 0 },
1334 {"c", ISA_SPEC_CLASS_2P2
, 2, 0, 0 },
1335 {"b", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1336 {"v", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1337 {"h", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1341 static struct riscv_supported_ext riscv_supported_std_z_ext
[] =
1343 {"zic64b", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1344 {"ziccamoa", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1345 {"ziccif", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1346 {"zicclsm", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1347 {"ziccrse", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1348 {"zicbom", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1349 {"zicbop", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1350 {"zicboz", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1351 {"zicond", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1352 {"zicntr", ISA_SPEC_CLASS_DRAFT
, 2, 0, 0 },
1353 {"zicsr", ISA_SPEC_CLASS_20191213
, 2, 0, 0 },
1354 {"zicsr", ISA_SPEC_CLASS_20190608
, 2, 0, 0 },
1355 {"zifencei", ISA_SPEC_CLASS_20191213
, 2, 0, 0 },
1356 {"zifencei", ISA_SPEC_CLASS_20190608
, 2, 0, 0 },
1357 {"zihintntl", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1358 {"zihintpause", ISA_SPEC_CLASS_DRAFT
, 2, 0, 0 },
1359 {"zihpm", ISA_SPEC_CLASS_DRAFT
, 2, 0, 0 },
1360 {"zimop", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1361 {"zicfiss", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1362 {"zicfilp", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1363 {"zmmul", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1364 {"za64rs", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1365 {"za128rs", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1366 {"zaamo", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1367 {"zabha", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1368 {"zacas", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1369 {"zalrsc", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1370 {"zawrs", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1371 {"zfbfmin", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1372 {"zfa", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1373 {"zfh", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1374 {"zfhmin", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1375 {"zfinx", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1376 {"zdinx", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1377 {"zqinx", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1378 {"zhinx", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1379 {"zhinxmin", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1380 {"zbb", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1381 {"zba", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1382 {"zbc", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1383 {"zbs", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1384 {"zbkb", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1385 {"zbkc", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1386 {"zbkx", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1387 {"zk", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1388 {"zkn", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1389 {"zknd", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1390 {"zkne", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1391 {"zknh", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1392 {"zkr", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1393 {"zks", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1394 {"zksed", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1395 {"zksh", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1396 {"zkt", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1397 {"zve32x", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1398 {"zve32f", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1399 {"zve64x", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1400 {"zve64f", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1401 {"zve64d", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1402 {"zvbb", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1403 {"zvbc", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1404 {"zvfbfmin", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1405 {"zvfbfwma", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1406 {"zvfh", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1407 {"zvfhmin", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1408 {"zvkb", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1409 {"zvkg", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1410 {"zvkn", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1411 {"zvkng", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1412 {"zvknc", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1413 {"zvkned", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1414 {"zvknha", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1415 {"zvknhb", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1416 {"zvksed", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1417 {"zvksh", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1418 {"zvks", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1419 {"zvksg", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1420 {"zvksc", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1421 {"zvkt", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1422 {"zvl32b", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1423 {"zvl64b", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1424 {"zvl128b", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1425 {"zvl256b", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1426 {"zvl512b", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1427 {"zvl1024b", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1428 {"zvl2048b", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1429 {"zvl4096b", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1430 {"zvl8192b", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1431 {"zvl16384b", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1432 {"zvl32768b", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1433 {"zvl65536b", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1434 {"ztso", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1435 {"zca", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1436 {"zcb", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1437 {"zcf", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1438 {"zcd", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1439 {"zcmop", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1440 {"zcmp", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1441 {"zcmt", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1445 static struct riscv_supported_ext riscv_supported_std_s_ext
[] =
1447 {"shcounterenw", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1448 {"shgatpa", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1449 {"shtvala", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1450 {"shvsatpa", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1451 {"shvstvala", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1452 {"shvstvecd", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1453 {"smaia", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1454 {"smcsrind", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1455 {"smcntrpmf", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1456 {"smctr", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1457 {"smepmp", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1458 {"smrnmi", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1459 {"smstateen", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1460 {"smdbltrp", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1461 {"ssaia", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1462 {"ssccptr", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1463 {"sscsrind", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1464 {"sscofpmf", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1465 {"sscounterenw", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1466 {"ssctr", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1467 {"ssstateen", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1468 {"sstc", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1469 {"sstvala", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1470 {"sstvecd", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1471 {"ssu64xl", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1472 {"ssdbltrp", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1473 {"svade", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1474 {"svadu", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1475 {"svbare", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1476 {"svinval", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1477 {"svnapot", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1478 {"svpbmt", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1482 static struct riscv_supported_ext riscv_supported_std_zxm_ext
[] =
1487 static struct riscv_supported_ext riscv_supported_vendor_x_ext
[] =
1489 {"xcvalu", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1490 {"xcvbi", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1491 {"xcvbitmanip", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1492 {"xcvelw", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1493 {"xcvmac", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1494 {"xcvmem", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1495 {"xcvsimd", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1496 {"xtheadba", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1497 {"xtheadbb", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1498 {"xtheadbs", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1499 {"xtheadcmo", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1500 {"xtheadcondmov", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1501 {"xtheadfmemidx", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1502 {"xtheadfmv", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1503 {"xtheadint", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1504 {"xtheadmac", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1505 {"xtheadmemidx", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1506 {"xtheadmempair", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1507 {"xtheadsync", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1508 {"xtheadvector", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1509 {"xtheadzvamo", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1510 {"xventanacondops", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1511 {"xsfvcp", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1512 {"xsfcease", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1513 {"xsfvqmaccqoq", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0},
1514 {"xsfvqmaccdod", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0},
1515 {"xsfvfnrclipxfqf", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0},
1519 const struct riscv_supported_ext
*riscv_all_supported_ext
[] =
1521 riscv_supported_std_ext
,
1522 riscv_supported_std_z_ext
,
1523 riscv_supported_std_s_ext
,
1524 riscv_supported_std_zxm_ext
,
1525 riscv_supported_vendor_x_ext
,
1529 /* ISA extension prefixed name class. Must define them in parsing order. */
1530 enum riscv_prefix_ext_class
1539 /* Record the strings of the prefixed extensions, and their corresponding
1540 classes. The more letters of the prefix string, the more forward it must
1541 be defined. Otherwise, the riscv_get_prefix_class will map it to the
1543 struct riscv_parse_prefix_config
1545 /* Class of the extension. */
1546 enum riscv_prefix_ext_class
class;
1548 /* Prefix string for error printing and internal parser usage. */
1551 static const struct riscv_parse_prefix_config parse_config
[] =
1553 {RV_ISA_CLASS_ZXM
, "zxm"},
1554 {RV_ISA_CLASS_Z
, "z"},
1555 {RV_ISA_CLASS_S
, "s"},
1556 {RV_ISA_CLASS_X
, "x"},
1557 {RV_ISA_CLASS_SINGLE
, NULL
}
1560 /* Get the prefixed name class for the extensions, the class also
1561 means the order of the prefixed extensions. */
1563 static enum riscv_prefix_ext_class
1564 riscv_get_prefix_class (const char *arch
)
1567 while (parse_config
[i
].class != RV_ISA_CLASS_SINGLE
)
1569 if (strncmp (arch
, parse_config
[i
].prefix
,
1570 strlen (parse_config
[i
].prefix
)) == 0)
1571 return parse_config
[i
].class;
1574 return RV_ISA_CLASS_SINGLE
;
1577 /* Check KNOWN_EXTS to see if the EXT is supported. */
1580 riscv_known_prefixed_ext (const char *ext
,
1581 struct riscv_supported_ext
*known_exts
)
1584 for (i
= 0; known_exts
[i
].name
!= NULL
; ++i
)
1585 if (strcmp (ext
, known_exts
[i
].name
) == 0)
1590 /* Check whether the prefixed extension is recognized or not. Return
1591 true if recognized, otehrwise return false. */
1594 riscv_recognized_prefixed_ext (const char *ext
)
1596 enum riscv_prefix_ext_class
class = riscv_get_prefix_class (ext
);
1599 case RV_ISA_CLASS_Z
:
1600 return riscv_known_prefixed_ext (ext
, riscv_supported_std_z_ext
);
1601 case RV_ISA_CLASS_ZXM
:
1602 return riscv_known_prefixed_ext (ext
, riscv_supported_std_zxm_ext
);
1603 case RV_ISA_CLASS_S
:
1604 return riscv_known_prefixed_ext (ext
, riscv_supported_std_s_ext
);
1605 case RV_ISA_CLASS_X
:
1606 /* Only the single x is unrecognized. */
1607 if (strcmp (ext
, "x") != 0)
1615 /* Canonical order for single letter extensions. */
1616 static const char riscv_ext_canonical_order
[] = "eigmafdqlcbkjtpvnh";
1618 /* Array is used to compare the orders of standard extensions quickly. */
1619 static int riscv_ext_order
[26] = {0};
1621 /* Init the riscv_ext_order array. */
1624 riscv_init_ext_order (void)
1626 static bool inited
= false;
1630 /* The orders of all standard extensions are positive. */
1633 for (const char *ext
= &riscv_ext_canonical_order
[0]; *ext
; ++ext
)
1634 riscv_ext_order
[(*ext
- 'a')] = order
++;
1636 /* Some of the prefixed keyword are not single letter, so we set
1637 their prefixed orders in the riscv_compare_subsets directly,
1638 not through the riscv_ext_order. */
1643 /* Similar to the strcmp. It returns an integer less than, equal to,
1644 or greater than zero if `subset2` is found, respectively, to be less
1645 than, to match, or be greater than `subset1`.
1648 Zero: Preserved keywords.
1649 Positive number: Standard extensions.
1650 Negative number: Prefixed keywords. */
1653 riscv_compare_subsets (const char *subset1
, const char *subset2
)
1655 int order1
= riscv_ext_order
[(*subset1
- 'a')];
1656 int order2
= riscv_ext_order
[(*subset2
- 'a')];
1658 /* Compare the standard extension first. */
1659 if (order1
> 0 && order2
> 0)
1660 return order1
- order2
;
1662 /* Set the prefixed orders to negative numbers. */
1663 enum riscv_prefix_ext_class class1
= riscv_get_prefix_class (subset1
);
1664 enum riscv_prefix_ext_class class2
= riscv_get_prefix_class (subset2
);
1666 if (class1
!= RV_ISA_CLASS_SINGLE
)
1667 order1
= - (int) class1
;
1668 if (class2
!= RV_ISA_CLASS_SINGLE
)
1669 order2
= - (int) class2
;
1671 if (order1
== order2
)
1673 /* Compare the standard addition z extensions. */
1674 if (class1
== RV_ISA_CLASS_Z
)
1676 order1
= riscv_ext_order
[(*++subset1
- 'a')];
1677 order2
= riscv_ext_order
[(*++subset2
- 'a')];
1678 if (order1
!= order2
)
1679 return order1
- order2
;
1681 return strcasecmp (++subset1
, ++subset2
);
1684 return order2
- order1
;
1687 /* Find subset in the list. Return TRUE and set `current` to the subset
1688 if it is found. Otherwise, return FALSE and set `current` to the place
1689 where we should insert the subset. However, return FALSE with the NULL
1690 `current` means we should insert the subset at the head of subset list,
1694 riscv_lookup_subset (const riscv_subset_list_t
*subset_list
,
1696 riscv_subset_t
**current
)
1698 riscv_subset_t
*s
, *pre_s
= NULL
;
1700 /* If the subset is added in order, then just add it at the tail. */
1701 if (subset_list
->tail
!= NULL
1702 && riscv_compare_subsets (subset_list
->tail
->name
, subset
) < 0)
1704 *current
= subset_list
->tail
;
1708 for (s
= subset_list
->head
;
1710 pre_s
= s
, s
= s
->next
)
1712 int cmp
= riscv_compare_subsets (s
->name
, subset
);
1726 /* Add the extension to the subset list. Search the
1727 list first, and then find the right place to add. */
1730 riscv_add_subset (riscv_subset_list_t
*subset_list
,
1735 riscv_subset_t
*current
, *new;
1737 if (riscv_lookup_subset (subset_list
, subset
, ¤t
))
1740 new = xmalloc (sizeof *new);
1741 new->name
= xstrdup (subset
);
1742 new->major_version
= major
;
1743 new->minor_version
= minor
;
1746 if (current
!= NULL
)
1748 new->next
= current
->next
;
1749 current
->next
= new;
1753 new->next
= subset_list
->head
;
1754 subset_list
->head
= new;
1757 if (new->next
== NULL
)
1758 subset_list
->tail
= new;
1761 /* Get the default versions from the riscv_supported_*ext tables. */
1764 riscv_get_default_ext_version (enum riscv_spec_class
*default_isa_spec
,
1770 || default_isa_spec
== NULL
1771 || *default_isa_spec
== ISA_SPEC_CLASS_NONE
)
1774 struct riscv_supported_ext
*table
= NULL
;
1775 enum riscv_prefix_ext_class
class = riscv_get_prefix_class (name
);
1778 case RV_ISA_CLASS_ZXM
: table
= riscv_supported_std_zxm_ext
; break;
1779 case RV_ISA_CLASS_Z
: table
= riscv_supported_std_z_ext
; break;
1780 case RV_ISA_CLASS_S
: table
= riscv_supported_std_s_ext
; break;
1781 case RV_ISA_CLASS_X
: table
= riscv_supported_vendor_x_ext
; break;
1783 table
= riscv_supported_std_ext
;
1787 while (table
!= NULL
&& table
[i
].name
!= NULL
)
1789 if (strcmp (table
[i
].name
, name
) == 0
1790 && (table
[i
].isa_spec_class
== ISA_SPEC_CLASS_DRAFT
1791 || table
[i
].isa_spec_class
== *default_isa_spec
))
1793 *major_version
= table
[i
].major_version
;
1794 *minor_version
= table
[i
].minor_version
;
1801 /* Find the default versions for the extension before adding them to
1802 the subset list, if their versions are RISCV_UNKNOWN_VERSION.
1803 Afterwards, report errors if we can not find their default versions. */
1806 riscv_parse_add_subset (riscv_parse_subset_t
*rps
,
1812 int major_version
= major
;
1813 int minor_version
= minor
;
1815 if (major_version
== RISCV_UNKNOWN_VERSION
1816 || minor_version
== RISCV_UNKNOWN_VERSION
)
1817 riscv_get_default_ext_version (rps
->isa_spec
, subset
,
1818 &major_version
, &minor_version
);
1820 /* We don't care the versions of the implicit extensions. */
1822 && (major_version
== RISCV_UNKNOWN_VERSION
1823 || minor_version
== RISCV_UNKNOWN_VERSION
))
1825 if (subset
[0] == 'x')
1827 (_("x ISA extension `%s' must be set with the versions"),
1829 /* Allow old ISA spec can recognize zicsr and zifencei. */
1830 else if (strcmp (subset
, "zicsr") != 0
1831 && strcmp (subset
, "zifencei") != 0)
1833 (_("cannot find default versions of the ISA extension `%s'"),
1838 riscv_add_subset (rps
->subset_list
, subset
,
1839 major_version
, minor_version
);
1842 /* Release subset list. */
1845 riscv_release_subset_list (riscv_subset_list_t
*subset_list
)
1847 while (subset_list
->head
!= NULL
)
1849 riscv_subset_t
*next
= subset_list
->head
->next
;
1850 free ((void *)subset_list
->head
->name
);
1851 free (subset_list
->head
);
1852 subset_list
->head
= next
;
1855 subset_list
->tail
= NULL
;
1857 if (subset_list
->arch_str
!= NULL
)
1859 free ((void*) subset_list
->arch_str
);
1860 subset_list
->arch_str
= NULL
;
1864 /* Parsing extension version.
1867 Points to the end of version
1870 `p`: Curent parsing position.
1871 `major_version`: Parsed major version.
1872 `minor_version`: Parsed minor version. */
1875 riscv_parsing_subset_version (const char *p
,
1879 bool major_p
= true;
1891 /* Might be beginning of `p` extension. */
1895 *major_version
= version
;
1899 else if (ISDIGIT (*p
))
1900 version
= (version
* 10) + (*p
- '0');
1906 *major_version
= version
;
1908 *minor_version
= version
;
1910 /* We can not find any version in string. */
1911 if (*major_version
== 0 && *minor_version
== 0)
1913 *major_version
= RISCV_UNKNOWN_VERSION
;
1914 *minor_version
= RISCV_UNKNOWN_VERSION
;
1920 /* Parsing function for both standard and prefixed extensions.
1923 Points to the end of extensions.
1926 `rps`: Hooks and status for parsing extensions.
1927 `arch`: Full ISA string.
1928 `p`: Curent parsing position. */
1931 riscv_parse_extensions (riscv_parse_subset_t
*rps
,
1935 /* First letter must start with i, e or g. */
1936 if (*p
!= 'e' && *p
!= 'i' && *p
!= 'g')
1939 (_("%s: first ISA extension must be `e', `i' or `g'"),
1952 char *subset
= xstrdup (p
);
1953 char *q
= subset
; /* Start of version. */
1954 const char *end_of_version
;
1955 bool implicit
= false;
1957 enum riscv_prefix_ext_class
class = riscv_get_prefix_class (p
);
1958 if (class == RV_ISA_CLASS_SINGLE
)
1960 if (riscv_ext_order
[(*subset
- 'a')] == 0)
1963 (_("%s: unknown standard ISA extension or prefix class `%c'"),
1972 /* Extract the whole prefixed extension by '_'. */
1973 while (*++q
!= '\0' && *q
!= '_')
1975 /* Look forward to the first letter which is not <major>p<minor>. */
1976 bool find_any_version
= false;
1977 bool find_minor_version
= false;
1982 find_any_version
= true;
1983 else if (find_any_version
1984 && !find_minor_version
1986 && ISDIGIT (*(q
- 1)))
1987 find_minor_version
= true;
1993 /* Check if the end of extension is 'p' or not. If yes, then
1994 the second letter from the end cannot be number. */
1995 if (*(q
- 1) == 'p' && ISDIGIT (*(q
- 2)))
1999 (_("%s: invalid prefixed ISA extension `%s' ends with <number>p"),
2006 int major_version
= RISCV_UNKNOWN_VERSION
;
2007 int minor_version
= RISCV_UNKNOWN_VERSION
;
2009 riscv_parsing_subset_version (q
, &major_version
, &minor_version
);
2011 if (end_of_version
== NULL
)
2017 /* Check if the prefixed extension name is well-formed. */
2018 if (class != RV_ISA_CLASS_SINGLE
2019 && rps
->check_unknown_prefixed_ext
2020 && !riscv_recognized_prefixed_ext (subset
))
2023 (_("%s: unknown prefixed ISA extension `%s'"),
2029 /* Added g as an implicit extension. */
2030 if (class == RV_ISA_CLASS_SINGLE
2031 && strcmp (subset
, "g") == 0)
2034 major_version
= RISCV_UNKNOWN_VERSION
;
2035 minor_version
= RISCV_UNKNOWN_VERSION
;
2037 riscv_parse_add_subset (rps
, subset
,
2039 minor_version
, implicit
);
2040 p
+= end_of_version
- subset
;
2043 if (class != RV_ISA_CLASS_SINGLE
2044 && *p
!= '\0' && *p
!= '_')
2047 (_("%s: prefixed ISA extension must separate with _"),
2057 riscv_update_subset1 (riscv_parse_subset_t
*, riscv_subset_t
*, const char *);
2059 /* Add the implicit extensions. */
2062 riscv_parse_add_implicit_subsets (riscv_parse_subset_t
*rps
)
2064 struct riscv_implicit_subset
*t
= riscv_implicit_subsets
;
2067 riscv_subset_t
*subset
= NULL
;
2068 if (riscv_lookup_subset (rps
->subset_list
, t
->ext
, &subset
)
2069 && t
->check_func (subset
))
2070 riscv_update_subset1 (rps
, subset
, t
->implicit_exts
);
2074 /* Check extensions conflicts. */
2077 riscv_parse_check_conflicts (riscv_parse_subset_t
*rps
)
2079 riscv_subset_t
*subset
= NULL
;
2080 int xlen
= *rps
->xlen
;
2081 bool no_conflict
= true;
2083 if (riscv_subset_supports (rps
, "e")
2084 && riscv_subset_supports (rps
, "h"))
2087 (_("rv%de does not support the `h' extension"), xlen
);
2088 no_conflict
= false;
2090 if (riscv_lookup_subset (rps
->subset_list
, "q", &subset
)
2091 && (subset
->major_version
< 2 || (subset
->major_version
== 2
2092 && subset
->minor_version
< 2))
2095 rps
->error_handler (_("rv%d does not support the `q' extension"), xlen
);
2096 no_conflict
= false;
2098 if (riscv_subset_supports (rps
, "zcmp")
2099 && riscv_subset_supports (rps
, "zcd"))
2102 (_("zcmp' is incompatible with `d/zcd' extension"));
2103 no_conflict
= false;
2105 if (riscv_lookup_subset (rps
->subset_list
, "zcf", &subset
)
2109 (_("rv%d does not support the `zcf' extension"), xlen
);
2110 no_conflict
= false;
2112 if (riscv_lookup_subset (rps
->subset_list
, "zfinx", &subset
)
2113 && riscv_lookup_subset (rps
->subset_list
, "f", &subset
))
2116 (_("`zfinx' is conflict with the `f/d/q/zfh/zfhmin' extension"));
2117 no_conflict
= false;
2119 if (riscv_lookup_subset (rps
->subset_list
, "xtheadvector", &subset
)
2120 && riscv_lookup_subset (rps
->subset_list
, "v", &subset
))
2123 (_("`xtheadvector' is conflict with the `v' extension"));
2124 no_conflict
= false;
2127 bool support_zve
= false;
2128 bool support_zvl
= false;
2129 riscv_subset_t
*s
= rps
->subset_list
->head
;
2130 for (; s
!= NULL
; s
= s
->next
)
2133 && strncmp (s
->name
, "zve", 3) == 0)
2136 && strncmp (s
->name
, "zvl", 3) == 0)
2138 if (support_zve
&& support_zvl
)
2141 if (support_zvl
&& !support_zve
)
2144 (_("zvl*b extensions need to enable either `v' or `zve' extension"));
2145 no_conflict
= false;
2151 /* Set the default subset list according to the default_enable field
2152 of riscv_supported_*ext tables. */
2155 riscv_set_default_arch (riscv_parse_subset_t
*rps
)
2157 unsigned long enable
= EXT_DEFAULT
;
2159 for (i
= 0; riscv_all_supported_ext
[i
] != NULL
; i
++)
2161 const struct riscv_supported_ext
*table
= riscv_all_supported_ext
[i
];
2162 for (j
= 0; table
[j
].name
!= NULL
; j
++)
2164 bool implicit
= false;
2165 if (strcmp (table
[j
].name
, "g") == 0)
2167 if (table
[j
].default_enable
& enable
)
2168 riscv_parse_add_subset (rps
, table
[j
].name
,
2169 RISCV_UNKNOWN_VERSION
,
2170 RISCV_UNKNOWN_VERSION
, implicit
);
2175 /* Function for parsing ISA string.
2178 Return TRUE on success.
2181 `rps`: Hooks and status for parsing extensions.
2182 `arch`: Full ISA string. */
2185 riscv_parse_subset (riscv_parse_subset_t
*rps
,
2190 /* Init the riscv_ext_order array to compare the order of extensions
2192 riscv_init_ext_order ();
2196 riscv_set_default_arch (rps
);
2197 riscv_parse_add_implicit_subsets (rps
);
2198 return riscv_parse_check_conflicts (rps
);
2201 for (p
= arch
; *p
!= '\0'; p
++)
2206 (_("%s: ISA string cannot contain uppercase letters"),
2213 if (startswith (p
, "rv32"))
2218 else if (startswith (p
, "rv64"))
2225 /* ISA string shouldn't be NULL or empty here. For linker,
2226 it might be empty when we failed to merge the ISA string
2227 in the riscv_merge_attributes. For assembler, we might
2228 give an empty string by .attribute arch, "" or -march=.
2229 However, We have already issued the correct error message
2230 in another side, so do not issue this error when the ISA
2233 rps
->error_handler (
2234 _("%s: ISA string must begin with rv32 or rv64"),
2239 /* Parse single standard and prefixed extensions. */
2240 if (riscv_parse_extensions (rps
, arch
, p
) == NULL
)
2243 /* Finally add implicit extensions according to the current
2245 riscv_parse_add_implicit_subsets (rps
);
2247 /* Check the conflicts. */
2248 return riscv_parse_check_conflicts (rps
);
2251 /* Return the number of digits for the input. */
2254 riscv_estimate_digit (unsigned num
)
2260 for (digit
= 0; num
; num
/= 10)
2266 /* Auxiliary function to estimate string length of subset list. */
2269 riscv_estimate_arch_strlen1 (const riscv_subset_t
*subset
)
2272 return 6; /* For rv32/rv64/rv128 and string terminator. */
2274 return riscv_estimate_arch_strlen1 (subset
->next
)
2275 + strlen (subset
->name
)
2276 + riscv_estimate_digit (subset
->major_version
)
2277 + 1 /* For version seperator 'p'. */
2278 + riscv_estimate_digit (subset
->minor_version
)
2279 + 1 /* For underscore. */;
2282 /* Estimate the string length of this subset list. */
2285 riscv_estimate_arch_strlen (const riscv_subset_list_t
*subset_list
)
2287 return riscv_estimate_arch_strlen1 (subset_list
->head
);
2290 /* Auxiliary function to convert subset info to string. */
2293 riscv_arch_str1 (riscv_subset_t
*subset
,
2294 char *attr_str
, char *buf
, size_t bufsz
)
2296 const char *underline
= "_";
2297 riscv_subset_t
*subset_t
= subset
;
2299 if (subset_t
== NULL
)
2302 /* No underline between rvXX and i/e. */
2303 if ((strcasecmp (subset_t
->name
, "i") == 0)
2304 || (strcasecmp (subset_t
->name
, "e") == 0))
2307 snprintf (buf
, bufsz
, "%s%s%dp%d",
2310 subset_t
->major_version
,
2311 subset_t
->minor_version
);
2313 strncat (attr_str
, buf
, bufsz
);
2315 /* Skip 'i' extension after 'e', or skip extensions which
2316 versions are unknown. */
2317 while (subset_t
->next
2318 && ((strcmp (subset_t
->name
, "e") == 0
2319 && strcmp (subset_t
->next
->name
, "i") == 0)
2320 || subset_t
->next
->major_version
== RISCV_UNKNOWN_VERSION
2321 || subset_t
->next
->minor_version
== RISCV_UNKNOWN_VERSION
))
2322 subset_t
= subset_t
->next
;
2324 riscv_arch_str1 (subset_t
->next
, attr_str
, buf
, bufsz
);
2327 /* Convert subset information into string with explicit versions. */
2330 riscv_arch_str (unsigned xlen
, const riscv_subset_list_t
*subset
)
2332 size_t arch_str_len
= riscv_estimate_arch_strlen (subset
);
2333 char *attr_str
= xmalloc (arch_str_len
);
2334 char *buf
= xmalloc (arch_str_len
);
2336 snprintf (attr_str
, arch_str_len
, "rv%u", xlen
);
2338 riscv_arch_str1 (subset
->head
, attr_str
, buf
, arch_str_len
);
2344 /* Copy the subset in the subset list. */
2346 static struct riscv_subset_t
*
2347 riscv_copy_subset (riscv_subset_list_t
*subset_list
,
2348 riscv_subset_t
*subset
)
2353 riscv_subset_t
*new = xmalloc (sizeof *new);
2354 new->name
= xstrdup (subset
->name
);
2355 new->major_version
= subset
->major_version
;
2356 new->minor_version
= subset
->minor_version
;
2357 new->next
= riscv_copy_subset (subset_list
, subset
->next
);
2359 if (subset
->next
== NULL
)
2360 subset_list
->tail
= new;
2365 /* Copy the subset list. */
2367 riscv_subset_list_t
*
2368 riscv_copy_subset_list (riscv_subset_list_t
*subset_list
)
2370 riscv_subset_list_t
*new = xmalloc (sizeof *new);
2371 new->head
= riscv_copy_subset (new, subset_list
->head
);
2372 new->arch_str
= strdup (subset_list
->arch_str
);
2376 /* Remove the SUBSET from the subset list. */
2379 riscv_remove_subset (riscv_subset_list_t
*subset_list
,
2382 riscv_subset_t
*current
= subset_list
->head
;
2383 riscv_subset_t
*pre
= NULL
;
2384 for (; current
!= NULL
; pre
= current
, current
= current
->next
)
2386 if (strcmp (current
->name
, subset
) == 0)
2389 subset_list
->head
= current
->next
;
2391 pre
->next
= current
->next
;
2392 if (current
->next
== NULL
)
2393 subset_list
->tail
= pre
;
2394 free ((void *) current
->name
);
2401 /* Auxiliary to add/remove extensions to/from the subset list.
2402 This is called from riscv_update_subset or riscv_parse_add_implicit_subsets.
2404 The EXPLICIT_SUBSET, the corresponding explicit extension. It is NULL means
2405 called from riscv_update_subset./
2407 The IMPLICIT_EXTS, +extension[version] [,...,+extension_n[version_n]]
2408 -extension [,...,-extension_n],
2412 riscv_update_subset1 (riscv_parse_subset_t
*rps
,
2413 riscv_subset_t
*explicit_subset
,
2414 const char *implicit_exts
)
2416 const char *p
= implicit_exts
;
2417 const char *errmsg_internal
= explicit_subset
== NULL
? "" : _("internal: ");
2418 const char *errmsg_caller
= explicit_subset
== NULL
2419 ? ".option arch" : "riscv_implicit_subsets";
2423 int major_version
= RISCV_UNKNOWN_VERSION
;
2424 int minor_version
= RISCV_UNKNOWN_VERSION
;
2426 bool removed
= false;
2429 case '+': removed
= false; break;
2430 case '-': removed
= true; break;
2432 riscv_release_subset_list (rps
->subset_list
);
2433 return riscv_parse_subset (rps
, p
);
2437 char *subset
= xstrdup (p
);
2439 const char *end_of_version
;
2440 /* Extract the whole prefixed extension by ','. */
2441 while (*q
!= '\0' && *q
!= ',')
2444 /* Look forward to the first letter which is not <major>p<minor>. */
2445 bool find_any_version
= false;
2446 bool find_minor_version
= false;
2447 size_t len
= q
- subset
;
2449 for (i
= len
; i
> 0; i
--)
2453 find_any_version
= true;
2454 else if (find_any_version
2455 && !find_minor_version
2457 && ISDIGIT (*(q
- 1)))
2458 find_minor_version
= true;
2465 /* Check if the end of extension is 'p' or not. If yes, then
2466 the second letter from the end cannot be number. */
2467 if (len
> 1 && *(q
- 1) == 'p' && ISDIGIT (*(q
- 2)))
2471 (_("%sinvalid ISA extension ends with <number>p in %s `%s'"),
2472 errmsg_internal
, errmsg_caller
, implicit_exts
);
2478 riscv_parsing_subset_version (q
, &major_version
, &minor_version
);
2480 if (end_of_version
== NULL
)
2486 if (strlen (subset
) == 0
2487 || (strlen (subset
) == 1
2488 && riscv_ext_order
[(*subset
- 'a')] == 0)
2489 || (strlen (subset
) > 1
2490 && rps
->check_unknown_prefixed_ext
2491 && !riscv_recognized_prefixed_ext (subset
)))
2494 (_("%sunknown ISA extension `%s' in %s `%s'"),
2495 errmsg_internal
, subset
, errmsg_caller
, implicit_exts
);
2500 if (explicit_subset
== NULL
2501 && (strcmp (subset
, "i") == 0
2502 || strcmp (subset
, "e") == 0
2503 || strcmp (subset
, "g") == 0))
2506 (_("%scannot + or - base extension `%s' in %s `%s'"),
2507 errmsg_internal
, subset
, errmsg_caller
, implicit_exts
);
2513 riscv_remove_subset (rps
->subset_list
, subset
);
2516 riscv_subset_t
*isubset
= NULL
;
2517 if (!riscv_lookup_subset (rps
->subset_list
, subset
, &isubset
))
2518 riscv_parse_add_subset (rps
, subset
, major_version
, minor_version
,
2519 true/* implicit */);
2521 p
+= end_of_version
- subset
;
2524 while (*p
++ == ',');
2526 bool conflict
= false;
2527 if (explicit_subset
== NULL
)
2529 riscv_parse_add_implicit_subsets (rps
);
2530 conflict
= riscv_parse_check_conflicts (rps
);
2535 /* Add/Remove an extension to/from the subset list. This is used for
2536 the .option rvc or norvc, and .option arch directives. */
2539 riscv_update_subset (riscv_parse_subset_t
*rps
,
2542 return riscv_update_subset1 (rps
, NULL
, str
);
2545 /* Check if the FEATURE subset is supported or not in the subset list.
2546 Return true if it is supported; Otherwise, return false. */
2549 riscv_subset_supports (riscv_parse_subset_t
*rps
,
2550 const char *feature
)
2552 struct riscv_subset_t
*subset
;
2553 return riscv_lookup_subset (rps
->subset_list
, feature
, &subset
);
2556 /* Each instuction is belonged to an instruction class INSN_CLASS_*.
2557 Call riscv_subset_supports to make sure if the instuction is valid. */
2560 riscv_multi_subset_supports (riscv_parse_subset_t
*rps
,
2561 enum riscv_insn_class insn_class
)
2566 return riscv_subset_supports (rps
, "i");
2567 case INSN_CLASS_ZICBOM
:
2568 return riscv_subset_supports (rps
, "zicbom");
2569 case INSN_CLASS_ZICBOP
:
2570 return riscv_subset_supports (rps
, "zicbop");
2571 case INSN_CLASS_ZICBOZ
:
2572 return riscv_subset_supports (rps
, "zicboz");
2573 case INSN_CLASS_ZICOND
:
2574 return riscv_subset_supports (rps
, "zicond");
2575 case INSN_CLASS_ZICSR
:
2576 return riscv_subset_supports (rps
, "zicsr");
2577 case INSN_CLASS_ZIFENCEI
:
2578 return riscv_subset_supports (rps
, "zifencei");
2579 case INSN_CLASS_ZIHINTNTL
:
2580 return riscv_subset_supports (rps
, "zihintntl");
2581 case INSN_CLASS_ZIHINTNTL_AND_C
:
2582 return (riscv_subset_supports (rps
, "zihintntl")
2583 && (riscv_subset_supports (rps
, "c")
2584 || riscv_subset_supports (rps
, "zca")));
2585 case INSN_CLASS_ZIHINTPAUSE
:
2586 return riscv_subset_supports (rps
, "zihintpause");
2587 case INSN_CLASS_ZIMOP
:
2588 return riscv_subset_supports (rps
, "zimop");
2589 case INSN_CLASS_ZICFISS
:
2590 return riscv_subset_supports (rps
, "zicfiss");
2591 case INSN_CLASS_ZICFISS_AND_ZCMOP
:
2592 return riscv_subset_supports (rps
, "zicfiss")
2593 && riscv_subset_supports (rps
, "zcmop");
2594 case INSN_CLASS_ZICFILP
:
2595 return riscv_subset_supports (rps
, "zicfilp");
2597 return riscv_subset_supports (rps
, "m");
2598 case INSN_CLASS_ZMMUL
:
2599 return riscv_subset_supports (rps
, "zmmul");
2600 case INSN_CLASS_ZAAMO
:
2601 return riscv_subset_supports (rps
, "zaamo");
2602 case INSN_CLASS_ZABHA
:
2603 return riscv_subset_supports (rps
, "zabha");
2604 case INSN_CLASS_ZACAS
:
2605 return riscv_subset_supports (rps
, "zacas");
2606 case INSN_CLASS_ZABHA_AND_ZACAS
:
2607 return (riscv_subset_supports (rps
, "zabha")
2608 && riscv_subset_supports (rps
, "zacas"));
2609 case INSN_CLASS_ZALRSC
:
2610 return riscv_subset_supports (rps
, "zalrsc");
2611 case INSN_CLASS_ZAWRS
:
2612 return riscv_subset_supports (rps
, "zawrs");
2614 return riscv_subset_supports (rps
, "f");
2616 return riscv_subset_supports (rps
, "d");
2618 return riscv_subset_supports (rps
, "q");
2620 return (riscv_subset_supports (rps
, "c")
2621 || riscv_subset_supports (rps
, "zca"));
2622 case INSN_CLASS_F_AND_C
:
2623 return (riscv_subset_supports (rps
, "f")
2624 && (riscv_subset_supports (rps
, "c")
2625 || riscv_subset_supports (rps
, "zcf")));
2626 case INSN_CLASS_D_AND_C
:
2627 return (riscv_subset_supports (rps
, "d")
2628 && (riscv_subset_supports (rps
, "c")
2629 || riscv_subset_supports (rps
, "zcd")));
2630 case INSN_CLASS_F_INX
:
2631 return (riscv_subset_supports (rps
, "f")
2632 || riscv_subset_supports (rps
, "zfinx"));
2633 case INSN_CLASS_D_INX
:
2634 return (riscv_subset_supports (rps
, "d")
2635 || riscv_subset_supports (rps
, "zdinx"));
2636 case INSN_CLASS_Q_INX
:
2637 return (riscv_subset_supports (rps
, "q")
2638 || riscv_subset_supports (rps
, "zqinx"));
2639 case INSN_CLASS_ZFH_INX
:
2640 return (riscv_subset_supports (rps
, "zfh")
2641 || riscv_subset_supports (rps
, "zhinx"));
2642 case INSN_CLASS_ZFHMIN
:
2643 return riscv_subset_supports (rps
, "zfhmin");
2644 case INSN_CLASS_ZFHMIN_INX
:
2645 return (riscv_subset_supports (rps
, "zfhmin")
2646 || riscv_subset_supports (rps
, "zhinxmin"));
2647 case INSN_CLASS_ZFHMIN_AND_D_INX
:
2648 return ((riscv_subset_supports (rps
, "zfhmin")
2649 && riscv_subset_supports (rps
, "d"))
2650 || (riscv_subset_supports (rps
, "zhinxmin")
2651 && riscv_subset_supports (rps
, "zdinx")));
2652 case INSN_CLASS_ZFHMIN_AND_Q_INX
:
2653 return ((riscv_subset_supports (rps
, "zfhmin")
2654 && riscv_subset_supports (rps
, "q"))
2655 || (riscv_subset_supports (rps
, "zhinxmin")
2656 && riscv_subset_supports (rps
, "zqinx")));
2657 case INSN_CLASS_ZFBFMIN
:
2658 return riscv_subset_supports (rps
, "zfbfmin");
2659 case INSN_CLASS_ZFA
:
2660 return riscv_subset_supports (rps
, "zfa");
2661 case INSN_CLASS_D_AND_ZFA
:
2662 return riscv_subset_supports (rps
, "d")
2663 && riscv_subset_supports (rps
, "zfa");
2664 case INSN_CLASS_Q_AND_ZFA
:
2665 return riscv_subset_supports (rps
, "q")
2666 && riscv_subset_supports (rps
, "zfa");
2667 case INSN_CLASS_ZFH_AND_ZFA
:
2668 return riscv_subset_supports (rps
, "zfh")
2669 && riscv_subset_supports (rps
, "zfa");
2670 case INSN_CLASS_ZFH_OR_ZVFH_AND_ZFA
:
2671 return (riscv_subset_supports (rps
, "zfh")
2672 || riscv_subset_supports (rps
, "zvfh"))
2673 && riscv_subset_supports (rps
, "zfa");
2674 case INSN_CLASS_ZBA
:
2675 return riscv_subset_supports (rps
, "zba");
2676 case INSN_CLASS_ZBB
:
2677 return riscv_subset_supports (rps
, "zbb");
2678 case INSN_CLASS_ZBC
:
2679 return riscv_subset_supports (rps
, "zbc");
2680 case INSN_CLASS_ZBS
:
2681 return riscv_subset_supports (rps
, "zbs");
2682 case INSN_CLASS_ZBKB
:
2683 return riscv_subset_supports (rps
, "zbkb");
2684 case INSN_CLASS_ZBKC
:
2685 return riscv_subset_supports (rps
, "zbkc");
2686 case INSN_CLASS_ZBKX
:
2687 return riscv_subset_supports (rps
, "zbkx");
2688 case INSN_CLASS_ZBB_OR_ZBKB
:
2689 return (riscv_subset_supports (rps
, "zbb")
2690 || riscv_subset_supports (rps
, "zbkb"));
2691 case INSN_CLASS_ZBC_OR_ZBKC
:
2692 return (riscv_subset_supports (rps
, "zbc")
2693 || riscv_subset_supports (rps
, "zbkc"));
2694 case INSN_CLASS_ZKND
:
2695 return riscv_subset_supports (rps
, "zknd");
2696 case INSN_CLASS_ZKNE
:
2697 return riscv_subset_supports (rps
, "zkne");
2698 case INSN_CLASS_ZKNH
:
2699 return riscv_subset_supports (rps
, "zknh");
2700 case INSN_CLASS_ZKND_OR_ZKNE
:
2701 return (riscv_subset_supports (rps
, "zknd")
2702 || riscv_subset_supports (rps
, "zkne"));
2703 case INSN_CLASS_ZKSED
:
2704 return riscv_subset_supports (rps
, "zksed");
2705 case INSN_CLASS_ZKSH
:
2706 return riscv_subset_supports (rps
, "zksh");
2708 return (riscv_subset_supports (rps
, "v")
2709 || riscv_subset_supports (rps
, "zve64x")
2710 || riscv_subset_supports (rps
, "zve32x"));
2711 case INSN_CLASS_ZVEF
:
2712 return (riscv_subset_supports (rps
, "v")
2713 || riscv_subset_supports (rps
, "zve64d")
2714 || riscv_subset_supports (rps
, "zve64f")
2715 || riscv_subset_supports (rps
, "zve32f"));
2716 case INSN_CLASS_ZVBB
:
2717 return riscv_subset_supports (rps
, "zvbb");
2718 case INSN_CLASS_ZVBC
:
2719 return riscv_subset_supports (rps
, "zvbc");
2720 case INSN_CLASS_ZVFBFMIN
:
2721 return riscv_subset_supports (rps
, "zvfbfmin");
2722 case INSN_CLASS_ZVFBFWMA
:
2723 return riscv_subset_supports (rps
, "zvfbfwma");
2724 case INSN_CLASS_ZVKB
:
2725 return riscv_subset_supports (rps
, "zvkb");
2726 case INSN_CLASS_ZVKG
:
2727 return riscv_subset_supports (rps
, "zvkg");
2728 case INSN_CLASS_ZVKNED
:
2729 return riscv_subset_supports (rps
, "zvkned");
2730 case INSN_CLASS_ZVKNHA_OR_ZVKNHB
:
2731 return (riscv_subset_supports (rps
, "zvknha")
2732 || riscv_subset_supports (rps
, "zvknhb"));
2733 case INSN_CLASS_ZVKSED
:
2734 return riscv_subset_supports (rps
, "zvksed");
2735 case INSN_CLASS_ZVKSH
:
2736 return riscv_subset_supports (rps
, "zvksh");
2737 case INSN_CLASS_ZCB
:
2738 return riscv_subset_supports (rps
, "zcb");
2739 case INSN_CLASS_ZCB_AND_ZBB
:
2740 return (riscv_subset_supports (rps
, "zcb")
2741 && riscv_subset_supports (rps
, "zbb"));
2742 case INSN_CLASS_ZCB_AND_ZBA
:
2743 return (riscv_subset_supports (rps
, "zcb")
2744 && riscv_subset_supports (rps
, "zba"));
2745 case INSN_CLASS_ZCB_AND_ZMMUL
:
2746 return (riscv_subset_supports (rps
, "zcb")
2747 && riscv_subset_supports (rps
, "zmmul"));
2748 case INSN_CLASS_ZCMOP
:
2749 return riscv_subset_supports (rps
, "zcmop");
2750 case INSN_CLASS_ZCMP
:
2751 return riscv_subset_supports (rps
, "zcmp");
2752 case INSN_CLASS_ZCMT
:
2753 return riscv_subset_supports (rps
, "zcmt");
2754 case INSN_CLASS_SMCTR_OR_SSCTR
:
2755 return (riscv_subset_supports (rps
, "smctr")
2756 || riscv_subset_supports (rps
, "ssctr"));
2757 case INSN_CLASS_SVINVAL
:
2758 return riscv_subset_supports (rps
, "svinval");
2760 return riscv_subset_supports (rps
, "h");
2761 case INSN_CLASS_XCVALU
:
2762 return riscv_subset_supports (rps
, "xcvalu");
2763 case INSN_CLASS_XCVBI
:
2764 return riscv_subset_supports (rps
, "xcvbi");
2765 case INSN_CLASS_XCVBITMANIP
:
2766 return riscv_subset_supports (rps
, "xcvbitmanip");
2767 case INSN_CLASS_XCVELW
:
2768 return riscv_subset_supports (rps
, "xcvelw");
2769 case INSN_CLASS_XCVMAC
:
2770 return riscv_subset_supports (rps
, "xcvmac");
2771 case INSN_CLASS_XCVMEM
:
2772 return riscv_subset_supports (rps
, "xcvmem");
2773 case INSN_CLASS_XCVSIMD
:
2774 return riscv_subset_supports (rps
, "xcvsimd");
2775 case INSN_CLASS_XTHEADBA
:
2776 return riscv_subset_supports (rps
, "xtheadba");
2777 case INSN_CLASS_XTHEADBB
:
2778 return riscv_subset_supports (rps
, "xtheadbb");
2779 case INSN_CLASS_XTHEADBS
:
2780 return riscv_subset_supports (rps
, "xtheadbs");
2781 case INSN_CLASS_XTHEADCMO
:
2782 return riscv_subset_supports (rps
, "xtheadcmo");
2783 case INSN_CLASS_XTHEADCONDMOV
:
2784 return riscv_subset_supports (rps
, "xtheadcondmov");
2785 case INSN_CLASS_XTHEADFMEMIDX
:
2786 return riscv_subset_supports (rps
, "xtheadfmemidx");
2787 case INSN_CLASS_XTHEADFMV
:
2788 return riscv_subset_supports (rps
, "xtheadfmv");
2789 case INSN_CLASS_XTHEADINT
:
2790 return riscv_subset_supports (rps
, "xtheadint");
2791 case INSN_CLASS_XTHEADMAC
:
2792 return riscv_subset_supports (rps
, "xtheadmac");
2793 case INSN_CLASS_XTHEADMEMIDX
:
2794 return riscv_subset_supports (rps
, "xtheadmemidx");
2795 case INSN_CLASS_XTHEADMEMPAIR
:
2796 return riscv_subset_supports (rps
, "xtheadmempair");
2797 case INSN_CLASS_XTHEADSYNC
:
2798 return riscv_subset_supports (rps
, "xtheadsync");
2799 case INSN_CLASS_XTHEADVECTOR
:
2800 return riscv_subset_supports (rps
, "xtheadvector");
2801 case INSN_CLASS_XTHEADZVAMO
:
2802 return riscv_subset_supports (rps
, "xtheadzvamo");
2803 case INSN_CLASS_XVENTANACONDOPS
:
2804 return riscv_subset_supports (rps
, "xventanacondops");
2805 case INSN_CLASS_XSFVCP
:
2806 return riscv_subset_supports (rps
, "xsfvcp");
2807 case INSN_CLASS_XSFCEASE
:
2808 return riscv_subset_supports (rps
, "xsfcease");
2809 case INSN_CLASS_XSFVQMACCQOQ
:
2810 return riscv_subset_supports (rps
, "xsfvqmaccqoq");
2811 case INSN_CLASS_XSFVQMACCDOD
:
2812 return riscv_subset_supports (rps
, "xsfvqmaccdod");
2813 case INSN_CLASS_XSFVFNRCLIPXFQF
:
2814 return riscv_subset_supports (rps
, "xsfvfnrclipxfqf");
2817 (_("internal: unreachable INSN_CLASS_*"));
2822 /* Each instuction is belonged to an instruction class INSN_CLASS_*.
2823 Call riscv_subset_supports_ext to determine the missing extension. */
2826 riscv_multi_subset_supports_ext (riscv_parse_subset_t
*rps
,
2827 enum riscv_insn_class insn_class
)
2833 case INSN_CLASS_ZICBOM
:
2835 case INSN_CLASS_ZICBOP
:
2837 case INSN_CLASS_ZICBOZ
:
2839 case INSN_CLASS_ZICOND
:
2841 case INSN_CLASS_ZICSR
:
2843 case INSN_CLASS_ZIFENCEI
:
2845 case INSN_CLASS_ZICFISS
:
2847 case INSN_CLASS_ZICFISS_AND_ZCMOP
:
2848 if (!riscv_subset_supports (rps
, "zicfiss"))
2850 if (!riscv_subset_supports (rps
, "zcmop"))
2851 return _("zicfiss' and `zcmop");
2856 case INSN_CLASS_ZICFILP
:
2858 case INSN_CLASS_ZIHINTNTL
:
2860 case INSN_CLASS_ZIHINTNTL_AND_C
:
2861 if (!riscv_subset_supports (rps
, "zihintntl"))
2863 if (!riscv_subset_supports (rps
, "c")
2864 && !riscv_subset_supports (rps
, "zca"))
2865 return _("zihintntl' and `c', or `zihintntl' and `zca");
2870 return _("c' or `zca");
2871 case INSN_CLASS_ZIHINTPAUSE
:
2872 return "zihintpause";
2873 case INSN_CLASS_ZIMOP
:
2877 case INSN_CLASS_ZMMUL
:
2878 return _ ("m' or `zmmul");
2879 case INSN_CLASS_ZAAMO
:
2881 case INSN_CLASS_ZABHA
:
2883 case INSN_CLASS_ZACAS
:
2885 case INSN_CLASS_ZALRSC
:
2887 case INSN_CLASS_ZAWRS
:
2896 return _("c' or `zca");
2897 case INSN_CLASS_F_AND_C
:
2898 if (!riscv_subset_supports (rps
, "f"))
2900 if (!riscv_subset_supports (rps
, "c")
2901 && !riscv_subset_supports (rps
, "zcf"))
2902 return _("f' and `c', or `f' and `zcf");
2907 return _("c' or `zcf");
2908 case INSN_CLASS_D_AND_C
:
2909 if (!riscv_subset_supports (rps
, "d"))
2911 if (!riscv_subset_supports (rps
, "c")
2912 && !riscv_subset_supports (rps
, "zcd"))
2913 return _("d' and `c', or `d' and `zcd");
2918 return _("c' or `zcd");
2919 case INSN_CLASS_F_INX
:
2920 return _("f' or `zfinx");
2921 case INSN_CLASS_D_INX
:
2922 return _("d' or `zdinx");
2923 case INSN_CLASS_Q_INX
:
2924 return _("q' or `zqinx");
2925 case INSN_CLASS_ZFH_INX
:
2926 return _("zfh' or `zhinx");
2927 case INSN_CLASS_ZFHMIN
:
2929 case INSN_CLASS_ZFHMIN_INX
:
2930 return _("zfhmin' or `zhinxmin");
2931 case INSN_CLASS_ZFHMIN_AND_D_INX
:
2932 if (riscv_subset_supports (rps
, "zfhmin"))
2934 else if (riscv_subset_supports (rps
, "d"))
2936 else if (riscv_subset_supports (rps
, "zhinxmin"))
2938 else if (riscv_subset_supports (rps
, "zdinx"))
2941 return _("zfhmin' and `d', or `zhinxmin' and `zdinx");
2942 case INSN_CLASS_ZFHMIN_AND_Q_INX
:
2943 if (riscv_subset_supports (rps
, "zfhmin"))
2945 else if (riscv_subset_supports (rps
, "q"))
2947 else if (riscv_subset_supports (rps
, "zhinxmin"))
2949 else if (riscv_subset_supports (rps
, "zqinx"))
2952 return _("zfhmin' and `q', or `zhinxmin' and `zqinx");
2953 case INSN_CLASS_ZFBFMIN
:
2955 case INSN_CLASS_ZFA
:
2957 case INSN_CLASS_D_AND_ZFA
:
2958 if (!riscv_subset_supports (rps
, "d")
2959 && !riscv_subset_supports (rps
, "zfa"))
2960 return _("d' and `zfa");
2961 else if (!riscv_subset_supports (rps
, "d"))
2965 case INSN_CLASS_Q_AND_ZFA
:
2966 if (!riscv_subset_supports (rps
, "q")
2967 && !riscv_subset_supports (rps
, "zfa"))
2968 return _("q' and `zfa");
2969 else if (!riscv_subset_supports (rps
, "q"))
2973 case INSN_CLASS_ZFH_AND_ZFA
:
2974 if (!riscv_subset_supports (rps
, "zfh")
2975 && !riscv_subset_supports (rps
, "zfa"))
2976 return _("zfh' and `zfa");
2977 else if (!riscv_subset_supports (rps
, "zfh"))
2981 case INSN_CLASS_ZFH_OR_ZVFH_AND_ZFA
:
2982 if (!riscv_subset_supports (rps
, "zfa"))
2984 if (!riscv_subset_supports (rps
, "zfh")
2985 && !riscv_subset_supports (rps
, "zvfh"))
2986 return _("zfh' and `zfa', or `zvfh' and `zfa");
2991 return _("zfh' or `zvfh");
2992 case INSN_CLASS_ZBA
:
2994 case INSN_CLASS_ZBB
:
2996 case INSN_CLASS_ZBC
:
2998 case INSN_CLASS_ZBS
:
3000 case INSN_CLASS_ZBKB
:
3002 case INSN_CLASS_ZBKC
:
3004 case INSN_CLASS_ZBKX
:
3006 case INSN_CLASS_ZBB_OR_ZBKB
:
3007 return _("zbb' or `zbkb");
3008 case INSN_CLASS_ZBC_OR_ZBKC
:
3009 return _("zbc' or `zbkc");
3010 case INSN_CLASS_ZKND
:
3012 case INSN_CLASS_ZKNE
:
3014 case INSN_CLASS_ZKNH
:
3016 case INSN_CLASS_ZKND_OR_ZKNE
:
3017 return _("zknd' or `zkne");
3018 case INSN_CLASS_ZKSED
:
3020 case INSN_CLASS_ZKSH
:
3023 return _("v' or `zve64x' or `zve32x");
3024 case INSN_CLASS_ZVEF
:
3025 return _("v' or `zve64d' or `zve64f' or `zve32f");
3026 case INSN_CLASS_ZVBB
:
3028 case INSN_CLASS_ZVBC
:
3030 case INSN_CLASS_ZVFBFMIN
:
3032 case INSN_CLASS_ZVFBFWMA
:
3034 case INSN_CLASS_ZVKB
:
3036 case INSN_CLASS_ZVKG
:
3038 case INSN_CLASS_ZVKNED
:
3040 case INSN_CLASS_ZVKNHA_OR_ZVKNHB
:
3041 return _("zvknha' or `zvknhb");
3042 case INSN_CLASS_ZVKSED
:
3044 case INSN_CLASS_ZVKSH
:
3046 case INSN_CLASS_ZCB
:
3048 case INSN_CLASS_ZCB_AND_ZBA
:
3049 return _("zcb' and `zba");
3050 case INSN_CLASS_ZCB_AND_ZBB
:
3051 return _("zcb' and `zbb");
3052 case INSN_CLASS_ZCB_AND_ZMMUL
:
3053 return _("zcb' and `zmmul', or `zcb' and `m");
3054 case INSN_CLASS_ZCMOP
:
3056 case INSN_CLASS_ZCMP
:
3058 case INSN_CLASS_ZCMT
:
3060 case INSN_CLASS_SMCTR_OR_SSCTR
:
3061 return _("smctr' or `ssctr");
3062 case INSN_CLASS_SVINVAL
:
3066 case INSN_CLASS_XCVALU
:
3068 case INSN_CLASS_XCVBI
:
3070 case INSN_CLASS_XCVBITMANIP
:
3071 return "xcvbitmanip";
3072 case INSN_CLASS_XCVELW
:
3074 case INSN_CLASS_XCVMAC
:
3076 case INSN_CLASS_XCVMEM
:
3078 case INSN_CLASS_XCVSIMD
:
3080 case INSN_CLASS_XTHEADBA
:
3082 case INSN_CLASS_XTHEADBB
:
3084 case INSN_CLASS_XTHEADBS
:
3086 case INSN_CLASS_XTHEADCMO
:
3088 case INSN_CLASS_XTHEADCONDMOV
:
3089 return "xtheadcondmov";
3090 case INSN_CLASS_XTHEADFMEMIDX
:
3091 return "xtheadfmemidx";
3092 case INSN_CLASS_XTHEADFMV
:
3094 case INSN_CLASS_XTHEADINT
:
3096 case INSN_CLASS_XTHEADMAC
:
3098 case INSN_CLASS_XTHEADMEMIDX
:
3099 return "xtheadmemidx";
3100 case INSN_CLASS_XTHEADMEMPAIR
:
3101 return "xtheadmempair";
3102 case INSN_CLASS_XTHEADSYNC
:
3103 return "xtheadsync";
3104 case INSN_CLASS_XTHEADVECTOR
:
3105 return "xtheadvector";
3106 case INSN_CLASS_XTHEADZVAMO
:
3107 return "xtheadzvamo";
3108 case INSN_CLASS_XSFCEASE
:
3112 (_("internal: unreachable INSN_CLASS_*"));
3117 /* Print supported extensions with versions if -march=help. */
3120 riscv_print_extensions (void)
3122 /* Record the previous printed extension.
3123 Print the current one if they are not the same. */
3124 const struct riscv_supported_ext
*cur
= NULL
, *prev
= NULL
;
3127 printf ("All available -march extensions for RISC-V:");
3129 for (i
= 0; riscv_all_supported_ext
[i
] != NULL
; i
++)
3131 const struct riscv_supported_ext
*exts
= riscv_all_supported_ext
[i
];
3133 for (j
= 0; exts
[j
].name
!= NULL
; j
++)
3136 /* Unclear version information, skip. */
3137 if (cur
->isa_spec_class
== ISA_SPEC_CLASS_NONE
3138 || cur
->major_version
== RISCV_UNKNOWN_VERSION
3139 || cur
->minor_version
== RISCV_UNKNOWN_VERSION
)
3142 /* Same extension. */
3143 if (prev
&& strcmp (prev
->name
, cur
->name
) == 0)
3145 /* Same version, skip. */
3146 if (prev
->major_version
== cur
->major_version
3147 && prev
->minor_version
== cur
->minor_version
)
3149 /* Different version, print version with comma. */
3151 printf (", %d.%d", cur
->major_version
, cur
->minor_version
);
3153 /* Different extension, print extension and version with newline. */
3155 printf ("\n\t%-40s%d.%d", cur
->name
, cur
->major_version
,
3156 cur
->minor_version
);