Coverage Report

Created: 2026-04-04 08:16

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
4.28k
{
1065
4.28k
  if (r_type < ARRAY_SIZE (howto_table))
1066
4.09k
    return &howto_table[r_type];
1067
193
  else if (r_type < R_RISCV_max + ARRAY_SIZE (howto_table_internal))
1068
1
    return &howto_table_internal[r_type - R_RISCV_max];
1069
192
  else
1070
192
    {
1071
192
      (*_bfd_error_handler) (_("%pB: unsupported relocation type %#x"),
1072
192
           abfd, r_type);
1073
192
      bfd_set_error (bfd_error_bad_value);
1074
192
      return NULL;
1075
192
    }
1076
4.28k
}
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
8
{
1089
8
  reloc_howto_type *howto = reloc_entry->howto;
1090
8
  bfd_vma relocation;
1091
1092
8
  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
8
  if (output_bfd != NULL)
1101
0
    return bfd_reloc_continue;
1102
1103
8
  relocation = symbol->value + symbol->section->output_section->vma
1104
8
    + symbol->section->output_offset + reloc_entry->addend;
1105
1106
8
  bfd_size_type octets = reloc_entry->address
1107
8
    * bfd_octets_per_byte (abfd, input_section);
1108
8
  if (!bfd_reloc_offset_in_range (reloc_entry->howto, abfd,
1109
8
          input_section, octets))
1110
1
    return bfd_reloc_outofrange;
1111
1112
7
  bfd_vma old_value = bfd_get (howto->bitsize, abfd,
1113
7
             data + reloc_entry->address);
1114
1115
7
  switch (howto->type)
1116
7
    {
1117
2
    case R_RISCV_ADD8:
1118
2
    case R_RISCV_ADD16:
1119
2
    case R_RISCV_ADD32:
1120
5
    case R_RISCV_ADD64:
1121
5
      relocation = old_value + relocation;
1122
5
      break;
1123
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
2
    case R_RISCV_SUB16:
1130
2
    case R_RISCV_SUB32:
1131
2
    case R_RISCV_SUB64:
1132
2
      relocation = old_value - relocation;
1133
2
      break;
1134
7
    }
1135
7
  bfd_put (howto->bitsize, abfd, relocation, data + reloc_entry->address);
1136
1137
7
  return bfd_reloc_ok;
1138
7
}
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
5.04k
{
1163
5.04k
  return true;
1164
5.04k
}
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
841
{
1172
841
  return (subset->major_version < 2
1173
841
    || (subset->major_version == 2
1174
841
        && subset->minor_version < 1));
1175
841
}
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
841
{
1184
841
  return (rps != NULL
1185
841
    && rps->xlen != NULL
1186
841
    && *rps->xlen == 32
1187
0
    && riscv_subset_supports (rps, "f"));
1188
841
}
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
841
{
1196
841
  return (rps != NULL
1197
841
    && riscv_subset_supports (rps, "d"));
1198
841
}
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
51.5M
{
1697
51.5M
  int i = 0;
1698
141M
  while (parse_config[i].class != RV_ISA_CLASS_SINGLE)
1699
128M
    {
1700
128M
      if (strncmp (arch, parse_config[i].prefix,
1701
128M
       strlen (parse_config[i].prefix)) == 0)
1702
38.6M
  return parse_config[i].class;
1703
90.0M
      i++;
1704
90.0M
    }
1705
12.8M
  return RV_ISA_CLASS_SINGLE;
1706
51.5M
}
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
841
{
1757
841
  static bool inited = false;
1758
841
  if (inited)
1759
839
    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
26.0M
{
1786
26.0M
  int order1 = riscv_ext_order[(*subset1 - 'a')];
1787
26.0M
  int order2 = riscv_ext_order[(*subset2 - 'a')];
1788
1789
  /* Compare the standard extension first.  */
1790
26.0M
  if (order1 > 0 && order2 > 0)
1791
313k
    return order1 - order2;
1792
1793
  /* Set the prefixed orders to negative numbers.  */
1794
25.7M
  enum riscv_prefix_ext_class class1 = riscv_get_prefix_class (subset1);
1795
25.7M
  enum riscv_prefix_ext_class class2 = riscv_get_prefix_class (subset2);
1796
1797
25.7M
  if (class1 != RV_ISA_CLASS_SINGLE)
1798
13.0M
    order1 = - (int) class1;
1799
25.7M
  if (class2 != RV_ISA_CLASS_SINGLE)
1800
25.6M
    order2 = - (int) class2;
1801
1802
25.7M
  if (order1 == order2)
1803
12.8M
    {
1804
      /* Compare the standard addition z extensions.  */
1805
12.8M
      if (class1 == RV_ISA_CLASS_Z)
1806
12.8M
  {
1807
12.8M
    order1 = riscv_ext_order[(*++subset1 - 'a')];
1808
12.8M
    order2 = riscv_ext_order[(*++subset2 - 'a')];
1809
12.8M
    if (order1 != order2)
1810
11.1M
      return order1 - order2;
1811
12.8M
  }
1812
1.72M
      return strcasecmp (++subset1, ++subset2);
1813
12.8M
    }
1814
1815
12.8M
  return order2 - order1;
1816
25.7M
}
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
2.04M
{
1829
2.04M
  riscv_subset_t *s, *pre_s = NULL;
1830
1831
  /* If the subset is added in order, then just add it at the tail.  */
1832
2.04M
  if (subset_list->tail != NULL
1833
2.04M
      && riscv_compare_subsets (subset_list->tail->name, subset) < 0)
1834
140k
    {
1835
140k
      *current = subset_list->tail;
1836
140k
      return false;
1837
140k
    }
1838
1839
1.90M
  for (s = subset_list->head;
1840
24.0M
       s != NULL;
1841
22.1M
       pre_s = s, s = s->next)
1842
24.0M
    {
1843
24.0M
      int cmp = riscv_compare_subsets (s->name, subset);
1844
24.0M
      if (cmp == 0)
1845
841k
  {
1846
841k
    *current = s;
1847
841k
    return true;
1848
841k
  }
1849
23.1M
      else if (cmp > 0)
1850
1.06M
  break;
1851
24.0M
    }
1852
1.06M
  *current = pre_s;
1853
1854
1.06M
  return false;
1855
1.90M
}
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.7k
{
1866
11.7k
  riscv_subset_t *current, *new;
1867
1868
11.7k
  if (riscv_lookup_subset (subset_list, subset, &current))
1869
0
    return;
1870
1871
11.7k
  new = xmalloc (sizeof *new);
1872
11.7k
  new->name = xstrdup (subset);
1873
11.7k
  new->major_version = major;
1874
11.7k
  new->minor_version = minor;
1875
11.7k
  new->next = NULL;
1876
1877
11.7k
  if (current != NULL)
1878
10.0k
    {
1879
10.0k
      new->next = current->next;
1880
10.0k
      current->next = new;
1881
10.0k
    }
1882
1.68k
  else
1883
1.68k
    {
1884
1.68k
      new->next = subset_list->head;
1885
1.68k
      subset_list->head = new;
1886
1.68k
    }
1887
1888
11.7k
  if (new->next == NULL)
1889
6.72k
    subset_list->tail = new;
1890
11.7k
}
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.7k
{
1900
11.7k
  if (name == NULL
1901
11.7k
      || default_isa_spec == NULL
1902
11.7k
      || *default_isa_spec == ISA_SPEC_CLASS_NONE)
1903
0
    return;
1904
1905
11.7k
  const struct riscv_supported_ext *table = NULL;
1906
11.7k
  enum riscv_prefix_ext_class class = riscv_get_prefix_class (name);
1907
11.7k
  switch (class)
1908
11.7k
    {
1909
0
    case RV_ISA_CLASS_ZXM: table = riscv_supported_std_zxm_ext; break;
1910
5.88k
    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.88k
    default:
1914
5.88k
      table = riscv_supported_std_ext;
1915
11.7k
    }
1916
1917
11.7k
  int i = 0;
1918
333k
  while (table != NULL && table[i].name != NULL)
1919
333k
    {
1920
333k
      if (strcmp (table[i].name, name) == 0
1921
11.7k
    && (table[i].isa_spec_class == ISA_SPEC_CLASS_DRAFT
1922
7.56k
        || table[i].isa_spec_class == *default_isa_spec))
1923
10.9k
  {
1924
10.9k
    *major_version = table[i].major_version;
1925
10.9k
    *minor_version = table[i].minor_version;
1926
10.9k
    return;
1927
10.9k
  }
1928
322k
      i++;
1929
322k
    }
1930
11.7k
}
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.7k
{
1943
11.7k
  int major_version = major;
1944
11.7k
  int minor_version = minor;
1945
1946
11.7k
  if (major_version == RISCV_UNKNOWN_VERSION
1947
0
       || minor_version == RISCV_UNKNOWN_VERSION)
1948
11.7k
    riscv_get_default_ext_version (rps->isa_spec, subset,
1949
11.7k
           &major_version, &minor_version);
1950
1951
  /* We don't care the versions of the implicit extensions.  */
1952
11.7k
  if (!implicit
1953
841
      && (major_version == RISCV_UNKNOWN_VERSION
1954
841
    || 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.7k
  riscv_add_subset (rps->subset_list, subset,
1970
11.7k
        major_version, minor_version);
1971
11.7k
}
1972
1973
/* Release subset list.  */
1974
1975
void
1976
riscv_release_subset_list (riscv_subset_list_t *subset_list)
1977
1.68k
{
1978
13.4k
   while (subset_list->head != NULL)
1979
11.7k
    {
1980
11.7k
      riscv_subset_t *next = subset_list->head->next;
1981
11.7k
      free ((void *)subset_list->head->name);
1982
11.7k
      free (subset_list->head);
1983
11.7k
      subset_list->head = next;
1984
11.7k
    }
1985
1986
1.68k
  subset_list->tail = NULL;
1987
1988
1.68k
  if (subset_list->arch_str != NULL)
1989
841
    {
1990
841
      free ((void*) subset_list->arch_str);
1991
841
      subset_list->arch_str = NULL;
1992
841
    }
1993
1.68k
}
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.4k
{
2010
13.4k
  bool major_p = true;
2011
13.4k
  int version = 0;
2012
13.4k
  char np;
2013
2014
13.4k
  *major_version = 0;
2015
13.4k
  *minor_version = 0;
2016
13.4k
  for (; *p; ++p)
2017
6.72k
    {
2018
6.72k
      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.72k
      else if (ISDIGIT (*p))
2031
0
  version = (version * 10) + (*p - '0');
2032
6.72k
      else
2033
6.72k
  break;
2034
6.72k
    }
2035
2036
13.4k
  if (major_p)
2037
13.4k
    *major_version = version;
2038
0
  else
2039
0
    *minor_version = version;
2040
2041
  /* We can not find any version in string.  */
2042
13.4k
  if (*major_version == 0 && *minor_version == 0)
2043
13.4k
    {
2044
13.4k
      *major_version = RISCV_UNKNOWN_VERSION;
2045
13.4k
      *minor_version = RISCV_UNKNOWN_VERSION;
2046
13.4k
    }
2047
2048
13.4k
  return p;
2049
13.4k
}
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
841
{
2067
  /* First letter must start with i, e, g or a profile.  */
2068
841
  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.52k
  while (*p != '\0')
2077
1.68k
    {
2078
1.68k
      if (*p == '_')
2079
0
  {
2080
0
    p++;
2081
0
    continue;
2082
0
  }
2083
2084
1.68k
      char *subset = xstrdup (p);
2085
1.68k
      char *q = subset; /* Start of version.  */
2086
1.68k
      const char *end_of_version;
2087
1.68k
      bool implicit = false;
2088
2089
1.68k
      enum riscv_prefix_ext_class class = riscv_get_prefix_class (p);
2090
1.68k
      if (class == RV_ISA_CLASS_SINGLE)
2091
1.68k
  {
2092
1.68k
    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.68k
    q++;
2101
1.68k
  }
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.68k
      int major_version = RISCV_UNKNOWN_VERSION;
2139
1.68k
      int minor_version = RISCV_UNKNOWN_VERSION;
2140
1.68k
      end_of_version =
2141
1.68k
  riscv_parsing_subset_version (q, &major_version, &minor_version);
2142
1.68k
      *q = '\0';
2143
1.68k
      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.68k
      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.68k
      if (class == RV_ISA_CLASS_SINGLE
2163
1.68k
    && strcmp (subset, "g") == 0)
2164
841
  {
2165
841
    implicit = true;
2166
841
    major_version = RISCV_UNKNOWN_VERSION;
2167
841
    minor_version = RISCV_UNKNOWN_VERSION;
2168
841
  }
2169
1.68k
      riscv_parse_add_subset (rps, subset,
2170
1.68k
            major_version,
2171
1.68k
            minor_version, implicit);
2172
1.68k
      p += end_of_version - subset;
2173
1.68k
      free (subset);
2174
2175
1.68k
      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.68k
    }
2184
2185
841
  return p;
2186
841
}
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
841
{
2196
841
  const struct riscv_implicit_subset *t = riscv_implicit_subsets;
2197
93.3k
  for (; t->ext; t++)
2198
92.5k
    {
2199
92.5k
      riscv_subset_t *subset = NULL;
2200
92.5k
      if (riscv_lookup_subset (rps->subset_list, t->ext, &subset)
2201
7.56k
  && t->check_func (rps, subset))
2202
5.88k
      riscv_update_subset1 (rps, subset, t->implicit_exts);
2203
92.5k
    }
2204
841
}
2205
2206
/* Check extensions conflicts.  */
2207
2208
static bool
2209
riscv_parse_check_conflicts (riscv_parse_subset_t *rps)
2210
841
{
2211
841
  riscv_subset_t *subset = NULL;
2212
841
  int xlen = *rps->xlen;
2213
841
  bool no_conflict = true;
2214
2215
841
  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
841
  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
841
  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
841
  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
841
  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
841
  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
841
  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
841
  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
841
  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
841
  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
841
  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
841
  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
841
  bool support_zve = false;
2299
841
  bool support_zvl = false;
2300
841
  riscv_subset_t *s = rps->subset_list->head;
2301
12.6k
  for (; s != NULL; s = s->next)
2302
11.7k
    {
2303
11.7k
      if (!support_zve
2304
11.7k
    && strncmp (s->name, "zve", 3) == 0)
2305
0
  support_zve = true;
2306
11.7k
      if (!support_zvl
2307
11.7k
    && strncmp (s->name, "zvl", 3) == 0)
2308
0
  support_zvl = true;
2309
11.7k
      if (support_zve && support_zvl)
2310
0
  break;
2311
11.7k
    }
2312
841
  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
841
  return no_conflict;
2320
841
}
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
841
{
2349
841
  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.56k
  for (int i = 0; riscv_profiles_table[i].profile_name != NULL; ++i)
2360
6.72k
    {
2361
      /* Find profile at the begin.  */
2362
6.72k
      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.72k
    }
2378
  /* Not found profile, return directly.  */
2379
841
  return false;
2380
841
}
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
841
{
2395
841
  const char *p;
2396
2397
  /* Init the riscv_ext_order array to compare the order of extensions
2398
     quickly.  */
2399
841
  riscv_init_ext_order ();
2400
2401
841
  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.88k
  for (p = arch; *p != '\0'; p++)
2409
5.04k
    {
2410
5.04k
      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
5.04k
    }
2418
2419
841
  bool profile = false;
2420
841
  p = arch;
2421
841
  if (riscv_find_profiles (rps, &p))
2422
0
    {
2423
      /* Check if using Profiles.  */
2424
0
      profile = true;
2425
0
    }
2426
841
  else if (startswith (p, "rv32"))
2427
0
    {
2428
0
      *rps->xlen = 32;
2429
0
      p += 4;
2430
0
    }
2431
841
  else if (startswith (p, "rv64"))
2432
841
    {
2433
841
      *rps->xlen = 64;
2434
841
      p += 4;
2435
841
    }
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
841
  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
841
  riscv_parse_add_implicit_subsets (rps);
2459
2460
  /* Check the conflicts.  */
2461
841
  return riscv_parse_check_conflicts (rps);
2462
841
}
2463
2464
/* Return the number of digits for the input.  */
2465
2466
size_t
2467
riscv_estimate_digit (unsigned num)
2468
23.5k
{
2469
23.5k
  size_t digit = 0;
2470
23.5k
  if (num == 0)
2471
7.56k
    return 1;
2472
2473
47.0k
  for (digit = 0; num ; num /= 10)
2474
31.1k
    digit++;
2475
2476
15.9k
  return digit;
2477
23.5k
}
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.6k
{
2484
12.6k
  if (subset == NULL)
2485
841
    return 6; /* For rv32/rv64/rv128 and string terminator.  */
2486
2487
11.7k
  return riscv_estimate_arch_strlen1 (subset->next)
2488
11.7k
   + strlen (subset->name)
2489
11.7k
   + riscv_estimate_digit (subset->major_version)
2490
11.7k
   + 1 /* For version seperator 'p'.  */
2491
11.7k
   + riscv_estimate_digit (subset->minor_version)
2492
11.7k
   + 1 /* For underscore.  */;
2493
12.6k
}
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
841
{
2500
841
  return riscv_estimate_arch_strlen1 (subset_list->head);
2501
841
}
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.7k
{
2509
11.7k
  const char *underline = "_";
2510
11.7k
  riscv_subset_t *subset_t = subset;
2511
2512
11.7k
  if (subset_t == NULL)
2513
841
    return;
2514
2515
  /* No underline between rvXX and i/e.  */
2516
10.9k
  if ((strcasecmp (subset_t->name, "i") == 0)
2517
10.0k
      || (strcasecmp (subset_t->name, "e") == 0))
2518
841
    underline = "";
2519
2520
10.9k
  snprintf (buf, bufsz, "%s%s%dp%d",
2521
10.9k
      underline,
2522
10.9k
      subset_t->name,
2523
10.9k
      subset_t->major_version,
2524
10.9k
      subset_t->minor_version);
2525
2526
10.9k
  strncat (attr_str, buf, bufsz);
2527
2528
  /* Skip 'i' extension after 'e', or skip extensions which
2529
     versions are unknown.  */
2530
11.7k
  while (subset_t->next
2531
10.9k
   && ((strcmp (subset_t->name, "e") == 0
2532
0
        && strcmp (subset_t->next->name, "i") == 0)
2533
10.9k
       || subset_t->next->major_version == RISCV_UNKNOWN_VERSION
2534
10.0k
       || subset_t->next->minor_version == RISCV_UNKNOWN_VERSION))
2535
841
    subset_t = subset_t->next;
2536
2537
10.9k
  riscv_arch_str1 (subset_t->next, attr_str, buf, bufsz);
2538
10.9k
}
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
841
{
2545
841
  size_t arch_str_len = riscv_estimate_arch_strlen (subset);
2546
841
  char *attr_str = xmalloc (arch_str_len);
2547
841
  char *buf = xmalloc (arch_str_len);
2548
2549
841
  snprintf (attr_str, arch_str_len, "rv%u", xlen);
2550
2551
841
  riscv_arch_str1 (subset->head, attr_str, buf, arch_str_len);
2552
841
  free (buf);
2553
2554
841
  if (update)
2555
841
    {
2556
841
      if (subset->arch_str != NULL)
2557
0
  free ((void *) subset->arch_str);
2558
841
      subset->arch_str = attr_str;
2559
841
    }
2560
2561
841
  return attr_str;
2562
841
}
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.88k
{
2636
5.88k
  const char *p = implicit_exts;
2637
5.88k
  const char *errmsg_internal = explicit_subset == NULL ? "" : _("internal: ");
2638
5.88k
  const char *errmsg_caller = explicit_subset == NULL
2639
5.88k
            ? ".option arch" : "riscv_implicit_subsets";
2640
2641
5.88k
  do
2642
11.7k
    {
2643
11.7k
      int major_version = RISCV_UNKNOWN_VERSION;
2644
11.7k
      int minor_version = RISCV_UNKNOWN_VERSION;
2645
2646
11.7k
      bool removed = false;
2647
11.7k
      switch (*p)
2648
11.7k
  {
2649
11.7k
  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.7k
  }
2655
11.7k
      ++p;
2656
2657
11.7k
      char *subset = xstrdup (p);
2658
11.7k
      char *q = subset;
2659
11.7k
      const char *end_of_version;
2660
      /* Extract the whole prefixed extension by ','.  */
2661
50.4k
      while (*q != '\0' && *q != ',')
2662
38.6k
        q++;
2663
2664
      /* Look forward to the first letter which is not <major>p<minor>.  */
2665
11.7k
      bool find_any_version = false;
2666
11.7k
      bool find_minor_version = false;
2667
11.7k
      size_t len = q - subset;
2668
11.7k
      size_t i;
2669
11.7k
      for (i = len; i > 0; i--)
2670
11.7k
        {
2671
11.7k
    q--;
2672
11.7k
    if (ISDIGIT (*q))
2673
0
      find_any_version = true;
2674
11.7k
    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.7k
    else
2680
11.7k
      break;
2681
11.7k
  }
2682
11.7k
      if (len > 0)
2683
11.7k
  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.7k
      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.7k
      end_of_version =
2698
11.7k
  riscv_parsing_subset_version (q, &major_version, &minor_version);
2699
11.7k
      *q = '\0';
2700
11.7k
      if (end_of_version == NULL)
2701
0
  {
2702
0
    free (subset);
2703
0
    return false;
2704
0
  }
2705
2706
11.7k
      if (strlen (subset) == 0
2707
11.7k
    || (strlen (subset) == 1
2708
5.04k
        && riscv_ext_order[(*subset - 'a')] == 0)
2709
11.7k
    || (strlen (subset) > 1
2710
6.72k
        && 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.7k
      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.7k
      if (removed)
2743
0
  riscv_remove_subset (rps->subset_list, subset);
2744
11.7k
      else
2745
11.7k
  {
2746
11.7k
    riscv_subset_t *isubset = NULL;
2747
11.7k
    if (!riscv_lookup_subset (rps->subset_list, subset, &isubset))
2748
10.0k
      riscv_parse_add_subset (rps, subset, major_version, minor_version,
2749
10.0k
            true/* implicit */);
2750
11.7k
  }
2751
11.7k
      p += end_of_version - subset;
2752
11.7k
      free (subset);
2753
11.7k
    }
2754
11.7k
  while (*p++ == ',');
2755
2756
5.88k
  bool no_conflict = true;
2757
5.88k
  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.88k
  return no_conflict;
2763
5.88k
}
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.92M
{
2792
1.92M
  struct riscv_subset_t *subset;
2793
1.92M
  return riscv_lookup_subset (rps->subset_list, feature, &subset);
2794
1.92M
}
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
899k
{
2803
899k
  switch (insn_class)
2804
899k
    {
2805
39.3k
    case INSN_CLASS_I:
2806
39.3k
      return riscv_subset_supports (rps, "i");
2807
59
    case INSN_CLASS_ZICBOM:
2808
59
      return riscv_subset_supports (rps, "zicbom");
2809
17
    case INSN_CLASS_ZICBOP:
2810
17
      return riscv_subset_supports (rps, "zicbop");
2811
92
    case INSN_CLASS_ZICBOZ:
2812
92
      return riscv_subset_supports (rps, "zicboz");
2813
31
    case INSN_CLASS_ZICOND:
2814
31
      return riscv_subset_supports (rps, "zicond");
2815
5.38k
    case INSN_CLASS_ZICSR:
2816
5.38k
      return riscv_subset_supports (rps, "zicsr");
2817
18
    case INSN_CLASS_ZIFENCEI:
2818
18
      return riscv_subset_supports (rps, "zifencei");
2819
17
    case INSN_CLASS_ZIHINTNTL:
2820
17
      return riscv_subset_supports (rps, "zihintntl");
2821
130
    case INSN_CLASS_ZIHINTNTL_AND_ZCA:
2822
130
      return riscv_subset_supports (rps, "zihintntl")
2823
0
       && riscv_subset_supports (rps, "zca");
2824
110
    case INSN_CLASS_ZIHINTPAUSE:
2825
110
      return riscv_subset_supports (rps, "zihintpause");
2826
168
    case INSN_CLASS_ZIMOP:
2827
168
      return riscv_subset_supports (rps, "zimop");
2828
74
    case INSN_CLASS_ZICFISS:
2829
74
      return riscv_subset_supports (rps, "zicfiss");
2830
128
    case INSN_CLASS_ZICFISS_AND_ZCMOP:
2831
128
      return riscv_subset_supports (rps, "zicfiss")
2832
0
       && riscv_subset_supports (rps, "zcmop");
2833
522
    case INSN_CLASS_ZICFILP:
2834
522
      return riscv_subset_supports (rps, "zicfilp");
2835
53
    case INSN_CLASS_M:
2836
53
      return riscv_subset_supports (rps, "m");
2837
96
    case INSN_CLASS_ZMMUL:
2838
96
      return riscv_subset_supports (rps, "zmmul");
2839
638
    case INSN_CLASS_ZAAMO:
2840
638
      return riscv_subset_supports (rps, "zaamo");
2841
489
    case INSN_CLASS_ZABHA:
2842
489
      return riscv_subset_supports (rps, "zabha");
2843
1.07k
    case INSN_CLASS_ZACAS:
2844
1.07k
      return riscv_subset_supports (rps, "zacas");
2845
146
    case INSN_CLASS_ZABHA_AND_ZACAS:
2846
146
      return (riscv_subset_supports (rps, "zabha")
2847
0
        && riscv_subset_supports (rps, "zacas"));
2848
131
    case INSN_CLASS_ZALRSC:
2849
131
      return riscv_subset_supports (rps, "zalrsc");
2850
17
    case INSN_CLASS_ZAWRS:
2851
17
      return riscv_subset_supports (rps, "zawrs");
2852
1.36k
    case INSN_CLASS_F:
2853
1.36k
      return riscv_subset_supports (rps, "f");
2854
404
    case INSN_CLASS_D:
2855
404
      return riscv_subset_supports (rps, "d");
2856
870
    case INSN_CLASS_Q:
2857
870
      return riscv_subset_supports (rps, "q");
2858
683k
    case INSN_CLASS_ZCA:
2859
683k
      return riscv_subset_supports (rps, "zca");
2860
0
    case INSN_CLASS_ZCF:
2861
0
      return riscv_subset_supports (rps, "zcf");
2862
87.1k
    case INSN_CLASS_ZCD:
2863
87.1k
      return riscv_subset_supports (rps, "zcd");
2864
5.48k
    case INSN_CLASS_F_INX:
2865
5.48k
      return (riscv_subset_supports (rps, "f")
2866
0
        || riscv_subset_supports (rps, "zfinx"));
2867
7.90k
    case INSN_CLASS_D_INX:
2868
7.90k
      return (riscv_subset_supports (rps, "d")
2869
0
        || riscv_subset_supports (rps, "zdinx"));
2870
3.63k
    case INSN_CLASS_Q_INX:
2871
3.63k
      return (riscv_subset_supports (rps, "q")
2872
3.63k
        || riscv_subset_supports (rps, "zqinx"));
2873
2.89k
    case INSN_CLASS_ZFH_INX:
2874
2.89k
      return (riscv_subset_supports (rps, "zfh")
2875
2.89k
        || riscv_subset_supports (rps, "zhinx"));
2876
590
    case INSN_CLASS_ZFHMIN:
2877
590
      return riscv_subset_supports (rps, "zfhmin");
2878
66
    case INSN_CLASS_ZFHMIN_INX:
2879
66
      return (riscv_subset_supports (rps, "zfhmin")
2880
66
        || 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
25
    case INSN_CLASS_ZFHMIN_AND_Q_INX:
2887
25
      return ((riscv_subset_supports (rps, "zfhmin")
2888
0
         && riscv_subset_supports (rps, "q"))
2889
25
        || (riscv_subset_supports (rps, "zhinxmin")
2890
0
      && riscv_subset_supports (rps, "zqinx")));
2891
6
    case INSN_CLASS_ZFBFMIN:
2892
6
      return riscv_subset_supports (rps, "zfbfmin");
2893
39
    case INSN_CLASS_ZFA:
2894
39
      return riscv_subset_supports (rps, "zfa");
2895
137
    case INSN_CLASS_D_AND_ZFA:
2896
137
      return riscv_subset_supports (rps, "d")
2897
137
       && 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
72
    case INSN_CLASS_ZBA:
2909
72
      return riscv_subset_supports (rps, "zba");
2910
56
    case INSN_CLASS_ZBB:
2911
56
      return riscv_subset_supports (rps, "zbb");
2912
10
    case INSN_CLASS_ZBC:
2913
10
      return riscv_subset_supports (rps, "zbc");
2914
70
    case INSN_CLASS_ZBS:
2915
70
      return riscv_subset_supports (rps, "zbs");
2916
117
    case INSN_CLASS_ZBKB:
2917
117
      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
166
    case INSN_CLASS_ZBB_OR_ZBKB:
2923
166
      return (riscv_subset_supports (rps, "zbb")
2924
166
        || riscv_subset_supports (rps, "zbkb"));
2925
17
    case INSN_CLASS_ZBC_OR_ZBKC:
2926
17
      return (riscv_subset_supports (rps, "zbc")
2927
17
        || riscv_subset_supports (rps, "zbkc"));
2928
101
    case INSN_CLASS_ZKND:
2929
101
      return riscv_subset_supports (rps, "zknd");
2930
34
    case INSN_CLASS_ZKNE:
2931
34
      return riscv_subset_supports (rps, "zkne");
2932
55
    case INSN_CLASS_ZKNH:
2933
55
      return riscv_subset_supports (rps, "zknh");
2934
27
    case INSN_CLASS_ZKND_OR_ZKNE:
2935
27
      return (riscv_subset_supports (rps, "zknd")
2936
27
        || riscv_subset_supports (rps, "zkne"));
2937
132
    case INSN_CLASS_ZKSED:
2938
132
      return riscv_subset_supports (rps, "zksed");
2939
61
    case INSN_CLASS_ZKSH:
2940
61
      return riscv_subset_supports (rps, "zksh");
2941
4.58k
    case INSN_CLASS_V:
2942
4.58k
      return (riscv_subset_supports (rps, "v")
2943
4.58k
        || riscv_subset_supports (rps, "zve64x")
2944
4.58k
        || riscv_subset_supports (rps, "zve32x"));
2945
1.00k
    case INSN_CLASS_ZVEF:
2946
1.00k
      return (riscv_subset_supports (rps, "v")
2947
1.00k
        || riscv_subset_supports (rps, "zve64d")
2948
1.00k
        || riscv_subset_supports (rps, "zve64f")
2949
1.00k
        || riscv_subset_supports (rps, "zve32f"));
2950
87
    case INSN_CLASS_ZVBB:
2951
87
      return riscv_subset_supports (rps, "zvbb");
2952
32
    case INSN_CLASS_ZVBC:
2953
32
      return riscv_subset_supports (rps, "zvbc");
2954
11
    case INSN_CLASS_ZVFBFMIN:
2955
11
      return riscv_subset_supports (rps, "zvfbfmin");
2956
38
    case INSN_CLASS_ZVFBFWMA:
2957
38
      return riscv_subset_supports (rps, "zvfbfwma");
2958
121
    case INSN_CLASS_ZVKB:
2959
121
      return riscv_subset_supports (rps, "zvkb");
2960
20
    case INSN_CLASS_ZVKG:
2961
20
      return riscv_subset_supports (rps, "zvkg");
2962
18
    case INSN_CLASS_ZVKNED:
2963
18
      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
68
    case INSN_CLASS_ZVKSED:
2968
68
      return riscv_subset_supports (rps, "zvksed");
2969
17
    case INSN_CLASS_ZVKSH:
2970
17
      return riscv_subset_supports (rps, "zvksh");
2971
21.6k
    case INSN_CLASS_ZCB:
2972
21.6k
      return riscv_subset_supports (rps, "zcb");
2973
426
    case INSN_CLASS_ZCB_AND_ZBB:
2974
426
      return (riscv_subset_supports (rps, "zcb")
2975
0
        && riscv_subset_supports (rps, "zbb"));
2976
28
    case INSN_CLASS_ZCB_AND_ZBA:
2977
28
      return (riscv_subset_supports (rps, "zcb")
2978
0
        && riscv_subset_supports (rps, "zba"));
2979
1.51k
    case INSN_CLASS_ZCB_AND_ZMMUL:
2980
1.51k
      return (riscv_subset_supports (rps, "zcb")
2981
0
        && riscv_subset_supports (rps, "zmmul"));
2982
90
    case INSN_CLASS_ZCMOP:
2983
90
      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
20
    case INSN_CLASS_SVINVAL:
2998
20
      return riscv_subset_supports (rps, "svinval");
2999
128
    case INSN_CLASS_H:
3000
128
      return riscv_subset_supports (rps, "h");
3001
505
    case INSN_CLASS_XCVALU:
3002
505
      return riscv_subset_supports (rps, "xcvalu");
3003
1.26k
    case INSN_CLASS_XCVBI:
3004
1.26k
      return riscv_subset_supports (rps, "xcvbi");
3005
808
    case INSN_CLASS_XCVBITMANIP:
3006
808
      return riscv_subset_supports (rps, "xcvbitmanip");
3007
471
    case INSN_CLASS_XCVELW:
3008
471
      return riscv_subset_supports (rps, "xcvelw");
3009
3.15k
    case INSN_CLASS_XCVMAC:
3010
3.15k
      return riscv_subset_supports (rps, "xcvmac");
3011
6.82k
    case INSN_CLASS_XCVMEM:
3012
6.82k
      return riscv_subset_supports (rps, "xcvmem");
3013
1.16k
    case INSN_CLASS_XCVSIMD:
3014
1.16k
      return riscv_subset_supports (rps, "xcvsimd");
3015
511
    case INSN_CLASS_XTHEADBA:
3016
511
      return riscv_subset_supports (rps, "xtheadba");
3017
476
    case INSN_CLASS_XTHEADBB:
3018
476
      return riscv_subset_supports (rps, "xtheadbb");
3019
26
    case INSN_CLASS_XTHEADBS:
3020
26
      return riscv_subset_supports (rps, "xtheadbs");
3021
804
    case INSN_CLASS_XTHEADCMO:
3022
804
      return riscv_subset_supports (rps, "xtheadcmo");
3023
368
    case INSN_CLASS_XTHEADCONDMOV:
3024
368
      return riscv_subset_supports (rps, "xtheadcondmov");
3025
210
    case INSN_CLASS_XTHEADFMEMIDX:
3026
210
      return riscv_subset_supports (rps, "xtheadfmemidx");
3027
0
    case INSN_CLASS_XTHEADFMV:
3028
0
      return riscv_subset_supports (rps, "xtheadfmv");
3029
34
    case INSN_CLASS_XTHEADINT:
3030
34
      return riscv_subset_supports (rps, "xtheadint");
3031
58
    case INSN_CLASS_XTHEADMAC:
3032
58
      return riscv_subset_supports (rps, "xtheadmac");
3033
992
    case INSN_CLASS_XTHEADMEMIDX:
3034
992
      return riscv_subset_supports (rps, "xtheadmemidx");
3035
239
    case INSN_CLASS_XTHEADMEMPAIR:
3036
239
      return riscv_subset_supports (rps, "xtheadmempair");
3037
25
    case INSN_CLASS_XTHEADSYNC:
3038
25
      return riscv_subset_supports (rps, "xtheadsync");
3039
4.46k
    case INSN_CLASS_XTHEADVECTOR:
3040
4.46k
      return riscv_subset_supports (rps, "xtheadvector");
3041
73
    case INSN_CLASS_XTHEADVDOT:
3042
73
      return riscv_subset_supports (rps, "xtheadvdot");
3043
332
    case INSN_CLASS_XTHEADZVAMO:
3044
332
      return riscv_subset_supports (rps, "xtheadzvamo");
3045
313
    case INSN_CLASS_XVENTANACONDOPS:
3046
313
      return riscv_subset_supports (rps, "xventanacondops");
3047
362
    case INSN_CLASS_XSFVCP:
3048
362
      return riscv_subset_supports (rps, "xsfvcp");
3049
0
    case INSN_CLASS_XSFCEASE:
3050
0
      return riscv_subset_supports (rps, "xsfcease");
3051
25
    case INSN_CLASS_XSFVQMACCQOQ:
3052
25
      return riscv_subset_supports (rps, "xsfvqmaccqoq");
3053
111
    case INSN_CLASS_XSFVQMACCDOD:
3054
111
      return riscv_subset_supports (rps, "xsfvqmaccdod");
3055
42
    case INSN_CLASS_XSFVFNRCLIPXFQF:
3056
42
      return riscv_subset_supports (rps, "xsfvfnrclipxfqf");
3057
1.42k
    case INSN_CLASS_XMIPSCBOP:
3058
1.42k
      return riscv_subset_supports (rps, "xmipscbop");
3059
74
    case INSN_CLASS_XMIPSCMOV:
3060
74
      return riscv_subset_supports (rps, "xmipscmov");
3061
5
    case INSN_CLASS_XMIPSEXECTL:
3062
5
      return riscv_subset_supports (rps, "xmipsexectl");
3063
658
    case INSN_CLASS_XMIPSLSP:
3064
658
      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
899k
    }
3070
899k
}
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
}