Coverage Report

Created: 2023-08-28 06:31

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