Automatic date update in version.in
[binutils-gdb.git] / bfd / elfxx-riscv.c
1 /* RISC-V-specific support for ELF.
2 Copyright (C) 2011-2018 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 #include <stdint.h>
33
34 #define MINUS_ONE ((bfd_vma)0 - 1)
35
36 /* Special handler for ADD/SUB relocations that allows them to be filled out
37 both in the pre-linked and post-linked file. This is necessary to make
38 pre-linked debug info work, as due to linker relaxations we need to emit
39 relocations for the debug info. */
40 static bfd_reloc_status_type riscv_elf_add_sub_reloc
41 (bfd *, arelent *, asymbol *, void *, asection *, bfd *, char **);
42
43 /* The relocation table used for SHT_RELA sections. */
44
45 static reloc_howto_type howto_table[] =
46 {
47 /* No relocation. */
48 HOWTO (R_RISCV_NONE, /* type */
49 0, /* rightshift */
50 3, /* size */
51 0, /* bitsize */
52 FALSE, /* pc_relative */
53 0, /* bitpos */
54 complain_overflow_dont, /* complain_on_overflow */
55 bfd_elf_generic_reloc, /* special_function */
56 "R_RISCV_NONE", /* name */
57 FALSE, /* partial_inplace */
58 0, /* src_mask */
59 0, /* dst_mask */
60 FALSE), /* pcrel_offset */
61
62 /* 32 bit relocation. */
63 HOWTO (R_RISCV_32, /* type */
64 0, /* rightshift */
65 2, /* size */
66 32, /* bitsize */
67 FALSE, /* pc_relative */
68 0, /* bitpos */
69 complain_overflow_dont, /* complain_on_overflow */
70 bfd_elf_generic_reloc, /* special_function */
71 "R_RISCV_32", /* name */
72 FALSE, /* partial_inplace */
73 0, /* src_mask */
74 MINUS_ONE, /* dst_mask */
75 FALSE), /* pcrel_offset */
76
77 /* 64 bit relocation. */
78 HOWTO (R_RISCV_64, /* type */
79 0, /* rightshift */
80 4, /* size */
81 64, /* bitsize */
82 FALSE, /* pc_relative */
83 0, /* bitpos */
84 complain_overflow_dont, /* complain_on_overflow */
85 bfd_elf_generic_reloc, /* special_function */
86 "R_RISCV_64", /* name */
87 FALSE, /* partial_inplace */
88 0, /* src_mask */
89 MINUS_ONE, /* dst_mask */
90 FALSE), /* pcrel_offset */
91
92 /* Relocation against a local symbol in a shared object. */
93 HOWTO (R_RISCV_RELATIVE, /* type */
94 0, /* rightshift */
95 2, /* size */
96 32, /* bitsize */
97 FALSE, /* pc_relative */
98 0, /* bitpos */
99 complain_overflow_dont, /* complain_on_overflow */
100 bfd_elf_generic_reloc, /* special_function */
101 "R_RISCV_RELATIVE", /* name */
102 FALSE, /* partial_inplace */
103 0, /* src_mask */
104 MINUS_ONE, /* dst_mask */
105 FALSE), /* pcrel_offset */
106
107 HOWTO (R_RISCV_COPY, /* type */
108 0, /* rightshift */
109 0, /* this one is variable size */
110 0, /* bitsize */
111 FALSE, /* pc_relative */
112 0, /* bitpos */
113 complain_overflow_bitfield, /* complain_on_overflow */
114 bfd_elf_generic_reloc, /* special_function */
115 "R_RISCV_COPY", /* name */
116 FALSE, /* partial_inplace */
117 0, /* src_mask */
118 0, /* dst_mask */
119 FALSE), /* pcrel_offset */
120
121 HOWTO (R_RISCV_JUMP_SLOT, /* type */
122 0, /* rightshift */
123 4, /* size */
124 64, /* bitsize */
125 FALSE, /* pc_relative */
126 0, /* bitpos */
127 complain_overflow_bitfield, /* complain_on_overflow */
128 bfd_elf_generic_reloc, /* special_function */
129 "R_RISCV_JUMP_SLOT", /* name */
130 FALSE, /* partial_inplace */
131 0, /* src_mask */
132 0, /* dst_mask */
133 FALSE), /* pcrel_offset */
134
135 /* Dynamic TLS relocations. */
136 HOWTO (R_RISCV_TLS_DTPMOD32, /* type */
137 0, /* rightshift */
138 4, /* size */
139 32, /* bitsize */
140 FALSE, /* pc_relative */
141 0, /* bitpos */
142 complain_overflow_dont, /* complain_on_overflow */
143 bfd_elf_generic_reloc, /* special_function */
144 "R_RISCV_TLS_DTPMOD32", /* name */
145 FALSE, /* partial_inplace */
146 0, /* src_mask */
147 MINUS_ONE, /* dst_mask */
148 FALSE), /* pcrel_offset */
149
150 HOWTO (R_RISCV_TLS_DTPMOD64, /* type */
151 0, /* rightshift */
152 4, /* size */
153 64, /* bitsize */
154 FALSE, /* pc_relative */
155 0, /* bitpos */
156 complain_overflow_dont, /* complain_on_overflow */
157 bfd_elf_generic_reloc, /* special_function */
158 "R_RISCV_TLS_DTPMOD64", /* name */
159 FALSE, /* partial_inplace */
160 0, /* src_mask */
161 MINUS_ONE, /* dst_mask */
162 FALSE), /* pcrel_offset */
163
164 HOWTO (R_RISCV_TLS_DTPREL32, /* type */
165 0, /* rightshift */
166 4, /* size */
167 32, /* bitsize */
168 FALSE, /* pc_relative */
169 0, /* bitpos */
170 complain_overflow_dont, /* complain_on_overflow */
171 bfd_elf_generic_reloc, /* special_function */
172 "R_RISCV_TLS_DTPREL32", /* name */
173 TRUE, /* partial_inplace */
174 0, /* src_mask */
175 MINUS_ONE, /* dst_mask */
176 FALSE), /* pcrel_offset */
177
178 HOWTO (R_RISCV_TLS_DTPREL64, /* type */
179 0, /* rightshift */
180 4, /* size */
181 64, /* bitsize */
182 FALSE, /* pc_relative */
183 0, /* bitpos */
184 complain_overflow_dont, /* complain_on_overflow */
185 bfd_elf_generic_reloc, /* special_function */
186 "R_RISCV_TLS_DTPREL64", /* name */
187 TRUE, /* partial_inplace */
188 0, /* src_mask */
189 MINUS_ONE, /* dst_mask */
190 FALSE), /* pcrel_offset */
191
192 HOWTO (R_RISCV_TLS_TPREL32, /* type */
193 0, /* rightshift */
194 2, /* size */
195 32, /* bitsize */
196 FALSE, /* pc_relative */
197 0, /* bitpos */
198 complain_overflow_dont, /* complain_on_overflow */
199 bfd_elf_generic_reloc, /* special_function */
200 "R_RISCV_TLS_TPREL32", /* name */
201 FALSE, /* partial_inplace */
202 0, /* src_mask */
203 MINUS_ONE, /* dst_mask */
204 FALSE), /* pcrel_offset */
205
206 HOWTO (R_RISCV_TLS_TPREL64, /* type */
207 0, /* rightshift */
208 4, /* size */
209 64, /* bitsize */
210 FALSE, /* pc_relative */
211 0, /* bitpos */
212 complain_overflow_dont, /* complain_on_overflow */
213 bfd_elf_generic_reloc, /* special_function */
214 "R_RISCV_TLS_TPREL64", /* name */
215 FALSE, /* partial_inplace */
216 0, /* src_mask */
217 MINUS_ONE, /* dst_mask */
218 FALSE), /* pcrel_offset */
219
220 /* Reserved for future relocs that the dynamic linker must understand. */
221 EMPTY_HOWTO (12),
222 EMPTY_HOWTO (13),
223 EMPTY_HOWTO (14),
224 EMPTY_HOWTO (15),
225
226 /* 12-bit PC-relative branch offset. */
227 HOWTO (R_RISCV_BRANCH, /* type */
228 0, /* rightshift */
229 2, /* size */
230 32, /* bitsize */
231 TRUE, /* pc_relative */
232 0, /* bitpos */
233 complain_overflow_signed, /* complain_on_overflow */
234 bfd_elf_generic_reloc, /* special_function */
235 "R_RISCV_BRANCH", /* name */
236 FALSE, /* partial_inplace */
237 0, /* src_mask */
238 ENCODE_SBTYPE_IMM (-1U), /* dst_mask */
239 TRUE), /* pcrel_offset */
240
241 /* 20-bit PC-relative jump offset. */
242 HOWTO (R_RISCV_JAL, /* type */
243 0, /* rightshift */
244 2, /* size */
245 32, /* bitsize */
246 TRUE, /* pc_relative */
247 0, /* bitpos */
248 complain_overflow_dont, /* complain_on_overflow */
249 bfd_elf_generic_reloc, /* special_function */
250 "R_RISCV_JAL", /* name */
251 FALSE, /* partial_inplace */
252 0, /* src_mask */
253 ENCODE_UJTYPE_IMM (-1U), /* dst_mask */
254 TRUE), /* pcrel_offset */
255
256 /* 32-bit PC-relative function call (AUIPC/JALR). */
257 HOWTO (R_RISCV_CALL, /* type */
258 0, /* rightshift */
259 2, /* size */
260 64, /* bitsize */
261 TRUE, /* pc_relative */
262 0, /* bitpos */
263 complain_overflow_dont, /* complain_on_overflow */
264 bfd_elf_generic_reloc, /* special_function */
265 "R_RISCV_CALL", /* name */
266 FALSE, /* partial_inplace */
267 0, /* src_mask */
268 ENCODE_UTYPE_IMM (-1U) | ((bfd_vma) ENCODE_ITYPE_IMM (-1U) << 32),
269 /* dst_mask */
270 TRUE), /* pcrel_offset */
271
272 /* Like R_RISCV_CALL, but not locally binding. */
273 HOWTO (R_RISCV_CALL_PLT, /* type */
274 0, /* rightshift */
275 2, /* size */
276 64, /* bitsize */
277 TRUE, /* pc_relative */
278 0, /* bitpos */
279 complain_overflow_dont, /* complain_on_overflow */
280 bfd_elf_generic_reloc, /* special_function */
281 "R_RISCV_CALL_PLT", /* name */
282 FALSE, /* partial_inplace */
283 0, /* src_mask */
284 ENCODE_UTYPE_IMM (-1U) | ((bfd_vma) ENCODE_ITYPE_IMM (-1U) << 32),
285 /* dst_mask */
286 TRUE), /* pcrel_offset */
287
288 /* High 20 bits of 32-bit PC-relative GOT access. */
289 HOWTO (R_RISCV_GOT_HI20, /* type */
290 0, /* rightshift */
291 2, /* size */
292 32, /* bitsize */
293 TRUE, /* pc_relative */
294 0, /* bitpos */
295 complain_overflow_dont, /* complain_on_overflow */
296 bfd_elf_generic_reloc, /* special_function */
297 "R_RISCV_GOT_HI20", /* name */
298 FALSE, /* partial_inplace */
299 0, /* src_mask */
300 ENCODE_UTYPE_IMM (-1U), /* dst_mask */
301 FALSE), /* pcrel_offset */
302
303 /* High 20 bits of 32-bit PC-relative TLS IE GOT access. */
304 HOWTO (R_RISCV_TLS_GOT_HI20, /* type */
305 0, /* rightshift */
306 2, /* size */
307 32, /* bitsize */
308 TRUE, /* pc_relative */
309 0, /* bitpos */
310 complain_overflow_dont, /* complain_on_overflow */
311 bfd_elf_generic_reloc, /* special_function */
312 "R_RISCV_TLS_GOT_HI20", /* name */
313 FALSE, /* partial_inplace */
314 0, /* src_mask */
315 ENCODE_UTYPE_IMM (-1U), /* dst_mask */
316 FALSE), /* pcrel_offset */
317
318 /* High 20 bits of 32-bit PC-relative TLS GD GOT reference. */
319 HOWTO (R_RISCV_TLS_GD_HI20, /* type */
320 0, /* rightshift */
321 2, /* size */
322 32, /* bitsize */
323 TRUE, /* pc_relative */
324 0, /* bitpos */
325 complain_overflow_dont, /* complain_on_overflow */
326 bfd_elf_generic_reloc, /* special_function */
327 "R_RISCV_TLS_GD_HI20", /* name */
328 FALSE, /* partial_inplace */
329 0, /* src_mask */
330 ENCODE_UTYPE_IMM (-1U), /* dst_mask */
331 FALSE), /* pcrel_offset */
332
333 /* High 20 bits of 32-bit PC-relative reference. */
334 HOWTO (R_RISCV_PCREL_HI20, /* type */
335 0, /* rightshift */
336 2, /* size */
337 32, /* bitsize */
338 TRUE, /* pc_relative */
339 0, /* bitpos */
340 complain_overflow_dont, /* complain_on_overflow */
341 bfd_elf_generic_reloc, /* special_function */
342 "R_RISCV_PCREL_HI20", /* name */
343 FALSE, /* partial_inplace */
344 0, /* src_mask */
345 ENCODE_UTYPE_IMM (-1U), /* dst_mask */
346 TRUE), /* pcrel_offset */
347
348 /* Low 12 bits of a 32-bit PC-relative load or add. */
349 HOWTO (R_RISCV_PCREL_LO12_I, /* type */
350 0, /* rightshift */
351 2, /* size */
352 32, /* bitsize */
353 FALSE, /* pc_relative */
354 0, /* bitpos */
355 complain_overflow_dont, /* complain_on_overflow */
356 bfd_elf_generic_reloc, /* special_function */
357 "R_RISCV_PCREL_LO12_I", /* name */
358 FALSE, /* partial_inplace */
359 0, /* src_mask */
360 ENCODE_ITYPE_IMM (-1U), /* dst_mask */
361 FALSE), /* pcrel_offset */
362
363 /* Low 12 bits of a 32-bit PC-relative store. */
364 HOWTO (R_RISCV_PCREL_LO12_S, /* type */
365 0, /* rightshift */
366 2, /* size */
367 32, /* bitsize */
368 FALSE, /* pc_relative */
369 0, /* bitpos */
370 complain_overflow_dont, /* complain_on_overflow */
371 bfd_elf_generic_reloc, /* special_function */
372 "R_RISCV_PCREL_LO12_S", /* name */
373 FALSE, /* partial_inplace */
374 0, /* src_mask */
375 ENCODE_STYPE_IMM (-1U), /* dst_mask */
376 FALSE), /* pcrel_offset */
377
378 /* High 20 bits of 32-bit absolute address. */
379 HOWTO (R_RISCV_HI20, /* type */
380 0, /* rightshift */
381 2, /* size */
382 32, /* bitsize */
383 FALSE, /* pc_relative */
384 0, /* bitpos */
385 complain_overflow_dont, /* complain_on_overflow */
386 bfd_elf_generic_reloc, /* special_function */
387 "R_RISCV_HI20", /* name */
388 FALSE, /* partial_inplace */
389 0, /* src_mask */
390 ENCODE_UTYPE_IMM (-1U), /* dst_mask */
391 FALSE), /* pcrel_offset */
392
393 /* High 12 bits of 32-bit load or add. */
394 HOWTO (R_RISCV_LO12_I, /* type */
395 0, /* rightshift */
396 2, /* size */
397 32, /* bitsize */
398 FALSE, /* pc_relative */
399 0, /* bitpos */
400 complain_overflow_dont, /* complain_on_overflow */
401 bfd_elf_generic_reloc, /* special_function */
402 "R_RISCV_LO12_I", /* name */
403 FALSE, /* partial_inplace */
404 0, /* src_mask */
405 ENCODE_ITYPE_IMM (-1U), /* dst_mask */
406 FALSE), /* pcrel_offset */
407
408 /* High 12 bits of 32-bit store. */
409 HOWTO (R_RISCV_LO12_S, /* type */
410 0, /* rightshift */
411 2, /* size */
412 32, /* bitsize */
413 FALSE, /* pc_relative */
414 0, /* bitpos */
415 complain_overflow_dont, /* complain_on_overflow */
416 bfd_elf_generic_reloc, /* special_function */
417 "R_RISCV_LO12_S", /* name */
418 FALSE, /* partial_inplace */
419 0, /* src_mask */
420 ENCODE_STYPE_IMM (-1U), /* dst_mask */
421 FALSE), /* pcrel_offset */
422
423 /* High 20 bits of TLS LE thread pointer offset. */
424 HOWTO (R_RISCV_TPREL_HI20, /* type */
425 0, /* rightshift */
426 2, /* size */
427 32, /* bitsize */
428 FALSE, /* pc_relative */
429 0, /* bitpos */
430 complain_overflow_signed, /* complain_on_overflow */
431 bfd_elf_generic_reloc, /* special_function */
432 "R_RISCV_TPREL_HI20", /* name */
433 TRUE, /* partial_inplace */
434 0, /* src_mask */
435 ENCODE_UTYPE_IMM (-1U), /* dst_mask */
436 FALSE), /* pcrel_offset */
437
438 /* Low 12 bits of TLS LE thread pointer offset for loads and adds. */
439 HOWTO (R_RISCV_TPREL_LO12_I, /* type */
440 0, /* rightshift */
441 2, /* size */
442 32, /* bitsize */
443 FALSE, /* pc_relative */
444 0, /* bitpos */
445 complain_overflow_signed, /* complain_on_overflow */
446 bfd_elf_generic_reloc, /* special_function */
447 "R_RISCV_TPREL_LO12_I", /* name */
448 FALSE, /* partial_inplace */
449 0, /* src_mask */
450 ENCODE_ITYPE_IMM (-1U), /* dst_mask */
451 FALSE), /* pcrel_offset */
452
453 /* Low 12 bits of TLS LE thread pointer offset for stores. */
454 HOWTO (R_RISCV_TPREL_LO12_S, /* type */
455 0, /* rightshift */
456 2, /* size */
457 32, /* bitsize */
458 FALSE, /* pc_relative */
459 0, /* bitpos */
460 complain_overflow_signed, /* complain_on_overflow */
461 bfd_elf_generic_reloc, /* special_function */
462 "R_RISCV_TPREL_LO12_S", /* name */
463 FALSE, /* partial_inplace */
464 0, /* src_mask */
465 ENCODE_STYPE_IMM (-1U), /* dst_mask */
466 FALSE), /* pcrel_offset */
467
468 /* TLS LE thread pointer usage. May be relaxed. */
469 HOWTO (R_RISCV_TPREL_ADD, /* type */
470 0, /* rightshift */
471 2, /* size */
472 32, /* bitsize */
473 FALSE, /* pc_relative */
474 0, /* bitpos */
475 complain_overflow_dont, /* complain_on_overflow */
476 bfd_elf_generic_reloc, /* special_function */
477 "R_RISCV_TPREL_ADD", /* name */
478 TRUE, /* partial_inplace */
479 0, /* src_mask */
480 0, /* dst_mask */
481 FALSE), /* pcrel_offset */
482
483 /* 8-bit in-place addition, for local label subtraction. */
484 HOWTO (R_RISCV_ADD8, /* type */
485 0, /* rightshift */
486 0, /* size */
487 8, /* bitsize */
488 FALSE, /* pc_relative */
489 0, /* bitpos */
490 complain_overflow_dont, /* complain_on_overflow */
491 riscv_elf_add_sub_reloc, /* special_function */
492 "R_RISCV_ADD8", /* name */
493 FALSE, /* partial_inplace */
494 0, /* src_mask */
495 MINUS_ONE, /* dst_mask */
496 FALSE), /* pcrel_offset */
497
498 /* 16-bit in-place addition, for local label subtraction. */
499 HOWTO (R_RISCV_ADD16, /* type */
500 0, /* rightshift */
501 1, /* size */
502 16, /* bitsize */
503 FALSE, /* pc_relative */
504 0, /* bitpos */
505 complain_overflow_dont, /* complain_on_overflow */
506 riscv_elf_add_sub_reloc, /* special_function */
507 "R_RISCV_ADD16", /* name */
508 FALSE, /* partial_inplace */
509 0, /* src_mask */
510 MINUS_ONE, /* dst_mask */
511 FALSE), /* pcrel_offset */
512
513 /* 32-bit in-place addition, for local label subtraction. */
514 HOWTO (R_RISCV_ADD32, /* type */
515 0, /* rightshift */
516 2, /* size */
517 32, /* bitsize */
518 FALSE, /* pc_relative */
519 0, /* bitpos */
520 complain_overflow_dont, /* complain_on_overflow */
521 riscv_elf_add_sub_reloc, /* special_function */
522 "R_RISCV_ADD32", /* name */
523 FALSE, /* partial_inplace */
524 0, /* src_mask */
525 MINUS_ONE, /* dst_mask */
526 FALSE), /* pcrel_offset */
527
528 /* 64-bit in-place addition, for local label subtraction. */
529 HOWTO (R_RISCV_ADD64, /* type */
530 0, /* rightshift */
531 4, /* size */
532 64, /* bitsize */
533 FALSE, /* pc_relative */
534 0, /* bitpos */
535 complain_overflow_dont, /* complain_on_overflow */
536 riscv_elf_add_sub_reloc, /* special_function */
537 "R_RISCV_ADD64", /* name */
538 FALSE, /* partial_inplace */
539 0, /* src_mask */
540 MINUS_ONE, /* dst_mask */
541 FALSE), /* pcrel_offset */
542
543 /* 8-bit in-place addition, for local label subtraction. */
544 HOWTO (R_RISCV_SUB8, /* type */
545 0, /* rightshift */
546 0, /* size */
547 8, /* bitsize */
548 FALSE, /* pc_relative */
549 0, /* bitpos */
550 complain_overflow_dont, /* complain_on_overflow */
551 riscv_elf_add_sub_reloc, /* special_function */
552 "R_RISCV_SUB8", /* name */
553 FALSE, /* partial_inplace */
554 0, /* src_mask */
555 MINUS_ONE, /* dst_mask */
556 FALSE), /* pcrel_offset */
557
558 /* 16-bit in-place addition, for local label subtraction. */
559 HOWTO (R_RISCV_SUB16, /* type */
560 0, /* rightshift */
561 1, /* size */
562 16, /* bitsize */
563 FALSE, /* pc_relative */
564 0, /* bitpos */
565 complain_overflow_dont, /* complain_on_overflow */
566 riscv_elf_add_sub_reloc, /* special_function */
567 "R_RISCV_SUB16", /* name */
568 FALSE, /* partial_inplace */
569 0, /* src_mask */
570 MINUS_ONE, /* dst_mask */
571 FALSE), /* pcrel_offset */
572
573 /* 32-bit in-place addition, for local label subtraction. */
574 HOWTO (R_RISCV_SUB32, /* type */
575 0, /* rightshift */
576 2, /* size */
577 32, /* bitsize */
578 FALSE, /* pc_relative */
579 0, /* bitpos */
580 complain_overflow_dont, /* complain_on_overflow */
581 riscv_elf_add_sub_reloc, /* special_function */
582 "R_RISCV_SUB32", /* name */
583 FALSE, /* partial_inplace */
584 0, /* src_mask */
585 MINUS_ONE, /* dst_mask */
586 FALSE), /* pcrel_offset */
587
588 /* 64-bit in-place addition, for local label subtraction. */
589 HOWTO (R_RISCV_SUB64, /* type */
590 0, /* rightshift */
591 4, /* size */
592 64, /* bitsize */
593 FALSE, /* pc_relative */
594 0, /* bitpos */
595 complain_overflow_dont, /* complain_on_overflow */
596 riscv_elf_add_sub_reloc, /* special_function */
597 "R_RISCV_SUB64", /* name */
598 FALSE, /* partial_inplace */
599 0, /* src_mask */
600 MINUS_ONE, /* dst_mask */
601 FALSE), /* pcrel_offset */
602
603 /* GNU extension to record C++ vtable hierarchy */
604 HOWTO (R_RISCV_GNU_VTINHERIT, /* type */
605 0, /* rightshift */
606 4, /* size */
607 0, /* bitsize */
608 FALSE, /* pc_relative */
609 0, /* bitpos */
610 complain_overflow_dont, /* complain_on_overflow */
611 NULL, /* special_function */
612 "R_RISCV_GNU_VTINHERIT", /* name */
613 FALSE, /* partial_inplace */
614 0, /* src_mask */
615 0, /* dst_mask */
616 FALSE), /* pcrel_offset */
617
618 /* GNU extension to record C++ vtable member usage */
619 HOWTO (R_RISCV_GNU_VTENTRY, /* type */
620 0, /* rightshift */
621 4, /* size */
622 0, /* bitsize */
623 FALSE, /* pc_relative */
624 0, /* bitpos */
625 complain_overflow_dont, /* complain_on_overflow */
626 _bfd_elf_rel_vtable_reloc_fn, /* special_function */
627 "R_RISCV_GNU_VTENTRY", /* name */
628 FALSE, /* partial_inplace */
629 0, /* src_mask */
630 0, /* dst_mask */
631 FALSE), /* pcrel_offset */
632
633 /* Indicates an alignment statement. The addend field encodes how many
634 bytes of NOPs follow the statement. The desired alignment is the
635 addend rounded up to the next power of two. */
636 HOWTO (R_RISCV_ALIGN, /* type */
637 0, /* rightshift */
638 2, /* size */
639 0, /* bitsize */
640 FALSE, /* pc_relative */
641 0, /* bitpos */
642 complain_overflow_dont, /* complain_on_overflow */
643 bfd_elf_generic_reloc, /* special_function */
644 "R_RISCV_ALIGN", /* name */
645 FALSE, /* partial_inplace */
646 0, /* src_mask */
647 0, /* dst_mask */
648 TRUE), /* pcrel_offset */
649
650 /* 8-bit PC-relative branch offset. */
651 HOWTO (R_RISCV_RVC_BRANCH, /* type */
652 0, /* rightshift */
653 2, /* size */
654 32, /* bitsize */
655 TRUE, /* pc_relative */
656 0, /* bitpos */
657 complain_overflow_signed, /* complain_on_overflow */
658 bfd_elf_generic_reloc, /* special_function */
659 "R_RISCV_RVC_BRANCH", /* name */
660 FALSE, /* partial_inplace */
661 0, /* src_mask */
662 ENCODE_RVC_B_IMM (-1U), /* dst_mask */
663 TRUE), /* pcrel_offset */
664
665 /* 11-bit PC-relative jump offset. */
666 HOWTO (R_RISCV_RVC_JUMP, /* type */
667 0, /* rightshift */
668 2, /* size */
669 32, /* bitsize */
670 TRUE, /* pc_relative */
671 0, /* bitpos */
672 complain_overflow_dont, /* complain_on_overflow */
673 bfd_elf_generic_reloc, /* special_function */
674 "R_RISCV_RVC_JUMP", /* name */
675 FALSE, /* partial_inplace */
676 0, /* src_mask */
677 ENCODE_RVC_J_IMM (-1U), /* dst_mask */
678 TRUE), /* pcrel_offset */
679
680 /* High 6 bits of 18-bit absolute address. */
681 HOWTO (R_RISCV_RVC_LUI, /* type */
682 0, /* rightshift */
683 2, /* size */
684 32, /* bitsize */
685 FALSE, /* pc_relative */
686 0, /* bitpos */
687 complain_overflow_dont, /* complain_on_overflow */
688 bfd_elf_generic_reloc, /* special_function */
689 "R_RISCV_RVC_LUI", /* name */
690 FALSE, /* partial_inplace */
691 0, /* src_mask */
692 ENCODE_RVC_IMM (-1U), /* dst_mask */
693 FALSE), /* pcrel_offset */
694
695 /* GP-relative load. */
696 HOWTO (R_RISCV_GPREL_I, /* type */
697 0, /* rightshift */
698 2, /* size */
699 32, /* bitsize */
700 FALSE, /* pc_relative */
701 0, /* bitpos */
702 complain_overflow_dont, /* complain_on_overflow */
703 bfd_elf_generic_reloc, /* special_function */
704 "R_RISCV_GPREL_I", /* name */
705 FALSE, /* partial_inplace */
706 0, /* src_mask */
707 ENCODE_ITYPE_IMM (-1U), /* dst_mask */
708 FALSE), /* pcrel_offset */
709
710 /* GP-relative store. */
711 HOWTO (R_RISCV_GPREL_S, /* type */
712 0, /* rightshift */
713 2, /* size */
714 32, /* bitsize */
715 FALSE, /* pc_relative */
716 0, /* bitpos */
717 complain_overflow_dont, /* complain_on_overflow */
718 bfd_elf_generic_reloc, /* special_function */
719 "R_RISCV_GPREL_S", /* name */
720 FALSE, /* partial_inplace */
721 0, /* src_mask */
722 ENCODE_STYPE_IMM (-1U), /* dst_mask */
723 FALSE), /* pcrel_offset */
724
725 /* TP-relative TLS LE load. */
726 HOWTO (R_RISCV_TPREL_I, /* type */
727 0, /* rightshift */
728 2, /* size */
729 32, /* bitsize */
730 FALSE, /* pc_relative */
731 0, /* bitpos */
732 complain_overflow_signed, /* complain_on_overflow */
733 bfd_elf_generic_reloc, /* special_function */
734 "R_RISCV_TPREL_I", /* name */
735 FALSE, /* partial_inplace */
736 0, /* src_mask */
737 ENCODE_ITYPE_IMM (-1U), /* dst_mask */
738 FALSE), /* pcrel_offset */
739
740 /* TP-relative TLS LE store. */
741 HOWTO (R_RISCV_TPREL_S, /* type */
742 0, /* rightshift */
743 2, /* size */
744 32, /* bitsize */
745 FALSE, /* pc_relative */
746 0, /* bitpos */
747 complain_overflow_signed, /* complain_on_overflow */
748 bfd_elf_generic_reloc, /* special_function */
749 "R_RISCV_TPREL_S", /* name */
750 FALSE, /* partial_inplace */
751 0, /* src_mask */
752 ENCODE_STYPE_IMM (-1U), /* dst_mask */
753 FALSE), /* pcrel_offset */
754
755 /* The paired relocation may be relaxed. */
756 HOWTO (R_RISCV_RELAX, /* type */
757 0, /* rightshift */
758 3, /* size */
759 0, /* bitsize */
760 FALSE, /* pc_relative */
761 0, /* bitpos */
762 complain_overflow_dont, /* complain_on_overflow */
763 bfd_elf_generic_reloc, /* special_function */
764 "R_RISCV_RELAX", /* name */
765 FALSE, /* partial_inplace */
766 0, /* src_mask */
767 0, /* dst_mask */
768 FALSE), /* pcrel_offset */
769
770 /* 6-bit in-place addition, for local label subtraction. */
771 HOWTO (R_RISCV_SUB6, /* type */
772 0, /* rightshift */
773 0, /* size */
774 8, /* bitsize */
775 FALSE, /* pc_relative */
776 0, /* bitpos */
777 complain_overflow_dont, /* complain_on_overflow */
778 riscv_elf_add_sub_reloc, /* special_function */
779 "R_RISCV_SUB6", /* name */
780 FALSE, /* partial_inplace */
781 0, /* src_mask */
782 0x3f, /* dst_mask */
783 FALSE), /* pcrel_offset */
784
785 /* 6-bit in-place setting, for local label subtraction. */
786 HOWTO (R_RISCV_SET6, /* type */
787 0, /* rightshift */
788 0, /* size */
789 8, /* bitsize */
790 FALSE, /* pc_relative */
791 0, /* bitpos */
792 complain_overflow_dont, /* complain_on_overflow */
793 bfd_elf_generic_reloc, /* special_function */
794 "R_RISCV_SET6", /* name */
795 FALSE, /* partial_inplace */
796 0, /* src_mask */
797 0x3f, /* dst_mask */
798 FALSE), /* pcrel_offset */
799
800 /* 8-bit in-place setting, for local label subtraction. */
801 HOWTO (R_RISCV_SET8, /* type */
802 0, /* rightshift */
803 0, /* size */
804 8, /* bitsize */
805 FALSE, /* pc_relative */
806 0, /* bitpos */
807 complain_overflow_dont, /* complain_on_overflow */
808 bfd_elf_generic_reloc, /* special_function */
809 "R_RISCV_SET8", /* name */
810 FALSE, /* partial_inplace */
811 0, /* src_mask */
812 MINUS_ONE, /* dst_mask */
813 FALSE), /* pcrel_offset */
814
815 /* 16-bit in-place setting, for local label subtraction. */
816 HOWTO (R_RISCV_SET16, /* type */
817 0, /* rightshift */
818 1, /* size */
819 16, /* bitsize */
820 FALSE, /* pc_relative */
821 0, /* bitpos */
822 complain_overflow_dont, /* complain_on_overflow */
823 bfd_elf_generic_reloc, /* special_function */
824 "R_RISCV_SET16", /* name */
825 FALSE, /* partial_inplace */
826 0, /* src_mask */
827 MINUS_ONE, /* dst_mask */
828 FALSE), /* pcrel_offset */
829
830 /* 32-bit in-place setting, for local label subtraction. */
831 HOWTO (R_RISCV_SET32, /* type */
832 0, /* rightshift */
833 2, /* size */
834 32, /* bitsize */
835 FALSE, /* pc_relative */
836 0, /* bitpos */
837 complain_overflow_dont, /* complain_on_overflow */
838 bfd_elf_generic_reloc, /* special_function */
839 "R_RISCV_SET32", /* name */
840 FALSE, /* partial_inplace */
841 0, /* src_mask */
842 MINUS_ONE, /* dst_mask */
843 FALSE), /* pcrel_offset */
844
845 /* 32-bit PC relative. */
846 HOWTO (R_RISCV_32_PCREL, /* type */
847 0, /* rightshift */
848 2, /* size */
849 32, /* bitsize */
850 TRUE, /* pc_relative */
851 0, /* bitpos */
852 complain_overflow_dont, /* complain_on_overflow */
853 bfd_elf_generic_reloc, /* special_function */
854 "R_RISCV_32_PCREL", /* name */
855 FALSE, /* partial_inplace */
856 0, /* src_mask */
857 MINUS_ONE, /* dst_mask */
858 FALSE), /* pcrel_offset */
859 };
860
861 /* A mapping from BFD reloc types to RISC-V ELF reloc types. */
862
863 struct elf_reloc_map
864 {
865 bfd_reloc_code_real_type bfd_val;
866 enum elf_riscv_reloc_type elf_val;
867 };
868
869 static const struct elf_reloc_map riscv_reloc_map[] =
870 {
871 { BFD_RELOC_NONE, R_RISCV_NONE },
872 { BFD_RELOC_32, R_RISCV_32 },
873 { BFD_RELOC_64, R_RISCV_64 },
874 { BFD_RELOC_RISCV_ADD8, R_RISCV_ADD8 },
875 { BFD_RELOC_RISCV_ADD16, R_RISCV_ADD16 },
876 { BFD_RELOC_RISCV_ADD32, R_RISCV_ADD32 },
877 { BFD_RELOC_RISCV_ADD64, R_RISCV_ADD64 },
878 { BFD_RELOC_RISCV_SUB8, R_RISCV_SUB8 },
879 { BFD_RELOC_RISCV_SUB16, R_RISCV_SUB16 },
880 { BFD_RELOC_RISCV_SUB32, R_RISCV_SUB32 },
881 { BFD_RELOC_RISCV_SUB64, R_RISCV_SUB64 },
882 { BFD_RELOC_CTOR, R_RISCV_64 },
883 { BFD_RELOC_12_PCREL, R_RISCV_BRANCH },
884 { BFD_RELOC_RISCV_HI20, R_RISCV_HI20 },
885 { BFD_RELOC_RISCV_LO12_I, R_RISCV_LO12_I },
886 { BFD_RELOC_RISCV_LO12_S, R_RISCV_LO12_S },
887 { BFD_RELOC_RISCV_PCREL_LO12_I, R_RISCV_PCREL_LO12_I },
888 { BFD_RELOC_RISCV_PCREL_LO12_S, R_RISCV_PCREL_LO12_S },
889 { BFD_RELOC_RISCV_CALL, R_RISCV_CALL },
890 { BFD_RELOC_RISCV_CALL_PLT, R_RISCV_CALL_PLT },
891 { BFD_RELOC_RISCV_PCREL_HI20, R_RISCV_PCREL_HI20 },
892 { BFD_RELOC_RISCV_JMP, R_RISCV_JAL },
893 { BFD_RELOC_RISCV_GOT_HI20, R_RISCV_GOT_HI20 },
894 { BFD_RELOC_RISCV_TLS_DTPMOD32, R_RISCV_TLS_DTPMOD32 },
895 { BFD_RELOC_RISCV_TLS_DTPREL32, R_RISCV_TLS_DTPREL32 },
896 { BFD_RELOC_RISCV_TLS_DTPMOD64, R_RISCV_TLS_DTPMOD64 },
897 { BFD_RELOC_RISCV_TLS_DTPREL64, R_RISCV_TLS_DTPREL64 },
898 { BFD_RELOC_RISCV_TLS_TPREL32, R_RISCV_TLS_TPREL32 },
899 { BFD_RELOC_RISCV_TLS_TPREL64, R_RISCV_TLS_TPREL64 },
900 { BFD_RELOC_RISCV_TPREL_HI20, R_RISCV_TPREL_HI20 },
901 { BFD_RELOC_RISCV_TPREL_ADD, R_RISCV_TPREL_ADD },
902 { BFD_RELOC_RISCV_TPREL_LO12_S, R_RISCV_TPREL_LO12_S },
903 { BFD_RELOC_RISCV_TPREL_LO12_I, R_RISCV_TPREL_LO12_I },
904 { BFD_RELOC_RISCV_TLS_GOT_HI20, R_RISCV_TLS_GOT_HI20 },
905 { BFD_RELOC_RISCV_TLS_GD_HI20, R_RISCV_TLS_GD_HI20 },
906 { BFD_RELOC_RISCV_ALIGN, R_RISCV_ALIGN },
907 { BFD_RELOC_RISCV_RVC_BRANCH, R_RISCV_RVC_BRANCH },
908 { BFD_RELOC_RISCV_RVC_JUMP, R_RISCV_RVC_JUMP },
909 { BFD_RELOC_RISCV_RVC_LUI, R_RISCV_RVC_LUI },
910 { BFD_RELOC_RISCV_GPREL_I, R_RISCV_GPREL_I },
911 { BFD_RELOC_RISCV_GPREL_S, R_RISCV_GPREL_S },
912 { BFD_RELOC_RISCV_TPREL_I, R_RISCV_TPREL_I },
913 { BFD_RELOC_RISCV_TPREL_S, R_RISCV_TPREL_S },
914 { BFD_RELOC_RISCV_RELAX, R_RISCV_RELAX },
915 { BFD_RELOC_RISCV_SUB6, R_RISCV_SUB6 },
916 { BFD_RELOC_RISCV_SET6, R_RISCV_SET6 },
917 { BFD_RELOC_RISCV_SET8, R_RISCV_SET8 },
918 { BFD_RELOC_RISCV_SET16, R_RISCV_SET16 },
919 { BFD_RELOC_RISCV_SET32, R_RISCV_SET32 },
920 { BFD_RELOC_RISCV_32_PCREL, R_RISCV_32_PCREL },
921 };
922
923 /* Given a BFD reloc type, return a howto structure. */
924
925 reloc_howto_type *
926 riscv_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED,
927 bfd_reloc_code_real_type code)
928 {
929 unsigned int i;
930
931 for (i = 0; i < ARRAY_SIZE (riscv_reloc_map); i++)
932 if (riscv_reloc_map[i].bfd_val == code)
933 return &howto_table[(int) riscv_reloc_map[i].elf_val];
934
935 bfd_set_error (bfd_error_bad_value);
936 return NULL;
937 }
938
939 reloc_howto_type *
940 riscv_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED, const char *r_name)
941 {
942 unsigned int i;
943
944 for (i = 0; i < ARRAY_SIZE (howto_table); i++)
945 if (howto_table[i].name && strcasecmp (howto_table[i].name, r_name) == 0)
946 return &howto_table[i];
947
948 return NULL;
949 }
950
951 reloc_howto_type *
952 riscv_elf_rtype_to_howto (bfd *abfd, unsigned int r_type)
953 {
954 if (r_type >= ARRAY_SIZE (howto_table))
955 {
956 (*_bfd_error_handler) (_("%pB: unsupported relocation type %#x"),
957 abfd, r_type);
958 bfd_set_error (bfd_error_bad_value);
959 return NULL;
960 }
961 return &howto_table[r_type];
962 }
963
964 /* Special_function of RISCV_ADD and RISCV_SUB relocations. */
965
966 static bfd_reloc_status_type
967 riscv_elf_add_sub_reloc (bfd *abfd,
968 arelent *reloc_entry,
969 asymbol *symbol,
970 void *data,
971 asection *input_section,
972 bfd *output_bfd,
973 char **error_message ATTRIBUTE_UNUSED)
974 {
975 reloc_howto_type *howto = reloc_entry->howto;
976 bfd_vma relocation;
977
978 if (output_bfd != NULL
979 && (symbol->flags & BSF_SECTION_SYM) == 0
980 && (!reloc_entry->howto->partial_inplace || reloc_entry->addend == 0))
981 {
982 reloc_entry->address += input_section->output_offset;
983 return bfd_reloc_ok;
984 }
985
986 if (output_bfd != NULL)
987 return bfd_reloc_continue;
988
989 relocation = symbol->value + symbol->section->output_section->vma
990 + symbol->section->output_offset + reloc_entry->addend;
991 bfd_vma old_value = bfd_get (howto->bitsize, abfd,
992 data + reloc_entry->address);
993
994 switch (howto->type)
995 {
996 case R_RISCV_ADD8:
997 case R_RISCV_ADD16:
998 case R_RISCV_ADD32:
999 case R_RISCV_ADD64:
1000 relocation = old_value + relocation;
1001 break;
1002 case R_RISCV_SUB6:
1003 case R_RISCV_SUB8:
1004 case R_RISCV_SUB16:
1005 case R_RISCV_SUB32:
1006 case R_RISCV_SUB64:
1007 relocation = old_value - relocation;
1008 break;
1009 }
1010 bfd_put (howto->bitsize, abfd, relocation, data + reloc_entry->address);
1011
1012 return bfd_reloc_ok;
1013 }
1014
1015 /* Parsing subset version.
1016
1017 Return Value:
1018 Points to the end of version
1019
1020 Arguments:
1021 `rps`: Hooks and status for parsing subset.
1022 `march`: Full arch string.
1023 `p`: Curent parsing position.
1024 `major_version`: Parsing result of major version, using
1025 default_major_version if version is not present in arch string.
1026 `minor_version`: Parsing result of minor version, set to 0 if version is
1027 not present in arch string, but set to `default_minor_version` if
1028 `major_version` using default_major_version.
1029 `default_major_version`: Default major version.
1030 `default_minor_version`: Default minor version.
1031 `std_ext_p`: True if parsing std extension. */
1032
1033 static const char *
1034 riscv_parsing_subset_version (riscv_parse_subset_t *rps,
1035 const char *march,
1036 const char *p,
1037 unsigned *major_version,
1038 unsigned *minor_version,
1039 unsigned default_major_version,
1040 unsigned default_minor_version,
1041 bfd_boolean std_ext_p)
1042 {
1043 bfd_boolean major_p = TRUE;
1044 unsigned version = 0;
1045 unsigned major = 0;
1046 unsigned minor = 0;
1047 char np;
1048
1049 for (;*p; ++p)
1050 {
1051 if (*p == 'p')
1052 {
1053 np = *(p + 1);
1054
1055 if (!ISDIGIT (np))
1056 {
1057 /* Might be beginning of `p` extension. */
1058 if (std_ext_p)
1059 {
1060 *major_version = version;
1061 *minor_version = 0;
1062 return p;
1063 }
1064 else
1065 {
1066 rps->error_handler ("-march=%s: Expect number after `%dp'.",
1067 march, version);
1068 return NULL;
1069 }
1070 }
1071
1072 major = version;
1073 major_p = FALSE;
1074 version = 0;
1075 }
1076 else if (ISDIGIT (*p))
1077 version = (version * 10) + (*p - '0');
1078 else
1079 break;
1080 }
1081
1082 if (major_p)
1083 major = version;
1084 else
1085 minor = version;
1086
1087 if (major == 0 && minor == 0)
1088 {
1089 /* We don't found any version string, use default version. */
1090 *major_version = default_major_version;
1091 *minor_version = default_minor_version;
1092 }
1093 else
1094 {
1095 *major_version = major;
1096 *minor_version = minor;
1097 }
1098 return p;
1099 }
1100
1101 /* Return string which contain all supported standard extensions in
1102 canonical order. */
1103
1104 const char *
1105 riscv_supported_std_ext (void)
1106 {
1107 return "mafdqlcbjtpvn";
1108 }
1109
1110 /* Parsing function for standard extensions.
1111
1112 Return Value:
1113 Points to the end of extensions.
1114
1115 Arguments:
1116 `rps`: Hooks and status for parsing subset.
1117 `march`: Full arch string.
1118 `p`: Curent parsing position. */
1119
1120 static const char *
1121 riscv_parse_std_ext (riscv_parse_subset_t *rps,
1122 const char *march, const char *p)
1123 {
1124 const char *all_std_exts = riscv_supported_std_ext ();
1125 const char *std_exts = all_std_exts;
1126
1127 unsigned major_version = 0;
1128 unsigned minor_version = 0;
1129 char std_ext = '\0';
1130
1131 /* First letter must start with i, e or g. */
1132 switch (*p)
1133 {
1134 case 'i':
1135 p++;
1136 p = riscv_parsing_subset_version (
1137 rps,
1138 march,
1139 p, &major_version, &minor_version,
1140 /* default_major_version= */ 2,
1141 /* default_minor_version= */ 0,
1142 /* std_ext_p= */TRUE);
1143 riscv_add_subset (rps->subset_list, "i", major_version, minor_version);
1144 break;
1145
1146 case 'e':
1147 p++;
1148 p = riscv_parsing_subset_version (
1149 rps,
1150 march,
1151 p, &major_version, &minor_version,
1152 /* default_major_version= */ 1,
1153 /* default_minor_version= */ 9,
1154 /* std_ext_p= */TRUE);
1155
1156 riscv_add_subset (rps->subset_list, "e", major_version, minor_version);
1157 riscv_add_subset (rps->subset_list, "i", 2, 0);
1158
1159 if (*rps->xlen > 32)
1160 {
1161 rps->error_handler ("-march=%s: rv%de is not a valid base ISA",
1162 march, *rps->xlen);
1163 return NULL;
1164 }
1165
1166 break;
1167
1168 case 'g':
1169 p++;
1170 p = riscv_parsing_subset_version (
1171 rps,
1172 march,
1173 p, &major_version, &minor_version,
1174 /* default_major_version= */ 2,
1175 /* default_minor_version= */ 0,
1176 /* std_ext_p= */TRUE);
1177 riscv_add_subset (rps->subset_list, "i", major_version, minor_version);
1178
1179 for ( ; *std_exts != 'q'; std_exts++)
1180 {
1181 const char subset[] = {*std_exts, '\0'};
1182 riscv_add_subset (
1183 rps->subset_list, subset, major_version, minor_version);
1184 }
1185 break;
1186
1187 default:
1188 rps->error_handler (
1189 "-march=%s: first ISA subset must be `e', `i' or `g'", march);
1190 return NULL;
1191 }
1192
1193 while (*p)
1194 {
1195 char subset[2] = {0, 0};
1196
1197 if (*p == 'x' || *p == 's')
1198 break;
1199
1200 if (*p == '_')
1201 {
1202 p++;
1203 continue;
1204 }
1205
1206 std_ext = *p;
1207
1208 /* Checking canonical order. */
1209 while (*std_exts && std_ext != *std_exts) std_exts++;
1210
1211 if (std_ext != *std_exts)
1212 {
1213 if (strchr (all_std_exts, std_ext) == NULL)
1214 rps->error_handler (
1215 "-march=%s: unsupported ISA subset `%c'", march, *p);
1216 else
1217 rps->error_handler (
1218 "-march=%s: ISA string is not in canonical order. `%c'",
1219 march, *p);
1220 return NULL;
1221 }
1222
1223 std_exts++;
1224
1225 p++;
1226 p = riscv_parsing_subset_version (
1227 rps,
1228 march,
1229 p, &major_version, &minor_version,
1230 /* default_major_version= */ 2,
1231 /* default_minor_version= */ 0,
1232 /* std_ext_p= */TRUE);
1233
1234 subset[0] = std_ext;
1235
1236 riscv_add_subset (rps->subset_list, subset, major_version, minor_version);
1237 }
1238 return p;
1239 }
1240
1241 /* Parsing function for non-standard and supervisor extensions.
1242
1243 Return Value:
1244 Points to the end of extensions.
1245
1246 Arguments:
1247 `rps`: Hooks and status for parsing subset.
1248 `march`: Full arch string.
1249 `p`: Curent parsing position.
1250 `ext_type`: What kind of extensions, 'x', 's' or 'sx'.
1251 `ext_type_str`: Full name for kind of extension. */
1252
1253 static const char *
1254 riscv_parse_sv_or_non_std_ext (riscv_parse_subset_t *rps,
1255 const char *march,
1256 const char *p,
1257 const char *ext_type,
1258 const char *ext_type_str)
1259 {
1260 unsigned major_version = 0;
1261 unsigned minor_version = 0;
1262 size_t ext_type_len = strlen (ext_type);
1263
1264 while (*p)
1265 {
1266 if (*p == '_')
1267 {
1268 p++;
1269 continue;
1270 }
1271
1272 if (strncmp (p, ext_type, ext_type_len) != 0)
1273 break;
1274
1275 /* It's non-standard supervisor extension if it prefix with sx. */
1276 if ((ext_type[0] == 's') && (ext_type_len == 1)
1277 && (*(p + 1) == 'x'))
1278 break;
1279
1280 char *subset = xstrdup (p);
1281 char *q = subset;
1282 const char *end_of_version;
1283
1284 while (*++q != '\0' && *q != '_' && !ISDIGIT (*q))
1285 ;
1286
1287 end_of_version =
1288 riscv_parsing_subset_version (
1289 rps,
1290 march,
1291 q, &major_version, &minor_version,
1292 /* default_major_version= */ 2,
1293 /* default_minor_version= */ 0,
1294 /* std_ext_p= */FALSE);
1295
1296 *q = '\0';
1297
1298 riscv_add_subset (rps->subset_list, subset, major_version, minor_version);
1299 free (subset);
1300 p += end_of_version - subset;
1301
1302 if (*p != '\0' && *p != '_')
1303 {
1304 rps->error_handler ("-march=%s: %s must seperate with _",
1305 march, ext_type_str);
1306 return NULL;
1307 }
1308 }
1309
1310 return p;
1311 }
1312
1313 /* Function for parsing arch string.
1314
1315 Return Value:
1316 Return TRUE on success.
1317
1318 Arguments:
1319 `rps`: Hooks and status for parsing subset.
1320 `arch`: Arch string. */
1321
1322 bfd_boolean
1323 riscv_parse_subset (riscv_parse_subset_t *rps,
1324 const char *arch)
1325 {
1326 const char *p = arch;
1327
1328 if (strncmp (p, "rv32", 4) == 0)
1329 {
1330 *rps->xlen = 32;
1331 p += 4;
1332 }
1333 else if (strncmp (p, "rv64", 4) == 0)
1334 {
1335 *rps->xlen = 64;
1336 p += 4;
1337 }
1338 else
1339 {
1340 rps->error_handler ("-march=%s: ISA string must begin with rv32 or rv64",
1341 arch);
1342 return FALSE;
1343 }
1344
1345 /* Parsing standard extension. */
1346 p = riscv_parse_std_ext (rps, arch, p);
1347
1348 if (p == NULL)
1349 return FALSE;
1350
1351 /* Parsing non-standard extension. */
1352 p = riscv_parse_sv_or_non_std_ext (
1353 rps, arch, p, "x", "non-standard extension");
1354
1355 if (p == NULL)
1356 return FALSE;
1357
1358 /* Parsing supervisor extension. */
1359 p = riscv_parse_sv_or_non_std_ext (
1360 rps, arch, p, "s", "supervisor extension");
1361
1362 if (p == NULL)
1363 return FALSE;
1364
1365 /* Parsing non-standard supervisor extension. */
1366 p = riscv_parse_sv_or_non_std_ext (
1367 rps, arch, p, "sx", "non-standard supervisor extension");
1368
1369 if (p == NULL)
1370 return FALSE;
1371
1372 if (*p != '\0')
1373 {
1374 rps->error_handler ("-march=%s: unexpected ISA string at end: %s",
1375 arch, p);
1376 return FALSE;
1377 }
1378
1379 if (riscv_lookup_subset (rps->subset_list, "e")
1380 && riscv_lookup_subset (rps->subset_list, "f"))
1381 {
1382 rps->error_handler ("-march=%s: rv32e does not support the `f' extension",
1383 arch);
1384 return FALSE;
1385 }
1386
1387 if (riscv_lookup_subset (rps->subset_list, "d")
1388 && !riscv_lookup_subset (rps->subset_list, "f"))
1389 {
1390 rps->error_handler ("-march=%s: `d' extension requires `f' extension",
1391 arch);
1392 return FALSE;
1393 }
1394
1395 if (riscv_lookup_subset (rps->subset_list, "q")
1396 && !riscv_lookup_subset (rps->subset_list, "d"))
1397 {
1398 rps->error_handler ("-march=%s: `q' extension requires `d' extension",
1399 arch);
1400 return FALSE;
1401 }
1402
1403 if (riscv_lookup_subset (rps->subset_list, "q") && *rps->xlen < 64)
1404 {
1405 rps->error_handler ("-march=%s: rv32 does not support the `q' extension",
1406 arch);
1407 return FALSE;
1408 }
1409 return TRUE;
1410 }
1411
1412 /* Add new subset to list. */
1413
1414 void
1415 riscv_add_subset (riscv_subset_list_t *subset_list,
1416 const char *subset,
1417 int major, int minor)
1418 {
1419 riscv_subset_t *s = xmalloc (sizeof *s);
1420
1421 if (subset_list->head == NULL)
1422 subset_list->head = s;
1423
1424 s->name = xstrdup (subset);
1425 s->major_version = major;
1426 s->minor_version = minor;
1427 s->next = NULL;
1428
1429 if (subset_list->tail != NULL)
1430 subset_list->tail->next = s;
1431
1432 subset_list->tail = s;
1433 }
1434
1435 /* Find subset in list without version checking, return NULL if not found. */
1436
1437 riscv_subset_t *
1438 riscv_lookup_subset (const riscv_subset_list_t *subset_list,
1439 const char *subset)
1440 {
1441 return riscv_lookup_subset_version (
1442 subset_list, subset,
1443 RISCV_DONT_CARE_VERSION,
1444 RISCV_DONT_CARE_VERSION);
1445 }
1446
1447 /* Find subset in list with version checking, return NULL if not found. */
1448
1449 riscv_subset_t *
1450 riscv_lookup_subset_version (const riscv_subset_list_t *subset_list,
1451 const char *subset,
1452 int major, int minor)
1453 {
1454 riscv_subset_t *s;
1455
1456 for (s = subset_list->head; s != NULL; s = s->next)
1457 if (strcasecmp (s->name, subset) == 0)
1458 {
1459 if ((major != RISCV_DONT_CARE_VERSION)
1460 && (s->major_version != major))
1461 return NULL;
1462
1463 if ((minor != RISCV_DONT_CARE_VERSION)
1464 && (s->minor_version != minor))
1465 return NULL;
1466
1467 return s;
1468 }
1469
1470 return NULL;
1471 }
1472
1473 /* Release subset list. */
1474
1475 void
1476 riscv_release_subset_list (riscv_subset_list_t *subset_list)
1477 {
1478 while (subset_list->head != NULL)
1479 {
1480 riscv_subset_t *next = subset_list->head->next;
1481 free ((void *)subset_list->head->name);
1482 free (subset_list->head);
1483 subset_list->head = next;
1484 }
1485
1486 subset_list->tail = NULL;
1487 }