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