Coverage Report

Created: 2023-08-28 06:26

/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-2023 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
  /* Reserved for future relocs that the dynamic linker must understand.  */
222
  EMPTY_HOWTO (12),
223
  EMPTY_HOWTO (13),
224
  EMPTY_HOWTO (14),
225
  EMPTY_HOWTO (15),
226
227
  /* 12-bit PC-relative branch offset.  */
228
  HOWTO (R_RISCV_BRANCH,    /* type */
229
   0,       /* rightshift */
230
   4,       /* size */
231
   32,        /* bitsize */
232
   true,        /* pc_relative */
233
   0,       /* bitpos */
234
   complain_overflow_signed,  /* complain_on_overflow */
235
   bfd_elf_generic_reloc,   /* special_function */
236
   "R_RISCV_BRANCH",    /* name */
237
   false,       /* partial_inplace */
238
   0,       /* src_mask */
239
   ENCODE_BTYPE_IMM (-1U),  /* dst_mask */
240
   true),       /* pcrel_offset */
241
242
  /* 20-bit PC-relative jump offset.  */
243
  HOWTO (R_RISCV_JAL,     /* type */
244
   0,       /* rightshift */
245
   4,       /* size */
246
   32,        /* bitsize */
247
   true,        /* pc_relative */
248
   0,       /* bitpos */
249
   complain_overflow_dont,  /* complain_on_overflow */
250
   bfd_elf_generic_reloc,   /* special_function */
251
   "R_RISCV_JAL",     /* name */
252
   false,       /* partial_inplace */
253
   0,       /* src_mask */
254
   ENCODE_JTYPE_IMM (-1U),  /* dst_mask */
255
   true),       /* pcrel_offset */
256
257
  /* 32-bit PC-relative function call (AUIPC/JALR).  */
258
  HOWTO (R_RISCV_CALL,      /* type */
259
   0,       /* rightshift */
260
   8,       /* size */
261
   64,        /* bitsize */
262
   true,        /* pc_relative */
263
   0,       /* bitpos */
264
   complain_overflow_dont,  /* complain_on_overflow */
265
   bfd_elf_generic_reloc,   /* special_function */
266
   "R_RISCV_CALL",    /* name */
267
   false,       /* partial_inplace */
268
   0,       /* src_mask */
269
   ENCODE_UTYPE_IMM (-1U) | ((bfd_vma) ENCODE_ITYPE_IMM (-1U) << 32),
270
          /* dst_mask */
271
   true),       /* pcrel_offset */
272
273
  /* Like R_RISCV_CALL, but not locally binding.  */
274
  HOWTO (R_RISCV_CALL_PLT,    /* type */
275
   0,       /* rightshift */
276
   8,       /* size */
277
   64,        /* bitsize */
278
   true,        /* pc_relative */
279
   0,       /* bitpos */
280
   complain_overflow_dont,  /* complain_on_overflow */
281
   bfd_elf_generic_reloc,   /* special_function */
282
   "R_RISCV_CALL_PLT",    /* name */
283
   false,       /* partial_inplace */
284
   0,       /* src_mask */
285
   ENCODE_UTYPE_IMM (-1U) | ((bfd_vma) ENCODE_ITYPE_IMM (-1U) << 32),
286
          /* dst_mask */
287
   true),       /* pcrel_offset */
288
289
  /* High 20 bits of 32-bit PC-relative GOT access.  */
290
  HOWTO (R_RISCV_GOT_HI20,    /* type */
291
   0,       /* rightshift */
292
   4,       /* size */
293
   32,        /* bitsize */
294
   true,        /* pc_relative */
295
   0,       /* bitpos */
296
   complain_overflow_dont,  /* complain_on_overflow */
297
   bfd_elf_generic_reloc,   /* special_function */
298
   "R_RISCV_GOT_HI20",    /* name */
299
   false,       /* partial_inplace */
300
   0,       /* src_mask */
301
   ENCODE_UTYPE_IMM (-1U),  /* dst_mask */
302
   false),      /* pcrel_offset */
303
304
  /* High 20 bits of 32-bit PC-relative TLS IE GOT access.  */
305
  HOWTO (R_RISCV_TLS_GOT_HI20,    /* type */
306
   0,       /* rightshift */
307
   4,       /* size */
308
   32,        /* bitsize */
309
   true,        /* pc_relative */
310
   0,       /* bitpos */
311
   complain_overflow_dont,  /* complain_on_overflow */
312
   bfd_elf_generic_reloc,   /* special_function */
313
   "R_RISCV_TLS_GOT_HI20",  /* name */
314
   false,       /* partial_inplace */
315
   0,       /* src_mask */
316
   ENCODE_UTYPE_IMM (-1U),  /* dst_mask */
317
   false),      /* pcrel_offset */
318
319
  /* High 20 bits of 32-bit PC-relative TLS GD GOT reference.  */
320
  HOWTO (R_RISCV_TLS_GD_HI20,   /* type */
321
   0,       /* rightshift */
322
   4,       /* size */
323
   32,        /* bitsize */
324
   true,        /* pc_relative */
325
   0,       /* bitpos */
326
   complain_overflow_dont,  /* complain_on_overflow */
327
   bfd_elf_generic_reloc,   /* special_function */
328
   "R_RISCV_TLS_GD_HI20",   /* name */
329
   false,       /* partial_inplace */
330
   0,       /* src_mask */
331
   ENCODE_UTYPE_IMM (-1U),  /* dst_mask */
332
   false),      /* pcrel_offset */
333
334
  /* High 20 bits of 32-bit PC-relative reference.  */
335
  HOWTO (R_RISCV_PCREL_HI20,    /* type */
336
   0,       /* rightshift */
337
   4,       /* size */
338
   32,        /* bitsize */
339
   true,        /* pc_relative */
340
   0,       /* bitpos */
341
   complain_overflow_dont,  /* complain_on_overflow */
342
   bfd_elf_generic_reloc,   /* special_function */
343
   "R_RISCV_PCREL_HI20",    /* name */
344
   false,       /* partial_inplace */
345
   0,       /* src_mask */
346
   ENCODE_UTYPE_IMM (-1U),  /* dst_mask */
347
   true),       /* pcrel_offset */
348
349
  /* Low 12 bits of a 32-bit PC-relative load or add.  */
350
  HOWTO (R_RISCV_PCREL_LO12_I,    /* type */
351
   0,       /* rightshift */
352
   4,       /* size */
353
   32,        /* bitsize */
354
   false,       /* pc_relative */
355
   0,       /* bitpos */
356
   complain_overflow_dont,  /* complain_on_overflow */
357
   bfd_elf_generic_reloc,   /* special_function */
358
   "R_RISCV_PCREL_LO12_I",  /* name */
359
   false,       /* partial_inplace */
360
   0,       /* src_mask */
361
   ENCODE_ITYPE_IMM (-1U),  /* dst_mask */
362
   false),      /* pcrel_offset */
363
364
  /* Low 12 bits of a 32-bit PC-relative store.  */
365
  HOWTO (R_RISCV_PCREL_LO12_S,    /* type */
366
   0,       /* rightshift */
367
   4,       /* size */
368
   32,        /* bitsize */
369
   false,       /* pc_relative */
370
   0,       /* bitpos */
371
   complain_overflow_dont,  /* complain_on_overflow */
372
   bfd_elf_generic_reloc,   /* special_function */
373
   "R_RISCV_PCREL_LO12_S",  /* name */
374
   false,       /* partial_inplace */
375
   0,       /* src_mask */
376
   ENCODE_STYPE_IMM (-1U),  /* dst_mask */
377
   false),      /* pcrel_offset */
378
379
  /* High 20 bits of 32-bit absolute address.  */
380
  HOWTO (R_RISCV_HI20,      /* type */
381
   0,       /* rightshift */
382
   4,       /* size */
383
   32,        /* bitsize */
384
   false,       /* pc_relative */
385
   0,       /* bitpos */
386
   complain_overflow_dont,  /* complain_on_overflow */
387
   bfd_elf_generic_reloc,   /* special_function */
388
   "R_RISCV_HI20",    /* name */
389
   false,       /* partial_inplace */
390
   0,       /* src_mask */
391
   ENCODE_UTYPE_IMM (-1U),  /* dst_mask */
392
   false),      /* pcrel_offset */
393
394
  /* High 12 bits of 32-bit load or add.  */
395
  HOWTO (R_RISCV_LO12_I,    /* type */
396
   0,       /* rightshift */
397
   4,       /* size */
398
   32,        /* bitsize */
399
   false,       /* pc_relative */
400
   0,       /* bitpos */
401
   complain_overflow_dont,  /* complain_on_overflow */
402
   bfd_elf_generic_reloc,   /* special_function */
403
   "R_RISCV_LO12_I",    /* name */
404
   false,       /* partial_inplace */
405
   0,       /* src_mask */
406
   ENCODE_ITYPE_IMM (-1U),  /* dst_mask */
407
   false),      /* pcrel_offset */
408
409
  /* High 12 bits of 32-bit store.  */
410
  HOWTO (R_RISCV_LO12_S,    /* type */
411
   0,       /* rightshift */
412
   4,       /* size */
413
   32,        /* bitsize */
414
   false,       /* pc_relative */
415
   0,       /* bitpos */
416
   complain_overflow_dont,  /* complain_on_overflow */
417
   bfd_elf_generic_reloc,   /* special_function */
418
   "R_RISCV_LO12_S",    /* name */
419
   false,       /* partial_inplace */
420
   0,       /* src_mask */
421
   ENCODE_STYPE_IMM (-1U),  /* dst_mask */
422
   false),      /* pcrel_offset */
423
424
  /* High 20 bits of TLS LE thread pointer offset.  */
425
  HOWTO (R_RISCV_TPREL_HI20,    /* type */
426
   0,       /* rightshift */
427
   4,       /* size */
428
   32,        /* bitsize */
429
   false,       /* pc_relative */
430
   0,       /* bitpos */
431
   complain_overflow_signed,  /* complain_on_overflow */
432
   bfd_elf_generic_reloc,   /* special_function */
433
   "R_RISCV_TPREL_HI20",    /* name */
434
   true,        /* partial_inplace */
435
   0,       /* src_mask */
436
   ENCODE_UTYPE_IMM (-1U),  /* dst_mask */
437
   false),      /* pcrel_offset */
438
439
  /* Low 12 bits of TLS LE thread pointer offset for loads and adds.  */
440
  HOWTO (R_RISCV_TPREL_LO12_I,    /* type */
441
   0,       /* rightshift */
442
   4,       /* size */
443
   32,        /* bitsize */
444
   false,       /* pc_relative */
445
   0,       /* bitpos */
446
   complain_overflow_signed,  /* complain_on_overflow */
447
   bfd_elf_generic_reloc,   /* special_function */
448
   "R_RISCV_TPREL_LO12_I",  /* name */
449
   false,       /* partial_inplace */
450
   0,       /* src_mask */
451
   ENCODE_ITYPE_IMM (-1U),  /* dst_mask */
452
   false),      /* pcrel_offset */
453
454
  /* Low 12 bits of TLS LE thread pointer offset for stores.  */
455
  HOWTO (R_RISCV_TPREL_LO12_S,    /* type */
456
   0,       /* rightshift */
457
   4,       /* size */
458
   32,        /* bitsize */
459
   false,       /* pc_relative */
460
   0,       /* bitpos */
461
   complain_overflow_signed,  /* complain_on_overflow */
462
   bfd_elf_generic_reloc,   /* special_function */
463
   "R_RISCV_TPREL_LO12_S",  /* name */
464
   false,       /* partial_inplace */
465
   0,       /* src_mask */
466
   ENCODE_STYPE_IMM (-1U),  /* dst_mask */
467
   false),      /* pcrel_offset */
468
469
  /* TLS LE thread pointer usage.  May be relaxed.  */
470
  HOWTO (R_RISCV_TPREL_ADD,   /* type */
471
   0,       /* rightshift */
472
   0,       /* size */
473
   0,       /* bitsize */
474
   false,       /* pc_relative */
475
   0,       /* bitpos */
476
   complain_overflow_dont,  /* complain_on_overflow */
477
   bfd_elf_generic_reloc,   /* special_function */
478
   "R_RISCV_TPREL_ADD",   /* name */
479
   false,       /* partial_inplace */
480
   0,       /* src_mask */
481
   0,       /* dst_mask */
482
   false),      /* pcrel_offset */
483
484
  /* 8-bit in-place addition, for local label subtraction.  */
485
  HOWTO (R_RISCV_ADD8,      /* type */
486
   0,       /* rightshift */
487
   1,       /* size */
488
   8,       /* bitsize */
489
   false,       /* pc_relative */
490
   0,       /* bitpos */
491
   complain_overflow_dont,  /* complain_on_overflow */
492
   riscv_elf_add_sub_reloc, /* special_function */
493
   "R_RISCV_ADD8",    /* name */
494
   false,       /* partial_inplace */
495
   0,       /* src_mask */
496
   0xff,        /* dst_mask */
497
   false),      /* pcrel_offset */
498
499
  /* 16-bit in-place addition, for local label subtraction.  */
500
  HOWTO (R_RISCV_ADD16,     /* type */
501
   0,       /* rightshift */
502
   2,       /* size */
503
   16,        /* bitsize */
504
   false,       /* pc_relative */
505
   0,       /* bitpos */
506
   complain_overflow_dont,  /* complain_on_overflow */
507
   riscv_elf_add_sub_reloc, /* special_function */
508
   "R_RISCV_ADD16",   /* name */
509
   false,       /* partial_inplace */
510
   0,       /* src_mask */
511
   0xffff,      /* dst_mask */
512
   false),      /* pcrel_offset */
513
514
  /* 32-bit in-place addition, for local label subtraction.  */
515
  HOWTO (R_RISCV_ADD32,     /* type */
516
   0,       /* rightshift */
517
   4,       /* size */
518
   32,        /* bitsize */
519
   false,       /* pc_relative */
520
   0,       /* bitpos */
521
   complain_overflow_dont,  /* complain_on_overflow */
522
   riscv_elf_add_sub_reloc, /* special_function */
523
   "R_RISCV_ADD32",   /* name */
524
   false,       /* partial_inplace */
525
   0,       /* src_mask */
526
   0xffffffff,      /* dst_mask */
527
   false),      /* pcrel_offset */
528
529
  /* 64-bit in-place addition, for local label subtraction.  */
530
  HOWTO (R_RISCV_ADD64,     /* type */
531
   0,       /* rightshift */
532
   8,       /* size */
533
   64,        /* bitsize */
534
   false,       /* pc_relative */
535
   0,       /* bitpos */
536
   complain_overflow_dont,  /* complain_on_overflow */
537
   riscv_elf_add_sub_reloc, /* special_function */
538
   "R_RISCV_ADD64",   /* name */
539
   false,       /* partial_inplace */
540
   0,       /* src_mask */
541
   MINUS_ONE,     /* dst_mask */
542
   false),      /* pcrel_offset */
543
544
  /* 8-bit in-place addition, for local label subtraction.  */
545
  HOWTO (R_RISCV_SUB8,      /* type */
546
   0,       /* rightshift */
547
   1,       /* size */
548
   8,       /* bitsize */
549
   false,       /* pc_relative */
550
   0,       /* bitpos */
551
   complain_overflow_dont,  /* complain_on_overflow */
552
   riscv_elf_add_sub_reloc, /* special_function */
553
   "R_RISCV_SUB8",    /* name */
554
   false,       /* partial_inplace */
555
   0,       /* src_mask */
556
   0xff,        /* dst_mask */
557
   false),      /* pcrel_offset */
