Coverage Report

Created: 2023-06-29 07:13

/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
  {"zve64d", "d", check_implicit_always},
1114
  {"zve64d", "zve64f",  check_implicit_always},
1115
  {"zve64f", "zve32f",  check_implicit_always},
1116
  {"zve64f", "zve64x",  check_implicit_always},
1117
  {"zve64f", "zvl64b",  check_implicit_always},
1118
  {"zve32f", "f", check_implicit_always},
1119
  {"zve32f", "zvl32b",  check_implicit_always},
1120
  {"zve32f", "zve32x",  check_implicit_always},
1121
  {"zve64x", "zve32x",  check_implicit_always},
1122
  {"zve64x", "zvl64b",  check_implicit_always},
1123
  {"zve32x", "zvl32b",  check_implicit_always},
1124
  {"zvl65536b", "zvl32768b",  check_implicit_always},
1125
  {"zvl32768b", "zvl16384b",  check_implicit_always},
1126
  {"zvl16384b", "zvl8192b", check_implicit_always},
1127
  {"zvl8192b", "zvl4096b",  check_implicit_always},
1128
  {"zvl4096b", "zvl2048b",  check_implicit_always},
1129
  {"zvl2048b", "zvl1024b",  check_implicit_always},
1130
  {"zvl1024b", "zvl512b", check_implicit_always},
1131
  {"zvl512b", "zvl256b",  check_implicit_always},
1132
  {"zvl256b", "zvl128b",  check_implicit_always},
1133
  {"zvl128b", "zvl64b",   check_implicit_always},
1134
  {"zvl64b", "zvl32b",    check_implicit_always},
1135
  {"d", "f",    check_implicit_always},
1136
  {"zfh", "zfhmin", check_implicit_always},
1137
  {"zfhmin", "f", check_implicit_always},
1138
  {"f", "zicsr",  check_implicit_always},
1139
  {"zqinx", "zdinx",  check_implicit_always},
1140
  {"zdinx", "zfinx",  check_implicit_always},
1141
  {"zhinx", "zhinxmin", check_implicit_always},
1142
  {"zhinxmin", "zfinx", check_implicit_always},
1143
  {"zfinx", "zicsr",  check_implicit_always},
1144
  {"zk", "zkn",   check_implicit_always},
1145
  {"zk", "zkr",   check_implicit_always},
1146
  {"zk", "zkt",   check_implicit_always},
1147
  {"zkn", "zbkb", check_implicit_always},
1148
  {"zkn", "zbkc", check_implicit_always},
1149
  {"zkn", "zbkx", check_implicit_always},
1150
  {"zkn", "zkne", check_implicit_always},
1151
  {"zkn", "zknd", check_implicit_always},
1152
  {"zkn", "zknh", check_implicit_always},
1153
  {"zks", "zbkb", check_implicit_always},
1154
  {"zks", "zbkc", check_implicit_always},
1155
  {"zks", "zbkx", check_implicit_always},
1156
  {"zks", "zksed",  check_implicit_always},
1157
  {"zks", "zksh", check_implicit_always},
1158
  {"smaia", "ssaia",    check_implicit_always},
1159
  {"smstateen", "ssstateen",  check_implicit_always},
1160
  {"smepmp", "zicsr",   check_implicit_always},
1161
  {"ssaia", "zicsr",    check_implicit_always},
1162
  {"sscofpmf", "zicsr",   check_implicit_always},
1163
  {"ssstateen", "zicsr",  check_implicit_always},
1164
  {"sstc", "zicsr",   check_implicit_always},
1165
  {NULL, NULL, NULL}
1166
};
1167
1168
/* For default_enable field, decide if the extension should
1169
   be enbaled by default.  */
