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