Add a note to the binutils/NEWS file about DCO signed contributions.
[binutils-gdb.git] / bfd / elfxx-riscv.c
blobc89b1e53e922bedfdf2e8949c70f4cbe1fe64efd
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 {"h", "zicsr", check_implicit_always},
1051 {"q", "d", check_implicit_always},
1052 {"v", "d", check_implicit_always},
1053 {"v", "zve64d", check_implicit_always},
1054 {"v", "zvl128b", check_implicit_always},
1055 {"zve64d", "d", check_implicit_always},
1056 {"zve64d", "zve64f", check_implicit_always},
1057 {"zve64f", "zve32f", check_implicit_always},
1058 {"zve64f", "zve64x", check_implicit_always},
1059 {"zve64f", "zvl64b", check_implicit_always},
1060 {"zve32f", "f", check_implicit_always},
1061 {"zve32f", "zvl32b", check_implicit_always},
1062 {"zve32f", "zve32x", check_implicit_always},
1063 {"zve64x", "zve32x", check_implicit_always},
1064 {"zve64x", "zvl64b", check_implicit_always},
1065 {"zve32x", "zvl32b", check_implicit_always},
1066 {"zvl65536b", "zvl32768b", check_implicit_always},
1067 {"zvl32768b", "zvl16384b", check_implicit_always},
1068 {"zvl16384b", "zvl8192b", check_implicit_always},
1069 {"zvl8192b", "zvl4096b", check_implicit_always},
1070 {"zvl4096b", "zvl2048b", check_implicit_always},
1071 {"zvl2048b", "zvl1024b", check_implicit_always},
1072 {"zvl1024b", "zvl512b", check_implicit_always},
1073 {"zvl512b", "zvl256b", check_implicit_always},
1074 {"zvl256b", "zvl128b", check_implicit_always},
1075 {"zvl128b", "zvl64b", check_implicit_always},
1076 {"zvl64b", "zvl32b", check_implicit_always},
1077 {"d", "f", check_implicit_always},
1078 {"zfh", "zfhmin", check_implicit_always},
1079 {"zfhmin", "f", check_implicit_always},
1080 {"f", "zicsr", check_implicit_always},
1081 {"zqinx", "zdinx", check_implicit_always},
1082 {"zdinx", "zfinx", check_implicit_always},
1083 {"zhinx", "zhinxmin", check_implicit_always},
1084 {"zhinxmin", "zfinx", check_implicit_always},
1085 {"zfinx", "zicsr", check_implicit_always},
1086 {"zk", "zkn", check_implicit_always},
1087 {"zk", "zkr", check_implicit_always},
1088 {"zk", "zkt", check_implicit_always},
1089 {"zkn", "zbkb", check_implicit_always},
1090 {"zkn", "zbkc", check_implicit_always},
1091 {"zkn", "zbkx", check_implicit_always},
1092 {"zkn", "zkne", check_implicit_always},
1093 {"zkn", "zknd", check_implicit_always},
1094 {"zkn", "zknh", check_implicit_always},
1095 {"zks", "zbkb", check_implicit_always},
1096 {"zks", "zbkc", check_implicit_always},
1097 {"zks", "zbkx", check_implicit_always},
1098 {"zks", "zksed", check_implicit_always},
1099 {"zks", "zksh", check_implicit_always},
1100 {"smepmp", "zicsr", check_implicit_always},
1101 {"smstateen", "zicsr", check_implicit_always},
1102 {"sscofpmf", "zicsr", check_implicit_always},
1103 {"sstc", "zicsr", check_implicit_always},
1104 {NULL, NULL, NULL}
1107 /* For default_enable field, decide if the extension should
1108 be enbaled by default. */
1110 #define EXT_DEFAULT 0x1
1112 /* List all extensions that binutils should know about. */
1114 struct riscv_supported_ext
1116 const char *name;
1117 enum riscv_spec_class isa_spec_class;
1118 int major_version;
1119 int minor_version;
1120 unsigned long default_enable;
1123 /* The standard extensions must be added in canonical order. */
1125 static struct riscv_supported_ext riscv_supported_std_ext[] =
1127 {"e", ISA_SPEC_CLASS_20191213, 1, 9, 0 },
1128 {"e", ISA_SPEC_CLASS_20190608, 1, 9, 0 },
1129 {"e", ISA_SPEC_CLASS_2P2, 1, 9, 0 },
1130 {"i", ISA_SPEC_CLASS_20191213, 2, 1, 0 },
1131 {"i", ISA_SPEC_CLASS_20190608, 2, 1, 0 },
1132 {"i", ISA_SPEC_CLASS_2P2, 2, 0, 0 },
1133 /* The g is a special case which we don't want to output it,
1134 but still need it when adding implicit extensions. */
1135 {"g", ISA_SPEC_CLASS_NONE, RISCV_UNKNOWN_VERSION, RISCV_UNKNOWN_VERSION, EXT_DEFAULT },
1136 {"m", ISA_SPEC_CLASS_20191213, 2, 0, 0 },
1137 {"m", ISA_SPEC_CLASS_20190608, 2, 0, 0 },
1138 {"m", ISA_SPEC_CLASS_2P2, 2, 0, 0 },
1139 {"a", ISA_SPEC_CLASS_20191213, 2, 1, 0 },
1140 {"a", ISA_SPEC_CLASS_20190608, 2, 0, 0 },
1141 {"a", ISA_SPEC_CLASS_2P2, 2, 0, 0 },
1142 {"f", ISA_SPEC_CLASS_20191213, 2, 2, 0 },
1143 {"f", ISA_SPEC_CLASS_20190608, 2, 2, 0 },
1144 {"f", ISA_SPEC_CLASS_2P2, 2, 0, 0 },
1145 {"d", ISA_SPEC_CLASS_20191213, 2, 2, 0 },
1146 {"d", ISA_SPEC_CLASS_20190608, 2, 2, 0 },
1147 {"d", ISA_SPEC_CLASS_2P2, 2, 0, 0 },
1148 {"q", ISA_SPEC_CLASS_20191213, 2, 2, 0 },
1149 {"q", ISA_SPEC_CLASS_20190608, 2, 2, 0 },
1150 {"q", ISA_SPEC_CLASS_2P2, 2, 0, 0 },
1151 {"c", ISA_SPEC_CLASS_20191213, 2, 0, 0 },
1152 {"c", ISA_SPEC_CLASS_20190608, 2, 0, 0 },
1153 {"c", ISA_SPEC_CLASS_2P2, 2, 0, 0 },
1154 {"v", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1155 {"h", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1156 {NULL, 0, 0, 0, 0}
1159 static struct riscv_supported_ext riscv_supported_std_z_ext[] =
1161 {"zicbom", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1162 {"zicbop", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1163 {"zicboz", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1164 {"zicsr", ISA_SPEC_CLASS_20191213, 2, 0, 0 },
1165 {"zicsr", ISA_SPEC_CLASS_20190608, 2, 0, 0 },
1166 {"zifencei", ISA_SPEC_CLASS_20191213, 2, 0, 0 },
1167 {"zifencei", ISA_SPEC_CLASS_20190608, 2, 0, 0 },
1168 {"zihintpause", ISA_SPEC_CLASS_DRAFT, 2, 0, 0 },
1169 {"zmmul", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1170 {"zawrs", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1171 {"zfh", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1172 {"zfhmin", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1173 {"zfinx", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1174 {"zdinx", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1175 {"zqinx", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1176 {"zhinx", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1177 {"zhinxmin", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1178 {"zbb", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1179 {"zba", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1180 {"zbc", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1181 {"zbs", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1182 {"zbkb", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1183 {"zbkc", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1184 {"zbkx", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1185 {"zk", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1186 {"zkn", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1187 {"zknd", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1188 {"zkne", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1189 {"zknh", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1190 {"zkr", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1191 {"zks", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1192 {"zksed", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1193 {"zksh", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1194 {"zkt", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1195 {"zve32x", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1196 {"zve32f", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1197 {"zve32d", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1198 {"zve64x", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1199 {"zve64f", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1200 {"zve64d", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1201 {"zvl32b", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1202 {"zvl64b", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1203 {"zvl128b", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1204 {"zvl256b", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1205 {"zvl512b", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1206 {"zvl1024b", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1207 {"zvl2048b", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1208 {"zvl4096b", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1209 {"zvl8192b", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1210 {"zvl16384b", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1211 {"zvl32768b", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1212 {"zvl65536b", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1213 {"ztso", ISA_SPEC_CLASS_DRAFT, 0, 1, 0 },
1214 {NULL, 0, 0, 0, 0}
1217 static struct riscv_supported_ext riscv_supported_std_s_ext[] =
1219 {"smepmp", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1220 {"smstateen", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1221 {"sscofpmf", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1222 {"sstc", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1223 {"svinval", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1224 {"svnapot", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1225 {"svpbmt", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1226 {NULL, 0, 0, 0, 0}
1229 static struct riscv_supported_ext riscv_supported_std_zxm_ext[] =
1231 {NULL, 0, 0, 0, 0}
1234 static struct riscv_supported_ext riscv_supported_vendor_x_ext[] =
1236 {"xtheadba", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1237 {"xtheadbb", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1238 {"xtheadbs", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1239 {"xtheadcmo", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1240 {"xtheadcondmov", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1241 {"xtheadfmemidx", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1242 {"xtheadmac", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1243 {"xtheadmemidx", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1244 {"xtheadmempair", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1245 {"xtheadsync", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1246 {NULL, 0, 0, 0, 0}
1249 const struct riscv_supported_ext *riscv_all_supported_ext[] =
1251 riscv_supported_std_ext,
1252 riscv_supported_std_z_ext,
1253 riscv_supported_std_s_ext,
1254 riscv_supported_std_zxm_ext,
1255 riscv_supported_vendor_x_ext,
1256 NULL
1259 /* ISA extension prefixed name class. Must define them in parsing order. */
1260 enum riscv_prefix_ext_class
1262 RV_ISA_CLASS_Z = 1,
1263 RV_ISA_CLASS_S,
1264 RV_ISA_CLASS_ZXM,
1265 RV_ISA_CLASS_X,
1266 RV_ISA_CLASS_UNKNOWN
1269 /* Record the strings of the prefixed extensions, and their corresponding
1270 classes. The more letters of the prefix string, the more forward it must
1271 be defined. Otherwise, the riscv_get_prefix_class will map it to the
1272 wrong classes. */
1273 struct riscv_parse_prefix_config
1275 /* Class of the extension. */
1276 enum riscv_prefix_ext_class class;
1278 /* Prefix string for error printing and internal parser usage. */
1279 const char *prefix;
1281 static const struct riscv_parse_prefix_config parse_config[] =
1283 {RV_ISA_CLASS_ZXM, "zxm"},
1284 {RV_ISA_CLASS_Z, "z"},
1285 {RV_ISA_CLASS_S, "s"},
1286 {RV_ISA_CLASS_X, "x"},
1287 {RV_ISA_CLASS_UNKNOWN, NULL}
1290 /* Get the prefixed name class for the extensions, the class also
1291 means the order of the prefixed extensions. */
1293 static enum riscv_prefix_ext_class
1294 riscv_get_prefix_class (const char *arch)
1296 int i = 0;
1297 while (parse_config[i].class != RV_ISA_CLASS_UNKNOWN)
1299 if (strncmp (arch, parse_config[i].prefix,
1300 strlen (parse_config[i].prefix)) == 0)
1301 return parse_config[i].class;
1302 i++;
1304 return RV_ISA_CLASS_UNKNOWN;
1307 /* Check KNOWN_EXTS to see if the EXT is supported. */
1309 static bool
1310 riscv_known_prefixed_ext (const char *ext,
1311 struct riscv_supported_ext *known_exts)
1313 size_t i;
1314 for (i = 0; known_exts[i].name != NULL; ++i)
1315 if (strcmp (ext, known_exts[i].name) == 0)
1316 return true;
1317 return false;
1320 /* Check whether the prefixed extension is recognized or not. Return
1321 true if recognized, otehrwise return false. */
1323 static bool
1324 riscv_recognized_prefixed_ext (const char *ext)
1326 enum riscv_prefix_ext_class class = riscv_get_prefix_class (ext);
1327 switch (class)
1329 case RV_ISA_CLASS_Z:
1330 return riscv_known_prefixed_ext (ext, riscv_supported_std_z_ext);
1331 case RV_ISA_CLASS_ZXM:
1332 return riscv_known_prefixed_ext (ext, riscv_supported_std_zxm_ext);
1333 case RV_ISA_CLASS_S:
1334 return riscv_known_prefixed_ext (ext, riscv_supported_std_s_ext);
1335 case RV_ISA_CLASS_X:
1336 /* Only the single x is unrecognized. */
1337 if (strcmp (ext, "x") != 0)
1338 return true;
1339 default:
1340 break;
1342 return false;
1345 /* Canonical order for single letter extensions. */
1346 static const char riscv_ext_canonical_order[] = "eigmafdqlcbkjtpvnh";
1348 /* Array is used to compare the orders of standard extensions quickly. */
1349 static int riscv_ext_order[26] = {0};
1351 /* Init the riscv_ext_order array. */
1353 static void
1354 riscv_init_ext_order (void)
1356 static bool inited = false;
1357 if (inited)
1358 return;
1360 /* The orders of all standard extensions are positive. */
1361 int order = 1;
1363 for (const char *ext = &riscv_ext_canonical_order[0]; *ext; ++ext)
1364 riscv_ext_order[(*ext - 'a')] = order++;
1366 /* Some of the prefixed keyword are not single letter, so we set
1367 their prefixed orders in the riscv_compare_subsets directly,
1368 not through the riscv_ext_order. */
1370 inited = true;
1373 /* Similar to the strcmp. It returns an integer less than, equal to,
1374 or greater than zero if `subset2` is found, respectively, to be less
1375 than, to match, or be greater than `subset1`.
1377 The order values,
1378 Zero: Preserved keywords.
1379 Positive number: Standard extensions.
1380 Negative number: Prefixed keywords. */
1383 riscv_compare_subsets (const char *subset1, const char *subset2)
1385 int order1 = riscv_ext_order[(*subset1 - 'a')];
1386 int order2 = riscv_ext_order[(*subset2 - 'a')];
1388 /* Compare the standard extension first. */
1389 if (order1 > 0 && order2 > 0)
1390 return order1 - order2;
1392 /* Set the prefixed orders to negative numbers. */
1393 enum riscv_prefix_ext_class class1 = riscv_get_prefix_class (subset1);
1394 enum riscv_prefix_ext_class class2 = riscv_get_prefix_class (subset2);
1396 if (class1 != RV_ISA_CLASS_UNKNOWN)
1397 order1 = - (int) class1;
1398 if (class2 != RV_ISA_CLASS_UNKNOWN)
1399 order2 = - (int) class2;
1401 if (order1 == order2)
1403 /* Compare the standard addition z extensions. */
1404 if (class1 == RV_ISA_CLASS_Z)
1406 order1 = riscv_ext_order[(*++subset1 - 'a')];
1407 order2 = riscv_ext_order[(*++subset2 - 'a')];
1408 if (order1 != order2)
1409 return order1 - order2;
1411 return strcasecmp (++subset1, ++subset2);
1414 return order2 - order1;
1417 /* Find subset in the list. Return TRUE and set `current` to the subset
1418 if it is found. Otherwise, return FALSE and set `current` to the place
1419 where we should insert the subset. However, return FALSE with the NULL
1420 `current` means we should insert the subset at the head of subset list,
1421 if needed. */
1423 bool
1424 riscv_lookup_subset (const riscv_subset_list_t *subset_list,
1425 const char *subset,
1426 riscv_subset_t **current)
1428 riscv_subset_t *s, *pre_s = NULL;
1430 /* If the subset is added in order, then just add it at the tail. */
1431 if (subset_list->tail != NULL
1432 && riscv_compare_subsets (subset_list->tail->name, subset) < 0)
1434 *current = subset_list->tail;
1435 return false;
1438 for (s = subset_list->head;
1439 s != NULL;
1440 pre_s = s, s = s->next)
1442 int cmp = riscv_compare_subsets (s->name, subset);
1443 if (cmp == 0)
1445 *current = s;
1446 return true;
1448 else if (cmp > 0)
1449 break;
1451 *current = pre_s;
1453 return false;
1456 /* Add the extension to the subset list. Search the
1457 list first, and then find the right place to add. */
1459 void
1460 riscv_add_subset (riscv_subset_list_t *subset_list,
1461 const char *subset,
1462 int major,
1463 int minor)
1465 riscv_subset_t *current, *new;
1467 if (riscv_lookup_subset (subset_list, subset, &current))
1468 return;
1470 new = xmalloc (sizeof *new);
1471 new->name = xstrdup (subset);
1472 new->major_version = major;
1473 new->minor_version = minor;
1474 new->next = NULL;
1476 if (current != NULL)
1478 new->next = current->next;
1479 current->next = new;
1481 else
1483 new->next = subset_list->head;
1484 subset_list->head = new;
1487 if (new->next == NULL)
1488 subset_list->tail = new;
1491 /* Get the default versions from the riscv_supported_*ext tables. */
1493 static void
1494 riscv_get_default_ext_version (enum riscv_spec_class *default_isa_spec,
1495 const char *name,
1496 int *major_version,
1497 int *minor_version)
1499 if (name == NULL
1500 || default_isa_spec == NULL
1501 || *default_isa_spec == ISA_SPEC_CLASS_NONE)
1502 return;
1504 struct riscv_supported_ext *table = NULL;
1505 enum riscv_prefix_ext_class class = riscv_get_prefix_class (name);
1506 switch (class)
1508 case RV_ISA_CLASS_ZXM: table = riscv_supported_std_zxm_ext; break;
1509 case RV_ISA_CLASS_Z: table = riscv_supported_std_z_ext; break;
1510 case RV_ISA_CLASS_S: table = riscv_supported_std_s_ext; break;
1511 case RV_ISA_CLASS_X: table = riscv_supported_vendor_x_ext; break;
1512 default:
1513 table = riscv_supported_std_ext;
1516 int i = 0;
1517 while (table != NULL && table[i].name != NULL)
1519 if (strcmp (table[i].name, name) == 0
1520 && (table[i].isa_spec_class == ISA_SPEC_CLASS_DRAFT
1521 || table[i].isa_spec_class == *default_isa_spec))
1523 *major_version = table[i].major_version;
1524 *minor_version = table[i].minor_version;
1525 return;
1527 i++;
1531 /* Find the default versions for the extension before adding them to
1532 the subset list, if their versions are RISCV_UNKNOWN_VERSION.
1533 Afterwards, report errors if we can not find their default versions. */
1535 static void
1536 riscv_parse_add_subset (riscv_parse_subset_t *rps,
1537 const char *subset,
1538 int major,
1539 int minor,
1540 bool implicit)
1542 int major_version = major;
1543 int minor_version = minor;
1545 if (major_version == RISCV_UNKNOWN_VERSION
1546 || minor_version == RISCV_UNKNOWN_VERSION)
1547 riscv_get_default_ext_version (rps->isa_spec, subset,
1548 &major_version, &minor_version);
1550 /* We don't care the versions of the implicit extensions. */
1551 if (!implicit
1552 && (major_version == RISCV_UNKNOWN_VERSION
1553 || minor_version == RISCV_UNKNOWN_VERSION))
1555 if (subset[0] == 'x')
1556 rps->error_handler
1557 (_("x ISA extension `%s' must be set with the versions"),
1558 subset);
1559 /* Allow old ISA spec can recognize zicsr and zifencei. */
1560 else if (strcmp (subset, "zicsr") != 0
1561 && strcmp (subset, "zifencei") != 0)
1562 rps->error_handler
1563 (_("cannot find default versions of the ISA extension `%s'"),
1564 subset);
1565 return;
1568 riscv_add_subset (rps->subset_list, subset,
1569 major_version, minor_version);
1572 /* Release subset list. */
1574 void
1575 riscv_release_subset_list (riscv_subset_list_t *subset_list)
1577 while (subset_list->head != NULL)
1579 riscv_subset_t *next = subset_list->head->next;
1580 free ((void *)subset_list->head->name);
1581 free (subset_list->head);
1582 subset_list->head = next;
1585 subset_list->tail = NULL;
1588 /* Parsing extension version.
1590 Return Value:
1591 Points to the end of version
1593 Arguments:
1594 `p`: Curent parsing position.
1595 `major_version`: Parsed major version.
1596 `minor_version`: Parsed minor version. */
1598 static const char *
1599 riscv_parsing_subset_version (const char *p,
1600 int *major_version,
1601 int *minor_version)
1603 bool major_p = true;
1604 int version = 0;
1605 char np;
1607 *major_version = 0;
1608 *minor_version = 0;
1609 for (; *p; ++p)
1611 if (*p == 'p')
1613 np = *(p + 1);
1615 /* Might be beginning of `p` extension. */
1616 if (!ISDIGIT (np))
1617 break;
1619 *major_version = version;
1620 major_p = false;
1621 version = 0;
1623 else if (ISDIGIT (*p))
1624 version = (version * 10) + (*p - '0');
1625 else
1626 break;
1629 if (major_p)
1630 *major_version = version;
1631 else
1632 *minor_version = version;
1634 /* We can not find any version in string. */
1635 if (*major_version == 0 && *minor_version == 0)
1637 *major_version = RISCV_UNKNOWN_VERSION;
1638 *minor_version = RISCV_UNKNOWN_VERSION;
1641 return p;
1644 /* Parsing function for standard extensions.
1646 Return Value:
1647 Points to the end of extensions.
1649 Arguments:
1650 `rps`: Hooks and status for parsing extensions.
1651 `arch`: Full ISA string.
1652 `p`: Curent parsing position. */
1654 static const char *
1655 riscv_parse_std_ext (riscv_parse_subset_t *rps,
1656 const char *arch,
1657 const char *p)
1659 /* First letter must start with i, e or g. */
1660 if (*p != 'e' && *p != 'i' && *p != 'g')
1662 rps->error_handler
1663 (_("%s: first ISA extension must be `e', `i' or `g'"),
1664 arch);
1665 return NULL;
1668 while (p != NULL && *p != '\0')
1670 /* Stop when we parsed the known prefix class. */
1671 enum riscv_prefix_ext_class class = riscv_get_prefix_class (p);
1672 if (class != RV_ISA_CLASS_UNKNOWN)
1673 break;
1675 if (*p == '_')
1677 p++;
1678 continue;
1681 bool implicit = false;
1682 int major = RISCV_UNKNOWN_VERSION;
1683 int minor = RISCV_UNKNOWN_VERSION;
1684 char subset[2] = {0, 0};
1686 subset[0] = *p;
1688 /* Check if the standard extension is supported. */
1689 if (riscv_ext_order[(subset[0] - 'a')] == 0)
1691 rps->error_handler
1692 (_("%s: unknown standard ISA extension `%c'"),
1693 arch, subset[0]);
1694 return NULL;
1697 /* Checking canonical order. */
1698 if (rps->subset_list->tail != NULL
1699 && riscv_compare_subsets (rps->subset_list->tail->name, subset) > 0)
1701 rps->error_handler
1702 (_("%s: standard ISA extension `%c' is not "
1703 "in canonical order"), arch, subset[0]);
1704 return NULL;
1707 p = riscv_parsing_subset_version (++p, &major, &minor);
1708 /* Added g as an implicit extension. */
1709 if (subset[0] == 'g')
1711 implicit = true;
1712 major = RISCV_UNKNOWN_VERSION;
1713 minor = RISCV_UNKNOWN_VERSION;
1715 riscv_parse_add_subset (rps, subset, major, minor, implicit);
1718 return p;
1721 /* Parsing function for prefixed extensions.
1723 Return Value:
1724 Points to the end of extension.
1726 Arguments:
1727 `rps`: Hooks and status for parsing extensions.
1728 `arch`: Full ISA string.
1729 `p`: Curent parsing position. */
1731 static const char *
1732 riscv_parse_prefixed_ext (riscv_parse_subset_t *rps,
1733 const char *arch,
1734 const char *p)
1736 int major_version;
1737 int minor_version;
1738 enum riscv_prefix_ext_class class;
1740 while (*p)
1742 if (*p == '_')
1744 p++;
1745 continue;
1748 class = riscv_get_prefix_class (p);
1749 if (class == RV_ISA_CLASS_UNKNOWN)
1751 rps->error_handler
1752 (_("%s: unknown prefix class for the ISA extension `%s'"),
1753 arch, p);
1754 return NULL;
1757 char *subset = xstrdup (p);
1758 char *q = subset;
1759 const char *end_of_version;
1761 /* Extract the whole prefixed extension by '_'. */
1762 while (*++q != '\0' && *q != '_')
1764 /* Look forward to the first letter which is not <major>p<minor>. */
1765 bool find_any_version = false;
1766 bool find_minor_version = false;
1767 while (1)
1769 q--;
1770 if (ISDIGIT (*q))
1771 find_any_version = true;
1772 else if (find_any_version
1773 && !find_minor_version
1774 && *q == 'p'
1775 && ISDIGIT (*(q - 1)))
1776 find_minor_version = true;
1777 else
1778 break;
1780 q++;
1782 /* Check if the end of extension is 'p' or not. If yes, then
1783 the second letter from the end cannot be number. */
1784 if (*(q - 1) == 'p' && ISDIGIT (*(q - 2)))
1786 *q = '\0';
1787 rps->error_handler
1788 (_("%s: invalid prefixed ISA extension `%s' ends with <number>p"),
1789 arch, subset);
1790 free (subset);
1791 return NULL;
1794 end_of_version =
1795 riscv_parsing_subset_version (q, &major_version, &minor_version);
1796 *q = '\0';
1797 if (end_of_version == NULL)
1799 free (subset);
1800 return NULL;
1803 /* Check that the extension name is well-formed. */
1804 if (rps->check_unknown_prefixed_ext
1805 && !riscv_recognized_prefixed_ext (subset))
1807 rps->error_handler
1808 (_("%s: unknown prefixed ISA extension `%s'"),
1809 arch, subset);
1810 free (subset);
1811 return NULL;
1814 riscv_parse_add_subset (rps, subset,
1815 major_version,
1816 minor_version, false);
1817 p += end_of_version - subset;
1818 free (subset);
1820 if (*p != '\0' && *p != '_')
1822 rps->error_handler
1823 (_("%s: prefixed ISA extension must separate with _"),
1824 arch);
1825 return NULL;
1829 return p;
1832 /* Add the implicit extensions. */
1834 static void
1835 riscv_parse_add_implicit_subsets (riscv_parse_subset_t *rps)
1837 struct riscv_implicit_subset *t = riscv_implicit_subsets;
1838 for (; t->subset_name; t++)
1840 riscv_subset_t *subset = NULL;
1841 if (riscv_lookup_subset (rps->subset_list, t->subset_name, &subset)
1842 && t->check_func (t->implicit_name, subset))
1843 riscv_parse_add_subset (rps, t->implicit_name,
1844 RISCV_UNKNOWN_VERSION,
1845 RISCV_UNKNOWN_VERSION, true);
1849 /* Check extensions conflicts. */
1851 static bool
1852 riscv_parse_check_conflicts (riscv_parse_subset_t *rps)
1854 riscv_subset_t *subset = NULL;
1855 int xlen = *rps->xlen;
1856 bool no_conflict = true;
1858 if (riscv_lookup_subset (rps->subset_list, "e", &subset)
1859 && xlen > 32)
1861 rps->error_handler
1862 (_("rv%d does not support the `e' extension"), xlen);
1863 no_conflict = false;
1865 if (riscv_lookup_subset (rps->subset_list, "q", &subset)
1866 && (subset->major_version < 2 || (subset->major_version == 2
1867 && subset->minor_version < 2))
1868 && xlen < 64)
1870 rps->error_handler (_("rv%d does not support the `q' extension"), xlen);
1871 no_conflict = false;
1873 if (riscv_lookup_subset (rps->subset_list, "e", &subset)
1874 && riscv_lookup_subset (rps->subset_list, "f", &subset))
1876 rps->error_handler
1877 (_("rv32e does not support the `f' extension"));
1878 no_conflict = false;
1880 if (riscv_lookup_subset (rps->subset_list, "zfinx", &subset)
1881 && riscv_lookup_subset (rps->subset_list, "f", &subset))
1883 rps->error_handler
1884 (_("`zfinx' is conflict with the `f/d/q/zfh/zfhmin' extension"));
1885 no_conflict = false;
1888 bool support_zve = false;
1889 bool support_zvl = false;
1890 riscv_subset_t *s = rps->subset_list->head;
1891 for (; s != NULL; s = s->next)
1893 if (!support_zve
1894 && strncmp (s->name, "zve", 3) == 0)
1895 support_zve = true;
1896 if (!support_zvl
1897 && strncmp (s->name, "zvl", 3) == 0)
1898 support_zvl = true;
1899 if (support_zve && support_zvl)
1900 break;
1902 if (support_zvl && !support_zve)
1904 rps->error_handler
1905 (_("zvl*b extensions need to enable either `v' or `zve' extension"));
1906 no_conflict = false;
1909 return no_conflict;
1912 /* Set the default subset list according to the default_enable field
1913 of riscv_supported_*ext tables. */
1915 static void
1916 riscv_set_default_arch (riscv_parse_subset_t *rps)
1918 unsigned long enable = EXT_DEFAULT;
1919 int i, j;
1920 for (i = 0; riscv_all_supported_ext[i] != NULL; i++)
1922 const struct riscv_supported_ext *table = riscv_all_supported_ext[i];
1923 for (j = 0; table[j].name != NULL; j++)
1925 bool implicit = false;
1926 if (strcmp (table[j].name, "g") == 0)
1927 implicit = true;
1928 if (table[j].default_enable & enable)
1929 riscv_parse_add_subset (rps, table[j].name,
1930 RISCV_UNKNOWN_VERSION,
1931 RISCV_UNKNOWN_VERSION, implicit);
1936 /* Function for parsing ISA string.
1938 Return Value:
1939 Return TRUE on success.
1941 Arguments:
1942 `rps`: Hooks and status for parsing extensions.
1943 `arch`: Full ISA string. */
1945 bool
1946 riscv_parse_subset (riscv_parse_subset_t *rps,
1947 const char *arch)
1949 const char *p;
1951 /* Init the riscv_ext_order array to compare the order of extensions
1952 quickly. */
1953 riscv_init_ext_order ();
1955 if (arch == NULL)
1957 riscv_set_default_arch (rps);
1958 riscv_parse_add_implicit_subsets (rps);
1959 return riscv_parse_check_conflicts (rps);
1962 for (p = arch; *p != '\0'; p++)
1964 if (ISUPPER (*p))
1966 rps->error_handler
1967 (_("%s: ISA string cannot contain uppercase letters"),
1968 arch);
1969 return false;
1973 p = arch;
1974 if (startswith (p, "rv32"))
1976 *rps->xlen = 32;
1977 p += 4;
1979 else if (startswith (p, "rv64"))
1981 *rps->xlen = 64;
1982 p += 4;
1984 else
1986 /* ISA string shouldn't be NULL or empty here. For linker,
1987 it might be empty when we failed to merge the ISA string
1988 in the riscv_merge_attributes. For assembler, we might
1989 give an empty string by .attribute arch, "" or -march=.
1990 However, We have already issued the correct error message
1991 in another side, so do not issue this error when the ISA
1992 string is empty. */
1993 if (strlen (arch))
1994 rps->error_handler (
1995 _("%s: ISA string must begin with rv32 or rv64"),
1996 arch);
1997 return false;
2000 /* Parsing standard extension. */
2001 p = riscv_parse_std_ext (rps, arch, p);
2003 if (p == NULL)
2004 return false;
2006 /* Parse prefixed extensions. */
2007 p = riscv_parse_prefixed_ext (rps, arch, p);
2009 if (p == NULL)
2010 return false;
2012 /* Finally add implicit extensions according to the current
2013 extensions. */
2014 riscv_parse_add_implicit_subsets (rps);
2016 /* Check the conflicts. */
2017 return riscv_parse_check_conflicts (rps);
2020 /* Return the number of digits for the input. */
2022 size_t
2023 riscv_estimate_digit (unsigned num)
2025 size_t digit = 0;
2026 if (num == 0)
2027 return 1;
2029 for (digit = 0; num ; num /= 10)
2030 digit++;
2032 return digit;
2035 /* Auxiliary function to estimate string length of subset list. */
2037 static size_t
2038 riscv_estimate_arch_strlen1 (const riscv_subset_t *subset)
2040 if (subset == NULL)
2041 return 6; /* For rv32/rv64/rv128 and string terminator. */
2043 return riscv_estimate_arch_strlen1 (subset->next)
2044 + strlen (subset->name)
2045 + riscv_estimate_digit (subset->major_version)
2046 + 1 /* For version seperator 'p'. */
2047 + riscv_estimate_digit (subset->minor_version)
2048 + 1 /* For underscore. */;
2051 /* Estimate the string length of this subset list. */
2053 static size_t
2054 riscv_estimate_arch_strlen (const riscv_subset_list_t *subset_list)
2056 return riscv_estimate_arch_strlen1 (subset_list->head);
2059 /* Auxiliary function to convert subset info to string. */
2061 static void
2062 riscv_arch_str1 (riscv_subset_t *subset,
2063 char *attr_str, char *buf, size_t bufsz)
2065 const char *underline = "_";
2066 riscv_subset_t *subset_t = subset;
2068 if (subset_t == NULL)
2069 return;
2071 /* No underline between rvXX and i/e. */
2072 if ((strcasecmp (subset_t->name, "i") == 0)
2073 || (strcasecmp (subset_t->name, "e") == 0))
2074 underline = "";
2076 snprintf (buf, bufsz, "%s%s%dp%d",
2077 underline,
2078 subset_t->name,
2079 subset_t->major_version,
2080 subset_t->minor_version);
2082 strncat (attr_str, buf, bufsz);
2084 /* Skip 'i' extension after 'e', or skip extensions which
2085 versions are unknown. */
2086 while (subset_t->next
2087 && ((strcmp (subset_t->name, "e") == 0
2088 && strcmp (subset_t->next->name, "i") == 0)
2089 || subset_t->next->major_version == RISCV_UNKNOWN_VERSION
2090 || subset_t->next->minor_version == RISCV_UNKNOWN_VERSION))
2091 subset_t = subset_t->next;
2093 riscv_arch_str1 (subset_t->next, attr_str, buf, bufsz);
2096 /* Convert subset information into string with explicit versions. */
2098 char *
2099 riscv_arch_str (unsigned xlen, const riscv_subset_list_t *subset)
2101 size_t arch_str_len = riscv_estimate_arch_strlen (subset);
2102 char *attr_str = xmalloc (arch_str_len);
2103 char *buf = xmalloc (arch_str_len);
2105 snprintf (attr_str, arch_str_len, "rv%u", xlen);
2107 riscv_arch_str1 (subset->head, attr_str, buf, arch_str_len);
2108 free (buf);
2110 return attr_str;
2113 /* Copy the subset in the subset list. */
2115 static struct riscv_subset_t *
2116 riscv_copy_subset (riscv_subset_list_t *subset_list,
2117 riscv_subset_t *subset)
2119 if (subset == NULL)
2120 return NULL;
2122 riscv_subset_t *new = xmalloc (sizeof *new);
2123 new->name = xstrdup (subset->name);
2124 new->major_version = subset->major_version;
2125 new->minor_version = subset->minor_version;
2126 new->next = riscv_copy_subset (subset_list, subset->next);
2128 if (subset->next == NULL)
2129 subset_list->tail = new;
2131 return new;
2134 /* Copy the subset list. */
2136 riscv_subset_list_t *
2137 riscv_copy_subset_list (riscv_subset_list_t *subset_list)
2139 riscv_subset_list_t *new = xmalloc (sizeof *new);
2140 new->head = riscv_copy_subset (new, subset_list->head);
2141 return new;
2144 /* Remove the SUBSET from the subset list. */
2146 static void
2147 riscv_remove_subset (riscv_subset_list_t *subset_list,
2148 const char *subset)
2150 riscv_subset_t *current = subset_list->head;
2151 riscv_subset_t *pre = NULL;
2152 for (; current != NULL; pre = current, current = current->next)
2154 if (strcmp (current->name, subset) == 0)
2156 if (pre == NULL)
2157 subset_list->head = current->next;
2158 else
2159 pre->next = current->next;
2160 if (current->next == NULL)
2161 subset_list->tail = pre;
2162 free ((void *) current->name);
2163 free (current);
2164 break;
2169 /* Add/Remove an extension to/from the subset list. This is used for
2170 the .option rvc or norvc, and .option arch directives. */
2172 bool
2173 riscv_update_subset (riscv_parse_subset_t *rps,
2174 const char *str)
2176 const char *p = str;
2180 int major_version = RISCV_UNKNOWN_VERSION;
2181 int minor_version = RISCV_UNKNOWN_VERSION;
2183 bool removed = false;
2184 switch (*p)
2186 case '+': removed = false; break;
2187 case '-': removed = true; break;
2188 default:
2189 riscv_release_subset_list (rps->subset_list);
2190 return riscv_parse_subset (rps, p);
2192 ++p;
2194 char *subset = xstrdup (p);
2195 char *q = subset;
2196 const char *end_of_version;
2197 /* Extract the whole prefixed extension by ','. */
2198 while (*q != '\0' && *q != ',')
2199 q++;
2201 /* Look forward to the first letter which is not <major>p<minor>. */
2202 bool find_any_version = false;
2203 bool find_minor_version = false;
2204 size_t len = q - subset;
2205 size_t i;
2206 for (i = len; i > 0; i--)
2208 q--;
2209 if (ISDIGIT (*q))
2210 find_any_version = true;
2211 else if (find_any_version
2212 && !find_minor_version
2213 && *q == 'p'
2214 && ISDIGIT (*(q - 1)))
2215 find_minor_version = true;
2216 else
2217 break;
2219 if (len > 0)
2220 q++;
2222 /* Check if the end of extension is 'p' or not. If yes, then
2223 the second letter from the end cannot be number. */
2224 if (len > 1 && *(q - 1) == 'p' && ISDIGIT (*(q - 2)))
2226 *q = '\0';
2227 rps->error_handler
2228 (_("invalid ISA extension ends with <number>p "
2229 "in .option arch `%s'"), str);
2230 free (subset);
2231 return false;
2234 end_of_version =
2235 riscv_parsing_subset_version (q, &major_version, &minor_version);
2236 *q = '\0';
2237 if (end_of_version == NULL)
2239 free (subset);
2240 return false;
2243 if (strlen (subset) == 0
2244 || (strlen (subset) == 1
2245 && riscv_ext_order[(*subset - 'a')] == 0)
2246 || (strlen (subset) > 1
2247 && rps->check_unknown_prefixed_ext
2248 && !riscv_recognized_prefixed_ext (subset)))
2250 rps->error_handler
2251 (_("unknown ISA extension `%s' in .option arch `%s'"),
2252 subset, str);
2253 free (subset);
2254 return false;
2257 if (strcmp (subset, "i") == 0
2258 || strcmp (subset, "e") == 0
2259 || strcmp (subset, "g") == 0)
2261 rps->error_handler
2262 (_("cannot + or - base extension `%s' in .option "
2263 "arch `%s'"), subset, str);
2264 free (subset);
2265 return false;
2268 if (removed)
2269 riscv_remove_subset (rps->subset_list, subset);
2270 else
2271 riscv_parse_add_subset (rps, subset, major_version, minor_version, true);
2272 p += end_of_version - subset;
2273 free (subset);
2275 while (*p++ == ',');
2277 riscv_parse_add_implicit_subsets (rps);
2278 return riscv_parse_check_conflicts (rps);
2281 /* Check if the FEATURE subset is supported or not in the subset list.
2282 Return true if it is supported; Otherwise, return false. */
2284 bool
2285 riscv_subset_supports (riscv_parse_subset_t *rps,
2286 const char *feature)
2288 struct riscv_subset_t *subset;
2289 return riscv_lookup_subset (rps->subset_list, feature, &subset);
2292 /* Each instuction is belonged to an instruction class INSN_CLASS_*.
2293 Call riscv_subset_supports to make sure if the instuction is valid. */
2295 bool
2296 riscv_multi_subset_supports (riscv_parse_subset_t *rps,
2297 enum riscv_insn_class insn_class)
2299 switch (insn_class)
2301 case INSN_CLASS_I:
2302 return riscv_subset_supports (rps, "i");
2303 case INSN_CLASS_ZICBOM:
2304 return riscv_subset_supports (rps, "zicbom");
2305 case INSN_CLASS_ZICBOP:
2306 return riscv_subset_supports (rps, "zicbop");
2307 case INSN_CLASS_ZICBOZ:
2308 return riscv_subset_supports (rps, "zicboz");
2309 case INSN_CLASS_ZICSR:
2310 return riscv_subset_supports (rps, "zicsr");
2311 case INSN_CLASS_ZIFENCEI:
2312 return riscv_subset_supports (rps, "zifencei");
2313 case INSN_CLASS_ZIHINTPAUSE:
2314 return riscv_subset_supports (rps, "zihintpause");
2315 case INSN_CLASS_M:
2316 return riscv_subset_supports (rps, "m");
2317 case INSN_CLASS_ZMMUL:
2318 return riscv_subset_supports (rps, "zmmul");
2319 case INSN_CLASS_A:
2320 return riscv_subset_supports (rps, "a");
2321 case INSN_CLASS_ZAWRS:
2322 return riscv_subset_supports (rps, "zawrs");
2323 case INSN_CLASS_F:
2324 return riscv_subset_supports (rps, "f");
2325 case INSN_CLASS_D:
2326 return riscv_subset_supports (rps, "d");
2327 case INSN_CLASS_Q:
2328 return riscv_subset_supports (rps, "q");
2329 case INSN_CLASS_C:
2330 return riscv_subset_supports (rps, "c");
2331 case INSN_CLASS_F_AND_C:
2332 return (riscv_subset_supports (rps, "f")
2333 && riscv_subset_supports (rps, "c"));
2334 case INSN_CLASS_D_AND_C:
2335 return (riscv_subset_supports (rps, "d")
2336 && riscv_subset_supports (rps, "c"));
2337 case INSN_CLASS_F_INX:
2338 return (riscv_subset_supports (rps, "f")
2339 || riscv_subset_supports (rps, "zfinx"));
2340 case INSN_CLASS_D_INX:
2341 return (riscv_subset_supports (rps, "d")
2342 || riscv_subset_supports (rps, "zdinx"));
2343 case INSN_CLASS_Q_INX:
2344 return (riscv_subset_supports (rps, "q")
2345 || riscv_subset_supports (rps, "zqinx"));
2346 case INSN_CLASS_ZFH_INX:
2347 return (riscv_subset_supports (rps, "zfh")
2348 || riscv_subset_supports (rps, "zhinx"));
2349 case INSN_CLASS_ZFHMIN:
2350 return riscv_subset_supports (rps, "zfhmin");
2351 case INSN_CLASS_ZFHMIN_INX:
2352 return (riscv_subset_supports (rps, "zfhmin")
2353 || riscv_subset_supports (rps, "zhinxmin"));
2354 case INSN_CLASS_ZFHMIN_AND_D_INX:
2355 return ((riscv_subset_supports (rps, "zfhmin")
2356 && riscv_subset_supports (rps, "d"))
2357 || (riscv_subset_supports (rps, "zhinxmin")
2358 && riscv_subset_supports (rps, "zdinx")));
2359 case INSN_CLASS_ZFHMIN_AND_Q_INX:
2360 return ((riscv_subset_supports (rps, "zfhmin")
2361 && riscv_subset_supports (rps, "q"))
2362 || (riscv_subset_supports (rps, "zhinxmin")
2363 && riscv_subset_supports (rps, "zqinx")));
2364 case INSN_CLASS_ZBA:
2365 return riscv_subset_supports (rps, "zba");
2366 case INSN_CLASS_ZBB:
2367 return riscv_subset_supports (rps, "zbb");
2368 case INSN_CLASS_ZBC:
2369 return riscv_subset_supports (rps, "zbc");
2370 case INSN_CLASS_ZBS:
2371 return riscv_subset_supports (rps, "zbs");
2372 case INSN_CLASS_ZBKB:
2373 return riscv_subset_supports (rps, "zbkb");
2374 case INSN_CLASS_ZBKC:
2375 return riscv_subset_supports (rps, "zbkc");
2376 case INSN_CLASS_ZBKX:
2377 return riscv_subset_supports (rps, "zbkx");
2378 case INSN_CLASS_ZBB_OR_ZBKB:
2379 return (riscv_subset_supports (rps, "zbb")
2380 || riscv_subset_supports (rps, "zbkb"));
2381 case INSN_CLASS_ZBC_OR_ZBKC:
2382 return (riscv_subset_supports (rps, "zbc")
2383 || riscv_subset_supports (rps, "zbkc"));
2384 case INSN_CLASS_ZKND:
2385 return riscv_subset_supports (rps, "zknd");
2386 case INSN_CLASS_ZKNE:
2387 return riscv_subset_supports (rps, "zkne");
2388 case INSN_CLASS_ZKNH:
2389 return riscv_subset_supports (rps, "zknh");
2390 case INSN_CLASS_ZKND_OR_ZKNE:
2391 return (riscv_subset_supports (rps, "zknd")
2392 || riscv_subset_supports (rps, "zkne"));
2393 case INSN_CLASS_ZKSED:
2394 return riscv_subset_supports (rps, "zksed");
2395 case INSN_CLASS_ZKSH:
2396 return riscv_subset_supports (rps, "zksh");
2397 case INSN_CLASS_V:
2398 return (riscv_subset_supports (rps, "v")
2399 || riscv_subset_supports (rps, "zve64x")
2400 || riscv_subset_supports (rps, "zve32x"));
2401 case INSN_CLASS_ZVEF:
2402 return (riscv_subset_supports (rps, "v")
2403 || riscv_subset_supports (rps, "zve64d")
2404 || riscv_subset_supports (rps, "zve64f")
2405 || riscv_subset_supports (rps, "zve32f"));
2406 case INSN_CLASS_SVINVAL:
2407 return riscv_subset_supports (rps, "svinval");
2408 case INSN_CLASS_H:
2409 return riscv_subset_supports (rps, "h");
2410 case INSN_CLASS_XTHEADBA:
2411 return riscv_subset_supports (rps, "xtheadba");
2412 case INSN_CLASS_XTHEADBB:
2413 return riscv_subset_supports (rps, "xtheadbb");
2414 case INSN_CLASS_XTHEADBS:
2415 return riscv_subset_supports (rps, "xtheadbs");
2416 case INSN_CLASS_XTHEADCMO:
2417 return riscv_subset_supports (rps, "xtheadcmo");
2418 case INSN_CLASS_XTHEADCONDMOV:
2419 return riscv_subset_supports (rps, "xtheadcondmov");
2420 case INSN_CLASS_XTHEADFMEMIDX:
2421 return riscv_subset_supports (rps, "xtheadfmemidx");
2422 case INSN_CLASS_XTHEADMAC:
2423 return riscv_subset_supports (rps, "xtheadmac");
2424 case INSN_CLASS_XTHEADMEMIDX:
2425 return riscv_subset_supports (rps, "xtheadmemidx");
2426 case INSN_CLASS_XTHEADMEMPAIR:
2427 return riscv_subset_supports (rps, "xtheadmempair");
2428 case INSN_CLASS_XTHEADSYNC:
2429 return riscv_subset_supports (rps, "xtheadsync");
2430 default:
2431 rps->error_handler
2432 (_("internal: unreachable INSN_CLASS_*"));
2433 return false;
2437 /* Each instuction is belonged to an instruction class INSN_CLASS_*.
2438 Call riscv_subset_supports_ext to determine the missing extension. */
2440 const char *
2441 riscv_multi_subset_supports_ext (riscv_parse_subset_t *rps,
2442 enum riscv_insn_class insn_class)
2444 switch (insn_class)
2446 case INSN_CLASS_I:
2447 return "i";
2448 case INSN_CLASS_ZICBOM:
2449 return "zicbom";
2450 case INSN_CLASS_ZICBOP:
2451 return "zicbop";
2452 case INSN_CLASS_ZICBOZ:
2453 return "zicboz";
2454 case INSN_CLASS_ZICSR:
2455 return "zicsr";
2456 case INSN_CLASS_ZIFENCEI:
2457 return "zifencei";
2458 case INSN_CLASS_ZIHINTPAUSE:
2459 return "zihintpause";
2460 case INSN_CLASS_M:
2461 return "m";
2462 case INSN_CLASS_ZMMUL:
2463 return _ ("m' or `zmmul");
2464 case INSN_CLASS_A:
2465 return "a";
2466 case INSN_CLASS_ZAWRS:
2467 return "zawrs";
2468 case INSN_CLASS_F:
2469 return "f";
2470 case INSN_CLASS_D:
2471 return "d";
2472 case INSN_CLASS_Q:
2473 return "q";
2474 case INSN_CLASS_C:
2475 return "c";
2476 case INSN_CLASS_F_AND_C:
2477 if (!riscv_subset_supports (rps, "f")
2478 && !riscv_subset_supports (rps, "c"))
2479 return _("f' and `c");
2480 else if (!riscv_subset_supports (rps, "f"))
2481 return "f";
2482 else
2483 return "c";
2484 case INSN_CLASS_D_AND_C:
2485 if (!riscv_subset_supports (rps, "d")
2486 && !riscv_subset_supports (rps, "c"))
2487 return _("d' and `c");
2488 else if (!riscv_subset_supports (rps, "d"))
2489 return "d";
2490 else
2491 return "c";
2492 case INSN_CLASS_F_INX:
2493 return _("f' or `zfinx");
2494 case INSN_CLASS_D_INX:
2495 return _("d' or `zdinx");
2496 case INSN_CLASS_Q_INX:
2497 return _("q' or `zqinx");
2498 case INSN_CLASS_ZFH_INX:
2499 return _("zfh' or `zhinx");
2500 case INSN_CLASS_ZFHMIN:
2501 return "zfhmin";
2502 case INSN_CLASS_ZFHMIN_INX:
2503 return _("zfhmin' or `zhinxmin");
2504 case INSN_CLASS_ZFHMIN_AND_D_INX:
2505 if (riscv_subset_supports (rps, "zfhmin"))
2506 return "d";
2507 else if (riscv_subset_supports (rps, "d"))
2508 return "zfhmin";
2509 else if (riscv_subset_supports (rps, "zhinxmin"))
2510 return "zdinx";
2511 else if (riscv_subset_supports (rps, "zdinx"))
2512 return "zhinxmin";
2513 else
2514 return _("zfhmin' and `d', or `zhinxmin' and `zdinx");
2515 case INSN_CLASS_ZFHMIN_AND_Q_INX:
2516 if (riscv_subset_supports (rps, "zfhmin"))
2517 return "q";
2518 else if (riscv_subset_supports (rps, "q"))
2519 return "zfhmin";
2520 else if (riscv_subset_supports (rps, "zhinxmin"))
2521 return "zqinx";
2522 else if (riscv_subset_supports (rps, "zqinx"))
2523 return "zhinxmin";
2524 else
2525 return _("zfhmin' and `q', or `zhinxmin' and `zqinx");
2526 case INSN_CLASS_ZBA:
2527 return "zba";
2528 case INSN_CLASS_ZBB:
2529 return "zbb";
2530 case INSN_CLASS_ZBC:
2531 return "zbc";
2532 case INSN_CLASS_ZBS:
2533 return "zbs";
2534 case INSN_CLASS_ZBKB:
2535 return "zbkb";
2536 case INSN_CLASS_ZBKC:
2537 return "zbkc";
2538 case INSN_CLASS_ZBKX:
2539 return "zbkx";
2540 case INSN_CLASS_ZBB_OR_ZBKB:
2541 return _("zbb' or `zbkb");
2542 case INSN_CLASS_ZBC_OR_ZBKC:
2543 return _("zbc' or `zbkc");
2544 case INSN_CLASS_ZKND:
2545 return "zknd";
2546 case INSN_CLASS_ZKNE:
2547 return "zkne";
2548 case INSN_CLASS_ZKNH:
2549 return "zknh";
2550 case INSN_CLASS_ZKND_OR_ZKNE:
2551 return _("zknd' or `zkne");
2552 case INSN_CLASS_ZKSED:
2553 return "zksed";
2554 case INSN_CLASS_ZKSH:
2555 return "zksh";
2556 case INSN_CLASS_V:
2557 return _("v' or `zve64x' or `zve32x");
2558 case INSN_CLASS_ZVEF:
2559 return _("v' or `zve64d' or `zve64f' or `zve32f");
2560 case INSN_CLASS_SVINVAL:
2561 return "svinval";
2562 case INSN_CLASS_H:
2563 return _("h");
2564 case INSN_CLASS_XTHEADBA:
2565 return "xtheadba";
2566 case INSN_CLASS_XTHEADBB:
2567 return "xtheadbb";
2568 case INSN_CLASS_XTHEADBS:
2569 return "xtheadbs";
2570 case INSN_CLASS_XTHEADCMO:
2571 return "xtheadcmo";
2572 case INSN_CLASS_XTHEADCONDMOV:
2573 return "xtheadcondmov";
2574 case INSN_CLASS_XTHEADFMEMIDX:
2575 return "xtheadfmemidx";
2576 case INSN_CLASS_XTHEADMAC:
2577 return "xtheadmac";
2578 case INSN_CLASS_XTHEADMEMIDX:
2579 return "xtheadmemidx";
2580 case INSN_CLASS_XTHEADMEMPAIR:
2581 return "xtheadmempair";
2582 case INSN_CLASS_XTHEADSYNC:
2583 return "xtheadsync";
2584 default:
2585 rps->error_handler
2586 (_("internal: unreachable INSN_CLASS_*"));
2587 return NULL;