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