558
559
  /* 16-bit in-place addition, for local label subtraction.  */
560
  HOWTO (R_RISCV_SUB16,     /* type */
561
   0,       /* rightshift */
562
   2,       /* size */
563
   16,        /* bitsize */
564
   false,       /* pc_relative */
565
   0,       /* bitpos */
566
   complain_overflow_dont,  /* complain_on_overflow */
567
   riscv_elf_add_sub_reloc, /* special_function */
568
   "R_RISCV_SUB16",   /* name */
569
   false,       /* partial_inplace */
570
   0,       /* src_mask */
571
   0xffff,      /* dst_mask */
572
   false),      /* pcrel_offset */
573
574
  /* 32-bit in-place addition, for local label subtraction.  */
575
  HOWTO (R_RISCV_SUB32,     /* type */
576
   0,       /* rightshift */
577
   4,       /* size */
578
   32,        /* bitsize */
579
   false,       /* pc_relative */
580
   0,       /* bitpos */
581
   complain_overflow_dont,  /* complain_on_overflow */
582
   riscv_elf_add_sub_reloc, /* special_function */
583
   "R_RISCV_SUB32",   /* name */
584
   false,       /* partial_inplace */
585
   0,       /* src_mask */
586
   0xffffffff,      /* dst_mask */
587
   false),      /* pcrel_offset */
588
589
  /* 64-bit in-place addition, for local label subtraction.  */
590
  HOWTO (R_RISCV_SUB64,     /* type */
591
   0,       /* rightshift */
592
   8,       /* size */
593
   64,        /* bitsize */
594
   false,       /* pc_relative */
595
   0,       /* bitpos */
596
   complain_overflow_dont,  /* complain_on_overflow */
597
   riscv_elf_add_sub_reloc, /* special_function */
598
   "R_RISCV_SUB64",   /* name */
599
   false,       /* partial_inplace */
600
   0,       /* src_mask */
601
   MINUS_ONE,     /* dst_mask */
602
   false),      /* pcrel_offset */
603
604
  /* 41 and 42 are reserved.  */
605
  EMPTY_HOWTO (0),
606
  EMPTY_HOWTO (0),
607
608
  /* Indicates an alignment statement.  The addend field encodes how many
609
     bytes of NOPs follow the statement.  The desired alignment is the
610
     addend rounded up to the next power of two.  */
611
  HOWTO (R_RISCV_ALIGN,     /* type */
612
   0,       /* rightshift */
613
   0,       /* size */
614
   0,       /* bitsize */
615
   false,       /* pc_relative */
616
   0,       /* bitpos */
617
   complain_overflow_dont,  /* complain_on_overflow */
618
   bfd_elf_generic_reloc,   /* special_function */
619
   "R_RISCV_ALIGN",   /* name */
620
   false,       /* partial_inplace */
621
   0,       /* src_mask */
622
   0,       /* dst_mask */
623
   false),      /* pcrel_offset */
624
625
  /* 8-bit PC-relative branch offset.  */
626
  HOWTO (R_RISCV_RVC_BRANCH,    /* type */
627
   0,       /* rightshift */
628
   2,       /* size */
629
   16,        /* bitsize */
630
   true,        /* pc_relative */
631
   0,       /* bitpos */
632
   complain_overflow_signed,  /* complain_on_overflow */
633
   bfd_elf_generic_reloc,   /* special_function */
634
   "R_RISCV_RVC_BRANCH",    /* name */
635
   false,       /* partial_inplace */
636
   0,       /* src_mask */
637
   ENCODE_CBTYPE_IMM (-1U), /* dst_mask */
638
   true),       /* pcrel_offset */
639
640
  /* 11-bit PC-relative jump offset.  */
641
  HOWTO (R_RISCV_RVC_JUMP,    /* type */
642
   0,       /* rightshift */
643
   2,       /* size */
644
   16,        /* bitsize */
645
   true,        /* pc_relative */
646
   0,       /* bitpos */
647
   complain_overflow_dont,  /* complain_on_overflow */
648
   bfd_elf_generic_reloc,   /* special_function */
649
   "R_RISCV_RVC_JUMP",    /* name */
650
   false,       /* partial_inplace */
651
   0,       /* src_mask */
652
   ENCODE_CJTYPE_IMM (-1U), /* dst_mask */
653
   true),       /* pcrel_offset */
654
655
  /* High 6 bits of 18-bit absolute address.  */
656
  HOWTO (R_RISCV_RVC_LUI,   /* type */
657
   0,       /* rightshift */
658
   2,       /* size */
659
   16,        /* bitsize */
660
   false,       /* pc_relative */
661
   0,       /* bitpos */
662
   complain_overflow_dont,  /* complain_on_overflow */
663
   bfd_elf_generic_reloc,   /* special_function */
664
   "R_RISCV_RVC_LUI",   /* name */
665
   false,       /* partial_inplace */
666
   0,       /* src_mask */
667
   ENCODE_CITYPE_IMM (-1U), /* dst_mask */
668
   false),      /* pcrel_offset */
669
670
  /* GP-relative load.  */
671
  HOWTO (R_RISCV_GPREL_I,   /* type */
672
   0,       /* rightshift */
673
   4,       /* size */
674
   32,        /* bitsize */
675
   false,       /* pc_relative */
676
   0,       /* bitpos */
677
   complain_overflow_dont,  /* complain_on_overflow */
678
   bfd_elf_generic_reloc,   /* special_function */
679
   "R_RISCV_GPREL_I",   /* name */
680
   false,       /* partial_inplace */
681
   0,       /* src_mask */
682
   ENCODE_ITYPE_IMM (-1U),  /* dst_mask */
683
   false),      /* pcrel_offset */
684
685
  /* GP-relative store.  */
686
  HOWTO (R_RISCV_GPREL_S,   /* type */
687
   0,       /* rightshift */
688
   4,       /* size */
689
   32,        /* bitsize */
690
   false,       /* pc_relative */
691
   0,       /* bitpos */
692
   complain_overflow_dont,  /* complain_on_overflow */
693
   bfd_elf_generic_reloc,   /* special_function */
694
   "R_RISCV_GPREL_S",   /* name */
695
   false,       /* partial_inplace */
696
   0,       /* src_mask */
697
   ENCODE_STYPE_IMM (-1U),  /* dst_mask */
698
   false),      /* pcrel_offset */
699
700
  /* TP-relative TLS LE load.  */
701
  HOWTO (R_RISCV_TPREL_I,   /* type */
702
   0,       /* rightshift */
703
   4,       /* size */
704
   32,        /* bitsize */
705
   false,       /* pc_relative */
706
   0,       /* bitpos */
707
   complain_overflow_signed,  /* complain_on_overflow */
708
   bfd_elf_generic_reloc,   /* special_function */
709
   "R_RISCV_TPREL_I",   /* name */
710
   false,       /* partial_inplace */
711
   0,       /* src_mask */
712
   ENCODE_ITYPE_IMM (-1U),  /* dst_mask */
713
   false),      /* pcrel_offset */
714
715
  /* TP-relative TLS LE store.  */
716
  HOWTO (R_RISCV_TPREL_S,   /* type */
717
   0,       /* rightshift */
718
   4,       /* size */
719
   32,        /* bitsize */
720
   false,       /* pc_relative */
721
   0,       /* bitpos */
722
   complain_overflow_signed,  /* complain_on_overflow */
723
   bfd_elf_generic_reloc,   /* special_function */
724
   "R_RISCV_TPREL_S",   /* name */
725
   false,       /* partial_inplace */
726
   0,       /* src_mask */
727
   ENCODE_STYPE_IMM (-1U),  /* dst_mask */
728
   false),      /* pcrel_offset */
729
730
  /* The paired relocation may be relaxed.  */
731
  HOWTO (R_RISCV_RELAX,     /* type */
732
   0,       /* rightshift */
733
   0,       /* size */
734
   0,       /* bitsize */
735
   false,       /* pc_relative */
736
   0,       /* bitpos */
737
   complain_overflow_dont,  /* complain_on_overflow */
738
   bfd_elf_generic_reloc,   /* special_function */
739
   "R_RISCV_RELAX",   /* name */
740
   false,       /* partial_inplace */
741
   0,       /* src_mask */
742
   0,       /* dst_mask */
743
   false),      /* pcrel_offset */
744
745
  /* 6-bit in-place addition, for local label subtraction.  */
746
  HOWTO (R_RISCV_SUB6,      /* type */
747
   0,       /* rightshift */
748
   1,       /* size */
749
   8,       /* bitsize */
750
   false,       /* pc_relative */
751
   0,       /* bitpos */
752
   complain_overflow_dont,  /* complain_on_overflow */
753
   riscv_elf_add_sub_reloc, /* special_function */
754
   "R_RISCV_SUB6",    /* name */
755
   false,       /* partial_inplace */
756
   0,       /* src_mask */
757
   0x3f,        /* dst_mask */
758
   false),      /* pcrel_offset */
759
760
  /* 6-bit in-place setting, for local label subtraction.  */
761
  HOWTO (R_RISCV_SET6,      /* type */
762
   0,       /* rightshift */
763
   1,       /* size */
764
   8,       /* bitsize */
765
   false,       /* pc_relative */
766
   0,       /* bitpos */
767
   complain_overflow_dont,  /* complain_on_overflow */
768
   bfd_elf_generic_reloc,   /* special_function */
769
   "R_RISCV_SET6",    /* name */
770
   false,       /* partial_inplace */
771
   0,       /* src_mask */
772
   0x3f,        /* dst_mask */
773
   false),      /* pcrel_offset */
774
775
  /* 8-bit in-place setting, for local label subtraction.  */
776
  HOWTO (R_RISCV_SET8,      /* type */
777
   0,       /* rightshift */
778
   1,       /* size */
779
   8,       /* bitsize */
780
   false,       /* pc_relative */
781
   0,       /* bitpos */
782
   complain_overflow_dont,  /* complain_on_overflow */
783
   bfd_elf_generic_reloc,   /* special_function */
784
   "R_RISCV_SET8",    /* name */
785
   false,       /* partial_inplace */
786
   0,       /* src_mask */
787
   0xff,        /* dst_mask */
788
   false),      /* pcrel_offset */
789
790
  /* 16-bit in-place setting, for local label subtraction.  */
791
  HOWTO (R_RISCV_SET16,     /* type */
792
   0,       /* rightshift */
793
   2,       /* size */
794
   16,        /* bitsize */
795
   false,       /* pc_relative */
796
   0,       /* bitpos */
797
   complain_overflow_dont,  /* complain_on_overflow */
798
   bfd_elf_generic_reloc,   /* special_function */
799
   "R_RISCV_SET16",   /* name */
800
   false,       /* partial_inplace */
801
   0,       /* src_mask */
802
   0xffff,      /* dst_mask */
803
   false),      /* pcrel_offset */
804
805
  /* 32-bit in-place setting, for local label subtraction.  */
806
  HOWTO (R_RISCV_SET32,     /* type */
807
   0,       /* rightshift */
808
   4,       /* size */
809
   32,        /* bitsize */
810
   false,       /* pc_relative */
811
   0,       /* bitpos */
812
   complain_overflow_dont,  /* complain_on_overflow */
813
   bfd_elf_generic_reloc,   /* special_function */
814
   "R_RISCV_SET32",   /* name */
815
   false,       /* partial_inplace */
816
   0,       /* src_mask */
817
   0xffffffff,      /* dst_mask */
818
   false),      /* pcrel_offset */
819
820
  /* 32-bit PC relative.  */
821
  HOWTO (R_RISCV_32_PCREL,    /* type */
822
   0,       /* rightshift */
823
   4,       /* size */
824
   32,        /* bitsize */
825
   true,        /* pc_relative */
826
   0,       /* bitpos */
827
   complain_overflow_dont,  /* complain_on_overflow */
828
   bfd_elf_generic_reloc,   /* special_function */
829
   "R_RISCV_32_PCREL",    /* name */
830
   false,       /* partial_inplace */
831
   0,       /* src_mask */
832
   0xffffffff,      /* dst_mask */
833
   false),      /* pcrel_offset */
834
835
  /* Relocation against a local ifunc symbol in a shared object.  */
836
  HOWTO (R_RISCV_IRELATIVE,   /* type */
837
   0,       /* rightshift */
838
   4,       /* size */
839
   32,        /* bitsize */
840
   false,       /* pc_relative */
841
   0,       /* bitpos */
842
   complain_overflow_dont,  /* complain_on_overflow */
843
   bfd_elf_generic_reloc,   /* special_function */
844
   "R_RISCV_IRELATIVE",   /* name */
845
   false,       /* partial_inplace */
846
   0,       /* src_mask */
847
   0xffffffff,      /* dst_mask */
848
   false),      /* pcrel_offset */
849
850
  /* Reserved for R_RISCV_PLT32.  */
851
  EMPTY_HOWTO (59),
852
853
  /* N-bit in-place setting, for unsigned-leb128 local label subtraction.  */
854
  HOWTO (R_RISCV_SET_ULEB128,   /* type */
855
   0,       /* rightshift */
856
   0,       /* size */
857
   0,       /* bitsize */
858
   false,       /* pc_relative */
859
   0,       /* bitpos */
860
   complain_overflow_dont,  /* complain_on_overflow */
861
   riscv_elf_ignore_reloc,  /* special_function */
862
   "R_RISCV_SET_ULEB128",   /* name */
863
   false,       /* partial_inplace */
864
   0,       /* src_mask */
865
   0,       /* dst_mask */
866
   false),      /* pcrel_offset */
867
868
  /* N-bit in-place addition, for unsigned-leb128 local label subtraction.  */
869
  HOWTO (R_RISCV_SUB_ULEB128,   /* type */
870
   0,       /* rightshift */
871
   0,       /* size */
872
   0,       /* bitsize */
873
   false,       /* pc_relative */
874
   0,       /* bitpos */
875
   complain_overflow_dont,  /* complain_on_overflow */
876
   riscv_elf_ignore_reloc,  /* special_function */
877
   "R_RISCV_SUB_ULEB128",   /* name */
878
   false,       /* partial_inplace */
879
   0,       /* src_mask */
880
   0,       /* dst_mask */
881
   false),      /* pcrel_offset */
