go32 sanity check
[binutils-gdb.git] / bfd / elfxx-riscv.c
1 /* RISC-V-specific support for ELF.
2 Copyright (C) 2011-2022 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
42 /* The relocation table used for SHT_RELA sections. */
43
44 static reloc_howto_type howto_table[] =
45 {
46 /* No relocation. */
47 HOWTO (R_RISCV_NONE, /* type */
48 0, /* rightshift */
49 0, /* size */
50 0, /* bitsize */
51 false, /* pc_relative */
52 0, /* bitpos */
53 complain_overflow_dont, /* complain_on_overflow */
54 bfd_elf_generic_reloc, /* special_function */
55 "R_RISCV_NONE", /* name */
56 false, /* partial_inplace */
57 0, /* src_mask */
58 0, /* dst_mask */
59 false), /* pcrel_offset */
60
61 /* 32 bit relocation. */
62 HOWTO (R_RISCV_32, /* type */
63 0, /* rightshift */
64 4, /* size */
65 32, /* bitsize */
66 false, /* pc_relative */
67 0, /* bitpos */
68 complain_overflow_dont, /* complain_on_overflow */
69 bfd_elf_generic_reloc, /* special_function */
70 "R_RISCV_32", /* name */
71 false, /* partial_inplace */
72 0, /* src_mask */
73 0xffffffff, /* dst_mask */
74 false), /* pcrel_offset */
75
76 /* 64 bit relocation. */
77 HOWTO (R_RISCV_64, /* type */
78 0, /* rightshift */
79 8, /* size */
80 64, /* bitsize */
81 false, /* pc_relative */
82 0, /* bitpos */
83 complain_overflow_dont, /* complain_on_overflow */
84 bfd_elf_generic_reloc, /* special_function */
85 "R_RISCV_64", /* name */
86 false, /* partial_inplace */
87 0, /* src_mask */
88 MINUS_ONE, /* dst_mask */
89 false), /* pcrel_offset */
90
91 /* Relocation against a local symbol in a shared object. */
92 HOWTO (R_RISCV_RELATIVE, /* type */
93 0, /* rightshift */
94 4, /* size */
95 32, /* bitsize */
96 false, /* pc_relative */
97 0, /* bitpos */
98 complain_overflow_dont, /* complain_on_overflow */
99 bfd_elf_generic_reloc, /* special_function */
100 "R_RISCV_RELATIVE", /* name */
101 false, /* partial_inplace */
102 0, /* src_mask */
103 0xffffffff, /* dst_mask */
104 false), /* pcrel_offset */
105
106 HOWTO (R_RISCV_COPY, /* type */
107 0, /* rightshift */
108 0, /* this one is variable size */
109 0, /* bitsize */
110 false, /* pc_relative */
111 0, /* bitpos */
112 complain_overflow_bitfield, /* complain_on_overflow */
113 bfd_elf_generic_reloc, /* special_function */
114 "R_RISCV_COPY", /* name */
115 false, /* partial_inplace */
116 0, /* src_mask */
117 0, /* dst_mask */
118 false), /* pcrel_offset */
119
120 HOWTO (R_RISCV_JUMP_SLOT, /* type */
121 0, /* rightshift */
122 8, /* size */
123 64, /* bitsize */
124 false, /* pc_relative */
125 0, /* bitpos */
126 complain_overflow_bitfield, /* complain_on_overflow */
127 bfd_elf_generic_reloc, /* special_function */
128 "R_RISCV_JUMP_SLOT", /* name */
129 false, /* partial_inplace */
130 0, /* src_mask */
131 0, /* dst_mask */
132 false), /* pcrel_offset */
133
134 /* Dynamic TLS relocations. */
135 HOWTO (R_RISCV_TLS_DTPMOD32, /* type */
136 0, /* rightshift */
137 4, /* size */
138 32, /* bitsize */
139 false, /* pc_relative */
140 0, /* bitpos */
141 complain_overflow_dont, /* complain_on_overflow */
142 bfd_elf_generic_reloc, /* special_function */
143 "R_RISCV_TLS_DTPMOD32", /* name */
144 false, /* partial_inplace */
145 0, /* src_mask */
146 0xffffffff, /* dst_mask */
147 false), /* pcrel_offset */
148
149 HOWTO (R_RISCV_TLS_DTPMOD64, /* type */
150 0, /* rightshift */
151 8, /* size */
152 64, /* bitsize */
153 false, /* pc_relative */
154 0, /* bitpos */
155 complain_overflow_dont, /* complain_on_overflow */
156 bfd_elf_generic_reloc, /* special_function */
157 "R_RISCV_TLS_DTPMOD64", /* name */
158 false, /* partial_inplace */
159 0, /* src_mask */
160 MINUS_ONE, /* dst_mask */
161 false), /* pcrel_offset */
162
163 HOWTO (R_RISCV_TLS_DTPREL32, /* type */
164 0, /* rightshift */
165 4, /* size */
166 32, /* bitsize */
167 false, /* pc_relative */
168 0, /* bitpos */
169 complain_overflow_dont, /* complain_on_overflow */
170 bfd_elf_generic_reloc, /* special_function */
171 "R_RISCV_TLS_DTPREL32", /* name */
172 true, /* partial_inplace */
173 0, /* src_mask */
174 0xffffffff, /* dst_mask */
175 false), /* pcrel_offset */
176
177 HOWTO (R_RISCV_TLS_DTPREL64, /* type */
178 0, /* rightshift */
179 8, /* size */
180 64, /* bitsize */
181 false, /* pc_relative */
182 0, /* bitpos */
183 complain_overflow_dont, /* complain_on_overflow */
184 bfd_elf_generic_reloc, /* special_function */
185 "R_RISCV_TLS_DTPREL64", /* name */
186 true, /* partial_inplace */
187 0, /* src_mask */
188 MINUS_ONE, /* dst_mask */
189 false), /* pcrel_offset */
190
191 HOWTO (R_RISCV_TLS_TPREL32, /* type */
192 0, /* rightshift */
193 4, /* size */
194 32, /* bitsize */
195 false, /* pc_relative */
196 0, /* bitpos */
197 complain_overflow_dont, /* complain_on_overflow */
198 bfd_elf_generic_reloc, /* special_function */
199 "R_RISCV_TLS_TPREL32", /* name */
200 false, /* partial_inplace */
201 0, /* src_mask */
202 0xffffffff, /* dst_mask */
203 false), /* pcrel_offset */
204
205 HOWTO (R_RISCV_TLS_TPREL64, /* type */
206 0, /* rightshift */
207 8, /* size */
208 64, /* bitsize */
209 false, /* pc_relative */
210 0, /* bitpos */
211 complain_overflow_dont, /* complain_on_overflow */
212 bfd_elf_generic_reloc, /* special_function */
213 "R_RISCV_TLS_TPREL64", /* name */
214 false, /* partial_inplace */
215 0, /* src_mask */
216 MINUS_ONE, /* dst_mask */
217 false), /* pcrel_offset */
218
219 /* Reserved for future relocs that the dynamic linker must understand. */
220 EMPTY_HOWTO (12),
221 EMPTY_HOWTO (13),
222 EMPTY_HOWTO (14),
223 EMPTY_HOWTO (15),
224
225 /* 12-bit PC-relative branch offset. */
226 HOWTO (R_RISCV_BRANCH, /* type */
227 0, /* rightshift */
228 4, /* size */
229 32, /* bitsize */
230 true, /* pc_relative */
231 0, /* bitpos */
232 complain_overflow_signed, /* complain_on_overflow */
233 bfd_elf_generic_reloc, /* special_function */
234 "R_RISCV_BRANCH", /* name */
235 false, /* partial_inplace */
236 0, /* src_mask */
237 ENCODE_BTYPE_IMM (-1U), /* dst_mask */
238 true), /* pcrel_offset */
239
240 /* 20-bit PC-relative jump offset. */
241 HOWTO (R_RISCV_JAL, /* type */
242 0, /* rightshift */
243 4, /* size */
244 32, /* bitsize */
245 true, /* pc_relative */
246 0, /* bitpos */
247 complain_overflow_dont, /* complain_on_overflow */
248 bfd_elf_generic_reloc, /* special_function */
249 "R_RISCV_JAL", /* name */
250 false, /* partial_inplace */
251 0, /* src_mask */
252 ENCODE_JTYPE_IMM (-1U), /* dst_mask */
253 true), /* pcrel_offset */
254
255 /* 32-bit PC-relative function call (AUIPC/JALR). */
256 HOWTO (R_RISCV_CALL, /* type */
257 0, /* rightshift */
258 8, /* size */
259 64, /* bitsize */
260 true, /* pc_relative */
261 0, /* bitpos */
262 complain_overflow_dont, /* complain_on_overflow */
263 bfd_elf_generic_reloc, /* special_function */
264 "R_RISCV_CALL", /* name */
265 false, /* partial_inplace */
266 0, /* src_mask */
267 ENCODE_UTYPE_IMM (-1U) | ((bfd_vma) ENCODE_ITYPE_IMM (-1U) << 32),
268 /* dst_mask */
269 true), /* pcrel_offset */
270
271 /* Like R_RISCV_CALL, but not locally binding. */
272 HOWTO (R_RISCV_CALL_PLT, /* type */
273 0, /* rightshift */
274 8, /* size */
275 64, /* bitsize */
276 true, /* pc_relative */
277 0, /* bitpos */
278 complain_overflow_dont, /* complain_on_overflow */
279 bfd_elf_generic_reloc, /* special_function */
280 "R_RISCV_CALL_PLT", /* name */
281 false, /* partial_inplace */
282 0, /* src_mask */
283 ENCODE_UTYPE_IMM (-1U) | ((bfd_vma) ENCODE_ITYPE_IMM (-1U) << 32),
284 /* dst_mask */
285 true), /* pcrel_offset */
286
287 /* High 20 bits of 32-bit PC-relative GOT access. */
288 HOWTO (R_RISCV_GOT_HI20, /* type */
289 0, /* rightshift */
290 4, /* size */
291 32, /* bitsize */
292 true, /* pc_relative */
293 0, /* bitpos */
294 complain_overflow_dont, /* complain_on_overflow */
295 bfd_elf_generic_reloc, /* special_function */
296 "R_RISCV_GOT_HI20", /* name */
297 false, /* partial_inplace */
298 0, /* src_mask */
299 ENCODE_UTYPE_IMM (-1U), /* dst_mask */
300 false), /* pcrel_offset */
301
302 /* High 20 bits of 32-bit PC-relative TLS IE GOT access. */
303 HOWTO (R_RISCV_TLS_GOT_HI20, /* type */
304 0, /* rightshift */
305 4, /* size */
306 32, /* bitsize */
307 true, /* pc_relative */
308 0, /* bitpos */
309 complain_overflow_dont, /* complain_on_overflow */
310 bfd_elf_generic_reloc, /* special_function */
311 "R_RISCV_TLS_GOT_HI20", /* name */
312 false, /* partial_inplace */
313 0, /* src_mask */
314 ENCODE_UTYPE_IMM (-1U), /* dst_mask */
315 false), /* pcrel_offset */
316
317 /* High 20 bits of 32-bit PC-relative TLS GD GOT reference. */
318 HOWTO (R_RISCV_TLS_GD_HI20, /* type */
319 0, /* rightshift */
320 4, /* size */
321 32, /* bitsize */
322 true, /* pc_relative */
323 0, /* bitpos */
324 complain_overflow_dont, /* complain_on_overflow */
325 bfd_elf_generic_reloc, /* special_function */
326 "R_RISCV_TLS_GD_HI20", /* name */
327 false, /* partial_inplace */
328 0, /* src_mask */
329 ENCODE_UTYPE_IMM (-1U), /* dst_mask */
330 false), /* pcrel_offset */
331
332 /* High 20 bits of 32-bit PC-relative reference. */
333 HOWTO (R_RISCV_PCREL_HI20, /* type */
334 0, /* rightshift */
335 4, /* size */
336 32, /* bitsize */
337 true, /* pc_relative */
338 0, /* bitpos */
339 complain_overflow_dont, /* complain_on_overflow */
340 bfd_elf_generic_reloc, /* special_function */
341 "R_RISCV_PCREL_HI20", /* name */
342 false, /* partial_inplace */
343 0, /* src_mask */
344 ENCODE_UTYPE_IMM (-1U), /* dst_mask */
345 true), /* pcrel_offset */
346
347 /* Low 12 bits of a 32-bit PC-relative load or add. */
348 HOWTO (R_RISCV_PCREL_LO12_I, /* type */
349 0, /* rightshift */
350 4, /* size */
351 32, /* bitsize */
352 false, /* pc_relative */
353 0, /* bitpos */
354 complain_overflow_dont, /* complain_on_overflow */
355 bfd_elf_generic_reloc, /* special_function */
356 "R_RISCV_PCREL_LO12_I", /* name */
357 false, /* partial_inplace */
358 0, /* src_mask */
359 ENCODE_ITYPE_IMM (-1U), /* dst_mask */
360 false), /* pcrel_offset */
361
362 /* Low 12 bits of a 32-bit PC-relative store. */
363 HOWTO (R_RISCV_PCREL_LO12_S, /* type */
364 0, /* rightshift */
365 4, /* size */
366 32, /* bitsize */
367 false, /* pc_relative */
368 0, /* bitpos */
369 complain_overflow_dont, /* complain_on_overflow */
370 bfd_elf_generic_reloc, /* special_function */
371 "R_RISCV_PCREL_LO12_S", /* name */
372 false, /* partial_inplace */
373 0, /* src_mask */
374 ENCODE_STYPE_IMM (-1U), /* dst_mask */
375 false), /* pcrel_offset */
376
377 /* High 20 bits of 32-bit absolute address. */
378 HOWTO (R_RISCV_HI20, /* type */
379 0, /* rightshift */
380 4, /* size */
381 32, /* bitsize */
382 false, /* pc_relative */
383 0, /* bitpos */
384 complain_overflow_dont, /* complain_on_overflow */
385 bfd_elf_generic_reloc, /* special_function */
386 "R_RISCV_HI20", /* name */
387 false, /* partial_inplace */
388 0, /* src_mask */
389 ENCODE_UTYPE_IMM (-1U), /* dst_mask */
390 false), /* pcrel_offset */
391
392 /* High 12 bits of 32-bit load or add. */
393 HOWTO (R_RISCV_LO12_I, /* type */
394 0, /* rightshift */
395 4, /* size */
396 32, /* bitsize */
397 false, /* pc_relative */
398 0, /* bitpos */
399 complain_overflow_dont, /* complain_on_overflow */
400 bfd_elf_generic_reloc, /* special_function */
401 "R_RISCV_LO12_I", /* name */
402 false, /* partial_inplace */
403 0, /* src_mask */
404 ENCODE_ITYPE_IMM (-1U), /* dst_mask */
405 false), /* pcrel_offset */
406
407 /* High 12 bits of 32-bit store. */
408 HOWTO (R_RISCV_LO12_S, /* type */
409 0, /* rightshift */
410 4, /* size */
411 32, /* bitsize */
412 false, /* pc_relative */
413 0, /* bitpos */
414 complain_overflow_dont, /* complain_on_overflow */
415 bfd_elf_generic_reloc, /* special_function */
416 "R_RISCV_LO12_S", /* name */
417 false, /* partial_inplace */
418 0, /* src_mask */
419 ENCODE_STYPE_IMM (-1U), /* dst_mask */
420 false), /* pcrel_offset */
421
422 /* High 20 bits of TLS LE thread pointer offset. */
423 HOWTO (R_RISCV_TPREL_HI20, /* type */
424 0, /* rightshift */
425 4, /* size */
426 32, /* bitsize */
427 false, /* pc_relative */
428 0, /* bitpos */
429 complain_overflow_signed, /* complain_on_overflow */
430 bfd_elf_generic_reloc, /* special_function */
431 "R_RISCV_TPREL_HI20", /* name */
432 true, /* partial_inplace */
433 0, /* src_mask */
434 ENCODE_UTYPE_IMM (-1U), /* dst_mask */
435 false), /* pcrel_offset */
436
437 /* Low 12 bits of TLS LE thread pointer offset for loads and adds. */
438 HOWTO (R_RISCV_TPREL_LO12_I, /* type */
439 0, /* rightshift */
440 4, /* size */
441 32, /* bitsize */
442 false, /* pc_relative */
443 0, /* bitpos */
444 complain_overflow_signed, /* complain_on_overflow */
445 bfd_elf_generic_reloc, /* special_function */
446 "R_RISCV_TPREL_LO12_I", /* name */
447 false, /* partial_inplace */
448 0, /* src_mask */
449 ENCODE_ITYPE_IMM (-1U), /* dst_mask */
450 false), /* pcrel_offset */
451
452 /* Low 12 bits of TLS LE thread pointer offset for stores. */
453 HOWTO (R_RISCV_TPREL_LO12_S, /* type */
454 0, /* rightshift */
455 4, /* size */
456 32, /* bitsize */
457 false, /* pc_relative */
458 0, /* bitpos */
459 complain_overflow_signed, /* complain_on_overflow */
460 bfd_elf_generic_reloc, /* special_function */
461 "R_RISCV_TPREL_LO12_S", /* name */
462 false, /* partial_inplace */
463 0, /* src_mask */
464 ENCODE_STYPE_IMM (-1U), /* dst_mask */
465 false), /* pcrel_offset */
466
467 /* TLS LE thread pointer usage. May be relaxed. */
468 HOWTO (R_RISCV_TPREL_ADD, /* type */
469 0, /* rightshift */
470 0, /* size */
471 0, /* bitsize */
472 false, /* pc_relative */
473 0, /* bitpos */
474 complain_overflow_dont, /* complain_on_overflow */
475 bfd_elf_generic_reloc, /* special_function */
476 "R_RISCV_TPREL_ADD", /* name */
477 false, /* partial_inplace */
478 0, /* src_mask */
479 0, /* dst_mask */
480 false), /* pcrel_offset */
481
482 /* 8-bit in-place addition, for local label subtraction. */
483 HOWTO (R_RISCV_ADD8, /* type */
484 0, /* rightshift */
485 1, /* size */
486 8, /* bitsize */
487 false, /* pc_relative */
488 0, /* bitpos */
489 complain_overflow_dont, /* complain_on_overflow */
490 riscv_elf_add_sub_reloc, /* special_function */
491 "R_RISCV_ADD8", /* name */
492 false, /* partial_inplace */
493 0, /* src_mask */
494 0xff, /* dst_mask */
495 false), /* pcrel_offset */
496
497 /* 16-bit in-place addition, for local label subtraction. */
498 HOWTO (R_RISCV_ADD16, /* type */
499 0, /* rightshift */
500 2, /* size */
501 16, /* bitsize */
502 false, /* pc_relative */
503 0, /* bitpos */
504 complain_overflow_dont, /* complain_on_overflow */
505 riscv_elf_add_sub_reloc, /* special_function */
506 "R_RISCV_ADD16", /* name */
507 false, /* partial_inplace */
508 0, /* src_mask */
509 0xffff, /* dst_mask */
510 false), /* pcrel_offset */
511
512 /* 32-bit in-place addition, for local label subtraction. */
513 HOWTO (R_RISCV_ADD32, /* type */
514 0, /* rightshift */
515 4, /* size */
516 32, /* bitsize */
517 false, /* pc_relative */
518 0, /* bitpos */
519 complain_overflow_dont, /* complain_on_overflow */
520 riscv_elf_add_sub_reloc, /* special_function */
521 "R_RISCV_ADD32", /* name */
522 false, /* partial_inplace */
523 0, /* src_mask */
524 0xffffffff, /* dst_mask */
525 false), /* pcrel_offset */
526
527 /* 64-bit in-place addition, for local label subtraction. */
528 HOWTO (R_RISCV_ADD64, /* type */
529 0, /* rightshift */
530 8, /* size */
531 64, /* bitsize */
532 false, /* pc_relative */
533 0, /* bitpos */
534 complain_overflow_dont, /* complain_on_overflow */
535 riscv_elf_add_sub_reloc, /* special_function */
536 "R_RISCV_ADD64", /* name */
537 false, /* partial_inplace */
538 0, /* src_mask */
539 MINUS_ONE, /* dst_mask */
540 false), /* pcrel_offset */
541
542 /* 8-bit in-place addition, for local label subtraction. */
543 HOWTO (R_RISCV_SUB8, /* type */
544 0, /* rightshift */
545 1, /* size */
546 8, /* bitsize */
547 false, /* pc_relative */
548 0, /* bitpos */
549 complain_overflow_dont, /* complain_on_overflow */
550 riscv_elf_add_sub_reloc, /* special_function */
551 "R_RISCV_SUB8", /* name */
552 false, /* partial_inplace */
553 0, /* src_mask */
554 0xff, /* dst_mask */
555 false), /* pcrel_offset */
556
557 /* 16-bit in-place addition, for local label subtraction. */
558 HOWTO (R_RISCV_SUB16, /* type */
559 0, /* rightshift */
560 2, /* size */
561 16, /* bitsize */
562 false, /* pc_relative */
563 0, /* bitpos */
564 complain_overflow_dont, /* complain_on_overflow */
565 riscv_elf_add_sub_reloc, /* special_function */
566 "R_RISCV_SUB16", /* name */
567 false, /* partial_inplace */
568 0, /* src_mask */
569 0xffff, /* dst_mask */
570 false), /* pcrel_offset */
571
572 /* 32-bit in-place addition, for local label subtraction. */
573 HOWTO (R_RISCV_SUB32, /* type */
574 0, /* rightshift */
575 4, /* size */
576 32, /* bitsize */
577 false, /* pc_relative */
578 0, /* bitpos */
579 complain_overflow_dont, /* complain_on_overflow */
580 riscv_elf_add_sub_reloc, /* special_function */
581 "R_RISCV_SUB32", /* name */
582 false, /* partial_inplace */
583 0, /* src_mask */
584 0xffffffff, /* dst_mask */
585 false), /* pcrel_offset */
586
587 /* 64-bit in-place addition, for local label subtraction. */
588 HOWTO (R_RISCV_SUB64, /* type */
589 0, /* rightshift */
590 8, /* size */
591 64, /* bitsize */
592 false, /* pc_relative */
593 0, /* bitpos */
594 complain_overflow_dont, /* complain_on_overflow */
595 riscv_elf_add_sub_reloc, /* special_function */
596 "R_RISCV_SUB64", /* name */
597 false, /* partial_inplace */
598 0, /* src_mask */
599 MINUS_ONE, /* dst_mask */
600 false), /* pcrel_offset */
601
602 /* 41 and 42 are reserved. */
603 EMPTY_HOWTO (0),
604 EMPTY_HOWTO (0),
605
606 /* Indicates an alignment statement. The addend field encodes how many
607 bytes of NOPs follow the statement. The desired alignment is the
608 addend rounded up to the next power of two. */
609 HOWTO (R_RISCV_ALIGN, /* type */
610 0, /* rightshift */
611 0, /* size */
612 0, /* bitsize */
613 false, /* pc_relative */
614 0, /* bitpos */
615 complain_overflow_dont, /* complain_on_overflow */
616 bfd_elf_generic_reloc, /* special_function */
617 "R_RISCV_ALIGN", /* name */
618 false, /* partial_inplace */
619 0, /* src_mask */
620 0, /* dst_mask */
621 false), /* pcrel_offset */
622
623 /* 8-bit PC-relative branch offset. */
624 HOWTO (R_RISCV_RVC_BRANCH, /* type */
625 0, /* rightshift */
626 2, /* size */
627 16, /* bitsize */
628 true, /* pc_relative */
629 0, /* bitpos */
630 complain_overflow_signed, /* complain_on_overflow */
631 bfd_elf_generic_reloc, /* special_function */
632 "R_RISCV_RVC_BRANCH", /* name */
633 false, /* partial_inplace */
634 0, /* src_mask */
635 ENCODE_CBTYPE_IMM (-1U), /* dst_mask */
636 true), /* pcrel_offset */
637
638 /* 11-bit PC-relative jump offset. */
639 HOWTO (R_RISCV_RVC_JUMP, /* type */
640 0, /* rightshift */
641 2, /* size */
642 16, /* bitsize */
643 true, /* pc_relative */
644 0, /* bitpos */
645 complain_overflow_dont, /* complain_on_overflow */
646 bfd_elf_generic_reloc, /* special_function */
647 "R_RISCV_RVC_JUMP", /* name */
648 false, /* partial_inplace */
649 0, /* src_mask */
650 ENCODE_CJTYPE_IMM (-1U), /* dst_mask */
651 true), /* pcrel_offset */
652
653 /* High 6 bits of 18-bit absolute address. */
654 HOWTO (R_RISCV_RVC_LUI, /* type */
655 0, /* rightshift */
656 2, /* size */
657 16, /* bitsize */
658 false, /* pc_relative */
659 0, /* bitpos */
660 complain_overflow_dont, /* complain_on_overflow */
661 bfd_elf_generic_reloc, /* special_function */
662 "R_RISCV_RVC_LUI", /* name */
663 false, /* partial_inplace */
664 0, /* src_mask */
665 ENCODE_CITYPE_IMM (-1U), /* dst_mask */
666 false), /* pcrel_offset */
667
668 /* GP-relative load. */
669 HOWTO (R_RISCV_GPREL_I, /* type */
670 0, /* rightshift */
671 4, /* size */
672 32, /* bitsize */
673 false, /* pc_relative */
674 0, /* bitpos */
675 complain_overflow_dont, /* complain_on_overflow */
676 bfd_elf_generic_reloc, /* special_function */
677 "R_RISCV_GPREL_I", /* name */
678 false, /* partial_inplace */
679 0, /* src_mask */
680 ENCODE_ITYPE_IMM (-1U), /* dst_mask */
681 false), /* pcrel_offset */
682
683 /* GP-relative store. */
684 HOWTO (R_RISCV_GPREL_S, /* type */
685 0, /* rightshift */
686 4, /* size */
687 32, /* bitsize */
688 false, /* pc_relative */
689 0, /* bitpos */
690 complain_overflow_dont, /* complain_on_overflow */
691 bfd_elf_generic_reloc, /* special_function */
692 "R_RISCV_GPREL_S", /* name */
693 false, /* partial_inplace */
694 0, /* src_mask */
695 ENCODE_STYPE_IMM (-1U), /* dst_mask */
696 false), /* pcrel_offset */
697
698 /* TP-relative TLS LE load. */
699 HOWTO (R_RISCV_TPREL_I, /* type */
700 0, /* rightshift */
701 4, /* size */
702 32, /* bitsize */
703 false, /* pc_relative */
704 0, /* bitpos */
705 complain_overflow_signed, /* complain_on_overflow */
706 bfd_elf_generic_reloc, /* special_function */
707 "R_RISCV_TPREL_I", /* name */
708 false, /* partial_inplace */
709 0, /* src_mask */
710 ENCODE_ITYPE_IMM (-1U), /* dst_mask */
711 false), /* pcrel_offset */
712
713 /* TP-relative TLS LE store. */
714 HOWTO (R_RISCV_TPREL_S, /* type */
715 0, /* rightshift */
716 4, /* size */
717 32, /* bitsize */
718 false, /* pc_relative */
719 0, /* bitpos */
720 complain_overflow_signed, /* complain_on_overflow */
721 bfd_elf_generic_reloc, /* special_function */
722 "R_RISCV_TPREL_S", /* name */
723 false, /* partial_inplace */
724 0, /* src_mask */
725 ENCODE_STYPE_IMM (-1U), /* dst_mask */
726 false), /* pcrel_offset */
727
728 /* The paired relocation may be relaxed. */
729 HOWTO (R_RISCV_RELAX, /* type */
730 0, /* rightshift */
731 0, /* size */
732 0, /* bitsize */
733 false, /* pc_relative */
734 0, /* bitpos */
735 complain_overflow_dont, /* complain_on_overflow */
736 bfd_elf_generic_reloc, /* special_function */
737 "R_RISCV_RELAX", /* name */
738 false, /* partial_inplace */
739 0, /* src_mask */
740 0, /* dst_mask */
741 false), /* pcrel_offset */
742
743 /* 6-bit in-place addition, for local label subtraction. */
744 HOWTO (R_RISCV_SUB6, /* type */
745 0, /* rightshift */
746 1, /* size */
747 8, /* bitsize */
748 false, /* pc_relative */
749 0, /* bitpos */
750 complain_overflow_dont, /* complain_on_overflow */
751 riscv_elf_add_sub_reloc, /* special_function */
752 "R_RISCV_SUB6", /* name */
753 false, /* partial_inplace */
754 0, /* src_mask */
755 0x3f, /* dst_mask */
756 false), /* pcrel_offset */
757
758 /* 6-bit in-place setting, for local label subtraction. */
759 HOWTO (R_RISCV_SET6, /* type */
760 0, /* rightshift */
761 1, /* size */
762 8, /* bitsize */
763 false, /* pc_relative */
764 0, /* bitpos */
765 complain_overflow_dont, /* complain_on_overflow */
766 bfd_elf_generic_reloc, /* special_function */
767 "R_RISCV_SET6", /* name */
768 false, /* partial_inplace */
769 0, /* src_mask */
770 0x3f, /* dst_mask */
771 false), /* pcrel_offset */
772
773 /* 8-bit in-place setting, for local label subtraction. */
774 HOWTO (R_RISCV_SET8, /* type */
775 0, /* rightshift */
776 1, /* size */
777 8, /* bitsize */
778 false, /* pc_relative */
779 0, /* bitpos */
780 complain_overflow_dont, /* complain_on_overflow */
781 bfd_elf_generic_reloc, /* special_function */
782 "R_RISCV_SET8", /* name */
783 false, /* partial_inplace */
784 0, /* src_mask */
785 0xff, /* dst_mask */
786 false), /* pcrel_offset */
787
788 /* 16-bit in-place setting, for local label subtraction. */
789 HOWTO (R_RISCV_SET16, /* type */
790 0, /* rightshift */
791 2, /* size */
792 16, /* bitsize */
793 false, /* pc_relative */
794 0, /* bitpos */
795 complain_overflow_dont, /* complain_on_overflow */
796 bfd_elf_generic_reloc, /* special_function */
797 "R_RISCV_SET16", /* name */
798 false, /* partial_inplace */
799 0, /* src_mask */
800 0xffff, /* dst_mask */
801 false), /* pcrel_offset */
802
803 /* 32-bit in-place setting, for local label subtraction. */
804 HOWTO (R_RISCV_SET32, /* type */
805 0, /* rightshift */
806 4, /* size */
807 32, /* bitsize */
808 false, /* pc_relative */
809 0, /* bitpos */
810 complain_overflow_dont, /* complain_on_overflow */
811 bfd_elf_generic_reloc, /* special_function */
812 "R_RISCV_SET32", /* name */
813 false, /* partial_inplace */
814 0, /* src_mask */
815 0xffffffff, /* dst_mask */
816 false), /* pcrel_offset */
817
818 /* 32-bit PC relative. */
819 HOWTO (R_RISCV_32_PCREL, /* type */
820 0, /* rightshift */
821 4, /* size */
822 32, /* bitsize */
823 true, /* pc_relative */
824 0, /* bitpos */
825 complain_overflow_dont, /* complain_on_overflow */
826 bfd_elf_generic_reloc, /* special_function */
827 "R_RISCV_32_PCREL", /* name */
828 false, /* partial_inplace */
829 0, /* src_mask */
830 0xffffffff, /* dst_mask */
831 false), /* pcrel_offset */
832
833 /* Relocation against a local ifunc symbol in a shared object. */
834 HOWTO (R_RISCV_IRELATIVE, /* type */
835 0, /* rightshift */
836 4, /* size */
837 32, /* bitsize */
838 false, /* pc_relative */
839 0, /* bitpos */
840 complain_overflow_dont, /* complain_on_overflow */
841 bfd_elf_generic_reloc, /* special_function */
842 "R_RISCV_IRELATIVE", /* name */
843 false, /* partial_inplace */
844 0, /* src_mask */
845 0xffffffff, /* dst_mask */
846 false), /* pcrel_offset */
847 };
848
849 /* A mapping from BFD reloc types to RISC-V ELF reloc types. */
850 struct elf_reloc_map
851 {
852 bfd_reloc_code_real_type bfd_val;
853 enum elf_riscv_reloc_type elf_val;
854 };
855
856 static const struct elf_reloc_map riscv_reloc_map[] =
857 {
858 { BFD_RELOC_NONE, R_RISCV_NONE },
859 { BFD_RELOC_32, R_RISCV_32 },
860 { BFD_RELOC_64, R_RISCV_64 },
861 { BFD_RELOC_RISCV_ADD8, R_RISCV_ADD8 },
862 { BFD_RELOC_RISCV_ADD16, R_RISCV_ADD16 },
863 { BFD_RELOC_RISCV_ADD32, R_RISCV_ADD32 },
864 { BFD_RELOC_RISCV_ADD64, R_RISCV_ADD64 },
865 { BFD_RELOC_RISCV_SUB8, R_RISCV_SUB8 },
866 { BFD_RELOC_RISCV_SUB16, R_RISCV_SUB16 },
867 { BFD_RELOC_RISCV_SUB32, R_RISCV_SUB32 },
868 { BFD_RELOC_RISCV_SUB64, R_RISCV_SUB64 },
869 { BFD_RELOC_CTOR, R_RISCV_64 },
870 { BFD_RELOC_12_PCREL, R_RISCV_BRANCH },
871 { BFD_RELOC_RISCV_HI20, R_RISCV_HI20 },
872 { BFD_RELOC_RISCV_LO12_I, R_RISCV_LO12_I },
873 { BFD_RELOC_RISCV_LO12_S, R_RISCV_LO12_S },
874 { BFD_RELOC_RISCV_PCREL_LO12_I, R_RISCV_PCREL_LO12_I },
875 { BFD_RELOC_RISCV_PCREL_LO12_S, R_RISCV_PCREL_LO12_S },
876 { BFD_RELOC_RISCV_CALL, R_RISCV_CALL },
877 { BFD_RELOC_RISCV_CALL_PLT, R_RISCV_CALL_PLT },
878 { BFD_RELOC_RISCV_PCREL_HI20, R_RISCV_PCREL_HI20 },
879 { BFD_RELOC_RISCV_JMP, R_RISCV_JAL },
880 { BFD_RELOC_RISCV_GOT_HI20, R_RISCV_GOT_HI20 },
881 { BFD_RELOC_RISCV_TLS_DTPMOD32, R_RISCV_TLS_DTPMOD32 },
882 { BFD_RELOC_RISCV_TLS_DTPREL32, R_RISCV_TLS_DTPREL32 },
883 { BFD_RELOC_RISCV_TLS_DTPMOD64, R_RISCV_TLS_DTPMOD64 },
884 { BFD_RELOC_RISCV_TLS_DTPREL64, R_RISCV_TLS_DTPREL64 },
885 { BFD_RELOC_RISCV_TLS_TPREL32, R_RISCV_TLS_TPREL32 },
886 { BFD_RELOC_RISCV_TLS_TPREL64, R_RISCV_TLS_TPREL64 },
887 { BFD_RELOC_RISCV_TPREL_HI20, R_RISCV_TPREL_HI20 },
888 { BFD_RELOC_RISCV_TPREL_ADD, R_RISCV_TPREL_ADD },
889 { BFD_RELOC_RISCV_TPREL_LO12_S, R_RISCV_TPREL_LO12_S },
890 { BFD_RELOC_RISCV_TPREL_LO12_I, R_RISCV_TPREL_LO12_I },
891 { BFD_RELOC_RISCV_TLS_GOT_HI20, R_RISCV_TLS_GOT_HI20 },
892 { BFD_RELOC_RISCV_TLS_GD_HI20, R_RISCV_TLS_GD_HI20 },
893 { BFD_RELOC_RISCV_ALIGN, R_RISCV_ALIGN },
894 { BFD_RELOC_RISCV_RVC_BRANCH, R_RISCV_RVC_BRANCH },
895 { BFD_RELOC_RISCV_RVC_JUMP, R_RISCV_RVC_JUMP },
896 { BFD_RELOC_RISCV_RVC_LUI, R_RISCV_RVC_LUI },
897 { BFD_RELOC_RISCV_GPREL_I, R_RISCV_GPREL_I },
898 { BFD_RELOC_RISCV_GPREL_S, R_RISCV_GPREL_S },
899 { BFD_RELOC_RISCV_TPREL_I, R_RISCV_TPREL_I },
900 { BFD_RELOC_RISCV_TPREL_S, R_RISCV_TPREL_S },
901 { BFD_RELOC_RISCV_RELAX, R_RISCV_RELAX },
902 { BFD_RELOC_RISCV_SUB6, R_RISCV_SUB6 },
903 { BFD_RELOC_RISCV_SET6, R_RISCV_SET6 },
904 { BFD_RELOC_RISCV_SET8, R_RISCV_SET8 },
905 { BFD_RELOC_RISCV_SET16, R_RISCV_SET16 },
906 { BFD_RELOC_RISCV_SET32, R_RISCV_SET32 },
907 { BFD_RELOC_RISCV_32_PCREL, R_RISCV_32_PCREL },
908 };
909
910 /* Given a BFD reloc type, return a howto structure. */
911
912 reloc_howto_type *
913 riscv_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED,
914 bfd_reloc_code_real_type code)
915 {
916 unsigned int i;
917
918 for (i = 0; i < ARRAY_SIZE (riscv_reloc_map); i++)
919 if (riscv_reloc_map[i].bfd_val == code)
920 return &howto_table[(int) riscv_reloc_map[i].elf_val];
921
922 bfd_set_error (bfd_error_bad_value);
923 return NULL;
924 }
925
926 reloc_howto_type *
927 riscv_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED, const char *r_name)
928 {
929 unsigned int i;
930
931 for (i = 0; i < ARRAY_SIZE (howto_table); i++)
932 if (howto_table[i].name && strcasecmp (howto_table[i].name, r_name) == 0)
933 return &howto_table[i];
934
935 return NULL;
936 }
937
938 reloc_howto_type *
939 riscv_elf_rtype_to_howto (bfd *abfd, unsigned int r_type)
940 {
941 if (r_type >= ARRAY_SIZE (howto_table))
942 {
943 (*_bfd_error_handler) (_("%pB: unsupported relocation type %#x"),
944 abfd, r_type);
945 bfd_set_error (bfd_error_bad_value);
946 return NULL;
947 }
948 return &howto_table[r_type];
949 }
950
951 /* Special_function of RISCV_ADD and RISCV_SUB relocations. */
952
953 static bfd_reloc_status_type
954 riscv_elf_add_sub_reloc (bfd *abfd,
955 arelent *reloc_entry,
956 asymbol *symbol,
957 void *data,
958 asection *input_section,
959 bfd *output_bfd,
960 char **error_message ATTRIBUTE_UNUSED)
961 {
962 reloc_howto_type *howto = reloc_entry->howto;
963 bfd_vma relocation;
964
965 if (output_bfd != NULL
966 && (symbol->flags & BSF_SECTION_SYM) == 0
967 && (!reloc_entry->howto->partial_inplace || reloc_entry->addend == 0))
968 {
969 reloc_entry->address += input_section->output_offset;
970 return bfd_reloc_ok;
971 }
972
973 if (output_bfd != NULL)
974 return bfd_reloc_continue;
975
976 relocation = symbol->value + symbol->section->output_section->vma
977 + symbol->section->output_offset + reloc_entry->addend;
978
979 bfd_size_type octets = reloc_entry->address
980 * bfd_octets_per_byte (abfd, input_section);
981 if (!bfd_reloc_offset_in_range (reloc_entry->howto, abfd,
982 input_section, octets))
983 return bfd_reloc_outofrange;
984
985 bfd_vma old_value = bfd_get (howto->bitsize, abfd,
986 data + reloc_entry->address);
987
988 switch (howto->type)
989 {
990 case R_RISCV_ADD8:
991 case R_RISCV_ADD16:
992 case R_RISCV_ADD32:
993 case R_RISCV_ADD64:
994 relocation = old_value + relocation;
995 break;
996 case R_RISCV_SUB6:
997 case R_RISCV_SUB8:
998 case R_RISCV_SUB16:
999 case R_RISCV_SUB32:
1000 case R_RISCV_SUB64:
1001 relocation = old_value - relocation;
1002 break;
1003 }
1004 bfd_put (howto->bitsize, abfd, relocation, data + reloc_entry->address);
1005
1006 return bfd_reloc_ok;
1007 }
1008
1009 /* Always add the IMPLICIT for the SUBSET. */
1010
1011 static bool
1012 check_implicit_always (const char *implicit ATTRIBUTE_UNUSED,
1013 riscv_subset_t *subset ATTRIBUTE_UNUSED)
1014 {
1015 return true;
1016 }
1017
1018 /* Add the IMPLICIT only when the version of SUBSET less than 2.1. */
1019
1020 static bool
1021 check_implicit_for_i (const char *implicit ATTRIBUTE_UNUSED,
1022 riscv_subset_t *subset)
1023 {
1024 return (subset->major_version < 2
1025 || (subset->major_version == 2
1026 && subset->minor_version < 1));
1027 }
1028
1029 /* Record all implicit information for the subsets. */
1030 struct riscv_implicit_subset
1031 {
1032 const char *subset_name;
1033 const char *implicit_name;
1034 /* A function to determine if we need to add the implicit subset. */
1035 bool (*check_func) (const char *, riscv_subset_t *);
1036 };
1037 static struct riscv_implicit_subset riscv_implicit_subsets[] =
1038 {
1039 {"e", "i", check_implicit_always},
1040 {"i", "zicsr", check_implicit_for_i},
1041 {"i", "zifencei", check_implicit_for_i},
1042 {"g", "i", check_implicit_always},
1043 {"g", "m", check_implicit_always},
1044 {"g", "a", check_implicit_always},
1045 {"g", "f", check_implicit_always},
1046 {"g", "d", check_implicit_always},
1047 {"g", "zicsr", check_implicit_always},
1048 {"g", "zifencei", check_implicit_always},
1049 {"m", "zmmul", check_implicit_always},
1050 {"h", "zicsr", check_implicit_always},
1051 {"q", "d", check_implicit_always},
1052 {"v", "d", check_implicit_always},
1053 {"v", "zve64d", check_implicit_always},
1054 {"v", "zvl128b", check_implicit_always},
1055 {"zve64d", "d", check_implicit_always},
1056 {"zve64d", "zve64f", check_implicit_always},
1057 {"zve64f", "zve32f", check_implicit_always},
1058 {"zve64f", "zve64x", check_implicit_always},
1059 {"zve64f", "zvl64b", check_implicit_always},
1060 {"zve32f", "f", check_implicit_always},
1061 {"zve32f", "zvl32b", check_implicit_always},
1062 {"zve32f", "zve32x", check_implicit_always},
1063 {"zve64x", "zve32x", check_implicit_always},
1064 {"zve64x", "zvl64b", check_implicit_always},
1065 {"zve32x", "zvl32b", check_implicit_always},
1066 {"zvl65536b", "zvl32768b", check_implicit_always},
1067 {"zvl32768b", "zvl16384b", check_implicit_always},
1068 {"zvl16384b", "zvl8192b", check_implicit_always},
1069 {"zvl8192b", "zvl4096b", check_implicit_always},
1070 {"zvl4096b", "zvl2048b", check_implicit_always},
1071 {"zvl2048b", "zvl1024b", check_implicit_always},
1072 {"zvl1024b", "zvl512b", check_implicit_always},
1073 {"zvl512b", "zvl256b", check_implicit_always},
1074 {"zvl256b", "zvl128b", check_implicit_always},
1075 {"zvl128b", "zvl64b", check_implicit_always},
1076 {"zvl64b", "zvl32b", check_implicit_always},
1077 {"d", "f", check_implicit_always},
1078 {"zfh", "zfhmin", check_implicit_always},
1079 {"zfhmin", "f", check_implicit_always},
1080 {"f", "zicsr", check_implicit_always},
1081 {"zqinx", "zdinx", check_implicit_always},
1082 {"zdinx", "zfinx", check_implicit_always},
1083 {"zhinx", "zhinxmin", check_implicit_always},
1084 {"zhinxmin", "zfinx", check_implicit_always},
1085 {"zfinx", "zicsr", check_implicit_always},
1086 {"zk", "zkn", check_implicit_always},
1087 {"zk", "zkr", check_implicit_always},
1088 {"zk", "zkt", check_implicit_always},
1089 {"zkn", "zbkb", check_implicit_always},
1090 {"zkn", "zbkc", check_implicit_always},
1091 {"zkn", "zbkx", check_implicit_always},
1092 {"zkn", "zkne", check_implicit_always},
1093 {"zkn", "zknd", check_implicit_always},
1094 {"zkn", "zknh", check_implicit_always},
1095 {"zks", "zbkb", check_implicit_always},
1096 {"zks", "zbkc", check_implicit_always},
1097 {"zks", "zbkx", check_implicit_always},
1098 {"zks", "zksed", check_implicit_always},
1099 {"zks", "zksh", check_implicit_always},
1100 {"smepmp", "zicsr", check_implicit_always},
1101 {"smstateen", "zicsr", check_implicit_always},
1102 {"sscofpmf", "zicsr", check_implicit_always},
1103 {"sstc", "zicsr", check_implicit_always},
1104 {NULL, NULL, NULL}
1105 };
1106
1107 /* For default_enable field, decide if the extension should
1108 be enbaled by default. */
1109
1110 #define EXT_DEFAULT 0x1
1111
1112 /* List all extensions that binutils should know about. */
1113
1114 struct riscv_supported_ext
1115 {
1116 const char *name;
1117 enum riscv_spec_class isa_spec_class;
1118 int major_version;
1119 int minor_version;
1120 unsigned long default_enable;
1121 };
1122
1123 /* The standard extensions must be added in canonical order. */
1124
1125 static struct riscv_supported_ext riscv_supported_std_ext[] =
1126 {
1127 {"e", ISA_SPEC_CLASS_20191213, 1, 9, 0 },
1128 {"e", ISA_SPEC_CLASS_20190608, 1, 9, 0 },
1129 {"e", ISA_SPEC_CLASS_2P2, 1, 9, 0 },
1130 {"i", ISA_SPEC_CLASS_20191213, 2, 1, 0 },
1131 {"i", ISA_SPEC_CLASS_20190608, 2, 1, 0 },
1132 {"i", ISA_SPEC_CLASS_2P2, 2, 0, 0 },
1133 /* The g is a special case which we don't want to output it,
1134 but still need it when adding implicit extensions. */
1135 {"g", ISA_SPEC_CLASS_NONE, RISCV_UNKNOWN_VERSION, RISCV_UNKNOWN_VERSION, EXT_DEFAULT },
1136 {"m", ISA_SPEC_CLASS_20191213, 2, 0, 0 },
1137 {"m", ISA_SPEC_CLASS_20190608, 2, 0, 0 },
1138 {"m", ISA_SPEC_CLASS_2P2, 2, 0, 0 },
1139 {"a", ISA_SPEC_CLASS_20191213, 2, 1, 0 },
1140 {"a", ISA_SPEC_CLASS_20190608, 2, 0, 0 },
1141 {"a", ISA_SPEC_CLASS_2P2, 2, 0, 0 },
1142 {"f", ISA_SPEC_CLASS_20191213, 2, 2, 0 },
1143 {"f", ISA_SPEC_CLASS_20190608, 2, 2, 0 },
1144 {"f", ISA_SPEC_CLASS_2P2, 2, 0, 0 },
1145 {"d", ISA_SPEC_CLASS_20191213, 2, 2, 0 },
1146 {"d", ISA_SPEC_CLASS_20190608, 2, 2, 0 },
1147 {"d", ISA_SPEC_CLASS_2P2, 2, 0, 0 },
1148 {"q", ISA_SPEC_CLASS_20191213, 2, 2, 0 },
1149 {"q", ISA_SPEC_CLASS_20190608, 2, 2, 0 },
1150 {"q", ISA_SPEC_CLASS_2P2, 2, 0, 0 },
1151 {"c", ISA_SPEC_CLASS_20191213, 2, 0, 0 },
1152 {"c", ISA_SPEC_CLASS_20190608, 2, 0, 0 },
1153 {"c", ISA_SPEC_CLASS_2P2, 2, 0, 0 },
1154 {"v", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1155 {"h", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1156 {NULL, 0, 0, 0, 0}
1157 };
1158
1159 static struct riscv_supported_ext riscv_supported_std_z_ext[] =
1160 {
1161 {"zicbom", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1162 {"zicbop", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1163 {"zicboz", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1164 {"zicsr", ISA_SPEC_CLASS_20191213, 2, 0, 0 },
1165 {"zicsr", ISA_SPEC_CLASS_20190608, 2, 0, 0 },
1166 {"zifencei", ISA_SPEC_CLASS_20191213, 2, 0, 0 },
1167 {"zifencei", ISA_SPEC_CLASS_20190608, 2, 0, 0 },
1168 {"zihintpause", ISA_SPEC_CLASS_DRAFT, 2, 0, 0 },
1169 {"zmmul", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1170 {"zawrs", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1171 {"zfh", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1172 {"zfhmin", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1173 {"zfinx", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1174 {"zdinx", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1175 {"zqinx", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1176 {"zhinx", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1177 {"zhinxmin", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1178 {"zbb", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1179 {"zba", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1180 {"zbc", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1181 {"zbs", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1182 {"zbkb", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1183 {"zbkc", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1184 {"zbkx", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1185 {"zk", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1186 {"zkn", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1187 {"zknd", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1188 {"zkne", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1189 {"zknh", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1190 {"zkr", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1191 {"zks", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1192 {"zksed", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1193 {"zksh", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1194 {"zkt", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1195 {"zve32x", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1196 {"zve32f", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1197 {"zve32d", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1198 {"zve64x", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1199 {"zve64f", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1200 {"zve64d", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1201 {"zvl32b", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1202 {"zvl64b", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1203 {"zvl128b", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1204 {"zvl256b", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1205 {"zvl512b", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1206 {"zvl1024b", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1207 {"zvl2048b", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1208 {"zvl4096b", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1209 {"zvl8192b", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1210 {"zvl16384b", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1211 {"zvl32768b", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1212 {"zvl65536b", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1213 {"ztso", ISA_SPEC_CLASS_DRAFT, 0, 1, 0 },
1214 {NULL, 0, 0, 0, 0}
1215 };
1216
1217 static struct riscv_supported_ext riscv_supported_std_s_ext[] =
1218 {
1219 {"smepmp", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1220 {"smstateen", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1221 {"sscofpmf", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1222 {"sstc", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1223 {"svinval", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1224 {"svnapot", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1225 {"svpbmt", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1226 {NULL, 0, 0, 0, 0}
1227 };
1228
1229 static struct riscv_supported_ext riscv_supported_std_zxm_ext[] =
1230 {
1231 {NULL, 0, 0, 0, 0}
1232 };
1233
1234 static struct riscv_supported_ext riscv_supported_vendor_x_ext[] =
1235 {
1236 {"xtheadba", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1237 {"xtheadbb", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1238 {"xtheadbs", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1239 {"xtheadcmo", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1240 {"xtheadcondmov", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1241 {"xtheadfmemidx", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1242 {"xtheadfmv", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1243 {"xtheadint", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1244 {"xtheadmac", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1245 {"xtheadmemidx", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1246 {"xtheadmempair", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1247 {"xtheadsync", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1248 {NULL, 0, 0, 0, 0}
1249 };
1250
1251 const struct riscv_supported_ext *riscv_all_supported_ext[] =
1252 {
1253 riscv_supported_std_ext,
1254 riscv_supported_std_z_ext,
1255 riscv_supported_std_s_ext,
1256 riscv_supported_std_zxm_ext,
1257 riscv_supported_vendor_x_ext,
1258 NULL
1259 };
1260
1261 /* ISA extension prefixed name class. Must define them in parsing order. */
1262 enum riscv_prefix_ext_class
1263 {
1264 RV_ISA_CLASS_Z = 1,
1265 RV_ISA_CLASS_S,
1266 RV_ISA_CLASS_ZXM,
1267 RV_ISA_CLASS_X,
1268 RV_ISA_CLASS_UNKNOWN
1269 };
1270
1271 /* Record the strings of the prefixed extensions, and their corresponding
1272 classes. The more letters of the prefix string, the more forward it must
1273 be defined. Otherwise, the riscv_get_prefix_class will map it to the
1274 wrong classes. */
1275 struct riscv_parse_prefix_config
1276 {
1277 /* Class of the extension. */
1278 enum riscv_prefix_ext_class class;
1279
1280 /* Prefix string for error printing and internal parser usage. */
1281 const char *prefix;
1282 };
1283 static const struct riscv_parse_prefix_config parse_config[] =
1284 {
1285 {RV_ISA_CLASS_ZXM, "zxm"},
1286 {RV_ISA_CLASS_Z, "z"},
1287 {RV_ISA_CLASS_S, "s"},
1288 {RV_ISA_CLASS_X, "x"},
1289 {RV_ISA_CLASS_UNKNOWN, NULL}
1290 };
1291
1292 /* Get the prefixed name class for the extensions, the class also
1293 means the order of the prefixed extensions. */
1294
1295 static enum riscv_prefix_ext_class
1296 riscv_get_prefix_class (const char *arch)
1297 {
1298 int i = 0;
1299 while (parse_config[i].class != RV_ISA_CLASS_UNKNOWN)
1300 {
1301 if (strncmp (arch, parse_config[i].prefix,
1302 strlen (parse_config[i].prefix)) == 0)
1303 return parse_config[i].class;
1304 i++;
1305 }
1306 return RV_ISA_CLASS_UNKNOWN;
1307 }
1308
1309 /* Check KNOWN_EXTS to see if the EXT is supported. */
1310
1311 static bool
1312 riscv_known_prefixed_ext (const char *ext,
1313 struct riscv_supported_ext *known_exts)
1314 {
1315 size_t i;
1316 for (i = 0; known_exts[i].name != NULL; ++i)
1317 if (strcmp (ext, known_exts[i].name) == 0)
1318 return true;
1319 return false;
1320 }
1321
1322 /* Check whether the prefixed extension is recognized or not. Return
1323 true if recognized, otehrwise return false. */
1324
1325 static bool
1326 riscv_recognized_prefixed_ext (const char *ext)
1327 {
1328 enum riscv_prefix_ext_class class = riscv_get_prefix_class (ext);
1329 switch (class)
1330 {
1331 case RV_ISA_CLASS_Z:
1332 return riscv_known_prefixed_ext (ext, riscv_supported_std_z_ext);
1333 case RV_ISA_CLASS_ZXM:
1334 return riscv_known_prefixed_ext (ext, riscv_supported_std_zxm_ext);
1335 case RV_ISA_CLASS_S:
1336 return riscv_known_prefixed_ext (ext, riscv_supported_std_s_ext);
1337 case RV_ISA_CLASS_X:
1338 /* Only the single x is unrecognized. */
1339 if (strcmp (ext, "x") != 0)
1340 return true;
1341 default:
1342 break;
1343 }
1344 return false;
1345 }
1346
1347 /* Canonical order for single letter extensions. */
1348 static const char riscv_ext_canonical_order[] = "eigmafdqlcbkjtpvnh";
1349
1350 /* Array is used to compare the orders of standard extensions quickly. */
1351 static int riscv_ext_order[26] = {0};
1352
1353 /* Init the riscv_ext_order array. */
1354
1355 static void
1356 riscv_init_ext_order (void)
1357 {
1358 static bool inited = false;
1359 if (inited)
1360 return;
1361
1362 /* The orders of all standard extensions are positive. */
1363 int order = 1;
1364
1365 for (const char *ext = &riscv_ext_canonical_order[0]; *ext; ++ext)
1366 riscv_ext_order[(*ext - 'a')] = order++;
1367
1368 /* Some of the prefixed keyword are not single letter, so we set
1369 their prefixed orders in the riscv_compare_subsets directly,
1370 not through the riscv_ext_order. */
1371
1372 inited = true;
1373 }
1374
1375 /* Similar to the strcmp. It returns an integer less than, equal to,
1376 or greater than zero if `subset2` is found, respectively, to be less
1377 than, to match, or be greater than `subset1`.
1378
1379 The order values,
1380 Zero: Preserved keywords.
1381 Positive number: Standard extensions.
1382 Negative number: Prefixed keywords. */
1383
1384 int
1385 riscv_compare_subsets (const char *subset1, const char *subset2)
1386 {
1387 int order1 = riscv_ext_order[(*subset1 - 'a')];
1388 int order2 = riscv_ext_order[(*subset2 - 'a')];
1389
1390 /* Compare the standard extension first. */
1391 if (order1 > 0 && order2 > 0)
1392 return order1 - order2;
1393
1394 /* Set the prefixed orders to negative numbers. */
1395 enum riscv_prefix_ext_class class1 = riscv_get_prefix_class (subset1);
1396 enum riscv_prefix_ext_class class2 = riscv_get_prefix_class (subset2);
1397
1398 if (class1 != RV_ISA_CLASS_UNKNOWN)
1399 order1 = - (int) class1;
1400 if (class2 != RV_ISA_CLASS_UNKNOWN)
1401 order2 = - (int) class2;
1402
1403 if (order1 == order2)
1404 {
1405 /* Compare the standard addition z extensions. */
1406 if (class1 == RV_ISA_CLASS_Z)
1407 {
1408 order1 = riscv_ext_order[(*++subset1 - 'a')];
1409 order2 = riscv_ext_order[(*++subset2 - 'a')];
1410 if (order1 != order2)
1411 return order1 - order2;
1412 }
1413 return strcasecmp (++subset1, ++subset2);
1414 }
1415
1416 return order2 - order1;
1417 }
1418
1419 /* Find subset in the list. Return TRUE and set `current` to the subset
1420 if it is found. Otherwise, return FALSE and set `current` to the place
1421 where we should insert the subset. However, return FALSE with the NULL
1422 `current` means we should insert the subset at the head of subset list,
1423 if needed. */
1424
1425 bool
1426 riscv_lookup_subset (const riscv_subset_list_t *subset_list,
1427 const char *subset,
1428 riscv_subset_t **current)
1429 {
1430 riscv_subset_t *s, *pre_s = NULL;
1431
1432 /* If the subset is added in order, then just add it at the tail. */
1433 if (subset_list->tail != NULL
1434 && riscv_compare_subsets (subset_list->tail->name, subset) < 0)
1435 {
1436 *current = subset_list->tail;
1437 return false;
1438 }
1439
1440 for (s = subset_list->head;
1441 s != NULL;
1442 pre_s = s, s = s->next)
1443 {
1444 int cmp = riscv_compare_subsets (s->name, subset);
1445 if (cmp == 0)
1446 {
1447 *current = s;
1448 return true;
1449 }
1450 else if (cmp > 0)
1451 break;
1452 }
1453 *current = pre_s;
1454
1455 return false;
1456 }
1457
1458 /* Add the extension to the subset list. Search the
1459 list first, and then find the right place to add. */
1460
1461 void
1462 riscv_add_subset (riscv_subset_list_t *subset_list,
1463 const char *subset,
1464 int major,
1465 int minor)
1466 {
1467 riscv_subset_t *current, *new;
1468
1469 if (riscv_lookup_subset (subset_list, subset, &current))
1470 return;
1471
1472 new = xmalloc (sizeof *new);
1473 new->name = xstrdup (subset);
1474 new->major_version = major;
1475 new->minor_version = minor;
1476 new->next = NULL;
1477
1478 if (current != NULL)
1479 {
1480 new->next = current->next;
1481 current->next = new;
1482 }
1483 else
1484 {
1485 new->next = subset_list->head;
1486 subset_list->head = new;
1487 }
1488
1489 if (new->next == NULL)
1490 subset_list->tail = new;
1491 }
1492
1493 /* Get the default versions from the riscv_supported_*ext tables. */
1494
1495 static void
1496 riscv_get_default_ext_version (enum riscv_spec_class *default_isa_spec,
1497 const char *name,
1498 int *major_version,
1499 int *minor_version)
1500 {
1501 if (name == NULL
1502 || default_isa_spec == NULL
1503 || *default_isa_spec == ISA_SPEC_CLASS_NONE)
1504 return;
1505
1506 struct riscv_supported_ext *table = NULL;
1507 enum riscv_prefix_ext_class class = riscv_get_prefix_class (name);
1508 switch (class)
1509 {
1510 case RV_ISA_CLASS_ZXM: table = riscv_supported_std_zxm_ext; break;
1511 case RV_ISA_CLASS_Z: table = riscv_supported_std_z_ext; break;
1512 case RV_ISA_CLASS_S: table = riscv_supported_std_s_ext; break;
1513 case RV_ISA_CLASS_X: table = riscv_supported_vendor_x_ext; break;
1514 default:
1515 table = riscv_supported_std_ext;
1516 }
1517
1518 int i = 0;
1519 while (table != NULL && table[i].name != NULL)
1520 {
1521 if (strcmp (table[i].name, name) == 0
1522 && (table[i].isa_spec_class == ISA_SPEC_CLASS_DRAFT
1523 || table[i].isa_spec_class == *default_isa_spec))
1524 {
1525 *major_version = table[i].major_version;
1526 *minor_version = table[i].minor_version;
1527 return;
1528 }
1529 i++;
1530 }
1531 }
1532
1533 /* Find the default versions for the extension before adding them to
1534 the subset list, if their versions are RISCV_UNKNOWN_VERSION.
1535 Afterwards, report errors if we can not find their default versions. */
1536
1537 static void
1538 riscv_parse_add_subset (riscv_parse_subset_t *rps,
1539 const char *subset,
1540 int major,
1541 int minor,
1542 bool implicit)
1543 {
1544 int major_version = major;
1545 int minor_version = minor;
1546
1547 if (major_version == RISCV_UNKNOWN_VERSION
1548 || minor_version == RISCV_UNKNOWN_VERSION)
1549 riscv_get_default_ext_version (rps->isa_spec, subset,
1550 &major_version, &minor_version);
1551
1552 /* We don't care the versions of the implicit extensions. */
1553 if (!implicit
1554 && (major_version == RISCV_UNKNOWN_VERSION
1555 || minor_version == RISCV_UNKNOWN_VERSION))
1556 {
1557 if (subset[0] == 'x')
1558 rps->error_handler
1559 (_("x ISA extension `%s' must be set with the versions"),
1560 subset);
1561 /* Allow old ISA spec can recognize zicsr and zifencei. */
1562 else if (strcmp (subset, "zicsr") != 0
1563 && strcmp (subset, "zifencei") != 0)
1564 rps->error_handler
1565 (_("cannot find default versions of the ISA extension `%s'"),
1566 subset);
1567 return;
1568 }
1569
1570 riscv_add_subset (rps->subset_list, subset,
1571 major_version, minor_version);
1572 }
1573
1574 /* Release subset list. */
1575
1576 void
1577 riscv_release_subset_list (riscv_subset_list_t *subset_list)
1578 {
1579 while (subset_list->head != NULL)
1580 {
1581 riscv_subset_t *next = subset_list->head->next;
1582 free ((void *)subset_list->head->name);
1583 free (subset_list->head);
1584 subset_list->head = next;
1585 }
1586
1587 subset_list->tail = NULL;
1588
1589 if (subset_list->arch_str != NULL)
1590 {
1591 free ((void*) subset_list->arch_str);
1592 subset_list->arch_str = NULL;
1593 }
1594 }
1595
1596 /* Parsing extension version.
1597
1598 Return Value:
1599 Points to the end of version
1600
1601 Arguments:
1602 `p`: Curent parsing position.
1603 `major_version`: Parsed major version.
1604 `minor_version`: Parsed minor version. */
1605
1606 static const char *
1607 riscv_parsing_subset_version (const char *p,
1608 int *major_version,
1609 int *minor_version)
1610 {
1611 bool major_p = true;
1612 int version = 0;
1613 char np;
1614
1615 *major_version = 0;
1616 *minor_version = 0;
1617 for (; *p; ++p)
1618 {
1619 if (*p == 'p')
1620 {
1621 np = *(p + 1);
1622
1623 /* Might be beginning of `p` extension. */
1624 if (!ISDIGIT (np))
1625 break;
1626
1627 *major_version = version;
1628 major_p = false;
1629 version = 0;
1630 }
1631 else if (ISDIGIT (*p))
1632 version = (version * 10) + (*p - '0');
1633 else
1634 break;
1635 }
1636
1637 if (major_p)
1638 *major_version = version;
1639 else
1640 *minor_version = version;
1641
1642 /* We can not find any version in string. */
1643 if (*major_version == 0 && *minor_version == 0)
1644 {
1645 *major_version = RISCV_UNKNOWN_VERSION;
1646 *minor_version = RISCV_UNKNOWN_VERSION;
1647 }
1648
1649 return p;
1650 }
1651
1652 /* Parsing function for standard extensions.
1653
1654 Return Value:
1655 Points to the end of extensions.
1656
1657 Arguments:
1658 `rps`: Hooks and status for parsing extensions.
1659 `arch`: Full ISA string.
1660 `p`: Curent parsing position. */
1661
1662 static const char *
1663 riscv_parse_std_ext (riscv_parse_subset_t *rps,
1664 const char *arch,
1665 const char *p)
1666 {
1667 /* First letter must start with i, e or g. */
1668 if (*p != 'e' && *p != 'i' && *p != 'g')
1669 {
1670 rps->error_handler
1671 (_("%s: first ISA extension must be `e', `i' or `g'"),
1672 arch);
1673 return NULL;
1674 }
1675
1676 while (p != NULL && *p != '\0')
1677 {
1678 /* Stop when we parsed the known prefix class. */
1679 enum riscv_prefix_ext_class class = riscv_get_prefix_class (p);
1680 if (class != RV_ISA_CLASS_UNKNOWN)
1681 break;
1682
1683 if (*p == '_')
1684 {
1685 p++;
1686 continue;
1687 }
1688
1689 bool implicit = false;
1690 int major = RISCV_UNKNOWN_VERSION;
1691 int minor = RISCV_UNKNOWN_VERSION;
1692 char subset[2] = {0, 0};
1693
1694 subset[0] = *p;
1695
1696 /* Check if the standard extension is supported. */
1697 if (riscv_ext_order[(subset[0] - 'a')] == 0)
1698 {
1699 rps->error_handler
1700 (_("%s: unknown standard ISA extension `%c'"),
1701 arch, subset[0]);
1702 return NULL;
1703 }
1704
1705 /* Checking canonical order. */
1706 if (rps->subset_list->tail != NULL
1707 && riscv_compare_subsets (rps->subset_list->tail->name, subset) > 0)
1708 {
1709 rps->error_handler
1710 (_("%s: standard ISA extension `%c' is not "
1711 "in canonical order"), arch, subset[0]);
1712 return NULL;
1713 }
1714
1715 p = riscv_parsing_subset_version (++p, &major, &minor);
1716 /* Added g as an implicit extension. */
1717 if (subset[0] == 'g')
1718 {
1719 implicit = true;
1720 major = RISCV_UNKNOWN_VERSION;
1721 minor = RISCV_UNKNOWN_VERSION;
1722 }
1723 riscv_parse_add_subset (rps, subset, major, minor, implicit);
1724 }
1725
1726 return p;
1727 }
1728
1729 /* Parsing function for prefixed extensions.
1730
1731 Return Value:
1732 Points to the end of extension.
1733
1734 Arguments:
1735 `rps`: Hooks and status for parsing extensions.
1736 `arch`: Full ISA string.
1737 `p`: Curent parsing position. */
1738
1739 static const char *
1740 riscv_parse_prefixed_ext (riscv_parse_subset_t *rps,
1741 const char *arch,
1742 const char *p)
1743 {
1744 int major_version;
1745 int minor_version;
1746 enum riscv_prefix_ext_class class;
1747
1748 while (*p)
1749 {
1750 if (*p == '_')
1751 {
1752 p++;
1753 continue;
1754 }
1755
1756 class = riscv_get_prefix_class (p);
1757 if (class == RV_ISA_CLASS_UNKNOWN)
1758 {
1759 rps->error_handler
1760 (_("%s: unknown prefix class for the ISA extension `%s'"),
1761 arch, p);
1762 return NULL;
1763 }
1764
1765 char *subset = xstrdup (p);
1766 char *q = subset;
1767 const char *end_of_version;
1768
1769 /* Extract the whole prefixed extension by '_'. */
1770 while (*++q != '\0' && *q != '_')
1771 ;
1772 /* Look forward to the first letter which is not <major>p<minor>. */
1773 bool find_any_version = false;
1774 bool find_minor_version = false;
1775 while (1)
1776 {
1777 q--;
1778 if (ISDIGIT (*q))
1779 find_any_version = true;
1780 else if (find_any_version
1781 && !find_minor_version
1782 && *q == 'p'
1783 && ISDIGIT (*(q - 1)))
1784 find_minor_version = true;
1785 else
1786 break;
1787 }
1788 q++;
1789
1790 /* Check if the end of extension is 'p' or not. If yes, then
1791 the second letter from the end cannot be number. */
1792 if (*(q - 1) == 'p' && ISDIGIT (*(q - 2)))
1793 {
1794 *q = '\0';
1795 rps->error_handler
1796 (_("%s: invalid prefixed ISA extension `%s' ends with <number>p"),
1797 arch, subset);
1798 free (subset);
1799 return NULL;
1800 }
1801
1802 end_of_version =
1803 riscv_parsing_subset_version (q, &major_version, &minor_version);
1804 *q = '\0';
1805 if (end_of_version == NULL)
1806 {
1807 free (subset);
1808 return NULL;
1809 }
1810
1811 /* Check that the extension name is well-formed. */
1812 if (rps->check_unknown_prefixed_ext
1813 && !riscv_recognized_prefixed_ext (subset))
1814 {
1815 rps->error_handler
1816 (_("%s: unknown prefixed ISA extension `%s'"),
1817 arch, subset);
1818 free (subset);
1819 return NULL;
1820 }
1821
1822 riscv_parse_add_subset (rps, subset,
1823 major_version,
1824 minor_version, false);
1825 p += end_of_version - subset;
1826 free (subset);
1827
1828 if (*p != '\0' && *p != '_')
1829 {
1830 rps->error_handler
1831 (_("%s: prefixed ISA extension must separate with _"),
1832 arch);
1833 return NULL;
1834 }
1835 }
1836
1837 return p;
1838 }
1839
1840 /* Add the implicit extensions. */
1841
1842 static void
1843 riscv_parse_add_implicit_subsets (riscv_parse_subset_t *rps)
1844 {
1845 struct riscv_implicit_subset *t = riscv_implicit_subsets;
1846 for (; t->subset_name; t++)
1847 {
1848 riscv_subset_t *subset = NULL;
1849 if (riscv_lookup_subset (rps->subset_list, t->subset_name, &subset)
1850 && t->check_func (t->implicit_name, subset))
1851 riscv_parse_add_subset (rps, t->implicit_name,
1852 RISCV_UNKNOWN_VERSION,
1853 RISCV_UNKNOWN_VERSION, true);
1854 }
1855 }
1856
1857 /* Check extensions conflicts. */
1858
1859 static bool
1860 riscv_parse_check_conflicts (riscv_parse_subset_t *rps)
1861 {
1862 riscv_subset_t *subset = NULL;
1863 int xlen = *rps->xlen;
1864 bool no_conflict = true;
1865
1866 if (riscv_lookup_subset (rps->subset_list, "e", &subset)
1867 && xlen > 32)
1868 {
1869 rps->error_handler
1870 (_("rv%d does not support the `e' extension"), xlen);
1871 no_conflict = false;
1872 }
1873 if (riscv_lookup_subset (rps->subset_list, "q", &subset)
1874 && (subset->major_version < 2 || (subset->major_version == 2
1875 && subset->minor_version < 2))
1876 && xlen < 64)
1877 {
1878 rps->error_handler (_("rv%d does not support the `q' extension"), xlen);
1879 no_conflict = false;
1880 }
1881 if (riscv_lookup_subset (rps->subset_list, "zfinx", &subset)
1882 && riscv_lookup_subset (rps->subset_list, "f", &subset))
1883 {
1884 rps->error_handler
1885 (_("`zfinx' is conflict with the `f/d/q/zfh/zfhmin' extension"));
1886 no_conflict = false;
1887 }
1888
1889 bool support_zve = false;
1890 bool support_zvl = false;
1891 riscv_subset_t *s = rps->subset_list->head;
1892 for (; s != NULL; s = s->next)
1893 {
1894 if (!support_zve
1895 && strncmp (s->name, "zve", 3) == 0)
1896 support_zve = true;
1897 if (!support_zvl
1898 && strncmp (s->name, "zvl", 3) == 0)
1899 support_zvl = true;
1900 if (support_zve && support_zvl)
1901 break;
1902 }
1903 if (support_zvl && !support_zve)
1904 {
1905 rps->error_handler
1906 (_("zvl*b extensions need to enable either `v' or `zve' extension"));
1907 no_conflict = false;
1908 }
1909
1910 return no_conflict;
1911 }
1912
1913 /* Set the default subset list according to the default_enable field
1914 of riscv_supported_*ext tables. */
1915
1916 static void
1917 riscv_set_default_arch (riscv_parse_subset_t *rps)
1918 {
1919 unsigned long enable = EXT_DEFAULT;
1920 int i, j;
1921 for (i = 0; riscv_all_supported_ext[i] != NULL; i++)
1922 {
1923 const struct riscv_supported_ext *table = riscv_all_supported_ext[i];
1924 for (j = 0; table[j].name != NULL; j++)
1925 {
1926 bool implicit = false;
1927 if (strcmp (table[j].name, "g") == 0)
1928 implicit = true;
1929 if (table[j].default_enable & enable)
1930 riscv_parse_add_subset (rps, table[j].name,
1931 RISCV_UNKNOWN_VERSION,
1932 RISCV_UNKNOWN_VERSION, implicit);
1933 }
1934 }
1935 }
1936
1937 /* Function for parsing ISA string.
1938
1939 Return Value:
1940 Return TRUE on success.
1941
1942 Arguments:
1943 `rps`: Hooks and status for parsing extensions.
1944 `arch`: Full ISA string. */
1945
1946 bool
1947 riscv_parse_subset (riscv_parse_subset_t *rps,
1948 const char *arch)
1949 {
1950 const char *p;
1951
1952 /* Init the riscv_ext_order array to compare the order of extensions
1953 quickly. */
1954 riscv_init_ext_order ();
1955
1956 if (arch == NULL)
1957 {
1958 riscv_set_default_arch (rps);
1959 riscv_parse_add_implicit_subsets (rps);
1960 return riscv_parse_check_conflicts (rps);
1961 }
1962
1963 for (p = arch; *p != '\0'; p++)
1964 {
1965 if (ISUPPER (*p))
1966 {
1967 rps->error_handler
1968 (_("%s: ISA string cannot contain uppercase letters"),
1969 arch);
1970 return false;
1971 }
1972 }
1973
1974 p = arch;
1975 if (startswith (p, "rv32"))
1976 {
1977 *rps->xlen = 32;
1978 p += 4;
1979 }
1980 else if (startswith (p, "rv64"))
1981 {
1982 *rps->xlen = 64;
1983 p += 4;
1984 }
1985 else
1986 {
1987 /* ISA string shouldn't be NULL or empty here. For linker,
1988 it might be empty when we failed to merge the ISA string
1989 in the riscv_merge_attributes. For assembler, we might
1990 give an empty string by .attribute arch, "" or -march=.
1991 However, We have already issued the correct error message
1992 in another side, so do not issue this error when the ISA
1993 string is empty. */
1994 if (strlen (arch))
1995 rps->error_handler (
1996 _("%s: ISA string must begin with rv32 or rv64"),
1997 arch);
1998 return false;
1999 }
2000
2001 /* Parsing standard extension. */
2002 p = riscv_parse_std_ext (rps, arch, p);
2003
2004 if (p == NULL)
2005 return false;
2006
2007 /* Parse prefixed extensions. */
2008 p = riscv_parse_prefixed_ext (rps, arch, p);
2009
2010 if (p == NULL)
2011 return false;
2012
2013 /* Finally add implicit extensions according to the current
2014 extensions. */
2015 riscv_parse_add_implicit_subsets (rps);
2016
2017 /* Check the conflicts. */
2018 return riscv_parse_check_conflicts (rps);
2019 }
2020
2021 /* Return the number of digits for the input. */
2022
2023 size_t
2024 riscv_estimate_digit (unsigned num)
2025 {
2026 size_t digit = 0;
2027 if (num == 0)
2028 return 1;
2029
2030 for (digit = 0; num ; num /= 10)
2031 digit++;
2032
2033 return digit;
2034 }
2035
2036 /* Auxiliary function to estimate string length of subset list. */
2037
2038 static size_t
2039 riscv_estimate_arch_strlen1 (const riscv_subset_t *subset)
2040 {
2041 if (subset == NULL)
2042 return 6; /* For rv32/rv64/rv128 and string terminator. */
2043
2044 return riscv_estimate_arch_strlen1 (subset->next)
2045 + strlen (subset->name)
2046 + riscv_estimate_digit (subset->major_version)
2047 + 1 /* For version seperator 'p'. */
2048 + riscv_estimate_digit (subset->minor_version)
2049 + 1 /* For underscore. */;
2050 }
2051
2052 /* Estimate the string length of this subset list. */
2053
2054 static size_t
2055 riscv_estimate_arch_strlen (const riscv_subset_list_t *subset_list)
2056 {
2057 return riscv_estimate_arch_strlen1 (subset_list->head);
2058 }
2059
2060 /* Auxiliary function to convert subset info to string. */
2061
2062 static void
2063 riscv_arch_str1 (riscv_subset_t *subset,
2064 char *attr_str, char *buf, size_t bufsz)
2065 {
2066 const char *underline = "_";
2067 riscv_subset_t *subset_t = subset;
2068
2069 if (subset_t == NULL)
2070 return;
2071
2072 /* No underline between rvXX and i/e. */
2073 if ((strcasecmp (subset_t->name, "i") == 0)
2074 || (strcasecmp (subset_t->name, "e") == 0))
2075 underline = "";
2076
2077 snprintf (buf, bufsz, "%s%s%dp%d",
2078 underline,
2079 subset_t->name,
2080 subset_t->major_version,
2081 subset_t->minor_version);
2082
2083 strncat (attr_str, buf, bufsz);
2084
2085 /* Skip 'i' extension after 'e', or skip extensions which
2086 versions are unknown. */
2087 while (subset_t->next
2088 && ((strcmp (subset_t->name, "e") == 0
2089 && strcmp (subset_t->next->name, "i") == 0)
2090 || subset_t->next->major_version == RISCV_UNKNOWN_VERSION
2091 || subset_t->next->minor_version == RISCV_UNKNOWN_VERSION))
2092 subset_t = subset_t->next;
2093
2094 riscv_arch_str1 (subset_t->next, attr_str, buf, bufsz);
2095 }
2096
2097 /* Convert subset information into string with explicit versions. */
2098
2099 char *
2100 riscv_arch_str (unsigned xlen, const riscv_subset_list_t *subset)
2101 {
2102 size_t arch_str_len = riscv_estimate_arch_strlen (subset);
2103 char *attr_str = xmalloc (arch_str_len);
2104 char *buf = xmalloc (arch_str_len);
2105
2106 snprintf (attr_str, arch_str_len, "rv%u", xlen);
2107
2108 riscv_arch_str1 (subset->head, attr_str, buf, arch_str_len);
2109 free (buf);
2110
2111 return attr_str;
2112 }
2113
2114 /* Copy the subset in the subset list. */
2115
2116 static struct riscv_subset_t *
2117 riscv_copy_subset (riscv_subset_list_t *subset_list,
2118 riscv_subset_t *subset)
2119 {
2120 if (subset == NULL)
2121 return NULL;
2122
2123 riscv_subset_t *new = xmalloc (sizeof *new);
2124 new->name = xstrdup (subset->name);
2125 new->major_version = subset->major_version;
2126 new->minor_version = subset->minor_version;
2127 new->next = riscv_copy_subset (subset_list, subset->next);
2128
2129 if (subset->next == NULL)
2130 subset_list->tail = new;
2131
2132 return new;
2133 }
2134
2135 /* Copy the subset list. */
2136
2137 riscv_subset_list_t *
2138 riscv_copy_subset_list (riscv_subset_list_t *subset_list)
2139 {
2140 riscv_subset_list_t *new = xmalloc (sizeof *new);
2141 new->head = riscv_copy_subset (new, subset_list->head);
2142 new->arch_str = strdup (subset_list->arch_str);
2143 return new;
2144 }
2145
2146 /* Remove the SUBSET from the subset list. */
2147
2148 static void
2149 riscv_remove_subset (riscv_subset_list_t *subset_list,
2150 const char *subset)
2151 {
2152 riscv_subset_t *current = subset_list->head;
2153 riscv_subset_t *pre = NULL;
2154 for (; current != NULL; pre = current, current = current->next)
2155 {
2156 if (strcmp (current->name, subset) == 0)
2157 {
2158 if (pre == NULL)
2159 subset_list->head = current->next;
2160 else
2161 pre->next = current->next;
2162 if (current->next == NULL)
2163 subset_list->tail = pre;
2164 free ((void *) current->name);
2165 free (current);
2166 break;
2167 }
2168 }
2169 }
2170
2171 /* Add/Remove an extension to/from the subset list. This is used for
2172 the .option rvc or norvc, and .option arch directives. */
2173
2174 bool
2175 riscv_update_subset (riscv_parse_subset_t *rps,
2176 const char *str)
2177 {
2178 const char *p = str;
2179
2180 do
2181 {
2182 int major_version = RISCV_UNKNOWN_VERSION;
2183 int minor_version = RISCV_UNKNOWN_VERSION;
2184
2185 bool removed = false;
2186 switch (*p)
2187 {
2188 case '+': removed = false; break;
2189 case '-': removed = true; break;
2190 default:
2191 riscv_release_subset_list (rps->subset_list);
2192 return riscv_parse_subset (rps, p);
2193 }
2194 ++p;
2195
2196 char *subset = xstrdup (p);
2197 char *q = subset;
2198 const char *end_of_version;
2199 /* Extract the whole prefixed extension by ','. */
2200 while (*q != '\0' && *q != ',')
2201 q++;
2202
2203 /* Look forward to the first letter which is not <major>p<minor>. */
2204 bool find_any_version = false;
2205 bool find_minor_version = false;
2206 size_t len = q - subset;
2207 size_t i;
2208 for (i = len; i > 0; i--)
2209 {
2210 q--;
2211 if (ISDIGIT (*q))
2212 find_any_version = true;
2213 else if (find_any_version
2214 && !find_minor_version
2215 && *q == 'p'
2216 && ISDIGIT (*(q - 1)))
2217 find_minor_version = true;
2218 else
2219 break;
2220 }
2221 if (len > 0)
2222 q++;
2223
2224 /* Check if the end of extension is 'p' or not. If yes, then
2225 the second letter from the end cannot be number. */
2226 if (len > 1 && *(q - 1) == 'p' && ISDIGIT (*(q - 2)))
2227 {
2228 *q = '\0';
2229 rps->error_handler
2230 (_("invalid ISA extension ends with <number>p "
2231 "in .option arch `%s'"), str);
2232 free (subset);
2233 return false;
2234 }
2235
2236 end_of_version =
2237 riscv_parsing_subset_version (q, &major_version, &minor_version);
2238 *q = '\0';
2239 if (end_of_version == NULL)
2240 {
2241 free (subset);
2242 return false;
2243 }
2244
2245 if (strlen (subset) == 0
2246 || (strlen (subset) == 1
2247 && riscv_ext_order[(*subset - 'a')] == 0)
2248 || (strlen (subset) > 1
2249 && rps->check_unknown_prefixed_ext
2250 && !riscv_recognized_prefixed_ext (subset)))
2251 {
2252 rps->error_handler
2253 (_("unknown ISA extension `%s' in .option arch `%s'"),
2254 subset, str);
2255 free (subset);
2256 return false;
2257 }
2258
2259 if (strcmp (subset, "i") == 0
2260 || strcmp (subset, "e") == 0
2261 || strcmp (subset, "g") == 0)
2262 {
2263 rps->error_handler
2264 (_("cannot + or - base extension `%s' in .option "
2265 "arch `%s'"), subset, str);
2266 free (subset);
2267 return false;
2268 }
2269
2270 if (removed)
2271 riscv_remove_subset (rps->subset_list, subset);
2272 else
2273 riscv_parse_add_subset (rps, subset, major_version, minor_version, true);
2274 p += end_of_version - subset;
2275 free (subset);
2276 }
2277 while (*p++ == ',');
2278
2279 riscv_parse_add_implicit_subsets (rps);
2280 return riscv_parse_check_conflicts (rps);
2281 }
2282
2283 /* Check if the FEATURE subset is supported or not in the subset list.
2284 Return true if it is supported; Otherwise, return false. */
2285
2286 bool
2287 riscv_subset_supports (riscv_parse_subset_t *rps,
2288 const char *feature)
2289 {
2290 struct riscv_subset_t *subset;
2291 return riscv_lookup_subset (rps->subset_list, feature, &subset);
2292 }
2293
2294 /* Each instuction is belonged to an instruction class INSN_CLASS_*.
2295 Call riscv_subset_supports to make sure if the instuction is valid. */
2296
2297 bool
2298 riscv_multi_subset_supports (riscv_parse_subset_t *rps,
2299 enum riscv_insn_class insn_class)
2300 {
2301 switch (insn_class)
2302 {
2303 case INSN_CLASS_I:
2304 return riscv_subset_supports (rps, "i");
2305 case INSN_CLASS_ZICBOM:
2306 return riscv_subset_supports (rps, "zicbom");
2307 case INSN_CLASS_ZICBOP:
2308 return riscv_subset_supports (rps, "zicbop");
2309 case INSN_CLASS_ZICBOZ:
2310 return riscv_subset_supports (rps, "zicboz");
2311 case INSN_CLASS_ZICSR:
2312 return riscv_subset_supports (rps, "zicsr");
2313 case INSN_CLASS_ZIFENCEI:
2314 return riscv_subset_supports (rps, "zifencei");
2315 case INSN_CLASS_ZIHINTPAUSE:
2316 return riscv_subset_supports (rps, "zihintpause");
2317 case INSN_CLASS_M:
2318 return riscv_subset_supports (rps, "m");
2319 case INSN_CLASS_ZMMUL:
2320 return riscv_subset_supports (rps, "zmmul");
2321 case INSN_CLASS_A:
2322 return riscv_subset_supports (rps, "a");
2323 case INSN_CLASS_ZAWRS:
2324 return riscv_subset_supports (rps, "zawrs");
2325 case INSN_CLASS_F:
2326 return riscv_subset_supports (rps, "f");
2327 case INSN_CLASS_D:
2328 return riscv_subset_supports (rps, "d");
2329 case INSN_CLASS_Q:
2330 return riscv_subset_supports (rps, "q");
2331 case INSN_CLASS_C:
2332 return riscv_subset_supports (rps, "c");
2333 case INSN_CLASS_F_AND_C:
2334 return (riscv_subset_supports (rps, "f")
2335 && riscv_subset_supports (rps, "c"));
2336 case INSN_CLASS_D_AND_C:
2337 return (riscv_subset_supports (rps, "d")
2338 && riscv_subset_supports (rps, "c"));
2339 case INSN_CLASS_F_INX:
2340 return (riscv_subset_supports (rps, "f")
2341 || riscv_subset_supports (rps, "zfinx"));
2342 case INSN_CLASS_D_INX:
2343 return (riscv_subset_supports (rps, "d")
2344 || riscv_subset_supports (rps, "zdinx"));
2345 case INSN_CLASS_Q_INX:
2346 return (riscv_subset_supports (rps, "q")
2347 || riscv_subset_supports (rps, "zqinx"));
2348 case INSN_CLASS_ZFH_INX:
2349 return (riscv_subset_supports (rps, "zfh")
2350 || riscv_subset_supports (rps, "zhinx"));
2351 case INSN_CLASS_ZFHMIN:
2352 return riscv_subset_supports (rps, "zfhmin");
2353 case INSN_CLASS_ZFHMIN_INX:
2354 return (riscv_subset_supports (rps, "zfhmin")
2355 || riscv_subset_supports (rps, "zhinxmin"));
2356 case INSN_CLASS_ZFHMIN_AND_D_INX:
2357 return ((riscv_subset_supports (rps, "zfhmin")
2358 && riscv_subset_supports (rps, "d"))
2359 || (riscv_subset_supports (rps, "zhinxmin")
2360 && riscv_subset_supports (rps, "zdinx")));
2361 case INSN_CLASS_ZFHMIN_AND_Q_INX:
2362 return ((riscv_subset_supports (rps, "zfhmin")
2363 && riscv_subset_supports (rps, "q"))
2364 || (riscv_subset_supports (rps, "zhinxmin")
2365 && riscv_subset_supports (rps, "zqinx")));
2366 case INSN_CLASS_ZBA:
2367 return riscv_subset_supports (rps, "zba");
2368 case INSN_CLASS_ZBB:
2369 return riscv_subset_supports (rps, "zbb");
2370 case INSN_CLASS_ZBC:
2371 return riscv_subset_supports (rps, "zbc");
2372 case INSN_CLASS_ZBS:
2373 return riscv_subset_supports (rps, "zbs");
2374 case INSN_CLASS_ZBKB:
2375 return riscv_subset_supports (rps, "zbkb");
2376 case INSN_CLASS_ZBKC:
2377 return riscv_subset_supports (rps, "zbkc");
2378 case INSN_CLASS_ZBKX:
2379 return riscv_subset_supports (rps, "zbkx");
2380 case INSN_CLASS_ZBB_OR_ZBKB:
2381 return (riscv_subset_supports (rps, "zbb")
2382 || riscv_subset_supports (rps, "zbkb"));
2383 case INSN_CLASS_ZBC_OR_ZBKC:
2384 return (riscv_subset_supports (rps, "zbc")
2385 || riscv_subset_supports (rps, "zbkc"));
2386 case INSN_CLASS_ZKND:
2387 return riscv_subset_supports (rps, "zknd");
2388 case INSN_CLASS_ZKNE:
2389 return riscv_subset_supports (rps, "zkne");
2390 case INSN_CLASS_ZKNH:
2391 return riscv_subset_supports (rps, "zknh");
2392 case INSN_CLASS_ZKND_OR_ZKNE:
2393 return (riscv_subset_supports (rps, "zknd")
2394 || riscv_subset_supports (rps, "zkne"));
2395 case INSN_CLASS_ZKSED:
2396 return riscv_subset_supports (rps, "zksed");
2397 case INSN_CLASS_ZKSH:
2398 return riscv_subset_supports (rps, "zksh");
2399 case INSN_CLASS_V:
2400 return (riscv_subset_supports (rps, "v")
2401 || riscv_subset_supports (rps, "zve64x")
2402 || riscv_subset_supports (rps, "zve32x"));
2403 case INSN_CLASS_ZVEF:
2404 return (riscv_subset_supports (rps, "v")
2405 || riscv_subset_supports (rps, "zve64d")
2406 || riscv_subset_supports (rps, "zve64f")
2407 || riscv_subset_supports (rps, "zve32f"));
2408 case INSN_CLASS_SVINVAL:
2409 return riscv_subset_supports (rps, "svinval");
2410 case INSN_CLASS_H:
2411 return riscv_subset_supports (rps, "h");
2412 case INSN_CLASS_XTHEADBA:
2413 return riscv_subset_supports (rps, "xtheadba");
2414 case INSN_CLASS_XTHEADBB:
2415 return riscv_subset_supports (rps, "xtheadbb");
2416 case INSN_CLASS_XTHEADBS:
2417 return riscv_subset_supports (rps, "xtheadbs");
2418 case INSN_CLASS_XTHEADCMO:
2419 return riscv_subset_supports (rps, "xtheadcmo");
2420 case INSN_CLASS_XTHEADCONDMOV:
2421 return riscv_subset_supports (rps, "xtheadcondmov");
2422 case INSN_CLASS_XTHEADFMEMIDX:
2423 return riscv_subset_supports (rps, "xtheadfmemidx");
2424 case INSN_CLASS_XTHEADFMV:
2425 return riscv_subset_supports (rps, "xtheadfmv");
2426 case INSN_CLASS_XTHEADINT:
2427 return riscv_subset_supports (rps, "xtheadint");
2428 case INSN_CLASS_XTHEADMAC:
2429 return riscv_subset_supports (rps, "xtheadmac");
2430 case INSN_CLASS_XTHEADMEMIDX:
2431 return riscv_subset_supports (rps, "xtheadmemidx");
2432 case INSN_CLASS_XTHEADMEMPAIR:
2433 return riscv_subset_supports (rps, "xtheadmempair");
2434 case INSN_CLASS_XTHEADSYNC:
2435 return riscv_subset_supports (rps, "xtheadsync");
2436 default:
2437 rps->error_handler
2438 (_("internal: unreachable INSN_CLASS_*"));
2439 return false;
2440 }
2441 }
2442
2443 /* Each instuction is belonged to an instruction class INSN_CLASS_*.
2444 Call riscv_subset_supports_ext to determine the missing extension. */
2445
2446 const char *
2447 riscv_multi_subset_supports_ext (riscv_parse_subset_t *rps,
2448 enum riscv_insn_class insn_class)
2449 {
2450 switch (insn_class)
2451 {
2452 case INSN_CLASS_I:
2453 return "i";
2454 case INSN_CLASS_ZICBOM:
2455 return "zicbom";
2456 case INSN_CLASS_ZICBOP:
2457 return "zicbop";
2458 case INSN_CLASS_ZICBOZ:
2459 return "zicboz";
2460 case INSN_CLASS_ZICSR:
2461 return "zicsr";
2462 case INSN_CLASS_ZIFENCEI:
2463 return "zifencei";
2464 case INSN_CLASS_ZIHINTPAUSE:
2465 return "zihintpause";
2466 case INSN_CLASS_M:
2467 return "m";
2468 case INSN_CLASS_ZMMUL:
2469 return _ ("m' or `zmmul");
2470 case INSN_CLASS_A:
2471 return "a";
2472 case INSN_CLASS_ZAWRS:
2473 return "zawrs";
2474 case INSN_CLASS_F:
2475 return "f";
2476 case INSN_CLASS_D:
2477 return "d";
2478 case INSN_CLASS_Q:
2479 return "q";
2480 case INSN_CLASS_C:
2481 return "c";
2482 case INSN_CLASS_F_AND_C:
2483 if (!riscv_subset_supports (rps, "f")
2484 && !riscv_subset_supports (rps, "c"))
2485 return _("f' and `c");
2486 else if (!riscv_subset_supports (rps, "f"))
2487 return "f";
2488 else
2489 return "c";
2490 case INSN_CLASS_D_AND_C:
2491 if (!riscv_subset_supports (rps, "d")
2492 && !riscv_subset_supports (rps, "c"))
2493 return _("d' and `c");
2494 else if (!riscv_subset_supports (rps, "d"))
2495 return "d";
2496 else
2497 return "c";
2498 case INSN_CLASS_F_INX:
2499 return _("f' or `zfinx");
2500 case INSN_CLASS_D_INX:
2501 return _("d' or `zdinx");
2502 case INSN_CLASS_Q_INX:
2503 return _("q' or `zqinx");
2504 case INSN_CLASS_ZFH_INX:
2505 return _("zfh' or `zhinx");
2506 case INSN_CLASS_ZFHMIN:
2507 return "zfhmin";
2508 case INSN_CLASS_ZFHMIN_INX:
2509 return _("zfhmin' or `zhinxmin");
2510 case INSN_CLASS_ZFHMIN_AND_D_INX:
2511 if (riscv_subset_supports (rps, "zfhmin"))
2512 return "d";
2513 else if (riscv_subset_supports (rps, "d"))
2514 return "zfhmin";
2515 else if (riscv_subset_supports (rps, "zhinxmin"))
2516 return "zdinx";
2517 else if (riscv_subset_supports (rps, "zdinx"))
2518 return "zhinxmin";
2519 else
2520 return _("zfhmin' and `d', or `zhinxmin' and `zdinx");
2521 case INSN_CLASS_ZFHMIN_AND_Q_INX:
2522 if (riscv_subset_supports (rps, "zfhmin"))
2523 return "q";
2524 else if (riscv_subset_supports (rps, "q"))
2525 return "zfhmin";
2526 else if (riscv_subset_supports (rps, "zhinxmin"))
2527 return "zqinx";
2528 else if (riscv_subset_supports (rps, "zqinx"))
2529 return "zhinxmin";
2530 else
2531 return _("zfhmin' and `q', or `zhinxmin' and `zqinx");
2532 case INSN_CLASS_ZBA:
2533 return "zba";
2534 case INSN_CLASS_ZBB:
2535 return "zbb";
2536 case INSN_CLASS_ZBC:
2537 return "zbc";
2538 case INSN_CLASS_ZBS:
2539 return "zbs";
2540 case INSN_CLASS_ZBKB:
2541 return "zbkb";
2542 case INSN_CLASS_ZBKC:
2543 return "zbkc";
2544 case INSN_CLASS_ZBKX:
2545 return "zbkx";
2546 case INSN_CLASS_ZBB_OR_ZBKB:
2547 return _("zbb' or `zbkb");
2548 case INSN_CLASS_ZBC_OR_ZBKC:
2549 return _("zbc' or `zbkc");
2550 case INSN_CLASS_ZKND:
2551 return "zknd";
2552 case INSN_CLASS_ZKNE:
2553 return "zkne";
2554 case INSN_CLASS_ZKNH:
2555 return "zknh";
2556 case INSN_CLASS_ZKND_OR_ZKNE:
2557 return _("zknd' or `zkne");
2558 case INSN_CLASS_ZKSED:
2559 return "zksed";
2560 case INSN_CLASS_ZKSH:
2561 return "zksh";
2562 case INSN_CLASS_V:
2563 return _("v' or `zve64x' or `zve32x");
2564 case INSN_CLASS_ZVEF:
2565 return _("v' or `zve64d' or `zve64f' or `zve32f");
2566 case INSN_CLASS_SVINVAL:
2567 return "svinval";
2568 case INSN_CLASS_H:
2569 return _("h");
2570 case INSN_CLASS_XTHEADBA:
2571 return "xtheadba";
2572 case INSN_CLASS_XTHEADBB:
2573 return "xtheadbb";
2574 case INSN_CLASS_XTHEADBS:
2575 return "xtheadbs";
2576 case INSN_CLASS_XTHEADCMO:
2577 return "xtheadcmo";
2578 case INSN_CLASS_XTHEADCONDMOV:
2579 return "xtheadcondmov";
2580 case INSN_CLASS_XTHEADFMEMIDX:
2581 return "xtheadfmemidx";
2582 case INSN_CLASS_XTHEADFMV:
2583 return "xtheadfmv";
2584 case INSN_CLASS_XTHEADINT:
2585 return "xtheadint";
2586 case INSN_CLASS_XTHEADMAC:
2587 return "xtheadmac";
2588 case INSN_CLASS_XTHEADMEMIDX:
2589 return "xtheadmemidx";
2590 case INSN_CLASS_XTHEADMEMPAIR:
2591 return "xtheadmempair";
2592 case INSN_CLASS_XTHEADSYNC:
2593 return "xtheadsync";
2594 default:
2595 rps->error_handler
2596 (_("internal: unreachable INSN_CLASS_*"));
2597 return NULL;
2598 }
2599 }