]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blame - bfd/elfxx-riscv.c
[PATCH] fix windmc typedef bug
[thirdparty/binutils-gdb.git] / bfd / elfxx-riscv.c
CommitLineData
e23eba97 1/* RISC-V-specific support for ELF.
b3adc24a 2 Copyright (C) 2011-2020 Free Software Foundation, Inc.
e23eba97
NC
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"
1080bf78 31#include "safe-ctype.h"
e23eba97
NC
32
33#define MINUS_ONE ((bfd_vma)0 - 1)
34
57593436
KLC
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. */
39static bfd_reloc_status_type riscv_elf_add_sub_reloc
40 (bfd *, arelent *, asymbol *, void *, asection *, bfd *, char **);
41
e23eba97
NC
42/* The relocation table used for SHT_RELA sections. */
43
44static 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 */
1d65abb5 73 MINUS_ONE, /* dst_mask */
e23eba97
NC
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 */
1d65abb5 103 MINUS_ONE, /* dst_mask */
e23eba97
NC
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 */
07d6d2b8
AM
116 0, /* src_mask */
117 0, /* dst_mask */
e23eba97
NC
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 */
07d6d2b8
AM
130 0, /* src_mask */
131 0, /* dst_mask */
e23eba97
NC
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 */
07d6d2b8 142 bfd_elf_generic_reloc, /* special_function */
e23eba97
NC
143 "R_RISCV_TLS_DTPMOD32", /* name */
144 FALSE, /* partial_inplace */
1d65abb5 145 0, /* src_mask */
e23eba97
NC
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 */
07d6d2b8 156 bfd_elf_generic_reloc, /* special_function */
e23eba97
NC
157 "R_RISCV_TLS_DTPMOD64", /* name */
158 FALSE, /* partial_inplace */
1d65abb5 159 0, /* src_mask */
e23eba97
NC
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 */
07d6d2b8 170 bfd_elf_generic_reloc, /* special_function */
e23eba97
NC
171 "R_RISCV_TLS_DTPREL32", /* name */
172 TRUE, /* partial_inplace */
1d65abb5 173 0, /* src_mask */
e23eba97
NC
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 */
07d6d2b8 184 bfd_elf_generic_reloc, /* special_function */
e23eba97
NC
185 "R_RISCV_TLS_DTPREL64", /* name */
186 TRUE, /* partial_inplace */
1d65abb5 187 0, /* src_mask */
e23eba97
NC
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 */
07d6d2b8 198 bfd_elf_generic_reloc, /* special_function */
e23eba97
NC
199 "R_RISCV_TLS_TPREL32", /* name */
200 FALSE, /* partial_inplace */
1d65abb5 201 0, /* src_mask */
e23eba97
NC
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 */
07d6d2b8 212 bfd_elf_generic_reloc, /* special_function */
e23eba97
NC
213 "R_RISCV_TLS_TPREL64", /* name */
214 FALSE, /* partial_inplace */
1d65abb5 215 0, /* src_mask */
e23eba97
NC
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 */
e23eba97
NC
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
1d65abb5 271 /* Like R_RISCV_CALL, but not locally binding. */
e23eba97
NC
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
1d65abb5 467 /* TLS LE thread pointer usage. May be relaxed. */
e23eba97
NC
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 */
0b14696a 486 8, /* bitsize */
e23eba97
NC
487 FALSE, /* pc_relative */
488 0, /* bitpos */
489 complain_overflow_dont, /* complain_on_overflow */
57593436 490 riscv_elf_add_sub_reloc, /* special_function */
e23eba97
NC
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 */
57593436 505 riscv_elf_add_sub_reloc, /* special_function */
e23eba97
NC
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 */
57593436 520 riscv_elf_add_sub_reloc, /* special_function */
e23eba97
NC
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 */
57593436 535 riscv_elf_add_sub_reloc, /* special_function */
e23eba97
NC
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 */
57593436 550 riscv_elf_add_sub_reloc, /* special_function */
e23eba97
NC
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 */
57593436 565 riscv_elf_add_sub_reloc, /* special_function */
e23eba97
NC
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 */
57593436 580 riscv_elf_add_sub_reloc, /* special_function */
e23eba97
NC
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 */
57593436 595 riscv_elf_add_sub_reloc, /* special_function */
e23eba97
NC
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 */
e23eba97
NC
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
1d65abb5 694 /* GP-relative load. */
e23eba97
NC
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
1d65abb5 709 /* GP-relative store. */
e23eba97
NC
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 */
45f76423
AW
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 */
57593436 777 riscv_elf_add_sub_reloc, /* special_function */
45f76423
AW
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 */
a6cbf936
KLC
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 */
e23eba97
NC
858};
859
860/* A mapping from BFD reloc types to RISC-V ELF reloc types. */
861
862struct elf_reloc_map
863{
864 bfd_reloc_code_real_type bfd_val;
865 enum elf_riscv_reloc_type elf_val;
866};
867
868static 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 },
45f76423
AW
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 },
a6cbf936 919 { BFD_RELOC_RISCV_32_PCREL, R_RISCV_32_PCREL },
e23eba97
NC
920};
921
922/* Given a BFD reloc type, return a howto structure. */
923
924reloc_howto_type *
925riscv_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
938reloc_howto_type *
939riscv_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
950reloc_howto_type *
0aa13fee 951riscv_elf_rtype_to_howto (bfd *abfd, unsigned int r_type)
e23eba97
NC
952{
953 if (r_type >= ARRAY_SIZE (howto_table))
954 {
0aa13fee
AM
955 (*_bfd_error_handler) (_("%pB: unsupported relocation type %#x"),
956 abfd, r_type);
e23eba97
NC
957 bfd_set_error (bfd_error_bad_value);
958 return NULL;
959 }
960 return &howto_table[r_type];
961}
57593436
KLC
962
963/* Special_function of RISCV_ADD and RISCV_SUB relocations. */
964
965static bfd_reloc_status_type
966riscv_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}
1080bf78
JW
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.
8f595e9b
NC
1028 `std_ext_p`: True if parsing std extension.
1029 `use_default_version`: Set it to True if we need the default version. */
1080bf78
JW
1030
1031static const char *
1032riscv_parsing_subset_version (riscv_parse_subset_t *rps,
1033 const char *march,
1034 const char *p,
1035 unsigned *major_version,
1036 unsigned *minor_version,
8f595e9b
NC
1037 bfd_boolean std_ext_p,
1038 bfd_boolean *use_default_version)
1080bf78
JW
1039{
1040 bfd_boolean major_p = TRUE;
1041 unsigned version = 0;
1080bf78
JW
1042 char np;
1043
8f595e9b
NC
1044 *major_version = 0;
1045 *minor_version = 0;
1046 for (; *p; ++p)
1080bf78
JW
1047 {
1048 if (*p == 'p')
1049 {
1050 np = *(p + 1);
1051
1052 if (!ISDIGIT (np))
1053 {
1054 /* Might be beginning of `p` extension. */
1055 if (std_ext_p)
1056 {
1057 *major_version = version;
1058 *minor_version = 0;
1059 return p;
1060 }
1061 else
1062 {
8f595e9b
NC
1063 rps->error_handler
1064 (_("-march=%s: Expect number after `%dp'."),
1065 march, version);
1080bf78
JW
1066 return NULL;
1067 }
1068 }
1069
8f595e9b 1070 *major_version = version;
1080bf78
JW
1071 major_p = FALSE;
1072 version = 0;
1073 }
1074 else if (ISDIGIT (*p))
1075 version = (version * 10) + (*p - '0');
1076 else
1077 break;
1078 }
1079
1080 if (major_p)
8f595e9b 1081 *major_version = version;
1080bf78 1082 else
8f595e9b 1083 *minor_version = version;
1080bf78 1084
8f595e9b
NC
1085 /* We can not find any version in string, need to parse default version. */
1086 if (use_default_version != NULL
1087 && *major_version == 0
1088 && *minor_version == 0)
1089 *use_default_version = TRUE;
1080bf78
JW
1090 return p;
1091}
1092
1093/* Return string which contain all supported standard extensions in
1094 canonical order. */
1095
1096const char *
1097riscv_supported_std_ext (void)
1098{
1099 return "mafdqlcbjtpvn";
1100}
1101
1102/* Parsing function for standard extensions.
1103
1104 Return Value:
1105 Points to the end of extensions.
1106
1107 Arguments:
1108 `rps`: Hooks and status for parsing subset.
1109 `march`: Full arch string.
1110 `p`: Curent parsing position. */
1111
1112static const char *
1113riscv_parse_std_ext (riscv_parse_subset_t *rps,
8f595e9b
NC
1114 const char *march,
1115 const char *p)
1080bf78
JW
1116{
1117 const char *all_std_exts = riscv_supported_std_ext ();
1118 const char *std_exts = all_std_exts;
1080bf78
JW
1119 unsigned major_version = 0;
1120 unsigned minor_version = 0;
1121 char std_ext = '\0';
8f595e9b 1122 bfd_boolean use_default_version = FALSE;
1080bf78
JW
1123
1124 /* First letter must start with i, e or g. */
1125 switch (*p)
1126 {
1127 case 'i':
8f595e9b
NC
1128 p = riscv_parsing_subset_version (rps,
1129 march,
1130 ++p,
1131 &major_version,
1132 &minor_version,
1133 /* std_ext_p= */TRUE,
1134 &use_default_version);
1135
1136 /* Find the default version if needed. */
1137 if (use_default_version
1138 && rps->get_default_version != NULL)
1139 rps->get_default_version ("i",
1140 &major_version,
1141 &minor_version);
1142 riscv_add_subset (rps->subset_list, "i",
1143 major_version, minor_version);
1080bf78
JW
1144 break;
1145
1146 case 'e':
8f595e9b
NC
1147 p = riscv_parsing_subset_version (rps,
1148 march,
1149 ++p,
1150 &major_version,
1151 &minor_version,
1152 /* std_ext_p= */TRUE,
1153 &use_default_version);
1154
1155 /* Find the default version if needed. */
1156 if (use_default_version
1157 && rps->get_default_version != NULL)
1158 rps->get_default_version ("e",
1159 &major_version,
1160 &minor_version);
1161 riscv_add_subset (rps->subset_list, "e",
1162 major_version, minor_version);
1163
1164 /* i-ext must be enabled. */
1165 if (rps->get_default_version != NULL)
1166 rps->get_default_version ("i",
1167 &major_version,
1168 &minor_version);
1169 riscv_add_subset (rps->subset_list, "i",
1170 major_version, minor_version);
1080bf78
JW
1171
1172 if (*rps->xlen > 32)
1173 {
8f595e9b
NC
1174 rps->error_handler
1175 (_("-march=%s: rv%de is not a valid base ISA"),
1176 march, *rps->xlen);
1080bf78
JW
1177 return NULL;
1178 }
1080bf78
JW
1179 break;
1180
1181 case 'g':
8f595e9b
NC
1182 /* The g-ext shouldn't has the version, so we just
1183 skip the setting if user set a version to it. */
1184 p = riscv_parsing_subset_version (rps,
1185 march,
1186 ++p,
1187 &major_version,
1188 &minor_version,
1189 TRUE,
1190 &use_default_version);
1191
1192 /* i-ext must be enabled. */
1193 if (rps->get_default_version != NULL)
1194 rps->get_default_version ("i",
1195 &major_version,
1196 &minor_version);
1197 riscv_add_subset (rps->subset_list, "i",
1198 major_version, minor_version);
1080bf78
JW
1199
1200 for ( ; *std_exts != 'q'; std_exts++)
1201 {
1202 const char subset[] = {*std_exts, '\0'};
8f595e9b
NC
1203
1204 if (rps->get_default_version != NULL)
1205 rps->get_default_version (subset,
1206 &major_version,
1207 &minor_version);
1208 riscv_add_subset (rps->subset_list, subset,
1209 major_version, minor_version);
1080bf78
JW
1210 }
1211 break;
1212
1213 default:
8f595e9b
NC
1214 rps->error_handler
1215 (_("-march=%s: first ISA subset must be `e', `i' or `g'"), march);
1080bf78
JW
1216 return NULL;
1217 }
1218
8f595e9b
NC
1219 /* The riscv_parsing_subset_version may set `p` to NULL, so I think we should
1220 skip parsing the string if `p` is NULL or value of `p` is `\0`. */
1221 while (p != NULL && *p != '\0')
1080bf78
JW
1222 {
1223 char subset[2] = {0, 0};
1224
403d1bd9 1225 if (*p == 'x' || *p == 's' || *p == 'z')
1080bf78
JW
1226 break;
1227
1228 if (*p == '_')
1229 {
1230 p++;
1231 continue;
1232 }
1233
1234 std_ext = *p;
1235
1236 /* Checking canonical order. */
1237 while (*std_exts && std_ext != *std_exts) std_exts++;
1238
1239 if (std_ext != *std_exts)
1240 {
1241 if (strchr (all_std_exts, std_ext) == NULL)
8f595e9b
NC
1242 rps->error_handler
1243 (_("-march=%s: unsupported ISA subset `%c'"), march, *p);
1080bf78 1244 else
8f595e9b
NC
1245 rps->error_handler
1246 (_("-march=%s: ISA string is not in canonical order. `%c'"),
1247 march, *p);
1080bf78
JW
1248 return NULL;
1249 }
1250
1251 std_exts++;
1252
8f595e9b 1253 use_default_version = FALSE;
1080bf78 1254 subset[0] = std_ext;
8f595e9b
NC
1255 p = riscv_parsing_subset_version (rps,
1256 march,
1257 ++p,
1258 &major_version,
1259 &minor_version,
1260 TRUE,
1261 &use_default_version);
1262
1263 /* Find the default version if needed. */
1264 if (use_default_version
1265 && rps->get_default_version != NULL)
1266 rps->get_default_version (subset,
1267 &major_version,
1268 &minor_version);
1269 riscv_add_subset (rps->subset_list, subset,
1270 major_version, minor_version);
1080bf78
JW
1271 }
1272 return p;
1273}
1274
403d1bd9 1275/* Classify the argument 'arch' into one of riscv_isa_ext_class_t. */
1080bf78 1276
403d1bd9
JW
1277riscv_isa_ext_class_t
1278riscv_get_prefix_class (const char *arch)
1279{
1280 switch (*arch)
1281 {
b5f998b2 1282 case 's': return RV_ISA_CLASS_S;
403d1bd9
JW
1283 case 'x': return RV_ISA_CLASS_X;
1284 case 'z': return RV_ISA_CLASS_Z;
1285 default: return RV_ISA_CLASS_UNKNOWN;
1286 }
1287}
1288
1289/* Structure describing parameters to use when parsing a particular
1290 riscv_isa_ext_class_t. One of these should be provided for each
1291 possible class, except RV_ISA_CLASS_UNKNOWN. */
1292
1293typedef struct riscv_parse_config
1294{
1295 /* Class of the extension. */
1296 riscv_isa_ext_class_t class;
1297
1298 /* Lower-case prefix string for error printing
1299 and internal parser usage, e.g. "z", "x". */
1300 const char *prefix;
1301
1302 /* Predicate which is used for checking whether
1303 this is a "known" extension. For 'x',
1304 it always returns true (since they are by
1305 definition non-standard and cannot be known. */
1306 bfd_boolean (*ext_valid_p) (const char *);
1307} riscv_parse_config_t;
1308
1309/* Parse a generic prefixed extension.
8f595e9b
NC
1310 `rps`: Hooks and status for parsing subset.
1311 `march`: The full architecture string as passed in by "-march=...".
1312 `p`: Point from which to start parsing the -march string.
1313 `config`: What class of extensions to parse, predicate funcs,
403d1bd9 1314 and strings to use in error reporting. */
1080bf78
JW
1315
1316static const char *
403d1bd9
JW
1317riscv_parse_prefixed_ext (riscv_parse_subset_t *rps,
1318 const char *march,
1319 const char *p,
1320 const riscv_parse_config_t *config)
1080bf78
JW
1321{
1322 unsigned major_version = 0;
1323 unsigned minor_version = 0;
403d1bd9
JW
1324 const char *last_name;
1325 riscv_isa_ext_class_t class;
8f595e9b 1326 bfd_boolean use_default_version;
1080bf78
JW
1327
1328 while (*p)
1329 {
1330 if (*p == '_')
1331 {
1332 p++;
1333 continue;
1334 }
1335
403d1bd9
JW
1336 /* Assert that the current extension specifier matches our parsing
1337 class. */
1338 class = riscv_get_prefix_class (p);
1339 if (class != config->class)
1080bf78
JW
1340 break;
1341
1342 char *subset = xstrdup (p);
1343 char *q = subset;
1344 const char *end_of_version;
1345
1346 while (*++q != '\0' && *q != '_' && !ISDIGIT (*q))
1347 ;
1348
8f595e9b 1349 use_default_version = FALSE;
1080bf78 1350 end_of_version =
8f595e9b
NC
1351 riscv_parsing_subset_version (rps, march, q, &major_version,
1352 &minor_version, FALSE,
1353 &use_default_version);
1080bf78
JW
1354 *q = '\0';
1355
403d1bd9
JW
1356 /* Check that the name is valid.
1357 For 'x', anything goes but it cannot simply be 'x'.
b5f998b2
JW
1358 For 's', it must be known from a list and cannot simply be 's'.
1359 For 'z', it must be known from a list and cannot simply be 'z'. */
403d1bd9
JW
1360
1361 /* Check that the extension name is well-formed. */
1362 if (!config->ext_valid_p (subset))
1363 {
1364 rps->error_handler
8f595e9b 1365 (_("-march=%s: Invalid or unknown %s ISA extension: '%s'"),
403d1bd9
JW
1366 march, config->prefix, subset);
1367 free (subset);
1368 return NULL;
1369 }
1370
1371 /* Check that the last item is not the same as this. */
1372 last_name = rps->subset_list->tail->name;
403d1bd9
JW
1373 if (!strcasecmp (last_name, subset))
1374 {
8f595e9b
NC
1375 rps->error_handler
1376 (_("-march=%s: Duplicate %s ISA extension: \'%s\'"),
1377 march, config->prefix, subset);
403d1bd9
JW
1378 free (subset);
1379 return NULL;
1380 }
1381
1382 /* Check that we are in alphabetical order within the subset. */
1383 if (!strncasecmp (last_name, config->prefix, 1)
1384 && strcasecmp (last_name, subset) > 0)
1385 {
8f595e9b
NC
1386 rps->error_handler
1387 (_("\
1388-march=%s: %s ISA extension not in alphabetical order: \'%s\' must come before \'%s\'."),
1389 march, config->prefix, subset, last_name);
403d1bd9
JW
1390 free (subset);
1391 return NULL;
1392 }
1393
8f595e9b
NC
1394 /* Find the default version if needed. */
1395 if (use_default_version
1396 && rps->get_default_version != NULL)
1397 rps->get_default_version (subset,
1398 &major_version,
1399 &minor_version);
1400 riscv_add_subset (rps->subset_list, subset,
1401 major_version, minor_version);
1402
1080bf78
JW
1403 free (subset);
1404 p += end_of_version - subset;
1405
1406 if (*p != '\0' && *p != '_')
1407 {
8f595e9b 1408 rps->error_handler (_("-march=%s: %s must separate with _"),
403d1bd9 1409 march, config->prefix);
1080bf78
JW
1410 return NULL;
1411 }
1412 }
1413
1414 return p;
1415}
1416
403d1bd9
JW
1417/* List of Z-class extensions that binutils should know about.
1418 Whether or not a particular entry is in this list will
1419 dictate if gas/ld will accept its presence in the -march
1420 string.
1421
1422 Example: To add an extension called "Zbb" (bitmanip base extension),
1423 add "zbb" string to the list (all lowercase).
1424
1425 Keep this list alphabetically ordered. */
1426
1427static const char * const riscv_std_z_ext_strtab[] =
1428 {
8f595e9b 1429 "zicsr", NULL
403d1bd9
JW
1430 };
1431
1432/* Same as `riscv_std_z_ext_strtab', but for S-class extensions. */
1433
1434static const char * const riscv_std_s_ext_strtab[] =
1435 {
1436 NULL
1437 };
1438
1439/* For the extension EXT, search through the list of known extensions
1440 KNOWN_EXTS for a match, and return TRUE if found. */
1441
1442static bfd_boolean
1443riscv_multi_letter_ext_valid_p (const char *ext,
1444 const char *const *known_exts)
1445{
2d0e1217
AM
1446 size_t i;
1447
1448 for (i = 0; known_exts[i]; ++i)
1449 if (!strcmp (ext, known_exts[i]))
1450 return TRUE;
403d1bd9
JW
1451
1452 return FALSE;
1453}
1454
1455/* Predicator function for x-prefixed extensions.
1456 Anything goes, except the literal 'x'. */
1457
1458static bfd_boolean
1459riscv_ext_x_valid_p (const char *arg)
1460{
1461 if (!strcasecmp (arg, "x"))
1462 return FALSE;
1463
1464 return TRUE;
1465}
1466
1467/* Predicator functions for z-prefixed extensions.
1468 Only known z-extensions are permitted. */
1469
1470static bfd_boolean
1471riscv_ext_z_valid_p (const char *arg)
1472{
1473 return riscv_multi_letter_ext_valid_p (arg, riscv_std_z_ext_strtab);
1474}
1475
1476/* Predicator function for 's' prefixed extensions.
1477 Must be either literal 's', or a known s-prefixed extension. */
1478
1479static bfd_boolean
1480riscv_ext_s_valid_p (const char *arg)
1481{
1482 return riscv_multi_letter_ext_valid_p (arg, riscv_std_s_ext_strtab);
1483}
1484
1485/* Parsing order that is specified by the ISA manual. */
1486
1487static const riscv_parse_config_t parse_config[] =
1488{
1489 {RV_ISA_CLASS_S, "s", riscv_ext_s_valid_p},
1490 {RV_ISA_CLASS_Z, "z", riscv_ext_z_valid_p},
1491 {RV_ISA_CLASS_X, "x", riscv_ext_x_valid_p},
1492 {RV_ISA_CLASS_UNKNOWN, NULL, NULL}
1493};
1494
1080bf78
JW
1495/* Function for parsing arch string.
1496
1497 Return Value:
1498 Return TRUE on success.
1499
1500 Arguments:
1501 `rps`: Hooks and status for parsing subset.
1502 `arch`: Arch string. */
1503
1504bfd_boolean
1505riscv_parse_subset (riscv_parse_subset_t *rps,
1506 const char *arch)
1507{
1508 const char *p = arch;
effc14f5 1509 size_t i;
1080bf78
JW
1510
1511 if (strncmp (p, "rv32", 4) == 0)
1512 {
1513 *rps->xlen = 32;
1514 p += 4;
1515 }
1516 else if (strncmp (p, "rv64", 4) == 0)
1517 {
1518 *rps->xlen = 64;
1519 p += 4;
1520 }
1521 else
1522 {
8f595e9b
NC
1523 rps->error_handler
1524 (_("-march=%s: ISA string must begin with rv32 or rv64"),
1525 arch);
1080bf78
JW
1526 return FALSE;
1527 }
1528
1529 /* Parsing standard extension. */
1530 p = riscv_parse_std_ext (rps, arch, p);
1531
1532 if (p == NULL)
1533 return FALSE;
1534
403d1bd9 1535 /* Parse the different classes of extensions in the specified order. */
effc14f5 1536 for (i = 0; i < ARRAY_SIZE (parse_config); ++i) {
403d1bd9 1537 p = riscv_parse_prefixed_ext (rps, arch, p, &parse_config[i]);
1080bf78 1538
403d1bd9
JW
1539 if (p == NULL)
1540 return FALSE;
1541 }
1080bf78
JW
1542
1543 if (*p != '\0')
1544 {
8f595e9b 1545 rps->error_handler (_("-march=%s: unexpected ISA string at end: %s"),
1080bf78
JW
1546 arch, p);
1547 return FALSE;
1548 }
1549
1550 if (riscv_lookup_subset (rps->subset_list, "e")
1551 && riscv_lookup_subset (rps->subset_list, "f"))
1552 {
8f595e9b
NC
1553 rps->error_handler
1554 (_("-march=%s: rv32e does not support the `f' extension"),
1555 arch);
1080bf78
JW
1556 return FALSE;
1557 }
1558
1559 if (riscv_lookup_subset (rps->subset_list, "d")
1560 && !riscv_lookup_subset (rps->subset_list, "f"))
1561 {
8f595e9b
NC
1562 rps->error_handler
1563 (_("-march=%s: `d' extension requires `f' extension"),
1564 arch);
1080bf78
JW
1565 return FALSE;
1566 }
1567
1568 if (riscv_lookup_subset (rps->subset_list, "q")
1569 && !riscv_lookup_subset (rps->subset_list, "d"))
1570 {
8f595e9b
NC
1571 rps->error_handler
1572 (_("-march=%s: `q' extension requires `d' extension"),
1573 arch);
1080bf78
JW
1574 return FALSE;
1575 }
1576
1577 if (riscv_lookup_subset (rps->subset_list, "q") && *rps->xlen < 64)
1578 {
8f595e9b
NC
1579 rps->error_handler
1580 (_("-march=%s: rv32 does not support the `q' extension"),
1581 arch);
1080bf78
JW
1582 return FALSE;
1583 }
1584 return TRUE;
1585}
1586
1587/* Add new subset to list. */
1588
1589void
1590riscv_add_subset (riscv_subset_list_t *subset_list,
1591 const char *subset,
8f595e9b
NC
1592 int major,
1593 int minor)
1080bf78
JW
1594{
1595 riscv_subset_t *s = xmalloc (sizeof *s);
1596
1597 if (subset_list->head == NULL)
1598 subset_list->head = s;
1599
1600 s->name = xstrdup (subset);
1601 s->major_version = major;
1602 s->minor_version = minor;
1603 s->next = NULL;
1604
1605 if (subset_list->tail != NULL)
1606 subset_list->tail->next = s;
1607
1608 subset_list->tail = s;
1609}
1610
1611/* Find subset in list without version checking, return NULL if not found. */
1612
1613riscv_subset_t *
1614riscv_lookup_subset (const riscv_subset_list_t *subset_list,
1615 const char *subset)
1616{
8f595e9b
NC
1617 return riscv_lookup_subset_version
1618 (subset_list, subset,
1619 RISCV_DONT_CARE_VERSION,
1620 RISCV_DONT_CARE_VERSION);
1080bf78
JW
1621}
1622
1623/* Find subset in list with version checking, return NULL if not found. */
1624
1625riscv_subset_t *
1626riscv_lookup_subset_version (const riscv_subset_list_t *subset_list,
1627 const char *subset,
1628 int major, int minor)
1629{
1630 riscv_subset_t *s;
1631
1632 for (s = subset_list->head; s != NULL; s = s->next)
1633 if (strcasecmp (s->name, subset) == 0)
1634 {
1635 if ((major != RISCV_DONT_CARE_VERSION)
1636 && (s->major_version != major))
1637 return NULL;
1638
1639 if ((minor != RISCV_DONT_CARE_VERSION)
1640 && (s->minor_version != minor))
1641 return NULL;
1642
1643 return s;
1644 }
1645
1646 return NULL;
1647}
1648
1649/* Release subset list. */
1650
1651void
1652riscv_release_subset_list (riscv_subset_list_t *subset_list)
1653{
1654 while (subset_list->head != NULL)
1655 {
1656 riscv_subset_t *next = subset_list->head->next;
1657 free ((void *)subset_list->head->name);
1658 free (subset_list->head);
1659 subset_list->head = next;
1660 }
1661
1662 subset_list->tail = NULL;
1663}
2dc8dd17
JW
1664
1665/* Return the number of digits for the input. */
1666
8f595e9b 1667size_t
2dc8dd17
JW
1668riscv_estimate_digit (unsigned num)
1669{
1670 size_t digit = 0;
1671 if (num == 0)
1672 return 1;
1673
1674 for (digit = 0; num ; num /= 10)
1675 digit++;
1676
1677 return digit;
1678}
1679
1680/* Auxiliary function to estimate string length of subset list. */
1681
1682static size_t
1683riscv_estimate_arch_strlen1 (const riscv_subset_t *subset)
1684{
1685 if (subset == NULL)
1686 return 6; /* For rv32/rv64/rv128 and string terminator. */
1687
1688 return riscv_estimate_arch_strlen1 (subset->next)
1689 + strlen (subset->name)
1690 + riscv_estimate_digit (subset->major_version)
1691 + 1 /* For version seperator: 'p'. */
1692 + riscv_estimate_digit (subset->minor_version)
1693 + 1 /* For underscore. */;
1694}
1695
1696/* Estimate the string length of this subset list. */
1697
1698static size_t
1699riscv_estimate_arch_strlen (const riscv_subset_list_t *subset_list)
1700{
1701 return riscv_estimate_arch_strlen1 (subset_list->head);
1702}
1703
1704/* Auxiliary function to convert subset info to string. */
1705
1706static void
1707riscv_arch_str1 (riscv_subset_t *subset,
1708 char *attr_str, char *buf, size_t bufsz)
1709{
1710 const char *underline = "_";
1711
1712 if (subset == NULL)
1713 return;
1714
1715 /* No underline between rvXX and i/e. */
1716 if ((strcasecmp (subset->name, "i") == 0)
1717 || (strcasecmp (subset->name, "e") == 0))
1718 underline = "";
1719
1720 snprintf (buf, bufsz, "%s%s%dp%d",
1721 underline,
4b24dd1a
AM
1722 subset->name,
1723 subset->major_version,
1724 subset->minor_version);
2dc8dd17
JW
1725
1726 strncat (attr_str, buf, bufsz);
1727
1728 /* Skip 'i' extension after 'e'. */
1729 if ((strcasecmp (subset->name, "e") == 0)
1730 && subset->next
1731 && (strcasecmp (subset->next->name, "i") == 0))
1732 riscv_arch_str1 (subset->next->next, attr_str, buf, bufsz);
1733 else
1734 riscv_arch_str1 (subset->next, attr_str, buf, bufsz);
1735}
1736
1737/* Convert subset info to string with explicit version info. */
1738
1739char *
1740riscv_arch_str (unsigned xlen, const riscv_subset_list_t *subset)
1741{
1742 size_t arch_str_len = riscv_estimate_arch_strlen (subset);
1743 char *attr_str = xmalloc (arch_str_len);
1744 char *buf = xmalloc (arch_str_len);
1745
1746 snprintf (attr_str, arch_str_len, "rv%u", xlen);
1747
1748 riscv_arch_str1 (subset->head, attr_str, buf, arch_str_len);
1749 free (buf);
1750
1751 return attr_str;
1752}