]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blob - bfd/elfxx-riscv.c
RISC-V: Support rvv extension with released version 1.0.
[thirdparty/binutils-gdb.git] / bfd / elfxx-riscv.c
1 /* RISC-V-specific support for ELF.
2 Copyright (C) 2011-2021 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 3, /* 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 2, /* 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 4, /* 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 2, /* 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 4, /* 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 2, /* 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 4, /* 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 2, /* 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 4, /* 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 2, /* 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 4, /* 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 2, /* 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 2, /* 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 4, /* 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 4, /* 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 2, /* 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 2, /* 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 2, /* 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 2, /* 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 2, /* 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 2, /* 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 2, /* 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 2, /* 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 2, /* 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 2, /* 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 2, /* 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 2, /* 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 3, /* 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 0, /* 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 1, /* 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 2, /* 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 4, /* 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 0, /* 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 1, /* 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 2, /* 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 4, /* 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 /* GNU extension to record C++ vtable hierarchy */
603 HOWTO (R_RISCV_GNU_VTINHERIT, /* type */
604 0, /* rightshift */
605 4, /* size */
606 0, /* bitsize */
607 false, /* pc_relative */
608 0, /* bitpos */
609 complain_overflow_dont, /* complain_on_overflow */
610 NULL, /* special_function */
611 "R_RISCV_GNU_VTINHERIT", /* name */
612 false, /* partial_inplace */
613 0, /* src_mask */
614 0, /* dst_mask */
615 false), /* pcrel_offset */
616
617 /* GNU extension to record C++ vtable member usage */
618 HOWTO (R_RISCV_GNU_VTENTRY, /* type */
619 0, /* rightshift */
620 4, /* size */
621 0, /* bitsize */
622 false, /* pc_relative */
623 0, /* bitpos */
624 complain_overflow_dont, /* complain_on_overflow */
625 _bfd_elf_rel_vtable_reloc_fn, /* special_function */
626 "R_RISCV_GNU_VTENTRY", /* name */
627 false, /* partial_inplace */
628 0, /* src_mask */
629 0, /* dst_mask */
630 false), /* pcrel_offset */
631
632 /* Indicates an alignment statement. The addend field encodes how many
633 bytes of NOPs follow the statement. The desired alignment is the
634 addend rounded up to the next power of two. */
635 HOWTO (R_RISCV_ALIGN, /* type */
636 0, /* rightshift */
637 3, /* size */
638 0, /* bitsize */
639 false, /* pc_relative */
640 0, /* bitpos */
641 complain_overflow_dont, /* complain_on_overflow */
642 bfd_elf_generic_reloc, /* special_function */
643 "R_RISCV_ALIGN", /* name */
644 false, /* partial_inplace */
645 0, /* src_mask */
646 0, /* dst_mask */
647 false), /* pcrel_offset */
648
649 /* 8-bit PC-relative branch offset. */
650 HOWTO (R_RISCV_RVC_BRANCH, /* type */
651 0, /* rightshift */
652 1, /* size */
653 16, /* bitsize */
654 true, /* pc_relative */
655 0, /* bitpos */
656 complain_overflow_signed, /* complain_on_overflow */
657 bfd_elf_generic_reloc, /* special_function */
658 "R_RISCV_RVC_BRANCH", /* name */
659 false, /* partial_inplace */
660 0, /* src_mask */
661 ENCODE_CBTYPE_IMM (-1U), /* dst_mask */
662 true), /* pcrel_offset */
663
664 /* 11-bit PC-relative jump offset. */
665 HOWTO (R_RISCV_RVC_JUMP, /* type */
666 0, /* rightshift */
667 1, /* size */
668 16, /* bitsize */
669 true, /* pc_relative */
670 0, /* bitpos */
671 complain_overflow_dont, /* complain_on_overflow */
672 bfd_elf_generic_reloc, /* special_function */
673 "R_RISCV_RVC_JUMP", /* name */
674 false, /* partial_inplace */
675 0, /* src_mask */
676 ENCODE_CJTYPE_IMM (-1U), /* dst_mask */
677 true), /* pcrel_offset */
678
679 /* High 6 bits of 18-bit absolute address. */
680 HOWTO (R_RISCV_RVC_LUI, /* type */
681 0, /* rightshift */
682 1, /* size */
683 16, /* bitsize */
684 false, /* pc_relative */
685 0, /* bitpos */
686 complain_overflow_dont, /* complain_on_overflow */
687 bfd_elf_generic_reloc, /* special_function */
688 "R_RISCV_RVC_LUI", /* name */
689 false, /* partial_inplace */
690 0, /* src_mask */
691 ENCODE_CITYPE_IMM (-1U), /* dst_mask */
692 false), /* pcrel_offset */
693
694 /* GP-relative load. */
695 HOWTO (R_RISCV_GPREL_I, /* type */
696 0, /* rightshift */
697 2, /* size */
698 32, /* bitsize */
699 false, /* pc_relative */
700 0, /* bitpos */
701 complain_overflow_dont, /* complain_on_overflow */
702 bfd_elf_generic_reloc, /* special_function */
703 "R_RISCV_GPREL_I", /* name */
704 false, /* partial_inplace */
705 0, /* src_mask */
706 ENCODE_ITYPE_IMM (-1U), /* dst_mask */
707 false), /* pcrel_offset */
708
709 /* GP-relative store. */
710 HOWTO (R_RISCV_GPREL_S, /* type */
711 0, /* rightshift */
712 2, /* size */
713 32, /* bitsize */
714 false, /* pc_relative */
715 0, /* bitpos */
716 complain_overflow_dont, /* complain_on_overflow */
717 bfd_elf_generic_reloc, /* special_function */
718 "R_RISCV_GPREL_S", /* name */
719 false, /* partial_inplace */
720 0, /* src_mask */
721 ENCODE_STYPE_IMM (-1U), /* dst_mask */
722 false), /* pcrel_offset */
723
724 /* TP-relative TLS LE load. */
725 HOWTO (R_RISCV_TPREL_I, /* type */
726 0, /* rightshift */
727 2, /* size */
728 32, /* bitsize */
729 false, /* pc_relative */
730 0, /* bitpos */
731 complain_overflow_signed, /* complain_on_overflow */
732 bfd_elf_generic_reloc, /* special_function */
733 "R_RISCV_TPREL_I", /* name */
734 false, /* partial_inplace */
735 0, /* src_mask */
736 ENCODE_ITYPE_IMM (-1U), /* dst_mask */
737 false), /* pcrel_offset */
738
739 /* TP-relative TLS LE store. */
740 HOWTO (R_RISCV_TPREL_S, /* type */
741 0, /* rightshift */
742 2, /* size */
743 32, /* bitsize */
744 false, /* pc_relative */
745 0, /* bitpos */
746 complain_overflow_signed, /* complain_on_overflow */
747 bfd_elf_generic_reloc, /* special_function */
748 "R_RISCV_TPREL_S", /* name */
749 false, /* partial_inplace */
750 0, /* src_mask */
751 ENCODE_STYPE_IMM (-1U), /* dst_mask */
752 false), /* pcrel_offset */
753
754 /* The paired relocation may be relaxed. */
755 HOWTO (R_RISCV_RELAX, /* type */
756 0, /* rightshift */
757 3, /* size */
758 0, /* bitsize */
759 false, /* pc_relative */
760 0, /* bitpos */
761 complain_overflow_dont, /* complain_on_overflow */
762 bfd_elf_generic_reloc, /* special_function */
763 "R_RISCV_RELAX", /* name */
764 false, /* partial_inplace */
765 0, /* src_mask */
766 0, /* dst_mask */
767 false), /* pcrel_offset */
768
769 /* 6-bit in-place addition, for local label subtraction. */
770 HOWTO (R_RISCV_SUB6, /* type */
771 0, /* rightshift */
772 0, /* size */
773 8, /* bitsize */
774 false, /* pc_relative */
775 0, /* bitpos */
776 complain_overflow_dont, /* complain_on_overflow */
777 riscv_elf_add_sub_reloc, /* special_function */
778 "R_RISCV_SUB6", /* name */
779 false, /* partial_inplace */
780 0, /* src_mask */
781 0x3f, /* dst_mask */
782 false), /* pcrel_offset */
783
784 /* 6-bit in-place setting, for local label subtraction. */
785 HOWTO (R_RISCV_SET6, /* type */
786 0, /* rightshift */
787 0, /* size */
788 8, /* bitsize */
789 false, /* pc_relative */
790 0, /* bitpos */
791 complain_overflow_dont, /* complain_on_overflow */
792 bfd_elf_generic_reloc, /* special_function */
793 "R_RISCV_SET6", /* name */
794 false, /* partial_inplace */
795 0, /* src_mask */
796 0x3f, /* dst_mask */
797 false), /* pcrel_offset */
798
799 /* 8-bit in-place setting, for local label subtraction. */
800 HOWTO (R_RISCV_SET8, /* type */
801 0, /* rightshift */
802 0, /* size */
803 8, /* bitsize */
804 false, /* pc_relative */
805 0, /* bitpos */
806 complain_overflow_dont, /* complain_on_overflow */
807 bfd_elf_generic_reloc, /* special_function */
808 "R_RISCV_SET8", /* name */
809 false, /* partial_inplace */
810 0, /* src_mask */
811 0xff, /* dst_mask */
812 false), /* pcrel_offset */
813
814 /* 16-bit in-place setting, for local label subtraction. */
815 HOWTO (R_RISCV_SET16, /* type */
816 0, /* rightshift */
817 1, /* size */
818 16, /* bitsize */
819 false, /* pc_relative */
820 0, /* bitpos */
821 complain_overflow_dont, /* complain_on_overflow */
822 bfd_elf_generic_reloc, /* special_function */
823 "R_RISCV_SET16", /* name */
824 false, /* partial_inplace */
825 0, /* src_mask */
826 0xffff, /* dst_mask */
827 false), /* pcrel_offset */
828
829 /* 32-bit in-place setting, for local label subtraction. */
830 HOWTO (R_RISCV_SET32, /* type */
831 0, /* rightshift */
832 2, /* size */
833 32, /* bitsize */
834 false, /* pc_relative */
835 0, /* bitpos */
836 complain_overflow_dont, /* complain_on_overflow */
837 bfd_elf_generic_reloc, /* special_function */
838 "R_RISCV_SET32", /* name */
839 false, /* partial_inplace */
840 0, /* src_mask */
841 0xffffffff, /* dst_mask */
842 false), /* pcrel_offset */
843
844 /* 32-bit PC relative. */
845 HOWTO (R_RISCV_32_PCREL, /* type */
846 0, /* rightshift */
847 2, /* size */
848 32, /* bitsize */
849 true, /* pc_relative */
850 0, /* bitpos */
851 complain_overflow_dont, /* complain_on_overflow */
852 bfd_elf_generic_reloc, /* special_function */
853 "R_RISCV_32_PCREL", /* name */
854 false, /* partial_inplace */
855 0, /* src_mask */
856 0xffffffff, /* dst_mask */
857 false), /* pcrel_offset */
858
859 /* Relocation against a local ifunc symbol in a shared object. */
860 HOWTO (R_RISCV_IRELATIVE, /* type */
861 0, /* rightshift */
862 2, /* size */
863 32, /* bitsize */
864 false, /* pc_relative */
865 0, /* bitpos */
866 complain_overflow_dont, /* complain_on_overflow */
867 bfd_elf_generic_reloc, /* special_function */
868 "R_RISCV_IRELATIVE", /* name */
869 false, /* partial_inplace */
870 0, /* src_mask */
871 0xffffffff, /* dst_mask */
872 false), /* pcrel_offset */
873 };
874
875 /* A mapping from BFD reloc types to RISC-V ELF reloc types. */
876 struct elf_reloc_map
877 {
878 bfd_reloc_code_real_type bfd_val;
879 enum elf_riscv_reloc_type elf_val;
880 };
881
882 static const struct elf_reloc_map riscv_reloc_map[] =
883 {
884 { BFD_RELOC_NONE, R_RISCV_NONE },
885 { BFD_RELOC_32, R_RISCV_32 },
886 { BFD_RELOC_64, R_RISCV_64 },
887 { BFD_RELOC_RISCV_ADD8, R_RISCV_ADD8 },
888 { BFD_RELOC_RISCV_ADD16, R_RISCV_ADD16 },
889 { BFD_RELOC_RISCV_ADD32, R_RISCV_ADD32 },
890 { BFD_RELOC_RISCV_ADD64, R_RISCV_ADD64 },
891 { BFD_RELOC_RISCV_SUB8, R_RISCV_SUB8 },
892 { BFD_RELOC_RISCV_SUB16, R_RISCV_SUB16 },
893 { BFD_RELOC_RISCV_SUB32, R_RISCV_SUB32 },
894 { BFD_RELOC_RISCV_SUB64, R_RISCV_SUB64 },
895 { BFD_RELOC_CTOR, R_RISCV_64 },
896 { BFD_RELOC_12_PCREL, R_RISCV_BRANCH },
897 { BFD_RELOC_RISCV_HI20, R_RISCV_HI20 },
898 { BFD_RELOC_RISCV_LO12_I, R_RISCV_LO12_I },
899 { BFD_RELOC_RISCV_LO12_S, R_RISCV_LO12_S },
900 { BFD_RELOC_RISCV_PCREL_LO12_I, R_RISCV_PCREL_LO12_I },
901 { BFD_RELOC_RISCV_PCREL_LO12_S, R_RISCV_PCREL_LO12_S },
902 { BFD_RELOC_RISCV_CALL, R_RISCV_CALL },
903 { BFD_RELOC_RISCV_CALL_PLT, R_RISCV_CALL_PLT },
904 { BFD_RELOC_RISCV_PCREL_HI20, R_RISCV_PCREL_HI20 },
905 { BFD_RELOC_RISCV_JMP, R_RISCV_JAL },
906 { BFD_RELOC_RISCV_GOT_HI20, R_RISCV_GOT_HI20 },
907 { BFD_RELOC_RISCV_TLS_DTPMOD32, R_RISCV_TLS_DTPMOD32 },
908 { BFD_RELOC_RISCV_TLS_DTPREL32, R_RISCV_TLS_DTPREL32 },
909 { BFD_RELOC_RISCV_TLS_DTPMOD64, R_RISCV_TLS_DTPMOD64 },
910 { BFD_RELOC_RISCV_TLS_DTPREL64, R_RISCV_TLS_DTPREL64 },
911 { BFD_RELOC_RISCV_TLS_TPREL32, R_RISCV_TLS_TPREL32 },
912 { BFD_RELOC_RISCV_TLS_TPREL64, R_RISCV_TLS_TPREL64 },
913 { BFD_RELOC_RISCV_TPREL_HI20, R_RISCV_TPREL_HI20 },
914 { BFD_RELOC_RISCV_TPREL_ADD, R_RISCV_TPREL_ADD },
915 { BFD_RELOC_RISCV_TPREL_LO12_S, R_RISCV_TPREL_LO12_S },
916 { BFD_RELOC_RISCV_TPREL_LO12_I, R_RISCV_TPREL_LO12_I },
917 { BFD_RELOC_RISCV_TLS_GOT_HI20, R_RISCV_TLS_GOT_HI20 },
918 { BFD_RELOC_RISCV_TLS_GD_HI20, R_RISCV_TLS_GD_HI20 },
919 { BFD_RELOC_RISCV_ALIGN, R_RISCV_ALIGN },
920 { BFD_RELOC_RISCV_RVC_BRANCH, R_RISCV_RVC_BRANCH },
921 { BFD_RELOC_RISCV_RVC_JUMP, R_RISCV_RVC_JUMP },
922 { BFD_RELOC_RISCV_RVC_LUI, R_RISCV_RVC_LUI },
923 { BFD_RELOC_RISCV_GPREL_I, R_RISCV_GPREL_I },
924 { BFD_RELOC_RISCV_GPREL_S, R_RISCV_GPREL_S },
925 { BFD_RELOC_RISCV_TPREL_I, R_RISCV_TPREL_I },
926 { BFD_RELOC_RISCV_TPREL_S, R_RISCV_TPREL_S },
927 { BFD_RELOC_RISCV_RELAX, R_RISCV_RELAX },
928 { BFD_RELOC_RISCV_SUB6, R_RISCV_SUB6 },
929 { BFD_RELOC_RISCV_SET6, R_RISCV_SET6 },
930 { BFD_RELOC_RISCV_SET8, R_RISCV_SET8 },
931 { BFD_RELOC_RISCV_SET16, R_RISCV_SET16 },
932 { BFD_RELOC_RISCV_SET32, R_RISCV_SET32 },
933 { BFD_RELOC_RISCV_32_PCREL, R_RISCV_32_PCREL },
934 };
935
936 /* Given a BFD reloc type, return a howto structure. */
937
938 reloc_howto_type *
939 riscv_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED,
940 bfd_reloc_code_real_type code)
941 {
942 unsigned int i;
943
944 for (i = 0; i < ARRAY_SIZE (riscv_reloc_map); i++)
945 if (riscv_reloc_map[i].bfd_val == code)
946 return &howto_table[(int) riscv_reloc_map[i].elf_val];
947
948 bfd_set_error (bfd_error_bad_value);
949 return NULL;
950 }
951
952 reloc_howto_type *
953 riscv_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED, const char *r_name)
954 {
955 unsigned int i;
956
957 for (i = 0; i < ARRAY_SIZE (howto_table); i++)
958 if (howto_table[i].name && strcasecmp (howto_table[i].name, r_name) == 0)
959 return &howto_table[i];
960
961 return NULL;
962 }
963
964 reloc_howto_type *
965 riscv_elf_rtype_to_howto (bfd *abfd, unsigned int r_type)
966 {
967 if (r_type >= ARRAY_SIZE (howto_table))
968 {
969 (*_bfd_error_handler) (_("%pB: unsupported relocation type %#x"),
970 abfd, r_type);
971 bfd_set_error (bfd_error_bad_value);
972 return NULL;
973 }
974 return &howto_table[r_type];
975 }
976
977 /* Special_function of RISCV_ADD and RISCV_SUB relocations. */
978
979 static bfd_reloc_status_type
980 riscv_elf_add_sub_reloc (bfd *abfd,
981 arelent *reloc_entry,
982 asymbol *symbol,
983 void *data,
984 asection *input_section,
985 bfd *output_bfd,
986 char **error_message ATTRIBUTE_UNUSED)
987 {
988 reloc_howto_type *howto = reloc_entry->howto;
989 bfd_vma relocation;
990
991 if (output_bfd != NULL
992 && (symbol->flags & BSF_SECTION_SYM) == 0
993 && (!reloc_entry->howto->partial_inplace || reloc_entry->addend == 0))
994 {
995 reloc_entry->address += input_section->output_offset;
996 return bfd_reloc_ok;
997 }
998
999 if (output_bfd != NULL)
1000 return bfd_reloc_continue;
1001
1002 relocation = symbol->value + symbol->section->output_section->vma
1003 + symbol->section->output_offset + reloc_entry->addend;
1004
1005 bfd_size_type octets = reloc_entry->address
1006 * bfd_octets_per_byte (abfd, input_section);
1007 if (!bfd_reloc_offset_in_range (reloc_entry->howto, abfd,
1008 input_section, octets))
1009 return bfd_reloc_outofrange;
1010
1011 bfd_vma old_value = bfd_get (howto->bitsize, abfd,
1012 data + reloc_entry->address);
1013
1014 switch (howto->type)
1015 {
1016 case R_RISCV_ADD8:
1017 case R_RISCV_ADD16:
1018 case R_RISCV_ADD32:
1019 case R_RISCV_ADD64:
1020 relocation = old_value + relocation;
1021 break;
1022 case R_RISCV_SUB6:
1023 case R_RISCV_SUB8:
1024 case R_RISCV_SUB16:
1025 case R_RISCV_SUB32:
1026 case R_RISCV_SUB64:
1027 relocation = old_value - relocation;
1028 break;
1029 }
1030 bfd_put (howto->bitsize, abfd, relocation, data + reloc_entry->address);
1031
1032 return bfd_reloc_ok;
1033 }
1034
1035 /* Always add the IMPLICIT for the SUBSET. */
1036
1037 static bool
1038 check_implicit_always (const char *implicit ATTRIBUTE_UNUSED,
1039 riscv_subset_t *subset ATTRIBUTE_UNUSED)
1040 {
1041 return true;
1042 }
1043
1044 /* Add the IMPLICIT only when the version of SUBSET less than 2.1. */
1045
1046 static bool
1047 check_implicit_for_i (const char *implicit ATTRIBUTE_UNUSED,
1048 riscv_subset_t *subset)
1049 {
1050 return (subset->major_version < 2
1051 || (subset->major_version == 2
1052 && subset->minor_version < 1));
1053 }
1054
1055 /* Record all implicit information for the subsets. */
1056 struct riscv_implicit_subset
1057 {
1058 const char *subset_name;
1059 const char *implicit_name;
1060 /* A function to determine if we need to add the implicit subset. */
1061 bool (*check_func) (const char *, riscv_subset_t *);
1062 };
1063 static struct riscv_implicit_subset riscv_implicit_subsets[] =
1064 {
1065 {"e", "i", check_implicit_always},
1066 {"i", "zicsr", check_implicit_for_i},
1067 {"i", "zifencei", check_implicit_for_i},
1068 {"g", "i", check_implicit_always},
1069 {"g", "m", check_implicit_always},
1070 {"g", "a", check_implicit_always},
1071 {"g", "f", check_implicit_always},
1072 {"g", "d", check_implicit_always},
1073 {"g", "zicsr", check_implicit_always},
1074 {"g", "zifencei", check_implicit_always},
1075 {"q", "d", check_implicit_always},
1076 {"v", "d", check_implicit_always},
1077 {"v", "zve64d", check_implicit_always},
1078 {"v", "zvl128b", check_implicit_always},
1079 {"zve64d", "d", check_implicit_always},
1080 {"zve64d", "zve64f", check_implicit_always},
1081 {"zve64f", "zve32f", check_implicit_always},
1082 {"zve64f", "zve64x", check_implicit_always},
1083 {"zve64f", "zvl64b", check_implicit_always},
1084 {"zve32f", "f", check_implicit_always},
1085 {"zve32f", "zvl32b", check_implicit_always},
1086 {"zve32f", "zve32x", check_implicit_always},
1087 {"zve64x", "zve32x", check_implicit_always},
1088 {"zve64x", "zvl64b", check_implicit_always},
1089 {"zve32x", "zvl32b", check_implicit_always},
1090 {"zvl65536b", "zvl32768b", check_implicit_always},
1091 {"zvl32768b", "zvl16384b", check_implicit_always},
1092 {"zvl16384b", "zvl8192b", check_implicit_always},
1093 {"zvl8192b", "zvl4096b", check_implicit_always},
1094 {"zvl4096b", "zvl2048b", check_implicit_always},
1095 {"zvl2048b", "zvl1024b", check_implicit_always},
1096 {"zvl1024b", "zvl512b", check_implicit_always},
1097 {"zvl512b", "zvl256b", check_implicit_always},
1098 {"zvl256b", "zvl128b", check_implicit_always},
1099 {"zvl128b", "zvl64b", check_implicit_always},
1100 {"zvl64b", "zvl32b", check_implicit_always},
1101 {"d", "f", check_implicit_always},
1102 {"f", "zicsr", check_implicit_always},
1103 {"zk", "zkn", check_implicit_always},
1104 {"zk", "zkr", check_implicit_always},
1105 {"zk", "zkt", check_implicit_always},
1106 {"zkn", "zbkb", check_implicit_always},
1107 {"zkn", "zbkc", check_implicit_always},
1108 {"zkn", "zbkx", check_implicit_always},
1109 {"zkn", "zkne", check_implicit_always},
1110 {"zkn", "zknd", check_implicit_always},
1111 {"zkn", "zknh", check_implicit_always},
1112 {"zks", "zbkb", check_implicit_always},
1113 {"zks", "zbkc", check_implicit_always},
1114 {"zks", "zbkx", check_implicit_always},
1115 {"zks", "zksed", check_implicit_always},
1116 {"zks", "zksh", check_implicit_always},
1117 {NULL, NULL, NULL}
1118 };
1119
1120 /* For default_enable field, decide if the extension should
1121 be enbaled by default. */
1122
1123 #define EXT_DEFAULT 0x1
1124
1125 /* List all extensions that binutils should know about. */
1126
1127 struct riscv_supported_ext
1128 {
1129 const char *name;
1130 enum riscv_spec_class isa_spec_class;
1131 int major_version;
1132 int minor_version;
1133 unsigned long default_enable;
1134 };
1135
1136 /* The standard extensions must be added in canonical order. */
1137
1138 static struct riscv_supported_ext riscv_supported_std_ext[] =
1139 {
1140 {"e", ISA_SPEC_CLASS_20191213, 1, 9, 0 },
1141 {"e", ISA_SPEC_CLASS_20190608, 1, 9, 0 },
1142 {"e", ISA_SPEC_CLASS_2P2, 1, 9, 0 },
1143 {"i", ISA_SPEC_CLASS_20191213, 2, 1, 0 },
1144 {"i", ISA_SPEC_CLASS_20190608, 2, 1, 0 },
1145 {"i", ISA_SPEC_CLASS_2P2, 2, 0, 0 },
1146 /* The g is a special case which we don't want to output it,
1147 but still need it when adding implicit extensions. */
1148 {"g", ISA_SPEC_CLASS_NONE, RISCV_UNKNOWN_VERSION, RISCV_UNKNOWN_VERSION, EXT_DEFAULT },
1149 {"m", ISA_SPEC_CLASS_20191213, 2, 0, 0 },
1150 {"m", ISA_SPEC_CLASS_20190608, 2, 0, 0 },
1151 {"m", ISA_SPEC_CLASS_2P2, 2, 0, 0 },
1152 {"a", ISA_SPEC_CLASS_20191213, 2, 1, 0 },
1153 {"a", ISA_SPEC_CLASS_20190608, 2, 0, 0 },
1154 {"a", ISA_SPEC_CLASS_2P2, 2, 0, 0 },
1155 {"f", ISA_SPEC_CLASS_20191213, 2, 2, 0 },
1156 {"f", ISA_SPEC_CLASS_20190608, 2, 2, 0 },
1157 {"f", ISA_SPEC_CLASS_2P2, 2, 0, 0 },
1158 {"d", ISA_SPEC_CLASS_20191213, 2, 2, 0 },
1159 {"d", ISA_SPEC_CLASS_20190608, 2, 2, 0 },
1160 {"d", ISA_SPEC_CLASS_2P2, 2, 0, 0 },
1161 {"q", ISA_SPEC_CLASS_20191213, 2, 2, 0 },
1162 {"q", ISA_SPEC_CLASS_20190608, 2, 2, 0 },
1163 {"q", ISA_SPEC_CLASS_2P2, 2, 0, 0 },
1164 {"l", ISA_SPEC_CLASS_NONE, RISCV_UNKNOWN_VERSION, RISCV_UNKNOWN_VERSION, 0 },
1165 {"c", ISA_SPEC_CLASS_20191213, 2, 0, 0 },
1166 {"c", ISA_SPEC_CLASS_20190608, 2, 0, 0 },
1167 {"c", ISA_SPEC_CLASS_2P2, 2, 0, 0 },
1168 {"b", ISA_SPEC_CLASS_NONE, RISCV_UNKNOWN_VERSION, RISCV_UNKNOWN_VERSION, 0 },
1169 {"k", ISA_SPEC_CLASS_NONE, RISCV_UNKNOWN_VERSION, RISCV_UNKNOWN_VERSION, 0 },
1170 {"j", ISA_SPEC_CLASS_NONE, RISCV_UNKNOWN_VERSION, RISCV_UNKNOWN_VERSION, 0 },
1171 {"t", ISA_SPEC_CLASS_NONE, RISCV_UNKNOWN_VERSION, RISCV_UNKNOWN_VERSION, 0 },
1172 {"p", ISA_SPEC_CLASS_NONE, RISCV_UNKNOWN_VERSION, RISCV_UNKNOWN_VERSION, 0 },
1173 {"v", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1174 {"n", ISA_SPEC_CLASS_NONE, RISCV_UNKNOWN_VERSION, RISCV_UNKNOWN_VERSION, 0 },
1175 {NULL, 0, 0, 0, 0}
1176 };
1177
1178 static struct riscv_supported_ext riscv_supported_std_z_ext[] =
1179 {
1180 {"zicsr", ISA_SPEC_CLASS_20191213, 2, 0, 0 },
1181 {"zicsr", ISA_SPEC_CLASS_20190608, 2, 0, 0 },
1182 {"zifencei", ISA_SPEC_CLASS_20191213, 2, 0, 0 },
1183 {"zifencei", ISA_SPEC_CLASS_20190608, 2, 0, 0 },
1184 {"zihintpause", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1185 {"zbb", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1186 {"zba", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1187 {"zbc", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1188 {"zbs", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1189 {"zbkb", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1190 {"zbkc", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1191 {"zbkx", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1192 {"zk", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1193 {"zkn", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1194 {"zknd", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1195 {"zkne", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1196 {"zknh", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1197 {"zkr", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1198 {"zks", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1199 {"zksed", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1200 {"zksh", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1201 {"zkt", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1202 {"zve32x", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1203 {"zve32f", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1204 {"zve32d", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1205 {"zve64x", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1206 {"zve64f", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1207 {"zve64d", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1208 {"zvl32b", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1209 {"zvl64b", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1210 {"zvl128b", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1211 {"zvl256b", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1212 {"zvl512b", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1213 {"zvl1024b", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1214 {"zvl2048b", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1215 {"zvl4096b", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1216 {"zvl8192b", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1217 {"zvl16384b", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1218 {"zvl32768b", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1219 {"zvl65536b", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1220 {NULL, 0, 0, 0, 0}
1221 };
1222
1223 static struct riscv_supported_ext riscv_supported_std_s_ext[] =
1224 {
1225 {NULL, 0, 0, 0, 0}
1226 };
1227
1228 static struct riscv_supported_ext riscv_supported_std_h_ext[] =
1229 {
1230 {NULL, 0, 0, 0, 0}
1231 };
1232
1233 static struct riscv_supported_ext riscv_supported_std_zxm_ext[] =
1234 {
1235 {NULL, 0, 0, 0, 0}
1236 };
1237
1238 const struct riscv_supported_ext *riscv_all_supported_ext[] =
1239 {
1240 riscv_supported_std_ext,
1241 riscv_supported_std_z_ext,
1242 riscv_supported_std_s_ext,
1243 riscv_supported_std_h_ext,
1244 riscv_supported_std_zxm_ext,
1245 NULL
1246 };
1247
1248 /* ISA extension prefixed name class. Must define them in parsing order. */
1249 enum riscv_prefix_ext_class
1250 {
1251 RV_ISA_CLASS_Z = 1,
1252 RV_ISA_CLASS_S,
1253 RV_ISA_CLASS_H,
1254 RV_ISA_CLASS_ZXM,
1255 RV_ISA_CLASS_X,
1256 RV_ISA_CLASS_UNKNOWN
1257 };
1258
1259 /* Record the strings of the prefixed extensions, and their corresponding
1260 classes. The more letters of the prefix string, the more forward it must
1261 be defined. Otherwise, the riscv_get_prefix_class will map it to the
1262 wrong classes. */
1263 struct riscv_parse_prefix_config
1264 {
1265 /* Class of the extension. */
1266 enum riscv_prefix_ext_class class;
1267
1268 /* Prefix string for error printing and internal parser usage. */
1269 const char *prefix;
1270 };
1271 static const struct riscv_parse_prefix_config parse_config[] =
1272 {
1273 {RV_ISA_CLASS_ZXM, "zxm"},
1274 {RV_ISA_CLASS_Z, "z"},
1275 {RV_ISA_CLASS_S, "s"},
1276 {RV_ISA_CLASS_H, "h"},
1277 {RV_ISA_CLASS_X, "x"},
1278 {RV_ISA_CLASS_UNKNOWN, NULL}
1279 };
1280
1281 /* Get the prefixed name class for the extensions, the class also
1282 means the order of the prefixed extensions. */
1283
1284 static enum riscv_prefix_ext_class
1285 riscv_get_prefix_class (const char *arch)
1286 {
1287 int i = 0;
1288 while (parse_config[i].class != RV_ISA_CLASS_UNKNOWN)
1289 {
1290 if (strncmp (arch, parse_config[i].prefix,
1291 strlen (parse_config[i].prefix)) == 0)
1292 return parse_config[i].class;
1293 i++;
1294 }
1295 return RV_ISA_CLASS_UNKNOWN;
1296 }
1297
1298 /* Check KNOWN_EXTS to see if the EXT is supported. */
1299
1300 static bool
1301 riscv_known_prefixed_ext (const char *ext,
1302 struct riscv_supported_ext *known_exts)
1303 {
1304 size_t i;
1305 for (i = 0; known_exts[i].name != NULL; ++i)
1306 if (strcmp (ext, known_exts[i].name) == 0)
1307 return true;
1308 return false;
1309 }
1310
1311 /* Check whether the prefixed extension is recognized or not. Return
1312 true if recognized, otehrwise return false. */
1313
1314 static bool
1315 riscv_recognized_prefixed_ext (const char *ext)
1316 {
1317 enum riscv_prefix_ext_class class = riscv_get_prefix_class (ext);
1318 switch (class)
1319 {
1320 case RV_ISA_CLASS_Z:
1321 return riscv_known_prefixed_ext (ext, riscv_supported_std_z_ext);
1322 case RV_ISA_CLASS_ZXM:
1323 return riscv_known_prefixed_ext (ext, riscv_supported_std_zxm_ext);
1324 case RV_ISA_CLASS_S:
1325 return riscv_known_prefixed_ext (ext, riscv_supported_std_s_ext);
1326 case RV_ISA_CLASS_H:
1327 return riscv_known_prefixed_ext (ext, riscv_supported_std_h_ext);
1328 case RV_ISA_CLASS_X:
1329 /* Only the single x is unrecognized. */
1330 if (strcmp (ext, "x") != 0)
1331 return true;
1332 default:
1333 break;
1334 }
1335 return false;
1336 }
1337
1338 /* Array is used to compare the orders of standard extensions quickly. */
1339 static int riscv_ext_order[26] = {0};
1340
1341 /* Init the riscv_ext_order array. */
1342
1343 static void
1344 riscv_init_ext_order (void)
1345 {
1346 static bool inited = false;
1347 if (inited)
1348 return;
1349
1350 /* The orders of all standard extensions are positive. */
1351 int order = 1;
1352
1353 int i = 0;
1354 while (riscv_supported_std_ext[i].name != NULL)
1355 {
1356 const char *ext = riscv_supported_std_ext[i].name;
1357 riscv_ext_order[(*ext - 'a')] = order++;
1358 i++;
1359 while (riscv_supported_std_ext[i].name
1360 && strcmp (ext, riscv_supported_std_ext[i].name) == 0)
1361 i++;
1362 }
1363
1364 /* Some of the prefixed keyword are not single letter, so we set
1365 their prefixed orders in the riscv_compare_subsets directly,
1366 not through the riscv_ext_order. */
1367
1368 inited = true;
1369 }
1370
1371 /* Similar to the strcmp. It returns an integer less than, equal to,
1372 or greater than zero if `subset2` is found, respectively, to be less
1373 than, to match, or be greater than `subset1`.
1374
1375 The order values,
1376 Zero: Preserved keywords.
1377 Positive number: Standard extensions.
1378 Negative number: Prefixed keywords. */
1379
1380 int
1381 riscv_compare_subsets (const char *subset1, const char *subset2)
1382 {
1383 int order1 = riscv_ext_order[(*subset1 - 'a')];
1384 int order2 = riscv_ext_order[(*subset2 - 'a')];
1385
1386 /* Compare the standard extension first. */
1387 if (order1 > 0 && order2 > 0)
1388 return order1 - order2;
1389
1390 /* Set the prefixed orders to negative numbers. */
1391 enum riscv_prefix_ext_class class1 = riscv_get_prefix_class (subset1);
1392 enum riscv_prefix_ext_class class2 = riscv_get_prefix_class (subset2);
1393
1394 if (class1 != RV_ISA_CLASS_UNKNOWN)
1395 order1 = - (int) class1;
1396 if (class2 != RV_ISA_CLASS_UNKNOWN)
1397 order2 = - (int) class2;
1398
1399 if (order1 == order2)
1400 {
1401 /* Compare the standard addition z extensions. */
1402 if (class1 == RV_ISA_CLASS_Z)
1403 {
1404 order1 = riscv_ext_order[(*++subset1 - 'a')];
1405 order2 = riscv_ext_order[(*++subset2 - 'a')];
1406 if (order1 != order2)
1407 return order1 - order2;
1408 }
1409 return strcasecmp (++subset1, ++subset2);
1410 }
1411
1412 return order2 - order1;
1413 }
1414
1415 /* Find subset in the list. Return TRUE and set `current` to the subset
1416 if it is found. Otherwise, return FALSE and set `current` to the place
1417 where we should insert the subset. However, return FALSE with the NULL
1418 `current` means we should insert the subset at the head of subset list,
1419 if needed. */
1420
1421 bool
1422 riscv_lookup_subset (const riscv_subset_list_t *subset_list,
1423 const char *subset,
1424 riscv_subset_t **current)
1425 {
1426 riscv_subset_t *s, *pre_s = NULL;
1427
1428 /* If the subset is added in order, then just add it at the tail. */
1429 if (subset_list->tail != NULL
1430 && riscv_compare_subsets (subset_list->tail->name, subset) < 0)
1431 {
1432 *current = subset_list->tail;
1433 return false;
1434 }
1435
1436 for (s = subset_list->head;
1437 s != NULL;
1438 pre_s = s, s = s->next)
1439 {
1440 int cmp = riscv_compare_subsets (s->name, subset);
1441 if (cmp == 0)
1442 {
1443 *current = s;
1444 return true;
1445 }
1446 else if (cmp > 0)
1447 break;
1448 }
1449 *current = pre_s;
1450
1451 return false;
1452 }
1453
1454 /* Add the extension to the subset list. Search the
1455 list first, and then find the right place to add. */
1456
1457 void
1458 riscv_add_subset (riscv_subset_list_t *subset_list,
1459 const char *subset,
1460 int major,
1461 int minor)
1462 {
1463 riscv_subset_t *current, *new;
1464
1465 if (riscv_lookup_subset (subset_list, subset, &current))
1466 return;
1467
1468 new = xmalloc (sizeof *new);
1469 new->name = xstrdup (subset);
1470 new->major_version = major;
1471 new->minor_version = minor;
1472 new->next = NULL;
1473
1474 if (current != NULL)
1475 {
1476 new->next = current->next;
1477 current->next = new;
1478 }
1479 else
1480 {
1481 new->next = subset_list->head;
1482 subset_list->head = new;
1483 }
1484
1485 if (new->next == NULL)
1486 subset_list->tail = new;
1487 }
1488
1489 /* Get the default versions from the riscv_supported_*ext tables. */
1490
1491 static void
1492 riscv_get_default_ext_version (enum riscv_spec_class *default_isa_spec,
1493 const char *name,
1494 int *major_version,
1495 int *minor_version)
1496 {
1497 if (name == NULL
1498 || default_isa_spec == NULL
1499 || *default_isa_spec == ISA_SPEC_CLASS_NONE)
1500 return;
1501
1502 struct riscv_supported_ext *table = NULL;
1503 enum riscv_prefix_ext_class class = riscv_get_prefix_class (name);
1504 switch (class)
1505 {
1506 case RV_ISA_CLASS_ZXM: table = riscv_supported_std_zxm_ext; break;
1507 case RV_ISA_CLASS_Z: table = riscv_supported_std_z_ext; break;
1508 case RV_ISA_CLASS_S: table = riscv_supported_std_s_ext; break;
1509 case RV_ISA_CLASS_H: table = riscv_supported_std_h_ext; break;
1510 case RV_ISA_CLASS_X:
1511 break;
1512 default:
1513 table = riscv_supported_std_ext;
1514 }
1515
1516 int i = 0;
1517 while (table != NULL && table[i].name != NULL)
1518 {
1519 if (strcmp (table[i].name, name) == 0
1520 && (table[i].isa_spec_class == ISA_SPEC_CLASS_DRAFT
1521 || table[i].isa_spec_class == *default_isa_spec))
1522 {
1523 *major_version = table[i].major_version;
1524 *minor_version = table[i].minor_version;
1525 return;
1526 }
1527 i++;
1528 }
1529 }
1530
1531 /* Find the default versions for the extension before adding them to
1532 the subset list, if their versions are RISCV_UNKNOWN_VERSION.
1533 Afterwards, report errors if we can not find their default versions. */
1534
1535 static void
1536 riscv_parse_add_subset (riscv_parse_subset_t *rps,
1537 const char *subset,
1538 int major,
1539 int minor,
1540 bool implicit)
1541 {
1542 int major_version = major;
1543 int minor_version = minor;
1544
1545 if (major_version == RISCV_UNKNOWN_VERSION
1546 || minor_version == RISCV_UNKNOWN_VERSION)
1547 riscv_get_default_ext_version (rps->isa_spec, subset,
1548 &major_version, &minor_version);
1549
1550 /* We don't care the versions of the implicit extensions. */
1551 if (!implicit
1552 && (major_version == RISCV_UNKNOWN_VERSION
1553 || minor_version == RISCV_UNKNOWN_VERSION))
1554 {
1555 if (subset[0] == 'x')
1556 rps->error_handler
1557 (_("x ISA extension `%s' must be set with the versions"),
1558 subset);
1559 else
1560 rps->error_handler
1561 (_("cannot find default versions of the ISA extension `%s'"),
1562 subset);
1563 return;
1564 }
1565
1566 riscv_add_subset (rps->subset_list, subset,
1567 major_version, minor_version);
1568 }
1569
1570 /* Release subset list. */
1571
1572 void
1573 riscv_release_subset_list (riscv_subset_list_t *subset_list)
1574 {
1575 while (subset_list->head != NULL)
1576 {
1577 riscv_subset_t *next = subset_list->head->next;
1578 free ((void *)subset_list->head->name);
1579 free (subset_list->head);
1580 subset_list->head = next;
1581 }
1582
1583 subset_list->tail = NULL;
1584 }
1585
1586 /* Parsing extension version.
1587
1588 Return Value:
1589 Points to the end of version
1590
1591 Arguments:
1592 `p`: Curent parsing position.
1593 `major_version`: Parsed major version.
1594 `minor_version`: Parsed minor version. */
1595
1596 static const char *
1597 riscv_parsing_subset_version (const char *p,
1598 int *major_version,
1599 int *minor_version)
1600 {
1601 bool major_p = true;
1602 int version = 0;
1603 char np;
1604
1605 *major_version = 0;
1606 *minor_version = 0;
1607 for (; *p; ++p)
1608 {
1609 if (*p == 'p')
1610 {
1611 np = *(p + 1);
1612
1613 /* Might be beginning of `p` extension. */
1614 if (!ISDIGIT (np))
1615 break;
1616
1617 *major_version = version;
1618 major_p = false;
1619 version = 0;
1620 }
1621 else if (ISDIGIT (*p))
1622 version = (version * 10) + (*p - '0');
1623 else
1624 break;
1625 }
1626
1627 if (major_p)
1628 *major_version = version;
1629 else
1630 *minor_version = version;
1631
1632 /* We can not find any version in string. */
1633 if (*major_version == 0 && *minor_version == 0)
1634 {
1635 *major_version = RISCV_UNKNOWN_VERSION;
1636 *minor_version = RISCV_UNKNOWN_VERSION;
1637 }
1638
1639 return p;
1640 }
1641
1642 /* Parsing function for standard extensions.
1643
1644 Return Value:
1645 Points to the end of extensions.
1646
1647 Arguments:
1648 `rps`: Hooks and status for parsing extensions.
1649 `arch`: Full ISA string.
1650 `p`: Curent parsing position. */
1651
1652 static const char *
1653 riscv_parse_std_ext (riscv_parse_subset_t *rps,
1654 const char *arch,
1655 const char *p)
1656 {
1657 /* First letter must start with i, e or g. */
1658 if (*p != 'e' && *p != 'i' && *p != 'g')
1659 {
1660 rps->error_handler
1661 (_("%s: first ISA extension must be `e', `i' or `g'"),
1662 arch);
1663 return NULL;
1664 }
1665
1666 while (p != NULL && *p != '\0')
1667 {
1668 /* Stop when we parsed the known prefix class. */
1669 enum riscv_prefix_ext_class class = riscv_get_prefix_class (p);
1670 if (class != RV_ISA_CLASS_UNKNOWN)
1671 break;
1672
1673 if (*p == '_')
1674 {
1675 p++;
1676 continue;
1677 }
1678
1679 bool implicit = false;
1680 int major = RISCV_UNKNOWN_VERSION;
1681 int minor = RISCV_UNKNOWN_VERSION;
1682 char subset[2] = {0, 0};
1683
1684 subset[0] = *p;
1685
1686 /* Check if the standard extension is supported. */
1687 if (riscv_ext_order[(subset[0] - 'a')] == 0)
1688 {
1689 rps->error_handler
1690 (_("%s: unknown standard ISA extension `%c'"),
1691 arch, subset[0]);
1692 return NULL;
1693 }
1694
1695 /* Checking canonical order. */
1696 if (rps->subset_list->tail != NULL
1697 && riscv_compare_subsets (rps->subset_list->tail->name, subset) > 0)
1698 {
1699 rps->error_handler
1700 (_("%s: standard ISA extension `%c' is not "
1701 "in canonical order"), arch, subset[0]);
1702 return NULL;
1703 }
1704
1705 p = riscv_parsing_subset_version (++p, &major, &minor);
1706 /* Added g as an implicit extension. */
1707 if (subset[0] == 'g')
1708 {
1709 implicit = true;
1710 major = RISCV_UNKNOWN_VERSION;
1711 minor = RISCV_UNKNOWN_VERSION;
1712 }
1713 riscv_parse_add_subset (rps, subset, major, minor, implicit);
1714 }
1715
1716 return p;
1717 }
1718
1719 /* Parsing function for prefixed extensions.
1720
1721 Return Value:
1722 Points to the end of extension.
1723
1724 Arguments:
1725 `rps`: Hooks and status for parsing extensions.
1726 `arch`: Full ISA string.
1727 `p`: Curent parsing position. */
1728
1729 static const char *
1730 riscv_parse_prefixed_ext (riscv_parse_subset_t *rps,
1731 const char *arch,
1732 const char *p)
1733 {
1734 int major_version;
1735 int minor_version;
1736 const char *last_name;
1737 enum riscv_prefix_ext_class class;
1738
1739 while (*p)
1740 {
1741 if (*p == '_')
1742 {
1743 p++;
1744 continue;
1745 }
1746
1747 class = riscv_get_prefix_class (p);
1748 if (class == RV_ISA_CLASS_UNKNOWN)
1749 {
1750 rps->error_handler
1751 (_("%s: unknown prefix class for the ISA extension `%s'"),
1752 arch, p);
1753 return NULL;
1754 }
1755
1756 char *subset = xstrdup (p);
1757 char *q = subset;
1758 const char *end_of_version;
1759
1760 /* Extract the whole prefixed extension by '_'. */
1761 while (*++q != '\0' && *q != '_')
1762 ;
1763 /* Look forward to the first letter which is not <major>p<minor>. */
1764 bool find_any_version = false;
1765 bool find_minor_version = false;
1766 while (1)
1767 {
1768 q--;
1769 if (ISDIGIT (*q))
1770 find_any_version = true;
1771 else if (find_any_version
1772 && !find_minor_version
1773 && *q == 'p'
1774 && ISDIGIT (*(q - 1)))
1775 find_minor_version = true;
1776 else
1777 break;
1778 }
1779 q++;
1780
1781 /* Check if the end of extension is 'p' or not. If yes, then
1782 the second letter from the end cannot be number. */
1783 if (*(q - 1) == 'p' && ISDIGIT (*(q - 2)))
1784 {
1785 *q = '\0';
1786 rps->error_handler
1787 (_("%s: invalid prefixed ISA extension `%s' ends with <number>p"),
1788 arch, subset);
1789 free (subset);
1790 return NULL;
1791 }
1792
1793 end_of_version =
1794 riscv_parsing_subset_version (q, &major_version, &minor_version);
1795 *q = '\0';
1796 if (end_of_version == NULL)
1797 {
1798 free (subset);
1799 return NULL;
1800 }
1801
1802 /* Check that the extension name is well-formed. */
1803 if (rps->check_unknown_prefixed_ext
1804 && !riscv_recognized_prefixed_ext (subset))
1805 {
1806 rps->error_handler
1807 (_("%s: unknown prefixed ISA extension `%s'"),
1808 arch, subset);
1809 free (subset);
1810 return NULL;
1811 }
1812
1813 /* Check that the extension isn't duplicate. */
1814 last_name = rps->subset_list->tail->name;
1815 if (!strcasecmp (last_name, subset))
1816 {
1817 rps->error_handler
1818 (_("%s: duplicate prefixed ISA extension `%s'"),
1819 arch, subset);
1820 free (subset);
1821 return NULL;
1822 }
1823
1824 /* Check that the extension is in expected order. */
1825 if (riscv_compare_subsets (last_name, subset) > 0)
1826 {
1827 rps->error_handler
1828 (_("%s: prefixed ISA extension `%s' is not in expected "
1829 "order. It must come before `%s'"),
1830 arch, subset, last_name);
1831 free (subset);
1832 return NULL;
1833 }
1834
1835 riscv_parse_add_subset (rps, subset,
1836 major_version,
1837 minor_version, false);
1838 p += end_of_version - subset;
1839 free (subset);
1840
1841 if (*p != '\0' && *p != '_')
1842 {
1843 rps->error_handler
1844 (_("%s: prefixed ISA extension must separate with _"),
1845 arch);
1846 return NULL;
1847 }
1848 }
1849
1850 return p;
1851 }
1852
1853 /* Add the implicit extensions. */
1854
1855 static void
1856 riscv_parse_add_implicit_subsets (riscv_parse_subset_t *rps)
1857 {
1858 struct riscv_implicit_subset *t = riscv_implicit_subsets;
1859 for (; t->subset_name; t++)
1860 {
1861 riscv_subset_t *subset = NULL;
1862 if (riscv_lookup_subset (rps->subset_list, t->subset_name, &subset)
1863 && t->check_func (t->implicit_name, subset))
1864 riscv_parse_add_subset (rps, t->implicit_name,
1865 RISCV_UNKNOWN_VERSION,
1866 RISCV_UNKNOWN_VERSION, true);
1867 }
1868 }
1869
1870 /* Check extensions conflicts. */
1871
1872 static bool
1873 riscv_parse_check_conflicts (riscv_parse_subset_t *rps)
1874 {
1875 riscv_subset_t *subset = NULL;
1876 int xlen = *rps->xlen;
1877 bool no_conflict = true;
1878
1879 if (riscv_lookup_subset (rps->subset_list, "e", &subset)
1880 && xlen > 32)
1881 {
1882 rps->error_handler
1883 (_("rv%d does not support the `e' extension"), xlen);
1884 no_conflict = false;
1885 }
1886 if (riscv_lookup_subset (rps->subset_list, "q", &subset)
1887 && xlen < 64)
1888 {
1889 rps->error_handler
1890 (_("rv%d does not support the `q' extension"), xlen);
1891 no_conflict = false;
1892 }
1893 if (riscv_lookup_subset (rps->subset_list, "e", &subset)
1894 && riscv_lookup_subset (rps->subset_list, "f", &subset))
1895 {
1896 rps->error_handler
1897 (_("rv32e does not support the `f' extension"));
1898 no_conflict = false;
1899 }
1900
1901 bool support_zve = false;
1902 bool support_zvl = false;
1903 riscv_subset_t *s = rps->subset_list->head;
1904 for (; s != NULL; s = s->next)
1905 {
1906 if (!support_zve
1907 && strncmp (s->name, "zve", 3) == 0)
1908 support_zve = true;
1909 if (!support_zvl
1910 && strncmp (s->name, "zvl", 3) == 0)
1911 support_zvl = true;
1912 if (support_zve && support_zvl)
1913 break;
1914 }
1915 if (support_zvl && !support_zve)
1916 {
1917 rps->error_handler
1918 (_("zvl*b extensions need to enable either `v' or `zve' extension"));
1919 no_conflict = false;
1920 }
1921
1922 return no_conflict;
1923 }
1924
1925 /* Set the default subset list according to the default_enable field
1926 of riscv_supported_*ext tables. */
1927
1928 static void
1929 riscv_set_default_arch (riscv_parse_subset_t *rps)
1930 {
1931 unsigned long enable = EXT_DEFAULT;
1932 int i, j;
1933 for (i = 0; riscv_all_supported_ext[i] != NULL; i++)
1934 {
1935 const struct riscv_supported_ext *table = riscv_all_supported_ext[i];
1936 for (j = 0; table[j].name != NULL; j++)
1937 {
1938 bool implicit = false;
1939 if (strcmp (table[j].name, "g") == 0)
1940 implicit = true;
1941 if (table[j].default_enable & enable)
1942 riscv_parse_add_subset (rps, table[j].name,
1943 RISCV_UNKNOWN_VERSION,
1944 RISCV_UNKNOWN_VERSION, implicit);
1945 }
1946 }
1947 }
1948
1949 /* Function for parsing ISA string.
1950
1951 Return Value:
1952 Return TRUE on success.
1953
1954 Arguments:
1955 `rps`: Hooks and status for parsing extensions.
1956 `arch`: Full ISA string. */
1957
1958 bool
1959 riscv_parse_subset (riscv_parse_subset_t *rps,
1960 const char *arch)
1961 {
1962 const char *p;
1963
1964 /* Init the riscv_ext_order array to compare the order of extensions
1965 quickly. */
1966 riscv_init_ext_order ();
1967
1968 if (arch == NULL)
1969 {
1970 riscv_set_default_arch (rps);
1971 riscv_parse_add_implicit_subsets (rps);
1972 return riscv_parse_check_conflicts (rps);
1973 }
1974
1975 for (p = arch; *p != '\0'; p++)
1976 {
1977 if (ISUPPER (*p))
1978 {
1979 rps->error_handler
1980 (_("%s: ISA string cannot contain uppercase letters"),
1981 arch);
1982 return false;
1983 }
1984 }
1985
1986 p = arch;
1987 if (startswith (p, "rv32"))
1988 {
1989 *rps->xlen = 32;
1990 p += 4;
1991 }
1992 else if (startswith (p, "rv64"))
1993 {
1994 *rps->xlen = 64;
1995 p += 4;
1996 }
1997 else
1998 {
1999 /* ISA string shouldn't be NULL or empty here. For linker,
2000 it might be empty when we failed to merge the ISA string
2001 in the riscv_merge_attributes. For assembler, we might
2002 give an empty string by .attribute arch, "" or -march=.
2003 However, We have already issued the correct error message
2004 in another side, so do not issue this error when the ISA
2005 string is empty. */
2006 if (strlen (arch))
2007 rps->error_handler (
2008 _("%s: ISA string must begin with rv32 or rv64"),
2009 arch);
2010 return false;
2011 }
2012
2013 /* Parsing standard extension. */
2014 p = riscv_parse_std_ext (rps, arch, p);
2015
2016 if (p == NULL)
2017 return false;
2018
2019 /* Parse the different classes of extensions in the specified order. */
2020 while (*p != '\0')
2021 {
2022 p = riscv_parse_prefixed_ext (rps, arch, p);
2023
2024 if (p == NULL)
2025 return false;
2026 }
2027
2028 /* Finally add implicit extensions according to the current
2029 extensions. */
2030 riscv_parse_add_implicit_subsets (rps);
2031
2032 /* Check the conflicts. */
2033 return riscv_parse_check_conflicts (rps);
2034 }
2035
2036 /* Return the number of digits for the input. */
2037
2038 size_t
2039 riscv_estimate_digit (unsigned num)
2040 {
2041 size_t digit = 0;
2042 if (num == 0)
2043 return 1;
2044
2045 for (digit = 0; num ; num /= 10)
2046 digit++;
2047
2048 return digit;
2049 }
2050
2051 /* Auxiliary function to estimate string length of subset list. */
2052
2053 static size_t
2054 riscv_estimate_arch_strlen1 (const riscv_subset_t *subset)
2055 {
2056 if (subset == NULL)
2057 return 6; /* For rv32/rv64/rv128 and string terminator. */
2058
2059 return riscv_estimate_arch_strlen1 (subset->next)
2060 + strlen (subset->name)
2061 + riscv_estimate_digit (subset->major_version)
2062 + 1 /* For version seperator 'p'. */
2063 + riscv_estimate_digit (subset->minor_version)
2064 + 1 /* For underscore. */;
2065 }
2066
2067 /* Estimate the string length of this subset list. */
2068
2069 static size_t
2070 riscv_estimate_arch_strlen (const riscv_subset_list_t *subset_list)
2071 {
2072 return riscv_estimate_arch_strlen1 (subset_list->head);
2073 }
2074
2075 /* Auxiliary function to convert subset info to string. */
2076
2077 static void
2078 riscv_arch_str1 (riscv_subset_t *subset,
2079 char *attr_str, char *buf, size_t bufsz)
2080 {
2081 const char *underline = "_";
2082 riscv_subset_t *subset_t = subset;
2083
2084 if (subset_t == NULL)
2085 return;
2086
2087 /* No underline between rvXX and i/e. */
2088 if ((strcasecmp (subset_t->name, "i") == 0)
2089 || (strcasecmp (subset_t->name, "e") == 0))
2090 underline = "";
2091
2092 snprintf (buf, bufsz, "%s%s%dp%d",
2093 underline,
2094 subset_t->name,
2095 subset_t->major_version,
2096 subset_t->minor_version);
2097
2098 strncat (attr_str, buf, bufsz);
2099
2100 /* Skip 'i' extension after 'e', or skip extensions which
2101 versions are unknown. */
2102 while (subset_t->next
2103 && ((strcmp (subset_t->name, "e") == 0
2104 && strcmp (subset_t->next->name, "i") == 0)
2105 || subset_t->next->major_version == RISCV_UNKNOWN_VERSION
2106 || subset_t->next->minor_version == RISCV_UNKNOWN_VERSION))
2107 subset_t = subset_t->next;
2108
2109 riscv_arch_str1 (subset_t->next, attr_str, buf, bufsz);
2110 }
2111
2112 /* Convert subset information into string with explicit versions. */
2113
2114 char *
2115 riscv_arch_str (unsigned xlen, const riscv_subset_list_t *subset)
2116 {
2117 size_t arch_str_len = riscv_estimate_arch_strlen (subset);
2118 char *attr_str = xmalloc (arch_str_len);
2119 char *buf = xmalloc (arch_str_len);
2120
2121 snprintf (attr_str, arch_str_len, "rv%u", xlen);
2122
2123 riscv_arch_str1 (subset->head, attr_str, buf, arch_str_len);
2124 free (buf);
2125
2126 return attr_str;
2127 }
2128
2129 /* Remove the SUBSET from the subset list. */
2130
2131 static void
2132 riscv_remove_subset (riscv_subset_list_t *subset_list,
2133 const char *subset)
2134 {
2135 riscv_subset_t *current = subset_list->head;
2136 riscv_subset_t *pre = NULL;
2137 for (; current != NULL; pre = current, current = current->next)
2138 {
2139 if (strcmp (current->name, subset) == 0)
2140 {
2141 if (pre == NULL)
2142 subset_list->head = current->next;
2143 else
2144 pre->next = current->next;
2145 if (current->next == NULL)
2146 subset_list->tail = pre;
2147 free ((void *) current->name);
2148 free (current);
2149 break;
2150 }
2151 }
2152 }
2153
2154 /* Add/Remove an extension to/from the subset list. This is used for
2155 the .option rvc or norvc. */
2156
2157 bool
2158 riscv_update_subset (riscv_parse_subset_t *rps,
2159 const char *subset,
2160 bool removed)
2161 {
2162 if (strlen (subset) == 0
2163 || (strlen (subset) == 1
2164 && riscv_ext_order[(*subset - 'a')] == 0)
2165 || (strlen (subset) > 1
2166 && rps->check_unknown_prefixed_ext
2167 && !riscv_recognized_prefixed_ext (subset)))
2168 {
2169 rps->error_handler
2170 (_("riscv_update_subset: unknown ISA extension `%s'"), subset);
2171 return false;
2172 }
2173
2174 if (removed)
2175 {
2176 if (strcmp (subset, "i") == 0)
2177 {
2178 rps->error_handler
2179 (_("riscv_update_subset: cannot remove extension i from "
2180 "the subset list"));
2181 return false;
2182 }
2183 riscv_remove_subset (rps->subset_list, subset);
2184 }
2185 else
2186 riscv_parse_add_subset (rps, subset,
2187 RISCV_UNKNOWN_VERSION,
2188 RISCV_UNKNOWN_VERSION, true);
2189
2190 riscv_parse_add_implicit_subsets (rps);
2191 return riscv_parse_check_conflicts (rps);
2192 }
2193
2194 /* Check if the FEATURE subset is supported or not in the subset list.
2195 Return true if it is supported; Otherwise, return false. */
2196
2197 bool
2198 riscv_subset_supports (riscv_parse_subset_t *rps,
2199 const char *feature)
2200 {
2201 struct riscv_subset_t *subset;
2202 return riscv_lookup_subset (rps->subset_list, feature, &subset);
2203 }
2204
2205 /* Each instuction is belonged to an instruction class INSN_CLASS_*.
2206 Call riscv_subset_supports to make sure if the instuction is valid. */
2207
2208 bool
2209 riscv_multi_subset_supports (riscv_parse_subset_t *rps,
2210 enum riscv_insn_class insn_class)
2211 {
2212 switch (insn_class)
2213 {
2214 case INSN_CLASS_I:
2215 return riscv_subset_supports (rps, "i");
2216 case INSN_CLASS_ZICSR:
2217 return riscv_subset_supports (rps, "zicsr");
2218 case INSN_CLASS_ZIFENCEI:
2219 return riscv_subset_supports (rps, "zifencei");
2220 case INSN_CLASS_ZIHINTPAUSE:
2221 return riscv_subset_supports (rps, "zihintpause");
2222 case INSN_CLASS_M:
2223 return riscv_subset_supports (rps, "m");
2224 case INSN_CLASS_A:
2225 return riscv_subset_supports (rps, "a");
2226 case INSN_CLASS_F:
2227 return riscv_subset_supports (rps, "f");
2228 case INSN_CLASS_D:
2229 return riscv_subset_supports (rps, "d");
2230 case INSN_CLASS_Q:
2231 return riscv_subset_supports (rps, "q");
2232 case INSN_CLASS_C:
2233 return riscv_subset_supports (rps, "c");
2234 case INSN_CLASS_F_AND_C:
2235 return (riscv_subset_supports (rps, "f")
2236 && riscv_subset_supports (rps, "c"));
2237 case INSN_CLASS_D_AND_C:
2238 return (riscv_subset_supports (rps, "d")
2239 && riscv_subset_supports (rps, "c"));
2240 case INSN_CLASS_ZBA:
2241 return riscv_subset_supports (rps, "zba");
2242 case INSN_CLASS_ZBB:
2243 return riscv_subset_supports (rps, "zbb");
2244 case INSN_CLASS_ZBC:
2245 return riscv_subset_supports (rps, "zbc");
2246 case INSN_CLASS_ZBS:
2247 return riscv_subset_supports (rps, "zbs");
2248 case INSN_CLASS_ZBKB:
2249 return riscv_subset_supports (rps, "zbkb");
2250 case INSN_CLASS_ZBKC:
2251 return riscv_subset_supports (rps, "zbkc");
2252 case INSN_CLASS_ZBKX:
2253 return riscv_subset_supports (rps, "zbkx");
2254 case INSN_CLASS_ZBB_OR_ZBKB:
2255 return (riscv_subset_supports (rps, "zbb")
2256 || riscv_subset_supports (rps, "zbkb"));
2257 case INSN_CLASS_ZBC_OR_ZBKC:
2258 return (riscv_subset_supports (rps, "zbc")
2259 || riscv_subset_supports (rps, "zbkc"));
2260 case INSN_CLASS_ZKND:
2261 return riscv_subset_supports (rps, "zknd");
2262 case INSN_CLASS_ZKNE:
2263 return riscv_subset_supports (rps, "zkne");
2264 case INSN_CLASS_ZKNH:
2265 return riscv_subset_supports (rps, "zknh");
2266 case INSN_CLASS_ZKND_OR_ZKNE:
2267 return (riscv_subset_supports (rps, "zknd")
2268 || riscv_subset_supports (rps, "zkne"));
2269 case INSN_CLASS_ZKSED:
2270 return riscv_subset_supports (rps, "zksed");
2271 case INSN_CLASS_ZKSH:
2272 return riscv_subset_supports (rps, "zksh");
2273 case INSN_CLASS_V:
2274 return (riscv_subset_supports (rps, "v")
2275 || riscv_subset_supports (rps, "zve64x")
2276 || riscv_subset_supports (rps, "zve32x"));
2277 case INSN_CLASS_ZVEF:
2278 return (riscv_subset_supports (rps, "v")
2279 || riscv_subset_supports (rps, "zve64d")
2280 || riscv_subset_supports (rps, "zve64f")
2281 || riscv_subset_supports (rps, "zve32f"));
2282 default:
2283 rps->error_handler
2284 (_("internal: unreachable INSN_CLASS_*"));
2285 return false;
2286 }
2287 }