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