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