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