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