1 /* RISC-V-specific support for ELF.
2 Copyright (C) 2011-2021 Free Software Foundation, Inc.
4 Contributed by Andrew Waterman (andrew@sifive.com).
5 Based on TILE-Gx and MIPS targets.
7 This file is part of BFD, the Binary File Descriptor library.
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 3 of the License, or
12 (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with this program; see the file COPYING3. If not,
21 see <http://www.gnu.org/licenses/>. */
27 #include "elf/riscv.h"
28 #include "opcode/riscv.h"
29 #include "libiberty.h"
30 #include "elfxx-riscv.h"
31 #include "safe-ctype.h"
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 **);
42 /* The relocation table used for SHT_RELA sections. */
44 static reloc_howto_type howto_table
[] =
47 HOWTO (R_RISCV_NONE
, /* type */
51 false, /* pc_relative */
53 complain_overflow_dont
, /* complain_on_overflow */
54 bfd_elf_generic_reloc
, /* special_function */
55 "R_RISCV_NONE", /* name */
56 false, /* partial_inplace */
59 false), /* pcrel_offset */
61 /* 32 bit relocation. */
62 HOWTO (R_RISCV_32
, /* type */
66 false, /* pc_relative */
68 complain_overflow_dont
, /* complain_on_overflow */
69 bfd_elf_generic_reloc
, /* special_function */
70 "R_RISCV_32", /* name */
71 false, /* partial_inplace */
73 0xffffffff, /* dst_mask */
74 false), /* pcrel_offset */
76 /* 64 bit relocation. */
77 HOWTO (R_RISCV_64
, /* type */
81 false, /* pc_relative */
83 complain_overflow_dont
, /* complain_on_overflow */
84 bfd_elf_generic_reloc
, /* special_function */
85 "R_RISCV_64", /* name */
86 false, /* partial_inplace */
88 MINUS_ONE
, /* dst_mask */
89 false), /* pcrel_offset */
91 /* Relocation against a local symbol in a shared object. */
92 HOWTO (R_RISCV_RELATIVE
, /* type */
96 false, /* pc_relative */
98 complain_overflow_dont
, /* complain_on_overflow */
99 bfd_elf_generic_reloc
, /* special_function */
100 "R_RISCV_RELATIVE", /* name */
101 false, /* partial_inplace */
103 0xffffffff, /* dst_mask */
104 false), /* pcrel_offset */
106 HOWTO (R_RISCV_COPY
, /* type */
108 0, /* this one is variable size */
110 false, /* pc_relative */
112 complain_overflow_bitfield
, /* complain_on_overflow */
113 bfd_elf_generic_reloc
, /* special_function */
114 "R_RISCV_COPY", /* name */
115 false, /* partial_inplace */
118 false), /* pcrel_offset */
120 HOWTO (R_RISCV_JUMP_SLOT
, /* type */
124 false, /* pc_relative */
126 complain_overflow_bitfield
, /* complain_on_overflow */
127 bfd_elf_generic_reloc
, /* special_function */
128 "R_RISCV_JUMP_SLOT", /* name */
129 false, /* partial_inplace */
132 false), /* pcrel_offset */
134 /* Dynamic TLS relocations. */
135 HOWTO (R_RISCV_TLS_DTPMOD32
, /* type */
139 false, /* pc_relative */
141 complain_overflow_dont
, /* complain_on_overflow */
142 bfd_elf_generic_reloc
, /* special_function */
143 "R_RISCV_TLS_DTPMOD32", /* name */
144 false, /* partial_inplace */
146 0xffffffff, /* dst_mask */
147 false), /* pcrel_offset */
149 HOWTO (R_RISCV_TLS_DTPMOD64
, /* type */
153 false, /* pc_relative */
155 complain_overflow_dont
, /* complain_on_overflow */
156 bfd_elf_generic_reloc
, /* special_function */
157 "R_RISCV_TLS_DTPMOD64", /* name */
158 false, /* partial_inplace */
160 MINUS_ONE
, /* dst_mask */
161 false), /* pcrel_offset */
163 HOWTO (R_RISCV_TLS_DTPREL32
, /* type */
167 false, /* pc_relative */
169 complain_overflow_dont
, /* complain_on_overflow */
170 bfd_elf_generic_reloc
, /* special_function */
171 "R_RISCV_TLS_DTPREL32", /* name */
172 true, /* partial_inplace */
174 0xffffffff, /* dst_mask */
175 false), /* pcrel_offset */
177 HOWTO (R_RISCV_TLS_DTPREL64
, /* type */
181 false, /* pc_relative */
183 complain_overflow_dont
, /* complain_on_overflow */
184 bfd_elf_generic_reloc
, /* special_function */
185 "R_RISCV_TLS_DTPREL64", /* name */
186 true, /* partial_inplace */
188 MINUS_ONE
, /* dst_mask */
189 false), /* pcrel_offset */
191 HOWTO (R_RISCV_TLS_TPREL32
, /* type */
195 false, /* pc_relative */
197 complain_overflow_dont
, /* complain_on_overflow */
198 bfd_elf_generic_reloc
, /* special_function */
199 "R_RISCV_TLS_TPREL32", /* name */
200 false, /* partial_inplace */
202 0xffffffff, /* dst_mask */
203 false), /* pcrel_offset */
205 HOWTO (R_RISCV_TLS_TPREL64
, /* type */
209 false, /* pc_relative */
211 complain_overflow_dont
, /* complain_on_overflow */
212 bfd_elf_generic_reloc
, /* special_function */
213 "R_RISCV_TLS_TPREL64", /* name */
214 false, /* partial_inplace */
216 MINUS_ONE
, /* dst_mask */
217 false), /* pcrel_offset */
219 /* Reserved for future relocs that the dynamic linker must understand. */
225 /* 12-bit PC-relative branch offset. */
226 HOWTO (R_RISCV_BRANCH
, /* type */
230 true, /* pc_relative */
232 complain_overflow_signed
, /* complain_on_overflow */
233 bfd_elf_generic_reloc
, /* special_function */
234 "R_RISCV_BRANCH", /* name */
235 false, /* partial_inplace */
237 ENCODE_BTYPE_IMM (-1U), /* dst_mask */
238 true), /* pcrel_offset */
240 /* 20-bit PC-relative jump offset. */
241 HOWTO (R_RISCV_JAL
, /* type */
245 true, /* pc_relative */
247 complain_overflow_dont
, /* complain_on_overflow */
248 bfd_elf_generic_reloc
, /* special_function */
249 "R_RISCV_JAL", /* name */
250 false, /* partial_inplace */
252 ENCODE_JTYPE_IMM (-1U), /* dst_mask */
253 true), /* pcrel_offset */
255 /* 32-bit PC-relative function call (AUIPC/JALR). */
256 HOWTO (R_RISCV_CALL
, /* type */
260 true, /* pc_relative */
262 complain_overflow_dont
, /* complain_on_overflow */
263 bfd_elf_generic_reloc
, /* special_function */
264 "R_RISCV_CALL", /* name */
265 false, /* partial_inplace */
267 ENCODE_UTYPE_IMM (-1U) | ((bfd_vma
) ENCODE_ITYPE_IMM (-1U) << 32),
269 true), /* pcrel_offset */
271 /* Like R_RISCV_CALL, but not locally binding. */
272 HOWTO (R_RISCV_CALL_PLT
, /* type */
276 true, /* pc_relative */
278 complain_overflow_dont
, /* complain_on_overflow */
279 bfd_elf_generic_reloc
, /* special_function */
280 "R_RISCV_CALL_PLT", /* name */
281 false, /* partial_inplace */
283 ENCODE_UTYPE_IMM (-1U) | ((bfd_vma
) ENCODE_ITYPE_IMM (-1U) << 32),
285 true), /* pcrel_offset */
287 /* High 20 bits of 32-bit PC-relative GOT access. */
288 HOWTO (R_RISCV_GOT_HI20
, /* type */
292 true, /* pc_relative */
294 complain_overflow_dont
, /* complain_on_overflow */
295 bfd_elf_generic_reloc
, /* special_function */
296 "R_RISCV_GOT_HI20", /* name */
297 false, /* partial_inplace */
299 ENCODE_UTYPE_IMM (-1U), /* dst_mask */
300 false), /* pcrel_offset */
302 /* High 20 bits of 32-bit PC-relative TLS IE GOT access. */
303 HOWTO (R_RISCV_TLS_GOT_HI20
, /* type */
307 true, /* pc_relative */
309 complain_overflow_dont
, /* complain_on_overflow */
310 bfd_elf_generic_reloc
, /* special_function */
311 "R_RISCV_TLS_GOT_HI20", /* name */
312 false, /* partial_inplace */
314 ENCODE_UTYPE_IMM (-1U), /* dst_mask */
315 false), /* pcrel_offset */
317 /* High 20 bits of 32-bit PC-relative TLS GD GOT reference. */
318 HOWTO (R_RISCV_TLS_GD_HI20
, /* type */
322 true, /* pc_relative */
324 complain_overflow_dont
, /* complain_on_overflow */
325 bfd_elf_generic_reloc
, /* special_function */
326 "R_RISCV_TLS_GD_HI20", /* name */
327 false, /* partial_inplace */
329 ENCODE_UTYPE_IMM (-1U), /* dst_mask */
330 false), /* pcrel_offset */
332 /* High 20 bits of 32-bit PC-relative reference. */
333 HOWTO (R_RISCV_PCREL_HI20
, /* type */
337 true, /* pc_relative */
339 complain_overflow_dont
, /* complain_on_overflow */
340 bfd_elf_generic_reloc
, /* special_function */
341 "R_RISCV_PCREL_HI20", /* name */
342 false, /* partial_inplace */
344 ENCODE_UTYPE_IMM (-1U), /* dst_mask */
345 true), /* pcrel_offset */
347 /* Low 12 bits of a 32-bit PC-relative load or add. */
348 HOWTO (R_RISCV_PCREL_LO12_I
, /* type */
352 false, /* pc_relative */
354 complain_overflow_dont
, /* complain_on_overflow */
355 bfd_elf_generic_reloc
, /* special_function */
356 "R_RISCV_PCREL_LO12_I", /* name */
357 false, /* partial_inplace */
359 ENCODE_ITYPE_IMM (-1U), /* dst_mask */
360 false), /* pcrel_offset */
362 /* Low 12 bits of a 32-bit PC-relative store. */
363 HOWTO (R_RISCV_PCREL_LO12_S
, /* type */
367 false, /* pc_relative */
369 complain_overflow_dont
, /* complain_on_overflow */
370 bfd_elf_generic_reloc
, /* special_function */
371 "R_RISCV_PCREL_LO12_S", /* name */
372 false, /* partial_inplace */
374 ENCODE_STYPE_IMM (-1U), /* dst_mask */
375 false), /* pcrel_offset */
377 /* High 20 bits of 32-bit absolute address. */
378 HOWTO (R_RISCV_HI20
, /* type */
382 false, /* pc_relative */
384 complain_overflow_dont
, /* complain_on_overflow */
385 bfd_elf_generic_reloc
, /* special_function */
386 "R_RISCV_HI20", /* name */
387 false, /* partial_inplace */
389 ENCODE_UTYPE_IMM (-1U), /* dst_mask */
390 false), /* pcrel_offset */
392 /* High 12 bits of 32-bit load or add. */
393 HOWTO (R_RISCV_LO12_I
, /* type */
397 false, /* pc_relative */
399 complain_overflow_dont
, /* complain_on_overflow */
400 bfd_elf_generic_reloc
, /* special_function */
401 "R_RISCV_LO12_I", /* name */
402 false, /* partial_inplace */
404 ENCODE_ITYPE_IMM (-1U), /* dst_mask */
405 false), /* pcrel_offset */
407 /* High 12 bits of 32-bit store. */
408 HOWTO (R_RISCV_LO12_S
, /* type */
412 false, /* pc_relative */
414 complain_overflow_dont
, /* complain_on_overflow */
415 bfd_elf_generic_reloc
, /* special_function */
416 "R_RISCV_LO12_S", /* name */
417 false, /* partial_inplace */
419 ENCODE_STYPE_IMM (-1U), /* dst_mask */
420 false), /* pcrel_offset */
422 /* High 20 bits of TLS LE thread pointer offset. */
423 HOWTO (R_RISCV_TPREL_HI20
, /* type */
427 false, /* pc_relative */
429 complain_overflow_signed
, /* complain_on_overflow */
430 bfd_elf_generic_reloc
, /* special_function */
431 "R_RISCV_TPREL_HI20", /* name */
432 true, /* partial_inplace */
434 ENCODE_UTYPE_IMM (-1U), /* dst_mask */
435 false), /* pcrel_offset */
437 /* Low 12 bits of TLS LE thread pointer offset for loads and adds. */
438 HOWTO (R_RISCV_TPREL_LO12_I
, /* type */
442 false, /* pc_relative */
444 complain_overflow_signed
, /* complain_on_overflow */
445 bfd_elf_generic_reloc
, /* special_function */
446 "R_RISCV_TPREL_LO12_I", /* name */
447 false, /* partial_inplace */
449 ENCODE_ITYPE_IMM (-1U), /* dst_mask */
450 false), /* pcrel_offset */
452 /* Low 12 bits of TLS LE thread pointer offset for stores. */
453 HOWTO (R_RISCV_TPREL_LO12_S
, /* type */
457 false, /* pc_relative */
459 complain_overflow_signed
, /* complain_on_overflow */
460 bfd_elf_generic_reloc
, /* special_function */
461 "R_RISCV_TPREL_LO12_S", /* name */
462 false, /* partial_inplace */
464 ENCODE_STYPE_IMM (-1U), /* dst_mask */
465 false), /* pcrel_offset */
467 /* TLS LE thread pointer usage. May be relaxed. */
468 HOWTO (R_RISCV_TPREL_ADD
, /* type */
472 false, /* pc_relative */
474 complain_overflow_dont
, /* complain_on_overflow */
475 bfd_elf_generic_reloc
, /* special_function */
476 "R_RISCV_TPREL_ADD", /* name */
477 false, /* partial_inplace */
480 false), /* pcrel_offset */
482 /* 8-bit in-place addition, for local label subtraction. */
483 HOWTO (R_RISCV_ADD8
, /* type */
487 false, /* pc_relative */
489 complain_overflow_dont
, /* complain_on_overflow */
490 riscv_elf_add_sub_reloc
, /* special_function */
491 "R_RISCV_ADD8", /* name */
492 false, /* partial_inplace */
495 false), /* pcrel_offset */
497 /* 16-bit in-place addition, for local label subtraction. */
498 HOWTO (R_RISCV_ADD16
, /* type */
502 false, /* pc_relative */
504 complain_overflow_dont
, /* complain_on_overflow */
505 riscv_elf_add_sub_reloc
, /* special_function */
506 "R_RISCV_ADD16", /* name */
507 false, /* partial_inplace */
509 0xffff, /* dst_mask */
510 false), /* pcrel_offset */
512 /* 32-bit in-place addition, for local label subtraction. */
513 HOWTO (R_RISCV_ADD32
, /* type */
517 false, /* pc_relative */
519 complain_overflow_dont
, /* complain_on_overflow */
520 riscv_elf_add_sub_reloc
, /* special_function */
521 "R_RISCV_ADD32", /* name */
522 false, /* partial_inplace */
524 0xffffffff, /* dst_mask */
525 false), /* pcrel_offset */
527 /* 64-bit in-place addition, for local label subtraction. */
528 HOWTO (R_RISCV_ADD64
, /* type */
532 false, /* pc_relative */
534 complain_overflow_dont
, /* complain_on_overflow */
535 riscv_elf_add_sub_reloc
, /* special_function */
536 "R_RISCV_ADD64", /* name */
537 false, /* partial_inplace */
539 MINUS_ONE
, /* dst_mask */
540 false), /* pcrel_offset */
542 /* 8-bit in-place addition, for local label subtraction. */
543 HOWTO (R_RISCV_SUB8
, /* type */
547 false, /* pc_relative */
549 complain_overflow_dont
, /* complain_on_overflow */
550 riscv_elf_add_sub_reloc
, /* special_function */
551 "R_RISCV_SUB8", /* name */
552 false, /* partial_inplace */
555 false), /* pcrel_offset */
557 /* 16-bit in-place addition, for local label subtraction. */
558 HOWTO (R_RISCV_SUB16
, /* type */
562 false, /* pc_relative */
564 complain_overflow_dont
, /* complain_on_overflow */
565 riscv_elf_add_sub_reloc
, /* special_function */
566 "R_RISCV_SUB16", /* name */
567 false, /* partial_inplace */
569 0xffff, /* dst_mask */
570 false), /* pcrel_offset */
572 /* 32-bit in-place addition, for local label subtraction. */
573 HOWTO (R_RISCV_SUB32
, /* type */
577 false, /* pc_relative */
579 complain_overflow_dont
, /* complain_on_overflow */
580 riscv_elf_add_sub_reloc
, /* special_function */
581 "R_RISCV_SUB32", /* name */
582 false, /* partial_inplace */
584 0xffffffff, /* dst_mask */
585 false), /* pcrel_offset */
587 /* 64-bit in-place addition, for local label subtraction. */
588 HOWTO (R_RISCV_SUB64
, /* type */
592 false, /* pc_relative */
594 complain_overflow_dont
, /* complain_on_overflow */
595 riscv_elf_add_sub_reloc
, /* special_function */
596 "R_RISCV_SUB64", /* name */
597 false, /* partial_inplace */
599 MINUS_ONE
, /* dst_mask */
600 false), /* pcrel_offset */
602 /* GNU extension to record C++ vtable hierarchy */
603 HOWTO (R_RISCV_GNU_VTINHERIT
, /* type */
607 false, /* pc_relative */
609 complain_overflow_dont
, /* complain_on_overflow */
610 NULL
, /* special_function */
611 "R_RISCV_GNU_VTINHERIT", /* name */
612 false, /* partial_inplace */
615 false), /* pcrel_offset */
617 /* GNU extension to record C++ vtable member usage */
618 HOWTO (R_RISCV_GNU_VTENTRY
, /* type */
622 false, /* pc_relative */
624 complain_overflow_dont
, /* complain_on_overflow */
625 _bfd_elf_rel_vtable_reloc_fn
, /* special_function */
626 "R_RISCV_GNU_VTENTRY", /* name */
627 false, /* partial_inplace */
630 false), /* pcrel_offset */
632 /* Indicates an alignment statement. The addend field encodes how many
633 bytes of NOPs follow the statement. The desired alignment is the
634 addend rounded up to the next power of two. */
635 HOWTO (R_RISCV_ALIGN
, /* type */
639 false, /* pc_relative */
641 complain_overflow_dont
, /* complain_on_overflow */
642 bfd_elf_generic_reloc
, /* special_function */
643 "R_RISCV_ALIGN", /* name */
644 false, /* partial_inplace */
647 false), /* pcrel_offset */
649 /* 8-bit PC-relative branch offset. */
650 HOWTO (R_RISCV_RVC_BRANCH
, /* type */
654 true, /* pc_relative */
656 complain_overflow_signed
, /* complain_on_overflow */
657 bfd_elf_generic_reloc
, /* special_function */
658 "R_RISCV_RVC_BRANCH", /* name */
659 false, /* partial_inplace */
661 ENCODE_CBTYPE_IMM (-1U), /* dst_mask */
662 true), /* pcrel_offset */
664 /* 11-bit PC-relative jump offset. */
665 HOWTO (R_RISCV_RVC_JUMP
, /* type */
669 true, /* pc_relative */
671 complain_overflow_dont
, /* complain_on_overflow */
672 bfd_elf_generic_reloc
, /* special_function */
673 "R_RISCV_RVC_JUMP", /* name */
674 false, /* partial_inplace */
676 ENCODE_CJTYPE_IMM (-1U), /* dst_mask */
677 true), /* pcrel_offset */
679 /* High 6 bits of 18-bit absolute address. */
680 HOWTO (R_RISCV_RVC_LUI
, /* type */
684 false, /* pc_relative */
686 complain_overflow_dont
, /* complain_on_overflow */
687 bfd_elf_generic_reloc
, /* special_function */
688 "R_RISCV_RVC_LUI", /* name */
689 false, /* partial_inplace */
691 ENCODE_CITYPE_IMM (-1U), /* dst_mask */
692 false), /* pcrel_offset */
694 /* GP-relative load. */
695 HOWTO (R_RISCV_GPREL_I
, /* type */
699 false, /* pc_relative */
701 complain_overflow_dont
, /* complain_on_overflow */
702 bfd_elf_generic_reloc
, /* special_function */
703 "R_RISCV_GPREL_I", /* name */
704 false, /* partial_inplace */
706 ENCODE_ITYPE_IMM (-1U), /* dst_mask */
707 false), /* pcrel_offset */
709 /* GP-relative store. */
710 HOWTO (R_RISCV_GPREL_S
, /* type */
714 false, /* pc_relative */
716 complain_overflow_dont
, /* complain_on_overflow */
717 bfd_elf_generic_reloc
, /* special_function */
718 "R_RISCV_GPREL_S", /* name */
719 false, /* partial_inplace */
721 ENCODE_STYPE_IMM (-1U), /* dst_mask */
722 false), /* pcrel_offset */
724 /* TP-relative TLS LE load. */
725 HOWTO (R_RISCV_TPREL_I
, /* type */
729 false, /* pc_relative */
731 complain_overflow_signed
, /* complain_on_overflow */
732 bfd_elf_generic_reloc
, /* special_function */
733 "R_RISCV_TPREL_I", /* name */
734 false, /* partial_inplace */
736 ENCODE_ITYPE_IMM (-1U), /* dst_mask */
737 false), /* pcrel_offset */
739 /* TP-relative TLS LE store. */
740 HOWTO (R_RISCV_TPREL_S
, /* type */
744 false, /* pc_relative */
746 complain_overflow_signed
, /* complain_on_overflow */
747 bfd_elf_generic_reloc
, /* special_function */
748 "R_RISCV_TPREL_S", /* name */
749 false, /* partial_inplace */
751 ENCODE_STYPE_IMM (-1U), /* dst_mask */
752 false), /* pcrel_offset */
754 /* The paired relocation may be relaxed. */
755 HOWTO (R_RISCV_RELAX
, /* type */
759 false, /* pc_relative */
761 complain_overflow_dont
, /* complain_on_overflow */
762 bfd_elf_generic_reloc
, /* special_function */
763 "R_RISCV_RELAX", /* name */
764 false, /* partial_inplace */
767 false), /* pcrel_offset */
769 /* 6-bit in-place addition, for local label subtraction. */
770 HOWTO (R_RISCV_SUB6
, /* type */
774 false, /* pc_relative */
776 complain_overflow_dont
, /* complain_on_overflow */
777 riscv_elf_add_sub_reloc
, /* special_function */
778 "R_RISCV_SUB6", /* name */
779 false, /* partial_inplace */
782 false), /* pcrel_offset */
784 /* 6-bit in-place setting, for local label subtraction. */
785 HOWTO (R_RISCV_SET6
, /* type */
789 false, /* pc_relative */
791 complain_overflow_dont
, /* complain_on_overflow */
792 bfd_elf_generic_reloc
, /* special_function */
793 "R_RISCV_SET6", /* name */
794 false, /* partial_inplace */
797 false), /* pcrel_offset */
799 /* 8-bit in-place setting, for local label subtraction. */
800 HOWTO (R_RISCV_SET8
, /* type */
804 false, /* pc_relative */
806 complain_overflow_dont
, /* complain_on_overflow */
807 bfd_elf_generic_reloc
, /* special_function */
808 "R_RISCV_SET8", /* name */
809 false, /* partial_inplace */
812 false), /* pcrel_offset */
814 /* 16-bit in-place setting, for local label subtraction. */
815 HOWTO (R_RISCV_SET16
, /* type */
819 false, /* pc_relative */
821 complain_overflow_dont
, /* complain_on_overflow */
822 bfd_elf_generic_reloc
, /* special_function */
823 "R_RISCV_SET16", /* name */
824 false, /* partial_inplace */
826 0xffff, /* dst_mask */
827 false), /* pcrel_offset */
829 /* 32-bit in-place setting, for local label subtraction. */
830 HOWTO (R_RISCV_SET32
, /* type */
834 false, /* pc_relative */
836 complain_overflow_dont
, /* complain_on_overflow */
837 bfd_elf_generic_reloc
, /* special_function */
838 "R_RISCV_SET32", /* name */
839 false, /* partial_inplace */
841 0xffffffff, /* dst_mask */
842 false), /* pcrel_offset */
844 /* 32-bit PC relative. */
845 HOWTO (R_RISCV_32_PCREL
, /* type */
849 true, /* pc_relative */
851 complain_overflow_dont
, /* complain_on_overflow */
852 bfd_elf_generic_reloc
, /* special_function */
853 "R_RISCV_32_PCREL", /* name */
854 false, /* partial_inplace */
856 0xffffffff, /* dst_mask */
857 false), /* pcrel_offset */
859 /* Relocation against a local ifunc symbol in a shared object. */
860 HOWTO (R_RISCV_IRELATIVE
, /* type */
864 false, /* pc_relative */
866 complain_overflow_dont
, /* complain_on_overflow */
867 bfd_elf_generic_reloc
, /* special_function */
868 "R_RISCV_IRELATIVE", /* name */
869 false, /* partial_inplace */
871 0xffffffff, /* dst_mask */
872 false), /* pcrel_offset */
875 /* A mapping from BFD reloc types to RISC-V ELF reloc types. */
878 bfd_reloc_code_real_type bfd_val
;
879 enum elf_riscv_reloc_type elf_val
;
882 static const struct elf_reloc_map riscv_reloc_map
[] =
884 { BFD_RELOC_NONE
, R_RISCV_NONE
},
885 { BFD_RELOC_32
, R_RISCV_32
},
886 { BFD_RELOC_64
, R_RISCV_64
},
887 { BFD_RELOC_RISCV_ADD8
, R_RISCV_ADD8
},
888 { BFD_RELOC_RISCV_ADD16
, R_RISCV_ADD16
},
889 { BFD_RELOC_RISCV_ADD32
, R_RISCV_ADD32
},
890 { BFD_RELOC_RISCV_ADD64
, R_RISCV_ADD64
},
891 { BFD_RELOC_RISCV_SUB8
, R_RISCV_SUB8
},
892 { BFD_RELOC_RISCV_SUB16
, R_RISCV_SUB16
},
893 { BFD_RELOC_RISCV_SUB32
, R_RISCV_SUB32
},
894 { BFD_RELOC_RISCV_SUB64
, R_RISCV_SUB64
},
895 { BFD_RELOC_CTOR
, R_RISCV_64
},
896 { BFD_RELOC_12_PCREL
, R_RISCV_BRANCH
},
897 { BFD_RELOC_RISCV_HI20
, R_RISCV_HI20
},
898 { BFD_RELOC_RISCV_LO12_I
, R_RISCV_LO12_I
},
899 { BFD_RELOC_RISCV_LO12_S
, R_RISCV_LO12_S
},
900 { BFD_RELOC_RISCV_PCREL_LO12_I
, R_RISCV_PCREL_LO12_I
},
901 { BFD_RELOC_RISCV_PCREL_LO12_S
, R_RISCV_PCREL_LO12_S
},
902 { BFD_RELOC_RISCV_CALL
, R_RISCV_CALL
},
903 { BFD_RELOC_RISCV_CALL_PLT
, R_RISCV_CALL_PLT
},
904 { BFD_RELOC_RISCV_PCREL_HI20
, R_RISCV_PCREL_HI20
},
905 { BFD_RELOC_RISCV_JMP
, R_RISCV_JAL
},
906 { BFD_RELOC_RISCV_GOT_HI20
, R_RISCV_GOT_HI20
},
907 { BFD_RELOC_RISCV_TLS_DTPMOD32
, R_RISCV_TLS_DTPMOD32
},
908 { BFD_RELOC_RISCV_TLS_DTPREL32
, R_RISCV_TLS_DTPREL32
},
909 { BFD_RELOC_RISCV_TLS_DTPMOD64
, R_RISCV_TLS_DTPMOD64
},
910 { BFD_RELOC_RISCV_TLS_DTPREL64
, R_RISCV_TLS_DTPREL64
},
911 { BFD_RELOC_RISCV_TLS_TPREL32
, R_RISCV_TLS_TPREL32
},
912 { BFD_RELOC_RISCV_TLS_TPREL64
, R_RISCV_TLS_TPREL64
},
913 { BFD_RELOC_RISCV_TPREL_HI20
, R_RISCV_TPREL_HI20
},
914 { BFD_RELOC_RISCV_TPREL_ADD
, R_RISCV_TPREL_ADD
},
915 { BFD_RELOC_RISCV_TPREL_LO12_S
, R_RISCV_TPREL_LO12_S
},
916 { BFD_RELOC_RISCV_TPREL_LO12_I
, R_RISCV_TPREL_LO12_I
},
917 { BFD_RELOC_RISCV_TLS_GOT_HI20
, R_RISCV_TLS_GOT_HI20
},
918 { BFD_RELOC_RISCV_TLS_GD_HI20
, R_RISCV_TLS_GD_HI20
},
919 { BFD_RELOC_RISCV_ALIGN
, R_RISCV_ALIGN
},
920 { BFD_RELOC_RISCV_RVC_BRANCH
, R_RISCV_RVC_BRANCH
},
921 { BFD_RELOC_RISCV_RVC_JUMP
, R_RISCV_RVC_JUMP
},
922 { BFD_RELOC_RISCV_RVC_LUI
, R_RISCV_RVC_LUI
},
923 { BFD_RELOC_RISCV_GPREL_I
, R_RISCV_GPREL_I
},
924 { BFD_RELOC_RISCV_GPREL_S
, R_RISCV_GPREL_S
},
925 { BFD_RELOC_RISCV_TPREL_I
, R_RISCV_TPREL_I
},
926 { BFD_RELOC_RISCV_TPREL_S
, R_RISCV_TPREL_S
},
927 { BFD_RELOC_RISCV_RELAX
, R_RISCV_RELAX
},
928 { BFD_RELOC_RISCV_SUB6
, R_RISCV_SUB6
},
929 { BFD_RELOC_RISCV_SET6
, R_RISCV_SET6
},
930 { BFD_RELOC_RISCV_SET8
, R_RISCV_SET8
},
931 { BFD_RELOC_RISCV_SET16
, R_RISCV_SET16
},
932 { BFD_RELOC_RISCV_SET32
, R_RISCV_SET32
},
933 { BFD_RELOC_RISCV_32_PCREL
, R_RISCV_32_PCREL
},
936 /* Given a BFD reloc type, return a howto structure. */
939 riscv_reloc_type_lookup (bfd
*abfd ATTRIBUTE_UNUSED
,
940 bfd_reloc_code_real_type code
)
944 for (i
= 0; i
< ARRAY_SIZE (riscv_reloc_map
); i
++)
945 if (riscv_reloc_map
[i
].bfd_val
== code
)
946 return &howto_table
[(int) riscv_reloc_map
[i
].elf_val
];
948 bfd_set_error (bfd_error_bad_value
);
953 riscv_reloc_name_lookup (bfd
*abfd ATTRIBUTE_UNUSED
, const char *r_name
)
957 for (i
= 0; i
< ARRAY_SIZE (howto_table
); i
++)
958 if (howto_table
[i
].name
&& strcasecmp (howto_table
[i
].name
, r_name
) == 0)
959 return &howto_table
[i
];
965 riscv_elf_rtype_to_howto (bfd
*abfd
, unsigned int r_type
)
967 if (r_type
>= ARRAY_SIZE (howto_table
))
969 (*_bfd_error_handler
) (_("%pB: unsupported relocation type %#x"),
971 bfd_set_error (bfd_error_bad_value
);
974 return &howto_table
[r_type
];
977 /* Special_function of RISCV_ADD and RISCV_SUB relocations. */
979 static bfd_reloc_status_type
980 riscv_elf_add_sub_reloc (bfd
*abfd
,
981 arelent
*reloc_entry
,
984 asection
*input_section
,
986 char **error_message ATTRIBUTE_UNUSED
)
988 reloc_howto_type
*howto
= reloc_entry
->howto
;
991 if (output_bfd
!= NULL
992 && (symbol
->flags
& BSF_SECTION_SYM
) == 0
993 && (!reloc_entry
->howto
->partial_inplace
|| reloc_entry
->addend
== 0))
995 reloc_entry
->address
+= input_section
->output_offset
;
999 if (output_bfd
!= NULL
)
1000 return bfd_reloc_continue
;
1002 relocation
= symbol
->value
+ symbol
->section
->output_section
->vma
1003 + symbol
->section
->output_offset
+ reloc_entry
->addend
;
1005 bfd_size_type octets
= reloc_entry
->address
1006 * bfd_octets_per_byte (abfd
, input_section
);
1007 if (!bfd_reloc_offset_in_range (reloc_entry
->howto
, abfd
,
1008 input_section
, octets
))
1009 return bfd_reloc_outofrange
;
1011 bfd_vma old_value
= bfd_get (howto
->bitsize
, abfd
,
1012 data
+ reloc_entry
->address
);
1014 switch (howto
->type
)
1020 relocation
= old_value
+ relocation
;
1027 relocation
= old_value
- relocation
;
1030 bfd_put (howto
->bitsize
, abfd
, relocation
, data
+ reloc_entry
->address
);
1032 return bfd_reloc_ok
;
1035 /* Always add the IMPLICIT for the SUBSET. */
1038 check_implicit_always (const char *implicit ATTRIBUTE_UNUSED
,
1039 riscv_subset_t
*subset ATTRIBUTE_UNUSED
)
1044 /* Add the IMPLICIT only when the version of SUBSET less than 2.1. */
1047 check_implicit_for_i (const char *implicit ATTRIBUTE_UNUSED
,
1048 riscv_subset_t
*subset
)
1050 return (subset
->major_version
< 2
1051 || (subset
->major_version
== 2
1052 && subset
->minor_version
< 1));
1055 /* Record all implicit information for the subsets. */
1056 struct riscv_implicit_subset
1058 const char *subset_name
;
1059 const char *implicit_name
;
1060 /* A function to determine if we need to add the implicit subset. */
1061 bool (*check_func
) (const char *, riscv_subset_t
*);
1063 static struct riscv_implicit_subset riscv_implicit_subsets
[] =
1065 {"e", "i", check_implicit_always
},
1066 {"i", "zicsr", check_implicit_for_i
},
1067 {"i", "zifencei", check_implicit_for_i
},
1068 {"g", "i", check_implicit_always
},
1069 {"g", "m", check_implicit_always
},
1070 {"g", "a", check_implicit_always
},
1071 {"g", "f", check_implicit_always
},
1072 {"g", "d", check_implicit_always
},
1073 {"g", "zicsr", check_implicit_always
},
1074 {"g", "zifencei", check_implicit_always
},
1075 {"q", "d", check_implicit_always
},
1076 {"v", "d", check_implicit_always
},
1077 {"v", "zve64d", check_implicit_always
},
1078 {"v", "zvl128b", check_implicit_always
},
1079 {"zve64d", "d", check_implicit_always
},
1080 {"zve64d", "zve64f", check_implicit_always
},
1081 {"zve64f", "zve32f", check_implicit_always
},
1082 {"zve64f", "zve64x", check_implicit_always
},
1083 {"zve64f", "zvl64b", check_implicit_always
},
1084 {"zve32f", "f", check_implicit_always
},
1085 {"zve32f", "zvl32b", check_implicit_always
},
1086 {"zve32f", "zve32x", check_implicit_always
},
1087 {"zve64x", "zve32x", check_implicit_always
},
1088 {"zve64x", "zvl64b", check_implicit_always
},
1089 {"zve32x", "zvl32b", check_implicit_always
},
1090 {"zvl65536b", "zvl32768b", check_implicit_always
},
1091 {"zvl32768b", "zvl16384b", check_implicit_always
},
1092 {"zvl16384b", "zvl8192b", check_implicit_always
},
1093 {"zvl8192b", "zvl4096b", check_implicit_always
},
1094 {"zvl4096b", "zvl2048b", check_implicit_always
},
1095 {"zvl2048b", "zvl1024b", check_implicit_always
},
1096 {"zvl1024b", "zvl512b", check_implicit_always
},
1097 {"zvl512b", "zvl256b", check_implicit_always
},
1098 {"zvl256b", "zvl128b", check_implicit_always
},
1099 {"zvl128b", "zvl64b", check_implicit_always
},
1100 {"zvl64b", "zvl32b", check_implicit_always
},
1101 {"d", "f", check_implicit_always
},
1102 {"f", "zicsr", check_implicit_always
},
1103 {"zk", "zkn", check_implicit_always
},
1104 {"zk", "zkr", check_implicit_always
},
1105 {"zk", "zkt", check_implicit_always
},
1106 {"zkn", "zbkb", check_implicit_always
},
1107 {"zkn", "zbkc", check_implicit_always
},
1108 {"zkn", "zbkx", check_implicit_always
},
1109 {"zkn", "zkne", check_implicit_always
},
1110 {"zkn", "zknd", check_implicit_always
},
1111 {"zkn", "zknh", check_implicit_always
},
1112 {"zks", "zbkb", check_implicit_always
},
1113 {"zks", "zbkc", check_implicit_always
},
1114 {"zks", "zbkx", check_implicit_always
},
1115 {"zks", "zksed", check_implicit_always
},
1116 {"zks", "zksh", check_implicit_always
},
1120 /* For default_enable field, decide if the extension should
1121 be enbaled by default. */
1123 #define EXT_DEFAULT 0x1
1125 /* List all extensions that binutils should know about. */
1127 struct riscv_supported_ext
1130 enum riscv_spec_class isa_spec_class
;
1133 unsigned long default_enable
;
1136 /* The standard extensions must be added in canonical order. */
1138 static struct riscv_supported_ext riscv_supported_std_ext
[] =
1140 {"e", ISA_SPEC_CLASS_20191213
, 1, 9, 0 },
1141 {"e", ISA_SPEC_CLASS_20190608
, 1, 9, 0 },
1142 {"e", ISA_SPEC_CLASS_2P2
, 1, 9, 0 },
1143 {"i", ISA_SPEC_CLASS_20191213
, 2, 1, 0 },
1144 {"i", ISA_SPEC_CLASS_20190608
, 2, 1, 0 },
1145 {"i", ISA_SPEC_CLASS_2P2
, 2, 0, 0 },
1146 /* The g is a special case which we don't want to output it,
1147 but still need it when adding implicit extensions. */
1148 {"g", ISA_SPEC_CLASS_NONE
, RISCV_UNKNOWN_VERSION
, RISCV_UNKNOWN_VERSION
, EXT_DEFAULT
},
1149 {"m", ISA_SPEC_CLASS_20191213
, 2, 0, 0 },
1150 {"m", ISA_SPEC_CLASS_20190608
, 2, 0, 0 },
1151 {"m", ISA_SPEC_CLASS_2P2
, 2, 0, 0 },
1152 {"a", ISA_SPEC_CLASS_20191213
, 2, 1, 0 },
1153 {"a", ISA_SPEC_CLASS_20190608
, 2, 0, 0 },
1154 {"a", ISA_SPEC_CLASS_2P2
, 2, 0, 0 },
1155 {"f", ISA_SPEC_CLASS_20191213
, 2, 2, 0 },
1156 {"f", ISA_SPEC_CLASS_20190608
, 2, 2, 0 },
1157 {"f", ISA_SPEC_CLASS_2P2
, 2, 0, 0 },
1158 {"d", ISA_SPEC_CLASS_20191213
, 2, 2, 0 },
1159 {"d", ISA_SPEC_CLASS_20190608
, 2, 2, 0 },
1160 {"d", ISA_SPEC_CLASS_2P2
, 2, 0, 0 },
1161 {"q", ISA_SPEC_CLASS_20191213
, 2, 2, 0 },
1162 {"q", ISA_SPEC_CLASS_20190608
, 2, 2, 0 },
1163 {"q", ISA_SPEC_CLASS_2P2
, 2, 0, 0 },
1164 {"l", ISA_SPEC_CLASS_NONE
, RISCV_UNKNOWN_VERSION
, RISCV_UNKNOWN_VERSION
, 0 },
1165 {"c", ISA_SPEC_CLASS_20191213
, 2, 0, 0 },
1166 {"c", ISA_SPEC_CLASS_20190608
, 2, 0, 0 },
1167 {"c", ISA_SPEC_CLASS_2P2
, 2, 0, 0 },
1168 {"b", ISA_SPEC_CLASS_NONE
, RISCV_UNKNOWN_VERSION
, RISCV_UNKNOWN_VERSION
, 0 },
1169 {"k", ISA_SPEC_CLASS_NONE
, RISCV_UNKNOWN_VERSION
, RISCV_UNKNOWN_VERSION
, 0 },
1170 {"j", ISA_SPEC_CLASS_NONE
, RISCV_UNKNOWN_VERSION
, RISCV_UNKNOWN_VERSION
, 0 },
1171 {"t", ISA_SPEC_CLASS_NONE
, RISCV_UNKNOWN_VERSION
, RISCV_UNKNOWN_VERSION
, 0 },
1172 {"p", ISA_SPEC_CLASS_NONE
, RISCV_UNKNOWN_VERSION
, RISCV_UNKNOWN_VERSION
, 0 },
1173 {"v", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1174 {"n", ISA_SPEC_CLASS_NONE
, RISCV_UNKNOWN_VERSION
, RISCV_UNKNOWN_VERSION
, 0 },
1178 static struct riscv_supported_ext riscv_supported_std_z_ext
[] =
1180 {"zicsr", ISA_SPEC_CLASS_20191213
, 2, 0, 0 },
1181 {"zicsr", ISA_SPEC_CLASS_20190608
, 2, 0, 0 },
1182 {"zifencei", ISA_SPEC_CLASS_20191213
, 2, 0, 0 },
1183 {"zifencei", ISA_SPEC_CLASS_20190608
, 2, 0, 0 },
1184 {"zihintpause", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1185 {"zbb", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1186 {"zba", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1187 {"zbc", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1188 {"zbs", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1189 {"zbkb", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1190 {"zbkc", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1191 {"zbkx", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1192 {"zk", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1193 {"zkn", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1194 {"zknd", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1195 {"zkne", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1196 {"zknh", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1197 {"zkr", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1198 {"zks", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1199 {"zksed", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1200 {"zksh", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1201 {"zkt", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1202 {"zve32x", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1203 {"zve32f", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1204 {"zve32d", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1205 {"zve64x", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1206 {"zve64f", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1207 {"zve64d", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1208 {"zvl32b", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1209 {"zvl64b", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1210 {"zvl128b", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1211 {"zvl256b", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1212 {"zvl512b", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1213 {"zvl1024b", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1214 {"zvl2048b", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1215 {"zvl4096b", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1216 {"zvl8192b", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1217 {"zvl16384b", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1218 {"zvl32768b", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1219 {"zvl65536b", ISA_SPEC_CLASS_DRAFT
, 1, 0, 0 },
1223 static struct riscv_supported_ext riscv_supported_std_s_ext
[] =
1228 static struct riscv_supported_ext riscv_supported_std_h_ext
[] =
1233 static struct riscv_supported_ext riscv_supported_std_zxm_ext
[] =
1238 const struct riscv_supported_ext
*riscv_all_supported_ext
[] =
1240 riscv_supported_std_ext
,
1241 riscv_supported_std_z_ext
,
1242 riscv_supported_std_s_ext
,
1243 riscv_supported_std_h_ext
,
1244 riscv_supported_std_zxm_ext
,
1248 /* ISA extension prefixed name class. Must define them in parsing order. */
1249 enum riscv_prefix_ext_class
1256 RV_ISA_CLASS_UNKNOWN
1259 /* Record the strings of the prefixed extensions, and their corresponding
1260 classes. The more letters of the prefix string, the more forward it must
1261 be defined. Otherwise, the riscv_get_prefix_class will map it to the
1263 struct riscv_parse_prefix_config
1265 /* Class of the extension. */
1266 enum riscv_prefix_ext_class
class;
1268 /* Prefix string for error printing and internal parser usage. */
1271 static const struct riscv_parse_prefix_config parse_config
[] =
1273 {RV_ISA_CLASS_ZXM
, "zxm"},
1274 {RV_ISA_CLASS_Z
, "z"},
1275 {RV_ISA_CLASS_S
, "s"},
1276 {RV_ISA_CLASS_H
, "h"},
1277 {RV_ISA_CLASS_X
, "x"},
1278 {RV_ISA_CLASS_UNKNOWN
, NULL
}
1281 /* Get the prefixed name class for the extensions, the class also
1282 means the order of the prefixed extensions. */
1284 static enum riscv_prefix_ext_class
1285 riscv_get_prefix_class (const char *arch
)
1288 while (parse_config
[i
].class != RV_ISA_CLASS_UNKNOWN
)
1290 if (strncmp (arch
, parse_config
[i
].prefix
,
1291 strlen (parse_config
[i
].prefix
)) == 0)
1292 return parse_config
[i
].class;
1295 return RV_ISA_CLASS_UNKNOWN
;
1298 /* Check KNOWN_EXTS to see if the EXT is supported. */
1301 riscv_known_prefixed_ext (const char *ext
,
1302 struct riscv_supported_ext
*known_exts
)
1305 for (i
= 0; known_exts
[i
].name
!= NULL
; ++i
)
1306 if (strcmp (ext
, known_exts
[i
].name
) == 0)
1311 /* Check whether the prefixed extension is recognized or not. Return
1312 true if recognized, otehrwise return false. */
1315 riscv_recognized_prefixed_ext (const char *ext
)
1317 enum riscv_prefix_ext_class
class = riscv_get_prefix_class (ext
);
1320 case RV_ISA_CLASS_Z
:
1321 return riscv_known_prefixed_ext (ext
, riscv_supported_std_z_ext
);
1322 case RV_ISA_CLASS_ZXM
:
1323 return riscv_known_prefixed_ext (ext
, riscv_supported_std_zxm_ext
);
1324 case RV_ISA_CLASS_S
:
1325 return riscv_known_prefixed_ext (ext
, riscv_supported_std_s_ext
);
1326 case RV_ISA_CLASS_H
:
1327 return riscv_known_prefixed_ext (ext
, riscv_supported_std_h_ext
);
1328 case RV_ISA_CLASS_X
:
1329 /* Only the single x is unrecognized. */
1330 if (strcmp (ext
, "x") != 0)
1338 /* Array is used to compare the orders of standard extensions quickly. */
1339 static int riscv_ext_order
[26] = {0};
1341 /* Init the riscv_ext_order array. */
1344 riscv_init_ext_order (void)
1346 static bool inited
= false;
1350 /* The orders of all standard extensions are positive. */
1354 while (riscv_supported_std_ext
[i
].name
!= NULL
)
1356 const char *ext
= riscv_supported_std_ext
[i
].name
;
1357 riscv_ext_order
[(*ext
- 'a')] = order
++;
1359 while (riscv_supported_std_ext
[i
].name
1360 && strcmp (ext
, riscv_supported_std_ext
[i
].name
) == 0)
1364 /* Some of the prefixed keyword are not single letter, so we set
1365 their prefixed orders in the riscv_compare_subsets directly,
1366 not through the riscv_ext_order. */
1371 /* Similar to the strcmp. It returns an integer less than, equal to,
1372 or greater than zero if `subset2` is found, respectively, to be less
1373 than, to match, or be greater than `subset1`.
1376 Zero: Preserved keywords.
1377 Positive number: Standard extensions.
1378 Negative number: Prefixed keywords. */
1381 riscv_compare_subsets (const char *subset1
, const char *subset2
)
1383 int order1
= riscv_ext_order
[(*subset1
- 'a')];
1384 int order2
= riscv_ext_order
[(*subset2
- 'a')];
1386 /* Compare the standard extension first. */
1387 if (order1
> 0 && order2
> 0)
1388 return order1
- order2
;
1390 /* Set the prefixed orders to negative numbers. */
1391 enum riscv_prefix_ext_class class1
= riscv_get_prefix_class (subset1
);
1392 enum riscv_prefix_ext_class class2
= riscv_get_prefix_class (subset2
);
1394 if (class1
!= RV_ISA_CLASS_UNKNOWN
)
1395 order1
= - (int) class1
;
1396 if (class2
!= RV_ISA_CLASS_UNKNOWN
)
1397 order2
= - (int) class2
;
1399 if (order1
== order2
)
1401 /* Compare the standard addition z extensions. */
1402 if (class1
== RV_ISA_CLASS_Z
)
1404 order1
= riscv_ext_order
[(*++subset1
- 'a')];
1405 order2
= riscv_ext_order
[(*++subset2
- 'a')];
1406 if (order1
!= order2
)
1407 return order1
- order2
;
1409 return strcasecmp (++subset1
, ++subset2
);
1412 return order2
- order1
;
1415 /* Find subset in the list. Return TRUE and set `current` to the subset
1416 if it is found. Otherwise, return FALSE and set `current` to the place
1417 where we should insert the subset. However, return FALSE with the NULL
1418 `current` means we should insert the subset at the head of subset list,
1422 riscv_lookup_subset (const riscv_subset_list_t
*subset_list
,
1424 riscv_subset_t
**current
)
1426 riscv_subset_t
*s
, *pre_s
= NULL
;
1428 /* If the subset is added in order, then just add it at the tail. */
1429 if (subset_list
->tail
!= NULL
1430 && riscv_compare_subsets (subset_list
->tail
->name
, subset
) < 0)
1432 *current
= subset_list
->tail
;
1436 for (s
= subset_list
->head
;
1438 pre_s
= s
, s
= s
->next
)
1440 int cmp
= riscv_compare_subsets (s
->name
, subset
);
1454 /* Add the extension to the subset list. Search the
1455 list first, and then find the right place to add. */
1458 riscv_add_subset (riscv_subset_list_t
*subset_list
,
1463 riscv_subset_t
*current
, *new;
1465 if (riscv_lookup_subset (subset_list
, subset
, ¤t
))
1468 new = xmalloc (sizeof *new);
1469 new->name
= xstrdup (subset
);
1470 new->major_version
= major
;
1471 new->minor_version
= minor
;
1474 if (current
!= NULL
)
1476 new->next
= current
->next
;
1477 current
->next
= new;
1481 new->next
= subset_list
->head
;
1482 subset_list
->head
= new;
1485 if (new->next
== NULL
)
1486 subset_list
->tail
= new;
1489 /* Get the default versions from the riscv_supported_*ext tables. */
1492 riscv_get_default_ext_version (enum riscv_spec_class
*default_isa_spec
,
1498 || default_isa_spec
== NULL
1499 || *default_isa_spec
== ISA_SPEC_CLASS_NONE
)
1502 struct riscv_supported_ext
*table
= NULL
;
1503 enum riscv_prefix_ext_class
class = riscv_get_prefix_class (name
);
1506 case RV_ISA_CLASS_ZXM
: table
= riscv_supported_std_zxm_ext
; break;
1507 case RV_ISA_CLASS_Z
: table
= riscv_supported_std_z_ext
; break;
1508 case RV_ISA_CLASS_S
: table
= riscv_supported_std_s_ext
; break;
1509 case RV_ISA_CLASS_H
: table
= riscv_supported_std_h_ext
; break;
1510 case RV_ISA_CLASS_X
:
1513 table
= riscv_supported_std_ext
;
1517 while (table
!= NULL
&& table
[i
].name
!= NULL
)
1519 if (strcmp (table
[i
].name
, name
) == 0
1520 && (table
[i
].isa_spec_class
== ISA_SPEC_CLASS_DRAFT
1521 || table
[i
].isa_spec_class
== *default_isa_spec
))
1523 *major_version
= table
[i
].major_version
;
1524 *minor_version
= table
[i
].minor_version
;
1531 /* Find the default versions for the extension before adding them to
1532 the subset list, if their versions are RISCV_UNKNOWN_VERSION.
1533 Afterwards, report errors if we can not find their default versions. */
1536 riscv_parse_add_subset (riscv_parse_subset_t
*rps
,
1542 int major_version
= major
;
1543 int minor_version
= minor
;
1545 if (major_version
== RISCV_UNKNOWN_VERSION
1546 || minor_version
== RISCV_UNKNOWN_VERSION
)
1547 riscv_get_default_ext_version (rps
->isa_spec
, subset
,
1548 &major_version
, &minor_version
);
1550 /* We don't care the versions of the implicit extensions. */
1552 && (major_version
== RISCV_UNKNOWN_VERSION
1553 || minor_version
== RISCV_UNKNOWN_VERSION
))
1555 if (subset
[0] == 'x')
1557 (_("x ISA extension `%s' must be set with the versions"),
1561 (_("cannot find default versions of the ISA extension `%s'"),
1566 riscv_add_subset (rps
->subset_list
, subset
,
1567 major_version
, minor_version
);
1570 /* Release subset list. */
1573 riscv_release_subset_list (riscv_subset_list_t
*subset_list
)
1575 while (subset_list
->head
!= NULL
)
1577 riscv_subset_t
*next
= subset_list
->head
->next
;
1578 free ((void *)subset_list
->head
->name
);
1579 free (subset_list
->head
);
1580 subset_list
->head
= next
;
1583 subset_list
->tail
= NULL
;
1586 /* Parsing extension version.
1589 Points to the end of version
1592 `p`: Curent parsing position.
1593 `major_version`: Parsed major version.
1594 `minor_version`: Parsed minor version. */
1597 riscv_parsing_subset_version (const char *p
,
1601 bool major_p
= true;
1613 /* Might be beginning of `p` extension. */
1617 *major_version
= version
;
1621 else if (ISDIGIT (*p
))
1622 version
= (version
* 10) + (*p
- '0');
1628 *major_version
= version
;
1630 *minor_version
= version
;
1632 /* We can not find any version in string. */
1633 if (*major_version
== 0 && *minor_version
== 0)
1635 *major_version
= RISCV_UNKNOWN_VERSION
;
1636 *minor_version
= RISCV_UNKNOWN_VERSION
;
1642 /* Parsing function for standard extensions.
1645 Points to the end of extensions.
1648 `rps`: Hooks and status for parsing extensions.
1649 `arch`: Full ISA string.
1650 `p`: Curent parsing position. */
1653 riscv_parse_std_ext (riscv_parse_subset_t
*rps
,
1657 /* First letter must start with i, e or g. */
1658 if (*p
!= 'e' && *p
!= 'i' && *p
!= 'g')
1661 (_("%s: first ISA extension must be `e', `i' or `g'"),
1666 while (p
!= NULL
&& *p
!= '\0')
1668 /* Stop when we parsed the known prefix class. */
1669 enum riscv_prefix_ext_class
class = riscv_get_prefix_class (p
);
1670 if (class != RV_ISA_CLASS_UNKNOWN
)
1679 bool implicit
= false;
1680 int major
= RISCV_UNKNOWN_VERSION
;
1681 int minor
= RISCV_UNKNOWN_VERSION
;
1682 char subset
[2] = {0, 0};
1686 /* Check if the standard extension is supported. */
1687 if (riscv_ext_order
[(subset
[0] - 'a')] == 0)
1690 (_("%s: unknown standard ISA extension `%c'"),
1695 /* Checking canonical order. */
1696 if (rps
->subset_list
->tail
!= NULL
1697 && riscv_compare_subsets (rps
->subset_list
->tail
->name
, subset
) > 0)
1700 (_("%s: standard ISA extension `%c' is not "
1701 "in canonical order"), arch
, subset
[0]);
1705 p
= riscv_parsing_subset_version (++p
, &major
, &minor
);
1706 /* Added g as an implicit extension. */
1707 if (subset
[0] == 'g')
1710 major
= RISCV_UNKNOWN_VERSION
;
1711 minor
= RISCV_UNKNOWN_VERSION
;
1713 riscv_parse_add_subset (rps
, subset
, major
, minor
, implicit
);
1719 /* Parsing function for prefixed extensions.
1722 Points to the end of extension.
1725 `rps`: Hooks and status for parsing extensions.
1726 `arch`: Full ISA string.
1727 `p`: Curent parsing position. */
1730 riscv_parse_prefixed_ext (riscv_parse_subset_t
*rps
,
1736 const char *last_name
;
1737 enum riscv_prefix_ext_class
class;
1747 class = riscv_get_prefix_class (p
);
1748 if (class == RV_ISA_CLASS_UNKNOWN
)
1751 (_("%s: unknown prefix class for the ISA extension `%s'"),
1756 char *subset
= xstrdup (p
);
1758 const char *end_of_version
;
1760 /* Extract the whole prefixed extension by '_'. */
1761 while (*++q
!= '\0' && *q
!= '_')
1763 /* Look forward to the first letter which is not <major>p<minor>. */
1764 bool find_any_version
= false;
1765 bool find_minor_version
= false;
1770 find_any_version
= true;
1771 else if (find_any_version
1772 && !find_minor_version
1774 && ISDIGIT (*(q
- 1)))
1775 find_minor_version
= true;
1781 /* Check if the end of extension is 'p' or not. If yes, then
1782 the second letter from the end cannot be number. */
1783 if (*(q
- 1) == 'p' && ISDIGIT (*(q
- 2)))
1787 (_("%s: invalid prefixed ISA extension `%s' ends with <number>p"),
1794 riscv_parsing_subset_version (q
, &major_version
, &minor_version
);
1796 if (end_of_version
== NULL
)
1802 /* Check that the extension name is well-formed. */
1803 if (rps
->check_unknown_prefixed_ext
1804 && !riscv_recognized_prefixed_ext (subset
))
1807 (_("%s: unknown prefixed ISA extension `%s'"),
1813 /* Check that the extension isn't duplicate. */
1814 last_name
= rps
->subset_list
->tail
->name
;
1815 if (!strcasecmp (last_name
, subset
))
1818 (_("%s: duplicate prefixed ISA extension `%s'"),
1824 /* Check that the extension is in expected order. */
1825 if (riscv_compare_subsets (last_name
, subset
) > 0)
1828 (_("%s: prefixed ISA extension `%s' is not in expected "
1829 "order. It must come before `%s'"),
1830 arch
, subset
, last_name
);
1835 riscv_parse_add_subset (rps
, subset
,
1837 minor_version
, false);
1838 p
+= end_of_version
- subset
;
1841 if (*p
!= '\0' && *p
!= '_')
1844 (_("%s: prefixed ISA extension must separate with _"),
1853 /* Add the implicit extensions. */
1856 riscv_parse_add_implicit_subsets (riscv_parse_subset_t
*rps
)
1858 struct riscv_implicit_subset
*t
= riscv_implicit_subsets
;
1859 for (; t
->subset_name
; t
++)
1861 riscv_subset_t
*subset
= NULL
;
1862 if (riscv_lookup_subset (rps
->subset_list
, t
->subset_name
, &subset
)
1863 && t
->check_func (t
->implicit_name
, subset
))
1864 riscv_parse_add_subset (rps
, t
->implicit_name
,
1865 RISCV_UNKNOWN_VERSION
,
1866 RISCV_UNKNOWN_VERSION
, true);
1870 /* Check extensions conflicts. */
1873 riscv_parse_check_conflicts (riscv_parse_subset_t
*rps
)
1875 riscv_subset_t
*subset
= NULL
;
1876 int xlen
= *rps
->xlen
;
1877 bool no_conflict
= true;
1879 if (riscv_lookup_subset (rps
->subset_list
, "e", &subset
)
1883 (_("rv%d does not support the `e' extension"), xlen
);
1884 no_conflict
= false;
1886 if (riscv_lookup_subset (rps
->subset_list
, "q", &subset
)
1890 (_("rv%d does not support the `q' extension"), xlen
);
1891 no_conflict
= false;
1893 if (riscv_lookup_subset (rps
->subset_list
, "e", &subset
)
1894 && riscv_lookup_subset (rps
->subset_list
, "f", &subset
))
1897 (_("rv32e does not support the `f' extension"));
1898 no_conflict
= false;
1901 bool support_zve
= false;
1902 bool support_zvl
= false;
1903 riscv_subset_t
*s
= rps
->subset_list
->head
;
1904 for (; s
!= NULL
; s
= s
->next
)
1907 && strncmp (s
->name
, "zve", 3) == 0)
1910 && strncmp (s
->name
, "zvl", 3) == 0)
1912 if (support_zve
&& support_zvl
)
1915 if (support_zvl
&& !support_zve
)
1918 (_("zvl*b extensions need to enable either `v' or `zve' extension"));
1919 no_conflict
= false;
1925 /* Set the default subset list according to the default_enable field
1926 of riscv_supported_*ext tables. */
1929 riscv_set_default_arch (riscv_parse_subset_t
*rps
)
1931 unsigned long enable
= EXT_DEFAULT
;
1933 for (i
= 0; riscv_all_supported_ext
[i
] != NULL
; i
++)
1935 const struct riscv_supported_ext
*table
= riscv_all_supported_ext
[i
];
1936 for (j
= 0; table
[j
].name
!= NULL
; j
++)
1938 bool implicit
= false;
1939 if (strcmp (table
[j
].name
, "g") == 0)
1941 if (table
[j
].default_enable
& enable
)
1942 riscv_parse_add_subset (rps
, table
[j
].name
,
1943 RISCV_UNKNOWN_VERSION
,
1944 RISCV_UNKNOWN_VERSION
, implicit
);
1949 /* Function for parsing ISA string.
1952 Return TRUE on success.
1955 `rps`: Hooks and status for parsing extensions.
1956 `arch`: Full ISA string. */
1959 riscv_parse_subset (riscv_parse_subset_t
*rps
,
1964 /* Init the riscv_ext_order array to compare the order of extensions
1966 riscv_init_ext_order ();
1970 riscv_set_default_arch (rps
);
1971 riscv_parse_add_implicit_subsets (rps
);
1972 return riscv_parse_check_conflicts (rps
);
1975 for (p
= arch
; *p
!= '\0'; p
++)
1980 (_("%s: ISA string cannot contain uppercase letters"),
1987 if (startswith (p
, "rv32"))
1992 else if (startswith (p
, "rv64"))
1999 /* ISA string shouldn't be NULL or empty here. For linker,
2000 it might be empty when we failed to merge the ISA string
2001 in the riscv_merge_attributes. For assembler, we might
2002 give an empty string by .attribute arch, "" or -march=.
2003 However, We have already issued the correct error message
2004 in another side, so do not issue this error when the ISA
2007 rps
->error_handler (
2008 _("%s: ISA string must begin with rv32 or rv64"),
2013 /* Parsing standard extension. */
2014 p
= riscv_parse_std_ext (rps
, arch
, p
);
2019 /* Parse the different classes of extensions in the specified order. */
2022 p
= riscv_parse_prefixed_ext (rps
, arch
, p
);
2028 /* Finally add implicit extensions according to the current
2030 riscv_parse_add_implicit_subsets (rps
);
2032 /* Check the conflicts. */
2033 return riscv_parse_check_conflicts (rps
);
2036 /* Return the number of digits for the input. */
2039 riscv_estimate_digit (unsigned num
)
2045 for (digit
= 0; num
; num
/= 10)
2051 /* Auxiliary function to estimate string length of subset list. */
2054 riscv_estimate_arch_strlen1 (const riscv_subset_t
*subset
)
2057 return 6; /* For rv32/rv64/rv128 and string terminator. */
2059 return riscv_estimate_arch_strlen1 (subset
->next
)
2060 + strlen (subset
->name
)
2061 + riscv_estimate_digit (subset
->major_version
)
2062 + 1 /* For version seperator 'p'. */
2063 + riscv_estimate_digit (subset
->minor_version
)
2064 + 1 /* For underscore. */;
2067 /* Estimate the string length of this subset list. */
2070 riscv_estimate_arch_strlen (const riscv_subset_list_t
*subset_list
)
2072 return riscv_estimate_arch_strlen1 (subset_list
->head
);
2075 /* Auxiliary function to convert subset info to string. */
2078 riscv_arch_str1 (riscv_subset_t
*subset
,
2079 char *attr_str
, char *buf
, size_t bufsz
)
2081 const char *underline
= "_";
2082 riscv_subset_t
*subset_t
= subset
;
2084 if (subset_t
== NULL
)
2087 /* No underline between rvXX and i/e. */
2088 if ((strcasecmp (subset_t
->name
, "i") == 0)
2089 || (strcasecmp (subset_t
->name
, "e") == 0))
2092 snprintf (buf
, bufsz
, "%s%s%dp%d",
2095 subset_t
->major_version
,
2096 subset_t
->minor_version
);
2098 strncat (attr_str
, buf
, bufsz
);
2100 /* Skip 'i' extension after 'e', or skip extensions which
2101 versions are unknown. */
2102 while (subset_t
->next
2103 && ((strcmp (subset_t
->name
, "e") == 0
2104 && strcmp (subset_t
->next
->name
, "i") == 0)
2105 || subset_t
->next
->major_version
== RISCV_UNKNOWN_VERSION
2106 || subset_t
->next
->minor_version
== RISCV_UNKNOWN_VERSION
))
2107 subset_t
= subset_t
->next
;
2109 riscv_arch_str1 (subset_t
->next
, attr_str
, buf
, bufsz
);
2112 /* Convert subset information into string with explicit versions. */
2115 riscv_arch_str (unsigned xlen
, const riscv_subset_list_t
*subset
)
2117 size_t arch_str_len
= riscv_estimate_arch_strlen (subset
);
2118 char *attr_str
= xmalloc (arch_str_len
);
2119 char *buf
= xmalloc (arch_str_len
);
2121 snprintf (attr_str
, arch_str_len
, "rv%u", xlen
);
2123 riscv_arch_str1 (subset
->head
, attr_str
, buf
, arch_str_len
);
2129 /* Remove the SUBSET from the subset list. */
2132 riscv_remove_subset (riscv_subset_list_t
*subset_list
,
2135 riscv_subset_t
*current
= subset_list
->head
;
2136 riscv_subset_t
*pre
= NULL
;
2137 for (; current
!= NULL
; pre
= current
, current
= current
->next
)
2139 if (strcmp (current
->name
, subset
) == 0)
2142 subset_list
->head
= current
->next
;
2144 pre
->next
= current
->next
;
2145 if (current
->next
== NULL
)
2146 subset_list
->tail
= pre
;
2147 free ((void *) current
->name
);
2154 /* Add/Remove an extension to/from the subset list. This is used for
2155 the .option rvc or norvc. */
2158 riscv_update_subset (riscv_parse_subset_t
*rps
,
2162 if (strlen (subset
) == 0
2163 || (strlen (subset
) == 1
2164 && riscv_ext_order
[(*subset
- 'a')] == 0)
2165 || (strlen (subset
) > 1
2166 && rps
->check_unknown_prefixed_ext
2167 && !riscv_recognized_prefixed_ext (subset
)))
2170 (_("riscv_update_subset: unknown ISA extension `%s'"), subset
);
2176 if (strcmp (subset
, "i") == 0)
2179 (_("riscv_update_subset: cannot remove extension i from "
2180 "the subset list"));
2183 riscv_remove_subset (rps
->subset_list
, subset
);
2186 riscv_parse_add_subset (rps
, subset
,
2187 RISCV_UNKNOWN_VERSION
,
2188 RISCV_UNKNOWN_VERSION
, true);
2190 riscv_parse_add_implicit_subsets (rps
);
2191 return riscv_parse_check_conflicts (rps
);
2194 /* Check if the FEATURE subset is supported or not in the subset list.
2195 Return true if it is supported; Otherwise, return false. */
2198 riscv_subset_supports (riscv_parse_subset_t
*rps
,
2199 const char *feature
)
2201 struct riscv_subset_t
*subset
;
2202 return riscv_lookup_subset (rps
->subset_list
, feature
, &subset
);
2205 /* Each instuction is belonged to an instruction class INSN_CLASS_*.
2206 Call riscv_subset_supports to make sure if the instuction is valid. */
2209 riscv_multi_subset_supports (riscv_parse_subset_t
*rps
,
2210 enum riscv_insn_class insn_class
)
2215 return riscv_subset_supports (rps
, "i");
2216 case INSN_CLASS_ZICSR
:
2217 return riscv_subset_supports (rps
, "zicsr");
2218 case INSN_CLASS_ZIFENCEI
:
2219 return riscv_subset_supports (rps
, "zifencei");
2220 case INSN_CLASS_ZIHINTPAUSE
:
2221 return riscv_subset_supports (rps
, "zihintpause");
2223 return riscv_subset_supports (rps
, "m");
2225 return riscv_subset_supports (rps
, "a");
2227 return riscv_subset_supports (rps
, "f");
2229 return riscv_subset_supports (rps
, "d");
2231 return riscv_subset_supports (rps
, "q");
2233 return riscv_subset_supports (rps
, "c");
2234 case INSN_CLASS_F_AND_C
:
2235 return (riscv_subset_supports (rps
, "f")
2236 && riscv_subset_supports (rps
, "c"));
2237 case INSN_CLASS_D_AND_C
:
2238 return (riscv_subset_supports (rps
, "d")
2239 && riscv_subset_supports (rps
, "c"));
2240 case INSN_CLASS_ZBA
:
2241 return riscv_subset_supports (rps
, "zba");
2242 case INSN_CLASS_ZBB
:
2243 return riscv_subset_supports (rps
, "zbb");
2244 case INSN_CLASS_ZBC
:
2245 return riscv_subset_supports (rps
, "zbc");
2246 case INSN_CLASS_ZBS
:
2247 return riscv_subset_supports (rps
, "zbs");
2248 case INSN_CLASS_ZBKB
:
2249 return riscv_subset_supports (rps
, "zbkb");
2250 case INSN_CLASS_ZBKC
:
2251 return riscv_subset_supports (rps
, "zbkc");
2252 case INSN_CLASS_ZBKX
:
2253 return riscv_subset_supports (rps
, "zbkx");
2254 case INSN_CLASS_ZBB_OR_ZBKB
:
2255 return (riscv_subset_supports (rps
, "zbb")
2256 || riscv_subset_supports (rps
, "zbkb"));
2257 case INSN_CLASS_ZBC_OR_ZBKC
:
2258 return (riscv_subset_supports (rps
, "zbc")
2259 || riscv_subset_supports (rps
, "zbkc"));
2260 case INSN_CLASS_ZKND
:
2261 return riscv_subset_supports (rps
, "zknd");
2262 case INSN_CLASS_ZKNE
:
2263 return riscv_subset_supports (rps
, "zkne");
2264 case INSN_CLASS_ZKNH
:
2265 return riscv_subset_supports (rps
, "zknh");
2266 case INSN_CLASS_ZKND_OR_ZKNE
:
2267 return (riscv_subset_supports (rps
, "zknd")
2268 || riscv_subset_supports (rps
, "zkne"));
2269 case INSN_CLASS_ZKSED
:
2270 return riscv_subset_supports (rps
, "zksed");
2271 case INSN_CLASS_ZKSH
:
2272 return riscv_subset_supports (rps
, "zksh");
2274 return (riscv_subset_supports (rps
, "v")
2275 || riscv_subset_supports (rps
, "zve64x")
2276 || riscv_subset_supports (rps
, "zve32x"));
2277 case INSN_CLASS_ZVEF
:
2278 return (riscv_subset_supports (rps
, "v")
2279 || riscv_subset_supports (rps
, "zve64d")
2280 || riscv_subset_supports (rps
, "zve64f")
2281 || riscv_subset_supports (rps
, "zve32f"));
2284 (_("internal: unreachable INSN_CLASS_*"));