]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blame - bfd/elfxx-riscv.c
Remove streq_hash in favor of htab_eq_string
[thirdparty/binutils-gdb.git] / bfd / elfxx-riscv.c
CommitLineData
e23eba97 1/* RISC-V-specific support for ELF.
250d07de 2 Copyright (C) 2011-2021 Free Software Foundation, Inc.
e23eba97
NC
3
4 Contributed by Andrew Waterman (andrew@sifive.com).
5 Based on TILE-Gx and MIPS targets.
6
7 This file is part of BFD, the Binary File Descriptor library.
8
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 3 of the License, or
12 (at your option) any later version.
13
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
18
19 You should have received a copy of the GNU General Public License
20 along with this program; see the file COPYING3. If not,
21 see <http://www.gnu.org/licenses/>. */
22
23#include "sysdep.h"
24#include "bfd.h"
25#include "libbfd.h"
26#include "elf-bfd.h"
27#include "elf/riscv.h"
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 */
0a1b45a2 52 false, /* pc_relative */
e23eba97
NC
53 0, /* bitpos */
54 complain_overflow_dont, /* complain_on_overflow */
55 bfd_elf_generic_reloc, /* special_function */
56 "R_RISCV_NONE", /* name */
0a1b45a2 57 false, /* partial_inplace */
e23eba97
NC
58 0, /* src_mask */
59 0, /* dst_mask */
0a1b45a2 60 false), /* pcrel_offset */
e23eba97
NC
61
62 /* 32 bit relocation. */
63 HOWTO (R_RISCV_32, /* type */
64 0, /* rightshift */
65 2, /* size */
66 32, /* bitsize */
0a1b45a2 67 false, /* pc_relative */
e23eba97
NC
68 0, /* bitpos */
69 complain_overflow_dont, /* complain_on_overflow */
70 bfd_elf_generic_reloc, /* special_function */
71 "R_RISCV_32", /* name */
0a1b45a2 72 false, /* partial_inplace */
e23eba97 73 0, /* src_mask */
b1b11e92 74 0xffffffff, /* dst_mask */
0a1b45a2 75 false), /* pcrel_offset */
e23eba97
NC
76
77 /* 64 bit relocation. */
78 HOWTO (R_RISCV_64, /* type */
79 0, /* rightshift */
80 4, /* size */
81 64, /* bitsize */
0a1b45a2 82 false, /* pc_relative */
e23eba97
NC
83 0, /* bitpos */
84 complain_overflow_dont, /* complain_on_overflow */
85 bfd_elf_generic_reloc, /* special_function */
86 "R_RISCV_64", /* name */
0a1b45a2 87 false, /* partial_inplace */
e23eba97
NC
88 0, /* src_mask */
89 MINUS_ONE, /* dst_mask */
0a1b45a2 90 false), /* pcrel_offset */
e23eba97
NC
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 */
0a1b45a2 97 false, /* pc_relative */
e23eba97
NC
98 0, /* bitpos */
99 complain_overflow_dont, /* complain_on_overflow */
100 bfd_elf_generic_reloc, /* special_function */
101 "R_RISCV_RELATIVE", /* name */
0a1b45a2 102 false, /* partial_inplace */
e23eba97 103 0, /* src_mask */
b1b11e92 104 0xffffffff, /* dst_mask */
0a1b45a2 105 false), /* pcrel_offset */
e23eba97
NC
106
107 HOWTO (R_RISCV_COPY, /* type */
108 0, /* rightshift */
109 0, /* this one is variable size */
110 0, /* bitsize */
0a1b45a2 111 false, /* pc_relative */
e23eba97
NC
112 0, /* bitpos */
113 complain_overflow_bitfield, /* complain_on_overflow */
114 bfd_elf_generic_reloc, /* special_function */
115 "R_RISCV_COPY", /* name */
0a1b45a2 116 false, /* partial_inplace */
07d6d2b8
AM
117 0, /* src_mask */
118 0, /* dst_mask */
0a1b45a2 119 false), /* pcrel_offset */
e23eba97
NC
120
121 HOWTO (R_RISCV_JUMP_SLOT, /* type */
122 0, /* rightshift */
123 4, /* size */
124 64, /* bitsize */
0a1b45a2 125 false, /* pc_relative */
e23eba97
NC
126 0, /* bitpos */
127 complain_overflow_bitfield, /* complain_on_overflow */
128 bfd_elf_generic_reloc, /* special_function */
129 "R_RISCV_JUMP_SLOT", /* name */
0a1b45a2 130 false, /* partial_inplace */
07d6d2b8
AM
131 0, /* src_mask */
132 0, /* dst_mask */
0a1b45a2 133 false), /* pcrel_offset */
e23eba97
NC
134
135 /* Dynamic TLS relocations. */
136 HOWTO (R_RISCV_TLS_DTPMOD32, /* type */
137 0, /* rightshift */
b1b11e92 138 2, /* size */
e23eba97 139 32, /* bitsize */
0a1b45a2 140 false, /* pc_relative */
e23eba97
NC
141 0, /* bitpos */
142 complain_overflow_dont, /* complain_on_overflow */
07d6d2b8 143 bfd_elf_generic_reloc, /* special_function */
e23eba97 144 "R_RISCV_TLS_DTPMOD32", /* name */
0a1b45a2 145 false, /* partial_inplace */
1d65abb5 146 0, /* src_mask */
b1b11e92 147 0xffffffff, /* dst_mask */
0a1b45a2 148 false), /* pcrel_offset */
e23eba97
NC
149
150 HOWTO (R_RISCV_TLS_DTPMOD64, /* type */
151 0, /* rightshift */
152 4, /* size */
153 64, /* bitsize */
0a1b45a2 154 false, /* pc_relative */
e23eba97
NC
155 0, /* bitpos */
156 complain_overflow_dont, /* complain_on_overflow */
07d6d2b8 157 bfd_elf_generic_reloc, /* special_function */
e23eba97 158 "R_RISCV_TLS_DTPMOD64", /* name */
0a1b45a2 159 false, /* partial_inplace */
1d65abb5 160 0, /* src_mask */
e23eba97 161 MINUS_ONE, /* dst_mask */
0a1b45a2 162 false), /* pcrel_offset */
e23eba97
NC
163
164 HOWTO (R_RISCV_TLS_DTPREL32, /* type */
165 0, /* rightshift */
b1b11e92 166 2, /* size */
e23eba97 167 32, /* bitsize */
0a1b45a2 168 false, /* pc_relative */
e23eba97
NC
169 0, /* bitpos */
170 complain_overflow_dont, /* complain_on_overflow */
07d6d2b8 171 bfd_elf_generic_reloc, /* special_function */
e23eba97 172 "R_RISCV_TLS_DTPREL32", /* name */
0a1b45a2 173 true, /* partial_inplace */
1d65abb5 174 0, /* src_mask */
b1b11e92 175 0xffffffff, /* dst_mask */
0a1b45a2 176 false), /* pcrel_offset */
e23eba97
NC
177
178 HOWTO (R_RISCV_TLS_DTPREL64, /* type */
179 0, /* rightshift */
180 4, /* size */
181 64, /* bitsize */
0a1b45a2 182 false, /* pc_relative */
e23eba97
NC
183 0, /* bitpos */
184 complain_overflow_dont, /* complain_on_overflow */
07d6d2b8 185 bfd_elf_generic_reloc, /* special_function */
e23eba97 186 "R_RISCV_TLS_DTPREL64", /* name */
0a1b45a2 187 true, /* partial_inplace */
1d65abb5 188 0, /* src_mask */
e23eba97 189 MINUS_ONE, /* dst_mask */
0a1b45a2 190 false), /* pcrel_offset */
e23eba97
NC
191
192 HOWTO (R_RISCV_TLS_TPREL32, /* type */
193 0, /* rightshift */
194 2, /* size */
195 32, /* bitsize */
0a1b45a2 196 false, /* pc_relative */
e23eba97
NC
197 0, /* bitpos */
198 complain_overflow_dont, /* complain_on_overflow */
07d6d2b8 199 bfd_elf_generic_reloc, /* special_function */
e23eba97 200 "R_RISCV_TLS_TPREL32", /* name */
0a1b45a2 201 false, /* partial_inplace */
1d65abb5 202 0, /* src_mask */
b1b11e92 203 0xffffffff, /* dst_mask */
0a1b45a2 204 false), /* pcrel_offset */
e23eba97
NC
205
206 HOWTO (R_RISCV_TLS_TPREL64, /* type */
207 0, /* rightshift */
208 4, /* size */
209 64, /* bitsize */
0a1b45a2 210 false, /* pc_relative */
e23eba97
NC
211 0, /* bitpos */
212 complain_overflow_dont, /* complain_on_overflow */
07d6d2b8 213 bfd_elf_generic_reloc, /* special_function */
e23eba97 214 "R_RISCV_TLS_TPREL64", /* name */
0a1b45a2 215 false, /* partial_inplace */
1d65abb5 216 0, /* src_mask */
e23eba97 217 MINUS_ONE, /* dst_mask */
0a1b45a2 218 false), /* pcrel_offset */
e23eba97
NC
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 */
0a1b45a2 231 true, /* pc_relative */
e23eba97
NC
232 0, /* bitpos */
233 complain_overflow_signed, /* complain_on_overflow */
234 bfd_elf_generic_reloc, /* special_function */
235 "R_RISCV_BRANCH", /* name */
0a1b45a2 236 false, /* partial_inplace */
e23eba97 237 0, /* src_mask */
5a9f5403 238 ENCODE_BTYPE_IMM (-1U), /* dst_mask */
0a1b45a2 239 true), /* pcrel_offset */
e23eba97
NC
240
241 /* 20-bit PC-relative jump offset. */
242 HOWTO (R_RISCV_JAL, /* type */
243 0, /* rightshift */
244 2, /* size */
245 32, /* bitsize */
0a1b45a2 246 true, /* pc_relative */
e23eba97
NC
247 0, /* bitpos */
248 complain_overflow_dont, /* complain_on_overflow */
e23eba97
NC
249 bfd_elf_generic_reloc, /* special_function */
250 "R_RISCV_JAL", /* name */
0a1b45a2 251 false, /* partial_inplace */
e23eba97 252 0, /* src_mask */
5a9f5403 253 ENCODE_JTYPE_IMM (-1U), /* dst_mask */
0a1b45a2 254 true), /* pcrel_offset */
e23eba97
NC
255
256 /* 32-bit PC-relative function call (AUIPC/JALR). */
257 HOWTO (R_RISCV_CALL, /* type */
258 0, /* rightshift */
b1b11e92 259 4, /* size */
e23eba97 260 64, /* bitsize */
0a1b45a2 261 true, /* pc_relative */
e23eba97
NC
262 0, /* bitpos */
263 complain_overflow_dont, /* complain_on_overflow */
264 bfd_elf_generic_reloc, /* special_function */
265 "R_RISCV_CALL", /* name */
0a1b45a2 266 false, /* partial_inplace */
e23eba97
NC
267 0, /* src_mask */
268 ENCODE_UTYPE_IMM (-1U) | ((bfd_vma) ENCODE_ITYPE_IMM (-1U) << 32),
269 /* dst_mask */
0a1b45a2 270 true), /* pcrel_offset */
e23eba97 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 276 64, /* bitsize */
0a1b45a2 277 true, /* pc_relative */
e23eba97
NC
278 0, /* bitpos */
279 complain_overflow_dont, /* complain_on_overflow */
280 bfd_elf_generic_reloc, /* special_function */
281 "R_RISCV_CALL_PLT", /* name */
0a1b45a2 282 false, /* partial_inplace */
e23eba97
NC
283 0, /* src_mask */
284 ENCODE_UTYPE_IMM (-1U) | ((bfd_vma) ENCODE_ITYPE_IMM (-1U) << 32),
285 /* dst_mask */
0a1b45a2 286 true), /* pcrel_offset */
e23eba97
NC
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 */
0a1b45a2 293 true, /* pc_relative */
e23eba97
NC
294 0, /* bitpos */
295 complain_overflow_dont, /* complain_on_overflow */
296 bfd_elf_generic_reloc, /* special_function */
297 "R_RISCV_GOT_HI20", /* name */
0a1b45a2 298 false, /* partial_inplace */
e23eba97
NC
299 0, /* src_mask */
300 ENCODE_UTYPE_IMM (-1U), /* dst_mask */
0a1b45a2 301 false), /* pcrel_offset */
e23eba97
NC
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 */
0a1b45a2 308 true, /* pc_relative */
e23eba97
NC
309 0, /* bitpos */
310 complain_overflow_dont, /* complain_on_overflow */
311 bfd_elf_generic_reloc, /* special_function */
312 "R_RISCV_TLS_GOT_HI20", /* name */
0a1b45a2 313 false, /* partial_inplace */
e23eba97
NC
314 0, /* src_mask */
315 ENCODE_UTYPE_IMM (-1U), /* dst_mask */
0a1b45a2 316 false), /* pcrel_offset */
e23eba97
NC
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 */
0a1b45a2 323 true, /* pc_relative */
e23eba97
NC
324 0, /* bitpos */
325 complain_overflow_dont, /* complain_on_overflow */
326 bfd_elf_generic_reloc, /* special_function */
327 "R_RISCV_TLS_GD_HI20", /* name */
0a1b45a2 328 false, /* partial_inplace */
e23eba97
NC
329 0, /* src_mask */
330 ENCODE_UTYPE_IMM (-1U), /* dst_mask */
0a1b45a2 331 false), /* pcrel_offset */
e23eba97
NC
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 */
0a1b45a2 338 true, /* pc_relative */
e23eba97
NC
339 0, /* bitpos */
340 complain_overflow_dont, /* complain_on_overflow */
341 bfd_elf_generic_reloc, /* special_function */
342 "R_RISCV_PCREL_HI20", /* name */
0a1b45a2 343 false, /* partial_inplace */
e23eba97
NC
344 0, /* src_mask */
345 ENCODE_UTYPE_IMM (-1U), /* dst_mask */
0a1b45a2 346 true), /* pcrel_offset */
e23eba97
NC
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 */
0a1b45a2 353 false, /* pc_relative */
e23eba97
NC
354 0, /* bitpos */
355 complain_overflow_dont, /* complain_on_overflow */
356 bfd_elf_generic_reloc, /* special_function */
357 "R_RISCV_PCREL_LO12_I", /* name */
0a1b45a2 358 false, /* partial_inplace */
e23eba97
NC
359 0, /* src_mask */
360 ENCODE_ITYPE_IMM (-1U), /* dst_mask */
0a1b45a2 361 false), /* pcrel_offset */
e23eba97
NC
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 */
0a1b45a2 368 false, /* pc_relative */
e23eba97
NC
369 0, /* bitpos */
370 complain_overflow_dont, /* complain_on_overflow */
371 bfd_elf_generic_reloc, /* special_function */
372 "R_RISCV_PCREL_LO12_S", /* name */
0a1b45a2 373 false, /* partial_inplace */
e23eba97
NC
374 0, /* src_mask */
375 ENCODE_STYPE_IMM (-1U), /* dst_mask */
0a1b45a2 376 false), /* pcrel_offset */
e23eba97
NC
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 */
0a1b45a2 383 false, /* pc_relative */
e23eba97
NC
384 0, /* bitpos */
385 complain_overflow_dont, /* complain_on_overflow */
386 bfd_elf_generic_reloc, /* special_function */
387 "R_RISCV_HI20", /* name */
0a1b45a2 388 false, /* partial_inplace */
e23eba97
NC
389 0, /* src_mask */
390 ENCODE_UTYPE_IMM (-1U), /* dst_mask */
0a1b45a2 391 false), /* pcrel_offset */
e23eba97
NC
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 */
0a1b45a2 398 false, /* pc_relative */
e23eba97
NC
399 0, /* bitpos */
400 complain_overflow_dont, /* complain_on_overflow */
401 bfd_elf_generic_reloc, /* special_function */
402 "R_RISCV_LO12_I", /* name */
0a1b45a2 403 false, /* partial_inplace */
e23eba97
NC
404 0, /* src_mask */
405 ENCODE_ITYPE_IMM (-1U), /* dst_mask */
0a1b45a2 406 false), /* pcrel_offset */
e23eba97
NC
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 */
0a1b45a2 413 false, /* pc_relative */
e23eba97
NC
414 0, /* bitpos */
415 complain_overflow_dont, /* complain_on_overflow */
416 bfd_elf_generic_reloc, /* special_function */
417 "R_RISCV_LO12_S", /* name */
0a1b45a2 418 false, /* partial_inplace */
e23eba97
NC
419 0, /* src_mask */
420 ENCODE_STYPE_IMM (-1U), /* dst_mask */
0a1b45a2 421 false), /* pcrel_offset */
e23eba97
NC
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 */
0a1b45a2 428 false, /* pc_relative */
e23eba97
NC
429 0, /* bitpos */
430 complain_overflow_signed, /* complain_on_overflow */
431 bfd_elf_generic_reloc, /* special_function */
432 "R_RISCV_TPREL_HI20", /* name */
0a1b45a2 433 true, /* partial_inplace */
e23eba97
NC
434 0, /* src_mask */
435 ENCODE_UTYPE_IMM (-1U), /* dst_mask */
0a1b45a2 436 false), /* pcrel_offset */
e23eba97
NC
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 */
0a1b45a2 443 false, /* pc_relative */
e23eba97
NC
444 0, /* bitpos */
445 complain_overflow_signed, /* complain_on_overflow */
446 bfd_elf_generic_reloc, /* special_function */
447 "R_RISCV_TPREL_LO12_I", /* name */
0a1b45a2 448 false, /* partial_inplace */
e23eba97
NC
449 0, /* src_mask */
450 ENCODE_ITYPE_IMM (-1U), /* dst_mask */
0a1b45a2 451 false), /* pcrel_offset */
e23eba97
NC
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 */
0a1b45a2 458 false, /* pc_relative */
e23eba97
NC
459 0, /* bitpos */
460 complain_overflow_signed, /* complain_on_overflow */
461 bfd_elf_generic_reloc, /* special_function */
462 "R_RISCV_TPREL_LO12_S", /* name */
0a1b45a2 463 false, /* partial_inplace */
e23eba97
NC
464 0, /* src_mask */
465 ENCODE_STYPE_IMM (-1U), /* dst_mask */
0a1b45a2 466 false), /* pcrel_offset */
e23eba97 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 */
0a1b45a2 473 false, /* pc_relative */
e23eba97
NC
474 0, /* bitpos */
475 complain_overflow_dont, /* complain_on_overflow */
476 bfd_elf_generic_reloc, /* special_function */
477 "R_RISCV_TPREL_ADD", /* name */
0a1b45a2 478 false, /* partial_inplace */
e23eba97
NC
479 0, /* src_mask */
480 0, /* dst_mask */
0a1b45a2 481 false), /* pcrel_offset */
e23eba97
NC
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 */
0a1b45a2 488 false, /* pc_relative */
e23eba97
NC
489 0, /* bitpos */
490 complain_overflow_dont, /* complain_on_overflow */
57593436 491 riscv_elf_add_sub_reloc, /* special_function */
e23eba97 492 "R_RISCV_ADD8", /* name */
0a1b45a2 493 false, /* partial_inplace */
e23eba97 494 0, /* src_mask */
b1b11e92 495 0xff, /* dst_mask */
0a1b45a2 496 false), /* pcrel_offset */
e23eba97
NC
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 */
0a1b45a2 503 false, /* pc_relative */
e23eba97
NC
504 0, /* bitpos */
505 complain_overflow_dont, /* complain_on_overflow */
57593436 506 riscv_elf_add_sub_reloc, /* special_function */
e23eba97 507 "R_RISCV_ADD16", /* name */
0a1b45a2 508 false, /* partial_inplace */
e23eba97 509 0, /* src_mask */
b1b11e92 510 0xffff, /* dst_mask */
0a1b45a2 511 false), /* pcrel_offset */
e23eba97
NC
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 */
0a1b45a2 518 false, /* pc_relative */
e23eba97
NC
519 0, /* bitpos */
520 complain_overflow_dont, /* complain_on_overflow */
57593436 521 riscv_elf_add_sub_reloc, /* special_function */
e23eba97 522 "R_RISCV_ADD32", /* name */
0a1b45a2 523 false, /* partial_inplace */
e23eba97 524 0, /* src_mask */
b1b11e92 525 0xffffffff, /* dst_mask */
0a1b45a2 526 false), /* pcrel_offset */
e23eba97
NC
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 */
0a1b45a2 533 false, /* pc_relative */
e23eba97
NC
534 0, /* bitpos */
535 complain_overflow_dont, /* complain_on_overflow */
57593436 536 riscv_elf_add_sub_reloc, /* special_function */
e23eba97 537 "R_RISCV_ADD64", /* name */
0a1b45a2 538 false, /* partial_inplace */
e23eba97
NC
539 0, /* src_mask */
540 MINUS_ONE, /* dst_mask */
0a1b45a2 541 false), /* pcrel_offset */
e23eba97
NC
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 */
0a1b45a2 548 false, /* pc_relative */
e23eba97
NC
549 0, /* bitpos */
550 complain_overflow_dont, /* complain_on_overflow */
57593436 551 riscv_elf_add_sub_reloc, /* special_function */
e23eba97 552 "R_RISCV_SUB8", /* name */
0a1b45a2 553 false, /* partial_inplace */
e23eba97 554 0, /* src_mask */
b1b11e92 555 0xff, /* dst_mask */
0a1b45a2 556 false), /* pcrel_offset */
e23eba97
NC
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 */
0a1b45a2 563 false, /* pc_relative */
e23eba97
NC
564 0, /* bitpos */
565 complain_overflow_dont, /* complain_on_overflow */
57593436 566 riscv_elf_add_sub_reloc, /* special_function */
e23eba97 567 "R_RISCV_SUB16", /* name */
0a1b45a2 568 false, /* partial_inplace */
e23eba97 569 0, /* src_mask */
b1b11e92 570 0xffff, /* dst_mask */
0a1b45a2 571 false), /* pcrel_offset */
e23eba97
NC
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 */
0a1b45a2 578 false, /* pc_relative */
e23eba97
NC
579 0, /* bitpos */
580 complain_overflow_dont, /* complain_on_overflow */
57593436 581 riscv_elf_add_sub_reloc, /* special_function */
e23eba97 582 "R_RISCV_SUB32", /* name */
0a1b45a2 583 false, /* partial_inplace */
e23eba97 584 0, /* src_mask */
b1b11e92 585 0xffffffff, /* dst_mask */
0a1b45a2 586 false), /* pcrel_offset */
e23eba97
NC
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 */
0a1b45a2 593 false, /* pc_relative */
e23eba97
NC
594 0, /* bitpos */
595 complain_overflow_dont, /* complain_on_overflow */
57593436 596 riscv_elf_add_sub_reloc, /* special_function */
e23eba97 597 "R_RISCV_SUB64", /* name */
0a1b45a2 598 false, /* partial_inplace */
e23eba97
NC
599 0, /* src_mask */
600 MINUS_ONE, /* dst_mask */
0a1b45a2 601 false), /* pcrel_offset */
e23eba97
NC
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 */
0a1b45a2 608 false, /* pc_relative */
e23eba97
NC
609 0, /* bitpos */
610 complain_overflow_dont, /* complain_on_overflow */
611 NULL, /* special_function */
612 "R_RISCV_GNU_VTINHERIT", /* name */
0a1b45a2 613 false, /* partial_inplace */
e23eba97
NC
614 0, /* src_mask */
615 0, /* dst_mask */
0a1b45a2 616 false), /* pcrel_offset */
e23eba97
NC
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 */
0a1b45a2 623 false, /* pc_relative */
e23eba97
NC
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 */
0a1b45a2 628 false, /* partial_inplace */
e23eba97
NC
629 0, /* src_mask */
630 0, /* dst_mask */
0a1b45a2 631 false), /* pcrel_offset */
e23eba97
NC
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 639 0, /* bitsize */
0a1b45a2 640 false, /* pc_relative */
e23eba97
NC
641 0, /* bitpos */
642 complain_overflow_dont, /* complain_on_overflow */
643 bfd_elf_generic_reloc, /* special_function */
644 "R_RISCV_ALIGN", /* name */
0a1b45a2 645 false, /* partial_inplace */
e23eba97
NC
646 0, /* src_mask */
647 0, /* dst_mask */
0a1b45a2 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 */
0a1b45a2 655 true, /* pc_relative */
e23eba97
NC
656 0, /* bitpos */
657 complain_overflow_signed, /* complain_on_overflow */
658 bfd_elf_generic_reloc, /* special_function */
659 "R_RISCV_RVC_BRANCH", /* name */
0a1b45a2 660 false, /* partial_inplace */
e23eba97 661 0, /* src_mask */
5a9f5403 662 ENCODE_CBTYPE_IMM (-1U), /* dst_mask */
0a1b45a2 663 true), /* pcrel_offset */
e23eba97
NC
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 */
0a1b45a2 670 true, /* pc_relative */
e23eba97
NC
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 */
0a1b45a2 675 false, /* partial_inplace */
e23eba97 676 0, /* src_mask */
5a9f5403 677 ENCODE_CJTYPE_IMM (-1U), /* dst_mask */
0a1b45a2 678 true), /* pcrel_offset */
e23eba97
NC
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 */
0a1b45a2 685 false, /* pc_relative */
e23eba97
NC
686 0, /* bitpos */
687 complain_overflow_dont, /* complain_on_overflow */
688 bfd_elf_generic_reloc, /* special_function */
689 "R_RISCV_RVC_LUI", /* name */
0a1b45a2 690 false, /* partial_inplace */
e23eba97 691 0, /* src_mask */
5a9f5403 692 ENCODE_CITYPE_IMM (-1U), /* dst_mask */
0a1b45a2 693 false), /* pcrel_offset */
e23eba97 694
1d65abb5 695 /* GP-relative load. */
e23eba97
NC
696 HOWTO (R_RISCV_GPREL_I, /* type */
697 0, /* rightshift */
698 2, /* size */
699 32, /* bitsize */
0a1b45a2 700 false, /* pc_relative */
e23eba97
NC
701 0, /* bitpos */
702 complain_overflow_dont, /* complain_on_overflow */
703 bfd_elf_generic_reloc, /* special_function */
704 "R_RISCV_GPREL_I", /* name */
0a1b45a2 705 false, /* partial_inplace */
e23eba97
NC
706 0, /* src_mask */
707 ENCODE_ITYPE_IMM (-1U), /* dst_mask */
0a1b45a2 708 false), /* pcrel_offset */
e23eba97 709
1d65abb5 710 /* GP-relative store. */
e23eba97
NC
711 HOWTO (R_RISCV_GPREL_S, /* type */
712 0, /* rightshift */
713 2, /* size */
714 32, /* bitsize */
0a1b45a2 715 false, /* pc_relative */
e23eba97
NC
716 0, /* bitpos */
717 complain_overflow_dont, /* complain_on_overflow */
718 bfd_elf_generic_reloc, /* special_function */
719 "R_RISCV_GPREL_S", /* name */
0a1b45a2 720 false, /* partial_inplace */
e23eba97
NC
721 0, /* src_mask */
722 ENCODE_STYPE_IMM (-1U), /* dst_mask */
0a1b45a2 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 */
0a1b45a2 730 false, /* pc_relative */
45f76423
AW
731 0, /* bitpos */
732 complain_overflow_signed, /* complain_on_overflow */
733 bfd_elf_generic_reloc, /* special_function */
734 "R_RISCV_TPREL_I", /* name */
0a1b45a2 735 false, /* partial_inplace */
45f76423
AW
736 0, /* src_mask */
737 ENCODE_ITYPE_IMM (-1U), /* dst_mask */
0a1b45a2 738 false), /* pcrel_offset */
45f76423
AW
739
740 /* TP-relative TLS LE store. */
741 HOWTO (R_RISCV_TPREL_S, /* type */
742 0, /* rightshift */
743 2, /* size */
744 32, /* bitsize */
0a1b45a2 745 false, /* pc_relative */
45f76423
AW
746 0, /* bitpos */
747 complain_overflow_signed, /* complain_on_overflow */
748 bfd_elf_generic_reloc, /* special_function */
749 "R_RISCV_TPREL_S", /* name */
0a1b45a2 750 false, /* partial_inplace */
45f76423
AW
751 0, /* src_mask */
752 ENCODE_STYPE_IMM (-1U), /* dst_mask */
0a1b45a2 753 false), /* pcrel_offset */
45f76423
AW
754
755 /* The paired relocation may be relaxed. */
756 HOWTO (R_RISCV_RELAX, /* type */
757 0, /* rightshift */
758 3, /* size */
759 0, /* bitsize */
0a1b45a2 760 false, /* pc_relative */
45f76423
AW
761 0, /* bitpos */
762 complain_overflow_dont, /* complain_on_overflow */
763 bfd_elf_generic_reloc, /* special_function */
764 "R_RISCV_RELAX", /* name */
0a1b45a2 765 false, /* partial_inplace */
45f76423
AW
766 0, /* src_mask */
767 0, /* dst_mask */
0a1b45a2 768 false), /* pcrel_offset */
45f76423
AW
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 */
0a1b45a2 775 false, /* pc_relative */
45f76423
AW
776 0, /* bitpos */
777 complain_overflow_dont, /* complain_on_overflow */
57593436 778 riscv_elf_add_sub_reloc, /* special_function */
45f76423 779 "R_RISCV_SUB6", /* name */
0a1b45a2 780 false, /* partial_inplace */
45f76423
AW
781 0, /* src_mask */
782 0x3f, /* dst_mask */
0a1b45a2 783 false), /* pcrel_offset */
45f76423
AW
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 */
0a1b45a2 790 false, /* pc_relative */
45f76423
AW
791 0, /* bitpos */
792 complain_overflow_dont, /* complain_on_overflow */
793 bfd_elf_generic_reloc, /* special_function */
794 "R_RISCV_SET6", /* name */
0a1b45a2 795 false, /* partial_inplace */
45f76423
AW
796 0, /* src_mask */
797 0x3f, /* dst_mask */
0a1b45a2 798 false), /* pcrel_offset */
45f76423
AW
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 */
0a1b45a2 805 false, /* pc_relative */
45f76423
AW
806 0, /* bitpos */
807 complain_overflow_dont, /* complain_on_overflow */
808 bfd_elf_generic_reloc, /* special_function */
809 "R_RISCV_SET8", /* name */
0a1b45a2 810 false, /* partial_inplace */
45f76423 811 0, /* src_mask */
b1b11e92 812 0xff, /* dst_mask */
0a1b45a2 813 false), /* pcrel_offset */
45f76423
AW
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 */
0a1b45a2 820 false, /* pc_relative */
45f76423
AW
821 0, /* bitpos */
822 complain_overflow_dont, /* complain_on_overflow */
823 bfd_elf_generic_reloc, /* special_function */
824 "R_RISCV_SET16", /* name */
0a1b45a2 825 false, /* partial_inplace */
45f76423 826 0, /* src_mask */
b1b11e92 827 0xffff, /* dst_mask */
0a1b45a2 828 false), /* pcrel_offset */
45f76423
AW
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 */
0a1b45a2 835 false, /* pc_relative */
45f76423
AW
836 0, /* bitpos */
837 complain_overflow_dont, /* complain_on_overflow */
838 bfd_elf_generic_reloc, /* special_function */
839 "R_RISCV_SET32", /* name */
0a1b45a2 840 false, /* partial_inplace */
45f76423 841 0, /* src_mask */
b1b11e92 842 0xffffffff, /* dst_mask */
0a1b45a2 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 */
0a1b45a2 850 true, /* pc_relative */
a6cbf936
KLC
851 0, /* bitpos */
852 complain_overflow_dont, /* complain_on_overflow */
853 bfd_elf_generic_reloc, /* special_function */
854 "R_RISCV_32_PCREL", /* name */
0a1b45a2 855 false, /* partial_inplace */
02dd9d25
NC
856 0, /* src_mask */
857 0xffffffff, /* dst_mask */
0a1b45a2 858 false), /* pcrel_offset */
02dd9d25
NC
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 */
0a1b45a2 865 false, /* pc_relative */
02dd9d25
NC
866 0, /* bitpos */
867 complain_overflow_dont, /* complain_on_overflow */
868 bfd_elf_generic_reloc, /* special_function */
869 "R_RISCV_IRELATIVE", /* name */
0a1b45a2 870 false, /* partial_inplace */
a6cbf936 871 0, /* src_mask */
b1b11e92 872 0xffffffff, /* dst_mask */
0a1b45a2 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
e601909a
NC
1029/* Lists of prefixed class extensions that binutils should know about.
1030 Whether or not a particular entry is in these lists will dictate if
1031 gas/ld will accept its presence in the architecture string.
1032
1033 Please add the extensions to the lists in lower case. However, keep
1034 these subsets in alphabetical order in these tables is recommended,
1035 although there is no impact on the current implementation. */
1036
1037static const char * const riscv_std_z_ext_strtab[] =
1038{
1039 "zba", "zbb", "zbc", "zicsr", "zifencei", "zihintpause", NULL
1040};
1041
1042static const char * const riscv_std_s_ext_strtab[] =
1043{
1044 NULL
1045};
1046
1047static const char * const riscv_std_h_ext_strtab[] =
1048{
1049 NULL
1050};
1051
1052static const char * const riscv_std_zxm_ext_strtab[] =
1053{
1054 NULL
1055};
1056
1057/* ISA extension prefixed name class. Must define them in parsing order. */
1058enum riscv_prefix_ext_class
1059{
1060 RV_ISA_CLASS_Z = 1,
1061 RV_ISA_CLASS_S,
1062 RV_ISA_CLASS_H,
1063 RV_ISA_CLASS_ZXM,
1064 RV_ISA_CLASS_X,
1065 RV_ISA_CLASS_UNKNOWN
1066};
1067
1068/* Record the strings of the prefixed extensions, and their corresponding
1069 classes. The more letters of the prefix string, the more forward it must
1070 be defined. Otherwise, the riscv_get_prefix_class will map it to the
1071 wrong classes. */
1072struct riscv_parse_prefix_config
1073{
1074 /* Class of the extension. */
1075 enum riscv_prefix_ext_class class;
1076
1077 /* Prefix string for error printing and internal parser usage. */
1078 const char *prefix;
1079};
1080static const struct riscv_parse_prefix_config parse_config[] =
1081{
1082 {RV_ISA_CLASS_ZXM, "zxm"},
1083 {RV_ISA_CLASS_Z, "z"},
1084 {RV_ISA_CLASS_S, "s"},
1085 {RV_ISA_CLASS_H, "h"},
1086 {RV_ISA_CLASS_X, "x"},
1087 {RV_ISA_CLASS_UNKNOWN, NULL}
1088};
1089
1090/* Get the prefixed name class for the extensions, the class also
1091 means the order of the prefixed extensions. */
1092
1093static enum riscv_prefix_ext_class
1094riscv_get_prefix_class (const char *arch)
1095{
1096 int i = 0;
1097 while (parse_config[i].class != RV_ISA_CLASS_UNKNOWN)
1098 {
1099 if (strncmp (arch, parse_config[i].prefix,
1100 strlen (parse_config[i].prefix)) == 0)
1101 return parse_config[i].class;
1102 i++;
1103 }
1104 return RV_ISA_CLASS_UNKNOWN;
1105}
1106
1107/* Check KNOWN_EXTS to see if the EXT is supported. */
1108
1109static bool
1110riscv_known_prefixed_ext (const char *ext,
1111 const char *const *known_exts)
1112{
1113 size_t i;
1114 for (i = 0; known_exts[i]; ++i)
1115 if (strcmp (ext, known_exts[i]) == 0)
1116 return true;
1117 return false;
1118}
7ef19aa6 1119
e601909a
NC
1120/* Check whether the prefixed extension is valid or not. Return
1121 true if valid, otehrwise return false. */
1122
1123static bool
1124riscv_valid_prefixed_ext (const char *ext)
1125{
1126 enum riscv_prefix_ext_class class = riscv_get_prefix_class (ext);
1127 switch (class)
1128 {
1129 case RV_ISA_CLASS_Z:
1130 return riscv_known_prefixed_ext (ext, riscv_std_z_ext_strtab);
1131 case RV_ISA_CLASS_ZXM:
1132 return riscv_known_prefixed_ext (ext, riscv_std_zxm_ext_strtab);
1133 case RV_ISA_CLASS_S:
1134 return riscv_known_prefixed_ext (ext, riscv_std_s_ext_strtab);
1135 case RV_ISA_CLASS_H:
1136 return riscv_known_prefixed_ext (ext, riscv_std_h_ext_strtab);
1137 case RV_ISA_CLASS_X:
1138 /* Only the single x is invalid. */
1139 if (strcmp (ext, "x") != 0)
1140 return true;
1141 default:
1142 break;
1143 }
1144 return false;
1145}
1146
1147/* Array is used to compare the orders of standard extensions quickly. */
dfe92496
NC
1148static int riscv_ext_order[26] = {0};
1149
e601909a
NC
1150/* Init the riscv_ext_order array. */
1151
1152static void
1153riscv_init_ext_order (void)
1154{
1155 static bool inited = false;
1156 const char *std_base_exts = "eig";
1157 const char *std_remain_exts = riscv_supported_std_ext ();
1158 const char *ext;
1159 int order;
1160
1161 if (inited)
1162 return;
1163
1164 /* The orders of all standard extensions are positive. */
1165 order = 1;
1166
1167 /* Init the standard base extensions first. */
1168 for (ext = std_base_exts; *ext; ext++)
1169 riscv_ext_order[(*ext - 'a')] = order++;
1170
1171 /* Init the standard remaining extensions. */
1172 for (ext = std_remain_exts; *ext; ext++)
1173 riscv_ext_order[(*ext - 'a')] = order++;
1174
1175 /* Some of the prefixed keyword are not single letter, so we set
1176 their prefixed orders in the riscv_compare_subsets directly,
1177 not through the riscv_ext_order. */
1178
1179 inited = true;
1180}
1181
dfe92496
NC
1182/* Similar to the strcmp. It returns an integer less than, equal to,
1183 or greater than zero if `subset2` is found, respectively, to be less
e601909a
NC
1184 than, to match, or be greater than `subset1`.
1185
1186 The order values,
1187 Zero: Preserved keywords.
1188 Positive number: Standard extensions.
1189 Negative number: Prefixed keywords. */
dfe92496 1190
4c0e540e 1191int
dfe92496 1192riscv_compare_subsets (const char *subset1, const char *subset2)
7ef19aa6 1193{
dfe92496
NC
1194 int order1 = riscv_ext_order[(*subset1 - 'a')];
1195 int order2 = riscv_ext_order[(*subset2 - 'a')];
7ef19aa6 1196
dfe92496
NC
1197 /* Compare the standard extension first. */
1198 if (order1 > 0 && order2 > 0)
1199 return order1 - order2;
7ef19aa6 1200
e601909a
NC
1201 /* Set the prefixed orders to negative numbers. */
1202 enum riscv_prefix_ext_class class1 = riscv_get_prefix_class (subset1);
1203 enum riscv_prefix_ext_class class2 = riscv_get_prefix_class (subset2);
1204
1205 if (class1 != RV_ISA_CLASS_UNKNOWN)
1206 order1 = - (int) class1;
1207 if (class2 != RV_ISA_CLASS_UNKNOWN)
1208 order2 = - (int) class2;
1209
1210 if (order1 == order2)
dfe92496
NC
1211 {
1212 /* Compare the standard addition z extensions. */
e601909a 1213 if (class1 == RV_ISA_CLASS_Z)
dfe92496
NC
1214 {
1215 order1 = riscv_ext_order[(*++subset1 - 'a')];
1216 order2 = riscv_ext_order[(*++subset2 - 'a')];
1217 if (order1 != order2)
1218 return order1 - order2;
1219 }
1220 return strcasecmp (++subset1, ++subset2);
1221 }
1222
1223 return order2 - order1;
1224}
1225
1226/* Find subset in the list. Return TRUE and set `current` to the subset
1227 if it is found. Otherwise, return FALSE and set `current` to the place
1228 where we should insert the subset. However, return FALSE with the NULL
1229 `current` means we should insert the subset at the head of subset list,
1230 if needed. */
1231
0a1b45a2 1232bool
dfe92496
NC
1233riscv_lookup_subset (const riscv_subset_list_t *subset_list,
1234 const char *subset,
1235 riscv_subset_t **current)
1236{
1237 riscv_subset_t *s, *pre_s = NULL;
1238
1239 for (s = subset_list->head;
1240 s != NULL;
1241 pre_s = s, s = s->next)
1242 {
1243 int cmp = riscv_compare_subsets (s->name, subset);
1244 if (cmp == 0)
1245 {
1246 *current = s;
0a1b45a2 1247 return true;
dfe92496
NC
1248 }
1249 else if (cmp > 0)
1250 break;
1251 }
1252 *current = pre_s;
0a1b45a2 1253 return false;
7ef19aa6
NC
1254}
1255
dcd709e0 1256/* Add extension from ISA string to the last of the subset list. */
7ef19aa6
NC
1257
1258void
1259riscv_add_subset (riscv_subset_list_t *subset_list,
1260 const char *subset,
1261 int major,
1262 int minor)
1263{
1264 riscv_subset_t *s = xmalloc (sizeof *s);
1265
1266 if (subset_list->head == NULL)
1267 subset_list->head = s;
1268
1269 s->name = xstrdup (subset);
1270 s->major_version = major;
1271 s->minor_version = minor;
1272 s->next = NULL;
1273
1274 if (subset_list->tail != NULL)
1275 subset_list->tail->next = s;
1276 subset_list->tail = s;
1277}
1278
dfe92496
NC
1279/* Add the implicit extension to the subset list. Search the
1280 list first, and then find the right place to add. */
1281
1282static void
1283riscv_add_implicit_subset (riscv_subset_list_t *subset_list,
1284 const char *subset,
1285 int major,
1286 int minor)
1287{
1288 riscv_subset_t *current, *new;
1289
1290 if (riscv_lookup_subset (subset_list, subset, &current))
1291 return;
1292
1293 new = xmalloc (sizeof *new);
1294 new->name = xstrdup (subset);
1295 new->major_version = major;
1296 new->minor_version = minor;
1297 new->next = NULL;
1298
1299 if (current != NULL)
1300 {
1301 new->next = current->next;
1302 current->next = new;
1303 }
1304 else
1305 {
1306 new->next = subset_list->head;
1307 subset_list->head = new;
1308 }
1309}
1310
dcd709e0
NC
1311/* We have to add all extensions from ISA string first, and then start to
1312 add their implicit extensions. The extensions from ISA string must be
dfe92496
NC
1313 set in order, so we can add them to the last of the subset list
1314 directly, without searching.
1315
1316 Find the default versions for the extension before adding them to
7ef19aa6
NC
1317 the subset list, if their versions are RISCV_UNKNOWN_VERSION.
1318 Afterwards, report errors if we can not find their default versions. */
1319
1320static void
1321riscv_parse_add_subset (riscv_parse_subset_t *rps,
1322 const char *subset,
1323 int major,
dfe92496 1324 int minor,
0a1b45a2 1325 bool implicit)
7ef19aa6
NC
1326{
1327 int major_version = major;
1328 int minor_version = minor;
1329
1330 if ((major_version == RISCV_UNKNOWN_VERSION
1331 || minor_version == RISCV_UNKNOWN_VERSION)
1332 && rps->get_default_version != NULL)
1333 rps->get_default_version (subset, &major_version, &minor_version);
1334
f0bae255
NC
1335 /* We don't care the versions of the implicit extensions. */
1336 if (!implicit
dfe92496
NC
1337 && (major_version == RISCV_UNKNOWN_VERSION
1338 || minor_version == RISCV_UNKNOWN_VERSION))
7ef19aa6
NC
1339 {
1340 if (subset[0] == 'x')
1341 rps->error_handler
1342 (_("x ISA extension `%s' must be set with the versions"),
1343 subset);
1344 else
1345 rps->error_handler
1346 (_("cannot find default versions of the ISA extension `%s'"),
1347 subset);
1348 return;
1349 }
1350
dfe92496
NC
1351 if (!implicit)
1352 riscv_add_subset (rps->subset_list, subset,
1353 major_version, minor_version);
729a5353 1354 else
dfe92496
NC
1355 riscv_add_implicit_subset (rps->subset_list, subset,
1356 major_version, minor_version);
7ef19aa6
NC
1357}
1358
1359/* Release subset list. */
1360
1361void
1362riscv_release_subset_list (riscv_subset_list_t *subset_list)
1363{
1364 while (subset_list->head != NULL)
1365 {
1366 riscv_subset_t *next = subset_list->head->next;
1367 free ((void *)subset_list->head->name);
1368 free (subset_list->head);
1369 subset_list->head = next;
1370 }
1371
1372 subset_list->tail = NULL;
1373}
1374
d541518b 1375/* Parsing extension version.
1080bf78
JW
1376
1377 Return Value:
1378 Points to the end of version
1379
1380 Arguments:
d541518b 1381 `rps`: Hooks and status for parsing extensions.
dcd709e0 1382 `march`: Full ISA string.
1080bf78 1383 `p`: Curent parsing position.
7ef19aa6
NC
1384 `major_version`: Parsed major version.
1385 `minor_version`: Parsed minor version.
1386 `std_ext_p`: True if parsing standard extension. */
1080bf78
JW
1387
1388static const char *
1389riscv_parsing_subset_version (riscv_parse_subset_t *rps,
1390 const char *march,
1391 const char *p,
7ef19aa6
NC
1392 int *major_version,
1393 int *minor_version,
0a1b45a2 1394 bool std_ext_p)
1080bf78 1395{
0a1b45a2 1396 bool major_p = true;
7ef19aa6 1397 int version = 0;
1080bf78
JW
1398 char np;
1399
8f595e9b
NC
1400 *major_version = 0;
1401 *minor_version = 0;
1402 for (; *p; ++p)
1080bf78
JW
1403 {
1404 if (*p == 'p')
1405 {
1406 np = *(p + 1);
1407
1408 if (!ISDIGIT (np))
1409 {
1410 /* Might be beginning of `p` extension. */
1411 if (std_ext_p)
1412 {
1413 *major_version = version;
1414 *minor_version = 0;
1415 return p;
1416 }
1417 else
1418 {
8f595e9b 1419 rps->error_handler
d541518b 1420 (_("-march=%s: expect number after `%dp'"),
8f595e9b 1421 march, version);
1080bf78
JW
1422 return NULL;
1423 }
1424 }
1425
8f595e9b 1426 *major_version = version;
0a1b45a2 1427 major_p = false;
1080bf78
JW
1428 version = 0;
1429 }
1430 else if (ISDIGIT (*p))
1431 version = (version * 10) + (*p - '0');
1432 else
1433 break;
1434 }
1435
1436 if (major_p)
8f595e9b 1437 *major_version = version;
1080bf78 1438 else
8f595e9b 1439 *minor_version = version;
1080bf78 1440
7ef19aa6
NC
1441 /* We can not find any version in string. */
1442 if (*major_version == 0 && *minor_version == 0)
1443 {
1444 *major_version = RISCV_UNKNOWN_VERSION;
1445 *minor_version = RISCV_UNKNOWN_VERSION;
1446 }
1447
1080bf78
JW
1448 return p;
1449}
1450
1451/* Return string which contain all supported standard extensions in
1452 canonical order. */
1453
1454const char *
1455riscv_supported_std_ext (void)
1456{
1457 return "mafdqlcbjtpvn";
1458}
1459
1460/* Parsing function for standard extensions.
1461
1462 Return Value:
1463 Points to the end of extensions.
1464
1465 Arguments:
d541518b 1466 `rps`: Hooks and status for parsing extensions.
dcd709e0 1467 `march`: Full ISA string.
1080bf78
JW
1468 `p`: Curent parsing position. */
1469
1470static const char *
1471riscv_parse_std_ext (riscv_parse_subset_t *rps,
8f595e9b
NC
1472 const char *march,
1473 const char *p)
1080bf78
JW
1474{
1475 const char *all_std_exts = riscv_supported_std_ext ();
1476 const char *std_exts = all_std_exts;
7ef19aa6
NC
1477 int major_version;
1478 int minor_version;
d541518b 1479 char subset[2] = {0, 0};
1080bf78
JW
1480
1481 /* First letter must start with i, e or g. */
1482 switch (*p)
1483 {
1484 case 'i':
d541518b 1485 p = riscv_parsing_subset_version (rps, march, ++p,
8f595e9b 1486 &major_version,
0a1b45a2 1487 &minor_version, true);
7ef19aa6
NC
1488 riscv_parse_add_subset (rps, "i",
1489 major_version,
0a1b45a2 1490 minor_version, false);
1080bf78
JW
1491 break;
1492
1493 case 'e':
d541518b 1494 p = riscv_parsing_subset_version (rps, march, ++p,
8f595e9b 1495 &major_version,
0a1b45a2 1496 &minor_version, true);
7ef19aa6
NC
1497 riscv_parse_add_subset (rps, "e",
1498 major_version,
0a1b45a2 1499 minor_version, false);
1080bf78
JW
1500 if (*rps->xlen > 32)
1501 {
8f595e9b
NC
1502 rps->error_handler
1503 (_("-march=%s: rv%de is not a valid base ISA"),
1504 march, *rps->xlen);
1080bf78
JW
1505 return NULL;
1506 }
1080bf78
JW
1507 break;
1508
1509 case 'g':
d541518b 1510 p = riscv_parsing_subset_version (rps, march, ++p,
8f595e9b 1511 &major_version,
0a1b45a2 1512 &minor_version, true);
f0bae255 1513 /* Expand g to imafd. */
7ef19aa6 1514 riscv_parse_add_subset (rps, "i",
f5b10973
NC
1515 RISCV_UNKNOWN_VERSION,
1516 RISCV_UNKNOWN_VERSION, false);
1080bf78
JW
1517 for ( ; *std_exts != 'q'; std_exts++)
1518 {
d541518b 1519 subset[0] = *std_exts;
7ef19aa6
NC
1520 riscv_parse_add_subset (rps, subset,
1521 RISCV_UNKNOWN_VERSION,
0a1b45a2 1522 RISCV_UNKNOWN_VERSION, false);
1080bf78 1523 }
f0bae255
NC
1524 /* Add g as an implicit extension. */
1525 riscv_parse_add_subset (rps, "g",
1526 RISCV_UNKNOWN_VERSION,
1527 RISCV_UNKNOWN_VERSION, true);
1080bf78
JW
1528 break;
1529
1530 default:
8f595e9b 1531 rps->error_handler
d541518b
NC
1532 (_("-march=%s: first ISA extension must be `e', `i' or `g'"),
1533 march);
1080bf78
JW
1534 return NULL;
1535 }
1536
8f595e9b 1537 while (p != NULL && *p != '\0')
1080bf78 1538 {
e601909a
NC
1539 /* Stop when we parsed the known prefix class. */
1540 enum riscv_prefix_ext_class class = riscv_get_prefix_class (p);
1541 if (class != RV_ISA_CLASS_UNKNOWN)
1080bf78
JW
1542 break;
1543
1544 if (*p == '_')
1545 {
1546 p++;
1547 continue;
1548 }
1549
1080bf78 1550 /* Checking canonical order. */
d541518b
NC
1551 char std_ext = *p;
1552 while (*std_exts && std_ext != *std_exts)
1553 std_exts++;
1080bf78
JW
1554
1555 if (std_ext != *std_exts)
1556 {
e601909a 1557 if (riscv_ext_order[(std_ext - 'a')] == 0)
8f595e9b 1558 rps->error_handler
e601909a
NC
1559 (_("-march=%s: unknown standard and prefixed ISA "
1560 "extension `%s'"), march, p);
1080bf78 1561 else
8f595e9b 1562 rps->error_handler
d541518b
NC
1563 (_("-march=%s: standard ISA extension `%c' is not "
1564 "in canonical order"), march, std_ext);
1080bf78
JW
1565 return NULL;
1566 }
1567
1568 std_exts++;
1080bf78 1569 subset[0] = std_ext;
d541518b 1570 p = riscv_parsing_subset_version (rps, march, ++p,
8f595e9b 1571 &major_version,
0a1b45a2 1572 &minor_version, true);
7ef19aa6
NC
1573 riscv_parse_add_subset (rps, subset,
1574 major_version,
0a1b45a2 1575 minor_version, false);
1080bf78 1576 }
d541518b 1577
1080bf78
JW
1578 return p;
1579}
1580
d541518b
NC
1581/* Parsing function for prefixed extensions.
1582
1583 Return Value:
1584 Points to the end of extension.
1585
1586 Arguments:
1587 `rps`: Hooks and status for parsing extensions.
dcd709e0 1588 `march`: Full ISA string.
e3839c10 1589 `p`: Curent parsing position. */
1080bf78
JW
1590
1591static const char *
403d1bd9
JW
1592riscv_parse_prefixed_ext (riscv_parse_subset_t *rps,
1593 const char *march,
e601909a 1594 const char *p)
1080bf78 1595{
7ef19aa6
NC
1596 int major_version;
1597 int minor_version;
403d1bd9 1598 const char *last_name;
e601909a 1599 enum riscv_prefix_ext_class class;
1080bf78
JW
1600
1601 while (*p)
1602 {
1603 if (*p == '_')
1604 {
1605 p++;
1606 continue;
1607 }
1608
403d1bd9 1609 class = riscv_get_prefix_class (p);
e601909a
NC
1610 if (class == RV_ISA_CLASS_UNKNOWN)
1611 {
1612 rps->error_handler
1613 (_("-march=%s: unknown prefix class for the ISA extension `%s'"),
1614 march, p);
1615 return NULL;
1616 }
1080bf78
JW
1617
1618 char *subset = xstrdup (p);
1619 char *q = subset;
1620 const char *end_of_version;
1621
1622 while (*++q != '\0' && *q != '_' && !ISDIGIT (*q))
1623 ;
1624
1625 end_of_version =
d541518b
NC
1626 riscv_parsing_subset_version (rps, march, q,
1627 &major_version,
0a1b45a2 1628 &minor_version, false);
1080bf78
JW
1629 *q = '\0';
1630
7ef19aa6
NC
1631 if (end_of_version == NULL)
1632 {
1633 free (subset);
1634 return NULL;
1635 }
1636
e601909a 1637 /* Check if the prefix extension is known.
403d1bd9 1638 For 'x', anything goes but it cannot simply be 'x'.
e3839c10
NC
1639 For other prefixed extensions, it must be known from a list
1640 and cannot simply be the prefixed name. */
403d1bd9
JW
1641
1642 /* Check that the extension name is well-formed. */
e601909a 1643 if (!riscv_valid_prefixed_ext (subset))
403d1bd9
JW
1644 {
1645 rps->error_handler
e601909a
NC
1646 (_("-march=%s: unknown prefixed ISA extension `%s'"),
1647 march, subset);
403d1bd9
JW
1648 free (subset);
1649 return NULL;
1650 }
1651
d541518b 1652 /* Check that the extension isn't duplicate. */
403d1bd9 1653 last_name = rps->subset_list->tail->name;
403d1bd9
JW
1654 if (!strcasecmp (last_name, subset))
1655 {
8f595e9b 1656 rps->error_handler
e601909a
NC
1657 (_("-march=%s: duplicate prefixed ISA extension `%s'"),
1658 march, subset);
403d1bd9
JW
1659 free (subset);
1660 return NULL;
1661 }
1662
e601909a 1663 /* Check that the extension is in expected order. */
6729e2c2 1664 if (riscv_compare_subsets (last_name, subset) > 0)
403d1bd9 1665 {
8f595e9b 1666 rps->error_handler
e601909a 1667 (_("-march=%s: prefixed ISA extension `%s' is not in expected "
d541518b 1668 "order. It must come before `%s'"),
e601909a 1669 march, subset, last_name);
403d1bd9
JW
1670 free (subset);
1671 return NULL;
1672 }
1673
7ef19aa6
NC
1674 riscv_parse_add_subset (rps, subset,
1675 major_version,
0a1b45a2 1676 minor_version, false);
1080bf78 1677 p += end_of_version - subset;
e9cf3691 1678 free (subset);
1080bf78
JW
1679
1680 if (*p != '\0' && *p != '_')
1681 {
d541518b 1682 rps->error_handler
e601909a
NC
1683 (_("-march=%s: prefixed ISA extension must separate with _"),
1684 march);
1080bf78
JW
1685 return NULL;
1686 }
1687 }
1688
1689 return p;
1690}
1691
dcd709e0 1692/* Add the implicit extensions. */
dfe92496
NC
1693
1694static void
1695riscv_parse_add_implicit_subsets (riscv_parse_subset_t *rps)
1696{
1697 riscv_subset_t *subset = NULL;
1698
f0bae255
NC
1699 if (riscv_lookup_subset (rps->subset_list, "e", &subset))
1700 riscv_parse_add_subset (rps, "i",
1701 RISCV_UNKNOWN_VERSION,
1702 RISCV_UNKNOWN_VERSION, true);
1703
dfe92496 1704 /* Add the zicsr and zifencei only when the i's version less than 2.1. */
f0bae255 1705 if (riscv_lookup_subset (rps->subset_list, "i", &subset)
dfe92496
NC
1706 && (subset->major_version < 2
1707 || (subset->major_version == 2
1708 && subset->minor_version < 1)))
1709 {
1710 riscv_parse_add_subset (rps, "zicsr",
1711 RISCV_UNKNOWN_VERSION,
0a1b45a2 1712 RISCV_UNKNOWN_VERSION, true);
dfe92496
NC
1713 riscv_parse_add_subset (rps, "zifencei",
1714 RISCV_UNKNOWN_VERSION,
0a1b45a2 1715 RISCV_UNKNOWN_VERSION, true);
dfe92496
NC
1716 }
1717
f0bae255 1718 if (riscv_lookup_subset (rps->subset_list, "q", &subset))
dfe92496
NC
1719 {
1720 riscv_parse_add_subset (rps, "d",
1721 RISCV_UNKNOWN_VERSION,
0a1b45a2 1722 RISCV_UNKNOWN_VERSION, true);
dfe92496
NC
1723 riscv_parse_add_subset (rps, "f",
1724 RISCV_UNKNOWN_VERSION,
0a1b45a2 1725 RISCV_UNKNOWN_VERSION, true);
dfe92496
NC
1726 riscv_parse_add_subset (rps, "zicsr",
1727 RISCV_UNKNOWN_VERSION,
0a1b45a2 1728 RISCV_UNKNOWN_VERSION, true);
dfe92496 1729 }
f0bae255 1730 else if (riscv_lookup_subset (rps->subset_list, "d", &subset))
dfe92496
NC
1731 {
1732 riscv_parse_add_subset (rps, "f",
1733 RISCV_UNKNOWN_VERSION,
0a1b45a2 1734 RISCV_UNKNOWN_VERSION, true);
dfe92496
NC
1735 riscv_parse_add_subset (rps, "zicsr",
1736 RISCV_UNKNOWN_VERSION,
0a1b45a2 1737 RISCV_UNKNOWN_VERSION, true);
dfe92496 1738 }
f0bae255 1739 else if (riscv_lookup_subset (rps->subset_list, "f", &subset))
dfe92496
NC
1740 riscv_parse_add_subset (rps, "zicsr",
1741 RISCV_UNKNOWN_VERSION,
0a1b45a2 1742 RISCV_UNKNOWN_VERSION, true);
00d4d1b0 1743
f0bae255 1744 if (riscv_lookup_subset (rps->subset_list, "g", &subset))
00d4d1b0
NC
1745 {
1746 riscv_parse_add_subset (rps, "zicsr",
1747 RISCV_UNKNOWN_VERSION,
0a1b45a2 1748 RISCV_UNKNOWN_VERSION, true);
00d4d1b0
NC
1749 riscv_parse_add_subset (rps, "zifencei",
1750 RISCV_UNKNOWN_VERSION,
0a1b45a2 1751 RISCV_UNKNOWN_VERSION, true);
00d4d1b0 1752 }
dfe92496
NC
1753}
1754
dcd709e0 1755/* Function for parsing ISA string.
1080bf78
JW
1756
1757 Return Value:
1758 Return TRUE on success.
1759
1760 Arguments:
d541518b 1761 `rps`: Hooks and status for parsing extensions.
dcd709e0 1762 `arch`: Full ISA string. */
1080bf78 1763
0a1b45a2 1764bool
1080bf78
JW
1765riscv_parse_subset (riscv_parse_subset_t *rps,
1766 const char *arch)
1767{
dfe92496 1768 riscv_subset_t *subset = NULL;
e8d4709e 1769 const char *p;
0a1b45a2 1770 bool no_conflict = true;
1080bf78 1771
e8d4709e
NC
1772 for (p = arch; *p != '\0'; p++)
1773 {
1774 if (ISUPPER (*p))
1775 {
1776 rps->error_handler
1777 (_("-march=%s: ISA string cannot contain uppercase letters"),
1778 arch);
0a1b45a2 1779 return false;
e8d4709e
NC
1780 }
1781 }
1782
1783 p = arch;
3f3328b8 1784 if (startswith (p, "rv32"))
1080bf78
JW
1785 {
1786 *rps->xlen = 32;
1787 p += 4;
1788 }
3f3328b8 1789 else if (startswith (p, "rv64"))
1080bf78
JW
1790 {
1791 *rps->xlen = 64;
1792 p += 4;
1793 }
1794 else
1795 {
dcd709e0
NC
1796 /* ISA string shouldn't be NULL or empty here. However,
1797 it might be empty only when we failed to merge the ISA
72bd6912
KC
1798 string in the riscv_merge_attributes. We have already
1799 issued the correct error message in another side, so do
dcd709e0 1800 not issue this error when the ISA string is empty. */
72bd6912
KC
1801 if (strlen (arch))
1802 rps->error_handler (
1803 _("-march=%s: ISA string must begin with rv32 or rv64"),
1804 arch);
0a1b45a2 1805 return false;
1080bf78
JW
1806 }
1807
dfe92496
NC
1808 /* Init the riscv_ext_order array to compare the order of extensions
1809 quickly. */
1810 riscv_init_ext_order ();
1811
1080bf78
JW
1812 /* Parsing standard extension. */
1813 p = riscv_parse_std_ext (rps, arch, p);
1814
1815 if (p == NULL)
0a1b45a2 1816 return false;
1080bf78 1817
403d1bd9 1818 /* Parse the different classes of extensions in the specified order. */
e601909a 1819 while (*p != '\0')
d541518b 1820 {
e601909a 1821 p = riscv_parse_prefixed_ext (rps, arch, p);
1080bf78 1822
d541518b 1823 if (p == NULL)
e601909a 1824 return false;
1080bf78
JW
1825 }
1826
dfe92496
NC
1827 /* Finally add implicit extensions according to the current
1828 extensions. */
1829 riscv_parse_add_implicit_subsets (rps);
1830
d541518b 1831 /* Check the conflicts. */
dfe92496
NC
1832 if (riscv_lookup_subset (rps->subset_list, "e", &subset)
1833 && riscv_lookup_subset (rps->subset_list, "f", &subset))
1080bf78 1834 {
8f595e9b
NC
1835 rps->error_handler
1836 (_("-march=%s: rv32e does not support the `f' extension"),
1837 arch);
0a1b45a2 1838 no_conflict = false;
1080bf78 1839 }
dfe92496
NC
1840 if (riscv_lookup_subset (rps->subset_list, "q", &subset)
1841 && *rps->xlen < 64)
d541518b
NC
1842 {
1843 rps->error_handler
1844 (_("-march=%s: rv32 does not support the `q' extension"),
1845 arch);
0a1b45a2 1846 no_conflict = false;
d541518b 1847 }
7ef19aa6 1848 return no_conflict;
1080bf78 1849}
2dc8dd17
JW
1850
1851/* Return the number of digits for the input. */
1852
8f595e9b 1853size_t
2dc8dd17
JW
1854riscv_estimate_digit (unsigned num)
1855{
1856 size_t digit = 0;
1857 if (num == 0)
1858 return 1;
1859
1860 for (digit = 0; num ; num /= 10)
1861 digit++;
1862
1863 return digit;
1864}
1865
1866/* Auxiliary function to estimate string length of subset list. */
1867
1868static size_t
1869riscv_estimate_arch_strlen1 (const riscv_subset_t *subset)
1870{
1871 if (subset == NULL)
1872 return 6; /* For rv32/rv64/rv128 and string terminator. */
1873
1874 return riscv_estimate_arch_strlen1 (subset->next)
1875 + strlen (subset->name)
1876 + riscv_estimate_digit (subset->major_version)
dcd709e0 1877 + 1 /* For version seperator 'p'. */
2dc8dd17
JW
1878 + riscv_estimate_digit (subset->minor_version)
1879 + 1 /* For underscore. */;
1880}
1881
1882/* Estimate the string length of this subset list. */
1883
1884static size_t
1885riscv_estimate_arch_strlen (const riscv_subset_list_t *subset_list)
1886{
1887 return riscv_estimate_arch_strlen1 (subset_list->head);
1888}
1889
1890/* Auxiliary function to convert subset info to string. */
1891
1892static void
1893riscv_arch_str1 (riscv_subset_t *subset,
1894 char *attr_str, char *buf, size_t bufsz)
1895{
1896 const char *underline = "_";
729a5353 1897 riscv_subset_t *subset_t = subset;
2dc8dd17 1898
729a5353 1899 if (subset_t == NULL)
2dc8dd17
JW
1900 return;
1901
dcd709e0 1902 /* No underline between rvXX and i/e. */
729a5353
NC
1903 if ((strcasecmp (subset_t->name, "i") == 0)
1904 || (strcasecmp (subset_t->name, "e") == 0))
2dc8dd17
JW
1905 underline = "";
1906
1907 snprintf (buf, bufsz, "%s%s%dp%d",
1908 underline,
729a5353
NC
1909 subset_t->name,
1910 subset_t->major_version,
1911 subset_t->minor_version);
2dc8dd17
JW
1912
1913 strncat (attr_str, buf, bufsz);
1914
729a5353
NC
1915 /* Skip 'i' extension after 'e', or skip extensions which
1916 versions are unknown. */
1917 while (subset_t->next
1918 && ((strcmp (subset_t->name, "e") == 0
1919 && strcmp (subset_t->next->name, "i") == 0)
1920 || subset_t->next->major_version == RISCV_UNKNOWN_VERSION
1921 || subset_t->next->minor_version == RISCV_UNKNOWN_VERSION))
1922 subset_t = subset_t->next;
1923
1924 riscv_arch_str1 (subset_t->next, attr_str, buf, bufsz);
2dc8dd17
JW
1925}
1926
dcd709e0 1927/* Convert subset information into string with explicit versions. */
2dc8dd17
JW
1928
1929char *
1930riscv_arch_str (unsigned xlen, const riscv_subset_list_t *subset)
1931{
1932 size_t arch_str_len = riscv_estimate_arch_strlen (subset);
1933 char *attr_str = xmalloc (arch_str_len);
1934 char *buf = xmalloc (arch_str_len);
1935
1936 snprintf (attr_str, arch_str_len, "rv%u", xlen);
1937
1938 riscv_arch_str1 (subset->head, attr_str, buf, arch_str_len);
1939 free (buf);
1940
1941 return attr_str;
1942}