Fix memory leak in RiscV assembler.
[binutils-gdb.git] / bfd / elfxx-riscv.c
blob6ed657171f0fb4a71022a166e2a790c5f2503bd5
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 /* Reserved for future relocs that the dynamic linker must understand. */
222 EMPTY_HOWTO (12),
223 EMPTY_HOWTO (13),
224 EMPTY_HOWTO (14),
225 EMPTY_HOWTO (15),
227 /* 12-bit PC-relative branch offset. */
228 HOWTO (R_RISCV_BRANCH, /* type */
229 0, /* rightshift */
230 4, /* size */
231 32, /* bitsize */
232 true, /* pc_relative */
233 0, /* bitpos */
234 complain_overflow_signed, /* complain_on_overflow */
235 bfd_elf_generic_reloc, /* special_function */
236 "R_RISCV_BRANCH", /* name */
237 false, /* partial_inplace */
238 0, /* src_mask */
239 ENCODE_BTYPE_IMM (-1U), /* dst_mask */
240 true), /* pcrel_offset */
242 /* 20-bit PC-relative jump offset. */
243 HOWTO (R_RISCV_JAL, /* type */
244 0, /* rightshift */
245 4, /* size */
246 32, /* bitsize */
247 true, /* pc_relative */
248 0, /* bitpos */
249 complain_overflow_dont, /* complain_on_overflow */
250 bfd_elf_generic_reloc, /* special_function */
251 "R_RISCV_JAL", /* name */
252 false, /* partial_inplace */
253 0, /* src_mask */
254 ENCODE_JTYPE_IMM (-1U), /* dst_mask */
255 true), /* pcrel_offset */
257 /* 32-bit PC-relative function call (AUIPC/JALR). */
258 HOWTO (R_RISCV_CALL, /* type */
259 0, /* rightshift */
260 8, /* size */
261 64, /* bitsize */
262 true, /* pc_relative */
263 0, /* bitpos */
264 complain_overflow_dont, /* complain_on_overflow */
265 bfd_elf_generic_reloc, /* special_function */
266 "R_RISCV_CALL", /* name */
267 false, /* partial_inplace */
268 0, /* src_mask */
269 ENCODE_UTYPE_IMM (-1U) | ((bfd_vma) ENCODE_ITYPE_IMM (-1U) << 32),
270 /* dst_mask */
271 true), /* pcrel_offset */
273 /* Like R_RISCV_CALL, but not locally binding. */
274 HOWTO (R_RISCV_CALL_PLT, /* type */
275 0, /* rightshift */
276 8, /* size */
277 64, /* bitsize */
278 true, /* pc_relative */
279 0, /* bitpos */
280 complain_overflow_dont, /* complain_on_overflow */
281 bfd_elf_generic_reloc, /* special_function */
282 "R_RISCV_CALL_PLT", /* name */
283 false, /* partial_inplace */
284 0, /* src_mask */
285 ENCODE_UTYPE_IMM (-1U) | ((bfd_vma) ENCODE_ITYPE_IMM (-1U) << 32),
286 /* dst_mask */
287 true), /* pcrel_offset */
289 /* High 20 bits of 32-bit PC-relative GOT access. */
290 HOWTO (R_RISCV_GOT_HI20, /* type */
291 0, /* rightshift */
292 4, /* size */
293 32, /* bitsize */
294 true, /* pc_relative */
295 0, /* bitpos */
296 complain_overflow_dont, /* complain_on_overflow */
297 bfd_elf_generic_reloc, /* special_function */
298 "R_RISCV_GOT_HI20", /* name */
299 false, /* partial_inplace */
300 0, /* src_mask */
301 ENCODE_UTYPE_IMM (-1U), /* dst_mask */
302 false), /* pcrel_offset */
304 /* High 20 bits of 32-bit PC-relative TLS IE GOT access. */
305 HOWTO (R_RISCV_TLS_GOT_HI20, /* type */
306 0, /* rightshift */
307 4, /* size */
308 32, /* bitsize */
309 true, /* pc_relative */
310 0, /* bitpos */
311 complain_overflow_dont, /* complain_on_overflow */
312 bfd_elf_generic_reloc, /* special_function */
313 "R_RISCV_TLS_GOT_HI20", /* name */
314 false, /* partial_inplace */
315 0, /* src_mask */
316 ENCODE_UTYPE_IMM (-1U), /* dst_mask */
317 false), /* pcrel_offset */
319 /* High 20 bits of 32-bit PC-relative TLS GD GOT reference. */
320 HOWTO (R_RISCV_TLS_GD_HI20, /* type */
321 0, /* rightshift */
322 4, /* size */
323 32, /* bitsize */
324 true, /* pc_relative */
325 0, /* bitpos */
326 complain_overflow_dont, /* complain_on_overflow */
327 bfd_elf_generic_reloc, /* special_function */
328 "R_RISCV_TLS_GD_HI20", /* name */
329 false, /* partial_inplace */
330 0, /* src_mask */
331 ENCODE_UTYPE_IMM (-1U), /* dst_mask */
332 false), /* pcrel_offset */
334 /* High 20 bits of 32-bit PC-relative reference. */
335 HOWTO (R_RISCV_PCREL_HI20, /* type */
336 0, /* rightshift */
337 4, /* size */
338 32, /* bitsize */
339 true, /* pc_relative */
340 0, /* bitpos */
341 complain_overflow_dont, /* complain_on_overflow */
342 bfd_elf_generic_reloc, /* special_function */
343 "R_RISCV_PCREL_HI20", /* name */
344 false, /* partial_inplace */
345 0, /* src_mask */
346 ENCODE_UTYPE_IMM (-1U), /* dst_mask */
347 true), /* pcrel_offset */
349 /* Low 12 bits of a 32-bit PC-relative load or add. */
350 HOWTO (R_RISCV_PCREL_LO12_I, /* type */
351 0, /* rightshift */
352 4, /* size */
353 32, /* bitsize */
354 false, /* pc_relative */
355 0, /* bitpos */
356 complain_overflow_dont, /* complain_on_overflow */
357 bfd_elf_generic_reloc, /* special_function */
358 "R_RISCV_PCREL_LO12_I", /* name */
359 false, /* partial_inplace */
360 0, /* src_mask */
361 ENCODE_ITYPE_IMM (-1U), /* dst_mask */
362 false), /* pcrel_offset */
364 /* Low 12 bits of a 32-bit PC-relative store. */
365 HOWTO (R_RISCV_PCREL_LO12_S, /* type */
366 0, /* rightshift */
367 4, /* size */
368 32, /* bitsize */
369 false, /* pc_relative */
370 0, /* bitpos */
371 complain_overflow_dont, /* complain_on_overflow */
372 bfd_elf_generic_reloc, /* special_function */
373 "R_RISCV_PCREL_LO12_S", /* name */
374 false, /* partial_inplace */
375 0, /* src_mask */
376 ENCODE_STYPE_IMM (-1U), /* dst_mask */
377 false), /* pcrel_offset */
379 /* High 20 bits of 32-bit absolute address. */
380 HOWTO (R_RISCV_HI20, /* type */
381 0, /* rightshift */
382 4, /* size */
383 32, /* bitsize */
384 false, /* pc_relative */
385 0, /* bitpos */
386 complain_overflow_dont, /* complain_on_overflow */
387 bfd_elf_generic_reloc, /* special_function */
388 "R_RISCV_HI20", /* name */
389 false, /* partial_inplace */
390 0, /* src_mask */
391 ENCODE_UTYPE_IMM (-1U), /* dst_mask */
392 false), /* pcrel_offset */
394 /* High 12 bits of 32-bit load or add. */
395 HOWTO (R_RISCV_LO12_I, /* type */
396 0, /* rightshift */
397 4, /* size */
398 32, /* bitsize */
399 false, /* pc_relative */
400 0, /* bitpos */
401 complain_overflow_dont, /* complain_on_overflow */
402 bfd_elf_generic_reloc, /* special_function */
403 "R_RISCV_LO12_I", /* name */
404 false, /* partial_inplace */
405 0, /* src_mask */
406 ENCODE_ITYPE_IMM (-1U), /* dst_mask */
407 false), /* pcrel_offset */
409 /* High 12 bits of 32-bit store. */
410 HOWTO (R_RISCV_LO12_S, /* type */
411 0, /* rightshift */
412 4, /* size */
413 32, /* bitsize */
414 false, /* pc_relative */
415 0, /* bitpos */
416 complain_overflow_dont, /* complain_on_overflow */
417 bfd_elf_generic_reloc, /* special_function */
418 "R_RISCV_LO12_S", /* name */
419 false, /* partial_inplace */
420 0, /* src_mask */
421 ENCODE_STYPE_IMM (-1U), /* dst_mask */
422 false), /* pcrel_offset */
424 /* High 20 bits of TLS LE thread pointer offset. */
425 HOWTO (R_RISCV_TPREL_HI20, /* type */
426 0, /* rightshift */
427 4, /* size */
428 32, /* bitsize */
429 false, /* pc_relative */
430 0, /* bitpos */
431 complain_overflow_signed, /* complain_on_overflow */
432 bfd_elf_generic_reloc, /* special_function */
433 "R_RISCV_TPREL_HI20", /* name */
434 true, /* partial_inplace */
435 0, /* src_mask */
436 ENCODE_UTYPE_IMM (-1U), /* dst_mask */
437 false), /* pcrel_offset */
439 /* Low 12 bits of TLS LE thread pointer offset for loads and adds. */
440 HOWTO (R_RISCV_TPREL_LO12_I, /* type */
441 0, /* rightshift */
442 4, /* size */
443 32, /* bitsize */
444 false, /* pc_relative */
445 0, /* bitpos */
446 complain_overflow_signed, /* complain_on_overflow */
447 bfd_elf_generic_reloc, /* special_function */
448 "R_RISCV_TPREL_LO12_I", /* name */
449 false, /* partial_inplace */
450 0, /* src_mask */
451 ENCODE_ITYPE_IMM (-1U), /* dst_mask */
452 false), /* pcrel_offset */
454 /* Low 12 bits of TLS LE thread pointer offset for stores. */
455 HOWTO (R_RISCV_TPREL_LO12_S, /* type */
456 0, /* rightshift */
457 4, /* size */
458 32, /* bitsize */
459 false, /* pc_relative */
460 0, /* bitpos */
461 complain_overflow_signed, /* complain_on_overflow */
462 bfd_elf_generic_reloc, /* special_function */
463 "R_RISCV_TPREL_LO12_S", /* name */
464 false, /* partial_inplace */
465 0, /* src_mask */
466 ENCODE_STYPE_IMM (-1U), /* dst_mask */
467 false), /* pcrel_offset */
469 /* TLS LE thread pointer usage. May be relaxed. */
470 HOWTO (R_RISCV_TPREL_ADD, /* type */
471 0, /* rightshift */
472 0, /* size */
473 0, /* bitsize */
474 false, /* pc_relative */
475 0, /* bitpos */
476 complain_overflow_dont, /* complain_on_overflow */
477 bfd_elf_generic_reloc, /* special_function */
478 "R_RISCV_TPREL_ADD", /* name */
479 false, /* partial_inplace */
480 0, /* src_mask */
481 0, /* dst_mask */
482 false), /* pcrel_offset */
484 /* 8-bit in-place addition, for local label subtraction. */
485 HOWTO (R_RISCV_ADD8, /* type */
486 0, /* rightshift */
487 1, /* size */
488 8, /* bitsize */
489 false, /* pc_relative */
490 0, /* bitpos */
491 complain_overflow_dont, /* complain_on_overflow */
492 riscv_elf_add_sub_reloc, /* special_function */
493 "R_RISCV_ADD8", /* name */
494 false, /* partial_inplace */
495 0, /* src_mask */
496 0xff, /* dst_mask */
497 false), /* pcrel_offset */
499 /* 16-bit in-place addition, for local label subtraction. */
500 HOWTO (R_RISCV_ADD16, /* type */
501 0, /* rightshift */
502 2, /* size */
503 16, /* bitsize */
504 false, /* pc_relative */
505 0, /* bitpos */
506 complain_overflow_dont, /* complain_on_overflow */
507 riscv_elf_add_sub_reloc, /* special_function */
508 "R_RISCV_ADD16", /* name */
509 false, /* partial_inplace */
510 0, /* src_mask */
511 0xffff, /* dst_mask */
512 false), /* pcrel_offset */
514 /* 32-bit in-place addition, for local label subtraction. */
515 HOWTO (R_RISCV_ADD32, /* type */
516 0, /* rightshift */
517 4, /* size */
518 32, /* bitsize */
519 false, /* pc_relative */
520 0, /* bitpos */
521 complain_overflow_dont, /* complain_on_overflow */
522 riscv_elf_add_sub_reloc, /* special_function */
523 "R_RISCV_ADD32", /* name */
524 false, /* partial_inplace */
525 0, /* src_mask */
526 0xffffffff, /* dst_mask */
527 false), /* pcrel_offset */
529 /* 64-bit in-place addition, for local label subtraction. */
530 HOWTO (R_RISCV_ADD64, /* type */
531 0, /* rightshift */
532 8, /* size */
533 64, /* bitsize */
534 false, /* pc_relative */
535 0, /* bitpos */
536 complain_overflow_dont, /* complain_on_overflow */
537 riscv_elf_add_sub_reloc, /* special_function */
538 "R_RISCV_ADD64", /* name */
539 false, /* partial_inplace */
540 0, /* src_mask */
541 MINUS_ONE, /* dst_mask */
542 false), /* pcrel_offset */
544 /* 8-bit in-place addition, for local label subtraction. */
545 HOWTO (R_RISCV_SUB8, /* type */
546 0, /* rightshift */
547 1, /* size */
548 8, /* bitsize */
549 false, /* pc_relative */
550 0, /* bitpos */
551 complain_overflow_dont, /* complain_on_overflow */
552 riscv_elf_add_sub_reloc, /* special_function */
553 "R_RISCV_SUB8", /* name */
554 false, /* partial_inplace */
555 0, /* src_mask */
556 0xff, /* dst_mask */
557 false), /* pcrel_offset */
559 /* 16-bit in-place addition, for local label subtraction. */
560 HOWTO (R_RISCV_SUB16, /* type */
561 0, /* rightshift */
562 2, /* size */
563 16, /* bitsize */
564 false, /* pc_relative */
565 0, /* bitpos */
566 complain_overflow_dont, /* complain_on_overflow */
567 riscv_elf_add_sub_reloc, /* special_function */
568 "R_RISCV_SUB16", /* name */
569 false, /* partial_inplace */
570 0, /* src_mask */
571 0xffff, /* dst_mask */
572 false), /* pcrel_offset */
574 /* 32-bit in-place addition, for local label subtraction. */
575 HOWTO (R_RISCV_SUB32, /* type */
576 0, /* rightshift */
577 4, /* size */
578 32, /* bitsize */
579 false, /* pc_relative */
580 0, /* bitpos */
581 complain_overflow_dont, /* complain_on_overflow */
582 riscv_elf_add_sub_reloc, /* special_function */
583 "R_RISCV_SUB32", /* name */
584 false, /* partial_inplace */
585 0, /* src_mask */
586 0xffffffff, /* dst_mask */
587 false), /* pcrel_offset */
589 /* 64-bit in-place addition, for local label subtraction. */
590 HOWTO (R_RISCV_SUB64, /* type */
591 0, /* rightshift */
592 8, /* size */
593 64, /* bitsize */
594 false, /* pc_relative */
595 0, /* bitpos */
596 complain_overflow_dont, /* complain_on_overflow */
597 riscv_elf_add_sub_reloc, /* special_function */
598 "R_RISCV_SUB64", /* name */
599 false, /* partial_inplace */
600 0, /* src_mask */
601 MINUS_ONE, /* dst_mask */
602 false), /* pcrel_offset */
604 /* 41 and 42 are reserved. */
605 EMPTY_HOWTO (0),
606 EMPTY_HOWTO (0),
608 /* Indicates an alignment statement. The addend field encodes how many
609 bytes of NOPs follow the statement. The desired alignment is the
610 addend rounded up to the next power of two. */
611 HOWTO (R_RISCV_ALIGN, /* type */
612 0, /* rightshift */
613 0, /* size */
614 0, /* bitsize */
615 false, /* pc_relative */
616 0, /* bitpos */
617 complain_overflow_dont, /* complain_on_overflow */
618 bfd_elf_generic_reloc, /* special_function */
619 "R_RISCV_ALIGN", /* name */
620 false, /* partial_inplace */
621 0, /* src_mask */
622 0, /* dst_mask */
623 false), /* pcrel_offset */
625 /* 8-bit PC-relative branch offset. */
626 HOWTO (R_RISCV_RVC_BRANCH, /* type */
627 0, /* rightshift */
628 2, /* size */
629 16, /* bitsize */
630 true, /* pc_relative */
631 0, /* bitpos */
632 complain_overflow_signed, /* complain_on_overflow */
633 bfd_elf_generic_reloc, /* special_function */
634 "R_RISCV_RVC_BRANCH", /* name */
635 false, /* partial_inplace */
636 0, /* src_mask */
637 ENCODE_CBTYPE_IMM (-1U), /* dst_mask */
638 true), /* pcrel_offset */
640 /* 11-bit PC-relative jump offset. */
641 HOWTO (R_RISCV_RVC_JUMP, /* type */
642 0, /* rightshift */
643 2, /* size */
644 16, /* bitsize */
645 true, /* pc_relative */
646 0, /* bitpos */
647 complain_overflow_dont, /* complain_on_overflow */
648 bfd_elf_generic_reloc, /* special_function */
649 "R_RISCV_RVC_JUMP", /* name */
650 false, /* partial_inplace */
651 0, /* src_mask */
652 ENCODE_CJTYPE_IMM (-1U), /* dst_mask */
653 true), /* pcrel_offset */
655 /* High 6 bits of 18-bit absolute address. */
656 HOWTO (R_RISCV_RVC_LUI, /* type */
657 0, /* rightshift */
658 2, /* size */
659 16, /* bitsize */
660 false, /* pc_relative */
661 0, /* bitpos */
662 complain_overflow_dont, /* complain_on_overflow */
663 bfd_elf_generic_reloc, /* special_function */
664 "R_RISCV_RVC_LUI", /* name */
665 false, /* partial_inplace */
666 0, /* src_mask */
667 ENCODE_CITYPE_IMM (-1U), /* dst_mask */
668 false), /* pcrel_offset */
670 /* GP-relative load. */
671 HOWTO (R_RISCV_GPREL_I, /* type */
672 0, /* rightshift */
673 4, /* size */
674 32, /* bitsize */
675 false, /* pc_relative */
676 0, /* bitpos */
677 complain_overflow_dont, /* complain_on_overflow */
678 bfd_elf_generic_reloc, /* special_function */
679 "R_RISCV_GPREL_I", /* name */
680 false, /* partial_inplace */
681 0, /* src_mask */
682 ENCODE_ITYPE_IMM (-1U), /* dst_mask */
683 false), /* pcrel_offset */
685 /* GP-relative store. */
686 HOWTO (R_RISCV_GPREL_S, /* type */
687 0, /* rightshift */
688 4, /* size */
689 32, /* bitsize */
690 false, /* pc_relative */
691 0, /* bitpos */
692 complain_overflow_dont, /* complain_on_overflow */
693 bfd_elf_generic_reloc, /* special_function */
694 "R_RISCV_GPREL_S", /* name */
695 false, /* partial_inplace */
696 0, /* src_mask */
697 ENCODE_STYPE_IMM (-1U), /* dst_mask */
698 false), /* pcrel_offset */
700 /* TP-relative TLS LE load. */
701 HOWTO (R_RISCV_TPREL_I, /* type */
702 0, /* rightshift */
703 4, /* size */
704 32, /* bitsize */
705 false, /* pc_relative */
706 0, /* bitpos */
707 complain_overflow_signed, /* complain_on_overflow */
708 bfd_elf_generic_reloc, /* special_function */
709 "R_RISCV_TPREL_I", /* name */
710 false, /* partial_inplace */
711 0, /* src_mask */
712 ENCODE_ITYPE_IMM (-1U), /* dst_mask */
713 false), /* pcrel_offset */
715 /* TP-relative TLS LE store. */
716 HOWTO (R_RISCV_TPREL_S, /* type */
717 0, /* rightshift */
718 4, /* size */
719 32, /* bitsize */
720 false, /* pc_relative */
721 0, /* bitpos */
722 complain_overflow_signed, /* complain_on_overflow */
723 bfd_elf_generic_reloc, /* special_function */
724 "R_RISCV_TPREL_S", /* name */
725 false, /* partial_inplace */
726 0, /* src_mask */
727 ENCODE_STYPE_IMM (-1U), /* dst_mask */
728 false), /* pcrel_offset */
730 /* The paired relocation may be relaxed. */
731 HOWTO (R_RISCV_RELAX, /* type */
732 0, /* rightshift */
733 0, /* size */
734 0, /* bitsize */
735 false, /* pc_relative */
736 0, /* bitpos */
737 complain_overflow_dont, /* complain_on_overflow */
738 bfd_elf_generic_reloc, /* special_function */
739 "R_RISCV_RELAX", /* name */
740 false, /* partial_inplace */
741 0, /* src_mask */
742 0, /* dst_mask */
743 false), /* pcrel_offset */
745 /* 6-bit in-place addition, for local label subtraction. */
746 HOWTO (R_RISCV_SUB6, /* type */
747 0, /* rightshift */
748 1, /* size */
749 8, /* bitsize */
750 false, /* pc_relative */
751 0, /* bitpos */
752 complain_overflow_dont, /* complain_on_overflow */
753 riscv_elf_add_sub_reloc, /* special_function */
754 "R_RISCV_SUB6", /* name */
755 false, /* partial_inplace */
756 0, /* src_mask */
757 0x3f, /* dst_mask */
758 false), /* pcrel_offset */
760 /* 6-bit in-place setting, for local label subtraction. */
761 HOWTO (R_RISCV_SET6, /* type */
762 0, /* rightshift */
763 1, /* size */
764 8, /* bitsize */
765 false, /* pc_relative */
766 0, /* bitpos */
767 complain_overflow_dont, /* complain_on_overflow */
768 bfd_elf_generic_reloc, /* special_function */
769 "R_RISCV_SET6", /* name */
770 false, /* partial_inplace */
771 0, /* src_mask */
772 0x3f, /* dst_mask */
773 false), /* pcrel_offset */
775 /* 8-bit in-place setting, for local label subtraction. */
776 HOWTO (R_RISCV_SET8, /* type */
777 0, /* rightshift */
778 1, /* size */
779 8, /* bitsize */
780 false, /* pc_relative */
781 0, /* bitpos */
782 complain_overflow_dont, /* complain_on_overflow */
783 bfd_elf_generic_reloc, /* special_function */
784 "R_RISCV_SET8", /* name */
785 false, /* partial_inplace */
786 0, /* src_mask */
787 0xff, /* dst_mask */
788 false), /* pcrel_offset */
790 /* 16-bit in-place setting, for local label subtraction. */
791 HOWTO (R_RISCV_SET16, /* type */
792 0, /* rightshift */
793 2, /* size */
794 16, /* bitsize */
795 false, /* pc_relative */
796 0, /* bitpos */
797 complain_overflow_dont, /* complain_on_overflow */
798 bfd_elf_generic_reloc, /* special_function */
799 "R_RISCV_SET16", /* name */
800 false, /* partial_inplace */
801 0, /* src_mask */
802 0xffff, /* dst_mask */
803 false), /* pcrel_offset */
805 /* 32-bit in-place setting, for local label subtraction. */
806 HOWTO (R_RISCV_SET32, /* type */
807 0, /* rightshift */
808 4, /* size */
809 32, /* bitsize */
810 false, /* pc_relative */
811 0, /* bitpos */
812 complain_overflow_dont, /* complain_on_overflow */
813 bfd_elf_generic_reloc, /* special_function */
814 "R_RISCV_SET32", /* name */
815 false, /* partial_inplace */
816 0, /* src_mask */
817 0xffffffff, /* dst_mask */
818 false), /* pcrel_offset */
820 /* 32-bit PC relative. */
821 HOWTO (R_RISCV_32_PCREL, /* type */
822 0, /* rightshift */
823 4, /* size */
824 32, /* bitsize */
825 true, /* pc_relative */
826 0, /* bitpos */
827 complain_overflow_dont, /* complain_on_overflow */
828 bfd_elf_generic_reloc, /* special_function */
829 "R_RISCV_32_PCREL", /* name */
830 false, /* partial_inplace */
831 0, /* src_mask */
832 0xffffffff, /* dst_mask */
833 false), /* pcrel_offset */
835 /* Relocation against a local ifunc symbol in a shared object. */
836 HOWTO (R_RISCV_IRELATIVE, /* type */
837 0, /* rightshift */
838 4, /* size */
839 32, /* bitsize */
840 false, /* pc_relative */
841 0, /* bitpos */
842 complain_overflow_dont, /* complain_on_overflow */
843 bfd_elf_generic_reloc, /* special_function */
844 "R_RISCV_IRELATIVE", /* name */
845 false, /* partial_inplace */
846 0, /* src_mask */
847 0xffffffff, /* dst_mask */
848 false), /* pcrel_offset */
850 /* Reserved for R_RISCV_PLT32. */
851 EMPTY_HOWTO (59),
853 /* N-bit in-place setting, for unsigned-leb128 local label subtraction. */
854 HOWTO (R_RISCV_SET_ULEB128, /* type */
855 0, /* rightshift */
856 0, /* size */
857 0, /* bitsize */
858 false, /* pc_relative */
859 0, /* bitpos */
860 complain_overflow_dont, /* complain_on_overflow */
861 riscv_elf_ignore_reloc, /* special_function */
862 "R_RISCV_SET_ULEB128", /* name */
863 false, /* partial_inplace */
864 0, /* src_mask */
865 0, /* dst_mask */
866 false), /* pcrel_offset */
868 /* N-bit in-place addition, for unsigned-leb128 local label subtraction. */
869 HOWTO (R_RISCV_SUB_ULEB128, /* type */
870 0, /* rightshift */
871 0, /* size */
872 0, /* bitsize */
873 false, /* pc_relative */
874 0, /* bitpos */
875 complain_overflow_dont, /* complain_on_overflow */
876 riscv_elf_ignore_reloc, /* special_function */
877 "R_RISCV_SUB_ULEB128", /* name */
878 false, /* partial_inplace */
879 0, /* src_mask */
880 0, /* dst_mask */
881 false), /* pcrel_offset */
884 /* A mapping from BFD reloc types to RISC-V ELF reloc types. */
885 struct elf_reloc_map
887 bfd_reloc_code_real_type bfd_val;
888 enum elf_riscv_reloc_type elf_val;
891 static const struct elf_reloc_map riscv_reloc_map[] =
893 { BFD_RELOC_NONE, R_RISCV_NONE },
894 { BFD_RELOC_32, R_RISCV_32 },
895 { BFD_RELOC_64, R_RISCV_64 },
896 { BFD_RELOC_RISCV_ADD8, R_RISCV_ADD8 },
897 { BFD_RELOC_RISCV_ADD16, R_RISCV_ADD16 },
898 { BFD_RELOC_RISCV_ADD32, R_RISCV_ADD32 },
899 { BFD_RELOC_RISCV_ADD64, R_RISCV_ADD64 },
900 { BFD_RELOC_RISCV_SUB8, R_RISCV_SUB8 },
901 { BFD_RELOC_RISCV_SUB16, R_RISCV_SUB16 },
902 { BFD_RELOC_RISCV_SUB32, R_RISCV_SUB32 },
903 { BFD_RELOC_RISCV_SUB64, R_RISCV_SUB64 },
904 { BFD_RELOC_CTOR, R_RISCV_64 },
905 { BFD_RELOC_12_PCREL, R_RISCV_BRANCH },
906 { BFD_RELOC_RISCV_HI20, R_RISCV_HI20 },
907 { BFD_RELOC_RISCV_LO12_I, R_RISCV_LO12_I },
908 { BFD_RELOC_RISCV_LO12_S, R_RISCV_LO12_S },
909 { BFD_RELOC_RISCV_PCREL_LO12_I, R_RISCV_PCREL_LO12_I },
910 { BFD_RELOC_RISCV_PCREL_LO12_S, R_RISCV_PCREL_LO12_S },
911 { BFD_RELOC_RISCV_CALL, R_RISCV_CALL },
912 { BFD_RELOC_RISCV_CALL_PLT, R_RISCV_CALL_PLT },
913 { BFD_RELOC_RISCV_PCREL_HI20, R_RISCV_PCREL_HI20 },
914 { BFD_RELOC_RISCV_JMP, R_RISCV_JAL },
915 { BFD_RELOC_RISCV_GOT_HI20, R_RISCV_GOT_HI20 },
916 { BFD_RELOC_RISCV_TLS_DTPMOD32, R_RISCV_TLS_DTPMOD32 },
917 { BFD_RELOC_RISCV_TLS_DTPREL32, R_RISCV_TLS_DTPREL32 },
918 { BFD_RELOC_RISCV_TLS_DTPMOD64, R_RISCV_TLS_DTPMOD64 },
919 { BFD_RELOC_RISCV_TLS_DTPREL64, R_RISCV_TLS_DTPREL64 },
920 { BFD_RELOC_RISCV_TLS_TPREL32, R_RISCV_TLS_TPREL32 },
921 { BFD_RELOC_RISCV_TLS_TPREL64, R_RISCV_TLS_TPREL64 },
922 { BFD_RELOC_RISCV_TPREL_HI20, R_RISCV_TPREL_HI20 },
923 { BFD_RELOC_RISCV_TPREL_ADD, R_RISCV_TPREL_ADD },
924 { BFD_RELOC_RISCV_TPREL_LO12_S, R_RISCV_TPREL_LO12_S },
925 { BFD_RELOC_RISCV_TPREL_LO12_I, R_RISCV_TPREL_LO12_I },
926 { BFD_RELOC_RISCV_TLS_GOT_HI20, R_RISCV_TLS_GOT_HI20 },
927 { BFD_RELOC_RISCV_TLS_GD_HI20, R_RISCV_TLS_GD_HI20 },
928 { BFD_RELOC_RISCV_ALIGN, R_RISCV_ALIGN },
929 { BFD_RELOC_RISCV_RVC_BRANCH, R_RISCV_RVC_BRANCH },
930 { BFD_RELOC_RISCV_RVC_JUMP, R_RISCV_RVC_JUMP },
931 { BFD_RELOC_RISCV_RVC_LUI, R_RISCV_RVC_LUI },
932 { BFD_RELOC_RISCV_GPREL_I, R_RISCV_GPREL_I },
933 { BFD_RELOC_RISCV_GPREL_S, R_RISCV_GPREL_S },
934 { BFD_RELOC_RISCV_TPREL_I, R_RISCV_TPREL_I },
935 { BFD_RELOC_RISCV_TPREL_S, R_RISCV_TPREL_S },
936 { BFD_RELOC_RISCV_RELAX, R_RISCV_RELAX },
937 { BFD_RELOC_RISCV_SUB6, R_RISCV_SUB6 },
938 { BFD_RELOC_RISCV_SET6, R_RISCV_SET6 },
939 { BFD_RELOC_RISCV_SET8, R_RISCV_SET8 },
940 { BFD_RELOC_RISCV_SET16, R_RISCV_SET16 },
941 { BFD_RELOC_RISCV_SET32, R_RISCV_SET32 },
942 { BFD_RELOC_RISCV_32_PCREL, R_RISCV_32_PCREL },
943 { BFD_RELOC_RISCV_SET_ULEB128, R_RISCV_SET_ULEB128 },
944 { BFD_RELOC_RISCV_SUB_ULEB128, R_RISCV_SUB_ULEB128 },
947 /* Given a BFD reloc type, return a howto structure. */
949 reloc_howto_type *
950 riscv_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED,
951 bfd_reloc_code_real_type code)
953 unsigned int i;
955 for (i = 0; i < ARRAY_SIZE (riscv_reloc_map); i++)
956 if (riscv_reloc_map[i].bfd_val == code)
957 return &howto_table[(int) riscv_reloc_map[i].elf_val];
959 bfd_set_error (bfd_error_bad_value);
960 return NULL;
963 reloc_howto_type *
964 riscv_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED, const char *r_name)
966 unsigned int i;
968 for (i = 0; i < ARRAY_SIZE (howto_table); i++)
969 if (howto_table[i].name && strcasecmp (howto_table[i].name, r_name) == 0)
970 return &howto_table[i];
972 return NULL;
975 reloc_howto_type *
976 riscv_elf_rtype_to_howto (bfd *abfd, unsigned int r_type)
978 if (r_type >= ARRAY_SIZE (howto_table))
980 (*_bfd_error_handler) (_("%pB: unsupported relocation type %#x"),
981 abfd, r_type);
982 bfd_set_error (bfd_error_bad_value);
983 return NULL;
985 return &howto_table[r_type];
988 /* Special_function of RISCV_ADD and RISCV_SUB relocations. */
990 static bfd_reloc_status_type
991 riscv_elf_add_sub_reloc (bfd *abfd,
992 arelent *reloc_entry,
993 asymbol *symbol,
994 void *data,
995 asection *input_section,
996 bfd *output_bfd,
997 char **error_message ATTRIBUTE_UNUSED)
999 reloc_howto_type *howto = reloc_entry->howto;
1000 bfd_vma relocation;
1002 if (output_bfd != NULL
1003 && (symbol->flags & BSF_SECTION_SYM) == 0
1004 && (!reloc_entry->howto->partial_inplace || reloc_entry->addend == 0))
1006 reloc_entry->address += input_section->output_offset;
1007 return bfd_reloc_ok;
1010 if (output_bfd != NULL)
1011 return bfd_reloc_continue;
1013 relocation = symbol->value + symbol->section->output_section->vma
1014 + symbol->section->output_offset + reloc_entry->addend;
1016 bfd_size_type octets = reloc_entry->address
1017 * bfd_octets_per_byte (abfd, input_section);
1018 if (!bfd_reloc_offset_in_range (reloc_entry->howto, abfd,
1019 input_section, octets))
1020 return bfd_reloc_outofrange;
1022 bfd_vma old_value = bfd_get (howto->bitsize, abfd,
1023 data + reloc_entry->address);
1025 switch (howto->type)
1027 case R_RISCV_ADD8:
1028 case R_RISCV_ADD16:
1029 case R_RISCV_ADD32:
1030 case R_RISCV_ADD64:
1031 relocation = old_value + relocation;
1032 break;
1033 case R_RISCV_SUB6:
1034 relocation = (old_value & ~howto->dst_mask)
1035 | (((old_value & howto->dst_mask) - relocation)
1036 & howto->dst_mask);
1037 break;
1038 case R_RISCV_SUB8:
1039 case R_RISCV_SUB16:
1040 case R_RISCV_SUB32:
1041 case R_RISCV_SUB64:
1042 relocation = old_value - relocation;
1043 break;
1045 bfd_put (howto->bitsize, abfd, relocation, data + reloc_entry->address);
1047 return bfd_reloc_ok;
1050 /* Special handler for relocations which don't have to be relocated.
1051 This function just simply return bfd_reloc_ok. */
1053 static bfd_reloc_status_type
1054 riscv_elf_ignore_reloc (bfd *abfd ATTRIBUTE_UNUSED,
1055 arelent *reloc_entry,
1056 asymbol *symbol ATTRIBUTE_UNUSED,
1057 void *data ATTRIBUTE_UNUSED,
1058 asection *input_section,
1059 bfd *output_bfd,
1060 char **error_message ATTRIBUTE_UNUSED)
1062 if (output_bfd != NULL)
1063 reloc_entry->address += input_section->output_offset;
1064 return bfd_reloc_ok;
1067 /* Always add the IMPLICIT for the SUBSET. */
1069 static bool
1070 check_implicit_always (const char *implicit ATTRIBUTE_UNUSED,
1071 riscv_subset_t *subset ATTRIBUTE_UNUSED)
1073 return true;
1076 /* Add the IMPLICIT only when the version of SUBSET less than 2.1. */
1078 static bool
1079 check_implicit_for_i (const char *implicit ATTRIBUTE_UNUSED,
1080 riscv_subset_t *subset)
1082 return (subset->major_version < 2
1083 || (subset->major_version == 2
1084 && subset->minor_version < 1));
1087 /* Record all implicit information for the subsets. */
1088 struct riscv_implicit_subset
1090 const char *subset_name;
1091 const char *implicit_name;
1092 /* A function to determine if we need to add the implicit subset. */
1093 bool (*check_func) (const char *, riscv_subset_t *);
1095 static struct riscv_implicit_subset riscv_implicit_subsets[] =
1097 {"e", "i", check_implicit_always},
1098 {"i", "zicsr", check_implicit_for_i},
1099 {"i", "zifencei", check_implicit_for_i},
1100 {"g", "i", check_implicit_always},
1101 {"g", "m", check_implicit_always},
1102 {"g", "a", check_implicit_always},
1103 {"g", "f", check_implicit_always},
1104 {"g", "d", check_implicit_always},
1105 {"g", "zicsr", check_implicit_always},
1106 {"g", "zifencei", check_implicit_always},
1107 {"m", "zmmul", check_implicit_always},
1108 {"h", "zicsr", check_implicit_always},
1109 {"q", "d", check_implicit_always},
1110 {"v", "d", check_implicit_always},
1111 {"v", "zve64d", check_implicit_always},
1112 {"v", "zvl128b", check_implicit_always},
1113 {"zvfh", "zvfhmin", check_implicit_always},
1114 {"zvfh", "zfhmin", check_implicit_always},
1115 {"zvfhmin", "zve32f", check_implicit_always},
1116 {"zve64d", "d", check_implicit_always},
1117 {"zve64d", "zve64f", check_implicit_always},
1118 {"zve64f", "zve32f", check_implicit_always},
1119 {"zve64f", "zve64x", check_implicit_always},
1120 {"zve64f", "zvl64b", check_implicit_always},
1121 {"zve32f", "f", check_implicit_always},
1122 {"zve32f", "zvl32b", check_implicit_always},
1123 {"zve32f", "zve32x", check_implicit_always},
1124 {"zve64x", "zve32x", check_implicit_always},
1125 {"zve64x", "zvl64b", check_implicit_always},
1126 {"zve32x", "zvl32b", check_implicit_always},
1127 {"zve32x", "zicsr", check_implicit_always},
1128 {"zvl65536b", "zvl32768b", check_implicit_always},
1129 {"zvl32768b", "zvl16384b", check_implicit_always},
1130 {"zvl16384b", "zvl8192b", check_implicit_always},
1131 {"zvl8192b", "zvl4096b", check_implicit_always},
1132 {"zvl4096b", "zvl2048b", check_implicit_always},
1133 {"zvl2048b", "zvl1024b", check_implicit_always},
1134 {"zvl1024b", "zvl512b", check_implicit_always},
1135 {"zvl512b", "zvl256b", check_implicit_always},
1136 {"zvl256b", "zvl128b", check_implicit_always},
1137 {"zvl128b", "zvl64b", check_implicit_always},
1138 {"zvl64b", "zvl32b", check_implicit_always},
1139 {"zcd", "d", check_implicit_always},
1140 {"zcf", "f", check_implicit_always},
1141 {"zfa", "f", check_implicit_always},
1142 {"d", "f", check_implicit_always},
1143 {"zfh", "zfhmin", check_implicit_always},
1144 {"zfhmin", "f", check_implicit_always},
1145 {"f", "zicsr", check_implicit_always},
1146 {"zqinx", "zdinx", check_implicit_always},
1147 {"zdinx", "zfinx", check_implicit_always},
1148 {"zhinx", "zhinxmin", check_implicit_always},
1149 {"zhinxmin", "zfinx", check_implicit_always},
1150 {"zfinx", "zicsr", check_implicit_always},
1151 {"zk", "zkn", check_implicit_always},
1152 {"zk", "zkr", check_implicit_always},
1153 {"zk", "zkt", check_implicit_always},
1154 {"zkn", "zbkb", check_implicit_always},
1155 {"zkn", "zbkc", check_implicit_always},
1156 {"zkn", "zbkx", check_implicit_always},
1157 {"zkn", "zkne", check_implicit_always},
1158 {"zkn", "zknd", check_implicit_always},
1159 {"zkn", "zknh", check_implicit_always},
1160 {"zks", "zbkb", check_implicit_always},
1161 {"zks", "zbkc", check_implicit_always},
1162 {"zks", "zbkx", check_implicit_always},
1163 {"zks", "zksed", check_implicit_always},
1164 {"zks", "zksh", check_implicit_always},
1165 {"zvkn", "zvkned", check_implicit_always},
1166 {"zvkn", "zvknha", check_implicit_always},
1167 {"zvkn", "zvknhb", check_implicit_always},
1168 {"zvkn", "zvbb", check_implicit_always},
1169 {"zvkn", "zvkt", check_implicit_always},
1170 {"zvkng", "zvkn", check_implicit_always},
1171 {"zvkng", "zvkg", check_implicit_always},
1172 {"zvknc", "zvkn", check_implicit_always},
1173 {"zvknc", "zvbc", check_implicit_always},
1174 {"zvks", "zvksed", check_implicit_always},
1175 {"zvks", "zvksh", check_implicit_always},
1176 {"zvks", "zvbb", check_implicit_always},
1177 {"zvks", "zvkt", check_implicit_always},
1178 {"zvksg", "zvks", check_implicit_always},
1179 {"zvksg", "zvkg", check_implicit_always},
1180 {"zvksc", "zvks", check_implicit_always},
1181 {"zvksc", "zvbc", check_implicit_always},
1182 {"zcf", "zca", check_implicit_always},
1183 {"zcd", "zca", check_implicit_always},
1184 {"zcb", "zca", check_implicit_always},
1185 {"smaia", "ssaia", check_implicit_always},
1186 {"smcntrpmf", "zicsr", check_implicit_always},
1187 {"smstateen", "ssstateen", check_implicit_always},
1188 {"smepmp", "zicsr", check_implicit_always},
1189 {"ssaia", "zicsr", check_implicit_always},
1190 {"sscofpmf", "zicsr", check_implicit_always},
1191 {"ssstateen", "zicsr", check_implicit_always},
1192 {"sstc", "zicsr", check_implicit_always},
1193 {"svadu", "zicsr", check_implicit_always},
1194 {NULL, NULL, NULL}
1197 /* For default_enable field, decide if the extension should
1198 be enbaled by default. */
1200 #define EXT_DEFAULT 0x1
1202 /* List all extensions that binutils should know about. */
1204 struct riscv_supported_ext
1206 const char *name;
1207 enum riscv_spec_class isa_spec_class;
1208 int major_version;
1209 int minor_version;
1210 unsigned long default_enable;
1213 /* The standard extensions must be added in canonical order. */
1215 static struct riscv_supported_ext riscv_supported_std_ext[] =
1217 {"e", ISA_SPEC_CLASS_20191213, 1, 9, 0 },
1218 {"e", ISA_SPEC_CLASS_20190608, 1, 9, 0 },
1219 {"e", ISA_SPEC_CLASS_2P2, 1, 9, 0 },
1220 {"i", ISA_SPEC_CLASS_20191213, 2, 1, 0 },
1221 {"i", ISA_SPEC_CLASS_20190608, 2, 1, 0 },
1222 {"i", ISA_SPEC_CLASS_2P2, 2, 0, 0 },
1223 /* The g is a special case which we don't want to output it,
1224 but still need it when adding implicit extensions. */
1225 {"g", ISA_SPEC_CLASS_NONE, RISCV_UNKNOWN_VERSION, RISCV_UNKNOWN_VERSION, EXT_DEFAULT },
1226 {"m", ISA_SPEC_CLASS_20191213, 2, 0, 0 },
1227 {"m", ISA_SPEC_CLASS_20190608, 2, 0, 0 },
1228 {"m", ISA_SPEC_CLASS_2P2, 2, 0, 0 },
1229 {"a", ISA_SPEC_CLASS_20191213, 2, 1, 0 },
1230 {"a", ISA_SPEC_CLASS_20190608, 2, 0, 0 },
1231 {"a", ISA_SPEC_CLASS_2P2, 2, 0, 0 },
1232 {"f", ISA_SPEC_CLASS_20191213, 2, 2, 0 },
1233 {"f", ISA_SPEC_CLASS_20190608, 2, 2, 0 },
1234 {"f", ISA_SPEC_CLASS_2P2, 2, 0, 0 },
1235 {"d", ISA_SPEC_CLASS_20191213, 2, 2, 0 },
1236 {"d", ISA_SPEC_CLASS_20190608, 2, 2, 0 },
1237 {"d", ISA_SPEC_CLASS_2P2, 2, 0, 0 },
1238 {"q", ISA_SPEC_CLASS_20191213, 2, 2, 0 },
1239 {"q", ISA_SPEC_CLASS_20190608, 2, 2, 0 },
1240 {"q", ISA_SPEC_CLASS_2P2, 2, 0, 0 },
1241 {"c", ISA_SPEC_CLASS_20191213, 2, 0, 0 },
1242 {"c", ISA_SPEC_CLASS_20190608, 2, 0, 0 },
1243 {"c", ISA_SPEC_CLASS_2P2, 2, 0, 0 },
1244 {"v", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1245 {"h", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1246 {NULL, 0, 0, 0, 0}
1249 static struct riscv_supported_ext riscv_supported_std_z_ext[] =
1251 {"zicbom", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1252 {"zicbop", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1253 {"zicboz", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1254 {"zicond", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1255 {"zicsr", ISA_SPEC_CLASS_20191213, 2, 0, 0 },
1256 {"zicsr", ISA_SPEC_CLASS_20190608, 2, 0, 0 },
1257 {"zifencei", ISA_SPEC_CLASS_20191213, 2, 0, 0 },
1258 {"zifencei", ISA_SPEC_CLASS_20190608, 2, 0, 0 },
1259 {"zihintntl", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1260 {"zihintpause", ISA_SPEC_CLASS_DRAFT, 2, 0, 0 },
1261 {"zmmul", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1262 {"zawrs", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1263 {"zfa", ISA_SPEC_CLASS_DRAFT, 0, 1, 0 },
1264 {"zfh", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1265 {"zfhmin", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1266 {"zfinx", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1267 {"zdinx", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1268 {"zqinx", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1269 {"zhinx", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1270 {"zhinxmin", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1271 {"zbb", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1272 {"zba", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1273 {"zbc", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1274 {"zbs", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1275 {"zbkb", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1276 {"zbkc", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1277 {"zbkx", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1278 {"zk", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1279 {"zkn", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1280 {"zknd", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1281 {"zkne", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1282 {"zknh", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1283 {"zkr", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1284 {"zks", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1285 {"zksed", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1286 {"zksh", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1287 {"zkt", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1288 {"zve32x", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1289 {"zve32f", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1290 {"zve64x", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1291 {"zve64f", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1292 {"zve64d", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1293 {"zvbb", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1294 {"zvbc", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1295 {"zvfh", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1296 {"zvfhmin", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1297 {"zvkg", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1298 {"zvkn", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1299 {"zvkng", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1300 {"zvknc", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1301 {"zvkned", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1302 {"zvknha", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1303 {"zvknhb", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1304 {"zvksed", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1305 {"zvksh", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1306 {"zvks", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1307 {"zvksg", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1308 {"zvksc", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1309 {"zvkt", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1310 {"zvl32b", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1311 {"zvl64b", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1312 {"zvl128b", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1313 {"zvl256b", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1314 {"zvl512b", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1315 {"zvl1024b", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1316 {"zvl2048b", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1317 {"zvl4096b", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1318 {"zvl8192b", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1319 {"zvl16384b", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1320 {"zvl32768b", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1321 {"zvl65536b", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1322 {"ztso", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1323 {"zca", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1324 {"zcb", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1325 {"zcf", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1326 {"zcd", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1327 {NULL, 0, 0, 0, 0}
1330 static struct riscv_supported_ext riscv_supported_std_s_ext[] =
1332 {"smaia", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1333 {"smcntrpmf", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1334 {"smepmp", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1335 {"smstateen", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1336 {"ssaia", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1337 {"sscofpmf", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1338 {"ssstateen", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1339 {"sstc", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1340 {"svadu", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1341 {"svinval", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1342 {"svnapot", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1343 {"svpbmt", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1344 {NULL, 0, 0, 0, 0}
1347 static struct riscv_supported_ext riscv_supported_std_zxm_ext[] =
1349 {NULL, 0, 0, 0, 0}
1352 static struct riscv_supported_ext riscv_supported_vendor_x_ext[] =
1354 {"xtheadba", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1355 {"xtheadbb", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1356 {"xtheadbs", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1357 {"xtheadcmo", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1358 {"xtheadcondmov", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1359 {"xtheadfmemidx", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1360 {"xtheadfmv", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1361 {"xtheadint", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1362 {"xtheadmac", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1363 {"xtheadmemidx", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1364 {"xtheadmempair", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1365 {"xtheadsync", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1366 {"xventanacondops", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1367 {NULL, 0, 0, 0, 0}
1370 const struct riscv_supported_ext *riscv_all_supported_ext[] =
1372 riscv_supported_std_ext,
1373 riscv_supported_std_z_ext,
1374 riscv_supported_std_s_ext,
1375 riscv_supported_std_zxm_ext,
1376 riscv_supported_vendor_x_ext,
1377 NULL
1380 /* ISA extension prefixed name class. Must define them in parsing order. */
1381 enum riscv_prefix_ext_class
1383 RV_ISA_CLASS_Z = 1,
1384 RV_ISA_CLASS_S,
1385 RV_ISA_CLASS_ZXM,
1386 RV_ISA_CLASS_X,
1387 RV_ISA_CLASS_SINGLE
1390 /* Record the strings of the prefixed extensions, and their corresponding
1391 classes. The more letters of the prefix string, the more forward it must
1392 be defined. Otherwise, the riscv_get_prefix_class will map it to the
1393 wrong classes. */
1394 struct riscv_parse_prefix_config
1396 /* Class of the extension. */
1397 enum riscv_prefix_ext_class class;
1399 /* Prefix string for error printing and internal parser usage. */
1400 const char *prefix;
1402 static const struct riscv_parse_prefix_config parse_config[] =
1404 {RV_ISA_CLASS_ZXM, "zxm"},
1405 {RV_ISA_CLASS_Z, "z"},
1406 {RV_ISA_CLASS_S, "s"},
1407 {RV_ISA_CLASS_X, "x"},
1408 {RV_ISA_CLASS_SINGLE, NULL}
1411 /* Get the prefixed name class for the extensions, the class also
1412 means the order of the prefixed extensions. */
1414 static enum riscv_prefix_ext_class
1415 riscv_get_prefix_class (const char *arch)
1417 int i = 0;
1418 while (parse_config[i].class != RV_ISA_CLASS_SINGLE)
1420 if (strncmp (arch, parse_config[i].prefix,
1421 strlen (parse_config[i].prefix)) == 0)
1422 return parse_config[i].class;
1423 i++;
1425 return RV_ISA_CLASS_SINGLE;
1428 /* Check KNOWN_EXTS to see if the EXT is supported. */
1430 static bool
1431 riscv_known_prefixed_ext (const char *ext,
1432 struct riscv_supported_ext *known_exts)
1434 size_t i;
1435 for (i = 0; known_exts[i].name != NULL; ++i)
1436 if (strcmp (ext, known_exts[i].name) == 0)
1437 return true;
1438 return false;
1441 /* Check whether the prefixed extension is recognized or not. Return
1442 true if recognized, otehrwise return false. */
1444 static bool
1445 riscv_recognized_prefixed_ext (const char *ext)
1447 enum riscv_prefix_ext_class class = riscv_get_prefix_class (ext);
1448 switch (class)
1450 case RV_ISA_CLASS_Z:
1451 return riscv_known_prefixed_ext (ext, riscv_supported_std_z_ext);
1452 case RV_ISA_CLASS_ZXM:
1453 return riscv_known_prefixed_ext (ext, riscv_supported_std_zxm_ext);
1454 case RV_ISA_CLASS_S:
1455 return riscv_known_prefixed_ext (ext, riscv_supported_std_s_ext);
1456 case RV_ISA_CLASS_X:
1457 /* Only the single x is unrecognized. */
1458 if (strcmp (ext, "x") != 0)
1459 return true;
1460 default:
1461 break;
1463 return false;
1466 /* Canonical order for single letter extensions. */
1467 static const char riscv_ext_canonical_order[] = "eigmafdqlcbkjtpvnh";
1469 /* Array is used to compare the orders of standard extensions quickly. */
1470 static int riscv_ext_order[26] = {0};
1472 /* Init the riscv_ext_order array. */
1474 static void
1475 riscv_init_ext_order (void)
1477 static bool inited = false;
1478 if (inited)
1479 return;
1481 /* The orders of all standard extensions are positive. */
1482 int order = 1;
1484 for (const char *ext = &riscv_ext_canonical_order[0]; *ext; ++ext)
1485 riscv_ext_order[(*ext - 'a')] = order++;
1487 /* Some of the prefixed keyword are not single letter, so we set
1488 their prefixed orders in the riscv_compare_subsets directly,
1489 not through the riscv_ext_order. */
1491 inited = true;
1494 /* Similar to the strcmp. It returns an integer less than, equal to,
1495 or greater than zero if `subset2` is found, respectively, to be less
1496 than, to match, or be greater than `subset1`.
1498 The order values,
1499 Zero: Preserved keywords.
1500 Positive number: Standard extensions.
1501 Negative number: Prefixed keywords. */
1504 riscv_compare_subsets (const char *subset1, const char *subset2)
1506 int order1 = riscv_ext_order[(*subset1 - 'a')];
1507 int order2 = riscv_ext_order[(*subset2 - 'a')];
1509 /* Compare the standard extension first. */
1510 if (order1 > 0 && order2 > 0)
1511 return order1 - order2;
1513 /* Set the prefixed orders to negative numbers. */
1514 enum riscv_prefix_ext_class class1 = riscv_get_prefix_class (subset1);
1515 enum riscv_prefix_ext_class class2 = riscv_get_prefix_class (subset2);
1517 if (class1 != RV_ISA_CLASS_SINGLE)
1518 order1 = - (int) class1;
1519 if (class2 != RV_ISA_CLASS_SINGLE)
1520 order2 = - (int) class2;
1522 if (order1 == order2)
1524 /* Compare the standard addition z extensions. */
1525 if (class1 == RV_ISA_CLASS_Z)
1527 order1 = riscv_ext_order[(*++subset1 - 'a')];
1528 order2 = riscv_ext_order[(*++subset2 - 'a')];
1529 if (order1 != order2)
1530 return order1 - order2;
1532 return strcasecmp (++subset1, ++subset2);
1535 return order2 - order1;
1538 /* Find subset in the list. Return TRUE and set `current` to the subset
1539 if it is found. Otherwise, return FALSE and set `current` to the place
1540 where we should insert the subset. However, return FALSE with the NULL
1541 `current` means we should insert the subset at the head of subset list,
1542 if needed. */
1544 bool
1545 riscv_lookup_subset (const riscv_subset_list_t *subset_list,
1546 const char *subset,
1547 riscv_subset_t **current)
1549 riscv_subset_t *s, *pre_s = NULL;
1551 /* If the subset is added in order, then just add it at the tail. */
1552 if (subset_list->tail != NULL
1553 && riscv_compare_subsets (subset_list->tail->name, subset) < 0)
1555 *current = subset_list->tail;
1556 return false;
1559 for (s = subset_list->head;
1560 s != NULL;
1561 pre_s = s, s = s->next)
1563 int cmp = riscv_compare_subsets (s->name, subset);
1564 if (cmp == 0)
1566 *current = s;
1567 return true;
1569 else if (cmp > 0)
1570 break;
1572 *current = pre_s;
1574 return false;
1577 /* Add the extension to the subset list. Search the
1578 list first, and then find the right place to add. */
1580 void
1581 riscv_add_subset (riscv_subset_list_t *subset_list,
1582 const char *subset,
1583 int major,
1584 int minor)
1586 riscv_subset_t *current, *new;
1588 if (riscv_lookup_subset (subset_list, subset, &current))
1589 return;
1591 new = xmalloc (sizeof *new);
1592 new->name = xstrdup (subset);
1593 new->major_version = major;
1594 new->minor_version = minor;
1595 new->next = NULL;
1597 if (current != NULL)
1599 new->next = current->next;
1600 current->next = new;
1602 else
1604 new->next = subset_list->head;
1605 subset_list->head = new;
1608 if (new->next == NULL)
1609 subset_list->tail = new;
1612 /* Get the default versions from the riscv_supported_*ext tables. */
1614 static void
1615 riscv_get_default_ext_version (enum riscv_spec_class *default_isa_spec,
1616 const char *name,
1617 int *major_version,
1618 int *minor_version)
1620 if (name == NULL
1621 || default_isa_spec == NULL
1622 || *default_isa_spec == ISA_SPEC_CLASS_NONE)
1623 return;
1625 struct riscv_supported_ext *table = NULL;
1626 enum riscv_prefix_ext_class class = riscv_get_prefix_class (name);
1627 switch (class)
1629 case RV_ISA_CLASS_ZXM: table = riscv_supported_std_zxm_ext; break;
1630 case RV_ISA_CLASS_Z: table = riscv_supported_std_z_ext; break;
1631 case RV_ISA_CLASS_S: table = riscv_supported_std_s_ext; break;
1632 case RV_ISA_CLASS_X: table = riscv_supported_vendor_x_ext; break;
1633 default:
1634 table = riscv_supported_std_ext;
1637 int i = 0;
1638 while (table != NULL && table[i].name != NULL)
1640 if (strcmp (table[i].name, name) == 0
1641 && (table[i].isa_spec_class == ISA_SPEC_CLASS_DRAFT
1642 || table[i].isa_spec_class == *default_isa_spec))
1644 *major_version = table[i].major_version;
1645 *minor_version = table[i].minor_version;
1646 return;
1648 i++;
1652 /* Find the default versions for the extension before adding them to
1653 the subset list, if their versions are RISCV_UNKNOWN_VERSION.
1654 Afterwards, report errors if we can not find their default versions. */
1656 static void
1657 riscv_parse_add_subset (riscv_parse_subset_t *rps,
1658 const char *subset,
1659 int major,
1660 int minor,
1661 bool implicit)
1663 int major_version = major;
1664 int minor_version = minor;
1666 if (major_version == RISCV_UNKNOWN_VERSION
1667 || minor_version == RISCV_UNKNOWN_VERSION)
1668 riscv_get_default_ext_version (rps->isa_spec, subset,
1669 &major_version, &minor_version);
1671 /* We don't care the versions of the implicit extensions. */
1672 if (!implicit
1673 && (major_version == RISCV_UNKNOWN_VERSION
1674 || minor_version == RISCV_UNKNOWN_VERSION))
1676 if (subset[0] == 'x')
1677 rps->error_handler
1678 (_("x ISA extension `%s' must be set with the versions"),
1679 subset);
1680 /* Allow old ISA spec can recognize zicsr and zifencei. */
1681 else if (strcmp (subset, "zicsr") != 0
1682 && strcmp (subset, "zifencei") != 0)
1683 rps->error_handler
1684 (_("cannot find default versions of the ISA extension `%s'"),
1685 subset);
1686 return;
1689 riscv_add_subset (rps->subset_list, subset,
1690 major_version, minor_version);
1693 /* Release subset list. */
1695 void
1696 riscv_release_subset_list (riscv_subset_list_t *subset_list)
1698 while (subset_list->head != NULL)
1700 riscv_subset_t *next = subset_list->head->next;
1701 free ((void *)subset_list->head->name);
1702 free (subset_list->head);
1703 subset_list->head = next;
1706 subset_list->tail = NULL;
1708 if (subset_list->arch_str != NULL)
1710 free ((void*) subset_list->arch_str);
1711 subset_list->arch_str = NULL;
1715 /* Parsing extension version.
1717 Return Value:
1718 Points to the end of version
1720 Arguments:
1721 `p`: Curent parsing position.
1722 `major_version`: Parsed major version.
1723 `minor_version`: Parsed minor version. */
1725 static const char *
1726 riscv_parsing_subset_version (const char *p,
1727 int *major_version,
1728 int *minor_version)
1730 bool major_p = true;
1731 int version = 0;
1732 char np;
1734 *major_version = 0;
1735 *minor_version = 0;
1736 for (; *p; ++p)
1738 if (*p == 'p')
1740 np = *(p + 1);
1742 /* Might be beginning of `p` extension. */
1743 if (!ISDIGIT (np))
1744 break;
1746 *major_version = version;
1747 major_p = false;
1748 version = 0;
1750 else if (ISDIGIT (*p))
1751 version = (version * 10) + (*p - '0');
1752 else
1753 break;
1756 if (major_p)
1757 *major_version = version;
1758 else
1759 *minor_version = version;
1761 /* We can not find any version in string. */
1762 if (*major_version == 0 && *minor_version == 0)
1764 *major_version = RISCV_UNKNOWN_VERSION;
1765 *minor_version = RISCV_UNKNOWN_VERSION;
1768 return p;
1771 /* Parsing function for both standard and prefixed extensions.
1773 Return Value:
1774 Points to the end of extensions.
1776 Arguments:
1777 `rps`: Hooks and status for parsing extensions.
1778 `arch`: Full ISA string.
1779 `p`: Curent parsing position. */
1781 static const char *
1782 riscv_parse_extensions (riscv_parse_subset_t *rps,
1783 const char *arch,
1784 const char *p)
1786 /* First letter must start with i, e or g. */
1787 if (*p != 'e' && *p != 'i' && *p != 'g')
1789 rps->error_handler
1790 (_("%s: first ISA extension must be `e', `i' or `g'"),
1791 arch);
1792 return NULL;
1795 while (*p != '\0')
1797 if (*p == '_')
1799 p++;
1800 continue;
1803 char *subset = xstrdup (p);
1804 char *q = subset; /* Start of version. */
1805 const char *end_of_version;
1806 bool implicit = false;
1808 enum riscv_prefix_ext_class class = riscv_get_prefix_class (p);
1809 if (class == RV_ISA_CLASS_SINGLE)
1811 if (riscv_ext_order[(*subset - 'a')] == 0)
1813 rps->error_handler
1814 (_("%s: unknown standard ISA extension or prefix class `%c'"),
1815 arch, *subset);
1816 free (subset);
1817 return NULL;
1819 q++;
1821 else
1823 /* Extract the whole prefixed extension by '_'. */
1824 while (*++q != '\0' && *q != '_')
1826 /* Look forward to the first letter which is not <major>p<minor>. */
1827 bool find_any_version = false;
1828 bool find_minor_version = false;
1829 while (1)
1831 q--;
1832 if (ISDIGIT (*q))
1833 find_any_version = true;
1834 else if (find_any_version
1835 && !find_minor_version
1836 && *q == 'p'
1837 && ISDIGIT (*(q - 1)))
1838 find_minor_version = true;
1839 else
1840 break;
1842 q++;
1844 /* Check if the end of extension is 'p' or not. If yes, then
1845 the second letter from the end cannot be number. */
1846 if (*(q - 1) == 'p' && ISDIGIT (*(q - 2)))
1848 *q = '\0';
1849 rps->error_handler
1850 (_("%s: invalid prefixed ISA extension `%s' ends with <number>p"),
1851 arch, subset);
1852 free (subset);
1853 return NULL;
1857 int major_version = RISCV_UNKNOWN_VERSION;
1858 int minor_version = RISCV_UNKNOWN_VERSION;
1859 end_of_version =
1860 riscv_parsing_subset_version (q, &major_version, &minor_version);
1861 *q = '\0';
1862 if (end_of_version == NULL)
1864 free (subset);
1865 return NULL;
1868 /* Check if the prefixed extension name is well-formed. */
1869 if (class != RV_ISA_CLASS_SINGLE
1870 && rps->check_unknown_prefixed_ext
1871 && !riscv_recognized_prefixed_ext (subset))
1873 rps->error_handler
1874 (_("%s: unknown prefixed ISA extension `%s'"),
1875 arch, subset);
1876 free (subset);
1877 return NULL;
1880 /* Added g as an implicit extension. */
1881 if (class == RV_ISA_CLASS_SINGLE
1882 && strcmp (subset, "g") == 0)
1884 implicit = true;
1885 major_version = RISCV_UNKNOWN_VERSION;
1886 minor_version = RISCV_UNKNOWN_VERSION;
1888 riscv_parse_add_subset (rps, subset,
1889 major_version,
1890 minor_version, implicit);
1891 p += end_of_version - subset;
1892 free (subset);
1894 if (class != RV_ISA_CLASS_SINGLE
1895 && *p != '\0' && *p != '_')
1897 rps->error_handler
1898 (_("%s: prefixed ISA extension must separate with _"),
1899 arch);
1900 return NULL;
1904 return p;
1907 /* Add the implicit extensions. */
1909 static void
1910 riscv_parse_add_implicit_subsets (riscv_parse_subset_t *rps)
1912 struct riscv_implicit_subset *t = riscv_implicit_subsets;
1913 bool finished = false;
1914 while (!finished)
1916 finished = true;
1917 for (; t->subset_name; t++)
1919 riscv_subset_t *subset = NULL;
1920 riscv_subset_t *implicit_subset = NULL;
1921 if (riscv_lookup_subset (rps->subset_list, t->subset_name, &subset)
1922 && !riscv_lookup_subset (rps->subset_list, t->implicit_name,
1923 &implicit_subset)
1924 && t->check_func (t->implicit_name, subset))
1926 riscv_parse_add_subset (rps, t->implicit_name,
1927 RISCV_UNKNOWN_VERSION,
1928 RISCV_UNKNOWN_VERSION, true);
1930 /* Restart the loop and pick up any new implications. */
1931 finished = false;
1932 t = riscv_implicit_subsets;
1933 break;
1939 /* Check extensions conflicts. */
1941 static bool
1942 riscv_parse_check_conflicts (riscv_parse_subset_t *rps)
1944 riscv_subset_t *subset = NULL;
1945 int xlen = *rps->xlen;
1946 bool no_conflict = true;
1948 if (riscv_lookup_subset (rps->subset_list, "e", &subset)
1949 && xlen > 32)
1951 rps->error_handler
1952 (_("rv%d does not support the `e' extension"), xlen);
1953 no_conflict = false;
1955 if (riscv_subset_supports (rps, "e")
1956 && riscv_subset_supports (rps, "h"))
1958 rps->error_handler
1959 (_("rv%de does not support the `h' extension"), xlen);
1960 no_conflict = false;
1962 if (riscv_lookup_subset (rps->subset_list, "q", &subset)
1963 && (subset->major_version < 2 || (subset->major_version == 2
1964 && subset->minor_version < 2))
1965 && xlen < 64)
1967 rps->error_handler (_("rv%d does not support the `q' extension"), xlen);
1968 no_conflict = false;
1970 if (riscv_lookup_subset (rps->subset_list, "zcf", &subset)
1971 && xlen > 32)
1973 rps->error_handler
1974 (_("rv%d does not support the `zcf' extension"), xlen);
1975 no_conflict = false;
1977 if (riscv_lookup_subset (rps->subset_list, "zfinx", &subset)
1978 && riscv_lookup_subset (rps->subset_list, "f", &subset))
1980 rps->error_handler
1981 (_("`zfinx' is conflict with the `f/d/q/zfh/zfhmin' extension"));
1982 no_conflict = false;
1985 bool support_zve = false;
1986 bool support_zvl = false;
1987 riscv_subset_t *s = rps->subset_list->head;
1988 for (; s != NULL; s = s->next)
1990 if (!support_zve
1991 && strncmp (s->name, "zve", 3) == 0)
1992 support_zve = true;
1993 if (!support_zvl
1994 && strncmp (s->name, "zvl", 3) == 0)
1995 support_zvl = true;
1996 if (support_zve && support_zvl)
1997 break;
1999 if (support_zvl && !support_zve)
2001 rps->error_handler
2002 (_("zvl*b extensions need to enable either `v' or `zve' extension"));
2003 no_conflict = false;
2006 return no_conflict;
2009 /* Set the default subset list according to the default_enable field
2010 of riscv_supported_*ext tables. */
2012 static void
2013 riscv_set_default_arch (riscv_parse_subset_t *rps)
2015 unsigned long enable = EXT_DEFAULT;
2016 int i, j;
2017 for (i = 0; riscv_all_supported_ext[i] != NULL; i++)
2019 const struct riscv_supported_ext *table = riscv_all_supported_ext[i];
2020 for (j = 0; table[j].name != NULL; j++)
2022 bool implicit = false;
2023 if (strcmp (table[j].name, "g") == 0)
2024 implicit = true;
2025 if (table[j].default_enable & enable)
2026 riscv_parse_add_subset (rps, table[j].name,
2027 RISCV_UNKNOWN_VERSION,
2028 RISCV_UNKNOWN_VERSION, implicit);
2033 /* Function for parsing ISA string.
2035 Return Value:
2036 Return TRUE on success.
2038 Arguments:
2039 `rps`: Hooks and status for parsing extensions.
2040 `arch`: Full ISA string. */
2042 bool
2043 riscv_parse_subset (riscv_parse_subset_t *rps,
2044 const char *arch)
2046 const char *p;
2048 /* Init the riscv_ext_order array to compare the order of extensions
2049 quickly. */
2050 riscv_init_ext_order ();
2052 if (arch == NULL)
2054 riscv_set_default_arch (rps);
2055 riscv_parse_add_implicit_subsets (rps);
2056 return riscv_parse_check_conflicts (rps);
2059 for (p = arch; *p != '\0'; p++)
2061 if (ISUPPER (*p))
2063 rps->error_handler
2064 (_("%s: ISA string cannot contain uppercase letters"),
2065 arch);
2066 return false;
2070 p = arch;
2071 if (startswith (p, "rv32"))
2073 *rps->xlen = 32;
2074 p += 4;
2076 else if (startswith (p, "rv64"))
2078 *rps->xlen = 64;
2079 p += 4;
2081 else
2083 /* ISA string shouldn't be NULL or empty here. For linker,
2084 it might be empty when we failed to merge the ISA string
2085 in the riscv_merge_attributes. For assembler, we might
2086 give an empty string by .attribute arch, "" or -march=.
2087 However, We have already issued the correct error message
2088 in another side, so do not issue this error when the ISA
2089 string is empty. */
2090 if (strlen (arch))
2091 rps->error_handler (
2092 _("%s: ISA string must begin with rv32 or rv64"),
2093 arch);
2094 return false;
2097 /* Parse single standard and prefixed extensions. */
2098 if (riscv_parse_extensions (rps, arch, p) == NULL)
2099 return false;
2101 /* Finally add implicit extensions according to the current
2102 extensions. */
2103 riscv_parse_add_implicit_subsets (rps);
2105 /* Check the conflicts. */
2106 return riscv_parse_check_conflicts (rps);
2109 /* Return the number of digits for the input. */
2111 size_t
2112 riscv_estimate_digit (unsigned num)
2114 size_t digit = 0;
2115 if (num == 0)
2116 return 1;
2118 for (digit = 0; num ; num /= 10)
2119 digit++;
2121 return digit;
2124 /* Auxiliary function to estimate string length of subset list. */
2126 static size_t
2127 riscv_estimate_arch_strlen1 (const riscv_subset_t *subset)
2129 if (subset == NULL)
2130 return 6; /* For rv32/rv64/rv128 and string terminator. */
2132 return riscv_estimate_arch_strlen1 (subset->next)
2133 + strlen (subset->name)
2134 + riscv_estimate_digit (subset->major_version)
2135 + 1 /* For version seperator 'p'. */
2136 + riscv_estimate_digit (subset->minor_version)
2137 + 1 /* For underscore. */;
2140 /* Estimate the string length of this subset list. */
2142 static size_t
2143 riscv_estimate_arch_strlen (const riscv_subset_list_t *subset_list)
2145 return riscv_estimate_arch_strlen1 (subset_list->head);
2148 /* Auxiliary function to convert subset info to string. */
2150 static void
2151 riscv_arch_str1 (riscv_subset_t *subset,
2152 char *attr_str, char *buf, size_t bufsz)
2154 const char *underline = "_";
2155 riscv_subset_t *subset_t = subset;
2157 if (subset_t == NULL)
2158 return;
2160 /* No underline between rvXX and i/e. */
2161 if ((strcasecmp (subset_t->name, "i") == 0)
2162 || (strcasecmp (subset_t->name, "e") == 0))
2163 underline = "";
2165 snprintf (buf, bufsz, "%s%s%dp%d",
2166 underline,
2167 subset_t->name,
2168 subset_t->major_version,
2169 subset_t->minor_version);
2171 strncat (attr_str, buf, bufsz);
2173 /* Skip 'i' extension after 'e', or skip extensions which
2174 versions are unknown. */
2175 while (subset_t->next
2176 && ((strcmp (subset_t->name, "e") == 0
2177 && strcmp (subset_t->next->name, "i") == 0)
2178 || subset_t->next->major_version == RISCV_UNKNOWN_VERSION
2179 || subset_t->next->minor_version == RISCV_UNKNOWN_VERSION))
2180 subset_t = subset_t->next;
2182 riscv_arch_str1 (subset_t->next, attr_str, buf, bufsz);
2185 /* Convert subset information into string with explicit versions. */
2187 char *
2188 riscv_arch_str (unsigned xlen, const riscv_subset_list_t *subset)
2190 size_t arch_str_len = riscv_estimate_arch_strlen (subset);
2191 char *attr_str = xmalloc (arch_str_len);
2192 char *buf = xmalloc (arch_str_len);
2194 snprintf (attr_str, arch_str_len, "rv%u", xlen);
2196 riscv_arch_str1 (subset->head, attr_str, buf, arch_str_len);
2197 free (buf);
2199 return attr_str;
2202 /* Copy the subset in the subset list. */
2204 static struct riscv_subset_t *
2205 riscv_copy_subset (riscv_subset_list_t *subset_list,
2206 riscv_subset_t *subset)
2208 if (subset == NULL)
2209 return NULL;
2211 riscv_subset_t *new = xmalloc (sizeof *new);
2212 new->name = xstrdup (subset->name);
2213 new->major_version = subset->major_version;
2214 new->minor_version = subset->minor_version;
2215 new->next = riscv_copy_subset (subset_list, subset->next);
2217 if (subset->next == NULL)
2218 subset_list->tail = new;
2220 return new;
2223 /* Copy the subset list. */
2225 riscv_subset_list_t *
2226 riscv_copy_subset_list (riscv_subset_list_t *subset_list)
2228 riscv_subset_list_t *new = xmalloc (sizeof *new);
2229 new->head = riscv_copy_subset (new, subset_list->head);
2230 new->arch_str = strdup (subset_list->arch_str);
2231 return new;
2234 /* Remove the SUBSET from the subset list. */
2236 static void
2237 riscv_remove_subset (riscv_subset_list_t *subset_list,
2238 const char *subset)
2240 riscv_subset_t *current = subset_list->head;
2241 riscv_subset_t *pre = NULL;
2242 for (; current != NULL; pre = current, current = current->next)
2244 if (strcmp (current->name, subset) == 0)
2246 if (pre == NULL)
2247 subset_list->head = current->next;
2248 else
2249 pre->next = current->next;
2250 if (current->next == NULL)
2251 subset_list->tail = pre;
2252 free ((void *) current->name);
2253 free (current);
2254 break;
2259 /* Add/Remove an extension to/from the subset list. This is used for
2260 the .option rvc or norvc, and .option arch directives. */
2262 bool
2263 riscv_update_subset (riscv_parse_subset_t *rps,
2264 const char *str)
2266 const char *p = str;
2270 int major_version = RISCV_UNKNOWN_VERSION;
2271 int minor_version = RISCV_UNKNOWN_VERSION;
2273 bool removed = false;
2274 switch (*p)
2276 case '+': removed = false; break;
2277 case '-': removed = true; break;
2278 default:
2279 riscv_release_subset_list (rps->subset_list);
2280 return riscv_parse_subset (rps, p);
2282 ++p;
2284 char *subset = xstrdup (p);
2285 char *q = subset;
2286 const char *end_of_version;
2287 /* Extract the whole prefixed extension by ','. */
2288 while (*q != '\0' && *q != ',')
2289 q++;
2291 /* Look forward to the first letter which is not <major>p<minor>. */
2292 bool find_any_version = false;
2293 bool find_minor_version = false;
2294 size_t len = q - subset;
2295 size_t i;
2296 for (i = len; i > 0; i--)
2298 q--;
2299 if (ISDIGIT (*q))
2300 find_any_version = true;
2301 else if (find_any_version
2302 && !find_minor_version
2303 && *q == 'p'
2304 && ISDIGIT (*(q - 1)))
2305 find_minor_version = true;
2306 else
2307 break;
2309 if (len > 0)
2310 q++;
2312 /* Check if the end of extension is 'p' or not. If yes, then
2313 the second letter from the end cannot be number. */
2314 if (len > 1 && *(q - 1) == 'p' && ISDIGIT (*(q - 2)))
2316 *q = '\0';
2317 rps->error_handler
2318 (_("invalid ISA extension ends with <number>p "
2319 "in .option arch `%s'"), str);
2320 free (subset);
2321 return false;
2324 end_of_version =
2325 riscv_parsing_subset_version (q, &major_version, &minor_version);
2326 *q = '\0';
2327 if (end_of_version == NULL)
2329 free (subset);
2330 return false;
2333 if (strlen (subset) == 0
2334 || (strlen (subset) == 1
2335 && riscv_ext_order[(*subset - 'a')] == 0)
2336 || (strlen (subset) > 1
2337 && rps->check_unknown_prefixed_ext
2338 && !riscv_recognized_prefixed_ext (subset)))
2340 rps->error_handler
2341 (_("unknown ISA extension `%s' in .option arch `%s'"),
2342 subset, str);
2343 free (subset);
2344 return false;
2347 if (strcmp (subset, "i") == 0
2348 || strcmp (subset, "e") == 0
2349 || strcmp (subset, "g") == 0)
2351 rps->error_handler
2352 (_("cannot + or - base extension `%s' in .option "
2353 "arch `%s'"), subset, str);
2354 free (subset);
2355 return false;
2358 if (removed)
2359 riscv_remove_subset (rps->subset_list, subset);
2360 else
2361 riscv_parse_add_subset (rps, subset, major_version, minor_version, true);
2362 p += end_of_version - subset;
2363 free (subset);
2365 while (*p++ == ',');
2367 riscv_parse_add_implicit_subsets (rps);
2368 return riscv_parse_check_conflicts (rps);
2371 /* Check if the FEATURE subset is supported or not in the subset list.
2372 Return true if it is supported; Otherwise, return false. */
2374 bool
2375 riscv_subset_supports (riscv_parse_subset_t *rps,
2376 const char *feature)
2378 struct riscv_subset_t *subset;
2379 return riscv_lookup_subset (rps->subset_list, feature, &subset);
2382 /* Each instuction is belonged to an instruction class INSN_CLASS_*.
2383 Call riscv_subset_supports to make sure if the instuction is valid. */
2385 bool
2386 riscv_multi_subset_supports (riscv_parse_subset_t *rps,
2387 enum riscv_insn_class insn_class)
2389 switch (insn_class)
2391 case INSN_CLASS_I:
2392 return riscv_subset_supports (rps, "i");
2393 case INSN_CLASS_ZICBOM:
2394 return riscv_subset_supports (rps, "zicbom");
2395 case INSN_CLASS_ZICBOP:
2396 return riscv_subset_supports (rps, "zicbop");
2397 case INSN_CLASS_ZICBOZ:
2398 return riscv_subset_supports (rps, "zicboz");
2399 case INSN_CLASS_ZICOND:
2400 return riscv_subset_supports (rps, "zicond");
2401 case INSN_CLASS_ZICSR:
2402 return riscv_subset_supports (rps, "zicsr");
2403 case INSN_CLASS_ZIFENCEI:
2404 return riscv_subset_supports (rps, "zifencei");
2405 case INSN_CLASS_ZIHINTNTL:
2406 return riscv_subset_supports (rps, "zihintntl");
2407 case INSN_CLASS_ZIHINTNTL_AND_C:
2408 return (riscv_subset_supports (rps, "zihintntl")
2409 && (riscv_subset_supports (rps, "c")
2410 || riscv_subset_supports (rps, "zca")));
2411 case INSN_CLASS_ZIHINTPAUSE:
2412 return riscv_subset_supports (rps, "zihintpause");
2413 case INSN_CLASS_M:
2414 return riscv_subset_supports (rps, "m");
2415 case INSN_CLASS_ZMMUL:
2416 return riscv_subset_supports (rps, "zmmul");
2417 case INSN_CLASS_A:
2418 return riscv_subset_supports (rps, "a");
2419 case INSN_CLASS_ZAWRS:
2420 return riscv_subset_supports (rps, "zawrs");
2421 case INSN_CLASS_F:
2422 return riscv_subset_supports (rps, "f");
2423 case INSN_CLASS_D:
2424 return riscv_subset_supports (rps, "d");
2425 case INSN_CLASS_Q:
2426 return riscv_subset_supports (rps, "q");
2427 case INSN_CLASS_C:
2428 return (riscv_subset_supports (rps, "c")
2429 || riscv_subset_supports (rps, "zca"));
2430 case INSN_CLASS_F_AND_C:
2431 return (riscv_subset_supports (rps, "f")
2432 && (riscv_subset_supports (rps, "c")
2433 || riscv_subset_supports (rps, "zcf")));
2434 case INSN_CLASS_D_AND_C:
2435 return (riscv_subset_supports (rps, "d")
2436 && (riscv_subset_supports (rps, "c")
2437 || riscv_subset_supports (rps, "zcd")));
2438 case INSN_CLASS_F_INX:
2439 return (riscv_subset_supports (rps, "f")
2440 || riscv_subset_supports (rps, "zfinx"));
2441 case INSN_CLASS_D_INX:
2442 return (riscv_subset_supports (rps, "d")
2443 || riscv_subset_supports (rps, "zdinx"));
2444 case INSN_CLASS_Q_INX:
2445 return (riscv_subset_supports (rps, "q")
2446 || riscv_subset_supports (rps, "zqinx"));
2447 case INSN_CLASS_ZFH_INX:
2448 return (riscv_subset_supports (rps, "zfh")
2449 || riscv_subset_supports (rps, "zhinx"));
2450 case INSN_CLASS_ZFHMIN:
2451 return riscv_subset_supports (rps, "zfhmin");
2452 case INSN_CLASS_ZFHMIN_INX:
2453 return (riscv_subset_supports (rps, "zfhmin")
2454 || riscv_subset_supports (rps, "zhinxmin"));
2455 case INSN_CLASS_ZFHMIN_AND_D_INX:
2456 return ((riscv_subset_supports (rps, "zfhmin")
2457 && riscv_subset_supports (rps, "d"))
2458 || (riscv_subset_supports (rps, "zhinxmin")
2459 && riscv_subset_supports (rps, "zdinx")));
2460 case INSN_CLASS_ZFHMIN_AND_Q_INX:
2461 return ((riscv_subset_supports (rps, "zfhmin")
2462 && riscv_subset_supports (rps, "q"))
2463 || (riscv_subset_supports (rps, "zhinxmin")
2464 && riscv_subset_supports (rps, "zqinx")));
2465 case INSN_CLASS_ZFA:
2466 return riscv_subset_supports (rps, "zfa");
2467 case INSN_CLASS_D_AND_ZFA:
2468 return riscv_subset_supports (rps, "d")
2469 && riscv_subset_supports (rps, "zfa");
2470 case INSN_CLASS_Q_AND_ZFA:
2471 return riscv_subset_supports (rps, "q")
2472 && riscv_subset_supports (rps, "zfa");
2473 case INSN_CLASS_ZFH_AND_ZFA:
2474 return riscv_subset_supports (rps, "zfh")
2475 && riscv_subset_supports (rps, "zfa");
2476 case INSN_CLASS_ZFH_OR_ZVFH_AND_ZFA:
2477 return (riscv_subset_supports (rps, "zfh")
2478 || riscv_subset_supports (rps, "zvfh"))
2479 && riscv_subset_supports (rps, "zfa");
2480 case INSN_CLASS_ZBA:
2481 return riscv_subset_supports (rps, "zba");
2482 case INSN_CLASS_ZBB:
2483 return riscv_subset_supports (rps, "zbb");
2484 case INSN_CLASS_ZBC:
2485 return riscv_subset_supports (rps, "zbc");
2486 case INSN_CLASS_ZBS:
2487 return riscv_subset_supports (rps, "zbs");
2488 case INSN_CLASS_ZBKB:
2489 return riscv_subset_supports (rps, "zbkb");
2490 case INSN_CLASS_ZBKC:
2491 return riscv_subset_supports (rps, "zbkc");
2492 case INSN_CLASS_ZBKX:
2493 return riscv_subset_supports (rps, "zbkx");
2494 case INSN_CLASS_ZBB_OR_ZBKB:
2495 return (riscv_subset_supports (rps, "zbb")
2496 || riscv_subset_supports (rps, "zbkb"));
2497 case INSN_CLASS_ZBC_OR_ZBKC:
2498 return (riscv_subset_supports (rps, "zbc")
2499 || riscv_subset_supports (rps, "zbkc"));
2500 case INSN_CLASS_ZKND:
2501 return riscv_subset_supports (rps, "zknd");
2502 case INSN_CLASS_ZKNE:
2503 return riscv_subset_supports (rps, "zkne");
2504 case INSN_CLASS_ZKNH:
2505 return riscv_subset_supports (rps, "zknh");
2506 case INSN_CLASS_ZKND_OR_ZKNE:
2507 return (riscv_subset_supports (rps, "zknd")
2508 || riscv_subset_supports (rps, "zkne"));
2509 case INSN_CLASS_ZKSED:
2510 return riscv_subset_supports (rps, "zksed");
2511 case INSN_CLASS_ZKSH:
2512 return riscv_subset_supports (rps, "zksh");
2513 case INSN_CLASS_V:
2514 return (riscv_subset_supports (rps, "v")
2515 || riscv_subset_supports (rps, "zve64x")
2516 || riscv_subset_supports (rps, "zve32x"));
2517 case INSN_CLASS_ZVEF:
2518 return (riscv_subset_supports (rps, "v")
2519 || riscv_subset_supports (rps, "zve64d")
2520 || riscv_subset_supports (rps, "zve64f")
2521 || riscv_subset_supports (rps, "zve32f"));
2522 case INSN_CLASS_ZVBB:
2523 return riscv_subset_supports (rps, "zvbb");
2524 case INSN_CLASS_ZVBC:
2525 return riscv_subset_supports (rps, "zvbc");
2526 case INSN_CLASS_ZVKG:
2527 return riscv_subset_supports (rps, "zvkg");
2528 case INSN_CLASS_ZVKNED:
2529 return riscv_subset_supports (rps, "zvkned");
2530 case INSN_CLASS_ZVKNHA_OR_ZVKNHB:
2531 return (riscv_subset_supports (rps, "zvknha")
2532 || riscv_subset_supports (rps, "zvknhb"));
2533 case INSN_CLASS_ZVKSED:
2534 return riscv_subset_supports (rps, "zvksed");
2535 case INSN_CLASS_ZVKSH:
2536 return riscv_subset_supports (rps, "zvksh");
2537 case INSN_CLASS_ZCB:
2538 return riscv_subset_supports (rps, "zcb");
2539 case INSN_CLASS_ZCB_AND_ZBB:
2540 return (riscv_subset_supports (rps, "zcb")
2541 && riscv_subset_supports (rps, "zbb"));
2542 case INSN_CLASS_ZCB_AND_ZBA:
2543 return (riscv_subset_supports (rps, "zcb")
2544 && riscv_subset_supports (rps, "zba"));
2545 case INSN_CLASS_ZCB_AND_ZMMUL:
2546 return (riscv_subset_supports (rps, "zcb")
2547 && riscv_subset_supports (rps, "zmmul"));
2548 case INSN_CLASS_SVINVAL:
2549 return riscv_subset_supports (rps, "svinval");
2550 case INSN_CLASS_H:
2551 return riscv_subset_supports (rps, "h");
2552 case INSN_CLASS_XTHEADBA:
2553 return riscv_subset_supports (rps, "xtheadba");
2554 case INSN_CLASS_XTHEADBB:
2555 return riscv_subset_supports (rps, "xtheadbb");
2556 case INSN_CLASS_XTHEADBS:
2557 return riscv_subset_supports (rps, "xtheadbs");
2558 case INSN_CLASS_XTHEADCMO:
2559 return riscv_subset_supports (rps, "xtheadcmo");
2560 case INSN_CLASS_XTHEADCONDMOV:
2561 return riscv_subset_supports (rps, "xtheadcondmov");
2562 case INSN_CLASS_XTHEADFMEMIDX:
2563 return riscv_subset_supports (rps, "xtheadfmemidx");
2564 case INSN_CLASS_XTHEADFMV:
2565 return riscv_subset_supports (rps, "xtheadfmv");
2566 case INSN_CLASS_XTHEADINT:
2567 return riscv_subset_supports (rps, "xtheadint");
2568 case INSN_CLASS_XTHEADMAC:
2569 return riscv_subset_supports (rps, "xtheadmac");
2570 case INSN_CLASS_XTHEADMEMIDX:
2571 return riscv_subset_supports (rps, "xtheadmemidx");
2572 case INSN_CLASS_XTHEADMEMPAIR:
2573 return riscv_subset_supports (rps, "xtheadmempair");
2574 case INSN_CLASS_XTHEADSYNC:
2575 return riscv_subset_supports (rps, "xtheadsync");
2576 case INSN_CLASS_XVENTANACONDOPS:
2577 return riscv_subset_supports (rps, "xventanacondops");
2578 default:
2579 rps->error_handler
2580 (_("internal: unreachable INSN_CLASS_*"));
2581 return false;
2585 /* Each instuction is belonged to an instruction class INSN_CLASS_*.
2586 Call riscv_subset_supports_ext to determine the missing extension. */
2588 const char *
2589 riscv_multi_subset_supports_ext (riscv_parse_subset_t *rps,
2590 enum riscv_insn_class insn_class)
2592 switch (insn_class)
2594 case INSN_CLASS_I:
2595 return "i";
2596 case INSN_CLASS_ZICBOM:
2597 return "zicbom";
2598 case INSN_CLASS_ZICBOP:
2599 return "zicbop";
2600 case INSN_CLASS_ZICBOZ:
2601 return "zicboz";
2602 case INSN_CLASS_ZICOND:
2603 return "zicond";
2604 case INSN_CLASS_ZICSR:
2605 return "zicsr";
2606 case INSN_CLASS_ZIFENCEI:
2607 return "zifencei";
2608 case INSN_CLASS_ZIHINTNTL:
2609 return "zihintntl";
2610 case INSN_CLASS_ZIHINTNTL_AND_C:
2611 if (!riscv_subset_supports (rps, "zihintntl"))
2613 if (!riscv_subset_supports (rps, "c")
2614 && !riscv_subset_supports (rps, "zca"))
2615 return _("zihintntl' and `c', or `zihintntl' and `zca");
2616 else
2617 return "zihintntl";
2619 else
2620 return _("c' or `zca");
2621 case INSN_CLASS_ZIHINTPAUSE:
2622 return "zihintpause";
2623 case INSN_CLASS_M:
2624 return "m";
2625 case INSN_CLASS_ZMMUL:
2626 return _ ("m' or `zmmul");
2627 case INSN_CLASS_A:
2628 return "a";
2629 case INSN_CLASS_ZAWRS:
2630 return "zawrs";
2631 case INSN_CLASS_F:
2632 return "f";
2633 case INSN_CLASS_D:
2634 return "d";
2635 case INSN_CLASS_Q:
2636 return "q";
2637 case INSN_CLASS_C:
2638 return _("c' or `zca");
2639 case INSN_CLASS_F_AND_C:
2640 if (!riscv_subset_supports (rps, "f"))
2642 if (!riscv_subset_supports (rps, "c")
2643 && !riscv_subset_supports (rps, "zcf"))
2644 return _("f' and `c', or `f' and `zcf");
2645 else
2646 return "f";
2648 else
2649 return _("c' or `zcf");
2650 case INSN_CLASS_D_AND_C:
2651 if (!riscv_subset_supports (rps, "d"))
2653 if (!riscv_subset_supports (rps, "c")
2654 && !riscv_subset_supports (rps, "zcd"))
2655 return _("d' and `c', or `d' and `zcd");
2656 else
2657 return "d";
2659 else
2660 return _("c' or `zcd");
2661 case INSN_CLASS_F_INX:
2662 return _("f' or `zfinx");
2663 case INSN_CLASS_D_INX:
2664 return _("d' or `zdinx");
2665 case INSN_CLASS_Q_INX:
2666 return _("q' or `zqinx");
2667 case INSN_CLASS_ZFH_INX:
2668 return _("zfh' or `zhinx");
2669 case INSN_CLASS_ZFHMIN:
2670 return "zfhmin";
2671 case INSN_CLASS_ZFHMIN_INX:
2672 return _("zfhmin' or `zhinxmin");
2673 case INSN_CLASS_ZFHMIN_AND_D_INX:
2674 if (riscv_subset_supports (rps, "zfhmin"))
2675 return "d";
2676 else if (riscv_subset_supports (rps, "d"))
2677 return "zfhmin";
2678 else if (riscv_subset_supports (rps, "zhinxmin"))
2679 return "zdinx";
2680 else if (riscv_subset_supports (rps, "zdinx"))
2681 return "zhinxmin";
2682 else
2683 return _("zfhmin' and `d', or `zhinxmin' and `zdinx");
2684 case INSN_CLASS_ZFHMIN_AND_Q_INX:
2685 if (riscv_subset_supports (rps, "zfhmin"))
2686 return "q";
2687 else if (riscv_subset_supports (rps, "q"))
2688 return "zfhmin";
2689 else if (riscv_subset_supports (rps, "zhinxmin"))
2690 return "zqinx";
2691 else if (riscv_subset_supports (rps, "zqinx"))
2692 return "zhinxmin";
2693 else
2694 return _("zfhmin' and `q', or `zhinxmin' and `zqinx");
2695 case INSN_CLASS_ZFA:
2696 return "zfa";
2697 case INSN_CLASS_D_AND_ZFA:
2698 if (!riscv_subset_supports (rps, "d")
2699 && !riscv_subset_supports (rps, "zfa"))
2700 return _("d' and `zfa");
2701 else if (!riscv_subset_supports (rps, "d"))
2702 return "d";
2703 else
2704 return "zfa";
2705 case INSN_CLASS_Q_AND_ZFA:
2706 if (!riscv_subset_supports (rps, "q")
2707 && !riscv_subset_supports (rps, "zfa"))
2708 return _("q' and `zfa");
2709 else if (!riscv_subset_supports (rps, "q"))
2710 return "q";
2711 else
2712 return "zfa";
2713 case INSN_CLASS_ZFH_AND_ZFA:
2714 if (!riscv_subset_supports (rps, "zfh")
2715 && !riscv_subset_supports (rps, "zfa"))
2716 return _("zfh' and `zfa");
2717 else if (!riscv_subset_supports (rps, "zfh"))
2718 return "zfh";
2719 else
2720 return "zfa";
2721 case INSN_CLASS_ZFH_OR_ZVFH_AND_ZFA:
2722 if (!riscv_subset_supports (rps, "zfa"))
2724 if (!riscv_subset_supports (rps, "zfh")
2725 && !riscv_subset_supports (rps, "zvfh"))
2726 return _("zfh' and `zfa', or `zvfh' and `zfa");
2727 else
2728 return "zfa";
2730 else
2731 return _("zfh' or `zvfh");
2732 case INSN_CLASS_ZBA:
2733 return "zba";
2734 case INSN_CLASS_ZBB:
2735 return "zbb";
2736 case INSN_CLASS_ZBC:
2737 return "zbc";
2738 case INSN_CLASS_ZBS:
2739 return "zbs";
2740 case INSN_CLASS_ZBKB:
2741 return "zbkb";
2742 case INSN_CLASS_ZBKC:
2743 return "zbkc";
2744 case INSN_CLASS_ZBKX:
2745 return "zbkx";
2746 case INSN_CLASS_ZBB_OR_ZBKB:
2747 return _("zbb' or `zbkb");
2748 case INSN_CLASS_ZBC_OR_ZBKC:
2749 return _("zbc' or `zbkc");
2750 case INSN_CLASS_ZKND:
2751 return "zknd";
2752 case INSN_CLASS_ZKNE:
2753 return "zkne";
2754 case INSN_CLASS_ZKNH:
2755 return "zknh";
2756 case INSN_CLASS_ZKND_OR_ZKNE:
2757 return _("zknd' or `zkne");
2758 case INSN_CLASS_ZKSED:
2759 return "zksed";
2760 case INSN_CLASS_ZKSH:
2761 return "zksh";
2762 case INSN_CLASS_V:
2763 return _("v' or `zve64x' or `zve32x");
2764 case INSN_CLASS_ZVEF:
2765 return _("v' or `zve64d' or `zve64f' or `zve32f");
2766 case INSN_CLASS_ZVBB:
2767 return _("zvbb");
2768 case INSN_CLASS_ZVBC:
2769 return _("zvbc");
2770 case INSN_CLASS_ZVKG:
2771 return _("zvkg");
2772 case INSN_CLASS_ZVKNED:
2773 return _("zvkned");
2774 case INSN_CLASS_ZVKNHA_OR_ZVKNHB:
2775 return _("zvknha' or `zvknhb");
2776 case INSN_CLASS_ZVKSED:
2777 return _("zvksed");
2778 case INSN_CLASS_ZVKSH:
2779 return _("zvksh");
2780 case INSN_CLASS_ZCB:
2781 return "zcb";
2782 case INSN_CLASS_ZCB_AND_ZBA:
2783 return _("zcb' and `zba");
2784 case INSN_CLASS_ZCB_AND_ZBB:
2785 return _("zcb' and `zbb");
2786 case INSN_CLASS_ZCB_AND_ZMMUL:
2787 return _("zcb' and `zmmul', or `zcb' and `m");
2788 case INSN_CLASS_SVINVAL:
2789 return "svinval";
2790 case INSN_CLASS_H:
2791 return _("h");
2792 case INSN_CLASS_XTHEADBA:
2793 return "xtheadba";
2794 case INSN_CLASS_XTHEADBB:
2795 return "xtheadbb";
2796 case INSN_CLASS_XTHEADBS:
2797 return "xtheadbs";
2798 case INSN_CLASS_XTHEADCMO:
2799 return "xtheadcmo";
2800 case INSN_CLASS_XTHEADCONDMOV:
2801 return "xtheadcondmov";
2802 case INSN_CLASS_XTHEADFMEMIDX:
2803 return "xtheadfmemidx";
2804 case INSN_CLASS_XTHEADFMV:
2805 return "xtheadfmv";
2806 case INSN_CLASS_XTHEADINT:
2807 return "xtheadint";
2808 case INSN_CLASS_XTHEADMAC:
2809 return "xtheadmac";
2810 case INSN_CLASS_XTHEADMEMIDX:
2811 return "xtheadmemidx";
2812 case INSN_CLASS_XTHEADMEMPAIR:
2813 return "xtheadmempair";
2814 case INSN_CLASS_XTHEADSYNC:
2815 return "xtheadsync";
2816 default:
2817 rps->error_handler
2818 (_("internal: unreachable INSN_CLASS_*"));
2819 return NULL;