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