Automatic date update in version.in
[binutils-gdb.git] / bfd / elfxx-riscv.c
blob0bcf2fdcfa34be09e6eec7580f7548c951946098
1 /* RISC-V-specific support for ELF.
2 Copyright (C) 2011-2022 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 **);
42 /* The relocation table used for SHT_RELA sections. */
44 static reloc_howto_type howto_table[] =
46 /* No relocation. */
47 HOWTO (R_RISCV_NONE, /* type */
48 0, /* rightshift */
49 0, /* size */
50 0, /* bitsize */
51 false, /* pc_relative */
52 0, /* bitpos */
53 complain_overflow_dont, /* complain_on_overflow */
54 bfd_elf_generic_reloc, /* special_function */
55 "R_RISCV_NONE", /* name */
56 false, /* partial_inplace */
57 0, /* src_mask */
58 0, /* dst_mask */
59 false), /* pcrel_offset */
61 /* 32 bit relocation. */
62 HOWTO (R_RISCV_32, /* type */
63 0, /* rightshift */
64 4, /* size */
65 32, /* bitsize */
66 false, /* pc_relative */
67 0, /* bitpos */
68 complain_overflow_dont, /* complain_on_overflow */
69 bfd_elf_generic_reloc, /* special_function */
70 "R_RISCV_32", /* name */
71 false, /* partial_inplace */
72 0, /* src_mask */
73 0xffffffff, /* dst_mask */
74 false), /* pcrel_offset */
76 /* 64 bit relocation. */
77 HOWTO (R_RISCV_64, /* type */
78 0, /* rightshift */
79 8, /* size */
80 64, /* bitsize */
81 false, /* pc_relative */
82 0, /* bitpos */
83 complain_overflow_dont, /* complain_on_overflow */
84 bfd_elf_generic_reloc, /* special_function */
85 "R_RISCV_64", /* name */
86 false, /* partial_inplace */
87 0, /* src_mask */
88 MINUS_ONE, /* dst_mask */
89 false), /* pcrel_offset */
91 /* Relocation against a local symbol in a shared object. */
92 HOWTO (R_RISCV_RELATIVE, /* type */
93 0, /* rightshift */
94 4, /* size */
95 32, /* bitsize */
96 false, /* pc_relative */
97 0, /* bitpos */
98 complain_overflow_dont, /* complain_on_overflow */
99 bfd_elf_generic_reloc, /* special_function */
100 "R_RISCV_RELATIVE", /* name */
101 false, /* partial_inplace */
102 0, /* src_mask */
103 0xffffffff, /* dst_mask */
104 false), /* pcrel_offset */
106 HOWTO (R_RISCV_COPY, /* type */
107 0, /* rightshift */
108 0, /* this one is variable size */
109 0, /* bitsize */
110 false, /* pc_relative */
111 0, /* bitpos */
112 complain_overflow_bitfield, /* complain_on_overflow */
113 bfd_elf_generic_reloc, /* special_function */
114 "R_RISCV_COPY", /* name */
115 false, /* partial_inplace */
116 0, /* src_mask */
117 0, /* dst_mask */
118 false), /* pcrel_offset */
120 HOWTO (R_RISCV_JUMP_SLOT, /* type */
121 0, /* rightshift */
122 8, /* size */
123 64, /* bitsize */
124 false, /* pc_relative */
125 0, /* bitpos */
126 complain_overflow_bitfield, /* complain_on_overflow */
127 bfd_elf_generic_reloc, /* special_function */
128 "R_RISCV_JUMP_SLOT", /* name */
129 false, /* partial_inplace */
130 0, /* src_mask */
131 0, /* dst_mask */
132 false), /* pcrel_offset */
134 /* Dynamic TLS relocations. */
135 HOWTO (R_RISCV_TLS_DTPMOD32, /* type */
136 0, /* rightshift */
137 4, /* size */
138 32, /* bitsize */
139 false, /* pc_relative */
140 0, /* bitpos */
141 complain_overflow_dont, /* complain_on_overflow */
142 bfd_elf_generic_reloc, /* special_function */
143 "R_RISCV_TLS_DTPMOD32", /* name */
144 false, /* partial_inplace */
145 0, /* src_mask */
146 0xffffffff, /* dst_mask */
147 false), /* pcrel_offset */
149 HOWTO (R_RISCV_TLS_DTPMOD64, /* type */
150 0, /* rightshift */
151 8, /* size */
152 64, /* bitsize */
153 false, /* pc_relative */
154 0, /* bitpos */
155 complain_overflow_dont, /* complain_on_overflow */
156 bfd_elf_generic_reloc, /* special_function */
157 "R_RISCV_TLS_DTPMOD64", /* name */
158 false, /* partial_inplace */
159 0, /* src_mask */
160 MINUS_ONE, /* dst_mask */
161 false), /* pcrel_offset */
163 HOWTO (R_RISCV_TLS_DTPREL32, /* type */
164 0, /* rightshift */
165 4, /* size */
166 32, /* bitsize */
167 false, /* pc_relative */
168 0, /* bitpos */
169 complain_overflow_dont, /* complain_on_overflow */
170 bfd_elf_generic_reloc, /* special_function */
171 "R_RISCV_TLS_DTPREL32", /* name */
172 true, /* partial_inplace */
173 0, /* src_mask */
174 0xffffffff, /* dst_mask */
175 false), /* pcrel_offset */
177 HOWTO (R_RISCV_TLS_DTPREL64, /* type */
178 0, /* rightshift */
179 8, /* size */
180 64, /* bitsize */
181 false, /* pc_relative */
182 0, /* bitpos */
183 complain_overflow_dont, /* complain_on_overflow */
184 bfd_elf_generic_reloc, /* special_function */
185 "R_RISCV_TLS_DTPREL64", /* name */
186 true, /* partial_inplace */
187 0, /* src_mask */
188 MINUS_ONE, /* dst_mask */
189 false), /* pcrel_offset */
191 HOWTO (R_RISCV_TLS_TPREL32, /* type */
192 0, /* rightshift */
193 4, /* size */
194 32, /* bitsize */
195 false, /* pc_relative */
196 0, /* bitpos */
197 complain_overflow_dont, /* complain_on_overflow */
198 bfd_elf_generic_reloc, /* special_function */
199 "R_RISCV_TLS_TPREL32", /* name */
200 false, /* partial_inplace */
201 0, /* src_mask */
202 0xffffffff, /* dst_mask */
203 false), /* pcrel_offset */
205 HOWTO (R_RISCV_TLS_TPREL64, /* type */
206 0, /* rightshift */
207 8, /* size */
208 64, /* bitsize */
209 false, /* pc_relative */
210 0, /* bitpos */
211 complain_overflow_dont, /* complain_on_overflow */
212 bfd_elf_generic_reloc, /* special_function */
213 "R_RISCV_TLS_TPREL64", /* name */
214 false, /* partial_inplace */
215 0, /* src_mask */
216 MINUS_ONE, /* dst_mask */
217 false), /* pcrel_offset */
219 /* Reserved for future relocs that the dynamic linker must understand. */
220 EMPTY_HOWTO (12),
221 EMPTY_HOWTO (13),
222 EMPTY_HOWTO (14),
223 EMPTY_HOWTO (15),
225 /* 12-bit PC-relative branch offset. */
226 HOWTO (R_RISCV_BRANCH, /* type */
227 0, /* rightshift */
228 4, /* size */
229 32, /* bitsize */
230 true, /* pc_relative */
231 0, /* bitpos */
232 complain_overflow_signed, /* complain_on_overflow */
233 bfd_elf_generic_reloc, /* special_function */
234 "R_RISCV_BRANCH", /* name */
235 false, /* partial_inplace */
236 0, /* src_mask */
237 ENCODE_BTYPE_IMM (-1U), /* dst_mask */
238 true), /* pcrel_offset */
240 /* 20-bit PC-relative jump offset. */
241 HOWTO (R_RISCV_JAL, /* type */
242 0, /* rightshift */
243 4, /* size */
244 32, /* bitsize */
245 true, /* pc_relative */
246 0, /* bitpos */
247 complain_overflow_dont, /* complain_on_overflow */
248 bfd_elf_generic_reloc, /* special_function */
249 "R_RISCV_JAL", /* name */
250 false, /* partial_inplace */
251 0, /* src_mask */
252 ENCODE_JTYPE_IMM (-1U), /* dst_mask */
253 true), /* pcrel_offset */
255 /* 32-bit PC-relative function call (AUIPC/JALR). */
256 HOWTO (R_RISCV_CALL, /* type */
257 0, /* rightshift */
258 8, /* size */
259 64, /* bitsize */
260 true, /* pc_relative */
261 0, /* bitpos */
262 complain_overflow_dont, /* complain_on_overflow */
263 bfd_elf_generic_reloc, /* special_function */
264 "R_RISCV_CALL", /* name */
265 false, /* partial_inplace */
266 0, /* src_mask */
267 ENCODE_UTYPE_IMM (-1U) | ((bfd_vma) ENCODE_ITYPE_IMM (-1U) << 32),
268 /* dst_mask */
269 true), /* pcrel_offset */
271 /* Like R_RISCV_CALL, but not locally binding. */
272 HOWTO (R_RISCV_CALL_PLT, /* type */
273 0, /* rightshift */
274 8, /* size */
275 64, /* bitsize */
276 true, /* pc_relative */
277 0, /* bitpos */
278 complain_overflow_dont, /* complain_on_overflow */
279 bfd_elf_generic_reloc, /* special_function */
280 "R_RISCV_CALL_PLT", /* name */
281 false, /* partial_inplace */
282 0, /* src_mask */
283 ENCODE_UTYPE_IMM (-1U) | ((bfd_vma) ENCODE_ITYPE_IMM (-1U) << 32),
284 /* dst_mask */
285 true), /* pcrel_offset */
287 /* High 20 bits of 32-bit PC-relative GOT access. */
288 HOWTO (R_RISCV_GOT_HI20, /* type */
289 0, /* rightshift */
290 4, /* size */
291 32, /* bitsize */
292 true, /* pc_relative */
293 0, /* bitpos */
294 complain_overflow_dont, /* complain_on_overflow */
295 bfd_elf_generic_reloc, /* special_function */
296 "R_RISCV_GOT_HI20", /* name */
297 false, /* partial_inplace */
298 0, /* src_mask */
299 ENCODE_UTYPE_IMM (-1U), /* dst_mask */
300 false), /* pcrel_offset */
302 /* High 20 bits of 32-bit PC-relative TLS IE GOT access. */
303 HOWTO (R_RISCV_TLS_GOT_HI20, /* type */
304 0, /* rightshift */
305 4, /* size */
306 32, /* bitsize */
307 true, /* pc_relative */
308 0, /* bitpos */
309 complain_overflow_dont, /* complain_on_overflow */
310 bfd_elf_generic_reloc, /* special_function */
311 "R_RISCV_TLS_GOT_HI20", /* name */
312 false, /* partial_inplace */
313 0, /* src_mask */
314 ENCODE_UTYPE_IMM (-1U), /* dst_mask */
315 false), /* pcrel_offset */
317 /* High 20 bits of 32-bit PC-relative TLS GD GOT reference. */
318 HOWTO (R_RISCV_TLS_GD_HI20, /* type */
319 0, /* rightshift */
320 4, /* size */
321 32, /* bitsize */
322 true, /* pc_relative */
323 0, /* bitpos */
324 complain_overflow_dont, /* complain_on_overflow */
325 bfd_elf_generic_reloc, /* special_function */
326 "R_RISCV_TLS_GD_HI20", /* name */
327 false, /* partial_inplace */
328 0, /* src_mask */
329 ENCODE_UTYPE_IMM (-1U), /* dst_mask */
330 false), /* pcrel_offset */
332 /* High 20 bits of 32-bit PC-relative reference. */
333 HOWTO (R_RISCV_PCREL_HI20, /* type */
334 0, /* rightshift */
335 4, /* size */
336 32, /* bitsize */
337 true, /* pc_relative */
338 0, /* bitpos */
339 complain_overflow_dont, /* complain_on_overflow */
340 bfd_elf_generic_reloc, /* special_function */
341 "R_RISCV_PCREL_HI20", /* name */
342 false, /* partial_inplace */
343 0, /* src_mask */
344 ENCODE_UTYPE_IMM (-1U), /* dst_mask */
345 true), /* pcrel_offset */
347 /* Low 12 bits of a 32-bit PC-relative load or add. */
348 HOWTO (R_RISCV_PCREL_LO12_I, /* type */
349 0, /* rightshift */
350 4, /* size */
351 32, /* bitsize */
352 false, /* pc_relative */
353 0, /* bitpos */
354 complain_overflow_dont, /* complain_on_overflow */
355 bfd_elf_generic_reloc, /* special_function */
356 "R_RISCV_PCREL_LO12_I", /* name */
357 false, /* partial_inplace */
358 0, /* src_mask */
359 ENCODE_ITYPE_IMM (-1U), /* dst_mask */
360 false), /* pcrel_offset */
362 /* Low 12 bits of a 32-bit PC-relative store. */
363 HOWTO (R_RISCV_PCREL_LO12_S, /* type */
364 0, /* rightshift */
365 4, /* size */
366 32, /* bitsize */
367 false, /* pc_relative */
368 0, /* bitpos */
369 complain_overflow_dont, /* complain_on_overflow */
370 bfd_elf_generic_reloc, /* special_function */
371 "R_RISCV_PCREL_LO12_S", /* name */
372 false, /* partial_inplace */
373 0, /* src_mask */
374 ENCODE_STYPE_IMM (-1U), /* dst_mask */
375 false), /* pcrel_offset */
377 /* High 20 bits of 32-bit absolute address. */
378 HOWTO (R_RISCV_HI20, /* type */
379 0, /* rightshift */
380 4, /* size */
381 32, /* bitsize */
382 false, /* pc_relative */
383 0, /* bitpos */
384 complain_overflow_dont, /* complain_on_overflow */
385 bfd_elf_generic_reloc, /* special_function */
386 "R_RISCV_HI20", /* name */
387 false, /* partial_inplace */
388 0, /* src_mask */
389 ENCODE_UTYPE_IMM (-1U), /* dst_mask */
390 false), /* pcrel_offset */
392 /* High 12 bits of 32-bit load or add. */
393 HOWTO (R_RISCV_LO12_I, /* type */
394 0, /* rightshift */
395 4, /* size */
396 32, /* bitsize */
397 false, /* pc_relative */
398 0, /* bitpos */
399 complain_overflow_dont, /* complain_on_overflow */
400 bfd_elf_generic_reloc, /* special_function */
401 "R_RISCV_LO12_I", /* name */
402 false, /* partial_inplace */
403 0, /* src_mask */
404 ENCODE_ITYPE_IMM (-1U), /* dst_mask */
405 false), /* pcrel_offset */
407 /* High 12 bits of 32-bit store. */
408 HOWTO (R_RISCV_LO12_S, /* type */
409 0, /* rightshift */
410 4, /* size */
411 32, /* bitsize */
412 false, /* pc_relative */
413 0, /* bitpos */
414 complain_overflow_dont, /* complain_on_overflow */
415 bfd_elf_generic_reloc, /* special_function */
416 "R_RISCV_LO12_S", /* name */
417 false, /* partial_inplace */
418 0, /* src_mask */
419 ENCODE_STYPE_IMM (-1U), /* dst_mask */
420 false), /* pcrel_offset */
422 /* High 20 bits of TLS LE thread pointer offset. */
423 HOWTO (R_RISCV_TPREL_HI20, /* type */
424 0, /* rightshift */
425 4, /* size */
426 32, /* bitsize */
427 false, /* pc_relative */
428 0, /* bitpos */
429 complain_overflow_signed, /* complain_on_overflow */
430 bfd_elf_generic_reloc, /* special_function */
431 "R_RISCV_TPREL_HI20", /* name */
432 true, /* partial_inplace */
433 0, /* src_mask */
434 ENCODE_UTYPE_IMM (-1U), /* dst_mask */
435 false), /* pcrel_offset */
437 /* Low 12 bits of TLS LE thread pointer offset for loads and adds. */
438 HOWTO (R_RISCV_TPREL_LO12_I, /* type */
439 0, /* rightshift */
440 4, /* size */
441 32, /* bitsize */
442 false, /* pc_relative */
443 0, /* bitpos */
444 complain_overflow_signed, /* complain_on_overflow */
445 bfd_elf_generic_reloc, /* special_function */
446 "R_RISCV_TPREL_LO12_I", /* name */
447 false, /* partial_inplace */
448 0, /* src_mask */
449 ENCODE_ITYPE_IMM (-1U), /* dst_mask */
450 false), /* pcrel_offset */
452 /* Low 12 bits of TLS LE thread pointer offset for stores. */
453 HOWTO (R_RISCV_TPREL_LO12_S, /* type */
454 0, /* rightshift */
455 4, /* size */
456 32, /* bitsize */
457 false, /* pc_relative */
458 0, /* bitpos */
459 complain_overflow_signed, /* complain_on_overflow */
460 bfd_elf_generic_reloc, /* special_function */
461 "R_RISCV_TPREL_LO12_S", /* name */
462 false, /* partial_inplace */
463 0, /* src_mask */
464 ENCODE_STYPE_IMM (-1U), /* dst_mask */
465 false), /* pcrel_offset */
467 /* TLS LE thread pointer usage. May be relaxed. */
468 HOWTO (R_RISCV_TPREL_ADD, /* type */
469 0, /* rightshift */
470 0, /* size */
471 0, /* bitsize */
472 false, /* pc_relative */
473 0, /* bitpos */
474 complain_overflow_dont, /* complain_on_overflow */
475 bfd_elf_generic_reloc, /* special_function */
476 "R_RISCV_TPREL_ADD", /* name */
477 false, /* partial_inplace */
478 0, /* src_mask */
479 0, /* dst_mask */
480 false), /* pcrel_offset */
482 /* 8-bit in-place addition, for local label subtraction. */
483 HOWTO (R_RISCV_ADD8, /* type */
484 0, /* rightshift */
485 1, /* size */
486 8, /* bitsize */
487 false, /* pc_relative */
488 0, /* bitpos */
489 complain_overflow_dont, /* complain_on_overflow */
490 riscv_elf_add_sub_reloc, /* special_function */
491 "R_RISCV_ADD8", /* name */
492 false, /* partial_inplace */
493 0, /* src_mask */
494 0xff, /* dst_mask */
495 false), /* pcrel_offset */
497 /* 16-bit in-place addition, for local label subtraction. */
498 HOWTO (R_RISCV_ADD16, /* type */
499 0, /* rightshift */
500 2, /* size */
501 16, /* bitsize */
502 false, /* pc_relative */
503 0, /* bitpos */
504 complain_overflow_dont, /* complain_on_overflow */
505 riscv_elf_add_sub_reloc, /* special_function */
506 "R_RISCV_ADD16", /* name */
507 false, /* partial_inplace */
508 0, /* src_mask */
509 0xffff, /* dst_mask */
510 false), /* pcrel_offset */
512 /* 32-bit in-place addition, for local label subtraction. */
513 HOWTO (R_RISCV_ADD32, /* type */
514 0, /* rightshift */
515 4, /* size */
516 32, /* bitsize */
517 false, /* pc_relative */
518 0, /* bitpos */
519 complain_overflow_dont, /* complain_on_overflow */
520 riscv_elf_add_sub_reloc, /* special_function */
521 "R_RISCV_ADD32", /* name */
522 false, /* partial_inplace */
523 0, /* src_mask */
524 0xffffffff, /* dst_mask */
525 false), /* pcrel_offset */
527 /* 64-bit in-place addition, for local label subtraction. */
528 HOWTO (R_RISCV_ADD64, /* type */
529 0, /* rightshift */
530 8, /* size */
531 64, /* bitsize */
532 false, /* pc_relative */
533 0, /* bitpos */
534 complain_overflow_dont, /* complain_on_overflow */
535 riscv_elf_add_sub_reloc, /* special_function */
536 "R_RISCV_ADD64", /* name */
537 false, /* partial_inplace */
538 0, /* src_mask */
539 MINUS_ONE, /* dst_mask */
540 false), /* pcrel_offset */
542 /* 8-bit in-place addition, for local label subtraction. */
543 HOWTO (R_RISCV_SUB8, /* type */
544 0, /* rightshift */
545 1, /* size */
546 8, /* bitsize */
547 false, /* pc_relative */
548 0, /* bitpos */
549 complain_overflow_dont, /* complain_on_overflow */
550 riscv_elf_add_sub_reloc, /* special_function */
551 "R_RISCV_SUB8", /* name */
552 false, /* partial_inplace */
553 0, /* src_mask */
554 0xff, /* dst_mask */
555 false), /* pcrel_offset */
557 /* 16-bit in-place addition, for local label subtraction. */
558 HOWTO (R_RISCV_SUB16, /* type */
559 0, /* rightshift */
560 2, /* size */
561 16, /* bitsize */
562 false, /* pc_relative */
563 0, /* bitpos */
564 complain_overflow_dont, /* complain_on_overflow */
565 riscv_elf_add_sub_reloc, /* special_function */
566 "R_RISCV_SUB16", /* name */
567 false, /* partial_inplace */
568 0, /* src_mask */
569 0xffff, /* dst_mask */
570 false), /* pcrel_offset */
572 /* 32-bit in-place addition, for local label subtraction. */
573 HOWTO (R_RISCV_SUB32, /* type */
574 0, /* rightshift */
575 4, /* size */
576 32, /* bitsize */
577 false, /* pc_relative */
578 0, /* bitpos */
579 complain_overflow_dont, /* complain_on_overflow */
580 riscv_elf_add_sub_reloc, /* special_function */
581 "R_RISCV_SUB32", /* name */
582 false, /* partial_inplace */
583 0, /* src_mask */
584 0xffffffff, /* dst_mask */
585 false), /* pcrel_offset */
587 /* 64-bit in-place addition, for local label subtraction. */
588 HOWTO (R_RISCV_SUB64, /* type */
589 0, /* rightshift */
590 8, /* size */
591 64, /* bitsize */
592 false, /* pc_relative */
593 0, /* bitpos */
594 complain_overflow_dont, /* complain_on_overflow */
595 riscv_elf_add_sub_reloc, /* special_function */
596 "R_RISCV_SUB64", /* name */
597 false, /* partial_inplace */
598 0, /* src_mask */
599 MINUS_ONE, /* dst_mask */
600 false), /* pcrel_offset */
602 /* 41 and 42 are reserved. */
603 EMPTY_HOWTO (0),
604 EMPTY_HOWTO (0),
606 /* Indicates an alignment statement. The addend field encodes how many
607 bytes of NOPs follow the statement. The desired alignment is the
608 addend rounded up to the next power of two. */
609 HOWTO (R_RISCV_ALIGN, /* type */
610 0, /* rightshift */
611 0, /* size */
612 0, /* bitsize */
613 false, /* pc_relative */
614 0, /* bitpos */
615 complain_overflow_dont, /* complain_on_overflow */
616 bfd_elf_generic_reloc, /* special_function */
617 "R_RISCV_ALIGN", /* name */
618 false, /* partial_inplace */
619 0, /* src_mask */
620 0, /* dst_mask */
621 false), /* pcrel_offset */
623 /* 8-bit PC-relative branch offset. */
624 HOWTO (R_RISCV_RVC_BRANCH, /* type */
625 0, /* rightshift */
626 2, /* size */
627 16, /* bitsize */
628 true, /* pc_relative */
629 0, /* bitpos */
630 complain_overflow_signed, /* complain_on_overflow */
631 bfd_elf_generic_reloc, /* special_function */
632 "R_RISCV_RVC_BRANCH", /* name */
633 false, /* partial_inplace */
634 0, /* src_mask */
635 ENCODE_CBTYPE_IMM (-1U), /* dst_mask */
636 true), /* pcrel_offset */
638 /* 11-bit PC-relative jump offset. */
639 HOWTO (R_RISCV_RVC_JUMP, /* type */
640 0, /* rightshift */
641 2, /* size */
642 16, /* bitsize */
643 true, /* pc_relative */
644 0, /* bitpos */
645 complain_overflow_dont, /* complain_on_overflow */
646 bfd_elf_generic_reloc, /* special_function */
647 "R_RISCV_RVC_JUMP", /* name */
648 false, /* partial_inplace */
649 0, /* src_mask */
650 ENCODE_CJTYPE_IMM (-1U), /* dst_mask */
651 true), /* pcrel_offset */
653 /* High 6 bits of 18-bit absolute address. */
654 HOWTO (R_RISCV_RVC_LUI, /* type */
655 0, /* rightshift */
656 2, /* size */
657 16, /* bitsize */
658 false, /* pc_relative */
659 0, /* bitpos */
660 complain_overflow_dont, /* complain_on_overflow */
661 bfd_elf_generic_reloc, /* special_function */
662 "R_RISCV_RVC_LUI", /* name */
663 false, /* partial_inplace */
664 0, /* src_mask */
665 ENCODE_CITYPE_IMM (-1U), /* dst_mask */
666 false), /* pcrel_offset */
668 /* GP-relative load. */
669 HOWTO (R_RISCV_GPREL_I, /* type */
670 0, /* rightshift */
671 4, /* size */
672 32, /* bitsize */
673 false, /* pc_relative */
674 0, /* bitpos */
675 complain_overflow_dont, /* complain_on_overflow */
676 bfd_elf_generic_reloc, /* special_function */
677 "R_RISCV_GPREL_I", /* name */
678 false, /* partial_inplace */
679 0, /* src_mask */
680 ENCODE_ITYPE_IMM (-1U), /* dst_mask */
681 false), /* pcrel_offset */
683 /* GP-relative store. */
684 HOWTO (R_RISCV_GPREL_S, /* type */
685 0, /* rightshift */
686 4, /* size */
687 32, /* bitsize */
688 false, /* pc_relative */
689 0, /* bitpos */
690 complain_overflow_dont, /* complain_on_overflow */
691 bfd_elf_generic_reloc, /* special_function */
692 "R_RISCV_GPREL_S", /* name */
693 false, /* partial_inplace */
694 0, /* src_mask */
695 ENCODE_STYPE_IMM (-1U), /* dst_mask */
696 false), /* pcrel_offset */
698 /* TP-relative TLS LE load. */
699 HOWTO (R_RISCV_TPREL_I, /* type */
700 0, /* rightshift */
701 4, /* size */
702 32, /* bitsize */
703 false, /* pc_relative */
704 0, /* bitpos */
705 complain_overflow_signed, /* complain_on_overflow */
706 bfd_elf_generic_reloc, /* special_function */
707 "R_RISCV_TPREL_I", /* name */
708 false, /* partial_inplace */
709 0, /* src_mask */
710 ENCODE_ITYPE_IMM (-1U), /* dst_mask */
711 false), /* pcrel_offset */
713 /* TP-relative TLS LE store. */
714 HOWTO (R_RISCV_TPREL_S, /* type */
715 0, /* rightshift */
716 4, /* size */
717 32, /* bitsize */
718 false, /* pc_relative */
719 0, /* bitpos */
720 complain_overflow_signed, /* complain_on_overflow */
721 bfd_elf_generic_reloc, /* special_function */
722 "R_RISCV_TPREL_S", /* name */
723 false, /* partial_inplace */
724 0, /* src_mask */
725 ENCODE_STYPE_IMM (-1U), /* dst_mask */
726 false), /* pcrel_offset */
728 /* The paired relocation may be relaxed. */
729 HOWTO (R_RISCV_RELAX, /* type */
730 0, /* rightshift */
731 0, /* size */
732 0, /* bitsize */
733 false, /* pc_relative */
734 0, /* bitpos */
735 complain_overflow_dont, /* complain_on_overflow */
736 bfd_elf_generic_reloc, /* special_function */
737 "R_RISCV_RELAX", /* name */
738 false, /* partial_inplace */
739 0, /* src_mask */
740 0, /* dst_mask */
741 false), /* pcrel_offset */
743 /* 6-bit in-place addition, for local label subtraction. */
744 HOWTO (R_RISCV_SUB6, /* type */
745 0, /* rightshift */
746 1, /* size */
747 8, /* bitsize */
748 false, /* pc_relative */
749 0, /* bitpos */
750 complain_overflow_dont, /* complain_on_overflow */
751 riscv_elf_add_sub_reloc, /* special_function */
752 "R_RISCV_SUB6", /* name */
753 false, /* partial_inplace */
754 0, /* src_mask */
755 0x3f, /* dst_mask */
756 false), /* pcrel_offset */
758 /* 6-bit in-place setting, for local label subtraction. */
759 HOWTO (R_RISCV_SET6, /* type */
760 0, /* rightshift */
761 1, /* size */
762 8, /* bitsize */
763 false, /* pc_relative */
764 0, /* bitpos */
765 complain_overflow_dont, /* complain_on_overflow */
766 bfd_elf_generic_reloc, /* special_function */
767 "R_RISCV_SET6", /* name */
768 false, /* partial_inplace */
769 0, /* src_mask */
770 0x3f, /* dst_mask */
771 false), /* pcrel_offset */
773 /* 8-bit in-place setting, for local label subtraction. */
774 HOWTO (R_RISCV_SET8, /* type */
775 0, /* rightshift */
776 1, /* size */
777 8, /* bitsize */
778 false, /* pc_relative */
779 0, /* bitpos */
780 complain_overflow_dont, /* complain_on_overflow */
781 bfd_elf_generic_reloc, /* special_function */
782 "R_RISCV_SET8", /* name */
783 false, /* partial_inplace */
784 0, /* src_mask */
785 0xff, /* dst_mask */
786 false), /* pcrel_offset */
788 /* 16-bit in-place setting, for local label subtraction. */
789 HOWTO (R_RISCV_SET16, /* type */
790 0, /* rightshift */
791 2, /* size */
792 16, /* bitsize */
793 false, /* pc_relative */
794 0, /* bitpos */
795 complain_overflow_dont, /* complain_on_overflow */
796 bfd_elf_generic_reloc, /* special_function */
797 "R_RISCV_SET16", /* name */
798 false, /* partial_inplace */
799 0, /* src_mask */
800 0xffff, /* dst_mask */
801 false), /* pcrel_offset */
803 /* 32-bit in-place setting, for local label subtraction. */
804 HOWTO (R_RISCV_SET32, /* type */
805 0, /* rightshift */
806 4, /* size */
807 32, /* bitsize */
808 false, /* pc_relative */
809 0, /* bitpos */
810 complain_overflow_dont, /* complain_on_overflow */
811 bfd_elf_generic_reloc, /* special_function */
812 "R_RISCV_SET32", /* name */
813 false, /* partial_inplace */
814 0, /* src_mask */
815 0xffffffff, /* dst_mask */
816 false), /* pcrel_offset */
818 /* 32-bit PC relative. */
819 HOWTO (R_RISCV_32_PCREL, /* type */
820 0, /* rightshift */
821 4, /* size */
822 32, /* bitsize */
823 true, /* pc_relative */
824 0, /* bitpos */
825 complain_overflow_dont, /* complain_on_overflow */
826 bfd_elf_generic_reloc, /* special_function */
827 "R_RISCV_32_PCREL", /* name */
828 false, /* partial_inplace */
829 0, /* src_mask */
830 0xffffffff, /* dst_mask */
831 false), /* pcrel_offset */
833 /* Relocation against a local ifunc symbol in a shared object. */
834 HOWTO (R_RISCV_IRELATIVE, /* type */
835 0, /* rightshift */
836 4, /* size */
837 32, /* bitsize */
838 false, /* pc_relative */
839 0, /* bitpos */
840 complain_overflow_dont, /* complain_on_overflow */
841 bfd_elf_generic_reloc, /* special_function */
842 "R_RISCV_IRELATIVE", /* name */
843 false, /* partial_inplace */
844 0, /* src_mask */
845 0xffffffff, /* dst_mask */
846 false), /* pcrel_offset */
849 /* A mapping from BFD reloc types to RISC-V ELF reloc types. */
850 struct elf_reloc_map
852 bfd_reloc_code_real_type bfd_val;
853 enum elf_riscv_reloc_type elf_val;
856 static const struct elf_reloc_map riscv_reloc_map[] =
858 { BFD_RELOC_NONE, R_RISCV_NONE },
859 { BFD_RELOC_32, R_RISCV_32 },
860 { BFD_RELOC_64, R_RISCV_64 },
861 { BFD_RELOC_RISCV_ADD8, R_RISCV_ADD8 },
862 { BFD_RELOC_RISCV_ADD16, R_RISCV_ADD16 },
863 { BFD_RELOC_RISCV_ADD32, R_RISCV_ADD32 },
864 { BFD_RELOC_RISCV_ADD64, R_RISCV_ADD64 },
865 { BFD_RELOC_RISCV_SUB8, R_RISCV_SUB8 },
866 { BFD_RELOC_RISCV_SUB16, R_RISCV_SUB16 },
867 { BFD_RELOC_RISCV_SUB32, R_RISCV_SUB32 },
868 { BFD_RELOC_RISCV_SUB64, R_RISCV_SUB64 },
869 { BFD_RELOC_CTOR, R_RISCV_64 },
870 { BFD_RELOC_12_PCREL, R_RISCV_BRANCH },
871 { BFD_RELOC_RISCV_HI20, R_RISCV_HI20 },
872 { BFD_RELOC_RISCV_LO12_I, R_RISCV_LO12_I },
873 { BFD_RELOC_RISCV_LO12_S, R_RISCV_LO12_S },
874 { BFD_RELOC_RISCV_PCREL_LO12_I, R_RISCV_PCREL_LO12_I },
875 { BFD_RELOC_RISCV_PCREL_LO12_S, R_RISCV_PCREL_LO12_S },
876 { BFD_RELOC_RISCV_CALL, R_RISCV_CALL },
877 { BFD_RELOC_RISCV_CALL_PLT, R_RISCV_CALL_PLT },
878 { BFD_RELOC_RISCV_PCREL_HI20, R_RISCV_PCREL_HI20 },
879 { BFD_RELOC_RISCV_JMP, R_RISCV_JAL },
880 { BFD_RELOC_RISCV_GOT_HI20, R_RISCV_GOT_HI20 },
881 { BFD_RELOC_RISCV_TLS_DTPMOD32, R_RISCV_TLS_DTPMOD32 },
882 { BFD_RELOC_RISCV_TLS_DTPREL32, R_RISCV_TLS_DTPREL32 },
883 { BFD_RELOC_RISCV_TLS_DTPMOD64, R_RISCV_TLS_DTPMOD64 },
884 { BFD_RELOC_RISCV_TLS_DTPREL64, R_RISCV_TLS_DTPREL64 },
885 { BFD_RELOC_RISCV_TLS_TPREL32, R_RISCV_TLS_TPREL32 },
886 { BFD_RELOC_RISCV_TLS_TPREL64, R_RISCV_TLS_TPREL64 },
887 { BFD_RELOC_RISCV_TPREL_HI20, R_RISCV_TPREL_HI20 },
888 { BFD_RELOC_RISCV_TPREL_ADD, R_RISCV_TPREL_ADD },
889 { BFD_RELOC_RISCV_TPREL_LO12_S, R_RISCV_TPREL_LO12_S },
890 { BFD_RELOC_RISCV_TPREL_LO12_I, R_RISCV_TPREL_LO12_I },
891 { BFD_RELOC_RISCV_TLS_GOT_HI20, R_RISCV_TLS_GOT_HI20 },
892 { BFD_RELOC_RISCV_TLS_GD_HI20, R_RISCV_TLS_GD_HI20 },
893 { BFD_RELOC_RISCV_ALIGN, R_RISCV_ALIGN },
894 { BFD_RELOC_RISCV_RVC_BRANCH, R_RISCV_RVC_BRANCH },
895 { BFD_RELOC_RISCV_RVC_JUMP, R_RISCV_RVC_JUMP },
896 { BFD_RELOC_RISCV_RVC_LUI, R_RISCV_RVC_LUI },
897 { BFD_RELOC_RISCV_GPREL_I, R_RISCV_GPREL_I },
898 { BFD_RELOC_RISCV_GPREL_S, R_RISCV_GPREL_S },
899 { BFD_RELOC_RISCV_TPREL_I, R_RISCV_TPREL_I },
900 { BFD_RELOC_RISCV_TPREL_S, R_RISCV_TPREL_S },
901 { BFD_RELOC_RISCV_RELAX, R_RISCV_RELAX },
902 { BFD_RELOC_RISCV_SUB6, R_RISCV_SUB6 },
903 { BFD_RELOC_RISCV_SET6, R_RISCV_SET6 },
904 { BFD_RELOC_RISCV_SET8, R_RISCV_SET8 },
905 { BFD_RELOC_RISCV_SET16, R_RISCV_SET16 },
906 { BFD_RELOC_RISCV_SET32, R_RISCV_SET32 },
907 { BFD_RELOC_RISCV_32_PCREL, R_RISCV_32_PCREL },
910 /* Given a BFD reloc type, return a howto structure. */
912 reloc_howto_type *
913 riscv_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED,
914 bfd_reloc_code_real_type code)
916 unsigned int i;
918 for (i = 0; i < ARRAY_SIZE (riscv_reloc_map); i++)
919 if (riscv_reloc_map[i].bfd_val == code)
920 return &howto_table[(int) riscv_reloc_map[i].elf_val];
922 bfd_set_error (bfd_error_bad_value);
923 return NULL;
926 reloc_howto_type *
927 riscv_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED, const char *r_name)
929 unsigned int i;
931 for (i = 0; i < ARRAY_SIZE (howto_table); i++)
932 if (howto_table[i].name && strcasecmp (howto_table[i].name, r_name) == 0)
933 return &howto_table[i];
935 return NULL;
938 reloc_howto_type *
939 riscv_elf_rtype_to_howto (bfd *abfd, unsigned int r_type)
941 if (r_type >= ARRAY_SIZE (howto_table))
943 (*_bfd_error_handler) (_("%pB: unsupported relocation type %#x"),
944 abfd, r_type);
945 bfd_set_error (bfd_error_bad_value);
946 return NULL;
948 return &howto_table[r_type];
951 /* Special_function of RISCV_ADD and RISCV_SUB relocations. */
953 static bfd_reloc_status_type
954 riscv_elf_add_sub_reloc (bfd *abfd,
955 arelent *reloc_entry,
956 asymbol *symbol,
957 void *data,
958 asection *input_section,
959 bfd *output_bfd,
960 char **error_message ATTRIBUTE_UNUSED)
962 reloc_howto_type *howto = reloc_entry->howto;
963 bfd_vma relocation;
965 if (output_bfd != NULL
966 && (symbol->flags & BSF_SECTION_SYM) == 0
967 && (!reloc_entry->howto->partial_inplace || reloc_entry->addend == 0))
969 reloc_entry->address += input_section->output_offset;
970 return bfd_reloc_ok;
973 if (output_bfd != NULL)
974 return bfd_reloc_continue;
976 relocation = symbol->value + symbol->section->output_section->vma
977 + symbol->section->output_offset + reloc_entry->addend;
979 bfd_size_type octets = reloc_entry->address
980 * bfd_octets_per_byte (abfd, input_section);
981 if (!bfd_reloc_offset_in_range (reloc_entry->howto, abfd,
982 input_section, octets))
983 return bfd_reloc_outofrange;
985 bfd_vma old_value = bfd_get (howto->bitsize, abfd,
986 data + reloc_entry->address);
988 switch (howto->type)
990 case R_RISCV_ADD8:
991 case R_RISCV_ADD16:
992 case R_RISCV_ADD32:
993 case R_RISCV_ADD64:
994 relocation = old_value + relocation;
995 break;
996 case R_RISCV_SUB6:
997 relocation = (old_value & ~howto->dst_mask)
998 | (((old_value & howto->dst_mask) - relocation)
999 & howto->dst_mask);
1000 break;
1001 case R_RISCV_SUB8:
1002 case R_RISCV_SUB16:
1003 case R_RISCV_SUB32:
1004 case R_RISCV_SUB64:
1005 relocation = old_value - relocation;
1006 break;
1008 bfd_put (howto->bitsize, abfd, relocation, data + reloc_entry->address);
1010 return bfd_reloc_ok;
1013 /* Always add the IMPLICIT for the SUBSET. */
1015 static bool
1016 check_implicit_always (const char *implicit ATTRIBUTE_UNUSED,
1017 riscv_subset_t *subset ATTRIBUTE_UNUSED)
1019 return true;
1022 /* Add the IMPLICIT only when the version of SUBSET less than 2.1. */
1024 static bool
1025 check_implicit_for_i (const char *implicit ATTRIBUTE_UNUSED,
1026 riscv_subset_t *subset)
1028 return (subset->major_version < 2
1029 || (subset->major_version == 2
1030 && subset->minor_version < 1));
1033 /* Record all implicit information for the subsets. */
1034 struct riscv_implicit_subset
1036 const char *subset_name;
1037 const char *implicit_name;
1038 /* A function to determine if we need to add the implicit subset. */
1039 bool (*check_func) (const char *, riscv_subset_t *);
1041 static struct riscv_implicit_subset riscv_implicit_subsets[] =
1043 {"e", "i", check_implicit_always},
1044 {"i", "zicsr", check_implicit_for_i},
1045 {"i", "zifencei", check_implicit_for_i},
1046 {"g", "i", check_implicit_always},
1047 {"g", "m", check_implicit_always},
1048 {"g", "a", check_implicit_always},
1049 {"g", "f", check_implicit_always},
1050 {"g", "d", check_implicit_always},
1051 {"g", "zicsr", check_implicit_always},
1052 {"g", "zifencei", check_implicit_always},
1053 {"m", "zmmul", check_implicit_always},
1054 {"h", "zicsr", check_implicit_always},
1055 {"q", "d", check_implicit_always},
1056 {"v", "d", check_implicit_always},
1057 {"v", "zve64d", check_implicit_always},
1058 {"v", "zvl128b", check_implicit_always},
1059 {"zve64d", "d", check_implicit_always},
1060 {"zve64d", "zve64f", check_implicit_always},
1061 {"zve64f", "zve32f", check_implicit_always},
1062 {"zve64f", "zve64x", check_implicit_always},
1063 {"zve64f", "zvl64b", check_implicit_always},
1064 {"zve32f", "f", check_implicit_always},
1065 {"zve32f", "zvl32b", check_implicit_always},
1066 {"zve32f", "zve32x", check_implicit_always},
1067 {"zve64x", "zve32x", check_implicit_always},
1068 {"zve64x", "zvl64b", check_implicit_always},
1069 {"zve32x", "zvl32b", check_implicit_always},
1070 {"zvl65536b", "zvl32768b", check_implicit_always},
1071 {"zvl32768b", "zvl16384b", check_implicit_always},
1072 {"zvl16384b", "zvl8192b", check_implicit_always},
1073 {"zvl8192b", "zvl4096b", check_implicit_always},
1074 {"zvl4096b", "zvl2048b", check_implicit_always},
1075 {"zvl2048b", "zvl1024b", check_implicit_always},
1076 {"zvl1024b", "zvl512b", check_implicit_always},
1077 {"zvl512b", "zvl256b", check_implicit_always},
1078 {"zvl256b", "zvl128b", check_implicit_always},
1079 {"zvl128b", "zvl64b", check_implicit_always},
1080 {"zvl64b", "zvl32b", check_implicit_always},
1081 {"d", "f", check_implicit_always},
1082 {"zfh", "zfhmin", check_implicit_always},
1083 {"zfhmin", "f", check_implicit_always},
1084 {"f", "zicsr", check_implicit_always},
1085 {"zqinx", "zdinx", check_implicit_always},
1086 {"zdinx", "zfinx", check_implicit_always},
1087 {"zhinx", "zhinxmin", check_implicit_always},
1088 {"zhinxmin", "zfinx", check_implicit_always},
1089 {"zfinx", "zicsr", check_implicit_always},
1090 {"zk", "zkn", check_implicit_always},
1091 {"zk", "zkr", check_implicit_always},
1092 {"zk", "zkt", check_implicit_always},
1093 {"zkn", "zbkb", check_implicit_always},
1094 {"zkn", "zbkc", check_implicit_always},
1095 {"zkn", "zbkx", check_implicit_always},
1096 {"zkn", "zkne", check_implicit_always},
1097 {"zkn", "zknd", check_implicit_always},
1098 {"zkn", "zknh", check_implicit_always},
1099 {"zks", "zbkb", check_implicit_always},
1100 {"zks", "zbkc", check_implicit_always},
1101 {"zks", "zbkx", check_implicit_always},
1102 {"zks", "zksed", check_implicit_always},
1103 {"zks", "zksh", check_implicit_always},
1104 {"smaia", "ssaia", check_implicit_always},
1105 {"smstateen", "ssstateen", check_implicit_always},
1106 {"smepmp", "zicsr", check_implicit_always},
1107 {"ssaia", "zicsr", check_implicit_always},
1108 {"sscofpmf", "zicsr", check_implicit_always},
1109 {"ssstateen", "zicsr", check_implicit_always},
1110 {"sstc", "zicsr", check_implicit_always},
1111 {NULL, NULL, NULL}
1114 /* For default_enable field, decide if the extension should
1115 be enbaled by default. */
1117 #define EXT_DEFAULT 0x1
1119 /* List all extensions that binutils should know about. */
1121 struct riscv_supported_ext
1123 const char *name;
1124 enum riscv_spec_class isa_spec_class;
1125 int major_version;
1126 int minor_version;
1127 unsigned long default_enable;
1130 /* The standard extensions must be added in canonical order. */
1132 static struct riscv_supported_ext riscv_supported_std_ext[] =
1134 {"e", ISA_SPEC_CLASS_20191213, 1, 9, 0 },
1135 {"e", ISA_SPEC_CLASS_20190608, 1, 9, 0 },
1136 {"e", ISA_SPEC_CLASS_2P2, 1, 9, 0 },
1137 {"i", ISA_SPEC_CLASS_20191213, 2, 1, 0 },
1138 {"i", ISA_SPEC_CLASS_20190608, 2, 1, 0 },
1139 {"i", ISA_SPEC_CLASS_2P2, 2, 0, 0 },
1140 /* The g is a special case which we don't want to output it,
1141 but still need it when adding implicit extensions. */
1142 {"g", ISA_SPEC_CLASS_NONE, RISCV_UNKNOWN_VERSION, RISCV_UNKNOWN_VERSION, EXT_DEFAULT },
1143 {"m", ISA_SPEC_CLASS_20191213, 2, 0, 0 },
1144 {"m", ISA_SPEC_CLASS_20190608, 2, 0, 0 },
1145 {"m", ISA_SPEC_CLASS_2P2, 2, 0, 0 },
1146 {"a", ISA_SPEC_CLASS_20191213, 2, 1, 0 },
1147 {"a", ISA_SPEC_CLASS_20190608, 2, 0, 0 },
1148 {"a", ISA_SPEC_CLASS_2P2, 2, 0, 0 },
1149 {"f", ISA_SPEC_CLASS_20191213, 2, 2, 0 },
1150 {"f", ISA_SPEC_CLASS_20190608, 2, 2, 0 },
1151 {"f", ISA_SPEC_CLASS_2P2, 2, 0, 0 },
1152 {"d", ISA_SPEC_CLASS_20191213, 2, 2, 0 },
1153 {"d", ISA_SPEC_CLASS_20190608, 2, 2, 0 },
1154 {"d", ISA_SPEC_CLASS_2P2, 2, 0, 0 },
1155 {"q", ISA_SPEC_CLASS_20191213, 2, 2, 0 },
1156 {"q", ISA_SPEC_CLASS_20190608, 2, 2, 0 },
1157 {"q", ISA_SPEC_CLASS_2P2, 2, 0, 0 },
1158 {"c", ISA_SPEC_CLASS_20191213, 2, 0, 0 },
1159 {"c", ISA_SPEC_CLASS_20190608, 2, 0, 0 },
1160 {"c", ISA_SPEC_CLASS_2P2, 2, 0, 0 },
1161 {"v", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1162 {"h", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1163 {NULL, 0, 0, 0, 0}
1166 static struct riscv_supported_ext riscv_supported_std_z_ext[] =
1168 {"zicbom", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1169 {"zicbop", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1170 {"zicboz", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1171 {"zicsr", ISA_SPEC_CLASS_20191213, 2, 0, 0 },
1172 {"zicsr", ISA_SPEC_CLASS_20190608, 2, 0, 0 },
1173 {"zifencei", ISA_SPEC_CLASS_20191213, 2, 0, 0 },
1174 {"zifencei", ISA_SPEC_CLASS_20190608, 2, 0, 0 },
1175 {"zihintpause", ISA_SPEC_CLASS_DRAFT, 2, 0, 0 },
1176 {"zmmul", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1177 {"zawrs", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1178 {"zfh", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1179 {"zfhmin", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1180 {"zfinx", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1181 {"zdinx", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1182 {"zqinx", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1183 {"zhinx", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1184 {"zhinxmin", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1185 {"zbb", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1186 {"zba", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1187 {"zbc", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1188 {"zbs", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1189 {"zbkb", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1190 {"zbkc", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1191 {"zbkx", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1192 {"zk", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1193 {"zkn", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1194 {"zknd", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1195 {"zkne", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1196 {"zknh", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1197 {"zkr", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1198 {"zks", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1199 {"zksed", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1200 {"zksh", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1201 {"zkt", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1202 {"zve32x", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1203 {"zve32f", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1204 {"zve32d", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1205 {"zve64x", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1206 {"zve64f", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1207 {"zve64d", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1208 {"zvl32b", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1209 {"zvl64b", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1210 {"zvl128b", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1211 {"zvl256b", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1212 {"zvl512b", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1213 {"zvl1024b", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1214 {"zvl2048b", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1215 {"zvl4096b", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1216 {"zvl8192b", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1217 {"zvl16384b", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1218 {"zvl32768b", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1219 {"zvl65536b", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1220 {"ztso", ISA_SPEC_CLASS_DRAFT, 0, 1, 0 },
1221 {NULL, 0, 0, 0, 0}
1224 static struct riscv_supported_ext riscv_supported_std_s_ext[] =
1226 {"smaia", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1227 {"smepmp", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1228 {"smstateen", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1229 {"ssaia", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1230 {"sscofpmf", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1231 {"ssstateen", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1232 {"sstc", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1233 {"svinval", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1234 {"svnapot", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1235 {"svpbmt", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1236 {NULL, 0, 0, 0, 0}
1239 static struct riscv_supported_ext riscv_supported_std_zxm_ext[] =
1241 {NULL, 0, 0, 0, 0}
1244 static struct riscv_supported_ext riscv_supported_vendor_x_ext[] =
1246 {"xtheadba", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1247 {"xtheadbb", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1248 {"xtheadbs", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1249 {"xtheadcmo", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1250 {"xtheadcondmov", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1251 {"xtheadfmemidx", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1252 {"xtheadfmv", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1253 {"xtheadint", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1254 {"xtheadmac", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1255 {"xtheadmemidx", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1256 {"xtheadmempair", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1257 {"xtheadsync", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1258 {NULL, 0, 0, 0, 0}
1261 const struct riscv_supported_ext *riscv_all_supported_ext[] =
1263 riscv_supported_std_ext,
1264 riscv_supported_std_z_ext,
1265 riscv_supported_std_s_ext,
1266 riscv_supported_std_zxm_ext,
1267 riscv_supported_vendor_x_ext,
1268 NULL
1271 /* ISA extension prefixed name class. Must define them in parsing order. */
1272 enum riscv_prefix_ext_class
1274 RV_ISA_CLASS_Z = 1,
1275 RV_ISA_CLASS_S,
1276 RV_ISA_CLASS_ZXM,
1277 RV_ISA_CLASS_X,
1278 RV_ISA_CLASS_UNKNOWN
1281 /* Record the strings of the prefixed extensions, and their corresponding
1282 classes. The more letters of the prefix string, the more forward it must
1283 be defined. Otherwise, the riscv_get_prefix_class will map it to the
1284 wrong classes. */
1285 struct riscv_parse_prefix_config
1287 /* Class of the extension. */
1288 enum riscv_prefix_ext_class class;
1290 /* Prefix string for error printing and internal parser usage. */
1291 const char *prefix;
1293 static const struct riscv_parse_prefix_config parse_config[] =
1295 {RV_ISA_CLASS_ZXM, "zxm"},
1296 {RV_ISA_CLASS_Z, "z"},
1297 {RV_ISA_CLASS_S, "s"},
1298 {RV_ISA_CLASS_X, "x"},
1299 {RV_ISA_CLASS_UNKNOWN, NULL}
1302 /* Get the prefixed name class for the extensions, the class also
1303 means the order of the prefixed extensions. */
1305 static enum riscv_prefix_ext_class
1306 riscv_get_prefix_class (const char *arch)
1308 int i = 0;
1309 while (parse_config[i].class != RV_ISA_CLASS_UNKNOWN)
1311 if (strncmp (arch, parse_config[i].prefix,
1312 strlen (parse_config[i].prefix)) == 0)
1313 return parse_config[i].class;
1314 i++;
1316 return RV_ISA_CLASS_UNKNOWN;
1319 /* Check KNOWN_EXTS to see if the EXT is supported. */
1321 static bool
1322 riscv_known_prefixed_ext (const char *ext,
1323 struct riscv_supported_ext *known_exts)
1325 size_t i;
1326 for (i = 0; known_exts[i].name != NULL; ++i)
1327 if (strcmp (ext, known_exts[i].name) == 0)
1328 return true;
1329 return false;
1332 /* Check whether the prefixed extension is recognized or not. Return
1333 true if recognized, otehrwise return false. */
1335 static bool
1336 riscv_recognized_prefixed_ext (const char *ext)
1338 enum riscv_prefix_ext_class class = riscv_get_prefix_class (ext);
1339 switch (class)
1341 case RV_ISA_CLASS_Z:
1342 return riscv_known_prefixed_ext (ext, riscv_supported_std_z_ext);
1343 case RV_ISA_CLASS_ZXM:
1344 return riscv_known_prefixed_ext (ext, riscv_supported_std_zxm_ext);
1345 case RV_ISA_CLASS_S:
1346 return riscv_known_prefixed_ext (ext, riscv_supported_std_s_ext);
1347 case RV_ISA_CLASS_X:
1348 /* Only the single x is unrecognized. */
1349 if (strcmp (ext, "x") != 0)
1350 return true;
1351 default:
1352 break;
1354 return false;
1357 /* Canonical order for single letter extensions. */
1358 static const char riscv_ext_canonical_order[] = "eigmafdqlcbkjtpvnh";
1360 /* Array is used to compare the orders of standard extensions quickly. */
1361 static int riscv_ext_order[26] = {0};
1363 /* Init the riscv_ext_order array. */
1365 static void
1366 riscv_init_ext_order (void)
1368 static bool inited = false;
1369 if (inited)
1370 return;
1372 /* The orders of all standard extensions are positive. */
1373 int order = 1;
1375 for (const char *ext = &riscv_ext_canonical_order[0]; *ext; ++ext)
1376 riscv_ext_order[(*ext - 'a')] = order++;
1378 /* Some of the prefixed keyword are not single letter, so we set
1379 their prefixed orders in the riscv_compare_subsets directly,
1380 not through the riscv_ext_order. */
1382 inited = true;
1385 /* Similar to the strcmp. It returns an integer less than, equal to,
1386 or greater than zero if `subset2` is found, respectively, to be less
1387 than, to match, or be greater than `subset1`.
1389 The order values,
1390 Zero: Preserved keywords.
1391 Positive number: Standard extensions.
1392 Negative number: Prefixed keywords. */
1395 riscv_compare_subsets (const char *subset1, const char *subset2)
1397 int order1 = riscv_ext_order[(*subset1 - 'a')];
1398 int order2 = riscv_ext_order[(*subset2 - 'a')];
1400 /* Compare the standard extension first. */
1401 if (order1 > 0 && order2 > 0)
1402 return order1 - order2;
1404 /* Set the prefixed orders to negative numbers. */
1405 enum riscv_prefix_ext_class class1 = riscv_get_prefix_class (subset1);
1406 enum riscv_prefix_ext_class class2 = riscv_get_prefix_class (subset2);
1408 if (class1 != RV_ISA_CLASS_UNKNOWN)
1409 order1 = - (int) class1;
1410 if (class2 != RV_ISA_CLASS_UNKNOWN)
1411 order2 = - (int) class2;
1413 if (order1 == order2)
1415 /* Compare the standard addition z extensions. */
1416 if (class1 == RV_ISA_CLASS_Z)
1418 order1 = riscv_ext_order[(*++subset1 - 'a')];
1419 order2 = riscv_ext_order[(*++subset2 - 'a')];
1420 if (order1 != order2)
1421 return order1 - order2;
1423 return strcasecmp (++subset1, ++subset2);
1426 return order2 - order1;
1429 /* Find subset in the list. Return TRUE and set `current` to the subset
1430 if it is found. Otherwise, return FALSE and set `current` to the place
1431 where we should insert the subset. However, return FALSE with the NULL
1432 `current` means we should insert the subset at the head of subset list,
1433 if needed. */
1435 bool
1436 riscv_lookup_subset (const riscv_subset_list_t *subset_list,
1437 const char *subset,
1438 riscv_subset_t **current)
1440 riscv_subset_t *s, *pre_s = NULL;
1442 /* If the subset is added in order, then just add it at the tail. */
1443 if (subset_list->tail != NULL
1444 && riscv_compare_subsets (subset_list->tail->name, subset) < 0)
1446 *current = subset_list->tail;
1447 return false;
1450 for (s = subset_list->head;
1451 s != NULL;
1452 pre_s = s, s = s->next)
1454 int cmp = riscv_compare_subsets (s->name, subset);
1455 if (cmp == 0)
1457 *current = s;
1458 return true;
1460 else if (cmp > 0)
1461 break;
1463 *current = pre_s;
1465 return false;
1468 /* Add the extension to the subset list. Search the
1469 list first, and then find the right place to add. */
1471 void
1472 riscv_add_subset (riscv_subset_list_t *subset_list,
1473 const char *subset,
1474 int major,
1475 int minor)
1477 riscv_subset_t *current, *new;
1479 if (riscv_lookup_subset (subset_list, subset, &current))
1480 return;
1482 new = xmalloc (sizeof *new);
1483 new->name = xstrdup (subset);
1484 new->major_version = major;
1485 new->minor_version = minor;
1486 new->next = NULL;
1488 if (current != NULL)
1490 new->next = current->next;
1491 current->next = new;
1493 else
1495 new->next = subset_list->head;
1496 subset_list->head = new;
1499 if (new->next == NULL)
1500 subset_list->tail = new;
1503 /* Get the default versions from the riscv_supported_*ext tables. */
1505 static void
1506 riscv_get_default_ext_version (enum riscv_spec_class *default_isa_spec,
1507 const char *name,
1508 int *major_version,
1509 int *minor_version)
1511 if (name == NULL
1512 || default_isa_spec == NULL
1513 || *default_isa_spec == ISA_SPEC_CLASS_NONE)
1514 return;
1516 struct riscv_supported_ext *table = NULL;
1517 enum riscv_prefix_ext_class class = riscv_get_prefix_class (name);
1518 switch (class)
1520 case RV_ISA_CLASS_ZXM: table = riscv_supported_std_zxm_ext; break;
1521 case RV_ISA_CLASS_Z: table = riscv_supported_std_z_ext; break;
1522 case RV_ISA_CLASS_S: table = riscv_supported_std_s_ext; break;
1523 case RV_ISA_CLASS_X: table = riscv_supported_vendor_x_ext; break;
1524 default:
1525 table = riscv_supported_std_ext;
1528 int i = 0;
1529 while (table != NULL && table[i].name != NULL)
1531 if (strcmp (table[i].name, name) == 0
1532 && (table[i].isa_spec_class == ISA_SPEC_CLASS_DRAFT
1533 || table[i].isa_spec_class == *default_isa_spec))
1535 *major_version = table[i].major_version;
1536 *minor_version = table[i].minor_version;
1537 return;
1539 i++;
1543 /* Find the default versions for the extension before adding them to
1544 the subset list, if their versions are RISCV_UNKNOWN_VERSION.
1545 Afterwards, report errors if we can not find their default versions. */
1547 static void
1548 riscv_parse_add_subset (riscv_parse_subset_t *rps,
1549 const char *subset,
1550 int major,
1551 int minor,
1552 bool implicit)
1554 int major_version = major;
1555 int minor_version = minor;
1557 if (major_version == RISCV_UNKNOWN_VERSION
1558 || minor_version == RISCV_UNKNOWN_VERSION)
1559 riscv_get_default_ext_version (rps->isa_spec, subset,
1560 &major_version, &minor_version);
1562 /* We don't care the versions of the implicit extensions. */
1563 if (!implicit
1564 && (major_version == RISCV_UNKNOWN_VERSION
1565 || minor_version == RISCV_UNKNOWN_VERSION))
1567 if (subset[0] == 'x')
1568 rps->error_handler
1569 (_("x ISA extension `%s' must be set with the versions"),
1570 subset);
1571 /* Allow old ISA spec can recognize zicsr and zifencei. */
1572 else if (strcmp (subset, "zicsr") != 0
1573 && strcmp (subset, "zifencei") != 0)
1574 rps->error_handler
1575 (_("cannot find default versions of the ISA extension `%s'"),
1576 subset);
1577 return;
1580 riscv_add_subset (rps->subset_list, subset,
1581 major_version, minor_version);
1584 /* Release subset list. */
1586 void
1587 riscv_release_subset_list (riscv_subset_list_t *subset_list)
1589 while (subset_list->head != NULL)
1591 riscv_subset_t *next = subset_list->head->next;
1592 free ((void *)subset_list->head->name);
1593 free (subset_list->head);
1594 subset_list->head = next;
1597 subset_list->tail = NULL;
1599 if (subset_list->arch_str != NULL)
1601 free ((void*) subset_list->arch_str);
1602 subset_list->arch_str = NULL;
1606 /* Parsing extension version.
1608 Return Value:
1609 Points to the end of version
1611 Arguments:
1612 `p`: Curent parsing position.
1613 `major_version`: Parsed major version.
1614 `minor_version`: Parsed minor version. */
1616 static const char *
1617 riscv_parsing_subset_version (const char *p,
1618 int *major_version,
1619 int *minor_version)
1621 bool major_p = true;
1622 int version = 0;
1623 char np;
1625 *major_version = 0;
1626 *minor_version = 0;
1627 for (; *p; ++p)
1629 if (*p == 'p')
1631 np = *(p + 1);
1633 /* Might be beginning of `p` extension. */
1634 if (!ISDIGIT (np))
1635 break;
1637 *major_version = version;
1638 major_p = false;
1639 version = 0;
1641 else if (ISDIGIT (*p))
1642 version = (version * 10) + (*p - '0');
1643 else
1644 break;
1647 if (major_p)
1648 *major_version = version;
1649 else
1650 *minor_version = version;
1652 /* We can not find any version in string. */
1653 if (*major_version == 0 && *minor_version == 0)
1655 *major_version = RISCV_UNKNOWN_VERSION;
1656 *minor_version = RISCV_UNKNOWN_VERSION;
1659 return p;
1662 /* Parsing function for standard extensions.
1664 Return Value:
1665 Points to the end of extensions.
1667 Arguments:
1668 `rps`: Hooks and status for parsing extensions.
1669 `arch`: Full ISA string.
1670 `p`: Curent parsing position. */
1672 static const char *
1673 riscv_parse_std_ext (riscv_parse_subset_t *rps,
1674 const char *arch,
1675 const char *p)
1677 /* First letter must start with i, e or g. */
1678 if (*p != 'e' && *p != 'i' && *p != 'g')
1680 rps->error_handler
1681 (_("%s: first ISA extension must be `e', `i' or `g'"),
1682 arch);
1683 return NULL;
1686 while (p != NULL && *p != '\0')
1688 /* Stop when we parsed the known prefix class. */
1689 enum riscv_prefix_ext_class class = riscv_get_prefix_class (p);
1690 if (class != RV_ISA_CLASS_UNKNOWN)
1691 break;
1693 if (*p == '_')
1695 p++;
1696 continue;
1699 bool implicit = false;
1700 int major = RISCV_UNKNOWN_VERSION;
1701 int minor = RISCV_UNKNOWN_VERSION;
1702 char subset[2] = {0, 0};
1704 subset[0] = *p;
1706 /* Check if the standard extension is supported. */
1707 if (riscv_ext_order[(subset[0] - 'a')] == 0)
1709 rps->error_handler
1710 (_("%s: unknown standard ISA extension `%c'"),
1711 arch, subset[0]);
1712 return NULL;
1715 /* Checking canonical order. */
1716 if (rps->subset_list->tail != NULL
1717 && riscv_compare_subsets (rps->subset_list->tail->name, subset) > 0)
1719 rps->error_handler
1720 (_("%s: standard ISA extension `%c' is not "
1721 "in canonical order"), arch, subset[0]);
1722 return NULL;
1725 p = riscv_parsing_subset_version (++p, &major, &minor);
1726 /* Added g as an implicit extension. */
1727 if (subset[0] == 'g')
1729 implicit = true;
1730 major = RISCV_UNKNOWN_VERSION;
1731 minor = RISCV_UNKNOWN_VERSION;
1733 riscv_parse_add_subset (rps, subset, major, minor, implicit);
1736 return p;
1739 /* Parsing function for prefixed extensions.
1741 Return Value:
1742 Points to the end of extension.
1744 Arguments:
1745 `rps`: Hooks and status for parsing extensions.
1746 `arch`: Full ISA string.
1747 `p`: Curent parsing position. */
1749 static const char *
1750 riscv_parse_prefixed_ext (riscv_parse_subset_t *rps,
1751 const char *arch,
1752 const char *p)
1754 int major_version;
1755 int minor_version;
1756 enum riscv_prefix_ext_class class;
1758 while (*p)
1760 if (*p == '_')
1762 p++;
1763 continue;
1766 class = riscv_get_prefix_class (p);
1767 if (class == RV_ISA_CLASS_UNKNOWN)
1769 rps->error_handler
1770 (_("%s: unknown prefix class for the ISA extension `%s'"),
1771 arch, p);
1772 return NULL;
1775 char *subset = xstrdup (p);
1776 char *q = subset;
1777 const char *end_of_version;
1779 /* Extract the whole prefixed extension by '_'. */
1780 while (*++q != '\0' && *q != '_')
1782 /* Look forward to the first letter which is not <major>p<minor>. */
1783 bool find_any_version = false;
1784 bool find_minor_version = false;
1785 while (1)
1787 q--;
1788 if (ISDIGIT (*q))
1789 find_any_version = true;
1790 else if (find_any_version
1791 && !find_minor_version
1792 && *q == 'p'
1793 && ISDIGIT (*(q - 1)))
1794 find_minor_version = true;
1795 else
1796 break;
1798 q++;
1800 /* Check if the end of extension is 'p' or not. If yes, then
1801 the second letter from the end cannot be number. */
1802 if (*(q - 1) == 'p' && ISDIGIT (*(q - 2)))
1804 *q = '\0';
1805 rps->error_handler
1806 (_("%s: invalid prefixed ISA extension `%s' ends with <number>p"),
1807 arch, subset);
1808 free (subset);
1809 return NULL;
1812 end_of_version =
1813 riscv_parsing_subset_version (q, &major_version, &minor_version);
1814 *q = '\0';
1815 if (end_of_version == NULL)
1817 free (subset);
1818 return NULL;
1821 /* Check that the extension name is well-formed. */
1822 if (rps->check_unknown_prefixed_ext
1823 && !riscv_recognized_prefixed_ext (subset))
1825 rps->error_handler
1826 (_("%s: unknown prefixed ISA extension `%s'"),
1827 arch, subset);
1828 free (subset);
1829 return NULL;
1832 riscv_parse_add_subset (rps, subset,
1833 major_version,
1834 minor_version, false);
1835 p += end_of_version - subset;
1836 free (subset);
1838 if (*p != '\0' && *p != '_')
1840 rps->error_handler
1841 (_("%s: prefixed ISA extension must separate with _"),
1842 arch);
1843 return NULL;
1847 return p;
1850 /* Add the implicit extensions. */
1852 static void
1853 riscv_parse_add_implicit_subsets (riscv_parse_subset_t *rps)
1855 struct riscv_implicit_subset *t = riscv_implicit_subsets;
1856 for (; t->subset_name; t++)
1858 riscv_subset_t *subset = NULL;
1859 if (riscv_lookup_subset (rps->subset_list, t->subset_name, &subset)
1860 && t->check_func (t->implicit_name, subset))
1861 riscv_parse_add_subset (rps, t->implicit_name,
1862 RISCV_UNKNOWN_VERSION,
1863 RISCV_UNKNOWN_VERSION, true);
1867 /* Check extensions conflicts. */
1869 static bool
1870 riscv_parse_check_conflicts (riscv_parse_subset_t *rps)
1872 riscv_subset_t *subset = NULL;
1873 int xlen = *rps->xlen;
1874 bool no_conflict = true;
1876 if (riscv_lookup_subset (rps->subset_list, "e", &subset)
1877 && xlen > 32)
1879 rps->error_handler
1880 (_("rv%d does not support the `e' extension"), xlen);
1881 no_conflict = false;
1883 if (riscv_lookup_subset (rps->subset_list, "q", &subset)
1884 && (subset->major_version < 2 || (subset->major_version == 2
1885 && subset->minor_version < 2))
1886 && xlen < 64)
1888 rps->error_handler (_("rv%d does not support the `q' extension"), xlen);
1889 no_conflict = false;
1891 if (riscv_lookup_subset (rps->subset_list, "zfinx", &subset)
1892 && riscv_lookup_subset (rps->subset_list, "f", &subset))
1894 rps->error_handler
1895 (_("`zfinx' is conflict with the `f/d/q/zfh/zfhmin' extension"));
1896 no_conflict = false;
1899 bool support_zve = false;
1900 bool support_zvl = false;
1901 riscv_subset_t *s = rps->subset_list->head;
1902 for (; s != NULL; s = s->next)
1904 if (!support_zve
1905 && strncmp (s->name, "zve", 3) == 0)
1906 support_zve = true;
1907 if (!support_zvl
1908 && strncmp (s->name, "zvl", 3) == 0)
1909 support_zvl = true;
1910 if (support_zve && support_zvl)
1911 break;
1913 if (support_zvl && !support_zve)
1915 rps->error_handler
1916 (_("zvl*b extensions need to enable either `v' or `zve' extension"));
1917 no_conflict = false;
1920 return no_conflict;
1923 /* Set the default subset list according to the default_enable field
1924 of riscv_supported_*ext tables. */
1926 static void
1927 riscv_set_default_arch (riscv_parse_subset_t *rps)
1929 unsigned long enable = EXT_DEFAULT;
1930 int i, j;
1931 for (i = 0; riscv_all_supported_ext[i] != NULL; i++)
1933 const struct riscv_supported_ext *table = riscv_all_supported_ext[i];
1934 for (j = 0; table[j].name != NULL; j++)
1936 bool implicit = false;
1937 if (strcmp (table[j].name, "g") == 0)
1938 implicit = true;
1939 if (table[j].default_enable & enable)
1940 riscv_parse_add_subset (rps, table[j].name,
1941 RISCV_UNKNOWN_VERSION,
1942 RISCV_UNKNOWN_VERSION, implicit);
1947 /* Function for parsing ISA string.
1949 Return Value:
1950 Return TRUE on success.
1952 Arguments:
1953 `rps`: Hooks and status for parsing extensions.
1954 `arch`: Full ISA string. */
1956 bool
1957 riscv_parse_subset (riscv_parse_subset_t *rps,
1958 const char *arch)
1960 const char *p;
1962 /* Init the riscv_ext_order array to compare the order of extensions
1963 quickly. */
1964 riscv_init_ext_order ();
1966 if (arch == NULL)
1968 riscv_set_default_arch (rps);
1969 riscv_parse_add_implicit_subsets (rps);
1970 return riscv_parse_check_conflicts (rps);
1973 for (p = arch; *p != '\0'; p++)
1975 if (ISUPPER (*p))
1977 rps->error_handler
1978 (_("%s: ISA string cannot contain uppercase letters"),
1979 arch);
1980 return false;
1984 p = arch;
1985 if (startswith (p, "rv32"))
1987 *rps->xlen = 32;
1988 p += 4;
1990 else if (startswith (p, "rv64"))
1992 *rps->xlen = 64;
1993 p += 4;
1995 else
1997 /* ISA string shouldn't be NULL or empty here. For linker,
1998 it might be empty when we failed to merge the ISA string
1999 in the riscv_merge_attributes. For assembler, we might
2000 give an empty string by .attribute arch, "" or -march=.
2001 However, We have already issued the correct error message
2002 in another side, so do not issue this error when the ISA
2003 string is empty. */
2004 if (strlen (arch))
2005 rps->error_handler (
2006 _("%s: ISA string must begin with rv32 or rv64"),
2007 arch);
2008 return false;
2011 /* Parsing standard extension. */
2012 p = riscv_parse_std_ext (rps, arch, p);
2014 if (p == NULL)
2015 return false;
2017 /* Parse prefixed extensions. */
2018 p = riscv_parse_prefixed_ext (rps, arch, p);
2020 if (p == NULL)
2021 return false;
2023 /* Finally add implicit extensions according to the current
2024 extensions. */
2025 riscv_parse_add_implicit_subsets (rps);
2027 /* Check the conflicts. */
2028 return riscv_parse_check_conflicts (rps);
2031 /* Return the number of digits for the input. */
2033 size_t
2034 riscv_estimate_digit (unsigned num)
2036 size_t digit = 0;
2037 if (num == 0)
2038 return 1;
2040 for (digit = 0; num ; num /= 10)
2041 digit++;
2043 return digit;
2046 /* Auxiliary function to estimate string length of subset list. */
2048 static size_t
2049 riscv_estimate_arch_strlen1 (const riscv_subset_t *subset)
2051 if (subset == NULL)
2052 return 6; /* For rv32/rv64/rv128 and string terminator. */
2054 return riscv_estimate_arch_strlen1 (subset->next)
2055 + strlen (subset->name)
2056 + riscv_estimate_digit (subset->major_version)
2057 + 1 /* For version seperator 'p'. */
2058 + riscv_estimate_digit (subset->minor_version)
2059 + 1 /* For underscore. */;
2062 /* Estimate the string length of this subset list. */
2064 static size_t
2065 riscv_estimate_arch_strlen (const riscv_subset_list_t *subset_list)
2067 return riscv_estimate_arch_strlen1 (subset_list->head);
2070 /* Auxiliary function to convert subset info to string. */
2072 static void
2073 riscv_arch_str1 (riscv_subset_t *subset,
2074 char *attr_str, char *buf, size_t bufsz)
2076 const char *underline = "_";
2077 riscv_subset_t *subset_t = subset;
2079 if (subset_t == NULL)
2080 return;
2082 /* No underline between rvXX and i/e. */
2083 if ((strcasecmp (subset_t->name, "i") == 0)
2084 || (strcasecmp (subset_t->name, "e") == 0))
2085 underline = "";
2087 snprintf (buf, bufsz, "%s%s%dp%d",
2088 underline,
2089 subset_t->name,
2090 subset_t->major_version,
2091 subset_t->minor_version);
2093 strncat (attr_str, buf, bufsz);
2095 /* Skip 'i' extension after 'e', or skip extensions which
2096 versions are unknown. */
2097 while (subset_t->next
2098 && ((strcmp (subset_t->name, "e") == 0
2099 && strcmp (subset_t->next->name, "i") == 0)
2100 || subset_t->next->major_version == RISCV_UNKNOWN_VERSION
2101 || subset_t->next->minor_version == RISCV_UNKNOWN_VERSION))
2102 subset_t = subset_t->next;
2104 riscv_arch_str1 (subset_t->next, attr_str, buf, bufsz);
2107 /* Convert subset information into string with explicit versions. */
2109 char *
2110 riscv_arch_str (unsigned xlen, const riscv_subset_list_t *subset)
2112 size_t arch_str_len = riscv_estimate_arch_strlen (subset);
2113 char *attr_str = xmalloc (arch_str_len);
2114 char *buf = xmalloc (arch_str_len);
2116 snprintf (attr_str, arch_str_len, "rv%u", xlen);
2118 riscv_arch_str1 (subset->head, attr_str, buf, arch_str_len);
2119 free (buf);
2121 return attr_str;
2124 /* Copy the subset in the subset list. */
2126 static struct riscv_subset_t *
2127 riscv_copy_subset (riscv_subset_list_t *subset_list,
2128 riscv_subset_t *subset)
2130 if (subset == NULL)
2131 return NULL;
2133 riscv_subset_t *new = xmalloc (sizeof *new);
2134 new->name = xstrdup (subset->name);
2135 new->major_version = subset->major_version;
2136 new->minor_version = subset->minor_version;
2137 new->next = riscv_copy_subset (subset_list, subset->next);
2139 if (subset->next == NULL)
2140 subset_list->tail = new;
2142 return new;
2145 /* Copy the subset list. */
2147 riscv_subset_list_t *
2148 riscv_copy_subset_list (riscv_subset_list_t *subset_list)
2150 riscv_subset_list_t *new = xmalloc (sizeof *new);
2151 new->head = riscv_copy_subset (new, subset_list->head);
2152 new->arch_str = strdup (subset_list->arch_str);
2153 return new;
2156 /* Remove the SUBSET from the subset list. */
2158 static void
2159 riscv_remove_subset (riscv_subset_list_t *subset_list,
2160 const char *subset)
2162 riscv_subset_t *current = subset_list->head;
2163 riscv_subset_t *pre = NULL;
2164 for (; current != NULL; pre = current, current = current->next)
2166 if (strcmp (current->name, subset) == 0)
2168 if (pre == NULL)
2169 subset_list->head = current->next;
2170 else
2171 pre->next = current->next;
2172 if (current->next == NULL)
2173 subset_list->tail = pre;
2174 free ((void *) current->name);
2175 free (current);
2176 break;
2181 /* Add/Remove an extension to/from the subset list. This is used for
2182 the .option rvc or norvc, and .option arch directives. */
2184 bool
2185 riscv_update_subset (riscv_parse_subset_t *rps,
2186 const char *str)
2188 const char *p = str;
2192 int major_version = RISCV_UNKNOWN_VERSION;
2193 int minor_version = RISCV_UNKNOWN_VERSION;
2195 bool removed = false;
2196 switch (*p)
2198 case '+': removed = false; break;
2199 case '-': removed = true; break;
2200 default:
2201 riscv_release_subset_list (rps->subset_list);
2202 return riscv_parse_subset (rps, p);
2204 ++p;
2206 char *subset = xstrdup (p);
2207 char *q = subset;
2208 const char *end_of_version;
2209 /* Extract the whole prefixed extension by ','. */
2210 while (*q != '\0' && *q != ',')
2211 q++;
2213 /* Look forward to the first letter which is not <major>p<minor>. */
2214 bool find_any_version = false;
2215 bool find_minor_version = false;
2216 size_t len = q - subset;
2217 size_t i;
2218 for (i = len; i > 0; i--)
2220 q--;
2221 if (ISDIGIT (*q))
2222 find_any_version = true;
2223 else if (find_any_version
2224 && !find_minor_version
2225 && *q == 'p'
2226 && ISDIGIT (*(q - 1)))
2227 find_minor_version = true;
2228 else
2229 break;
2231 if (len > 0)
2232 q++;
2234 /* Check if the end of extension is 'p' or not. If yes, then
2235 the second letter from the end cannot be number. */
2236 if (len > 1 && *(q - 1) == 'p' && ISDIGIT (*(q - 2)))
2238 *q = '\0';
2239 rps->error_handler
2240 (_("invalid ISA extension ends with <number>p "
2241 "in .option arch `%s'"), str);
2242 free (subset);
2243 return false;
2246 end_of_version =
2247 riscv_parsing_subset_version (q, &major_version, &minor_version);
2248 *q = '\0';
2249 if (end_of_version == NULL)
2251 free (subset);
2252 return false;
2255 if (strlen (subset) == 0
2256 || (strlen (subset) == 1
2257 && riscv_ext_order[(*subset - 'a')] == 0)
2258 || (strlen (subset) > 1
2259 && rps->check_unknown_prefixed_ext
2260 && !riscv_recognized_prefixed_ext (subset)))
2262 rps->error_handler
2263 (_("unknown ISA extension `%s' in .option arch `%s'"),
2264 subset, str);
2265 free (subset);
2266 return false;
2269 if (strcmp (subset, "i") == 0
2270 || strcmp (subset, "e") == 0
2271 || strcmp (subset, "g") == 0)
2273 rps->error_handler
2274 (_("cannot + or - base extension `%s' in .option "
2275 "arch `%s'"), subset, str);
2276 free (subset);
2277 return false;
2280 if (removed)
2281 riscv_remove_subset (rps->subset_list, subset);
2282 else
2283 riscv_parse_add_subset (rps, subset, major_version, minor_version, true);
2284 p += end_of_version - subset;
2285 free (subset);
2287 while (*p++ == ',');
2289 riscv_parse_add_implicit_subsets (rps);
2290 return riscv_parse_check_conflicts (rps);
2293 /* Check if the FEATURE subset is supported or not in the subset list.
2294 Return true if it is supported; Otherwise, return false. */
2296 bool
2297 riscv_subset_supports (riscv_parse_subset_t *rps,
2298 const char *feature)
2300 struct riscv_subset_t *subset;
2301 return riscv_lookup_subset (rps->subset_list, feature, &subset);
2304 /* Each instuction is belonged to an instruction class INSN_CLASS_*.
2305 Call riscv_subset_supports to make sure if the instuction is valid. */
2307 bool
2308 riscv_multi_subset_supports (riscv_parse_subset_t *rps,
2309 enum riscv_insn_class insn_class)
2311 switch (insn_class)
2313 case INSN_CLASS_I:
2314 return riscv_subset_supports (rps, "i");
2315 case INSN_CLASS_ZICBOM:
2316 return riscv_subset_supports (rps, "zicbom");
2317 case INSN_CLASS_ZICBOP:
2318 return riscv_subset_supports (rps, "zicbop");
2319 case INSN_CLASS_ZICBOZ:
2320 return riscv_subset_supports (rps, "zicboz");
2321 case INSN_CLASS_ZICSR:
2322 return riscv_subset_supports (rps, "zicsr");
2323 case INSN_CLASS_ZIFENCEI:
2324 return riscv_subset_supports (rps, "zifencei");
2325 case INSN_CLASS_ZIHINTPAUSE:
2326 return riscv_subset_supports (rps, "zihintpause");
2327 case INSN_CLASS_M:
2328 return riscv_subset_supports (rps, "m");
2329 case INSN_CLASS_ZMMUL:
2330 return riscv_subset_supports (rps, "zmmul");
2331 case INSN_CLASS_A:
2332 return riscv_subset_supports (rps, "a");
2333 case INSN_CLASS_ZAWRS:
2334 return riscv_subset_supports (rps, "zawrs");
2335 case INSN_CLASS_F:
2336 return riscv_subset_supports (rps, "f");
2337 case INSN_CLASS_D:
2338 return riscv_subset_supports (rps, "d");
2339 case INSN_CLASS_Q:
2340 return riscv_subset_supports (rps, "q");
2341 case INSN_CLASS_C:
2342 return riscv_subset_supports (rps, "c");
2343 case INSN_CLASS_F_AND_C:
2344 return (riscv_subset_supports (rps, "f")
2345 && riscv_subset_supports (rps, "c"));
2346 case INSN_CLASS_D_AND_C:
2347 return (riscv_subset_supports (rps, "d")
2348 && riscv_subset_supports (rps, "c"));
2349 case INSN_CLASS_F_INX:
2350 return (riscv_subset_supports (rps, "f")
2351 || riscv_subset_supports (rps, "zfinx"));
2352 case INSN_CLASS_D_INX:
2353 return (riscv_subset_supports (rps, "d")
2354 || riscv_subset_supports (rps, "zdinx"));
2355 case INSN_CLASS_Q_INX:
2356 return (riscv_subset_supports (rps, "q")
2357 || riscv_subset_supports (rps, "zqinx"));
2358 case INSN_CLASS_ZFH_INX:
2359 return (riscv_subset_supports (rps, "zfh")
2360 || riscv_subset_supports (rps, "zhinx"));
2361 case INSN_CLASS_ZFHMIN:
2362 return riscv_subset_supports (rps, "zfhmin");
2363 case INSN_CLASS_ZFHMIN_INX:
2364 return (riscv_subset_supports (rps, "zfhmin")
2365 || riscv_subset_supports (rps, "zhinxmin"));
2366 case INSN_CLASS_ZFHMIN_AND_D_INX:
2367 return ((riscv_subset_supports (rps, "zfhmin")
2368 && riscv_subset_supports (rps, "d"))
2369 || (riscv_subset_supports (rps, "zhinxmin")
2370 && riscv_subset_supports (rps, "zdinx")));
2371 case INSN_CLASS_ZFHMIN_AND_Q_INX:
2372 return ((riscv_subset_supports (rps, "zfhmin")
2373 && riscv_subset_supports (rps, "q"))
2374 || (riscv_subset_supports (rps, "zhinxmin")
2375 && riscv_subset_supports (rps, "zqinx")));
2376 case INSN_CLASS_ZBA:
2377 return riscv_subset_supports (rps, "zba");
2378 case INSN_CLASS_ZBB:
2379 return riscv_subset_supports (rps, "zbb");
2380 case INSN_CLASS_ZBC:
2381 return riscv_subset_supports (rps, "zbc");
2382 case INSN_CLASS_ZBS:
2383 return riscv_subset_supports (rps, "zbs");
2384 case INSN_CLASS_ZBKB:
2385 return riscv_subset_supports (rps, "zbkb");
2386 case INSN_CLASS_ZBKC:
2387 return riscv_subset_supports (rps, "zbkc");
2388 case INSN_CLASS_ZBKX:
2389 return riscv_subset_supports (rps, "zbkx");
2390 case INSN_CLASS_ZBB_OR_ZBKB:
2391 return (riscv_subset_supports (rps, "zbb")
2392 || riscv_subset_supports (rps, "zbkb"));
2393 case INSN_CLASS_ZBC_OR_ZBKC:
2394 return (riscv_subset_supports (rps, "zbc")
2395 || riscv_subset_supports (rps, "zbkc"));
2396 case INSN_CLASS_ZKND:
2397 return riscv_subset_supports (rps, "zknd");
2398 case INSN_CLASS_ZKNE:
2399 return riscv_subset_supports (rps, "zkne");
2400 case INSN_CLASS_ZKNH:
2401 return riscv_subset_supports (rps, "zknh");
2402 case INSN_CLASS_ZKND_OR_ZKNE:
2403 return (riscv_subset_supports (rps, "zknd")
2404 || riscv_subset_supports (rps, "zkne"));
2405 case INSN_CLASS_ZKSED:
2406 return riscv_subset_supports (rps, "zksed");
2407 case INSN_CLASS_ZKSH:
2408 return riscv_subset_supports (rps, "zksh");
2409 case INSN_CLASS_V:
2410 return (riscv_subset_supports (rps, "v")
2411 || riscv_subset_supports (rps, "zve64x")
2412 || riscv_subset_supports (rps, "zve32x"));
2413 case INSN_CLASS_ZVEF:
2414 return (riscv_subset_supports (rps, "v")
2415 || riscv_subset_supports (rps, "zve64d")
2416 || riscv_subset_supports (rps, "zve64f")
2417 || riscv_subset_supports (rps, "zve32f"));
2418 case INSN_CLASS_SVINVAL:
2419 return riscv_subset_supports (rps, "svinval");
2420 case INSN_CLASS_H:
2421 return riscv_subset_supports (rps, "h");
2422 case INSN_CLASS_XTHEADBA:
2423 return riscv_subset_supports (rps, "xtheadba");
2424 case INSN_CLASS_XTHEADBB:
2425 return riscv_subset_supports (rps, "xtheadbb");
2426 case INSN_CLASS_XTHEADBS:
2427 return riscv_subset_supports (rps, "xtheadbs");
2428 case INSN_CLASS_XTHEADCMO:
2429 return riscv_subset_supports (rps, "xtheadcmo");
2430 case INSN_CLASS_XTHEADCONDMOV:
2431 return riscv_subset_supports (rps, "xtheadcondmov");
2432 case INSN_CLASS_XTHEADFMEMIDX:
2433 return riscv_subset_supports (rps, "xtheadfmemidx");
2434 case INSN_CLASS_XTHEADFMV:
2435 return riscv_subset_supports (rps, "xtheadfmv");
2436 case INSN_CLASS_XTHEADINT:
2437 return riscv_subset_supports (rps, "xtheadint");
2438 case INSN_CLASS_XTHEADMAC:
2439 return riscv_subset_supports (rps, "xtheadmac");
2440 case INSN_CLASS_XTHEADMEMIDX:
2441 return riscv_subset_supports (rps, "xtheadmemidx");
2442 case INSN_CLASS_XTHEADMEMPAIR:
2443 return riscv_subset_supports (rps, "xtheadmempair");
2444 case INSN_CLASS_XTHEADSYNC:
2445 return riscv_subset_supports (rps, "xtheadsync");
2446 default:
2447 rps->error_handler
2448 (_("internal: unreachable INSN_CLASS_*"));
2449 return false;
2453 /* Each instuction is belonged to an instruction class INSN_CLASS_*.
2454 Call riscv_subset_supports_ext to determine the missing extension. */
2456 const char *
2457 riscv_multi_subset_supports_ext (riscv_parse_subset_t *rps,
2458 enum riscv_insn_class insn_class)
2460 switch (insn_class)
2462 case INSN_CLASS_I:
2463 return "i";
2464 case INSN_CLASS_ZICBOM:
2465 return "zicbom";
2466 case INSN_CLASS_ZICBOP:
2467 return "zicbop";
2468 case INSN_CLASS_ZICBOZ:
2469 return "zicboz";
2470 case INSN_CLASS_ZICSR:
2471 return "zicsr";
2472 case INSN_CLASS_ZIFENCEI:
2473 return "zifencei";
2474 case INSN_CLASS_ZIHINTPAUSE:
2475 return "zihintpause";
2476 case INSN_CLASS_M:
2477 return "m";
2478 case INSN_CLASS_ZMMUL:
2479 return _ ("m' or `zmmul");
2480 case INSN_CLASS_A:
2481 return "a";
2482 case INSN_CLASS_ZAWRS:
2483 return "zawrs";
2484 case INSN_CLASS_F:
2485 return "f";
2486 case INSN_CLASS_D:
2487 return "d";
2488 case INSN_CLASS_Q:
2489 return "q";
2490 case INSN_CLASS_C:
2491 return "c";
2492 case INSN_CLASS_F_AND_C:
2493 if (!riscv_subset_supports (rps, "f")
2494 && !riscv_subset_supports (rps, "c"))
2495 return _("f' and `c");
2496 else if (!riscv_subset_supports (rps, "f"))
2497 return "f";
2498 else
2499 return "c";
2500 case INSN_CLASS_D_AND_C:
2501 if (!riscv_subset_supports (rps, "d")
2502 && !riscv_subset_supports (rps, "c"))
2503 return _("d' and `c");
2504 else if (!riscv_subset_supports (rps, "d"))
2505 return "d";
2506 else
2507 return "c";
2508 case INSN_CLASS_F_INX:
2509 return _("f' or `zfinx");
2510 case INSN_CLASS_D_INX:
2511 return _("d' or `zdinx");
2512 case INSN_CLASS_Q_INX:
2513 return _("q' or `zqinx");
2514 case INSN_CLASS_ZFH_INX:
2515 return _("zfh' or `zhinx");
2516 case INSN_CLASS_ZFHMIN:
2517 return "zfhmin";
2518 case INSN_CLASS_ZFHMIN_INX:
2519 return _("zfhmin' or `zhinxmin");
2520 case INSN_CLASS_ZFHMIN_AND_D_INX:
2521 if (riscv_subset_supports (rps, "zfhmin"))
2522 return "d";
2523 else if (riscv_subset_supports (rps, "d"))
2524 return "zfhmin";
2525 else if (riscv_subset_supports (rps, "zhinxmin"))
2526 return "zdinx";
2527 else if (riscv_subset_supports (rps, "zdinx"))
2528 return "zhinxmin";
2529 else
2530 return _("zfhmin' and `d', or `zhinxmin' and `zdinx");
2531 case INSN_CLASS_ZFHMIN_AND_Q_INX:
2532 if (riscv_subset_supports (rps, "zfhmin"))
2533 return "q";
2534 else if (riscv_subset_supports (rps, "q"))
2535 return "zfhmin";
2536 else if (riscv_subset_supports (rps, "zhinxmin"))
2537 return "zqinx";
2538 else if (riscv_subset_supports (rps, "zqinx"))
2539 return "zhinxmin";
2540 else
2541 return _("zfhmin' and `q', or `zhinxmin' and `zqinx");
2542 case INSN_CLASS_ZBA:
2543 return "zba";
2544 case INSN_CLASS_ZBB:
2545 return "zbb";
2546 case INSN_CLASS_ZBC:
2547 return "zbc";
2548 case INSN_CLASS_ZBS:
2549 return "zbs";
2550 case INSN_CLASS_ZBKB:
2551 return "zbkb";
2552 case INSN_CLASS_ZBKC:
2553 return "zbkc";
2554 case INSN_CLASS_ZBKX:
2555 return "zbkx";
2556 case INSN_CLASS_ZBB_OR_ZBKB:
2557 return _("zbb' or `zbkb");
2558 case INSN_CLASS_ZBC_OR_ZBKC:
2559 return _("zbc' or `zbkc");
2560 case INSN_CLASS_ZKND:
2561 return "zknd";
2562 case INSN_CLASS_ZKNE:
2563 return "zkne";
2564 case INSN_CLASS_ZKNH:
2565 return "zknh";
2566 case INSN_CLASS_ZKND_OR_ZKNE:
2567 return _("zknd' or `zkne");
2568 case INSN_CLASS_ZKSED:
2569 return "zksed";
2570 case INSN_CLASS_ZKSH:
2571 return "zksh";
2572 case INSN_CLASS_V:
2573 return _("v' or `zve64x' or `zve32x");
2574 case INSN_CLASS_ZVEF:
2575 return _("v' or `zve64d' or `zve64f' or `zve32f");
2576 case INSN_CLASS_SVINVAL:
2577 return "svinval";
2578 case INSN_CLASS_H:
2579 return _("h");
2580 case INSN_CLASS_XTHEADBA:
2581 return "xtheadba";
2582 case INSN_CLASS_XTHEADBB:
2583 return "xtheadbb";
2584 case INSN_CLASS_XTHEADBS:
2585 return "xtheadbs";
2586 case INSN_CLASS_XTHEADCMO:
2587 return "xtheadcmo";
2588 case INSN_CLASS_XTHEADCONDMOV:
2589 return "xtheadcondmov";
2590 case INSN_CLASS_XTHEADFMEMIDX:
2591 return "xtheadfmemidx";
2592 case INSN_CLASS_XTHEADFMV:
2593 return "xtheadfmv";
2594 case INSN_CLASS_XTHEADINT:
2595 return "xtheadint";
2596 case INSN_CLASS_XTHEADMAC:
2597 return "xtheadmac";
2598 case INSN_CLASS_XTHEADMEMIDX:
2599 return "xtheadmemidx";
2600 case INSN_CLASS_XTHEADMEMPAIR:
2601 return "xtheadmempair";
2602 case INSN_CLASS_XTHEADSYNC:
2603 return "xtheadsync";
2604 default:
2605 rps->error_handler
2606 (_("internal: unreachable INSN_CLASS_*"));
2607 return NULL;