Coverage Report

Created: 2026-07-25 10:20

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