Automatic date update in version.in
[binutils-gdb.git] / bfd / elfxx-riscv.c
blobd6a3b6c6eae4cf798215a26673eb7e8cab0e61df
1 /* RISC-V-specific support for ELF.
2 Copyright (C) 2011-2023 Free Software Foundation, Inc.
4 Contributed by Andrew Waterman (andrew@sifive.com).
5 Based on TILE-Gx and MIPS targets.
7 This file is part of BFD, the Binary File Descriptor library.
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 3 of the License, or
12 (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with this program; see the file COPYING3. If not,
21 see <http://www.gnu.org/licenses/>. */
23 #include "sysdep.h"
24 #include "bfd.h"
25 #include "libbfd.h"
26 #include "elf-bfd.h"
27 #include "elf/riscv.h"
28 #include "opcode/riscv.h"
29 #include "libiberty.h"
30 #include "elfxx-riscv.h"
31 #include "safe-ctype.h"
33 #define MINUS_ONE ((bfd_vma)0 - 1)
35 /* Special handler for ADD/SUB relocations that allows them to be filled out
36 both in the pre-linked and post-linked file. This is necessary to make
37 pre-linked debug info work, as due to linker relaxations we need to emit
38 relocations for the debug info. */
39 static bfd_reloc_status_type riscv_elf_add_sub_reloc
40 (bfd *, arelent *, asymbol *, void *, asection *, bfd *, char **);
41 static bfd_reloc_status_type riscv_elf_ignore_reloc
42 (bfd *, arelent *, asymbol *, void *, asection *, bfd *, char **);
44 /* The relocation table used for SHT_RELA sections. */
46 static reloc_howto_type howto_table[] =
48 /* No relocation. */
49 HOWTO (R_RISCV_NONE, /* type */
50 0, /* rightshift */
51 0, /* size */
52 0, /* bitsize */
53 false, /* pc_relative */
54 0, /* bitpos */
55 complain_overflow_dont, /* complain_on_overflow */
56 bfd_elf_generic_reloc, /* special_function */
57 "R_RISCV_NONE", /* name */
58 false, /* partial_inplace */
59 0, /* src_mask */
60 0, /* dst_mask */
61 false), /* pcrel_offset */
63 /* 32 bit relocation. */
64 HOWTO (R_RISCV_32, /* type */
65 0, /* rightshift */
66 4, /* size */
67 32, /* bitsize */
68 false, /* pc_relative */
69 0, /* bitpos */
70 complain_overflow_dont, /* complain_on_overflow */
71 bfd_elf_generic_reloc, /* special_function */
72 "R_RISCV_32", /* name */
73 false, /* partial_inplace */
74 0, /* src_mask */
75 0xffffffff, /* dst_mask */
76 false), /* pcrel_offset */
78 /* 64 bit relocation. */
79 HOWTO (R_RISCV_64, /* type */
80 0, /* rightshift */
81 8, /* size */
82 64, /* bitsize */
83 false, /* pc_relative */
84 0, /* bitpos */
85 complain_overflow_dont, /* complain_on_overflow */
86 bfd_elf_generic_reloc, /* special_function */
87 "R_RISCV_64", /* name */
88 false, /* partial_inplace */
89 0, /* src_mask */
90 MINUS_ONE, /* dst_mask */
91 false), /* pcrel_offset */
93 /* Relocation against a local symbol in a shared object. */
94 HOWTO (R_RISCV_RELATIVE, /* type */
95 0, /* rightshift */
96 4, /* size */
97 32, /* bitsize */
98 false, /* pc_relative */
99 0, /* bitpos */
100 complain_overflow_dont, /* complain_on_overflow */
101 bfd_elf_generic_reloc, /* special_function */
102 "R_RISCV_RELATIVE", /* name */
103 false, /* partial_inplace */
104 0, /* src_mask */
105 0xffffffff, /* dst_mask */
106 false), /* pcrel_offset */
108 HOWTO (R_RISCV_COPY, /* type */
109 0, /* rightshift */
110 0, /* this one is variable size */
111 0, /* bitsize */
112 false, /* pc_relative */
113 0, /* bitpos */
114 complain_overflow_bitfield, /* complain_on_overflow */
115 bfd_elf_generic_reloc, /* special_function */
116 "R_RISCV_COPY", /* name */
117 false, /* partial_inplace */
118 0, /* src_mask */
119 0, /* dst_mask */
120 false), /* pcrel_offset */
122 HOWTO (R_RISCV_JUMP_SLOT, /* type */
123 0, /* rightshift */
124 8, /* size */
125 64, /* bitsize */
126 false, /* pc_relative */
127 0, /* bitpos */
128 complain_overflow_bitfield, /* complain_on_overflow */
129 bfd_elf_generic_reloc, /* special_function */
130 "R_RISCV_JUMP_SLOT", /* name */
131 false, /* partial_inplace */
132 0, /* src_mask */
133 0, /* dst_mask */
134 false), /* pcrel_offset */
136 /* Dynamic TLS relocations. */
137 HOWTO (R_RISCV_TLS_DTPMOD32, /* type */
138 0, /* rightshift */
139 4, /* size */
140 32, /* bitsize */
141 false, /* pc_relative */
142 0, /* bitpos */
143 complain_overflow_dont, /* complain_on_overflow */
144 bfd_elf_generic_reloc, /* special_function */
145 "R_RISCV_TLS_DTPMOD32", /* name */
146 false, /* partial_inplace */
147 0, /* src_mask */
148 0xffffffff, /* dst_mask */
149 false), /* pcrel_offset */
151 HOWTO (R_RISCV_TLS_DTPMOD64, /* type */
152 0, /* rightshift */
153 8, /* size */
154 64, /* bitsize */
155 false, /* pc_relative */
156 0, /* bitpos */
157 complain_overflow_dont, /* complain_on_overflow */
158 bfd_elf_generic_reloc, /* special_function */
159 "R_RISCV_TLS_DTPMOD64", /* name */
160 false, /* partial_inplace */
161 0, /* src_mask */
162 MINUS_ONE, /* dst_mask */
163 false), /* pcrel_offset */
165 HOWTO (R_RISCV_TLS_DTPREL32, /* type */
166 0, /* rightshift */
167 4, /* size */
168 32, /* bitsize */
169 false, /* pc_relative */
170 0, /* bitpos */
171 complain_overflow_dont, /* complain_on_overflow */
172 bfd_elf_generic_reloc, /* special_function */
173 "R_RISCV_TLS_DTPREL32", /* name */
174 true, /* partial_inplace */
175 0, /* src_mask */
176 0xffffffff, /* dst_mask */
177 false), /* pcrel_offset */
179 HOWTO (R_RISCV_TLS_DTPREL64, /* type */
180 0, /* rightshift */
181 8, /* size */
182 64, /* bitsize */
183 false, /* pc_relative */
184 0, /* bitpos */
185 complain_overflow_dont, /* complain_on_overflow */
186 bfd_elf_generic_reloc, /* special_function */
187 "R_RISCV_TLS_DTPREL64", /* name */
188 true, /* partial_inplace */
189 0, /* src_mask */
190 MINUS_ONE, /* dst_mask */
191 false), /* pcrel_offset */
193 HOWTO (R_RISCV_TLS_TPREL32, /* type */
194 0, /* rightshift */
195 4, /* size */
196 32, /* bitsize */
197 false, /* pc_relative */
198 0, /* bitpos */
199 complain_overflow_dont, /* complain_on_overflow */
200 bfd_elf_generic_reloc, /* special_function */
201 "R_RISCV_TLS_TPREL32", /* name */
202 false, /* partial_inplace */
203 0, /* src_mask */
204 0xffffffff, /* dst_mask */
205 false), /* pcrel_offset */
207 HOWTO (R_RISCV_TLS_TPREL64, /* type */
208 0, /* rightshift */
209 8, /* size */
210 64, /* bitsize */
211 false, /* pc_relative */
212 0, /* bitpos */
213 complain_overflow_dont, /* complain_on_overflow */
214 bfd_elf_generic_reloc, /* special_function */
215 "R_RISCV_TLS_TPREL64", /* name */
216 false, /* partial_inplace */
217 0, /* src_mask */
218 MINUS_ONE, /* dst_mask */
219 false), /* pcrel_offset */
221 EMPTY_HOWTO (12),
222 EMPTY_HOWTO (13),
223 EMPTY_HOWTO (14),
224 EMPTY_HOWTO (15),
226 /* 12-bit PC-relative branch offset. */
227 HOWTO (R_RISCV_BRANCH, /* type */
228 0, /* rightshift */
229 4, /* size */
230 32, /* bitsize */
231 true, /* pc_relative */
232 0, /* bitpos */
233 complain_overflow_signed, /* complain_on_overflow */
234 bfd_elf_generic_reloc, /* special_function */
235 "R_RISCV_BRANCH", /* name */
236 false, /* partial_inplace */
237 0, /* src_mask */
238 ENCODE_BTYPE_IMM (-1U), /* dst_mask */
239 true), /* pcrel_offset */
241 /* 20-bit PC-relative jump offset. */
242 HOWTO (R_RISCV_JAL, /* type */
243 0, /* rightshift */
244 4, /* size */
245 32, /* bitsize */
246 true, /* pc_relative */
247 0, /* bitpos */
248 complain_overflow_dont, /* complain_on_overflow */
249 bfd_elf_generic_reloc, /* special_function */
250 "R_RISCV_JAL", /* name */
251 false, /* partial_inplace */
252 0, /* src_mask */
253 ENCODE_JTYPE_IMM (-1U), /* dst_mask */
254 true), /* pcrel_offset */
256 /* 32-bit PC-relative function call (AUIPC/JALR). */
257 HOWTO (R_RISCV_CALL, /* type */
258 0, /* rightshift */
259 8, /* size */
260 64, /* bitsize */
261 true, /* pc_relative */
262 0, /* bitpos */
263 complain_overflow_dont, /* complain_on_overflow */
264 bfd_elf_generic_reloc, /* special_function */
265 "R_RISCV_CALL", /* name */
266 false, /* partial_inplace */
267 0, /* src_mask */
268 ENCODE_UTYPE_IMM (-1U) | ((bfd_vma) ENCODE_ITYPE_IMM (-1U) << 32),
269 /* dst_mask */
270 true), /* pcrel_offset */
272 /* Like R_RISCV_CALL, but not locally binding. */
273 HOWTO (R_RISCV_CALL_PLT, /* type */
274 0, /* rightshift */
275 8, /* size */
276 64, /* bitsize */
277 true, /* pc_relative */
278 0, /* bitpos */
279 complain_overflow_dont, /* complain_on_overflow */
280 bfd_elf_generic_reloc, /* special_function */
281 "R_RISCV_CALL_PLT", /* name */
282 false, /* partial_inplace */
283 0, /* src_mask */
284 ENCODE_UTYPE_IMM (-1U) | ((bfd_vma) ENCODE_ITYPE_IMM (-1U) << 32),
285 /* dst_mask */
286 true), /* pcrel_offset */
288 /* High 20 bits of 32-bit PC-relative GOT access. */
289 HOWTO (R_RISCV_GOT_HI20, /* type */
290 0, /* rightshift */
291 4, /* size */
292 32, /* bitsize */
293 true, /* pc_relative */
294 0, /* bitpos */
295 complain_overflow_dont, /* complain_on_overflow */
296 bfd_elf_generic_reloc, /* special_function */
297 "R_RISCV_GOT_HI20", /* name */
298 false, /* partial_inplace */
299 0, /* src_mask */
300 ENCODE_UTYPE_IMM (-1U), /* dst_mask */
301 false), /* pcrel_offset */
303 /* High 20 bits of 32-bit PC-relative TLS IE GOT access. */
304 HOWTO (R_RISCV_TLS_GOT_HI20, /* type */
305 0, /* rightshift */
306 4, /* size */
307 32, /* bitsize */
308 true, /* pc_relative */
309 0, /* bitpos */
310 complain_overflow_dont, /* complain_on_overflow */
311 bfd_elf_generic_reloc, /* special_function */
312 "R_RISCV_TLS_GOT_HI20", /* name */
313 false, /* partial_inplace */
314 0, /* src_mask */
315 ENCODE_UTYPE_IMM (-1U), /* dst_mask */
316 false), /* pcrel_offset */
318 /* High 20 bits of 32-bit PC-relative TLS GD GOT reference. */
319 HOWTO (R_RISCV_TLS_GD_HI20, /* type */
320 0, /* rightshift */
321 4, /* size */
322 32, /* bitsize */
323 true, /* pc_relative */
324 0, /* bitpos */
325 complain_overflow_dont, /* complain_on_overflow */
326 bfd_elf_generic_reloc, /* special_function */
327 "R_RISCV_TLS_GD_HI20", /* name */
328 false, /* partial_inplace */
329 0, /* src_mask */
330 ENCODE_UTYPE_IMM (-1U), /* dst_mask */
331 false), /* pcrel_offset */
333 /* High 20 bits of 32-bit PC-relative reference. */
334 HOWTO (R_RISCV_PCREL_HI20, /* type */
335 0, /* rightshift */
336 4, /* size */
337 32, /* bitsize */
338 true, /* pc_relative */
339 0, /* bitpos */
340 complain_overflow_dont, /* complain_on_overflow */
341 bfd_elf_generic_reloc, /* special_function */
342 "R_RISCV_PCREL_HI20", /* name */
343 false, /* partial_inplace */
344 0, /* src_mask */
345 ENCODE_UTYPE_IMM (-1U), /* dst_mask */
346 true), /* pcrel_offset */
348 /* Low 12 bits of a 32-bit PC-relative load or add. */
349 HOWTO (R_RISCV_PCREL_LO12_I, /* type */
350 0, /* rightshift */
351 4, /* size */
352 32, /* bitsize */
353 false, /* pc_relative */
354 0, /* bitpos */
355 complain_overflow_dont, /* complain_on_overflow */
356 bfd_elf_generic_reloc, /* special_function */
357 "R_RISCV_PCREL_LO12_I", /* name */
358 false, /* partial_inplace */
359 0, /* src_mask */
360 ENCODE_ITYPE_IMM (-1U), /* dst_mask */
361 false), /* pcrel_offset */
363 /* Low 12 bits of a 32-bit PC-relative store. */
364 HOWTO (R_RISCV_PCREL_LO12_S, /* type */
365 0, /* rightshift */
366 4, /* size */
367 32, /* bitsize */
368 false, /* pc_relative */
369 0, /* bitpos */
370 complain_overflow_dont, /* complain_on_overflow */
371 bfd_elf_generic_reloc, /* special_function */
372 "R_RISCV_PCREL_LO12_S", /* name */
373 false, /* partial_inplace */
374 0, /* src_mask */
375 ENCODE_STYPE_IMM (-1U), /* dst_mask */
376 false), /* pcrel_offset */
378 /* High 20 bits of 32-bit absolute address. */
379 HOWTO (R_RISCV_HI20, /* type */
380 0, /* rightshift */
381 4, /* size */
382 32, /* bitsize */
383 false, /* pc_relative */
384 0, /* bitpos */
385 complain_overflow_dont, /* complain_on_overflow */
386 bfd_elf_generic_reloc, /* special_function */
387 "R_RISCV_HI20", /* name */
388 false, /* partial_inplace */
389 0, /* src_mask */
390 ENCODE_UTYPE_IMM (-1U), /* dst_mask */
391 false), /* pcrel_offset */
393 /* High 12 bits of 32-bit load or add. */
394 HOWTO (R_RISCV_LO12_I, /* type */
395 0, /* rightshift */
396 4, /* size */
397 32, /* bitsize */
398 false, /* pc_relative */
399 0, /* bitpos */
400 complain_overflow_dont, /* complain_on_overflow */
401 bfd_elf_generic_reloc, /* special_function */
402 "R_RISCV_LO12_I", /* name */
403 false, /* partial_inplace */
404 0, /* src_mask */
405 ENCODE_ITYPE_IMM (-1U), /* dst_mask */
406 false), /* pcrel_offset */
408 /* High 12 bits of 32-bit store. */
409 HOWTO (R_RISCV_LO12_S, /* type */
410 0, /* rightshift */
411 4, /* size */
412 32, /* bitsize */
413 false, /* pc_relative */
414 0, /* bitpos */
415 complain_overflow_dont, /* complain_on_overflow */
416 bfd_elf_generic_reloc, /* special_function */
417 "R_RISCV_LO12_S", /* name */
418 false, /* partial_inplace */
419 0, /* src_mask */
420 ENCODE_STYPE_IMM (-1U), /* dst_mask */
421 false), /* pcrel_offset */
423 /* High 20 bits of TLS LE thread pointer offset. */
424 HOWTO (R_RISCV_TPREL_HI20, /* type */
425 0, /* rightshift */
426 4, /* size */
427 32, /* bitsize */
428 false, /* pc_relative */
429 0, /* bitpos */
430 complain_overflow_signed, /* complain_on_overflow */
431 bfd_elf_generic_reloc, /* special_function */
432 "R_RISCV_TPREL_HI20", /* name */
433 true, /* partial_inplace */
434 0, /* src_mask */
435 ENCODE_UTYPE_IMM (-1U), /* dst_mask */
436 false), /* pcrel_offset */
438 /* Low 12 bits of TLS LE thread pointer offset for loads and adds. */
439 HOWTO (R_RISCV_TPREL_LO12_I, /* type */
440 0, /* rightshift */
441 4, /* size */
442 32, /* bitsize */
443 false, /* pc_relative */
444 0, /* bitpos */
445 complain_overflow_signed, /* complain_on_overflow */
446 bfd_elf_generic_reloc, /* special_function */
447 "R_RISCV_TPREL_LO12_I", /* name */
448 false, /* partial_inplace */
449 0, /* src_mask */
450 ENCODE_ITYPE_IMM (-1U), /* dst_mask */
451 false), /* pcrel_offset */
453 /* Low 12 bits of TLS LE thread pointer offset for stores. */
454 HOWTO (R_RISCV_TPREL_LO12_S, /* type */
455 0, /* rightshift */
456 4, /* size */
457 32, /* bitsize */
458 false, /* pc_relative */
459 0, /* bitpos */
460 complain_overflow_signed, /* complain_on_overflow */
461 bfd_elf_generic_reloc, /* special_function */
462 "R_RISCV_TPREL_LO12_S", /* name */
463 false, /* partial_inplace */
464 0, /* src_mask */
465 ENCODE_STYPE_IMM (-1U), /* dst_mask */
466 false), /* pcrel_offset */
468 /* TLS LE thread pointer usage. May be relaxed. */
469 HOWTO (R_RISCV_TPREL_ADD, /* type */
470 0, /* rightshift */
471 0, /* size */
472 0, /* bitsize */
473 false, /* pc_relative */
474 0, /* bitpos */
475 complain_overflow_dont, /* complain_on_overflow */
476 bfd_elf_generic_reloc, /* special_function */
477 "R_RISCV_TPREL_ADD", /* name */
478 false, /* partial_inplace */
479 0, /* src_mask */
480 0, /* dst_mask */
481 false), /* pcrel_offset */
483 /* 8-bit in-place addition, for local label subtraction. */
484 HOWTO (R_RISCV_ADD8, /* type */
485 0, /* rightshift */
486 1, /* size */
487 8, /* bitsize */
488 false, /* pc_relative */
489 0, /* bitpos */
490 complain_overflow_dont, /* complain_on_overflow */
491 riscv_elf_add_sub_reloc, /* special_function */
492 "R_RISCV_ADD8", /* name */
493 false, /* partial_inplace */
494 0, /* src_mask */
495 0xff, /* dst_mask */
496 false), /* pcrel_offset */
498 /* 16-bit in-place addition, for local label subtraction. */
499 HOWTO (R_RISCV_ADD16, /* type */
500 0, /* rightshift */
501 2, /* size */
502 16, /* bitsize */
503 false, /* pc_relative */
504 0, /* bitpos */
505 complain_overflow_dont, /* complain_on_overflow */
506 riscv_elf_add_sub_reloc, /* special_function */
507 "R_RISCV_ADD16", /* name */
508 false, /* partial_inplace */
509 0, /* src_mask */
510 0xffff, /* dst_mask */
511 false), /* pcrel_offset */
513 /* 32-bit in-place addition, for local label subtraction. */
514 HOWTO (R_RISCV_ADD32, /* type */
515 0, /* rightshift */
516 4, /* size */
517 32, /* bitsize */
518 false, /* pc_relative */
519 0, /* bitpos */
520 complain_overflow_dont, /* complain_on_overflow */
521 riscv_elf_add_sub_reloc, /* special_function */
522 "R_RISCV_ADD32", /* name */
523 false, /* partial_inplace */
524 0, /* src_mask */
525 0xffffffff, /* dst_mask */
526 false), /* pcrel_offset */
528 /* 64-bit in-place addition, for local label subtraction. */
529 HOWTO (R_RISCV_ADD64, /* type */
530 0, /* rightshift */
531 8, /* size */
532 64, /* bitsize */
533 false, /* pc_relative */
534 0, /* bitpos */
535 complain_overflow_dont, /* complain_on_overflow */
536 riscv_elf_add_sub_reloc, /* special_function */
537 "R_RISCV_ADD64", /* name */
538 false, /* partial_inplace */
539 0, /* src_mask */
540 MINUS_ONE, /* dst_mask */
541 false), /* pcrel_offset */
543 /* 8-bit in-place addition, for local label subtraction. */
544 HOWTO (R_RISCV_SUB8, /* type */
545 0, /* rightshift */
546 1, /* size */
547 8, /* bitsize */
548 false, /* pc_relative */
549 0, /* bitpos */
550 complain_overflow_dont, /* complain_on_overflow */
551 riscv_elf_add_sub_reloc, /* special_function */
552 "R_RISCV_SUB8", /* name */
553 false, /* partial_inplace */
554 0, /* src_mask */
555 0xff, /* dst_mask */
556 false), /* pcrel_offset */
558 /* 16-bit in-place addition, for local label subtraction. */
559 HOWTO (R_RISCV_SUB16, /* type */
560 0, /* rightshift */
561 2, /* size */
562 16, /* bitsize */
563 false, /* pc_relative */
564 0, /* bitpos */
565 complain_overflow_dont, /* complain_on_overflow */
566 riscv_elf_add_sub_reloc, /* special_function */
567 "R_RISCV_SUB16", /* name */
568 false, /* partial_inplace */
569 0, /* src_mask */
570 0xffff, /* dst_mask */
571 false), /* pcrel_offset */
573 /* 32-bit in-place addition, for local label subtraction. */
574 HOWTO (R_RISCV_SUB32, /* type */
575 0, /* rightshift */
576 4, /* size */
577 32, /* bitsize */
578 false, /* pc_relative */
579 0, /* bitpos */
580 complain_overflow_dont, /* complain_on_overflow */
581 riscv_elf_add_sub_reloc, /* special_function */
582 "R_RISCV_SUB32", /* name */
583 false, /* partial_inplace */
584 0, /* src_mask */
585 0xffffffff, /* dst_mask */
586 false), /* pcrel_offset */
588 /* 64-bit in-place addition, for local label subtraction. */
589 HOWTO (R_RISCV_SUB64, /* type */
590 0, /* rightshift */
591 8, /* size */
592 64, /* bitsize */
593 false, /* pc_relative */
594 0, /* bitpos */
595 complain_overflow_dont, /* complain_on_overflow */
596 riscv_elf_add_sub_reloc, /* special_function */
597 "R_RISCV_SUB64", /* name */
598 false, /* partial_inplace */
599 0, /* src_mask */
600 MINUS_ONE, /* dst_mask */
601 false), /* pcrel_offset */
603 EMPTY_HOWTO (41),
604 EMPTY_HOWTO (42),
606 /* Indicates an alignment statement. The addend field encodes how many
607 bytes of NOPs follow the statement. The desired alignment is the
608 addend rounded up to the next power of two. */
609 HOWTO (R_RISCV_ALIGN, /* type */
610 0, /* rightshift */
611 0, /* size */
612 0, /* bitsize */
613 false, /* pc_relative */
614 0, /* bitpos */
615 complain_overflow_dont, /* complain_on_overflow */
616 bfd_elf_generic_reloc, /* special_function */
617 "R_RISCV_ALIGN", /* name */
618 false, /* partial_inplace */
619 0, /* src_mask */
620 0, /* dst_mask */
621 false), /* pcrel_offset */
623 /* 8-bit PC-relative branch offset. */
624 HOWTO (R_RISCV_RVC_BRANCH, /* type */
625 0, /* rightshift */
626 2, /* size */
627 16, /* bitsize */
628 true, /* pc_relative */
629 0, /* bitpos */
630 complain_overflow_signed, /* complain_on_overflow */
631 bfd_elf_generic_reloc, /* special_function */
632 "R_RISCV_RVC_BRANCH", /* name */
633 false, /* partial_inplace */
634 0, /* src_mask */
635 ENCODE_CBTYPE_IMM (-1U), /* dst_mask */
636 true), /* pcrel_offset */
638 /* 11-bit PC-relative jump offset. */
639 HOWTO (R_RISCV_RVC_JUMP, /* type */
640 0, /* rightshift */
641 2, /* size */
642 16, /* bitsize */
643 true, /* pc_relative */
644 0, /* bitpos */
645 complain_overflow_dont, /* complain_on_overflow */
646 bfd_elf_generic_reloc, /* special_function */
647 "R_RISCV_RVC_JUMP", /* name */
648 false, /* partial_inplace */
649 0, /* src_mask */
650 ENCODE_CJTYPE_IMM (-1U), /* dst_mask */
651 true), /* pcrel_offset */
653 EMPTY_HOWTO (46),
654 EMPTY_HOWTO (47),
655 EMPTY_HOWTO (48),
656 EMPTY_HOWTO (49),
657 EMPTY_HOWTO (50),
659 /* The paired relocation may be relaxed. */
660 HOWTO (R_RISCV_RELAX, /* type */
661 0, /* rightshift */
662 0, /* size */
663 0, /* bitsize */
664 false, /* pc_relative */
665 0, /* bitpos */
666 complain_overflow_dont, /* complain_on_overflow */
667 bfd_elf_generic_reloc, /* special_function */
668 "R_RISCV_RELAX", /* name */
669 false, /* partial_inplace */
670 0, /* src_mask */
671 0, /* dst_mask */
672 false), /* pcrel_offset */
674 /* 6-bit in-place addition, for local label subtraction. */
675 HOWTO (R_RISCV_SUB6, /* type */
676 0, /* rightshift */
677 1, /* size */
678 8, /* bitsize */
679 false, /* pc_relative */
680 0, /* bitpos */
681 complain_overflow_dont, /* complain_on_overflow */
682 riscv_elf_add_sub_reloc, /* special_function */
683 "R_RISCV_SUB6", /* name */
684 false, /* partial_inplace */
685 0, /* src_mask */
686 0x3f, /* dst_mask */
687 false), /* pcrel_offset */
689 /* 6-bit in-place setting, for local label subtraction. */
690 HOWTO (R_RISCV_SET6, /* type */
691 0, /* rightshift */
692 1, /* size */
693 8, /* bitsize */
694 false, /* pc_relative */
695 0, /* bitpos */
696 complain_overflow_dont, /* complain_on_overflow */
697 bfd_elf_generic_reloc, /* special_function */
698 "R_RISCV_SET6", /* name */
699 false, /* partial_inplace */
700 0, /* src_mask */
701 0x3f, /* dst_mask */
702 false), /* pcrel_offset */
704 /* 8-bit in-place setting, for local label subtraction. */
705 HOWTO (R_RISCV_SET8, /* type */
706 0, /* rightshift */
707 1, /* size */
708 8, /* bitsize */
709 false, /* pc_relative */
710 0, /* bitpos */
711 complain_overflow_dont, /* complain_on_overflow */
712 bfd_elf_generic_reloc, /* special_function */
713 "R_RISCV_SET8", /* name */
714 false, /* partial_inplace */
715 0, /* src_mask */
716 0xff, /* dst_mask */
717 false), /* pcrel_offset */
719 /* 16-bit in-place setting, for local label subtraction. */
720 HOWTO (R_RISCV_SET16, /* type */
721 0, /* rightshift */
722 2, /* size */
723 16, /* bitsize */
724 false, /* pc_relative */
725 0, /* bitpos */
726 complain_overflow_dont, /* complain_on_overflow */
727 bfd_elf_generic_reloc, /* special_function */
728 "R_RISCV_SET16", /* name */
729 false, /* partial_inplace */
730 0, /* src_mask */
731 0xffff, /* dst_mask */
732 false), /* pcrel_offset */
734 /* 32-bit in-place setting, for local label subtraction. */
735 HOWTO (R_RISCV_SET32, /* type */
736 0, /* rightshift */
737 4, /* size */
738 32, /* bitsize */
739 false, /* pc_relative */
740 0, /* bitpos */
741 complain_overflow_dont, /* complain_on_overflow */
742 bfd_elf_generic_reloc, /* special_function */
743 "R_RISCV_SET32", /* name */
744 false, /* partial_inplace */
745 0, /* src_mask */
746 0xffffffff, /* dst_mask */
747 false), /* pcrel_offset */
749 /* 32-bit PC relative. */
750 HOWTO (R_RISCV_32_PCREL, /* type */
751 0, /* rightshift */
752 4, /* size */
753 32, /* bitsize */
754 true, /* pc_relative */
755 0, /* bitpos */
756 complain_overflow_dont, /* complain_on_overflow */
757 bfd_elf_generic_reloc, /* special_function */
758 "R_RISCV_32_PCREL", /* name */
759 false, /* partial_inplace */
760 0, /* src_mask */
761 0xffffffff, /* dst_mask */
762 false), /* pcrel_offset */
764 /* Relocation against a local ifunc symbol in a shared object. */
765 HOWTO (R_RISCV_IRELATIVE, /* type */
766 0, /* rightshift */
767 4, /* size */
768 32, /* bitsize */
769 false, /* pc_relative */
770 0, /* bitpos */
771 complain_overflow_dont, /* complain_on_overflow */
772 bfd_elf_generic_reloc, /* special_function */
773 "R_RISCV_IRELATIVE", /* name */
774 false, /* partial_inplace */
775 0, /* src_mask */
776 0xffffffff, /* dst_mask */
777 false), /* pcrel_offset */
779 /* Reserved for R_RISCV_PLT32. */
780 EMPTY_HOWTO (59),
782 /* N-bit in-place setting, for unsigned-leb128 local label subtraction. */
783 HOWTO (R_RISCV_SET_ULEB128, /* type */
784 0, /* rightshift */
785 0, /* size */
786 0, /* bitsize */
787 false, /* pc_relative */
788 0, /* bitpos */
789 complain_overflow_dont, /* complain_on_overflow */
790 riscv_elf_ignore_reloc, /* special_function */
791 "R_RISCV_SET_ULEB128", /* name */
792 false, /* partial_inplace */
793 0, /* src_mask */
794 0, /* dst_mask */
795 false), /* pcrel_offset */
797 /* N-bit in-place addition, for unsigned-leb128 local label subtraction. */
798 HOWTO (R_RISCV_SUB_ULEB128, /* type */
799 0, /* rightshift */
800 0, /* size */
801 0, /* bitsize */
802 false, /* pc_relative */
803 0, /* bitpos */
804 complain_overflow_dont, /* complain_on_overflow */
805 riscv_elf_ignore_reloc, /* special_function */
806 "R_RISCV_SUB_ULEB128", /* name */
807 false, /* partial_inplace */
808 0, /* src_mask */
809 0, /* dst_mask */
810 false), /* pcrel_offset */
813 static reloc_howto_type howto_table_internal[] =
815 /* R_RISCV_DELETE. */
816 EMPTY_HOWTO (0),
818 /* High 6 bits of 18-bit absolute address. */
819 HOWTO (R_RISCV_RVC_LUI, /* type */
820 0, /* rightshift */
821 2, /* size */
822 16, /* bitsize */
823 false, /* pc_relative */
824 0, /* bitpos */
825 complain_overflow_dont, /* complain_on_overflow */
826 bfd_elf_generic_reloc, /* special_function */
827 "R_RISCV_RVC_LUI", /* name */
828 false, /* partial_inplace */
829 0, /* src_mask */
830 ENCODE_CITYPE_IMM (-1U), /* dst_mask */
831 false), /* pcrel_offset */
833 /* GP-relative load. */
834 HOWTO (R_RISCV_GPREL_I, /* 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_GPREL_I", /* name */
843 false, /* partial_inplace */
844 0, /* src_mask */
845 ENCODE_ITYPE_IMM (-1U), /* dst_mask */
846 false), /* pcrel_offset */
848 /* GP-relative store. */
849 HOWTO (R_RISCV_GPREL_S, /* type */
850 0, /* rightshift */
851 4, /* size */
852 32, /* bitsize */
853 false, /* pc_relative */
854 0, /* bitpos */
855 complain_overflow_dont, /* complain_on_overflow */
856 bfd_elf_generic_reloc, /* special_function */
857 "R_RISCV_GPREL_S", /* name */
858 false, /* partial_inplace */
859 0, /* src_mask */
860 ENCODE_STYPE_IMM (-1U), /* dst_mask */
861 false), /* pcrel_offset */
863 /* TP-relative TLS LE load. */
864 HOWTO (R_RISCV_TPREL_I, /* type */
865 0, /* rightshift */
866 4, /* size */
867 32, /* bitsize */
868 false, /* pc_relative */
869 0, /* bitpos */
870 complain_overflow_signed, /* complain_on_overflow */
871 bfd_elf_generic_reloc, /* special_function */
872 "R_RISCV_TPREL_I", /* name */
873 false, /* partial_inplace */
874 0, /* src_mask */
875 ENCODE_ITYPE_IMM (-1U), /* dst_mask */
876 false), /* pcrel_offset */
878 /* TP-relative TLS LE store. */
879 HOWTO (R_RISCV_TPREL_S, /* type */
880 0, /* rightshift */
881 4, /* size */
882 32, /* bitsize */
883 false, /* pc_relative */
884 0, /* bitpos */
885 complain_overflow_signed, /* complain_on_overflow */
886 bfd_elf_generic_reloc, /* special_function */
887 "R_RISCV_TPREL_S", /* name */
888 false, /* partial_inplace */
889 0, /* src_mask */
890 ENCODE_STYPE_IMM (-1U), /* dst_mask */
891 false), /* pcrel_offset */
894 /* A mapping from BFD reloc types to RISC-V ELF reloc types. */
895 struct elf_reloc_map
897 bfd_reloc_code_real_type bfd_val;
898 enum elf_riscv_reloc_type elf_val;
901 static const struct elf_reloc_map riscv_reloc_map[] =
903 { BFD_RELOC_NONE, R_RISCV_NONE },
904 { BFD_RELOC_32, R_RISCV_32 },
905 { BFD_RELOC_64, R_RISCV_64 },
906 { BFD_RELOC_RISCV_ADD8, R_RISCV_ADD8 },
907 { BFD_RELOC_RISCV_ADD16, R_RISCV_ADD16 },
908 { BFD_RELOC_RISCV_ADD32, R_RISCV_ADD32 },
909 { BFD_RELOC_RISCV_ADD64, R_RISCV_ADD64 },
910 { BFD_RELOC_RISCV_SUB8, R_RISCV_SUB8 },
911 { BFD_RELOC_RISCV_SUB16, R_RISCV_SUB16 },
912 { BFD_RELOC_RISCV_SUB32, R_RISCV_SUB32 },
913 { BFD_RELOC_RISCV_SUB64, R_RISCV_SUB64 },
914 { BFD_RELOC_CTOR, R_RISCV_64 },
915 { BFD_RELOC_12_PCREL, R_RISCV_BRANCH },
916 { BFD_RELOC_RISCV_HI20, R_RISCV_HI20 },
917 { BFD_RELOC_RISCV_LO12_I, R_RISCV_LO12_I },
918 { BFD_RELOC_RISCV_LO12_S, R_RISCV_LO12_S },
919 { BFD_RELOC_RISCV_PCREL_LO12_I, R_RISCV_PCREL_LO12_I },
920 { BFD_RELOC_RISCV_PCREL_LO12_S, R_RISCV_PCREL_LO12_S },
921 { BFD_RELOC_RISCV_CALL, R_RISCV_CALL },
922 { BFD_RELOC_RISCV_CALL_PLT, R_RISCV_CALL_PLT },
923 { BFD_RELOC_RISCV_PCREL_HI20, R_RISCV_PCREL_HI20 },
924 { BFD_RELOC_RISCV_JMP, R_RISCV_JAL },
925 { BFD_RELOC_RISCV_GOT_HI20, R_RISCV_GOT_HI20 },
926 { BFD_RELOC_RISCV_TLS_DTPMOD32, R_RISCV_TLS_DTPMOD32 },
927 { BFD_RELOC_RISCV_TLS_DTPREL32, R_RISCV_TLS_DTPREL32 },
928 { BFD_RELOC_RISCV_TLS_DTPMOD64, R_RISCV_TLS_DTPMOD64 },
929 { BFD_RELOC_RISCV_TLS_DTPREL64, R_RISCV_TLS_DTPREL64 },
930 { BFD_RELOC_RISCV_TLS_TPREL32, R_RISCV_TLS_TPREL32 },
931 { BFD_RELOC_RISCV_TLS_TPREL64, R_RISCV_TLS_TPREL64 },
932 { BFD_RELOC_RISCV_TPREL_HI20, R_RISCV_TPREL_HI20 },
933 { BFD_RELOC_RISCV_TPREL_ADD, R_RISCV_TPREL_ADD },
934 { BFD_RELOC_RISCV_TPREL_LO12_S, R_RISCV_TPREL_LO12_S },
935 { BFD_RELOC_RISCV_TPREL_LO12_I, R_RISCV_TPREL_LO12_I },
936 { BFD_RELOC_RISCV_TLS_GOT_HI20, R_RISCV_TLS_GOT_HI20 },
937 { BFD_RELOC_RISCV_TLS_GD_HI20, R_RISCV_TLS_GD_HI20 },
938 { BFD_RELOC_RISCV_ALIGN, R_RISCV_ALIGN },
939 { BFD_RELOC_RISCV_RVC_BRANCH, R_RISCV_RVC_BRANCH },
940 { BFD_RELOC_RISCV_RVC_JUMP, R_RISCV_RVC_JUMP },
941 { BFD_RELOC_RISCV_RELAX, R_RISCV_RELAX },
942 { BFD_RELOC_RISCV_SUB6, R_RISCV_SUB6 },
943 { BFD_RELOC_RISCV_SET6, R_RISCV_SET6 },
944 { BFD_RELOC_RISCV_SET8, R_RISCV_SET8 },
945 { BFD_RELOC_RISCV_SET16, R_RISCV_SET16 },
946 { BFD_RELOC_RISCV_SET32, R_RISCV_SET32 },
947 { BFD_RELOC_RISCV_32_PCREL, R_RISCV_32_PCREL },
948 { BFD_RELOC_RISCV_SET_ULEB128, R_RISCV_SET_ULEB128 },
949 { BFD_RELOC_RISCV_SUB_ULEB128, R_RISCV_SUB_ULEB128 },
952 /* Given a BFD reloc type, return a howto structure. */
954 reloc_howto_type *
955 riscv_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED,
956 bfd_reloc_code_real_type code)
958 unsigned int i;
960 for (i = 0; i < ARRAY_SIZE (riscv_reloc_map); i++)
961 if (riscv_reloc_map[i].bfd_val == code)
962 return &howto_table[(int) riscv_reloc_map[i].elf_val];
964 bfd_set_error (bfd_error_bad_value);
965 return NULL;
968 reloc_howto_type *
969 riscv_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED, const char *r_name)
971 unsigned int i;
973 for (i = 0; i < ARRAY_SIZE (howto_table); i++)
974 if (howto_table[i].name && strcasecmp (howto_table[i].name, r_name) == 0)
975 return &howto_table[i];
977 return NULL;
980 reloc_howto_type *
981 riscv_elf_rtype_to_howto (bfd *abfd, unsigned int r_type)
983 if (r_type < ARRAY_SIZE (howto_table))
984 return &howto_table[r_type];
985 else if (r_type < R_RISCV_max + ARRAY_SIZE (howto_table_internal))
986 return &howto_table_internal[r_type - R_RISCV_max];
987 else
989 (*_bfd_error_handler) (_("%pB: unsupported relocation type %#x"),
990 abfd, r_type);
991 bfd_set_error (bfd_error_bad_value);
992 return NULL;
996 /* Special_function of RISCV_ADD and RISCV_SUB relocations. */
998 static bfd_reloc_status_type
999 riscv_elf_add_sub_reloc (bfd *abfd,
1000 arelent *reloc_entry,
1001 asymbol *symbol,
1002 void *data,
1003 asection *input_section,
1004 bfd *output_bfd,
1005 char **error_message ATTRIBUTE_UNUSED)
1007 reloc_howto_type *howto = reloc_entry->howto;
1008 bfd_vma relocation;
1010 if (output_bfd != NULL
1011 && (symbol->flags & BSF_SECTION_SYM) == 0
1012 && (!reloc_entry->howto->partial_inplace || reloc_entry->addend == 0))
1014 reloc_entry->address += input_section->output_offset;
1015 return bfd_reloc_ok;
1018 if (output_bfd != NULL)
1019 return bfd_reloc_continue;
1021 relocation = symbol->value + symbol->section->output_section->vma
1022 + symbol->section->output_offset + reloc_entry->addend;
1024 bfd_size_type octets = reloc_entry->address
1025 * bfd_octets_per_byte (abfd, input_section);
1026 if (!bfd_reloc_offset_in_range (reloc_entry->howto, abfd,
1027 input_section, octets))
1028 return bfd_reloc_outofrange;
1030 bfd_vma old_value = bfd_get (howto->bitsize, abfd,
1031 data + reloc_entry->address);
1033 switch (howto->type)
1035 case R_RISCV_ADD8:
1036 case R_RISCV_ADD16:
1037 case R_RISCV_ADD32:
1038 case R_RISCV_ADD64:
1039 relocation = old_value + relocation;
1040 break;
1041 case R_RISCV_SUB6:
1042 relocation = (old_value & ~howto->dst_mask)
1043 | (((old_value & howto->dst_mask) - relocation)
1044 & howto->dst_mask);
1045 break;
1046 case R_RISCV_SUB8:
1047 case R_RISCV_SUB16:
1048 case R_RISCV_SUB32:
1049 case R_RISCV_SUB64:
1050 relocation = old_value - relocation;
1051 break;
1053 bfd_put (howto->bitsize, abfd, relocation, data + reloc_entry->address);
1055 return bfd_reloc_ok;
1058 /* Special handler for relocations which don't have to be relocated.
1059 This function just simply return bfd_reloc_ok. */
1061 static bfd_reloc_status_type
1062 riscv_elf_ignore_reloc (bfd *abfd ATTRIBUTE_UNUSED,
1063 arelent *reloc_entry,
1064 asymbol *symbol ATTRIBUTE_UNUSED,
1065 void *data ATTRIBUTE_UNUSED,
1066 asection *input_section,
1067 bfd *output_bfd,
1068 char **error_message ATTRIBUTE_UNUSED)
1070 if (output_bfd != NULL)
1071 reloc_entry->address += input_section->output_offset;
1072 return bfd_reloc_ok;
1075 /* Always add the IMPLICIT for the SUBSET. */
1077 static bool
1078 check_implicit_always (const char *implicit ATTRIBUTE_UNUSED,
1079 riscv_subset_t *subset ATTRIBUTE_UNUSED)
1081 return true;
1084 /* Add the IMPLICIT only when the version of SUBSET less than 2.1. */
1086 static bool
1087 check_implicit_for_i (const char *implicit ATTRIBUTE_UNUSED,
1088 riscv_subset_t *subset)
1090 return (subset->major_version < 2
1091 || (subset->major_version == 2
1092 && subset->minor_version < 1));
1095 /* Record all implicit information for the subsets. */
1096 struct riscv_implicit_subset
1098 const char *subset_name;
1099 const char *implicit_name;
1100 /* A function to determine if we need to add the implicit subset. */
1101 bool (*check_func) (const char *, riscv_subset_t *);
1103 static struct riscv_implicit_subset riscv_implicit_subsets[] =
1105 {"e", "i", check_implicit_always},
1106 {"i", "zicsr", check_implicit_for_i},
1107 {"i", "zifencei", check_implicit_for_i},
1108 {"g", "i", check_implicit_always},
1109 {"g", "m", check_implicit_always},
1110 {"g", "a", check_implicit_always},
1111 {"g", "f", check_implicit_always},
1112 {"g", "d", check_implicit_always},
1113 {"g", "zicsr", check_implicit_always},
1114 {"g", "zifencei", check_implicit_always},
1115 {"m", "zmmul", check_implicit_always},
1116 {"h", "zicsr", check_implicit_always},
1117 {"q", "d", check_implicit_always},
1118 {"v", "d", check_implicit_always},
1119 {"v", "zve64d", check_implicit_always},
1120 {"v", "zvl128b", check_implicit_always},
1121 {"zvfh", "zvfhmin", check_implicit_always},
1122 {"zvfh", "zfhmin", check_implicit_always},
1123 {"zvfhmin", "zve32f", check_implicit_always},
1124 {"zve64d", "d", check_implicit_always},
1125 {"zve64d", "zve64f", check_implicit_always},
1126 {"zve64f", "zve32f", check_implicit_always},
1127 {"zve64f", "zve64x", check_implicit_always},
1128 {"zve64f", "zvl64b", check_implicit_always},
1129 {"zve32f", "f", check_implicit_always},
1130 {"zve32f", "zvl32b", check_implicit_always},
1131 {"zve32f", "zve32x", check_implicit_always},
1132 {"zve64x", "zve32x", check_implicit_always},
1133 {"zve64x", "zvl64b", check_implicit_always},
1134 {"zve32x", "zvl32b", check_implicit_always},
1135 {"zve32x", "zicsr", check_implicit_always},
1136 {"zvl65536b", "zvl32768b", check_implicit_always},
1137 {"zvl32768b", "zvl16384b", check_implicit_always},
1138 {"zvl16384b", "zvl8192b", check_implicit_always},
1139 {"zvl8192b", "zvl4096b", check_implicit_always},
1140 {"zvl4096b", "zvl2048b", check_implicit_always},
1141 {"zvl2048b", "zvl1024b", check_implicit_always},
1142 {"zvl1024b", "zvl512b", check_implicit_always},
1143 {"zvl512b", "zvl256b", check_implicit_always},
1144 {"zvl256b", "zvl128b", check_implicit_always},
1145 {"zvl128b", "zvl64b", check_implicit_always},
1146 {"zvl64b", "zvl32b", check_implicit_always},
1147 {"zcd", "d", check_implicit_always},
1148 {"zcf", "f", check_implicit_always},
1149 {"zfa", "f", check_implicit_always},
1150 {"d", "f", check_implicit_always},
1151 {"zfh", "zfhmin", check_implicit_always},
1152 {"zfhmin", "f", check_implicit_always},
1153 {"f", "zicsr", check_implicit_always},
1154 {"zqinx", "zdinx", check_implicit_always},
1155 {"zdinx", "zfinx", check_implicit_always},
1156 {"zhinx", "zhinxmin", check_implicit_always},
1157 {"zhinxmin", "zfinx", check_implicit_always},
1158 {"zfinx", "zicsr", check_implicit_always},
1159 {"zk", "zkn", check_implicit_always},
1160 {"zk", "zkr", check_implicit_always},
1161 {"zk", "zkt", check_implicit_always},
1162 {"zkn", "zbkb", check_implicit_always},
1163 {"zkn", "zbkc", check_implicit_always},
1164 {"zkn", "zbkx", check_implicit_always},
1165 {"zkn", "zkne", check_implicit_always},
1166 {"zkn", "zknd", check_implicit_always},
1167 {"zkn", "zknh", check_implicit_always},
1168 {"zks", "zbkb", check_implicit_always},
1169 {"zks", "zbkc", check_implicit_always},
1170 {"zks", "zbkx", check_implicit_always},
1171 {"zks", "zksed", check_implicit_always},
1172 {"zks", "zksh", check_implicit_always},
1173 {"zvbb", "zvkb", check_implicit_always},
1174 {"zvkn", "zvkned", check_implicit_always},
1175 {"zvkn", "zvknha", check_implicit_always},
1176 {"zvkn", "zvknhb", check_implicit_always},
1177 {"zvkn", "zvkb", check_implicit_always},
1178 {"zvkn", "zvkt", check_implicit_always},
1179 {"zvkng", "zvkn", check_implicit_always},
1180 {"zvkng", "zvkg", check_implicit_always},
1181 {"zvknc", "zvkn", check_implicit_always},
1182 {"zvknc", "zvbc", check_implicit_always},
1183 {"zvks", "zvksed", check_implicit_always},
1184 {"zvks", "zvksh", check_implicit_always},
1185 {"zvks", "zvkb", check_implicit_always},
1186 {"zvks", "zvkt", check_implicit_always},
1187 {"zvksg", "zvks", check_implicit_always},
1188 {"zvksg", "zvkg", check_implicit_always},
1189 {"zvksc", "zvks", check_implicit_always},
1190 {"zvksc", "zvbc", check_implicit_always},
1191 {"zcf", "zca", check_implicit_always},
1192 {"zcd", "zca", check_implicit_always},
1193 {"zcb", "zca", check_implicit_always},
1194 {"smaia", "ssaia", check_implicit_always},
1195 {"smcntrpmf", "zicsr", check_implicit_always},
1196 {"smstateen", "ssstateen", check_implicit_always},
1197 {"smepmp", "zicsr", check_implicit_always},
1198 {"ssaia", "zicsr", check_implicit_always},
1199 {"sscofpmf", "zicsr", check_implicit_always},
1200 {"ssstateen", "zicsr", check_implicit_always},
1201 {"sstc", "zicsr", check_implicit_always},
1202 {"svadu", "zicsr", check_implicit_always},
1204 {"xsfvcp", "zve32x", check_implicit_always},
1205 {NULL, NULL, NULL}
1208 /* For default_enable field, decide if the extension should
1209 be enbaled by default. */
1211 #define EXT_DEFAULT 0x1
1213 /* List all extensions that binutils should know about. */
1215 struct riscv_supported_ext
1217 const char *name;
1218 enum riscv_spec_class isa_spec_class;
1219 int major_version;
1220 int minor_version;
1221 unsigned long default_enable;
1224 /* The standard extensions must be added in canonical order. */
1226 static struct riscv_supported_ext riscv_supported_std_ext[] =
1228 {"e", ISA_SPEC_CLASS_20191213, 1, 9, 0 },
1229 {"e", ISA_SPEC_CLASS_20190608, 1, 9, 0 },
1230 {"e", ISA_SPEC_CLASS_2P2, 1, 9, 0 },
1231 {"i", ISA_SPEC_CLASS_20191213, 2, 1, 0 },
1232 {"i", ISA_SPEC_CLASS_20190608, 2, 1, 0 },
1233 {"i", ISA_SPEC_CLASS_2P2, 2, 0, 0 },
1234 /* The g is a special case which we don't want to output it,
1235 but still need it when adding implicit extensions. */
1236 {"g", ISA_SPEC_CLASS_NONE, RISCV_UNKNOWN_VERSION, RISCV_UNKNOWN_VERSION, EXT_DEFAULT },
1237 {"m", ISA_SPEC_CLASS_20191213, 2, 0, 0 },
1238 {"m", ISA_SPEC_CLASS_20190608, 2, 0, 0 },
1239 {"m", ISA_SPEC_CLASS_2P2, 2, 0, 0 },
1240 {"a", ISA_SPEC_CLASS_20191213, 2, 1, 0 },
1241 {"a", ISA_SPEC_CLASS_20190608, 2, 0, 0 },
1242 {"a", ISA_SPEC_CLASS_2P2, 2, 0, 0 },
1243 {"f", ISA_SPEC_CLASS_20191213, 2, 2, 0 },
1244 {"f", ISA_SPEC_CLASS_20190608, 2, 2, 0 },
1245 {"f", ISA_SPEC_CLASS_2P2, 2, 0, 0 },
1246 {"d", ISA_SPEC_CLASS_20191213, 2, 2, 0 },
1247 {"d", ISA_SPEC_CLASS_20190608, 2, 2, 0 },
1248 {"d", ISA_SPEC_CLASS_2P2, 2, 0, 0 },
1249 {"q", ISA_SPEC_CLASS_20191213, 2, 2, 0 },
1250 {"q", ISA_SPEC_CLASS_20190608, 2, 2, 0 },
1251 {"q", ISA_SPEC_CLASS_2P2, 2, 0, 0 },
1252 {"c", ISA_SPEC_CLASS_20191213, 2, 0, 0 },
1253 {"c", ISA_SPEC_CLASS_20190608, 2, 0, 0 },
1254 {"c", ISA_SPEC_CLASS_2P2, 2, 0, 0 },
1255 {"v", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1256 {"h", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1257 {NULL, 0, 0, 0, 0}
1260 static struct riscv_supported_ext riscv_supported_std_z_ext[] =
1262 {"zicbom", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1263 {"zicbop", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1264 {"zicboz", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1265 {"zicond", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1266 {"zicsr", ISA_SPEC_CLASS_20191213, 2, 0, 0 },
1267 {"zicsr", ISA_SPEC_CLASS_20190608, 2, 0, 0 },
1268 {"zifencei", ISA_SPEC_CLASS_20191213, 2, 0, 0 },
1269 {"zifencei", ISA_SPEC_CLASS_20190608, 2, 0, 0 },
1270 {"zihintntl", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1271 {"zihintpause", ISA_SPEC_CLASS_DRAFT, 2, 0, 0 },
1272 {"zmmul", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1273 {"zawrs", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1274 {"zfa", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1275 {"zfh", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1276 {"zfhmin", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1277 {"zfinx", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1278 {"zdinx", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1279 {"zqinx", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1280 {"zhinx", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1281 {"zhinxmin", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1282 {"zbb", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1283 {"zba", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1284 {"zbc", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1285 {"zbs", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1286 {"zbkb", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1287 {"zbkc", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1288 {"zbkx", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1289 {"zk", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1290 {"zkn", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1291 {"zknd", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1292 {"zkne", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1293 {"zknh", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1294 {"zkr", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1295 {"zks", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1296 {"zksed", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1297 {"zksh", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1298 {"zkt", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1299 {"zve32x", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1300 {"zve32f", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1301 {"zve64x", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1302 {"zve64f", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1303 {"zve64d", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1304 {"zvbb", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1305 {"zvbc", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1306 {"zvfh", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1307 {"zvfhmin", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1308 {"zvkb", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1309 {"zvkg", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1310 {"zvkn", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1311 {"zvkng", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1312 {"zvknc", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1313 {"zvkned", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1314 {"zvknha", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1315 {"zvknhb", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1316 {"zvksed", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1317 {"zvksh", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1318 {"zvks", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1319 {"zvksg", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1320 {"zvksc", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1321 {"zvkt", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1322 {"zvl32b", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1323 {"zvl64b", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1324 {"zvl128b", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1325 {"zvl256b", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1326 {"zvl512b", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1327 {"zvl1024b", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1328 {"zvl2048b", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1329 {"zvl4096b", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1330 {"zvl8192b", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1331 {"zvl16384b", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1332 {"zvl32768b", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1333 {"zvl65536b", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1334 {"ztso", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1335 {"zca", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1336 {"zcb", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1337 {"zcf", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1338 {"zcd", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1339 {NULL, 0, 0, 0, 0}
1342 static struct riscv_supported_ext riscv_supported_std_s_ext[] =
1344 {"smaia", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1345 {"smcntrpmf", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1346 {"smepmp", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1347 {"smstateen", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1348 {"ssaia", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1349 {"sscofpmf", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1350 {"ssstateen", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1351 {"sstc", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1352 {"svadu", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1353 {"svinval", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1354 {"svnapot", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1355 {"svpbmt", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1356 {NULL, 0, 0, 0, 0}
1359 static struct riscv_supported_ext riscv_supported_std_zxm_ext[] =
1361 {NULL, 0, 0, 0, 0}
1364 static struct riscv_supported_ext riscv_supported_vendor_x_ext[] =
1366 {"xcvmac", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1367 {"xcvalu", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1368 {"xtheadba", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1369 {"xtheadbb", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1370 {"xtheadbs", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1371 {"xtheadcmo", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1372 {"xtheadcondmov", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1373 {"xtheadfmemidx", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1374 {"xtheadfmv", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1375 {"xtheadint", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1376 {"xtheadmac", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1377 {"xtheadmemidx", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1378 {"xtheadmempair", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1379 {"xtheadsync", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1380 {"xtheadvector", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1381 {"xtheadzvamo", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1382 {"xventanacondops", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1383 {"xsfvcp", ISA_SPEC_CLASS_DRAFT, 1, 0, 0},
1384 {NULL, 0, 0, 0, 0}
1387 const struct riscv_supported_ext *riscv_all_supported_ext[] =
1389 riscv_supported_std_ext,
1390 riscv_supported_std_z_ext,
1391 riscv_supported_std_s_ext,
1392 riscv_supported_std_zxm_ext,
1393 riscv_supported_vendor_x_ext,
1394 NULL
1397 /* ISA extension prefixed name class. Must define them in parsing order. */
1398 enum riscv_prefix_ext_class
1400 RV_ISA_CLASS_Z = 1,
1401 RV_ISA_CLASS_S,
1402 RV_ISA_CLASS_ZXM,
1403 RV_ISA_CLASS_X,
1404 RV_ISA_CLASS_SINGLE
1407 /* Record the strings of the prefixed extensions, and their corresponding
1408 classes. The more letters of the prefix string, the more forward it must
1409 be defined. Otherwise, the riscv_get_prefix_class will map it to the
1410 wrong classes. */
1411 struct riscv_parse_prefix_config
1413 /* Class of the extension. */
1414 enum riscv_prefix_ext_class class;
1416 /* Prefix string for error printing and internal parser usage. */
1417 const char *prefix;
1419 static const struct riscv_parse_prefix_config parse_config[] =
1421 {RV_ISA_CLASS_ZXM, "zxm"},
1422 {RV_ISA_CLASS_Z, "z"},
1423 {RV_ISA_CLASS_S, "s"},
1424 {RV_ISA_CLASS_X, "x"},
1425 {RV_ISA_CLASS_SINGLE, NULL}
1428 /* Get the prefixed name class for the extensions, the class also
1429 means the order of the prefixed extensions. */
1431 static enum riscv_prefix_ext_class
1432 riscv_get_prefix_class (const char *arch)
1434 int i = 0;
1435 while (parse_config[i].class != RV_ISA_CLASS_SINGLE)
1437 if (strncmp (arch, parse_config[i].prefix,
1438 strlen (parse_config[i].prefix)) == 0)
1439 return parse_config[i].class;
1440 i++;
1442 return RV_ISA_CLASS_SINGLE;
1445 /* Check KNOWN_EXTS to see if the EXT is supported. */
1447 static bool
1448 riscv_known_prefixed_ext (const char *ext,
1449 struct riscv_supported_ext *known_exts)
1451 size_t i;
1452 for (i = 0; known_exts[i].name != NULL; ++i)
1453 if (strcmp (ext, known_exts[i].name) == 0)
1454 return true;
1455 return false;
1458 /* Check whether the prefixed extension is recognized or not. Return
1459 true if recognized, otehrwise return false. */
1461 static bool
1462 riscv_recognized_prefixed_ext (const char *ext)
1464 enum riscv_prefix_ext_class class = riscv_get_prefix_class (ext);
1465 switch (class)
1467 case RV_ISA_CLASS_Z:
1468 return riscv_known_prefixed_ext (ext, riscv_supported_std_z_ext);
1469 case RV_ISA_CLASS_ZXM:
1470 return riscv_known_prefixed_ext (ext, riscv_supported_std_zxm_ext);
1471 case RV_ISA_CLASS_S:
1472 return riscv_known_prefixed_ext (ext, riscv_supported_std_s_ext);
1473 case RV_ISA_CLASS_X:
1474 /* Only the single x is unrecognized. */
1475 if (strcmp (ext, "x") != 0)
1476 return true;
1477 default:
1478 break;
1480 return false;
1483 /* Canonical order for single letter extensions. */
1484 static const char riscv_ext_canonical_order[] = "eigmafdqlcbkjtpvnh";
1486 /* Array is used to compare the orders of standard extensions quickly. */
1487 static int riscv_ext_order[26] = {0};
1489 /* Init the riscv_ext_order array. */
1491 static void
1492 riscv_init_ext_order (void)
1494 static bool inited = false;
1495 if (inited)
1496 return;
1498 /* The orders of all standard extensions are positive. */
1499 int order = 1;
1501 for (const char *ext = &riscv_ext_canonical_order[0]; *ext; ++ext)
1502 riscv_ext_order[(*ext - 'a')] = order++;
1504 /* Some of the prefixed keyword are not single letter, so we set
1505 their prefixed orders in the riscv_compare_subsets directly,
1506 not through the riscv_ext_order. */
1508 inited = true;
1511 /* Similar to the strcmp. It returns an integer less than, equal to,
1512 or greater than zero if `subset2` is found, respectively, to be less
1513 than, to match, or be greater than `subset1`.
1515 The order values,
1516 Zero: Preserved keywords.
1517 Positive number: Standard extensions.
1518 Negative number: Prefixed keywords. */
1521 riscv_compare_subsets (const char *subset1, const char *subset2)
1523 int order1 = riscv_ext_order[(*subset1 - 'a')];
1524 int order2 = riscv_ext_order[(*subset2 - 'a')];
1526 /* Compare the standard extension first. */
1527 if (order1 > 0 && order2 > 0)
1528 return order1 - order2;
1530 /* Set the prefixed orders to negative numbers. */
1531 enum riscv_prefix_ext_class class1 = riscv_get_prefix_class (subset1);
1532 enum riscv_prefix_ext_class class2 = riscv_get_prefix_class (subset2);
1534 if (class1 != RV_ISA_CLASS_SINGLE)
1535 order1 = - (int) class1;
1536 if (class2 != RV_ISA_CLASS_SINGLE)
1537 order2 = - (int) class2;
1539 if (order1 == order2)
1541 /* Compare the standard addition z extensions. */
1542 if (class1 == RV_ISA_CLASS_Z)
1544 order1 = riscv_ext_order[(*++subset1 - 'a')];
1545 order2 = riscv_ext_order[(*++subset2 - 'a')];
1546 if (order1 != order2)
1547 return order1 - order2;
1549 return strcasecmp (++subset1, ++subset2);
1552 return order2 - order1;
1555 /* Find subset in the list. Return TRUE and set `current` to the subset
1556 if it is found. Otherwise, return FALSE and set `current` to the place
1557 where we should insert the subset. However, return FALSE with the NULL
1558 `current` means we should insert the subset at the head of subset list,
1559 if needed. */
1561 bool
1562 riscv_lookup_subset (const riscv_subset_list_t *subset_list,
1563 const char *subset,
1564 riscv_subset_t **current)
1566 riscv_subset_t *s, *pre_s = NULL;
1568 /* If the subset is added in order, then just add it at the tail. */
1569 if (subset_list->tail != NULL
1570 && riscv_compare_subsets (subset_list->tail->name, subset) < 0)
1572 *current = subset_list->tail;
1573 return false;
1576 for (s = subset_list->head;
1577 s != NULL;
1578 pre_s = s, s = s->next)
1580 int cmp = riscv_compare_subsets (s->name, subset);
1581 if (cmp == 0)
1583 *current = s;
1584 return true;
1586 else if (cmp > 0)
1587 break;
1589 *current = pre_s;
1591 return false;
1594 /* Add the extension to the subset list. Search the
1595 list first, and then find the right place to add. */
1597 void
1598 riscv_add_subset (riscv_subset_list_t *subset_list,
1599 const char *subset,
1600 int major,
1601 int minor)
1603 riscv_subset_t *current, *new;
1605 if (riscv_lookup_subset (subset_list, subset, &current))
1606 return;
1608 new = xmalloc (sizeof *new);
1609 new->name = xstrdup (subset);
1610 new->major_version = major;
1611 new->minor_version = minor;
1612 new->next = NULL;
1614 if (current != NULL)
1616 new->next = current->next;
1617 current->next = new;
1619 else
1621 new->next = subset_list->head;
1622 subset_list->head = new;
1625 if (new->next == NULL)
1626 subset_list->tail = new;
1629 /* Get the default versions from the riscv_supported_*ext tables. */
1631 static void
1632 riscv_get_default_ext_version (enum riscv_spec_class *default_isa_spec,
1633 const char *name,
1634 int *major_version,
1635 int *minor_version)
1637 if (name == NULL
1638 || default_isa_spec == NULL
1639 || *default_isa_spec == ISA_SPEC_CLASS_NONE)
1640 return;
1642 struct riscv_supported_ext *table = NULL;
1643 enum riscv_prefix_ext_class class = riscv_get_prefix_class (name);
1644 switch (class)
1646 case RV_ISA_CLASS_ZXM: table = riscv_supported_std_zxm_ext; break;
1647 case RV_ISA_CLASS_Z: table = riscv_supported_std_z_ext; break;
1648 case RV_ISA_CLASS_S: table = riscv_supported_std_s_ext; break;
1649 case RV_ISA_CLASS_X: table = riscv_supported_vendor_x_ext; break;
1650 default:
1651 table = riscv_supported_std_ext;
1654 int i = 0;
1655 while (table != NULL && table[i].name != NULL)
1657 if (strcmp (table[i].name, name) == 0
1658 && (table[i].isa_spec_class == ISA_SPEC_CLASS_DRAFT
1659 || table[i].isa_spec_class == *default_isa_spec))
1661 *major_version = table[i].major_version;
1662 *minor_version = table[i].minor_version;
1663 return;
1665 i++;
1669 /* Find the default versions for the extension before adding them to
1670 the subset list, if their versions are RISCV_UNKNOWN_VERSION.
1671 Afterwards, report errors if we can not find their default versions. */
1673 static void
1674 riscv_parse_add_subset (riscv_parse_subset_t *rps,
1675 const char *subset,
1676 int major,
1677 int minor,
1678 bool implicit)
1680 int major_version = major;
1681 int minor_version = minor;
1683 if (major_version == RISCV_UNKNOWN_VERSION
1684 || minor_version == RISCV_UNKNOWN_VERSION)
1685 riscv_get_default_ext_version (rps->isa_spec, subset,
1686 &major_version, &minor_version);
1688 /* We don't care the versions of the implicit extensions. */
1689 if (!implicit
1690 && (major_version == RISCV_UNKNOWN_VERSION
1691 || minor_version == RISCV_UNKNOWN_VERSION))
1693 if (subset[0] == 'x')
1694 rps->error_handler
1695 (_("x ISA extension `%s' must be set with the versions"),
1696 subset);
1697 /* Allow old ISA spec can recognize zicsr and zifencei. */
1698 else if (strcmp (subset, "zicsr") != 0
1699 && strcmp (subset, "zifencei") != 0)
1700 rps->error_handler
1701 (_("cannot find default versions of the ISA extension `%s'"),
1702 subset);
1703 return;
1706 riscv_add_subset (rps->subset_list, subset,
1707 major_version, minor_version);
1710 /* Release subset list. */
1712 void
1713 riscv_release_subset_list (riscv_subset_list_t *subset_list)
1715 while (subset_list->head != NULL)
1717 riscv_subset_t *next = subset_list->head->next;
1718 free ((void *)subset_list->head->name);
1719 free (subset_list->head);
1720 subset_list->head = next;
1723 subset_list->tail = NULL;
1725 if (subset_list->arch_str != NULL)
1727 free ((void*) subset_list->arch_str);
1728 subset_list->arch_str = NULL;
1732 /* Parsing extension version.
1734 Return Value:
1735 Points to the end of version
1737 Arguments:
1738 `p`: Curent parsing position.
1739 `major_version`: Parsed major version.
1740 `minor_version`: Parsed minor version. */
1742 static const char *
1743 riscv_parsing_subset_version (const char *p,
1744 int *major_version,
1745 int *minor_version)
1747 bool major_p = true;
1748 int version = 0;
1749 char np;
1751 *major_version = 0;
1752 *minor_version = 0;
1753 for (; *p; ++p)
1755 if (*p == 'p')
1757 np = *(p + 1);
1759 /* Might be beginning of `p` extension. */
1760 if (!ISDIGIT (np))
1761 break;
1763 *major_version = version;
1764 major_p = false;
1765 version = 0;
1767 else if (ISDIGIT (*p))
1768 version = (version * 10) + (*p - '0');
1769 else
1770 break;
1773 if (major_p)
1774 *major_version = version;
1775 else
1776 *minor_version = version;
1778 /* We can not find any version in string. */
1779 if (*major_version == 0 && *minor_version == 0)
1781 *major_version = RISCV_UNKNOWN_VERSION;
1782 *minor_version = RISCV_UNKNOWN_VERSION;
1785 return p;
1788 /* Parsing function for both standard and prefixed extensions.
1790 Return Value:
1791 Points to the end of extensions.
1793 Arguments:
1794 `rps`: Hooks and status for parsing extensions.
1795 `arch`: Full ISA string.
1796 `p`: Curent parsing position. */
1798 static const char *
1799 riscv_parse_extensions (riscv_parse_subset_t *rps,
1800 const char *arch,
1801 const char *p)
1803 /* First letter must start with i, e or g. */
1804 if (*p != 'e' && *p != 'i' && *p != 'g')
1806 rps->error_handler
1807 (_("%s: first ISA extension must be `e', `i' or `g'"),
1808 arch);
1809 return NULL;
1812 while (*p != '\0')
1814 if (*p == '_')
1816 p++;
1817 continue;
1820 char *subset = xstrdup (p);
1821 char *q = subset; /* Start of version. */
1822 const char *end_of_version;
1823 bool implicit = false;
1825 enum riscv_prefix_ext_class class = riscv_get_prefix_class (p);
1826 if (class == RV_ISA_CLASS_SINGLE)
1828 if (riscv_ext_order[(*subset - 'a')] == 0)
1830 rps->error_handler
1831 (_("%s: unknown standard ISA extension or prefix class `%c'"),
1832 arch, *subset);
1833 free (subset);
1834 return NULL;
1836 q++;
1838 else
1840 /* Extract the whole prefixed extension by '_'. */
1841 while (*++q != '\0' && *q != '_')
1843 /* Look forward to the first letter which is not <major>p<minor>. */
1844 bool find_any_version = false;
1845 bool find_minor_version = false;
1846 while (1)
1848 q--;
1849 if (ISDIGIT (*q))
1850 find_any_version = true;
1851 else if (find_any_version
1852 && !find_minor_version
1853 && *q == 'p'
1854 && ISDIGIT (*(q - 1)))
1855 find_minor_version = true;
1856 else
1857 break;
1859 q++;
1861 /* Check if the end of extension is 'p' or not. If yes, then
1862 the second letter from the end cannot be number. */
1863 if (*(q - 1) == 'p' && ISDIGIT (*(q - 2)))
1865 *q = '\0';
1866 rps->error_handler
1867 (_("%s: invalid prefixed ISA extension `%s' ends with <number>p"),
1868 arch, subset);
1869 free (subset);
1870 return NULL;
1874 int major_version = RISCV_UNKNOWN_VERSION;
1875 int minor_version = RISCV_UNKNOWN_VERSION;
1876 end_of_version =
1877 riscv_parsing_subset_version (q, &major_version, &minor_version);
1878 *q = '\0';
1879 if (end_of_version == NULL)
1881 free (subset);
1882 return NULL;
1885 /* Check if the prefixed extension name is well-formed. */
1886 if (class != RV_ISA_CLASS_SINGLE
1887 && rps->check_unknown_prefixed_ext
1888 && !riscv_recognized_prefixed_ext (subset))
1890 rps->error_handler
1891 (_("%s: unknown prefixed ISA extension `%s'"),
1892 arch, subset);
1893 free (subset);
1894 return NULL;
1897 /* Added g as an implicit extension. */
1898 if (class == RV_ISA_CLASS_SINGLE
1899 && strcmp (subset, "g") == 0)
1901 implicit = true;
1902 major_version = RISCV_UNKNOWN_VERSION;
1903 minor_version = RISCV_UNKNOWN_VERSION;
1905 riscv_parse_add_subset (rps, subset,
1906 major_version,
1907 minor_version, implicit);
1908 p += end_of_version - subset;
1909 free (subset);
1911 if (class != RV_ISA_CLASS_SINGLE
1912 && *p != '\0' && *p != '_')
1914 rps->error_handler
1915 (_("%s: prefixed ISA extension must separate with _"),
1916 arch);
1917 return NULL;
1921 return p;
1924 /* Add the implicit extensions. */
1926 static void
1927 riscv_parse_add_implicit_subsets (riscv_parse_subset_t *rps)
1929 struct riscv_implicit_subset *t = riscv_implicit_subsets;
1930 bool finished = false;
1931 while (!finished)
1933 finished = true;
1934 for (; t->subset_name; t++)
1936 riscv_subset_t *subset = NULL;
1937 riscv_subset_t *implicit_subset = NULL;
1938 if (riscv_lookup_subset (rps->subset_list, t->subset_name, &subset)
1939 && !riscv_lookup_subset (rps->subset_list, t->implicit_name,
1940 &implicit_subset)
1941 && t->check_func (t->implicit_name, subset))
1943 riscv_parse_add_subset (rps, t->implicit_name,
1944 RISCV_UNKNOWN_VERSION,
1945 RISCV_UNKNOWN_VERSION, true);
1947 /* Restart the loop and pick up any new implications. */
1948 finished = false;
1949 t = riscv_implicit_subsets;
1950 break;
1956 /* Check extensions conflicts. */
1958 static bool
1959 riscv_parse_check_conflicts (riscv_parse_subset_t *rps)
1961 riscv_subset_t *subset = NULL;
1962 int xlen = *rps->xlen;
1963 bool no_conflict = true;
1965 if (riscv_subset_supports (rps, "e")
1966 && riscv_subset_supports (rps, "h"))
1968 rps->error_handler
1969 (_("rv%de does not support the `h' extension"), xlen);
1970 no_conflict = false;
1972 if (riscv_lookup_subset (rps->subset_list, "q", &subset)
1973 && (subset->major_version < 2 || (subset->major_version == 2
1974 && subset->minor_version < 2))
1975 && xlen < 64)
1977 rps->error_handler (_("rv%d does not support the `q' extension"), xlen);
1978 no_conflict = false;
1980 if (riscv_lookup_subset (rps->subset_list, "zcf", &subset)
1981 && xlen > 32)
1983 rps->error_handler
1984 (_("rv%d does not support the `zcf' extension"), xlen);
1985 no_conflict = false;
1987 if (riscv_lookup_subset (rps->subset_list, "zfinx", &subset)
1988 && riscv_lookup_subset (rps->subset_list, "f", &subset))
1990 rps->error_handler
1991 (_("`zfinx' is conflict with the `f/d/q/zfh/zfhmin' extension"));
1992 no_conflict = false;
1994 if (riscv_lookup_subset (rps->subset_list, "xtheadvector", &subset)
1995 && riscv_lookup_subset (rps->subset_list, "v", &subset))
1997 rps->error_handler
1998 (_("`xtheadvector' is conflict with the `v' extension"));
1999 no_conflict = false;
2002 bool support_zve = false;
2003 bool support_zvl = false;
2004 riscv_subset_t *s = rps->subset_list->head;
2005 for (; s != NULL; s = s->next)
2007 if (!support_zve
2008 && strncmp (s->name, "zve", 3) == 0)
2009 support_zve = true;
2010 if (!support_zvl
2011 && strncmp (s->name, "zvl", 3) == 0)
2012 support_zvl = true;
2013 if (support_zve && support_zvl)
2014 break;
2016 if (support_zvl && !support_zve)
2018 rps->error_handler
2019 (_("zvl*b extensions need to enable either `v' or `zve' extension"));
2020 no_conflict = false;
2023 return no_conflict;
2026 /* Set the default subset list according to the default_enable field
2027 of riscv_supported_*ext tables. */
2029 static void
2030 riscv_set_default_arch (riscv_parse_subset_t *rps)
2032 unsigned long enable = EXT_DEFAULT;
2033 int i, j;
2034 for (i = 0; riscv_all_supported_ext[i] != NULL; i++)
2036 const struct riscv_supported_ext *table = riscv_all_supported_ext[i];
2037 for (j = 0; table[j].name != NULL; j++)
2039 bool implicit = false;
2040 if (strcmp (table[j].name, "g") == 0)
2041 implicit = true;
2042 if (table[j].default_enable & enable)
2043 riscv_parse_add_subset (rps, table[j].name,
2044 RISCV_UNKNOWN_VERSION,
2045 RISCV_UNKNOWN_VERSION, implicit);
2050 /* Function for parsing ISA string.
2052 Return Value:
2053 Return TRUE on success.
2055 Arguments:
2056 `rps`: Hooks and status for parsing extensions.
2057 `arch`: Full ISA string. */
2059 bool
2060 riscv_parse_subset (riscv_parse_subset_t *rps,
2061 const char *arch)
2063 const char *p;
2065 /* Init the riscv_ext_order array to compare the order of extensions
2066 quickly. */
2067 riscv_init_ext_order ();
2069 if (arch == NULL)
2071 riscv_set_default_arch (rps);
2072 riscv_parse_add_implicit_subsets (rps);
2073 return riscv_parse_check_conflicts (rps);
2076 for (p = arch; *p != '\0'; p++)
2078 if (ISUPPER (*p))
2080 rps->error_handler
2081 (_("%s: ISA string cannot contain uppercase letters"),
2082 arch);
2083 return false;
2087 p = arch;
2088 if (startswith (p, "rv32"))
2090 *rps->xlen = 32;
2091 p += 4;
2093 else if (startswith (p, "rv64"))
2095 *rps->xlen = 64;
2096 p += 4;
2098 else
2100 /* ISA string shouldn't be NULL or empty here. For linker,
2101 it might be empty when we failed to merge the ISA string
2102 in the riscv_merge_attributes. For assembler, we might
2103 give an empty string by .attribute arch, "" or -march=.
2104 However, We have already issued the correct error message
2105 in another side, so do not issue this error when the ISA
2106 string is empty. */
2107 if (strlen (arch))
2108 rps->error_handler (
2109 _("%s: ISA string must begin with rv32 or rv64"),
2110 arch);
2111 return false;
2114 /* Parse single standard and prefixed extensions. */
2115 if (riscv_parse_extensions (rps, arch, p) == NULL)
2116 return false;
2118 /* Finally add implicit extensions according to the current
2119 extensions. */
2120 riscv_parse_add_implicit_subsets (rps);
2122 /* Check the conflicts. */
2123 return riscv_parse_check_conflicts (rps);
2126 /* Return the number of digits for the input. */
2128 size_t
2129 riscv_estimate_digit (unsigned num)
2131 size_t digit = 0;
2132 if (num == 0)
2133 return 1;
2135 for (digit = 0; num ; num /= 10)
2136 digit++;
2138 return digit;
2141 /* Auxiliary function to estimate string length of subset list. */
2143 static size_t
2144 riscv_estimate_arch_strlen1 (const riscv_subset_t *subset)
2146 if (subset == NULL)
2147 return 6; /* For rv32/rv64/rv128 and string terminator. */
2149 return riscv_estimate_arch_strlen1 (subset->next)
2150 + strlen (subset->name)
2151 + riscv_estimate_digit (subset->major_version)
2152 + 1 /* For version seperator 'p'. */
2153 + riscv_estimate_digit (subset->minor_version)
2154 + 1 /* For underscore. */;
2157 /* Estimate the string length of this subset list. */
2159 static size_t
2160 riscv_estimate_arch_strlen (const riscv_subset_list_t *subset_list)
2162 return riscv_estimate_arch_strlen1 (subset_list->head);
2165 /* Auxiliary function to convert subset info to string. */
2167 static void
2168 riscv_arch_str1 (riscv_subset_t *subset,
2169 char *attr_str, char *buf, size_t bufsz)
2171 const char *underline = "_";
2172 riscv_subset_t *subset_t = subset;
2174 if (subset_t == NULL)
2175 return;
2177 /* No underline between rvXX and i/e. */
2178 if ((strcasecmp (subset_t->name, "i") == 0)
2179 || (strcasecmp (subset_t->name, "e") == 0))
2180 underline = "";
2182 snprintf (buf, bufsz, "%s%s%dp%d",
2183 underline,
2184 subset_t->name,
2185 subset_t->major_version,
2186 subset_t->minor_version);
2188 strncat (attr_str, buf, bufsz);
2190 /* Skip 'i' extension after 'e', or skip extensions which
2191 versions are unknown. */
2192 while (subset_t->next
2193 && ((strcmp (subset_t->name, "e") == 0
2194 && strcmp (subset_t->next->name, "i") == 0)
2195 || subset_t->next->major_version == RISCV_UNKNOWN_VERSION
2196 || subset_t->next->minor_version == RISCV_UNKNOWN_VERSION))
2197 subset_t = subset_t->next;
2199 riscv_arch_str1 (subset_t->next, attr_str, buf, bufsz);
2202 /* Convert subset information into string with explicit versions. */
2204 char *
2205 riscv_arch_str (unsigned xlen, const riscv_subset_list_t *subset)
2207 size_t arch_str_len = riscv_estimate_arch_strlen (subset);
2208 char *attr_str = xmalloc (arch_str_len);
2209 char *buf = xmalloc (arch_str_len);
2211 snprintf (attr_str, arch_str_len, "rv%u", xlen);
2213 riscv_arch_str1 (subset->head, attr_str, buf, arch_str_len);
2214 free (buf);
2216 return attr_str;
2219 /* Copy the subset in the subset list. */
2221 static struct riscv_subset_t *
2222 riscv_copy_subset (riscv_subset_list_t *subset_list,
2223 riscv_subset_t *subset)
2225 if (subset == NULL)
2226 return NULL;
2228 riscv_subset_t *new = xmalloc (sizeof *new);
2229 new->name = xstrdup (subset->name);
2230 new->major_version = subset->major_version;
2231 new->minor_version = subset->minor_version;
2232 new->next = riscv_copy_subset (subset_list, subset->next);
2234 if (subset->next == NULL)
2235 subset_list->tail = new;
2237 return new;
2240 /* Copy the subset list. */
2242 riscv_subset_list_t *
2243 riscv_copy_subset_list (riscv_subset_list_t *subset_list)
2245 riscv_subset_list_t *new = xmalloc (sizeof *new);
2246 new->head = riscv_copy_subset (new, subset_list->head);
2247 new->arch_str = strdup (subset_list->arch_str);
2248 return new;
2251 /* Remove the SUBSET from the subset list. */
2253 static void
2254 riscv_remove_subset (riscv_subset_list_t *subset_list,
2255 const char *subset)
2257 riscv_subset_t *current = subset_list->head;
2258 riscv_subset_t *pre = NULL;
2259 for (; current != NULL; pre = current, current = current->next)
2261 if (strcmp (current->name, subset) == 0)
2263 if (pre == NULL)
2264 subset_list->head = current->next;
2265 else
2266 pre->next = current->next;
2267 if (current->next == NULL)
2268 subset_list->tail = pre;
2269 free ((void *) current->name);
2270 free (current);
2271 break;
2276 /* Add/Remove an extension to/from the subset list. This is used for
2277 the .option rvc or norvc, and .option arch directives. */
2279 bool
2280 riscv_update_subset (riscv_parse_subset_t *rps,
2281 const char *str)
2283 const char *p = str;
2287 int major_version = RISCV_UNKNOWN_VERSION;
2288 int minor_version = RISCV_UNKNOWN_VERSION;
2290 bool removed = false;
2291 switch (*p)
2293 case '+': removed = false; break;
2294 case '-': removed = true; break;
2295 default:
2296 riscv_release_subset_list (rps->subset_list);
2297 return riscv_parse_subset (rps, p);
2299 ++p;
2301 char *subset = xstrdup (p);
2302 char *q = subset;
2303 const char *end_of_version;
2304 /* Extract the whole prefixed extension by ','. */
2305 while (*q != '\0' && *q != ',')
2306 q++;
2308 /* Look forward to the first letter which is not <major>p<minor>. */
2309 bool find_any_version = false;
2310 bool find_minor_version = false;
2311 size_t len = q - subset;
2312 size_t i;
2313 for (i = len; i > 0; i--)
2315 q--;
2316 if (ISDIGIT (*q))
2317 find_any_version = true;
2318 else if (find_any_version
2319 && !find_minor_version
2320 && *q == 'p'
2321 && ISDIGIT (*(q - 1)))
2322 find_minor_version = true;
2323 else
2324 break;
2326 if (len > 0)
2327 q++;
2329 /* Check if the end of extension is 'p' or not. If yes, then
2330 the second letter from the end cannot be number. */
2331 if (len > 1 && *(q - 1) == 'p' && ISDIGIT (*(q - 2)))
2333 *q = '\0';
2334 rps->error_handler
2335 (_("invalid ISA extension ends with <number>p "
2336 "in .option arch `%s'"), str);
2337 free (subset);
2338 return false;
2341 end_of_version =
2342 riscv_parsing_subset_version (q, &major_version, &minor_version);
2343 *q = '\0';
2344 if (end_of_version == NULL)
2346 free (subset);
2347 return false;
2350 if (strlen (subset) == 0
2351 || (strlen (subset) == 1
2352 && riscv_ext_order[(*subset - 'a')] == 0)
2353 || (strlen (subset) > 1
2354 && rps->check_unknown_prefixed_ext
2355 && !riscv_recognized_prefixed_ext (subset)))
2357 rps->error_handler
2358 (_("unknown ISA extension `%s' in .option arch `%s'"),
2359 subset, str);
2360 free (subset);
2361 return false;
2364 if (strcmp (subset, "i") == 0
2365 || strcmp (subset, "e") == 0
2366 || strcmp (subset, "g") == 0)
2368 rps->error_handler
2369 (_("cannot + or - base extension `%s' in .option "
2370 "arch `%s'"), subset, str);
2371 free (subset);
2372 return false;
2375 if (removed)
2376 riscv_remove_subset (rps->subset_list, subset);
2377 else
2378 riscv_parse_add_subset (rps, subset, major_version, minor_version, true);
2379 p += end_of_version - subset;
2380 free (subset);
2382 while (*p++ == ',');
2384 riscv_parse_add_implicit_subsets (rps);
2385 return riscv_parse_check_conflicts (rps);
2388 /* Check if the FEATURE subset is supported or not in the subset list.
2389 Return true if it is supported; Otherwise, return false. */
2391 bool
2392 riscv_subset_supports (riscv_parse_subset_t *rps,
2393 const char *feature)
2395 struct riscv_subset_t *subset;
2396 return riscv_lookup_subset (rps->subset_list, feature, &subset);
2399 /* Each instuction is belonged to an instruction class INSN_CLASS_*.
2400 Call riscv_subset_supports to make sure if the instuction is valid. */
2402 bool
2403 riscv_multi_subset_supports (riscv_parse_subset_t *rps,
2404 enum riscv_insn_class insn_class)
2406 switch (insn_class)
2408 case INSN_CLASS_I:
2409 return riscv_subset_supports (rps, "i");
2410 case INSN_CLASS_ZICBOM:
2411 return riscv_subset_supports (rps, "zicbom");
2412 case INSN_CLASS_ZICBOP:
2413 return riscv_subset_supports (rps, "zicbop");
2414 case INSN_CLASS_ZICBOZ:
2415 return riscv_subset_supports (rps, "zicboz");
2416 case INSN_CLASS_ZICOND:
2417 return riscv_subset_supports (rps, "zicond");
2418 case INSN_CLASS_ZICSR:
2419 return riscv_subset_supports (rps, "zicsr");
2420 case INSN_CLASS_ZIFENCEI:
2421 return riscv_subset_supports (rps, "zifencei");
2422 case INSN_CLASS_ZIHINTNTL:
2423 return riscv_subset_supports (rps, "zihintntl");
2424 case INSN_CLASS_ZIHINTNTL_AND_C:
2425 return (riscv_subset_supports (rps, "zihintntl")
2426 && (riscv_subset_supports (rps, "c")
2427 || riscv_subset_supports (rps, "zca")));
2428 case INSN_CLASS_ZIHINTPAUSE:
2429 return riscv_subset_supports (rps, "zihintpause");
2430 case INSN_CLASS_M:
2431 return riscv_subset_supports (rps, "m");
2432 case INSN_CLASS_ZMMUL:
2433 return riscv_subset_supports (rps, "zmmul");
2434 case INSN_CLASS_A:
2435 return riscv_subset_supports (rps, "a");
2436 case INSN_CLASS_ZAWRS:
2437 return riscv_subset_supports (rps, "zawrs");
2438 case INSN_CLASS_F:
2439 return riscv_subset_supports (rps, "f");
2440 case INSN_CLASS_D:
2441 return riscv_subset_supports (rps, "d");
2442 case INSN_CLASS_Q:
2443 return riscv_subset_supports (rps, "q");
2444 case INSN_CLASS_C:
2445 return (riscv_subset_supports (rps, "c")
2446 || riscv_subset_supports (rps, "zca"));
2447 case INSN_CLASS_F_AND_C:
2448 return (riscv_subset_supports (rps, "f")
2449 && (riscv_subset_supports (rps, "c")
2450 || riscv_subset_supports (rps, "zcf")));
2451 case INSN_CLASS_D_AND_C:
2452 return (riscv_subset_supports (rps, "d")
2453 && (riscv_subset_supports (rps, "c")
2454 || riscv_subset_supports (rps, "zcd")));
2455 case INSN_CLASS_F_INX:
2456 return (riscv_subset_supports (rps, "f")
2457 || riscv_subset_supports (rps, "zfinx"));
2458 case INSN_CLASS_D_INX:
2459 return (riscv_subset_supports (rps, "d")
2460 || riscv_subset_supports (rps, "zdinx"));
2461 case INSN_CLASS_Q_INX:
2462 return (riscv_subset_supports (rps, "q")
2463 || riscv_subset_supports (rps, "zqinx"));
2464 case INSN_CLASS_ZFH_INX:
2465 return (riscv_subset_supports (rps, "zfh")
2466 || riscv_subset_supports (rps, "zhinx"));
2467 case INSN_CLASS_ZFHMIN:
2468 return riscv_subset_supports (rps, "zfhmin");
2469 case INSN_CLASS_ZFHMIN_INX:
2470 return (riscv_subset_supports (rps, "zfhmin")
2471 || riscv_subset_supports (rps, "zhinxmin"));
2472 case INSN_CLASS_ZFHMIN_AND_D_INX:
2473 return ((riscv_subset_supports (rps, "zfhmin")
2474 && riscv_subset_supports (rps, "d"))
2475 || (riscv_subset_supports (rps, "zhinxmin")
2476 && riscv_subset_supports (rps, "zdinx")));
2477 case INSN_CLASS_ZFHMIN_AND_Q_INX:
2478 return ((riscv_subset_supports (rps, "zfhmin")
2479 && riscv_subset_supports (rps, "q"))
2480 || (riscv_subset_supports (rps, "zhinxmin")
2481 && riscv_subset_supports (rps, "zqinx")));
2482 case INSN_CLASS_ZFA:
2483 return riscv_subset_supports (rps, "zfa");
2484 case INSN_CLASS_D_AND_ZFA:
2485 return riscv_subset_supports (rps, "d")
2486 && riscv_subset_supports (rps, "zfa");
2487 case INSN_CLASS_Q_AND_ZFA:
2488 return riscv_subset_supports (rps, "q")
2489 && riscv_subset_supports (rps, "zfa");
2490 case INSN_CLASS_ZFH_AND_ZFA:
2491 return riscv_subset_supports (rps, "zfh")
2492 && riscv_subset_supports (rps, "zfa");
2493 case INSN_CLASS_ZFH_OR_ZVFH_AND_ZFA:
2494 return (riscv_subset_supports (rps, "zfh")
2495 || riscv_subset_supports (rps, "zvfh"))
2496 && riscv_subset_supports (rps, "zfa");
2497 case INSN_CLASS_ZBA:
2498 return riscv_subset_supports (rps, "zba");
2499 case INSN_CLASS_ZBB:
2500 return riscv_subset_supports (rps, "zbb");
2501 case INSN_CLASS_ZBC:
2502 return riscv_subset_supports (rps, "zbc");
2503 case INSN_CLASS_ZBS:
2504 return riscv_subset_supports (rps, "zbs");
2505 case INSN_CLASS_ZBKB:
2506 return riscv_subset_supports (rps, "zbkb");
2507 case INSN_CLASS_ZBKC:
2508 return riscv_subset_supports (rps, "zbkc");
2509 case INSN_CLASS_ZBKX:
2510 return riscv_subset_supports (rps, "zbkx");
2511 case INSN_CLASS_ZBB_OR_ZBKB:
2512 return (riscv_subset_supports (rps, "zbb")
2513 || riscv_subset_supports (rps, "zbkb"));
2514 case INSN_CLASS_ZBC_OR_ZBKC:
2515 return (riscv_subset_supports (rps, "zbc")
2516 || riscv_subset_supports (rps, "zbkc"));
2517 case INSN_CLASS_ZKND:
2518 return riscv_subset_supports (rps, "zknd");
2519 case INSN_CLASS_ZKNE:
2520 return riscv_subset_supports (rps, "zkne");
2521 case INSN_CLASS_ZKNH:
2522 return riscv_subset_supports (rps, "zknh");
2523 case INSN_CLASS_ZKND_OR_ZKNE:
2524 return (riscv_subset_supports (rps, "zknd")
2525 || riscv_subset_supports (rps, "zkne"));
2526 case INSN_CLASS_ZKSED:
2527 return riscv_subset_supports (rps, "zksed");
2528 case INSN_CLASS_ZKSH:
2529 return riscv_subset_supports (rps, "zksh");
2530 case INSN_CLASS_V:
2531 return (riscv_subset_supports (rps, "v")
2532 || riscv_subset_supports (rps, "zve64x")
2533 || riscv_subset_supports (rps, "zve32x"));
2534 case INSN_CLASS_ZVEF:
2535 return (riscv_subset_supports (rps, "v")
2536 || riscv_subset_supports (rps, "zve64d")
2537 || riscv_subset_supports (rps, "zve64f")
2538 || riscv_subset_supports (rps, "zve32f"));
2539 case INSN_CLASS_ZVBB:
2540 return riscv_subset_supports (rps, "zvbb");
2541 case INSN_CLASS_ZVBC:
2542 return riscv_subset_supports (rps, "zvbc");
2543 case INSN_CLASS_ZVKB:
2544 return riscv_subset_supports (rps, "zvkb");
2545 case INSN_CLASS_ZVKG:
2546 return riscv_subset_supports (rps, "zvkg");
2547 case INSN_CLASS_ZVKNED:
2548 return riscv_subset_supports (rps, "zvkned");
2549 case INSN_CLASS_ZVKNHA_OR_ZVKNHB:
2550 return (riscv_subset_supports (rps, "zvknha")
2551 || riscv_subset_supports (rps, "zvknhb"));
2552 case INSN_CLASS_ZVKSED:
2553 return riscv_subset_supports (rps, "zvksed");
2554 case INSN_CLASS_ZVKSH:
2555 return riscv_subset_supports (rps, "zvksh");
2556 case INSN_CLASS_ZCB:
2557 return riscv_subset_supports (rps, "zcb");
2558 case INSN_CLASS_ZCB_AND_ZBB:
2559 return (riscv_subset_supports (rps, "zcb")
2560 && riscv_subset_supports (rps, "zbb"));
2561 case INSN_CLASS_ZCB_AND_ZBA:
2562 return (riscv_subset_supports (rps, "zcb")
2563 && riscv_subset_supports (rps, "zba"));
2564 case INSN_CLASS_ZCB_AND_ZMMUL:
2565 return (riscv_subset_supports (rps, "zcb")
2566 && riscv_subset_supports (rps, "zmmul"));
2567 case INSN_CLASS_SVINVAL:
2568 return riscv_subset_supports (rps, "svinval");
2569 case INSN_CLASS_H:
2570 return riscv_subset_supports (rps, "h");
2571 case INSN_CLASS_XCVMAC:
2572 return riscv_subset_supports (rps, "xcvmac");
2573 case INSN_CLASS_XCVALU:
2574 return riscv_subset_supports (rps, "xcvalu");
2575 case INSN_CLASS_XTHEADBA:
2576 return riscv_subset_supports (rps, "xtheadba");
2577 case INSN_CLASS_XTHEADBB:
2578 return riscv_subset_supports (rps, "xtheadbb");
2579 case INSN_CLASS_XTHEADBS:
2580 return riscv_subset_supports (rps, "xtheadbs");
2581 case INSN_CLASS_XTHEADCMO:
2582 return riscv_subset_supports (rps, "xtheadcmo");
2583 case INSN_CLASS_XTHEADCONDMOV:
2584 return riscv_subset_supports (rps, "xtheadcondmov");
2585 case INSN_CLASS_XTHEADFMEMIDX:
2586 return riscv_subset_supports (rps, "xtheadfmemidx");
2587 case INSN_CLASS_XTHEADFMV:
2588 return riscv_subset_supports (rps, "xtheadfmv");
2589 case INSN_CLASS_XTHEADINT:
2590 return riscv_subset_supports (rps, "xtheadint");
2591 case INSN_CLASS_XTHEADMAC:
2592 return riscv_subset_supports (rps, "xtheadmac");
2593 case INSN_CLASS_XTHEADMEMIDX:
2594 return riscv_subset_supports (rps, "xtheadmemidx");
2595 case INSN_CLASS_XTHEADMEMPAIR:
2596 return riscv_subset_supports (rps, "xtheadmempair");
2597 case INSN_CLASS_XTHEADSYNC:
2598 return riscv_subset_supports (rps, "xtheadsync");
2599 case INSN_CLASS_XTHEADVECTOR:
2600 return riscv_subset_supports (rps, "xtheadvector");
2601 case INSN_CLASS_XTHEADZVAMO:
2602 return riscv_subset_supports (rps, "xtheadzvamo");
2603 case INSN_CLASS_XVENTANACONDOPS:
2604 return riscv_subset_supports (rps, "xventanacondops");
2605 case INSN_CLASS_XSFVCP:
2606 return riscv_subset_supports (rps, "xsfvcp");
2607 default:
2608 rps->error_handler
2609 (_("internal: unreachable INSN_CLASS_*"));
2610 return false;
2614 /* Each instuction is belonged to an instruction class INSN_CLASS_*.
2615 Call riscv_subset_supports_ext to determine the missing extension. */
2617 const char *
2618 riscv_multi_subset_supports_ext (riscv_parse_subset_t *rps,
2619 enum riscv_insn_class insn_class)
2621 switch (insn_class)
2623 case INSN_CLASS_I:
2624 return "i";
2625 case INSN_CLASS_ZICBOM:
2626 return "zicbom";
2627 case INSN_CLASS_ZICBOP:
2628 return "zicbop";
2629 case INSN_CLASS_ZICBOZ:
2630 return "zicboz";
2631 case INSN_CLASS_ZICOND:
2632 return "zicond";
2633 case INSN_CLASS_ZICSR:
2634 return "zicsr";
2635 case INSN_CLASS_ZIFENCEI:
2636 return "zifencei";
2637 case INSN_CLASS_ZIHINTNTL:
2638 return "zihintntl";
2639 case INSN_CLASS_ZIHINTNTL_AND_C:
2640 if (!riscv_subset_supports (rps, "zihintntl"))
2642 if (!riscv_subset_supports (rps, "c")
2643 && !riscv_subset_supports (rps, "zca"))
2644 return _("zihintntl' and `c', or `zihintntl' and `zca");
2645 else
2646 return "zihintntl";
2648 else
2649 return _("c' or `zca");
2650 case INSN_CLASS_ZIHINTPAUSE:
2651 return "zihintpause";
2652 case INSN_CLASS_M:
2653 return "m";
2654 case INSN_CLASS_ZMMUL:
2655 return _ ("m' or `zmmul");
2656 case INSN_CLASS_A:
2657 return "a";
2658 case INSN_CLASS_ZAWRS:
2659 return "zawrs";
2660 case INSN_CLASS_F:
2661 return "f";
2662 case INSN_CLASS_D:
2663 return "d";
2664 case INSN_CLASS_Q:
2665 return "q";
2666 case INSN_CLASS_C:
2667 return _("c' or `zca");
2668 case INSN_CLASS_F_AND_C:
2669 if (!riscv_subset_supports (rps, "f"))
2671 if (!riscv_subset_supports (rps, "c")
2672 && !riscv_subset_supports (rps, "zcf"))
2673 return _("f' and `c', or `f' and `zcf");
2674 else
2675 return "f";
2677 else
2678 return _("c' or `zcf");
2679 case INSN_CLASS_D_AND_C:
2680 if (!riscv_subset_supports (rps, "d"))
2682 if (!riscv_subset_supports (rps, "c")
2683 && !riscv_subset_supports (rps, "zcd"))
2684 return _("d' and `c', or `d' and `zcd");
2685 else
2686 return "d";
2688 else
2689 return _("c' or `zcd");
2690 case INSN_CLASS_F_INX:
2691 return _("f' or `zfinx");
2692 case INSN_CLASS_D_INX:
2693 return _("d' or `zdinx");
2694 case INSN_CLASS_Q_INX:
2695 return _("q' or `zqinx");
2696 case INSN_CLASS_ZFH_INX:
2697 return _("zfh' or `zhinx");
2698 case INSN_CLASS_ZFHMIN:
2699 return "zfhmin";
2700 case INSN_CLASS_ZFHMIN_INX:
2701 return _("zfhmin' or `zhinxmin");
2702 case INSN_CLASS_ZFHMIN_AND_D_INX:
2703 if (riscv_subset_supports (rps, "zfhmin"))
2704 return "d";
2705 else if (riscv_subset_supports (rps, "d"))
2706 return "zfhmin";
2707 else if (riscv_subset_supports (rps, "zhinxmin"))
2708 return "zdinx";
2709 else if (riscv_subset_supports (rps, "zdinx"))
2710 return "zhinxmin";
2711 else
2712 return _("zfhmin' and `d', or `zhinxmin' and `zdinx");
2713 case INSN_CLASS_ZFHMIN_AND_Q_INX:
2714 if (riscv_subset_supports (rps, "zfhmin"))
2715 return "q";
2716 else if (riscv_subset_supports (rps, "q"))
2717 return "zfhmin";
2718 else if (riscv_subset_supports (rps, "zhinxmin"))
2719 return "zqinx";
2720 else if (riscv_subset_supports (rps, "zqinx"))
2721 return "zhinxmin";
2722 else
2723 return _("zfhmin' and `q', or `zhinxmin' and `zqinx");
2724 case INSN_CLASS_ZFA:
2725 return "zfa";
2726 case INSN_CLASS_D_AND_ZFA:
2727 if (!riscv_subset_supports (rps, "d")
2728 && !riscv_subset_supports (rps, "zfa"))
2729 return _("d' and `zfa");
2730 else if (!riscv_subset_supports (rps, "d"))
2731 return "d";
2732 else
2733 return "zfa";
2734 case INSN_CLASS_Q_AND_ZFA:
2735 if (!riscv_subset_supports (rps, "q")
2736 && !riscv_subset_supports (rps, "zfa"))
2737 return _("q' and `zfa");
2738 else if (!riscv_subset_supports (rps, "q"))
2739 return "q";
2740 else
2741 return "zfa";
2742 case INSN_CLASS_ZFH_AND_ZFA:
2743 if (!riscv_subset_supports (rps, "zfh")
2744 && !riscv_subset_supports (rps, "zfa"))
2745 return _("zfh' and `zfa");
2746 else if (!riscv_subset_supports (rps, "zfh"))
2747 return "zfh";
2748 else
2749 return "zfa";
2750 case INSN_CLASS_ZFH_OR_ZVFH_AND_ZFA:
2751 if (!riscv_subset_supports (rps, "zfa"))
2753 if (!riscv_subset_supports (rps, "zfh")
2754 && !riscv_subset_supports (rps, "zvfh"))
2755 return _("zfh' and `zfa', or `zvfh' and `zfa");
2756 else
2757 return "zfa";
2759 else
2760 return _("zfh' or `zvfh");
2761 case INSN_CLASS_ZBA:
2762 return "zba";
2763 case INSN_CLASS_ZBB:
2764 return "zbb";
2765 case INSN_CLASS_ZBC:
2766 return "zbc";
2767 case INSN_CLASS_ZBS:
2768 return "zbs";
2769 case INSN_CLASS_ZBKB:
2770 return "zbkb";
2771 case INSN_CLASS_ZBKC:
2772 return "zbkc";
2773 case INSN_CLASS_ZBKX:
2774 return "zbkx";
2775 case INSN_CLASS_ZBB_OR_ZBKB:
2776 return _("zbb' or `zbkb");
2777 case INSN_CLASS_ZBC_OR_ZBKC:
2778 return _("zbc' or `zbkc");
2779 case INSN_CLASS_ZKND:
2780 return "zknd";
2781 case INSN_CLASS_ZKNE:
2782 return "zkne";
2783 case INSN_CLASS_ZKNH:
2784 return "zknh";
2785 case INSN_CLASS_ZKND_OR_ZKNE:
2786 return _("zknd' or `zkne");
2787 case INSN_CLASS_ZKSED:
2788 return "zksed";
2789 case INSN_CLASS_ZKSH:
2790 return "zksh";
2791 case INSN_CLASS_V:
2792 return _("v' or `zve64x' or `zve32x");
2793 case INSN_CLASS_ZVEF:
2794 return _("v' or `zve64d' or `zve64f' or `zve32f");
2795 case INSN_CLASS_ZVBB:
2796 return _("zvbb");
2797 case INSN_CLASS_ZVBC:
2798 return _("zvbc");
2799 case INSN_CLASS_ZVKB:
2800 return _("zvkb");
2801 case INSN_CLASS_ZVKG:
2802 return _("zvkg");
2803 case INSN_CLASS_ZVKNED:
2804 return _("zvkned");
2805 case INSN_CLASS_ZVKNHA_OR_ZVKNHB:
2806 return _("zvknha' or `zvknhb");
2807 case INSN_CLASS_ZVKSED:
2808 return _("zvksed");
2809 case INSN_CLASS_ZVKSH:
2810 return _("zvksh");
2811 case INSN_CLASS_ZCB:
2812 return "zcb";
2813 case INSN_CLASS_ZCB_AND_ZBA:
2814 return _("zcb' and `zba");
2815 case INSN_CLASS_ZCB_AND_ZBB:
2816 return _("zcb' and `zbb");
2817 case INSN_CLASS_ZCB_AND_ZMMUL:
2818 return _("zcb' and `zmmul', or `zcb' and `m");
2819 case INSN_CLASS_SVINVAL:
2820 return "svinval";
2821 case INSN_CLASS_H:
2822 return _("h");
2823 case INSN_CLASS_XCVMAC:
2824 return "xcvmac";
2825 case INSN_CLASS_XCVALU:
2826 return "xcvalu";
2827 case INSN_CLASS_XTHEADBA:
2828 return "xtheadba";
2829 case INSN_CLASS_XTHEADBB:
2830 return "xtheadbb";
2831 case INSN_CLASS_XTHEADBS:
2832 return "xtheadbs";
2833 case INSN_CLASS_XTHEADCMO:
2834 return "xtheadcmo";
2835 case INSN_CLASS_XTHEADCONDMOV:
2836 return "xtheadcondmov";
2837 case INSN_CLASS_XTHEADFMEMIDX:
2838 return "xtheadfmemidx";
2839 case INSN_CLASS_XTHEADFMV:
2840 return "xtheadfmv";
2841 case INSN_CLASS_XTHEADINT:
2842 return "xtheadint";
2843 case INSN_CLASS_XTHEADMAC:
2844 return "xtheadmac";
2845 case INSN_CLASS_XTHEADMEMIDX:
2846 return "xtheadmemidx";
2847 case INSN_CLASS_XTHEADMEMPAIR:
2848 return "xtheadmempair";
2849 case INSN_CLASS_XTHEADSYNC:
2850 return "xtheadsync";
2851 case INSN_CLASS_XTHEADVECTOR:
2852 return "xtheadvector";
2853 case INSN_CLASS_XTHEADZVAMO:
2854 return "xtheadzvamo";
2855 default:
2856 rps->error_handler
2857 (_("internal: unreachable INSN_CLASS_*"));
2858 return NULL;