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