RISC-V: Comments tidy and improvement.
[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"
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. */
e23eba97
NC
875struct elf_reloc_map
876{
877 bfd_reloc_code_real_type bfd_val;
878 enum elf_riscv_reloc_type elf_val;
879};
880
881static const struct elf_reloc_map riscv_reloc_map[] =
882{
883 { BFD_RELOC_NONE, R_RISCV_NONE },
884 { BFD_RELOC_32, R_RISCV_32 },
885 { BFD_RELOC_64, R_RISCV_64 },
886 { BFD_RELOC_RISCV_ADD8, R_RISCV_ADD8 },
887 { BFD_RELOC_RISCV_ADD16, R_RISCV_ADD16 },
888 { BFD_RELOC_RISCV_ADD32, R_RISCV_ADD32 },
889 { BFD_RELOC_RISCV_ADD64, R_RISCV_ADD64 },
890 { BFD_RELOC_RISCV_SUB8, R_RISCV_SUB8 },
891 { BFD_RELOC_RISCV_SUB16, R_RISCV_SUB16 },
892 { BFD_RELOC_RISCV_SUB32, R_RISCV_SUB32 },
893 { BFD_RELOC_RISCV_SUB64, R_RISCV_SUB64 },
894 { BFD_RELOC_CTOR, R_RISCV_64 },
895 { BFD_RELOC_12_PCREL, R_RISCV_BRANCH },
896 { BFD_RELOC_RISCV_HI20, R_RISCV_HI20 },
897 { BFD_RELOC_RISCV_LO12_I, R_RISCV_LO12_I },
898 { BFD_RELOC_RISCV_LO12_S, R_RISCV_LO12_S },
899 { BFD_RELOC_RISCV_PCREL_LO12_I, R_RISCV_PCREL_LO12_I },
900 { BFD_RELOC_RISCV_PCREL_LO12_S, R_RISCV_PCREL_LO12_S },
901 { BFD_RELOC_RISCV_CALL, R_RISCV_CALL },
902 { BFD_RELOC_RISCV_CALL_PLT, R_RISCV_CALL_PLT },
903 { BFD_RELOC_RISCV_PCREL_HI20, R_RISCV_PCREL_HI20 },
904 { BFD_RELOC_RISCV_JMP, R_RISCV_JAL },
905 { BFD_RELOC_RISCV_GOT_HI20, R_RISCV_GOT_HI20 },
906 { BFD_RELOC_RISCV_TLS_DTPMOD32, R_RISCV_TLS_DTPMOD32 },
907 { BFD_RELOC_RISCV_TLS_DTPREL32, R_RISCV_TLS_DTPREL32 },
908 { BFD_RELOC_RISCV_TLS_DTPMOD64, R_RISCV_TLS_DTPMOD64 },
909 { BFD_RELOC_RISCV_TLS_DTPREL64, R_RISCV_TLS_DTPREL64 },
910 { BFD_RELOC_RISCV_TLS_TPREL32, R_RISCV_TLS_TPREL32 },
911 { BFD_RELOC_RISCV_TLS_TPREL64, R_RISCV_TLS_TPREL64 },
912 { BFD_RELOC_RISCV_TPREL_HI20, R_RISCV_TPREL_HI20 },
913 { BFD_RELOC_RISCV_TPREL_ADD, R_RISCV_TPREL_ADD },
914 { BFD_RELOC_RISCV_TPREL_LO12_S, R_RISCV_TPREL_LO12_S },
915 { BFD_RELOC_RISCV_TPREL_LO12_I, R_RISCV_TPREL_LO12_I },
916 { BFD_RELOC_RISCV_TLS_GOT_HI20, R_RISCV_TLS_GOT_HI20 },
917 { BFD_RELOC_RISCV_TLS_GD_HI20, R_RISCV_TLS_GD_HI20 },
918 { BFD_RELOC_RISCV_ALIGN, R_RISCV_ALIGN },
919 { BFD_RELOC_RISCV_RVC_BRANCH, R_RISCV_RVC_BRANCH },
920 { BFD_RELOC_RISCV_RVC_JUMP, R_RISCV_RVC_JUMP },
921 { BFD_RELOC_RISCV_RVC_LUI, R_RISCV_RVC_LUI },
922 { BFD_RELOC_RISCV_GPREL_I, R_RISCV_GPREL_I },
923 { BFD_RELOC_RISCV_GPREL_S, R_RISCV_GPREL_S },
45f76423
AW
924 { BFD_RELOC_RISCV_TPREL_I, R_RISCV_TPREL_I },
925 { BFD_RELOC_RISCV_TPREL_S, R_RISCV_TPREL_S },
926 { BFD_RELOC_RISCV_RELAX, R_RISCV_RELAX },
927 { BFD_RELOC_RISCV_SUB6, R_RISCV_SUB6 },
928 { BFD_RELOC_RISCV_SET6, R_RISCV_SET6 },
929 { BFD_RELOC_RISCV_SET8, R_RISCV_SET8 },
930 { BFD_RELOC_RISCV_SET16, R_RISCV_SET16 },
931 { BFD_RELOC_RISCV_SET32, R_RISCV_SET32 },
a6cbf936 932 { BFD_RELOC_RISCV_32_PCREL, R_RISCV_32_PCREL },
e23eba97
NC
933};
934
935/* Given a BFD reloc type, return a howto structure. */
936
937reloc_howto_type *
938riscv_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED,
939 bfd_reloc_code_real_type code)
940{
941 unsigned int i;
942
943 for (i = 0; i < ARRAY_SIZE (riscv_reloc_map); i++)
944 if (riscv_reloc_map[i].bfd_val == code)
945 return &howto_table[(int) riscv_reloc_map[i].elf_val];
946
947 bfd_set_error (bfd_error_bad_value);
948 return NULL;
949}
950
951reloc_howto_type *
952riscv_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED, const char *r_name)
953{
954 unsigned int i;
955
956 for (i = 0; i < ARRAY_SIZE (howto_table); i++)
957 if (howto_table[i].name && strcasecmp (howto_table[i].name, r_name) == 0)
958 return &howto_table[i];
959
960 return NULL;
961}
962
963reloc_howto_type *
0aa13fee 964riscv_elf_rtype_to_howto (bfd *abfd, unsigned int r_type)
e23eba97
NC
965{
966 if (r_type >= ARRAY_SIZE (howto_table))
967 {
0aa13fee
AM
968 (*_bfd_error_handler) (_("%pB: unsupported relocation type %#x"),
969 abfd, r_type);
e23eba97
NC
970 bfd_set_error (bfd_error_bad_value);
971 return NULL;
972 }
973 return &howto_table[r_type];
974}
57593436
KLC
975
976/* Special_function of RISCV_ADD and RISCV_SUB relocations. */
977
978static bfd_reloc_status_type
979riscv_elf_add_sub_reloc (bfd *abfd,
980 arelent *reloc_entry,
981 asymbol *symbol,
982 void *data,
983 asection *input_section,
984 bfd *output_bfd,
985 char **error_message ATTRIBUTE_UNUSED)
986{
987 reloc_howto_type *howto = reloc_entry->howto;
988 bfd_vma relocation;
989
990 if (output_bfd != NULL
991 && (symbol->flags & BSF_SECTION_SYM) == 0
992 && (!reloc_entry->howto->partial_inplace || reloc_entry->addend == 0))
993 {
994 reloc_entry->address += input_section->output_offset;
995 return bfd_reloc_ok;
996 }
997
998 if (output_bfd != NULL)
999 return bfd_reloc_continue;
1000
1001 relocation = symbol->value + symbol->section->output_section->vma
1002 + symbol->section->output_offset + reloc_entry->addend;
1003 bfd_vma old_value = bfd_get (howto->bitsize, abfd,
1004 data + reloc_entry->address);
1005
1006 switch (howto->type)
1007 {
1008 case R_RISCV_ADD8:
1009 case R_RISCV_ADD16:
1010 case R_RISCV_ADD32:
1011 case R_RISCV_ADD64:
1012 relocation = old_value + relocation;
1013 break;
1014 case R_RISCV_SUB6:
1015 case R_RISCV_SUB8:
1016 case R_RISCV_SUB16:
1017 case R_RISCV_SUB32:
1018 case R_RISCV_SUB64:
1019 relocation = old_value - relocation;
1020 break;
1021 }
1022 bfd_put (howto->bitsize, abfd, relocation, data + reloc_entry->address);
1023
1024 return bfd_reloc_ok;
1025}
1080bf78 1026
dcd709e0 1027/* Array is used to compare the orders of all extensions quickly.
7ef19aa6 1028
dcd709e0
NC
1029 Zero value: Preserved keyword.
1030 Negative value: Prefixed keyword (s, h, x, z).
1031 Positive value: Standard extension. */
dfe92496
NC
1032
1033static int riscv_ext_order[26] = {0};
1034
1035/* Similar to the strcmp. It returns an integer less than, equal to,
1036 or greater than zero if `subset2` is found, respectively, to be less
1037 than, to match, or be greater than `subset1`. */
1038
4c0e540e 1039int
dfe92496 1040riscv_compare_subsets (const char *subset1, const char *subset2)
7ef19aa6 1041{
dfe92496
NC
1042 int order1 = riscv_ext_order[(*subset1 - 'a')];
1043 int order2 = riscv_ext_order[(*subset2 - 'a')];
7ef19aa6 1044
dfe92496
NC
1045 /* Compare the standard extension first. */
1046 if (order1 > 0 && order2 > 0)
1047 return order1 - order2;
7ef19aa6 1048
dfe92496
NC
1049 if (order1 == order2 && order1 < 0)
1050 {
1051 /* Compare the standard addition z extensions. */
1052 if (*subset1 == 'z')
1053 {
1054 order1 = riscv_ext_order[(*++subset1 - 'a')];
1055 order2 = riscv_ext_order[(*++subset2 - 'a')];
1056 if (order1 != order2)
1057 return order1 - order2;
1058 }
1059 return strcasecmp (++subset1, ++subset2);
1060 }
1061
1062 return order2 - order1;
1063}
1064
1065/* Find subset in the list. Return TRUE and set `current` to the subset
1066 if it is found. Otherwise, return FALSE and set `current` to the place
1067 where we should insert the subset. However, return FALSE with the NULL
1068 `current` means we should insert the subset at the head of subset list,
1069 if needed. */
1070
1071bfd_boolean
1072riscv_lookup_subset (const riscv_subset_list_t *subset_list,
1073 const char *subset,
1074 riscv_subset_t **current)
1075{
1076 riscv_subset_t *s, *pre_s = NULL;
1077
1078 for (s = subset_list->head;
1079 s != NULL;
1080 pre_s = s, s = s->next)
1081 {
1082 int cmp = riscv_compare_subsets (s->name, subset);
1083 if (cmp == 0)
1084 {
1085 *current = s;
1086 return TRUE;
1087 }
1088 else if (cmp > 0)
1089 break;
1090 }
1091 *current = pre_s;
1092 return FALSE;
7ef19aa6
NC
1093}
1094
dcd709e0 1095/* Add extension from ISA string to the last of the subset list. */
7ef19aa6
NC
1096
1097void
1098riscv_add_subset (riscv_subset_list_t *subset_list,
1099 const char *subset,
1100 int major,
1101 int minor)
1102{
1103 riscv_subset_t *s = xmalloc (sizeof *s);
1104
1105 if (subset_list->head == NULL)
1106 subset_list->head = s;
1107
1108 s->name = xstrdup (subset);
1109 s->major_version = major;
1110 s->minor_version = minor;
1111 s->next = NULL;
1112
1113 if (subset_list->tail != NULL)
1114 subset_list->tail->next = s;
1115 subset_list->tail = s;
1116}
1117
dfe92496
NC
1118/* Add the implicit extension to the subset list. Search the
1119 list first, and then find the right place to add. */
1120
1121static void
1122riscv_add_implicit_subset (riscv_subset_list_t *subset_list,
1123 const char *subset,
1124 int major,
1125 int minor)
1126{
1127 riscv_subset_t *current, *new;
1128
1129 if (riscv_lookup_subset (subset_list, subset, &current))
1130 return;
1131
1132 new = xmalloc (sizeof *new);
1133 new->name = xstrdup (subset);
1134 new->major_version = major;
1135 new->minor_version = minor;
1136 new->next = NULL;
1137
1138 if (current != NULL)
1139 {
1140 new->next = current->next;
1141 current->next = new;
1142 }
1143 else
1144 {
1145 new->next = subset_list->head;
1146 subset_list->head = new;
1147 }
1148}
1149
729a5353
NC
1150/* These extensions are added to the subset list for special purposes,
1151 with the explicit versions or the RISCV_UNKNOWN_VERSION versions.
dcd709e0 1152 Therefore, we won't output them to the output ISA string in the
729a5353
NC
1153 riscv_arch_str1, if the versions are unknown. */
1154
1155static bfd_boolean
1156riscv_ext_dont_care_version (const char *subset)
1157{
1158 if (strcmp (subset, "g") == 0
1159 || strcmp (subset, "zicsr") == 0
1160 || strcmp (subset, "zifencei") == 0)
1161 return TRUE;
1162 return FALSE;
1163}
1164
dcd709e0
NC
1165/* We have to add all extensions from ISA string first, and then start to
1166 add their implicit extensions. The extensions from ISA string must be
dfe92496
NC
1167 set in order, so we can add them to the last of the subset list
1168 directly, without searching.
1169
1170 Find the default versions for the extension before adding them to
7ef19aa6
NC
1171 the subset list, if their versions are RISCV_UNKNOWN_VERSION.
1172 Afterwards, report errors if we can not find their default versions. */
1173
1174static void
1175riscv_parse_add_subset (riscv_parse_subset_t *rps,
1176 const char *subset,
1177 int major,
dfe92496
NC
1178 int minor,
1179 bfd_boolean implicit)
7ef19aa6
NC
1180{
1181 int major_version = major;
1182 int minor_version = minor;
1183
1184 if ((major_version == RISCV_UNKNOWN_VERSION
1185 || minor_version == RISCV_UNKNOWN_VERSION)
1186 && rps->get_default_version != NULL)
1187 rps->get_default_version (subset, &major_version, &minor_version);
1188
729a5353 1189 if (!riscv_ext_dont_care_version (subset)
dfe92496
NC
1190 && (major_version == RISCV_UNKNOWN_VERSION
1191 || minor_version == RISCV_UNKNOWN_VERSION))
7ef19aa6 1192 {
729a5353
NC
1193 /* We only add the implicit extension if it is supported in the
1194 chosen ISA spec. */
1195 if (implicit)
1196 return;
1197
7ef19aa6
NC
1198 if (subset[0] == 'x')
1199 rps->error_handler
1200 (_("x ISA extension `%s' must be set with the versions"),
1201 subset);
1202 else
1203 rps->error_handler
1204 (_("cannot find default versions of the ISA extension `%s'"),
1205 subset);
1206 return;
1207 }
1208
dfe92496
NC
1209 if (!implicit)
1210 riscv_add_subset (rps->subset_list, subset,
1211 major_version, minor_version);
729a5353 1212 else
dfe92496
NC
1213 riscv_add_implicit_subset (rps->subset_list, subset,
1214 major_version, minor_version);
7ef19aa6
NC
1215}
1216
1217/* Release subset list. */
1218
1219void
1220riscv_release_subset_list (riscv_subset_list_t *subset_list)
1221{
1222 while (subset_list->head != NULL)
1223 {
1224 riscv_subset_t *next = subset_list->head->next;
1225 free ((void *)subset_list->head->name);
1226 free (subset_list->head);
1227 subset_list->head = next;
1228 }
1229
1230 subset_list->tail = NULL;
1231}
1232
d541518b 1233/* Parsing extension version.
1080bf78
JW
1234
1235 Return Value:
1236 Points to the end of version
1237
1238 Arguments:
d541518b 1239 `rps`: Hooks and status for parsing extensions.
dcd709e0 1240 `march`: Full ISA string.
1080bf78 1241 `p`: Curent parsing position.
7ef19aa6
NC
1242 `major_version`: Parsed major version.
1243 `minor_version`: Parsed minor version.
1244 `std_ext_p`: True if parsing standard extension. */
1080bf78
JW
1245
1246static const char *
1247riscv_parsing_subset_version (riscv_parse_subset_t *rps,
1248 const char *march,
1249 const char *p,
7ef19aa6
NC
1250 int *major_version,
1251 int *minor_version,
1252 bfd_boolean std_ext_p)
1080bf78
JW
1253{
1254 bfd_boolean major_p = TRUE;
7ef19aa6 1255 int version = 0;
1080bf78
JW
1256 char np;
1257
8f595e9b
NC
1258 *major_version = 0;
1259 *minor_version = 0;
1260 for (; *p; ++p)
1080bf78
JW
1261 {
1262 if (*p == 'p')
1263 {
1264 np = *(p + 1);
1265
1266 if (!ISDIGIT (np))
1267 {
1268 /* Might be beginning of `p` extension. */
1269 if (std_ext_p)
1270 {
1271 *major_version = version;
1272 *minor_version = 0;
1273 return p;
1274 }
1275 else
1276 {
8f595e9b 1277 rps->error_handler
d541518b 1278 (_("-march=%s: expect number after `%dp'"),
8f595e9b 1279 march, version);
1080bf78
JW
1280 return NULL;
1281 }
1282 }
1283
8f595e9b 1284 *major_version = version;
1080bf78
JW
1285 major_p = FALSE;
1286 version = 0;
1287 }
1288 else if (ISDIGIT (*p))
1289 version = (version * 10) + (*p - '0');
1290 else
1291 break;
1292 }
1293
1294 if (major_p)
8f595e9b 1295 *major_version = version;
1080bf78 1296 else
8f595e9b 1297 *minor_version = version;
1080bf78 1298
7ef19aa6
NC
1299 /* We can not find any version in string. */
1300 if (*major_version == 0 && *minor_version == 0)
1301 {
1302 *major_version = RISCV_UNKNOWN_VERSION;
1303 *minor_version = RISCV_UNKNOWN_VERSION;
1304 }
1305
1080bf78
JW
1306 return p;
1307}
1308
1309/* Return string which contain all supported standard extensions in
1310 canonical order. */
1311
1312const char *
1313riscv_supported_std_ext (void)
1314{
1315 return "mafdqlcbjtpvn";
1316}
1317
1318/* Parsing function for standard extensions.
1319
1320 Return Value:
1321 Points to the end of extensions.
1322
1323 Arguments:
d541518b 1324 `rps`: Hooks and status for parsing extensions.
dcd709e0 1325 `march`: Full ISA string.
1080bf78
JW
1326 `p`: Curent parsing position. */
1327
1328static const char *
1329riscv_parse_std_ext (riscv_parse_subset_t *rps,
8f595e9b
NC
1330 const char *march,
1331 const char *p)
1080bf78
JW
1332{
1333 const char *all_std_exts = riscv_supported_std_ext ();
1334 const char *std_exts = all_std_exts;
7ef19aa6
NC
1335 int major_version;
1336 int minor_version;
d541518b 1337 char subset[2] = {0, 0};
1080bf78
JW
1338
1339 /* First letter must start with i, e or g. */
1340 switch (*p)
1341 {
1342 case 'i':
d541518b 1343 p = riscv_parsing_subset_version (rps, march, ++p,
8f595e9b 1344 &major_version,
7ef19aa6
NC
1345 &minor_version, TRUE);
1346 riscv_parse_add_subset (rps, "i",
1347 major_version,
dfe92496 1348 minor_version, FALSE);
1080bf78
JW
1349 break;
1350
1351 case 'e':
d541518b 1352 p = riscv_parsing_subset_version (rps, march, ++p,
8f595e9b 1353 &major_version,
7ef19aa6
NC
1354 &minor_version, TRUE);
1355 riscv_parse_add_subset (rps, "e",
1356 major_version,
dfe92496 1357 minor_version, FALSE);
8f595e9b 1358 /* i-ext must be enabled. */
7ef19aa6
NC
1359 riscv_parse_add_subset (rps, "i",
1360 RISCV_UNKNOWN_VERSION,
dfe92496 1361 RISCV_UNKNOWN_VERSION, FALSE);
1080bf78
JW
1362
1363 if (*rps->xlen > 32)
1364 {
8f595e9b
NC
1365 rps->error_handler
1366 (_("-march=%s: rv%de is not a valid base ISA"),
1367 march, *rps->xlen);
1080bf78
JW
1368 return NULL;
1369 }
1080bf78
JW
1370 break;
1371
1372 case 'g':
d541518b 1373 p = riscv_parsing_subset_version (rps, march, ++p,
8f595e9b 1374 &major_version,
7ef19aa6 1375 &minor_version, TRUE);
8f595e9b 1376 /* i-ext must be enabled. */
7ef19aa6
NC
1377 riscv_parse_add_subset (rps, "i",
1378 RISCV_UNKNOWN_VERSION,
dfe92496 1379 RISCV_UNKNOWN_VERSION, FALSE);
00d4d1b0 1380 /* g-ext is used to add the implicit extensions, but will
dcd709e0 1381 not be output to the ISA string. */
00d4d1b0
NC
1382 riscv_parse_add_subset (rps, "g",
1383 major_version,
1384 minor_version, FALSE);
1080bf78
JW
1385 for ( ; *std_exts != 'q'; std_exts++)
1386 {
d541518b 1387 subset[0] = *std_exts;
7ef19aa6
NC
1388 riscv_parse_add_subset (rps, subset,
1389 RISCV_UNKNOWN_VERSION,
dfe92496 1390 RISCV_UNKNOWN_VERSION, FALSE);
1080bf78
JW
1391 }
1392 break;
1393
1394 default:
8f595e9b 1395 rps->error_handler
d541518b
NC
1396 (_("-march=%s: first ISA extension must be `e', `i' or `g'"),
1397 march);
1080bf78
JW
1398 return NULL;
1399 }
1400
8f595e9b 1401 while (p != NULL && *p != '\0')
1080bf78 1402 {
5a1b31e1 1403 if (*p == 'x' || *p == 's' || *p == 'h' || *p == 'z')
1080bf78
JW
1404 break;
1405
1406 if (*p == '_')
1407 {
1408 p++;
1409 continue;
1410 }
1411
1080bf78 1412 /* Checking canonical order. */
d541518b
NC
1413 char std_ext = *p;
1414 while (*std_exts && std_ext != *std_exts)
1415 std_exts++;
1080bf78
JW
1416
1417 if (std_ext != *std_exts)
1418 {
1419 if (strchr (all_std_exts, std_ext) == NULL)
8f595e9b 1420 rps->error_handler
d541518b
NC
1421 (_("-march=%s: unknown standard ISA extension `%c'"),
1422 march, std_ext);
1080bf78 1423 else
8f595e9b 1424 rps->error_handler
d541518b
NC
1425 (_("-march=%s: standard ISA extension `%c' is not "
1426 "in canonical order"), march, std_ext);
1080bf78
JW
1427 return NULL;
1428 }
1429
1430 std_exts++;
1080bf78 1431 subset[0] = std_ext;
d541518b 1432 p = riscv_parsing_subset_version (rps, march, ++p,
8f595e9b 1433 &major_version,
7ef19aa6
NC
1434 &minor_version, TRUE);
1435 riscv_parse_add_subset (rps, subset,
1436 major_version,
dfe92496 1437 minor_version, FALSE);
1080bf78 1438 }
d541518b 1439
1080bf78
JW
1440 return p;
1441}
1442
dcd709e0 1443/* Classify ARCH into one of riscv_isa_ext_class_t. */
1080bf78 1444
403d1bd9
JW
1445riscv_isa_ext_class_t
1446riscv_get_prefix_class (const char *arch)
1447{
1448 switch (*arch)
1449 {
b5f998b2 1450 case 's': return RV_ISA_CLASS_S;
5a1b31e1 1451 case 'h': return RV_ISA_CLASS_H;
403d1bd9
JW
1452 case 'x': return RV_ISA_CLASS_X;
1453 case 'z': return RV_ISA_CLASS_Z;
1454 default: return RV_ISA_CLASS_UNKNOWN;
1455 }
1456}
1457
1458/* Structure describing parameters to use when parsing a particular
dcd709e0 1459 riscv_isa_ext_class_t. One of these should be provided for each
403d1bd9 1460 possible class, except RV_ISA_CLASS_UNKNOWN. */
403d1bd9
JW
1461typedef struct riscv_parse_config
1462{
1463 /* Class of the extension. */
1464 riscv_isa_ext_class_t class;
1465
d541518b 1466 /* Prefix string for error printing and internal parser usage. */
403d1bd9
JW
1467 const char *prefix;
1468
d541518b
NC
1469 /* Predicate which is used for checking whether this is a "known"
1470 extension. For 'x', it always returns true since they are by
403d1bd9
JW
1471 definition non-standard and cannot be known. */
1472 bfd_boolean (*ext_valid_p) (const char *);
1473} riscv_parse_config_t;
1474
d541518b
NC
1475/* Parsing function for prefixed extensions.
1476
1477 Return Value:
1478 Points to the end of extension.
1479
1480 Arguments:
1481 `rps`: Hooks and status for parsing extensions.
dcd709e0 1482 `march`: Full ISA string.
d541518b
NC
1483 `p`: Curent parsing position.
1484 `config`: What class and predicate function to use for the
1485 extension. */
1080bf78
JW
1486
1487static const char *
403d1bd9
JW
1488riscv_parse_prefixed_ext (riscv_parse_subset_t *rps,
1489 const char *march,
1490 const char *p,
1491 const riscv_parse_config_t *config)
1080bf78 1492{
7ef19aa6
NC
1493 int major_version;
1494 int minor_version;
403d1bd9
JW
1495 const char *last_name;
1496 riscv_isa_ext_class_t class;
1080bf78
JW
1497
1498 while (*p)
1499 {
1500 if (*p == '_')
1501 {
1502 p++;
1503 continue;
1504 }
1505
403d1bd9
JW
1506 /* Assert that the current extension specifier matches our parsing
1507 class. */
1508 class = riscv_get_prefix_class (p);
d541518b
NC
1509 if (class != config->class
1510 || class == RV_ISA_CLASS_UNKNOWN)
1080bf78
JW
1511 break;
1512
1513 char *subset = xstrdup (p);
1514 char *q = subset;
1515 const char *end_of_version;
1516
1517 while (*++q != '\0' && *q != '_' && !ISDIGIT (*q))
1518 ;
1519
1520 end_of_version =
d541518b
NC
1521 riscv_parsing_subset_version (rps, march, q,
1522 &major_version,
7ef19aa6 1523 &minor_version, FALSE);
1080bf78
JW
1524 *q = '\0';
1525
7ef19aa6
NC
1526 if (end_of_version == NULL)
1527 {
1528 free (subset);
1529 return NULL;
1530 }
1531
d541518b 1532 /* Check that the prefix extension is known.
403d1bd9 1533 For 'x', anything goes but it cannot simply be 'x'.
b5f998b2 1534 For 's', it must be known from a list and cannot simply be 's'.
5a1b31e1 1535 For 'h', it must be known from a list and cannot simply be 'h'.
b5f998b2 1536 For 'z', it must be known from a list and cannot simply be 'z'. */
403d1bd9
JW
1537
1538 /* Check that the extension name is well-formed. */
1539 if (!config->ext_valid_p (subset))
1540 {
1541 rps->error_handler
d541518b 1542 (_("-march=%s: unknown %s ISA extension `%s'"),
403d1bd9
JW
1543 march, config->prefix, subset);
1544 free (subset);
1545 return NULL;
1546 }
1547
d541518b 1548 /* Check that the extension isn't duplicate. */
403d1bd9 1549 last_name = rps->subset_list->tail->name;
403d1bd9
JW
1550 if (!strcasecmp (last_name, subset))
1551 {
8f595e9b 1552 rps->error_handler
d541518b 1553 (_("-march=%s: duplicate %s ISA extension `%s'"),
8f595e9b 1554 march, config->prefix, subset);
403d1bd9
JW
1555 free (subset);
1556 return NULL;
1557 }
1558
d541518b 1559 /* Check that the extension is in alphabetical order. */
6729e2c2 1560 if (riscv_compare_subsets (last_name, subset) > 0)
403d1bd9 1561 {
8f595e9b 1562 rps->error_handler
d541518b
NC
1563 (_("-march=%s: %s ISA extension `%s' is not in alphabetical "
1564 "order. It must come before `%s'"),
8f595e9b 1565 march, config->prefix, subset, last_name);
403d1bd9
JW
1566 free (subset);
1567 return NULL;
1568 }
1569
7ef19aa6
NC
1570 riscv_parse_add_subset (rps, subset,
1571 major_version,
dfe92496 1572 minor_version, FALSE);
1080bf78 1573 p += end_of_version - subset;
e9cf3691 1574 free (subset);
1080bf78
JW
1575
1576 if (*p != '\0' && *p != '_')
1577 {
d541518b
NC
1578 rps->error_handler
1579 (_("-march=%s: %s ISA extension must separate with _"),
1580 march, config->prefix);
1080bf78
JW
1581 return NULL;
1582 }
1583 }
1584
1585 return p;
1586}
1587
d541518b
NC
1588/* Lists of prefixed class extensions that binutils should know about.
1589 Whether or not a particular entry is in these lists will dictate if
1590 gas/ld will accept its presence in the architecture string.
403d1bd9 1591
d541518b
NC
1592 Please add the extensions to the lists in lower case. However, keep
1593 these subsets in alphabetical order in these tables is recommended,
1594 although there is no impact on the current implementation. */
403d1bd9
JW
1595
1596static const char * const riscv_std_z_ext_strtab[] =
d541518b 1597{
aa881ecd 1598 "zicsr", "zifencei", "zihintpause", "zba", "zbb", "zbc", NULL
d541518b 1599};
403d1bd9
JW
1600
1601static const char * const riscv_std_s_ext_strtab[] =
d541518b
NC
1602{
1603 NULL
1604};
403d1bd9 1605
5a1b31e1
NC
1606static const char * const riscv_std_h_ext_strtab[] =
1607{
1608 NULL
1609};
1610
d541518b
NC
1611/* For the extension `ext`, search through the list of known extensions
1612 `known_exts` for a match, and return TRUE if found. */
403d1bd9
JW
1613
1614static bfd_boolean
1615riscv_multi_letter_ext_valid_p (const char *ext,
1616 const char *const *known_exts)
1617{
2d0e1217
AM
1618 size_t i;
1619
1620 for (i = 0; known_exts[i]; ++i)
1621 if (!strcmp (ext, known_exts[i]))
1622 return TRUE;
403d1bd9
JW
1623
1624 return FALSE;
1625}
1626
1627/* Predicator function for x-prefixed extensions.
1628 Anything goes, except the literal 'x'. */
1629
1630static bfd_boolean
1631riscv_ext_x_valid_p (const char *arg)
1632{
1633 if (!strcasecmp (arg, "x"))
1634 return FALSE;
1635
1636 return TRUE;
1637}
1638
1639/* Predicator functions for z-prefixed extensions.
1640 Only known z-extensions are permitted. */
1641
1642static bfd_boolean
1643riscv_ext_z_valid_p (const char *arg)
1644{
1645 return riscv_multi_letter_ext_valid_p (arg, riscv_std_z_ext_strtab);
1646}
1647
1648/* Predicator function for 's' prefixed extensions.
d541518b 1649 Only known s-extensions are permitted. */
403d1bd9
JW
1650
1651static bfd_boolean
1652riscv_ext_s_valid_p (const char *arg)
1653{
1654 return riscv_multi_letter_ext_valid_p (arg, riscv_std_s_ext_strtab);
1655}
1656
5a1b31e1
NC
1657/* Predicator function for 'h' prefixed extensions.
1658 Only known h-extensions are permitted. */
1659
1660static bfd_boolean
1661riscv_ext_h_valid_p (const char *arg)
1662{
1663 return riscv_multi_letter_ext_valid_p (arg, riscv_std_h_ext_strtab);
1664}
1665
d541518b
NC
1666/* Parsing order of the prefixed extensions that is specified by
1667 the ISA spec. */
403d1bd9
JW
1668static const riscv_parse_config_t parse_config[] =
1669{
d541518b 1670 {RV_ISA_CLASS_S, "s", riscv_ext_s_valid_p},
5a1b31e1 1671 {RV_ISA_CLASS_H, "h", riscv_ext_h_valid_p},
d541518b
NC
1672 {RV_ISA_CLASS_Z, "z", riscv_ext_z_valid_p},
1673 {RV_ISA_CLASS_X, "x", riscv_ext_x_valid_p},
1674 {RV_ISA_CLASS_UNKNOWN, NULL, NULL}
403d1bd9
JW
1675};
1676
dfe92496
NC
1677/* Init the riscv_ext_order array. */
1678
1679static void
1680riscv_init_ext_order (void)
1681{
1682 static bfd_boolean inited = FALSE;
1683 const char *std_base_exts = "eig";
1684 const char *std_remain_exts = riscv_supported_std_ext ();
1685 const char *ext;
1686 unsigned int i;
1687 int order;
1688
1689 if (inited)
1690 return;
1691
dcd709e0 1692 /* The orders of all standard extensions are positive. */
dfe92496
NC
1693 order = 1;
1694
1695 /* Init the standard base extensions first. */
1696 for (ext = std_base_exts; *ext; ext++)
1697 riscv_ext_order[(*ext - 'a')] = order++;
1698
1699 /* Init the standard remaining extensions. */
1700 for (ext = std_remain_exts; *ext; ext++)
1701 riscv_ext_order[(*ext - 'a')] = order++;
1702
dcd709e0 1703 /* Init the order for prefixed keywords. The orders are negative. */
dfe92496
NC
1704 order = -1;
1705 for (i = 0; parse_config[i].class != RV_ISA_CLASS_UNKNOWN; i++)
1706 {
1707 ext = parse_config[i].prefix;
1708 riscv_ext_order[(*ext - 'a')] = order--;
1709 }
1710
1711 inited = TRUE;
1712}
1713
dcd709e0 1714/* Add the implicit extensions. */
dfe92496
NC
1715
1716static void
1717riscv_parse_add_implicit_subsets (riscv_parse_subset_t *rps)
1718{
1719 riscv_subset_t *subset = NULL;
1720
1721 /* Add the zicsr and zifencei only when the i's version less than 2.1. */
1722 if ((riscv_lookup_subset (rps->subset_list, "i", &subset))
1723 && (subset->major_version < 2
1724 || (subset->major_version == 2
1725 && subset->minor_version < 1)))
1726 {
1727 riscv_parse_add_subset (rps, "zicsr",
1728 RISCV_UNKNOWN_VERSION,
1729 RISCV_UNKNOWN_VERSION, TRUE);
1730 riscv_parse_add_subset (rps, "zifencei",
1731 RISCV_UNKNOWN_VERSION,
1732 RISCV_UNKNOWN_VERSION, TRUE);
1733 }
1734
1735 if ((riscv_lookup_subset (rps->subset_list, "q", &subset)))
1736 {
1737 riscv_parse_add_subset (rps, "d",
1738 RISCV_UNKNOWN_VERSION,
1739 RISCV_UNKNOWN_VERSION, TRUE);
1740 riscv_parse_add_subset (rps, "f",
1741 RISCV_UNKNOWN_VERSION,
1742 RISCV_UNKNOWN_VERSION, TRUE);
1743 riscv_parse_add_subset (rps, "zicsr",
1744 RISCV_UNKNOWN_VERSION,
1745 RISCV_UNKNOWN_VERSION, TRUE);
1746 }
1747 else if ((riscv_lookup_subset (rps->subset_list, "d", &subset)))
1748 {
1749 riscv_parse_add_subset (rps, "f",
1750 RISCV_UNKNOWN_VERSION,
1751 RISCV_UNKNOWN_VERSION, TRUE);
1752 riscv_parse_add_subset (rps, "zicsr",
1753 RISCV_UNKNOWN_VERSION,
1754 RISCV_UNKNOWN_VERSION, TRUE);
1755 }
1756 else if ((riscv_lookup_subset (rps->subset_list, "f", &subset)))
1757 riscv_parse_add_subset (rps, "zicsr",
1758 RISCV_UNKNOWN_VERSION,
1759 RISCV_UNKNOWN_VERSION, TRUE);
00d4d1b0
NC
1760
1761 if ((riscv_lookup_subset (rps->subset_list, "g", &subset)))
1762 {
1763 riscv_parse_add_subset (rps, "zicsr",
1764 RISCV_UNKNOWN_VERSION,
1765 RISCV_UNKNOWN_VERSION, TRUE);
1766 riscv_parse_add_subset (rps, "zifencei",
1767 RISCV_UNKNOWN_VERSION,
1768 RISCV_UNKNOWN_VERSION, TRUE);
1769 }
dfe92496
NC
1770}
1771
dcd709e0 1772/* Function for parsing ISA string.
1080bf78
JW
1773
1774 Return Value:
1775 Return TRUE on success.
1776
1777 Arguments:
d541518b 1778 `rps`: Hooks and status for parsing extensions.
dcd709e0 1779 `arch`: Full ISA string. */
1080bf78
JW
1780
1781bfd_boolean
1782riscv_parse_subset (riscv_parse_subset_t *rps,
1783 const char *arch)
1784{
dfe92496 1785 riscv_subset_t *subset = NULL;
e8d4709e 1786 const char *p;
effc14f5 1787 size_t i;
7ef19aa6 1788 bfd_boolean no_conflict = TRUE;
1080bf78 1789
e8d4709e
NC
1790 for (p = arch; *p != '\0'; p++)
1791 {
1792 if (ISUPPER (*p))
1793 {
1794 rps->error_handler
1795 (_("-march=%s: ISA string cannot contain uppercase letters"),
1796 arch);
1797 return FALSE;
1798 }
1799 }
1800
1801 p = arch;
1080bf78
JW
1802 if (strncmp (p, "rv32", 4) == 0)
1803 {
1804 *rps->xlen = 32;
1805 p += 4;
1806 }
1807 else if (strncmp (p, "rv64", 4) == 0)
1808 {
1809 *rps->xlen = 64;
1810 p += 4;
1811 }
1812 else
1813 {
dcd709e0
NC
1814 /* ISA string shouldn't be NULL or empty here. However,
1815 it might be empty only when we failed to merge the ISA
72bd6912
KC
1816 string in the riscv_merge_attributes. We have already
1817 issued the correct error message in another side, so do
dcd709e0 1818 not issue this error when the ISA string is empty. */
72bd6912
KC
1819 if (strlen (arch))
1820 rps->error_handler (
1821 _("-march=%s: ISA string must begin with rv32 or rv64"),
1822 arch);
1080bf78
JW
1823 return FALSE;
1824 }
1825
dfe92496
NC
1826 /* Init the riscv_ext_order array to compare the order of extensions
1827 quickly. */
1828 riscv_init_ext_order ();
1829
1080bf78
JW
1830 /* Parsing standard extension. */
1831 p = riscv_parse_std_ext (rps, arch, p);
1832
1833 if (p == NULL)
1834 return FALSE;
1835
403d1bd9 1836 /* Parse the different classes of extensions in the specified order. */
d541518b
NC
1837 for (i = 0; i < ARRAY_SIZE (parse_config); ++i)
1838 {
1839 p = riscv_parse_prefixed_ext (rps, arch, p, &parse_config[i]);
1080bf78 1840
d541518b
NC
1841 if (p == NULL)
1842 return FALSE;
1843 }
1080bf78
JW
1844
1845 if (*p != '\0')
1846 {
8f595e9b 1847 rps->error_handler (_("-march=%s: unexpected ISA string at end: %s"),
1080bf78
JW
1848 arch, p);
1849 return FALSE;
1850 }
1851
dfe92496
NC
1852 /* Finally add implicit extensions according to the current
1853 extensions. */
1854 riscv_parse_add_implicit_subsets (rps);
1855
d541518b 1856 /* Check the conflicts. */
dfe92496
NC
1857 if (riscv_lookup_subset (rps->subset_list, "e", &subset)
1858 && riscv_lookup_subset (rps->subset_list, "f", &subset))
1080bf78 1859 {
8f595e9b
NC
1860 rps->error_handler
1861 (_("-march=%s: rv32e does not support the `f' extension"),
1862 arch);
7ef19aa6 1863 no_conflict = FALSE;
1080bf78 1864 }
dfe92496
NC
1865 if (riscv_lookup_subset (rps->subset_list, "q", &subset)
1866 && *rps->xlen < 64)
d541518b
NC
1867 {
1868 rps->error_handler
1869 (_("-march=%s: rv32 does not support the `q' extension"),
1870 arch);
7ef19aa6 1871 no_conflict = FALSE;
d541518b 1872 }
7ef19aa6 1873 return no_conflict;
1080bf78 1874}
2dc8dd17
JW
1875
1876/* Return the number of digits for the input. */
1877
8f595e9b 1878size_t
2dc8dd17
JW
1879riscv_estimate_digit (unsigned num)
1880{
1881 size_t digit = 0;
1882 if (num == 0)
1883 return 1;
1884
1885 for (digit = 0; num ; num /= 10)
1886 digit++;
1887
1888 return digit;
1889}
1890
1891/* Auxiliary function to estimate string length of subset list. */
1892
1893static size_t
1894riscv_estimate_arch_strlen1 (const riscv_subset_t *subset)
1895{
1896 if (subset == NULL)
1897 return 6; /* For rv32/rv64/rv128 and string terminator. */
1898
1899 return riscv_estimate_arch_strlen1 (subset->next)
1900 + strlen (subset->name)
1901 + riscv_estimate_digit (subset->major_version)
dcd709e0 1902 + 1 /* For version seperator 'p'. */
2dc8dd17
JW
1903 + riscv_estimate_digit (subset->minor_version)
1904 + 1 /* For underscore. */;
1905}
1906
1907/* Estimate the string length of this subset list. */
1908
1909static size_t
1910riscv_estimate_arch_strlen (const riscv_subset_list_t *subset_list)
1911{
1912 return riscv_estimate_arch_strlen1 (subset_list->head);
1913}
1914
1915/* Auxiliary function to convert subset info to string. */
1916
1917static void
1918riscv_arch_str1 (riscv_subset_t *subset,
1919 char *attr_str, char *buf, size_t bufsz)
1920{
1921 const char *underline = "_";
729a5353 1922 riscv_subset_t *subset_t = subset;
2dc8dd17 1923
729a5353 1924 if (subset_t == NULL)
2dc8dd17
JW
1925 return;
1926
dcd709e0 1927 /* No underline between rvXX and i/e. */
729a5353
NC
1928 if ((strcasecmp (subset_t->name, "i") == 0)
1929 || (strcasecmp (subset_t->name, "e") == 0))
2dc8dd17
JW
1930 underline = "";
1931
1932 snprintf (buf, bufsz, "%s%s%dp%d",
1933 underline,
729a5353
NC
1934 subset_t->name,
1935 subset_t->major_version,
1936 subset_t->minor_version);
2dc8dd17
JW
1937
1938 strncat (attr_str, buf, bufsz);
1939
729a5353
NC
1940 /* Skip 'i' extension after 'e', or skip extensions which
1941 versions are unknown. */
1942 while (subset_t->next
1943 && ((strcmp (subset_t->name, "e") == 0
1944 && strcmp (subset_t->next->name, "i") == 0)
1945 || subset_t->next->major_version == RISCV_UNKNOWN_VERSION
1946 || subset_t->next->minor_version == RISCV_UNKNOWN_VERSION))
1947 subset_t = subset_t->next;
1948
1949 riscv_arch_str1 (subset_t->next, attr_str, buf, bufsz);
2dc8dd17
JW
1950}
1951
dcd709e0 1952/* Convert subset information into string with explicit versions. */
2dc8dd17
JW
1953
1954char *
1955riscv_arch_str (unsigned xlen, const riscv_subset_list_t *subset)
1956{
1957 size_t arch_str_len = riscv_estimate_arch_strlen (subset);
1958 char *attr_str = xmalloc (arch_str_len);
1959 char *buf = xmalloc (arch_str_len);
1960
1961 snprintf (attr_str, arch_str_len, "rv%u", xlen);
1962
1963 riscv_arch_str1 (subset->head, attr_str, buf, arch_str_len);
1964 free (buf);
1965
1966 return attr_str;
1967}
This page took 0.36675 seconds and 4 git commands to generate.