Coverage Report

Created: 2025-06-24 06:45

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