Coverage Report

Created: 2026-03-10 08:46

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_RISCV_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.60k
{
1065
3.60k
  if (r_type < ARRAY_SIZE (howto_table))
1066
3.43k
    return &howto_table[r_type];
1067
173
  else if (r_type < R_RISCV_max + ARRAY_SIZE (howto_table_internal))
1068
0
    return &howto_table_internal[r_type - R_RISCV_max];
1069
173
  else
1070
173
    {
1071
173
      (*_bfd_error_handler) (_("%pB: unsupported relocation type %#x"),
1072
173
           abfd, r_type);
1073
173
      bfd_set_error (bfd_error_bad_value);
1074
173
      return NULL;
1075
173
    }
1076
3.60k
}
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
10
{
1089
10
  reloc_howto_type *howto = reloc_entry->howto;
1090
10
  bfd_vma relocation;
1091
1092
10
  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
10
  if (output_bfd != NULL)
1101
0
    return bfd_reloc_continue;
1102
1103
10
  relocation = symbol->value + symbol->section->output_section->vma
1104
10
    + symbol->section->output_offset + reloc_entry->addend;
1105
1106
10
  bfd_size_type octets = reloc_entry->address
1107
10
    * bfd_octets_per_byte (abfd, input_section);
1108
10
  if (!bfd_reloc_offset_in_range (reloc_entry->howto, abfd,
1109
10
          input_section, octets))
1110
1
    return bfd_reloc_outofrange;
1111
1112
9
  bfd_vma old_value = bfd_get (howto->bitsize, abfd,
1113
9
             data + reloc_entry->address);
1114
1115
9
  switch (howto->type)
1116
9
    {
1117
2
    case R_RISCV_ADD8:
1118
2
    case R_RISCV_ADD16:
1119
2
    case R_RISCV_ADD32:
1120
6
    case R_RISCV_ADD64:
1121
6
      relocation = old_value + relocation;
1122
6
      break;
1123
0
    case R_RISCV_SUB6:
1124
0
      relocation = (old_value & ~howto->dst_mask)
1125
0
       | (((old_value & howto->dst_mask) - relocation)
1126
0
          & howto->dst_mask);
1127
0
      break;
1128
0
    case R_RISCV_SUB8:
1129
3
    case R_RISCV_SUB16:
1130
3
    case R_RISCV_SUB32:
1131
3
    case R_RISCV_SUB64:
1132
3
      relocation = old_value - relocation;
1133
3
      break;
1134
9
    }
1135
9
  bfd_put (howto->bitsize, abfd, relocation, data + reloc_entry->address);
1136
1137
9
  return bfd_reloc_ok;
1138
9
}
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
4.96k
{
1163
4.96k
  return true;
1164
4.96k
}
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
828
{
1172
828
  return (subset->major_version < 2
1173
828
    || (subset->major_version == 2
1174
828
        && subset->minor_version < 1));
1175
828
}
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
828
{
1184
828
  return (rps != NULL
1185
828
    && rps->xlen != NULL
1186
828
    && *rps->xlen == 32
1187
0
    && riscv_subset_supports (rps, "f"));
1188
828
}
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
828
{
1196
828
  return (rps != NULL
1197
828
    && riscv_subset_supports (rps, "d"));
1198
828
}
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
1224
  {"xsfvcp", "+zve32x", check_implicit_always},
1225
  {"xsfvqmaccqoq", "+zve32x,+zvl256b", check_implicit_always},
1226
  {"xsfvqmaccdod", "+zve32x,+zvl128b", check_implicit_always},
1227
  {"xsfvfnrclipxfqf", "+zve32f", check_implicit_always},
1228
1229
  {"xtheadvector", "+zicsr", check_implicit_always},
1230
  {"xtheadzvamo", "+zaamo", check_implicit_always},
1231
1232
  {"v", "+zve64d,+zvl128b", check_implicit_always},
1233
  {"zvfh", "+zvfhmin,+zfhmin", check_implicit_always},
1234
  {"zvfhmin", "+zve32f", check_implicit_always},
1235
  {"zvfbfwma", "+zve32f,+zfbfmin", check_implicit_always},
1236
  {"zvfbfmin", "+zve32f", check_implicit_always},
1237
  {"zve64d", "+d,+zve64f", check_implicit_always},
1238
  {"zve64f", "+zve32f,+zve64x,+zvl64b", check_implicit_always},
1239
  {"zve32f", "+f,+zve32x,+zvl32b", check_implicit_always},
1240
  {"zve64x", "+zve32x,+zvl64b", check_implicit_always},
1241
  {"zve32x", "+zvl32b,+zicsr", check_implicit_always},
1242
  {"zvl65536b", "+zvl32768b", check_implicit_always},
1243
  {"zvl32768b", "+zvl16384b", check_implicit_always},
1244
  {"zvl16384b", "+zvl8192b", check_implicit_always},
1245
  {"zvl8192b", "+zvl4096b", check_implicit_always},
1246
  {"zvl4096b", "+zvl2048b", check_implicit_always},
1247
  {"zvl2048b", "+zvl1024b", check_implicit_always},
1248
  {"zvl1024b", "+zvl512b", check_implicit_always},
1249
  {"zvl512b", "+zvl256b", check_implicit_always},
1250
  {"zvl256b", "+zvl128b", check_implicit_always},
1251
  {"zvl128b", "+zvl64b", check_implicit_always},
1252
  {"zvl64b", "+zvl32b", check_implicit_always},
1253
1254
  {"zicfilp", "+zicsr", check_implicit_always},
1255
  {"zicfiss", "+zimop,+zicsr", check_implicit_always},
1256
  {"zclsd", "+zca,+zilsd", check_implicit_always},
1257
1258
  {"sha", "+h,+ssstateen,+shcounterenw,+shvstvala,+shtvala,+shvstvecd,+shvsatpa,+shgatpa", check_implicit_always},
1259
1260
  {"shcounterenw", "+h", check_implicit_always},
1261
  {"shgatpa", "+h", check_implicit_always},
1262
  {"shtvala", "+h", check_implicit_always},
1263
  {"shvsatpa", "+h", check_implicit_always},
1264
  {"shvstvala", "+h", check_implicit_always},
1265
  {"shvstvecd", "+h", check_implicit_always},
1266
  {"h", "+zicsr", check_implicit_always},
1267
  {"zhinx", "+zhinxmin", check_implicit_always},
1268
  {"zhinxmin", "+zfinx", check_implicit_always},
1269
1270
  {"zcd", "+d,+zca", check_implicit_always},
1271
  {"zcf", "+f,+zca", check_implicit_always},
1272
1273
  {"q", "+d", check_implicit_always},
1274
  {"zqinx", "+zdinx", check_implicit_always},
1275
1276
  {"d", "+f", check_implicit_always},
1277
  {"zdinx", "+zfinx", check_implicit_always},
1278
1279
  {"zfa", "+f", check_implicit_always},
1280
  {"zfbfmin", "+zfhmin", check_implicit_always},
1281
  {"zfh", "+zfhmin", check_implicit_always},
1282
  {"zfhmin", "+f", check_implicit_always},
1283
  {"zfinx", "+zicsr", check_implicit_always},
1284
  {"f", "+zicsr", check_implicit_always},
1285
1286
  {"zce", "+zcb,+zcmp,+zcmt", check_implicit_always},
1287
  {"zce", "+zcf", check_implicit_for_zcf},
1288
  {"zcb", "+zca", check_implicit_always},
1289
  {"zcmp", "+zca", check_implicit_always},
1290
  {"zcmop", "+zca", check_implicit_always},
1291
  {"zcmt", "+zca,+zicsr", check_implicit_always},
1292
  {"c", "+zcf", check_implicit_for_zcf},
1293
  {"c", "+zcd", check_implicit_for_zcd},
1294
  {"c", "+zca", check_implicit_always},
1295
1296
  {"b", "+zba,+zbb,+zbs", check_implicit_always},
1297
1298
  {"zk", "+zkn,+zkr,+zkt", check_implicit_always},
1299
  {"zkn", "+zbkb,+zbkc,+zbkx,+zkne,+zknd,+zknh", check_implicit_always},
1300
  {"zks", "+zbkb,+zbkc,+zbkx,+zksed,+zksh", check_implicit_always},
1301
  {"zvbb", "+zvkb", check_implicit_always},
1302
  {"zvkng", "+zvkn,+zvkg", check_implicit_always},
1303
  {"zvknc", "+zvkn,+zvbc", check_implicit_always},
1304
  {"zvkn", "+zvkned,+zvknhb,+zvkb,+zvkt", check_implicit_always},
1305
  {"zvksg", "+zvks,+zvkg", check_implicit_always},
1306
  {"zvksc", "+zvks,+zvbc", check_implicit_always},
1307
  {"zvks", "+zvksed,+zvksh,+zvkb,+zvkt", check_implicit_always},
1308
1309
  {"sdtrig", "+zicsr", check_implicit_always},
1310
1311
  {"smaia", "+ssaia", check_implicit_always},
1312
  {"smcdeleg", "+ssccfg", check_implicit_always},
1313
  {"smcsrind", "+sscsrind", check_implicit_always},
1314
  {"smcntrpmf", "+zicsr", check_implicit_always},
1315
  {"smctr", "+zicsr", check_implicit_always},
1316
  {"smrnmi", "+zicsr", check_implicit_always},
1317
  {"smstateen", "+ssstateen", check_implicit_always},
1318
  {"smepmp", "+zicsr", check_implicit_always},
1319
  {"smdbltrp", "+zicsr", check_implicit_always},
1320
  {"smnpm", "+zicsr", check_implicit_always},
1321
  {"smmpm", "+zicsr", check_implicit_always},
1322
1323
  {"ssaia", "+zicsr", check_implicit_always},
1324
  {"ssccfg", "+sscsrind", check_implicit_always},
1325
  {"sscsrind", "+zicsr", check_implicit_always},
1326
  {"sscofpmf", "+zicsr", check_implicit_always},
1327
  {"sscounterenw", "+zicsr", check_implicit_always},
1328
  {"ssctr", "+zicsr", check_implicit_always},
1329
  {"ssstateen", "+zicsr", check_implicit_always},
1330
  {"ssstrict", "+zicsr", check_implicit_always},
1331
  {"sstc", "+zicsr", check_implicit_always},
1332
  {"sstvala", "+zicsr", check_implicit_always},
1333
  {"sstvecd", "+zicsr", check_implicit_always},
1334
  {"ssu64xl", "+zicsr", check_implicit_always},
1335
  {"ssdbltrp", "+zicsr", check_implicit_always},
1336
  {"ssnpm", "+zicsr", check_implicit_always},
1337
1338
  {"svade", "+zicsr", check_implicit_always},
1339
  {"svadu", "+zicsr", check_implicit_always},
1340
  {"svbare", "+zicsr", check_implicit_always},
1341
  {NULL, NULL, NULL}
1342
};
1343
1344
/* This table records the mapping form RISC-V Profiles into march string.  */
1345
static const struct riscv_profiles riscv_profiles_table[] =
1346
{
1347
  /* RVI20U only contains the base extension 'i' as mandatory extension.  */
1348
  {"rvi20u64", "rv64i"},
1349
  {"rvi20u32", "rv32i"},
1350
1351
  /* RVA20U contains the 'i,m,a,f,d,c,zicsr,zicntr,ziccif,ziccrse,ziccamoa,
1352
     zicclsm,za128rs' as mandatory extensions.  */
1353
  {"rva20u64", "rv64imafdc_zicsr_zicntr_ziccif_ziccrse_ziccamoa"
1354
   "_zicclsm_za128rs"},
1355
1356
  /* RVA22U contains the 'i,m,a,f,d,c,zicsr,zihintpause,zba,zbb,zbs,zicntr,
1357
     zihpm,ziccif,ziccrse,ziccamoa, zicclsm,zic64b,za64rs,zicbom,zicbop,zicboz,
1358
     zfhmin,zkt' as mandatory extensions.  */
1359
  {"rva22u64", "rv64imafdc_zicsr_zicntr_ziccif_ziccrse_ziccamoa"
1360
   "_zicclsm_zic64b_za64rs_zihintpause_zba_zbb_zbs_zicbom_zicbop"
1361
   "_zicboz_zfhmin_zkt"},
1362
1363
  /* RVA23 contains all mandatory base ISA for RVA22U64 and the new extension
1364
     'v,zihintntl,zvfhmin,zvbb,zvkt,zicond,zimop,zcmop,zfa,zawrs' as mandatory
1365
     extensions.  */
1366
  {"rva23u64", "rv64imafdcbv_zicsr_zicntr_zihpm_ziccif_ziccrse_ziccamoa"
1367
   "_zicclsm_zic64b_za64rs_zihintpause_zba_zbb_zbs_zicbom_zicbop"
1368
   "_zicboz_zfhmin_zkt_zvfhmin_zvbb_zvkt_zihintntl_zicond_zimop_zcmop_zcb"
1369
   "_zfa_zawrs_supm"},
1370
1371
  /* RVA23S contains all mandatory base ISA for RVA23U64 and the privileged
1372
     extensions as mandatory extensions.  */
1373
  {"rva23s64", "rv64imafdcbv_zicsr_zicntr_zihpm_ziccif_ziccrse_ziccamoa"
1374
   "_zicclsm_zic64b_za64rs_zihintpause_zba_zbb_zbs_zicbom_zicbop"
1375
   "_zicboz_zfhmin_zkt_zvfhmin_zvbb_zvkt_zihintntl_zicond_zimop_zcmop_zcb"
1376
   "_zfa_zawrs_supm_svbare_svade_ssccptr_sstvecd_sstvala_sscounterenw_svpbmt"
1377
   "_svinval_svnapot_sstc_sscofpmf_ssnpm_ssu64xl_sha"},
1378
1379
  /* RVB23 contains all mandatory base ISA for RVA22U64 and the new extension
1380
     'zihintntl,zicond,zimop,zcmop,zfa,zawrs' as mandatory
1381
     extensions.  */
1382
  {"rvb23u64", "rv64imafdcb_zicsr_zicntr_zihpm_ziccif_ziccrse_ziccamoa"
1383
   "_zicclsm_zic64b_za64rs_zihintpause_zba_zbb_zbs_zicbom_zicbop"
1384
   "_zicboz_zfhmin_zkt_zihintntl_zicond_zimop_zcmop_zcb"
1385
   "_zfa_zawrs_supm"},
1386
1387
  /* RVB23S contains all mandatory base ISA for RVB23U64 and the privileged
1388
     extensions as mandatory extensions.  */
1389
  {"rvb23s64", "rv64imafdcb_zicsr_zicntr_zihpm_ziccif_ziccrse_ziccamoa"
1390
   "_zicclsm_zic64b_za64rs_zihintpause_zba_zbb_zbs_zicbom_zicbop"
1391
   "_zicboz_zfhmin_zkt_zvfhmin_zvbb_zvkt_zihintntl_zicond_zimop_zcmop_zcb"
1392
   "_zfa_zawrs_supm_svbare_svade_ssccptr_sstvecd_sstvala_sscounterenw_svpbmt"
1393
   "_svinval_svnapot_sstc_sscofpmf_ssu64xl"},
1394
1395
  /* Terminate the list.  */
1396
  {NULL, NULL}
1397
};
1398
1399
/* For default_enable field, decide if the extension should
1400
   be enbaled by default.  */
