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