Update HOWTO document after creating the 2.42 branch
[binutils-gdb.git] / bfd / elfxx-riscv.c
blob9a121b4712145030d5e69a8c05282d898c89fd7a
1 /* RISC-V-specific support for ELF.
2 Copyright (C) 2011-2024 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 {"zicntr", "zicsr", check_implicit_always},
1148 {"zihpm", "zicsr", check_implicit_always},
1149 {"zcd", "d", check_implicit_always},
1150 {"zcf", "f", check_implicit_always},
1151 {"zfa", "f", check_implicit_always},
1152 {"d", "f", check_implicit_always},
1153 {"zfh", "zfhmin", check_implicit_always},
1154 {"zfhmin", "f", check_implicit_always},
1155 {"f", "zicsr", check_implicit_always},
1156 {"zqinx", "zdinx", check_implicit_always},
1157 {"zdinx", "zfinx", check_implicit_always},
1158 {"zhinx", "zhinxmin", check_implicit_always},
1159 {"zhinxmin", "zfinx", check_implicit_always},
1160 {"zfinx", "zicsr", check_implicit_always},
1161 {"zk", "zkn", check_implicit_always},
1162 {"zk", "zkr", check_implicit_always},
1163 {"zk", "zkt", check_implicit_always},
1164 {"zkn", "zbkb", check_implicit_always},
1165 {"zkn", "zbkc", check_implicit_always},
1166 {"zkn", "zbkx", check_implicit_always},
1167 {"zkn", "zkne", check_implicit_always},
1168 {"zkn", "zknd", check_implicit_always},
1169 {"zkn", "zknh", check_implicit_always},
1170 {"zks", "zbkb", check_implicit_always},
1171 {"zks", "zbkc", check_implicit_always},
1172 {"zks", "zbkx", check_implicit_always},
1173 {"zks", "zksed", check_implicit_always},
1174 {"zks", "zksh", check_implicit_always},
1175 {"zvbb", "zvkb", check_implicit_always},
1176 {"zvkn", "zvkned", check_implicit_always},
1177 {"zvkn", "zvknha", check_implicit_always},
1178 {"zvkn", "zvknhb", check_implicit_always},
1179 {"zvkn", "zvkb", check_implicit_always},
1180 {"zvkn", "zvkt", check_implicit_always},
1181 {"zvkng", "zvkn", check_implicit_always},
1182 {"zvkng", "zvkg", check_implicit_always},
1183 {"zvknc", "zvkn", check_implicit_always},
1184 {"zvknc", "zvbc", check_implicit_always},
1185 {"zvks", "zvksed", check_implicit_always},
1186 {"zvks", "zvksh", check_implicit_always},
1187 {"zvks", "zvkb", check_implicit_always},
1188 {"zvks", "zvkt", check_implicit_always},
1189 {"zvksg", "zvks", check_implicit_always},
1190 {"zvksg", "zvkg", check_implicit_always},
1191 {"zvksc", "zvks", check_implicit_always},
1192 {"zvksc", "zvbc", check_implicit_always},
1193 {"zcf", "zca", check_implicit_always},
1194 {"zcd", "zca", check_implicit_always},
1195 {"zcb", "zca", check_implicit_always},
1196 {"smaia", "ssaia", check_implicit_always},
1197 {"smcntrpmf", "zicsr", check_implicit_always},
1198 {"smstateen", "ssstateen", check_implicit_always},
1199 {"smepmp", "zicsr", check_implicit_always},
1200 {"ssaia", "zicsr", check_implicit_always},
1201 {"sscofpmf", "zicsr", check_implicit_always},
1202 {"ssstateen", "zicsr", check_implicit_always},
1203 {"sstc", "zicsr", check_implicit_always},
1204 {"svadu", "zicsr", check_implicit_always},
1206 {"xsfvcp", "zve32x", check_implicit_always},
1207 {NULL, NULL, NULL}
1210 /* For default_enable field, decide if the extension should
1211 be enbaled by default. */
1213 #define EXT_DEFAULT 0x1
1215 /* List all extensions that binutils should know about. */
1217 struct riscv_supported_ext
1219 const char *name;
1220 enum riscv_spec_class isa_spec_class;
1221 int major_version;
1222 int minor_version;
1223 unsigned long default_enable;
1226 /* The standard extensions must be added in canonical order. */
1228 static struct riscv_supported_ext riscv_supported_std_ext[] =
1230 {"e", ISA_SPEC_CLASS_20191213, 1, 9, 0 },
1231 {"e", ISA_SPEC_CLASS_20190608, 1, 9, 0 },
1232 {"e", ISA_SPEC_CLASS_2P2, 1, 9, 0 },
1233 {"i", ISA_SPEC_CLASS_20191213, 2, 1, 0 },
1234 {"i", ISA_SPEC_CLASS_20190608, 2, 1, 0 },
1235 {"i", ISA_SPEC_CLASS_2P2, 2, 0, 0 },
1236 /* The g is a special case which we don't want to output it,
1237 but still need it when adding implicit extensions. */
1238 {"g", ISA_SPEC_CLASS_NONE, RISCV_UNKNOWN_VERSION, RISCV_UNKNOWN_VERSION, EXT_DEFAULT },
1239 {"m", ISA_SPEC_CLASS_20191213, 2, 0, 0 },
1240 {"m", ISA_SPEC_CLASS_20190608, 2, 0, 0 },
1241 {"m", ISA_SPEC_CLASS_2P2, 2, 0, 0 },
1242 {"a", ISA_SPEC_CLASS_20191213, 2, 1, 0 },
1243 {"a", ISA_SPEC_CLASS_20190608, 2, 0, 0 },
1244 {"a", ISA_SPEC_CLASS_2P2, 2, 0, 0 },
1245 {"f", ISA_SPEC_CLASS_20191213, 2, 2, 0 },
1246 {"f", ISA_SPEC_CLASS_20190608, 2, 2, 0 },
1247 {"f", ISA_SPEC_CLASS_2P2, 2, 0, 0 },
1248 {"d", ISA_SPEC_CLASS_20191213, 2, 2, 0 },
1249 {"d", ISA_SPEC_CLASS_20190608, 2, 2, 0 },
1250 {"d", ISA_SPEC_CLASS_2P2, 2, 0, 0 },
1251 {"q", ISA_SPEC_CLASS_20191213, 2, 2, 0 },
1252 {"q", ISA_SPEC_CLASS_20190608, 2, 2, 0 },
1253 {"q", ISA_SPEC_CLASS_2P2, 2, 0, 0 },
1254 {"c", ISA_SPEC_CLASS_20191213, 2, 0, 0 },
1255 {"c", ISA_SPEC_CLASS_20190608, 2, 0, 0 },
1256 {"c", ISA_SPEC_CLASS_2P2, 2, 0, 0 },
1257 {"v", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1258 {"h", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1259 {NULL, 0, 0, 0, 0}
1262 static struct riscv_supported_ext riscv_supported_std_z_ext[] =
1264 {"zicbom", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1265 {"zicbop", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1266 {"zicboz", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1267 {"zicond", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1268 {"zicntr", ISA_SPEC_CLASS_DRAFT, 2, 0, 0 },
1269 {"zicsr", ISA_SPEC_CLASS_20191213, 2, 0, 0 },
1270 {"zicsr", ISA_SPEC_CLASS_20190608, 2, 0, 0 },
1271 {"zifencei", ISA_SPEC_CLASS_20191213, 2, 0, 0 },
1272 {"zifencei", ISA_SPEC_CLASS_20190608, 2, 0, 0 },
1273 {"zihintntl", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1274 {"zihintpause", ISA_SPEC_CLASS_DRAFT, 2, 0, 0 },
1275 {"zihpm", ISA_SPEC_CLASS_DRAFT, 2, 0, 0 },
1276 {"zmmul", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1277 {"zawrs", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1278 {"zfa", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1279 {"zfh", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1280 {"zfhmin", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1281 {"zfinx", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1282 {"zdinx", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1283 {"zqinx", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1284 {"zhinx", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1285 {"zhinxmin", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1286 {"zbb", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1287 {"zba", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1288 {"zbc", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1289 {"zbs", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1290 {"zbkb", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1291 {"zbkc", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1292 {"zbkx", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1293 {"zk", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1294 {"zkn", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1295 {"zknd", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1296 {"zkne", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1297 {"zknh", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1298 {"zkr", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1299 {"zks", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1300 {"zksed", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1301 {"zksh", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1302 {"zkt", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1303 {"zve32x", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1304 {"zve32f", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1305 {"zve64x", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1306 {"zve64f", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1307 {"zve64d", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1308 {"zvbb", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1309 {"zvbc", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1310 {"zvfh", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1311 {"zvfhmin", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1312 {"zvkb", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1313 {"zvkg", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1314 {"zvkn", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1315 {"zvkng", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1316 {"zvknc", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1317 {"zvkned", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1318 {"zvknha", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1319 {"zvknhb", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1320 {"zvksed", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1321 {"zvksh", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1322 {"zvks", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1323 {"zvksg", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1324 {"zvksc", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1325 {"zvkt", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1326 {"zvl32b", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1327 {"zvl64b", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1328 {"zvl128b", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1329 {"zvl256b", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1330 {"zvl512b", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1331 {"zvl1024b", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1332 {"zvl2048b", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1333 {"zvl4096b", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1334 {"zvl8192b", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1335 {"zvl16384b", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1336 {"zvl32768b", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1337 {"zvl65536b", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1338 {"ztso", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1339 {"zca", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1340 {"zcb", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1341 {"zcf", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1342 {"zcd", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1343 {NULL, 0, 0, 0, 0}
1346 static struct riscv_supported_ext riscv_supported_std_s_ext[] =
1348 {"smaia", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1349 {"smcntrpmf", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1350 {"smepmp", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1351 {"smstateen", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1352 {"ssaia", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1353 {"sscofpmf", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1354 {"ssstateen", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1355 {"sstc", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1356 {"svadu", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1357 {"svinval", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1358 {"svnapot", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1359 {"svpbmt", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1360 {NULL, 0, 0, 0, 0}
1363 static struct riscv_supported_ext riscv_supported_std_zxm_ext[] =
1365 {NULL, 0, 0, 0, 0}
1368 static struct riscv_supported_ext riscv_supported_vendor_x_ext[] =
1370 {"xcvmac", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1371 {"xcvalu", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1372 {"xtheadba", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1373 {"xtheadbb", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1374 {"xtheadbs", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1375 {"xtheadcmo", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1376 {"xtheadcondmov", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1377 {"xtheadfmemidx", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1378 {"xtheadfmv", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1379 {"xtheadint", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1380 {"xtheadmac", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1381 {"xtheadmemidx", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1382 {"xtheadmempair", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1383 {"xtheadsync", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1384 {"xtheadvector", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1385 {"xtheadzvamo", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1386 {"xventanacondops", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1387 {"xsfvcp", ISA_SPEC_CLASS_DRAFT, 1, 0, 0},
1388 {NULL, 0, 0, 0, 0}
1391 const struct riscv_supported_ext *riscv_all_supported_ext[] =
1393 riscv_supported_std_ext,
1394 riscv_supported_std_z_ext,
1395 riscv_supported_std_s_ext,
1396 riscv_supported_std_zxm_ext,
1397 riscv_supported_vendor_x_ext,
1398 NULL
1401 /* ISA extension prefixed name class. Must define them in parsing order. */
1402 enum riscv_prefix_ext_class
1404 RV_ISA_CLASS_Z = 1,
1405 RV_ISA_CLASS_S,
1406 RV_ISA_CLASS_ZXM,
1407 RV_ISA_CLASS_X,
1408 RV_ISA_CLASS_SINGLE
1411 /* Record the strings of the prefixed extensions, and their corresponding
1412 classes. The more letters of the prefix string, the more forward it must
1413 be defined. Otherwise, the riscv_get_prefix_class will map it to the
1414 wrong classes. */
1415 struct riscv_parse_prefix_config
1417 /* Class of the extension. */
1418 enum riscv_prefix_ext_class class;
1420 /* Prefix string for error printing and internal parser usage. */
1421 const char *prefix;
1423 static const struct riscv_parse_prefix_config parse_config[] =
1425 {RV_ISA_CLASS_ZXM, "zxm"},
1426 {RV_ISA_CLASS_Z, "z"},
1427 {RV_ISA_CLASS_S, "s"},
1428 {RV_ISA_CLASS_X, "x"},
1429 {RV_ISA_CLASS_SINGLE, NULL}
1432 /* Get the prefixed name class for the extensions, the class also
1433 means the order of the prefixed extensions. */
1435 static enum riscv_prefix_ext_class
1436 riscv_get_prefix_class (const char *arch)
1438 int i = 0;
1439 while (parse_config[i].class != RV_ISA_CLASS_SINGLE)
1441 if (strncmp (arch, parse_config[i].prefix,
1442 strlen (parse_config[i].prefix)) == 0)
1443 return parse_config[i].class;
1444 i++;
1446 return RV_ISA_CLASS_SINGLE;
1449 /* Check KNOWN_EXTS to see if the EXT is supported. */
1451 static bool
1452 riscv_known_prefixed_ext (const char *ext,
1453 struct riscv_supported_ext *known_exts)
1455 size_t i;
1456 for (i = 0; known_exts[i].name != NULL; ++i)
1457 if (strcmp (ext, known_exts[i].name) == 0)
1458 return true;
1459 return false;
1462 /* Check whether the prefixed extension is recognized or not. Return
1463 true if recognized, otehrwise return false. */
1465 static bool
1466 riscv_recognized_prefixed_ext (const char *ext)
1468 enum riscv_prefix_ext_class class = riscv_get_prefix_class (ext);
1469 switch (class)
1471 case RV_ISA_CLASS_Z:
1472 return riscv_known_prefixed_ext (ext, riscv_supported_std_z_ext);
1473 case RV_ISA_CLASS_ZXM:
1474 return riscv_known_prefixed_ext (ext, riscv_supported_std_zxm_ext);
1475 case RV_ISA_CLASS_S:
1476 return riscv_known_prefixed_ext (ext, riscv_supported_std_s_ext);
1477 case RV_ISA_CLASS_X:
1478 /* Only the single x is unrecognized. */
1479 if (strcmp (ext, "x") != 0)
1480 return true;
1481 default:
1482 break;
1484 return false;
1487 /* Canonical order for single letter extensions. */
1488 static const char riscv_ext_canonical_order[] = "eigmafdqlcbkjtpvnh";
1490 /* Array is used to compare the orders of standard extensions quickly. */
1491 static int riscv_ext_order[26] = {0};
1493 /* Init the riscv_ext_order array. */
1495 static void
1496 riscv_init_ext_order (void)
1498 static bool inited = false;
1499 if (inited)
1500 return;
1502 /* The orders of all standard extensions are positive. */
1503 int order = 1;
1505 for (const char *ext = &riscv_ext_canonical_order[0]; *ext; ++ext)
1506 riscv_ext_order[(*ext - 'a')] = order++;
1508 /* Some of the prefixed keyword are not single letter, so we set
1509 their prefixed orders in the riscv_compare_subsets directly,
1510 not through the riscv_ext_order. */
1512 inited = true;
1515 /* Similar to the strcmp. It returns an integer less than, equal to,
1516 or greater than zero if `subset2` is found, respectively, to be less
1517 than, to match, or be greater than `subset1`.
1519 The order values,
1520 Zero: Preserved keywords.
1521 Positive number: Standard extensions.
1522 Negative number: Prefixed keywords. */
1525 riscv_compare_subsets (const char *subset1, const char *subset2)
1527 int order1 = riscv_ext_order[(*subset1 - 'a')];
1528 int order2 = riscv_ext_order[(*subset2 - 'a')];
1530 /* Compare the standard extension first. */
1531 if (order1 > 0 && order2 > 0)
1532 return order1 - order2;
1534 /* Set the prefixed orders to negative numbers. */
1535 enum riscv_prefix_ext_class class1 = riscv_get_prefix_class (subset1);
1536 enum riscv_prefix_ext_class class2 = riscv_get_prefix_class (subset2);
1538 if (class1 != RV_ISA_CLASS_SINGLE)
1539 order1 = - (int) class1;
1540 if (class2 != RV_ISA_CLASS_SINGLE)
1541 order2 = - (int) class2;
1543 if (order1 == order2)
1545 /* Compare the standard addition z extensions. */
1546 if (class1 == RV_ISA_CLASS_Z)
1548 order1 = riscv_ext_order[(*++subset1 - 'a')];
1549 order2 = riscv_ext_order[(*++subset2 - 'a')];
1550 if (order1 != order2)
1551 return order1 - order2;
1553 return strcasecmp (++subset1, ++subset2);
1556 return order2 - order1;
1559 /* Find subset in the list. Return TRUE and set `current` to the subset
1560 if it is found. Otherwise, return FALSE and set `current` to the place
1561 where we should insert the subset. However, return FALSE with the NULL
1562 `current` means we should insert the subset at the head of subset list,
1563 if needed. */
1565 bool
1566 riscv_lookup_subset (const riscv_subset_list_t *subset_list,
1567 const char *subset,
1568 riscv_subset_t **current)
1570 riscv_subset_t *s, *pre_s = NULL;
1572 /* If the subset is added in order, then just add it at the tail. */
1573 if (subset_list->tail != NULL
1574 && riscv_compare_subsets (subset_list->tail->name, subset) < 0)
1576 *current = subset_list->tail;
1577 return false;
1580 for (s = subset_list->head;
1581 s != NULL;
1582 pre_s = s, s = s->next)
1584 int cmp = riscv_compare_subsets (s->name, subset);
1585 if (cmp == 0)
1587 *current = s;
1588 return true;
1590 else if (cmp > 0)
1591 break;
1593 *current = pre_s;
1595 return false;
1598 /* Add the extension to the subset list. Search the
1599 list first, and then find the right place to add. */
1601 void
1602 riscv_add_subset (riscv_subset_list_t *subset_list,
1603 const char *subset,
1604 int major,
1605 int minor)
1607 riscv_subset_t *current, *new;
1609 if (riscv_lookup_subset (subset_list, subset, &current))
1610 return;
1612 new = xmalloc (sizeof *new);
1613 new->name = xstrdup (subset);
1614 new->major_version = major;
1615 new->minor_version = minor;
1616 new->next = NULL;
1618 if (current != NULL)
1620 new->next = current->next;
1621 current->next = new;
1623 else
1625 new->next = subset_list->head;
1626 subset_list->head = new;
1629 if (new->next == NULL)
1630 subset_list->tail = new;
1633 /* Get the default versions from the riscv_supported_*ext tables. */
1635 static void
1636 riscv_get_default_ext_version (enum riscv_spec_class *default_isa_spec,
1637 const char *name,
1638 int *major_version,
1639 int *minor_version)
1641 if (name == NULL
1642 || default_isa_spec == NULL
1643 || *default_isa_spec == ISA_SPEC_CLASS_NONE)
1644 return;
1646 struct riscv_supported_ext *table = NULL;
1647 enum riscv_prefix_ext_class class = riscv_get_prefix_class (name);
1648 switch (class)
1650 case RV_ISA_CLASS_ZXM: table = riscv_supported_std_zxm_ext; break;
1651 case RV_ISA_CLASS_Z: table = riscv_supported_std_z_ext; break;
1652 case RV_ISA_CLASS_S: table = riscv_supported_std_s_ext; break;
1653 case RV_ISA_CLASS_X: table = riscv_supported_vendor_x_ext; break;
1654 default:
1655 table = riscv_supported_std_ext;
1658 int i = 0;
1659 while (table != NULL && table[i].name != NULL)
1661 if (strcmp (table[i].name, name) == 0
1662 && (table[i].isa_spec_class == ISA_SPEC_CLASS_DRAFT
1663 || table[i].isa_spec_class == *default_isa_spec))
1665 *major_version = table[i].major_version;
1666 *minor_version = table[i].minor_version;
1667 return;
1669 i++;
1673 /* Find the default versions for the extension before adding them to
1674 the subset list, if their versions are RISCV_UNKNOWN_VERSION.
1675 Afterwards, report errors if we can not find their default versions. */
1677 static void
1678 riscv_parse_add_subset (riscv_parse_subset_t *rps,
1679 const char *subset,
1680 int major,
1681 int minor,
1682 bool implicit)
1684 int major_version = major;
1685 int minor_version = minor;
1687 if (major_version == RISCV_UNKNOWN_VERSION
1688 || minor_version == RISCV_UNKNOWN_VERSION)
1689 riscv_get_default_ext_version (rps->isa_spec, subset,
1690 &major_version, &minor_version);
1692 /* We don't care the versions of the implicit extensions. */
1693 if (!implicit
1694 && (major_version == RISCV_UNKNOWN_VERSION
1695 || minor_version == RISCV_UNKNOWN_VERSION))
1697 if (subset[0] == 'x')
1698 rps->error_handler
1699 (_("x ISA extension `%s' must be set with the versions"),
1700 subset);
1701 /* Allow old ISA spec can recognize zicsr and zifencei. */
1702 else if (strcmp (subset, "zicsr") != 0
1703 && strcmp (subset, "zifencei") != 0)
1704 rps->error_handler
1705 (_("cannot find default versions of the ISA extension `%s'"),
1706 subset);
1707 return;
1710 riscv_add_subset (rps->subset_list, subset,
1711 major_version, minor_version);
1714 /* Release subset list. */
1716 void
1717 riscv_release_subset_list (riscv_subset_list_t *subset_list)
1719 while (subset_list->head != NULL)
1721 riscv_subset_t *next = subset_list->head->next;
1722 free ((void *)subset_list->head->name);
1723 free (subset_list->head);
1724 subset_list->head = next;
1727 subset_list->tail = NULL;
1729 if (subset_list->arch_str != NULL)
1731 free ((void*) subset_list->arch_str);
1732 subset_list->arch_str = NULL;
1736 /* Parsing extension version.
1738 Return Value:
1739 Points to the end of version
1741 Arguments:
1742 `p`: Curent parsing position.
1743 `major_version`: Parsed major version.
1744 `minor_version`: Parsed minor version. */
1746 static const char *
1747 riscv_parsing_subset_version (const char *p,
1748 int *major_version,
1749 int *minor_version)
1751 bool major_p = true;
1752 int version = 0;
1753 char np;
1755 *major_version = 0;
1756 *minor_version = 0;
1757 for (; *p; ++p)
1759 if (*p == 'p')
1761 np = *(p + 1);
1763 /* Might be beginning of `p` extension. */
1764 if (!ISDIGIT (np))
1765 break;
1767 *major_version = version;
1768 major_p = false;
1769 version = 0;
1771 else if (ISDIGIT (*p))
1772 version = (version * 10) + (*p - '0');
1773 else
1774 break;
1777 if (major_p)
1778 *major_version = version;
1779 else
1780 *minor_version = version;
1782 /* We can not find any version in string. */
1783 if (*major_version == 0 && *minor_version == 0)
1785 *major_version = RISCV_UNKNOWN_VERSION;
1786 *minor_version = RISCV_UNKNOWN_VERSION;
1789 return p;
1792 /* Parsing function for both standard and prefixed extensions.
1794 Return Value:
1795 Points to the end of extensions.
1797 Arguments:
1798 `rps`: Hooks and status for parsing extensions.
1799 `arch`: Full ISA string.
1800 `p`: Curent parsing position. */
1802 static const char *
1803 riscv_parse_extensions (riscv_parse_subset_t *rps,
1804 const char *arch,
1805 const char *p)
1807 /* First letter must start with i, e or g. */
1808 if (*p != 'e' && *p != 'i' && *p != 'g')
1810 rps->error_handler
1811 (_("%s: first ISA extension must be `e', `i' or `g'"),
1812 arch);
1813 return NULL;
1816 while (*p != '\0')
1818 if (*p == '_')
1820 p++;
1821 continue;
1824 char *subset = xstrdup (p);
1825 char *q = subset; /* Start of version. */
1826 const char *end_of_version;
1827 bool implicit = false;
1829 enum riscv_prefix_ext_class class = riscv_get_prefix_class (p);
1830 if (class == RV_ISA_CLASS_SINGLE)
1832 if (riscv_ext_order[(*subset - 'a')] == 0)
1834 rps->error_handler
1835 (_("%s: unknown standard ISA extension or prefix class `%c'"),
1836 arch, *subset);
1837 free (subset);
1838 return NULL;
1840 q++;
1842 else
1844 /* Extract the whole prefixed extension by '_'. */
1845 while (*++q != '\0' && *q != '_')
1847 /* Look forward to the first letter which is not <major>p<minor>. */
1848 bool find_any_version = false;
1849 bool find_minor_version = false;
1850 while (1)
1852 q--;
1853 if (ISDIGIT (*q))
1854 find_any_version = true;
1855 else if (find_any_version
1856 && !find_minor_version
1857 && *q == 'p'
1858 && ISDIGIT (*(q - 1)))
1859 find_minor_version = true;
1860 else
1861 break;
1863 q++;
1865 /* Check if the end of extension is 'p' or not. If yes, then
1866 the second letter from the end cannot be number. */
1867 if (*(q - 1) == 'p' && ISDIGIT (*(q - 2)))
1869 *q = '\0';
1870 rps->error_handler
1871 (_("%s: invalid prefixed ISA extension `%s' ends with <number>p"),
1872 arch, subset);
1873 free (subset);
1874 return NULL;
1878 int major_version = RISCV_UNKNOWN_VERSION;
1879 int minor_version = RISCV_UNKNOWN_VERSION;
1880 end_of_version =
1881 riscv_parsing_subset_version (q, &major_version, &minor_version);
1882 *q = '\0';
1883 if (end_of_version == NULL)
1885 free (subset);
1886 return NULL;
1889 /* Check if the prefixed extension name is well-formed. */
1890 if (class != RV_ISA_CLASS_SINGLE
1891 && rps->check_unknown_prefixed_ext
1892 && !riscv_recognized_prefixed_ext (subset))
1894 rps->error_handler
1895 (_("%s: unknown prefixed ISA extension `%s'"),
1896 arch, subset);
1897 free (subset);
1898 return NULL;
1901 /* Added g as an implicit extension. */
1902 if (class == RV_ISA_CLASS_SINGLE
1903 && strcmp (subset, "g") == 0)
1905 implicit = true;
1906 major_version = RISCV_UNKNOWN_VERSION;
1907 minor_version = RISCV_UNKNOWN_VERSION;
1909 riscv_parse_add_subset (rps, subset,
1910 major_version,
1911 minor_version, implicit);
1912 p += end_of_version - subset;
1913 free (subset);
1915 if (class != RV_ISA_CLASS_SINGLE
1916 && *p != '\0' && *p != '_')
1918 rps->error_handler
1919 (_("%s: prefixed ISA extension must separate with _"),
1920 arch);
1921 return NULL;
1925 return p;
1928 /* Add the implicit extensions. */
1930 static void
1931 riscv_parse_add_implicit_subsets (riscv_parse_subset_t *rps)
1933 struct riscv_implicit_subset *t = riscv_implicit_subsets;
1934 bool finished = false;
1935 while (!finished)
1937 finished = true;
1938 for (; t->subset_name; t++)
1940 riscv_subset_t *subset = NULL;
1941 riscv_subset_t *implicit_subset = NULL;
1942 if (riscv_lookup_subset (rps->subset_list, t->subset_name, &subset)
1943 && !riscv_lookup_subset (rps->subset_list, t->implicit_name,
1944 &implicit_subset)
1945 && t->check_func (t->implicit_name, subset))
1947 riscv_parse_add_subset (rps, t->implicit_name,
1948 RISCV_UNKNOWN_VERSION,
1949 RISCV_UNKNOWN_VERSION, true);
1951 /* Restart the loop and pick up any new implications. */
1952 finished = false;
1953 t = riscv_implicit_subsets;
1954 break;
1960 /* Check extensions conflicts. */
1962 static bool
1963 riscv_parse_check_conflicts (riscv_parse_subset_t *rps)
1965 riscv_subset_t *subset = NULL;
1966 int xlen = *rps->xlen;
1967 bool no_conflict = true;
1969 if (riscv_subset_supports (rps, "e")
1970 && riscv_subset_supports (rps, "h"))
1972 rps->error_handler
1973 (_("rv%de does not support the `h' extension"), xlen);
1974 no_conflict = false;
1976 if (riscv_lookup_subset (rps->subset_list, "q", &subset)
1977 && (subset->major_version < 2 || (subset->major_version == 2
1978 && subset->minor_version < 2))
1979 && xlen < 64)
1981 rps->error_handler (_("rv%d does not support the `q' extension"), xlen);
1982 no_conflict = false;
1984 if (riscv_lookup_subset (rps->subset_list, "zcf", &subset)
1985 && xlen > 32)
1987 rps->error_handler
1988 (_("rv%d does not support the `zcf' extension"), xlen);
1989 no_conflict = false;
1991 if (riscv_lookup_subset (rps->subset_list, "zfinx", &subset)
1992 && riscv_lookup_subset (rps->subset_list, "f", &subset))
1994 rps->error_handler
1995 (_("`zfinx' is conflict with the `f/d/q/zfh/zfhmin' extension"));
1996 no_conflict = false;
1998 if (riscv_lookup_subset (rps->subset_list, "xtheadvector", &subset)
1999 && riscv_lookup_subset (rps->subset_list, "v", &subset))
2001 rps->error_handler
2002 (_("`xtheadvector' is conflict with the `v' extension"));
2003 no_conflict = false;
2006 bool support_zve = false;
2007 bool support_zvl = false;
2008 riscv_subset_t *s = rps->subset_list->head;
2009 for (; s != NULL; s = s->next)
2011 if (!support_zve
2012 && strncmp (s->name, "zve", 3) == 0)
2013 support_zve = true;
2014 if (!support_zvl
2015 && strncmp (s->name, "zvl", 3) == 0)
2016 support_zvl = true;
2017 if (support_zve && support_zvl)
2018 break;
2020 if (support_zvl && !support_zve)
2022 rps->error_handler
2023 (_("zvl*b extensions need to enable either `v' or `zve' extension"));
2024 no_conflict = false;
2027 return no_conflict;
2030 /* Set the default subset list according to the default_enable field
2031 of riscv_supported_*ext tables. */
2033 static void
2034 riscv_set_default_arch (riscv_parse_subset_t *rps)
2036 unsigned long enable = EXT_DEFAULT;
2037 int i, j;
2038 for (i = 0; riscv_all_supported_ext[i] != NULL; i++)
2040 const struct riscv_supported_ext *table = riscv_all_supported_ext[i];
2041 for (j = 0; table[j].name != NULL; j++)
2043 bool implicit = false;
2044 if (strcmp (table[j].name, "g") == 0)
2045 implicit = true;
2046 if (table[j].default_enable & enable)
2047 riscv_parse_add_subset (rps, table[j].name,
2048 RISCV_UNKNOWN_VERSION,
2049 RISCV_UNKNOWN_VERSION, implicit);
2054 /* Function for parsing ISA string.
2056 Return Value:
2057 Return TRUE on success.
2059 Arguments:
2060 `rps`: Hooks and status for parsing extensions.
2061 `arch`: Full ISA string. */
2063 bool
2064 riscv_parse_subset (riscv_parse_subset_t *rps,
2065 const char *arch)
2067 const char *p;
2069 /* Init the riscv_ext_order array to compare the order of extensions
2070 quickly. */
2071 riscv_init_ext_order ();
2073 if (arch == NULL)
2075 riscv_set_default_arch (rps);
2076 riscv_parse_add_implicit_subsets (rps);
2077 return riscv_parse_check_conflicts (rps);
2080 for (p = arch; *p != '\0'; p++)
2082 if (ISUPPER (*p))
2084 rps->error_handler
2085 (_("%s: ISA string cannot contain uppercase letters"),
2086 arch);
2087 return false;
2091 p = arch;
2092 if (startswith (p, "rv32"))
2094 *rps->xlen = 32;
2095 p += 4;
2097 else if (startswith (p, "rv64"))
2099 *rps->xlen = 64;
2100 p += 4;
2102 else
2104 /* ISA string shouldn't be NULL or empty here. For linker,
2105 it might be empty when we failed to merge the ISA string
2106 in the riscv_merge_attributes. For assembler, we might
2107 give an empty string by .attribute arch, "" or -march=.
2108 However, We have already issued the correct error message
2109 in another side, so do not issue this error when the ISA
2110 string is empty. */
2111 if (strlen (arch))
2112 rps->error_handler (
2113 _("%s: ISA string must begin with rv32 or rv64"),
2114 arch);
2115 return false;
2118 /* Parse single standard and prefixed extensions. */
2119 if (riscv_parse_extensions (rps, arch, p) == NULL)
2120 return false;
2122 /* Finally add implicit extensions according to the current
2123 extensions. */
2124 riscv_parse_add_implicit_subsets (rps);
2126 /* Check the conflicts. */
2127 return riscv_parse_check_conflicts (rps);
2130 /* Return the number of digits for the input. */
2132 size_t
2133 riscv_estimate_digit (unsigned num)
2135 size_t digit = 0;
2136 if (num == 0)
2137 return 1;
2139 for (digit = 0; num ; num /= 10)
2140 digit++;
2142 return digit;
2145 /* Auxiliary function to estimate string length of subset list. */
2147 static size_t
2148 riscv_estimate_arch_strlen1 (const riscv_subset_t *subset)
2150 if (subset == NULL)
2151 return 6; /* For rv32/rv64/rv128 and string terminator. */
2153 return riscv_estimate_arch_strlen1 (subset->next)
2154 + strlen (subset->name)
2155 + riscv_estimate_digit (subset->major_version)
2156 + 1 /* For version seperator 'p'. */
2157 + riscv_estimate_digit (subset->minor_version)
2158 + 1 /* For underscore. */;
2161 /* Estimate the string length of this subset list. */
2163 static size_t
2164 riscv_estimate_arch_strlen (const riscv_subset_list_t *subset_list)
2166 return riscv_estimate_arch_strlen1 (subset_list->head);
2169 /* Auxiliary function to convert subset info to string. */
2171 static void
2172 riscv_arch_str1 (riscv_subset_t *subset,
2173 char *attr_str, char *buf, size_t bufsz)
2175 const char *underline = "_";
2176 riscv_subset_t *subset_t = subset;
2178 if (subset_t == NULL)
2179 return;
2181 /* No underline between rvXX and i/e. */
2182 if ((strcasecmp (subset_t->name, "i") == 0)
2183 || (strcasecmp (subset_t->name, "e") == 0))
2184 underline = "";
2186 snprintf (buf, bufsz, "%s%s%dp%d",
2187 underline,
2188 subset_t->name,
2189 subset_t->major_version,
2190 subset_t->minor_version);
2192 strncat (attr_str, buf, bufsz);
2194 /* Skip 'i' extension after 'e', or skip extensions which
2195 versions are unknown. */
2196 while (subset_t->next
2197 && ((strcmp (subset_t->name, "e") == 0
2198 && strcmp (subset_t->next->name, "i") == 0)
2199 || subset_t->next->major_version == RISCV_UNKNOWN_VERSION
2200 || subset_t->next->minor_version == RISCV_UNKNOWN_VERSION))
2201 subset_t = subset_t->next;
2203 riscv_arch_str1 (subset_t->next, attr_str, buf, bufsz);
2206 /* Convert subset information into string with explicit versions. */
2208 char *
2209 riscv_arch_str (unsigned xlen, const riscv_subset_list_t *subset)
2211 size_t arch_str_len = riscv_estimate_arch_strlen (subset);
2212 char *attr_str = xmalloc (arch_str_len);
2213 char *buf = xmalloc (arch_str_len);
2215 snprintf (attr_str, arch_str_len, "rv%u", xlen);
2217 riscv_arch_str1 (subset->head, attr_str, buf, arch_str_len);
2218 free (buf);
2220 return attr_str;
2223 /* Copy the subset in the subset list. */
2225 static struct riscv_subset_t *
2226 riscv_copy_subset (riscv_subset_list_t *subset_list,
2227 riscv_subset_t *subset)
2229 if (subset == NULL)
2230 return NULL;
2232 riscv_subset_t *new = xmalloc (sizeof *new);
2233 new->name = xstrdup (subset->name);
2234 new->major_version = subset->major_version;
2235 new->minor_version = subset->minor_version;
2236 new->next = riscv_copy_subset (subset_list, subset->next);
2238 if (subset->next == NULL)
2239 subset_list->tail = new;
2241 return new;
2244 /* Copy the subset list. */
2246 riscv_subset_list_t *
2247 riscv_copy_subset_list (riscv_subset_list_t *subset_list)
2249 riscv_subset_list_t *new = xmalloc (sizeof *new);
2250 new->head = riscv_copy_subset (new, subset_list->head);
2251 new->arch_str = strdup (subset_list->arch_str);
2252 return new;
2255 /* Remove the SUBSET from the subset list. */
2257 static void
2258 riscv_remove_subset (riscv_subset_list_t *subset_list,
2259 const char *subset)
2261 riscv_subset_t *current = subset_list->head;
2262 riscv_subset_t *pre = NULL;
2263 for (; current != NULL; pre = current, current = current->next)
2265 if (strcmp (current->name, subset) == 0)
2267 if (pre == NULL)
2268 subset_list->head = current->next;
2269 else
2270 pre->next = current->next;
2271 if (current->next == NULL)
2272 subset_list->tail = pre;
2273 free ((void *) current->name);
2274 free (current);
2275 break;
2280 /* Add/Remove an extension to/from the subset list. This is used for
2281 the .option rvc or norvc, and .option arch directives. */
2283 bool
2284 riscv_update_subset (riscv_parse_subset_t *rps,
2285 const char *str)
2287 const char *p = str;
2291 int major_version = RISCV_UNKNOWN_VERSION;
2292 int minor_version = RISCV_UNKNOWN_VERSION;
2294 bool removed = false;
2295 switch (*p)
2297 case '+': removed = false; break;
2298 case '-': removed = true; break;
2299 default:
2300 riscv_release_subset_list (rps->subset_list);
2301 return riscv_parse_subset (rps, p);
2303 ++p;
2305 char *subset = xstrdup (p);
2306 char *q = subset;
2307 const char *end_of_version;
2308 /* Extract the whole prefixed extension by ','. */
2309 while (*q != '\0' && *q != ',')
2310 q++;
2312 /* Look forward to the first letter which is not <major>p<minor>. */
2313 bool find_any_version = false;
2314 bool find_minor_version = false;
2315 size_t len = q - subset;
2316 size_t i;
2317 for (i = len; i > 0; i--)
2319 q--;
2320 if (ISDIGIT (*q))
2321 find_any_version = true;
2322 else if (find_any_version
2323 && !find_minor_version
2324 && *q == 'p'
2325 && ISDIGIT (*(q - 1)))
2326 find_minor_version = true;
2327 else
2328 break;
2330 if (len > 0)
2331 q++;
2333 /* Check if the end of extension is 'p' or not. If yes, then
2334 the second letter from the end cannot be number. */
2335 if (len > 1 && *(q - 1) == 'p' && ISDIGIT (*(q - 2)))
2337 *q = '\0';
2338 rps->error_handler
2339 (_("invalid ISA extension ends with <number>p "
2340 "in .option arch `%s'"), str);
2341 free (subset);
2342 return false;
2345 end_of_version =
2346 riscv_parsing_subset_version (q, &major_version, &minor_version);
2347 *q = '\0';
2348 if (end_of_version == NULL)
2350 free (subset);
2351 return false;
2354 if (strlen (subset) == 0
2355 || (strlen (subset) == 1
2356 && riscv_ext_order[(*subset - 'a')] == 0)
2357 || (strlen (subset) > 1
2358 && rps->check_unknown_prefixed_ext
2359 && !riscv_recognized_prefixed_ext (subset)))
2361 rps->error_handler
2362 (_("unknown ISA extension `%s' in .option arch `%s'"),
2363 subset, str);
2364 free (subset);
2365 return false;
2368 if (strcmp (subset, "i") == 0
2369 || strcmp (subset, "e") == 0
2370 || strcmp (subset, "g") == 0)
2372 rps->error_handler
2373 (_("cannot + or - base extension `%s' in .option "
2374 "arch `%s'"), subset, str);
2375 free (subset);
2376 return false;
2379 if (removed)
2380 riscv_remove_subset (rps->subset_list, subset);
2381 else
2382 riscv_parse_add_subset (rps, subset, major_version, minor_version, true);
2383 p += end_of_version - subset;
2384 free (subset);
2386 while (*p++ == ',');
2388 riscv_parse_add_implicit_subsets (rps);
2389 return riscv_parse_check_conflicts (rps);
2392 /* Check if the FEATURE subset is supported or not in the subset list.
2393 Return true if it is supported; Otherwise, return false. */
2395 bool
2396 riscv_subset_supports (riscv_parse_subset_t *rps,
2397 const char *feature)
2399 struct riscv_subset_t *subset;
2400 return riscv_lookup_subset (rps->subset_list, feature, &subset);
2403 /* Each instuction is belonged to an instruction class INSN_CLASS_*.
2404 Call riscv_subset_supports to make sure if the instuction is valid. */
2406 bool
2407 riscv_multi_subset_supports (riscv_parse_subset_t *rps,
2408 enum riscv_insn_class insn_class)
2410 switch (insn_class)
2412 case INSN_CLASS_I:
2413 return riscv_subset_supports (rps, "i");
2414 case INSN_CLASS_ZICBOM:
2415 return riscv_subset_supports (rps, "zicbom");
2416 case INSN_CLASS_ZICBOP:
2417 return riscv_subset_supports (rps, "zicbop");
2418 case INSN_CLASS_ZICBOZ:
2419 return riscv_subset_supports (rps, "zicboz");
2420 case INSN_CLASS_ZICOND:
2421 return riscv_subset_supports (rps, "zicond");
2422 case INSN_CLASS_ZICSR:
2423 return riscv_subset_supports (rps, "zicsr");
2424 case INSN_CLASS_ZIFENCEI:
2425 return riscv_subset_supports (rps, "zifencei");
2426 case INSN_CLASS_ZIHINTNTL:
2427 return riscv_subset_supports (rps, "zihintntl");
2428 case INSN_CLASS_ZIHINTNTL_AND_C:
2429 return (riscv_subset_supports (rps, "zihintntl")
2430 && (riscv_subset_supports (rps, "c")
2431 || riscv_subset_supports (rps, "zca")));
2432 case INSN_CLASS_ZIHINTPAUSE:
2433 return riscv_subset_supports (rps, "zihintpause");
2434 case INSN_CLASS_M:
2435 return riscv_subset_supports (rps, "m");
2436 case INSN_CLASS_ZMMUL:
2437 return riscv_subset_supports (rps, "zmmul");
2438 case INSN_CLASS_A:
2439 return riscv_subset_supports (rps, "a");
2440 case INSN_CLASS_ZAWRS:
2441 return riscv_subset_supports (rps, "zawrs");
2442 case INSN_CLASS_F:
2443 return riscv_subset_supports (rps, "f");
2444 case INSN_CLASS_D:
2445 return riscv_subset_supports (rps, "d");
2446 case INSN_CLASS_Q:
2447 return riscv_subset_supports (rps, "q");
2448 case INSN_CLASS_C:
2449 return (riscv_subset_supports (rps, "c")
2450 || riscv_subset_supports (rps, "zca"));
2451 case INSN_CLASS_F_AND_C:
2452 return (riscv_subset_supports (rps, "f")
2453 && (riscv_subset_supports (rps, "c")
2454 || riscv_subset_supports (rps, "zcf")));
2455 case INSN_CLASS_D_AND_C:
2456 return (riscv_subset_supports (rps, "d")
2457 && (riscv_subset_supports (rps, "c")
2458 || riscv_subset_supports (rps, "zcd")));
2459 case INSN_CLASS_F_INX:
2460 return (riscv_subset_supports (rps, "f")
2461 || riscv_subset_supports (rps, "zfinx"));
2462 case INSN_CLASS_D_INX:
2463 return (riscv_subset_supports (rps, "d")
2464 || riscv_subset_supports (rps, "zdinx"));
2465 case INSN_CLASS_Q_INX:
2466 return (riscv_subset_supports (rps, "q")
2467 || riscv_subset_supports (rps, "zqinx"));
2468 case INSN_CLASS_ZFH_INX:
2469 return (riscv_subset_supports (rps, "zfh")
2470 || riscv_subset_supports (rps, "zhinx"));
2471 case INSN_CLASS_ZFHMIN:
2472 return riscv_subset_supports (rps, "zfhmin");
2473 case INSN_CLASS_ZFHMIN_INX:
2474 return (riscv_subset_supports (rps, "zfhmin")
2475 || riscv_subset_supports (rps, "zhinxmin"));
2476 case INSN_CLASS_ZFHMIN_AND_D_INX:
2477 return ((riscv_subset_supports (rps, "zfhmin")
2478 && riscv_subset_supports (rps, "d"))
2479 || (riscv_subset_supports (rps, "zhinxmin")
2480 && riscv_subset_supports (rps, "zdinx")));
2481 case INSN_CLASS_ZFHMIN_AND_Q_INX:
2482 return ((riscv_subset_supports (rps, "zfhmin")
2483 && riscv_subset_supports (rps, "q"))
2484 || (riscv_subset_supports (rps, "zhinxmin")
2485 && riscv_subset_supports (rps, "zqinx")));
2486 case INSN_CLASS_ZFA:
2487 return riscv_subset_supports (rps, "zfa");
2488 case INSN_CLASS_D_AND_ZFA:
2489 return riscv_subset_supports (rps, "d")
2490 && riscv_subset_supports (rps, "zfa");
2491 case INSN_CLASS_Q_AND_ZFA:
2492 return riscv_subset_supports (rps, "q")
2493 && riscv_subset_supports (rps, "zfa");
2494 case INSN_CLASS_ZFH_AND_ZFA:
2495 return riscv_subset_supports (rps, "zfh")
2496 && riscv_subset_supports (rps, "zfa");
2497 case INSN_CLASS_ZFH_OR_ZVFH_AND_ZFA:
2498 return (riscv_subset_supports (rps, "zfh")
2499 || riscv_subset_supports (rps, "zvfh"))
2500 && riscv_subset_supports (rps, "zfa");
2501 case INSN_CLASS_ZBA:
2502 return riscv_subset_supports (rps, "zba");
2503 case INSN_CLASS_ZBB:
2504 return riscv_subset_supports (rps, "zbb");
2505 case INSN_CLASS_ZBC:
2506 return riscv_subset_supports (rps, "zbc");
2507 case INSN_CLASS_ZBS:
2508 return riscv_subset_supports (rps, "zbs");
2509 case INSN_CLASS_ZBKB:
2510 return riscv_subset_supports (rps, "zbkb");
2511 case INSN_CLASS_ZBKC:
2512 return riscv_subset_supports (rps, "zbkc");
2513 case INSN_CLASS_ZBKX:
2514 return riscv_subset_supports (rps, "zbkx");
2515 case INSN_CLASS_ZBB_OR_ZBKB:
2516 return (riscv_subset_supports (rps, "zbb")
2517 || riscv_subset_supports (rps, "zbkb"));
2518 case INSN_CLASS_ZBC_OR_ZBKC:
2519 return (riscv_subset_supports (rps, "zbc")
2520 || riscv_subset_supports (rps, "zbkc"));
2521 case INSN_CLASS_ZKND:
2522 return riscv_subset_supports (rps, "zknd");
2523 case INSN_CLASS_ZKNE:
2524 return riscv_subset_supports (rps, "zkne");
2525 case INSN_CLASS_ZKNH:
2526 return riscv_subset_supports (rps, "zknh");
2527 case INSN_CLASS_ZKND_OR_ZKNE:
2528 return (riscv_subset_supports (rps, "zknd")
2529 || riscv_subset_supports (rps, "zkne"));
2530 case INSN_CLASS_ZKSED:
2531 return riscv_subset_supports (rps, "zksed");
2532 case INSN_CLASS_ZKSH:
2533 return riscv_subset_supports (rps, "zksh");
2534 case INSN_CLASS_V:
2535 return (riscv_subset_supports (rps, "v")
2536 || riscv_subset_supports (rps, "zve64x")
2537 || riscv_subset_supports (rps, "zve32x"));
2538 case INSN_CLASS_ZVEF:
2539 return (riscv_subset_supports (rps, "v")
2540 || riscv_subset_supports (rps, "zve64d")
2541 || riscv_subset_supports (rps, "zve64f")
2542 || riscv_subset_supports (rps, "zve32f"));
2543 case INSN_CLASS_ZVBB:
2544 return riscv_subset_supports (rps, "zvbb");
2545 case INSN_CLASS_ZVBC:
2546 return riscv_subset_supports (rps, "zvbc");
2547 case INSN_CLASS_ZVKB:
2548 return riscv_subset_supports (rps, "zvkb");
2549 case INSN_CLASS_ZVKG:
2550 return riscv_subset_supports (rps, "zvkg");
2551 case INSN_CLASS_ZVKNED:
2552 return riscv_subset_supports (rps, "zvkned");
2553 case INSN_CLASS_ZVKNHA_OR_ZVKNHB:
2554 return (riscv_subset_supports (rps, "zvknha")
2555 || riscv_subset_supports (rps, "zvknhb"));
2556 case INSN_CLASS_ZVKSED:
2557 return riscv_subset_supports (rps, "zvksed");
2558 case INSN_CLASS_ZVKSH:
2559 return riscv_subset_supports (rps, "zvksh");
2560 case INSN_CLASS_ZCB:
2561 return riscv_subset_supports (rps, "zcb");
2562 case INSN_CLASS_ZCB_AND_ZBB:
2563 return (riscv_subset_supports (rps, "zcb")
2564 && riscv_subset_supports (rps, "zbb"));
2565 case INSN_CLASS_ZCB_AND_ZBA:
2566 return (riscv_subset_supports (rps, "zcb")
2567 && riscv_subset_supports (rps, "zba"));
2568 case INSN_CLASS_ZCB_AND_ZMMUL:
2569 return (riscv_subset_supports (rps, "zcb")
2570 && riscv_subset_supports (rps, "zmmul"));
2571 case INSN_CLASS_SVINVAL:
2572 return riscv_subset_supports (rps, "svinval");
2573 case INSN_CLASS_H:
2574 return riscv_subset_supports (rps, "h");
2575 case INSN_CLASS_XCVMAC:
2576 return riscv_subset_supports (rps, "xcvmac");
2577 case INSN_CLASS_XCVALU:
2578 return riscv_subset_supports (rps, "xcvalu");
2579 case INSN_CLASS_XTHEADBA:
2580 return riscv_subset_supports (rps, "xtheadba");
2581 case INSN_CLASS_XTHEADBB:
2582 return riscv_subset_supports (rps, "xtheadbb");
2583 case INSN_CLASS_XTHEADBS:
2584 return riscv_subset_supports (rps, "xtheadbs");
2585 case INSN_CLASS_XTHEADCMO:
2586 return riscv_subset_supports (rps, "xtheadcmo");
2587 case INSN_CLASS_XTHEADCONDMOV:
2588 return riscv_subset_supports (rps, "xtheadcondmov");
2589 case INSN_CLASS_XTHEADFMEMIDX:
2590 return riscv_subset_supports (rps, "xtheadfmemidx");
2591 case INSN_CLASS_XTHEADFMV:
2592 return riscv_subset_supports (rps, "xtheadfmv");
2593 case INSN_CLASS_XTHEADINT:
2594 return riscv_subset_supports (rps, "xtheadint");
2595 case INSN_CLASS_XTHEADMAC:
2596 return riscv_subset_supports (rps, "xtheadmac");
2597 case INSN_CLASS_XTHEADMEMIDX:
2598 return riscv_subset_supports (rps, "xtheadmemidx");
2599 case INSN_CLASS_XTHEADMEMPAIR:
2600 return riscv_subset_supports (rps, "xtheadmempair");
2601 case INSN_CLASS_XTHEADSYNC:
2602 return riscv_subset_supports (rps, "xtheadsync");
2603 case INSN_CLASS_XTHEADVECTOR:
2604 return riscv_subset_supports (rps, "xtheadvector");
2605 case INSN_CLASS_XTHEADZVAMO:
2606 return riscv_subset_supports (rps, "xtheadzvamo");
2607 case INSN_CLASS_XVENTANACONDOPS:
2608 return riscv_subset_supports (rps, "xventanacondops");
2609 case INSN_CLASS_XSFVCP:
2610 return riscv_subset_supports (rps, "xsfvcp");
2611 default:
2612 rps->error_handler
2613 (_("internal: unreachable INSN_CLASS_*"));
2614 return false;
2618 /* Each instuction is belonged to an instruction class INSN_CLASS_*.
2619 Call riscv_subset_supports_ext to determine the missing extension. */
2621 const char *
2622 riscv_multi_subset_supports_ext (riscv_parse_subset_t *rps,
2623 enum riscv_insn_class insn_class)
2625 switch (insn_class)
2627 case INSN_CLASS_I:
2628 return "i";
2629 case INSN_CLASS_ZICBOM:
2630 return "zicbom";
2631 case INSN_CLASS_ZICBOP:
2632 return "zicbop";
2633 case INSN_CLASS_ZICBOZ:
2634 return "zicboz";
2635 case INSN_CLASS_ZICOND:
2636 return "zicond";
2637 case INSN_CLASS_ZICSR:
2638 return "zicsr";
2639 case INSN_CLASS_ZIFENCEI:
2640 return "zifencei";
2641 case INSN_CLASS_ZIHINTNTL:
2642 return "zihintntl";
2643 case INSN_CLASS_ZIHINTNTL_AND_C:
2644 if (!riscv_subset_supports (rps, "zihintntl"))
2646 if (!riscv_subset_supports (rps, "c")
2647 && !riscv_subset_supports (rps, "zca"))
2648 return _("zihintntl' and `c', or `zihintntl' and `zca");
2649 else
2650 return "zihintntl";
2652 else
2653 return _("c' or `zca");
2654 case INSN_CLASS_ZIHINTPAUSE:
2655 return "zihintpause";
2656 case INSN_CLASS_M:
2657 return "m";
2658 case INSN_CLASS_ZMMUL:
2659 return _ ("m' or `zmmul");
2660 case INSN_CLASS_A:
2661 return "a";
2662 case INSN_CLASS_ZAWRS:
2663 return "zawrs";
2664 case INSN_CLASS_F:
2665 return "f";
2666 case INSN_CLASS_D:
2667 return "d";
2668 case INSN_CLASS_Q:
2669 return "q";
2670 case INSN_CLASS_C:
2671 return _("c' or `zca");
2672 case INSN_CLASS_F_AND_C:
2673 if (!riscv_subset_supports (rps, "f"))
2675 if (!riscv_subset_supports (rps, "c")
2676 && !riscv_subset_supports (rps, "zcf"))
2677 return _("f' and `c', or `f' and `zcf");
2678 else
2679 return "f";
2681 else
2682 return _("c' or `zcf");
2683 case INSN_CLASS_D_AND_C:
2684 if (!riscv_subset_supports (rps, "d"))
2686 if (!riscv_subset_supports (rps, "c")
2687 && !riscv_subset_supports (rps, "zcd"))
2688 return _("d' and `c', or `d' and `zcd");
2689 else
2690 return "d";
2692 else
2693 return _("c' or `zcd");
2694 case INSN_CLASS_F_INX:
2695 return _("f' or `zfinx");
2696 case INSN_CLASS_D_INX:
2697 return _("d' or `zdinx");
2698 case INSN_CLASS_Q_INX:
2699 return _("q' or `zqinx");
2700 case INSN_CLASS_ZFH_INX:
2701 return _("zfh' or `zhinx");
2702 case INSN_CLASS_ZFHMIN:
2703 return "zfhmin";
2704 case INSN_CLASS_ZFHMIN_INX:
2705 return _("zfhmin' or `zhinxmin");
2706 case INSN_CLASS_ZFHMIN_AND_D_INX:
2707 if (riscv_subset_supports (rps, "zfhmin"))
2708 return "d";
2709 else if (riscv_subset_supports (rps, "d"))
2710 return "zfhmin";
2711 else if (riscv_subset_supports (rps, "zhinxmin"))
2712 return "zdinx";
2713 else if (riscv_subset_supports (rps, "zdinx"))
2714 return "zhinxmin";
2715 else
2716 return _("zfhmin' and `d', or `zhinxmin' and `zdinx");
2717 case INSN_CLASS_ZFHMIN_AND_Q_INX:
2718 if (riscv_subset_supports (rps, "zfhmin"))
2719 return "q";
2720 else if (riscv_subset_supports (rps, "q"))
2721 return "zfhmin";
2722 else if (riscv_subset_supports (rps, "zhinxmin"))
2723 return "zqinx";
2724 else if (riscv_subset_supports (rps, "zqinx"))
2725 return "zhinxmin";
2726 else
2727 return _("zfhmin' and `q', or `zhinxmin' and `zqinx");
2728 case INSN_CLASS_ZFA:
2729 return "zfa";
2730 case INSN_CLASS_D_AND_ZFA:
2731 if (!riscv_subset_supports (rps, "d")
2732 && !riscv_subset_supports (rps, "zfa"))
2733 return _("d' and `zfa");
2734 else if (!riscv_subset_supports (rps, "d"))
2735 return "d";
2736 else
2737 return "zfa";
2738 case INSN_CLASS_Q_AND_ZFA:
2739 if (!riscv_subset_supports (rps, "q")
2740 && !riscv_subset_supports (rps, "zfa"))
2741 return _("q' and `zfa");
2742 else if (!riscv_subset_supports (rps, "q"))
2743 return "q";
2744 else
2745 return "zfa";
2746 case INSN_CLASS_ZFH_AND_ZFA:
2747 if (!riscv_subset_supports (rps, "zfh")
2748 && !riscv_subset_supports (rps, "zfa"))
2749 return _("zfh' and `zfa");
2750 else if (!riscv_subset_supports (rps, "zfh"))
2751 return "zfh";
2752 else
2753 return "zfa";
2754 case INSN_CLASS_ZFH_OR_ZVFH_AND_ZFA:
2755 if (!riscv_subset_supports (rps, "zfa"))
2757 if (!riscv_subset_supports (rps, "zfh")
2758 && !riscv_subset_supports (rps, "zvfh"))
2759 return _("zfh' and `zfa', or `zvfh' and `zfa");
2760 else
2761 return "zfa";
2763 else
2764 return _("zfh' or `zvfh");
2765 case INSN_CLASS_ZBA:
2766 return "zba";
2767 case INSN_CLASS_ZBB:
2768 return "zbb";
2769 case INSN_CLASS_ZBC:
2770 return "zbc";
2771 case INSN_CLASS_ZBS:
2772 return "zbs";
2773 case INSN_CLASS_ZBKB:
2774 return "zbkb";
2775 case INSN_CLASS_ZBKC:
2776 return "zbkc";
2777 case INSN_CLASS_ZBKX:
2778 return "zbkx";
2779 case INSN_CLASS_ZBB_OR_ZBKB:
2780 return _("zbb' or `zbkb");
2781 case INSN_CLASS_ZBC_OR_ZBKC:
2782 return _("zbc' or `zbkc");
2783 case INSN_CLASS_ZKND:
2784 return "zknd";
2785 case INSN_CLASS_ZKNE:
2786 return "zkne";
2787 case INSN_CLASS_ZKNH:
2788 return "zknh";
2789 case INSN_CLASS_ZKND_OR_ZKNE:
2790 return _("zknd' or `zkne");
2791 case INSN_CLASS_ZKSED:
2792 return "zksed";
2793 case INSN_CLASS_ZKSH:
2794 return "zksh";
2795 case INSN_CLASS_V:
2796 return _("v' or `zve64x' or `zve32x");
2797 case INSN_CLASS_ZVEF:
2798 return _("v' or `zve64d' or `zve64f' or `zve32f");
2799 case INSN_CLASS_ZVBB:
2800 return _("zvbb");
2801 case INSN_CLASS_ZVBC:
2802 return _("zvbc");
2803 case INSN_CLASS_ZVKB:
2804 return _("zvkb");
2805 case INSN_CLASS_ZVKG:
2806 return _("zvkg");
2807 case INSN_CLASS_ZVKNED:
2808 return _("zvkned");
2809 case INSN_CLASS_ZVKNHA_OR_ZVKNHB:
2810 return _("zvknha' or `zvknhb");
2811 case INSN_CLASS_ZVKSED:
2812 return _("zvksed");
2813 case INSN_CLASS_ZVKSH:
2814 return _("zvksh");
2815 case INSN_CLASS_ZCB:
2816 return "zcb";
2817 case INSN_CLASS_ZCB_AND_ZBA:
2818 return _("zcb' and `zba");
2819 case INSN_CLASS_ZCB_AND_ZBB:
2820 return _("zcb' and `zbb");
2821 case INSN_CLASS_ZCB_AND_ZMMUL:
2822 return _("zcb' and `zmmul', or `zcb' and `m");
2823 case INSN_CLASS_SVINVAL:
2824 return "svinval";
2825 case INSN_CLASS_H:
2826 return _("h");
2827 case INSN_CLASS_XCVMAC:
2828 return "xcvmac";
2829 case INSN_CLASS_XCVALU:
2830 return "xcvalu";
2831 case INSN_CLASS_XTHEADBA:
2832 return "xtheadba";
2833 case INSN_CLASS_XTHEADBB:
2834 return "xtheadbb";
2835 case INSN_CLASS_XTHEADBS:
2836 return "xtheadbs";
2837 case INSN_CLASS_XTHEADCMO:
2838 return "xtheadcmo";
2839 case INSN_CLASS_XTHEADCONDMOV:
2840 return "xtheadcondmov";
2841 case INSN_CLASS_XTHEADFMEMIDX:
2842 return "xtheadfmemidx";
2843 case INSN_CLASS_XTHEADFMV:
2844 return "xtheadfmv";
2845 case INSN_CLASS_XTHEADINT:
2846 return "xtheadint";
2847 case INSN_CLASS_XTHEADMAC:
2848 return "xtheadmac";
2849 case INSN_CLASS_XTHEADMEMIDX:
2850 return "xtheadmemidx";
2851 case INSN_CLASS_XTHEADMEMPAIR:
2852 return "xtheadmempair";
2853 case INSN_CLASS_XTHEADSYNC:
2854 return "xtheadsync";
2855 case INSN_CLASS_XTHEADVECTOR:
2856 return "xtheadvector";
2857 case INSN_CLASS_XTHEADZVAMO:
2858 return "xtheadzvamo";
2859 default:
2860 rps->error_handler
2861 (_("internal: unreachable INSN_CLASS_*"));
2862 return NULL;