Coverage Report

Created: 2024-05-21 06:29

/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-2024 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
/* Given a BFD reloc type, return a howto structure.  */
1026
1027
reloc_howto_type *
1028
riscv_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED,
1029
       bfd_reloc_code_real_type code)
1030
0
{
1031
0
  unsigned int i;
1032
1033
0
  for (i = 0; i < ARRAY_SIZE (riscv_reloc_map); i++)
1034
0
    if (riscv_reloc_map[i].bfd_val == code)
1035
0
      return &howto_table[(int) riscv_reloc_map[i].elf_val];
1036
1037
0
  bfd_set_error (bfd_error_bad_value);
1038
0
  return NULL;
1039
0
}
1040
1041
reloc_howto_type *
1042
riscv_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED, const char *r_name)
1043
0
{
1044
0
  unsigned int i;
1045
1046
0
  for (i = 0; i < ARRAY_SIZE (howto_table); i++)
1047
0
    if (howto_table[i].name && strcasecmp (howto_table[i].name, r_name) == 0)
1048
0
      return &howto_table[i];
1049
1050
0
  return NULL;
1051
0
}
1052
1053
reloc_howto_type *
1054
riscv_elf_rtype_to_howto (bfd *abfd, unsigned int r_type)
1055
210
{
1056
210
  if (r_type < ARRAY_SIZE (howto_table))
1057
88
    return &howto_table[r_type];
1058
122
  else if (r_type < R_RISCV_max + ARRAY_SIZE (howto_table_internal))
1059
0
    return &howto_table_internal[r_type - R_RISCV_max];
1060
122
  else
1061
122
    {
1062
122
      (*_bfd_error_handler) (_("%pB: unsupported relocation type %#x"),
1063
122
           abfd, r_type);
1064
122
      bfd_set_error (bfd_error_bad_value);
1065
122
      return NULL;
1066
122
    }
1067
210
}
1068
1069
/* Special_function of RISCV_ADD and RISCV_SUB relocations.  */
1070
1071
static bfd_reloc_status_type
1072
riscv_elf_add_sub_reloc (bfd *abfd,
1073
       arelent *reloc_entry,
1074
       asymbol *symbol,
1075
       void *data,
1076
       asection *input_section,
1077
       bfd *output_bfd,
1078
       char **error_message ATTRIBUTE_UNUSED)
1079
0
{
1080
0
  reloc_howto_type *howto = reloc_entry->howto;
1081
0
  bfd_vma relocation;
1082
1083
0
  if (output_bfd != NULL
1084
0
      && (symbol->flags & BSF_SECTION_SYM) == 0
1085
0
      && (!reloc_entry->howto->partial_inplace || reloc_entry->addend == 0))
1086
0
    {
1087
0
      reloc_entry->address += input_section->output_offset;
1088
0
      return bfd_reloc_ok;
1089
0
    }
1090
1091
0
  if (output_bfd != NULL)
1092
0
    return bfd_reloc_continue;
1093
1094
0
  relocation = symbol->value + symbol->section->output_section->vma
1095
0
    + symbol->section->output_offset + reloc_entry->addend;
1096
1097
0
  bfd_size_type octets = reloc_entry->address
1098
0
    * bfd_octets_per_byte (abfd, input_section);
1099
0
  if (!bfd_reloc_offset_in_range (reloc_entry->howto, abfd,
1100
0
          input_section, octets))
1101
0
    return bfd_reloc_outofrange;
1102
1103
0
  bfd_vma old_value = bfd_get (howto->bitsize, abfd,
1104
0
             data + reloc_entry->address);
1105
1106
0
  switch (howto->type)
1107
0
    {
1108
0
    case R_RISCV_ADD8:
1109
0
    case R_RISCV_ADD16:
1110
0
    case R_RISCV_ADD32:
1111
0
    case R_RISCV_ADD64:
1112
0
      relocation = old_value + relocation;
1113
0
      break;
1114
0
    case R_RISCV_SUB6:
1115
0
      relocation = (old_value & ~howto->dst_mask)
1116
0
       | (((old_value & howto->dst_mask) - relocation)
1117
0
          & howto->dst_mask);
1118
0
      break;
1119
0
    case R_RISCV_SUB8:
1120
0
    case R_RISCV_SUB16:
1121
0
    case R_RISCV_SUB32:
1122
0
    case R_RISCV_SUB64:
1123
0
      relocation = old_value - relocation;
1124
0
      break;
1125
0
    }
1126
0
  bfd_put (howto->bitsize, abfd, relocation, data + reloc_entry->address);
1127
1128
0
  return bfd_reloc_ok;
1129
0
}
1130
1131
/* Special handler for relocations which don't have to be relocated.
1132
   This function just simply return bfd_reloc_ok.  */
1133
1134
static bfd_reloc_status_type
1135
riscv_elf_ignore_reloc (bfd *abfd ATTRIBUTE_UNUSED,
1136
      arelent *reloc_entry,
1137
      asymbol *symbol ATTRIBUTE_UNUSED,
1138
      void *data ATTRIBUTE_UNUSED,
1139
      asection *input_section,
1140
      bfd *output_bfd,
1141
      char **error_message ATTRIBUTE_UNUSED)
1142
0
{
1143
0
  if (output_bfd != NULL)
1144
0
    reloc_entry->address += input_section->output_offset;
1145
0
  return bfd_reloc_ok;
1146
0
}
1147
1148
/* Always add the IMPLICIT for the SUBSET.  */
1149
1150
static bool
1151
check_implicit_always (const char *implicit ATTRIBUTE_UNUSED,
1152
           riscv_subset_t *subset ATTRIBUTE_UNUSED)
1153
6.69k
{
1154
6.69k
  return true;
1155
6.69k
}
1156
1157
/* Add the IMPLICIT only when the version of SUBSET less than 2.1.  */
1158
1159
static bool
1160
check_implicit_for_i (const char *implicit ATTRIBUTE_UNUSED,
1161
          riscv_subset_t *subset)
1162
7.35k
{
1163
7.35k
  return (subset->major_version < 2
1164
7.35k
    || (subset->major_version == 2
1165
7.35k
        && subset->minor_version < 1));
1166
7.35k
}
1167
1168
/* Record all implicit information for the subsets.  */
1169
struct riscv_implicit_subset
1170
{
1171
  const char *subset_name;
1172
  const char *implicit_name;
1173
  /* A function to determine if we need to add the implicit subset.  */
1174
  bool (*check_func) (const char *, riscv_subset_t *);
1175
};
1176
static struct riscv_implicit_subset riscv_implicit_subsets[] =
1177
{
1178
  {"e", "i",    check_implicit_always},
1179
  {"i", "zicsr",  check_implicit_for_i},
1180
  {"i", "zifencei", check_implicit_for_i},
1181
  {"g", "i",    check_implicit_always},
1182
  {"g", "m",    check_implicit_always},
1183
  {"g", "a",    check_implicit_always},
1184
  {"g", "f",    check_implicit_always},
1185
  {"g", "d",    check_implicit_always},
1186
  {"g", "zicsr",  check_implicit_always},
1187
  {"g", "zifencei", check_implicit_always},
1188
  {"m", "zmmul",  check_implicit_always},
1189
  {"h", "zicsr",  check_implicit_always},
1190
  {"q", "d",    check_implicit_always},
1191
  {"v", "d",    check_implicit_always},
1192
  {"v", "zve64d", check_implicit_always},
1193
  {"v", "zvl128b",  check_implicit_always},
1194
  {"zabha", "a",  check_implicit_always},
1195
  {"zvfh", "zvfhmin", check_implicit_always},
1196
  {"zvfh", "zfhmin",  check_implicit_always},
1197
  {"zvfhmin", "zve32f", check_implicit_always},
1198
  {"zve64d", "d", check_implicit_always},
1199
  {"zve64d", "zve64f",  check_implicit_always},
1200
  {"zve64f", "zve32f",  check_implicit_always},
1201
  {"zve64f", "zve64x",  check_implicit_always},
1202
  {"zve64f", "zvl64b",  check_implicit_always},
1203
  {"zve32f", "f", check_implicit_always},
1204
  {"zve32f", "zvl32b",  check_implicit_always},
1205
  {"zve32f", "zve32x",  check_implicit_always},
1206
  {"zve64x", "zve32x",  check_implicit_always},
1207
  {"zve64x", "zvl64b",  check_implicit_always},
1208
  {"zve32x", "zvl32b",  check_implicit_always},
1209
  {"zve32x", "zicsr", check_implicit_always},
1210
  {"zvl65536b", "zvl32768b",  check_implicit_always},
1211
  {"zvl32768b", "zvl16384b",  check_implicit_always},
1212
  {"zvl16384b", "zvl8192b", check_implicit_always},
1213
  {"zvl8192b", "zvl4096b",  check_implicit_always},
1214
  {"zvl4096b", "zvl2048b",  check_implicit_always},
1215
  {"zvl2048b", "zvl1024b",  check_implicit_always},
1216
  {"zvl1024b", "zvl512b", check_implicit_always},
1217
  {"zvl512b", "zvl256b",  check_implicit_always},
1218
  {"zvl256b", "zvl128b",  check_implicit_always},
1219
  {"zvl128b", "zvl64b",   check_implicit_always},
1220
  {"zvl64b", "zvl32b",    check_implicit_always},
1221
  {"zicntr", "zicsr",   check_implicit_always},
1222
  {"zihpm", "zicsr",    check_implicit_always},
1223
  {"zcd", "d",    check_implicit_always},
1224
  {"zcf", "f",    check_implicit_always},
1225
  {"zfa", "f",    check_implicit_always},
1226
  {"d", "f",    check_implicit_always},
1227
  {"zfh", "zfhmin", check_implicit_always},
1228
  {"zfhmin", "f", check_implicit_always},
1229
  {"f", "zicsr",  check_implicit_always},
1230
  {"zqinx", "zdinx",  check_implicit_always},
1231
  {"zdinx", "zfinx",  check_implicit_always},
1232
  {"zhinx", "zhinxmin", check_implicit_always},
1233
  {"zhinxmin", "zfinx", check_implicit_always},
1234
  {"zfinx", "zicsr",  check_implicit_always},
1235
  {"zk", "zkn",   check_implicit_always},
1236
  {"zk", "zkr",   check_implicit_always},
1237
  {"zk", "zkt",   check_implicit_always},
1238
  {"zkn", "zbkb", check_implicit_always},
1239
  {"zkn", "zbkc", check_implicit_always},
1240
  {"zkn", "zbkx", check_implicit_always},
1241
  {"zkn", "zkne", check_implicit_always},
1242
  {"zkn", "zknd", check_implicit_always},
1243
  {"zkn", "zknh", check_implicit_always},
1244
  {"zks", "zbkb", check_implicit_always},
1245
  {"zks", "zbkc", check_implicit_always},
1246
  {"zks", "zbkx", check_implicit_always},
1247
  {"zks", "zksed",  check_implicit_always},
1248
  {"zks", "zksh", check_implicit_always},
1249
  {"zvbb", "zvkb",  check_implicit_always},
1250
  {"zvkn", "zvkned",  check_implicit_always},
1251
  {"zvkn", "zvknha",  check_implicit_always},
1252
  {"zvkn", "zvknhb",  check_implicit_always},
1253
  {"zvkn", "zvkb",  check_implicit_always},
1254
  {"zvkn", "zvkt",  check_implicit_always},
1255
  {"zvkng", "zvkn", check_implicit_always},
1256
  {"zvkng", "zvkg", check_implicit_always},
1257
  {"zvknc", "zvkn", check_implicit_always},
1258
  {"zvknc", "zvbc", check_implicit_always},
1259
  {"zvks", "zvksed",  check_implicit_always},
1260
  {"zvks", "zvksh", check_implicit_always},
1261
  {"zvks", "zvkb",  check_implicit_always},
1262
  {"zvks", "zvkt",  check_implicit_always},
1263
  {"zvksg", "zvks", check_implicit_always},
1264
  {"zvksg", "zvkg", check_implicit_always},
1265
  {"zvksc", "zvks", check_implicit_always},
1266
  {"zvksc", "zvbc", check_implicit_always},
1267
  {"zcf", "zca",  check_implicit_always},
1268
  {"zcd", "zca",  check_implicit_always},
1269
  {"zcb", "zca",  check_implicit_always},
1270
  {"zcmp", "zca", check_implicit_always},
1271
  {"smaia", "ssaia",    check_implicit_always},
1272
  {"smcntrpmf", "zicsr",  check_implicit_always},
1273
  {"smstateen", "ssstateen",  check_implicit_always},
1274
  {"smepmp", "zicsr",   check_implicit_always},
1275
  {"ssaia", "zicsr",    check_implicit_always},
1276
  {"sscofpmf", "zicsr",   check_implicit_always},
1277
  {"ssstateen", "zicsr",  check_implicit_always},
1278
  {"sstc", "zicsr",   check_implicit_always},
1279
  {"svadu", "zicsr",    check_implicit_always},
1280
  {"b", "zba",    check_implicit_always},
1281
  {"b", "zbb",    check_implicit_always},
1282
  {"b", "zbs",    check_implicit_always},
1283
  {"a", "zaamo",  check_implicit_always},
1284
  {"a", "zalrsc", check_implicit_always},
1285
1286
  {"xsfvcp", "zve32x",  check_implicit_always},
1287
  {NULL, NULL, NULL}
1288
};
1289
1290
/* For default_enable field, decide if the extension should
1291
   be enbaled by default.  */
