Add translations for various sub-directories
[binutils-gdb.git] / bfd / elfxx-riscv.c
blobc9e4b03b17daa96bf06d36096abe22fd757106a3
1 /* RISC-V-specific support for ELF.
2 Copyright (C) 2011-2025 Free Software Foundation, Inc.
4 Contributed by Andrew Waterman (andrew@sifive.com).
5 Based on TILE-Gx and MIPS targets.
7 This file is part of BFD, the Binary File Descriptor library.
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 3 of the License, or
12 (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with this program; see the file COPYING3. If not,
21 see <http://www.gnu.org/licenses/>. */
23 #include "sysdep.h"
24 #include "bfd.h"
25 #include "libbfd.h"
26 #include "elf-bfd.h"
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[] =
48 /* No relocation. */
49 HOWTO (R_RISCV_NONE, /* type */
50 0, /* rightshift */
51 0, /* size */
52 0, /* bitsize */
53 false, /* pc_relative */
54 0, /* bitpos */
55 complain_overflow_dont, /* complain_on_overflow */
56 bfd_elf_generic_reloc, /* special_function */
57 "R_RISCV_NONE", /* name */
58 false, /* partial_inplace */
59 0, /* src_mask */
60 0, /* dst_mask */
61 false), /* pcrel_offset */
63 /* 32 bit relocation. */
64 HOWTO (R_RISCV_32, /* type */
65 0, /* rightshift */
66 4, /* size */
67 32, /* bitsize */
68 false, /* pc_relative */
69 0, /* bitpos */
70 complain_overflow_dont, /* complain_on_overflow */
71 bfd_elf_generic_reloc, /* special_function */
72 "R_RISCV_32", /* name */
73 false, /* partial_inplace */
74 0, /* src_mask */
75 0xffffffff, /* dst_mask */
76 false), /* pcrel_offset */
78 /* 64 bit relocation. */
79 HOWTO (R_RISCV_64, /* type */
80 0, /* rightshift */
81 8, /* size */
82 64, /* bitsize */
83 false, /* pc_relative */
84 0, /* bitpos */
85 complain_overflow_dont, /* complain_on_overflow */
86 bfd_elf_generic_reloc, /* special_function */
87 "R_RISCV_64", /* name */
88 false, /* partial_inplace */
89 0, /* src_mask */
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 */
95 0, /* rightshift */
96 4, /* size */
97 32, /* bitsize */
98 false, /* pc_relative */
99 0, /* bitpos */
100 complain_overflow_dont, /* complain_on_overflow */
101 bfd_elf_generic_reloc, /* special_function */
102 "R_RISCV_RELATIVE", /* name */
103 false, /* partial_inplace */
104 0, /* src_mask */
105 0xffffffff, /* dst_mask */
106 false), /* pcrel_offset */
108 HOWTO (R_RISCV_COPY, /* type */
109 0, /* rightshift */
110 0, /* this one is variable size */
111 0, /* bitsize */
112 false, /* pc_relative */
113 0, /* bitpos */
114 complain_overflow_bitfield, /* complain_on_overflow */
115 bfd_elf_generic_reloc, /* special_function */
116 "R_RISCV_COPY", /* name */
117 false, /* partial_inplace */
118 0, /* src_mask */
119 0, /* dst_mask */
120 false), /* pcrel_offset */
122 HOWTO (R_RISCV_JUMP_SLOT, /* type */
123 0, /* rightshift */
124 8, /* size */
125 64, /* bitsize */
126 false, /* pc_relative */
127 0, /* bitpos */
128 complain_overflow_bitfield, /* complain_on_overflow */
129 bfd_elf_generic_reloc, /* special_function */
130 "R_RISCV_JUMP_SLOT", /* name */
131 false, /* partial_inplace */
132 0, /* src_mask */
133 0, /* dst_mask */
134 false), /* pcrel_offset */
136 /* Dynamic TLS relocations. */
137 HOWTO (R_RISCV_TLS_DTPMOD32, /* type */
138 0, /* rightshift */
139 4, /* size */
140 32, /* bitsize */
141 false, /* pc_relative */
142 0, /* bitpos */
143 complain_overflow_dont, /* complain_on_overflow */
144 bfd_elf_generic_reloc, /* special_function */
145 "R_RISCV_TLS_DTPMOD32", /* name */
146 false, /* partial_inplace */
147 0, /* src_mask */
148 0xffffffff, /* dst_mask */
149 false), /* pcrel_offset */
151 HOWTO (R_RISCV_TLS_DTPMOD64, /* type */
152 0, /* rightshift */
153 8, /* size */
154 64, /* bitsize */
155 false, /* pc_relative */
156 0, /* bitpos */
157 complain_overflow_dont, /* complain_on_overflow */
158 bfd_elf_generic_reloc, /* special_function */
159 "R_RISCV_TLS_DTPMOD64", /* name */
160 false, /* partial_inplace */
161 0, /* src_mask */
162 MINUS_ONE, /* dst_mask */
163 false), /* pcrel_offset */
165 HOWTO (R_RISCV_TLS_DTPREL32, /* type */
166 0, /* rightshift */
167 4, /* size */
168 32, /* bitsize */
169 false, /* pc_relative */
170 0, /* bitpos */
171 complain_overflow_dont, /* complain_on_overflow */
172 bfd_elf_generic_reloc, /* special_function */
173 "R_RISCV_TLS_DTPREL32", /* name */
174 true, /* partial_inplace */
175 0, /* src_mask */
176 0xffffffff, /* dst_mask */
177 false), /* pcrel_offset */
179 HOWTO (R_RISCV_TLS_DTPREL64, /* type */
180 0, /* rightshift */
181 8, /* size */
182 64, /* bitsize */
183 false, /* pc_relative */
184 0, /* bitpos */
185 complain_overflow_dont, /* complain_on_overflow */
186 bfd_elf_generic_reloc, /* special_function */
187 "R_RISCV_TLS_DTPREL64", /* name */
188 true, /* partial_inplace */
189 0, /* src_mask */
190 MINUS_ONE, /* dst_mask */
191 false), /* pcrel_offset */
193 HOWTO (R_RISCV_TLS_TPREL32, /* type */
194 0, /* rightshift */
195 4, /* size */
196 32, /* bitsize */
197 false, /* pc_relative */
198 0, /* bitpos */
199 complain_overflow_dont, /* complain_on_overflow */
200 bfd_elf_generic_reloc, /* special_function */
201 "R_RISCV_TLS_TPREL32", /* name */
202 false, /* partial_inplace */
203 0, /* src_mask */
204 0xffffffff, /* dst_mask */
205 false), /* pcrel_offset */
207 HOWTO (R_RISCV_TLS_TPREL64, /* type */
208 0, /* rightshift */
209 8, /* size */
210 64, /* bitsize */
211 false, /* pc_relative */
212 0, /* bitpos */
213 complain_overflow_dont, /* complain_on_overflow */
214 bfd_elf_generic_reloc, /* special_function */
215 "R_RISCV_TLS_TPREL64", /* name */
216 false, /* partial_inplace */
217 0, /* src_mask */
218 MINUS_ONE, /* dst_mask */
219 false), /* pcrel_offset */
221 HOWTO (R_RISCV_TLSDESC, /* type */
222 0, /* rightshift */
223 0, /* size is handled by dynamic linker */
224 0, /* bitsize */
225 false, /* pc_relative */
226 0, /* bitpos */
227 complain_overflow_dont, /* complain_on_overflow */
228 bfd_elf_generic_reloc, /* special_function */
229 "R_RISCV_TLSDESC", /* name */
230 false, /* partial_inplace */
231 0, /* src_mask */
232 MINUS_ONE, /* dst_mask */
233 false), /* pcrel_offset */
235 EMPTY_HOWTO (13),
236 EMPTY_HOWTO (14),
237 EMPTY_HOWTO (15),
239 /* 12-bit PC-relative branch offset. */
240 HOWTO (R_RISCV_BRANCH, /* type */
241 0, /* rightshift */
242 4, /* size */
243 32, /* bitsize */
244 true, /* pc_relative */
245 0, /* bitpos */
246 complain_overflow_signed, /* complain_on_overflow */
247 bfd_elf_generic_reloc, /* special_function */
248 "R_RISCV_BRANCH", /* name */
249 false, /* partial_inplace */
250 0, /* src_mask */
251 ENCODE_BTYPE_IMM (-1U), /* dst_mask */
252 true), /* pcrel_offset */
254 /* 20-bit PC-relative jump offset. */
255 HOWTO (R_RISCV_JAL, /* type */
256 0, /* rightshift */
257 4, /* size */
258 32, /* bitsize */
259 true, /* pc_relative */
260 0, /* bitpos */
261 complain_overflow_dont, /* complain_on_overflow */
262 bfd_elf_generic_reloc, /* special_function */
263 "R_RISCV_JAL", /* name */
264 false, /* partial_inplace */
265 0, /* src_mask */
266 ENCODE_JTYPE_IMM (-1U), /* dst_mask */
267 true), /* pcrel_offset */
269 /* 32-bit PC-relative function call (AUIPC/JALR). */
270 HOWTO (R_RISCV_CALL, /* type */
271 0, /* rightshift */
272 8, /* size */
273 64, /* bitsize */
274 true, /* pc_relative */
275 0, /* bitpos */
276 complain_overflow_dont, /* complain_on_overflow */
277 bfd_elf_generic_reloc, /* special_function */
278 "R_RISCV_CALL", /* name */
279 false, /* partial_inplace */
280 0, /* src_mask */
281 ENCODE_UTYPE_IMM (-1U) | ((bfd_vma) ENCODE_ITYPE_IMM (-1U) << 32),
282 /* dst_mask */
283 true), /* pcrel_offset */
285 /* Like R_RISCV_CALL, but not locally binding. */
286 HOWTO (R_RISCV_CALL_PLT, /* type */
287 0, /* rightshift */
288 8, /* size */
289 64, /* bitsize */
290 true, /* pc_relative */
291 0, /* bitpos */
292 complain_overflow_dont, /* complain_on_overflow */
293 bfd_elf_generic_reloc, /* special_function */
294 "R_RISCV_CALL_PLT", /* name */
295 false, /* partial_inplace */
296 0, /* src_mask */
297 ENCODE_UTYPE_IMM (-1U) | ((bfd_vma) ENCODE_ITYPE_IMM (-1U) << 32),
298 /* dst_mask */
299 true), /* pcrel_offset */
301 /* High 20 bits of 32-bit PC-relative GOT access. */
302 HOWTO (R_RISCV_GOT_HI20, /* type */
303 0, /* rightshift */
304 4, /* size */
305 32, /* bitsize */
306 true, /* pc_relative */
307 0, /* bitpos */
308 complain_overflow_dont, /* complain_on_overflow */
309 bfd_elf_generic_reloc, /* special_function */
310 "R_RISCV_GOT_HI20", /* name */
311 false, /* partial_inplace */
312 0, /* src_mask */
313 ENCODE_UTYPE_IMM (-1U), /* dst_mask */
314 false), /* pcrel_offset */
316 /* High 20 bits of 32-bit PC-relative TLS IE GOT access. */
317 HOWTO (R_RISCV_TLS_GOT_HI20, /* type */
318 0, /* rightshift */
319 4, /* size */
320 32, /* bitsize */
321 true, /* pc_relative */
322 0, /* bitpos */
323 complain_overflow_dont, /* complain_on_overflow */
324 bfd_elf_generic_reloc, /* special_function */
325 "R_RISCV_TLS_GOT_HI20", /* name */
326 false, /* partial_inplace */
327 0, /* src_mask */
328 ENCODE_UTYPE_IMM (-1U), /* dst_mask */
329 false), /* pcrel_offset */
331 /* High 20 bits of 32-bit PC-relative TLS GD GOT reference. */
332 HOWTO (R_RISCV_TLS_GD_HI20, /* type */
333 0, /* rightshift */
334 4, /* size */
335 32, /* bitsize */
336 true, /* pc_relative */
337 0, /* bitpos */
338 complain_overflow_dont, /* complain_on_overflow */
339 bfd_elf_generic_reloc, /* special_function */
340 "R_RISCV_TLS_GD_HI20", /* name */
341 false, /* partial_inplace */
342 0, /* src_mask */
343 ENCODE_UTYPE_IMM (-1U), /* dst_mask */
344 false), /* pcrel_offset */
346 /* High 20 bits of 32-bit PC-relative reference. */
347 HOWTO (R_RISCV_PCREL_HI20, /* type */
348 0, /* rightshift */
349 4, /* size */
350 32, /* bitsize */
351 true, /* pc_relative */
352 0, /* bitpos */
353 complain_overflow_dont, /* complain_on_overflow */
354 bfd_elf_generic_reloc, /* special_function */
355 "R_RISCV_PCREL_HI20", /* name */
356 false, /* partial_inplace */
357 0, /* src_mask */
358 ENCODE_UTYPE_IMM (-1U), /* dst_mask */
359 true), /* pcrel_offset */
361 /* Low 12 bits of a 32-bit PC-relative load or add. */
362 HOWTO (R_RISCV_PCREL_LO12_I, /* type */
363 0, /* rightshift */
364 4, /* size */
365 32, /* bitsize */
366 false, /* pc_relative */
367 0, /* bitpos */
368 complain_overflow_dont, /* complain_on_overflow */
369 bfd_elf_generic_reloc, /* special_function */
370 "R_RISCV_PCREL_LO12_I", /* name */
371 false, /* partial_inplace */
372 0, /* src_mask */
373 ENCODE_ITYPE_IMM (-1U), /* dst_mask */
374 false), /* pcrel_offset */
376 /* Low 12 bits of a 32-bit PC-relative store. */
377 HOWTO (R_RISCV_PCREL_LO12_S, /* type */
378 0, /* rightshift */
379 4, /* size */
380 32, /* bitsize */
381 false, /* pc_relative */
382 0, /* bitpos */
383 complain_overflow_dont, /* complain_on_overflow */
384 bfd_elf_generic_reloc, /* special_function */
385 "R_RISCV_PCREL_LO12_S", /* name */
386 false, /* partial_inplace */
387 0, /* src_mask */
388 ENCODE_STYPE_IMM (-1U), /* dst_mask */
389 false), /* pcrel_offset */
391 /* High 20 bits of 32-bit absolute address. */
392 HOWTO (R_RISCV_HI20, /* type */
393 0, /* rightshift */
394 4, /* size */
395 32, /* bitsize */
396 false, /* pc_relative */
397 0, /* bitpos */
398 complain_overflow_dont, /* complain_on_overflow */
399 bfd_elf_generic_reloc, /* special_function */
400 "R_RISCV_HI20", /* name */
401 false, /* partial_inplace */
402 0, /* src_mask */
403 ENCODE_UTYPE_IMM (-1U), /* dst_mask */
404 false), /* pcrel_offset */
406 /* High 12 bits of 32-bit load or add. */
407 HOWTO (R_RISCV_LO12_I, /* type */
408 0, /* rightshift */
409 4, /* size */
410 32, /* bitsize */
411 false, /* pc_relative */
412 0, /* bitpos */
413 complain_overflow_dont, /* complain_on_overflow */
414 bfd_elf_generic_reloc, /* special_function */
415 "R_RISCV_LO12_I", /* name */
416 false, /* partial_inplace */
417 0, /* src_mask */
418 ENCODE_ITYPE_IMM (-1U), /* dst_mask */
419 false), /* pcrel_offset */
421 /* High 12 bits of 32-bit store. */
422 HOWTO (R_RISCV_LO12_S, /* type */
423 0, /* rightshift */
424 4, /* size */
425 32, /* bitsize */
426 false, /* pc_relative */
427 0, /* bitpos */
428 complain_overflow_dont, /* complain_on_overflow */
429 bfd_elf_generic_reloc, /* special_function */
430 "R_RISCV_LO12_S", /* name */
431 false, /* partial_inplace */
432 0, /* src_mask */
433 ENCODE_STYPE_IMM (-1U), /* dst_mask */
434 false), /* pcrel_offset */
436 /* High 20 bits of TLS LE thread pointer offset. */
437 HOWTO (R_RISCV_TPREL_HI20, /* type */
438 0, /* rightshift */
439 4, /* size */
440 32, /* bitsize */
441 false, /* pc_relative */
442 0, /* bitpos */
443 complain_overflow_signed, /* complain_on_overflow */
444 bfd_elf_generic_reloc, /* special_function */
445 "R_RISCV_TPREL_HI20", /* name */
446 true, /* partial_inplace */
447 0, /* src_mask */
448 ENCODE_UTYPE_IMM (-1U), /* dst_mask */
449 false), /* pcrel_offset */
451 /* Low 12 bits of TLS LE thread pointer offset for loads and adds. */
452 HOWTO (R_RISCV_TPREL_LO12_I, /* type */
453 0, /* rightshift */
454 4, /* size */
455 32, /* bitsize */
456 false, /* pc_relative */
457 0, /* bitpos */
458 complain_overflow_signed, /* complain_on_overflow */
459 bfd_elf_generic_reloc, /* special_function */
460 "R_RISCV_TPREL_LO12_I", /* name */
461 false, /* partial_inplace */
462 0, /* src_mask */
463 ENCODE_ITYPE_IMM (-1U), /* dst_mask */
464 false), /* pcrel_offset */
466 /* Low 12 bits of TLS LE thread pointer offset for stores. */
467 HOWTO (R_RISCV_TPREL_LO12_S, /* type */
468 0, /* rightshift */
469 4, /* size */
470 32, /* bitsize */
471 false, /* pc_relative */
472 0, /* bitpos */
473 complain_overflow_signed, /* complain_on_overflow */
474 bfd_elf_generic_reloc, /* special_function */
475 "R_RISCV_TPREL_LO12_S", /* name */
476 false, /* partial_inplace */
477 0, /* src_mask */
478 ENCODE_STYPE_IMM (-1U), /* dst_mask */
479 false), /* pcrel_offset */
481 /* TLS LE thread pointer usage. May be relaxed. */
482 HOWTO (R_RISCV_TPREL_ADD, /* type */
483 0, /* rightshift */
484 0, /* size */
485 0, /* bitsize */
486 false, /* pc_relative */
487 0, /* bitpos */
488 complain_overflow_dont, /* complain_on_overflow */
489 bfd_elf_generic_reloc, /* special_function */
490 "R_RISCV_TPREL_ADD", /* name */
491 false, /* partial_inplace */
492 0, /* src_mask */
493 0, /* dst_mask */
494 false), /* pcrel_offset */
496 /* 8-bit in-place addition, for local label subtraction. */
497 HOWTO (R_RISCV_ADD8, /* type */
498 0, /* rightshift */
499 1, /* size */
500 8, /* bitsize */
501 false, /* pc_relative */
502 0, /* bitpos */
503 complain_overflow_dont, /* complain_on_overflow */
504 riscv_elf_add_sub_reloc, /* special_function */
505 "R_RISCV_ADD8", /* name */
506 false, /* partial_inplace */
507 0, /* src_mask */
508 0xff, /* dst_mask */
509 false), /* pcrel_offset */
511 /* 16-bit in-place addition, for local label subtraction. */
512 HOWTO (R_RISCV_ADD16, /* type */
513 0, /* rightshift */
514 2, /* size */
515 16, /* bitsize */
516 false, /* pc_relative */
517 0, /* bitpos */
518 complain_overflow_dont, /* complain_on_overflow */
519 riscv_elf_add_sub_reloc, /* special_function */
520 "R_RISCV_ADD16", /* name */
521 false, /* partial_inplace */
522 0, /* src_mask */
523 0xffff, /* dst_mask */
524 false), /* pcrel_offset */
526 /* 32-bit in-place addition, for local label subtraction. */
527 HOWTO (R_RISCV_ADD32, /* type */
528 0, /* rightshift */
529 4, /* size */
530 32, /* bitsize */
531 false, /* pc_relative */
532 0, /* bitpos */
533 complain_overflow_dont, /* complain_on_overflow */
534 riscv_elf_add_sub_reloc, /* special_function */
535 "R_RISCV_ADD32", /* name */
536 false, /* partial_inplace */
537 0, /* src_mask */
538 0xffffffff, /* dst_mask */
539 false), /* pcrel_offset */
541 /* 64-bit in-place addition, for local label subtraction. */
542 HOWTO (R_RISCV_ADD64, /* type */
543 0, /* rightshift */
544 8, /* size */
545 64, /* bitsize */
546 false, /* pc_relative */
547 0, /* bitpos */
548 complain_overflow_dont, /* complain_on_overflow */
549 riscv_elf_add_sub_reloc, /* special_function */
550 "R_RISCV_ADD64", /* name */
551 false, /* partial_inplace */
552 0, /* src_mask */
553 MINUS_ONE, /* dst_mask */
554 false), /* pcrel_offset */
556 /* 8-bit in-place addition, for local label subtraction. */
557 HOWTO (R_RISCV_SUB8, /* type */
558 0, /* rightshift */
559 1, /* size */
560 8, /* bitsize */
561 false, /* pc_relative */
562 0, /* bitpos */
563 complain_overflow_dont, /* complain_on_overflow */
564 riscv_elf_add_sub_reloc, /* special_function */
565 "R_RISCV_SUB8", /* name */
566 false, /* partial_inplace */
567 0, /* src_mask */
568 0xff, /* dst_mask */
569 false), /* pcrel_offset */
571 /* 16-bit in-place addition, for local label subtraction. */
572 HOWTO (R_RISCV_SUB16, /* type */
573 0, /* rightshift */
574 2, /* size */
575 16, /* bitsize */
576 false, /* pc_relative */
577 0, /* bitpos */
578 complain_overflow_dont, /* complain_on_overflow */
579 riscv_elf_add_sub_reloc, /* special_function */
580 "R_RISCV_SUB16", /* name */
581 false, /* partial_inplace */
582 0, /* src_mask */
583 0xffff, /* dst_mask */
584 false), /* pcrel_offset */
586 /* 32-bit in-place addition, for local label subtraction. */
587 HOWTO (R_RISCV_SUB32, /* type */
588 0, /* rightshift */
589 4, /* size */
590 32, /* bitsize */
591 false, /* pc_relative */
592 0, /* bitpos */
593 complain_overflow_dont, /* complain_on_overflow */
594 riscv_elf_add_sub_reloc, /* special_function */
595 "R_RISCV_SUB32", /* name */
596 false, /* partial_inplace */
597 0, /* src_mask */
598 0xffffffff, /* dst_mask */
599 false), /* pcrel_offset */
601 /* 64-bit in-place addition, for local label subtraction. */
602 HOWTO (R_RISCV_SUB64, /* type */
603 0, /* rightshift */
604 8, /* size */
605 64, /* bitsize */
606 false, /* pc_relative */
607 0, /* bitpos */
608 complain_overflow_dont, /* complain_on_overflow */
609 riscv_elf_add_sub_reloc, /* special_function */
610 "R_RISCV_SUB64", /* name */
611 false, /* partial_inplace */
612 0, /* src_mask */
613 MINUS_ONE, /* dst_mask */
614 false), /* pcrel_offset */
616 EMPTY_HOWTO (41),
617 EMPTY_HOWTO (42),
619 /* Indicates an alignment statement. The addend field encodes how many
620 bytes of NOPs follow the statement. The desired alignment is the
621 addend rounded up to the next power of two. */
622 HOWTO (R_RISCV_ALIGN, /* type */
623 0, /* rightshift */
624 0, /* size */
625 0, /* bitsize */
626 false, /* pc_relative */
627 0, /* bitpos */
628 complain_overflow_dont, /* complain_on_overflow */
629 bfd_elf_generic_reloc, /* special_function */
630 "R_RISCV_ALIGN", /* name */
631 false, /* partial_inplace */
632 0, /* src_mask */
633 0, /* dst_mask */
634 false), /* pcrel_offset */
636 /* 8-bit PC-relative branch offset. */
637 HOWTO (R_RISCV_RVC_BRANCH, /* type */
638 0, /* rightshift */
639 2, /* size */
640 16, /* bitsize */
641 true, /* pc_relative */
642 0, /* bitpos */
643 complain_overflow_signed, /* complain_on_overflow */
644 bfd_elf_generic_reloc, /* special_function */
645 "R_RISCV_RVC_BRANCH", /* name */
646 false, /* partial_inplace */
647 0, /* src_mask */
648 ENCODE_CBTYPE_IMM (-1U), /* dst_mask */
649 true), /* pcrel_offset */
651 /* 11-bit PC-relative jump offset. */
652 HOWTO (R_RISCV_RVC_JUMP, /* type */
653 0, /* rightshift */
654 2, /* size */
655 16, /* bitsize */
656 true, /* pc_relative */
657 0, /* bitpos */
658 complain_overflow_dont, /* complain_on_overflow */
659 bfd_elf_generic_reloc, /* special_function */
660 "R_RISCV_RVC_JUMP", /* name */
661 false, /* partial_inplace */
662 0, /* src_mask */
663 ENCODE_CJTYPE_IMM (-1U), /* dst_mask */
664 true), /* pcrel_offset */
666 EMPTY_HOWTO (46),
667 EMPTY_HOWTO (47),
668 EMPTY_HOWTO (48),
669 EMPTY_HOWTO (49),
670 EMPTY_HOWTO (50),
672 /* The paired relocation may be relaxed. */
673 HOWTO (R_RISCV_RELAX, /* type */
674 0, /* rightshift */
675 0, /* size */
676 0, /* bitsize */
677 false, /* pc_relative */
678 0, /* bitpos */
679 complain_overflow_dont, /* complain_on_overflow */
680 bfd_elf_generic_reloc, /* special_function */
681 "R_RISCV_RELAX", /* name */
682 false, /* partial_inplace */
683 0, /* src_mask */
684 0, /* dst_mask */
685 false), /* pcrel_offset */
687 /* 6-bit in-place addition, for local label subtraction. */
688 HOWTO (R_RISCV_SUB6, /* type */
689 0, /* rightshift */
690 1, /* size */
691 8, /* bitsize */
692 false, /* pc_relative */
693 0, /* bitpos */
694 complain_overflow_dont, /* complain_on_overflow */
695 riscv_elf_add_sub_reloc, /* special_function */
696 "R_RISCV_SUB6", /* name */
697 false, /* partial_inplace */
698 0, /* src_mask */
699 0x3f, /* dst_mask */
700 false), /* pcrel_offset */
702 /* 6-bit in-place setting, for local label subtraction. */
703 HOWTO (R_RISCV_SET6, /* type */
704 0, /* rightshift */
705 1, /* size */
706 8, /* bitsize */
707 false, /* pc_relative */
708 0, /* bitpos */
709 complain_overflow_dont, /* complain_on_overflow */
710 bfd_elf_generic_reloc, /* special_function */
711 "R_RISCV_SET6", /* name */
712 false, /* partial_inplace */
713 0, /* src_mask */
714 0x3f, /* dst_mask */
715 false), /* pcrel_offset */
717 /* 8-bit in-place setting, for local label subtraction. */
718 HOWTO (R_RISCV_SET8, /* type */
719 0, /* rightshift */
720 1, /* size */
721 8, /* bitsize */
722 false, /* pc_relative */
723 0, /* bitpos */
724 complain_overflow_dont, /* complain_on_overflow */
725 bfd_elf_generic_reloc, /* special_function */
726 "R_RISCV_SET8", /* name */
727 false, /* partial_inplace */
728 0, /* src_mask */
729 0xff, /* dst_mask */
730 false), /* pcrel_offset */
732 /* 16-bit in-place setting, for local label subtraction. */
733 HOWTO (R_RISCV_SET16, /* type */
734 0, /* rightshift */
735 2, /* size */
736 16, /* bitsize */
737 false, /* pc_relative */
738 0, /* bitpos */
739 complain_overflow_dont, /* complain_on_overflow */
740 bfd_elf_generic_reloc, /* special_function */
741 "R_RISCV_SET16", /* name */
742 false, /* partial_inplace */
743 0, /* src_mask */
744 0xffff, /* dst_mask */
745 false), /* pcrel_offset */
747 /* 32-bit in-place setting, for local label subtraction. */
748 HOWTO (R_RISCV_SET32, /* type */
749 0, /* rightshift */
750 4, /* size */
751 32, /* bitsize */
752 false, /* pc_relative */
753 0, /* bitpos */
754 complain_overflow_dont, /* complain_on_overflow */
755 bfd_elf_generic_reloc, /* special_function */
756 "R_RISCV_SET32", /* name */
757 false, /* partial_inplace */
758 0, /* src_mask */
759 0xffffffff, /* dst_mask */
760 false), /* pcrel_offset */
762 /* 32-bit PC relative. */
763 HOWTO (R_RISCV_32_PCREL, /* type */
764 0, /* rightshift */
765 4, /* size */
766 32, /* bitsize */
767 true, /* pc_relative */
768 0, /* bitpos */
769 complain_overflow_dont, /* complain_on_overflow */
770 bfd_elf_generic_reloc, /* special_function */
771 "R_RISCV_32_PCREL", /* name */
772 false, /* partial_inplace */
773 0, /* src_mask */
774 0xffffffff, /* dst_mask */
775 false), /* pcrel_offset */
777 /* Relocation against a local ifunc symbol in a shared object. */
778 HOWTO (R_RISCV_IRELATIVE, /* type */
779 0, /* rightshift */
780 4, /* size */
781 32, /* bitsize */
782 false, /* pc_relative */
783 0, /* bitpos */
784 complain_overflow_dont, /* complain_on_overflow */
785 bfd_elf_generic_reloc, /* special_function */
786 "R_RISCV_IRELATIVE", /* name */
787 false, /* partial_inplace */
788 0, /* src_mask */
789 0xffffffff, /* dst_mask */
790 false), /* pcrel_offset */
792 /* Reserved for R_RISCV_PLT32. */
793 EMPTY_HOWTO (59),
795 /* N-bit in-place setting, for unsigned-leb128 local label subtraction. */
796 HOWTO (R_RISCV_SET_ULEB128, /* type */
797 0, /* rightshift */
798 0, /* size */
799 0, /* bitsize */
800 false, /* pc_relative */
801 0, /* bitpos */
802 complain_overflow_dont, /* complain_on_overflow */
803 riscv_elf_ignore_reloc, /* special_function */
804 "R_RISCV_SET_ULEB128", /* name */
805 false, /* partial_inplace */
806 0, /* src_mask */
807 0, /* dst_mask */
808 false), /* pcrel_offset */
810 /* N-bit in-place addition, for unsigned-leb128 local label subtraction. */
811 HOWTO (R_RISCV_SUB_ULEB128, /* type */
812 0, /* rightshift */
813 0, /* size */
814 0, /* bitsize */
815 false, /* pc_relative */
816 0, /* bitpos */
817 complain_overflow_dont, /* complain_on_overflow */
818 riscv_elf_ignore_reloc, /* special_function */
819 "R_RISCV_SUB_ULEB128", /* name */
820 false, /* partial_inplace */
821 0, /* src_mask */
822 0, /* dst_mask */
823 false), /* pcrel_offset */
825 HOWTO (R_RISCV_TLSDESC_HI20, /* type */
826 0, /* rightshift */
827 4, /* size */
828 32, /* bitsize */
829 true, /* pc_relative */
830 0, /* bitpos */
831 complain_overflow_dont, /* complain_on_overflow */
832 bfd_elf_generic_reloc, /* special_function */
833 "R_RISCV_TLSDESC_HI20", /* name */
834 true, /* partial_inplace */
835 0, /* src_mask */
836 ENCODE_UTYPE_IMM (-1U), /* dst_mask */
837 false), /* pcrel_offset */
839 HOWTO (R_RISCV_TLSDESC_LOAD_LO12, /* type */
840 0, /* rightshift */
841 4, /* size */
842 32, /* bitsize */
843 false, /* pc_relative */
844 0, /* bitpos */
845 complain_overflow_dont, /* complain_on_overflow */
846 bfd_elf_generic_reloc, /* special_function */
847 "R_RISCV_TLSDESC_LOAD_LO12", /* name */
848 false, /* partial_inplace */
849 0, /* src_mask */
850 ENCODE_ITYPE_IMM (-1U), /* dst_mask */
851 false), /* pcrel_offset */
853 HOWTO (R_RISCV_TLSDESC_ADD_LO12, /* type */
854 0, /* rightshift */
855 4, /* size */
856 32, /* bitsize */
857 false, /* pc_relative */
858 0, /* bitpos */
859 complain_overflow_dont, /* complain_on_overflow */
860 bfd_elf_generic_reloc, /* special_function */
861 "R_RISCV_TLSDESC_ADD_LO12", /* name */
862 false, /* partial_inplace */
863 0, /* src_mask */
864 ENCODE_ITYPE_IMM (-1U), /* dst_mask */
865 false), /* pcrel_offset */
867 HOWTO (R_RISCV_TLSDESC_CALL, /* type */
868 0, /* rightshift */
869 0, /* size */
870 0, /* bitsize */
871 false, /* pc_relative */
872 0, /* bitpos */
873 complain_overflow_dont, /* complain_on_overflow */
874 bfd_elf_generic_reloc, /* special_function */
875 "R_RISCV_TLSDESC_CALL", /* name */
876 false, /* partial_inplace */
877 0, /* src_mask */
878 ENCODE_ITYPE_IMM (-1U), /* dst_mask */
879 false) /* pcrel_offset */
882 static reloc_howto_type howto_table_internal[] =
884 /* R_RISCV_DELETE. */
885 EMPTY_HOWTO (0),
887 /* High 6 bits of 18-bit absolute address. */
888 HOWTO (R_RISCV_RVC_LUI, /* type */
889 0, /* rightshift */
890 2, /* size */
891 16, /* bitsize */
892 false, /* pc_relative */
893 0, /* bitpos */
894 complain_overflow_dont, /* complain_on_overflow */
895 bfd_elf_generic_reloc, /* special_function */
896 "R_RISCV_RVC_LUI", /* name */
897 false, /* partial_inplace */
898 0, /* src_mask */
899 ENCODE_CITYPE_IMM (-1U), /* dst_mask */
900 false), /* pcrel_offset */
902 /* GP-relative load. */
903 HOWTO (R_RISCV_GPREL_I, /* type */
904 0, /* rightshift */
905 4, /* size */
906 32, /* bitsize */
907 false, /* pc_relative */
908 0, /* bitpos */
909 complain_overflow_dont, /* complain_on_overflow */
910 bfd_elf_generic_reloc, /* special_function */
911 "R_RISCV_GPREL_I", /* name */
912 false, /* partial_inplace */
913 0, /* src_mask */
914 ENCODE_ITYPE_IMM (-1U), /* dst_mask */
915 false), /* pcrel_offset */
917 /* GP-relative store. */
918 HOWTO (R_RISCV_GPREL_S, /* type */
919 0, /* rightshift */
920 4, /* size */
921 32, /* bitsize */
922 false, /* pc_relative */
923 0, /* bitpos */
924 complain_overflow_dont, /* complain_on_overflow */
925 bfd_elf_generic_reloc, /* special_function */
926 "R_RISCV_GPREL_S", /* name */
927 false, /* partial_inplace */
928 0, /* src_mask */
929 ENCODE_STYPE_IMM (-1U), /* dst_mask */
930 false), /* pcrel_offset */
932 /* TP-relative TLS LE load. */
933 HOWTO (R_RISCV_TPREL_I, /* type */
934 0, /* rightshift */
935 4, /* size */
936 32, /* bitsize */
937 false, /* pc_relative */
938 0, /* bitpos */
939 complain_overflow_signed, /* complain_on_overflow */
940 bfd_elf_generic_reloc, /* special_function */
941 "R_RISCV_TPREL_I", /* name */
942 false, /* partial_inplace */
943 0, /* src_mask */
944 ENCODE_ITYPE_IMM (-1U), /* dst_mask */
945 false), /* pcrel_offset */
947 /* TP-relative TLS LE store. */
948 HOWTO (R_RISCV_TPREL_S, /* type */
949 0, /* rightshift */
950 4, /* size */
951 32, /* bitsize */
952 false, /* pc_relative */
953 0, /* bitpos */
954 complain_overflow_signed, /* complain_on_overflow */
955 bfd_elf_generic_reloc, /* special_function */
956 "R_RISCV_TPREL_S", /* name */
957 false, /* partial_inplace */
958 0, /* src_mask */
959 ENCODE_STYPE_IMM (-1U), /* dst_mask */
960 false), /* pcrel_offset */
963 /* A mapping from BFD reloc types to RISC-V ELF reloc types. */
964 struct elf_reloc_map
966 bfd_reloc_code_real_type bfd_val;
967 enum elf_riscv_reloc_type elf_val;
970 static const struct elf_reloc_map riscv_reloc_map[] =
972 { BFD_RELOC_NONE, R_RISCV_NONE },
973 { BFD_RELOC_32, R_RISCV_32 },
974 { BFD_RELOC_64, R_RISCV_64 },
975 { BFD_RELOC_RISCV_ADD8, R_RISCV_ADD8 },
976 { BFD_RELOC_RISCV_ADD16, R_RISCV_ADD16 },
977 { BFD_RELOC_RISCV_ADD32, R_RISCV_ADD32 },
978 { BFD_RELOC_RISCV_ADD64, R_RISCV_ADD64 },
979 { BFD_RELOC_RISCV_SUB8, R_RISCV_SUB8 },
980 { BFD_RELOC_RISCV_SUB16, R_RISCV_SUB16 },
981 { BFD_RELOC_RISCV_SUB32, R_RISCV_SUB32 },
982 { BFD_RELOC_RISCV_SUB64, R_RISCV_SUB64 },
983 { BFD_RELOC_CTOR, R_RISCV_64 },
984 { BFD_RELOC_12_PCREL, R_RISCV_BRANCH },
985 { BFD_RELOC_RISCV_HI20, R_RISCV_HI20 },
986 { BFD_RELOC_RISCV_LO12_I, R_RISCV_LO12_I },
987 { BFD_RELOC_RISCV_LO12_S, R_RISCV_LO12_S },
988 { BFD_RELOC_RISCV_PCREL_LO12_I, R_RISCV_PCREL_LO12_I },
989 { BFD_RELOC_RISCV_PCREL_LO12_S, R_RISCV_PCREL_LO12_S },
990 { BFD_RELOC_RISCV_CALL, R_RISCV_CALL },
991 { BFD_RELOC_RISCV_CALL_PLT, R_RISCV_CALL_PLT },
992 { BFD_RELOC_RISCV_PCREL_HI20, R_RISCV_PCREL_HI20 },
993 { BFD_RELOC_RISCV_JMP, R_RISCV_JAL },
994 { BFD_RELOC_RISCV_GOT_HI20, R_RISCV_GOT_HI20 },
995 { BFD_RELOC_RISCV_TLS_DTPMOD32, R_RISCV_TLS_DTPMOD32 },
996 { BFD_RELOC_RISCV_TLS_DTPREL32, R_RISCV_TLS_DTPREL32 },
997 { BFD_RELOC_RISCV_TLS_DTPMOD64, R_RISCV_TLS_DTPMOD64 },
998 { BFD_RELOC_RISCV_TLS_DTPREL64, R_RISCV_TLS_DTPREL64 },
999 { BFD_RELOC_RISCV_TLS_TPREL32, R_RISCV_TLS_TPREL32 },
1000 { BFD_RELOC_RISCV_TLS_TPREL64, R_RISCV_TLS_TPREL64 },
1001 { BFD_RELOC_RISCV_TPREL_HI20, R_RISCV_TPREL_HI20 },
1002 { BFD_RELOC_RISCV_TPREL_ADD, R_RISCV_TPREL_ADD },
1003 { BFD_RELOC_RISCV_TPREL_LO12_S, R_RISCV_TPREL_LO12_S },
1004 { BFD_RELOC_RISCV_TPREL_LO12_I, R_RISCV_TPREL_LO12_I },
1005 { BFD_RELOC_RISCV_TLS_GOT_HI20, R_RISCV_TLS_GOT_HI20 },
1006 { BFD_RELOC_RISCV_TLS_GD_HI20, R_RISCV_TLS_GD_HI20 },
1007 { BFD_RELOC_RISCV_TLSDESC_HI20, R_RISCV_TLSDESC_HI20 },
1008 { BFD_RELOC_RISCV_TLSDESC_LOAD_LO12, R_RISCV_TLSDESC_LOAD_LO12 },
1009 { BFD_RELOC_RISCV_TLSDESC_ADD_LO12, R_RISCV_TLSDESC_ADD_LO12 },
1010 { BFD_RELOC_RISCV_TLSDESC_CALL, R_RISCV_TLSDESC_CALL },
1011 { BFD_RELOC_RISCV_ALIGN, R_RISCV_ALIGN },
1012 { BFD_RELOC_RISCV_RVC_BRANCH, R_RISCV_RVC_BRANCH },
1013 { BFD_RELOC_RISCV_RVC_JUMP, R_RISCV_RVC_JUMP },
1014 { BFD_RELOC_RISCV_RELAX, R_RISCV_RELAX },
1015 { BFD_RELOC_RISCV_SUB6, R_RISCV_SUB6 },
1016 { BFD_RELOC_RISCV_SET6, R_RISCV_SET6 },
1017 { BFD_RELOC_RISCV_SET8, R_RISCV_SET8 },
1018 { BFD_RELOC_RISCV_SET16, R_RISCV_SET16 },
1019 { BFD_RELOC_RISCV_SET32, R_RISCV_SET32 },
1020 { BFD_RELOC_RISCV_32_PCREL, R_RISCV_32_PCREL },
1021 { BFD_RELOC_RISCV_SET_ULEB128, R_RISCV_SET_ULEB128 },
1022 { BFD_RELOC_RISCV_SUB_ULEB128, R_RISCV_SUB_ULEB128 },
1025 /* Given a BFD reloc type, return a howto structure. */
1027 reloc_howto_type *
1028 riscv_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED,
1029 bfd_reloc_code_real_type code)
1031 unsigned int i;
1033 for (i = 0; i < ARRAY_SIZE (riscv_reloc_map); i++)
1034 if (riscv_reloc_map[i].bfd_val == code)
1035 return &howto_table[(int) riscv_reloc_map[i].elf_val];
1037 bfd_set_error (bfd_error_bad_value);
1038 return NULL;
1041 reloc_howto_type *
1042 riscv_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED, const char *r_name)
1044 unsigned int i;
1046 for (i = 0; i < ARRAY_SIZE (howto_table); i++)
1047 if (howto_table[i].name && strcasecmp (howto_table[i].name, r_name) == 0)
1048 return &howto_table[i];
1050 return NULL;
1053 reloc_howto_type *
1054 riscv_elf_rtype_to_howto (bfd *abfd, unsigned int r_type)
1056 if (r_type < ARRAY_SIZE (howto_table))
1057 return &howto_table[r_type];
1058 else if (r_type < R_RISCV_max + ARRAY_SIZE (howto_table_internal))
1059 return &howto_table_internal[r_type - R_RISCV_max];
1060 else
1062 (*_bfd_error_handler) (_("%pB: unsupported relocation type %#x"),
1063 abfd, r_type);
1064 bfd_set_error (bfd_error_bad_value);
1065 return NULL;
1069 /* Special_function of RISCV_ADD and RISCV_SUB relocations. */
1071 static bfd_reloc_status_type
1072 riscv_elf_add_sub_reloc (bfd *abfd,
1073 arelent *reloc_entry,
1074 asymbol *symbol,
1075 void *data,
1076 asection *input_section,
1077 bfd *output_bfd,
1078 char **error_message ATTRIBUTE_UNUSED)
1080 reloc_howto_type *howto = reloc_entry->howto;
1081 bfd_vma relocation;
1083 if (output_bfd != NULL
1084 && (symbol->flags & BSF_SECTION_SYM) == 0
1085 && (!reloc_entry->howto->partial_inplace || reloc_entry->addend == 0))
1087 reloc_entry->address += input_section->output_offset;
1088 return bfd_reloc_ok;
1091 if (output_bfd != NULL)
1092 return bfd_reloc_continue;
1094 relocation = symbol->value + symbol->section->output_section->vma
1095 + symbol->section->output_offset + reloc_entry->addend;
1097 bfd_size_type octets = reloc_entry->address
1098 * bfd_octets_per_byte (abfd, input_section);
1099 if (!bfd_reloc_offset_in_range (reloc_entry->howto, abfd,
1100 input_section, octets))
1101 return bfd_reloc_outofrange;
1103 bfd_vma old_value = bfd_get (howto->bitsize, abfd,
1104 data + reloc_entry->address);
1106 switch (howto->type)
1108 case R_RISCV_ADD8:
1109 case R_RISCV_ADD16:
1110 case R_RISCV_ADD32:
1111 case R_RISCV_ADD64:
1112 relocation = old_value + relocation;
1113 break;
1114 case R_RISCV_SUB6:
1115 relocation = (old_value & ~howto->dst_mask)
1116 | (((old_value & howto->dst_mask) - relocation)
1117 & howto->dst_mask);
1118 break;
1119 case R_RISCV_SUB8:
1120 case R_RISCV_SUB16:
1121 case R_RISCV_SUB32:
1122 case R_RISCV_SUB64:
1123 relocation = old_value - relocation;
1124 break;
1126 bfd_put (howto->bitsize, abfd, relocation, data + reloc_entry->address);
1128 return bfd_reloc_ok;
1131 /* Special handler for relocations which don't have to be relocated.
1132 This function just simply return bfd_reloc_ok. */
1134 static bfd_reloc_status_type
1135 riscv_elf_ignore_reloc (bfd *abfd ATTRIBUTE_UNUSED,
1136 arelent *reloc_entry,
1137 asymbol *symbol ATTRIBUTE_UNUSED,
1138 void *data ATTRIBUTE_UNUSED,
1139 asection *input_section,
1140 bfd *output_bfd,
1141 char **error_message ATTRIBUTE_UNUSED)
1143 if (output_bfd != NULL)
1144 reloc_entry->address += input_section->output_offset;
1145 return bfd_reloc_ok;
1148 /* Always add implicit extensions for the SUBSET. */
1150 static bool
1151 check_implicit_always (riscv_subset_t *subset ATTRIBUTE_UNUSED)
1153 return true;
1156 /* Add implicit extensions only when the version of SUBSET less than 2.1. */
1158 static bool
1159 check_implicit_for_i (riscv_subset_t *subset)
1161 return (subset->major_version < 2
1162 || (subset->major_version == 2
1163 && subset->minor_version < 1));
1166 /* Record all implicit information for the subsets. */
1167 struct riscv_implicit_subset
1169 const char *ext;
1170 const char *implicit_exts;
1171 /* A function to determine if we need to add the implicit subsets. */
1172 bool (*check_func) (riscv_subset_t *);
1174 /* Please added in order since this table is only run once time. */
1175 static struct riscv_implicit_subset riscv_implicit_subsets[] =
1177 {"g", "+i,+m,+a,+f,+d,+zicsr,+zifencei", check_implicit_always},
1178 {"e", "+i", check_implicit_always},
1179 {"i", "+zicsr,+zifencei", check_implicit_for_i},
1180 {"zicntr", "+zicsr", check_implicit_always},
1181 {"zihpm", "+zicsr", check_implicit_always},
1183 {"m", "+zmmul", check_implicit_always},
1185 {"zabha", "+zaamo", check_implicit_always},
1186 {"zacas", "+zaamo", check_implicit_always},
1187 {"a", "+zaamo,+zalrsc", check_implicit_always},
1189 {"xsfvcp", "+zve32x", check_implicit_always},
1190 {"xsfvqmaccqoq", "+zve32x,+zvl256b", check_implicit_always},
1191 {"xsfvqmaccdod", "+zve32x,+zvl128b", check_implicit_always},
1192 {"xsfvfnrclipxfqf", "+zve32f", check_implicit_always},
1194 {"v", "+zve64d,+zvl128b", check_implicit_always},
1195 {"zvfh", "+zvfhmin,+zfhmin", check_implicit_always},
1196 {"zvfhmin", "+zve32f", check_implicit_always},
1197 {"zvfbfwma", "+zve32f,+zfbfmin", check_implicit_always},
1198 {"zvfbfmin", "+zve32f", check_implicit_always},
1199 {"zve64d", "+d,+zve64f", check_implicit_always},
1200 {"zve64f", "+zve32f,+zve64x,+zvl64b", check_implicit_always},
1201 {"zve32f", "+f,+zve32x,+zvl32b", check_implicit_always},
1202 {"zve64x", "+zve32x,+zvl64b", check_implicit_always},
1203 {"zve32x", "+zvl32b,+zicsr", check_implicit_always},
1204 {"zvl65536b", "+zvl32768b", check_implicit_always},
1205 {"zvl32768b", "+zvl16384b", check_implicit_always},
1206 {"zvl16384b", "+zvl8192b", check_implicit_always},
1207 {"zvl8192b", "+zvl4096b", check_implicit_always},
1208 {"zvl4096b", "+zvl2048b", check_implicit_always},
1209 {"zvl2048b", "+zvl1024b", check_implicit_always},
1210 {"zvl1024b", "+zvl512b", check_implicit_always},
1211 {"zvl512b", "+zvl256b", check_implicit_always},
1212 {"zvl256b", "+zvl128b", check_implicit_always},
1213 {"zvl128b", "+zvl64b", check_implicit_always},
1214 {"zvl64b", "+zvl32b", check_implicit_always},
1216 {"zcb", "+zca", check_implicit_always},
1217 {"zcd", "+d,+zca", check_implicit_always},
1218 {"zcf", "+f,+zca", check_implicit_always},
1219 {"zcmp", "+zca", check_implicit_always},
1220 {"zcmop", "+zca", check_implicit_always},
1221 {"zcmt", "+zca,+zicsr", check_implicit_always},
1223 {"zicfilp", "+zicsr", check_implicit_always},
1224 {"zicfiss", "+zimop,+zicsr", check_implicit_always},
1226 {"shcounterenw", "+h", check_implicit_always},
1227 {"shgatpa", "+h", check_implicit_always},
1228 {"shtvala", "+h", check_implicit_always},
1229 {"shvsatpa", "+h", check_implicit_always},
1230 {"shvstvala", "+h", check_implicit_always},
1231 {"shvstvecd", "+h", check_implicit_always},
1232 {"h", "+zicsr", check_implicit_always},
1233 {"zhinx", "+zhinxmin", check_implicit_always},
1234 {"zhinxmin", "+zfinx", check_implicit_always},
1236 {"q", "+d", check_implicit_always},
1237 {"zqinx", "+zdinx", check_implicit_always},
1239 {"d", "+f", check_implicit_always},
1240 {"zdinx", "+zfinx", check_implicit_always},
1242 {"zfa", "+f", check_implicit_always},
1243 {"zfbfmin", "+zfhmin", check_implicit_always},
1244 {"zfh", "+zfhmin", check_implicit_always},
1245 {"zfhmin", "+f", check_implicit_always},
1246 {"zfinx", "+zicsr", check_implicit_always},
1247 {"f", "+zicsr", check_implicit_always},
1249 {"b", "+zba,+zbb,+zbs", check_implicit_always},
1251 {"zk", "+zkn,+zkr,+zkt", check_implicit_always},
1252 {"zkn", "+zbkb,+zbkc,+zbkx,+zkne,+zknd,+zknh", check_implicit_always},
1253 {"zks", "+zbkb,+zbkc,+zbkx,+zksed,+zksh", check_implicit_always},
1254 {"zvbb", "+zvkb", check_implicit_always},
1255 {"zvkng", "+zvkn,+zvkg", check_implicit_always},
1256 {"zvknc", "+zvkn,+zvbc", check_implicit_always},
1257 {"zvkn", "+zvkned,+zvknhb,+zvkb,+zvkt", check_implicit_always},
1258 {"zvksg", "+zvks,+zvkg", check_implicit_always},
1259 {"zvksc", "+zvks,+zvbc", check_implicit_always},
1260 {"zvks", "+zvksed,+zvksh,+zvkb,+zvkt", check_implicit_always},
1262 {"smaia", "+ssaia", check_implicit_always},
1263 {"smcsrind", "+sscsrind", check_implicit_always},
1264 {"smcntrpmf", "+zicsr", check_implicit_always},
1265 {"smctr", "+zicsr", check_implicit_always},
1266 {"smstateen", "+ssstateen", check_implicit_always},
1267 {"smepmp", "+zicsr", check_implicit_always},
1268 {"smdbltrp", "+zicsr", check_implicit_always},
1270 {"ssaia", "+zicsr", check_implicit_always},
1271 {"sscsrind", "+zicsr", check_implicit_always},
1272 {"sscofpmf", "+zicsr", check_implicit_always},
1273 {"sscounterenw", "+zicsr", check_implicit_always},
1274 {"ssctr", "+zicsr", check_implicit_always},
1275 {"ssstateen", "+zicsr", check_implicit_always},
1276 {"sstc", "+zicsr", check_implicit_always},
1277 {"sstvala", "+zicsr", check_implicit_always},
1278 {"sstvecd", "+zicsr", check_implicit_always},
1279 {"ssu64xl", "+zicsr", check_implicit_always},
1280 {"ssdbltrp", "+zicsr", check_implicit_always},
1282 {"svade", "+zicsr", check_implicit_always},
1283 {"svadu", "+zicsr", check_implicit_always},
1284 {"svbare", "+zicsr", check_implicit_always},
1285 {NULL, NULL, NULL}
1288 /* For default_enable field, decide if the extension should
1289 be enbaled by default. */
1291 #define EXT_DEFAULT 0x1
1293 /* List all extensions that binutils should know about. */
1295 struct riscv_supported_ext
1297 const char *name;
1298 enum riscv_spec_class isa_spec_class;
1299 int major_version;
1300 int minor_version;
1301 unsigned long default_enable;
1304 /* The standard extensions must be added in canonical order. */
1306 static struct riscv_supported_ext riscv_supported_std_ext[] =
1308 {"e", ISA_SPEC_CLASS_20191213, 1, 9, 0 },
1309 {"e", ISA_SPEC_CLASS_20190608, 1, 9, 0 },
1310 {"e", ISA_SPEC_CLASS_2P2, 1, 9, 0 },
1311 {"i", ISA_SPEC_CLASS_20191213, 2, 1, 0 },
1312 {"i", ISA_SPEC_CLASS_20190608, 2, 1, 0 },
1313 {"i", ISA_SPEC_CLASS_2P2, 2, 0, 0 },
1314 /* The g is a special case which we don't want to output it,
1315 but still need it when adding implicit extensions. */
1316 {"g", ISA_SPEC_CLASS_NONE, RISCV_UNKNOWN_VERSION, RISCV_UNKNOWN_VERSION, EXT_DEFAULT },
1317 {"m", ISA_SPEC_CLASS_20191213, 2, 0, 0 },
1318 {"m", ISA_SPEC_CLASS_20190608, 2, 0, 0 },
1319 {"m", ISA_SPEC_CLASS_2P2, 2, 0, 0 },
1320 {"a", ISA_SPEC_CLASS_20191213, 2, 1, 0 },
1321 {"a", ISA_SPEC_CLASS_20190608, 2, 0, 0 },
1322 {"a", ISA_SPEC_CLASS_2P2, 2, 0, 0 },
1323 {"f", ISA_SPEC_CLASS_20191213, 2, 2, 0 },
1324 {"f", ISA_SPEC_CLASS_20190608, 2, 2, 0 },
1325 {"f", ISA_SPEC_CLASS_2P2, 2, 0, 0 },
1326 {"d", ISA_SPEC_CLASS_20191213, 2, 2, 0 },
1327 {"d", ISA_SPEC_CLASS_20190608, 2, 2, 0 },
1328 {"d", ISA_SPEC_CLASS_2P2, 2, 0, 0 },
1329 {"q", ISA_SPEC_CLASS_20191213, 2, 2, 0 },
1330 {"q", ISA_SPEC_CLASS_20190608, 2, 2, 0 },
1331 {"q", ISA_SPEC_CLASS_2P2, 2, 0, 0 },
1332 {"c", ISA_SPEC_CLASS_20191213, 2, 0, 0 },
1333 {"c", ISA_SPEC_CLASS_20190608, 2, 0, 0 },
1334 {"c", ISA_SPEC_CLASS_2P2, 2, 0, 0 },
1335 {"b", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1336 {"v", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1337 {"h", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1338 {NULL, 0, 0, 0, 0}
1341 static struct riscv_supported_ext riscv_supported_std_z_ext[] =
1343 {"zic64b", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1344 {"ziccamoa", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1345 {"ziccif", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1346 {"zicclsm", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1347 {"ziccrse", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1348 {"zicbom", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1349 {"zicbop", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1350 {"zicboz", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1351 {"zicond", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1352 {"zicntr", ISA_SPEC_CLASS_DRAFT, 2, 0, 0 },
1353 {"zicsr", ISA_SPEC_CLASS_20191213, 2, 0, 0 },
1354 {"zicsr", ISA_SPEC_CLASS_20190608, 2, 0, 0 },
1355 {"zifencei", ISA_SPEC_CLASS_20191213, 2, 0, 0 },
1356 {"zifencei", ISA_SPEC_CLASS_20190608, 2, 0, 0 },
1357 {"zihintntl", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1358 {"zihintpause", ISA_SPEC_CLASS_DRAFT, 2, 0, 0 },
1359 {"zihpm", ISA_SPEC_CLASS_DRAFT, 2, 0, 0 },
1360 {"zimop", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1361 {"zicfiss", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1362 {"zicfilp", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1363 {"zmmul", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1364 {"za64rs", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1365 {"za128rs", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1366 {"zaamo", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1367 {"zabha", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1368 {"zacas", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1369 {"zalrsc", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1370 {"zawrs", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1371 {"zfbfmin", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1372 {"zfa", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1373 {"zfh", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1374 {"zfhmin", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1375 {"zfinx", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1376 {"zdinx", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1377 {"zqinx", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1378 {"zhinx", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1379 {"zhinxmin", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1380 {"zbb", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1381 {"zba", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1382 {"zbc", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1383 {"zbs", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1384 {"zbkb", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1385 {"zbkc", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1386 {"zbkx", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1387 {"zk", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1388 {"zkn", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1389 {"zknd", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1390 {"zkne", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1391 {"zknh", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1392 {"zkr", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1393 {"zks", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1394 {"zksed", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1395 {"zksh", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1396 {"zkt", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1397 {"zve32x", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1398 {"zve32f", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1399 {"zve64x", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1400 {"zve64f", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1401 {"zve64d", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1402 {"zvbb", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1403 {"zvbc", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1404 {"zvfbfmin", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1405 {"zvfbfwma", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1406 {"zvfh", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1407 {"zvfhmin", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1408 {"zvkb", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1409 {"zvkg", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1410 {"zvkn", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1411 {"zvkng", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1412 {"zvknc", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1413 {"zvkned", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1414 {"zvknha", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1415 {"zvknhb", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1416 {"zvksed", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1417 {"zvksh", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1418 {"zvks", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1419 {"zvksg", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1420 {"zvksc", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1421 {"zvkt", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1422 {"zvl32b", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1423 {"zvl64b", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1424 {"zvl128b", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1425 {"zvl256b", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1426 {"zvl512b", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1427 {"zvl1024b", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1428 {"zvl2048b", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1429 {"zvl4096b", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1430 {"zvl8192b", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1431 {"zvl16384b", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1432 {"zvl32768b", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1433 {"zvl65536b", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1434 {"ztso", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1435 {"zca", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1436 {"zcb", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1437 {"zcf", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1438 {"zcd", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1439 {"zcmop", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1440 {"zcmp", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1441 {"zcmt", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1442 {NULL, 0, 0, 0, 0}
1445 static struct riscv_supported_ext riscv_supported_std_s_ext[] =
1447 {"shcounterenw", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1448 {"shgatpa", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1449 {"shtvala", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1450 {"shvsatpa", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1451 {"shvstvala", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1452 {"shvstvecd", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1453 {"smaia", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1454 {"smcsrind", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1455 {"smcntrpmf", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1456 {"smctr", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1457 {"smepmp", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1458 {"smrnmi", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1459 {"smstateen", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1460 {"smdbltrp", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1461 {"ssaia", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1462 {"ssccptr", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1463 {"sscsrind", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1464 {"sscofpmf", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1465 {"sscounterenw", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1466 {"ssctr", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1467 {"ssstateen", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1468 {"sstc", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1469 {"sstvala", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1470 {"sstvecd", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1471 {"ssu64xl", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1472 {"ssdbltrp", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1473 {"svade", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1474 {"svadu", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1475 {"svbare", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1476 {"svinval", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1477 {"svnapot", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1478 {"svpbmt", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1479 {NULL, 0, 0, 0, 0}
1482 static struct riscv_supported_ext riscv_supported_std_zxm_ext[] =
1484 {NULL, 0, 0, 0, 0}
1487 static struct riscv_supported_ext riscv_supported_vendor_x_ext[] =
1489 {"xcvalu", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1490 {"xcvbi", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1491 {"xcvbitmanip", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1492 {"xcvelw", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1493 {"xcvmac", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1494 {"xcvmem", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1495 {"xcvsimd", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1496 {"xtheadba", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1497 {"xtheadbb", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1498 {"xtheadbs", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1499 {"xtheadcmo", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1500 {"xtheadcondmov", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1501 {"xtheadfmemidx", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1502 {"xtheadfmv", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1503 {"xtheadint", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1504 {"xtheadmac", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1505 {"xtheadmemidx", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1506 {"xtheadmempair", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1507 {"xtheadsync", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1508 {"xtheadvector", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1509 {"xtheadzvamo", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1510 {"xventanacondops", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1511 {"xsfvcp", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1512 {"xsfcease", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1513 {"xsfvqmaccqoq", ISA_SPEC_CLASS_DRAFT, 1, 0, 0},
1514 {"xsfvqmaccdod", ISA_SPEC_CLASS_DRAFT, 1, 0, 0},
1515 {"xsfvfnrclipxfqf", ISA_SPEC_CLASS_DRAFT, 1, 0, 0},
1516 {NULL, 0, 0, 0, 0}
1519 const struct riscv_supported_ext *riscv_all_supported_ext[] =
1521 riscv_supported_std_ext,
1522 riscv_supported_std_z_ext,
1523 riscv_supported_std_s_ext,
1524 riscv_supported_std_zxm_ext,
1525 riscv_supported_vendor_x_ext,
1526 NULL
1529 /* ISA extension prefixed name class. Must define them in parsing order. */
1530 enum riscv_prefix_ext_class
1532 RV_ISA_CLASS_Z = 1,
1533 RV_ISA_CLASS_S,
1534 RV_ISA_CLASS_ZXM,
1535 RV_ISA_CLASS_X,
1536 RV_ISA_CLASS_SINGLE
1539 /* Record the strings of the prefixed extensions, and their corresponding
1540 classes. The more letters of the prefix string, the more forward it must
1541 be defined. Otherwise, the riscv_get_prefix_class will map it to the
1542 wrong classes. */
1543 struct riscv_parse_prefix_config
1545 /* Class of the extension. */
1546 enum riscv_prefix_ext_class class;
1548 /* Prefix string for error printing and internal parser usage. */
1549 const char *prefix;
1551 static const struct riscv_parse_prefix_config parse_config[] =
1553 {RV_ISA_CLASS_ZXM, "zxm"},
1554 {RV_ISA_CLASS_Z, "z"},
1555 {RV_ISA_CLASS_S, "s"},
1556 {RV_ISA_CLASS_X, "x"},
1557 {RV_ISA_CLASS_SINGLE, NULL}
1560 /* Get the prefixed name class for the extensions, the class also
1561 means the order of the prefixed extensions. */
1563 static enum riscv_prefix_ext_class
1564 riscv_get_prefix_class (const char *arch)
1566 int i = 0;
1567 while (parse_config[i].class != RV_ISA_CLASS_SINGLE)
1569 if (strncmp (arch, parse_config[i].prefix,
1570 strlen (parse_config[i].prefix)) == 0)
1571 return parse_config[i].class;
1572 i++;
1574 return RV_ISA_CLASS_SINGLE;
1577 /* Check KNOWN_EXTS to see if the EXT is supported. */
1579 static bool
1580 riscv_known_prefixed_ext (const char *ext,
1581 struct riscv_supported_ext *known_exts)
1583 size_t i;
1584 for (i = 0; known_exts[i].name != NULL; ++i)
1585 if (strcmp (ext, known_exts[i].name) == 0)
1586 return true;
1587 return false;
1590 /* Check whether the prefixed extension is recognized or not. Return
1591 true if recognized, otehrwise return false. */
1593 static bool
1594 riscv_recognized_prefixed_ext (const char *ext)
1596 enum riscv_prefix_ext_class class = riscv_get_prefix_class (ext);
1597 switch (class)
1599 case RV_ISA_CLASS_Z:
1600 return riscv_known_prefixed_ext (ext, riscv_supported_std_z_ext);
1601 case RV_ISA_CLASS_ZXM:
1602 return riscv_known_prefixed_ext (ext, riscv_supported_std_zxm_ext);
1603 case RV_ISA_CLASS_S:
1604 return riscv_known_prefixed_ext (ext, riscv_supported_std_s_ext);
1605 case RV_ISA_CLASS_X:
1606 /* Only the single x is unrecognized. */
1607 if (strcmp (ext, "x") != 0)
1608 return true;
1609 default:
1610 break;
1612 return false;
1615 /* Canonical order for single letter extensions. */
1616 static const char riscv_ext_canonical_order[] = "eigmafdqlcbkjtpvnh";
1618 /* Array is used to compare the orders of standard extensions quickly. */
1619 static int riscv_ext_order[26] = {0};
1621 /* Init the riscv_ext_order array. */
1623 static void
1624 riscv_init_ext_order (void)
1626 static bool inited = false;
1627 if (inited)
1628 return;
1630 /* The orders of all standard extensions are positive. */
1631 int order = 1;
1633 for (const char *ext = &riscv_ext_canonical_order[0]; *ext; ++ext)
1634 riscv_ext_order[(*ext - 'a')] = order++;
1636 /* Some of the prefixed keyword are not single letter, so we set
1637 their prefixed orders in the riscv_compare_subsets directly,
1638 not through the riscv_ext_order. */
1640 inited = true;
1643 /* Similar to the strcmp. It returns an integer less than, equal to,
1644 or greater than zero if `subset2` is found, respectively, to be less
1645 than, to match, or be greater than `subset1`.
1647 The order values,
1648 Zero: Preserved keywords.
1649 Positive number: Standard extensions.
1650 Negative number: Prefixed keywords. */
1653 riscv_compare_subsets (const char *subset1, const char *subset2)
1655 int order1 = riscv_ext_order[(*subset1 - 'a')];
1656 int order2 = riscv_ext_order[(*subset2 - 'a')];
1658 /* Compare the standard extension first. */
1659 if (order1 > 0 && order2 > 0)
1660 return order1 - order2;
1662 /* Set the prefixed orders to negative numbers. */
1663 enum riscv_prefix_ext_class class1 = riscv_get_prefix_class (subset1);
1664 enum riscv_prefix_ext_class class2 = riscv_get_prefix_class (subset2);
1666 if (class1 != RV_ISA_CLASS_SINGLE)
1667 order1 = - (int) class1;
1668 if (class2 != RV_ISA_CLASS_SINGLE)
1669 order2 = - (int) class2;
1671 if (order1 == order2)
1673 /* Compare the standard addition z extensions. */
1674 if (class1 == RV_ISA_CLASS_Z)
1676 order1 = riscv_ext_order[(*++subset1 - 'a')];
1677 order2 = riscv_ext_order[(*++subset2 - 'a')];
1678 if (order1 != order2)
1679 return order1 - order2;
1681 return strcasecmp (++subset1, ++subset2);
1684 return order2 - order1;
1687 /* Find subset in the list. Return TRUE and set `current` to the subset
1688 if it is found. Otherwise, return FALSE and set `current` to the place
1689 where we should insert the subset. However, return FALSE with the NULL
1690 `current` means we should insert the subset at the head of subset list,
1691 if needed. */
1693 bool
1694 riscv_lookup_subset (const riscv_subset_list_t *subset_list,
1695 const char *subset,
1696 riscv_subset_t **current)
1698 riscv_subset_t *s, *pre_s = NULL;
1700 /* If the subset is added in order, then just add it at the tail. */
1701 if (subset_list->tail != NULL
1702 && riscv_compare_subsets (subset_list->tail->name, subset) < 0)
1704 *current = subset_list->tail;
1705 return false;
1708 for (s = subset_list->head;
1709 s != NULL;
1710 pre_s = s, s = s->next)
1712 int cmp = riscv_compare_subsets (s->name, subset);
1713 if (cmp == 0)
1715 *current = s;
1716 return true;
1718 else if (cmp > 0)
1719 break;
1721 *current = pre_s;
1723 return false;
1726 /* Add the extension to the subset list. Search the
1727 list first, and then find the right place to add. */
1729 void
1730 riscv_add_subset (riscv_subset_list_t *subset_list,
1731 const char *subset,
1732 int major,
1733 int minor)
1735 riscv_subset_t *current, *new;
1737 if (riscv_lookup_subset (subset_list, subset, &current))
1738 return;
1740 new = xmalloc (sizeof *new);
1741 new->name = xstrdup (subset);
1742 new->major_version = major;
1743 new->minor_version = minor;
1744 new->next = NULL;
1746 if (current != NULL)
1748 new->next = current->next;
1749 current->next = new;
1751 else
1753 new->next = subset_list->head;
1754 subset_list->head = new;
1757 if (new->next == NULL)
1758 subset_list->tail = new;
1761 /* Get the default versions from the riscv_supported_*ext tables. */
1763 static void
1764 riscv_get_default_ext_version (enum riscv_spec_class *default_isa_spec,
1765 const char *name,
1766 int *major_version,
1767 int *minor_version)
1769 if (name == NULL
1770 || default_isa_spec == NULL
1771 || *default_isa_spec == ISA_SPEC_CLASS_NONE)
1772 return;
1774 struct riscv_supported_ext *table = NULL;
1775 enum riscv_prefix_ext_class class = riscv_get_prefix_class (name);
1776 switch (class)
1778 case RV_ISA_CLASS_ZXM: table = riscv_supported_std_zxm_ext; break;
1779 case RV_ISA_CLASS_Z: table = riscv_supported_std_z_ext; break;
1780 case RV_ISA_CLASS_S: table = riscv_supported_std_s_ext; break;
1781 case RV_ISA_CLASS_X: table = riscv_supported_vendor_x_ext; break;
1782 default:
1783 table = riscv_supported_std_ext;
1786 int i = 0;
1787 while (table != NULL && table[i].name != NULL)
1789 if (strcmp (table[i].name, name) == 0
1790 && (table[i].isa_spec_class == ISA_SPEC_CLASS_DRAFT
1791 || table[i].isa_spec_class == *default_isa_spec))
1793 *major_version = table[i].major_version;
1794 *minor_version = table[i].minor_version;
1795 return;
1797 i++;
1801 /* Find the default versions for the extension before adding them to
1802 the subset list, if their versions are RISCV_UNKNOWN_VERSION.
1803 Afterwards, report errors if we can not find their default versions. */
1805 static void
1806 riscv_parse_add_subset (riscv_parse_subset_t *rps,
1807 const char *subset,
1808 int major,
1809 int minor,
1810 bool implicit)
1812 int major_version = major;
1813 int minor_version = minor;
1815 if (major_version == RISCV_UNKNOWN_VERSION
1816 || minor_version == RISCV_UNKNOWN_VERSION)
1817 riscv_get_default_ext_version (rps->isa_spec, subset,
1818 &major_version, &minor_version);
1820 /* We don't care the versions of the implicit extensions. */
1821 if (!implicit
1822 && (major_version == RISCV_UNKNOWN_VERSION
1823 || minor_version == RISCV_UNKNOWN_VERSION))
1825 if (subset[0] == 'x')
1826 rps->error_handler
1827 (_("x ISA extension `%s' must be set with the versions"),
1828 subset);
1829 /* Allow old ISA spec can recognize zicsr and zifencei. */
1830 else if (strcmp (subset, "zicsr") != 0
1831 && strcmp (subset, "zifencei") != 0)
1832 rps->error_handler
1833 (_("cannot find default versions of the ISA extension `%s'"),
1834 subset);
1835 return;
1838 riscv_add_subset (rps->subset_list, subset,
1839 major_version, minor_version);
1842 /* Release subset list. */
1844 void
1845 riscv_release_subset_list (riscv_subset_list_t *subset_list)
1847 while (subset_list->head != NULL)
1849 riscv_subset_t *next = subset_list->head->next;
1850 free ((void *)subset_list->head->name);
1851 free (subset_list->head);
1852 subset_list->head = next;
1855 subset_list->tail = NULL;
1857 if (subset_list->arch_str != NULL)
1859 free ((void*) subset_list->arch_str);
1860 subset_list->arch_str = NULL;
1864 /* Parsing extension version.
1866 Return Value:
1867 Points to the end of version
1869 Arguments:
1870 `p`: Curent parsing position.
1871 `major_version`: Parsed major version.
1872 `minor_version`: Parsed minor version. */
1874 static const char *
1875 riscv_parsing_subset_version (const char *p,
1876 int *major_version,
1877 int *minor_version)
1879 bool major_p = true;
1880 int version = 0;
1881 char np;
1883 *major_version = 0;
1884 *minor_version = 0;
1885 for (; *p; ++p)
1887 if (*p == 'p')
1889 np = *(p + 1);
1891 /* Might be beginning of `p` extension. */
1892 if (!ISDIGIT (np))
1893 break;
1895 *major_version = version;
1896 major_p = false;
1897 version = 0;
1899 else if (ISDIGIT (*p))
1900 version = (version * 10) + (*p - '0');
1901 else
1902 break;
1905 if (major_p)
1906 *major_version = version;
1907 else
1908 *minor_version = version;
1910 /* We can not find any version in string. */
1911 if (*major_version == 0 && *minor_version == 0)
1913 *major_version = RISCV_UNKNOWN_VERSION;
1914 *minor_version = RISCV_UNKNOWN_VERSION;
1917 return p;
1920 /* Parsing function for both standard and prefixed extensions.
1922 Return Value:
1923 Points to the end of extensions.
1925 Arguments:
1926 `rps`: Hooks and status for parsing extensions.
1927 `arch`: Full ISA string.
1928 `p`: Curent parsing position. */
1930 static const char *
1931 riscv_parse_extensions (riscv_parse_subset_t *rps,
1932 const char *arch,
1933 const char *p)
1935 /* First letter must start with i, e or g. */
1936 if (*p != 'e' && *p != 'i' && *p != 'g')
1938 rps->error_handler
1939 (_("%s: first ISA extension must be `e', `i' or `g'"),
1940 arch);
1941 return NULL;
1944 while (*p != '\0')
1946 if (*p == '_')
1948 p++;
1949 continue;
1952 char *subset = xstrdup (p);
1953 char *q = subset; /* Start of version. */
1954 const char *end_of_version;
1955 bool implicit = false;
1957 enum riscv_prefix_ext_class class = riscv_get_prefix_class (p);
1958 if (class == RV_ISA_CLASS_SINGLE)
1960 if (riscv_ext_order[(*subset - 'a')] == 0)
1962 rps->error_handler
1963 (_("%s: unknown standard ISA extension or prefix class `%c'"),
1964 arch, *subset);
1965 free (subset);
1966 return NULL;
1968 q++;
1970 else
1972 /* Extract the whole prefixed extension by '_'. */
1973 while (*++q != '\0' && *q != '_')
1975 /* Look forward to the first letter which is not <major>p<minor>. */
1976 bool find_any_version = false;
1977 bool find_minor_version = false;
1978 while (1)
1980 q--;
1981 if (ISDIGIT (*q))
1982 find_any_version = true;
1983 else if (find_any_version
1984 && !find_minor_version
1985 && *q == 'p'
1986 && ISDIGIT (*(q - 1)))
1987 find_minor_version = true;
1988 else
1989 break;
1991 q++;
1993 /* Check if the end of extension is 'p' or not. If yes, then
1994 the second letter from the end cannot be number. */
1995 if (*(q - 1) == 'p' && ISDIGIT (*(q - 2)))
1997 *q = '\0';
1998 rps->error_handler
1999 (_("%s: invalid prefixed ISA extension `%s' ends with <number>p"),
2000 arch, subset);
2001 free (subset);
2002 return NULL;
2006 int major_version = RISCV_UNKNOWN_VERSION;
2007 int minor_version = RISCV_UNKNOWN_VERSION;
2008 end_of_version =
2009 riscv_parsing_subset_version (q, &major_version, &minor_version);
2010 *q = '\0';
2011 if (end_of_version == NULL)
2013 free (subset);
2014 return NULL;
2017 /* Check if the prefixed extension name is well-formed. */
2018 if (class != RV_ISA_CLASS_SINGLE
2019 && rps->check_unknown_prefixed_ext
2020 && !riscv_recognized_prefixed_ext (subset))
2022 rps->error_handler
2023 (_("%s: unknown prefixed ISA extension `%s'"),
2024 arch, subset);
2025 free (subset);
2026 return NULL;
2029 /* Added g as an implicit extension. */
2030 if (class == RV_ISA_CLASS_SINGLE
2031 && strcmp (subset, "g") == 0)
2033 implicit = true;
2034 major_version = RISCV_UNKNOWN_VERSION;
2035 minor_version = RISCV_UNKNOWN_VERSION;
2037 riscv_parse_add_subset (rps, subset,
2038 major_version,
2039 minor_version, implicit);
2040 p += end_of_version - subset;
2041 free (subset);
2043 if (class != RV_ISA_CLASS_SINGLE
2044 && *p != '\0' && *p != '_')
2046 rps->error_handler
2047 (_("%s: prefixed ISA extension must separate with _"),
2048 arch);
2049 return NULL;
2053 return p;
2056 static bool
2057 riscv_update_subset1 (riscv_parse_subset_t *, riscv_subset_t *, const char *);
2059 /* Add the implicit extensions. */
2061 static void
2062 riscv_parse_add_implicit_subsets (riscv_parse_subset_t *rps)
2064 struct riscv_implicit_subset *t = riscv_implicit_subsets;
2065 for (; t->ext; t++)
2067 riscv_subset_t *subset = NULL;
2068 if (riscv_lookup_subset (rps->subset_list, t->ext, &subset)
2069 && t->check_func (subset))
2070 riscv_update_subset1 (rps, subset, t->implicit_exts);
2074 /* Check extensions conflicts. */
2076 static bool
2077 riscv_parse_check_conflicts (riscv_parse_subset_t *rps)
2079 riscv_subset_t *subset = NULL;
2080 int xlen = *rps->xlen;
2081 bool no_conflict = true;
2083 if (riscv_subset_supports (rps, "e")
2084 && riscv_subset_supports (rps, "h"))
2086 rps->error_handler
2087 (_("rv%de does not support the `h' extension"), xlen);
2088 no_conflict = false;
2090 if (riscv_lookup_subset (rps->subset_list, "q", &subset)
2091 && (subset->major_version < 2 || (subset->major_version == 2
2092 && subset->minor_version < 2))
2093 && xlen < 64)
2095 rps->error_handler (_("rv%d does not support the `q' extension"), xlen);
2096 no_conflict = false;
2098 if (riscv_subset_supports (rps, "zcmp")
2099 && riscv_subset_supports (rps, "zcd"))
2101 rps->error_handler
2102 (_("zcmp' is incompatible with `d/zcd' extension"));
2103 no_conflict = false;
2105 if (riscv_lookup_subset (rps->subset_list, "zcf", &subset)
2106 && xlen > 32)
2108 rps->error_handler
2109 (_("rv%d does not support the `zcf' extension"), xlen);
2110 no_conflict = false;
2112 if (riscv_lookup_subset (rps->subset_list, "zfinx", &subset)
2113 && riscv_lookup_subset (rps->subset_list, "f", &subset))
2115 rps->error_handler
2116 (_("`zfinx' is conflict with the `f/d/q/zfh/zfhmin' extension"));
2117 no_conflict = false;
2119 if (riscv_lookup_subset (rps->subset_list, "xtheadvector", &subset)
2120 && riscv_lookup_subset (rps->subset_list, "v", &subset))
2122 rps->error_handler
2123 (_("`xtheadvector' is conflict with the `v' extension"));
2124 no_conflict = false;
2127 bool support_zve = false;
2128 bool support_zvl = false;
2129 riscv_subset_t *s = rps->subset_list->head;
2130 for (; s != NULL; s = s->next)
2132 if (!support_zve
2133 && strncmp (s->name, "zve", 3) == 0)
2134 support_zve = true;
2135 if (!support_zvl
2136 && strncmp (s->name, "zvl", 3) == 0)
2137 support_zvl = true;
2138 if (support_zve && support_zvl)
2139 break;
2141 if (support_zvl && !support_zve)
2143 rps->error_handler
2144 (_("zvl*b extensions need to enable either `v' or `zve' extension"));
2145 no_conflict = false;
2148 return no_conflict;
2151 /* Set the default subset list according to the default_enable field
2152 of riscv_supported_*ext tables. */
2154 static void
2155 riscv_set_default_arch (riscv_parse_subset_t *rps)
2157 unsigned long enable = EXT_DEFAULT;
2158 int i, j;
2159 for (i = 0; riscv_all_supported_ext[i] != NULL; i++)
2161 const struct riscv_supported_ext *table = riscv_all_supported_ext[i];
2162 for (j = 0; table[j].name != NULL; j++)
2164 bool implicit = false;
2165 if (strcmp (table[j].name, "g") == 0)
2166 implicit = true;
2167 if (table[j].default_enable & enable)
2168 riscv_parse_add_subset (rps, table[j].name,
2169 RISCV_UNKNOWN_VERSION,
2170 RISCV_UNKNOWN_VERSION, implicit);
2175 /* Function for parsing ISA string.
2177 Return Value:
2178 Return TRUE on success.
2180 Arguments:
2181 `rps`: Hooks and status for parsing extensions.
2182 `arch`: Full ISA string. */
2184 bool
2185 riscv_parse_subset (riscv_parse_subset_t *rps,
2186 const char *arch)
2188 const char *p;
2190 /* Init the riscv_ext_order array to compare the order of extensions
2191 quickly. */
2192 riscv_init_ext_order ();
2194 if (arch == NULL)
2196 riscv_set_default_arch (rps);
2197 riscv_parse_add_implicit_subsets (rps);
2198 return riscv_parse_check_conflicts (rps);
2201 for (p = arch; *p != '\0'; p++)
2203 if (ISUPPER (*p))
2205 rps->error_handler
2206 (_("%s: ISA string cannot contain uppercase letters"),
2207 arch);
2208 return false;
2212 p = arch;
2213 if (startswith (p, "rv32"))
2215 *rps->xlen = 32;
2216 p += 4;
2218 else if (startswith (p, "rv64"))
2220 *rps->xlen = 64;
2221 p += 4;
2223 else
2225 /* ISA string shouldn't be NULL or empty here. For linker,
2226 it might be empty when we failed to merge the ISA string
2227 in the riscv_merge_attributes. For assembler, we might
2228 give an empty string by .attribute arch, "" or -march=.
2229 However, We have already issued the correct error message
2230 in another side, so do not issue this error when the ISA
2231 string is empty. */
2232 if (strlen (arch))
2233 rps->error_handler (
2234 _("%s: ISA string must begin with rv32 or rv64"),
2235 arch);
2236 return false;
2239 /* Parse single standard and prefixed extensions. */
2240 if (riscv_parse_extensions (rps, arch, p) == NULL)
2241 return false;
2243 /* Finally add implicit extensions according to the current
2244 extensions. */
2245 riscv_parse_add_implicit_subsets (rps);
2247 /* Check the conflicts. */
2248 return riscv_parse_check_conflicts (rps);
2251 /* Return the number of digits for the input. */
2253 size_t
2254 riscv_estimate_digit (unsigned num)
2256 size_t digit = 0;
2257 if (num == 0)
2258 return 1;
2260 for (digit = 0; num ; num /= 10)
2261 digit++;
2263 return digit;
2266 /* Auxiliary function to estimate string length of subset list. */
2268 static size_t
2269 riscv_estimate_arch_strlen1 (const riscv_subset_t *subset)
2271 if (subset == NULL)
2272 return 6; /* For rv32/rv64/rv128 and string terminator. */
2274 return riscv_estimate_arch_strlen1 (subset->next)
2275 + strlen (subset->name)
2276 + riscv_estimate_digit (subset->major_version)
2277 + 1 /* For version seperator 'p'. */
2278 + riscv_estimate_digit (subset->minor_version)
2279 + 1 /* For underscore. */;
2282 /* Estimate the string length of this subset list. */
2284 static size_t
2285 riscv_estimate_arch_strlen (const riscv_subset_list_t *subset_list)
2287 return riscv_estimate_arch_strlen1 (subset_list->head);
2290 /* Auxiliary function to convert subset info to string. */
2292 static void
2293 riscv_arch_str1 (riscv_subset_t *subset,
2294 char *attr_str, char *buf, size_t bufsz)
2296 const char *underline = "_";
2297 riscv_subset_t *subset_t = subset;
2299 if (subset_t == NULL)
2300 return;
2302 /* No underline between rvXX and i/e. */
2303 if ((strcasecmp (subset_t->name, "i") == 0)
2304 || (strcasecmp (subset_t->name, "e") == 0))
2305 underline = "";
2307 snprintf (buf, bufsz, "%s%s%dp%d",
2308 underline,
2309 subset_t->name,
2310 subset_t->major_version,
2311 subset_t->minor_version);
2313 strncat (attr_str, buf, bufsz);
2315 /* Skip 'i' extension after 'e', or skip extensions which
2316 versions are unknown. */
2317 while (subset_t->next
2318 && ((strcmp (subset_t->name, "e") == 0
2319 && strcmp (subset_t->next->name, "i") == 0)
2320 || subset_t->next->major_version == RISCV_UNKNOWN_VERSION
2321 || subset_t->next->minor_version == RISCV_UNKNOWN_VERSION))
2322 subset_t = subset_t->next;
2324 riscv_arch_str1 (subset_t->next, attr_str, buf, bufsz);
2327 /* Convert subset information into string with explicit versions. */
2329 char *
2330 riscv_arch_str (unsigned xlen, const riscv_subset_list_t *subset)
2332 size_t arch_str_len = riscv_estimate_arch_strlen (subset);
2333 char *attr_str = xmalloc (arch_str_len);
2334 char *buf = xmalloc (arch_str_len);
2336 snprintf (attr_str, arch_str_len, "rv%u", xlen);
2338 riscv_arch_str1 (subset->head, attr_str, buf, arch_str_len);
2339 free (buf);
2341 return attr_str;
2344 /* Copy the subset in the subset list. */
2346 static struct riscv_subset_t *
2347 riscv_copy_subset (riscv_subset_list_t *subset_list,
2348 riscv_subset_t *subset)
2350 if (subset == NULL)
2351 return NULL;
2353 riscv_subset_t *new = xmalloc (sizeof *new);
2354 new->name = xstrdup (subset->name);
2355 new->major_version = subset->major_version;
2356 new->minor_version = subset->minor_version;
2357 new->next = riscv_copy_subset (subset_list, subset->next);
2359 if (subset->next == NULL)
2360 subset_list->tail = new;
2362 return new;
2365 /* Copy the subset list. */
2367 riscv_subset_list_t *
2368 riscv_copy_subset_list (riscv_subset_list_t *subset_list)
2370 riscv_subset_list_t *new = xmalloc (sizeof *new);
2371 new->head = riscv_copy_subset (new, subset_list->head);
2372 new->arch_str = strdup (subset_list->arch_str);
2373 return new;
2376 /* Remove the SUBSET from the subset list. */
2378 static void
2379 riscv_remove_subset (riscv_subset_list_t *subset_list,
2380 const char *subset)
2382 riscv_subset_t *current = subset_list->head;
2383 riscv_subset_t *pre = NULL;
2384 for (; current != NULL; pre = current, current = current->next)
2386 if (strcmp (current->name, subset) == 0)
2388 if (pre == NULL)
2389 subset_list->head = current->next;
2390 else
2391 pre->next = current->next;
2392 if (current->next == NULL)
2393 subset_list->tail = pre;
2394 free ((void *) current->name);
2395 free (current);
2396 break;
2401 /* Auxiliary to add/remove extensions to/from the subset list.
2402 This is called from riscv_update_subset or riscv_parse_add_implicit_subsets.
2404 The EXPLICIT_SUBSET, the corresponding explicit extension. It is NULL means
2405 called from riscv_update_subset./
2407 The IMPLICIT_EXTS, +extension[version] [,...,+extension_n[version_n]]
2408 -extension [,...,-extension_n],
2409 full ISA. */
2411 static bool
2412 riscv_update_subset1 (riscv_parse_subset_t *rps,
2413 riscv_subset_t *explicit_subset,
2414 const char *implicit_exts)
2416 const char *p = implicit_exts;
2417 const char *errmsg_internal = explicit_subset == NULL ? "" : _("internal: ");
2418 const char *errmsg_caller = explicit_subset == NULL
2419 ? ".option arch" : "riscv_implicit_subsets";
2423 int major_version = RISCV_UNKNOWN_VERSION;
2424 int minor_version = RISCV_UNKNOWN_VERSION;
2426 bool removed = false;
2427 switch (*p)
2429 case '+': removed = false; break;
2430 case '-': removed = true; break;
2431 default:
2432 riscv_release_subset_list (rps->subset_list);
2433 return riscv_parse_subset (rps, p);
2435 ++p;
2437 char *subset = xstrdup (p);
2438 char *q = subset;
2439 const char *end_of_version;
2440 /* Extract the whole prefixed extension by ','. */
2441 while (*q != '\0' && *q != ',')
2442 q++;
2444 /* Look forward to the first letter which is not <major>p<minor>. */
2445 bool find_any_version = false;
2446 bool find_minor_version = false;
2447 size_t len = q - subset;
2448 size_t i;
2449 for (i = len; i > 0; i--)
2451 q--;
2452 if (ISDIGIT (*q))
2453 find_any_version = true;
2454 else if (find_any_version
2455 && !find_minor_version
2456 && *q == 'p'
2457 && ISDIGIT (*(q - 1)))
2458 find_minor_version = true;
2459 else
2460 break;
2462 if (len > 0)
2463 q++;
2465 /* Check if the end of extension is 'p' or not. If yes, then
2466 the second letter from the end cannot be number. */
2467 if (len > 1 && *(q - 1) == 'p' && ISDIGIT (*(q - 2)))
2469 *q = '\0';
2470 rps->error_handler
2471 (_("%sinvalid ISA extension ends with <number>p in %s `%s'"),
2472 errmsg_internal, errmsg_caller, implicit_exts);
2473 free (subset);
2474 return false;
2477 end_of_version =
2478 riscv_parsing_subset_version (q, &major_version, &minor_version);
2479 *q = '\0';
2480 if (end_of_version == NULL)
2482 free (subset);
2483 return false;
2486 if (strlen (subset) == 0
2487 || (strlen (subset) == 1
2488 && riscv_ext_order[(*subset - 'a')] == 0)
2489 || (strlen (subset) > 1
2490 && rps->check_unknown_prefixed_ext
2491 && !riscv_recognized_prefixed_ext (subset)))
2493 rps->error_handler
2494 (_("%sunknown ISA extension `%s' in %s `%s'"),
2495 errmsg_internal, subset, errmsg_caller, implicit_exts);
2496 free (subset);
2497 return false;
2500 if (explicit_subset == NULL
2501 && (strcmp (subset, "i") == 0
2502 || strcmp (subset, "e") == 0
2503 || strcmp (subset, "g") == 0))
2505 rps->error_handler
2506 (_("%scannot + or - base extension `%s' in %s `%s'"),
2507 errmsg_internal, subset, errmsg_caller, implicit_exts);
2508 free (subset);
2509 return false;
2512 if (removed)
2513 riscv_remove_subset (rps->subset_list, subset);
2514 else
2516 riscv_subset_t *isubset = NULL;
2517 if (!riscv_lookup_subset (rps->subset_list, subset, &isubset))
2518 riscv_parse_add_subset (rps, subset, major_version, minor_version,
2519 true/* implicit */);
2521 p += end_of_version - subset;
2522 free (subset);
2524 while (*p++ == ',');
2526 bool conflict = false;
2527 if (explicit_subset == NULL)
2529 riscv_parse_add_implicit_subsets (rps);
2530 conflict = riscv_parse_check_conflicts (rps);
2532 return conflict;
2535 /* Add/Remove an extension to/from the subset list. This is used for
2536 the .option rvc or norvc, and .option arch directives. */
2538 bool
2539 riscv_update_subset (riscv_parse_subset_t *rps,
2540 const char *str)
2542 return riscv_update_subset1 (rps, NULL, str);
2545 /* Check if the FEATURE subset is supported or not in the subset list.
2546 Return true if it is supported; Otherwise, return false. */
2548 bool
2549 riscv_subset_supports (riscv_parse_subset_t *rps,
2550 const char *feature)
2552 struct riscv_subset_t *subset;
2553 return riscv_lookup_subset (rps->subset_list, feature, &subset);
2556 /* Each instuction is belonged to an instruction class INSN_CLASS_*.
2557 Call riscv_subset_supports to make sure if the instuction is valid. */
2559 bool
2560 riscv_multi_subset_supports (riscv_parse_subset_t *rps,
2561 enum riscv_insn_class insn_class)
2563 switch (insn_class)
2565 case INSN_CLASS_I:
2566 return riscv_subset_supports (rps, "i");
2567 case INSN_CLASS_ZICBOM:
2568 return riscv_subset_supports (rps, "zicbom");
2569 case INSN_CLASS_ZICBOP:
2570 return riscv_subset_supports (rps, "zicbop");
2571 case INSN_CLASS_ZICBOZ:
2572 return riscv_subset_supports (rps, "zicboz");
2573 case INSN_CLASS_ZICOND:
2574 return riscv_subset_supports (rps, "zicond");
2575 case INSN_CLASS_ZICSR:
2576 return riscv_subset_supports (rps, "zicsr");
2577 case INSN_CLASS_ZIFENCEI:
2578 return riscv_subset_supports (rps, "zifencei");
2579 case INSN_CLASS_ZIHINTNTL:
2580 return riscv_subset_supports (rps, "zihintntl");
2581 case INSN_CLASS_ZIHINTNTL_AND_C:
2582 return (riscv_subset_supports (rps, "zihintntl")
2583 && (riscv_subset_supports (rps, "c")
2584 || riscv_subset_supports (rps, "zca")));
2585 case INSN_CLASS_ZIHINTPAUSE:
2586 return riscv_subset_supports (rps, "zihintpause");
2587 case INSN_CLASS_ZIMOP:
2588 return riscv_subset_supports (rps, "zimop");
2589 case INSN_CLASS_ZICFISS:
2590 return riscv_subset_supports (rps, "zicfiss");
2591 case INSN_CLASS_ZICFISS_AND_ZCMOP:
2592 return riscv_subset_supports (rps, "zicfiss")
2593 && riscv_subset_supports (rps, "zcmop");
2594 case INSN_CLASS_ZICFILP:
2595 return riscv_subset_supports (rps, "zicfilp");
2596 case INSN_CLASS_M:
2597 return riscv_subset_supports (rps, "m");
2598 case INSN_CLASS_ZMMUL:
2599 return riscv_subset_supports (rps, "zmmul");
2600 case INSN_CLASS_ZAAMO:
2601 return riscv_subset_supports (rps, "zaamo");
2602 case INSN_CLASS_ZABHA:
2603 return riscv_subset_supports (rps, "zabha");
2604 case INSN_CLASS_ZACAS:
2605 return riscv_subset_supports (rps, "zacas");
2606 case INSN_CLASS_ZABHA_AND_ZACAS:
2607 return (riscv_subset_supports (rps, "zabha")
2608 && riscv_subset_supports (rps, "zacas"));
2609 case INSN_CLASS_ZALRSC:
2610 return riscv_subset_supports (rps, "zalrsc");
2611 case INSN_CLASS_ZAWRS:
2612 return riscv_subset_supports (rps, "zawrs");
2613 case INSN_CLASS_F:
2614 return riscv_subset_supports (rps, "f");
2615 case INSN_CLASS_D:
2616 return riscv_subset_supports (rps, "d");
2617 case INSN_CLASS_Q:
2618 return riscv_subset_supports (rps, "q");
2619 case INSN_CLASS_C:
2620 return (riscv_subset_supports (rps, "c")
2621 || riscv_subset_supports (rps, "zca"));
2622 case INSN_CLASS_F_AND_C:
2623 return (riscv_subset_supports (rps, "f")
2624 && (riscv_subset_supports (rps, "c")
2625 || riscv_subset_supports (rps, "zcf")));
2626 case INSN_CLASS_D_AND_C:
2627 return (riscv_subset_supports (rps, "d")
2628 && (riscv_subset_supports (rps, "c")
2629 || riscv_subset_supports (rps, "zcd")));
2630 case INSN_CLASS_F_INX:
2631 return (riscv_subset_supports (rps, "f")
2632 || riscv_subset_supports (rps, "zfinx"));
2633 case INSN_CLASS_D_INX:
2634 return (riscv_subset_supports (rps, "d")
2635 || riscv_subset_supports (rps, "zdinx"));
2636 case INSN_CLASS_Q_INX:
2637 return (riscv_subset_supports (rps, "q")
2638 || riscv_subset_supports (rps, "zqinx"));
2639 case INSN_CLASS_ZFH_INX:
2640 return (riscv_subset_supports (rps, "zfh")
2641 || riscv_subset_supports (rps, "zhinx"));
2642 case INSN_CLASS_ZFHMIN:
2643 return riscv_subset_supports (rps, "zfhmin");
2644 case INSN_CLASS_ZFHMIN_INX:
2645 return (riscv_subset_supports (rps, "zfhmin")
2646 || riscv_subset_supports (rps, "zhinxmin"));
2647 case INSN_CLASS_ZFHMIN_AND_D_INX:
2648 return ((riscv_subset_supports (rps, "zfhmin")
2649 && riscv_subset_supports (rps, "d"))
2650 || (riscv_subset_supports (rps, "zhinxmin")
2651 && riscv_subset_supports (rps, "zdinx")));
2652 case INSN_CLASS_ZFHMIN_AND_Q_INX:
2653 return ((riscv_subset_supports (rps, "zfhmin")
2654 && riscv_subset_supports (rps, "q"))
2655 || (riscv_subset_supports (rps, "zhinxmin")
2656 && riscv_subset_supports (rps, "zqinx")));
2657 case INSN_CLASS_ZFBFMIN:
2658 return riscv_subset_supports (rps, "zfbfmin");
2659 case INSN_CLASS_ZFA:
2660 return riscv_subset_supports (rps, "zfa");
2661 case INSN_CLASS_D_AND_ZFA:
2662 return riscv_subset_supports (rps, "d")
2663 && riscv_subset_supports (rps, "zfa");
2664 case INSN_CLASS_Q_AND_ZFA:
2665 return riscv_subset_supports (rps, "q")
2666 && riscv_subset_supports (rps, "zfa");
2667 case INSN_CLASS_ZFH_AND_ZFA:
2668 return riscv_subset_supports (rps, "zfh")
2669 && riscv_subset_supports (rps, "zfa");
2670 case INSN_CLASS_ZFH_OR_ZVFH_AND_ZFA:
2671 return (riscv_subset_supports (rps, "zfh")
2672 || riscv_subset_supports (rps, "zvfh"))
2673 && riscv_subset_supports (rps, "zfa");
2674 case INSN_CLASS_ZBA:
2675 return riscv_subset_supports (rps, "zba");
2676 case INSN_CLASS_ZBB:
2677 return riscv_subset_supports (rps, "zbb");
2678 case INSN_CLASS_ZBC:
2679 return riscv_subset_supports (rps, "zbc");
2680 case INSN_CLASS_ZBS:
2681 return riscv_subset_supports (rps, "zbs");
2682 case INSN_CLASS_ZBKB:
2683 return riscv_subset_supports (rps, "zbkb");
2684 case INSN_CLASS_ZBKC:
2685 return riscv_subset_supports (rps, "zbkc");
2686 case INSN_CLASS_ZBKX:
2687 return riscv_subset_supports (rps, "zbkx");
2688 case INSN_CLASS_ZBB_OR_ZBKB:
2689 return (riscv_subset_supports (rps, "zbb")
2690 || riscv_subset_supports (rps, "zbkb"));
2691 case INSN_CLASS_ZBC_OR_ZBKC:
2692 return (riscv_subset_supports (rps, "zbc")
2693 || riscv_subset_supports (rps, "zbkc"));
2694 case INSN_CLASS_ZKND:
2695 return riscv_subset_supports (rps, "zknd");
2696 case INSN_CLASS_ZKNE:
2697 return riscv_subset_supports (rps, "zkne");
2698 case INSN_CLASS_ZKNH:
2699 return riscv_subset_supports (rps, "zknh");
2700 case INSN_CLASS_ZKND_OR_ZKNE:
2701 return (riscv_subset_supports (rps, "zknd")
2702 || riscv_subset_supports (rps, "zkne"));
2703 case INSN_CLASS_ZKSED:
2704 return riscv_subset_supports (rps, "zksed");
2705 case INSN_CLASS_ZKSH:
2706 return riscv_subset_supports (rps, "zksh");
2707 case INSN_CLASS_V:
2708 return (riscv_subset_supports (rps, "v")
2709 || riscv_subset_supports (rps, "zve64x")
2710 || riscv_subset_supports (rps, "zve32x"));
2711 case INSN_CLASS_ZVEF:
2712 return (riscv_subset_supports (rps, "v")
2713 || riscv_subset_supports (rps, "zve64d")
2714 || riscv_subset_supports (rps, "zve64f")
2715 || riscv_subset_supports (rps, "zve32f"));
2716 case INSN_CLASS_ZVBB:
2717 return riscv_subset_supports (rps, "zvbb");
2718 case INSN_CLASS_ZVBC:
2719 return riscv_subset_supports (rps, "zvbc");
2720 case INSN_CLASS_ZVFBFMIN:
2721 return riscv_subset_supports (rps, "zvfbfmin");
2722 case INSN_CLASS_ZVFBFWMA:
2723 return riscv_subset_supports (rps, "zvfbfwma");
2724 case INSN_CLASS_ZVKB:
2725 return riscv_subset_supports (rps, "zvkb");
2726 case INSN_CLASS_ZVKG:
2727 return riscv_subset_supports (rps, "zvkg");
2728 case INSN_CLASS_ZVKNED:
2729 return riscv_subset_supports (rps, "zvkned");
2730 case INSN_CLASS_ZVKNHA_OR_ZVKNHB:
2731 return (riscv_subset_supports (rps, "zvknha")
2732 || riscv_subset_supports (rps, "zvknhb"));
2733 case INSN_CLASS_ZVKSED:
2734 return riscv_subset_supports (rps, "zvksed");
2735 case INSN_CLASS_ZVKSH:
2736 return riscv_subset_supports (rps, "zvksh");
2737 case INSN_CLASS_ZCB:
2738 return riscv_subset_supports (rps, "zcb");
2739 case INSN_CLASS_ZCB_AND_ZBB:
2740 return (riscv_subset_supports (rps, "zcb")
2741 && riscv_subset_supports (rps, "zbb"));
2742 case INSN_CLASS_ZCB_AND_ZBA:
2743 return (riscv_subset_supports (rps, "zcb")
2744 && riscv_subset_supports (rps, "zba"));
2745 case INSN_CLASS_ZCB_AND_ZMMUL:
2746 return (riscv_subset_supports (rps, "zcb")
2747 && riscv_subset_supports (rps, "zmmul"));
2748 case INSN_CLASS_ZCMOP:
2749 return riscv_subset_supports (rps, "zcmop");
2750 case INSN_CLASS_ZCMP:
2751 return riscv_subset_supports (rps, "zcmp");
2752 case INSN_CLASS_ZCMT:
2753 return riscv_subset_supports (rps, "zcmt");
2754 case INSN_CLASS_SMCTR_OR_SSCTR:
2755 return (riscv_subset_supports (rps, "smctr")
2756 || riscv_subset_supports (rps, "ssctr"));
2757 case INSN_CLASS_SVINVAL:
2758 return riscv_subset_supports (rps, "svinval");
2759 case INSN_CLASS_H:
2760 return riscv_subset_supports (rps, "h");
2761 case INSN_CLASS_XCVALU:
2762 return riscv_subset_supports (rps, "xcvalu");
2763 case INSN_CLASS_XCVBI:
2764 return riscv_subset_supports (rps, "xcvbi");
2765 case INSN_CLASS_XCVBITMANIP:
2766 return riscv_subset_supports (rps, "xcvbitmanip");
2767 case INSN_CLASS_XCVELW:
2768 return riscv_subset_supports (rps, "xcvelw");
2769 case INSN_CLASS_XCVMAC:
2770 return riscv_subset_supports (rps, "xcvmac");
2771 case INSN_CLASS_XCVMEM:
2772 return riscv_subset_supports (rps, "xcvmem");
2773 case INSN_CLASS_XCVSIMD:
2774 return riscv_subset_supports (rps, "xcvsimd");
2775 case INSN_CLASS_XTHEADBA:
2776 return riscv_subset_supports (rps, "xtheadba");
2777 case INSN_CLASS_XTHEADBB:
2778 return riscv_subset_supports (rps, "xtheadbb");
2779 case INSN_CLASS_XTHEADBS:
2780 return riscv_subset_supports (rps, "xtheadbs");
2781 case INSN_CLASS_XTHEADCMO:
2782 return riscv_subset_supports (rps, "xtheadcmo");
2783 case INSN_CLASS_XTHEADCONDMOV:
2784 return riscv_subset_supports (rps, "xtheadcondmov");
2785 case INSN_CLASS_XTHEADFMEMIDX:
2786 return riscv_subset_supports (rps, "xtheadfmemidx");
2787 case INSN_CLASS_XTHEADFMV:
2788 return riscv_subset_supports (rps, "xtheadfmv");
2789 case INSN_CLASS_XTHEADINT:
2790 return riscv_subset_supports (rps, "xtheadint");
2791 case INSN_CLASS_XTHEADMAC:
2792 return riscv_subset_supports (rps, "xtheadmac");
2793 case INSN_CLASS_XTHEADMEMIDX:
2794 return riscv_subset_supports (rps, "xtheadmemidx");
2795 case INSN_CLASS_XTHEADMEMPAIR:
2796 return riscv_subset_supports (rps, "xtheadmempair");
2797 case INSN_CLASS_XTHEADSYNC:
2798 return riscv_subset_supports (rps, "xtheadsync");
2799 case INSN_CLASS_XTHEADVECTOR:
2800 return riscv_subset_supports (rps, "xtheadvector");
2801 case INSN_CLASS_XTHEADZVAMO:
2802 return riscv_subset_supports (rps, "xtheadzvamo");
2803 case INSN_CLASS_XVENTANACONDOPS:
2804 return riscv_subset_supports (rps, "xventanacondops");
2805 case INSN_CLASS_XSFVCP:
2806 return riscv_subset_supports (rps, "xsfvcp");
2807 case INSN_CLASS_XSFCEASE:
2808 return riscv_subset_supports (rps, "xsfcease");
2809 case INSN_CLASS_XSFVQMACCQOQ:
2810 return riscv_subset_supports (rps, "xsfvqmaccqoq");
2811 case INSN_CLASS_XSFVQMACCDOD:
2812 return riscv_subset_supports (rps, "xsfvqmaccdod");
2813 case INSN_CLASS_XSFVFNRCLIPXFQF:
2814 return riscv_subset_supports (rps, "xsfvfnrclipxfqf");
2815 default:
2816 rps->error_handler
2817 (_("internal: unreachable INSN_CLASS_*"));
2818 return false;
2822 /* Each instuction is belonged to an instruction class INSN_CLASS_*.
2823 Call riscv_subset_supports_ext to determine the missing extension. */
2825 const char *
2826 riscv_multi_subset_supports_ext (riscv_parse_subset_t *rps,
2827 enum riscv_insn_class insn_class)
2829 switch (insn_class)
2831 case INSN_CLASS_I:
2832 return "i";
2833 case INSN_CLASS_ZICBOM:
2834 return "zicbom";
2835 case INSN_CLASS_ZICBOP:
2836 return "zicbop";
2837 case INSN_CLASS_ZICBOZ:
2838 return "zicboz";
2839 case INSN_CLASS_ZICOND:
2840 return "zicond";
2841 case INSN_CLASS_ZICSR:
2842 return "zicsr";
2843 case INSN_CLASS_ZIFENCEI:
2844 return "zifencei";
2845 case INSN_CLASS_ZICFISS:
2846 return "zicfiss";
2847 case INSN_CLASS_ZICFISS_AND_ZCMOP:
2848 if (!riscv_subset_supports (rps, "zicfiss"))
2850 if (!riscv_subset_supports (rps, "zcmop"))
2851 return _("zicfiss' and `zcmop");
2852 else
2853 return "zicfiss";
2855 return "zcmop";
2856 case INSN_CLASS_ZICFILP:
2857 return "zicfilp";
2858 case INSN_CLASS_ZIHINTNTL:
2859 return "zihintntl";
2860 case INSN_CLASS_ZIHINTNTL_AND_C:
2861 if (!riscv_subset_supports (rps, "zihintntl"))
2863 if (!riscv_subset_supports (rps, "c")
2864 && !riscv_subset_supports (rps, "zca"))
2865 return _("zihintntl' and `c', or `zihintntl' and `zca");
2866 else
2867 return "zihintntl";
2869 else
2870 return _("c' or `zca");
2871 case INSN_CLASS_ZIHINTPAUSE:
2872 return "zihintpause";
2873 case INSN_CLASS_ZIMOP:
2874 return "zimop";
2875 case INSN_CLASS_M:
2876 return "m";
2877 case INSN_CLASS_ZMMUL:
2878 return _ ("m' or `zmmul");
2879 case INSN_CLASS_ZAAMO:
2880 return "zaamo";
2881 case INSN_CLASS_ZABHA:
2882 return "zabha";
2883 case INSN_CLASS_ZACAS:
2884 return "zacas";
2885 case INSN_CLASS_ZALRSC:
2886 return "zalrsc";
2887 case INSN_CLASS_ZAWRS:
2888 return "zawrs";
2889 case INSN_CLASS_F:
2890 return "f";
2891 case INSN_CLASS_D:
2892 return "d";
2893 case INSN_CLASS_Q:
2894 return "q";
2895 case INSN_CLASS_C:
2896 return _("c' or `zca");
2897 case INSN_CLASS_F_AND_C:
2898 if (!riscv_subset_supports (rps, "f"))
2900 if (!riscv_subset_supports (rps, "c")
2901 && !riscv_subset_supports (rps, "zcf"))
2902 return _("f' and `c', or `f' and `zcf");
2903 else
2904 return "f";
2906 else
2907 return _("c' or `zcf");
2908 case INSN_CLASS_D_AND_C:
2909 if (!riscv_subset_supports (rps, "d"))
2911 if (!riscv_subset_supports (rps, "c")
2912 && !riscv_subset_supports (rps, "zcd"))
2913 return _("d' and `c', or `d' and `zcd");
2914 else
2915 return "d";
2917 else
2918 return _("c' or `zcd");
2919 case INSN_CLASS_F_INX:
2920 return _("f' or `zfinx");
2921 case INSN_CLASS_D_INX:
2922 return _("d' or `zdinx");
2923 case INSN_CLASS_Q_INX:
2924 return _("q' or `zqinx");
2925 case INSN_CLASS_ZFH_INX:
2926 return _("zfh' or `zhinx");
2927 case INSN_CLASS_ZFHMIN:
2928 return "zfhmin";
2929 case INSN_CLASS_ZFHMIN_INX:
2930 return _("zfhmin' or `zhinxmin");
2931 case INSN_CLASS_ZFHMIN_AND_D_INX:
2932 if (riscv_subset_supports (rps, "zfhmin"))
2933 return "d";
2934 else if (riscv_subset_supports (rps, "d"))
2935 return "zfhmin";
2936 else if (riscv_subset_supports (rps, "zhinxmin"))
2937 return "zdinx";
2938 else if (riscv_subset_supports (rps, "zdinx"))
2939 return "zhinxmin";
2940 else
2941 return _("zfhmin' and `d', or `zhinxmin' and `zdinx");
2942 case INSN_CLASS_ZFHMIN_AND_Q_INX:
2943 if (riscv_subset_supports (rps, "zfhmin"))
2944 return "q";
2945 else if (riscv_subset_supports (rps, "q"))
2946 return "zfhmin";
2947 else if (riscv_subset_supports (rps, "zhinxmin"))
2948 return "zqinx";
2949 else if (riscv_subset_supports (rps, "zqinx"))
2950 return "zhinxmin";
2951 else
2952 return _("zfhmin' and `q', or `zhinxmin' and `zqinx");
2953 case INSN_CLASS_ZFBFMIN:
2954 return "zfbfmin";
2955 case INSN_CLASS_ZFA:
2956 return "zfa";
2957 case INSN_CLASS_D_AND_ZFA:
2958 if (!riscv_subset_supports (rps, "d")
2959 && !riscv_subset_supports (rps, "zfa"))
2960 return _("d' and `zfa");
2961 else if (!riscv_subset_supports (rps, "d"))
2962 return "d";
2963 else
2964 return "zfa";
2965 case INSN_CLASS_Q_AND_ZFA:
2966 if (!riscv_subset_supports (rps, "q")
2967 && !riscv_subset_supports (rps, "zfa"))
2968 return _("q' and `zfa");
2969 else if (!riscv_subset_supports (rps, "q"))
2970 return "q";
2971 else
2972 return "zfa";
2973 case INSN_CLASS_ZFH_AND_ZFA:
2974 if (!riscv_subset_supports (rps, "zfh")
2975 && !riscv_subset_supports (rps, "zfa"))
2976 return _("zfh' and `zfa");
2977 else if (!riscv_subset_supports (rps, "zfh"))
2978 return "zfh";
2979 else
2980 return "zfa";
2981 case INSN_CLASS_ZFH_OR_ZVFH_AND_ZFA:
2982 if (!riscv_subset_supports (rps, "zfa"))
2984 if (!riscv_subset_supports (rps, "zfh")
2985 && !riscv_subset_supports (rps, "zvfh"))
2986 return _("zfh' and `zfa', or `zvfh' and `zfa");
2987 else
2988 return "zfa";
2990 else
2991 return _("zfh' or `zvfh");
2992 case INSN_CLASS_ZBA:
2993 return "zba";
2994 case INSN_CLASS_ZBB:
2995 return "zbb";
2996 case INSN_CLASS_ZBC:
2997 return "zbc";
2998 case INSN_CLASS_ZBS:
2999 return "zbs";
3000 case INSN_CLASS_ZBKB:
3001 return "zbkb";
3002 case INSN_CLASS_ZBKC:
3003 return "zbkc";
3004 case INSN_CLASS_ZBKX:
3005 return "zbkx";
3006 case INSN_CLASS_ZBB_OR_ZBKB:
3007 return _("zbb' or `zbkb");
3008 case INSN_CLASS_ZBC_OR_ZBKC:
3009 return _("zbc' or `zbkc");
3010 case INSN_CLASS_ZKND:
3011 return "zknd";
3012 case INSN_CLASS_ZKNE:
3013 return "zkne";
3014 case INSN_CLASS_ZKNH:
3015 return "zknh";
3016 case INSN_CLASS_ZKND_OR_ZKNE:
3017 return _("zknd' or `zkne");
3018 case INSN_CLASS_ZKSED:
3019 return "zksed";
3020 case INSN_CLASS_ZKSH:
3021 return "zksh";
3022 case INSN_CLASS_V:
3023 return _("v' or `zve64x' or `zve32x");
3024 case INSN_CLASS_ZVEF:
3025 return _("v' or `zve64d' or `zve64f' or `zve32f");
3026 case INSN_CLASS_ZVBB:
3027 return _("zvbb");
3028 case INSN_CLASS_ZVBC:
3029 return _("zvbc");
3030 case INSN_CLASS_ZVFBFMIN:
3031 return "zvfbfmin";
3032 case INSN_CLASS_ZVFBFWMA:
3033 return "zvfbfwma";
3034 case INSN_CLASS_ZVKB:
3035 return _("zvkb");
3036 case INSN_CLASS_ZVKG:
3037 return _("zvkg");
3038 case INSN_CLASS_ZVKNED:
3039 return _("zvkned");
3040 case INSN_CLASS_ZVKNHA_OR_ZVKNHB:
3041 return _("zvknha' or `zvknhb");
3042 case INSN_CLASS_ZVKSED:
3043 return _("zvksed");
3044 case INSN_CLASS_ZVKSH:
3045 return _("zvksh");
3046 case INSN_CLASS_ZCB:
3047 return "zcb";
3048 case INSN_CLASS_ZCB_AND_ZBA:
3049 return _("zcb' and `zba");
3050 case INSN_CLASS_ZCB_AND_ZBB:
3051 return _("zcb' and `zbb");
3052 case INSN_CLASS_ZCB_AND_ZMMUL:
3053 return _("zcb' and `zmmul', or `zcb' and `m");
3054 case INSN_CLASS_ZCMOP:
3055 return "zcmop";
3056 case INSN_CLASS_ZCMP:
3057 return "zcmp";
3058 case INSN_CLASS_ZCMT:
3059 return "zcmt";
3060 case INSN_CLASS_SMCTR_OR_SSCTR:
3061 return _("smctr' or `ssctr");
3062 case INSN_CLASS_SVINVAL:
3063 return "svinval";
3064 case INSN_CLASS_H:
3065 return _("h");
3066 case INSN_CLASS_XCVALU:
3067 return "xcvalu";
3068 case INSN_CLASS_XCVBI:
3069 return "xcvbi";
3070 case INSN_CLASS_XCVBITMANIP:
3071 return "xcvbitmanip";
3072 case INSN_CLASS_XCVELW:
3073 return "xcvelw";
3074 case INSN_CLASS_XCVMAC:
3075 return "xcvmac";
3076 case INSN_CLASS_XCVMEM:
3077 return "xcvmem";
3078 case INSN_CLASS_XCVSIMD:
3079 return "xcvsimd";
3080 case INSN_CLASS_XTHEADBA:
3081 return "xtheadba";
3082 case INSN_CLASS_XTHEADBB:
3083 return "xtheadbb";
3084 case INSN_CLASS_XTHEADBS:
3085 return "xtheadbs";
3086 case INSN_CLASS_XTHEADCMO:
3087 return "xtheadcmo";
3088 case INSN_CLASS_XTHEADCONDMOV:
3089 return "xtheadcondmov";
3090 case INSN_CLASS_XTHEADFMEMIDX:
3091 return "xtheadfmemidx";
3092 case INSN_CLASS_XTHEADFMV:
3093 return "xtheadfmv";
3094 case INSN_CLASS_XTHEADINT:
3095 return "xtheadint";
3096 case INSN_CLASS_XTHEADMAC:
3097 return "xtheadmac";
3098 case INSN_CLASS_XTHEADMEMIDX:
3099 return "xtheadmemidx";
3100 case INSN_CLASS_XTHEADMEMPAIR:
3101 return "xtheadmempair";
3102 case INSN_CLASS_XTHEADSYNC:
3103 return "xtheadsync";
3104 case INSN_CLASS_XTHEADVECTOR:
3105 return "xtheadvector";
3106 case INSN_CLASS_XTHEADZVAMO:
3107 return "xtheadzvamo";
3108 case INSN_CLASS_XSFCEASE:
3109 return "xsfcease";
3110 default:
3111 rps->error_handler
3112 (_("internal: unreachable INSN_CLASS_*"));
3113 return NULL;
3117 /* Print supported extensions with versions if -march=help. */
3119 void
3120 riscv_print_extensions (void)
3122 /* Record the previous printed extension.
3123 Print the current one if they are not the same. */
3124 const struct riscv_supported_ext *cur = NULL, *prev = NULL;
3125 int i, j;
3127 printf ("All available -march extensions for RISC-V:");
3129 for (i = 0; riscv_all_supported_ext[i] != NULL; i++)
3131 const struct riscv_supported_ext *exts = riscv_all_supported_ext[i];
3132 prev = NULL;
3133 for (j = 0; exts[j].name != NULL; j++)
3135 cur = &exts[j];
3136 /* Unclear version information, skip. */
3137 if (cur->isa_spec_class == ISA_SPEC_CLASS_NONE
3138 || cur->major_version == RISCV_UNKNOWN_VERSION
3139 || cur->minor_version == RISCV_UNKNOWN_VERSION)
3140 continue;
3142 /* Same extension. */
3143 if (prev && strcmp (prev->name, cur->name) == 0)
3145 /* Same version, skip. */
3146 if (prev->major_version == cur->major_version
3147 && prev->minor_version == cur->minor_version)
3148 continue;
3149 /* Different version, print version with comma. */
3150 else
3151 printf (", %d.%d", cur->major_version, cur->minor_version);
3153 /* Different extension, print extension and version with newline. */
3154 else
3155 printf ("\n\t%-40s%d.%d", cur->name, cur->major_version,
3156 cur->minor_version);
3157 prev = &exts[j];
3160 printf ("\n");