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