RISC-V: Add 'Sscofpmf' extension with its CSRs
[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, 1, 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 {"svinval", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1237 {NULL, 0, 0, 0, 0}
1238 };
1239
1240 static struct riscv_supported_ext riscv_supported_std_zxm_ext[] =
1241 {
1242 {NULL, 0, 0, 0, 0}
1243 };
1244
1245 const struct riscv_supported_ext *riscv_all_supported_ext[] =
1246 {
1247 riscv_supported_std_ext,
1248 riscv_supported_std_z_ext,
1249 riscv_supported_std_s_ext,
1250 riscv_supported_std_zxm_ext,
1251 NULL
1252 };
1253
1254 /* ISA extension prefixed name class. Must define them in parsing order. */
1255 enum riscv_prefix_ext_class
1256 {
1257 RV_ISA_CLASS_Z = 1,
1258 RV_ISA_CLASS_S,
1259 RV_ISA_CLASS_ZXM,
1260 RV_ISA_CLASS_X,
1261 RV_ISA_CLASS_UNKNOWN
1262 };
1263
1264 /* Record the strings of the prefixed extensions, and their corresponding
1265 classes. The more letters of the prefix string, the more forward it must
1266 be defined. Otherwise, the riscv_get_prefix_class will map it to the
1267 wrong classes. */
1268 struct riscv_parse_prefix_config
1269 {
1270 /* Class of the extension. */
1271 enum riscv_prefix_ext_class class;
1272
1273 /* Prefix string for error printing and internal parser usage. */
1274 const char *prefix;
1275 };
1276 static const struct riscv_parse_prefix_config parse_config[] =
1277 {
1278 {RV_ISA_CLASS_ZXM, "zxm"},
1279 {RV_ISA_CLASS_Z, "z"},
1280 {RV_ISA_CLASS_S, "s"},
1281 {RV_ISA_CLASS_X, "x"},
1282 {RV_ISA_CLASS_UNKNOWN, NULL}
1283 };
1284
1285 /* Get the prefixed name class for the extensions, the class also
1286 means the order of the prefixed extensions. */
1287
1288 static enum riscv_prefix_ext_class
1289 riscv_get_prefix_class (const char *arch)
1290 {
1291 int i = 0;
1292 while (parse_config[i].class != RV_ISA_CLASS_UNKNOWN)
1293 {
1294 if (strncmp (arch, parse_config[i].prefix,
1295 strlen (parse_config[i].prefix)) == 0)
1296 return parse_config[i].class;
1297 i++;
1298 }
1299 return RV_ISA_CLASS_UNKNOWN;
1300 }
1301
1302 /* Check KNOWN_EXTS to see if the EXT is supported. */
1303
1304 static bool
1305 riscv_known_prefixed_ext (const char *ext,
1306 struct riscv_supported_ext *known_exts)
1307 {
1308 size_t i;
1309 for (i = 0; known_exts[i].name != NULL; ++i)
1310 if (strcmp (ext, known_exts[i].name) == 0)
1311 return true;
1312 return false;
1313 }
1314
1315 /* Check whether the prefixed extension is recognized or not. Return
1316 true if recognized, otehrwise return false. */
1317
1318 static bool
1319 riscv_recognized_prefixed_ext (const char *ext)
1320 {
1321 enum riscv_prefix_ext_class class = riscv_get_prefix_class (ext);
1322 switch (class)
1323 {
1324 case RV_ISA_CLASS_Z:
1325 return riscv_known_prefixed_ext (ext, riscv_supported_std_z_ext);
1326 case RV_ISA_CLASS_ZXM:
1327 return riscv_known_prefixed_ext (ext, riscv_supported_std_zxm_ext);
1328 case RV_ISA_CLASS_S:
1329 return riscv_known_prefixed_ext (ext, riscv_supported_std_s_ext);
1330 case RV_ISA_CLASS_X:
1331 /* Only the single x is unrecognized. */
1332 if (strcmp (ext, "x") != 0)
1333 return true;
1334 default:
1335 break;
1336 }
1337 return false;
1338 }
1339
1340 /* Canonical order for single letter extensions. */
1341 static const char riscv_ext_canonical_order[] = "eigmafdqlcbkjtpvnh";
1342
1343 /* Array is used to compare the orders of standard extensions quickly. */
1344 static int riscv_ext_order[26] = {0};
1345
1346 /* Init the riscv_ext_order array. */
1347
1348 static void
1349 riscv_init_ext_order (void)
1350 {
1351 static bool inited = false;
1352 if (inited)
1353 return;
1354
1355 /* The orders of all standard extensions are positive. */
1356 int order = 1;
1357
1358 for (const char *ext = &riscv_ext_canonical_order[0]; *ext; ++ext)
1359 riscv_ext_order[(*ext - 'a')] = order++;
1360
1361 /* Some of the prefixed keyword are not single letter, so we set
1362 their prefixed orders in the riscv_compare_subsets directly,
1363 not through the riscv_ext_order. */
1364
1365 inited = true;
1366 }
1367
1368 /* Similar to the strcmp. It returns an integer less than, equal to,
1369 or greater than zero if `subset2` is found, respectively, to be less
1370 than, to match, or be greater than `subset1`.
1371
1372 The order values,
1373 Zero: Preserved keywords.
1374 Positive number: Standard extensions.
1375 Negative number: Prefixed keywords. */
1376
1377 int
1378 riscv_compare_subsets (const char *subset1, const char *subset2)
1379 {
1380 int order1 = riscv_ext_order[(*subset1 - 'a')];
1381 int order2 = riscv_ext_order[(*subset2 - 'a')];
1382
1383 /* Compare the standard extension first. */
1384 if (order1 > 0 && order2 > 0)
1385 return order1 - order2;
1386
1387 /* Set the prefixed orders to negative numbers. */
1388 enum riscv_prefix_ext_class class1 = riscv_get_prefix_class (subset1);
1389 enum riscv_prefix_ext_class class2 = riscv_get_prefix_class (subset2);
1390
1391 if (class1 != RV_ISA_CLASS_UNKNOWN)
1392 order1 = - (int) class1;
1393 if (class2 != RV_ISA_CLASS_UNKNOWN)
1394 order2 = - (int) class2;
1395
1396 if (order1 == order2)
1397 {
1398 /* Compare the standard addition z extensions. */
1399 if (class1 == RV_ISA_CLASS_Z)
1400 {
1401 order1 = riscv_ext_order[(*++subset1 - 'a')];
1402 order2 = riscv_ext_order[(*++subset2 - 'a')];
1403 if (order1 != order2)
1404 return order1 - order2;
1405 }
1406 return strcasecmp (++subset1, ++subset2);
1407 }
1408
1409 return order2 - order1;
1410 }
1411
1412 /* Find subset in the list. Return TRUE and set `current` to the subset
1413 if it is found. Otherwise, return FALSE and set `current` to the place
1414 where we should insert the subset. However, return FALSE with the NULL
1415 `current` means we should insert the subset at the head of subset list,
1416 if needed. */
1417
1418 bool
1419 riscv_lookup_subset (const riscv_subset_list_t *subset_list,
1420 const char *subset,
1421 riscv_subset_t **current)
1422 {
1423 riscv_subset_t *s, *pre_s = NULL;
1424
1425 /* If the subset is added in order, then just add it at the tail. */
1426 if (subset_list->tail != NULL
1427 && riscv_compare_subsets (subset_list->tail->name, subset) < 0)
1428 {
1429 *current = subset_list->tail;
1430 return false;
1431 }
1432
1433 for (s = subset_list->head;
1434 s != NULL;
1435 pre_s = s, s = s->next)
1436 {
1437 int cmp = riscv_compare_subsets (s->name, subset);
1438 if (cmp == 0)
1439 {
1440 *current = s;
1441 return true;
1442 }
1443 else if (cmp > 0)
1444 break;
1445 }
1446 *current = pre_s;
1447
1448 return false;
1449 }
1450
1451 /* Add the extension to the subset list. Search the
1452 list first, and then find the right place to add. */
1453
1454 void
1455 riscv_add_subset (riscv_subset_list_t *subset_list,
1456 const char *subset,
1457 int major,
1458 int minor)
1459 {
1460 riscv_subset_t *current, *new;
1461
1462 if (riscv_lookup_subset (subset_list, subset, &current))
1463 return;
1464
1465 new = xmalloc (sizeof *new);
1466 new->name = xstrdup (subset);
1467 new->major_version = major;
1468 new->minor_version = minor;
1469 new->next = NULL;
1470
1471 if (current != NULL)
1472 {
1473 new->next = current->next;
1474 current->next = new;
1475 }
1476 else
1477 {
1478 new->next = subset_list->head;
1479 subset_list->head = new;
1480 }
1481
1482 if (new->next == NULL)
1483 subset_list->tail = new;
1484 }
1485
1486 /* Get the default versions from the riscv_supported_*ext tables. */
1487
1488 static void
1489 riscv_get_default_ext_version (enum riscv_spec_class *default_isa_spec,
1490 const char *name,
1491 int *major_version,
1492 int *minor_version)
1493 {
1494 if (name == NULL
1495 || default_isa_spec == NULL
1496 || *default_isa_spec == ISA_SPEC_CLASS_NONE)
1497 return;
1498
1499 struct riscv_supported_ext *table = NULL;
1500 enum riscv_prefix_ext_class class = riscv_get_prefix_class (name);
1501 switch (class)
1502 {
1503 case RV_ISA_CLASS_ZXM: table = riscv_supported_std_zxm_ext; break;
1504 case RV_ISA_CLASS_Z: table = riscv_supported_std_z_ext; break;
1505 case RV_ISA_CLASS_S: table = riscv_supported_std_s_ext; break;
1506 case RV_ISA_CLASS_X:
1507 break;
1508 default:
1509 table = riscv_supported_std_ext;
1510 }
1511
1512 int i = 0;
1513 while (table != NULL && table[i].name != NULL)
1514 {
1515 if (strcmp (table[i].name, name) == 0
1516 && (table[i].isa_spec_class == ISA_SPEC_CLASS_DRAFT
1517 || table[i].isa_spec_class == *default_isa_spec))
1518 {
1519 *major_version = table[i].major_version;
1520 *minor_version = table[i].minor_version;
1521 return;
1522 }
1523 i++;
1524 }
1525 }
1526
1527 /* Find the default versions for the extension before adding them to
1528 the subset list, if their versions are RISCV_UNKNOWN_VERSION.
1529 Afterwards, report errors if we can not find their default versions. */
1530
1531 static void
1532 riscv_parse_add_subset (riscv_parse_subset_t *rps,
1533 const char *subset,
1534 int major,
1535 int minor,
1536 bool implicit)
1537 {
1538 int major_version = major;
1539 int minor_version = minor;
1540
1541 if (major_version == RISCV_UNKNOWN_VERSION
1542 || minor_version == RISCV_UNKNOWN_VERSION)
1543 riscv_get_default_ext_version (rps->isa_spec, subset,
1544 &major_version, &minor_version);
1545
1546 /* We don't care the versions of the implicit extensions. */
1547 if (!implicit
1548 && (major_version == RISCV_UNKNOWN_VERSION
1549 || minor_version == RISCV_UNKNOWN_VERSION))
1550 {
1551 if (subset[0] == 'x')
1552 rps->error_handler
1553 (_("x ISA extension `%s' must be set with the versions"),
1554 subset);
1555 /* Allow old ISA spec can recognize zicsr and zifencei. */
1556 else if (strcmp (subset, "zicsr") != 0
1557 && strcmp (subset, "zifencei") != 0)
1558 rps->error_handler
1559 (_("cannot find default versions of the ISA extension `%s'"),
1560 subset);
1561 return;
1562 }
1563
1564 riscv_add_subset (rps->subset_list, subset,
1565 major_version, minor_version);
1566 }
1567
1568 /* Release subset list. */
1569
1570 void
1571 riscv_release_subset_list (riscv_subset_list_t *subset_list)
1572 {
1573 while (subset_list->head != NULL)
1574 {
1575 riscv_subset_t *next = subset_list->head->next;
1576 free ((void *)subset_list->head->name);
1577 free (subset_list->head);
1578 subset_list->head = next;
1579 }
1580
1581 subset_list->tail = NULL;
1582 }
1583
1584 /* Parsing extension version.
1585
1586 Return Value:
1587 Points to the end of version
1588
1589 Arguments:
1590 `p`: Curent parsing position.
1591 `major_version`: Parsed major version.
1592 `minor_version`: Parsed minor version. */
1593
1594 static const char *
1595 riscv_parsing_subset_version (const char *p,
1596 int *major_version,
1597 int *minor_version)
1598 {
1599 bool major_p = true;
1600 int version = 0;
1601 char np;
1602
1603 *major_version = 0;
1604 *minor_version = 0;
1605 for (; *p; ++p)
1606 {
1607 if (*p == 'p')
1608 {
1609 np = *(p + 1);
1610
1611 /* Might be beginning of `p` extension. */
1612 if (!ISDIGIT (np))
1613 break;
1614
1615 *major_version = version;
1616 major_p = false;
1617 version = 0;
1618 }
1619 else if (ISDIGIT (*p))
1620 version = (version * 10) + (*p - '0');
1621 else
1622 break;
1623 }
1624
1625 if (major_p)
1626 *major_version = version;
1627 else
1628 *minor_version = version;
1629
1630 /* We can not find any version in string. */
1631 if (*major_version == 0 && *minor_version == 0)
1632 {
1633 *major_version = RISCV_UNKNOWN_VERSION;
1634 *minor_version = RISCV_UNKNOWN_VERSION;
1635 }
1636
1637 return p;
1638 }
1639
1640 /* Parsing function for standard extensions.
1641
1642 Return Value:
1643 Points to the end of extensions.
1644
1645 Arguments:
1646 `rps`: Hooks and status for parsing extensions.
1647 `arch`: Full ISA string.
1648 `p`: Curent parsing position. */
1649
1650 static const char *
1651 riscv_parse_std_ext (riscv_parse_subset_t *rps,
1652 const char *arch,
1653 const char *p)
1654 {
1655 /* First letter must start with i, e or g. */
1656 if (*p != 'e' && *p != 'i' && *p != 'g')
1657 {
1658 rps->error_handler
1659 (_("%s: first ISA extension must be `e', `i' or `g'"),
1660 arch);
1661 return NULL;
1662 }
1663
1664 while (p != NULL && *p != '\0')
1665 {
1666 /* Stop when we parsed the known prefix class. */
1667 enum riscv_prefix_ext_class class = riscv_get_prefix_class (p);
1668 if (class != RV_ISA_CLASS_UNKNOWN)
1669 break;
1670
1671 if (*p == '_')
1672 {
1673 p++;
1674 continue;
1675 }
1676
1677 bool implicit = false;
1678 int major = RISCV_UNKNOWN_VERSION;
1679 int minor = RISCV_UNKNOWN_VERSION;
1680 char subset[2] = {0, 0};
1681
1682 subset[0] = *p;
1683
1684 /* Check if the standard extension is supported. */
1685 if (riscv_ext_order[(subset[0] - 'a')] == 0)
1686 {
1687 rps->error_handler
1688 (_("%s: unknown standard ISA extension `%c'"),
1689 arch, subset[0]);
1690 return NULL;
1691 }
1692
1693 /* Checking canonical order. */
1694 if (rps->subset_list->tail != NULL
1695 && riscv_compare_subsets (rps->subset_list->tail->name, subset) > 0)
1696 {
1697 rps->error_handler
1698 (_("%s: standard ISA extension `%c' is not "
1699 "in canonical order"), arch, subset[0]);
1700 return NULL;
1701 }
1702
1703 p = riscv_parsing_subset_version (++p, &major, &minor);
1704 /* Added g as an implicit extension. */
1705 if (subset[0] == 'g')
1706 {
1707 implicit = true;
1708 major = RISCV_UNKNOWN_VERSION;
1709 minor = RISCV_UNKNOWN_VERSION;
1710 }
1711 riscv_parse_add_subset (rps, subset, major, minor, implicit);
1712 }
1713
1714 return p;
1715 }
1716
1717 /* Parsing function for prefixed extensions.
1718
1719 Return Value:
1720 Points to the end of extension.
1721
1722 Arguments:
1723 `rps`: Hooks and status for parsing extensions.
1724 `arch`: Full ISA string.
1725 `p`: Curent parsing position. */
1726
1727 static const char *
1728 riscv_parse_prefixed_ext (riscv_parse_subset_t *rps,
1729 const char *arch,
1730 const char *p)
1731 {
1732 int major_version;
1733 int minor_version;
1734 enum riscv_prefix_ext_class class;
1735
1736 while (*p)
1737 {
1738 if (*p == '_')
1739 {
1740 p++;
1741 continue;
1742 }
1743
1744 class = riscv_get_prefix_class (p);
1745 if (class == RV_ISA_CLASS_UNKNOWN)
1746 {
1747 rps->error_handler
1748 (_("%s: unknown prefix class for the ISA extension `%s'"),
1749 arch, p);
1750 return NULL;
1751 }
1752
1753 char *subset = xstrdup (p);
1754 char *q = subset;
1755 const char *end_of_version;
1756
1757 /* Extract the whole prefixed extension by '_'. */
1758 while (*++q != '\0' && *q != '_')
1759 ;
1760 /* Look forward to the first letter which is not <major>p<minor>. */
1761 bool find_any_version = false;
1762 bool find_minor_version = false;
1763 while (1)
1764 {
1765 q--;
1766 if (ISDIGIT (*q))
1767 find_any_version = true;
1768 else if (find_any_version
1769 && !find_minor_version
1770 && *q == 'p'
1771 && ISDIGIT (*(q - 1)))
1772 find_minor_version = true;
1773 else
1774 break;
1775 }
1776 q++;
1777
1778 /* Check if the end of extension is 'p' or not. If yes, then
1779 the second letter from the end cannot be number. */
1780 if (*(q - 1) == 'p' && ISDIGIT (*(q - 2)))
1781 {
1782 *q = '\0';
1783 rps->error_handler
1784 (_("%s: invalid prefixed ISA extension `%s' ends with <number>p"),
1785 arch, subset);
1786 free (subset);
1787 return NULL;
1788 }
1789
1790 end_of_version =
1791 riscv_parsing_subset_version (q, &major_version, &minor_version);
1792 *q = '\0';
1793 if (end_of_version == NULL)
1794 {
1795 free (subset);
1796 return NULL;
1797 }
1798
1799 /* Check that the extension name is well-formed. */
1800 if (rps->check_unknown_prefixed_ext
1801 && !riscv_recognized_prefixed_ext (subset))
1802 {
1803 rps->error_handler
1804 (_("%s: unknown prefixed ISA extension `%s'"),
1805 arch, subset);
1806 free (subset);
1807 return NULL;
1808 }
1809
1810 riscv_parse_add_subset (rps, subset,
1811 major_version,
1812 minor_version, false);
1813 p += end_of_version - subset;
1814 free (subset);
1815
1816 if (*p != '\0' && *p != '_')
1817 {
1818 rps->error_handler
1819 (_("%s: prefixed ISA extension must separate with _"),
1820 arch);
1821 return NULL;
1822 }
1823 }
1824
1825 return p;
1826 }
1827
1828 /* Add the implicit extensions. */
1829
1830 static void
1831 riscv_parse_add_implicit_subsets (riscv_parse_subset_t *rps)
1832 {
1833 struct riscv_implicit_subset *t = riscv_implicit_subsets;
1834 for (; t->subset_name; t++)
1835 {
1836 riscv_subset_t *subset = NULL;
1837 if (riscv_lookup_subset (rps->subset_list, t->subset_name, &subset)
1838 && t->check_func (t->implicit_name, subset))
1839 riscv_parse_add_subset (rps, t->implicit_name,
1840 RISCV_UNKNOWN_VERSION,
1841 RISCV_UNKNOWN_VERSION, true);
1842 }
1843 }
1844
1845 /* Check extensions conflicts. */
1846
1847 static bool
1848 riscv_parse_check_conflicts (riscv_parse_subset_t *rps)
1849 {
1850 riscv_subset_t *subset = NULL;
1851 int xlen = *rps->xlen;
1852 bool no_conflict = true;
1853
1854 if (riscv_lookup_subset (rps->subset_list, "e", &subset)
1855 && xlen > 32)
1856 {
1857 rps->error_handler
1858 (_("rv%d does not support the `e' extension"), xlen);
1859 no_conflict = false;
1860 }
1861 if (riscv_lookup_subset (rps->subset_list, "q", &subset)
1862 && (subset->major_version < 2 || (subset->major_version == 2
1863 && subset->minor_version < 2))
1864 && xlen < 64)
1865 {
1866 rps->error_handler (_("rv%d does not support the `q' extension"), xlen);
1867 no_conflict = false;
1868 }
1869 if (riscv_lookup_subset (rps->subset_list, "e", &subset)
1870 && riscv_lookup_subset (rps->subset_list, "f", &subset))
1871 {
1872 rps->error_handler
1873 (_("rv32e does not support the `f' extension"));
1874 no_conflict = false;
1875 }
1876 if (riscv_lookup_subset (rps->subset_list, "zfinx", &subset)
1877 && riscv_lookup_subset (rps->subset_list, "f", &subset))
1878 {
1879 rps->error_handler
1880 (_("`zfinx' is conflict with the `f/d/q' extension"));
1881 no_conflict = false;
1882 }
1883
1884 bool support_zve = false;
1885 bool support_zvl = false;
1886 riscv_subset_t *s = rps->subset_list->head;
1887 for (; s != NULL; s = s->next)
1888 {
1889 if (!support_zve
1890 && strncmp (s->name, "zve", 3) == 0)
1891 support_zve = true;
1892 if (!support_zvl
1893 && strncmp (s->name, "zvl", 3) == 0)
1894 support_zvl = true;
1895 if (support_zve && support_zvl)
1896 break;
1897 }
1898 if (support_zvl && !support_zve)
1899 {
1900 rps->error_handler
1901 (_("zvl*b extensions need to enable either `v' or `zve' extension"));
1902 no_conflict = false;
1903 }
1904
1905 return no_conflict;
1906 }
1907
1908 /* Set the default subset list according to the default_enable field
1909 of riscv_supported_*ext tables. */
1910
1911 static void
1912 riscv_set_default_arch (riscv_parse_subset_t *rps)
1913 {
1914 unsigned long enable = EXT_DEFAULT;
1915 int i, j;
1916 for (i = 0; riscv_all_supported_ext[i] != NULL; i++)
1917 {
1918 const struct riscv_supported_ext *table = riscv_all_supported_ext[i];
1919 for (j = 0; table[j].name != NULL; j++)
1920 {
1921 bool implicit = false;
1922 if (strcmp (table[j].name, "g") == 0)
1923 implicit = true;
1924 if (table[j].default_enable & enable)
1925 riscv_parse_add_subset (rps, table[j].name,
1926 RISCV_UNKNOWN_VERSION,
1927 RISCV_UNKNOWN_VERSION, implicit);
1928 }
1929 }
1930 }
1931
1932 /* Function for parsing ISA string.
1933
1934 Return Value:
1935 Return TRUE on success.
1936
1937 Arguments:
1938 `rps`: Hooks and status for parsing extensions.
1939 `arch`: Full ISA string. */
1940
1941 bool
1942 riscv_parse_subset (riscv_parse_subset_t *rps,
1943 const char *arch)
1944 {
1945 const char *p;
1946
1947 /* Init the riscv_ext_order array to compare the order of extensions
1948 quickly. */
1949 riscv_init_ext_order ();
1950
1951 if (arch == NULL)
1952 {
1953 riscv_set_default_arch (rps);
1954 riscv_parse_add_implicit_subsets (rps);
1955 return riscv_parse_check_conflicts (rps);
1956 }
1957
1958 for (p = arch; *p != '\0'; p++)
1959 {
1960 if (ISUPPER (*p))
1961 {
1962 rps->error_handler
1963 (_("%s: ISA string cannot contain uppercase letters"),
1964 arch);
1965 return false;
1966 }
1967 }
1968
1969 p = arch;
1970 if (startswith (p, "rv32"))
1971 {
1972 *rps->xlen = 32;
1973 p += 4;
1974 }
1975 else if (startswith (p, "rv64"))
1976 {
1977 *rps->xlen = 64;
1978 p += 4;
1979 }
1980 else
1981 {
1982 /* ISA string shouldn't be NULL or empty here. For linker,
1983 it might be empty when we failed to merge the ISA string
1984 in the riscv_merge_attributes. For assembler, we might
1985 give an empty string by .attribute arch, "" or -march=.
1986 However, We have already issued the correct error message
1987 in another side, so do not issue this error when the ISA
1988 string is empty. */
1989 if (strlen (arch))
1990 rps->error_handler (
1991 _("%s: ISA string must begin with rv32 or rv64"),
1992 arch);
1993 return false;
1994 }
1995
1996 /* Parsing standard extension. */
1997 p = riscv_parse_std_ext (rps, arch, p);
1998
1999 if (p == NULL)
2000 return false;
2001
2002 /* Parse prefixed extensions. */
2003 p = riscv_parse_prefixed_ext (rps, arch, p);
2004
2005 if (p == NULL)
2006 return false;
2007
2008 /* Finally add implicit extensions according to the current
2009 extensions. */
2010 riscv_parse_add_implicit_subsets (rps);
2011
2012 /* Check the conflicts. */
2013 return riscv_parse_check_conflicts (rps);
2014 }
2015
2016 /* Return the number of digits for the input. */
2017
2018 size_t
2019 riscv_estimate_digit (unsigned num)
2020 {
2021 size_t digit = 0;
2022 if (num == 0)
2023 return 1;
2024
2025 for (digit = 0; num ; num /= 10)
2026 digit++;
2027
2028 return digit;
2029 }
2030
2031 /* Auxiliary function to estimate string length of subset list. */
2032
2033 static size_t
2034 riscv_estimate_arch_strlen1 (const riscv_subset_t *subset)
2035 {
2036 if (subset == NULL)
2037 return 6; /* For rv32/rv64/rv128 and string terminator. */
2038
2039 return riscv_estimate_arch_strlen1 (subset->next)
2040 + strlen (subset->name)
2041 + riscv_estimate_digit (subset->major_version)
2042 + 1 /* For version seperator 'p'. */
2043 + riscv_estimate_digit (subset->minor_version)
2044 + 1 /* For underscore. */;
2045 }
2046
2047 /* Estimate the string length of this subset list. */
2048
2049 static size_t
2050 riscv_estimate_arch_strlen (const riscv_subset_list_t *subset_list)
2051 {
2052 return riscv_estimate_arch_strlen1 (subset_list->head);
2053 }
2054
2055 /* Auxiliary function to convert subset info to string. */
2056
2057 static void
2058 riscv_arch_str1 (riscv_subset_t *subset,
2059 char *attr_str, char *buf, size_t bufsz)
2060 {
2061 const char *underline = "_";
2062 riscv_subset_t *subset_t = subset;
2063
2064 if (subset_t == NULL)
2065 return;
2066
2067 /* No underline between rvXX and i/e. */
2068 if ((strcasecmp (subset_t->name, "i") == 0)
2069 || (strcasecmp (subset_t->name, "e") == 0))
2070 underline = "";
2071
2072 snprintf (buf, bufsz, "%s%s%dp%d",
2073 underline,
2074 subset_t->name,
2075 subset_t->major_version,
2076 subset_t->minor_version);
2077
2078 strncat (attr_str, buf, bufsz);
2079
2080 /* Skip 'i' extension after 'e', or skip extensions which
2081 versions are unknown. */
2082 while (subset_t->next
2083 && ((strcmp (subset_t->name, "e") == 0
2084 && strcmp (subset_t->next->name, "i") == 0)
2085 || subset_t->next->major_version == RISCV_UNKNOWN_VERSION
2086 || subset_t->next->minor_version == RISCV_UNKNOWN_VERSION))
2087 subset_t = subset_t->next;
2088
2089 riscv_arch_str1 (subset_t->next, attr_str, buf, bufsz);
2090 }
2091
2092 /* Convert subset information into string with explicit versions. */
2093
2094 char *
2095 riscv_arch_str (unsigned xlen, const riscv_subset_list_t *subset)
2096 {
2097 size_t arch_str_len = riscv_estimate_arch_strlen (subset);
2098 char *attr_str = xmalloc (arch_str_len);
2099 char *buf = xmalloc (arch_str_len);
2100
2101 snprintf (attr_str, arch_str_len, "rv%u", xlen);
2102
2103 riscv_arch_str1 (subset->head, attr_str, buf, arch_str_len);
2104 free (buf);
2105
2106 return attr_str;
2107 }
2108
2109 /* Copy the subset in the subset list. */
2110
2111 static struct riscv_subset_t *
2112 riscv_copy_subset (riscv_subset_list_t *subset_list,
2113 riscv_subset_t *subset)
2114 {
2115 if (subset == NULL)
2116 return NULL;
2117
2118 riscv_subset_t *new = xmalloc (sizeof *new);
2119 new->name = xstrdup (subset->name);
2120 new->major_version = subset->major_version;
2121 new->minor_version = subset->minor_version;
2122 new->next = riscv_copy_subset (subset_list, subset->next);
2123
2124 if (subset->next == NULL)
2125 subset_list->tail = new;
2126
2127 return new;
2128 }
2129
2130 /* Copy the subset list. */
2131
2132 riscv_subset_list_t *
2133 riscv_copy_subset_list (riscv_subset_list_t *subset_list)
2134 {
2135 riscv_subset_list_t *new = xmalloc (sizeof *new);
2136 new->head = riscv_copy_subset (new, subset_list->head);
2137 return new;
2138 }
2139
2140 /* Remove the SUBSET from the subset list. */
2141
2142 static void
2143 riscv_remove_subset (riscv_subset_list_t *subset_list,
2144 const char *subset)
2145 {
2146 riscv_subset_t *current = subset_list->head;
2147 riscv_subset_t *pre = NULL;
2148 for (; current != NULL; pre = current, current = current->next)
2149 {
2150 if (strcmp (current->name, subset) == 0)
2151 {
2152 if (pre == NULL)
2153 subset_list->head = current->next;
2154 else
2155 pre->next = current->next;
2156 if (current->next == NULL)
2157 subset_list->tail = pre;
2158 free ((void *) current->name);
2159 free (current);
2160 break;
2161 }
2162 }
2163 }
2164
2165 /* Add/Remove an extension to/from the subset list. This is used for
2166 the .option rvc or norvc, and .option arch directives. */
2167
2168 bool
2169 riscv_update_subset (riscv_parse_subset_t *rps,
2170 const char *str)
2171 {
2172 const char *p = str;
2173
2174 do
2175 {
2176 int major_version = RISCV_UNKNOWN_VERSION;
2177 int minor_version = RISCV_UNKNOWN_VERSION;
2178
2179 bool removed = false;
2180 switch (*p)
2181 {
2182 case '+': removed = false; break;
2183 case '-': removed = true; break;
2184 default:
2185 riscv_release_subset_list (rps->subset_list);
2186 return riscv_parse_subset (rps, p);
2187 }
2188 ++p;
2189
2190 char *subset = xstrdup (p);
2191 char *q = subset;
2192 const char *end_of_version;
2193 /* Extract the whole prefixed extension by ','. */
2194 while (*q != '\0' && *q != ',')
2195 q++;
2196
2197 /* Look forward to the first letter which is not <major>p<minor>. */
2198 bool find_any_version = false;
2199 bool find_minor_version = false;
2200 size_t len = q - subset;
2201 size_t i;
2202 for (i = len; i > 0; i--)
2203 {
2204 q--;
2205 if (ISDIGIT (*q))
2206 find_any_version = true;
2207 else if (find_any_version
2208 && !find_minor_version
2209 && *q == 'p'
2210 && ISDIGIT (*(q - 1)))
2211 find_minor_version = true;
2212 else
2213 break;
2214 }
2215 if (len > 0)
2216 q++;
2217
2218 /* Check if the end of extension is 'p' or not. If yes, then
2219 the second letter from the end cannot be number. */
2220 if (len > 1 && *(q - 1) == 'p' && ISDIGIT (*(q - 2)))
2221 {
2222 *q = '\0';
2223 rps->error_handler
2224 (_("invalid ISA extension ends with <number>p "
2225 "in .option arch `%s'"), str);
2226 free (subset);
2227 return false;
2228 }
2229
2230 end_of_version =
2231 riscv_parsing_subset_version (q, &major_version, &minor_version);
2232 *q = '\0';
2233 if (end_of_version == NULL)
2234 {
2235 free (subset);
2236 return false;
2237 }
2238
2239 if (strlen (subset) == 0
2240 || (strlen (subset) == 1
2241 && riscv_ext_order[(*subset - 'a')] == 0)
2242 || (strlen (subset) > 1
2243 && rps->check_unknown_prefixed_ext
2244 && !riscv_recognized_prefixed_ext (subset)))
2245 {
2246 rps->error_handler
2247 (_("unknown ISA extension `%s' in .option arch `%s'"),
2248 subset, str);
2249 free (subset);
2250 return false;
2251 }
2252
2253 if (strcmp (subset, "i") == 0
2254 || strcmp (subset, "e") == 0
2255 || strcmp (subset, "g") == 0)
2256 {
2257 rps->error_handler
2258 (_("cannot + or - base extension `%s' in .option "
2259 "arch `%s'"), subset, str);
2260 free (subset);
2261 return false;
2262 }
2263
2264 if (removed)
2265 riscv_remove_subset (rps->subset_list, subset);
2266 else
2267 riscv_parse_add_subset (rps, subset, major_version, minor_version, true);
2268 p += end_of_version - subset;
2269 free (subset);
2270 }
2271 while (*p++ == ',');
2272
2273 riscv_parse_add_implicit_subsets (rps);
2274 return riscv_parse_check_conflicts (rps);
2275 }
2276
2277 /* Check if the FEATURE subset is supported or not in the subset list.
2278 Return true if it is supported; Otherwise, return false. */
2279
2280 bool
2281 riscv_subset_supports (riscv_parse_subset_t *rps,
2282 const char *feature)
2283 {
2284 struct riscv_subset_t *subset;
2285 return riscv_lookup_subset (rps->subset_list, feature, &subset);
2286 }
2287
2288 /* Each instuction is belonged to an instruction class INSN_CLASS_*.
2289 Call riscv_subset_supports to make sure if the instuction is valid. */
2290
2291 bool
2292 riscv_multi_subset_supports (riscv_parse_subset_t *rps,
2293 enum riscv_insn_class insn_class)
2294 {
2295 switch (insn_class)
2296 {
2297 case INSN_CLASS_I:
2298 return riscv_subset_supports (rps, "i");
2299 case INSN_CLASS_ZICBOM:
2300 return riscv_subset_supports (rps, "zicbom");
2301 case INSN_CLASS_ZICBOP:
2302 return riscv_subset_supports (rps, "zicbop");
2303 case INSN_CLASS_ZICBOZ:
2304 return riscv_subset_supports (rps, "zicboz");
2305 case INSN_CLASS_ZICSR:
2306 return riscv_subset_supports (rps, "zicsr");
2307 case INSN_CLASS_ZIFENCEI:
2308 return riscv_subset_supports (rps, "zifencei");
2309 case INSN_CLASS_ZIHINTPAUSE:
2310 return riscv_subset_supports (rps, "zihintpause");
2311 case INSN_CLASS_M:
2312 return riscv_subset_supports (rps, "m");
2313 case INSN_CLASS_A:
2314 return riscv_subset_supports (rps, "a");
2315 case INSN_CLASS_F:
2316 return riscv_subset_supports (rps, "f");
2317 case INSN_CLASS_D:
2318 return riscv_subset_supports (rps, "d");
2319 case INSN_CLASS_Q:
2320 return riscv_subset_supports (rps, "q");
2321 case INSN_CLASS_C:
2322 return riscv_subset_supports (rps, "c");
2323 case INSN_CLASS_F_AND_C:
2324 return (riscv_subset_supports (rps, "f")
2325 && riscv_subset_supports (rps, "c"));
2326 case INSN_CLASS_D_AND_C:
2327 return (riscv_subset_supports (rps, "d")
2328 && riscv_subset_supports (rps, "c"));
2329 case INSN_CLASS_F_OR_ZFINX:
2330 return (riscv_subset_supports (rps, "f")
2331 || riscv_subset_supports (rps, "zfinx"));
2332 case INSN_CLASS_D_OR_ZDINX:
2333 return (riscv_subset_supports (rps, "d")
2334 || riscv_subset_supports (rps, "zdinx"));
2335 case INSN_CLASS_Q_OR_ZQINX:
2336 return (riscv_subset_supports (rps, "q")
2337 || riscv_subset_supports (rps, "zqinx"));
2338 case INSN_CLASS_ZFH:
2339 return riscv_subset_supports (rps, "zfh");
2340 case INSN_CLASS_ZFH_OR_ZHINX:
2341 return riscv_subset_supports (rps, "zfh")
2342 || riscv_subset_supports (rps, "zhinx");
2343 case INSN_CLASS_D_AND_ZFH_INX:
2344 return (riscv_subset_supports (rps, "d")
2345 && riscv_subset_supports (rps, "zfh"))
2346 || riscv_subset_supports (rps, "zhinx");
2347 case INSN_CLASS_Q_AND_ZFH_INX:
2348 return (riscv_subset_supports (rps, "q")
2349 && riscv_subset_supports (rps, "zfh"))
2350 || riscv_subset_supports (rps, "zhinx");
2351 case INSN_CLASS_ZBA:
2352 return riscv_subset_supports (rps, "zba");
2353 case INSN_CLASS_ZBB:
2354 return riscv_subset_supports (rps, "zbb");
2355 case INSN_CLASS_ZBC:
2356 return riscv_subset_supports (rps, "zbc");
2357 case INSN_CLASS_ZBS:
2358 return riscv_subset_supports (rps, "zbs");
2359 case INSN_CLASS_ZBKB:
2360 return riscv_subset_supports (rps, "zbkb");
2361 case INSN_CLASS_ZBKC:
2362 return riscv_subset_supports (rps, "zbkc");
2363 case INSN_CLASS_ZBKX:
2364 return riscv_subset_supports (rps, "zbkx");
2365 case INSN_CLASS_ZBB_OR_ZBKB:
2366 return (riscv_subset_supports (rps, "zbb")
2367 || riscv_subset_supports (rps, "zbkb"));
2368 case INSN_CLASS_ZBC_OR_ZBKC:
2369 return (riscv_subset_supports (rps, "zbc")
2370 || riscv_subset_supports (rps, "zbkc"));
2371 case INSN_CLASS_ZKND:
2372 return riscv_subset_supports (rps, "zknd");
2373 case INSN_CLASS_ZKNE:
2374 return riscv_subset_supports (rps, "zkne");
2375 case INSN_CLASS_ZKNH:
2376 return riscv_subset_supports (rps, "zknh");
2377 case INSN_CLASS_ZKND_OR_ZKNE:
2378 return (riscv_subset_supports (rps, "zknd")
2379 || riscv_subset_supports (rps, "zkne"));
2380 case INSN_CLASS_ZKSED:
2381 return riscv_subset_supports (rps, "zksed");
2382 case INSN_CLASS_ZKSH:
2383 return riscv_subset_supports (rps, "zksh");
2384 case INSN_CLASS_V:
2385 return (riscv_subset_supports (rps, "v")
2386 || riscv_subset_supports (rps, "zve64x")
2387 || riscv_subset_supports (rps, "zve32x"));
2388 case INSN_CLASS_ZVEF:
2389 return (riscv_subset_supports (rps, "v")
2390 || riscv_subset_supports (rps, "zve64d")
2391 || riscv_subset_supports (rps, "zve64f")
2392 || riscv_subset_supports (rps, "zve32f"));
2393 case INSN_CLASS_SVINVAL:
2394 return riscv_subset_supports (rps, "svinval");
2395 case INSN_CLASS_H:
2396 return riscv_subset_supports (rps, "h");
2397 default:
2398 rps->error_handler
2399 (_("internal: unreachable INSN_CLASS_*"));
2400 return false;
2401 }
2402 }
2403
2404 /* Each instuction is belonged to an instruction class INSN_CLASS_*.
2405 Call riscv_subset_supports_ext to determine the missing extension. */
2406
2407 const char *
2408 riscv_multi_subset_supports_ext (riscv_parse_subset_t *rps,
2409 enum riscv_insn_class insn_class)
2410 {
2411 switch (insn_class)
2412 {
2413 case INSN_CLASS_I:
2414 return "i";
2415 case INSN_CLASS_ZICSR:
2416 return "zicsr";
2417 case INSN_CLASS_ZIFENCEI:
2418 return "zifencei";
2419 case INSN_CLASS_ZIHINTPAUSE:
2420 return "zihintpause";
2421 case INSN_CLASS_M:
2422 return "m";
2423 case INSN_CLASS_A:
2424 return "a";
2425 case INSN_CLASS_F:
2426 return "f";
2427 case INSN_CLASS_D:
2428 return "d";
2429 case INSN_CLASS_Q:
2430 return "q";
2431 case INSN_CLASS_C:
2432 return "c";
2433 case INSN_CLASS_F_AND_C:
2434 if (!riscv_subset_supports (rps, "f")
2435 && !riscv_subset_supports (rps, "c"))
2436 return _("f' and `c");
2437 else if (!riscv_subset_supports (rps, "f"))
2438 return "f";
2439 else
2440 return "c";
2441 case INSN_CLASS_D_AND_C:
2442 if (!riscv_subset_supports (rps, "d")
2443 && !riscv_subset_supports (rps, "c"))
2444 return _("d' and `c");
2445 else if (!riscv_subset_supports (rps, "d"))
2446 return "d";
2447 else
2448 return "c";
2449 case INSN_CLASS_F_OR_ZFINX:
2450 /* i18n: Formatted like "extension `f' or `zfinx' required". */
2451 return _("f' or `zfinx");
2452 case INSN_CLASS_D_OR_ZDINX:
2453 return _("d' or `zdinx");
2454 case INSN_CLASS_Q_OR_ZQINX:
2455 return _("q' or `zqinx");
2456 case INSN_CLASS_ZBA:
2457 return "zba";
2458 case INSN_CLASS_ZBB:
2459 return "zbb";
2460 case INSN_CLASS_ZBC:
2461 return "zbc";
2462 case INSN_CLASS_ZBS:
2463 return "zbs";
2464 case INSN_CLASS_ZBKB:
2465 return "zbkb";
2466 case INSN_CLASS_ZBKC:
2467 return "zbkc";
2468 case INSN_CLASS_ZBKX:
2469 return "zbkx";
2470 case INSN_CLASS_ZBB_OR_ZBKB:
2471 return _("zbb' or `zbkb");
2472 case INSN_CLASS_ZBC_OR_ZBKC:
2473 return _("zbc' or `zbkc");
2474 case INSN_CLASS_ZKND:
2475 return "zknd";
2476 case INSN_CLASS_ZKNE:
2477 return "zkne";
2478 case INSN_CLASS_ZKNH:
2479 return "zknh";
2480 case INSN_CLASS_ZKND_OR_ZKNE:
2481 return _("zknd' or `zkne");
2482 case INSN_CLASS_ZKSED:
2483 return "zksed";
2484 case INSN_CLASS_ZKSH:
2485 return "zksh";
2486 case INSN_CLASS_V:
2487 return _("v' or `zve64x' or `zve32x");
2488 case INSN_CLASS_ZVEF:
2489 return _("v' or `zve64d' or `zve64f' or `zve32f");
2490 case INSN_CLASS_SVINVAL:
2491 return "svinval";
2492 case INSN_CLASS_ZFH:
2493 return "zfh";
2494 case INSN_CLASS_ZFH_OR_ZHINX:
2495 return _("zfh' or 'zhinx");
2496 case INSN_CLASS_D_AND_ZFH_INX:
2497 return _("('d' and 'zfh') or 'zhinx");
2498 case INSN_CLASS_Q_AND_ZFH_INX:
2499 return _("('q' and 'zfh') or 'zhinx");
2500 case INSN_CLASS_H:
2501 return _("h");
2502 default:
2503 rps->error_handler
2504 (_("internal: unreachable INSN_CLASS_*"));
2505 return NULL;
2506 }
2507 }