]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blame - bfd/elfxx-riscv.c
Update year range in copyright notice of binutils files
[thirdparty/binutils-gdb.git] / bfd / elfxx-riscv.c
CommitLineData
e23eba97 1/* RISC-V-specific support for ELF.
250d07de 2 Copyright (C) 2011-2021 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"
e23eba97
NC
28#include "libiberty.h"
29#include "elfxx-riscv.h"
1080bf78 30#include "safe-ctype.h"
e23eba97
NC
31
32#define MINUS_ONE ((bfd_vma)0 - 1)
33
57593436
KLC
34/* Special handler for ADD/SUB relocations that allows them to be filled out
35 both in the pre-linked and post-linked file. This is necessary to make
36 pre-linked debug info work, as due to linker relaxations we need to emit
37 relocations for the debug info. */
38static bfd_reloc_status_type riscv_elf_add_sub_reloc
39 (bfd *, arelent *, asymbol *, void *, asection *, bfd *, char **);
40
e23eba97
NC
41/* The relocation table used for SHT_RELA sections. */
42
43static reloc_howto_type howto_table[] =
44{
45 /* No relocation. */
46 HOWTO (R_RISCV_NONE, /* type */
47 0, /* rightshift */
48 3, /* size */
49 0, /* bitsize */
50 FALSE, /* pc_relative */
51 0, /* bitpos */
52 complain_overflow_dont, /* complain_on_overflow */
53 bfd_elf_generic_reloc, /* special_function */
54 "R_RISCV_NONE", /* name */
55 FALSE, /* partial_inplace */
56 0, /* src_mask */
57 0, /* dst_mask */
58 FALSE), /* pcrel_offset */
59
60 /* 32 bit relocation. */
61 HOWTO (R_RISCV_32, /* type */
62 0, /* rightshift */
63 2, /* size */
64 32, /* bitsize */
65 FALSE, /* pc_relative */
66 0, /* bitpos */
67 complain_overflow_dont, /* complain_on_overflow */
68 bfd_elf_generic_reloc, /* special_function */
69 "R_RISCV_32", /* name */
70 FALSE, /* partial_inplace */
71 0, /* src_mask */
b1b11e92 72 0xffffffff, /* dst_mask */
e23eba97
NC
73 FALSE), /* pcrel_offset */
74
75 /* 64 bit relocation. */
76 HOWTO (R_RISCV_64, /* type */
77 0, /* rightshift */
78 4, /* size */
79 64, /* bitsize */
80 FALSE, /* pc_relative */
81 0, /* bitpos */
82 complain_overflow_dont, /* complain_on_overflow */
83 bfd_elf_generic_reloc, /* special_function */
84 "R_RISCV_64", /* name */
85 FALSE, /* partial_inplace */
86 0, /* src_mask */
87 MINUS_ONE, /* dst_mask */
88 FALSE), /* pcrel_offset */
89
90 /* Relocation against a local symbol in a shared object. */
91 HOWTO (R_RISCV_RELATIVE, /* type */
92 0, /* rightshift */
93 2, /* size */
94 32, /* bitsize */
95 FALSE, /* pc_relative */
96 0, /* bitpos */
97 complain_overflow_dont, /* complain_on_overflow */
98 bfd_elf_generic_reloc, /* special_function */
99 "R_RISCV_RELATIVE", /* name */
100 FALSE, /* partial_inplace */
101 0, /* src_mask */
b1b11e92 102 0xffffffff, /* dst_mask */
e23eba97
NC
103 FALSE), /* pcrel_offset */
104
105 HOWTO (R_RISCV_COPY, /* type */
106 0, /* rightshift */
107 0, /* this one is variable size */
108 0, /* bitsize */
109 FALSE, /* pc_relative */
110 0, /* bitpos */
111 complain_overflow_bitfield, /* complain_on_overflow */
112 bfd_elf_generic_reloc, /* special_function */
113 "R_RISCV_COPY", /* name */
114 FALSE, /* partial_inplace */
07d6d2b8
AM
115 0, /* src_mask */
116 0, /* dst_mask */
e23eba97
NC
117 FALSE), /* pcrel_offset */
118
119 HOWTO (R_RISCV_JUMP_SLOT, /* type */
120 0, /* rightshift */
121 4, /* size */
122 64, /* bitsize */
123 FALSE, /* pc_relative */
124 0, /* bitpos */
125 complain_overflow_bitfield, /* complain_on_overflow */
126 bfd_elf_generic_reloc, /* special_function */
127 "R_RISCV_JUMP_SLOT", /* name */
128 FALSE, /* partial_inplace */
07d6d2b8
AM
129 0, /* src_mask */
130 0, /* dst_mask */
e23eba97
NC
131 FALSE), /* pcrel_offset */
132
133 /* Dynamic TLS relocations. */
134 HOWTO (R_RISCV_TLS_DTPMOD32, /* type */
135 0, /* rightshift */
b1b11e92 136 2, /* size */
e23eba97
NC
137 32, /* bitsize */
138 FALSE, /* pc_relative */
139 0, /* bitpos */
140 complain_overflow_dont, /* complain_on_overflow */
07d6d2b8 141 bfd_elf_generic_reloc, /* special_function */
e23eba97
NC
142 "R_RISCV_TLS_DTPMOD32", /* name */
143 FALSE, /* partial_inplace */
1d65abb5 144 0, /* src_mask */
b1b11e92 145 0xffffffff, /* dst_mask */
e23eba97
NC
146 FALSE), /* pcrel_offset */
147
148 HOWTO (R_RISCV_TLS_DTPMOD64, /* type */
149 0, /* rightshift */
150 4, /* size */
151 64, /* bitsize */
152 FALSE, /* pc_relative */
153 0, /* bitpos */
154 complain_overflow_dont, /* complain_on_overflow */
07d6d2b8 155 bfd_elf_generic_reloc, /* special_function */
e23eba97
NC
156 "R_RISCV_TLS_DTPMOD64", /* name */
157 FALSE, /* partial_inplace */
1d65abb5 158 0, /* src_mask */
e23eba97
NC
159 MINUS_ONE, /* dst_mask */
160 FALSE), /* pcrel_offset */
161
162 HOWTO (R_RISCV_TLS_DTPREL32, /* type */
163 0, /* rightshift */
b1b11e92 164 2, /* size */
e23eba97
NC
165 32, /* bitsize */
166 FALSE, /* pc_relative */
167 0, /* bitpos */
168 complain_overflow_dont, /* complain_on_overflow */
07d6d2b8 169 bfd_elf_generic_reloc, /* special_function */
e23eba97
NC
170 "R_RISCV_TLS_DTPREL32", /* name */
171 TRUE, /* partial_inplace */
1d65abb5 172 0, /* src_mask */
b1b11e92 173 0xffffffff, /* dst_mask */
e23eba97
NC
174 FALSE), /* pcrel_offset */
175
176 HOWTO (R_RISCV_TLS_DTPREL64, /* type */
177 0, /* rightshift */
178 4, /* size */
179 64, /* bitsize */
180 FALSE, /* pc_relative */
181 0, /* bitpos */
182 complain_overflow_dont, /* complain_on_overflow */
07d6d2b8 183 bfd_elf_generic_reloc, /* special_function */
e23eba97
NC
184 "R_RISCV_TLS_DTPREL64", /* name */
185 TRUE, /* partial_inplace */
1d65abb5 186 0, /* src_mask */
e23eba97
NC
187 MINUS_ONE, /* dst_mask */
188 FALSE), /* pcrel_offset */
189
190 HOWTO (R_RISCV_TLS_TPREL32, /* type */
191 0, /* rightshift */
192 2, /* size */
193 32, /* bitsize */
194 FALSE, /* pc_relative */
195 0, /* bitpos */
196 complain_overflow_dont, /* complain_on_overflow */
07d6d2b8 197 bfd_elf_generic_reloc, /* special_function */
e23eba97
NC
198 "R_RISCV_TLS_TPREL32", /* name */
199 FALSE, /* partial_inplace */
1d65abb5 200 0, /* src_mask */
b1b11e92 201 0xffffffff, /* dst_mask */
e23eba97
NC
202 FALSE), /* pcrel_offset */
203
204 HOWTO (R_RISCV_TLS_TPREL64, /* type */
205 0, /* rightshift */
206 4, /* size */
207 64, /* bitsize */
208 FALSE, /* pc_relative */
209 0, /* bitpos */
210 complain_overflow_dont, /* complain_on_overflow */
07d6d2b8 211 bfd_elf_generic_reloc, /* special_function */
e23eba97
NC
212 "R_RISCV_TLS_TPREL64", /* name */
213 FALSE, /* partial_inplace */
1d65abb5 214 0, /* src_mask */
e23eba97
NC
215 MINUS_ONE, /* dst_mask */
216 FALSE), /* pcrel_offset */
217
218 /* Reserved for future relocs that the dynamic linker must understand. */
219 EMPTY_HOWTO (12),
220 EMPTY_HOWTO (13),
221 EMPTY_HOWTO (14),
222 EMPTY_HOWTO (15),
223
224 /* 12-bit PC-relative branch offset. */
225 HOWTO (R_RISCV_BRANCH, /* type */
226 0, /* rightshift */
227 2, /* size */
228 32, /* bitsize */
229 TRUE, /* pc_relative */
230 0, /* bitpos */
231 complain_overflow_signed, /* complain_on_overflow */
232 bfd_elf_generic_reloc, /* special_function */
233 "R_RISCV_BRANCH", /* name */
234 FALSE, /* partial_inplace */
235 0, /* src_mask */
236 ENCODE_SBTYPE_IMM (-1U), /* dst_mask */
237 TRUE), /* pcrel_offset */
238
239 /* 20-bit PC-relative jump offset. */
240 HOWTO (R_RISCV_JAL, /* type */
241 0, /* rightshift */
242 2, /* size */
243 32, /* bitsize */
244 TRUE, /* pc_relative */
245 0, /* bitpos */
246 complain_overflow_dont, /* complain_on_overflow */
e23eba97
NC
247 bfd_elf_generic_reloc, /* special_function */
248 "R_RISCV_JAL", /* name */
249 FALSE, /* partial_inplace */
250 0, /* src_mask */
251 ENCODE_UJTYPE_IMM (-1U), /* dst_mask */
252 TRUE), /* pcrel_offset */
253
254 /* 32-bit PC-relative function call (AUIPC/JALR). */
255 HOWTO (R_RISCV_CALL, /* type */
256 0, /* rightshift */
b1b11e92 257 4, /* size */
e23eba97
NC
258 64, /* bitsize */
259 TRUE, /* pc_relative */
260 0, /* bitpos */
261 complain_overflow_dont, /* complain_on_overflow */
262 bfd_elf_generic_reloc, /* special_function */
263 "R_RISCV_CALL", /* name */
264 FALSE, /* partial_inplace */
265 0, /* src_mask */
266 ENCODE_UTYPE_IMM (-1U) | ((bfd_vma) ENCODE_ITYPE_IMM (-1U) << 32),
267 /* dst_mask */
268 TRUE), /* pcrel_offset */
269
1d65abb5 270 /* Like R_RISCV_CALL, but not locally binding. */
e23eba97
NC
271 HOWTO (R_RISCV_CALL_PLT, /* type */
272 0, /* rightshift */
b1b11e92 273 4, /* size */
e23eba97
NC
274 64, /* bitsize */
275 TRUE, /* pc_relative */
276 0, /* bitpos */
277 complain_overflow_dont, /* complain_on_overflow */
278 bfd_elf_generic_reloc, /* special_function */
279 "R_RISCV_CALL_PLT", /* name */
280 FALSE, /* partial_inplace */
281 0, /* src_mask */
282 ENCODE_UTYPE_IMM (-1U) | ((bfd_vma) ENCODE_ITYPE_IMM (-1U) << 32),
283 /* dst_mask */
284 TRUE), /* pcrel_offset */
285
286 /* High 20 bits of 32-bit PC-relative GOT access. */
287 HOWTO (R_RISCV_GOT_HI20, /* type */
288 0, /* rightshift */
289 2, /* size */
290 32, /* bitsize */
291 TRUE, /* pc_relative */
292 0, /* bitpos */
293 complain_overflow_dont, /* complain_on_overflow */
294 bfd_elf_generic_reloc, /* special_function */
295 "R_RISCV_GOT_HI20", /* name */
296 FALSE, /* partial_inplace */
297 0, /* src_mask */
298 ENCODE_UTYPE_IMM (-1U), /* dst_mask */
299 FALSE), /* pcrel_offset */
300
301 /* High 20 bits of 32-bit PC-relative TLS IE GOT access. */
302 HOWTO (R_RISCV_TLS_GOT_HI20, /* type */
303 0, /* rightshift */
304 2, /* size */
305 32, /* bitsize */
306 TRUE, /* pc_relative */
307 0, /* bitpos */
308 complain_overflow_dont, /* complain_on_overflow */
309 bfd_elf_generic_reloc, /* special_function */
310 "R_RISCV_TLS_GOT_HI20", /* name */
311 FALSE, /* partial_inplace */
312 0, /* src_mask */
313 ENCODE_UTYPE_IMM (-1U), /* dst_mask */
314 FALSE), /* pcrel_offset */
315
316 /* High 20 bits of 32-bit PC-relative TLS GD GOT reference. */
317 HOWTO (R_RISCV_TLS_GD_HI20, /* type */
318 0, /* rightshift */
319 2, /* size */
320 32, /* bitsize */
321 TRUE, /* pc_relative */
322 0, /* bitpos */
323 complain_overflow_dont, /* complain_on_overflow */
324 bfd_elf_generic_reloc, /* special_function */
325 "R_RISCV_TLS_GD_HI20", /* name */
326 FALSE, /* partial_inplace */
327 0, /* src_mask */
328 ENCODE_UTYPE_IMM (-1U), /* dst_mask */
329 FALSE), /* pcrel_offset */
330
331 /* High 20 bits of 32-bit PC-relative reference. */
332 HOWTO (R_RISCV_PCREL_HI20, /* type */
333 0, /* rightshift */
334 2, /* size */
335 32, /* bitsize */
336 TRUE, /* pc_relative */
337 0, /* bitpos */
338 complain_overflow_dont, /* complain_on_overflow */
339 bfd_elf_generic_reloc, /* special_function */
340 "R_RISCV_PCREL_HI20", /* name */
341 FALSE, /* partial_inplace */
342 0, /* src_mask */
343 ENCODE_UTYPE_IMM (-1U), /* dst_mask */
344 TRUE), /* pcrel_offset */
345
346 /* Low 12 bits of a 32-bit PC-relative load or add. */
347 HOWTO (R_RISCV_PCREL_LO12_I, /* type */
348 0, /* rightshift */
349 2, /* size */
350 32, /* bitsize */
351 FALSE, /* pc_relative */
352 0, /* bitpos */
353 complain_overflow_dont, /* complain_on_overflow */
354 bfd_elf_generic_reloc, /* special_function */
355 "R_RISCV_PCREL_LO12_I", /* name */
356 FALSE, /* partial_inplace */
357 0, /* src_mask */
358 ENCODE_ITYPE_IMM (-1U), /* dst_mask */
359 FALSE), /* pcrel_offset */
360
361 /* Low 12 bits of a 32-bit PC-relative store. */
362 HOWTO (R_RISCV_PCREL_LO12_S, /* type */
363 0, /* rightshift */
364 2, /* size */
365 32, /* bitsize */
366 FALSE, /* pc_relative */
367 0, /* bitpos */
368 complain_overflow_dont, /* complain_on_overflow */
369 bfd_elf_generic_reloc, /* special_function */
370 "R_RISCV_PCREL_LO12_S", /* name */
371 FALSE, /* partial_inplace */
372 0, /* src_mask */
373 ENCODE_STYPE_IMM (-1U), /* dst_mask */
374 FALSE), /* pcrel_offset */
375
376 /* High 20 bits of 32-bit absolute address. */
377 HOWTO (R_RISCV_HI20, /* type */
378 0, /* rightshift */
379 2, /* size */
380 32, /* bitsize */
381 FALSE, /* pc_relative */
382 0, /* bitpos */
383 complain_overflow_dont, /* complain_on_overflow */
384 bfd_elf_generic_reloc, /* special_function */
385 "R_RISCV_HI20", /* name */
386 FALSE, /* partial_inplace */
387 0, /* src_mask */
388 ENCODE_UTYPE_IMM (-1U), /* dst_mask */
389 FALSE), /* pcrel_offset */
390
391 /* High 12 bits of 32-bit load or add. */
392 HOWTO (R_RISCV_LO12_I, /* type */
393 0, /* rightshift */
394 2, /* size */
395 32, /* bitsize */
396 FALSE, /* pc_relative */
397 0, /* bitpos */
398 complain_overflow_dont, /* complain_on_overflow */
399 bfd_elf_generic_reloc, /* special_function */
400 "R_RISCV_LO12_I", /* name */
401 FALSE, /* partial_inplace */
402 0, /* src_mask */
403 ENCODE_ITYPE_IMM (-1U), /* dst_mask */
404 FALSE), /* pcrel_offset */
405
406 /* High 12 bits of 32-bit store. */
407 HOWTO (R_RISCV_LO12_S, /* type */
408 0, /* rightshift */
409 2, /* size */
410 32, /* bitsize */
411 FALSE, /* pc_relative */
412 0, /* bitpos */
413 complain_overflow_dont, /* complain_on_overflow */
414 bfd_elf_generic_reloc, /* special_function */
415 "R_RISCV_LO12_S", /* name */
416 FALSE, /* partial_inplace */
417 0, /* src_mask */
418 ENCODE_STYPE_IMM (-1U), /* dst_mask */
419 FALSE), /* pcrel_offset */
420
421 /* High 20 bits of TLS LE thread pointer offset. */
422 HOWTO (R_RISCV_TPREL_HI20, /* type */
423 0, /* rightshift */
424 2, /* size */
425 32, /* bitsize */
426 FALSE, /* pc_relative */
427 0, /* bitpos */
428 complain_overflow_signed, /* complain_on_overflow */
429 bfd_elf_generic_reloc, /* special_function */
430 "R_RISCV_TPREL_HI20", /* name */
431 TRUE, /* partial_inplace */
432 0, /* src_mask */
433 ENCODE_UTYPE_IMM (-1U), /* dst_mask */
434 FALSE), /* pcrel_offset */
435
436 /* Low 12 bits of TLS LE thread pointer offset for loads and adds. */
437 HOWTO (R_RISCV_TPREL_LO12_I, /* type */
438 0, /* rightshift */
439 2, /* size */
440 32, /* bitsize */
441 FALSE, /* pc_relative */
442 0, /* bitpos */
443 complain_overflow_signed, /* complain_on_overflow */
444 bfd_elf_generic_reloc, /* special_function */
445 "R_RISCV_TPREL_LO12_I", /* name */
446 FALSE, /* partial_inplace */
447 0, /* src_mask */
448 ENCODE_ITYPE_IMM (-1U), /* dst_mask */
449 FALSE), /* pcrel_offset */
450
451 /* Low 12 bits of TLS LE thread pointer offset for stores. */
452 HOWTO (R_RISCV_TPREL_LO12_S, /* type */
453 0, /* rightshift */
454 2, /* size */
455 32, /* bitsize */
456 FALSE, /* pc_relative */
457 0, /* bitpos */
458 complain_overflow_signed, /* complain_on_overflow */
459 bfd_elf_generic_reloc, /* special_function */
460 "R_RISCV_TPREL_LO12_S", /* name */
461 FALSE, /* partial_inplace */
462 0, /* src_mask */
463 ENCODE_STYPE_IMM (-1U), /* dst_mask */
464 FALSE), /* pcrel_offset */
465
1d65abb5 466 /* TLS LE thread pointer usage. May be relaxed. */
e23eba97
NC
467 HOWTO (R_RISCV_TPREL_ADD, /* type */
468 0, /* rightshift */
b1b11e92
AM
469 3, /* size */
470 0, /* bitsize */
e23eba97
NC
471 FALSE, /* pc_relative */
472 0, /* bitpos */
473 complain_overflow_dont, /* complain_on_overflow */
474 bfd_elf_generic_reloc, /* special_function */
475 "R_RISCV_TPREL_ADD", /* name */
b1b11e92 476 FALSE, /* partial_inplace */
e23eba97
NC
477 0, /* src_mask */
478 0, /* dst_mask */
479 FALSE), /* pcrel_offset */
480
481 /* 8-bit in-place addition, for local label subtraction. */
482 HOWTO (R_RISCV_ADD8, /* type */
483 0, /* rightshift */
484 0, /* size */
0b14696a 485 8, /* bitsize */
e23eba97
NC
486 FALSE, /* pc_relative */
487 0, /* bitpos */
488 complain_overflow_dont, /* complain_on_overflow */
57593436 489 riscv_elf_add_sub_reloc, /* special_function */
e23eba97
NC
490 "R_RISCV_ADD8", /* name */
491 FALSE, /* partial_inplace */
492 0, /* src_mask */
b1b11e92 493 0xff, /* dst_mask */
e23eba97
NC
494 FALSE), /* pcrel_offset */
495
496 /* 16-bit in-place addition, for local label subtraction. */
497 HOWTO (R_RISCV_ADD16, /* type */
498 0, /* rightshift */
499 1, /* size */
500 16, /* bitsize */
501 FALSE, /* pc_relative */
502 0, /* bitpos */
503 complain_overflow_dont, /* complain_on_overflow */
57593436 504 riscv_elf_add_sub_reloc, /* special_function */
e23eba97
NC
505 "R_RISCV_ADD16", /* name */
506 FALSE, /* partial_inplace */
507 0, /* src_mask */
b1b11e92 508 0xffff, /* dst_mask */
e23eba97
NC
509 FALSE), /* pcrel_offset */
510
511 /* 32-bit in-place addition, for local label subtraction. */
512 HOWTO (R_RISCV_ADD32, /* type */
513 0, /* rightshift */
514 2, /* size */
515 32, /* bitsize */
516 FALSE, /* pc_relative */
517 0, /* bitpos */
518 complain_overflow_dont, /* complain_on_overflow */
57593436 519 riscv_elf_add_sub_reloc, /* special_function */
e23eba97
NC
520 "R_RISCV_ADD32", /* name */
521 FALSE, /* partial_inplace */
522 0, /* src_mask */
b1b11e92 523 0xffffffff, /* dst_mask */
e23eba97
NC
524 FALSE), /* pcrel_offset */
525
526 /* 64-bit in-place addition, for local label subtraction. */
527 HOWTO (R_RISCV_ADD64, /* type */
528 0, /* rightshift */
529 4, /* size */
530 64, /* bitsize */
531 FALSE, /* pc_relative */
532 0, /* bitpos */
533 complain_overflow_dont, /* complain_on_overflow */
57593436 534 riscv_elf_add_sub_reloc, /* special_function */
e23eba97
NC
535 "R_RISCV_ADD64", /* name */
536 FALSE, /* partial_inplace */
537 0, /* src_mask */
538 MINUS_ONE, /* dst_mask */
539 FALSE), /* pcrel_offset */
540
541 /* 8-bit in-place addition, for local label subtraction. */
542 HOWTO (R_RISCV_SUB8, /* type */
543 0, /* rightshift */
544 0, /* size */
545 8, /* bitsize */
546 FALSE, /* pc_relative */
547 0, /* bitpos */
548 complain_overflow_dont, /* complain_on_overflow */
57593436 549 riscv_elf_add_sub_reloc, /* special_function */
e23eba97
NC
550 "R_RISCV_SUB8", /* name */
551 FALSE, /* partial_inplace */
552 0, /* src_mask */
b1b11e92 553 0xff, /* dst_mask */
e23eba97
NC
554 FALSE), /* pcrel_offset */
555
556 /* 16-bit in-place addition, for local label subtraction. */
557 HOWTO (R_RISCV_SUB16, /* type */
558 0, /* rightshift */
559 1, /* size */
560 16, /* bitsize */
561 FALSE, /* pc_relative */
562 0, /* bitpos */
563 complain_overflow_dont, /* complain_on_overflow */
57593436 564 riscv_elf_add_sub_reloc, /* special_function */
e23eba97
NC
565 "R_RISCV_SUB16", /* name */
566 FALSE, /* partial_inplace */
567 0, /* src_mask */
b1b11e92 568 0xffff, /* dst_mask */
e23eba97
NC
569 FALSE), /* pcrel_offset */
570
571 /* 32-bit in-place addition, for local label subtraction. */
572 HOWTO (R_RISCV_SUB32, /* type */
573 0, /* rightshift */
574 2, /* size */
575 32, /* bitsize */
576 FALSE, /* pc_relative */
577 0, /* bitpos */
578 complain_overflow_dont, /* complain_on_overflow */
57593436 579 riscv_elf_add_sub_reloc, /* special_function */
e23eba97
NC
580 "R_RISCV_SUB32", /* name */
581 FALSE, /* partial_inplace */
582 0, /* src_mask */
b1b11e92 583 0xffffffff, /* dst_mask */
e23eba97
NC
584 FALSE), /* pcrel_offset */
585
586 /* 64-bit in-place addition, for local label subtraction. */
587 HOWTO (R_RISCV_SUB64, /* type */
588 0, /* rightshift */
589 4, /* size */
590 64, /* bitsize */
591 FALSE, /* pc_relative */
592 0, /* bitpos */
593 complain_overflow_dont, /* complain_on_overflow */
57593436 594 riscv_elf_add_sub_reloc, /* special_function */
e23eba97
NC
595 "R_RISCV_SUB64", /* name */
596 FALSE, /* partial_inplace */
597 0, /* src_mask */
598 MINUS_ONE, /* dst_mask */
599 FALSE), /* pcrel_offset */
600
601 /* GNU extension to record C++ vtable hierarchy */
602 HOWTO (R_RISCV_GNU_VTINHERIT, /* type */
603 0, /* rightshift */
604 4, /* size */
605 0, /* bitsize */
606 FALSE, /* pc_relative */
607 0, /* bitpos */
608 complain_overflow_dont, /* complain_on_overflow */
609 NULL, /* special_function */
610 "R_RISCV_GNU_VTINHERIT", /* name */
611 FALSE, /* partial_inplace */
612 0, /* src_mask */
613 0, /* dst_mask */
614 FALSE), /* pcrel_offset */
615
616 /* GNU extension to record C++ vtable member usage */
617 HOWTO (R_RISCV_GNU_VTENTRY, /* type */
618 0, /* rightshift */
619 4, /* size */
620 0, /* bitsize */
621 FALSE, /* pc_relative */
622 0, /* bitpos */
623 complain_overflow_dont, /* complain_on_overflow */
624 _bfd_elf_rel_vtable_reloc_fn, /* special_function */
625 "R_RISCV_GNU_VTENTRY", /* name */
626 FALSE, /* partial_inplace */
627 0, /* src_mask */
628 0, /* dst_mask */
629 FALSE), /* pcrel_offset */
630
631 /* Indicates an alignment statement. The addend field encodes how many
632 bytes of NOPs follow the statement. The desired alignment is the
633 addend rounded up to the next power of two. */
634 HOWTO (R_RISCV_ALIGN, /* type */
635 0, /* rightshift */
b1b11e92 636 3, /* size */
e23eba97
NC
637 0, /* bitsize */
638 FALSE, /* pc_relative */
639 0, /* bitpos */
640 complain_overflow_dont, /* complain_on_overflow */
641 bfd_elf_generic_reloc, /* special_function */
642 "R_RISCV_ALIGN", /* name */
643 FALSE, /* partial_inplace */
644 0, /* src_mask */
645 0, /* dst_mask */
b1b11e92 646 FALSE), /* pcrel_offset */
e23eba97
NC
647
648 /* 8-bit PC-relative branch offset. */
649 HOWTO (R_RISCV_RVC_BRANCH, /* type */
650 0, /* rightshift */
b1b11e92
AM
651 1, /* size */
652 16, /* bitsize */
e23eba97
NC
653 TRUE, /* pc_relative */
654 0, /* bitpos */
655 complain_overflow_signed, /* complain_on_overflow */
656 bfd_elf_generic_reloc, /* special_function */
657 "R_RISCV_RVC_BRANCH", /* name */
658 FALSE, /* partial_inplace */
659 0, /* src_mask */
660 ENCODE_RVC_B_IMM (-1U), /* dst_mask */
661 TRUE), /* pcrel_offset */
662
663 /* 11-bit PC-relative jump offset. */
664 HOWTO (R_RISCV_RVC_JUMP, /* type */
665 0, /* rightshift */
b1b11e92
AM
666 1, /* size */
667 16, /* bitsize */
e23eba97
NC
668 TRUE, /* pc_relative */
669 0, /* bitpos */
670 complain_overflow_dont, /* complain_on_overflow */
e23eba97
NC
671 bfd_elf_generic_reloc, /* special_function */
672 "R_RISCV_RVC_JUMP", /* name */
673 FALSE, /* partial_inplace */
674 0, /* src_mask */
675 ENCODE_RVC_J_IMM (-1U), /* dst_mask */
676 TRUE), /* pcrel_offset */
677
678 /* High 6 bits of 18-bit absolute address. */
679 HOWTO (R_RISCV_RVC_LUI, /* type */
680 0, /* rightshift */
b1b11e92
AM
681 1, /* size */
682 16, /* bitsize */
e23eba97
NC
683 FALSE, /* pc_relative */
684 0, /* bitpos */
685 complain_overflow_dont, /* complain_on_overflow */
686 bfd_elf_generic_reloc, /* special_function */
687 "R_RISCV_RVC_LUI", /* name */
688 FALSE, /* partial_inplace */
689 0, /* src_mask */
690 ENCODE_RVC_IMM (-1U), /* dst_mask */
691 FALSE), /* pcrel_offset */
692
1d65abb5 693 /* GP-relative load. */
e23eba97
NC
694 HOWTO (R_RISCV_GPREL_I, /* type */
695 0, /* rightshift */
696 2, /* size */
697 32, /* bitsize */
698 FALSE, /* pc_relative */
699 0, /* bitpos */
700 complain_overflow_dont, /* complain_on_overflow */
701 bfd_elf_generic_reloc, /* special_function */
702 "R_RISCV_GPREL_I", /* name */
703 FALSE, /* partial_inplace */
704 0, /* src_mask */
705 ENCODE_ITYPE_IMM (-1U), /* dst_mask */
706 FALSE), /* pcrel_offset */
707
1d65abb5 708 /* GP-relative store. */
e23eba97
NC
709 HOWTO (R_RISCV_GPREL_S, /* type */
710 0, /* rightshift */
711 2, /* size */
712 32, /* bitsize */
713 FALSE, /* pc_relative */
714 0, /* bitpos */
715 complain_overflow_dont, /* complain_on_overflow */
716 bfd_elf_generic_reloc, /* special_function */
717 "R_RISCV_GPREL_S", /* name */
718 FALSE, /* partial_inplace */
719 0, /* src_mask */
720 ENCODE_STYPE_IMM (-1U), /* dst_mask */
721 FALSE), /* pcrel_offset */
45f76423
AW
722
723 /* TP-relative TLS LE load. */
724 HOWTO (R_RISCV_TPREL_I, /* type */
725 0, /* rightshift */
726 2, /* size */
727 32, /* bitsize */
728 FALSE, /* pc_relative */
729 0, /* bitpos */
730 complain_overflow_signed, /* complain_on_overflow */
731 bfd_elf_generic_reloc, /* special_function */
732 "R_RISCV_TPREL_I", /* name */
733 FALSE, /* partial_inplace */
734 0, /* src_mask */
735 ENCODE_ITYPE_IMM (-1U), /* dst_mask */
736 FALSE), /* pcrel_offset */
737
738 /* TP-relative TLS LE store. */
739 HOWTO (R_RISCV_TPREL_S, /* type */
740 0, /* rightshift */
741 2, /* size */
742 32, /* bitsize */
743 FALSE, /* pc_relative */
744 0, /* bitpos */
745 complain_overflow_signed, /* complain_on_overflow */
746 bfd_elf_generic_reloc, /* special_function */
747 "R_RISCV_TPREL_S", /* name */
748 FALSE, /* partial_inplace */
749 0, /* src_mask */
750 ENCODE_STYPE_IMM (-1U), /* dst_mask */
751 FALSE), /* pcrel_offset */
752
753 /* The paired relocation may be relaxed. */
754 HOWTO (R_RISCV_RELAX, /* type */
755 0, /* rightshift */
756 3, /* size */
757 0, /* bitsize */
758 FALSE, /* pc_relative */
759 0, /* bitpos */
760 complain_overflow_dont, /* complain_on_overflow */
761 bfd_elf_generic_reloc, /* special_function */
762 "R_RISCV_RELAX", /* name */
763 FALSE, /* partial_inplace */
764 0, /* src_mask */
765 0, /* dst_mask */
766 FALSE), /* pcrel_offset */
767
768 /* 6-bit in-place addition, for local label subtraction. */
769 HOWTO (R_RISCV_SUB6, /* type */
770 0, /* rightshift */
771 0, /* size */
772 8, /* bitsize */
773 FALSE, /* pc_relative */
774 0, /* bitpos */
775 complain_overflow_dont, /* complain_on_overflow */
57593436 776 riscv_elf_add_sub_reloc, /* special_function */
45f76423
AW
777 "R_RISCV_SUB6", /* name */
778 FALSE, /* partial_inplace */
779 0, /* src_mask */
780 0x3f, /* dst_mask */
781 FALSE), /* pcrel_offset */
782
783 /* 6-bit in-place setting, for local label subtraction. */
784 HOWTO (R_RISCV_SET6, /* type */
785 0, /* rightshift */
786 0, /* size */
787 8, /* bitsize */
788 FALSE, /* pc_relative */
789 0, /* bitpos */
790 complain_overflow_dont, /* complain_on_overflow */
791 bfd_elf_generic_reloc, /* special_function */
792 "R_RISCV_SET6", /* name */
793 FALSE, /* partial_inplace */
794 0, /* src_mask */
795 0x3f, /* dst_mask */
796 FALSE), /* pcrel_offset */
797
798 /* 8-bit in-place setting, for local label subtraction. */
799 HOWTO (R_RISCV_SET8, /* type */
800 0, /* rightshift */
801 0, /* size */
802 8, /* bitsize */
803 FALSE, /* pc_relative */
804 0, /* bitpos */
805 complain_overflow_dont, /* complain_on_overflow */
806 bfd_elf_generic_reloc, /* special_function */
807 "R_RISCV_SET8", /* name */
808 FALSE, /* partial_inplace */
809 0, /* src_mask */
b1b11e92 810 0xff, /* dst_mask */
45f76423
AW
811 FALSE), /* pcrel_offset */
812
813 /* 16-bit in-place setting, for local label subtraction. */
814 HOWTO (R_RISCV_SET16, /* type */
815 0, /* rightshift */
816 1, /* size */
817 16, /* bitsize */
818 FALSE, /* pc_relative */
819 0, /* bitpos */
820 complain_overflow_dont, /* complain_on_overflow */
821 bfd_elf_generic_reloc, /* special_function */
822 "R_RISCV_SET16", /* name */
823 FALSE, /* partial_inplace */
824 0, /* src_mask */
b1b11e92 825 0xffff, /* dst_mask */
45f76423
AW
826 FALSE), /* pcrel_offset */
827
828 /* 32-bit in-place setting, for local label subtraction. */
829 HOWTO (R_RISCV_SET32, /* type */
830 0, /* rightshift */
831 2, /* size */
832 32, /* bitsize */
833 FALSE, /* pc_relative */
834 0, /* bitpos */
835 complain_overflow_dont, /* complain_on_overflow */
836 bfd_elf_generic_reloc, /* special_function */
837 "R_RISCV_SET32", /* name */
838 FALSE, /* partial_inplace */
839 0, /* src_mask */
b1b11e92 840 0xffffffff, /* dst_mask */
45f76423 841 FALSE), /* pcrel_offset */
a6cbf936
KLC
842
843 /* 32-bit PC relative. */
844 HOWTO (R_RISCV_32_PCREL, /* type */
845 0, /* rightshift */
846 2, /* size */
847 32, /* bitsize */
848 TRUE, /* pc_relative */
849 0, /* bitpos */
850 complain_overflow_dont, /* complain_on_overflow */
851 bfd_elf_generic_reloc, /* special_function */
852 "R_RISCV_32_PCREL", /* name */
853 FALSE, /* partial_inplace */
02dd9d25
NC
854 0, /* src_mask */
855 0xffffffff, /* dst_mask */
856 FALSE), /* pcrel_offset */
857
858 /* Relocation against a local ifunc symbol in a shared object. */
859 HOWTO (R_RISCV_IRELATIVE, /* type */
860 0, /* rightshift */
861 2, /* size */
862 32, /* bitsize */
863 FALSE, /* pc_relative */
864 0, /* bitpos */
865 complain_overflow_dont, /* complain_on_overflow */
866 bfd_elf_generic_reloc, /* special_function */
867 "R_RISCV_IRELATIVE", /* name */
868 FALSE, /* partial_inplace */
a6cbf936 869 0, /* src_mask */
b1b11e92 870 0xffffffff, /* dst_mask */
a6cbf936 871 FALSE), /* pcrel_offset */
e23eba97
NC
872};
873
874/* A mapping from BFD reloc types to RISC-V ELF reloc types. */
875
876struct elf_reloc_map
877{
878 bfd_reloc_code_real_type bfd_val;
879 enum elf_riscv_reloc_type elf_val;
880};
881
882static const struct elf_reloc_map riscv_reloc_map[] =
883{
884 { BFD_RELOC_NONE, R_RISCV_NONE },
885 { BFD_RELOC_32, R_RISCV_32 },
886 { BFD_RELOC_64, R_RISCV_64 },
887 { BFD_RELOC_RISCV_ADD8, R_RISCV_ADD8 },
888 { BFD_RELOC_RISCV_ADD16, R_RISCV_ADD16 },
889 { BFD_RELOC_RISCV_ADD32, R_RISCV_ADD32 },
890 { BFD_RELOC_RISCV_ADD64, R_RISCV_ADD64 },
891 { BFD_RELOC_RISCV_SUB8, R_RISCV_SUB8 },
892 { BFD_RELOC_RISCV_SUB16, R_RISCV_SUB16 },
893 { BFD_RELOC_RISCV_SUB32, R_RISCV_SUB32 },
894 { BFD_RELOC_RISCV_SUB64, R_RISCV_SUB64 },
895 { BFD_RELOC_CTOR, R_RISCV_64 },
896 { BFD_RELOC_12_PCREL, R_RISCV_BRANCH },
897 { BFD_RELOC_RISCV_HI20, R_RISCV_HI20 },
898 { BFD_RELOC_RISCV_LO12_I, R_RISCV_LO12_I },
899 { BFD_RELOC_RISCV_LO12_S, R_RISCV_LO12_S },
900 { BFD_RELOC_RISCV_PCREL_LO12_I, R_RISCV_PCREL_LO12_I },
901 { BFD_RELOC_RISCV_PCREL_LO12_S, R_RISCV_PCREL_LO12_S },
902 { BFD_RELOC_RISCV_CALL, R_RISCV_CALL },
903 { BFD_RELOC_RISCV_CALL_PLT, R_RISCV_CALL_PLT },
904 { BFD_RELOC_RISCV_PCREL_HI20, R_RISCV_PCREL_HI20 },
905 { BFD_RELOC_RISCV_JMP, R_RISCV_JAL },
906 { BFD_RELOC_RISCV_GOT_HI20, R_RISCV_GOT_HI20 },
907 { BFD_RELOC_RISCV_TLS_DTPMOD32, R_RISCV_TLS_DTPMOD32 },
908 { BFD_RELOC_RISCV_TLS_DTPREL32, R_RISCV_TLS_DTPREL32 },
909 { BFD_RELOC_RISCV_TLS_DTPMOD64, R_RISCV_TLS_DTPMOD64 },
910 { BFD_RELOC_RISCV_TLS_DTPREL64, R_RISCV_TLS_DTPREL64 },
911 { BFD_RELOC_RISCV_TLS_TPREL32, R_RISCV_TLS_TPREL32 },
912 { BFD_RELOC_RISCV_TLS_TPREL64, R_RISCV_TLS_TPREL64 },
913 { BFD_RELOC_RISCV_TPREL_HI20, R_RISCV_TPREL_HI20 },
914 { BFD_RELOC_RISCV_TPREL_ADD, R_RISCV_TPREL_ADD },
915 { BFD_RELOC_RISCV_TPREL_LO12_S, R_RISCV_TPREL_LO12_S },
916 { BFD_RELOC_RISCV_TPREL_LO12_I, R_RISCV_TPREL_LO12_I },
917 { BFD_RELOC_RISCV_TLS_GOT_HI20, R_RISCV_TLS_GOT_HI20 },
918 { BFD_RELOC_RISCV_TLS_GD_HI20, R_RISCV_TLS_GD_HI20 },
919 { BFD_RELOC_RISCV_ALIGN, R_RISCV_ALIGN },
920 { BFD_RELOC_RISCV_RVC_BRANCH, R_RISCV_RVC_BRANCH },
921 { BFD_RELOC_RISCV_RVC_JUMP, R_RISCV_RVC_JUMP },
922 { BFD_RELOC_RISCV_RVC_LUI, R_RISCV_RVC_LUI },
923 { BFD_RELOC_RISCV_GPREL_I, R_RISCV_GPREL_I },
924 { BFD_RELOC_RISCV_GPREL_S, R_RISCV_GPREL_S },
45f76423
AW
925 { BFD_RELOC_RISCV_TPREL_I, R_RISCV_TPREL_I },
926 { BFD_RELOC_RISCV_TPREL_S, R_RISCV_TPREL_S },
927 { BFD_RELOC_RISCV_RELAX, R_RISCV_RELAX },
928 { BFD_RELOC_RISCV_SUB6, R_RISCV_SUB6 },
929 { BFD_RELOC_RISCV_SET6, R_RISCV_SET6 },
930 { BFD_RELOC_RISCV_SET8, R_RISCV_SET8 },
931 { BFD_RELOC_RISCV_SET16, R_RISCV_SET16 },
932 { BFD_RELOC_RISCV_SET32, R_RISCV_SET32 },
a6cbf936 933 { BFD_RELOC_RISCV_32_PCREL, R_RISCV_32_PCREL },
e23eba97
NC
934};
935
936/* Given a BFD reloc type, return a howto structure. */
937
938reloc_howto_type *
939riscv_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED,
940 bfd_reloc_code_real_type code)
941{
942 unsigned int i;
943
944 for (i = 0; i < ARRAY_SIZE (riscv_reloc_map); i++)
945 if (riscv_reloc_map[i].bfd_val == code)
946 return &howto_table[(int) riscv_reloc_map[i].elf_val];
947
948 bfd_set_error (bfd_error_bad_value);
949 return NULL;
950}
951
952reloc_howto_type *
953riscv_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED, const char *r_name)
954{
955 unsigned int i;
956
957 for (i = 0; i < ARRAY_SIZE (howto_table); i++)
958 if (howto_table[i].name && strcasecmp (howto_table[i].name, r_name) == 0)
959 return &howto_table[i];
960
961 return NULL;
962}
963
964reloc_howto_type *
0aa13fee 965riscv_elf_rtype_to_howto (bfd *abfd, unsigned int r_type)
e23eba97
NC
966{
967 if (r_type >= ARRAY_SIZE (howto_table))
968 {
0aa13fee
AM
969 (*_bfd_error_handler) (_("%pB: unsupported relocation type %#x"),
970 abfd, r_type);
e23eba97
NC
971 bfd_set_error (bfd_error_bad_value);
972 return NULL;
973 }
974 return &howto_table[r_type];
975}
57593436
KLC
976
977/* Special_function of RISCV_ADD and RISCV_SUB relocations. */
978
979static bfd_reloc_status_type
980riscv_elf_add_sub_reloc (bfd *abfd,
981 arelent *reloc_entry,
982 asymbol *symbol,
983 void *data,
984 asection *input_section,
985 bfd *output_bfd,
986 char **error_message ATTRIBUTE_UNUSED)
987{
988 reloc_howto_type *howto = reloc_entry->howto;
989 bfd_vma relocation;
990
991 if (output_bfd != NULL
992 && (symbol->flags & BSF_SECTION_SYM) == 0
993 && (!reloc_entry->howto->partial_inplace || reloc_entry->addend == 0))
994 {
995 reloc_entry->address += input_section->output_offset;
996 return bfd_reloc_ok;
997 }
998
999 if (output_bfd != NULL)
1000 return bfd_reloc_continue;
1001
1002 relocation = symbol->value + symbol->section->output_section->vma
1003 + symbol->section->output_offset + reloc_entry->addend;
1004 bfd_vma old_value = bfd_get (howto->bitsize, abfd,
1005 data + reloc_entry->address);
1006
1007 switch (howto->type)
1008 {
1009 case R_RISCV_ADD8:
1010 case R_RISCV_ADD16:
1011 case R_RISCV_ADD32:
1012 case R_RISCV_ADD64:
1013 relocation = old_value + relocation;
1014 break;
1015 case R_RISCV_SUB6:
1016 case R_RISCV_SUB8:
1017 case R_RISCV_SUB16:
1018 case R_RISCV_SUB32:
1019 case R_RISCV_SUB64:
1020 relocation = old_value - relocation;
1021 break;
1022 }
1023 bfd_put (howto->bitsize, abfd, relocation, data + reloc_entry->address);
1024
1025 return bfd_reloc_ok;
1026}
1080bf78 1027
dfe92496 1028/* Array is used to compare the all extensions' order quickly.
7ef19aa6 1029
dfe92496
NC
1030 Zero number means it is a preserved keyword.
1031 Negative number means it is a prefix keyword (s, h, x, z).
1032 Positive number means it is a standard extension. */
1033
1034static int riscv_ext_order[26] = {0};
1035
1036/* Similar to the strcmp. It returns an integer less than, equal to,
1037 or greater than zero if `subset2` is found, respectively, to be less
1038 than, to match, or be greater than `subset1`. */
1039
1040static int
1041riscv_compare_subsets (const char *subset1, const char *subset2)
7ef19aa6 1042{
dfe92496
NC
1043 int order1 = riscv_ext_order[(*subset1 - 'a')];
1044 int order2 = riscv_ext_order[(*subset2 - 'a')];
7ef19aa6 1045
dfe92496
NC
1046 /* Compare the standard extension first. */
1047 if (order1 > 0 && order2 > 0)
1048 return order1 - order2;
7ef19aa6 1049
dfe92496
NC
1050 if (order1 == order2 && order1 < 0)
1051 {
1052 /* Compare the standard addition z extensions. */
1053 if (*subset1 == 'z')
1054 {
1055 order1 = riscv_ext_order[(*++subset1 - 'a')];
1056 order2 = riscv_ext_order[(*++subset2 - 'a')];
1057 if (order1 != order2)
1058 return order1 - order2;
1059 }
1060 return strcasecmp (++subset1, ++subset2);
1061 }
1062
1063 return order2 - order1;
1064}
1065
1066/* Find subset in the list. Return TRUE and set `current` to the subset
1067 if it is found. Otherwise, return FALSE and set `current` to the place
1068 where we should insert the subset. However, return FALSE with the NULL
1069 `current` means we should insert the subset at the head of subset list,
1070 if needed. */
1071
1072bfd_boolean
1073riscv_lookup_subset (const riscv_subset_list_t *subset_list,
1074 const char *subset,
1075 riscv_subset_t **current)
1076{
1077 riscv_subset_t *s, *pre_s = NULL;
1078
1079 for (s = subset_list->head;
1080 s != NULL;
1081 pre_s = s, s = s->next)
1082 {
1083 int cmp = riscv_compare_subsets (s->name, subset);
1084 if (cmp == 0)
1085 {
1086 *current = s;
1087 return TRUE;
1088 }
1089 else if (cmp > 0)
1090 break;
1091 }
1092 *current = pre_s;
1093 return FALSE;
7ef19aa6
NC
1094}
1095
dfe92496 1096/* Add arch string extension to the last of the subset list. */
7ef19aa6
NC
1097
1098void
1099riscv_add_subset (riscv_subset_list_t *subset_list,
1100 const char *subset,
1101 int major,
1102 int minor)
1103{
1104 riscv_subset_t *s = xmalloc (sizeof *s);
1105
1106 if (subset_list->head == NULL)
1107 subset_list->head = s;
1108
1109 s->name = xstrdup (subset);
1110 s->major_version = major;
1111 s->minor_version = minor;
1112 s->next = NULL;
1113
1114 if (subset_list->tail != NULL)
1115 subset_list->tail->next = s;
1116 subset_list->tail = s;
1117}
1118
dfe92496
NC
1119/* Add the implicit extension to the subset list. Search the
1120 list first, and then find the right place to add. */
1121
1122static void
1123riscv_add_implicit_subset (riscv_subset_list_t *subset_list,
1124 const char *subset,
1125 int major,
1126 int minor)
1127{
1128 riscv_subset_t *current, *new;
1129
1130 if (riscv_lookup_subset (subset_list, subset, &current))
1131 return;
1132
1133 new = xmalloc (sizeof *new);
1134 new->name = xstrdup (subset);
1135 new->major_version = major;
1136 new->minor_version = minor;
1137 new->next = NULL;
1138
1139 if (current != NULL)
1140 {
1141 new->next = current->next;
1142 current->next = new;
1143 }
1144 else
1145 {
1146 new->next = subset_list->head;
1147 subset_list->head = new;
1148 }
1149}
1150
729a5353
NC
1151/* These extensions are added to the subset list for special purposes,
1152 with the explicit versions or the RISCV_UNKNOWN_VERSION versions.
1153 Therefore, we won't output them to the output arch string in the
1154 riscv_arch_str1, if the versions are unknown. */
1155
1156static bfd_boolean
1157riscv_ext_dont_care_version (const char *subset)
1158{
1159 if (strcmp (subset, "g") == 0
1160 || strcmp (subset, "zicsr") == 0
1161 || strcmp (subset, "zifencei") == 0)
1162 return TRUE;
1163 return FALSE;
1164}
1165
dfe92496
NC
1166/* We have to add all arch string extensions first, and then start to
1167 add their implicit extensions. The arch string extensions must be
1168 set in order, so we can add them to the last of the subset list
1169 directly, without searching.
1170
1171 Find the default versions for the extension before adding them to
7ef19aa6
NC
1172 the subset list, if their versions are RISCV_UNKNOWN_VERSION.
1173 Afterwards, report errors if we can not find their default versions. */
1174
1175static void
1176riscv_parse_add_subset (riscv_parse_subset_t *rps,
1177 const char *subset,
1178 int major,
dfe92496
NC
1179 int minor,
1180 bfd_boolean implicit)
7ef19aa6
NC
1181{
1182 int major_version = major;
1183 int minor_version = minor;
1184
1185 if ((major_version == RISCV_UNKNOWN_VERSION
1186 || minor_version == RISCV_UNKNOWN_VERSION)
1187 && rps->get_default_version != NULL)
1188 rps->get_default_version (subset, &major_version, &minor_version);
1189
729a5353 1190 if (!riscv_ext_dont_care_version (subset)
dfe92496
NC
1191 && (major_version == RISCV_UNKNOWN_VERSION
1192 || minor_version == RISCV_UNKNOWN_VERSION))
7ef19aa6 1193 {
729a5353
NC
1194 /* We only add the implicit extension if it is supported in the
1195 chosen ISA spec. */
1196 if (implicit)
1197 return;
1198
7ef19aa6
NC
1199 if (subset[0] == 'x')
1200 rps->error_handler
1201 (_("x ISA extension `%s' must be set with the versions"),
1202 subset);
1203 else
1204 rps->error_handler
1205 (_("cannot find default versions of the ISA extension `%s'"),
1206 subset);
1207 return;
1208 }
1209
dfe92496
NC
1210 if (!implicit)
1211 riscv_add_subset (rps->subset_list, subset,
1212 major_version, minor_version);
729a5353 1213 else
dfe92496
NC
1214 riscv_add_implicit_subset (rps->subset_list, subset,
1215 major_version, minor_version);
7ef19aa6
NC
1216}
1217
1218/* Release subset list. */
1219
1220void
1221riscv_release_subset_list (riscv_subset_list_t *subset_list)
1222{
1223 while (subset_list->head != NULL)
1224 {
1225 riscv_subset_t *next = subset_list->head->next;
1226 free ((void *)subset_list->head->name);
1227 free (subset_list->head);
1228 subset_list->head = next;
1229 }
1230
1231 subset_list->tail = NULL;
1232}
1233
d541518b 1234/* Parsing extension version.
1080bf78
JW
1235
1236 Return Value:
1237 Points to the end of version
1238
1239 Arguments:
d541518b 1240 `rps`: Hooks and status for parsing extensions.
1080bf78
JW
1241 `march`: Full arch string.
1242 `p`: Curent parsing position.
7ef19aa6
NC
1243 `major_version`: Parsed major version.
1244 `minor_version`: Parsed minor version.
1245 `std_ext_p`: True if parsing standard extension. */
1080bf78
JW
1246
1247static const char *
1248riscv_parsing_subset_version (riscv_parse_subset_t *rps,
1249 const char *march,
1250 const char *p,
7ef19aa6
NC
1251 int *major_version,
1252 int *minor_version,
1253 bfd_boolean std_ext_p)
1080bf78
JW
1254{
1255 bfd_boolean major_p = TRUE;
7ef19aa6 1256 int version = 0;
1080bf78
JW
1257 char np;
1258
8f595e9b
NC
1259 *major_version = 0;
1260 *minor_version = 0;
1261 for (; *p; ++p)
1080bf78
JW
1262 {
1263 if (*p == 'p')
1264 {
1265 np = *(p + 1);
1266
1267 if (!ISDIGIT (np))
1268 {
1269 /* Might be beginning of `p` extension. */
1270 if (std_ext_p)
1271 {
1272 *major_version = version;
1273 *minor_version = 0;
1274 return p;
1275 }
1276 else
1277 {
8f595e9b 1278 rps->error_handler
d541518b 1279 (_("-march=%s: expect number after `%dp'"),
8f595e9b 1280 march, version);
1080bf78
JW
1281 return NULL;
1282 }
1283 }
1284
8f595e9b 1285 *major_version = version;
1080bf78
JW
1286 major_p = FALSE;
1287 version = 0;
1288 }
1289 else if (ISDIGIT (*p))
1290 version = (version * 10) + (*p - '0');
1291 else
1292 break;
1293 }
1294
1295 if (major_p)
8f595e9b 1296 *major_version = version;
1080bf78 1297 else
8f595e9b 1298 *minor_version = version;
1080bf78 1299
7ef19aa6
NC
1300 /* We can not find any version in string. */
1301 if (*major_version == 0 && *minor_version == 0)
1302 {
1303 *major_version = RISCV_UNKNOWN_VERSION;
1304 *minor_version = RISCV_UNKNOWN_VERSION;
1305 }
1306
1080bf78
JW
1307 return p;
1308}
1309
1310/* Return string which contain all supported standard extensions in
1311 canonical order. */
1312
1313const char *
1314riscv_supported_std_ext (void)
1315{
1316 return "mafdqlcbjtpvn";
1317}
1318
1319/* Parsing function for standard extensions.
1320
1321 Return Value:
1322 Points to the end of extensions.
1323
1324 Arguments:
d541518b 1325 `rps`: Hooks and status for parsing extensions.
1080bf78
JW
1326 `march`: Full arch string.
1327 `p`: Curent parsing position. */
1328
1329static const char *
1330riscv_parse_std_ext (riscv_parse_subset_t *rps,
8f595e9b
NC
1331 const char *march,
1332 const char *p)
1080bf78
JW
1333{
1334 const char *all_std_exts = riscv_supported_std_ext ();
1335 const char *std_exts = all_std_exts;
7ef19aa6
NC
1336 int major_version;
1337 int minor_version;
d541518b 1338 char subset[2] = {0, 0};
1080bf78
JW
1339
1340 /* First letter must start with i, e or g. */
1341 switch (*p)
1342 {
1343 case 'i':
d541518b 1344 p = riscv_parsing_subset_version (rps, march, ++p,
8f595e9b 1345 &major_version,
7ef19aa6
NC
1346 &minor_version, TRUE);
1347 riscv_parse_add_subset (rps, "i",
1348 major_version,
dfe92496 1349 minor_version, FALSE);
1080bf78
JW
1350 break;
1351
1352 case 'e':
d541518b 1353 p = riscv_parsing_subset_version (rps, march, ++p,
8f595e9b 1354 &major_version,
7ef19aa6
NC
1355 &minor_version, TRUE);
1356 riscv_parse_add_subset (rps, "e",
1357 major_version,
dfe92496 1358 minor_version, FALSE);
8f595e9b 1359 /* i-ext must be enabled. */
7ef19aa6
NC
1360 riscv_parse_add_subset (rps, "i",
1361 RISCV_UNKNOWN_VERSION,
dfe92496 1362 RISCV_UNKNOWN_VERSION, FALSE);
1080bf78
JW
1363
1364 if (*rps->xlen > 32)
1365 {
8f595e9b
NC
1366 rps->error_handler
1367 (_("-march=%s: rv%de is not a valid base ISA"),
1368 march, *rps->xlen);
1080bf78
JW
1369 return NULL;
1370 }
1080bf78
JW
1371 break;
1372
1373 case 'g':
d541518b 1374 p = riscv_parsing_subset_version (rps, march, ++p,
8f595e9b 1375 &major_version,
7ef19aa6 1376 &minor_version, TRUE);
8f595e9b 1377 /* i-ext must be enabled. */
7ef19aa6
NC
1378 riscv_parse_add_subset (rps, "i",
1379 RISCV_UNKNOWN_VERSION,
dfe92496 1380 RISCV_UNKNOWN_VERSION, FALSE);
00d4d1b0
NC
1381 /* g-ext is used to add the implicit extensions, but will
1382 not be output to the arch string. */
1383 riscv_parse_add_subset (rps, "g",
1384 major_version,
1385 minor_version, FALSE);
1080bf78
JW
1386 for ( ; *std_exts != 'q'; std_exts++)
1387 {
d541518b 1388 subset[0] = *std_exts;
7ef19aa6
NC
1389 riscv_parse_add_subset (rps, subset,
1390 RISCV_UNKNOWN_VERSION,
dfe92496 1391 RISCV_UNKNOWN_VERSION, FALSE);
1080bf78
JW
1392 }
1393 break;
1394
1395 default:
8f595e9b 1396 rps->error_handler
d541518b
NC
1397 (_("-march=%s: first ISA extension must be `e', `i' or `g'"),
1398 march);
1080bf78
JW
1399 return NULL;
1400 }
1401
8f595e9b 1402 while (p != NULL && *p != '\0')
1080bf78 1403 {
5a1b31e1 1404 if (*p == 'x' || *p == 's' || *p == 'h' || *p == 'z')
1080bf78
JW
1405 break;
1406
1407 if (*p == '_')
1408 {
1409 p++;
1410 continue;
1411 }
1412
1080bf78 1413 /* Checking canonical order. */
d541518b
NC
1414 char std_ext = *p;
1415 while (*std_exts && std_ext != *std_exts)
1416 std_exts++;
1080bf78
JW
1417
1418 if (std_ext != *std_exts)
1419 {
1420 if (strchr (all_std_exts, std_ext) == NULL)
8f595e9b 1421 rps->error_handler
d541518b
NC
1422 (_("-march=%s: unknown standard ISA extension `%c'"),
1423 march, std_ext);
1080bf78 1424 else
8f595e9b 1425 rps->error_handler
d541518b
NC
1426 (_("-march=%s: standard ISA extension `%c' is not "
1427 "in canonical order"), march, std_ext);
1080bf78
JW
1428 return NULL;
1429 }
1430
1431 std_exts++;
1080bf78 1432 subset[0] = std_ext;
d541518b 1433 p = riscv_parsing_subset_version (rps, march, ++p,
8f595e9b 1434 &major_version,
7ef19aa6
NC
1435 &minor_version, TRUE);
1436 riscv_parse_add_subset (rps, subset,
1437 major_version,
dfe92496 1438 minor_version, FALSE);
1080bf78 1439 }
d541518b 1440
1080bf78
JW
1441 return p;
1442}
1443
403d1bd9 1444/* Classify the argument 'arch' into one of riscv_isa_ext_class_t. */
1080bf78 1445
403d1bd9
JW
1446riscv_isa_ext_class_t
1447riscv_get_prefix_class (const char *arch)
1448{
1449 switch (*arch)
1450 {
b5f998b2 1451 case 's': return RV_ISA_CLASS_S;
5a1b31e1 1452 case 'h': return RV_ISA_CLASS_H;
403d1bd9
JW
1453 case 'x': return RV_ISA_CLASS_X;
1454 case 'z': return RV_ISA_CLASS_Z;
1455 default: return RV_ISA_CLASS_UNKNOWN;
1456 }
1457}
1458
1459/* Structure describing parameters to use when parsing a particular
1460 riscv_isa_ext_class_t. One of these should be provided for each
1461 possible class, except RV_ISA_CLASS_UNKNOWN. */
1462
1463typedef struct riscv_parse_config
1464{
1465 /* Class of the extension. */
1466 riscv_isa_ext_class_t class;
1467
d541518b 1468 /* Prefix string for error printing and internal parser usage. */
403d1bd9
JW
1469 const char *prefix;
1470
d541518b
NC
1471 /* Predicate which is used for checking whether this is a "known"
1472 extension. For 'x', it always returns true since they are by
403d1bd9
JW
1473 definition non-standard and cannot be known. */
1474 bfd_boolean (*ext_valid_p) (const char *);
1475} riscv_parse_config_t;
1476
d541518b
NC
1477/* Parsing function for prefixed extensions.
1478
1479 Return Value:
1480 Points to the end of extension.
1481
1482 Arguments:
1483 `rps`: Hooks and status for parsing extensions.
1484 `march`: Full architecture string.
1485 `p`: Curent parsing position.
1486 `config`: What class and predicate function to use for the
1487 extension. */
1080bf78
JW
1488
1489static const char *
403d1bd9
JW
1490riscv_parse_prefixed_ext (riscv_parse_subset_t *rps,
1491 const char *march,
1492 const char *p,
1493 const riscv_parse_config_t *config)
1080bf78 1494{
7ef19aa6
NC
1495 int major_version;
1496 int minor_version;
403d1bd9
JW
1497 const char *last_name;
1498 riscv_isa_ext_class_t class;
1080bf78
JW
1499
1500 while (*p)
1501 {
1502 if (*p == '_')
1503 {
1504 p++;
1505 continue;
1506 }
1507
403d1bd9
JW
1508 /* Assert that the current extension specifier matches our parsing
1509 class. */
1510 class = riscv_get_prefix_class (p);
d541518b
NC
1511 if (class != config->class
1512 || class == RV_ISA_CLASS_UNKNOWN)
1080bf78
JW
1513 break;
1514
1515 char *subset = xstrdup (p);
1516 char *q = subset;
1517 const char *end_of_version;
1518
1519 while (*++q != '\0' && *q != '_' && !ISDIGIT (*q))
1520 ;
1521
1522 end_of_version =
d541518b
NC
1523 riscv_parsing_subset_version (rps, march, q,
1524 &major_version,
7ef19aa6 1525 &minor_version, FALSE);
1080bf78
JW
1526 *q = '\0';
1527
7ef19aa6
NC
1528 if (end_of_version == NULL)
1529 {
1530 free (subset);
1531 return NULL;
1532 }
1533
d541518b 1534 /* Check that the prefix extension is known.
403d1bd9 1535 For 'x', anything goes but it cannot simply be 'x'.
b5f998b2 1536 For 's', it must be known from a list and cannot simply be 's'.
5a1b31e1 1537 For 'h', it must be known from a list and cannot simply be 'h'.
b5f998b2 1538 For 'z', it must be known from a list and cannot simply be 'z'. */
403d1bd9
JW
1539
1540 /* Check that the extension name is well-formed. */
1541 if (!config->ext_valid_p (subset))
1542 {
1543 rps->error_handler
d541518b 1544 (_("-march=%s: unknown %s ISA extension `%s'"),
403d1bd9
JW
1545 march, config->prefix, subset);
1546 free (subset);
1547 return NULL;
1548 }
1549
d541518b 1550 /* Check that the extension isn't duplicate. */
403d1bd9 1551 last_name = rps->subset_list->tail->name;
403d1bd9
JW
1552 if (!strcasecmp (last_name, subset))
1553 {
8f595e9b 1554 rps->error_handler
d541518b 1555 (_("-march=%s: duplicate %s ISA extension `%s'"),
8f595e9b 1556 march, config->prefix, subset);
403d1bd9
JW
1557 free (subset);
1558 return NULL;
1559 }
1560
d541518b 1561 /* Check that the extension is in alphabetical order. */
6729e2c2 1562 if (riscv_compare_subsets (last_name, subset) > 0)
403d1bd9 1563 {
8f595e9b 1564 rps->error_handler
d541518b
NC
1565 (_("-march=%s: %s ISA extension `%s' is not in alphabetical "
1566 "order. It must come before `%s'"),
8f595e9b 1567 march, config->prefix, subset, last_name);
403d1bd9
JW
1568 free (subset);
1569 return NULL;
1570 }
1571
7ef19aa6
NC
1572 riscv_parse_add_subset (rps, subset,
1573 major_version,
dfe92496 1574 minor_version, FALSE);
1080bf78
JW
1575 free (subset);
1576 p += end_of_version - subset;
1577
1578 if (*p != '\0' && *p != '_')
1579 {
d541518b
NC
1580 rps->error_handler
1581 (_("-march=%s: %s ISA extension must separate with _"),
1582 march, config->prefix);
1080bf78
JW
1583 return NULL;
1584 }
1585 }
1586
1587 return p;
1588}
1589
d541518b
NC
1590/* Lists of prefixed class extensions that binutils should know about.
1591 Whether or not a particular entry is in these lists will dictate if
1592 gas/ld will accept its presence in the architecture string.
403d1bd9 1593
d541518b
NC
1594 Please add the extensions to the lists in lower case. However, keep
1595 these subsets in alphabetical order in these tables is recommended,
1596 although there is no impact on the current implementation. */
403d1bd9
JW
1597
1598static const char * const riscv_std_z_ext_strtab[] =
d541518b 1599{
5a1b31e1 1600 "zicsr", "zifencei", NULL
d541518b 1601};
403d1bd9
JW
1602
1603static const char * const riscv_std_s_ext_strtab[] =
d541518b
NC
1604{
1605 NULL
1606};
403d1bd9 1607
5a1b31e1
NC
1608static const char * const riscv_std_h_ext_strtab[] =
1609{
1610 NULL
1611};
1612
d541518b
NC
1613/* For the extension `ext`, search through the list of known extensions
1614 `known_exts` for a match, and return TRUE if found. */
403d1bd9
JW
1615
1616static bfd_boolean
1617riscv_multi_letter_ext_valid_p (const char *ext,
1618 const char *const *known_exts)
1619{
2d0e1217
AM
1620 size_t i;
1621
1622 for (i = 0; known_exts[i]; ++i)
1623 if (!strcmp (ext, known_exts[i]))
1624 return TRUE;
403d1bd9
JW
1625
1626 return FALSE;
1627}
1628
1629/* Predicator function for x-prefixed extensions.
1630 Anything goes, except the literal 'x'. */
1631
1632static bfd_boolean
1633riscv_ext_x_valid_p (const char *arg)
1634{
1635 if (!strcasecmp (arg, "x"))
1636 return FALSE;
1637
1638 return TRUE;
1639}
1640
1641/* Predicator functions for z-prefixed extensions.
1642 Only known z-extensions are permitted. */
1643
1644static bfd_boolean
1645riscv_ext_z_valid_p (const char *arg)
1646{
1647 return riscv_multi_letter_ext_valid_p (arg, riscv_std_z_ext_strtab);
1648}
1649
1650/* Predicator function for 's' prefixed extensions.
d541518b 1651 Only known s-extensions are permitted. */
403d1bd9
JW
1652
1653static bfd_boolean
1654riscv_ext_s_valid_p (const char *arg)
1655{
1656 return riscv_multi_letter_ext_valid_p (arg, riscv_std_s_ext_strtab);
1657}
1658
5a1b31e1
NC
1659/* Predicator function for 'h' prefixed extensions.
1660 Only known h-extensions are permitted. */
1661
1662static bfd_boolean
1663riscv_ext_h_valid_p (const char *arg)
1664{
1665 return riscv_multi_letter_ext_valid_p (arg, riscv_std_h_ext_strtab);
1666}
1667
d541518b
NC
1668/* Parsing order of the prefixed extensions that is specified by
1669 the ISA spec. */
403d1bd9
JW
1670
1671static const riscv_parse_config_t parse_config[] =
1672{
d541518b 1673 {RV_ISA_CLASS_S, "s", riscv_ext_s_valid_p},
5a1b31e1 1674 {RV_ISA_CLASS_H, "h", riscv_ext_h_valid_p},
d541518b
NC
1675 {RV_ISA_CLASS_Z, "z", riscv_ext_z_valid_p},
1676 {RV_ISA_CLASS_X, "x", riscv_ext_x_valid_p},
1677 {RV_ISA_CLASS_UNKNOWN, NULL, NULL}
403d1bd9
JW
1678};
1679
dfe92496
NC
1680/* Init the riscv_ext_order array. */
1681
1682static void
1683riscv_init_ext_order (void)
1684{
1685 static bfd_boolean inited = FALSE;
1686 const char *std_base_exts = "eig";
1687 const char *std_remain_exts = riscv_supported_std_ext ();
1688 const char *ext;
1689 unsigned int i;
1690 int order;
1691
1692 if (inited)
1693 return;
1694
1695 /* All standard extensions' orders are positive numbers. */
1696 order = 1;
1697
1698 /* Init the standard base extensions first. */
1699 for (ext = std_base_exts; *ext; ext++)
1700 riscv_ext_order[(*ext - 'a')] = order++;
1701
1702 /* Init the standard remaining extensions. */
1703 for (ext = std_remain_exts; *ext; ext++)
1704 riscv_ext_order[(*ext - 'a')] = order++;
1705
1706 /* Init the order for prefixed keywords. The orders are
1707 negative numbers. */
1708 order = -1;
1709 for (i = 0; parse_config[i].class != RV_ISA_CLASS_UNKNOWN; i++)
1710 {
1711 ext = parse_config[i].prefix;
1712 riscv_ext_order[(*ext - 'a')] = order--;
1713 }
1714
1715 inited = TRUE;
1716}
1717
1718/* Add the implicit extensions according to the arch string extensions. */
1719
1720static void
1721riscv_parse_add_implicit_subsets (riscv_parse_subset_t *rps)
1722{
1723 riscv_subset_t *subset = NULL;
1724
1725 /* Add the zicsr and zifencei only when the i's version less than 2.1. */
1726 if ((riscv_lookup_subset (rps->subset_list, "i", &subset))
1727 && (subset->major_version < 2
1728 || (subset->major_version == 2
1729 && subset->minor_version < 1)))
1730 {
1731 riscv_parse_add_subset (rps, "zicsr",
1732 RISCV_UNKNOWN_VERSION,
1733 RISCV_UNKNOWN_VERSION, TRUE);
1734 riscv_parse_add_subset (rps, "zifencei",
1735 RISCV_UNKNOWN_VERSION,
1736 RISCV_UNKNOWN_VERSION, TRUE);
1737 }
1738
1739 if ((riscv_lookup_subset (rps->subset_list, "q", &subset)))
1740 {
1741 riscv_parse_add_subset (rps, "d",
1742 RISCV_UNKNOWN_VERSION,
1743 RISCV_UNKNOWN_VERSION, TRUE);
1744 riscv_parse_add_subset (rps, "f",
1745 RISCV_UNKNOWN_VERSION,
1746 RISCV_UNKNOWN_VERSION, TRUE);
1747 riscv_parse_add_subset (rps, "zicsr",
1748 RISCV_UNKNOWN_VERSION,
1749 RISCV_UNKNOWN_VERSION, TRUE);
1750 }
1751 else if ((riscv_lookup_subset (rps->subset_list, "d", &subset)))
1752 {
1753 riscv_parse_add_subset (rps, "f",
1754 RISCV_UNKNOWN_VERSION,
1755 RISCV_UNKNOWN_VERSION, TRUE);
1756 riscv_parse_add_subset (rps, "zicsr",
1757 RISCV_UNKNOWN_VERSION,
1758 RISCV_UNKNOWN_VERSION, TRUE);
1759 }
1760 else if ((riscv_lookup_subset (rps->subset_list, "f", &subset)))
1761 riscv_parse_add_subset (rps, "zicsr",
1762 RISCV_UNKNOWN_VERSION,
1763 RISCV_UNKNOWN_VERSION, TRUE);
00d4d1b0
NC
1764
1765 if ((riscv_lookup_subset (rps->subset_list, "g", &subset)))
1766 {
1767 riscv_parse_add_subset (rps, "zicsr",
1768 RISCV_UNKNOWN_VERSION,
1769 RISCV_UNKNOWN_VERSION, TRUE);
1770 riscv_parse_add_subset (rps, "zifencei",
1771 RISCV_UNKNOWN_VERSION,
1772 RISCV_UNKNOWN_VERSION, TRUE);
1773 }
dfe92496
NC
1774}
1775
1080bf78
JW
1776/* Function for parsing arch string.
1777
1778 Return Value:
1779 Return TRUE on success.
1780
1781 Arguments:
d541518b
NC
1782 `rps`: Hooks and status for parsing extensions.
1783 `arch`: Full arch string. */
1080bf78
JW
1784
1785bfd_boolean
1786riscv_parse_subset (riscv_parse_subset_t *rps,
1787 const char *arch)
1788{
dfe92496 1789 riscv_subset_t *subset = NULL;
e8d4709e 1790 const char *p;
effc14f5 1791 size_t i;
7ef19aa6 1792 bfd_boolean no_conflict = TRUE;
1080bf78 1793
e8d4709e
NC
1794 for (p = arch; *p != '\0'; p++)
1795 {
1796 if (ISUPPER (*p))
1797 {
1798 rps->error_handler
1799 (_("-march=%s: ISA string cannot contain uppercase letters"),
1800 arch);
1801 return FALSE;
1802 }
1803 }
1804
1805 p = arch;
1080bf78
JW
1806 if (strncmp (p, "rv32", 4) == 0)
1807 {
1808 *rps->xlen = 32;
1809 p += 4;
1810 }
1811 else if (strncmp (p, "rv64", 4) == 0)
1812 {
1813 *rps->xlen = 64;
1814 p += 4;
1815 }
1816 else
1817 {
72bd6912
KC
1818 /* Arch string shouldn't be NULL or empty here. However,
1819 it might be empty only when we failed to merge the arch
1820 string in the riscv_merge_attributes. We have already
1821 issued the correct error message in another side, so do
1822 not issue this error when the arch string is empty. */
1823 if (strlen (arch))
1824 rps->error_handler (
1825 _("-march=%s: ISA string must begin with rv32 or rv64"),
1826 arch);
1080bf78
JW
1827 return FALSE;
1828 }
1829
dfe92496
NC
1830 /* Init the riscv_ext_order array to compare the order of extensions
1831 quickly. */
1832 riscv_init_ext_order ();
1833
1080bf78
JW
1834 /* Parsing standard extension. */
1835 p = riscv_parse_std_ext (rps, arch, p);
1836
1837 if (p == NULL)
1838 return FALSE;
1839
403d1bd9 1840 /* Parse the different classes of extensions in the specified order. */
d541518b
NC
1841 for (i = 0; i < ARRAY_SIZE (parse_config); ++i)
1842 {
1843 p = riscv_parse_prefixed_ext (rps, arch, p, &parse_config[i]);
1080bf78 1844
d541518b
NC
1845 if (p == NULL)
1846 return FALSE;
1847 }
1080bf78
JW
1848
1849 if (*p != '\0')
1850 {
8f595e9b 1851 rps->error_handler (_("-march=%s: unexpected ISA string at end: %s"),
1080bf78
JW
1852 arch, p);
1853 return FALSE;
1854 }
1855
dfe92496
NC
1856 /* Finally add implicit extensions according to the current
1857 extensions. */
1858 riscv_parse_add_implicit_subsets (rps);
1859
d541518b 1860 /* Check the conflicts. */
dfe92496
NC
1861 if (riscv_lookup_subset (rps->subset_list, "e", &subset)
1862 && riscv_lookup_subset (rps->subset_list, "f", &subset))
1080bf78 1863 {
8f595e9b
NC
1864 rps->error_handler
1865 (_("-march=%s: rv32e does not support the `f' extension"),
1866 arch);
7ef19aa6 1867 no_conflict = FALSE;
1080bf78 1868 }
dfe92496
NC
1869 if (riscv_lookup_subset (rps->subset_list, "q", &subset)
1870 && *rps->xlen < 64)
d541518b
NC
1871 {
1872 rps->error_handler
1873 (_("-march=%s: rv32 does not support the `q' extension"),
1874 arch);
7ef19aa6 1875 no_conflict = FALSE;
d541518b 1876 }
7ef19aa6 1877 return no_conflict;
1080bf78 1878}
2dc8dd17
JW
1879
1880/* Return the number of digits for the input. */
1881
8f595e9b 1882size_t
2dc8dd17
JW
1883riscv_estimate_digit (unsigned num)
1884{
1885 size_t digit = 0;
1886 if (num == 0)
1887 return 1;
1888
1889 for (digit = 0; num ; num /= 10)
1890 digit++;
1891
1892 return digit;
1893}
1894
1895/* Auxiliary function to estimate string length of subset list. */
1896
1897static size_t
1898riscv_estimate_arch_strlen1 (const riscv_subset_t *subset)
1899{
1900 if (subset == NULL)
1901 return 6; /* For rv32/rv64/rv128 and string terminator. */
1902
1903 return riscv_estimate_arch_strlen1 (subset->next)
1904 + strlen (subset->name)
1905 + riscv_estimate_digit (subset->major_version)
1906 + 1 /* For version seperator: 'p'. */
1907 + riscv_estimate_digit (subset->minor_version)
1908 + 1 /* For underscore. */;
1909}
1910
1911/* Estimate the string length of this subset list. */
1912
1913static size_t
1914riscv_estimate_arch_strlen (const riscv_subset_list_t *subset_list)
1915{
1916 return riscv_estimate_arch_strlen1 (subset_list->head);
1917}
1918
1919/* Auxiliary function to convert subset info to string. */
1920
1921static void
1922riscv_arch_str1 (riscv_subset_t *subset,
1923 char *attr_str, char *buf, size_t bufsz)
1924{
1925 const char *underline = "_";
729a5353 1926 riscv_subset_t *subset_t = subset;
2dc8dd17 1927
729a5353 1928 if (subset_t == NULL)
2dc8dd17
JW
1929 return;
1930
1931 /* No underline between rvXX and i/e. */
729a5353
NC
1932 if ((strcasecmp (subset_t->name, "i") == 0)
1933 || (strcasecmp (subset_t->name, "e") == 0))
2dc8dd17
JW
1934 underline = "";
1935
1936 snprintf (buf, bufsz, "%s%s%dp%d",
1937 underline,
729a5353
NC
1938 subset_t->name,
1939 subset_t->major_version,
1940 subset_t->minor_version);
2dc8dd17
JW
1941
1942 strncat (attr_str, buf, bufsz);
1943
729a5353
NC
1944 /* Skip 'i' extension after 'e', or skip extensions which
1945 versions are unknown. */
1946 while (subset_t->next
1947 && ((strcmp (subset_t->name, "e") == 0
1948 && strcmp (subset_t->next->name, "i") == 0)
1949 || subset_t->next->major_version == RISCV_UNKNOWN_VERSION
1950 || subset_t->next->minor_version == RISCV_UNKNOWN_VERSION))
1951 subset_t = subset_t->next;
1952
1953 riscv_arch_str1 (subset_t->next, attr_str, buf, bufsz);
2dc8dd17
JW
1954}
1955
1956/* Convert subset info to string with explicit version info. */
1957
1958char *
1959riscv_arch_str (unsigned xlen, const riscv_subset_list_t *subset)
1960{
1961 size_t arch_str_len = riscv_estimate_arch_strlen (subset);
1962 char *attr_str = xmalloc (arch_str_len);
1963 char *buf = xmalloc (arch_str_len);
1964
1965 snprintf (attr_str, arch_str_len, "rv%u", xlen);
1966
1967 riscv_arch_str1 (subset->head, attr_str, buf, arch_str_len);
1968 free (buf);
1969
1970 return attr_str;
1971}