1 /* RISC-V-specific support for ELF.
2 Copyright (C) 2011-2023 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 {"zcd", "d", check_implicit_always
},
1148 {"zcf", "f", check_implicit_always
},
1149 {"zfa", "f", check_implicit_always
},
1150 {"d", "f", check_implicit_always
},
1151 {"zfh", "zfhmin", check_implicit_always
},
1152 {"zfhmin", "f", check_implicit_always
},
1153 {"f", "zicsr", check_implicit_always
},
1154 {"zqinx", "zdinx", check_implicit_always
},
1155 {"zdinx", "zfinx", check_implicit_always
},
1156 {"zhinx", "zhinxmin", check_implicit_always
},
1157 {"zhinxmin", "zfinx", check_implicit_always
},
1158 {"zfinx", "zicsr", check_implicit_always
},
1159 {"zk", "zkn", check_implicit_always
},
1160 {"zk", "zkr", check_implicit_always
},
1161 {"zk", "zkt", check_implicit_always
},
1162 {"zkn", "zbkb", check_implicit_always
},
1163 {"zkn", "zbkc", check_implicit_always
},
1164 {"zkn", "zbkx", check_implicit_always
},
1165 {"zkn", "zkne", check_implicit_always
},
1166 {"zkn", "zknd", check_implicit_always
},
1167 {"zkn", "zknh", check_implicit_always
},
1168 {"zks", "zbkb", check_implicit_always
},
1169 {"zks", "zbkc", check_implicit_always
},
1170 {"zks", "zbkx", check_implicit_always
},
1171 {"zks", "zksed", check_implicit_always
},
1172 {"zks", "zksh", check_implicit_always
},
1173 {"zvbb", "zvkb", check_implicit_always
},
1174 {"zvkn", "zvkned", check_implicit_always
},
1175 {"zvkn", "zvknha", check_implicit_always
},
1176 {"zvkn", "zvknhb", check_implicit_always
},
1177 {"zvkn", "zvkb", check_implicit_always
},
1178 {"zvkn", "zvkt", check_implicit_always
},
1179 {"zvkng", "zvkn", check_implicit_always
},
1180 {"zvkng", "zvkg", check_implicit_always
},
1181 {"zvknc", "zvkn", check_implicit_always
},
1182 {"zvknc", "zvbc", check_implicit_always
},
1183 {"zvks", "zvksed", check_implicit_always
},
1184 {"zvks", "zvksh", check_implicit_always
},
1185 {"zvks", "zvkb", check_implicit_always
},
1186 {"zvks", "zvkt", check_implicit_always
},
1187 {"zvksg", "zvks", check_implicit_always
},
1188 {"zvksg", "zvkg", check_implicit_always
},
1189 {"zvksc", "zvks", check_implicit_always
},
1190 {"zvksc", "zvbc", check_implicit_always
},
1191 {"zcf", "zca", check_implicit_always
},
1192 {"zcd", "zca", check_implicit_always
},
1193 {"zcb", "zca", check_implicit_always
},
1194 {"smaia", "ssaia", check_implicit_always
},
1195 {"smcntrpmf", "zicsr", check_implicit_always
},
1196 {"smstateen", "ssstateen", check_implicit_always
},
1197 {"smepmp", "zicsr", check_implicit_always
},
1198 {"ssaia", "zicsr", check_implicit_always
},
1199 {"sscofpmf", "zicsr", check_implicit_always
},
1200 {"ssstateen", "zicsr", check_implicit_always
},
1201 {"sstc", "zicsr", check_implicit_always
},
1202 {"svadu", "zicsr", check_implicit_always
},
1204 {"xsfvcp", "zve32x", check_implicit_always
},
1208 /* For default_enable field, decide if the extension should
1209 be enbaled by default. */
1211 #define EXT_DEFAULT 0x1
1213 /* List all extensions that binutils should know about. */
1215 struct riscv_supported_ext
1218 enum riscv_spec_class isa_spec_class
;
1221 unsigned long default_enable
;
1224 /* The standard extensions must be added in canonical order. */
1226 static struct riscv_supported_ext riscv_supported_std_ext
[] =
1228 {"e", ISA_SPEC_CLASS_20191213
, 1, 9, 0 },
1229 {"e", ISA_SPEC_CLASS_20190608
, 1, 9, 0 },
1230 {"e", ISA_SPEC_CLASS_2P2
, 1, 9, 0 },
1231 {"i", ISA_SPEC_CLASS_20191213
, 2, 1, 0 },
1232 {"i", ISA_SPEC_CLASS_20190608
, 2, 1, 0 },
1233 {"i", ISA_SPEC_CLASS_2P2
, 2, 0, 0 },
1234 /* The g is a special case which we don't want to output it,
1235 but still need it when adding implicit extensions. */
1236 {"g", ISA_SPEC_CLASS_NONE
, RISCV_UNKNOWN_VERSION
, RISCV_UNKNOWN_VERSION
, EXT_DEFAULT
},
1237 {"m", ISA_SPEC_CLASS_20191213
, 2, 0, 0 },
1238 {"m", ISA_SPEC_CLASS_20190608
, 2, 0, 0 },
1239 {"m", ISA_SPEC_CLASS_2P2
, 2, 0, 0 },
1240 {"a", ISA_SPEC_CLASS_20191213
, 2, 1, 0 },
1241 {"a", ISA_SPEC_CLASS_20190608
, 2, 0, 0 },
1242 {"a", ISA_SPEC_CLASS_2P2
, 2, 0, 0 },
1243 {"f", ISA_SPEC_CLASS_20191213
, 2, 2, 0 },
1244 {"f", ISA_SPEC_CLASS_20190608
, 2, 2, 0 },
1245 {"f", ISA_SPEC_CLASS_2P2
, 2, 0, 0 },
1246 {"d", ISA_SPEC_CLASS_20191213
, 2, 2, 0 },
1247 {"d", ISA_SPEC_CLASS_20190608
, 2, 2, 0 },
1248 {"d", ISA_SPEC_CLASS_2P2
, 2, 0, 0 },
1249 {"q", ISA_SPEC_CLASS_20191213
, 2, 2, 0 },
1250 {"q", ISA_SPEC_CLASS_20190608
, 2, 2, 0 },
1251 {"q", ISA_SPEC_CLASS_2P2
, 2, 0, 0 },
1252 {"c", ISA_SPEC_CLASS_20191213
, 2, 0, 0 },
1253 {"c", ISA_SPEC_CLASS_20190608
, 2, 0, 0 },
1254 {"c", ISA_SPEC_CLASS_2P2
, 2, 0, 0 },
1255 {"v", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1256 {"h", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1260 static struct riscv_supported_ext riscv_supported_std_z_ext
[] =
1262 {"zicbom", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1263 {"zicbop", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1264 {"zicboz", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1265 {"zicond", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1266 {"zicsr", ISA_SPEC_CLASS_20191213
, 2, 0, 0 },
1267 {"zicsr", ISA_SPEC_CLASS_20190608
, 2, 0, 0 },
1268 {"zifencei", ISA_SPEC_CLASS_20191213
, 2, 0, 0 },
1269 {"zifencei", ISA_SPEC_CLASS_20190608
, 2, 0, 0 },
1270 {"zihintntl", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1271 {"zihintpause", ISA_SPEC_CLASS_DRAFT
, 2, 0, 0 },
1272 {"zmmul", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1273 {"zawrs", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1274 {"zfa", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1275 {"zfh", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1276 {"zfhmin", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1277 {"zfinx", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1278 {"zdinx", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1279 {"zqinx", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1280 {"zhinx", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1281 {"zhinxmin", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1282 {"zbb", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1283 {"zba", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1284 {"zbc", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1285 {"zbs", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1286 {"zbkb", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1287 {"zbkc", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1288 {"zbkx", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1289 {"zk", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1290 {"zkn", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1291 {"zknd", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1292 {"zkne", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1293 {"zknh", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1294 {"zkr", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1295 {"zks", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1296 {"zksed", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1297 {"zksh", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1298 {"zkt", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1299 {"zve32x", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1300 {"zve32f", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1301 {"zve64x", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1302 {"zve64f", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1303 {"zve64d", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1304 {"zvbb", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1305 {"zvbc", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1306 {"zvfh", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1307 {"zvfhmin", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1308 {"zvkb", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1309 {"zvkg", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1310 {"zvkn", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1311 {"zvkng", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1312 {"zvknc", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1313 {"zvkned", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1314 {"zvknha", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1315 {"zvknhb", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1316 {"zvksed", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1317 {"zvksh", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1318 {"zvks", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1319 {"zvksg", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1320 {"zvksc", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1321 {"zvkt", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1322 {"zvl32b", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1323 {"zvl64b", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1324 {"zvl128b", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1325 {"zvl256b", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1326 {"zvl512b", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1327 {"zvl1024b", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1328 {"zvl2048b", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1329 {"zvl4096b", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1330 {"zvl8192b", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1331 {"zvl16384b", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1332 {"zvl32768b", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1333 {"zvl65536b", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1334 {"ztso", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1335 {"zca", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1336 {"zcb", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1337 {"zcf", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1338 {"zcd", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1342 static struct riscv_supported_ext riscv_supported_std_s_ext
[] =
1344 {"smaia", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1345 {"smcntrpmf", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1346 {"smepmp", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1347 {"smstateen", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1348 {"ssaia", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1349 {"sscofpmf", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1350 {"ssstateen", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1351 {"sstc", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1352 {"svadu", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1353 {"svinval", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1354 {"svnapot", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1355 {"svpbmt", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1359 static struct riscv_supported_ext riscv_supported_std_zxm_ext
[] =
1364 static struct riscv_supported_ext riscv_supported_vendor_x_ext
[] =
1366 {"xcvmac", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1367 {"xcvalu", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1368 {"xtheadba", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1369 {"xtheadbb", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1370 {"xtheadbs", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1371 {"xtheadcmo", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1372 {"xtheadcondmov", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1373 {"xtheadfmemidx", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1374 {"xtheadfmv", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1375 {"xtheadint", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1376 {"xtheadmac", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1377 {"xtheadmemidx", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1378 {"xtheadmempair", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1379 {"xtheadsync", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1380 {"xtheadvector", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1381 {"xtheadzvamo", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1382 {"xventanacondops", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1383 {"xsfvcp", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0},
1387 const struct riscv_supported_ext
*riscv_all_supported_ext
[] =
1389 riscv_supported_std_ext
,
1390 riscv_supported_std_z_ext
,
1391 riscv_supported_std_s_ext
,
1392 riscv_supported_std_zxm_ext
,
1393 riscv_supported_vendor_x_ext
,
1397 /* ISA extension prefixed name class. Must define them in parsing order. */
1398 enum riscv_prefix_ext_class
1407 /* Record the strings of the prefixed extensions, and their corresponding
1408 classes. The more letters of the prefix string, the more forward it must
1409 be defined. Otherwise, the riscv_get_prefix_class will map it to the
1411 struct riscv_parse_prefix_config
1413 /* Class of the extension. */
1414 enum riscv_prefix_ext_class
class;
1416 /* Prefix string for error printing and internal parser usage. */
1419 static const struct riscv_parse_prefix_config parse_config
[] =
1421 {RV_ISA_CLASS_ZXM
, "zxm"},
1422 {RV_ISA_CLASS_Z
, "z"},
1423 {RV_ISA_CLASS_S
, "s"},
1424 {RV_ISA_CLASS_X
, "x"},
1425 {RV_ISA_CLASS_SINGLE
, NULL
}
1428 /* Get the prefixed name class for the extensions, the class also
1429 means the order of the prefixed extensions. */
1431 static enum riscv_prefix_ext_class
1432 riscv_get_prefix_class (const char *arch
)
1435 while (parse_config
[i
].class != RV_ISA_CLASS_SINGLE
)
1437 if (strncmp (arch
, parse_config
[i
].prefix
,
1438 strlen (parse_config
[i
].prefix
)) == 0)
1439 return parse_config
[i
].class;
1442 return RV_ISA_CLASS_SINGLE
;
1445 /* Check KNOWN_EXTS to see if the EXT is supported. */
1448 riscv_known_prefixed_ext (const char *ext
,
1449 struct riscv_supported_ext
*known_exts
)
1452 for (i
= 0; known_exts
[i
].name
!= NULL
; ++i
)
1453 if (strcmp (ext
, known_exts
[i
].name
) == 0)
1458 /* Check whether the prefixed extension is recognized or not. Return
1459 true if recognized, otehrwise return false. */
1462 riscv_recognized_prefixed_ext (const char *ext
)
1464 enum riscv_prefix_ext_class
class = riscv_get_prefix_class (ext
);
1467 case RV_ISA_CLASS_Z
:
1468 return riscv_known_prefixed_ext (ext
, riscv_supported_std_z_ext
);
1469 case RV_ISA_CLASS_ZXM
:
1470 return riscv_known_prefixed_ext (ext
, riscv_supported_std_zxm_ext
);
1471 case RV_ISA_CLASS_S
:
1472 return riscv_known_prefixed_ext (ext
, riscv_supported_std_s_ext
);
1473 case RV_ISA_CLASS_X
:
1474 /* Only the single x is unrecognized. */
1475 if (strcmp (ext
, "x") != 0)
1483 /* Canonical order for single letter extensions. */
1484 static const char riscv_ext_canonical_order
[] = "eigmafdqlcbkjtpvnh";
1486 /* Array is used to compare the orders of standard extensions quickly. */
1487 static int riscv_ext_order
[26] = {0};
1489 /* Init the riscv_ext_order array. */
1492 riscv_init_ext_order (void)
1494 static bool inited
= false;
1498 /* The orders of all standard extensions are positive. */
1501 for (const char *ext
= &riscv_ext_canonical_order
[0]; *ext
; ++ext
)
1502 riscv_ext_order
[(*ext
- 'a')] = order
++;
1504 /* Some of the prefixed keyword are not single letter, so we set
1505 their prefixed orders in the riscv_compare_subsets directly,
1506 not through the riscv_ext_order. */
1511 /* Similar to the strcmp. It returns an integer less than, equal to,
1512 or greater than zero if `subset2` is found, respectively, to be less
1513 than, to match, or be greater than `subset1`.
1516 Zero: Preserved keywords.
1517 Positive number: Standard extensions.
1518 Negative number: Prefixed keywords. */
1521 riscv_compare_subsets (const char *subset1
, const char *subset2
)
1523 int order1
= riscv_ext_order
[(*subset1
- 'a')];
1524 int order2
= riscv_ext_order
[(*subset2
- 'a')];
1526 /* Compare the standard extension first. */
1527 if (order1
> 0 && order2
> 0)
1528 return order1
- order2
;
1530 /* Set the prefixed orders to negative numbers. */
1531 enum riscv_prefix_ext_class class1
= riscv_get_prefix_class (subset1
);
1532 enum riscv_prefix_ext_class class2
= riscv_get_prefix_class (subset2
);
1534 if (class1
!= RV_ISA_CLASS_SINGLE
)
1535 order1
= - (int) class1
;
1536 if (class2
!= RV_ISA_CLASS_SINGLE
)
1537 order2
= - (int) class2
;
1539 if (order1
== order2
)
1541 /* Compare the standard addition z extensions. */
1542 if (class1
== RV_ISA_CLASS_Z
)
1544 order1
= riscv_ext_order
[(*++subset1
- 'a')];
1545 order2
= riscv_ext_order
[(*++subset2
- 'a')];
1546 if (order1
!= order2
)
1547 return order1
- order2
;
1549 return strcasecmp (++subset1
, ++subset2
);
1552 return order2
- order1
;
1555 /* Find subset in the list. Return TRUE and set `current` to the subset
1556 if it is found. Otherwise, return FALSE and set `current` to the place
1557 where we should insert the subset. However, return FALSE with the NULL
1558 `current` means we should insert the subset at the head of subset list,
1562 riscv_lookup_subset (const riscv_subset_list_t
*subset_list
,
1564 riscv_subset_t
**current
)
1566 riscv_subset_t
*s
, *pre_s
= NULL
;
1568 /* If the subset is added in order, then just add it at the tail. */
1569 if (subset_list
->tail
!= NULL
1570 && riscv_compare_subsets (subset_list
->tail
->name
, subset
) < 0)
1572 *current
= subset_list
->tail
;
1576 for (s
= subset_list
->head
;
1578 pre_s
= s
, s
= s
->next
)
1580 int cmp
= riscv_compare_subsets (s
->name
, subset
);
1594 /* Add the extension to the subset list. Search the
1595 list first, and then find the right place to add. */
1598 riscv_add_subset (riscv_subset_list_t
*subset_list
,
1603 riscv_subset_t
*current
, *new;
1605 if (riscv_lookup_subset (subset_list
, subset
, ¤t
))
1608 new = xmalloc (sizeof *new);
1609 new->name
= xstrdup (subset
);
1610 new->major_version
= major
;
1611 new->minor_version
= minor
;
1614 if (current
!= NULL
)
1616 new->next
= current
->next
;
1617 current
->next
= new;
1621 new->next
= subset_list
->head
;
1622 subset_list
->head
= new;
1625 if (new->next
== NULL
)
1626 subset_list
->tail
= new;
1629 /* Get the default versions from the riscv_supported_*ext tables. */
1632 riscv_get_default_ext_version (enum riscv_spec_class
*default_isa_spec
,
1638 || default_isa_spec
== NULL
1639 || *default_isa_spec
== ISA_SPEC_CLASS_NONE
)
1642 struct riscv_supported_ext
*table
= NULL
;
1643 enum riscv_prefix_ext_class
class = riscv_get_prefix_class (name
);
1646 case RV_ISA_CLASS_ZXM
: table
= riscv_supported_std_zxm_ext
; break;
1647 case RV_ISA_CLASS_Z
: table
= riscv_supported_std_z_ext
; break;
1648 case RV_ISA_CLASS_S
: table
= riscv_supported_std_s_ext
; break;
1649 case RV_ISA_CLASS_X
: table
= riscv_supported_vendor_x_ext
; break;
1651 table
= riscv_supported_std_ext
;
1655 while (table
!= NULL
&& table
[i
].name
!= NULL
)
1657 if (strcmp (table
[i
].name
, name
) == 0
1658 && (table
[i
].isa_spec_class
== ISA_SPEC_CLASS_DRAFT
1659 || table
[i
].isa_spec_class
== *default_isa_spec
))
1661 *major_version
= table
[i
].major_version
;
1662 *minor_version
= table
[i
].minor_version
;
1669 /* Find the default versions for the extension before adding them to
1670 the subset list, if their versions are RISCV_UNKNOWN_VERSION.
1671 Afterwards, report errors if we can not find their default versions. */
1674 riscv_parse_add_subset (riscv_parse_subset_t
*rps
,
1680 int major_version
= major
;
1681 int minor_version
= minor
;
1683 if (major_version
== RISCV_UNKNOWN_VERSION
1684 || minor_version
== RISCV_UNKNOWN_VERSION
)
1685 riscv_get_default_ext_version (rps
->isa_spec
, subset
,
1686 &major_version
, &minor_version
);
1688 /* We don't care the versions of the implicit extensions. */
1690 && (major_version
== RISCV_UNKNOWN_VERSION
1691 || minor_version
== RISCV_UNKNOWN_VERSION
))
1693 if (subset
[0] == 'x')
1695 (_("x ISA extension `%s' must be set with the versions"),
1697 /* Allow old ISA spec can recognize zicsr and zifencei. */
1698 else if (strcmp (subset
, "zicsr") != 0
1699 && strcmp (subset
, "zifencei") != 0)
1701 (_("cannot find default versions of the ISA extension `%s'"),
1706 riscv_add_subset (rps
->subset_list
, subset
,
1707 major_version
, minor_version
);
1710 /* Release subset list. */
1713 riscv_release_subset_list (riscv_subset_list_t
*subset_list
)
1715 while (subset_list
->head
!= NULL
)
1717 riscv_subset_t
*next
= subset_list
->head
->next
;
1718 free ((void *)subset_list
->head
->name
);
1719 free (subset_list
->head
);
1720 subset_list
->head
= next
;
1723 subset_list
->tail
= NULL
;
1725 if (subset_list
->arch_str
!= NULL
)
1727 free ((void*) subset_list
->arch_str
);
1728 subset_list
->arch_str
= NULL
;
1732 /* Parsing extension version.
1735 Points to the end of version
1738 `p`: Curent parsing position.
1739 `major_version`: Parsed major version.
1740 `minor_version`: Parsed minor version. */
1743 riscv_parsing_subset_version (const char *p
,
1747 bool major_p
= true;
1759 /* Might be beginning of `p` extension. */
1763 *major_version
= version
;
1767 else if (ISDIGIT (*p
))
1768 version
= (version
* 10) + (*p
- '0');
1774 *major_version
= version
;
1776 *minor_version
= version
;
1778 /* We can not find any version in string. */
1779 if (*major_version
== 0 && *minor_version
== 0)
1781 *major_version
= RISCV_UNKNOWN_VERSION
;
1782 *minor_version
= RISCV_UNKNOWN_VERSION
;
1788 /* Parsing function for both standard and prefixed extensions.
1791 Points to the end of extensions.
1794 `rps`: Hooks and status for parsing extensions.
1795 `arch`: Full ISA string.
1796 `p`: Curent parsing position. */
1799 riscv_parse_extensions (riscv_parse_subset_t
*rps
,
1803 /* First letter must start with i, e or g. */
1804 if (*p
!= 'e' && *p
!= 'i' && *p
!= 'g')
1807 (_("%s: first ISA extension must be `e', `i' or `g'"),
1820 char *subset
= xstrdup (p
);
1821 char *q
= subset
; /* Start of version. */
1822 const char *end_of_version
;
1823 bool implicit
= false;
1825 enum riscv_prefix_ext_class
class = riscv_get_prefix_class (p
);
1826 if (class == RV_ISA_CLASS_SINGLE
)
1828 if (riscv_ext_order
[(*subset
- 'a')] == 0)
1831 (_("%s: unknown standard ISA extension or prefix class `%c'"),
1840 /* Extract the whole prefixed extension by '_'. */
1841 while (*++q
!= '\0' && *q
!= '_')
1843 /* Look forward to the first letter which is not <major>p<minor>. */
1844 bool find_any_version
= false;
1845 bool find_minor_version
= false;
1850 find_any_version
= true;
1851 else if (find_any_version
1852 && !find_minor_version
1854 && ISDIGIT (*(q
- 1)))
1855 find_minor_version
= true;
1861 /* Check if the end of extension is 'p' or not. If yes, then
1862 the second letter from the end cannot be number. */
1863 if (*(q
- 1) == 'p' && ISDIGIT (*(q
- 2)))
1867 (_("%s: invalid prefixed ISA extension `%s' ends with <number>p"),
1874 int major_version
= RISCV_UNKNOWN_VERSION
;
1875 int minor_version
= RISCV_UNKNOWN_VERSION
;
1877 riscv_parsing_subset_version (q
, &major_version
, &minor_version
);
1879 if (end_of_version
== NULL
)
1885 /* Check if the prefixed extension name is well-formed. */
1886 if (class != RV_ISA_CLASS_SINGLE
1887 && rps
->check_unknown_prefixed_ext
1888 && !riscv_recognized_prefixed_ext (subset
))
1891 (_("%s: unknown prefixed ISA extension `%s'"),
1897 /* Added g as an implicit extension. */
1898 if (class == RV_ISA_CLASS_SINGLE
1899 && strcmp (subset
, "g") == 0)
1902 major_version
= RISCV_UNKNOWN_VERSION
;
1903 minor_version
= RISCV_UNKNOWN_VERSION
;
1905 riscv_parse_add_subset (rps
, subset
,
1907 minor_version
, implicit
);
1908 p
+= end_of_version
- subset
;
1911 if (class != RV_ISA_CLASS_SINGLE
1912 && *p
!= '\0' && *p
!= '_')
1915 (_("%s: prefixed ISA extension must separate with _"),
1924 /* Add the implicit extensions. */
1927 riscv_parse_add_implicit_subsets (riscv_parse_subset_t
*rps
)
1929 struct riscv_implicit_subset
*t
= riscv_implicit_subsets
;
1930 bool finished
= false;
1934 for (; t
->subset_name
; t
++)
1936 riscv_subset_t
*subset
= NULL
;
1937 riscv_subset_t
*implicit_subset
= NULL
;
1938 if (riscv_lookup_subset (rps
->subset_list
, t
->subset_name
, &subset
)
1939 && !riscv_lookup_subset (rps
->subset_list
, t
->implicit_name
,
1941 && t
->check_func (t
->implicit_name
, subset
))
1943 riscv_parse_add_subset (rps
, t
->implicit_name
,
1944 RISCV_UNKNOWN_VERSION
,
1945 RISCV_UNKNOWN_VERSION
, true);
1947 /* Restart the loop and pick up any new implications. */
1949 t
= riscv_implicit_subsets
;
1956 /* Check extensions conflicts. */
1959 riscv_parse_check_conflicts (riscv_parse_subset_t
*rps
)
1961 riscv_subset_t
*subset
= NULL
;
1962 int xlen
= *rps
->xlen
;
1963 bool no_conflict
= true;
1965 if (riscv_subset_supports (rps
, "e")
1966 && riscv_subset_supports (rps
, "h"))
1969 (_("rv%de does not support the `h' extension"), xlen
);
1970 no_conflict
= false;
1972 if (riscv_lookup_subset (rps
->subset_list
, "q", &subset
)
1973 && (subset
->major_version
< 2 || (subset
->major_version
== 2
1974 && subset
->minor_version
< 2))
1977 rps
->error_handler (_("rv%d does not support the `q' extension"), xlen
);
1978 no_conflict
= false;
1980 if (riscv_lookup_subset (rps
->subset_list
, "zcf", &subset
)
1984 (_("rv%d does not support the `zcf' extension"), xlen
);
1985 no_conflict
= false;
1987 if (riscv_lookup_subset (rps
->subset_list
, "zfinx", &subset
)
1988 && riscv_lookup_subset (rps
->subset_list
, "f", &subset
))
1991 (_("`zfinx' is conflict with the `f/d/q/zfh/zfhmin' extension"));
1992 no_conflict
= false;
1994 if (riscv_lookup_subset (rps
->subset_list
, "xtheadvector", &subset
)
1995 && riscv_lookup_subset (rps
->subset_list
, "v", &subset
))
1998 (_("`xtheadvector' is conflict with the `v' extension"));
1999 no_conflict
= false;
2002 bool support_zve
= false;
2003 bool support_zvl
= false;
2004 riscv_subset_t
*s
= rps
->subset_list
->head
;
2005 for (; s
!= NULL
; s
= s
->next
)
2008 && strncmp (s
->name
, "zve", 3) == 0)
2011 && strncmp (s
->name
, "zvl", 3) == 0)
2013 if (support_zve
&& support_zvl
)
2016 if (support_zvl
&& !support_zve
)
2019 (_("zvl*b extensions need to enable either `v' or `zve' extension"));
2020 no_conflict
= false;
2026 /* Set the default subset list according to the default_enable field
2027 of riscv_supported_*ext tables. */
2030 riscv_set_default_arch (riscv_parse_subset_t
*rps
)
2032 unsigned long enable
= EXT_DEFAULT
;
2034 for (i
= 0; riscv_all_supported_ext
[i
] != NULL
; i
++)
2036 const struct riscv_supported_ext
*table
= riscv_all_supported_ext
[i
];
2037 for (j
= 0; table
[j
].name
!= NULL
; j
++)
2039 bool implicit
= false;
2040 if (strcmp (table
[j
].name
, "g") == 0)
2042 if (table
[j
].default_enable
& enable
)
2043 riscv_parse_add_subset (rps
, table
[j
].name
,
2044 RISCV_UNKNOWN_VERSION
,
2045 RISCV_UNKNOWN_VERSION
, implicit
);
2050 /* Function for parsing ISA string.
2053 Return TRUE on success.
2056 `rps`: Hooks and status for parsing extensions.
2057 `arch`: Full ISA string. */
2060 riscv_parse_subset (riscv_parse_subset_t
*rps
,
2065 /* Init the riscv_ext_order array to compare the order of extensions
2067 riscv_init_ext_order ();
2071 riscv_set_default_arch (rps
);
2072 riscv_parse_add_implicit_subsets (rps
);
2073 return riscv_parse_check_conflicts (rps
);
2076 for (p
= arch
; *p
!= '\0'; p
++)
2081 (_("%s: ISA string cannot contain uppercase letters"),
2088 if (startswith (p
, "rv32"))
2093 else if (startswith (p
, "rv64"))
2100 /* ISA string shouldn't be NULL or empty here. For linker,
2101 it might be empty when we failed to merge the ISA string
2102 in the riscv_merge_attributes. For assembler, we might
2103 give an empty string by .attribute arch, "" or -march=.
2104 However, We have already issued the correct error message
2105 in another side, so do not issue this error when the ISA
2108 rps
->error_handler (
2109 _("%s: ISA string must begin with rv32 or rv64"),
2114 /* Parse single standard and prefixed extensions. */
2115 if (riscv_parse_extensions (rps
, arch
, p
) == NULL
)
2118 /* Finally add implicit extensions according to the current
2120 riscv_parse_add_implicit_subsets (rps
);
2122 /* Check the conflicts. */
2123 return riscv_parse_check_conflicts (rps
);
2126 /* Return the number of digits for the input. */
2129 riscv_estimate_digit (unsigned num
)
2135 for (digit
= 0; num
; num
/= 10)
2141 /* Auxiliary function to estimate string length of subset list. */
2144 riscv_estimate_arch_strlen1 (const riscv_subset_t
*subset
)
2147 return 6; /* For rv32/rv64/rv128 and string terminator. */
2149 return riscv_estimate_arch_strlen1 (subset
->next
)
2150 + strlen (subset
->name
)
2151 + riscv_estimate_digit (subset
->major_version
)
2152 + 1 /* For version seperator 'p'. */
2153 + riscv_estimate_digit (subset
->minor_version
)
2154 + 1 /* For underscore. */;
2157 /* Estimate the string length of this subset list. */
2160 riscv_estimate_arch_strlen (const riscv_subset_list_t
*subset_list
)
2162 return riscv_estimate_arch_strlen1 (subset_list
->head
);
2165 /* Auxiliary function to convert subset info to string. */
2168 riscv_arch_str1 (riscv_subset_t
*subset
,
2169 char *attr_str
, char *buf
, size_t bufsz
)
2171 const char *underline
= "_";
2172 riscv_subset_t
*subset_t
= subset
;
2174 if (subset_t
== NULL
)
2177 /* No underline between rvXX and i/e. */
2178 if ((strcasecmp (subset_t
->name
, "i") == 0)
2179 || (strcasecmp (subset_t
->name
, "e") == 0))
2182 snprintf (buf
, bufsz
, "%s%s%dp%d",
2185 subset_t
->major_version
,
2186 subset_t
->minor_version
);
2188 strncat (attr_str
, buf
, bufsz
);
2190 /* Skip 'i' extension after 'e', or skip extensions which
2191 versions are unknown. */
2192 while (subset_t
->next
2193 && ((strcmp (subset_t
->name
, "e") == 0
2194 && strcmp (subset_t
->next
->name
, "i") == 0)
2195 || subset_t
->next
->major_version
== RISCV_UNKNOWN_VERSION
2196 || subset_t
->next
->minor_version
== RISCV_UNKNOWN_VERSION
))
2197 subset_t
= subset_t
->next
;
2199 riscv_arch_str1 (subset_t
->next
, attr_str
, buf
, bufsz
);
2202 /* Convert subset information into string with explicit versions. */
2205 riscv_arch_str (unsigned xlen
, const riscv_subset_list_t
*subset
)
2207 size_t arch_str_len
= riscv_estimate_arch_strlen (subset
);
2208 char *attr_str
= xmalloc (arch_str_len
);
2209 char *buf
= xmalloc (arch_str_len
);
2211 snprintf (attr_str
, arch_str_len
, "rv%u", xlen
);
2213 riscv_arch_str1 (subset
->head
, attr_str
, buf
, arch_str_len
);
2219 /* Copy the subset in the subset list. */
2221 static struct riscv_subset_t
*
2222 riscv_copy_subset (riscv_subset_list_t
*subset_list
,
2223 riscv_subset_t
*subset
)
2228 riscv_subset_t
*new = xmalloc (sizeof *new);
2229 new->name
= xstrdup (subset
->name
);
2230 new->major_version
= subset
->major_version
;
2231 new->minor_version
= subset
->minor_version
;
2232 new->next
= riscv_copy_subset (subset_list
, subset
->next
);
2234 if (subset
->next
== NULL
)
2235 subset_list
->tail
= new;
2240 /* Copy the subset list. */
2242 riscv_subset_list_t
*
2243 riscv_copy_subset_list (riscv_subset_list_t
*subset_list
)
2245 riscv_subset_list_t
*new = xmalloc (sizeof *new);
2246 new->head
= riscv_copy_subset (new, subset_list
->head
);
2247 new->arch_str
= strdup (subset_list
->arch_str
);
2251 /* Remove the SUBSET from the subset list. */
2254 riscv_remove_subset (riscv_subset_list_t
*subset_list
,
2257 riscv_subset_t
*current
= subset_list
->head
;
2258 riscv_subset_t
*pre
= NULL
;
2259 for (; current
!= NULL
; pre
= current
, current
= current
->next
)
2261 if (strcmp (current
->name
, subset
) == 0)
2264 subset_list
->head
= current
->next
;
2266 pre
->next
= current
->next
;
2267 if (current
->next
== NULL
)
2268 subset_list
->tail
= pre
;
2269 free ((void *) current
->name
);
2276 /* Add/Remove an extension to/from the subset list. This is used for
2277 the .option rvc or norvc, and .option arch directives. */
2280 riscv_update_subset (riscv_parse_subset_t
*rps
,
2283 const char *p
= str
;
2287 int major_version
= RISCV_UNKNOWN_VERSION
;
2288 int minor_version
= RISCV_UNKNOWN_VERSION
;
2290 bool removed
= false;
2293 case '+': removed
= false; break;
2294 case '-': removed
= true; break;
2296 riscv_release_subset_list (rps
->subset_list
);
2297 return riscv_parse_subset (rps
, p
);
2301 char *subset
= xstrdup (p
);
2303 const char *end_of_version
;
2304 /* Extract the whole prefixed extension by ','. */
2305 while (*q
!= '\0' && *q
!= ',')
2308 /* Look forward to the first letter which is not <major>p<minor>. */
2309 bool find_any_version
= false;
2310 bool find_minor_version
= false;
2311 size_t len
= q
- subset
;
2313 for (i
= len
; i
> 0; i
--)
2317 find_any_version
= true;
2318 else if (find_any_version
2319 && !find_minor_version
2321 && ISDIGIT (*(q
- 1)))
2322 find_minor_version
= true;
2329 /* Check if the end of extension is 'p' or not. If yes, then
2330 the second letter from the end cannot be number. */
2331 if (len
> 1 && *(q
- 1) == 'p' && ISDIGIT (*(q
- 2)))
2335 (_("invalid ISA extension ends with <number>p "
2336 "in .option arch `%s'"), str
);
2342 riscv_parsing_subset_version (q
, &major_version
, &minor_version
);
2344 if (end_of_version
== NULL
)
2350 if (strlen (subset
) == 0
2351 || (strlen (subset
) == 1
2352 && riscv_ext_order
[(*subset
- 'a')] == 0)
2353 || (strlen (subset
) > 1
2354 && rps
->check_unknown_prefixed_ext
2355 && !riscv_recognized_prefixed_ext (subset
)))
2358 (_("unknown ISA extension `%s' in .option arch `%s'"),
2364 if (strcmp (subset
, "i") == 0
2365 || strcmp (subset
, "e") == 0
2366 || strcmp (subset
, "g") == 0)
2369 (_("cannot + or - base extension `%s' in .option "
2370 "arch `%s'"), subset
, str
);
2376 riscv_remove_subset (rps
->subset_list
, subset
);
2378 riscv_parse_add_subset (rps
, subset
, major_version
, minor_version
, true);
2379 p
+= end_of_version
- subset
;
2382 while (*p
++ == ',');
2384 riscv_parse_add_implicit_subsets (rps
);
2385 return riscv_parse_check_conflicts (rps
);
2388 /* Check if the FEATURE subset is supported or not in the subset list.
2389 Return true if it is supported; Otherwise, return false. */
2392 riscv_subset_supports (riscv_parse_subset_t
*rps
,
2393 const char *feature
)
2395 struct riscv_subset_t
*subset
;
2396 return riscv_lookup_subset (rps
->subset_list
, feature
, &subset
);
2399 /* Each instuction is belonged to an instruction class INSN_CLASS_*.
2400 Call riscv_subset_supports to make sure if the instuction is valid. */
2403 riscv_multi_subset_supports (riscv_parse_subset_t
*rps
,
2404 enum riscv_insn_class insn_class
)
2409 return riscv_subset_supports (rps
, "i");
2410 case INSN_CLASS_ZICBOM
:
2411 return riscv_subset_supports (rps
, "zicbom");
2412 case INSN_CLASS_ZICBOP
:
2413 return riscv_subset_supports (rps
, "zicbop");
2414 case INSN_CLASS_ZICBOZ
:
2415 return riscv_subset_supports (rps
, "zicboz");
2416 case INSN_CLASS_ZICOND
:
2417 return riscv_subset_supports (rps
, "zicond");
2418 case INSN_CLASS_ZICSR
:
2419 return riscv_subset_supports (rps
, "zicsr");
2420 case INSN_CLASS_ZIFENCEI
:
2421 return riscv_subset_supports (rps
, "zifencei");
2422 case INSN_CLASS_ZIHINTNTL
:
2423 return riscv_subset_supports (rps
, "zihintntl");
2424 case INSN_CLASS_ZIHINTNTL_AND_C
:
2425 return (riscv_subset_supports (rps
, "zihintntl")
2426 && (riscv_subset_supports (rps
, "c")
2427 || riscv_subset_supports (rps
, "zca")));
2428 case INSN_CLASS_ZIHINTPAUSE
:
2429 return riscv_subset_supports (rps
, "zihintpause");
2431 return riscv_subset_supports (rps
, "m");
2432 case INSN_CLASS_ZMMUL
:
2433 return riscv_subset_supports (rps
, "zmmul");
2435 return riscv_subset_supports (rps
, "a");
2436 case INSN_CLASS_ZAWRS
:
2437 return riscv_subset_supports (rps
, "zawrs");
2439 return riscv_subset_supports (rps
, "f");
2441 return riscv_subset_supports (rps
, "d");
2443 return riscv_subset_supports (rps
, "q");
2445 return (riscv_subset_supports (rps
, "c")
2446 || riscv_subset_supports (rps
, "zca"));
2447 case INSN_CLASS_F_AND_C
:
2448 return (riscv_subset_supports (rps
, "f")
2449 && (riscv_subset_supports (rps
, "c")
2450 || riscv_subset_supports (rps
, "zcf")));
2451 case INSN_CLASS_D_AND_C
:
2452 return (riscv_subset_supports (rps
, "d")
2453 && (riscv_subset_supports (rps
, "c")
2454 || riscv_subset_supports (rps
, "zcd")));
2455 case INSN_CLASS_F_INX
:
2456 return (riscv_subset_supports (rps
, "f")
2457 || riscv_subset_supports (rps
, "zfinx"));
2458 case INSN_CLASS_D_INX
:
2459 return (riscv_subset_supports (rps
, "d")
2460 || riscv_subset_supports (rps
, "zdinx"));
2461 case INSN_CLASS_Q_INX
:
2462 return (riscv_subset_supports (rps
, "q")
2463 || riscv_subset_supports (rps
, "zqinx"));
2464 case INSN_CLASS_ZFH_INX
:
2465 return (riscv_subset_supports (rps
, "zfh")
2466 || riscv_subset_supports (rps
, "zhinx"));
2467 case INSN_CLASS_ZFHMIN
:
2468 return riscv_subset_supports (rps
, "zfhmin");
2469 case INSN_CLASS_ZFHMIN_INX
:
2470 return (riscv_subset_supports (rps
, "zfhmin")
2471 || riscv_subset_supports (rps
, "zhinxmin"));
2472 case INSN_CLASS_ZFHMIN_AND_D_INX
:
2473 return ((riscv_subset_supports (rps
, "zfhmin")
2474 && riscv_subset_supports (rps
, "d"))
2475 || (riscv_subset_supports (rps
, "zhinxmin")
2476 && riscv_subset_supports (rps
, "zdinx")));
2477 case INSN_CLASS_ZFHMIN_AND_Q_INX
:
2478 return ((riscv_subset_supports (rps
, "zfhmin")
2479 && riscv_subset_supports (rps
, "q"))
2480 || (riscv_subset_supports (rps
, "zhinxmin")
2481 && riscv_subset_supports (rps
, "zqinx")));
2482 case INSN_CLASS_ZFA
:
2483 return riscv_subset_supports (rps
, "zfa");
2484 case INSN_CLASS_D_AND_ZFA
:
2485 return riscv_subset_supports (rps
, "d")
2486 && riscv_subset_supports (rps
, "zfa");
2487 case INSN_CLASS_Q_AND_ZFA
:
2488 return riscv_subset_supports (rps
, "q")
2489 && riscv_subset_supports (rps
, "zfa");
2490 case INSN_CLASS_ZFH_AND_ZFA
:
2491 return riscv_subset_supports (rps
, "zfh")
2492 && riscv_subset_supports (rps
, "zfa");
2493 case INSN_CLASS_ZFH_OR_ZVFH_AND_ZFA
:
2494 return (riscv_subset_supports (rps
, "zfh")
2495 || riscv_subset_supports (rps
, "zvfh"))
2496 && riscv_subset_supports (rps
, "zfa");
2497 case INSN_CLASS_ZBA
:
2498 return riscv_subset_supports (rps
, "zba");
2499 case INSN_CLASS_ZBB
:
2500 return riscv_subset_supports (rps
, "zbb");
2501 case INSN_CLASS_ZBC
:
2502 return riscv_subset_supports (rps
, "zbc");
2503 case INSN_CLASS_ZBS
:
2504 return riscv_subset_supports (rps
, "zbs");
2505 case INSN_CLASS_ZBKB
:
2506 return riscv_subset_supports (rps
, "zbkb");
2507 case INSN_CLASS_ZBKC
:
2508 return riscv_subset_supports (rps
, "zbkc");
2509 case INSN_CLASS_ZBKX
:
2510 return riscv_subset_supports (rps
, "zbkx");
2511 case INSN_CLASS_ZBB_OR_ZBKB
:
2512 return (riscv_subset_supports (rps
, "zbb")
2513 || riscv_subset_supports (rps
, "zbkb"));
2514 case INSN_CLASS_ZBC_OR_ZBKC
:
2515 return (riscv_subset_supports (rps
, "zbc")
2516 || riscv_subset_supports (rps
, "zbkc"));
2517 case INSN_CLASS_ZKND
:
2518 return riscv_subset_supports (rps
, "zknd");
2519 case INSN_CLASS_ZKNE
:
2520 return riscv_subset_supports (rps
, "zkne");
2521 case INSN_CLASS_ZKNH
:
2522 return riscv_subset_supports (rps
, "zknh");
2523 case INSN_CLASS_ZKND_OR_ZKNE
:
2524 return (riscv_subset_supports (rps
, "zknd")
2525 || riscv_subset_supports (rps
, "zkne"));
2526 case INSN_CLASS_ZKSED
:
2527 return riscv_subset_supports (rps
, "zksed");
2528 case INSN_CLASS_ZKSH
:
2529 return riscv_subset_supports (rps
, "zksh");
2531 return (riscv_subset_supports (rps
, "v")
2532 || riscv_subset_supports (rps
, "zve64x")
2533 || riscv_subset_supports (rps
, "zve32x"));
2534 case INSN_CLASS_ZVEF
:
2535 return (riscv_subset_supports (rps
, "v")
2536 || riscv_subset_supports (rps
, "zve64d")
2537 || riscv_subset_supports (rps
, "zve64f")
2538 || riscv_subset_supports (rps
, "zve32f"));
2539 case INSN_CLASS_ZVBB
:
2540 return riscv_subset_supports (rps
, "zvbb");
2541 case INSN_CLASS_ZVBC
:
2542 return riscv_subset_supports (rps
, "zvbc");
2543 case INSN_CLASS_ZVKB
:
2544 return riscv_subset_supports (rps
, "zvkb");
2545 case INSN_CLASS_ZVKG
:
2546 return riscv_subset_supports (rps
, "zvkg");
2547 case INSN_CLASS_ZVKNED
:
2548 return riscv_subset_supports (rps
, "zvkned");
2549 case INSN_CLASS_ZVKNHA_OR_ZVKNHB
:
2550 return (riscv_subset_supports (rps
, "zvknha")
2551 || riscv_subset_supports (rps
, "zvknhb"));
2552 case INSN_CLASS_ZVKSED
:
2553 return riscv_subset_supports (rps
, "zvksed");
2554 case INSN_CLASS_ZVKSH
:
2555 return riscv_subset_supports (rps
, "zvksh");
2556 case INSN_CLASS_ZCB
:
2557 return riscv_subset_supports (rps
, "zcb");
2558 case INSN_CLASS_ZCB_AND_ZBB
:
2559 return (riscv_subset_supports (rps
, "zcb")
2560 && riscv_subset_supports (rps
, "zbb"));
2561 case INSN_CLASS_ZCB_AND_ZBA
:
2562 return (riscv_subset_supports (rps
, "zcb")
2563 && riscv_subset_supports (rps
, "zba"));
2564 case INSN_CLASS_ZCB_AND_ZMMUL
:
2565 return (riscv_subset_supports (rps
, "zcb")
2566 && riscv_subset_supports (rps
, "zmmul"));
2567 case INSN_CLASS_SVINVAL
:
2568 return riscv_subset_supports (rps
, "svinval");
2570 return riscv_subset_supports (rps
, "h");
2571 case INSN_CLASS_XCVMAC
:
2572 return riscv_subset_supports (rps
, "xcvmac");
2573 case INSN_CLASS_XCVALU
:
2574 return riscv_subset_supports (rps
, "xcvalu");
2575 case INSN_CLASS_XTHEADBA
:
2576 return riscv_subset_supports (rps
, "xtheadba");
2577 case INSN_CLASS_XTHEADBB
:
2578 return riscv_subset_supports (rps
, "xtheadbb");
2579 case INSN_CLASS_XTHEADBS
:
2580 return riscv_subset_supports (rps
, "xtheadbs");
2581 case INSN_CLASS_XTHEADCMO
:
2582 return riscv_subset_supports (rps
, "xtheadcmo");
2583 case INSN_CLASS_XTHEADCONDMOV
:
2584 return riscv_subset_supports (rps
, "xtheadcondmov");
2585 case INSN_CLASS_XTHEADFMEMIDX
:
2586 return riscv_subset_supports (rps
, "xtheadfmemidx");
2587 case INSN_CLASS_XTHEADFMV
:
2588 return riscv_subset_supports (rps
, "xtheadfmv");
2589 case INSN_CLASS_XTHEADINT
:
2590 return riscv_subset_supports (rps
, "xtheadint");
2591 case INSN_CLASS_XTHEADMAC
:
2592 return riscv_subset_supports (rps
, "xtheadmac");
2593 case INSN_CLASS_XTHEADMEMIDX
:
2594 return riscv_subset_supports (rps
, "xtheadmemidx");
2595 case INSN_CLASS_XTHEADMEMPAIR
:
2596 return riscv_subset_supports (rps
, "xtheadmempair");
2597 case INSN_CLASS_XTHEADSYNC
:
2598 return riscv_subset_supports (rps
, "xtheadsync");
2599 case INSN_CLASS_XTHEADVECTOR
:
2600 return riscv_subset_supports (rps
, "xtheadvector");
2601 case INSN_CLASS_XTHEADZVAMO
:
2602 return riscv_subset_supports (rps
, "xtheadzvamo");
2603 case INSN_CLASS_XVENTANACONDOPS
:
2604 return riscv_subset_supports (rps
, "xventanacondops");
2605 case INSN_CLASS_XSFVCP
:
2606 return riscv_subset_supports (rps
, "xsfvcp");
2609 (_("internal: unreachable INSN_CLASS_*"));
2614 /* Each instuction is belonged to an instruction class INSN_CLASS_*.
2615 Call riscv_subset_supports_ext to determine the missing extension. */
2618 riscv_multi_subset_supports_ext (riscv_parse_subset_t
*rps
,
2619 enum riscv_insn_class insn_class
)
2625 case INSN_CLASS_ZICBOM
:
2627 case INSN_CLASS_ZICBOP
:
2629 case INSN_CLASS_ZICBOZ
:
2631 case INSN_CLASS_ZICOND
:
2633 case INSN_CLASS_ZICSR
:
2635 case INSN_CLASS_ZIFENCEI
:
2637 case INSN_CLASS_ZIHINTNTL
:
2639 case INSN_CLASS_ZIHINTNTL_AND_C
:
2640 if (!riscv_subset_supports (rps
, "zihintntl"))
2642 if (!riscv_subset_supports (rps
, "c")
2643 && !riscv_subset_supports (rps
, "zca"))
2644 return _("zihintntl' and `c', or `zihintntl' and `zca");
2649 return _("c' or `zca");
2650 case INSN_CLASS_ZIHINTPAUSE
:
2651 return "zihintpause";
2654 case INSN_CLASS_ZMMUL
:
2655 return _ ("m' or `zmmul");
2658 case INSN_CLASS_ZAWRS
:
2667 return _("c' or `zca");
2668 case INSN_CLASS_F_AND_C
:
2669 if (!riscv_subset_supports (rps
, "f"))
2671 if (!riscv_subset_supports (rps
, "c")
2672 && !riscv_subset_supports (rps
, "zcf"))
2673 return _("f' and `c', or `f' and `zcf");
2678 return _("c' or `zcf");
2679 case INSN_CLASS_D_AND_C
:
2680 if (!riscv_subset_supports (rps
, "d"))
2682 if (!riscv_subset_supports (rps
, "c")
2683 && !riscv_subset_supports (rps
, "zcd"))
2684 return _("d' and `c', or `d' and `zcd");
2689 return _("c' or `zcd");
2690 case INSN_CLASS_F_INX
:
2691 return _("f' or `zfinx");
2692 case INSN_CLASS_D_INX
:
2693 return _("d' or `zdinx");
2694 case INSN_CLASS_Q_INX
:
2695 return _("q' or `zqinx");
2696 case INSN_CLASS_ZFH_INX
:
2697 return _("zfh' or `zhinx");
2698 case INSN_CLASS_ZFHMIN
:
2700 case INSN_CLASS_ZFHMIN_INX
:
2701 return _("zfhmin' or `zhinxmin");
2702 case INSN_CLASS_ZFHMIN_AND_D_INX
:
2703 if (riscv_subset_supports (rps
, "zfhmin"))
2705 else if (riscv_subset_supports (rps
, "d"))
2707 else if (riscv_subset_supports (rps
, "zhinxmin"))
2709 else if (riscv_subset_supports (rps
, "zdinx"))
2712 return _("zfhmin' and `d', or `zhinxmin' and `zdinx");
2713 case INSN_CLASS_ZFHMIN_AND_Q_INX
:
2714 if (riscv_subset_supports (rps
, "zfhmin"))
2716 else if (riscv_subset_supports (rps
, "q"))
2718 else if (riscv_subset_supports (rps
, "zhinxmin"))
2720 else if (riscv_subset_supports (rps
, "zqinx"))
2723 return _("zfhmin' and `q', or `zhinxmin' and `zqinx");
2724 case INSN_CLASS_ZFA
:
2726 case INSN_CLASS_D_AND_ZFA
:
2727 if (!riscv_subset_supports (rps
, "d")
2728 && !riscv_subset_supports (rps
, "zfa"))
2729 return _("d' and `zfa");
2730 else if (!riscv_subset_supports (rps
, "d"))
2734 case INSN_CLASS_Q_AND_ZFA
:
2735 if (!riscv_subset_supports (rps
, "q")
2736 && !riscv_subset_supports (rps
, "zfa"))
2737 return _("q' and `zfa");
2738 else if (!riscv_subset_supports (rps
, "q"))
2742 case INSN_CLASS_ZFH_AND_ZFA
:
2743 if (!riscv_subset_supports (rps
, "zfh")
2744 && !riscv_subset_supports (rps
, "zfa"))
2745 return _("zfh' and `zfa");
2746 else if (!riscv_subset_supports (rps
, "zfh"))
2750 case INSN_CLASS_ZFH_OR_ZVFH_AND_ZFA
:
2751 if (!riscv_subset_supports (rps
, "zfa"))
2753 if (!riscv_subset_supports (rps
, "zfh")
2754 && !riscv_subset_supports (rps
, "zvfh"))
2755 return _("zfh' and `zfa', or `zvfh' and `zfa");
2760 return _("zfh' or `zvfh");
2761 case INSN_CLASS_ZBA
:
2763 case INSN_CLASS_ZBB
:
2765 case INSN_CLASS_ZBC
:
2767 case INSN_CLASS_ZBS
:
2769 case INSN_CLASS_ZBKB
:
2771 case INSN_CLASS_ZBKC
:
2773 case INSN_CLASS_ZBKX
:
2775 case INSN_CLASS_ZBB_OR_ZBKB
:
2776 return _("zbb' or `zbkb");
2777 case INSN_CLASS_ZBC_OR_ZBKC
:
2778 return _("zbc' or `zbkc");
2779 case INSN_CLASS_ZKND
:
2781 case INSN_CLASS_ZKNE
:
2783 case INSN_CLASS_ZKNH
:
2785 case INSN_CLASS_ZKND_OR_ZKNE
:
2786 return _("zknd' or `zkne");
2787 case INSN_CLASS_ZKSED
:
2789 case INSN_CLASS_ZKSH
:
2792 return _("v' or `zve64x' or `zve32x");
2793 case INSN_CLASS_ZVEF
:
2794 return _("v' or `zve64d' or `zve64f' or `zve32f");
2795 case INSN_CLASS_ZVBB
:
2797 case INSN_CLASS_ZVBC
:
2799 case INSN_CLASS_ZVKB
:
2801 case INSN_CLASS_ZVKG
:
2803 case INSN_CLASS_ZVKNED
:
2805 case INSN_CLASS_ZVKNHA_OR_ZVKNHB
:
2806 return _("zvknha' or `zvknhb");
2807 case INSN_CLASS_ZVKSED
:
2809 case INSN_CLASS_ZVKSH
:
2811 case INSN_CLASS_ZCB
:
2813 case INSN_CLASS_ZCB_AND_ZBA
:
2814 return _("zcb' and `zba");
2815 case INSN_CLASS_ZCB_AND_ZBB
:
2816 return _("zcb' and `zbb");
2817 case INSN_CLASS_ZCB_AND_ZMMUL
:
2818 return _("zcb' and `zmmul', or `zcb' and `m");
2819 case INSN_CLASS_SVINVAL
:
2823 case INSN_CLASS_XCVMAC
:
2825 case INSN_CLASS_XCVALU
:
2827 case INSN_CLASS_XTHEADBA
:
2829 case INSN_CLASS_XTHEADBB
:
2831 case INSN_CLASS_XTHEADBS
:
2833 case INSN_CLASS_XTHEADCMO
:
2835 case INSN_CLASS_XTHEADCONDMOV
:
2836 return "xtheadcondmov";
2837 case INSN_CLASS_XTHEADFMEMIDX
:
2838 return "xtheadfmemidx";
2839 case INSN_CLASS_XTHEADFMV
:
2841 case INSN_CLASS_XTHEADINT
:
2843 case INSN_CLASS_XTHEADMAC
:
2845 case INSN_CLASS_XTHEADMEMIDX
:
2846 return "xtheadmemidx";
2847 case INSN_CLASS_XTHEADMEMPAIR
:
2848 return "xtheadmempair";
2849 case INSN_CLASS_XTHEADSYNC
:
2850 return "xtheadsync";
2851 case INSN_CLASS_XTHEADVECTOR
:
2852 return "xtheadvector";
2853 case INSN_CLASS_XTHEADZVAMO
:
2854 return "xtheadzvamo";
2857 (_("internal: unreachable INSN_CLASS_*"));