]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blame - bfd/elfxx-riscv.c
RISC-V: Remove RV128-only fmv instructions
[thirdparty/binutils-gdb.git] / bfd / elfxx-riscv.c
CommitLineData
e23eba97 1/* RISC-V-specific support for ELF.
a2c58332 2 Copyright (C) 2011-2022 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"
e23eba97
NC
32
33#define MINUS_ONE ((bfd_vma)0 - 1)
34
57593436
KLC
35/* Special handler for ADD/SUB relocations that allows them to be filled out
36 both in the pre-linked and post-linked file. This is necessary to make
37 pre-linked debug info work, as due to linker relaxations we need to emit
38 relocations for the debug info. */
39static bfd_reloc_status_type riscv_elf_add_sub_reloc
40 (bfd *, arelent *, asymbol *, void *, asection *, bfd *, char **);
41
e23eba97
NC
42/* The relocation table used for SHT_RELA sections. */
43
44static reloc_howto_type howto_table[] =
45{
46 /* No relocation. */
47 HOWTO (R_RISCV_NONE, /* type */
48 0, /* rightshift */
49 3, /* size */
50 0, /* bitsize */
0a1b45a2 51 false, /* pc_relative */
e23eba97
NC
52 0, /* bitpos */
53 complain_overflow_dont, /* complain_on_overflow */
54 bfd_elf_generic_reloc, /* special_function */
55 "R_RISCV_NONE", /* name */
0a1b45a2 56 false, /* partial_inplace */
e23eba97
NC
57 0, /* src_mask */
58 0, /* dst_mask */
0a1b45a2 59 false), /* pcrel_offset */
e23eba97
NC
60
61 /* 32 bit relocation. */
62 HOWTO (R_RISCV_32, /* type */
63 0, /* rightshift */
64 2, /* size */
65 32, /* bitsize */
0a1b45a2 66 false, /* pc_relative */
e23eba97
NC
67 0, /* bitpos */
68 complain_overflow_dont, /* complain_on_overflow */
69 bfd_elf_generic_reloc, /* special_function */
70 "R_RISCV_32", /* name */
0a1b45a2 71 false, /* partial_inplace */
e23eba97 72 0, /* src_mask */
b1b11e92 73 0xffffffff, /* dst_mask */
0a1b45a2 74 false), /* pcrel_offset */
e23eba97
NC
75
76 /* 64 bit relocation. */
77 HOWTO (R_RISCV_64, /* type */
78 0, /* rightshift */
79 4, /* size */
80 64, /* bitsize */
0a1b45a2 81 false, /* pc_relative */
e23eba97
NC
82 0, /* bitpos */
83 complain_overflow_dont, /* complain_on_overflow */
84 bfd_elf_generic_reloc, /* special_function */
85 "R_RISCV_64", /* name */
0a1b45a2 86 false, /* partial_inplace */
e23eba97
NC
87 0, /* src_mask */
88 MINUS_ONE, /* dst_mask */
0a1b45a2 89 false), /* pcrel_offset */
e23eba97
NC
90
91 /* Relocation against a local symbol in a shared object. */
92 HOWTO (R_RISCV_RELATIVE, /* type */
93 0, /* rightshift */
94 2, /* size */
95 32, /* bitsize */
0a1b45a2 96 false, /* pc_relative */
e23eba97
NC
97 0, /* bitpos */
98 complain_overflow_dont, /* complain_on_overflow */
99 bfd_elf_generic_reloc, /* special_function */
100 "R_RISCV_RELATIVE", /* name */
0a1b45a2 101 false, /* partial_inplace */
e23eba97 102 0, /* src_mask */
b1b11e92 103 0xffffffff, /* dst_mask */
0a1b45a2 104 false), /* pcrel_offset */
e23eba97
NC
105
106 HOWTO (R_RISCV_COPY, /* type */
107 0, /* rightshift */
108 0, /* this one is variable size */
109 0, /* bitsize */
0a1b45a2 110 false, /* pc_relative */
e23eba97
NC
111 0, /* bitpos */
112 complain_overflow_bitfield, /* complain_on_overflow */
113 bfd_elf_generic_reloc, /* special_function */
114 "R_RISCV_COPY", /* name */
0a1b45a2 115 false, /* partial_inplace */
07d6d2b8
AM
116 0, /* src_mask */
117 0, /* dst_mask */
0a1b45a2 118 false), /* pcrel_offset */
e23eba97
NC
119
120 HOWTO (R_RISCV_JUMP_SLOT, /* type */
121 0, /* rightshift */
122 4, /* size */
123 64, /* bitsize */
0a1b45a2 124 false, /* pc_relative */
e23eba97
NC
125 0, /* bitpos */
126 complain_overflow_bitfield, /* complain_on_overflow */
127 bfd_elf_generic_reloc, /* special_function */
128 "R_RISCV_JUMP_SLOT", /* name */
0a1b45a2 129 false, /* partial_inplace */
07d6d2b8
AM
130 0, /* src_mask */
131 0, /* dst_mask */
0a1b45a2 132 false), /* pcrel_offset */
e23eba97
NC
133
134 /* Dynamic TLS relocations. */
135 HOWTO (R_RISCV_TLS_DTPMOD32, /* type */
136 0, /* rightshift */
b1b11e92 137 2, /* size */
e23eba97 138 32, /* bitsize */
0a1b45a2 139 false, /* pc_relative */
e23eba97
NC
140 0, /* bitpos */
141 complain_overflow_dont, /* complain_on_overflow */
07d6d2b8 142 bfd_elf_generic_reloc, /* special_function */
e23eba97 143 "R_RISCV_TLS_DTPMOD32", /* name */
0a1b45a2 144 false, /* partial_inplace */
1d65abb5 145 0, /* src_mask */
b1b11e92 146 0xffffffff, /* dst_mask */
0a1b45a2 147 false), /* pcrel_offset */
e23eba97
NC
148
149 HOWTO (R_RISCV_TLS_DTPMOD64, /* type */
150 0, /* rightshift */
151 4, /* size */
152 64, /* bitsize */
0a1b45a2 153 false, /* pc_relative */
e23eba97
NC
154 0, /* bitpos */
155 complain_overflow_dont, /* complain_on_overflow */
07d6d2b8 156 bfd_elf_generic_reloc, /* special_function */
e23eba97 157 "R_RISCV_TLS_DTPMOD64", /* name */
0a1b45a2 158 false, /* partial_inplace */
1d65abb5 159 0, /* src_mask */
e23eba97 160 MINUS_ONE, /* dst_mask */
0a1b45a2 161 false), /* pcrel_offset */
e23eba97
NC
162
163 HOWTO (R_RISCV_TLS_DTPREL32, /* type */
164 0, /* rightshift */
b1b11e92 165 2, /* size */
e23eba97 166 32, /* bitsize */
0a1b45a2 167 false, /* pc_relative */
e23eba97
NC
168 0, /* bitpos */
169 complain_overflow_dont, /* complain_on_overflow */
07d6d2b8 170 bfd_elf_generic_reloc, /* special_function */
e23eba97 171 "R_RISCV_TLS_DTPREL32", /* name */
0a1b45a2 172 true, /* partial_inplace */
1d65abb5 173 0, /* src_mask */
b1b11e92 174 0xffffffff, /* dst_mask */
0a1b45a2 175 false), /* pcrel_offset */
e23eba97
NC
176
177 HOWTO (R_RISCV_TLS_DTPREL64, /* type */
178 0, /* rightshift */
179 4, /* size */
180 64, /* bitsize */
0a1b45a2 181 false, /* pc_relative */
e23eba97
NC
182 0, /* bitpos */
183 complain_overflow_dont, /* complain_on_overflow */
07d6d2b8 184 bfd_elf_generic_reloc, /* special_function */
e23eba97 185 "R_RISCV_TLS_DTPREL64", /* name */
0a1b45a2 186 true, /* partial_inplace */
1d65abb5 187 0, /* src_mask */
e23eba97 188 MINUS_ONE, /* dst_mask */
0a1b45a2 189 false), /* pcrel_offset */
e23eba97
NC
190
191 HOWTO (R_RISCV_TLS_TPREL32, /* type */
192 0, /* rightshift */
193 2, /* size */
194 32, /* bitsize */
0a1b45a2 195 false, /* pc_relative */
e23eba97
NC
196 0, /* bitpos */
197 complain_overflow_dont, /* complain_on_overflow */
07d6d2b8 198 bfd_elf_generic_reloc, /* special_function */
e23eba97 199 "R_RISCV_TLS_TPREL32", /* name */
0a1b45a2 200 false, /* partial_inplace */
1d65abb5 201 0, /* src_mask */
b1b11e92 202 0xffffffff, /* dst_mask */
0a1b45a2 203 false), /* pcrel_offset */
e23eba97
NC
204
205 HOWTO (R_RISCV_TLS_TPREL64, /* type */
206 0, /* rightshift */
207 4, /* size */
208 64, /* bitsize */
0a1b45a2 209 false, /* pc_relative */
e23eba97
NC
210 0, /* bitpos */
211 complain_overflow_dont, /* complain_on_overflow */
07d6d2b8 212 bfd_elf_generic_reloc, /* special_function */
e23eba97 213 "R_RISCV_TLS_TPREL64", /* name */
0a1b45a2 214 false, /* partial_inplace */
1d65abb5 215 0, /* src_mask */
e23eba97 216 MINUS_ONE, /* dst_mask */
0a1b45a2 217 false), /* pcrel_offset */
e23eba97
NC
218
219 /* Reserved for future relocs that the dynamic linker must understand. */
220 EMPTY_HOWTO (12),
221 EMPTY_HOWTO (13),
222 EMPTY_HOWTO (14),
223 EMPTY_HOWTO (15),
224
225 /* 12-bit PC-relative branch offset. */
226 HOWTO (R_RISCV_BRANCH, /* type */
227 0, /* rightshift */
228 2, /* size */
229 32, /* bitsize */
0a1b45a2 230 true, /* pc_relative */
e23eba97
NC
231 0, /* bitpos */
232 complain_overflow_signed, /* complain_on_overflow */
233 bfd_elf_generic_reloc, /* special_function */
234 "R_RISCV_BRANCH", /* name */
0a1b45a2 235 false, /* partial_inplace */
e23eba97 236 0, /* src_mask */
5a9f5403 237 ENCODE_BTYPE_IMM (-1U), /* dst_mask */
0a1b45a2 238 true), /* pcrel_offset */
e23eba97
NC
239
240 /* 20-bit PC-relative jump offset. */
241 HOWTO (R_RISCV_JAL, /* type */
242 0, /* rightshift */
243 2, /* size */
244 32, /* bitsize */
0a1b45a2 245 true, /* pc_relative */
e23eba97
NC
246 0, /* bitpos */
247 complain_overflow_dont, /* complain_on_overflow */
e23eba97
NC
248 bfd_elf_generic_reloc, /* special_function */
249 "R_RISCV_JAL", /* name */
0a1b45a2 250 false, /* partial_inplace */
e23eba97 251 0, /* src_mask */
5a9f5403 252 ENCODE_JTYPE_IMM (-1U), /* dst_mask */
0a1b45a2 253 true), /* pcrel_offset */
e23eba97
NC
254
255 /* 32-bit PC-relative function call (AUIPC/JALR). */
256 HOWTO (R_RISCV_CALL, /* type */
257 0, /* rightshift */
b1b11e92 258 4, /* size */
e23eba97 259 64, /* bitsize */
0a1b45a2 260 true, /* pc_relative */
e23eba97
NC
261 0, /* bitpos */
262 complain_overflow_dont, /* complain_on_overflow */
263 bfd_elf_generic_reloc, /* special_function */
264 "R_RISCV_CALL", /* name */
0a1b45a2 265 false, /* partial_inplace */
e23eba97
NC
266 0, /* src_mask */
267 ENCODE_UTYPE_IMM (-1U) | ((bfd_vma) ENCODE_ITYPE_IMM (-1U) << 32),
268 /* dst_mask */
0a1b45a2 269 true), /* pcrel_offset */
e23eba97 270
1d65abb5 271 /* Like R_RISCV_CALL, but not locally binding. */
e23eba97
NC
272 HOWTO (R_RISCV_CALL_PLT, /* type */
273 0, /* rightshift */
b1b11e92 274 4, /* size */
e23eba97 275 64, /* bitsize */
0a1b45a2 276 true, /* pc_relative */
e23eba97
NC
277 0, /* bitpos */
278 complain_overflow_dont, /* complain_on_overflow */
279 bfd_elf_generic_reloc, /* special_function */
280 "R_RISCV_CALL_PLT", /* name */
0a1b45a2 281 false, /* partial_inplace */
e23eba97
NC
282 0, /* src_mask */
283 ENCODE_UTYPE_IMM (-1U) | ((bfd_vma) ENCODE_ITYPE_IMM (-1U) << 32),
284 /* dst_mask */
0a1b45a2 285 true), /* pcrel_offset */
e23eba97
NC
286
287 /* High 20 bits of 32-bit PC-relative GOT access. */
288 HOWTO (R_RISCV_GOT_HI20, /* type */
289 0, /* rightshift */
290 2, /* size */
291 32, /* bitsize */
0a1b45a2 292 true, /* pc_relative */
e23eba97
NC
293 0, /* bitpos */
294 complain_overflow_dont, /* complain_on_overflow */
295 bfd_elf_generic_reloc, /* special_function */
296 "R_RISCV_GOT_HI20", /* name */
0a1b45a2 297 false, /* partial_inplace */
e23eba97
NC
298 0, /* src_mask */
299 ENCODE_UTYPE_IMM (-1U), /* dst_mask */
0a1b45a2 300 false), /* pcrel_offset */
e23eba97
NC
301
302 /* High 20 bits of 32-bit PC-relative TLS IE GOT access. */
303 HOWTO (R_RISCV_TLS_GOT_HI20, /* type */
304 0, /* rightshift */
305 2, /* size */
306 32, /* bitsize */
0a1b45a2 307 true, /* pc_relative */
e23eba97
NC
308 0, /* bitpos */
309 complain_overflow_dont, /* complain_on_overflow */
310 bfd_elf_generic_reloc, /* special_function */
311 "R_RISCV_TLS_GOT_HI20", /* name */
0a1b45a2 312 false, /* partial_inplace */
e23eba97
NC
313 0, /* src_mask */
314 ENCODE_UTYPE_IMM (-1U), /* dst_mask */
0a1b45a2 315 false), /* pcrel_offset */
e23eba97
NC
316
317 /* High 20 bits of 32-bit PC-relative TLS GD GOT reference. */
318 HOWTO (R_RISCV_TLS_GD_HI20, /* type */
319 0, /* rightshift */
320 2, /* size */
321 32, /* bitsize */
0a1b45a2 322 true, /* pc_relative */
e23eba97
NC
323 0, /* bitpos */
324 complain_overflow_dont, /* complain_on_overflow */
325 bfd_elf_generic_reloc, /* special_function */
326 "R_RISCV_TLS_GD_HI20", /* name */
0a1b45a2 327 false, /* partial_inplace */
e23eba97
NC
328 0, /* src_mask */
329 ENCODE_UTYPE_IMM (-1U), /* dst_mask */
0a1b45a2 330 false), /* pcrel_offset */
e23eba97
NC
331
332 /* High 20 bits of 32-bit PC-relative reference. */
333 HOWTO (R_RISCV_PCREL_HI20, /* type */
334 0, /* rightshift */
335 2, /* size */
336 32, /* bitsize */
0a1b45a2 337 true, /* pc_relative */
e23eba97
NC
338 0, /* bitpos */
339 complain_overflow_dont, /* complain_on_overflow */
340 bfd_elf_generic_reloc, /* special_function */
341 "R_RISCV_PCREL_HI20", /* name */
0a1b45a2 342 false, /* partial_inplace */
e23eba97
NC
343 0, /* src_mask */
344 ENCODE_UTYPE_IMM (-1U), /* dst_mask */
0a1b45a2 345 true), /* pcrel_offset */
e23eba97
NC
346
347 /* Low 12 bits of a 32-bit PC-relative load or add. */
348 HOWTO (R_RISCV_PCREL_LO12_I, /* type */
349 0, /* rightshift */
350 2, /* size */
351 32, /* bitsize */
0a1b45a2 352 false, /* pc_relative */
e23eba97
NC
353 0, /* bitpos */
354 complain_overflow_dont, /* complain_on_overflow */
355 bfd_elf_generic_reloc, /* special_function */
356 "R_RISCV_PCREL_LO12_I", /* name */
0a1b45a2 357 false, /* partial_inplace */
e23eba97
NC
358 0, /* src_mask */
359 ENCODE_ITYPE_IMM (-1U), /* dst_mask */
0a1b45a2 360 false), /* pcrel_offset */
e23eba97
NC
361
362 /* Low 12 bits of a 32-bit PC-relative store. */
363 HOWTO (R_RISCV_PCREL_LO12_S, /* type */
364 0, /* rightshift */
365 2, /* size */
366 32, /* bitsize */
0a1b45a2 367 false, /* pc_relative */
e23eba97
NC
368 0, /* bitpos */
369 complain_overflow_dont, /* complain_on_overflow */
370 bfd_elf_generic_reloc, /* special_function */
371 "R_RISCV_PCREL_LO12_S", /* name */
0a1b45a2 372 false, /* partial_inplace */
e23eba97
NC
373 0, /* src_mask */
374 ENCODE_STYPE_IMM (-1U), /* dst_mask */
0a1b45a2 375 false), /* pcrel_offset */
e23eba97
NC
376
377 /* High 20 bits of 32-bit absolute address. */
378 HOWTO (R_RISCV_HI20, /* type */
379 0, /* rightshift */
380 2, /* size */
381 32, /* bitsize */
0a1b45a2 382 false, /* pc_relative */
e23eba97
NC
383 0, /* bitpos */
384 complain_overflow_dont, /* complain_on_overflow */
385 bfd_elf_generic_reloc, /* special_function */
386 "R_RISCV_HI20", /* name */
0a1b45a2 387 false, /* partial_inplace */
e23eba97
NC
388 0, /* src_mask */
389 ENCODE_UTYPE_IMM (-1U), /* dst_mask */
0a1b45a2 390 false), /* pcrel_offset */
e23eba97
NC
391
392 /* High 12 bits of 32-bit load or add. */
393 HOWTO (R_RISCV_LO12_I, /* type */
394 0, /* rightshift */
395 2, /* size */
396 32, /* bitsize */
0a1b45a2 397 false, /* pc_relative */
e23eba97
NC
398 0, /* bitpos */
399 complain_overflow_dont, /* complain_on_overflow */
400 bfd_elf_generic_reloc, /* special_function */
401 "R_RISCV_LO12_I", /* name */
0a1b45a2 402 false, /* partial_inplace */
e23eba97
NC
403 0, /* src_mask */
404 ENCODE_ITYPE_IMM (-1U), /* dst_mask */
0a1b45a2 405 false), /* pcrel_offset */
e23eba97
NC
406
407 /* High 12 bits of 32-bit store. */
408 HOWTO (R_RISCV_LO12_S, /* type */
409 0, /* rightshift */
410 2, /* size */
411 32, /* bitsize */
0a1b45a2 412 false, /* pc_relative */
e23eba97
NC
413 0, /* bitpos */
414 complain_overflow_dont, /* complain_on_overflow */
415 bfd_elf_generic_reloc, /* special_function */
416 "R_RISCV_LO12_S", /* name */
0a1b45a2 417 false, /* partial_inplace */
e23eba97
NC
418 0, /* src_mask */
419 ENCODE_STYPE_IMM (-1U), /* dst_mask */
0a1b45a2 420 false), /* pcrel_offset */
e23eba97
NC
421
422 /* High 20 bits of TLS LE thread pointer offset. */
423 HOWTO (R_RISCV_TPREL_HI20, /* type */
424 0, /* rightshift */
425 2, /* size */
426 32, /* bitsize */
0a1b45a2 427 false, /* pc_relative */
e23eba97
NC
428 0, /* bitpos */
429 complain_overflow_signed, /* complain_on_overflow */
430 bfd_elf_generic_reloc, /* special_function */
431 "R_RISCV_TPREL_HI20", /* name */
0a1b45a2 432 true, /* partial_inplace */
e23eba97
NC
433 0, /* src_mask */
434 ENCODE_UTYPE_IMM (-1U), /* dst_mask */
0a1b45a2 435 false), /* pcrel_offset */
e23eba97
NC
436
437 /* Low 12 bits of TLS LE thread pointer offset for loads and adds. */
438 HOWTO (R_RISCV_TPREL_LO12_I, /* type */
439 0, /* rightshift */
440 2, /* size */
441 32, /* bitsize */
0a1b45a2 442 false, /* pc_relative */
e23eba97
NC
443 0, /* bitpos */
444 complain_overflow_signed, /* complain_on_overflow */
445 bfd_elf_generic_reloc, /* special_function */
446 "R_RISCV_TPREL_LO12_I", /* name */
0a1b45a2 447 false, /* partial_inplace */
e23eba97
NC
448 0, /* src_mask */
449 ENCODE_ITYPE_IMM (-1U), /* dst_mask */
0a1b45a2 450 false), /* pcrel_offset */
e23eba97
NC
451
452 /* Low 12 bits of TLS LE thread pointer offset for stores. */
453 HOWTO (R_RISCV_TPREL_LO12_S, /* type */
454 0, /* rightshift */
455 2, /* size */
456 32, /* bitsize */
0a1b45a2 457 false, /* pc_relative */
e23eba97
NC
458 0, /* bitpos */
459 complain_overflow_signed, /* complain_on_overflow */
460 bfd_elf_generic_reloc, /* special_function */
461 "R_RISCV_TPREL_LO12_S", /* name */
0a1b45a2 462 false, /* partial_inplace */
e23eba97
NC
463 0, /* src_mask */
464 ENCODE_STYPE_IMM (-1U), /* dst_mask */
0a1b45a2 465 false), /* pcrel_offset */
e23eba97 466
1d65abb5 467 /* TLS LE thread pointer usage. May be relaxed. */
e23eba97
NC
468 HOWTO (R_RISCV_TPREL_ADD, /* type */
469 0, /* rightshift */
b1b11e92
AM
470 3, /* size */
471 0, /* bitsize */
0a1b45a2 472 false, /* pc_relative */
e23eba97
NC
473 0, /* bitpos */
474 complain_overflow_dont, /* complain_on_overflow */
475 bfd_elf_generic_reloc, /* special_function */
476 "R_RISCV_TPREL_ADD", /* name */
0a1b45a2 477 false, /* partial_inplace */
e23eba97
NC
478 0, /* src_mask */
479 0, /* dst_mask */
0a1b45a2 480 false), /* pcrel_offset */
e23eba97
NC
481
482 /* 8-bit in-place addition, for local label subtraction. */
483 HOWTO (R_RISCV_ADD8, /* type */
484 0, /* rightshift */
485 0, /* size */
0b14696a 486 8, /* bitsize */
0a1b45a2 487 false, /* pc_relative */
e23eba97
NC
488 0, /* bitpos */
489 complain_overflow_dont, /* complain_on_overflow */
57593436 490 riscv_elf_add_sub_reloc, /* special_function */
e23eba97 491 "R_RISCV_ADD8", /* name */
0a1b45a2 492 false, /* partial_inplace */
e23eba97 493 0, /* src_mask */
b1b11e92 494 0xff, /* dst_mask */
0a1b45a2 495 false), /* pcrel_offset */
e23eba97
NC
496
497 /* 16-bit in-place addition, for local label subtraction. */
498 HOWTO (R_RISCV_ADD16, /* type */
499 0, /* rightshift */
500 1, /* size */
501 16, /* bitsize */
0a1b45a2 502 false, /* pc_relative */
e23eba97
NC
503 0, /* bitpos */
504 complain_overflow_dont, /* complain_on_overflow */
57593436 505 riscv_elf_add_sub_reloc, /* special_function */
e23eba97 506 "R_RISCV_ADD16", /* name */
0a1b45a2 507 false, /* partial_inplace */
e23eba97 508 0, /* src_mask */
b1b11e92 509 0xffff, /* dst_mask */
0a1b45a2 510 false), /* pcrel_offset */
e23eba97
NC
511
512 /* 32-bit in-place addition, for local label subtraction. */
513 HOWTO (R_RISCV_ADD32, /* type */
514 0, /* rightshift */
515 2, /* size */
516 32, /* bitsize */
0a1b45a2 517 false, /* pc_relative */
e23eba97
NC
518 0, /* bitpos */
519 complain_overflow_dont, /* complain_on_overflow */
57593436 520 riscv_elf_add_sub_reloc, /* special_function */
e23eba97 521 "R_RISCV_ADD32", /* name */
0a1b45a2 522 false, /* partial_inplace */
e23eba97 523 0, /* src_mask */
b1b11e92 524 0xffffffff, /* dst_mask */
0a1b45a2 525 false), /* pcrel_offset */
e23eba97
NC
526
527 /* 64-bit in-place addition, for local label subtraction. */
528 HOWTO (R_RISCV_ADD64, /* type */
529 0, /* rightshift */
530 4, /* size */
531 64, /* bitsize */
0a1b45a2 532 false, /* pc_relative */
e23eba97
NC
533 0, /* bitpos */
534 complain_overflow_dont, /* complain_on_overflow */
57593436 535 riscv_elf_add_sub_reloc, /* special_function */
e23eba97 536 "R_RISCV_ADD64", /* name */
0a1b45a2 537 false, /* partial_inplace */
e23eba97
NC
538 0, /* src_mask */
539 MINUS_ONE, /* dst_mask */
0a1b45a2 540 false), /* pcrel_offset */
e23eba97
NC
541
542 /* 8-bit in-place addition, for local label subtraction. */
543 HOWTO (R_RISCV_SUB8, /* type */
544 0, /* rightshift */
545 0, /* size */
546 8, /* bitsize */
0a1b45a2 547 false, /* pc_relative */
e23eba97
NC
548 0, /* bitpos */
549 complain_overflow_dont, /* complain_on_overflow */
57593436 550 riscv_elf_add_sub_reloc, /* special_function */
e23eba97 551 "R_RISCV_SUB8", /* name */
0a1b45a2 552 false, /* partial_inplace */
e23eba97 553 0, /* src_mask */
b1b11e92 554 0xff, /* dst_mask */
0a1b45a2 555 false), /* pcrel_offset */
e23eba97
NC
556
557 /* 16-bit in-place addition, for local label subtraction. */
558 HOWTO (R_RISCV_SUB16, /* type */
559 0, /* rightshift */
560 1, /* size */
561 16, /* bitsize */
0a1b45a2 562 false, /* pc_relative */
e23eba97
NC
563 0, /* bitpos */
564 complain_overflow_dont, /* complain_on_overflow */
57593436 565 riscv_elf_add_sub_reloc, /* special_function */
e23eba97 566 "R_RISCV_SUB16", /* name */
0a1b45a2 567 false, /* partial_inplace */
e23eba97 568 0, /* src_mask */
b1b11e92 569 0xffff, /* dst_mask */
0a1b45a2 570 false), /* pcrel_offset */
e23eba97
NC
571
572 /* 32-bit in-place addition, for local label subtraction. */
573 HOWTO (R_RISCV_SUB32, /* type */
574 0, /* rightshift */
575 2, /* size */
576 32, /* bitsize */
0a1b45a2 577 false, /* pc_relative */
e23eba97
NC
578 0, /* bitpos */
579 complain_overflow_dont, /* complain_on_overflow */
57593436 580 riscv_elf_add_sub_reloc, /* special_function */
e23eba97 581 "R_RISCV_SUB32", /* name */
0a1b45a2 582 false, /* partial_inplace */
e23eba97 583 0, /* src_mask */
b1b11e92 584 0xffffffff, /* dst_mask */
0a1b45a2 585 false), /* pcrel_offset */
e23eba97
NC
586
587 /* 64-bit in-place addition, for local label subtraction. */
588 HOWTO (R_RISCV_SUB64, /* type */
589 0, /* rightshift */
590 4, /* size */
591 64, /* bitsize */
0a1b45a2 592 false, /* pc_relative */
e23eba97
NC
593 0, /* bitpos */
594 complain_overflow_dont, /* complain_on_overflow */
57593436 595 riscv_elf_add_sub_reloc, /* special_function */
e23eba97 596 "R_RISCV_SUB64", /* name */
0a1b45a2 597 false, /* partial_inplace */
e23eba97
NC
598 0, /* src_mask */
599 MINUS_ONE, /* dst_mask */
0a1b45a2 600 false), /* pcrel_offset */
e23eba97
NC
601
602 /* GNU extension to record C++ vtable hierarchy */
603 HOWTO (R_RISCV_GNU_VTINHERIT, /* type */
604 0, /* rightshift */
605 4, /* size */
606 0, /* bitsize */
0a1b45a2 607 false, /* pc_relative */
e23eba97
NC
608 0, /* bitpos */
609 complain_overflow_dont, /* complain_on_overflow */
610 NULL, /* special_function */
611 "R_RISCV_GNU_VTINHERIT", /* name */
0a1b45a2 612 false, /* partial_inplace */
e23eba97
NC
613 0, /* src_mask */
614 0, /* dst_mask */
0a1b45a2 615 false), /* pcrel_offset */
e23eba97
NC
616
617 /* GNU extension to record C++ vtable member usage */
618 HOWTO (R_RISCV_GNU_VTENTRY, /* type */
619 0, /* rightshift */
620 4, /* size */
621 0, /* bitsize */
0a1b45a2 622 false, /* pc_relative */
e23eba97
NC
623 0, /* bitpos */
624 complain_overflow_dont, /* complain_on_overflow */
625 _bfd_elf_rel_vtable_reloc_fn, /* special_function */
626 "R_RISCV_GNU_VTENTRY", /* name */
0a1b45a2 627 false, /* partial_inplace */
e23eba97
NC
628 0, /* src_mask */
629 0, /* dst_mask */
0a1b45a2 630 false), /* pcrel_offset */
e23eba97
NC
631
632 /* Indicates an alignment statement. The addend field encodes how many
633 bytes of NOPs follow the statement. The desired alignment is the
634 addend rounded up to the next power of two. */
635 HOWTO (R_RISCV_ALIGN, /* type */
636 0, /* rightshift */
b1b11e92 637 3, /* size */
e23eba97 638 0, /* bitsize */
0a1b45a2 639 false, /* pc_relative */
e23eba97
NC
640 0, /* bitpos */
641 complain_overflow_dont, /* complain_on_overflow */
642 bfd_elf_generic_reloc, /* special_function */
643 "R_RISCV_ALIGN", /* name */
0a1b45a2 644 false, /* partial_inplace */
e23eba97
NC
645 0, /* src_mask */
646 0, /* dst_mask */
0a1b45a2 647 false), /* pcrel_offset */
e23eba97
NC
648
649 /* 8-bit PC-relative branch offset. */
650 HOWTO (R_RISCV_RVC_BRANCH, /* type */
651 0, /* rightshift */
b1b11e92
AM
652 1, /* size */
653 16, /* bitsize */
0a1b45a2 654 true, /* pc_relative */
e23eba97
NC
655 0, /* bitpos */
656 complain_overflow_signed, /* complain_on_overflow */
657 bfd_elf_generic_reloc, /* special_function */
658 "R_RISCV_RVC_BRANCH", /* name */
0a1b45a2 659 false, /* partial_inplace */
e23eba97 660 0, /* src_mask */
5a9f5403 661 ENCODE_CBTYPE_IMM (-1U), /* dst_mask */
0a1b45a2 662 true), /* pcrel_offset */
e23eba97
NC
663
664 /* 11-bit PC-relative jump offset. */
665 HOWTO (R_RISCV_RVC_JUMP, /* type */
666 0, /* rightshift */
b1b11e92
AM
667 1, /* size */
668 16, /* bitsize */
0a1b45a2 669 true, /* pc_relative */
e23eba97
NC
670 0, /* bitpos */
671 complain_overflow_dont, /* complain_on_overflow */
e23eba97
NC
672 bfd_elf_generic_reloc, /* special_function */
673 "R_RISCV_RVC_JUMP", /* name */
0a1b45a2 674 false, /* partial_inplace */
e23eba97 675 0, /* src_mask */
5a9f5403 676 ENCODE_CJTYPE_IMM (-1U), /* dst_mask */
0a1b45a2 677 true), /* pcrel_offset */
e23eba97
NC
678
679 /* High 6 bits of 18-bit absolute address. */
680 HOWTO (R_RISCV_RVC_LUI, /* type */
681 0, /* rightshift */
b1b11e92
AM
682 1, /* size */
683 16, /* bitsize */
0a1b45a2 684 false, /* pc_relative */
e23eba97
NC
685 0, /* bitpos */
686 complain_overflow_dont, /* complain_on_overflow */
687 bfd_elf_generic_reloc, /* special_function */
688 "R_RISCV_RVC_LUI", /* name */
0a1b45a2 689 false, /* partial_inplace */
e23eba97 690 0, /* src_mask */
5a9f5403 691 ENCODE_CITYPE_IMM (-1U), /* dst_mask */
0a1b45a2 692 false), /* pcrel_offset */
e23eba97 693
1d65abb5 694 /* GP-relative load. */
e23eba97
NC
695 HOWTO (R_RISCV_GPREL_I, /* type */
696 0, /* rightshift */
697 2, /* size */
698 32, /* bitsize */
0a1b45a2 699 false, /* pc_relative */
e23eba97
NC
700 0, /* bitpos */
701 complain_overflow_dont, /* complain_on_overflow */
702 bfd_elf_generic_reloc, /* special_function */
703 "R_RISCV_GPREL_I", /* name */
0a1b45a2 704 false, /* partial_inplace */
e23eba97
NC
705 0, /* src_mask */
706 ENCODE_ITYPE_IMM (-1U), /* dst_mask */
0a1b45a2 707 false), /* pcrel_offset */
e23eba97 708
1d65abb5 709 /* GP-relative store. */
e23eba97
NC
710 HOWTO (R_RISCV_GPREL_S, /* type */
711 0, /* rightshift */
712 2, /* size */
713 32, /* bitsize */
0a1b45a2 714 false, /* pc_relative */
e23eba97
NC
715 0, /* bitpos */
716 complain_overflow_dont, /* complain_on_overflow */
717 bfd_elf_generic_reloc, /* special_function */
718 "R_RISCV_GPREL_S", /* name */
0a1b45a2 719 false, /* partial_inplace */
e23eba97
NC
720 0, /* src_mask */
721 ENCODE_STYPE_IMM (-1U), /* dst_mask */
0a1b45a2 722 false), /* pcrel_offset */
45f76423
AW
723
724 /* TP-relative TLS LE load. */
725 HOWTO (R_RISCV_TPREL_I, /* type */
726 0, /* rightshift */
727 2, /* size */
728 32, /* bitsize */
0a1b45a2 729 false, /* pc_relative */
45f76423
AW
730 0, /* bitpos */
731 complain_overflow_signed, /* complain_on_overflow */
732 bfd_elf_generic_reloc, /* special_function */
733 "R_RISCV_TPREL_I", /* name */
0a1b45a2 734 false, /* partial_inplace */
45f76423
AW
735 0, /* src_mask */
736 ENCODE_ITYPE_IMM (-1U), /* dst_mask */
0a1b45a2 737 false), /* pcrel_offset */
45f76423
AW
738
739 /* TP-relative TLS LE store. */
740 HOWTO (R_RISCV_TPREL_S, /* type */
741 0, /* rightshift */
742 2, /* size */
743 32, /* bitsize */
0a1b45a2 744 false, /* pc_relative */
45f76423
AW
745 0, /* bitpos */
746 complain_overflow_signed, /* complain_on_overflow */
747 bfd_elf_generic_reloc, /* special_function */
748 "R_RISCV_TPREL_S", /* name */
0a1b45a2 749 false, /* partial_inplace */
45f76423
AW
750 0, /* src_mask */
751 ENCODE_STYPE_IMM (-1U), /* dst_mask */
0a1b45a2 752 false), /* pcrel_offset */
45f76423
AW
753
754 /* The paired relocation may be relaxed. */
755 HOWTO (R_RISCV_RELAX, /* type */
756 0, /* rightshift */
757 3, /* size */
758 0, /* bitsize */
0a1b45a2 759 false, /* pc_relative */
45f76423
AW
760 0, /* bitpos */
761 complain_overflow_dont, /* complain_on_overflow */
762 bfd_elf_generic_reloc, /* special_function */
763 "R_RISCV_RELAX", /* name */
0a1b45a2 764 false, /* partial_inplace */
45f76423
AW
765 0, /* src_mask */
766 0, /* dst_mask */
0a1b45a2 767 false), /* pcrel_offset */
45f76423
AW
768
769 /* 6-bit in-place addition, for local label subtraction. */
770 HOWTO (R_RISCV_SUB6, /* type */
771 0, /* rightshift */
772 0, /* size */
773 8, /* bitsize */
0a1b45a2 774 false, /* pc_relative */
45f76423
AW
775 0, /* bitpos */
776 complain_overflow_dont, /* complain_on_overflow */
57593436 777 riscv_elf_add_sub_reloc, /* special_function */
45f76423 778 "R_RISCV_SUB6", /* name */
0a1b45a2 779 false, /* partial_inplace */
45f76423
AW
780 0, /* src_mask */
781 0x3f, /* dst_mask */
0a1b45a2 782 false), /* pcrel_offset */
45f76423
AW
783
784 /* 6-bit in-place setting, for local label subtraction. */
785 HOWTO (R_RISCV_SET6, /* type */
786 0, /* rightshift */
787 0, /* size */
788 8, /* bitsize */
0a1b45a2 789 false, /* pc_relative */
45f76423
AW
790 0, /* bitpos */
791 complain_overflow_dont, /* complain_on_overflow */
792 bfd_elf_generic_reloc, /* special_function */
793 "R_RISCV_SET6", /* name */
0a1b45a2 794 false, /* partial_inplace */
45f76423
AW
795 0, /* src_mask */
796 0x3f, /* dst_mask */
0a1b45a2 797 false), /* pcrel_offset */
45f76423
AW
798
799 /* 8-bit in-place setting, for local label subtraction. */
800 HOWTO (R_RISCV_SET8, /* type */
801 0, /* rightshift */
802 0, /* size */
803 8, /* bitsize */
0a1b45a2 804 false, /* pc_relative */
45f76423
AW
805 0, /* bitpos */
806 complain_overflow_dont, /* complain_on_overflow */
807 bfd_elf_generic_reloc, /* special_function */
808 "R_RISCV_SET8", /* name */
0a1b45a2 809 false, /* partial_inplace */
45f76423 810 0, /* src_mask */
b1b11e92 811 0xff, /* dst_mask */
0a1b45a2 812 false), /* pcrel_offset */
45f76423
AW
813
814 /* 16-bit in-place setting, for local label subtraction. */
815 HOWTO (R_RISCV_SET16, /* type */
816 0, /* rightshift */
817 1, /* size */
818 16, /* bitsize */
0a1b45a2 819 false, /* pc_relative */
45f76423
AW
820 0, /* bitpos */
821 complain_overflow_dont, /* complain_on_overflow */
822 bfd_elf_generic_reloc, /* special_function */
823 "R_RISCV_SET16", /* name */
0a1b45a2 824 false, /* partial_inplace */
45f76423 825 0, /* src_mask */
b1b11e92 826 0xffff, /* dst_mask */
0a1b45a2 827 false), /* pcrel_offset */
45f76423
AW
828
829 /* 32-bit in-place setting, for local label subtraction. */
830 HOWTO (R_RISCV_SET32, /* type */
831 0, /* rightshift */
832 2, /* size */
833 32, /* bitsize */
0a1b45a2 834 false, /* pc_relative */
45f76423
AW
835 0, /* bitpos */
836 complain_overflow_dont, /* complain_on_overflow */
837 bfd_elf_generic_reloc, /* special_function */
838 "R_RISCV_SET32", /* name */
0a1b45a2 839 false, /* partial_inplace */
45f76423 840 0, /* src_mask */
b1b11e92 841 0xffffffff, /* dst_mask */
0a1b45a2 842 false), /* pcrel_offset */
a6cbf936
KLC
843
844 /* 32-bit PC relative. */
845 HOWTO (R_RISCV_32_PCREL, /* type */
846 0, /* rightshift */
847 2, /* size */
848 32, /* bitsize */
0a1b45a2 849 true, /* pc_relative */
a6cbf936
KLC
850 0, /* bitpos */
851 complain_overflow_dont, /* complain_on_overflow */
852 bfd_elf_generic_reloc, /* special_function */
853 "R_RISCV_32_PCREL", /* name */
0a1b45a2 854 false, /* partial_inplace */
02dd9d25
NC
855 0, /* src_mask */
856 0xffffffff, /* dst_mask */
0a1b45a2 857 false), /* pcrel_offset */
02dd9d25
NC
858
859 /* Relocation against a local ifunc symbol in a shared object. */
860 HOWTO (R_RISCV_IRELATIVE, /* type */
861 0, /* rightshift */
862 2, /* size */
863 32, /* bitsize */
0a1b45a2 864 false, /* pc_relative */
02dd9d25
NC
865 0, /* bitpos */
866 complain_overflow_dont, /* complain_on_overflow */
867 bfd_elf_generic_reloc, /* special_function */
868 "R_RISCV_IRELATIVE", /* name */
0a1b45a2 869 false, /* partial_inplace */
a6cbf936 870 0, /* src_mask */
b1b11e92 871 0xffffffff, /* dst_mask */
0a1b45a2 872 false), /* pcrel_offset */
e23eba97
NC
873};
874
875/* A mapping from BFD reloc types to RISC-V ELF reloc types. */
e23eba97
NC
876struct elf_reloc_map
877{
878 bfd_reloc_code_real_type bfd_val;
879 enum elf_riscv_reloc_type elf_val;
880};
881
882static const struct elf_reloc_map riscv_reloc_map[] =
883{
884 { BFD_RELOC_NONE, R_RISCV_NONE },
885 { BFD_RELOC_32, R_RISCV_32 },
886 { BFD_RELOC_64, R_RISCV_64 },
887 { BFD_RELOC_RISCV_ADD8, R_RISCV_ADD8 },
888 { BFD_RELOC_RISCV_ADD16, R_RISCV_ADD16 },
889 { BFD_RELOC_RISCV_ADD32, R_RISCV_ADD32 },
890 { BFD_RELOC_RISCV_ADD64, R_RISCV_ADD64 },
891 { BFD_RELOC_RISCV_SUB8, R_RISCV_SUB8 },
892 { BFD_RELOC_RISCV_SUB16, R_RISCV_SUB16 },
893 { BFD_RELOC_RISCV_SUB32, R_RISCV_SUB32 },
894 { BFD_RELOC_RISCV_SUB64, R_RISCV_SUB64 },
895 { BFD_RELOC_CTOR, R_RISCV_64 },
896 { BFD_RELOC_12_PCREL, R_RISCV_BRANCH },
897 { BFD_RELOC_RISCV_HI20, R_RISCV_HI20 },
898 { BFD_RELOC_RISCV_LO12_I, R_RISCV_LO12_I },
899 { BFD_RELOC_RISCV_LO12_S, R_RISCV_LO12_S },
900 { BFD_RELOC_RISCV_PCREL_LO12_I, R_RISCV_PCREL_LO12_I },
901 { BFD_RELOC_RISCV_PCREL_LO12_S, R_RISCV_PCREL_LO12_S },
902 { BFD_RELOC_RISCV_CALL, R_RISCV_CALL },
903 { BFD_RELOC_RISCV_CALL_PLT, R_RISCV_CALL_PLT },
904 { BFD_RELOC_RISCV_PCREL_HI20, R_RISCV_PCREL_HI20 },
905 { BFD_RELOC_RISCV_JMP, R_RISCV_JAL },
906 { BFD_RELOC_RISCV_GOT_HI20, R_RISCV_GOT_HI20 },
907 { BFD_RELOC_RISCV_TLS_DTPMOD32, R_RISCV_TLS_DTPMOD32 },
908 { BFD_RELOC_RISCV_TLS_DTPREL32, R_RISCV_TLS_DTPREL32 },
909 { BFD_RELOC_RISCV_TLS_DTPMOD64, R_RISCV_TLS_DTPMOD64 },
910 { BFD_RELOC_RISCV_TLS_DTPREL64, R_RISCV_TLS_DTPREL64 },
911 { BFD_RELOC_RISCV_TLS_TPREL32, R_RISCV_TLS_TPREL32 },
912 { BFD_RELOC_RISCV_TLS_TPREL64, R_RISCV_TLS_TPREL64 },
913 { BFD_RELOC_RISCV_TPREL_HI20, R_RISCV_TPREL_HI20 },
914 { BFD_RELOC_RISCV_TPREL_ADD, R_RISCV_TPREL_ADD },
915 { BFD_RELOC_RISCV_TPREL_LO12_S, R_RISCV_TPREL_LO12_S },
916 { BFD_RELOC_RISCV_TPREL_LO12_I, R_RISCV_TPREL_LO12_I },
917 { BFD_RELOC_RISCV_TLS_GOT_HI20, R_RISCV_TLS_GOT_HI20 },
918 { BFD_RELOC_RISCV_TLS_GD_HI20, R_RISCV_TLS_GD_HI20 },
919 { BFD_RELOC_RISCV_ALIGN, R_RISCV_ALIGN },
920 { BFD_RELOC_RISCV_RVC_BRANCH, R_RISCV_RVC_BRANCH },
921 { BFD_RELOC_RISCV_RVC_JUMP, R_RISCV_RVC_JUMP },
922 { BFD_RELOC_RISCV_RVC_LUI, R_RISCV_RVC_LUI },
923 { BFD_RELOC_RISCV_GPREL_I, R_RISCV_GPREL_I },
924 { BFD_RELOC_RISCV_GPREL_S, R_RISCV_GPREL_S },
45f76423
AW
925 { BFD_RELOC_RISCV_TPREL_I, R_RISCV_TPREL_I },
926 { BFD_RELOC_RISCV_TPREL_S, R_RISCV_TPREL_S },
927 { BFD_RELOC_RISCV_RELAX, R_RISCV_RELAX },
928 { BFD_RELOC_RISCV_SUB6, R_RISCV_SUB6 },
929 { BFD_RELOC_RISCV_SET6, R_RISCV_SET6 },
930 { BFD_RELOC_RISCV_SET8, R_RISCV_SET8 },
931 { BFD_RELOC_RISCV_SET16, R_RISCV_SET16 },
932 { BFD_RELOC_RISCV_SET32, R_RISCV_SET32 },
a6cbf936 933 { BFD_RELOC_RISCV_32_PCREL, R_RISCV_32_PCREL },
e23eba97
NC
934};
935
936/* Given a BFD reloc type, return a howto structure. */
937
938reloc_howto_type *
939riscv_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED,
940 bfd_reloc_code_real_type code)
941{
942 unsigned int i;
943
944 for (i = 0; i < ARRAY_SIZE (riscv_reloc_map); i++)
945 if (riscv_reloc_map[i].bfd_val == code)
946 return &howto_table[(int) riscv_reloc_map[i].elf_val];
947
948 bfd_set_error (bfd_error_bad_value);
949 return NULL;
950}
951
952reloc_howto_type *
953riscv_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED, const char *r_name)
954{
955 unsigned int i;
956
957 for (i = 0; i < ARRAY_SIZE (howto_table); i++)
958 if (howto_table[i].name && strcasecmp (howto_table[i].name, r_name) == 0)
959 return &howto_table[i];
960
961 return NULL;
962}
963
964reloc_howto_type *
0aa13fee 965riscv_elf_rtype_to_howto (bfd *abfd, unsigned int r_type)
e23eba97
NC
966{
967 if (r_type >= ARRAY_SIZE (howto_table))
968 {
0aa13fee
AM
969 (*_bfd_error_handler) (_("%pB: unsupported relocation type %#x"),
970 abfd, r_type);
e23eba97
NC
971 bfd_set_error (bfd_error_bad_value);
972 return NULL;
973 }
974 return &howto_table[r_type];
975}
57593436
KLC
976
977/* Special_function of RISCV_ADD and RISCV_SUB relocations. */
978
979static bfd_reloc_status_type
980riscv_elf_add_sub_reloc (bfd *abfd,
981 arelent *reloc_entry,
982 asymbol *symbol,
983 void *data,
984 asection *input_section,
985 bfd *output_bfd,
986 char **error_message ATTRIBUTE_UNUSED)
987{
988 reloc_howto_type *howto = reloc_entry->howto;
989 bfd_vma relocation;
990
991 if (output_bfd != NULL
992 && (symbol->flags & BSF_SECTION_SYM) == 0
993 && (!reloc_entry->howto->partial_inplace || reloc_entry->addend == 0))
994 {
995 reloc_entry->address += input_section->output_offset;
996 return bfd_reloc_ok;
997 }
998
999 if (output_bfd != NULL)
1000 return bfd_reloc_continue;
1001
1002 relocation = symbol->value + symbol->section->output_section->vma
1003 + symbol->section->output_offset + reloc_entry->addend;
3f1a2892
NC
1004
1005 bfd_size_type octets = reloc_entry->address
1006 * bfd_octets_per_byte (abfd, input_section);
1007 if (!bfd_reloc_offset_in_range (reloc_entry->howto, abfd,
1008 input_section, octets))
1009 return bfd_reloc_outofrange;
1010
57593436
KLC
1011 bfd_vma old_value = bfd_get (howto->bitsize, abfd,
1012 data + reloc_entry->address);
1013
1014 switch (howto->type)
1015 {
1016 case R_RISCV_ADD8:
1017 case R_RISCV_ADD16:
1018 case R_RISCV_ADD32:
1019 case R_RISCV_ADD64:
1020 relocation = old_value + relocation;
1021 break;
1022 case R_RISCV_SUB6:
1023 case R_RISCV_SUB8:
1024 case R_RISCV_SUB16:
1025 case R_RISCV_SUB32:
1026 case R_RISCV_SUB64:
1027 relocation = old_value - relocation;
1028 break;
1029 }
1030 bfd_put (howto->bitsize, abfd, relocation, data + reloc_entry->address);
1031
1032 return bfd_reloc_ok;
1033}
1080bf78 1034
7671eff8
NC
1035/* Always add the IMPLICIT for the SUBSET. */
1036
1037static bool
1038check_implicit_always (const char *implicit ATTRIBUTE_UNUSED,
1039 riscv_subset_t *subset ATTRIBUTE_UNUSED)
1040{
1041 return true;
1042}
1043
1044/* Add the IMPLICIT only when the version of SUBSET less than 2.1. */
1045
1046static bool
1047check_implicit_for_i (const char *implicit ATTRIBUTE_UNUSED,
1048 riscv_subset_t *subset)
1049{
1050 return (subset->major_version < 2
1051 || (subset->major_version == 2
1052 && subset->minor_version < 1));
1053}
1054
1055/* Record all implicit information for the subsets. */
1056struct riscv_implicit_subset
1057{
1058 const char *subset_name;
1059 const char *implicit_name;
1060 /* A function to determine if we need to add the implicit subset. */
1061 bool (*check_func) (const char *, riscv_subset_t *);
1062};
1063static struct riscv_implicit_subset riscv_implicit_subsets[] =
1064{
1065 {"e", "i", check_implicit_always},
1066 {"i", "zicsr", check_implicit_for_i},
1067 {"i", "zifencei", check_implicit_for_i},
c9f27991
NC
1068 {"g", "i", check_implicit_always},
1069 {"g", "m", check_implicit_always},
1070 {"g", "a", check_implicit_always},
1071 {"g", "f", check_implicit_always},
1072 {"g", "d", check_implicit_always},
7671eff8
NC
1073 {"g", "zicsr", check_implicit_always},
1074 {"g", "zifencei", check_implicit_always},
1075 {"q", "d", check_implicit_always},
65e4a99a
NC
1076 {"v", "d", check_implicit_always},
1077 {"v", "zve64d", check_implicit_always},
1078 {"v", "zvl128b", check_implicit_always},
1079 {"zve64d", "d", check_implicit_always},
1080 {"zve64d", "zve64f", check_implicit_always},
1081 {"zve64f", "zve32f", check_implicit_always},
1082 {"zve64f", "zve64x", check_implicit_always},
1083 {"zve64f", "zvl64b", check_implicit_always},
1084 {"zve32f", "f", check_implicit_always},
1085 {"zve32f", "zvl32b", check_implicit_always},
1086 {"zve32f", "zve32x", check_implicit_always},
1087 {"zve64x", "zve32x", check_implicit_always},
1088 {"zve64x", "zvl64b", check_implicit_always},
1089 {"zve32x", "zvl32b", check_implicit_always},
1090 {"zvl65536b", "zvl32768b", check_implicit_always},
1091 {"zvl32768b", "zvl16384b", check_implicit_always},
1092 {"zvl16384b", "zvl8192b", check_implicit_always},
1093 {"zvl8192b", "zvl4096b", check_implicit_always},
1094 {"zvl4096b", "zvl2048b", check_implicit_always},
1095 {"zvl2048b", "zvl1024b", check_implicit_always},
1096 {"zvl1024b", "zvl512b", check_implicit_always},
1097 {"zvl512b", "zvl256b", check_implicit_always},
1098 {"zvl256b", "zvl128b", check_implicit_always},
1099 {"zvl128b", "zvl64b", check_implicit_always},
1100 {"zvl64b", "zvl32b", check_implicit_always},
7671eff8
NC
1101 {"d", "f", check_implicit_always},
1102 {"f", "zicsr", check_implicit_always},
035784e3
NC
1103 {"zfh", "f", check_implicit_always},
1104 {"zfh", "zicsr", check_implicit_always},
da05b70e 1105 {"zqinx", "zdinx", check_implicit_always},
1106 {"zdinx", "zfinx", check_implicit_always},
dfdba097 1107 {"zk", "zkn", check_implicit_always},
1108 {"zk", "zkr", check_implicit_always},
1109 {"zk", "zkt", check_implicit_always},
1110 {"zkn", "zbkb", check_implicit_always},
1111 {"zkn", "zbkc", check_implicit_always},
1112 {"zkn", "zbkx", check_implicit_always},
1113 {"zkn", "zkne", check_implicit_always},
1114 {"zkn", "zknd", check_implicit_always},
1115 {"zkn", "zknh", check_implicit_always},
1116 {"zks", "zbkb", check_implicit_always},
1117 {"zks", "zbkc", check_implicit_always},
1118 {"zks", "zbkx", check_implicit_always},
1119 {"zks", "zksed", check_implicit_always},
1120 {"zks", "zksh", check_implicit_always},
7671eff8
NC
1121 {NULL, NULL, NULL}
1122};
1123
c9f27991
NC
1124/* For default_enable field, decide if the extension should
1125 be enbaled by default. */
e601909a 1126
c9f27991 1127#define EXT_DEFAULT 0x1
e601909a 1128
c9f27991
NC
1129/* List all extensions that binutils should know about. */
1130
1131struct riscv_supported_ext
e601909a 1132{
c9f27991
NC
1133 const char *name;
1134 enum riscv_spec_class isa_spec_class;
1135 int major_version;
1136 int minor_version;
1137 unsigned long default_enable;
e601909a
NC
1138};
1139
c9f27991
NC
1140/* The standard extensions must be added in canonical order. */
1141
1142static struct riscv_supported_ext riscv_supported_std_ext[] =
e601909a 1143{
c9f27991
NC
1144 {"e", ISA_SPEC_CLASS_20191213, 1, 9, 0 },
1145 {"e", ISA_SPEC_CLASS_20190608, 1, 9, 0 },
1146 {"e", ISA_SPEC_CLASS_2P2, 1, 9, 0 },
1147 {"i", ISA_SPEC_CLASS_20191213, 2, 1, 0 },
1148 {"i", ISA_SPEC_CLASS_20190608, 2, 1, 0 },
1149 {"i", ISA_SPEC_CLASS_2P2, 2, 0, 0 },
1150 /* The g is a special case which we don't want to output it,
1151 but still need it when adding implicit extensions. */
1152 {"g", ISA_SPEC_CLASS_NONE, RISCV_UNKNOWN_VERSION, RISCV_UNKNOWN_VERSION, EXT_DEFAULT },
1153 {"m", ISA_SPEC_CLASS_20191213, 2, 0, 0 },
1154 {"m", ISA_SPEC_CLASS_20190608, 2, 0, 0 },
1155 {"m", ISA_SPEC_CLASS_2P2, 2, 0, 0 },
1156 {"a", ISA_SPEC_CLASS_20191213, 2, 1, 0 },
1157 {"a", ISA_SPEC_CLASS_20190608, 2, 0, 0 },
1158 {"a", ISA_SPEC_CLASS_2P2, 2, 0, 0 },
1159 {"f", ISA_SPEC_CLASS_20191213, 2, 2, 0 },
1160 {"f", ISA_SPEC_CLASS_20190608, 2, 2, 0 },
1161 {"f", ISA_SPEC_CLASS_2P2, 2, 0, 0 },
1162 {"d", ISA_SPEC_CLASS_20191213, 2, 2, 0 },
1163 {"d", ISA_SPEC_CLASS_20190608, 2, 2, 0 },
1164 {"d", ISA_SPEC_CLASS_2P2, 2, 0, 0 },
1165 {"q", ISA_SPEC_CLASS_20191213, 2, 2, 0 },
1166 {"q", ISA_SPEC_CLASS_20190608, 2, 2, 0 },
1167 {"q", ISA_SPEC_CLASS_2P2, 2, 0, 0 },
c9f27991
NC
1168 {"c", ISA_SPEC_CLASS_20191213, 2, 0, 0 },
1169 {"c", ISA_SPEC_CLASS_20190608, 2, 0, 0 },
1170 {"c", ISA_SPEC_CLASS_2P2, 2, 0, 0 },
65e4a99a 1171 {"v", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
c9f27991 1172 {NULL, 0, 0, 0, 0}
e601909a
NC
1173};
1174
c9f27991 1175static struct riscv_supported_ext riscv_supported_std_z_ext[] =
e601909a 1176{
41d6ac5d 1177 {"zicbom", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
3b374308 1178 {"zicbop", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
41d6ac5d 1179 {"zicboz", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
c9f27991
NC
1180 {"zicsr", ISA_SPEC_CLASS_20191213, 2, 0, 0 },
1181 {"zicsr", ISA_SPEC_CLASS_20190608, 2, 0, 0 },
1182 {"zifencei", ISA_SPEC_CLASS_20191213, 2, 0, 0 },
1183 {"zifencei", ISA_SPEC_CLASS_20190608, 2, 0, 0 },
1184 {"zihintpause", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
035784e3 1185 {"zfh", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
da05b70e 1186 {"zfinx", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1187 {"zdinx", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1188 {"zqinx", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
586dcfc8
PT
1189 {"zbb", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1190 {"zba", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1191 {"zbc", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
dfdba097 1192 {"zbs", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1193 {"zbkb", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1194 {"zbkc", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1195 {"zbkx", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1196 {"zk", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1197 {"zkn", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1198 {"zknd", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1199 {"zkne", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1200 {"zknh", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1201 {"zkr", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1202 {"zks", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1203 {"zksed", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1204 {"zksh", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1205 {"zkt", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
65e4a99a
NC
1206 {"zve32x", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1207 {"zve32f", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1208 {"zve32d", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1209 {"zve64x", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1210 {"zve64f", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1211 {"zve64d", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1212 {"zvl32b", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1213 {"zvl64b", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1214 {"zvl128b", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1215 {"zvl256b", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1216 {"zvl512b", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1217 {"zvl1024b", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1218 {"zvl2048b", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1219 {"zvl4096b", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1220 {"zvl8192b", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1221 {"zvl16384b", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1222 {"zvl32768b", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1223 {"zvl65536b", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
c9f27991
NC
1224 {NULL, 0, 0, 0, 0}
1225};
1226
1227static struct riscv_supported_ext riscv_supported_std_s_ext[] =
1228{
23ff54c2 1229 {"svinval", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
c9f27991
NC
1230 {NULL, 0, 0, 0, 0}
1231};
1232
1233static struct riscv_supported_ext riscv_supported_std_h_ext[] =
1234{
1235 {NULL, 0, 0, 0, 0}
e601909a
NC
1236};
1237
c9f27991 1238static struct riscv_supported_ext riscv_supported_std_zxm_ext[] =
e601909a 1239{
c9f27991
NC
1240 {NULL, 0, 0, 0, 0}
1241};
1242
1243const struct riscv_supported_ext *riscv_all_supported_ext[] =
1244{
1245 riscv_supported_std_ext,
1246 riscv_supported_std_z_ext,
1247 riscv_supported_std_s_ext,
1248 riscv_supported_std_h_ext,
1249 riscv_supported_std_zxm_ext,
e601909a
NC
1250 NULL
1251};
1252
1253/* ISA extension prefixed name class. Must define them in parsing order. */
1254enum riscv_prefix_ext_class
1255{
1256 RV_ISA_CLASS_Z = 1,
1257 RV_ISA_CLASS_S,
1258 RV_ISA_CLASS_H,
1259 RV_ISA_CLASS_ZXM,
1260 RV_ISA_CLASS_X,
1261 RV_ISA_CLASS_UNKNOWN
1262};
1263
1264/* Record the strings of the prefixed extensions, and their corresponding
1265 classes. The more letters of the prefix string, the more forward it must
1266 be defined. Otherwise, the riscv_get_prefix_class will map it to the
1267 wrong classes. */
1268struct riscv_parse_prefix_config
1269{
1270 /* Class of the extension. */
1271 enum riscv_prefix_ext_class class;
1272
1273 /* Prefix string for error printing and internal parser usage. */
1274 const char *prefix;
1275};
1276static const struct riscv_parse_prefix_config parse_config[] =
1277{
1278 {RV_ISA_CLASS_ZXM, "zxm"},
1279 {RV_ISA_CLASS_Z, "z"},
1280 {RV_ISA_CLASS_S, "s"},
1281 {RV_ISA_CLASS_H, "h"},
1282 {RV_ISA_CLASS_X, "x"},
1283 {RV_ISA_CLASS_UNKNOWN, NULL}
1284};
1285
1286/* Get the prefixed name class for the extensions, the class also
1287 means the order of the prefixed extensions. */
1288
1289static enum riscv_prefix_ext_class
1290riscv_get_prefix_class (const char *arch)
1291{
1292 int i = 0;
1293 while (parse_config[i].class != RV_ISA_CLASS_UNKNOWN)
1294 {
1295 if (strncmp (arch, parse_config[i].prefix,
1296 strlen (parse_config[i].prefix)) == 0)
1297 return parse_config[i].class;
1298 i++;
1299 }
1300 return RV_ISA_CLASS_UNKNOWN;
1301}
1302
1303/* Check KNOWN_EXTS to see if the EXT is supported. */
1304
1305static bool
1306riscv_known_prefixed_ext (const char *ext,
c9f27991 1307 struct riscv_supported_ext *known_exts)
e601909a
NC
1308{
1309 size_t i;
c9f27991
NC
1310 for (i = 0; known_exts[i].name != NULL; ++i)
1311 if (strcmp (ext, known_exts[i].name) == 0)
e601909a
NC
1312 return true;
1313 return false;
1314}
7ef19aa6 1315
69a61890
NC
1316/* Check whether the prefixed extension is recognized or not. Return
1317 true if recognized, otehrwise return false. */
e601909a
NC
1318
1319static bool
69a61890 1320riscv_recognized_prefixed_ext (const char *ext)
e601909a
NC
1321{
1322 enum riscv_prefix_ext_class class = riscv_get_prefix_class (ext);
1323 switch (class)
1324 {
1325 case RV_ISA_CLASS_Z:
c9f27991 1326 return riscv_known_prefixed_ext (ext, riscv_supported_std_z_ext);
e601909a 1327 case RV_ISA_CLASS_ZXM:
c9f27991 1328 return riscv_known_prefixed_ext (ext, riscv_supported_std_zxm_ext);
e601909a 1329 case RV_ISA_CLASS_S:
c9f27991 1330 return riscv_known_prefixed_ext (ext, riscv_supported_std_s_ext);
e601909a 1331 case RV_ISA_CLASS_H:
c9f27991 1332 return riscv_known_prefixed_ext (ext, riscv_supported_std_h_ext);
e601909a 1333 case RV_ISA_CLASS_X:
69a61890 1334 /* Only the single x is unrecognized. */
e601909a
NC
1335 if (strcmp (ext, "x") != 0)
1336 return true;
1337 default:
1338 break;
1339 }
1340 return false;
1341}
1342
3a3e333f 1343/* Canonical order for single letter extensions. */
c4dd8eb5 1344static const char riscv_ext_canonical_order[] = "eigmafdqlcbkjtpvn";
3a3e333f 1345
e601909a 1346/* Array is used to compare the orders of standard extensions quickly. */
dfe92496
NC
1347static int riscv_ext_order[26] = {0};
1348
e601909a
NC
1349/* Init the riscv_ext_order array. */
1350
1351static void
1352riscv_init_ext_order (void)
1353{
1354 static bool inited = false;
e601909a
NC
1355 if (inited)
1356 return;
1357
1358 /* The orders of all standard extensions are positive. */
c9f27991 1359 int order = 1;
e601909a 1360
3a3e333f
KC
1361 for (const char *ext = &riscv_ext_canonical_order[0]; *ext; ++ext)
1362 riscv_ext_order[(*ext - 'a')] = order++;
e601909a
NC
1363
1364 /* Some of the prefixed keyword are not single letter, so we set
1365 their prefixed orders in the riscv_compare_subsets directly,
1366 not through the riscv_ext_order. */
1367
1368 inited = true;
1369}
1370
dfe92496
NC
1371/* Similar to the strcmp. It returns an integer less than, equal to,
1372 or greater than zero if `subset2` is found, respectively, to be less
e601909a
NC
1373 than, to match, or be greater than `subset1`.
1374
1375 The order values,
1376 Zero: Preserved keywords.
1377 Positive number: Standard extensions.
1378 Negative number: Prefixed keywords. */
dfe92496 1379
4c0e540e 1380int
dfe92496 1381riscv_compare_subsets (const char *subset1, const char *subset2)
7ef19aa6 1382{
dfe92496
NC
1383 int order1 = riscv_ext_order[(*subset1 - 'a')];
1384 int order2 = riscv_ext_order[(*subset2 - 'a')];
7ef19aa6 1385
dfe92496
NC
1386 /* Compare the standard extension first. */
1387 if (order1 > 0 && order2 > 0)
1388 return order1 - order2;
7ef19aa6 1389
e601909a
NC
1390 /* Set the prefixed orders to negative numbers. */
1391 enum riscv_prefix_ext_class class1 = riscv_get_prefix_class (subset1);
1392 enum riscv_prefix_ext_class class2 = riscv_get_prefix_class (subset2);
1393
1394 if (class1 != RV_ISA_CLASS_UNKNOWN)
1395 order1 = - (int) class1;
1396 if (class2 != RV_ISA_CLASS_UNKNOWN)
1397 order2 = - (int) class2;
1398
1399 if (order1 == order2)
dfe92496
NC
1400 {
1401 /* Compare the standard addition z extensions. */
e601909a 1402 if (class1 == RV_ISA_CLASS_Z)
dfe92496
NC
1403 {
1404 order1 = riscv_ext_order[(*++subset1 - 'a')];
1405 order2 = riscv_ext_order[(*++subset2 - 'a')];
1406 if (order1 != order2)
1407 return order1 - order2;
1408 }
1409 return strcasecmp (++subset1, ++subset2);
1410 }
1411
1412 return order2 - order1;
1413}
1414
1415/* Find subset in the list. Return TRUE and set `current` to the subset
1416 if it is found. Otherwise, return FALSE and set `current` to the place
1417 where we should insert the subset. However, return FALSE with the NULL
1418 `current` means we should insert the subset at the head of subset list,
1419 if needed. */
1420
0a1b45a2 1421bool
dfe92496
NC
1422riscv_lookup_subset (const riscv_subset_list_t *subset_list,
1423 const char *subset,
1424 riscv_subset_t **current)
1425{
1426 riscv_subset_t *s, *pre_s = NULL;
1427
cb959bd8
NC
1428 /* If the subset is added in order, then just add it at the tail. */
1429 if (subset_list->tail != NULL
1430 && riscv_compare_subsets (subset_list->tail->name, subset) < 0)
1431 {
1432 *current = subset_list->tail;
1433 return false;
1434 }
1435
dfe92496
NC
1436 for (s = subset_list->head;
1437 s != NULL;
1438 pre_s = s, s = s->next)
1439 {
1440 int cmp = riscv_compare_subsets (s->name, subset);
1441 if (cmp == 0)
1442 {
1443 *current = s;
0a1b45a2 1444 return true;
dfe92496
NC
1445 }
1446 else if (cmp > 0)
1447 break;
1448 }
1449 *current = pre_s;
cb959bd8 1450
0a1b45a2 1451 return false;
7ef19aa6
NC
1452}
1453
cb959bd8
NC
1454/* Add the extension to the subset list. Search the
1455 list first, and then find the right place to add. */
7ef19aa6
NC
1456
1457void
1458riscv_add_subset (riscv_subset_list_t *subset_list,
1459 const char *subset,
1460 int major,
1461 int minor)
dfe92496
NC
1462{
1463 riscv_subset_t *current, *new;
1464
1465 if (riscv_lookup_subset (subset_list, subset, &current))
de3a913d 1466 return;
dfe92496
NC
1467
1468 new = xmalloc (sizeof *new);
1469 new->name = xstrdup (subset);
1470 new->major_version = major;
1471 new->minor_version = minor;
1472 new->next = NULL;
1473
1474 if (current != NULL)
1475 {
1476 new->next = current->next;
1477 current->next = new;
1478 }
1479 else
1480 {
1481 new->next = subset_list->head;
1482 subset_list->head = new;
1483 }
dfe92496 1484
cb959bd8
NC
1485 if (new->next == NULL)
1486 subset_list->tail = new;
1487}
dfe92496 1488
c9f27991
NC
1489/* Get the default versions from the riscv_supported_*ext tables. */
1490
1491static void
f786c359 1492riscv_get_default_ext_version (enum riscv_spec_class *default_isa_spec,
c9f27991
NC
1493 const char *name,
1494 int *major_version,
1495 int *minor_version)
1496{
f786c359
NC
1497 if (name == NULL
1498 || default_isa_spec == NULL
1499 || *default_isa_spec == ISA_SPEC_CLASS_NONE)
c9f27991
NC
1500 return;
1501
1502 struct riscv_supported_ext *table = NULL;
1503 enum riscv_prefix_ext_class class = riscv_get_prefix_class (name);
1504 switch (class)
1505 {
1506 case RV_ISA_CLASS_ZXM: table = riscv_supported_std_zxm_ext; break;
1507 case RV_ISA_CLASS_Z: table = riscv_supported_std_z_ext; break;
1508 case RV_ISA_CLASS_S: table = riscv_supported_std_s_ext; break;
1509 case RV_ISA_CLASS_H: table = riscv_supported_std_h_ext; break;
1510 case RV_ISA_CLASS_X:
1511 break;
1512 default:
1513 table = riscv_supported_std_ext;
1514 }
1515
1516 int i = 0;
1517 while (table != NULL && table[i].name != NULL)
1518 {
1519 if (strcmp (table[i].name, name) == 0
1520 && (table[i].isa_spec_class == ISA_SPEC_CLASS_DRAFT
f786c359 1521 || table[i].isa_spec_class == *default_isa_spec))
c9f27991
NC
1522 {
1523 *major_version = table[i].major_version;
1524 *minor_version = table[i].minor_version;
1525 return;
1526 }
1527 i++;
1528 }
1529}
1530
cb959bd8 1531/* Find the default versions for the extension before adding them to
7ef19aa6
NC
1532 the subset list, if their versions are RISCV_UNKNOWN_VERSION.
1533 Afterwards, report errors if we can not find their default versions. */
1534
1535static void
1536riscv_parse_add_subset (riscv_parse_subset_t *rps,
1537 const char *subset,
1538 int major,
dfe92496 1539 int minor,
0a1b45a2 1540 bool implicit)
7ef19aa6
NC
1541{
1542 int major_version = major;
1543 int minor_version = minor;
1544
c9f27991 1545 if (major_version == RISCV_UNKNOWN_VERSION
7ef19aa6 1546 || minor_version == RISCV_UNKNOWN_VERSION)
c9f27991
NC
1547 riscv_get_default_ext_version (rps->isa_spec, subset,
1548 &major_version, &minor_version);
7ef19aa6 1549
f0bae255
NC
1550 /* We don't care the versions of the implicit extensions. */
1551 if (!implicit
dfe92496
NC
1552 && (major_version == RISCV_UNKNOWN_VERSION
1553 || minor_version == RISCV_UNKNOWN_VERSION))
7ef19aa6
NC
1554 {
1555 if (subset[0] == 'x')
1556 rps->error_handler
1557 (_("x ISA extension `%s' must be set with the versions"),
1558 subset);
aed44286
NC
1559 /* Allow old ISA spec can recognize zicsr and zifencei. */
1560 else if (strcmp (subset, "zicsr") != 0
1561 && strcmp (subset, "zifencei") != 0)
7ef19aa6
NC
1562 rps->error_handler
1563 (_("cannot find default versions of the ISA extension `%s'"),
1564 subset);
1565 return;
1566 }
1567
cb959bd8
NC
1568 riscv_add_subset (rps->subset_list, subset,
1569 major_version, minor_version);
7ef19aa6
NC
1570}
1571
1572/* Release subset list. */
1573
1574void
1575riscv_release_subset_list (riscv_subset_list_t *subset_list)
1576{
1577 while (subset_list->head != NULL)
1578 {
1579 riscv_subset_t *next = subset_list->head->next;
1580 free ((void *)subset_list->head->name);
1581 free (subset_list->head);
1582 subset_list->head = next;
1583 }
1584
1585 subset_list->tail = NULL;
1586}
1587
d541518b 1588/* Parsing extension version.
1080bf78
JW
1589
1590 Return Value:
1591 Points to the end of version
1592
1593 Arguments:
1080bf78 1594 `p`: Curent parsing position.
7ef19aa6 1595 `major_version`: Parsed major version.
69a61890 1596 `minor_version`: Parsed minor version. */
1080bf78
JW
1597
1598static const char *
69a61890 1599riscv_parsing_subset_version (const char *p,
7ef19aa6 1600 int *major_version,
69a61890 1601 int *minor_version)
1080bf78 1602{
0a1b45a2 1603 bool major_p = true;
7ef19aa6 1604 int version = 0;
1080bf78
JW
1605 char np;
1606
8f595e9b
NC
1607 *major_version = 0;
1608 *minor_version = 0;
1609 for (; *p; ++p)
1080bf78
JW
1610 {
1611 if (*p == 'p')
1612 {
1613 np = *(p + 1);
1614
3a6a0158 1615 /* Might be beginning of `p` extension. */
1080bf78 1616 if (!ISDIGIT (np))
3a6a0158 1617 break;
1080bf78 1618
8f595e9b 1619 *major_version = version;
0a1b45a2 1620 major_p = false;
1080bf78
JW
1621 version = 0;
1622 }
1623 else if (ISDIGIT (*p))
1624 version = (version * 10) + (*p - '0');
1625 else
1626 break;
1627 }
1628
1629 if (major_p)
8f595e9b 1630 *major_version = version;
1080bf78 1631 else
8f595e9b 1632 *minor_version = version;
1080bf78 1633
7ef19aa6
NC
1634 /* We can not find any version in string. */
1635 if (*major_version == 0 && *minor_version == 0)
1636 {
1637 *major_version = RISCV_UNKNOWN_VERSION;
1638 *minor_version = RISCV_UNKNOWN_VERSION;
1639 }
1640
1080bf78
JW
1641 return p;
1642}
1643
1080bf78
JW
1644/* Parsing function for standard extensions.
1645
1646 Return Value:
1647 Points to the end of extensions.
1648
1649 Arguments:
d541518b 1650 `rps`: Hooks and status for parsing extensions.
cb959bd8 1651 `arch`: Full ISA string.
1080bf78
JW
1652 `p`: Curent parsing position. */
1653
1654static const char *
1655riscv_parse_std_ext (riscv_parse_subset_t *rps,
cb959bd8 1656 const char *arch,
8f595e9b 1657 const char *p)
1080bf78 1658{
1080bf78 1659 /* First letter must start with i, e or g. */
c9f27991 1660 if (*p != 'e' && *p != 'i' && *p != 'g')
1080bf78 1661 {
c9f27991
NC
1662 rps->error_handler
1663 (_("%s: first ISA extension must be `e', `i' or `g'"),
1664 arch);
1665 return NULL;
1080bf78
JW
1666 }
1667
8f595e9b 1668 while (p != NULL && *p != '\0')
1080bf78 1669 {
e601909a
NC
1670 /* Stop when we parsed the known prefix class. */
1671 enum riscv_prefix_ext_class class = riscv_get_prefix_class (p);
1672 if (class != RV_ISA_CLASS_UNKNOWN)
1080bf78
JW
1673 break;
1674
1675 if (*p == '_')
1676 {
1677 p++;
1678 continue;
1679 }
1680
c9f27991
NC
1681 bool implicit = false;
1682 int major = RISCV_UNKNOWN_VERSION;
1683 int minor = RISCV_UNKNOWN_VERSION;
1684 char subset[2] = {0, 0};
1685
1686 subset[0] = *p;
1080bf78 1687
c9f27991
NC
1688 /* Check if the standard extension is supported. */
1689 if (riscv_ext_order[(subset[0] - 'a')] == 0)
1080bf78 1690 {
c9f27991
NC
1691 rps->error_handler
1692 (_("%s: unknown standard ISA extension `%c'"),
1693 arch, subset[0]);
1080bf78
JW
1694 return NULL;
1695 }
1696
c9f27991
NC
1697 /* Checking canonical order. */
1698 if (rps->subset_list->tail != NULL
1699 && riscv_compare_subsets (rps->subset_list->tail->name, subset) > 0)
1700 {
1701 rps->error_handler
1702 (_("%s: standard ISA extension `%c' is not "
1703 "in canonical order"), arch, subset[0]);
1704 return NULL;
1705 }
1706
69a61890 1707 p = riscv_parsing_subset_version (++p, &major, &minor);
c9f27991
NC
1708 /* Added g as an implicit extension. */
1709 if (subset[0] == 'g')
1710 {
1711 implicit = true;
1712 major = RISCV_UNKNOWN_VERSION;
1713 minor = RISCV_UNKNOWN_VERSION;
1714 }
1715 riscv_parse_add_subset (rps, subset, major, minor, implicit);
1080bf78 1716 }
d541518b 1717
1080bf78
JW
1718 return p;
1719}
1720
d541518b
NC
1721/* Parsing function for prefixed extensions.
1722
1723 Return Value:
1724 Points to the end of extension.
1725
1726 Arguments:
1727 `rps`: Hooks and status for parsing extensions.
cb959bd8 1728 `arch`: Full ISA string.
e3839c10 1729 `p`: Curent parsing position. */
1080bf78
JW
1730
1731static const char *
403d1bd9 1732riscv_parse_prefixed_ext (riscv_parse_subset_t *rps,
cb959bd8 1733 const char *arch,
e601909a 1734 const char *p)
1080bf78 1735{
7ef19aa6
NC
1736 int major_version;
1737 int minor_version;
403d1bd9 1738 const char *last_name;
e601909a 1739 enum riscv_prefix_ext_class class;
1080bf78
JW
1740
1741 while (*p)
1742 {
1743 if (*p == '_')
1744 {
1745 p++;
1746 continue;
1747 }
1748
403d1bd9 1749 class = riscv_get_prefix_class (p);
e601909a
NC
1750 if (class == RV_ISA_CLASS_UNKNOWN)
1751 {
1752 rps->error_handler
cb959bd8
NC
1753 (_("%s: unknown prefix class for the ISA extension `%s'"),
1754 arch, p);
e601909a
NC
1755 return NULL;
1756 }
1080bf78
JW
1757
1758 char *subset = xstrdup (p);
1759 char *q = subset;
1760 const char *end_of_version;
1761
69a61890
NC
1762 /* Extract the whole prefixed extension by '_'. */
1763 while (*++q != '\0' && *q != '_')
1080bf78 1764 ;
69a61890
NC
1765 /* Look forward to the first letter which is not <major>p<minor>. */
1766 bool find_any_version = false;
1767 bool find_minor_version = false;
1768 while (1)
1769 {
1770 q--;
1771 if (ISDIGIT (*q))
1772 find_any_version = true;
1773 else if (find_any_version
1774 && !find_minor_version
1775 && *q == 'p'
1776 && ISDIGIT (*(q - 1)))
1777 find_minor_version = true;
1778 else
1779 break;
1780 }
1781 q++;
1782
1783 /* Check if the end of extension is 'p' or not. If yes, then
1784 the second letter from the end cannot be number. */
1785 if (*(q - 1) == 'p' && ISDIGIT (*(q - 2)))
1786 {
1787 *q = '\0';
1788 rps->error_handler
1789 (_("%s: invalid prefixed ISA extension `%s' ends with <number>p"),
1790 arch, subset);
1791 free (subset);
1792 return NULL;
1793 }
1080bf78
JW
1794
1795 end_of_version =
69a61890 1796 riscv_parsing_subset_version (q, &major_version, &minor_version);
1080bf78 1797 *q = '\0';
7ef19aa6
NC
1798 if (end_of_version == NULL)
1799 {
1800 free (subset);
1801 return NULL;
1802 }
1803
403d1bd9 1804 /* Check that the extension name is well-formed. */
fe1f847d 1805 if (rps->check_unknown_prefixed_ext
69a61890 1806 && !riscv_recognized_prefixed_ext (subset))
403d1bd9
JW
1807 {
1808 rps->error_handler
cb959bd8
NC
1809 (_("%s: unknown prefixed ISA extension `%s'"),
1810 arch, subset);
403d1bd9
JW
1811 free (subset);
1812 return NULL;
1813 }
1814
d541518b 1815 /* Check that the extension isn't duplicate. */
403d1bd9 1816 last_name = rps->subset_list->tail->name;
403d1bd9
JW
1817 if (!strcasecmp (last_name, subset))
1818 {
8f595e9b 1819 rps->error_handler
cb959bd8
NC
1820 (_("%s: duplicate prefixed ISA extension `%s'"),
1821 arch, subset);
403d1bd9
JW
1822 free (subset);
1823 return NULL;
1824 }
1825
e601909a 1826 /* Check that the extension is in expected order. */
6729e2c2 1827 if (riscv_compare_subsets (last_name, subset) > 0)
403d1bd9 1828 {
8f595e9b 1829 rps->error_handler
cb959bd8 1830 (_("%s: prefixed ISA extension `%s' is not in expected "
d541518b 1831 "order. It must come before `%s'"),
cb959bd8 1832 arch, subset, last_name);
403d1bd9
JW
1833 free (subset);
1834 return NULL;
1835 }
1836
7ef19aa6
NC
1837 riscv_parse_add_subset (rps, subset,
1838 major_version,
0a1b45a2 1839 minor_version, false);
1080bf78 1840 p += end_of_version - subset;
e9cf3691 1841 free (subset);
1080bf78
JW
1842
1843 if (*p != '\0' && *p != '_')
1844 {
d541518b 1845 rps->error_handler
cb959bd8
NC
1846 (_("%s: prefixed ISA extension must separate with _"),
1847 arch);
1080bf78
JW
1848 return NULL;
1849 }
1850 }
1851
1852 return p;
1853}
1854
dcd709e0 1855/* Add the implicit extensions. */
dfe92496
NC
1856
1857static void
1858riscv_parse_add_implicit_subsets (riscv_parse_subset_t *rps)
1859{
7671eff8
NC
1860 struct riscv_implicit_subset *t = riscv_implicit_subsets;
1861 for (; t->subset_name; t++)
dfe92496 1862 {
7671eff8
NC
1863 riscv_subset_t *subset = NULL;
1864 if (riscv_lookup_subset (rps->subset_list, t->subset_name, &subset)
1865 && t->check_func (t->implicit_name, subset))
1866 riscv_parse_add_subset (rps, t->implicit_name,
1867 RISCV_UNKNOWN_VERSION,
1868 RISCV_UNKNOWN_VERSION, true);
00d4d1b0 1869 }
dfe92496
NC
1870}
1871
cb959bd8
NC
1872/* Check extensions conflicts. */
1873
1874static bool
1875riscv_parse_check_conflicts (riscv_parse_subset_t *rps)
1876{
1877 riscv_subset_t *subset = NULL;
1878 int xlen = *rps->xlen;
1879 bool no_conflict = true;
1880
1881 if (riscv_lookup_subset (rps->subset_list, "e", &subset)
1882 && xlen > 32)
1883 {
1884 rps->error_handler
1885 (_("rv%d does not support the `e' extension"), xlen);
1886 no_conflict = false;
1887 }
1888 if (riscv_lookup_subset (rps->subset_list, "q", &subset)
1889 && xlen < 64)
1890 {
1891 rps->error_handler
1892 (_("rv%d does not support the `q' extension"), xlen);
1893 no_conflict = false;
1894 }
1895 if (riscv_lookup_subset (rps->subset_list, "e", &subset)
1896 && riscv_lookup_subset (rps->subset_list, "f", &subset))
1897 {
1898 rps->error_handler
1899 (_("rv32e does not support the `f' extension"));
1900 no_conflict = false;
1901 }
da05b70e 1902 if (riscv_lookup_subset (rps->subset_list, "zfinx", &subset)
1903 && riscv_lookup_subset (rps->subset_list, "f", &subset))
1904 {
1905 rps->error_handler
1906 (_("`zfinx' is conflict with the `f/d/q' extension"));
1907 no_conflict = false;
1908 }
65e4a99a
NC
1909
1910 bool support_zve = false;
1911 bool support_zvl = false;
1912 riscv_subset_t *s = rps->subset_list->head;
1913 for (; s != NULL; s = s->next)
1914 {
1915 if (!support_zve
1916 && strncmp (s->name, "zve", 3) == 0)
1917 support_zve = true;
1918 if (!support_zvl
1919 && strncmp (s->name, "zvl", 3) == 0)
1920 support_zvl = true;
1921 if (support_zve && support_zvl)
1922 break;
1923 }
1924 if (support_zvl && !support_zve)
1925 {
1926 rps->error_handler
1927 (_("zvl*b extensions need to enable either `v' or `zve' extension"));
1928 no_conflict = false;
1929 }
1930
cb959bd8
NC
1931 return no_conflict;
1932}
1933
c9f27991
NC
1934/* Set the default subset list according to the default_enable field
1935 of riscv_supported_*ext tables. */
1936
1937static void
1938riscv_set_default_arch (riscv_parse_subset_t *rps)
1939{
1940 unsigned long enable = EXT_DEFAULT;
1941 int i, j;
1942 for (i = 0; riscv_all_supported_ext[i] != NULL; i++)
1943 {
1944 const struct riscv_supported_ext *table = riscv_all_supported_ext[i];
1945 for (j = 0; table[j].name != NULL; j++)
1946 {
1947 bool implicit = false;
1948 if (strcmp (table[j].name, "g") == 0)
1949 implicit = true;
1950 if (table[j].default_enable & enable)
1951 riscv_parse_add_subset (rps, table[j].name,
1952 RISCV_UNKNOWN_VERSION,
1953 RISCV_UNKNOWN_VERSION, implicit);
1954 }
1955 }
1956}
1957
dcd709e0 1958/* Function for parsing ISA string.
1080bf78
JW
1959
1960 Return Value:
1961 Return TRUE on success.
1962
1963 Arguments:
d541518b 1964 `rps`: Hooks and status for parsing extensions.
dcd709e0 1965 `arch`: Full ISA string. */
1080bf78 1966
0a1b45a2 1967bool
1080bf78
JW
1968riscv_parse_subset (riscv_parse_subset_t *rps,
1969 const char *arch)
1970{
e8d4709e 1971 const char *p;
1080bf78 1972
c9f27991
NC
1973 /* Init the riscv_ext_order array to compare the order of extensions
1974 quickly. */
1975 riscv_init_ext_order ();
1976
1977 if (arch == NULL)
1978 {
1979 riscv_set_default_arch (rps);
1980 riscv_parse_add_implicit_subsets (rps);
1981 return riscv_parse_check_conflicts (rps);
1982 }
1983
e8d4709e
NC
1984 for (p = arch; *p != '\0'; p++)
1985 {
1986 if (ISUPPER (*p))
1987 {
1988 rps->error_handler
cb959bd8 1989 (_("%s: ISA string cannot contain uppercase letters"),
e8d4709e 1990 arch);
0a1b45a2 1991 return false;
e8d4709e
NC
1992 }
1993 }
1994
1995 p = arch;
3f3328b8 1996 if (startswith (p, "rv32"))
1080bf78
JW
1997 {
1998 *rps->xlen = 32;
1999 p += 4;
2000 }
3f3328b8 2001 else if (startswith (p, "rv64"))
1080bf78
JW
2002 {
2003 *rps->xlen = 64;
2004 p += 4;
2005 }
2006 else
2007 {
c9f27991
NC
2008 /* ISA string shouldn't be NULL or empty here. For linker,
2009 it might be empty when we failed to merge the ISA string
2010 in the riscv_merge_attributes. For assembler, we might
2011 give an empty string by .attribute arch, "" or -march=.
2012 However, We have already issued the correct error message
2013 in another side, so do not issue this error when the ISA
2014 string is empty. */
72bd6912
KC
2015 if (strlen (arch))
2016 rps->error_handler (
cb959bd8 2017 _("%s: ISA string must begin with rv32 or rv64"),
72bd6912 2018 arch);
0a1b45a2 2019 return false;
1080bf78
JW
2020 }
2021
2022 /* Parsing standard extension. */
2023 p = riscv_parse_std_ext (rps, arch, p);
2024
2025 if (p == NULL)
0a1b45a2 2026 return false;
1080bf78 2027
0f94906f
TO
2028 /* Parse prefixed extensions. */
2029 p = riscv_parse_prefixed_ext (rps, arch, p);
1080bf78 2030
0f94906f
TO
2031 if (p == NULL)
2032 return false;
1080bf78 2033
dfe92496
NC
2034 /* Finally add implicit extensions according to the current
2035 extensions. */
2036 riscv_parse_add_implicit_subsets (rps);
2037
d541518b 2038 /* Check the conflicts. */
cb959bd8 2039 return riscv_parse_check_conflicts (rps);
1080bf78 2040}
2dc8dd17
JW
2041
2042/* Return the number of digits for the input. */
2043
8f595e9b 2044size_t
2dc8dd17
JW
2045riscv_estimate_digit (unsigned num)
2046{
2047 size_t digit = 0;
2048 if (num == 0)
2049 return 1;
2050
2051 for (digit = 0; num ; num /= 10)
2052 digit++;
2053
2054 return digit;
2055}
2056
2057/* Auxiliary function to estimate string length of subset list. */
2058
2059static size_t
2060riscv_estimate_arch_strlen1 (const riscv_subset_t *subset)
2061{
2062 if (subset == NULL)
2063 return 6; /* For rv32/rv64/rv128 and string terminator. */
2064
2065 return riscv_estimate_arch_strlen1 (subset->next)
2066 + strlen (subset->name)
2067 + riscv_estimate_digit (subset->major_version)
dcd709e0 2068 + 1 /* For version seperator 'p'. */
2dc8dd17
JW
2069 + riscv_estimate_digit (subset->minor_version)
2070 + 1 /* For underscore. */;
2071}
2072
2073/* Estimate the string length of this subset list. */
2074
2075static size_t
2076riscv_estimate_arch_strlen (const riscv_subset_list_t *subset_list)
2077{
2078 return riscv_estimate_arch_strlen1 (subset_list->head);
2079}
2080
2081/* Auxiliary function to convert subset info to string. */
2082
2083static void
2084riscv_arch_str1 (riscv_subset_t *subset,
2085 char *attr_str, char *buf, size_t bufsz)
2086{
2087 const char *underline = "_";
729a5353 2088 riscv_subset_t *subset_t = subset;
2dc8dd17 2089
729a5353 2090 if (subset_t == NULL)
2dc8dd17
JW
2091 return;
2092
dcd709e0 2093 /* No underline between rvXX and i/e. */
729a5353
NC
2094 if ((strcasecmp (subset_t->name, "i") == 0)
2095 || (strcasecmp (subset_t->name, "e") == 0))
2dc8dd17
JW
2096 underline = "";
2097
2098 snprintf (buf, bufsz, "%s%s%dp%d",
2099 underline,
729a5353
NC
2100 subset_t->name,
2101 subset_t->major_version,
2102 subset_t->minor_version);
2dc8dd17
JW
2103
2104 strncat (attr_str, buf, bufsz);
2105
729a5353
NC
2106 /* Skip 'i' extension after 'e', or skip extensions which
2107 versions are unknown. */
2108 while (subset_t->next
2109 && ((strcmp (subset_t->name, "e") == 0
2110 && strcmp (subset_t->next->name, "i") == 0)
2111 || subset_t->next->major_version == RISCV_UNKNOWN_VERSION
2112 || subset_t->next->minor_version == RISCV_UNKNOWN_VERSION))
2113 subset_t = subset_t->next;
2114
2115 riscv_arch_str1 (subset_t->next, attr_str, buf, bufsz);
2dc8dd17
JW
2116}
2117
dcd709e0 2118/* Convert subset information into string with explicit versions. */
2dc8dd17
JW
2119
2120char *
2121riscv_arch_str (unsigned xlen, const riscv_subset_list_t *subset)
2122{
2123 size_t arch_str_len = riscv_estimate_arch_strlen (subset);
2124 char *attr_str = xmalloc (arch_str_len);
2125 char *buf = xmalloc (arch_str_len);
2126
2127 snprintf (attr_str, arch_str_len, "rv%u", xlen);
2128
2129 riscv_arch_str1 (subset->head, attr_str, buf, arch_str_len);
2130 free (buf);
2131
2132 return attr_str;
2133}
edc77c59 2134
d3ffd7f7
NC
2135/* Copy the subset in the subset list. */
2136
2137static struct riscv_subset_t *
2138riscv_copy_subset (riscv_subset_list_t *subset_list,
2139 riscv_subset_t *subset)
2140{
2141 if (subset == NULL)
2142 return NULL;
2143
2144 riscv_subset_t *new = xmalloc (sizeof *new);
2145 new->name = xstrdup (subset->name);
2146 new->major_version = subset->major_version;
2147 new->minor_version = subset->minor_version;
2148 new->next = riscv_copy_subset (subset_list, subset->next);
2149
2150 if (subset->next == NULL)
2151 subset_list->tail = new;
2152
2153 return new;
2154}
2155
2156/* Copy the subset list. */
2157
2158riscv_subset_list_t *
2159riscv_copy_subset_list (riscv_subset_list_t *subset_list)
2160{
2161 riscv_subset_list_t *new = xmalloc (sizeof *new);
2162 new->head = riscv_copy_subset (new, subset_list->head);
2163 return new;
2164}
2165
edc77c59
NC
2166/* Remove the SUBSET from the subset list. */
2167
2168static void
2169riscv_remove_subset (riscv_subset_list_t *subset_list,
2170 const char *subset)
2171{
2172 riscv_subset_t *current = subset_list->head;
2173 riscv_subset_t *pre = NULL;
2174 for (; current != NULL; pre = current, current = current->next)
2175 {
2176 if (strcmp (current->name, subset) == 0)
2177 {
2178 if (pre == NULL)
2179 subset_list->head = current->next;
2180 else
2181 pre->next = current->next;
2182 if (current->next == NULL)
2183 subset_list->tail = pre;
2184 free ((void *) current->name);
2185 free (current);
2186 break;
2187 }
2188 }
2189}
2190
2191/* Add/Remove an extension to/from the subset list. This is used for
d3ffd7f7 2192 the .option rvc or norvc, and .option arch directives. */
edc77c59
NC
2193
2194bool
2195riscv_update_subset (riscv_parse_subset_t *rps,
d3ffd7f7 2196 const char *str)
edc77c59 2197{
d3ffd7f7 2198 const char *p = str;
edc77c59 2199
d3ffd7f7 2200 do
edc77c59 2201 {
d3ffd7f7
NC
2202 int major_version = RISCV_UNKNOWN_VERSION;
2203 int minor_version = RISCV_UNKNOWN_VERSION;
2204
2205 bool removed = false;
de3a913d 2206 switch (*p)
d3ffd7f7
NC
2207 {
2208 case '+': removed = false; break;
2209 case '-': removed = true; break;
de3a913d 2210 default:
d3ffd7f7
NC
2211 riscv_release_subset_list (rps->subset_list);
2212 return riscv_parse_subset (rps, p);
d3ffd7f7 2213 }
de3a913d 2214 ++p;
d3ffd7f7
NC
2215
2216 char *subset = xstrdup (p);
2217 char *q = subset;
2218 const char *end_of_version;
2219 /* Extract the whole prefixed extension by ','. */
2220 while (*q != '\0' && *q != ',')
2221 q++;
577bf39f 2222
d3ffd7f7
NC
2223 /* Look forward to the first letter which is not <major>p<minor>. */
2224 bool find_any_version = false;
2225 bool find_minor_version = false;
577bf39f
NC
2226 size_t len = q - subset;
2227 size_t i;
2228 for (i = len; i > 0; i--)
d3ffd7f7
NC
2229 {
2230 q--;
2231 if (ISDIGIT (*q))
2232 find_any_version = true;
2233 else if (find_any_version
2234 && !find_minor_version
2235 && *q == 'p'
2236 && ISDIGIT (*(q - 1)))
2237 find_minor_version = true;
2238 else
2239 break;
2240 }
577bf39f
NC
2241 if (len > 0)
2242 q++;
2243
d3ffd7f7
NC
2244 /* Check if the end of extension is 'p' or not. If yes, then
2245 the second letter from the end cannot be number. */
577bf39f 2246 if (len > 1 && *(q - 1) == 'p' && ISDIGIT (*(q - 2)))
d3ffd7f7
NC
2247 {
2248 *q = '\0';
2249 rps->error_handler
2250 (_("invalid ISA extension ends with <number>p "
2251 "in .option arch `%s'"), str);
2252 free (subset);
2253 return false;
2254 }
577bf39f 2255
d3ffd7f7
NC
2256 end_of_version =
2257 riscv_parsing_subset_version (q, &major_version, &minor_version);
2258 *q = '\0';
2259 if (end_of_version == NULL)
2260 {
2261 free (subset);
2262 return false;
2263 }
2264
2265 if (strlen (subset) == 0
2266 || (strlen (subset) == 1
2267 && riscv_ext_order[(*subset - 'a')] == 0)
2268 || (strlen (subset) > 1
2269 && rps->check_unknown_prefixed_ext
2270 && !riscv_recognized_prefixed_ext (subset)))
edc77c59
NC
2271 {
2272 rps->error_handler
d3ffd7f7
NC
2273 (_("unknown ISA extension `%s' in .option arch `%s'"),
2274 subset, str);
2275 free (subset);
edc77c59
NC
2276 return false;
2277 }
d3ffd7f7 2278
de3a913d
NC
2279 if (strcmp (subset, "i") == 0
2280 || strcmp (subset, "e") == 0
2281 || strcmp (subset, "g") == 0)
d3ffd7f7 2282 {
de3a913d
NC
2283 rps->error_handler
2284 (_("cannot + or - base extension `%s' in .option "
2285 "arch `%s'"), subset, str);
2286 free (subset);
2287 return false;
d3ffd7f7 2288 }
de3a913d
NC
2289
2290 if (removed)
2291 riscv_remove_subset (rps->subset_list, subset);
d3ffd7f7
NC
2292 else
2293 riscv_parse_add_subset (rps, subset, major_version, minor_version, true);
2294 p += end_of_version - subset;
2295 free (subset);
edc77c59 2296 }
d3ffd7f7
NC
2297 while (*p++ == ',');
2298
edc77c59
NC
2299 riscv_parse_add_implicit_subsets (rps);
2300 return riscv_parse_check_conflicts (rps);
2301}
f786c359
NC
2302
2303/* Check if the FEATURE subset is supported or not in the subset list.
2304 Return true if it is supported; Otherwise, return false. */
2305
2306bool
2307riscv_subset_supports (riscv_parse_subset_t *rps,
2308 const char *feature)
2309{
2310 struct riscv_subset_t *subset;
2311 return riscv_lookup_subset (rps->subset_list, feature, &subset);
2312}
2313
2314/* Each instuction is belonged to an instruction class INSN_CLASS_*.
2315 Call riscv_subset_supports to make sure if the instuction is valid. */
2316
2317bool
2318riscv_multi_subset_supports (riscv_parse_subset_t *rps,
2319 enum riscv_insn_class insn_class)
2320{
2321 switch (insn_class)
2322 {
2323 case INSN_CLASS_I:
2324 return riscv_subset_supports (rps, "i");
41d6ac5d
TO
2325 case INSN_CLASS_ZICBOM:
2326 return riscv_subset_supports (rps, "zicbom");
3b374308
TO
2327 case INSN_CLASS_ZICBOP:
2328 return riscv_subset_supports (rps, "zicbop");
41d6ac5d
TO
2329 case INSN_CLASS_ZICBOZ:
2330 return riscv_subset_supports (rps, "zicboz");
f786c359
NC
2331 case INSN_CLASS_ZICSR:
2332 return riscv_subset_supports (rps, "zicsr");
2333 case INSN_CLASS_ZIFENCEI:
2334 return riscv_subset_supports (rps, "zifencei");
2335 case INSN_CLASS_ZIHINTPAUSE:
2336 return riscv_subset_supports (rps, "zihintpause");
2337 case INSN_CLASS_M:
2338 return riscv_subset_supports (rps, "m");
2339 case INSN_CLASS_A:
2340 return riscv_subset_supports (rps, "a");
2341 case INSN_CLASS_F:
2342 return riscv_subset_supports (rps, "f");
2343 case INSN_CLASS_D:
2344 return riscv_subset_supports (rps, "d");
2345 case INSN_CLASS_Q:
2346 return riscv_subset_supports (rps, "q");
2347 case INSN_CLASS_C:
2348 return riscv_subset_supports (rps, "c");
2349 case INSN_CLASS_F_AND_C:
2350 return (riscv_subset_supports (rps, "f")
2351 && riscv_subset_supports (rps, "c"));
2352 case INSN_CLASS_D_AND_C:
2353 return (riscv_subset_supports (rps, "d")
2354 && riscv_subset_supports (rps, "c"));
de83e514 2355 case INSN_CLASS_F_OR_ZFINX:
2356 return (riscv_subset_supports (rps, "f")
2357 || riscv_subset_supports (rps, "zfinx"));
2358 case INSN_CLASS_D_OR_ZDINX:
2359 return (riscv_subset_supports (rps, "d")
2360 || riscv_subset_supports (rps, "zdinx"));
2361 case INSN_CLASS_Q_OR_ZQINX:
2362 return (riscv_subset_supports (rps, "q")
2363 || riscv_subset_supports (rps, "zqinx"));
035784e3
NC
2364 case INSN_CLASS_ZFH:
2365 return riscv_subset_supports (rps, "zfh");
2366 case INSN_CLASS_D_AND_ZFH:
2367 return (riscv_subset_supports (rps, "d")
2368 && riscv_subset_supports (rps, "zfh") );
2369 case INSN_CLASS_Q_AND_ZFH:
2370 return (riscv_subset_supports (rps, "q")
2371 && riscv_subset_supports (rps, "zfh"));
f786c359
NC
2372 case INSN_CLASS_ZBA:
2373 return riscv_subset_supports (rps, "zba");
2374 case INSN_CLASS_ZBB:
2375 return riscv_subset_supports (rps, "zbb");
2376 case INSN_CLASS_ZBC:
2377 return riscv_subset_supports (rps, "zbc");
2378 case INSN_CLASS_ZBS:
2379 return riscv_subset_supports (rps, "zbs");
3d1cafa0 2380 case INSN_CLASS_ZBKB:
2381 return riscv_subset_supports (rps, "zbkb");
2382 case INSN_CLASS_ZBKC:
2383 return riscv_subset_supports (rps, "zbkc");
2384 case INSN_CLASS_ZBKX:
2385 return riscv_subset_supports (rps, "zbkx");
2386 case INSN_CLASS_ZBB_OR_ZBKB:
2387 return (riscv_subset_supports (rps, "zbb")
2388 || riscv_subset_supports (rps, "zbkb"));
2389 case INSN_CLASS_ZBC_OR_ZBKC:
2390 return (riscv_subset_supports (rps, "zbc")
2391 || riscv_subset_supports (rps, "zbkc"));
2392 case INSN_CLASS_ZKND:
2393 return riscv_subset_supports (rps, "zknd");
2394 case INSN_CLASS_ZKNE:
2395 return riscv_subset_supports (rps, "zkne");
2396 case INSN_CLASS_ZKNH:
2397 return riscv_subset_supports (rps, "zknh");
2398 case INSN_CLASS_ZKND_OR_ZKNE:
2399 return (riscv_subset_supports (rps, "zknd")
2400 || riscv_subset_supports (rps, "zkne"));
2401 case INSN_CLASS_ZKSED:
2402 return riscv_subset_supports (rps, "zksed");
2403 case INSN_CLASS_ZKSH:
2404 return riscv_subset_supports (rps, "zksh");
65e4a99a
NC
2405 case INSN_CLASS_V:
2406 return (riscv_subset_supports (rps, "v")
2407 || riscv_subset_supports (rps, "zve64x")
2408 || riscv_subset_supports (rps, "zve32x"));
2409 case INSN_CLASS_ZVEF:
2410 return (riscv_subset_supports (rps, "v")
2411 || riscv_subset_supports (rps, "zve64d")
2412 || riscv_subset_supports (rps, "zve64f")
2413 || riscv_subset_supports (rps, "zve32f"));
23ff54c2
NC
2414 case INSN_CLASS_SVINVAL:
2415 return riscv_subset_supports (rps, "svinval");
f786c359
NC
2416 default:
2417 rps->error_handler
2418 (_("internal: unreachable INSN_CLASS_*"));
2419 return false;
2420 }
2421}
e4028336
PN
2422
2423/* Each instuction is belonged to an instruction class INSN_CLASS_*.
2424 Call riscv_subset_supports_ext to determine the missing extension. */
2425
2426const char *
2427riscv_multi_subset_supports_ext (riscv_parse_subset_t *rps,
2428 enum riscv_insn_class insn_class)
2429{
2430 switch (insn_class)
2431 {
2432 case INSN_CLASS_I:
2433 return "i";
2434 case INSN_CLASS_ZICSR:
2435 return "zicsr";
2436 case INSN_CLASS_ZIFENCEI:
2437 return "zifencei";
2438 case INSN_CLASS_ZIHINTPAUSE:
2439 return "zihintpause";
2440 case INSN_CLASS_M:
2441 return "m";
2442 case INSN_CLASS_A:
2443 return "a";
2444 case INSN_CLASS_F:
2445 return "f";
2446 case INSN_CLASS_D:
2447 return "d";
2448 case INSN_CLASS_Q:
2449 return "q";
2450 case INSN_CLASS_C:
2451 return "c";
2452 case INSN_CLASS_F_AND_C:
2453 if (!riscv_subset_supports (rps, "f")
2454 && !riscv_subset_supports (rps, "c"))
2455 return "f' and `c";
2456 else if (!riscv_subset_supports (rps, "f"))
2457 return "f";
2458 else
2459 return "c";
2460 case INSN_CLASS_D_AND_C:
2461 if (!riscv_subset_supports (rps, "d")
2462 && !riscv_subset_supports (rps, "c"))
2463 return "d' and `c";
2464 else if (!riscv_subset_supports (rps, "d"))
2465 return "d";
2466 else
2467 return "c";
2468 case INSN_CLASS_F_OR_ZFINX:
2469 return "f' or `zfinx";
2470 case INSN_CLASS_D_OR_ZDINX:
2471 return "d' or `zdinx";
2472 case INSN_CLASS_Q_OR_ZQINX:
2473 return "q' or `zqinx";
2474 case INSN_CLASS_ZBA:
2475 return "zba";
2476 case INSN_CLASS_ZBB:
2477 return "zbb";
2478 case INSN_CLASS_ZBC:
2479 return "zbc";
2480 case INSN_CLASS_ZBS:
2481 return "zbs";
2482 case INSN_CLASS_ZBKB:
2483 return "zbkb";
2484 case INSN_CLASS_ZBKC:
2485 return "zbkc";
2486 case INSN_CLASS_ZBKX:
2487 return "zbkx";
2488 case INSN_CLASS_ZBB_OR_ZBKB:
2489 return "zbb' or `zbkb";
2490 case INSN_CLASS_ZBC_OR_ZBKC:
2491 return "zbc' or `zbkc";
2492 case INSN_CLASS_ZKND:
2493 return "zknd";
2494 case INSN_CLASS_ZKNE:
2495 return "zkne";
2496 case INSN_CLASS_ZKNH:
2497 return "zknh";
2498 case INSN_CLASS_ZKND_OR_ZKNE:
2499 return "zknd' or `zkne";
2500 case INSN_CLASS_ZKSED:
2501 return "zksed";
2502 case INSN_CLASS_ZKSH:
2503 return "zksh";
2504 case INSN_CLASS_V:
2505 return "v' or `zve64x' or `zve32x";
2506 case INSN_CLASS_ZVEF:
2507 return "v' or `zve64d' or `zve64f' or `zve32f";
2508 case INSN_CLASS_SVINVAL:
2509 return "svinval";
2510 default:
2511 rps->error_handler
2512 (_("internal: unreachable INSN_CLASS_*"));
2513 return NULL;
2514 }
2515}