RISC-V: Allow nested implications for extensions
[binutils-gdb.git] / bfd / elfxx-riscv.c
1 /* RISC-V-specific support for ELF.
2 Copyright (C) 2011-2023 Free Software Foundation, Inc.
3
4 Contributed by Andrew Waterman (andrew@sifive.com).
5 Based on TILE-Gx and MIPS targets.
6
7 This file is part of BFD, the Binary File Descriptor library.
8
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 3 of the License, or
12 (at your option) any later version.
13
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
18
19 You should have received a copy of the GNU General Public License
20 along with this program; see the file COPYING3. If not,
21 see <http://www.gnu.org/licenses/>. */
22
23 #include "sysdep.h"
24 #include "bfd.h"
25 #include "libbfd.h"
26 #include "elf-bfd.h"
27 #include "elf/riscv.h"
28 #include "opcode/riscv.h"
29 #include "libiberty.h"
30 #include "elfxx-riscv.h"
31 #include "safe-ctype.h"
32
33 #define MINUS_ONE ((bfd_vma)0 - 1)
34
35 /* Special handler for ADD/SUB relocations that allows them to be filled out
36 both in the pre-linked and post-linked file. This is necessary to make
37 pre-linked debug info work, as due to linker relaxations we need to emit
38 relocations for the debug info. */
39 static bfd_reloc_status_type riscv_elf_add_sub_reloc
40 (bfd *, arelent *, asymbol *, void *, asection *, bfd *, char **);
41 static bfd_reloc_status_type riscv_elf_ignore_reloc
42 (bfd *, arelent *, asymbol *, void *, asection *, bfd *, char **);
43
44 /* The relocation table used for SHT_RELA sections. */
45
46 static reloc_howto_type howto_table[] =
47 {
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 */
62
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 */
77
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 */
92
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 */
107
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 */
121
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 */
135
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 */
150
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 */
164
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 */
178
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 */
192
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 */
206
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 */
220
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),
226
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 */
241
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 */
256
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 */
272
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 */
288
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 */
303
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 */
318
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 */
333
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 */
348
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 */
363
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 */
378
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 */
393
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 */
408
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 */
423
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 */
438
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 */
453
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 */
468
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 */
483
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 */
498
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 */
513
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 */
528
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 */
543
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 */
558
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 */
573
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 */
588
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 */
603
604 /* 41 and 42 are reserved. */
605 EMPTY_HOWTO (0),
606 EMPTY_HOWTO (0),
607
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 */
624
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 */
639
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 */
654
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 */
669
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 */
684
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 */
699
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 */
714
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 */
729
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 */
744
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 */
759
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 */
774
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 */
789
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 */
804
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 */
819
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 */
834
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 */
849
850 /* Reserved for R_RISCV_PLT32. */
851 EMPTY_HOWTO (59),
852
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 */
867
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 */
882 };
883
884 /* A mapping from BFD reloc types to RISC-V ELF reloc types. */
885 struct elf_reloc_map
886 {
887 bfd_reloc_code_real_type bfd_val;
888 enum elf_riscv_reloc_type elf_val;
889 };
890
891 static const struct elf_reloc_map riscv_reloc_map[] =
892 {
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 },
945 };
946
947 /* Given a BFD reloc type, return a howto structure. */
948
949 reloc_howto_type *
950 riscv_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED,
951 bfd_reloc_code_real_type code)
952 {
953 unsigned int i;
954
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];
958
959 bfd_set_error (bfd_error_bad_value);
960 return NULL;
961 }
962
963 reloc_howto_type *
964 riscv_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED, const char *r_name)
965 {
966 unsigned int i;
967
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];
971
972 return NULL;
973 }
974
975 reloc_howto_type *
976 riscv_elf_rtype_to_howto (bfd *abfd, unsigned int r_type)
977 {
978 if (r_type >= ARRAY_SIZE (howto_table))
979 {
980 (*_bfd_error_handler) (_("%pB: unsupported relocation type %#x"),
981 abfd, r_type);
982 bfd_set_error (bfd_error_bad_value);
983 return NULL;
984 }
985 return &howto_table[r_type];
986 }
987
988 /* Special_function of RISCV_ADD and RISCV_SUB relocations. */
989
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)
998 {
999 reloc_howto_type *howto = reloc_entry->howto;
1000 bfd_vma relocation;
1001
1002 if (output_bfd != NULL
1003 && (symbol->flags & BSF_SECTION_SYM) == 0
1004 && (!reloc_entry->howto->partial_inplace || reloc_entry->addend == 0))
1005 {
1006 reloc_entry->address += input_section->output_offset;
1007 return bfd_reloc_ok;
1008 }
1009
1010 if (output_bfd != NULL)
1011 return bfd_reloc_continue;
1012
1013 relocation = symbol->value + symbol->section->output_section->vma
1014 + symbol->section->output_offset + reloc_entry->addend;
1015
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;
1021
1022 bfd_vma old_value = bfd_get (howto->bitsize, abfd,
1023 data + reloc_entry->address);
1024
1025 switch (howto->type)
1026 {
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;
1044 }
1045 bfd_put (howto->bitsize, abfd, relocation, data + reloc_entry->address);
1046
1047 return bfd_reloc_ok;
1048 }
1049
1050 /* Special handler for relocations which don't have to be relocated.
1051 This function just simply return bfd_reloc_ok. */
1052
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)
1061 {
1062 if (output_bfd != NULL)
1063 reloc_entry->address += input_section->output_offset;
1064 return bfd_reloc_ok;
1065 }
1066
1067 /* Always add the IMPLICIT for the SUBSET. */
1068
1069 static bool
1070 check_implicit_always (const char *implicit ATTRIBUTE_UNUSED,
1071 riscv_subset_t *subset ATTRIBUTE_UNUSED)
1072 {
1073 return true;
1074 }
1075
1076 /* Add the IMPLICIT only when the version of SUBSET less than 2.1. */
1077
1078 static bool
1079 check_implicit_for_i (const char *implicit ATTRIBUTE_UNUSED,
1080 riscv_subset_t *subset)
1081 {
1082 return (subset->major_version < 2
1083 || (subset->major_version == 2
1084 && subset->minor_version < 1));
1085 }
1086
1087 /* Record all implicit information for the subsets. */
1088 struct riscv_implicit_subset
1089 {
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 *);
1094 };
1095 static struct riscv_implicit_subset riscv_implicit_subsets[] =
1096 {
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 {"zve64d", "d", check_implicit_always},
1114 {"zve64d", "zve64f", check_implicit_always},
1115 {"zve64f", "zve32f", check_implicit_always},
1116 {"zve64f", "zve64x", check_implicit_always},
1117 {"zve64f", "zvl64b", check_implicit_always},
1118 {"zve32f", "f", check_implicit_always},
1119 {"zve32f", "zvl32b", check_implicit_always},
1120 {"zve32f", "zve32x", check_implicit_always},
1121 {"zve64x", "zve32x", check_implicit_always},
1122 {"zve64x", "zvl64b", check_implicit_always},
1123 {"zve32x", "zvl32b", check_implicit_always},
1124 {"zvl65536b", "zvl32768b", check_implicit_always},
1125 {"zvl32768b", "zvl16384b", check_implicit_always},
1126 {"zvl16384b", "zvl8192b", check_implicit_always},
1127 {"zvl8192b", "zvl4096b", check_implicit_always},
1128 {"zvl4096b", "zvl2048b", check_implicit_always},
1129 {"zvl2048b", "zvl1024b", check_implicit_always},
1130 {"zvl1024b", "zvl512b", check_implicit_always},
1131 {"zvl512b", "zvl256b", check_implicit_always},
1132 {"zvl256b", "zvl128b", check_implicit_always},
1133 {"zvl128b", "zvl64b", check_implicit_always},
1134 {"zvl64b", "zvl32b", check_implicit_always},
1135 {"zfa", "f", check_implicit_always},
1136 {"d", "f", check_implicit_always},
1137 {"zfh", "zfhmin", check_implicit_always},
1138 {"zfhmin", "f", check_implicit_always},
1139 {"f", "zicsr", check_implicit_always},
1140 {"zqinx", "zdinx", check_implicit_always},
1141 {"zdinx", "zfinx", check_implicit_always},
1142 {"zhinx", "zhinxmin", check_implicit_always},
1143 {"zhinxmin", "zfinx", check_implicit_always},
1144 {"zfinx", "zicsr", check_implicit_always},
1145 {"zk", "zkn", check_implicit_always},
1146 {"zk", "zkr", check_implicit_always},
1147 {"zk", "zkt", check_implicit_always},
1148 {"zkn", "zbkb", check_implicit_always},
1149 {"zkn", "zbkc", check_implicit_always},
1150 {"zkn", "zbkx", check_implicit_always},
1151 {"zkn", "zkne", check_implicit_always},
1152 {"zkn", "zknd", check_implicit_always},
1153 {"zkn", "zknh", check_implicit_always},
1154 {"zks", "zbkb", check_implicit_always},
1155 {"zks", "zbkc", check_implicit_always},
1156 {"zks", "zbkx", check_implicit_always},
1157 {"zks", "zksed", check_implicit_always},
1158 {"zks", "zksh", check_implicit_always},
1159 {"zvkn", "zvkned", check_implicit_always},
1160 {"zvkn", "zvknha", check_implicit_always},
1161 {"zvkn", "zvknhb", check_implicit_always},
1162 {"zvkn", "zvbb", check_implicit_always},
1163 {"smaia", "ssaia", check_implicit_always},
1164 {"smstateen", "ssstateen", check_implicit_always},
1165 {"smepmp", "zicsr", check_implicit_always},
1166 {"ssaia", "zicsr", check_implicit_always},
1167 {"sscofpmf", "zicsr", check_implicit_always},
1168 {"ssstateen", "zicsr", check_implicit_always},
1169 {"sstc", "zicsr", check_implicit_always},
1170 {NULL, NULL, NULL}
1171 };
1172
1173 /* For default_enable field, decide if the extension should
1174 be enbaled by default. */
1175
1176 #define EXT_DEFAULT 0x1
1177
1178 /* List all extensions that binutils should know about. */
1179
1180 struct riscv_supported_ext
1181 {
1182 const char *name;
1183 enum riscv_spec_class isa_spec_class;
1184 int major_version;
1185 int minor_version;
1186 unsigned long default_enable;
1187 };
1188
1189 /* The standard extensions must be added in canonical order. */
1190
1191 static struct riscv_supported_ext riscv_supported_std_ext[] =
1192 {
1193 {"e", ISA_SPEC_CLASS_20191213, 1, 9, 0 },
1194 {"e", ISA_SPEC_CLASS_20190608, 1, 9, 0 },
1195 {"e", ISA_SPEC_CLASS_2P2, 1, 9, 0 },
1196 {"i", ISA_SPEC_CLASS_20191213, 2, 1, 0 },
1197 {"i", ISA_SPEC_CLASS_20190608, 2, 1, 0 },
1198 {"i", ISA_SPEC_CLASS_2P2, 2, 0, 0 },
1199 /* The g is a special case which we don't want to output it,
1200 but still need it when adding implicit extensions. */
1201 {"g", ISA_SPEC_CLASS_NONE, RISCV_UNKNOWN_VERSION, RISCV_UNKNOWN_VERSION, EXT_DEFAULT },
1202 {"m", ISA_SPEC_CLASS_20191213, 2, 0, 0 },
1203 {"m", ISA_SPEC_CLASS_20190608, 2, 0, 0 },
1204 {"m", ISA_SPEC_CLASS_2P2, 2, 0, 0 },
1205 {"a", ISA_SPEC_CLASS_20191213, 2, 1, 0 },
1206 {"a", ISA_SPEC_CLASS_20190608, 2, 0, 0 },
1207 {"a", ISA_SPEC_CLASS_2P2, 2, 0, 0 },
1208 {"f", ISA_SPEC_CLASS_20191213, 2, 2, 0 },
1209 {"f", ISA_SPEC_CLASS_20190608, 2, 2, 0 },
1210 {"f", ISA_SPEC_CLASS_2P2, 2, 0, 0 },
1211 {"d", ISA_SPEC_CLASS_20191213, 2, 2, 0 },
1212 {"d", ISA_SPEC_CLASS_20190608, 2, 2, 0 },
1213 {"d", ISA_SPEC_CLASS_2P2, 2, 0, 0 },
1214 {"q", ISA_SPEC_CLASS_20191213, 2, 2, 0 },
1215 {"q", ISA_SPEC_CLASS_20190608, 2, 2, 0 },
1216 {"q", ISA_SPEC_CLASS_2P2, 2, 0, 0 },
1217 {"c", ISA_SPEC_CLASS_20191213, 2, 0, 0 },
1218 {"c", ISA_SPEC_CLASS_20190608, 2, 0, 0 },
1219 {"c", ISA_SPEC_CLASS_2P2, 2, 0, 0 },
1220 {"v", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1221 {"h", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1222 {NULL, 0, 0, 0, 0}
1223 };
1224
1225 static struct riscv_supported_ext riscv_supported_std_z_ext[] =
1226 {
1227 {"zicbom", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1228 {"zicbop", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1229 {"zicboz", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1230 {"zicond", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1231 {"zicsr", ISA_SPEC_CLASS_20191213, 2, 0, 0 },
1232 {"zicsr", ISA_SPEC_CLASS_20190608, 2, 0, 0 },
1233 {"zifencei", ISA_SPEC_CLASS_20191213, 2, 0, 0 },
1234 {"zifencei", ISA_SPEC_CLASS_20190608, 2, 0, 0 },
1235 {"zihintpause", ISA_SPEC_CLASS_DRAFT, 2, 0, 0 },
1236 {"zmmul", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1237 {"zawrs", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1238 {"zfa", ISA_SPEC_CLASS_DRAFT, 0, 1, 0 },
1239 {"zfh", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1240 {"zfhmin", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1241 {"zfinx", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1242 {"zdinx", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1243 {"zqinx", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1244 {"zhinx", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1245 {"zhinxmin", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1246 {"zbb", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1247 {"zba", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1248 {"zbc", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1249 {"zbs", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1250 {"zbkb", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1251 {"zbkc", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1252 {"zbkx", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1253 {"zk", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1254 {"zkn", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1255 {"zknd", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1256 {"zkne", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1257 {"zknh", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1258 {"zkr", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1259 {"zks", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1260 {"zksed", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1261 {"zksh", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1262 {"zkt", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1263 {"zve32x", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1264 {"zve32f", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1265 {"zve32d", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1266 {"zve64x", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1267 {"zve64f", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1268 {"zve64d", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1269 {"zvbb", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1270 {"zvbc", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1271 {"zvkg", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1272 {"zvkn", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1273 {"zvkned", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1274 {"zvknha", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1275 {"zvknhb", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1276 {"zvksed", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1277 {"zvksh", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1278 {"zvl32b", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1279 {"zvl64b", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1280 {"zvl128b", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1281 {"zvl256b", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1282 {"zvl512b", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1283 {"zvl1024b", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1284 {"zvl2048b", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1285 {"zvl4096b", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1286 {"zvl8192b", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1287 {"zvl16384b", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1288 {"zvl32768b", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1289 {"zvl65536b", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1290 {"ztso", ISA_SPEC_CLASS_DRAFT, 0, 1, 0 },
1291 {NULL, 0, 0, 0, 0}
1292 };
1293
1294 static struct riscv_supported_ext riscv_supported_std_s_ext[] =
1295 {
1296 {"smaia", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1297 {"smepmp", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1298 {"smstateen", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1299 {"ssaia", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1300 {"sscofpmf", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1301 {"ssstateen", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1302 {"sstc", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1303 {"svinval", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1304 {"svnapot", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1305 {"svpbmt", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1306 {NULL, 0, 0, 0, 0}
1307 };
1308
1309 static struct riscv_supported_ext riscv_supported_std_zxm_ext[] =
1310 {
1311 {NULL, 0, 0, 0, 0}
1312 };
1313
1314 static struct riscv_supported_ext riscv_supported_vendor_x_ext[] =
1315 {
1316 {"xtheadba", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1317 {"xtheadbb", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1318 {"xtheadbs", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1319 {"xtheadcmo", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1320 {"xtheadcondmov", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1321 {"xtheadfmemidx", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1322 {"xtheadfmv", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1323 {"xtheadint", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1324 {"xtheadmac", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1325 {"xtheadmemidx", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1326 {"xtheadmempair", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1327 {"xtheadsync", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1328 /* XVentanaCondOps: https://github.com/ventanamicro/ventana-custom-extensions/releases/download/v1.0.0/ventana-custom-extensions-v1.0.0.pdf */
1329 {"xventanacondops", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1330 {NULL, 0, 0, 0, 0}
1331 };
1332
1333 const struct riscv_supported_ext *riscv_all_supported_ext[] =
1334 {
1335 riscv_supported_std_ext,
1336 riscv_supported_std_z_ext,
1337 riscv_supported_std_s_ext,
1338 riscv_supported_std_zxm_ext,
1339 riscv_supported_vendor_x_ext,
1340 NULL
1341 };
1342
1343 /* ISA extension prefixed name class. Must define them in parsing order. */
1344 enum riscv_prefix_ext_class
1345 {
1346 RV_ISA_CLASS_Z = 1,
1347 RV_ISA_CLASS_S,
1348 RV_ISA_CLASS_ZXM,
1349 RV_ISA_CLASS_X,
1350 RV_ISA_CLASS_SINGLE
1351 };
1352
1353 /* Record the strings of the prefixed extensions, and their corresponding
1354 classes. The more letters of the prefix string, the more forward it must
1355 be defined. Otherwise, the riscv_get_prefix_class will map it to the
1356 wrong classes. */
1357 struct riscv_parse_prefix_config
1358 {
1359 /* Class of the extension. */
1360 enum riscv_prefix_ext_class class;
1361
1362 /* Prefix string for error printing and internal parser usage. */
1363 const char *prefix;
1364 };
1365 static const struct riscv_parse_prefix_config parse_config[] =
1366 {
1367 {RV_ISA_CLASS_ZXM, "zxm"},
1368 {RV_ISA_CLASS_Z, "z"},
1369 {RV_ISA_CLASS_S, "s"},
1370 {RV_ISA_CLASS_X, "x"},
1371 {RV_ISA_CLASS_SINGLE, NULL}
1372 };
1373
1374 /* Get the prefixed name class for the extensions, the class also
1375 means the order of the prefixed extensions. */
1376
1377 static enum riscv_prefix_ext_class
1378 riscv_get_prefix_class (const char *arch)
1379 {
1380 int i = 0;
1381 while (parse_config[i].class != RV_ISA_CLASS_SINGLE)
1382 {
1383 if (strncmp (arch, parse_config[i].prefix,
1384 strlen (parse_config[i].prefix)) == 0)
1385 return parse_config[i].class;
1386 i++;
1387 }
1388 return RV_ISA_CLASS_SINGLE;
1389 }
1390
1391 /* Check KNOWN_EXTS to see if the EXT is supported. */
1392
1393 static bool
1394 riscv_known_prefixed_ext (const char *ext,
1395 struct riscv_supported_ext *known_exts)
1396 {
1397 size_t i;
1398 for (i = 0; known_exts[i].name != NULL; ++i)
1399 if (strcmp (ext, known_exts[i].name) == 0)
1400 return true;
1401 return false;
1402 }
1403
1404 /* Check whether the prefixed extension is recognized or not. Return
1405 true if recognized, otehrwise return false. */
1406
1407 static bool
1408 riscv_recognized_prefixed_ext (const char *ext)
1409 {
1410 enum riscv_prefix_ext_class class = riscv_get_prefix_class (ext);
1411 switch (class)
1412 {
1413 case RV_ISA_CLASS_Z:
1414 return riscv_known_prefixed_ext (ext, riscv_supported_std_z_ext);
1415 case RV_ISA_CLASS_ZXM:
1416 return riscv_known_prefixed_ext (ext, riscv_supported_std_zxm_ext);
1417 case RV_ISA_CLASS_S:
1418 return riscv_known_prefixed_ext (ext, riscv_supported_std_s_ext);
1419 case RV_ISA_CLASS_X:
1420 /* Only the single x is unrecognized. */
1421 if (strcmp (ext, "x") != 0)
1422 return true;
1423 default:
1424 break;
1425 }
1426 return false;
1427 }
1428
1429 /* Canonical order for single letter extensions. */
1430 static const char riscv_ext_canonical_order[] = "eigmafdqlcbkjtpvnh";
1431
1432 /* Array is used to compare the orders of standard extensions quickly. */
1433 static int riscv_ext_order[26] = {0};
1434
1435 /* Init the riscv_ext_order array. */
1436
1437 static void
1438 riscv_init_ext_order (void)
1439 {
1440 static bool inited = false;
1441 if (inited)
1442 return;
1443
1444 /* The orders of all standard extensions are positive. */
1445 int order = 1;
1446
1447 for (const char *ext = &riscv_ext_canonical_order[0]; *ext; ++ext)
1448 riscv_ext_order[(*ext - 'a')] = order++;
1449
1450 /* Some of the prefixed keyword are not single letter, so we set
1451 their prefixed orders in the riscv_compare_subsets directly,
1452 not through the riscv_ext_order. */
1453
1454 inited = true;
1455 }
1456
1457 /* Similar to the strcmp. It returns an integer less than, equal to,
1458 or greater than zero if `subset2` is found, respectively, to be less
1459 than, to match, or be greater than `subset1`.
1460
1461 The order values,
1462 Zero: Preserved keywords.
1463 Positive number: Standard extensions.
1464 Negative number: Prefixed keywords. */
1465
1466 int
1467 riscv_compare_subsets (const char *subset1, const char *subset2)
1468 {
1469 int order1 = riscv_ext_order[(*subset1 - 'a')];
1470 int order2 = riscv_ext_order[(*subset2 - 'a')];
1471
1472 /* Compare the standard extension first. */
1473 if (order1 > 0 && order2 > 0)
1474 return order1 - order2;
1475
1476 /* Set the prefixed orders to negative numbers. */
1477 enum riscv_prefix_ext_class class1 = riscv_get_prefix_class (subset1);
1478 enum riscv_prefix_ext_class class2 = riscv_get_prefix_class (subset2);
1479
1480 if (class1 != RV_ISA_CLASS_SINGLE)
1481 order1 = - (int) class1;
1482 if (class2 != RV_ISA_CLASS_SINGLE)
1483 order2 = - (int) class2;
1484
1485 if (order1 == order2)
1486 {
1487 /* Compare the standard addition z extensions. */
1488 if (class1 == RV_ISA_CLASS_Z)
1489 {
1490 order1 = riscv_ext_order[(*++subset1 - 'a')];
1491 order2 = riscv_ext_order[(*++subset2 - 'a')];
1492 if (order1 != order2)
1493 return order1 - order2;
1494 }
1495 return strcasecmp (++subset1, ++subset2);
1496 }
1497
1498 return order2 - order1;
1499 }
1500
1501 /* Find subset in the list. Return TRUE and set `current` to the subset
1502 if it is found. Otherwise, return FALSE and set `current` to the place
1503 where we should insert the subset. However, return FALSE with the NULL
1504 `current` means we should insert the subset at the head of subset list,
1505 if needed. */
1506
1507 bool
1508 riscv_lookup_subset (const riscv_subset_list_t *subset_list,
1509 const char *subset,
1510 riscv_subset_t **current)
1511 {
1512 riscv_subset_t *s, *pre_s = NULL;
1513
1514 /* If the subset is added in order, then just add it at the tail. */
1515 if (subset_list->tail != NULL
1516 && riscv_compare_subsets (subset_list->tail->name, subset) < 0)
1517 {
1518 *current = subset_list->tail;
1519 return false;
1520 }
1521
1522 for (s = subset_list->head;
1523 s != NULL;
1524 pre_s = s, s = s->next)
1525 {
1526 int cmp = riscv_compare_subsets (s->name, subset);
1527 if (cmp == 0)
1528 {
1529 *current = s;
1530 return true;
1531 }
1532 else if (cmp > 0)
1533 break;
1534 }
1535 *current = pre_s;
1536
1537 return false;
1538 }
1539
1540 /* Add the extension to the subset list. Search the
1541 list first, and then find the right place to add. */
1542
1543 void
1544 riscv_add_subset (riscv_subset_list_t *subset_list,
1545 const char *subset,
1546 int major,
1547 int minor)
1548 {
1549 riscv_subset_t *current, *new;
1550
1551 if (riscv_lookup_subset (subset_list, subset, &current))
1552 return;
1553
1554 new = xmalloc (sizeof *new);
1555 new->name = xstrdup (subset);
1556 new->major_version = major;
1557 new->minor_version = minor;
1558 new->next = NULL;
1559
1560 if (current != NULL)
1561 {
1562 new->next = current->next;
1563 current->next = new;
1564 }
1565 else
1566 {
1567 new->next = subset_list->head;
1568 subset_list->head = new;
1569 }
1570
1571 if (new->next == NULL)
1572 subset_list->tail = new;
1573 }
1574
1575 /* Get the default versions from the riscv_supported_*ext tables. */
1576
1577 static void
1578 riscv_get_default_ext_version (enum riscv_spec_class *default_isa_spec,
1579 const char *name,
1580 int *major_version,
1581 int *minor_version)
1582 {
1583 if (name == NULL
1584 || default_isa_spec == NULL
1585 || *default_isa_spec == ISA_SPEC_CLASS_NONE)
1586 return;
1587
1588 struct riscv_supported_ext *table = NULL;
1589 enum riscv_prefix_ext_class class = riscv_get_prefix_class (name);
1590 switch (class)
1591 {
1592 case RV_ISA_CLASS_ZXM: table = riscv_supported_std_zxm_ext; break;
1593 case RV_ISA_CLASS_Z: table = riscv_supported_std_z_ext; break;
1594 case RV_ISA_CLASS_S: table = riscv_supported_std_s_ext; break;
1595 case RV_ISA_CLASS_X: table = riscv_supported_vendor_x_ext; break;
1596 default:
1597 table = riscv_supported_std_ext;
1598 }
1599
1600 int i = 0;
1601 while (table != NULL && table[i].name != NULL)
1602 {
1603 if (strcmp (table[i].name, name) == 0
1604 && (table[i].isa_spec_class == ISA_SPEC_CLASS_DRAFT
1605 || table[i].isa_spec_class == *default_isa_spec))
1606 {
1607 *major_version = table[i].major_version;
1608 *minor_version = table[i].minor_version;
1609 return;
1610 }
1611 i++;
1612 }
1613 }
1614
1615 /* Find the default versions for the extension before adding them to
1616 the subset list, if their versions are RISCV_UNKNOWN_VERSION.
1617 Afterwards, report errors if we can not find their default versions. */
1618
1619 static void
1620 riscv_parse_add_subset (riscv_parse_subset_t *rps,
1621 const char *subset,
1622 int major,
1623 int minor,
1624 bool implicit)
1625 {
1626 int major_version = major;
1627 int minor_version = minor;
1628
1629 if (major_version == RISCV_UNKNOWN_VERSION
1630 || minor_version == RISCV_UNKNOWN_VERSION)
1631 riscv_get_default_ext_version (rps->isa_spec, subset,
1632 &major_version, &minor_version);
1633
1634 /* We don't care the versions of the implicit extensions. */
1635 if (!implicit
1636 && (major_version == RISCV_UNKNOWN_VERSION
1637 || minor_version == RISCV_UNKNOWN_VERSION))
1638 {
1639 if (subset[0] == 'x')
1640 rps->error_handler
1641 (_("x ISA extension `%s' must be set with the versions"),
1642 subset);
1643 /* Allow old ISA spec can recognize zicsr and zifencei. */
1644 else if (strcmp (subset, "zicsr") != 0
1645 && strcmp (subset, "zifencei") != 0)
1646 rps->error_handler
1647 (_("cannot find default versions of the ISA extension `%s'"),
1648 subset);
1649 return;
1650 }
1651
1652 riscv_add_subset (rps->subset_list, subset,
1653 major_version, minor_version);
1654 }
1655
1656 /* Release subset list. */
1657
1658 void
1659 riscv_release_subset_list (riscv_subset_list_t *subset_list)
1660 {
1661 while (subset_list->head != NULL)
1662 {
1663 riscv_subset_t *next = subset_list->head->next;
1664 free ((void *)subset_list->head->name);
1665 free (subset_list->head);
1666 subset_list->head = next;
1667 }
1668
1669 subset_list->tail = NULL;
1670
1671 if (subset_list->arch_str != NULL)
1672 {
1673 free ((void*) subset_list->arch_str);
1674 subset_list->arch_str = NULL;
1675 }
1676 }
1677
1678 /* Parsing extension version.
1679
1680 Return Value:
1681 Points to the end of version
1682
1683 Arguments:
1684 `p`: Curent parsing position.
1685 `major_version`: Parsed major version.
1686 `minor_version`: Parsed minor version. */
1687
1688 static const char *
1689 riscv_parsing_subset_version (const char *p,
1690 int *major_version,
1691 int *minor_version)
1692 {
1693 bool major_p = true;
1694 int version = 0;
1695 char np;
1696
1697 *major_version = 0;
1698 *minor_version = 0;
1699 for (; *p; ++p)
1700 {
1701 if (*p == 'p')
1702 {
1703 np = *(p + 1);
1704
1705 /* Might be beginning of `p` extension. */
1706 if (!ISDIGIT (np))
1707 break;
1708
1709 *major_version = version;
1710 major_p = false;
1711 version = 0;
1712 }
1713 else if (ISDIGIT (*p))
1714 version = (version * 10) + (*p - '0');
1715 else
1716 break;
1717 }
1718
1719 if (major_p)
1720 *major_version = version;
1721 else
1722 *minor_version = version;
1723
1724 /* We can not find any version in string. */
1725 if (*major_version == 0 && *minor_version == 0)
1726 {
1727 *major_version = RISCV_UNKNOWN_VERSION;
1728 *minor_version = RISCV_UNKNOWN_VERSION;
1729 }
1730
1731 return p;
1732 }
1733
1734 /* Parsing function for both standard and prefixed extensions.
1735
1736 Return Value:
1737 Points to the end of extensions.
1738
1739 Arguments:
1740 `rps`: Hooks and status for parsing extensions.
1741 `arch`: Full ISA string.
1742 `p`: Curent parsing position. */
1743
1744 static const char *
1745 riscv_parse_extensions (riscv_parse_subset_t *rps,
1746 const char *arch,
1747 const char *p)
1748 {
1749 /* First letter must start with i, e or g. */
1750 if (*p != 'e' && *p != 'i' && *p != 'g')
1751 {
1752 rps->error_handler
1753 (_("%s: first ISA extension must be `e', `i' or `g'"),
1754 arch);
1755 return NULL;
1756 }
1757
1758 while (*p != '\0')
1759 {
1760 if (*p == '_')
1761 {
1762 p++;
1763 continue;
1764 }
1765
1766 char *subset = xstrdup (p);
1767 char *q = subset; /* Start of version. */
1768 const char *end_of_version;
1769 bool implicit = false;
1770
1771 enum riscv_prefix_ext_class class = riscv_get_prefix_class (p);
1772 if (class == RV_ISA_CLASS_SINGLE)
1773 {
1774 if (riscv_ext_order[(*subset - 'a')] == 0)
1775 {
1776 rps->error_handler
1777 (_("%s: unknown standard ISA extension or prefix class `%c'"),
1778 arch, *subset);
1779 free (subset);
1780 return NULL;
1781 }
1782 q++;
1783 }
1784 else
1785 {
1786 /* Extract the whole prefixed extension by '_'. */
1787 while (*++q != '\0' && *q != '_')
1788 ;
1789 /* Look forward to the first letter which is not <major>p<minor>. */
1790 bool find_any_version = false;
1791 bool find_minor_version = false;
1792 while (1)
1793 {
1794 q--;
1795 if (ISDIGIT (*q))
1796 find_any_version = true;
1797 else if (find_any_version
1798 && !find_minor_version
1799 && *q == 'p'
1800 && ISDIGIT (*(q - 1)))
1801 find_minor_version = true;
1802 else
1803 break;
1804 }
1805 q++;
1806
1807 /* Check if the end of extension is 'p' or not. If yes, then
1808 the second letter from the end cannot be number. */
1809 if (*(q - 1) == 'p' && ISDIGIT (*(q - 2)))
1810 {
1811 *q = '\0';
1812 rps->error_handler
1813 (_("%s: invalid prefixed ISA extension `%s' ends with <number>p"),
1814 arch, subset);
1815 free (subset);
1816 return NULL;
1817 }
1818 }
1819
1820 int major_version = RISCV_UNKNOWN_VERSION;
1821 int minor_version = RISCV_UNKNOWN_VERSION;
1822 end_of_version =
1823 riscv_parsing_subset_version (q, &major_version, &minor_version);
1824 *q = '\0';
1825 if (end_of_version == NULL)
1826 {
1827 free (subset);
1828 return NULL;
1829 }
1830
1831 /* Check if the prefixed extension name is well-formed. */
1832 if (class != RV_ISA_CLASS_SINGLE
1833 && rps->check_unknown_prefixed_ext
1834 && !riscv_recognized_prefixed_ext (subset))
1835 {
1836 rps->error_handler
1837 (_("%s: unknown prefixed ISA extension `%s'"),
1838 arch, subset);
1839 free (subset);
1840 return NULL;
1841 }
1842
1843 /* Added g as an implicit extension. */
1844 if (class == RV_ISA_CLASS_SINGLE
1845 && strcmp (subset, "g") == 0)
1846 {
1847 implicit = true;
1848 major_version = RISCV_UNKNOWN_VERSION;
1849 minor_version = RISCV_UNKNOWN_VERSION;
1850 }
1851 riscv_parse_add_subset (rps, subset,
1852 major_version,
1853 minor_version, implicit);
1854 p += end_of_version - subset;
1855 free (subset);
1856
1857 if (class != RV_ISA_CLASS_SINGLE
1858 && *p != '\0' && *p != '_')
1859 {
1860 rps->error_handler
1861 (_("%s: prefixed ISA extension must separate with _"),
1862 arch);
1863 return NULL;
1864 }
1865 }
1866
1867 return p;
1868 }
1869
1870 /* Add the implicit extensions. */
1871
1872 static void
1873 riscv_parse_add_implicit_subsets (riscv_parse_subset_t *rps)
1874 {
1875 struct riscv_implicit_subset *t = riscv_implicit_subsets;
1876 bool finished = false;
1877 while (!finished)
1878 {
1879 finished = true;
1880 for (; t->subset_name; t++)
1881 {
1882 riscv_subset_t *subset = NULL;
1883 riscv_subset_t *implicit_subset = NULL;
1884 if (riscv_lookup_subset (rps->subset_list, t->subset_name, &subset)
1885 && !riscv_lookup_subset (rps->subset_list, t->implicit_name,
1886 &implicit_subset)
1887 && t->check_func (t->implicit_name, subset))
1888 {
1889 riscv_parse_add_subset (rps, t->implicit_name,
1890 RISCV_UNKNOWN_VERSION,
1891 RISCV_UNKNOWN_VERSION, true);
1892
1893 /* Restart the loop and pick up any new implications. */
1894 finished = false;
1895 t = riscv_implicit_subsets;
1896 break;
1897 }
1898 }
1899 }
1900 }
1901
1902 /* Check extensions conflicts. */
1903
1904 static bool
1905 riscv_parse_check_conflicts (riscv_parse_subset_t *rps)
1906 {
1907 riscv_subset_t *subset = NULL;
1908 int xlen = *rps->xlen;
1909 bool no_conflict = true;
1910
1911 if (riscv_lookup_subset (rps->subset_list, "e", &subset)
1912 && xlen > 32)
1913 {
1914 rps->error_handler
1915 (_("rv%d does not support the `e' extension"), xlen);
1916 no_conflict = false;
1917 }
1918 if (riscv_lookup_subset (rps->subset_list, "q", &subset)
1919 && (subset->major_version < 2 || (subset->major_version == 2
1920 && subset->minor_version < 2))
1921 && xlen < 64)
1922 {
1923 rps->error_handler (_("rv%d does not support the `q' extension"), xlen);
1924 no_conflict = false;
1925 }
1926 if (riscv_lookup_subset (rps->subset_list, "zfinx", &subset)
1927 && riscv_lookup_subset (rps->subset_list, "f", &subset))
1928 {
1929 rps->error_handler
1930 (_("`zfinx' is conflict with the `f/d/q/zfh/zfhmin' extension"));
1931 no_conflict = false;
1932 }
1933
1934 bool support_zve = false;
1935 bool support_zvl = false;
1936 riscv_subset_t *s = rps->subset_list->head;
1937 for (; s != NULL; s = s->next)
1938 {
1939 if (!support_zve
1940 && strncmp (s->name, "zve", 3) == 0)
1941 support_zve = true;
1942 if (!support_zvl
1943 && strncmp (s->name, "zvl", 3) == 0)
1944 support_zvl = true;
1945 if (support_zve && support_zvl)
1946 break;
1947 }
1948 if (support_zvl && !support_zve)
1949 {
1950 rps->error_handler
1951 (_("zvl*b extensions need to enable either `v' or `zve' extension"));
1952 no_conflict = false;
1953 }
1954
1955 return no_conflict;
1956 }
1957
1958 /* Set the default subset list according to the default_enable field
1959 of riscv_supported_*ext tables. */
1960
1961 static void
1962 riscv_set_default_arch (riscv_parse_subset_t *rps)
1963 {
1964 unsigned long enable = EXT_DEFAULT;
1965 int i, j;
1966 for (i = 0; riscv_all_supported_ext[i] != NULL; i++)
1967 {
1968 const struct riscv_supported_ext *table = riscv_all_supported_ext[i];
1969 for (j = 0; table[j].name != NULL; j++)
1970 {
1971 bool implicit = false;
1972 if (strcmp (table[j].name, "g") == 0)
1973 implicit = true;
1974 if (table[j].default_enable & enable)
1975 riscv_parse_add_subset (rps, table[j].name,
1976 RISCV_UNKNOWN_VERSION,
1977 RISCV_UNKNOWN_VERSION, implicit);
1978 }
1979 }
1980 }
1981
1982 /* Function for parsing ISA string.
1983
1984 Return Value:
1985 Return TRUE on success.
1986
1987 Arguments:
1988 `rps`: Hooks and status for parsing extensions.
1989 `arch`: Full ISA string. */
1990
1991 bool
1992 riscv_parse_subset (riscv_parse_subset_t *rps,
1993 const char *arch)
1994 {
1995 const char *p;
1996
1997 /* Init the riscv_ext_order array to compare the order of extensions
1998 quickly. */
1999 riscv_init_ext_order ();
2000
2001 if (arch == NULL)
2002 {
2003 riscv_set_default_arch (rps);
2004 riscv_parse_add_implicit_subsets (rps);
2005 return riscv_parse_check_conflicts (rps);
2006 }
2007
2008 for (p = arch; *p != '\0'; p++)
2009 {
2010 if (ISUPPER (*p))
2011 {
2012 rps->error_handler
2013 (_("%s: ISA string cannot contain uppercase letters"),
2014 arch);
2015 return false;
2016 }
2017 }
2018
2019 p = arch;
2020 if (startswith (p, "rv32"))
2021 {
2022 *rps->xlen = 32;
2023 p += 4;
2024 }
2025 else if (startswith (p, "rv64"))
2026 {
2027 *rps->xlen = 64;
2028 p += 4;
2029 }
2030 else
2031 {
2032 /* ISA string shouldn't be NULL or empty here. For linker,
2033 it might be empty when we failed to merge the ISA string
2034 in the riscv_merge_attributes. For assembler, we might
2035 give an empty string by .attribute arch, "" or -march=.
2036 However, We have already issued the correct error message
2037 in another side, so do not issue this error when the ISA
2038 string is empty. */
2039 if (strlen (arch))
2040 rps->error_handler (
2041 _("%s: ISA string must begin with rv32 or rv64"),
2042 arch);
2043 return false;
2044 }
2045
2046 /* Parse single standard and prefixed extensions. */
2047 if (riscv_parse_extensions (rps, arch, p) == NULL)
2048 return false;
2049
2050 /* Finally add implicit extensions according to the current
2051 extensions. */
2052 riscv_parse_add_implicit_subsets (rps);
2053
2054 /* Check the conflicts. */
2055 return riscv_parse_check_conflicts (rps);
2056 }
2057
2058 /* Return the number of digits for the input. */
2059
2060 size_t
2061 riscv_estimate_digit (unsigned num)
2062 {
2063 size_t digit = 0;
2064 if (num == 0)
2065 return 1;
2066
2067 for (digit = 0; num ; num /= 10)
2068 digit++;
2069
2070 return digit;
2071 }
2072
2073 /* Auxiliary function to estimate string length of subset list. */
2074
2075 static size_t
2076 riscv_estimate_arch_strlen1 (const riscv_subset_t *subset)
2077 {
2078 if (subset == NULL)
2079 return 6; /* For rv32/rv64/rv128 and string terminator. */
2080
2081 return riscv_estimate_arch_strlen1 (subset->next)
2082 + strlen (subset->name)
2083 + riscv_estimate_digit (subset->major_version)
2084 + 1 /* For version seperator 'p'. */
2085 + riscv_estimate_digit (subset->minor_version)
2086 + 1 /* For underscore. */;
2087 }
2088
2089 /* Estimate the string length of this subset list. */
2090
2091 static size_t
2092 riscv_estimate_arch_strlen (const riscv_subset_list_t *subset_list)
2093 {
2094 return riscv_estimate_arch_strlen1 (subset_list->head);
2095 }
2096
2097 /* Auxiliary function to convert subset info to string. */
2098
2099 static void
2100 riscv_arch_str1 (riscv_subset_t *subset,
2101 char *attr_str, char *buf, size_t bufsz)
2102 {
2103 const char *underline = "_";
2104 riscv_subset_t *subset_t = subset;
2105
2106 if (subset_t == NULL)
2107 return;
2108
2109 /* No underline between rvXX and i/e. */
2110 if ((strcasecmp (subset_t->name, "i") == 0)
2111 || (strcasecmp (subset_t->name, "e") == 0))
2112 underline = "";
2113
2114 snprintf (buf, bufsz, "%s%s%dp%d",
2115 underline,
2116 subset_t->name,
2117 subset_t->major_version,
2118 subset_t->minor_version);
2119
2120 strncat (attr_str, buf, bufsz);
2121
2122 /* Skip 'i' extension after 'e', or skip extensions which
2123 versions are unknown. */
2124 while (subset_t->next
2125 && ((strcmp (subset_t->name, "e") == 0
2126 && strcmp (subset_t->next->name, "i") == 0)
2127 || subset_t->next->major_version == RISCV_UNKNOWN_VERSION
2128 || subset_t->next->minor_version == RISCV_UNKNOWN_VERSION))
2129 subset_t = subset_t->next;
2130
2131 riscv_arch_str1 (subset_t->next, attr_str, buf, bufsz);
2132 }
2133
2134 /* Convert subset information into string with explicit versions. */
2135
2136 char *
2137 riscv_arch_str (unsigned xlen, const riscv_subset_list_t *subset)
2138 {
2139 size_t arch_str_len = riscv_estimate_arch_strlen (subset);
2140 char *attr_str = xmalloc (arch_str_len);
2141 char *buf = xmalloc (arch_str_len);
2142
2143 snprintf (attr_str, arch_str_len, "rv%u", xlen);
2144
2145 riscv_arch_str1 (subset->head, attr_str, buf, arch_str_len);
2146 free (buf);
2147
2148 return attr_str;
2149 }
2150
2151 /* Copy the subset in the subset list. */
2152
2153 static struct riscv_subset_t *
2154 riscv_copy_subset (riscv_subset_list_t *subset_list,
2155 riscv_subset_t *subset)
2156 {
2157 if (subset == NULL)
2158 return NULL;
2159
2160 riscv_subset_t *new = xmalloc (sizeof *new);
2161 new->name = xstrdup (subset->name);
2162 new->major_version = subset->major_version;
2163 new->minor_version = subset->minor_version;
2164 new->next = riscv_copy_subset (subset_list, subset->next);
2165
2166 if (subset->next == NULL)
2167 subset_list->tail = new;
2168
2169 return new;
2170 }
2171
2172 /* Copy the subset list. */
2173
2174 riscv_subset_list_t *
2175 riscv_copy_subset_list (riscv_subset_list_t *subset_list)
2176 {
2177 riscv_subset_list_t *new = xmalloc (sizeof *new);
2178 new->head = riscv_copy_subset (new, subset_list->head);
2179 new->arch_str = strdup (subset_list->arch_str);
2180 return new;
2181 }
2182
2183 /* Remove the SUBSET from the subset list. */
2184
2185 static void
2186 riscv_remove_subset (riscv_subset_list_t *subset_list,
2187 const char *subset)
2188 {
2189 riscv_subset_t *current = subset_list->head;
2190 riscv_subset_t *pre = NULL;
2191 for (; current != NULL; pre = current, current = current->next)
2192 {
2193 if (strcmp (current->name, subset) == 0)
2194 {
2195 if (pre == NULL)
2196 subset_list->head = current->next;
2197 else
2198 pre->next = current->next;
2199 if (current->next == NULL)
2200 subset_list->tail = pre;
2201 free ((void *) current->name);
2202 free (current);
2203 break;
2204 }
2205 }
2206 }
2207
2208 /* Add/Remove an extension to/from the subset list. This is used for
2209 the .option rvc or norvc, and .option arch directives. */
2210
2211 bool
2212 riscv_update_subset (riscv_parse_subset_t *rps,
2213 const char *str)
2214 {
2215 const char *p = str;
2216
2217 do
2218 {
2219 int major_version = RISCV_UNKNOWN_VERSION;
2220 int minor_version = RISCV_UNKNOWN_VERSION;
2221
2222 bool removed = false;
2223 switch (*p)
2224 {
2225 case '+': removed = false; break;
2226 case '-': removed = true; break;
2227 default:
2228 riscv_release_subset_list (rps->subset_list);
2229 return riscv_parse_subset (rps, p);
2230 }
2231 ++p;
2232
2233 char *subset = xstrdup (p);
2234 char *q = subset;
2235 const char *end_of_version;
2236 /* Extract the whole prefixed extension by ','. */
2237 while (*q != '\0' && *q != ',')
2238 q++;
2239
2240 /* Look forward to the first letter which is not <major>p<minor>. */
2241 bool find_any_version = false;
2242 bool find_minor_version = false;
2243 size_t len = q - subset;
2244 size_t i;
2245 for (i = len; i > 0; i--)
2246 {
2247 q--;
2248 if (ISDIGIT (*q))
2249 find_any_version = true;
2250 else if (find_any_version
2251 && !find_minor_version
2252 && *q == 'p'
2253 && ISDIGIT (*(q - 1)))
2254 find_minor_version = true;
2255 else
2256 break;
2257 }
2258 if (len > 0)
2259 q++;
2260
2261 /* Check if the end of extension is 'p' or not. If yes, then
2262 the second letter from the end cannot be number. */
2263 if (len > 1 && *(q - 1) == 'p' && ISDIGIT (*(q - 2)))
2264 {
2265 *q = '\0';
2266 rps->error_handler
2267 (_("invalid ISA extension ends with <number>p "
2268 "in .option arch `%s'"), str);
2269 free (subset);
2270 return false;
2271 }
2272
2273 end_of_version =
2274 riscv_parsing_subset_version (q, &major_version, &minor_version);
2275 *q = '\0';
2276 if (end_of_version == NULL)
2277 {
2278 free (subset);
2279 return false;
2280 }
2281
2282 if (strlen (subset) == 0
2283 || (strlen (subset) == 1
2284 && riscv_ext_order[(*subset - 'a')] == 0)
2285 || (strlen (subset) > 1
2286 && rps->check_unknown_prefixed_ext
2287 && !riscv_recognized_prefixed_ext (subset)))
2288 {
2289 rps->error_handler
2290 (_("unknown ISA extension `%s' in .option arch `%s'"),
2291 subset, str);
2292 free (subset);
2293 return false;
2294 }
2295
2296 if (strcmp (subset, "i") == 0
2297 || strcmp (subset, "e") == 0
2298 || strcmp (subset, "g") == 0)
2299 {
2300 rps->error_handler
2301 (_("cannot + or - base extension `%s' in .option "
2302 "arch `%s'"), subset, str);
2303 free (subset);
2304 return false;
2305 }
2306
2307 if (removed)
2308 riscv_remove_subset (rps->subset_list, subset);
2309 else
2310 riscv_parse_add_subset (rps, subset, major_version, minor_version, true);
2311 p += end_of_version - subset;
2312 free (subset);
2313 }
2314 while (*p++ == ',');
2315
2316 riscv_parse_add_implicit_subsets (rps);
2317 return riscv_parse_check_conflicts (rps);
2318 }
2319
2320 /* Check if the FEATURE subset is supported or not in the subset list.
2321 Return true if it is supported; Otherwise, return false. */
2322
2323 bool
2324 riscv_subset_supports (riscv_parse_subset_t *rps,
2325 const char *feature)
2326 {
2327 struct riscv_subset_t *subset;
2328 return riscv_lookup_subset (rps->subset_list, feature, &subset);
2329 }
2330
2331 /* Each instuction is belonged to an instruction class INSN_CLASS_*.
2332 Call riscv_subset_supports to make sure if the instuction is valid. */
2333
2334 bool
2335 riscv_multi_subset_supports (riscv_parse_subset_t *rps,
2336 enum riscv_insn_class insn_class)
2337 {
2338 switch (insn_class)
2339 {
2340 case INSN_CLASS_I:
2341 return riscv_subset_supports (rps, "i");
2342 case INSN_CLASS_ZICBOM:
2343 return riscv_subset_supports (rps, "zicbom");
2344 case INSN_CLASS_ZICBOP:
2345 return riscv_subset_supports (rps, "zicbop");
2346 case INSN_CLASS_ZICBOZ:
2347 return riscv_subset_supports (rps, "zicboz");
2348 case INSN_CLASS_ZICOND:
2349 return riscv_subset_supports (rps, "zicond");
2350 case INSN_CLASS_ZICSR:
2351 return riscv_subset_supports (rps, "zicsr");
2352 case INSN_CLASS_ZIFENCEI:
2353 return riscv_subset_supports (rps, "zifencei");
2354 case INSN_CLASS_ZIHINTPAUSE:
2355 return riscv_subset_supports (rps, "zihintpause");
2356 case INSN_CLASS_M:
2357 return riscv_subset_supports (rps, "m");
2358 case INSN_CLASS_ZMMUL:
2359 return riscv_subset_supports (rps, "zmmul");
2360 case INSN_CLASS_A:
2361 return riscv_subset_supports (rps, "a");
2362 case INSN_CLASS_ZAWRS:
2363 return riscv_subset_supports (rps, "zawrs");
2364 case INSN_CLASS_F:
2365 return riscv_subset_supports (rps, "f");
2366 case INSN_CLASS_D:
2367 return riscv_subset_supports (rps, "d");
2368 case INSN_CLASS_Q:
2369 return riscv_subset_supports (rps, "q");
2370 case INSN_CLASS_C:
2371 return riscv_subset_supports (rps, "c");
2372 case INSN_CLASS_F_AND_C:
2373 return (riscv_subset_supports (rps, "f")
2374 && riscv_subset_supports (rps, "c"));
2375 case INSN_CLASS_D_AND_C:
2376 return (riscv_subset_supports (rps, "d")
2377 && riscv_subset_supports (rps, "c"));
2378 case INSN_CLASS_F_INX:
2379 return (riscv_subset_supports (rps, "f")
2380 || riscv_subset_supports (rps, "zfinx"));
2381 case INSN_CLASS_D_INX:
2382 return (riscv_subset_supports (rps, "d")
2383 || riscv_subset_supports (rps, "zdinx"));
2384 case INSN_CLASS_Q_INX:
2385 return (riscv_subset_supports (rps, "q")
2386 || riscv_subset_supports (rps, "zqinx"));
2387 case INSN_CLASS_ZFH_INX:
2388 return (riscv_subset_supports (rps, "zfh")
2389 || riscv_subset_supports (rps, "zhinx"));
2390 case INSN_CLASS_ZFHMIN:
2391 return riscv_subset_supports (rps, "zfhmin");
2392 case INSN_CLASS_ZFHMIN_INX:
2393 return (riscv_subset_supports (rps, "zfhmin")
2394 || riscv_subset_supports (rps, "zhinxmin"));
2395 case INSN_CLASS_ZFHMIN_AND_D_INX:
2396 return ((riscv_subset_supports (rps, "zfhmin")
2397 && riscv_subset_supports (rps, "d"))
2398 || (riscv_subset_supports (rps, "zhinxmin")
2399 && riscv_subset_supports (rps, "zdinx")));
2400 case INSN_CLASS_ZFHMIN_AND_Q_INX:
2401 return ((riscv_subset_supports (rps, "zfhmin")
2402 && riscv_subset_supports (rps, "q"))
2403 || (riscv_subset_supports (rps, "zhinxmin")
2404 && riscv_subset_supports (rps, "zqinx")));
2405 case INSN_CLASS_ZFA:
2406 return riscv_subset_supports (rps, "zfa");
2407 case INSN_CLASS_D_AND_ZFA:
2408 return riscv_subset_supports (rps, "d")
2409 && riscv_subset_supports (rps, "zfa");
2410 case INSN_CLASS_Q_AND_ZFA:
2411 return riscv_subset_supports (rps, "q")
2412 && riscv_subset_supports (rps, "zfa");
2413 case INSN_CLASS_ZFH_AND_ZFA:
2414 return riscv_subset_supports (rps, "zfh")
2415 && riscv_subset_supports (rps, "zfa");
2416 case INSN_CLASS_ZBA:
2417 return riscv_subset_supports (rps, "zba");
2418 case INSN_CLASS_ZBB:
2419 return riscv_subset_supports (rps, "zbb");
2420 case INSN_CLASS_ZBC:
2421 return riscv_subset_supports (rps, "zbc");
2422 case INSN_CLASS_ZBS:
2423 return riscv_subset_supports (rps, "zbs");
2424 case INSN_CLASS_ZBKB:
2425 return riscv_subset_supports (rps, "zbkb");
2426 case INSN_CLASS_ZBKC:
2427 return riscv_subset_supports (rps, "zbkc");
2428 case INSN_CLASS_ZBKX:
2429 return riscv_subset_supports (rps, "zbkx");
2430 case INSN_CLASS_ZBB_OR_ZBKB:
2431 return (riscv_subset_supports (rps, "zbb")
2432 || riscv_subset_supports (rps, "zbkb"));
2433 case INSN_CLASS_ZBC_OR_ZBKC:
2434 return (riscv_subset_supports (rps, "zbc")
2435 || riscv_subset_supports (rps, "zbkc"));
2436 case INSN_CLASS_ZKND:
2437 return riscv_subset_supports (rps, "zknd");
2438 case INSN_CLASS_ZKNE:
2439 return riscv_subset_supports (rps, "zkne");
2440 case INSN_CLASS_ZKNH:
2441 return riscv_subset_supports (rps, "zknh");
2442 case INSN_CLASS_ZKND_OR_ZKNE:
2443 return (riscv_subset_supports (rps, "zknd")
2444 || riscv_subset_supports (rps, "zkne"));
2445 case INSN_CLASS_ZKSED:
2446 return riscv_subset_supports (rps, "zksed");
2447 case INSN_CLASS_ZKSH:
2448 return riscv_subset_supports (rps, "zksh");
2449 case INSN_CLASS_V:
2450 return (riscv_subset_supports (rps, "v")
2451 || riscv_subset_supports (rps, "zve64x")
2452 || riscv_subset_supports (rps, "zve32x"));
2453 case INSN_CLASS_ZVEF:
2454 return (riscv_subset_supports (rps, "v")
2455 || riscv_subset_supports (rps, "zve64d")
2456 || riscv_subset_supports (rps, "zve64f")
2457 || riscv_subset_supports (rps, "zve32f"));
2458 case INSN_CLASS_ZVBB:
2459 return riscv_subset_supports (rps, "zvbb");
2460 case INSN_CLASS_ZVBC:
2461 return riscv_subset_supports (rps, "zvbc");
2462 case INSN_CLASS_ZVKG:
2463 return riscv_subset_supports (rps, "zvkg");
2464 case INSN_CLASS_ZVKNED:
2465 return riscv_subset_supports (rps, "zvkned");
2466 case INSN_CLASS_ZVKNHA:
2467 return riscv_subset_supports (rps, "zvknha");
2468 case INSN_CLASS_ZVKNHB:
2469 return riscv_subset_supports (rps, "zvknhb");
2470 case INSN_CLASS_ZVKNHA_OR_ZVKNHB:
2471 return (riscv_subset_supports (rps, "zvknha")
2472 || riscv_subset_supports (rps, "zvknhb"));
2473 case INSN_CLASS_ZVKSED:
2474 return riscv_subset_supports (rps, "zvksed");
2475 case INSN_CLASS_ZVKSH:
2476 return riscv_subset_supports (rps, "zvksh");
2477 case INSN_CLASS_SVINVAL:
2478 return riscv_subset_supports (rps, "svinval");
2479 case INSN_CLASS_H:
2480 return riscv_subset_supports (rps, "h");
2481 case INSN_CLASS_XTHEADBA:
2482 return riscv_subset_supports (rps, "xtheadba");
2483 case INSN_CLASS_XTHEADBB:
2484 return riscv_subset_supports (rps, "xtheadbb");
2485 case INSN_CLASS_XTHEADBS:
2486 return riscv_subset_supports (rps, "xtheadbs");
2487 case INSN_CLASS_XTHEADCMO:
2488 return riscv_subset_supports (rps, "xtheadcmo");
2489 case INSN_CLASS_XTHEADCONDMOV:
2490 return riscv_subset_supports (rps, "xtheadcondmov");
2491 case INSN_CLASS_XTHEADFMEMIDX:
2492 return riscv_subset_supports (rps, "xtheadfmemidx");
2493 case INSN_CLASS_XTHEADFMV:
2494 return riscv_subset_supports (rps, "xtheadfmv");
2495 case INSN_CLASS_XTHEADINT:
2496 return riscv_subset_supports (rps, "xtheadint");
2497 case INSN_CLASS_XTHEADMAC:
2498 return riscv_subset_supports (rps, "xtheadmac");
2499 case INSN_CLASS_XTHEADMEMIDX:
2500 return riscv_subset_supports (rps, "xtheadmemidx");
2501 case INSN_CLASS_XTHEADMEMPAIR:
2502 return riscv_subset_supports (rps, "xtheadmempair");
2503 case INSN_CLASS_XTHEADSYNC:
2504 return riscv_subset_supports (rps, "xtheadsync");
2505 case INSN_CLASS_XVENTANACONDOPS:
2506 return riscv_subset_supports (rps, "xventanacondops");
2507 default:
2508 rps->error_handler
2509 (_("internal: unreachable INSN_CLASS_*"));
2510 return false;
2511 }
2512 }
2513
2514 /* Each instuction is belonged to an instruction class INSN_CLASS_*.
2515 Call riscv_subset_supports_ext to determine the missing extension. */
2516
2517 const char *
2518 riscv_multi_subset_supports_ext (riscv_parse_subset_t *rps,
2519 enum riscv_insn_class insn_class)
2520 {
2521 switch (insn_class)
2522 {
2523 case INSN_CLASS_I:
2524 return "i";
2525 case INSN_CLASS_ZICBOM:
2526 return "zicbom";
2527 case INSN_CLASS_ZICBOP:
2528 return "zicbop";
2529 case INSN_CLASS_ZICBOZ:
2530 return "zicboz";
2531 case INSN_CLASS_ZICOND:
2532 return "zicond";
2533 case INSN_CLASS_ZICSR:
2534 return "zicsr";
2535 case INSN_CLASS_ZIFENCEI:
2536 return "zifencei";
2537 case INSN_CLASS_ZIHINTPAUSE:
2538 return "zihintpause";
2539 case INSN_CLASS_M:
2540 return "m";
2541 case INSN_CLASS_ZMMUL:
2542 return _ ("m' or `zmmul");
2543 case INSN_CLASS_A:
2544 return "a";
2545 case INSN_CLASS_ZAWRS:
2546 return "zawrs";
2547 case INSN_CLASS_F:
2548 return "f";
2549 case INSN_CLASS_D:
2550 return "d";
2551 case INSN_CLASS_Q:
2552 return "q";
2553 case INSN_CLASS_C:
2554 return "c";
2555 case INSN_CLASS_F_AND_C:
2556 if (!riscv_subset_supports (rps, "f")
2557 && !riscv_subset_supports (rps, "c"))
2558 return _("f' and `c");
2559 else if (!riscv_subset_supports (rps, "f"))
2560 return "f";
2561 else
2562 return "c";
2563 case INSN_CLASS_D_AND_C:
2564 if (!riscv_subset_supports (rps, "d")
2565 && !riscv_subset_supports (rps, "c"))
2566 return _("d' and `c");
2567 else if (!riscv_subset_supports (rps, "d"))
2568 return "d";
2569 else
2570 return "c";
2571 case INSN_CLASS_F_INX:
2572 return _("f' or `zfinx");
2573 case INSN_CLASS_D_INX:
2574 return _("d' or `zdinx");
2575 case INSN_CLASS_Q_INX:
2576 return _("q' or `zqinx");
2577 case INSN_CLASS_ZFH_INX:
2578 return _("zfh' or `zhinx");
2579 case INSN_CLASS_ZFHMIN:
2580 return "zfhmin";
2581 case INSN_CLASS_ZFHMIN_INX:
2582 return _("zfhmin' or `zhinxmin");
2583 case INSN_CLASS_ZFHMIN_AND_D_INX:
2584 if (riscv_subset_supports (rps, "zfhmin"))
2585 return "d";
2586 else if (riscv_subset_supports (rps, "d"))
2587 return "zfhmin";
2588 else if (riscv_subset_supports (rps, "zhinxmin"))
2589 return "zdinx";
2590 else if (riscv_subset_supports (rps, "zdinx"))
2591 return "zhinxmin";
2592 else
2593 return _("zfhmin' and `d', or `zhinxmin' and `zdinx");
2594 case INSN_CLASS_ZFHMIN_AND_Q_INX:
2595 if (riscv_subset_supports (rps, "zfhmin"))
2596 return "q";
2597 else if (riscv_subset_supports (rps, "q"))
2598 return "zfhmin";
2599 else if (riscv_subset_supports (rps, "zhinxmin"))
2600 return "zqinx";
2601 else if (riscv_subset_supports (rps, "zqinx"))
2602 return "zhinxmin";
2603 else
2604 return _("zfhmin' and `q', or `zhinxmin' and `zqinx");
2605 case INSN_CLASS_ZFA:
2606 return "zfa";
2607 case INSN_CLASS_D_AND_ZFA:
2608 if (!riscv_subset_supports (rps, "d")
2609 && !riscv_subset_supports (rps, "zfa"))
2610 return _("d' and `zfa");
2611 else if (!riscv_subset_supports (rps, "d"))
2612 return "d";
2613 else
2614 return "zfa";
2615 case INSN_CLASS_Q_AND_ZFA:
2616 if (!riscv_subset_supports (rps, "q")
2617 && !riscv_subset_supports (rps, "zfa"))
2618 return _("q' and `zfa");
2619 else if (!riscv_subset_supports (rps, "q"))
2620 return "q";
2621 else
2622 return "zfa";
2623 case INSN_CLASS_ZFH_AND_ZFA:
2624 if (!riscv_subset_supports (rps, "zfh")
2625 && !riscv_subset_supports (rps, "zfa"))
2626 return _("zfh' and `zfa");
2627 else if (!riscv_subset_supports (rps, "zfh"))
2628 return "zfh";
2629 else
2630 return "zfa";
2631 case INSN_CLASS_ZBA:
2632 return "zba";
2633 case INSN_CLASS_ZBB:
2634 return "zbb";
2635 case INSN_CLASS_ZBC:
2636 return "zbc";
2637 case INSN_CLASS_ZBS:
2638 return "zbs";
2639 case INSN_CLASS_ZBKB:
2640 return "zbkb";
2641 case INSN_CLASS_ZBKC:
2642 return "zbkc";
2643 case INSN_CLASS_ZBKX:
2644 return "zbkx";
2645 case INSN_CLASS_ZBB_OR_ZBKB:
2646 return _("zbb' or `zbkb");
2647 case INSN_CLASS_ZBC_OR_ZBKC:
2648 return _("zbc' or `zbkc");
2649 case INSN_CLASS_ZKND:
2650 return "zknd";
2651 case INSN_CLASS_ZKNE:
2652 return "zkne";
2653 case INSN_CLASS_ZKNH:
2654 return "zknh";
2655 case INSN_CLASS_ZKND_OR_ZKNE:
2656 return _("zknd' or `zkne");
2657 case INSN_CLASS_ZKSED:
2658 return "zksed";
2659 case INSN_CLASS_ZKSH:
2660 return "zksh";
2661 case INSN_CLASS_V:
2662 return _("v' or `zve64x' or `zve32x");
2663 case INSN_CLASS_ZVEF:
2664 return _("v' or `zve64d' or `zve64f' or `zve32f");
2665 case INSN_CLASS_ZVBB:
2666 return _("zvbb");
2667 case INSN_CLASS_ZVBC:
2668 return _("zvbc");
2669 case INSN_CLASS_ZVKG:
2670 return _("zvkg");
2671 case INSN_CLASS_ZVKNED:
2672 return _("zvkned");
2673 case INSN_CLASS_ZVKNHA:
2674 return _("zvknha");
2675 case INSN_CLASS_ZVKNHB:
2676 return _("zvknhb");
2677 case INSN_CLASS_ZVKSED:
2678 return _("zvksed");
2679 case INSN_CLASS_ZVKSH:
2680 return _("zvksh");
2681 case INSN_CLASS_SVINVAL:
2682 return "svinval";
2683 case INSN_CLASS_H:
2684 return _("h");
2685 case INSN_CLASS_XTHEADBA:
2686 return "xtheadba";
2687 case INSN_CLASS_XTHEADBB:
2688 return "xtheadbb";
2689 case INSN_CLASS_XTHEADBS:
2690 return "xtheadbs";
2691 case INSN_CLASS_XTHEADCMO:
2692 return "xtheadcmo";
2693 case INSN_CLASS_XTHEADCONDMOV:
2694 return "xtheadcondmov";
2695 case INSN_CLASS_XTHEADFMEMIDX:
2696 return "xtheadfmemidx";
2697 case INSN_CLASS_XTHEADFMV:
2698 return "xtheadfmv";
2699 case INSN_CLASS_XTHEADINT:
2700 return "xtheadint";
2701 case INSN_CLASS_XTHEADMAC:
2702 return "xtheadmac";
2703 case INSN_CLASS_XTHEADMEMIDX:
2704 return "xtheadmemidx";
2705 case INSN_CLASS_XTHEADMEMPAIR:
2706 return "xtheadmempair";
2707 case INSN_CLASS_XTHEADSYNC:
2708 return "xtheadsync";
2709 default:
2710 rps->error_handler
2711 (_("internal: unreachable INSN_CLASS_*"));
2712 return NULL;
2713 }
2714 }