1170
1171
0
#define EXT_DEFAULT   0x1
1172
1173
/* List all extensions that binutils should know about.  */
1174
1175
struct riscv_supported_ext
1176
{
1177
  const char *name;
1178
  enum riscv_spec_class isa_spec_class;
1179
  int major_version;
1180
  int minor_version;
1181
  unsigned long default_enable;
1182
};
1183
1184
/* The standard extensions must be added in canonical order.  */
1185
1186
static struct riscv_supported_ext riscv_supported_std_ext[] =
1187
{
1188
  {"e",   ISA_SPEC_CLASS_20191213,  1, 9, 0 },
1189
  {"e",   ISA_SPEC_CLASS_20190608,  1, 9, 0 },
1190
  {"e",   ISA_SPEC_CLASS_2P2,   1, 9, 0 },
1191
  {"i",   ISA_SPEC_CLASS_20191213,  2, 1, 0 },
1192
  {"i",   ISA_SPEC_CLASS_20190608,  2, 1, 0 },
1193
  {"i",   ISA_SPEC_CLASS_2P2,   2, 0, 0 },
1194
  /* The g is a special case which we don't want to output it,
1195
     but still need it when adding implicit extensions.  */
1196
  {"g",   ISA_SPEC_CLASS_NONE, RISCV_UNKNOWN_VERSION, RISCV_UNKNOWN_VERSION, EXT_DEFAULT },
1197
  {"m",   ISA_SPEC_CLASS_20191213,  2, 0, 0 },
1198
  {"m",   ISA_SPEC_CLASS_20190608,  2, 0, 0 },
1199
  {"m",   ISA_SPEC_CLASS_2P2,   2, 0, 0 },
1200
  {"a",   ISA_SPEC_CLASS_20191213,  2, 1, 0 },
1201
  {"a",   ISA_SPEC_CLASS_20190608,  2, 0, 0 },
1202
  {"a",   ISA_SPEC_CLASS_2P2,   2, 0, 0 },
1203
  {"f",   ISA_SPEC_CLASS_20191213,  2, 2, 0 },
1204
  {"f",   ISA_SPEC_CLASS_20190608,  2, 2, 0 },
1205
  {"f",   ISA_SPEC_CLASS_2P2,   2, 0, 0 },
1206
  {"d",   ISA_SPEC_CLASS_20191213,  2, 2, 0 },
1207
  {"d",   ISA_SPEC_CLASS_20190608,  2, 2, 0 },
1208
  {"d",   ISA_SPEC_CLASS_2P2,   2, 0, 0 },
1209
  {"q",   ISA_SPEC_CLASS_20191213,  2, 2, 0 },
1210
  {"q",   ISA_SPEC_CLASS_20190608,  2, 2, 0 },
1211
  {"q",   ISA_SPEC_CLASS_2P2,   2, 0, 0 },
1212
  {"c",   ISA_SPEC_CLASS_20191213,  2, 0, 0 },
1213
  {"c",   ISA_SPEC_CLASS_20190608,  2, 0, 0 },
1214
  {"c",   ISA_SPEC_CLASS_2P2,   2, 0, 0 },
1215
  {"v",   ISA_SPEC_CLASS_DRAFT,   1, 0, 0 },
1216
  {"h",   ISA_SPEC_CLASS_DRAFT,   1, 0, 0 },
1217
  {NULL, 0, 0, 0, 0}
1218
};
1219
1220
static struct riscv_supported_ext riscv_supported_std_z_ext[] =
1221
{
1222
  {"zicbom",    ISA_SPEC_CLASS_DRAFT,   1, 0,  0 },
1223
  {"zicbop",    ISA_SPEC_CLASS_DRAFT,   1, 0,  0 },
1224
  {"zicboz",    ISA_SPEC_CLASS_DRAFT,   1, 0,  0 },
1225
  {"zicond",    ISA_SPEC_CLASS_DRAFT,   1, 0,  0 },
1226
  {"zicsr",   ISA_SPEC_CLASS_20191213,  2, 0,  0 },
1227
  {"zicsr",   ISA_SPEC_CLASS_20190608,  2, 0,  0 },
1228
  {"zifencei",    ISA_SPEC_CLASS_20191213,  2, 0,  0 },
1229
  {"zifencei",    ISA_SPEC_CLASS_20190608,  2, 0,  0 },
1230
  {"zihintpause", ISA_SPEC_CLASS_DRAFT,   2, 0,  0 },
1231
  {"zmmul",   ISA_SPEC_CLASS_DRAFT,   1, 0,  0 },
1232
  {"zawrs",   ISA_SPEC_CLASS_DRAFT,   1, 0,  0 },
1233
  {"zfh",   ISA_SPEC_CLASS_DRAFT,   1, 0,  0 },
1234
  {"zfhmin",    ISA_SPEC_CLASS_DRAFT,   1, 0,  0 },
1235
  {"zfinx",   ISA_SPEC_CLASS_DRAFT,   1, 0,  0 },
1236
  {"zdinx",   ISA_SPEC_CLASS_DRAFT,   1, 0,  0 },
1237
  {"zqinx",   ISA_SPEC_CLASS_DRAFT,   1, 0,  0 },
1238
  {"zhinx",   ISA_SPEC_CLASS_DRAFT,   1, 0,  0 },
1239
  {"zhinxmin",    ISA_SPEC_CLASS_DRAFT,   1, 0,  0 },
1240
  {"zbb",   ISA_SPEC_CLASS_DRAFT,   1, 0,  0 },
1241
  {"zba",   ISA_SPEC_CLASS_DRAFT,   1, 0,  0 },
1242
  {"zbc",   ISA_SPEC_CLASS_DRAFT,   1, 0,  0 },
1243
  {"zbs",   ISA_SPEC_CLASS_DRAFT,   1, 0,  0 },
1244
  {"zbkb",    ISA_SPEC_CLASS_DRAFT,   1, 0,  0 },
1245
  {"zbkc",    ISA_SPEC_CLASS_DRAFT,   1, 0,  0 },
1246
  {"zbkx",    ISA_SPEC_CLASS_DRAFT,   1, 0,  0 },
1247
  {"zk",    ISA_SPEC_CLASS_DRAFT,   1, 0,  0 },
1248
  {"zkn",   ISA_SPEC_CLASS_DRAFT,   1, 0,  0 },
1249
  {"zknd",    ISA_SPEC_CLASS_DRAFT,   1, 0,  0 },
1250
  {"zkne",    ISA_SPEC_CLASS_DRAFT,   1, 0,  0 },
1251
  {"zknh",    ISA_SPEC_CLASS_DRAFT,   1, 0,  0 },
1252
  {"zkr",   ISA_SPEC_CLASS_DRAFT,   1, 0,  0 },
1253
  {"zks",   ISA_SPEC_CLASS_DRAFT,   1, 0,  0 },
1254
  {"zksed",   ISA_SPEC_CLASS_DRAFT,   1, 0,  0 },
1255
  {"zksh",    ISA_SPEC_CLASS_DRAFT,   1, 0,  0 },
1256
  {"zkt",   ISA_SPEC_CLASS_DRAFT,   1, 0,  0 },
1257
  {"zve32x",    ISA_SPEC_CLASS_DRAFT,   1, 0,  0 },
1258
  {"zve32f",    ISA_SPEC_CLASS_DRAFT,   1, 0,  0 },
1259
  {"zve32d",    ISA_SPEC_CLASS_DRAFT,   1, 0,  0 },
1260
  {"zve64x",    ISA_SPEC_CLASS_DRAFT,   1, 0,  0 },
1261
  {"zve64f",    ISA_SPEC_CLASS_DRAFT,   1, 0,  0 },
1262
  {"zve64d",    ISA_SPEC_CLASS_DRAFT,   1, 0,  0 },
1263
  {"zvl32b",    ISA_SPEC_CLASS_DRAFT,   1, 0,  0 },
1264
  {"zvl64b",    ISA_SPEC_CLASS_DRAFT,   1, 0,  0 },
1265
  {"zvl128b",   ISA_SPEC_CLASS_DRAFT,   1, 0,  0 },
1266
  {"zvl256b",   ISA_SPEC_CLASS_DRAFT,   1, 0,  0 },
1267
  {"zvl512b",   ISA_SPEC_CLASS_DRAFT,   1, 0,  0 },
1268
  {"zvl1024b",    ISA_SPEC_CLASS_DRAFT,   1, 0,  0 },
1269
  {"zvl2048b",    ISA_SPEC_CLASS_DRAFT,   1, 0,  0 },
1270
  {"zvl4096b",    ISA_SPEC_CLASS_DRAFT,   1, 0,  0 },
1271
  {"zvl8192b",    ISA_SPEC_CLASS_DRAFT,   1, 0,  0 },
1272
  {"zvl16384b",   ISA_SPEC_CLASS_DRAFT,   1, 0,  0 },
1273
  {"zvl32768b",   ISA_SPEC_CLASS_DRAFT,   1, 0,  0 },
1274
  {"zvl65536b",   ISA_SPEC_CLASS_DRAFT,   1, 0,  0 },
1275
  {"ztso",    ISA_SPEC_CLASS_DRAFT,   0, 1,  0 },
1276
  {NULL, 0, 0, 0, 0}
1277
};
1278
1279
static struct riscv_supported_ext riscv_supported_std_s_ext[] =
1280
{
1281
  {"smaia",   ISA_SPEC_CLASS_DRAFT,   1, 0, 0 },
1282
  {"smepmp",    ISA_SPEC_CLASS_DRAFT,   1, 0, 0 },
1283
  {"smstateen",   ISA_SPEC_CLASS_DRAFT,   1, 0, 0 },
1284
  {"ssaia",   ISA_SPEC_CLASS_DRAFT,   1, 0, 0 },
1285
  {"sscofpmf",    ISA_SPEC_CLASS_DRAFT,   1, 0, 0 },
1286
  {"ssstateen",   ISA_SPEC_CLASS_DRAFT,   1, 0, 0 },
1287
  {"sstc",    ISA_SPEC_CLASS_DRAFT,   1, 0, 0 },
1288
  {"svinval",   ISA_SPEC_CLASS_DRAFT,   1, 0, 0 },
1289
  {"svnapot",   ISA_SPEC_CLASS_DRAFT,   1, 0, 0 },
1290
  {"svpbmt",    ISA_SPEC_CLASS_DRAFT,   1, 0, 0 },
1291
  {NULL, 0, 0, 0, 0}
1292
};
1293
1294
static struct riscv_supported_ext riscv_supported_std_zxm_ext[] =
1295
{
1296
  {NULL, 0, 0, 0, 0}
1297
};
1298
1299
static struct riscv_supported_ext riscv_supported_vendor_x_ext[] =
1300
{
1301
  {"xtheadba",    ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1302
  {"xtheadbb",    ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1303
  {"xtheadbs",    ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1304
  {"xtheadcmo",   ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1305
  {"xtheadcondmov", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1306
  {"xtheadfmemidx", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1307
  {"xtheadfmv",   ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1308
  {"xtheadint",   ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1309
  {"xtheadmac",   ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1310
  {"xtheadmemidx",  ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1311
  {"xtheadmempair", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1312
  {"xtheadsync",  ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1313
  /* XVentanaCondOps: https://github.com/ventanamicro/ventana-custom-extensions/releases/download/v1.0.0/ventana-custom-extensions-v1.0.0.pdf */
1314
  {"xventanacondops", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1315
  {NULL, 0, 0, 0, 0}
1316
};
1317
1318
const struct riscv_supported_ext *riscv_all_supported_ext[] =
1319
{
1320
  riscv_supported_std_ext,
1321
  riscv_supported_std_z_ext,
1322
  riscv_supported_std_s_ext,
1323
  riscv_supported_std_zxm_ext,
1324
  riscv_supported_vendor_x_ext,
1325
  NULL
1326
};
1327
1328
/* ISA extension prefixed name class.  Must define them in parsing order.  */
1329
enum riscv_prefix_ext_class
1330
{
1331
  RV_ISA_CLASS_Z = 1,
1332
  RV_ISA_CLASS_S,
1333
  RV_ISA_CLASS_ZXM,
1334
  RV_ISA_CLASS_X,
1335
  RV_ISA_CLASS_SINGLE
1336
};
1337
1338
/* Record the strings of the prefixed extensions, and their corresponding
1339
   classes.  The more letters of the prefix string, the more forward it must
1340
   be defined.  Otherwise, the riscv_get_prefix_class will map it to the
1341
   wrong classes.  */
1342
struct riscv_parse_prefix_config
1343
{
1344
  /* Class of the extension. */
1345
  enum riscv_prefix_ext_class class;
1346
1347
  /* Prefix string for error printing and internal parser usage.  */
1348
  const char *prefix;
1349
};
1350
static const struct riscv_parse_prefix_config parse_config[] =
1351
{
1352
  {RV_ISA_CLASS_ZXM, "zxm"},
1353
  {RV_ISA_CLASS_Z, "z"},
1354
  {RV_ISA_CLASS_S, "s"},
1355
  {RV_ISA_CLASS_X, "x"},
1356
  {RV_ISA_CLASS_SINGLE, NULL}
1357
};
1358
1359
/* Get the prefixed name class for the extensions, the class also
1360
   means the order of the prefixed extensions.  */
1361
1362
static enum riscv_prefix_ext_class
1363
riscv_get_prefix_class (const char *arch)
1364
0
{
1365
0
  int i = 0;
1366
0
  while (parse_config[i].class != RV_ISA_CLASS_SINGLE)
1367
0
    {
1368
0
      if (strncmp (arch, parse_config[i].prefix,
1369
0
       strlen (parse_config[i].prefix)) == 0)
1370
0
  return parse_config[i].class;
1371
0
      i++;
1372
0
    }
1373
0
  return RV_ISA_CLASS_SINGLE;
1374
0
}
1375
1376
/* Check KNOWN_EXTS to see if the EXT is supported.  */
1377
1378
static bool
1379
riscv_known_prefixed_ext (const char *ext,
1380
        struct riscv_supported_ext *known_exts)
1381
0
{
1382
0
  size_t i;
1383
0
  for (i = 0; known_exts[i].name != NULL; ++i)
1384
0
    if (strcmp (ext, known_exts[i].name) == 0)
1385
0
      return true;
1386
0
  return false;
1387
0
}
1388
1389
/* Check whether the prefixed extension is recognized or not.  Return
1390
   true if recognized, otehrwise return false.  */
1391
1392
static bool
1393
riscv_recognized_prefixed_ext (const char *ext)
1394
0
{
1395
0
  enum riscv_prefix_ext_class class = riscv_get_prefix_class (ext);
1396
0
  switch (class)
1397
0
  {
1398
0
  case RV_ISA_CLASS_Z:
1399
0
    return riscv_known_prefixed_ext (ext, riscv_supported_std_z_ext);
1400
0
  case RV_ISA_CLASS_ZXM:
1401
0
    return riscv_known_prefixed_ext (ext, riscv_supported_std_zxm_ext);
1402
0
  case RV_ISA_CLASS_S:
1403
0
    return riscv_known_prefixed_ext (ext, riscv_supported_std_s_ext);
1404
0
  case RV_ISA_CLASS_X:
1405
    /* Only the single x is unrecognized.  */
1406
0
    if (strcmp (ext, "x") != 0)
1407
0
      return true;
1408
0
  default:
1409
0
    break;
1410
0
  }
1411
0
  return false;
1412
0
}
1413
1414
/* Canonical order for single letter extensions.  */
1415
static const char riscv_ext_canonical_order[] = "eigmafdqlcbkjtpvnh";
1416
1417
/* Array is used to compare the orders of standard extensions quickly.  */
1418
static int riscv_ext_order[26] = {0};
1419
1420
/* Init the riscv_ext_order array.  */
1421
1422
static void
1423
riscv_init_ext_order (void)
1424
0
{
1425
0
  static bool inited = false;
1426
0
  if (inited)
1427
0
    return;
1428
1429
  /* The orders of all standard extensions are positive.  */
1430
0
  int order = 1;
1431
1432
0
  for (const char *ext = &riscv_ext_canonical_order[0]; *ext; ++ext)
1433
0
    riscv_ext_order[(*ext - 'a')] = order++;
1434
1435
  /* Some of the prefixed keyword are not single letter, so we set
1436
     their prefixed orders in the riscv_compare_subsets directly,
1437
     not through the riscv_ext_order.  */
1438
1439
0
  inited = true;
1440
0
}
1441
1442
/* Similar to the strcmp.  It returns an integer less than, equal to,
1443
   or greater than zero if `subset2` is found, respectively, to be less
1444
   than, to match, or be greater than `subset1`.
1445
1446
   The order values,
1447
   Zero: Preserved keywords.
1448
   Positive number: Standard extensions.
1449
   Negative number: Prefixed keywords.  */
1450
1451
int
1452
riscv_compare_subsets (const char *subset1, const char *subset2)
1453
0
{
1454
0
  int order1 = riscv_ext_order[(*subset1 - 'a')];
1455
0
  int order2 = riscv_ext_order[(*subset2 - 'a')];
1456
1457
  /* Compare the standard extension first.  */
1458
0
  if (order1 > 0 && order2 > 0)
1459
0
    return order1 - order2;
1460
1461
  /* Set the prefixed orders to negative numbers.  */
1462
0
  enum riscv_prefix_ext_class class1 = riscv_get_prefix_class (subset1);
1463
0
  enum riscv_prefix_ext_class class2 = riscv_get_prefix_class (subset2);
1464
1465
0
  if (class1 != RV_ISA_CLASS_SINGLE)
1466
0
    order1 = - (int) class1;
1467
0
  if (class2 != RV_ISA_CLASS_SINGLE)
1468
0
    order2 = - (int) class2;
1469
1470
0
  if (order1 == order2)
1471
0
    {
1472
      /* Compare the standard addition z extensions.  */
1473
0
      if (class1 == RV_ISA_CLASS_Z)
1474
0
  {
1475
0
    order1 = riscv_ext_order[(*++subset1 - 'a')];
1476
0
    order2 = riscv_ext_order[(*++subset2 - 'a')];
1477
0
    if (order1 != order2)
1478
0
      return order1 - order2;
1479
0
  }
1480
0
      return strcasecmp (++subset1, ++subset2);
1481
0
    }
1482
1483
0
  return order2 - order1;
1484
0
}
1485
1486
/* Find subset in the list.  Return TRUE and set `current` to the subset
1487
   if it is found.  Otherwise, return FALSE and set `current` to the place
1488
   where we should insert the subset.  However, return FALSE with the NULL
1489
   `current` means we should insert the subset at the head of subset list,
1490
   if needed.  */
1491
1492
bool
1493
riscv_lookup_subset (const riscv_subset_list_t *subset_list,
1494
         const char *subset,
1495
         riscv_subset_t **current)
1496
0
{
1497
0
  riscv_subset_t *s, *pre_s = NULL;
1498
1499
  /* If the subset is added in order, then just add it at the tail.  */
1500
0
  if (subset_list->tail != NULL
1501
0
      && riscv_compare_subsets (subset_list->tail->name, subset) < 0)
1502
0
    {
1503
0
      *current = subset_list->tail;
1504
0
      return false;
1505
0
    }
1506
1507
0
  for (s = subset_list->head;
1508
0
       s != NULL;
1509
0
       pre_s = s, s = s->next)
1510
0
    {
1511
0
      int cmp = riscv_compare_subsets (s->name, subset);
1512
0
      if (cmp == 0)
1513
0
  {
1514
0
    *current = s;
1515
0
    return true;
1516
0
  }
1517
0
      else if (cmp > 0)
1518
0
  break;
1519
0
    }
1520
0
  *current = pre_s;
1521
1522
0
  return false;
1523
0
}
1524
1525
/* Add the extension to the subset list.  Search the
1526
   list first, and then find the right place to add.  */
1527
1528
void
1529
riscv_add_subset (riscv_subset_list_t *subset_list,
1530
      const char *subset,
1531
      int major,
1532
      int minor)
1533
0
{
1534
0
  riscv_subset_t *current, *new;
1535
1536
0
  if (riscv_lookup_subset (subset_list, subset, &current))
1537
0
    return;
1538
1539
0
  new = xmalloc (sizeof *new);
1540
0
  new->name = xstrdup (subset);
1541
0
  new->major_version = major;
1542
0
  new->minor_version = minor;
1543
0
  new->next = NULL;
1544
1545
0
  if (current != NULL)
1546
0
    {
1547
0
      new->next = current->next;
1548
0
      current->next = new;
1549
0
    }
1550
0
  else
1551
0
    {
1552
0
      new->next = subset_list->head;
1553
0
      subset_list->head = new;
1554
0
    }
1555
1556
0
  if (new->next == NULL)
1557
0
    subset_list->tail = new;
1558
0
}
1559
1560
/* Get the default versions from the riscv_supported_*ext tables.  */
1561
1562
static void
1563
riscv_get_default_ext_version (enum riscv_spec_class *default_isa_spec,
1564
             const char *name,
1565
             int *major_version,
1566
             int *minor_version)
1567
0
{
1568
0
  if (name == NULL
1569
0
      || default_isa_spec == NULL
1570
0
      || *default_isa_spec == ISA_SPEC_CLASS_NONE)
1571
0
    return;
1572
1573
0
  struct riscv_supported_ext *table = NULL;
1574
0
  enum riscv_prefix_ext_class class = riscv_get_prefix_class (name);
1575
0
  switch (class)
1576
0
    {
1577
0
    case RV_ISA_CLASS_ZXM: table = riscv_supported_std_zxm_ext; break;
1578
0
    case RV_ISA_CLASS_Z: table = riscv_supported_std_z_ext; break;
1579
0
    case RV_ISA_CLASS_S: table = riscv_supported_std_s_ext; break;
1580
0
    case RV_ISA_CLASS_X: table = riscv_supported_vendor_x_ext; break;
1581
0
    default:
1582
0
      table = riscv_supported_std_ext;
1583
0
    }
1584
1585
0
  int i = 0;
1586
0
  while (table != NULL && table[i].name != NULL)
1587
0
    {
1588
0
      if (strcmp (table[i].name, name) == 0
1589
0
    && (table[i].isa_spec_class == ISA_SPEC_CLASS_DRAFT
1590
0
        || table[i].isa_spec_class == *default_isa_spec))
1591
0
  {
1592
0
    *major_version = table[i].major_version;
1593
0
    *minor_version = table[i].minor_version;
1594
0
    return;
1595
0
  }
1596
0
      i++;
1597
0
    }
1598
0
}
1599
1600
/* Find the default versions for the extension before adding them to
1601
   the subset list, if their versions are RISCV_UNKNOWN_VERSION.
1602
   Afterwards, report errors if we can not find their default versions.  */
1603
1604
static void
1605
riscv_parse_add_subset (riscv_parse_subset_t *rps,
1606
      const char *subset,
1607
      int major,
1608
      int minor,
1609
      bool implicit)
1610
0
{
1611
0
  int major_version = major;
1612
0
  int minor_version = minor;
1613
1614
0
  if (major_version == RISCV_UNKNOWN_VERSION
1615
0
       || minor_version == RISCV_UNKNOWN_VERSION)
1616
0
    riscv_get_default_ext_version (rps->isa_spec, subset,
1617
0
           &major_version, &minor_version);
1618
1619
  /* We don't care the versions of the implicit extensions.  */
1620
0
  if (!implicit
1621
0
      && (major_version == RISCV_UNKNOWN_VERSION
1622
0
    || minor_version == RISCV_UNKNOWN_VERSION))
1623
0
    {
1624
0
      if (subset[0] == 'x')
1625
0
  rps->error_handler
1626
0
    (_("x ISA extension `%s' must be set with the versions"),
1627
0
     subset);
1628
      /* Allow old ISA spec can recognize zicsr and zifencei.  */
1629
0
      else if (strcmp (subset, "zicsr") != 0
1630
0
         && strcmp (subset, "zifencei") != 0)
1631
0
  rps->error_handler
1632
0
    (_("cannot find default versions of the ISA extension `%s'"),
1633
0
     subset);
1634
0
      return;
1635
0
    }
1636
1637
0
  riscv_add_subset (rps->subset_list, subset,
1638
0
        major_version, minor_version);
1639
0
}
1640
1641
/* Release subset list.  */
1642
1643
void
1644
riscv_release_subset_list (riscv_subset_list_t *subset_list)
1645
0
{
1646
0
   while (subset_list->head != NULL)
1647
0
    {
1648
0
      riscv_subset_t *next = subset_list->head->next;
1649
0
      free ((void *)subset_list->head->name);
1650
0
      free (subset_list->head);
1651
0
      subset_list->head = next;
1652
0
    }
1653
1654
0
  subset_list->tail = NULL;
1655
1656
0
  if (subset_list->arch_str != NULL)
1657
0
    {
1658
0
      free ((void*) subset_list->arch_str);
1659
0
      subset_list->arch_str = NULL;
1660
0
    }
1661
0
}
1662
1663
/* Parsing extension version.
1664
1665
   Return Value:
1666
     Points to the end of version
1667
1668
   Arguments:
1669
     `p`: Curent parsing position.
1670
     `major_version`: Parsed major version.
1671
     `minor_version`: Parsed minor version.  */
1672
1673
static const char *
1674
riscv_parsing_subset_version (const char *p,
1675
            int *major_version,
1676
            int *minor_version)
1677
0
{
1678
0
  bool major_p = true;
1679
0
  int version = 0;
1680
0
  char np;
1681
1682
0
  *major_version = 0;
1683
0
  *minor_version = 0;
1684
0
  for (; *p; ++p)
1685
0
    {
1686
0
      if (*p == 'p')
1687
0
  {
1688
0
    np = *(p + 1);
1689
1690
    /* Might be beginning of `p` extension.  */
1691
0
    if (!ISDIGIT (np))
1692
0
      break;
1693
1694
0
    *major_version = version;
1695
0
    major_p = false;
1696
0
    version = 0;
1697
0
  }
1698
0
      else if (ISDIGIT (*p))
1699
0
  version = (version * 10) + (*p - '0');
1700
0
      else
1701
0
  break;
1702
0
    }
1703
1704
0
  if (major_p)
1705
0
    *major_version = version;
1706
0
  else
1707
0
    *minor_version = version;
1708
1709
  /* We can not find any version in string.  */
1710
0
  if (*major_version == 0 && *minor_version == 0)
1711
0
    {
1712
0
      *major_version = RISCV_UNKNOWN_VERSION;
1713
0
      *minor_version = RISCV_UNKNOWN_VERSION;
1714
0
    }
1715
1716
0
  return p;
1717
0
}
1718
1719
/* Parsing function for both standard and prefixed extensions.
1720
1721
   Return Value:
1722
     Points to the end of extensions.
1723
1724
   Arguments:
1725
     `rps`: Hooks and status for parsing extensions.
1726
     `arch`: Full ISA string.
1727
     `p`: Curent parsing position.  */
1728
1729
static const char *
1730
riscv_parse_extensions (riscv_parse_subset_t *rps,
1731
      const char *arch,
1732
      const char *p)
1733
0
{
1734
  /* First letter must start with i, e or g.  */
1735
0
  if (*p != 'e' && *p != 'i' && *p != 'g')
1736
0
    {
1737
0
      rps->error_handler
1738
0
  (_("%s: first ISA extension must be `e', `i' or `g'"),
1739
0
   arch);
1740
0
      return NULL;
1741
0
    }
1742
1743
0
  while (*p != '\0')
1744
0
    {
1745
0
      if (*p == '_')
1746
0
  {
1747
0
    p++;
1748
0
    continue;
1749
0
  }
1750
1751
0
      char *subset = xstrdup (p);
1752
0
      char *q = subset; /* Start of version.  */
1753
0
      const char *end_of_version;
1754
0
      bool implicit = false;
1755
1756
0
      enum riscv_prefix_ext_class class = riscv_get_prefix_class (p);
1757
0
      if (class == RV_ISA_CLASS_SINGLE)
1758
0
  {
1759
0
    if (riscv_ext_order[(*subset - 'a')] == 0)
1760
0
      {
1761
0
        rps->error_handler
1762
0
    (_("%s: unknown standard ISA extension or prefix class `%c'"),
1763
0
     arch, *subset);
1764
0
        free (subset);
1765
0
        return NULL;
1766
0
      }
1767
0
    q++;
1768
0
  }
1769
0
      else
1770
0
  {
1771
    /* Extract the whole prefixed extension by '_'.  */
1772
0
    while (*++q != '\0' && *q != '_')
1773
0
      ;
1774
    /* Look forward to the first letter which is not <major>p<minor>.  */
1775
0
    bool find_any_version = false;
1776
0
    bool find_minor_version = false;
1777
0
    while (1)
1778
0
      {
1779
0
        q--;
1780
0
        if (ISDIGIT (*q))
1781
0
    find_any_version = true;
1782
0
        else if (find_any_version
1783
0
           && !find_minor_version
1784
0
           && *q == 'p'
1785
0
           && ISDIGIT (*(q - 1)))
1786
0
        find_minor_version = true;
1787
0
        else
1788
0
    break;
1789
0
      }
1790
0
    q++;
1791
1792
    /* Check if the end of extension is 'p' or not.  If yes, then
1793
       the second letter from the end cannot be number.  */
1794
0
    if (*(q - 1) == 'p' && ISDIGIT (*(q - 2)))
1795
0
      {
1796
0
        *q = '\0';
1797
0
        rps->error_handler
1798
0
    (_("%s: invalid prefixed ISA extension `%s' ends with <number>p"),
1799
0
     arch, subset);
1800
0
        free (subset);
1801
0
        return NULL;
1802
0
      }
1803
0
  }
1804
1805
0
      int major_version = RISCV_UNKNOWN_VERSION;
1806
0
      int minor_version = RISCV_UNKNOWN_VERSION;
1807
0
      end_of_version =
1808
0
  riscv_parsing_subset_version (q, &major_version, &minor_version);
1809
0
      *q = '\0';
1810
0
      if (end_of_version == NULL)
1811
0
  {
1812
0
    free (subset);
1813
0
    return NULL;
1814
0
  }
1815
1816
      /* Check if the prefixed extension name is well-formed.  */
1817
0
      if (class != RV_ISA_CLASS_SINGLE
1818
0
    && rps->check_unknown_prefixed_ext
1819
0
    && !riscv_recognized_prefixed_ext (subset))
1820
0
  {
1821
0
    rps->error_handler
1822
0
      (_("%s: unknown prefixed ISA extension `%s'"),
1823
0
       arch, subset);
1824
0
    free (subset);
1825
0
    return NULL;
1826
0
  }
1827
1828
      /* Added g as an implicit extension.  */
1829
0
      if (class == RV_ISA_CLASS_SINGLE
1830
0
    && strcmp (subset, "g") == 0)
1831
0
  {
1832
0
    implicit = true;
1833
0
    major_version = RISCV_UNKNOWN_VERSION;
1834
0
    minor_version = RISCV_UNKNOWN_VERSION;
1835
0
  }
1836
0
      riscv_parse_add_subset (rps, subset,
1837
0
            major_version,
1838
0
            minor_version, implicit);
1839
0
      p += end_of_version - subset;
1840
0
      free (subset);
1841
1842
0
      if (class != RV_ISA_CLASS_SINGLE
1843
0
    && *p != '\0' && *p != '_')
1844
0
  {
1845
0
    rps->error_handler
1846
0
      (_("%s: prefixed ISA extension must separate with _"),
1847
0
       arch);
1848
0
    return NULL;
1849
0
  }
1850
0
    }
1851
1852
0
  return p;
1853
0
}
1854
1855
/* Add the implicit extensions.  */
1856
1857
static void
1858
riscv_parse_add_implicit_subsets (riscv_parse_subset_t *rps)
1859
0
{
1860
0
  struct riscv_implicit_subset *t = riscv_implicit_subsets;
1861
0
  for (; t->subset_name; t++)
1862
0
    {
1863
0
      riscv_subset_t *subset = NULL;
1864
0
      if (riscv_lookup_subset (rps->subset_list, t->subset_name, &subset)
1865
0
    && t->check_func (t->implicit_name, subset))
1866
0
  riscv_parse_add_subset (rps, t->implicit_name,
1867
0
        RISCV_UNKNOWN_VERSION,
1868
0
        RISCV_UNKNOWN_VERSION, true);
1869
0
    }
1870
0
}
1871
1872
/* Check extensions conflicts.  */
1873
1874
static bool
1875
riscv_parse_check_conflicts (riscv_parse_subset_t *rps)
1876
0
{
1877
0
  riscv_subset_t *subset = NULL;
1878
0
  int xlen = *rps->xlen;
1879
0
  bool no_conflict = true;
1880
1881
0
  if (riscv_lookup_subset (rps->subset_list, "e", &subset)
1882
0
      && xlen > 32)
1883
0
    {
1884
0
      rps->error_handler
1885
0
  (_("rv%d does not support the `e' extension"), xlen);
1886
0
      no_conflict = false;
1887
0
    }
1888
0
  if (riscv_lookup_subset (rps->subset_list, "q", &subset)
1889
0
      && (subset->major_version < 2 || (subset->major_version == 2
1890
0
          && subset->minor_version < 2))
1891
0
      && xlen < 64)
1892
0
    {
1893
0
      rps->error_handler (_("rv%d does not support the `q' extension"), xlen);
1894
0
      no_conflict = false;
1895
0
    }
1896
0
  if (riscv_lookup_subset (rps->subset_list, "zfinx", &subset)
1897
0
      && riscv_lookup_subset (rps->subset_list, "f", &subset))
1898
0
    {
1899
0
      rps->error_handler
1900
0
  (_("`zfinx' is conflict with the `f/d/q/zfh/zfhmin' extension"));
1901
0
      no_conflict = false;
1902
0
    }
1903
1904
0
  bool support_zve = false;
1905
0
  bool support_zvl = false;
1906
0
  riscv_subset_t *s = rps->subset_list->head;
1907
0
  for (; s != NULL; s = s->next)
1908
0
    {
1909
0
      if (!support_zve
1910
0
    && strncmp (s->name, "zve", 3) == 0)
1911
0
  support_zve = true;
1912
0
      if (!support_zvl
1913
0
    && strncmp (s->name, "zvl", 3) == 0)
1914
0
  support_zvl = true;
1915
0
      if (support_zve && support_zvl)
1916
0
  break;
1917
0
    }
1918
0
  if (support_zvl && !support_zve)
1919
0
    {
1920
0
      rps->error_handler
1921
0
  (_("zvl*b extensions need to enable either `v' or `zve' extension"));
1922
0
      no_conflict = false;
1923
0
    }
1924
1925
0
  return no_conflict;
1926
0
}
1927
1928
/* Set the default subset list according to the default_enable field
1929
   of riscv_supported_*ext tables.  */
1930
1931
static void
1932
riscv_set_default_arch (riscv_parse_subset_t *rps)
1933
0
{
1934
0
  unsigned long enable = EXT_DEFAULT;
1935
0
  int i, j;
1936
0
  for (i = 0; riscv_all_supported_ext[i] != NULL; i++)
1937
0
    {
1938
0
      const struct riscv_supported_ext *table = riscv_all_supported_ext[i];
1939
0
      for (j = 0; table[j].name != NULL; j++)
1940
0
  {
1941
0
    bool implicit = false;
1942
0
    if (strcmp (table[j].name, "g") == 0)
1943
0
      implicit = true;
1944
0
    if (table[j].default_enable & enable)
1945
0
      riscv_parse_add_subset (rps, table[j].name,
1946
0
            RISCV_UNKNOWN_VERSION,
1947
0
            RISCV_UNKNOWN_VERSION, implicit);
1948
0
  }
1949
0
    }
1950
0
}
1951
1952
/* Function for parsing ISA string.
1953
1954
   Return Value:
1955
     Return TRUE on success.
1956
1957
   Arguments:
1958
     `rps`: Hooks and status for parsing extensions.
1959
     `arch`: Full ISA string.  */
1960
1961
bool
1962
riscv_parse_subset (riscv_parse_subset_t *rps,
1963
        const char *arch)
1964
0
{
1965
0
  const char *p;
1966
1967
  /* Init the riscv_ext_order array to compare the order of extensions
1968
     quickly.  */
1969
0
  riscv_init_ext_order ();
1970
1971
0
  if (arch == NULL)
1972
0
    {
1973
0
      riscv_set_default_arch (rps);
1974
0
      riscv_parse_add_implicit_subsets (rps);
1975
0
      return riscv_parse_check_conflicts (rps);
1976
0
    }
1977
1978
0
  for (p = arch; *p != '\0'; p++)
1979
0
    {
1980
0
      if (ISUPPER (*p))
1981
0
  {
1982
0
    rps->error_handler
1983
0
      (_("%s: ISA string cannot contain uppercase letters"),
1984
0
       arch);
1985
0
    return false;
1986
0
  }
1987
0
    }
1988
1989
0
  p = arch;
1990
0
  if (startswith (p, "rv32"))
1991
0
    {
1992
0
      *rps->xlen = 32;
1993
0
      p += 4;
1994
0
    }
1995
0
  else if (startswith (p, "rv64"))
1996
0
    {
1997
0
      *rps->xlen = 64;
1998
0
      p += 4;
1999
0
    }
2000
0
  else
2001
0
    {
2002
      /* ISA string shouldn't be NULL or empty here.  For linker,
2003
   it might be empty when we failed to merge the ISA string
2004
   in the riscv_merge_attributes.  For assembler, we might
2005
   give an empty string by .attribute arch, "" or -march=.
2006
   However, We have already issued the correct error message
2007
   in another side, so do not issue this error when the ISA
2008
   string is empty.  */
2009
0
      if (strlen (arch))
2010
0
  rps->error_handler (
2011
0
    _("%s: ISA string must begin with rv32 or rv64"),
2012
0
    arch);
2013
0
      return false;
2014
0
    }
2015
2016
  /* Parse single standard and prefixed extensions.  */
2017
0
  if (riscv_parse_extensions (rps, arch, p) == NULL)
2018
0
    return false;
2019
2020
  /* Finally add implicit extensions according to the current
2021
     extensions.  */
2022
0
  riscv_parse_add_implicit_subsets (rps);
2023
2024
  /* Check the conflicts.  */
2025
0
  return riscv_parse_check_conflicts (rps);
2026
0
}
2027
2028
/* Return the number of digits for the input.  */
2029
2030
size_t
2031
riscv_estimate_digit (unsigned num)
2032
0
{
2033
0
  size_t digit = 0;
2034
0
  if (num == 0)
2035
0
    return 1;
2036
2037
0
  for (digit = 0; num ; num /= 10)
2038
0
    digit++;
2039
2040
0
  return digit;
2041
0
}
2042
2043
/* Auxiliary function to estimate string length of subset list.  */
2044
2045
static size_t
2046
riscv_estimate_arch_strlen1 (const riscv_subset_t *subset)
2047
0
{
2048
0
  if (subset == NULL)
2049
0
    return 6; /* For rv32/rv64/rv128 and string terminator.  */
2050
2051
0
  return riscv_estimate_arch_strlen1 (subset->next)
2052
0
   + strlen (subset->name)
2053
0
   + riscv_estimate_digit (subset->major_version)
2054
0
   + 1 /* For version seperator 'p'.  */
2055
0
   + riscv_estimate_digit (subset->minor_version)
2056
0
   + 1 /* For underscore.  */;
2057
0
}
2058
2059
/* Estimate the string length of this subset list.  */
2060
2061
static size_t
2062
riscv_estimate_arch_strlen (const riscv_subset_list_t *subset_list)
2063
0
{
2064
0
  return riscv_estimate_arch_strlen1 (subset_list->head);
2065
0
}
2066
2067
/* Auxiliary function to convert subset info to string.  */
2068
2069
static void
2070
riscv_arch_str1 (riscv_subset_t *subset,
2071
     char *attr_str, char *buf, size_t bufsz)
2072
0
{
2073
0
  const char *underline = "_";
2074
0
  riscv_subset_t *subset_t = subset;
2075
2076
0
  if (subset_t == NULL)
2077
0
    return;
2078
2079
  /* No underline between rvXX and i/e.  */
2080
0
  if ((strcasecmp (subset_t->name, "i") == 0)
2081
0
      || (strcasecmp (subset_t->name, "e") == 0))
2082
0
    underline = "";
2083
2084
0
  snprintf (buf, bufsz, "%s%s%dp%d",
2085
0
      underline,
2086
0
      subset_t->name,
2087
0
      subset_t->major_version,
2088
0
      subset_t->minor_version);
2089
2090
0
  strncat (attr_str, buf, bufsz);
2091
2092
  /* Skip 'i' extension after 'e', or skip extensions which
2093
     versions are unknown.  */
2094
0
  while (subset_t->next
2095
0
   && ((strcmp (subset_t->name, "e") == 0
2096
0
        && strcmp (subset_t->next->name, "i") == 0)
2097
0
       || subset_t->next->major_version == RISCV_UNKNOWN_VERSION
2098
0
       || subset_t->next->minor_version == RISCV_UNKNOWN_VERSION))
2099
0
    subset_t = subset_t->next;
2100
2101
0
  riscv_arch_str1 (subset_t->next, attr_str, buf, bufsz);
2102
0
}
2103
2104
/* Convert subset information into string with explicit versions.  */
2105
2106
char *
2107
riscv_arch_str (unsigned xlen, const riscv_subset_list_t *subset)
2108
0
{
2109
0
  size_t arch_str_len = riscv_estimate_arch_strlen (subset);
2110
0
  char *attr_str = xmalloc (arch_str_len);
2111
0
  char *buf = xmalloc (arch_str_len);
2112
2113
0
  snprintf (attr_str, arch_str_len, "rv%u", xlen);
2114
2115
0
  riscv_arch_str1 (subset->head, attr_str, buf, arch_str_len);
2116
0
  free (buf);
2117
2118
0
  return attr_str;
2119
0
}
2120
2121
/* Copy the subset in the subset list.  */
2122
2123
static struct riscv_subset_t *
2124
riscv_copy_subset (riscv_subset_list_t *subset_list,
2125
       riscv_subset_t *subset)
2126
0
{
2127
0
  if (subset == NULL)
2128
0
    return NULL;
2129
2130
0
  riscv_subset_t *new = xmalloc (sizeof *new);
2131
0
  new->name = xstrdup (subset->name);
2132
0
  new->major_version = subset->major_version;
2133
0
  new->minor_version = subset->minor_version;
2134
0
  new->next = riscv_copy_subset (subset_list, subset->next);
2135
2136
0
  if (subset->next == NULL)
2137
0
    subset_list->tail = new;
2138
2139
0
  return new;
2140
0
}
2141
2142
/* Copy the subset list.  */
2143
2144
riscv_subset_list_t *
2145
riscv_copy_subset_list (riscv_subset_list_t *subset_list)
2146
0
{
2147
0
  riscv_subset_list_t *new = xmalloc (sizeof *new);
2148
0
  new->head = riscv_copy_subset (new, subset_list->head);
2149
0
  new->arch_str = strdup (subset_list->arch_str);
2150
0
  return new;
2151
0
}
2152
2153
/* Remove the SUBSET from the subset list.  */
2154
2155
static void
2156
riscv_remove_subset (riscv_subset_list_t *subset_list,
2157
         const char *subset)
2158
0
{
2159
0
  riscv_subset_t *current = subset_list->head;
2160
0
  riscv_subset_t *pre = NULL;
2161
0
  for (; current != NULL; pre = current, current = current->next)
2162
0
    {
2163
0
      if (strcmp (current->name, subset) == 0)
2164
0
  {
2165
0
    if (pre == NULL)
2166
0
      subset_list->head = current->next;
2167
0
    else
2168
0
      pre->next = current->next;
2169
0
    if (current->next == NULL)
2170
0
      subset_list->tail = pre;
2171
0
    free ((void *) current->name);
2172
0
    free (current);
2173
0
    break;
2174
0
  }
2175
0
    }
2176
0
}
2177
2178
/* Add/Remove an extension to/from the subset list.  This is used for
2179
   the .option rvc or norvc, and .option arch directives.  */
2180
2181
bool
2182
riscv_update_subset (riscv_parse_subset_t *rps,
2183
         const char *str)
2184
0
{
2185
0
  const char *p = str;
2186
2187
0
  do
2188
0
    {
2189
0
      int major_version = RISCV_UNKNOWN_VERSION;
2190
0
      int minor_version = RISCV_UNKNOWN_VERSION;
2191
2192
0
      bool removed = false;
2193
0
      switch (*p)
2194
0
  {
2195
0
  case '+': removed = false; break;
2196
0
  case '-': removed = true; break;
2197
0
  default:
2198
0
    riscv_release_subset_list (rps->subset_list);
2199
0
    return riscv_parse_subset (rps, p);
2200
0
  }
2201
0
      ++p;
2202
2203
0
      char *subset = xstrdup (p);
2204
0
      char *q = subset;
2205
0
      const char *end_of_version;
2206
      /* Extract the whole prefixed extension by ','.  */
2207
0
      while (*q != '\0' && *q != ',')
2208
0
        q++;
2209
2210
      /* Look forward to the first letter which is not <major>p<minor>.  */
2211
0
      bool find_any_version = false;
2212
0
      bool find_minor_version = false;
2213
0
      size_t len = q - subset;
2214
0
      size_t i;
2215
0
      for (i = len; i > 0; i--)
2216
0
        {
2217
0
    q--;
2218
0
    if (ISDIGIT (*q))
2219
0
      find_any_version = true;
2220
0
    else if (find_any_version
2221
0
       && !find_minor_version
2222
0
       && *q == 'p'
2223
0
       && ISDIGIT (*(q - 1)))
2224
0
      find_minor_version = true;
2225
0
    else
2226
0
      break;
2227
0
  }
2228
0
      if (len > 0)
2229
0
  q++;
2230
2231
      /* Check if the end of extension is 'p' or not.  If yes, then
2232
   the second letter from the end cannot be number.  */
2233
0
      if (len > 1 && *(q - 1) == 'p' && ISDIGIT (*(q - 2)))
2234
0
  {
2235
0
    *q = '\0';
2236
0
    rps->error_handler
2237
0
      (_("invalid ISA extension ends with <number>p "
2238
0
         "in .option arch `%s'"), str);
2239
0
    free (subset);
2240
0
    return false;
2241
0
  }
2242
2243
0
      end_of_version =
2244
0
  riscv_parsing_subset_version (q, &major_version, &minor_version);
2245
0
      *q = '\0';
2246
0
      if (end_of_version == NULL)
2247
0
  {
2248
0
    free (subset);
2249
0
    return false;
2250
0
  }
2251
2252
0
      if (strlen (subset) == 0
2253
0
    || (strlen (subset) == 1
2254
0
        && riscv_ext_order[(*subset - 'a')] == 0)
2255
0
    || (strlen (subset) > 1
2256
0
        && rps->check_unknown_prefixed_ext
2257
0
        && !riscv_recognized_prefixed_ext (subset)))
2258
0
  {
2259
0
    rps->error_handler
2260
0
      (_("unknown ISA extension `%s' in .option arch `%s'"),
2261
0
       subset, str);
2262
0
    free (subset);
2263
0
    return false;
2264
0
  }
2265
2266
0
      if (strcmp (subset, "i") == 0
2267
0
    || strcmp (subset, "e") == 0
2268
0
    || strcmp (subset, "g") == 0)
2269
0
  {
2270
0
    rps->error_handler
2271
0
      (_("cannot + or - base extension `%s' in .option "
2272
0
         "arch `%s'"), subset, str);
2273
0
    free (subset);
2274
0
    return false;
2275
0
  }
2276
2277
0
      if (removed)
2278
0
  riscv_remove_subset (rps->subset_list, subset);
2279
0
      else
2280
0
  riscv_parse_add_subset (rps, subset, major_version, minor_version, true);
2281
0
      p += end_of_version - subset;
2282
0
      free (subset);
2283
0
    }
2284
0
  while (*p++ == ',');
2285
2286
0
  riscv_parse_add_implicit_subsets (rps);
2287
0
  return riscv_parse_check_conflicts (rps);
2288
0
}
2289
2290
/* Check if the FEATURE subset is supported or not in the subset list.
2291
   Return true if it is supported; Otherwise, return false.  */
2292
2293
bool
2294
riscv_subset_supports (riscv_parse_subset_t *rps,
2295
           const char *feature)
2296
0
{
2297
0
  struct riscv_subset_t *subset;
2298
0
  return riscv_lookup_subset (rps->subset_list, feature, &subset);
2299
0
}
2300
2301
/* Each instuction is belonged to an instruction class INSN_CLASS_*.
2302
   Call riscv_subset_supports to make sure if the instuction is valid.  */
2303
2304
bool
2305
riscv_multi_subset_supports (riscv_parse_subset_t *rps,
2306
           enum riscv_insn_class insn_class)
2307
0
{
2308
0
  switch (insn_class)
2309
0
    {
2310
0
    case INSN_CLASS_I:
2311
0
      return riscv_subset_supports (rps, "i");
2312
0
    case INSN_CLASS_ZICBOM:
2313
0
      return riscv_subset_supports (rps, "zicbom");
2314
0
    case INSN_CLASS_ZICBOP:
2315
0
      return riscv_subset_supports (rps, "zicbop");
2316
0
    case INSN_CLASS_ZICBOZ:
2317
0
      return riscv_subset_supports (rps, "zicboz");
2318
0
    case INSN_CLASS_ZICOND:
2319
0
      return riscv_subset_supports (rps, "zicond");
2320
0
    case INSN_CLASS_ZICSR:
2321
0
      return riscv_subset_supports (rps, "zicsr");
2322
0
    case INSN_CLASS_ZIFENCEI:
2323
0
      return riscv_subset_supports (rps, "zifencei");
2324
0
    case INSN_CLASS_ZIHINTPAUSE:
2325
0
      return riscv_subset_supports (rps, "zihintpause");
2326
0
    case INSN_CLASS_M:
2327
0
      return riscv_subset_supports (rps, "m");
2328
0
    case INSN_CLASS_ZMMUL:
2329
0
      return riscv_subset_supports (rps, "zmmul");
2330
0
    case INSN_CLASS_A:
2331
0
      return riscv_subset_supports (rps, "a");
2332
0
    case INSN_CLASS_ZAWRS:
2333
0
      return riscv_subset_supports (rps, "zawrs");
2334
0
    case INSN_CLASS_F:
2335
0
      return riscv_subset_supports (rps, "f");
2336
0
    case INSN_CLASS_D:
2337
0
      return riscv_subset_supports (rps, "d");
2338
0
    case INSN_CLASS_Q:
2339
0
      return riscv_subset_supports (rps, "q");
2340
0
    case INSN_CLASS_C:
2341
0
      return riscv_subset_supports (rps, "c");
2342
0
    case INSN_CLASS_F_AND_C:
2343
0
      return (riscv_subset_supports (rps, "f")
2344
0
        && riscv_subset_supports (rps, "c"));
2345
0
    case INSN_CLASS_D_AND_C:
2346
0
      return (riscv_subset_supports (rps, "d")
2347
0
        && riscv_subset_supports (rps, "c"));
2348
0
    case INSN_CLASS_F_INX:
2349
0
      return (riscv_subset_supports (rps, "f")
2350
0
        || riscv_subset_supports (rps, "zfinx"));
2351
0
    case INSN_CLASS_D_INX:
2352
0
      return (riscv_subset_supports (rps, "d")
2353
0
        || riscv_subset_supports (rps, "zdinx"));
2354
0
    case INSN_CLASS_Q_INX:
2355
0
      return (riscv_subset_supports (rps, "q")
2356
0
        || riscv_subset_supports (rps, "zqinx"));
2357
0
    case INSN_CLASS_ZFH_INX:
2358
0
      return (riscv_subset_supports (rps, "zfh")
2359
0
        || riscv_subset_supports (rps, "zhinx"));
2360
0
    case INSN_CLASS_ZFHMIN:
2361
0
      return riscv_subset_supports (rps, "zfhmin");
2362
0
    case INSN_CLASS_ZFHMIN_INX:
2363
0
      return (riscv_subset_supports (rps, "zfhmin")
2364
0
        || riscv_subset_supports (rps, "zhinxmin"));
2365
0
    case INSN_CLASS_ZFHMIN_AND_D_INX:
2366
0
      return ((riscv_subset_supports (rps, "zfhmin")
2367
0
         && riscv_subset_supports (rps, "d"))
2368
0
        || (riscv_subset_supports (rps, "zhinxmin")
2369
0
      && riscv_subset_supports (rps, "zdinx")));
2370
0
    case INSN_CLASS_ZFHMIN_AND_Q_INX:
2371
0
      return ((riscv_subset_supports (rps, "zfhmin")
2372
0
         && riscv_subset_supports (rps, "q"))
2373
0
        || (riscv_subset_supports (rps, "zhinxmin")
2374
0
      && riscv_subset_supports (rps, "zqinx")));
2375
0
    case INSN_CLASS_ZBA:
2376
0
      return riscv_subset_supports (rps, "zba");
2377
0
    case INSN_CLASS_ZBB:
2378
0
      return riscv_subset_supports (rps, "zbb");
2379
0
    case INSN_CLASS_ZBC:
2380
0
      return riscv_subset_supports (rps, "zbc");
2381
0
    case INSN_CLASS_ZBS:
2382
0
      return riscv_subset_supports (rps, "zbs");
2383
0
    case INSN_CLASS_ZBKB:
2384
0
      return riscv_subset_supports (rps, "zbkb");
2385
0
    case INSN_CLASS_ZBKC:
2386
0
      return riscv_subset_supports (rps, "zbkc");
2387
0
    case INSN_CLASS_ZBKX:
2388
0
      return riscv_subset_supports (rps, "zbkx");
2389
0
    case INSN_CLASS_ZBB_OR_ZBKB:
2390
0
      return (riscv_subset_supports (rps, "zbb")
2391
0
        || riscv_subset_supports (rps, "zbkb"));
2392
0
    case INSN_CLASS_ZBC_OR_ZBKC:
2393
0
      return (riscv_subset_supports (rps, "zbc")
2394
0
        || riscv_subset_supports (rps, "zbkc"));
2395
0
    case INSN_CLASS_ZKND:
2396
0
      return riscv_subset_supports (rps, "zknd");
2397
0
    case INSN_CLASS_ZKNE:
2398
0
      return riscv_subset_supports (rps, "zkne");
2399
0
    case INSN_CLASS_ZKNH:
2400
0
      return riscv_subset_supports (rps, "zknh");
2401
0
    case INSN_CLASS_ZKND_OR_ZKNE:
2402
0
      return (riscv_subset_supports (rps, "zknd")
2403
0
        || riscv_subset_supports (rps, "zkne"));
2404
0
    case INSN_CLASS_ZKSED:
2405
0
      return riscv_subset_supports (rps, "zksed");
2406
0
    case INSN_CLASS_ZKSH:
2407
0
      return riscv_subset_supports (rps, "zksh");
2408
0
    case INSN_CLASS_V:
2409
0
      return (riscv_subset_supports (rps, "v")
2410
0
        || riscv_subset_supports (rps, "zve64x")
2411
0
        || riscv_subset_supports (rps, "zve32x"));
2412
0
    case INSN_CLASS_ZVEF:
2413
0
      return (riscv_subset_supports (rps, "v")
2414
0
        || riscv_subset_supports (rps, "zve64d")
2415
0
        || riscv_subset_supports (rps, "zve64f")
2416
0
        || riscv_subset_supports (rps, "zve32f"));
2417
0
    case INSN_CLASS_SVINVAL:
2418
0
      return riscv_subset_supports (rps, "svinval");
2419
0
    case INSN_CLASS_H:
2420
0
      return riscv_subset_supports (rps, "h");
2421
0
    case INSN_CLASS_XTHEADBA:
2422
0
      return riscv_subset_supports (rps, "xtheadba");
2423
0
    case INSN_CLASS_XTHEADBB:
2424
0
      return riscv_subset_supports (rps, "xtheadbb");
2425
0
    case INSN_CLASS_XTHEADBS:
2426
0
      return riscv_subset_supports (rps, "xtheadbs");
2427
0
    case INSN_CLASS_XTHEADCMO:
2428
0
      return riscv_subset_supports (rps, "xtheadcmo");
2429
0
    case INSN_CLASS_XTHEADCONDMOV:
2430
0
      return riscv_subset_supports (rps, "xtheadcondmov");
2431
0
    case INSN_CLASS_XTHEADFMEMIDX:
2432
0
      return riscv_subset_supports (rps, "xtheadfmemidx");
2433
0
    case INSN_CLASS_XTHEADFMV:
2434
0
      return riscv_subset_supports (rps, "xtheadfmv");
2435
0
    case INSN_CLASS_XTHEADINT:
2436
0
      return riscv_subset_supports (rps, "xtheadint");
2437
0
    case INSN_CLASS_XTHEADMAC:
2438
0
      return riscv_subset_supports (rps, "xtheadmac");
2439
0
    case INSN_CLASS_XTHEADMEMIDX:
2440
0
      return riscv_subset_supports (rps, "xtheadmemidx");
2441
0
    case INSN_CLASS_XTHEADMEMPAIR:
2442
0
      return riscv_subset_supports (rps, "xtheadmempair");
2443
0
    case INSN_CLASS_XTHEADSYNC:
2444
0
      return riscv_subset_supports (rps, "xtheadsync");
2445
0
    case INSN_CLASS_XVENTANACONDOPS:
2446
0
      return riscv_subset_supports (rps, "xventanacondops");
2447
0
    default:
2448
0
      rps->error_handler
2449
0
        (_("internal: unreachable INSN_CLASS_*"));
2450
0
      return false;
2451
0
    }
2452
0
}
2453
2454
/* Each instuction is belonged to an instruction class INSN_CLASS_*.
2455
   Call riscv_subset_supports_ext to determine the missing extension.  */
2456
2457
const char *
2458
riscv_multi_subset_supports_ext (riscv_parse_subset_t *rps,
2459
         enum riscv_insn_class insn_class)
2460
0
{
2461
0
  switch (insn_class)
2462
0
    {
2463
0
    case INSN_CLASS_I:
2464
0
      return "i";
2465
0
    case INSN_CLASS_ZICBOM:
2466
0
      return "zicbom";
2467
0
    case INSN_CLASS_ZICBOP:
2468
0
      return "zicbop";
2469
0
    case INSN_CLASS_ZICBOZ:
2470
0
      return "zicboz";
2471
0
    case INSN_CLASS_ZICOND:
2472
0
      return "zicond";
2473
0
    case INSN_CLASS_ZICSR:
2474
0
      return "zicsr";
2475
0
    case INSN_CLASS_ZIFENCEI:
2476
0
      return "zifencei";
2477
0
    case INSN_CLASS_ZIHINTPAUSE:
2478
0
      return "zihintpause";
2479
0
    case INSN_CLASS_M:
2480
0
      return "m";
2481
0
    case INSN_CLASS_ZMMUL:
2482
0
      return _ ("m' or `zmmul");
2483
0
    case INSN_CLASS_A:
2484
0
      return "a";
2485
0
    case INSN_CLASS_ZAWRS:
2486
0
      return "zawrs";
2487
0
    case INSN_CLASS_F:
2488
0
      return "f";
2489
0
    case INSN_CLASS_D:
2490
0
      return "d";
2491
0
    case INSN_CLASS_Q:
2492
0
      return "q";
2493
0
    case INSN_CLASS_C:
2494
0
      return "c";
2495
0
    case INSN_CLASS_F_AND_C:
2496
0
      if (!riscv_subset_supports (rps, "f")
2497
0
    && !riscv_subset_supports (rps, "c"))
2498
0
  return _("f' and `c");
2499
0
      else if (!riscv_subset_supports (rps, "f"))
2500
0
  return "f";
2501
0
      else
2502
0
  return "c";
2503
0
    case INSN_CLASS_D_AND_C:
2504
0
      if (!riscv_subset_supports (rps, "d")
2505
0
    && !riscv_subset_supports (rps, "c"))
2506
0
  return _("d' and `c");
2507
0
      else if (!riscv_subset_supports (rps, "d"))
2508
0
  return "d";
2509
0
      else
2510
0
  return "c";
2511
0
    case INSN_CLASS_F_INX:
2512
0
      return _("f' or `zfinx");
2513
0
    case INSN_CLASS_D_INX:
2514
0
      return _("d' or `zdinx");
2515
0
    case INSN_CLASS_Q_INX:
2516
0
      return _("q' or `zqinx");
2517
0
    case INSN_CLASS_ZFH_INX:
2518
0
      return _("zfh' or `zhinx");
2519
0
    case INSN_CLASS_ZFHMIN:
2520
0
      return "zfhmin";
2521
0
    case INSN_CLASS_ZFHMIN_INX:
2522
0
      return _("zfhmin' or `zhinxmin");
2523
0
    case INSN_CLASS_ZFHMIN_AND_D_INX:
2524
0
      if (riscv_subset_supports (rps, "zfhmin"))
2525
0
  return "d";
2526
0
      else if (riscv_subset_supports (rps, "d"))
2527
0
  return "zfhmin";
2528
0
      else if (riscv_subset_supports (rps, "zhinxmin"))
2529
0
  return "zdinx";
2530
0
      else if (riscv_subset_supports (rps, "zdinx"))
2531
0
  return "zhinxmin";
2532
0
      else
2533
0
  return _("zfhmin' and `d', or `zhinxmin' and `zdinx");
2534
0
    case INSN_CLASS_ZFHMIN_AND_Q_INX:
2535
0
      if (riscv_subset_supports (rps, "zfhmin"))
2536
0
  return "q";
2537
0
      else if (riscv_subset_supports (rps, "q"))
2538
0
  return "zfhmin";
2539
0
      else if (riscv_subset_supports (rps, "zhinxmin"))
2540
0
  return "zqinx";
2541
0
      else if (riscv_subset_supports (rps, "zqinx"))
2542
0
  return "zhinxmin";
2543
0
      else
2544
0
  return _("zfhmin' and `q', or `zhinxmin' and `zqinx");
2545
0
    case INSN_CLASS_ZBA:
2546
0
      return "zba";
2547
0
    case INSN_CLASS_ZBB:
2548
0
      return "zbb";
2549
0
    case INSN_CLASS_ZBC:
2550
0
      return "zbc";
2551
0
    case INSN_CLASS_ZBS:
2552
0
      return "zbs";
2553
0
    case INSN_CLASS_ZBKB:
2554
0
      return "zbkb";
2555
0
    case INSN_CLASS_ZBKC:
2556
0
      return "zbkc";
2557
0
    case INSN_CLASS_ZBKX:
2558
0
      return "zbkx";
2559
0
    case INSN_CLASS_ZBB_OR_ZBKB:
2560
0
      return _("zbb' or `zbkb");
2561
0
    case INSN_CLASS_ZBC_OR_ZBKC:
2562
0
      return _("zbc' or `zbkc");
2563
0
    case INSN_CLASS_ZKND:
2564
0
      return "zknd";
2565
0
    case INSN_CLASS_ZKNE:
2566
0
      return "zkne";
2567
0
    case INSN_CLASS_ZKNH:
2568
0
      return "zknh";
2569
0
    case INSN_CLASS_ZKND_OR_ZKNE:
2570
0
      return _("zknd' or `zkne");
2571
0
    case INSN_CLASS_ZKSED:
2572
0
      return "zksed";
2573
0
    case INSN_CLASS_ZKSH:
2574
0
      return "zksh";
2575
0
    case INSN_CLASS_V:
2576
0
      return _("v' or `zve64x' or `zve32x");
2577
0
    case INSN_CLASS_ZVEF:
2578
0
      return _("v' or `zve64d' or `zve64f' or `zve32f");
2579
0
    case INSN_CLASS_SVINVAL:
2580
0
      return "svinval";
2581
0
    case INSN_CLASS_H:
2582
0
      return _("h");
2583
0
    case INSN_CLASS_XTHEADBA:
2584
0
      return "xtheadba";
2585
0
    case INSN_CLASS_XTHEADBB:
2586
0
      return "xtheadbb";
2587
0
    case INSN_CLASS_XTHEADBS:
2588
0
      return "xtheadbs";
2589
0
    case INSN_CLASS_XTHEADCMO:
2590
0
      return "xtheadcmo";
2591
0
    case INSN_CLASS_XTHEADCONDMOV:
2592
0
      return "xtheadcondmov";
2593
0
    case INSN_CLASS_XTHEADFMEMIDX:
2594
0
      return "xtheadfmemidx";
2595
0
    case INSN_CLASS_XTHEADFMV:
2596
0
      return "xtheadfmv";
2597
0
    case INSN_CLASS_XTHEADINT:
2598
0
      return "xtheadint";
2599
0
    case INSN_CLASS_XTHEADMAC:
2600
0
      return "xtheadmac";
2601
0
    case INSN_CLASS_XTHEADMEMIDX:
2602
0
      return "xtheadmemidx";
2603
0
    case INSN_CLASS_XTHEADMEMPAIR:
2604
0
      return "xtheadmempair";
2605
0
    case INSN_CLASS_XTHEADSYNC:
2606
0
      return "xtheadsync";
2607
0
    default:
2608
0
      rps->error_handler
2609
0
        (_("internal: unreachable INSN_CLASS_*"));
2610
0
      return NULL;
2611
0
    }
2612
0
}