Coverage Report

Created: 2025-07-08 11:15

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