Coverage Report

Created: 2026-10-02 09:53

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/binutils-gdb/bfd/elfxx-riscv.c
Line
Count
Source
1
/* RISC-V-specific support for ELF.
2
   Copyright (C) 2011-2026 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 const 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 const reloc_howto_type howto_table_internal[] =
883
{
884
  /* R_RISCV_DELETE.  */
885
  EMPTY_HOWTO (0),
886
887
  /* R_RISCV_DELETE_AND_RELAX.  */
888
  EMPTY_HOWTO (0),
889
890
  /* High 6 bits of 18-bit absolute address.  */
891
  HOWTO (R_RISCV_RVC_LUI,   /* type */
892
   0,       /* rightshift */
893
   2,       /* size */
894
   16,        /* bitsize */
895
   false,       /* pc_relative */
896
   0,       /* bitpos */
897
   complain_overflow_dont,  /* complain_on_overflow */
898
   bfd_elf_generic_reloc,   /* special_function */
899
   "R_RISCV_RVC_LUI",   /* name */
900
   false,       /* partial_inplace */
901
   0,       /* src_mask */
902
   ENCODE_CITYPE_IMM (-1U), /* dst_mask */
903
   false),      /* pcrel_offset */
904
905
  /* GP-relative load.  */
906
  HOWTO (R_RISCV_GPREL_I,   /* type */
907
   0,       /* rightshift */
908
   4,       /* size */
909
   32,        /* bitsize */
910
   false,       /* pc_relative */
911
   0,       /* bitpos */
912
   complain_overflow_dont,  /* complain_on_overflow */
913
   bfd_elf_generic_reloc,   /* special_function */
914
   "R_RISCV_GPREL_I",   /* name */
915
   false,       /* partial_inplace */
916
   0,       /* src_mask */
917
   ENCODE_ITYPE_IMM (-1U),  /* dst_mask */
918
   false),      /* pcrel_offset */
919
920
  /* GP-relative store.  */
921
  HOWTO (R_RISCV_GPREL_S,   /* type */
922
   0,       /* rightshift */
923
   4,       /* size */
924
   32,        /* bitsize */
925
   false,       /* pc_relative */
926
   0,       /* bitpos */
927
   complain_overflow_dont,  /* complain_on_overflow */
928
   bfd_elf_generic_reloc,   /* special_function */
929
   "R_RISCV_GPREL_S",   /* name */
930
   false,       /* partial_inplace */
931
   0,       /* src_mask */
932
   ENCODE_STYPE_IMM (-1U),  /* dst_mask */
933
   false),      /* pcrel_offset */
934
935
  /* TP-relative TLS LE load.  */
936
  HOWTO (R_RISCV_TPREL_I,   /* type */
937
   0,       /* rightshift */
938
   4,       /* size */
939
   32,        /* bitsize */
940
   false,       /* pc_relative */
941
   0,       /* bitpos */
942
   complain_overflow_signed,  /* complain_on_overflow */
943
   bfd_elf_generic_reloc,   /* special_function */
944
   "R_RISCV_TPREL_I",   /* name */
945
   false,       /* partial_inplace */
946
   0,       /* src_mask */
947
   ENCODE_ITYPE_IMM (-1U),  /* dst_mask */
948
   false),      /* pcrel_offset */
949
950
  /* TP-relative TLS LE store.  */
951
  HOWTO (R_RISCV_TPREL_S,   /* type */
952
   0,       /* rightshift */
953
   4,       /* size */
954
   32,        /* bitsize */
955
   false,       /* pc_relative */
956
   0,       /* bitpos */
957
   complain_overflow_signed,  /* complain_on_overflow */
958
   bfd_elf_generic_reloc,   /* special_function */
959
   "R_RISCV_TPREL_S",   /* name */
960
   false,       /* partial_inplace */
961
   0,       /* src_mask */
962
   ENCODE_STYPE_IMM (-1U),  /* dst_mask */
963
   false),      /* pcrel_offset */
964
};
965
966
/* A mapping from BFD reloc types to RISC-V ELF reloc types.  */
967
struct elf_reloc_map
968
{
969
  bfd_reloc_code_real_type bfd_val;
970
  enum elf_riscv_reloc_type elf_val;
971
};
972
973
static const struct elf_reloc_map riscv_reloc_map[] =
974
{
975
  { BFD_RELOC_NONE, R_RISCV_NONE },
976
  { BFD_RELOC_32, R_RISCV_32 },
977
  { BFD_RELOC_64, R_RISCV_64 },
978
  { BFD_RELOC_RISCV_ADD8, R_RISCV_ADD8 },
979
  { BFD_RELOC_RISCV_ADD16, R_RISCV_ADD16 },
980
  { BFD_RELOC_RISCV_ADD32, R_RISCV_ADD32 },
981
  { BFD_RELOC_RISCV_ADD64, R_RISCV_ADD64 },
982
  { BFD_RELOC_RISCV_SUB8, R_RISCV_SUB8 },
983
  { BFD_RELOC_RISCV_SUB16, R_RISCV_SUB16 },
984
  { BFD_RELOC_RISCV_SUB32, R_RISCV_SUB32 },
985
  { BFD_RELOC_RISCV_SUB64, R_RISCV_SUB64 },
986
  { BFD_RELOC_CTOR, R_RISCV_64 },
987
  { BFD_RELOC_12_PCREL, R_RISCV_BRANCH },
988
  { BFD_RELOC_RISCV_HI20, R_RISCV_HI20 },
989
  { BFD_RELOC_RISCV_LO12_I, R_RISCV_LO12_I },
990
  { BFD_RELOC_RISCV_LO12_S, R_RISCV_LO12_S },
991
  { BFD_RELOC_RISCV_PCREL_LO12_I, R_RISCV_PCREL_LO12_I },
992
  { BFD_RELOC_RISCV_PCREL_LO12_S, R_RISCV_PCREL_LO12_S },
993
  { BFD_RELOC_RISCV_CALL, R_RISCV_CALL },
994
  { BFD_RELOC_RISCV_CALL_PLT, R_RISCV_CALL_PLT },
995
  { BFD_RELOC_RISCV_PCREL_HI20, R_RISCV_PCREL_HI20 },
996
  { BFD_RELOC_RISCV_JMP, R_RISCV_JAL },
997
  { BFD_RELOC_RISCV_GOT_HI20, R_RISCV_GOT_HI20 },
998
  { BFD_RELOC_RISCV_TLS_DTPMOD32, R_RISCV_TLS_DTPMOD32 },
999
  { BFD_RELOC_RISCV_TLS_DTPREL32, R_RISCV_TLS_DTPREL32 },
1000
  { BFD_RELOC_RISCV_TLS_DTPMOD64, R_RISCV_TLS_DTPMOD64 },
1001
  { BFD_RELOC_RISCV_TLS_DTPREL64, R_RISCV_TLS_DTPREL64 },
1002
  { BFD_RELOC_RISCV_TLS_TPREL32, R_RISCV_TLS_TPREL32 },
1003
  { BFD_RELOC_RISCV_TLS_TPREL64, R_RISCV_TLS_TPREL64 },
1004
  { BFD_RELOC_RISCV_TPREL_HI20, R_RISCV_TPREL_HI20 },
1005
  { BFD_RELOC_RISCV_TPREL_ADD, R_RISCV_TPREL_ADD },
1006
  { BFD_RELOC_RISCV_TPREL_LO12_S, R_RISCV_TPREL_LO12_S },
1007
  { BFD_RELOC_RISCV_TPREL_LO12_I, R_RISCV_TPREL_LO12_I },
1008
  { BFD_RELOC_RISCV_TLS_GOT_HI20, R_RISCV_TLS_GOT_HI20 },
1009
  { BFD_RELOC_RISCV_TLS_GD_HI20, R_RISCV_TLS_GD_HI20 },
1010
  { BFD_RELOC_RISCV_TLSDESC_HI20, R_RISCV_TLSDESC_HI20 },
1011
  { BFD_RELOC_RISCV_TLSDESC_LOAD_LO12, R_RISCV_TLSDESC_LOAD_LO12 },
1012
  { BFD_RELOC_RISCV_TLSDESC_ADD_LO12, R_RISCV_TLSDESC_ADD_LO12 },
1013
  { BFD_RELOC_RISCV_TLSDESC_CALL, R_RISCV_TLSDESC_CALL },
1014
  { BFD_RELOC_RISCV_ALIGN, R_RISCV_ALIGN },
1015
  { BFD_RELOC_RISCV_RVC_BRANCH, R_RISCV_RVC_BRANCH },
1016
  { BFD_RELOC_RISCV_RVC_JUMP, R_RISCV_RVC_JUMP },
1017
  { BFD_RELOC_RISCV_RELAX, R_RISCV_RELAX },
1018
  { BFD_RELOC_RISCV_SUB6, R_RISCV_SUB6 },
1019
  { BFD_RELOC_RISCV_SET6, R_RISCV_SET6 },
1020
  { BFD_RELOC_RISCV_SET8, R_RISCV_SET8 },
1021
  { BFD_RELOC_RISCV_SET16, R_RISCV_SET16 },
1022
  { BFD_RELOC_RISCV_SET32, R_RISCV_SET32 },
1023
  { BFD_RELOC_32_PCREL, R_RISCV_32_PCREL },
1024
  { BFD_RELOC_RISCV_SET_ULEB128, R_RISCV_SET_ULEB128 },
1025
  { BFD_RELOC_RISCV_SUB_ULEB128, R_RISCV_SUB_ULEB128 },
1026
};
1027
1028
struct riscv_profiles
1029
{
1030
  const char *profile_name;
1031
  const char *profile_string;
1032
};
1033
1034
/* Given a BFD reloc type, return a howto structure.  */
1035
1036
reloc_howto_type *
1037
riscv_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED,
1038
       bfd_reloc_code_real_type code)
1039
0
{
1040
0
  unsigned int i;
1041
1042
0
  for (i = 0; i < ARRAY_SIZE (riscv_reloc_map); i++)
1043
0
    if (riscv_reloc_map[i].bfd_val == code)
1044
0
      return &howto_table[(int) riscv_reloc_map[i].elf_val];
1045
1046
0
  bfd_set_error (bfd_error_bad_value);
1047
0
  return NULL;
1048
0
}
1049
1050
reloc_howto_type *
1051
riscv_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED, const char *r_name)
1052
0
{
1053
0
  unsigned int i;
1054
1055
0
  for (i = 0; i < ARRAY_SIZE (howto_table); i++)
1056
0
    if (howto_table[i].name && strcasecmp (howto_table[i].name, r_name) == 0)
1057
0
      return &howto_table[i];
1058
1059
0
  return NULL;
1060
0
}
1061
1062
reloc_howto_type *
1063
riscv_elf_rtype_to_howto (bfd *abfd, unsigned int r_type)
1064
3.38k
{
1065
3.38k
  if (r_type < ARRAY_SIZE (howto_table))
1066
3.03k
    return &howto_table[r_type];
1067
345
  else if (r_type < R_RISCV_max + ARRAY_SIZE (howto_table_internal))
1068
51
    return &howto_table_internal[r_type - R_RISCV_max];
1069
294
  else
1070
294
    {
1071
294
      (*_bfd_error_handler) (_("%pB: unsupported relocation type %#x"),
1072
294
           abfd, r_type);
1073
294
      bfd_set_error (bfd_error_bad_value);
1074
294
      return NULL;
1075
294
    }
1076
3.38k
}
1077
1078
/* Special_function of RISCV_ADD and RISCV_SUB relocations.  */
1079
1080
static bfd_reloc_status_type
1081
riscv_elf_add_sub_reloc (bfd *abfd,
1082
       arelent *reloc_entry,
1083
       asymbol *symbol,
1084
       void *data,
1085
       asection *input_section,
1086
       bfd *output_bfd,
1087
       char **error_message ATTRIBUTE_UNUSED)
1088
13
{
1089
13
  reloc_howto_type *howto = reloc_entry->howto;
1090
13
  bfd_vma relocation;
1091
1092
13
  if (output_bfd != NULL
1093
0
      && (symbol->flags & BSF_SECTION_SYM) == 0
1094
0
      && (!reloc_entry->howto->partial_inplace || reloc_entry->addend == 0))
1095
0
    {
1096
0
      reloc_entry->address += input_section->output_offset;
1097
0
      return bfd_reloc_ok;
1098
0
    }
1099
1100
13
  if (output_bfd != NULL)
1101
0
    return bfd_reloc_continue;
1102
1103
13
  relocation = symbol->value + symbol->section->output_section->vma
1104
13
    + symbol->section->output_offset + reloc_entry->addend;
1105
1106
13
  bfd_size_type octets = reloc_entry->address
1107
13
    * bfd_octets_per_byte (abfd, input_section);
1108
13
  if (!bfd_reloc_offset_in_range (reloc_entry->howto, abfd,
1109
13
          input_section, octets))
1110
1
    return bfd_reloc_outofrange;
1111
1112
12
  bfd_vma old_value = bfd_get (howto->bitsize, abfd,
1113
12
             data + reloc_entry->address);
1114
1115
12
  switch (howto->type)
1116
12
    {
1117
2
    case R_RISCV_ADD8:
1118
2
    case R_RISCV_ADD16:
1119
3
    case R_RISCV_ADD32:
1120
4
    case R_RISCV_ADD64:
1121
4
      relocation = old_value + relocation;
1122
4
      break;
1123
1
    case R_RISCV_SUB6:
1124
1
      relocation = (old_value & ~howto->dst_mask)
1125
1
       | (((old_value & howto->dst_mask) - relocation)
1126
1
          & howto->dst_mask);
1127
1
      break;
1128
0
    case R_RISCV_SUB8:
1129
5
    case R_RISCV_SUB16:
1130
6
    case R_RISCV_SUB32:
1131
7
    case R_RISCV_SUB64:
1132
7
      relocation = old_value - relocation;
1133
7
      break;
1134
12
    }
1135
12
  bfd_put (howto->bitsize, abfd, relocation, data + reloc_entry->address);
1136
1137
12
  return bfd_reloc_ok;
1138
12
}
1139
1140
/* Special handler for relocations which don't have to be relocated.
1141
   This function just simply return bfd_reloc_ok.  */
1142
1143
static bfd_reloc_status_type
1144
riscv_elf_ignore_reloc (bfd *abfd ATTRIBUTE_UNUSED,
1145
      arelent *reloc_entry,
1146
      asymbol *symbol ATTRIBUTE_UNUSED,
1147
      void *data ATTRIBUTE_UNUSED,
1148
      asection *input_section,
1149
      bfd *output_bfd,
1150
      char **error_message ATTRIBUTE_UNUSED)
1151
1
{
1152
1
  if (output_bfd != NULL)
1153
0
    reloc_entry->address += input_section->output_offset;
1154
1
  return bfd_reloc_ok;
1155
1
}
1156
1157
/* Always add implicit extensions for the SUBSET.  */
1158
1159
static bool
1160
check_implicit_always (riscv_parse_subset_t *rps ATTRIBUTE_UNUSED,
1161
           const riscv_subset_t *subset ATTRIBUTE_UNUSED)
1162
9.73k
{
1163
9.73k
  return true;
1164
9.73k
}
1165
1166
/* Add implicit extensions only when the version of SUBSET less than 2.1.  */
1167
1168
static bool
1169
check_implicit_for_i (riscv_parse_subset_t *rps ATTRIBUTE_UNUSED,
1170
          const riscv_subset_t *subset ATTRIBUTE_UNUSED)
1171
1.62k
{
1172
1.62k
  return (subset->major_version < 2
1173
1.62k
    || (subset->major_version == 2
1174
1.62k
        && subset->minor_version < 1));
1175
1.62k
}
1176
1177
/* Add the IMPLICIT only when the 'f' extension is also available
1178
   and XLEN is 32.  */
1179
1180
static bool
1181
check_implicit_for_zcf (riscv_parse_subset_t *rps,
1182
      const riscv_subset_t *subset ATTRIBUTE_UNUSED)
1183
1.62k
{
1184
1.62k
  return (rps != NULL
1185
1.62k
    && rps->xlen != NULL
1186
1.62k
    && *rps->xlen == 32
1187
0
    && riscv_subset_supports (rps, "f"));
1188
1.62k
}
1189
1190
/* Add the implicit only when 'd' extension is also available.  */
1191
1192
static bool
1193
check_implicit_for_zcd (riscv_parse_subset_t *rps,
1194
      const riscv_subset_t *subset ATTRIBUTE_UNUSED)
