RISC-V: Update Zihintpause extension version
[binutils-gdb.git] / bfd / elfxx-riscv.c
1 /* RISC-V-specific support for ELF.
2 Copyright (C) 2011-2022 Free Software Foundation, Inc.
3
4 Contributed by Andrew Waterman (andrew@sifive.com).
5 Based on TILE-Gx and MIPS targets.
6
7 This file is part of BFD, the Binary File Descriptor library.
8
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.
13
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.
18
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/>. */
22
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"
32
33 #define MINUS_ONE ((bfd_vma)0 - 1)
34
35 /* Special handler for ADD/SUB relocations that allows them to be filled out
36 both in the pre-linked and post-linked file. This is necessary to make
37 pre-linked debug info work, as due to linker relaxations we need to emit
38 relocations for the debug info. */
39 static bfd_reloc_status_type riscv_elf_add_sub_reloc
40 (bfd *, arelent *, asymbol *, void *, asection *, bfd *, char **);
41
42 /* The relocation table used for SHT_RELA sections. */
43
44 static reloc_howto_type howto_table[] =
45 {
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 */
60
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 */
75
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 */
90
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 */
105
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 */
119
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 */
133
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 */
148
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 */
162
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 */
176
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 */
190
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 */
204
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 */
218
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),
224
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 */
239
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 */
254
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 */
270
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 */
286
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 */
301
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 */
316
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 */
331
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 */
346
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 */
361
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 */
376
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 */
391
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 */
406
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 */
421
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 */
436
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 */
451
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 */
466
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 */
481
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 */
496
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 */
511
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 */
526
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 */
541
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 */
556
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 */
571
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 */
586
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 */
601
602 /* GNU extension to record C++ vtable hierarchy */
603 HOWTO (R_RISCV_GNU_VTINHERIT, /* type */
604 0, /* rightshift */
605 8, /* size */
606 0, /* bitsize */
607 false, /* pc_relative */
608 0, /* bitpos */
609 complain_overflow_dont, /* complain_on_overflow */
610 NULL, /* special_function */
611 "R_RISCV_GNU_VTINHERIT", /* name */
612 false, /* partial_inplace */
613 0, /* src_mask */
614 0, /* dst_mask */
615 false), /* pcrel_offset */
616
617 /* GNU extension to record C++ vtable member usage */
618 HOWTO (R_RISCV_GNU_VTENTRY, /* type */
619 0, /* rightshift */
620 8, /* size */
621 0, /* bitsize */
622 false, /* pc_relative */
623 0, /* bitpos */
624 complain_overflow_dont, /* complain_on_overflow */
625 _bfd_elf_rel_vtable_reloc_fn, /* special_function */
626 "R_RISCV_GNU_VTENTRY", /* name */
627 false, /* partial_inplace */
628 0, /* src_mask */
629 0, /* dst_mask */
630 false), /* pcrel_offset */
631
632 /* Indicates an alignment statement. The addend field encodes how many
633 bytes of NOPs follow the statement. The desired alignment is the
634 addend rounded up to the next power of two. */
635 HOWTO (R_RISCV_ALIGN, /* type */
636 0, /* rightshift */
637 0, /* size */
638 0, /* bitsize */
639 false, /* pc_relative */
640 0, /* bitpos */
641 complain_overflow_dont, /* complain_on_overflow */
642 bfd_elf_generic_reloc, /* special_function */
643 "R_RISCV_ALIGN", /* name */
644 false, /* partial_inplace */
645 0, /* src_mask */
646 0, /* dst_mask */
647 false), /* pcrel_offset */
648
649 /* 8-bit PC-relative branch offset. */
650 HOWTO (R_RISCV_RVC_BRANCH, /* type */
651 0, /* rightshift */
652 2, /* size */
653 16, /* bitsize */
654 true, /* pc_relative */
655 0, /* bitpos */
656 complain_overflow_signed, /* complain_on_overflow */
657 bfd_elf_generic_reloc, /* special_function */
658 "R_RISCV_RVC_BRANCH", /* name */
659 false, /* partial_inplace */
660 0, /* src_mask */
661 ENCODE_CBTYPE_IMM (-1U), /* dst_mask */
662 true), /* pcrel_offset */
663
664 /* 11-bit PC-relative jump offset. */
665 HOWTO (R_RISCV_RVC_JUMP, /* type */
666 0, /* rightshift */
667 2, /* size */
668 16, /* bitsize */
669 true, /* pc_relative */
670 0, /* bitpos */
671 complain_overflow_dont, /* complain_on_overflow */
672 bfd_elf_generic_reloc, /* special_function */
673 "R_RISCV_RVC_JUMP", /* name */
674 false, /* partial_inplace */
675 0, /* src_mask */
676 ENCODE_CJTYPE_IMM (-1U), /* dst_mask */
677 true), /* pcrel_offset */
678
679 /* High 6 bits of 18-bit absolute address. */
680 HOWTO (R_RISCV_RVC_LUI, /* type */
681 0, /* rightshift */
682 2, /* size */
683 16, /* bitsize */
684 false, /* pc_relative */
685 0, /* bitpos */
686 complain_overflow_dont, /* complain_on_overflow */
687 bfd_elf_generic_reloc, /* special_function */
688 "R_RISCV_RVC_LUI", /* name */
689 false, /* partial_inplace */
690 0, /* src_mask */
691 ENCODE_CITYPE_IMM (-1U), /* dst_mask */
692 false), /* pcrel_offset */
693
694 /* GP-relative load. */
695 HOWTO (R_RISCV_GPREL_I, /* type */
696 0, /* rightshift */
697 4, /* size */
698 32, /* bitsize */
699 false, /* pc_relative */
700 0, /* bitpos */
701 complain_overflow_dont, /* complain_on_overflow */
702 bfd_elf_generic_reloc, /* special_function */
703 "R_RISCV_GPREL_I", /* name */
704 false, /* partial_inplace */
705 0, /* src_mask */
706 ENCODE_ITYPE_IMM (-1U), /* dst_mask */
707 false), /* pcrel_offset */
708
709 /* GP-relative store. */
710 HOWTO (R_RISCV_GPREL_S, /* type */
711 0, /* rightshift */
712 4, /* size */
713 32, /* bitsize */
714 false, /* pc_relative */
715 0, /* bitpos */
716 complain_overflow_dont, /* complain_on_overflow */
717 bfd_elf_generic_reloc, /* special_function */
718 "R_RISCV_GPREL_S", /* name */
719 false, /* partial_inplace */
720 0, /* src_mask */
721 ENCODE_STYPE_IMM (-1U), /* dst_mask */
722 false), /* pcrel_offset */
723
724 /* TP-relative TLS LE load. */
725 HOWTO (R_RISCV_TPREL_I, /* type */
726 0, /* rightshift */
727 4, /* size */
728 32, /* bitsize */
729 false, /* pc_relative */
730 0, /* bitpos */
731 complain_overflow_signed, /* complain_on_overflow */
732 bfd_elf_generic_reloc, /* special_function */
733 "R_RISCV_TPREL_I", /* name */
734 false, /* partial_inplace */
735 0, /* src_mask */
736 ENCODE_ITYPE_IMM (-1U), /* dst_mask */
737 false), /* pcrel_offset */
738
739 /* TP-relative TLS LE store. */
740 HOWTO (R_RISCV_TPREL_S, /* type */
741 0, /* rightshift */
742 4, /* size */
743 32, /* bitsize */
744 false, /* pc_relative */
745 0, /* bitpos */
746 complain_overflow_signed, /* complain_on_overflow */
747 bfd_elf_generic_reloc, /* special_function */
748 "R_RISCV_TPREL_S", /* name */
749 false, /* partial_inplace */
750 0, /* src_mask */
751 ENCODE_STYPE_IMM (-1U), /* dst_mask */
752 false), /* pcrel_offset */
753
754 /* The paired relocation may be relaxed. */
755 HOWTO (R_RISCV_RELAX, /* type */
756 0, /* rightshift */
757 0, /* size */
758 0, /* bitsize */
759 false, /* pc_relative */
760 0, /* bitpos */
761 complain_overflow_dont, /* complain_on_overflow */
762 bfd_elf_generic_reloc, /* special_function */
763 "R_RISCV_RELAX", /* name */
764 false, /* partial_inplace */
765 0, /* src_mask */
766 0, /* dst_mask */
767 false), /* pcrel_offset */
768
769 /* 6-bit in-place addition, for local label subtraction. */
770 HOWTO (R_RISCV_SUB6, /* type */
771 0, /* rightshift */
772 1, /* size */
773 8, /* bitsize */
774 false, /* pc_relative */
775 0, /* bitpos */
776 complain_overflow_dont, /* complain_on_overflow */
777 riscv_elf_add_sub_reloc, /* special_function */
778 "R_RISCV_SUB6", /* name */
779 false, /* partial_inplace */
780 0, /* src_mask */
781 0x3f, /* dst_mask */
782 false), /* pcrel_offset */
783
784 /* 6-bit in-place setting, for local label subtraction. */
785 HOWTO (R_RISCV_SET6, /* type */
786 0, /* rightshift */
787 1, /* size */
788 8, /* bitsize */
789 false, /* pc_relative */
790 0, /* bitpos */
791 complain_overflow_dont, /* complain_on_overflow */
792 bfd_elf_generic_reloc, /* special_function */
793 "R_RISCV_SET6", /* name */
794 false, /* partial_inplace */
795 0, /* src_mask */
796 0x3f, /* dst_mask */
797 false), /* pcrel_offset */
798
799 /* 8-bit in-place setting, for local label subtraction. */
800 HOWTO (R_RISCV_SET8, /* type */
801 0, /* rightshift */
802 1, /* size */
803 8, /* bitsize */
804 false, /* pc_relative */
805 0, /* bitpos */
806 complain_overflow_dont, /* complain_on_overflow */
807 bfd_elf_generic_reloc, /* special_function */
808 "R_RISCV_SET8", /* name */
809 false, /* partial_inplace */
810 0, /* src_mask */
811 0xff, /* dst_mask */
812 false), /* pcrel_offset */
813
814 /* 16-bit in-place setting, for local label subtraction. */
815 HOWTO (R_RISCV_SET16, /* type */
816 0, /* rightshift */
817 2, /* size */
818 16, /* bitsize */
819 false, /* pc_relative */
820 0, /* bitpos */
821 complain_overflow_dont, /* complain_on_overflow */
822 bfd_elf_generic_reloc, /* special_function */
823 "R_RISCV_SET16", /* name */
824 false, /* partial_inplace */
825 0, /* src_mask */
826 0xffff, /* dst_mask */
827 false), /* pcrel_offset */
828
829 /* 32-bit in-place setting, for local label subtraction. */
830 HOWTO (R_RISCV_SET32, /* type */
831 0, /* rightshift */
832 4, /* size */
833 32, /* bitsize */
834 false, /* pc_relative */
835 0, /* bitpos */
836 complain_overflow_dont, /* complain_on_overflow */
837 bfd_elf_generic_reloc, /* special_function */
838 "R_RISCV_SET32", /* name */
839 false, /* partial_inplace */
840 0, /* src_mask */
841 0xffffffff, /* dst_mask */
842 false), /* pcrel_offset */
843
844 /* 32-bit PC relative. */
845 HOWTO (R_RISCV_32_PCREL, /* type */
846 0, /* rightshift */
847 4, /* size */
848 32, /* bitsize */
849 true, /* pc_relative */
850 0, /* bitpos */
851 complain_overflow_dont, /* complain_on_overflow */
852 bfd_elf_generic_reloc, /* special_function */
853 "R_RISCV_32_PCREL", /* name */
854 false, /* partial_inplace */
855 0, /* src_mask */
856 0xffffffff, /* dst_mask */
857 false), /* pcrel_offset */
858
859 /* Relocation against a local ifunc symbol in a shared object. */
860 HOWTO (R_RISCV_IRELATIVE, /* type */
861 0, /* rightshift */
862 4, /* size */
863 32, /* bitsize */
864 false, /* pc_relative */
865 0, /* bitpos */
866 complain_overflow_dont, /* complain_on_overflow */
867 bfd_elf_generic_reloc, /* special_function */
868 "R_RISCV_IRELATIVE", /* name */
869 false, /* partial_inplace */
870 0, /* src_mask */
871 0xffffffff, /* dst_mask */
872 false), /* pcrel_offset */
873 };
874
875 /* A mapping from BFD reloc types to RISC-V ELF reloc types. */
876 struct elf_reloc_map
877 {
878 bfd_reloc_code_real_type bfd_val;
879 enum elf_riscv_reloc_type elf_val;
880 };
881
882 static const struct elf_reloc_map riscv_reloc_map[] =
883 {
884 { BFD_RELOC_NONE, R_RISCV_NONE },
885 { BFD_RELOC_32, R_RISCV_32 },
886 { BFD_RELOC_64, R_RISCV_64 },
887 { BFD_RELOC_RISCV_ADD8, R_RISCV_ADD8 },
888 { BFD_RELOC_RISCV_ADD16, R_RISCV_ADD16 },
889 { BFD_RELOC_RISCV_ADD32, R_RISCV_ADD32 },
890 { BFD_RELOC_RISCV_ADD64, R_RISCV_ADD64 },
891 { BFD_RELOC_RISCV_SUB8, R_RISCV_SUB8 },
892 { BFD_RELOC_RISCV_SUB16, R_RISCV_SUB16 },
893 { BFD_RELOC_RISCV_SUB32, R_RISCV_SUB32 },
894 { BFD_RELOC_RISCV_SUB64, R_RISCV_SUB64 },
895 { BFD_RELOC_CTOR, R_RISCV_64 },
896 { BFD_RELOC_12_PCREL, R_RISCV_BRANCH },
897 { BFD_RELOC_RISCV_HI20, R_RISCV_HI20 },
898 { BFD_RELOC_RISCV_LO12_I, R_RISCV_LO12_I },
899 { BFD_RELOC_RISCV_LO12_S, R_RISCV_LO12_S },
900 { BFD_RELOC_RISCV_PCREL_LO12_I, R_RISCV_PCREL_LO12_I },
901 { BFD_RELOC_RISCV_PCREL_LO12_S, R_RISCV_PCREL_LO12_S },
902 { BFD_RELOC_RISCV_CALL, R_RISCV_CALL },
903 { BFD_RELOC_RISCV_CALL_PLT, R_RISCV_CALL_PLT },
904 { BFD_RELOC_RISCV_PCREL_HI20, R_RISCV_PCREL_HI20 },
905 { BFD_RELOC_RISCV_JMP, R_RISCV_JAL },
906 { BFD_RELOC_RISCV_GOT_HI20, R_RISCV_GOT_HI20 },
907 { BFD_RELOC_RISCV_TLS_DTPMOD32, R_RISCV_TLS_DTPMOD32 },
908 { BFD_RELOC_RISCV_TLS_DTPREL32, R_RISCV_TLS_DTPREL32 },
909 { BFD_RELOC_RISCV_TLS_DTPMOD64, R_RISCV_TLS_DTPMOD64 },
910 { BFD_RELOC_RISCV_TLS_DTPREL64, R_RISCV_TLS_DTPREL64 },
911 { BFD_RELOC_RISCV_TLS_TPREL32, R_RISCV_TLS_TPREL32 },
912 { BFD_RELOC_RISCV_TLS_TPREL64, R_RISCV_TLS_TPREL64 },
913 { BFD_RELOC_RISCV_TPREL_HI20, R_RISCV_TPREL_HI20 },
914 { BFD_RELOC_RISCV_TPREL_ADD, R_RISCV_TPREL_ADD },
915 { BFD_RELOC_RISCV_TPREL_LO12_S, R_RISCV_TPREL_LO12_S },
916 { BFD_RELOC_RISCV_TPREL_LO12_I, R_RISCV_TPREL_LO12_I },
917 { BFD_RELOC_RISCV_TLS_GOT_HI20, R_RISCV_TLS_GOT_HI20 },
918 { BFD_RELOC_RISCV_TLS_GD_HI20, R_RISCV_TLS_GD_HI20 },
919 { BFD_RELOC_RISCV_ALIGN, R_RISCV_ALIGN },
920 { BFD_RELOC_RISCV_RVC_BRANCH, R_RISCV_RVC_BRANCH },
921 { BFD_RELOC_RISCV_RVC_JUMP, R_RISCV_RVC_JUMP },
922 { BFD_RELOC_RISCV_RVC_LUI, R_RISCV_RVC_LUI },
923 { BFD_RELOC_RISCV_GPREL_I, R_RISCV_GPREL_I },
924 { BFD_RELOC_RISCV_GPREL_S, R_RISCV_GPREL_S },
925 { BFD_RELOC_RISCV_TPREL_I, R_RISCV_TPREL_I },
926 { BFD_RELOC_RISCV_TPREL_S, R_RISCV_TPREL_S },
927 { BFD_RELOC_RISCV_RELAX, R_RISCV_RELAX },
928 { BFD_RELOC_RISCV_SUB6, R_RISCV_SUB6 },
929 { BFD_RELOC_RISCV_SET6, R_RISCV_SET6 },
930 { BFD_RELOC_RISCV_SET8, R_RISCV_SET8 },
931 { BFD_RELOC_RISCV_SET16, R_RISCV_SET16 },
932 { BFD_RELOC_RISCV_SET32, R_RISCV_SET32 },
933 { BFD_RELOC_RISCV_32_PCREL, R_RISCV_32_PCREL },
934 };
935
936 /* Given a BFD reloc type, return a howto structure. */
937
938 reloc_howto_type *
939 riscv_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED,
940 bfd_reloc_code_real_type code)
941 {
942 unsigned int i;
943
944 for (i = 0; i < ARRAY_SIZE (riscv_reloc_map); i++)
945 if (riscv_reloc_map[i].bfd_val == code)
946 return &howto_table[(int) riscv_reloc_map[i].elf_val];
947
948 bfd_set_error (bfd_error_bad_value);
949 return NULL;
950 }
951
952 reloc_howto_type *
953 riscv_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED, const char *r_name)
954 {
955 unsigned int i;
956
957 for (i = 0; i < ARRAY_SIZE (howto_table); i++)
958 if (howto_table[i].name && strcasecmp (howto_table[i].name, r_name) == 0)
959 return &howto_table[i];
960
961 return NULL;
962 }
963
964 reloc_howto_type *
965 riscv_elf_rtype_to_howto (bfd *abfd, unsigned int r_type)
966 {
967 if (r_type >= ARRAY_SIZE (howto_table))
968 {
969 (*_bfd_error_handler) (_("%pB: unsupported relocation type %#x"),
970 abfd, r_type);
971 bfd_set_error (bfd_error_bad_value);
972 return NULL;
973 }
974 return &howto_table[r_type];
975 }
976
977 /* Special_function of RISCV_ADD and RISCV_SUB relocations. */
978
979 static bfd_reloc_status_type
980 riscv_elf_add_sub_reloc (bfd *abfd,
981 arelent *reloc_entry,
982 asymbol *symbol,
983 void *data,
984 asection *input_section,
985 bfd *output_bfd,
986 char **error_message ATTRIBUTE_UNUSED)
987 {
988 reloc_howto_type *howto = reloc_entry->howto;
989 bfd_vma relocation;
990
991 if (output_bfd != NULL
992 && (symbol->flags & BSF_SECTION_SYM) == 0
993 && (!reloc_entry->howto->partial_inplace || reloc_entry->addend == 0))
994 {
995 reloc_entry->address += input_section->output_offset;
996 return bfd_reloc_ok;
997 }
998
999 if (output_bfd != NULL)
1000 return bfd_reloc_continue;
1001
1002 relocation = symbol->value + symbol->section->output_section->vma
1003 + symbol->section->output_offset + reloc_entry->addend;
1004
1005 bfd_size_type octets = reloc_entry->address
1006 * bfd_octets_per_byte (abfd, input_section);
1007 if (!bfd_reloc_offset_in_range (reloc_entry->howto, abfd,
1008 input_section, octets))
1009 return bfd_reloc_outofrange;
1010
1011 bfd_vma old_value = bfd_get (howto->bitsize, abfd,
1012 data + reloc_entry->address);
1013
1014 switch (howto->type)
1015 {
1016 case R_RISCV_ADD8:
1017 case R_RISCV_ADD16:
1018 case R_RISCV_ADD32:
1019 case R_RISCV_ADD64:
1020 relocation = old_value + relocation;
1021 break;
1022 case R_RISCV_SUB6:
1023 case R_RISCV_SUB8:
1024 case R_RISCV_SUB16:
1025 case R_RISCV_SUB32:
1026 case R_RISCV_SUB64:
1027 relocation = old_value - relocation;
1028 break;
1029 }
1030 bfd_put (howto->bitsize, abfd, relocation, data + reloc_entry->address);
1031
1032 return bfd_reloc_ok;
1033 }
1034
1035 /* Always add the IMPLICIT for the SUBSET. */
1036
1037 static bool
1038 check_implicit_always (const char *implicit ATTRIBUTE_UNUSED,
1039 riscv_subset_t *subset ATTRIBUTE_UNUSED)
1040 {
1041 return true;
1042 }
1043
1044 /* Add the IMPLICIT only when the version of SUBSET less than 2.1. */
1045
1046 static bool
1047 check_implicit_for_i (const char *implicit ATTRIBUTE_UNUSED,
1048 riscv_subset_t *subset)
1049 {
1050 return (subset->major_version < 2
1051 || (subset->major_version == 2
1052 && subset->minor_version < 1));
1053 }
1054
1055 /* Record all implicit information for the subsets. */
1056 struct riscv_implicit_subset
1057 {
1058 const char *subset_name;
1059 const char *implicit_name;
1060 /* A function to determine if we need to add the implicit subset. */
1061 bool (*check_func) (const char *, riscv_subset_t *);
1062 };
1063 static struct riscv_implicit_subset riscv_implicit_subsets[] =
1064 {
1065 {"e", "i", check_implicit_always},
1066 {"i", "zicsr", check_implicit_for_i},
1067 {"i", "zifencei", check_implicit_for_i},
1068 {"g", "i", check_implicit_always},
1069 {"g", "m", check_implicit_always},
1070 {"g", "a", check_implicit_always},
1071 {"g", "f", check_implicit_always},
1072 {"g", "d", check_implicit_always},
1073 {"g", "zicsr", check_implicit_always},
1074 {"g", "zifencei", check_implicit_always},
1075 {"q", "d", check_implicit_always},
1076 {"v", "d", check_implicit_always},
1077 {"v", "zve64d", check_implicit_always},
1078 {"v", "zvl128b", check_implicit_always},
1079 {"zve64d", "d", check_implicit_always},
1080 {"zve64d", "zve64f", check_implicit_always},
1081 {"zve64f", "zve32f", check_implicit_always},
1082 {"zve64f", "zve64x", check_implicit_always},
1083 {"zve64f", "zvl64b", check_implicit_always},
1084 {"zve32f", "f", check_implicit_always},
1085 {"zve32f", "zvl32b", check_implicit_always},
1086 {"zve32f", "zve32x", check_implicit_always},
1087 {"zve64x", "zve32x", check_implicit_always},
1088 {"zve64x", "zvl64b", check_implicit_always},
1089 {"zve32x", "zvl32b", check_implicit_always},
1090 {"zvl65536b", "zvl32768b", check_implicit_always},
1091 {"zvl32768b", "zvl16384b", check_implicit_always},
1092 {"zvl16384b", "zvl8192b", check_implicit_always},
1093 {"zvl8192b", "zvl4096b", check_implicit_always},
1094 {"zvl4096b", "zvl2048b", check_implicit_always},
1095 {"zvl2048b", "zvl1024b", check_implicit_always},
1096 {"zvl1024b", "zvl512b", check_implicit_always},
1097 {"zvl512b", "zvl256b", check_implicit_always},
1098 {"zvl256b", "zvl128b", check_implicit_always},
1099 {"zvl128b", "zvl64b", check_implicit_always},
1100 {"zvl64b", "zvl32b", check_implicit_always},
1101 {"d", "f", check_implicit_always},
1102 {"f", "zicsr", check_implicit_always},
1103 {"zfh", "f", check_implicit_always},
1104 {"zfh", "zicsr", check_implicit_always},
1105 {"zqinx", "zdinx", check_implicit_always},
1106 {"zdinx", "zfinx", check_implicit_always},
1107 {"zfinx", "zicsr", check_implicit_always},
1108 {"zhinx", "zfinx", check_implicit_always},
1109 {"zhinx", "zicsr", check_implicit_always},
1110 {"zk", "zkn", check_implicit_always},
1111 {"zk", "zkr", check_implicit_always},
1112 {"zk", "zkt", check_implicit_always},
1113 {"zkn", "zbkb", check_implicit_always},
1114 {"zkn", "zbkc", check_implicit_always},
1115 {"zkn", "zbkx", check_implicit_always},
1116 {"zkn", "zkne", check_implicit_always},
1117 {"zkn", "zknd", check_implicit_always},
1118 {"zkn", "zknh", check_implicit_always},
1119 {"zks", "zbkb", check_implicit_always},
1120 {"zks", "zbkc", check_implicit_always},
1121 {"zks", "zbkx", check_implicit_always},
1122 {"zks", "zksed", check_implicit_always},
1123 {"zks", "zksh", check_implicit_always},
1124 {NULL, NULL, NULL}
1125 };
1126
1127 /* For default_enable field, decide if the extension should
1128 be enbaled by default. */
1129
1130 #define EXT_DEFAULT 0x1
1131
1132 /* List all extensions that binutils should know about. */
1133
1134 struct riscv_supported_ext
1135 {
1136 const char *name;
1137 enum riscv_spec_class isa_spec_class;
1138 int major_version;
1139 int minor_version;
1140 unsigned long default_enable;
1141 };
1142
1143 /* The standard extensions must be added in canonical order. */
1144
1145 static struct riscv_supported_ext riscv_supported_std_ext[] =
1146 {
1147 {"e", ISA_SPEC_CLASS_20191213, 1, 9, 0 },
1148 {"e", ISA_SPEC_CLASS_20190608, 1, 9, 0 },
1149 {"e", ISA_SPEC_CLASS_2P2, 1, 9, 0 },
1150 {"i", ISA_SPEC_CLASS_20191213, 2, 1, 0 },
1151 {"i", ISA_SPEC_CLASS_20190608, 2, 1, 0 },
1152 {"i", ISA_SPEC_CLASS_2P2, 2, 0, 0 },
1153 /* The g is a special case which we don't want to output it,
1154 but still need it when adding implicit extensions. */
1155 {"g", ISA_SPEC_CLASS_NONE, RISCV_UNKNOWN_VERSION, RISCV_UNKNOWN_VERSION, EXT_DEFAULT },
1156 {"m", ISA_SPEC_CLASS_20191213, 2, 0, 0 },
1157 {"m", ISA_SPEC_CLASS_20190608, 2, 0, 0 },
1158 {"m", ISA_SPEC_CLASS_2P2, 2, 0, 0 },
1159 {"a", ISA_SPEC_CLASS_20191213, 2, 1, 0 },
1160 {"a", ISA_SPEC_CLASS_20190608, 2, 0, 0 },
1161 {"a", ISA_SPEC_CLASS_2P2, 2, 0, 0 },
1162 {"f", ISA_SPEC_CLASS_20191213, 2, 2, 0 },
1163 {"f", ISA_SPEC_CLASS_20190608, 2, 2, 0 },
1164 {"f", ISA_SPEC_CLASS_2P2, 2, 0, 0 },
1165 {"d", ISA_SPEC_CLASS_20191213, 2, 2, 0 },
1166 {"d", ISA_SPEC_CLASS_20190608, 2, 2, 0 },
1167 {"d", ISA_SPEC_CLASS_2P2, 2, 0, 0 },
1168 {"q", ISA_SPEC_CLASS_20191213, 2, 2, 0 },
1169 {"q", ISA_SPEC_CLASS_20190608, 2, 2, 0 },
1170 {"q", ISA_SPEC_CLASS_2P2, 2, 0, 0 },
1171 {"c", ISA_SPEC_CLASS_20191213, 2, 0, 0 },
1172 {"c", ISA_SPEC_CLASS_20190608, 2, 0, 0 },
1173 {"c", ISA_SPEC_CLASS_2P2, 2, 0, 0 },
1174 {"v", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1175 {"h", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1176 {NULL, 0, 0, 0, 0}
1177 };
1178
1179 static struct riscv_supported_ext riscv_supported_std_z_ext[] =
1180 {
1181 {"zicbom", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1182 {"zicbop", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1183 {"zicboz", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1184 {"zicsr", ISA_SPEC_CLASS_20191213, 2, 0, 0 },
1185 {"zicsr", ISA_SPEC_CLASS_20190608, 2, 0, 0 },
1186 {"zifencei", ISA_SPEC_CLASS_20191213, 2, 0, 0 },
1187 {"zifencei", ISA_SPEC_CLASS_20190608, 2, 0, 0 },
1188 {"zihintpause", ISA_SPEC_CLASS_DRAFT, 2, 0, 0 },
1189 {"zfh", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1190 {"zfinx", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1191 {"zdinx", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1192 {"zqinx", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1193 {"zhinx", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1194 {"zbb", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1195 {"zba", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1196 {"zbc", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1197 {"zbs", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1198 {"zbkb", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1199 {"zbkc", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1200 {"zbkx", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1201 {"zk", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1202 {"zkn", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1203 {"zknd", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1204 {"zkne", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1205 {"zknh", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1206 {"zkr", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1207 {"zks", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1208 {"zksed", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1209 {"zksh", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1210 {"zkt", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1211 {"zve32x", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1212 {"zve32f", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1213 {"zve32d", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1214 {"zve64x", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1215 {"zve64f", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1216 {"zve64d", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1217 {"zvl32b", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1218 {"zvl64b", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1219 {"zvl128b", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1220 {"zvl256b", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1221 {"zvl512b", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1222 {"zvl1024b", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1223 {"zvl2048b", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1224 {"zvl4096b", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1225 {"zvl8192b", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1226 {"zvl16384b", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1227 {"zvl32768b", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1228 {"zvl65536b", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1229 {NULL, 0, 0, 0, 0}
1230 };
1231
1232 static struct riscv_supported_ext riscv_supported_std_s_ext[] =
1233 {
1234 {"smstateen", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1235 {"sscofpmf", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1236 {"sstc", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1237 {"svinval", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1238 {NULL, 0, 0, 0, 0}
1239 };
1240
1241 static struct riscv_supported_ext riscv_supported_std_zxm_ext[] =
1242 {
1243 {NULL, 0, 0, 0, 0}
1244 };
1245
1246 const struct riscv_supported_ext *riscv_all_supported_ext[] =
1247 {
1248 riscv_supported_std_ext,
1249 riscv_supported_std_z_ext,
1250 riscv_supported_std_s_ext,
1251 riscv_supported_std_zxm_ext,
1252 NULL
1253 };
1254
1255 /* ISA extension prefixed name class. Must define them in parsing order. */
1256 enum riscv_prefix_ext_class
1257 {
1258 RV_ISA_CLASS_Z = 1,
1259 RV_ISA_CLASS_S,
1260 RV_ISA_CLASS_ZXM,
1261 RV_ISA_CLASS_X,
1262 RV_ISA_CLASS_UNKNOWN
1263 };
1264
1265 /* Record the strings of the prefixed extensions, and their corresponding
1266 classes. The more letters of the prefix string, the more forward it must
1267 be defined. Otherwise, the riscv_get_prefix_class will map it to the
1268 wrong classes. */
1269 struct riscv_parse_prefix_config
1270 {
1271 /* Class of the extension. */
1272 enum riscv_prefix_ext_class class;
1273
1274 /* Prefix string for error printing and internal parser usage. */
1275 const char *prefix;
1276 };
1277 static const struct riscv_parse_prefix_config parse_config[] =
1278 {
1279 {RV_ISA_CLASS_ZXM, "zxm"},
1280 {RV_ISA_CLASS_Z, "z"},
1281 {RV_ISA_CLASS_S, "s"},
1282 {RV_ISA_CLASS_X, "x"},
1283 {RV_ISA_CLASS_UNKNOWN, NULL}
1284 };
1285
1286 /* Get the prefixed name class for the extensions, the class also
1287 means the order of the prefixed extensions. */
1288
1289 static enum riscv_prefix_ext_class
1290 riscv_get_prefix_class (const char *arch)
1291 {
1292 int i = 0;
1293 while (parse_config[i].class != RV_ISA_CLASS_UNKNOWN)
1294 {
1295 if (strncmp (arch, parse_config[i].prefix,
1296 strlen (parse_config[i].prefix)) == 0)
1297 return parse_config[i].class;
1298 i++;
1299 }
1300 return RV_ISA_CLASS_UNKNOWN;
1301 }
1302
1303 /* Check KNOWN_EXTS to see if the EXT is supported. */
1304
1305 static bool
1306 riscv_known_prefixed_ext (const char *ext,
1307 struct riscv_supported_ext *known_exts)
1308 {
1309 size_t i;
1310 for (i = 0; known_exts[i].name != NULL; ++i)
1311 if (strcmp (ext, known_exts[i].name) == 0)
1312 return true;
1313 return false;
1314 }
1315
1316 /* Check whether the prefixed extension is recognized or not. Return
1317 true if recognized, otehrwise return false. */
1318
1319 static bool
1320 riscv_recognized_prefixed_ext (const char *ext)
1321 {
1322 enum riscv_prefix_ext_class class = riscv_get_prefix_class (ext);
1323 switch (class)
1324 {
1325 case RV_ISA_CLASS_Z:
1326 return riscv_known_prefixed_ext (ext, riscv_supported_std_z_ext);
1327 case RV_ISA_CLASS_ZXM:
1328 return riscv_known_prefixed_ext (ext, riscv_supported_std_zxm_ext);
1329 case RV_ISA_CLASS_S:
1330 return riscv_known_prefixed_ext (ext, riscv_supported_std_s_ext);
1331 case RV_ISA_CLASS_X:
1332 /* Only the single x is unrecognized. */
1333 if (strcmp (ext, "x") != 0)
1334 return true;
1335 default:
1336 break;
1337 }
1338 return false;
1339 }
1340
1341 /* Canonical order for single letter extensions. */
1342 static const char riscv_ext_canonical_order[] = "eigmafdqlcbkjtpvnh";
1343
1344 /* Array is used to compare the orders of standard extensions quickly. */
1345 static int riscv_ext_order[26] = {0};
1346
1347 /* Init the riscv_ext_order array. */
1348
1349 static void
1350 riscv_init_ext_order (void)
1351 {
1352 static bool inited = false;
1353 if (inited)
1354 return;
1355
1356 /* The orders of all standard extensions are positive. */
1357 int order = 1;
1358
1359 for (const char *ext = &riscv_ext_canonical_order[0]; *ext; ++ext)
1360 riscv_ext_order[(*ext - 'a')] = order++;
1361
1362 /* Some of the prefixed keyword are not single letter, so we set
1363 their prefixed orders in the riscv_compare_subsets directly,
1364 not through the riscv_ext_order. */
1365
1366 inited = true;
1367 }
1368
1369 /* Similar to the strcmp. It returns an integer less than, equal to,
1370 or greater than zero if `subset2` is found, respectively, to be less
1371 than, to match, or be greater than `subset1`.
1372
1373 The order values,
1374 Zero: Preserved keywords.
1375 Positive number: Standard extensions.
1376 Negative number: Prefixed keywords. */
1377
1378 int
1379 riscv_compare_subsets (const char *subset1, const char *subset2)
1380 {
1381 int order1 = riscv_ext_order[(*subset1 - 'a')];
1382 int order2 = riscv_ext_order[(*subset2 - 'a')];
1383
1384 /* Compare the standard extension first. */
1385 if (order1 > 0 && order2 > 0)
1386 return order1 - order2;
1387
1388 /* Set the prefixed orders to negative numbers. */
1389 enum riscv_prefix_ext_class class1 = riscv_get_prefix_class (subset1);
1390 enum riscv_prefix_ext_class class2 = riscv_get_prefix_class (subset2);
1391
1392 if (class1 != RV_ISA_CLASS_UNKNOWN)
1393 order1 = - (int) class1;
1394 if (class2 != RV_ISA_CLASS_UNKNOWN)
1395 order2 = - (int) class2;
1396
1397 if (order1 == order2)
1398 {
1399 /* Compare the standard addition z extensions. */
1400 if (class1 == RV_ISA_CLASS_Z)
1401 {
1402 order1 = riscv_ext_order[(*++subset1 - 'a')];
1403 order2 = riscv_ext_order[(*++subset2 - 'a')];
1404 if (order1 != order2)
1405 return order1 - order2;
1406 }
1407 return strcasecmp (++subset1, ++subset2);
1408 }
1409
1410 return order2 - order1;
1411 }
1412
1413 /* Find subset in the list. Return TRUE and set `current` to the subset
1414 if it is found. Otherwise, return FALSE and set `current` to the place
1415 where we should insert the subset. However, return FALSE with the NULL
1416 `current` means we should insert the subset at the head of subset list,
1417 if needed. */
1418
1419 bool
1420 riscv_lookup_subset (const riscv_subset_list_t *subset_list,
1421 const char *subset,
1422 riscv_subset_t **current)
1423 {
1424 riscv_subset_t *s, *pre_s = NULL;
1425
1426 /* If the subset is added in order, then just add it at the tail. */
1427 if (subset_list->tail != NULL
1428 && riscv_compare_subsets (subset_list->tail->name, subset) < 0)
1429 {
1430 *current = subset_list->tail;
1431 return false;
1432 }
1433
1434 for (s = subset_list->head;
1435 s != NULL;
1436 pre_s = s, s = s->next)
1437 {
1438 int cmp = riscv_compare_subsets (s->name, subset);
1439 if (cmp == 0)
1440 {
1441 *current = s;
1442 return true;
1443 }
1444 else if (cmp > 0)
1445 break;
1446 }
1447 *current = pre_s;
1448
1449 return false;
1450 }
1451
1452 /* Add the extension to the subset list. Search the
1453 list first, and then find the right place to add. */
1454
1455 void
1456 riscv_add_subset (riscv_subset_list_t *subset_list,
1457 const char *subset,
1458 int major,
1459 int minor)
1460 {
1461 riscv_subset_t *current, *new;
1462
1463 if (riscv_lookup_subset (subset_list, subset, &current))
1464 return;
1465
1466 new = xmalloc (sizeof *new);
1467 new->name = xstrdup (subset);
1468 new->major_version = major;
1469 new->minor_version = minor;
1470 new->next = NULL;
1471
1472 if (current != NULL)
1473 {
1474 new->next = current->next;
1475 current->next = new;
1476 }
1477 else
1478 {
1479 new->next = subset_list->head;
1480 subset_list->head = new;
1481 }
1482
1483 if (new->next == NULL)
1484 subset_list->tail = new;
1485 }
1486
1487 /* Get the default versions from the riscv_supported_*ext tables. */
1488
1489 static void
1490 riscv_get_default_ext_version (enum riscv_spec_class *default_isa_spec,
1491 const char *name,
1492 int *major_version,
1493 int *minor_version)
1494 {
1495 if (name == NULL
1496 || default_isa_spec == NULL
1497 || *default_isa_spec == ISA_SPEC_CLASS_NONE)
1498 return;
1499
1500 struct riscv_supported_ext *table = NULL;
1501 enum riscv_prefix_ext_class class = riscv_get_prefix_class (name);
1502 switch (class)
1503 {
1504 case RV_ISA_CLASS_ZXM: table = riscv_supported_std_zxm_ext; break;
1505 case RV_ISA_CLASS_Z: table = riscv_supported_std_z_ext; break;
1506 case RV_ISA_CLASS_S: table = riscv_supported_std_s_ext; break;
1507 case RV_ISA_CLASS_X:
1508 break;
1509 default:
1510 table = riscv_supported_std_ext;
1511 }
1512
1513 int i = 0;
1514 while (table != NULL && table[i].name != NULL)
1515 {
1516 if (strcmp (table[i].name, name) == 0
1517 && (table[i].isa_spec_class == ISA_SPEC_CLASS_DRAFT
1518 || table[i].isa_spec_class == *default_isa_spec))
1519 {
1520 *major_version = table[i].major_version;
1521 *minor_version = table[i].minor_version;
1522 return;
1523 }
1524 i++;
1525 }
1526 }
1527
1528 /* Find the default versions for the extension before adding them to
1529 the subset list, if their versions are RISCV_UNKNOWN_VERSION.
1530 Afterwards, report errors if we can not find their default versions. */
1531
1532 static void
1533 riscv_parse_add_subset (riscv_parse_subset_t *rps,
1534 const char *subset,
1535 int major,
1536 int minor,
1537 bool implicit)
1538 {
1539 int major_version = major;
1540 int minor_version = minor;
1541
1542 if (major_version == RISCV_UNKNOWN_VERSION
1543 || minor_version == RISCV_UNKNOWN_VERSION)
1544 riscv_get_default_ext_version (rps->isa_spec, subset,
1545 &major_version, &minor_version);
1546
1547 /* We don't care the versions of the implicit extensions. */
1548 if (!implicit
1549 && (major_version == RISCV_UNKNOWN_VERSION
1550 || minor_version == RISCV_UNKNOWN_VERSION))
1551 {
1552 if (subset[0] == 'x')
1553 rps->error_handler
1554 (_("x ISA extension `%s' must be set with the versions"),
1555 subset);
1556 /* Allow old ISA spec can recognize zicsr and zifencei. */
1557 else if (strcmp (subset, "zicsr") != 0
1558 && strcmp (subset, "zifencei") != 0)
1559 rps->error_handler
1560 (_("cannot find default versions of the ISA extension `%s'"),
1561 subset);
1562 return;
1563 }
1564
1565 riscv_add_subset (rps->subset_list, subset,
1566 major_version, minor_version);
1567 }
1568
1569 /* Release subset list. */
1570
1571 void
1572 riscv_release_subset_list (riscv_subset_list_t *subset_list)
1573 {
1574 while (subset_list->head != NULL)
1575 {
1576 riscv_subset_t *next = subset_list->head->next;
1577 free ((void *)subset_list->head->name);
1578 free (subset_list->head);
1579 subset_list->head = next;
1580 }
1581
1582 subset_list->tail = NULL;
1583 }
1584
1585 /* Parsing extension version.
1586
1587 Return Value:
1588 Points to the end of version
1589
1590 Arguments:
1591 `p`: Curent parsing position.
1592 `major_version`: Parsed major version.
1593 `minor_version`: Parsed minor version. */
1594
1595 static const char *
1596 riscv_parsing_subset_version (const char *p,
1597 int *major_version,
1598 int *minor_version)
1599 {
1600 bool major_p = true;
1601 int version = 0;
1602 char np;
1603
1604 *major_version = 0;
1605 *minor_version = 0;
1606 for (; *p; ++p)
1607 {
1608 if (*p == 'p')
1609 {
1610 np = *(p + 1);
1611
1612 /* Might be beginning of `p` extension. */
1613 if (!ISDIGIT (np))
1614 break;
1615
1616 *major_version = version;
1617 major_p = false;
1618 version = 0;
1619 }
1620 else if (ISDIGIT (*p))
1621 version = (version * 10) + (*p - '0');
1622 else
1623 break;
1624 }
1625
1626 if (major_p)
1627 *major_version = version;
1628 else
1629 *minor_version = version;
1630
1631 /* We can not find any version in string. */
1632 if (*major_version == 0 && *minor_version == 0)
1633 {
1634 *major_version = RISCV_UNKNOWN_VERSION;
1635 *minor_version = RISCV_UNKNOWN_VERSION;
1636 }
1637
1638 return p;
1639 }
1640
1641 /* Parsing function for standard extensions.
1642
1643 Return Value:
1644 Points to the end of extensions.
1645
1646 Arguments:
1647 `rps`: Hooks and status for parsing extensions.
1648 `arch`: Full ISA string.
1649 `p`: Curent parsing position. */
1650
1651 static const char *
1652 riscv_parse_std_ext (riscv_parse_subset_t *rps,
1653 const char *arch,
1654 const char *p)
1655 {
1656 /* First letter must start with i, e or g. */
1657 if (*p != 'e' && *p != 'i' && *p != 'g')
1658 {
1659 rps->error_handler
1660 (_("%s: first ISA extension must be `e', `i' or `g'"),
1661 arch);
1662 return NULL;
1663 }
1664
1665 while (p != NULL && *p != '\0')
1666 {
1667 /* Stop when we parsed the known prefix class. */
1668 enum riscv_prefix_ext_class class = riscv_get_prefix_class (p);
1669 if (class != RV_ISA_CLASS_UNKNOWN)
1670 break;
1671
1672 if (*p == '_')
1673 {
1674 p++;
1675 continue;
1676 }
1677
1678 bool implicit = false;
1679 int major = RISCV_UNKNOWN_VERSION;
1680 int minor = RISCV_UNKNOWN_VERSION;
1681 char subset[2] = {0, 0};
1682
1683 subset[0] = *p;
1684
1685 /* Check if the standard extension is supported. */
1686 if (riscv_ext_order[(subset[0] - 'a')] == 0)
1687 {
1688 rps->error_handler
1689 (_("%s: unknown standard ISA extension `%c'"),
1690 arch, subset[0]);
1691 return NULL;
1692 }
1693
1694 /* Checking canonical order. */
1695 if (rps->subset_list->tail != NULL
1696 && riscv_compare_subsets (rps->subset_list->tail->name, subset) > 0)
1697 {
1698 rps->error_handler
1699 (_("%s: standard ISA extension `%c' is not "
1700 "in canonical order"), arch, subset[0]);
1701 return NULL;
1702 }
1703
1704 p = riscv_parsing_subset_version (++p, &major, &minor);
1705 /* Added g as an implicit extension. */
1706 if (subset[0] == 'g')
1707 {
1708 implicit = true;
1709 major = RISCV_UNKNOWN_VERSION;
1710 minor = RISCV_UNKNOWN_VERSION;
1711 }
1712 riscv_parse_add_subset (rps, subset, major, minor, implicit);
1713 }
1714
1715 return p;
1716 }
1717
1718 /* Parsing function for prefixed extensions.
1719
1720 Return Value:
1721 Points to the end of extension.
1722
1723 Arguments:
1724 `rps`: Hooks and status for parsing extensions.
1725 `arch`: Full ISA string.
1726 `p`: Curent parsing position. */
1727
1728 static const char *
1729 riscv_parse_prefixed_ext (riscv_parse_subset_t *rps,
1730 const char *arch,
1731 const char *p)
1732 {
1733 int major_version;
1734 int minor_version;
1735 enum riscv_prefix_ext_class class;
1736
1737 while (*p)
1738 {
1739 if (*p == '_')
1740 {
1741 p++;
1742 continue;
1743 }
1744
1745 class = riscv_get_prefix_class (p);
1746 if (class == RV_ISA_CLASS_UNKNOWN)
1747 {
1748 rps->error_handler
1749 (_("%s: unknown prefix class for the ISA extension `%s'"),
1750 arch, p);
1751 return NULL;
1752 }
1753
1754 char *subset = xstrdup (p);
1755 char *q = subset;
1756 const char *end_of_version;
1757
1758 /* Extract the whole prefixed extension by '_'. */
1759 while (*++q != '\0' && *q != '_')
1760 ;
1761 /* Look forward to the first letter which is not <major>p<minor>. */
1762 bool find_any_version = false;
1763 bool find_minor_version = false;
1764 while (1)
1765 {
1766 q--;
1767 if (ISDIGIT (*q))
1768 find_any_version = true;
1769 else if (find_any_version
1770 && !find_minor_version
1771 && *q == 'p'
1772 && ISDIGIT (*(q - 1)))
1773 find_minor_version = true;
1774 else
1775 break;
1776 }
1777 q++;
1778
1779 /* Check if the end of extension is 'p' or not. If yes, then
1780 the second letter from the end cannot be number. */
1781 if (*(q - 1) == 'p' && ISDIGIT (*(q - 2)))
1782 {
1783 *q = '\0';
1784 rps->error_handler
1785 (_("%s: invalid prefixed ISA extension `%s' ends with <number>p"),
1786 arch, subset);
1787 free (subset);
1788 return NULL;
1789 }
1790
1791 end_of_version =
1792 riscv_parsing_subset_version (q, &major_version, &minor_version);
1793 *q = '\0';
1794 if (end_of_version == NULL)
1795 {
1796 free (subset);
1797 return NULL;
1798 }
1799
1800 /* Check that the extension name is well-formed. */
1801 if (rps->check_unknown_prefixed_ext
1802 && !riscv_recognized_prefixed_ext (subset))
1803 {
1804 rps->error_handler
1805 (_("%s: unknown prefixed ISA extension `%s'"),
1806 arch, subset);
1807 free (subset);
1808 return NULL;
1809 }
1810
1811 riscv_parse_add_subset (rps, subset,
1812 major_version,
1813 minor_version, false);
1814 p += end_of_version - subset;
1815 free (subset);
1816
1817 if (*p != '\0' && *p != '_')
1818 {
1819 rps->error_handler
1820 (_("%s: prefixed ISA extension must separate with _"),
1821 arch);
1822 return NULL;
1823 }
1824 }
1825
1826 return p;
1827 }
1828
1829 /* Add the implicit extensions. */
1830
1831 static void
1832 riscv_parse_add_implicit_subsets (riscv_parse_subset_t *rps)
1833 {
1834 struct riscv_implicit_subset *t = riscv_implicit_subsets;
1835 for (; t->subset_name; t++)
1836 {
1837 riscv_subset_t *subset = NULL;
1838 if (riscv_lookup_subset (rps->subset_list, t->subset_name, &subset)
1839 && t->check_func (t->implicit_name, subset))
1840 riscv_parse_add_subset (rps, t->implicit_name,
1841 RISCV_UNKNOWN_VERSION,
1842 RISCV_UNKNOWN_VERSION, true);
1843 }
1844 }
1845
1846 /* Check extensions conflicts. */
1847
1848 static bool
1849 riscv_parse_check_conflicts (riscv_parse_subset_t *rps)
1850 {
1851 riscv_subset_t *subset = NULL;
1852 int xlen = *rps->xlen;
1853 bool no_conflict = true;
1854
1855 if (riscv_lookup_subset (rps->subset_list, "e", &subset)
1856 && xlen > 32)
1857 {
1858 rps->error_handler
1859 (_("rv%d does not support the `e' extension"), xlen);
1860 no_conflict = false;
1861 }
1862 if (riscv_lookup_subset (rps->subset_list, "q", &subset)
1863 && (subset->major_version < 2 || (subset->major_version == 2
1864 && subset->minor_version < 2))
1865 && xlen < 64)
1866 {
1867 rps->error_handler (_("rv%d does not support the `q' extension"), xlen);
1868 no_conflict = false;
1869 }
1870 if (riscv_lookup_subset (rps->subset_list, "e", &subset)
1871 && riscv_lookup_subset (rps->subset_list, "f", &subset))
1872 {
1873 rps->error_handler
1874 (_("rv32e does not support the `f' extension"));
1875 no_conflict = false;
1876 }
1877 if (riscv_lookup_subset (rps->subset_list, "zfinx", &subset)
1878 && riscv_lookup_subset (rps->subset_list, "f", &subset))
1879 {
1880 rps->error_handler
1881 (_("`zfinx' is conflict with the `f/d/q' extension"));
1882 no_conflict = false;
1883 }
1884
1885 bool support_zve = false;
1886 bool support_zvl = false;
1887 riscv_subset_t *s = rps->subset_list->head;
1888 for (; s != NULL; s = s->next)
1889 {
1890 if (!support_zve
1891 && strncmp (s->name, "zve", 3) == 0)
1892 support_zve = true;
1893 if (!support_zvl
1894 && strncmp (s->name, "zvl", 3) == 0)
1895 support_zvl = true;
1896 if (support_zve && support_zvl)
1897 break;
1898 }
1899 if (support_zvl && !support_zve)
1900 {
1901 rps->error_handler
1902 (_("zvl*b extensions need to enable either `v' or `zve' extension"));
1903 no_conflict = false;
1904 }
1905
1906 return no_conflict;
1907 }
1908
1909 /* Set the default subset list according to the default_enable field
1910 of riscv_supported_*ext tables. */
1911
1912 static void
1913 riscv_set_default_arch (riscv_parse_subset_t *rps)
1914 {
1915 unsigned long enable = EXT_DEFAULT;
1916 int i, j;
1917 for (i = 0; riscv_all_supported_ext[i] != NULL; i++)
1918 {
1919 const struct riscv_supported_ext *table = riscv_all_supported_ext[i];
1920 for (j = 0; table[j].name != NULL; j++)
1921 {
1922 bool implicit = false;
1923 if (strcmp (table[j].name, "g") == 0)
1924 implicit = true;
1925 if (table[j].default_enable & enable)
1926 riscv_parse_add_subset (rps, table[j].name,
1927 RISCV_UNKNOWN_VERSION,
1928 RISCV_UNKNOWN_VERSION, implicit);
1929 }
1930 }
1931 }
1932
1933 /* Function for parsing ISA string.
1934
1935 Return Value:
1936 Return TRUE on success.
1937
1938 Arguments:
1939 `rps`: Hooks and status for parsing extensions.
1940 `arch`: Full ISA string. */
1941
1942 bool
1943 riscv_parse_subset (riscv_parse_subset_t *rps,
1944 const char *arch)
1945 {
1946 const char *p;
1947
1948 /* Init the riscv_ext_order array to compare the order of extensions
1949 quickly. */
1950 riscv_init_ext_order ();
1951
1952 if (arch == NULL)
1953 {
1954 riscv_set_default_arch (rps);
1955 riscv_parse_add_implicit_subsets (rps);
1956 return riscv_parse_check_conflicts (rps);
1957 }
1958
1959 for (p = arch; *p != '\0'; p++)
1960 {
1961 if (ISUPPER (*p))
1962 {
1963 rps->error_handler
1964 (_("%s: ISA string cannot contain uppercase letters"),
1965 arch);
1966 return false;
1967 }
1968 }
1969
1970 p = arch;
1971 if (startswith (p, "rv32"))
1972 {
1973 *rps->xlen = 32;
1974 p += 4;
1975 }
1976 else if (startswith (p, "rv64"))
1977 {
1978 *rps->xlen = 64;
1979 p += 4;
1980 }
1981 else
1982 {
1983 /* ISA string shouldn't be NULL or empty here. For linker,
1984 it might be empty when we failed to merge the ISA string
1985 in the riscv_merge_attributes. For assembler, we might
1986 give an empty string by .attribute arch, "" or -march=.
1987 However, We have already issued the correct error message
1988 in another side, so do not issue this error when the ISA
1989 string is empty. */
1990 if (strlen (arch))
1991 rps->error_handler (
1992 _("%s: ISA string must begin with rv32 or rv64"),
1993 arch);
1994 return false;
1995 }
1996
1997 /* Parsing standard extension. */
1998 p = riscv_parse_std_ext (rps, arch, p);
1999
2000 if (p == NULL)
2001 return false;
2002
2003 /* Parse prefixed extensions. */
2004 p = riscv_parse_prefixed_ext (rps, arch, p);
2005
2006 if (p == NULL)
2007 return false;
2008
2009 /* Finally add implicit extensions according to the current
2010 extensions. */
2011 riscv_parse_add_implicit_subsets (rps);
2012
2013 /* Check the conflicts. */
2014 return riscv_parse_check_conflicts (rps);
2015 }
2016
2017 /* Return the number of digits for the input. */
2018
2019 size_t
2020 riscv_estimate_digit (unsigned num)
2021 {
2022 size_t digit = 0;
2023 if (num == 0)
2024 return 1;
2025
2026 for (digit = 0; num ; num /= 10)
2027 digit++;
2028
2029 return digit;
2030 }
2031
2032 /* Auxiliary function to estimate string length of subset list. */
2033
2034 static size_t
2035 riscv_estimate_arch_strlen1 (const riscv_subset_t *subset)
2036 {
2037 if (subset == NULL)
2038 return 6; /* For rv32/rv64/rv128 and string terminator. */
2039
2040 return riscv_estimate_arch_strlen1 (subset->next)
2041 + strlen (subset->name)
2042 + riscv_estimate_digit (subset->major_version)
2043 + 1 /* For version seperator 'p'. */
2044 + riscv_estimate_digit (subset->minor_version)
2045 + 1 /* For underscore. */;
2046 }
2047
2048 /* Estimate the string length of this subset list. */
2049
2050 static size_t
2051 riscv_estimate_arch_strlen (const riscv_subset_list_t *subset_list)
2052 {
2053 return riscv_estimate_arch_strlen1 (subset_list->head);
2054 }
2055
2056 /* Auxiliary function to convert subset info to string. */
2057
2058 static void
2059 riscv_arch_str1 (riscv_subset_t *subset,
2060 char *attr_str, char *buf, size_t bufsz)
2061 {
2062 const char *underline = "_";
2063 riscv_subset_t *subset_t = subset;
2064
2065 if (subset_t == NULL)
2066 return;
2067
2068 /* No underline between rvXX and i/e. */
2069 if ((strcasecmp (subset_t->name, "i") == 0)
2070 || (strcasecmp (subset_t->name, "e") == 0))
2071 underline = "";
2072
2073 snprintf (buf, bufsz, "%s%s%dp%d",
2074 underline,
2075 subset_t->name,
2076 subset_t->major_version,
2077 subset_t->minor_version);
2078
2079 strncat (attr_str, buf, bufsz);
2080
2081 /* Skip 'i' extension after 'e', or skip extensions which
2082 versions are unknown. */
2083 while (subset_t->next
2084 && ((strcmp (subset_t->name, "e") == 0
2085 && strcmp (subset_t->next->name, "i") == 0)
2086 || subset_t->next->major_version == RISCV_UNKNOWN_VERSION
2087 || subset_t->next->minor_version == RISCV_UNKNOWN_VERSION))
2088 subset_t = subset_t->next;
2089
2090 riscv_arch_str1 (subset_t->next, attr_str, buf, bufsz);
2091 }
2092
2093 /* Convert subset information into string with explicit versions. */
2094
2095 char *
2096 riscv_arch_str (unsigned xlen, const riscv_subset_list_t *subset)
2097 {
2098 size_t arch_str_len = riscv_estimate_arch_strlen (subset);
2099 char *attr_str = xmalloc (arch_str_len);
2100 char *buf = xmalloc (arch_str_len);
2101
2102 snprintf (attr_str, arch_str_len, "rv%u", xlen);
2103
2104 riscv_arch_str1 (subset->head, attr_str, buf, arch_str_len);
2105 free (buf);
2106
2107 return attr_str;
2108 }
2109
2110 /* Copy the subset in the subset list. */
2111
2112 static struct riscv_subset_t *
2113 riscv_copy_subset (riscv_subset_list_t *subset_list,
2114 riscv_subset_t *subset)
2115 {
2116 if (subset == NULL)
2117 return NULL;
2118
2119 riscv_subset_t *new = xmalloc (sizeof *new);
2120 new->name = xstrdup (subset->name);
2121 new->major_version = subset->major_version;
2122 new->minor_version = subset->minor_version;
2123 new->next = riscv_copy_subset (subset_list, subset->next);
2124
2125 if (subset->next == NULL)
2126 subset_list->tail = new;
2127
2128 return new;
2129 }
2130
2131 /* Copy the subset list. */
2132
2133 riscv_subset_list_t *
2134 riscv_copy_subset_list (riscv_subset_list_t *subset_list)
2135 {
2136 riscv_subset_list_t *new = xmalloc (sizeof *new);
2137 new->head = riscv_copy_subset (new, subset_list->head);
2138 return new;
2139 }
2140
2141 /* Remove the SUBSET from the subset list. */
2142
2143 static void
2144 riscv_remove_subset (riscv_subset_list_t *subset_list,
2145 const char *subset)
2146 {
2147 riscv_subset_t *current = subset_list->head;
2148 riscv_subset_t *pre = NULL;
2149 for (; current != NULL; pre = current, current = current->next)
2150 {
2151 if (strcmp (current->name, subset) == 0)
2152 {
2153 if (pre == NULL)
2154 subset_list->head = current->next;
2155 else
2156 pre->next = current->next;
2157 if (current->next == NULL)
2158 subset_list->tail = pre;
2159 free ((void *) current->name);
2160 free (current);
2161 break;
2162 }
2163 }
2164 }
2165
2166 /* Add/Remove an extension to/from the subset list. This is used for
2167 the .option rvc or norvc, and .option arch directives. */
2168
2169 bool
2170 riscv_update_subset (riscv_parse_subset_t *rps,
2171 const char *str)
2172 {
2173 const char *p = str;
2174
2175 do
2176 {
2177 int major_version = RISCV_UNKNOWN_VERSION;
2178 int minor_version = RISCV_UNKNOWN_VERSION;
2179
2180 bool removed = false;
2181 switch (*p)
2182 {
2183 case '+': removed = false; break;
2184 case '-': removed = true; break;
2185 default:
2186 riscv_release_subset_list (rps->subset_list);
2187 return riscv_parse_subset (rps, p);
2188 }
2189 ++p;
2190
2191 char *subset = xstrdup (p);
2192 char *q = subset;
2193 const char *end_of_version;
2194 /* Extract the whole prefixed extension by ','. */
2195 while (*q != '\0' && *q != ',')
2196 q++;
2197
2198 /* Look forward to the first letter which is not <major>p<minor>. */
2199 bool find_any_version = false;
2200 bool find_minor_version = false;
2201 size_t len = q - subset;
2202 size_t i;
2203 for (i = len; i > 0; i--)
2204 {
2205 q--;
2206 if (ISDIGIT (*q))
2207 find_any_version = true;
2208 else if (find_any_version
2209 && !find_minor_version
2210 && *q == 'p'
2211 && ISDIGIT (*(q - 1)))
2212 find_minor_version = true;
2213 else
2214 break;
2215 }
2216 if (len > 0)
2217 q++;
2218
2219 /* Check if the end of extension is 'p' or not. If yes, then
2220 the second letter from the end cannot be number. */
2221 if (len > 1 && *(q - 1) == 'p' && ISDIGIT (*(q - 2)))
2222 {
2223 *q = '\0';
2224 rps->error_handler
2225 (_("invalid ISA extension ends with <number>p "
2226 "in .option arch `%s'"), str);
2227 free (subset);
2228 return false;
2229 }
2230
2231 end_of_version =
2232 riscv_parsing_subset_version (q, &major_version, &minor_version);
2233 *q = '\0';
2234 if (end_of_version == NULL)
2235 {
2236 free (subset);
2237 return false;
2238 }
2239
2240 if (strlen (subset) == 0
2241 || (strlen (subset) == 1
2242 && riscv_ext_order[(*subset - 'a')] == 0)
2243 || (strlen (subset) > 1
2244 && rps->check_unknown_prefixed_ext
2245 && !riscv_recognized_prefixed_ext (subset)))
2246 {
2247 rps->error_handler
2248 (_("unknown ISA extension `%s' in .option arch `%s'"),
2249 subset, str);
2250 free (subset);
2251 return false;
2252 }
2253
2254 if (strcmp (subset, "i") == 0
2255 || strcmp (subset, "e") == 0
2256 || strcmp (subset, "g") == 0)
2257 {
2258 rps->error_handler
2259 (_("cannot + or - base extension `%s' in .option "
2260 "arch `%s'"), subset, str);
2261 free (subset);
2262 return false;
2263 }
2264
2265 if (removed)
2266 riscv_remove_subset (rps->subset_list, subset);
2267 else
2268 riscv_parse_add_subset (rps, subset, major_version, minor_version, true);
2269 p += end_of_version - subset;
2270 free (subset);
2271 }
2272 while (*p++ == ',');
2273
2274 riscv_parse_add_implicit_subsets (rps);
2275 return riscv_parse_check_conflicts (rps);
2276 }
2277
2278 /* Check if the FEATURE subset is supported or not in the subset list.
2279 Return true if it is supported; Otherwise, return false. */
2280
2281 bool
2282 riscv_subset_supports (riscv_parse_subset_t *rps,
2283 const char *feature)
2284 {
2285 struct riscv_subset_t *subset;
2286 return riscv_lookup_subset (rps->subset_list, feature, &subset);
2287 }
2288
2289 /* Each instuction is belonged to an instruction class INSN_CLASS_*.
2290 Call riscv_subset_supports to make sure if the instuction is valid. */
2291
2292 bool
2293 riscv_multi_subset_supports (riscv_parse_subset_t *rps,
2294 enum riscv_insn_class insn_class)
2295 {
2296 switch (insn_class)
2297 {
2298 case INSN_CLASS_I:
2299 return riscv_subset_supports (rps, "i");
2300 case INSN_CLASS_ZICBOM:
2301 return riscv_subset_supports (rps, "zicbom");
2302 case INSN_CLASS_ZICBOP:
2303 return riscv_subset_supports (rps, "zicbop");
2304 case INSN_CLASS_ZICBOZ:
2305 return riscv_subset_supports (rps, "zicboz");
2306 case INSN_CLASS_ZICSR:
2307 return riscv_subset_supports (rps, "zicsr");
2308 case INSN_CLASS_ZIFENCEI:
2309 return riscv_subset_supports (rps, "zifencei");
2310 case INSN_CLASS_ZIHINTPAUSE:
2311 return riscv_subset_supports (rps, "zihintpause");
2312 case INSN_CLASS_M:
2313 return riscv_subset_supports (rps, "m");
2314 case INSN_CLASS_A:
2315 return riscv_subset_supports (rps, "a");
2316 case INSN_CLASS_F:
2317 return riscv_subset_supports (rps, "f");
2318 case INSN_CLASS_D:
2319 return riscv_subset_supports (rps, "d");
2320 case INSN_CLASS_Q:
2321 return riscv_subset_supports (rps, "q");
2322 case INSN_CLASS_C:
2323 return riscv_subset_supports (rps, "c");
2324 case INSN_CLASS_F_AND_C:
2325 return (riscv_subset_supports (rps, "f")
2326 && riscv_subset_supports (rps, "c"));
2327 case INSN_CLASS_D_AND_C:
2328 return (riscv_subset_supports (rps, "d")
2329 && riscv_subset_supports (rps, "c"));
2330 case INSN_CLASS_F_OR_ZFINX:
2331 return (riscv_subset_supports (rps, "f")
2332 || riscv_subset_supports (rps, "zfinx"));
2333 case INSN_CLASS_D_OR_ZDINX:
2334 return (riscv_subset_supports (rps, "d")
2335 || riscv_subset_supports (rps, "zdinx"));
2336 case INSN_CLASS_Q_OR_ZQINX:
2337 return (riscv_subset_supports (rps, "q")
2338 || riscv_subset_supports (rps, "zqinx"));
2339 case INSN_CLASS_ZFH:
2340 return riscv_subset_supports (rps, "zfh");
2341 case INSN_CLASS_ZFH_OR_ZHINX:
2342 return riscv_subset_supports (rps, "zfh")
2343 || riscv_subset_supports (rps, "zhinx");
2344 case INSN_CLASS_D_AND_ZFH_INX:
2345 return (riscv_subset_supports (rps, "d")
2346 && riscv_subset_supports (rps, "zfh"))
2347 || riscv_subset_supports (rps, "zhinx");
2348 case INSN_CLASS_Q_AND_ZFH_INX:
2349 return (riscv_subset_supports (rps, "q")
2350 && riscv_subset_supports (rps, "zfh"))
2351 || riscv_subset_supports (rps, "zhinx");
2352 case INSN_CLASS_ZBA:
2353 return riscv_subset_supports (rps, "zba");
2354 case INSN_CLASS_ZBB:
2355 return riscv_subset_supports (rps, "zbb");
2356 case INSN_CLASS_ZBC:
2357 return riscv_subset_supports (rps, "zbc");
2358 case INSN_CLASS_ZBS:
2359 return riscv_subset_supports (rps, "zbs");
2360 case INSN_CLASS_ZBKB:
2361 return riscv_subset_supports (rps, "zbkb");
2362 case INSN_CLASS_ZBKC:
2363 return riscv_subset_supports (rps, "zbkc");
2364 case INSN_CLASS_ZBKX:
2365 return riscv_subset_supports (rps, "zbkx");
2366 case INSN_CLASS_ZBB_OR_ZBKB:
2367 return (riscv_subset_supports (rps, "zbb")
2368 || riscv_subset_supports (rps, "zbkb"));
2369 case INSN_CLASS_ZBC_OR_ZBKC:
2370 return (riscv_subset_supports (rps, "zbc")
2371 || riscv_subset_supports (rps, "zbkc"));
2372 case INSN_CLASS_ZKND:
2373 return riscv_subset_supports (rps, "zknd");
2374 case INSN_CLASS_ZKNE:
2375 return riscv_subset_supports (rps, "zkne");
2376 case INSN_CLASS_ZKNH:
2377 return riscv_subset_supports (rps, "zknh");
2378 case INSN_CLASS_ZKND_OR_ZKNE:
2379 return (riscv_subset_supports (rps, "zknd")
2380 || riscv_subset_supports (rps, "zkne"));
2381 case INSN_CLASS_ZKSED:
2382 return riscv_subset_supports (rps, "zksed");
2383 case INSN_CLASS_ZKSH:
2384 return riscv_subset_supports (rps, "zksh");
2385 case INSN_CLASS_V:
2386 return (riscv_subset_supports (rps, "v")
2387 || riscv_subset_supports (rps, "zve64x")
2388 || riscv_subset_supports (rps, "zve32x"));
2389 case INSN_CLASS_ZVEF:
2390 return (riscv_subset_supports (rps, "v")
2391 || riscv_subset_supports (rps, "zve64d")
2392 || riscv_subset_supports (rps, "zve64f")
2393 || riscv_subset_supports (rps, "zve32f"));
2394 case INSN_CLASS_SVINVAL:
2395 return riscv_subset_supports (rps, "svinval");
2396 case INSN_CLASS_H:
2397 return riscv_subset_supports (rps, "h");
2398 default:
2399 rps->error_handler
2400 (_("internal: unreachable INSN_CLASS_*"));
2401 return false;
2402 }
2403 }
2404
2405 /* Each instuction is belonged to an instruction class INSN_CLASS_*.
2406 Call riscv_subset_supports_ext to determine the missing extension. */
2407
2408 const char *
2409 riscv_multi_subset_supports_ext (riscv_parse_subset_t *rps,
2410 enum riscv_insn_class insn_class)
2411 {
2412 switch (insn_class)
2413 {
2414 case INSN_CLASS_I:
2415 return "i";
2416 case INSN_CLASS_ZICSR:
2417 return "zicsr";
2418 case INSN_CLASS_ZIFENCEI:
2419 return "zifencei";
2420 case INSN_CLASS_ZIHINTPAUSE:
2421 return "zihintpause";
2422 case INSN_CLASS_M:
2423 return "m";
2424 case INSN_CLASS_A:
2425 return "a";
2426 case INSN_CLASS_F:
2427 return "f";
2428 case INSN_CLASS_D:
2429 return "d";
2430 case INSN_CLASS_Q:
2431 return "q";
2432 case INSN_CLASS_C:
2433 return "c";
2434 case INSN_CLASS_F_AND_C:
2435 if (!riscv_subset_supports (rps, "f")
2436 && !riscv_subset_supports (rps, "c"))
2437 return _("f' and `c");
2438 else if (!riscv_subset_supports (rps, "f"))
2439 return "f";
2440 else
2441 return "c";
2442 case INSN_CLASS_D_AND_C:
2443 if (!riscv_subset_supports (rps, "d")
2444 && !riscv_subset_supports (rps, "c"))
2445 return _("d' and `c");
2446 else if (!riscv_subset_supports (rps, "d"))
2447 return "d";
2448 else
2449 return "c";
2450 case INSN_CLASS_F_OR_ZFINX:
2451 /* i18n: Formatted like "extension `f' or `zfinx' required". */
2452 return _("f' or `zfinx");
2453 case INSN_CLASS_D_OR_ZDINX:
2454 return _("d' or `zdinx");
2455 case INSN_CLASS_Q_OR_ZQINX:
2456 return _("q' or `zqinx");
2457 case INSN_CLASS_ZBA:
2458 return "zba";
2459 case INSN_CLASS_ZBB:
2460 return "zbb";
2461 case INSN_CLASS_ZBC:
2462 return "zbc";
2463 case INSN_CLASS_ZBS:
2464 return "zbs";
2465 case INSN_CLASS_ZBKB:
2466 return "zbkb";
2467 case INSN_CLASS_ZBKC:
2468 return "zbkc";
2469 case INSN_CLASS_ZBKX:
2470 return "zbkx";
2471 case INSN_CLASS_ZBB_OR_ZBKB:
2472 return _("zbb' or `zbkb");
2473 case INSN_CLASS_ZBC_OR_ZBKC:
2474 return _("zbc' or `zbkc");
2475 case INSN_CLASS_ZKND:
2476 return "zknd";
2477 case INSN_CLASS_ZKNE:
2478 return "zkne";
2479 case INSN_CLASS_ZKNH:
2480 return "zknh";
2481 case INSN_CLASS_ZKND_OR_ZKNE:
2482 return _("zknd' or `zkne");
2483 case INSN_CLASS_ZKSED:
2484 return "zksed";
2485 case INSN_CLASS_ZKSH:
2486 return "zksh";
2487 case INSN_CLASS_V:
2488 return _("v' or `zve64x' or `zve32x");
2489 case INSN_CLASS_ZVEF:
2490 return _("v' or `zve64d' or `zve64f' or `zve32f");
2491 case INSN_CLASS_SVINVAL:
2492 return "svinval";
2493 case INSN_CLASS_ZFH:
2494 return "zfh";
2495 case INSN_CLASS_ZFH_OR_ZHINX:
2496 return _("zfh' or 'zhinx");
2497 case INSN_CLASS_D_AND_ZFH_INX:
2498 return _("('d' and 'zfh') or 'zhinx");
2499 case INSN_CLASS_Q_AND_ZFH_INX:
2500 return _("('q' and 'zfh') or 'zhinx");
2501 case INSN_CLASS_H:
2502 return _("h");
2503 default:
2504 rps->error_handler
2505 (_("internal: unreachable INSN_CLASS_*"));
2506 return NULL;
2507 }
2508 }