1401
1402
0
#define EXT_DEFAULT   0x1
1403
1404
/* List all extensions that binutils should know about.  */
1405
1406
struct riscv_supported_ext
1407
{
1408
  const char *name;
1409
  enum riscv_spec_class isa_spec_class;
1410
  int major_version;
1411
  int minor_version;
1412
  unsigned long default_enable;
1413
};
1414
1415
/* The standard extensions must be added in canonical order.  */
1416
1417
static const struct riscv_supported_ext riscv_supported_std_ext[] =
1418
{
1419
  {"e",   ISA_SPEC_CLASS_20191213,  1, 9, 0 },
1420
  {"e",   ISA_SPEC_CLASS_20190608,  1, 9, 0 },
1421
  {"e",   ISA_SPEC_CLASS_2P2,   1, 9, 0 },
1422
  {"i",   ISA_SPEC_CLASS_20191213,  2, 1, 0 },
1423
  {"i",   ISA_SPEC_CLASS_20190608,  2, 1, 0 },
1424
  {"i",   ISA_SPEC_CLASS_2P2,   2, 0, 0 },
1425
  /* The g is a special case which we don't want to output it,
1426
     but still need it when adding implicit extensions.  */
1427
  {"g",   ISA_SPEC_CLASS_NONE, RISCV_UNKNOWN_VERSION, RISCV_UNKNOWN_VERSION, EXT_DEFAULT },
1428
  {"m",   ISA_SPEC_CLASS_20191213,  2, 0, 0 },
1429
  {"m",   ISA_SPEC_CLASS_20190608,  2, 0, 0 },
1430
  {"m",   ISA_SPEC_CLASS_2P2,   2, 0, 0 },
1431
  {"a",   ISA_SPEC_CLASS_20191213,  2, 1, 0 },
1432
  {"a",   ISA_SPEC_CLASS_20190608,  2, 0, 0 },
1433
  {"a",   ISA_SPEC_CLASS_2P2,   2, 0, 0 },
1434
  {"f",   ISA_SPEC_CLASS_20191213,  2, 2, 0 },
1435
  {"f",   ISA_SPEC_CLASS_20190608,  2, 2, 0 },
1436
  {"f",   ISA_SPEC_CLASS_2P2,   2, 0, 0 },
1437
  {"d",   ISA_SPEC_CLASS_20191213,  2, 2, 0 },
1438
  {"d",   ISA_SPEC_CLASS_20190608,  2, 2, 0 },
1439
  {"d",   ISA_SPEC_CLASS_2P2,   2, 0, 0 },
1440
  {"q",   ISA_SPEC_CLASS_20191213,  2, 2, 0 },
1441
  {"q",   ISA_SPEC_CLASS_20190608,  2, 2, 0 },
1442
  {"q",   ISA_SPEC_CLASS_2P2,   2, 0, 0 },
1443
  {"c",   ISA_SPEC_CLASS_20191213,  2, 0, 0 },
1444
  {"c",   ISA_SPEC_CLASS_20190608,  2, 0, 0 },
1445
  {"c",   ISA_SPEC_CLASS_2P2,   2, 0, 0 },
1446
  {"b",   ISA_SPEC_CLASS_DRAFT,   1, 0, 0 },
1447
  {"v",   ISA_SPEC_CLASS_DRAFT,   1, 0, 0 },
1448
  {"h",   ISA_SPEC_CLASS_DRAFT,   1, 0, 0 },
1449
  {NULL, 0, 0, 0, 0}
1450
};
1451
1452
static const struct riscv_supported_ext riscv_supported_std_z_ext[] =
1453
{
1454
  {"zic64b",    ISA_SPEC_CLASS_DRAFT,   1, 0, 0 },
1455
  {"ziccamoa",    ISA_SPEC_CLASS_DRAFT,   1, 0, 0 },
1456
  {"ziccif",    ISA_SPEC_CLASS_DRAFT,   1, 0, 0 },
1457
  {"zicclsm",   ISA_SPEC_CLASS_DRAFT,   1, 0, 0 },
1458
  {"ziccrse",   ISA_SPEC_CLASS_DRAFT,   1, 0, 0 },
1459
  {"zicbom",    ISA_SPEC_CLASS_DRAFT,   1, 0, 0 },
1460
  {"zicbop",    ISA_SPEC_CLASS_DRAFT,   1, 0, 0 },
1461
  {"zicboz",    ISA_SPEC_CLASS_DRAFT,   1, 0, 0 },
1462
  {"zicond",    ISA_SPEC_CLASS_DRAFT,   1, 0, 0 },
1463
  {"zicntr",    ISA_SPEC_CLASS_DRAFT,   2, 0, 0 },
1464
  {"zicsr",   ISA_SPEC_CLASS_20191213,  2, 0, 0 },
1465
  {"zicsr",   ISA_SPEC_CLASS_20190608,  2, 0, 0 },
1466
  {"zifencei",    ISA_SPEC_CLASS_20191213,  2, 0, 0 },
1467
  {"zifencei",    ISA_SPEC_CLASS_20190608,  2, 0, 0 },
1468
  {"zihintntl",   ISA_SPEC_CLASS_DRAFT,   1, 0, 0 },
1469
  {"zihintpause", ISA_SPEC_CLASS_DRAFT,   2, 0, 0 },
1470
  {"zihpm",   ISA_SPEC_CLASS_DRAFT,   2, 0, 0 },
1471
  {"zimop",   ISA_SPEC_CLASS_DRAFT,   1, 0, 0 },
1472
  {"zicfiss",   ISA_SPEC_CLASS_DRAFT,   1, 0, 0 },
1473
  {"zicfilp",   ISA_SPEC_CLASS_DRAFT,   1, 0, 0 },
1474
  {"zilsd",   ISA_SPEC_CLASS_DRAFT,   1, 0, 0 },
1475
  {"zmmul",   ISA_SPEC_CLASS_DRAFT,   1, 0, 0 },
1476
  {"za64rs",    ISA_SPEC_CLASS_DRAFT,   1, 0, 0 },
1477
  {"za128rs",   ISA_SPEC_CLASS_DRAFT,   1, 0, 0 },
1478
  {"zaamo",   ISA_SPEC_CLASS_DRAFT,   1, 0, 0 },
1479
  {"zabha",   ISA_SPEC_CLASS_DRAFT,   1, 0, 0 },
1480
  {"zacas",   ISA_SPEC_CLASS_DRAFT,   1, 0, 0 },
1481
  {"zalrsc",    ISA_SPEC_CLASS_DRAFT,   1, 0, 0 },
1482
  {"zawrs",   ISA_SPEC_CLASS_DRAFT,   1, 0, 0 },
1483
  {"zfbfmin",   ISA_SPEC_CLASS_DRAFT,   1, 0, 0 },
1484
  {"zfa",   ISA_SPEC_CLASS_DRAFT,   1, 0, 0 },
1485
  {"zfh",   ISA_SPEC_CLASS_DRAFT,   1, 0, 0 },
1486
  {"zfhmin",    ISA_SPEC_CLASS_DRAFT,   1, 0, 0 },
1487
  {"zfinx",   ISA_SPEC_CLASS_DRAFT,   1, 0, 0 },
1488
  {"zdinx",   ISA_SPEC_CLASS_DRAFT,   1, 0, 0 },
1489
  {"zqinx",   ISA_SPEC_CLASS_DRAFT,   1, 0, 0 },
1490
  {"zhinx",   ISA_SPEC_CLASS_DRAFT,   1, 0, 0 },
1491
  {"zhinxmin",    ISA_SPEC_CLASS_DRAFT,   1, 0, 0 },
1492
  {"zbb",   ISA_SPEC_CLASS_DRAFT,   1, 0, 0 },
1493
  {"zba",   ISA_SPEC_CLASS_DRAFT,   1, 0, 0 },
1494
  {"zbc",   ISA_SPEC_CLASS_DRAFT,   1, 0, 0 },
1495
  {"zbs",   ISA_SPEC_CLASS_DRAFT,   1, 0, 0 },
1496
  {"zbkb",    ISA_SPEC_CLASS_DRAFT,   1, 0, 0 },
1497
  {"zbkc",    ISA_SPEC_CLASS_DRAFT,   1, 0, 0 },
1498
  {"zbkx",    ISA_SPEC_CLASS_DRAFT,   1, 0, 0 },
1499
  {"zk",    ISA_SPEC_CLASS_DRAFT,   1, 0, 0 },
1500
  {"zkn",   ISA_SPEC_CLASS_DRAFT,   1, 0, 0 },
1501
  {"zknd",    ISA_SPEC_CLASS_DRAFT,   1, 0, 0 },
1502
  {"zkne",    ISA_SPEC_CLASS_DRAFT,   1, 0, 0 },
1503
  {"zknh",    ISA_SPEC_CLASS_DRAFT,   1, 0, 0 },
1504
  {"zkr",   ISA_SPEC_CLASS_DRAFT,   1, 0, 0 },
1505
  {"zks",   ISA_SPEC_CLASS_DRAFT,   1, 0, 0 },
1506
  {"zksed",   ISA_SPEC_CLASS_DRAFT,   1, 0, 0 },
1507
  {"zksh",    ISA_SPEC_CLASS_DRAFT,   1, 0, 0 },
1508
  {"zkt",   ISA_SPEC_CLASS_DRAFT,   1, 0, 0 },
1509
  {"zve32x",    ISA_SPEC_CLASS_DRAFT,   1, 0, 0 },
1510
  {"zve32f",    ISA_SPEC_CLASS_DRAFT,   1, 0, 0 },
1511
  {"zve64x",    ISA_SPEC_CLASS_DRAFT,   1, 0, 0 },
1512
  {"zve64f",    ISA_SPEC_CLASS_DRAFT,   1, 0, 0 },
1513
  {"zve64d",    ISA_SPEC_CLASS_DRAFT,   1, 0, 0 },
1514
  {"zvbb",    ISA_SPEC_CLASS_DRAFT,   1, 0, 0 },
1515
  {"zvbc",    ISA_SPEC_CLASS_DRAFT,   1, 0, 0 },
1516
  {"zvfbfmin",    ISA_SPEC_CLASS_DRAFT,   1, 0, 0 },
1517
  {"zvfbfwma",    ISA_SPEC_CLASS_DRAFT,   1, 0, 0 },
1518
  {"zvfh",    ISA_SPEC_CLASS_DRAFT,   1, 0, 0 },
1519
  {"zvfhmin",   ISA_SPEC_CLASS_DRAFT,   1, 0, 0 },
1520
  {"zvkb",    ISA_SPEC_CLASS_DRAFT,   1, 0, 0 },
1521
  {"zvkg",    ISA_SPEC_CLASS_DRAFT,   1, 0, 0 },
1522
  {"zvkn",    ISA_SPEC_CLASS_DRAFT,   1, 0, 0 },
1523
  {"zvkng",   ISA_SPEC_CLASS_DRAFT,   1, 0, 0 },
1524
  {"zvknc",   ISA_SPEC_CLASS_DRAFT,   1, 0, 0 },
1525
  {"zvkned",    ISA_SPEC_CLASS_DRAFT,   1, 0, 0 },
1526
  {"zvknha",    ISA_SPEC_CLASS_DRAFT,   1, 0, 0 },
1527
  {"zvknhb",    ISA_SPEC_CLASS_DRAFT,   1, 0, 0 },
1528
  {"zvksed",    ISA_SPEC_CLASS_DRAFT,   1, 0, 0 },
1529
  {"zvksh",   ISA_SPEC_CLASS_DRAFT,   1, 0, 0 },
1530
  {"zvks",    ISA_SPEC_CLASS_DRAFT,   1, 0, 0 },
1531
  {"zvksg",   ISA_SPEC_CLASS_DRAFT,   1, 0, 0 },
1532
  {"zvksc",   ISA_SPEC_CLASS_DRAFT,   1, 0, 0 },
1533
  {"zvkt",    ISA_SPEC_CLASS_DRAFT,   1, 0, 0 },
1534
  {"zvl32b",    ISA_SPEC_CLASS_DRAFT,   1, 0, 0 },
1535
  {"zvl64b",    ISA_SPEC_CLASS_DRAFT,   1, 0, 0 },
1536
  {"zvl128b",   ISA_SPEC_CLASS_DRAFT,   1, 0, 0 },
1537
  {"zvl256b",   ISA_SPEC_CLASS_DRAFT,   1, 0, 0 },
1538
  {"zvl512b",   ISA_SPEC_CLASS_DRAFT,   1, 0, 0 },
1539
  {"zvl1024b",    ISA_SPEC_CLASS_DRAFT,   1, 0, 0 },
1540
  {"zvl2048b",    ISA_SPEC_CLASS_DRAFT,   1, 0, 0 },
1541
  {"zvl4096b",    ISA_SPEC_CLASS_DRAFT,   1, 0, 0 },
1542
  {"zvl8192b",    ISA_SPEC_CLASS_DRAFT,   1, 0, 0 },
1543
  {"zvl16384b",   ISA_SPEC_CLASS_DRAFT,   1, 0, 0 },
1544
  {"zvl32768b",   ISA_SPEC_CLASS_DRAFT,   1, 0, 0 },
1545
  {"zvl65536b",   ISA_SPEC_CLASS_DRAFT,   1, 0, 0 },
1546
  {"ztso",    ISA_SPEC_CLASS_DRAFT,   1, 0, 0 },
1547
  {"zca",   ISA_SPEC_CLASS_DRAFT,   1, 0, 0 },
1548
  {"zcb",   ISA_SPEC_CLASS_DRAFT,   1, 0, 0 },
1549
  {"zce",   ISA_SPEC_CLASS_DRAFT,   1, 0, 0 },
1550
  {"zcf",   ISA_SPEC_CLASS_DRAFT,   1, 0, 0 },
1551
  {"zcd",   ISA_SPEC_CLASS_DRAFT,   1, 0, 0 },
1552
  {"zcmop",   ISA_SPEC_CLASS_DRAFT,   1, 0, 0 },
1553
  {"zcmp",    ISA_SPEC_CLASS_DRAFT,   1, 0, 0 },
1554
  {"zcmt",    ISA_SPEC_CLASS_DRAFT,   1, 0, 0 },
1555
  {"zclsd",   ISA_SPEC_CLASS_DRAFT,   1, 0, 0 },
1556
  {NULL, 0, 0, 0, 0}
1557
};
1558
1559
static const struct riscv_supported_ext riscv_supported_std_s_ext[] =
1560
{
1561
  {"sdtrig",    ISA_SPEC_CLASS_DRAFT,   1, 0, 0 },
1562
  {"sha",   ISA_SPEC_CLASS_DRAFT,   1, 0, 0 },
1563
  {"shcounterenw",  ISA_SPEC_CLASS_DRAFT,   1, 0, 0 },
1564
  {"shgatpa",   ISA_SPEC_CLASS_DRAFT,   1, 0, 0 },
1565
  {"shtvala",   ISA_SPEC_CLASS_DRAFT,   1, 0, 0 },
1566
  {"shvsatpa",    ISA_SPEC_CLASS_DRAFT,   1, 0, 0 },
1567
  {"shvstvala",   ISA_SPEC_CLASS_DRAFT,   1, 0, 0 },
1568
  {"shvstvecd",   ISA_SPEC_CLASS_DRAFT,   1, 0, 0 },
1569
  {"smaia",   ISA_SPEC_CLASS_DRAFT,   1, 0, 0 },
1570
  {"smcdeleg",    ISA_SPEC_CLASS_DRAFT,   1, 0, 0 },
1571
  {"smcsrind",    ISA_SPEC_CLASS_DRAFT,   1, 0, 0 },
1572
  {"smcntrpmf",   ISA_SPEC_CLASS_DRAFT,   1, 0, 0 },
1573
  {"smctr",   ISA_SPEC_CLASS_DRAFT,   1, 0, 0 },
1574
  {"smepmp",    ISA_SPEC_CLASS_DRAFT,   1, 0, 0 },
1575
  {"smrnmi",    ISA_SPEC_CLASS_DRAFT,   1, 0, 0 },
1576
  {"smstateen",   ISA_SPEC_CLASS_DRAFT,   1, 0, 0 },
1577
  {"smdbltrp",    ISA_SPEC_CLASS_DRAFT,   1, 0, 0 },
1578
  {"ssaia",   ISA_SPEC_CLASS_DRAFT,   1, 0, 0 },
1579
  {"ssccfg",    ISA_SPEC_CLASS_DRAFT,   1, 0, 0 },
1580
  {"ssccptr",   ISA_SPEC_CLASS_DRAFT,   1, 0, 0 },
1581
  {"sscsrind",    ISA_SPEC_CLASS_DRAFT,   1, 0, 0 },
1582
  {"sscofpmf",    ISA_SPEC_CLASS_DRAFT,   1, 0, 0 },
1583
  {"sscounterenw",  ISA_SPEC_CLASS_DRAFT,   1, 0, 0 },
1584
  {"ssctr",   ISA_SPEC_CLASS_DRAFT,   1, 0, 0 },
1585
  {"ssstateen",   ISA_SPEC_CLASS_DRAFT,   1, 0, 0 },
1586
  {"ssstrict",    ISA_SPEC_CLASS_DRAFT,   1, 0, 0 },
1587
  {"sstc",    ISA_SPEC_CLASS_DRAFT,   1, 0, 0 },
1588
  {"sstvala",   ISA_SPEC_CLASS_DRAFT,   1, 0, 0 },
1589
  {"sstvecd",   ISA_SPEC_CLASS_DRAFT,   1, 0, 0 },
1590
  {"ssu64xl",   ISA_SPEC_CLASS_DRAFT,   1, 0, 0 },
1591
  {"ssdbltrp",    ISA_SPEC_CLASS_DRAFT,   1, 0, 0 },
1592
  {"svade",   ISA_SPEC_CLASS_DRAFT,   1, 0, 0 },
1593
  {"svadu",   ISA_SPEC_CLASS_DRAFT,   1, 0, 0 },
1594
  {"svbare",    ISA_SPEC_CLASS_DRAFT,   1, 0, 0 },
1595
  {"svinval",   ISA_SPEC_CLASS_DRAFT,   1, 0, 0 },
1596
  {"svnapot",   ISA_SPEC_CLASS_DRAFT,   1, 0, 0 },
1597
  {"svpbmt",    ISA_SPEC_CLASS_DRAFT,   1, 0, 0 },
1598
  {"svvptc",    ISA_SPEC_CLASS_DRAFT,   1, 0, 0 },
1599
  {"ssqosid",   ISA_SPEC_CLASS_DRAFT,   1, 0, 0 },
1600
  {"ssnpm",   ISA_SPEC_CLASS_DRAFT,   1, 0, 0 },
1601
  {"smnpm",   ISA_SPEC_CLASS_DRAFT,   1, 0, 0 },
1602
  {"smmpm",   ISA_SPEC_CLASS_DRAFT,   1, 0, 0 },
1603
  {"sspm",    ISA_SPEC_CLASS_DRAFT,   1, 0, 0 },
1604
  {"supm",    ISA_SPEC_CLASS_DRAFT,   1, 0, 0 },
1605
  {NULL, 0, 0, 0, 0}
1606
};
1607
1608
static const struct riscv_supported_ext riscv_supported_std_zxm_ext[] =
1609
{
1610
  {NULL, 0, 0, 0, 0}
1611
};
1612
1613
static const struct riscv_supported_ext riscv_supported_vendor_x_ext[] =
1614
{
1615
  {"xcvalu",    ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1616
  {"xcvbi",   ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1617
  {"xcvbitmanip", ISA_SPEC_CLASS_DRAFT,   1, 0, 0 },
1618
  {"xcvelw",    ISA_SPEC_CLASS_DRAFT,   1, 0, 0 },
1619
  {"xcvmac",    ISA_SPEC_CLASS_DRAFT,   1, 0, 0 },
1620
  {"xcvmem",    ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1621
  {"xcvsimd",   ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1622
  {"xtheadba",    ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1623
  {"xtheadbb",    ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1624
  {"xtheadbs",    ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1625
  {"xtheadcmo",   ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1626
  {"xtheadcondmov", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1627
  {"xtheadfmemidx", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1628
  {"xtheadfmv",   ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1629
  {"xtheadint",   ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1630
  {"xtheadmac",   ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1631
  {"xtheadmemidx",  ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1632
  {"xtheadmempair", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1633
  {"xtheadsync",  ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1634
  {"xtheadvector",  ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1635
  {"xtheadvdot",  ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1636
  {"xtheadzvamo", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1637
  {"xventanacondops", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1638
  {"xsfvcp",    ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1639
  {"xsfcease",    ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1640
  {"xsfvqmaccqoq",  ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1641
  {"xsfvqmaccdod",  ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1642
  {"xsfvfnrclipxfqf", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1643
  {"xmipscbop",   ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1644
  {"xmipscmov",   ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1645
  {"xmipsexectl", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1646
  {"xmipslsp",    ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1647
  {NULL, 0, 0, 0, 0}
1648
};
1649
1650
static const struct riscv_supported_ext *riscv_all_supported_ext[] =
1651
{
1652
  riscv_supported_std_ext,
1653
  riscv_supported_std_z_ext,
1654
  riscv_supported_std_s_ext,
1655
  riscv_supported_std_zxm_ext,
1656
  riscv_supported_vendor_x_ext,
1657
  NULL
1658
};
1659
1660
/* ISA extension prefixed name class.  Must define them in parsing order.  */
1661
enum riscv_prefix_ext_class
1662
{
1663
  RV_ISA_CLASS_Z = 1,
1664
  RV_ISA_CLASS_S,
1665
  RV_ISA_CLASS_ZXM,
1666
  RV_ISA_CLASS_X,
1667
  RV_ISA_CLASS_SINGLE
1668
};
1669
1670
/* Record the strings of the prefixed extensions, and their corresponding
1671
   classes.  The more letters of the prefix string, the more forward it must
1672
   be defined.  Otherwise, the riscv_get_prefix_class will map it to the
1673
   wrong classes.  */
1674
struct riscv_parse_prefix_config
1675
{
1676
  /* Class of the extension. */
1677
  enum riscv_prefix_ext_class class;
1678
1679
  /* Prefix string for error printing and internal parser usage.  */
1680
  const char *prefix;
1681
};
1682
static const struct riscv_parse_prefix_config parse_config[] =
1683
{
1684
  {RV_ISA_CLASS_ZXM, "zxm"},
1685
  {RV_ISA_CLASS_Z, "z"},
1686
  {RV_ISA_CLASS_S, "s"},
1687
  {RV_ISA_CLASS_X, "x"},
1688
  {RV_ISA_CLASS_SINGLE, NULL}
1689
};
1690
1691
/* Get the prefixed name class for the extensions, the class also
1692
   means the order of the prefixed extensions.  */
1693
1694
static enum riscv_prefix_ext_class
1695
riscv_get_prefix_class (const char *arch)
1696
43.7M
{
1697
43.7M
  int i = 0;
1698
120M
  while (parse_config[i].class != RV_ISA_CLASS_SINGLE)
1699
109M
    {
1700
109M
      if (strncmp (arch, parse_config[i].prefix,
1701
109M
       strlen (parse_config[i].prefix)) == 0)
1702
32.8M
  return parse_config[i].class;
1703
76.4M
      i++;
1704
76.4M
    }
1705
10.8M
  return RV_ISA_CLASS_SINGLE;
1706
43.7M
}
1707
1708
/* Check KNOWN_EXTS to see if the EXT is supported.  */
1709
1710
static bool
1711
riscv_known_prefixed_ext (const char *ext,
1712
        const struct riscv_supported_ext *known_exts)
1713
0
{
1714
0
  size_t i;
1715
0
  for (i = 0; known_exts[i].name != NULL; ++i)
1716
0
    if (strcmp (ext, known_exts[i].name) == 0)
1717
0
      return true;
1718
0
  return false;
1719
0
}
1720
1721
/* Check whether the prefixed extension is recognized or not.  Return
1722
   true if recognized, otehrwise return false.  */
1723
1724
static bool
1725
riscv_recognized_prefixed_ext (const char *ext)
1726
0
{
1727
0
  enum riscv_prefix_ext_class class = riscv_get_prefix_class (ext);
1728
0
  switch (class)
1729
0
  {
1730
0
  case RV_ISA_CLASS_Z:
1731
0
    return riscv_known_prefixed_ext (ext, riscv_supported_std_z_ext);
1732
0
  case RV_ISA_CLASS_ZXM:
1733
0
    return riscv_known_prefixed_ext (ext, riscv_supported_std_zxm_ext);
1734
0
  case RV_ISA_CLASS_S:
1735
0
    return riscv_known_prefixed_ext (ext, riscv_supported_std_s_ext);
1736
0
  case RV_ISA_CLASS_X:
1737
    /* Only the single x is unrecognized.  */
1738
0
    if (strcmp (ext, "x") != 0)
1739
0
      return true;
1740
0
  default:
1741
0
    break;
1742
0
  }
1743
0
  return false;
1744
0
}
1745
1746
/* Canonical order for single letter extensions.  */
1747
static const char riscv_ext_canonical_order[] = "eigmafdqlcbkjtpvnh";
1748
1749
/* Array is used to compare the orders of standard extensions quickly.  */
1750
static int riscv_ext_order[26] = {0};
1751
1752
/* Init the riscv_ext_order array.  */
1753
1754
static void
1755
riscv_init_ext_order (void)
1756
828
{
1757
828
  static bool inited = false;
1758
828
  if (inited)
1759
826
    return;
1760
1761
  /* The orders of all standard extensions are positive.  */
1762
2
  int order = 1;
1763
1764
38
  for (const char *ext = &riscv_ext_canonical_order[0]; *ext; ++ext)
1765
36
    riscv_ext_order[(*ext - 'a')] = order++;
1766
1767
  /* Some of the prefixed keyword are not single letter, so we set
1768
     their prefixed orders in the riscv_compare_subsets directly,
1769
     not through the riscv_ext_order.  */
1770
1771
2
  inited = true;
1772
2
}
1773
1774
/* Similar to the strcmp.  It returns an integer less than, equal to,
1775
   or greater than zero if `subset2` is found, respectively, to be less
1776
   than, to match, or be greater than `subset1`.
1777
1778
   The order values,
1779
   Zero: Preserved keywords.
1780
   Positive number: Standard extensions.
1781
   Negative number: Prefixed keywords.  */
1782
1783
int
1784
riscv_compare_subsets (const char *subset1, const char *subset2)
1785
22.1M
{
1786
22.1M
  int order1 = riscv_ext_order[(*subset1 - 'a')];
1787
22.1M
  int order2 = riscv_ext_order[(*subset2 - 'a')];
1788
1789
  /* Compare the standard extension first.  */
1790
22.1M
  if (order1 > 0 && order2 > 0)
1791
275k
    return order1 - order2;
1792
1793
  /* Set the prefixed orders to negative numbers.  */
1794
21.8M
  enum riscv_prefix_ext_class class1 = riscv_get_prefix_class (subset1);
1795
21.8M
  enum riscv_prefix_ext_class class2 = riscv_get_prefix_class (subset2);
1796
1797
21.8M
  if (class1 != RV_ISA_CLASS_SINGLE)
1798
11.0M
    order1 = - (int) class1;
1799
21.8M
  if (class2 != RV_ISA_CLASS_SINGLE)
1800
21.7M
    order2 = - (int) class2;
1801
1802
21.8M
  if (order1 == order2)
1803
10.9M
    {
1804
      /* Compare the standard addition z extensions.  */
1805
10.9M
      if (class1 == RV_ISA_CLASS_Z)
1806
10.9M
  {
1807
10.9M
    order1 = riscv_ext_order[(*++subset1 - 'a')];
1808
10.9M
    order2 = riscv_ext_order[(*++subset2 - 'a')];
1809
10.9M
    if (order1 != order2)
1810
9.45M
      return order1 - order2;
1811
10.9M
  }
1812
1.46M
      return strcasecmp (++subset1, ++subset2);
1813
10.9M
    }
1814
1815
10.9M
  return order2 - order1;
1816
21.8M
}
1817
1818
/* Find subset in the list.  Return TRUE and set `current` to the subset
1819
   if it is found.  Otherwise, return FALSE and set `current` to the place
1820
   where we should insert the subset.  However, return FALSE with the NULL
1821
   `current` means we should insert the subset at the head of subset list,
1822
   if needed.  */
1823
1824
bool
1825
riscv_lookup_subset (const riscv_subset_list_t *subset_list,
1826
         const char *subset,
1827
         riscv_subset_t **current)
1828
1.75M
{
1829
1.75M
  riscv_subset_t *s, *pre_s = NULL;
1830
1831
  /* If the subset is added in order, then just add it at the tail.  */
1832
1.75M
  if (subset_list->tail != NULL
1833
1.75M
      && riscv_compare_subsets (subset_list->tail->name, subset) < 0)
1834
133k
    {
1835
133k
      *current = subset_list->tail;
1836
133k
      return false;
1837
133k
    }
1838
1839
1.62M
  for (s = subset_list->head;
1840
20.3M
       s != NULL;
1841
18.7M
       pre_s = s, s = s->next)
1842
20.3M
    {
1843
20.3M
      int cmp = riscv_compare_subsets (s->name, subset);
1844
20.3M
      if (cmp == 0)
1845
709k
  {
1846
709k
    *current = s;
1847
709k
    return true;
1848
709k
  }
1849
19.6M
      else if (cmp > 0)
1850
910k
  break;
1851
20.3M
    }
1852
911k
  *current = pre_s;
1853
1854
911k
  return false;
1855
1.62M
}
1856
1857
/* Add the extension to the subset list.  Search the
1858
   list first, and then find the right place to add.  */
1859
1860
void
1861
riscv_add_subset (riscv_subset_list_t *subset_list,
1862
      const char *subset,
1863
      int major,
1864
      int minor)
1865
11.5k
{
1866
11.5k
  riscv_subset_t *current, *new;
1867
1868
11.5k
  if (riscv_lookup_subset (subset_list, subset, &current))
1869
0
    return;
1870
1871
11.5k
  new = xmalloc (sizeof *new);
1872
11.5k
  new->name = xstrdup (subset);
1873
11.5k
  new->major_version = major;
1874
11.5k
  new->minor_version = minor;
1875
11.5k
  new->next = NULL;
1876
1877
11.5k
  if (current != NULL)
1878
9.93k
    {
1879
9.93k
      new->next = current->next;
1880
9.93k
      current->next = new;
1881
9.93k
    }
1882
1.65k
  else
1883
1.65k
    {
1884
1.65k
      new->next = subset_list->head;
1885
1.65k
      subset_list->head = new;
1886
1.65k
    }
1887
1888
11.5k
  if (new->next == NULL)
1889
6.62k
    subset_list->tail = new;
1890
11.5k
}
1891
1892
/* Get the default versions from the riscv_supported_*ext tables.  */
1893
1894
static void
1895
riscv_get_default_ext_version (enum riscv_spec_class *default_isa_spec,
1896
             const char *name,
1897
             int *major_version,
1898
             int *minor_version)
1899
11.5k
{
1900
11.5k
  if (name == NULL
1901
11.5k
      || default_isa_spec == NULL
1902
11.5k
      || *default_isa_spec == ISA_SPEC_CLASS_NONE)
1903
0
    return;
1904
1905
11.5k
  const struct riscv_supported_ext *table = NULL;
1906
11.5k
  enum riscv_prefix_ext_class class = riscv_get_prefix_class (name);
1907
11.5k
  switch (class)
1908
11.5k
    {
1909
0
    case RV_ISA_CLASS_ZXM: table = riscv_supported_std_zxm_ext; break;
1910
5.79k
    case RV_ISA_CLASS_Z: table = riscv_supported_std_z_ext; break;
1911
0
    case RV_ISA_CLASS_S: table = riscv_supported_std_s_ext; break;
1912
0
    case RV_ISA_CLASS_X: table = riscv_supported_vendor_x_ext; break;
1913
5.79k
    default:
1914
5.79k
      table = riscv_supported_std_ext;
1915
11.5k
    }
1916
1917
11.5k
  int i = 0;
1918
328k
  while (table != NULL && table[i].name != NULL)
1919
327k
    {
1920
327k
      if (strcmp (table[i].name, name) == 0
1921
11.5k
    && (table[i].isa_spec_class == ISA_SPEC_CLASS_DRAFT
1922
7.45k
        || table[i].isa_spec_class == *default_isa_spec))
1923
10.7k
  {
1924
10.7k
    *major_version = table[i].major_version;
1925
10.7k
    *minor_version = table[i].minor_version;
1926
10.7k
    return;
1927
10.7k
  }
1928
317k
      i++;
1929
317k
    }
1930
11.5k
}
1931
1932
/* Find the default versions for the extension before adding them to
1933
   the subset list, if their versions are RISCV_UNKNOWN_VERSION.
1934
   Afterwards, report errors if we can not find their default versions.  */
1935
1936
static void
1937
riscv_parse_add_subset (riscv_parse_subset_t *rps,
1938
      const char *subset,
1939
      int major,
1940
      int minor,
1941
      bool implicit)
1942
11.5k
{
1943
11.5k
  int major_version = major;
1944
11.5k
  int minor_version = minor;
1945
1946
11.5k
  if (major_version == RISCV_UNKNOWN_VERSION
1947
0
       || minor_version == RISCV_UNKNOWN_VERSION)
1948
11.5k
    riscv_get_default_ext_version (rps->isa_spec, subset,
1949
11.5k
           &major_version, &minor_version);
1950
1951
  /* We don't care the versions of the implicit extensions.  */
1952
11.5k
  if (!implicit
1953
828
      && (major_version == RISCV_UNKNOWN_VERSION
1954
828
    || minor_version == RISCV_UNKNOWN_VERSION))
1955
0
    {
1956
0
      if (subset[0] == 'x')
1957
0
  rps->error_handler
1958
0
    (_("x ISA extension `%s' must be set with the versions"),
1959
0
     subset);
1960
      /* Allow old ISA spec can recognize zicsr and zifencei.  */
1961
0
      else if (strcmp (subset, "zicsr") != 0
1962
0
         && strcmp (subset, "zifencei") != 0)
1963
0
  rps->error_handler
1964
0
    (_("cannot find default versions of the ISA extension `%s'"),
1965
0
     subset);
1966
0
      return;
1967
0
    }
1968
1969
11.5k
  riscv_add_subset (rps->subset_list, subset,
1970
11.5k
        major_version, minor_version);
1971
11.5k
}
1972
1973
/* Release subset list.  */
1974
1975
void
1976
riscv_release_subset_list (riscv_subset_list_t *subset_list)
1977
1.65k
{
1978
13.2k
   while (subset_list->head != NULL)
1979
11.5k
    {
1980
11.5k
      riscv_subset_t *next = subset_list->head->next;
1981
11.5k
      free ((void *)subset_list->head->name);
1982
11.5k
      free (subset_list->head);
1983
11.5k
      subset_list->head = next;
1984
11.5k
    }
1985
1986
1.65k
  subset_list->tail = NULL;
1987
1988
1.65k
  if (subset_list->arch_str != NULL)
1989
828
    {
1990
828
      free ((void*) subset_list->arch_str);
1991
828
      subset_list->arch_str = NULL;
1992
828
    }
1993
1.65k
}
1994
1995
/* Parsing extension version.
1996
1997
   Return Value:
1998
     Points to the end of version
1999
2000
   Arguments:
2001
     `p`: Curent parsing position.
2002
     `major_version`: Parsed major version.
2003
     `minor_version`: Parsed minor version.  */
2004
2005
static const char *
2006
riscv_parsing_subset_version (const char *p,
2007
            int *major_version,
2008
            int *minor_version)
2009
13.2k
{
2010
13.2k
  bool major_p = true;
2011
13.2k
  int version = 0;
2012
13.2k
  char np;
2013
2014
13.2k
  *major_version = 0;
2015
13.2k
  *minor_version = 0;
2016
13.2k
  for (; *p; ++p)
2017
6.62k
    {
2018
6.62k
      if (*p == 'p')
2019
0
  {
2020
0
    np = *(p + 1);
2021
2022
    /* Might be beginning of `p` extension.  */
2023
0
    if (!ISDIGIT (np))
2024
0
      break;
2025
2026
0
    *major_version = version;
2027
0
    major_p = false;
2028
0
    version = 0;
2029
0
  }
2030
6.62k
      else if (ISDIGIT (*p))
2031
0
  version = (version * 10) + (*p - '0');
2032
6.62k
      else
2033
6.62k
  break;
2034
6.62k
    }
2035
2036
13.2k
  if (major_p)
2037
13.2k
    *major_version = version;
2038
0
  else
2039
0
    *minor_version = version;
2040
2041
  /* We can not find any version in string.  */
2042
13.2k
  if (*major_version == 0 && *minor_version == 0)
2043
13.2k
    {
2044
13.2k
      *major_version = RISCV_UNKNOWN_VERSION;
2045
13.2k
      *minor_version = RISCV_UNKNOWN_VERSION;
2046
13.2k
    }
2047
2048
13.2k
  return p;
2049
13.2k
}
2050
2051
/* Parsing function for both standard and prefixed extensions.
2052
2053
   Return Value:
2054
     Points to the end of extensions.
2055
2056
   Arguments:
2057
     `rps`: Hooks and status for parsing extensions.
2058
     `arch`: Full ISA string.
2059
     `p`: Curent parsing position.  */
2060
2061
static const char *
2062
riscv_parse_extensions (riscv_parse_subset_t *rps,
2063
      const char *arch,
2064
      const char *p,
2065
      bool profile)
2066
828
{
2067
  /* First letter must start with i, e, g or a profile.  */
2068
828
  if (*p != 'e' && *p != 'i' && *p != 'g' && !profile)
2069
0
    {
2070
0
      rps->error_handler
2071
0
  (_("%s: first ISA extension must be `e', `i' or `g'"),
2072
0
   arch);
2073
0
      return NULL;
2074
0
    }
2075
2076
2.48k
  while (*p != '\0')
2077
1.65k
    {
2078
1.65k
      if (*p == '_')
2079
0
  {
2080
0
    p++;
2081
0
    continue;
2082
0
  }
2083
2084
1.65k
      char *subset = xstrdup (p);
2085
1.65k
      char *q = subset; /* Start of version.  */
2086
1.65k
      const char *end_of_version;
2087
1.65k
      bool implicit = false;
2088
2089
1.65k
      enum riscv_prefix_ext_class class = riscv_get_prefix_class (p);
2090
1.65k
      if (class == RV_ISA_CLASS_SINGLE)
2091
1.65k
  {
2092
1.65k
    if (riscv_ext_order[(*subset - 'a')] == 0)
2093
0
      {
2094
0
        rps->error_handler
2095
0
    (_("%s: unknown standard ISA extension or prefix class `%c'"),
2096
0
     arch, *subset);
2097
0
        free (subset);
2098
0
        return NULL;
2099
0
      }
2100
1.65k
    q++;
2101
1.65k
  }
2102
0
      else
2103
0
  {
2104
    /* Extract the whole prefixed extension by '_'.  */
2105
0
    while (*++q != '\0' && *q != '_')
2106
0
      ;
2107
    /* Look forward to the first letter which is not <major>p<minor>.  */
2108
0
    bool find_any_version = false;
2109
0
    bool find_minor_version = false;
2110
0
    while (1)
2111
0
      {
2112
0
        q--;
2113
0
        if (ISDIGIT (*q))
2114
0
    find_any_version = true;
2115
0
        else if (find_any_version
2116
0
           && !find_minor_version
2117
0
           && *q == 'p'
2118
0
           && ISDIGIT (*(q - 1)))
2119
0
        find_minor_version = true;
2120
0
        else
2121
0
    break;
2122
0
      }
2123
0
    q++;
2124
2125
    /* Check if the end of extension is 'p' or not.  If yes, then
2126
       the second letter from the end cannot be number.  */
2127
0
    if (*(q - 1) == 'p' && ISDIGIT (*(q - 2)))
2128
0
      {
2129
0
        *q = '\0';
2130
0
        rps->error_handler
2131
0
    (_("%s: invalid prefixed ISA extension `%s' ends with <number>p"),
2132
0
     arch, subset);
2133
0
        free (subset);
2134
0
        return NULL;
2135
0
      }
2136
0
  }
2137
2138
1.65k
      int major_version = RISCV_UNKNOWN_VERSION;
2139
1.65k
      int minor_version = RISCV_UNKNOWN_VERSION;
2140
1.65k
      end_of_version =
2141
1.65k
  riscv_parsing_subset_version (q, &major_version, &minor_version);
2142
1.65k
      *q = '\0';
2143
1.65k
      if (end_of_version == NULL)
2144
0
  {
2145
0
    free (subset);
2146
0
    return NULL;
2147
0
  }
2148
2149
      /* Check if the prefixed extension name is well-formed.  */
2150
1.65k
      if (class != RV_ISA_CLASS_SINGLE
2151
0
    && rps->check_unknown_prefixed_ext
2152
0
    && !riscv_recognized_prefixed_ext (subset))
2153
0
  {
2154
0
    rps->error_handler
2155
0
      (_("%s: unknown prefixed ISA extension `%s'"),
2156
0
       arch, subset);
2157
0
    free (subset);
2158
0
    return NULL;
2159
0
  }
2160
2161
      /* Added g as an implicit extension.  */
2162
1.65k
      if (class == RV_ISA_CLASS_SINGLE
2163
1.65k
    && strcmp (subset, "g") == 0)
2164
828
  {
2165
828
    implicit = true;
2166
828
    major_version = RISCV_UNKNOWN_VERSION;
2167
828
    minor_version = RISCV_UNKNOWN_VERSION;
2168
828
  }
2169
1.65k
      riscv_parse_add_subset (rps, subset,
2170
1.65k
            major_version,
2171
1.65k
            minor_version, implicit);
2172
1.65k
      p += end_of_version - subset;
2173
1.65k
      free (subset);
2174
2175
1.65k
      if (class != RV_ISA_CLASS_SINGLE
2176
0
    && *p != '\0' && *p != '_')
2177
0
  {
2178
0
    rps->error_handler
2179
0
      (_("%s: prefixed ISA extension must separate with _"),
2180
0
       arch);
2181
0
    return NULL;
2182
0
  }
2183
1.65k
    }
2184
2185
828
  return p;
2186
828
}
2187
2188
static bool
2189
riscv_update_subset1 (riscv_parse_subset_t *, riscv_subset_t *, const char *);
2190
2191
/* Add the implicit extensions.  */
2192
2193
static void
2194
riscv_parse_add_implicit_subsets (riscv_parse_subset_t *rps)
2195
828
{
2196
828
  const struct riscv_implicit_subset *t = riscv_implicit_subsets;
2197
91.9k
  for (; t->ext; t++)
2198
91.0k
    {
2199
91.0k
      riscv_subset_t *subset = NULL;
2200
91.0k
      if (riscv_lookup_subset (rps->subset_list, t->ext, &subset)
2201
7.45k
  && t->check_func (rps, subset))
2202
5.79k
      riscv_update_subset1 (rps, subset, t->implicit_exts);
2203
91.0k
    }
2204
828
}
2205
2206
/* Check extensions conflicts.  */
2207
2208
static bool
2209
riscv_parse_check_conflicts (riscv_parse_subset_t *rps)
2210
828
{
2211
828
  riscv_subset_t *subset = NULL;
2212
828
  int xlen = *rps->xlen;
2213
828
  bool no_conflict = true;
2214
2215
828
  if (riscv_subset_supports (rps, "e")
2216
0
      && riscv_subset_supports (rps, "h"))
2217
0
    {
2218
0
      rps->error_handler
2219
0
  (_("rv%de does not support the `h' extension"), xlen);
2220
0
      no_conflict = false;
2221
0
    }
2222
828
  if (riscv_lookup_subset (rps->subset_list, "q", &subset)
2223
0
      && (subset->major_version < 2 || (subset->major_version == 2
2224
0
          && subset->minor_version < 2))
2225
0
      && xlen < 64)
2226
0
    {
2227
0
      rps->error_handler (_("rv%d does not support the `q' extension"), xlen);
2228
0
      no_conflict = false;
2229
0
    }
2230
828
  if (riscv_subset_supports (rps, "zcmp")
2231
0
      && riscv_subset_supports (rps, "zcd"))
2232
0
    {
2233
0
      rps->error_handler
2234
0
  (_("zcmp' is incompatible with `d' and `c', or `zcd' extension"));
2235
0
      no_conflict = false;
2236
0
    }
2237
828
  if (riscv_lookup_subset (rps->subset_list, "zcf", &subset)
2238
0
      && xlen > 32)
2239
0
    {
2240
0
      rps->error_handler
2241
0
  (_("rv%d does not support the `zcf' extension"), xlen);
2242
0
      no_conflict = false;
2243
0
    }
2244
828
  if (riscv_lookup_subset (rps->subset_list, "zfinx", &subset)
2245
0
      && riscv_lookup_subset (rps->subset_list, "f", &subset))
2246
0
    {
2247
0
      rps->error_handler
2248
0
  (_("`zfinx' is conflict with the `f/d/q/zfh/zfhmin' extension"));
2249
0
      no_conflict = false;
2250
0
    }
2251
828
  if (riscv_lookup_subset (rps->subset_list, "xtheadvector", &subset)
2252
0
      && riscv_lookup_subset (rps->subset_list, "zve32x", &subset))
2253
0
    {
2254
0
      rps->error_handler
2255
0
  (_("`xtheadvector' is conflict with the `v/zve32x' extension"));
2256
0
      no_conflict = false;
2257
0
    }
2258
828
  if (riscv_lookup_subset (rps->subset_list, "zclsd", &subset)
2259
0
      && ((riscv_lookup_subset (rps->subset_list, "c", &subset)
2260
0
     && riscv_lookup_subset (rps->subset_list, "f", &subset))
2261
0
    || riscv_lookup_subset (rps->subset_list, "zcf", &subset)))
2262
0
    {
2263
0
      rps->error_handler
2264
0
  (_("`zclsd' is conflict with the `c+f'/ `zcf' extension"));
2265
0
      no_conflict = false;
2266
0
    }
2267
828
  if (riscv_lookup_subset (rps->subset_list, "ssnpm", &subset) && xlen != 64)
2268
0
    {
2269
0
      rps->error_handler (_ ("rv%d does not support the `ssnpm' extension"),
2270
0
        xlen);
2271
0
      no_conflict = false;
2272
0
    }
2273
828
  if (riscv_lookup_subset (rps->subset_list, "smnpm", &subset) && xlen != 64)
2274
0
    {
2275
0
      rps->error_handler (_ ("rv%d does not support the `smnpm' extension"),
2276
0
        xlen);
2277
0
      no_conflict = false;
2278
0
    }
2279
828
  if (riscv_lookup_subset (rps->subset_list, "smmpm", &subset) && xlen != 64)
2280
0
    {
2281
0
      rps->error_handler (_ ("rv%d does not support the `smmpm' extension"),
2282
0
        xlen);
2283
0
      no_conflict = false;
2284
0
    }
2285
828
  if (riscv_lookup_subset (rps->subset_list, "sspm", &subset) && xlen != 64)
2286
0
    {
2287
0
      rps->error_handler (_ ("rv%d does not support the `sspm' extension"),
2288
0
        xlen);
2289
0
      no_conflict = false;
2290
0
    }
2291
828
  if (riscv_lookup_subset (rps->subset_list, "supm", &subset) && xlen != 64)
2292
0
    {
2293
0
      rps->error_handler (_ ("rv%d does not support the `supm' extension"),
2294
0
        xlen);
2295
0
      no_conflict = false;
2296
0
    }
2297
2298
828
  bool support_zve = false;
2299
828
  bool support_zvl = false;
2300
828
  riscv_subset_t *s = rps->subset_list->head;
2301
12.4k
  for (; s != NULL; s = s->next)
2302
11.5k
    {
2303
11.5k
      if (!support_zve
2304
11.5k
    && strncmp (s->name, "zve", 3) == 0)
2305
0
  support_zve = true;
2306
11.5k
      if (!support_zvl
2307
11.5k
    && strncmp (s->name, "zvl", 3) == 0)
2308
0
  support_zvl = true;
2309
11.5k
      if (support_zve && support_zvl)
2310
0
  break;
2311
11.5k
    }
2312
828
  if (support_zvl && !support_zve)
2313
0
    {
2314
0
      rps->error_handler
2315
0
  (_("zvl*b extensions need to enable either `v' or `zve' extension"));
2316
0
      no_conflict = false;
2317
0
    }
2318
2319
828
  return no_conflict;
2320
828
}
2321
2322
/* Set the default subset list according to the default_enable field
2323
   of riscv_supported_*ext tables.  */
2324
2325
static void
2326
riscv_set_default_arch (riscv_parse_subset_t *rps)
2327
0
{
2328
0
  unsigned long enable = EXT_DEFAULT;
2329
0
  int i, j;
2330
0
  for (i = 0; riscv_all_supported_ext[i] != NULL; i++)
2331
0
    {
2332
0
      const struct riscv_supported_ext *table = riscv_all_supported_ext[i];
2333
0
      for (j = 0; table[j].name != NULL; j++)
2334
0
  {
2335
0
    bool implicit = false;
2336
0
    if (strcmp (table[j].name, "g") == 0)
2337
0
      implicit = true;
2338
0
    if (table[j].default_enable & enable)
2339
0
      riscv_parse_add_subset (rps, table[j].name,
2340
0
            RISCV_UNKNOWN_VERSION,
2341
0
            RISCV_UNKNOWN_VERSION, implicit);
2342
0
  }
2343
0
    }
2344
0
}
2345
2346
static bool
2347
riscv_find_profiles (riscv_parse_subset_t *rps, const char **pp)
2348
828
{
2349
828
  const char *p = *pp;
2350
2351
  /* Checking if input string contains a Profiles.
2352
     There are two cases use Profiles in -march option:
2353
2354
      1. Only use Profiles in '-march' as input
2355
      2. Mixed Profiles with other extensions
2356
2357
      Use '_' to split Profiles and other extensions.  */
2358
2359
7.45k
  for (int i = 0; riscv_profiles_table[i].profile_name != NULL; ++i)
2360
6.62k
    {
2361
      /* Find profile at the begin.  */
2362
6.62k
      if (startswith (p, riscv_profiles_table[i].profile_name))
2363
0
  {
2364
    /* Handle the profile string.  */
2365
0
    riscv_parse_subset (rps, riscv_profiles_table[i].profile_string);
2366
0
    p += strlen (riscv_profiles_table[i].profile_name);
2367
    /* Handle string after profiles if exists.  If missing underline
2368
       bewteen profile and other extensions, warn the user but not deal
2369
       as an error.  */
2370
0
    if (*p != '\0' && *p != '_')
2371
0
      _bfd_error_handler
2372
0
        (_("Warning: should use \"_\" to contact Profiles with other "
2373
0
     "extensions"));
2374
0
    *pp = p;
2375
0
    return true;
2376
0
  }
2377
6.62k
    }
2378
  /* Not found profile, return directly.  */
2379
828
  return false;
2380
828
}
2381
2382
/* Function for parsing ISA string.
2383
2384
   Return Value:
2385
     Return TRUE on success.
2386
2387
   Arguments:
2388
     `rps`: Hooks and status for parsing extensions.
2389
     `arch`: Full ISA string.  */
2390
2391
bool
2392
riscv_parse_subset (riscv_parse_subset_t *rps,
2393
        const char *arch)
2394
828
{
2395
828
  const char *p;
2396
2397
  /* Init the riscv_ext_order array to compare the order of extensions
2398
     quickly.  */
2399
828
  riscv_init_ext_order ();
2400
2401
828
  if (arch == NULL)
2402
0
    {
2403
0
      riscv_set_default_arch (rps);
2404
0
      riscv_parse_add_implicit_subsets (rps);
2405
0
      return riscv_parse_check_conflicts (rps);
2406
0
    }
2407
2408
5.79k
  for (p = arch; *p != '\0'; p++)
2409
4.96k
    {
2410
4.96k
      if (ISUPPER (*p))
2411
0
  {
2412
0
    rps->error_handler
2413
0
      (_("%s: ISA string cannot contain uppercase letters"),
2414
0
       arch);
2415
0
    return false;
2416
0
  }
2417
4.96k
    }
2418
2419
828
  bool profile = false;
2420
828
  p = arch;
2421
828
  if (riscv_find_profiles (rps, &p))
2422
0
    {
2423
      /* Check if using Profiles.  */
2424
0
      profile = true;
2425
0
    }
2426
828
  else if (startswith (p, "rv32"))
2427
0
    {
2428
0
      *rps->xlen = 32;
2429
0
      p += 4;
2430
0
    }
2431
828
  else if (startswith (p, "rv64"))
2432
828
    {
2433
828
      *rps->xlen = 64;
2434
828
      p += 4;
2435
828
    }
2436
0
  else
2437
0
    {
2438
      /* ISA string shouldn't be NULL or empty here.  For linker,
2439
   it might be empty when we failed to merge the ISA string
2440
   in the riscv_merge_attributes.  For assembler, we might
2441
   give an empty string by .attribute arch, "" or -march=.
2442
   However, We have already issued the correct error message
2443
   in another side, so do not issue this error when the ISA
2444
   string is empty.  */
2445
0
      if (strlen (arch))
2446
0
  rps->error_handler (
2447
0
    _("%s: ISA string must begin with rv32, rv64 or Profiles"),
2448
0
    arch);
2449
0
      return false;
2450
0
    }
2451
2452
  /* Parse single standard and prefixed extensions.  */
2453
828
  if (riscv_parse_extensions (rps, arch, p, profile) == NULL)
2454
0
    return false;
2455
2456
  /* Finally add implicit extensions according to the current
2457
     extensions.  */
2458
828
  riscv_parse_add_implicit_subsets (rps);
2459
2460
  /* Check the conflicts.  */
2461
828
  return riscv_parse_check_conflicts (rps);
2462
828
}
2463
2464
/* Return the number of digits for the input.  */
2465
2466
size_t
2467
riscv_estimate_digit (unsigned num)
2468
23.1k
{
2469
23.1k
  size_t digit = 0;
2470
23.1k
  if (num == 0)
2471
7.45k
    return 1;
2472
2473
46.3k
  for (digit = 0; num ; num /= 10)
2474
30.6k
    digit++;
2475
2476
15.7k
  return digit;
2477
23.1k
}
2478
2479
/* Auxiliary function to estimate string length of subset list.  */
2480
2481
static size_t
2482
riscv_estimate_arch_strlen1 (const riscv_subset_t *subset)
2483
12.4k
{
2484
12.4k
  if (subset == NULL)
2485
828
    return 6; /* For rv32/rv64/rv128 and string terminator.  */
2486
2487
11.5k
  return riscv_estimate_arch_strlen1 (subset->next)
2488
11.5k
   + strlen (subset->name)
2489
11.5k
   + riscv_estimate_digit (subset->major_version)
2490
11.5k
   + 1 /* For version seperator 'p'.  */
2491
11.5k
   + riscv_estimate_digit (subset->minor_version)
2492
11.5k
   + 1 /* For underscore.  */;
2493
12.4k
}
2494
2495
/* Estimate the string length of this subset list.  */
2496
2497
static size_t
2498
riscv_estimate_arch_strlen (const riscv_subset_list_t *subset_list)
2499
828
{
2500
828
  return riscv_estimate_arch_strlen1 (subset_list->head);
2501
828
}
2502
2503
/* Auxiliary function to convert subset info to string.  */
2504
2505
static void
2506
riscv_arch_str1 (riscv_subset_t *subset,
2507
     char *attr_str, char *buf, size_t bufsz)
2508
11.5k
{
2509
11.5k
  const char *underline = "_";
2510
11.5k
  riscv_subset_t *subset_t = subset;
2511
2512
11.5k
  if (subset_t == NULL)
2513
828
    return;
2514
2515
  /* No underline between rvXX and i/e.  */
2516
10.7k
  if ((strcasecmp (subset_t->name, "i") == 0)
2517
9.93k
      || (strcasecmp (subset_t->name, "e") == 0))
2518
828
    underline = "";
2519
2520
10.7k
  snprintf (buf, bufsz, "%s%s%dp%d",
2521
10.7k
      underline,
2522
10.7k
      subset_t->name,
2523
10.7k
      subset_t->major_version,
2524
10.7k
      subset_t->minor_version);
2525
2526
10.7k
  strncat (attr_str, buf, bufsz);
2527
2528
  /* Skip 'i' extension after 'e', or skip extensions which
2529
     versions are unknown.  */
2530
11.5k
  while (subset_t->next
2531
10.7k
   && ((strcmp (subset_t->name, "e") == 0
2532
0
        && strcmp (subset_t->next->name, "i") == 0)
2533
10.7k
       || subset_t->next->major_version == RISCV_UNKNOWN_VERSION
2534
9.93k
       || subset_t->next->minor_version == RISCV_UNKNOWN_VERSION))
2535
828
    subset_t = subset_t->next;
2536
2537
10.7k
  riscv_arch_str1 (subset_t->next, attr_str, buf, bufsz);
2538
10.7k
}
2539
2540
/* Convert subset information into string with explicit versions.  */
2541
2542
char *
2543
riscv_arch_str (unsigned xlen, riscv_subset_list_t *subset, bool update)
2544
828
{
2545
828
  size_t arch_str_len = riscv_estimate_arch_strlen (subset);
2546
828
  char *attr_str = xmalloc (arch_str_len);
2547
828
  char *buf = xmalloc (arch_str_len);
2548
2549
828
  snprintf (attr_str, arch_str_len, "rv%u", xlen);
2550
2551
828
  riscv_arch_str1 (subset->head, attr_str, buf, arch_str_len);
2552
828
  free (buf);
2553
2554
828
  if (update)
2555
828
    {
2556
828
      if (subset->arch_str != NULL)
2557
0
  free ((void *) subset->arch_str);
2558
828
      subset->arch_str = attr_str;
2559
828
    }
2560
2561
828
  return attr_str;
2562
828
}
2563
2564
/* Copy the subset in the subset list.  */
2565
2566
static struct riscv_subset_t *
2567
riscv_copy_subset (riscv_subset_list_t *subset_list,
2568
       riscv_subset_t *subset)
2569
0
{
2570
0
  if (subset == NULL)
2571
0
    return NULL;
2572
2573
0
  riscv_subset_t *new = xmalloc (sizeof *new);
2574
0
  new->name = xstrdup (subset->name);
2575
0
  new->major_version = subset->major_version;
2576
0
  new->minor_version = subset->minor_version;
2577
0
  new->next = riscv_copy_subset (subset_list, subset->next);
2578
2579
0
  if (subset->next == NULL)
2580
0
    subset_list->tail = new;
2581
2582
0
  return new;
2583
0
}
2584
2585
/* Copy the subset list.  */
2586
2587
riscv_subset_list_t *
2588
riscv_copy_subset_list (riscv_subset_list_t *subset_list)
2589
0
{
2590
0
  riscv_subset_list_t *new = xmalloc (sizeof *new);
2591
0
  new->head = riscv_copy_subset (new, subset_list->head);
2592
0
  new->arch_str = strdup (subset_list->arch_str);
2593
0
  return new;
2594
0
}
2595
2596
/* Remove the SUBSET from the subset list.  */
2597
2598
static void
2599
riscv_remove_subset (riscv_subset_list_t *subset_list,
2600
         const char *subset)
2601
0
{
2602
0
  riscv_subset_t *current = subset_list->head;
2603
0
  riscv_subset_t *pre = NULL;
2604
0
  for (; current != NULL; pre = current, current = current->next)
2605
0
    {
2606
0
      if (strcmp (current->name, subset) == 0)
2607
0
  {
2608
0
    if (pre == NULL)
2609
0
      subset_list->head = current->next;
2610
0
    else
2611
0
      pre->next = current->next;
2612
0
    if (current->next == NULL)
2613
0
      subset_list->tail = pre;
2614
0
    free ((void *) current->name);
2615
0
    free (current);
2616
0
    break;
2617
0
  }
2618
0
    }
2619
0
}
2620
2621
/* Auxiliary to add/remove extensions to/from the subset list.
2622
   This is called from riscv_update_subset or riscv_parse_add_implicit_subsets.
2623
2624
   The EXPLICIT_SUBSET, the corresponding explicit extension.  It is NULL means
2625
   called from riscv_update_subset./
2626
2627
   The IMPLICIT_EXTS, +extension[version] [,...,+extension_n[version_n]]
2628
          (Deprecated) -extension [,...,-extension_n],
2629
          full ISA.  */
2630
2631
static bool
2632
riscv_update_subset1 (riscv_parse_subset_t *rps,
2633
          riscv_subset_t *explicit_subset,
2634
          const char *implicit_exts)
2635
5.79k
{
2636
5.79k
  const char *p = implicit_exts;
2637
5.79k
  const char *errmsg_internal = explicit_subset == NULL ? "" : _("internal: ");
2638
5.79k
  const char *errmsg_caller = explicit_subset == NULL
2639
5.79k
            ? ".option arch" : "riscv_implicit_subsets";
2640
2641
5.79k
  do
2642
11.5k
    {
2643
11.5k
      int major_version = RISCV_UNKNOWN_VERSION;
2644
11.5k
      int minor_version = RISCV_UNKNOWN_VERSION;
2645
2646
11.5k
      bool removed = false;
2647
11.5k
      switch (*p)
2648
11.5k
  {
2649
11.5k
  case '+': removed = false; break;
2650
0
  case '-': removed = true; break;
2651
0
  default:
2652
0
    riscv_release_subset_list (rps->subset_list);
2653
0
    return riscv_parse_subset (rps, p);
2654
11.5k
  }
2655
11.5k
      ++p;
2656
2657
11.5k
      char *subset = xstrdup (p);
2658
11.5k
      char *q = subset;
2659
11.5k
      const char *end_of_version;
2660
      /* Extract the whole prefixed extension by ','.  */
2661
49.6k
      while (*q != '\0' && *q != ',')
2662
38.0k
        q++;
2663
2664
      /* Look forward to the first letter which is not <major>p<minor>.  */
2665
11.5k
      bool find_any_version = false;
2666
11.5k
      bool find_minor_version = false;
2667
11.5k
      size_t len = q - subset;
2668
11.5k
      size_t i;
2669
11.5k
      for (i = len; i > 0; i--)
2670
11.5k
        {
2671
11.5k
    q--;
2672
11.5k
    if (ISDIGIT (*q))
2673
0
      find_any_version = true;
2674
11.5k
    else if (find_any_version
2675
0
       && !find_minor_version
2676
0
       && *q == 'p'
2677
0
       && ISDIGIT (*(q - 1)))
2678
0
      find_minor_version = true;
2679
11.5k
    else
2680
11.5k
      break;
2681
11.5k
  }
2682
11.5k
      if (len > 0)
2683
11.5k
  q++;
2684
2685
      /* Check if the end of extension is 'p' or not.  If yes, then
2686
   the second letter from the end cannot be number.  */
2687
11.5k
      if (len > 1 && *(q - 1) == 'p' && ISDIGIT (*(q - 2)))
2688
0
  {
2689
0
    *q = '\0';
2690
0
    rps->error_handler
2691
0
      (_("%sinvalid ISA extension ends with <number>p in %s `%s'"),
2692
0
         errmsg_internal, errmsg_caller, implicit_exts);
2693
0
    free (subset);
2694
0
    return false;
2695
0
  }
2696
2697
11.5k
      end_of_version =
2698
11.5k
  riscv_parsing_subset_version (q, &major_version, &minor_version);
2699
11.5k
      *q = '\0';
2700
11.5k
      if (end_of_version == NULL)
2701
0
  {
2702
0
    free (subset);
2703
0
    return false;
2704
0
  }
2705
2706
11.5k
      if (strlen (subset) == 0
2707
11.5k
    || (strlen (subset) == 1
2708
4.96k
        && riscv_ext_order[(*subset - 'a')] == 0)
2709
11.5k
    || (strlen (subset) > 1
2710
6.62k
        && rps->check_unknown_prefixed_ext
2711
0
        && !riscv_recognized_prefixed_ext (subset)))
2712
0
  {
2713
0
    rps->error_handler
2714
0
      (_("%sunknown ISA extension `%s' in %s `%s'"),
2715
0
       errmsg_internal, subset, errmsg_caller, implicit_exts);
2716
0
    free (subset);
2717
0
    return false;
2718
0
  }
2719
2720
11.5k
      if (explicit_subset == NULL)
2721
0
  {
2722
0
    if (removed)
2723
0
      {
2724
0
        rps->error_handler
2725
0
    (_("%sdeprecated - extension `%s' in %s `%s'"),
2726
0
       errmsg_internal, subset, errmsg_caller, implicit_exts);
2727
0
        free (subset);
2728
0
        return false;
2729
0
      }
2730
0
    else if (strcmp (subset, "i") == 0
2731
0
       || strcmp (subset, "e") == 0
2732
0
       || strcmp (subset, "g") == 0)
2733
0
      {
2734
0
        rps->error_handler
2735
0
    (_("%scannot + base extension `%s' in %s `%s'"),
2736
0
       errmsg_internal, subset, errmsg_caller, implicit_exts);
2737
0
        free (subset);
2738
0
        return false;
2739
0
      }
2740
0
  }
2741
2742
11.5k
      if (removed)
2743
0
  riscv_remove_subset (rps->subset_list, subset);
2744
11.5k
      else
2745
11.5k
  {
2746
11.5k
    riscv_subset_t *isubset = NULL;
2747
11.5k
    if (!riscv_lookup_subset (rps->subset_list, subset, &isubset))
2748
9.93k
      riscv_parse_add_subset (rps, subset, major_version, minor_version,
2749
9.93k
            true/* implicit */);
2750
11.5k
  }
2751
11.5k
      p += end_of_version - subset;
2752
11.5k
      free (subset);
2753
11.5k
    }
2754
11.5k
  while (*p++ == ',');
2755
2756
5.79k
  bool no_conflict = true;
2757
5.79k
  if (explicit_subset == NULL)
2758
0
    {
2759
0
      riscv_parse_add_implicit_subsets (rps);
2760
0
      no_conflict = riscv_parse_check_conflicts (rps);
2761
0
    }
2762
5.79k
  return no_conflict;
2763
5.79k
}
2764
2765
/* Add an extension to/from the subset list.  This is used for the .option rvc
2766
   and .option arch directives.  */
2767
2768
bool
2769
riscv_update_subset (riscv_parse_subset_t *rps,
2770
         const char *str)
2771
0
{
2772
0
  return riscv_update_subset1 (rps, NULL, str);
2773
0
}
2774
2775
/* Called from .option norvc directives.  */
2776
2777
bool
2778
riscv_update_subset_norvc (riscv_parse_subset_t *rps)
2779
0
{
2780
0
  return riscv_update_subset1 (rps, rps->subset_list->head,
2781
0
             "-c,-zca,-zcd,-zcf,-zcb,-zce,-zcmp,-zcmt,"
2782
0
             "-zcmop,-zclsd");
2783
0
}
2784
2785
/* Check if the FEATURE subset is supported or not in the subset list.
2786
   Return true if it is supported; Otherwise, return false.  */
2787
2788
bool
2789
riscv_subset_supports (riscv_parse_subset_t *rps,
2790
           const char *feature)
2791
1.63M
{
2792
1.63M
  struct riscv_subset_t *subset;
2793
1.63M
  return riscv_lookup_subset (rps->subset_list, feature, &subset);
2794
1.63M
}
2795
2796
/* Each instuction is belonged to an instruction class INSN_CLASS_*.
2797
   Call riscv_subset_supports to make sure if the instuction is valid.  */
2798
2799
bool
2800
riscv_multi_subset_supports (riscv_parse_subset_t *rps,
2801
           enum riscv_insn_class insn_class)
2802
760k
{
2803
760k
  switch (insn_class)
2804
760k
    {
2805
33.6k
    case INSN_CLASS_I:
2806
33.6k
      return riscv_subset_supports (rps, "i");
2807
54
    case INSN_CLASS_ZICBOM:
2808
54
      return riscv_subset_supports (rps, "zicbom");
2809
20
    case INSN_CLASS_ZICBOP:
2810
20
      return riscv_subset_supports (rps, "zicbop");
2811
102
    case INSN_CLASS_ZICBOZ:
2812
102
      return riscv_subset_supports (rps, "zicboz");
2813
26
    case INSN_CLASS_ZICOND:
2814
26
      return riscv_subset_supports (rps, "zicond");
2815
4.71k
    case INSN_CLASS_ZICSR:
2816
4.71k
      return riscv_subset_supports (rps, "zicsr");
2817
21
    case INSN_CLASS_ZIFENCEI:
2818
21
      return riscv_subset_supports (rps, "zifencei");
2819
21
    case INSN_CLASS_ZIHINTNTL:
2820
21
      return riscv_subset_supports (rps, "zihintntl");
2821
174
    case INSN_CLASS_ZIHINTNTL_AND_ZCA:
2822
174
      return riscv_subset_supports (rps, "zihintntl")
2823
0
       && riscv_subset_supports (rps, "zca");
2824
88
    case INSN_CLASS_ZIHINTPAUSE:
2825
88
      return riscv_subset_supports (rps, "zihintpause");
2826
186
    case INSN_CLASS_ZIMOP:
2827
186
      return riscv_subset_supports (rps, "zimop");
2828
60
    case INSN_CLASS_ZICFISS:
2829
60
      return riscv_subset_supports (rps, "zicfiss");
2830
52
    case INSN_CLASS_ZICFISS_AND_ZCMOP:
2831
52
      return riscv_subset_supports (rps, "zicfiss")
2832
0
       && riscv_subset_supports (rps, "zcmop");
2833
499
    case INSN_CLASS_ZICFILP:
2834
499
      return riscv_subset_supports (rps, "zicfilp");
2835
45
    case INSN_CLASS_M:
2836
45
      return riscv_subset_supports (rps, "m");
2837
110
    case INSN_CLASS_ZMMUL:
2838
110
      return riscv_subset_supports (rps, "zmmul");
2839
481
    case INSN_CLASS_ZAAMO:
2840
481
      return riscv_subset_supports (rps, "zaamo");
2841
418
    case INSN_CLASS_ZABHA:
2842
418
      return riscv_subset_supports (rps, "zabha");
2843
992
    case INSN_CLASS_ZACAS:
2844
992
      return riscv_subset_supports (rps, "zacas");
2845
135
    case INSN_CLASS_ZABHA_AND_ZACAS:
2846
135
      return (riscv_subset_supports (rps, "zabha")
2847
0
        && riscv_subset_supports (rps, "zacas"));
2848
123
    case INSN_CLASS_ZALRSC:
2849
123
      return riscv_subset_supports (rps, "zalrsc");
2850
17
    case INSN_CLASS_ZAWRS:
2851
17
      return riscv_subset_supports (rps, "zawrs");
2852
1.31k
    case INSN_CLASS_F:
2853
1.31k
      return riscv_subset_supports (rps, "f");
2854
337
    case INSN_CLASS_D:
2855
337
      return riscv_subset_supports (rps, "d");
2856
605
    case INSN_CLASS_Q:
2857
605
      return riscv_subset_supports (rps, "q");
2858
573k
    case INSN_CLASS_ZCA:
2859
573k
      return riscv_subset_supports (rps, "zca");
2860
0
    case INSN_CLASS_ZCF:
2861
0
      return riscv_subset_supports (rps, "zcf");
2862
77.3k
    case INSN_CLASS_ZCD:
2863
77.3k
      return riscv_subset_supports (rps, "zcd");
2864
4.28k
    case INSN_CLASS_F_INX:
2865
4.28k
      return (riscv_subset_supports (rps, "f")
2866
0
        || riscv_subset_supports (rps, "zfinx"));
2867
4.17k
    case INSN_CLASS_D_INX:
2868
4.17k
      return (riscv_subset_supports (rps, "d")
2869
0
        || riscv_subset_supports (rps, "zdinx"));
2870
4.19k
    case INSN_CLASS_Q_INX:
2871
4.19k
      return (riscv_subset_supports (rps, "q")
2872
4.19k
        || riscv_subset_supports (rps, "zqinx"));
2873
2.66k
    case INSN_CLASS_ZFH_INX:
2874
2.66k
      return (riscv_subset_supports (rps, "zfh")
2875
2.66k
        || riscv_subset_supports (rps, "zhinx"));
2876
528
    case INSN_CLASS_ZFHMIN:
2877
528
      return riscv_subset_supports (rps, "zfhmin");
2878
58
    case INSN_CLASS_ZFHMIN_INX:
2879
58
      return (riscv_subset_supports (rps, "zfhmin")
2880
58
        || riscv_subset_supports (rps, "zhinxmin"));
2881
0
    case INSN_CLASS_ZFHMIN_AND_D_INX:
2882
0
      return ((riscv_subset_supports (rps, "zfhmin")
2883
0
         && riscv_subset_supports (rps, "d"))
2884
0
        || (riscv_subset_supports (rps, "zhinxmin")
2885
0
      && riscv_subset_supports (rps, "zdinx")));
2886
29
    case INSN_CLASS_ZFHMIN_AND_Q_INX:
2887
29
      return ((riscv_subset_supports (rps, "zfhmin")
2888
0
         && riscv_subset_supports (rps, "q"))
2889
29
        || (riscv_subset_supports (rps, "zhinxmin")
2890
0
      && riscv_subset_supports (rps, "zqinx")));
2891
4
    case INSN_CLASS_ZFBFMIN:
2892
4
      return riscv_subset_supports (rps, "zfbfmin");
2893
37
    case INSN_CLASS_ZFA:
2894
37
      return riscv_subset_supports (rps, "zfa");
2895
134
    case INSN_CLASS_D_AND_ZFA:
2896
134
      return riscv_subset_supports (rps, "d")
2897
134
       && riscv_subset_supports (rps, "zfa");
2898
21
    case INSN_CLASS_Q_AND_ZFA:
2899
21
      return riscv_subset_supports (rps, "q")
2900
0
       && riscv_subset_supports (rps, "zfa");
2901
14
    case INSN_CLASS_ZFH_AND_ZFA:
2902
14
      return riscv_subset_supports (rps, "zfh")
2903
0
       && riscv_subset_supports (rps, "zfa");
2904
0
    case INSN_CLASS_ZFH_OR_ZVFH_AND_ZFA:
2905
0
      return (riscv_subset_supports (rps, "zfh")
2906
0
        || riscv_subset_supports (rps, "zvfh"))
2907
0
       && riscv_subset_supports (rps, "zfa");
2908
69
    case INSN_CLASS_ZBA:
2909
69
      return riscv_subset_supports (rps, "zba");
2910
44
    case INSN_CLASS_ZBB:
2911
44
      return riscv_subset_supports (rps, "zbb");
2912
8
    case INSN_CLASS_ZBC:
2913
8
      return riscv_subset_supports (rps, "zbc");
2914
73
    case INSN_CLASS_ZBS:
2915
73
      return riscv_subset_supports (rps, "zbs");
2916
88
    case INSN_CLASS_ZBKB:
2917
88
      return riscv_subset_supports (rps, "zbkb");
2918
0
    case INSN_CLASS_ZBKC:
2919
0
      return riscv_subset_supports (rps, "zbkc");
2920
28
    case INSN_CLASS_ZBKX:
2921
28
      return riscv_subset_supports (rps, "zbkx");
2922
161
    case INSN_CLASS_ZBB_OR_ZBKB:
2923
161
      return (riscv_subset_supports (rps, "zbb")
2924
161
        || riscv_subset_supports (rps, "zbkb"));
2925
20
    case INSN_CLASS_ZBC_OR_ZBKC:
2926
20
      return (riscv_subset_supports (rps, "zbc")
2927
20
        || riscv_subset_supports (rps, "zbkc"));
2928
92
    case INSN_CLASS_ZKND:
2929
92
      return riscv_subset_supports (rps, "zknd");
2930
40
    case INSN_CLASS_ZKNE:
2931
40
      return riscv_subset_supports (rps, "zkne");
2932
19
    case INSN_CLASS_ZKNH:
2933
19
      return riscv_subset_supports (rps, "zknh");
2934
26
    case INSN_CLASS_ZKND_OR_ZKNE:
2935
26
      return (riscv_subset_supports (rps, "zknd")
2936
26
        || riscv_subset_supports (rps, "zkne"));
2937
84
    case INSN_CLASS_ZKSED:
2938
84
      return riscv_subset_supports (rps, "zksed");
2939
20
    case INSN_CLASS_ZKSH:
2940
20
      return riscv_subset_supports (rps, "zksh");
2941
4.28k
    case INSN_CLASS_V:
2942
4.28k
      return (riscv_subset_supports (rps, "v")
2943
4.28k
        || riscv_subset_supports (rps, "zve64x")
2944
4.28k
        || riscv_subset_supports (rps, "zve32x"));
2945
896
    case INSN_CLASS_ZVEF:
2946
896
      return (riscv_subset_supports (rps, "v")
2947
896
        || riscv_subset_supports (rps, "zve64d")
2948
896
        || riscv_subset_supports (rps, "zve64f")
2949
896
        || riscv_subset_supports (rps, "zve32f"));
2950
83
    case INSN_CLASS_ZVBB:
2951
83
      return riscv_subset_supports (rps, "zvbb");
2952
38
    case INSN_CLASS_ZVBC:
2953
38
      return riscv_subset_supports (rps, "zvbc");
2954
8
    case INSN_CLASS_ZVFBFMIN:
2955
8
      return riscv_subset_supports (rps, "zvfbfmin");
2956
51
    case INSN_CLASS_ZVFBFWMA:
2957
51
      return riscv_subset_supports (rps, "zvfbfwma");
2958
116
    case INSN_CLASS_ZVKB:
2959
116
      return riscv_subset_supports (rps, "zvkb");
2960
18
    case INSN_CLASS_ZVKG:
2961
18
      return riscv_subset_supports (rps, "zvkg");
2962
14
    case INSN_CLASS_ZVKNED:
2963
14
      return riscv_subset_supports (rps, "zvkned");
2964
37
    case INSN_CLASS_ZVKNHA_OR_ZVKNHB:
2965
37
      return (riscv_subset_supports (rps, "zvknha")
2966
37
        || riscv_subset_supports (rps, "zvknhb"));
2967
52
    case INSN_CLASS_ZVKSED:
2968
52
      return riscv_subset_supports (rps, "zvksed");
2969
19
    case INSN_CLASS_ZVKSH:
2970
19
      return riscv_subset_supports (rps, "zvksh");
2971
19.4k
    case INSN_CLASS_ZCB:
2972
19.4k
      return riscv_subset_supports (rps, "zcb");
2973
424
    case INSN_CLASS_ZCB_AND_ZBB:
2974
424
      return (riscv_subset_supports (rps, "zcb")
2975
0
        && riscv_subset_supports (rps, "zbb"));
2976
12
    case INSN_CLASS_ZCB_AND_ZBA:
2977
12
      return (riscv_subset_supports (rps, "zcb")
2978
0
        && riscv_subset_supports (rps, "zba"));
2979
988
    case INSN_CLASS_ZCB_AND_ZMMUL:
2980
988
      return (riscv_subset_supports (rps, "zcb")
2981
0
        && riscv_subset_supports (rps, "zmmul"));
2982
69
    case INSN_CLASS_ZCMOP:
2983
69
      return riscv_subset_supports (rps, "zcmop");
2984
0
    case INSN_CLASS_ZCMP:
2985
0
      return riscv_subset_supports (rps, "zcmp");
2986
0
    case INSN_CLASS_ZCMT:
2987
0
      return riscv_subset_supports (rps, "zcmt");
2988
0
    case INSN_CLASS_SMCTR_OR_SSCTR:
2989
0
      return (riscv_subset_supports (rps, "smctr")
2990
0
        || riscv_subset_supports (rps, "ssctr"));
2991
0
    case INSN_CLASS_ZILSD:
2992
0
      return riscv_subset_supports (rps, "zilsd");
2993
0
    case INSN_CLASS_ZCLSD:
2994
0
      return riscv_subset_supports (rps, "zclsd");
2995
0
    case INSN_CLASS_SMRNMI:
2996
0
      return riscv_subset_supports (rps, "smrnmi");
2997
24
    case INSN_CLASS_SVINVAL:
2998
24
      return riscv_subset_supports (rps, "svinval");
2999
132
    case INSN_CLASS_H:
3000
132
      return riscv_subset_supports (rps, "h");
3001
440
    case INSN_CLASS_XCVALU:
3002
440
      return riscv_subset_supports (rps, "xcvalu");
3003
1.12k
    case INSN_CLASS_XCVBI:
3004
1.12k
      return riscv_subset_supports (rps, "xcvbi");
3005
620
    case INSN_CLASS_XCVBITMANIP:
3006
620
      return riscv_subset_supports (rps, "xcvbitmanip");
3007
390
    case INSN_CLASS_XCVELW:
3008
390
      return riscv_subset_supports (rps, "xcvelw");
3009
2.39k
    case INSN_CLASS_XCVMAC:
3010
2.39k
      return riscv_subset_supports (rps, "xcvmac");
3011
6.09k
    case INSN_CLASS_XCVMEM:
3012
6.09k
      return riscv_subset_supports (rps, "xcvmem");
3013
1.27k
    case INSN_CLASS_XCVSIMD:
3014
1.27k
      return riscv_subset_supports (rps, "xcvsimd");
3015
440
    case INSN_CLASS_XTHEADBA:
3016
440
      return riscv_subset_supports (rps, "xtheadba");
3017
357
    case INSN_CLASS_XTHEADBB:
3018
357
      return riscv_subset_supports (rps, "xtheadbb");
3019
25
    case INSN_CLASS_XTHEADBS:
3020
25
      return riscv_subset_supports (rps, "xtheadbs");
3021
352
    case INSN_CLASS_XTHEADCMO:
3022
352
      return riscv_subset_supports (rps, "xtheadcmo");
3023
377
    case INSN_CLASS_XTHEADCONDMOV:
3024
377
      return riscv_subset_supports (rps, "xtheadcondmov");
3025
222
    case INSN_CLASS_XTHEADFMEMIDX:
3026
222
      return riscv_subset_supports (rps, "xtheadfmemidx");
3027
0
    case INSN_CLASS_XTHEADFMV:
3028
0
      return riscv_subset_supports (rps, "xtheadfmv");
3029
33
    case INSN_CLASS_XTHEADINT:
3030
33
      return riscv_subset_supports (rps, "xtheadint");
3031
54
    case INSN_CLASS_XTHEADMAC:
3032
54
      return riscv_subset_supports (rps, "xtheadmac");
3033
584
    case INSN_CLASS_XTHEADMEMIDX:
3034
584
      return riscv_subset_supports (rps, "xtheadmemidx");
3035
198
    case INSN_CLASS_XTHEADMEMPAIR:
3036
198
      return riscv_subset_supports (rps, "xtheadmempair");
3037
31
    case INSN_CLASS_XTHEADSYNC:
3038
31
      return riscv_subset_supports (rps, "xtheadsync");
3039
3.76k
    case INSN_CLASS_XTHEADVECTOR:
3040
3.76k
      return riscv_subset_supports (rps, "xtheadvector");
3041
63
    case INSN_CLASS_XTHEADVDOT:
3042
63
      return riscv_subset_supports (rps, "xtheadvdot");
3043
269
    case INSN_CLASS_XTHEADZVAMO:
3044
269
      return riscv_subset_supports (rps, "xtheadzvamo");
3045
279
    case INSN_CLASS_XVENTANACONDOPS:
3046
279
      return riscv_subset_supports (rps, "xventanacondops");
3047
294
    case INSN_CLASS_XSFVCP:
3048
294
      return riscv_subset_supports (rps, "xsfvcp");
3049
0
    case INSN_CLASS_XSFCEASE:
3050
0
      return riscv_subset_supports (rps, "xsfcease");
3051
16
    case INSN_CLASS_XSFVQMACCQOQ:
3052
16
      return riscv_subset_supports (rps, "xsfvqmaccqoq");
3053
112
    case INSN_CLASS_XSFVQMACCDOD:
3054
112
      return riscv_subset_supports (rps, "xsfvqmaccdod");
3055
42
    case INSN_CLASS_XSFVFNRCLIPXFQF:
3056
42
      return riscv_subset_supports (rps, "xsfvfnrclipxfqf");
3057
1.26k
    case INSN_CLASS_XMIPSCBOP:
3058
1.26k
      return riscv_subset_supports (rps, "xmipscbop");
3059
91
    case INSN_CLASS_XMIPSCMOV:
3060
91
      return riscv_subset_supports (rps, "xmipscmov");
3061
11
    case INSN_CLASS_XMIPSEXECTL:
3062
11
      return riscv_subset_supports (rps, "xmipsexectl");
3063
459
    case INSN_CLASS_XMIPSLSP:
3064
459
      return riscv_subset_supports (rps, "xmipslsp");
3065
0
    default:
3066
0
      rps->error_handler
3067
0
        (_("internal: unreachable INSN_CLASS_*"));
3068
0
      return false;
3069
760k
    }
3070
760k
}
3071
3072
/* Each instuction is belonged to an instruction class INSN_CLASS_*.
3073
   Call riscv_subset_supports_ext to determine the missing extension.  */
3074
3075
const char *
3076
riscv_multi_subset_supports_ext (riscv_parse_subset_t *rps,
3077
         enum riscv_insn_class insn_class)
3078
0
{
3079
0
  switch (insn_class)
3080
0
    {
3081
0
    case INSN_CLASS_I:
3082
0
      return "i";
3083
0
    case INSN_CLASS_ZICBOM:
3084
0
      return "zicbom";
3085
0
    case INSN_CLASS_ZICBOP:
3086
0
      return "zicbop";
3087
0
    case INSN_CLASS_ZICBOZ:
3088
0
      return "zicboz";
3089
0
    case INSN_CLASS_ZICOND:
3090
0
      return "zicond";
3091
0
    case INSN_CLASS_ZICSR:
3092
0
      return "zicsr";
3093
0
    case INSN_CLASS_ZIFENCEI:
3094
0
      return "zifencei";
3095
0
    case INSN_CLASS_ZICFISS:
3096
0
      return "zicfiss";
3097
0
    case INSN_CLASS_ZICFISS_AND_ZCMOP:
3098
0
      if (!riscv_subset_supports (rps, "zicfiss"))
3099
0
  {
3100
0
    if (!riscv_subset_supports (rps, "zcmop"))
3101
0
      return _("zicfiss' and `zcmop");
3102
0
    else
3103
0
      return "zicfiss";
3104
0
  }
3105
0
      return "zcmop";
3106
0
    case INSN_CLASS_ZICFILP:
3107
0
      return "zicfilp";
3108
0
    case INSN_CLASS_ZIHINTNTL:
3109
0
      return "zihintntl";
3110
0
    case INSN_CLASS_ZIHINTNTL_AND_ZCA:
3111
0
      if (!riscv_subset_supports (rps, "zihintntl"))
3112
0
  {
3113
0
    if (!riscv_subset_supports (rps, "zca"))
3114
0
      return _("zihintntl' and `c', or `zihintntl' and `zca");
3115
0
    else
3116
0
      return "zihintntl";
3117
0
  }
3118
0
      else
3119
0
  return _("c' or `zca");
3120
0
    case INSN_CLASS_ZIHINTPAUSE:
3121
0
      return "zihintpause";
3122
0
    case INSN_CLASS_ZIMOP:
3123
0
      return "zimop";
3124
0
    case INSN_CLASS_M:
3125
0
      return "m";
3126
0
    case INSN_CLASS_ZMMUL:
3127
0
      return _ ("m' or `zmmul");
3128
0
    case INSN_CLASS_ZAAMO:
3129
0
      return "zaamo";
3130
0
    case INSN_CLASS_ZABHA:
3131
0
      return "zabha";
3132
0
    case INSN_CLASS_ZACAS:
3133
0
      return "zacas";
3134
0
    case INSN_CLASS_ZABHA_AND_ZACAS:
3135
0
      if (!riscv_subset_supports (rps, "zabha"))
3136
0
  {
3137
0
    if (!riscv_subset_supports (rps, "zacas"))
3138
0
      return _ ("zabha' and `zacas");
3139
0
    else
3140
0
      return "zabha";
3141
0
  }
3142
0
      return "zacas";
3143
0
    case INSN_CLASS_ZALRSC:
3144
0
      return "zalrsc";
3145
0
    case INSN_CLASS_ZAWRS:
3146
0
      return "zawrs";
3147
0
    case INSN_CLASS_F:
3148
0
      return "f";
3149
0
    case INSN_CLASS_D:
3150
0
      return "d";
3151
0
    case INSN_CLASS_Q:
3152
0
      return "q";
3153
0
    case INSN_CLASS_ZCA:
3154
0
      return _("c' or `zca");
3155
0
    case INSN_CLASS_ZCF:
3156
0
      return _("f' and `c', or `zcf");
3157
0
    case INSN_CLASS_ZCD:
3158
0
      return _("d' and `c', or `zcd");
3159
0
    case INSN_CLASS_F_INX:
3160
0
      return _("f' or `zfinx");
3161
0
    case INSN_CLASS_D_INX:
3162
0
      return _("d' or `zdinx");
3163
0
    case INSN_CLASS_Q_INX:
3164
0
      return _("q' or `zqinx");
3165
0
    case INSN_CLASS_ZFH_INX:
3166
0
      return _("zfh' or `zhinx");
3167
0
    case INSN_CLASS_ZFHMIN:
3168
0
      return "zfhmin";
3169
0
    case INSN_CLASS_ZFHMIN_INX:
3170
0
      return _("zfhmin' or `zhinxmin");
3171
0
    case INSN_CLASS_ZFHMIN_AND_D_INX:
3172
0
      if (riscv_subset_supports (rps, "zfhmin"))
3173
0
  return "d";
3174
0
      else if (riscv_subset_supports (rps, "d"))
3175
0
  return "zfhmin";
3176
0
      else if (riscv_subset_supports (rps, "zhinxmin"))
3177
0
  return "zdinx";
3178
0
      else if (riscv_subset_supports (rps, "zdinx"))
3179
0
  return "zhinxmin";
3180
0
      else
3181
0
  return _("zfhmin' and `d', or `zhinxmin' and `zdinx");
3182
0
    case INSN_CLASS_ZFHMIN_AND_Q_INX:
3183
0
      if (riscv_subset_supports (rps, "zfhmin"))
3184
0
  return "q";
3185
0
      else if (riscv_subset_supports (rps, "q"))
3186
0
  return "zfhmin";
3187
0
      else if (riscv_subset_supports (rps, "zhinxmin"))
3188
0
  return "zqinx";
3189
0
      else if (riscv_subset_supports (rps, "zqinx"))
3190
0
  return "zhinxmin";
3191
0
      else
3192
0
  return _("zfhmin' and `q', or `zhinxmin' and `zqinx");
3193
0
    case INSN_CLASS_ZFBFMIN:
3194
0
      return "zfbfmin";
3195
0
    case INSN_CLASS_ZFA:
3196
0
      return "zfa";
3197
0
    case INSN_CLASS_D_AND_ZFA:
3198
0
      if (!riscv_subset_supports (rps, "d")
3199
0
    && !riscv_subset_supports (rps, "zfa"))
3200
0
  return _("d' and `zfa");
3201
0
      else if (!riscv_subset_supports (rps, "d"))
3202
0
  return "d";
3203
0
      else
3204
0
  return "zfa";
3205
0
    case INSN_CLASS_Q_AND_ZFA:
3206
0
      if (!riscv_subset_supports (rps, "q")
3207
0
    && !riscv_subset_supports (rps, "zfa"))
3208
0
  return _("q' and `zfa");
3209
0
      else if (!riscv_subset_supports (rps, "q"))
3210
0
  return "q";
3211
0
      else
3212
0
  return "zfa";
3213
0
    case INSN_CLASS_ZFH_AND_ZFA:
3214
0
      if (!riscv_subset_supports (rps, "zfh")
3215
0
    && !riscv_subset_supports (rps, "zfa"))
3216
0
  return _("zfh' and `zfa");
3217
0
      else if (!riscv_subset_supports (rps, "zfh"))
3218
0
  return "zfh";
3219
0
      else
3220
0
  return "zfa";
3221
0
    case INSN_CLASS_ZFH_OR_ZVFH_AND_ZFA:
3222
0
      if (!riscv_subset_supports (rps, "zfa"))
3223
0
  {
3224
0
    if (!riscv_subset_supports (rps, "zfh")
3225
0
        && !riscv_subset_supports (rps, "zvfh"))
3226
0
      return _("zfh' and `zfa', or `zvfh' and `zfa");
3227
0
    else
3228
0
      return "zfa";
3229
0
  }
3230
0
      else
3231
0
  return _("zfh' or `zvfh");
3232
0
    case INSN_CLASS_ZBA:
3233
0
      return "zba";
3234
0
    case INSN_CLASS_ZBB:
3235
0
      return "zbb";
3236
0
    case INSN_CLASS_ZBC:
3237
0
      return "zbc";
3238
0
    case INSN_CLASS_ZBS:
3239
0
      return "zbs";
3240
0
    case INSN_CLASS_ZBKB:
3241
0
      return "zbkb";
3242
0
    case INSN_CLASS_ZBKC:
3243
0
      return "zbkc";
3244
0
    case INSN_CLASS_ZBKX:
3245
0
      return "zbkx";
3246
0
    case INSN_CLASS_ZBB_OR_ZBKB:
3247
0
      return _("zbb' or `zbkb");
3248
0
    case INSN_CLASS_ZBC_OR_ZBKC:
3249
0
      return _("zbc' or `zbkc");
3250
0
    case INSN_CLASS_ZKND:
3251
0
      return "zknd";
3252
0
    case INSN_CLASS_ZKNE:
3253
0
      return "zkne";
3254
0
    case INSN_CLASS_ZKNH:
3255
0
      return "zknh";
3256
0
    case INSN_CLASS_ZKND_OR_ZKNE:
3257
0
      return _("zknd' or `zkne");
3258
0
    case INSN_CLASS_ZKSED:
3259
0
      return "zksed";
3260
0
    case INSN_CLASS_ZKSH:
3261
0
      return "zksh";
3262
0
    case INSN_CLASS_V:
3263
0
      return _("v' or `zve64x' or `zve32x");
3264
0
    case INSN_CLASS_ZVEF:
3265
0
      return _("v' or `zve64d' or `zve64f' or `zve32f");
3266
0
    case INSN_CLASS_ZVBB:
3267
0
      return _("zvbb");
3268
0
    case INSN_CLASS_ZVBC:
3269
0
      return _("zvbc");
3270
0
    case INSN_CLASS_ZVFBFMIN:
3271
0
      return "zvfbfmin";
3272
0
    case INSN_CLASS_ZVFBFWMA:
3273
0
      return "zvfbfwma";
3274
0
    case INSN_CLASS_ZVKB:
3275
0
      return _("zvkb");
3276
0
    case INSN_CLASS_ZVKG:
3277
0
      return _("zvkg");
3278
0
    case INSN_CLASS_ZVKNED:
3279
0
      return _("zvkned");
3280
0
    case INSN_CLASS_ZVKNHA_OR_ZVKNHB:
3281
0
      return _("zvknha' or `zvknhb");
3282
0
    case INSN_CLASS_ZVKSED:
3283
0
      return _("zvksed");
3284
0
    case INSN_CLASS_ZVKSH:
3285
0
      return _("zvksh");
3286
0
    case INSN_CLASS_ZCB:
3287
0
      return "zcb";
3288
0
    case INSN_CLASS_ZCB_AND_ZBA:
3289
0
      return _("zcb' and `zba");
3290
0
    case INSN_CLASS_ZCB_AND_ZBB:
3291
0
      return _("zcb' and `zbb");
3292
0
    case INSN_CLASS_ZCB_AND_ZMMUL:
3293
0
      return _("zcb' and `zmmul', or `zcb' and `m");
3294
0
    case INSN_CLASS_ZCMOP:
3295
0
      return "zcmop";
3296
0
    case INSN_CLASS_ZCMP:
3297
0
      return "zcmp";
3298
0
    case INSN_CLASS_ZCMT:
3299
0
      return "zcmt";
3300
0
    case INSN_CLASS_SMCTR_OR_SSCTR:
3301
0
      return _("smctr' or `ssctr");
3302
0
    case INSN_CLASS_ZILSD:
3303
0
     return "zilsd";
3304
0
    case INSN_CLASS_ZCLSD:
3305
0
      return "zclsd";
3306
0
    case INSN_CLASS_SMRNMI:
3307
0
      return "smrnmi";
3308
0
    case INSN_CLASS_SVINVAL:
3309
0
      return "svinval";
3310
0
    case INSN_CLASS_H:
3311
0
      return _("h");
3312
0
    case INSN_CLASS_XCVALU:
3313
0
      return "xcvalu";
3314
0
    case INSN_CLASS_XCVBI:
3315
0
      return "xcvbi";
3316
0
    case INSN_CLASS_XCVBITMANIP:
3317
0
      return "xcvbitmanip";
3318
0
    case INSN_CLASS_XCVELW:
3319
0
      return "xcvelw";
3320
0
    case INSN_CLASS_XCVMAC:
3321
0
      return "xcvmac";
3322
0
    case INSN_CLASS_XCVMEM:
3323
0
      return "xcvmem";
3324
0
    case INSN_CLASS_XCVSIMD:
3325
0
      return "xcvsimd";
3326
0
    case INSN_CLASS_XTHEADBA:
3327
0
      return "xtheadba";
3328
0
    case INSN_CLASS_XTHEADBB:
3329
0
      return "xtheadbb";
3330
0
    case INSN_CLASS_XTHEADBS:
3331
0
      return "xtheadbs";
3332
0
    case INSN_CLASS_XTHEADCMO:
3333
0
      return "xtheadcmo";
3334
0
    case INSN_CLASS_XTHEADCONDMOV:
3335
0
      return "xtheadcondmov";
3336
0
    case INSN_CLASS_XTHEADFMEMIDX:
3337
0
      return "xtheadfmemidx";
3338
0
    case INSN_CLASS_XTHEADFMV:
3339
0
      return "xtheadfmv";
3340
0
    case INSN_CLASS_XTHEADINT:
3341
0
      return "xtheadint";
3342
0
    case INSN_CLASS_XTHEADMAC:
3343
0
      return "xtheadmac";
3344
0
    case INSN_CLASS_XTHEADMEMIDX:
3345
0
      return "xtheadmemidx";
3346
0
    case INSN_CLASS_XTHEADMEMPAIR:
3347
0
      return "xtheadmempair";
3348
0
    case INSN_CLASS_XTHEADSYNC:
3349
0
      return "xtheadsync";
3350
0
    case INSN_CLASS_XTHEADVECTOR:
3351
0
      return "xtheadvector";
3352
0
    case INSN_CLASS_XTHEADVDOT:
3353
0
      return "xtheadvdot";
3354
0
    case INSN_CLASS_XTHEADZVAMO:
3355
0
      return "xtheadzvamo";
3356
0
    case INSN_CLASS_XVENTANACONDOPS:
3357
0
      return "xventanacondops";
3358
0
    case INSN_CLASS_XSFVCP:
3359
0
      return "xsfvcp";
3360
0
    case INSN_CLASS_XSFCEASE:
3361
0
      return "xsfcease";
3362
0
    case INSN_CLASS_XSFVQMACCQOQ:
3363
0
      return "xsfvqmaccqoq";
3364
0
    case INSN_CLASS_XSFVQMACCDOD:
3365
0
      return "xsfvqmaccdod";
3366
0
    case INSN_CLASS_XSFVFNRCLIPXFQF:
3367
0
      return "xsfvfnrclipxfqf";
3368
0
    default:
3369
0
      rps->error_handler
3370
0
        (_("internal: unreachable INSN_CLASS_*"));
3371
0
      return NULL;
3372
0
    }
3373
0
}
3374
3375
/* Print supported extensions with versions if -march=help.  */
3376
3377
void
3378
riscv_print_extensions (void)
3379
0
{
3380
  /* Record the previous printed extension.
3381
     Print the current one if they are not the same.  */
3382
0
  const struct riscv_supported_ext *cur = NULL, *prev = NULL;
3383
0
  int i, j;
3384
3385
0
  printf ("All available -march extensions for RISC-V:");
3386
3387
0
  for (i = 0; riscv_all_supported_ext[i] != NULL; i++)
3388
0
    {
3389
0
      const struct riscv_supported_ext *exts = riscv_all_supported_ext[i];
3390
0
      prev = NULL;
3391
0
      for (j = 0; exts[j].name != NULL; j++)
3392
0
  {
3393
0
    cur = &exts[j];
3394
    /* Unclear version information, skip.  */
3395
0
    if (cur->isa_spec_class == ISA_SPEC_CLASS_NONE
3396
0
        || cur->major_version == RISCV_UNKNOWN_VERSION
3397
0
        || cur->minor_version == RISCV_UNKNOWN_VERSION)
3398
0
      continue;
3399
3400
    /* Same extension.  */
3401
0
    if (prev && strcmp (prev->name, cur->name) == 0)
3402
0
      {
3403
        /* Same version, skip.  */
3404
0
        if (prev->major_version == cur->major_version
3405
0
      && prev->minor_version == cur->minor_version)
3406
0
    continue;
3407
        /* Different version, print version with comma.  */
3408
0
        else
3409
0
    printf (", %d.%d", cur->major_version, cur->minor_version);
3410
0
      }
3411
    /* Different extension, print extension and version with newline.  */
3412
0
    else
3413
0
      printf ("\n\t%-40s%d.%d", cur->name, cur->major_version,
3414
0
        cur->minor_version);
3415
0
    prev = &exts[j];
3416
0
  }
3417
0
    }
3418
0
  printf ("\n");
3419
0
}
3420
3421
/* Find the first input bfd with GNU property and merge it with GPROP.  If no
3422
   such input is found, add it to a new section at the last input.  Update
3423
   GPROP accordingly.  */
3424
3425
bfd *
3426
_bfd_riscv_elf_link_setup_gnu_properties (struct bfd_link_info *info,
3427
            uint32_t *and_prop_p)
3428
0
{
3429
0
  asection *sec;
3430
0
  bfd *pbfd;
3431
0
  bfd *ebfd = NULL;
3432
0
  elf_property *prop;
3433
3434
0
  uint32_t and_prop = *and_prop_p;
3435
3436
  /* Find a normal input file with GNU property note.  */
3437
0
  for (pbfd = info->input_bfds; pbfd != NULL; pbfd = pbfd->link.next)
3438
0
    if (bfd_get_flavour (pbfd) == bfd_target_elf_flavour
3439
0
  && bfd_count_sections (pbfd) != 0)
3440
0
      {
3441
0
  ebfd = pbfd;
3442
3443
0
  if (elf_properties (pbfd) != NULL)
3444
0
    break;
3445
0
      }
3446
3447
  /* If ebfd != NULL it is either an input with property note or the last
3448
     input.  Either way if we have and_prop, we should add it (by
3449
     creating a section if needed).  */
3450
0
  if (ebfd != NULL && (and_prop))
3451
0
    {
3452
0
      prop = _bfd_elf_get_property (ebfd, GNU_PROPERTY_RISCV_FEATURE_1_AND, 4);
3453
3454
0
      prop->u.number |= and_prop;
3455
0
      prop->pr_kind = property_number;
3456
3457
      /* pbfd being NULL implies ebfd is the last input.  Create the GNU
3458
   property note section.  */
3459
0
      if (pbfd == NULL)
3460
0
  {
3461
0
    sec
3462
0
      = bfd_make_section_with_flags (ebfd, NOTE_GNU_PROPERTY_SECTION_NAME,
3463
0
             (SEC_ALLOC | SEC_LOAD | SEC_IN_MEMORY
3464
0
              | SEC_READONLY | SEC_HAS_CONTENTS
3465
0
              | SEC_DATA));
3466
0
    if (sec == NULL)
3467
0
      info->callbacks->fatal (
3468
0
        _("%P: failed to create GNU property section\n"));
3469
3470
0
    elf_section_type (sec) = SHT_NOTE;
3471
0
  }
3472
0
    }
3473
3474
0
  pbfd = _bfd_elf_link_setup_gnu_properties (info);
3475
3476
0
  if (bfd_link_relocatable (info))
3477
0
    return pbfd;
3478
3479
  /* If pbfd has any GNU_PROPERTY_RISCV_FEATURE_1_AND properties, update
3480
  and_prop accordingly.  */
3481
0
  if (pbfd != NULL)
3482
0
    {
3483
0
      elf_property_list *p;
3484
0
      elf_property_list *plist = elf_properties (pbfd);
3485
3486
0
      if ((p = _bfd_elf_find_property (plist, GNU_PROPERTY_RISCV_FEATURE_1_AND,
3487
0
               NULL))
3488
0
    != NULL)
3489
0
  and_prop = p->property.u.number
3490
0
       & (GNU_PROPERTY_RISCV_FEATURE_1_CFI_LP_UNLABELED
3491
0
          | GNU_PROPERTY_RISCV_FEATURE_1_CFI_SS);
3492
0
    }
3493
3494
0
  *and_prop_p = and_prop;
3495
0
  return pbfd;
3496
0
}
3497
3498
/* Define elf_backend_parse_gnu_properties for RISC-V.  */
3499
3500
enum elf_property_kind
3501
_bfd_riscv_elf_parse_gnu_properties (bfd *abfd, unsigned int type,
3502
             bfd_byte *ptr, unsigned int datasz)
3503
1
{
3504
1
  elf_property *prop;
3505
3506
1
  switch (type)
3507
1
    {
3508
0
    case GNU_PROPERTY_RISCV_FEATURE_1_AND:
3509
0
      if (datasz != 4)
3510
0
  {
3511
0
    _bfd_error_handler (_ (
3512
0
        "error: %pB: <corrupt RISC-V used size: 0x%x>"),
3513
0
            abfd, datasz);
3514
0
    return property_corrupt;
3515
0
  }
3516
0
      prop = _bfd_elf_get_property (abfd, type, datasz);
3517
      /* Combine properties of the same type.  */
3518
0
      prop->u.number |= bfd_h_get_32 (abfd, ptr);
3519
0
      prop->pr_kind = property_number;
3520
0
      break;
3521
3522
1
    default:
3523
1
      return property_ignored;
3524
1
    }
3525
3526
0
  return property_number;
3527
1
}
3528
3529
/* Merge RISC-V GNU property BPROP with APROP also accounting for PROP.
3530
   If APROP isn't NULL, merge it with BPROP and/or PROP.  Vice-versa if BROP
3531
   isn't NULL.  Return TRUE if there is any update to APROP or if BPROP should
3532
   be merge with ABFD.  */
3533
3534
bool
3535
_bfd_riscv_elf_merge_gnu_properties
3536
  (struct bfd_link_info *info ATTRIBUTE_UNUSED, bfd *abfd ATTRIBUTE_UNUSED,
3537
   elf_property *aprop, elf_property *bprop, uint32_t and_prop)
3538
0
{
3539
0
  unsigned int orig_number;
3540
0
  bool updated = false;
3541
0
  unsigned int pr_type = aprop != NULL ? aprop->pr_type : bprop->pr_type;
3542
3543
0
  switch (pr_type)
3544
0
    {
3545
0
      case GNU_PROPERTY_RISCV_FEATURE_1_AND: {
3546
0
  if (aprop != NULL && bprop != NULL)
3547
0
    {
3548
0
      orig_number = aprop->u.number;
3549
0
      aprop->u.number = (orig_number & bprop->u.number) | and_prop;
3550
0
      updated = orig_number != aprop->u.number;
3551
      /* Remove the property if all feature bits are cleared.  */
3552
0
      if (aprop->u.number == 0)
3553
0
        aprop->pr_kind = property_remove;
3554
0
      break;
3555
0
    }
3556
  /* If either is NULL, the AND would be 0 so, if there is
3557
     any PROP, asign it to the input that is not NULL.  */
3558
0
  if (and_prop)
3559
0
    {
3560
0
      if (aprop != NULL)
3561
0
        {
3562
0
    orig_number = aprop->u.number;
3563
0
    aprop->u.number = and_prop;
3564
0
    updated = orig_number != aprop->u.number;
3565
0
        }
3566
0
      else if (bprop != NULL)
3567
0
        {
3568
0
    bprop->u.number = and_prop;
3569
0
    updated = true;
3570
0
        }
3571
      /* Shouldn't happen because we checked one of APROP or BPROP !=
3572
       * NULL. */
3573
0
      else
3574
0
        abort ();
3575
0
    }
3576
  /* No PROP and BPROP is NULL, so remove APROP.  */
3577
0
  else if (!and_prop && bprop == NULL && aprop != NULL)
3578
0
    {
3579
0
      aprop->pr_kind = property_remove;
3580
0
      updated = true;
3581
0
    }
3582
0
      }
3583
0
      break;
3584
3585
0
    default:
3586
0
      abort ();
3587
0
    }
3588
3589
0
  return updated;
3590
0
}