1195
1.62k
{
1196
1.62k
  return (rps != NULL
1197
1.62k
    && riscv_subset_supports (rps, "d"));
1198
1.62k
}
1199
1200
/* Record all implicit information for the subsets.  */
1201
struct riscv_implicit_subset
1202
{
1203
  const char *ext;
1204
  const char *implicit_exts;
1205
  /* A function to determine if we need to add the implicit subsets.  */
1206
  bool (*check_func) (riscv_parse_subset_t *,
1207
          const riscv_subset_t *);
1208
};
1209
/* Please added in order since this table is only run once time.  */
1210
static const struct riscv_implicit_subset riscv_implicit_subsets[] =
1211
{
1212
  {"g", "+i,+m,+a,+f,+d,+zicsr,+zifencei", check_implicit_always},
1213
  {"e", "+i", check_implicit_always},
1214
  {"i", "+zicsr,+zifencei", check_implicit_for_i},
1215
  {"zicntr", "+zicsr", check_implicit_always},
1216
  {"zihpm", "+zicsr", check_implicit_always},
1217
1218
  {"m", "+zmmul", check_implicit_always},
1219
1220
  {"zabha", "+zaamo", check_implicit_always},
1221
  {"zacas", "+zaamo", check_implicit_always},
1222
  {"a", "+zaamo,+zalrsc", check_implicit_always},
1223
  {"zalasr", "+zaamo,+zalrsc,+zabha", check_implicit_always},
1224
1225
  {"xsfvcp", "+zve32x", check_implicit_always},
1226
  {"xsfvqmaccqoq", "+zve32x,+zvl256b", check_implicit_always},
1227
  {"xsfvqmaccdod", "+zve32x,+zvl128b", check_implicit_always},
1228
  {"xsfvfnrclipxfqf", "+zve32f", check_implicit_always},
1229
1230
  {"xtheadvector", "+zicsr", check_implicit_always},
1231
  {"xtheadzvamo", "+zaamo", check_implicit_always},
1232
1233
  {"xxtvarith", "+v", check_implicit_always},
1234
  {"xxtvcoder", "+v", check_implicit_always},
1235
1236
  {"xsmtvdot", "+zve32x", check_implicit_always},
1237
  {"xsmtvdotii", "+xsmtvdot", check_implicit_always},
1238
1239
  {"v", "+zve64d,+zvl128b", check_implicit_always},
1240
  {"zvabd", "+zve32x", check_implicit_always},
1241
  {"zvfh", "+zvfhmin,+zfhmin", check_implicit_always},
1242
  {"zvfhmin", "+zve32f", check_implicit_always},
1243
  {"zvfbfwma", "+zfbfmin,+zvfbfmin", check_implicit_always},
1244
  {"zvfbfmin", "+zve32f", check_implicit_always},
1245
  {"zvfbdota32f", "+zve32f", check_implicit_always},
1246
  {"zvfqwbdota8f", "+zve32f", check_implicit_always},
1247
  {"zvfqwdota8f", "+zve32f", check_implicit_always},
1248
  {"zvfwbdota16bf", "+zve32f", check_implicit_always},
1249
  {"zvfwdota16bf", "+zve32f", check_implicit_always},
1250
1251
  {"zvbb", "+zvkb", check_implicit_always},
1252
  {"zvkng", "+zvkn,+zvkg", check_implicit_always},
1253
  {"zvknc", "+zvkn,+zvbc", check_implicit_always},
1254
  {"zvkn", "+zvkned,+zvknhb,+zvkb,+zvkt", check_implicit_always},
1255
  {"zvksg", "+zvks,+zvkg", check_implicit_always},
1256
  {"zvksc", "+zvks,+zvbc", check_implicit_always},
1257
  {"zvks", "+zvksed,+zvksh,+zvkb,+zvkt", check_implicit_always},
1258
1259
  {"zvbc", "+zve32x", check_implicit_always},
1260
  {"zvkb", "+zve32x", check_implicit_always},
1261
  {"zvkg", "+zve32x", check_implicit_always},
1262
  {"zvkned", "+zve32x", check_implicit_always},
1263
  {"zvknha", "+zve32x", check_implicit_always},
1264
  {"zvknhb", "+zve32x", check_implicit_always},
1265
  {"zvksed", "+zve32x", check_implicit_always},
1266
  {"zvksh", "+zve32x", check_implicit_always},
1267
1268
  {"zvqwbdota8i", "+zve32x", check_implicit_always},
1269
  {"zvqwbdota16i", "+zve64x", check_implicit_always},
1270
  {"zvqwdota8i", "+zve32x", check_implicit_always},
1271
  {"zvqwdota16i", "+zve64x", check_implicit_always},
1272
1273
  {"zve64d", "+d,+zve64f", check_implicit_always},
1274
  {"zve64f", "+zve32f,+zve64x", check_implicit_always},
1275
  {"zve32f", "+f,+zve32x", check_implicit_always},
1276
  {"zve64x", "+zve32x,+zvl64b", check_implicit_always},
1277
  {"zve32x", "+zvl32b,+zicsr", check_implicit_always},
1278
1279
  {"zvl65536b", "+zvl32768b", check_implicit_always},
1280
  {"zvl32768b", "+zvl16384b", check_implicit_always},
1281
  {"zvl16384b", "+zvl8192b", check_implicit_always},
1282
  {"zvl8192b", "+zvl4096b", check_implicit_always},
1283
  {"zvl4096b", "+zvl2048b", check_implicit_always},
1284
  {"zvl2048b", "+zvl1024b", check_implicit_always},
1285
  {"zvl1024b", "+zvl512b", check_implicit_always},
1286
  {"zvl512b", "+zvl256b", check_implicit_always},
1287
  {"zvl256b", "+zvl128b", check_implicit_always},
1288
  {"zvl128b", "+zvl64b", check_implicit_always},
1289
  {"zvl64b", "+zvl32b", check_implicit_always},
1290
1291
  {"zicfilp", "+zicsr", check_implicit_always},
1292
  {"zicfiss", "+zimop,+zicsr", check_implicit_always},
1293
  {"zclsd", "+zca,+zilsd", check_implicit_always},
1294
1295
  {"sha", "+h,+ssstateen,+shcounterenw,+shvstvala,+shtvala,+shvstvecd,+shvsatpa,+shgatpa", check_implicit_always},
1296
1297
  {"shcounterenw", "+h", check_implicit_always},
1298
  {"shgatpa", "+h", check_implicit_always},
1299
  {"shtvala", "+h", check_implicit_always},
1300
  {"shvsatpa", "+h", check_implicit_always},
1301
  {"shvstvala", "+h", check_implicit_always},
1302
  {"shvstvecd", "+h", check_implicit_always},
1303
  {"h", "+zicsr", check_implicit_always},
1304
  {"zhinx", "+zhinxmin", check_implicit_always},
1305
  {"zhinxmin", "+zfinx", check_implicit_always},
1306
1307
  {"zcd", "+d,+zca", check_implicit_always},
1308
  {"zcf", "+f,+zca", check_implicit_always},
1309
1310
  {"q", "+d", check_implicit_always},
1311
  {"zqinx", "+zdinx", check_implicit_always},
1312
1313
  {"d", "+f", check_implicit_always},
1314
  {"zdinx", "+zfinx", check_implicit_always},
1315
1316
  {"zfa", "+f", check_implicit_always},
1317
  {"zfbfmin", "+zfhmin", check_implicit_always},
1318
  {"zfh", "+zfhmin", check_implicit_always},
1319
  {"zfhmin", "+f", check_implicit_always},
1320
  {"zfinx", "+zicsr", check_implicit_always},
1321
  {"f", "+zicsr", check_implicit_always},
1322
1323
  {"zce", "+zcb,+zcmp,+zcmt", check_implicit_always},
1324
  {"zce", "+zcf", check_implicit_for_zcf},
1325
  {"zcb", "+zca", check_implicit_always},
1326
  {"zcmp", "+zca", check_implicit_always},
1327
  {"zcmop", "+zca", check_implicit_always},
1328
  {"zcmt", "+zca,+zicsr", check_implicit_always},
1329
  {"c", "+zcf", check_implicit_for_zcf},
1330
  {"c", "+zcd", check_implicit_for_zcd},
1331
  {"c", "+zca", check_implicit_always},
1332
1333
  {"b", "+zba,+zbb,+zbs", check_implicit_always},
1334
1335
  {"zk", "+zkn,+zkr,+zkt", check_implicit_always},
1336
  {"zkn", "+zbkb,+zbkc,+zbkx,+zkne,+zknd,+zknh", check_implicit_always},
1337
  {"zks", "+zbkb,+zbkc,+zbkx,+zksed,+zksh", check_implicit_always},
1338
1339
  {"sdtrig", "+zicsr", check_implicit_always},
1340
1341
  {"smaia", "+ssaia", check_implicit_always},
1342
  {"smcdeleg", "+ssccfg", check_implicit_always},
1343
  {"smpmpdeleg", "+smcsrind,+sspmp", check_implicit_always},
1344
  {"smcsrind", "+sscsrind", check_implicit_always},
1345
  {"smcntrpmf", "+zicsr", check_implicit_always},
1346
  {"smctr", "+zicsr", check_implicit_always},
1347
  {"smrnmi", "+zicsr", check_implicit_always},
1348
  {"smstateen", "+ssstateen", check_implicit_always},
1349
  {"smepmp", "+zicsr", check_implicit_always},
1350
  {"smdbltrp", "+zicsr", check_implicit_always},
1351
  {"smnpm", "+zicsr", check_implicit_always},
1352
  {"smmpm", "+zicsr", check_implicit_always},
1353
1354
  {"ssaia", "+zicsr", check_implicit_always},
1355
  {"ssccfg", "+sscsrind", check_implicit_always},
1356
  {"sspmpen", "+sspmp", check_implicit_always},
1357
  {"sspmp", "+sscsrind", check_implicit_always},
1358
  {"sscsrind", "+zicsr", check_implicit_always},
1359
  {"sscofpmf", "+zicsr", check_implicit_always},
1360
  {"sscounterenw", "+zicsr", check_implicit_always},
1361
  {"ssctr", "+zicsr", check_implicit_always},
1362
  {"ssstateen", "+zicsr", check_implicit_always},
1363
  {"ssstrict", "+zicsr", check_implicit_always},
1364
  {"sstc", "+zicsr", check_implicit_always},
1365
  {"sstvala", "+zicsr", check_implicit_always},
1366
  {"sstvecd", "+zicsr", check_implicit_always},
1367
  {"ssu64xl", "+zicsr", check_implicit_always},
1368
  {"ssdbltrp", "+zicsr", check_implicit_always},
1369
  {"ssnpm", "+zicsr", check_implicit_always},
1370
1371
  {"svade", "+zicsr", check_implicit_always},
1372
  {"svadu", "+zicsr", check_implicit_always},
1373
  {"svbare", "+zicsr", check_implicit_always},
1374
  {NULL, NULL, NULL}
1375
};
1376
1377
/* This table records the mapping form RISC-V Profiles into march string.  */
1378
static const struct riscv_profiles riscv_profiles_table[] =
1379
{
1380
  /* RVI20U only contains the base extension 'i' as mandatory extension.  */
1381
  {"rvi20u64", "rv64i"},
1382
  {"rvi20u32", "rv32i"},
1383
1384
  /* RVA20U contains the 'i,m,a,f,d,c,zicsr,zicntr,ziccif,ziccrse,ziccamoa,
1385
     zicclsm,za128rs' as mandatory extensions.  */
1386
  {"rva20u64", "rv64imafdc_zicsr_zicntr_ziccif_ziccrse_ziccamoa"
1387
   "_zicclsm_za128rs"},
1388
1389
  /* RVA22U contains the 'i,m,a,f,d,c,zicsr,zihintpause,zba,zbb,zbs,zicntr,
1390
     zihpm,ziccif,ziccrse,ziccamoa, zicclsm,zic64b,za64rs,zicbom,zicbop,zicboz,
1391
     zfhmin,zkt' as mandatory extensions.  */
1392
  {"rva22u64", "rv64imafdc_zicsr_zicntr_ziccif_ziccrse_ziccamoa"
1393
   "_zicclsm_zic64b_za64rs_zihintpause_zba_zbb_zbs_zicbom_zicbop"
1394
   "_zicboz_zfhmin_zkt"},
1395
1396
  /* RVA23 contains all mandatory base ISA for RVA22U64 and the new extension
1397
     'v,zihintntl,zvfhmin,zvbb,zvkt,zicond,zimop,zcmop,zfa,zawrs' as mandatory
1398
     extensions.  */
1399
  {"rva23u64", "rv64imafdcbv_zicsr_zicntr_zihpm_ziccif_ziccrse_ziccamoa"
1400
   "_zicclsm_zic64b_za64rs_zihintpause_zba_zbb_zbs_zicbom_zicbop"
1401
   "_zicboz_zfhmin_zkt_zvfhmin_zvbb_zvkt_zihintntl_zicond_zimop_zcmop_zcb"
1402
   "_zfa_zawrs_supm"},
1403
1404
  /* RVA23S contains all mandatory base ISA for RVA23U64 and the privileged
1405
     extensions as mandatory extensions.  */
1406
  {"rva23s64", "rv64imafdcbv_zicsr_zicntr_zihpm_ziccif_ziccrse_ziccamoa"
1407
   "_zicclsm_zic64b_za64rs_zihintpause_zba_zbb_zbs_zicbom_zicbop"
1408
   "_zicboz_zfhmin_zkt_zvfhmin_zvbb_zvkt_zihintntl_zicond_zimop_zcmop_zcb"
1409
   "_zfa_zawrs_supm_svbare_svade_ssccptr_sstvecd_sstvala_sscounterenw_svpbmt"
1410
   "_svinval_svnapot_sstc_sscofpmf_ssnpm_ssu64xl_sha"},
1411
1412
  /* RVB23 contains all mandatory base ISA for RVA22U64 and the new extension
1413
     'zihintntl,zicond,zimop,zcmop,zfa,zawrs' as mandatory
1414
     extensions.  */
1415
  {"rvb23u64", "rv64imafdcb_zicsr_zicntr_zihpm_ziccif_ziccrse_ziccamoa"
1416
   "_zicclsm_zic64b_za64rs_zihintpause_zba_zbb_zbs_zicbom_zicbop"
1417
   "_zicboz_zfhmin_zkt_zihintntl_zicond_zimop_zcmop_zcb"
1418
   "_zfa_zawrs_supm"},
1419
1420
  /* RVB23S contains all mandatory base ISA for RVB23U64 and the privileged
1421
     extensions as mandatory extensions.  */
1422
  {"rvb23s64", "rv64imafdcb_zicsr_zicntr_zihpm_ziccif_ziccrse_ziccamoa"
1423
   "_zicclsm_zic64b_za64rs_zihintpause_zba_zbb_zbs_zicbom_zicbop"
1424
   "_zicboz_zfhmin_zkt_zvfhmin_zvbb_zvkt_zihintntl_zicond_zimop_zcmop_zcb"
1425
   "_zfa_zawrs_supm_svbare_svade_ssccptr_sstvecd_sstvala_sscounterenw_svpbmt"
1426
   "_svinval_svnapot_sstc_sscofpmf_ssu64xl"},
1427
1428
  /* Terminate the list.  */
1429
  {NULL, NULL}
1430
};
1431
1432
/* For default_enable field, decide if the extension should
1433
   be enbaled by default.  */
