Automatic date update in version.in
[binutils-gdb.git] / bfd / elfxx-riscv.c
blob1bcc6c0acb4495005aa40a06b489b9447fcf47a2
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 case R_RISCV_SUB8:
998 case R_RISCV_SUB16:
999 case R_RISCV_SUB32:
1000 case R_RISCV_SUB64:
1001 relocation = old_value - relocation;
1002 break;
1004 bfd_put (howto->bitsize, abfd, relocation, data + reloc_entry->address);
1006 return bfd_reloc_ok;
1009 /* Always add the IMPLICIT for the SUBSET. */
1011 static bool
1012 check_implicit_always (const char *implicit ATTRIBUTE_UNUSED,
1013 riscv_subset_t *subset ATTRIBUTE_UNUSED)
1015 return true;
1018 /* Add the IMPLICIT only when the version of SUBSET less than 2.1. */
1020 static bool
1021 check_implicit_for_i (const char *implicit ATTRIBUTE_UNUSED,
1022 riscv_subset_t *subset)
1024 return (subset->major_version < 2
1025 || (subset->major_version == 2
1026 && subset->minor_version < 1));
1029 /* Record all implicit information for the subsets. */
1030 struct riscv_implicit_subset
1032 const char *subset_name;
1033 const char *implicit_name;
1034 /* A function to determine if we need to add the implicit subset. */
1035 bool (*check_func) (const char *, riscv_subset_t *);
1037 static struct riscv_implicit_subset riscv_implicit_subsets[] =
1039 {"e", "i", check_implicit_always},
1040 {"i", "zicsr", check_implicit_for_i},
1041 {"i", "zifencei", check_implicit_for_i},
1042 {"g", "i", check_implicit_always},
1043 {"g", "m", check_implicit_always},
1044 {"g", "a", check_implicit_always},
1045 {"g", "f", check_implicit_always},
1046 {"g", "d", check_implicit_always},
1047 {"g", "zicsr", check_implicit_always},
1048 {"g", "zifencei", check_implicit_always},
1049 {"m", "zmmul", check_implicit_always},
1050 {"q", "d", check_implicit_always},
1051 {"v", "d", check_implicit_always},
1052 {"v", "zve64d", check_implicit_always},
1053 {"v", "zvl128b", check_implicit_always},
1054 {"zve64d", "d", check_implicit_always},
1055 {"zve64d", "zve64f", check_implicit_always},
1056 {"zve64f", "zve32f", check_implicit_always},
1057 {"zve64f", "zve64x", check_implicit_always},
1058 {"zve64f", "zvl64b", check_implicit_always},
1059 {"zve32f", "f", check_implicit_always},
1060 {"zve32f", "zvl32b", check_implicit_always},
1061 {"zve32f", "zve32x", check_implicit_always},
1062 {"zve64x", "zve32x", check_implicit_always},
1063 {"zve64x", "zvl64b", check_implicit_always},
1064 {"zve32x", "zvl32b", check_implicit_always},
1065 {"zvl65536b", "zvl32768b", check_implicit_always},
1066 {"zvl32768b", "zvl16384b", check_implicit_always},
1067 {"zvl16384b", "zvl8192b", check_implicit_always},
1068 {"zvl8192b", "zvl4096b", check_implicit_always},
1069 {"zvl4096b", "zvl2048b", check_implicit_always},
1070 {"zvl2048b", "zvl1024b", check_implicit_always},
1071 {"zvl1024b", "zvl512b", check_implicit_always},
1072 {"zvl512b", "zvl256b", check_implicit_always},
1073 {"zvl256b", "zvl128b", check_implicit_always},
1074 {"zvl128b", "zvl64b", check_implicit_always},
1075 {"zvl64b", "zvl32b", check_implicit_always},
1076 {"d", "f", check_implicit_always},
1077 {"zfh", "zfhmin", check_implicit_always},
1078 {"zfhmin", "f", check_implicit_always},
1079 {"f", "zicsr", check_implicit_always},
1080 {"zqinx", "zdinx", check_implicit_always},
1081 {"zdinx", "zfinx", check_implicit_always},
1082 {"zhinx", "zhinxmin", check_implicit_always},
1083 {"zhinxmin", "zfinx", check_implicit_always},
1084 {"zfinx", "zicsr", check_implicit_always},
1085 {"zk", "zkn", check_implicit_always},
1086 {"zk", "zkr", check_implicit_always},
1087 {"zk", "zkt", check_implicit_always},
1088 {"zkn", "zbkb", check_implicit_always},
1089 {"zkn", "zbkc", check_implicit_always},
1090 {"zkn", "zbkx", check_implicit_always},
1091 {"zkn", "zkne", check_implicit_always},
1092 {"zkn", "zknd", check_implicit_always},
1093 {"zkn", "zknh", check_implicit_always},
1094 {"zks", "zbkb", check_implicit_always},
1095 {"zks", "zbkc", check_implicit_always},
1096 {"zks", "zbkx", check_implicit_always},
1097 {"zks", "zksed", check_implicit_always},
1098 {"zks", "zksh", check_implicit_always},
1099 {NULL, NULL, NULL}
1102 /* For default_enable field, decide if the extension should
1103 be enbaled by default. */
1105 #define EXT_DEFAULT 0x1
1107 /* List all extensions that binutils should know about. */
1109 struct riscv_supported_ext
1111 const char *name;
1112 enum riscv_spec_class isa_spec_class;
1113 int major_version;
1114 int minor_version;
1115 unsigned long default_enable;
1118 /* The standard extensions must be added in canonical order. */
1120 static struct riscv_supported_ext riscv_supported_std_ext[] =
1122 {"e", ISA_SPEC_CLASS_20191213, 1, 9, 0 },
1123 {"e", ISA_SPEC_CLASS_20190608, 1, 9, 0 },
1124 {"e", ISA_SPEC_CLASS_2P2, 1, 9, 0 },
1125 {"i", ISA_SPEC_CLASS_20191213, 2, 1, 0 },
1126 {"i", ISA_SPEC_CLASS_20190608, 2, 1, 0 },
1127 {"i", ISA_SPEC_CLASS_2P2, 2, 0, 0 },
1128 /* The g is a special case which we don't want to output it,
1129 but still need it when adding implicit extensions. */
1130 {"g", ISA_SPEC_CLASS_NONE, RISCV_UNKNOWN_VERSION, RISCV_UNKNOWN_VERSION, EXT_DEFAULT },
1131 {"m", ISA_SPEC_CLASS_20191213, 2, 0, 0 },
1132 {"m", ISA_SPEC_CLASS_20190608, 2, 0, 0 },
1133 {"m", ISA_SPEC_CLASS_2P2, 2, 0, 0 },
1134 {"a", ISA_SPEC_CLASS_20191213, 2, 1, 0 },
1135 {"a", ISA_SPEC_CLASS_20190608, 2, 0, 0 },
1136 {"a", ISA_SPEC_CLASS_2P2, 2, 0, 0 },
1137 {"f", ISA_SPEC_CLASS_20191213, 2, 2, 0 },
1138 {"f", ISA_SPEC_CLASS_20190608, 2, 2, 0 },
1139 {"f", ISA_SPEC_CLASS_2P2, 2, 0, 0 },
1140 {"d", ISA_SPEC_CLASS_20191213, 2, 2, 0 },
1141 {"d", ISA_SPEC_CLASS_20190608, 2, 2, 0 },
1142 {"d", ISA_SPEC_CLASS_2P2, 2, 0, 0 },
1143 {"q", ISA_SPEC_CLASS_20191213, 2, 2, 0 },
1144 {"q", ISA_SPEC_CLASS_20190608, 2, 2, 0 },
1145 {"q", ISA_SPEC_CLASS_2P2, 2, 0, 0 },
1146 {"c", ISA_SPEC_CLASS_20191213, 2, 0, 0 },
1147 {"c", ISA_SPEC_CLASS_20190608, 2, 0, 0 },
1148 {"c", ISA_SPEC_CLASS_2P2, 2, 0, 0 },
1149 {"v", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1150 {"h", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1151 {NULL, 0, 0, 0, 0}
1154 static struct riscv_supported_ext riscv_supported_std_z_ext[] =
1156 {"zicbom", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1157 {"zicbop", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1158 {"zicboz", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1159 {"zicsr", ISA_SPEC_CLASS_20191213, 2, 0, 0 },
1160 {"zicsr", ISA_SPEC_CLASS_20190608, 2, 0, 0 },
1161 {"zifencei", ISA_SPEC_CLASS_20191213, 2, 0, 0 },
1162 {"zifencei", ISA_SPEC_CLASS_20190608, 2, 0, 0 },
1163 {"zihintpause", ISA_SPEC_CLASS_DRAFT, 2, 0, 0 },
1164 {"zmmul", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1165 {"zawrs", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1166 {"zfh", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1167 {"zfhmin", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1168 {"zfinx", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1169 {"zdinx", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1170 {"zqinx", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1171 {"zhinx", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1172 {"zhinxmin", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1173 {"zbb", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1174 {"zba", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1175 {"zbc", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1176 {"zbs", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1177 {"zbkb", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1178 {"zbkc", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1179 {"zbkx", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1180 {"zk", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1181 {"zkn", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1182 {"zknd", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1183 {"zkne", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1184 {"zknh", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1185 {"zkr", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1186 {"zks", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1187 {"zksed", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1188 {"zksh", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1189 {"zkt", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1190 {"zve32x", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1191 {"zve32f", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1192 {"zve32d", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1193 {"zve64x", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1194 {"zve64f", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1195 {"zve64d", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1196 {"zvl32b", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1197 {"zvl64b", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1198 {"zvl128b", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1199 {"zvl256b", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1200 {"zvl512b", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1201 {"zvl1024b", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1202 {"zvl2048b", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1203 {"zvl4096b", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1204 {"zvl8192b", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1205 {"zvl16384b", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1206 {"zvl32768b", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1207 {"zvl65536b", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1208 {"ztso", ISA_SPEC_CLASS_DRAFT, 0, 1, 0 },
1209 {NULL, 0, 0, 0, 0}
1212 static struct riscv_supported_ext riscv_supported_std_s_ext[] =
1214 {"smepmp", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1215 {"smstateen", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1216 {"sscofpmf", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1217 {"sstc", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1218 {"svinval", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1219 {"svnapot", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1220 {"svpbmt", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1221 {NULL, 0, 0, 0, 0}
1224 static struct riscv_supported_ext riscv_supported_std_zxm_ext[] =
1226 {NULL, 0, 0, 0, 0}
1229 static struct riscv_supported_ext riscv_supported_vendor_x_ext[] =
1231 {"xtheadba", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1232 {"xtheadbb", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1233 {"xtheadbs", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1234 {"xtheadcmo", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1235 {"xtheadcondmov", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1236 {"xtheadfmemidx", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1237 {"xtheadmac", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1238 {"xtheadmemidx", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1239 {"xtheadmempair", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1240 {"xtheadsync", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1241 {NULL, 0, 0, 0, 0}
1244 const struct riscv_supported_ext *riscv_all_supported_ext[] =
1246 riscv_supported_std_ext,
1247 riscv_supported_std_z_ext,
1248 riscv_supported_std_s_ext,
1249 riscv_supported_std_zxm_ext,
1250 riscv_supported_vendor_x_ext,
1251 NULL
1254 /* ISA extension prefixed name class. Must define them in parsing order. */
1255 enum riscv_prefix_ext_class
1257 RV_ISA_CLASS_Z = 1,
1258 RV_ISA_CLASS_S,
1259 RV_ISA_CLASS_ZXM,
1260 RV_ISA_CLASS_X,
1261 RV_ISA_CLASS_UNKNOWN
1264 /* Record the strings of the prefixed extensions, and their corresponding
1265 classes. The more letters of the prefix string, the more forward it must
1266 be defined. Otherwise, the riscv_get_prefix_class will map it to the
1267 wrong classes. */
1268 struct riscv_parse_prefix_config
1270 /* Class of the extension. */
1271 enum riscv_prefix_ext_class class;
1273 /* Prefix string for error printing and internal parser usage. */
1274 const char *prefix;
1276 static const struct riscv_parse_prefix_config parse_config[] =
1278 {RV_ISA_CLASS_ZXM, "zxm"},
1279 {RV_ISA_CLASS_Z, "z"},
1280 {RV_ISA_CLASS_S, "s"},
1281 {RV_ISA_CLASS_X, "x"},
1282 {RV_ISA_CLASS_UNKNOWN, NULL}
1285 /* Get the prefixed name class for the extensions, the class also
1286 means the order of the prefixed extensions. */
1288 static enum riscv_prefix_ext_class
1289 riscv_get_prefix_class (const char *arch)
1291 int i = 0;
1292 while (parse_config[i].class != RV_ISA_CLASS_UNKNOWN)
1294 if (strncmp (arch, parse_config[i].prefix,
1295 strlen (parse_config[i].prefix)) == 0)
1296 return parse_config[i].class;
1297 i++;
1299 return RV_ISA_CLASS_UNKNOWN;
1302 /* Check KNOWN_EXTS to see if the EXT is supported. */
1304 static bool
1305 riscv_known_prefixed_ext (const char *ext,
1306 struct riscv_supported_ext *known_exts)
1308 size_t i;
1309 for (i = 0; known_exts[i].name != NULL; ++i)
1310 if (strcmp (ext, known_exts[i].name) == 0)
1311 return true;
1312 return false;
1315 /* Check whether the prefixed extension is recognized or not. Return
1316 true if recognized, otehrwise return false. */
1318 static bool
1319 riscv_recognized_prefixed_ext (const char *ext)
1321 enum riscv_prefix_ext_class class = riscv_get_prefix_class (ext);
1322 switch (class)
1324 case RV_ISA_CLASS_Z:
1325 return riscv_known_prefixed_ext (ext, riscv_supported_std_z_ext);
1326 case RV_ISA_CLASS_ZXM:
1327 return riscv_known_prefixed_ext (ext, riscv_supported_std_zxm_ext);
1328 case RV_ISA_CLASS_S:
1329 return riscv_known_prefixed_ext (ext, riscv_supported_std_s_ext);
1330 case RV_ISA_CLASS_X:
1331 /* Only the single x is unrecognized. */
1332 if (strcmp (ext, "x") != 0)
1333 return true;
1334 default:
1335 break;
1337 return false;
1340 /* Canonical order for single letter extensions. */
1341 static const char riscv_ext_canonical_order[] = "eigmafdqlcbkjtpvnh";
1343 /* Array is used to compare the orders of standard extensions quickly. */
1344 static int riscv_ext_order[26] = {0};
1346 /* Init the riscv_ext_order array. */
1348 static void
1349 riscv_init_ext_order (void)
1351 static bool inited = false;
1352 if (inited)
1353 return;
1355 /* The orders of all standard extensions are positive. */
1356 int order = 1;
1358 for (const char *ext = &riscv_ext_canonical_order[0]; *ext; ++ext)
1359 riscv_ext_order[(*ext - 'a')] = order++;
1361 /* Some of the prefixed keyword are not single letter, so we set
1362 their prefixed orders in the riscv_compare_subsets directly,
1363 not through the riscv_ext_order. */
1365 inited = true;
1368 /* Similar to the strcmp. It returns an integer less than, equal to,
1369 or greater than zero if `subset2` is found, respectively, to be less
1370 than, to match, or be greater than `subset1`.
1372 The order values,
1373 Zero: Preserved keywords.
1374 Positive number: Standard extensions.
1375 Negative number: Prefixed keywords. */
1378 riscv_compare_subsets (const char *subset1, const char *subset2)
1380 int order1 = riscv_ext_order[(*subset1 - 'a')];
1381 int order2 = riscv_ext_order[(*subset2 - 'a')];
1383 /* Compare the standard extension first. */
1384 if (order1 > 0 && order2 > 0)
1385 return order1 - order2;
1387 /* Set the prefixed orders to negative numbers. */
1388 enum riscv_prefix_ext_class class1 = riscv_get_prefix_class (subset1);
1389 enum riscv_prefix_ext_class class2 = riscv_get_prefix_class (subset2);
1391 if (class1 != RV_ISA_CLASS_UNKNOWN)
1392 order1 = - (int) class1;
1393 if (class2 != RV_ISA_CLASS_UNKNOWN)
1394 order2 = - (int) class2;
1396 if (order1 == order2)
1398 /* Compare the standard addition z extensions. */
1399 if (class1 == RV_ISA_CLASS_Z)
1401 order1 = riscv_ext_order[(*++subset1 - 'a')];
1402 order2 = riscv_ext_order[(*++subset2 - 'a')];
1403 if (order1 != order2)
1404 return order1 - order2;
1406 return strcasecmp (++subset1, ++subset2);
1409 return order2 - order1;
1412 /* Find subset in the list. Return TRUE and set `current` to the subset
1413 if it is found. Otherwise, return FALSE and set `current` to the place
1414 where we should insert the subset. However, return FALSE with the NULL
1415 `current` means we should insert the subset at the head of subset list,
1416 if needed. */
1418 bool
1419 riscv_lookup_subset (const riscv_subset_list_t *subset_list,
1420 const char *subset,
1421 riscv_subset_t **current)
1423 riscv_subset_t *s, *pre_s = NULL;
1425 /* If the subset is added in order, then just add it at the tail. */
1426 if (subset_list->tail != NULL
1427 && riscv_compare_subsets (subset_list->tail->name, subset) < 0)
1429 *current = subset_list->tail;
1430 return false;
1433 for (s = subset_list->head;
1434 s != NULL;
1435 pre_s = s, s = s->next)
1437 int cmp = riscv_compare_subsets (s->name, subset);
1438 if (cmp == 0)
1440 *current = s;
1441 return true;
1443 else if (cmp > 0)
1444 break;
1446 *current = pre_s;
1448 return false;
1451 /* Add the extension to the subset list. Search the
1452 list first, and then find the right place to add. */
1454 void
1455 riscv_add_subset (riscv_subset_list_t *subset_list,
1456 const char *subset,
1457 int major,
1458 int minor)
1460 riscv_subset_t *current, *new;
1462 if (riscv_lookup_subset (subset_list, subset, &current))
1463 return;
1465 new = xmalloc (sizeof *new);
1466 new->name = xstrdup (subset);
1467 new->major_version = major;
1468 new->minor_version = minor;
1469 new->next = NULL;
1471 if (current != NULL)
1473 new->next = current->next;
1474 current->next = new;
1476 else
1478 new->next = subset_list->head;
1479 subset_list->head = new;
1482 if (new->next == NULL)
1483 subset_list->tail = new;
1486 /* Get the default versions from the riscv_supported_*ext tables. */
1488 static void
1489 riscv_get_default_ext_version (enum riscv_spec_class *default_isa_spec,
1490 const char *name,
1491 int *major_version,
1492 int *minor_version)
1494 if (name == NULL
1495 || default_isa_spec == NULL
1496 || *default_isa_spec == ISA_SPEC_CLASS_NONE)
1497 return;
1499 struct riscv_supported_ext *table = NULL;
1500 enum riscv_prefix_ext_class class = riscv_get_prefix_class (name);
1501 switch (class)
1503 case RV_ISA_CLASS_ZXM: table = riscv_supported_std_zxm_ext; break;
1504 case RV_ISA_CLASS_Z: table = riscv_supported_std_z_ext; break;
1505 case RV_ISA_CLASS_S: table = riscv_supported_std_s_ext; break;
1506 case RV_ISA_CLASS_X: table = riscv_supported_vendor_x_ext; break;
1507 default:
1508 table = riscv_supported_std_ext;
1511 int i = 0;
1512 while (table != NULL && table[i].name != NULL)
1514 if (strcmp (table[i].name, name) == 0
1515 && (table[i].isa_spec_class == ISA_SPEC_CLASS_DRAFT
1516 || table[i].isa_spec_class == *default_isa_spec))
1518 *major_version = table[i].major_version;
1519 *minor_version = table[i].minor_version;
1520 return;
1522 i++;
1526 /* Find the default versions for the extension before adding them to
1527 the subset list, if their versions are RISCV_UNKNOWN_VERSION.
1528 Afterwards, report errors if we can not find their default versions. */
1530 static void
1531 riscv_parse_add_subset (riscv_parse_subset_t *rps,
1532 const char *subset,
1533 int major,
1534 int minor,
1535 bool implicit)
1537 int major_version = major;
1538 int minor_version = minor;
1540 if (major_version == RISCV_UNKNOWN_VERSION
1541 || minor_version == RISCV_UNKNOWN_VERSION)
1542 riscv_get_default_ext_version (rps->isa_spec, subset,
1543 &major_version, &minor_version);
1545 /* We don't care the versions of the implicit extensions. */
1546 if (!implicit
1547 && (major_version == RISCV_UNKNOWN_VERSION
1548 || minor_version == RISCV_UNKNOWN_VERSION))
1550 if (subset[0] == 'x')
1551 rps->error_handler
1552 (_("x ISA extension `%s' must be set with the versions"),
1553 subset);
1554 /* Allow old ISA spec can recognize zicsr and zifencei. */
1555 else if (strcmp (subset, "zicsr") != 0
1556 && strcmp (subset, "zifencei") != 0)
1557 rps->error_handler
1558 (_("cannot find default versions of the ISA extension `%s'"),
1559 subset);
1560 return;
1563 riscv_add_subset (rps->subset_list, subset,
1564 major_version, minor_version);
1567 /* Release subset list. */
1569 void
1570 riscv_release_subset_list (riscv_subset_list_t *subset_list)
1572 while (subset_list->head != NULL)
1574 riscv_subset_t *next = subset_list->head->next;
1575 free ((void *)subset_list->head->name);
1576 free (subset_list->head);
1577 subset_list->head = next;
1580 subset_list->tail = NULL;
1583 /* Parsing extension version.
1585 Return Value:
1586 Points to the end of version
1588 Arguments:
1589 `p`: Curent parsing position.
1590 `major_version`: Parsed major version.
1591 `minor_version`: Parsed minor version. */
1593 static const char *
1594 riscv_parsing_subset_version (const char *p,
1595 int *major_version,
1596 int *minor_version)
1598 bool major_p = true;
1599 int version = 0;
1600 char np;
1602 *major_version = 0;
1603 *minor_version = 0;
1604 for (; *p; ++p)
1606 if (*p == 'p')
1608 np = *(p + 1);
1610 /* Might be beginning of `p` extension. */
1611 if (!ISDIGIT (np))
1612 break;
1614 *major_version = version;
1615 major_p = false;
1616 version = 0;
1618 else if (ISDIGIT (*p))
1619 version = (version * 10) + (*p - '0');
1620 else
1621 break;
1624 if (major_p)
1625 *major_version = version;
1626 else
1627 *minor_version = version;
1629 /* We can not find any version in string. */
1630 if (*major_version == 0 && *minor_version == 0)
1632 *major_version = RISCV_UNKNOWN_VERSION;
1633 *minor_version = RISCV_UNKNOWN_VERSION;
1636 return p;
1639 /* Parsing function for standard extensions.
1641 Return Value:
1642 Points to the end of extensions.
1644 Arguments:
1645 `rps`: Hooks and status for parsing extensions.
1646 `arch`: Full ISA string.
1647 `p`: Curent parsing position. */
1649 static const char *
1650 riscv_parse_std_ext (riscv_parse_subset_t *rps,
1651 const char *arch,
1652 const char *p)
1654 /* First letter must start with i, e or g. */
1655 if (*p != 'e' && *p != 'i' && *p != 'g')
1657 rps->error_handler
1658 (_("%s: first ISA extension must be `e', `i' or `g'"),
1659 arch);
1660 return NULL;
1663 while (p != NULL && *p != '\0')
1665 /* Stop when we parsed the known prefix class. */
1666 enum riscv_prefix_ext_class class = riscv_get_prefix_class (p);
1667 if (class != RV_ISA_CLASS_UNKNOWN)
1668 break;
1670 if (*p == '_')
1672 p++;
1673 continue;
1676 bool implicit = false;
1677 int major = RISCV_UNKNOWN_VERSION;
1678 int minor = RISCV_UNKNOWN_VERSION;
1679 char subset[2] = {0, 0};
1681 subset[0] = *p;
1683 /* Check if the standard extension is supported. */
1684 if (riscv_ext_order[(subset[0] - 'a')] == 0)
1686 rps->error_handler
1687 (_("%s: unknown standard ISA extension `%c'"),
1688 arch, subset[0]);
1689 return NULL;
1692 /* Checking canonical order. */
1693 if (rps->subset_list->tail != NULL
1694 && riscv_compare_subsets (rps->subset_list->tail->name, subset) > 0)
1696 rps->error_handler
1697 (_("%s: standard ISA extension `%c' is not "
1698 "in canonical order"), arch, subset[0]);
1699 return NULL;
1702 p = riscv_parsing_subset_version (++p, &major, &minor);
1703 /* Added g as an implicit extension. */
1704 if (subset[0] == 'g')
1706 implicit = true;
1707 major = RISCV_UNKNOWN_VERSION;
1708 minor = RISCV_UNKNOWN_VERSION;
1710 riscv_parse_add_subset (rps, subset, major, minor, implicit);
1713 return p;
1716 /* Parsing function for prefixed extensions.
1718 Return Value:
1719 Points to the end of extension.
1721 Arguments:
1722 `rps`: Hooks and status for parsing extensions.
1723 `arch`: Full ISA string.
1724 `p`: Curent parsing position. */
1726 static const char *
1727 riscv_parse_prefixed_ext (riscv_parse_subset_t *rps,
1728 const char *arch,
1729 const char *p)
1731 int major_version;
1732 int minor_version;
1733 enum riscv_prefix_ext_class class;
1735 while (*p)
1737 if (*p == '_')
1739 p++;
1740 continue;
1743 class = riscv_get_prefix_class (p);
1744 if (class == RV_ISA_CLASS_UNKNOWN)
1746 rps->error_handler
1747 (_("%s: unknown prefix class for the ISA extension `%s'"),
1748 arch, p);
1749 return NULL;
1752 char *subset = xstrdup (p);
1753 char *q = subset;
1754 const char *end_of_version;
1756 /* Extract the whole prefixed extension by '_'. */
1757 while (*++q != '\0' && *q != '_')
1759 /* Look forward to the first letter which is not <major>p<minor>. */
1760 bool find_any_version = false;
1761 bool find_minor_version = false;
1762 while (1)
1764 q--;
1765 if (ISDIGIT (*q))
1766 find_any_version = true;
1767 else if (find_any_version
1768 && !find_minor_version
1769 && *q == 'p'
1770 && ISDIGIT (*(q - 1)))
1771 find_minor_version = true;
1772 else
1773 break;
1775 q++;
1777 /* Check if the end of extension is 'p' or not. If yes, then
1778 the second letter from the end cannot be number. */
1779 if (*(q - 1) == 'p' && ISDIGIT (*(q - 2)))
1781 *q = '\0';
1782 rps->error_handler
1783 (_("%s: invalid prefixed ISA extension `%s' ends with <number>p"),
1784 arch, subset);
1785 free (subset);
1786 return NULL;
1789 end_of_version =
1790 riscv_parsing_subset_version (q, &major_version, &minor_version);
1791 *q = '\0';
1792 if (end_of_version == NULL)
1794 free (subset);
1795 return NULL;
1798 /* Check that the extension name is well-formed. */
1799 if (rps->check_unknown_prefixed_ext
1800 && !riscv_recognized_prefixed_ext (subset))
1802 rps->error_handler
1803 (_("%s: unknown prefixed ISA extension `%s'"),
1804 arch, subset);
1805 free (subset);
1806 return NULL;
1809 riscv_parse_add_subset (rps, subset,
1810 major_version,
1811 minor_version, false);
1812 p += end_of_version - subset;
1813 free (subset);
1815 if (*p != '\0' && *p != '_')
1817 rps->error_handler
1818 (_("%s: prefixed ISA extension must separate with _"),
1819 arch);
1820 return NULL;
1824 return p;
1827 /* Add the implicit extensions. */
1829 static void
1830 riscv_parse_add_implicit_subsets (riscv_parse_subset_t *rps)
1832 struct riscv_implicit_subset *t = riscv_implicit_subsets;
1833 for (; t->subset_name; t++)
1835 riscv_subset_t *subset = NULL;
1836 if (riscv_lookup_subset (rps->subset_list, t->subset_name, &subset)
1837 && t->check_func (t->implicit_name, subset))
1838 riscv_parse_add_subset (rps, t->implicit_name,
1839 RISCV_UNKNOWN_VERSION,
1840 RISCV_UNKNOWN_VERSION, true);
1844 /* Check extensions conflicts. */
1846 static bool
1847 riscv_parse_check_conflicts (riscv_parse_subset_t *rps)
1849 riscv_subset_t *subset = NULL;
1850 int xlen = *rps->xlen;
1851 bool no_conflict = true;
1853 if (riscv_lookup_subset (rps->subset_list, "e", &subset)
1854 && xlen > 32)
1856 rps->error_handler
1857 (_("rv%d does not support the `e' extension"), xlen);
1858 no_conflict = false;
1860 if (riscv_lookup_subset (rps->subset_list, "q", &subset)
1861 && (subset->major_version < 2 || (subset->major_version == 2
1862 && subset->minor_version < 2))
1863 && xlen < 64)
1865 rps->error_handler (_("rv%d does not support the `q' extension"), xlen);
1866 no_conflict = false;
1868 if (riscv_lookup_subset (rps->subset_list, "e", &subset)
1869 && riscv_lookup_subset (rps->subset_list, "f", &subset))
1871 rps->error_handler
1872 (_("rv32e does not support the `f' extension"));
1873 no_conflict = false;
1875 if (riscv_lookup_subset (rps->subset_list, "zfinx", &subset)
1876 && riscv_lookup_subset (rps->subset_list, "f", &subset))
1878 rps->error_handler
1879 (_("`zfinx' is conflict with the `f/d/q/zfh/zfhmin' extension"));
1880 no_conflict = false;
1883 bool support_zve = false;
1884 bool support_zvl = false;
1885 riscv_subset_t *s = rps->subset_list->head;
1886 for (; s != NULL; s = s->next)
1888 if (!support_zve
1889 && strncmp (s->name, "zve", 3) == 0)
1890 support_zve = true;
1891 if (!support_zvl
1892 && strncmp (s->name, "zvl", 3) == 0)
1893 support_zvl = true;
1894 if (support_zve && support_zvl)
1895 break;
1897 if (support_zvl && !support_zve)
1899 rps->error_handler
1900 (_("zvl*b extensions need to enable either `v' or `zve' extension"));
1901 no_conflict = false;
1904 return no_conflict;
1907 /* Set the default subset list according to the default_enable field
1908 of riscv_supported_*ext tables. */
1910 static void
1911 riscv_set_default_arch (riscv_parse_subset_t *rps)
1913 unsigned long enable = EXT_DEFAULT;
1914 int i, j;
1915 for (i = 0; riscv_all_supported_ext[i] != NULL; i++)
1917 const struct riscv_supported_ext *table = riscv_all_supported_ext[i];
1918 for (j = 0; table[j].name != NULL; j++)
1920 bool implicit = false;
1921 if (strcmp (table[j].name, "g") == 0)
1922 implicit = true;
1923 if (table[j].default_enable & enable)
1924 riscv_parse_add_subset (rps, table[j].name,
1925 RISCV_UNKNOWN_VERSION,
1926 RISCV_UNKNOWN_VERSION, implicit);
1931 /* Function for parsing ISA string.
1933 Return Value:
1934 Return TRUE on success.
1936 Arguments:
1937 `rps`: Hooks and status for parsing extensions.
1938 `arch`: Full ISA string. */
1940 bool
1941 riscv_parse_subset (riscv_parse_subset_t *rps,
1942 const char *arch)
1944 const char *p;
1946 /* Init the riscv_ext_order array to compare the order of extensions
1947 quickly. */
1948 riscv_init_ext_order ();
1950 if (arch == NULL)
1952 riscv_set_default_arch (rps);
1953 riscv_parse_add_implicit_subsets (rps);
1954 return riscv_parse_check_conflicts (rps);
1957 for (p = arch; *p != '\0'; p++)
1959 if (ISUPPER (*p))
1961 rps->error_handler
1962 (_("%s: ISA string cannot contain uppercase letters"),
1963 arch);
1964 return false;
1968 p = arch;
1969 if (startswith (p, "rv32"))
1971 *rps->xlen = 32;
1972 p += 4;
1974 else if (startswith (p, "rv64"))
1976 *rps->xlen = 64;
1977 p += 4;
1979 else
1981 /* ISA string shouldn't be NULL or empty here. For linker,
1982 it might be empty when we failed to merge the ISA string
1983 in the riscv_merge_attributes. For assembler, we might
1984 give an empty string by .attribute arch, "" or -march=.
1985 However, We have already issued the correct error message
1986 in another side, so do not issue this error when the ISA
1987 string is empty. */
1988 if (strlen (arch))
1989 rps->error_handler (
1990 _("%s: ISA string must begin with rv32 or rv64"),
1991 arch);
1992 return false;
1995 /* Parsing standard extension. */
1996 p = riscv_parse_std_ext (rps, arch, p);
1998 if (p == NULL)
1999 return false;
2001 /* Parse prefixed extensions. */
2002 p = riscv_parse_prefixed_ext (rps, arch, p);
2004 if (p == NULL)
2005 return false;
2007 /* Finally add implicit extensions according to the current
2008 extensions. */
2009 riscv_parse_add_implicit_subsets (rps);
2011 /* Check the conflicts. */
2012 return riscv_parse_check_conflicts (rps);
2015 /* Return the number of digits for the input. */
2017 size_t
2018 riscv_estimate_digit (unsigned num)
2020 size_t digit = 0;
2021 if (num == 0)
2022 return 1;
2024 for (digit = 0; num ; num /= 10)
2025 digit++;
2027 return digit;
2030 /* Auxiliary function to estimate string length of subset list. */
2032 static size_t
2033 riscv_estimate_arch_strlen1 (const riscv_subset_t *subset)
2035 if (subset == NULL)
2036 return 6; /* For rv32/rv64/rv128 and string terminator. */
2038 return riscv_estimate_arch_strlen1 (subset->next)
2039 + strlen (subset->name)
2040 + riscv_estimate_digit (subset->major_version)
2041 + 1 /* For version seperator 'p'. */
2042 + riscv_estimate_digit (subset->minor_version)
2043 + 1 /* For underscore. */;
2046 /* Estimate the string length of this subset list. */
2048 static size_t
2049 riscv_estimate_arch_strlen (const riscv_subset_list_t *subset_list)
2051 return riscv_estimate_arch_strlen1 (subset_list->head);
2054 /* Auxiliary function to convert subset info to string. */
2056 static void
2057 riscv_arch_str1 (riscv_subset_t *subset,
2058 char *attr_str, char *buf, size_t bufsz)
2060 const char *underline = "_";
2061 riscv_subset_t *subset_t = subset;
2063 if (subset_t == NULL)
2064 return;
2066 /* No underline between rvXX and i/e. */
2067 if ((strcasecmp (subset_t->name, "i") == 0)
2068 || (strcasecmp (subset_t->name, "e") == 0))
2069 underline = "";
2071 snprintf (buf, bufsz, "%s%s%dp%d",
2072 underline,
2073 subset_t->name,
2074 subset_t->major_version,
2075 subset_t->minor_version);
2077 strncat (attr_str, buf, bufsz);
2079 /* Skip 'i' extension after 'e', or skip extensions which
2080 versions are unknown. */
2081 while (subset_t->next
2082 && ((strcmp (subset_t->name, "e") == 0
2083 && strcmp (subset_t->next->name, "i") == 0)
2084 || subset_t->next->major_version == RISCV_UNKNOWN_VERSION
2085 || subset_t->next->minor_version == RISCV_UNKNOWN_VERSION))
2086 subset_t = subset_t->next;
2088 riscv_arch_str1 (subset_t->next, attr_str, buf, bufsz);
2091 /* Convert subset information into string with explicit versions. */
2093 char *
2094 riscv_arch_str (unsigned xlen, const riscv_subset_list_t *subset)
2096 size_t arch_str_len = riscv_estimate_arch_strlen (subset);
2097 char *attr_str = xmalloc (arch_str_len);
2098 char *buf = xmalloc (arch_str_len);
2100 snprintf (attr_str, arch_str_len, "rv%u", xlen);
2102 riscv_arch_str1 (subset->head, attr_str, buf, arch_str_len);
2103 free (buf);
2105 return attr_str;
2108 /* Copy the subset in the subset list. */
2110 static struct riscv_subset_t *
2111 riscv_copy_subset (riscv_subset_list_t *subset_list,
2112 riscv_subset_t *subset)
2114 if (subset == NULL)
2115 return NULL;
2117 riscv_subset_t *new = xmalloc (sizeof *new);
2118 new->name = xstrdup (subset->name);
2119 new->major_version = subset->major_version;
2120 new->minor_version = subset->minor_version;
2121 new->next = riscv_copy_subset (subset_list, subset->next);
2123 if (subset->next == NULL)
2124 subset_list->tail = new;
2126 return new;
2129 /* Copy the subset list. */
2131 riscv_subset_list_t *
2132 riscv_copy_subset_list (riscv_subset_list_t *subset_list)
2134 riscv_subset_list_t *new = xmalloc (sizeof *new);
2135 new->head = riscv_copy_subset (new, subset_list->head);
2136 return new;
2139 /* Remove the SUBSET from the subset list. */
2141 static void
2142 riscv_remove_subset (riscv_subset_list_t *subset_list,
2143 const char *subset)
2145 riscv_subset_t *current = subset_list->head;
2146 riscv_subset_t *pre = NULL;
2147 for (; current != NULL; pre = current, current = current->next)
2149 if (strcmp (current->name, subset) == 0)
2151 if (pre == NULL)
2152 subset_list->head = current->next;
2153 else
2154 pre->next = current->next;
2155 if (current->next == NULL)
2156 subset_list->tail = pre;
2157 free ((void *) current->name);
2158 free (current);
2159 break;
2164 /* Add/Remove an extension to/from the subset list. This is used for
2165 the .option rvc or norvc, and .option arch directives. */
2167 bool
2168 riscv_update_subset (riscv_parse_subset_t *rps,
2169 const char *str)
2171 const char *p = str;
2175 int major_version = RISCV_UNKNOWN_VERSION;
2176 int minor_version = RISCV_UNKNOWN_VERSION;
2178 bool removed = false;
2179 switch (*p)
2181 case '+': removed = false; break;
2182 case '-': removed = true; break;
2183 default:
2184 riscv_release_subset_list (rps->subset_list);
2185 return riscv_parse_subset (rps, p);
2187 ++p;
2189 char *subset = xstrdup (p);
2190 char *q = subset;
2191 const char *end_of_version;
2192 /* Extract the whole prefixed extension by ','. */
2193 while (*q != '\0' && *q != ',')
2194 q++;
2196 /* Look forward to the first letter which is not <major>p<minor>. */
2197 bool find_any_version = false;
2198 bool find_minor_version = false;
2199 size_t len = q - subset;
2200 size_t i;
2201 for (i = len; i > 0; i--)
2203 q--;
2204 if (ISDIGIT (*q))
2205 find_any_version = true;
2206 else if (find_any_version
2207 && !find_minor_version
2208 && *q == 'p'
2209 && ISDIGIT (*(q - 1)))
2210 find_minor_version = true;
2211 else
2212 break;
2214 if (len > 0)
2215 q++;
2217 /* Check if the end of extension is 'p' or not. If yes, then
2218 the second letter from the end cannot be number. */
2219 if (len > 1 && *(q - 1) == 'p' && ISDIGIT (*(q - 2)))
2221 *q = '\0';
2222 rps->error_handler
2223 (_("invalid ISA extension ends with <number>p "
2224 "in .option arch `%s'"), str);
2225 free (subset);
2226 return false;
2229 end_of_version =
2230 riscv_parsing_subset_version (q, &major_version, &minor_version);
2231 *q = '\0';
2232 if (end_of_version == NULL)
2234 free (subset);
2235 return false;
2238 if (strlen (subset) == 0
2239 || (strlen (subset) == 1
2240 && riscv_ext_order[(*subset - 'a')] == 0)
2241 || (strlen (subset) > 1
2242 && rps->check_unknown_prefixed_ext
2243 && !riscv_recognized_prefixed_ext (subset)))
2245 rps->error_handler
2246 (_("unknown ISA extension `%s' in .option arch `%s'"),
2247 subset, str);
2248 free (subset);
2249 return false;
2252 if (strcmp (subset, "i") == 0
2253 || strcmp (subset, "e") == 0
2254 || strcmp (subset, "g") == 0)
2256 rps->error_handler
2257 (_("cannot + or - base extension `%s' in .option "
2258 "arch `%s'"), subset, str);
2259 free (subset);
2260 return false;
2263 if (removed)
2264 riscv_remove_subset (rps->subset_list, subset);
2265 else
2266 riscv_parse_add_subset (rps, subset, major_version, minor_version, true);
2267 p += end_of_version - subset;
2268 free (subset);
2270 while (*p++ == ',');
2272 riscv_parse_add_implicit_subsets (rps);
2273 return riscv_parse_check_conflicts (rps);
2276 /* Check if the FEATURE subset is supported or not in the subset list.
2277 Return true if it is supported; Otherwise, return false. */
2279 bool
2280 riscv_subset_supports (riscv_parse_subset_t *rps,
2281 const char *feature)
2283 struct riscv_subset_t *subset;
2284 return riscv_lookup_subset (rps->subset_list, feature, &subset);
2287 /* Each instuction is belonged to an instruction class INSN_CLASS_*.
2288 Call riscv_subset_supports to make sure if the instuction is valid. */
2290 bool
2291 riscv_multi_subset_supports (riscv_parse_subset_t *rps,
2292 enum riscv_insn_class insn_class)
2294 switch (insn_class)
2296 case INSN_CLASS_I:
2297 return riscv_subset_supports (rps, "i");
2298 case INSN_CLASS_ZICBOM:
2299 return riscv_subset_supports (rps, "zicbom");
2300 case INSN_CLASS_ZICBOP:
2301 return riscv_subset_supports (rps, "zicbop");
2302 case INSN_CLASS_ZICBOZ:
2303 return riscv_subset_supports (rps, "zicboz");
2304 case INSN_CLASS_ZICSR:
2305 return riscv_subset_supports (rps, "zicsr");
2306 case INSN_CLASS_ZIFENCEI:
2307 return riscv_subset_supports (rps, "zifencei");
2308 case INSN_CLASS_ZIHINTPAUSE:
2309 return riscv_subset_supports (rps, "zihintpause");
2310 case INSN_CLASS_M:
2311 return riscv_subset_supports (rps, "m");
2312 case INSN_CLASS_ZMMUL:
2313 return riscv_subset_supports (rps, "zmmul");
2314 case INSN_CLASS_A:
2315 return riscv_subset_supports (rps, "a");
2316 case INSN_CLASS_ZAWRS:
2317 return riscv_subset_supports (rps, "zawrs");
2318 case INSN_CLASS_F:
2319 return riscv_subset_supports (rps, "f");
2320 case INSN_CLASS_D:
2321 return riscv_subset_supports (rps, "d");
2322 case INSN_CLASS_Q:
2323 return riscv_subset_supports (rps, "q");
2324 case INSN_CLASS_C:
2325 return riscv_subset_supports (rps, "c");
2326 case INSN_CLASS_F_AND_C:
2327 return (riscv_subset_supports (rps, "f")
2328 && riscv_subset_supports (rps, "c"));
2329 case INSN_CLASS_D_AND_C:
2330 return (riscv_subset_supports (rps, "d")
2331 && riscv_subset_supports (rps, "c"));
2332 case INSN_CLASS_F_INX:
2333 return (riscv_subset_supports (rps, "f")
2334 || riscv_subset_supports (rps, "zfinx"));
2335 case INSN_CLASS_D_INX:
2336 return (riscv_subset_supports (rps, "d")
2337 || riscv_subset_supports (rps, "zdinx"));
2338 case INSN_CLASS_Q_INX:
2339 return (riscv_subset_supports (rps, "q")
2340 || riscv_subset_supports (rps, "zqinx"));
2341 case INSN_CLASS_ZFH_INX:
2342 return (riscv_subset_supports (rps, "zfh")
2343 || riscv_subset_supports (rps, "zhinx"));
2344 case INSN_CLASS_ZFHMIN:
2345 return riscv_subset_supports (rps, "zfhmin");
2346 case INSN_CLASS_ZFHMIN_INX:
2347 return (riscv_subset_supports (rps, "zfhmin")
2348 || riscv_subset_supports (rps, "zhinxmin"));
2349 case INSN_CLASS_ZFHMIN_AND_D_INX:
2350 return ((riscv_subset_supports (rps, "zfhmin")
2351 && riscv_subset_supports (rps, "d"))
2352 || (riscv_subset_supports (rps, "zhinxmin")
2353 && riscv_subset_supports (rps, "zdinx")));
2354 case INSN_CLASS_ZFHMIN_AND_Q_INX:
2355 return ((riscv_subset_supports (rps, "zfhmin")
2356 && riscv_subset_supports (rps, "q"))
2357 || (riscv_subset_supports (rps, "zhinxmin")
2358 && riscv_subset_supports (rps, "zqinx")));
2359 case INSN_CLASS_ZBA:
2360 return riscv_subset_supports (rps, "zba");
2361 case INSN_CLASS_ZBB:
2362 return riscv_subset_supports (rps, "zbb");
2363 case INSN_CLASS_ZBC:
2364 return riscv_subset_supports (rps, "zbc");
2365 case INSN_CLASS_ZBS:
2366 return riscv_subset_supports (rps, "zbs");
2367 case INSN_CLASS_ZBKB:
2368 return riscv_subset_supports (rps, "zbkb");
2369 case INSN_CLASS_ZBKC:
2370 return riscv_subset_supports (rps, "zbkc");
2371 case INSN_CLASS_ZBKX:
2372 return riscv_subset_supports (rps, "zbkx");
2373 case INSN_CLASS_ZBB_OR_ZBKB:
2374 return (riscv_subset_supports (rps, "zbb")
2375 || riscv_subset_supports (rps, "zbkb"));
2376 case INSN_CLASS_ZBC_OR_ZBKC:
2377 return (riscv_subset_supports (rps, "zbc")
2378 || riscv_subset_supports (rps, "zbkc"));
2379 case INSN_CLASS_ZKND:
2380 return riscv_subset_supports (rps, "zknd");
2381 case INSN_CLASS_ZKNE:
2382 return riscv_subset_supports (rps, "zkne");
2383 case INSN_CLASS_ZKNH:
2384 return riscv_subset_supports (rps, "zknh");
2385 case INSN_CLASS_ZKND_OR_ZKNE:
2386 return (riscv_subset_supports (rps, "zknd")
2387 || riscv_subset_supports (rps, "zkne"));
2388 case INSN_CLASS_ZKSED:
2389 return riscv_subset_supports (rps, "zksed");
2390 case INSN_CLASS_ZKSH:
2391 return riscv_subset_supports (rps, "zksh");
2392 case INSN_CLASS_V:
2393 return (riscv_subset_supports (rps, "v")
2394 || riscv_subset_supports (rps, "zve64x")
2395 || riscv_subset_supports (rps, "zve32x"));
2396 case INSN_CLASS_ZVEF:
2397 return (riscv_subset_supports (rps, "v")
2398 || riscv_subset_supports (rps, "zve64d")
2399 || riscv_subset_supports (rps, "zve64f")
2400 || riscv_subset_supports (rps, "zve32f"));
2401 case INSN_CLASS_SVINVAL:
2402 return riscv_subset_supports (rps, "svinval");
2403 case INSN_CLASS_H:
2404 return riscv_subset_supports (rps, "h");
2405 case INSN_CLASS_XTHEADBA:
2406 return riscv_subset_supports (rps, "xtheadba");
2407 case INSN_CLASS_XTHEADBB:
2408 return riscv_subset_supports (rps, "xtheadbb");
2409 case INSN_CLASS_XTHEADBS:
2410 return riscv_subset_supports (rps, "xtheadbs");
2411 case INSN_CLASS_XTHEADCMO:
2412 return riscv_subset_supports (rps, "xtheadcmo");
2413 case INSN_CLASS_XTHEADCONDMOV:
2414 return riscv_subset_supports (rps, "xtheadcondmov");
2415 case INSN_CLASS_XTHEADFMEMIDX:
2416 return riscv_subset_supports (rps, "xtheadfmemidx");
2417 case INSN_CLASS_XTHEADMAC:
2418 return riscv_subset_supports (rps, "xtheadmac");
2419 case INSN_CLASS_XTHEADMEMIDX:
2420 return riscv_subset_supports (rps, "xtheadmemidx");
2421 case INSN_CLASS_XTHEADMEMPAIR:
2422 return riscv_subset_supports (rps, "xtheadmempair");
2423 case INSN_CLASS_XTHEADSYNC:
2424 return riscv_subset_supports (rps, "xtheadsync");
2425 default:
2426 rps->error_handler
2427 (_("internal: unreachable INSN_CLASS_*"));
2428 return false;
2432 /* Each instuction is belonged to an instruction class INSN_CLASS_*.
2433 Call riscv_subset_supports_ext to determine the missing extension. */
2435 const char *
2436 riscv_multi_subset_supports_ext (riscv_parse_subset_t *rps,
2437 enum riscv_insn_class insn_class)
2439 switch (insn_class)
2441 case INSN_CLASS_I:
2442 return "i";
2443 case INSN_CLASS_ZICSR:
2444 return "zicsr";
2445 case INSN_CLASS_ZIFENCEI:
2446 return "zifencei";
2447 case INSN_CLASS_ZIHINTPAUSE:
2448 return "zihintpause";
2449 case INSN_CLASS_M:
2450 return "m";
2451 case INSN_CLASS_ZMMUL:
2452 return _ ("m' or `zmmul");
2453 case INSN_CLASS_A:
2454 return "a";
2455 case INSN_CLASS_ZAWRS:
2456 return "zawrs";
2457 case INSN_CLASS_F:
2458 return "f";
2459 case INSN_CLASS_D:
2460 return "d";
2461 case INSN_CLASS_Q:
2462 return "q";
2463 case INSN_CLASS_C:
2464 return "c";
2465 case INSN_CLASS_F_AND_C:
2466 if (!riscv_subset_supports (rps, "f")
2467 && !riscv_subset_supports (rps, "c"))
2468 return _("f' and `c");
2469 else if (!riscv_subset_supports (rps, "f"))
2470 return "f";
2471 else
2472 return "c";
2473 case INSN_CLASS_D_AND_C:
2474 if (!riscv_subset_supports (rps, "d")
2475 && !riscv_subset_supports (rps, "c"))
2476 return _("d' and `c");
2477 else if (!riscv_subset_supports (rps, "d"))
2478 return "d";
2479 else
2480 return "c";
2481 case INSN_CLASS_F_INX:
2482 return _("f' or `zfinx");
2483 case INSN_CLASS_D_INX:
2484 return _("d' or `zdinx");
2485 case INSN_CLASS_Q_INX:
2486 return _("q' or `zqinx");
2487 case INSN_CLASS_ZFH_INX:
2488 return _("zfh' or `zhinx");
2489 case INSN_CLASS_ZFHMIN:
2490 return "zfhmin";
2491 case INSN_CLASS_ZFHMIN_INX:
2492 return _("zfhmin' or `zhinxmin");
2493 case INSN_CLASS_ZFHMIN_AND_D_INX:
2494 if (riscv_subset_supports (rps, "zfhmin"))
2495 return "d";
2496 else if (riscv_subset_supports (rps, "d"))
2497 return "zfhmin";
2498 else if (riscv_subset_supports (rps, "zhinxmin"))
2499 return "zdinx";
2500 else if (riscv_subset_supports (rps, "zdinx"))
2501 return "zhinxmin";
2502 else
2503 return _("zfhmin' and `d', or `zhinxmin' and `zdinx");
2504 case INSN_CLASS_ZFHMIN_AND_Q_INX:
2505 if (riscv_subset_supports (rps, "zfhmin"))
2506 return "q";
2507 else if (riscv_subset_supports (rps, "q"))
2508 return "zfhmin";
2509 else if (riscv_subset_supports (rps, "zhinxmin"))
2510 return "zqinx";
2511 else if (riscv_subset_supports (rps, "zqinx"))
2512 return "zhinxmin";
2513 else
2514 return _("zfhmin' and `q', or `zhinxmin' and `zqinx");
2515 case INSN_CLASS_ZBA:
2516 return "zba";
2517 case INSN_CLASS_ZBB:
2518 return "zbb";
2519 case INSN_CLASS_ZBC:
2520 return "zbc";
2521 case INSN_CLASS_ZBS:
2522 return "zbs";
2523 case INSN_CLASS_ZBKB:
2524 return "zbkb";
2525 case INSN_CLASS_ZBKC:
2526 return "zbkc";
2527 case INSN_CLASS_ZBKX:
2528 return "zbkx";
2529 case INSN_CLASS_ZBB_OR_ZBKB:
2530 return _("zbb' or `zbkb");
2531 case INSN_CLASS_ZBC_OR_ZBKC:
2532 return _("zbc' or `zbkc");
2533 case INSN_CLASS_ZKND:
2534 return "zknd";
2535 case INSN_CLASS_ZKNE:
2536 return "zkne";
2537 case INSN_CLASS_ZKNH:
2538 return "zknh";
2539 case INSN_CLASS_ZKND_OR_ZKNE:
2540 return _("zknd' or `zkne");
2541 case INSN_CLASS_ZKSED:
2542 return "zksed";
2543 case INSN_CLASS_ZKSH:
2544 return "zksh";
2545 case INSN_CLASS_V:
2546 return _("v' or `zve64x' or `zve32x");
2547 case INSN_CLASS_ZVEF:
2548 return _("v' or `zve64d' or `zve64f' or `zve32f");
2549 case INSN_CLASS_SVINVAL:
2550 return "svinval";
2551 case INSN_CLASS_H:
2552 return _("h");
2553 case INSN_CLASS_XTHEADBA:
2554 return "xtheadba";
2555 case INSN_CLASS_XTHEADBB:
2556 return "xtheadbb";
2557 case INSN_CLASS_XTHEADBS:
2558 return "xtheadbs";
2559 case INSN_CLASS_XTHEADCMO:
2560 return "xtheadcmo";
2561 case INSN_CLASS_XTHEADCONDMOV:
2562 return "xtheadcondmov";
2563 case INSN_CLASS_XTHEADFMEMIDX:
2564 return "xtheadfmemidx";
2565 case INSN_CLASS_XTHEADMAC:
2566 return "xtheadmac";
2567 case INSN_CLASS_XTHEADMEMIDX:
2568 return "xtheadmemidx";
2569 case INSN_CLASS_XTHEADMEMPAIR:
2570 return "xtheadmempair";
2571 case INSN_CLASS_XTHEADSYNC:
2572 return "xtheadsync";
2573 default:
2574 rps->error_handler
2575 (_("internal: unreachable INSN_CLASS_*"));
2576 return NULL;