1292
1293
0
#define EXT_DEFAULT   0x1
1294
1295
/* List all extensions that binutils should know about.  */
1296
1297
struct riscv_supported_ext
1298
{
1299
  const char *name;
1300
  enum riscv_spec_class isa_spec_class;
1301
  int major_version;
1302
  int minor_version;
1303
  unsigned long default_enable;
1304
};
1305
1306
/* The standard extensions must be added in canonical order.  */
1307
1308
static struct riscv_supported_ext riscv_supported_std_ext[] =
1309
{
1310
  {"e",   ISA_SPEC_CLASS_20191213,  1, 9, 0 },
1311
  {"e",   ISA_SPEC_CLASS_20190608,  1, 9, 0 },
1312
  {"e",   ISA_SPEC_CLASS_2P2,   1, 9, 0 },
1313
  {"i",   ISA_SPEC_CLASS_20191213,  2, 1, 0 },
1314
  {"i",   ISA_SPEC_CLASS_20190608,  2, 1, 0 },
1315
  {"i",   ISA_SPEC_CLASS_2P2,   2, 0, 0 },
1316
  /* The g is a special case which we don't want to output it,
1317
     but still need it when adding implicit extensions.  */
1318
  {"g",   ISA_SPEC_CLASS_NONE, RISCV_UNKNOWN_VERSION, RISCV_UNKNOWN_VERSION, EXT_DEFAULT },
1319
  {"m",   ISA_SPEC_CLASS_20191213,  2, 0, 0 },
1320
  {"m",   ISA_SPEC_CLASS_20190608,  2, 0, 0 },
1321
  {"m",   ISA_SPEC_CLASS_2P2,   2, 0, 0 },
1322
  {"a",   ISA_SPEC_CLASS_20191213,  2, 1, 0 },
1323
  {"a",   ISA_SPEC_CLASS_20190608,  2, 0, 0 },
1324
  {"a",   ISA_SPEC_CLASS_2P2,   2, 0, 0 },
1325
  {"f",   ISA_SPEC_CLASS_20191213,  2, 2, 0 },
1326
  {"f",   ISA_SPEC_CLASS_20190608,  2, 2, 0 },
1327
  {"f",   ISA_SPEC_CLASS_2P2,   2, 0, 0 },
1328
  {"d",   ISA_SPEC_CLASS_20191213,  2, 2, 0 },
1329
  {"d",   ISA_SPEC_CLASS_20190608,  2, 2, 0 },
1330
  {"d",   ISA_SPEC_CLASS_2P2,   2, 0, 0 },
1331
  {"q",   ISA_SPEC_CLASS_20191213,  2, 2, 0 },
1332
  {"q",   ISA_SPEC_CLASS_20190608,  2, 2, 0 },
1333
  {"q",   ISA_SPEC_CLASS_2P2,   2, 0, 0 },
1334
  {"c",   ISA_SPEC_CLASS_20191213,  2, 0, 0 },
1335
  {"c",   ISA_SPEC_CLASS_20190608,  2, 0, 0 },
1336
  {"c",   ISA_SPEC_CLASS_2P2,   2, 0, 0 },
1337
  {"b",   ISA_SPEC_CLASS_DRAFT,   1, 0, 0 },
1338
  {"v",   ISA_SPEC_CLASS_DRAFT,   1, 0, 0 },
1339
  {"h",   ISA_SPEC_CLASS_DRAFT,   1, 0, 0 },
1340
  {NULL, 0, 0, 0, 0}
1341
};
1342
1343
static struct riscv_supported_ext riscv_supported_std_z_ext[] =
1344
{
1345
  {"zicbom",    ISA_SPEC_CLASS_DRAFT,   1, 0,  0 },
1346
  {"zicbop",    ISA_SPEC_CLASS_DRAFT,   1, 0,  0 },
1347
  {"zicboz",    ISA_SPEC_CLASS_DRAFT,   1, 0,  0 },
1348
  {"zicond",    ISA_SPEC_CLASS_DRAFT,   1, 0,  0 },
1349
  {"zicntr",    ISA_SPEC_CLASS_DRAFT,   2, 0,  0 },
1350
  {"zicsr",   ISA_SPEC_CLASS_20191213,  2, 0,  0 },
1351
  {"zicsr",   ISA_SPEC_CLASS_20190608,  2, 0,  0 },
1352
  {"zifencei",    ISA_SPEC_CLASS_20191213,  2, 0,  0 },
1353
  {"zifencei",    ISA_SPEC_CLASS_20190608,  2, 0,  0 },
1354
  {"zihintntl",   ISA_SPEC_CLASS_DRAFT,   1, 0,  0 },
1355
  {"zihintpause", ISA_SPEC_CLASS_DRAFT,   2, 0,  0 },
1356
  {"zihpm",   ISA_SPEC_CLASS_DRAFT,   2, 0,  0 },
1357
  {"zmmul",   ISA_SPEC_CLASS_DRAFT,   1, 0,  0 },
1358
  {"zaamo",   ISA_SPEC_CLASS_DRAFT,   1, 0,  0 },
1359
  {"zabha",   ISA_SPEC_CLASS_DRAFT,   1, 0,  0 },
1360
  {"zalrsc",    ISA_SPEC_CLASS_DRAFT,   1, 0,  0 },
1361
  {"zawrs",   ISA_SPEC_CLASS_DRAFT,   1, 0,  0 },
1362
  {"zfa",   ISA_SPEC_CLASS_DRAFT,   1, 0,  0 },
1363
  {"zfh",   ISA_SPEC_CLASS_DRAFT,   1, 0,  0 },
1364
  {"zfhmin",    ISA_SPEC_CLASS_DRAFT,   1, 0,  0 },
1365
  {"zfinx",   ISA_SPEC_CLASS_DRAFT,   1, 0,  0 },
1366
  {"zdinx",   ISA_SPEC_CLASS_DRAFT,   1, 0,  0 },
1367
  {"zqinx",   ISA_SPEC_CLASS_DRAFT,   1, 0,  0 },
1368
  {"zhinx",   ISA_SPEC_CLASS_DRAFT,   1, 0,  0 },
1369
  {"zhinxmin",    ISA_SPEC_CLASS_DRAFT,   1, 0,  0 },
1370
  {"zbb",   ISA_SPEC_CLASS_DRAFT,   1, 0,  0 },
1371
  {"zba",   ISA_SPEC_CLASS_DRAFT,   1, 0,  0 },
1372
  {"zbc",   ISA_SPEC_CLASS_DRAFT,   1, 0,  0 },
1373
  {"zbs",   ISA_SPEC_CLASS_DRAFT,   1, 0,  0 },
1374
  {"zbkb",    ISA_SPEC_CLASS_DRAFT,   1, 0,  0 },
1375
  {"zbkc",    ISA_SPEC_CLASS_DRAFT,   1, 0,  0 },
1376
  {"zbkx",    ISA_SPEC_CLASS_DRAFT,   1, 0,  0 },
1377
  {"zk",    ISA_SPEC_CLASS_DRAFT,   1, 0,  0 },
1378
  {"zkn",   ISA_SPEC_CLASS_DRAFT,   1, 0,  0 },
1379
  {"zknd",    ISA_SPEC_CLASS_DRAFT,   1, 0,  0 },
1380
  {"zkne",    ISA_SPEC_CLASS_DRAFT,   1, 0,  0 },
1381
  {"zknh",    ISA_SPEC_CLASS_DRAFT,   1, 0,  0 },
1382
  {"zkr",   ISA_SPEC_CLASS_DRAFT,   1, 0,  0 },
1383
  {"zks",   ISA_SPEC_CLASS_DRAFT,   1, 0,  0 },
1384
  {"zksed",   ISA_SPEC_CLASS_DRAFT,   1, 0,  0 },
1385
  {"zksh",    ISA_SPEC_CLASS_DRAFT,   1, 0,  0 },
1386
  {"zkt",   ISA_SPEC_CLASS_DRAFT,   1, 0,  0 },
1387
  {"zve32x",    ISA_SPEC_CLASS_DRAFT,   1, 0,  0 },
1388
  {"zve32f",    ISA_SPEC_CLASS_DRAFT,   1, 0,  0 },
1389
  {"zve64x",    ISA_SPEC_CLASS_DRAFT,   1, 0,  0 },
1390
  {"zve64f",    ISA_SPEC_CLASS_DRAFT,   1, 0,  0 },
1391
  {"zve64d",    ISA_SPEC_CLASS_DRAFT,   1, 0,  0 },
1392
  {"zvbb",    ISA_SPEC_CLASS_DRAFT,   1, 0,  0 },
1393
  {"zvbc",    ISA_SPEC_CLASS_DRAFT,   1, 0,  0 },
1394
  {"zvfh",    ISA_SPEC_CLASS_DRAFT,   1, 0,  0 },
1395
  {"zvfhmin",   ISA_SPEC_CLASS_DRAFT,   1, 0,  0 },
1396
  {"zvkb",    ISA_SPEC_CLASS_DRAFT,   1, 0,  0 },
1397
  {"zvkg",    ISA_SPEC_CLASS_DRAFT,   1, 0,  0 },
1398
  {"zvkn",    ISA_SPEC_CLASS_DRAFT,   1, 0,  0 },
1399
  {"zvkng",   ISA_SPEC_CLASS_DRAFT,   1, 0,  0 },
1400
  {"zvknc",   ISA_SPEC_CLASS_DRAFT,   1, 0,  0 },
1401
  {"zvkned",    ISA_SPEC_CLASS_DRAFT,   1, 0,  0 },
1402
  {"zvknha",    ISA_SPEC_CLASS_DRAFT,   1, 0,  0 },
1403
  {"zvknhb",    ISA_SPEC_CLASS_DRAFT,   1, 0,  0 },
1404
  {"zvksed",    ISA_SPEC_CLASS_DRAFT,   1, 0,  0 },
1405
  {"zvksh",   ISA_SPEC_CLASS_DRAFT,   1, 0,  0 },
1406
  {"zvks",    ISA_SPEC_CLASS_DRAFT,   1, 0,  0 },
1407
  {"zvksg",   ISA_SPEC_CLASS_DRAFT,   1, 0,  0 },
1408
  {"zvksc",   ISA_SPEC_CLASS_DRAFT,   1, 0,  0 },
1409
  {"zvkt",    ISA_SPEC_CLASS_DRAFT,   1, 0,  0 },
1410
  {"zvl32b",    ISA_SPEC_CLASS_DRAFT,   1, 0,  0 },
1411
  {"zvl64b",    ISA_SPEC_CLASS_DRAFT,   1, 0,  0 },
1412
  {"zvl128b",   ISA_SPEC_CLASS_DRAFT,   1, 0,  0 },
1413
  {"zvl256b",   ISA_SPEC_CLASS_DRAFT,   1, 0,  0 },
1414
  {"zvl512b",   ISA_SPEC_CLASS_DRAFT,   1, 0,  0 },
1415
  {"zvl1024b",    ISA_SPEC_CLASS_DRAFT,   1, 0,  0 },
1416
  {"zvl2048b",    ISA_SPEC_CLASS_DRAFT,   1, 0,  0 },
1417
  {"zvl4096b",    ISA_SPEC_CLASS_DRAFT,   1, 0,  0 },
1418
  {"zvl8192b",    ISA_SPEC_CLASS_DRAFT,   1, 0,  0 },
1419
  {"zvl16384b",   ISA_SPEC_CLASS_DRAFT,   1, 0,  0 },
1420
  {"zvl32768b",   ISA_SPEC_CLASS_DRAFT,   1, 0,  0 },
1421
  {"zvl65536b",   ISA_SPEC_CLASS_DRAFT,   1, 0,  0 },
1422
  {"ztso",    ISA_SPEC_CLASS_DRAFT,   1, 0,  0 },
1423
  {"zca",   ISA_SPEC_CLASS_DRAFT,   1, 0,  0 },
1424
  {"zcb",   ISA_SPEC_CLASS_DRAFT,   1, 0,  0 },
1425
  {"zcf",   ISA_SPEC_CLASS_DRAFT,   1, 0,  0 },
1426
  {"zcd",   ISA_SPEC_CLASS_DRAFT,   1, 0,  0 },
1427
  {"zcmp",    ISA_SPEC_CLASS_DRAFT,   1, 0,  0 },
1428
  {NULL, 0, 0, 0, 0}
1429
};
1430
1431
static struct riscv_supported_ext riscv_supported_std_s_ext[] =
1432
{
1433
  {"smaia",   ISA_SPEC_CLASS_DRAFT,   1, 0, 0 },
1434
  {"smcntrpmf",   ISA_SPEC_CLASS_DRAFT,   1, 0, 0 },
1435
  {"smepmp",    ISA_SPEC_CLASS_DRAFT,   1, 0, 0 },
1436
  {"smstateen",   ISA_SPEC_CLASS_DRAFT,   1, 0, 0 },
1437
  {"ssaia",   ISA_SPEC_CLASS_DRAFT,   1, 0, 0 },
1438
  {"sscofpmf",    ISA_SPEC_CLASS_DRAFT,   1, 0, 0 },
1439
  {"ssstateen",   ISA_SPEC_CLASS_DRAFT,   1, 0, 0 },
1440
  {"sstc",    ISA_SPEC_CLASS_DRAFT,   1, 0, 0 },
1441
  {"svadu",   ISA_SPEC_CLASS_DRAFT,   1, 0, 0 },
1442
  {"svinval",   ISA_SPEC_CLASS_DRAFT,   1, 0, 0 },
1443
  {"svnapot",   ISA_SPEC_CLASS_DRAFT,   1, 0, 0 },
1444
  {"svpbmt",    ISA_SPEC_CLASS_DRAFT,   1, 0, 0 },
1445
  {NULL, 0, 0, 0, 0}
1446
};
1447
1448
static struct riscv_supported_ext riscv_supported_std_zxm_ext[] =
1449
{
1450
  {NULL, 0, 0, 0, 0}
1451
};
1452
1453
static struct riscv_supported_ext riscv_supported_vendor_x_ext[] =
1454
{
1455
  {"xcvmac",    ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1456
  {"xcvalu",    ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1457
  {"xtheadba",    ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1458
  {"xtheadbb",    ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1459
  {"xtheadbs",    ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1460
  {"xtheadcmo",   ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1461
  {"xtheadcondmov", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1462
  {"xtheadfmemidx", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1463
  {"xtheadfmv",   ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1464
  {"xtheadint",   ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1465
  {"xtheadmac",   ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1466
  {"xtheadmemidx",  ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1467
  {"xtheadmempair", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1468
  {"xtheadsync",  ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1469
  {"xtheadvector",  ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1470
  {"xtheadzvamo", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1471
  {"xventanacondops", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1472
  {"xsfvcp",    ISA_SPEC_CLASS_DRAFT, 1, 0, 0},
1473
  {NULL, 0, 0, 0, 0}
1474
};
1475
1476
const struct riscv_supported_ext *riscv_all_supported_ext[] =
1477
{
1478
  riscv_supported_std_ext,
1479
  riscv_supported_std_z_ext,
1480
  riscv_supported_std_s_ext,
1481
  riscv_supported_std_zxm_ext,
1482
  riscv_supported_vendor_x_ext,
1483
  NULL
1484
};
1485
1486
/* ISA extension prefixed name class.  Must define them in parsing order.  */
1487
enum riscv_prefix_ext_class
1488
{
1489
  RV_ISA_CLASS_Z = 1,
1490
  RV_ISA_CLASS_S,
1491
  RV_ISA_CLASS_ZXM,
1492
  RV_ISA_CLASS_X,
1493
  RV_ISA_CLASS_SINGLE
1494
};
1495
1496
/* Record the strings of the prefixed extensions, and their corresponding
1497
   classes.  The more letters of the prefix string, the more forward it must
1498
   be defined.  Otherwise, the riscv_get_prefix_class will map it to the
1499
   wrong classes.  */
1500
struct riscv_parse_prefix_config
1501
{
1502
  /* Class of the extension. */
1503
  enum riscv_prefix_ext_class class;
1504
1505
  /* Prefix string for error printing and internal parser usage.  */
1506
  const char *prefix;
1507
};
1508
static const struct riscv_parse_prefix_config parse_config[] =
1509
{
1510
  {RV_ISA_CLASS_ZXM, "zxm"},
1511
  {RV_ISA_CLASS_Z, "z"},
1512
  {RV_ISA_CLASS_S, "s"},
1513
  {RV_ISA_CLASS_X, "x"},
1514
  {RV_ISA_CLASS_SINGLE, NULL}
1515
};
1516
1517
/* Get the prefixed name class for the extensions, the class also
1518
   means the order of the prefixed extensions.  */
1519
1520
static enum riscv_prefix_ext_class
1521
riscv_get_prefix_class (const char *arch)
1522
3.61M
{
1523
3.61M
  int i = 0;
1524
9.96M
  while (parse_config[i].class != RV_ISA_CLASS_SINGLE)
1525
9.07M
    {
1526
9.07M
      if (strncmp (arch, parse_config[i].prefix,
1527
9.07M
       strlen (parse_config[i].prefix)) == 0)
1528
2.72M
  return parse_config[i].class;
1529
6.34M
      i++;
1530
6.34M
    }
1531
896k
  return RV_ISA_CLASS_SINGLE;
1532
3.61M
}
1533
1534
/* Check KNOWN_EXTS to see if the EXT is supported.  */
1535
1536
static bool
1537
riscv_known_prefixed_ext (const char *ext,
1538
        struct riscv_supported_ext *known_exts)
1539
0
{
1540
0
  size_t i;
1541
0
  for (i = 0; known_exts[i].name != NULL; ++i)
1542
0
    if (strcmp (ext, known_exts[i].name) == 0)
1543
0
      return true;
1544
0
  return false;
1545
0
}
1546
1547
/* Check whether the prefixed extension is recognized or not.  Return
1548
   true if recognized, otehrwise return false.  */
1549
1550
static bool
1551
riscv_recognized_prefixed_ext (const char *ext)
1552
0
{
1553
0
  enum riscv_prefix_ext_class class = riscv_get_prefix_class (ext);
1554
0
  switch (class)
1555
0
  {
1556
0
  case RV_ISA_CLASS_Z:
1557
0
    return riscv_known_prefixed_ext (ext, riscv_supported_std_z_ext);
1558
0
  case RV_ISA_CLASS_ZXM:
1559
0
    return riscv_known_prefixed_ext (ext, riscv_supported_std_zxm_ext);
1560
0
  case RV_ISA_CLASS_S:
1561
0
    return riscv_known_prefixed_ext (ext, riscv_supported_std_s_ext);
1562
0
  case RV_ISA_CLASS_X:
1563
    /* Only the single x is unrecognized.  */
1564
0
    if (strcmp (ext, "x") != 0)
1565
0
      return true;
1566
0
  default:
1567
0
    break;
1568
0
  }
1569
0
  return false;
1570
0
}
1571
1572
/* Canonical order for single letter extensions.  */
1573
static const char riscv_ext_canonical_order[] = "eigmafdqlcbkjtpvnh";
1574
1575
/* Array is used to compare the orders of standard extensions quickly.  */
1576
static int riscv_ext_order[26] = {0};
1577
1578
/* Init the riscv_ext_order array.  */
1579
1580
static void
1581
riscv_init_ext_order (void)
1582
669
{
1583
669
  static bool inited = false;
1584
669
  if (inited)
1585
667
    return;
1586
1587
  /* The orders of all standard extensions are positive.  */
1588
2
  int order = 1;
1589
1590
38
  for (const char *ext = &riscv_ext_canonical_order[0]; *ext; ++ext)
1591
36
    riscv_ext_order[(*ext - 'a')] = order++;
1592
1593
  /* Some of the prefixed keyword are not single letter, so we set
1594
     their prefixed orders in the riscv_compare_subsets directly,
1595
     not through the riscv_ext_order.  */
1596
1597
2
  inited = true;
1598
2
}
1599
1600
/* Similar to the strcmp.  It returns an integer less than, equal to,
1601
   or greater than zero if `subset2` is found, respectively, to be less
1602
   than, to match, or be greater than `subset1`.
1603
1604
   The order values,
1605
   Zero: Preserved keywords.
1606
   Positive number: Standard extensions.
1607
   Negative number: Prefixed keywords.  */
1608
1609
int
1610
riscv_compare_subsets (const char *subset1, const char *subset2)
1611
6.12M
{
1612
6.12M
  int order1 = riscv_ext_order[(*subset1 - 'a')];
1613
6.12M
  int order2 = riscv_ext_order[(*subset2 - 'a')];
1614
1615
  /* Compare the standard extension first.  */
1616
6.12M
  if (order1 > 0 && order2 > 0)
1617
4.32M
    return order1 - order2;
1618
1619
  /* Set the prefixed orders to negative numbers.  */
1620
1.80M
  enum riscv_prefix_ext_class class1 = riscv_get_prefix_class (subset1);
1621
1.80M
  enum riscv_prefix_ext_class class2 = riscv_get_prefix_class (subset2);
1622
1623
1.80M
  if (class1 != RV_ISA_CLASS_SINGLE)
1624
1.60M
    order1 = - (int) class1;
1625
1.80M
  if (class2 != RV_ISA_CLASS_SINGLE)
1626
1.11M
    order2 = - (int) class2;
1627
1628
1.80M
  if (order1 == order2)
1629
886k
    {
1630
      /* Compare the standard addition z extensions.  */
1631
886k
      if (class1 == RV_ISA_CLASS_Z)
1632
886k
  {
1633
886k
    order1 = riscv_ext_order[(*++subset1 - 'a')];
1634
886k
    order2 = riscv_ext_order[(*++subset2 - 'a')];
1635
886k
    if (order1 != order2)
1636
837k
      return order1 - order2;
1637
886k
  }
1638
48.6k
      return strcasecmp (++subset1, ++subset2);
1639
886k
    }
1640
1641
918k
  return order2 - order1;
1642
1.80M
}
1643
1644
/* Find subset in the list.  Return TRUE and set `current` to the subset
1645
   if it is found.  Otherwise, return FALSE and set `current` to the place
1646
   where we should insert the subset.  However, return FALSE with the NULL
1647
   `current` means we should insert the subset at the head of subset list,
1648
   if needed.  */
1649
1650
bool
1651
riscv_lookup_subset (const riscv_subset_list_t *subset_list,
1652
         const char *subset,
1653
         riscv_subset_t **current)
1654
1.58M
{
1655
1.58M
  riscv_subset_t *s, *pre_s = NULL;
1656
1657
  /* If the subset is added in order, then just add it at the tail.  */
1658
1.58M
  if (subset_list->tail != NULL
1659
1.58M
      && riscv_compare_subsets (subset_list->tail->name, subset) < 0)
1660
842k
    {
1661
842k
      *current = subset_list->tail;
1662
842k
      return false;
1663
842k
    }
1664
1665
742k
  for (s = subset_list->head;
1666
4.54M
       s != NULL;
1667
3.79M
       pre_s = s, s = s->next)
1668
4.54M
    {
1669
4.54M
      int cmp = riscv_compare_subsets (s->name, subset);
1670
4.54M
      if (cmp == 0)
1671
696k
  {
1672
696k
    *current = s;
1673
696k
    return true;
1674
696k
  }
1675
3.84M
      else if (cmp > 0)
1676
45.6k
  break;
1677
4.54M
    }
1678
46.3k
  *current = pre_s;
1679
1680
46.3k
  return false;
1681
742k
}
1682
1683
/* Add the extension to the subset list.  Search the
1684
   list first, and then find the right place to add.  */
1685
1686
void
1687
riscv_add_subset (riscv_subset_list_t *subset_list,
1688
      const char *subset,
1689
      int major,
1690
      int minor)
1691
8.02k
{
1692
8.02k
  riscv_subset_t *current, *new;
1693
1694
8.02k
  if (riscv_lookup_subset (subset_list, subset, &current))
1695
0
    return;
1696
1697
8.02k
  new = xmalloc (sizeof *new);
1698
8.02k
  new->name = xstrdup (subset);
1699
8.02k
  new->major_version = major;
1700
8.02k
  new->minor_version = minor;
1701
8.02k
  new->next = NULL;
1702
1703
8.02k
  if (current != NULL)
1704
6.69k
    {
1705
6.69k
      new->next = current->next;
1706
6.69k
      current->next = new;
1707
6.69k
    }
1708
1.33k
  else
1709
1.33k
    {
1710
1.33k
      new->next = subset_list->head;
1711
1.33k
      subset_list->head = new;
1712
1.33k
    }
1713
1714
8.02k
  if (new->next == NULL)
1715
4.68k
    subset_list->tail = new;
1716
8.02k
}
1717
1718
/* Get the default versions from the riscv_supported_*ext tables.  */
1719
1720
static void
1721
riscv_get_default_ext_version (enum riscv_spec_class *default_isa_spec,
1722
             const char *name,
1723
             int *major_version,
1724
             int *minor_version)
1725
8.02k
{
1726
8.02k
  if (name == NULL
1727
8.02k
      || default_isa_spec == NULL
1728
8.02k
      || *default_isa_spec == ISA_SPEC_CLASS_NONE)
1729
0
    return;
1730
1731
8.02k
  struct riscv_supported_ext *table = NULL;
1732
8.02k
  enum riscv_prefix_ext_class class = riscv_get_prefix_class (name);
1733
8.02k
  switch (class)
1734
8.02k
    {
1735
0
    case RV_ISA_CLASS_ZXM: table = riscv_supported_std_zxm_ext; break;
1736
3.34k
    case RV_ISA_CLASS_Z: table = riscv_supported_std_z_ext; break;
1737
0
    case RV_ISA_CLASS_S: table = riscv_supported_std_s_ext; break;
1738
0
    case RV_ISA_CLASS_X: table = riscv_supported_vendor_x_ext; break;
1739
4.68k
    default:
1740
4.68k
      table = riscv_supported_std_ext;
1741
8.02k
    }
1742
1743
8.02k
  int i = 0;
1744
109k
  while (table != NULL && table[i].name != NULL)
1745
108k
    {
1746
108k
      if (strcmp (table[i].name, name) == 0
1747
108k
    && (table[i].isa_spec_class == ISA_SPEC_CLASS_DRAFT
1748
8.02k
        || table[i].isa_spec_class == *default_isa_spec))
1749
7.35k
  {
1750
7.35k
    *major_version = table[i].major_version;
1751
7.35k
    *minor_version = table[i].minor_version;
1752
7.35k
    return;
1753
7.35k
  }
1754
101k
      i++;
1755
101k
    }
1756
8.02k
}
1757
1758
/* Find the default versions for the extension before adding them to
1759
   the subset list, if their versions are RISCV_UNKNOWN_VERSION.
1760
   Afterwards, report errors if we can not find their default versions.  */
1761
1762
static void
1763
riscv_parse_add_subset (riscv_parse_subset_t *rps,
1764
      const char *subset,
1765
      int major,
1766
      int minor,
1767
      bool implicit)
1768
8.02k
{
1769
8.02k
  int major_version = major;
1770
8.02k
  int minor_version = minor;
1771
1772
8.02k
  if (major_version == RISCV_UNKNOWN_VERSION
1773
8.02k
       || minor_version == RISCV_UNKNOWN_VERSION)
1774
8.02k
    riscv_get_default_ext_version (rps->isa_spec, subset,
1775
8.02k
           &major_version, &minor_version);
1776
1777
  /* We don't care the versions of the implicit extensions.  */
1778
8.02k
  if (!implicit
1779
8.02k
      && (major_version == RISCV_UNKNOWN_VERSION
1780
669
    || minor_version == RISCV_UNKNOWN_VERSION))
1781
0
    {
1782
0
      if (subset[0] == 'x')
1783
0
  rps->error_handler
1784
0
    (_("x ISA extension `%s' must be set with the versions"),
1785
0
     subset);
1786
      /* Allow old ISA spec can recognize zicsr and zifencei.  */
1787
0
      else if (strcmp (subset, "zicsr") != 0
1788
0
         && strcmp (subset, "zifencei") != 0)
1789
0
  rps->error_handler
1790
0
    (_("cannot find default versions of the ISA extension `%s'"),
1791
0
     subset);
1792
0
      return;
1793
0
    }
1794
1795
8.02k
  riscv_add_subset (rps->subset_list, subset,
1796
8.02k
        major_version, minor_version);
1797
8.02k
}
1798
1799
/* Release subset list.  */
1800
1801
void
1802
riscv_release_subset_list (riscv_subset_list_t *subset_list)
1803
1.33k
{
1804
9.36k
   while (subset_list->head != NULL)
1805
8.02k
    {
1806
8.02k
      riscv_subset_t *next = subset_list->head->next;
1807
8.02k
      free ((void *)subset_list->head->name);
1808
8.02k
      free (subset_list->head);
1809
8.02k
      subset_list->head = next;
1810
8.02k
    }
1811
1812
1.33k
  subset_list->tail = NULL;
1813
1814
1.33k
  if (subset_list->arch_str != NULL)
1815
0
    {
1816
0
      free ((void*) subset_list->arch_str);
1817
0
      subset_list->arch_str = NULL;
1818
0
    }
1819
1.33k
}
1820
1821
/* Parsing extension version.
1822
1823
   Return Value:
1824
     Points to the end of version
1825
1826
   Arguments:
1827
     `p`: Curent parsing position.
1828
     `major_version`: Parsed major version.
1829
     `minor_version`: Parsed minor version.  */
1830
1831
static const char *
1832
riscv_parsing_subset_version (const char *p,
1833
            int *major_version,
1834
            int *minor_version)
1835
1.33k
{
1836
1.33k
  bool major_p = true;
1837
1.33k
  int version = 0;
1838
1.33k
  char np;
1839
1840
1.33k
  *major_version = 0;
1841
1.33k
  *minor_version = 0;
1842
1.33k
  for (; *p; ++p)
1843
669
    {
1844
669
      if (*p == 'p')
1845
0
  {
1846
0
    np = *(p + 1);
1847
1848
    /* Might be beginning of `p` extension.  */
1849
0
    if (!ISDIGIT (np))
1850
0
      break;
1851
1852
0
    *major_version = version;
1853
0
    major_p = false;
1854
0
    version = 0;
1855
0
  }
1856
669
      else if (ISDIGIT (*p))
1857
0
  version = (version * 10) + (*p - '0');
1858
669
      else
1859
669
  break;
1860
669
    }
1861
1862
1.33k
  if (major_p)
1863
1.33k
    *major_version = version;
1864
0
  else
1865
0
    *minor_version = version;
1866
1867
  /* We can not find any version in string.  */
1868
1.33k
  if (*major_version == 0 && *minor_version == 0)
1869
1.33k
    {
1870
1.33k
      *major_version = RISCV_UNKNOWN_VERSION;
1871
1.33k
      *minor_version = RISCV_UNKNOWN_VERSION;
1872
1.33k
    }
1873
1874
1.33k
  return p;
1875
1.33k
}
1876
1877
/* Parsing function for both standard and prefixed extensions.
1878
1879
   Return Value:
1880
     Points to the end of extensions.
1881
1882
   Arguments:
1883
     `rps`: Hooks and status for parsing extensions.
1884
     `arch`: Full ISA string.
1885
     `p`: Curent parsing position.  */
1886
1887
static const char *
1888
riscv_parse_extensions (riscv_parse_subset_t *rps,
1889
      const char *arch,
1890
      const char *p)
1891
669
{
1892
  /* First letter must start with i, e or g.  */
1893
669
  if (*p != 'e' && *p != 'i' && *p != 'g')
1894
0
    {
1895
0
      rps->error_handler
1896
0
  (_("%s: first ISA extension must be `e', `i' or `g'"),
1897
0
   arch);
1898
0
      return NULL;
1899
0
    }
1900
1901
2.00k
  while (*p != '\0')
1902
1.33k
    {
1903
1.33k
      if (*p == '_')
1904
0
  {
1905
0
    p++;
1906
0
    continue;
1907
0
  }
1908
1909
1.33k
      char *subset = xstrdup (p);
1910
1.33k
      char *q = subset; /* Start of version.  */
1911
1.33k
      const char *end_of_version;
1912
1.33k
      bool implicit = false;
1913
1914
1.33k
      enum riscv_prefix_ext_class class = riscv_get_prefix_class (p);
1915
1.33k
      if (class == RV_ISA_CLASS_SINGLE)
1916
1.33k
  {
1917
1.33k
    if (riscv_ext_order[(*subset - 'a')] == 0)
1918
0
      {
1919
0
        rps->error_handler
1920
0
    (_("%s: unknown standard ISA extension or prefix class `%c'"),
1921
0
     arch, *subset);
1922
0
        free (subset);
1923
0
        return NULL;
1924
0
      }
1925
1.33k
    q++;
1926
1.33k
  }
1927
0
      else
1928
0
  {
1929
    /* Extract the whole prefixed extension by '_'.  */
1930
0
    while (*++q != '\0' && *q != '_')
1931
0
      ;
1932
    /* Look forward to the first letter which is not <major>p<minor>.  */
1933
0
    bool find_any_version = false;
1934
0
    bool find_minor_version = false;
1935
0
    while (1)
1936
0
      {
1937
0
        q--;
1938
0
        if (ISDIGIT (*q))
1939
0
    find_any_version = true;
1940
0
        else if (find_any_version
1941
0
           && !find_minor_version
1942
0
           && *q == 'p'
1943
0
           && ISDIGIT (*(q - 1)))
1944
0
        find_minor_version = true;
1945
0
        else
1946
0
    break;
1947
0
      }
1948
0
    q++;
1949
1950
    /* Check if the end of extension is 'p' or not.  If yes, then
1951
       the second letter from the end cannot be number.  */
1952
0
    if (*(q - 1) == 'p' && ISDIGIT (*(q - 2)))
1953
0
      {
1954
0
        *q = '\0';
1955
0
        rps->error_handler
1956
0
    (_("%s: invalid prefixed ISA extension `%s' ends with <number>p"),
1957
0
     arch, subset);
1958
0
        free (subset);
1959
0
        return NULL;
1960
0
      }
1961
0
  }
1962
1963
1.33k
      int major_version = RISCV_UNKNOWN_VERSION;
1964
1.33k
      int minor_version = RISCV_UNKNOWN_VERSION;
1965
1.33k
      end_of_version =
1966
1.33k
  riscv_parsing_subset_version (q, &major_version, &minor_version);
1967
1.33k
      *q = '\0';
1968
1.33k
      if (end_of_version == NULL)
1969
0
  {
1970
0
    free (subset);
1971
0
    return NULL;
1972
0
  }
1973
1974
      /* Check if the prefixed extension name is well-formed.  */
1975
1.33k
      if (class != RV_ISA_CLASS_SINGLE
1976
1.33k
    && rps->check_unknown_prefixed_ext
1977
1.33k
    && !riscv_recognized_prefixed_ext (subset))
1978
0
  {
1979
0
    rps->error_handler
1980
0
      (_("%s: unknown prefixed ISA extension `%s'"),
1981
0
       arch, subset);
1982
0
    free (subset);
1983
0
    return NULL;
1984
0
  }
1985
1986
      /* Added g as an implicit extension.  */
1987
1.33k
      if (class == RV_ISA_CLASS_SINGLE
1988
1.33k
    && strcmp (subset, "g") == 0)
1989
669
  {
1990
669
    implicit = true;
1991
669
    major_version = RISCV_UNKNOWN_VERSION;
1992
669
    minor_version = RISCV_UNKNOWN_VERSION;
1993
669
  }
1994
1.33k
      riscv_parse_add_subset (rps, subset,
1995
1.33k
            major_version,
1996
1.33k
            minor_version, implicit);
1997
1.33k
      p += end_of_version - subset;
1998
1.33k
      free (subset);
1999
2000
1.33k
      if (class != RV_ISA_CLASS_SINGLE
2001
1.33k
    && *p != '\0' && *p != '_')
2002
0
  {
2003
0
    rps->error_handler
2004
0
      (_("%s: prefixed ISA extension must separate with _"),
2005
0
       arch);
2006
0
    return NULL;
2007
0
  }
2008
1.33k
    }
2009
2010
669
  return p;
2011
669
}
2012
2013
/* Add the implicit extensions.  */
2014
2015
static void
2016
riscv_parse_add_implicit_subsets (riscv_parse_subset_t *rps)
2017
669
{
2018
669
  struct riscv_implicit_subset *t = riscv_implicit_subsets;
2019
669
  bool finished = false;
2020
8.02k
  while (!finished)
2021
7.35k
    {
2022
7.35k
      finished = true;
2023
255k
      for (; t->subset_name; t++)
2024
254k
  {
2025
254k
    riscv_subset_t *subset = NULL;
2026
254k
    riscv_subset_t *implicit_subset = NULL;
2027
254k
    if (riscv_lookup_subset (rps->subset_list, t->subset_name, &subset)
2028
254k
        && !riscv_lookup_subset (rps->subset_list, t->implicit_name,
2029
60.8k
               &implicit_subset)
2030
254k
        && t->check_func (t->implicit_name, subset))
2031
6.69k
      {
2032
6.69k
        riscv_parse_add_subset (rps, t->implicit_name,
2033
6.69k
              RISCV_UNKNOWN_VERSION,
2034
6.69k
              RISCV_UNKNOWN_VERSION, true);
2035
2036
        /* Restart the loop and pick up any new implications.  */
2037
6.69k
        finished = false;
2038
6.69k
        t = riscv_implicit_subsets;
2039
6.69k
        break;
2040
6.69k
      }
2041
254k
  }
2042
7.35k
    }
2043
669
}
2044
2045
/* Check extensions conflicts.  */
2046
2047
static bool
2048
riscv_parse_check_conflicts (riscv_parse_subset_t *rps)
2049
669
{
2050
669
  riscv_subset_t *subset = NULL;
2051
669
  int xlen = *rps->xlen;
2052
669
  bool no_conflict = true;
2053
2054
669
  if (riscv_subset_supports (rps, "e")
2055
669
      && riscv_subset_supports (rps, "h"))
2056
0
    {
2057
0
      rps->error_handler
2058
0
  (_("rv%de does not support the `h' extension"), xlen);
2059
0
      no_conflict = false;
2060
0
    }
2061
669
  if (riscv_lookup_subset (rps->subset_list, "q", &subset)
2062
669
      && (subset->major_version < 2 || (subset->major_version == 2
2063
0
          && subset->minor_version < 2))
2064
669
      && xlen < 64)
2065
0
    {
2066
0
      rps->error_handler (_("rv%d does not support the `q' extension"), xlen);
2067
0
      no_conflict = false;
2068
0
    }
2069
669
  if (riscv_subset_supports (rps, "zcmp")
2070
669
      && riscv_subset_supports (rps, "zcd"))
2071
0
    {
2072
0
      rps->error_handler
2073
0
  (_("zcmp' is incompatible with `d/zcd' extension"));
2074
0
      no_conflict = false;
2075
0
    }
2076
669
  if (riscv_lookup_subset (rps->subset_list, "zcf", &subset)
2077
669
      && xlen > 32)
2078
0
    {
2079
0
      rps->error_handler
2080
0
  (_("rv%d does not support the `zcf' extension"), xlen);
2081
0
      no_conflict = false;
2082
0
    }
2083
669
  if (riscv_lookup_subset (rps->subset_list, "zfinx", &subset)
2084
669
      && riscv_lookup_subset (rps->subset_list, "f", &subset))
2085
0
    {
2086
0
      rps->error_handler
2087
0
  (_("`zfinx' is conflict with the `f/d/q/zfh/zfhmin' extension"));
2088
0
      no_conflict = false;
2089
0
    }
2090
669
  if (riscv_lookup_subset (rps->subset_list, "xtheadvector", &subset)
2091
669
      && riscv_lookup_subset (rps->subset_list, "v", &subset))
2092
0
    {
2093
0
      rps->error_handler
2094
0
  (_("`xtheadvector' is conflict with the `v' extension"));
2095
0
      no_conflict = false;
2096
0
    }
2097
2098
669
  bool support_zve = false;
2099
669
  bool support_zvl = false;
2100
669
  riscv_subset_t *s = rps->subset_list->head;
2101
8.69k
  for (; s != NULL; s = s->next)
2102
8.02k
    {
2103
8.02k
      if (!support_zve
2104
8.02k
    && strncmp (s->name, "zve", 3) == 0)
2105
0
  support_zve = true;
2106
8.02k
      if (!support_zvl
2107
8.02k
    && strncmp (s->name, "zvl", 3) == 0)
2108
0
  support_zvl = true;
2109
8.02k
      if (support_zve && support_zvl)
2110
0
  break;
2111
8.02k
    }
2112
669
  if (support_zvl && !support_zve)
2113
0
    {
2114
0
      rps->error_handler
2115
0
  (_("zvl*b extensions need to enable either `v' or `zve' extension"));
2116
0
      no_conflict = false;
2117
0
    }
2118
2119
669
  return no_conflict;
2120
669
}
2121
2122
/* Set the default subset list according to the default_enable field
2123
   of riscv_supported_*ext tables.  */
2124
2125
static void
2126
riscv_set_default_arch (riscv_parse_subset_t *rps)
2127
0
{
2128
0
  unsigned long enable = EXT_DEFAULT;
2129
0
  int i, j;
2130
0
  for (i = 0; riscv_all_supported_ext[i] != NULL; i++)
2131
0
    {
2132
0
      const struct riscv_supported_ext *table = riscv_all_supported_ext[i];
2133
0
      for (j = 0; table[j].name != NULL; j++)
2134
0
  {
2135
0
    bool implicit = false;
2136
0
    if (strcmp (table[j].name, "g") == 0)
2137
0
      implicit = true;
2138
0
    if (table[j].default_enable & enable)
2139
0
      riscv_parse_add_subset (rps, table[j].name,
2140
0
            RISCV_UNKNOWN_VERSION,
2141
0
            RISCV_UNKNOWN_VERSION, implicit);
2142
0
  }
2143
0
    }
2144
0
}
2145
2146
/* Function for parsing ISA string.
2147
2148
   Return Value:
2149
     Return TRUE on success.
2150
2151
   Arguments:
2152
     `rps`: Hooks and status for parsing extensions.
2153
     `arch`: Full ISA string.  */
2154
2155
bool
2156
riscv_parse_subset (riscv_parse_subset_t *rps,
2157
        const char *arch)
2158
669
{
2159
669
  const char *p;
2160
2161
  /* Init the riscv_ext_order array to compare the order of extensions
2162
     quickly.  */
2163
669
  riscv_init_ext_order ();
2164
2165
669
  if (arch == NULL)
2166
0
    {
2167
0
      riscv_set_default_arch (rps);
2168
0
      riscv_parse_add_implicit_subsets (rps);
2169
0
      return riscv_parse_check_conflicts (rps);
2170
0
    }
2171
2172
4.68k
  for (p = arch; *p != '\0'; p++)
2173
4.01k
    {
2174
4.01k
      if (ISUPPER (*p))
2175
0
  {
2176
0
    rps->error_handler
2177
0
      (_("%s: ISA string cannot contain uppercase letters"),
2178
0
       arch);
2179
0
    return false;
2180
0
  }
2181
4.01k
    }
2182
2183
669
  p = arch;
2184
669
  if (startswith (p, "rv32"))
2185
0
    {
2186
0
      *rps->xlen = 32;
2187
0
      p += 4;
2188
0
    }
2189
669
  else if (startswith (p, "rv64"))
2190
669
    {
2191
669
      *rps->xlen = 64;
2192
669
      p += 4;
2193
669
    }
2194
0
  else
2195
0
    {
2196
      /* ISA string shouldn't be NULL or empty here.  For linker,
2197
   it might be empty when we failed to merge the ISA string
2198
   in the riscv_merge_attributes.  For assembler, we might
2199
   give an empty string by .attribute arch, "" or -march=.
2200
   However, We have already issued the correct error message
2201
   in another side, so do not issue this error when the ISA
2202
   string is empty.  */
2203
0
      if (strlen (arch))
2204
0
  rps->error_handler (
2205
0
    _("%s: ISA string must begin with rv32 or rv64"),
2206
0
    arch);
2207
0
      return false;
2208
0
    }
2209
2210
  /* Parse single standard and prefixed extensions.  */
2211
669
  if (riscv_parse_extensions (rps, arch, p) == NULL)
2212
0
    return false;
2213
2214
  /* Finally add implicit extensions according to the current
2215
     extensions.  */
2216
669
  riscv_parse_add_implicit_subsets (rps);
2217
2218
  /* Check the conflicts.  */
2219
669
  return riscv_parse_check_conflicts (rps);
2220
669
}
2221
2222
/* Return the number of digits for the input.  */
2223
2224
size_t
2225
riscv_estimate_digit (unsigned num)
2226
0
{
2227
0
  size_t digit = 0;
2228
0
  if (num == 0)
2229
0
    return 1;
2230
2231
0
  for (digit = 0; num ; num /= 10)
2232
0
    digit++;
2233
2234
0
  return digit;
2235
0
}
2236
2237
/* Auxiliary function to estimate string length of subset list.  */
2238
2239
static size_t
2240
riscv_estimate_arch_strlen1 (const riscv_subset_t *subset)
2241
0
{
2242
0
  if (subset == NULL)
2243
0
    return 6; /* For rv32/rv64/rv128 and string terminator.  */
2244
2245
0
  return riscv_estimate_arch_strlen1 (subset->next)
2246
0
   + strlen (subset->name)
2247
0
   + riscv_estimate_digit (subset->major_version)
2248
0
   + 1 /* For version seperator 'p'.  */
2249
0
   + riscv_estimate_digit (subset->minor_version)
2250
0
   + 1 /* For underscore.  */;
2251
0
}
2252
2253
/* Estimate the string length of this subset list.  */
2254
2255
static size_t
2256
riscv_estimate_arch_strlen (const riscv_subset_list_t *subset_list)
2257
0
{
2258
0
  return riscv_estimate_arch_strlen1 (subset_list->head);
2259
0
}
2260
2261
/* Auxiliary function to convert subset info to string.  */
2262
2263
static void
2264
riscv_arch_str1 (riscv_subset_t *subset,
2265
     char *attr_str, char *buf, size_t bufsz)
2266
0
{
2267
0
  const char *underline = "_";
2268
0
  riscv_subset_t *subset_t = subset;
2269
2270
0
  if (subset_t == NULL)
2271
0
    return;
2272
2273
  /* No underline between rvXX and i/e.  */
2274
0
  if ((strcasecmp (subset_t->name, "i") == 0)
2275
0
      || (strcasecmp (subset_t->name, "e") == 0))
2276
0
    underline = "";
2277
2278
0
  snprintf (buf, bufsz, "%s%s%dp%d",
2279
0
      underline,
2280
0
      subset_t->name,
2281
0
      subset_t->major_version,
2282
0
      subset_t->minor_version);
2283
2284
0
  strncat (attr_str, buf, bufsz);
2285
2286
  /* Skip 'i' extension after 'e', or skip extensions which
2287
     versions are unknown.  */
2288
0
  while (subset_t->next
2289
0
   && ((strcmp (subset_t->name, "e") == 0
2290
0
        && strcmp (subset_t->next->name, "i") == 0)
2291
0
       || subset_t->next->major_version == RISCV_UNKNOWN_VERSION
2292
0
       || subset_t->next->minor_version == RISCV_UNKNOWN_VERSION))
2293
0
    subset_t = subset_t->next;
2294
2295
0
  riscv_arch_str1 (subset_t->next, attr_str, buf, bufsz);
2296
0
}
2297
2298
/* Convert subset information into string with explicit versions.  */
2299
2300
char *
2301
riscv_arch_str (unsigned xlen, const riscv_subset_list_t *subset)
2302
0
{
2303
0
  size_t arch_str_len = riscv_estimate_arch_strlen (subset);
2304
0
  char *attr_str = xmalloc (arch_str_len);
2305
0
  char *buf = xmalloc (arch_str_len);
2306
2307
0
  snprintf (attr_str, arch_str_len, "rv%u", xlen);
2308
2309
0
  riscv_arch_str1 (subset->head, attr_str, buf, arch_str_len);
2310
0
  free (buf);
2311
2312
0
  return attr_str;
2313
0
}
2314
2315
/* Copy the subset in the subset list.  */
2316
2317
static struct riscv_subset_t *
2318
riscv_copy_subset (riscv_subset_list_t *subset_list,
2319
       riscv_subset_t *subset)
2320
0
{
2321
0
  if (subset == NULL)
2322
0
    return NULL;
2323
2324
0
  riscv_subset_t *new = xmalloc (sizeof *new);
2325
0
  new->name = xstrdup (subset->name);
2326
0
  new->major_version = subset->major_version;
2327
0
  new->minor_version = subset->minor_version;
2328
0
  new->next = riscv_copy_subset (subset_list, subset->next);
2329
2330
0
  if (subset->next == NULL)
2331
0
    subset_list->tail = new;
2332
2333
0
  return new;
2334
0
}
2335
2336
/* Copy the subset list.  */
2337
2338
riscv_subset_list_t *
2339
riscv_copy_subset_list (riscv_subset_list_t *subset_list)
2340
0
{
2341
0
  riscv_subset_list_t *new = xmalloc (sizeof *new);
2342
0
  new->head = riscv_copy_subset (new, subset_list->head);
2343
0
  new->arch_str = strdup (subset_list->arch_str);
2344
0
  return new;
2345
0
}
2346
2347
/* Remove the SUBSET from the subset list.  */
2348
2349
static void
2350
riscv_remove_subset (riscv_subset_list_t *subset_list,
2351
         const char *subset)
2352
0
{
2353
0
  riscv_subset_t *current = subset_list->head;
2354
0
  riscv_subset_t *pre = NULL;
2355
0
  for (; current != NULL; pre = current, current = current->next)
2356
0
    {
2357
0
      if (strcmp (current->name, subset) == 0)
2358
0
  {
2359
0
    if (pre == NULL)
2360
0
      subset_list->head = current->next;
2361
0
    else
2362
0
      pre->next = current->next;
2363
0
    if (current->next == NULL)
2364
0
      subset_list->tail = pre;
2365
0
    free ((void *) current->name);
2366
0
    free (current);
2367
0
    break;
2368
0
  }
2369
0
    }
2370
0
}
2371
2372
/* Add/Remove an extension to/from the subset list.  This is used for
2373
   the .option rvc or norvc, and .option arch directives.  */
2374
2375
bool
2376
riscv_update_subset (riscv_parse_subset_t *rps,
2377
         const char *str)
2378
0
{
2379
0
  const char *p = str;
2380
2381
0
  do
2382
0
    {
2383
0
      int major_version = RISCV_UNKNOWN_VERSION;
2384
0
      int minor_version = RISCV_UNKNOWN_VERSION;
2385
2386
0
      bool removed = false;
2387
0
      switch (*p)
2388
0
  {
2389
0
  case '+': removed = false; break;
2390
0
  case '-': removed = true; break;
2391
0
  default:
2392
0
    riscv_release_subset_list (rps->subset_list);
2393
0
    return riscv_parse_subset (rps, p);
2394
0
  }
2395
0
      ++p;
2396
2397
0
      char *subset = xstrdup (p);
2398
0
      char *q = subset;
2399
0
      const char *end_of_version;
2400
      /* Extract the whole prefixed extension by ','.  */
2401
0
      while (*q != '\0' && *q != ',')
2402
0
        q++;
2403
2404
      /* Look forward to the first letter which is not <major>p<minor>.  */
2405
0
      bool find_any_version = false;
2406
0
      bool find_minor_version = false;
2407
0
      size_t len = q - subset;
2408
0
      size_t i;
2409
0
      for (i = len; i > 0; i--)
2410
0
        {
2411
0
    q--;
2412
0
    if (ISDIGIT (*q))
2413
0
      find_any_version = true;
2414
0
    else if (find_any_version
2415
0
       && !find_minor_version
2416
0
       && *q == 'p'
2417
0
       && ISDIGIT (*(q - 1)))
2418
0
      find_minor_version = true;
2419
0
    else
2420
0
      break;
2421
0
  }
2422
0
      if (len > 0)
2423
0
  q++;
2424
2425
      /* Check if the end of extension is 'p' or not.  If yes, then
2426
   the second letter from the end cannot be number.  */
2427
0
      if (len > 1 && *(q - 1) == 'p' && ISDIGIT (*(q - 2)))
2428
0
  {
2429
0
    *q = '\0';
2430
0
    rps->error_handler
2431
0
      (_("invalid ISA extension ends with <number>p "
2432
0
         "in .option arch `%s'"), str);
2433
0
    free (subset);
2434
0
    return false;
2435
0
  }
2436
2437
0
      end_of_version =
2438
0
  riscv_parsing_subset_version (q, &major_version, &minor_version);
2439
0
      *q = '\0';
2440
0
      if (end_of_version == NULL)
2441
0
  {
2442
0
    free (subset);
2443
0
    return false;
2444
0
  }
2445
2446
0
      if (strlen (subset) == 0
2447
0
    || (strlen (subset) == 1
2448
0
        && riscv_ext_order[(*subset - 'a')] == 0)
2449
0
    || (strlen (subset) > 1
2450
0
        && rps->check_unknown_prefixed_ext
2451
0
        && !riscv_recognized_prefixed_ext (subset)))
2452
0
  {
2453
0
    rps->error_handler
2454
0
      (_("unknown ISA extension `%s' in .option arch `%s'"),
2455
0
       subset, str);
2456
0
    free (subset);
2457
0
    return false;
2458
0
  }
2459
2460
0
      if (strcmp (subset, "i") == 0
2461
0
    || strcmp (subset, "e") == 0
2462
0
    || strcmp (subset, "g") == 0)
2463
0
  {
2464
0
    rps->error_handler
2465
0
      (_("cannot + or - base extension `%s' in .option "
2466
0
         "arch `%s'"), subset, str);
2467
0
    free (subset);
2468
0
    return false;
2469
0
  }
2470
2471
0
      if (removed)
2472
0
  riscv_remove_subset (rps->subset_list, subset);
2473
0
      else
2474
0
  riscv_parse_add_subset (rps, subset, major_version, minor_version, true);
2475
0
      p += end_of_version - subset;
2476
0
      free (subset);
2477
0
    }
2478
0
  while (*p++ == ',');
2479
2480
0
  riscv_parse_add_implicit_subsets (rps);
2481
0
  return riscv_parse_check_conflicts (rps);
2482
0
}
2483
2484
/* Check if the FEATURE subset is supported or not in the subset list.
2485
   Return true if it is supported; Otherwise, return false.  */
2486
2487
bool
2488
riscv_subset_supports (riscv_parse_subset_t *rps,
2489
           const char *feature)
2490
1.25M
{
2491
1.25M
  struct riscv_subset_t *subset;
2492
1.25M
  return riscv_lookup_subset (rps->subset_list, feature, &subset);
2493
1.25M
}
2494
2495
/* Each instuction is belonged to an instruction class INSN_CLASS_*.
2496
   Call riscv_subset_supports to make sure if the instuction is valid.  */
2497
2498
bool
2499
riscv_multi_subset_supports (riscv_parse_subset_t *rps,
2500
           enum riscv_insn_class insn_class)
2501
539k
{
2502
539k
  switch (insn_class)
2503
539k
    {
2504
23.3k
    case INSN_CLASS_I:
2505
23.3k
      return riscv_subset_supports (rps, "i");
2506
6
    case INSN_CLASS_ZICBOM:
2507
6
      return riscv_subset_supports (rps, "zicbom");
2508
1
    case INSN_CLASS_ZICBOP:
2509
1
      return riscv_subset_supports (rps, "zicbop");
2510
0
    case INSN_CLASS_ZICBOZ:
2511
0
      return riscv_subset_supports (rps, "zicboz");
2512
1
    case INSN_CLASS_ZICOND:
2513
1
      return riscv_subset_supports (rps, "zicond");
2514
4.26k
    case INSN_CLASS_ZICSR:
2515
4.26k
      return riscv_subset_supports (rps, "zicsr");
2516
0
    case INSN_CLASS_ZIFENCEI:
2517
0
      return riscv_subset_supports (rps, "zifencei");
2518
0
    case INSN_CLASS_ZIHINTNTL:
2519
0
      return riscv_subset_supports (rps, "zihintntl");
2520
6
    case INSN_CLASS_ZIHINTNTL_AND_C:
2521
6
      return (riscv_subset_supports (rps, "zihintntl")
2522
6
        && (riscv_subset_supports (rps, "c")
2523
0
      || riscv_subset_supports (rps, "zca")));
2524
3
    case INSN_CLASS_ZIHINTPAUSE:
2525
3
      return riscv_subset_supports (rps, "zihintpause");
2526
23
    case INSN_CLASS_M:
2527
23
      return riscv_subset_supports (rps, "m");
2528
48
    case INSN_CLASS_ZMMUL:
2529
48
      return riscv_subset_supports (rps, "zmmul");
2530
318
    case INSN_CLASS_ZAAMO:
2531
318
      return riscv_subset_supports (rps, "zaamo");
2532
290
    case INSN_CLASS_ZABHA:
2533
290
      return riscv_subset_supports (rps, "zabha");
2534
10
    case INSN_CLASS_ZALRSC:
2535
10
      return riscv_subset_supports (rps, "zalrsc");
2536
0
    case INSN_CLASS_ZAWRS:
2537
0
      return riscv_subset_supports (rps, "zawrs");
2538
1.11k
    case INSN_CLASS_F:
2539
1.11k
      return riscv_subset_supports (rps, "f");
2540
403
    case INSN_CLASS_D:
2541
403
      return riscv_subset_supports (rps, "d");
2542
903
    case INSN_CLASS_Q:
2543
903
      return riscv_subset_supports (rps, "q");
2544
388k
    case INSN_CLASS_C:
2545
388k
      return (riscv_subset_supports (rps, "c")
2546
388k
        || riscv_subset_supports (rps, "zca"));
2547
21.1k
    case INSN_CLASS_F_AND_C:
2548
21.1k
      return (riscv_subset_supports (rps, "f")
2549
21.1k
        && (riscv_subset_supports (rps, "c")
2550
21.1k
      || riscv_subset_supports (rps, "zcf")));
2551
61.6k
    case INSN_CLASS_D_AND_C:
2552
61.6k
      return (riscv_subset_supports (rps, "d")
2553
61.6k
        && (riscv_subset_supports (rps, "c")
2554
61.6k
      || riscv_subset_supports (rps, "zcd")));
2555
2.94k
    case INSN_CLASS_F_INX:
2556
2.94k
      return (riscv_subset_supports (rps, "f")
2557
2.94k
        || riscv_subset_supports (rps, "zfinx"));
2558
2.34k
    case INSN_CLASS_D_INX:
2559
2.34k
      return (riscv_subset_supports (rps, "d")
2560
2.34k
        || riscv_subset_supports (rps, "zdinx"));
2561
3.99k
    case INSN_CLASS_Q_INX:
2562
3.99k
      return (riscv_subset_supports (rps, "q")
2563
3.99k
        || riscv_subset_supports (rps, "zqinx"));
2564
1.54k
    case INSN_CLASS_ZFH_INX:
2565
1.54k
      return (riscv_subset_supports (rps, "zfh")
2566
1.54k
        || riscv_subset_supports (rps, "zhinx"));
2567
312
    case INSN_CLASS_ZFHMIN:
2568
312
      return riscv_subset_supports (rps, "zfhmin");
2569
6
    case INSN_CLASS_ZFHMIN_INX:
2570
6
      return (riscv_subset_supports (rps, "zfhmin")
2571
6
        || riscv_subset_supports (rps, "zhinxmin"));
2572
0
    case INSN_CLASS_ZFHMIN_AND_D_INX:
2573
0
      return ((riscv_subset_supports (rps, "zfhmin")
2574
0
         && riscv_subset_supports (rps, "d"))
2575
0
        || (riscv_subset_supports (rps, "zhinxmin")
2576
0
      && riscv_subset_supports (rps, "zdinx")));
2577
0
    case INSN_CLASS_ZFHMIN_AND_Q_INX:
2578
0
      return ((riscv_subset_supports (rps, "zfhmin")
2579
0
         && riscv_subset_supports (rps, "q"))
2580
0
        || (riscv_subset_supports (rps, "zhinxmin")
2581
0
      && riscv_subset_supports (rps, "zqinx")));
2582
3
    case INSN_CLASS_ZFA:
2583
3
      return riscv_subset_supports (rps, "zfa");
2584
22
    case INSN_CLASS_D_AND_ZFA:
2585
22
      return riscv_subset_supports (rps, "d")
2586
22
       && riscv_subset_supports (rps, "zfa");
2587
13
    case INSN_CLASS_Q_AND_ZFA:
2588
13
      return riscv_subset_supports (rps, "q")
2589
13
       && riscv_subset_supports (rps, "zfa");
2590
25
    case INSN_CLASS_ZFH_AND_ZFA:
2591
25
      return riscv_subset_supports (rps, "zfh")
2592
25
       && riscv_subset_supports (rps, "zfa");
2593
0
    case INSN_CLASS_ZFH_OR_ZVFH_AND_ZFA:
2594
0
      return (riscv_subset_supports (rps, "zfh")
2595
0
        || riscv_subset_supports (rps, "zvfh"))
2596
0
       && riscv_subset_supports (rps, "zfa");
2597
15
    case INSN_CLASS_ZBA:
2598
15
      return riscv_subset_supports (rps, "zba");
2599
13
    case INSN_CLASS_ZBB:
2600
13
      return riscv_subset_supports (rps, "zbb");
2601
1
    case INSN_CLASS_ZBC:
2602
1
      return riscv_subset_supports (rps, "zbc");
2603
24
    case INSN_CLASS_ZBS:
2604
24
      return riscv_subset_supports (rps, "zbs");
2605
5
    case INSN_CLASS_ZBKB:
2606
5
      return riscv_subset_supports (rps, "zbkb");
2607
0
    case INSN_CLASS_ZBKC:
2608
0
      return riscv_subset_supports (rps, "zbkc");
2609
28
    case INSN_CLASS_ZBKX:
2610
28
      return riscv_subset_supports (rps, "zbkx");
2611
1
    case INSN_CLASS_ZBB_OR_ZBKB:
2612
1
      return (riscv_subset_supports (rps, "zbb")
2613
1
        || riscv_subset_supports (rps, "zbkb"));
2614
28
    case INSN_CLASS_ZBC_OR_ZBKC:
2615
28
      return (riscv_subset_supports (rps, "zbc")
2616
28
        || riscv_subset_supports (rps, "zbkc"));
2617
11
    case INSN_CLASS_ZKND:
2618
11
      return riscv_subset_supports (rps, "zknd");
2619
7
    case INSN_CLASS_ZKNE:
2620
7
      return riscv_subset_supports (rps, "zkne");
2621
125
    case INSN_CLASS_ZKNH:
2622
125
      return riscv_subset_supports (rps, "zknh");
2623
29
    case INSN_CLASS_ZKND_OR_ZKNE:
2624
29
      return (riscv_subset_supports (rps, "zknd")
2625
29
        || riscv_subset_supports (rps, "zkne"));
2626
100
    case INSN_CLASS_ZKSED:
2627
100
      return riscv_subset_supports (rps, "zksed");
2628
203
    case INSN_CLASS_ZKSH:
2629
203
      return riscv_subset_supports (rps, "zksh");
2630
2.85k
    case INSN_CLASS_V:
2631
2.85k
      return (riscv_subset_supports (rps, "v")
2632
2.85k
        || riscv_subset_supports (rps, "zve64x")
2633
2.85k
        || riscv_subset_supports (rps, "zve32x"));
2634
112
    case INSN_CLASS_ZVEF:
2635
112
      return (riscv_subset_supports (rps, "v")
2636
112
        || riscv_subset_supports (rps, "zve64d")
2637
112
        || riscv_subset_supports (rps, "zve64f")
2638
112
        || riscv_subset_supports (rps, "zve32f"));
2639
10
    case INSN_CLASS_ZVBB:
2640
10
      return riscv_subset_supports (rps, "zvbb");
2641
20
    case INSN_CLASS_ZVBC:
2642
20
      return riscv_subset_supports (rps, "zvbc");
2643
49
    case INSN_CLASS_ZVKB:
2644
49
      return riscv_subset_supports (rps, "zvkb");
2645
0
    case INSN_CLASS_ZVKG:
2646
0
      return riscv_subset_supports (rps, "zvkg");
2647
2
    case INSN_CLASS_ZVKNED:
2648
2
      return riscv_subset_supports (rps, "zvkned");
2649
5
    case INSN_CLASS_ZVKNHA_OR_ZVKNHB:
2650
5
      return (riscv_subset_supports (rps, "zvknha")
2651
5
        || riscv_subset_supports (rps, "zvknhb"));
2652
8
    case INSN_CLASS_ZVKSED:
2653
8
      return riscv_subset_supports (rps, "zvksed");
2654
2
    case INSN_CLASS_ZVKSH:
2655
2
      return riscv_subset_supports (rps, "zvksh");
2656
14.4k
    case INSN_CLASS_ZCB:
2657
14.4k
      return riscv_subset_supports (rps, "zcb");
2658
60
    case INSN_CLASS_ZCB_AND_ZBB:
2659
60
      return (riscv_subset_supports (rps, "zcb")
2660
60
        && riscv_subset_supports (rps, "zbb"));
2661
40
    case INSN_CLASS_ZCB_AND_ZBA:
2662
40
      return (riscv_subset_supports (rps, "zcb")
2663
40
        && riscv_subset_supports (rps, "zba"));
2664
216
    case INSN_CLASS_ZCB_AND_ZMMUL:
2665
216
      return (riscv_subset_supports (rps, "zcb")
2666
216
        && riscv_subset_supports (rps, "zmmul"));
2667
0
    case INSN_CLASS_ZCMP:
2668
0
      return riscv_subset_supports (rps, "zcmp");
2669
1
    case INSN_CLASS_SVINVAL:
2670
1
      return riscv_subset_supports (rps, "svinval");
2671
8
    case INSN_CLASS_H:
2672
8
      return riscv_subset_supports (rps, "h");
2673
3.71k
    case INSN_CLASS_XCVMAC:
2674
3.71k
      return riscv_subset_supports (rps, "xcvmac");
2675
321
    case INSN_CLASS_XCVALU:
2676
321
      return riscv_subset_supports (rps, "xcvalu");
2677
213
    case INSN_CLASS_XTHEADBA:
2678
213
      return riscv_subset_supports (rps, "xtheadba");
2679
304
    case INSN_CLASS_XTHEADBB:
2680
304
      return riscv_subset_supports (rps, "xtheadbb");
2681
0
    case INSN_CLASS_XTHEADBS:
2682
0
      return riscv_subset_supports (rps, "xtheadbs");
2683
78
    case INSN_CLASS_XTHEADCMO:
2684
78
      return riscv_subset_supports (rps, "xtheadcmo");
2685
392
    case INSN_CLASS_XTHEADCONDMOV:
2686
392
      return riscv_subset_supports (rps, "xtheadcondmov");
2687
54
    case INSN_CLASS_XTHEADFMEMIDX:
2688
54
      return riscv_subset_supports (rps, "xtheadfmemidx");
2689
0
    case INSN_CLASS_XTHEADFMV:
2690
0
      return riscv_subset_supports (rps, "xtheadfmv");
2691
0
    case INSN_CLASS_XTHEADINT:
2692
0
      return riscv_subset_supports (rps, "xtheadint");
2693
44
    case INSN_CLASS_XTHEADMAC:
2694
44
      return riscv_subset_supports (rps, "xtheadmac");
2695
365
    case INSN_CLASS_XTHEADMEMIDX:
2696
365
      return riscv_subset_supports (rps, "xtheadmemidx");
2697
11
    case INSN_CLASS_XTHEADMEMPAIR:
2698
11
      return riscv_subset_supports (rps, "xtheadmempair");
2699
1
    case INSN_CLASS_XTHEADSYNC:
2700
1
      return riscv_subset_supports (rps, "xtheadsync");
2701
2.27k
    case INSN_CLASS_XTHEADVECTOR:
2702
2.27k
      return riscv_subset_supports (rps, "xtheadvector");
2703
162
    case INSN_CLASS_XTHEADZVAMO:
2704
162
      return riscv_subset_supports (rps, "xtheadzvamo");
2705
43
    case INSN_CLASS_XVENTANACONDOPS:
2706
43
      return riscv_subset_supports (rps, "xventanacondops");
2707
203
    case INSN_CLASS_XSFVCP:
2708
203
      return riscv_subset_supports (rps, "xsfvcp");
2709
0
    default:
2710
0
      rps->error_handler
2711
0
        (_("internal: unreachable INSN_CLASS_*"));
2712
0
      return false;
2713
539k
    }
2714
539k
}
2715
2716
/* Each instuction is belonged to an instruction class INSN_CLASS_*.
2717
   Call riscv_subset_supports_ext to determine the missing extension.  */
2718
2719
const char *
2720
riscv_multi_subset_supports_ext (riscv_parse_subset_t *rps,
2721
         enum riscv_insn_class insn_class)
2722
0
{
2723
0
  switch (insn_class)
2724
0
    {
2725
0
    case INSN_CLASS_I:
2726
0
      return "i";
2727
0
    case INSN_CLASS_ZICBOM:
2728
0
      return "zicbom";
2729
0
    case INSN_CLASS_ZICBOP:
2730
0
      return "zicbop";
2731
0
    case INSN_CLASS_ZICBOZ:
2732
0
      return "zicboz";
2733
0
    case INSN_CLASS_ZICOND:
2734
0
      return "zicond";
2735
0
    case INSN_CLASS_ZICSR:
2736
0
      return "zicsr";
2737
0
    case INSN_CLASS_ZIFENCEI:
2738
0
      return "zifencei";
2739
0
    case INSN_CLASS_ZIHINTNTL:
2740
0
      return "zihintntl";
2741
0
    case INSN_CLASS_ZIHINTNTL_AND_C:
2742
0
      if (!riscv_subset_supports (rps, "zihintntl"))
2743
0
  {
2744
0
    if (!riscv_subset_supports (rps, "c")
2745
0
        && !riscv_subset_supports (rps, "zca"))
2746
0
      return _("zihintntl' and `c', or `zihintntl' and `zca");
2747
0
    else
2748
0
      return "zihintntl";
2749
0
  }
2750
0
      else
2751
0
  return _("c' or `zca");
2752
0
    case INSN_CLASS_ZIHINTPAUSE:
2753
0
      return "zihintpause";
2754
0
    case INSN_CLASS_M:
2755
0
      return "m";
2756
0
    case INSN_CLASS_ZMMUL:
2757
0
      return _ ("m' or `zmmul");
2758
0
    case INSN_CLASS_ZAAMO:
2759
0
      return "zaamo";
2760
0
    case INSN_CLASS_ZABHA:
2761
0
      return "zabha";
2762
0
    case INSN_CLASS_ZALRSC:
2763
0
      return "zalrsc";
2764
0
    case INSN_CLASS_ZAWRS:
2765
0
      return "zawrs";
2766
0
    case INSN_CLASS_F:
2767
0
      return "f";
2768
0
    case INSN_CLASS_D:
2769
0
      return "d";
2770
0
    case INSN_CLASS_Q:
2771
0
      return "q";
2772
0
    case INSN_CLASS_C:
2773
0
      return _("c' or `zca");
2774
0
    case INSN_CLASS_F_AND_C:
2775
0
      if (!riscv_subset_supports (rps, "f"))
2776
0
  {
2777
0
    if (!riscv_subset_supports (rps, "c")
2778
0
        && !riscv_subset_supports (rps, "zcf"))
2779
0
      return _("f' and `c', or `f' and `zcf"); 
2780
0
    else
2781
0
      return "f";
2782
0
  }
2783
0
      else
2784
0
  return _("c' or `zcf");
2785
0
    case INSN_CLASS_D_AND_C:
2786
0
      if (!riscv_subset_supports (rps, "d"))
2787
0
  {
2788
0
    if (!riscv_subset_supports (rps, "c")
2789
0
        && !riscv_subset_supports (rps, "zcd"))
2790
0
      return _("d' and `c', or `d' and `zcd");
2791
0
    else
2792
0
      return "d";
2793
0
  }
2794
0
      else
2795
0
  return _("c' or `zcd");
2796
0
    case INSN_CLASS_F_INX:
2797
0
      return _("f' or `zfinx");
2798
0
    case INSN_CLASS_D_INX:
2799
0
      return _("d' or `zdinx");
2800
0
    case INSN_CLASS_Q_INX:
2801
0
      return _("q' or `zqinx");
2802
0
    case INSN_CLASS_ZFH_INX:
2803
0
      return _("zfh' or `zhinx");
2804
0
    case INSN_CLASS_ZFHMIN:
2805
0
      return "zfhmin";
2806
0
    case INSN_CLASS_ZFHMIN_INX:
2807
0
      return _("zfhmin' or `zhinxmin");
2808
0
    case INSN_CLASS_ZFHMIN_AND_D_INX:
2809
0
      if (riscv_subset_supports (rps, "zfhmin"))
2810
0
  return "d";
2811
0
      else if (riscv_subset_supports (rps, "d"))
2812
0
  return "zfhmin";
2813
0
      else if (riscv_subset_supports (rps, "zhinxmin"))
2814
0
  return "zdinx";
2815
0
      else if (riscv_subset_supports (rps, "zdinx"))
2816
0
  return "zhinxmin";
2817
0
      else
2818
0
  return _("zfhmin' and `d', or `zhinxmin' and `zdinx");
2819
0
    case INSN_CLASS_ZFHMIN_AND_Q_INX:
2820
0
      if (riscv_subset_supports (rps, "zfhmin"))
2821
0
  return "q";
2822
0
      else if (riscv_subset_supports (rps, "q"))
2823
0
  return "zfhmin";
2824
0
      else if (riscv_subset_supports (rps, "zhinxmin"))
2825
0
  return "zqinx";
2826
0
      else if (riscv_subset_supports (rps, "zqinx"))
2827
0
  return "zhinxmin";
2828
0
      else
2829
0
  return _("zfhmin' and `q', or `zhinxmin' and `zqinx");
2830
0
    case INSN_CLASS_ZFA:
2831
0
      return "zfa";
2832
0
    case INSN_CLASS_D_AND_ZFA:
2833
0
      if (!riscv_subset_supports (rps, "d")
2834
0
    && !riscv_subset_supports (rps, "zfa"))
2835
0
  return _("d' and `zfa");
2836
0
      else if (!riscv_subset_supports (rps, "d"))
2837
0
  return "d";
2838
0
      else
2839
0
  return "zfa";
2840
0
    case INSN_CLASS_Q_AND_ZFA:
2841
0
      if (!riscv_subset_supports (rps, "q")
2842
0
    && !riscv_subset_supports (rps, "zfa"))
2843
0
  return _("q' and `zfa");
2844
0
      else if (!riscv_subset_supports (rps, "q"))
2845
0
  return "q";
2846
0
      else
2847
0
  return "zfa";
2848
0
    case INSN_CLASS_ZFH_AND_ZFA:
2849
0
      if (!riscv_subset_supports (rps, "zfh")
2850
0
    && !riscv_subset_supports (rps, "zfa"))
2851
0
  return _("zfh' and `zfa");
2852
0
      else if (!riscv_subset_supports (rps, "zfh"))
2853
0
  return "zfh";
2854
0
      else
2855
0
  return "zfa";
2856
0
    case INSN_CLASS_ZFH_OR_ZVFH_AND_ZFA:
2857
0
      if (!riscv_subset_supports (rps, "zfa"))
2858
0
  {
2859
0
    if (!riscv_subset_supports (rps, "zfh")
2860
0
        && !riscv_subset_supports (rps, "zvfh"))
2861
0
      return _("zfh' and `zfa', or `zvfh' and `zfa");
2862
0
    else
2863
0
      return "zfa";
2864
0
  }
2865
0
      else
2866
0
  return _("zfh' or `zvfh");
2867
0
    case INSN_CLASS_ZBA:
2868
0
      return "zba";
2869
0
    case INSN_CLASS_ZBB:
2870
0
      return "zbb";
2871
0
    case INSN_CLASS_ZBC:
2872
0
      return "zbc";
2873
0
    case INSN_CLASS_ZBS:
2874
0
      return "zbs";
2875
0
    case INSN_CLASS_ZBKB:
2876
0
      return "zbkb";
2877
0
    case INSN_CLASS_ZBKC:
2878
0
      return "zbkc";
2879
0
    case INSN_CLASS_ZBKX:
2880
0
      return "zbkx";
2881
0
    case INSN_CLASS_ZBB_OR_ZBKB:
2882
0
      return _("zbb' or `zbkb");
2883
0
    case INSN_CLASS_ZBC_OR_ZBKC:
2884
0
      return _("zbc' or `zbkc");
2885
0
    case INSN_CLASS_ZKND:
2886
0
      return "zknd";
2887
0
    case INSN_CLASS_ZKNE:
2888
0
      return "zkne";
2889
0
    case INSN_CLASS_ZKNH:
2890
0
      return "zknh";
2891
0
    case INSN_CLASS_ZKND_OR_ZKNE:
2892
0
      return _("zknd' or `zkne");
2893
0
    case INSN_CLASS_ZKSED:
2894
0
      return "zksed";
2895
0
    case INSN_CLASS_ZKSH:
2896
0
      return "zksh";
2897
0
    case INSN_CLASS_V:
2898
0
      return _("v' or `zve64x' or `zve32x");
2899
0
    case INSN_CLASS_ZVEF:
2900
0
      return _("v' or `zve64d' or `zve64f' or `zve32f");
2901
0
    case INSN_CLASS_ZVBB:
2902
0
      return _("zvbb");
2903
0
    case INSN_CLASS_ZVBC:
2904
0
      return _("zvbc");
2905
0
    case INSN_CLASS_ZVKB:
2906
0
      return _("zvkb");
2907
0
    case INSN_CLASS_ZVKG:
2908
0
      return _("zvkg");
2909
0
    case INSN_CLASS_ZVKNED:
2910
0
      return _("zvkned");
2911
0
    case INSN_CLASS_ZVKNHA_OR_ZVKNHB:
2912
0
      return _("zvknha' or `zvknhb");
2913
0
    case INSN_CLASS_ZVKSED:
2914
0
      return _("zvksed");
2915
0
    case INSN_CLASS_ZVKSH:
2916
0
      return _("zvksh");
2917
0
    case INSN_CLASS_ZCB:
2918
0
      return "zcb";
2919
0
    case INSN_CLASS_ZCB_AND_ZBA:
2920
0
      return _("zcb' and `zba");
2921
0
    case INSN_CLASS_ZCB_AND_ZBB:
2922
0
      return _("zcb' and `zbb");
2923
0
    case INSN_CLASS_ZCB_AND_ZMMUL:
2924
0
      return _("zcb' and `zmmul', or `zcb' and `m");
2925
0
    case INSN_CLASS_ZCMP:
2926
0
      return "zcmp";
2927
0
    case INSN_CLASS_SVINVAL:
2928
0
      return "svinval";
2929
0
    case INSN_CLASS_H:
2930
0
      return _("h");
2931
0
    case INSN_CLASS_XCVMAC:
2932
0
      return "xcvmac";
2933
0
    case INSN_CLASS_XCVALU:
2934
0
      return "xcvalu";
2935
0
    case INSN_CLASS_XTHEADBA:
2936
0
      return "xtheadba";
2937
0
    case INSN_CLASS_XTHEADBB:
2938
0
      return "xtheadbb";
2939
0
    case INSN_CLASS_XTHEADBS:
2940
0
      return "xtheadbs";
2941
0
    case INSN_CLASS_XTHEADCMO:
2942
0
      return "xtheadcmo";
2943
0
    case INSN_CLASS_XTHEADCONDMOV:
2944
0
      return "xtheadcondmov";
2945
0
    case INSN_CLASS_XTHEADFMEMIDX:
2946
0
      return "xtheadfmemidx";
2947
0
    case INSN_CLASS_XTHEADFMV:
2948
0
      return "xtheadfmv";
2949
0
    case INSN_CLASS_XTHEADINT:
2950
0
      return "xtheadint";
2951
0
    case INSN_CLASS_XTHEADMAC:
2952
0
      return "xtheadmac";
2953
0
    case INSN_CLASS_XTHEADMEMIDX:
2954
0
      return "xtheadmemidx";
2955
0
    case INSN_CLASS_XTHEADMEMPAIR:
2956
0
      return "xtheadmempair";
2957
0
    case INSN_CLASS_XTHEADSYNC:
2958
0
      return "xtheadsync";
2959
0
    case INSN_CLASS_XTHEADVECTOR:
2960
0
      return "xtheadvector";
2961
0
    case INSN_CLASS_XTHEADZVAMO:
2962
0
      return "xtheadzvamo";
2963
0
    default:
2964
0
      rps->error_handler
2965
0
        (_("internal: unreachable INSN_CLASS_*"));
2966
0
      return NULL;
2967
0
    }
2968
0
}
2969
2970
/* Print supported extensions with versions if -march=help.  */
2971
2972
void
2973
riscv_print_extensions (void)
2974
0
{
2975
  /* Record the previous printed extension.
2976
     Print the current one if they are not the same.  */
2977
0
  const struct riscv_supported_ext *cur = NULL, *prev = NULL;
2978
0
  int i, j;
2979
2980
0
  printf ("All available -march extensions for RISC-V:");
2981
2982
0
  for (i = 0; riscv_all_supported_ext[i] != NULL; i++)
2983
0
    {
2984
0
      const struct riscv_supported_ext *exts = riscv_all_supported_ext[i];
2985
0
      prev = NULL;
2986
0
      for (j = 0; exts[j].name != NULL; j++)
2987
0
  {
2988
0
    cur = &exts[j];
2989
    /* Unclear version information, skip.  */
2990
0
    if (cur->isa_spec_class == ISA_SPEC_CLASS_NONE
2991
0
        || cur->major_version == RISCV_UNKNOWN_VERSION
2992
0
        || cur->minor_version == RISCV_UNKNOWN_VERSION)
2993
0
      continue;
2994
2995
    /* Same extension.  */
2996
0
    if (prev && strcmp (prev->name, cur->name) == 0)
2997
0
      {
2998
        /* Same version, skip.  */
2999
0
        if (prev->major_version == cur->major_version
3000
0
      && prev->minor_version == cur->minor_version)
3001
0
    continue;
3002
        /* Different version, print version with comma.  */
3003
0
        else
3004
0
    printf (", %d.%d", cur->major_version, cur->minor_version);
3005
0
      }
3006
    /* Different extension, print extension and version with newline.  */
3007
0
    else
3008
0
      printf ("\n\t%-40s%d.%d", cur->name, cur->major_version,
3009
0
        cur->minor_version);
3010
0
    prev = &exts[j];
3011
0
  }
3012
0
    }
3013
0
  printf ("\n");
3014
0
}