882
};
883
884
/* A mapping from BFD reloc types to RISC-V ELF reloc types.  */
885
struct elf_reloc_map
886
{
887
  bfd_reloc_code_real_type bfd_val;
888
  enum elf_riscv_reloc_type elf_val;
889
};
890
891
static const struct elf_reloc_map riscv_reloc_map[] =
892
{
893
  { BFD_RELOC_NONE, R_RISCV_NONE },
894
  { BFD_RELOC_32, R_RISCV_32 },
895
  { BFD_RELOC_64, R_RISCV_64 },
896
  { BFD_RELOC_RISCV_ADD8, R_RISCV_ADD8 },
897
  { BFD_RELOC_RISCV_ADD16, R_RISCV_ADD16 },
898
  { BFD_RELOC_RISCV_ADD32, R_RISCV_ADD32 },
899
  { BFD_RELOC_RISCV_ADD64, R_RISCV_ADD64 },
900
  { BFD_RELOC_RISCV_SUB8, R_RISCV_SUB8 },
901
  { BFD_RELOC_RISCV_SUB16, R_RISCV_SUB16 },
902
  { BFD_RELOC_RISCV_SUB32, R_RISCV_SUB32 },
903
  { BFD_RELOC_RISCV_SUB64, R_RISCV_SUB64 },
904
  { BFD_RELOC_CTOR, R_RISCV_64 },
905
  { BFD_RELOC_12_PCREL, R_RISCV_BRANCH },
906
  { BFD_RELOC_RISCV_HI20, R_RISCV_HI20 },
907
  { BFD_RELOC_RISCV_LO12_I, R_RISCV_LO12_I },
908
  { BFD_RELOC_RISCV_LO12_S, R_RISCV_LO12_S },
909
  { BFD_RELOC_RISCV_PCREL_LO12_I, R_RISCV_PCREL_LO12_I },
910
  { BFD_RELOC_RISCV_PCREL_LO12_S, R_RISCV_PCREL_LO12_S },
911
  { BFD_RELOC_RISCV_CALL, R_RISCV_CALL },
912
  { BFD_RELOC_RISCV_CALL_PLT, R_RISCV_CALL_PLT },
913
  { BFD_RELOC_RISCV_PCREL_HI20, R_RISCV_PCREL_HI20 },
914
  { BFD_RELOC_RISCV_JMP, R_RISCV_JAL },
915
  { BFD_RELOC_RISCV_GOT_HI20, R_RISCV_GOT_HI20 },
916
  { BFD_RELOC_RISCV_TLS_DTPMOD32, R_RISCV_TLS_DTPMOD32 },
917
  { BFD_RELOC_RISCV_TLS_DTPREL32, R_RISCV_TLS_DTPREL32 },
918
  { BFD_RELOC_RISCV_TLS_DTPMOD64, R_RISCV_TLS_DTPMOD64 },
919
  { BFD_RELOC_RISCV_TLS_DTPREL64, R_RISCV_TLS_DTPREL64 },
920
  { BFD_RELOC_RISCV_TLS_TPREL32, R_RISCV_TLS_TPREL32 },
921
  { BFD_RELOC_RISCV_TLS_TPREL64, R_RISCV_TLS_TPREL64 },
922
  { BFD_RELOC_RISCV_TPREL_HI20, R_RISCV_TPREL_HI20 },
923
  { BFD_RELOC_RISCV_TPREL_ADD, R_RISCV_TPREL_ADD },
924
  { BFD_RELOC_RISCV_TPREL_LO12_S, R_RISCV_TPREL_LO12_S },
925
  { BFD_RELOC_RISCV_TPREL_LO12_I, R_RISCV_TPREL_LO12_I },
926
  { BFD_RELOC_RISCV_TLS_GOT_HI20, R_RISCV_TLS_GOT_HI20 },
927
  { BFD_RELOC_RISCV_TLS_GD_HI20, R_RISCV_TLS_GD_HI20 },
928
  { BFD_RELOC_RISCV_ALIGN, R_RISCV_ALIGN },
929
  { BFD_RELOC_RISCV_RVC_BRANCH, R_RISCV_RVC_BRANCH },
930
  { BFD_RELOC_RISCV_RVC_JUMP, R_RISCV_RVC_JUMP },
931
  { BFD_RELOC_RISCV_RVC_LUI, R_RISCV_RVC_LUI },
932
  { BFD_RELOC_RISCV_GPREL_I, R_RISCV_GPREL_I },
933
  { BFD_RELOC_RISCV_GPREL_S, R_RISCV_GPREL_S },
934
  { BFD_RELOC_RISCV_TPREL_I, R_RISCV_TPREL_I },
935
  { BFD_RELOC_RISCV_TPREL_S, R_RISCV_TPREL_S },
936
  { BFD_RELOC_RISCV_RELAX, R_RISCV_RELAX },
937
  { BFD_RELOC_RISCV_SUB6, R_RISCV_SUB6 },
938
  { BFD_RELOC_RISCV_SET6, R_RISCV_SET6 },
939
  { BFD_RELOC_RISCV_SET8, R_RISCV_SET8 },
940
  { BFD_RELOC_RISCV_SET16, R_RISCV_SET16 },
941
  { BFD_RELOC_RISCV_SET32, R_RISCV_SET32 },
942
  { BFD_RELOC_RISCV_32_PCREL, R_RISCV_32_PCREL },
943
  { BFD_RELOC_RISCV_SET_ULEB128, R_RISCV_SET_ULEB128 },
944
  { BFD_RELOC_RISCV_SUB_ULEB128, R_RISCV_SUB_ULEB128 },
945
};
946
947
/* Given a BFD reloc type, return a howto structure.  */
948
949
reloc_howto_type *
950
riscv_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED,
951
       bfd_reloc_code_real_type code)
952
0
{
953
0
  unsigned int i;
954
955
0
  for (i = 0; i < ARRAY_SIZE (riscv_reloc_map); i++)
956
0
    if (riscv_reloc_map[i].bfd_val == code)
957
0
      return &howto_table[(int) riscv_reloc_map[i].elf_val];
958
959
0
  bfd_set_error (bfd_error_bad_value);
960
0
  return NULL;
961
0
}
962
963
reloc_howto_type *
964
riscv_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED, const char *r_name)
965
0
{
966
0
  unsigned int i;
967
968
0
  for (i = 0; i < ARRAY_SIZE (howto_table); i++)
969
0
    if (howto_table[i].name && strcasecmp (howto_table[i].name, r_name) == 0)
970
0
      return &howto_table[i];
971
972
0
  return NULL;
973
0
}
974
975
reloc_howto_type *
976
riscv_elf_rtype_to_howto (bfd *abfd, unsigned int r_type)
977
0
{
978
0
  if (r_type >= ARRAY_SIZE (howto_table))
979
0
    {
980
0
      (*_bfd_error_handler) (_("%pB: unsupported relocation type %#x"),
981
0
           abfd, r_type);
982
0
      bfd_set_error (bfd_error_bad_value);
983
0
      return NULL;
984
0
    }
985
0
  return &howto_table[r_type];
986
0
}
987
988
/* Special_function of RISCV_ADD and RISCV_SUB relocations.  */
989
990
static bfd_reloc_status_type
991
riscv_elf_add_sub_reloc (bfd *abfd,
992
       arelent *reloc_entry,
993
       asymbol *symbol,
994
       void *data,
995
       asection *input_section,
996
       bfd *output_bfd,
997
       char **error_message ATTRIBUTE_UNUSED)
998
0
{
999
0
  reloc_howto_type *howto = reloc_entry->howto;
1000
0
  bfd_vma relocation;
1001
1002
0
  if (output_bfd != NULL
1003
0
      && (symbol->flags & BSF_SECTION_SYM) == 0
1004
0
      && (!reloc_entry->howto->partial_inplace || reloc_entry->addend == 0))
1005
0
    {
1006
0
      reloc_entry->address += input_section->output_offset;
1007
0
      return bfd_reloc_ok;
1008
0
    }
1009
1010
0
  if (output_bfd != NULL)
1011
0
    return bfd_reloc_continue;
1012
1013
0
  relocation = symbol->value + symbol->section->output_section->vma
1014
0
    + symbol->section->output_offset + reloc_entry->addend;
1015
1016
0
  bfd_size_type octets = reloc_entry->address
1017
0
    * bfd_octets_per_byte (abfd, input_section);
1018
0
  if (!bfd_reloc_offset_in_range (reloc_entry->howto, abfd,
1019
0
          input_section, octets))
1020
0
    return bfd_reloc_outofrange;
1021
1022
0
  bfd_vma old_value = bfd_get (howto->bitsize, abfd,
1023
0
             data + reloc_entry->address);
1024
1025
0
  switch (howto->type)
1026
0
    {
1027
0
    case R_RISCV_ADD8:
1028
0
    case R_RISCV_ADD16:
1029
0
    case R_RISCV_ADD32:
1030
0
    case R_RISCV_ADD64:
1031
0
      relocation = old_value + relocation;
1032
0
      break;
1033
0
    case R_RISCV_SUB6:
1034
0
      relocation = (old_value & ~howto->dst_mask)
1035
0
       | (((old_value & howto->dst_mask) - relocation)
1036
0
          & howto->dst_mask);
1037
0
      break;
1038
0
    case R_RISCV_SUB8:
1039
0
    case R_RISCV_SUB16:
1040
0
    case R_RISCV_SUB32:
1041
0
    case R_RISCV_SUB64:
1042
0
      relocation = old_value - relocation;
1043
0
      break;
1044
0
    }
1045
0
  bfd_put (howto->bitsize, abfd, relocation, data + reloc_entry->address);
1046
1047
0
  return bfd_reloc_ok;
1048
0
}
1049
1050
/* Special handler for relocations which don't have to be relocated.
1051
   This function just simply return bfd_reloc_ok.  */
1052
1053
static bfd_reloc_status_type
1054
riscv_elf_ignore_reloc (bfd *abfd ATTRIBUTE_UNUSED,
1055
      arelent *reloc_entry,
1056
      asymbol *symbol ATTRIBUTE_UNUSED,
1057
      void *data ATTRIBUTE_UNUSED,
1058
      asection *input_section,
1059
      bfd *output_bfd,
1060
      char **error_message ATTRIBUTE_UNUSED)
1061
0
{
1062
0
  if (output_bfd != NULL)
1063
0
    reloc_entry->address += input_section->output_offset;
1064
0
  return bfd_reloc_ok;
1065
0
}
1066
1067
/* Always add the IMPLICIT for the SUBSET.  */
1068
1069
static bool
1070
check_implicit_always (const char *implicit ATTRIBUTE_UNUSED,
1071
           riscv_subset_t *subset ATTRIBUTE_UNUSED)
1072
0
{
1073
0
  return true;
1074
0
}
1075
1076
/* Add the IMPLICIT only when the version of SUBSET less than 2.1.  */
1077
1078
static bool
1079
check_implicit_for_i (const char *implicit ATTRIBUTE_UNUSED,
1080
          riscv_subset_t *subset)
1081
0
{
1082
0
  return (subset->major_version < 2
1083
0
    || (subset->major_version == 2
1084
0
        && subset->minor_version < 1));
1085
0
}
1086
1087
/* Record all implicit information for the subsets.  */
1088
struct riscv_implicit_subset
1089
{
1090
  const char *subset_name;
1091
  const char *implicit_name;
1092
  /* A function to determine if we need to add the implicit subset.  */
1093
  bool (*check_func) (const char *, riscv_subset_t *);
1094
};
1095
static struct riscv_implicit_subset riscv_implicit_subsets[] =
1096
{
1097
  {"e", "i",    check_implicit_always},
1098
  {"i", "zicsr",  check_implicit_for_i},
1099
  {"i", "zifencei", check_implicit_for_i},
1100
  {"g", "i",    check_implicit_always},
1101
  {"g", "m",    check_implicit_always},
1102
  {"g", "a",    check_implicit_always},
1103
  {"g", "f",    check_implicit_always},
1104
  {"g", "d",    check_implicit_always},
1105
  {"g", "zicsr",  check_implicit_always},
1106
  {"g", "zifencei", check_implicit_always},
1107
  {"m", "zmmul",  check_implicit_always},
1108
  {"h", "zicsr",  check_implicit_always},
1109
  {"q", "d",    check_implicit_always},
1110
  {"v", "d",    check_implicit_always},
1111
  {"v", "zve64d", check_implicit_always},
1112
  {"v", "zvl128b",  check_implicit_always},
1113
  {"zvfh", "zvfhmin", check_implicit_always},
1114
  {"zvfh", "zfhmin",  check_implicit_always},
1115
  {"zvfhmin", "zve32f", check_implicit_always},
1116
  {"zve64d", "d", check_implicit_always},
1117
  {"zve64d", "zve64f",  check_implicit_always},
1118
  {"zve64f", "zve32f",  check_implicit_always},
1119
  {"zve64f", "zve64x",  check_implicit_always},
1120
  {"zve64f", "zvl64b",  check_implicit_always},
1121
  {"zve32f", "f", check_implicit_always},
1122
  {"zve32f", "zvl32b",  check_implicit_always},
1123
  {"zve32f", "zve32x",  check_implicit_always},
1124
  {"zve64x", "zve32x",  check_implicit_always},
1125
  {"zve64x", "zvl64b",  check_implicit_always},
1126
  {"zve32x", "zvl32b",  check_implicit_always},
1127
  {"zve32x", "zicsr", check_implicit_always},
1128
  {"zvl65536b", "zvl32768b",  check_implicit_always},
1129
  {"zvl32768b", "zvl16384b",  check_implicit_always},
1130
  {"zvl16384b", "zvl8192b", check_implicit_always},
1131
  {"zvl8192b", "zvl4096b",  check_implicit_always},
1132
  {"zvl4096b", "zvl2048b",  check_implicit_always},
1133
  {"zvl2048b", "zvl1024b",  check_implicit_always},
1134
  {"zvl1024b", "zvl512b", check_implicit_always},
1135
  {"zvl512b", "zvl256b",  check_implicit_always},
1136
  {"zvl256b", "zvl128b",  check_implicit_always},
1137
  {"zvl128b", "zvl64b",   check_implicit_always},
1138
  {"zvl64b", "zvl32b",    check_implicit_always},
1139
  {"zcd", "d",    check_implicit_always},
1140
  {"zcf", "f",    check_implicit_always},
1141
  {"zfa", "f",    check_implicit_always},
1142
  {"d", "f",    check_implicit_always},
1143
  {"zfh", "zfhmin", check_implicit_always},
1144
  {"zfhmin", "f", check_implicit_always},
1145
  {"f", "zicsr",  check_implicit_always},
1146
  {"zqinx", "zdinx",  check_implicit_always},
1147
  {"zdinx", "zfinx",  check_implicit_always},
1148
  {"zhinx", "zhinxmin", check_implicit_always},
1149
  {"zhinxmin", "zfinx", check_implicit_always},
1150
  {"zfinx", "zicsr",  check_implicit_always},
1151
  {"zk", "zkn",   check_implicit_always},
1152
  {"zk", "zkr",   check_implicit_always},
1153
  {"zk", "zkt",   check_implicit_always},
1154
  {"zkn", "zbkb", check_implicit_always},
1155
  {"zkn", "zbkc", check_implicit_always},
1156
  {"zkn", "zbkx", check_implicit_always},
1157
  {"zkn", "zkne", check_implicit_always},
1158
  {"zkn", "zknd", check_implicit_always},
1159
  {"zkn", "zknh", check_implicit_always},
1160
  {"zks", "zbkb", check_implicit_always},
1161
  {"zks", "zbkc", check_implicit_always},
1162
  {"zks", "zbkx", check_implicit_always},
1163
  {"zks", "zksed",  check_implicit_always},
1164
  {"zks", "zksh", check_implicit_always},
1165
  {"zvkn", "zvkned",  check_implicit_always},
1166
  {"zvkn", "zvknha",  check_implicit_always},
1167
  {"zvkn", "zvknhb",  check_implicit_always},
1168
  {"zvkn", "zvbb",  check_implicit_always},
1169
  {"zvkn", "zvkt",  check_implicit_always},
1170
  {"zvkng", "zvkn", check_implicit_always},
1171
  {"zvkng", "zvkg", check_implicit_always},
1172
  {"zvknc", "zvkn", check_implicit_always},
1173
  {"zvknc", "zvbc", check_implicit_always},
1174
  {"zvks", "zvksed",  check_implicit_always},
1175
  {"zvks", "zvksh", check_implicit_always},
1176
  {"zvks", "zvbb",  check_implicit_always},
1177
  {"zvks", "zvkt",  check_implicit_always},
1178
  {"zvksg", "zvks", check_implicit_always},
1179
  {"zvksg", "zvkg", check_implicit_always},
1180
  {"zvksc", "zvks", check_implicit_always},
1181
  {"zvksc", "zvbc", check_implicit_always},
1182
  {"zcf", "zca",  check_implicit_always},
1183
  {"zcd", "zca",  check_implicit_always},
1184
  {"zcb", "zca",  check_implicit_always},
1185
  {"smaia", "ssaia",    check_implicit_always},
1186
  {"smstateen", "ssstateen",  check_implicit_always},
1187
  {"smepmp", "zicsr",   check_implicit_always},
1188
  {"ssaia", "zicsr",    check_implicit_always},
1189
  {"sscofpmf", "zicsr",   check_implicit_always},
1190
  {"ssstateen", "zicsr",  check_implicit_always},
1191
  {"sstc", "zicsr",   check_implicit_always},
1192
  {NULL, NULL, NULL}
1193
};
1194
1195
/* For default_enable field, decide if the extension should
1196
   be enbaled by default.  */
