Coverage Report

Created: 2026-09-14 08:07

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