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