1197
1198
0
#define EXT_DEFAULT   0x1
1199
1200
/* List all extensions that binutils should know about.  */
1201
1202
struct riscv_supported_ext
1203
{
1204
  const char *name;
1205
  enum riscv_spec_class isa_spec_class;
1206
  int major_version;
1207
  int minor_version;
1208
  unsigned long default_enable;
1209
};
1210
1211
/* The standard extensions must be added in canonical order.  */
1212
1213
static struct riscv_supported_ext riscv_supported_std_ext[] =
1214
{
1215
  {"e",   ISA_SPEC_CLASS_20191213,  1, 9, 0 },
1216
  {"e",   ISA_SPEC_CLASS_20190608,  1, 9, 0 },
1217
  {"e",   ISA_SPEC_CLASS_2P2,   1, 9, 0 },
1218
  {"i",   ISA_SPEC_CLASS_20191213,  2, 1, 0 },
1219
  {"i",   ISA_SPEC_CLASS_20190608,  2, 1, 0 },
1220
  {"i",   ISA_SPEC_CLASS_2P2,   2, 0, 0 },
1221
  /* The g is a special case which we don't want to output it,
1222
     but still need it when adding implicit extensions.  */
1223
  {"g",   ISA_SPEC_CLASS_NONE, RISCV_UNKNOWN_VERSION, RISCV_UNKNOWN_VERSION, EXT_DEFAULT },
1224
  {"m",   ISA_SPEC_CLASS_20191213,  2, 0, 0 },
1225
  {"m",   ISA_SPEC_CLASS_20190608,  2, 0, 0 },
1226
  {"m",   ISA_SPEC_CLASS_2P2,   2, 0, 0 },
1227
  {"a",   ISA_SPEC_CLASS_20191213,  2, 1, 0 },
1228
  {"a",   ISA_SPEC_CLASS_20190608,  2, 0, 0 },
1229
  {"a",   ISA_SPEC_CLASS_2P2,   2, 0, 0 },
1230
  {"f",   ISA_SPEC_CLASS_20191213,  2, 2, 0 },
1231
  {"f",   ISA_SPEC_CLASS_20190608,  2, 2, 0 },
1232
  {"f",   ISA_SPEC_CLASS_2P2,   2, 0, 0 },
1233
  {"d",   ISA_SPEC_CLASS_20191213,  2, 2, 0 },
1234
  {"d",   ISA_SPEC_CLASS_20190608,  2, 2, 0 },
1235
  {"d",   ISA_SPEC_CLASS_2P2,   2, 0, 0 },
1236
  {"q",   ISA_SPEC_CLASS_20191213,  2, 2, 0 },
1237
  {"q",   ISA_SPEC_CLASS_20190608,  2, 2, 0 },
1238
  {"q",   ISA_SPEC_CLASS_2P2,   2, 0, 0 },
1239
  {"c",   ISA_SPEC_CLASS_20191213,  2, 0, 0 },
1240
  {"c",   ISA_SPEC_CLASS_20190608,  2, 0, 0 },
1241
  {"c",   ISA_SPEC_CLASS_2P2,   2, 0, 0 },
1242
  {"v",   ISA_SPEC_CLASS_DRAFT,   1, 0, 0 },
1243
  {"h",   ISA_SPEC_CLASS_DRAFT,   1, 0, 0 },
1244
  {NULL, 0, 0, 0, 0}
1245
};
1246
1247
static struct riscv_supported_ext riscv_supported_std_z_ext[] =
1248
{
1249
  {"zicbom",    ISA_SPEC_CLASS_DRAFT,   1, 0,  0 },
1250
  {"zicbop",    ISA_SPEC_CLASS_DRAFT,   1, 0,  0 },
1251
  {"zicboz",    ISA_SPEC_CLASS_DRAFT,   1, 0,  0 },
1252
  {"zicond",    ISA_SPEC_CLASS_DRAFT,   1, 0,  0 },
1253
  {"zicsr",   ISA_SPEC_CLASS_20191213,  2, 0,  0 },
1254
  {"zicsr",   ISA_SPEC_CLASS_20190608,  2, 0,  0 },
1255
  {"zifencei",    ISA_SPEC_CLASS_20191213,  2, 0,  0 },
1256
  {"zifencei",    ISA_SPEC_CLASS_20190608,  2, 0,  0 },
1257
  {"zihintntl",   ISA_SPEC_CLASS_DRAFT,   1, 0,  0 },
1258
  {"zihintpause", ISA_SPEC_CLASS_DRAFT,   2, 0,  0 },
1259
  {"zmmul",   ISA_SPEC_CLASS_DRAFT,   1, 0,  0 },
1260
  {"zawrs",   ISA_SPEC_CLASS_DRAFT,   1, 0,  0 },
1261
  {"zfa",   ISA_SPEC_CLASS_DRAFT,   0, 1,  0 },
1262
  {"zfh",   ISA_SPEC_CLASS_DRAFT,   1, 0,  0 },
1263
  {"zfhmin",    ISA_SPEC_CLASS_DRAFT,   1, 0,  0 },
1264
  {"zfinx",   ISA_SPEC_CLASS_DRAFT,   1, 0,  0 },
1265
  {"zdinx",   ISA_SPEC_CLASS_DRAFT,   1, 0,  0 },
1266
  {"zqinx",   ISA_SPEC_CLASS_DRAFT,   1, 0,  0 },
1267
  {"zhinx",   ISA_SPEC_CLASS_DRAFT,   1, 0,  0 },
1268
  {"zhinxmin",    ISA_SPEC_CLASS_DRAFT,   1, 0,  0 },
1269
  {"zbb",   ISA_SPEC_CLASS_DRAFT,   1, 0,  0 },
1270
  {"zba",   ISA_SPEC_CLASS_DRAFT,   1, 0,  0 },
1271
  {"zbc",   ISA_SPEC_CLASS_DRAFT,   1, 0,  0 },
1272
  {"zbs",   ISA_SPEC_CLASS_DRAFT,   1, 0,  0 },
1273
  {"zbkb",    ISA_SPEC_CLASS_DRAFT,   1, 0,  0 },
1274
  {"zbkc",    ISA_SPEC_CLASS_DRAFT,   1, 0,  0 },
1275
  {"zbkx",    ISA_SPEC_CLASS_DRAFT,   1, 0,  0 },
1276
  {"zk",    ISA_SPEC_CLASS_DRAFT,   1, 0,  0 },
1277
  {"zkn",   ISA_SPEC_CLASS_DRAFT,   1, 0,  0 },
1278
  {"zknd",    ISA_SPEC_CLASS_DRAFT,   1, 0,  0 },
1279
  {"zkne",    ISA_SPEC_CLASS_DRAFT,   1, 0,  0 },
1280
  {"zknh",    ISA_SPEC_CLASS_DRAFT,   1, 0,  0 },
1281
  {"zkr",   ISA_SPEC_CLASS_DRAFT,   1, 0,  0 },
1282
  {"zks",   ISA_SPEC_CLASS_DRAFT,   1, 0,  0 },
1283
  {"zksed",   ISA_SPEC_CLASS_DRAFT,   1, 0,  0 },
1284
  {"zksh",    ISA_SPEC_CLASS_DRAFT,   1, 0,  0 },
1285
  {"zkt",   ISA_SPEC_CLASS_DRAFT,   1, 0,  0 },
1286
  {"zve32x",    ISA_SPEC_CLASS_DRAFT,   1, 0,  0 },
1287
  {"zve32f",    ISA_SPEC_CLASS_DRAFT,   1, 0,  0 },
1288
  {"zve64x",    ISA_SPEC_CLASS_DRAFT,   1, 0,  0 },
1289
  {"zve64f",    ISA_SPEC_CLASS_DRAFT,   1, 0,  0 },
1290
  {"zve64d",    ISA_SPEC_CLASS_DRAFT,   1, 0,  0 },
1291
  {"zvbb",    ISA_SPEC_CLASS_DRAFT,   1, 0,  0 },
1292
  {"zvbc",    ISA_SPEC_CLASS_DRAFT,   1, 0,  0 },
1293
  {"zvfh",    ISA_SPEC_CLASS_DRAFT,   1, 0,  0 },
1294
  {"zvfhmin",   ISA_SPEC_CLASS_DRAFT,   1, 0,  0 },
1295
  {"zvkg",    ISA_SPEC_CLASS_DRAFT,   1, 0,  0 },
1296
  {"zvkn",    ISA_SPEC_CLASS_DRAFT,   1, 0,  0 },
1297
  {"zvkng",   ISA_SPEC_CLASS_DRAFT,   1, 0,  0 },
1298
  {"zvknc",   ISA_SPEC_CLASS_DRAFT,   1, 0,  0 },
1299
  {"zvkned",    ISA_SPEC_CLASS_DRAFT,   1, 0,  0 },
1300
  {"zvknha",    ISA_SPEC_CLASS_DRAFT,   1, 0,  0 },
1301
  {"zvknhb",    ISA_SPEC_CLASS_DRAFT,   1, 0,  0 },
1302
  {"zvksed",    ISA_SPEC_CLASS_DRAFT,   1, 0,  0 },
1303
  {"zvksh",   ISA_SPEC_CLASS_DRAFT,   1, 0,  0 },
1304
  {"zvks",    ISA_SPEC_CLASS_DRAFT,   1, 0,  0 },
1305
  {"zvksg",   ISA_SPEC_CLASS_DRAFT,   1, 0,  0 },
1306
  {"zvksc",   ISA_SPEC_CLASS_DRAFT,   1, 0,  0 },
1307
  {"zvkt",    ISA_SPEC_CLASS_DRAFT,   1, 0,  0 },
1308
  {"zvl32b",    ISA_SPEC_CLASS_DRAFT,   1, 0,  0 },
1309
  {"zvl64b",    ISA_SPEC_CLASS_DRAFT,   1, 0,  0 },
1310
  {"zvl128b",   ISA_SPEC_CLASS_DRAFT,   1, 0,  0 },
1311
  {"zvl256b",   ISA_SPEC_CLASS_DRAFT,   1, 0,  0 },
1312
  {"zvl512b",   ISA_SPEC_CLASS_DRAFT,   1, 0,  0 },
1313
  {"zvl1024b",    ISA_SPEC_CLASS_DRAFT,   1, 0,  0 },
1314
  {"zvl2048b",    ISA_SPEC_CLASS_DRAFT,   1, 0,  0 },
1315
  {"zvl4096b",    ISA_SPEC_CLASS_DRAFT,   1, 0,  0 },
1316
  {"zvl8192b",    ISA_SPEC_CLASS_DRAFT,   1, 0,  0 },
1317
  {"zvl16384b",   ISA_SPEC_CLASS_DRAFT,   1, 0,  0 },
1318
  {"zvl32768b",   ISA_SPEC_CLASS_DRAFT,   1, 0,  0 },
1319
  {"zvl65536b",   ISA_SPEC_CLASS_DRAFT,   1, 0,  0 },
1320
  {"ztso",    ISA_SPEC_CLASS_DRAFT,   1, 0,  0 },
1321
  {"zca",   ISA_SPEC_CLASS_DRAFT,   1, 0,  0 },
1322
  {"zcb",   ISA_SPEC_CLASS_DRAFT,   1, 0,  0 },
1323
  {"zcf",   ISA_SPEC_CLASS_DRAFT,   1, 0,  0 },
1324
  {"zcd",   ISA_SPEC_CLASS_DRAFT,   1, 0,  0 },
1325
  {NULL, 0, 0, 0, 0}
1326
};
1327
1328
static struct riscv_supported_ext riscv_supported_std_s_ext[] =
1329
{
1330
  {"smaia",   ISA_SPEC_CLASS_DRAFT,   1, 0, 0 },
1331
  {"smepmp",    ISA_SPEC_CLASS_DRAFT,   1, 0, 0 },
1332
  {"smstateen",   ISA_SPEC_CLASS_DRAFT,   1, 0, 0 },
1333
  {"ssaia",   ISA_SPEC_CLASS_DRAFT,   1, 0, 0 },
1334
  {"sscofpmf",    ISA_SPEC_CLASS_DRAFT,   1, 0, 0 },
1335
  {"ssstateen",   ISA_SPEC_CLASS_DRAFT,   1, 0, 0 },
1336
  {"sstc",    ISA_SPEC_CLASS_DRAFT,   1, 0, 0 },
1337
  {"svinval",   ISA_SPEC_CLASS_DRAFT,   1, 0, 0 },
1338
  {"svnapot",   ISA_SPEC_CLASS_DRAFT,   1, 0, 0 },
1339
  {"svpbmt",    ISA_SPEC_CLASS_DRAFT,   1, 0, 0 },
1340
  {NULL, 0, 0, 0, 0}
1341
};
1342
1343
static struct riscv_supported_ext riscv_supported_std_zxm_ext[] =
1344
{
1345
  {NULL, 0, 0, 0, 0}
1346
};
1347
1348
static struct riscv_supported_ext riscv_supported_vendor_x_ext[] =
1349
{
1350
  {"xtheadba",    ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1351
  {"xtheadbb",    ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1352
  {"xtheadbs",    ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1353
  {"xtheadcmo",   ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1354
  {"xtheadcondmov", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1355
  {"xtheadfmemidx", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1356
  {"xtheadfmv",   ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1357
  {"xtheadint",   ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1358
  {"xtheadmac",   ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1359
  {"xtheadmemidx",  ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1360
  {"xtheadmempair", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1361
  {"xtheadsync",  ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1362
  /* XVentanaCondOps: https://github.com/ventanamicro/ventana-custom-extensions/releases/download/v1.0.0/ventana-custom-extensions-v1.0.0.pdf */
1363
  {"xventanacondops", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1364
  {NULL, 0, 0, 0, 0}
1365
};
1366
1367
const struct riscv_supported_ext *riscv_all_supported_ext[] =
1368
{
1369
  riscv_supported_std_ext,
1370
  riscv_supported_std_z_ext,
1371
  riscv_supported_std_s_ext,
1372
  riscv_supported_std_zxm_ext,
1373
  riscv_supported_vendor_x_ext,
1374
  NULL
1375
};
1376
1377
/* ISA extension prefixed name class.  Must define them in parsing order.  */
1378
enum riscv_prefix_ext_class
1379
{
1380
  RV_ISA_CLASS_Z = 1,
1381
  RV_ISA_CLASS_S,
1382
  RV_ISA_CLASS_ZXM,
1383
  RV_ISA_CLASS_X,
1384
  RV_ISA_CLASS_SINGLE
1385
};
1386
1387
/* Record the strings of the prefixed extensions, and their corresponding
1388
   classes.  The more letters of the prefix string, the more forward it must
1389
   be defined.  Otherwise, the riscv_get_prefix_class will map it to the
1390
   wrong classes.  */
1391
struct riscv_parse_prefix_config
1392
{
1393
  /* Class of the extension. */
1394
  enum riscv_prefix_ext_class class;
1395
1396
  /* Prefix string for error printing and internal parser usage.  */
1397
  const char *prefix;
1398
};
1399
static const struct riscv_parse_prefix_config parse_config[] =
1400
{
1401
  {RV_ISA_CLASS_ZXM, "zxm"},
1402
  {RV_ISA_CLASS_Z, "z"},
1403
  {RV_ISA_CLASS_S, "s"},
1404
  {RV_ISA_CLASS_X, "x"},
1405
  {RV_ISA_CLASS_SINGLE, NULL}
1406
};
1407
1408
/* Get the prefixed name class for the extensions, the class also
1409
   means the order of the prefixed extensions.  */
1410
1411
static enum riscv_prefix_ext_class
1412
riscv_get_prefix_class (const char *arch)
1413
0
{
1414
0
  int i = 0;
1415
0
  while (parse_config[i].class != RV_ISA_CLASS_SINGLE)
1416
0
    {
1417
0
      if (strncmp (arch, parse_config[i].prefix,
1418
0
       strlen (parse_config[i].prefix)) == 0)
1419
0
  return parse_config[i].class;
1420
0
      i++;
1421
0
    }
1422
0
  return RV_ISA_CLASS_SINGLE;
1423
0
}
1424
1425
/* Check KNOWN_EXTS to see if the EXT is supported.  */
1426
1427
static bool
1428
riscv_known_prefixed_ext (const char *ext,
1429
        struct riscv_supported_ext *known_exts)
1430
0
{
1431
0
  size_t i;
1432
0
  for (i = 0; known_exts[i].name != NULL; ++i)
1433
0
    if (strcmp (ext, known_exts[i].name) == 0)
1434
0
      return true;
1435
0
  return false;
1436
0
}
1437
1438
/* Check whether the prefixed extension is recognized or not.  Return
1439
   true if recognized, otehrwise return false.  */
1440
1441
static bool
1442
riscv_recognized_prefixed_ext (const char *ext)
1443
0
{
1444
0
  enum riscv_prefix_ext_class class = riscv_get_prefix_class (ext);
1445
0
  switch (class)
1446
0
  {
1447
0
  case RV_ISA_CLASS_Z:
1448
0
    return riscv_known_prefixed_ext (ext, riscv_supported_std_z_ext);
1449
0
  case RV_ISA_CLASS_ZXM:
1450
0
    return riscv_known_prefixed_ext (ext, riscv_supported_std_zxm_ext);
1451
0
  case RV_ISA_CLASS_S:
1452
0
    return riscv_known_prefixed_ext (ext, riscv_supported_std_s_ext);
1453
0
  case RV_ISA_CLASS_X:
1454
    /* Only the single x is unrecognized.  */
1455
0
    if (strcmp (ext, "x") != 0)
1456
0
      return true;
1457
0
  default:
1458
0
    break;
1459
0
  }
1460
0
  return false;
1461
0
}
1462
1463
/* Canonical order for single letter extensions.  */
1464
static const char riscv_ext_canonical_order[] = "eigmafdqlcbkjtpvnh";
1465
1466
/* Array is used to compare the orders of standard extensions quickly.  */
1467
static int riscv_ext_order[26] = {0};
1468
1469
/* Init the riscv_ext_order array.  */
1470
1471
static void
1472
riscv_init_ext_order (void)
1473
0
{
1474
0
  static bool inited = false;
1475
0
  if (inited)
1476
0
    return;
1477
1478
  /* The orders of all standard extensions are positive.  */
1479
0
  int order = 1;
1480
1481
0
  for (const char *ext = &riscv_ext_canonical_order[0]; *ext; ++ext)
1482
0
    riscv_ext_order[(*ext - 'a')] = order++;
1483
1484
  /* Some of the prefixed keyword are not single letter, so we set
1485
     their prefixed orders in the riscv_compare_subsets directly,
1486
     not through the riscv_ext_order.  */
1487
1488
0
  inited = true;
1489
0
}
1490
1491
/* Similar to the strcmp.  It returns an integer less than, equal to,
1492
   or greater than zero if `subset2` is found, respectively, to be less
1493
   than, to match, or be greater than `subset1`.
1494
1495
   The order values,
1496
   Zero: Preserved keywords.
1497
   Positive number: Standard extensions.
1498
   Negative number: Prefixed keywords.  */
1499
1500
int
1501
riscv_compare_subsets (const char *subset1, const char *subset2)
1502
0
{
1503
0
  int order1 = riscv_ext_order[(*subset1 - 'a')];
1504
0
  int order2 = riscv_ext_order[(*subset2 - 'a')];
1505
1506
  /* Compare the standard extension first.  */
1507
0
  if (order1 > 0 && order2 > 0)
1508
0
    return order1 - order2;
1509
1510
  /* Set the prefixed orders to negative numbers.  */
1511
0
  enum riscv_prefix_ext_class class1 = riscv_get_prefix_class (subset1);
1512
0
  enum riscv_prefix_ext_class class2 = riscv_get_prefix_class (subset2);
1513
1514
0
  if (class1 != RV_ISA_CLASS_SINGLE)
1515
0
    order1 = - (int) class1;
1516
0
  if (class2 != RV_ISA_CLASS_SINGLE)
1517
0
    order2 = - (int) class2;
1518
1519
0
  if (order1 == order2)
1520
0
    {
1521
      /* Compare the standard addition z extensions.  */
1522
0
      if (class1 == RV_ISA_CLASS_Z)
1523
0
  {
1524
0
    order1 = riscv_ext_order[(*++subset1 - 'a')];
1525
0
    order2 = riscv_ext_order[(*++subset2 - 'a')];
1526
0
    if (order1 != order2)
1527
0
      return order1 - order2;
1528
0
  }
1529
0
      return strcasecmp (++subset1, ++subset2);
1530
0
    }
1531
1532
0
  return order2 - order1;
1533
0
}
1534
1535
/* Find subset in the list.  Return TRUE and set `current` to the subset
1536
   if it is found.  Otherwise, return FALSE and set `current` to the place
1537
   where we should insert the subset.  However, return FALSE with the NULL
1538
   `current` means we should insert the subset at the head of subset list,
1539
   if needed.  */
1540
1541
bool
1542
riscv_lookup_subset (const riscv_subset_list_t *subset_list,
1543
         const char *subset,
1544
         riscv_subset_t **current)
1545
0
{
1546
0
  riscv_subset_t *s, *pre_s = NULL;
1547
1548
  /* If the subset is added in order, then just add it at the tail.  */
1549
0
  if (subset_list->tail != NULL
1550
0
      && riscv_compare_subsets (subset_list->tail->name, subset) < 0)
1551
0
    {
1552
0
      *current = subset_list->tail;
1553
0
      return false;
1554
0
    }
1555
1556
0
  for (s = subset_list->head;
1557
0
       s != NULL;
1558
0
       pre_s = s, s = s->next)
1559
0
    {
1560
0
      int cmp = riscv_compare_subsets (s->name, subset);
1561
0
      if (cmp == 0)
1562
0
  {
1563
0
    *current = s;
1564
0
    return true;
1565
0
  }
1566
0
      else if (cmp > 0)
1567
0
  break;
1568
0
    }
1569
0
  *current = pre_s;
1570
1571
0
  return false;
1572
0
}
1573
1574
/* Add the extension to the subset list.  Search the
1575
   list first, and then find the right place to add.  */
1576
1577
void
1578
riscv_add_subset (riscv_subset_list_t *subset_list,
1579
      const char *subset,
1580
      int major,
1581
      int minor)
1582
0
{
1583
0
  riscv_subset_t *current, *new;
1584
1585
0
  if (riscv_lookup_subset (subset_list, subset, &current))
1586
0
    return;
1587
1588
0
  new = xmalloc (sizeof *new);
1589
0
  new->name = xstrdup (subset);
1590
0
  new->major_version = major;
1591
0
  new->minor_version = minor;
1592
0
  new->next = NULL;
1593
1594
0
  if (current != NULL)
1595
0
    {
1596
0
      new->next = current->next;
1597
0
      current->next = new;
1598
0
    }
1599
0
  else
1600
0
    {
1601
0
      new->next = subset_list->head;
1602
0
      subset_list->head = new;
1603
0
    }
1604
1605
0
  if (new->next == NULL)
1606
0
    subset_list->tail = new;
1607
0
}
1608
1609
/* Get the default versions from the riscv_supported_*ext tables.  */
1610
1611
static void
1612
riscv_get_default_ext_version (enum riscv_spec_class *default_isa_spec,
1613
             const char *name,
1614
             int *major_version,
1615
             int *minor_version)
1616
0
{
1617
0
  if (name == NULL
1618
0
      || default_isa_spec == NULL
1619
0
      || *default_isa_spec == ISA_SPEC_CLASS_NONE)
1620
0
    return;
1621
1622
0
  struct riscv_supported_ext *table = NULL;
1623
0
  enum riscv_prefix_ext_class class = riscv_get_prefix_class (name);
1624
0
  switch (class)
1625
0
    {
1626
0
    case RV_ISA_CLASS_ZXM: table = riscv_supported_std_zxm_ext; break;
1627
0
    case RV_ISA_CLASS_Z: table = riscv_supported_std_z_ext; break;
1628
0
    case RV_ISA_CLASS_S: table = riscv_supported_std_s_ext; break;
1629
0
    case RV_ISA_CLASS_X: table = riscv_supported_vendor_x_ext; break;
1630
0
    default:
1631
0
      table = riscv_supported_std_ext;
1632
0
    }
1633
1634
0
  int i = 0;
1635
0
  while (table != NULL && table[i].name != NULL)
1636
0
    {
1637
0
      if (strcmp (table[i].name, name) == 0
1638
0
    && (table[i].isa_spec_class == ISA_SPEC_CLASS_DRAFT
1639
0
        || table[i].isa_spec_class == *default_isa_spec))
1640
0
  {
1641
0
    *major_version = table[i].major_version;
1642
0
    *minor_version = table[i].minor_version;
1643
0
    return;
1644
0
  }
1645
0
      i++;
1646
0
    }
1647
0
}
1648
1649
/* Find the default versions for the extension before adding them to
1650
   the subset list, if their versions are RISCV_UNKNOWN_VERSION.
1651
   Afterwards, report errors if we can not find their default versions.  */
1652
1653
static void
1654
riscv_parse_add_subset (riscv_parse_subset_t *rps,
1655
      const char *subset,
1656
      int major,
1657
      int minor,
1658
      bool implicit)
1659
0
{
1660
0
  int major_version = major;
1661
0
  int minor_version = minor;
1662
1663
0
  if (major_version == RISCV_UNKNOWN_VERSION
1664
0
       || minor_version == RISCV_UNKNOWN_VERSION)
1665
0
    riscv_get_default_ext_version (rps->isa_spec, subset,
1666
0
           &major_version, &minor_version);
1667
1668
  /* We don't care the versions of the implicit extensions.  */
1669
0
  if (!implicit
1670
0
      && (major_version == RISCV_UNKNOWN_VERSION
1671
0
    || minor_version == RISCV_UNKNOWN_VERSION))
1672
0
    {
1673
0
      if (subset[0] == 'x')
1674
0
  rps->error_handler
1675
0
    (_("x ISA extension `%s' must be set with the versions"),
1676
0
     subset);
1677
      /* Allow old ISA spec can recognize zicsr and zifencei.  */
1678
0
      else if (strcmp (subset, "zicsr") != 0
1679
0
         && strcmp (subset, "zifencei") != 0)
1680
0
  rps->error_handler
1681
0
    (_("cannot find default versions of the ISA extension `%s'"),
1682
0
     subset);
1683
0
      return;
1684
0
    }
1685
1686
0
  riscv_add_subset (rps->subset_list, subset,
1687
0
        major_version, minor_version);
1688
0
}
1689
1690
/* Release subset list.  */
1691
1692
void
1693
riscv_release_subset_list (riscv_subset_list_t *subset_list)
1694
0
{
1695
0
   while (subset_list->head != NULL)
1696
0
    {
1697
0
      riscv_subset_t *next = subset_list->head->next;
1698
0
      free ((void *)subset_list->head->name);
1699
0
      free (subset_list->head);
1700
0
      subset_list->head = next;
1701
0
    }
1702
1703
0
  subset_list->tail = NULL;
1704
1705
0
  if (subset_list->arch_str != NULL)
1706
0
    {
1707
0
      free ((void*) subset_list->arch_str);
1708
0
      subset_list->arch_str = NULL;
1709
0
    }
1710
0
}
1711
1712
/* Parsing extension version.
1713
1714
   Return Value:
1715
     Points to the end of version
1716
1717
   Arguments:
1718
     `p`: Curent parsing position.
1719
     `major_version`: Parsed major version.
1720
     `minor_version`: Parsed minor version.  */
1721
1722
static const char *
1723
riscv_parsing_subset_version (const char *p,
1724
            int *major_version,
1725
            int *minor_version)
1726
0
{
1727
0
  bool major_p = true;
1728
0
  int version = 0;
1729
0
  char np;
1730
1731
0
  *major_version = 0;
1732
0
  *minor_version = 0;
1733
0
  for (; *p; ++p)
1734
0
    {
1735
0
      if (*p == 'p')
1736
0
  {
1737
0
    np = *(p + 1);
1738
1739
    /* Might be beginning of `p` extension.  */
1740
0
    if (!ISDIGIT (np))
1741
0
      break;
1742
1743
0
    *major_version = version;
1744
0
    major_p = false;
1745
0
    version = 0;
1746
0
  }
1747
0
      else if (ISDIGIT (*p))
1748
0
  version = (version * 10) + (*p - '0');
1749
0
      else
1750
0
  break;
1751
0
    }
1752
1753
0
  if (major_p)
1754
0
    *major_version = version;
1755
0
  else
1756
0
    *minor_version = version;
1757
1758
  /* We can not find any version in string.  */
1759
0
  if (*major_version == 0 && *minor_version == 0)
1760
0
    {
1761
0
      *major_version = RISCV_UNKNOWN_VERSION;
1762
0
      *minor_version = RISCV_UNKNOWN_VERSION;
1763
0
    }
1764
1765
0
  return p;
1766
0
}
1767
1768
/* Parsing function for both standard and prefixed extensions.
1769
1770
   Return Value:
1771
     Points to the end of extensions.
1772
1773
   Arguments:
1774
     `rps`: Hooks and status for parsing extensions.
1775
     `arch`: Full ISA string.
1776
     `p`: Curent parsing position.  */
1777
1778
static const char *
1779
riscv_parse_extensions (riscv_parse_subset_t *rps,
1780
      const char *arch,
1781
      const char *p)
1782
0
{
1783
  /* First letter must start with i, e or g.  */
1784
0
  if (*p != 'e' && *p != 'i' && *p != 'g')
1785
0
    {
1786
0
      rps->error_handler
1787
0
  (_("%s: first ISA extension must be `e', `i' or `g'"),
1788
0
   arch);
1789
0
      return NULL;
1790
0
    }
1791
1792
0
  while (*p != '\0')
1793
0
    {
1794
0
      if (*p == '_')
1795
0
  {
1796
0
    p++;
1797
0
    continue;
1798
0
  }
1799
1800
0
      char *subset = xstrdup (p);
1801
0
      char *q = subset; /* Start of version.  */
1802
0
      const char *end_of_version;
1803
0
      bool implicit = false;
1804
1805
0
      enum riscv_prefix_ext_class class = riscv_get_prefix_class (p);
1806
0
      if (class == RV_ISA_CLASS_SINGLE)
1807
0
  {
1808
0
    if (riscv_ext_order[(*subset - 'a')] == 0)
1809
0
      {
1810
0
        rps->error_handler
1811
0
    (_("%s: unknown standard ISA extension or prefix class `%c'"),
1812
0
     arch, *subset);
1813
0
        free (subset);
1814
0
        return NULL;
1815
0
      }
1816
0
    q++;
1817
0
  }
1818
0
      else
1819
0
  {
1820
    /* Extract the whole prefixed extension by '_'.  */
1821
0
    while (*++q != '\0' && *q != '_')
1822
0
      ;
1823
    /* Look forward to the first letter which is not <major>p<minor>.  */
1824
0
    bool find_any_version = false;
1825
0
    bool find_minor_version = false;
1826
0
    while (1)
1827
0
      {
1828
0
        q--;
1829
0
        if (ISDIGIT (*q))
1830
0
    find_any_version = true;
1831
0
        else if (find_any_version
1832
0
           && !find_minor_version
1833
0
           && *q == 'p'
1834
0
           && ISDIGIT (*(q - 1)))
1835
0
        find_minor_version = true;
1836
0
        else
1837
0
    break;
1838
0
      }
1839
0
    q++;
1840
1841
    /* Check if the end of extension is 'p' or not.  If yes, then
1842
       the second letter from the end cannot be number.  */
1843
0
    if (*(q - 1) == 'p' && ISDIGIT (*(q - 2)))
1844
0
      {
1845
0
        *q = '\0';
1846
0
        rps->error_handler
1847
0
    (_("%s: invalid prefixed ISA extension `%s' ends with <number>p"),
1848
0
     arch, subset);
1849
0
        free (subset);
1850
0
        return NULL;
1851
0
      }
1852
0
  }
1853
1854
0
      int major_version = RISCV_UNKNOWN_VERSION;
1855
0
      int minor_version = RISCV_UNKNOWN_VERSION;
1856
0
      end_of_version =
1857
0
  riscv_parsing_subset_version (q, &major_version, &minor_version);
1858
0
      *q = '\0';
1859
0
      if (end_of_version == NULL)
1860
0
  {
1861
0
    free (subset);
1862
0
    return NULL;
1863
0
  }
1864
1865
      /* Check if the prefixed extension name is well-formed.  */
1866
0
      if (class != RV_ISA_CLASS_SINGLE
1867
0
    && rps->check_unknown_prefixed_ext
1868
0
    && !riscv_recognized_prefixed_ext (subset))
1869
0
  {
1870
0
    rps->error_handler
1871
0
      (_("%s: unknown prefixed ISA extension `%s'"),
1872
0
       arch, subset);
1873
0
    free (subset);
1874
0
    return NULL;
1875
0
  }
1876
1877
      /* Added g as an implicit extension.  */
1878
0
      if (class == RV_ISA_CLASS_SINGLE
1879
0
    && strcmp (subset, "g") == 0)
1880
0
  {
1881
0
    implicit = true;
1882
0
    major_version = RISCV_UNKNOWN_VERSION;
1883
0
    minor_version = RISCV_UNKNOWN_VERSION;
1884
0
  }
1885
0
      riscv_parse_add_subset (rps, subset,
1886
0
            major_version,
1887
0
            minor_version, implicit);
1888
0
      p += end_of_version - subset;
1889
0
      free (subset);
1890
1891
0
      if (class != RV_ISA_CLASS_SINGLE
1892
0
    && *p != '\0' && *p != '_')
1893
0
  {
1894
0
    rps->error_handler
1895
0
      (_("%s: prefixed ISA extension must separate with _"),
1896
0
       arch);
1897
0
    return NULL;
1898
0
  }
1899
0
    }
1900
1901
0
  return p;
1902
0
}
1903
1904
/* Add the implicit extensions.  */
1905
1906
static void
1907
riscv_parse_add_implicit_subsets (riscv_parse_subset_t *rps)
1908
0
{
1909
0
  struct riscv_implicit_subset *t = riscv_implicit_subsets;
1910
0
  bool finished = false;
1911
0
  while (!finished)
1912
0
    {
1913
0
      finished = true;
1914
0
      for (; t->subset_name; t++)
1915
0
  {
1916
0
    riscv_subset_t *subset = NULL;
1917
0
    riscv_subset_t *implicit_subset = NULL;
1918
0
    if (riscv_lookup_subset (rps->subset_list, t->subset_name, &subset)
1919
0
        && !riscv_lookup_subset (rps->subset_list, t->implicit_name,
1920
0
               &implicit_subset)
1921
0
        && t->check_func (t->implicit_name, subset))
1922
0
      {
1923
0
        riscv_parse_add_subset (rps, t->implicit_name,
1924
0
              RISCV_UNKNOWN_VERSION,
1925
0
              RISCV_UNKNOWN_VERSION, true);
1926
1927
        /* Restart the loop and pick up any new implications.  */
1928
0
        finished = false;
1929
0
        t = riscv_implicit_subsets;
1930
0
        break;
1931
0
      }
1932
0
  }
1933
0
    }
1934
0
}
1935
1936
/* Check extensions conflicts.  */
1937
1938
static bool
1939
riscv_parse_check_conflicts (riscv_parse_subset_t *rps)
1940
0
{
1941
0
  riscv_subset_t *subset = NULL;
1942
0
  int xlen = *rps->xlen;
1943
0
  bool no_conflict = true;
1944
1945
0
  if (riscv_lookup_subset (rps->subset_list, "e", &subset)
1946
0
      && xlen > 32)
1947
0
    {
1948
0
      rps->error_handler
1949
0
  (_("rv%d does not support the `e' extension"), xlen);
1950
0
      no_conflict = false;
1951
0
    }
1952
0
  if (riscv_lookup_subset (rps->subset_list, "q", &subset)
1953
0
      && (subset->major_version < 2 || (subset->major_version == 2
1954
0
          && subset->minor_version < 2))
1955
0
      && xlen < 64)
1956
0
    {
1957
0
      rps->error_handler (_("rv%d does not support the `q' extension"), xlen);
1958
0
      no_conflict = false;
1959
0
    }
1960
0
  if (riscv_lookup_subset (rps->subset_list, "zcf", &subset)
1961
0
      && xlen > 32)
1962
0
    {
1963
0
      rps->error_handler
1964
0
  (_("rv%d does not support the `zcf' extension"), xlen);
1965
0
      no_conflict = false;
1966
0
    }
1967
0
  if (riscv_lookup_subset (rps->subset_list, "zfinx", &subset)
1968
0
      && riscv_lookup_subset (rps->subset_list, "f", &subset))
1969
0
    {
1970
0
      rps->error_handler
1971
0
  (_("`zfinx' is conflict with the `f/d/q/zfh/zfhmin' extension"));
1972
0
      no_conflict = false;
1973
0
    }
1974
1975
0
  bool support_zve = false;
1976
0
  bool support_zvl = false;
1977
0
  riscv_subset_t *s = rps->subset_list->head;
1978
0
  for (; s != NULL; s = s->next)
1979
0
    {
1980
0
      if (!support_zve
1981
0
    && strncmp (s->name, "zve", 3) == 0)
1982
0
  support_zve = true;
1983
0
      if (!support_zvl
1984
0
    && strncmp (s->name, "zvl", 3) == 0)
1985
0
  support_zvl = true;
1986
0
      if (support_zve && support_zvl)
1987
0
  break;
1988
0
    }
1989
0
  if (support_zvl && !support_zve)
1990
0
    {
1991
0
      rps->error_handler
1992
0
  (_("zvl*b extensions need to enable either `v' or `zve' extension"));
1993
0
      no_conflict = false;
1994
0
    }
1995
1996
0
  return no_conflict;
1997
0
}
1998
1999
/* Set the default subset list according to the default_enable field
2000
   of riscv_supported_*ext tables.  */
2001
2002
static void
2003
riscv_set_default_arch (riscv_parse_subset_t *rps)
2004
0
{
2005
0
  unsigned long enable = EXT_DEFAULT;
2006
0
  int i, j;
2007
0
  for (i = 0; riscv_all_supported_ext[i] != NULL; i++)
2008
0
    {
2009
0
      const struct riscv_supported_ext *table = riscv_all_supported_ext[i];
2010
0
      for (j = 0; table[j].name != NULL; j++)
2011
0
  {
2012
0
    bool implicit = false;
2013
0
    if (strcmp (table[j].name, "g") == 0)
2014
0
      implicit = true;
2015
0
    if (table[j].default_enable & enable)
2016
0
      riscv_parse_add_subset (rps, table[j].name,
2017
0
            RISCV_UNKNOWN_VERSION,
2018
0
            RISCV_UNKNOWN_VERSION, implicit);
2019
0
  }
2020
0
    }
2021
0
}
2022
2023
/* Function for parsing ISA string.
2024
2025
   Return Value:
2026
     Return TRUE on success.
2027
2028
   Arguments:
2029
     `rps`: Hooks and status for parsing extensions.
2030
     `arch`: Full ISA string.  */
2031
2032
bool
2033
riscv_parse_subset (riscv_parse_subset_t *rps,
2034
        const char *arch)
2035
0
{
2036
0
  const char *p;
2037
2038
  /* Init the riscv_ext_order array to compare the order of extensions
2039
     quickly.  */
2040
0
  riscv_init_ext_order ();
2041
2042
0
  if (arch == NULL)
2043
0
    {
2044
0
      riscv_set_default_arch (rps);
2045
0
      riscv_parse_add_implicit_subsets (rps);
2046
0
      return riscv_parse_check_conflicts (rps);
2047
0
    }
2048
2049
0
  for (p = arch; *p != '\0'; p++)
2050
0
    {
2051
0
      if (ISUPPER (*p))
2052
0
  {
2053
0
    rps->error_handler
2054
0
      (_("%s: ISA string cannot contain uppercase letters"),
2055
0
       arch);
2056
0
    return false;
2057
0
  }
2058
0
    }
2059
2060
0
  p = arch;
2061
0
  if (startswith (p, "rv32"))
2062
0
    {
2063
0
      *rps->xlen = 32;
2064
0
      p += 4;
2065
0
    }
2066
0
  else if (startswith (p, "rv64"))
2067
0
    {
2068
0
      *rps->xlen = 64;
2069
0
      p += 4;
2070
0
    }
2071
0
  else
2072
0
    {
2073
      /* ISA string shouldn't be NULL or empty here.  For linker,
2074
   it might be empty when we failed to merge the ISA string
2075
   in the riscv_merge_attributes.  For assembler, we might
2076
   give an empty string by .attribute arch, "" or -march=.
2077
   However, We have already issued the correct error message
2078
   in another side, so do not issue this error when the ISA
2079
   string is empty.  */
2080
0
      if (strlen (arch))
2081
0
  rps->error_handler (
2082
0
    _("%s: ISA string must begin with rv32 or rv64"),
2083
0
    arch);
2084
0
      return false;
2085
0
    }
2086
2087
  /* Parse single standard and prefixed extensions.  */
2088
0
  if (riscv_parse_extensions (rps, arch, p) == NULL)
2089
0
    return false;
2090
2091
  /* Finally add implicit extensions according to the current
2092
     extensions.  */
2093
0
  riscv_parse_add_implicit_subsets (rps);
2094
2095
  /* Check the conflicts.  */
2096
0
  return riscv_parse_check_conflicts (rps);
2097
0
}
2098
2099
/* Return the number of digits for the input.  */
2100
2101
size_t
2102
riscv_estimate_digit (unsigned num)
2103
0
{
2104
0
  size_t digit = 0;
2105
0
  if (num == 0)
2106
0
    return 1;
2107
2108
0
  for (digit = 0; num ; num /= 10)
2109
0
    digit++;
2110
2111
0
  return digit;
2112
0
}
2113
2114
/* Auxiliary function to estimate string length of subset list.  */
2115
2116
static size_t
2117
riscv_estimate_arch_strlen1 (const riscv_subset_t *subset)
2118
0
{
2119
0
  if (subset == NULL)
2120
0
    return 6; /* For rv32/rv64/rv128 and string terminator.  */
2121
2122
0
  return riscv_estimate_arch_strlen1 (subset->next)
2123
0
   + strlen (subset->name)
2124
0
   + riscv_estimate_digit (subset->major_version)
2125
0
   + 1 /* For version seperator 'p'.  */
2126
0
   + riscv_estimate_digit (subset->minor_version)
2127
0
   + 1 /* For underscore.  */;
2128
0
}
2129
2130
/* Estimate the string length of this subset list.  */
2131
2132
static size_t
2133
riscv_estimate_arch_strlen (const riscv_subset_list_t *subset_list)
2134
0
{
2135
0
  return riscv_estimate_arch_strlen1 (subset_list->head);
2136
0
}
2137
2138
/* Auxiliary function to convert subset info to string.  */
2139
2140
static void
2141
riscv_arch_str1 (riscv_subset_t *subset,
2142
     char *attr_str, char *buf, size_t bufsz)
2143
0
{
2144
0
  const char *underline = "_";
2145
0
  riscv_subset_t *subset_t = subset;
2146
2147
0
  if (subset_t == NULL)
2148
0
    return;
2149
2150
  /* No underline between rvXX and i/e.  */
2151
0
  if ((strcasecmp (subset_t->name, "i") == 0)
2152
0
      || (strcasecmp (subset_t->name, "e") == 0))
2153
0
    underline = "";
2154
2155
0
  snprintf (buf, bufsz, "%s%s%dp%d",
2156
0
      underline,
2157
0
      subset_t->name,
2158
0
      subset_t->major_version,
2159
0
      subset_t->minor_version);
2160
2161
0
  strncat (attr_str, buf, bufsz);
2162
2163
  /* Skip 'i' extension after 'e', or skip extensions which
2164
     versions are unknown.  */
2165
0
  while (subset_t->next
2166
0
   && ((strcmp (subset_t->name, "e") == 0
2167
0
        && strcmp (subset_t->next->name, "i") == 0)
2168
0
       || subset_t->next->major_version == RISCV_UNKNOWN_VERSION
2169
0
       || subset_t->next->minor_version == RISCV_UNKNOWN_VERSION))
2170
0
    subset_t = subset_t->next;
2171
2172
0
  riscv_arch_str1 (subset_t->next, attr_str, buf, bufsz);
2173
0
}
2174
2175
/* Convert subset information into string with explicit versions.  */
2176
2177
char *
2178
riscv_arch_str (unsigned xlen, const riscv_subset_list_t *subset)
2179
0
{
2180
0
  size_t arch_str_len = riscv_estimate_arch_strlen (subset);
2181
0
  char *attr_str = xmalloc (arch_str_len);
2182
0
  char *buf = xmalloc (arch_str_len);
2183
2184
0
  snprintf (attr_str, arch_str_len, "rv%u", xlen);
2185
2186
0
  riscv_arch_str1 (subset->head, attr_str, buf, arch_str_len);
2187
0
  free (buf);
2188
2189
0
  return attr_str;
2190
0
}
2191
2192
/* Copy the subset in the subset list.  */
2193
2194
static struct riscv_subset_t *
2195
riscv_copy_subset (riscv_subset_list_t *subset_list,
2196
       riscv_subset_t *subset)
2197
0
{
2198
0
  if (subset == NULL)
2199
0
    return NULL;
2200
2201
0
  riscv_subset_t *new = xmalloc (sizeof *new);
2202
0
  new->name = xstrdup (subset->name);
2203
0
  new->major_version = subset->major_version;
2204
0
  new->minor_version = subset->minor_version;
2205
0
  new->next = riscv_copy_subset (subset_list, subset->next);
2206
2207
0
  if (subset->next == NULL)
2208
0
    subset_list->tail = new;
2209
2210
0
  return new;
2211
0
}
2212
2213
/* Copy the subset list.  */
2214
2215
riscv_subset_list_t *
2216
riscv_copy_subset_list (riscv_subset_list_t *subset_list)
2217
0
{
2218
0
  riscv_subset_list_t *new = xmalloc (sizeof *new);
2219
0
  new->head = riscv_copy_subset (new, subset_list->head);
2220
0
  new->arch_str = strdup (subset_list->arch_str);
2221
0
  return new;
2222
0
}
2223
2224
/* Remove the SUBSET from the subset list.  */
2225
2226
static void
2227
riscv_remove_subset (riscv_subset_list_t *subset_list,
2228
         const char *subset)
2229
0
{
2230
0
  riscv_subset_t *current = subset_list->head;
2231
0
  riscv_subset_t *pre = NULL;
2232
0
  for (; current != NULL; pre = current, current = current->next)
2233
0
    {
2234
0
      if (strcmp (current->name, subset) == 0)
2235
0
  {
2236
0
    if (pre == NULL)
2237
0
      subset_list->head = current->next;
2238
0
    else
2239
0
      pre->next = current->next;
2240
0
    if (current->next == NULL)
2241
0
      subset_list->tail = pre;
2242
0
    free ((void *) current->name);
2243
0
    free (current);
2244
0
    break;
2245
0
  }
2246
0
    }
2247
0
}
2248
2249
/* Add/Remove an extension to/from the subset list.  This is used for
2250
   the .option rvc or norvc, and .option arch directives.  */
2251
2252
bool
2253
riscv_update_subset (riscv_parse_subset_t *rps,
2254
         const char *str)
2255
0
{
2256
0
  const char *p = str;
2257
2258
0
  do
2259
0
    {
2260
0
      int major_version = RISCV_UNKNOWN_VERSION;
2261
0
      int minor_version = RISCV_UNKNOWN_VERSION;
2262
2263
0
      bool removed = false;
2264
0
      switch (*p)
2265
0
  {
2266
0
  case '+': removed = false; break;
2267
0
  case '-': removed = true; break;
2268
0
  default:
2269
0
    riscv_release_subset_list (rps->subset_list);
2270
0
    return riscv_parse_subset (rps, p);
2271
0
  }
2272
0
      ++p;
2273
2274
0
      char *subset = xstrdup (p);
2275
0
      char *q = subset;
2276
0
      const char *end_of_version;
2277
      /* Extract the whole prefixed extension by ','.  */
2278
0
      while (*q != '\0' && *q != ',')
2279
0
        q++;
2280
2281
      /* Look forward to the first letter which is not <major>p<minor>.  */
2282
0
      bool find_any_version = false;
2283
0
      bool find_minor_version = false;
2284
0
      size_t len = q - subset;
2285
0
      size_t i;
2286
0
      for (i = len; i > 0; i--)
2287
0
        {
2288
0
    q--;
2289
0
    if (ISDIGIT (*q))
2290
0
      find_any_version = true;
2291
0
    else if (find_any_version
2292
0
       && !find_minor_version
2293
0
       && *q == 'p'
2294
0
       && ISDIGIT (*(q - 1)))
2295
0
      find_minor_version = true;
2296
0
    else
2297
0
      break;
2298
0
  }
2299
0
      if (len > 0)
2300
0
  q++;
2301
2302
      /* Check if the end of extension is 'p' or not.  If yes, then
2303
   the second letter from the end cannot be number.  */
2304
0
      if (len > 1 && *(q - 1) == 'p' && ISDIGIT (*(q - 2)))
2305
0
  {
2306
0
    *q = '\0';
2307
0
    rps->error_handler
2308
0
      (_("invalid ISA extension ends with <number>p "
2309
0
         "in .option arch `%s'"), str);
2310
0
    free (subset);
2311
0
    return false;
2312
0
  }
2313
2314
0
      end_of_version =
2315
0
  riscv_parsing_subset_version (q, &major_version, &minor_version);
2316
0
      *q = '\0';
2317
0
      if (end_of_version == NULL)
2318
0
  {
2319
0
    free (subset);
2320
0
    return false;
2321
0
  }
2322
2323
0
      if (strlen (subset) == 0
2324
0
    || (strlen (subset) == 1
2325
0
        && riscv_ext_order[(*subset - 'a')] == 0)
2326
0
    || (strlen (subset) > 1
2327
0
        && rps->check_unknown_prefixed_ext
2328
0
        && !riscv_recognized_prefixed_ext (subset)))
2329
0
  {
2330
0
    rps->error_handler
2331
0
      (_("unknown ISA extension `%s' in .option arch `%s'"),
2332
0
       subset, str);
2333
0
    free (subset);
2334
0
    return false;
2335
0
  }
2336
2337
0
      if (strcmp (subset, "i") == 0
2338
0
    || strcmp (subset, "e") == 0
2339
0
    || strcmp (subset, "g") == 0)
2340
0
  {
2341
0
    rps->error_handler
2342
0
      (_("cannot + or - base extension `%s' in .option "
2343
0
         "arch `%s'"), subset, str);
2344
0
    free (subset);
2345
0
    return false;
2346
0
  }
2347
2348
0
      if (removed)
2349
0
  riscv_remove_subset (rps->subset_list, subset);
2350
0
      else
2351
0
  riscv_parse_add_subset (rps, subset, major_version, minor_version, true);
2352
0
      p += end_of_version - subset;
2353
0
      free (subset);
2354
0
    }
2355
0
  while (*p++ == ',');
2356
2357
0
  riscv_parse_add_implicit_subsets (rps);
2358
0
  return riscv_parse_check_conflicts (rps);
2359
0
}
2360
2361
/* Check if the FEATURE subset is supported or not in the subset list.
2362
   Return true if it is supported; Otherwise, return false.  */
2363
2364
bool
2365
riscv_subset_supports (riscv_parse_subset_t *rps,
2366
           const char *feature)
2367
0
{
2368
0
  struct riscv_subset_t *subset;
2369
0
  return riscv_lookup_subset (rps->subset_list, feature, &subset);
2370
0
}
2371
2372
/* Each instuction is belonged to an instruction class INSN_CLASS_*.
2373
   Call riscv_subset_supports to make sure if the instuction is valid.  */
2374
2375
bool
2376
riscv_multi_subset_supports (riscv_parse_subset_t *rps,
2377
           enum riscv_insn_class insn_class)
2378
0
{
2379
0
  switch (insn_class)
2380
0
    {
2381
0
    case INSN_CLASS_I:
2382
0
      return riscv_subset_supports (rps, "i");
2383
0
    case INSN_CLASS_ZICBOM:
2384
0
      return riscv_subset_supports (rps, "zicbom");
2385
0
    case INSN_CLASS_ZICBOP:
2386
0
      return riscv_subset_supports (rps, "zicbop");
2387
0
    case INSN_CLASS_ZICBOZ:
2388
0
      return riscv_subset_supports (rps, "zicboz");
2389
0
    case INSN_CLASS_ZICOND:
2390
0
      return riscv_subset_supports (rps, "zicond");
2391
0
    case INSN_CLASS_ZICSR:
2392
0
      return riscv_subset_supports (rps, "zicsr");
2393
0
    case INSN_CLASS_ZIFENCEI:
2394
0
      return riscv_subset_supports (rps, "zifencei");
2395
0
    case INSN_CLASS_ZIHINTNTL:
2396
0
      return riscv_subset_supports (rps, "zihintntl");
2397
0
    case INSN_CLASS_ZIHINTNTL_AND_C:
2398
0
      return (riscv_subset_supports (rps, "zihintntl")
2399
0
        && (riscv_subset_supports (rps, "c")
2400
0
      || riscv_subset_supports (rps, "zca")));
2401
0
    case INSN_CLASS_ZIHINTPAUSE:
2402
0
      return riscv_subset_supports (rps, "zihintpause");
2403
0
    case INSN_CLASS_M:
2404
0
      return riscv_subset_supports (rps, "m");
2405
0
    case INSN_CLASS_ZMMUL:
2406
0
      return riscv_subset_supports (rps, "zmmul");
2407
0
    case INSN_CLASS_A:
2408
0
      return riscv_subset_supports (rps, "a");
2409
0
    case INSN_CLASS_ZAWRS:
2410
0
      return riscv_subset_supports (rps, "zawrs");
2411
0
    case INSN_CLASS_F:
2412
0
      return riscv_subset_supports (rps, "f");
2413
0
    case INSN_CLASS_D:
2414
0
      return riscv_subset_supports (rps, "d");
2415
0
    case INSN_CLASS_Q:
2416
0
      return riscv_subset_supports (rps, "q");
2417
0
    case INSN_CLASS_C:
2418
0
      return (riscv_subset_supports (rps, "c")
2419
0
        || riscv_subset_supports (rps, "zca"));
2420
0
    case INSN_CLASS_F_AND_C:
2421
0
      return (riscv_subset_supports (rps, "f")
2422
0
        && (riscv_subset_supports (rps, "c")
2423
0
      || riscv_subset_supports (rps, "zcf")));
2424
0
    case INSN_CLASS_D_AND_C:
2425
0
      return (riscv_subset_supports (rps, "d")
2426
0
        && (riscv_subset_supports (rps, "c")
2427
0
      || riscv_subset_supports (rps, "zcd")));
2428
0
    case INSN_CLASS_F_INX:
2429
0
      return (riscv_subset_supports (rps, "f")
2430
0
        || riscv_subset_supports (rps, "zfinx"));
2431
0
    case INSN_CLASS_D_INX:
2432
0
      return (riscv_subset_supports (rps, "d")
2433
0
        || riscv_subset_supports (rps, "zdinx"));
2434
0
    case INSN_CLASS_Q_INX:
2435
0
      return (riscv_subset_supports (rps, "q")
2436
0
        || riscv_subset_supports (rps, "zqinx"));
2437
0
    case INSN_CLASS_ZFH_INX:
2438
0
      return (riscv_subset_supports (rps, "zfh")
2439
0
        || riscv_subset_supports (rps, "zhinx"));
2440
0
    case INSN_CLASS_ZFHMIN:
2441
0
      return riscv_subset_supports (rps, "zfhmin");
2442
0
    case INSN_CLASS_ZFHMIN_INX:
2443
0
      return (riscv_subset_supports (rps, "zfhmin")
2444
0
        || riscv_subset_supports (rps, "zhinxmin"));
2445
0
    case INSN_CLASS_ZFHMIN_AND_D_INX:
2446
0
      return ((riscv_subset_supports (rps, "zfhmin")
2447
0
         && riscv_subset_supports (rps, "d"))
2448
0
        || (riscv_subset_supports (rps, "zhinxmin")
2449
0
      && riscv_subset_supports (rps, "zdinx")));
2450
0
    case INSN_CLASS_ZFHMIN_AND_Q_INX:
2451
0
      return ((riscv_subset_supports (rps, "zfhmin")
2452
0
         && riscv_subset_supports (rps, "q"))
2453
0
        || (riscv_subset_supports (rps, "zhinxmin")
2454
0
      && riscv_subset_supports (rps, "zqinx")));
2455
0
    case INSN_CLASS_ZFA:
2456
0
      return riscv_subset_supports (rps, "zfa");
2457
0
    case INSN_CLASS_D_AND_ZFA:
2458
0
      return riscv_subset_supports (rps, "d")
2459
0
       && riscv_subset_supports (rps, "zfa");
2460
0
    case INSN_CLASS_Q_AND_ZFA:
2461
0
      return riscv_subset_supports (rps, "q")
2462
0
       && riscv_subset_supports (rps, "zfa");
2463
0
    case INSN_CLASS_ZFH_AND_ZFA:
2464
0
      return riscv_subset_supports (rps, "zfh")
2465
0
       && riscv_subset_supports (rps, "zfa");
2466
0
    case INSN_CLASS_ZFH_OR_ZVFH_AND_ZFA:
2467
0
      return (riscv_subset_supports (rps, "zfh")
2468
0
        || riscv_subset_supports (rps, "zvfh"))
2469
0
       && riscv_subset_supports (rps, "zfa");
2470
0
    case INSN_CLASS_ZBA:
2471
0
      return riscv_subset_supports (rps, "zba");
2472
0
    case INSN_CLASS_ZBB:
2473
0
      return riscv_subset_supports (rps, "zbb");
2474
0
    case INSN_CLASS_ZBC:
2475
0
      return riscv_subset_supports (rps, "zbc");
2476
0
    case INSN_CLASS_ZBS:
2477
0
      return riscv_subset_supports (rps, "zbs");
2478
0
    case INSN_CLASS_ZBKB:
2479
0
      return riscv_subset_supports (rps, "zbkb");
2480
0
    case INSN_CLASS_ZBKC:
2481
0
      return riscv_subset_supports (rps, "zbkc");
2482
0
    case INSN_CLASS_ZBKX:
2483
0
      return riscv_subset_supports (rps, "zbkx");
2484
0
    case INSN_CLASS_ZBB_OR_ZBKB:
2485
0
      return (riscv_subset_supports (rps, "zbb")
2486
0
        || riscv_subset_supports (rps, "zbkb"));
2487
0
    case INSN_CLASS_ZBC_OR_ZBKC:
2488
0
      return (riscv_subset_supports (rps, "zbc")
2489
0
        || riscv_subset_supports (rps, "zbkc"));
2490
0
    case INSN_CLASS_ZKND:
2491
0
      return riscv_subset_supports (rps, "zknd");
2492
0
    case INSN_CLASS_ZKNE:
2493
0
      return riscv_subset_supports (rps, "zkne");
2494
0
    case INSN_CLASS_ZKNH:
2495
0
      return riscv_subset_supports (rps, "zknh");
2496
0
    case INSN_CLASS_ZKND_OR_ZKNE:
2497
0
      return (riscv_subset_supports (rps, "zknd")
2498
0
        || riscv_subset_supports (rps, "zkne"));
2499
0
    case INSN_CLASS_ZKSED:
2500
0
      return riscv_subset_supports (rps, "zksed");
2501
0
    case INSN_CLASS_ZKSH:
2502
0
      return riscv_subset_supports (rps, "zksh");
2503
0
    case INSN_CLASS_V:
2504
0
      return (riscv_subset_supports (rps, "v")
2505
0
        || riscv_subset_supports (rps, "zve64x")
2506
0
        || riscv_subset_supports (rps, "zve32x"));
2507
0
    case INSN_CLASS_ZVEF:
2508
0
      return (riscv_subset_supports (rps, "v")
2509
0
        || riscv_subset_supports (rps, "zve64d")
2510
0
        || riscv_subset_supports (rps, "zve64f")
2511
0
        || riscv_subset_supports (rps, "zve32f"));
2512
0
    case INSN_CLASS_ZVBB:
2513
0
      return riscv_subset_supports (rps, "zvbb");
2514
0
    case INSN_CLASS_ZVBC:
2515
0
      return riscv_subset_supports (rps, "zvbc");
2516
0
    case INSN_CLASS_ZVKG:
2517
0
      return riscv_subset_supports (rps, "zvkg");
2518
0
    case INSN_CLASS_ZVKNED:
2519
0
      return riscv_subset_supports (rps, "zvkned");
2520
0
    case INSN_CLASS_ZVKNHA_OR_ZVKNHB:
2521
0
      return (riscv_subset_supports (rps, "zvknha")
2522
0
        || riscv_subset_supports (rps, "zvknhb"));
2523
0
    case INSN_CLASS_ZVKSED:
2524
0
      return riscv_subset_supports (rps, "zvksed");
2525
0
    case INSN_CLASS_ZVKSH:
2526
0
      return riscv_subset_supports (rps, "zvksh");
2527
0
    case INSN_CLASS_ZCB:
2528
0
      return riscv_subset_supports (rps, "zcb");
2529
0
    case INSN_CLASS_ZCB_AND_ZBB:
2530
0
      return (riscv_subset_supports (rps, "zcb")
2531
0
        && riscv_subset_supports (rps, "zbb"));
2532
0
    case INSN_CLASS_ZCB_AND_ZBA:
2533
0
      return (riscv_subset_supports (rps, "zcb")
2534
0
        && riscv_subset_supports (rps, "zba"));
2535
0
    case INSN_CLASS_ZCB_AND_ZMMUL:
2536
0
      return (riscv_subset_supports (rps, "zcb")
2537
0
        && riscv_subset_supports (rps, "zmmul"));
2538
0
    case INSN_CLASS_SVINVAL:
2539
0
      return riscv_subset_supports (rps, "svinval");
2540
0
    case INSN_CLASS_H:
2541
0
      return riscv_subset_supports (rps, "h");
2542
0
    case INSN_CLASS_XTHEADBA:
2543
0
      return riscv_subset_supports (rps, "xtheadba");
2544
0
    case INSN_CLASS_XTHEADBB:
2545
0
      return riscv_subset_supports (rps, "xtheadbb");
2546
0
    case INSN_CLASS_XTHEADBS:
2547
0
      return riscv_subset_supports (rps, "xtheadbs");
2548
0
    case INSN_CLASS_XTHEADCMO:
2549
0
      return riscv_subset_supports (rps, "xtheadcmo");
2550
0
    case INSN_CLASS_XTHEADCONDMOV:
2551
0
      return riscv_subset_supports (rps, "xtheadcondmov");
2552
0
    case INSN_CLASS_XTHEADFMEMIDX:
2553
0
      return riscv_subset_supports (rps, "xtheadfmemidx");
2554
0
    case INSN_CLASS_XTHEADFMV:
2555
0
      return riscv_subset_supports (rps, "xtheadfmv");
2556
0
    case INSN_CLASS_XTHEADINT:
2557
0
      return riscv_subset_supports (rps, "xtheadint");
2558
0
    case INSN_CLASS_XTHEADMAC:
2559
0
      return riscv_subset_supports (rps, "xtheadmac");
2560
0
    case INSN_CLASS_XTHEADMEMIDX:
2561
0
      return riscv_subset_supports (rps, "xtheadmemidx");
2562
0
    case INSN_CLASS_XTHEADMEMPAIR:
2563
0
      return riscv_subset_supports (rps, "xtheadmempair");
2564
0
    case INSN_CLASS_XTHEADSYNC:
2565
0
      return riscv_subset_supports (rps, "xtheadsync");
2566
0
    case INSN_CLASS_XVENTANACONDOPS:
2567
0
      return riscv_subset_supports (rps, "xventanacondops");
2568
0
    default:
2569
0
      rps->error_handler
2570
0
        (_("internal: unreachable INSN_CLASS_*"));
2571
0
      return false;
2572
0
    }
2573
0
}
2574
2575
/* Each instuction is belonged to an instruction class INSN_CLASS_*.
2576
   Call riscv_subset_supports_ext to determine the missing extension.  */
2577
2578
const char *
2579
riscv_multi_subset_supports_ext (riscv_parse_subset_t *rps,
2580
         enum riscv_insn_class insn_class)
2581
0
{
2582
0
  switch (insn_class)
2583
0
    {
2584
0
    case INSN_CLASS_I:
2585
0
      return "i";
2586
0
    case INSN_CLASS_ZICBOM:
2587
0
      return "zicbom";
2588
0
    case INSN_CLASS_ZICBOP:
2589
0
      return "zicbop";
2590
0
    case INSN_CLASS_ZICBOZ:
2591
0
      return "zicboz";
2592
0
    case INSN_CLASS_ZICOND:
2593
0
      return "zicond";
2594
0
    case INSN_CLASS_ZICSR:
2595
0
      return "zicsr";
2596
0
    case INSN_CLASS_ZIFENCEI:
2597
0
      return "zifencei";
2598
0
    case INSN_CLASS_ZIHINTNTL:
2599
0
      return "zihintntl";
2600
0
    case INSN_CLASS_ZIHINTNTL_AND_C:
2601
0
      if (!riscv_subset_supports (rps, "zihintntl"))
2602
0
  {
2603
0
    if (!riscv_subset_supports (rps, "c")
2604
0
        && !riscv_subset_supports (rps, "zca"))
2605
0
      return _("zihintntl' and `c', or `zihintntl' and `zca");
2606
0
    else
2607
0
      return "zihintntl";
2608
0
  }
2609
0
      else
2610
0
  return _("c' or `zca");
2611
0
    case INSN_CLASS_ZIHINTPAUSE:
2612
0
      return "zihintpause";
2613
0
    case INSN_CLASS_M:
2614
0
      return "m";
2615
0
    case INSN_CLASS_ZMMUL:
2616
0
      return _ ("m' or `zmmul");
2617
0
    case INSN_CLASS_A:
2618
0
      return "a";
2619
0
    case INSN_CLASS_ZAWRS:
2620
0
      return "zawrs";
2621
0
    case INSN_CLASS_F:
2622
0
      return "f";
2623
0
    case INSN_CLASS_D:
2624
0
      return "d";
2625
0
    case INSN_CLASS_Q:
2626
0
      return "q";
2627
0
    case INSN_CLASS_C:
2628
0
      return _("c' or `zca");
2629
0
    case INSN_CLASS_F_AND_C:
2630
0
      if (!riscv_subset_supports (rps, "f"))
2631
0
  {
2632
0
    if (!riscv_subset_supports (rps, "c")
2633
0
        && !riscv_subset_supports (rps, "zcf"))
2634
0
      return _("f' and `c', or `f' and `zcf"); 
2635
0
    else
2636
0
      return "f";
2637
0
  }
2638
0
      else
2639
0
  return _("c' or `zcf");
2640
0
    case INSN_CLASS_D_AND_C:
2641
0
      if (!riscv_subset_supports (rps, "d"))
2642
0
  {
2643
0
    if (!riscv_subset_supports (rps, "c")
2644
0
        && !riscv_subset_supports (rps, "zcd"))
2645
0
      return _("d' and `c', or `d' and `zcd");
2646
0
    else
2647
0
      return "d";
2648
0
  }
2649
0
      else
2650
0
  return _("c' or `zcd");
2651
0
    case INSN_CLASS_F_INX:
2652
0
      return _("f' or `zfinx");
2653
0
    case INSN_CLASS_D_INX:
2654
0
      return _("d' or `zdinx");
2655
0
    case INSN_CLASS_Q_INX:
2656
0
      return _("q' or `zqinx");
2657
0
    case INSN_CLASS_ZFH_INX:
2658
0
      return _("zfh' or `zhinx");
2659
0
    case INSN_CLASS_ZFHMIN:
2660
0
      return "zfhmin";
2661
0
    case INSN_CLASS_ZFHMIN_INX:
2662
0
      return _("zfhmin' or `zhinxmin");
2663
0
    case INSN_CLASS_ZFHMIN_AND_D_INX:
2664
0
      if (riscv_subset_supports (rps, "zfhmin"))
2665
0
  return "d";
2666
0
      else if (riscv_subset_supports (rps, "d"))
2667
0
  return "zfhmin";
2668
0
      else if (riscv_subset_supports (rps, "zhinxmin"))
2669
0
  return "zdinx";
2670
0
      else if (riscv_subset_supports (rps, "zdinx"))
2671
0
  return "zhinxmin";
2672
0
      else
2673
0
  return _("zfhmin' and `d', or `zhinxmin' and `zdinx");
2674
0
    case INSN_CLASS_ZFHMIN_AND_Q_INX:
2675
0
      if (riscv_subset_supports (rps, "zfhmin"))
2676
0
  return "q";
2677
0
      else if (riscv_subset_supports (rps, "q"))
2678
0
  return "zfhmin";
2679
0
      else if (riscv_subset_supports (rps, "zhinxmin"))
2680
0
  return "zqinx";
2681
0
      else if (riscv_subset_supports (rps, "zqinx"))
2682
0
  return "zhinxmin";
2683
0
      else
2684
0
  return _("zfhmin' and `q', or `zhinxmin' and `zqinx");
2685
0
    case INSN_CLASS_ZFA:
2686
0
      return "zfa";
2687
0
    case INSN_CLASS_D_AND_ZFA:
2688
0
      if (!riscv_subset_supports (rps, "d")
2689
0
    && !riscv_subset_supports (rps, "zfa"))
2690
0
  return _("d' and `zfa");
2691
0
      else if (!riscv_subset_supports (rps, "d"))
2692
0
  return "d";
2693
0
      else
2694
0
  return "zfa";
2695
0
    case INSN_CLASS_Q_AND_ZFA:
2696
0
      if (!riscv_subset_supports (rps, "q")
2697
0
    && !riscv_subset_supports (rps, "zfa"))
2698
0
  return _("q' and `zfa");
2699
0
      else if (!riscv_subset_supports (rps, "q"))
2700
0
  return "q";
2701
0
      else
2702
0
  return "zfa";
2703
0
    case INSN_CLASS_ZFH_AND_ZFA:
2704
0
      if (!riscv_subset_supports (rps, "zfh")
2705
0
    && !riscv_subset_supports (rps, "zfa"))
2706
0
  return _("zfh' and `zfa");
2707
0
      else if (!riscv_subset_supports (rps, "zfh"))
2708
0
  return "zfh";
2709
0
      else
2710
0
  return "zfa";
2711
0
    case INSN_CLASS_ZFH_OR_ZVFH_AND_ZFA:
2712
0
      if (!riscv_subset_supports (rps, "zfa"))
2713
0
  {
2714
0
    if (!riscv_subset_supports (rps, "zfh")
2715
0
        && !riscv_subset_supports (rps, "zvfh"))
2716
0
      return _("zfh' and `zfa', or `zvfh' and `zfa");
2717
0
    else
2718
0
      return "zfa";
2719
0
  }
2720
0
      else
2721
0
  return _("zfh' or `zvfh");
2722
0
    case INSN_CLASS_ZBA:
2723
0
      return "zba";
2724
0
    case INSN_CLASS_ZBB:
2725
0
      return "zbb";
2726
0
    case INSN_CLASS_ZBC:
2727
0
      return "zbc";
2728
0
    case INSN_CLASS_ZBS:
2729
0
      return "zbs";
2730
0
    case INSN_CLASS_ZBKB:
2731
0
      return "zbkb";
2732
0
    case INSN_CLASS_ZBKC:
2733
0
      return "zbkc";
2734
0
    case INSN_CLASS_ZBKX:
2735
0
      return "zbkx";
2736
0
    case INSN_CLASS_ZBB_OR_ZBKB:
2737
0
      return _("zbb' or `zbkb");
2738
0
    case INSN_CLASS_ZBC_OR_ZBKC:
2739
0
      return _("zbc' or `zbkc");
2740
0
    case INSN_CLASS_ZKND:
2741
0
      return "zknd";
2742
0
    case INSN_CLASS_ZKNE:
2743
0
      return "zkne";
2744
0
    case INSN_CLASS_ZKNH:
2745
0
      return "zknh";
2746
0
    case INSN_CLASS_ZKND_OR_ZKNE:
2747
0
      return _("zknd' or `zkne");
2748
0
    case INSN_CLASS_ZKSED:
2749
0
      return "zksed";
2750
0
    case INSN_CLASS_ZKSH:
2751
0
      return "zksh";
2752
0
    case INSN_CLASS_V:
2753
0
      return _("v' or `zve64x' or `zve32x");
2754
0
    case INSN_CLASS_ZVEF:
2755
0
      return _("v' or `zve64d' or `zve64f' or `zve32f");
2756
0
    case INSN_CLASS_ZVBB:
2757
0
      return _("zvbb");
2758
0
    case INSN_CLASS_ZVBC:
2759
0
      return _("zvbc");
2760
0
    case INSN_CLASS_ZVKG:
2761
0
      return _("zvkg");
2762
0
    case INSN_CLASS_ZVKNED:
2763
0
      return _("zvkned");
2764
0
    case INSN_CLASS_ZVKNHA_OR_ZVKNHB:
2765
0
      return _("zvknha' or `zvknhb");
2766
0
    case INSN_CLASS_ZVKSED:
2767
0
      return _("zvksed");
2768
0
    case INSN_CLASS_ZVKSH:
2769
0
      return _("zvksh");
2770
0
    case INSN_CLASS_ZCB:
2771
0
      return "zcb";
2772
0
    case INSN_CLASS_ZCB_AND_ZBA:
2773
0
      return _("zcb' and `zba");
2774
0
    case INSN_CLASS_ZCB_AND_ZBB:
2775
0
      return _("zcb' and `zbb");
2776
0
    case INSN_CLASS_ZCB_AND_ZMMUL:
2777
0
      return _("zcb' and `zmmul', or `zcb' and `m");
2778
0
    case INSN_CLASS_SVINVAL:
2779
0
      return "svinval";
2780
0
    case INSN_CLASS_H:
2781
0
      return _("h");
2782
0
    case INSN_CLASS_XTHEADBA:
2783
0
      return "xtheadba";
2784
0
    case INSN_CLASS_XTHEADBB:
2785
0
      return "xtheadbb";
2786
0
    case INSN_CLASS_XTHEADBS:
2787
0
      return "xtheadbs";
2788
0
    case INSN_CLASS_XTHEADCMO:
2789
0
      return "xtheadcmo";
2790
0
    case INSN_CLASS_XTHEADCONDMOV:
2791
0
      return "xtheadcondmov";
2792
0
    case INSN_CLASS_XTHEADFMEMIDX:
2793
0
      return "xtheadfmemidx";
2794
0
    case INSN_CLASS_XTHEADFMV:
2795
0
      return "xtheadfmv";
2796
0
    case INSN_CLASS_XTHEADINT:
2797
0
      return "xtheadint";
2798
0
    case INSN_CLASS_XTHEADMAC:
2799
0
      return "xtheadmac";
2800
0
    case INSN_CLASS_XTHEADMEMIDX:
2801
0
      return "xtheadmemidx";
2802
0
    case INSN_CLASS_XTHEADMEMPAIR:
2803
0
      return "xtheadmempair";
2804
0
    case INSN_CLASS_XTHEADSYNC:
2805
0
      return "xtheadsync";
2806
0
    default:
2807
0
      rps->error_handler
2808
0
        (_("internal: unreachable INSN_CLASS_*"));
2809
0
      return NULL;
2810
0
    }
2811
0
}