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