1434
1435
0
#define EXT_DEFAULT   0x1
1436
1437
/* List all extensions that binutils should know about.  */
1438
1439
struct riscv_supported_ext
1440
{
1441
  const char *name;
1442
  enum riscv_spec_class isa_spec_class;
1443
  int major_version;
1444
  int minor_version;
1445
  unsigned long default_enable;
1446
};
1447
1448
/* The standard extensions must be added in canonical order.  */
1449
1450
static const struct riscv_supported_ext riscv_supported_std_ext[] =
1451
{
1452
  {"e",   ISA_SPEC_CLASS_20191213,  1, 9, 0 },
1453
  {"e",   ISA_SPEC_CLASS_20190608,  1, 9, 0 },
1454
  {"e",   ISA_SPEC_CLASS_2P2,   1, 9, 0 },
1455
  {"i",   ISA_SPEC_CLASS_20191213,  2, 1, 0 },
1456
  {"i",   ISA_SPEC_CLASS_20190608,  2, 1, 0 },
1457
  {"i",   ISA_SPEC_CLASS_2P2,   2, 0, 0 },
1458
  /* The g is a special case which we don't want to output it,
1459
     but still need it when adding implicit extensions.  */
1460
  {"g",   ISA_SPEC_CLASS_NONE, RISCV_UNKNOWN_VERSION, RISCV_UNKNOWN_VERSION, EXT_DEFAULT },
1461
  {"m",   ISA_SPEC_CLASS_20191213,  2, 0, 0 },
1462
  {"m",   ISA_SPEC_CLASS_20190608,  2, 0, 0 },
1463
  {"m",   ISA_SPEC_CLASS_2P2,   2, 0, 0 },
1464
  {"a",   ISA_SPEC_CLASS_20191213,  2, 1, 0 },
1465
  {"a",   ISA_SPEC_CLASS_20190608,  2, 0, 0 },
1466
  {"a",   ISA_SPEC_CLASS_2P2,   2, 0, 0 },
1467
  {"f",   ISA_SPEC_CLASS_20191213,  2, 2, 0 },
1468
  {"f",   ISA_SPEC_CLASS_20190608,  2, 2, 0 },
1469
  {"f",   ISA_SPEC_CLASS_2P2,   2, 0, 0 },
1470
  {"d",   ISA_SPEC_CLASS_20191213,  2, 2, 0 },
1471
  {"d",   ISA_SPEC_CLASS_20190608,  2, 2, 0 },
1472
  {"d",   ISA_SPEC_CLASS_2P2,   2, 0, 0 },
1473
  {"q",   ISA_SPEC_CLASS_20191213,  2, 2, 0 },
1474
  {"q",   ISA_SPEC_CLASS_20190608,  2, 2, 0 },
1475
  {"q",   ISA_SPEC_CLASS_2P2,   2, 0, 0 },
1476
  {"c",   ISA_SPEC_CLASS_20191213,  2, 0, 0 },
1477
  {"c",   ISA_SPEC_CLASS_20190608,  2, 0, 0 },
1478
  {"c",   ISA_SPEC_CLASS_2P2,   2, 0, 0 },
1479
  {"b",   ISA_SPEC_CLASS_DRAFT,   1, 0, 0 },
1480
  {"v",   ISA_SPEC_CLASS_DRAFT,   1, 0, 0 },
1481
  {"h",   ISA_SPEC_CLASS_DRAFT,   1, 0, 0 },
1482
  {NULL, 0, 0, 0, 0}
1483
};
1484
1485
static const struct riscv_supported_ext riscv_supported_std_z_ext[] =
1486
{
1487
  {"zic64b",    ISA_SPEC_CLASS_DRAFT,   1, 0, 0 },
1488
  {"ziccamoa",    ISA_SPEC_CLASS_DRAFT,   1, 0, 0 },
1489
  {"ziccamoc",    ISA_SPEC_CLASS_DRAFT,   1, 0, 0 },
1490
  {"ziccif",    ISA_SPEC_CLASS_DRAFT,   1, 0, 0 },
1491
  {"zicclsm",   ISA_SPEC_CLASS_DRAFT,   1, 0, 0 },
1492
  {"ziccrse",   ISA_SPEC_CLASS_DRAFT,   1, 0, 0 },
1493
  {"zicbom",    ISA_SPEC_CLASS_DRAFT,   1, 0, 0 },
1494
  {"zicbop",    ISA_SPEC_CLASS_DRAFT,   1, 0, 0 },
1495
  {"zicboz",    ISA_SPEC_CLASS_DRAFT,   1, 0, 0 },
1496
  {"zicond",    ISA_SPEC_CLASS_DRAFT,   1, 0, 0 },
1497
  {"zicntr",    ISA_SPEC_CLASS_DRAFT,   2, 0, 0 },
1498
  {"zicsr",   ISA_SPEC_CLASS_20191213,  2, 0, 0 },
1499
  {"zicsr",   ISA_SPEC_CLASS_20190608,  2, 0, 0 },
1500
  {"zifencei",    ISA_SPEC_CLASS_20191213,  2, 0, 0 },
1501
  {"zifencei",    ISA_SPEC_CLASS_20190608,  2, 0, 0 },
1502
  {"zihintntl",   ISA_SPEC_CLASS_DRAFT,   1, 0, 0 },
1503
  {"zihintpause", ISA_SPEC_CLASS_DRAFT,   2, 0, 0 },
1504
  {"zihpm",   ISA_SPEC_CLASS_DRAFT,   2, 0, 0 },
1505
  {"zimop",   ISA_SPEC_CLASS_DRAFT,   1, 0, 0 },
1506
  {"zicfiss",   ISA_SPEC_CLASS_DRAFT,   1, 0, 0 },
1507
  {"zicfilp",   ISA_SPEC_CLASS_DRAFT,   1, 0, 0 },
1508
  {"zilsd",   ISA_SPEC_CLASS_DRAFT,   1, 0, 0 },
1509
  {"zmmul",   ISA_SPEC_CLASS_DRAFT,   1, 0, 0 },
1510
  {"za64rs",    ISA_SPEC_CLASS_DRAFT,   1, 0, 0 },
1511
  {"za128rs",   ISA_SPEC_CLASS_DRAFT,   1, 0, 0 },
1512
  {"zaamo",   ISA_SPEC_CLASS_DRAFT,   1, 0, 0 },
1513
  {"zabha",   ISA_SPEC_CLASS_DRAFT,   1, 0, 0 },
1514
  {"zacas",   ISA_SPEC_CLASS_DRAFT,   1, 0, 0 },
1515
  {"zalasr",           ISA_SPEC_CLASS_DRAFT,           1, 0,  0 },
1516
  {"zalrsc",    ISA_SPEC_CLASS_DRAFT,   1, 0, 0 },
1517
  {"zama16b",   ISA_SPEC_CLASS_DRAFT,   1, 0, 0 },
1518
  {"zawrs",   ISA_SPEC_CLASS_DRAFT,   1, 0, 0 },
1519
  {"zfbfmin",   ISA_SPEC_CLASS_DRAFT,   1, 0, 0 },
1520
  {"zfa",   ISA_SPEC_CLASS_DRAFT,   1, 0, 0 },
1521
  {"zfh",   ISA_SPEC_CLASS_DRAFT,   1, 0, 0 },
1522
  {"zfhmin",    ISA_SPEC_CLASS_DRAFT,   1, 0, 0 },
1523
  {"zfinx",   ISA_SPEC_CLASS_DRAFT,   1, 0, 0 },
1524
  {"zdinx",   ISA_SPEC_CLASS_DRAFT,   1, 0, 0 },
1525
  {"zqinx",   ISA_SPEC_CLASS_DRAFT,   1, 0, 0 },
1526
  {"zhinx",   ISA_SPEC_CLASS_DRAFT,   1, 0, 0 },
1527
  {"zhinxmin",    ISA_SPEC_CLASS_DRAFT,   1, 0, 0 },
1528
  {"zbb",   ISA_SPEC_CLASS_DRAFT,   1, 0, 0 },
1529
  {"zba",   ISA_SPEC_CLASS_DRAFT,   1, 0, 0 },
1530
  {"zbc",   ISA_SPEC_CLASS_DRAFT,   1, 0, 0 },
1531
  {"zbs",   ISA_SPEC_CLASS_DRAFT,   1, 0, 0 },
1532
  {"zbkb",    ISA_SPEC_CLASS_DRAFT,   1, 0, 0 },
1533
  {"zbkc",    ISA_SPEC_CLASS_DRAFT,   1, 0, 0 },
1534
  {"zbkx",    ISA_SPEC_CLASS_DRAFT,   1, 0, 0 },
1535
  {"zk",    ISA_SPEC_CLASS_DRAFT,   1, 0, 0 },
1536
  {"zkn",   ISA_SPEC_CLASS_DRAFT,   1, 0, 0 },
1537
  {"zknd",    ISA_SPEC_CLASS_DRAFT,   1, 0, 0 },
1538
  {"zkne",    ISA_SPEC_CLASS_DRAFT,   1, 0, 0 },
1539
  {"zknh",    ISA_SPEC_CLASS_DRAFT,   1, 0, 0 },
1540
  {"zkr",   ISA_SPEC_CLASS_DRAFT,   1, 0, 0 },
1541
  {"zks",   ISA_SPEC_CLASS_DRAFT,   1, 0, 0 },
1542
  {"zksed",   ISA_SPEC_CLASS_DRAFT,   1, 0, 0 },
1543
  {"zksh",    ISA_SPEC_CLASS_DRAFT,   1, 0, 0 },
1544
  {"zkt",   ISA_SPEC_CLASS_DRAFT,   1, 0, 0 },
1545
  {"zve32x",    ISA_SPEC_CLASS_DRAFT,   1, 0, 0 },
1546
  {"zve32f",    ISA_SPEC_CLASS_DRAFT,   1, 0, 0 },
1547
  {"zve64x",    ISA_SPEC_CLASS_DRAFT,   1, 0, 0 },
1548
  {"zve64f",    ISA_SPEC_CLASS_DRAFT,   1, 0, 0 },
1549
  {"zve64d",    ISA_SPEC_CLASS_DRAFT,   1, 0, 0 },
1550
  {"zvabd",   ISA_SPEC_CLASS_DRAFT,   0, 9, 0 },
1551
  {"zvbb",    ISA_SPEC_CLASS_DRAFT,   1, 0, 0 },
1552
  {"zvbc",    ISA_SPEC_CLASS_DRAFT,   1, 0, 0 },
1553
  {"zvfbdota32f", ISA_SPEC_CLASS_DRAFT,   1, 0, 0 },
1554
  {"zvfbfmin",    ISA_SPEC_CLASS_DRAFT,   1, 0, 0 },
1555
  {"zvfbfwma",    ISA_SPEC_CLASS_DRAFT,   1, 0, 0 },
1556
  {"zvfh",    ISA_SPEC_CLASS_DRAFT,   1, 0, 0 },
1557
  {"zvfhmin",   ISA_SPEC_CLASS_DRAFT,   1, 0, 0 },
1558
  {"zvfqwbdota8f",  ISA_SPEC_CLASS_DRAFT,   1, 0, 0 },
1559
  {"zvfqwdota8f", ISA_SPEC_CLASS_DRAFT,   1, 0, 0 },
1560
  {"zvfwbdota16bf", ISA_SPEC_CLASS_DRAFT,   1, 0, 0 },
1561
  {"zvfwdota16bf",  ISA_SPEC_CLASS_DRAFT,   1, 0, 0 },
1562
  {"zvkb",    ISA_SPEC_CLASS_DRAFT,   1, 0, 0 },
1563
  {"zvkg",    ISA_SPEC_CLASS_DRAFT,   1, 0, 0 },
1564
  {"zvkn",    ISA_SPEC_CLASS_DRAFT,   1, 0, 0 },
1565
  {"zvkng",   ISA_SPEC_CLASS_DRAFT,   1, 0, 0 },
1566
  {"zvknc",   ISA_SPEC_CLASS_DRAFT,   1, 0, 0 },
1567
  {"zvkned",    ISA_SPEC_CLASS_DRAFT,   1, 0, 0 },
1568
  {"zvknha",    ISA_SPEC_CLASS_DRAFT,   1, 0, 0 },
1569
  {"zvknhb",    ISA_SPEC_CLASS_DRAFT,   1, 0, 0 },
1570
  {"zvksed",    ISA_SPEC_CLASS_DRAFT,   1, 0, 0 },
1571
  {"zvksh",   ISA_SPEC_CLASS_DRAFT,   1, 0, 0 },
1572
  {"zvks",    ISA_SPEC_CLASS_DRAFT,   1, 0, 0 },
1573
  {"zvksg",   ISA_SPEC_CLASS_DRAFT,   1, 0, 0 },
1574
  {"zvksc",   ISA_SPEC_CLASS_DRAFT,   1, 0, 0 },
1575
  {"zvkt",    ISA_SPEC_CLASS_DRAFT,   1, 0, 0 },
1576
  {"zvqwbdota8i", ISA_SPEC_CLASS_DRAFT,   1, 0, 0 },
1577
  {"zvqwbdota16i",  ISA_SPEC_CLASS_DRAFT,   1, 0, 0 },
1578
  {"zvqwdota8i",  ISA_SPEC_CLASS_DRAFT,   1, 0, 0 },
1579
  {"zvqwdota16i", ISA_SPEC_CLASS_DRAFT,   1, 0, 0 },
1580
  {"zvl32b",    ISA_SPEC_CLASS_DRAFT,   1, 0, 0 },
1581
  {"zvl64b",    ISA_SPEC_CLASS_DRAFT,   1, 0, 0 },
1582
  {"zvl128b",   ISA_SPEC_CLASS_DRAFT,   1, 0, 0 },
1583
  {"zvl256b",   ISA_SPEC_CLASS_DRAFT,   1, 0, 0 },
1584
  {"zvl512b",   ISA_SPEC_CLASS_DRAFT,   1, 0, 0 },
1585
  {"zvl1024b",    ISA_SPEC_CLASS_DRAFT,   1, 0, 0 },
1586
  {"zvl2048b",    ISA_SPEC_CLASS_DRAFT,   1, 0, 0 },
1587
  {"zvl4096b",    ISA_SPEC_CLASS_DRAFT,   1, 0, 0 },
1588
  {"zvl8192b",    ISA_SPEC_CLASS_DRAFT,   1, 0, 0 },
1589
  {"zvl16384b",   ISA_SPEC_CLASS_DRAFT,   1, 0, 0 },
1590
  {"zvl32768b",   ISA_SPEC_CLASS_DRAFT,   1, 0, 0 },
1591
  {"zvl65536b",   ISA_SPEC_CLASS_DRAFT,   1, 0, 0 },
1592
  {"ztso",    ISA_SPEC_CLASS_DRAFT,   1, 0, 0 },
1593
  {"zca",   ISA_SPEC_CLASS_DRAFT,   1, 0, 0 },
1594
  {"zcb",   ISA_SPEC_CLASS_DRAFT,   1, 0, 0 },
1595
  {"zce",   ISA_SPEC_CLASS_DRAFT,   1, 0, 0 },
1596
  {"zcf",   ISA_SPEC_CLASS_DRAFT,   1, 0, 0 },
1597
  {"zcd",   ISA_SPEC_CLASS_DRAFT,   1, 0, 0 },
1598
  {"zcmop",   ISA_SPEC_CLASS_DRAFT,   1, 0, 0 },
1599
  {"zcmp",    ISA_SPEC_CLASS_DRAFT,   1, 0, 0 },
1600
  {"zcmt",    ISA_SPEC_CLASS_DRAFT,   1, 0, 0 },
1601
  {"zclsd",   ISA_SPEC_CLASS_DRAFT,   1, 0, 0 },
1602
  {NULL, 0, 0, 0, 0}
1603
};
1604
1605
static const struct riscv_supported_ext riscv_supported_std_s_ext[] =
1606
{
1607
  {"sdtrig",    ISA_SPEC_CLASS_DRAFT,   1, 0, 0 },
1608
  {"sha",   ISA_SPEC_CLASS_DRAFT,   1, 0, 0 },
1609
  {"shcounterenw",  ISA_SPEC_CLASS_DRAFT,   1, 0, 0 },
1610
  {"shgatpa",   ISA_SPEC_CLASS_DRAFT,   1, 0, 0 },
1611
  {"shtvala",   ISA_SPEC_CLASS_DRAFT,   1, 0, 0 },
1612
  {"shvsatpa",    ISA_SPEC_CLASS_DRAFT,   1, 0, 0 },
1613
  {"shvstvala",   ISA_SPEC_CLASS_DRAFT,   1, 0, 0 },
1614
  {"shvstvecd",   ISA_SPEC_CLASS_DRAFT,   1, 0, 0 },
1615
  {"smaia",   ISA_SPEC_CLASS_DRAFT,   1, 0, 0 },
1616
  {"smcdeleg",    ISA_SPEC_CLASS_DRAFT,   1, 0, 0 },
1617
  {"smcsrind",    ISA_SPEC_CLASS_DRAFT,   1, 0, 0 },
1618
  {"smcntrpmf",   ISA_SPEC_CLASS_DRAFT,   1, 0, 0 },
1619
  {"smctr",   ISA_SPEC_CLASS_DRAFT,   1, 0, 0 },
1620
  {"smepmp",    ISA_SPEC_CLASS_DRAFT,   1, 0, 0 },
1621
  {"smpmpdeleg",    ISA_SPEC_CLASS_DRAFT,   1, 0, 0 },
1622
  {"smpmpmt",   ISA_SPEC_CLASS_DRAFT,   1, 0, 0 },
1623
  {"smrnmi",    ISA_SPEC_CLASS_DRAFT,   1, 0, 0 },
1624
  {"smstateen",   ISA_SPEC_CLASS_DRAFT,   1, 0, 0 },
1625
  {"smdbltrp",    ISA_SPEC_CLASS_DRAFT,   1, 0, 0 },
1626
  {"ss",    ISA_SPEC_CLASS_DRAFT,   1, 11, 0 },
1627
  {"ss",    ISA_SPEC_CLASS_DRAFT,   1, 12, 0 },
1628
  {"ss",    ISA_SPEC_CLASS_DRAFT,   1, 13, 0 },
1629
  {"ssaia",   ISA_SPEC_CLASS_DRAFT,   1, 0, 0 },
1630
  {"ssccfg",    ISA_SPEC_CLASS_DRAFT,   1, 0, 0 },
1631
  {"ssccptr",   ISA_SPEC_CLASS_DRAFT,   1, 0, 0 },
1632
  {"sscsrind",    ISA_SPEC_CLASS_DRAFT,   1, 0, 0 },
1633
  {"sscofpmf",    ISA_SPEC_CLASS_DRAFT,   1, 0, 0 },
1634
  {"sscounterenw",  ISA_SPEC_CLASS_DRAFT,   1, 0, 0 },
1635
  {"ssctr",   ISA_SPEC_CLASS_DRAFT,   1, 0, 0 },
1636
  {"ssstateen",   ISA_SPEC_CLASS_DRAFT,   1, 0, 0 },
1637
  {"ssstrict",    ISA_SPEC_CLASS_DRAFT,   1, 0, 0 },
1638
  {"sstc",    ISA_SPEC_CLASS_DRAFT,   1, 0, 0 },
1639
  {"sstvala",   ISA_SPEC_CLASS_DRAFT,   1, 0, 0 },
1640
  {"sstvecd",   ISA_SPEC_CLASS_DRAFT,   1, 0, 0 },
1641
  {"ssu64xl",   ISA_SPEC_CLASS_DRAFT,   1, 0, 0 },
1642
  {"ssdbltrp",    ISA_SPEC_CLASS_DRAFT,   1, 0, 0 },
1643
  {"svade",   ISA_SPEC_CLASS_DRAFT,   1, 0, 0 },
1644
  {"svadu",   ISA_SPEC_CLASS_DRAFT,   1, 0, 0 },
1645
  {"svbare",    ISA_SPEC_CLASS_DRAFT,   1, 0, 0 },
1646
  {"svinval",   ISA_SPEC_CLASS_DRAFT,   1, 0, 0 },
1647
  {"svnapot",   ISA_SPEC_CLASS_DRAFT,   1, 0, 0 },
1648
  {"svpbmt",    ISA_SPEC_CLASS_DRAFT,   1, 0, 0 },
1649
  {"svrsw60t59b",   ISA_SPEC_CLASS_DRAFT,   1, 0, 0 },
1650
  {"svvptc",    ISA_SPEC_CLASS_DRAFT,   1, 0, 0 },
1651
  {"ssqosid",   ISA_SPEC_CLASS_DRAFT,   1, 0, 0 },
1652
  {"sspmp",   ISA_SPEC_CLASS_DRAFT,   1, 0, 0 },
1653
  {"sspmpen",   ISA_SPEC_CLASS_DRAFT,   1, 0, 0 },
1654
  {"ssnpm",   ISA_SPEC_CLASS_DRAFT,   1, 0, 0 },
1655
  {"smnpm",   ISA_SPEC_CLASS_DRAFT,   1, 0, 0 },
1656
  {"smmpm",   ISA_SPEC_CLASS_DRAFT,   1, 0, 0 },
1657
  {"sspm",    ISA_SPEC_CLASS_DRAFT,   1, 0, 0 },
1658
  {"supm",    ISA_SPEC_CLASS_DRAFT,   1, 0, 0 },
1659
  {NULL, 0, 0, 0, 0}
1660
};
1661
1662
static const struct riscv_supported_ext riscv_supported_std_zxm_ext[] =
1663
{
1664
  {NULL, 0, 0, 0, 0}
1665
};
1666
1667
static const struct riscv_supported_ext riscv_supported_vendor_x_ext[] =
1668
{
1669
  {"xandesbfhcvt",  ISA_SPEC_CLASS_DRAFT, 5, 0, 0 },
1670
  {"xandesvbfhcvt", ISA_SPEC_CLASS_DRAFT, 5, 0, 0 },
1671
  {"xandesvsintload", ISA_SPEC_CLASS_DRAFT, 5, 0, 0 },
1672
  {"xandesvpackfph",  ISA_SPEC_CLASS_DRAFT, 5, 0, 0 },
1673
  {"xandesvdot",  ISA_SPEC_CLASS_DRAFT, 5, 0, 0 },
1674
  {"xandesvsinth",  ISA_SPEC_CLASS_DRAFT, 5, 0, 0 },
1675
  {"xcvalu",    ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1676
  {"xcvbi",   ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1677
  {"xcvbitmanip", ISA_SPEC_CLASS_DRAFT,   1, 0, 0 },
1678
  {"xcvelw",    ISA_SPEC_CLASS_DRAFT,   1, 0, 0 },
1679
  {"xcvmac",    ISA_SPEC_CLASS_DRAFT,   1, 0, 0 },
1680
  {"xcvmem",    ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1681
  {"xcvsimd",   ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1682
  {"xtheadba",    ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1683
  {"xtheadbb",    ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1684
  {"xtheadbs",    ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1685
  {"xtheadcmo",   ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1686
  {"xtheadcondmov", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1687
  {"xtheadfmemidx", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1688
  {"xtheadfmv",   ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1689
  {"xtheadint",   ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1690
  {"xtheadmac",   ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1691
  {"xtheadmemidx",  ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1692
  {"xtheadmempair", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1693
  {"xtheadsync",  ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1694
  {"xtheadvector",  ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1695
  {"xtheadvdot",  ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1696
  {"xtheadzvamo", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1697
  {"xxtvarith", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1698
  {"xxtvcoder", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1699
  {"xventanacondops", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1700
  {"xsfvcp",    ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1701
  {"xsfcease",    ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1702
  {"xsfvqmaccqoq",  ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1703
  {"xsfvqmaccdod",  ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1704
  {"xsfvfnrclipxfqf", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1705
  {"xmipscbop",   ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1706
  {"xmipscmov",   ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1707
  {"xmipsexectl", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1708
  {"xmipslsp",    ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1709
  {"xsmtvdot",    ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1710
  {"xsmtvdotii",  ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1711
  {NULL, 0, 0, 0, 0}
1712
};
1713
1714
static const struct riscv_supported_ext *riscv_all_supported_ext[] =
1715
{
1716
  riscv_supported_std_ext,
1717
  riscv_supported_std_z_ext,
1718
  riscv_supported_std_s_ext,
1719
  riscv_supported_std_zxm_ext,
1720
  riscv_supported_vendor_x_ext,
1721
  NULL
1722
};
1723
1724
/* ISA extension prefixed name class.  Must define them in parsing order.  */
1725
enum riscv_prefix_ext_class
1726
{
1727
  RV_ISA_CLASS_Z = 1,
1728
  RV_ISA_CLASS_S,
1729
  RV_ISA_CLASS_ZXM,
1730
  RV_ISA_CLASS_X,
1731
  RV_ISA_CLASS_SINGLE
1732
};
1733
1734
/* Record the strings of the prefixed extensions, and their corresponding
1735
   classes.  The more letters of the prefix string, the more forward it must
1736
   be defined.  Otherwise, the riscv_get_prefix_class will map it to the
1737
   wrong classes.  */
1738
struct riscv_parse_prefix_config
1739
{
1740
  /* Class of the extension. */
1741
  enum riscv_prefix_ext_class class;
1742
1743
  /* Prefix string for error printing and internal parser usage.  */
1744
  const char *prefix;
1745
};
1746
static const struct riscv_parse_prefix_config parse_config[] =
1747
{
1748
  {RV_ISA_CLASS_ZXM, "zxm"},
1749
  {RV_ISA_CLASS_Z, "z"},
1750
  {RV_ISA_CLASS_S, "s"},
1751
  {RV_ISA_CLASS_X, "x"},
1752
  {RV_ISA_CLASS_SINGLE, NULL}
1753
};
1754
1755
/* Get the prefixed name class for the extensions, the class also
1756
   means the order of the prefixed extensions.  */
1757
1758
static enum riscv_prefix_ext_class
1759
riscv_get_prefix_class (const char *arch)
1760
127M
{
1761
127M
  int i = 0;
1762
350M
  while (parse_config[i].class != RV_ISA_CLASS_SINGLE)
1763
318M
    {
1764
318M
      if (strncmp (arch, parse_config[i].prefix,
1765
318M
       strlen (parse_config[i].prefix)) == 0)
1766
95.7M
  return parse_config[i].class;
1767
223M
      i++;
1768
223M
    }
1769
31.7M
  return RV_ISA_CLASS_SINGLE;
1770
127M
}
1771
1772
/* Check KNOWN_EXTS to see if the EXT is supported.  */
1773
1774
static bool
1775
riscv_known_prefixed_ext (const char *ext,
1776
        const struct riscv_supported_ext *known_exts)
1777
0
{
1778
0
  size_t i;
1779
0
  for (i = 0; known_exts[i].name != NULL; ++i)
1780
0
    if (strcmp (ext, known_exts[i].name) == 0)
1781
0
      return true;
1782
0
  return false;
1783
0
}
1784
1785
/* Check whether the prefixed extension is recognized or not.  Return
1786
   true if recognized, otehrwise return false.  */
1787
1788
static bool
1789
riscv_recognized_prefixed_ext (const char *ext)
1790
0
{
1791
0
  enum riscv_prefix_ext_class class = riscv_get_prefix_class (ext);
1792
0
  switch (class)
1793
0
  {
1794
0
  case RV_ISA_CLASS_Z:
1795
0
    return riscv_known_prefixed_ext (ext, riscv_supported_std_z_ext);
1796
0
  case RV_ISA_CLASS_ZXM:
1797
0
    return riscv_known_prefixed_ext (ext, riscv_supported_std_zxm_ext);
1798
0
  case RV_ISA_CLASS_S:
1799
0
    return riscv_known_prefixed_ext (ext, riscv_supported_std_s_ext);
1800
0
  case RV_ISA_CLASS_X:
1801
    /* Only the single x is unrecognized.  */
1802
0
    if (strcmp (ext, "x") != 0)
1803
0
      return true;
1804
0
  default:
1805
0
    break;
1806
0
  }
1807
0
  return false;
1808
0
}
1809
1810
/* Canonical order for single letter extensions.  */
1811
static const char riscv_ext_canonical_order[] = "eigmafdqlcbkjtpvnh";
1812
1813
/* Array is used to compare the orders of standard extensions quickly.  */
1814
static int riscv_ext_order[26] = {0};
1815
1816
/* Init the riscv_ext_order array.  */
1817
1818
static void
1819
riscv_init_ext_order (void)
1820
1.62k
{
1821
1.62k
  static bool inited = false;
1822
1.62k
  if (inited)
1823
1.62k
    return;
1824
1825
  /* The orders of all standard extensions are positive.  */
1826
2
  int order = 1;
1827
1828
38
  for (const char *ext = &riscv_ext_canonical_order[0]; *ext; ++ext)
1829
36
    riscv_ext_order[(*ext - 'a')] = order++;
1830
1831
  /* Some of the prefixed keyword are not single letter, so we set
1832
     their prefixed orders in the riscv_compare_subsets directly,
1833
     not through the riscv_ext_order.  */
1834
1835
2
  inited = true;
1836
2
}
1837
1838
/* Similar to the strcmp.  It returns an integer less than, equal to,
1839
   or greater than zero if `subset2` is found, respectively, to be less
1840
   than, to match, or be greater than `subset1`.
1841
1842
   The order values,
1843
   Zero: Preserved keywords.
1844
   Positive number: Standard extensions.
1845
   Negative number: Prefixed keywords.  */
1846
1847
int
1848
riscv_compare_subsets (const char *subset1, const char *subset2)
1849
64.3M
{
1850
64.3M
  int order1 = riscv_ext_order[(*subset1 - 'a')];
1851
64.3M
  int order2 = riscv_ext_order[(*subset2 - 'a')];
1852
1853
  /* Compare the standard extension first.  */
1854
64.3M
  if (order1 > 0 && order2 > 0)
1855
563k
    return order1 - order2;
1856
1857
  /* Set the prefixed orders to negative numbers.  */
1858
63.7M
  enum riscv_prefix_ext_class class1 = riscv_get_prefix_class (subset1);
1859
63.7M
  enum riscv_prefix_ext_class class2 = riscv_get_prefix_class (subset2);
1860
1861
63.7M
  if (class1 != RV_ISA_CLASS_SINGLE)
1862
32.1M
    order1 = - (int) class1;
1863
63.7M
  if (class2 != RV_ISA_CLASS_SINGLE)
1864
63.6M
    order2 = - (int) class2;
1865
1866
63.7M
  if (order1 == order2)
1867
31.8M
    {
1868
      /* Compare the standard addition z extensions.  */
1869
31.8M
      if (class1 == RV_ISA_CLASS_Z)
1870
31.8M
  {
1871
31.8M
    order1 = riscv_ext_order[(*++subset1 - 'a')];
1872
31.8M
    order2 = riscv_ext_order[(*++subset2 - 'a')];
1873
31.8M
    if (order1 != order2)
1874
28.9M
      return order1 - order2;
1875
31.8M
  }
1876
2.94M
      return strcasecmp (++subset1, ++subset2);
1877
31.8M
    }
1878
1879
31.9M
  return order2 - order1;
1880
63.7M
}
1881
1882
/* Find subset in the list.  Return TRUE and set `current` to the subset
1883
   if it is found.  Otherwise, return FALSE and set `current` to the place
1884
   where we should insert the subset.  However, return FALSE with the NULL
1885
   `current` means we should insert the subset at the head of subset list,
1886
   if needed.  */
1887
1888
bool
1889
riscv_lookup_subset (const riscv_subset_list_t *subset_list,
1890
         const char *subset,
1891
         riscv_subset_t **current)
1892
4.99M
{
1893
4.99M
  riscv_subset_t *s, *pre_s = NULL;
1894
1895
  /* If the subset is added in order, then just add it at the tail.  */
1896
4.99M
  if (subset_list->tail != NULL
1897
4.98M
      && riscv_compare_subsets (subset_list->tail->name, subset) < 0)
1898
315k
    {
1899
315k
      *current = subset_list->tail;
1900
315k
      return false;
1901
315k
    }
1902
1903
4.67M
  for (s = subset_list->head;
1904
59.3M
       s != NULL;
1905
54.6M
       pre_s = s, s = s->next)
1906
59.3M
    {
1907
59.3M
      int cmp = riscv_compare_subsets (s->name, subset);
1908
59.3M
      if (cmp == 0)
1909
1.42M
  {
1910
1.42M
    *current = s;
1911
1.42M
    return true;
1912
1.42M
  }
1913
57.9M
      else if (cmp > 0)
1914
3.25M
  break;
1915
59.3M
    }
1916
3.25M
  *current = pre_s;
1917
1918
3.25M
  return false;
1919
4.67M
}
1920
1921
/* Add the extension to the subset list.  Search the
1922
   list first, and then find the right place to add.  */
1923
1924
void
1925
riscv_add_subset (riscv_subset_list_t *subset_list,
1926
      const char *subset,
1927
      int major,
1928
      int minor)
1929
22.7k
{
1930
22.7k
  riscv_subset_t *current, *new;
1931
1932
22.7k
  if (riscv_lookup_subset (subset_list, subset, &current))
1933
0
    return;
1934
1935
22.7k
  new = xmalloc (sizeof *new);
1936
22.7k
  new->name = xstrdup (subset);
1937
22.7k
  new->major_version = major;
1938
22.7k
  new->minor_version = minor;
1939
22.7k
  new->next = NULL;
1940
1941
22.7k
  if (current != NULL)
1942
19.4k
    {
1943
19.4k
      new->next = current->next;
1944
19.4k
      current->next = new;
1945
19.4k
    }
1946
3.24k
  else
1947
3.24k
    {
1948
3.24k
      new->next = subset_list->head;
1949
3.24k
      subset_list->head = new;
1950
3.24k
    }
1951
1952
22.7k
  if (new->next == NULL)
1953
12.9k
    subset_list->tail = new;
1954
22.7k
}
1955
1956
/* Get the default versions from the riscv_supported_*ext tables.  */
1957
1958
static void
1959
riscv_get_default_ext_version (enum riscv_spec_class default_isa_spec,
1960
             const char *name,
1961
             int *major_version,
1962
             int *minor_version)
1963
22.7k
{
1964
22.7k
  if (name == NULL
1965
22.7k
      || default_isa_spec == ISA_SPEC_CLASS_NONE)
1966
0
    return;
1967
1968
22.7k
  const struct riscv_supported_ext *table = NULL;
1969
22.7k
  enum riscv_prefix_ext_class class = riscv_get_prefix_class (name);
1970
22.7k
  switch (class)
1971
22.7k
    {
1972
0
    case RV_ISA_CLASS_ZXM: table = riscv_supported_std_zxm_ext; break;
1973
11.3k
    case RV_ISA_CLASS_Z: table = riscv_supported_std_z_ext; break;
1974
0
    case RV_ISA_CLASS_S: table = riscv_supported_std_s_ext; break;
1975
0
    case RV_ISA_CLASS_X: table = riscv_supported_vendor_x_ext; break;
1976
11.3k
    default:
1977
11.3k
      table = riscv_supported_std_ext;
1978
22.7k
    }
1979
1980
22.7k
  int i = 0;
1981
695k
  while (table != NULL && table[i].name != NULL)
1982
694k
    {
1983
694k
      if (strcmp (table[i].name, name) == 0
1984
22.7k
    && (table[i].isa_spec_class == ISA_SPEC_CLASS_DRAFT
1985
14.5k
        || table[i].isa_spec_class == default_isa_spec))
1986
21.0k
  {
1987
21.0k
    *major_version = table[i].major_version;
1988
21.0k
    *minor_version = table[i].minor_version;
1989
21.0k
    return;
1990
21.0k
  }
1991
673k
      i++;
1992
673k
    }
1993
22.7k
}
1994
1995
/* Find the default versions for the extension before adding them to
1996
   the subset list, if their versions are RISCV_UNKNOWN_VERSION.
1997
   Afterwards, report errors if we can not find their default versions.  */
1998
1999
static void
2000
riscv_parse_add_subset (riscv_parse_subset_t *rps,
2001
      const char *subset,
2002
      int major,
2003
      int minor,
2004
      bool implicit)
2005
22.7k
{
2006
22.7k
  int major_version = major;
2007
22.7k
  int minor_version = minor;
2008
2009
22.7k
  if ((major_version == RISCV_UNKNOWN_VERSION
2010
0
       || minor_version == RISCV_UNKNOWN_VERSION)
2011
22.7k
      && rps->isa_spec != NULL)
2012
22.7k
    riscv_get_default_ext_version (*rps->isa_spec, subset,
2013
22.7k
           &major_version, &minor_version);
2014
2015
  /* We don't care the versions of the implicit extensions.  */
2016
22.7k
  if (!implicit
2017
1.62k
      && (major_version == RISCV_UNKNOWN_VERSION
2018
1.62k
    || minor_version == RISCV_UNKNOWN_VERSION))
2019
0
    {
2020
0
      if (subset[0] == 'x')
2021
0
  rps->error_handler
2022
0
    (_("x ISA extension `%s' must be set with the versions"),
2023
0
     subset);
2024
      /* Allow old ISA spec can recognize zicsr and zifencei.  */
2025
0
      else if (strcmp (subset, "zicsr") != 0
2026
0
         && strcmp (subset, "zifencei") != 0)
2027
0
  rps->error_handler
2028
0
    (_("cannot find default versions of the ISA extension `%s'"),
2029
0
     subset);
2030
0
      return;
2031
0
    }
2032
2033
22.7k
  riscv_add_subset (rps->subset_list, subset,
2034
22.7k
        major_version, minor_version);
2035
22.7k
}
2036
2037
/* Release subset list.  */
2038
2039
void
2040
riscv_release_subset_list (riscv_subset_list_t *subset_list)
2041
3.24k
{
2042
25.9k
   while (subset_list->head != NULL)
2043
22.7k
    {
2044
22.7k
      riscv_subset_t *next = subset_list->head->next;
2045
22.7k
      free ((void *)subset_list->head->name);
2046
22.7k
      free (subset_list->head);
2047
22.7k
      subset_list->head = next;
2048
22.7k
    }
2049
2050
3.24k
  subset_list->tail = NULL;
2051
2052
3.24k
  if (subset_list->arch_str != NULL)
2053
1.62k
    {
2054
1.62k
      free ((void*) subset_list->arch_str);
2055
1.62k
      subset_list->arch_str = NULL;
2056
1.62k
    }
2057
3.24k
}
2058
2059
/* Parsing extension version.
2060
2061
   Return Value:
2062
     Points to the end of version
2063
2064
   Arguments:
2065
     `p`: Curent parsing position.
2066
     `major_version`: Parsed major version.
2067
     `minor_version`: Parsed minor version.  */
2068
2069
static const char *
2070
riscv_parsing_subset_version (const char *p,
2071
            int *major_version,
2072
            int *minor_version)
2073
25.9k
{
2074
25.9k
  bool major_p = true;
2075
25.9k
  int version = 0;
2076
25.9k
  char np;
2077
2078
25.9k
  *major_version = 0;
2079
25.9k
  *minor_version = 0;
2080
25.9k
  for (; *p; ++p)
2081
12.9k
    {
2082
12.9k
      if (*p == 'p')
2083
0
  {
2084
0
    np = *(p + 1);
2085
2086
    /* Might be beginning of `p` extension.  */
2087
0
    if (!ISDIGIT (np))
2088
0
      break;
2089
2090
0
    *major_version = version;
2091
0
    major_p = false;
2092
0
    version = 0;
2093
0
  }
2094
12.9k
      else if (ISDIGIT (*p))
2095
0
  version = (version * 10) + (*p - '0');
2096
12.9k
      else
2097
12.9k
  break;
2098
12.9k
    }
2099
2100
25.9k
  if (major_p)
2101
25.9k
    *major_version = version;
2102
0
  else
2103
0
    *minor_version = version;
2104
2105
  /* We can not find any version in string.  */
2106
25.9k
  if (*major_version == 0 && *minor_version == 0)
2107
25.9k
    {
2108
25.9k
      *major_version = RISCV_UNKNOWN_VERSION;
2109
25.9k
      *minor_version = RISCV_UNKNOWN_VERSION;
2110
25.9k
    }
2111
2112
25.9k
  return p;
2113
25.9k
}
2114
2115
/* Parsing function for both standard and prefixed extensions.
2116
2117
   Return Value:
2118
     Points to the end of extensions.
2119
2120
   Arguments:
2121
     `rps`: Hooks and status for parsing extensions.
2122
     `arch`: Full ISA string.
2123
     `p`: Curent parsing position.  */
2124
2125
static const char *
2126
riscv_parse_extensions (riscv_parse_subset_t *rps,
2127
      const char *arch,
2128
      const char *p,
2129
      bool profile)
2130
1.62k
{
2131
  /* First letter must start with i, e, g or a profile.  */
2132
1.62k
  if (*p != 'e' && *p != 'i' && *p != 'g' && !profile)
2133
0
    {
2134
0
      rps->error_handler
2135
0
  (_("%s: first ISA extension must be `e', `i' or `g'"),
2136
0
   arch);
2137
0
      return NULL;
2138
0
    }
2139
2140
4.86k
  while (*p != '\0')
2141
3.24k
    {
2142
3.24k
      if (*p == '_')
2143
0
  {
2144
0
    p++;
2145
0
    continue;
2146
0
  }
2147
2148
3.24k
      char *subset = xstrdup (p);
2149
3.24k
      char *q = subset; /* Start of version.  */
2150
3.24k
      const char *end_of_version;
2151
3.24k
      bool implicit = false;
2152
2153
3.24k
      enum riscv_prefix_ext_class class = riscv_get_prefix_class (p);
2154
3.24k
      if (class == RV_ISA_CLASS_SINGLE)
2155
3.24k
  {
2156
3.24k
    if (riscv_ext_order[(*subset - 'a')] == 0)
2157
0
      {
2158
0
        rps->error_handler
2159
0
    (_("%s: unknown standard ISA extension or prefix class `%c'"),
2160
0
     arch, *subset);
2161
0
        free (subset);
2162
0
        return NULL;
2163
0
      }
2164
3.24k
    q++;
2165
3.24k
  }
2166
0
      else
2167
0
  {
2168
    /* Extract the whole prefixed extension by '_'.  */
2169
0
    while (*++q != '\0' && *q != '_')
2170
0
      ;
2171
    /* Look forward to the first letter which is not <major>p<minor>.  */
2172
0
    bool find_any_version = false;
2173
0
    bool find_minor_version = false;
2174
0
    while (1)
2175
0
      {
2176
0
        q--;
2177
0
        if (ISDIGIT (*q))
2178
0
    find_any_version = true;
2179
0
        else if (find_any_version
2180
0
           && !find_minor_version
2181
0
           && q > subset
2182
0
           && *q == 'p'
2183
0
           && ISDIGIT (*(q - 1)))
2184
0
    find_minor_version = true;
2185
0
        else
2186
0
    break;
2187
0
      }
2188
2189
    /* Check if the end of extension is 'p' or not.  If yes, then
2190
       the second letter from the end cannot be number.  */
2191
0
    if (q > subset && *q == 'p' && ISDIGIT (*(q - 1)))
2192
0
      {
2193
0
        q[1] = '\0';
2194
0
        rps->error_handler
2195
0
    (_("%s: invalid prefixed ISA extension `%s' ends with <number>p"),
2196
0
     arch, subset);
2197
0
        free (subset);
2198
0
        return NULL;
2199
0
      }
2200
2201
0
    q++;
2202
0
  }
2203
2204
3.24k
      int major_version = RISCV_UNKNOWN_VERSION;
2205
3.24k
      int minor_version = RISCV_UNKNOWN_VERSION;
2206
3.24k
      end_of_version =
2207
3.24k
  riscv_parsing_subset_version (q, &major_version, &minor_version);
2208
3.24k
      *q = '\0';
2209
2210
      /* Check if the prefixed extension name is well-formed.  */
2211
3.24k
      if (class != RV_ISA_CLASS_SINGLE
2212
0
    && rps->check_unknown_prefixed_ext
2213
0
    && !riscv_recognized_prefixed_ext (subset))
2214
0
  {
2215
0
    rps->error_handler
2216
0
      (_("%s: unknown prefixed ISA extension `%s'"),
2217
0
       arch, subset);
2218
0
    free (subset);
2219
0
    return NULL;
2220
0
  }
2221
2222
      /* Added g as an implicit extension.  */
2223
3.24k
      if (class == RV_ISA_CLASS_SINGLE
2224
3.24k
    && strcmp (subset, "g") == 0)
2225
1.62k
  {
2226
1.62k
    implicit = true;
2227
1.62k
    major_version = RISCV_UNKNOWN_VERSION;
2228
1.62k
    minor_version = RISCV_UNKNOWN_VERSION;
2229
1.62k
  }
2230
3.24k
      riscv_parse_add_subset (rps, subset,
2231
3.24k
            major_version,
2232
3.24k
            minor_version, implicit);
2233
3.24k
      p += end_of_version - subset;
2234
3.24k
      free (subset);
2235
2236
3.24k
      if (class != RV_ISA_CLASS_SINGLE
2237
0
    && *p != '\0' && *p != '_')
2238
0
  {
2239
0
    rps->error_handler
2240
0
      (_("%s: prefixed ISA extension must separate with _"),
2241
0
       arch);
2242
0
    return NULL;
2243
0
  }
2244
3.24k
    }
2245
2246
1.62k
  return p;
2247
1.62k
}
2248
2249
static bool
2250
riscv_update_subset1 (riscv_parse_subset_t *, riscv_subset_t *, const char *);
2251
2252
/* Add the implicit extensions.  */
2253
2254
static void
2255
riscv_parse_add_implicit_subsets (riscv_parse_subset_t *rps)
2256
1.62k
{
2257
1.62k
  const struct riscv_implicit_subset *t = riscv_implicit_subsets;
2258
222k
  for (; t->ext; t++)
2259
220k
    {
2260
220k
      riscv_subset_t *subset = NULL;
2261
220k
      if (riscv_lookup_subset (rps->subset_list, t->ext, &subset)
2262
14.5k
  && t->check_func (rps, subset))
2263
11.3k
      riscv_update_subset1 (rps, subset, t->implicit_exts);
2264
220k
    }
2265
1.62k
}
2266
2267
/* Check extensions conflicts.  */
2268
2269
static bool
2270
riscv_parse_check_conflicts (riscv_parse_subset_t *rps)
2271
1.62k
{
2272
1.62k
  riscv_subset_t *subset = NULL;
2273
1.62k
  int xlen = *rps->xlen;
2274
1.62k
  bool no_conflict = true;
2275
2276
1.62k
  if (riscv_subset_supports (rps, "e")
2277
0
      && riscv_subset_supports (rps, "h"))
2278
0
    {
2279
0
      rps->error_handler
2280
0
  (_("rv%de does not support the `h' extension"), xlen);
2281
0
      no_conflict = false;
2282
0
    }
2283
1.62k
  if (riscv_lookup_subset (rps->subset_list, "q", &subset)
2284
0
      && (subset->major_version < 2 || (subset->major_version == 2
2285
0
          && subset->minor_version < 2))
2286
0
      && xlen < 64)
2287
0
    {
2288
0
      rps->error_handler (_("rv%d does not support the `q' extension"), xlen);
2289
0
      no_conflict = false;
2290
0
    }
2291
1.62k
  if (riscv_subset_supports (rps, "zcmp")
2292
0
      && riscv_subset_supports (rps, "zcd"))
2293
0
    {
2294
0
      rps->error_handler
2295
0
  (_("zcmp' is incompatible with `d' and `c', or `zcd' extension"));
2296
0
      no_conflict = false;
2297
0
    }
2298
1.62k
  if (riscv_lookup_subset (rps->subset_list, "zcf", &subset)
2299
0
      && xlen > 32)
2300
0
    {
2301
0
      rps->error_handler
2302
0
  (_("rv%d does not support the `zcf' extension"), xlen);
2303
0
      no_conflict = false;
2304
0
    }
2305
1.62k
  if (riscv_lookup_subset (rps->subset_list, "zfinx", &subset)
2306
0
      && riscv_lookup_subset (rps->subset_list, "f", &subset))
2307
0
    {
2308
0
      rps->error_handler
2309
0
  (_("`zfinx' conflicts with the `f/d/q/zfh/zfhmin' extension"));
2310
0
      no_conflict = false;
2311
0
    }
2312
1.62k
  if (riscv_lookup_subset (rps->subset_list, "xtheadvector", &subset)
2313
0
      && riscv_lookup_subset (rps->subset_list, "zve32x", &subset))
2314
0
    {
2315
0
      rps->error_handler
2316
0
  (_("`xtheadvector' conflicts with the `v/zve32x' extension"));
2317
0
      no_conflict = false;
2318
0
    }
2319
1.62k
  if (riscv_lookup_subset (rps->subset_list, "zclsd", &subset)
2320
0
      && ((riscv_lookup_subset (rps->subset_list, "c", &subset)
2321
0
     && riscv_lookup_subset (rps->subset_list, "f", &subset))
2322
0
    || riscv_lookup_subset (rps->subset_list, "zcf", &subset)))
2323
0
    {
2324
0
      rps->error_handler
2325
0
  (_("`zclsd' conflicts with the `c+f'/`zcf' extension"));
2326
0
      no_conflict = false;
2327
0
    }
2328
1.62k
  if (riscv_lookup_subset (rps->subset_list, "ssnpm", &subset) && xlen != 64)
2329
0
    {
2330
0
      rps->error_handler (_ ("rv%d does not support the `ssnpm' extension"),
2331
0
        xlen);
2332
0
      no_conflict = false;
2333
0
    }
2334
1.62k
  if (riscv_lookup_subset (rps->subset_list, "smnpm", &subset) && xlen != 64)
2335
0
    {
2336
0
      rps->error_handler (_ ("rv%d does not support the `smnpm' extension"),
2337
0
        xlen);
2338
0
      no_conflict = false;
2339
0
    }
2340
1.62k
  if (riscv_lookup_subset (rps->subset_list, "smmpm", &subset) && xlen != 64)
2341
0
    {
2342
0
      rps->error_handler (_ ("rv%d does not support the `smmpm' extension"),
2343
0
        xlen);
2344
0
      no_conflict = false;
2345
0
    }
2346
1.62k
  if (riscv_lookup_subset (rps->subset_list, "sspm", &subset) && xlen != 64)
2347
0
    {
2348
0
      rps->error_handler (_ ("rv%d does not support the `sspm' extension"),
2349
0
        xlen);
2350
0
      no_conflict = false;
2351
0
    }
2352
1.62k
  if (riscv_lookup_subset (rps->subset_list, "supm", &subset) && xlen != 64)
2353
0
    {
2354
0
      rps->error_handler (_ ("rv%d does not support the `supm' extension"),
2355
0
        xlen);
2356
0
      no_conflict = false;
2357
0
    }
2358
2359
1.62k
  bool support_zve = false;
2360
1.62k
  bool support_zvl = false;
2361
1.62k
  riscv_subset_t *s = rps->subset_list->head;
2362
24.3k
  for (; s != NULL; s = s->next)
2363
22.7k
    {
2364
22.7k
      if (!support_zve
2365
22.7k
    && strncmp (s->name, "zve", 3) == 0)
2366
0
  support_zve = true;
2367
22.7k
      if (!support_zvl
2368
22.7k
    && strncmp (s->name, "zvl", 3) == 0)
2369
0
  support_zvl = true;
2370
22.7k
      if (support_zve && support_zvl)
2371
0
  break;
2372
22.7k
    }
2373
1.62k
  if (support_zvl && !support_zve)
2374
0
    {
2375
0
      rps->error_handler
2376
0
  (_("zvl*b extensions need to enable either `v' or `zve' extension"));
2377
0
      no_conflict = false;
2378
0
    }
2379
2380
1.62k
  return no_conflict;
2381
1.62k
}
2382
2383
/* Set the default subset list according to the default_enable field
2384
   of riscv_supported_*ext tables.  */
2385
2386
static void
2387
riscv_set_default_arch (riscv_parse_subset_t *rps)
2388
0
{
2389
0
  unsigned long enable = EXT_DEFAULT;
2390
0
  int i, j;
2391
0
  for (i = 0; riscv_all_supported_ext[i] != NULL; i++)
2392
0
    {
2393
0
      const struct riscv_supported_ext *table = riscv_all_supported_ext[i];
2394
0
      for (j = 0; table[j].name != NULL; j++)
2395
0
  {
2396
0
    bool implicit = false;
2397
0
    if (strcmp (table[j].name, "g") == 0)
2398
0
      implicit = true;
2399
0
    if (table[j].default_enable & enable)
2400
0
      riscv_parse_add_subset (rps, table[j].name,
2401
0
            RISCV_UNKNOWN_VERSION,
2402
0
            RISCV_UNKNOWN_VERSION, implicit);
2403
0
  }
2404
0
    }
2405
0
}
2406
2407
static bool
2408
riscv_find_profiles (riscv_parse_subset_t *rps, const char **pp)
2409
1.62k
{
2410
1.62k
  const char *p = *pp;
2411
2412
  /* Checking if input string contains a Profiles.
2413
     There are two cases use Profiles in -march option:
2414
2415
      1. Only use Profiles in '-march' as input
2416
      2. Mixed Profiles with other extensions
2417
2418
      Use '_' to split Profiles and other extensions.  */
2419
2420
14.5k
  for (int i = 0; riscv_profiles_table[i].profile_name != NULL; ++i)
2421
12.9k
    {
2422
      /* Find profile at the begin.  */
2423
12.9k
      if (startswith (p, riscv_profiles_table[i].profile_name))
2424
0
  {
2425
    /* Handle the profile string.  */
2426
0
    riscv_parse_subset (rps, riscv_profiles_table[i].profile_string);
2427
0
    p += strlen (riscv_profiles_table[i].profile_name);
2428
    /* Handle string after profiles if exists.  If missing underline
2429
       bewteen profile and other extensions, warn the user but not deal
2430
       as an error.  */
2431
0
    if (*p != '\0' && *p != '_')
2432
0
      _bfd_error_handler
2433
0
        (_("Warning: should use \"_\" to contact Profiles with other "
2434
0
     "extensions"));
2435
0
    *pp = p;
2436
0
    return true;
2437
0
  }
2438
12.9k
    }
2439
  /* Not found profile, return directly.  */
2440
1.62k
  return false;
2441
1.62k
}
2442
2443
/* Function for parsing ISA string.
2444
2445
   Return Value:
2446
     Return TRUE on success.
2447
2448
   Arguments:
2449
     `rps`: Hooks and status for parsing extensions.
2450
     `arch`: Full ISA string.  */
2451
2452
bool
2453
riscv_parse_subset (riscv_parse_subset_t *rps,
2454
        const char *arch)
2455
1.62k
{
2456
1.62k
  const char *p;
2457
2458
  /* Init the riscv_ext_order array to compare the order of extensions
2459
     quickly.  */
2460
1.62k
  riscv_init_ext_order ();
2461
2462
1.62k
  if (arch == NULL)
2463
0
    {
2464
0
      riscv_set_default_arch (rps);
2465
0
      riscv_parse_add_implicit_subsets (rps);
2466
0
      return riscv_parse_check_conflicts (rps);
2467
0
    }
2468
2469
11.3k
  for (p = arch; *p != '\0'; p++)
2470
9.73k
    {
2471
9.73k
      if (ISUPPER (*p))
2472
0
  {
2473
0
    rps->error_handler
2474
0
      (_("%s: ISA string cannot contain uppercase letters"),
2475
0
       arch);
2476
0
    return false;
2477
0
  }
2478
9.73k
    }
2479
2480
1.62k
  bool profile = false;
2481
1.62k
  p = arch;
2482
1.62k
  if (riscv_find_profiles (rps, &p))
2483
0
    {
2484
      /* Check if using Profiles.  */
2485
0
      profile = true;
2486
0
    }
2487
1.62k
  else if (startswith (p, "rv32"))
2488
0
    {
2489
0
      *rps->xlen = 32;
2490
0
      p += 4;
2491
0
    }
2492
1.62k
  else if (startswith (p, "rv64"))
2493
1.62k
    {
2494
1.62k
      *rps->xlen = 64;
2495
1.62k
      p += 4;
2496
1.62k
    }
2497
0
  else
2498
0
    {
2499
      /* ISA string shouldn't be NULL or empty here.  For linker,
2500
   it might be empty when we failed to merge the ISA string
2501
   in the riscv_merge_attributes.  For assembler, we might
2502
   give an empty string by .attribute arch, "" or -march=.
2503
   However, We have already issued the correct error message
2504
   in another side, so do not issue this error when the ISA
2505
   string is empty.  */
2506
0
      if (strlen (arch))
2507
0
  rps->error_handler (
2508
0
    _("%s: ISA string must begin with rv32, rv64 or Profiles"),
2509
0
    arch);
2510
0
      return false;
2511
0
    }
2512
2513
  /* Parse single standard and prefixed extensions.  */
2514
1.62k
  if (riscv_parse_extensions (rps, arch, p, profile) == NULL)
2515
0
    return false;
2516
2517
  /* Finally add implicit extensions according to the current
2518
     extensions.  */
2519
1.62k
  riscv_parse_add_implicit_subsets (rps);
2520
2521
  /* Check the conflicts.  */
2522
1.62k
  return riscv_parse_check_conflicts (rps);
2523
1.62k
}
2524
2525
/* Return the number of digits for the input.  */
2526
2527
size_t
2528
riscv_estimate_digit (unsigned num)
2529
45.4k
{
2530
45.4k
  size_t digit = 0;
2531
45.4k
  if (num == 0)
2532
14.5k
    return 1;
2533
2534
90.8k
  for (digit = 0; num ; num /= 10)
2535
60.0k
    digit++;
2536
2537
30.8k
  return digit;
2538
45.4k
}
2539
2540
/* Auxiliary function to estimate string length of subset list.  */
2541
2542
static size_t
2543
riscv_estimate_arch_strlen1 (const riscv_subset_t *subset)
2544
24.3k
{
2545
24.3k
  if (subset == NULL)
2546
1.62k
    return 6; /* For rv32/rv64/rv128 and string terminator.  */
2547
2548
22.7k
  return riscv_estimate_arch_strlen1 (subset->next)
2549
22.7k
   + strlen (subset->name)
2550
22.7k
   + riscv_estimate_digit (subset->major_version)
2551
22.7k
   + 1 /* For version seperator 'p'.  */
2552
22.7k
   + riscv_estimate_digit (subset->minor_version)
2553
22.7k
   + 1 /* For underscore.  */;
2554
24.3k
}
2555
2556
/* Estimate the string length of this subset list.  */
2557
2558
static size_t
2559
riscv_estimate_arch_strlen (const riscv_subset_list_t *subset_list)
2560
1.62k
{
2561
1.62k
  return riscv_estimate_arch_strlen1 (subset_list->head);
2562
1.62k
}
2563
2564
/* Auxiliary function to convert subset info to string.  */
2565
2566
static void
2567
riscv_arch_str1 (riscv_subset_t *subset,
2568
     char *attr_str, char *buf, size_t bufsz)
2569
22.7k
{
2570
22.7k
  const char *underline = "_";
2571
22.7k
  riscv_subset_t *subset_t = subset;
2572
2573
22.7k
  if (subset_t == NULL)
2574
1.62k
    return;
2575
2576
  /* No underline between rvXX and i/e.  */
2577
21.0k
  if ((strcasecmp (subset_t->name, "i") == 0)
2578
19.4k
      || (strcasecmp (subset_t->name, "e") == 0))
2579
1.62k
    underline = "";
2580
2581
21.0k
  snprintf (buf, bufsz, "%s%s%dp%d",
2582
21.0k
      underline,
2583
21.0k
      subset_t->name,
2584
21.0k
      subset_t->major_version,
2585
21.0k
      subset_t->minor_version);
2586
2587
21.0k
  strncat (attr_str, buf, bufsz);
2588
2589
  /* Skip 'i' extension after 'e', or skip extensions which
2590
     versions are unknown.  */
2591
22.7k
  while (subset_t->next
2592
21.0k
   && ((strcmp (subset_t->name, "e") == 0
2593
0
        && strcmp (subset_t->next->name, "i") == 0)
2594
21.0k
       || subset_t->next->major_version == RISCV_UNKNOWN_VERSION
2595
19.4k
       || subset_t->next->minor_version == RISCV_UNKNOWN_VERSION))
2596
1.62k
    subset_t = subset_t->next;
2597
2598
21.0k
  riscv_arch_str1 (subset_t->next, attr_str, buf, bufsz);
2599
21.0k
}
2600
2601
/* Convert subset information into string with explicit versions.  */
2602
2603
char *
2604
riscv_arch_str (unsigned xlen, riscv_subset_list_t *subset, bool update)
2605
1.62k
{
2606
1.62k
  size_t arch_str_len = riscv_estimate_arch_strlen (subset);
2607
1.62k
  char *attr_str = xmalloc (arch_str_len);
2608
1.62k
  char *buf = xmalloc (arch_str_len);
2609
2610
1.62k
  snprintf (attr_str, arch_str_len, "rv%u", xlen);
2611
2612
1.62k
  riscv_arch_str1 (subset->head, attr_str, buf, arch_str_len);
2613
1.62k
  free (buf);
2614
2615
1.62k
  if (update)
2616
1.62k
    {
2617
1.62k
      if (subset->arch_str != NULL)
2618
0
  free ((void *) subset->arch_str);
2619
1.62k
      subset->arch_str = attr_str;
2620
1.62k
    }
2621
2622
1.62k
  return attr_str;
2623
1.62k
}
2624
2625
/* Copy the subset in the subset list.  */
2626
2627
static struct riscv_subset_t *
2628
riscv_copy_subset (riscv_subset_list_t *subset_list,
2629
       riscv_subset_t *subset)
2630
0
{
2631
0
  if (subset == NULL)
2632
0
    return NULL;
2633
2634
0
  riscv_subset_t *new = xmalloc (sizeof *new);
2635
0
  new->name = xstrdup (subset->name);
2636
0
  new->major_version = subset->major_version;
2637
0
  new->minor_version = subset->minor_version;
2638
0
  new->next = riscv_copy_subset (subset_list, subset->next);
2639
2640
0
  if (subset->next == NULL)
2641
0
    subset_list->tail = new;
2642
2643
0
  return new;
2644
0
}
2645
2646
/* Copy the subset list.  */
2647
2648
riscv_subset_list_t *
2649
riscv_copy_subset_list (riscv_subset_list_t *subset_list)
2650
0
{
2651
0
  riscv_subset_list_t *new = xmalloc (sizeof *new);
2652
0
  new->head = riscv_copy_subset (new, subset_list->head);
2653
0
  new->arch_str = xstrdup (subset_list->arch_str);
2654
0
  return new;
2655
0
}
2656
2657
/* Remove the SUBSET from the subset list.  */
2658
2659
static void
2660
riscv_remove_subset (riscv_subset_list_t *subset_list,
2661
         const char *subset)
2662
0
{
2663
0
  riscv_subset_t *current = subset_list->head;
2664
0
  riscv_subset_t *pre = NULL;
2665
0
  for (; current != NULL; pre = current, current = current->next)
2666
0
    {
2667
0
      if (strcmp (current->name, subset) == 0)
2668
0
  {
2669
0
    if (pre == NULL)
2670
0
      subset_list->head = current->next;
2671
0
    else
2672
0
      pre->next = current->next;
2673
0
    if (current->next == NULL)
2674
0
      subset_list->tail = pre;
2675
0
    free ((void *) current->name);
2676
0
    free (current);
2677
0
    break;
2678
0
  }
2679
0
    }
2680
0
}
2681
2682
/* Auxiliary to add/remove extensions to/from the subset list.
2683
   This is called from riscv_update_subset or riscv_parse_add_implicit_subsets.
2684
2685
   The EXPLICIT_SUBSET, the corresponding explicit extension.  It is NULL means
2686
   called from riscv_update_subset./
2687
2688
   The IMPLICIT_EXTS, +extension[version] [,...,+extension_n[version_n]]
2689
          (Deprecated) -extension [,...,-extension_n],
2690
          full ISA.  */
2691
2692
static bool
2693
riscv_update_subset1 (riscv_parse_subset_t *rps,
2694
          riscv_subset_t *explicit_subset,
2695
          const char *implicit_exts)
2696
11.3k
{
2697
11.3k
  const char *p = implicit_exts;
2698
11.3k
  const char *errmsg_internal = explicit_subset == NULL ? "" : _("internal: ");
2699
11.3k
  const char *errmsg_caller = explicit_subset == NULL
2700
11.3k
            ? ".option arch" : "riscv_implicit_subsets";
2701
2702
11.3k
  do
2703
22.7k
    {
2704
22.7k
      int major_version = RISCV_UNKNOWN_VERSION;
2705
22.7k
      int minor_version = RISCV_UNKNOWN_VERSION;
2706
2707
22.7k
      bool removed = false;
2708
22.7k
      switch (*p)
2709
22.7k
  {
2710
22.7k
  case '+': removed = false; break;
2711
0
  case '-': removed = true; break;
2712
0
  default:
2713
0
    riscv_release_subset_list (rps->subset_list);
2714
0
    return riscv_parse_subset (rps, p);
2715
22.7k
  }
2716
22.7k
      ++p;
2717
2718
22.7k
      char *subset = xstrdup (p);
2719
22.7k
      char *q = subset;
2720
22.7k
      const char *end_of_version;
2721
      /* Extract the whole prefixed extension by ','.  */
2722
97.3k
      while (*q != '\0' && *q != ',')
2723
74.6k
        q++;
2724
2725
      /* Look forward to the first letter which is not <major>p<minor>.  */
2726
22.7k
      bool find_any_version = false;
2727
22.7k
      bool find_minor_version = false;
2728
22.7k
      size_t len = q - subset;
2729
22.7k
      size_t i;
2730
22.7k
      for (i = len; i > 0; i--)
2731
22.7k
        {
2732
22.7k
    q--;
2733
22.7k
    if (ISDIGIT (*q))
2734
0
      find_any_version = true;
2735
22.7k
    else if (find_any_version
2736
0
       && !find_minor_version
2737
0
       && q > subset
2738
0
       && *q == 'p'
2739
0
       && ISDIGIT (*(q - 1)))
2740
0
      find_minor_version = true;
2741
22.7k
    else
2742
22.7k
      break;
2743
22.7k
  }
2744
2745
      /* Check if the end of extension is 'p' or not.  If yes, then
2746
   the second letter from the end cannot be number.  */
2747
22.7k
      if (q > subset && *q == 'p' && ISDIGIT (*(q - 1)))
2748
0
  {
2749
0
    q[1] = '\0';
2750
0
    rps->error_handler
2751
0
      (_("%sinvalid ISA extension `%s' ends with <number>p in %s `%s'"),
2752
0
         errmsg_internal, subset, errmsg_caller, implicit_exts);
2753
0
    free (subset);
2754
0
    return false;
2755
0
  }
2756
2757
22.7k
      if (len > 0)
2758
22.7k
  q++;
2759
2760
22.7k
      end_of_version =
2761
22.7k
  riscv_parsing_subset_version (q, &major_version, &minor_version);
2762
22.7k
      *q = '\0';
2763
2764
22.7k
      if (strlen (subset) == 0
2765
22.7k
    || (strlen (subset) == 1
2766
9.73k
        && riscv_ext_order[(*subset - 'a')] == 0)
2767
22.7k
    || (strlen (subset) > 1
2768
12.9k
        && rps->check_unknown_prefixed_ext
2769
0
        && !riscv_recognized_prefixed_ext (subset)))
2770
0
  {
2771
0
    rps->error_handler
2772
0
      (_("%sunknown ISA extension `%s' in %s `%s'"),
2773
0
       errmsg_internal, subset, errmsg_caller, implicit_exts);
2774
0
    free (subset);
2775
0
    return false;
2776
0
  }
2777
2778
22.7k
      if (explicit_subset == NULL)
2779
0
  {
2780
0
    if (removed)
2781
0
      {
2782
0
        rps->error_handler
2783
0
    (_("deprecated - extension `%s' in %s `%s'"),
2784
0
       subset, errmsg_caller, implicit_exts);
2785
0
        free (subset);
2786
0
        return false;
2787
0
      }
2788
0
    else if (strcmp (subset, "i") == 0
2789
0
       || strcmp (subset, "e") == 0
2790
0
       || strcmp (subset, "g") == 0)
2791
0
      {
2792
0
        rps->error_handler
2793
0
    (_("cannot + base extension `%s' in %s `%s'"),
2794
0
       subset, errmsg_caller, implicit_exts);
2795
0
        free (subset);
2796
0
        return false;
2797
0
      }
2798
0
  }
2799
2800
22.7k
      if (removed)
2801
0
  riscv_remove_subset (rps->subset_list, subset);
2802
22.7k
      else
2803
22.7k
  {
2804
22.7k
    riscv_subset_t *isubset = NULL;
2805
22.7k
    if (!riscv_lookup_subset (rps->subset_list, subset, &isubset))
2806
19.4k
      riscv_parse_add_subset (rps, subset, major_version, minor_version,
2807
19.4k
            true/* implicit */);
2808
22.7k
  }
2809
22.7k
      p += end_of_version - subset;
2810
22.7k
      free (subset);
2811
22.7k
    }
2812
22.7k
  while (*p++ == ',');
2813
2814
11.3k
  bool no_conflict = true;
2815
11.3k
  if (explicit_subset == NULL)
2816
0
    {
2817
0
      riscv_parse_add_implicit_subsets (rps);
2818
0
      no_conflict = riscv_parse_check_conflicts (rps);
2819
0
    }
2820
11.3k
  return no_conflict;
2821
11.3k
}
2822
2823
/* Add an extension to/from the subset list.  This is used for the .option rvc
2824
   and .option arch directives.  */
2825
2826
bool
2827
riscv_update_subset (riscv_parse_subset_t *rps,
2828
         const char *str)
2829
0
{
2830
0
  unsigned int newxlen = *rps->xlen;
2831
0
  riscv_parse_subset_t newrps = {
2832
0
    .subset_list = riscv_copy_subset_list (rps->subset_list),
2833
0
    .error_handler = rps->error_handler,
2834
0
    .xlen = &newxlen,
2835
0
    .isa_spec = rps->isa_spec,
2836
0
    .check_unknown_prefixed_ext = rps->check_unknown_prefixed_ext,
2837
0
  };
2838
2839
0
  if (!riscv_update_subset1 (&newrps, NULL, str))
2840
0
    {
2841
0
      riscv_release_subset_list (newrps.subset_list);
2842
0
      free (newrps.subset_list);
2843
0
      return false;
2844
0
    }
2845
2846
0
  *rps->xlen = newxlen;
2847
0
  riscv_release_subset_list (rps->subset_list);
2848
0
  *rps->subset_list = *newrps.subset_list;
2849
0
  free (newrps.subset_list);
2850
2851
0
  return true;
2852
0
}
2853
2854
/* Called from .option norvc directives.  */
2855
2856
bool
2857
riscv_update_subset_norvc (riscv_parse_subset_t *rps)
2858
0
{
2859
0
  return riscv_update_subset1 (rps, rps->subset_list->head,
2860
0
             "-c,-zca,-zcd,-zcf,-zcb,-zce,-zcmp,-zcmt,"
2861
0
             "-zcmop,-zclsd");
2862
0
}
2863
2864
/* Check if the FEATURE subset is supported or not in the subset list.
2865
   Return true if it is supported; Otherwise, return false.  */
2866
2867
bool
2868
riscv_subset_supports (riscv_parse_subset_t *rps,
2869
           const char *feature)
2870
4.70M
{
2871
4.70M
  struct riscv_subset_t *subset;
2872
4.70M
  return riscv_lookup_subset (rps->subset_list, feature, &subset);
2873
4.70M
}
2874
2875
/* Each instuction is belonged to an instruction class INSN_CLASS_*.
2876
   Call riscv_subset_supports to make sure if the instuction is valid.  */
2877
2878
bool
2879
riscv_multi_subset_supports (riscv_parse_subset_t *rps,
2880
           enum riscv_insn_class insn_class)
2881
1.53M
{
2882
1.53M
  switch (insn_class)
2883
1.53M
    {
2884
70.5k
    case INSN_CLASS_I:
2885
70.5k
      return riscv_subset_supports (rps, "i");
2886
163
    case INSN_CLASS_ZICBOM:
2887
163
      return riscv_subset_supports (rps, "zicbom");
2888
179
    case INSN_CLASS_ZICBOP:
2889
179
      return riscv_subset_supports (rps, "zicbop");
2890
69
    case INSN_CLASS_ZICBOZ:
2891
69
      return riscv_subset_supports (rps, "zicboz");
2892
97
    case INSN_CLASS_ZICOND:
2893
97
      return riscv_subset_supports (rps, "zicond");
2894
9.26k
    case INSN_CLASS_ZICSR:
2895
9.26k
      return riscv_subset_supports (rps, "zicsr");
2896
56
    case INSN_CLASS_ZIFENCEI:
2897
56
      return riscv_subset_supports (rps, "zifencei");
2898
55
    case INSN_CLASS_ZIHINTNTL:
2899
55
      return riscv_subset_supports (rps, "zihintntl");
2900
190
    case INSN_CLASS_ZIHINTNTL_AND_ZCA:
2901
190
      return riscv_subset_supports (rps, "zihintntl")
2902
0
       && riscv_subset_supports (rps, "zca");
2903
151
    case INSN_CLASS_ZIHINTPAUSE:
2904
151
      return riscv_subset_supports (rps, "zihintpause");
2905
128
    case INSN_CLASS_ZIMOP:
2906
128
      return riscv_subset_supports (rps, "zimop");
2907
92
    case INSN_CLASS_ZICFISS:
2908
92
      return riscv_subset_supports (rps, "zicfiss");
2909
318
    case INSN_CLASS_ZICFISS_AND_ZCMOP:
2910
318
      return riscv_subset_supports (rps, "zicfiss")
2911
0
       && riscv_subset_supports (rps, "zcmop");
2912
1.07k
    case INSN_CLASS_ZICFILP:
2913
1.07k
      return riscv_subset_supports (rps, "zicfilp");
2914
210
    case INSN_CLASS_M:
2915
210
      return riscv_subset_supports (rps, "m");
2916
183
    case INSN_CLASS_ZMMUL:
2917
183
      return riscv_subset_supports (rps, "zmmul");
2918
1.22k
    case INSN_CLASS_ZAAMO:
2919
1.22k
      return riscv_subset_supports (rps, "zaamo");
2920
1.27k
    case INSN_CLASS_ZABHA:
2921
1.27k
      return riscv_subset_supports (rps, "zabha");
2922
1.62k
    case INSN_CLASS_ZACAS:
2923
1.62k
      return riscv_subset_supports (rps, "zacas");
2924
323
    case INSN_CLASS_ZABHA_AND_ZACAS:
2925
323
      return (riscv_subset_supports (rps, "zabha")
2926
0
        && riscv_subset_supports (rps, "zacas"));
2927
23
    case INSN_CLASS_ZALASR:
2928
23
      return riscv_subset_supports (rps, "zalasr");
2929
194
    case INSN_CLASS_ZALRSC:
2930
194
      return riscv_subset_supports (rps, "zalrsc");
2931
106
    case INSN_CLASS_ZAWRS:
2932
106
      return riscv_subset_supports (rps, "zawrs");
2933
3.90k
    case INSN_CLASS_F:
2934
3.90k
      return riscv_subset_supports (rps, "f");
2935
1.03k
    case INSN_CLASS_D:
2936
1.03k
      return riscv_subset_supports (rps, "d");
2937
1.41k
    case INSN_CLASS_Q:
2938
1.41k
      return riscv_subset_supports (rps, "q");
2939
1.14M
    case INSN_CLASS_ZCA:
2940
1.14M
      return riscv_subset_supports (rps, "zca");
2941
0
    case INSN_CLASS_ZCF:
2942
0
      return riscv_subset_supports (rps, "zcf");
2943
151k
    case INSN_CLASS_ZCD:
2944
151k
      return riscv_subset_supports (rps, "zcd");
2945
10.5k
    case INSN_CLASS_F_INX:
2946
10.5k
      return (riscv_subset_supports (rps, "f")
2947
0
        || riscv_subset_supports (rps, "zfinx"));
2948
8.06k
    case INSN_CLASS_D_INX:
2949
8.06k
      return (riscv_subset_supports (rps, "d")
2950
0
        || riscv_subset_supports (rps, "zdinx"));
2951
7.27k
    case INSN_CLASS_Q_INX:
2952
7.27k
      return (riscv_subset_supports (rps, "q")
2953
7.27k
        || riscv_subset_supports (rps, "zqinx"));
2954
5.36k
    case INSN_CLASS_ZFH_INX:
2955
5.36k
      return (riscv_subset_supports (rps, "zfh")
2956
5.36k
        || riscv_subset_supports (rps, "zhinx"));
2957
927
    case INSN_CLASS_ZFHMIN:
2958
927
      return riscv_subset_supports (rps, "zfhmin");
2959
110
    case INSN_CLASS_ZFHMIN_INX:
2960
110
      return (riscv_subset_supports (rps, "zfhmin")
2961
110
        || riscv_subset_supports (rps, "zhinxmin"));
2962
12
    case INSN_CLASS_ZFHMIN_AND_D_INX:
2963
12
      return ((riscv_subset_supports (rps, "zfhmin")
2964
0
         && riscv_subset_supports (rps, "d"))
2965
12
        || (riscv_subset_supports (rps, "zhinxmin")
2966
0
      && riscv_subset_supports (rps, "zdinx")));
2967
78
    case INSN_CLASS_ZFHMIN_AND_Q_INX:
2968
78
      return ((riscv_subset_supports (rps, "zfhmin")
2969
0
         && riscv_subset_supports (rps, "q"))
2970
78
        || (riscv_subset_supports (rps, "zhinxmin")
2971
0
      && riscv_subset_supports (rps, "zqinx")));
2972
22
    case INSN_CLASS_ZFBFMIN:
2973
22
      return riscv_subset_supports (rps, "zfbfmin");
2974
158
    case INSN_CLASS_ZFA:
2975
158
      return riscv_subset_supports (rps, "zfa");
2976
161
    case INSN_CLASS_D_AND_ZFA:
2977
161
      return riscv_subset_supports (rps, "d")
2978
161
       && riscv_subset_supports (rps, "zfa");
2979
109
    case INSN_CLASS_Q_AND_ZFA:
2980
109
      return riscv_subset_supports (rps, "q")
2981
0
       && riscv_subset_supports (rps, "zfa");
2982
99
    case INSN_CLASS_ZFH_AND_ZFA:
2983
99
      return riscv_subset_supports (rps, "zfh")
2984
0
       && riscv_subset_supports (rps, "zfa");
2985
0
    case INSN_CLASS_ZFH_OR_ZVFH_AND_ZFA:
2986
0
      return (riscv_subset_supports (rps, "zfh")
2987
0
        || riscv_subset_supports (rps, "zvfh"))
2988
0
       && riscv_subset_supports (rps, "zfa");
2989
192
    case INSN_CLASS_ZBA:
2990
192
      return riscv_subset_supports (rps, "zba");
2991
206
    case INSN_CLASS_ZBB:
2992
206
      return riscv_subset_supports (rps, "zbb");
2993
20
    case INSN_CLASS_ZBC:
2994
20
      return riscv_subset_supports (rps, "zbc");
2995
304
    case INSN_CLASS_ZBS:
2996
304
      return riscv_subset_supports (rps, "zbs");
2997
101
    case INSN_CLASS_ZBKB:
2998
101
      return riscv_subset_supports (rps, "zbkb");
2999
0
    case INSN_CLASS_ZBKC:
3000
0
      return riscv_subset_supports (rps, "zbkc");
3001
55
    case INSN_CLASS_ZBKX:
3002
55
      return riscv_subset_supports (rps, "zbkx");
3003
270
    case INSN_CLASS_ZBB_OR_ZBKB:
3004
270
      return (riscv_subset_supports (rps, "zbb")
3005
270
        || riscv_subset_supports (rps, "zbkb"));
3006
39
    case INSN_CLASS_ZBC_OR_ZBKC:
3007
39
      return (riscv_subset_supports (rps, "zbc")
3008
39
        || riscv_subset_supports (rps, "zbkc"));
3009
162
    case INSN_CLASS_ZKND:
3010
162
      return riscv_subset_supports (rps, "zknd");
3011
55
    case INSN_CLASS_ZKNE:
3012
55
      return riscv_subset_supports (rps, "zkne");
3013
178
    case INSN_CLASS_ZKNH:
3014
178
      return riscv_subset_supports (rps, "zknh");
3015
69
    case INSN_CLASS_ZKND_OR_ZKNE:
3016
69
      return (riscv_subset_supports (rps, "zknd")
3017
69
        || riscv_subset_supports (rps, "zkne"));
3018
137
    case INSN_CLASS_ZKSED:
3019
137
      return riscv_subset_supports (rps, "zksed");
3020
221
    case INSN_CLASS_ZKSH:
3021
221
      return riscv_subset_supports (rps, "zksh");
3022
9.17k
    case INSN_CLASS_V:
3023
9.17k
      return (riscv_subset_supports (rps, "v")
3024
9.17k
        || riscv_subset_supports (rps, "zve64x")
3025
9.17k
        || riscv_subset_supports (rps, "zve32x"));
3026
557
    case INSN_CLASS_ZVE64X:
3027
557
      return (riscv_subset_supports (rps, "v")
3028
557
        || riscv_subset_supports (rps, "zve64x"));
3029
1.13k
    case INSN_CLASS_ZVEF:
3030
1.13k
      return (riscv_subset_supports (rps, "v")
3031
1.13k
        || riscv_subset_supports (rps, "zve64d")
3032
1.13k
        || riscv_subset_supports (rps, "zve64f")
3033
1.13k
        || riscv_subset_supports (rps, "zve32f"));
3034
125
    case INSN_CLASS_ZVABD:
3035
125
      return riscv_subset_supports (rps, "zvabd");
3036
400
    case INSN_CLASS_ZVBB:
3037
400
      return riscv_subset_supports (rps, "zvbb");
3038
109
    case INSN_CLASS_ZVBC:
3039
109
      return riscv_subset_supports (rps, "zvbc");
3040
16
    case INSN_CLASS_ZVFBFMIN:
3041
16
      return riscv_subset_supports (rps, "zvfbfmin");
3042
117
    case INSN_CLASS_ZVFBFWMA:
3043
117
      return riscv_subset_supports (rps, "zvfbfwma");
3044
98
    case INSN_CLASS_ZVFBDOTA32F:
3045
98
      return riscv_subset_supports (rps, "zvfbdota32f");
3046
75
    case INSN_CLASS_ZVFQWBDOTA8F:
3047
75
      return riscv_subset_supports (rps, "zvfqwbdota8f");
3048
22
    case INSN_CLASS_ZVFQWDOTA8F:
3049
22
      return riscv_subset_supports (rps, "zvfqwdota8f");
3050
26
    case INSN_CLASS_ZVFWBDOTA16BF:
3051
26
      return riscv_subset_supports (rps, "zvfwbdota16bf");
3052
44
    case INSN_CLASS_ZVFWDOTA16BF:
3053
44
      return riscv_subset_supports (rps, "zvfwdota16bf");
3054
160
    case INSN_CLASS_ZVKB:
3055
160
      return riscv_subset_supports (rps, "zvkb");
3056
46
    case INSN_CLASS_ZVKG:
3057
46
      return riscv_subset_supports (rps, "zvkg");
3058
57
    case INSN_CLASS_ZVKNED:
3059
57
      return riscv_subset_supports (rps, "zvkned");
3060
78
    case INSN_CLASS_ZVKNHA_OR_ZVKNHB:
3061
78
      return (riscv_subset_supports (rps, "zvknha")
3062
78
        || riscv_subset_supports (rps, "zvknhb"));
3063
228
    case INSN_CLASS_ZVKSED:
3064
228
      return riscv_subset_supports (rps, "zvksed");
3065
29
    case INSN_CLASS_ZVKSH:
3066
29
      return riscv_subset_supports (rps, "zvksh");
3067
0
    case INSN_CLASS_ZVQWBDOTA8I:
3068
0
      return riscv_subset_supports (rps, "zvqwbdota8i");
3069
0
    case INSN_CLASS_ZVQWBDOTA16I:
3070
0
      return riscv_subset_supports (rps, "zvqwbdota16i");
3071
62
    case INSN_CLASS_ZVQWBDOTA8I_OR_ZVQWBDOTA16I:
3072
62
      return (riscv_subset_supports (rps, "zvqwbdota8i")
3073
62
        || riscv_subset_supports (rps, "zvqwbdota16i"));
3074
0
    case INSN_CLASS_ZVQWDOTA8I:
3075
0
      return riscv_subset_supports (rps, "zvqwdota8i");
3076
0
    case INSN_CLASS_ZVQWDOTA16I:
3077
0
      return riscv_subset_supports (rps, "zvqwdota16i");
3078
102
    case INSN_CLASS_ZVQWDOTA8I_OR_ZVQWDOTA16I:
3079
102
      return (riscv_subset_supports (rps, "zvqwdota8i")
3080
102
        || riscv_subset_supports (rps, "zvqwdota16i"));
3081
45.1k
    case INSN_CLASS_ZCB:
3082
45.1k
      return riscv_subset_supports (rps, "zcb");
3083
806
    case INSN_CLASS_ZCB_AND_ZBB:
3084
806
      return (riscv_subset_supports (rps, "zcb")
3085
0
        && riscv_subset_supports (rps, "zbb"));
3086
150
    case INSN_CLASS_ZCB_AND_ZBA:
3087
150
      return (riscv_subset_supports (rps, "zcb")
3088
0
        && riscv_subset_supports (rps, "zba"));
3089
1.54k
    case INSN_CLASS_ZCB_AND_ZMMUL:
3090
1.54k
      return (riscv_subset_supports (rps, "zcb")
3091
0
        && riscv_subset_supports (rps, "zmmul"));
3092
808
    case INSN_CLASS_ZCMOP:
3093
808
      return riscv_subset_supports (rps, "zcmop");
3094
0
    case INSN_CLASS_ZCMP:
3095
0
      return riscv_subset_supports (rps, "zcmp");
3096
0
    case INSN_CLASS_ZCMT:
3097
0
      return riscv_subset_supports (rps, "zcmt");
3098
4
    case INSN_CLASS_SMCTR_OR_SSCTR:
3099
4
      return (riscv_subset_supports (rps, "smctr")
3100
4
        || riscv_subset_supports (rps, "ssctr"));
3101
0
    case INSN_CLASS_ZILSD:
3102
0
      return riscv_subset_supports (rps, "zilsd");
3103
0
    case INSN_CLASS_ZCLSD:
3104
0
      return riscv_subset_supports (rps, "zclsd");
3105
0
    case INSN_CLASS_SMRNMI:
3106
0
      return riscv_subset_supports (rps, "smrnmi");
3107
86
    case INSN_CLASS_SVINVAL:
3108
86
      return riscv_subset_supports (rps, "svinval");
3109
137
    case INSN_CLASS_H:
3110
137
      return riscv_subset_supports (rps, "h");
3111
22
    case INSN_CLASS_XANDESBFHCVT:
3112
22
      return riscv_subset_supports (rps, "xandesbfhcvt");
3113
86
    case INSN_CLASS_XANDESVBFHCVT:
3114
86
      return riscv_subset_supports (rps, "xandesvbfhcvt");
3115
0
    case INSN_CLASS_XANDESVSINTLOAD:
3116
0
      return riscv_subset_supports (rps, "xandesvsintload");
3117
20
    case INSN_CLASS_XANDESVPACKFPH:
3118
20
      return riscv_subset_supports (rps, "xandesvpackfph");
3119
10
    case INSN_CLASS_XANDESVDOT:
3120
10
      return riscv_subset_supports (rps, "xandesvdot");
3121
10
    case INSN_CLASS_XANDESVSINTH:
3122
10
      return riscv_subset_supports (rps, "xandesvsinth");
3123
1.30k
    case INSN_CLASS_XCVALU:
3124
1.30k
      return riscv_subset_supports (rps, "xcvalu");
3125
3.41k
    case INSN_CLASS_XCVBI:
3126
3.41k
      return riscv_subset_supports (rps, "xcvbi");
3127
1.65k
    case INSN_CLASS_XCVBITMANIP:
3128
1.65k
      return riscv_subset_supports (rps, "xcvbitmanip");
3129
1.71k
    case INSN_CLASS_XCVELW:
3130
1.71k
      return riscv_subset_supports (rps, "xcvelw");
3131
4.41k
    case INSN_CLASS_XCVMAC:
3132
4.41k
      return riscv_subset_supports (rps, "xcvmac");
3133
14.4k
    case INSN_CLASS_XCVMEM:
3134
14.4k
      return riscv_subset_supports (rps, "xcvmem");
3135
2.40k
    case INSN_CLASS_XCVSIMD:
3136
2.40k
      return riscv_subset_supports (rps, "xcvsimd");
3137
445
    case INSN_CLASS_XTHEADBA:
3138
445
      return riscv_subset_supports (rps, "xtheadba");
3139
1.53k
    case INSN_CLASS_XTHEADBB:
3140
1.53k
      return riscv_subset_supports (rps, "xtheadbb");
3141
165
    case INSN_CLASS_XTHEADBS:
3142
165
      return riscv_subset_supports (rps, "xtheadbs");
3143
234
    case INSN_CLASS_XTHEADCMO:
3144
234
      return riscv_subset_supports (rps, "xtheadcmo");
3145
358
    case INSN_CLASS_XTHEADCONDMOV:
3146
358
      return riscv_subset_supports (rps, "xtheadcondmov");
3147
680
    case INSN_CLASS_XTHEADFMEMIDX:
3148
680
      return riscv_subset_supports (rps, "xtheadfmemidx");
3149
0
    case INSN_CLASS_XTHEADFMV:
3150
0
      return riscv_subset_supports (rps, "xtheadfmv");
3151
89
    case INSN_CLASS_XTHEADINT:
3152
89
      return riscv_subset_supports (rps, "xtheadint");
3153
127
    case INSN_CLASS_XTHEADMAC:
3154
127
      return riscv_subset_supports (rps, "xtheadmac");
3155
1.69k
    case INSN_CLASS_XTHEADMEMIDX:
3156
1.69k
      return riscv_subset_supports (rps, "xtheadmemidx");
3157
239
    case INSN_CLASS_XTHEADMEMPAIR:
3158
239
      return riscv_subset_supports (rps, "xtheadmempair");
3159
44
    case INSN_CLASS_XTHEADSYNC:
3160
44
      return riscv_subset_supports (rps, "xtheadsync");
3161
7.19k
    case INSN_CLASS_XTHEADVECTOR:
3162
7.19k
      return riscv_subset_supports (rps, "xtheadvector");
3163
199
    case INSN_CLASS_XTHEADVDOT:
3164
199
      return riscv_subset_supports (rps, "xtheadvdot");
3165
115
    case INSN_CLASS_XXTVARITH:
3166
115
      return riscv_subset_supports (rps, "xxtvarith");
3167
759
    case INSN_CLASS_XXTVCODER:
3168
759
      return riscv_subset_supports (rps, "xxtvcoder");
3169
647
    case INSN_CLASS_XTHEADZVAMO:
3170
647
      return riscv_subset_supports (rps, "xtheadzvamo");
3171
546
    case INSN_CLASS_XVENTANACONDOPS:
3172
546
      return riscv_subset_supports (rps, "xventanacondops");
3173
615
    case INSN_CLASS_XSFVCP:
3174
615
      return riscv_subset_supports (rps, "xsfvcp");
3175
0
    case INSN_CLASS_XSFCEASE:
3176
0
      return riscv_subset_supports (rps, "xsfcease");
3177
105
    case INSN_CLASS_XSFVQMACCQOQ:
3178
105
      return riscv_subset_supports (rps, "xsfvqmaccqoq");
3179
147
    case INSN_CLASS_XSFVQMACCDOD:
3180
147
      return riscv_subset_supports (rps, "xsfvqmaccdod");
3181
95
    case INSN_CLASS_XSFVFNRCLIPXFQF:
3182
95
      return riscv_subset_supports (rps, "xsfvfnrclipxfqf");
3183
3.08k
    case INSN_CLASS_XMIPSCBOP:
3184
3.08k
      return riscv_subset_supports (rps, "xmipscbop");
3185
126
    case INSN_CLASS_XMIPSCMOV:
3186
126
      return riscv_subset_supports (rps, "xmipscmov");
3187
41
    case INSN_CLASS_XMIPSEXECTL:
3188
41
      return riscv_subset_supports (rps, "xmipsexectl");
3189
1.26k
    case INSN_CLASS_XMIPSLSP:
3190
1.26k
      return riscv_subset_supports (rps, "xmipslsp");
3191
0
    case INSN_CLASS_XSMTVDOT:
3192
0
      return riscv_subset_supports (rps, "xsmtvdot");
3193
2.61k
    case INSN_CLASS_XSMTVDOTII:
3194
2.61k
      return riscv_subset_supports (rps, "xsmtvdotii");
3195
140
    case INSN_CLASS_XSMTVDOT_OR_XSMTVDOTII:
3196
140
      return (riscv_subset_supports (rps, "xsmtvdot")
3197
140
        || riscv_subset_supports (rps, "xsmtvdotii"));
3198
0
    default:
3199
0
      rps->error_handler
3200
0
        (_("internal: unreachable INSN_CLASS_*"));
3201
0
      return false;
3202
1.53M
    }
3203
1.53M
}
3204
3205
/* Each instuction is belonged to an instruction class INSN_CLASS_*.
3206
   Call riscv_subset_supports_ext to determine the missing extension.  */
3207
3208
const char *
3209
riscv_multi_subset_supports_ext (riscv_parse_subset_t *rps,
3210
         enum riscv_insn_class insn_class)
3211
0
{
3212
0
  switch (insn_class)
3213
0
    {
3214
0
    case INSN_CLASS_I:
3215
0
      return "i";
3216
0
    case INSN_CLASS_ZICBOM:
3217
0
      return "zicbom";
3218
0
    case INSN_CLASS_ZICBOP:
3219
0
      return "zicbop";
3220
0
    case INSN_CLASS_ZICBOZ:
3221
0
      return "zicboz";
3222
0
    case INSN_CLASS_ZICOND:
3223
0
      return "zicond";
3224
0
    case INSN_CLASS_ZICSR:
3225
0
      return "zicsr";
3226
0
    case INSN_CLASS_ZIFENCEI:
3227
0
      return "zifencei";
3228
0
    case INSN_CLASS_ZICFISS:
3229
0
      return "zicfiss";
3230
0
    case INSN_CLASS_ZICFISS_AND_ZCMOP:
3231
0
      if (!riscv_subset_supports (rps, "zicfiss"))
3232
0
  {
3233
0
    if (!riscv_subset_supports (rps, "zcmop"))
3234
0
      return _("zicfiss' and `zcmop");
3235
0
    else
3236
0
      return "zicfiss";
3237
0
  }
3238
0
      return "zcmop";
3239
0
    case INSN_CLASS_ZICFILP:
3240
0
      return "zicfilp";
3241
0
    case INSN_CLASS_ZIHINTNTL:
3242
0
      return "zihintntl";
3243
0
    case INSN_CLASS_ZIHINTNTL_AND_ZCA:
3244
0
      if (!riscv_subset_supports (rps, "zihintntl"))
3245
0
  {
3246
0
    if (!riscv_subset_supports (rps, "zca"))
3247
0
      return _("zihintntl' and `c', or `zihintntl' and `zca");
3248
0
    else
3249
0
      return "zihintntl";
3250
0
  }
3251
0
      else
3252
0
  return _("c' or `zca");
3253
0
    case INSN_CLASS_ZIHINTPAUSE:
3254
0
      return "zihintpause";
3255
0
    case INSN_CLASS_ZIMOP:
3256
0
      return "zimop";
3257
0
    case INSN_CLASS_M:
3258
0
      return "m";
3259
0
    case INSN_CLASS_ZMMUL:
3260
0
      return _ ("m' or `zmmul");
3261
0
    case INSN_CLASS_ZAAMO:
3262
0
      return "zaamo";
3263
0
    case INSN_CLASS_ZABHA:
3264
0
      return "zabha";
3265
0
    case INSN_CLASS_ZACAS:
3266
0
      return "zacas";
3267
0
    case INSN_CLASS_ZABHA_AND_ZACAS:
3268
0
      if (!riscv_subset_supports (rps, "zabha"))
3269
0
  {
3270
0
    if (!riscv_subset_supports (rps, "zacas"))
3271
0
      return _ ("zabha' and `zacas");
3272
0
    else
3273
0
      return "zabha";
3274
0
  }
3275
0
      return "zacas";
3276
0
    case INSN_CLASS_ZALASR:
3277
0
      return "zalasr";
3278
0
    case INSN_CLASS_ZALRSC:
3279
0
      return "zalrsc";
3280
0
    case INSN_CLASS_ZAWRS:
3281
0
      return "zawrs";
3282
0
    case INSN_CLASS_F:
3283
0
      return "f";
3284
0
    case INSN_CLASS_D:
3285
0
      return "d";
3286
0
    case INSN_CLASS_Q:
3287
0
      return "q";
3288
0
    case INSN_CLASS_ZCA:
3289
0
      return _("c' or `zca");
3290
0
    case INSN_CLASS_ZCF:
3291
0
      return _("f' and `c', or `zcf");
3292
0
    case INSN_CLASS_ZCD:
3293
0
      return _("d' and `c', or `zcd");
3294
0
    case INSN_CLASS_F_INX:
3295
0
      return _("f' or `zfinx");
3296
0
    case INSN_CLASS_D_INX:
3297
0
      return _("d' or `zdinx");
3298
0
    case INSN_CLASS_Q_INX:
3299
0
      return _("q' or `zqinx");
3300
0
    case INSN_CLASS_ZFH_INX:
3301
0
      return _("zfh' or `zhinx");
3302
0
    case INSN_CLASS_ZFHMIN:
3303
0
      return "zfhmin";
3304
0
    case INSN_CLASS_ZFHMIN_INX:
3305
0
      return _("zfhmin' or `zhinxmin");
3306
0
    case INSN_CLASS_ZFHMIN_AND_D_INX:
3307
0
      if (riscv_subset_supports (rps, "zfhmin"))
3308
0
  return "d";
3309
0
      else if (riscv_subset_supports (rps, "d"))
3310
0
  return "zfhmin";
3311
0
      else if (riscv_subset_supports (rps, "zhinxmin"))
3312
0
  return "zdinx";
3313
0
      else if (riscv_subset_supports (rps, "zdinx"))
3314
0
  return "zhinxmin";
3315
0
      else
3316
0
  return _("zfhmin' and `d', or `zhinxmin' and `zdinx");
3317
0
    case INSN_CLASS_ZFHMIN_AND_Q_INX:
3318
0
      if (riscv_subset_supports (rps, "zfhmin"))
3319
0
  return "q";
3320
0
      else if (riscv_subset_supports (rps, "q"))
3321
0
  return "zfhmin";
3322
0
      else if (riscv_subset_supports (rps, "zhinxmin"))
3323
0
  return "zqinx";
3324
0
      else if (riscv_subset_supports (rps, "zqinx"))
3325
0
  return "zhinxmin";
3326
0
      else
3327
0
  return _("zfhmin' and `q', or `zhinxmin' and `zqinx");
3328
0
    case INSN_CLASS_ZFBFMIN:
3329
0
      return "zfbfmin";
3330
0
    case INSN_CLASS_ZFA:
3331
0
      return "zfa";
3332
0
    case INSN_CLASS_D_AND_ZFA:
3333
0
      if (!riscv_subset_supports (rps, "d")
3334
0
    && !riscv_subset_supports (rps, "zfa"))
3335
0
  return _("d' and `zfa");
3336
0
      else if (!riscv_subset_supports (rps, "d"))
3337
0
  return "d";
3338
0
      else
3339
0
  return "zfa";
3340
0
    case INSN_CLASS_Q_AND_ZFA:
3341
0
      if (!riscv_subset_supports (rps, "q")
3342
0
    && !riscv_subset_supports (rps, "zfa"))
3343
0
  return _("q' and `zfa");
3344
0
      else if (!riscv_subset_supports (rps, "q"))
3345
0
  return "q";
3346
0
      else
3347
0
  return "zfa";
3348
0
    case INSN_CLASS_ZFH_AND_ZFA:
3349
0
      if (!riscv_subset_supports (rps, "zfh")
3350
0
    && !riscv_subset_supports (rps, "zfa"))
3351
0
  return _("zfh' and `zfa");
3352
0
      else if (!riscv_subset_supports (rps, "zfh"))
3353
0
  return "zfh";
3354
0
      else
3355
0
  return "zfa";
3356
0
    case INSN_CLASS_ZFH_OR_ZVFH_AND_ZFA:
3357
0
      if (!riscv_subset_supports (rps, "zfa"))
3358
0
  {
3359
0
    if (!riscv_subset_supports (rps, "zfh")
3360
0
        && !riscv_subset_supports (rps, "zvfh"))
3361
0
      return _("zfh' and `zfa', or `zvfh' and `zfa");
3362
0
    else
3363
0
      return "zfa";
3364
0
  }
3365
0
      else
3366
0
  return _("zfh' or `zvfh");
3367
0
    case INSN_CLASS_ZBA:
3368
0
      return "zba";
3369
0
    case INSN_CLASS_ZBB:
3370
0
      return "zbb";
3371
0
    case INSN_CLASS_ZBC:
3372
0
      return "zbc";
3373
0
    case INSN_CLASS_ZBS:
3374
0
      return "zbs";
3375
0
    case INSN_CLASS_ZBKB:
3376
0
      return "zbkb";
3377
0
    case INSN_CLASS_ZBKC:
3378
0
      return "zbkc";
3379
0
    case INSN_CLASS_ZBKX:
3380
0
      return "zbkx";
3381
0
    case INSN_CLASS_ZBB_OR_ZBKB:
3382
0
      return _("zbb' or `zbkb");
3383
0
    case INSN_CLASS_ZBC_OR_ZBKC:
3384
0
      return _("zbc' or `zbkc");
3385
0
    case INSN_CLASS_ZKND:
3386
0
      return "zknd";
3387
0
    case INSN_CLASS_ZKNE:
3388
0
      return "zkne";
3389
0
    case INSN_CLASS_ZKNH:
3390
0
      return "zknh";
3391
0
    case INSN_CLASS_ZKND_OR_ZKNE:
3392
0
      return _("zknd' or `zkne");
3393
0
    case INSN_CLASS_ZKSED:
3394
0
      return "zksed";
3395
0
    case INSN_CLASS_ZKSH:
3396
0
      return "zksh";
3397
0
    case INSN_CLASS_V:
3398
0
      return _("v' or `zve64x' or `zve32x");
3399
0
    case INSN_CLASS_ZVE64X:
3400
0
      return _("v' or `zve64x");
3401
0
    case INSN_CLASS_ZVEF:
3402
0
      return _("v' or `zve64d' or `zve64f' or `zve32f");
3403
0
    case INSN_CLASS_ZVABD:
3404
0
      return _("zvabd");
3405
0
    case INSN_CLASS_ZVBB:
3406
0
      return _("zvbb");
3407
0
    case INSN_CLASS_ZVBC:
3408
0
      return _("zvbc");
3409
0
    case INSN_CLASS_ZVFBFMIN:
3410
0
      return "zvfbfmin";
3411
0
    case INSN_CLASS_ZVFBFWMA:
3412
0
      return "zvfbfwma";
3413
0
    case INSN_CLASS_ZVFBDOTA32F:
3414
0
      return "zvfbdota32f";
3415
0
    case INSN_CLASS_ZVFQWBDOTA8F:
3416
0
      return "zvfqwbdota8f";
3417
0
    case INSN_CLASS_ZVFQWDOTA8F:
3418
0
      return "zvfqwdota8f";
3419
0
    case INSN_CLASS_ZVFWBDOTA16BF:
3420
0
      return "zvfwbdota16bf";
3421
0
    case INSN_CLASS_ZVFWDOTA16BF:
3422
0
      return "zvfwdota16bf";
3423
0
    case INSN_CLASS_ZVKB:
3424
0
      return _("zvkb");
3425
0
    case INSN_CLASS_ZVKG:
3426
0
      return _("zvkg");
3427
0
    case INSN_CLASS_ZVKNED:
3428
0
      return _("zvkned");
3429
0
    case INSN_CLASS_ZVKNHA_OR_ZVKNHB:
3430
0
      return _("zvknha' or `zvknhb");
3431
0
    case INSN_CLASS_ZVKSED:
3432
0
      return _("zvksed");
3433
0
    case INSN_CLASS_ZVKSH:
3434
0
      return _("zvksh");
3435
0
    case INSN_CLASS_ZVQWBDOTA8I:
3436
0
      return "zvqwbdota8i";
3437
0
    case INSN_CLASS_ZVQWBDOTA16I:
3438
0
      return "zvqwbdota16i";
3439
0
    case INSN_CLASS_ZVQWBDOTA8I_OR_ZVQWBDOTA16I:
3440
0
      return _("zvqwbdota8i' or `zvqwbdota16i");
3441
0
    case INSN_CLASS_ZVQWDOTA8I:
3442
0
      return "zvqwdota8i";
3443
0
    case INSN_CLASS_ZVQWDOTA16I:
3444
0
      return "zvqwdota16i";
3445
0
    case INSN_CLASS_ZVQWDOTA8I_OR_ZVQWDOTA16I:
3446
0
      return _("zvqwdota8i' or `zvqwdota16i");
3447
0
    case INSN_CLASS_ZCB:
3448
0
      return "zcb";
3449
0
    case INSN_CLASS_ZCB_AND_ZBA:
3450
0
      return _("zcb' and `zba");
3451
0
    case INSN_CLASS_ZCB_AND_ZBB:
3452
0
      return _("zcb' and `zbb");
3453
0
    case INSN_CLASS_ZCB_AND_ZMMUL:
3454
0
      return _("zcb' and `zmmul', or `zcb' and `m");
3455
0
    case INSN_CLASS_ZCMOP:
3456
0
      return "zcmop";
3457
0
    case INSN_CLASS_ZCMP:
3458
0
      return "zcmp";
3459
0
    case INSN_CLASS_ZCMT:
3460
0
      return "zcmt";
3461
0
    case INSN_CLASS_SMCTR_OR_SSCTR:
3462
0
      return _("smctr' or `ssctr");
3463
0
    case INSN_CLASS_ZILSD:
3464
0
     return "zilsd";
3465
0
    case INSN_CLASS_ZCLSD:
3466
0
      return "zclsd";
3467
0
    case INSN_CLASS_SMRNMI:
3468
0
      return "smrnmi";
3469
0
    case INSN_CLASS_SVINVAL:
3470
0
      return "svinval";
3471
0
    case INSN_CLASS_H:
3472
0
      return _("h");
3473
0
    case INSN_CLASS_XANDESBFHCVT:
3474
0
      return "xandesbfhcvt";
3475
0
    case INSN_CLASS_XANDESVBFHCVT:
3476
0
      return "xandesvbfhcvt";
3477
0
    case INSN_CLASS_XANDESVSINTLOAD:
3478
0
      return "xandesvsintload";
3479
0
    case INSN_CLASS_XANDESVPACKFPH:
3480
0
      return "xandesvpackfph";
3481
0
    case INSN_CLASS_XANDESVDOT:
3482
0
      return "xandesvdot";
3483
0
    case INSN_CLASS_XANDESVSINTH:
3484
0
      return "xandesvsinth";
3485
0
    case INSN_CLASS_XCVALU:
3486
0
      return "xcvalu";
3487
0
    case INSN_CLASS_XCVBI:
3488
0
      return "xcvbi";
3489
0
    case INSN_CLASS_XCVBITMANIP:
3490
0
      return "xcvbitmanip";
3491
0
    case INSN_CLASS_XCVELW:
3492
0
      return "xcvelw";
3493
0
    case INSN_CLASS_XCVMAC:
3494
0
      return "xcvmac";
3495
0
    case INSN_CLASS_XCVMEM:
3496
0
      return "xcvmem";
3497
0
    case INSN_CLASS_XCVSIMD:
3498
0
      return "xcvsimd";
3499
0
    case INSN_CLASS_XTHEADBA:
3500
0
      return "xtheadba";
3501
0
    case INSN_CLASS_XTHEADBB:
3502
0
      return "xtheadbb";
3503
0
    case INSN_CLASS_XTHEADBS:
3504
0
      return "xtheadbs";
3505
0
    case INSN_CLASS_XTHEADCMO:
3506
0
      return "xtheadcmo";
3507
0
    case INSN_CLASS_XTHEADCONDMOV:
3508
0
      return "xtheadcondmov";
3509
0
    case INSN_CLASS_XTHEADFMEMIDX:
3510
0
      return "xtheadfmemidx";
3511
0
    case INSN_CLASS_XTHEADFMV:
3512
0
      return "xtheadfmv";
3513
0
    case INSN_CLASS_XTHEADINT:
3514
0
      return "xtheadint";
3515
0
    case INSN_CLASS_XTHEADMAC:
3516
0
      return "xtheadmac";
3517
0
    case INSN_CLASS_XTHEADMEMIDX:
3518
0
      return "xtheadmemidx";
3519
0
    case INSN_CLASS_XTHEADMEMPAIR:
3520
0
      return "xtheadmempair";
3521
0
    case INSN_CLASS_XTHEADSYNC:
3522
0
      return "xtheadsync";
3523
0
    case INSN_CLASS_XTHEADVECTOR:
3524
0
      return "xtheadvector";
3525
0
    case INSN_CLASS_XTHEADVDOT:
3526
0
      return "xtheadvdot";
3527
0
    case INSN_CLASS_XXTVARITH:
3528
0
      return "xxtvarith";
3529
0
    case INSN_CLASS_XXTVCODER:
3530
0
      return "xxtvcoder";
3531
0
    case INSN_CLASS_XTHEADZVAMO:
3532
0
      return "xtheadzvamo";
3533
0
    case INSN_CLASS_XVENTANACONDOPS:
3534
0
      return "xventanacondops";
3535
0
    case INSN_CLASS_XSFVCP:
3536
0
      return "xsfvcp";
3537
0
    case INSN_CLASS_XSFCEASE:
3538
0
      return "xsfcease";
3539
0
    case INSN_CLASS_XSFVQMACCQOQ:
3540
0
      return "xsfvqmaccqoq";
3541
0
    case INSN_CLASS_XSFVQMACCDOD:
3542
0
      return "xsfvqmaccdod";
3543
0
    case INSN_CLASS_XSFVFNRCLIPXFQF:
3544
0
      return "xsfvfnrclipxfqf";
3545
0
    case INSN_CLASS_XSMTVDOT:
3546
0
      return "xsmtvdot";
3547
0
    case INSN_CLASS_XSMTVDOTII:
3548
0
      return "xsmtvdotii";
3549
0
    case INSN_CLASS_XSMTVDOT_OR_XSMTVDOTII:
3550
0
      return _("xsmtvdot' or `xsmtvdotii");
3551
0
    default:
3552
0
      rps->error_handler
3553
0
        (_("internal: unreachable INSN_CLASS_*"));
3554
0
      return NULL;
3555
0
    }
3556
0
}
3557
3558
/* Print supported extensions with versions if -march=help.  */
3559
3560
void
3561
riscv_print_extensions (void)
3562
0
{
3563
  /* Record the previous printed extension.
3564
     Print the current one if they are not the same.  */
3565
0
  const struct riscv_supported_ext *cur = NULL, *prev = NULL;
3566
0
  int i, j;
3567
3568
0
  printf ("All available -march extensions for RISC-V:");
3569
3570
0
  for (i = 0; riscv_all_supported_ext[i] != NULL; i++)
3571
0
    {
3572
0
      const struct riscv_supported_ext *exts = riscv_all_supported_ext[i];
3573
0
      prev = NULL;
3574
0
      for (j = 0; exts[j].name != NULL; j++)
3575
0
  {
3576
0
    cur = &exts[j];
3577
    /* Unclear version information, skip.  */
3578
0
    if (cur->isa_spec_class == ISA_SPEC_CLASS_NONE
3579
0
        || cur->major_version == RISCV_UNKNOWN_VERSION
3580
0
        || cur->minor_version == RISCV_UNKNOWN_VERSION)
3581
0
      continue;
3582
3583
    /* Same extension.  */
3584
0
    if (prev && strcmp (prev->name, cur->name) == 0)
3585
0
      {
3586
        /* Same version, skip.  */
3587
0
        if (prev->major_version == cur->major_version
3588
0
      && prev->minor_version == cur->minor_version)
3589
0
    continue;
3590
        /* Different version, print version with comma.  */
3591
0
        else
3592
0
    printf (", %d.%d", cur->major_version, cur->minor_version);
3593
0
      }
3594
    /* Different extension, print extension and version with newline.  */
3595
0
    else
3596
0
      printf ("\n\t%-40s%d.%d", cur->name, cur->major_version,
3597
0
        cur->minor_version);
3598
0
    prev = &exts[j];
3599
0
  }
3600
0
    }
3601
0
  printf ("\n");
3602
0
}
3603
3604
/* Given the ELF header flags in FLAGS, it returns a string that describes the
3605
   float ABI.  */
3606
3607
static const char *
3608
riscv_float_abi_string (flagword flags)
3609
0
{
3610
0
  switch (flags & EF_RISCV_FLOAT_ABI)
3611
0
    {
3612
0
    case EF_RISCV_FLOAT_ABI_SOFT:
3613
0
      return "soft-float";
3614
0
      break;
3615
0
    case EF_RISCV_FLOAT_ABI_SINGLE:
3616
0
      return "single-float";
3617
0
      break;
3618
0
    case EF_RISCV_FLOAT_ABI_DOUBLE:
3619
0
      return "double-float";
3620
0
      break;
3621
0
    case EF_RISCV_FLOAT_ABI_QUAD:
3622
0
      return "quad-float";
3623
0
      break;
3624
0
    default:
3625
0
      abort ();
3626
0
    }
3627
0
}
3628
3629
/* The information of architecture elf attributes.  */
3630
static riscv_subset_list_t in_subsets;
3631
static riscv_subset_list_t out_subsets;
3632
static riscv_subset_list_t merged_subsets;
3633
3634
/* Predicator for standard extension.  */
3635
3636
static bool
3637
riscv_std_ext_p (const char *name)
3638
0
{
3639
0
  return (strlen (name) == 1) && (name[0] != 'x') && (name[0] != 's');
3640
0
}
3641
3642
/* Update the output subset's version to match the input when the input
3643
   subset's version is newer.  */
3644
3645
static void
3646
riscv_update_subset_version (struct riscv_subset_t *in,
3647
           struct riscv_subset_t *out)
3648
0
{
3649
0
  if (in == NULL || out == NULL)
3650
0
    return;
3651
3652
  /* Update the output ISA versions to the newest ones, but otherwise don't
3653
     provide any errors or warnings about mis-matched ISA versions as it's
3654
     generally too tricky to check for these at link time. */
3655
0
  if ((in->major_version > out->major_version)
3656
0
      || (in->major_version == out->major_version
3657
0
    && in->minor_version > out->minor_version)
3658
0
      || (out->major_version == RISCV_UNKNOWN_VERSION))
3659
0
    {
3660
0
      out->major_version = in->major_version;
3661
0
      out->minor_version = in->minor_version;
3662
0
    }
3663
0
}
3664
3665
/* Return true if subset is 'i' or 'e'.  */
3666
3667
static bool
3668
riscv_i_or_e_p (bfd *ibfd,
3669
    const char *arch,
3670
    struct riscv_subset_t *subset)
3671
0
{
3672
0
  if ((strcasecmp (subset->name, "e") != 0)
3673
0
      && (strcasecmp (subset->name, "i") != 0))
3674
0
    {
3675
0
      _bfd_error_handler
3676
0
  (_("error: %pB: corrupted ISA string '%s'.  "
3677
0
     "First letter should be 'i' or 'e' but got '%s'"),
3678
0
     ibfd, arch, subset->name);
3679
0
      return false;
3680
0
    }
3681
0
  return true;
3682
0
}
3683
3684
/* Merge standard extensions.
3685
3686
   Return Value:
3687
     Return FALSE if failed to merge.
3688
3689
   Arguments:
3690
     `bfd`: bfd handler.
3691
     `in_arch`: Raw ISA string for input object.
3692
     `out_arch`: Raw ISA string for output object.
3693
     `pin`: Subset list for input object.
3694
     `pout`: Subset list for output object.  */
3695
3696
static bool
3697
riscv_merge_std_ext (bfd *ibfd,
3698
         const char *in_arch,
3699
         const char *out_arch,
3700
         struct riscv_subset_t **pin,
3701
         struct riscv_subset_t **pout)
3702
0
{
3703
0
  const char *standard_exts = "mafdqlcbjtpvnh";
3704
0
  const char *p;
3705
0
  struct riscv_subset_t *in = *pin;
3706
0
  struct riscv_subset_t *out = *pout;
3707
3708
  /* First letter should be 'i' or 'e'.  */
3709
0
  if (!riscv_i_or_e_p (ibfd, in_arch, in))
3710
0
    return false;
3711
3712
0
  if (!riscv_i_or_e_p (ibfd, out_arch, out))
3713
0
    return false;
3714
3715
0
  if (strcasecmp (in->name, out->name) != 0)
3716
0
    {
3717
      /* TODO: We might allow merge 'i' with 'e'.  */
3718
0
      _bfd_error_handler
3719
0
  (_("error: %pB: mis-matched ISA string to merge '%s' and '%s'"),
3720
0
   ibfd, in->name, out->name);
3721
0
      return false;
3722
0
    }
3723
3724
0
  riscv_update_subset_version(in, out);
3725
0
  riscv_add_subset (&merged_subsets,
3726
0
        out->name, out->major_version, out->minor_version);
3727
3728
0
  in = in->next;
3729
0
  out = out->next;
3730
3731
  /* Handle standard extension first.  */
3732
0
  for (p = standard_exts; *p; ++p)
3733
0
    {
3734
0
      struct riscv_subset_t *ext_in, *ext_out, *ext_merged;
3735
0
      char find_ext[2] = {*p, '\0'};
3736
0
      bool find_in, find_out;
3737
3738
0
      find_in = riscv_lookup_subset (&in_subsets, find_ext, &ext_in);
3739
0
      find_out = riscv_lookup_subset (&out_subsets, find_ext, &ext_out);
3740
3741
0
      if (!find_in && !find_out)
3742
0
  continue;
3743
3744
0
      if (find_in && find_out)
3745
0
  riscv_update_subset_version(ext_in, ext_out);
3746
3747
0
      ext_merged = find_out ? ext_out : ext_in;
3748
0
      riscv_add_subset (&merged_subsets, ext_merged->name,
3749
0
      ext_merged->major_version, ext_merged->minor_version);
3750
0
    }
3751
3752
  /* Skip all standard extensions.  */
3753
0
  while ((in != NULL) && riscv_std_ext_p (in->name)) in = in->next;
3754
0
  while ((out != NULL) && riscv_std_ext_p (out->name)) out = out->next;
3755
3756
0
  *pin = in;
3757
0
  *pout = out;
3758
3759
0
  return true;
3760
0
}
3761
3762
/* Merge multi letter extensions.  PIN is a pointer to the head of the input
3763
   object subset list.  Likewise for POUT and the output object.  Return TRUE
3764
   on success and FALSE when a conflict is found.  */
3765
3766
static bool
3767
riscv_merge_multi_letter_ext (riscv_subset_t **pin,
3768
            riscv_subset_t **pout)
3769
0
{
3770
0
  riscv_subset_t *in = *pin;
3771
0
  riscv_subset_t *out = *pout;
3772
0
  riscv_subset_t *tail;
3773
3774
0
  int cmp;
3775
3776
0
  while (in && out)
3777
0
    {
3778
0
      cmp = riscv_compare_subsets (in->name, out->name);
3779
3780
0
      if (cmp < 0)
3781
0
  {
3782
    /* `in' comes before `out', append `in' and increment.  */
3783
0
    riscv_add_subset (&merged_subsets, in->name, in->major_version,
3784
0
          in->minor_version);
3785
0
    in = in->next;
3786
0
  }
3787
0
      else if (cmp > 0)
3788
0
  {
3789
    /* `out' comes before `in', append `out' and increment.  */
3790
0
    riscv_add_subset (&merged_subsets, out->name, out->major_version,
3791
0
          out->minor_version);
3792
0
    out = out->next;
3793
0
  }
3794
0
      else
3795
0
  {
3796
    /* Both present, check version and increment both.  */
3797
0
    riscv_update_subset_version (in, out);
3798
3799
0
    riscv_add_subset (&merged_subsets, out->name, out->major_version,
3800
0
          out->minor_version);
3801
0
    out = out->next;
3802
0
    in = in->next;
3803
0
  }
3804
0
    }
3805
3806
0
  if (in || out)
3807
0
    {
3808
      /* If we're here, either `in' or `out' is running longer than
3809
   the other. So, we need to append the corresponding tail.  */
3810
0
      tail = in ? in : out;
3811
0
      while (tail)
3812
0
  {
3813
0
    riscv_add_subset (&merged_subsets, tail->name, tail->major_version,
3814
0
          tail->minor_version);
3815
0
    tail = tail->next;
3816
0
  }
3817
0
    }
3818
3819
0
  return true;
3820
0
}
3821
3822
/* Merge Tag_RISCV_arch attribute.  */
3823
3824
static char *
3825
riscv_merge_arch_attr_info (bfd *ibfd, char *in_arch, char *out_arch,
3826
          unsigned int arch_size)
3827
0
{
3828
0
  riscv_subset_t *in, *out;
3829
0
  static char *merged_arch_str = NULL;
3830
0
  char *result = NULL;
3831
3832
0
  unsigned xlen_in, xlen_out;
3833
3834
0
  riscv_parse_subset_t riscv_rps_ld_in =
3835
0
    {&in_subsets, _bfd_error_handler, &xlen_in, NULL, false};
3836
0
  riscv_parse_subset_t riscv_rps_ld_out =
3837
0
    {&out_subsets, _bfd_error_handler, &xlen_out, NULL, false};
3838
3839
0
  if (in_arch == NULL && out_arch == NULL)
3840
0
    return NULL;
3841
0
  if (in_arch == NULL && out_arch != NULL)
3842
0
    return out_arch;
3843
0
  if (in_arch != NULL && out_arch == NULL)
3844
0
    return in_arch;
3845
3846
  /* Parse subset from ISA string.  */
3847
0
  if (!riscv_parse_subset (&riscv_rps_ld_in, in_arch))
3848
0
    goto cleanup;
3849
0
  if (!riscv_parse_subset (&riscv_rps_ld_out, out_arch))
3850
0
    goto cleanup;
3851
3852
  /* Checking XLEN.  */
3853
0
  if (xlen_out != xlen_in)
3854
0
    {
3855
0
      _bfd_error_handler
3856
0
  (_("error: %pB: ISA string of input (%s) doesn't match "
3857
0
     "output (%s)"), ibfd, in_arch, out_arch);
3858
0
      goto cleanup;
3859
0
    }
3860
3861
  /* Merge subset list.  */
3862
0
  in = in_subsets.head;
3863
0
  out = out_subsets.head;
3864
3865
  /* Merge standard extension.  */
3866
0
  if (!riscv_merge_std_ext (ibfd, in_arch, out_arch, &in, &out))
3867
0
    goto cleanup;
3868
3869
  /* Merge all non-single letter extensions with single call.  */
3870
0
  if (!riscv_merge_multi_letter_ext (&in, &out))
3871
0
    goto cleanup;
3872
3873
0
  if (xlen_in != xlen_out)
3874
0
    {
3875
0
      _bfd_error_handler
3876
0
  (_("error: %pB: XLEN of input (%u) doesn't match "
3877
0
     "output (%u)"), ibfd, xlen_in, xlen_out);
3878
0
      goto cleanup;
3879
0
    }
3880
3881
0
  if (xlen_in != arch_size)
3882
0
    {
3883
0
      _bfd_error_handler
3884
0
  (_("error: %pB: unsupported XLEN (%u), you might be "
3885
0
     "using wrong emulation"), ibfd, xlen_in);
3886
0
      goto cleanup;
3887
0
    }
3888
3889
  /* Add the implicit subsets implied by the merged subset list, then
3890
     check if the result is conflicting.  */
3891
0
  riscv_parse_subset_t riscv_rps_ld_merged =
3892
0
    {&merged_subsets, _bfd_error_handler, &xlen_in, NULL, false};
3893
0
  riscv_parse_add_implicit_subsets (&riscv_rps_ld_merged);
3894
0
  if (!riscv_parse_check_conflicts (&riscv_rps_ld_merged))
3895
0
    goto cleanup;
3896
3897
  /* Free the previous merged_arch_str which called xmalloc.  */
3898
0
  free (merged_arch_str);
3899
3900
0
  merged_arch_str = riscv_arch_str (arch_size, &merged_subsets,
3901
0
            false/* update */);
3902
0
  result = merged_arch_str;
3903
3904
0
 cleanup:
3905
  /* Release the subset lists.  */
3906
0
  riscv_release_subset_list (&in_subsets);
3907
0
  riscv_release_subset_list (&out_subsets);
3908
0
  riscv_release_subset_list (&merged_subsets);
3909
3910
0
  return result;
3911
0
}
3912
3913
/* Merge object attributes from IBFD into output_bfd of INFO.
3914
   Raise an error if there are conflicting attributes.  */
3915
3916
static bool
3917
riscv_merge_attributes (bfd *ibfd, struct bfd_link_info *info,
3918
      unsigned int arch_size)
3919
0
{
3920
0
  bfd *obfd = info->output_bfd;
3921
0
  obj_attribute *in_attr;
3922
0
  obj_attribute *out_attr;
3923
0
  bool result = true;
3924
0
  bool priv_attrs_merged = false;
3925
0
  const char *sec_name = get_elf_backend_data (ibfd)->obj_attrs_section;
3926
0
  unsigned int i;
3927
3928
  /* Skip linker created files.  */
3929
0
  if (ibfd->flags & BFD_LINKER_CREATED)
3930
0
    return true;
3931
3932
  /* Skip any input that doesn't have an attribute section.
3933
     This enables to link object files without attribute section with
3934
     any others.  */
3935
0
  if (bfd_get_section_by_name (ibfd, sec_name) == NULL)
3936
0
    return true;
3937
3938
0
  if (!elf_known_obj_attributes_proc (obfd)[0].i)
3939
0
    {
3940
      /* This is the first object.  Copy the attributes.  */
3941
0
      _bfd_elf_copy_obj_attributes (ibfd, obfd);
3942
3943
0
      out_attr = elf_known_obj_attributes_proc (obfd);
3944
3945
      /* Use the Tag_null value to indicate the attributes have been
3946
   initialized.  */
3947
0
      out_attr[0].i = 1;
3948
3949
0
      for (i = LEAST_KNOWN_OBJ_ATTRIBUTE; i < NUM_KNOWN_OBJ_ATTRIBUTES; i++)
3950
0
  {
3951
0
    switch (i)
3952
0
      {
3953
0
      case Tag_RISCV_unaligned_access:
3954
0
        if (out_attr[i].i <= 1)
3955
0
    break;
3956
3957
0
        _bfd_error_handler
3958
0
    (_("warning: %pB uses non-boolean `unaligned_access' attribute; "
3959
0
       "converting to boolean"),
3960
0
     ibfd);
3961
0
        out_attr[i].i = 1;
3962
0
        break;
3963
3964
0
      case Tag_RISCV_stack_align:
3965
0
        if (!(out_attr[i].i & (out_attr[i].i - 1)))
3966
0
    break;
3967
3968
0
        _bfd_error_handler
3969
0
    (_("warning: %pB uses non-power-of-2 `stack_align' attribute; "
3970
0
       "ignoring"),
3971
0
     ibfd);
3972
0
        out_attr[i].i = 0;
3973
0
        break;
3974
0
      }
3975
0
  }
3976
3977
0
      return true;
3978
0
    }
3979
3980
0
  in_attr = elf_known_obj_attributes_proc (ibfd);
3981
0
  out_attr = elf_known_obj_attributes_proc (obfd);
3982
3983
0
  for (i = LEAST_KNOWN_OBJ_ATTRIBUTE; i < NUM_KNOWN_OBJ_ATTRIBUTES; i++)
3984
0
    {
3985
0
    switch (i)
3986
0
      {
3987
0
      case Tag_RISCV_arch:
3988
0
  if (!out_attr[Tag_RISCV_arch].s)
3989
0
    out_attr[Tag_RISCV_arch].s = in_attr[Tag_RISCV_arch].s;
3990
0
  else if (in_attr[Tag_RISCV_arch].s
3991
0
     && out_attr[Tag_RISCV_arch].s)
3992
0
    {
3993
      /* Check compatible.  */
3994
0
      char *merged_arch =
3995
0
    riscv_merge_arch_attr_info (ibfd,
3996
0
              in_attr[Tag_RISCV_arch].s,
3997
0
              out_attr[Tag_RISCV_arch].s,
3998
0
              arch_size);
3999
0
      if (merged_arch == NULL)
4000
0
        {
4001
0
    result = false;
4002
0
    out_attr[Tag_RISCV_arch].s = "";
4003
0
        }
4004
0
      else
4005
0
        out_attr[Tag_RISCV_arch].s = merged_arch;
4006
0
    }
4007
0
  break;
4008
4009
0
      case Tag_RISCV_priv_spec:
4010
0
      case Tag_RISCV_priv_spec_minor:
4011
0
      case Tag_RISCV_priv_spec_revision:
4012
  /* If we have handled the privileged elf attributes, then skip it.  */
4013
0
  if (!priv_attrs_merged)
4014
0
    {
4015
0
      unsigned int Tag_a = Tag_RISCV_priv_spec;
4016
0
      unsigned int Tag_b = Tag_RISCV_priv_spec_minor;
4017
0
      unsigned int Tag_c = Tag_RISCV_priv_spec_revision;
4018
0
      enum riscv_spec_class in_priv_spec = PRIV_SPEC_CLASS_NONE;
4019
0
      enum riscv_spec_class out_priv_spec = PRIV_SPEC_CLASS_NONE;
4020
4021
      /* Get the privileged spec class from elf attributes.  */
4022
0
      riscv_get_priv_spec_class_from_numbers (in_attr[Tag_a].i,
4023
0
                in_attr[Tag_b].i,
4024
0
                in_attr[Tag_c].i,
4025
0
                &in_priv_spec);
4026
0
      riscv_get_priv_spec_class_from_numbers (out_attr[Tag_a].i,
4027
0
                out_attr[Tag_b].i,
4028
0
                out_attr[Tag_c].i,
4029
0
                &out_priv_spec);
4030
4031
      /* Allow to link the object without the privileged specs.  */
4032
0
      if (out_priv_spec == PRIV_SPEC_CLASS_NONE)
4033
0
        {
4034
0
    out_attr[Tag_a].i = in_attr[Tag_a].i;
4035
0
    out_attr[Tag_b].i = in_attr[Tag_b].i;
4036
0
    out_attr[Tag_c].i = in_attr[Tag_c].i;
4037
0
        }
4038
0
      else if (in_priv_spec != PRIV_SPEC_CLASS_NONE
4039
0
         && in_priv_spec != out_priv_spec)
4040
0
        {
4041
    /* The abandoned privileged spec v1.9.1 can not be linked with
4042
       others since the conflicts.  Keep the check since compatible
4043
       issue.  */
4044
0
    if (in_priv_spec == PRIV_SPEC_CLASS_1P9P1
4045
0
        || out_priv_spec == PRIV_SPEC_CLASS_1P9P1)
4046
0
      {
4047
0
        _bfd_error_handler
4048
0
          (_("warning: privileged spec version 1.9.1 can not be "
4049
0
       "linked with other spec versions"));
4050
0
      }
4051
4052
    /* Update the output privileged spec to the newest one.  */
4053
0
    if (in_priv_spec > out_priv_spec)
4054
0
      {
4055
0
        out_attr[Tag_a].i = in_attr[Tag_a].i;
4056
0
        out_attr[Tag_b].i = in_attr[Tag_b].i;
4057
0
        out_attr[Tag_c].i = in_attr[Tag_c].i;
4058
0
      }
4059
0
        }
4060
0
      priv_attrs_merged = true;
4061
0
    }
4062
0
  break;
4063
4064
0
      case Tag_RISCV_unaligned_access:
4065
0
  if (in_attr[i].i > 1)
4066
0
    _bfd_error_handler
4067
0
      (_("warning: %pB uses non-boolean `unaligned_access' attribute; "
4068
0
         "converting to boolean"),
4069
0
       ibfd);
4070
0
  out_attr[i].i |= !!in_attr[i].i;
4071
0
  break;
4072
4073
0
      case Tag_RISCV_stack_align:
4074
0
  if ((in_attr[i].i & (in_attr[i].i - 1)) != 0)
4075
0
    _bfd_error_handler
4076
0
      (_("warning: %pB uses non-power-of-2 `stack_align' attribute; "
4077
0
         "ignoring"),
4078
0
       ibfd);
4079
0
  else if (out_attr[i].i == 0)
4080
0
    out_attr[i].i = in_attr[i].i;
4081
0
  else if (in_attr[i].i != 0
4082
0
     && out_attr[i].i != in_attr[i].i)
4083
0
    {
4084
0
      _bfd_error_handler
4085
0
        (_("error: %pB use %u-byte stack aligned but the output "
4086
0
     "use %u-byte stack aligned"),
4087
0
         ibfd, in_attr[i].i, out_attr[i].i);
4088
0
      result = false;
4089
0
    }
4090
0
  break;
4091
4092
0
      default:
4093
0
  result &= _bfd_elf_merge_unknown_attribute_low (ibfd, obfd, i);
4094
0
      }
4095
4096
      /* If out_attr was copied from in_attr then it won't have a type yet.  */
4097
0
      if (in_attr[i].type && !out_attr[i].type)
4098
0
  out_attr[i].type = in_attr[i].type;
4099
0
    }
4100
4101
  /* Merge Tag_compatibility attributes and any common GNU ones.  */
4102
0
  if (!_bfd_elf_merge_object_attributes (ibfd, info))
4103
0
    return false;
4104
4105
  /* Check for any attributes not known on RISC-V.  */
4106
0
  result &= _bfd_elf_merge_unknown_attribute_list (ibfd, obfd);
4107
4108
0
  return result;
4109
0
}
4110
4111
/* Merge backend specific data from an object file to the output
4112
   object file when linking.  */
4113
4114
bool
4115
_bfd_riscv_elf_merge_private_bfd_data (bfd *ibfd, struct bfd_link_info *info,
4116
               unsigned int arch_size)
4117
0
{
4118
0
  bfd *obfd = info->output_bfd;
4119
0
  flagword new_flags, old_flags;
4120
4121
0
  if (!is_riscv_elf (ibfd))
4122
0
    return true;
4123
4124
0
  if (strcmp (bfd_get_target (ibfd), bfd_get_target (obfd)) != 0)
4125
0
    {
4126
0
      (*_bfd_error_handler)
4127
0
  (_("%pB: ABI is incompatible with that of the selected emulation:\n"
4128
0
     "  target emulation `%s' does not match `%s'"),
4129
0
   ibfd, bfd_get_target (ibfd), bfd_get_target (obfd));
4130
0
      return false;
4131
0
    }
4132
4133
0
  if (!_bfd_elf_merge_object_attributes (ibfd, info))
4134
0
    return false;
4135
4136
0
  if (!riscv_merge_attributes (ibfd, info, arch_size))
4137
0
    return false;
4138
4139
  /* Check to see if the input BFD actually contains any sections.  If not,
4140
     its flags may not have been initialized either, but it cannot actually
4141
     cause any incompatibility.  Do not short-circuit dynamic objects; their
4142
     section list may be emptied by elf_link_add_object_symbols.
4143
4144
     Also check to see if there are no code sections in the input.  In this
4145
     case, there is no need to check for code specific flags.  */
4146
0
  if (!(ibfd->flags & DYNAMIC))
4147
0
    {
4148
0
      bool null_input_bfd = true;
4149
0
      bool only_data_sections = true;
4150
0
      asection *sec;
4151
4152
0
      for (sec = ibfd->sections; sec != NULL; sec = sec->next)
4153
0
  {
4154
0
    null_input_bfd = false;
4155
4156
0
    if ((bfd_section_flags (sec)
4157
0
         & (SEC_LOAD | SEC_CODE | SEC_HAS_CONTENTS))
4158
0
        == (SEC_LOAD | SEC_CODE | SEC_HAS_CONTENTS))
4159
0
      {
4160
0
        only_data_sections = false;
4161
0
        break;
4162
0
      }
4163
0
  }
4164
4165
0
      if (null_input_bfd || only_data_sections)
4166
0
  return true;
4167
0
    }
4168
4169
0
  new_flags = elf_elfheader (ibfd)->e_flags;
4170
0
  old_flags = elf_elfheader (obfd)->e_flags;
4171
4172
0
  if (!elf_flags_init (obfd))
4173
0
    {
4174
0
      elf_flags_init (obfd) = true;
4175
0
      elf_elfheader (obfd)->e_flags = new_flags;
4176
0
      return true;
4177
0
    }
4178
4179
  /* Disallow linking different float ABIs.  */
4180
0
  if ((old_flags ^ new_flags) & EF_RISCV_FLOAT_ABI)
4181
0
    {
4182
0
      (*_bfd_error_handler)
4183
0
  (_("%pB: can't link %s modules with %s modules"), ibfd,
4184
0
   riscv_float_abi_string (new_flags),
4185
0
   riscv_float_abi_string (old_flags));
4186
0
      goto fail;
4187
0
    }
4188
4189
  /* Disallow linking RVE and non-RVE.  */
4190
0
  if ((old_flags ^ new_flags) & EF_RISCV_RVE)
4191
0
    {
4192
0
      (*_bfd_error_handler)
4193
0
       (_("%pB: can't link RVE with other target"), ibfd);
4194
0
      goto fail;
4195
0
    }
4196
4197
  /* Allow linking RVC and non-RVC, and keep the RVC flag.  */
4198
0
  elf_elfheader (obfd)->e_flags |= new_flags & EF_RISCV_RVC;
4199
4200
  /* Allow linking TSO and non-TSO, and keep the TSO flag.  */
4201
0
  elf_elfheader (obfd)->e_flags |= new_flags & EF_RISCV_TSO;
4202
4203
0
  return true;
4204
4205
0
 fail:
4206
0
  bfd_set_error (bfd_error_bad_value);
4207
0
  return false;
4208
0
}
4209
4210
/* Find the first input bfd with GNU property and merge it with GPROP.  If no
4211
   such input is found, add it to a new section at the last input.  Update
4212
   GPROP accordingly.  */
4213
4214
bfd *
4215
_bfd_riscv_elf_link_setup_gnu_properties (struct bfd_link_info *info,
4216
            uint32_t *and_prop_p)
4217
0
{
4218
0
  asection *sec;
4219
0
  bfd *pbfd;
4220
0
  bfd *ebfd = NULL;
4221
0
  elf_property *prop;
4222
4223
0
  uint32_t and_prop = *and_prop_p;
4224
4225
  /* Find a normal input file with GNU property note.  */
4226
0
  for (pbfd = info->input_bfds; pbfd != NULL; pbfd = pbfd->link.next)
4227
0
    if (bfd_get_flavour (pbfd) == bfd_target_elf_flavour
4228
0
  && bfd_count_sections (pbfd) != 0)
4229
0
      {
4230
0
  ebfd = pbfd;
4231
4232
0
  if (elf_properties (pbfd) != NULL)
4233
0
    break;
4234
0
      }
4235
4236
  /* If ebfd != NULL it is either an input with property note or the last
4237
     input.  Either way if we have and_prop, we should add it (by
4238
     creating a section if needed).  */
4239
0
  if (ebfd != NULL && (and_prop))
4240
0
    {
4241
0
      prop = _bfd_elf_get_property (ebfd, GNU_PROPERTY_RISCV_FEATURE_1_AND, 4);
4242
4243
0
      prop->u.number |= and_prop;
4244
0
      prop->pr_kind = property_number;
4245
4246
      /* pbfd being NULL implies ebfd is the last input.  Create the GNU
4247
   property note section.  */
4248
0
      if (pbfd == NULL)
4249
0
  {
4250
0
    sec
4251
0
      = bfd_make_section_with_flags (ebfd, NOTE_GNU_PROPERTY_SECTION_NAME,
4252
0
             (SEC_ALLOC | SEC_LOAD | SEC_IN_MEMORY
4253
0
              | SEC_READONLY | SEC_HAS_CONTENTS
4254
0
              | SEC_DATA));
4255
0
    if (sec == NULL)
4256
0
      info->callbacks->fatal (
4257
0
        _("%P: failed to create GNU property section\n"));
4258
4259
0
    elf_section_type (sec) = SHT_NOTE;
4260
0
  }
4261
0
    }
4262
4263
0
  pbfd = _bfd_elf_link_setup_gnu_properties (info);
4264
4265
0
  if (bfd_link_relocatable (info))
4266
0
    return pbfd;
4267
4268
  /* If pbfd has any GNU_PROPERTY_RISCV_FEATURE_1_AND properties, update
4269
  and_prop accordingly.  */
4270
0
  if (pbfd != NULL)
4271
0
    {
4272
0
      elf_property_list *p;
4273
0
      elf_property_list *plist = elf_properties (pbfd);
4274
4275
0
      if ((p = _bfd_elf_find_property (plist, GNU_PROPERTY_RISCV_FEATURE_1_AND,
4276
0
               NULL))
4277
0
    != NULL)
4278
0
  and_prop = p->property.u.number
4279
0
       & (GNU_PROPERTY_RISCV_FEATURE_1_CFI_LP_UNLABELED
4280
0
          | GNU_PROPERTY_RISCV_FEATURE_1_CFI_SS);
4281
0
    }
4282
4283
0
  *and_prop_p = and_prop;
4284
0
  return pbfd;
4285
0
}
4286
4287
/* Define elf_backend_parse_gnu_properties for RISC-V.  */
4288
4289
enum elf_property_kind
4290
_bfd_riscv_elf_parse_gnu_properties (bfd *abfd, unsigned int type,
4291
             bfd_byte *ptr, unsigned int datasz)
4292
7
{
4293
7
  elf_property *prop;
4294
4295
7
  switch (type)
4296
7
    {
4297
0
    case GNU_PROPERTY_RISCV_FEATURE_1_AND:
4298
0
      if (datasz != 4)
4299
0
  {
4300
0
    _bfd_error_handler (_ (
4301
0
        "error: %pB: <corrupt RISC-V used size: 0x%x>"),
4302
0
            abfd, datasz);
4303
0
    return property_corrupt;
4304
0
  }
4305
0
      prop = _bfd_elf_get_property (abfd, type, datasz);
4306
      /* Combine properties of the same type.  */
4307
0
      prop->u.number |= bfd_h_get_32 (abfd, ptr);
4308
0
      prop->pr_kind = property_number;
4309
0
      break;
4310
4311
7
    default:
4312
7
      return property_ignored;
4313
7
    }
4314
4315
0
  return property_number;
4316
7
}
4317
4318
/* Merge RISC-V GNU property BPROP with APROP also accounting for PROP.
4319
   If APROP isn't NULL, merge it with BPROP and/or PROP.  Vice-versa if BROP
4320
   isn't NULL.  Return TRUE if there is any update to APROP or if BPROP should
4321
   be merge with ABFD.  */
4322
4323
bool
4324
_bfd_riscv_elf_merge_gnu_properties
4325
  (struct bfd_link_info *info ATTRIBUTE_UNUSED, bfd *abfd ATTRIBUTE_UNUSED,
4326
   elf_property *aprop, elf_property *bprop, uint32_t and_prop)
4327
0
{
4328
0
  unsigned int orig_number;
4329
0
  bool updated = false;
4330
0
  unsigned int pr_type = aprop != NULL ? aprop->pr_type : bprop->pr_type;
4331
4332
0
  switch (pr_type)
4333
0
    {
4334
0
      case GNU_PROPERTY_RISCV_FEATURE_1_AND: {
4335
0
  if (aprop != NULL && bprop != NULL)
4336
0
    {
4337
0
      orig_number = aprop->u.number;
4338
0
      aprop->u.number = (orig_number & bprop->u.number) | and_prop;
4339
0
      updated = orig_number != aprop->u.number;
4340
      /* Remove the property if all feature bits are cleared.  */
4341
0
      if (aprop->u.number == 0)
4342
0
        aprop->pr_kind = property_remove;
4343
0
      break;
4344
0
    }
4345
  /* If either is NULL, the AND would be 0 so, if there is
4346
     any PROP, asign it to the input that is not NULL.  */
4347
0
  if (and_prop)
4348
0
    {
4349
0
      if (aprop != NULL)
4350
0
        {
4351
0
    orig_number = aprop->u.number;
4352
0
    aprop->u.number = and_prop;
4353
0
    updated = orig_number != aprop->u.number;
4354
0
        }
4355
0
      else if (bprop != NULL)
4356
0
        {
4357
0
    bprop->u.number = and_prop;
4358
0
    updated = true;
4359
0
        }
4360
      /* Shouldn't happen because we checked one of APROP or BPROP !=
4361
       * NULL. */
4362
0
      else
4363
0
        abort ();
4364
0
    }
4365
  /* No PROP and BPROP is NULL, so remove APROP.  */
4366
0
  else if (!and_prop && bprop == NULL && aprop != NULL)
4367
0
    {
4368
0
      aprop->pr_kind = property_remove;
4369
0
      updated = true;
4370
0
    }
4371
0
      }
4372
0
      break;
4373
4374
0
    default:
4375
0
      abort ();
4376
0
    }
4377
4378
0
  return updated;
4379
0
}