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 */
226 /* 12-bit PC-relative branch offset. */
227 HOWTO (R_RISCV_BRANCH
, /* type */
231 true, /* pc_relative */
233 complain_overflow_signed
, /* complain_on_overflow */
234 bfd_elf_generic_reloc
, /* special_function */
235 "R_RISCV_BRANCH", /* name */
236 false, /* partial_inplace */
238 ENCODE_BTYPE_IMM (-1U), /* dst_mask */
239 true), /* pcrel_offset */
241 /* 20-bit PC-relative jump offset. */
242 HOWTO (R_RISCV_JAL
, /* type */
246 true, /* pc_relative */
248 complain_overflow_dont
, /* complain_on_overflow */
249 bfd_elf_generic_reloc
, /* special_function */
250 "R_RISCV_JAL", /* name */
251 false, /* partial_inplace */
253 ENCODE_JTYPE_IMM (-1U), /* dst_mask */
254 true), /* pcrel_offset */
256 /* 32-bit PC-relative function call (AUIPC/JALR). */
257 HOWTO (R_RISCV_CALL
, /* type */
261 true, /* pc_relative */
263 complain_overflow_dont
, /* complain_on_overflow */
264 bfd_elf_generic_reloc
, /* special_function */
265 "R_RISCV_CALL", /* name */
266 false, /* partial_inplace */
268 ENCODE_UTYPE_IMM (-1U) | ((bfd_vma
) ENCODE_ITYPE_IMM (-1U) << 32),
270 true), /* pcrel_offset */
272 /* Like R_RISCV_CALL, but not locally binding. */
273 HOWTO (R_RISCV_CALL_PLT
, /* type */
277 true, /* pc_relative */
279 complain_overflow_dont
, /* complain_on_overflow */
280 bfd_elf_generic_reloc
, /* special_function */
281 "R_RISCV_CALL_PLT", /* name */
282 false, /* partial_inplace */
284 ENCODE_UTYPE_IMM (-1U) | ((bfd_vma
) ENCODE_ITYPE_IMM (-1U) << 32),
286 true), /* pcrel_offset */
288 /* High 20 bits of 32-bit PC-relative GOT access. */
289 HOWTO (R_RISCV_GOT_HI20
, /* type */
293 true, /* pc_relative */
295 complain_overflow_dont
, /* complain_on_overflow */
296 bfd_elf_generic_reloc
, /* special_function */
297 "R_RISCV_GOT_HI20", /* name */
298 false, /* partial_inplace */
300 ENCODE_UTYPE_IMM (-1U), /* dst_mask */
301 false), /* pcrel_offset */
303 /* High 20 bits of 32-bit PC-relative TLS IE GOT access. */
304 HOWTO (R_RISCV_TLS_GOT_HI20
, /* type */
308 true, /* pc_relative */
310 complain_overflow_dont
, /* complain_on_overflow */
311 bfd_elf_generic_reloc
, /* special_function */
312 "R_RISCV_TLS_GOT_HI20", /* name */
313 false, /* partial_inplace */
315 ENCODE_UTYPE_IMM (-1U), /* dst_mask */
316 false), /* pcrel_offset */
318 /* High 20 bits of 32-bit PC-relative TLS GD GOT reference. */
319 HOWTO (R_RISCV_TLS_GD_HI20
, /* type */
323 true, /* pc_relative */
325 complain_overflow_dont
, /* complain_on_overflow */
326 bfd_elf_generic_reloc
, /* special_function */
327 "R_RISCV_TLS_GD_HI20", /* name */
328 false, /* partial_inplace */
330 ENCODE_UTYPE_IMM (-1U), /* dst_mask */
331 false), /* pcrel_offset */
333 /* High 20 bits of 32-bit PC-relative reference. */
334 HOWTO (R_RISCV_PCREL_HI20
, /* type */
338 true, /* pc_relative */
340 complain_overflow_dont
, /* complain_on_overflow */
341 bfd_elf_generic_reloc
, /* special_function */
342 "R_RISCV_PCREL_HI20", /* name */
343 false, /* partial_inplace */
345 ENCODE_UTYPE_IMM (-1U), /* dst_mask */
346 true), /* pcrel_offset */
348 /* Low 12 bits of a 32-bit PC-relative load or add. */
349 HOWTO (R_RISCV_PCREL_LO12_I
, /* type */
353 false, /* pc_relative */
355 complain_overflow_dont
, /* complain_on_overflow */
356 bfd_elf_generic_reloc
, /* special_function */
357 "R_RISCV_PCREL_LO12_I", /* name */
358 false, /* partial_inplace */
360 ENCODE_ITYPE_IMM (-1U), /* dst_mask */
361 false), /* pcrel_offset */
363 /* Low 12 bits of a 32-bit PC-relative store. */
364 HOWTO (R_RISCV_PCREL_LO12_S
, /* type */
368 false, /* pc_relative */
370 complain_overflow_dont
, /* complain_on_overflow */
371 bfd_elf_generic_reloc
, /* special_function */
372 "R_RISCV_PCREL_LO12_S", /* name */
373 false, /* partial_inplace */
375 ENCODE_STYPE_IMM (-1U), /* dst_mask */
376 false), /* pcrel_offset */
378 /* High 20 bits of 32-bit absolute address. */
379 HOWTO (R_RISCV_HI20
, /* type */
383 false, /* pc_relative */
385 complain_overflow_dont
, /* complain_on_overflow */
386 bfd_elf_generic_reloc
, /* special_function */
387 "R_RISCV_HI20", /* name */
388 false, /* partial_inplace */
390 ENCODE_UTYPE_IMM (-1U), /* dst_mask */
391 false), /* pcrel_offset */
393 /* High 12 bits of 32-bit load or add. */
394 HOWTO (R_RISCV_LO12_I
, /* type */
398 false, /* pc_relative */
400 complain_overflow_dont
, /* complain_on_overflow */
401 bfd_elf_generic_reloc
, /* special_function */
402 "R_RISCV_LO12_I", /* name */
403 false, /* partial_inplace */
405 ENCODE_ITYPE_IMM (-1U), /* dst_mask */
406 false), /* pcrel_offset */
408 /* High 12 bits of 32-bit store. */
409 HOWTO (R_RISCV_LO12_S
, /* type */
413 false, /* pc_relative */
415 complain_overflow_dont
, /* complain_on_overflow */
416 bfd_elf_generic_reloc
, /* special_function */
417 "R_RISCV_LO12_S", /* name */
418 false, /* partial_inplace */
420 ENCODE_STYPE_IMM (-1U), /* dst_mask */
421 false), /* pcrel_offset */
423 /* High 20 bits of TLS LE thread pointer offset. */
424 HOWTO (R_RISCV_TPREL_HI20
, /* type */
428 false, /* pc_relative */
430 complain_overflow_signed
, /* complain_on_overflow */
431 bfd_elf_generic_reloc
, /* special_function */
432 "R_RISCV_TPREL_HI20", /* name */
433 true, /* partial_inplace */
435 ENCODE_UTYPE_IMM (-1U), /* dst_mask */
436 false), /* pcrel_offset */
438 /* Low 12 bits of TLS LE thread pointer offset for loads and adds. */
439 HOWTO (R_RISCV_TPREL_LO12_I
, /* type */
443 false, /* pc_relative */
445 complain_overflow_signed
, /* complain_on_overflow */
446 bfd_elf_generic_reloc
, /* special_function */
447 "R_RISCV_TPREL_LO12_I", /* name */
448 false, /* partial_inplace */
450 ENCODE_ITYPE_IMM (-1U), /* dst_mask */
451 false), /* pcrel_offset */
453 /* Low 12 bits of TLS LE thread pointer offset for stores. */
454 HOWTO (R_RISCV_TPREL_LO12_S
, /* type */
458 false, /* pc_relative */
460 complain_overflow_signed
, /* complain_on_overflow */
461 bfd_elf_generic_reloc
, /* special_function */
462 "R_RISCV_TPREL_LO12_S", /* name */
463 false, /* partial_inplace */
465 ENCODE_STYPE_IMM (-1U), /* dst_mask */
466 false), /* pcrel_offset */
468 /* TLS LE thread pointer usage. May be relaxed. */
469 HOWTO (R_RISCV_TPREL_ADD
, /* type */
473 false, /* pc_relative */
475 complain_overflow_dont
, /* complain_on_overflow */
476 bfd_elf_generic_reloc
, /* special_function */
477 "R_RISCV_TPREL_ADD", /* name */
478 false, /* partial_inplace */
481 false), /* pcrel_offset */
483 /* 8-bit in-place addition, for local label subtraction. */
484 HOWTO (R_RISCV_ADD8
, /* type */
488 false, /* pc_relative */
490 complain_overflow_dont
, /* complain_on_overflow */
491 riscv_elf_add_sub_reloc
, /* special_function */
492 "R_RISCV_ADD8", /* name */
493 false, /* partial_inplace */
496 false), /* pcrel_offset */
498 /* 16-bit in-place addition, for local label subtraction. */
499 HOWTO (R_RISCV_ADD16
, /* type */
503 false, /* pc_relative */
505 complain_overflow_dont
, /* complain_on_overflow */
506 riscv_elf_add_sub_reloc
, /* special_function */
507 "R_RISCV_ADD16", /* name */
508 false, /* partial_inplace */
510 0xffff, /* dst_mask */
511 false), /* pcrel_offset */
513 /* 32-bit in-place addition, for local label subtraction. */
514 HOWTO (R_RISCV_ADD32
, /* type */
518 false, /* pc_relative */
520 complain_overflow_dont
, /* complain_on_overflow */
521 riscv_elf_add_sub_reloc
, /* special_function */
522 "R_RISCV_ADD32", /* name */
523 false, /* partial_inplace */
525 0xffffffff, /* dst_mask */
526 false), /* pcrel_offset */
528 /* 64-bit in-place addition, for local label subtraction. */
529 HOWTO (R_RISCV_ADD64
, /* type */
533 false, /* pc_relative */
535 complain_overflow_dont
, /* complain_on_overflow */
536 riscv_elf_add_sub_reloc
, /* special_function */
537 "R_RISCV_ADD64", /* name */
538 false, /* partial_inplace */
540 MINUS_ONE
, /* dst_mask */
541 false), /* pcrel_offset */
543 /* 8-bit in-place addition, for local label subtraction. */
544 HOWTO (R_RISCV_SUB8
, /* type */
548 false, /* pc_relative */
550 complain_overflow_dont
, /* complain_on_overflow */
551 riscv_elf_add_sub_reloc
, /* special_function */
552 "R_RISCV_SUB8", /* name */
553 false, /* partial_inplace */
556 false), /* pcrel_offset */
558 /* 16-bit in-place addition, for local label subtraction. */
559 HOWTO (R_RISCV_SUB16
, /* type */
563 false, /* pc_relative */
565 complain_overflow_dont
, /* complain_on_overflow */
566 riscv_elf_add_sub_reloc
, /* special_function */
567 "R_RISCV_SUB16", /* name */
568 false, /* partial_inplace */
570 0xffff, /* dst_mask */
571 false), /* pcrel_offset */
573 /* 32-bit in-place addition, for local label subtraction. */
574 HOWTO (R_RISCV_SUB32
, /* type */
578 false, /* pc_relative */
580 complain_overflow_dont
, /* complain_on_overflow */
581 riscv_elf_add_sub_reloc
, /* special_function */
582 "R_RISCV_SUB32", /* name */
583 false, /* partial_inplace */
585 0xffffffff, /* dst_mask */
586 false), /* pcrel_offset */
588 /* 64-bit in-place addition, for local label subtraction. */
589 HOWTO (R_RISCV_SUB64
, /* type */
593 false, /* pc_relative */
595 complain_overflow_dont
, /* complain_on_overflow */
596 riscv_elf_add_sub_reloc
, /* special_function */
597 "R_RISCV_SUB64", /* name */
598 false, /* partial_inplace */
600 MINUS_ONE
, /* dst_mask */
601 false), /* pcrel_offset */
606 /* Indicates an alignment statement. The addend field encodes how many
607 bytes of NOPs follow the statement. The desired alignment is the
608 addend rounded up to the next power of two. */
609 HOWTO (R_RISCV_ALIGN
, /* type */
613 false, /* pc_relative */
615 complain_overflow_dont
, /* complain_on_overflow */
616 bfd_elf_generic_reloc
, /* special_function */
617 "R_RISCV_ALIGN", /* name */
618 false, /* partial_inplace */
621 false), /* pcrel_offset */
623 /* 8-bit PC-relative branch offset. */
624 HOWTO (R_RISCV_RVC_BRANCH
, /* type */
628 true, /* pc_relative */
630 complain_overflow_signed
, /* complain_on_overflow */
631 bfd_elf_generic_reloc
, /* special_function */
632 "R_RISCV_RVC_BRANCH", /* name */
633 false, /* partial_inplace */
635 ENCODE_CBTYPE_IMM (-1U), /* dst_mask */
636 true), /* pcrel_offset */
638 /* 11-bit PC-relative jump offset. */
639 HOWTO (R_RISCV_RVC_JUMP
, /* type */
643 true, /* pc_relative */
645 complain_overflow_dont
, /* complain_on_overflow */
646 bfd_elf_generic_reloc
, /* special_function */
647 "R_RISCV_RVC_JUMP", /* name */
648 false, /* partial_inplace */
650 ENCODE_CJTYPE_IMM (-1U), /* dst_mask */
651 true), /* pcrel_offset */
659 /* The paired relocation may be relaxed. */
660 HOWTO (R_RISCV_RELAX
, /* type */
664 false, /* pc_relative */
666 complain_overflow_dont
, /* complain_on_overflow */
667 bfd_elf_generic_reloc
, /* special_function */
668 "R_RISCV_RELAX", /* name */
669 false, /* partial_inplace */
672 false), /* pcrel_offset */
674 /* 6-bit in-place addition, for local label subtraction. */
675 HOWTO (R_RISCV_SUB6
, /* type */
679 false, /* pc_relative */
681 complain_overflow_dont
, /* complain_on_overflow */
682 riscv_elf_add_sub_reloc
, /* special_function */
683 "R_RISCV_SUB6", /* name */
684 false, /* partial_inplace */
687 false), /* pcrel_offset */
689 /* 6-bit in-place setting, for local label subtraction. */
690 HOWTO (R_RISCV_SET6
, /* type */
694 false, /* pc_relative */
696 complain_overflow_dont
, /* complain_on_overflow */
697 bfd_elf_generic_reloc
, /* special_function */
698 "R_RISCV_SET6", /* name */
699 false, /* partial_inplace */
702 false), /* pcrel_offset */
704 /* 8-bit in-place setting, for local label subtraction. */
705 HOWTO (R_RISCV_SET8
, /* type */
709 false, /* pc_relative */
711 complain_overflow_dont
, /* complain_on_overflow */
712 bfd_elf_generic_reloc
, /* special_function */
713 "R_RISCV_SET8", /* name */
714 false, /* partial_inplace */
717 false), /* pcrel_offset */
719 /* 16-bit in-place setting, for local label subtraction. */
720 HOWTO (R_RISCV_SET16
, /* type */
724 false, /* pc_relative */
726 complain_overflow_dont
, /* complain_on_overflow */
727 bfd_elf_generic_reloc
, /* special_function */
728 "R_RISCV_SET16", /* name */
729 false, /* partial_inplace */
731 0xffff, /* dst_mask */
732 false), /* pcrel_offset */
734 /* 32-bit in-place setting, for local label subtraction. */
735 HOWTO (R_RISCV_SET32
, /* type */
739 false, /* pc_relative */
741 complain_overflow_dont
, /* complain_on_overflow */
742 bfd_elf_generic_reloc
, /* special_function */
743 "R_RISCV_SET32", /* name */
744 false, /* partial_inplace */
746 0xffffffff, /* dst_mask */
747 false), /* pcrel_offset */
749 /* 32-bit PC relative. */
750 HOWTO (R_RISCV_32_PCREL
, /* type */
754 true, /* pc_relative */
756 complain_overflow_dont
, /* complain_on_overflow */
757 bfd_elf_generic_reloc
, /* special_function */
758 "R_RISCV_32_PCREL", /* name */
759 false, /* partial_inplace */
761 0xffffffff, /* dst_mask */
762 false), /* pcrel_offset */
764 /* Relocation against a local ifunc symbol in a shared object. */
765 HOWTO (R_RISCV_IRELATIVE
, /* type */
769 false, /* pc_relative */
771 complain_overflow_dont
, /* complain_on_overflow */
772 bfd_elf_generic_reloc
, /* special_function */
773 "R_RISCV_IRELATIVE", /* name */
774 false, /* partial_inplace */
776 0xffffffff, /* dst_mask */
777 false), /* pcrel_offset */
779 /* Reserved for R_RISCV_PLT32. */
782 /* N-bit in-place setting, for unsigned-leb128 local label subtraction. */
783 HOWTO (R_RISCV_SET_ULEB128
, /* type */
787 false, /* pc_relative */
789 complain_overflow_dont
, /* complain_on_overflow */
790 riscv_elf_ignore_reloc
, /* special_function */
791 "R_RISCV_SET_ULEB128", /* name */
792 false, /* partial_inplace */
795 false), /* pcrel_offset */
797 /* N-bit in-place addition, for unsigned-leb128 local label subtraction. */
798 HOWTO (R_RISCV_SUB_ULEB128
, /* type */
802 false, /* pc_relative */
804 complain_overflow_dont
, /* complain_on_overflow */
805 riscv_elf_ignore_reloc
, /* special_function */
806 "R_RISCV_SUB_ULEB128", /* name */
807 false, /* partial_inplace */
810 false), /* pcrel_offset */
813 static reloc_howto_type howto_table_internal
[] =
815 /* R_RISCV_DELETE. */
818 /* High 6 bits of 18-bit absolute address. */
819 HOWTO (R_RISCV_RVC_LUI
, /* type */
823 false, /* pc_relative */
825 complain_overflow_dont
, /* complain_on_overflow */
826 bfd_elf_generic_reloc
, /* special_function */
827 "R_RISCV_RVC_LUI", /* name */
828 false, /* partial_inplace */
830 ENCODE_CITYPE_IMM (-1U), /* dst_mask */
831 false), /* pcrel_offset */
833 /* GP-relative load. */
834 HOWTO (R_RISCV_GPREL_I
, /* type */
838 false, /* pc_relative */
840 complain_overflow_dont
, /* complain_on_overflow */
841 bfd_elf_generic_reloc
, /* special_function */
842 "R_RISCV_GPREL_I", /* name */
843 false, /* partial_inplace */
845 ENCODE_ITYPE_IMM (-1U), /* dst_mask */
846 false), /* pcrel_offset */
848 /* GP-relative store. */
849 HOWTO (R_RISCV_GPREL_S
, /* type */
853 false, /* pc_relative */
855 complain_overflow_dont
, /* complain_on_overflow */
856 bfd_elf_generic_reloc
, /* special_function */
857 "R_RISCV_GPREL_S", /* name */
858 false, /* partial_inplace */
860 ENCODE_STYPE_IMM (-1U), /* dst_mask */
861 false), /* pcrel_offset */
863 /* TP-relative TLS LE load. */
864 HOWTO (R_RISCV_TPREL_I
, /* type */
868 false, /* pc_relative */
870 complain_overflow_signed
, /* complain_on_overflow */
871 bfd_elf_generic_reloc
, /* special_function */
872 "R_RISCV_TPREL_I", /* name */
873 false, /* partial_inplace */
875 ENCODE_ITYPE_IMM (-1U), /* dst_mask */
876 false), /* pcrel_offset */
878 /* TP-relative TLS LE store. */
879 HOWTO (R_RISCV_TPREL_S
, /* type */
883 false, /* pc_relative */
885 complain_overflow_signed
, /* complain_on_overflow */
886 bfd_elf_generic_reloc
, /* special_function */
887 "R_RISCV_TPREL_S", /* name */
888 false, /* partial_inplace */
890 ENCODE_STYPE_IMM (-1U), /* dst_mask */
891 false), /* pcrel_offset */
894 /* A mapping from BFD reloc types to RISC-V ELF reloc types. */
897 bfd_reloc_code_real_type bfd_val
;
898 enum elf_riscv_reloc_type elf_val
;
901 static const struct elf_reloc_map riscv_reloc_map
[] =
903 { BFD_RELOC_NONE
, R_RISCV_NONE
},
904 { BFD_RELOC_32
, R_RISCV_32
},
905 { BFD_RELOC_64
, R_RISCV_64
},
906 { BFD_RELOC_RISCV_ADD8
, R_RISCV_ADD8
},
907 { BFD_RELOC_RISCV_ADD16
, R_RISCV_ADD16
},
908 { BFD_RELOC_RISCV_ADD32
, R_RISCV_ADD32
},
909 { BFD_RELOC_RISCV_ADD64
, R_RISCV_ADD64
},
910 { BFD_RELOC_RISCV_SUB8
, R_RISCV_SUB8
},
911 { BFD_RELOC_RISCV_SUB16
, R_RISCV_SUB16
},
912 { BFD_RELOC_RISCV_SUB32
, R_RISCV_SUB32
},
913 { BFD_RELOC_RISCV_SUB64
, R_RISCV_SUB64
},
914 { BFD_RELOC_CTOR
, R_RISCV_64
},
915 { BFD_RELOC_12_PCREL
, R_RISCV_BRANCH
},
916 { BFD_RELOC_RISCV_HI20
, R_RISCV_HI20
},
917 { BFD_RELOC_RISCV_LO12_I
, R_RISCV_LO12_I
},
918 { BFD_RELOC_RISCV_LO12_S
, R_RISCV_LO12_S
},
919 { BFD_RELOC_RISCV_PCREL_LO12_I
, R_RISCV_PCREL_LO12_I
},
920 { BFD_RELOC_RISCV_PCREL_LO12_S
, R_RISCV_PCREL_LO12_S
},
921 { BFD_RELOC_RISCV_CALL
, R_RISCV_CALL
},
922 { BFD_RELOC_RISCV_CALL_PLT
, R_RISCV_CALL_PLT
},
923 { BFD_RELOC_RISCV_PCREL_HI20
, R_RISCV_PCREL_HI20
},
924 { BFD_RELOC_RISCV_JMP
, R_RISCV_JAL
},
925 { BFD_RELOC_RISCV_GOT_HI20
, R_RISCV_GOT_HI20
},
926 { BFD_RELOC_RISCV_TLS_DTPMOD32
, R_RISCV_TLS_DTPMOD32
},
927 { BFD_RELOC_RISCV_TLS_DTPREL32
, R_RISCV_TLS_DTPREL32
},
928 { BFD_RELOC_RISCV_TLS_DTPMOD64
, R_RISCV_TLS_DTPMOD64
},
929 { BFD_RELOC_RISCV_TLS_DTPREL64
, R_RISCV_TLS_DTPREL64
},
930 { BFD_RELOC_RISCV_TLS_TPREL32
, R_RISCV_TLS_TPREL32
},
931 { BFD_RELOC_RISCV_TLS_TPREL64
, R_RISCV_TLS_TPREL64
},
932 { BFD_RELOC_RISCV_TPREL_HI20
, R_RISCV_TPREL_HI20
},
933 { BFD_RELOC_RISCV_TPREL_ADD
, R_RISCV_TPREL_ADD
},
934 { BFD_RELOC_RISCV_TPREL_LO12_S
, R_RISCV_TPREL_LO12_S
},
935 { BFD_RELOC_RISCV_TPREL_LO12_I
, R_RISCV_TPREL_LO12_I
},
936 { BFD_RELOC_RISCV_TLS_GOT_HI20
, R_RISCV_TLS_GOT_HI20
},
937 { BFD_RELOC_RISCV_TLS_GD_HI20
, R_RISCV_TLS_GD_HI20
},
938 { BFD_RELOC_RISCV_ALIGN
, R_RISCV_ALIGN
},
939 { BFD_RELOC_RISCV_RVC_BRANCH
, R_RISCV_RVC_BRANCH
},
940 { BFD_RELOC_RISCV_RVC_JUMP
, R_RISCV_RVC_JUMP
},
941 { BFD_RELOC_RISCV_RELAX
, R_RISCV_RELAX
},
942 { BFD_RELOC_RISCV_SUB6
, R_RISCV_SUB6
},
943 { BFD_RELOC_RISCV_SET6
, R_RISCV_SET6
},
944 { BFD_RELOC_RISCV_SET8
, R_RISCV_SET8
},
945 { BFD_RELOC_RISCV_SET16
, R_RISCV_SET16
},
946 { BFD_RELOC_RISCV_SET32
, R_RISCV_SET32
},
947 { BFD_RELOC_RISCV_32_PCREL
, R_RISCV_32_PCREL
},
948 { BFD_RELOC_RISCV_SET_ULEB128
, R_RISCV_SET_ULEB128
},
949 { BFD_RELOC_RISCV_SUB_ULEB128
, R_RISCV_SUB_ULEB128
},
952 /* Given a BFD reloc type, return a howto structure. */
955 riscv_reloc_type_lookup (bfd
*abfd ATTRIBUTE_UNUSED
,
956 bfd_reloc_code_real_type code
)
960 for (i
= 0; i
< ARRAY_SIZE (riscv_reloc_map
); i
++)
961 if (riscv_reloc_map
[i
].bfd_val
== code
)
962 return &howto_table
[(int) riscv_reloc_map
[i
].elf_val
];
964 bfd_set_error (bfd_error_bad_value
);
969 riscv_reloc_name_lookup (bfd
*abfd ATTRIBUTE_UNUSED
, const char *r_name
)
973 for (i
= 0; i
< ARRAY_SIZE (howto_table
); i
++)
974 if (howto_table
[i
].name
&& strcasecmp (howto_table
[i
].name
, r_name
) == 0)
975 return &howto_table
[i
];
981 riscv_elf_rtype_to_howto (bfd
*abfd
, unsigned int r_type
)
983 if (r_type
< ARRAY_SIZE (howto_table
))
984 return &howto_table
[r_type
];
985 else if (r_type
< R_RISCV_max
+ ARRAY_SIZE (howto_table_internal
))
986 return &howto_table_internal
[r_type
- R_RISCV_max
];
989 (*_bfd_error_handler
) (_("%pB: unsupported relocation type %#x"),
991 bfd_set_error (bfd_error_bad_value
);
996 /* Special_function of RISCV_ADD and RISCV_SUB relocations. */
998 static bfd_reloc_status_type
999 riscv_elf_add_sub_reloc (bfd
*abfd
,
1000 arelent
*reloc_entry
,
1003 asection
*input_section
,
1005 char **error_message ATTRIBUTE_UNUSED
)
1007 reloc_howto_type
*howto
= reloc_entry
->howto
;
1010 if (output_bfd
!= NULL
1011 && (symbol
->flags
& BSF_SECTION_SYM
) == 0
1012 && (!reloc_entry
->howto
->partial_inplace
|| reloc_entry
->addend
== 0))
1014 reloc_entry
->address
+= input_section
->output_offset
;
1015 return bfd_reloc_ok
;
1018 if (output_bfd
!= NULL
)
1019 return bfd_reloc_continue
;
1021 relocation
= symbol
->value
+ symbol
->section
->output_section
->vma
1022 + symbol
->section
->output_offset
+ reloc_entry
->addend
;
1024 bfd_size_type octets
= reloc_entry
->address
1025 * bfd_octets_per_byte (abfd
, input_section
);
1026 if (!bfd_reloc_offset_in_range (reloc_entry
->howto
, abfd
,
1027 input_section
, octets
))
1028 return bfd_reloc_outofrange
;
1030 bfd_vma old_value
= bfd_get (howto
->bitsize
, abfd
,
1031 data
+ reloc_entry
->address
);
1033 switch (howto
->type
)
1039 relocation
= old_value
+ relocation
;
1042 relocation
= (old_value
& ~howto
->dst_mask
)
1043 | (((old_value
& howto
->dst_mask
) - relocation
)
1050 relocation
= old_value
- relocation
;
1053 bfd_put (howto
->bitsize
, abfd
, relocation
, data
+ reloc_entry
->address
);
1055 return bfd_reloc_ok
;
1058 /* Special handler for relocations which don't have to be relocated.
1059 This function just simply return bfd_reloc_ok. */
1061 static bfd_reloc_status_type
1062 riscv_elf_ignore_reloc (bfd
*abfd ATTRIBUTE_UNUSED
,
1063 arelent
*reloc_entry
,
1064 asymbol
*symbol ATTRIBUTE_UNUSED
,
1065 void *data ATTRIBUTE_UNUSED
,
1066 asection
*input_section
,
1068 char **error_message ATTRIBUTE_UNUSED
)
1070 if (output_bfd
!= NULL
)
1071 reloc_entry
->address
+= input_section
->output_offset
;
1072 return bfd_reloc_ok
;
1075 /* Always add the IMPLICIT for the SUBSET. */
1078 check_implicit_always (const char *implicit ATTRIBUTE_UNUSED
,
1079 riscv_subset_t
*subset ATTRIBUTE_UNUSED
)
1084 /* Add the IMPLICIT only when the version of SUBSET less than 2.1. */
1087 check_implicit_for_i (const char *implicit ATTRIBUTE_UNUSED
,
1088 riscv_subset_t
*subset
)
1090 return (subset
->major_version
< 2
1091 || (subset
->major_version
== 2
1092 && subset
->minor_version
< 1));
1095 /* Record all implicit information for the subsets. */
1096 struct riscv_implicit_subset
1098 const char *subset_name
;
1099 const char *implicit_name
;
1100 /* A function to determine if we need to add the implicit subset. */
1101 bool (*check_func
) (const char *, riscv_subset_t
*);
1103 static struct riscv_implicit_subset riscv_implicit_subsets
[] =
1105 {"e", "i", check_implicit_always
},
1106 {"i", "zicsr", check_implicit_for_i
},
1107 {"i", "zifencei", check_implicit_for_i
},
1108 {"g", "i", check_implicit_always
},
1109 {"g", "m", check_implicit_always
},
1110 {"g", "a", check_implicit_always
},
1111 {"g", "f", check_implicit_always
},
1112 {"g", "d", check_implicit_always
},
1113 {"g", "zicsr", check_implicit_always
},
1114 {"g", "zifencei", check_implicit_always
},
1115 {"m", "zmmul", check_implicit_always
},
1116 {"h", "zicsr", check_implicit_always
},
1117 {"q", "d", check_implicit_always
},
1118 {"v", "d", check_implicit_always
},
1119 {"v", "zve64d", check_implicit_always
},
1120 {"v", "zvl128b", check_implicit_always
},
1121 {"zvfh", "zvfhmin", check_implicit_always
},
1122 {"zvfh", "zfhmin", check_implicit_always
},
1123 {"zvfhmin", "zve32f", check_implicit_always
},
1124 {"zve64d", "d", check_implicit_always
},
1125 {"zve64d", "zve64f", check_implicit_always
},
1126 {"zve64f", "zve32f", check_implicit_always
},
1127 {"zve64f", "zve64x", check_implicit_always
},
1128 {"zve64f", "zvl64b", check_implicit_always
},
1129 {"zve32f", "f", check_implicit_always
},
1130 {"zve32f", "zvl32b", check_implicit_always
},
1131 {"zve32f", "zve32x", check_implicit_always
},
1132 {"zve64x", "zve32x", check_implicit_always
},
1133 {"zve64x", "zvl64b", check_implicit_always
},
1134 {"zve32x", "zvl32b", check_implicit_always
},
1135 {"zve32x", "zicsr", check_implicit_always
},
1136 {"zvl65536b", "zvl32768b", check_implicit_always
},
1137 {"zvl32768b", "zvl16384b", check_implicit_always
},
1138 {"zvl16384b", "zvl8192b", check_implicit_always
},
1139 {"zvl8192b", "zvl4096b", check_implicit_always
},
1140 {"zvl4096b", "zvl2048b", check_implicit_always
},
1141 {"zvl2048b", "zvl1024b", check_implicit_always
},
1142 {"zvl1024b", "zvl512b", check_implicit_always
},
1143 {"zvl512b", "zvl256b", check_implicit_always
},
1144 {"zvl256b", "zvl128b", check_implicit_always
},
1145 {"zvl128b", "zvl64b", check_implicit_always
},
1146 {"zvl64b", "zvl32b", check_implicit_always
},
1147 {"zicntr", "zicsr", check_implicit_always
},
1148 {"zihpm", "zicsr", check_implicit_always
},
1149 {"zcd", "d", check_implicit_always
},
1150 {"zcf", "f", check_implicit_always
},
1151 {"zfa", "f", check_implicit_always
},
1152 {"d", "f", check_implicit_always
},
1153 {"zfh", "zfhmin", check_implicit_always
},
1154 {"zfhmin", "f", check_implicit_always
},
1155 {"f", "zicsr", check_implicit_always
},
1156 {"zqinx", "zdinx", check_implicit_always
},
1157 {"zdinx", "zfinx", check_implicit_always
},
1158 {"zhinx", "zhinxmin", check_implicit_always
},
1159 {"zhinxmin", "zfinx", check_implicit_always
},
1160 {"zfinx", "zicsr", check_implicit_always
},
1161 {"zk", "zkn", check_implicit_always
},
1162 {"zk", "zkr", check_implicit_always
},
1163 {"zk", "zkt", check_implicit_always
},
1164 {"zkn", "zbkb", check_implicit_always
},
1165 {"zkn", "zbkc", check_implicit_always
},
1166 {"zkn", "zbkx", check_implicit_always
},
1167 {"zkn", "zkne", check_implicit_always
},
1168 {"zkn", "zknd", check_implicit_always
},
1169 {"zkn", "zknh", check_implicit_always
},
1170 {"zks", "zbkb", check_implicit_always
},
1171 {"zks", "zbkc", check_implicit_always
},
1172 {"zks", "zbkx", check_implicit_always
},
1173 {"zks", "zksed", check_implicit_always
},
1174 {"zks", "zksh", check_implicit_always
},
1175 {"zvbb", "zvkb", check_implicit_always
},
1176 {"zvkn", "zvkned", check_implicit_always
},
1177 {"zvkn", "zvknha", check_implicit_always
},
1178 {"zvkn", "zvknhb", check_implicit_always
},
1179 {"zvkn", "zvkb", check_implicit_always
},
1180 {"zvkn", "zvkt", check_implicit_always
},
1181 {"zvkng", "zvkn", check_implicit_always
},
1182 {"zvkng", "zvkg", check_implicit_always
},
1183 {"zvknc", "zvkn", check_implicit_always
},
1184 {"zvknc", "zvbc", check_implicit_always
},
1185 {"zvks", "zvksed", check_implicit_always
},
1186 {"zvks", "zvksh", check_implicit_always
},
1187 {"zvks", "zvkb", check_implicit_always
},
1188 {"zvks", "zvkt", check_implicit_always
},
1189 {"zvksg", "zvks", check_implicit_always
},
1190 {"zvksg", "zvkg", check_implicit_always
},
1191 {"zvksc", "zvks", check_implicit_always
},
1192 {"zvksc", "zvbc", check_implicit_always
},
1193 {"zcf", "zca", check_implicit_always
},
1194 {"zcd", "zca", check_implicit_always
},
1195 {"zcb", "zca", check_implicit_always
},
1196 {"smaia", "ssaia", check_implicit_always
},
1197 {"smcntrpmf", "zicsr", check_implicit_always
},
1198 {"smstateen", "ssstateen", check_implicit_always
},
1199 {"smepmp", "zicsr", check_implicit_always
},
1200 {"ssaia", "zicsr", check_implicit_always
},
1201 {"sscofpmf", "zicsr", check_implicit_always
},
1202 {"ssstateen", "zicsr", check_implicit_always
},
1203 {"sstc", "zicsr", check_implicit_always
},
1204 {"svadu", "zicsr", check_implicit_always
},
1206 {"xsfvcp", "zve32x", check_implicit_always
},
1210 /* For default_enable field, decide if the extension should
1211 be enbaled by default. */
1213 #define EXT_DEFAULT 0x1
1215 /* List all extensions that binutils should know about. */
1217 struct riscv_supported_ext
1220 enum riscv_spec_class isa_spec_class
;
1223 unsigned long default_enable
;
1226 /* The standard extensions must be added in canonical order. */
1228 static struct riscv_supported_ext riscv_supported_std_ext
[] =
1230 {"e", ISA_SPEC_CLASS_20191213
, 1, 9, 0 },
1231 {"e", ISA_SPEC_CLASS_20190608
, 1, 9, 0 },
1232 {"e", ISA_SPEC_CLASS_2P2
, 1, 9, 0 },
1233 {"i", ISA_SPEC_CLASS_20191213
, 2, 1, 0 },
1234 {"i", ISA_SPEC_CLASS_20190608
, 2, 1, 0 },
1235 {"i", ISA_SPEC_CLASS_2P2
, 2, 0, 0 },
1236 /* The g is a special case which we don't want to output it,
1237 but still need it when adding implicit extensions. */
1238 {"g", ISA_SPEC_CLASS_NONE
, RISCV_UNKNOWN_VERSION
, RISCV_UNKNOWN_VERSION
, EXT_DEFAULT
},
1239 {"m", ISA_SPEC_CLASS_20191213
, 2, 0, 0 },
1240 {"m", ISA_SPEC_CLASS_20190608
, 2, 0, 0 },
1241 {"m", ISA_SPEC_CLASS_2P2
, 2, 0, 0 },
1242 {"a", ISA_SPEC_CLASS_20191213
, 2, 1, 0 },
1243 {"a", ISA_SPEC_CLASS_20190608
, 2, 0, 0 },
1244 {"a", ISA_SPEC_CLASS_2P2
, 2, 0, 0 },
1245 {"f", ISA_SPEC_CLASS_20191213
, 2, 2, 0 },
1246 {"f", ISA_SPEC_CLASS_20190608
, 2, 2, 0 },
1247 {"f", ISA_SPEC_CLASS_2P2
, 2, 0, 0 },
1248 {"d", ISA_SPEC_CLASS_20191213
, 2, 2, 0 },
1249 {"d", ISA_SPEC_CLASS_20190608
, 2, 2, 0 },
1250 {"d", ISA_SPEC_CLASS_2P2
, 2, 0, 0 },
1251 {"q", ISA_SPEC_CLASS_20191213
, 2, 2, 0 },
1252 {"q", ISA_SPEC_CLASS_20190608
, 2, 2, 0 },
1253 {"q", ISA_SPEC_CLASS_2P2
, 2, 0, 0 },
1254 {"c", ISA_SPEC_CLASS_20191213
, 2, 0, 0 },
1255 {"c", ISA_SPEC_CLASS_20190608
, 2, 0, 0 },
1256 {"c", ISA_SPEC_CLASS_2P2
, 2, 0, 0 },
1257 {"v", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1258 {"h", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1262 static struct riscv_supported_ext riscv_supported_std_z_ext
[] =
1264 {"zicbom", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1265 {"zicbop", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1266 {"zicboz", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1267 {"zicond", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1268 {"zicntr", ISA_SPEC_CLASS_DRAFT
, 2, 0, 0 },
1269 {"zicsr", ISA_SPEC_CLASS_20191213
, 2, 0, 0 },
1270 {"zicsr", ISA_SPEC_CLASS_20190608
, 2, 0, 0 },
1271 {"zifencei", ISA_SPEC_CLASS_20191213
, 2, 0, 0 },
1272 {"zifencei", ISA_SPEC_CLASS_20190608
, 2, 0, 0 },
1273 {"zihintntl", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1274 {"zihintpause", ISA_SPEC_CLASS_DRAFT
, 2, 0, 0 },
1275 {"zihpm", ISA_SPEC_CLASS_DRAFT
, 2, 0, 0 },
1276 {"zmmul", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1277 {"zawrs", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1278 {"zfa", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1279 {"zfh", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1280 {"zfhmin", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1281 {"zfinx", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1282 {"zdinx", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1283 {"zqinx", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1284 {"zhinx", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1285 {"zhinxmin", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1286 {"zbb", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1287 {"zba", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1288 {"zbc", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1289 {"zbs", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1290 {"zbkb", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1291 {"zbkc", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1292 {"zbkx", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1293 {"zk", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1294 {"zkn", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1295 {"zknd", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1296 {"zkne", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1297 {"zknh", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1298 {"zkr", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1299 {"zks", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1300 {"zksed", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1301 {"zksh", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1302 {"zkt", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1303 {"zve32x", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1304 {"zve32f", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1305 {"zve64x", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1306 {"zve64f", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1307 {"zve64d", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1308 {"zvbb", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1309 {"zvbc", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1310 {"zvfh", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1311 {"zvfhmin", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1312 {"zvkb", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1313 {"zvkg", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1314 {"zvkn", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1315 {"zvkng", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1316 {"zvknc", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1317 {"zvkned", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1318 {"zvknha", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1319 {"zvknhb", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1320 {"zvksed", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1321 {"zvksh", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1322 {"zvks", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1323 {"zvksg", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1324 {"zvksc", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1325 {"zvkt", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1326 {"zvl32b", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1327 {"zvl64b", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1328 {"zvl128b", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1329 {"zvl256b", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1330 {"zvl512b", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1331 {"zvl1024b", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1332 {"zvl2048b", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1333 {"zvl4096b", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1334 {"zvl8192b", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1335 {"zvl16384b", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1336 {"zvl32768b", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1337 {"zvl65536b", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1338 {"ztso", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1339 {"zca", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1340 {"zcb", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1341 {"zcf", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1342 {"zcd", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1346 static struct riscv_supported_ext riscv_supported_std_s_ext
[] =
1348 {"smaia", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1349 {"smcntrpmf", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1350 {"smepmp", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1351 {"smstateen", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1352 {"ssaia", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1353 {"sscofpmf", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1354 {"ssstateen", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1355 {"sstc", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1356 {"svadu", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1357 {"svinval", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1358 {"svnapot", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1359 {"svpbmt", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1363 static struct riscv_supported_ext riscv_supported_std_zxm_ext
[] =
1368 static struct riscv_supported_ext riscv_supported_vendor_x_ext
[] =
1370 {"xcvmac", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1371 {"xcvalu", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1372 {"xtheadba", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1373 {"xtheadbb", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1374 {"xtheadbs", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1375 {"xtheadcmo", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1376 {"xtheadcondmov", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1377 {"xtheadfmemidx", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1378 {"xtheadfmv", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1379 {"xtheadint", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1380 {"xtheadmac", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1381 {"xtheadmemidx", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1382 {"xtheadmempair", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1383 {"xtheadsync", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1384 {"xtheadvector", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1385 {"xtheadzvamo", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1386 {"xventanacondops", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1387 {"xsfvcp", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0},
1391 const struct riscv_supported_ext
*riscv_all_supported_ext
[] =
1393 riscv_supported_std_ext
,
1394 riscv_supported_std_z_ext
,
1395 riscv_supported_std_s_ext
,
1396 riscv_supported_std_zxm_ext
,
1397 riscv_supported_vendor_x_ext
,
1401 /* ISA extension prefixed name class. Must define them in parsing order. */
1402 enum riscv_prefix_ext_class
1411 /* Record the strings of the prefixed extensions, and their corresponding
1412 classes. The more letters of the prefix string, the more forward it must
1413 be defined. Otherwise, the riscv_get_prefix_class will map it to the
1415 struct riscv_parse_prefix_config
1417 /* Class of the extension. */
1418 enum riscv_prefix_ext_class
class;
1420 /* Prefix string for error printing and internal parser usage. */
1423 static const struct riscv_parse_prefix_config parse_config
[] =
1425 {RV_ISA_CLASS_ZXM
, "zxm"},
1426 {RV_ISA_CLASS_Z
, "z"},
1427 {RV_ISA_CLASS_S
, "s"},
1428 {RV_ISA_CLASS_X
, "x"},
1429 {RV_ISA_CLASS_SINGLE
, NULL
}
1432 /* Get the prefixed name class for the extensions, the class also
1433 means the order of the prefixed extensions. */
1435 static enum riscv_prefix_ext_class
1436 riscv_get_prefix_class (const char *arch
)
1439 while (parse_config
[i
].class != RV_ISA_CLASS_SINGLE
)
1441 if (strncmp (arch
, parse_config
[i
].prefix
,
1442 strlen (parse_config
[i
].prefix
)) == 0)
1443 return parse_config
[i
].class;
1446 return RV_ISA_CLASS_SINGLE
;
1449 /* Check KNOWN_EXTS to see if the EXT is supported. */
1452 riscv_known_prefixed_ext (const char *ext
,
1453 struct riscv_supported_ext
*known_exts
)
1456 for (i
= 0; known_exts
[i
].name
!= NULL
; ++i
)
1457 if (strcmp (ext
, known_exts
[i
].name
) == 0)
1462 /* Check whether the prefixed extension is recognized or not. Return
1463 true if recognized, otehrwise return false. */
1466 riscv_recognized_prefixed_ext (const char *ext
)
1468 enum riscv_prefix_ext_class
class = riscv_get_prefix_class (ext
);
1471 case RV_ISA_CLASS_Z
:
1472 return riscv_known_prefixed_ext (ext
, riscv_supported_std_z_ext
);
1473 case RV_ISA_CLASS_ZXM
:
1474 return riscv_known_prefixed_ext (ext
, riscv_supported_std_zxm_ext
);
1475 case RV_ISA_CLASS_S
:
1476 return riscv_known_prefixed_ext (ext
, riscv_supported_std_s_ext
);
1477 case RV_ISA_CLASS_X
:
1478 /* Only the single x is unrecognized. */
1479 if (strcmp (ext
, "x") != 0)
1487 /* Canonical order for single letter extensions. */
1488 static const char riscv_ext_canonical_order
[] = "eigmafdqlcbkjtpvnh";
1490 /* Array is used to compare the orders of standard extensions quickly. */
1491 static int riscv_ext_order
[26] = {0};
1493 /* Init the riscv_ext_order array. */
1496 riscv_init_ext_order (void)
1498 static bool inited
= false;
1502 /* The orders of all standard extensions are positive. */
1505 for (const char *ext
= &riscv_ext_canonical_order
[0]; *ext
; ++ext
)
1506 riscv_ext_order
[(*ext
- 'a')] = order
++;
1508 /* Some of the prefixed keyword are not single letter, so we set
1509 their prefixed orders in the riscv_compare_subsets directly,
1510 not through the riscv_ext_order. */
1515 /* Similar to the strcmp. It returns an integer less than, equal to,
1516 or greater than zero if `subset2` is found, respectively, to be less
1517 than, to match, or be greater than `subset1`.
1520 Zero: Preserved keywords.
1521 Positive number: Standard extensions.
1522 Negative number: Prefixed keywords. */
1525 riscv_compare_subsets (const char *subset1
, const char *subset2
)
1527 int order1
= riscv_ext_order
[(*subset1
- 'a')];
1528 int order2
= riscv_ext_order
[(*subset2
- 'a')];
1530 /* Compare the standard extension first. */
1531 if (order1
> 0 && order2
> 0)
1532 return order1
- order2
;
1534 /* Set the prefixed orders to negative numbers. */
1535 enum riscv_prefix_ext_class class1
= riscv_get_prefix_class (subset1
);
1536 enum riscv_prefix_ext_class class2
= riscv_get_prefix_class (subset2
);
1538 if (class1
!= RV_ISA_CLASS_SINGLE
)
1539 order1
= - (int) class1
;
1540 if (class2
!= RV_ISA_CLASS_SINGLE
)
1541 order2
= - (int) class2
;
1543 if (order1
== order2
)
1545 /* Compare the standard addition z extensions. */
1546 if (class1
== RV_ISA_CLASS_Z
)
1548 order1
= riscv_ext_order
[(*++subset1
- 'a')];
1549 order2
= riscv_ext_order
[(*++subset2
- 'a')];
1550 if (order1
!= order2
)
1551 return order1
- order2
;
1553 return strcasecmp (++subset1
, ++subset2
);
1556 return order2
- order1
;
1559 /* Find subset in the list. Return TRUE and set `current` to the subset
1560 if it is found. Otherwise, return FALSE and set `current` to the place
1561 where we should insert the subset. However, return FALSE with the NULL
1562 `current` means we should insert the subset at the head of subset list,
1566 riscv_lookup_subset (const riscv_subset_list_t
*subset_list
,
1568 riscv_subset_t
**current
)
1570 riscv_subset_t
*s
, *pre_s
= NULL
;
1572 /* If the subset is added in order, then just add it at the tail. */
1573 if (subset_list
->tail
!= NULL
1574 && riscv_compare_subsets (subset_list
->tail
->name
, subset
) < 0)
1576 *current
= subset_list
->tail
;
1580 for (s
= subset_list
->head
;
1582 pre_s
= s
, s
= s
->next
)
1584 int cmp
= riscv_compare_subsets (s
->name
, subset
);
1598 /* Add the extension to the subset list. Search the
1599 list first, and then find the right place to add. */
1602 riscv_add_subset (riscv_subset_list_t
*subset_list
,
1607 riscv_subset_t
*current
, *new;
1609 if (riscv_lookup_subset (subset_list
, subset
, ¤t
))
1612 new = xmalloc (sizeof *new);
1613 new->name
= xstrdup (subset
);
1614 new->major_version
= major
;
1615 new->minor_version
= minor
;
1618 if (current
!= NULL
)
1620 new->next
= current
->next
;
1621 current
->next
= new;
1625 new->next
= subset_list
->head
;
1626 subset_list
->head
= new;
1629 if (new->next
== NULL
)
1630 subset_list
->tail
= new;
1633 /* Get the default versions from the riscv_supported_*ext tables. */
1636 riscv_get_default_ext_version (enum riscv_spec_class
*default_isa_spec
,
1642 || default_isa_spec
== NULL
1643 || *default_isa_spec
== ISA_SPEC_CLASS_NONE
)
1646 struct riscv_supported_ext
*table
= NULL
;
1647 enum riscv_prefix_ext_class
class = riscv_get_prefix_class (name
);
1650 case RV_ISA_CLASS_ZXM
: table
= riscv_supported_std_zxm_ext
; break;
1651 case RV_ISA_CLASS_Z
: table
= riscv_supported_std_z_ext
; break;
1652 case RV_ISA_CLASS_S
: table
= riscv_supported_std_s_ext
; break;
1653 case RV_ISA_CLASS_X
: table
= riscv_supported_vendor_x_ext
; break;
1655 table
= riscv_supported_std_ext
;
1659 while (table
!= NULL
&& table
[i
].name
!= NULL
)
1661 if (strcmp (table
[i
].name
, name
) == 0
1662 && (table
[i
].isa_spec_class
== ISA_SPEC_CLASS_DRAFT
1663 || table
[i
].isa_spec_class
== *default_isa_spec
))
1665 *major_version
= table
[i
].major_version
;
1666 *minor_version
= table
[i
].minor_version
;
1673 /* Find the default versions for the extension before adding them to
1674 the subset list, if their versions are RISCV_UNKNOWN_VERSION.
1675 Afterwards, report errors if we can not find their default versions. */
1678 riscv_parse_add_subset (riscv_parse_subset_t
*rps
,
1684 int major_version
= major
;
1685 int minor_version
= minor
;
1687 if (major_version
== RISCV_UNKNOWN_VERSION
1688 || minor_version
== RISCV_UNKNOWN_VERSION
)
1689 riscv_get_default_ext_version (rps
->isa_spec
, subset
,
1690 &major_version
, &minor_version
);
1692 /* We don't care the versions of the implicit extensions. */
1694 && (major_version
== RISCV_UNKNOWN_VERSION
1695 || minor_version
== RISCV_UNKNOWN_VERSION
))
1697 if (subset
[0] == 'x')
1699 (_("x ISA extension `%s' must be set with the versions"),
1701 /* Allow old ISA spec can recognize zicsr and zifencei. */
1702 else if (strcmp (subset
, "zicsr") != 0
1703 && strcmp (subset
, "zifencei") != 0)
1705 (_("cannot find default versions of the ISA extension `%s'"),
1710 riscv_add_subset (rps
->subset_list
, subset
,
1711 major_version
, minor_version
);
1714 /* Release subset list. */
1717 riscv_release_subset_list (riscv_subset_list_t
*subset_list
)
1719 while (subset_list
->head
!= NULL
)
1721 riscv_subset_t
*next
= subset_list
->head
->next
;
1722 free ((void *)subset_list
->head
->name
);
1723 free (subset_list
->head
);
1724 subset_list
->head
= next
;
1727 subset_list
->tail
= NULL
;
1729 if (subset_list
->arch_str
!= NULL
)
1731 free ((void*) subset_list
->arch_str
);
1732 subset_list
->arch_str
= NULL
;
1736 /* Parsing extension version.
1739 Points to the end of version
1742 `p`: Curent parsing position.
1743 `major_version`: Parsed major version.
1744 `minor_version`: Parsed minor version. */
1747 riscv_parsing_subset_version (const char *p
,
1751 bool major_p
= true;
1763 /* Might be beginning of `p` extension. */
1767 *major_version
= version
;
1771 else if (ISDIGIT (*p
))
1772 version
= (version
* 10) + (*p
- '0');
1778 *major_version
= version
;
1780 *minor_version
= version
;
1782 /* We can not find any version in string. */
1783 if (*major_version
== 0 && *minor_version
== 0)
1785 *major_version
= RISCV_UNKNOWN_VERSION
;
1786 *minor_version
= RISCV_UNKNOWN_VERSION
;
1792 /* Parsing function for both standard and prefixed extensions.
1795 Points to the end of extensions.
1798 `rps`: Hooks and status for parsing extensions.
1799 `arch`: Full ISA string.
1800 `p`: Curent parsing position. */
1803 riscv_parse_extensions (riscv_parse_subset_t
*rps
,
1807 /* First letter must start with i, e or g. */
1808 if (*p
!= 'e' && *p
!= 'i' && *p
!= 'g')
1811 (_("%s: first ISA extension must be `e', `i' or `g'"),
1824 char *subset
= xstrdup (p
);
1825 char *q
= subset
; /* Start of version. */
1826 const char *end_of_version
;
1827 bool implicit
= false;
1829 enum riscv_prefix_ext_class
class = riscv_get_prefix_class (p
);
1830 if (class == RV_ISA_CLASS_SINGLE
)
1832 if (riscv_ext_order
[(*subset
- 'a')] == 0)
1835 (_("%s: unknown standard ISA extension or prefix class `%c'"),
1844 /* Extract the whole prefixed extension by '_'. */
1845 while (*++q
!= '\0' && *q
!= '_')
1847 /* Look forward to the first letter which is not <major>p<minor>. */
1848 bool find_any_version
= false;
1849 bool find_minor_version
= false;
1854 find_any_version
= true;
1855 else if (find_any_version
1856 && !find_minor_version
1858 && ISDIGIT (*(q
- 1)))
1859 find_minor_version
= true;
1865 /* Check if the end of extension is 'p' or not. If yes, then
1866 the second letter from the end cannot be number. */
1867 if (*(q
- 1) == 'p' && ISDIGIT (*(q
- 2)))
1871 (_("%s: invalid prefixed ISA extension `%s' ends with <number>p"),
1878 int major_version
= RISCV_UNKNOWN_VERSION
;
1879 int minor_version
= RISCV_UNKNOWN_VERSION
;
1881 riscv_parsing_subset_version (q
, &major_version
, &minor_version
);
1883 if (end_of_version
== NULL
)
1889 /* Check if the prefixed extension name is well-formed. */
1890 if (class != RV_ISA_CLASS_SINGLE
1891 && rps
->check_unknown_prefixed_ext
1892 && !riscv_recognized_prefixed_ext (subset
))
1895 (_("%s: unknown prefixed ISA extension `%s'"),
1901 /* Added g as an implicit extension. */
1902 if (class == RV_ISA_CLASS_SINGLE
1903 && strcmp (subset
, "g") == 0)
1906 major_version
= RISCV_UNKNOWN_VERSION
;
1907 minor_version
= RISCV_UNKNOWN_VERSION
;
1909 riscv_parse_add_subset (rps
, subset
,
1911 minor_version
, implicit
);
1912 p
+= end_of_version
- subset
;
1915 if (class != RV_ISA_CLASS_SINGLE
1916 && *p
!= '\0' && *p
!= '_')
1919 (_("%s: prefixed ISA extension must separate with _"),
1928 /* Add the implicit extensions. */
1931 riscv_parse_add_implicit_subsets (riscv_parse_subset_t
*rps
)
1933 struct riscv_implicit_subset
*t
= riscv_implicit_subsets
;
1934 bool finished
= false;
1938 for (; t
->subset_name
; t
++)
1940 riscv_subset_t
*subset
= NULL
;
1941 riscv_subset_t
*implicit_subset
= NULL
;
1942 if (riscv_lookup_subset (rps
->subset_list
, t
->subset_name
, &subset
)
1943 && !riscv_lookup_subset (rps
->subset_list
, t
->implicit_name
,
1945 && t
->check_func (t
->implicit_name
, subset
))
1947 riscv_parse_add_subset (rps
, t
->implicit_name
,
1948 RISCV_UNKNOWN_VERSION
,
1949 RISCV_UNKNOWN_VERSION
, true);
1951 /* Restart the loop and pick up any new implications. */
1953 t
= riscv_implicit_subsets
;
1960 /* Check extensions conflicts. */
1963 riscv_parse_check_conflicts (riscv_parse_subset_t
*rps
)
1965 riscv_subset_t
*subset
= NULL
;
1966 int xlen
= *rps
->xlen
;
1967 bool no_conflict
= true;
1969 if (riscv_subset_supports (rps
, "e")
1970 && riscv_subset_supports (rps
, "h"))
1973 (_("rv%de does not support the `h' extension"), xlen
);
1974 no_conflict
= false;
1976 if (riscv_lookup_subset (rps
->subset_list
, "q", &subset
)
1977 && (subset
->major_version
< 2 || (subset
->major_version
== 2
1978 && subset
->minor_version
< 2))
1981 rps
->error_handler (_("rv%d does not support the `q' extension"), xlen
);
1982 no_conflict
= false;
1984 if (riscv_lookup_subset (rps
->subset_list
, "zcf", &subset
)
1988 (_("rv%d does not support the `zcf' extension"), xlen
);
1989 no_conflict
= false;
1991 if (riscv_lookup_subset (rps
->subset_list
, "zfinx", &subset
)
1992 && riscv_lookup_subset (rps
->subset_list
, "f", &subset
))
1995 (_("`zfinx' is conflict with the `f/d/q/zfh/zfhmin' extension"));
1996 no_conflict
= false;
1998 if (riscv_lookup_subset (rps
->subset_list
, "xtheadvector", &subset
)
1999 && riscv_lookup_subset (rps
->subset_list
, "v", &subset
))
2002 (_("`xtheadvector' is conflict with the `v' extension"));
2003 no_conflict
= false;
2006 bool support_zve
= false;
2007 bool support_zvl
= false;
2008 riscv_subset_t
*s
= rps
->subset_list
->head
;
2009 for (; s
!= NULL
; s
= s
->next
)
2012 && strncmp (s
->name
, "zve", 3) == 0)
2015 && strncmp (s
->name
, "zvl", 3) == 0)
2017 if (support_zve
&& support_zvl
)
2020 if (support_zvl
&& !support_zve
)
2023 (_("zvl*b extensions need to enable either `v' or `zve' extension"));
2024 no_conflict
= false;
2030 /* Set the default subset list according to the default_enable field
2031 of riscv_supported_*ext tables. */
2034 riscv_set_default_arch (riscv_parse_subset_t
*rps
)
2036 unsigned long enable
= EXT_DEFAULT
;
2038 for (i
= 0; riscv_all_supported_ext
[i
] != NULL
; i
++)
2040 const struct riscv_supported_ext
*table
= riscv_all_supported_ext
[i
];
2041 for (j
= 0; table
[j
].name
!= NULL
; j
++)
2043 bool implicit
= false;
2044 if (strcmp (table
[j
].name
, "g") == 0)
2046 if (table
[j
].default_enable
& enable
)
2047 riscv_parse_add_subset (rps
, table
[j
].name
,
2048 RISCV_UNKNOWN_VERSION
,
2049 RISCV_UNKNOWN_VERSION
, implicit
);
2054 /* Function for parsing ISA string.
2057 Return TRUE on success.
2060 `rps`: Hooks and status for parsing extensions.
2061 `arch`: Full ISA string. */
2064 riscv_parse_subset (riscv_parse_subset_t
*rps
,
2069 /* Init the riscv_ext_order array to compare the order of extensions
2071 riscv_init_ext_order ();
2075 riscv_set_default_arch (rps
);
2076 riscv_parse_add_implicit_subsets (rps
);
2077 return riscv_parse_check_conflicts (rps
);
2080 for (p
= arch
; *p
!= '\0'; p
++)
2085 (_("%s: ISA string cannot contain uppercase letters"),
2092 if (startswith (p
, "rv32"))
2097 else if (startswith (p
, "rv64"))
2104 /* ISA string shouldn't be NULL or empty here. For linker,
2105 it might be empty when we failed to merge the ISA string
2106 in the riscv_merge_attributes. For assembler, we might
2107 give an empty string by .attribute arch, "" or -march=.
2108 However, We have already issued the correct error message
2109 in another side, so do not issue this error when the ISA
2112 rps
->error_handler (
2113 _("%s: ISA string must begin with rv32 or rv64"),
2118 /* Parse single standard and prefixed extensions. */
2119 if (riscv_parse_extensions (rps
, arch
, p
) == NULL
)
2122 /* Finally add implicit extensions according to the current
2124 riscv_parse_add_implicit_subsets (rps
);
2126 /* Check the conflicts. */
2127 return riscv_parse_check_conflicts (rps
);
2130 /* Return the number of digits for the input. */
2133 riscv_estimate_digit (unsigned num
)
2139 for (digit
= 0; num
; num
/= 10)
2145 /* Auxiliary function to estimate string length of subset list. */
2148 riscv_estimate_arch_strlen1 (const riscv_subset_t
*subset
)
2151 return 6; /* For rv32/rv64/rv128 and string terminator. */
2153 return riscv_estimate_arch_strlen1 (subset
->next
)
2154 + strlen (subset
->name
)
2155 + riscv_estimate_digit (subset
->major_version
)
2156 + 1 /* For version seperator 'p'. */
2157 + riscv_estimate_digit (subset
->minor_version
)
2158 + 1 /* For underscore. */;
2161 /* Estimate the string length of this subset list. */
2164 riscv_estimate_arch_strlen (const riscv_subset_list_t
*subset_list
)
2166 return riscv_estimate_arch_strlen1 (subset_list
->head
);
2169 /* Auxiliary function to convert subset info to string. */
2172 riscv_arch_str1 (riscv_subset_t
*subset
,
2173 char *attr_str
, char *buf
, size_t bufsz
)
2175 const char *underline
= "_";
2176 riscv_subset_t
*subset_t
= subset
;
2178 if (subset_t
== NULL
)
2181 /* No underline between rvXX and i/e. */
2182 if ((strcasecmp (subset_t
->name
, "i") == 0)
2183 || (strcasecmp (subset_t
->name
, "e") == 0))
2186 snprintf (buf
, bufsz
, "%s%s%dp%d",
2189 subset_t
->major_version
,
2190 subset_t
->minor_version
);
2192 strncat (attr_str
, buf
, bufsz
);
2194 /* Skip 'i' extension after 'e', or skip extensions which
2195 versions are unknown. */
2196 while (subset_t
->next
2197 && ((strcmp (subset_t
->name
, "e") == 0
2198 && strcmp (subset_t
->next
->name
, "i") == 0)
2199 || subset_t
->next
->major_version
== RISCV_UNKNOWN_VERSION
2200 || subset_t
->next
->minor_version
== RISCV_UNKNOWN_VERSION
))
2201 subset_t
= subset_t
->next
;
2203 riscv_arch_str1 (subset_t
->next
, attr_str
, buf
, bufsz
);
2206 /* Convert subset information into string with explicit versions. */
2209 riscv_arch_str (unsigned xlen
, const riscv_subset_list_t
*subset
)
2211 size_t arch_str_len
= riscv_estimate_arch_strlen (subset
);
2212 char *attr_str
= xmalloc (arch_str_len
);
2213 char *buf
= xmalloc (arch_str_len
);
2215 snprintf (attr_str
, arch_str_len
, "rv%u", xlen
);
2217 riscv_arch_str1 (subset
->head
, attr_str
, buf
, arch_str_len
);
2223 /* Copy the subset in the subset list. */
2225 static struct riscv_subset_t
*
2226 riscv_copy_subset (riscv_subset_list_t
*subset_list
,
2227 riscv_subset_t
*subset
)
2232 riscv_subset_t
*new = xmalloc (sizeof *new);
2233 new->name
= xstrdup (subset
->name
);
2234 new->major_version
= subset
->major_version
;
2235 new->minor_version
= subset
->minor_version
;
2236 new->next
= riscv_copy_subset (subset_list
, subset
->next
);
2238 if (subset
->next
== NULL
)
2239 subset_list
->tail
= new;
2244 /* Copy the subset list. */
2246 riscv_subset_list_t
*
2247 riscv_copy_subset_list (riscv_subset_list_t
*subset_list
)
2249 riscv_subset_list_t
*new = xmalloc (sizeof *new);
2250 new->head
= riscv_copy_subset (new, subset_list
->head
);
2251 new->arch_str
= strdup (subset_list
->arch_str
);
2255 /* Remove the SUBSET from the subset list. */
2258 riscv_remove_subset (riscv_subset_list_t
*subset_list
,
2261 riscv_subset_t
*current
= subset_list
->head
;
2262 riscv_subset_t
*pre
= NULL
;
2263 for (; current
!= NULL
; pre
= current
, current
= current
->next
)
2265 if (strcmp (current
->name
, subset
) == 0)
2268 subset_list
->head
= current
->next
;
2270 pre
->next
= current
->next
;
2271 if (current
->next
== NULL
)
2272 subset_list
->tail
= pre
;
2273 free ((void *) current
->name
);
2280 /* Add/Remove an extension to/from the subset list. This is used for
2281 the .option rvc or norvc, and .option arch directives. */
2284 riscv_update_subset (riscv_parse_subset_t
*rps
,
2287 const char *p
= str
;
2291 int major_version
= RISCV_UNKNOWN_VERSION
;
2292 int minor_version
= RISCV_UNKNOWN_VERSION
;
2294 bool removed
= false;
2297 case '+': removed
= false; break;
2298 case '-': removed
= true; break;
2300 riscv_release_subset_list (rps
->subset_list
);
2301 return riscv_parse_subset (rps
, p
);
2305 char *subset
= xstrdup (p
);
2307 const char *end_of_version
;
2308 /* Extract the whole prefixed extension by ','. */
2309 while (*q
!= '\0' && *q
!= ',')
2312 /* Look forward to the first letter which is not <major>p<minor>. */
2313 bool find_any_version
= false;
2314 bool find_minor_version
= false;
2315 size_t len
= q
- subset
;
2317 for (i
= len
; i
> 0; i
--)
2321 find_any_version
= true;
2322 else if (find_any_version
2323 && !find_minor_version
2325 && ISDIGIT (*(q
- 1)))
2326 find_minor_version
= true;
2333 /* Check if the end of extension is 'p' or not. If yes, then
2334 the second letter from the end cannot be number. */
2335 if (len
> 1 && *(q
- 1) == 'p' && ISDIGIT (*(q
- 2)))
2339 (_("invalid ISA extension ends with <number>p "
2340 "in .option arch `%s'"), str
);
2346 riscv_parsing_subset_version (q
, &major_version
, &minor_version
);
2348 if (end_of_version
== NULL
)
2354 if (strlen (subset
) == 0
2355 || (strlen (subset
) == 1
2356 && riscv_ext_order
[(*subset
- 'a')] == 0)
2357 || (strlen (subset
) > 1
2358 && rps
->check_unknown_prefixed_ext
2359 && !riscv_recognized_prefixed_ext (subset
)))
2362 (_("unknown ISA extension `%s' in .option arch `%s'"),
2368 if (strcmp (subset
, "i") == 0
2369 || strcmp (subset
, "e") == 0
2370 || strcmp (subset
, "g") == 0)
2373 (_("cannot + or - base extension `%s' in .option "
2374 "arch `%s'"), subset
, str
);
2380 riscv_remove_subset (rps
->subset_list
, subset
);
2382 riscv_parse_add_subset (rps
, subset
, major_version
, minor_version
, true);
2383 p
+= end_of_version
- subset
;
2386 while (*p
++ == ',');
2388 riscv_parse_add_implicit_subsets (rps
);
2389 return riscv_parse_check_conflicts (rps
);
2392 /* Check if the FEATURE subset is supported or not in the subset list.
2393 Return true if it is supported; Otherwise, return false. */
2396 riscv_subset_supports (riscv_parse_subset_t
*rps
,
2397 const char *feature
)
2399 struct riscv_subset_t
*subset
;
2400 return riscv_lookup_subset (rps
->subset_list
, feature
, &subset
);
2403 /* Each instuction is belonged to an instruction class INSN_CLASS_*.
2404 Call riscv_subset_supports to make sure if the instuction is valid. */
2407 riscv_multi_subset_supports (riscv_parse_subset_t
*rps
,
2408 enum riscv_insn_class insn_class
)
2413 return riscv_subset_supports (rps
, "i");
2414 case INSN_CLASS_ZICBOM
:
2415 return riscv_subset_supports (rps
, "zicbom");
2416 case INSN_CLASS_ZICBOP
:
2417 return riscv_subset_supports (rps
, "zicbop");
2418 case INSN_CLASS_ZICBOZ
:
2419 return riscv_subset_supports (rps
, "zicboz");
2420 case INSN_CLASS_ZICOND
:
2421 return riscv_subset_supports (rps
, "zicond");
2422 case INSN_CLASS_ZICSR
:
2423 return riscv_subset_supports (rps
, "zicsr");
2424 case INSN_CLASS_ZIFENCEI
:
2425 return riscv_subset_supports (rps
, "zifencei");
2426 case INSN_CLASS_ZIHINTNTL
:
2427 return riscv_subset_supports (rps
, "zihintntl");
2428 case INSN_CLASS_ZIHINTNTL_AND_C
:
2429 return (riscv_subset_supports (rps
, "zihintntl")
2430 && (riscv_subset_supports (rps
, "c")
2431 || riscv_subset_supports (rps
, "zca")));
2432 case INSN_CLASS_ZIHINTPAUSE
:
2433 return riscv_subset_supports (rps
, "zihintpause");
2435 return riscv_subset_supports (rps
, "m");
2436 case INSN_CLASS_ZMMUL
:
2437 return riscv_subset_supports (rps
, "zmmul");
2439 return riscv_subset_supports (rps
, "a");
2440 case INSN_CLASS_ZAWRS
:
2441 return riscv_subset_supports (rps
, "zawrs");
2443 return riscv_subset_supports (rps
, "f");
2445 return riscv_subset_supports (rps
, "d");
2447 return riscv_subset_supports (rps
, "q");
2449 return (riscv_subset_supports (rps
, "c")
2450 || riscv_subset_supports (rps
, "zca"));
2451 case INSN_CLASS_F_AND_C
:
2452 return (riscv_subset_supports (rps
, "f")
2453 && (riscv_subset_supports (rps
, "c")
2454 || riscv_subset_supports (rps
, "zcf")));
2455 case INSN_CLASS_D_AND_C
:
2456 return (riscv_subset_supports (rps
, "d")
2457 && (riscv_subset_supports (rps
, "c")
2458 || riscv_subset_supports (rps
, "zcd")));
2459 case INSN_CLASS_F_INX
:
2460 return (riscv_subset_supports (rps
, "f")
2461 || riscv_subset_supports (rps
, "zfinx"));
2462 case INSN_CLASS_D_INX
:
2463 return (riscv_subset_supports (rps
, "d")
2464 || riscv_subset_supports (rps
, "zdinx"));
2465 case INSN_CLASS_Q_INX
:
2466 return (riscv_subset_supports (rps
, "q")
2467 || riscv_subset_supports (rps
, "zqinx"));
2468 case INSN_CLASS_ZFH_INX
:
2469 return (riscv_subset_supports (rps
, "zfh")
2470 || riscv_subset_supports (rps
, "zhinx"));
2471 case INSN_CLASS_ZFHMIN
:
2472 return riscv_subset_supports (rps
, "zfhmin");
2473 case INSN_CLASS_ZFHMIN_INX
:
2474 return (riscv_subset_supports (rps
, "zfhmin")
2475 || riscv_subset_supports (rps
, "zhinxmin"));
2476 case INSN_CLASS_ZFHMIN_AND_D_INX
:
2477 return ((riscv_subset_supports (rps
, "zfhmin")
2478 && riscv_subset_supports (rps
, "d"))
2479 || (riscv_subset_supports (rps
, "zhinxmin")
2480 && riscv_subset_supports (rps
, "zdinx")));
2481 case INSN_CLASS_ZFHMIN_AND_Q_INX
:
2482 return ((riscv_subset_supports (rps
, "zfhmin")
2483 && riscv_subset_supports (rps
, "q"))
2484 || (riscv_subset_supports (rps
, "zhinxmin")
2485 && riscv_subset_supports (rps
, "zqinx")));
2486 case INSN_CLASS_ZFA
:
2487 return riscv_subset_supports (rps
, "zfa");
2488 case INSN_CLASS_D_AND_ZFA
:
2489 return riscv_subset_supports (rps
, "d")
2490 && riscv_subset_supports (rps
, "zfa");
2491 case INSN_CLASS_Q_AND_ZFA
:
2492 return riscv_subset_supports (rps
, "q")
2493 && riscv_subset_supports (rps
, "zfa");
2494 case INSN_CLASS_ZFH_AND_ZFA
:
2495 return riscv_subset_supports (rps
, "zfh")
2496 && riscv_subset_supports (rps
, "zfa");
2497 case INSN_CLASS_ZFH_OR_ZVFH_AND_ZFA
:
2498 return (riscv_subset_supports (rps
, "zfh")
2499 || riscv_subset_supports (rps
, "zvfh"))
2500 && riscv_subset_supports (rps
, "zfa");
2501 case INSN_CLASS_ZBA
:
2502 return riscv_subset_supports (rps
, "zba");
2503 case INSN_CLASS_ZBB
:
2504 return riscv_subset_supports (rps
, "zbb");
2505 case INSN_CLASS_ZBC
:
2506 return riscv_subset_supports (rps
, "zbc");
2507 case INSN_CLASS_ZBS
:
2508 return riscv_subset_supports (rps
, "zbs");
2509 case INSN_CLASS_ZBKB
:
2510 return riscv_subset_supports (rps
, "zbkb");
2511 case INSN_CLASS_ZBKC
:
2512 return riscv_subset_supports (rps
, "zbkc");
2513 case INSN_CLASS_ZBKX
:
2514 return riscv_subset_supports (rps
, "zbkx");
2515 case INSN_CLASS_ZBB_OR_ZBKB
:
2516 return (riscv_subset_supports (rps
, "zbb")
2517 || riscv_subset_supports (rps
, "zbkb"));
2518 case INSN_CLASS_ZBC_OR_ZBKC
:
2519 return (riscv_subset_supports (rps
, "zbc")
2520 || riscv_subset_supports (rps
, "zbkc"));
2521 case INSN_CLASS_ZKND
:
2522 return riscv_subset_supports (rps
, "zknd");
2523 case INSN_CLASS_ZKNE
:
2524 return riscv_subset_supports (rps
, "zkne");
2525 case INSN_CLASS_ZKNH
:
2526 return riscv_subset_supports (rps
, "zknh");
2527 case INSN_CLASS_ZKND_OR_ZKNE
:
2528 return (riscv_subset_supports (rps
, "zknd")
2529 || riscv_subset_supports (rps
, "zkne"));
2530 case INSN_CLASS_ZKSED
:
2531 return riscv_subset_supports (rps
, "zksed");
2532 case INSN_CLASS_ZKSH
:
2533 return riscv_subset_supports (rps
, "zksh");
2535 return (riscv_subset_supports (rps
, "v")
2536 || riscv_subset_supports (rps
, "zve64x")
2537 || riscv_subset_supports (rps
, "zve32x"));
2538 case INSN_CLASS_ZVEF
:
2539 return (riscv_subset_supports (rps
, "v")
2540 || riscv_subset_supports (rps
, "zve64d")
2541 || riscv_subset_supports (rps
, "zve64f")
2542 || riscv_subset_supports (rps
, "zve32f"));
2543 case INSN_CLASS_ZVBB
:
2544 return riscv_subset_supports (rps
, "zvbb");
2545 case INSN_CLASS_ZVBC
:
2546 return riscv_subset_supports (rps
, "zvbc");
2547 case INSN_CLASS_ZVKB
:
2548 return riscv_subset_supports (rps
, "zvkb");
2549 case INSN_CLASS_ZVKG
:
2550 return riscv_subset_supports (rps
, "zvkg");
2551 case INSN_CLASS_ZVKNED
:
2552 return riscv_subset_supports (rps
, "zvkned");
2553 case INSN_CLASS_ZVKNHA_OR_ZVKNHB
:
2554 return (riscv_subset_supports (rps
, "zvknha")
2555 || riscv_subset_supports (rps
, "zvknhb"));
2556 case INSN_CLASS_ZVKSED
:
2557 return riscv_subset_supports (rps
, "zvksed");
2558 case INSN_CLASS_ZVKSH
:
2559 return riscv_subset_supports (rps
, "zvksh");
2560 case INSN_CLASS_ZCB
:
2561 return riscv_subset_supports (rps
, "zcb");
2562 case INSN_CLASS_ZCB_AND_ZBB
:
2563 return (riscv_subset_supports (rps
, "zcb")
2564 && riscv_subset_supports (rps
, "zbb"));
2565 case INSN_CLASS_ZCB_AND_ZBA
:
2566 return (riscv_subset_supports (rps
, "zcb")
2567 && riscv_subset_supports (rps
, "zba"));
2568 case INSN_CLASS_ZCB_AND_ZMMUL
:
2569 return (riscv_subset_supports (rps
, "zcb")
2570 && riscv_subset_supports (rps
, "zmmul"));
2571 case INSN_CLASS_SVINVAL
:
2572 return riscv_subset_supports (rps
, "svinval");
2574 return riscv_subset_supports (rps
, "h");
2575 case INSN_CLASS_XCVMAC
:
2576 return riscv_subset_supports (rps
, "xcvmac");
2577 case INSN_CLASS_XCVALU
:
2578 return riscv_subset_supports (rps
, "xcvalu");
2579 case INSN_CLASS_XTHEADBA
:
2580 return riscv_subset_supports (rps
, "xtheadba");
2581 case INSN_CLASS_XTHEADBB
:
2582 return riscv_subset_supports (rps
, "xtheadbb");
2583 case INSN_CLASS_XTHEADBS
:
2584 return riscv_subset_supports (rps
, "xtheadbs");
2585 case INSN_CLASS_XTHEADCMO
:
2586 return riscv_subset_supports (rps
, "xtheadcmo");
2587 case INSN_CLASS_XTHEADCONDMOV
:
2588 return riscv_subset_supports (rps
, "xtheadcondmov");
2589 case INSN_CLASS_XTHEADFMEMIDX
:
2590 return riscv_subset_supports (rps
, "xtheadfmemidx");
2591 case INSN_CLASS_XTHEADFMV
:
2592 return riscv_subset_supports (rps
, "xtheadfmv");
2593 case INSN_CLASS_XTHEADINT
:
2594 return riscv_subset_supports (rps
, "xtheadint");
2595 case INSN_CLASS_XTHEADMAC
:
2596 return riscv_subset_supports (rps
, "xtheadmac");
2597 case INSN_CLASS_XTHEADMEMIDX
:
2598 return riscv_subset_supports (rps
, "xtheadmemidx");
2599 case INSN_CLASS_XTHEADMEMPAIR
:
2600 return riscv_subset_supports (rps
, "xtheadmempair");
2601 case INSN_CLASS_XTHEADSYNC
:
2602 return riscv_subset_supports (rps
, "xtheadsync");
2603 case INSN_CLASS_XTHEADVECTOR
:
2604 return riscv_subset_supports (rps
, "xtheadvector");
2605 case INSN_CLASS_XTHEADZVAMO
:
2606 return riscv_subset_supports (rps
, "xtheadzvamo");
2607 case INSN_CLASS_XVENTANACONDOPS
:
2608 return riscv_subset_supports (rps
, "xventanacondops");
2609 case INSN_CLASS_XSFVCP
:
2610 return riscv_subset_supports (rps
, "xsfvcp");
2613 (_("internal: unreachable INSN_CLASS_*"));
2618 /* Each instuction is belonged to an instruction class INSN_CLASS_*.
2619 Call riscv_subset_supports_ext to determine the missing extension. */
2622 riscv_multi_subset_supports_ext (riscv_parse_subset_t
*rps
,
2623 enum riscv_insn_class insn_class
)
2629 case INSN_CLASS_ZICBOM
:
2631 case INSN_CLASS_ZICBOP
:
2633 case INSN_CLASS_ZICBOZ
:
2635 case INSN_CLASS_ZICOND
:
2637 case INSN_CLASS_ZICSR
:
2639 case INSN_CLASS_ZIFENCEI
:
2641 case INSN_CLASS_ZIHINTNTL
:
2643 case INSN_CLASS_ZIHINTNTL_AND_C
:
2644 if (!riscv_subset_supports (rps
, "zihintntl"))
2646 if (!riscv_subset_supports (rps
, "c")
2647 && !riscv_subset_supports (rps
, "zca"))
2648 return _("zihintntl' and `c', or `zihintntl' and `zca");
2653 return _("c' or `zca");
2654 case INSN_CLASS_ZIHINTPAUSE
:
2655 return "zihintpause";
2658 case INSN_CLASS_ZMMUL
:
2659 return _ ("m' or `zmmul");
2662 case INSN_CLASS_ZAWRS
:
2671 return _("c' or `zca");
2672 case INSN_CLASS_F_AND_C
:
2673 if (!riscv_subset_supports (rps
, "f"))
2675 if (!riscv_subset_supports (rps
, "c")
2676 && !riscv_subset_supports (rps
, "zcf"))
2677 return _("f' and `c', or `f' and `zcf");
2682 return _("c' or `zcf");
2683 case INSN_CLASS_D_AND_C
:
2684 if (!riscv_subset_supports (rps
, "d"))
2686 if (!riscv_subset_supports (rps
, "c")
2687 && !riscv_subset_supports (rps
, "zcd"))
2688 return _("d' and `c', or `d' and `zcd");
2693 return _("c' or `zcd");
2694 case INSN_CLASS_F_INX
:
2695 return _("f' or `zfinx");
2696 case INSN_CLASS_D_INX
:
2697 return _("d' or `zdinx");
2698 case INSN_CLASS_Q_INX
:
2699 return _("q' or `zqinx");
2700 case INSN_CLASS_ZFH_INX
:
2701 return _("zfh' or `zhinx");
2702 case INSN_CLASS_ZFHMIN
:
2704 case INSN_CLASS_ZFHMIN_INX
:
2705 return _("zfhmin' or `zhinxmin");
2706 case INSN_CLASS_ZFHMIN_AND_D_INX
:
2707 if (riscv_subset_supports (rps
, "zfhmin"))
2709 else if (riscv_subset_supports (rps
, "d"))
2711 else if (riscv_subset_supports (rps
, "zhinxmin"))
2713 else if (riscv_subset_supports (rps
, "zdinx"))
2716 return _("zfhmin' and `d', or `zhinxmin' and `zdinx");
2717 case INSN_CLASS_ZFHMIN_AND_Q_INX
:
2718 if (riscv_subset_supports (rps
, "zfhmin"))
2720 else if (riscv_subset_supports (rps
, "q"))
2722 else if (riscv_subset_supports (rps
, "zhinxmin"))
2724 else if (riscv_subset_supports (rps
, "zqinx"))
2727 return _("zfhmin' and `q', or `zhinxmin' and `zqinx");
2728 case INSN_CLASS_ZFA
:
2730 case INSN_CLASS_D_AND_ZFA
:
2731 if (!riscv_subset_supports (rps
, "d")
2732 && !riscv_subset_supports (rps
, "zfa"))
2733 return _("d' and `zfa");
2734 else if (!riscv_subset_supports (rps
, "d"))
2738 case INSN_CLASS_Q_AND_ZFA
:
2739 if (!riscv_subset_supports (rps
, "q")
2740 && !riscv_subset_supports (rps
, "zfa"))
2741 return _("q' and `zfa");
2742 else if (!riscv_subset_supports (rps
, "q"))
2746 case INSN_CLASS_ZFH_AND_ZFA
:
2747 if (!riscv_subset_supports (rps
, "zfh")
2748 && !riscv_subset_supports (rps
, "zfa"))
2749 return _("zfh' and `zfa");
2750 else if (!riscv_subset_supports (rps
, "zfh"))
2754 case INSN_CLASS_ZFH_OR_ZVFH_AND_ZFA
:
2755 if (!riscv_subset_supports (rps
, "zfa"))
2757 if (!riscv_subset_supports (rps
, "zfh")
2758 && !riscv_subset_supports (rps
, "zvfh"))
2759 return _("zfh' and `zfa', or `zvfh' and `zfa");
2764 return _("zfh' or `zvfh");
2765 case INSN_CLASS_ZBA
:
2767 case INSN_CLASS_ZBB
:
2769 case INSN_CLASS_ZBC
:
2771 case INSN_CLASS_ZBS
:
2773 case INSN_CLASS_ZBKB
:
2775 case INSN_CLASS_ZBKC
:
2777 case INSN_CLASS_ZBKX
:
2779 case INSN_CLASS_ZBB_OR_ZBKB
:
2780 return _("zbb' or `zbkb");
2781 case INSN_CLASS_ZBC_OR_ZBKC
:
2782 return _("zbc' or `zbkc");
2783 case INSN_CLASS_ZKND
:
2785 case INSN_CLASS_ZKNE
:
2787 case INSN_CLASS_ZKNH
:
2789 case INSN_CLASS_ZKND_OR_ZKNE
:
2790 return _("zknd' or `zkne");
2791 case INSN_CLASS_ZKSED
:
2793 case INSN_CLASS_ZKSH
:
2796 return _("v' or `zve64x' or `zve32x");
2797 case INSN_CLASS_ZVEF
:
2798 return _("v' or `zve64d' or `zve64f' or `zve32f");
2799 case INSN_CLASS_ZVBB
:
2801 case INSN_CLASS_ZVBC
:
2803 case INSN_CLASS_ZVKB
:
2805 case INSN_CLASS_ZVKG
:
2807 case INSN_CLASS_ZVKNED
:
2809 case INSN_CLASS_ZVKNHA_OR_ZVKNHB
:
2810 return _("zvknha' or `zvknhb");
2811 case INSN_CLASS_ZVKSED
:
2813 case INSN_CLASS_ZVKSH
:
2815 case INSN_CLASS_ZCB
:
2817 case INSN_CLASS_ZCB_AND_ZBA
:
2818 return _("zcb' and `zba");
2819 case INSN_CLASS_ZCB_AND_ZBB
:
2820 return _("zcb' and `zbb");
2821 case INSN_CLASS_ZCB_AND_ZMMUL
:
2822 return _("zcb' and `zmmul', or `zcb' and `m");
2823 case INSN_CLASS_SVINVAL
:
2827 case INSN_CLASS_XCVMAC
:
2829 case INSN_CLASS_XCVALU
:
2831 case INSN_CLASS_XTHEADBA
:
2833 case INSN_CLASS_XTHEADBB
:
2835 case INSN_CLASS_XTHEADBS
:
2837 case INSN_CLASS_XTHEADCMO
:
2839 case INSN_CLASS_XTHEADCONDMOV
:
2840 return "xtheadcondmov";
2841 case INSN_CLASS_XTHEADFMEMIDX
:
2842 return "xtheadfmemidx";
2843 case INSN_CLASS_XTHEADFMV
:
2845 case INSN_CLASS_XTHEADINT
:
2847 case INSN_CLASS_XTHEADMAC
:
2849 case INSN_CLASS_XTHEADMEMIDX
:
2850 return "xtheadmemidx";
2851 case INSN_CLASS_XTHEADMEMPAIR
:
2852 return "xtheadmempair";
2853 case INSN_CLASS_XTHEADSYNC
:
2854 return "xtheadsync";
2855 case INSN_CLASS_XTHEADVECTOR
:
2856 return "xtheadvector";
2857 case INSN_CLASS_XTHEADZVAMO
:
2858 return "xtheadzvamo";
2861 (_("internal: unreachable INSN_CLASS_*"));