]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blame - bfd/elfxx-riscv.c
Note that at least dejagnu version 1.5.3 is required in order to be ale to run the...
[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 },
eb668e50 1165 {"zawrs", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
035784e3 1166 {"zfh", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
045f385d 1167 {"zfhmin", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
da05b70e 1168 {"zfinx", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1169 {"zdinx", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1170 {"zqinx", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
292c7bf8 1171 {"zhinx", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
045f385d 1172 {"zhinxmin", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
586dcfc8
PT
1173 {"zbb", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1174 {"zba", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1175 {"zbc", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
dfdba097 1176 {"zbs", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1177 {"zbkb", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1178 {"zbkc", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1179 {"zbkx", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1180 {"zk", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1181 {"zkn", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1182 {"zknd", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1183 {"zkne", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1184 {"zknh", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1185 {"zkr", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1186 {"zks", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1187 {"zksed", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1188 {"zksh", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1189 {"zkt", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
65e4a99a
NC
1190 {"zve32x", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1191 {"zve32f", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1192 {"zve32d", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1193 {"zve64x", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1194 {"zve64f", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1195 {"zve64d", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1196 {"zvl32b", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1197 {"zvl64b", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1198 {"zvl128b", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1199 {"zvl256b", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1200 {"zvl512b", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1201 {"zvl1024b", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1202 {"zvl2048b", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1203 {"zvl4096b", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1204 {"zvl8192b", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1205 {"zvl16384b", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1206 {"zvl32768b", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1207 {"zvl65536b", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
96462b01 1208 {"ztso", ISA_SPEC_CLASS_DRAFT, 0, 1, 0 },
c9f27991
NC
1209 {NULL, 0, 0, 0, 0}
1210};
1211
1212static struct riscv_supported_ext riscv_supported_std_s_ext[] =
1213{
d6b99a80 1214 {"smepmp", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
6af47b08 1215 {"smstateen", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
713f3708 1216 {"sscofpmf", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
766077c1 1217 {"sstc", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
23ff54c2 1218 {"svinval", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
d6b99a80
TO
1219 {"svnapot", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1220 {"svpbmt", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
c9f27991
NC
1221 {NULL, 0, 0, 0, 0}
1222};
1223
c9f27991 1224static struct riscv_supported_ext riscv_supported_std_zxm_ext[] =
e601909a 1225{
c9f27991
NC
1226 {NULL, 0, 0, 0, 0}
1227};
1228
fb173738
CM
1229static struct riscv_supported_ext riscv_supported_vendor_x_ext[] =
1230{
8254c3d2
CM
1231 {"xtheadba", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1232 {"xtheadbb", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1233 {"xtheadbs", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
a9ba8bc2 1234 {"xtheadcmo", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
73442230 1235 {"xtheadcondmov", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
f511f80f 1236 {"xtheadfmemidx", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
4041e11d 1237 {"xtheadmac", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
27cfd142 1238 {"xtheadmemidx", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
6e17ae62 1239 {"xtheadmempair", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
547c18d9 1240 {"xtheadsync", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
fb173738
CM
1241 {NULL, 0, 0, 0, 0}
1242};
1243
c9f27991
NC
1244const struct riscv_supported_ext *riscv_all_supported_ext[] =
1245{
1246 riscv_supported_std_ext,
1247 riscv_supported_std_z_ext,
1248 riscv_supported_std_s_ext,
c9f27991 1249 riscv_supported_std_zxm_ext,
fb173738 1250 riscv_supported_vendor_x_ext,
e601909a
NC
1251 NULL
1252};
1253
1254/* ISA extension prefixed name class. Must define them in parsing order. */
1255enum riscv_prefix_ext_class
1256{
1257 RV_ISA_CLASS_Z = 1,
1258 RV_ISA_CLASS_S,
e601909a
NC
1259 RV_ISA_CLASS_ZXM,
1260 RV_ISA_CLASS_X,
1261 RV_ISA_CLASS_UNKNOWN
1262};
1263
1264/* Record the strings of the prefixed extensions, and their corresponding
1265 classes. The more letters of the prefix string, the more forward it must
1266 be defined. Otherwise, the riscv_get_prefix_class will map it to the
1267 wrong classes. */
1268struct riscv_parse_prefix_config
1269{
1270 /* Class of the extension. */
1271 enum riscv_prefix_ext_class class;
1272
1273 /* Prefix string for error printing and internal parser usage. */
1274 const char *prefix;
1275};
1276static const struct riscv_parse_prefix_config parse_config[] =
1277{
1278 {RV_ISA_CLASS_ZXM, "zxm"},
1279 {RV_ISA_CLASS_Z, "z"},
1280 {RV_ISA_CLASS_S, "s"},
e601909a
NC
1281 {RV_ISA_CLASS_X, "x"},
1282 {RV_ISA_CLASS_UNKNOWN, NULL}
1283};
1284
1285/* Get the prefixed name class for the extensions, the class also
1286 means the order of the prefixed extensions. */
1287
1288static enum riscv_prefix_ext_class
1289riscv_get_prefix_class (const char *arch)
1290{
1291 int i = 0;
1292 while (parse_config[i].class != RV_ISA_CLASS_UNKNOWN)
1293 {
1294 if (strncmp (arch, parse_config[i].prefix,
1295 strlen (parse_config[i].prefix)) == 0)
1296 return parse_config[i].class;
1297 i++;
1298 }
1299 return RV_ISA_CLASS_UNKNOWN;
1300}
1301
1302/* Check KNOWN_EXTS to see if the EXT is supported. */
1303
1304static bool
1305riscv_known_prefixed_ext (const char *ext,
c9f27991 1306 struct riscv_supported_ext *known_exts)
e601909a
NC
1307{
1308 size_t i;
c9f27991
NC
1309 for (i = 0; known_exts[i].name != NULL; ++i)
1310 if (strcmp (ext, known_exts[i].name) == 0)
e601909a
NC
1311 return true;
1312 return false;
1313}
7ef19aa6 1314
69a61890
NC
1315/* Check whether the prefixed extension is recognized or not. Return
1316 true if recognized, otehrwise return false. */
e601909a
NC
1317
1318static bool
69a61890 1319riscv_recognized_prefixed_ext (const char *ext)
e601909a
NC
1320{
1321 enum riscv_prefix_ext_class class = riscv_get_prefix_class (ext);
1322 switch (class)
1323 {
1324 case RV_ISA_CLASS_Z:
c9f27991 1325 return riscv_known_prefixed_ext (ext, riscv_supported_std_z_ext);
e601909a 1326 case RV_ISA_CLASS_ZXM:
c9f27991 1327 return riscv_known_prefixed_ext (ext, riscv_supported_std_zxm_ext);
e601909a 1328 case RV_ISA_CLASS_S:
c9f27991 1329 return riscv_known_prefixed_ext (ext, riscv_supported_std_s_ext);
e601909a 1330 case RV_ISA_CLASS_X:
69a61890 1331 /* Only the single x is unrecognized. */
e601909a
NC
1332 if (strcmp (ext, "x") != 0)
1333 return true;
1334 default:
1335 break;
1336 }
1337 return false;
1338}
1339
3a3e333f 1340/* Canonical order for single letter extensions. */
1176bc38 1341static const char riscv_ext_canonical_order[] = "eigmafdqlcbkjtpvnh";
3a3e333f 1342
e601909a 1343/* Array is used to compare the orders of standard extensions quickly. */
dfe92496
NC
1344static int riscv_ext_order[26] = {0};
1345
e601909a
NC
1346/* Init the riscv_ext_order array. */
1347
1348static void
1349riscv_init_ext_order (void)
1350{
1351 static bool inited = false;
e601909a
NC
1352 if (inited)
1353 return;
1354
1355 /* The orders of all standard extensions are positive. */
c9f27991 1356 int order = 1;
e601909a 1357
3a3e333f
KC
1358 for (const char *ext = &riscv_ext_canonical_order[0]; *ext; ++ext)
1359 riscv_ext_order[(*ext - 'a')] = order++;
e601909a
NC
1360
1361 /* Some of the prefixed keyword are not single letter, so we set
1362 their prefixed orders in the riscv_compare_subsets directly,
1363 not through the riscv_ext_order. */
1364
1365 inited = true;
1366}
1367
dfe92496
NC
1368/* Similar to the strcmp. It returns an integer less than, equal to,
1369 or greater than zero if `subset2` is found, respectively, to be less
e601909a
NC
1370 than, to match, or be greater than `subset1`.
1371
1372 The order values,
1373 Zero: Preserved keywords.
1374 Positive number: Standard extensions.
1375 Negative number: Prefixed keywords. */
dfe92496 1376
4c0e540e 1377int
dfe92496 1378riscv_compare_subsets (const char *subset1, const char *subset2)
7ef19aa6 1379{
dfe92496
NC
1380 int order1 = riscv_ext_order[(*subset1 - 'a')];
1381 int order2 = riscv_ext_order[(*subset2 - 'a')];
7ef19aa6 1382
dfe92496
NC
1383 /* Compare the standard extension first. */
1384 if (order1 > 0 && order2 > 0)
1385 return order1 - order2;
7ef19aa6 1386
e601909a
NC
1387 /* Set the prefixed orders to negative numbers. */
1388 enum riscv_prefix_ext_class class1 = riscv_get_prefix_class (subset1);
1389 enum riscv_prefix_ext_class class2 = riscv_get_prefix_class (subset2);
1390
1391 if (class1 != RV_ISA_CLASS_UNKNOWN)
1392 order1 = - (int) class1;
1393 if (class2 != RV_ISA_CLASS_UNKNOWN)
1394 order2 = - (int) class2;
1395
1396 if (order1 == order2)
dfe92496
NC
1397 {
1398 /* Compare the standard addition z extensions. */
e601909a 1399 if (class1 == RV_ISA_CLASS_Z)
dfe92496
NC
1400 {
1401 order1 = riscv_ext_order[(*++subset1 - 'a')];
1402 order2 = riscv_ext_order[(*++subset2 - 'a')];
1403 if (order1 != order2)
1404 return order1 - order2;
1405 }
1406 return strcasecmp (++subset1, ++subset2);
1407 }
1408
1409 return order2 - order1;
1410}
1411
1412/* Find subset in the list. Return TRUE and set `current` to the subset
1413 if it is found. Otherwise, return FALSE and set `current` to the place
1414 where we should insert the subset. However, return FALSE with the NULL
1415 `current` means we should insert the subset at the head of subset list,
1416 if needed. */
1417
0a1b45a2 1418bool
dfe92496
NC
1419riscv_lookup_subset (const riscv_subset_list_t *subset_list,
1420 const char *subset,
1421 riscv_subset_t **current)
1422{
1423 riscv_subset_t *s, *pre_s = NULL;
1424
cb959bd8
NC
1425 /* If the subset is added in order, then just add it at the tail. */
1426 if (subset_list->tail != NULL
1427 && riscv_compare_subsets (subset_list->tail->name, subset) < 0)
1428 {
1429 *current = subset_list->tail;
1430 return false;
1431 }
1432
dfe92496
NC
1433 for (s = subset_list->head;
1434 s != NULL;
1435 pre_s = s, s = s->next)
1436 {
1437 int cmp = riscv_compare_subsets (s->name, subset);
1438 if (cmp == 0)
1439 {
1440 *current = s;
0a1b45a2 1441 return true;
dfe92496
NC
1442 }
1443 else if (cmp > 0)
1444 break;
1445 }
1446 *current = pre_s;
cb959bd8 1447
0a1b45a2 1448 return false;
7ef19aa6
NC
1449}
1450
cb959bd8
NC
1451/* Add the extension to the subset list. Search the
1452 list first, and then find the right place to add. */
7ef19aa6
NC
1453
1454void
1455riscv_add_subset (riscv_subset_list_t *subset_list,
1456 const char *subset,
1457 int major,
1458 int minor)
dfe92496
NC
1459{
1460 riscv_subset_t *current, *new;
1461
1462 if (riscv_lookup_subset (subset_list, subset, &current))
de3a913d 1463 return;
dfe92496
NC
1464
1465 new = xmalloc (sizeof *new);
1466 new->name = xstrdup (subset);
1467 new->major_version = major;
1468 new->minor_version = minor;
1469 new->next = NULL;
1470
1471 if (current != NULL)
1472 {
1473 new->next = current->next;
1474 current->next = new;
1475 }
1476 else
1477 {
1478 new->next = subset_list->head;
1479 subset_list->head = new;
1480 }
dfe92496 1481
cb959bd8
NC
1482 if (new->next == NULL)
1483 subset_list->tail = new;
1484}
dfe92496 1485
c9f27991
NC
1486/* Get the default versions from the riscv_supported_*ext tables. */
1487
1488static void
f786c359 1489riscv_get_default_ext_version (enum riscv_spec_class *default_isa_spec,
c9f27991
NC
1490 const char *name,
1491 int *major_version,
1492 int *minor_version)
1493{
f786c359
NC
1494 if (name == NULL
1495 || default_isa_spec == NULL
1496 || *default_isa_spec == ISA_SPEC_CLASS_NONE)
c9f27991
NC
1497 return;
1498
1499 struct riscv_supported_ext *table = NULL;
1500 enum riscv_prefix_ext_class class = riscv_get_prefix_class (name);
1501 switch (class)
1502 {
1503 case RV_ISA_CLASS_ZXM: table = riscv_supported_std_zxm_ext; break;
1504 case RV_ISA_CLASS_Z: table = riscv_supported_std_z_ext; break;
1505 case RV_ISA_CLASS_S: table = riscv_supported_std_s_ext; break;
fb173738 1506 case RV_ISA_CLASS_X: table = riscv_supported_vendor_x_ext; break;
c9f27991
NC
1507 default:
1508 table = riscv_supported_std_ext;
1509 }
1510
1511 int i = 0;
1512 while (table != NULL && table[i].name != NULL)
1513 {
1514 if (strcmp (table[i].name, name) == 0
1515 && (table[i].isa_spec_class == ISA_SPEC_CLASS_DRAFT
f786c359 1516 || table[i].isa_spec_class == *default_isa_spec))
c9f27991
NC
1517 {
1518 *major_version = table[i].major_version;
1519 *minor_version = table[i].minor_version;
1520 return;
1521 }
1522 i++;
1523 }
1524}
1525
cb959bd8 1526/* Find the default versions for the extension before adding them to
7ef19aa6
NC
1527 the subset list, if their versions are RISCV_UNKNOWN_VERSION.
1528 Afterwards, report errors if we can not find their default versions. */
1529
1530static void
1531riscv_parse_add_subset (riscv_parse_subset_t *rps,
1532 const char *subset,
1533 int major,
dfe92496 1534 int minor,
0a1b45a2 1535 bool implicit)
7ef19aa6
NC
1536{
1537 int major_version = major;
1538 int minor_version = minor;
1539
c9f27991 1540 if (major_version == RISCV_UNKNOWN_VERSION
7ef19aa6 1541 || minor_version == RISCV_UNKNOWN_VERSION)
c9f27991
NC
1542 riscv_get_default_ext_version (rps->isa_spec, subset,
1543 &major_version, &minor_version);
7ef19aa6 1544
f0bae255
NC
1545 /* We don't care the versions of the implicit extensions. */
1546 if (!implicit
dfe92496
NC
1547 && (major_version == RISCV_UNKNOWN_VERSION
1548 || minor_version == RISCV_UNKNOWN_VERSION))
7ef19aa6
NC
1549 {
1550 if (subset[0] == 'x')
1551 rps->error_handler
1552 (_("x ISA extension `%s' must be set with the versions"),
1553 subset);
aed44286
NC
1554 /* Allow old ISA spec can recognize zicsr and zifencei. */
1555 else if (strcmp (subset, "zicsr") != 0
1556 && strcmp (subset, "zifencei") != 0)
7ef19aa6
NC
1557 rps->error_handler
1558 (_("cannot find default versions of the ISA extension `%s'"),
1559 subset);
1560 return;
1561 }
1562
cb959bd8
NC
1563 riscv_add_subset (rps->subset_list, subset,
1564 major_version, minor_version);
7ef19aa6
NC
1565}
1566
1567/* Release subset list. */
1568
1569void
1570riscv_release_subset_list (riscv_subset_list_t *subset_list)
1571{
1572 while (subset_list->head != NULL)
1573 {
1574 riscv_subset_t *next = subset_list->head->next;
1575 free ((void *)subset_list->head->name);
1576 free (subset_list->head);
1577 subset_list->head = next;
1578 }
1579
1580 subset_list->tail = NULL;
1581}
1582
d541518b 1583/* Parsing extension version.
1080bf78
JW
1584
1585 Return Value:
1586 Points to the end of version
1587
1588 Arguments:
1080bf78 1589 `p`: Curent parsing position.
7ef19aa6 1590 `major_version`: Parsed major version.
69a61890 1591 `minor_version`: Parsed minor version. */
1080bf78
JW
1592
1593static const char *
69a61890 1594riscv_parsing_subset_version (const char *p,
7ef19aa6 1595 int *major_version,
69a61890 1596 int *minor_version)
1080bf78 1597{
0a1b45a2 1598 bool major_p = true;
7ef19aa6 1599 int version = 0;
1080bf78
JW
1600 char np;
1601
8f595e9b
NC
1602 *major_version = 0;
1603 *minor_version = 0;
1604 for (; *p; ++p)
1080bf78
JW
1605 {
1606 if (*p == 'p')
1607 {
1608 np = *(p + 1);
1609
3a6a0158 1610 /* Might be beginning of `p` extension. */
1080bf78 1611 if (!ISDIGIT (np))
3a6a0158 1612 break;
1080bf78 1613
8f595e9b 1614 *major_version = version;
0a1b45a2 1615 major_p = false;
1080bf78
JW
1616 version = 0;
1617 }
1618 else if (ISDIGIT (*p))
1619 version = (version * 10) + (*p - '0');
1620 else
1621 break;
1622 }
1623
1624 if (major_p)
8f595e9b 1625 *major_version = version;
1080bf78 1626 else
8f595e9b 1627 *minor_version = version;
1080bf78 1628
7ef19aa6
NC
1629 /* We can not find any version in string. */
1630 if (*major_version == 0 && *minor_version == 0)
1631 {
1632 *major_version = RISCV_UNKNOWN_VERSION;
1633 *minor_version = RISCV_UNKNOWN_VERSION;
1634 }
1635
1080bf78
JW
1636 return p;
1637}
1638
1080bf78
JW
1639/* Parsing function for standard extensions.
1640
1641 Return Value:
1642 Points to the end of extensions.
1643
1644 Arguments:
d541518b 1645 `rps`: Hooks and status for parsing extensions.
cb959bd8 1646 `arch`: Full ISA string.
1080bf78
JW
1647 `p`: Curent parsing position. */
1648
1649static const char *
1650riscv_parse_std_ext (riscv_parse_subset_t *rps,
cb959bd8 1651 const char *arch,
8f595e9b 1652 const char *p)
1080bf78 1653{
1080bf78 1654 /* First letter must start with i, e or g. */
c9f27991 1655 if (*p != 'e' && *p != 'i' && *p != 'g')
1080bf78 1656 {
c9f27991
NC
1657 rps->error_handler
1658 (_("%s: first ISA extension must be `e', `i' or `g'"),
1659 arch);
1660 return NULL;
1080bf78
JW
1661 }
1662
8f595e9b 1663 while (p != NULL && *p != '\0')
1080bf78 1664 {
e601909a
NC
1665 /* Stop when we parsed the known prefix class. */
1666 enum riscv_prefix_ext_class class = riscv_get_prefix_class (p);
1667 if (class != RV_ISA_CLASS_UNKNOWN)
1080bf78
JW
1668 break;
1669
1670 if (*p == '_')
1671 {
1672 p++;
1673 continue;
1674 }
1675
c9f27991
NC
1676 bool implicit = false;
1677 int major = RISCV_UNKNOWN_VERSION;
1678 int minor = RISCV_UNKNOWN_VERSION;
1679 char subset[2] = {0, 0};
1680
1681 subset[0] = *p;
1080bf78 1682
c9f27991
NC
1683 /* Check if the standard extension is supported. */
1684 if (riscv_ext_order[(subset[0] - 'a')] == 0)
1080bf78 1685 {
c9f27991
NC
1686 rps->error_handler
1687 (_("%s: unknown standard ISA extension `%c'"),
1688 arch, subset[0]);
1080bf78
JW
1689 return NULL;
1690 }
1691
c9f27991
NC
1692 /* Checking canonical order. */
1693 if (rps->subset_list->tail != NULL
1694 && riscv_compare_subsets (rps->subset_list->tail->name, subset) > 0)
1695 {
1696 rps->error_handler
1697 (_("%s: standard ISA extension `%c' is not "
1698 "in canonical order"), arch, subset[0]);
1699 return NULL;
1700 }
1701
69a61890 1702 p = riscv_parsing_subset_version (++p, &major, &minor);
c9f27991
NC
1703 /* Added g as an implicit extension. */
1704 if (subset[0] == 'g')
1705 {
1706 implicit = true;
1707 major = RISCV_UNKNOWN_VERSION;
1708 minor = RISCV_UNKNOWN_VERSION;
1709 }
1710 riscv_parse_add_subset (rps, subset, major, minor, implicit);
1080bf78 1711 }
d541518b 1712
1080bf78
JW
1713 return p;
1714}
1715
d541518b
NC
1716/* Parsing function for prefixed extensions.
1717
1718 Return Value:
1719 Points to the end of extension.
1720
1721 Arguments:
1722 `rps`: Hooks and status for parsing extensions.
cb959bd8 1723 `arch`: Full ISA string.
e3839c10 1724 `p`: Curent parsing position. */
1080bf78
JW
1725
1726static const char *
403d1bd9 1727riscv_parse_prefixed_ext (riscv_parse_subset_t *rps,
cb959bd8 1728 const char *arch,
e601909a 1729 const char *p)
1080bf78 1730{
7ef19aa6
NC
1731 int major_version;
1732 int minor_version;
e601909a 1733 enum riscv_prefix_ext_class class;
1080bf78
JW
1734
1735 while (*p)
1736 {
1737 if (*p == '_')
1738 {
1739 p++;
1740 continue;
1741 }
1742
403d1bd9 1743 class = riscv_get_prefix_class (p);
e601909a
NC
1744 if (class == RV_ISA_CLASS_UNKNOWN)
1745 {
1746 rps->error_handler
cb959bd8
NC
1747 (_("%s: unknown prefix class for the ISA extension `%s'"),
1748 arch, p);
e601909a
NC
1749 return NULL;
1750 }
1080bf78
JW
1751
1752 char *subset = xstrdup (p);
1753 char *q = subset;
1754 const char *end_of_version;
1755
69a61890
NC
1756 /* Extract the whole prefixed extension by '_'. */
1757 while (*++q != '\0' && *q != '_')
1080bf78 1758 ;
69a61890
NC
1759 /* Look forward to the first letter which is not <major>p<minor>. */
1760 bool find_any_version = false;
1761 bool find_minor_version = false;
1762 while (1)
1763 {
1764 q--;
1765 if (ISDIGIT (*q))
1766 find_any_version = true;
1767 else if (find_any_version
1768 && !find_minor_version
1769 && *q == 'p'
1770 && ISDIGIT (*(q - 1)))
1771 find_minor_version = true;
1772 else
1773 break;
1774 }
1775 q++;
1776
1777 /* Check if the end of extension is 'p' or not. If yes, then
1778 the second letter from the end cannot be number. */
1779 if (*(q - 1) == 'p' && ISDIGIT (*(q - 2)))
1780 {
1781 *q = '\0';
1782 rps->error_handler
1783 (_("%s: invalid prefixed ISA extension `%s' ends with <number>p"),
1784 arch, subset);
1785 free (subset);
1786 return NULL;
1787 }
1080bf78
JW
1788
1789 end_of_version =
69a61890 1790 riscv_parsing_subset_version (q, &major_version, &minor_version);
1080bf78 1791 *q = '\0';
7ef19aa6
NC
1792 if (end_of_version == NULL)
1793 {
1794 free (subset);
1795 return NULL;
1796 }
1797
403d1bd9 1798 /* Check that the extension name is well-formed. */
fe1f847d 1799 if (rps->check_unknown_prefixed_ext
69a61890 1800 && !riscv_recognized_prefixed_ext (subset))
403d1bd9
JW
1801 {
1802 rps->error_handler
cb959bd8
NC
1803 (_("%s: unknown prefixed ISA extension `%s'"),
1804 arch, subset);
403d1bd9
JW
1805 free (subset);
1806 return NULL;
1807 }
1808
7ef19aa6
NC
1809 riscv_parse_add_subset (rps, subset,
1810 major_version,
0a1b45a2 1811 minor_version, false);
1080bf78 1812 p += end_of_version - subset;
e9cf3691 1813 free (subset);
1080bf78
JW
1814
1815 if (*p != '\0' && *p != '_')
1816 {
d541518b 1817 rps->error_handler
cb959bd8
NC
1818 (_("%s: prefixed ISA extension must separate with _"),
1819 arch);
1080bf78
JW
1820 return NULL;
1821 }
1822 }
1823
1824 return p;
1825}
1826
dcd709e0 1827/* Add the implicit extensions. */
dfe92496
NC
1828
1829static void
1830riscv_parse_add_implicit_subsets (riscv_parse_subset_t *rps)
1831{
7671eff8
NC
1832 struct riscv_implicit_subset *t = riscv_implicit_subsets;
1833 for (; t->subset_name; t++)
dfe92496 1834 {
7671eff8
NC
1835 riscv_subset_t *subset = NULL;
1836 if (riscv_lookup_subset (rps->subset_list, t->subset_name, &subset)
1837 && t->check_func (t->implicit_name, subset))
1838 riscv_parse_add_subset (rps, t->implicit_name,
1839 RISCV_UNKNOWN_VERSION,
1840 RISCV_UNKNOWN_VERSION, true);
00d4d1b0 1841 }
dfe92496
NC
1842}
1843
cb959bd8
NC
1844/* Check extensions conflicts. */
1845
1846static bool
1847riscv_parse_check_conflicts (riscv_parse_subset_t *rps)
1848{
1849 riscv_subset_t *subset = NULL;
1850 int xlen = *rps->xlen;
1851 bool no_conflict = true;
1852
1853 if (riscv_lookup_subset (rps->subset_list, "e", &subset)
1854 && xlen > 32)
1855 {
1856 rps->error_handler
1857 (_("rv%d does not support the `e' extension"), xlen);
1858 no_conflict = false;
1859 }
1860 if (riscv_lookup_subset (rps->subset_list, "q", &subset)
51498ab9
TO
1861 && (subset->major_version < 2 || (subset->major_version == 2
1862 && subset->minor_version < 2))
cb959bd8
NC
1863 && xlen < 64)
1864 {
51498ab9 1865 rps->error_handler (_("rv%d does not support the `q' extension"), xlen);
cb959bd8
NC
1866 no_conflict = false;
1867 }
1868 if (riscv_lookup_subset (rps->subset_list, "e", &subset)
1869 && riscv_lookup_subset (rps->subset_list, "f", &subset))
1870 {
1871 rps->error_handler
1872 (_("rv32e does not support the `f' extension"));
1873 no_conflict = false;
1874 }
da05b70e 1875 if (riscv_lookup_subset (rps->subset_list, "zfinx", &subset)
1876 && riscv_lookup_subset (rps->subset_list, "f", &subset))
1877 {
1878 rps->error_handler
045f385d 1879 (_("`zfinx' is conflict with the `f/d/q/zfh/zfhmin' extension"));
da05b70e 1880 no_conflict = false;
1881 }
65e4a99a
NC
1882
1883 bool support_zve = false;
1884 bool support_zvl = false;
1885 riscv_subset_t *s = rps->subset_list->head;
1886 for (; s != NULL; s = s->next)
1887 {
1888 if (!support_zve
1889 && strncmp (s->name, "zve", 3) == 0)
1890 support_zve = true;
1891 if (!support_zvl
1892 && strncmp (s->name, "zvl", 3) == 0)
1893 support_zvl = true;
1894 if (support_zve && support_zvl)
1895 break;
1896 }
1897 if (support_zvl && !support_zve)
1898 {
1899 rps->error_handler
1900 (_("zvl*b extensions need to enable either `v' or `zve' extension"));
1901 no_conflict = false;
1902 }
1903
cb959bd8
NC
1904 return no_conflict;
1905}
1906
c9f27991
NC
1907/* Set the default subset list according to the default_enable field
1908 of riscv_supported_*ext tables. */
1909
1910static void
1911riscv_set_default_arch (riscv_parse_subset_t *rps)
1912{
1913 unsigned long enable = EXT_DEFAULT;
1914 int i, j;
1915 for (i = 0; riscv_all_supported_ext[i] != NULL; i++)
1916 {
1917 const struct riscv_supported_ext *table = riscv_all_supported_ext[i];
1918 for (j = 0; table[j].name != NULL; j++)
1919 {
1920 bool implicit = false;
1921 if (strcmp (table[j].name, "g") == 0)
1922 implicit = true;
1923 if (table[j].default_enable & enable)
1924 riscv_parse_add_subset (rps, table[j].name,
1925 RISCV_UNKNOWN_VERSION,
1926 RISCV_UNKNOWN_VERSION, implicit);
1927 }
1928 }
1929}
1930
dcd709e0 1931/* Function for parsing ISA string.
1080bf78
JW
1932
1933 Return Value:
1934 Return TRUE on success.
1935
1936 Arguments:
d541518b 1937 `rps`: Hooks and status for parsing extensions.
dcd709e0 1938 `arch`: Full ISA string. */
1080bf78 1939
0a1b45a2 1940bool
1080bf78
JW
1941riscv_parse_subset (riscv_parse_subset_t *rps,
1942 const char *arch)
1943{
e8d4709e 1944 const char *p;
1080bf78 1945
c9f27991
NC
1946 /* Init the riscv_ext_order array to compare the order of extensions
1947 quickly. */
1948 riscv_init_ext_order ();
1949
1950 if (arch == NULL)
1951 {
1952 riscv_set_default_arch (rps);
1953 riscv_parse_add_implicit_subsets (rps);
1954 return riscv_parse_check_conflicts (rps);
1955 }
1956
e8d4709e
NC
1957 for (p = arch; *p != '\0'; p++)
1958 {
1959 if (ISUPPER (*p))
1960 {
1961 rps->error_handler
cb959bd8 1962 (_("%s: ISA string cannot contain uppercase letters"),
e8d4709e 1963 arch);
0a1b45a2 1964 return false;
e8d4709e
NC
1965 }
1966 }
1967
1968 p = arch;
3f3328b8 1969 if (startswith (p, "rv32"))
1080bf78
JW
1970 {
1971 *rps->xlen = 32;
1972 p += 4;
1973 }
3f3328b8 1974 else if (startswith (p, "rv64"))
1080bf78
JW
1975 {
1976 *rps->xlen = 64;
1977 p += 4;
1978 }
1979 else
1980 {
c9f27991
NC
1981 /* ISA string shouldn't be NULL or empty here. For linker,
1982 it might be empty when we failed to merge the ISA string
1983 in the riscv_merge_attributes. For assembler, we might
1984 give an empty string by .attribute arch, "" or -march=.
1985 However, We have already issued the correct error message
1986 in another side, so do not issue this error when the ISA
1987 string is empty. */
72bd6912
KC
1988 if (strlen (arch))
1989 rps->error_handler (
cb959bd8 1990 _("%s: ISA string must begin with rv32 or rv64"),
72bd6912 1991 arch);
0a1b45a2 1992 return false;
1080bf78
JW
1993 }
1994
1995 /* Parsing standard extension. */
1996 p = riscv_parse_std_ext (rps, arch, p);
1997
1998 if (p == NULL)
0a1b45a2 1999 return false;
1080bf78 2000
0f94906f
TO
2001 /* Parse prefixed extensions. */
2002 p = riscv_parse_prefixed_ext (rps, arch, p);
1080bf78 2003
0f94906f
TO
2004 if (p == NULL)
2005 return false;
1080bf78 2006
dfe92496
NC
2007 /* Finally add implicit extensions according to the current
2008 extensions. */
2009 riscv_parse_add_implicit_subsets (rps);
2010
d541518b 2011 /* Check the conflicts. */
cb959bd8 2012 return riscv_parse_check_conflicts (rps);
1080bf78 2013}
2dc8dd17
JW
2014
2015/* Return the number of digits for the input. */
2016
8f595e9b 2017size_t
2dc8dd17
JW
2018riscv_estimate_digit (unsigned num)
2019{
2020 size_t digit = 0;
2021 if (num == 0)
2022 return 1;
2023
2024 for (digit = 0; num ; num /= 10)
2025 digit++;
2026
2027 return digit;
2028}
2029
2030/* Auxiliary function to estimate string length of subset list. */
2031
2032static size_t
2033riscv_estimate_arch_strlen1 (const riscv_subset_t *subset)
2034{
2035 if (subset == NULL)
2036 return 6; /* For rv32/rv64/rv128 and string terminator. */
2037
2038 return riscv_estimate_arch_strlen1 (subset->next)
2039 + strlen (subset->name)
2040 + riscv_estimate_digit (subset->major_version)
dcd709e0 2041 + 1 /* For version seperator 'p'. */
2dc8dd17
JW
2042 + riscv_estimate_digit (subset->minor_version)
2043 + 1 /* For underscore. */;
2044}
2045
2046/* Estimate the string length of this subset list. */
2047
2048static size_t
2049riscv_estimate_arch_strlen (const riscv_subset_list_t *subset_list)
2050{
2051 return riscv_estimate_arch_strlen1 (subset_list->head);
2052}
2053
2054/* Auxiliary function to convert subset info to string. */
2055
2056static void
2057riscv_arch_str1 (riscv_subset_t *subset,
2058 char *attr_str, char *buf, size_t bufsz)
2059{
2060 const char *underline = "_";
729a5353 2061 riscv_subset_t *subset_t = subset;
2dc8dd17 2062
729a5353 2063 if (subset_t == NULL)
2dc8dd17
JW
2064 return;
2065
dcd709e0 2066 /* No underline between rvXX and i/e. */
729a5353
NC
2067 if ((strcasecmp (subset_t->name, "i") == 0)
2068 || (strcasecmp (subset_t->name, "e") == 0))
2dc8dd17
JW
2069 underline = "";
2070
2071 snprintf (buf, bufsz, "%s%s%dp%d",
2072 underline,
729a5353
NC
2073 subset_t->name,
2074 subset_t->major_version,
2075 subset_t->minor_version);
2dc8dd17
JW
2076
2077 strncat (attr_str, buf, bufsz);
2078
729a5353
NC
2079 /* Skip 'i' extension after 'e', or skip extensions which
2080 versions are unknown. */
2081 while (subset_t->next
2082 && ((strcmp (subset_t->name, "e") == 0
2083 && strcmp (subset_t->next->name, "i") == 0)
2084 || subset_t->next->major_version == RISCV_UNKNOWN_VERSION
2085 || subset_t->next->minor_version == RISCV_UNKNOWN_VERSION))
2086 subset_t = subset_t->next;
2087
2088 riscv_arch_str1 (subset_t->next, attr_str, buf, bufsz);
2dc8dd17
JW
2089}
2090
dcd709e0 2091/* Convert subset information into string with explicit versions. */
2dc8dd17
JW
2092
2093char *
2094riscv_arch_str (unsigned xlen, const riscv_subset_list_t *subset)
2095{
2096 size_t arch_str_len = riscv_estimate_arch_strlen (subset);
2097 char *attr_str = xmalloc (arch_str_len);
2098 char *buf = xmalloc (arch_str_len);
2099
2100 snprintf (attr_str, arch_str_len, "rv%u", xlen);
2101
2102 riscv_arch_str1 (subset->head, attr_str, buf, arch_str_len);
2103 free (buf);
2104
2105 return attr_str;
2106}
edc77c59 2107
d3ffd7f7
NC
2108/* Copy the subset in the subset list. */
2109
2110static struct riscv_subset_t *
2111riscv_copy_subset (riscv_subset_list_t *subset_list,
2112 riscv_subset_t *subset)
2113{
2114 if (subset == NULL)
2115 return NULL;
2116
2117 riscv_subset_t *new = xmalloc (sizeof *new);
2118 new->name = xstrdup (subset->name);
2119 new->major_version = subset->major_version;
2120 new->minor_version = subset->minor_version;
2121 new->next = riscv_copy_subset (subset_list, subset->next);
2122
2123 if (subset->next == NULL)
2124 subset_list->tail = new;
2125
2126 return new;
2127}
2128
2129/* Copy the subset list. */
2130
2131riscv_subset_list_t *
2132riscv_copy_subset_list (riscv_subset_list_t *subset_list)
2133{
2134 riscv_subset_list_t *new = xmalloc (sizeof *new);
2135 new->head = riscv_copy_subset (new, subset_list->head);
2136 return new;
2137}
2138
edc77c59
NC
2139/* Remove the SUBSET from the subset list. */
2140
2141static void
2142riscv_remove_subset (riscv_subset_list_t *subset_list,
2143 const char *subset)
2144{
2145 riscv_subset_t *current = subset_list->head;
2146 riscv_subset_t *pre = NULL;
2147 for (; current != NULL; pre = current, current = current->next)
2148 {
2149 if (strcmp (current->name, subset) == 0)
2150 {
2151 if (pre == NULL)
2152 subset_list->head = current->next;
2153 else
2154 pre->next = current->next;
2155 if (current->next == NULL)
2156 subset_list->tail = pre;
2157 free ((void *) current->name);
2158 free (current);
2159 break;
2160 }
2161 }
2162}
2163
2164/* Add/Remove an extension to/from the subset list. This is used for
d3ffd7f7 2165 the .option rvc or norvc, and .option arch directives. */
edc77c59
NC
2166
2167bool
2168riscv_update_subset (riscv_parse_subset_t *rps,
d3ffd7f7 2169 const char *str)
edc77c59 2170{
d3ffd7f7 2171 const char *p = str;
edc77c59 2172
d3ffd7f7 2173 do
edc77c59 2174 {
d3ffd7f7
NC
2175 int major_version = RISCV_UNKNOWN_VERSION;
2176 int minor_version = RISCV_UNKNOWN_VERSION;
2177
2178 bool removed = false;
de3a913d 2179 switch (*p)
d3ffd7f7
NC
2180 {
2181 case '+': removed = false; break;
2182 case '-': removed = true; break;
de3a913d 2183 default:
d3ffd7f7
NC
2184 riscv_release_subset_list (rps->subset_list);
2185 return riscv_parse_subset (rps, p);
d3ffd7f7 2186 }
de3a913d 2187 ++p;
d3ffd7f7
NC
2188
2189 char *subset = xstrdup (p);
2190 char *q = subset;
2191 const char *end_of_version;
2192 /* Extract the whole prefixed extension by ','. */
2193 while (*q != '\0' && *q != ',')
2194 q++;
577bf39f 2195
d3ffd7f7
NC
2196 /* Look forward to the first letter which is not <major>p<minor>. */
2197 bool find_any_version = false;
2198 bool find_minor_version = false;
577bf39f
NC
2199 size_t len = q - subset;
2200 size_t i;
2201 for (i = len; i > 0; i--)
d3ffd7f7
NC
2202 {
2203 q--;
2204 if (ISDIGIT (*q))
2205 find_any_version = true;
2206 else if (find_any_version
2207 && !find_minor_version
2208 && *q == 'p'
2209 && ISDIGIT (*(q - 1)))
2210 find_minor_version = true;
2211 else
2212 break;
2213 }
577bf39f
NC
2214 if (len > 0)
2215 q++;
2216
d3ffd7f7
NC
2217 /* Check if the end of extension is 'p' or not. If yes, then
2218 the second letter from the end cannot be number. */
577bf39f 2219 if (len > 1 && *(q - 1) == 'p' && ISDIGIT (*(q - 2)))
d3ffd7f7
NC
2220 {
2221 *q = '\0';
2222 rps->error_handler
2223 (_("invalid ISA extension ends with <number>p "
2224 "in .option arch `%s'"), str);
2225 free (subset);
2226 return false;
2227 }
577bf39f 2228
d3ffd7f7
NC
2229 end_of_version =
2230 riscv_parsing_subset_version (q, &major_version, &minor_version);
2231 *q = '\0';
2232 if (end_of_version == NULL)
2233 {
2234 free (subset);
2235 return false;
2236 }
2237
2238 if (strlen (subset) == 0
2239 || (strlen (subset) == 1
2240 && riscv_ext_order[(*subset - 'a')] == 0)
2241 || (strlen (subset) > 1
2242 && rps->check_unknown_prefixed_ext
2243 && !riscv_recognized_prefixed_ext (subset)))
edc77c59
NC
2244 {
2245 rps->error_handler
d3ffd7f7
NC
2246 (_("unknown ISA extension `%s' in .option arch `%s'"),
2247 subset, str);
2248 free (subset);
edc77c59
NC
2249 return false;
2250 }
d3ffd7f7 2251
de3a913d
NC
2252 if (strcmp (subset, "i") == 0
2253 || strcmp (subset, "e") == 0
2254 || strcmp (subset, "g") == 0)
d3ffd7f7 2255 {
de3a913d
NC
2256 rps->error_handler
2257 (_("cannot + or - base extension `%s' in .option "
2258 "arch `%s'"), subset, str);
2259 free (subset);
2260 return false;
d3ffd7f7 2261 }
de3a913d
NC
2262
2263 if (removed)
2264 riscv_remove_subset (rps->subset_list, subset);
d3ffd7f7
NC
2265 else
2266 riscv_parse_add_subset (rps, subset, major_version, minor_version, true);
2267 p += end_of_version - subset;
2268 free (subset);
edc77c59 2269 }
d3ffd7f7
NC
2270 while (*p++ == ',');
2271
edc77c59
NC
2272 riscv_parse_add_implicit_subsets (rps);
2273 return riscv_parse_check_conflicts (rps);
2274}
f786c359
NC
2275
2276/* Check if the FEATURE subset is supported or not in the subset list.
2277 Return true if it is supported; Otherwise, return false. */
2278
2279bool
2280riscv_subset_supports (riscv_parse_subset_t *rps,
2281 const char *feature)
2282{
2283 struct riscv_subset_t *subset;
2284 return riscv_lookup_subset (rps->subset_list, feature, &subset);
2285}
2286
2287/* Each instuction is belonged to an instruction class INSN_CLASS_*.
2288 Call riscv_subset_supports to make sure if the instuction is valid. */
2289
2290bool
2291riscv_multi_subset_supports (riscv_parse_subset_t *rps,
2292 enum riscv_insn_class insn_class)
2293{
2294 switch (insn_class)
2295 {
2296 case INSN_CLASS_I:
2297 return riscv_subset_supports (rps, "i");
41d6ac5d
TO
2298 case INSN_CLASS_ZICBOM:
2299 return riscv_subset_supports (rps, "zicbom");
3b374308
TO
2300 case INSN_CLASS_ZICBOP:
2301 return riscv_subset_supports (rps, "zicbop");
41d6ac5d
TO
2302 case INSN_CLASS_ZICBOZ:
2303 return riscv_subset_supports (rps, "zicboz");
f786c359
NC
2304 case INSN_CLASS_ZICSR:
2305 return riscv_subset_supports (rps, "zicsr");
2306 case INSN_CLASS_ZIFENCEI:
2307 return riscv_subset_supports (rps, "zifencei");
2308 case INSN_CLASS_ZIHINTPAUSE:
2309 return riscv_subset_supports (rps, "zihintpause");
2310 case INSN_CLASS_M:
2311 return riscv_subset_supports (rps, "m");
0938b032
TO
2312 case INSN_CLASS_ZMMUL:
2313 return riscv_subset_supports (rps, "zmmul");
f786c359
NC
2314 case INSN_CLASS_A:
2315 return riscv_subset_supports (rps, "a");
eb668e50
CM
2316 case INSN_CLASS_ZAWRS:
2317 return riscv_subset_supports (rps, "zawrs");
f786c359
NC
2318 case INSN_CLASS_F:
2319 return riscv_subset_supports (rps, "f");
2320 case INSN_CLASS_D:
2321 return riscv_subset_supports (rps, "d");
2322 case INSN_CLASS_Q:
2323 return riscv_subset_supports (rps, "q");
2324 case INSN_CLASS_C:
2325 return riscv_subset_supports (rps, "c");
2326 case INSN_CLASS_F_AND_C:
2327 return (riscv_subset_supports (rps, "f")
2328 && riscv_subset_supports (rps, "c"));
2329 case INSN_CLASS_D_AND_C:
2330 return (riscv_subset_supports (rps, "d")
2331 && riscv_subset_supports (rps, "c"));
de83e514 2332 case INSN_CLASS_F_OR_ZFINX:
2333 return (riscv_subset_supports (rps, "f")
2334 || riscv_subset_supports (rps, "zfinx"));
2335 case INSN_CLASS_D_OR_ZDINX:
2336 return (riscv_subset_supports (rps, "d")
2337 || riscv_subset_supports (rps, "zdinx"));
2338 case INSN_CLASS_Q_OR_ZQINX:
2339 return (riscv_subset_supports (rps, "q")
2340 || riscv_subset_supports (rps, "zqinx"));
292c7bf8 2341 case INSN_CLASS_ZFH_OR_ZHINX:
045f385d
TO
2342 return (riscv_subset_supports (rps, "zfh")
2343 || riscv_subset_supports (rps, "zhinx"));
2344 case INSN_CLASS_ZFHMIN:
2345 return riscv_subset_supports (rps, "zfhmin");
2346 case INSN_CLASS_ZFHMIN_OR_ZHINXMIN:
2347 return (riscv_subset_supports (rps, "zfhmin")
2348 || riscv_subset_supports (rps, "zhinxmin"));
2349 case INSN_CLASS_ZFHMIN_AND_D:
2350 return ((riscv_subset_supports (rps, "zfhmin")
2351 && riscv_subset_supports (rps, "d"))
2352 || (riscv_subset_supports (rps, "zhinxmin")
2353 && riscv_subset_supports (rps, "zdinx")));
2354 case INSN_CLASS_ZFHMIN_AND_Q:
2355 return ((riscv_subset_supports (rps, "zfhmin")
2356 && riscv_subset_supports (rps, "q"))
2357 || (riscv_subset_supports (rps, "zhinxmin")
2358 && riscv_subset_supports (rps, "zqinx")));
f786c359
NC
2359 case INSN_CLASS_ZBA:
2360 return riscv_subset_supports (rps, "zba");
2361 case INSN_CLASS_ZBB:
2362 return riscv_subset_supports (rps, "zbb");
2363 case INSN_CLASS_ZBC:
2364 return riscv_subset_supports (rps, "zbc");
2365 case INSN_CLASS_ZBS:
2366 return riscv_subset_supports (rps, "zbs");
3d1cafa0 2367 case INSN_CLASS_ZBKB:
2368 return riscv_subset_supports (rps, "zbkb");
2369 case INSN_CLASS_ZBKC:
2370 return riscv_subset_supports (rps, "zbkc");
2371 case INSN_CLASS_ZBKX:
2372 return riscv_subset_supports (rps, "zbkx");
2373 case INSN_CLASS_ZBB_OR_ZBKB:
2374 return (riscv_subset_supports (rps, "zbb")
2375 || riscv_subset_supports (rps, "zbkb"));
2376 case INSN_CLASS_ZBC_OR_ZBKC:
2377 return (riscv_subset_supports (rps, "zbc")
2378 || riscv_subset_supports (rps, "zbkc"));
2379 case INSN_CLASS_ZKND:
2380 return riscv_subset_supports (rps, "zknd");
2381 case INSN_CLASS_ZKNE:
2382 return riscv_subset_supports (rps, "zkne");
2383 case INSN_CLASS_ZKNH:
2384 return riscv_subset_supports (rps, "zknh");
2385 case INSN_CLASS_ZKND_OR_ZKNE:
2386 return (riscv_subset_supports (rps, "zknd")
2387 || riscv_subset_supports (rps, "zkne"));
2388 case INSN_CLASS_ZKSED:
2389 return riscv_subset_supports (rps, "zksed");
2390 case INSN_CLASS_ZKSH:
2391 return riscv_subset_supports (rps, "zksh");
65e4a99a
NC
2392 case INSN_CLASS_V:
2393 return (riscv_subset_supports (rps, "v")
2394 || riscv_subset_supports (rps, "zve64x")
2395 || riscv_subset_supports (rps, "zve32x"));
2396 case INSN_CLASS_ZVEF:
2397 return (riscv_subset_supports (rps, "v")
2398 || riscv_subset_supports (rps, "zve64d")
2399 || riscv_subset_supports (rps, "zve64f")
2400 || riscv_subset_supports (rps, "zve32f"));
23ff54c2
NC
2401 case INSN_CLASS_SVINVAL:
2402 return riscv_subset_supports (rps, "svinval");
c625f4ed
NC
2403 case INSN_CLASS_H:
2404 return riscv_subset_supports (rps, "h");
8254c3d2
CM
2405 case INSN_CLASS_XTHEADBA:
2406 return riscv_subset_supports (rps, "xtheadba");
2407 case INSN_CLASS_XTHEADBB:
2408 return riscv_subset_supports (rps, "xtheadbb");
2409 case INSN_CLASS_XTHEADBS:
2410 return riscv_subset_supports (rps, "xtheadbs");
a9ba8bc2
CM
2411 case INSN_CLASS_XTHEADCMO:
2412 return riscv_subset_supports (rps, "xtheadcmo");
73442230
CM
2413 case INSN_CLASS_XTHEADCONDMOV:
2414 return riscv_subset_supports (rps, "xtheadcondmov");
f511f80f
CM
2415 case INSN_CLASS_XTHEADFMEMIDX:
2416 return riscv_subset_supports (rps, "xtheadfmemidx");
4041e11d
CM
2417 case INSN_CLASS_XTHEADMAC:
2418 return riscv_subset_supports (rps, "xtheadmac");
27cfd142
CM
2419 case INSN_CLASS_XTHEADMEMIDX:
2420 return riscv_subset_supports (rps, "xtheadmemidx");
6e17ae62
CM
2421 case INSN_CLASS_XTHEADMEMPAIR:
2422 return riscv_subset_supports (rps, "xtheadmempair");
547c18d9
CM
2423 case INSN_CLASS_XTHEADSYNC:
2424 return riscv_subset_supports (rps, "xtheadsync");
f786c359
NC
2425 default:
2426 rps->error_handler
2427 (_("internal: unreachable INSN_CLASS_*"));
2428 return false;
2429 }
2430}
e4028336
PN
2431
2432/* Each instuction is belonged to an instruction class INSN_CLASS_*.
2433 Call riscv_subset_supports_ext to determine the missing extension. */
2434
2435const char *
2436riscv_multi_subset_supports_ext (riscv_parse_subset_t *rps,
2437 enum riscv_insn_class insn_class)
2438{
2439 switch (insn_class)
2440 {
2441 case INSN_CLASS_I:
2442 return "i";
2443 case INSN_CLASS_ZICSR:
2444 return "zicsr";
2445 case INSN_CLASS_ZIFENCEI:
2446 return "zifencei";
2447 case INSN_CLASS_ZIHINTPAUSE:
2448 return "zihintpause";
2449 case INSN_CLASS_M:
2450 return "m";
0938b032
TO
2451 case INSN_CLASS_ZMMUL:
2452 return _ ("m' or `zmmul");
e4028336
PN
2453 case INSN_CLASS_A:
2454 return "a";
eb668e50
CM
2455 case INSN_CLASS_ZAWRS:
2456 return "zawrs";
e4028336
PN
2457 case INSN_CLASS_F:
2458 return "f";
2459 case INSN_CLASS_D:
2460 return "d";
2461 case INSN_CLASS_Q:
2462 return "q";
2463 case INSN_CLASS_C:
2464 return "c";
2465 case INSN_CLASS_F_AND_C:
2466 if (!riscv_subset_supports (rps, "f")
2467 && !riscv_subset_supports (rps, "c"))
dd8cc00c 2468 return _("f' and `c");
e4028336
PN
2469 else if (!riscv_subset_supports (rps, "f"))
2470 return "f";
2471 else
2472 return "c";
2473 case INSN_CLASS_D_AND_C:
2474 if (!riscv_subset_supports (rps, "d")
2475 && !riscv_subset_supports (rps, "c"))
dd8cc00c 2476 return _("d' and `c");
e4028336
PN
2477 else if (!riscv_subset_supports (rps, "d"))
2478 return "d";
2479 else
2480 return "c";
2481 case INSN_CLASS_F_OR_ZFINX:
dd8cc00c
TO
2482 /* i18n: Formatted like "extension `f' or `zfinx' required". */
2483 return _("f' or `zfinx");
e4028336 2484 case INSN_CLASS_D_OR_ZDINX:
dd8cc00c 2485 return _("d' or `zdinx");
e4028336 2486 case INSN_CLASS_Q_OR_ZQINX:
dd8cc00c 2487 return _("q' or `zqinx");
045f385d
TO
2488 case INSN_CLASS_ZFH_OR_ZHINX:
2489 return _("zfh' or `zhinx");
2490 case INSN_CLASS_ZFHMIN:
2491 return "zfhmin";
2492 case INSN_CLASS_ZFHMIN_OR_ZHINXMIN:
2493 return _("zfhmin' or `zhinxmin");
2494 case INSN_CLASS_ZFHMIN_AND_D:
2495 if (riscv_subset_supports (rps, "zfhmin"))
2496 return "d";
2497 else if (riscv_subset_supports (rps, "d"))
2498 return "zfhmin";
2499 else if (riscv_subset_supports (rps, "zhinxmin"))
2500 return "zdinx";
2501 else if (riscv_subset_supports (rps, "zdinx"))
2502 return "zhinxmin";
2503 else
2504 return _("zfhmin' and `d', or `zhinxmin' and `zdinx");
2505 case INSN_CLASS_ZFHMIN_AND_Q:
2506 if (riscv_subset_supports (rps, "zfhmin"))
2507 return "q";
2508 else if (riscv_subset_supports (rps, "q"))
2509 return "zfhmin";
2510 else if (riscv_subset_supports (rps, "zhinxmin"))
2511 return "zqinx";
2512 else if (riscv_subset_supports (rps, "zqinx"))
2513 return "zhinxmin";
2514 else
2515 return _("zfhmin' and `q', or `zhinxmin' and `zqinx");
e4028336
PN
2516 case INSN_CLASS_ZBA:
2517 return "zba";
2518 case INSN_CLASS_ZBB:
2519 return "zbb";
2520 case INSN_CLASS_ZBC:
2521 return "zbc";
2522 case INSN_CLASS_ZBS:
2523 return "zbs";
2524 case INSN_CLASS_ZBKB:
2525 return "zbkb";
2526 case INSN_CLASS_ZBKC:
2527 return "zbkc";
2528 case INSN_CLASS_ZBKX:
2529 return "zbkx";
2530 case INSN_CLASS_ZBB_OR_ZBKB:
dd8cc00c 2531 return _("zbb' or `zbkb");
e4028336 2532 case INSN_CLASS_ZBC_OR_ZBKC:
dd8cc00c 2533 return _("zbc' or `zbkc");
e4028336
PN
2534 case INSN_CLASS_ZKND:
2535 return "zknd";
2536 case INSN_CLASS_ZKNE:
2537 return "zkne";
2538 case INSN_CLASS_ZKNH:
2539 return "zknh";
2540 case INSN_CLASS_ZKND_OR_ZKNE:
dd8cc00c 2541 return _("zknd' or `zkne");
e4028336
PN
2542 case INSN_CLASS_ZKSED:
2543 return "zksed";
2544 case INSN_CLASS_ZKSH:
2545 return "zksh";
2546 case INSN_CLASS_V:
dd8cc00c 2547 return _("v' or `zve64x' or `zve32x");
e4028336 2548 case INSN_CLASS_ZVEF:
dd8cc00c 2549 return _("v' or `zve64d' or `zve64f' or `zve32f");
e4028336
PN
2550 case INSN_CLASS_SVINVAL:
2551 return "svinval";
c625f4ed
NC
2552 case INSN_CLASS_H:
2553 return _("h");
8254c3d2
CM
2554 case INSN_CLASS_XTHEADBA:
2555 return "xtheadba";
2556 case INSN_CLASS_XTHEADBB:
2557 return "xtheadbb";
2558 case INSN_CLASS_XTHEADBS:
2559 return "xtheadbs";
a9ba8bc2
CM
2560 case INSN_CLASS_XTHEADCMO:
2561 return "xtheadcmo";
73442230
CM
2562 case INSN_CLASS_XTHEADCONDMOV:
2563 return "xtheadcondmov";
f511f80f
CM
2564 case INSN_CLASS_XTHEADFMEMIDX:
2565 return "xtheadfmemidx";
4041e11d
CM
2566 case INSN_CLASS_XTHEADMAC:
2567 return "xtheadmac";
27cfd142
CM
2568 case INSN_CLASS_XTHEADMEMIDX:
2569 return "xtheadmemidx";
6e17ae62
CM
2570 case INSN_CLASS_XTHEADMEMPAIR:
2571 return "xtheadmempair";
547c18d9
CM
2572 case INSN_CLASS_XTHEADSYNC:
2573 return "xtheadsync";
e4028336
PN
2574 default:
2575 rps->error_handler
2576 (_("internal: unreachable INSN_CLASS_*"));
2577 return NULL;
2578 }
2579}