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