RISC-V: Change -march parsing.
[deliverable/binutils-gdb.git] / bfd / elfxx-riscv.c
1 /* RISC-V-specific support for ELF.
2 Copyright (C) 2011-2020 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 MINUS_ONE, /* 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 MINUS_ONE, /* 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 4, /* size */
138 32, /* bitsize */
139 FALSE, /* pc_relative */
140 0, /* bitpos */
141 complain_overflow_dont, /* complain_on_overflow */
142 bfd_elf_generic_reloc, /* special_function */
143 "R_RISCV_TLS_DTPMOD32", /* name */
144 FALSE, /* partial_inplace */
145 0, /* src_mask */
146 MINUS_ONE, /* 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 4, /* size */
166 32, /* bitsize */
167 FALSE, /* pc_relative */
168 0, /* bitpos */
169 complain_overflow_dont, /* complain_on_overflow */
170 bfd_elf_generic_reloc, /* special_function */
171 "R_RISCV_TLS_DTPREL32", /* name */
172 TRUE, /* partial_inplace */
173 0, /* src_mask */
174 MINUS_ONE, /* 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 MINUS_ONE, /* 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_SBTYPE_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_UJTYPE_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 2, /* 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 2, /* 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 2, /* size */
471 32, /* 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 TRUE, /* 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 MINUS_ONE, /* 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 MINUS_ONE, /* 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 MINUS_ONE, /* 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 MINUS_ONE, /* 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 MINUS_ONE, /* 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 MINUS_ONE, /* 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 2, /* 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 TRUE), /* pcrel_offset */
648
649 /* 8-bit PC-relative branch offset. */
650 HOWTO (R_RISCV_RVC_BRANCH, /* type */
651 0, /* rightshift */
652 2, /* size */
653 32, /* 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_RVC_B_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 2, /* size */
668 32, /* 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_RVC_J_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 2, /* size */
683 32, /* 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_RVC_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 MINUS_ONE, /* 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 MINUS_ONE, /* 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 MINUS_ONE, /* 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 MINUS_ONE, /* dst_mask */
857 FALSE), /* pcrel_offset */
858 };
859
860 /* A mapping from BFD reloc types to RISC-V ELF reloc types. */
861
862 struct elf_reloc_map
863 {
864 bfd_reloc_code_real_type bfd_val;
865 enum elf_riscv_reloc_type elf_val;
866 };
867
868 static const struct elf_reloc_map riscv_reloc_map[] =
869 {
870 { BFD_RELOC_NONE, R_RISCV_NONE },
871 { BFD_RELOC_32, R_RISCV_32 },
872 { BFD_RELOC_64, R_RISCV_64 },
873 { BFD_RELOC_RISCV_ADD8, R_RISCV_ADD8 },
874 { BFD_RELOC_RISCV_ADD16, R_RISCV_ADD16 },
875 { BFD_RELOC_RISCV_ADD32, R_RISCV_ADD32 },
876 { BFD_RELOC_RISCV_ADD64, R_RISCV_ADD64 },
877 { BFD_RELOC_RISCV_SUB8, R_RISCV_SUB8 },
878 { BFD_RELOC_RISCV_SUB16, R_RISCV_SUB16 },
879 { BFD_RELOC_RISCV_SUB32, R_RISCV_SUB32 },
880 { BFD_RELOC_RISCV_SUB64, R_RISCV_SUB64 },
881 { BFD_RELOC_CTOR, R_RISCV_64 },
882 { BFD_RELOC_12_PCREL, R_RISCV_BRANCH },
883 { BFD_RELOC_RISCV_HI20, R_RISCV_HI20 },
884 { BFD_RELOC_RISCV_LO12_I, R_RISCV_LO12_I },
885 { BFD_RELOC_RISCV_LO12_S, R_RISCV_LO12_S },
886 { BFD_RELOC_RISCV_PCREL_LO12_I, R_RISCV_PCREL_LO12_I },
887 { BFD_RELOC_RISCV_PCREL_LO12_S, R_RISCV_PCREL_LO12_S },
888 { BFD_RELOC_RISCV_CALL, R_RISCV_CALL },
889 { BFD_RELOC_RISCV_CALL_PLT, R_RISCV_CALL_PLT },
890 { BFD_RELOC_RISCV_PCREL_HI20, R_RISCV_PCREL_HI20 },
891 { BFD_RELOC_RISCV_JMP, R_RISCV_JAL },
892 { BFD_RELOC_RISCV_GOT_HI20, R_RISCV_GOT_HI20 },
893 { BFD_RELOC_RISCV_TLS_DTPMOD32, R_RISCV_TLS_DTPMOD32 },
894 { BFD_RELOC_RISCV_TLS_DTPREL32, R_RISCV_TLS_DTPREL32 },
895 { BFD_RELOC_RISCV_TLS_DTPMOD64, R_RISCV_TLS_DTPMOD64 },
896 { BFD_RELOC_RISCV_TLS_DTPREL64, R_RISCV_TLS_DTPREL64 },
897 { BFD_RELOC_RISCV_TLS_TPREL32, R_RISCV_TLS_TPREL32 },
898 { BFD_RELOC_RISCV_TLS_TPREL64, R_RISCV_TLS_TPREL64 },
899 { BFD_RELOC_RISCV_TPREL_HI20, R_RISCV_TPREL_HI20 },
900 { BFD_RELOC_RISCV_TPREL_ADD, R_RISCV_TPREL_ADD },
901 { BFD_RELOC_RISCV_TPREL_LO12_S, R_RISCV_TPREL_LO12_S },
902 { BFD_RELOC_RISCV_TPREL_LO12_I, R_RISCV_TPREL_LO12_I },
903 { BFD_RELOC_RISCV_TLS_GOT_HI20, R_RISCV_TLS_GOT_HI20 },
904 { BFD_RELOC_RISCV_TLS_GD_HI20, R_RISCV_TLS_GD_HI20 },
905 { BFD_RELOC_RISCV_ALIGN, R_RISCV_ALIGN },
906 { BFD_RELOC_RISCV_RVC_BRANCH, R_RISCV_RVC_BRANCH },
907 { BFD_RELOC_RISCV_RVC_JUMP, R_RISCV_RVC_JUMP },
908 { BFD_RELOC_RISCV_RVC_LUI, R_RISCV_RVC_LUI },
909 { BFD_RELOC_RISCV_GPREL_I, R_RISCV_GPREL_I },
910 { BFD_RELOC_RISCV_GPREL_S, R_RISCV_GPREL_S },
911 { BFD_RELOC_RISCV_TPREL_I, R_RISCV_TPREL_I },
912 { BFD_RELOC_RISCV_TPREL_S, R_RISCV_TPREL_S },
913 { BFD_RELOC_RISCV_RELAX, R_RISCV_RELAX },
914 { BFD_RELOC_RISCV_SUB6, R_RISCV_SUB6 },
915 { BFD_RELOC_RISCV_SET6, R_RISCV_SET6 },
916 { BFD_RELOC_RISCV_SET8, R_RISCV_SET8 },
917 { BFD_RELOC_RISCV_SET16, R_RISCV_SET16 },
918 { BFD_RELOC_RISCV_SET32, R_RISCV_SET32 },
919 { BFD_RELOC_RISCV_32_PCREL, R_RISCV_32_PCREL },
920 };
921
922 /* Given a BFD reloc type, return a howto structure. */
923
924 reloc_howto_type *
925 riscv_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED,
926 bfd_reloc_code_real_type code)
927 {
928 unsigned int i;
929
930 for (i = 0; i < ARRAY_SIZE (riscv_reloc_map); i++)
931 if (riscv_reloc_map[i].bfd_val == code)
932 return &howto_table[(int) riscv_reloc_map[i].elf_val];
933
934 bfd_set_error (bfd_error_bad_value);
935 return NULL;
936 }
937
938 reloc_howto_type *
939 riscv_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED, const char *r_name)
940 {
941 unsigned int i;
942
943 for (i = 0; i < ARRAY_SIZE (howto_table); i++)
944 if (howto_table[i].name && strcasecmp (howto_table[i].name, r_name) == 0)
945 return &howto_table[i];
946
947 return NULL;
948 }
949
950 reloc_howto_type *
951 riscv_elf_rtype_to_howto (bfd *abfd, unsigned int r_type)
952 {
953 if (r_type >= ARRAY_SIZE (howto_table))
954 {
955 (*_bfd_error_handler) (_("%pB: unsupported relocation type %#x"),
956 abfd, r_type);
957 bfd_set_error (bfd_error_bad_value);
958 return NULL;
959 }
960 return &howto_table[r_type];
961 }
962
963 /* Special_function of RISCV_ADD and RISCV_SUB relocations. */
964
965 static bfd_reloc_status_type
966 riscv_elf_add_sub_reloc (bfd *abfd,
967 arelent *reloc_entry,
968 asymbol *symbol,
969 void *data,
970 asection *input_section,
971 bfd *output_bfd,
972 char **error_message ATTRIBUTE_UNUSED)
973 {
974 reloc_howto_type *howto = reloc_entry->howto;
975 bfd_vma relocation;
976
977 if (output_bfd != NULL
978 && (symbol->flags & BSF_SECTION_SYM) == 0
979 && (!reloc_entry->howto->partial_inplace || reloc_entry->addend == 0))
980 {
981 reloc_entry->address += input_section->output_offset;
982 return bfd_reloc_ok;
983 }
984
985 if (output_bfd != NULL)
986 return bfd_reloc_continue;
987
988 relocation = symbol->value + symbol->section->output_section->vma
989 + symbol->section->output_offset + reloc_entry->addend;
990 bfd_vma old_value = bfd_get (howto->bitsize, abfd,
991 data + reloc_entry->address);
992
993 switch (howto->type)
994 {
995 case R_RISCV_ADD8:
996 case R_RISCV_ADD16:
997 case R_RISCV_ADD32:
998 case R_RISCV_ADD64:
999 relocation = old_value + relocation;
1000 break;
1001 case R_RISCV_SUB6:
1002 case R_RISCV_SUB8:
1003 case R_RISCV_SUB16:
1004 case R_RISCV_SUB32:
1005 case R_RISCV_SUB64:
1006 relocation = old_value - relocation;
1007 break;
1008 }
1009 bfd_put (howto->bitsize, abfd, relocation, data + reloc_entry->address);
1010
1011 return bfd_reloc_ok;
1012 }
1013
1014 /* Parsing subset version.
1015
1016 Return Value:
1017 Points to the end of version
1018
1019 Arguments:
1020 `rps`: Hooks and status for parsing subset.
1021 `march`: Full arch string.
1022 `p`: Curent parsing position.
1023 `major_version`: Parsing result of major version, using
1024 default_major_version if version is not present in arch string.
1025 `minor_version`: Parsing result of minor version, set to 0 if version is
1026 not present in arch string, but set to `default_minor_version` if
1027 `major_version` using default_major_version.
1028 `default_major_version`: Default major version.
1029 `default_minor_version`: Default minor version.
1030 `std_ext_p`: True if parsing std extension. */
1031
1032 static const char *
1033 riscv_parsing_subset_version (riscv_parse_subset_t *rps,
1034 const char *march,
1035 const char *p,
1036 unsigned *major_version,
1037 unsigned *minor_version,
1038 unsigned default_major_version,
1039 unsigned default_minor_version,
1040 bfd_boolean std_ext_p)
1041 {
1042 bfd_boolean major_p = TRUE;
1043 unsigned version = 0;
1044 unsigned major = 0;
1045 unsigned minor = 0;
1046 char np;
1047
1048 for (;*p; ++p)
1049 {
1050 if (*p == 'p')
1051 {
1052 np = *(p + 1);
1053
1054 if (!ISDIGIT (np))
1055 {
1056 /* Might be beginning of `p` extension. */
1057 if (std_ext_p)
1058 {
1059 *major_version = version;
1060 *minor_version = 0;
1061 return p;
1062 }
1063 else
1064 {
1065 rps->error_handler ("-march=%s: Expect number after `%dp'.",
1066 march, version);
1067 return NULL;
1068 }
1069 }
1070
1071 major = version;
1072 major_p = FALSE;
1073 version = 0;
1074 }
1075 else if (ISDIGIT (*p))
1076 version = (version * 10) + (*p - '0');
1077 else
1078 break;
1079 }
1080
1081 if (major_p)
1082 major = version;
1083 else
1084 minor = version;
1085
1086 if (major == 0 && minor == 0)
1087 {
1088 /* We don't found any version string, use default version. */
1089 *major_version = default_major_version;
1090 *minor_version = default_minor_version;
1091 }
1092 else
1093 {
1094 *major_version = major;
1095 *minor_version = minor;
1096 }
1097 return p;
1098 }
1099
1100 /* Return string which contain all supported standard extensions in
1101 canonical order. */
1102
1103 const char *
1104 riscv_supported_std_ext (void)
1105 {
1106 return "mafdqlcbjtpvn";
1107 }
1108
1109 /* Parsing function for standard extensions.
1110
1111 Return Value:
1112 Points to the end of extensions.
1113
1114 Arguments:
1115 `rps`: Hooks and status for parsing subset.
1116 `march`: Full arch string.
1117 `p`: Curent parsing position. */
1118
1119 static const char *
1120 riscv_parse_std_ext (riscv_parse_subset_t *rps,
1121 const char *march, const char *p)
1122 {
1123 const char *all_std_exts = riscv_supported_std_ext ();
1124 const char *std_exts = all_std_exts;
1125
1126 unsigned major_version = 0;
1127 unsigned minor_version = 0;
1128 char std_ext = '\0';
1129
1130 /* First letter must start with i, e or g. */
1131 switch (*p)
1132 {
1133 case 'i':
1134 p++;
1135 p = riscv_parsing_subset_version (
1136 rps,
1137 march,
1138 p, &major_version, &minor_version,
1139 /* default_major_version= */ 2,
1140 /* default_minor_version= */ 0,
1141 /* std_ext_p= */TRUE);
1142 riscv_add_subset (rps->subset_list, "i", major_version, minor_version);
1143 break;
1144
1145 case 'e':
1146 p++;
1147 p = riscv_parsing_subset_version (
1148 rps,
1149 march,
1150 p, &major_version, &minor_version,
1151 /* default_major_version= */ 1,
1152 /* default_minor_version= */ 9,
1153 /* std_ext_p= */TRUE);
1154
1155 riscv_add_subset (rps->subset_list, "e", major_version, minor_version);
1156 riscv_add_subset (rps->subset_list, "i", 2, 0);
1157
1158 if (*rps->xlen > 32)
1159 {
1160 rps->error_handler ("-march=%s: rv%de is not a valid base ISA",
1161 march, *rps->xlen);
1162 return NULL;
1163 }
1164
1165 break;
1166
1167 case 'g':
1168 p++;
1169 p = riscv_parsing_subset_version (
1170 rps,
1171 march,
1172 p, &major_version, &minor_version,
1173 /* default_major_version= */ 2,
1174 /* default_minor_version= */ 0,
1175 /* std_ext_p= */TRUE);
1176 riscv_add_subset (rps->subset_list, "i", major_version, minor_version);
1177
1178 for ( ; *std_exts != 'q'; std_exts++)
1179 {
1180 const char subset[] = {*std_exts, '\0'};
1181 riscv_add_subset (
1182 rps->subset_list, subset, major_version, minor_version);
1183 }
1184 break;
1185
1186 default:
1187 rps->error_handler (
1188 "-march=%s: first ISA subset must be `e', `i' or `g'", march);
1189 return NULL;
1190 }
1191
1192 while (*p)
1193 {
1194 char subset[2] = {0, 0};
1195
1196 if (*p == 'x' || *p == 's' || *p == 'z')
1197 break;
1198
1199 if (*p == '_')
1200 {
1201 p++;
1202 continue;
1203 }
1204
1205 std_ext = *p;
1206
1207 /* Checking canonical order. */
1208 while (*std_exts && std_ext != *std_exts) std_exts++;
1209
1210 if (std_ext != *std_exts)
1211 {
1212 if (strchr (all_std_exts, std_ext) == NULL)
1213 rps->error_handler (
1214 "-march=%s: unsupported ISA subset `%c'", march, *p);
1215 else
1216 rps->error_handler (
1217 "-march=%s: ISA string is not in canonical order. `%c'",
1218 march, *p);
1219 return NULL;
1220 }
1221
1222 std_exts++;
1223
1224 p++;
1225 p = riscv_parsing_subset_version (
1226 rps,
1227 march,
1228 p, &major_version, &minor_version,
1229 /* default_major_version= */ 2,
1230 /* default_minor_version= */ 0,
1231 /* std_ext_p= */TRUE);
1232
1233 subset[0] = std_ext;
1234
1235 riscv_add_subset (rps->subset_list, subset, major_version, minor_version);
1236 }
1237 return p;
1238 }
1239
1240 /* Classify the argument 'arch' into one of riscv_isa_ext_class_t. */
1241
1242 riscv_isa_ext_class_t
1243 riscv_get_prefix_class (const char *arch)
1244 {
1245 switch (*arch)
1246 {
1247 case 's':
1248 return RV_ISA_CLASS_S;
1249
1250 case 'x': return RV_ISA_CLASS_X;
1251 case 'z': return RV_ISA_CLASS_Z;
1252 default: return RV_ISA_CLASS_UNKNOWN;
1253 }
1254 }
1255
1256 /* Structure describing parameters to use when parsing a particular
1257 riscv_isa_ext_class_t. One of these should be provided for each
1258 possible class, except RV_ISA_CLASS_UNKNOWN. */
1259
1260 typedef struct riscv_parse_config
1261 {
1262 /* Class of the extension. */
1263 riscv_isa_ext_class_t class;
1264
1265 /* Lower-case prefix string for error printing
1266 and internal parser usage, e.g. "z", "x". */
1267 const char *prefix;
1268
1269 /* Predicate which is used for checking whether
1270 this is a "known" extension. For 'x',
1271 it always returns true (since they are by
1272 definition non-standard and cannot be known. */
1273 bfd_boolean (*ext_valid_p) (const char *);
1274 } riscv_parse_config_t;
1275
1276 /* Parse a generic prefixed extension.
1277 march: The full architecture string as passed in by "-march=...".
1278 p: Point from which to start parsing the -march string.
1279 config: What class of extensions to parse, predicate funcs,
1280 and strings to use in error reporting. */
1281
1282 static const char *
1283 riscv_parse_prefixed_ext (riscv_parse_subset_t *rps,
1284 const char *march,
1285 const char *p,
1286 const riscv_parse_config_t *config)
1287 {
1288 unsigned major_version = 0;
1289 unsigned minor_version = 0;
1290 const char *last_name;
1291 riscv_isa_ext_class_t class;
1292
1293 while (*p)
1294 {
1295 if (*p == '_')
1296 {
1297 p++;
1298 continue;
1299 }
1300
1301 /* Assert that the current extension specifier matches our parsing
1302 class. */
1303 class = riscv_get_prefix_class (p);
1304 if (class != config->class)
1305 break;
1306
1307 char *subset = xstrdup (p);
1308 char *q = subset;
1309 const char *end_of_version;
1310
1311 while (*++q != '\0' && *q != '_' && !ISDIGIT (*q))
1312 ;
1313
1314 end_of_version =
1315 riscv_parsing_subset_version (
1316 rps,
1317 march,
1318 q, &major_version, &minor_version,
1319 /* default_major_version= */ 2,
1320 /* default_minor_version= */ 0,
1321 /* std_ext_p= */FALSE);
1322
1323 *q = '\0';
1324
1325 /* Check that the name is valid.
1326 For 'x', anything goes but it cannot simply be 'x'.
1327 For 'z', it must be known from a list and also cannot simply be 'z'.
1328 For 's', it must be known from a list and also *can* simply be 's'. */
1329
1330 /* Check that the extension name is well-formed. */
1331 if (!config->ext_valid_p (subset))
1332 {
1333 rps->error_handler
1334 ("-march=%s: Invalid or unknown %s ISA extension: '%s'",
1335 march, config->prefix, subset);
1336 free (subset);
1337 return NULL;
1338 }
1339
1340 /* Check that the last item is not the same as this. */
1341 last_name = rps->subset_list->tail->name;
1342
1343 if (!strcasecmp (last_name, subset))
1344 {
1345 rps->error_handler ("-march=%s: Duplicate %s ISA extension: \'%s\'",
1346 march, config->prefix, subset);
1347 free (subset);
1348 return NULL;
1349 }
1350
1351 /* Check that we are in alphabetical order within the subset. */
1352 if (!strncasecmp (last_name, config->prefix, 1)
1353 && strcasecmp (last_name, subset) > 0)
1354 {
1355 rps->error_handler ("-march=%s: %s ISA extension not in alphabetical "
1356 "order: \'%s\' must come before \'%s\'.",
1357 march, config->prefix, subset, last_name);
1358 free (subset);
1359 return NULL;
1360 }
1361
1362 riscv_add_subset (rps->subset_list, subset, major_version, minor_version);
1363 free (subset);
1364 p += end_of_version - subset;
1365
1366 if (*p != '\0' && *p != '_')
1367 {
1368 rps->error_handler ("-march=%s: %s must separate with _",
1369 march, config->prefix);
1370 return NULL;
1371 }
1372 }
1373
1374 return p;
1375 }
1376
1377 /* List of Z-class extensions that binutils should know about.
1378 Whether or not a particular entry is in this list will
1379 dictate if gas/ld will accept its presence in the -march
1380 string.
1381
1382 Example: To add an extension called "Zbb" (bitmanip base extension),
1383 add "zbb" string to the list (all lowercase).
1384
1385 Keep this list alphabetically ordered. */
1386
1387 static const char * const riscv_std_z_ext_strtab[] =
1388 {
1389 NULL
1390 };
1391
1392 /* Same as `riscv_std_z_ext_strtab', but for S-class extensions. */
1393
1394 static const char * const riscv_std_s_ext_strtab[] =
1395 {
1396 NULL
1397 };
1398
1399 /* For the extension EXT, search through the list of known extensions
1400 KNOWN_EXTS for a match, and return TRUE if found. */
1401
1402 static bfd_boolean
1403 riscv_multi_letter_ext_valid_p (const char *ext,
1404 const char *const *known_exts)
1405 {
1406 for (size_t i = 0; known_exts[i]; ++i)
1407 {
1408 if (!strcmp (ext, known_exts[i]))
1409 return TRUE;
1410 }
1411
1412 return FALSE;
1413 }
1414
1415 /* Predicator function for x-prefixed extensions.
1416 Anything goes, except the literal 'x'. */
1417
1418 static bfd_boolean
1419 riscv_ext_x_valid_p (const char *arg)
1420 {
1421 if (!strcasecmp (arg, "x"))
1422 return FALSE;
1423
1424 return TRUE;
1425 }
1426
1427 /* Predicator functions for z-prefixed extensions.
1428 Only known z-extensions are permitted. */
1429
1430 static bfd_boolean
1431 riscv_ext_z_valid_p (const char *arg)
1432 {
1433 return riscv_multi_letter_ext_valid_p (arg, riscv_std_z_ext_strtab);
1434 }
1435
1436 /* Predicator function for 's' prefixed extensions.
1437 Must be either literal 's', or a known s-prefixed extension. */
1438
1439 static bfd_boolean
1440 riscv_ext_s_valid_p (const char *arg)
1441 {
1442 return riscv_multi_letter_ext_valid_p (arg, riscv_std_s_ext_strtab);
1443 }
1444
1445 /* Parsing order that is specified by the ISA manual. */
1446
1447 static const riscv_parse_config_t parse_config[] =
1448 {
1449 {RV_ISA_CLASS_S, "s", riscv_ext_s_valid_p},
1450 {RV_ISA_CLASS_Z, "z", riscv_ext_z_valid_p},
1451 {RV_ISA_CLASS_X, "x", riscv_ext_x_valid_p},
1452 {RV_ISA_CLASS_UNKNOWN, NULL, NULL}
1453 };
1454
1455 /* Function for parsing arch string.
1456
1457 Return Value:
1458 Return TRUE on success.
1459
1460 Arguments:
1461 `rps`: Hooks and status for parsing subset.
1462 `arch`: Arch string. */
1463
1464 bfd_boolean
1465 riscv_parse_subset (riscv_parse_subset_t *rps,
1466 const char *arch)
1467 {
1468 const char *p = arch;
1469
1470 if (strncmp (p, "rv32", 4) == 0)
1471 {
1472 *rps->xlen = 32;
1473 p += 4;
1474 }
1475 else if (strncmp (p, "rv64", 4) == 0)
1476 {
1477 *rps->xlen = 64;
1478 p += 4;
1479 }
1480 else
1481 {
1482 rps->error_handler ("-march=%s: ISA string must begin with rv32 or rv64",
1483 arch);
1484 return FALSE;
1485 }
1486
1487 /* Parsing standard extension. */
1488 p = riscv_parse_std_ext (rps, arch, p);
1489
1490 if (p == NULL)
1491 return FALSE;
1492
1493 /* Parse the different classes of extensions in the specified order. */
1494
1495 for (size_t i = 0; i < ARRAY_SIZE (parse_config); ++i) {
1496 p = riscv_parse_prefixed_ext (rps, arch, p, &parse_config[i]);
1497
1498 if (p == NULL)
1499 return FALSE;
1500 }
1501
1502 if (*p != '\0')
1503 {
1504 rps->error_handler ("-march=%s: unexpected ISA string at end: %s",
1505 arch, p);
1506 return FALSE;
1507 }
1508
1509 if (riscv_lookup_subset (rps->subset_list, "e")
1510 && riscv_lookup_subset (rps->subset_list, "f"))
1511 {
1512 rps->error_handler ("-march=%s: rv32e does not support the `f' extension",
1513 arch);
1514 return FALSE;
1515 }
1516
1517 if (riscv_lookup_subset (rps->subset_list, "d")
1518 && !riscv_lookup_subset (rps->subset_list, "f"))
1519 {
1520 rps->error_handler ("-march=%s: `d' extension requires `f' extension",
1521 arch);
1522 return FALSE;
1523 }
1524
1525 if (riscv_lookup_subset (rps->subset_list, "q")
1526 && !riscv_lookup_subset (rps->subset_list, "d"))
1527 {
1528 rps->error_handler ("-march=%s: `q' extension requires `d' extension",
1529 arch);
1530 return FALSE;
1531 }
1532
1533 if (riscv_lookup_subset (rps->subset_list, "q") && *rps->xlen < 64)
1534 {
1535 rps->error_handler ("-march=%s: rv32 does not support the `q' extension",
1536 arch);
1537 return FALSE;
1538 }
1539 return TRUE;
1540 }
1541
1542 /* Add new subset to list. */
1543
1544 void
1545 riscv_add_subset (riscv_subset_list_t *subset_list,
1546 const char *subset,
1547 int major, int minor)
1548 {
1549 riscv_subset_t *s = xmalloc (sizeof *s);
1550
1551 if (subset_list->head == NULL)
1552 subset_list->head = s;
1553
1554 s->name = xstrdup (subset);
1555 s->major_version = major;
1556 s->minor_version = minor;
1557 s->next = NULL;
1558
1559 if (subset_list->tail != NULL)
1560 subset_list->tail->next = s;
1561
1562 subset_list->tail = s;
1563 }
1564
1565 /* Find subset in list without version checking, return NULL if not found. */
1566
1567 riscv_subset_t *
1568 riscv_lookup_subset (const riscv_subset_list_t *subset_list,
1569 const char *subset)
1570 {
1571 return riscv_lookup_subset_version (
1572 subset_list, subset,
1573 RISCV_DONT_CARE_VERSION,
1574 RISCV_DONT_CARE_VERSION);
1575 }
1576
1577 /* Find subset in list with version checking, return NULL if not found. */
1578
1579 riscv_subset_t *
1580 riscv_lookup_subset_version (const riscv_subset_list_t *subset_list,
1581 const char *subset,
1582 int major, int minor)
1583 {
1584 riscv_subset_t *s;
1585
1586 for (s = subset_list->head; s != NULL; s = s->next)
1587 if (strcasecmp (s->name, subset) == 0)
1588 {
1589 if ((major != RISCV_DONT_CARE_VERSION)
1590 && (s->major_version != major))
1591 return NULL;
1592
1593 if ((minor != RISCV_DONT_CARE_VERSION)
1594 && (s->minor_version != minor))
1595 return NULL;
1596
1597 return s;
1598 }
1599
1600 return NULL;
1601 }
1602
1603 /* Release subset list. */
1604
1605 void
1606 riscv_release_subset_list (riscv_subset_list_t *subset_list)
1607 {
1608 while (subset_list->head != NULL)
1609 {
1610 riscv_subset_t *next = subset_list->head->next;
1611 free ((void *)subset_list->head->name);
1612 free (subset_list->head);
1613 subset_list->head = next;
1614 }
1615
1616 subset_list->tail = NULL;
1617 }
1618
1619 /* Return the number of digits for the input. */
1620
1621 static size_t
1622 riscv_estimate_digit (unsigned num)
1623 {
1624 size_t digit = 0;
1625 if (num == 0)
1626 return 1;
1627
1628 for (digit = 0; num ; num /= 10)
1629 digit++;
1630
1631 return digit;
1632 }
1633
1634 /* Auxiliary function to estimate string length of subset list. */
1635
1636 static size_t
1637 riscv_estimate_arch_strlen1 (const riscv_subset_t *subset)
1638 {
1639 if (subset == NULL)
1640 return 6; /* For rv32/rv64/rv128 and string terminator. */
1641
1642 return riscv_estimate_arch_strlen1 (subset->next)
1643 + strlen (subset->name)
1644 + riscv_estimate_digit (subset->major_version)
1645 + 1 /* For version seperator: 'p'. */
1646 + riscv_estimate_digit (subset->minor_version)
1647 + 1 /* For underscore. */;
1648 }
1649
1650 /* Estimate the string length of this subset list. */
1651
1652 static size_t
1653 riscv_estimate_arch_strlen (const riscv_subset_list_t *subset_list)
1654 {
1655 return riscv_estimate_arch_strlen1 (subset_list->head);
1656 }
1657
1658 /* Auxiliary function to convert subset info to string. */
1659
1660 static void
1661 riscv_arch_str1 (riscv_subset_t *subset,
1662 char *attr_str, char *buf, size_t bufsz)
1663 {
1664 const char *underline = "_";
1665
1666 if (subset == NULL)
1667 return;
1668
1669 /* No underline between rvXX and i/e. */
1670 if ((strcasecmp (subset->name, "i") == 0)
1671 || (strcasecmp (subset->name, "e") == 0))
1672 underline = "";
1673
1674 snprintf (buf, bufsz, "%s%s%dp%d",
1675 underline,
1676 subset->name,
1677 subset->major_version,
1678 subset->minor_version);
1679
1680 strncat (attr_str, buf, bufsz);
1681
1682 /* Skip 'i' extension after 'e'. */
1683 if ((strcasecmp (subset->name, "e") == 0)
1684 && subset->next
1685 && (strcasecmp (subset->next->name, "i") == 0))
1686 riscv_arch_str1 (subset->next->next, attr_str, buf, bufsz);
1687 else
1688 riscv_arch_str1 (subset->next, attr_str, buf, bufsz);
1689 }
1690
1691 /* Convert subset info to string with explicit version info. */
1692
1693 char *
1694 riscv_arch_str (unsigned xlen, const riscv_subset_list_t *subset)
1695 {
1696 size_t arch_str_len = riscv_estimate_arch_strlen (subset);
1697 char *attr_str = xmalloc (arch_str_len);
1698 char *buf = xmalloc (arch_str_len);
1699
1700 snprintf (attr_str, arch_str_len, "rv%u", xlen);
1701
1702 riscv_arch_str1 (subset->head, attr_str, buf, arch_str_len);
1703 free (buf);
1704
1705 return attr_str;
1706 }
This page took 0.06867 seconds and 4 git commands to generate.