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