blob: e4d3a9c87698a31f19bb346ade14e956a46bae46 [file] [log] [blame]
Patrick Georgiaf473ed2015-07-17 23:35:54 +02001diff -urN empty/bfd/cpu-riscv.c binutils-2.25/bfd/cpu-riscv.c
Jonathan A. Kollasch64fc4332015-08-25 13:09:51 -05002--- binutils-2.25/bfd/cpu-riscv.c 1970-01-01 01:00:00.000000000 +0100
Patrick Georgiaf473ed2015-07-17 23:35:54 +02003+++ binutils-2.25/bfd/cpu-riscv.c 2015-07-18 00:02:36.218287546 +0200
Patrick Georgif0bbc952015-03-07 10:57:25 +01004@@ -0,0 +1,80 @@
5+/* BFD backend for RISC-V
6+ Copyright 2011-2014 Free Software Foundation, Inc.
7+
8+ Contributed by Andrew Waterman (waterman@cs.berkeley.edu) at UC Berkeley.
9+ Based on MIPS target.
10+
11+ This file is part of BFD, the Binary File Descriptor library.
12+
13+ This program is free software; you can redistribute it and/or modify
14+ it under the terms of the GNU General Public License as published by
15+ the Free Software Foundation; either version 3 of the License, or
16+ (at your option) any later version.
17+
18+ This program is distributed in the hope that it will be useful,
19+ but WITHOUT ANY WARRANTY; without even the implied warranty of
20+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21+ GNU General Public License for more details.
22+
23+ You should have received a copy of the GNU General Public License
24+ along with this program; if not, write to the Free Software
25+ Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
26+ MA 02110-1301, USA. */
27+
28+#include "sysdep.h"
29+#include "bfd.h"
30+#include "libbfd.h"
31+
32+static const bfd_arch_info_type *riscv_compatible
33+ (const bfd_arch_info_type *, const bfd_arch_info_type *);
34+
35+/* The default routine tests bits_per_word, which is wrong on RISC-V, as
36+ RISC-V word size doesn't correlate with reloc size. */
37+
38+static const bfd_arch_info_type *
39+riscv_compatible (const bfd_arch_info_type *a, const bfd_arch_info_type *b)
40+{
41+ if (a->arch != b->arch)
42+ return NULL;
43+
44+ /* Machine compatibility is checked in
45+ _bfd_riscv_elf_merge_private_bfd_data. */
46+
47+ return a;
48+}
49+
50+#define N(BITS_WORD, BITS_ADDR, NUMBER, PRINT, DEFAULT, NEXT) \
51+ { \
52+ BITS_WORD, /* bits in a word */ \
53+ BITS_ADDR, /* bits in an address */ \
54+ 8, /* 8 bits in a byte */ \
55+ bfd_arch_riscv, \
56+ NUMBER, \
57+ "riscv", \
58+ PRINT, \
59+ 3, \
60+ DEFAULT, \
61+ riscv_compatible, \
62+ bfd_default_scan, \
63+ bfd_arch_default_fill, \
64+ NEXT, \
65+ }
66+
67+enum
68+{
69+ I_riscv64,
70+ I_riscv32
71+};
72+
73+#define NN(index) (&arch_info_struct[(index) + 1])
74+
75+static const bfd_arch_info_type arch_info_struct[] =
76+{
77+ N (64, 64, bfd_mach_riscv64, "riscv:rv64", FALSE, NN(I_riscv64)),
78+ N (32, 32, bfd_mach_riscv32, "riscv:rv32", FALSE, 0)
79+};
80+
81+/* The default architecture is riscv:rv64. */
82+
83+const bfd_arch_info_type bfd_riscv_arch =
84+N (64, 64, 0, "riscv", TRUE, &arch_info_struct[0]);
Patrick Georgiaf473ed2015-07-17 23:35:54 +020085diff -urN empty/bfd/elfnn-riscv.c binutils-2.25/bfd/elfnn-riscv.c
Jonathan A. Kollasch64fc4332015-08-25 13:09:51 -050086--- binutils-2.25/bfd/elfnn-riscv.c 1970-01-01 01:00:00.000000000 +0100
Patrick Georgiaf473ed2015-07-17 23:35:54 +020087+++ binutils-2.25/bfd/elfnn-riscv.c 2015-07-18 00:02:36.218287546 +0200
88@@ -0,0 +1,2995 @@
Patrick Georgif0bbc952015-03-07 10:57:25 +010089+/* RISC-V-specific support for NN-bit ELF.
90+ Copyright 2011-2014 Free Software Foundation, Inc.
91+
92+ Contributed by Andrew Waterman (waterman@cs.berkeley.edu) at UC Berkeley.
93+ Based on TILE-Gx and MIPS targets.
94+
95+ This file is part of BFD, the Binary File Descriptor library.
96+
97+ This program is free software; you can redistribute it and/or modify
98+ it under the terms of the GNU General Public License as published by
99+ the Free Software Foundation; either version 3 of the License, or
100+ (at your option) any later version.
101+
102+ This program is distributed in the hope that it will be useful,
103+ but WITHOUT ANY WARRANTY; without even the implied warranty of
104+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
105+ GNU General Public License for more details.
106+
107+ You should have received a copy of the GNU General Public License
108+ along with this program; if not, write to the Free Software
109+ Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
110+ MA 02110-1301, USA. */
111+
112+
113+/* This file handles RISC-V ELF targets. */
114+
115+#include "sysdep.h"
116+#include "bfd.h"
117+#include "libbfd.h"
118+#include "bfdlink.h"
119+#include "genlink.h"
120+#include "elf-bfd.h"
121+#include "elfxx-riscv.h"
122+#include "elf/riscv.h"
123+#include "opcode/riscv.h"
124+
125+#define ARCH_SIZE NN
126+
127+#define MINUS_ONE ((bfd_vma)0 - 1)
128+
129+#define RISCV_ELF_LOG_WORD_BYTES (ARCH_SIZE == 32 ? 2 : 3)
130+
131+#define RISCV_ELF_WORD_BYTES (1 << RISCV_ELF_LOG_WORD_BYTES)
132+
133+/* The name of the dynamic interpreter. This is put in the .interp
134+ section. */
135+
136+#define ELF64_DYNAMIC_INTERPRETER "/lib/ld.so.1"
137+#define ELF32_DYNAMIC_INTERPRETER "/lib32/ld.so.1"
138+
139+/* The RISC-V linker needs to keep track of the number of relocs that it
140+ decides to copy as dynamic relocs in check_relocs for each symbol.
141+ This is so that it can later discard them if they are found to be
142+ unnecessary. We store the information in a field extending the
143+ regular ELF linker hash table. */
144+
145+struct riscv_elf_dyn_relocs
146+{
147+ struct riscv_elf_dyn_relocs *next;
148+
149+ /* The input section of the reloc. */
150+ asection *sec;
151+
152+ /* Total number of relocs copied for the input section. */
153+ bfd_size_type count;
154+
155+ /* Number of pc-relative relocs copied for the input section. */
156+ bfd_size_type pc_count;
157+};
158+
159+/* RISC-V ELF linker hash entry. */
160+
161+struct riscv_elf_link_hash_entry
162+{
163+ struct elf_link_hash_entry elf;
164+
165+ /* Track dynamic relocs copied for this symbol. */
166+ struct riscv_elf_dyn_relocs *dyn_relocs;
167+
168+#define GOT_UNKNOWN 0
169+#define GOT_NORMAL 1
170+#define GOT_TLS_GD 2
171+#define GOT_TLS_IE 4
172+#define GOT_TLS_LE 8
173+ char tls_type;
174+};
175+
176+#define riscv_elf_hash_entry(ent) \
177+ ((struct riscv_elf_link_hash_entry *)(ent))
178+
179+struct _bfd_riscv_elf_obj_tdata
180+{
181+ struct elf_obj_tdata root;
182+
183+ /* tls_type for each local got entry. */
184+ char *local_got_tls_type;
185+};
186+
187+#define _bfd_riscv_elf_tdata(abfd) \
188+ ((struct _bfd_riscv_elf_obj_tdata *) (abfd)->tdata.any)
189+
190+#define _bfd_riscv_elf_local_got_tls_type(abfd) \
191+ (_bfd_riscv_elf_tdata (abfd)->local_got_tls_type)
192+
193+#define _bfd_riscv_elf_tls_type(abfd, h, symndx) \
194+ (*((h) != NULL ? &riscv_elf_hash_entry(h)->tls_type \
195+ : &_bfd_riscv_elf_local_got_tls_type (abfd) [symndx]))
196+
197+#define is_riscv_elf(bfd) \
198+ (bfd_get_flavour (bfd) == bfd_target_elf_flavour \
199+ && elf_tdata (bfd) != NULL \
200+ && elf_object_id (bfd) == RISCV_ELF_DATA)
201+
202+#include "elf/common.h"
203+#include "elf/internal.h"
204+
205+struct riscv_elf_link_hash_table
206+{
207+ struct elf_link_hash_table elf;
208+
209+ /* Short-cuts to get to dynamic linker sections. */
210+ asection *sdynbss;
211+ asection *srelbss;
212+ asection *sdyntdata;
213+
214+ /* Small local sym to section mapping cache. */
215+ struct sym_cache sym_cache;
216+};
217+
218+
219+/* Get the RISC-V ELF linker hash table from a link_info structure. */
220+#define riscv_elf_hash_table(p) \
221+ (elf_hash_table_id ((struct elf_link_hash_table *) ((p)->hash)) \
222+ == RISCV_ELF_DATA ? ((struct riscv_elf_link_hash_table *) ((p)->hash)) : NULL)
223+
224+static void
225+riscv_info_to_howto_rela (bfd *abfd ATTRIBUTE_UNUSED,
226+ arelent *cache_ptr,
227+ Elf_Internal_Rela *dst)
228+{
229+ cache_ptr->howto = riscv_elf_rtype_to_howto (ELFNN_R_TYPE (dst->r_info));
230+}
231+
232+static void
233+riscv_elf_append_rela (bfd *abfd, asection *s, Elf_Internal_Rela *rel)
234+{
235+ const struct elf_backend_data *bed;
236+ bfd_byte *loc;
237+
238+ bed = get_elf_backend_data (abfd);
239+ loc = s->contents + (s->reloc_count++ * bed->s->sizeof_rela);
240+ bed->s->swap_reloca_out (abfd, rel, loc);
241+}
242+
243+/* PLT/GOT stuff */
244+
245+#define PLT_HEADER_INSNS 8
246+#define PLT_ENTRY_INSNS 4
247+#define PLT_HEADER_SIZE (PLT_HEADER_INSNS * 4)
248+#define PLT_ENTRY_SIZE (PLT_ENTRY_INSNS * 4)
249+
250+#define GOT_ENTRY_SIZE RISCV_ELF_WORD_BYTES
251+
252+#define GOTPLT_HEADER_SIZE (2 * GOT_ENTRY_SIZE)
253+
254+#define sec_addr(sec) ((sec)->output_section->vma + (sec)->output_offset)
255+
256+static bfd_vma
257+riscv_elf_got_plt_val (bfd_vma plt_index, struct bfd_link_info *info)
258+{
259+ return sec_addr (riscv_elf_hash_table (info)->elf.sgotplt)
260+ + GOTPLT_HEADER_SIZE + (plt_index * GOT_ENTRY_SIZE);
261+}
262+
263+#if ARCH_SIZE == 32
264+# define MATCH_LREG MATCH_LW
265+#else
266+# define MATCH_LREG MATCH_LD
267+#endif
268+
269+/* The format of the first PLT entry. */
270+
271+static void
272+riscv_make_plt0_entry(bfd_vma gotplt_addr, bfd_vma addr, uint32_t *entry)
273+{
274+ /* auipc t2, %hi(.got.plt)
275+ sub t1, t1, t0 # shifted .got.plt offset + hdr size + 12
276+ l[w|d] t3, %lo(.got.plt)(t2) # _dl_runtime_resolve
277+ addi t1, t1, -(hdr size + 12) # shifted .got.plt offset
278+ addi t0, t2, %lo(.got.plt) # &.got.plt
279+ srli t1, t1, log2(16/PTRSIZE) # .got.plt offset
280+ l[w|d] t0, PTRSIZE(t0) # link map
281+ jr t3 */
282+
283+ entry[0] = RISCV_UTYPE (AUIPC, X_T2, RISCV_PCREL_HIGH_PART (gotplt_addr, addr));
284+ entry[1] = RISCV_RTYPE (SUB, X_T1, X_T1, X_T0);
285+ entry[2] = RISCV_ITYPE (LREG, X_T3, X_T2, RISCV_PCREL_LOW_PART (gotplt_addr, addr));
286+ entry[3] = RISCV_ITYPE (ADDI, X_T1, X_T1, -(PLT_HEADER_SIZE + 12));
287+ entry[4] = RISCV_ITYPE (ADDI, X_T0, X_T2, RISCV_PCREL_LOW_PART (gotplt_addr, addr));
288+ entry[5] = RISCV_ITYPE (SRLI, X_T1, X_T1, 4 - RISCV_ELF_LOG_WORD_BYTES);
289+ entry[6] = RISCV_ITYPE (LREG, X_T0, X_T0, RISCV_ELF_WORD_BYTES);
290+ entry[7] = RISCV_ITYPE (JALR, 0, X_T3, 0);
291+}
292+
293+/* The format of subsequent PLT entries. */
294+
295+static void
296+riscv_make_plt_entry(bfd_vma got_address, bfd_vma addr, uint32_t *entry)
297+{
298+ /* auipc t1, %hi(.got.plt entry)
299+ l[w|d] t0, %lo(.got.plt entry)(t1)
300+ jalr t1, t0
301+ nop */
302+
303+ entry[0] = RISCV_UTYPE (AUIPC, X_T1, RISCV_PCREL_HIGH_PART (got_address, addr));
304+ entry[1] = RISCV_ITYPE (LREG, X_T0, X_T1, RISCV_PCREL_LOW_PART(got_address, addr));
305+ entry[2] = RISCV_ITYPE (JALR, X_T1, X_T0, 0);
306+ entry[3] = RISCV_NOP;
307+}
308+
309+/* Create an entry in an RISC-V ELF linker hash table. */
310+
311+static struct bfd_hash_entry *
312+link_hash_newfunc (struct bfd_hash_entry *entry,
313+ struct bfd_hash_table *table, const char *string)
314+{
315+ /* Allocate the structure if it has not already been allocated by a
316+ subclass. */
317+ if (entry == NULL)
318+ {
319+ entry =
320+ bfd_hash_allocate (table,
321+ sizeof (struct riscv_elf_link_hash_entry));
322+ if (entry == NULL)
323+ return entry;
324+ }
325+
326+ /* Call the allocation method of the superclass. */
327+ entry = _bfd_elf_link_hash_newfunc (entry, table, string);
328+ if (entry != NULL)
329+ {
330+ struct riscv_elf_link_hash_entry *eh;
331+
332+ eh = (struct riscv_elf_link_hash_entry *) entry;
333+ eh->dyn_relocs = NULL;
334+ eh->tls_type = GOT_UNKNOWN;
335+ }
336+
337+ return entry;
338+}
339+
340+/* Create a RISC-V ELF linker hash table. */
341+
342+static struct bfd_link_hash_table *
343+riscv_elf_link_hash_table_create (bfd *abfd)
344+{
345+ struct riscv_elf_link_hash_table *ret;
346+ bfd_size_type amt = sizeof (struct riscv_elf_link_hash_table);
347+
348+ ret = (struct riscv_elf_link_hash_table *) bfd_zmalloc (amt);
349+ if (ret == NULL)
350+ return NULL;
351+
352+ if (!_bfd_elf_link_hash_table_init (&ret->elf, abfd, link_hash_newfunc,
353+ sizeof (struct riscv_elf_link_hash_entry),
354+ RISCV_ELF_DATA))
355+ {
356+ free (ret);
357+ return NULL;
358+ }
359+
360+ return &ret->elf.root;
361+}
362+
363+/* Create the .got section. */
364+
365+static bfd_boolean
366+riscv_elf_create_got_section (bfd *abfd, struct bfd_link_info *info)
367+{
368+ flagword flags;
369+ asection *s, *s_got;
370+ struct elf_link_hash_entry *h;
371+ const struct elf_backend_data *bed = get_elf_backend_data (abfd);
372+ struct elf_link_hash_table *htab = elf_hash_table (info);
373+
374+ /* This function may be called more than once. */
375+ s = bfd_get_linker_section (abfd, ".got");
376+ if (s != NULL)
377+ return TRUE;
378+
379+ flags = bed->dynamic_sec_flags;
380+
381+ s = bfd_make_section_anyway_with_flags (abfd,
382+ (bed->rela_plts_and_copies_p
383+ ? ".rela.got" : ".rel.got"),
384+ (bed->dynamic_sec_flags
385+ | SEC_READONLY));
386+ if (s == NULL
387+ || ! bfd_set_section_alignment (abfd, s, bed->s->log_file_align))
388+ return FALSE;
389+ htab->srelgot = s;
390+
391+ s = s_got = bfd_make_section_anyway_with_flags (abfd, ".got", flags);
392+ if (s == NULL
393+ || !bfd_set_section_alignment (abfd, s, bed->s->log_file_align))
394+ return FALSE;
395+ htab->sgot = s;
396+
397+ /* The first bit of the global offset table is the header. */
398+ s->size += bed->got_header_size;
399+
400+ if (bed->want_got_plt)
401+ {
402+ s = bfd_make_section_anyway_with_flags (abfd, ".got.plt", flags);
403+ if (s == NULL
404+ || !bfd_set_section_alignment (abfd, s,
405+ bed->s->log_file_align))
406+ return FALSE;
407+ htab->sgotplt = s;
408+
409+ /* Reserve room for the header. */
410+ s->size += GOTPLT_HEADER_SIZE;
411+ }
412+
413+ if (bed->want_got_sym)
414+ {
415+ /* Define the symbol _GLOBAL_OFFSET_TABLE_ at the start of the .got
416+ section. We don't do this in the linker script because we don't want
417+ to define the symbol if we are not creating a global offset
418+ table. */
419+ h = _bfd_elf_define_linkage_sym (abfd, info, s_got,
420+ "_GLOBAL_OFFSET_TABLE_");
421+ elf_hash_table (info)->hgot = h;
422+ if (h == NULL)
423+ return FALSE;
424+ }
425+
426+ return TRUE;
427+}
428+
429+/* Create .plt, .rela.plt, .got, .got.plt, .rela.got, .dynbss, and
430+ .rela.bss sections in DYNOBJ, and set up shortcuts to them in our
431+ hash table. */
432+
433+static bfd_boolean
434+riscv_elf_create_dynamic_sections (bfd *dynobj,
435+ struct bfd_link_info *info)
436+{
437+ struct riscv_elf_link_hash_table *htab;
438+
439+ htab = riscv_elf_hash_table (info);
440+ BFD_ASSERT (htab != NULL);
441+
442+ if (!riscv_elf_create_got_section (dynobj, info))
443+ return FALSE;
444+
445+ if (!_bfd_elf_create_dynamic_sections (dynobj, info))
446+ return FALSE;
447+
448+ htab->sdynbss = bfd_get_linker_section (dynobj, ".dynbss");
449+ if (!info->shared)
450+ {
451+ htab->srelbss = bfd_get_linker_section (dynobj, ".rela.bss");
452+ htab->sdyntdata =
453+ bfd_make_section_anyway_with_flags (dynobj, ".tdata.dyn",
454+ SEC_ALLOC | SEC_THREAD_LOCAL);
455+ }
456+
457+ if (!htab->elf.splt || !htab->elf.srelplt || !htab->sdynbss
458+ || (!info->shared && (!htab->srelbss || !htab->sdyntdata)))
459+ abort ();
460+
461+ return TRUE;
462+}
463+
464+/* Copy the extra info we tack onto an elf_link_hash_entry. */
465+
466+static void
467+riscv_elf_copy_indirect_symbol (struct bfd_link_info *info,
468+ struct elf_link_hash_entry *dir,
469+ struct elf_link_hash_entry *ind)
470+{
471+ struct riscv_elf_link_hash_entry *edir, *eind;
472+
473+ edir = (struct riscv_elf_link_hash_entry *) dir;
474+ eind = (struct riscv_elf_link_hash_entry *) ind;
475+
476+ if (eind->dyn_relocs != NULL)
477+ {
478+ if (edir->dyn_relocs != NULL)
479+ {
480+ struct riscv_elf_dyn_relocs **pp;
481+ struct riscv_elf_dyn_relocs *p;
482+
483+ /* Add reloc counts against the indirect sym to the direct sym
484+ list. Merge any entries against the same section. */
485+ for (pp = &eind->dyn_relocs; (p = *pp) != NULL; )
486+ {
487+ struct riscv_elf_dyn_relocs *q;
488+
489+ for (q = edir->dyn_relocs; q != NULL; q = q->next)
490+ if (q->sec == p->sec)
491+ {
492+ q->pc_count += p->pc_count;
493+ q->count += p->count;
494+ *pp = p->next;
495+ break;
496+ }
497+ if (q == NULL)
498+ pp = &p->next;
499+ }
500+ *pp = edir->dyn_relocs;
501+ }
502+
503+ edir->dyn_relocs = eind->dyn_relocs;
504+ eind->dyn_relocs = NULL;
505+ }
506+
507+ if (ind->root.type == bfd_link_hash_indirect
508+ && dir->got.refcount <= 0)
509+ {
510+ edir->tls_type = eind->tls_type;
511+ eind->tls_type = GOT_UNKNOWN;
512+ }
513+ _bfd_elf_link_hash_copy_indirect (info, dir, ind);
514+}
515+
516+static bfd_boolean
517+riscv_elf_record_tls_type (bfd *abfd, struct elf_link_hash_entry *h,
518+ unsigned long symndx, char tls_type)
519+{
520+ char *new_tls_type = &_bfd_riscv_elf_tls_type (abfd, h, symndx);
521+ *new_tls_type |= tls_type;
522+ if ((*new_tls_type & GOT_NORMAL) && (*new_tls_type & ~GOT_NORMAL))
523+ {
524+ (*_bfd_error_handler)
525+ (_("%B: `%s' accessed both as normal and thread local symbol"),
526+ abfd, h ? h->root.root.string : "<local>");
527+ return FALSE;
528+ }
529+ return TRUE;
530+}
531+
532+static bfd_boolean
533+riscv_elf_record_got_reference (bfd *abfd, struct bfd_link_info *info,
534+ struct elf_link_hash_entry *h, long symndx)
535+{
536+ struct riscv_elf_link_hash_table *htab = riscv_elf_hash_table (info);
537+ Elf_Internal_Shdr *symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
538+
539+ if (htab->elf.sgot == NULL)
540+ {
541+ if (!riscv_elf_create_got_section (htab->elf.dynobj, info))
542+ return FALSE;
543+ }
544+
545+ if (h != NULL)
546+ {
547+ h->got.refcount += 1;
548+ return TRUE;
549+ }
550+
551+ /* This is a global offset table entry for a local symbol. */
552+ if (elf_local_got_refcounts (abfd) == NULL)
553+ {
554+ bfd_size_type size = symtab_hdr->sh_info * (sizeof (bfd_vma) + 1);
555+ if (!(elf_local_got_refcounts (abfd) = bfd_zalloc (abfd, size)))
556+ return FALSE;
557+ _bfd_riscv_elf_local_got_tls_type (abfd)
558+ = (char *) (elf_local_got_refcounts (abfd) + symtab_hdr->sh_info);
559+ }
560+ elf_local_got_refcounts (abfd) [symndx] += 1;
561+
562+ return TRUE;
563+}
564+
565+static bfd_boolean
566+bad_static_reloc (bfd *abfd, unsigned r_type, struct elf_link_hash_entry *h)
567+{
568+ (*_bfd_error_handler)
569+ (_("%B: relocation %s against `%s' can not be used when making a shared object; recompile with -fPIC"),
570+ abfd, riscv_elf_rtype_to_howto (r_type)->name,
571+ h != NULL ? h->root.root.string : "a local symbol");
572+ bfd_set_error (bfd_error_bad_value);
573+ return FALSE;
574+}
575+/* Look through the relocs for a section during the first phase, and
576+ allocate space in the global offset table or procedure linkage
577+ table. */
578+
579+static bfd_boolean
580+riscv_elf_check_relocs (bfd *abfd, struct bfd_link_info *info,
581+ asection *sec, const Elf_Internal_Rela *relocs)
582+{
583+ struct riscv_elf_link_hash_table *htab;
584+ Elf_Internal_Shdr *symtab_hdr;
585+ struct elf_link_hash_entry **sym_hashes;
586+ const Elf_Internal_Rela *rel;
587+ asection *sreloc = NULL;
588+
589+ if (info->relocatable)
590+ return TRUE;
591+
592+ htab = riscv_elf_hash_table (info);
593+ symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
594+ sym_hashes = elf_sym_hashes (abfd);
595+
596+ if (htab->elf.dynobj == NULL)
597+ htab->elf.dynobj = abfd;
598+
599+ for (rel = relocs; rel < relocs + sec->reloc_count; rel++)
600+ {
601+ unsigned int r_type;
602+ unsigned long r_symndx;
603+ struct elf_link_hash_entry *h;
604+
605+ r_symndx = ELFNN_R_SYM (rel->r_info);
606+ r_type = ELFNN_R_TYPE (rel->r_info);
607+
608+ if (r_symndx >= NUM_SHDR_ENTRIES (symtab_hdr))
609+ {
610+ (*_bfd_error_handler) (_("%B: bad symbol index: %d"),
611+ abfd, r_symndx);
612+ return FALSE;
613+ }
614+
615+ if (r_symndx < symtab_hdr->sh_info)
616+ h = NULL;
617+ else
618+ {
619+ h = sym_hashes[r_symndx - symtab_hdr->sh_info];
620+ while (h->root.type == bfd_link_hash_indirect
621+ || h->root.type == bfd_link_hash_warning)
622+ h = (struct elf_link_hash_entry *) h->root.u.i.link;
623+
624+ /* PR15323, ref flags aren't set for references in the same
625+ object. */
626+ h->root.non_ir_ref = 1;
627+ }
628+
629+ switch (r_type)
630+ {
631+ case R_RISCV_TLS_GD_HI20:
632+ if (!riscv_elf_record_got_reference (abfd, info, h, r_symndx)
633+ || !riscv_elf_record_tls_type (abfd, h, r_symndx, GOT_TLS_GD))
634+ return FALSE;
635+ break;
636+
637+ case R_RISCV_TLS_GOT_HI20:
638+ if (info->shared)
639+ info->flags |= DF_STATIC_TLS;
640+ if (!riscv_elf_record_got_reference (abfd, info, h, r_symndx)
641+ || !riscv_elf_record_tls_type (abfd, h, r_symndx, GOT_TLS_IE))
642+ return FALSE;
643+ break;
644+
645+ case R_RISCV_GOT_HI20:
646+ if (!riscv_elf_record_got_reference (abfd, info, h, r_symndx)
647+ || !riscv_elf_record_tls_type (abfd, h, r_symndx, GOT_NORMAL))
648+ return FALSE;
649+ break;
650+
651+ case R_RISCV_CALL_PLT:
652+ /* This symbol requires a procedure linkage table entry. We
653+ actually build the entry in adjust_dynamic_symbol,
654+ because this might be a case of linking PIC code without
655+ linking in any dynamic objects, in which case we don't
656+ need to generate a procedure linkage table after all. */
657+
658+ if (h != NULL)
659+ {
660+ h->needs_plt = 1;
661+ h->plt.refcount += 1;
662+ }
663+ break;
664+
665+ case R_RISCV_CALL:
666+ case R_RISCV_JAL:
667+ case R_RISCV_BRANCH:
Patrick Georgiaf473ed2015-07-17 23:35:54 +0200668+ case R_RISCV_RVC_BRANCH:
669+ case R_RISCV_RVC_JUMP:
Patrick Georgif0bbc952015-03-07 10:57:25 +0100670+ case R_RISCV_PCREL_HI20:
671+ /* In shared libs, these relocs are known to bind locally. */
672+ if (info->shared)
673+ break;
674+ goto static_reloc;
675+
676+ case R_RISCV_TPREL_HI20:
677+ if (!info->executable)
678+ return bad_static_reloc (abfd, r_type, h);
679+ if (h != NULL)
680+ riscv_elf_record_tls_type (abfd, h, r_symndx, GOT_TLS_LE);
681+ goto static_reloc;
682+
683+ case R_RISCV_HI20:
684+ if (info->shared)
685+ return bad_static_reloc (abfd, r_type, h);
686+ /* Fall through. */
687+
688+ case R_RISCV_COPY:
689+ case R_RISCV_JUMP_SLOT:
690+ case R_RISCV_RELATIVE:
691+ case R_RISCV_64:
692+ case R_RISCV_32:
693+ /* Fall through. */
694+
695+ static_reloc:
696+ if (h != NULL)
697+ h->non_got_ref = 1;
698+
699+ if (h != NULL && !info->shared)
700+ {
701+ /* We may need a .plt entry if the function this reloc
702+ refers to is in a shared lib. */
703+ h->plt.refcount += 1;
704+ }
705+
706+ /* If we are creating a shared library, and this is a reloc
707+ against a global symbol, or a non PC relative reloc
708+ against a local symbol, then we need to copy the reloc
709+ into the shared library. However, if we are linking with
710+ -Bsymbolic, we do not need to copy a reloc against a
711+ global symbol which is defined in an object we are
712+ including in the link (i.e., DEF_REGULAR is set). At
713+ this point we have not seen all the input files, so it is
714+ possible that DEF_REGULAR is not set now but will be set
715+ later (it is never cleared). In case of a weak definition,
716+ DEF_REGULAR may be cleared later by a strong definition in
717+ a shared library. We account for that possibility below by
718+ storing information in the relocs_copied field of the hash
719+ table entry. A similar situation occurs when creating
720+ shared libraries and symbol visibility changes render the
721+ symbol local.
722+
723+ If on the other hand, we are creating an executable, we
724+ may need to keep relocations for symbols satisfied by a
725+ dynamic library if we manage to avoid copy relocs for the
726+ symbol. */
727+ if ((info->shared
728+ && (sec->flags & SEC_ALLOC) != 0
729+ && (! riscv_elf_rtype_to_howto (r_type)->pc_relative
730+ || (h != NULL
731+ && (! info->symbolic
732+ || h->root.type == bfd_link_hash_defweak
733+ || !h->def_regular))))
734+ || (!info->shared
735+ && (sec->flags & SEC_ALLOC) != 0
736+ && h != NULL
737+ && (h->root.type == bfd_link_hash_defweak
738+ || !h->def_regular)))
739+ {
740+ struct riscv_elf_dyn_relocs *p;
741+ struct riscv_elf_dyn_relocs **head;
742+
743+ /* When creating a shared object, we must copy these
744+ relocs into the output file. We create a reloc
745+ section in dynobj and make room for the reloc. */
746+ if (sreloc == NULL)
747+ {
748+ sreloc = _bfd_elf_make_dynamic_reloc_section
749+ (sec, htab->elf.dynobj, RISCV_ELF_LOG_WORD_BYTES,
750+ abfd, /*rela?*/ TRUE);
751+
752+ if (sreloc == NULL)
753+ return FALSE;
754+ }
755+
756+ /* If this is a global symbol, we count the number of
757+ relocations we need for this symbol. */
758+ if (h != NULL)
759+ head = &((struct riscv_elf_link_hash_entry *) h)->dyn_relocs;
760+ else
761+ {
762+ /* Track dynamic relocs needed for local syms too.
763+ We really need local syms available to do this
764+ easily. Oh well. */
765+
766+ asection *s;
767+ void *vpp;
768+ Elf_Internal_Sym *isym;
769+
770+ isym = bfd_sym_from_r_symndx (&htab->sym_cache,
771+ abfd, r_symndx);
772+ if (isym == NULL)
773+ return FALSE;
774+
775+ s = bfd_section_from_elf_index (abfd, isym->st_shndx);
776+ if (s == NULL)
777+ s = sec;
778+
779+ vpp = &elf_section_data (s)->local_dynrel;
780+ head = (struct riscv_elf_dyn_relocs **) vpp;
781+ }
782+
783+ p = *head;
784+ if (p == NULL || p->sec != sec)
785+ {
786+ bfd_size_type amt = sizeof *p;
787+ p = ((struct riscv_elf_dyn_relocs *)
788+ bfd_alloc (htab->elf.dynobj, amt));
789+ if (p == NULL)
790+ return FALSE;
791+ p->next = *head;
792+ *head = p;
793+ p->sec = sec;
794+ p->count = 0;
795+ p->pc_count = 0;
796+ }
797+
798+ p->count += 1;
799+ p->pc_count += riscv_elf_rtype_to_howto (r_type)->pc_relative;
800+ }
801+
802+ break;
803+
804+ case R_RISCV_GNU_VTINHERIT:
805+ if (!bfd_elf_gc_record_vtinherit (abfd, sec, h, rel->r_offset))
806+ return FALSE;
807+ break;
808+
809+ case R_RISCV_GNU_VTENTRY:
810+ if (!bfd_elf_gc_record_vtentry (abfd, sec, h, rel->r_addend))
811+ return FALSE;
812+ break;
813+
814+ default:
815+ break;
816+ }
817+ }
818+
819+ return TRUE;
820+}
821+
822+static asection *
823+riscv_elf_gc_mark_hook (asection *sec,
824+ struct bfd_link_info *info,
825+ Elf_Internal_Rela *rel,
826+ struct elf_link_hash_entry *h,
827+ Elf_Internal_Sym *sym)
828+{
829+ if (h != NULL)
830+ switch (ELFNN_R_TYPE (rel->r_info))
831+ {
832+ case R_RISCV_GNU_VTINHERIT:
833+ case R_RISCV_GNU_VTENTRY:
834+ return NULL;
835+ }
836+
837+ return _bfd_elf_gc_mark_hook (sec, info, rel, h, sym);
838+}
839+
840+/* Update the got entry reference counts for the section being removed. */
841+static bfd_boolean
842+riscv_elf_gc_sweep_hook (bfd *abfd, struct bfd_link_info *info,
843+ asection *sec, const Elf_Internal_Rela *relocs)
844+{
845+ const Elf_Internal_Rela *rel, *relend;
846+ Elf_Internal_Shdr *symtab_hdr = &elf_symtab_hdr (abfd);
847+ struct elf_link_hash_entry **sym_hashes = elf_sym_hashes (abfd);
848+ bfd_signed_vma *local_got_refcounts = elf_local_got_refcounts (abfd);
849+
850+ if (info->relocatable)
851+ return TRUE;
852+
853+ elf_section_data (sec)->local_dynrel = NULL;
854+
855+ for (rel = relocs, relend = relocs + sec->reloc_count; rel < relend; rel++)
856+ {
857+ unsigned long r_symndx;
858+ struct elf_link_hash_entry *h = NULL;
859+
860+ r_symndx = ELFNN_R_SYM (rel->r_info);
861+ if (r_symndx >= symtab_hdr->sh_info)
862+ {
863+ struct riscv_elf_link_hash_entry *eh;
864+ struct riscv_elf_dyn_relocs **pp;
865+ struct riscv_elf_dyn_relocs *p;
866+
867+ h = sym_hashes[r_symndx - symtab_hdr->sh_info];
868+ while (h->root.type == bfd_link_hash_indirect
869+ || h->root.type == bfd_link_hash_warning)
870+ h = (struct elf_link_hash_entry *) h->root.u.i.link;
871+ eh = (struct riscv_elf_link_hash_entry *) h;
872+ for (pp = &eh->dyn_relocs; (p = *pp) != NULL; pp = &p->next)
873+ if (p->sec == sec)
874+ {
875+ /* Everything must go for SEC. */
876+ *pp = p->next;
877+ break;
878+ }
879+ }
880+
881+ switch (ELFNN_R_TYPE (rel->r_info))
882+ {
883+ case R_RISCV_GOT_HI20:
884+ case R_RISCV_TLS_GOT_HI20:
885+ case R_RISCV_TLS_GD_HI20:
886+ if (h != NULL)
887+ {
888+ if (h->got.refcount > 0)
889+ h->got.refcount--;
890+ }
891+ else
892+ {
893+ if (local_got_refcounts &&
894+ local_got_refcounts[r_symndx] > 0)
895+ local_got_refcounts[r_symndx]--;
896+ }
897+ break;
898+
899+ case R_RISCV_HI20:
900+ case R_RISCV_PCREL_HI20:
901+ case R_RISCV_COPY:
902+ case R_RISCV_JUMP_SLOT:
903+ case R_RISCV_RELATIVE:
904+ case R_RISCV_64:
905+ case R_RISCV_32:
906+ case R_RISCV_BRANCH:
907+ case R_RISCV_CALL:
908+ case R_RISCV_JAL:
Patrick Georgiaf473ed2015-07-17 23:35:54 +0200909+ case R_RISCV_RVC_BRANCH:
910+ case R_RISCV_RVC_JUMP:
Patrick Georgif0bbc952015-03-07 10:57:25 +0100911+ if (info->shared)
912+ break;
913+ /* Fall through. */
914+
915+ case R_RISCV_CALL_PLT:
916+ if (h != NULL)
917+ {
918+ if (h->plt.refcount > 0)
919+ h->plt.refcount--;
920+ }
921+ break;
922+
923+ default:
924+ break;
925+ }
926+ }
927+
928+ return TRUE;
929+}
930+
931+/* Adjust a symbol defined by a dynamic object and referenced by a
932+ regular object. The current definition is in some section of the
933+ dynamic object, but we're not including those sections. We have to
934+ change the definition to something the rest of the link can
935+ understand. */
936+
937+static bfd_boolean
938+riscv_elf_adjust_dynamic_symbol (struct bfd_link_info *info,
939+ struct elf_link_hash_entry *h)
940+{
941+ struct riscv_elf_link_hash_table *htab;
942+ struct riscv_elf_link_hash_entry * eh;
943+ struct riscv_elf_dyn_relocs *p;
944+ bfd *dynobj;
945+ asection *s;
946+
947+ htab = riscv_elf_hash_table (info);
948+ BFD_ASSERT (htab != NULL);
949+
950+ dynobj = htab->elf.dynobj;
951+
952+ /* Make sure we know what is going on here. */
953+ BFD_ASSERT (dynobj != NULL
954+ && (h->needs_plt
Patrick Georgiaf473ed2015-07-17 23:35:54 +0200955+ || h->type == STT_GNU_IFUNC
Patrick Georgif0bbc952015-03-07 10:57:25 +0100956+ || h->u.weakdef != NULL
957+ || (h->def_dynamic
958+ && h->ref_regular
959+ && !h->def_regular)));
960+
961+ /* If this is a function, put it in the procedure linkage table. We
962+ will fill in the contents of the procedure linkage table later
963+ (although we could actually do it here). */
Patrick Georgiaf473ed2015-07-17 23:35:54 +0200964+ if (h->type == STT_FUNC || h->type == STT_GNU_IFUNC || h->needs_plt)
Patrick Georgif0bbc952015-03-07 10:57:25 +0100965+ {
966+ if (h->plt.refcount <= 0
967+ || SYMBOL_CALLS_LOCAL (info, h)
968+ || (ELF_ST_VISIBILITY (h->other) != STV_DEFAULT
969+ && h->root.type == bfd_link_hash_undefweak))
970+ {
971+ /* This case can occur if we saw a R_RISCV_CALL_PLT reloc in an
972+ input file, but the symbol was never referred to by a dynamic
973+ object, or if all references were garbage collected. In such
974+ a case, we don't actually need to build a PLT entry. */
975+ h->plt.offset = (bfd_vma) -1;
976+ h->needs_plt = 0;
977+ }
978+
979+ return TRUE;
980+ }
981+ else
982+ h->plt.offset = (bfd_vma) -1;
983+
984+ /* If this is a weak symbol, and there is a real definition, the
985+ processor independent code will have arranged for us to see the
986+ real definition first, and we can just use the same value. */
987+ if (h->u.weakdef != NULL)
988+ {
989+ BFD_ASSERT (h->u.weakdef->root.type == bfd_link_hash_defined
990+ || h->u.weakdef->root.type == bfd_link_hash_defweak);
991+ h->root.u.def.section = h->u.weakdef->root.u.def.section;
992+ h->root.u.def.value = h->u.weakdef->root.u.def.value;
993+ return TRUE;
994+ }
995+
996+ /* This is a reference to a symbol defined by a dynamic object which
997+ is not a function. */
998+
999+ /* If we are creating a shared library, we must presume that the
1000+ only references to the symbol are via the global offset table.
1001+ For such cases we need not do anything here; the relocations will
1002+ be handled correctly by relocate_section. */
1003+ if (info->shared)
1004+ return TRUE;
1005+
1006+ /* If there are no references to this symbol that do not use the
1007+ GOT, we don't need to generate a copy reloc. */
1008+ if (!h->non_got_ref)
1009+ return TRUE;
1010+
1011+ /* If -z nocopyreloc was given, we won't generate them either. */
1012+ if (info->nocopyreloc)
1013+ {
1014+ h->non_got_ref = 0;
1015+ return TRUE;
1016+ }
1017+
1018+ eh = (struct riscv_elf_link_hash_entry *) h;
1019+ for (p = eh->dyn_relocs; p != NULL; p = p->next)
1020+ {
1021+ s = p->sec->output_section;
1022+ if (s != NULL && (s->flags & SEC_READONLY) != 0)
1023+ break;
1024+ }
1025+
1026+ /* If we didn't find any dynamic relocs in read-only sections, then
1027+ we'll be keeping the dynamic relocs and avoiding the copy reloc. */
1028+ if (p == NULL)
1029+ {
1030+ h->non_got_ref = 0;
1031+ return TRUE;
1032+ }
1033+
1034+ /* We must allocate the symbol in our .dynbss section, which will
1035+ become part of the .bss section of the executable. There will be
1036+ an entry for this symbol in the .dynsym section. The dynamic
1037+ object will contain position independent code, so all references
1038+ from the dynamic object to this symbol will go through the global
1039+ offset table. The dynamic linker will use the .dynsym entry to
1040+ determine the address it must put in the global offset table, so
1041+ both the dynamic object and the regular object will refer to the
1042+ same memory location for the variable. */
1043+
1044+ /* We must generate a R_RISCV_COPY reloc to tell the dynamic linker
1045+ to copy the initial value out of the dynamic object and into the
1046+ runtime process image. We need to remember the offset into the
1047+ .rel.bss section we are going to use. */
1048+ if ((h->root.u.def.section->flags & SEC_ALLOC) != 0 && h->size != 0)
1049+ {
1050+ htab->srelbss->size += sizeof (ElfNN_External_Rela);
1051+ h->needs_copy = 1;
1052+ }
1053+
1054+ if (eh->tls_type & ~GOT_NORMAL)
1055+ return _bfd_elf_adjust_dynamic_copy (h, htab->sdyntdata);
1056+
1057+ return _bfd_elf_adjust_dynamic_copy (h, htab->sdynbss);
1058+}
1059+
1060+/* Allocate space in .plt, .got and associated reloc sections for
1061+ dynamic relocs. */
1062+
1063+static bfd_boolean
1064+allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf)
1065+{
1066+ struct bfd_link_info *info;
1067+ struct riscv_elf_link_hash_table *htab;
1068+ struct riscv_elf_link_hash_entry *eh;
1069+ struct riscv_elf_dyn_relocs *p;
1070+
1071+ if (h->root.type == bfd_link_hash_indirect)
1072+ return TRUE;
1073+
1074+ info = (struct bfd_link_info *) inf;
1075+ htab = riscv_elf_hash_table (info);
1076+ BFD_ASSERT (htab != NULL);
1077+
1078+ if (htab->elf.dynamic_sections_created
1079+ && h->plt.refcount > 0)
1080+ {
1081+ /* Make sure this symbol is output as a dynamic symbol.
1082+ Undefined weak syms won't yet be marked as dynamic. */
1083+ if (h->dynindx == -1
1084+ && !h->forced_local)
1085+ {
1086+ if (! bfd_elf_link_record_dynamic_symbol (info, h))
1087+ return FALSE;
1088+ }
1089+
1090+ if (WILL_CALL_FINISH_DYNAMIC_SYMBOL (1, info->shared, h))
1091+ {
1092+ asection *s = htab->elf.splt;
1093+
1094+ if (s->size == 0)
1095+ s->size = PLT_HEADER_SIZE;
1096+
1097+ h->plt.offset = s->size;
1098+
1099+ /* Make room for this entry. */
1100+ s->size += PLT_ENTRY_SIZE;
1101+
1102+ /* We also need to make an entry in the .got.plt section. */
1103+ htab->elf.sgotplt->size += GOT_ENTRY_SIZE;
1104+
1105+ /* We also need to make an entry in the .rela.plt section. */
1106+ htab->elf.srelplt->size += sizeof (ElfNN_External_Rela);
1107+
1108+ /* If this symbol is not defined in a regular file, and we are
1109+ not generating a shared library, then set the symbol to this
1110+ location in the .plt. This is required to make function
1111+ pointers compare as equal between the normal executable and
1112+ the shared library. */
1113+ if (! info->shared
1114+ && !h->def_regular)
1115+ {
1116+ h->root.u.def.section = s;
1117+ h->root.u.def.value = h->plt.offset;
1118+ }
1119+ }
1120+ else
1121+ {
1122+ h->plt.offset = (bfd_vma) -1;
1123+ h->needs_plt = 0;
1124+ }
1125+ }
1126+ else
1127+ {
1128+ h->plt.offset = (bfd_vma) -1;
1129+ h->needs_plt = 0;
1130+ }
1131+
1132+ if (h->got.refcount > 0)
1133+ {
1134+ asection *s;
1135+ bfd_boolean dyn;
1136+ int tls_type = riscv_elf_hash_entry(h)->tls_type;
1137+
1138+ /* Make sure this symbol is output as a dynamic symbol.
1139+ Undefined weak syms won't yet be marked as dynamic. */
1140+ if (h->dynindx == -1
1141+ && !h->forced_local)
1142+ {
1143+ if (! bfd_elf_link_record_dynamic_symbol (info, h))
1144+ return FALSE;
1145+ }
1146+
1147+ s = htab->elf.sgot;
1148+ h->got.offset = s->size;
1149+ dyn = htab->elf.dynamic_sections_created;
1150+ if (tls_type & (GOT_TLS_GD | GOT_TLS_IE))
1151+ {
1152+ /* TLS_GD needs two dynamic relocs and two GOT slots. */
1153+ if (tls_type & GOT_TLS_GD)
1154+ {
1155+ s->size += 2 * RISCV_ELF_WORD_BYTES;
1156+ htab->elf.srelgot->size += 2 * sizeof (ElfNN_External_Rela);
1157+ }
1158+
1159+ /* TLS_IE needs one dynamic reloc and one GOT slot. */
1160+ if (tls_type & GOT_TLS_IE)
1161+ {
1162+ s->size += RISCV_ELF_WORD_BYTES;
1163+ htab->elf.srelgot->size += sizeof (ElfNN_External_Rela);
1164+ }
1165+ }
1166+ else
1167+ {
1168+ s->size += RISCV_ELF_WORD_BYTES;
1169+ if (WILL_CALL_FINISH_DYNAMIC_SYMBOL (dyn, info->shared, h))
1170+ htab->elf.srelgot->size += sizeof (ElfNN_External_Rela);
1171+ }
1172+ }
1173+ else
1174+ h->got.offset = (bfd_vma) -1;
1175+
1176+ eh = (struct riscv_elf_link_hash_entry *) h;
1177+ if (eh->dyn_relocs == NULL)
1178+ return TRUE;
1179+
1180+ /* In the shared -Bsymbolic case, discard space allocated for
1181+ dynamic pc-relative relocs against symbols which turn out to be
1182+ defined in regular objects. For the normal shared case, discard
1183+ space for pc-relative relocs that have become local due to symbol
1184+ visibility changes. */
1185+
1186+ if (info->shared)
1187+ {
1188+ if (SYMBOL_CALLS_LOCAL (info, h))
1189+ {
1190+ struct riscv_elf_dyn_relocs **pp;
1191+
1192+ for (pp = &eh->dyn_relocs; (p = *pp) != NULL; )
1193+ {
1194+ p->count -= p->pc_count;
1195+ p->pc_count = 0;
1196+ if (p->count == 0)
1197+ *pp = p->next;
1198+ else
1199+ pp = &p->next;
1200+ }
1201+ }
1202+
1203+ /* Also discard relocs on undefined weak syms with non-default
1204+ visibility. */
1205+ if (eh->dyn_relocs != NULL
1206+ && h->root.type == bfd_link_hash_undefweak)
1207+ {
1208+ if (ELF_ST_VISIBILITY (h->other) != STV_DEFAULT)
1209+ eh->dyn_relocs = NULL;
1210+
1211+ /* Make sure undefined weak symbols are output as a dynamic
1212+ symbol in PIEs. */
1213+ else if (h->dynindx == -1
1214+ && !h->forced_local)
1215+ {
1216+ if (! bfd_elf_link_record_dynamic_symbol (info, h))
1217+ return FALSE;
1218+ }
1219+ }
1220+ }
1221+ else
1222+ {
1223+ /* For the non-shared case, discard space for relocs against
1224+ symbols which turn out to need copy relocs or are not
1225+ dynamic. */
1226+
1227+ if (!h->non_got_ref
1228+ && ((h->def_dynamic
1229+ && !h->def_regular)
1230+ || (htab->elf.dynamic_sections_created
1231+ && (h->root.type == bfd_link_hash_undefweak
1232+ || h->root.type == bfd_link_hash_undefined))))
1233+ {
1234+ /* Make sure this symbol is output as a dynamic symbol.
1235+ Undefined weak syms won't yet be marked as dynamic. */
1236+ if (h->dynindx == -1
1237+ && !h->forced_local)
1238+ {
1239+ if (! bfd_elf_link_record_dynamic_symbol (info, h))
1240+ return FALSE;
1241+ }
1242+
1243+ /* If that succeeded, we know we'll be keeping all the
1244+ relocs. */
1245+ if (h->dynindx != -1)
1246+ goto keep;
1247+ }
1248+
1249+ eh->dyn_relocs = NULL;
1250+
1251+ keep: ;
1252+ }
1253+
1254+ /* Finally, allocate space. */
1255+ for (p = eh->dyn_relocs; p != NULL; p = p->next)
1256+ {
1257+ asection *sreloc = elf_section_data (p->sec)->sreloc;
1258+ sreloc->size += p->count * sizeof (ElfNN_External_Rela);
1259+ }
1260+
1261+ return TRUE;
1262+}
1263+
1264+/* Find any dynamic relocs that apply to read-only sections. */
1265+
1266+static bfd_boolean
1267+readonly_dynrelocs (struct elf_link_hash_entry *h, void *inf)
1268+{
1269+ struct riscv_elf_link_hash_entry *eh;
1270+ struct riscv_elf_dyn_relocs *p;
1271+
1272+ eh = (struct riscv_elf_link_hash_entry *) h;
1273+ for (p = eh->dyn_relocs; p != NULL; p = p->next)
1274+ {
1275+ asection *s = p->sec->output_section;
1276+
1277+ if (s != NULL && (s->flags & SEC_READONLY) != 0)
1278+ {
1279+ ((struct bfd_link_info *) inf)->flags |= DF_TEXTREL;
1280+
1281+ /* Short-circuit the traversal. */
1282+ return FALSE;
1283+ }
1284+ }
1285+ return TRUE;
1286+}
1287+
1288+static bfd_boolean
1289+riscv_elf_size_dynamic_sections (bfd *output_bfd, struct bfd_link_info *info)
1290+{
1291+ struct riscv_elf_link_hash_table *htab;
1292+ bfd *dynobj;
1293+ asection *s;
1294+ bfd *ibfd;
1295+
1296+ htab = riscv_elf_hash_table (info);
1297+ BFD_ASSERT (htab != NULL);
1298+ dynobj = htab->elf.dynobj;
1299+ BFD_ASSERT (dynobj != NULL);
1300+
1301+ if (elf_hash_table (info)->dynamic_sections_created)
1302+ {
1303+ /* Set the contents of the .interp section to the interpreter. */
1304+ if (info->executable)
1305+ {
1306+ s = bfd_get_linker_section (dynobj, ".interp");
1307+ BFD_ASSERT (s != NULL);
1308+ s->size = strlen (ELFNN_DYNAMIC_INTERPRETER) + 1;
1309+ s->contents = (unsigned char *) ELFNN_DYNAMIC_INTERPRETER;
1310+ }
1311+ }
1312+
1313+ /* Set up .got offsets for local syms, and space for local dynamic
1314+ relocs. */
1315+ for (ibfd = info->input_bfds; ibfd != NULL; ibfd = ibfd->link.next)
1316+ {
1317+ bfd_signed_vma *local_got;
1318+ bfd_signed_vma *end_local_got;
1319+ char *local_tls_type;
1320+ bfd_size_type locsymcount;
1321+ Elf_Internal_Shdr *symtab_hdr;
1322+ asection *srel;
1323+
1324+ if (! is_riscv_elf (ibfd))
1325+ continue;
1326+
1327+ for (s = ibfd->sections; s != NULL; s = s->next)
1328+ {
1329+ struct riscv_elf_dyn_relocs *p;
1330+
1331+ for (p = elf_section_data (s)->local_dynrel; p != NULL; p = p->next)
1332+ {
1333+ if (!bfd_is_abs_section (p->sec)
1334+ && bfd_is_abs_section (p->sec->output_section))
1335+ {
1336+ /* Input section has been discarded, either because
1337+ it is a copy of a linkonce section or due to
1338+ linker script /DISCARD/, so we'll be discarding
1339+ the relocs too. */
1340+ }
1341+ else if (p->count != 0)
1342+ {
1343+ srel = elf_section_data (p->sec)->sreloc;
1344+ srel->size += p->count * sizeof (ElfNN_External_Rela);
1345+ if ((p->sec->output_section->flags & SEC_READONLY) != 0)
1346+ info->flags |= DF_TEXTREL;
1347+ }
1348+ }
1349+ }
1350+
1351+ local_got = elf_local_got_refcounts (ibfd);
1352+ if (!local_got)
1353+ continue;
1354+
1355+ symtab_hdr = &elf_symtab_hdr (ibfd);
1356+ locsymcount = symtab_hdr->sh_info;
1357+ end_local_got = local_got + locsymcount;
1358+ local_tls_type = _bfd_riscv_elf_local_got_tls_type (ibfd);
1359+ s = htab->elf.sgot;
1360+ srel = htab->elf.srelgot;
1361+ for (; local_got < end_local_got; ++local_got, ++local_tls_type)
1362+ {
1363+ if (*local_got > 0)
1364+ {
1365+ *local_got = s->size;
1366+ s->size += RISCV_ELF_WORD_BYTES;
1367+ if (*local_tls_type & GOT_TLS_GD)
1368+ s->size += RISCV_ELF_WORD_BYTES;
1369+ if (info->shared
1370+ || (*local_tls_type & (GOT_TLS_GD | GOT_TLS_IE)))
1371+ srel->size += sizeof (ElfNN_External_Rela);
1372+ }
1373+ else
1374+ *local_got = (bfd_vma) -1;
1375+ }
1376+ }
1377+
1378+ /* Allocate global sym .plt and .got entries, and space for global
1379+ sym dynamic relocs. */
1380+ elf_link_hash_traverse (&htab->elf, allocate_dynrelocs, info);
1381+
1382+ if (htab->elf.sgotplt)
1383+ {
1384+ struct elf_link_hash_entry *got;
1385+ got = elf_link_hash_lookup (elf_hash_table (info),
1386+ "_GLOBAL_OFFSET_TABLE_",
1387+ FALSE, FALSE, FALSE);
1388+
1389+ /* Don't allocate .got.plt section if there are no GOT nor PLT
1390+ entries and there is no refeence to _GLOBAL_OFFSET_TABLE_. */
1391+ if ((got == NULL
1392+ || !got->ref_regular_nonweak)
1393+ && (htab->elf.sgotplt->size == GOTPLT_HEADER_SIZE)
1394+ && (htab->elf.splt == NULL
1395+ || htab->elf.splt->size == 0)
1396+ && (htab->elf.sgot == NULL
1397+ || (htab->elf.sgot->size
1398+ == get_elf_backend_data (output_bfd)->got_header_size)))
1399+ htab->elf.sgotplt->size = 0;
1400+ }
1401+
1402+ /* The check_relocs and adjust_dynamic_symbol entry points have
1403+ determined the sizes of the various dynamic sections. Allocate
1404+ memory for them. */
1405+ for (s = dynobj->sections; s != NULL; s = s->next)
1406+ {
1407+ if ((s->flags & SEC_LINKER_CREATED) == 0)
1408+ continue;
1409+
1410+ if (s == htab->elf.splt
1411+ || s == htab->elf.sgot
1412+ || s == htab->elf.sgotplt
1413+ || s == htab->sdynbss)
1414+ {
1415+ /* Strip this section if we don't need it; see the
1416+ comment below. */
1417+ }
1418+ else if (strncmp (s->name, ".rela", 5) == 0)
1419+ {
1420+ if (s->size != 0)
1421+ {
1422+ /* We use the reloc_count field as a counter if we need
1423+ to copy relocs into the output file. */
1424+ s->reloc_count = 0;
1425+ }
1426+ }
1427+ else
1428+ {
1429+ /* It's not one of our sections. */
1430+ continue;
1431+ }
1432+
1433+ if (s->size == 0)
1434+ {
1435+ /* If we don't need this section, strip it from the
1436+ output file. This is mostly to handle .rela.bss and
1437+ .rela.plt. We must create both sections in
1438+ create_dynamic_sections, because they must be created
1439+ before the linker maps input sections to output
1440+ sections. The linker does that before
1441+ adjust_dynamic_symbol is called, and it is that
1442+ function which decides whether anything needs to go
1443+ into these sections. */
1444+ s->flags |= SEC_EXCLUDE;
1445+ continue;
1446+ }
1447+
1448+ if ((s->flags & SEC_HAS_CONTENTS) == 0)
1449+ continue;
1450+
1451+ /* Allocate memory for the section contents. Zero the memory
1452+ for the benefit of .rela.plt, which has 4 unused entries
1453+ at the beginning, and we don't want garbage. */
1454+ s->contents = (bfd_byte *) bfd_zalloc (dynobj, s->size);
1455+ if (s->contents == NULL)
1456+ return FALSE;
1457+ }
1458+
1459+ if (elf_hash_table (info)->dynamic_sections_created)
1460+ {
1461+ /* Add some entries to the .dynamic section. We fill in the
1462+ values later, in riscv_elf_finish_dynamic_sections, but we
1463+ must add the entries now so that we get the correct size for
1464+ the .dynamic section. The DT_DEBUG entry is filled in by the
1465+ dynamic linker and used by the debugger. */
1466+#define add_dynamic_entry(TAG, VAL) \
1467+ _bfd_elf_add_dynamic_entry (info, TAG, VAL)
1468+
1469+ if (info->executable)
1470+ {
1471+ if (!add_dynamic_entry (DT_DEBUG, 0))
1472+ return FALSE;
1473+ }
1474+
1475+ if (htab->elf.srelplt->size != 0)
1476+ {
1477+ if (!add_dynamic_entry (DT_PLTGOT, 0)
1478+ || !add_dynamic_entry (DT_PLTRELSZ, 0)
1479+ || !add_dynamic_entry (DT_PLTREL, DT_RELA)
1480+ || !add_dynamic_entry (DT_JMPREL, 0))
1481+ return FALSE;
1482+ }
1483+
1484+ if (!add_dynamic_entry (DT_RELA, 0)
1485+ || !add_dynamic_entry (DT_RELASZ, 0)
1486+ || !add_dynamic_entry (DT_RELAENT, sizeof (ElfNN_External_Rela)))
1487+ return FALSE;
1488+
1489+ /* If any dynamic relocs apply to a read-only section,
1490+ then we need a DT_TEXTREL entry. */
1491+ if ((info->flags & DF_TEXTREL) == 0)
1492+ elf_link_hash_traverse (&htab->elf, readonly_dynrelocs, info);
1493+
1494+ if (info->flags & DF_TEXTREL)
1495+ {
1496+ if (!add_dynamic_entry (DT_TEXTREL, 0))
1497+ return FALSE;
1498+ }
1499+ }
1500+#undef add_dynamic_entry
1501+
1502+ return TRUE;
1503+}
1504+
1505+#define TP_OFFSET 0
1506+#define DTP_OFFSET 0x800
1507+
1508+/* Return the relocation value for a TLS dtp-relative reloc. */
1509+
1510+static bfd_vma
1511+dtpoff (struct bfd_link_info *info, bfd_vma address)
1512+{
1513+ /* If tls_sec is NULL, we should have signalled an error already. */
1514+ if (elf_hash_table (info)->tls_sec == NULL)
1515+ return 0;
1516+ return address - elf_hash_table (info)->tls_sec->vma - DTP_OFFSET;
1517+}
1518+
1519+/* Return the relocation value for a static TLS tp-relative relocation. */
1520+
1521+static bfd_vma
1522+tpoff (struct bfd_link_info *info, bfd_vma address)
1523+{
1524+ /* If tls_sec is NULL, we should have signalled an error already. */
1525+ if (elf_hash_table (info)->tls_sec == NULL)
1526+ return 0;
1527+ return address - elf_hash_table (info)->tls_sec->vma - TP_OFFSET;
1528+}
1529+
1530+/* Return the global pointer's value, or 0 if it is not in use. */
1531+
1532+static bfd_vma
1533+riscv_global_pointer_value (struct bfd_link_info *info)
1534+{
1535+ struct bfd_link_hash_entry *h;
1536+
1537+ h = bfd_link_hash_lookup (info->hash, "_gp", FALSE, FALSE, TRUE);
1538+ if (h == NULL || h->type != bfd_link_hash_defined)
1539+ return 0;
1540+
1541+ return h->u.def.value + sec_addr (h->u.def.section);
1542+}
1543+
1544+/* Emplace a static relocation. */
1545+
1546+static bfd_reloc_status_type
1547+perform_relocation (const reloc_howto_type *howto,
1548+ const Elf_Internal_Rela *rel,
1549+ bfd_vma value,
1550+ asection *input_section,
1551+ bfd *input_bfd,
1552+ bfd_byte *contents)
1553+{
1554+ if (howto->pc_relative)
1555+ value -= sec_addr (input_section) + rel->r_offset;
1556+ value += rel->r_addend;
1557+
1558+ switch (ELFNN_R_TYPE (rel->r_info))
1559+ {
1560+ case R_RISCV_HI20:
1561+ case R_RISCV_TPREL_HI20:
1562+ case R_RISCV_PCREL_HI20:
1563+ case R_RISCV_GOT_HI20:
1564+ case R_RISCV_TLS_GOT_HI20:
1565+ case R_RISCV_TLS_GD_HI20:
1566+ value = ENCODE_UTYPE_IMM (RISCV_CONST_HIGH_PART (value));
1567+ break;
1568+
1569+ case R_RISCV_LO12_I:
1570+ case R_RISCV_TPREL_LO12_I:
1571+ case R_RISCV_PCREL_LO12_I:
1572+ value = ENCODE_ITYPE_IMM (value);
1573+ break;
1574+
1575+ case R_RISCV_LO12_S:
1576+ case R_RISCV_TPREL_LO12_S:
1577+ case R_RISCV_PCREL_LO12_S:
1578+ value = ENCODE_STYPE_IMM (value);
1579+ break;
1580+
1581+ case R_RISCV_CALL:
1582+ case R_RISCV_CALL_PLT:
1583+ if (!VALID_UTYPE_IMM (RISCV_CONST_HIGH_PART (value)))
1584+ return bfd_reloc_overflow;
1585+ value = ENCODE_UTYPE_IMM (RISCV_CONST_HIGH_PART (value))
1586+ | (ENCODE_ITYPE_IMM (value) << 32);
1587+ break;
1588+
1589+ case R_RISCV_JAL:
1590+ if (!VALID_UJTYPE_IMM (value))
1591+ return bfd_reloc_overflow;
1592+ value = ENCODE_UJTYPE_IMM (value);
1593+ break;
1594+
1595+ case R_RISCV_BRANCH:
1596+ if (!VALID_SBTYPE_IMM (value))
1597+ return bfd_reloc_overflow;
1598+ value = ENCODE_SBTYPE_IMM (value);
1599+ break;
1600+
Patrick Georgiaf473ed2015-07-17 23:35:54 +02001601+ case R_RISCV_RVC_BRANCH:
1602+ if (!VALID_RVC_B_IMM (value))
1603+ return bfd_reloc_overflow;
1604+ value = ENCODE_RVC_B_IMM (value);
1605+ break;
1606+
1607+ case R_RISCV_RVC_JUMP:
1608+ if (!VALID_RVC_J_IMM (value))
1609+ return bfd_reloc_overflow;
1610+ value = ENCODE_RVC_J_IMM (value);
1611+ break;
1612+
Patrick Georgif0bbc952015-03-07 10:57:25 +01001613+ case R_RISCV_32:
1614+ case R_RISCV_64:
1615+ case R_RISCV_ADD8:
1616+ case R_RISCV_ADD16:
1617+ case R_RISCV_ADD32:
1618+ case R_RISCV_ADD64:
1619+ case R_RISCV_SUB8:
1620+ case R_RISCV_SUB16:
1621+ case R_RISCV_SUB32:
1622+ case R_RISCV_SUB64:
1623+ case R_RISCV_TLS_DTPREL32:
1624+ case R_RISCV_TLS_DTPREL64:
1625+ break;
1626+
1627+ default:
1628+ return bfd_reloc_notsupported;
1629+ }
1630+
1631+ bfd_vma word = bfd_get (howto->bitsize, input_bfd, contents + rel->r_offset);
1632+ word = (word & ~howto->dst_mask) | (value & howto->dst_mask);
1633+ bfd_put (howto->bitsize, input_bfd, word, contents + rel->r_offset);
1634+
1635+ return bfd_reloc_ok;
1636+}
1637+
1638+/* Remember all PC-relative high-part relocs we've encountered to help us
1639+ later resolve the corresponding low-part relocs. */
1640+
1641+typedef struct {
1642+ bfd_vma address;
1643+ bfd_vma value;
1644+} riscv_pcrel_hi_reloc;
1645+
1646+typedef struct riscv_pcrel_lo_reloc {
1647+ asection *input_section;
1648+ struct bfd_link_info *info;
1649+ reloc_howto_type *howto;
1650+ const Elf_Internal_Rela *reloc;
1651+ bfd_vma addr;
1652+ const char *name;
1653+ bfd_byte *contents;
1654+ struct riscv_pcrel_lo_reloc *next;
1655+} riscv_pcrel_lo_reloc;
1656+
1657+typedef struct {
1658+ htab_t hi_relocs;
1659+ riscv_pcrel_lo_reloc *lo_relocs;
1660+} riscv_pcrel_relocs;
1661+
1662+static hashval_t
1663+riscv_pcrel_reloc_hash (const void *entry)
1664+{
1665+ const riscv_pcrel_hi_reloc *e = entry;
1666+ return (hashval_t)(e->address >> 2);
1667+}
1668+
1669+static bfd_boolean
1670+riscv_pcrel_reloc_eq (const void *entry1, const void *entry2)
1671+{
1672+ const riscv_pcrel_hi_reloc *e1 = entry1, *e2 = entry2;
1673+ return e1->address == e2->address;
1674+}
1675+
1676+static bfd_boolean
1677+riscv_init_pcrel_relocs (riscv_pcrel_relocs *p)
1678+{
1679+
1680+ p->lo_relocs = NULL;
1681+ p->hi_relocs = htab_create (1024, riscv_pcrel_reloc_hash,
1682+ riscv_pcrel_reloc_eq, free);
1683+ return p->hi_relocs != NULL;
1684+}
1685+
1686+static void
1687+riscv_free_pcrel_relocs (riscv_pcrel_relocs *p)
1688+{
1689+ riscv_pcrel_lo_reloc *cur = p->lo_relocs;
1690+ while (cur != NULL)
1691+ {
1692+ riscv_pcrel_lo_reloc *next = cur->next;
1693+ free (cur);
1694+ cur = next;
1695+ }
1696+
1697+ htab_delete (p->hi_relocs);
1698+}
1699+
1700+static bfd_boolean
1701+riscv_record_pcrel_hi_reloc (riscv_pcrel_relocs *p, bfd_vma addr, bfd_vma value)
1702+{
1703+ riscv_pcrel_hi_reloc entry = {addr, value - addr};
1704+ riscv_pcrel_hi_reloc **slot =
1705+ (riscv_pcrel_hi_reloc **) htab_find_slot (p->hi_relocs, &entry, INSERT);
1706+ BFD_ASSERT (*slot == NULL);
1707+ *slot = (riscv_pcrel_hi_reloc *) bfd_malloc (sizeof (riscv_pcrel_hi_reloc));
1708+ if (*slot == NULL)
1709+ return FALSE;
1710+ **slot = entry;
1711+ return TRUE;
1712+}
1713+
1714+static bfd_boolean
1715+riscv_record_pcrel_lo_reloc (riscv_pcrel_relocs *p,
1716+ asection *input_section,
1717+ struct bfd_link_info *info,
1718+ reloc_howto_type *howto,
1719+ const Elf_Internal_Rela *reloc,
1720+ bfd_vma addr,
1721+ const char *name,
1722+ bfd_byte *contents)
1723+{
1724+ riscv_pcrel_lo_reloc *entry;
1725+ entry = (riscv_pcrel_lo_reloc *) bfd_malloc (sizeof (riscv_pcrel_lo_reloc));
1726+ if (entry == NULL)
1727+ return FALSE;
1728+ *entry = (riscv_pcrel_lo_reloc) {input_section, info, howto, reloc, addr,
1729+ name, contents, p->lo_relocs};
1730+ p->lo_relocs = entry;
1731+ return TRUE;
1732+}
1733+
1734+static bfd_boolean
1735+riscv_resolve_pcrel_lo_relocs (riscv_pcrel_relocs *p)
1736+{
1737+ riscv_pcrel_lo_reloc *r;
1738+ for (r = p->lo_relocs; r != NULL; r = r->next)
1739+ {
1740+ bfd *input_bfd = r->input_section->owner;
1741+ riscv_pcrel_hi_reloc search = {r->addr, 0};
1742+ riscv_pcrel_hi_reloc *entry = htab_find (p->hi_relocs, &search);
1743+ if (entry == NULL)
1744+ return ((*r->info->callbacks->reloc_overflow)
1745+ (r->info, NULL, r->name, r->howto->name, (bfd_vma) 0,
1746+ input_bfd, r->input_section, r->reloc->r_offset));
1747+
1748+ perform_relocation (r->howto, r->reloc, entry->value, r->input_section,
1749+ input_bfd, r->contents);
1750+ }
1751+
1752+ return TRUE;
1753+}
1754+
1755+/* Relocate a RISC-V ELF section.
1756+
1757+ The RELOCATE_SECTION function is called by the new ELF backend linker
1758+ to handle the relocations for a section.
1759+
1760+ The relocs are always passed as Rela structures.
1761+
1762+ This function is responsible for adjusting the section contents as
1763+ necessary, and (if generating a relocatable output file) adjusting
1764+ the reloc addend as necessary.
1765+
1766+ This function does not have to worry about setting the reloc
1767+ address or the reloc symbol index.
1768+
1769+ LOCAL_SYMS is a pointer to the swapped in local symbols.
1770+
1771+ LOCAL_SECTIONS is an array giving the section in the input file
1772+ corresponding to the st_shndx field of each local symbol.
1773+
1774+ The global hash table entry for the global symbols can be found
1775+ via elf_sym_hashes (input_bfd).
1776+
1777+ When generating relocatable output, this function must handle
1778+ STB_LOCAL/STT_SECTION symbols specially. The output symbol is
1779+ going to be the section symbol corresponding to the output
1780+ section, which means that the addend must be adjusted
1781+ accordingly. */
1782+
1783+static bfd_boolean
1784+riscv_elf_relocate_section (bfd *output_bfd, struct bfd_link_info *info,
1785+ bfd *input_bfd, asection *input_section,
1786+ bfd_byte *contents, Elf_Internal_Rela *relocs,
1787+ Elf_Internal_Sym *local_syms,
1788+ asection **local_sections)
1789+{
1790+ Elf_Internal_Rela *rel;
1791+ Elf_Internal_Rela *relend;
1792+ riscv_pcrel_relocs pcrel_relocs;
1793+ bfd_boolean ret = FALSE;
1794+ asection *sreloc = elf_section_data (input_section)->sreloc;
1795+ struct riscv_elf_link_hash_table *htab = riscv_elf_hash_table (info);
1796+ Elf_Internal_Shdr *symtab_hdr = &elf_symtab_hdr (input_bfd);
1797+ struct elf_link_hash_entry **sym_hashes = elf_sym_hashes (input_bfd);
1798+ bfd_vma *local_got_offsets = elf_local_got_offsets (input_bfd);
1799+
1800+ if (!riscv_init_pcrel_relocs (&pcrel_relocs))
1801+ return FALSE;
1802+
1803+ relend = relocs + input_section->reloc_count;
1804+ for (rel = relocs; rel < relend; rel++)
1805+ {
1806+ unsigned long r_symndx;
1807+ struct elf_link_hash_entry *h;
1808+ Elf_Internal_Sym *sym;
1809+ asection *sec;
1810+ bfd_vma relocation;
1811+ bfd_reloc_status_type r = bfd_reloc_ok;
1812+ const char *name;
1813+ bfd_vma off, ie_off;
1814+ bfd_boolean unresolved_reloc, is_ie = FALSE;
1815+ bfd_vma pc = sec_addr (input_section) + rel->r_offset;
1816+ int r_type = ELFNN_R_TYPE (rel->r_info), tls_type;
1817+ reloc_howto_type *howto = riscv_elf_rtype_to_howto (r_type);
1818+ const char *msg = NULL;
1819+
1820+ if (r_type == R_RISCV_GNU_VTINHERIT || r_type == R_RISCV_GNU_VTENTRY)
1821+ continue;
1822+
1823+ /* This is a final link. */
1824+ r_symndx = ELFNN_R_SYM (rel->r_info);
1825+ h = NULL;
1826+ sym = NULL;
1827+ sec = NULL;
1828+ unresolved_reloc = FALSE;
1829+ if (r_symndx < symtab_hdr->sh_info)
1830+ {
1831+ sym = local_syms + r_symndx;
1832+ sec = local_sections[r_symndx];
1833+ relocation = _bfd_elf_rela_local_sym (output_bfd, sym, &sec, rel);
1834+ }
1835+ else
1836+ {
1837+ bfd_boolean warned, ignored;
1838+
1839+ RELOC_FOR_GLOBAL_SYMBOL (info, input_bfd, input_section, rel,
1840+ r_symndx, symtab_hdr, sym_hashes,
1841+ h, sec, relocation,
1842+ unresolved_reloc, warned, ignored);
1843+ if (warned)
1844+ {
1845+ /* To avoid generating warning messages about truncated
1846+ relocations, set the relocation's address to be the same as
1847+ the start of this section. */
1848+ if (input_section->output_section != NULL)
1849+ relocation = input_section->output_section->vma;
1850+ else
1851+ relocation = 0;
1852+ }
1853+ }
1854+
1855+ if (sec != NULL && discarded_section (sec))
1856+ RELOC_AGAINST_DISCARDED_SECTION (info, input_bfd, input_section,
1857+ rel, 1, relend, howto, 0, contents);
1858+
1859+ if (info->relocatable)
1860+ continue;
1861+
1862+ if (h != NULL)
1863+ name = h->root.root.string;
1864+ else
1865+ {
1866+ name = (bfd_elf_string_from_elf_section
1867+ (input_bfd, symtab_hdr->sh_link, sym->st_name));
1868+ if (name == NULL || *name == '\0')
1869+ name = bfd_section_name (input_bfd, sec);
1870+ }
1871+
1872+ switch (r_type)
1873+ {
1874+ case R_RISCV_NONE:
1875+ case R_RISCV_TPREL_ADD:
1876+ case R_RISCV_COPY:
1877+ case R_RISCV_JUMP_SLOT:
1878+ case R_RISCV_RELATIVE:
1879+ /* These require nothing of us at all. */
1880+ continue;
1881+
1882+ case R_RISCV_BRANCH:
Patrick Georgiaf473ed2015-07-17 23:35:54 +02001883+ case R_RISCV_RVC_BRANCH:
Patrick Georgif0bbc952015-03-07 10:57:25 +01001884+ case R_RISCV_HI20:
1885+ /* These require no special handling beyond perform_relocation. */
1886+ break;
1887+
1888+ case R_RISCV_GOT_HI20:
1889+ if (h != NULL)
1890+ {
1891+ bfd_boolean dyn;
1892+
1893+ off = h->got.offset;
1894+ BFD_ASSERT (off != (bfd_vma) -1);
1895+ dyn = elf_hash_table (info)->dynamic_sections_created;
1896+
1897+ if (! WILL_CALL_FINISH_DYNAMIC_SYMBOL (dyn, info->shared, h)
1898+ || (info->shared
1899+ && SYMBOL_REFERENCES_LOCAL (info, h)))
1900+ {
1901+ /* This is actually a static link, or it is a
1902+ -Bsymbolic link and the symbol is defined
1903+ locally, or the symbol was forced to be local
1904+ because of a version file. We must initialize
1905+ this entry in the global offset table. Since the
1906+ offset must always be a multiple of the word size,
1907+ we use the least significant bit to record whether
1908+ we have initialized it already.
1909+
1910+ When doing a dynamic link, we create a .rela.got
1911+ relocation entry to initialize the value. This
1912+ is done in the finish_dynamic_symbol routine. */
1913+ if ((off & 1) != 0)
1914+ off &= ~1;
1915+ else
1916+ {
1917+ bfd_put_NN (output_bfd, relocation,
1918+ htab->elf.sgot->contents + off);
1919+ h->got.offset |= 1;
1920+ }
1921+ }
1922+ else
1923+ unresolved_reloc = FALSE;
1924+ }
1925+ else
1926+ {
1927+ BFD_ASSERT (local_got_offsets != NULL
1928+ && local_got_offsets[r_symndx] != (bfd_vma) -1);
1929+
1930+ off = local_got_offsets[r_symndx];
1931+
1932+ /* The offset must always be a multiple of 8 on 64-bit.
1933+ We use the least significant bit to record
1934+ whether we have already processed this entry. */
1935+ if ((off & 1) != 0)
1936+ off &= ~1;
1937+ else
1938+ {
1939+ if (info->shared)
1940+ {
1941+ asection *s;
1942+ Elf_Internal_Rela outrel;
1943+
1944+ /* We need to generate a R_RISCV_RELATIVE reloc
1945+ for the dynamic linker. */
1946+ s = htab->elf.srelgot;
1947+ BFD_ASSERT (s != NULL);
1948+
1949+ outrel.r_offset = sec_addr (htab->elf.sgot) + off;
1950+ outrel.r_info =
1951+ ELFNN_R_INFO (0, R_RISCV_RELATIVE);
1952+ outrel.r_addend = relocation;
1953+ relocation = 0;
1954+ riscv_elf_append_rela (output_bfd, s, &outrel);
1955+ }
1956+
1957+ bfd_put_NN (output_bfd, relocation,
1958+ htab->elf.sgot->contents + off);
1959+ local_got_offsets[r_symndx] |= 1;
1960+ }
1961+ }
1962+ relocation = sec_addr (htab->elf.sgot) + off;
1963+ if (!riscv_record_pcrel_hi_reloc (&pcrel_relocs, pc, relocation))
1964+ r = bfd_reloc_overflow;
1965+ break;
1966+
1967+ case R_RISCV_ADD8:
1968+ case R_RISCV_ADD16:
1969+ case R_RISCV_ADD32:
1970+ case R_RISCV_ADD64:
1971+ {
1972+ bfd_vma old_value = bfd_get (howto->bitsize, input_bfd,
1973+ contents + rel->r_offset);
1974+ relocation = old_value + relocation;
1975+ }
1976+ break;
1977+
1978+ case R_RISCV_SUB8:
1979+ case R_RISCV_SUB16:
1980+ case R_RISCV_SUB32:
1981+ case R_RISCV_SUB64:
1982+ {
1983+ bfd_vma old_value = bfd_get (howto->bitsize, input_bfd,
1984+ contents + rel->r_offset);
1985+ relocation = old_value - relocation;
1986+ }
1987+ break;
1988+
1989+ case R_RISCV_CALL_PLT:
1990+ case R_RISCV_CALL:
1991+ case R_RISCV_JAL:
Patrick Georgiaf473ed2015-07-17 23:35:54 +02001992+ case R_RISCV_RVC_JUMP:
Patrick Georgif0bbc952015-03-07 10:57:25 +01001993+ if (info->shared && h != NULL && h->plt.offset != MINUS_ONE)
1994+ {
1995+ /* Refer to the PLT entry. */
1996+ relocation = sec_addr (htab->elf.splt) + h->plt.offset;
1997+ unresolved_reloc = FALSE;
1998+ }
1999+ break;
2000+
2001+ case R_RISCV_TPREL_HI20:
2002+ relocation = tpoff (info, relocation);
2003+ break;
2004+
2005+ case R_RISCV_TPREL_LO12_I:
2006+ case R_RISCV_TPREL_LO12_S:
2007+ relocation = tpoff (info, relocation);
2008+ if (VALID_ITYPE_IMM (relocation + rel->r_addend))
2009+ {
2010+ /* We can use tp as the base register. */
2011+ bfd_vma insn = bfd_get_32 (input_bfd, contents + rel->r_offset);
2012+ insn &= ~(OP_MASK_RS1 << OP_SH_RS1);
2013+ insn |= X_TP << OP_SH_RS1;
2014+ bfd_put_32 (input_bfd, insn, contents + rel->r_offset);
2015+ }
2016+ break;
2017+
2018+ case R_RISCV_LO12_I:
2019+ case R_RISCV_LO12_S:
2020+ {
2021+ bfd_vma gp = riscv_global_pointer_value (info);
2022+ bfd_boolean x0_base = VALID_ITYPE_IMM (relocation + rel->r_addend);
2023+ if (x0_base || VALID_ITYPE_IMM (relocation + rel->r_addend - gp))
2024+ {
2025+ /* We can use x0 or gp as the base register. */
2026+ bfd_vma insn = bfd_get_32 (input_bfd, contents + rel->r_offset);
2027+ insn &= ~(OP_MASK_RS1 << OP_SH_RS1);
2028+ if (!x0_base)
2029+ {
2030+ rel->r_addend -= gp;
2031+ insn |= X_GP << OP_SH_RS1;
2032+ }
2033+ bfd_put_32 (input_bfd, insn, contents + rel->r_offset);
2034+ }
2035+ break;
2036+ }
2037+
2038+ case R_RISCV_PCREL_HI20:
2039+ if (!riscv_record_pcrel_hi_reloc (&pcrel_relocs, pc,
2040+ relocation + rel->r_addend))
2041+ r = bfd_reloc_overflow;
2042+ break;
2043+
2044+ case R_RISCV_PCREL_LO12_I:
2045+ case R_RISCV_PCREL_LO12_S:
2046+ if (riscv_record_pcrel_lo_reloc (&pcrel_relocs, input_section, info,
2047+ howto, rel, relocation, name,
2048+ contents))
2049+ continue;
2050+ r = bfd_reloc_overflow;
2051+ break;
2052+
2053+ case R_RISCV_TLS_DTPREL32:
2054+ case R_RISCV_TLS_DTPREL64:
2055+ relocation = dtpoff (info, relocation);
2056+ break;
2057+
2058+ case R_RISCV_32:
2059+ case R_RISCV_64:
2060+ if ((input_section->flags & SEC_ALLOC) == 0)
2061+ break;
2062+
2063+ if ((info->shared
2064+ && (h == NULL
2065+ || ELF_ST_VISIBILITY (h->other) == STV_DEFAULT
2066+ || h->root.type != bfd_link_hash_undefweak)
2067+ && (! howto->pc_relative
2068+ || !SYMBOL_CALLS_LOCAL (info, h)))
2069+ || (!info->shared
2070+ && h != NULL
2071+ && h->dynindx != -1
2072+ && !h->non_got_ref
2073+ && ((h->def_dynamic
2074+ && !h->def_regular)
2075+ || h->root.type == bfd_link_hash_undefweak
2076+ || h->root.type == bfd_link_hash_undefined)))
2077+ {
2078+ Elf_Internal_Rela outrel;
2079+ bfd_boolean skip_static_relocation, skip_dynamic_relocation;
2080+
2081+ /* When generating a shared object, these relocations
2082+ are copied into the output file to be resolved at run
2083+ time. */
2084+
2085+ outrel.r_offset =
2086+ _bfd_elf_section_offset (output_bfd, info, input_section,
2087+ rel->r_offset);
2088+ skip_static_relocation = outrel.r_offset != (bfd_vma) -2;
2089+ skip_dynamic_relocation = outrel.r_offset >= (bfd_vma) -2;
2090+ outrel.r_offset += sec_addr (input_section);
2091+
2092+ if (skip_dynamic_relocation)
2093+ memset (&outrel, 0, sizeof outrel);
2094+ else if (h != NULL && h->dynindx != -1
2095+ && !(info->shared
2096+ && SYMBOLIC_BIND (info, h)
2097+ && h->def_regular))
2098+ {
2099+ outrel.r_info = ELFNN_R_INFO (h->dynindx, r_type);
2100+ outrel.r_addend = rel->r_addend;
2101+ }
2102+ else
2103+ {
2104+ outrel.r_info = ELFNN_R_INFO (0, R_RISCV_RELATIVE);
2105+ outrel.r_addend = relocation + rel->r_addend;
2106+ }
2107+
2108+ riscv_elf_append_rela (output_bfd, sreloc, &outrel);
2109+ if (skip_static_relocation)
2110+ continue;
2111+ }
2112+ break;
2113+
2114+ case R_RISCV_TLS_GOT_HI20:
2115+ is_ie = TRUE;
2116+ /* Fall through. */
2117+
2118+ case R_RISCV_TLS_GD_HI20:
2119+ if (h != NULL)
2120+ {
2121+ off = h->got.offset;
2122+ h->got.offset |= 1;
2123+ }
2124+ else
2125+ {
2126+ off = local_got_offsets[r_symndx];
2127+ local_got_offsets[r_symndx] |= 1;
2128+ }
2129+
2130+ tls_type = _bfd_riscv_elf_tls_type (input_bfd, h, r_symndx);
2131+ BFD_ASSERT (tls_type & (GOT_TLS_IE | GOT_TLS_GD));
2132+ /* If this symbol is referenced by both GD and IE TLS, the IE
2133+ reference's GOT slot follows the GD reference's slots. */
2134+ ie_off = 0;
2135+ if ((tls_type & GOT_TLS_GD) && (tls_type & GOT_TLS_IE))
2136+ ie_off = 2 * GOT_ENTRY_SIZE;
2137+
2138+ if ((off & 1) != 0)
2139+ off &= ~1;
2140+ else
2141+ {
2142+ Elf_Internal_Rela outrel;
2143+ int indx = 0;
2144+ bfd_boolean need_relocs = FALSE;
2145+
2146+ if (htab->elf.srelgot == NULL)
2147+ abort ();
2148+
2149+ if (h != NULL)
2150+ {
2151+ bfd_boolean dyn;
2152+ dyn = htab->elf.dynamic_sections_created;
2153+
2154+ if (WILL_CALL_FINISH_DYNAMIC_SYMBOL (dyn, info->shared, h)
2155+ && (!info->shared
2156+ || !SYMBOL_REFERENCES_LOCAL (info, h)))
2157+ {
2158+ indx = h->dynindx;
2159+ }
2160+ }
2161+
2162+ /* The GOT entries have not been initialized yet. Do it
2163+ now, and emit any relocations. */
2164+ if ((info->shared || indx != 0)
2165+ && (h == NULL
2166+ || ELF_ST_VISIBILITY (h->other) == STV_DEFAULT
2167+ || h->root.type != bfd_link_hash_undefweak))
2168+ need_relocs = TRUE;
2169+
2170+ if (tls_type & GOT_TLS_GD)
2171+ {
2172+ if (need_relocs)
2173+ {
2174+ outrel.r_offset = sec_addr (htab->elf.sgot) + off;
2175+ outrel.r_addend = 0;
2176+ outrel.r_info = ELFNN_R_INFO (indx, R_RISCV_TLS_DTPMODNN);
2177+ bfd_put_NN (output_bfd, 0,
2178+ htab->elf.sgot->contents + off);
2179+ riscv_elf_append_rela (output_bfd, htab->elf.srelgot, &outrel);
2180+ if (indx == 0)
2181+ {
2182+ BFD_ASSERT (! unresolved_reloc);
2183+ bfd_put_NN (output_bfd,
2184+ dtpoff (info, relocation),
2185+ (htab->elf.sgot->contents + off +
2186+ RISCV_ELF_WORD_BYTES));
2187+ }
2188+ else
2189+ {
2190+ bfd_put_NN (output_bfd, 0,
2191+ (htab->elf.sgot->contents + off +
2192+ RISCV_ELF_WORD_BYTES));
2193+ outrel.r_info = ELFNN_R_INFO (indx, R_RISCV_TLS_DTPRELNN);
2194+ outrel.r_offset += RISCV_ELF_WORD_BYTES;
2195+ riscv_elf_append_rela (output_bfd, htab->elf.srelgot, &outrel);
2196+ }
2197+ }
2198+ else
2199+ {
2200+ /* If we are not emitting relocations for a
2201+ general dynamic reference, then we must be in a
2202+ static link or an executable link with the
2203+ symbol binding locally. Mark it as belonging
2204+ to module 1, the executable. */
2205+ bfd_put_NN (output_bfd, 1,
2206+ htab->elf.sgot->contents + off);
2207+ bfd_put_NN (output_bfd,
2208+ dtpoff (info, relocation),
2209+ (htab->elf.sgot->contents + off +
2210+ RISCV_ELF_WORD_BYTES));
2211+ }
2212+ }
2213+
2214+ if (tls_type & GOT_TLS_IE)
2215+ {
2216+ if (need_relocs)
2217+ {
2218+ bfd_put_NN (output_bfd, 0,
2219+ htab->elf.sgot->contents + off + ie_off);
2220+ outrel.r_offset = sec_addr (htab->elf.sgot)
2221+ + off + ie_off;
2222+ outrel.r_addend = 0;
2223+ if (indx == 0)
2224+ outrel.r_addend = tpoff (info, relocation);
2225+ outrel.r_info = ELFNN_R_INFO (indx, R_RISCV_TLS_TPRELNN);
2226+ riscv_elf_append_rela (output_bfd, htab->elf.srelgot, &outrel);
2227+ }
2228+ else
2229+ {
2230+ bfd_put_NN (output_bfd, tpoff (info, relocation),
2231+ htab->elf.sgot->contents + off + ie_off);
2232+ }
2233+ }
2234+ }
2235+
2236+ BFD_ASSERT (off < (bfd_vma) -2);
2237+ relocation = sec_addr (htab->elf.sgot) + off + (is_ie ? ie_off : 0);
2238+ if (!riscv_record_pcrel_hi_reloc (&pcrel_relocs, pc, relocation))
2239+ r = bfd_reloc_overflow;
2240+ unresolved_reloc = FALSE;
2241+ break;
2242+
2243+ default:
2244+ r = bfd_reloc_notsupported;
2245+ }
2246+
2247+ /* Dynamic relocs are not propagated for SEC_DEBUGGING sections
2248+ because such sections are not SEC_ALLOC and thus ld.so will
2249+ not process them. */
2250+ if (unresolved_reloc
2251+ && !((input_section->flags & SEC_DEBUGGING) != 0
2252+ && h->def_dynamic)
2253+ && _bfd_elf_section_offset (output_bfd, info, input_section,
2254+ rel->r_offset) != (bfd_vma) -1)
2255+ {
2256+ (*_bfd_error_handler)
2257+ (_("%B(%A+0x%lx): unresolvable %s relocation against symbol `%s'"),
2258+ input_bfd,
2259+ input_section,
2260+ (long) rel->r_offset,
2261+ howto->name,
2262+ h->root.root.string);
2263+ continue;
2264+ }
2265+
2266+ if (r == bfd_reloc_ok)
2267+ r = perform_relocation (howto, rel, relocation, input_section,
2268+ input_bfd, contents);
2269+
2270+ switch (r)
2271+ {
2272+ case bfd_reloc_ok:
2273+ continue;
2274+
2275+ case bfd_reloc_overflow:
2276+ r = info->callbacks->reloc_overflow
2277+ (info, (h ? &h->root : NULL), name, howto->name,
2278+ (bfd_vma) 0, input_bfd, input_section, rel->r_offset);
2279+ break;
2280+
2281+ case bfd_reloc_undefined:
2282+ r = info->callbacks->undefined_symbol
2283+ (info, name, input_bfd, input_section, rel->r_offset,
2284+ TRUE);
2285+ break;
2286+
2287+ case bfd_reloc_outofrange:
2288+ msg = _("internal error: out of range error");
2289+ break;
2290+
2291+ case bfd_reloc_notsupported:
2292+ msg = _("internal error: unsupported relocation error");
2293+ break;
2294+
2295+ case bfd_reloc_dangerous:
2296+ msg = _("internal error: dangerous relocation");
2297+ break;
2298+
2299+ default:
2300+ msg = _("internal error: unknown error");
2301+ break;
2302+ }
2303+
2304+ if (msg)
2305+ r = info->callbacks->warning
2306+ (info, msg, name, input_bfd, input_section, rel->r_offset);
2307+ goto out;
2308+ }
2309+
2310+ ret = riscv_resolve_pcrel_lo_relocs (&pcrel_relocs);
2311+out:
2312+ riscv_free_pcrel_relocs (&pcrel_relocs);
2313+ return ret;
2314+}
2315+
2316+/* Finish up dynamic symbol handling. We set the contents of various
2317+ dynamic sections here. */
2318+
2319+static bfd_boolean
2320+riscv_elf_finish_dynamic_symbol (bfd *output_bfd,
2321+ struct bfd_link_info *info,
2322+ struct elf_link_hash_entry *h,
2323+ Elf_Internal_Sym *sym)
2324+{
2325+ struct riscv_elf_link_hash_table *htab = riscv_elf_hash_table (info);
2326+ const struct elf_backend_data *bed = get_elf_backend_data (output_bfd);
2327+
2328+ if (h->plt.offset != (bfd_vma) -1)
2329+ {
2330+ /* We've decided to create a PLT entry for this symbol. */
2331+ bfd_byte *loc;
2332+ bfd_vma i, header_address, plt_idx, got_address;
2333+ uint32_t plt_entry[PLT_ENTRY_INSNS];
2334+ Elf_Internal_Rela rela;
2335+
2336+ BFD_ASSERT (h->dynindx != -1);
2337+
2338+ /* Calculate the address of the PLT header. */
2339+ header_address = sec_addr (htab->elf.splt);
2340+
2341+ /* Calculate the index of the entry. */
2342+ plt_idx = (h->plt.offset - PLT_HEADER_SIZE) / PLT_ENTRY_SIZE;
2343+
2344+ /* Calculate the address of the .got.plt entry. */
2345+ got_address = riscv_elf_got_plt_val (plt_idx, info);
2346+
2347+ /* Find out where the .plt entry should go. */
2348+ loc = htab->elf.splt->contents + h->plt.offset;
2349+
2350+ /* Fill in the PLT entry itself. */
2351+ riscv_make_plt_entry (got_address, header_address + h->plt.offset,
2352+ plt_entry);
2353+ for (i = 0; i < PLT_ENTRY_INSNS; i++)
2354+ bfd_put_32 (output_bfd, plt_entry[i], loc + 4*i);
2355+
2356+ /* Fill in the initial value of the .got.plt entry. */
2357+ loc = htab->elf.sgotplt->contents
2358+ + (got_address - sec_addr (htab->elf.sgotplt));
2359+ bfd_put_NN (output_bfd, sec_addr (htab->elf.splt), loc);
2360+
2361+ /* Fill in the entry in the .rela.plt section. */
2362+ rela.r_offset = got_address;
2363+ rela.r_addend = 0;
2364+ rela.r_info = ELFNN_R_INFO (h->dynindx, R_RISCV_JUMP_SLOT);
2365+
2366+ loc = htab->elf.srelplt->contents + plt_idx * sizeof (ElfNN_External_Rela);
2367+ bed->s->swap_reloca_out (output_bfd, &rela, loc);
2368+
2369+ if (!h->def_regular)
2370+ {
2371+ /* Mark the symbol as undefined, rather than as defined in
2372+ the .plt section. Leave the value alone. */
2373+ sym->st_shndx = SHN_UNDEF;
2374+ /* If the symbol is weak, we do need to clear the value.
2375+ Otherwise, the PLT entry would provide a definition for
2376+ the symbol even if the symbol wasn't defined anywhere,
2377+ and so the symbol would never be NULL. */
2378+ if (!h->ref_regular_nonweak)
2379+ sym->st_value = 0;
2380+ }
2381+ }
2382+
2383+ if (h->got.offset != (bfd_vma) -1
2384+ && !(riscv_elf_hash_entry(h)->tls_type & (GOT_TLS_GD | GOT_TLS_IE)))
2385+ {
2386+ asection *sgot;
2387+ asection *srela;
2388+ Elf_Internal_Rela rela;
2389+
2390+ /* This symbol has an entry in the GOT. Set it up. */
2391+
2392+ sgot = htab->elf.sgot;
2393+ srela = htab->elf.srelgot;
2394+ BFD_ASSERT (sgot != NULL && srela != NULL);
2395+
2396+ rela.r_offset = sec_addr (sgot) + (h->got.offset &~ (bfd_vma) 1);
2397+
2398+ /* If this is a -Bsymbolic link, and the symbol is defined
2399+ locally, we just want to emit a RELATIVE reloc. Likewise if
2400+ the symbol was forced to be local because of a version file.
2401+ The entry in the global offset table will already have been
2402+ initialized in the relocate_section function. */
2403+ if (info->shared
2404+ && (info->symbolic || h->dynindx == -1)
2405+ && h->def_regular)
2406+ {
2407+ asection *sec = h->root.u.def.section;
2408+ rela.r_info = ELFNN_R_INFO (0, R_RISCV_RELATIVE);
2409+ rela.r_addend = (h->root.u.def.value
2410+ + sec->output_section->vma
2411+ + sec->output_offset);
2412+ }
2413+ else
2414+ {
2415+ BFD_ASSERT (h->dynindx != -1);
2416+ rela.r_info = ELFNN_R_INFO (h->dynindx, R_RISCV_NN);
2417+ rela.r_addend = 0;
2418+ }
2419+
2420+ bfd_put_NN (output_bfd, 0,
2421+ sgot->contents + (h->got.offset & ~(bfd_vma) 1));
2422+ riscv_elf_append_rela (output_bfd, srela, &rela);
2423+ }
2424+
2425+ if (h->needs_copy)
2426+ {
2427+ Elf_Internal_Rela rela;
2428+
2429+ /* This symbols needs a copy reloc. Set it up. */
2430+ BFD_ASSERT (h->dynindx != -1);
2431+
2432+ rela.r_offset = sec_addr (h->root.u.def.section) + h->root.u.def.value;
2433+ rela.r_info = ELFNN_R_INFO (h->dynindx, R_RISCV_COPY);
2434+ rela.r_addend = 0;
2435+ riscv_elf_append_rela (output_bfd, htab->srelbss, &rela);
2436+ }
2437+
2438+ /* Mark some specially defined symbols as absolute. */
2439+ if (h == htab->elf.hdynamic
2440+ || (h == htab->elf.hgot || h == htab->elf.hplt))
2441+ sym->st_shndx = SHN_ABS;
2442+
2443+ return TRUE;
2444+}
2445+
2446+/* Finish up the dynamic sections. */
2447+
2448+static bfd_boolean
2449+riscv_finish_dyn (bfd *output_bfd, struct bfd_link_info *info,
2450+ bfd *dynobj, asection *sdyn)
2451+{
2452+ struct riscv_elf_link_hash_table *htab = riscv_elf_hash_table (info);
2453+ const struct elf_backend_data *bed = get_elf_backend_data (output_bfd);
2454+ size_t dynsize = bed->s->sizeof_dyn;
2455+ bfd_byte *dyncon, *dynconend;
2456+
2457+ dynconend = sdyn->contents + sdyn->size;
2458+ for (dyncon = sdyn->contents; dyncon < dynconend; dyncon += dynsize)
2459+ {
2460+ Elf_Internal_Dyn dyn;
2461+ asection *s;
2462+
2463+ bed->s->swap_dyn_in (dynobj, dyncon, &dyn);
2464+
2465+ switch (dyn.d_tag)
2466+ {
2467+ case DT_PLTGOT:
2468+ s = htab->elf.sgotplt;
2469+ dyn.d_un.d_ptr = s->output_section->vma + s->output_offset;
2470+ break;
2471+ case DT_JMPREL:
2472+ s = htab->elf.srelplt;
2473+ dyn.d_un.d_ptr = s->output_section->vma + s->output_offset;
2474+ break;
2475+ case DT_PLTRELSZ:
2476+ s = htab->elf.srelplt;
2477+ dyn.d_un.d_val = s->size;
2478+ break;
2479+ default:
2480+ continue;
2481+ }
2482+
2483+ bed->s->swap_dyn_out (output_bfd, &dyn, dyncon);
2484+ }
2485+ return TRUE;
2486+}
2487+
2488+static bfd_boolean
2489+riscv_elf_finish_dynamic_sections (bfd *output_bfd,
2490+ struct bfd_link_info *info)
2491+{
2492+ bfd *dynobj;
2493+ asection *sdyn;
2494+ struct riscv_elf_link_hash_table *htab;
2495+
2496+ htab = riscv_elf_hash_table (info);
2497+ BFD_ASSERT (htab != NULL);
2498+ dynobj = htab->elf.dynobj;
2499+
2500+ sdyn = bfd_get_linker_section (dynobj, ".dynamic");
2501+
2502+ if (elf_hash_table (info)->dynamic_sections_created)
2503+ {
2504+ asection *splt;
2505+ bfd_boolean ret;
2506+
2507+ splt = htab->elf.splt;
2508+ BFD_ASSERT (splt != NULL && sdyn != NULL);
2509+
2510+ ret = riscv_finish_dyn (output_bfd, info, dynobj, sdyn);
2511+
2512+ if (ret != TRUE)
2513+ return ret;
2514+
2515+ /* Fill in the head and tail entries in the procedure linkage table. */
2516+ if (splt->size > 0)
2517+ {
2518+ int i;
2519+ uint32_t plt_header[PLT_HEADER_INSNS];
2520+ riscv_make_plt0_entry (sec_addr (htab->elf.sgotplt),
2521+ sec_addr (splt), plt_header);
2522+
2523+ for (i = 0; i < PLT_HEADER_INSNS; i++)
2524+ bfd_put_32 (output_bfd, plt_header[i], splt->contents + 4*i);
2525+ }
2526+
2527+ elf_section_data (splt->output_section)->this_hdr.sh_entsize
2528+ = PLT_ENTRY_SIZE;
2529+ }
2530+
2531+ if (htab->elf.sgotplt)
2532+ {
2533+ if (bfd_is_abs_section (htab->elf.sgotplt->output_section))
2534+ {
2535+ (*_bfd_error_handler)
2536+ (_("discarded output section: `%A'"), htab->elf.sgotplt);
2537+ return FALSE;
2538+ }
2539+
2540+ if (htab->elf.sgotplt->size > 0)
2541+ {
2542+ /* Write the first two entries in .got.plt, needed for the dynamic
2543+ linker. */
2544+ bfd_put_NN (output_bfd, (bfd_vma) -1, htab->elf.sgotplt->contents);
2545+ bfd_put_NN (output_bfd, (bfd_vma) 0,
2546+ htab->elf.sgotplt->contents + GOT_ENTRY_SIZE);
2547+ }
2548+
2549+ elf_section_data (htab->elf.sgotplt->output_section)->this_hdr.sh_entsize =
2550+ GOT_ENTRY_SIZE;
2551+ }
2552+
2553+ if (htab->elf.sgot)
2554+ {
2555+ if (htab->elf.sgot->size > 0)
2556+ {
2557+ /* Set the first entry in the global offset table to the address of
2558+ the dynamic section. */
2559+ bfd_vma val = sdyn ? sec_addr (sdyn) : 0;
2560+ bfd_put_NN (output_bfd, val, htab->elf.sgot->contents);
2561+ }
2562+
2563+ elf_section_data (htab->elf.sgot->output_section)->this_hdr.sh_entsize =
2564+ GOT_ENTRY_SIZE;
2565+ }
2566+
2567+ return TRUE;
2568+}
2569+
2570+/* Return address for Ith PLT stub in section PLT, for relocation REL
2571+ or (bfd_vma) -1 if it should not be included. */
2572+
2573+static bfd_vma
2574+riscv_elf_plt_sym_val (bfd_vma i, const asection *plt,
2575+ const arelent *rel ATTRIBUTE_UNUSED)
2576+{
2577+ return plt->vma + PLT_HEADER_SIZE + i * PLT_ENTRY_SIZE;
2578+}
2579+
2580+static enum elf_reloc_type_class
2581+riscv_reloc_type_class (const struct bfd_link_info *info ATTRIBUTE_UNUSED,
2582+ const asection *rel_sec ATTRIBUTE_UNUSED,
2583+ const Elf_Internal_Rela *rela)
2584+{
2585+ switch (ELFNN_R_TYPE (rela->r_info))
2586+ {
2587+ case R_RISCV_RELATIVE:
2588+ return reloc_class_relative;
2589+ case R_RISCV_JUMP_SLOT:
2590+ return reloc_class_plt;
2591+ case R_RISCV_COPY:
2592+ return reloc_class_copy;
2593+ default:
2594+ return reloc_class_normal;
2595+ }
2596+}
2597+
2598+/* Return true if bfd machine EXTENSION is an extension of machine BASE. */
2599+
2600+static bfd_boolean
2601+riscv_mach_extends_p (unsigned long base, unsigned long extension)
2602+{
2603+ return extension == base;
2604+}
2605+
2606+/* Merge backend specific data from an object file to the output
2607+ object file when linking. */
2608+
2609+static bfd_boolean
2610+_bfd_riscv_elf_merge_private_bfd_data (bfd *ibfd, bfd *obfd)
2611+{
2612+ flagword old_flags;
2613+ flagword new_flags;
2614+
2615+ if (!is_riscv_elf (ibfd) || !is_riscv_elf (obfd))
2616+ return TRUE;
2617+
2618+ if (strcmp (bfd_get_target (ibfd), bfd_get_target (obfd)) != 0)
2619+ {
2620+ (*_bfd_error_handler)
2621+ (_("%B: ABI is incompatible with that of the selected emulation"),
2622+ ibfd);
2623+ return FALSE;
2624+ }
2625+
2626+ if (!_bfd_elf_merge_object_attributes (ibfd, obfd))
2627+ return FALSE;
2628+
2629+ new_flags = elf_elfheader (ibfd)->e_flags;
2630+ old_flags = elf_elfheader (obfd)->e_flags;
2631+
2632+ if (! elf_flags_init (obfd))
2633+ {
2634+ elf_flags_init (obfd) = TRUE;
2635+ elf_elfheader (obfd)->e_flags = new_flags;
2636+ elf_elfheader (obfd)->e_ident[EI_CLASS]
2637+ = elf_elfheader (ibfd)->e_ident[EI_CLASS];
2638+
2639+ if (bfd_get_arch (obfd) == bfd_get_arch (ibfd)
2640+ && (bfd_get_arch_info (obfd)->the_default
2641+ || riscv_mach_extends_p (bfd_get_mach (obfd),
2642+ bfd_get_mach (ibfd))))
2643+ {
2644+ if (! bfd_set_arch_mach (obfd, bfd_get_arch (ibfd),
2645+ bfd_get_mach (ibfd)))
2646+ return FALSE;
2647+ }
2648+
2649+ return TRUE;
2650+ }
2651+
2652+ /* Check flag compatibility. */
2653+
2654+ if (new_flags == old_flags)
2655+ return TRUE;
2656+
2657+ /* Don't link RV32 and RV64. */
2658+ if (elf_elfheader (ibfd)->e_ident[EI_CLASS]
2659+ != elf_elfheader (obfd)->e_ident[EI_CLASS])
2660+ {
2661+ (*_bfd_error_handler)
2662+ (_("%B: ELF class mismatch: can't link 32- and 64-bit modules"), ibfd);
2663+ goto fail;
2664+ }
2665+
2666+ /* Warn about any other mismatches. */
2667+ if (new_flags != old_flags)
2668+ {
2669+ if (!EF_IS_RISCV_EXT_Xcustom (new_flags) &&
2670+ !EF_IS_RISCV_EXT_Xcustom (old_flags))
2671+ {
2672+ (*_bfd_error_handler)
2673+ (_("%B: uses different e_flags (0x%lx) fields than previous modules (0x%lx)"),
2674+ ibfd, (unsigned long) new_flags,
2675+ (unsigned long) old_flags);
2676+ goto fail;
2677+ }
2678+ else if (EF_IS_RISCV_EXT_Xcustom(new_flags))
2679+ EF_SET_RISCV_EXT (elf_elfheader (obfd)->e_flags,
2680+ EF_GET_RISCV_EXT (old_flags));
2681+ }
2682+
2683+ return TRUE;
2684+
2685+fail:
2686+ bfd_set_error (bfd_error_bad_value);
2687+ return FALSE;
2688+}
2689+
2690+/* Delete some bytes from a section while relaxing. */
2691+
2692+static bfd_boolean
2693+riscv_relax_delete_bytes (bfd *abfd, asection *sec, bfd_vma addr, size_t count)
2694+{
2695+ unsigned int i, symcount;
2696+ bfd_vma toaddr = sec->size;
2697+ struct elf_link_hash_entry **sym_hashes = elf_sym_hashes (abfd);
2698+ Elf_Internal_Shdr *symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
2699+ unsigned int sec_shndx = _bfd_elf_section_from_bfd_section (abfd, sec);
2700+ struct bfd_elf_section_data *data = elf_section_data (sec);
2701+ bfd_byte *contents = data->this_hdr.contents;
2702+
2703+ /* Actually delete the bytes. */
2704+ sec->size -= count;
2705+ memmove (contents + addr, contents + addr + count, toaddr - addr - count);
2706+
2707+ /* Adjust the location of all of the relocs. Note that we need not
2708+ adjust the addends, since all PC-relative references must be against
2709+ symbols, which we will adjust below. */
2710+ for (i = 0; i < sec->reloc_count; i++)
2711+ if (data->relocs[i].r_offset > addr && data->relocs[i].r_offset < toaddr)
2712+ data->relocs[i].r_offset -= count;
2713+
2714+ /* Adjust the local symbols defined in this section. */
2715+ for (i = 0; i < symtab_hdr->sh_info; i++)
2716+ {
2717+ Elf_Internal_Sym *sym = (Elf_Internal_Sym *) symtab_hdr->contents + i;
2718+ if (sym->st_shndx == sec_shndx)
2719+ {
2720+ /* If the symbol is in the range of memory we just moved, we
2721+ have to adjust its value. */
2722+ if (sym->st_value > addr && sym->st_value <= toaddr)
2723+ sym->st_value -= count;
2724+
2725+ /* If the symbol *spans* the bytes we just deleted (i.e. its
2726+ *end* is in the moved bytes but its *start* isn't), then we
2727+ must adjust its size. */
2728+ if (sym->st_value <= addr
2729+ && sym->st_value + sym->st_size > addr
2730+ && sym->st_value + sym->st_size <= toaddr)
2731+ sym->st_size -= count;
2732+ }
2733+ }
2734+
2735+ /* Now adjust the global symbols defined in this section. */
2736+ symcount = ((symtab_hdr->sh_size / sizeof(ElfNN_External_Sym))
2737+ - symtab_hdr->sh_info);
2738+
2739+ for (i = 0; i < symcount; i++)
2740+ {
2741+ struct elf_link_hash_entry *sym_hash = sym_hashes[i];
2742+
2743+ if ((sym_hash->root.type == bfd_link_hash_defined
2744+ || sym_hash->root.type == bfd_link_hash_defweak)
2745+ && sym_hash->root.u.def.section == sec)
2746+ {
2747+ /* As above, adjust the value if needed. */
2748+ if (sym_hash->root.u.def.value > addr
2749+ && sym_hash->root.u.def.value <= toaddr)
2750+ sym_hash->root.u.def.value -= count;
2751+
2752+ /* As above, adjust the size if needed. */
2753+ if (sym_hash->root.u.def.value <= addr
2754+ && sym_hash->root.u.def.value + sym_hash->size > addr
2755+ && sym_hash->root.u.def.value + sym_hash->size <= toaddr)
2756+ sym_hash->size -= count;
2757+ }
2758+ }
2759+
2760+ return TRUE;
2761+}
2762+
2763+/* Relax AUIPC + JALR into JAL. */
2764+
2765+static bfd_boolean
2766+_bfd_riscv_relax_call (bfd *abfd, asection *sec,
2767+ struct bfd_link_info *link_info,
2768+ Elf_Internal_Rela *rel,
2769+ bfd_vma symval,
2770+ bfd_boolean *again)
2771+{
2772+ bfd_byte *contents = elf_section_data (sec)->this_hdr.contents;
2773+ bfd_signed_vma foff = symval - (sec_addr (sec) + rel->r_offset);
Patrick Georgiaf473ed2015-07-17 23:35:54 +02002774+ bfd_boolean near_zero = (symval + RISCV_IMM_REACH/2) < RISCV_IMM_REACH;
Patrick Georgif0bbc952015-03-07 10:57:25 +01002775+ bfd_vma auipc, jalr;
Patrick Georgiaf473ed2015-07-17 23:35:54 +02002776+ int rd, r_type, len = 4, rvc = elf_elfheader (abfd)->e_flags & EF_RISCV_RVC;
Patrick Georgif0bbc952015-03-07 10:57:25 +01002777+
2778+ /* See if this function call can be shortened. */
Patrick Georgiaf473ed2015-07-17 23:35:54 +02002779+ if (!VALID_UJTYPE_IMM (foff) && !(!link_info->shared && near_zero))
Patrick Georgif0bbc952015-03-07 10:57:25 +01002780+ return TRUE;
2781+
2782+ /* Shorten the function call. */
2783+ BFD_ASSERT (rel->r_offset + 8 <= sec->size);
2784+
2785+ auipc = bfd_get_32 (abfd, contents + rel->r_offset);
2786+ jalr = bfd_get_32 (abfd, contents + rel->r_offset + 4);
Patrick Georgiaf473ed2015-07-17 23:35:54 +02002787+ rd = (jalr >> OP_SH_RD) & OP_MASK_RD;
2788+ rvc = rvc && VALID_RVC_J_IMM (foff);
Patrick Georgif0bbc952015-03-07 10:57:25 +01002789+
Patrick Georgiaf473ed2015-07-17 23:35:54 +02002790+ if (rvc && (rd == 0 || rd == X_RA))
2791+ {
2792+ /* Relax to C.J[AL] rd, addr. */
2793+ r_type = R_RISCV_RVC_JUMP;
2794+ auipc = rd == 0 ? MATCH_C_J : MATCH_C_JAL;
2795+ len = 2;
2796+ }
2797+ else if (VALID_UJTYPE_IMM (foff))
Patrick Georgif0bbc952015-03-07 10:57:25 +01002798+ {
2799+ /* Relax to JAL rd, addr. */
2800+ r_type = R_RISCV_JAL;
Patrick Georgiaf473ed2015-07-17 23:35:54 +02002801+ auipc = MATCH_JAL | (rd << OP_SH_RD);
Patrick Georgif0bbc952015-03-07 10:57:25 +01002802+ }
2803+ else /* near_zero */
2804+ {
2805+ /* Relax to JALR rd, x0, addr. */
2806+ r_type = R_RISCV_LO12_I;
Patrick Georgiaf473ed2015-07-17 23:35:54 +02002807+ auipc = MATCH_JALR | (rd << OP_SH_RD);
Patrick Georgif0bbc952015-03-07 10:57:25 +01002808+ }
2809+
2810+ /* Replace the R_RISCV_CALL reloc. */
2811+ rel->r_info = ELFNN_R_INFO (ELFNN_R_SYM (rel->r_info), r_type);
2812+ /* Replace the AUIPC. */
Patrick Georgiaf473ed2015-07-17 23:35:54 +02002813+ bfd_put (8 * len, abfd, auipc, contents + rel->r_offset);
Patrick Georgif0bbc952015-03-07 10:57:25 +01002814+
2815+ /* Delete unnecessary JALR. */
2816+ *again = TRUE;
Patrick Georgiaf473ed2015-07-17 23:35:54 +02002817+ return riscv_relax_delete_bytes (abfd, sec, rel->r_offset + len, 8 - len);
Patrick Georgif0bbc952015-03-07 10:57:25 +01002818+}
2819+
2820+/* Relax non-PIC global variable references. */
2821+
2822+static bfd_boolean
2823+_bfd_riscv_relax_lui (bfd *abfd, asection *sec,
2824+ struct bfd_link_info *link_info,
2825+ Elf_Internal_Rela *rel,
2826+ bfd_vma symval,
2827+ bfd_boolean *again)
2828+{
2829+ bfd_vma gp = riscv_global_pointer_value (link_info);
2830+
2831+ /* Bail out if this symbol isn't in range of either gp or x0. */
2832+ if (!VALID_ITYPE_IMM (symval - gp) && !(symval < RISCV_IMM_REACH/2))
2833+ return TRUE;
2834+
2835+ /* We can delete the unnecessary AUIPC. The corresponding LO12 reloc
2836+ will be converted to GPREL during relocation. */
2837+ BFD_ASSERT (rel->r_offset + 4 <= sec->size);
2838+ rel->r_info = ELFNN_R_INFO (0, R_RISCV_NONE);
2839+
2840+ *again = TRUE;
2841+ return riscv_relax_delete_bytes (abfd, sec, rel->r_offset, 4);
2842+}
2843+
2844+/* Relax non-PIC TLS references. */
2845+
2846+static bfd_boolean
2847+_bfd_riscv_relax_tls_le (bfd *abfd, asection *sec,
2848+ struct bfd_link_info *link_info,
2849+ Elf_Internal_Rela *rel,
2850+ bfd_vma symval,
2851+ bfd_boolean *again)
2852+{
2853+ /* See if this symbol is in range of tp. */
2854+ if (RISCV_CONST_HIGH_PART (tpoff (link_info, symval)) != 0)
2855+ return TRUE;
2856+
2857+ /* We can delete the unnecessary LUI and tp add. The LO12 reloc will be
2858+ made directly tp-relative. */
2859+ BFD_ASSERT (rel->r_offset + 4 <= sec->size);
2860+ rel->r_info = ELFNN_R_INFO (0, R_RISCV_NONE);
2861+
2862+ *again = TRUE;
2863+ return riscv_relax_delete_bytes (abfd, sec, rel->r_offset, 4);
2864+}
2865+
2866+/* Implement R_RISCV_ALIGN by deleting excess alignment NOPs. */
2867+
2868+static bfd_boolean
2869+_bfd_riscv_relax_align (bfd *abfd, asection *sec,
2870+ struct bfd_link_info *link_info ATTRIBUTE_UNUSED,
2871+ Elf_Internal_Rela *rel,
2872+ bfd_vma symval,
2873+ bfd_boolean *again ATTRIBUTE_UNUSED)
2874+{
Patrick Georgiaf473ed2015-07-17 23:35:54 +02002875+ bfd_byte *contents = elf_section_data (sec)->this_hdr.contents;
2876+ bfd_vma alignment = 1, pos;
Patrick Georgif0bbc952015-03-07 10:57:25 +01002877+ while (alignment <= rel->r_addend)
2878+ alignment *= 2;
2879+
2880+ symval -= rel->r_addend;
2881+ bfd_vma aligned_addr = ((symval - 1) & ~(alignment - 1)) + alignment;
Patrick Georgiaf473ed2015-07-17 23:35:54 +02002882+ bfd_vma nop_bytes = aligned_addr - symval;
2883+
2884+ /* Once we've handled an R_RISCV_ALIGN, we can't relax anything else. */
2885+ sec->sec_flg0 = TRUE;
Patrick Georgif0bbc952015-03-07 10:57:25 +01002886+
2887+ /* Make sure there are enough NOPs to actually achieve the alignment. */
Patrick Georgiaf473ed2015-07-17 23:35:54 +02002888+ if (rel->r_addend < nop_bytes)
Patrick Georgif0bbc952015-03-07 10:57:25 +01002889+ return FALSE;
2890+
2891+ /* Delete the reloc. */
2892+ rel->r_info = ELFNN_R_INFO (0, R_RISCV_NONE);
2893+
2894+ /* If the number of NOPs is already correct, there's nothing to do. */
Patrick Georgiaf473ed2015-07-17 23:35:54 +02002895+ if (nop_bytes == rel->r_addend)
Patrick Georgif0bbc952015-03-07 10:57:25 +01002896+ return TRUE;
2897+
Patrick Georgiaf473ed2015-07-17 23:35:54 +02002898+ /* Write as many RISC-V NOPs as we need. */
2899+ for (pos = 0; pos < (nop_bytes & -4); pos += 4)
2900+ bfd_put_32 (abfd, RISCV_NOP, contents + rel->r_offset + pos);
2901+
2902+ /* Write a final RVC NOP if need be. */
2903+ if (nop_bytes % 4 != 0)
2904+ bfd_put_16 (abfd, RVC_NOP, contents + rel->r_offset + pos);
2905+
2906+ /* Delete the excess bytes. */
2907+ return riscv_relax_delete_bytes (abfd, sec, rel->r_offset + nop_bytes,
2908+ rel->r_addend - nop_bytes);
Patrick Georgif0bbc952015-03-07 10:57:25 +01002909+}
2910+
2911+/* Relax a section. Pass 0 shortens code sequences unless disabled.
2912+ Pass 1, which cannot be disabled, handles code alignment directives. */
2913+
2914+static bfd_boolean
2915+_bfd_riscv_relax_section (bfd *abfd, asection *sec,
2916+ struct bfd_link_info *info, bfd_boolean *again)
2917+{
2918+ Elf_Internal_Shdr *symtab_hdr = &elf_symtab_hdr (abfd);
2919+ struct riscv_elf_link_hash_table *htab = riscv_elf_hash_table (info);
2920+ struct bfd_elf_section_data *data = elf_section_data (sec);
2921+ Elf_Internal_Rela *relocs;
2922+ bfd_boolean ret = FALSE;
2923+ unsigned int i;
2924+
2925+ *again = FALSE;
2926+
2927+ if (info->relocatable
Patrick Georgiaf473ed2015-07-17 23:35:54 +02002928+ || sec->sec_flg0
Patrick Georgif0bbc952015-03-07 10:57:25 +01002929+ || (sec->flags & SEC_RELOC) == 0
2930+ || sec->reloc_count == 0
2931+ || (info->disable_target_specific_optimizations
2932+ && info->relax_pass == 0))
2933+ return TRUE;
2934+
2935+ /* Read this BFD's relocs if we haven't done so already. */
2936+ if (data->relocs)
2937+ relocs = data->relocs;
2938+ else if (!(relocs = _bfd_elf_link_read_relocs (abfd, sec, NULL, NULL,
2939+ info->keep_memory)))
2940+ goto fail;
2941+
2942+ /* Examine and consider relaxing each reloc. */
2943+ for (i = 0; i < sec->reloc_count; i++)
2944+ {
Patrick Georgiaf473ed2015-07-17 23:35:54 +02002945+ Elf_Internal_Rela *rel = relocs + i;
Patrick Georgif0bbc952015-03-07 10:57:25 +01002946+ typeof(&_bfd_riscv_relax_call) relax_func = NULL;
2947+ int type = ELFNN_R_TYPE (rel->r_info);
2948+ bfd_vma symval;
2949+
2950+ if (info->relax_pass == 0)
2951+ {
2952+ if (type == R_RISCV_CALL || type == R_RISCV_CALL_PLT)
2953+ relax_func = _bfd_riscv_relax_call;
2954+ else if (type == R_RISCV_HI20)
2955+ relax_func = _bfd_riscv_relax_lui;
2956+ else if (type == R_RISCV_TPREL_HI20 || type == R_RISCV_TPREL_ADD)
2957+ relax_func = _bfd_riscv_relax_tls_le;
2958+ }
2959+ else if (type == R_RISCV_ALIGN)
2960+ relax_func = _bfd_riscv_relax_align;
2961+
2962+ if (!relax_func)
2963+ continue;
2964+
2965+ data->relocs = relocs;
2966+
2967+ /* Read this BFD's contents if we haven't done so already. */
2968+ if (!data->this_hdr.contents
2969+ && !bfd_malloc_and_get_section (abfd, sec, &data->this_hdr.contents))
2970+ goto fail;
2971+
2972+ /* Read this BFD's symbols if we haven't done so already. */
2973+ if (symtab_hdr->sh_info != 0
2974+ && !symtab_hdr->contents
2975+ && !(symtab_hdr->contents =
2976+ (unsigned char *) bfd_elf_get_elf_syms (abfd, symtab_hdr,
2977+ symtab_hdr->sh_info,
2978+ 0, NULL, NULL, NULL)))
2979+ goto fail;
2980+
2981+ /* Get the value of the symbol referred to by the reloc. */
2982+ if (ELFNN_R_SYM (rel->r_info) < symtab_hdr->sh_info)
2983+ {
2984+ /* A local symbol. */
2985+ Elf_Internal_Sym *isym = ((Elf_Internal_Sym *) symtab_hdr->contents
2986+ + ELFNN_R_SYM (rel->r_info));
2987+
2988+ if (isym->st_shndx == SHN_UNDEF)
2989+ symval = sec_addr (sec) + rel->r_offset;
2990+ else
2991+ {
2992+ asection *isec;
2993+ BFD_ASSERT (isym->st_shndx < elf_numsections (abfd));
2994+ isec = elf_elfsections (abfd)[isym->st_shndx]->bfd_section;
2995+ if (sec_addr (isec) == 0)
2996+ continue;
2997+ symval = sec_addr (isec) + isym->st_value;
2998+ }
2999+ }
3000+ else
3001+ {
3002+ unsigned long indx;
3003+ struct elf_link_hash_entry *h;
3004+
3005+ indx = ELFNN_R_SYM (rel->r_info) - symtab_hdr->sh_info;
3006+ h = elf_sym_hashes (abfd)[indx];
3007+
3008+ while (h->root.type == bfd_link_hash_indirect
3009+ || h->root.type == bfd_link_hash_warning)
3010+ h = (struct elf_link_hash_entry *) h->root.u.i.link;
3011+
3012+ if (h->plt.offset != MINUS_ONE)
3013+ symval = sec_addr (htab->elf.splt) + h->plt.offset;
3014+ else if (h->root.type == bfd_link_hash_undefweak)
3015+ symval = 0;
3016+ else if (h->root.u.def.section->output_section == NULL
3017+ || (h->root.type != bfd_link_hash_defined
3018+ && h->root.type != bfd_link_hash_defweak))
3019+ continue;
3020+ else
3021+ symval = sec_addr (h->root.u.def.section) + h->root.u.def.value;
3022+ }
3023+
3024+ symval += rel->r_addend;
3025+
3026+ if (!relax_func (abfd, sec, info, rel, symval, again))
3027+ goto fail;
3028+ }
3029+
3030+ ret = TRUE;
3031+
3032+fail:
3033+ if (relocs != data->relocs)
3034+ free (relocs);
3035+
3036+ return ret;
3037+}
3038+
3039+#define ELF_ARCH bfd_arch_riscv
3040+#define ELF_TARGET_ID RISCV_ELF_DATA
3041+#define ELF_MACHINE_CODE EM_RISCV
3042+#define ELF_MAXPAGESIZE 0x2000
3043+#define ELF_COMMONPAGESIZE 0x2000
3044+
3045+#define TARGET_LITTLE_SYM riscv_elfNN_vec
3046+#define TARGET_LITTLE_NAME "elfNN-littleriscv"
3047+
3048+#define elf_backend_reloc_type_class riscv_reloc_type_class
3049+
3050+#define bfd_elfNN_bfd_reloc_name_lookup riscv_reloc_name_lookup
3051+#define bfd_elfNN_bfd_link_hash_table_create riscv_elf_link_hash_table_create
3052+#define bfd_elfNN_bfd_reloc_type_lookup riscv_reloc_type_lookup
3053+#define bfd_elfNN_bfd_merge_private_bfd_data \
3054+ _bfd_riscv_elf_merge_private_bfd_data
3055+
3056+#define elf_backend_copy_indirect_symbol riscv_elf_copy_indirect_symbol
3057+#define elf_backend_create_dynamic_sections riscv_elf_create_dynamic_sections
3058+#define elf_backend_check_relocs riscv_elf_check_relocs
3059+#define elf_backend_adjust_dynamic_symbol riscv_elf_adjust_dynamic_symbol
3060+#define elf_backend_size_dynamic_sections riscv_elf_size_dynamic_sections
3061+#define elf_backend_relocate_section riscv_elf_relocate_section
3062+#define elf_backend_finish_dynamic_symbol riscv_elf_finish_dynamic_symbol
3063+#define elf_backend_finish_dynamic_sections riscv_elf_finish_dynamic_sections
3064+#define elf_backend_gc_mark_hook riscv_elf_gc_mark_hook
3065+#define elf_backend_gc_sweep_hook riscv_elf_gc_sweep_hook
3066+#define elf_backend_plt_sym_val riscv_elf_plt_sym_val
3067+#define elf_info_to_howto_rel NULL
3068+#define elf_info_to_howto riscv_info_to_howto_rela
3069+#define bfd_elfNN_bfd_relax_section _bfd_riscv_relax_section
3070+
3071+#define elf_backend_init_index_section _bfd_elf_init_1_index_section
3072+
3073+#define elf_backend_can_gc_sections 1
3074+#define elf_backend_can_refcount 1
3075+#define elf_backend_want_got_plt 1
3076+#define elf_backend_plt_readonly 1
3077+#define elf_backend_plt_alignment 4
3078+#define elf_backend_want_plt_sym 1
3079+#define elf_backend_got_header_size (ARCH_SIZE / 8)
3080+#define elf_backend_rela_normal 1
3081+#define elf_backend_default_execstack 0
3082+
3083+#include "elfNN-target.h"
Patrick Georgiaf473ed2015-07-17 23:35:54 +02003084diff -urN empty/bfd/elfxx-riscv.c binutils-2.25/bfd/elfxx-riscv.c
Jonathan A. Kollasch64fc4332015-08-25 13:09:51 -05003085--- binutils-2.25/bfd/elfxx-riscv.c 1970-01-01 01:00:00.000000000 +0100
Patrick Georgiaf473ed2015-07-17 23:35:54 +02003086+++ binutils-2.25/bfd/elfxx-riscv.c 2015-07-18 00:02:36.218287546 +0200
3087@@ -0,0 +1,765 @@
Patrick Georgif0bbc952015-03-07 10:57:25 +01003088+/* RISC-V-specific support for ELF.
3089+ Copyright 2011-2014 Free Software Foundation, Inc.
3090+
3091+ Contributed by Andrew Waterman (waterman@cs.berkeley.edu) at UC Berkeley.
3092+ Based on TILE-Gx and MIPS targets.
3093+
3094+ This file is part of BFD, the Binary File Descriptor library.
3095+
3096+ This program is free software; you can redistribute it and/or modify
3097+ it under the terms of the GNU General Public License as published by
3098+ the Free Software Foundation; either version 3 of the License, or
3099+ (at your option) any later version.
3100+
3101+ This program is distributed in the hope that it will be useful,
3102+ but WITHOUT ANY WARRANTY; without even the implied warranty of
3103+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
3104+ GNU General Public License for more details.
3105+
3106+ You should have received a copy of the GNU General Public License
3107+ along with this program; if not, write to the Free Software
3108+ Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
3109+ MA 02110-1301, USA. */
3110+
3111+#include "sysdep.h"
3112+#include "bfd.h"
3113+#include "libbfd.h"
3114+#include "elf-bfd.h"
3115+#include "elf/riscv.h"
3116+#include "opcode/riscv.h"
3117+#include "libiberty.h"
3118+#include "elfxx-riscv.h"
3119+#include <stdint.h>
3120+
3121+#define MINUS_ONE ((bfd_vma)0 - 1)
3122+
3123+/* The relocation table used for SHT_RELA sections. */
3124+
3125+static reloc_howto_type howto_table[] =
3126+{
3127+ /* No relocation. */
3128+ HOWTO (R_RISCV_NONE, /* type */
3129+ 0, /* rightshift */
3130+ 0, /* size (0 = byte, 1 = short, 2 = long) */
3131+ 0, /* bitsize */
3132+ FALSE, /* pc_relative */
3133+ 0, /* bitpos */
3134+ complain_overflow_dont, /* complain_on_overflow */
3135+ bfd_elf_generic_reloc, /* special_function */
3136+ "R_RISCV_NONE", /* name */
3137+ FALSE, /* partial_inplace */
3138+ 0, /* src_mask */
3139+ 0, /* dst_mask */
3140+ FALSE), /* pcrel_offset */
3141+
3142+ /* 32 bit relocation. */
3143+ HOWTO (R_RISCV_32, /* type */
3144+ 0, /* rightshift */
3145+ 2, /* size (0 = byte, 1 = short, 2 = long) */
3146+ 32, /* bitsize */
3147+ FALSE, /* pc_relative */
3148+ 0, /* bitpos */
3149+ complain_overflow_dont, /* complain_on_overflow */
3150+ bfd_elf_generic_reloc, /* special_function */
3151+ "R_RISCV_32", /* name */
3152+ FALSE, /* partial_inplace */
3153+ 0, /* src_mask */
3154+ 0xffffffff, /* dst_mask */
3155+ FALSE), /* pcrel_offset */
3156+
3157+ /* 64 bit relocation. */
3158+ HOWTO (R_RISCV_64, /* type */
3159+ 0, /* rightshift */
3160+ 4, /* size (0 = byte, 1 = short, 2 = long) */
3161+ 64, /* bitsize */
3162+ FALSE, /* pc_relative */
3163+ 0, /* bitpos */
3164+ complain_overflow_dont, /* complain_on_overflow */
3165+ bfd_elf_generic_reloc, /* special_function */
3166+ "R_RISCV_64", /* name */
3167+ FALSE, /* partial_inplace */
3168+ 0, /* src_mask */
3169+ MINUS_ONE, /* dst_mask */
3170+ FALSE), /* pcrel_offset */
3171+
3172+ /* Relocation against a local symbol in a shared object. */
3173+ HOWTO (R_RISCV_RELATIVE, /* type */
3174+ 0, /* rightshift */
3175+ 2, /* size (0 = byte, 1 = short, 2 = long) */
3176+ 32, /* bitsize */
3177+ FALSE, /* pc_relative */
3178+ 0, /* bitpos */
3179+ complain_overflow_dont, /* complain_on_overflow */
3180+ bfd_elf_generic_reloc, /* special_function */
3181+ "R_RISCV_RELATIVE", /* name */
3182+ FALSE, /* partial_inplace */
3183+ 0, /* src_mask */
3184+ 0xffffffff, /* dst_mask */
3185+ FALSE), /* pcrel_offset */
3186+
3187+ HOWTO (R_RISCV_COPY, /* type */
3188+ 0, /* rightshift */
3189+ 0, /* this one is variable size */
3190+ 0, /* bitsize */
3191+ FALSE, /* pc_relative */
3192+ 0, /* bitpos */
3193+ complain_overflow_bitfield, /* complain_on_overflow */
3194+ bfd_elf_generic_reloc, /* special_function */
3195+ "R_RISCV_COPY", /* name */
3196+ FALSE, /* partial_inplace */
3197+ 0x0, /* src_mask */
3198+ 0x0, /* dst_mask */
3199+ FALSE), /* pcrel_offset */
3200+
3201+ HOWTO (R_RISCV_JUMP_SLOT, /* type */
3202+ 0, /* rightshift */
3203+ 4, /* size (0 = byte, 1 = short, 2 = long) */
3204+ 64, /* bitsize */
3205+ FALSE, /* pc_relative */
3206+ 0, /* bitpos */
3207+ complain_overflow_bitfield, /* complain_on_overflow */
3208+ bfd_elf_generic_reloc, /* special_function */
3209+ "R_RISCV_JUMP_SLOT", /* name */
3210+ FALSE, /* partial_inplace */
3211+ 0x0, /* src_mask */
3212+ 0x0, /* dst_mask */
3213+ FALSE), /* pcrel_offset */
3214+
3215+ /* Dynamic TLS relocations. */
3216+ HOWTO (R_RISCV_TLS_DTPMOD32, /* type */
3217+ 0, /* rightshift */
3218+ 4, /* size (0 = byte, 1 = short, 2 = long) */
3219+ 32, /* bitsize */
3220+ FALSE, /* pc_relative */
3221+ 0, /* bitpos */
3222+ complain_overflow_dont, /* complain_on_overflow */
3223+ bfd_elf_generic_reloc, /* special_function */
3224+ "R_RISCV_TLS_DTPMOD32", /* name */
3225+ FALSE, /* partial_inplace */
3226+ MINUS_ONE, /* src_mask */
3227+ MINUS_ONE, /* dst_mask */
3228+ FALSE), /* pcrel_offset */
3229+
3230+ HOWTO (R_RISCV_TLS_DTPMOD64, /* type */
3231+ 0, /* rightshift */
3232+ 4, /* size (0 = byte, 1 = short, 2 = long) */
3233+ 64, /* bitsize */
3234+ FALSE, /* pc_relative */
3235+ 0, /* bitpos */
3236+ complain_overflow_dont, /* complain_on_overflow */
3237+ bfd_elf_generic_reloc, /* special_function */
3238+ "R_RISCV_TLS_DTPMOD64", /* name */
3239+ FALSE, /* partial_inplace */
3240+ MINUS_ONE, /* src_mask */
3241+ MINUS_ONE, /* dst_mask */
3242+ FALSE), /* pcrel_offset */
3243+
3244+ HOWTO (R_RISCV_TLS_DTPREL32, /* type */
3245+ 0, /* rightshift */
3246+ 4, /* size (0 = byte, 1 = short, 2 = long) */
3247+ 32, /* bitsize */
3248+ FALSE, /* pc_relative */
3249+ 0, /* bitpos */
3250+ complain_overflow_dont, /* complain_on_overflow */
3251+ bfd_elf_generic_reloc, /* special_function */
3252+ "R_RISCV_TLS_DTPREL32", /* name */
3253+ TRUE, /* partial_inplace */
3254+ MINUS_ONE, /* src_mask */
3255+ MINUS_ONE, /* dst_mask */
3256+ FALSE), /* pcrel_offset */
3257+
3258+ HOWTO (R_RISCV_TLS_DTPREL64, /* type */
3259+ 0, /* rightshift */
3260+ 4, /* size (0 = byte, 1 = short, 2 = long) */
3261+ 64, /* bitsize */
3262+ FALSE, /* pc_relative */
3263+ 0, /* bitpos */
3264+ complain_overflow_dont, /* complain_on_overflow */
3265+ bfd_elf_generic_reloc, /* special_function */
3266+ "R_RISCV_TLS_DTPREL64", /* name */
3267+ TRUE, /* partial_inplace */
3268+ MINUS_ONE, /* src_mask */
3269+ MINUS_ONE, /* dst_mask */
3270+ FALSE), /* pcrel_offset */
3271+
3272+ HOWTO (R_RISCV_TLS_TPREL32, /* type */
3273+ 0, /* rightshift */
3274+ 2, /* size (0 = byte, 1 = short, 2 = long) */
3275+ 32, /* bitsize */
3276+ FALSE, /* pc_relative */
3277+ 0, /* bitpos */
3278+ complain_overflow_dont, /* complain_on_overflow */
3279+ bfd_elf_generic_reloc, /* special_function */
3280+ "R_RISCV_TLS_TPREL32", /* name */
3281+ FALSE, /* partial_inplace */
3282+ MINUS_ONE, /* src_mask */
3283+ MINUS_ONE, /* dst_mask */
3284+ FALSE), /* pcrel_offset */
3285+
3286+ HOWTO (R_RISCV_TLS_TPREL64, /* type */
3287+ 0, /* rightshift */
3288+ 4, /* size (0 = byte, 1 = short, 2 = long) */
3289+ 64, /* bitsize */
3290+ FALSE, /* pc_relative */
3291+ 0, /* bitpos */
3292+ complain_overflow_dont, /* complain_on_overflow */
3293+ bfd_elf_generic_reloc, /* special_function */
3294+ "R_RISCV_TLS_TPREL64", /* name */
3295+ FALSE, /* partial_inplace */
3296+ MINUS_ONE, /* src_mask */
3297+ MINUS_ONE, /* dst_mask */
3298+ FALSE), /* pcrel_offset */
3299+
3300+ EMPTY_HOWTO (12),
3301+ EMPTY_HOWTO (13),
3302+ EMPTY_HOWTO (14),
3303+ EMPTY_HOWTO (15),
3304+
3305+ /* 12-bit PC-relative branch offset. */
3306+ HOWTO (R_RISCV_BRANCH, /* type */
3307+ 0, /* rightshift */
3308+ 2, /* size (0 = byte, 1 = short, 2 = long) */
3309+ 32, /* bitsize */
3310+ TRUE, /* pc_relative */
3311+ 0, /* bitpos */
3312+ complain_overflow_signed, /* complain_on_overflow */
3313+ bfd_elf_generic_reloc, /* special_function */
3314+ "R_RISCV_BRANCH", /* name */
3315+ FALSE, /* partial_inplace */
3316+ 0, /* src_mask */
3317+ ENCODE_SBTYPE_IMM(-1U),/* dst_mask */
3318+ TRUE), /* pcrel_offset */
3319+
3320+ /* 20-bit PC-relative jump offset. */
3321+ HOWTO (R_RISCV_JAL, /* type */
3322+ 0, /* rightshift */
3323+ 2, /* size (0 = byte, 1 = short, 2 = long) */
3324+ 32, /* bitsize */
3325+ TRUE, /* pc_relative */
3326+ 0, /* bitpos */
3327+ complain_overflow_dont, /* complain_on_overflow */
3328+ /* This needs complex overflow
3329+ detection, because the upper 36
3330+ bits must match the PC + 4. */
3331+ bfd_elf_generic_reloc, /* special_function */
3332+ "R_RISCV_JAL", /* name */
3333+ FALSE, /* partial_inplace */
3334+ 0, /* src_mask */
3335+ ENCODE_UJTYPE_IMM(-1U), /* dst_mask */
3336+ TRUE), /* pcrel_offset */
3337+
3338+ /* 32-bit PC-relative function call (AUIPC/JALR). */
3339+ HOWTO (R_RISCV_CALL, /* type */
3340+ 0, /* rightshift */
3341+ 2, /* size (0 = byte, 1 = short, 2 = long) */
3342+ 64, /* bitsize */
3343+ TRUE, /* pc_relative */
3344+ 0, /* bitpos */
3345+ complain_overflow_dont, /* complain_on_overflow */
3346+ bfd_elf_generic_reloc, /* special_function */
3347+ "R_RISCV_CALL", /* name */
3348+ FALSE, /* partial_inplace */
3349+ 0, /* src_mask */
3350+ ENCODE_UTYPE_IMM(-1U) | ((bfd_vma) ENCODE_ITYPE_IMM(-1U) << 32), /* dst_mask */
3351+ TRUE), /* pcrel_offset */
3352+
3353+ /* 32-bit PC-relative function call (AUIPC/JALR). */
3354+ HOWTO (R_RISCV_CALL_PLT, /* type */
3355+ 0, /* rightshift */
3356+ 2, /* size (0 = byte, 1 = short, 2 = long) */
3357+ 64, /* bitsize */
3358+ TRUE, /* pc_relative */
3359+ 0, /* bitpos */
3360+ complain_overflow_dont, /* complain_on_overflow */
3361+ bfd_elf_generic_reloc, /* special_function */
3362+ "R_RISCV_CALL_PLT", /* name */
3363+ FALSE, /* partial_inplace */
3364+ 0, /* src_mask */
3365+ ENCODE_UTYPE_IMM(-1U) | ((bfd_vma) ENCODE_ITYPE_IMM(-1U) << 32), /* dst_mask */
3366+ TRUE), /* pcrel_offset */
3367+
3368+ /* High 20 bits of 32-bit PC-relative GOT access. */
3369+ HOWTO (R_RISCV_GOT_HI20, /* type */
3370+ 0, /* rightshift */
3371+ 2, /* size (0 = byte, 1 = short, 2 = long) */
3372+ 32, /* bitsize */
3373+ TRUE, /* pc_relative */
3374+ 0, /* bitpos */
3375+ complain_overflow_dont, /* complain_on_overflow */
3376+ bfd_elf_generic_reloc, /* special_function */
3377+ "R_RISCV_GOT_HI20", /* name */
3378+ FALSE, /* partial_inplace */
3379+ 0, /* src_mask */
3380+ ENCODE_UTYPE_IMM(-1U), /* dst_mask */
3381+ FALSE), /* pcrel_offset */
3382+
3383+ /* High 20 bits of 32-bit PC-relative TLS IE GOT access. */
3384+ HOWTO (R_RISCV_TLS_GOT_HI20, /* type */
3385+ 0, /* rightshift */
3386+ 2, /* size (0 = byte, 1 = short, 2 = long) */
3387+ 32, /* bitsize */
3388+ TRUE, /* pc_relative */
3389+ 0, /* bitpos */
3390+ complain_overflow_dont, /* complain_on_overflow */
3391+ bfd_elf_generic_reloc, /* special_function */
3392+ "R_RISCV_TLS_GOT_HI20", /* name */
3393+ FALSE, /* partial_inplace */
3394+ 0, /* src_mask */
3395+ ENCODE_UTYPE_IMM(-1U), /* dst_mask */
3396+ FALSE), /* pcrel_offset */
3397+
3398+ /* High 20 bits of 32-bit PC-relative TLS GD GOT reference. */
3399+ HOWTO (R_RISCV_TLS_GD_HI20, /* type */
3400+ 0, /* rightshift */
3401+ 2, /* size (0 = byte, 1 = short, 2 = long) */
3402+ 32, /* bitsize */
3403+ TRUE, /* pc_relative */
3404+ 0, /* bitpos */
3405+ complain_overflow_dont, /* complain_on_overflow */
3406+ bfd_elf_generic_reloc, /* special_function */
3407+ "R_RISCV_TLS_GD_HI20", /* name */
3408+ FALSE, /* partial_inplace */
3409+ 0, /* src_mask */
3410+ ENCODE_UTYPE_IMM(-1U), /* dst_mask */
3411+ FALSE), /* pcrel_offset */
3412+
3413+ /* High 20 bits of 32-bit PC-relative reference. */
3414+ HOWTO (R_RISCV_PCREL_HI20, /* type */
3415+ 0, /* rightshift */
3416+ 2, /* size (0 = byte, 1 = short, 2 = long) */
3417+ 32, /* bitsize */
3418+ TRUE, /* pc_relative */
3419+ 0, /* bitpos */
3420+ complain_overflow_dont, /* complain_on_overflow */
3421+ bfd_elf_generic_reloc, /* special_function */
3422+ "R_RISCV_PCREL_HI20", /* name */
3423+ FALSE, /* partial_inplace */
3424+ 0, /* src_mask */
3425+ ENCODE_UTYPE_IMM(-1U), /* dst_mask */
3426+ TRUE), /* pcrel_offset */
3427+
3428+ /* Low 12 bits of a 32-bit PC-relative load or add. */
3429+ HOWTO (R_RISCV_PCREL_LO12_I, /* type */
3430+ 0, /* rightshift */
3431+ 2, /* size (0 = byte, 1 = short, 2 = long) */
3432+ 32, /* bitsize */
3433+ FALSE, /* pc_relative */
3434+ 0, /* bitpos */
3435+ complain_overflow_dont, /* complain_on_overflow */
3436+ bfd_elf_generic_reloc, /* special_function */
3437+ "R_RISCV_PCREL_LO12_I",/* name */
3438+ FALSE, /* partial_inplace */
3439+ 0, /* src_mask */
3440+ ENCODE_ITYPE_IMM(-1U), /* dst_mask */
3441+ FALSE), /* pcrel_offset */
3442+
3443+ /* Low 12 bits of a 32-bit PC-relative store. */
3444+ HOWTO (R_RISCV_PCREL_LO12_S, /* type */
3445+ 0, /* rightshift */
3446+ 2, /* size (0 = byte, 1 = short, 2 = long) */
3447+ 32, /* bitsize */
3448+ FALSE, /* pc_relative */
3449+ 0, /* bitpos */
3450+ complain_overflow_dont, /* complain_on_overflow */
3451+ bfd_elf_generic_reloc, /* special_function */
3452+ "R_RISCV_PCREL_LO12_S",/* name */
3453+ FALSE, /* partial_inplace */
3454+ 0, /* src_mask */
3455+ ENCODE_STYPE_IMM(-1U), /* dst_mask */
3456+ FALSE), /* pcrel_offset */
3457+
3458+ /* High 20 bits of 32-bit absolute address. */
3459+ HOWTO (R_RISCV_HI20, /* type */
3460+ 0, /* rightshift */
3461+ 2, /* size (0 = byte, 1 = short, 2 = long) */
3462+ 32, /* bitsize */
3463+ FALSE, /* pc_relative */
3464+ 0, /* bitpos */
3465+ complain_overflow_dont, /* complain_on_overflow */
3466+ bfd_elf_generic_reloc, /* special_function */
3467+ "R_RISCV_HI20", /* name */
3468+ FALSE, /* partial_inplace */
3469+ 0, /* src_mask */
3470+ ENCODE_UTYPE_IMM(-1U), /* dst_mask */
3471+ FALSE), /* pcrel_offset */
3472+
3473+ /* High 12 bits of 32-bit load or add. */
3474+ HOWTO (R_RISCV_LO12_I, /* type */
3475+ 0, /* rightshift */
3476+ 2, /* size (0 = byte, 1 = short, 2 = long) */
3477+ 32, /* bitsize */
3478+ FALSE, /* pc_relative */
3479+ 0, /* bitpos */
3480+ complain_overflow_dont, /* complain_on_overflow */
3481+ bfd_elf_generic_reloc, /* special_function */
3482+ "R_RISCV_LO12_I", /* name */
3483+ FALSE, /* partial_inplace */
3484+ 0, /* src_mask */
3485+ ENCODE_ITYPE_IMM(-1U), /* dst_mask */
3486+ FALSE), /* pcrel_offset */
3487+
3488+ /* High 12 bits of 32-bit store. */
3489+ HOWTO (R_RISCV_LO12_S, /* type */
3490+ 0, /* rightshift */
3491+ 2, /* size (0 = byte, 1 = short, 2 = long) */
3492+ 32, /* bitsize */
3493+ FALSE, /* pc_relative */
3494+ 0, /* bitpos */
3495+ complain_overflow_dont, /* complain_on_overflow */
3496+ bfd_elf_generic_reloc, /* special_function */
3497+ "R_RISCV_LO12_S", /* name */
3498+ FALSE, /* partial_inplace */
3499+ 0, /* src_mask */
3500+ ENCODE_STYPE_IMM(-1U), /* dst_mask */
3501+ FALSE), /* pcrel_offset */
3502+
3503+ /* High 20 bits of TLS LE thread pointer offset. */
3504+ HOWTO (R_RISCV_TPREL_HI20, /* type */
3505+ 0, /* rightshift */
3506+ 2, /* size (0 = byte, 1 = short, 2 = long) */
3507+ 32, /* bitsize */
3508+ FALSE, /* pc_relative */
3509+ 0, /* bitpos */
3510+ complain_overflow_signed, /* complain_on_overflow */
3511+ bfd_elf_generic_reloc, /* special_function */
3512+ "R_RISCV_TPREL_HI20", /* name */
3513+ TRUE, /* partial_inplace */
3514+ 0, /* src_mask */
3515+ ENCODE_UTYPE_IMM(-1U), /* dst_mask */
3516+ FALSE), /* pcrel_offset */
3517+
3518+ /* Low 12 bits of TLS LE thread pointer offset for loads and adds. */
3519+ HOWTO (R_RISCV_TPREL_LO12_I, /* type */
3520+ 0, /* rightshift */
3521+ 2, /* size (0 = byte, 1 = short, 2 = long) */
3522+ 32, /* bitsize */
3523+ FALSE, /* pc_relative */
3524+ 0, /* bitpos */
3525+ complain_overflow_signed, /* complain_on_overflow */
3526+ bfd_elf_generic_reloc, /* special_function */
3527+ "R_RISCV_TPREL_LO12_I",/* name */
3528+ FALSE, /* partial_inplace */
3529+ 0, /* src_mask */
3530+ ENCODE_ITYPE_IMM(-1U), /* dst_mask */
3531+ FALSE), /* pcrel_offset */
3532+
3533+ /* Low 12 bits of TLS LE thread pointer offset for stores. */
3534+ HOWTO (R_RISCV_TPREL_LO12_S, /* type */
3535+ 0, /* rightshift */
3536+ 2, /* size (0 = byte, 1 = short, 2 = long) */
3537+ 32, /* bitsize */
3538+ FALSE, /* pc_relative */
3539+ 0, /* bitpos */
3540+ complain_overflow_signed, /* complain_on_overflow */
3541+ bfd_elf_generic_reloc, /* special_function */
3542+ "R_RISCV_TPREL_LO12_S",/* name */
3543+ FALSE, /* partial_inplace */
3544+ 0, /* src_mask */
3545+ ENCODE_STYPE_IMM(-1U), /* dst_mask */
3546+ FALSE), /* pcrel_offset */
3547+
3548+ /* TLS LE thread pointer usage. */
3549+ HOWTO (R_RISCV_TPREL_ADD, /* type */
3550+ 0, /* rightshift */
3551+ 2, /* size (0 = byte, 1 = short, 2 = long) */
3552+ 32, /* bitsize */
3553+ FALSE, /* pc_relative */
3554+ 0, /* bitpos */
3555+ complain_overflow_dont,/* complain_on_overflow */
3556+ bfd_elf_generic_reloc, /* special_function */
3557+ "R_RISCV_TPREL_ADD", /* name */
3558+ TRUE, /* partial_inplace */
3559+ 0, /* src_mask */
3560+ 0, /* dst_mask */
3561+ FALSE), /* pcrel_offset */
3562+
3563+ /* 8-bit in-place addition, for local label subtraction. */
3564+ HOWTO (R_RISCV_ADD8, /* type */
3565+ 0, /* rightshift */
3566+ 0, /* size (0 = byte, 1 = short, 2 = long) */
3567+ 32, /* bitsize */
3568+ FALSE, /* pc_relative */
3569+ 0, /* bitpos */
3570+ complain_overflow_dont, /* complain_on_overflow */
3571+ bfd_elf_generic_reloc, /* special_function */
3572+ "R_RISCV_ADD8", /* name */
3573+ FALSE, /* partial_inplace */
3574+ 0, /* src_mask */
3575+ MINUS_ONE, /* dst_mask */
3576+ FALSE), /* pcrel_offset */
3577+
3578+ /* 16-bit in-place addition, for local label subtraction. */
3579+ HOWTO (R_RISCV_ADD16, /* type */
3580+ 0, /* rightshift */
3581+ 1, /* size (0 = byte, 1 = short, 2 = long) */
3582+ 16, /* bitsize */
3583+ FALSE, /* pc_relative */
3584+ 0, /* bitpos */
3585+ complain_overflow_dont, /* complain_on_overflow */
3586+ bfd_elf_generic_reloc, /* special_function */
3587+ "R_RISCV_ADD16", /* name */
3588+ FALSE, /* partial_inplace */
3589+ 0, /* src_mask */
3590+ MINUS_ONE, /* dst_mask */
3591+ FALSE), /* pcrel_offset */
3592+
3593+ /* 32-bit in-place addition, for local label subtraction. */
3594+ HOWTO (R_RISCV_ADD32, /* type */
3595+ 0, /* rightshift */
3596+ 2, /* size (0 = byte, 1 = short, 2 = long) */
3597+ 32, /* bitsize */
3598+ FALSE, /* pc_relative */
3599+ 0, /* bitpos */
3600+ complain_overflow_dont, /* complain_on_overflow */
3601+ bfd_elf_generic_reloc, /* special_function */
3602+ "R_RISCV_ADD32", /* name */
3603+ FALSE, /* partial_inplace */
3604+ 0, /* src_mask */
3605+ MINUS_ONE, /* dst_mask */
3606+ FALSE), /* pcrel_offset */
3607+
3608+ /* 64-bit in-place addition, for local label subtraction. */
3609+ HOWTO (R_RISCV_ADD64, /* type */
3610+ 0, /* rightshift */
3611+ 4, /* size (0 = byte, 1 = short, 2 = long) */
3612+ 64, /* bitsize */
3613+ FALSE, /* pc_relative */
3614+ 0, /* bitpos */
3615+ complain_overflow_dont, /* complain_on_overflow */
3616+ bfd_elf_generic_reloc, /* special_function */
3617+ "R_RISCV_ADD64", /* name */
3618+ FALSE, /* partial_inplace */
3619+ 0, /* src_mask */
3620+ MINUS_ONE, /* dst_mask */
3621+ FALSE), /* pcrel_offset */
3622+
3623+ /* 8-bit in-place addition, for local label subtraction. */
3624+ HOWTO (R_RISCV_SUB8, /* type */
3625+ 0, /* rightshift */
3626+ 0, /* size (0 = byte, 1 = short, 2 = long) */
3627+ 8, /* bitsize */
3628+ FALSE, /* pc_relative */
3629+ 0, /* bitpos */
3630+ complain_overflow_dont, /* complain_on_overflow */
3631+ bfd_elf_generic_reloc, /* special_function */
3632+ "R_RISCV_SUB8", /* name */
3633+ FALSE, /* partial_inplace */
3634+ 0, /* src_mask */
3635+ MINUS_ONE, /* dst_mask */
3636+ FALSE), /* pcrel_offset */
3637+
3638+ /* 16-bit in-place addition, for local label subtraction. */
3639+ HOWTO (R_RISCV_SUB16, /* type */
3640+ 0, /* rightshift */
3641+ 1, /* size (0 = byte, 1 = short, 2 = long) */
3642+ 16, /* bitsize */
3643+ FALSE, /* pc_relative */
3644+ 0, /* bitpos */
3645+ complain_overflow_dont, /* complain_on_overflow */
3646+ bfd_elf_generic_reloc, /* special_function */
3647+ "R_RISCV_SUB16", /* name */
3648+ FALSE, /* partial_inplace */
3649+ 0, /* src_mask */
3650+ MINUS_ONE, /* dst_mask */
3651+ FALSE), /* pcrel_offset */
3652+
3653+ /* 32-bit in-place addition, for local label subtraction. */
3654+ HOWTO (R_RISCV_SUB32, /* type */
3655+ 0, /* rightshift */
3656+ 2, /* size (0 = byte, 1 = short, 2 = long) */
3657+ 32, /* bitsize */
3658+ FALSE, /* pc_relative */
3659+ 0, /* bitpos */
3660+ complain_overflow_dont, /* complain_on_overflow */
3661+ bfd_elf_generic_reloc, /* special_function */
3662+ "R_RISCV_SUB32", /* name */
3663+ FALSE, /* partial_inplace */
3664+ 0, /* src_mask */
3665+ MINUS_ONE, /* dst_mask */
3666+ FALSE), /* pcrel_offset */
3667+
3668+ /* 64-bit in-place addition, for local label subtraction. */
3669+ HOWTO (R_RISCV_SUB64, /* type */
3670+ 0, /* rightshift */
3671+ 4, /* size (0 = byte, 1 = short, 2 = long) */
3672+ 64, /* bitsize */
3673+ FALSE, /* pc_relative */
3674+ 0, /* bitpos */
3675+ complain_overflow_dont, /* complain_on_overflow */
3676+ bfd_elf_generic_reloc, /* special_function */
3677+ "R_RISCV_SUB64", /* name */
3678+ FALSE, /* partial_inplace */
3679+ 0, /* src_mask */
3680+ MINUS_ONE, /* dst_mask */
3681+ FALSE), /* pcrel_offset */
3682+
3683+ /* GNU extension to record C++ vtable hierarchy */
3684+ HOWTO (R_RISCV_GNU_VTINHERIT, /* type */
3685+ 0, /* rightshift */
3686+ 4, /* size (0 = byte, 1 = short, 2 = long) */
3687+ 0, /* bitsize */
3688+ FALSE, /* pc_relative */
3689+ 0, /* bitpos */
3690+ complain_overflow_dont,/* complain_on_overflow */
3691+ NULL, /* special_function */
3692+ "R_RISCV_GNU_VTINHERIT", /* name */
3693+ FALSE, /* partial_inplace */
3694+ 0, /* src_mask */
3695+ 0, /* dst_mask */
3696+ FALSE), /* pcrel_offset */
3697+
3698+ /* GNU extension to record C++ vtable member usage */
3699+ HOWTO (R_RISCV_GNU_VTENTRY, /* type */
3700+ 0, /* rightshift */
3701+ 4, /* size (0 = byte, 1 = short, 2 = long) */
3702+ 0, /* bitsize */
3703+ FALSE, /* pc_relative */
3704+ 0, /* bitpos */
3705+ complain_overflow_dont,/* complain_on_overflow */
3706+ _bfd_elf_rel_vtable_reloc_fn, /* special_function */
3707+ "R_RISCV_GNU_VTENTRY", /* name */
3708+ FALSE, /* partial_inplace */
3709+ 0, /* src_mask */
3710+ 0, /* dst_mask */
3711+ FALSE), /* pcrel_offset */
3712+
3713+ /* Indicates an alignment statement. The addend field encodes how many
3714+ bytes of NOPs follow the statement. The desired alignment is the
3715+ addend rounded up to the next power of two. */
3716+ HOWTO (R_RISCV_ALIGN, /* type */
3717+ 0, /* rightshift */
3718+ 2, /* size (0 = byte, 1 = short, 2 = long) */
3719+ 0, /* bitsize */
3720+ FALSE, /* pc_relative */
3721+ 0, /* bitpos */
3722+ complain_overflow_dont, /* complain_on_overflow */
3723+ bfd_elf_generic_reloc, /* special_function */
3724+ "R_RISCV_ALIGN", /* name */
3725+ FALSE, /* partial_inplace */
3726+ 0, /* src_mask */
3727+ 0, /* dst_mask */
3728+ TRUE), /* pcrel_offset */
Patrick Georgiaf473ed2015-07-17 23:35:54 +02003729+
3730+ /* 8-bit PC-relative branch offset. */
3731+ HOWTO (R_RISCV_RVC_BRANCH, /* type */
3732+ 0, /* rightshift */
3733+ 2, /* size (0 = byte, 1 = short, 2 = long) */
3734+ 32, /* bitsize */
3735+ TRUE, /* pc_relative */
3736+ 0, /* bitpos */
3737+ complain_overflow_signed, /* complain_on_overflow */
3738+ bfd_elf_generic_reloc, /* special_function */
3739+ "R_RISCV_RVC_BRANCH", /* name */
3740+ FALSE, /* partial_inplace */
3741+ 0, /* src_mask */
3742+ ENCODE_RVC_B_IMM(-1U), /* dst_mask */
3743+ TRUE), /* pcrel_offset */
3744+
3745+ /* 11-bit PC-relative jump offset. */
3746+ HOWTO (R_RISCV_RVC_JUMP, /* type */
3747+ 0, /* rightshift */
3748+ 2, /* size (0 = byte, 1 = short, 2 = long) */
3749+ 32, /* bitsize */
3750+ TRUE, /* pc_relative */
3751+ 0, /* bitpos */
3752+ complain_overflow_dont, /* complain_on_overflow */
3753+ /* This needs complex overflow
3754+ detection, because the upper 36
3755+ bits must match the PC + 4. */
3756+ bfd_elf_generic_reloc, /* special_function */
3757+ "R_RISCV_RVC_JUMP", /* name */
3758+ FALSE, /* partial_inplace */
3759+ 0, /* src_mask */
3760+ ENCODE_RVC_J_IMM(-1U), /* dst_mask */
3761+ TRUE), /* pcrel_offset */
Patrick Georgif0bbc952015-03-07 10:57:25 +01003762+};
3763+
3764+/* A mapping from BFD reloc types to RISC-V ELF reloc types. */
3765+
3766+struct elf_reloc_map {
3767+ bfd_reloc_code_real_type bfd_val;
3768+ enum elf_riscv_reloc_type elf_val;
3769+};
3770+
3771+static const struct elf_reloc_map riscv_reloc_map[] =
3772+{
3773+ { BFD_RELOC_NONE, R_RISCV_NONE },
3774+ { BFD_RELOC_32, R_RISCV_32 },
3775+ { BFD_RELOC_64, R_RISCV_64 },
3776+ { BFD_RELOC_RISCV_ADD8, R_RISCV_ADD8 },
3777+ { BFD_RELOC_RISCV_ADD16, R_RISCV_ADD16 },
3778+ { BFD_RELOC_RISCV_ADD32, R_RISCV_ADD32 },
3779+ { BFD_RELOC_RISCV_ADD64, R_RISCV_ADD64 },
3780+ { BFD_RELOC_RISCV_SUB8, R_RISCV_SUB8 },
3781+ { BFD_RELOC_RISCV_SUB16, R_RISCV_SUB16 },
3782+ { BFD_RELOC_RISCV_SUB32, R_RISCV_SUB32 },
3783+ { BFD_RELOC_RISCV_SUB64, R_RISCV_SUB64 },
3784+ { BFD_RELOC_CTOR, R_RISCV_64 },
3785+ { BFD_RELOC_12_PCREL, R_RISCV_BRANCH },
3786+ { BFD_RELOC_RISCV_HI20, R_RISCV_HI20 },
3787+ { BFD_RELOC_RISCV_LO12_I, R_RISCV_LO12_I },
3788+ { BFD_RELOC_RISCV_LO12_S, R_RISCV_LO12_S },
3789+ { BFD_RELOC_RISCV_PCREL_LO12_I, R_RISCV_PCREL_LO12_I },
3790+ { BFD_RELOC_RISCV_PCREL_LO12_S, R_RISCV_PCREL_LO12_S },
3791+ { BFD_RELOC_RISCV_CALL, R_RISCV_CALL },
3792+ { BFD_RELOC_RISCV_CALL_PLT, R_RISCV_CALL_PLT },
3793+ { BFD_RELOC_RISCV_PCREL_HI20, R_RISCV_PCREL_HI20 },
3794+ { BFD_RELOC_RISCV_JMP, R_RISCV_JAL },
3795+ { BFD_RELOC_RISCV_GOT_HI20, R_RISCV_GOT_HI20 },
3796+ { BFD_RELOC_RISCV_TLS_DTPMOD32, R_RISCV_TLS_DTPMOD32 },
3797+ { BFD_RELOC_RISCV_TLS_DTPREL32, R_RISCV_TLS_DTPREL32 },
3798+ { BFD_RELOC_RISCV_TLS_DTPMOD64, R_RISCV_TLS_DTPMOD64 },
3799+ { BFD_RELOC_RISCV_TLS_DTPREL64, R_RISCV_TLS_DTPREL64 },
3800+ { BFD_RELOC_RISCV_TLS_TPREL32, R_RISCV_TLS_TPREL32 },
3801+ { BFD_RELOC_RISCV_TLS_TPREL64, R_RISCV_TLS_TPREL64 },
3802+ { BFD_RELOC_RISCV_TPREL_HI20, R_RISCV_TPREL_HI20 },
3803+ { BFD_RELOC_RISCV_TPREL_ADD, R_RISCV_TPREL_ADD },
3804+ { BFD_RELOC_RISCV_TPREL_LO12_S, R_RISCV_TPREL_LO12_S },
3805+ { BFD_RELOC_RISCV_TPREL_LO12_I, R_RISCV_TPREL_LO12_I },
3806+ { BFD_RELOC_RISCV_TLS_GOT_HI20, R_RISCV_TLS_GOT_HI20 },
3807+ { BFD_RELOC_RISCV_TLS_GD_HI20, R_RISCV_TLS_GD_HI20 },
3808+ { BFD_RELOC_RISCV_ALIGN, R_RISCV_ALIGN },
Patrick Georgiaf473ed2015-07-17 23:35:54 +02003809+ { BFD_RELOC_RISCV_RVC_BRANCH, R_RISCV_RVC_BRANCH },
3810+ { BFD_RELOC_RISCV_RVC_JUMP, R_RISCV_RVC_JUMP },
Patrick Georgif0bbc952015-03-07 10:57:25 +01003811+};
3812+
3813+/* Given a BFD reloc type, return a howto structure. */
3814+
3815+reloc_howto_type *
3816+riscv_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED,
3817+ bfd_reloc_code_real_type code)
3818+{
3819+ unsigned int i;
3820+
3821+ for (i = 0; i < ARRAY_SIZE (riscv_reloc_map); i++)
3822+ if (riscv_reloc_map[i].bfd_val == code)
3823+ return &howto_table[(int) riscv_reloc_map[i].elf_val];
3824+
3825+ bfd_set_error (bfd_error_bad_value);
3826+ return NULL;
3827+}
3828+
3829+reloc_howto_type *
3830+riscv_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED,
3831+ const char *r_name)
3832+{
3833+ unsigned int i;
3834+
3835+ for (i = 0; i < ARRAY_SIZE (howto_table); i++)
3836+ if (howto_table[i].name && strcasecmp (howto_table[i].name, r_name) == 0)
3837+ return &howto_table[i];
3838+
3839+ return NULL;
3840+}
3841+
3842+reloc_howto_type *
3843+riscv_elf_rtype_to_howto (unsigned int r_type)
3844+{
3845+ if ((unsigned int)r_type >= ARRAY_SIZE (howto_table))
3846+ {
3847+ (*_bfd_error_handler)(_("unrecognized relocation (0x%x)"), r_type);
3848+ bfd_set_error (bfd_error_bad_value);
3849+ return NULL;
3850+ }
3851+ return &howto_table[r_type];
3852+}
Patrick Georgiaf473ed2015-07-17 23:35:54 +02003853diff -urN empty/bfd/elfxx-riscv.h binutils-2.25/bfd/elfxx-riscv.h
Jonathan A. Kollasch64fc4332015-08-25 13:09:51 -05003854--- binutils-2.25/bfd/elfxx-riscv.h 1970-01-01 01:00:00.000000000 +0100
Patrick Georgiaf473ed2015-07-17 23:35:54 +02003855+++ binutils-2.25/bfd/elfxx-riscv.h 2015-07-18 00:02:36.218287546 +0200
Patrick Georgif0bbc952015-03-07 10:57:25 +01003856@@ -0,0 +1,34 @@
3857+/* RISC-V ELF specific backend routines.
3858+ Copyright 2011-2014 Free Software Foundation, Inc.
3859+
3860+ Contributed by Andrew Waterman (waterman@cs.berkeley.edu) at UC Berkeley.
3861+ Based on MIPS target.
3862+
3863+ This file is part of BFD, the Binary File Descriptor library.
3864+
3865+ This program is free software; you can redistribute it and/or modify
3866+ it under the terms of the GNU General Public License as published by
3867+ the Free Software Foundation; either version 3 of the License, or
3868+ (at your option) any later version.
3869+
3870+ This program is distributed in the hope that it will be useful,
3871+ but WITHOUT ANY WARRANTY; without even the implied warranty of
3872+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
3873+ GNU General Public License for more details.
3874+
3875+ You should have received a copy of the GNU General Public License
3876+ along with this program; if not, write to the Free Software
3877+ Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
3878+ MA 02110-1301, USA. */
3879+
3880+#include "elf/common.h"
3881+#include "elf/internal.h"
3882+
3883+extern reloc_howto_type *
3884+riscv_reloc_name_lookup (bfd *, const char *);
3885+
3886+extern reloc_howto_type *
3887+riscv_reloc_type_lookup (bfd *, bfd_reloc_code_real_type);
3888+
3889+extern reloc_howto_type *
3890+riscv_elf_rtype_to_howto (unsigned int r_type);
Patrick Georgiaf473ed2015-07-17 23:35:54 +02003891diff -urN empty/gas/config/tc-riscv.c binutils-2.25/gas/config/tc-riscv.c
Jonathan A. Kollasch64fc4332015-08-25 13:09:51 -05003892--- binutils-2.25/gas/config/tc-riscv.c 1970-01-01 01:00:00.000000000 +0100
Patrick Georgiaf473ed2015-07-17 23:35:54 +02003893+++ binutils-2.25/gas/config/tc-riscv.c 2015-07-18 00:02:36.222287541 +0200
3894@@ -0,0 +1,2484 @@
Patrick Georgif0bbc952015-03-07 10:57:25 +01003895+/* tc-riscv.c -- RISC-V assembler
3896+ Copyright 2011-2014 Free Software Foundation, Inc.
3897+
3898+ Contributed by Andrew Waterman (waterman@cs.berkeley.edu) at UC Berkeley.
3899+ Based on MIPS target.
3900+
3901+ This file is part of GAS.
3902+
3903+ GAS is free software; you can redistribute it and/or modify
3904+ it under the terms of the GNU General Public License as published by
3905+ the Free Software Foundation; either version 3, or (at your option)
3906+ any later version.
3907+
3908+ GAS is distributed in the hope that it will be useful,
3909+ but WITHOUT ANY WARRANTY; without even the implied warranty of
3910+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
3911+ GNU General Public License for more details.
3912+
3913+ You should have received a copy of the GNU General Public License
3914+ along with GAS; see the file COPYING. If not, write to the Free
3915+ Software Foundation, 51 Franklin Street - Fifth Floor, Boston, MA
3916+ 02110-1301, USA. */
3917+
3918+#include "as.h"
3919+#include "config.h"
3920+#include "subsegs.h"
3921+#include "safe-ctype.h"
3922+
3923+#include "itbl-ops.h"
3924+#include "dwarf2dbg.h"
3925+#include "dw2gencfi.h"
3926+
3927+#include "elf/riscv.h"
3928+#include "opcode/riscv.h"
3929+
3930+#include <execinfo.h>
3931+#include <stdint.h>
3932+
3933+/* Information about an instruction, including its format, operands
3934+ and fixups. */
3935+struct riscv_cl_insn
3936+{
3937+ /* The opcode's entry in riscv_opcodes. */
3938+ const struct riscv_opcode *insn_mo;
3939+
3940+ /* The encoded instruction bits. */
3941+ insn_t insn_opcode;
3942+
3943+ /* The frag that contains the instruction. */
3944+ struct frag *frag;
3945+
3946+ /* The offset into FRAG of the first instruction byte. */
3947+ long where;
3948+
3949+ /* The relocs associated with the instruction, if any. */
3950+ fixS *fixp;
3951+};
3952+
Patrick Georgiaf473ed2015-07-17 23:35:54 +02003953+/* The default architecture. */
3954+#ifndef DEFAULT_ARCH
3955+#define DEFAULT_ARCH "riscv64"
3956+#endif
3957+static const char default_arch[] = DEFAULT_ARCH;
3958+
3959+unsigned xlen = 0; /* width of an x-register */
3960+#define LOAD_ADDRESS_INSN (xlen == 64 ? "ld" : "lw")
3961+#define ADD32_INSN (xlen == 64 ? "addiw" : "addi")
3962+
3963+unsigned elf_flags = 0;
3964+
3965+/* This is the set of options which the .option pseudo-op may modify. */
3966+
3967+struct riscv_set_options
3968+{
3969+ int pic; /* Generate position-independent code. */
3970+ int rvc; /* Generate RVC code. */
3971+};
3972+
3973+static struct riscv_set_options riscv_opts =
3974+{
3975+ 0, /* pic */
3976+ 0, /* rvc */
3977+};
Patrick Georgif0bbc952015-03-07 10:57:25 +01003978+
3979+struct riscv_subset
3980+{
3981+ const char* name;
3982+ int version_major;
3983+ int version_minor;
3984+
3985+ struct riscv_subset* next;
3986+};
3987+
3988+static struct riscv_subset* riscv_subsets;
3989+
3990+static int
3991+riscv_subset_supports(const char* feature)
3992+{
3993+ struct riscv_subset* s;
3994+ bfd_boolean rv64_insn;
3995+
3996+ if ((rv64_insn = !strncmp(feature, "64", 2)) || !strncmp(feature, "32", 2))
3997+ {
Patrick Georgiaf473ed2015-07-17 23:35:54 +02003998+ if ((xlen == 64) != rv64_insn)
Patrick Georgif0bbc952015-03-07 10:57:25 +01003999+ return 0;
4000+ feature += 2;
4001+ }
4002+
4003+ for (s = riscv_subsets; s != NULL; s = s->next)
4004+ if (strcmp(s->name, feature) == 0)
4005+ /* FIXME: once we support version numbers:
4006+ return major == s->version_major && minor <= s->version_minor; */
4007+ return 1;
4008+
4009+ return 0;
4010+}
4011+
4012+static void
Patrick Georgiaf473ed2015-07-17 23:35:54 +02004013+riscv_add_subset (const char* subset)
Patrick Georgif0bbc952015-03-07 10:57:25 +01004014+{
4015+ struct riscv_subset* s = xmalloc(sizeof(struct riscv_subset));
4016+ s->name = xstrdup(subset);
4017+ s->version_major = 1;
4018+ s->version_minor = 0;
4019+ s->next = riscv_subsets;
4020+ riscv_subsets = s;
4021+}
4022+
4023+static void
Patrick Georgiaf473ed2015-07-17 23:35:54 +02004024+riscv_set_arch (const char* arg)
Patrick Georgif0bbc952015-03-07 10:57:25 +01004025+{
4026+ /* Formally, ISA subset names begin with RV, RV32, or RV64, but we allow the
4027+ prefix to be omitted. We also allow all-lowercase names if version
4028+ numbers and eXtensions are omitted (i.e. only some combination of imafd
4029+ is supported in this case).
4030+
4031+ FIXME: Version numbers are not supported yet. */
Patrick Georgiaf473ed2015-07-17 23:35:54 +02004032+ const char* subsets = "IMAFDC";
4033+ const char* extension = NULL;
Patrick Georgif0bbc952015-03-07 10:57:25 +01004034+ const char* p;
Patrick Georgiaf473ed2015-07-17 23:35:54 +02004035+ int rvc = 0;
Patrick Georgif0bbc952015-03-07 10:57:25 +01004036+
4037+ for (p = arg; *p; p++)
4038+ if (!ISLOWER(*p) || strchr(subsets, TOUPPER(*p)) == NULL)
4039+ break;
4040+
4041+ if (!*p)
4042+ {
4043+ /* Legal all-lowercase name. */
4044+ for (p = arg; *p; p++)
Patrick Georgiaf473ed2015-07-17 23:35:54 +02004045+ {
4046+ char subset[2] = {TOUPPER(*p), 0};
4047+ riscv_add_subset(subset);
4048+ }
Patrick Georgif0bbc952015-03-07 10:57:25 +01004049+ return;
4050+ }
4051+
4052+ if (strncmp(arg, "RV32", 4) == 0)
4053+ {
Patrick Georgiaf473ed2015-07-17 23:35:54 +02004054+ xlen = 32;
Patrick Georgif0bbc952015-03-07 10:57:25 +01004055+ arg += 4;
4056+ }
4057+ else if (strncmp(arg, "RV64", 4) == 0)
4058+ {
Patrick Georgiaf473ed2015-07-17 23:35:54 +02004059+ xlen = 64;
Patrick Georgif0bbc952015-03-07 10:57:25 +01004060+ arg += 4;
4061+ }
4062+ else if (strncmp(arg, "RV", 2) == 0)
4063+ arg += 2;
4064+
4065+ if (*arg && *arg != 'I')
4066+ as_fatal("`I' must be the first ISA subset name specified (got %c)", *arg);
4067+
Patrick Georgiaf473ed2015-07-17 23:35:54 +02004068+ for (p = arg; *p; )
Patrick Georgif0bbc952015-03-07 10:57:25 +01004069+ {
4070+ if (*p == 'X')
Patrick Georgiaf473ed2015-07-17 23:35:54 +02004071+ {
4072+ char *subset = xstrdup(p), *q = subset;
Patrick Georgif0bbc952015-03-07 10:57:25 +01004073+
Patrick Georgiaf473ed2015-07-17 23:35:54 +02004074+ do
4075+ q++;
4076+ while (ISLOWER(*q));
4077+ *q = 0;
Patrick Georgif0bbc952015-03-07 10:57:25 +01004078+
Patrick Georgiaf473ed2015-07-17 23:35:54 +02004079+ if (extension)
4080+ as_bad ("only one eXtension is supported (found %s and %s)",
4081+ extension, subset);
4082+ extension = subset;
4083+ EF_SET_RISCV_EXT (elf_flags, riscv_elf_name_to_flag (subset));
4084+
4085+ riscv_add_subset (subset);
4086+ p += strlen (subset);
4087+ free (subset);
4088+ }
Patrick Georgif0bbc952015-03-07 10:57:25 +01004089+ else if (strchr(subsets, *p) != NULL)
Patrick Georgiaf473ed2015-07-17 23:35:54 +02004090+ {
4091+ char subset[2] = {*p, 0};
4092+ riscv_add_subset (subset);
4093+ if (*p == 'C')
4094+ rvc = 1;
4095+ p++;
4096+ }
Patrick Georgif0bbc952015-03-07 10:57:25 +01004097+ else
Patrick Georgiaf473ed2015-07-17 23:35:54 +02004098+ as_fatal("unsupported ISA subset %c", *p);
Patrick Georgif0bbc952015-03-07 10:57:25 +01004099+ }
Patrick Georgiaf473ed2015-07-17 23:35:54 +02004100+
4101+ if (rvc)
4102+ /* Override -m[no-]rvc setting if C was explicitly listed. */
4103+ riscv_opts.rvc = 1;
4104+ else
4105+ /* Add RVC anyway. -m[no-]rvc toggles its availability. */
4106+ riscv_add_subset ("C");
Patrick Georgif0bbc952015-03-07 10:57:25 +01004107+}
4108+
Patrick Georgif0bbc952015-03-07 10:57:25 +01004109+/* handle of the OPCODE hash table */
4110+static struct hash_control *op_hash = NULL;
4111+
4112+/* This array holds the chars that always start a comment. If the
4113+ pre-processor is disabled, these aren't very useful */
4114+const char comment_chars[] = "#";
4115+
4116+/* This array holds the chars that only start a comment at the beginning of
4117+ a line. If the line seems to have the form '# 123 filename'
4118+ .line and .file directives will appear in the pre-processed output */
4119+/* Note that input_file.c hand checks for '#' at the beginning of the
4120+ first line of the input file. This is because the compiler outputs
4121+ #NO_APP at the beginning of its output. */
4122+/* Also note that C style comments are always supported. */
4123+const char line_comment_chars[] = "#";
4124+
4125+/* This array holds machine specific line separator characters. */
4126+const char line_separator_chars[] = ";";
4127+
4128+/* Chars that can be used to separate mant from exp in floating point nums */
4129+const char EXP_CHARS[] = "eE";
4130+
4131+/* Chars that mean this number is a floating point constant */
4132+/* As in 0f12.456 */
4133+/* or 0d1.2345e12 */
4134+const char FLT_CHARS[] = "rRsSfFdDxXpP";
4135+
Patrick Georgiaf473ed2015-07-17 23:35:54 +02004136+#define RELAX_BRANCH_ENCODE(uncond, rvc, length) \
Patrick Georgif0bbc952015-03-07 10:57:25 +01004137+ ((relax_substateT) \
4138+ (0xc0000000 \
Patrick Georgiaf473ed2015-07-17 23:35:54 +02004139+ | ((uncond) ? 1 : 0) \
4140+ | ((rvc) ? 2 : 0) \
4141+ | ((length) << 2)))
Patrick Georgif0bbc952015-03-07 10:57:25 +01004142+#define RELAX_BRANCH_P(i) (((i) & 0xf0000000) == 0xc0000000)
Patrick Georgiaf473ed2015-07-17 23:35:54 +02004143+#define RELAX_BRANCH_LENGTH(i) (((i) >> 2) & 0xF)
4144+#define RELAX_BRANCH_RVC(i) (((i) & 2) != 0)
4145+#define RELAX_BRANCH_UNCOND(i) (((i) & 1) != 0)
Patrick Georgif0bbc952015-03-07 10:57:25 +01004146+
4147+/* Is the given value a sign-extended 32-bit value? */
4148+#define IS_SEXT_32BIT_NUM(x) \
4149+ (((x) &~ (offsetT) 0x7fffffff) == 0 \
4150+ || (((x) &~ (offsetT) 0x7fffffff) == ~ (offsetT) 0x7fffffff))
4151+
4152+#define IS_SEXT_NBIT_NUM(x,n) \
4153+ ({ int64_t __tmp = (x); \
4154+ __tmp = (__tmp << (64-(n))) >> (64-(n)); \
4155+ __tmp == (x); })
4156+
4157+/* Is the given value a zero-extended 32-bit value? Or a negated one? */
4158+#define IS_ZEXT_32BIT_NUM(x) \
4159+ (((x) &~ (offsetT) 0xffffffff) == 0 \
4160+ || (((x) &~ (offsetT) 0xffffffff) == ~ (offsetT) 0xffffffff))
4161+
4162+/* Replace bits MASK << SHIFT of STRUCT with the equivalent bits in
4163+ VALUE << SHIFT. VALUE is evaluated exactly once. */
4164+#define INSERT_BITS(STRUCT, VALUE, MASK, SHIFT) \
4165+ (STRUCT) = (((STRUCT) & ~((insn_t)(MASK) << (SHIFT))) \
4166+ | ((insn_t)((VALUE) & (MASK)) << (SHIFT)))
4167+
4168+/* Extract bits MASK << SHIFT from STRUCT and shift them right
4169+ SHIFT places. */
4170+#define EXTRACT_BITS(STRUCT, MASK, SHIFT) \
4171+ (((STRUCT) >> (SHIFT)) & (MASK))
4172+
4173+/* Change INSN's opcode so that the operand given by FIELD has value VALUE.
4174+ INSN is a riscv_cl_insn structure and VALUE is evaluated exactly once. */
4175+#define INSERT_OPERAND(FIELD, INSN, VALUE) \
4176+ INSERT_BITS ((INSN).insn_opcode, VALUE, OP_MASK_##FIELD, OP_SH_##FIELD)
4177+
4178+/* Extract the operand given by FIELD from riscv_cl_insn INSN. */
4179+#define EXTRACT_OPERAND(FIELD, INSN) \
4180+ EXTRACT_BITS ((INSN).insn_opcode, OP_MASK_##FIELD, OP_SH_##FIELD)
4181+
4182+/* Determine if an instruction matches an opcode. */
4183+#define OPCODE_MATCHES(OPCODE, OP) \
4184+ (((OPCODE) & MASK_##OP) == MATCH_##OP)
4185+
4186+#define INSN_MATCHES(INSN, OP) \
4187+ (((INSN).insn_opcode & MASK_##OP) == MATCH_##OP)
4188+
4189+/* Prototypes for static functions. */
4190+
4191+#define internalError() \
4192+ as_fatal (_("internal Error, line %d, %s"), __LINE__, __FILE__)
4193+
4194+static char *expr_end;
4195+
Patrick Georgif0bbc952015-03-07 10:57:25 +01004196+/* The default target format to use. */
4197+
4198+const char *
4199+riscv_target_format (void)
4200+{
Patrick Georgiaf473ed2015-07-17 23:35:54 +02004201+ return xlen == 64 ? "elf64-littleriscv" : "elf32-littleriscv";
Patrick Georgif0bbc952015-03-07 10:57:25 +01004202+}
4203+
4204+/* Return the length of instruction INSN. */
4205+
4206+static inline unsigned int
4207+insn_length (const struct riscv_cl_insn *insn)
4208+{
4209+ return riscv_insn_length (insn->insn_opcode);
4210+}
4211+
4212+/* Initialise INSN from opcode entry MO. Leave its position unspecified. */
4213+
4214+static void
4215+create_insn (struct riscv_cl_insn *insn, const struct riscv_opcode *mo)
4216+{
4217+ insn->insn_mo = mo;
4218+ insn->insn_opcode = mo->match;
4219+ insn->frag = NULL;
4220+ insn->where = 0;
4221+ insn->fixp = NULL;
4222+}
4223+
4224+/* Install INSN at the location specified by its "frag" and "where" fields. */
4225+
4226+static void
4227+install_insn (const struct riscv_cl_insn *insn)
4228+{
4229+ char *f = insn->frag->fr_literal + insn->where;
4230+ md_number_to_chars (f, insn->insn_opcode, insn_length(insn));
4231+}
4232+
4233+/* Move INSN to offset WHERE in FRAG. Adjust the fixups accordingly
4234+ and install the opcode in the new location. */
4235+
4236+static void
4237+move_insn (struct riscv_cl_insn *insn, fragS *frag, long where)
4238+{
4239+ insn->frag = frag;
4240+ insn->where = where;
4241+ if (insn->fixp != NULL)
4242+ {
4243+ insn->fixp->fx_frag = frag;
4244+ insn->fixp->fx_where = where;
4245+ }
4246+ install_insn (insn);
4247+}
4248+
4249+/* Add INSN to the end of the output. */
4250+
4251+static void
4252+add_fixed_insn (struct riscv_cl_insn *insn)
4253+{
4254+ char *f = frag_more (insn_length (insn));
4255+ move_insn (insn, frag_now, f - frag_now->fr_literal);
4256+}
4257+
4258+static void
4259+add_relaxed_insn (struct riscv_cl_insn *insn, int max_chars, int var,
4260+ relax_substateT subtype, symbolS *symbol, offsetT offset)
4261+{
4262+ frag_grow (max_chars);
4263+ move_insn (insn, frag_now, frag_more (0) - frag_now->fr_literal);
4264+ frag_var (rs_machine_dependent, max_chars, var,
4265+ subtype, symbol, offset, NULL);
4266+}
4267+
Patrick Georgiaf473ed2015-07-17 23:35:54 +02004268+/* Compute the length of a branch sequence, and adjust the stored length
4269+ accordingly. If FRAGP is NULL, the worst-case length is returned. */
4270+
Patrick Georgif0bbc952015-03-07 10:57:25 +01004271+static int
4272+relaxed_branch_length (fragS *fragp, asection *sec, int update)
4273+{
Patrick Georgiaf473ed2015-07-17 23:35:54 +02004274+ int jump, rvc, length = 8;
Patrick Georgif0bbc952015-03-07 10:57:25 +01004275+
Patrick Georgiaf473ed2015-07-17 23:35:54 +02004276+ if (!fragp)
4277+ return length;
4278+
4279+ jump = RELAX_BRANCH_UNCOND (fragp->fr_subtype);
4280+ rvc = RELAX_BRANCH_RVC (fragp->fr_subtype);
4281+ length = RELAX_BRANCH_LENGTH (fragp->fr_subtype);
4282+
4283+ /* Assume jumps are in range; the linker will catch any that aren't. */
4284+ length = jump ? 4 : 8;
4285+
4286+ if (fragp->fr_symbol != NULL
4287+ && S_IS_DEFINED (fragp->fr_symbol)
4288+ && sec == S_GET_SEGMENT (fragp->fr_symbol))
Patrick Georgif0bbc952015-03-07 10:57:25 +01004289+ {
Patrick Georgiaf473ed2015-07-17 23:35:54 +02004290+ offsetT val = S_GET_VALUE (fragp->fr_symbol) + fragp->fr_offset;
4291+ bfd_vma rvc_range = jump ? RVC_JUMP_REACH : RVC_BRANCH_REACH;
4292+ val -= fragp->fr_address + fragp->fr_fix;
Patrick Georgif0bbc952015-03-07 10:57:25 +01004293+
Patrick Georgiaf473ed2015-07-17 23:35:54 +02004294+ if (rvc && (bfd_vma)(val + rvc_range/2) < rvc_range)
4295+ length = 2;
4296+ else if ((bfd_vma)(val + RISCV_BRANCH_REACH/2) < RISCV_BRANCH_REACH)
4297+ length = 4;
Patrick Georgif0bbc952015-03-07 10:57:25 +01004298+ }
4299+
Patrick Georgiaf473ed2015-07-17 23:35:54 +02004300+ if (update)
4301+ fragp->fr_subtype = RELAX_BRANCH_ENCODE (jump, rvc, length);
4302+
4303+ return length;
Patrick Georgif0bbc952015-03-07 10:57:25 +01004304+}
4305+
4306+struct regname {
4307+ const char *name;
4308+ unsigned int num;
4309+};
4310+
4311+enum reg_class {
4312+ RCLASS_GPR,
4313+ RCLASS_FPR,
4314+ RCLASS_CSR,
4315+ RCLASS_VEC_GPR,
4316+ RCLASS_VEC_FPR,
4317+ RCLASS_MAX
4318+};
4319+
4320+static struct hash_control *reg_names_hash = NULL;
4321+
4322+#define ENCODE_REG_HASH(cls, n) (void*)(uintptr_t)((n)*RCLASS_MAX + (cls) + 1)
4323+#define DECODE_REG_CLASS(hash) (((uintptr_t)(hash) - 1) % RCLASS_MAX)
4324+#define DECODE_REG_NUM(hash) (((uintptr_t)(hash) - 1) / RCLASS_MAX)
4325+
4326+static void
4327+hash_reg_name (enum reg_class class, const char *name, unsigned n)
4328+{
4329+ void *hash = ENCODE_REG_HASH (class, n);
4330+ const char *retval = hash_insert (reg_names_hash, name, hash);
4331+ if (retval != NULL)
4332+ as_fatal (_("internal error: can't hash `%s': %s"), name, retval);
4333+}
4334+
4335+static void
4336+hash_reg_names (enum reg_class class, const char * const names[], unsigned n)
4337+{
4338+ unsigned i;
4339+ for (i = 0; i < n; i++)
4340+ hash_reg_name (class, names[i], i);
4341+}
4342+
4343+static unsigned int
4344+reg_lookup_internal (const char *s, enum reg_class class)
4345+{
4346+ struct regname *r = (struct regname *) hash_find (reg_names_hash, s);
4347+ if (r == NULL || DECODE_REG_CLASS (r) != class)
4348+ return -1;
4349+ return DECODE_REG_NUM (r);
4350+}
4351+
4352+static int
4353+reg_lookup (char **s, enum reg_class class, unsigned int *regnop)
4354+{
4355+ char *e;
4356+ char save_c;
4357+ int reg = -1;
4358+
4359+ /* Find end of name. */
4360+ e = *s;
4361+ if (is_name_beginner (*e))
4362+ ++e;
4363+ while (is_part_of_name (*e))
4364+ ++e;
4365+
4366+ /* Terminate name. */
4367+ save_c = *e;
4368+ *e = '\0';
4369+
4370+ /* Look for the register. Advance to next token if one was recognized. */
4371+ if ((reg = reg_lookup_internal (*s, class)) >= 0)
4372+ *s = e;
4373+
4374+ *e = save_c;
4375+ if (regnop)
4376+ *regnop = reg;
4377+ return reg >= 0;
4378+}
4379+
4380+static int
4381+arg_lookup(char **s, const char* const* array, size_t size, unsigned *regnop)
4382+{
4383+ const char *p = strchr(*s, ',');
4384+ size_t i, len = p ? (size_t)(p - *s) : strlen(*s);
4385+
4386+ for (i = 0; i < size; i++)
4387+ if (array[i] != NULL && strncmp(array[i], *s, len) == 0)
4388+ {
4389+ *regnop = i;
4390+ *s += len;
4391+ return 1;
4392+ }
4393+
4394+ return 0;
4395+}
4396+
4397+/* For consistency checking, verify that all bits are specified either
4398+ by the match/mask part of the instruction definition, or by the
4399+ operand list. */
4400+static int
4401+validate_riscv_insn (const struct riscv_opcode *opc)
4402+{
4403+ const char *p = opc->args;
4404+ char c;
Patrick Georgiaf473ed2015-07-17 23:35:54 +02004405+ insn_t used_bits = opc->mask;
4406+ insn_t required_bits = (uint64_t)-1 >> (64 - 8 * riscv_insn_length (opc->match));
Patrick Georgif0bbc952015-03-07 10:57:25 +01004407+
Patrick Georgiaf473ed2015-07-17 23:35:54 +02004408+ if ((used_bits & opc->match) != (opc->match & required_bits))
Patrick Georgif0bbc952015-03-07 10:57:25 +01004409+ {
4410+ as_bad (_("internal: bad RISC-V opcode (mask error): %s %s"),
4411+ opc->name, opc->args);
4412+ return 0;
4413+ }
Patrick Georgif0bbc952015-03-07 10:57:25 +01004414+
4415+#define USE_BITS(mask,shift) (used_bits |= ((insn_t)(mask) << (shift)))
4416+ while (*p)
4417+ switch (c = *p++)
4418+ {
4419+ /* Xcustom */
4420+ case '^':
4421+ switch (c = *p++)
4422+ {
4423+ case 'd': USE_BITS (OP_MASK_RD, OP_SH_RD); break;
4424+ case 's': USE_BITS (OP_MASK_RS1, OP_SH_RS1); break;
4425+ case 't': USE_BITS (OP_MASK_RS2, OP_SH_RS2); break;
4426+ case 'j': USE_BITS (OP_MASK_CUSTOM_IMM, OP_SH_CUSTOM_IMM); break;
4427+ }
4428+ break;
4429+ /* Xhwacha */
4430+ case '#':
4431+ switch (c = *p++)
4432+ {
4433+ case 'g': USE_BITS (OP_MASK_IMMNGPR, OP_SH_IMMNGPR); break;
4434+ case 'f': USE_BITS (OP_MASK_IMMNFPR, OP_SH_IMMNFPR); break;
4435+ case 'n': USE_BITS (OP_MASK_IMMSEGNELM, OP_SH_IMMSEGNELM); break;
4436+ case 'd': USE_BITS (OP_MASK_VRD, OP_SH_VRD); break;
4437+ case 's': USE_BITS (OP_MASK_VRS, OP_SH_VRS); break;
4438+ case 't': USE_BITS (OP_MASK_VRT, OP_SH_VRT); break;
4439+ case 'r': USE_BITS (OP_MASK_VRR, OP_SH_VRR); break;
4440+ case 'D': USE_BITS (OP_MASK_VFD, OP_SH_VFD); break;
4441+ case 'S': USE_BITS (OP_MASK_VFS, OP_SH_VFS); break;
4442+ case 'T': USE_BITS (OP_MASK_VFT, OP_SH_VFT); break;
4443+ case 'R': USE_BITS (OP_MASK_VFR, OP_SH_VFR); break;
4444+
4445+ default:
4446+ as_bad (_("internal: bad RISC-V opcode (unknown extension operand type `#%c'): %s %s"),
4447+ c, opc->name, opc->args);
4448+ return 0;
4449+ }
4450+ break;
Patrick Georgiaf473ed2015-07-17 23:35:54 +02004451+ case 'C': /* RVC */
4452+ switch (c = *p++)
4453+ {
4454+ case 'd': USE_BITS (OP_MASK_CRDS, OP_SH_CRDS); break;
4455+ case 's': USE_BITS (OP_MASK_CRS1S, OP_SH_CRS1S); break;
4456+ case 't': USE_BITS (OP_MASK_CRS2S, OP_SH_CRS2S); break;
4457+ case 'w': break; /* RS1S, constrained to equal RD */
4458+ case 'x': break; /* RS1S, constrained to equal RD */
4459+ case 'D': USE_BITS (OP_MASK_RD, OP_SH_RD); break;
4460+ case 'T': USE_BITS (OP_MASK_CRS2, OP_SH_CRS2); break;
4461+ case 'V': USE_BITS (OP_MASK_CRS2, OP_SH_CRS2); break;
4462+ case 'c': break; /* RS1, constrained to equal sp */
4463+ case 'U': break; /* RS2, constrained to equal RD */
4464+ case '<': used_bits |= ENCODE_RVC_IMM(-1U); break;
4465+ case '>': used_bits |= ENCODE_RVC_IMM(-1U); break;
4466+ case 'i': used_bits |= ENCODE_RVC_SIMM3(-1U); break;
4467+ case 'j': used_bits |= ENCODE_RVC_IMM(-1U); break;
4468+ case 'k': used_bits |= ENCODE_RVC_LW_IMM(-1U); break;
4469+ case 'l': used_bits |= ENCODE_RVC_LD_IMM(-1U); break;
4470+ case 'm': used_bits |= ENCODE_RVC_LWSP_IMM(-1U); break;
4471+ case 'n': used_bits |= ENCODE_RVC_LDSP_IMM(-1U); break;
4472+ case 'K': used_bits |= ENCODE_RVC_ADDI4SPN_IMM(-1U); break;
4473+ case 'L': used_bits |= ENCODE_RVC_ADDI16SP_IMM(-1U); break;
4474+ case 'M': used_bits |= ENCODE_RVC_SWSP_IMM(-1U); break;
4475+ case 'N': used_bits |= ENCODE_RVC_SDSP_IMM(-1U); break;
4476+ case 'u': used_bits |= ENCODE_RVC_IMM(-1U); break;
4477+ case 'v': used_bits |= ENCODE_RVC_IMM(-1U); break;
4478+ case 'a': used_bits |= ENCODE_RVC_J_IMM(-1U); break;
4479+ case 'p': used_bits |= ENCODE_RVC_B_IMM(-1U); break;
4480+ default:
4481+ as_bad (_("internal: bad RISC-V opcode (unknown operand type `C%c'): %s %s"),
4482+ c, opc->name, opc->args);
4483+ return 0;
4484+ }
4485+ break;
Patrick Georgif0bbc952015-03-07 10:57:25 +01004486+ case ',': break;
4487+ case '(': break;
4488+ case ')': break;
4489+ case '<': USE_BITS (OP_MASK_SHAMTW, OP_SH_SHAMTW); break;
4490+ case '>': USE_BITS (OP_MASK_SHAMT, OP_SH_SHAMT); break;
4491+ case 'A': break;
4492+ case 'D': USE_BITS (OP_MASK_RD, OP_SH_RD); break;
4493+ case 'Z': USE_BITS (OP_MASK_RS1, OP_SH_RS1); break;
4494+ case 'E': USE_BITS (OP_MASK_CSR, OP_SH_CSR); break;
4495+ case 'I': break;
4496+ case 'R': USE_BITS (OP_MASK_RS3, OP_SH_RS3); break;
4497+ case 'S': USE_BITS (OP_MASK_RS1, OP_SH_RS1); break;
4498+ case 'U': USE_BITS (OP_MASK_RS1, OP_SH_RS1); /* fallthru */
4499+ case 'T': USE_BITS (OP_MASK_RS2, OP_SH_RS2); break;
4500+ case 'd': USE_BITS (OP_MASK_RD, OP_SH_RD); break;
4501+ case 'm': USE_BITS (OP_MASK_RM, OP_SH_RM); break;
4502+ case 's': USE_BITS (OP_MASK_RS1, OP_SH_RS1); break;
4503+ case 't': USE_BITS (OP_MASK_RS2, OP_SH_RS2); break;
4504+ case 'P': USE_BITS (OP_MASK_PRED, OP_SH_PRED); break;
4505+ case 'Q': USE_BITS (OP_MASK_SUCC, OP_SH_SUCC); break;
4506+ case 'o':
4507+ case 'j': used_bits |= ENCODE_ITYPE_IMM(-1U); break;
4508+ case 'a': used_bits |= ENCODE_UJTYPE_IMM(-1U); break;
4509+ case 'p': used_bits |= ENCODE_SBTYPE_IMM(-1U); break;
4510+ case 'q': used_bits |= ENCODE_STYPE_IMM(-1U); break;
4511+ case 'u': used_bits |= ENCODE_UTYPE_IMM(-1U); break;
4512+ case '[': break;
4513+ case ']': break;
4514+ case '0': break;
4515+ default:
4516+ as_bad (_("internal: bad RISC-V opcode (unknown operand type `%c'): %s %s"),
4517+ c, opc->name, opc->args);
4518+ return 0;
4519+ }
4520+#undef USE_BITS
4521+ if (used_bits != required_bits)
4522+ {
4523+ as_bad (_("internal: bad RISC-V opcode (bits 0x%lx undefined): %s %s"),
4524+ ~(long)(used_bits & required_bits), opc->name, opc->args);
4525+ return 0;
4526+ }
4527+ return 1;
4528+}
4529+
4530+struct percent_op_match
4531+{
4532+ const char *str;
4533+ bfd_reloc_code_real_type reloc;
4534+};
4535+
4536+/* This function is called once, at assembler startup time. It should set up
4537+ all the tables, etc. that the MD part of the assembler will need. */
4538+
4539+void
4540+md_begin (void)
4541+{
4542+ const char *retval = NULL;
4543+ int i = 0;
4544+
4545+ if (! bfd_set_arch_mach (stdoutput, bfd_arch_riscv, 0))
4546+ as_warn (_("Could not set architecture and machine"));
4547+
4548+ op_hash = hash_new ();
4549+
4550+ for (i = 0; i < NUMOPCODES;)
4551+ {
4552+ const char *name = riscv_opcodes[i].name;
4553+
Patrick Georgiaf473ed2015-07-17 23:35:54 +02004554+ retval = hash_insert (op_hash, name, (void *) &riscv_opcodes[i]);
Patrick Georgif0bbc952015-03-07 10:57:25 +01004555+
4556+ if (retval != NULL)
4557+ {
4558+ fprintf (stderr, _("internal error: can't hash `%s': %s\n"),
4559+ riscv_opcodes[i].name, retval);
4560+ /* Probably a memory allocation problem? Give up now. */
4561+ as_fatal (_("Broken assembler. No assembly attempted."));
4562+ }
4563+ do
4564+ {
4565+ if (riscv_opcodes[i].pinfo != INSN_MACRO)
4566+ {
4567+ if (!validate_riscv_insn (&riscv_opcodes[i]))
4568+ as_fatal (_("Broken assembler. No assembly attempted."));
4569+ }
4570+ ++i;
4571+ }
4572+ while ((i < NUMOPCODES) && !strcmp (riscv_opcodes[i].name, name));
4573+ }
4574+
4575+ reg_names_hash = hash_new ();
4576+ hash_reg_names (RCLASS_GPR, riscv_gpr_names_numeric, NGPR);
4577+ hash_reg_names (RCLASS_GPR, riscv_gpr_names_abi, NGPR);
4578+ hash_reg_names (RCLASS_FPR, riscv_fpr_names_numeric, NFPR);
4579+ hash_reg_names (RCLASS_FPR, riscv_fpr_names_abi, NFPR);
4580+ hash_reg_names (RCLASS_VEC_GPR, riscv_vec_gpr_names, NVGPR);
4581+ hash_reg_names (RCLASS_VEC_FPR, riscv_vec_fpr_names, NVFPR);
4582+
4583+#define DECLARE_CSR(name, num) hash_reg_name (RCLASS_CSR, #name, num);
4584+#include "opcode/riscv-opc.h"
4585+#undef DECLARE_CSR
4586+
4587+ /* set the default alignment for the text section (2**2) */
4588+ record_alignment (text_section, 2);
4589+}
4590+
4591+/* Output an instruction. IP is the instruction information.
4592+ ADDRESS_EXPR is an operand of the instruction to be used with
4593+ RELOC_TYPE. */
4594+
4595+static void
4596+append_insn (struct riscv_cl_insn *ip, expressionS *address_expr,
4597+ bfd_reloc_code_real_type reloc_type)
4598+{
4599+#ifdef OBJ_ELF
4600+ dwarf2_emit_insn (0);
4601+#endif
4602+
Patrick Georgiaf473ed2015-07-17 23:35:54 +02004603+ if (reloc_type != BFD_RELOC_UNUSED)
Patrick Georgif0bbc952015-03-07 10:57:25 +01004604+ {
Patrick Georgiaf473ed2015-07-17 23:35:54 +02004605+ reloc_howto_type *howto;
4606+
4607+ gas_assert(address_expr);
4608+ if (reloc_type == BFD_RELOC_12_PCREL
4609+ || reloc_type == BFD_RELOC_RISCV_JMP)
4610+ {
4611+ int j = reloc_type == BFD_RELOC_RISCV_JMP;
4612+ int best_case = riscv_insn_length (ip->insn_opcode);
4613+ int worst_case = relaxed_branch_length (NULL, NULL, 0);
4614+ add_relaxed_insn (ip, worst_case, best_case,
4615+ RELAX_BRANCH_ENCODE (j, best_case == 2, worst_case),
4616+ address_expr->X_add_symbol,
4617+ address_expr->X_add_number);
4618+ return;
4619+ }
4620+ else if (address_expr->X_op == O_constant)
Patrick Georgif0bbc952015-03-07 10:57:25 +01004621+ {
4622+ switch (reloc_type)
4623+ {
4624+ case BFD_RELOC_32:
4625+ ip->insn_opcode |= address_expr->X_add_number;
Patrick Georgiaf473ed2015-07-17 23:35:54 +02004626+ goto append;
Patrick Georgif0bbc952015-03-07 10:57:25 +01004627+
4628+ case BFD_RELOC_RISCV_HI20:
4629+ ip->insn_opcode |= ENCODE_UTYPE_IMM (
4630+ RISCV_CONST_HIGH_PART (address_expr->X_add_number));
Patrick Georgiaf473ed2015-07-17 23:35:54 +02004631+ goto append;
Patrick Georgif0bbc952015-03-07 10:57:25 +01004632+
4633+ case BFD_RELOC_RISCV_LO12_S:
4634+ ip->insn_opcode |= ENCODE_STYPE_IMM (address_expr->X_add_number);
Patrick Georgiaf473ed2015-07-17 23:35:54 +02004635+ goto append;
Patrick Georgif0bbc952015-03-07 10:57:25 +01004636+
Patrick Georgif0bbc952015-03-07 10:57:25 +01004637+ case BFD_RELOC_RISCV_LO12_I:
4638+ ip->insn_opcode |= ENCODE_ITYPE_IMM (address_expr->X_add_number);
Patrick Georgiaf473ed2015-07-17 23:35:54 +02004639+ goto append;
Patrick Georgif0bbc952015-03-07 10:57:25 +01004640+
4641+ default:
Patrick Georgiaf473ed2015-07-17 23:35:54 +02004642+ break;
Patrick Georgif0bbc952015-03-07 10:57:25 +01004643+ }
Patrick Georgif0bbc952015-03-07 10:57:25 +01004644+ }
Patrick Georgif0bbc952015-03-07 10:57:25 +01004645+
Patrick Georgiaf473ed2015-07-17 23:35:54 +02004646+ howto = bfd_reloc_type_lookup (stdoutput, reloc_type);
4647+ if (howto == NULL)
4648+ as_bad (_("Unsupported RISC-V relocation number %d"), reloc_type);
Patrick Georgif0bbc952015-03-07 10:57:25 +01004649+
Patrick Georgiaf473ed2015-07-17 23:35:54 +02004650+ ip->fixp = fix_new_exp (ip->frag, ip->where,
4651+ bfd_get_reloc_size (howto),
4652+ address_expr, FALSE, reloc_type);
4653+
4654+ /* These relocations can have an addend that won't fit in
4655+ 4 octets for 64bit assembly. */
4656+ if (xlen == 64
4657+ && ! howto->partial_inplace
4658+ && (reloc_type == BFD_RELOC_32
4659+ || reloc_type == BFD_RELOC_64
4660+ || reloc_type == BFD_RELOC_CTOR
4661+ || reloc_type == BFD_RELOC_RISCV_HI20
4662+ || reloc_type == BFD_RELOC_RISCV_LO12_I
4663+ || reloc_type == BFD_RELOC_RISCV_LO12_S))
4664+ ip->fixp->fx_no_overflow = 1;
Patrick Georgif0bbc952015-03-07 10:57:25 +01004665+ }
4666+
Patrick Georgiaf473ed2015-07-17 23:35:54 +02004667+append:
Patrick Georgif0bbc952015-03-07 10:57:25 +01004668+ add_fixed_insn (ip);
Patrick Georgif0bbc952015-03-07 10:57:25 +01004669+ install_insn (ip);
4670+}
4671+
4672+/* Build an instruction created by a macro expansion. This is passed
4673+ a pointer to the count of instructions created so far, an
4674+ expression, the name of the instruction to build, an operand format
4675+ string, and corresponding arguments. */
4676+
4677+static void
4678+macro_build (expressionS *ep, const char *name, const char *fmt, ...)
4679+{
4680+ const struct riscv_opcode *mo;
4681+ struct riscv_cl_insn insn;
4682+ bfd_reloc_code_real_type r;
4683+ va_list args;
4684+
4685+ va_start (args, fmt);
4686+
4687+ r = BFD_RELOC_UNUSED;
4688+ mo = (struct riscv_opcode *) hash_find (op_hash, name);
4689+ gas_assert (mo);
Patrick Georgiaf473ed2015-07-17 23:35:54 +02004690+
4691+ /* Find a non-RVC variant of the instruction. */
4692+ while (riscv_insn_length (mo->match) < 4)
4693+ mo++;
Patrick Georgif0bbc952015-03-07 10:57:25 +01004694+ gas_assert (strcmp (name, mo->name) == 0);
4695+
4696+ create_insn (&insn, mo);
4697+ for (;;)
4698+ {
4699+ switch (*fmt++)
4700+ {
4701+ case 'd':
4702+ INSERT_OPERAND (RD, insn, va_arg (args, int));
4703+ continue;
4704+
4705+ case 's':
4706+ INSERT_OPERAND (RS1, insn, va_arg (args, int));
4707+ continue;
4708+
4709+ case 't':
4710+ INSERT_OPERAND (RS2, insn, va_arg (args, int));
4711+ continue;
4712+
4713+ case '>':
4714+ INSERT_OPERAND (SHAMT, insn, va_arg (args, int));
4715+ continue;
4716+
4717+ case 'j':
4718+ case 'u':
4719+ case 'q':
4720+ gas_assert (ep != NULL);
4721+ r = va_arg (args, int);
4722+ continue;
4723+
4724+ case '\0':
4725+ break;
4726+ case ',':
4727+ continue;
4728+ default:
4729+ internalError ();
4730+ }
4731+ break;
4732+ }
4733+ va_end (args);
4734+ gas_assert (r == BFD_RELOC_UNUSED ? ep == NULL : ep != NULL);
4735+
4736+ append_insn (&insn, ep, r);
4737+}
4738+
4739+/*
4740+ * Sign-extend 32-bit mode constants that have bit 31 set and all
4741+ * higher bits unset.
4742+ */
4743+static void
4744+normalize_constant_expr (expressionS *ex)
4745+{
Patrick Georgiaf473ed2015-07-17 23:35:54 +02004746+ if (xlen > 32)
Patrick Georgif0bbc952015-03-07 10:57:25 +01004747+ return;
4748+ if ((ex->X_op == O_constant || ex->X_op == O_symbol)
4749+ && IS_ZEXT_32BIT_NUM (ex->X_add_number))
4750+ ex->X_add_number = (((ex->X_add_number & 0xffffffff) ^ 0x80000000)
4751+ - 0x80000000);
4752+}
4753+
4754+static symbolS *
4755+make_internal_label (void)
4756+{
4757+ return (symbolS *) local_symbol_make (FAKE_LABEL_NAME, now_seg,
4758+ (valueT) frag_now_fix(), frag_now);
4759+}
4760+
4761+/* Load an entry from the GOT. */
4762+static void
4763+pcrel_access (int destreg, int tempreg, expressionS *ep,
4764+ const char* lo_insn, const char* lo_pattern,
4765+ bfd_reloc_code_real_type hi_reloc,
4766+ bfd_reloc_code_real_type lo_reloc)
4767+{
4768+ expressionS ep2;
4769+ ep2.X_op = O_symbol;
4770+ ep2.X_add_symbol = make_internal_label ();
4771+ ep2.X_add_number = 0;
4772+
4773+ macro_build (ep, "auipc", "d,u", tempreg, hi_reloc);
4774+ macro_build (&ep2, lo_insn, lo_pattern, destreg, tempreg, lo_reloc);
4775+}
4776+
4777+static void
4778+pcrel_load (int destreg, int tempreg, expressionS *ep, const char* lo_insn,
4779+ bfd_reloc_code_real_type hi_reloc,
4780+ bfd_reloc_code_real_type lo_reloc)
4781+{
4782+ pcrel_access (destreg, tempreg, ep, lo_insn, "d,s,j", hi_reloc, lo_reloc);
4783+}
4784+
4785+static void
4786+pcrel_store (int srcreg, int tempreg, expressionS *ep, const char* lo_insn,
4787+ bfd_reloc_code_real_type hi_reloc,
4788+ bfd_reloc_code_real_type lo_reloc)
4789+{
4790+ pcrel_access (srcreg, tempreg, ep, lo_insn, "t,s,q", hi_reloc, lo_reloc);
4791+}
4792+
4793+/* PC-relative function call using AUIPC/JALR, relaxed to JAL. */
4794+static void
4795+riscv_call (int destreg, int tempreg, expressionS *ep,
4796+ bfd_reloc_code_real_type reloc)
4797+{
4798+ macro_build (ep, "auipc", "d,u", tempreg, reloc);
4799+ macro_build (NULL, "jalr", "d,s", destreg, tempreg);
4800+}
4801+
4802+/* Warn if an expression is not a constant. */
4803+
4804+static void
4805+check_absolute_expr (struct riscv_cl_insn *ip, expressionS *ex)
4806+{
4807+ if (ex->X_op == O_big)
4808+ as_bad (_("unsupported large constant"));
4809+ else if (ex->X_op != O_constant)
4810+ as_bad (_("Instruction %s requires absolute expression"),
4811+ ip->insn_mo->name);
4812+ normalize_constant_expr (ex);
4813+}
4814+
4815+/* Load an integer constant into a register. */
4816+
4817+static void
4818+load_const (int reg, expressionS *ep)
4819+{
4820+ int shift = RISCV_IMM_BITS;
4821+ expressionS upper = *ep, lower = *ep;
4822+ lower.X_add_number = (int32_t) ep->X_add_number << (32-shift) >> (32-shift);
4823+ upper.X_add_number -= lower.X_add_number;
4824+
4825+ gas_assert (ep->X_op == O_constant);
4826+
Patrick Georgiaf473ed2015-07-17 23:35:54 +02004827+ if (xlen > 32 && !IS_SEXT_32BIT_NUM(ep->X_add_number))
Patrick Georgif0bbc952015-03-07 10:57:25 +01004828+ {
4829+ /* Reduce to a signed 32-bit constant using SLLI and ADDI, which
4830+ is not optimal but also not so bad. */
4831+ while (((upper.X_add_number >> shift) & 1) == 0)
4832+ shift++;
4833+
4834+ upper.X_add_number = (int64_t) upper.X_add_number >> shift;
4835+ load_const(reg, &upper);
4836+
4837+ macro_build (NULL, "slli", "d,s,>", reg, reg, shift);
4838+ if (lower.X_add_number != 0)
4839+ macro_build (&lower, "addi", "d,s,j", reg, reg, BFD_RELOC_RISCV_LO12_I);
4840+ }
4841+ else
4842+ {
4843+ int hi_reg = 0;
4844+
4845+ if (upper.X_add_number != 0)
4846+ {
4847+ macro_build (ep, "lui", "d,u", reg, BFD_RELOC_RISCV_HI20);
4848+ hi_reg = reg;
4849+ }
4850+
4851+ if (lower.X_add_number != 0 || hi_reg == 0)
4852+ macro_build (ep, ADD32_INSN, "d,s,j", reg, hi_reg,
4853+ BFD_RELOC_RISCV_LO12_I);
4854+ }
4855+}
4856+
4857+/* Expand RISC-V assembly macros into one or more instructions. */
4858+static void
Patrick Georgiaf473ed2015-07-17 23:35:54 +02004859+macro (struct riscv_cl_insn *ip, expressionS *imm_expr,
4860+ bfd_reloc_code_real_type *imm_reloc)
Patrick Georgif0bbc952015-03-07 10:57:25 +01004861+{
4862+ int rd = (ip->insn_opcode >> OP_SH_RD) & OP_MASK_RD;
4863+ int rs1 = (ip->insn_opcode >> OP_SH_RS1) & OP_MASK_RS1;
4864+ int rs2 = (ip->insn_opcode >> OP_SH_RS2) & OP_MASK_RS2;
4865+ int mask = ip->insn_mo->mask;
4866+
4867+ switch (mask)
4868+ {
4869+ case M_LI:
Patrick Georgiaf473ed2015-07-17 23:35:54 +02004870+ load_const (rd, imm_expr);
Patrick Georgif0bbc952015-03-07 10:57:25 +01004871+ break;
4872+
4873+ case M_LA:
4874+ case M_LLA:
4875+ /* Load the address of a symbol into a register. */
Patrick Georgiaf473ed2015-07-17 23:35:54 +02004876+ if (!IS_SEXT_32BIT_NUM (imm_expr->X_add_number))
Patrick Georgif0bbc952015-03-07 10:57:25 +01004877+ as_bad(_("offset too large"));
4878+
Patrick Georgiaf473ed2015-07-17 23:35:54 +02004879+ if (imm_expr->X_op == O_constant)
4880+ load_const (rd, imm_expr);
Patrick Georgif0bbc952015-03-07 10:57:25 +01004881+ else if (riscv_opts.pic && mask == M_LA) /* Global PIC symbol */
Patrick Georgiaf473ed2015-07-17 23:35:54 +02004882+ pcrel_load (rd, rd, imm_expr, LOAD_ADDRESS_INSN,
Patrick Georgif0bbc952015-03-07 10:57:25 +01004883+ BFD_RELOC_RISCV_GOT_HI20, BFD_RELOC_RISCV_PCREL_LO12_I);
4884+ else /* Local PIC symbol, or any non-PIC symbol */
Patrick Georgiaf473ed2015-07-17 23:35:54 +02004885+ pcrel_load (rd, rd, imm_expr, "addi",
Patrick Georgif0bbc952015-03-07 10:57:25 +01004886+ BFD_RELOC_RISCV_PCREL_HI20, BFD_RELOC_RISCV_PCREL_LO12_I);
4887+ break;
4888+
4889+ case M_LA_TLS_GD:
Patrick Georgiaf473ed2015-07-17 23:35:54 +02004890+ pcrel_load (rd, rd, imm_expr, "addi",
Patrick Georgif0bbc952015-03-07 10:57:25 +01004891+ BFD_RELOC_RISCV_TLS_GD_HI20, BFD_RELOC_RISCV_PCREL_LO12_I);
4892+ break;
4893+
4894+ case M_LA_TLS_IE:
Patrick Georgiaf473ed2015-07-17 23:35:54 +02004895+ pcrel_load (rd, rd, imm_expr, LOAD_ADDRESS_INSN,
Patrick Georgif0bbc952015-03-07 10:57:25 +01004896+ BFD_RELOC_RISCV_TLS_GOT_HI20, BFD_RELOC_RISCV_PCREL_LO12_I);
4897+ break;
4898+
4899+ case M_LB:
Patrick Georgiaf473ed2015-07-17 23:35:54 +02004900+ pcrel_load (rd, rd, imm_expr, "lb",
Patrick Georgif0bbc952015-03-07 10:57:25 +01004901+ BFD_RELOC_RISCV_PCREL_HI20, BFD_RELOC_RISCV_PCREL_LO12_I);
4902+ break;
4903+
4904+ case M_LBU:
Patrick Georgiaf473ed2015-07-17 23:35:54 +02004905+ pcrel_load (rd, rd, imm_expr, "lbu",
Patrick Georgif0bbc952015-03-07 10:57:25 +01004906+ BFD_RELOC_RISCV_PCREL_HI20, BFD_RELOC_RISCV_PCREL_LO12_I);
4907+ break;
4908+
4909+ case M_LH:
Patrick Georgiaf473ed2015-07-17 23:35:54 +02004910+ pcrel_load (rd, rd, imm_expr, "lh",
Patrick Georgif0bbc952015-03-07 10:57:25 +01004911+ BFD_RELOC_RISCV_PCREL_HI20, BFD_RELOC_RISCV_PCREL_LO12_I);
4912+ break;
4913+
4914+ case M_LHU:
Patrick Georgiaf473ed2015-07-17 23:35:54 +02004915+ pcrel_load (rd, rd, imm_expr, "lhu",
Patrick Georgif0bbc952015-03-07 10:57:25 +01004916+ BFD_RELOC_RISCV_PCREL_HI20, BFD_RELOC_RISCV_PCREL_LO12_I);
4917+ break;
4918+
4919+ case M_LW:
Patrick Georgiaf473ed2015-07-17 23:35:54 +02004920+ pcrel_load (rd, rd, imm_expr, "lw",
Patrick Georgif0bbc952015-03-07 10:57:25 +01004921+ BFD_RELOC_RISCV_PCREL_HI20, BFD_RELOC_RISCV_PCREL_LO12_I);
4922+ break;
4923+
4924+ case M_LWU:
Patrick Georgiaf473ed2015-07-17 23:35:54 +02004925+ pcrel_load (rd, rd, imm_expr, "lwu",
Patrick Georgif0bbc952015-03-07 10:57:25 +01004926+ BFD_RELOC_RISCV_PCREL_HI20, BFD_RELOC_RISCV_PCREL_LO12_I);
4927+ break;
4928+
4929+ case M_LD:
Patrick Georgiaf473ed2015-07-17 23:35:54 +02004930+ pcrel_load (rd, rd, imm_expr, "ld",
Patrick Georgif0bbc952015-03-07 10:57:25 +01004931+ BFD_RELOC_RISCV_PCREL_HI20, BFD_RELOC_RISCV_PCREL_LO12_I);
4932+ break;
4933+
4934+ case M_FLW:
Patrick Georgiaf473ed2015-07-17 23:35:54 +02004935+ pcrel_load (rd, rs1, imm_expr, "flw",
Patrick Georgif0bbc952015-03-07 10:57:25 +01004936+ BFD_RELOC_RISCV_PCREL_HI20, BFD_RELOC_RISCV_PCREL_LO12_I);
4937+ break;
4938+
4939+ case M_FLD:
Patrick Georgiaf473ed2015-07-17 23:35:54 +02004940+ pcrel_load (rd, rs1, imm_expr, "fld",
Patrick Georgif0bbc952015-03-07 10:57:25 +01004941+ BFD_RELOC_RISCV_PCREL_HI20, BFD_RELOC_RISCV_PCREL_LO12_I);
4942+ break;
4943+
4944+ case M_SB:
Patrick Georgiaf473ed2015-07-17 23:35:54 +02004945+ pcrel_store (rs2, rs1, imm_expr, "sb",
Patrick Georgif0bbc952015-03-07 10:57:25 +01004946+ BFD_RELOC_RISCV_PCREL_HI20, BFD_RELOC_RISCV_PCREL_LO12_S);
4947+ break;
4948+
4949+ case M_SH:
Patrick Georgiaf473ed2015-07-17 23:35:54 +02004950+ pcrel_store (rs2, rs1, imm_expr, "sh",
Patrick Georgif0bbc952015-03-07 10:57:25 +01004951+ BFD_RELOC_RISCV_PCREL_HI20, BFD_RELOC_RISCV_PCREL_LO12_S);
4952+ break;
4953+
4954+ case M_SW:
Patrick Georgiaf473ed2015-07-17 23:35:54 +02004955+ pcrel_store (rs2, rs1, imm_expr, "sw",
Patrick Georgif0bbc952015-03-07 10:57:25 +01004956+ BFD_RELOC_RISCV_PCREL_HI20, BFD_RELOC_RISCV_PCREL_LO12_S);
4957+ break;
4958+
4959+ case M_SD:
Patrick Georgiaf473ed2015-07-17 23:35:54 +02004960+ pcrel_store (rs2, rs1, imm_expr, "sd",
Patrick Georgif0bbc952015-03-07 10:57:25 +01004961+ BFD_RELOC_RISCV_PCREL_HI20, BFD_RELOC_RISCV_PCREL_LO12_S);
4962+ break;
4963+
4964+ case M_FSW:
Patrick Georgiaf473ed2015-07-17 23:35:54 +02004965+ pcrel_store (rs2, rs1, imm_expr, "fsw",
Patrick Georgif0bbc952015-03-07 10:57:25 +01004966+ BFD_RELOC_RISCV_PCREL_HI20, BFD_RELOC_RISCV_PCREL_LO12_S);
4967+ break;
4968+
4969+ case M_FSD:
Patrick Georgiaf473ed2015-07-17 23:35:54 +02004970+ pcrel_store (rs2, rs1, imm_expr, "fsd",
Patrick Georgif0bbc952015-03-07 10:57:25 +01004971+ BFD_RELOC_RISCV_PCREL_HI20, BFD_RELOC_RISCV_PCREL_LO12_S);
4972+ break;
4973+
4974+ case M_VF:
Patrick Georgiaf473ed2015-07-17 23:35:54 +02004975+ pcrel_access (0, rs1, imm_expr, "vf", "s,s,q",
Patrick Georgif0bbc952015-03-07 10:57:25 +01004976+ BFD_RELOC_RISCV_PCREL_HI20, BFD_RELOC_RISCV_PCREL_LO12_S);
4977+ break;
4978+
4979+ case M_CALL:
Patrick Georgiaf473ed2015-07-17 23:35:54 +02004980+ riscv_call (rd, rs1, imm_expr, *imm_reloc);
Patrick Georgif0bbc952015-03-07 10:57:25 +01004981+ break;
4982+
4983+ default:
4984+ as_bad (_("Macro %s not implemented"), ip->insn_mo->name);
4985+ break;
4986+ }
4987+}
4988+
4989+static const struct percent_op_match percent_op_utype[] =
4990+{
4991+ {"%tprel_hi", BFD_RELOC_RISCV_TPREL_HI20},
4992+ {"%pcrel_hi", BFD_RELOC_RISCV_PCREL_HI20},
4993+ {"%tls_ie_pcrel_hi", BFD_RELOC_RISCV_TLS_GOT_HI20},
4994+ {"%tls_gd_pcrel_hi", BFD_RELOC_RISCV_TLS_GD_HI20},
4995+ {"%hi", BFD_RELOC_RISCV_HI20},
4996+ {0, 0}
4997+};
4998+
4999+static const struct percent_op_match percent_op_itype[] =
5000+{
5001+ {"%lo", BFD_RELOC_RISCV_LO12_I},
5002+ {"%tprel_lo", BFD_RELOC_RISCV_TPREL_LO12_I},
5003+ {"%pcrel_lo", BFD_RELOC_RISCV_PCREL_LO12_I},
5004+ {0, 0}
5005+};
5006+
5007+static const struct percent_op_match percent_op_stype[] =
5008+{
5009+ {"%lo", BFD_RELOC_RISCV_LO12_S},
5010+ {"%tprel_lo", BFD_RELOC_RISCV_TPREL_LO12_S},
5011+ {"%pcrel_lo", BFD_RELOC_RISCV_PCREL_LO12_S},
5012+ {0, 0}
5013+};
5014+
5015+static const struct percent_op_match percent_op_rtype[] =
5016+{
5017+ {"%tprel_add", BFD_RELOC_RISCV_TPREL_ADD},
5018+ {0, 0}
5019+};
5020+
5021+/* Return true if *STR points to a relocation operator. When returning true,
5022+ move *STR over the operator and store its relocation code in *RELOC.
5023+ Leave both *STR and *RELOC alone when returning false. */
5024+
5025+static bfd_boolean
5026+parse_relocation (char **str, bfd_reloc_code_real_type *reloc,
5027+ const struct percent_op_match *percent_op)
5028+{
5029+ for ( ; percent_op->str; percent_op++)
5030+ if (strncasecmp (*str, percent_op->str, strlen (percent_op->str)) == 0)
5031+ {
5032+ int len = strlen (percent_op->str);
5033+
5034+ if (!ISSPACE ((*str)[len]) && (*str)[len] != '(')
5035+ continue;
5036+
5037+ *str += strlen (percent_op->str);
5038+ *reloc = percent_op->reloc;
5039+
5040+ /* Check whether the output BFD supports this relocation.
5041+ If not, issue an error and fall back on something safe. */
5042+ if (!bfd_reloc_type_lookup (stdoutput, percent_op->reloc))
5043+ {
5044+ as_bad ("relocation %s isn't supported by the current ABI",
5045+ percent_op->str);
5046+ *reloc = BFD_RELOC_UNUSED;
5047+ }
5048+ return TRUE;
5049+ }
5050+ return FALSE;
5051+}
5052+
5053+static void
5054+my_getExpression (expressionS *ep, char *str)
5055+{
5056+ char *save_in;
5057+
5058+ save_in = input_line_pointer;
5059+ input_line_pointer = str;
5060+ expression (ep);
5061+ expr_end = input_line_pointer;
5062+ input_line_pointer = save_in;
5063+}
5064+
5065+/* Parse string STR as a 16-bit relocatable operand. Store the
5066+ expression in *EP and the relocation, if any, in RELOC.
5067+ Return the number of relocation operators used (0 or 1).
5068+
5069+ On exit, EXPR_END points to the first character after the expression. */
5070+
5071+static size_t
5072+my_getSmallExpression (expressionS *ep, bfd_reloc_code_real_type *reloc,
5073+ char *str, const struct percent_op_match *percent_op)
5074+{
5075+ size_t reloc_index;
Patrick Georgiaf473ed2015-07-17 23:35:54 +02005076+ unsigned crux_depth, str_depth, regno;
Patrick Georgif0bbc952015-03-07 10:57:25 +01005077+ char *crux;
5078+
Patrick Georgiaf473ed2015-07-17 23:35:54 +02005079+ /* First, check for integer registers. */
5080+ if (reg_lookup (&str, RCLASS_GPR, &regno))
5081+ {
5082+ ep->X_op = O_register;
5083+ ep->X_add_number = regno;
5084+ return 0;
5085+ }
5086+
Patrick Georgif0bbc952015-03-07 10:57:25 +01005087+ /* Search for the start of the main expression.
5088+ End the loop with CRUX pointing to the start
5089+ of the main expression and with CRUX_DEPTH containing the number
5090+ of open brackets at that point. */
5091+ reloc_index = -1;
5092+ str_depth = 0;
5093+ do
5094+ {
5095+ reloc_index++;
5096+ crux = str;
5097+ crux_depth = str_depth;
5098+
5099+ /* Skip over whitespace and brackets, keeping count of the number
5100+ of brackets. */
5101+ while (*str == ' ' || *str == '\t' || *str == '(')
5102+ if (*str++ == '(')
5103+ str_depth++;
5104+ }
5105+ while (*str == '%'
5106+ && reloc_index < 1
5107+ && parse_relocation (&str, reloc, percent_op));
5108+
5109+ my_getExpression (ep, crux);
5110+ str = expr_end;
5111+
5112+ /* Match every open bracket. */
5113+ while (crux_depth > 0 && (*str == ')' || *str == ' ' || *str == '\t'))
5114+ if (*str++ == ')')
5115+ crux_depth--;
5116+
5117+ if (crux_depth > 0)
5118+ as_bad ("unclosed '('");
5119+
5120+ expr_end = str;
5121+
5122+ return reloc_index;
5123+}
5124+
5125+/* This routine assembles an instruction into its binary format. As a
Patrick Georgiaf473ed2015-07-17 23:35:54 +02005126+ side effect, it sets the global variable imm_reloc to the type of
5127+ relocation to do if one of the operands is an address expression. */
Patrick Georgif0bbc952015-03-07 10:57:25 +01005128+
Patrick Georgiaf473ed2015-07-17 23:35:54 +02005129+static const char *
5130+riscv_ip (char *str, struct riscv_cl_insn *ip, expressionS *imm_expr,
5131+ bfd_reloc_code_real_type *imm_reloc)
Patrick Georgif0bbc952015-03-07 10:57:25 +01005132+{
5133+ char *s;
5134+ const char *args;
5135+ char c = 0;
Patrick Georgiaf473ed2015-07-17 23:35:54 +02005136+ struct riscv_opcode *insn, *end = &riscv_opcodes[NUMOPCODES];
Patrick Georgif0bbc952015-03-07 10:57:25 +01005137+ char *argsStart;
5138+ unsigned int regno;
5139+ char save_c = 0;
5140+ int argnum;
5141+ const struct percent_op_match *p;
Patrick Georgiaf473ed2015-07-17 23:35:54 +02005142+ const char *error = "unrecognized opcode";
Patrick Georgif0bbc952015-03-07 10:57:25 +01005143+
Patrick Georgiaf473ed2015-07-17 23:35:54 +02005144+ /* Parse the name of the instruction. Terminate the string if whitespace
5145+ is found so that hash_find only sees the name part of the string. */
5146+ for (s = str; *s != '\0'; ++s)
5147+ if (ISSPACE (*s))
5148+ {
5149+ save_c = *s;
5150+ *s++ = '\0';
5151+ break;
5152+ }
Patrick Georgif0bbc952015-03-07 10:57:25 +01005153+
5154+ insn = (struct riscv_opcode *) hash_find (op_hash, str);
5155+
Patrick Georgiaf473ed2015-07-17 23:35:54 +02005156+ argsStart = s;
5157+ for ( ; insn && insn < end && strcmp (insn->name, str) == 0; insn++)
Patrick Georgif0bbc952015-03-07 10:57:25 +01005158+ {
Patrick Georgiaf473ed2015-07-17 23:35:54 +02005159+ if (!riscv_subset_supports (insn->subset))
Patrick Georgif0bbc952015-03-07 10:57:25 +01005160+ continue;
5161+
Patrick Georgif0bbc952015-03-07 10:57:25 +01005162+ create_insn (ip, insn);
Patrick Georgif0bbc952015-03-07 10:57:25 +01005163+ argnum = 1;
Patrick Georgiaf473ed2015-07-17 23:35:54 +02005164+
5165+ imm_expr->X_op = O_absent;
5166+ *imm_reloc = BFD_RELOC_UNUSED;
5167+ p = percent_op_itype;
5168+
Patrick Georgif0bbc952015-03-07 10:57:25 +01005169+ for (args = insn->args;; ++args)
5170+ {
5171+ s += strspn (s, " \t");
5172+ switch (*args)
5173+ {
5174+ case '\0': /* end of args */
Patrick Georgiaf473ed2015-07-17 23:35:54 +02005175+ if (insn->pinfo != INSN_MACRO
5176+ && riscv_insn_length (insn->match) == 2
5177+ && !riscv_opts.rvc)
5178+ break;
Patrick Georgif0bbc952015-03-07 10:57:25 +01005179+ if (*s == '\0')
Patrick Georgiaf473ed2015-07-17 23:35:54 +02005180+ {
5181+ error = NULL;
5182+ goto out;
5183+ }
Patrick Georgif0bbc952015-03-07 10:57:25 +01005184+ break;
5185+ /* Xcustom */
5186+ case '^':
5187+ {
5188+ unsigned long max = OP_MASK_RD;
Patrick Georgiaf473ed2015-07-17 23:35:54 +02005189+ my_getExpression (imm_expr, s);
5190+ check_absolute_expr (ip, imm_expr);
Patrick Georgif0bbc952015-03-07 10:57:25 +01005191+ switch (*++args)
5192+ {
5193+ case 'j':
5194+ max = OP_MASK_CUSTOM_IMM;
Patrick Georgiaf473ed2015-07-17 23:35:54 +02005195+ INSERT_OPERAND (CUSTOM_IMM, *ip, imm_expr->X_add_number);
Patrick Georgif0bbc952015-03-07 10:57:25 +01005196+ break;
5197+ case 'd':
Patrick Georgiaf473ed2015-07-17 23:35:54 +02005198+ INSERT_OPERAND (RD, *ip, imm_expr->X_add_number);
Patrick Georgif0bbc952015-03-07 10:57:25 +01005199+ break;
5200+ case 's':
Patrick Georgiaf473ed2015-07-17 23:35:54 +02005201+ INSERT_OPERAND (RS1, *ip, imm_expr->X_add_number);
Patrick Georgif0bbc952015-03-07 10:57:25 +01005202+ break;
5203+ case 't':
Patrick Georgiaf473ed2015-07-17 23:35:54 +02005204+ INSERT_OPERAND (RS2, *ip, imm_expr->X_add_number);
Patrick Georgif0bbc952015-03-07 10:57:25 +01005205+ break;
5206+ }
Patrick Georgiaf473ed2015-07-17 23:35:54 +02005207+ imm_expr->X_op = O_absent;
Patrick Georgif0bbc952015-03-07 10:57:25 +01005208+ s = expr_end;
Patrick Georgiaf473ed2015-07-17 23:35:54 +02005209+ if ((unsigned long) imm_expr->X_add_number > max)
Patrick Georgif0bbc952015-03-07 10:57:25 +01005210+ as_warn ("Bad custom immediate (%lu), must be at most %lu",
Patrick Georgiaf473ed2015-07-17 23:35:54 +02005211+ (unsigned long)imm_expr->X_add_number, max);
Patrick Georgif0bbc952015-03-07 10:57:25 +01005212+ continue;
5213+ }
5214+
5215+ /* Xhwacha */
5216+ case '#':
5217+ switch ( *++args )
5218+ {
5219+ case 'g':
Patrick Georgiaf473ed2015-07-17 23:35:54 +02005220+ my_getExpression( imm_expr, s );
Patrick Georgif0bbc952015-03-07 10:57:25 +01005221+ /* check_absolute_expr( ip, &imm_expr ); */
Patrick Georgiaf473ed2015-07-17 23:35:54 +02005222+ if ((unsigned long) imm_expr->X_add_number > 32 )
Patrick Georgif0bbc952015-03-07 10:57:25 +01005223+ as_warn( _( "Improper ngpr amount (%lu)" ),
Patrick Georgiaf473ed2015-07-17 23:35:54 +02005224+ (unsigned long) imm_expr->X_add_number );
5225+ INSERT_OPERAND( IMMNGPR, *ip, imm_expr->X_add_number );
5226+ imm_expr->X_op = O_absent;
Patrick Georgif0bbc952015-03-07 10:57:25 +01005227+ s = expr_end;
5228+ continue;
5229+ case 'f':
Patrick Georgiaf473ed2015-07-17 23:35:54 +02005230+ my_getExpression( imm_expr, s );
Patrick Georgif0bbc952015-03-07 10:57:25 +01005231+ /* check_absolute_expr( ip, &imm_expr ); */
Patrick Georgiaf473ed2015-07-17 23:35:54 +02005232+ if ((unsigned long) imm_expr->X_add_number > 32 )
Patrick Georgif0bbc952015-03-07 10:57:25 +01005233+ as_warn( _( "Improper nfpr amount (%lu)" ),
Patrick Georgiaf473ed2015-07-17 23:35:54 +02005234+ (unsigned long) imm_expr->X_add_number );
5235+ INSERT_OPERAND( IMMNFPR, *ip, imm_expr->X_add_number );
5236+ imm_expr->X_op = O_absent;
Patrick Georgif0bbc952015-03-07 10:57:25 +01005237+ s = expr_end;
5238+ continue;
5239+ case 'n':
Patrick Georgiaf473ed2015-07-17 23:35:54 +02005240+ my_getExpression( imm_expr, s );
Patrick Georgif0bbc952015-03-07 10:57:25 +01005241+ /* check_absolute_expr( ip, &imm_expr ); */
Patrick Georgiaf473ed2015-07-17 23:35:54 +02005242+ if ((unsigned long) imm_expr->X_add_number > 8 )
Patrick Georgif0bbc952015-03-07 10:57:25 +01005243+ as_warn( _( "Improper nelm amount (%lu)" ),
Patrick Georgiaf473ed2015-07-17 23:35:54 +02005244+ (unsigned long) imm_expr->X_add_number );
5245+ INSERT_OPERAND( IMMSEGNELM, *ip, imm_expr->X_add_number - 1 );
5246+ imm_expr->X_op = O_absent;
Patrick Georgif0bbc952015-03-07 10:57:25 +01005247+ s = expr_end;
5248+ continue;
5249+ case 'd':
Patrick Georgiaf473ed2015-07-17 23:35:54 +02005250+ if (!reg_lookup( &s, RCLASS_VEC_GPR, &regno ))
Patrick Georgif0bbc952015-03-07 10:57:25 +01005251+ as_bad( _( "Invalid vector register" ) );
5252+ INSERT_OPERAND( VRD, *ip, regno );
5253+ continue;
5254+ case 's':
Patrick Georgiaf473ed2015-07-17 23:35:54 +02005255+ if (!reg_lookup( &s, RCLASS_VEC_GPR, &regno ))
Patrick Georgif0bbc952015-03-07 10:57:25 +01005256+ as_bad( _( "Invalid vector register" ) );
5257+ INSERT_OPERAND( VRS, *ip, regno );
5258+ continue;
5259+ case 't':
Patrick Georgiaf473ed2015-07-17 23:35:54 +02005260+ if (!reg_lookup( &s, RCLASS_VEC_GPR, &regno ))
Patrick Georgif0bbc952015-03-07 10:57:25 +01005261+ as_bad( _( "Invalid vector register" ) );
5262+ INSERT_OPERAND( VRT, *ip, regno );
5263+ continue;
5264+ case 'r':
Patrick Georgiaf473ed2015-07-17 23:35:54 +02005265+ if (!reg_lookup( &s, RCLASS_VEC_GPR, &regno ))
Patrick Georgif0bbc952015-03-07 10:57:25 +01005266+ as_bad( _( "Invalid vector register" ) );
5267+ INSERT_OPERAND( VRR, *ip, regno );
5268+ continue;
5269+ case 'D':
Patrick Georgiaf473ed2015-07-17 23:35:54 +02005270+ if (!reg_lookup( &s, RCLASS_VEC_FPR, &regno ))
Patrick Georgif0bbc952015-03-07 10:57:25 +01005271+ as_bad( _( "Invalid vector register" ) );
5272+ INSERT_OPERAND( VFD, *ip, regno );
5273+ continue;
5274+ case 'S':
Patrick Georgiaf473ed2015-07-17 23:35:54 +02005275+ if (!reg_lookup( &s, RCLASS_VEC_FPR, &regno ))
Patrick Georgif0bbc952015-03-07 10:57:25 +01005276+ as_bad( _( "Invalid vector register" ) );
5277+ INSERT_OPERAND( VFS, *ip, regno );
5278+ continue;
5279+ case 'T':
Patrick Georgiaf473ed2015-07-17 23:35:54 +02005280+ if (!reg_lookup( &s, RCLASS_VEC_FPR, &regno ))
Patrick Georgif0bbc952015-03-07 10:57:25 +01005281+ as_bad( _( "Invalid vector register" ) );
5282+ INSERT_OPERAND( VFT, *ip, regno );
5283+ continue;
5284+ case 'R':
Patrick Georgiaf473ed2015-07-17 23:35:54 +02005285+ if (!reg_lookup( &s, RCLASS_VEC_FPR, &regno ))
Patrick Georgif0bbc952015-03-07 10:57:25 +01005286+ as_bad( _( "Invalid vector register" ) );
5287+ INSERT_OPERAND( VFR, *ip, regno );
5288+ continue;
5289+ }
5290+ break;
5291+
Patrick Georgiaf473ed2015-07-17 23:35:54 +02005292+ case 'C': /* RVC */
5293+ switch (*++args)
5294+ {
5295+ case 'd': /* RD x8-x15 */
5296+ if (!reg_lookup (&s, RCLASS_GPR, &regno)
5297+ || !(regno >= 8 && regno <= 15))
5298+ break;
5299+ INSERT_OPERAND (CRDS, *ip, regno % 8);
5300+ continue;
5301+ case 's': /* RS1 x8-x15 */
5302+ if (!reg_lookup (&s, RCLASS_GPR, &regno)
5303+ || !(regno >= 8 && regno <= 15))
5304+ break;
5305+ INSERT_OPERAND (CRS1S, *ip, regno % 8);
5306+ continue;
5307+ case 'w': /* RS1 x8-x15, constrained to equal RD x8-x15 */
5308+ if (!reg_lookup (&s, RCLASS_GPR, &regno)
5309+ || EXTRACT_OPERAND (CRS1S, *ip) + 8 != regno)
5310+ break;
5311+ continue;
5312+ case 't': /* RS2 x8-x15 */
5313+ if (!reg_lookup (&s, RCLASS_GPR, &regno)
5314+ || !(regno >= 8 && regno <= 15))
5315+ break;
5316+ INSERT_OPERAND (CRS2S, *ip, regno % 8);
5317+ continue;
5318+ case 'x': /* RS2 x8-x15, constrained to equal RD x8-x15 */
5319+ if (!reg_lookup (&s, RCLASS_GPR, &regno)
5320+ || EXTRACT_OPERAND (CRS2S, *ip) + 8 != regno)
5321+ break;
5322+ continue;
5323+ case 'D': /* RD, nonzero */
5324+ if (!reg_lookup (&s, RCLASS_GPR, &regno) || regno == 0)
5325+ break;
5326+ INSERT_OPERAND (RD, *ip, regno);
5327+ continue;
5328+ case 'U': /* RS1, constrained to equal RD */
5329+ if (!reg_lookup (&s, RCLASS_GPR, &regno)
5330+ || EXTRACT_OPERAND (RD, *ip) != regno)
5331+ break;
5332+ continue;
5333+ case 'T': /* RS2, nonzero */
5334+ if (!reg_lookup (&s, RCLASS_GPR, &regno) || regno == 0)
5335+ break;
5336+ INSERT_OPERAND (CRS2, *ip, regno);
5337+ continue;
5338+ case 'V': /* RS2 */
5339+ if (!reg_lookup (&s, RCLASS_GPR, &regno))
5340+ break;
5341+ INSERT_OPERAND (CRS2, *ip, regno);
5342+ continue;
5343+ case 'c': /* RS1, constrained to equal sp */
5344+ if (!reg_lookup (&s, RCLASS_GPR, &regno)
5345+ || regno != X_SP)
5346+ break;
5347+ continue;
5348+ case '>':
5349+ if (my_getSmallExpression (imm_expr, imm_reloc, s, p)
5350+ || imm_expr->X_op != O_constant
5351+ || imm_expr->X_add_number <= 0
5352+ || imm_expr->X_add_number >= 64)
5353+ break;
5354+ ip->insn_opcode |= ENCODE_RVC_IMM (imm_expr->X_add_number);
5355+rvc_imm_done:
5356+ s = expr_end;
5357+ imm_expr->X_op = O_absent;
5358+ continue;
5359+ case '<':
5360+ if (my_getSmallExpression (imm_expr, imm_reloc, s, p)
5361+ || imm_expr->X_op != O_constant
5362+ || !VALID_RVC_IMM (imm_expr->X_add_number)
5363+ || imm_expr->X_add_number <= 0
5364+ || imm_expr->X_add_number >= 32)
5365+ break;
5366+ ip->insn_opcode |= ENCODE_RVC_IMM (imm_expr->X_add_number);
5367+ goto rvc_imm_done;
5368+ case 'i':
5369+ if (my_getSmallExpression (imm_expr, imm_reloc, s, p)
5370+ || imm_expr->X_op != O_constant
5371+ || imm_expr->X_add_number == 0
5372+ || !VALID_RVC_SIMM3 (imm_expr->X_add_number))
5373+ break;
5374+ ip->insn_opcode |= ENCODE_RVC_SIMM3 (imm_expr->X_add_number);
5375+ goto rvc_imm_done;
5376+ case 'j':
5377+ if (my_getSmallExpression (imm_expr, imm_reloc, s, p)
5378+ || imm_expr->X_op != O_constant
5379+ || imm_expr->X_add_number == 0
5380+ || !VALID_RVC_IMM (imm_expr->X_add_number))
5381+ break;
5382+ ip->insn_opcode |= ENCODE_RVC_IMM (imm_expr->X_add_number);
5383+ goto rvc_imm_done;
5384+ case 'k':
5385+ if (my_getSmallExpression (imm_expr, imm_reloc, s, p)
5386+ || imm_expr->X_op != O_constant
5387+ || !VALID_RVC_LW_IMM (imm_expr->X_add_number))
5388+ break;
5389+ ip->insn_opcode |= ENCODE_RVC_LW_IMM (imm_expr->X_add_number);
5390+ goto rvc_imm_done;
5391+ case 'l':
5392+ if (my_getSmallExpression (imm_expr, imm_reloc, s, p)
5393+ || imm_expr->X_op != O_constant
5394+ || !VALID_RVC_LD_IMM (imm_expr->X_add_number))
5395+ break;
5396+ ip->insn_opcode |= ENCODE_RVC_LD_IMM (imm_expr->X_add_number);
5397+ goto rvc_imm_done;
5398+ case 'm':
5399+ if (my_getSmallExpression (imm_expr, imm_reloc, s, p)
5400+ || imm_expr->X_op != O_constant
5401+ || !VALID_RVC_LWSP_IMM (imm_expr->X_add_number))
5402+ break;
5403+ ip->insn_opcode |= ENCODE_RVC_LWSP_IMM (imm_expr->X_add_number);
5404+ goto rvc_imm_done;
5405+ case 'n':
5406+ if (my_getSmallExpression (imm_expr, imm_reloc, s, p)
5407+ || imm_expr->X_op != O_constant
5408+ || !VALID_RVC_LDSP_IMM (imm_expr->X_add_number))
5409+ break;
5410+ ip->insn_opcode |= ENCODE_RVC_LDSP_IMM (imm_expr->X_add_number);
5411+ goto rvc_imm_done;
5412+ case 'K':
5413+ if (my_getSmallExpression (imm_expr, imm_reloc, s, p)
5414+ || imm_expr->X_op != O_constant
5415+ || !VALID_RVC_ADDI4SPN_IMM (imm_expr->X_add_number))
5416+ break;
5417+ ip->insn_opcode |= ENCODE_RVC_ADDI4SPN_IMM (imm_expr->X_add_number);
5418+ goto rvc_imm_done;
5419+ case 'L':
5420+ if (my_getSmallExpression (imm_expr, imm_reloc, s, p)
5421+ || imm_expr->X_op != O_constant
5422+ || !VALID_RVC_ADDI16SP_IMM (imm_expr->X_add_number))
5423+ break;
5424+ ip->insn_opcode |= ENCODE_RVC_ADDI16SP_IMM (imm_expr->X_add_number);
5425+ goto rvc_imm_done;
5426+ case 'M':
5427+ if (my_getSmallExpression (imm_expr, imm_reloc, s, p)
5428+ || imm_expr->X_op != O_constant
5429+ || !VALID_RVC_SWSP_IMM (imm_expr->X_add_number))
5430+ break;
5431+ ip->insn_opcode |= ENCODE_RVC_SWSP_IMM (imm_expr->X_add_number);
5432+ goto rvc_imm_done;
5433+ case 'N':
5434+ if (my_getSmallExpression (imm_expr, imm_reloc, s, p)
5435+ || imm_expr->X_op != O_constant
5436+ || !VALID_RVC_SDSP_IMM (imm_expr->X_add_number))
5437+ break;
5438+ ip->insn_opcode |= ENCODE_RVC_SDSP_IMM (imm_expr->X_add_number);
5439+ goto rvc_imm_done;
5440+ case 'u':
5441+ p = percent_op_utype;
5442+ if (my_getSmallExpression (imm_expr, imm_reloc, s, p))
5443+ break;
5444+rvc_lui:
5445+ if (imm_expr->X_op != O_constant
5446+ || imm_expr->X_add_number <= 0
5447+ || imm_expr->X_add_number >= RISCV_BIGIMM_REACH
5448+ || (imm_expr->X_add_number >= RISCV_RVC_IMM_REACH/2
5449+ && imm_expr->X_add_number <
5450+ RISCV_BIGIMM_REACH - RISCV_RVC_IMM_REACH/2))
5451+ break;
5452+ ip->insn_opcode |= ENCODE_RVC_IMM (imm_expr->X_add_number);
5453+ goto rvc_imm_done;
5454+ case 'v':
5455+ if (my_getSmallExpression (imm_expr, imm_reloc, s, p)
5456+ || (imm_expr->X_add_number & (RISCV_IMM_REACH-1))
5457+ || (int32_t)imm_expr->X_add_number
5458+ != imm_expr->X_add_number)
5459+ break;
5460+ imm_expr->X_add_number
5461+ = (uint32_t)imm_expr->X_add_number >> RISCV_IMM_BITS;
5462+ goto rvc_lui;
5463+ case 'p':
5464+ goto branch;
5465+ case 'a':
5466+ goto jump;
5467+ default:
5468+ as_bad (_("bad RVC field specifier 'C%c'\n"), *args);
5469+ }
5470+ break;
5471+
Patrick Georgif0bbc952015-03-07 10:57:25 +01005472+ case ',':
5473+ ++argnum;
5474+ if (*s++ == *args)
5475+ continue;
5476+ s--;
5477+ break;
5478+
5479+ case '(':
5480+ case ')':
5481+ case '[':
5482+ case ']':
5483+ if (*s++ == *args)
5484+ continue;
5485+ break;
5486+
5487+ case '<': /* shift amount, 0 - 31 */
Patrick Georgiaf473ed2015-07-17 23:35:54 +02005488+ my_getExpression (imm_expr, s);
5489+ check_absolute_expr (ip, imm_expr);
5490+ if ((unsigned long) imm_expr->X_add_number > 31)
Patrick Georgif0bbc952015-03-07 10:57:25 +01005491+ as_warn (_("Improper shift amount (%lu)"),
Patrick Georgiaf473ed2015-07-17 23:35:54 +02005492+ (unsigned long) imm_expr->X_add_number);
5493+ INSERT_OPERAND (SHAMTW, *ip, imm_expr->X_add_number);
5494+ imm_expr->X_op = O_absent;
Patrick Georgif0bbc952015-03-07 10:57:25 +01005495+ s = expr_end;
5496+ continue;
5497+
5498+ case '>': /* shift amount, 0 - (XLEN-1) */
Patrick Georgiaf473ed2015-07-17 23:35:54 +02005499+ my_getExpression (imm_expr, s);
5500+ check_absolute_expr (ip, imm_expr);
5501+ if ((unsigned long) imm_expr->X_add_number >= xlen)
Patrick Georgif0bbc952015-03-07 10:57:25 +01005502+ as_warn (_("Improper shift amount (%lu)"),
Patrick Georgiaf473ed2015-07-17 23:35:54 +02005503+ (unsigned long) imm_expr->X_add_number);
5504+ INSERT_OPERAND (SHAMT, *ip, imm_expr->X_add_number);
5505+ imm_expr->X_op = O_absent;
Patrick Georgif0bbc952015-03-07 10:57:25 +01005506+ s = expr_end;
5507+ continue;
5508+
5509+ case 'Z': /* CSRRxI immediate */
Patrick Georgiaf473ed2015-07-17 23:35:54 +02005510+ my_getExpression (imm_expr, s);
5511+ check_absolute_expr (ip, imm_expr);
5512+ if ((unsigned long) imm_expr->X_add_number > 31)
Patrick Georgif0bbc952015-03-07 10:57:25 +01005513+ as_warn (_("Improper CSRxI immediate (%lu)"),
Patrick Georgiaf473ed2015-07-17 23:35:54 +02005514+ (unsigned long) imm_expr->X_add_number);
5515+ INSERT_OPERAND (RS1, *ip, imm_expr->X_add_number);
5516+ imm_expr->X_op = O_absent;
Patrick Georgif0bbc952015-03-07 10:57:25 +01005517+ s = expr_end;
5518+ continue;
5519+
5520+ case 'E': /* Control register. */
Patrick Georgiaf473ed2015-07-17 23:35:54 +02005521+ if (reg_lookup (&s, RCLASS_CSR, &regno))
Patrick Georgif0bbc952015-03-07 10:57:25 +01005522+ INSERT_OPERAND (CSR, *ip, regno);
5523+ else
5524+ {
Patrick Georgiaf473ed2015-07-17 23:35:54 +02005525+ my_getExpression (imm_expr, s);
5526+ check_absolute_expr (ip, imm_expr);
5527+ if ((unsigned long) imm_expr->X_add_number > 0xfff)
Patrick Georgif0bbc952015-03-07 10:57:25 +01005528+ as_warn(_("Improper CSR address (%lu)"),
Patrick Georgiaf473ed2015-07-17 23:35:54 +02005529+ (unsigned long) imm_expr->X_add_number);
5530+ INSERT_OPERAND (CSR, *ip, imm_expr->X_add_number);
5531+ imm_expr->X_op = O_absent;
Patrick Georgif0bbc952015-03-07 10:57:25 +01005532+ s = expr_end;
5533+ }
5534+ continue;
5535+
5536+ case 'm': /* rounding mode */
5537+ if (arg_lookup (&s, riscv_rm, ARRAY_SIZE(riscv_rm), &regno))
5538+ {
5539+ INSERT_OPERAND (RM, *ip, regno);
5540+ continue;
5541+ }
5542+ break;
5543+
5544+ case 'P':
5545+ case 'Q': /* fence predecessor/successor */
5546+ if (arg_lookup (&s, riscv_pred_succ, ARRAY_SIZE(riscv_pred_succ), &regno))
5547+ {
5548+ if (*args == 'P')
5549+ INSERT_OPERAND(PRED, *ip, regno);
5550+ else
5551+ INSERT_OPERAND(SUCC, *ip, regno);
5552+ continue;
5553+ }
5554+ break;
5555+
5556+ case 'd': /* destination register */
5557+ case 's': /* source register */
5558+ case 't': /* target register */
Patrick Georgiaf473ed2015-07-17 23:35:54 +02005559+ if (reg_lookup (&s, RCLASS_GPR, &regno))
Patrick Georgif0bbc952015-03-07 10:57:25 +01005560+ {
5561+ c = *args;
5562+ if (*s == ' ')
5563+ ++s;
5564+
5565+ /* Now that we have assembled one operand, we use the args string
5566+ * to figure out where it goes in the instruction. */
5567+ switch (c)
5568+ {
5569+ case 's':
5570+ INSERT_OPERAND (RS1, *ip, regno);
5571+ break;
5572+ case 'd':
5573+ INSERT_OPERAND (RD, *ip, regno);
5574+ break;
5575+ case 't':
5576+ INSERT_OPERAND (RS2, *ip, regno);
5577+ break;
5578+ }
5579+ continue;
5580+ }
5581+ break;
5582+
5583+ case 'D': /* floating point rd */
5584+ case 'S': /* floating point rs1 */
5585+ case 'T': /* floating point rs2 */
5586+ case 'U': /* floating point rs1 and rs2 */
5587+ case 'R': /* floating point rs3 */
5588+ if (reg_lookup (&s, RCLASS_FPR, &regno))
5589+ {
5590+ c = *args;
5591+ if (*s == ' ')
5592+ ++s;
5593+ switch (c)
5594+ {
5595+ case 'D':
5596+ INSERT_OPERAND (RD, *ip, regno);
5597+ break;
5598+ case 'S':
5599+ INSERT_OPERAND (RS1, *ip, regno);
5600+ break;
5601+ case 'U':
5602+ INSERT_OPERAND (RS1, *ip, regno);
5603+ /* fallthru */
5604+ case 'T':
5605+ INSERT_OPERAND (RS2, *ip, regno);
5606+ break;
5607+ case 'R':
5608+ INSERT_OPERAND (RS3, *ip, regno);
5609+ break;
5610+ }
5611+ continue;
5612+ }
5613+
5614+ break;
5615+
5616+ case 'I':
Patrick Georgiaf473ed2015-07-17 23:35:54 +02005617+ my_getExpression (imm_expr, s);
5618+ if (imm_expr->X_op != O_big
5619+ && imm_expr->X_op != O_constant)
5620+ break;
5621+ normalize_constant_expr (imm_expr);
Patrick Georgif0bbc952015-03-07 10:57:25 +01005622+ s = expr_end;
5623+ continue;
5624+
5625+ case 'A':
Patrick Georgiaf473ed2015-07-17 23:35:54 +02005626+ my_getExpression (imm_expr, s);
5627+ normalize_constant_expr (imm_expr);
5628+ *imm_reloc = BFD_RELOC_32;
Patrick Georgif0bbc952015-03-07 10:57:25 +01005629+ s = expr_end;
5630+ continue;
5631+
5632+ case 'j': /* sign-extended immediate */
Patrick Georgiaf473ed2015-07-17 23:35:54 +02005633+ *imm_reloc = BFD_RELOC_RISCV_LO12_I;
Patrick Georgif0bbc952015-03-07 10:57:25 +01005634+ p = percent_op_itype;
5635+ goto alu_op;
5636+ case 'q': /* store displacement */
5637+ p = percent_op_stype;
Patrick Georgiaf473ed2015-07-17 23:35:54 +02005638+ *imm_reloc = BFD_RELOC_RISCV_LO12_S;
Patrick Georgif0bbc952015-03-07 10:57:25 +01005639+ goto load_store;
5640+ case 'o': /* load displacement */
5641+ p = percent_op_itype;
Patrick Georgiaf473ed2015-07-17 23:35:54 +02005642+ *imm_reloc = BFD_RELOC_RISCV_LO12_I;
Patrick Georgif0bbc952015-03-07 10:57:25 +01005643+ goto load_store;
5644+ case '0': /* AMO "displacement," which must be zero */
5645+ p = percent_op_rtype;
Patrick Georgiaf473ed2015-07-17 23:35:54 +02005646+ *imm_reloc = BFD_RELOC_UNUSED;
Patrick Georgif0bbc952015-03-07 10:57:25 +01005647+load_store:
5648+ /* Check whether there is only a single bracketed expression
5649+ left. If so, it must be the base register and the
5650+ constant must be zero. */
Patrick Georgiaf473ed2015-07-17 23:35:54 +02005651+ imm_expr->X_op = O_constant;
5652+ imm_expr->X_add_number = 0;
Patrick Georgif0bbc952015-03-07 10:57:25 +01005653+ if (*s == '(' && strchr (s + 1, '(') == 0)
5654+ continue;
5655+alu_op:
5656+ /* If this value won't fit into a 16 bit offset, then go
5657+ find a macro that will generate the 32 bit offset
5658+ code pattern. */
Patrick Georgiaf473ed2015-07-17 23:35:54 +02005659+ if (!my_getSmallExpression (imm_expr, imm_reloc, s, p))
Patrick Georgif0bbc952015-03-07 10:57:25 +01005660+ {
Patrick Georgiaf473ed2015-07-17 23:35:54 +02005661+ normalize_constant_expr (imm_expr);
5662+ if (imm_expr->X_op != O_constant
5663+ || (*args == '0' && imm_expr->X_add_number != 0)
5664+ || imm_expr->X_add_number >= (signed)RISCV_IMM_REACH/2
5665+ || imm_expr->X_add_number < -(signed)RISCV_IMM_REACH/2)
Patrick Georgif0bbc952015-03-07 10:57:25 +01005666+ break;
5667+ }
5668+
5669+ s = expr_end;
5670+ continue;
5671+
5672+ case 'p': /* pc relative offset */
Patrick Georgiaf473ed2015-07-17 23:35:54 +02005673+branch:
5674+ *imm_reloc = BFD_RELOC_12_PCREL;
5675+ my_getExpression (imm_expr, s);
Patrick Georgif0bbc952015-03-07 10:57:25 +01005676+ s = expr_end;
5677+ continue;
5678+
5679+ case 'u': /* upper 20 bits */
5680+ p = percent_op_utype;
Patrick Georgiaf473ed2015-07-17 23:35:54 +02005681+ if (!my_getSmallExpression (imm_expr, imm_reloc, s, p)
5682+ && imm_expr->X_op == O_constant)
Patrick Georgif0bbc952015-03-07 10:57:25 +01005683+ {
Patrick Georgiaf473ed2015-07-17 23:35:54 +02005684+ if (imm_expr->X_add_number < 0
5685+ || imm_expr->X_add_number >= (signed)RISCV_BIGIMM_REACH)
Patrick Georgif0bbc952015-03-07 10:57:25 +01005686+ as_bad (_("lui expression not in range 0..1048575"));
5687+
Patrick Georgiaf473ed2015-07-17 23:35:54 +02005688+ *imm_reloc = BFD_RELOC_RISCV_HI20;
5689+ imm_expr->X_add_number <<= RISCV_IMM_BITS;
Patrick Georgif0bbc952015-03-07 10:57:25 +01005690+ }
5691+ s = expr_end;
5692+ continue;
5693+
5694+ case 'a': /* 26 bit address */
Patrick Georgiaf473ed2015-07-17 23:35:54 +02005695+jump:
5696+ my_getExpression (imm_expr, s);
Patrick Georgif0bbc952015-03-07 10:57:25 +01005697+ s = expr_end;
Patrick Georgiaf473ed2015-07-17 23:35:54 +02005698+ *imm_reloc = BFD_RELOC_RISCV_JMP;
Patrick Georgif0bbc952015-03-07 10:57:25 +01005699+ continue;
5700+
5701+ case 'c':
Patrick Georgiaf473ed2015-07-17 23:35:54 +02005702+ my_getExpression (imm_expr, s);
Patrick Georgif0bbc952015-03-07 10:57:25 +01005703+ s = expr_end;
Patrick Georgiaf473ed2015-07-17 23:35:54 +02005704+ *imm_reloc = BFD_RELOC_RISCV_CALL;
Patrick Georgif0bbc952015-03-07 10:57:25 +01005705+ if (*s == '@')
Patrick Georgiaf473ed2015-07-17 23:35:54 +02005706+ *imm_reloc = BFD_RELOC_RISCV_CALL_PLT, s++;
Patrick Georgif0bbc952015-03-07 10:57:25 +01005707+ continue;
5708+
5709+ default:
5710+ as_bad (_("bad char = '%c'\n"), *args);
5711+ internalError ();
5712+ }
5713+ break;
5714+ }
Patrick Georgiaf473ed2015-07-17 23:35:54 +02005715+ s = argsStart;
5716+ error = _("illegal operands");
Patrick Georgif0bbc952015-03-07 10:57:25 +01005717+ }
Patrick Georgiaf473ed2015-07-17 23:35:54 +02005718+
5719+out:
5720+ /* Restore the character we might have clobbered above. */
5721+ if (save_c)
5722+ *(argsStart - 1) = save_c;
5723+
5724+ return error;
Patrick Georgif0bbc952015-03-07 10:57:25 +01005725+}
5726+
5727+void
5728+md_assemble (char *str)
5729+{
5730+ struct riscv_cl_insn insn;
Patrick Georgiaf473ed2015-07-17 23:35:54 +02005731+ expressionS imm_expr;
5732+ bfd_reloc_code_real_type imm_reloc = BFD_RELOC_UNUSED;
Patrick Georgif0bbc952015-03-07 10:57:25 +01005733+
Patrick Georgiaf473ed2015-07-17 23:35:54 +02005734+ const char *error = riscv_ip (str, &insn, &imm_expr, &imm_reloc);
Patrick Georgif0bbc952015-03-07 10:57:25 +01005735+
Patrick Georgiaf473ed2015-07-17 23:35:54 +02005736+ if (error)
Patrick Georgif0bbc952015-03-07 10:57:25 +01005737+ {
Patrick Georgiaf473ed2015-07-17 23:35:54 +02005738+ as_bad ("%s `%s'", error, str);
Patrick Georgif0bbc952015-03-07 10:57:25 +01005739+ return;
5740+ }
5741+
5742+ if (insn.insn_mo->pinfo == INSN_MACRO)
Patrick Georgiaf473ed2015-07-17 23:35:54 +02005743+ macro (&insn, &imm_expr, &imm_reloc);
Patrick Georgif0bbc952015-03-07 10:57:25 +01005744+ else
Patrick Georgiaf473ed2015-07-17 23:35:54 +02005745+ append_insn (&insn, &imm_expr, imm_reloc);
Patrick Georgif0bbc952015-03-07 10:57:25 +01005746+}
5747+
5748+char *
5749+md_atof (int type, char *litP, int *sizeP)
5750+{
5751+ return ieee_md_atof (type, litP, sizeP, TARGET_BYTES_BIG_ENDIAN);
5752+}
5753+
5754+void
5755+md_number_to_chars (char *buf, valueT val, int n)
5756+{
5757+ number_to_chars_littleendian (buf, val, n);
5758+}
5759+
5760+const char *md_shortopts = "O::g::G:";
5761+
5762+enum options
5763+ {
5764+ OPTION_M32 = OPTION_MD_BASE,
5765+ OPTION_M64,
5766+ OPTION_MARCH,
5767+ OPTION_PIC,
5768+ OPTION_NO_PIC,
5769+ OPTION_MRVC,
5770+ OPTION_MNO_RVC,
5771+ OPTION_END_OF_ENUM
5772+ };
5773+
5774+struct option md_longopts[] =
5775+{
5776+ {"m32", no_argument, NULL, OPTION_M32},
5777+ {"m64", no_argument, NULL, OPTION_M64},
5778+ {"march", required_argument, NULL, OPTION_MARCH},
5779+ {"fPIC", no_argument, NULL, OPTION_PIC},
5780+ {"fpic", no_argument, NULL, OPTION_PIC},
5781+ {"fno-pic", no_argument, NULL, OPTION_NO_PIC},
5782+ {"mrvc", no_argument, NULL, OPTION_MRVC},
5783+ {"mno-rvc", no_argument, NULL, OPTION_MNO_RVC},
5784+
5785+ {NULL, no_argument, NULL, 0}
5786+};
5787+size_t md_longopts_size = sizeof (md_longopts);
5788+
5789+int
5790+md_parse_option (int c, char *arg)
5791+{
5792+ switch (c)
5793+ {
5794+ case OPTION_MRVC:
5795+ riscv_opts.rvc = 1;
5796+ break;
5797+
5798+ case OPTION_MNO_RVC:
5799+ riscv_opts.rvc = 0;
5800+ break;
5801+
5802+ case OPTION_M32:
Patrick Georgiaf473ed2015-07-17 23:35:54 +02005803+ xlen = 32;
Patrick Georgif0bbc952015-03-07 10:57:25 +01005804+ break;
5805+
5806+ case OPTION_M64:
Patrick Georgiaf473ed2015-07-17 23:35:54 +02005807+ xlen = 64;
Patrick Georgif0bbc952015-03-07 10:57:25 +01005808+ break;
5809+
5810+ case OPTION_MARCH:
Patrick Georgiaf473ed2015-07-17 23:35:54 +02005811+ riscv_set_arch (arg);
5812+ break;
Patrick Georgif0bbc952015-03-07 10:57:25 +01005813+
5814+ case OPTION_NO_PIC:
5815+ riscv_opts.pic = FALSE;
5816+ break;
5817+
5818+ case OPTION_PIC:
5819+ riscv_opts.pic = TRUE;
5820+ break;
5821+
5822+ default:
5823+ return 0;
5824+ }
5825+
5826+ return 1;
5827+}
5828+
5829+void
5830+riscv_after_parse_args (void)
5831+{
5832+ if (riscv_subsets == NULL)
Patrick Georgiaf473ed2015-07-17 23:35:54 +02005833+ riscv_set_arch ("RVIMAFDXcustom");
5834+
5835+ if (xlen == 0)
5836+ {
5837+ if (strcmp (default_arch, "riscv32") == 0)
5838+ xlen = 32;
5839+ else if (strcmp (default_arch, "riscv64") == 0)
5840+ xlen = 64;
5841+ else
5842+ as_bad ("unknown default architecture `%s'", default_arch);
5843+ }
5844+
5845+ if (riscv_opts.rvc)
5846+ elf_flags |= EF_RISCV_RVC;
Patrick Georgif0bbc952015-03-07 10:57:25 +01005847+}
5848+
5849+void
5850+riscv_init_after_args (void)
5851+{
5852+ /* initialize opcodes */
5853+ bfd_riscv_num_opcodes = bfd_riscv_num_builtin_opcodes;
5854+ riscv_opcodes = (struct riscv_opcode *) riscv_builtin_opcodes;
5855+}
5856+
5857+long
5858+md_pcrel_from (fixS *fixP)
5859+{
5860+ return fixP->fx_where + fixP->fx_frag->fr_address;
5861+}
5862+
5863+/* Apply a fixup to the object file. */
5864+
5865+void
5866+md_apply_fix (fixS *fixP, valueT *valP, segT seg ATTRIBUTE_UNUSED)
5867+{
5868+ bfd_byte *buf = (bfd_byte *) (fixP->fx_frag->fr_literal + fixP->fx_where);
5869+
5870+ /* Remember value for tc_gen_reloc. */
5871+ fixP->fx_addnumber = *valP;
5872+
5873+ switch (fixP->fx_r_type)
5874+ {
5875+ case BFD_RELOC_RISCV_TLS_GOT_HI20:
5876+ case BFD_RELOC_RISCV_TLS_GD_HI20:
5877+ case BFD_RELOC_RISCV_TLS_DTPREL32:
5878+ case BFD_RELOC_RISCV_TLS_DTPREL64:
5879+ case BFD_RELOC_RISCV_TPREL_HI20:
5880+ case BFD_RELOC_RISCV_TPREL_LO12_I:
5881+ case BFD_RELOC_RISCV_TPREL_LO12_S:
5882+ case BFD_RELOC_RISCV_TPREL_ADD:
5883+ S_SET_THREAD_LOCAL (fixP->fx_addsy);
5884+ /* fall through */
5885+
5886+ case BFD_RELOC_RISCV_GOT_HI20:
5887+ case BFD_RELOC_RISCV_PCREL_HI20:
5888+ case BFD_RELOC_RISCV_HI20:
5889+ case BFD_RELOC_RISCV_LO12_I:
5890+ case BFD_RELOC_RISCV_LO12_S:
5891+ case BFD_RELOC_RISCV_ADD8:
5892+ case BFD_RELOC_RISCV_ADD16:
5893+ case BFD_RELOC_RISCV_ADD32:
5894+ case BFD_RELOC_RISCV_ADD64:
5895+ case BFD_RELOC_RISCV_SUB8:
5896+ case BFD_RELOC_RISCV_SUB16:
5897+ case BFD_RELOC_RISCV_SUB32:
5898+ case BFD_RELOC_RISCV_SUB64:
5899+ gas_assert (fixP->fx_addsy != NULL);
5900+ /* Nothing needed to do. The value comes from the reloc entry. */
5901+ break;
5902+
5903+ case BFD_RELOC_64:
5904+ case BFD_RELOC_32:
5905+ case BFD_RELOC_16:
5906+ case BFD_RELOC_8:
5907+ if (fixP->fx_addsy && fixP->fx_subsy)
5908+ {
5909+ fixP->fx_next = xmemdup (fixP, sizeof (*fixP), sizeof (*fixP));
5910+ fixP->fx_next->fx_addsy = fixP->fx_subsy;
5911+ fixP->fx_next->fx_subsy = NULL;
5912+ fixP->fx_next->fx_offset = 0;
5913+ fixP->fx_subsy = NULL;
5914+
5915+ if (fixP->fx_r_type == BFD_RELOC_64)
5916+ fixP->fx_r_type = BFD_RELOC_RISCV_ADD64,
5917+ fixP->fx_next->fx_r_type = BFD_RELOC_RISCV_SUB64;
5918+ else if (fixP->fx_r_type == BFD_RELOC_32)
5919+ fixP->fx_r_type = BFD_RELOC_RISCV_ADD32,
5920+ fixP->fx_next->fx_r_type = BFD_RELOC_RISCV_SUB32;
5921+ else if (fixP->fx_r_type == BFD_RELOC_16)
5922+ fixP->fx_r_type = BFD_RELOC_RISCV_ADD16,
5923+ fixP->fx_next->fx_r_type = BFD_RELOC_RISCV_SUB16;
5924+ else
5925+ fixP->fx_r_type = BFD_RELOC_RISCV_ADD8,
5926+ fixP->fx_next->fx_r_type = BFD_RELOC_RISCV_SUB8;
5927+ }
5928+ /* fall through */
5929+
5930+ case BFD_RELOC_RVA:
5931+ /* If we are deleting this reloc entry, we must fill in the
5932+ value now. This can happen if we have a .word which is not
5933+ resolved when it appears but is later defined. */
5934+ if (fixP->fx_addsy == NULL)
5935+ {
5936+ gas_assert (fixP->fx_size <= sizeof (valueT));
5937+ md_number_to_chars ((char *) buf, *valP, fixP->fx_size);
5938+ fixP->fx_done = 1;
5939+ }
5940+ break;
5941+
5942+ case BFD_RELOC_RISCV_JMP:
5943+ if (fixP->fx_addsy)
5944+ {
5945+ /* Fill in a tentative value to improve objdump readability. */
Patrick Georgiaf473ed2015-07-17 23:35:54 +02005946+ bfd_vma delta = ENCODE_UJTYPE_IMM (S_GET_VALUE (fixP->fx_addsy) + *valP - md_pcrel_from (fixP));
Patrick Georgif0bbc952015-03-07 10:57:25 +01005947+ bfd_putl32 (bfd_getl32 (buf) | delta, buf);
5948+ }
5949+ break;
5950+
5951+ case BFD_RELOC_12_PCREL:
5952+ if (fixP->fx_addsy)
5953+ {
5954+ /* Fill in a tentative value to improve objdump readability. */
Patrick Georgiaf473ed2015-07-17 23:35:54 +02005955+ bfd_vma delta = ENCODE_SBTYPE_IMM (S_GET_VALUE (fixP->fx_addsy) + *valP - md_pcrel_from (fixP));
Patrick Georgif0bbc952015-03-07 10:57:25 +01005956+ bfd_putl32 (bfd_getl32 (buf) | delta, buf);
5957+ }
5958+ break;
5959+
Patrick Georgiaf473ed2015-07-17 23:35:54 +02005960+ case BFD_RELOC_RISCV_RVC_BRANCH:
5961+ if (fixP->fx_addsy)
5962+ {
5963+ /* Fill in a tentative value to improve objdump readability. */
5964+ bfd_vma delta = ENCODE_RVC_B_IMM (S_GET_VALUE (fixP->fx_addsy) + *valP - md_pcrel_from (fixP));
5965+ bfd_putl16 (bfd_getl16 (buf) | delta, buf);
5966+ }
5967+ break;
5968+
5969+ case BFD_RELOC_RISCV_RVC_JUMP:
5970+ if (fixP->fx_addsy)
5971+ {
5972+ /* Fill in a tentative value to improve objdump readability. */
5973+ bfd_vma delta = ENCODE_RVC_J_IMM (S_GET_VALUE (fixP->fx_addsy) + *valP - md_pcrel_from (fixP));
5974+ bfd_putl16 (bfd_getl16 (buf) | delta, buf);
5975+ }
5976+ break;
5977+
Patrick Georgif0bbc952015-03-07 10:57:25 +01005978+ case BFD_RELOC_RISCV_PCREL_LO12_S:
5979+ case BFD_RELOC_RISCV_PCREL_LO12_I:
5980+ case BFD_RELOC_RISCV_CALL:
5981+ case BFD_RELOC_RISCV_CALL_PLT:
5982+ case BFD_RELOC_RISCV_ALIGN:
5983+ break;
5984+
5985+ default:
5986+ /* We ignore generic BFD relocations we don't know about. */
5987+ if (bfd_reloc_type_lookup (stdoutput, fixP->fx_r_type) != NULL)
5988+ internalError ();
5989+ }
5990+}
5991+
Patrick Georgiaf473ed2015-07-17 23:35:54 +02005992+/* This structure is used to hold a stack of .option values. */
Patrick Georgif0bbc952015-03-07 10:57:25 +01005993+
5994+struct riscv_option_stack
5995+{
5996+ struct riscv_option_stack *next;
5997+ struct riscv_set_options options;
5998+};
5999+
6000+static struct riscv_option_stack *riscv_opts_stack;
6001+
Patrick Georgiaf473ed2015-07-17 23:35:54 +02006002+/* Handle the .option pseudo-op. */
Patrick Georgif0bbc952015-03-07 10:57:25 +01006003+
6004+static void
6005+s_riscv_option (int x ATTRIBUTE_UNUSED)
6006+{
6007+ char *name = input_line_pointer, ch;
6008+
6009+ while (!is_end_of_line[(unsigned char) *input_line_pointer])
6010+ ++input_line_pointer;
6011+ ch = *input_line_pointer;
6012+ *input_line_pointer = '\0';
6013+
6014+ if (strcmp (name, "rvc") == 0)
6015+ riscv_opts.rvc = 1;
6016+ else if (strcmp (name, "norvc") == 0)
6017+ riscv_opts.rvc = 0;
6018+ else if (strcmp (name, "push") == 0)
6019+ {
6020+ struct riscv_option_stack *s;
6021+
6022+ s = (struct riscv_option_stack *) xmalloc (sizeof *s);
6023+ s->next = riscv_opts_stack;
6024+ s->options = riscv_opts;
6025+ riscv_opts_stack = s;
6026+ }
6027+ else if (strcmp (name, "pop") == 0)
6028+ {
6029+ struct riscv_option_stack *s;
6030+
6031+ s = riscv_opts_stack;
6032+ if (s == NULL)
6033+ as_bad (_(".option pop with no .option push"));
6034+ else
6035+ {
6036+ riscv_opts = s->options;
6037+ riscv_opts_stack = s->next;
6038+ free (s);
6039+ }
6040+ }
6041+ else
6042+ {
6043+ as_warn (_("Unrecognized .option directive: %s\n"), name);
6044+ }
6045+ *input_line_pointer = ch;
6046+ demand_empty_rest_of_line ();
6047+}
6048+
6049+/* Handle the .dtprelword and .dtpreldword pseudo-ops. They generate
6050+ a 32-bit or 64-bit DTP-relative relocation (BYTES says which) for
6051+ use in DWARF debug information. */
6052+
6053+static void
6054+s_dtprel (int bytes)
6055+{
6056+ expressionS ex;
6057+ char *p;
6058+
6059+ expression (&ex);
6060+
6061+ if (ex.X_op != O_symbol)
6062+ {
6063+ as_bad (_("Unsupported use of %s"), (bytes == 8
6064+ ? ".dtpreldword"
6065+ : ".dtprelword"));
6066+ ignore_rest_of_line ();
6067+ }
6068+
6069+ p = frag_more (bytes);
6070+ md_number_to_chars (p, 0, bytes);
6071+ fix_new_exp (frag_now, p - frag_now->fr_literal, bytes, &ex, FALSE,
6072+ (bytes == 8
6073+ ? BFD_RELOC_RISCV_TLS_DTPREL64
6074+ : BFD_RELOC_RISCV_TLS_DTPREL32));
6075+
6076+ demand_empty_rest_of_line ();
6077+}
6078+
6079+/* Handle the .bss pseudo-op. */
6080+
6081+static void
6082+s_bss (int ignore ATTRIBUTE_UNUSED)
6083+{
6084+ subseg_set (bss_section, 0);
6085+ demand_empty_rest_of_line ();
6086+}
6087+
6088+/* Align to a given power of two. */
6089+
6090+static void
Patrick Georgiaf473ed2015-07-17 23:35:54 +02006091+s_align (int bytes_p)
Patrick Georgif0bbc952015-03-07 10:57:25 +01006092+{
Patrick Georgiaf473ed2015-07-17 23:35:54 +02006093+ int fill_value = 0, fill_value_specified = 0;
6094+ int min_text_alignment = riscv_opts.rvc ? 2 : 4;
6095+ int alignment = get_absolute_expression(), bytes;
Patrick Georgif0bbc952015-03-07 10:57:25 +01006096+
Patrick Georgiaf473ed2015-07-17 23:35:54 +02006097+ if (bytes_p)
6098+ {
6099+ bytes = alignment;
6100+ if (bytes < 1 || (bytes & (bytes-1)) != 0)
6101+ as_bad (_("alignment not a power of 2: %d"), bytes);
6102+ for (alignment = 0; bytes > 1; bytes >>= 1)
6103+ alignment++;
6104+ }
6105+
6106+ bytes = 1 << alignment;
6107+
Patrick Georgif0bbc952015-03-07 10:57:25 +01006108+ if (alignment < 0 || alignment > 31)
6109+ as_bad (_("unsatisfiable alignment: %d"), alignment);
6110+
6111+ if (*input_line_pointer == ',')
6112+ {
6113+ ++input_line_pointer;
6114+ fill_value = get_absolute_expression ();
6115+ fill_value_specified = 1;
6116+ }
6117+
Patrick Georgiaf473ed2015-07-17 23:35:54 +02006118+ if (!fill_value_specified && subseg_text_p (now_seg)
6119+ && bytes > min_text_alignment)
Patrick Georgif0bbc952015-03-07 10:57:25 +01006120+ {
6121+ /* Emit the worst-case NOP string. The linker will delete any
6122+ unnecessary NOPs. This allows us to support code alignment
6123+ in spite of linker relaxations. */
Patrick Georgiaf473ed2015-07-17 23:35:54 +02006124+ bfd_vma i, worst_case_bytes = bytes - min_text_alignment;
6125+ char *nops = frag_more (worst_case_bytes);
6126+ for (i = 0; i < worst_case_bytes - 2; i += 4)
Patrick Georgif0bbc952015-03-07 10:57:25 +01006127+ md_number_to_chars (nops + i, RISCV_NOP, 4);
Patrick Georgiaf473ed2015-07-17 23:35:54 +02006128+ if (i < worst_case_bytes)
6129+ md_number_to_chars (nops + i, RVC_NOP, 2);
Patrick Georgif0bbc952015-03-07 10:57:25 +01006130+
6131+ expressionS ex;
6132+ ex.X_op = O_constant;
Patrick Georgiaf473ed2015-07-17 23:35:54 +02006133+ ex.X_add_number = worst_case_bytes;
Patrick Georgif0bbc952015-03-07 10:57:25 +01006134+
6135+ fix_new_exp (frag_now, nops - frag_now->fr_literal, 0,
Patrick Georgiaf473ed2015-07-17 23:35:54 +02006136+ &ex, FALSE, BFD_RELOC_RISCV_ALIGN);
Patrick Georgif0bbc952015-03-07 10:57:25 +01006137+ }
6138+ else if (alignment)
6139+ frag_align (alignment, fill_value, 0);
6140+
6141+ record_alignment (now_seg, alignment);
6142+
6143+ demand_empty_rest_of_line ();
6144+}
6145+
6146+int
6147+md_estimate_size_before_relax (fragS *fragp, asection *segtype)
6148+{
6149+ return (fragp->fr_var = relaxed_branch_length (fragp, segtype, FALSE));
6150+}
6151+
6152+/* Translate internal representation of relocation info to BFD target
6153+ format. */
6154+
6155+arelent *
6156+tc_gen_reloc (asection *section ATTRIBUTE_UNUSED, fixS *fixp)
6157+{
6158+ arelent *reloc = (arelent *) xmalloc (sizeof (arelent));
6159+
6160+ reloc->sym_ptr_ptr = (asymbol **) xmalloc (sizeof (asymbol *));
6161+ *reloc->sym_ptr_ptr = symbol_get_bfdsym (fixp->fx_addsy);
6162+ reloc->address = fixp->fx_frag->fr_address + fixp->fx_where;
Patrick Georgiaf473ed2015-07-17 23:35:54 +02006163+ reloc->addend = fixp->fx_addnumber;
Patrick Georgif0bbc952015-03-07 10:57:25 +01006164+
6165+ reloc->howto = bfd_reloc_type_lookup (stdoutput, fixp->fx_r_type);
6166+ if (reloc->howto == NULL)
6167+ {
6168+ if ((fixp->fx_r_type == BFD_RELOC_16 || fixp->fx_r_type == BFD_RELOC_8)
6169+ && fixp->fx_addsy != NULL && fixp->fx_subsy != NULL)
6170+ {
6171+ /* We don't have R_RISCV_8/16, but for this special case,
6172+ we can use R_RISCV_ADD8/16 with R_RISCV_SUB8/16. */
6173+ return reloc;
6174+ }
6175+
6176+ as_bad_where (fixp->fx_file, fixp->fx_line,
6177+ _("cannot represent %s relocation in object file"),
6178+ bfd_get_reloc_code_name (fixp->fx_r_type));
6179+ return NULL;
6180+ }
6181+
6182+ return reloc;
6183+}
6184+
6185+int
6186+riscv_relax_frag (asection *sec, fragS *fragp, long stretch ATTRIBUTE_UNUSED)
6187+{
6188+ if (RELAX_BRANCH_P (fragp->fr_subtype))
6189+ {
6190+ offsetT old_var = fragp->fr_var;
6191+ fragp->fr_var = relaxed_branch_length (fragp, sec, TRUE);
6192+ return fragp->fr_var - old_var;
6193+ }
6194+
6195+ return 0;
6196+}
6197+
Patrick Georgiaf473ed2015-07-17 23:35:54 +02006198+/* Expand far branches to multi-instruction sequences. */
Patrick Georgif0bbc952015-03-07 10:57:25 +01006199+
6200+static void
6201+md_convert_frag_branch (fragS *fragp)
6202+{
6203+ bfd_byte *buf;
Patrick Georgif0bbc952015-03-07 10:57:25 +01006204+ expressionS exp;
6205+ fixS *fixp;
Patrick Georgiaf473ed2015-07-17 23:35:54 +02006206+ insn_t insn;
6207+ int rs1, reloc;
Patrick Georgif0bbc952015-03-07 10:57:25 +01006208+
6209+ buf = (bfd_byte *)fragp->fr_literal + fragp->fr_fix;
6210+
6211+ exp.X_op = O_symbol;
6212+ exp.X_add_symbol = fragp->fr_symbol;
6213+ exp.X_add_number = fragp->fr_offset;
6214+
Patrick Georgiaf473ed2015-07-17 23:35:54 +02006215+ gas_assert (fragp->fr_var == RELAX_BRANCH_LENGTH (fragp->fr_subtype));
6216+
6217+ if (RELAX_BRANCH_RVC (fragp->fr_subtype))
Patrick Georgif0bbc952015-03-07 10:57:25 +01006218+ {
Patrick Georgiaf473ed2015-07-17 23:35:54 +02006219+ switch (RELAX_BRANCH_LENGTH (fragp->fr_subtype))
6220+ {
6221+ case 8:
6222+ case 4:
6223+ /* Expand the RVC branch into a RISC-V one. */
6224+ insn = bfd_getl16 (buf);
6225+ rs1 = 8 + ((insn >> OP_SH_CRS1S) & OP_MASK_CRS1S);
6226+ if ((insn & MASK_C_J) == MATCH_C_J)
6227+ insn = MATCH_JAL;
6228+ else if ((insn & MASK_C_JAL) == MATCH_C_JAL)
6229+ insn = MATCH_JAL | (X_RA << OP_SH_RD);
6230+ else if ((insn & MASK_C_BEQZ) == MATCH_C_BEQZ)
6231+ insn = MATCH_BEQ | (rs1 << OP_SH_RS1);
6232+ else if ((insn & MASK_C_BNEZ) == MATCH_C_BNEZ)
6233+ insn = MATCH_BNE | (rs1 << OP_SH_RS1);
6234+ else if ((insn & MASK_C_BLTZ) == MATCH_C_BLTZ)
6235+ insn = MATCH_BLT | (rs1 << OP_SH_RS1);
6236+ else if ((insn & MASK_C_BGEZ) == MATCH_C_BGEZ)
6237+ insn = MATCH_BGE | (rs1 << OP_SH_RS1);
6238+ else
6239+ abort ();
6240+ bfd_putl32 (insn, buf);
6241+ break;
6242+
6243+ case 2:
6244+ /* Just keep the RVC branch. */
6245+ reloc = RELAX_BRANCH_UNCOND (fragp->fr_subtype)
6246+ ? BFD_RELOC_RISCV_RVC_JUMP : BFD_RELOC_RISCV_RVC_BRANCH;
6247+ fixp = fix_new_exp (fragp, buf - (bfd_byte *)fragp->fr_literal,
6248+ 2, &exp, FALSE, reloc);
6249+ buf += 2;
6250+ goto done;
6251+
6252+ default:
6253+ abort();
6254+ }
6255+ }
6256+
6257+ switch (RELAX_BRANCH_LENGTH (fragp->fr_subtype))
6258+ {
6259+ case 8:
Patrick Georgif0bbc952015-03-07 10:57:25 +01006260+ gas_assert (!RELAX_BRANCH_UNCOND (fragp->fr_subtype));
6261+
6262+ /* Invert the branch condition. Branch over the jump. */
6263+ insn = bfd_getl32 (buf);
6264+ insn ^= MATCH_BEQ ^ MATCH_BNE;
6265+ insn |= ENCODE_SBTYPE_IMM (8);
6266+ md_number_to_chars ((char *) buf, insn, 4);
6267+ buf += 4;
6268+
6269+ /* Jump to the target. */
6270+ fixp = fix_new_exp (fragp, buf - (bfd_byte *)fragp->fr_literal,
6271+ 4, &exp, FALSE, BFD_RELOC_RISCV_JMP);
6272+ md_number_to_chars ((char *) buf, MATCH_JAL, 4);
6273+ buf += 4;
Patrick Georgiaf473ed2015-07-17 23:35:54 +02006274+ break;
6275+
6276+ case 4:
6277+ reloc = RELAX_BRANCH_UNCOND (fragp->fr_subtype)
6278+ ? BFD_RELOC_RISCV_JMP : BFD_RELOC_12_PCREL;
Patrick Georgif0bbc952015-03-07 10:57:25 +01006279+ fixp = fix_new_exp (fragp, buf - (bfd_byte *)fragp->fr_literal,
Patrick Georgiaf473ed2015-07-17 23:35:54 +02006280+ 4, &exp, FALSE, reloc);
Patrick Georgif0bbc952015-03-07 10:57:25 +01006281+ buf += 4;
Patrick Georgiaf473ed2015-07-17 23:35:54 +02006282+ break;
6283+
6284+ default:
6285+ abort ();
Patrick Georgif0bbc952015-03-07 10:57:25 +01006286+ }
6287+
Patrick Georgiaf473ed2015-07-17 23:35:54 +02006288+done:
Patrick Georgif0bbc952015-03-07 10:57:25 +01006289+ fixp->fx_file = fragp->fr_file;
6290+ fixp->fx_line = fragp->fr_line;
Patrick Georgif0bbc952015-03-07 10:57:25 +01006291+
6292+ gas_assert (buf == (bfd_byte *)fragp->fr_literal
6293+ + fragp->fr_fix + fragp->fr_var);
6294+
6295+ fragp->fr_fix += fragp->fr_var;
6296+}
6297+
6298+/* Relax a machine dependent frag. This returns the amount by which
6299+ the current size of the frag should change. */
6300+
6301+void
6302+md_convert_frag (bfd *abfd ATTRIBUTE_UNUSED, segT asec ATTRIBUTE_UNUSED,
6303+ fragS *fragp)
6304+{
6305+ gas_assert (RELAX_BRANCH_P (fragp->fr_subtype));
6306+ md_convert_frag_branch (fragp);
6307+}
6308+
6309+void
6310+md_show_usage (FILE *stream)
6311+{
6312+ fprintf (stream, _("\
6313+RISC-V options:\n\
6314+ -m32 assemble RV32 code\n\
6315+ -m64 assemble RV64 code (default)\n\
6316+ -fpic generate position-independent code\n\
6317+ -fno-pic don't generate position-independent code (default)\n\
6318+"));
6319+}
6320+
6321+/* Standard calling conventions leave the CFA at SP on entry. */
6322+void
6323+riscv_cfi_frame_initial_instructions (void)
6324+{
6325+ cfi_add_CFA_def_cfa_register (X_SP);
6326+}
6327+
6328+int
6329+tc_riscv_regname_to_dw2regnum (char *regname)
6330+{
6331+ int reg;
6332+
6333+ if ((reg = reg_lookup_internal (regname, RCLASS_GPR)) >= 0)
6334+ return reg;
6335+
6336+ if ((reg = reg_lookup_internal (regname, RCLASS_FPR)) >= 0)
6337+ return reg + 32;
6338+
6339+ as_bad (_("unknown register `%s'"), regname);
6340+ return -1;
6341+}
6342+
6343+void
6344+riscv_elf_final_processing (void)
6345+{
Patrick Georgiaf473ed2015-07-17 23:35:54 +02006346+ elf_elfheader (stdoutput)->e_flags |= elf_flags;
Patrick Georgif0bbc952015-03-07 10:57:25 +01006347+}
6348+
6349+/* Pseudo-op table. */
6350+
6351+static const pseudo_typeS riscv_pseudo_table[] =
6352+{
6353+ /* RISC-V-specific pseudo-ops. */
6354+ {"option", s_riscv_option, 0},
6355+ {"half", cons, 2},
6356+ {"word", cons, 4},
6357+ {"dword", cons, 8},
6358+ {"dtprelword", s_dtprel, 4},
6359+ {"dtpreldword", s_dtprel, 8},
6360+ {"bss", s_bss, 0},
6361+ {"align", s_align, 0},
Patrick Georgiaf473ed2015-07-17 23:35:54 +02006362+ {"p2align", s_align, 0},
6363+ {"balign", s_align, 1},
Patrick Georgif0bbc952015-03-07 10:57:25 +01006364+
6365+ /* leb128 doesn't work with relaxation; disallow it */
6366+ {"uleb128", s_err, 0},
6367+ {"sleb128", s_err, 0},
6368+
6369+ { NULL, NULL, 0 },
6370+};
6371+
6372+void
6373+riscv_pop_insert (void)
6374+{
6375+ extern void pop_insert (const pseudo_typeS *);
6376+
6377+ pop_insert (riscv_pseudo_table);
6378+}
Patrick Georgiaf473ed2015-07-17 23:35:54 +02006379diff -urN empty/gas/config/tc-riscv.h binutils-2.25/gas/config/tc-riscv.h
Jonathan A. Kollasch64fc4332015-08-25 13:09:51 -05006380--- binutils-2.25/gas/config/tc-riscv.h 1970-01-01 01:00:00.000000000 +0100
Patrick Georgiaf473ed2015-07-17 23:35:54 +02006381+++ binutils-2.25/gas/config/tc-riscv.h 2015-07-18 00:02:36.222287541 +0200
Patrick Georgif0bbc952015-03-07 10:57:25 +01006382@@ -0,0 +1,102 @@
6383+/* tc-riscv.h -- header file for tc-riscv.c.
6384+ Copyright 2011-2014 Free Software Foundation, Inc.
6385+
6386+ Contributed by Andrew Waterman (waterman@cs.berkeley.edu) at UC Berkeley.
6387+ Based on MIPS target.
6388+
6389+ This file is part of GAS.
6390+
6391+ GAS is free software; you can redistribute it and/or modify
6392+ it under the terms of the GNU General Public License as published by
6393+ the Free Software Foundation; either version 3, or (at your option)
6394+ any later version.
6395+
6396+ GAS is distributed in the hope that it will be useful,
6397+ but WITHOUT ANY WARRANTY; without even the implied warranty of
6398+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
6399+ GNU General Public License for more details.
6400+
6401+ You should have received a copy of the GNU General Public License
6402+ along with GAS; see the file COPYING. If not, write to the Free
6403+ Software Foundation, 51 Franklin Street - Fifth Floor, Boston, MA
6404+ 02110-1301, USA. */
6405+
6406+#ifndef TC_RISCV
6407+#define TC_RISCV
6408+
6409+#include "opcode/riscv.h"
6410+
6411+struct frag;
6412+struct expressionS;
6413+
6414+#define TARGET_BYTES_BIG_ENDIAN 0
6415+
6416+#define TARGET_ARCH bfd_arch_riscv
6417+
6418+#define WORKING_DOT_WORD 1
6419+#define OLD_FLOAT_READS
6420+#define REPEAT_CONS_EXPRESSIONS
6421+#define LOCAL_LABELS_FB 1
6422+#define FAKE_LABEL_NAME ".L0 "
6423+
6424+#define md_relax_frag(segment, fragp, stretch) \
6425+ riscv_relax_frag(segment, fragp, stretch)
6426+extern int riscv_relax_frag (asection *, struct frag *, long);
6427+
6428+#define md_section_align(seg,size) (size)
6429+#define md_undefined_symbol(name) (0)
6430+#define md_operand(x)
6431+
6432+#define MAX_MEM_FOR_RS_ALIGN_CODE (1 + 2)
6433+
6434+#define TC_SYMFIELD_TYPE int
6435+
6436+/* The ISA of the target may change based on command-line arguments. */
6437+#define TARGET_FORMAT riscv_target_format()
6438+extern const char *riscv_target_format (void);
6439+
6440+#define md_after_parse_args() riscv_after_parse_args()
6441+extern void riscv_after_parse_args (void);
6442+
6443+#define tc_init_after_args() riscv_init_after_args()
6444+extern void riscv_init_after_args (void);
6445+
6446+#define md_parse_long_option(arg) riscv_parse_long_option (arg)
6447+extern int riscv_parse_long_option (const char *);
6448+
6449+/* Let the linker resolve all the relocs due to relaxation. */
6450+#define tc_fix_adjustable(fixp) 0
6451+#define md_allow_local_subtract(l,r,s) 0
6452+
6453+/* Values passed to md_apply_fix don't include symbol values. */
6454+#define MD_APPLY_SYM_VALUE(FIX) 0
6455+
6456+/* Global syms must not be resolved, to support ELF shared libraries. */
6457+#define EXTERN_FORCE_RELOC \
6458+ (OUTPUT_FLAVOR == bfd_target_elf_flavour)
6459+
6460+#define TC_FORCE_RELOCATION_SUB_SAME(FIX, SEG) ((SEG)->flags & SEC_CODE)
6461+#define TC_FORCE_RELOCATION_SUB_LOCAL(FIX, SEG) 1
6462+#define TC_VALIDATE_FIX_SUB(FIX, SEG) 1
6463+#define TC_FORCE_RELOCATION_LOCAL(FIX) 1
6464+#define DIFF_EXPR_OK 1
6465+
6466+extern void riscv_pop_insert (void);
6467+#define md_pop_insert() riscv_pop_insert()
6468+
6469+#define TARGET_USE_CFIPOP 1
6470+
6471+#define tc_cfi_frame_initial_instructions riscv_cfi_frame_initial_instructions
6472+extern void riscv_cfi_frame_initial_instructions (void);
6473+
6474+#define tc_regname_to_dw2regnum tc_riscv_regname_to_dw2regnum
6475+extern int tc_riscv_regname_to_dw2regnum (char *regname);
6476+
Patrick Georgiaf473ed2015-07-17 23:35:54 +02006477+extern unsigned xlen;
Patrick Georgif0bbc952015-03-07 10:57:25 +01006478+#define DWARF2_DEFAULT_RETURN_COLUMN X_RA
Patrick Georgiaf473ed2015-07-17 23:35:54 +02006479+#define DWARF2_CIE_DATA_ALIGNMENT (xlen / 8)
Patrick Georgif0bbc952015-03-07 10:57:25 +01006480+
6481+#define elf_tc_final_processing riscv_elf_final_processing
6482+extern void riscv_elf_final_processing (void);
6483+
6484+#endif /* TC_RISCV */
Patrick Georgiaf473ed2015-07-17 23:35:54 +02006485diff -urN empty/include/elf/riscv.h binutils-2.25/include/elf/riscv.h
Jonathan A. Kollasch64fc4332015-08-25 13:09:51 -05006486--- binutils-2.25/include/elf/riscv.h 1970-01-01 01:00:00.000000000 +0100
Patrick Georgiaf473ed2015-07-17 23:35:54 +02006487+++ binutils-2.25/include/elf/riscv.h 2015-07-18 00:02:36.222287541 +0200
6488@@ -0,0 +1,143 @@
Patrick Georgif0bbc952015-03-07 10:57:25 +01006489+/* RISC-V ELF support for BFD.
6490+ Copyright 2011-2014 Free Software Foundation, Inc.
6491+
6492+ Contributed by Andrw Waterman <waterman@cs.berkeley.edu> at UC Berkeley.
6493+ Based on MIPS ELF support for BFD, by Ian Lance Taylor.
6494+
6495+ This file is part of BFD, the Binary File Descriptor library.
6496+
6497+ This program is free software; you can redistribute it and/or modify
6498+ it under the terms of the GNU General Public License as published by
6499+ the Free Software Foundation; either version 3 of the License, or
6500+ (at your option) any later version.
6501+
6502+ This program is distributed in the hope that it will be useful,
6503+ but WITHOUT ANY WARRANTY; without even the implied warranty of
6504+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
6505+ GNU General Public License for more details.
6506+
6507+ You should have received a copy of the GNU General Public License
6508+ along with this program; if not, write to the Free Software
6509+ Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
6510+ MA 02110-1301, USA. */
6511+
6512+/* This file holds definitions specific to the RISCV ELF ABI. Note
6513+ that most of this is not actually implemented by BFD. */
6514+
6515+#ifndef _ELF_RISCV_H
6516+#define _ELF_RISCV_H
6517+
6518+#include "elf/reloc-macros.h"
6519+
6520+/* Relocation types. */
6521+START_RELOC_NUMBERS (elf_riscv_reloc_type)
6522+ /* Relocation types used by the dynamic linker. */
6523+ RELOC_NUMBER (R_RISCV_NONE, 0)
6524+ RELOC_NUMBER (R_RISCV_32, 1)
6525+ RELOC_NUMBER (R_RISCV_64, 2)
6526+ RELOC_NUMBER (R_RISCV_RELATIVE, 3)
6527+ RELOC_NUMBER (R_RISCV_COPY, 4)
6528+ RELOC_NUMBER (R_RISCV_JUMP_SLOT, 5)
6529+ RELOC_NUMBER (R_RISCV_TLS_DTPMOD32, 6)
6530+ RELOC_NUMBER (R_RISCV_TLS_DTPMOD64, 7)
6531+ RELOC_NUMBER (R_RISCV_TLS_DTPREL32, 8)
6532+ RELOC_NUMBER (R_RISCV_TLS_DTPREL64, 9)
6533+ RELOC_NUMBER (R_RISCV_TLS_TPREL32, 10)
6534+ RELOC_NUMBER (R_RISCV_TLS_TPREL64, 11)
6535+
6536+ /* Relocation types not used by the dynamic linker. */
6537+ RELOC_NUMBER (R_RISCV_BRANCH, 16)
6538+ RELOC_NUMBER (R_RISCV_JAL, 17)
6539+ RELOC_NUMBER (R_RISCV_CALL, 18)
6540+ RELOC_NUMBER (R_RISCV_CALL_PLT, 19)
6541+ RELOC_NUMBER (R_RISCV_GOT_HI20, 20)
6542+ RELOC_NUMBER (R_RISCV_TLS_GOT_HI20, 21)
6543+ RELOC_NUMBER (R_RISCV_TLS_GD_HI20, 22)
6544+ RELOC_NUMBER (R_RISCV_PCREL_HI20, 23)
6545+ RELOC_NUMBER (R_RISCV_PCREL_LO12_I, 24)
6546+ RELOC_NUMBER (R_RISCV_PCREL_LO12_S, 25)
6547+ RELOC_NUMBER (R_RISCV_HI20, 26)
6548+ RELOC_NUMBER (R_RISCV_LO12_I, 27)
6549+ RELOC_NUMBER (R_RISCV_LO12_S, 28)
6550+ RELOC_NUMBER (R_RISCV_TPREL_HI20, 29)
6551+ RELOC_NUMBER (R_RISCV_TPREL_LO12_I, 30)
6552+ RELOC_NUMBER (R_RISCV_TPREL_LO12_S, 31)
6553+ RELOC_NUMBER (R_RISCV_TPREL_ADD, 32)
6554+ RELOC_NUMBER (R_RISCV_ADD8, 33)
6555+ RELOC_NUMBER (R_RISCV_ADD16, 34)
6556+ RELOC_NUMBER (R_RISCV_ADD32, 35)
6557+ RELOC_NUMBER (R_RISCV_ADD64, 36)
6558+ RELOC_NUMBER (R_RISCV_SUB8, 37)
6559+ RELOC_NUMBER (R_RISCV_SUB16, 38)
6560+ RELOC_NUMBER (R_RISCV_SUB32, 39)
6561+ RELOC_NUMBER (R_RISCV_SUB64, 40)
6562+ RELOC_NUMBER (R_RISCV_GNU_VTINHERIT, 41)
6563+ RELOC_NUMBER (R_RISCV_GNU_VTENTRY, 42)
6564+ RELOC_NUMBER (R_RISCV_ALIGN, 43)
Patrick Georgiaf473ed2015-07-17 23:35:54 +02006565+ RELOC_NUMBER (R_RISCV_RVC_BRANCH, 44)
6566+ RELOC_NUMBER (R_RISCV_RVC_JUMP, 45)
Patrick Georgif0bbc952015-03-07 10:57:25 +01006567+END_RELOC_NUMBERS (R_RISCV_max)
6568+
6569+/* Processor specific flags for the ELF header e_flags field. */
6570+
Patrick Georgiaf473ed2015-07-17 23:35:54 +02006571+/* File may contain compressed instructions. */
6572+#define EF_RISCV_RVC 0x0001
6573+
Patrick Georgif0bbc952015-03-07 10:57:25 +01006574+/* Custom flag definitions. */
6575+
6576+#define EF_RISCV_EXT_MASK 0xffff
6577+#define EF_RISCV_EXT_SH 16
6578+#define E_RISCV_EXT_Xcustom 0x0000
6579+#define E_RISCV_EXT_Xhwacha 0x0001
6580+#define E_RISCV_EXT_RESERVED 0xffff
6581+
6582+#define EF_GET_RISCV_EXT(x) \
6583+ ((x >> EF_RISCV_EXT_SH) & EF_RISCV_EXT_MASK)
6584+
6585+#define EF_SET_RISCV_EXT(x, ext) \
6586+ do { x |= ((ext & EF_RISCV_EXT_MASK) << EF_RISCV_EXT_SH); } while (0)
6587+
6588+#define EF_IS_RISCV_EXT_Xcustom(x) \
6589+ (EF_GET_RISCV_EXT(x) == E_RISCV_EXT_Xcustom)
6590+
6591+/* A mapping from extension names to elf flags */
6592+
6593+struct riscv_extension_entry
6594+{
6595+ const char* name;
6596+ unsigned int flag;
6597+};
6598+
6599+static const struct riscv_extension_entry riscv_extension_map[] =
6600+{
6601+ {"Xcustom", E_RISCV_EXT_Xcustom},
6602+ {"Xhwacha", E_RISCV_EXT_Xhwacha},
6603+};
6604+
6605+/* Given an extension name, return an elf flag. */
6606+
6607+static inline const char* riscv_elf_flag_to_name(unsigned int flag)
6608+{
6609+ unsigned int i;
6610+
6611+ for (i=0; i<sizeof(riscv_extension_map)/sizeof(riscv_extension_map[0]); i++)
6612+ if (riscv_extension_map[i].flag == flag)
6613+ return riscv_extension_map[i].name;
6614+
6615+ return NULL;
6616+}
6617+
6618+/* Given an elf flag, return an extension name. */
6619+
6620+static inline unsigned int riscv_elf_name_to_flag(const char* name)
6621+{
6622+ unsigned int i;
6623+
6624+ for (i=0; i<sizeof(riscv_extension_map)/sizeof(riscv_extension_map[0]); i++)
6625+ if (strcmp(riscv_extension_map[i].name, name) == 0)
6626+ return riscv_extension_map[i].flag;
6627+
6628+ return E_RISCV_EXT_Xcustom;
6629+}
6630+
6631+#endif /* _ELF_RISCV_H */
Patrick Georgiaf473ed2015-07-17 23:35:54 +02006632diff -urN empty/include/opcode/riscv-opc.h binutils-2.25/include/opcode/riscv-opc.h
Jonathan A. Kollasch64fc4332015-08-25 13:09:51 -05006633--- binutils-2.25/include/opcode/riscv-opc.h 1970-01-01 01:00:00.000000000 +0100
Patrick Georgiaf473ed2015-07-17 23:35:54 +02006634+++ binutils-2.25/include/opcode/riscv-opc.h 2015-07-18 00:02:36.222287541 +0200
6635@@ -0,0 +1,1348 @@
6636+/* Automatically generated by parse-opcodes */
6637+#ifndef RISCV_ENCODING_H
6638+#define RISCV_ENCODING_H
6639+#define MATCH_ADD 0x33
6640+#define MASK_ADD 0xfe00707f
6641+#define MATCH_ADDI 0x13
6642+#define MASK_ADDI 0x707f
6643+#define MATCH_ADDIW 0x1b
6644+#define MASK_ADDIW 0x707f
6645+#define MATCH_ADDW 0x3b
6646+#define MASK_ADDW 0xfe00707f
6647+#define MATCH_AMOADD_D 0x302f
6648+#define MASK_AMOADD_D 0xf800707f
6649+#define MATCH_AMOADD_W 0x202f
6650+#define MASK_AMOADD_W 0xf800707f
6651+#define MATCH_AMOAND_D 0x6000302f
6652+#define MASK_AMOAND_D 0xf800707f
6653+#define MATCH_AMOAND_W 0x6000202f
6654+#define MASK_AMOAND_W 0xf800707f
6655+#define MATCH_AMOMAX_D 0xa000302f
6656+#define MASK_AMOMAX_D 0xf800707f
6657+#define MATCH_AMOMAX_W 0xa000202f
6658+#define MASK_AMOMAX_W 0xf800707f
6659+#define MATCH_AMOMAXU_D 0xe000302f
6660+#define MASK_AMOMAXU_D 0xf800707f
6661+#define MATCH_AMOMAXU_W 0xe000202f
6662+#define MASK_AMOMAXU_W 0xf800707f
6663+#define MATCH_AMOMIN_D 0x8000302f
6664+#define MASK_AMOMIN_D 0xf800707f
6665+#define MATCH_AMOMIN_W 0x8000202f
6666+#define MASK_AMOMIN_W 0xf800707f
6667+#define MATCH_AMOMINU_D 0xc000302f
6668+#define MASK_AMOMINU_D 0xf800707f
6669+#define MATCH_AMOMINU_W 0xc000202f
6670+#define MASK_AMOMINU_W 0xf800707f
6671+#define MATCH_AMOOR_D 0x4000302f
6672+#define MASK_AMOOR_D 0xf800707f
6673+#define MATCH_AMOOR_W 0x4000202f
6674+#define MASK_AMOOR_W 0xf800707f
6675+#define MATCH_AMOSWAP_D 0x800302f
6676+#define MASK_AMOSWAP_D 0xf800707f
6677+#define MATCH_AMOSWAP_W 0x800202f
6678+#define MASK_AMOSWAP_W 0xf800707f
6679+#define MATCH_AMOXOR_D 0x2000302f
6680+#define MASK_AMOXOR_D 0xf800707f
6681+#define MATCH_AMOXOR_W 0x2000202f
6682+#define MASK_AMOXOR_W 0xf800707f
6683+#define MATCH_AND 0x7033
6684+#define MASK_AND 0xfe00707f
6685+#define MATCH_ANDI 0x7013
6686+#define MASK_ANDI 0x707f
6687+#define MATCH_AUIPC 0x17
6688+#define MASK_AUIPC 0x7f
6689+#define MATCH_BEQ 0x63
6690+#define MASK_BEQ 0x707f
6691+#define MATCH_BGE 0x5063
6692+#define MASK_BGE 0x707f
6693+#define MATCH_BGEU 0x7063
6694+#define MASK_BGEU 0x707f
6695+#define MATCH_BLT 0x4063
6696+#define MASK_BLT 0x707f
6697+#define MATCH_BLTU 0x6063
6698+#define MASK_BLTU 0x707f
6699+#define MATCH_BNE 0x1063
6700+#define MASK_BNE 0x707f
6701+#define MATCH_C_ADD 0x1000
6702+#define MASK_C_ADD 0xf003
6703+#define MATCH_C_ADD3 0xa000
6704+#define MASK_C_ADD3 0xe063
6705+#define MATCH_C_ADDI 0xc002
6706+#define MASK_C_ADDI 0xe003
6707+#define MATCH_C_ADDI16SP 0xc002
6708+#define MASK_C_ADDI16SP 0xef83
6709+#define MATCH_C_ADDI4SPN 0xa001
6710+#define MASK_C_ADDI4SPN 0xe003
6711+#define MATCH_C_ADDIN 0x8001
6712+#define MASK_C_ADDIN 0xe063
6713+#define MATCH_C_ADDIW 0xe002
6714+#define MASK_C_ADDIW 0xe003
6715+#define MATCH_C_ADDW 0x9000
6716+#define MASK_C_ADDW 0xf003
6717+#define MATCH_C_AND3 0xa060
6718+#define MASK_C_AND3 0xe063
6719+#define MATCH_C_ANDI 0xe002
6720+#define MASK_C_ANDI 0xe003
6721+#define MATCH_C_ANDIN 0x8061
6722+#define MASK_C_ANDIN 0xe063
6723+#define MATCH_C_BEQZ 0x4002
6724+#define MASK_C_BEQZ 0xe003
6725+#define MATCH_C_BGEZ 0xe001
6726+#define MASK_C_BGEZ 0xe003
6727+#define MATCH_C_BLTZ 0x6001
6728+#define MASK_C_BLTZ 0xe003
6729+#define MATCH_C_BNEZ 0x6002
6730+#define MASK_C_BNEZ 0xe003
6731+#define MATCH_C_EBREAK 0x1000
6732+#define MASK_C_EBREAK 0xffff
6733+#define MATCH_C_J 0x2
6734+#define MASK_C_J 0xe003
6735+#define MATCH_C_JAL 0x2002
6736+#define MASK_C_JAL 0xe003
6737+#define MATCH_C_JALR 0xa002
6738+#define MASK_C_JALR 0xf07f
6739+#define MATCH_C_JR 0x8002
6740+#define MASK_C_JR 0xf07f
6741+#define MATCH_C_LD 0xe000
6742+#define MASK_C_LD 0xe003
6743+#define MATCH_C_LDSP 0xe001
6744+#define MASK_C_LDSP 0xe003
6745+#define MATCH_C_LI 0x8002
6746+#define MASK_C_LI 0xe003
6747+#define MATCH_C_LUI 0xa002
6748+#define MASK_C_LUI 0xe003
6749+#define MATCH_C_LW 0xc000
6750+#define MASK_C_LW 0xe003
6751+#define MATCH_C_LWSP 0xc001
6752+#define MASK_C_LWSP 0xe003
6753+#define MATCH_C_MV 0x0
6754+#define MASK_C_MV 0xf003
6755+#define MATCH_C_OR3 0xa040
6756+#define MASK_C_OR3 0xe063
6757+#define MATCH_C_ORIN 0x8041
6758+#define MASK_C_ORIN 0xe063
6759+#define MATCH_C_SD 0x6000
6760+#define MASK_C_SD 0xe003
6761+#define MATCH_C_SDSP 0x6001
6762+#define MASK_C_SDSP 0xe003
6763+#define MATCH_C_SLL 0x6400
6764+#define MASK_C_SLL 0xfc63
6765+#define MATCH_C_SLLI 0x1
6766+#define MASK_C_SLLI 0xe003
6767+#define MATCH_C_SLLIW 0x8001
6768+#define MASK_C_SLLIW 0xe003
6769+#define MATCH_C_SLLR 0x6c00
6770+#define MASK_C_SLLR 0xfc63
6771+#define MATCH_C_SLT 0x6440
6772+#define MASK_C_SLT 0xfc63
6773+#define MATCH_C_SLTR 0x6c40
6774+#define MASK_C_SLTR 0xfc63
6775+#define MATCH_C_SLTU 0x6460
6776+#define MASK_C_SLTU 0xfc63
6777+#define MATCH_C_SLTUR 0x6c60
6778+#define MASK_C_SLTUR 0xfc63
6779+#define MATCH_C_SRA 0x6020
6780+#define MASK_C_SRA 0xfc63
6781+#define MATCH_C_SRAI 0x2000
6782+#define MASK_C_SRAI 0xe003
6783+#define MATCH_C_SRL 0x6420
6784+#define MASK_C_SRL 0xfc63
6785+#define MATCH_C_SRLI 0x2001
6786+#define MASK_C_SRLI 0xe003
6787+#define MATCH_C_SRLR 0x6c20
6788+#define MASK_C_SRLR 0xfc63
6789+#define MATCH_C_SUB 0x8000
6790+#define MASK_C_SUB 0xf003
6791+#define MATCH_C_SUB3 0xa020
6792+#define MASK_C_SUB3 0xe063
6793+#define MATCH_C_SW 0x4000
6794+#define MASK_C_SW 0xe003
6795+#define MATCH_C_SWSP 0x4001
6796+#define MASK_C_SWSP 0xe003
6797+#define MATCH_C_XOR 0x6000
6798+#define MASK_C_XOR 0xfc63
6799+#define MATCH_C_XORIN 0x8021
6800+#define MASK_C_XORIN 0xe063
6801+#define MATCH_CSRRC 0x3073
6802+#define MASK_CSRRC 0x707f
6803+#define MATCH_CSRRCI 0x7073
6804+#define MASK_CSRRCI 0x707f
6805+#define MATCH_CSRRS 0x2073
6806+#define MASK_CSRRS 0x707f
6807+#define MATCH_CSRRSI 0x6073
6808+#define MASK_CSRRSI 0x707f
6809+#define MATCH_CSRRW 0x1073
6810+#define MASK_CSRRW 0x707f
6811+#define MATCH_CSRRWI 0x5073
6812+#define MASK_CSRRWI 0x707f
6813+#define MATCH_CUSTOM0 0xb
6814+#define MASK_CUSTOM0 0x707f
6815+#define MATCH_CUSTOM0_RD 0x400b
6816+#define MASK_CUSTOM0_RD 0x707f
6817+#define MATCH_CUSTOM0_RD_RS1 0x600b
6818+#define MASK_CUSTOM0_RD_RS1 0x707f
6819+#define MATCH_CUSTOM0_RD_RS1_RS2 0x700b
6820+#define MASK_CUSTOM0_RD_RS1_RS2 0x707f
6821+#define MATCH_CUSTOM0_RS1 0x200b
6822+#define MASK_CUSTOM0_RS1 0x707f
6823+#define MATCH_CUSTOM0_RS1_RS2 0x300b
6824+#define MASK_CUSTOM0_RS1_RS2 0x707f
6825+#define MATCH_CUSTOM1 0x2b
6826+#define MASK_CUSTOM1 0x707f
6827+#define MATCH_CUSTOM1_RD 0x402b
6828+#define MASK_CUSTOM1_RD 0x707f
6829+#define MATCH_CUSTOM1_RD_RS1 0x602b
6830+#define MASK_CUSTOM1_RD_RS1 0x707f
6831+#define MATCH_CUSTOM1_RD_RS1_RS2 0x702b
6832+#define MASK_CUSTOM1_RD_RS1_RS2 0x707f
6833+#define MATCH_CUSTOM1_RS1 0x202b
6834+#define MASK_CUSTOM1_RS1 0x707f
6835+#define MATCH_CUSTOM1_RS1_RS2 0x302b
6836+#define MASK_CUSTOM1_RS1_RS2 0x707f
6837+#define MATCH_CUSTOM2 0x5b
6838+#define MASK_CUSTOM2 0x707f
6839+#define MATCH_CUSTOM2_RD 0x405b
6840+#define MASK_CUSTOM2_RD 0x707f
6841+#define MATCH_CUSTOM2_RD_RS1 0x605b
6842+#define MASK_CUSTOM2_RD_RS1 0x707f
6843+#define MATCH_CUSTOM2_RD_RS1_RS2 0x705b
6844+#define MASK_CUSTOM2_RD_RS1_RS2 0x707f
6845+#define MATCH_CUSTOM2_RS1 0x205b
6846+#define MASK_CUSTOM2_RS1 0x707f
6847+#define MATCH_CUSTOM2_RS1_RS2 0x305b
6848+#define MASK_CUSTOM2_RS1_RS2 0x707f
6849+#define MATCH_CUSTOM3 0x7b
6850+#define MASK_CUSTOM3 0x707f
6851+#define MATCH_CUSTOM3_RD 0x407b
6852+#define MASK_CUSTOM3_RD 0x707f
6853+#define MATCH_CUSTOM3_RD_RS1 0x607b
6854+#define MASK_CUSTOM3_RD_RS1 0x707f
6855+#define MATCH_CUSTOM3_RD_RS1_RS2 0x707b
6856+#define MASK_CUSTOM3_RD_RS1_RS2 0x707f
6857+#define MATCH_CUSTOM3_RS1 0x207b
6858+#define MASK_CUSTOM3_RS1 0x707f
6859+#define MATCH_CUSTOM3_RS1_RS2 0x307b
6860+#define MASK_CUSTOM3_RS1_RS2 0x707f
6861+#define MATCH_DIV 0x2004033
6862+#define MASK_DIV 0xfe00707f
6863+#define MATCH_DIVU 0x2005033
6864+#define MASK_DIVU 0xfe00707f
6865+#define MATCH_DIVUW 0x200503b
6866+#define MASK_DIVUW 0xfe00707f
6867+#define MATCH_DIVW 0x200403b
6868+#define MASK_DIVW 0xfe00707f
6869+#define MATCH_EBREAK 0x100073
6870+#define MASK_EBREAK 0xffffffff
6871+#define MATCH_ECALL 0x73
6872+#define MASK_ECALL 0xffffffff
6873+#define MATCH_ERET 0x10000073
6874+#define MASK_ERET 0xffffffff
6875+#define MATCH_FADD_D 0x2000053
6876+#define MASK_FADD_D 0xfe00007f
6877+#define MATCH_FADD_H 0x4000053
6878+#define MASK_FADD_H 0xfe00007f
6879+#define MATCH_FADD_S 0x53
6880+#define MASK_FADD_S 0xfe00007f
6881+#define MATCH_FCLASS_D 0xe2001053
6882+#define MASK_FCLASS_D 0xfff0707f
6883+#define MATCH_FCLASS_S 0xe0001053
6884+#define MASK_FCLASS_S 0xfff0707f
6885+#define MATCH_FCVT_D_H 0x8c000053
6886+#define MASK_FCVT_D_H 0xfff0007f
6887+#define MATCH_FCVT_D_L 0xd2200053
6888+#define MASK_FCVT_D_L 0xfff0007f
6889+#define MATCH_FCVT_D_LU 0xd2300053
6890+#define MASK_FCVT_D_LU 0xfff0007f
6891+#define MATCH_FCVT_D_S 0x42000053
6892+#define MASK_FCVT_D_S 0xfff0007f
6893+#define MATCH_FCVT_D_W 0xd2000053
6894+#define MASK_FCVT_D_W 0xfff0007f
6895+#define MATCH_FCVT_D_WU 0xd2100053
6896+#define MASK_FCVT_D_WU 0xfff0007f
6897+#define MATCH_FCVT_H_D 0x92000053
6898+#define MASK_FCVT_H_D 0xfff0007f
6899+#define MATCH_FCVT_H_L 0x64000053
6900+#define MASK_FCVT_H_L 0xfff0007f
6901+#define MATCH_FCVT_H_LU 0x6c000053
6902+#define MASK_FCVT_H_LU 0xfff0007f
6903+#define MATCH_FCVT_H_S 0x90000053
6904+#define MASK_FCVT_H_S 0xfff0007f
6905+#define MATCH_FCVT_H_W 0x74000053
6906+#define MASK_FCVT_H_W 0xfff0007f
6907+#define MATCH_FCVT_H_WU 0x7c000053
6908+#define MASK_FCVT_H_WU 0xfff0007f
6909+#define MATCH_FCVT_L_D 0xc2200053
6910+#define MASK_FCVT_L_D 0xfff0007f
6911+#define MATCH_FCVT_L_H 0x44000053
6912+#define MASK_FCVT_L_H 0xfff0007f
6913+#define MATCH_FCVT_L_S 0xc0200053
6914+#define MASK_FCVT_L_S 0xfff0007f
6915+#define MATCH_FCVT_LU_D 0xc2300053
6916+#define MASK_FCVT_LU_D 0xfff0007f
6917+#define MATCH_FCVT_LU_H 0x4c000053
6918+#define MASK_FCVT_LU_H 0xfff0007f
6919+#define MATCH_FCVT_LU_S 0xc0300053
6920+#define MASK_FCVT_LU_S 0xfff0007f
6921+#define MATCH_FCVT_S_D 0x40100053
6922+#define MASK_FCVT_S_D 0xfff0007f
6923+#define MATCH_FCVT_S_H 0x84000053
6924+#define MASK_FCVT_S_H 0xfff0007f
6925+#define MATCH_FCVT_S_L 0xd0200053
6926+#define MASK_FCVT_S_L 0xfff0007f
6927+#define MATCH_FCVT_S_LU 0xd0300053
6928+#define MASK_FCVT_S_LU 0xfff0007f
6929+#define MATCH_FCVT_S_W 0xd0000053
6930+#define MASK_FCVT_S_W 0xfff0007f
6931+#define MATCH_FCVT_S_WU 0xd0100053
6932+#define MASK_FCVT_S_WU 0xfff0007f
6933+#define MATCH_FCVT_W_D 0xc2000053
6934+#define MASK_FCVT_W_D 0xfff0007f
6935+#define MATCH_FCVT_W_H 0x54000053
6936+#define MASK_FCVT_W_H 0xfff0007f
6937+#define MATCH_FCVT_W_S 0xc0000053
6938+#define MASK_FCVT_W_S 0xfff0007f
6939+#define MATCH_FCVT_WU_D 0xc2100053
6940+#define MASK_FCVT_WU_D 0xfff0007f
6941+#define MATCH_FCVT_WU_H 0x5c000053
6942+#define MASK_FCVT_WU_H 0xfff0007f
6943+#define MATCH_FCVT_WU_S 0xc0100053
6944+#define MASK_FCVT_WU_S 0xfff0007f
6945+#define MATCH_FDIV_D 0x1a000053
6946+#define MASK_FDIV_D 0xfe00007f
6947+#define MATCH_FDIV_H 0x1c000053
6948+#define MASK_FDIV_H 0xfe00007f
6949+#define MATCH_FDIV_S 0x18000053
6950+#define MASK_FDIV_S 0xfe00007f
6951+#define MATCH_FENCE 0xf
6952+#define MASK_FENCE 0x707f
6953+#define MATCH_FENCE_I 0x100f
6954+#define MASK_FENCE_I 0x707f
6955+#define MATCH_FEQ_D 0xa2002053
6956+#define MASK_FEQ_D 0xfe00707f
6957+#define MATCH_FEQ_H 0xac000053
6958+#define MASK_FEQ_H 0xfe00707f
6959+#define MATCH_FEQ_S 0xa0002053
6960+#define MASK_FEQ_S 0xfe00707f
6961+#define MATCH_FLD 0x3007
6962+#define MASK_FLD 0x707f
6963+#define MATCH_FLE_D 0xa2000053
6964+#define MASK_FLE_D 0xfe00707f
6965+#define MATCH_FLE_H 0xbc000053
6966+#define MASK_FLE_H 0xfe00707f
6967+#define MATCH_FLE_S 0xa0000053
6968+#define MASK_FLE_S 0xfe00707f
6969+#define MATCH_FLH 0x1007
6970+#define MASK_FLH 0x707f
6971+#define MATCH_FLT_D 0xa2001053
6972+#define MASK_FLT_D 0xfe00707f
6973+#define MATCH_FLT_H 0xb4000053
6974+#define MASK_FLT_H 0xfe00707f
6975+#define MATCH_FLT_S 0xa0001053
6976+#define MASK_FLT_S 0xfe00707f
6977+#define MATCH_FLW 0x2007
6978+#define MASK_FLW 0x707f
6979+#define MATCH_FMADD_D 0x2000043
6980+#define MASK_FMADD_D 0x600007f
6981+#define MATCH_FMADD_H 0x4000043
6982+#define MASK_FMADD_H 0x600007f
6983+#define MATCH_FMADD_S 0x43
6984+#define MASK_FMADD_S 0x600007f
6985+#define MATCH_FMAX_D 0x2a001053
6986+#define MASK_FMAX_D 0xfe00707f
6987+#define MATCH_FMAX_H 0xcc000053
6988+#define MASK_FMAX_H 0xfe00707f
6989+#define MATCH_FMAX_S 0x28001053
6990+#define MASK_FMAX_S 0xfe00707f
6991+#define MATCH_FMIN_D 0x2a000053
6992+#define MASK_FMIN_D 0xfe00707f
6993+#define MATCH_FMIN_H 0xc4000053
6994+#define MASK_FMIN_H 0xfe00707f
6995+#define MATCH_FMIN_S 0x28000053
6996+#define MASK_FMIN_S 0xfe00707f
6997+#define MATCH_FMOVN 0x6007077
6998+#define MASK_FMOVN 0xfe00707f
6999+#define MATCH_FMOVZ 0x4007077
7000+#define MASK_FMOVZ 0xfe00707f
7001+#define MATCH_FMSUB_D 0x2000047
7002+#define MASK_FMSUB_D 0x600007f
7003+#define MATCH_FMSUB_H 0x4000047
7004+#define MASK_FMSUB_H 0x600007f
7005+#define MATCH_FMSUB_S 0x47
7006+#define MASK_FMSUB_S 0x600007f
7007+#define MATCH_FMUL_D 0x12000053
7008+#define MASK_FMUL_D 0xfe00007f
7009+#define MATCH_FMUL_H 0x14000053
7010+#define MASK_FMUL_H 0xfe00007f
7011+#define MATCH_FMUL_S 0x10000053
7012+#define MASK_FMUL_S 0xfe00007f
7013+#define MATCH_FMV_D_X 0xf2000053
7014+#define MASK_FMV_D_X 0xfff0707f
7015+#define MATCH_FMV_H_X 0xf4000053
7016+#define MASK_FMV_H_X 0xfff0707f
7017+#define MATCH_FMV_S_X 0xf0000053
7018+#define MASK_FMV_S_X 0xfff0707f
7019+#define MATCH_FMV_X_D 0xe2000053
7020+#define MASK_FMV_X_D 0xfff0707f
7021+#define MATCH_FMV_X_H 0xe4000053
7022+#define MASK_FMV_X_H 0xfff0707f
7023+#define MATCH_FMV_X_S 0xe0000053
7024+#define MASK_FMV_X_S 0xfff0707f
7025+#define MATCH_FNMADD_D 0x200004f
7026+#define MASK_FNMADD_D 0x600007f
7027+#define MATCH_FNMADD_H 0x400004f
7028+#define MASK_FNMADD_H 0x600007f
7029+#define MATCH_FNMADD_S 0x4f
7030+#define MASK_FNMADD_S 0x600007f
7031+#define MATCH_FNMSUB_D 0x200004b
7032+#define MASK_FNMSUB_D 0x600007f
7033+#define MATCH_FNMSUB_H 0x400004b
7034+#define MASK_FNMSUB_H 0x600007f
7035+#define MATCH_FNMSUB_S 0x4b
7036+#define MASK_FNMSUB_S 0x600007f
7037+#define MATCH_FRCSR 0x302073
7038+#define MASK_FRCSR 0xfffff07f
7039+#define MATCH_FRFLAGS 0x102073
7040+#define MASK_FRFLAGS 0xfffff07f
7041+#define MATCH_FRRM 0x202073
7042+#define MASK_FRRM 0xfffff07f
7043+#define MATCH_FSCSR 0x301073
7044+#define MASK_FSCSR 0xfff0707f
7045+#define MATCH_FSD 0x3027
7046+#define MASK_FSD 0x707f
7047+#define MATCH_FSFLAGS 0x101073
7048+#define MASK_FSFLAGS 0xfff0707f
7049+#define MATCH_FSFLAGSI 0x105073
7050+#define MASK_FSFLAGSI 0xfff0707f
7051+#define MATCH_FSGNJ_D 0x22000053
7052+#define MASK_FSGNJ_D 0xfe00707f
7053+#define MATCH_FSGNJ_H 0x2c000053
7054+#define MASK_FSGNJ_H 0xfe00707f
7055+#define MATCH_FSGNJ_S 0x20000053
7056+#define MASK_FSGNJ_S 0xfe00707f
7057+#define MATCH_FSGNJN_D 0x22001053
7058+#define MASK_FSGNJN_D 0xfe00707f
7059+#define MATCH_FSGNJN_H 0x34000053
7060+#define MASK_FSGNJN_H 0xfe00707f
7061+#define MATCH_FSGNJN_S 0x20001053
7062+#define MASK_FSGNJN_S 0xfe00707f
7063+#define MATCH_FSGNJX_D 0x22002053
7064+#define MASK_FSGNJX_D 0xfe00707f
7065+#define MATCH_FSGNJX_H 0x3c000053
7066+#define MASK_FSGNJX_H 0xfe00707f
7067+#define MATCH_FSGNJX_S 0x20002053
7068+#define MASK_FSGNJX_S 0xfe00707f
7069+#define MATCH_FSH 0x1027
7070+#define MASK_FSH 0x707f
7071+#define MATCH_FSQRT_D 0x5a000053
7072+#define MASK_FSQRT_D 0xfff0007f
7073+#define MATCH_FSQRT_H 0x24000053
7074+#define MASK_FSQRT_H 0xfff0007f
7075+#define MATCH_FSQRT_S 0x58000053
7076+#define MASK_FSQRT_S 0xfff0007f
7077+#define MATCH_FSRM 0x201073
7078+#define MASK_FSRM 0xfff0707f
7079+#define MATCH_FSRMI 0x205073
7080+#define MASK_FSRMI 0xfff0707f
7081+#define MATCH_FSUB_D 0xa000053
7082+#define MASK_FSUB_D 0xfe00007f
7083+#define MATCH_FSUB_H 0xc000053
7084+#define MASK_FSUB_H 0xfe00007f
7085+#define MATCH_FSUB_S 0x8000053
7086+#define MASK_FSUB_S 0xfe00007f
7087+#define MATCH_FSW 0x2027
7088+#define MASK_FSW 0x707f
7089+#define MATCH_HRTS 0x20500073
7090+#define MASK_HRTS 0xffffffff
7091+#define MATCH_JAL 0x6f
7092+#define MASK_JAL 0x7f
7093+#define MATCH_JALR 0x67
7094+#define MASK_JALR 0x707f
7095+#define MATCH_LB 0x3
7096+#define MASK_LB 0x707f
7097+#define MATCH_LBU 0x4003
7098+#define MASK_LBU 0x707f
7099+#define MATCH_LD 0x3003
7100+#define MASK_LD 0x707f
7101+#define MATCH_LH 0x1003
7102+#define MASK_LH 0x707f
7103+#define MATCH_LHU 0x5003
7104+#define MASK_LHU 0x707f
7105+#define MATCH_LR_D 0x1000302f
7106+#define MASK_LR_D 0xf9f0707f
7107+#define MATCH_LR_W 0x1000202f
7108+#define MASK_LR_W 0xf9f0707f
7109+#define MATCH_LUI 0x37
7110+#define MASK_LUI 0x7f
7111+#define MATCH_LW 0x2003
7112+#define MASK_LW 0x707f
7113+#define MATCH_LWU 0x6003
7114+#define MASK_LWU 0x707f
7115+#define MATCH_MOVN 0x2007077
7116+#define MASK_MOVN 0xfe00707f
7117+#define MATCH_MOVZ 0x7077
7118+#define MASK_MOVZ 0xfe00707f
7119+#define MATCH_MRTH 0x30600073
7120+#define MASK_MRTH 0xffffffff
7121+#define MATCH_MRTS 0x30500073
7122+#define MASK_MRTS 0xffffffff
7123+#define MATCH_MUL 0x2000033
7124+#define MASK_MUL 0xfe00707f
7125+#define MATCH_MULH 0x2001033
7126+#define MASK_MULH 0xfe00707f
7127+#define MATCH_MULHSU 0x2002033
7128+#define MASK_MULHSU 0xfe00707f
7129+#define MATCH_MULHU 0x2003033
7130+#define MASK_MULHU 0xfe00707f
7131+#define MATCH_MULW 0x200003b
7132+#define MASK_MULW 0xfe00707f
7133+#define MATCH_OR 0x6033
7134+#define MASK_OR 0xfe00707f
7135+#define MATCH_ORI 0x6013
7136+#define MASK_ORI 0x707f
7137+#define MATCH_RDCYCLE 0xc0002073
7138+#define MASK_RDCYCLE 0xfffff07f
7139+#define MATCH_RDCYCLEH 0xc8002073
7140+#define MASK_RDCYCLEH 0xfffff07f
7141+#define MATCH_RDINSTRET 0xc0202073
7142+#define MASK_RDINSTRET 0xfffff07f
7143+#define MATCH_RDINSTRETH 0xc8202073
7144+#define MASK_RDINSTRETH 0xfffff07f
7145+#define MATCH_RDTIME 0xc0102073
7146+#define MASK_RDTIME 0xfffff07f
7147+#define MATCH_RDTIMEH 0xc8102073
7148+#define MASK_RDTIMEH 0xfffff07f
7149+#define MATCH_REM 0x2006033
7150+#define MASK_REM 0xfe00707f
7151+#define MATCH_REMU 0x2007033
7152+#define MASK_REMU 0xfe00707f
7153+#define MATCH_REMUW 0x200703b
7154+#define MASK_REMUW 0xfe00707f
7155+#define MATCH_REMW 0x200603b
7156+#define MASK_REMW 0xfe00707f
7157+#define MATCH_SB 0x23
7158+#define MASK_SB 0x707f
7159+#define MATCH_SBREAK 0x100073
7160+#define MASK_SBREAK 0xffffffff
7161+#define MATCH_SC_D 0x1800302f
7162+#define MASK_SC_D 0xf800707f
7163+#define MATCH_SC_W 0x1800202f
7164+#define MASK_SC_W 0xf800707f
7165+#define MATCH_SCALL 0x73
7166+#define MASK_SCALL 0xffffffff
7167+#define MATCH_SD 0x3023
7168+#define MASK_SD 0x707f
7169+#define MATCH_SFENCE_VM 0x10100073
7170+#define MASK_SFENCE_VM 0xfff07fff
7171+#define MATCH_SH 0x1023
7172+#define MASK_SH 0x707f
7173+#define MATCH_SLL 0x1033
7174+#define MASK_SLL 0xfe00707f
7175+#define MATCH_SLLI 0x1013
7176+#define MASK_SLLI 0xfc00707f
7177+#define MATCH_SLLI_RV32 0x1013
7178+#define MASK_SLLI_RV32 0xfe00707f
7179+#define MATCH_SLLIW 0x101b
7180+#define MASK_SLLIW 0xfe00707f
7181+#define MATCH_SLLW 0x103b
7182+#define MASK_SLLW 0xfe00707f
7183+#define MATCH_SLT 0x2033
7184+#define MASK_SLT 0xfe00707f
7185+#define MATCH_SLTI 0x2013
7186+#define MASK_SLTI 0x707f
7187+#define MATCH_SLTIU 0x3013
7188+#define MASK_SLTIU 0x707f
7189+#define MATCH_SLTU 0x3033
7190+#define MASK_SLTU 0xfe00707f
7191+#define MATCH_SRA 0x40005033
7192+#define MASK_SRA 0xfe00707f
7193+#define MATCH_SRAI 0x40005013
7194+#define MASK_SRAI 0xfc00707f
7195+#define MATCH_SRAI_RV32 0x40005013
7196+#define MASK_SRAI_RV32 0xfe00707f
7197+#define MATCH_SRAIW 0x4000501b
7198+#define MASK_SRAIW 0xfe00707f
7199+#define MATCH_SRAW 0x4000503b
7200+#define MASK_SRAW 0xfe00707f
7201+#define MATCH_SRET 0x10000073
7202+#define MASK_SRET 0xffffffff
7203+#define MATCH_SRL 0x5033
7204+#define MASK_SRL 0xfe00707f
7205+#define MATCH_SRLI 0x5013
7206+#define MASK_SRLI 0xfc00707f
7207+#define MATCH_SRLI_RV32 0x5013
7208+#define MASK_SRLI_RV32 0xfe00707f
7209+#define MATCH_SRLIW 0x501b
7210+#define MASK_SRLIW 0xfe00707f
7211+#define MATCH_SRLW 0x503b
7212+#define MASK_SRLW 0xfe00707f
7213+#define MATCH_STOP 0x5077
7214+#define MASK_STOP 0xffffffff
7215+#define MATCH_SUB 0x40000033
7216+#define MASK_SUB 0xfe00707f
7217+#define MATCH_SUBW 0x4000003b
7218+#define MASK_SUBW 0xfe00707f
7219+#define MATCH_SW 0x2023
7220+#define MASK_SW 0x707f
7221+#define MATCH_UTIDX 0x6077
7222+#define MASK_UTIDX 0xfffff07f
7223+#define MATCH_VENQCMD 0xa00302b
7224+#define MASK_VENQCMD 0xfe007fff
7225+#define MATCH_VENQCNT 0x1000302b
7226+#define MASK_VENQCNT 0xfe007fff
7227+#define MATCH_VENQIMM1 0xc00302b
7228+#define MASK_VENQIMM1 0xfe007fff
7229+#define MATCH_VENQIMM2 0xe00302b
7230+#define MASK_VENQIMM2 0xfe007fff
7231+#define MATCH_VF 0x10202b
7232+#define MASK_VF 0x1f0707f
7233+#define MATCH_VFLD 0x1600205b
7234+#define MASK_VFLD 0xfff0707f
7235+#define MATCH_VFLSEGD 0x1600205b
7236+#define MASK_VFLSEGD 0x1ff0707f
7237+#define MATCH_VFLSEGSTD 0x1600305b
7238+#define MASK_VFLSEGSTD 0x1e00707f
7239+#define MATCH_VFLSEGSTW 0x1400305b
7240+#define MASK_VFLSEGSTW 0x1e00707f
7241+#define MATCH_VFLSEGW 0x1400205b
7242+#define MASK_VFLSEGW 0x1ff0707f
7243+#define MATCH_VFLSTD 0x1600305b
7244+#define MASK_VFLSTD 0xfe00707f
7245+#define MATCH_VFLSTW 0x1400305b
7246+#define MASK_VFLSTW 0xfe00707f
7247+#define MATCH_VFLW 0x1400205b
7248+#define MASK_VFLW 0xfff0707f
7249+#define MATCH_VFMSV_D 0x1200202b
7250+#define MASK_VFMSV_D 0xfff0707f
7251+#define MATCH_VFMSV_S 0x1000202b
7252+#define MASK_VFMSV_S 0xfff0707f
7253+#define MATCH_VFMVV 0x1000002b
7254+#define MASK_VFMVV 0xfff0707f
7255+#define MATCH_VFSD 0x1600207b
7256+#define MASK_VFSD 0xfff0707f
7257+#define MATCH_VFSSEGD 0x1600207b
7258+#define MASK_VFSSEGD 0x1ff0707f
7259+#define MATCH_VFSSEGSTD 0x1600307b
7260+#define MASK_VFSSEGSTD 0x1e00707f
7261+#define MATCH_VFSSEGSTW 0x1400307b
7262+#define MASK_VFSSEGSTW 0x1e00707f
7263+#define MATCH_VFSSEGW 0x1400207b
7264+#define MASK_VFSSEGW 0x1ff0707f
7265+#define MATCH_VFSSTD 0x1600307b
7266+#define MASK_VFSSTD 0xfe00707f
7267+#define MATCH_VFSSTW 0x1400307b
7268+#define MASK_VFSSTW 0xfe00707f
7269+#define MATCH_VFSW 0x1400207b
7270+#define MASK_VFSW 0xfff0707f
7271+#define MATCH_VGETCFG 0x400b
7272+#define MASK_VGETCFG 0xfffff07f
7273+#define MATCH_VGETVL 0x200400b
7274+#define MASK_VGETVL 0xfffff07f
7275+#define MATCH_VLB 0x205b
7276+#define MASK_VLB 0xfff0707f
7277+#define MATCH_VLBU 0x800205b
7278+#define MASK_VLBU 0xfff0707f
7279+#define MATCH_VLD 0x600205b
7280+#define MASK_VLD 0xfff0707f
7281+#define MATCH_VLH 0x200205b
7282+#define MASK_VLH 0xfff0707f
7283+#define MATCH_VLHU 0xa00205b
7284+#define MASK_VLHU 0xfff0707f
7285+#define MATCH_VLSEGB 0x205b
7286+#define MASK_VLSEGB 0x1ff0707f
7287+#define MATCH_VLSEGBU 0x800205b
7288+#define MASK_VLSEGBU 0x1ff0707f
7289+#define MATCH_VLSEGD 0x600205b
7290+#define MASK_VLSEGD 0x1ff0707f
7291+#define MATCH_VLSEGH 0x200205b
7292+#define MASK_VLSEGH 0x1ff0707f
7293+#define MATCH_VLSEGHU 0xa00205b
7294+#define MASK_VLSEGHU 0x1ff0707f
7295+#define MATCH_VLSEGSTB 0x305b
7296+#define MASK_VLSEGSTB 0x1e00707f
7297+#define MATCH_VLSEGSTBU 0x800305b
7298+#define MASK_VLSEGSTBU 0x1e00707f
7299+#define MATCH_VLSEGSTD 0x600305b
7300+#define MASK_VLSEGSTD 0x1e00707f
7301+#define MATCH_VLSEGSTH 0x200305b
7302+#define MASK_VLSEGSTH 0x1e00707f
7303+#define MATCH_VLSEGSTHU 0xa00305b
7304+#define MASK_VLSEGSTHU 0x1e00707f
7305+#define MATCH_VLSEGSTW 0x400305b
7306+#define MASK_VLSEGSTW 0x1e00707f
7307+#define MATCH_VLSEGSTWU 0xc00305b
7308+#define MASK_VLSEGSTWU 0x1e00707f
7309+#define MATCH_VLSEGW 0x400205b
7310+#define MASK_VLSEGW 0x1ff0707f
7311+#define MATCH_VLSEGWU 0xc00205b
7312+#define MASK_VLSEGWU 0x1ff0707f
7313+#define MATCH_VLSTB 0x305b
7314+#define MASK_VLSTB 0xfe00707f
7315+#define MATCH_VLSTBU 0x800305b
7316+#define MASK_VLSTBU 0xfe00707f
7317+#define MATCH_VLSTD 0x600305b
7318+#define MASK_VLSTD 0xfe00707f
7319+#define MATCH_VLSTH 0x200305b
7320+#define MASK_VLSTH 0xfe00707f
7321+#define MATCH_VLSTHU 0xa00305b
7322+#define MASK_VLSTHU 0xfe00707f
7323+#define MATCH_VLSTW 0x400305b
7324+#define MASK_VLSTW 0xfe00707f
7325+#define MATCH_VLSTWU 0xc00305b
7326+#define MASK_VLSTWU 0xfe00707f
7327+#define MATCH_VLW 0x400205b
7328+#define MASK_VLW 0xfff0707f
7329+#define MATCH_VLWU 0xc00205b
7330+#define MASK_VLWU 0xfff0707f
7331+#define MATCH_VMSV 0x200202b
7332+#define MASK_VMSV 0xfff0707f
7333+#define MATCH_VMVV 0x200002b
7334+#define MASK_VMVV 0xfff0707f
7335+#define MATCH_VSB 0x207b
7336+#define MASK_VSB 0xfff0707f
7337+#define MATCH_VSD 0x600207b
7338+#define MASK_VSD 0xfff0707f
7339+#define MATCH_VSETCFG 0x200b
7340+#define MASK_VSETCFG 0x7fff
7341+#define MATCH_VSETVL 0x600b
7342+#define MASK_VSETVL 0xfff0707f
7343+#define MATCH_VSH 0x200207b
7344+#define MASK_VSH 0xfff0707f
7345+#define MATCH_VSSEGB 0x207b
7346+#define MASK_VSSEGB 0x1ff0707f
7347+#define MATCH_VSSEGD 0x600207b
7348+#define MASK_VSSEGD 0x1ff0707f
7349+#define MATCH_VSSEGH 0x200207b
7350+#define MASK_VSSEGH 0x1ff0707f
7351+#define MATCH_VSSEGSTB 0x307b
7352+#define MASK_VSSEGSTB 0x1e00707f
7353+#define MATCH_VSSEGSTD 0x600307b
7354+#define MASK_VSSEGSTD 0x1e00707f
7355+#define MATCH_VSSEGSTH 0x200307b
7356+#define MASK_VSSEGSTH 0x1e00707f
7357+#define MATCH_VSSEGSTW 0x400307b
7358+#define MASK_VSSEGSTW 0x1e00707f
7359+#define MATCH_VSSEGW 0x400207b
7360+#define MASK_VSSEGW 0x1ff0707f
7361+#define MATCH_VSSTB 0x307b
7362+#define MASK_VSSTB 0xfe00707f
7363+#define MATCH_VSSTD 0x600307b
7364+#define MASK_VSSTD 0xfe00707f
7365+#define MATCH_VSSTH 0x200307b
7366+#define MASK_VSSTH 0xfe00707f
7367+#define MATCH_VSSTW 0x400307b
7368+#define MASK_VSSTW 0xfe00707f
7369+#define MATCH_VSW 0x400207b
7370+#define MASK_VSW 0xfff0707f
7371+#define MATCH_VXCPTAUX 0x200402b
7372+#define MASK_VXCPTAUX 0xfffff07f
7373+#define MATCH_VXCPTCAUSE 0x402b
7374+#define MASK_VXCPTCAUSE 0xfffff07f
7375+#define MATCH_VXCPTEVAC 0x600302b
7376+#define MASK_VXCPTEVAC 0xfff07fff
7377+#define MATCH_VXCPTHOLD 0x800302b
7378+#define MASK_VXCPTHOLD 0xfff07fff
7379+#define MATCH_VXCPTKILL 0x400302b
7380+#define MASK_VXCPTKILL 0xffffffff
7381+#define MATCH_VXCPTRESTORE 0x200302b
7382+#define MASK_VXCPTRESTORE 0xfff07fff
7383+#define MATCH_VXCPTSAVE 0x302b
7384+#define MASK_VXCPTSAVE 0xfff07fff
7385+#define MATCH_WFI 0x10200073
7386+#define MASK_WFI 0xffffffff
7387+#define MATCH_XOR 0x4033
7388+#define MASK_XOR 0xfe00707f
7389+#define MATCH_XORI 0x4013
7390+#define MASK_XORI 0x707f
7391+#define CSR_FFLAGS 0x1
7392+#define CSR_FRM 0x2
7393+#define CSR_FCSR 0x3
7394+#define CSR_CYCLE 0xc00
7395+#define CSR_TIME 0xc01
7396+#define CSR_INSTRET 0xc02
7397+#define CSR_STATS 0xc0
7398+#define CSR_UARCH0 0xcc0
7399+#define CSR_UARCH1 0xcc1
7400+#define CSR_UARCH2 0xcc2
7401+#define CSR_UARCH3 0xcc3
7402+#define CSR_UARCH4 0xcc4
7403+#define CSR_UARCH5 0xcc5
7404+#define CSR_UARCH6 0xcc6
7405+#define CSR_UARCH7 0xcc7
7406+#define CSR_UARCH8 0xcc8
7407+#define CSR_UARCH9 0xcc9
7408+#define CSR_UARCH10 0xcca
7409+#define CSR_UARCH11 0xccb
7410+#define CSR_UARCH12 0xccc
7411+#define CSR_UARCH13 0xccd
7412+#define CSR_UARCH14 0xcce
7413+#define CSR_UARCH15 0xccf
7414+#define CSR_SSTATUS 0x100
7415+#define CSR_STVEC 0x101
7416+#define CSR_SIE 0x104
7417+#define CSR_SSCRATCH 0x140
7418+#define CSR_SEPC 0x141
7419+#define CSR_SIP 0x144
7420+#define CSR_SPTBR 0x180
7421+#define CSR_SASID 0x181
7422+#define CSR_CYCLEW 0x900
7423+#define CSR_TIMEW 0x901
7424+#define CSR_INSTRETW 0x902
7425+#define CSR_STIME 0xd01
7426+#define CSR_SCAUSE 0xd42
7427+#define CSR_SBADADDR 0xd43
7428+#define CSR_STIMEW 0xa01
7429+#define CSR_MSTATUS 0x300
7430+#define CSR_MTVEC 0x301
7431+#define CSR_MTDELEG 0x302
7432+#define CSR_MIE 0x304
7433+#define CSR_MTIMECMP 0x321
7434+#define CSR_MSCRATCH 0x340
7435+#define CSR_MEPC 0x341
7436+#define CSR_MCAUSE 0x342
7437+#define CSR_MBADADDR 0x343
7438+#define CSR_MIP 0x344
7439+#define CSR_MTIME 0x701
7440+#define CSR_MCPUID 0xf00
7441+#define CSR_MIMPID 0xf01
7442+#define CSR_MHARTID 0xf10
7443+#define CSR_MTOHOST 0x780
7444+#define CSR_MFROMHOST 0x781
7445+#define CSR_MRESET 0x782
7446+#define CSR_SEND_IPI 0x783
7447+#define CSR_CYCLEH 0xc80
7448+#define CSR_TIMEH 0xc81
7449+#define CSR_INSTRETH 0xc82
7450+#define CSR_CYCLEHW 0x980
7451+#define CSR_TIMEHW 0x981
7452+#define CSR_INSTRETHW 0x982
7453+#define CSR_STIMEH 0xd81
7454+#define CSR_STIMEHW 0xa81
7455+#define CSR_MTIMECMPH 0x361
7456+#define CSR_MTIMEH 0x741
7457+#define CAUSE_MISALIGNED_FETCH 0x0
7458+#define CAUSE_FAULT_FETCH 0x1
7459+#define CAUSE_ILLEGAL_INSTRUCTION 0x2
7460+#define CAUSE_BREAKPOINT 0x3
7461+#define CAUSE_MISALIGNED_LOAD 0x4
7462+#define CAUSE_FAULT_LOAD 0x5
7463+#define CAUSE_MISALIGNED_STORE 0x6
7464+#define CAUSE_FAULT_STORE 0x7
7465+#define CAUSE_USER_ECALL 0x8
7466+#define CAUSE_SUPERVISOR_ECALL 0x9
7467+#define CAUSE_HYPERVISOR_ECALL 0xa
7468+#define CAUSE_MACHINE_ECALL 0xb
7469+#endif
7470+#ifdef DECLARE_INSN
7471+DECLARE_INSN(add, MATCH_ADD, MASK_ADD)
7472+DECLARE_INSN(addi, MATCH_ADDI, MASK_ADDI)
7473+DECLARE_INSN(addiw, MATCH_ADDIW, MASK_ADDIW)
7474+DECLARE_INSN(addw, MATCH_ADDW, MASK_ADDW)
7475+DECLARE_INSN(amoadd_d, MATCH_AMOADD_D, MASK_AMOADD_D)
7476+DECLARE_INSN(amoadd_w, MATCH_AMOADD_W, MASK_AMOADD_W)
7477+DECLARE_INSN(amoand_d, MATCH_AMOAND_D, MASK_AMOAND_D)
7478+DECLARE_INSN(amoand_w, MATCH_AMOAND_W, MASK_AMOAND_W)
7479+DECLARE_INSN(amomax_d, MATCH_AMOMAX_D, MASK_AMOMAX_D)
7480+DECLARE_INSN(amomax_w, MATCH_AMOMAX_W, MASK_AMOMAX_W)
7481+DECLARE_INSN(amomaxu_d, MATCH_AMOMAXU_D, MASK_AMOMAXU_D)
7482+DECLARE_INSN(amomaxu_w, MATCH_AMOMAXU_W, MASK_AMOMAXU_W)
7483+DECLARE_INSN(amomin_d, MATCH_AMOMIN_D, MASK_AMOMIN_D)
7484+DECLARE_INSN(amomin_w, MATCH_AMOMIN_W, MASK_AMOMIN_W)
7485+DECLARE_INSN(amominu_d, MATCH_AMOMINU_D, MASK_AMOMINU_D)
7486+DECLARE_INSN(amominu_w, MATCH_AMOMINU_W, MASK_AMOMINU_W)
7487+DECLARE_INSN(amoor_d, MATCH_AMOOR_D, MASK_AMOOR_D)
7488+DECLARE_INSN(amoor_w, MATCH_AMOOR_W, MASK_AMOOR_W)
7489+DECLARE_INSN(amoswap_d, MATCH_AMOSWAP_D, MASK_AMOSWAP_D)
7490+DECLARE_INSN(amoswap_w, MATCH_AMOSWAP_W, MASK_AMOSWAP_W)
7491+DECLARE_INSN(amoxor_d, MATCH_AMOXOR_D, MASK_AMOXOR_D)
7492+DECLARE_INSN(amoxor_w, MATCH_AMOXOR_W, MASK_AMOXOR_W)
7493+DECLARE_INSN(and, MATCH_AND, MASK_AND)
7494+DECLARE_INSN(andi, MATCH_ANDI, MASK_ANDI)
7495+DECLARE_INSN(auipc, MATCH_AUIPC, MASK_AUIPC)
7496+DECLARE_INSN(beq, MATCH_BEQ, MASK_BEQ)
7497+DECLARE_INSN(bge, MATCH_BGE, MASK_BGE)
7498+DECLARE_INSN(bgeu, MATCH_BGEU, MASK_BGEU)
7499+DECLARE_INSN(blt, MATCH_BLT, MASK_BLT)
7500+DECLARE_INSN(bltu, MATCH_BLTU, MASK_BLTU)
7501+DECLARE_INSN(bne, MATCH_BNE, MASK_BNE)
7502+DECLARE_INSN(c_add, MATCH_C_ADD, MASK_C_ADD)
7503+DECLARE_INSN(c_add3, MATCH_C_ADD3, MASK_C_ADD3)
7504+DECLARE_INSN(c_addi, MATCH_C_ADDI, MASK_C_ADDI)
7505+DECLARE_INSN(c_addi16sp, MATCH_C_ADDI16SP, MASK_C_ADDI16SP)
7506+DECLARE_INSN(c_addi4spn, MATCH_C_ADDI4SPN, MASK_C_ADDI4SPN)
7507+DECLARE_INSN(c_addin, MATCH_C_ADDIN, MASK_C_ADDIN)
7508+DECLARE_INSN(c_addiw, MATCH_C_ADDIW, MASK_C_ADDIW)
7509+DECLARE_INSN(c_addw, MATCH_C_ADDW, MASK_C_ADDW)
7510+DECLARE_INSN(c_and3, MATCH_C_AND3, MASK_C_AND3)
7511+DECLARE_INSN(c_andi, MATCH_C_ANDI, MASK_C_ANDI)
7512+DECLARE_INSN(c_andin, MATCH_C_ANDIN, MASK_C_ANDIN)
7513+DECLARE_INSN(c_beqz, MATCH_C_BEQZ, MASK_C_BEQZ)
7514+DECLARE_INSN(c_bgez, MATCH_C_BGEZ, MASK_C_BGEZ)
7515+DECLARE_INSN(c_bltz, MATCH_C_BLTZ, MASK_C_BLTZ)
7516+DECLARE_INSN(c_bnez, MATCH_C_BNEZ, MASK_C_BNEZ)
7517+DECLARE_INSN(c_ebreak, MATCH_C_EBREAK, MASK_C_EBREAK)
7518+DECLARE_INSN(c_j, MATCH_C_J, MASK_C_J)
7519+DECLARE_INSN(c_jal, MATCH_C_JAL, MASK_C_JAL)
7520+DECLARE_INSN(c_jalr, MATCH_C_JALR, MASK_C_JALR)
7521+DECLARE_INSN(c_jr, MATCH_C_JR, MASK_C_JR)
7522+DECLARE_INSN(c_ld, MATCH_C_LD, MASK_C_LD)
7523+DECLARE_INSN(c_ldsp, MATCH_C_LDSP, MASK_C_LDSP)
7524+DECLARE_INSN(c_li, MATCH_C_LI, MASK_C_LI)
7525+DECLARE_INSN(c_lui, MATCH_C_LUI, MASK_C_LUI)
7526+DECLARE_INSN(c_lw, MATCH_C_LW, MASK_C_LW)
7527+DECLARE_INSN(c_lwsp, MATCH_C_LWSP, MASK_C_LWSP)
7528+DECLARE_INSN(c_mv, MATCH_C_MV, MASK_C_MV)
7529+DECLARE_INSN(c_or3, MATCH_C_OR3, MASK_C_OR3)
7530+DECLARE_INSN(c_orin, MATCH_C_ORIN, MASK_C_ORIN)
7531+DECLARE_INSN(c_sd, MATCH_C_SD, MASK_C_SD)
7532+DECLARE_INSN(c_sdsp, MATCH_C_SDSP, MASK_C_SDSP)
7533+DECLARE_INSN(c_sll, MATCH_C_SLL, MASK_C_SLL)
7534+DECLARE_INSN(c_slli, MATCH_C_SLLI, MASK_C_SLLI)
7535+DECLARE_INSN(c_slliw, MATCH_C_SLLIW, MASK_C_SLLIW)
7536+DECLARE_INSN(c_sllr, MATCH_C_SLLR, MASK_C_SLLR)
7537+DECLARE_INSN(c_slt, MATCH_C_SLT, MASK_C_SLT)
7538+DECLARE_INSN(c_sltr, MATCH_C_SLTR, MASK_C_SLTR)
7539+DECLARE_INSN(c_sltu, MATCH_C_SLTU, MASK_C_SLTU)
7540+DECLARE_INSN(c_sltur, MATCH_C_SLTUR, MASK_C_SLTUR)
7541+DECLARE_INSN(c_sra, MATCH_C_SRA, MASK_C_SRA)
7542+DECLARE_INSN(c_srai, MATCH_C_SRAI, MASK_C_SRAI)
7543+DECLARE_INSN(c_srl, MATCH_C_SRL, MASK_C_SRL)
7544+DECLARE_INSN(c_srli, MATCH_C_SRLI, MASK_C_SRLI)
7545+DECLARE_INSN(c_srlr, MATCH_C_SRLR, MASK_C_SRLR)
7546+DECLARE_INSN(c_sub, MATCH_C_SUB, MASK_C_SUB)
7547+DECLARE_INSN(c_sub3, MATCH_C_SUB3, MASK_C_SUB3)
7548+DECLARE_INSN(c_sw, MATCH_C_SW, MASK_C_SW)
7549+DECLARE_INSN(c_swsp, MATCH_C_SWSP, MASK_C_SWSP)
7550+DECLARE_INSN(c_xor, MATCH_C_XOR, MASK_C_XOR)
7551+DECLARE_INSN(c_xorin, MATCH_C_XORIN, MASK_C_XORIN)
7552+DECLARE_INSN(csrrc, MATCH_CSRRC, MASK_CSRRC)
7553+DECLARE_INSN(csrrci, MATCH_CSRRCI, MASK_CSRRCI)
7554+DECLARE_INSN(csrrs, MATCH_CSRRS, MASK_CSRRS)
7555+DECLARE_INSN(csrrsi, MATCH_CSRRSI, MASK_CSRRSI)
7556+DECLARE_INSN(csrrw, MATCH_CSRRW, MASK_CSRRW)
7557+DECLARE_INSN(csrrwi, MATCH_CSRRWI, MASK_CSRRWI)
7558+DECLARE_INSN(custom0, MATCH_CUSTOM0, MASK_CUSTOM0)
7559+DECLARE_INSN(custom0_rd, MATCH_CUSTOM0_RD, MASK_CUSTOM0_RD)
7560+DECLARE_INSN(custom0_rd_rs1, MATCH_CUSTOM0_RD_RS1, MASK_CUSTOM0_RD_RS1)
7561+DECLARE_INSN(custom0_rd_rs1_rs2, MATCH_CUSTOM0_RD_RS1_RS2, MASK_CUSTOM0_RD_RS1_RS2)
7562+DECLARE_INSN(custom0_rs1, MATCH_CUSTOM0_RS1, MASK_CUSTOM0_RS1)
7563+DECLARE_INSN(custom0_rs1_rs2, MATCH_CUSTOM0_RS1_RS2, MASK_CUSTOM0_RS1_RS2)
7564+DECLARE_INSN(custom1, MATCH_CUSTOM1, MASK_CUSTOM1)
7565+DECLARE_INSN(custom1_rd, MATCH_CUSTOM1_RD, MASK_CUSTOM1_RD)
7566+DECLARE_INSN(custom1_rd_rs1, MATCH_CUSTOM1_RD_RS1, MASK_CUSTOM1_RD_RS1)
7567+DECLARE_INSN(custom1_rd_rs1_rs2, MATCH_CUSTOM1_RD_RS1_RS2, MASK_CUSTOM1_RD_RS1_RS2)
7568+DECLARE_INSN(custom1_rs1, MATCH_CUSTOM1_RS1, MASK_CUSTOM1_RS1)
7569+DECLARE_INSN(custom1_rs1_rs2, MATCH_CUSTOM1_RS1_RS2, MASK_CUSTOM1_RS1_RS2)
7570+DECLARE_INSN(custom2, MATCH_CUSTOM2, MASK_CUSTOM2)
7571+DECLARE_INSN(custom2_rd, MATCH_CUSTOM2_RD, MASK_CUSTOM2_RD)
7572+DECLARE_INSN(custom2_rd_rs1, MATCH_CUSTOM2_RD_RS1, MASK_CUSTOM2_RD_RS1)
7573+DECLARE_INSN(custom2_rd_rs1_rs2, MATCH_CUSTOM2_RD_RS1_RS2, MASK_CUSTOM2_RD_RS1_RS2)
7574+DECLARE_INSN(custom2_rs1, MATCH_CUSTOM2_RS1, MASK_CUSTOM2_RS1)
7575+DECLARE_INSN(custom2_rs1_rs2, MATCH_CUSTOM2_RS1_RS2, MASK_CUSTOM2_RS1_RS2)
7576+DECLARE_INSN(custom3, MATCH_CUSTOM3, MASK_CUSTOM3)
7577+DECLARE_INSN(custom3_rd, MATCH_CUSTOM3_RD, MASK_CUSTOM3_RD)
7578+DECLARE_INSN(custom3_rd_rs1, MATCH_CUSTOM3_RD_RS1, MASK_CUSTOM3_RD_RS1)
7579+DECLARE_INSN(custom3_rd_rs1_rs2, MATCH_CUSTOM3_RD_RS1_RS2, MASK_CUSTOM3_RD_RS1_RS2)
7580+DECLARE_INSN(custom3_rs1, MATCH_CUSTOM3_RS1, MASK_CUSTOM3_RS1)
7581+DECLARE_INSN(custom3_rs1_rs2, MATCH_CUSTOM3_RS1_RS2, MASK_CUSTOM3_RS1_RS2)
7582+DECLARE_INSN(div, MATCH_DIV, MASK_DIV)
7583+DECLARE_INSN(divu, MATCH_DIVU, MASK_DIVU)
7584+DECLARE_INSN(divuw, MATCH_DIVUW, MASK_DIVUW)
7585+DECLARE_INSN(divw, MATCH_DIVW, MASK_DIVW)
7586+DECLARE_INSN(ebreak, MATCH_EBREAK, MASK_EBREAK)
7587+DECLARE_INSN(ecall, MATCH_ECALL, MASK_ECALL)
7588+DECLARE_INSN(eret, MATCH_ERET, MASK_ERET)
7589+DECLARE_INSN(fadd_d, MATCH_FADD_D, MASK_FADD_D)
7590+DECLARE_INSN(fadd_h, MATCH_FADD_H, MASK_FADD_H)
7591+DECLARE_INSN(fadd_s, MATCH_FADD_S, MASK_FADD_S)
7592+DECLARE_INSN(fclass_d, MATCH_FCLASS_D, MASK_FCLASS_D)
7593+DECLARE_INSN(fclass_s, MATCH_FCLASS_S, MASK_FCLASS_S)
7594+DECLARE_INSN(fcvt_d_h, MATCH_FCVT_D_H, MASK_FCVT_D_H)
7595+DECLARE_INSN(fcvt_d_l, MATCH_FCVT_D_L, MASK_FCVT_D_L)
7596+DECLARE_INSN(fcvt_d_lu, MATCH_FCVT_D_LU, MASK_FCVT_D_LU)
7597+DECLARE_INSN(fcvt_d_s, MATCH_FCVT_D_S, MASK_FCVT_D_S)
7598+DECLARE_INSN(fcvt_d_w, MATCH_FCVT_D_W, MASK_FCVT_D_W)
7599+DECLARE_INSN(fcvt_d_wu, MATCH_FCVT_D_WU, MASK_FCVT_D_WU)
7600+DECLARE_INSN(fcvt_h_d, MATCH_FCVT_H_D, MASK_FCVT_H_D)
7601+DECLARE_INSN(fcvt_h_l, MATCH_FCVT_H_L, MASK_FCVT_H_L)
7602+DECLARE_INSN(fcvt_h_lu, MATCH_FCVT_H_LU, MASK_FCVT_H_LU)
7603+DECLARE_INSN(fcvt_h_s, MATCH_FCVT_H_S, MASK_FCVT_H_S)
7604+DECLARE_INSN(fcvt_h_w, MATCH_FCVT_H_W, MASK_FCVT_H_W)
7605+DECLARE_INSN(fcvt_h_wu, MATCH_FCVT_H_WU, MASK_FCVT_H_WU)
7606+DECLARE_INSN(fcvt_l_d, MATCH_FCVT_L_D, MASK_FCVT_L_D)
7607+DECLARE_INSN(fcvt_l_h, MATCH_FCVT_L_H, MASK_FCVT_L_H)
7608+DECLARE_INSN(fcvt_l_s, MATCH_FCVT_L_S, MASK_FCVT_L_S)
7609+DECLARE_INSN(fcvt_lu_d, MATCH_FCVT_LU_D, MASK_FCVT_LU_D)
7610+DECLARE_INSN(fcvt_lu_h, MATCH_FCVT_LU_H, MASK_FCVT_LU_H)
7611+DECLARE_INSN(fcvt_lu_s, MATCH_FCVT_LU_S, MASK_FCVT_LU_S)
7612+DECLARE_INSN(fcvt_s_d, MATCH_FCVT_S_D, MASK_FCVT_S_D)
7613+DECLARE_INSN(fcvt_s_h, MATCH_FCVT_S_H, MASK_FCVT_S_H)
7614+DECLARE_INSN(fcvt_s_l, MATCH_FCVT_S_L, MASK_FCVT_S_L)
7615+DECLARE_INSN(fcvt_s_lu, MATCH_FCVT_S_LU, MASK_FCVT_S_LU)
7616+DECLARE_INSN(fcvt_s_w, MATCH_FCVT_S_W, MASK_FCVT_S_W)
7617+DECLARE_INSN(fcvt_s_wu, MATCH_FCVT_S_WU, MASK_FCVT_S_WU)
7618+DECLARE_INSN(fcvt_w_d, MATCH_FCVT_W_D, MASK_FCVT_W_D)
7619+DECLARE_INSN(fcvt_w_h, MATCH_FCVT_W_H, MASK_FCVT_W_H)
7620+DECLARE_INSN(fcvt_w_s, MATCH_FCVT_W_S, MASK_FCVT_W_S)
7621+DECLARE_INSN(fcvt_wu_d, MATCH_FCVT_WU_D, MASK_FCVT_WU_D)
7622+DECLARE_INSN(fcvt_wu_h, MATCH_FCVT_WU_H, MASK_FCVT_WU_H)
7623+DECLARE_INSN(fcvt_wu_s, MATCH_FCVT_WU_S, MASK_FCVT_WU_S)
7624+DECLARE_INSN(fdiv_d, MATCH_FDIV_D, MASK_FDIV_D)
7625+DECLARE_INSN(fdiv_h, MATCH_FDIV_H, MASK_FDIV_H)
7626+DECLARE_INSN(fdiv_s, MATCH_FDIV_S, MASK_FDIV_S)
7627+DECLARE_INSN(fence, MATCH_FENCE, MASK_FENCE)
7628+DECLARE_INSN(fence_i, MATCH_FENCE_I, MASK_FENCE_I)
7629+DECLARE_INSN(feq_d, MATCH_FEQ_D, MASK_FEQ_D)
7630+DECLARE_INSN(feq_h, MATCH_FEQ_H, MASK_FEQ_H)
7631+DECLARE_INSN(feq_s, MATCH_FEQ_S, MASK_FEQ_S)
7632+DECLARE_INSN(fld, MATCH_FLD, MASK_FLD)
7633+DECLARE_INSN(fle_d, MATCH_FLE_D, MASK_FLE_D)
7634+DECLARE_INSN(fle_h, MATCH_FLE_H, MASK_FLE_H)
7635+DECLARE_INSN(fle_s, MATCH_FLE_S, MASK_FLE_S)
7636+DECLARE_INSN(flh, MATCH_FLH, MASK_FLH)
7637+DECLARE_INSN(flt_d, MATCH_FLT_D, MASK_FLT_D)
7638+DECLARE_INSN(flt_h, MATCH_FLT_H, MASK_FLT_H)
7639+DECLARE_INSN(flt_s, MATCH_FLT_S, MASK_FLT_S)
7640+DECLARE_INSN(flw, MATCH_FLW, MASK_FLW)
7641+DECLARE_INSN(fmadd_d, MATCH_FMADD_D, MASK_FMADD_D)
7642+DECLARE_INSN(fmadd_h, MATCH_FMADD_H, MASK_FMADD_H)
7643+DECLARE_INSN(fmadd_s, MATCH_FMADD_S, MASK_FMADD_S)
7644+DECLARE_INSN(fmax_d, MATCH_FMAX_D, MASK_FMAX_D)
7645+DECLARE_INSN(fmax_h, MATCH_FMAX_H, MASK_FMAX_H)
7646+DECLARE_INSN(fmax_s, MATCH_FMAX_S, MASK_FMAX_S)
7647+DECLARE_INSN(fmin_d, MATCH_FMIN_D, MASK_FMIN_D)
7648+DECLARE_INSN(fmin_h, MATCH_FMIN_H, MASK_FMIN_H)
7649+DECLARE_INSN(fmin_s, MATCH_FMIN_S, MASK_FMIN_S)
7650+DECLARE_INSN(fmovn, MATCH_FMOVN, MASK_FMOVN)
7651+DECLARE_INSN(fmovz, MATCH_FMOVZ, MASK_FMOVZ)
7652+DECLARE_INSN(fmsub_d, MATCH_FMSUB_D, MASK_FMSUB_D)
7653+DECLARE_INSN(fmsub_h, MATCH_FMSUB_H, MASK_FMSUB_H)
7654+DECLARE_INSN(fmsub_s, MATCH_FMSUB_S, MASK_FMSUB_S)
7655+DECLARE_INSN(fmul_d, MATCH_FMUL_D, MASK_FMUL_D)
7656+DECLARE_INSN(fmul_h, MATCH_FMUL_H, MASK_FMUL_H)
7657+DECLARE_INSN(fmul_s, MATCH_FMUL_S, MASK_FMUL_S)
7658+DECLARE_INSN(fmv_d_x, MATCH_FMV_D_X, MASK_FMV_D_X)
7659+DECLARE_INSN(fmv_h_x, MATCH_FMV_H_X, MASK_FMV_H_X)
7660+DECLARE_INSN(fmv_s_x, MATCH_FMV_S_X, MASK_FMV_S_X)
7661+DECLARE_INSN(fmv_x_d, MATCH_FMV_X_D, MASK_FMV_X_D)
7662+DECLARE_INSN(fmv_x_h, MATCH_FMV_X_H, MASK_FMV_X_H)
7663+DECLARE_INSN(fmv_x_s, MATCH_FMV_X_S, MASK_FMV_X_S)
7664+DECLARE_INSN(fnmadd_d, MATCH_FNMADD_D, MASK_FNMADD_D)
7665+DECLARE_INSN(fnmadd_h, MATCH_FNMADD_H, MASK_FNMADD_H)
7666+DECLARE_INSN(fnmadd_s, MATCH_FNMADD_S, MASK_FNMADD_S)
7667+DECLARE_INSN(fnmsub_d, MATCH_FNMSUB_D, MASK_FNMSUB_D)
7668+DECLARE_INSN(fnmsub_h, MATCH_FNMSUB_H, MASK_FNMSUB_H)
7669+DECLARE_INSN(fnmsub_s, MATCH_FNMSUB_S, MASK_FNMSUB_S)
7670+DECLARE_INSN(frcsr, MATCH_FRCSR, MASK_FRCSR)
7671+DECLARE_INSN(frflags, MATCH_FRFLAGS, MASK_FRFLAGS)
7672+DECLARE_INSN(frrm, MATCH_FRRM, MASK_FRRM)
7673+DECLARE_INSN(fscsr, MATCH_FSCSR, MASK_FSCSR)
7674+DECLARE_INSN(fsd, MATCH_FSD, MASK_FSD)
7675+DECLARE_INSN(fsflags, MATCH_FSFLAGS, MASK_FSFLAGS)
7676+DECLARE_INSN(fsflagsi, MATCH_FSFLAGSI, MASK_FSFLAGSI)
7677+DECLARE_INSN(fsgnj_d, MATCH_FSGNJ_D, MASK_FSGNJ_D)
7678+DECLARE_INSN(fsgnj_h, MATCH_FSGNJ_H, MASK_FSGNJ_H)
7679+DECLARE_INSN(fsgnj_s, MATCH_FSGNJ_S, MASK_FSGNJ_S)
7680+DECLARE_INSN(fsgnjn_d, MATCH_FSGNJN_D, MASK_FSGNJN_D)
7681+DECLARE_INSN(fsgnjn_h, MATCH_FSGNJN_H, MASK_FSGNJN_H)
7682+DECLARE_INSN(fsgnjn_s, MATCH_FSGNJN_S, MASK_FSGNJN_S)
7683+DECLARE_INSN(fsgnjx_d, MATCH_FSGNJX_D, MASK_FSGNJX_D)
7684+DECLARE_INSN(fsgnjx_h, MATCH_FSGNJX_H, MASK_FSGNJX_H)
7685+DECLARE_INSN(fsgnjx_s, MATCH_FSGNJX_S, MASK_FSGNJX_S)
7686+DECLARE_INSN(fsh, MATCH_FSH, MASK_FSH)
7687+DECLARE_INSN(fsqrt_d, MATCH_FSQRT_D, MASK_FSQRT_D)
7688+DECLARE_INSN(fsqrt_h, MATCH_FSQRT_H, MASK_FSQRT_H)
7689+DECLARE_INSN(fsqrt_s, MATCH_FSQRT_S, MASK_FSQRT_S)
7690+DECLARE_INSN(fsrm, MATCH_FSRM, MASK_FSRM)
7691+DECLARE_INSN(fsrmi, MATCH_FSRMI, MASK_FSRMI)
7692+DECLARE_INSN(fsub_d, MATCH_FSUB_D, MASK_FSUB_D)
7693+DECLARE_INSN(fsub_h, MATCH_FSUB_H, MASK_FSUB_H)
7694+DECLARE_INSN(fsub_s, MATCH_FSUB_S, MASK_FSUB_S)
7695+DECLARE_INSN(fsw, MATCH_FSW, MASK_FSW)
7696+DECLARE_INSN(hrts, MATCH_HRTS, MASK_HRTS)
7697+DECLARE_INSN(jal, MATCH_JAL, MASK_JAL)
7698+DECLARE_INSN(jalr, MATCH_JALR, MASK_JALR)
7699+DECLARE_INSN(lb, MATCH_LB, MASK_LB)
7700+DECLARE_INSN(lbu, MATCH_LBU, MASK_LBU)
7701+DECLARE_INSN(ld, MATCH_LD, MASK_LD)
7702+DECLARE_INSN(lh, MATCH_LH, MASK_LH)
7703+DECLARE_INSN(lhu, MATCH_LHU, MASK_LHU)
7704+DECLARE_INSN(lr_d, MATCH_LR_D, MASK_LR_D)
7705+DECLARE_INSN(lr_w, MATCH_LR_W, MASK_LR_W)
7706+DECLARE_INSN(lui, MATCH_LUI, MASK_LUI)
7707+DECLARE_INSN(lw, MATCH_LW, MASK_LW)
7708+DECLARE_INSN(lwu, MATCH_LWU, MASK_LWU)
7709+DECLARE_INSN(movn, MATCH_MOVN, MASK_MOVN)
7710+DECLARE_INSN(movz, MATCH_MOVZ, MASK_MOVZ)
7711+DECLARE_INSN(mrth, MATCH_MRTH, MASK_MRTH)
7712+DECLARE_INSN(mrts, MATCH_MRTS, MASK_MRTS)
7713+DECLARE_INSN(mul, MATCH_MUL, MASK_MUL)
7714+DECLARE_INSN(mulh, MATCH_MULH, MASK_MULH)
7715+DECLARE_INSN(mulhsu, MATCH_MULHSU, MASK_MULHSU)
7716+DECLARE_INSN(mulhu, MATCH_MULHU, MASK_MULHU)
7717+DECLARE_INSN(mulw, MATCH_MULW, MASK_MULW)
7718+DECLARE_INSN(or, MATCH_OR, MASK_OR)
7719+DECLARE_INSN(ori, MATCH_ORI, MASK_ORI)
7720+DECLARE_INSN(rdcycle, MATCH_RDCYCLE, MASK_RDCYCLE)
7721+DECLARE_INSN(rdcycleh, MATCH_RDCYCLEH, MASK_RDCYCLEH)
7722+DECLARE_INSN(rdinstret, MATCH_RDINSTRET, MASK_RDINSTRET)
7723+DECLARE_INSN(rdinstreth, MATCH_RDINSTRETH, MASK_RDINSTRETH)
7724+DECLARE_INSN(rdtime, MATCH_RDTIME, MASK_RDTIME)
7725+DECLARE_INSN(rdtimeh, MATCH_RDTIMEH, MASK_RDTIMEH)
7726+DECLARE_INSN(rem, MATCH_REM, MASK_REM)
7727+DECLARE_INSN(remu, MATCH_REMU, MASK_REMU)
7728+DECLARE_INSN(remuw, MATCH_REMUW, MASK_REMUW)
7729+DECLARE_INSN(remw, MATCH_REMW, MASK_REMW)
7730+DECLARE_INSN(sb, MATCH_SB, MASK_SB)
7731+DECLARE_INSN(sbreak, MATCH_SBREAK, MASK_SBREAK)
7732+DECLARE_INSN(sc_d, MATCH_SC_D, MASK_SC_D)
7733+DECLARE_INSN(sc_w, MATCH_SC_W, MASK_SC_W)
7734+DECLARE_INSN(scall, MATCH_SCALL, MASK_SCALL)
7735+DECLARE_INSN(sd, MATCH_SD, MASK_SD)
7736+DECLARE_INSN(sfence_vm, MATCH_SFENCE_VM, MASK_SFENCE_VM)
7737+DECLARE_INSN(sh, MATCH_SH, MASK_SH)
7738+DECLARE_INSN(sll, MATCH_SLL, MASK_SLL)
7739+DECLARE_INSN(slli, MATCH_SLLI, MASK_SLLI)
7740+DECLARE_INSN(slli_rv32, MATCH_SLLI_RV32, MASK_SLLI_RV32)
7741+DECLARE_INSN(slliw, MATCH_SLLIW, MASK_SLLIW)
7742+DECLARE_INSN(sllw, MATCH_SLLW, MASK_SLLW)
7743+DECLARE_INSN(slt, MATCH_SLT, MASK_SLT)
7744+DECLARE_INSN(slti, MATCH_SLTI, MASK_SLTI)
7745+DECLARE_INSN(sltiu, MATCH_SLTIU, MASK_SLTIU)
7746+DECLARE_INSN(sltu, MATCH_SLTU, MASK_SLTU)
7747+DECLARE_INSN(sra, MATCH_SRA, MASK_SRA)
7748+DECLARE_INSN(srai, MATCH_SRAI, MASK_SRAI)
7749+DECLARE_INSN(srai_rv32, MATCH_SRAI_RV32, MASK_SRAI_RV32)
7750+DECLARE_INSN(sraiw, MATCH_SRAIW, MASK_SRAIW)
7751+DECLARE_INSN(sraw, MATCH_SRAW, MASK_SRAW)
7752+DECLARE_INSN(sret, MATCH_SRET, MASK_SRET)
7753+DECLARE_INSN(srl, MATCH_SRL, MASK_SRL)
7754+DECLARE_INSN(srli, MATCH_SRLI, MASK_SRLI)
7755+DECLARE_INSN(srli_rv32, MATCH_SRLI_RV32, MASK_SRLI_RV32)
7756+DECLARE_INSN(srliw, MATCH_SRLIW, MASK_SRLIW)
7757+DECLARE_INSN(srlw, MATCH_SRLW, MASK_SRLW)
7758+DECLARE_INSN(stop, MATCH_STOP, MASK_STOP)
7759+DECLARE_INSN(sub, MATCH_SUB, MASK_SUB)
7760+DECLARE_INSN(subw, MATCH_SUBW, MASK_SUBW)
7761+DECLARE_INSN(sw, MATCH_SW, MASK_SW)
7762+DECLARE_INSN(utidx, MATCH_UTIDX, MASK_UTIDX)
7763+DECLARE_INSN(venqcmd, MATCH_VENQCMD, MASK_VENQCMD)
7764+DECLARE_INSN(venqcnt, MATCH_VENQCNT, MASK_VENQCNT)
7765+DECLARE_INSN(venqimm1, MATCH_VENQIMM1, MASK_VENQIMM1)
7766+DECLARE_INSN(venqimm2, MATCH_VENQIMM2, MASK_VENQIMM2)
7767+DECLARE_INSN(vf, MATCH_VF, MASK_VF)
7768+DECLARE_INSN(vfld, MATCH_VFLD, MASK_VFLD)
7769+DECLARE_INSN(vflsegd, MATCH_VFLSEGD, MASK_VFLSEGD)
7770+DECLARE_INSN(vflsegstd, MATCH_VFLSEGSTD, MASK_VFLSEGSTD)
7771+DECLARE_INSN(vflsegstw, MATCH_VFLSEGSTW, MASK_VFLSEGSTW)
7772+DECLARE_INSN(vflsegw, MATCH_VFLSEGW, MASK_VFLSEGW)
7773+DECLARE_INSN(vflstd, MATCH_VFLSTD, MASK_VFLSTD)
7774+DECLARE_INSN(vflstw, MATCH_VFLSTW, MASK_VFLSTW)
7775+DECLARE_INSN(vflw, MATCH_VFLW, MASK_VFLW)
7776+DECLARE_INSN(vfmsv_d, MATCH_VFMSV_D, MASK_VFMSV_D)
7777+DECLARE_INSN(vfmsv_s, MATCH_VFMSV_S, MASK_VFMSV_S)
7778+DECLARE_INSN(vfmvv, MATCH_VFMVV, MASK_VFMVV)
7779+DECLARE_INSN(vfsd, MATCH_VFSD, MASK_VFSD)
7780+DECLARE_INSN(vfssegd, MATCH_VFSSEGD, MASK_VFSSEGD)
7781+DECLARE_INSN(vfssegstd, MATCH_VFSSEGSTD, MASK_VFSSEGSTD)
7782+DECLARE_INSN(vfssegstw, MATCH_VFSSEGSTW, MASK_VFSSEGSTW)
7783+DECLARE_INSN(vfssegw, MATCH_VFSSEGW, MASK_VFSSEGW)
7784+DECLARE_INSN(vfsstd, MATCH_VFSSTD, MASK_VFSSTD)
7785+DECLARE_INSN(vfsstw, MATCH_VFSSTW, MASK_VFSSTW)
7786+DECLARE_INSN(vfsw, MATCH_VFSW, MASK_VFSW)
7787+DECLARE_INSN(vgetcfg, MATCH_VGETCFG, MASK_VGETCFG)
7788+DECLARE_INSN(vgetvl, MATCH_VGETVL, MASK_VGETVL)
7789+DECLARE_INSN(vlb, MATCH_VLB, MASK_VLB)
7790+DECLARE_INSN(vlbu, MATCH_VLBU, MASK_VLBU)
7791+DECLARE_INSN(vld, MATCH_VLD, MASK_VLD)
7792+DECLARE_INSN(vlh, MATCH_VLH, MASK_VLH)
7793+DECLARE_INSN(vlhu, MATCH_VLHU, MASK_VLHU)
7794+DECLARE_INSN(vlsegb, MATCH_VLSEGB, MASK_VLSEGB)
7795+DECLARE_INSN(vlsegbu, MATCH_VLSEGBU, MASK_VLSEGBU)
7796+DECLARE_INSN(vlsegd, MATCH_VLSEGD, MASK_VLSEGD)
7797+DECLARE_INSN(vlsegh, MATCH_VLSEGH, MASK_VLSEGH)
7798+DECLARE_INSN(vlseghu, MATCH_VLSEGHU, MASK_VLSEGHU)
7799+DECLARE_INSN(vlsegstb, MATCH_VLSEGSTB, MASK_VLSEGSTB)
7800+DECLARE_INSN(vlsegstbu, MATCH_VLSEGSTBU, MASK_VLSEGSTBU)
7801+DECLARE_INSN(vlsegstd, MATCH_VLSEGSTD, MASK_VLSEGSTD)
7802+DECLARE_INSN(vlsegsth, MATCH_VLSEGSTH, MASK_VLSEGSTH)
7803+DECLARE_INSN(vlsegsthu, MATCH_VLSEGSTHU, MASK_VLSEGSTHU)
7804+DECLARE_INSN(vlsegstw, MATCH_VLSEGSTW, MASK_VLSEGSTW)
7805+DECLARE_INSN(vlsegstwu, MATCH_VLSEGSTWU, MASK_VLSEGSTWU)
7806+DECLARE_INSN(vlsegw, MATCH_VLSEGW, MASK_VLSEGW)
7807+DECLARE_INSN(vlsegwu, MATCH_VLSEGWU, MASK_VLSEGWU)
7808+DECLARE_INSN(vlstb, MATCH_VLSTB, MASK_VLSTB)
7809+DECLARE_INSN(vlstbu, MATCH_VLSTBU, MASK_VLSTBU)
7810+DECLARE_INSN(vlstd, MATCH_VLSTD, MASK_VLSTD)
7811+DECLARE_INSN(vlsth, MATCH_VLSTH, MASK_VLSTH)
7812+DECLARE_INSN(vlsthu, MATCH_VLSTHU, MASK_VLSTHU)
7813+DECLARE_INSN(vlstw, MATCH_VLSTW, MASK_VLSTW)
7814+DECLARE_INSN(vlstwu, MATCH_VLSTWU, MASK_VLSTWU)
7815+DECLARE_INSN(vlw, MATCH_VLW, MASK_VLW)
7816+DECLARE_INSN(vlwu, MATCH_VLWU, MASK_VLWU)
7817+DECLARE_INSN(vmsv, MATCH_VMSV, MASK_VMSV)
7818+DECLARE_INSN(vmvv, MATCH_VMVV, MASK_VMVV)
7819+DECLARE_INSN(vsb, MATCH_VSB, MASK_VSB)
7820+DECLARE_INSN(vsd, MATCH_VSD, MASK_VSD)
7821+DECLARE_INSN(vsetcfg, MATCH_VSETCFG, MASK_VSETCFG)
7822+DECLARE_INSN(vsetvl, MATCH_VSETVL, MASK_VSETVL)
7823+DECLARE_INSN(vsh, MATCH_VSH, MASK_VSH)
7824+DECLARE_INSN(vssegb, MATCH_VSSEGB, MASK_VSSEGB)
7825+DECLARE_INSN(vssegd, MATCH_VSSEGD, MASK_VSSEGD)
7826+DECLARE_INSN(vssegh, MATCH_VSSEGH, MASK_VSSEGH)
7827+DECLARE_INSN(vssegstb, MATCH_VSSEGSTB, MASK_VSSEGSTB)
7828+DECLARE_INSN(vssegstd, MATCH_VSSEGSTD, MASK_VSSEGSTD)
7829+DECLARE_INSN(vssegsth, MATCH_VSSEGSTH, MASK_VSSEGSTH)
7830+DECLARE_INSN(vssegstw, MATCH_VSSEGSTW, MASK_VSSEGSTW)
7831+DECLARE_INSN(vssegw, MATCH_VSSEGW, MASK_VSSEGW)
7832+DECLARE_INSN(vsstb, MATCH_VSSTB, MASK_VSSTB)
7833+DECLARE_INSN(vsstd, MATCH_VSSTD, MASK_VSSTD)
7834+DECLARE_INSN(vssth, MATCH_VSSTH, MASK_VSSTH)
7835+DECLARE_INSN(vsstw, MATCH_VSSTW, MASK_VSSTW)
7836+DECLARE_INSN(vsw, MATCH_VSW, MASK_VSW)
7837+DECLARE_INSN(vxcptaux, MATCH_VXCPTAUX, MASK_VXCPTAUX)
7838+DECLARE_INSN(vxcptcause, MATCH_VXCPTCAUSE, MASK_VXCPTCAUSE)
7839+DECLARE_INSN(vxcptevac, MATCH_VXCPTEVAC, MASK_VXCPTEVAC)
7840+DECLARE_INSN(vxcpthold, MATCH_VXCPTHOLD, MASK_VXCPTHOLD)
7841+DECLARE_INSN(vxcptkill, MATCH_VXCPTKILL, MASK_VXCPTKILL)
7842+DECLARE_INSN(vxcptrestore, MATCH_VXCPTRESTORE, MASK_VXCPTRESTORE)
7843+DECLARE_INSN(vxcptsave, MATCH_VXCPTSAVE, MASK_VXCPTSAVE)
7844+DECLARE_INSN(wfi, MATCH_WFI, MASK_WFI)
7845+DECLARE_INSN(xor, MATCH_XOR, MASK_XOR)
7846+DECLARE_INSN(xori, MATCH_XORI, MASK_XORI)
7847+#endif
7848+#ifdef DECLARE_CSR
7849+DECLARE_CSR(fflags, CSR_FFLAGS)
7850+DECLARE_CSR(frm, CSR_FRM)
7851+DECLARE_CSR(fcsr, CSR_FCSR)
7852+DECLARE_CSR(cycle, CSR_CYCLE)
7853+DECLARE_CSR(time, CSR_TIME)
7854+DECLARE_CSR(instret, CSR_INSTRET)
7855+DECLARE_CSR(stats, CSR_STATS)
7856+DECLARE_CSR(uarch0, CSR_UARCH0)
7857+DECLARE_CSR(uarch1, CSR_UARCH1)
7858+DECLARE_CSR(uarch2, CSR_UARCH2)
7859+DECLARE_CSR(uarch3, CSR_UARCH3)
7860+DECLARE_CSR(uarch4, CSR_UARCH4)
7861+DECLARE_CSR(uarch5, CSR_UARCH5)
7862+DECLARE_CSR(uarch6, CSR_UARCH6)
7863+DECLARE_CSR(uarch7, CSR_UARCH7)
7864+DECLARE_CSR(uarch8, CSR_UARCH8)
7865+DECLARE_CSR(uarch9, CSR_UARCH9)
7866+DECLARE_CSR(uarch10, CSR_UARCH10)
7867+DECLARE_CSR(uarch11, CSR_UARCH11)
7868+DECLARE_CSR(uarch12, CSR_UARCH12)
7869+DECLARE_CSR(uarch13, CSR_UARCH13)
7870+DECLARE_CSR(uarch14, CSR_UARCH14)
7871+DECLARE_CSR(uarch15, CSR_UARCH15)
7872+DECLARE_CSR(sstatus, CSR_SSTATUS)
7873+DECLARE_CSR(stvec, CSR_STVEC)
7874+DECLARE_CSR(sie, CSR_SIE)
7875+DECLARE_CSR(sscratch, CSR_SSCRATCH)
7876+DECLARE_CSR(sepc, CSR_SEPC)
7877+DECLARE_CSR(sip, CSR_SIP)
7878+DECLARE_CSR(sptbr, CSR_SPTBR)
7879+DECLARE_CSR(sasid, CSR_SASID)
7880+DECLARE_CSR(cyclew, CSR_CYCLEW)
7881+DECLARE_CSR(timew, CSR_TIMEW)
7882+DECLARE_CSR(instretw, CSR_INSTRETW)
7883+DECLARE_CSR(stime, CSR_STIME)
7884+DECLARE_CSR(scause, CSR_SCAUSE)
7885+DECLARE_CSR(sbadaddr, CSR_SBADADDR)
7886+DECLARE_CSR(stimew, CSR_STIMEW)
7887+DECLARE_CSR(mstatus, CSR_MSTATUS)
7888+DECLARE_CSR(mtvec, CSR_MTVEC)
7889+DECLARE_CSR(mtdeleg, CSR_MTDELEG)
7890+DECLARE_CSR(mie, CSR_MIE)
7891+DECLARE_CSR(mtimecmp, CSR_MTIMECMP)
7892+DECLARE_CSR(mscratch, CSR_MSCRATCH)
7893+DECLARE_CSR(mepc, CSR_MEPC)
7894+DECLARE_CSR(mcause, CSR_MCAUSE)
7895+DECLARE_CSR(mbadaddr, CSR_MBADADDR)
7896+DECLARE_CSR(mip, CSR_MIP)
7897+DECLARE_CSR(mtime, CSR_MTIME)
7898+DECLARE_CSR(mcpuid, CSR_MCPUID)
7899+DECLARE_CSR(mimpid, CSR_MIMPID)
7900+DECLARE_CSR(mhartid, CSR_MHARTID)
7901+DECLARE_CSR(mtohost, CSR_MTOHOST)
7902+DECLARE_CSR(mfromhost, CSR_MFROMHOST)
7903+DECLARE_CSR(mreset, CSR_MRESET)
7904+DECLARE_CSR(send_ipi, CSR_SEND_IPI)
7905+DECLARE_CSR(cycleh, CSR_CYCLEH)
7906+DECLARE_CSR(timeh, CSR_TIMEH)
7907+DECLARE_CSR(instreth, CSR_INSTRETH)
7908+DECLARE_CSR(cyclehw, CSR_CYCLEHW)
7909+DECLARE_CSR(timehw, CSR_TIMEHW)
7910+DECLARE_CSR(instrethw, CSR_INSTRETHW)
7911+DECLARE_CSR(stimeh, CSR_STIMEH)
7912+DECLARE_CSR(stimehw, CSR_STIMEHW)
7913+DECLARE_CSR(mtimecmph, CSR_MTIMECMPH)
7914+DECLARE_CSR(mtimeh, CSR_MTIMEH)
7915+#endif
7916+#ifdef DECLARE_CAUSE
7917+DECLARE_CAUSE("fflags", CAUSE_FFLAGS)
7918+DECLARE_CAUSE("frm", CAUSE_FRM)
7919+DECLARE_CAUSE("fcsr", CAUSE_FCSR)
7920+DECLARE_CAUSE("cycle", CAUSE_CYCLE)
7921+DECLARE_CAUSE("time", CAUSE_TIME)
7922+DECLARE_CAUSE("instret", CAUSE_INSTRET)
7923+DECLARE_CAUSE("stats", CAUSE_STATS)
7924+DECLARE_CAUSE("uarch0", CAUSE_UARCH0)
7925+DECLARE_CAUSE("uarch1", CAUSE_UARCH1)
7926+DECLARE_CAUSE("uarch2", CAUSE_UARCH2)
7927+DECLARE_CAUSE("uarch3", CAUSE_UARCH3)
7928+DECLARE_CAUSE("uarch4", CAUSE_UARCH4)
7929+DECLARE_CAUSE("uarch5", CAUSE_UARCH5)
7930+DECLARE_CAUSE("uarch6", CAUSE_UARCH6)
7931+DECLARE_CAUSE("uarch7", CAUSE_UARCH7)
7932+DECLARE_CAUSE("uarch8", CAUSE_UARCH8)
7933+DECLARE_CAUSE("uarch9", CAUSE_UARCH9)
7934+DECLARE_CAUSE("uarch10", CAUSE_UARCH10)
7935+DECLARE_CAUSE("uarch11", CAUSE_UARCH11)
7936+DECLARE_CAUSE("uarch12", CAUSE_UARCH12)
7937+DECLARE_CAUSE("uarch13", CAUSE_UARCH13)
7938+DECLARE_CAUSE("uarch14", CAUSE_UARCH14)
7939+DECLARE_CAUSE("uarch15", CAUSE_UARCH15)
7940+DECLARE_CAUSE("sstatus", CAUSE_SSTATUS)
7941+DECLARE_CAUSE("stvec", CAUSE_STVEC)
7942+DECLARE_CAUSE("sie", CAUSE_SIE)
7943+DECLARE_CAUSE("sscratch", CAUSE_SSCRATCH)
7944+DECLARE_CAUSE("sepc", CAUSE_SEPC)
7945+DECLARE_CAUSE("sip", CAUSE_SIP)
7946+DECLARE_CAUSE("sptbr", CAUSE_SPTBR)
7947+DECLARE_CAUSE("sasid", CAUSE_SASID)
7948+DECLARE_CAUSE("cyclew", CAUSE_CYCLEW)
7949+DECLARE_CAUSE("timew", CAUSE_TIMEW)
7950+DECLARE_CAUSE("instretw", CAUSE_INSTRETW)
7951+DECLARE_CAUSE("stime", CAUSE_STIME)
7952+DECLARE_CAUSE("scause", CAUSE_SCAUSE)
7953+DECLARE_CAUSE("sbadaddr", CAUSE_SBADADDR)
7954+DECLARE_CAUSE("stimew", CAUSE_STIMEW)
7955+DECLARE_CAUSE("mstatus", CAUSE_MSTATUS)
7956+DECLARE_CAUSE("mtvec", CAUSE_MTVEC)
7957+DECLARE_CAUSE("mtdeleg", CAUSE_MTDELEG)
7958+DECLARE_CAUSE("mie", CAUSE_MIE)
7959+DECLARE_CAUSE("mtimecmp", CAUSE_MTIMECMP)
7960+DECLARE_CAUSE("mscratch", CAUSE_MSCRATCH)
7961+DECLARE_CAUSE("mepc", CAUSE_MEPC)
7962+DECLARE_CAUSE("mcause", CAUSE_MCAUSE)
7963+DECLARE_CAUSE("mbadaddr", CAUSE_MBADADDR)
7964+DECLARE_CAUSE("mip", CAUSE_MIP)
7965+DECLARE_CAUSE("mtime", CAUSE_MTIME)
7966+DECLARE_CAUSE("mcpuid", CAUSE_MCPUID)
7967+DECLARE_CAUSE("mimpid", CAUSE_MIMPID)
7968+DECLARE_CAUSE("mhartid", CAUSE_MHARTID)
7969+DECLARE_CAUSE("mtohost", CAUSE_MTOHOST)
7970+DECLARE_CAUSE("mfromhost", CAUSE_MFROMHOST)
7971+DECLARE_CAUSE("mreset", CAUSE_MRESET)
7972+DECLARE_CAUSE("send_ipi", CAUSE_SEND_IPI)
7973+DECLARE_CAUSE("cycleh", CAUSE_CYCLEH)
7974+DECLARE_CAUSE("timeh", CAUSE_TIMEH)
7975+DECLARE_CAUSE("instreth", CAUSE_INSTRETH)
7976+DECLARE_CAUSE("cyclehw", CAUSE_CYCLEHW)
7977+DECLARE_CAUSE("timehw", CAUSE_TIMEHW)
7978+DECLARE_CAUSE("instrethw", CAUSE_INSTRETHW)
7979+DECLARE_CAUSE("stimeh", CAUSE_STIMEH)
7980+DECLARE_CAUSE("stimehw", CAUSE_STIMEHW)
7981+DECLARE_CAUSE("mtimecmph", CAUSE_MTIMECMPH)
7982+DECLARE_CAUSE("mtimeh", CAUSE_MTIMEH)
7983+#endif
7984diff -urN empty/include/opcode/riscv.h binutils-2.25/include/opcode/riscv.h
Jonathan A. Kollasch64fc4332015-08-25 13:09:51 -05007985--- binutils-2.25/include/opcode/riscv.h 1970-01-01 01:00:00.000000000 +0100
Patrick Georgiaf473ed2015-07-17 23:35:54 +02007986+++ binutils-2.25/include/opcode/riscv.h 2015-07-18 00:02:36.222287541 +0200
7987@@ -0,0 +1,366 @@
Patrick Georgif0bbc952015-03-07 10:57:25 +01007988+/* riscv.h. RISC-V opcode list for GDB, the GNU debugger.
7989+ Copyright 2011
7990+ Free Software Foundation, Inc.
7991+ Contributed by Andrew Waterman
7992+
7993+This file is part of GDB, GAS, and the GNU binutils.
7994+
7995+GDB, GAS, and the GNU binutils are free software; you can redistribute
7996+them and/or modify them under the terms of the GNU General Public
7997+License as published by the Free Software Foundation; either version
7998+1, or (at your option) any later version.
7999+
8000+GDB, GAS, and the GNU binutils are distributed in the hope that they
8001+will be useful, but WITHOUT ANY WARRANTY; without even the implied
8002+warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
8003+the GNU General Public License for more details.
8004+
8005+You should have received a copy of the GNU General Public License
8006+along with this file; see the file COPYING. If not, write to the Free
8007+Software Foundation, 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. */
8008+
8009+#ifndef _RISCV_H_
8010+#define _RISCV_H_
8011+
8012+#include "riscv-opc.h"
8013+#include <stdlib.h>
8014+#include <stdint.h>
8015+
8016+/* RVC fields */
8017+
Patrick Georgiaf473ed2015-07-17 23:35:54 +02008018+#define OP_MASK_CRS2 0x1f
8019+#define OP_SH_CRS2 2
8020+#define OP_MASK_CRS1S 0x7
8021+#define OP_SH_CRS1S 7
8022+#define OP_MASK_CRS2S 0x7
8023+#define OP_SH_CRS2S 2
8024+#define OP_MASK_CRDS 0x7
8025+#define OP_SH_CRDS 10
Patrick Georgif0bbc952015-03-07 10:57:25 +01008026+
8027+static const char rvc_rs1_regmap[8] = { 20, 21, 2, 3, 4, 5, 6, 7 };
8028+#define rvc_rd_regmap rvc_rs1_regmap
8029+#define rvc_rs2b_regmap rvc_rs1_regmap
8030+static const char rvc_rs2_regmap[8] = { 20, 21, 2, 3, 4, 5, 6, 0 };
8031+
8032+typedef uint64_t insn_t;
8033+
8034+static inline unsigned int riscv_insn_length (insn_t insn)
8035+{
8036+ if ((insn & 0x3) != 3) /* RVC */
8037+ return 2;
8038+ if ((insn & 0x1f) != 0x1f) /* base ISA and extensions in 32-bit space */
8039+ return 4;
8040+ if ((insn & 0x3f) == 0x1f) /* 48-bit extensions */
8041+ return 6;
8042+ if ((insn & 0x7f) == 0x3f) /* 64-bit extensions */
8043+ return 8;
8044+ /* longer instructions not supported at the moment */
8045+ return 2;
8046+}
8047+
8048+static const char * const riscv_rm[8] = {
8049+ "rne", "rtz", "rdn", "rup", "rmm", 0, 0, "dyn"
8050+};
8051+static const char* const riscv_pred_succ[16] = {
8052+ 0, "w", "r", "rw", "o", "ow", "or", "orw",
8053+ "i", "iw", "ir", "irw", "io", "iow", "ior", "iorw",
8054+};
8055+
Patrick Georgiaf473ed2015-07-17 23:35:54 +02008056+#define RVC_JUMP_BITS 11
8057+#define RVC_JUMP_REACH ((1ULL<<RVC_JUMP_BITS)*RISCV_JUMP_ALIGN)
Patrick Georgif0bbc952015-03-07 10:57:25 +01008058+
Patrick Georgiaf473ed2015-07-17 23:35:54 +02008059+#define RVC_BRANCH_BITS 8
8060+#define RVC_BRANCH_REACH ((1ULL<<RVC_BRANCH_BITS)*RISCV_BRANCH_ALIGN)
Patrick Georgif0bbc952015-03-07 10:57:25 +01008061+
8062+#define RV_X(x, s, n) (((x) >> (s)) & ((1<<(n))-1))
8063+#define RV_IMM_SIGN(x) (-(((x) >> 31) & 1))
8064+
8065+#define EXTRACT_ITYPE_IMM(x) \
8066+ (RV_X(x, 20, 12) | (RV_IMM_SIGN(x) << 12))
8067+#define EXTRACT_STYPE_IMM(x) \
8068+ (RV_X(x, 7, 5) | (RV_X(x, 25, 7) << 5) | (RV_IMM_SIGN(x) << 12))
8069+#define EXTRACT_SBTYPE_IMM(x) \
8070+ ((RV_X(x, 8, 4) << 1) | (RV_X(x, 25, 6) << 5) | (RV_X(x, 7, 1) << 11) | (RV_IMM_SIGN(x) << 12))
8071+#define EXTRACT_UTYPE_IMM(x) \
8072+ ((RV_X(x, 12, 20) << 12) | (RV_IMM_SIGN(x) << 32))
8073+#define EXTRACT_UJTYPE_IMM(x) \
8074+ ((RV_X(x, 21, 10) << 1) | (RV_X(x, 20, 1) << 11) | (RV_X(x, 12, 8) << 12) | (RV_IMM_SIGN(x) << 20))
Patrick Georgiaf473ed2015-07-17 23:35:54 +02008075+#define EXTRACT_RVC_IMM(x) \
8076+ (RV_X(x, 2, 5) | (-RV_X(x, 12, 1) << 5))
8077+#define EXTRACT_RVC_SIMM3(x) \
8078+ (RV_X(x, 10, 2) | (-RV_X(x, 12, 1) << 2))
8079+#define EXTRACT_RVC_ADDI4SPN_IMM(x) \
8080+ ((RV_X(x, 6, 1) << 2) | (RV_X(x, 5, 1) << 3) | (RV_X(x, 11, 2) << 4) | (RV_X(x, 7, 4) << 6))
8081+#define EXTRACT_RVC_ADDI16SP_IMM(x) \
8082+ ((RV_X(x, 6, 1) << 4) | (RV_X(x, 5, 1) << 5) | (RV_X(x, 2, 3) << 6) | (-RV_X(x, 12, 1) << 9))
8083+#define EXTRACT_RVC_LW_IMM(x) \
8084+ ((RV_X(x, 6, 1) << 2) | (RV_X(x, 10, 3) << 3) | (RV_X(x, 5, 1) << 6))
8085+#define EXTRACT_RVC_LD_IMM(x) \
8086+ ((RV_X(x, 10, 3) << 3) | (RV_X(x, 5, 2) << 6))
8087+#define EXTRACT_RVC_LWSP_IMM(x) \
8088+ ((RV_X(x, 4, 3) << 2) | (RV_X(x, 12, 1) << 5) | (RV_X(x, 2, 2) << 6))
8089+#define EXTRACT_RVC_LDSP_IMM(x) \
8090+ ((RV_X(x, 5, 2) << 3) | (RV_X(x, 12, 1) << 5) | (RV_X(x, 2, 3) << 6))
8091+#define EXTRACT_RVC_SWSP_IMM(x) \
8092+ ((RV_X(x, 9, 4) << 2) | (RV_X(x, 7, 2) << 6))
8093+#define EXTRACT_RVC_SDSP_IMM(x) \
8094+ ((RV_X(x, 10, 3) << 3) | (RV_X(x, 7, 3) << 6))
8095+#define EXTRACT_RVC_B_IMM(x) \
8096+ ((RV_X(x, 3, 4) << 1) | (RV_X(x, 2, 1) << 5) | (RV_X(x, 10, 2) << 6) | (-RV_X(x, 12, 1) << 8))
8097+#define EXTRACT_RVC_J_IMM(x) \
8098+ ((RV_X(x, 3, 4) << 1) | (RV_X(x, 2, 1) << 5) | (RV_X(x, 7, 5) << 6) | (-RV_X(x, 12, 1) << 11))
Patrick Georgif0bbc952015-03-07 10:57:25 +01008099+
8100+#define ENCODE_ITYPE_IMM(x) \
8101+ (RV_X(x, 0, 12) << 20)
8102+#define ENCODE_STYPE_IMM(x) \
8103+ ((RV_X(x, 0, 5) << 7) | (RV_X(x, 5, 7) << 25))
8104+#define ENCODE_SBTYPE_IMM(x) \
8105+ ((RV_X(x, 1, 4) << 8) | (RV_X(x, 5, 6) << 25) | (RV_X(x, 11, 1) << 7) | (RV_X(x, 12, 1) << 31))
8106+#define ENCODE_UTYPE_IMM(x) \
8107+ (RV_X(x, 12, 20) << 12)
8108+#define ENCODE_UJTYPE_IMM(x) \
8109+ ((RV_X(x, 1, 10) << 21) | (RV_X(x, 11, 1) << 20) | (RV_X(x, 12, 8) << 12) | (RV_X(x, 20, 1) << 31))
Patrick Georgiaf473ed2015-07-17 23:35:54 +02008110+#define ENCODE_RVC_IMM(x) \
8111+ ((RV_X(x, 0, 5) << 2) | (RV_X(x, 5, 1) << 12))
8112+#define ENCODE_RVC_SIMM3(x) \
8113+ (RV_X(x, 0, 3) << 10)
8114+#define ENCODE_RVC_ADDI4SPN_IMM(x) \
8115+ ((RV_X(x, 2, 1) << 6) | (RV_X(x, 3, 1) << 5) | (RV_X(x, 4, 2) << 11) | (RV_X(x, 6, 4) << 7))
8116+#define ENCODE_RVC_ADDI16SP_IMM(x) \
8117+ ((RV_X(x, 4, 1) << 6) | (RV_X(x, 5, 1) << 5) | (RV_X(x, 6, 3) << 2) | (RV_X(x, 9, 1) << 12))
8118+#define ENCODE_RVC_LW_IMM(x) \
8119+ ((RV_X(x, 2, 1) << 6) | (RV_X(x, 3, 3) << 10) | (RV_X(x, 6, 1) << 5))
8120+#define ENCODE_RVC_LD_IMM(x) \
8121+ ((RV_X(x, 3, 3) << 10) | (RV_X(x, 6, 2) << 5))
8122+#define ENCODE_RVC_LWSP_IMM(x) \
8123+ ((RV_X(x, 2, 3) << 4) | (RV_X(x, 5, 1) << 12) | (RV_X(x, 6, 2) << 2))
8124+#define ENCODE_RVC_LDSP_IMM(x) \
8125+ ((RV_X(x, 3, 2) << 5) | (RV_X(x, 5, 1) << 12) | (RV_X(x, 6, 3) << 2))
8126+#define ENCODE_RVC_SWSP_IMM(x) \
8127+ ((RV_X(x, 2, 4) << 9) | (RV_X(x, 6, 2) << 7))
8128+#define ENCODE_RVC_SDSP_IMM(x) \
8129+ ((RV_X(x, 3, 3) << 10) | (RV_X(x, 6, 3) << 7))
8130+#define ENCODE_RVC_B_IMM(x) \
8131+ ((RV_X(x, 1, 4) << 3) | (RV_X(x, 5, 1) << 2) | (RV_X(x, 6, 3) << 10))
8132+#define ENCODE_RVC_J_IMM(x) \
8133+ ((RV_X(x, 1, 4) << 3) | (RV_X(x, 5, 1) << 2) | (RV_X(x, 6, 6) << 7))
Patrick Georgif0bbc952015-03-07 10:57:25 +01008134+
8135+#define VALID_ITYPE_IMM(x) (EXTRACT_ITYPE_IMM(ENCODE_ITYPE_IMM(x)) == (x))
8136+#define VALID_STYPE_IMM(x) (EXTRACT_STYPE_IMM(ENCODE_STYPE_IMM(x)) == (x))
8137+#define VALID_SBTYPE_IMM(x) (EXTRACT_SBTYPE_IMM(ENCODE_SBTYPE_IMM(x)) == (x))
8138+#define VALID_UTYPE_IMM(x) (EXTRACT_UTYPE_IMM(ENCODE_UTYPE_IMM(x)) == (x))
8139+#define VALID_UJTYPE_IMM(x) (EXTRACT_UJTYPE_IMM(ENCODE_UJTYPE_IMM(x)) == (x))
Patrick Georgiaf473ed2015-07-17 23:35:54 +02008140+#define VALID_RVC_IMM(x) (EXTRACT_RVC_IMM(ENCODE_RVC_IMM(x)) == (x))
8141+#define VALID_RVC_SIMM3(x) (EXTRACT_RVC_SIMM3(ENCODE_RVC_SIMM3(x)) == (x))
8142+#define VALID_RVC_ADDI4SPN_IMM(x) (EXTRACT_RVC_ADDI4SPN_IMM(ENCODE_RVC_ADDI4SPN_IMM(x)) == (x))
8143+#define VALID_RVC_ADDI16SP_IMM(x) (EXTRACT_RVC_ADDI16SP_IMM(ENCODE_RVC_ADDI16SP_IMM(x)) == (x))
8144+#define VALID_RVC_LW_IMM(x) (EXTRACT_RVC_LW_IMM(ENCODE_RVC_LW_IMM(x)) == (x))
8145+#define VALID_RVC_LD_IMM(x) (EXTRACT_RVC_LD_IMM(ENCODE_RVC_LD_IMM(x)) == (x))
8146+#define VALID_RVC_LWSP_IMM(x) (EXTRACT_RVC_LWSP_IMM(ENCODE_RVC_LWSP_IMM(x)) == (x))
8147+#define VALID_RVC_LDSP_IMM(x) (EXTRACT_RVC_LDSP_IMM(ENCODE_RVC_LDSP_IMM(x)) == (x))
8148+#define VALID_RVC_SWSP_IMM(x) (EXTRACT_RVC_SWSP_IMM(ENCODE_RVC_SWSP_IMM(x)) == (x))
8149+#define VALID_RVC_SDSP_IMM(x) (EXTRACT_RVC_SDSP_IMM(ENCODE_RVC_SDSP_IMM(x)) == (x))
8150+#define VALID_RVC_B_IMM(x) (EXTRACT_RVC_B_IMM(ENCODE_RVC_B_IMM(x)) == (x))
8151+#define VALID_RVC_J_IMM(x) (EXTRACT_RVC_J_IMM(ENCODE_RVC_J_IMM(x)) == (x))
Patrick Georgif0bbc952015-03-07 10:57:25 +01008152+
8153+#define RISCV_RTYPE(insn, rd, rs1, rs2) \
8154+ ((MATCH_ ## insn) | ((rd) << OP_SH_RD) | ((rs1) << OP_SH_RS1) | ((rs2) << OP_SH_RS2))
8155+#define RISCV_ITYPE(insn, rd, rs1, imm) \
8156+ ((MATCH_ ## insn) | ((rd) << OP_SH_RD) | ((rs1) << OP_SH_RS1) | ENCODE_ITYPE_IMM(imm))
8157+#define RISCV_STYPE(insn, rs1, rs2, imm) \
8158+ ((MATCH_ ## insn) | ((rs1) << OP_SH_RS1) | ((rs2) << OP_SH_RS2) | ENCODE_STYPE_IMM(imm))
8159+#define RISCV_SBTYPE(insn, rs1, rs2, target) \
8160+ ((MATCH_ ## insn) | ((rs1) << OP_SH_RS1) | ((rs2) << OP_SH_RS2) | ENCODE_SBTYPE_IMM(target))
8161+#define RISCV_UTYPE(insn, rd, bigimm) \
8162+ ((MATCH_ ## insn) | ((rd) << OP_SH_RD) | ENCODE_UTYPE_IMM(bigimm))
8163+#define RISCV_UJTYPE(insn, rd, target) \
8164+ ((MATCH_ ## insn) | ((rd) << OP_SH_RD) | ENCODE_UJTYPE_IMM(target))
8165+
8166+#define RISCV_NOP RISCV_ITYPE(ADDI, 0, 0, 0)
Patrick Georgiaf473ed2015-07-17 23:35:54 +02008167+#define RVC_NOP MATCH_C_ADDI
Patrick Georgif0bbc952015-03-07 10:57:25 +01008168+
8169+#define RISCV_CONST_HIGH_PART(VALUE) \
8170+ (((VALUE) + (RISCV_IMM_REACH/2)) & ~(RISCV_IMM_REACH-1))
8171+#define RISCV_CONST_LOW_PART(VALUE) ((VALUE) - RISCV_CONST_HIGH_PART (VALUE))
8172+#define RISCV_PCREL_HIGH_PART(VALUE, PC) RISCV_CONST_HIGH_PART((VALUE) - (PC))
8173+#define RISCV_PCREL_LOW_PART(VALUE, PC) RISCV_CONST_LOW_PART((VALUE) - (PC))
8174+
8175+/* RV fields */
8176+
8177+#define OP_MASK_OP 0x7f
8178+#define OP_SH_OP 0
8179+#define OP_MASK_RS2 0x1f
8180+#define OP_SH_RS2 20
8181+#define OP_MASK_RS1 0x1f
8182+#define OP_SH_RS1 15
8183+#define OP_MASK_RS3 0x1f
8184+#define OP_SH_RS3 27
8185+#define OP_MASK_RD 0x1f
8186+#define OP_SH_RD 7
8187+#define OP_MASK_SHAMT 0x3f
8188+#define OP_SH_SHAMT 20
8189+#define OP_MASK_SHAMTW 0x1f
8190+#define OP_SH_SHAMTW 20
8191+#define OP_MASK_RM 0x7
8192+#define OP_SH_RM 12
8193+#define OP_MASK_PRED 0xf
8194+#define OP_SH_PRED 24
8195+#define OP_MASK_SUCC 0xf
8196+#define OP_SH_SUCC 20
8197+#define OP_MASK_AQ 0x1
8198+#define OP_SH_AQ 26
8199+#define OP_MASK_RL 0x1
8200+#define OP_SH_RL 25
8201+
8202+#define OP_MASK_VRD 0x1f
8203+#define OP_SH_VRD 7
8204+#define OP_MASK_VRS 0x1f
8205+#define OP_SH_VRS 15
8206+#define OP_MASK_VRT 0x1f
8207+#define OP_SH_VRT 20
8208+#define OP_MASK_VRR 0x1f
8209+#define OP_SH_VRR 27
8210+
8211+#define OP_MASK_VFD 0x1f
8212+#define OP_SH_VFD 7
8213+#define OP_MASK_VFS 0x1f
8214+#define OP_SH_VFS 15
8215+#define OP_MASK_VFT 0x1f
8216+#define OP_SH_VFT 20
8217+#define OP_MASK_VFR 0x1f
8218+#define OP_SH_VFR 27
8219+
8220+#define OP_MASK_IMMNGPR 0x3f
8221+#define OP_SH_IMMNGPR 20
8222+#define OP_MASK_IMMNFPR 0x3f
8223+#define OP_SH_IMMNFPR 26
8224+#define OP_MASK_IMMSEGNELM 0x7
8225+#define OP_SH_IMMSEGNELM 29
8226+#define OP_MASK_CUSTOM_IMM 0x7f
8227+#define OP_SH_CUSTOM_IMM 25
8228+#define OP_MASK_CSR 0xfff
8229+#define OP_SH_CSR 20
8230+
8231+#define X_RA 1
8232+#define X_SP 2
8233+#define X_GP 3
8234+#define X_TP 4
8235+#define X_T0 5
8236+#define X_T1 6
8237+#define X_T2 7
8238+#define X_T3 28
8239+
8240+#define NGPR 32
8241+#define NFPR 32
8242+#define NVGPR 32
8243+#define NVFPR 32
8244+
8245+#define RISCV_JUMP_BITS RISCV_BIGIMM_BITS
8246+#define RISCV_JUMP_ALIGN_BITS 1
8247+#define RISCV_JUMP_ALIGN (1 << RISCV_JUMP_ALIGN_BITS)
8248+#define RISCV_JUMP_REACH ((1ULL<<RISCV_JUMP_BITS)*RISCV_JUMP_ALIGN)
8249+
8250+#define RISCV_IMM_BITS 12
8251+#define RISCV_BIGIMM_BITS (32-RISCV_IMM_BITS)
8252+#define RISCV_IMM_REACH (1LL<<RISCV_IMM_BITS)
8253+#define RISCV_BIGIMM_REACH (1LL<<RISCV_BIGIMM_BITS)
Patrick Georgiaf473ed2015-07-17 23:35:54 +02008254+#define RISCV_RVC_IMM_REACH (1LL<<6)
Patrick Georgif0bbc952015-03-07 10:57:25 +01008255+#define RISCV_BRANCH_BITS RISCV_IMM_BITS
8256+#define RISCV_BRANCH_ALIGN_BITS RISCV_JUMP_ALIGN_BITS
8257+#define RISCV_BRANCH_ALIGN (1 << RISCV_BRANCH_ALIGN_BITS)
8258+#define RISCV_BRANCH_REACH (RISCV_IMM_REACH*RISCV_BRANCH_ALIGN)
8259+
8260+/* This structure holds information for a particular instruction. */
8261+
8262+struct riscv_opcode
8263+{
8264+ /* The name of the instruction. */
8265+ const char *name;
8266+ /* The ISA subset name (I, M, A, F, D, Xextension). */
8267+ const char *subset;
8268+ /* A string describing the arguments for this instruction. */
8269+ const char *args;
8270+ /* The basic opcode for the instruction. When assembling, this
8271+ opcode is modified by the arguments to produce the actual opcode
8272+ that is used. If pinfo is INSN_MACRO, then this is 0. */
8273+ insn_t match;
8274+ /* If pinfo is not INSN_MACRO, then this is a bit mask for the
8275+ relevant portions of the opcode when disassembling. If the
8276+ actual opcode anded with the match field equals the opcode field,
8277+ then we have found the correct instruction. If pinfo is
8278+ INSN_MACRO, then this field is the macro identifier. */
8279+ insn_t mask;
8280+ /* A function to determine if a word corresponds to this instruction.
8281+ Usually, this computes ((word & mask) == match). */
8282+ int (*match_func)(const struct riscv_opcode *op, insn_t word);
8283+ /* For a macro, this is INSN_MACRO. Otherwise, it is a collection
8284+ of bits describing the instruction, notably any relevant hazard
8285+ information. */
8286+ unsigned long pinfo;
8287+};
8288+
8289+#define INSN_WRITE_GPR_D 0x00000001
8290+#define INSN_WRITE_GPR_RA 0x00000004
8291+#define INSN_WRITE_FPR_D 0x00000008
8292+#define INSN_READ_GPR_S 0x00000040
8293+#define INSN_READ_GPR_T 0x00000080
8294+#define INSN_READ_FPR_S 0x00000100
8295+#define INSN_READ_FPR_T 0x00000200
8296+#define INSN_READ_FPR_R 0x00000400
8297+/* Instruction is a simple alias (I.E. "move" for daddu/addu/or) */
8298+#define INSN_ALIAS 0x00001000
8299+/* Instruction is actually a macro. It should be ignored by the
8300+ disassembler, and requires special treatment by the assembler. */
8301+#define INSN_MACRO 0xffffffff
8302+
8303+/* This is a list of macro expanded instructions.
8304+
8305+ _I appended means immediate
8306+ _A appended means address
8307+ _AB appended means address with base register
8308+ _D appended means 64 bit floating point constant
8309+ _S appended means 32 bit floating point constant. */
8310+
8311+enum
8312+{
8313+ M_LA,
8314+ M_LLA,
8315+ M_LA_TLS_GD,
8316+ M_LA_TLS_IE,
8317+ M_LB,
8318+ M_LBU,
8319+ M_LH,
8320+ M_LHU,
8321+ M_LW,
8322+ M_LWU,
8323+ M_LD,
8324+ M_SB,
8325+ M_SH,
8326+ M_SW,
8327+ M_SD,
8328+ M_FLW,
8329+ M_FLD,
8330+ M_FSW,
8331+ M_FSD,
8332+ M_CALL,
8333+ M_J,
8334+ M_LI,
8335+ M_VF,
8336+ M_NUM_MACROS
8337+};
8338+
8339+
8340+extern const char * const riscv_gpr_names_numeric[NGPR];
8341+extern const char * const riscv_gpr_names_abi[NGPR];
8342+extern const char * const riscv_fpr_names_numeric[NFPR];
8343+extern const char * const riscv_fpr_names_abi[NFPR];
8344+extern const char * const riscv_vec_gpr_names[NVGPR];
8345+extern const char * const riscv_vec_fpr_names[NVFPR];
8346+
8347+extern const struct riscv_opcode riscv_builtin_opcodes[];
8348+extern const int bfd_riscv_num_builtin_opcodes;
8349+extern struct riscv_opcode *riscv_opcodes;
8350+extern int bfd_riscv_num_opcodes;
8351+#define NUMOPCODES bfd_riscv_num_opcodes
8352+
8353+#endif /* _RISCV_H_ */
Patrick Georgiaf473ed2015-07-17 23:35:54 +02008354diff -urN empty/ld/emulparams/elf32lriscv-defs.sh binutils-2.25/ld/emulparams/elf32lriscv-defs.sh
Jonathan A. Kollasch64fc4332015-08-25 13:09:51 -05008355--- binutils-2.25/ld/emulparams/elf32lriscv-defs.sh 1970-01-01 01:00:00.000000000 +0100
Patrick Georgiaf473ed2015-07-17 23:35:54 +02008356+++ binutils-2.25/ld/emulparams/elf32lriscv-defs.sh 2015-07-18 00:02:36.222287541 +0200
Patrick Georgif0bbc952015-03-07 10:57:25 +01008357@@ -0,0 +1,39 @@
8358+# This is an ELF platform.
8359+SCRIPT_NAME=elf
8360+ARCH=riscv
8361+OUTPUT_FORMAT="elf32-littleriscv"
8362+NO_REL_RELOCS=yes
8363+
8364+TEMPLATE_NAME=elf32
8365+EXTRA_EM_FILE=riscvelf
8366+
8367+case "$EMULATION_NAME" in
8368+elf32*) ELFSIZE=32; LIBPATH_SUFFIX=32 ;;
8369+elf64*) ELFSIZE=64; LIBPATH_SUFFIX= ;;
8370+*) echo $0: unhandled emulation $EMULATION_NAME >&2; exit 1 ;;
8371+esac
8372+
8373+if test `echo "$host" | sed -e s/64//` = `echo "$target" | sed -e s/64//`; then
8374+ case " $EMULATION_LIBPATH " in
8375+ *" ${EMULATION_NAME} "*)
8376+ NATIVE=yes
8377+ ;;
8378+ esac
8379+fi
8380+
8381+GENERATE_SHLIB_SCRIPT=yes
8382+GENERATE_PIE_SCRIPT=yes
8383+
8384+TEXT_START_ADDR=0x800000
8385+MAXPAGESIZE="CONSTANT (MAXPAGESIZE)"
8386+COMMONPAGESIZE="CONSTANT (COMMONPAGESIZE)"
8387+
8388+INITIAL_READONLY_SECTIONS=".interp ${RELOCATING-0} : { *(.interp) }"
8389+SDATA_START_SYMBOLS="_gp = . + 0x800;
8390+ *(.srodata.cst16) *(.srodata.cst8) *(.srodata.cst4) *(.srodata.cst2) *(.srodata*)"
8391+if test -n "${CREATE_SHLIB}"; then
8392+ INITIAL_READONLY_SECTIONS=
8393+ SDATA_START_SYMBOLS=
8394+ OTHER_READONLY_SECTIONS=".srodata ${RELOCATING-0} : { *(.srodata.cst16) *(.srodata.cst8) *(.srodata.cst4) *(.srodata.cst2) *(.srodata*) }"
8395+ unset GOT
8396+fi
Patrick Georgiaf473ed2015-07-17 23:35:54 +02008397diff -urN empty/ld/emulparams/elf32lriscv.sh binutils-2.25/ld/emulparams/elf32lriscv.sh
Jonathan A. Kollasch64fc4332015-08-25 13:09:51 -05008398--- binutils-2.25/ld/emulparams/elf32lriscv.sh 1970-01-01 01:00:00.000000000 +0100
Patrick Georgiaf473ed2015-07-17 23:35:54 +02008399+++ binutils-2.25/ld/emulparams/elf32lriscv.sh 2015-07-18 00:02:36.222287541 +0200
Patrick Georgif0bbc952015-03-07 10:57:25 +01008400@@ -0,0 +1,2 @@
8401+. ${srcdir}/emulparams/elf32lriscv-defs.sh
8402+OUTPUT_FORMAT="elf32-littleriscv"
Patrick Georgiaf473ed2015-07-17 23:35:54 +02008403diff -urN empty/ld/emulparams/elf64lriscv-defs.sh binutils-2.25/ld/emulparams/elf64lriscv-defs.sh
Jonathan A. Kollasch64fc4332015-08-25 13:09:51 -05008404--- binutils-2.25/ld/emulparams/elf64lriscv-defs.sh 1970-01-01 01:00:00.000000000 +0100
Patrick Georgiaf473ed2015-07-17 23:35:54 +02008405+++ binutils-2.25/ld/emulparams/elf64lriscv-defs.sh 2015-07-18 00:02:36.222287541 +0200
Patrick Georgif0bbc952015-03-07 10:57:25 +01008406@@ -0,0 +1 @@
8407+. ${srcdir}/emulparams/elf32lriscv-defs.sh
Patrick Georgiaf473ed2015-07-17 23:35:54 +02008408diff -urN empty/ld/emulparams/elf64lriscv.sh binutils-2.25/ld/emulparams/elf64lriscv.sh
Jonathan A. Kollasch64fc4332015-08-25 13:09:51 -05008409--- binutils-2.25/ld/emulparams/elf64lriscv.sh 1970-01-01 01:00:00.000000000 +0100
Patrick Georgiaf473ed2015-07-17 23:35:54 +02008410+++ binutils-2.25/ld/emulparams/elf64lriscv.sh 2015-07-18 00:02:36.222287541 +0200
Patrick Georgif0bbc952015-03-07 10:57:25 +01008411@@ -0,0 +1,2 @@
8412+. ${srcdir}/emulparams/elf64lriscv-defs.sh
8413+OUTPUT_FORMAT="elf64-littleriscv"
Patrick Georgiaf473ed2015-07-17 23:35:54 +02008414diff -urN empty/ld/emultempl/riscvelf.em binutils-2.25/ld/emultempl/riscvelf.em
Jonathan A. Kollasch64fc4332015-08-25 13:09:51 -05008415--- binutils-2.25/ld/emultempl/riscvelf.em 1970-01-01 01:00:00.000000000 +0100
Patrick Georgiaf473ed2015-07-17 23:35:54 +02008416+++ binutils-2.25/ld/emultempl/riscvelf.em 2015-07-18 00:02:36.222287541 +0200
Patrick Georgif0bbc952015-03-07 10:57:25 +01008417@@ -0,0 +1,68 @@
8418+# This shell script emits a C file. -*- C -*-
8419+# Copyright 2004, 2006, 2007, 2008 Free Software Foundation, Inc.
8420+#
8421+# This file is part of the GNU Binutils.
8422+#
8423+# This program is free software; you can redistribute it and/or modify
8424+# it under the terms of the GNU General Public License as published by
8425+# the Free Software Foundation; either version 3 of the License, or
8426+# (at your option) any later version.
8427+#
8428+# This program is distributed in the hope that it will be useful,
8429+# but WITHOUT ANY WARRANTY; without even the implied warranty of
8430+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
8431+# GNU General Public License for more details.
8432+#
8433+# You should have received a copy of the GNU General Public License
8434+# along with this program; if not, write to the Free Software
8435+# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
8436+# MA 02110-1301, USA.
8437+
8438+fragment <<EOF
8439+
8440+#include "ldmain.h"
8441+#include "ldctor.h"
8442+#include "elf/riscv.h"
8443+#include "elfxx-riscv.h"
8444+
8445+static void
8446+riscv_elf_before_allocation (void)
8447+{
8448+ gld${EMULATION_NAME}_before_allocation ();
8449+
8450+ if (link_info.discard == discard_sec_merge)
8451+ link_info.discard = discard_l;
8452+
8453+ /* We always need at least some relaxation to handle code alignment. */
8454+ if (RELAXATION_DISABLED_BY_USER)
8455+ TARGET_ENABLE_RELAXATION;
8456+ else
8457+ ENABLE_RELAXATION;
8458+
8459+ link_info.relax_pass = 2;
8460+}
8461+
8462+static void
8463+gld${EMULATION_NAME}_after_allocation (void)
8464+{
8465+ int need_layout = 0;
8466+
8467+ /* Don't attempt to discard unused .eh_frame sections until the final link,
8468+ as we can't reliably tell if they're used until after relaxation. */
8469+ if (!link_info.relocatable)
8470+ {
8471+ need_layout = bfd_elf_discard_info (link_info.output_bfd, &link_info);
8472+ if (need_layout < 0)
8473+ {
8474+ einfo ("%X%P: .eh_frame/.stab edit: %E\n");
8475+ return;
8476+ }
8477+ }
8478+
8479+ gld${EMULATION_NAME}_map_segments (need_layout);
8480+}
8481+
8482+EOF
8483+
8484+LDEMUL_BEFORE_ALLOCATION=riscv_elf_before_allocation
8485+LDEMUL_AFTER_ALLOCATION=gld${EMULATION_NAME}_after_allocation
Patrick Georgiaf473ed2015-07-17 23:35:54 +02008486diff -urN empty/opcodes/riscv-dis.c binutils-2.25/opcodes/riscv-dis.c
Jonathan A. Kollasch64fc4332015-08-25 13:09:51 -05008487--- binutils-2.25/opcodes/riscv-dis.c 1970-01-01 01:00:00.000000000 +0100
Patrick Georgiaf473ed2015-07-17 23:35:54 +02008488+++ binutils-2.25/opcodes/riscv-dis.c 2015-07-18 00:02:36.222287541 +0200
8489@@ -0,0 +1,590 @@
Patrick Georgif0bbc952015-03-07 10:57:25 +01008490+/* RISC-V disassembler
8491+ Copyright 2011-2014 Free Software Foundation, Inc.
8492+
8493+ Contributed by Andrew Waterman (waterman@cs.berkeley.edu) at UC Berkeley.
8494+ Based on MIPS target.
8495+
8496+ This file is part of the GNU opcodes library.
8497+
8498+ This library is free software; you can redistribute it and/or modify
8499+ it under the terms of the GNU General Public License as published by
8500+ the Free Software Foundation; either version 3, or (at your option)
8501+ any later version.
8502+
8503+ It is distributed in the hope that it will be useful, but WITHOUT
8504+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
8505+ or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
8506+ License for more details.
8507+
8508+ You should have received a copy of the GNU General Public License
8509+ along with this program; if not, write to the Free Software
8510+ Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
8511+ MA 02110-1301, USA. */
8512+
8513+#include "sysdep.h"
8514+#include "dis-asm.h"
8515+#include "libiberty.h"
8516+#include "opcode/riscv.h"
8517+#include "opintl.h"
8518+#include "elf-bfd.h"
8519+#include "elf/riscv.h"
8520+
8521+#include <stdint.h>
Patrick Georgiaf473ed2015-07-17 23:35:54 +02008522+#include <ctype.h>
Patrick Georgif0bbc952015-03-07 10:57:25 +01008523+
8524+struct riscv_private_data
8525+{
8526+ bfd_vma gp;
8527+ bfd_vma print_addr;
8528+ bfd_vma hi_addr[OP_MASK_RD + 1];
8529+};
8530+
8531+static const char * const *riscv_gpr_names;
8532+static const char * const *riscv_fpr_names;
8533+
8534+/* Other options */
8535+static int no_aliases; /* If set disassemble as most general inst. */
8536+
8537+static void
8538+set_default_riscv_dis_options (void)
8539+{
8540+ riscv_gpr_names = riscv_gpr_names_abi;
8541+ riscv_fpr_names = riscv_fpr_names_abi;
8542+ no_aliases = 0;
8543+}
8544+
8545+static void
8546+parse_riscv_dis_option (const char *option)
8547+{
8548+ if (CONST_STRNEQ (option, "no-aliases"))
8549+ no_aliases = 1;
8550+ else if (CONST_STRNEQ (option, "numeric"))
8551+ {
8552+ riscv_gpr_names = riscv_gpr_names_numeric;
8553+ riscv_fpr_names = riscv_fpr_names_numeric;
8554+ }
Patrick Georgiaf473ed2015-07-17 23:35:54 +02008555+ else
8556+ {
8557+ /* Invalid option. */
8558+ fprintf (stderr, _("Unrecognized disassembler option: %s\n"), option);
8559+ }
Patrick Georgif0bbc952015-03-07 10:57:25 +01008560+}
8561+
8562+static void
8563+parse_riscv_dis_options (const char *opts_in)
8564+{
8565+ char *opts = xstrdup (opts_in), *opt = opts, *opt_end = opts;
8566+
8567+ set_default_riscv_dis_options ();
8568+
8569+ for ( ; opt_end != NULL; opt = opt_end + 1)
8570+ {
8571+ if ((opt_end = strchr (opt, ',')) != NULL)
8572+ *opt_end = 0;
8573+ parse_riscv_dis_option (opt);
8574+ }
8575+
8576+ free (opts);
8577+}
8578+
8579+/* Print one argument from an array. */
8580+
8581+static void
8582+arg_print (struct disassemble_info *info, unsigned long val,
8583+ const char* const* array, size_t size)
8584+{
8585+ const char *s = val >= size || array[val] == NULL ? "unknown" : array[val];
8586+ (*info->fprintf_func) (info->stream, "%s", s);
8587+}
8588+
8589+static void
8590+maybe_print_address (struct riscv_private_data *pd, int base_reg, int offset)
8591+{
8592+ if (pd->hi_addr[base_reg] != (bfd_vma)-1)
8593+ {
8594+ pd->print_addr = pd->hi_addr[base_reg] + offset;
8595+ pd->hi_addr[base_reg] = -1;
8596+ }
8597+ else if (base_reg == X_GP && pd->gp != (bfd_vma)-1)
8598+ pd->print_addr = pd->gp + offset;
8599+ else if (base_reg == X_TP)
8600+ pd->print_addr = offset;
8601+}
8602+
8603+/* Print insn arguments for 32/64-bit code. */
8604+
8605+static void
8606+print_insn_args (const char *d, insn_t l, bfd_vma pc, disassemble_info *info)
8607+{
8608+ struct riscv_private_data *pd = info->private_data;
8609+ int rs1 = (l >> OP_SH_RS1) & OP_MASK_RS1;
8610+ int rd = (l >> OP_SH_RD) & OP_MASK_RD;
Patrick Georgiaf473ed2015-07-17 23:35:54 +02008611+ fprintf_ftype print = info->fprintf_func;
Patrick Georgif0bbc952015-03-07 10:57:25 +01008612+
8613+ if (*d != '\0')
Patrick Georgiaf473ed2015-07-17 23:35:54 +02008614+ print (info->stream, "\t");
Patrick Georgif0bbc952015-03-07 10:57:25 +01008615+
8616+ for (; *d != '\0'; d++)
8617+ {
8618+ switch (*d)
8619+ {
8620+ /* Xcustom */
8621+ case '^':
8622+ switch (*++d)
8623+ {
8624+ case 'd':
8625+ (*info->fprintf_func) (info->stream, "%d", rd);
8626+ break;
8627+ case 's':
8628+ (*info->fprintf_func) (info->stream, "%d", rs1);
8629+ break;
8630+ case 't':
8631+ (*info->fprintf_func)
8632+ ( info->stream, "%d", (int)((l >> OP_SH_RS2) & OP_MASK_RS2));
8633+ break;
8634+ case 'j':
8635+ (*info->fprintf_func)
8636+ ( info->stream, "%d", (int)((l >> OP_SH_CUSTOM_IMM) & OP_MASK_CUSTOM_IMM));
8637+ break;
8638+ }
8639+ break;
8640+
8641+ /* Xhwacha */
8642+ case '#':
8643+ switch ( *++d ) {
8644+ case 'g':
8645+ (*info->fprintf_func)
8646+ ( info->stream, "%d",
8647+ (int)((l >> OP_SH_IMMNGPR) & OP_MASK_IMMNGPR));
8648+ break;
8649+ case 'f':
8650+ (*info->fprintf_func)
8651+ ( info->stream, "%d",
8652+ (int)((l >> OP_SH_IMMNFPR) & OP_MASK_IMMNFPR));
8653+ break;
8654+ case 'p':
8655+ (*info->fprintf_func)
8656+ ( info->stream, "%d",
8657+ (int)((l >> OP_SH_CUSTOM_IMM) & OP_MASK_CUSTOM_IMM));
8658+ break;
8659+ case 'n':
8660+ (*info->fprintf_func)
8661+ ( info->stream, "%d",
8662+ (int)(((l >> OP_SH_IMMSEGNELM) & OP_MASK_IMMSEGNELM) + 1));
8663+ break;
8664+ case 'd':
8665+ (*info->fprintf_func)
8666+ ( info->stream, "%s",
8667+ riscv_vec_gpr_names[(l >> OP_SH_VRD) & OP_MASK_VRD]);
8668+ break;
8669+ case 's':
8670+ (*info->fprintf_func)
8671+ ( info->stream, "%s",
8672+ riscv_vec_gpr_names[(l >> OP_SH_VRS) & OP_MASK_VRS]);
8673+ break;
8674+ case 't':
8675+ (*info->fprintf_func)
8676+ ( info->stream, "%s",
8677+ riscv_vec_gpr_names[(l >> OP_SH_VRT) & OP_MASK_VRT]);
8678+ break;
8679+ case 'r':
8680+ (*info->fprintf_func)
8681+ ( info->stream, "%s",
8682+ riscv_vec_gpr_names[(l >> OP_SH_VRR) & OP_MASK_VRR]);
8683+ break;
8684+ case 'D':
8685+ (*info->fprintf_func)
8686+ ( info->stream, "%s",
8687+ riscv_vec_fpr_names[(l >> OP_SH_VFD) & OP_MASK_VFD]);
8688+ break;
8689+ case 'S':
8690+ (*info->fprintf_func)
8691+ ( info->stream, "%s",
8692+ riscv_vec_fpr_names[(l >> OP_SH_VFS) & OP_MASK_VFS]);
8693+ break;
8694+ case 'T':
8695+ (*info->fprintf_func)
8696+ ( info->stream, "%s",
8697+ riscv_vec_fpr_names[(l >> OP_SH_VFT) & OP_MASK_VFT]);
8698+ break;
8699+ case 'R':
8700+ (*info->fprintf_func)
8701+ ( info->stream, "%s",
8702+ riscv_vec_fpr_names[(l >> OP_SH_VFR) & OP_MASK_VFR]);
8703+ break;
8704+ }
8705+ break;
8706+
Patrick Georgiaf473ed2015-07-17 23:35:54 +02008707+ case 'C': /* RVC */
8708+ switch (*++d)
8709+ {
8710+ case 'd': /* RD x8-x15 */
8711+ print (info->stream, "%s",
8712+ riscv_gpr_names[((l >> OP_SH_CRDS) & OP_MASK_CRDS) + 8]);
8713+ break;
8714+ case 's': /* RS1 x8-x15 */
8715+ case 'w': /* RS1 x8-x15 */
8716+ print (info->stream, "%s",
8717+ riscv_gpr_names[((l >> OP_SH_CRS1S) & OP_MASK_CRS1S) + 8]);
8718+ break;
8719+ case 't': /* RS2 x8-x15 */
8720+ case 'x': /* RS2 x8-x15 */
8721+ print (info->stream, "%s",
8722+ riscv_gpr_names[((l >> OP_SH_CRS2S) & OP_MASK_CRS2S) + 8]);
8723+ break;
8724+ case 'U': /* RS1, constrained to equal RD */
8725+ case 'D': /* RS1 or RD, nonzero */
8726+ print (info->stream, "%s", riscv_gpr_names[rd]);
8727+ break;
8728+ case 'c': /* RS1, constrained to equal sp */
8729+ print (info->stream, "%s", riscv_gpr_names[X_SP]);
8730+ continue;
8731+ case 'T': /* RS2, nonzero */
8732+ case 'V': /* RS2 */
8733+ print (info->stream, "%s",
8734+ riscv_gpr_names[(l >> OP_SH_CRS2) & OP_MASK_CRS2]);
8735+ continue;
8736+ case 'i':
8737+ print (info->stream, "%d", (int)EXTRACT_RVC_SIMM3 (l));
8738+ break;
8739+ case 'j':
8740+ print (info->stream, "%d", (int)EXTRACT_RVC_IMM (l));
8741+ break;
8742+ case 'k':
8743+ print (info->stream, "%d", (int)EXTRACT_RVC_LW_IMM (l));
8744+ break;
8745+ case 'l':
8746+ print (info->stream, "%d", (int)EXTRACT_RVC_LD_IMM (l));
8747+ break;
8748+ case 'm':
8749+ print (info->stream, "%d", (int)EXTRACT_RVC_LWSP_IMM (l));
8750+ break;
8751+ case 'n':
8752+ print (info->stream, "%d", (int)EXTRACT_RVC_LDSP_IMM (l));
8753+ break;
8754+ case 'K':
8755+ print (info->stream, "%d", (int)EXTRACT_RVC_ADDI4SPN_IMM (l));
8756+ break;
8757+ case 'L':
8758+ print (info->stream, "%d", (int)EXTRACT_RVC_ADDI16SP_IMM (l));
8759+ break;
8760+ case 'M':
8761+ print (info->stream, "%d", (int)EXTRACT_RVC_SWSP_IMM (l));
8762+ break;
8763+ case 'N':
8764+ print (info->stream, "%d", (int)EXTRACT_RVC_SDSP_IMM (l));
8765+ break;
8766+ case 'p':
8767+ info->target = EXTRACT_RVC_B_IMM (l) + pc;
8768+ (*info->print_address_func) (info->target, info);
8769+ break;
8770+ case 'a':
8771+ info->target = EXTRACT_RVC_J_IMM (l) + pc;
8772+ (*info->print_address_func) (info->target, info);
8773+ break;
8774+ case 'u':
8775+ print (info->stream, "0x%x",
8776+ (int)(EXTRACT_RVC_IMM (l) & (RISCV_BIGIMM_REACH-1)));
8777+ break;
8778+ case '>':
8779+ print (info->stream, "0x%x", (int)EXTRACT_RVC_IMM (l) & 0x3f);
8780+ break;
8781+ case '<':
8782+ print (info->stream, "0x%x", (int)EXTRACT_RVC_IMM (l) & 0x1f);
8783+ break;
8784+ }
8785+ break;
8786+
Patrick Georgif0bbc952015-03-07 10:57:25 +01008787+ case ',':
8788+ case '(':
8789+ case ')':
8790+ case '[':
8791+ case ']':
8792+ (*info->fprintf_func) (info->stream, "%c", *d);
8793+ break;
8794+
8795+ case '0':
Patrick Georgiaf473ed2015-07-17 23:35:54 +02008796+ /* Only print constant 0 if it is the last argument */
8797+ if (!d[1])
8798+ print (info->stream, "0");
Patrick Georgif0bbc952015-03-07 10:57:25 +01008799+ break;
8800+
8801+ case 'b':
8802+ case 's':
8803+ (*info->fprintf_func) (info->stream, "%s", riscv_gpr_names[rs1]);
8804+ break;
8805+
8806+ case 't':
8807+ (*info->fprintf_func) (info->stream, "%s",
8808+ riscv_gpr_names[(l >> OP_SH_RS2) & OP_MASK_RS2]);
8809+ break;
8810+
8811+ case 'u':
8812+ (*info->fprintf_func) (info->stream, "0x%x", (unsigned)EXTRACT_UTYPE_IMM (l) >> RISCV_IMM_BITS);
8813+ break;
8814+
8815+ case 'm':
8816+ arg_print(info, (l >> OP_SH_RM) & OP_MASK_RM,
8817+ riscv_rm, ARRAY_SIZE(riscv_rm));
8818+ break;
8819+
8820+ case 'P':
8821+ arg_print(info, (l >> OP_SH_PRED) & OP_MASK_PRED,
8822+ riscv_pred_succ, ARRAY_SIZE(riscv_pred_succ));
8823+ break;
8824+
8825+ case 'Q':
8826+ arg_print(info, (l >> OP_SH_SUCC) & OP_MASK_SUCC,
8827+ riscv_pred_succ, ARRAY_SIZE(riscv_pred_succ));
8828+ break;
8829+
8830+ case 'o':
8831+ maybe_print_address (pd, rs1, EXTRACT_ITYPE_IMM (l));
8832+ case 'j':
8833+ if ((l & MASK_ADDI) == MATCH_ADDI || (l & MASK_JALR) == MATCH_JALR)
8834+ maybe_print_address (pd, rs1, EXTRACT_ITYPE_IMM (l));
8835+ (*info->fprintf_func) (info->stream, "%d", (int)EXTRACT_ITYPE_IMM (l));
8836+ break;
8837+
8838+ case 'q':
8839+ maybe_print_address (pd, rs1, EXTRACT_STYPE_IMM (l));
8840+ (*info->fprintf_func) (info->stream, "%d", (int)EXTRACT_STYPE_IMM (l));
8841+ break;
8842+
8843+ case 'a':
8844+ info->target = EXTRACT_UJTYPE_IMM (l) + pc;
8845+ (*info->print_address_func) (info->target, info);
8846+ break;
8847+
8848+ case 'p':
8849+ info->target = EXTRACT_SBTYPE_IMM (l) + pc;
8850+ (*info->print_address_func) (info->target, info);
8851+ break;
8852+
8853+ case 'd':
8854+ if ((l & MASK_AUIPC) == MATCH_AUIPC)
8855+ pd->hi_addr[rd] = pc + EXTRACT_UTYPE_IMM (l);
8856+ else if ((l & MASK_LUI) == MATCH_LUI)
8857+ pd->hi_addr[rd] = EXTRACT_UTYPE_IMM (l);
8858+ (*info->fprintf_func) (info->stream, "%s", riscv_gpr_names[rd]);
8859+ break;
8860+
8861+ case 'z':
8862+ (*info->fprintf_func) (info->stream, "%s", riscv_gpr_names[0]);
8863+ break;
8864+
8865+ case '>':
8866+ (*info->fprintf_func) (info->stream, "0x%x",
8867+ (unsigned)((l >> OP_SH_SHAMT) & OP_MASK_SHAMT));
8868+ break;
8869+
8870+ case '<':
8871+ (*info->fprintf_func) (info->stream, "0x%x",
8872+ (unsigned)((l >> OP_SH_SHAMTW) & OP_MASK_SHAMTW));
8873+ break;
8874+
8875+ case 'S':
8876+ case 'U':
8877+ (*info->fprintf_func) (info->stream, "%s", riscv_fpr_names[rs1]);
8878+ break;
8879+
8880+ case 'T':
8881+ (*info->fprintf_func) (info->stream, "%s",
8882+ riscv_fpr_names[(l >> OP_SH_RS2) & OP_MASK_RS2]);
8883+ break;
8884+
8885+ case 'D':
8886+ (*info->fprintf_func) (info->stream, "%s", riscv_fpr_names[rd]);
8887+ break;
8888+
8889+ case 'R':
8890+ (*info->fprintf_func) (info->stream, "%s",
8891+ riscv_fpr_names[(l >> OP_SH_RS3) & OP_MASK_RS3]);
8892+ break;
8893+
8894+ case 'E':
8895+ {
8896+ const char* csr_name = NULL;
8897+ unsigned int csr = (l >> OP_SH_CSR) & OP_MASK_CSR;
8898+ switch (csr)
8899+ {
8900+ #define DECLARE_CSR(name, num) case num: csr_name = #name; break;
8901+ #include "opcode/riscv-opc.h"
8902+ #undef DECLARE_CSR
8903+ }
8904+ if (csr_name)
8905+ (*info->fprintf_func) (info->stream, "%s", csr_name);
8906+ else
8907+ (*info->fprintf_func) (info->stream, "0x%x", csr);
8908+ break;
8909+ }
8910+
8911+ case 'Z':
8912+ (*info->fprintf_func) (info->stream, "%d", rs1);
8913+ break;
8914+
8915+ default:
8916+ /* xgettext:c-format */
8917+ (*info->fprintf_func) (info->stream,
8918+ _("# internal error, undefined modifier (%c)"),
8919+ *d);
8920+ return;
8921+ }
8922+ }
8923+}
8924+
8925+/* Print the RISC-V instruction at address MEMADDR in debugged memory,
8926+ on using INFO. Returns length of the instruction, in bytes.
8927+ BIGENDIAN must be 1 if this is big-endian code, 0 if
8928+ this is little-endian code. */
8929+
8930+static int
8931+riscv_disassemble_insn (bfd_vma memaddr, insn_t word, disassemble_info *info)
8932+{
8933+ const struct riscv_opcode *op;
8934+ static bfd_boolean init = 0;
Patrick Georgif0bbc952015-03-07 10:57:25 +01008935+ static const struct riscv_opcode *riscv_hash[OP_MASK_OP + 1];
8936+ struct riscv_private_data *pd;
8937+ int insnlen;
8938+
Patrick Georgiaf473ed2015-07-17 23:35:54 +02008939+#define OP_HASH_IDX(i) ((i) & (riscv_insn_length (i) == 2 ? 0x3 : 0x7f))
8940+
Patrick Georgif0bbc952015-03-07 10:57:25 +01008941+ /* Build a hash table to shorten the search time. */
8942+ if (! init)
8943+ {
Patrick Georgiaf473ed2015-07-17 23:35:54 +02008944+ for (op = riscv_opcodes; op < &riscv_opcodes[NUMOPCODES]; op++)
8945+ {
8946+ if (!riscv_hash[OP_HASH_IDX (op->match)])
8947+ riscv_hash[OP_HASH_IDX (op->match)] = op;
8948+ }
Patrick Georgif0bbc952015-03-07 10:57:25 +01008949+
8950+ init = 1;
8951+ }
8952+
8953+ if (info->private_data == NULL)
8954+ {
8955+ int i;
8956+
Patrick Georgiaf473ed2015-07-17 23:35:54 +02008957+ pd = info->private_data = xcalloc (1, sizeof (struct riscv_private_data));
Patrick Georgif0bbc952015-03-07 10:57:25 +01008958+ pd->gp = -1;
8959+ pd->print_addr = -1;
8960+ for (i = 0; i < (int) ARRAY_SIZE(pd->hi_addr); i++)
8961+ pd->hi_addr[i] = -1;
8962+
8963+ for (i = 0; i < info->symtab_size; i++)
8964+ if (strcmp (bfd_asymbol_name (info->symtab[i]), "_gp") == 0)
8965+ pd->gp = bfd_asymbol_value (info->symtab[i]);
8966+ }
8967+ else
8968+ pd = info->private_data;
8969+
8970+ insnlen = riscv_insn_length (word);
8971+
8972+ info->bytes_per_chunk = insnlen % 4 == 0 ? 4 : 2;
8973+ info->bytes_per_line = 8;
8974+ info->display_endian = info->endian;
8975+ info->insn_info_valid = 1;
8976+ info->branch_delay_insns = 0;
8977+ info->data_size = 0;
8978+ info->insn_type = dis_nonbranch;
8979+ info->target = 0;
8980+ info->target2 = 0;
8981+
Patrick Georgiaf473ed2015-07-17 23:35:54 +02008982+ op = riscv_hash[OP_HASH_IDX (word)];
Patrick Georgif0bbc952015-03-07 10:57:25 +01008983+ if (op != NULL)
8984+ {
Patrick Georgiaf473ed2015-07-17 23:35:54 +02008985+ const char *extension = NULL;
8986+ int xlen = 0;
8987+
8988+ /* The incoming section might not always be complete. */
8989+ if (info->section != NULL)
8990+ {
8991+ Elf_Internal_Ehdr *ehdr = elf_elfheader (info->section->owner);
8992+ unsigned int e_flags = ehdr->e_flags;
8993+ extension = riscv_elf_flag_to_name (EF_GET_RISCV_EXT (e_flags));
8994+
8995+ xlen = 32;
8996+ if (ehdr->e_ident[EI_CLASS] == ELFCLASS64)
8997+ xlen = 64;
8998+ }
8999+
Patrick Georgif0bbc952015-03-07 10:57:25 +01009000+ for (; op < &riscv_opcodes[NUMOPCODES]; op++)
9001+ {
9002+ if ((op->match_func) (op, word)
9003+ && !(no_aliases && (op->pinfo & INSN_ALIAS))
Patrick Georgiaf473ed2015-07-17 23:35:54 +02009004+ && !(op->subset[0] == 'X' && extension != NULL
9005+ && strcmp (op->subset, extension))
9006+ && !(isdigit(op->subset[0]) && atoi(op->subset) != xlen))
Patrick Georgif0bbc952015-03-07 10:57:25 +01009007+ {
9008+ (*info->fprintf_func) (info->stream, "%s", op->name);
9009+ print_insn_args (op->args, word, memaddr, info);
9010+ if (pd->print_addr != (bfd_vma)-1)
9011+ {
9012+ info->target = pd->print_addr;
9013+ (*info->fprintf_func) (info->stream, " # ");
9014+ (*info->print_address_func) (info->target, info);
9015+ pd->print_addr = -1;
9016+ }
9017+ return insnlen;
9018+ }
9019+ }
9020+ }
9021+
9022+ /* Handle undefined instructions. */
9023+ info->insn_type = dis_noninsn;
9024+ (*info->fprintf_func) (info->stream, "0x%llx", (unsigned long long)word);
9025+ return insnlen;
9026+}
9027+
9028+int
9029+print_insn_riscv (bfd_vma memaddr, struct disassemble_info *info)
9030+{
9031+ uint16_t i2;
9032+ insn_t insn = 0;
9033+ bfd_vma n;
9034+ int status;
9035+
9036+ if (info->disassembler_options != NULL)
9037+ {
9038+ parse_riscv_dis_options (info->disassembler_options);
9039+ /* Avoid repeatedly parsing the options. */
9040+ info->disassembler_options = NULL;
9041+ }
9042+ else if (riscv_gpr_names == NULL)
9043+ set_default_riscv_dis_options ();
9044+
9045+ /* Instructions are a sequence of 2-byte packets in little-endian order. */
9046+ for (n = 0; n < sizeof(insn) && n < riscv_insn_length (insn); n += 2)
9047+ {
9048+ status = (*info->read_memory_func) (memaddr + n, (bfd_byte*)&i2, 2, info);
9049+ if (status != 0)
9050+ {
9051+ if (n > 0) /* Don't fail just because we fell off the end. */
9052+ break;
9053+ (*info->memory_error_func) (status, memaddr, info);
9054+ return status;
9055+ }
9056+
9057+ i2 = bfd_getl16 (&i2);
9058+ insn |= (insn_t)i2 << (8*n);
9059+ }
9060+
9061+ return riscv_disassemble_insn (memaddr, insn, info);
9062+}
9063+
9064+void
9065+print_riscv_disassembler_options (FILE *stream)
9066+{
9067+ fprintf (stream, _("\n\
9068+The following RISC-V-specific disassembler options are supported for use\n\
9069+with the -M switch (multiple options should be separated by commas):\n"));
9070+
9071+ fprintf (stream, _("\n\
9072+ numeric Print numeric reigster names, rather than ABI names.\n"));
9073+
9074+ fprintf (stream, _("\n\
9075+ no-aliases Disassemble only into canonical instructions, rather\n\
9076+ than into pseudoinstructions.\n"));
9077+
9078+ fprintf (stream, _("\n"));
9079+}
Patrick Georgiaf473ed2015-07-17 23:35:54 +02009080diff -urN empty/opcodes/riscv-opc.c binutils-2.25/opcodes/riscv-opc.c
Jonathan A. Kollasch64fc4332015-08-25 13:09:51 -05009081--- binutils-2.25/opcodes/riscv-opc.c 1970-01-01 01:00:00.000000000 +0100
Patrick Georgiaf473ed2015-07-17 23:35:54 +02009082+++ binutils-2.25/opcodes/riscv-opc.c 2015-07-18 00:02:36.222287541 +0200
9083@@ -0,0 +1,867 @@
Patrick Georgif0bbc952015-03-07 10:57:25 +01009084+/* RISC-V opcode list
9085+ Copyright 2011-2014 Free Software Foundation, Inc.
9086+
9087+ Contributed by Andrew Waterman (waterman@cs.berkeley.edu) at UC Berkeley.
9088+ Based on MIPS target.
9089+
9090+ This file is part of the GNU opcodes library.
9091+
9092+ This library is free software; you can redistribute it and/or modify
9093+ it under the terms of the GNU General Public License as published by
9094+ the Free Software Foundation; either version 3, or (at your option)
9095+ any later version.
9096+
9097+ It is distributed in the hope that it will be useful, but WITHOUT
9098+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
9099+ or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
9100+ License for more details.
9101+
9102+ You should have received a copy of the GNU General Public License
9103+ along with this file; see the file COPYING. If not, write to the
9104+ Free Software Foundation, 51 Franklin Street - Fifth Floor, Boston,
9105+ MA 02110-1301, USA. */
9106+
9107+#include "sysdep.h"
9108+#include "opcode/riscv.h"
9109+#include <stdio.h>
9110+
9111+/* Register names used by gas and objdump. */
9112+
9113+const char * const riscv_gpr_names_numeric[32] =
9114+{
9115+ "x0", "x1", "x2", "x3", "x4", "x5", "x6", "x7",
9116+ "x8", "x9", "x10", "x11", "x12", "x13", "x14", "x15",
9117+ "x16", "x17", "x18", "x19", "x20", "x21", "x22", "x23",
9118+ "x24", "x25", "x26", "x27", "x28", "x29", "x30", "x31"
9119+};
9120+
9121+const char * const riscv_gpr_names_abi[32] = {
9122+ "zero", "ra", "sp", "gp", "tp", "t0", "t1", "t2",
9123+ "s0", "s1", "a0", "a1", "a2", "a3", "a4", "a5",
9124+ "a6", "a7", "s2", "s3", "s4", "s5", "s6", "s7",
9125+ "s8", "s9", "s10", "s11", "t3", "t4", "t5", "t6"
9126+};
9127+
9128+const char * const riscv_fpr_names_numeric[32] =
9129+{
9130+ "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7",
9131+ "f8", "f9", "f10", "f11", "f12", "f13", "f14", "f15",
9132+ "f16", "f17", "f18", "f19", "f20", "f21", "f22", "f23",
9133+ "f24", "f25", "f26", "f27", "f28", "f29", "f30", "f31"
9134+};
9135+
9136+const char * const riscv_fpr_names_abi[32] = {
9137+ "ft0", "ft1", "ft2", "ft3", "ft4", "ft5", "ft6", "ft7",
9138+ "fs0", "fs1", "fa0", "fa1", "fa2", "fa3", "fa4", "fa5",
9139+ "fa6", "fa7", "fs2", "fs3", "fs4", "fs5", "fs6", "fs7",
9140+ "fs8", "fs9", "fs10", "fs11", "ft8", "ft9", "ft10", "ft11"
9141+};
9142+
9143+const char * const riscv_vec_gpr_names[32] =
9144+{
9145+ "vx0", "vx1", "vx2", "vx3", "vx4", "vx5", "vx6", "vx7",
9146+ "vx8", "vx9", "vx10", "vx11", "vx12", "vx13", "vx14", "vx15",
9147+ "vx16", "vx17", "vx18", "vx19", "vx20", "vx21", "vx22", "vx23",
9148+ "vx24", "vx25", "vx26", "vx27", "vx28", "vx29", "vx30", "vx31"
9149+};
9150+
9151+const char * const riscv_vec_fpr_names[32] =
9152+{
9153+ "vf0", "vf1", "vf2", "vf3", "vf4", "vf5", "vf6", "vf7",
9154+ "vf8", "vf9", "vf10", "vf11", "vf12", "vf13", "vf14", "vf15",
9155+ "vf16", "vf17", "vf18", "vf19", "vf20", "vf21", "vf22", "vf23",
9156+ "vf24", "vf25", "vf26", "vf27", "vf28", "vf29", "vf30", "vf31"
9157+};
9158+
9159+/* The order of overloaded instructions matters. Label arguments and
9160+ register arguments look the same. Instructions that can have either
9161+ for arguments must apear in the correct order in this table for the
9162+ assembler to pick the right one. In other words, entries with
9163+ immediate operands must apear after the same instruction with
9164+ registers.
9165+
9166+ Because of the lookup algorithm used, entries with the same opcode
9167+ name must be contiguous. */
9168+
9169+#define WR_xd INSN_WRITE_GPR_D
9170+#define WR_fd INSN_WRITE_FPR_D
9171+#define RD_xs1 INSN_READ_GPR_S
9172+#define RD_xs2 INSN_READ_GPR_T
9173+#define RD_fs1 INSN_READ_FPR_S
9174+#define RD_fs2 INSN_READ_FPR_T
9175+#define RD_fs3 INSN_READ_FPR_R
9176+
9177+#define MASK_RS1 (OP_MASK_RS1 << OP_SH_RS1)
9178+#define MASK_RS2 (OP_MASK_RS2 << OP_SH_RS2)
9179+#define MASK_RD (OP_MASK_RD << OP_SH_RD)
9180+#define MASK_IMM ENCODE_ITYPE_IMM(-1U)
Patrick Georgiaf473ed2015-07-17 23:35:54 +02009181+#define MASK_RVC_IMM ENCODE_RVC_IMM(-1U)
Patrick Georgif0bbc952015-03-07 10:57:25 +01009182+#define MASK_UIMM ENCODE_UTYPE_IMM(-1U)
9183+#define MASK_RM (OP_MASK_RM << OP_SH_RM)
9184+#define MASK_PRED (OP_MASK_PRED << OP_SH_PRED)
9185+#define MASK_SUCC (OP_MASK_SUCC << OP_SH_SUCC)
9186+#define MASK_AQ (OP_MASK_AQ << OP_SH_AQ)
9187+#define MASK_RL (OP_MASK_RL << OP_SH_RL)
9188+#define MASK_AQRL (MASK_AQ | MASK_RL)
9189+
9190+static int match_opcode(const struct riscv_opcode *op, insn_t insn)
9191+{
Patrick Georgiaf473ed2015-07-17 23:35:54 +02009192+ return ((insn ^ op->match) & op->mask) == 0;
Patrick Georgif0bbc952015-03-07 10:57:25 +01009193+}
9194+
9195+static int match_never(const struct riscv_opcode *op ATTRIBUTE_UNUSED,
9196+ insn_t insn ATTRIBUTE_UNUSED)
9197+{
9198+ return 0;
9199+}
9200+
9201+static int match_rs1_eq_rs2(const struct riscv_opcode *op, insn_t insn)
9202+{
9203+ return match_opcode(op, insn) &&
9204+ ((insn & MASK_RS1) >> OP_SH_RS1) == ((insn & MASK_RS2) >> OP_SH_RS2);
9205+}
9206+
Patrick Georgiaf473ed2015-07-17 23:35:54 +02009207+static int match_rd_nonzero(const struct riscv_opcode *op, insn_t insn)
9208+{
9209+ return match_opcode(op, insn) && ((insn & MASK_RD) != 0);
9210+}
9211+
Patrick Georgif0bbc952015-03-07 10:57:25 +01009212+const struct riscv_opcode riscv_builtin_opcodes[] =
9213+{
Patrick Georgiaf473ed2015-07-17 23:35:54 +02009214+/* name, isa, operands, match, mask, match_func, pinfo */
9215+{"unimp", "C", "", 0, 0xffffU, match_opcode, 0 },
9216+{"unimp", "I", "", MATCH_CSRRW | (CSR_CYCLE << OP_SH_CSR), 0xffffffffU, match_opcode, 0 }, /* csrw cycle, x0 */
9217+{"ebreak", "C", "", MATCH_C_EBREAK, MASK_C_EBREAK, match_opcode, INSN_ALIAS },
9218+{"ebreak", "I", "", MATCH_EBREAK, MASK_EBREAK, match_opcode, 0 },
9219+{"sbreak", "C", "", MATCH_C_EBREAK, MASK_C_EBREAK, match_opcode, INSN_ALIAS },
9220+{"sbreak", "I", "", MATCH_EBREAK, MASK_EBREAK, match_opcode, INSN_ALIAS },
9221+{"ret", "C", "", MATCH_C_JR | (X_RA << OP_SH_RD), MASK_C_JR | MASK_RD, match_opcode, INSN_ALIAS },
9222+{"ret", "I", "", MATCH_JALR | (X_RA << OP_SH_RS1), MASK_JALR | MASK_RD | MASK_RS1 | MASK_IMM, match_opcode, INSN_ALIAS|WR_xd|RD_xs1 },
9223+{"jr", "C", "CD", MATCH_C_JR, MASK_C_JR, match_rd_nonzero, INSN_ALIAS },
9224+{"jr", "I", "s", MATCH_JALR, MASK_JALR | MASK_RD | MASK_IMM, match_opcode, INSN_ALIAS|WR_xd|RD_xs1 },
9225+{"jr", "I", "s,j", MATCH_JALR, MASK_JALR | MASK_RD, match_opcode, INSN_ALIAS|WR_xd|RD_xs1 },
9226+{"jalr", "C", "CD", MATCH_C_JALR, MASK_C_JALR, match_rd_nonzero, INSN_ALIAS },
9227+{"jalr", "I", "s", MATCH_JALR | (X_RA << OP_SH_RD), MASK_JALR | MASK_RD | MASK_IMM, match_opcode, INSN_ALIAS|WR_xd|RD_xs1 },
9228+{"jalr", "I", "s,j", MATCH_JALR | (X_RA << OP_SH_RD), MASK_JALR | MASK_RD, match_opcode, INSN_ALIAS|WR_xd|RD_xs1 },
9229+{"jalr", "I", "d,s", MATCH_JALR, MASK_JALR | MASK_IMM, match_opcode, INSN_ALIAS|WR_xd|RD_xs1 },
9230+{"jalr", "I", "d,s,j", MATCH_JALR, MASK_JALR, match_opcode, WR_xd|RD_xs1 },
9231+{"j", "C", "Ca", MATCH_C_J, MASK_C_J, match_opcode, INSN_ALIAS },
9232+{"j", "I", "a", MATCH_JAL, MASK_JAL | MASK_RD, match_opcode, INSN_ALIAS },
9233+{"jal", "C", "Ca", MATCH_C_JAL, MASK_C_JAL, match_opcode, INSN_ALIAS },
9234+{"jal", "I", "a", MATCH_JAL | (X_RA << OP_SH_RD), MASK_JAL | MASK_RD, match_opcode, INSN_ALIAS|WR_xd },
9235+{"jal", "I", "d,a", MATCH_JAL, MASK_JAL, match_opcode, WR_xd },
9236+{"call", "I", "c", (X_T0 << OP_SH_RS1) | (X_RA << OP_SH_RD), (int) M_CALL, match_never, INSN_MACRO },
9237+{"call", "I", "d,c", (X_T0 << OP_SH_RS1), (int) M_CALL, match_never, INSN_MACRO },
9238+{"tail", "I", "c", (X_T0 << OP_SH_RS1), (int) M_CALL, match_never, INSN_MACRO },
9239+{"jump", "I", "c,s", 0, (int) M_CALL, match_never, INSN_MACRO },
9240+{"nop", "C", "", MATCH_C_ADDI16SP, 0xffff, match_opcode, INSN_ALIAS },
Patrick Georgif0bbc952015-03-07 10:57:25 +01009241+{"nop", "I", "", MATCH_ADDI, MASK_ADDI | MASK_RD | MASK_RS1 | MASK_IMM, match_opcode, INSN_ALIAS },
Patrick Georgiaf473ed2015-07-17 23:35:54 +02009242+{"lui", "C", "CD,Cu", MATCH_C_LUI, MASK_C_LUI, match_rd_nonzero, INSN_ALIAS },
9243+{"lui", "I", "d,u", MATCH_LUI, MASK_LUI, match_opcode, WR_xd },
9244+{"li", "C", "CD,Cv", MATCH_C_LUI, MASK_C_LUI, match_rd_nonzero, INSN_ALIAS },
9245+{"li", "C", "CD,Cj", MATCH_C_LI, MASK_C_LI, match_rd_nonzero, INSN_ALIAS },
9246+{"li", "C", "CD,0", MATCH_C_MV, MASK_C_MV | (OP_MASK_CRS2 << OP_SH_CRS2), match_rd_nonzero, INSN_ALIAS },
Patrick Georgif0bbc952015-03-07 10:57:25 +01009247+{"li", "I", "d,j", MATCH_ADDI, MASK_ADDI | MASK_RS1, match_opcode, INSN_ALIAS|WR_xd }, /* addi */
9248+{"li", "I", "d,I", 0, (int) M_LI, match_never, INSN_MACRO },
Patrick Georgiaf473ed2015-07-17 23:35:54 +02009249+{"mv", "C", "CD,CV", MATCH_C_MV, MASK_C_MV, match_rd_nonzero, INSN_ALIAS },
Patrick Georgif0bbc952015-03-07 10:57:25 +01009250+{"mv", "I", "d,s", MATCH_ADDI, MASK_ADDI | MASK_IMM, match_opcode, INSN_ALIAS|WR_xd|RD_xs1 },
Patrick Georgiaf473ed2015-07-17 23:35:54 +02009251+{"move", "C", "CD,CV", MATCH_C_MV, MASK_C_MV, match_rd_nonzero, INSN_ALIAS },
Patrick Georgif0bbc952015-03-07 10:57:25 +01009252+{"move", "I", "d,s", MATCH_ADDI, MASK_ADDI | MASK_IMM, match_opcode, INSN_ALIAS|WR_xd|RD_xs1 },
Patrick Georgiaf473ed2015-07-17 23:35:54 +02009253+{"andi", "32C", "CD,CU,Cj", MATCH_C_ANDI, MASK_C_ANDI, match_rd_nonzero, INSN_ALIAS },
9254+{"andi", "32C", "Ct,Cs,Ci", MATCH_C_ANDIN, MASK_C_ANDIN, match_opcode, INSN_ALIAS },
Patrick Georgif0bbc952015-03-07 10:57:25 +01009255+{"andi", "I", "d,s,j", MATCH_ANDI, MASK_ANDI, match_opcode, WR_xd|RD_xs1 },
Patrick Georgiaf473ed2015-07-17 23:35:54 +02009256+{"and", "C", "Cd,Cs,Ct", MATCH_C_AND3, MASK_C_AND3, match_opcode, INSN_ALIAS },
9257+{"and", "32C", "CD,CU,Cj", MATCH_C_ANDI, MASK_C_ANDI, match_rd_nonzero, INSN_ALIAS },
9258+{"and", "32C", "Ct,Cs,Ci", MATCH_C_ANDIN, MASK_C_ANDIN, match_opcode, INSN_ALIAS },
Patrick Georgif0bbc952015-03-07 10:57:25 +01009259+{"and", "I", "d,s,t", MATCH_AND, MASK_AND, match_opcode, WR_xd|RD_xs1|RD_xs2 },
9260+{"and", "I", "d,s,j", MATCH_ANDI, MASK_ANDI, match_opcode, INSN_ALIAS|WR_xd|RD_xs1 },
Patrick Georgiaf473ed2015-07-17 23:35:54 +02009261+{"beqz", "C", "Cs,Cp", MATCH_C_BEQZ, MASK_C_BEQZ, match_opcode, INSN_ALIAS },
Patrick Georgif0bbc952015-03-07 10:57:25 +01009262+{"beqz", "I", "s,p", MATCH_BEQ, MASK_BEQ | MASK_RS2, match_opcode, INSN_ALIAS|RD_xs1 },
9263+{"beq", "I", "s,t,p", MATCH_BEQ, MASK_BEQ, match_opcode, RD_xs1|RD_xs2 },
9264+{"blez", "I", "t,p", MATCH_BGE, MASK_BGE | MASK_RS1, match_opcode, INSN_ALIAS|RD_xs2 },
Patrick Georgiaf473ed2015-07-17 23:35:54 +02009265+{"bgez", "32C", "Cs,Cp", MATCH_C_BGEZ, MASK_C_BGEZ, match_opcode, INSN_ALIAS },
Patrick Georgif0bbc952015-03-07 10:57:25 +01009266+{"bgez", "I", "s,p", MATCH_BGE, MASK_BGE | MASK_RS2, match_opcode, INSN_ALIAS|RD_xs1 },
9267+{"ble", "I", "t,s,p", MATCH_BGE, MASK_BGE, match_opcode, INSN_ALIAS|RD_xs1|RD_xs2 },
9268+{"bleu", "I", "t,s,p", MATCH_BGEU, MASK_BGEU, match_opcode, INSN_ALIAS|RD_xs1|RD_xs2 },
9269+{"bge", "I", "s,t,p", MATCH_BGE, MASK_BGE, match_opcode, RD_xs1|RD_xs2 },
9270+{"bgeu", "I", "s,t,p", MATCH_BGEU, MASK_BGEU, match_opcode, RD_xs1|RD_xs2 },
Patrick Georgiaf473ed2015-07-17 23:35:54 +02009271+{"bltz", "32C", "Cs,Cp", MATCH_C_BLTZ, MASK_C_BLTZ, match_opcode, INSN_ALIAS },
Patrick Georgif0bbc952015-03-07 10:57:25 +01009272+{"bltz", "I", "s,p", MATCH_BLT, MASK_BLT | MASK_RS2, match_opcode, INSN_ALIAS|RD_xs1 },
9273+{"bgtz", "I", "t,p", MATCH_BLT, MASK_BLT | MASK_RS1, match_opcode, INSN_ALIAS|RD_xs2 },
9274+{"blt", "I", "s,t,p", MATCH_BLT, MASK_BLT, match_opcode, RD_xs1|RD_xs2 },
9275+{"bltu", "I", "s,t,p", MATCH_BLTU, MASK_BLTU, match_opcode, RD_xs1|RD_xs2 },
9276+{"bgt", "I", "t,s,p", MATCH_BLT, MASK_BLT, match_opcode, INSN_ALIAS|RD_xs1|RD_xs2 },
9277+{"bgtu", "I", "t,s,p", MATCH_BLTU, MASK_BLTU, match_opcode, INSN_ALIAS|RD_xs1|RD_xs2 },
Patrick Georgiaf473ed2015-07-17 23:35:54 +02009278+{"bnez", "C", "Cs,Cp", MATCH_C_BNEZ, MASK_C_BNEZ, match_opcode, INSN_ALIAS },
Patrick Georgif0bbc952015-03-07 10:57:25 +01009279+{"bnez", "I", "s,p", MATCH_BNE, MASK_BNE | MASK_RS2, match_opcode, INSN_ALIAS|RD_xs1 },
9280+{"bne", "I", "s,t,p", MATCH_BNE, MASK_BNE, match_opcode, RD_xs1|RD_xs2 },
Patrick Georgiaf473ed2015-07-17 23:35:54 +02009281+{"addi", "C", "Ct,Cc,CK", MATCH_C_ADDI4SPN, MASK_C_ADDI4SPN, match_opcode, INSN_ALIAS },
9282+{"addi", "C", "CD,CU,Cj", MATCH_C_ADDI, MASK_C_ADDI, match_rd_nonzero, INSN_ALIAS },
9283+{"addi", "C", "Cc,Cc,CL", MATCH_C_ADDI16SP, MASK_C_ADDI16SP, match_opcode, INSN_ALIAS },
9284+{"addi", "32C", "Ct,Cs,Ci", MATCH_C_ADDIN, MASK_C_ADDIN, match_opcode, INSN_ALIAS },
Patrick Georgif0bbc952015-03-07 10:57:25 +01009285+{"addi", "I", "d,s,j", MATCH_ADDI, MASK_ADDI, match_opcode, WR_xd|RD_xs1 },
Patrick Georgiaf473ed2015-07-17 23:35:54 +02009286+{"add", "C", "CD,CU,CT", MATCH_C_ADD, MASK_C_ADD, match_rd_nonzero, INSN_ALIAS },
9287+{"add", "C", "CD,CT,CU", MATCH_C_ADD, MASK_C_ADD, match_rd_nonzero, INSN_ALIAS },
9288+{"add", "C", "CD,CU,Cj", MATCH_C_ADDI, MASK_C_ADDI, match_rd_nonzero, INSN_ALIAS },
9289+{"add", "C", "Ct,Cc,CK", MATCH_C_ADDI4SPN, MASK_C_ADDI4SPN, match_opcode, INSN_ALIAS },
9290+{"add", "C", "Cd,Cs,Ct", MATCH_C_ADD3, MASK_C_ADD3, match_opcode, INSN_ALIAS },
9291+{"add", "C", "Cc,Cc,CL", MATCH_C_ADDI16SP, MASK_C_ADDI16SP, match_opcode, INSN_ALIAS },
9292+{"add", "32C", "Ct,Cs,Ci", MATCH_C_ADDIN, MASK_C_ADDIN, match_opcode, INSN_ALIAS },
Patrick Georgif0bbc952015-03-07 10:57:25 +01009293+{"add", "I", "d,s,t", MATCH_ADD, MASK_ADD, match_opcode, WR_xd|RD_xs1|RD_xs2 },
9294+{"add", "I", "d,s,t,0",MATCH_ADD, MASK_ADD, match_opcode, WR_xd|RD_xs1|RD_xs2 },
9295+{"add", "I", "d,s,j", MATCH_ADDI, MASK_ADDI, match_opcode, INSN_ALIAS|WR_xd|RD_xs1 },
9296+{"la", "I", "d,A", 0, (int) M_LA, match_never, INSN_MACRO },
9297+{"lla", "I", "d,A", 0, (int) M_LLA, match_never, INSN_MACRO },
9298+{"la.tls.gd", "I", "d,A", 0, (int) M_LA_TLS_GD, match_never, INSN_MACRO },
9299+{"la.tls.ie", "I", "d,A", 0, (int) M_LA_TLS_IE, match_never, INSN_MACRO },
9300+{"neg", "I", "d,t", MATCH_SUB, MASK_SUB | MASK_RS1, match_opcode, INSN_ALIAS|WR_xd|RD_xs2 }, /* sub 0 */
Patrick Georgiaf473ed2015-07-17 23:35:54 +02009301+{"slli", "C", "CD,CU,C>", MATCH_C_SLLI, MASK_C_SLLI, match_rd_nonzero, INSN_ALIAS },
Patrick Georgif0bbc952015-03-07 10:57:25 +01009302+{"slli", "I", "d,s,>", MATCH_SLLI, MASK_SLLI, match_opcode, WR_xd|RD_xs1 },
Patrick Georgiaf473ed2015-07-17 23:35:54 +02009303+{"sll", "C", "CD,CU,C>", MATCH_C_SLLI, MASK_C_SLLI, match_rd_nonzero, INSN_ALIAS },
9304+{"sll", "32C", "Cs,Cw,Ct", MATCH_C_SLL, MASK_C_SLL, match_opcode, INSN_ALIAS },
9305+{"sll", "32C", "Ct,Cs,Cx", MATCH_C_SLLR, MASK_C_SLLR, match_opcode, INSN_ALIAS },
Patrick Georgif0bbc952015-03-07 10:57:25 +01009306+{"sll", "I", "d,s,t", MATCH_SLL, MASK_SLL, match_opcode, WR_xd|RD_xs1|RD_xs2 },
9307+{"sll", "I", "d,s,>", MATCH_SLLI, MASK_SLLI, match_opcode, INSN_ALIAS|WR_xd|RD_xs1 },
Patrick Georgiaf473ed2015-07-17 23:35:54 +02009308+{"srli", "C", "CD,CU,C>", MATCH_C_SRLI, MASK_C_SRLI, match_rd_nonzero, INSN_ALIAS },
Patrick Georgif0bbc952015-03-07 10:57:25 +01009309+{"srli", "I", "d,s,>", MATCH_SRLI, MASK_SRLI, match_opcode, WR_xd|RD_xs1 },
Patrick Georgiaf473ed2015-07-17 23:35:54 +02009310+{"srl", "C", "CD,CU,C>", MATCH_C_SRLI, MASK_C_SRLI, match_rd_nonzero, INSN_ALIAS },
9311+{"srl", "32C", "Cs,Cw,Ct", MATCH_C_SRL, MASK_C_SRL, match_opcode, INSN_ALIAS },
9312+{"srl", "32C", "Ct,Cs,Cx", MATCH_C_SRLR, MASK_C_SRLR, match_opcode, INSN_ALIAS },
Patrick Georgif0bbc952015-03-07 10:57:25 +01009313+{"srl", "I", "d,s,t", MATCH_SRL, MASK_SRL, match_opcode, WR_xd|RD_xs1|RD_xs2 },
9314+{"srl", "I", "d,s,>", MATCH_SRLI, MASK_SRLI, match_opcode, INSN_ALIAS|WR_xd|RD_xs1 },
Patrick Georgiaf473ed2015-07-17 23:35:54 +02009315+{"srai", "C", "CD,CU,C>", MATCH_C_SRAI, MASK_C_SRAI, match_rd_nonzero, INSN_ALIAS },
Patrick Georgif0bbc952015-03-07 10:57:25 +01009316+{"srai", "I", "d,s,>", MATCH_SRAI, MASK_SRAI, match_opcode, WR_xd|RD_xs1 },
Patrick Georgiaf473ed2015-07-17 23:35:54 +02009317+{"sra", "C", "CD,CU,C>", MATCH_C_SRAI, MASK_C_SRAI, match_rd_nonzero, INSN_ALIAS },
9318+{"sra", "32C", "Cs,Cw,Ct", MATCH_C_SRA, MASK_C_SRA, match_opcode, INSN_ALIAS },
Patrick Georgif0bbc952015-03-07 10:57:25 +01009319+{"sra", "I", "d,s,t", MATCH_SRA, MASK_SRA, match_opcode, WR_xd|RD_xs1|RD_xs2 },
9320+{"sra", "I", "d,s,>", MATCH_SRAI, MASK_SRAI, match_opcode, INSN_ALIAS|WR_xd|RD_xs1 },
Patrick Georgiaf473ed2015-07-17 23:35:54 +02009321+{"sub", "C", "CD,CU,CT", MATCH_C_SUB, MASK_C_SUB, match_rd_nonzero, INSN_ALIAS },
9322+{"sub", "C", "Cd,Cs,Ct", MATCH_C_SUB3, MASK_C_SUB3, match_opcode, INSN_ALIAS },
Patrick Georgif0bbc952015-03-07 10:57:25 +01009323+{"sub", "I", "d,s,t", MATCH_SUB, MASK_SUB, match_opcode, WR_xd|RD_xs1|RD_xs2 },
Patrick Georgif0bbc952015-03-07 10:57:25 +01009324+{"lb", "I", "d,o(s)", MATCH_LB, MASK_LB, match_opcode, WR_xd|RD_xs1 },
9325+{"lb", "I", "d,A", 0, (int) M_LB, match_never, INSN_MACRO },
9326+{"lbu", "I", "d,o(s)", MATCH_LBU, MASK_LBU, match_opcode, WR_xd|RD_xs1 },
9327+{"lbu", "I", "d,A", 0, (int) M_LBU, match_never, INSN_MACRO },
9328+{"lh", "I", "d,o(s)", MATCH_LH, MASK_LH, match_opcode, WR_xd|RD_xs1 },
9329+{"lh", "I", "d,A", 0, (int) M_LH, match_never, INSN_MACRO },
9330+{"lhu", "I", "d,o(s)", MATCH_LHU, MASK_LHU, match_opcode, WR_xd|RD_xs1 },
9331+{"lhu", "I", "d,A", 0, (int) M_LHU, match_never, INSN_MACRO },
Patrick Georgiaf473ed2015-07-17 23:35:54 +02009332+{"lw", "C", "CD,Cm(Cc)", MATCH_C_LWSP, MASK_C_LWSP, match_rd_nonzero, INSN_ALIAS },
9333+{"lw", "C", "Ct,Ck(Cs)", MATCH_C_LW, MASK_C_LW, match_opcode, INSN_ALIAS },
Patrick Georgif0bbc952015-03-07 10:57:25 +01009334+{"lw", "I", "d,o(s)", MATCH_LW, MASK_LW, match_opcode, WR_xd|RD_xs1 },
9335+{"lw", "I", "d,A", 0, (int) M_LW, match_never, INSN_MACRO },
Patrick Georgif0bbc952015-03-07 10:57:25 +01009336+{"not", "I", "d,s", MATCH_XORI | MASK_IMM, MASK_XORI | MASK_IMM, match_opcode, INSN_ALIAS|WR_xd|RD_xs1 },
Patrick Georgiaf473ed2015-07-17 23:35:54 +02009337+{"ori", "32C", "Ct,Cs,Ci", MATCH_C_ORIN, MASK_C_ORIN, match_opcode, INSN_ALIAS },
Patrick Georgif0bbc952015-03-07 10:57:25 +01009338+{"ori", "I", "d,s,j", MATCH_ORI, MASK_ORI, match_opcode, WR_xd|RD_xs1 },
Patrick Georgiaf473ed2015-07-17 23:35:54 +02009339+{"or", "C", "Cd,Cs,Ct", MATCH_C_OR3, MASK_C_OR3, match_opcode, INSN_ALIAS },
9340+{"or", "32C", "Ct,Cs,Ci", MATCH_C_ORIN, MASK_C_ORIN, match_opcode, INSN_ALIAS },
Patrick Georgif0bbc952015-03-07 10:57:25 +01009341+{"or", "I", "d,s,t", MATCH_OR, MASK_OR, match_opcode, WR_xd|RD_xs1|RD_xs2 },
9342+{"or", "I", "d,s,j", MATCH_ORI, MASK_ORI, match_opcode, INSN_ALIAS|WR_xd|RD_xs1 },
9343+{"auipc", "I", "d,u", MATCH_AUIPC, MASK_AUIPC, match_opcode, WR_xd },
9344+{"seqz", "I", "d,s", MATCH_SLTIU | ENCODE_ITYPE_IMM(1), MASK_SLTIU | MASK_IMM, match_opcode, INSN_ALIAS|WR_xd|RD_xs1 },
9345+{"snez", "I", "d,t", MATCH_SLTU, MASK_SLTU | MASK_RS1, match_opcode, INSN_ALIAS|WR_xd|RD_xs2 },
9346+{"sltz", "I", "d,s", MATCH_SLT, MASK_SLT | MASK_RS2, match_opcode, INSN_ALIAS|WR_xd|RD_xs1 },
9347+{"sgtz", "I", "d,t", MATCH_SLT, MASK_SLT | MASK_RS1, match_opcode, INSN_ALIAS|WR_xd|RD_xs2 },
9348+{"slti", "I", "d,s,j", MATCH_SLTI, MASK_SLTI, match_opcode, INSN_ALIAS|WR_xd|RD_xs1 },
Patrick Georgiaf473ed2015-07-17 23:35:54 +02009349+{"slt", "32C", "Cs,Cw,Ct", MATCH_C_SLT, MASK_C_SLT, match_opcode, INSN_ALIAS },
9350+{"slt", "32C", "Ct,Cs,Cx", MATCH_C_SLTR, MASK_C_SLTR, match_opcode, INSN_ALIAS },
Patrick Georgif0bbc952015-03-07 10:57:25 +01009351+{"slt", "I", "d,s,t", MATCH_SLT, MASK_SLT, match_opcode, WR_xd|RD_xs1|RD_xs2 },
9352+{"slt", "I", "d,s,j", MATCH_SLTI, MASK_SLTI, match_opcode, WR_xd|RD_xs1 },
9353+{"sltiu", "I", "d,s,j", MATCH_SLTIU, MASK_SLTIU, match_opcode, WR_xd|RD_xs1 },
Patrick Georgiaf473ed2015-07-17 23:35:54 +02009354+{"sltu", "32C", "Cs,Cw,Ct", MATCH_C_SLTU, MASK_C_SLTU, match_opcode, INSN_ALIAS },
9355+{"sltu", "32C", "Ct,Cs,Cx", MATCH_C_SLTUR, MASK_C_SLTUR, match_opcode, INSN_ALIAS },
Patrick Georgif0bbc952015-03-07 10:57:25 +01009356+{"sltu", "I", "d,s,t", MATCH_SLTU, MASK_SLTU, match_opcode, WR_xd|RD_xs1|RD_xs2 },
9357+{"sltu", "I", "d,s,j", MATCH_SLTIU, MASK_SLTIU, match_opcode, INSN_ALIAS|WR_xd|RD_xs1 },
9358+{"sgt", "I", "d,t,s", MATCH_SLT, MASK_SLT, match_opcode, INSN_ALIAS|WR_xd|RD_xs1|RD_xs2 },
9359+{"sgtu", "I", "d,t,s", MATCH_SLTU, MASK_SLTU, match_opcode, INSN_ALIAS|WR_xd|RD_xs1|RD_xs2 },
9360+{"sb", "I", "t,q(s)", MATCH_SB, MASK_SB, match_opcode, RD_xs1|RD_xs2 },
9361+{"sb", "I", "t,A,s", 0, (int) M_SB, match_never, INSN_MACRO },
9362+{"sh", "I", "t,q(s)", MATCH_SH, MASK_SH, match_opcode, RD_xs1|RD_xs2 },
9363+{"sh", "I", "t,A,s", 0, (int) M_SH, match_never, INSN_MACRO },
Patrick Georgiaf473ed2015-07-17 23:35:54 +02009364+{"sw", "C", "CV,CM(Cc)", MATCH_C_SWSP, MASK_C_SWSP, match_opcode, INSN_ALIAS },
9365+{"sw", "C", "Ct,Ck(Cs)", MATCH_C_SW, MASK_C_SW, match_opcode, INSN_ALIAS },
Patrick Georgif0bbc952015-03-07 10:57:25 +01009366+{"sw", "I", "t,q(s)", MATCH_SW, MASK_SW, match_opcode, RD_xs1|RD_xs2 },
9367+{"sw", "I", "t,A,s", 0, (int) M_SW, match_never, INSN_MACRO },
9368+{"fence", "I", "", MATCH_FENCE | MASK_PRED | MASK_SUCC, MASK_FENCE | MASK_RD | MASK_RS1 | MASK_IMM, match_opcode, INSN_ALIAS },
9369+{"fence", "I", "P,Q", MATCH_FENCE, MASK_FENCE | MASK_RD | MASK_RS1 | (MASK_IMM & ~MASK_PRED & ~MASK_SUCC), match_opcode, 0 },
9370+{"fence.i", "I", "", MATCH_FENCE_I, MASK_FENCE | MASK_RD | MASK_RS1 | MASK_IMM, match_opcode, 0 },
9371+{"rdcycle", "I", "d", MATCH_RDCYCLE, MASK_RDCYCLE, match_opcode, WR_xd },
9372+{"rdinstret", "I", "d", MATCH_RDINSTRET, MASK_RDINSTRET, match_opcode, WR_xd },
9373+{"rdtime", "I", "d", MATCH_RDTIME, MASK_RDTIME, match_opcode, WR_xd },
9374+{"rdcycleh", "32I", "d", MATCH_RDCYCLEH, MASK_RDCYCLEH, match_opcode, WR_xd },
9375+{"rdinstreth","32I", "d", MATCH_RDINSTRETH, MASK_RDINSTRETH, match_opcode, WR_xd },
9376+{"rdtimeh", "32I", "d", MATCH_RDTIMEH, MASK_RDTIMEH, match_opcode, WR_xd },
Patrick Georgiaf473ed2015-07-17 23:35:54 +02009377+{"ecall", "I", "", MATCH_SCALL, MASK_SCALL, match_opcode, 0 },
Patrick Georgif0bbc952015-03-07 10:57:25 +01009378+{"scall", "I", "", MATCH_SCALL, MASK_SCALL, match_opcode, 0 },
Patrick Georgiaf473ed2015-07-17 23:35:54 +02009379+{"xori", "32C", "Ct,Cs,Ci", MATCH_C_XORIN, MASK_C_XORIN, match_opcode, INSN_ALIAS },
Patrick Georgif0bbc952015-03-07 10:57:25 +01009380+{"xori", "I", "d,s,j", MATCH_XORI, MASK_XORI, match_opcode, WR_xd|RD_xs1 },
Patrick Georgiaf473ed2015-07-17 23:35:54 +02009381+{"xor", "32C", "Cs,Cw,Ct", MATCH_C_XOR, MASK_C_XOR, match_opcode, INSN_ALIAS },
9382+{"xor", "32C", "Cs,Ct,Cw", MATCH_C_XOR, MASK_C_XOR, match_opcode, INSN_ALIAS },
9383+{"xor", "32C", "Ct,Cs,Ci", MATCH_C_XORIN, MASK_C_XORIN, match_opcode, INSN_ALIAS },
Patrick Georgif0bbc952015-03-07 10:57:25 +01009384+{"xor", "I", "d,s,t", MATCH_XOR, MASK_XOR, match_opcode, WR_xd|RD_xs1|RD_xs2 },
9385+{"xor", "I", "d,s,j", MATCH_XORI, MASK_XORI, match_opcode, INSN_ALIAS|WR_xd|RD_xs1 },
9386+{"lwu", "64I", "d,o(s)", MATCH_LWU, MASK_LWU, match_opcode, WR_xd|RD_xs1 },
9387+{"lwu", "64I", "d,A", 0, (int) M_LWU, match_never, INSN_MACRO },
Patrick Georgiaf473ed2015-07-17 23:35:54 +02009388+{"ld", "64C", "CD,Cn(Cc)", MATCH_C_LDSP, MASK_C_LDSP, match_rd_nonzero, INSN_ALIAS },
9389+{"ld", "64C", "Ct,Cl(Cs)", MATCH_C_LD, MASK_C_LD, match_opcode, INSN_ALIAS },
Patrick Georgif0bbc952015-03-07 10:57:25 +01009390+{"ld", "64I", "d,o(s)", MATCH_LD, MASK_LD, match_opcode, WR_xd|RD_xs1 },
9391+{"ld", "64I", "d,A", 0, (int) M_LD, match_never, INSN_MACRO },
Patrick Georgiaf473ed2015-07-17 23:35:54 +02009392+{"sd", "64C", "CV,CN(Cc)", MATCH_C_SDSP, MASK_C_SDSP, match_opcode, INSN_ALIAS },
9393+{"sd", "64C", "Ct,Cl(Cs)", MATCH_C_SD, MASK_C_SD, match_opcode, INSN_ALIAS },
Patrick Georgif0bbc952015-03-07 10:57:25 +01009394+{"sd", "64I", "t,q(s)", MATCH_SD, MASK_SD, match_opcode, RD_xs1|RD_xs2 },
9395+{"sd", "64I", "t,A,s", 0, (int) M_SD, match_never, INSN_MACRO },
Patrick Georgiaf473ed2015-07-17 23:35:54 +02009396+{"sext.w", "64C", "CD,CU", MATCH_C_ADDIW, MASK_C_ADDIW | MASK_RVC_IMM, match_rd_nonzero, INSN_ALIAS },
Patrick Georgif0bbc952015-03-07 10:57:25 +01009397+{"sext.w", "64I", "d,s", MATCH_ADDIW, MASK_ADDIW | MASK_IMM, match_opcode, INSN_ALIAS|WR_xd|RD_xs1 },
Patrick Georgiaf473ed2015-07-17 23:35:54 +02009398+{"addiw", "64C", "CD,CU,Cj", MATCH_C_ADDIW, MASK_C_ADDIW, match_rd_nonzero, INSN_ALIAS },
Patrick Georgif0bbc952015-03-07 10:57:25 +01009399+{"addiw", "64I", "d,s,j", MATCH_ADDIW, MASK_ADDIW, match_opcode, WR_xd|RD_xs1 },
Patrick Georgiaf473ed2015-07-17 23:35:54 +02009400+{"addw", "64C", "CD,CU,CT", MATCH_C_ADDW, MASK_C_ADDW, match_rd_nonzero, INSN_ALIAS },
9401+{"addw", "64C", "CD,CT,CU", MATCH_C_ADDW, MASK_C_ADDW, match_rd_nonzero, INSN_ALIAS },
9402+{"addw", "64C", "CD,CU,Cj", MATCH_C_ADDIW, MASK_C_ADDIW, match_rd_nonzero, INSN_ALIAS },
Patrick Georgif0bbc952015-03-07 10:57:25 +01009403+{"addw", "64I", "d,s,t", MATCH_ADDW, MASK_ADDW, match_opcode, WR_xd|RD_xs1|RD_xs2 },
9404+{"addw", "64I", "d,s,j", MATCH_ADDIW, MASK_ADDIW, match_opcode, INSN_ALIAS|WR_xd|RD_xs1 },
9405+{"negw", "64I", "d,t", MATCH_SUBW, MASK_SUBW | MASK_RS1, match_opcode, INSN_ALIAS|WR_xd|RD_xs2 }, /* sub 0 */
Patrick Georgiaf473ed2015-07-17 23:35:54 +02009406+{"slliw", "64C", "CD,CU,C<", MATCH_C_SLLIW, MASK_C_SLLIW, match_rd_nonzero, INSN_ALIAS },
Patrick Georgif0bbc952015-03-07 10:57:25 +01009407+{"slliw", "64I", "d,s,<", MATCH_SLLIW, MASK_SLLIW, match_opcode, WR_xd|RD_xs1 },
Patrick Georgiaf473ed2015-07-17 23:35:54 +02009408+{"sllw", "64C", "CD,CU,C<", MATCH_C_SLLIW, MASK_C_SLLIW, match_rd_nonzero, INSN_ALIAS },
Patrick Georgif0bbc952015-03-07 10:57:25 +01009409+{"sllw", "64I", "d,s,t", MATCH_SLLW, MASK_SLLW, match_opcode, WR_xd|RD_xs1|RD_xs2 },
9410+{"sllw", "64I", "d,s,<", MATCH_SLLIW, MASK_SLLIW, match_opcode, INSN_ALIAS|WR_xd|RD_xs1 },
9411+{"srliw", "64I", "d,s,<", MATCH_SRLIW, MASK_SRLIW, match_opcode, WR_xd|RD_xs1 },
9412+{"srlw", "64I", "d,s,t", MATCH_SRLW, MASK_SRLW, match_opcode, WR_xd|RD_xs1|RD_xs2 },
9413+{"srlw", "64I", "d,s,<", MATCH_SRLIW, MASK_SRLIW, match_opcode, INSN_ALIAS|WR_xd|RD_xs1 },
9414+{"sraiw", "64I", "d,s,<", MATCH_SRAIW, MASK_SRAIW, match_opcode, WR_xd|RD_xs1 },
9415+{"sraw", "64I", "d,s,t", MATCH_SRAW, MASK_SRAW, match_opcode, WR_xd|RD_xs1|RD_xs2 },
9416+{"sraw", "64I", "d,s,<", MATCH_SRAIW, MASK_SRAIW, match_opcode, INSN_ALIAS|WR_xd|RD_xs1 },
9417+{"subw", "64I", "d,s,t", MATCH_SUBW, MASK_SUBW, match_opcode, WR_xd|RD_xs1|RD_xs2 },
9418+
Patrick Georgiaf473ed2015-07-17 23:35:54 +02009419+/* Compressed instructions */
9420+{"c.ebreak", "C", "", MATCH_C_EBREAK, MASK_C_EBREAK, match_opcode, 0 },
9421+{"c.jr", "C", "CD", MATCH_C_JR, MASK_C_JR, match_rd_nonzero, 0 },
9422+{"c.jalr", "C", "CD", MATCH_C_JALR, MASK_C_JALR, match_rd_nonzero, 0 },
9423+{"c.j", "C", "Ca", MATCH_C_J, MASK_C_J, match_opcode, 0 },
9424+{"c.jal", "C", "Ca", MATCH_C_JAL, MASK_C_JAL, match_opcode, 0 },
9425+{"c.beqz", "C", "Cs,Cp", MATCH_C_BEQZ, MASK_C_BEQZ, match_opcode, 0 },
9426+{"c.bnez", "C", "Cs,Cp", MATCH_C_BNEZ, MASK_C_BNEZ, match_opcode, 0 },
9427+{"c.lwsp", "C", "CD,Cm(Cc)", MATCH_C_LWSP, MASK_C_LWSP, match_rd_nonzero, 0 },
9428+{"c.lw", "C", "Ct,Ck(Cs)", MATCH_C_LW, MASK_C_LW, match_opcode, 0 },
9429+{"c.swsp", "C", "CV,CM(Cc)", MATCH_C_SWSP, MASK_C_SWSP, match_opcode, 0 },
9430+{"c.sw", "C", "Ct,Ck(Cs)", MATCH_C_SW, MASK_C_SW, match_opcode, 0 },
9431+{"c.nop", "C", "", MATCH_C_ADDI16SP, 0xffff, match_opcode, 0 },
9432+{"c.mv", "C", "CD,CV", MATCH_C_MV, MASK_C_MV, match_rd_nonzero, 0 },
9433+{"c.lui", "C", "CD,Cu", MATCH_C_LUI, MASK_C_LUI, match_rd_nonzero, 0 },
9434+{"c.li", "C", "CD,Cj", MATCH_C_LI, MASK_C_LI, match_rd_nonzero, 0 },
9435+{"c.addi4spn","C", "Ct,Cc,CK", MATCH_C_ADDI4SPN, MASK_C_ADDI4SPN, match_opcode, 0 },
9436+{"c.addi16sp","C", "Cc,CL", MATCH_C_ADDI16SP, MASK_C_ADDI16SP, match_opcode, 0 },
9437+{"c.addi", "C", "CD,Cj", MATCH_C_ADDI, MASK_C_ADDI, match_rd_nonzero, 0 },
9438+{"c.add", "C", "CD,CT", MATCH_C_ADD, MASK_C_ADD, match_rd_nonzero, 0 },
9439+{"c.sub", "C", "CD,CT", MATCH_C_SUB, MASK_C_SUB, match_rd_nonzero, 0 },
9440+{"c.add3", "C", "Cd,Cs,Ct", MATCH_C_ADD3, MASK_C_ADD3, match_opcode, 0 },
9441+{"c.sub3", "C", "Cd,Cs,Ct", MATCH_C_SUB3, MASK_C_SUB3, match_opcode, 0 },
9442+{"c.and3", "C", "Cd,Cs,Ct", MATCH_C_AND3, MASK_C_AND3, match_opcode, 0 },
9443+{"c.or3", "C", "Cd,Cs,Ct", MATCH_C_OR3, MASK_C_OR3, match_opcode, 0 },
9444+{"c.slli", "C", "CD,C>", MATCH_C_SLLI, MASK_C_SLLI, match_rd_nonzero, 0 },
9445+{"c.srli", "C", "CD,C>", MATCH_C_SRLI, MASK_C_SRLI, match_rd_nonzero, 0 },
9446+{"c.srai", "C", "CD,C>", MATCH_C_SRAI, MASK_C_SRAI, match_rd_nonzero, 0 },
9447+{"c.slliw", "64C", "CD,CU,C<", MATCH_C_SLLIW, MASK_C_SLLIW, match_rd_nonzero, 0 },
9448+{"c.addiw", "64C", "CD,Cj", MATCH_C_ADDIW, MASK_C_ADDIW, match_rd_nonzero, 0 },
9449+{"c.addw", "64C", "CD,CT", MATCH_C_ADDW, MASK_C_ADDW, match_rd_nonzero, 0 },
9450+{"c.ldsp", "64C", "CD,Cn(Cc)", MATCH_C_LDSP, MASK_C_LDSP, match_rd_nonzero, 0 },
9451+{"c.ld", "64C", "Ct,Cl(Cs)", MATCH_C_LD, MASK_C_LD, match_opcode, 0 },
9452+{"c.sdsp", "64C", "CV,CN(Cc)", MATCH_C_SDSP, MASK_C_SDSP, match_opcode, 0 },
9453+{"c.sd", "64C", "Ct,Cl(Cs)", MATCH_C_SD, MASK_C_SD, match_opcode, 0 },
9454+{"c.xor", "32C", "Cs,Ct", MATCH_C_XOR, MASK_C_XOR, match_opcode, 0 },
9455+{"c.sra", "32C", "Cs,Ct", MATCH_C_SRA, MASK_C_SRA, match_opcode, 0 },
9456+{"c.sll", "32C", "Cs,Ct", MATCH_C_SLL, MASK_C_SLL, match_opcode, 0 },
9457+{"c.srl", "32C", "Cs,Ct", MATCH_C_SRL, MASK_C_SRL, match_opcode, 0 },
9458+{"c.slt", "32C", "Cs,Ct", MATCH_C_SLT, MASK_C_SLT, match_opcode, 0 },
9459+{"c.sltu", "32C", "Cs,Ct", MATCH_C_SLTU, MASK_C_SLTU, match_opcode, 0 },
9460+{"c.sllr", "32C", "Ct,Cs", MATCH_C_SLLR, MASK_C_SLLR, match_opcode, 0 },
9461+{"c.srlr", "32C", "Ct,Cs", MATCH_C_SRLR, MASK_C_SRLR, match_opcode, 0 },
9462+{"c.sltr", "32C", "Ct,Cs", MATCH_C_SLTR, MASK_C_SLTR, match_opcode, 0 },
9463+{"c.sltur", "32C", "Ct,Cs", MATCH_C_SLTUR, MASK_C_SLTUR, match_opcode, 0 },
9464+{"c.addin", "32C", "Ct,Cs,Ci", MATCH_C_ADDIN, MASK_C_ADDIN, match_opcode, 0 },
9465+{"c.xorin", "32C", "Ct,Cs,Ci", MATCH_C_XORIN, MASK_C_XORIN, match_opcode, 0 },
9466+{"c.orin", "32C", "Ct,Cs,Ci", MATCH_C_ORIN, MASK_C_ORIN, match_opcode, 0 },
9467+{"c.andin", "32C", "Ct,Cs,Ci", MATCH_C_ANDIN, MASK_C_ANDIN, match_opcode, 0 },
9468+{"c.andi", "32C", "CD,Cj", MATCH_C_ANDI, MASK_C_ANDI, match_rd_nonzero, 0 },
9469+{"c.bltz", "32C", "Cs,Cp", MATCH_C_BLTZ, MASK_C_BLTZ, match_opcode, 0 },
9470+{"c.bgez", "32C", "Cs,Cp", MATCH_C_BGEZ, MASK_C_BGEZ, match_opcode, 0 },
9471+
Patrick Georgif0bbc952015-03-07 10:57:25 +01009472+/* Atomic memory operation instruction subset */
9473+{"lr.w", "A", "d,0(s)", MATCH_LR_W, MASK_LR_W | MASK_AQRL, match_opcode, WR_xd|RD_xs1 },
9474+{"sc.w", "A", "d,t,0(s)", MATCH_SC_W, MASK_SC_W | MASK_AQRL, match_opcode, WR_xd|RD_xs1|RD_xs2 },
9475+{"amoadd.w", "A", "d,t,0(s)", MATCH_AMOADD_W, MASK_AMOADD_W | MASK_AQRL, match_opcode, WR_xd|RD_xs1|RD_xs2 },
9476+{"amoswap.w", "A", "d,t,0(s)", MATCH_AMOSWAP_W, MASK_AMOSWAP_W | MASK_AQRL, match_opcode, WR_xd|RD_xs1|RD_xs2 },
9477+{"amoand.w", "A", "d,t,0(s)", MATCH_AMOAND_W, MASK_AMOAND_W | MASK_AQRL, match_opcode, WR_xd|RD_xs1|RD_xs2 },
9478+{"amoor.w", "A", "d,t,0(s)", MATCH_AMOOR_W, MASK_AMOOR_W | MASK_AQRL, match_opcode, WR_xd|RD_xs1|RD_xs2 },
9479+{"amoxor.w", "A", "d,t,0(s)", MATCH_AMOXOR_W, MASK_AMOXOR_W | MASK_AQRL, match_opcode, WR_xd|RD_xs1|RD_xs2 },
9480+{"amomax.w", "A", "d,t,0(s)", MATCH_AMOMAX_W, MASK_AMOMAX_W | MASK_AQRL, match_opcode, WR_xd|RD_xs1|RD_xs2 },
9481+{"amomaxu.w", "A", "d,t,0(s)", MATCH_AMOMAXU_W, MASK_AMOMAXU_W | MASK_AQRL, match_opcode, WR_xd|RD_xs1|RD_xs2 },
9482+{"amomin.w", "A", "d,t,0(s)", MATCH_AMOMIN_W, MASK_AMOMIN_W | MASK_AQRL, match_opcode, WR_xd|RD_xs1|RD_xs2 },
9483+{"amominu.w", "A", "d,t,0(s)", MATCH_AMOMINU_W, MASK_AMOMINU_W | MASK_AQRL, match_opcode, WR_xd|RD_xs1|RD_xs2 },
9484+{"lr.w.aq", "A", "d,0(s)", MATCH_LR_W | MASK_AQ, MASK_LR_W | MASK_AQRL, match_opcode, WR_xd|RD_xs1 },
9485+{"sc.w.aq", "A", "d,t,0(s)", MATCH_SC_W | MASK_AQ, MASK_SC_W | MASK_AQRL, match_opcode, WR_xd|RD_xs1|RD_xs2 },
9486+{"amoadd.w.aq", "A", "d,t,0(s)", MATCH_AMOADD_W | MASK_AQ, MASK_AMOADD_W | MASK_AQRL, match_opcode, WR_xd|RD_xs1|RD_xs2 },
9487+{"amoswap.w.aq", "A", "d,t,0(s)", MATCH_AMOSWAP_W | MASK_AQ, MASK_AMOSWAP_W | MASK_AQRL, match_opcode, WR_xd|RD_xs1|RD_xs2 },
9488+{"amoand.w.aq", "A", "d,t,0(s)", MATCH_AMOAND_W | MASK_AQ, MASK_AMOAND_W | MASK_AQRL, match_opcode, WR_xd|RD_xs1|RD_xs2 },
9489+{"amoor.w.aq", "A", "d,t,0(s)", MATCH_AMOOR_W | MASK_AQ, MASK_AMOOR_W | MASK_AQRL, match_opcode, WR_xd|RD_xs1|RD_xs2 },
9490+{"amoxor.w.aq", "A", "d,t,0(s)", MATCH_AMOXOR_W | MASK_AQ, MASK_AMOXOR_W | MASK_AQRL, match_opcode, WR_xd|RD_xs1|RD_xs2 },
9491+{"amomax.w.aq", "A", "d,t,0(s)", MATCH_AMOMAX_W | MASK_AQ, MASK_AMOMAX_W | MASK_AQRL, match_opcode, WR_xd|RD_xs1|RD_xs2 },
9492+{"amomaxu.w.aq", "A", "d,t,0(s)", MATCH_AMOMAXU_W | MASK_AQ, MASK_AMOMAXU_W | MASK_AQRL, match_opcode, WR_xd|RD_xs1|RD_xs2 },
9493+{"amomin.w.aq", "A", "d,t,0(s)", MATCH_AMOMIN_W | MASK_AQ, MASK_AMOMIN_W | MASK_AQRL, match_opcode, WR_xd|RD_xs1|RD_xs2 },
9494+{"amominu.w.aq", "A", "d,t,0(s)", MATCH_AMOMINU_W | MASK_AQ, MASK_AMOMINU_W | MASK_AQRL, match_opcode, WR_xd|RD_xs1|RD_xs2 },
9495+{"lr.w.rl", "A", "d,0(s)", MATCH_LR_W | MASK_RL, MASK_LR_W | MASK_AQRL, match_opcode, WR_xd|RD_xs1 },
9496+{"sc.w.rl", "A", "d,t,0(s)", MATCH_SC_W | MASK_RL, MASK_SC_W | MASK_AQRL, match_opcode, WR_xd|RD_xs1|RD_xs2 },
9497+{"amoadd.w.rl", "A", "d,t,0(s)", MATCH_AMOADD_W | MASK_RL, MASK_AMOADD_W | MASK_AQRL, match_opcode, WR_xd|RD_xs1|RD_xs2 },
9498+{"amoswap.w.rl", "A", "d,t,0(s)", MATCH_AMOSWAP_W | MASK_RL, MASK_AMOSWAP_W | MASK_AQRL, match_opcode, WR_xd|RD_xs1|RD_xs2 },
9499+{"amoand.w.rl", "A", "d,t,0(s)", MATCH_AMOAND_W | MASK_RL, MASK_AMOAND_W | MASK_AQRL, match_opcode, WR_xd|RD_xs1|RD_xs2 },
9500+{"amoor.w.rl", "A", "d,t,0(s)", MATCH_AMOOR_W | MASK_RL, MASK_AMOOR_W | MASK_AQRL, match_opcode, WR_xd|RD_xs1|RD_xs2 },
9501+{"amoxor.w.rl", "A", "d,t,0(s)", MATCH_AMOXOR_W | MASK_RL, MASK_AMOXOR_W | MASK_AQRL, match_opcode, WR_xd|RD_xs1|RD_xs2 },
9502+{"amomax.w.rl", "A", "d,t,0(s)", MATCH_AMOMAX_W | MASK_RL, MASK_AMOMAX_W | MASK_AQRL, match_opcode, WR_xd|RD_xs1|RD_xs2 },
9503+{"amomaxu.w.rl", "A", "d,t,0(s)", MATCH_AMOMAXU_W | MASK_RL, MASK_AMOMAXU_W | MASK_AQRL, match_opcode, WR_xd|RD_xs1|RD_xs2 },
9504+{"amomin.w.rl", "A", "d,t,0(s)", MATCH_AMOMIN_W | MASK_RL, MASK_AMOMIN_W | MASK_AQRL, match_opcode, WR_xd|RD_xs1|RD_xs2 },
9505+{"amominu.w.rl", "A", "d,t,0(s)", MATCH_AMOMINU_W | MASK_RL, MASK_AMOMINU_W | MASK_AQRL, match_opcode, WR_xd|RD_xs1|RD_xs2 },
9506+{"lr.w.sc", "A", "d,0(s)", MATCH_LR_W | MASK_AQRL, MASK_LR_W | MASK_AQRL, match_opcode, WR_xd|RD_xs1 },
9507+{"sc.w.sc", "A", "d,t,0(s)", MATCH_SC_W | MASK_AQRL, MASK_SC_W | MASK_AQRL, match_opcode, WR_xd|RD_xs1|RD_xs2 },
9508+{"amoadd.w.sc", "A", "d,t,0(s)", MATCH_AMOADD_W | MASK_AQRL, MASK_AMOADD_W | MASK_AQRL, match_opcode, WR_xd|RD_xs1|RD_xs2 },
9509+{"amoswap.w.sc", "A", "d,t,0(s)", MATCH_AMOSWAP_W | MASK_AQRL, MASK_AMOSWAP_W | MASK_AQRL, match_opcode, WR_xd|RD_xs1|RD_xs2 },
9510+{"amoand.w.sc", "A", "d,t,0(s)", MATCH_AMOAND_W | MASK_AQRL, MASK_AMOAND_W | MASK_AQRL, match_opcode, WR_xd|RD_xs1|RD_xs2 },
9511+{"amoor.w.sc", "A", "d,t,0(s)", MATCH_AMOOR_W | MASK_AQRL, MASK_AMOOR_W | MASK_AQRL, match_opcode, WR_xd|RD_xs1|RD_xs2 },
9512+{"amoxor.w.sc", "A", "d,t,0(s)", MATCH_AMOXOR_W | MASK_AQRL, MASK_AMOXOR_W | MASK_AQRL, match_opcode, WR_xd|RD_xs1|RD_xs2 },
9513+{"amomax.w.sc", "A", "d,t,0(s)", MATCH_AMOMAX_W | MASK_AQRL, MASK_AMOMAX_W | MASK_AQRL, match_opcode, WR_xd|RD_xs1|RD_xs2 },
9514+{"amomaxu.w.sc", "A", "d,t,0(s)", MATCH_AMOMAXU_W | MASK_AQRL, MASK_AMOMAXU_W | MASK_AQRL, match_opcode, WR_xd|RD_xs1|RD_xs2 },
9515+{"amomin.w.sc", "A", "d,t,0(s)", MATCH_AMOMIN_W | MASK_AQRL, MASK_AMOMIN_W | MASK_AQRL, match_opcode, WR_xd|RD_xs1|RD_xs2 },
9516+{"amominu.w.sc", "A", "d,t,0(s)", MATCH_AMOMINU_W | MASK_AQRL, MASK_AMOMINU_W | MASK_AQRL, match_opcode, WR_xd|RD_xs1|RD_xs2 },
9517+{"lr.d", "64A", "d,0(s)", MATCH_LR_D, MASK_LR_D | MASK_AQRL, match_opcode, WR_xd|RD_xs1 },
9518+{"sc.d", "64A", "d,t,0(s)", MATCH_SC_D, MASK_SC_D | MASK_AQRL, match_opcode, WR_xd|RD_xs1|RD_xs2 },
9519+{"amoadd.d", "64A", "d,t,0(s)", MATCH_AMOADD_D, MASK_AMOADD_D | MASK_AQRL, match_opcode, WR_xd|RD_xs1|RD_xs2 },
9520+{"amoswap.d", "64A", "d,t,0(s)", MATCH_AMOSWAP_D, MASK_AMOSWAP_D | MASK_AQRL, match_opcode, WR_xd|RD_xs1|RD_xs2 },
9521+{"amoand.d", "64A", "d,t,0(s)", MATCH_AMOAND_D, MASK_AMOAND_D | MASK_AQRL, match_opcode, WR_xd|RD_xs1|RD_xs2 },
9522+{"amoor.d", "64A", "d,t,0(s)", MATCH_AMOOR_D, MASK_AMOOR_D | MASK_AQRL, match_opcode, WR_xd|RD_xs1|RD_xs2 },
9523+{"amoxor.d", "64A", "d,t,0(s)", MATCH_AMOXOR_D, MASK_AMOXOR_D | MASK_AQRL, match_opcode, WR_xd|RD_xs1|RD_xs2 },
9524+{"amomax.d", "64A", "d,t,0(s)", MATCH_AMOMAX_D, MASK_AMOMAX_D | MASK_AQRL, match_opcode, WR_xd|RD_xs1|RD_xs2 },
9525+{"amomaxu.d", "64A", "d,t,0(s)", MATCH_AMOMAXU_D, MASK_AMOMAXU_D | MASK_AQRL, match_opcode, WR_xd|RD_xs1|RD_xs2 },
9526+{"amomin.d", "64A", "d,t,0(s)", MATCH_AMOMIN_D, MASK_AMOMIN_D | MASK_AQRL, match_opcode, WR_xd|RD_xs1|RD_xs2 },
9527+{"amominu.d", "64A", "d,t,0(s)", MATCH_AMOMINU_D, MASK_AMOMINU_D | MASK_AQRL, match_opcode, WR_xd|RD_xs1|RD_xs2 },
9528+{"lr.d.aq", "64A", "d,0(s)", MATCH_LR_D | MASK_AQ, MASK_LR_D | MASK_AQRL, match_opcode, WR_xd|RD_xs1 },
9529+{"sc.d.aq", "64A", "d,t,0(s)", MATCH_SC_D | MASK_AQ, MASK_SC_D | MASK_AQRL, match_opcode, WR_xd|RD_xs1|RD_xs2 },
9530+{"amoadd.d.aq", "64A", "d,t,0(s)", MATCH_AMOADD_D | MASK_AQ, MASK_AMOADD_D | MASK_AQRL, match_opcode, WR_xd|RD_xs1|RD_xs2 },
9531+{"amoswap.d.aq", "64A", "d,t,0(s)", MATCH_AMOSWAP_D | MASK_AQ, MASK_AMOSWAP_D | MASK_AQRL, match_opcode, WR_xd|RD_xs1|RD_xs2 },
9532+{"amoand.d.aq", "64A", "d,t,0(s)", MATCH_AMOAND_D | MASK_AQ, MASK_AMOAND_D | MASK_AQRL, match_opcode, WR_xd|RD_xs1|RD_xs2 },
9533+{"amoor.d.aq", "64A", "d,t,0(s)", MATCH_AMOOR_D | MASK_AQ, MASK_AMOOR_D | MASK_AQRL, match_opcode, WR_xd|RD_xs1|RD_xs2 },
9534+{"amoxor.d.aq", "64A", "d,t,0(s)", MATCH_AMOXOR_D | MASK_AQ, MASK_AMOXOR_D | MASK_AQRL, match_opcode, WR_xd|RD_xs1|RD_xs2 },
9535+{"amomax.d.aq", "64A", "d,t,0(s)", MATCH_AMOMAX_D | MASK_AQ, MASK_AMOMAX_D | MASK_AQRL, match_opcode, WR_xd|RD_xs1|RD_xs2 },
9536+{"amomaxu.d.aq", "64A", "d,t,0(s)", MATCH_AMOMAXU_D | MASK_AQ, MASK_AMOMAXU_D | MASK_AQRL, match_opcode, WR_xd|RD_xs1|RD_xs2 },
9537+{"amomin.d.aq", "64A", "d,t,0(s)", MATCH_AMOMIN_D | MASK_AQ, MASK_AMOMIN_D | MASK_AQRL, match_opcode, WR_xd|RD_xs1|RD_xs2 },
9538+{"amominu.d.aq", "64A", "d,t,0(s)", MATCH_AMOMINU_D | MASK_AQ, MASK_AMOMINU_D | MASK_AQRL, match_opcode, WR_xd|RD_xs1|RD_xs2 },
9539+{"lr.d.rl", "64A", "d,0(s)", MATCH_LR_D | MASK_RL, MASK_LR_D | MASK_AQRL, match_opcode, WR_xd|RD_xs1 },
9540+{"sc.d.rl", "64A", "d,t,0(s)", MATCH_SC_D | MASK_RL, MASK_SC_D | MASK_AQRL, match_opcode, WR_xd|RD_xs1|RD_xs2 },
9541+{"amoadd.d.rl", "64A", "d,t,0(s)", MATCH_AMOADD_D | MASK_RL, MASK_AMOADD_D | MASK_AQRL, match_opcode, WR_xd|RD_xs1|RD_xs2 },
9542+{"amoswap.d.rl", "64A", "d,t,0(s)", MATCH_AMOSWAP_D | MASK_RL, MASK_AMOSWAP_D | MASK_AQRL, match_opcode, WR_xd|RD_xs1|RD_xs2 },
9543+{"amoand.d.rl", "64A", "d,t,0(s)", MATCH_AMOAND_D | MASK_RL, MASK_AMOAND_D | MASK_AQRL, match_opcode, WR_xd|RD_xs1|RD_xs2 },
9544+{"amoor.d.rl", "64A", "d,t,0(s)", MATCH_AMOOR_D | MASK_RL, MASK_AMOOR_D | MASK_AQRL, match_opcode, WR_xd|RD_xs1|RD_xs2 },
9545+{"amoxor.d.rl", "64A", "d,t,0(s)", MATCH_AMOXOR_D | MASK_RL, MASK_AMOXOR_D | MASK_AQRL, match_opcode, WR_xd|RD_xs1|RD_xs2 },
9546+{"amomax.d.rl", "64A", "d,t,0(s)", MATCH_AMOMAX_D | MASK_RL, MASK_AMOMAX_D | MASK_AQRL, match_opcode, WR_xd|RD_xs1|RD_xs2 },
9547+{"amomaxu.d.rl", "64A", "d,t,0(s)", MATCH_AMOMAXU_D | MASK_RL, MASK_AMOMAXU_D | MASK_AQRL, match_opcode, WR_xd|RD_xs1|RD_xs2 },
9548+{"amomin.d.rl", "64A", "d,t,0(s)", MATCH_AMOMIN_D | MASK_RL, MASK_AMOMIN_D | MASK_AQRL, match_opcode, WR_xd|RD_xs1|RD_xs2 },
9549+{"amominu.d.rl", "64A", "d,t,0(s)", MATCH_AMOMINU_D | MASK_RL, MASK_AMOMINU_D | MASK_AQRL, match_opcode, WR_xd|RD_xs1|RD_xs2 },
9550+{"lr.d.sc", "64A", "d,0(s)", MATCH_LR_D | MASK_AQRL, MASK_LR_D | MASK_AQRL, match_opcode, WR_xd|RD_xs1 },
9551+{"sc.d.sc", "64A", "d,t,0(s)", MATCH_SC_D | MASK_AQRL, MASK_SC_D | MASK_AQRL, match_opcode, WR_xd|RD_xs1|RD_xs2 },
9552+{"amoadd.d.sc", "64A", "d,t,0(s)", MATCH_AMOADD_D | MASK_AQRL, MASK_AMOADD_D | MASK_AQRL, match_opcode, WR_xd|RD_xs1|RD_xs2 },
9553+{"amoswap.d.sc", "64A", "d,t,0(s)", MATCH_AMOSWAP_D | MASK_AQRL, MASK_AMOSWAP_D | MASK_AQRL, match_opcode, WR_xd|RD_xs1|RD_xs2 },
9554+{"amoand.d.sc", "64A", "d,t,0(s)", MATCH_AMOAND_D | MASK_AQRL, MASK_AMOAND_D | MASK_AQRL, match_opcode, WR_xd|RD_xs1|RD_xs2 },
9555+{"amoor.d.sc", "64A", "d,t,0(s)", MATCH_AMOOR_D | MASK_AQRL, MASK_AMOOR_D | MASK_AQRL, match_opcode, WR_xd|RD_xs1|RD_xs2 },
9556+{"amoxor.d.sc", "64A", "d,t,0(s)", MATCH_AMOXOR_D | MASK_AQRL, MASK_AMOXOR_D | MASK_AQRL, match_opcode, WR_xd|RD_xs1|RD_xs2 },
9557+{"amomax.d.sc", "64A", "d,t,0(s)", MATCH_AMOMAX_D | MASK_AQRL, MASK_AMOMAX_D | MASK_AQRL, match_opcode, WR_xd|RD_xs1|RD_xs2 },
9558+{"amomaxu.d.sc", "64A", "d,t,0(s)", MATCH_AMOMAXU_D | MASK_AQRL, MASK_AMOMAXU_D | MASK_AQRL, match_opcode, WR_xd|RD_xs1|RD_xs2 },
9559+{"amomin.d.sc", "64A", "d,t,0(s)", MATCH_AMOMIN_D | MASK_AQRL, MASK_AMOMIN_D | MASK_AQRL, match_opcode, WR_xd|RD_xs1|RD_xs2 },
9560+{"amominu.d.sc", "64A", "d,t,0(s)", MATCH_AMOMINU_D | MASK_AQRL, MASK_AMOMINU_D | MASK_AQRL, match_opcode, WR_xd|RD_xs1|RD_xs2 },
9561+
9562+/* Multiply/Divide instruction subset */
9563+{"mul", "M", "d,s,t", MATCH_MUL, MASK_MUL, match_opcode, WR_xd|RD_xs1|RD_xs2 },
9564+{"mulh", "M", "d,s,t", MATCH_MULH, MASK_MULH, match_opcode, WR_xd|RD_xs1|RD_xs2 },
9565+{"mulhu", "M", "d,s,t", MATCH_MULHU, MASK_MULHU, match_opcode, WR_xd|RD_xs1|RD_xs2 },
9566+{"mulhsu", "M", "d,s,t", MATCH_MULHSU, MASK_MULHSU, match_opcode, WR_xd|RD_xs1|RD_xs2 },
9567+{"div", "M", "d,s,t", MATCH_DIV, MASK_DIV, match_opcode, WR_xd|RD_xs1|RD_xs2 },
9568+{"divu", "M", "d,s,t", MATCH_DIVU, MASK_DIVU, match_opcode, WR_xd|RD_xs1|RD_xs2 },
9569+{"rem", "M", "d,s,t", MATCH_REM, MASK_REM, match_opcode, WR_xd|RD_xs1|RD_xs2 },
9570+{"remu", "M", "d,s,t", MATCH_REMU, MASK_REMU, match_opcode, WR_xd|RD_xs1|RD_xs2 },
9571+{"mulw", "64M", "d,s,t", MATCH_MULW, MASK_MULW, match_opcode, WR_xd|RD_xs1|RD_xs2 },
9572+{"divw", "64M", "d,s,t", MATCH_DIVW, MASK_DIVW, match_opcode, WR_xd|RD_xs1|RD_xs2 },
9573+{"divuw", "64M", "d,s,t", MATCH_DIVUW, MASK_DIVUW, match_opcode, WR_xd|RD_xs1|RD_xs2 },
9574+{"remw", "64M", "d,s,t", MATCH_REMW, MASK_REMW, match_opcode, WR_xd|RD_xs1|RD_xs2 },
9575+{"remuw", "64M", "d,s,t", MATCH_REMUW, MASK_REMUW, match_opcode, WR_xd|RD_xs1|RD_xs2 },
9576+
9577+/* Single-precision floating-point instruction subset */
9578+{"frsr", "F", "d", MATCH_FRCSR, MASK_FRCSR, match_opcode, WR_xd },
9579+{"fssr", "F", "s", MATCH_FSCSR, MASK_FSCSR | MASK_RD, match_opcode, RD_xs1 },
9580+{"fssr", "F", "d,s", MATCH_FSCSR, MASK_FSCSR, match_opcode, WR_xd|RD_xs1 },
9581+{"frcsr", "F", "d", MATCH_FRCSR, MASK_FRCSR, match_opcode, WR_xd },
9582+{"fscsr", "F", "s", MATCH_FSCSR, MASK_FSCSR | MASK_RD, match_opcode, RD_xs1 },
9583+{"fscsr", "F", "d,s", MATCH_FSCSR, MASK_FSCSR, match_opcode, WR_xd|RD_xs1 },
9584+{"frrm", "F", "d", MATCH_FRRM, MASK_FRRM, match_opcode, WR_xd },
9585+{"fsrm", "F", "s", MATCH_FSRM, MASK_FSRM | MASK_RD, match_opcode, RD_xs1 },
9586+{"fsrm", "F", "d,s", MATCH_FSRM, MASK_FSRM, match_opcode, WR_xd|RD_xs1 },
9587+{"frflags", "F", "d", MATCH_FRFLAGS, MASK_FRFLAGS, match_opcode, WR_xd },
9588+{"fsflags", "F", "s", MATCH_FSFLAGS, MASK_FSFLAGS | MASK_RD, match_opcode, RD_xs1 },
9589+{"fsflags", "F", "d,s", MATCH_FSFLAGS, MASK_FSFLAGS, match_opcode, WR_xd|RD_xs1 },
9590+{"flw", "F", "D,o(s)", MATCH_FLW, MASK_FLW, match_opcode, WR_fd|RD_xs1 },
9591+{"flw", "F", "D,A,s", 0, (int) M_FLW, match_never, INSN_MACRO },
9592+{"fsw", "F", "T,q(s)", MATCH_FSW, MASK_FSW, match_opcode, RD_xs1|RD_fs2 },
9593+{"fsw", "F", "T,A,s", 0, (int) M_FSW, match_never, INSN_MACRO },
9594+{"fmv.x.s", "F", "d,S", MATCH_FMV_X_S, MASK_FMV_X_S, match_opcode, WR_xd|RD_fs1 },
9595+{"fmv.s.x", "F", "D,s", MATCH_FMV_S_X, MASK_FMV_S_X, match_opcode, WR_fd|RD_xs1 },
9596+{"fmv.s", "F", "D,U", MATCH_FSGNJ_S, MASK_FSGNJ_S, match_rs1_eq_rs2, INSN_ALIAS|WR_fd|RD_fs1|RD_fs2 },
9597+{"fneg.s", "F", "D,U", MATCH_FSGNJN_S, MASK_FSGNJN_S, match_rs1_eq_rs2, INSN_ALIAS|WR_fd|RD_fs1|RD_fs2 },
9598+{"fabs.s", "F", "D,U", MATCH_FSGNJX_S, MASK_FSGNJX_S, match_rs1_eq_rs2, INSN_ALIAS|WR_fd|RD_fs1|RD_fs2 },
9599+{"fsgnj.s", "F", "D,S,T", MATCH_FSGNJ_S, MASK_FSGNJ_S, match_opcode, WR_fd|RD_fs1|RD_fs2 },
9600+{"fsgnjn.s", "F", "D,S,T", MATCH_FSGNJN_S, MASK_FSGNJN_S, match_opcode, WR_fd|RD_fs1|RD_fs2 },
9601+{"fsgnjx.s", "F", "D,S,T", MATCH_FSGNJX_S, MASK_FSGNJX_S, match_opcode, WR_fd|RD_fs1|RD_fs2 },
9602+{"fadd.s", "F", "D,S,T", MATCH_FADD_S | MASK_RM, MASK_FADD_S | MASK_RM, match_opcode, WR_fd|RD_fs1|RD_fs2 },
9603+{"fadd.s", "F", "D,S,T,m", MATCH_FADD_S, MASK_FADD_S, match_opcode, WR_fd|RD_fs1|RD_fs2 },
9604+{"fsub.s", "F", "D,S,T", MATCH_FSUB_S | MASK_RM, MASK_FSUB_S | MASK_RM, match_opcode, WR_fd|RD_fs1|RD_fs2 },
9605+{"fsub.s", "F", "D,S,T,m", MATCH_FSUB_S, MASK_FSUB_S, match_opcode, WR_fd|RD_fs1|RD_fs2 },
9606+{"fmul.s", "F", "D,S,T", MATCH_FMUL_S | MASK_RM, MASK_FMUL_S | MASK_RM, match_opcode, WR_fd|RD_fs1|RD_fs2 },
9607+{"fmul.s", "F", "D,S,T,m", MATCH_FMUL_S, MASK_FMUL_S, match_opcode, WR_fd|RD_fs1|RD_fs2 },
9608+{"fdiv.s", "F", "D,S,T", MATCH_FDIV_S | MASK_RM, MASK_FDIV_S | MASK_RM, match_opcode, WR_fd|RD_fs1|RD_fs2 },
9609+{"fdiv.s", "F", "D,S,T,m", MATCH_FDIV_S, MASK_FDIV_S, match_opcode, WR_fd|RD_fs1|RD_fs2 },
9610+{"fsqrt.s", "F", "D,S", MATCH_FSQRT_S | MASK_RM, MASK_FSQRT_S | MASK_RM, match_opcode, WR_fd|RD_fs1 },
9611+{"fsqrt.s", "F", "D,S,m", MATCH_FSQRT_S, MASK_FSQRT_S, match_opcode, WR_fd|RD_fs1 },
9612+{"fmin.s", "F", "D,S,T", MATCH_FMIN_S, MASK_FMIN_S, match_opcode, WR_fd|RD_fs1|RD_fs2 },
9613+{"fmax.s", "F", "D,S,T", MATCH_FMAX_S, MASK_FMAX_S, match_opcode, WR_fd|RD_fs1|RD_fs2 },
9614+{"fmadd.s", "F", "D,S,T,R", MATCH_FMADD_S | MASK_RM, MASK_FMADD_S | MASK_RM, match_opcode, WR_fd|RD_fs1|RD_fs2|RD_fs3 },
9615+{"fmadd.s", "F", "D,S,T,R,m", MATCH_FMADD_S, MASK_FMADD_S, match_opcode, WR_fd|RD_fs1|RD_fs2|RD_fs3 },
9616+{"fnmadd.s", "F", "D,S,T,R", MATCH_FNMADD_S | MASK_RM, MASK_FNMADD_S | MASK_RM, match_opcode, WR_fd|RD_fs1|RD_fs2|RD_fs3 },
9617+{"fnmadd.s", "F", "D,S,T,R,m", MATCH_FNMADD_S, MASK_FNMADD_S, match_opcode, WR_fd|RD_fs1|RD_fs2|RD_fs3 },
9618+{"fmsub.s", "F", "D,S,T,R", MATCH_FMSUB_S | MASK_RM, MASK_FMSUB_S | MASK_RM, match_opcode, WR_fd|RD_fs1|RD_fs2|RD_fs3 },
9619+{"fmsub.s", "F", "D,S,T,R,m", MATCH_FMSUB_S, MASK_FMSUB_S, match_opcode, WR_fd|RD_fs1|RD_fs2|RD_fs3 },
9620+{"fnmsub.s", "F", "D,S,T,R", MATCH_FNMSUB_S | MASK_RM, MASK_FNMSUB_S | MASK_RM, match_opcode, WR_fd|RD_fs1|RD_fs2|RD_fs3 },
9621+{"fnmsub.s", "F", "D,S,T,R,m", MATCH_FNMSUB_S, MASK_FNMSUB_S, match_opcode, WR_fd|RD_fs1|RD_fs2|RD_fs3 },
9622+{"fcvt.w.s", "F", "d,S", MATCH_FCVT_W_S | MASK_RM, MASK_FCVT_W_S | MASK_RM, match_opcode, WR_xd|RD_fs1 },
9623+{"fcvt.w.s", "F", "d,S,m", MATCH_FCVT_W_S, MASK_FCVT_W_S, match_opcode, WR_xd|RD_fs1 },
9624+{"fcvt.wu.s", "F", "d,S", MATCH_FCVT_WU_S | MASK_RM, MASK_FCVT_WU_S | MASK_RM, match_opcode, WR_xd|RD_fs1 },
9625+{"fcvt.wu.s", "F", "d,S,m", MATCH_FCVT_WU_S, MASK_FCVT_WU_S, match_opcode, WR_xd|RD_fs1 },
9626+{"fcvt.s.w", "F", "D,s", MATCH_FCVT_S_W | MASK_RM, MASK_FCVT_S_W | MASK_RM, match_opcode, WR_fd|RD_xs1 },
9627+{"fcvt.s.w", "F", "D,s,m", MATCH_FCVT_S_W, MASK_FCVT_S_W, match_opcode, WR_fd|RD_xs1 },
9628+{"fcvt.s.wu", "F", "D,s", MATCH_FCVT_S_WU | MASK_RM, MASK_FCVT_S_W | MASK_RM, match_opcode, WR_fd|RD_xs1 },
9629+{"fcvt.s.wu", "F", "D,s,m", MATCH_FCVT_S_WU, MASK_FCVT_S_WU, match_opcode, WR_fd|RD_xs1 },
9630+{"fclass.s", "F", "d,S", MATCH_FCLASS_S, MASK_FCLASS_S, match_opcode, WR_xd|RD_fs1 },
9631+{"feq.s", "F", "d,S,T", MATCH_FEQ_S, MASK_FEQ_S, match_opcode, WR_xd|RD_fs1|RD_fs2 },
9632+{"flt.s", "F", "d,S,T", MATCH_FLT_S, MASK_FLT_S, match_opcode, WR_xd|RD_fs1|RD_fs2 },
9633+{"fle.s", "F", "d,S,T", MATCH_FLE_S, MASK_FLE_S, match_opcode, WR_xd|RD_fs1|RD_fs2 },
9634+{"fgt.s", "F", "d,T,S", MATCH_FLT_S, MASK_FLT_S, match_opcode, WR_xd|RD_fs1|RD_fs2 },
9635+{"fge.s", "F", "d,T,S", MATCH_FLE_S, MASK_FLE_S, match_opcode, WR_xd|RD_fs1|RD_fs2 },
9636+{"fcvt.l.s", "64F", "d,S", MATCH_FCVT_L_S | MASK_RM, MASK_FCVT_L_S | MASK_RM, match_opcode, WR_xd|RD_fs1 },
9637+{"fcvt.l.s", "64F", "d,S,m", MATCH_FCVT_L_S, MASK_FCVT_L_S, match_opcode, WR_xd|RD_fs1 },
9638+{"fcvt.lu.s", "64F", "d,S", MATCH_FCVT_LU_S | MASK_RM, MASK_FCVT_LU_S | MASK_RM, match_opcode, WR_xd|RD_fs1 },
9639+{"fcvt.lu.s", "64F", "d,S,m", MATCH_FCVT_LU_S, MASK_FCVT_LU_S, match_opcode, WR_xd|RD_fs1 },
9640+{"fcvt.s.l", "64F", "D,s", MATCH_FCVT_S_L | MASK_RM, MASK_FCVT_S_L | MASK_RM, match_opcode, WR_fd|RD_xs1 },
9641+{"fcvt.s.l", "64F", "D,s,m", MATCH_FCVT_S_L, MASK_FCVT_S_L, match_opcode, WR_fd|RD_xs1 },
9642+{"fcvt.s.lu", "64F", "D,s", MATCH_FCVT_S_LU | MASK_RM, MASK_FCVT_S_L | MASK_RM, match_opcode, WR_fd|RD_xs1 },
9643+{"fcvt.s.lu", "64F", "D,s,m", MATCH_FCVT_S_LU, MASK_FCVT_S_LU, match_opcode, WR_fd|RD_xs1 },
9644+
9645+/* Double-precision floating-point instruction subset */
9646+{"fld", "D", "D,o(s)", MATCH_FLD, MASK_FLD, match_opcode, WR_fd|RD_xs1 },
9647+{"fld", "D", "D,A,s", 0, (int) M_FLD, match_never, INSN_MACRO },
9648+{"fsd", "D", "T,q(s)", MATCH_FSD, MASK_FSD, match_opcode, RD_xs1|RD_fs2 },
9649+{"fsd", "D", "T,A,s", 0, (int) M_FSD, match_never, INSN_MACRO },
9650+{"fmv.d", "D", "D,U", MATCH_FSGNJ_D, MASK_FSGNJ_D, match_rs1_eq_rs2, INSN_ALIAS|WR_fd|RD_fs1|RD_fs2 },
9651+{"fneg.d", "D", "D,U", MATCH_FSGNJN_D, MASK_FSGNJN_D, match_rs1_eq_rs2, INSN_ALIAS|WR_fd|RD_fs1|RD_fs2 },
9652+{"fabs.d", "D", "D,U", MATCH_FSGNJX_D, MASK_FSGNJX_D, match_rs1_eq_rs2, INSN_ALIAS|WR_fd|RD_fs1|RD_fs2 },
9653+{"fsgnj.d", "D", "D,S,T", MATCH_FSGNJ_D, MASK_FSGNJ_D, match_opcode, WR_fd|RD_fs1|RD_fs2 },
9654+{"fsgnjn.d", "D", "D,S,T", MATCH_FSGNJN_D, MASK_FSGNJN_D, match_opcode, WR_fd|RD_fs1|RD_fs2 },
9655+{"fsgnjx.d", "D", "D,S,T", MATCH_FSGNJX_D, MASK_FSGNJX_D, match_opcode, WR_fd|RD_fs1|RD_fs2 },
9656+{"fadd.d", "D", "D,S,T", MATCH_FADD_D | MASK_RM, MASK_FADD_D | MASK_RM, match_opcode, WR_fd|RD_fs1|RD_fs2 },
9657+{"fadd.d", "D", "D,S,T,m", MATCH_FADD_D, MASK_FADD_D, match_opcode, WR_fd|RD_fs1|RD_fs2 },
9658+{"fsub.d", "D", "D,S,T", MATCH_FSUB_D | MASK_RM, MASK_FSUB_D | MASK_RM, match_opcode, WR_fd|RD_fs1|RD_fs2 },
9659+{"fsub.d", "D", "D,S,T,m", MATCH_FSUB_D, MASK_FSUB_D, match_opcode, WR_fd|RD_fs1|RD_fs2 },
9660+{"fmul.d", "D", "D,S,T", MATCH_FMUL_D | MASK_RM, MASK_FMUL_D | MASK_RM, match_opcode, WR_fd|RD_fs1|RD_fs2 },
9661+{"fmul.d", "D", "D,S,T,m", MATCH_FMUL_D, MASK_FMUL_D, match_opcode, WR_fd|RD_fs1|RD_fs2 },
9662+{"fdiv.d", "D", "D,S,T", MATCH_FDIV_D | MASK_RM, MASK_FDIV_D | MASK_RM, match_opcode, WR_fd|RD_fs1|RD_fs2 },
9663+{"fdiv.d", "D", "D,S,T,m", MATCH_FDIV_D, MASK_FDIV_D, match_opcode, WR_fd|RD_fs1|RD_fs2 },
9664+{"fsqrt.d", "D", "D,S", MATCH_FSQRT_D | MASK_RM, MASK_FSQRT_D | MASK_RM, match_opcode, WR_fd|RD_fs1 },
9665+{"fsqrt.d", "D", "D,S,m", MATCH_FSQRT_D, MASK_FSQRT_D, match_opcode, WR_fd|RD_fs1 },
9666+{"fmin.d", "D", "D,S,T", MATCH_FMIN_D, MASK_FMIN_D, match_opcode, WR_fd|RD_fs1|RD_fs2 },
9667+{"fmax.d", "D", "D,S,T", MATCH_FMAX_D, MASK_FMAX_D, match_opcode, WR_fd|RD_fs1|RD_fs2 },
9668+{"fmadd.d", "D", "D,S,T,R", MATCH_FMADD_D | MASK_RM, MASK_FMADD_D | MASK_RM, match_opcode, WR_fd|RD_fs1|RD_fs2|RD_fs3 },
9669+{"fmadd.d", "D", "D,S,T,R,m", MATCH_FMADD_D, MASK_FMADD_D, match_opcode, WR_fd|RD_fs1|RD_fs2|RD_fs3 },
9670+{"fnmadd.d", "D", "D,S,T,R", MATCH_FNMADD_D | MASK_RM, MASK_FNMADD_D | MASK_RM, match_opcode, WR_fd|RD_fs1|RD_fs2|RD_fs3 },
9671+{"fnmadd.d", "D", "D,S,T,R,m", MATCH_FNMADD_D, MASK_FNMADD_D, match_opcode, WR_fd|RD_fs1|RD_fs2|RD_fs3 },
9672+{"fmsub.d", "D", "D,S,T,R", MATCH_FMSUB_D | MASK_RM, MASK_FMSUB_D | MASK_RM, match_opcode, WR_fd|RD_fs1|RD_fs2|RD_fs3 },
9673+{"fmsub.d", "D", "D,S,T,R,m", MATCH_FMSUB_D, MASK_FMSUB_D, match_opcode, WR_fd|RD_fs1|RD_fs2|RD_fs3 },
9674+{"fnmsub.d", "D", "D,S,T,R", MATCH_FNMSUB_D | MASK_RM, MASK_FNMSUB_D | MASK_RM, match_opcode, WR_fd|RD_fs1|RD_fs2|RD_fs3 },
9675+{"fnmsub.d", "D", "D,S,T,R,m", MATCH_FNMSUB_D, MASK_FNMSUB_D, match_opcode, WR_fd|RD_fs1|RD_fs2|RD_fs3 },
9676+{"fcvt.w.d", "D", "d,S", MATCH_FCVT_W_D | MASK_RM, MASK_FCVT_W_D | MASK_RM, match_opcode, WR_xd|RD_fs1 },
9677+{"fcvt.w.d", "D", "d,S,m", MATCH_FCVT_W_D, MASK_FCVT_W_D, match_opcode, WR_xd|RD_fs1 },
9678+{"fcvt.wu.d", "D", "d,S", MATCH_FCVT_WU_D | MASK_RM, MASK_FCVT_WU_D | MASK_RM, match_opcode, WR_xd|RD_fs1 },
9679+{"fcvt.wu.d", "D", "d,S,m", MATCH_FCVT_WU_D, MASK_FCVT_WU_D, match_opcode, WR_xd|RD_fs1 },
9680+{"fcvt.d.w", "D", "D,s", MATCH_FCVT_D_W, MASK_FCVT_D_W | MASK_RM, match_opcode, WR_fd|RD_xs1 },
9681+{"fcvt.d.wu", "D", "D,s", MATCH_FCVT_D_WU, MASK_FCVT_D_WU | MASK_RM, match_opcode, WR_fd|RD_xs1 },
9682+{"fcvt.d.s", "D", "D,S", MATCH_FCVT_D_S, MASK_FCVT_D_S | MASK_RM, match_opcode, WR_fd|RD_fs1 },
9683+{"fcvt.s.d", "D", "D,S", MATCH_FCVT_S_D | MASK_RM, MASK_FCVT_S_D | MASK_RM, match_opcode, WR_fd|RD_fs1 },
9684+{"fcvt.s.d", "D", "D,S,m", MATCH_FCVT_S_D, MASK_FCVT_S_D, match_opcode, WR_fd|RD_fs1 },
9685+{"fclass.d", "D", "d,S", MATCH_FCLASS_D, MASK_FCLASS_D, match_opcode, WR_xd|RD_fs1 },
9686+{"feq.d", "D", "d,S,T", MATCH_FEQ_D, MASK_FEQ_D, match_opcode, WR_xd|RD_fs1|RD_fs2 },
9687+{"flt.d", "D", "d,S,T", MATCH_FLT_D, MASK_FLT_D, match_opcode, WR_xd|RD_fs1|RD_fs2 },
9688+{"fle.d", "D", "d,S,T", MATCH_FLE_D, MASK_FLE_D, match_opcode, WR_xd|RD_fs1|RD_fs2 },
9689+{"fgt.d", "D", "d,T,S", MATCH_FLT_D, MASK_FLT_D, match_opcode, WR_xd|RD_fs1|RD_fs2 },
9690+{"fge.d", "D", "d,T,S", MATCH_FLE_D, MASK_FLE_D, match_opcode, WR_xd|RD_fs1|RD_fs2 },
9691+{"fmv.x.d", "64D", "d,S", MATCH_FMV_X_D, MASK_FMV_X_D, match_opcode, WR_xd|RD_fs1 },
9692+{"fmv.d.x", "64D", "D,s", MATCH_FMV_D_X, MASK_FMV_D_X, match_opcode, WR_fd|RD_xs1 },
9693+{"fcvt.l.d", "64D", "d,S", MATCH_FCVT_L_D | MASK_RM, MASK_FCVT_L_D | MASK_RM, match_opcode, WR_xd|RD_fs1 },
9694+{"fcvt.l.d", "64D", "d,S,m", MATCH_FCVT_L_D, MASK_FCVT_L_D, match_opcode, WR_xd|RD_fs1 },
9695+{"fcvt.lu.d", "64D", "d,S", MATCH_FCVT_LU_D | MASK_RM, MASK_FCVT_LU_D | MASK_RM, match_opcode, WR_xd|RD_fs1 },
9696+{"fcvt.lu.d", "64D", "d,S,m", MATCH_FCVT_LU_D, MASK_FCVT_LU_D, match_opcode, WR_xd|RD_fs1 },
9697+{"fcvt.d.l", "64D", "D,s", MATCH_FCVT_D_L | MASK_RM, MASK_FCVT_D_L | MASK_RM, match_opcode, WR_fd|RD_xs1 },
9698+{"fcvt.d.l", "64D", "D,s,m", MATCH_FCVT_D_L, MASK_FCVT_D_L, match_opcode, WR_fd|RD_xs1 },
9699+{"fcvt.d.lu", "64D", "D,s", MATCH_FCVT_D_LU | MASK_RM, MASK_FCVT_D_L | MASK_RM, match_opcode, WR_fd|RD_xs1 },
9700+{"fcvt.d.lu", "64D", "D,s,m", MATCH_FCVT_D_LU, MASK_FCVT_D_LU, match_opcode, WR_fd|RD_xs1 },
9701+
9702+/* Supervisor instructions */
9703+{"csrr", "I", "d,E", MATCH_CSRRS, MASK_CSRRS | MASK_RS1, match_opcode, WR_xd },
9704+{"csrwi", "I", "E,Z", MATCH_CSRRWI, MASK_CSRRWI | MASK_RD, match_opcode, WR_xd|RD_xs1 },
9705+{"csrw", "I", "E,s", MATCH_CSRRW, MASK_CSRRW | MASK_RD, match_opcode, RD_xs1 },
9706+{"csrw", "I", "E,Z", MATCH_CSRRWI, MASK_CSRRWI | MASK_RD, match_opcode, WR_xd|RD_xs1 },
9707+{"csrsi", "I", "E,Z", MATCH_CSRRSI, MASK_CSRRSI | MASK_RD, match_opcode, WR_xd|RD_xs1 },
9708+{"csrs", "I", "E,s", MATCH_CSRRS, MASK_CSRRS | MASK_RD, match_opcode, WR_xd|RD_xs1 },
9709+{"csrs", "I", "E,Z", MATCH_CSRRSI, MASK_CSRRSI | MASK_RD, match_opcode, WR_xd|RD_xs1 },
9710+{"csrci", "I", "E,Z", MATCH_CSRRCI, MASK_CSRRCI | MASK_RD, match_opcode, WR_xd|RD_xs1 },
9711+{"csrc", "I", "E,s", MATCH_CSRRC, MASK_CSRRC | MASK_RD, match_opcode, WR_xd|RD_xs1 },
9712+{"csrc", "I", "E,Z", MATCH_CSRRCI, MASK_CSRRCI | MASK_RD, match_opcode, WR_xd|RD_xs1 },
9713+{"csrrw", "I", "d,E,s", MATCH_CSRRW, MASK_CSRRW, match_opcode, WR_xd|RD_xs1 },
9714+{"csrrw", "I", "d,E,Z", MATCH_CSRRWI, MASK_CSRRWI, match_opcode, WR_xd|RD_xs1 },
9715+{"csrrs", "I", "d,E,s", MATCH_CSRRS, MASK_CSRRS, match_opcode, WR_xd|RD_xs1 },
9716+{"csrrs", "I", "d,E,Z", MATCH_CSRRSI, MASK_CSRRSI, match_opcode, WR_xd|RD_xs1 },
9717+{"csrrc", "I", "d,E,s", MATCH_CSRRC, MASK_CSRRC, match_opcode, WR_xd|RD_xs1 },
9718+{"csrrc", "I", "d,E,Z", MATCH_CSRRCI, MASK_CSRRCI, match_opcode, WR_xd|RD_xs1 },
9719+{"csrrwi", "I", "d,E,Z", MATCH_CSRRWI, MASK_CSRRWI, match_opcode, WR_xd|RD_xs1 },
9720+{"csrrsi", "I", "d,E,Z", MATCH_CSRRSI, MASK_CSRRSI, match_opcode, WR_xd|RD_xs1 },
9721+{"csrrci", "I", "d,E,Z", MATCH_CSRRCI, MASK_CSRRCI, match_opcode, WR_xd|RD_xs1 },
Patrick Georgiaf473ed2015-07-17 23:35:54 +02009722+{"eret", "I", "", MATCH_SRET, MASK_SRET, match_opcode, 0 },
Patrick Georgif0bbc952015-03-07 10:57:25 +01009723+{"sret", "I", "", MATCH_SRET, MASK_SRET, match_opcode, 0 },
Patrick Georgiaf473ed2015-07-17 23:35:54 +02009724+{"mrts", "I", "", MATCH_MRTS, MASK_MRTS, match_opcode, 0 },
9725+{"sfence.vm", "I", "", MATCH_SFENCE_VM | MASK_RS1, MASK_SFENCE_VM | MASK_RS1, match_opcode, 0 },
9726+{"sfence.vm", "I", "s", MATCH_SFENCE_VM, MASK_SFENCE_VM, match_opcode, RD_xs1 },
9727+{"wfi", "I", "", MATCH_WFI, MASK_WFI, match_opcode, 0 },
Patrick Georgif0bbc952015-03-07 10:57:25 +01009728+
9729+/* Half-precision floating-point instruction subset */
9730+{"flh", "Xhwacha", "D,o(s)", MATCH_FLH, MASK_FLH, match_opcode, WR_fd|RD_xs1 },
9731+{"fsh", "Xhwacha", "T,q(s)", MATCH_FSH, MASK_FSH, match_opcode, RD_xs1|RD_fs2 },
9732+{"fsgnj.h", "Xhwacha", "D,S,T", MATCH_FSGNJ_H, MASK_FSGNJ_H, match_opcode, WR_fd|RD_fs1|RD_fs2 },
9733+{"fsgnjn.h", "Xhwacha", "D,S,T", MATCH_FSGNJN_H, MASK_FSGNJN_H, match_opcode, WR_fd|RD_fs1|RD_fs2 },
9734+{"fsgnjx.h", "Xhwacha", "D,S,T", MATCH_FSGNJX_H, MASK_FSGNJX_H, match_opcode, WR_fd|RD_fs1|RD_fs2 },
9735+{"fadd.h", "Xhwacha", "D,S,T", MATCH_FADD_H | MASK_RM, MASK_FADD_H | MASK_RM, match_opcode, WR_fd|RD_fs1|RD_fs2 },
9736+{"fadd.h", "Xhwacha", "D,S,T,m", MATCH_FADD_H, MASK_FADD_H, match_opcode, WR_fd|RD_fs1|RD_fs2 },
9737+{"fsub.h", "Xhwacha", "D,S,T", MATCH_FSUB_H | MASK_RM, MASK_FSUB_H | MASK_RM, match_opcode, WR_fd|RD_fs1|RD_fs2 },
9738+{"fsub.h", "Xhwacha", "D,S,T,m", MATCH_FSUB_H, MASK_FSUB_H, match_opcode, WR_fd|RD_fs1|RD_fs2 },
9739+{"fmul.h", "Xhwacha", "D,S,T", MATCH_FMUL_H | MASK_RM, MASK_FMUL_H | MASK_RM, match_opcode, WR_fd|RD_fs1|RD_fs2 },
9740+{"fmul.h", "Xhwacha", "D,S,T,m", MATCH_FMUL_H, MASK_FMUL_H, match_opcode, WR_fd|RD_fs1|RD_fs2 },
9741+{"fdiv.h", "Xhwacha", "D,S,T", MATCH_FDIV_H | MASK_RM, MASK_FDIV_H | MASK_RM, match_opcode, WR_fd|RD_fs1|RD_fs2 },
9742+{"fdiv.h", "Xhwacha", "D,S,T,m", MATCH_FDIV_H, MASK_FDIV_H, match_opcode, WR_fd|RD_fs1|RD_fs2 },
9743+{"fsqrt.h", "Xhwacha", "D,S", MATCH_FSQRT_H | MASK_RM, MASK_FSQRT_H | MASK_RM, match_opcode, WR_fd|RD_fs1 },
9744+{"fsqrt.h", "Xhwacha", "D,S,m", MATCH_FSQRT_H, MASK_FSQRT_H, match_opcode, WR_fd|RD_fs1 },
9745+{"fmin.h", "Xhwacha", "D,S,T", MATCH_FMIN_H, MASK_FMIN_H, match_opcode, WR_fd|RD_fs1|RD_fs2 },
9746+{"fmax.h", "Xhwacha", "D,S,T", MATCH_FMAX_H, MASK_FMAX_H, match_opcode, WR_fd|RD_fs1|RD_fs2 },
9747+{"fmadd.h", "Xhwacha", "D,S,T,R", MATCH_FMADD_H | MASK_RM, MASK_FMADD_H | MASK_RM, match_opcode, WR_fd|RD_fs1|RD_fs2|RD_fs3 },
9748+{"fmadd.h", "Xhwacha", "D,S,T,R,m", MATCH_FMADD_H, MASK_FMADD_H, match_opcode, WR_fd|RD_fs1|RD_fs2|RD_fs3 },
9749+{"fnmadd.h", "Xhwacha", "D,S,T,R", MATCH_FNMADD_H | MASK_RM, MASK_FNMADD_H | MASK_RM, match_opcode, WR_fd|RD_fs1|RD_fs2|RD_fs3 },
9750+{"fnmadd.h", "Xhwacha", "D,S,T,R,m", MATCH_FNMADD_H, MASK_FNMADD_H, match_opcode, WR_fd|RD_fs1|RD_fs2|RD_fs3 },
9751+{"fmsub.h", "Xhwacha", "D,S,T,R", MATCH_FMSUB_H | MASK_RM, MASK_FMSUB_H | MASK_RM, match_opcode, WR_fd|RD_fs1|RD_fs2|RD_fs3 },
9752+{"fmsub.h", "Xhwacha", "D,S,T,R,m", MATCH_FMSUB_H, MASK_FMSUB_H, match_opcode, WR_fd|RD_fs1|RD_fs2|RD_fs3 },
9753+{"fnmsub.h", "Xhwacha", "D,S,T,R", MATCH_FNMSUB_H | MASK_RM, MASK_FNMSUB_H | MASK_RM, match_opcode, WR_fd|RD_fs1|RD_fs2|RD_fs3 },
9754+{"fnmsub.h", "Xhwacha", "D,S,T,R,m", MATCH_FNMSUB_H, MASK_FNMSUB_H, match_opcode, WR_fd|RD_fs1|RD_fs2|RD_fs3 },
9755+{"fcvt.s.h", "Xhwacha", "D,S", MATCH_FCVT_S_H, MASK_FCVT_S_H | MASK_RM, match_opcode, WR_fd|RD_fs1 },
9756+{"fcvt.h.s", "Xhwacha", "D,S", MATCH_FCVT_H_S | MASK_RM, MASK_FCVT_H_S | MASK_RM, match_opcode, WR_fd|RD_fs1 },
9757+{"fcvt.h.s", "Xhwacha", "D,S,m", MATCH_FCVT_H_S, MASK_FCVT_H_S, match_opcode, WR_fd|RD_fs1 },
9758+{"fcvt.d.h", "Xhwacha", "D,S", MATCH_FCVT_D_H, MASK_FCVT_D_H | MASK_RM, match_opcode, WR_fd|RD_fs1 },
9759+{"fcvt.h.d", "Xhwacha", "D,S", MATCH_FCVT_H_D | MASK_RM, MASK_FCVT_H_D | MASK_RM, match_opcode, WR_fd|RD_fs1 },
9760+{"fcvt.h.d", "Xhwacha", "D,S,m", MATCH_FCVT_H_D, MASK_FCVT_H_D, match_opcode, WR_fd|RD_fs1 },
9761+{"feq.h", "Xhwacha", "d,S,T", MATCH_FEQ_H, MASK_FEQ_H, match_opcode, WR_xd|RD_fs1|RD_fs2 },
9762+{"flt.h", "Xhwacha", "d,S,T", MATCH_FLT_H, MASK_FLT_H, match_opcode, WR_xd|RD_fs1|RD_fs2 },
9763+{"fle.h", "Xhwacha", "d,S,T", MATCH_FLE_H, MASK_FLE_H, match_opcode, WR_xd|RD_fs1|RD_fs2 },
9764+{"fgt.h", "Xhwacha", "d,T,S", MATCH_FLT_H, MASK_FLT_H, match_opcode, WR_xd|RD_fs1|RD_fs2 },
9765+{"fge.h", "Xhwacha", "d,T,S", MATCH_FLE_H, MASK_FLE_H, match_opcode, WR_xd|RD_fs1|RD_fs2 },
9766+{"fmv.x.h", "Xhwacha", "d,S", MATCH_FMV_X_H, MASK_FMV_X_H, match_opcode, WR_xd|RD_fs1 },
9767+{"fmv.h.x", "Xhwacha", "D,s", MATCH_FMV_H_X, MASK_FMV_H_X, match_opcode, WR_fd|RD_xs1 },
9768+{"fcvt.w.h", "Xhwacha", "d,S", MATCH_FCVT_W_H | MASK_RM, MASK_FCVT_W_H | MASK_RM, match_opcode, WR_xd|RD_fs1 },
9769+{"fcvt.w.h", "Xhwacha", "d,S,m", MATCH_FCVT_W_H, MASK_FCVT_W_H, match_opcode, WR_xd|RD_fs1 },
9770+{"fcvt.wu.h", "Xhwacha", "d,S", MATCH_FCVT_WU_H | MASK_RM, MASK_FCVT_WU_H | MASK_RM, match_opcode, WR_xd|RD_fs1 },
9771+{"fcvt.wu.h", "Xhwacha", "d,S,m", MATCH_FCVT_WU_H, MASK_FCVT_WU_H, match_opcode, WR_xd|RD_fs1 },
9772+{"fcvt.h.w", "Xhwacha", "D,s", MATCH_FCVT_H_W, MASK_FCVT_H_W | MASK_RM, match_opcode, WR_fd|RD_xs1 },
9773+{"fcvt.h.wu", "Xhwacha", "D,s", MATCH_FCVT_H_WU, MASK_FCVT_H_WU | MASK_RM, match_opcode, WR_fd|RD_xs1 },
9774+{"fcvt.l.h", "Xhwacha", "d,S", MATCH_FCVT_L_H | MASK_RM, MASK_FCVT_L_H | MASK_RM, match_opcode, WR_xd|RD_fs1 },
9775+{"fcvt.l.h", "Xhwacha", "d,S,m", MATCH_FCVT_L_H, MASK_FCVT_L_H, match_opcode, WR_xd|RD_fs1 },
9776+{"fcvt.lu.h", "Xhwacha", "d,S", MATCH_FCVT_LU_H | MASK_RM, MASK_FCVT_LU_H | MASK_RM, match_opcode, WR_xd|RD_fs1 },
9777+{"fcvt.lu.h", "Xhwacha", "d,S,m", MATCH_FCVT_LU_H, MASK_FCVT_LU_H, match_opcode, WR_xd|RD_fs1 },
9778+{"fcvt.h.l", "Xhwacha", "D,s", MATCH_FCVT_H_L | MASK_RM, MASK_FCVT_H_L | MASK_RM, match_opcode, WR_fd|RD_xs1 },
9779+{"fcvt.h.l", "Xhwacha", "D,s,m", MATCH_FCVT_H_L, MASK_FCVT_H_L, match_opcode, WR_fd|RD_xs1 },
9780+{"fcvt.h.lu", "Xhwacha", "D,s", MATCH_FCVT_H_LU | MASK_RM, MASK_FCVT_H_L | MASK_RM, match_opcode, WR_fd|RD_xs1 },
9781+{"fcvt.h.lu", "Xhwacha", "D,s,m", MATCH_FCVT_H_LU, MASK_FCVT_H_LU, match_opcode, WR_fd|RD_xs1 },
9782+
9783+/* Rocket Custom Coprocessor extension */
9784+{"custom0", "Xcustom", "d,s,t,^j", MATCH_CUSTOM0_RD_RS1_RS2, MASK_CUSTOM0_RD_RS1_RS2, match_opcode, 0},
9785+{"custom0", "Xcustom", "d,s,^t,^j", MATCH_CUSTOM0_RD_RS1, MASK_CUSTOM0_RD_RS1, match_opcode, 0},
9786+{"custom0", "Xcustom", "d,^s,^t,^j", MATCH_CUSTOM0_RD, MASK_CUSTOM0_RD, match_opcode, 0},
9787+{"custom0", "Xcustom", "^d,s,t,^j", MATCH_CUSTOM0_RS1_RS2, MASK_CUSTOM0_RS1_RS2, match_opcode, 0},
9788+{"custom0", "Xcustom", "^d,s,^t,^j", MATCH_CUSTOM0_RS1, MASK_CUSTOM0_RS1, match_opcode, 0},
9789+{"custom0", "Xcustom", "^d,^s,^t,^j", MATCH_CUSTOM0, MASK_CUSTOM0, match_opcode, 0},
9790+{"custom1", "Xcustom", "d,s,t,^j", MATCH_CUSTOM1_RD_RS1_RS2, MASK_CUSTOM1_RD_RS1_RS2, match_opcode, 0},
9791+{"custom1", "Xcustom", "d,s,^t,^j", MATCH_CUSTOM1_RD_RS1, MASK_CUSTOM1_RD_RS1, match_opcode, 0},
9792+{"custom1", "Xcustom", "d,^s,^t,^j", MATCH_CUSTOM1_RD, MASK_CUSTOM1_RD, match_opcode, 0},
9793+{"custom1", "Xcustom", "^d,s,t,^j", MATCH_CUSTOM1_RS1_RS2, MASK_CUSTOM1_RS1_RS2, match_opcode, 0},
9794+{"custom1", "Xcustom", "^d,s,^t,^j", MATCH_CUSTOM1_RS1, MASK_CUSTOM1_RS1, match_opcode, 0},
9795+{"custom1", "Xcustom", "^d,^s,^t,^j", MATCH_CUSTOM1, MASK_CUSTOM1, match_opcode, 0},
9796+{"custom2", "Xcustom", "d,s,t,^j", MATCH_CUSTOM2_RD_RS1_RS2, MASK_CUSTOM2_RD_RS1_RS2, match_opcode, 0},
9797+{"custom2", "Xcustom", "d,s,^t,^j", MATCH_CUSTOM2_RD_RS1, MASK_CUSTOM2_RD_RS1, match_opcode, 0},
9798+{"custom2", "Xcustom", "d,^s,^t,^j", MATCH_CUSTOM2_RD, MASK_CUSTOM2_RD, match_opcode, 0},
9799+{"custom2", "Xcustom", "^d,s,t,^j", MATCH_CUSTOM2_RS1_RS2, MASK_CUSTOM2_RS1_RS2, match_opcode, 0},
9800+{"custom2", "Xcustom", "^d,s,^t,^j", MATCH_CUSTOM2_RS1, MASK_CUSTOM2_RS1, match_opcode, 0},
9801+{"custom2", "Xcustom", "^d,^s,^t,^j", MATCH_CUSTOM2, MASK_CUSTOM2, match_opcode, 0},
9802+{"custom3", "Xcustom", "d,s,t,^j", MATCH_CUSTOM3_RD_RS1_RS2, MASK_CUSTOM3_RD_RS1_RS2, match_opcode, 0},
9803+{"custom3", "Xcustom", "d,s,^t,^j", MATCH_CUSTOM3_RD_RS1, MASK_CUSTOM3_RD_RS1, match_opcode, 0},
9804+{"custom3", "Xcustom", "d,^s,^t,^j", MATCH_CUSTOM3_RD, MASK_CUSTOM3_RD, match_opcode, 0},
9805+{"custom3", "Xcustom", "^d,s,t,^j", MATCH_CUSTOM3_RS1_RS2, MASK_CUSTOM3_RS1_RS2, match_opcode, 0},
9806+{"custom3", "Xcustom", "^d,s,^t,^j", MATCH_CUSTOM3_RS1, MASK_CUSTOM3_RS1, match_opcode, 0},
9807+{"custom3", "Xcustom", "^d,^s,^t,^j", MATCH_CUSTOM3, MASK_CUSTOM3, match_opcode, 0},
9808+
9809+/* Xhwacha extension */
9810+{"stop", "Xhwacha", "", MATCH_STOP, MASK_STOP, match_opcode, 0},
9811+{"utidx", "Xhwacha", "d", MATCH_UTIDX, MASK_UTIDX, match_opcode, WR_xd},
9812+{"movz", "Xhwacha", "d,s,t", MATCH_MOVZ, MASK_MOVZ, match_opcode, WR_xd|RD_xs1|RD_xs2},
9813+{"movn", "Xhwacha", "d,s,t", MATCH_MOVN, MASK_MOVN, match_opcode, WR_xd|RD_xs1|RD_xs2},
9814+{"fmovz", "Xhwacha", "D,s,T", MATCH_FMOVZ, MASK_FMOVZ, match_opcode, WR_fd|RD_xs1|RD_fs2},
9815+{"fmovn", "Xhwacha", "D,s,T", MATCH_FMOVN, MASK_FMOVN, match_opcode, WR_fd|RD_xs1|RD_fs2},
9816+
9817+/* unit stride */
9818+/* xloads */
9819+{"vld", "Xhwacha", "#d,s", MATCH_VLD, MASK_VLD, match_opcode, 0},
9820+{"vlw", "Xhwacha", "#d,s", MATCH_VLW, MASK_VLW, match_opcode, 0},
9821+{"vlwu", "Xhwacha", "#d,s", MATCH_VLWU, MASK_VLWU, match_opcode, 0},
9822+{"vlh", "Xhwacha", "#d,s", MATCH_VLH, MASK_VLH, match_opcode, 0},
9823+{"vlhu", "Xhwacha", "#d,s", MATCH_VLHU, MASK_VLHU, match_opcode, 0},
9824+{"vlb", "Xhwacha", "#d,s", MATCH_VLB, MASK_VLB, match_opcode, 0},
9825+{"vlbu", "Xhwacha", "#d,s", MATCH_VLBU, MASK_VLBU, match_opcode, 0},
9826+/* floads */
9827+{"vfld", "Xhwacha", "#D,s", MATCH_VFLD, MASK_VFLD, match_opcode, 0},
9828+{"vflw", "Xhwacha", "#D,s", MATCH_VFLW, MASK_VFLW, match_opcode, 0},
9829+
9830+/* stride */
9831+/* xloads */
9832+{"vlstd", "Xhwacha", "#d,s,t", MATCH_VLSTD, MASK_VLSTD, match_opcode, 0},
9833+{"vlstw", "Xhwacha", "#d,s,t", MATCH_VLSTW, MASK_VLSTW, match_opcode, 0},
9834+{"vlstwu", "Xhwacha", "#d,s,t", MATCH_VLSTWU, MASK_VLSTWU, match_opcode, 0},
9835+{"vlsth", "Xhwacha", "#d,s,t", MATCH_VLSTH, MASK_VLSTH, match_opcode, 0},
9836+{"vlsthu", "Xhwacha", "#d,s,t", MATCH_VLSTHU, MASK_VLSTHU, match_opcode, 0},
9837+{"vlstb", "Xhwacha", "#d,s,t", MATCH_VLSTB, MASK_VLSTB, match_opcode, 0},
9838+{"vlstbu", "Xhwacha", "#d,s,t", MATCH_VLSTBU, MASK_VLSTBU, match_opcode, 0},
9839+/* floads */
9840+{"vflstd", "Xhwacha", "#D,s,t", MATCH_VFLSTD, MASK_VFLSTD, match_opcode, 0},
9841+{"vflstw", "Xhwacha", "#D,s,t", MATCH_VFLSTW, MASK_VFLSTW, match_opcode, 0},
9842+
9843+/* segment */
9844+/* xloads */
9845+{"vlsegd", "Xhwacha", "#d,s,#n", MATCH_VLSEGD, MASK_VLSEGD, match_opcode, 0},
9846+{"vlsegw", "Xhwacha", "#d,s,#n", MATCH_VLSEGW, MASK_VLSEGW, match_opcode, 0},
9847+{"vlsegwu", "Xhwacha", "#d,s,#n", MATCH_VLSEGWU, MASK_VLSEGWU, match_opcode, 0},
9848+{"vlsegh", "Xhwacha", "#d,s,#n", MATCH_VLSEGH, MASK_VLSEGH, match_opcode, 0},
9849+{"vlseghu", "Xhwacha", "#d,s,#n", MATCH_VLSEGHU, MASK_VLSEGHU, match_opcode, 0},
9850+{"vlsegb", "Xhwacha", "#d,s,#n", MATCH_VLSEGB, MASK_VLSEGB, match_opcode, 0},
9851+{"vlsegbu", "Xhwacha", "#d,s,#n", MATCH_VLSEGBU, MASK_VLSEGBU, match_opcode, 0},
9852+/* floads */
9853+{"vflsegd", "Xhwacha", "#D,s,#n", MATCH_VFLSEGD, MASK_VFLSEGD, match_opcode, 0},
9854+{"vflsegw", "Xhwacha", "#D,s,#n", MATCH_VFLSEGW, MASK_VFLSEGW, match_opcode, 0},
9855+
9856+/* stride segment */
9857+/* xloads */
9858+{"vlsegstd", "Xhwacha", "#d,s,t,#n", MATCH_VLSEGSTD, MASK_VLSEGSTD, match_opcode, 0},
9859+{"vlsegstw", "Xhwacha", "#d,s,t,#n", MATCH_VLSEGSTW, MASK_VLSEGSTW, match_opcode, 0},
9860+{"vlsegstwu", "Xhwacha", "#d,s,t,#n", MATCH_VLSEGSTWU, MASK_VLSEGSTWU, match_opcode, 0},
9861+{"vlsegsth", "Xhwacha", "#d,s,t,#n", MATCH_VLSEGSTH, MASK_VLSEGSTH, match_opcode, 0},
9862+{"vlsegsthu", "Xhwacha", "#d,s,t,#n", MATCH_VLSEGSTHU, MASK_VLSEGSTHU, match_opcode, 0},
9863+{"vlsegstb", "Xhwacha", "#d,s,t,#n", MATCH_VLSEGSTB, MASK_VLSEGSTB, match_opcode, 0},
9864+{"vlsegstbu", "Xhwacha", "#d,s,t,#n", MATCH_VLSEGSTBU, MASK_VLSEGSTBU, match_opcode, 0},
9865+/* floads */
9866+{"vflsegstd", "Xhwacha", "#D,s,t,#n", MATCH_VFLSEGSTD, MASK_VFLSEGSTD, match_opcode, 0},
9867+{"vflsegstw", "Xhwacha", "#D,s,t,#n", MATCH_VFLSEGSTW, MASK_VFLSEGSTW, match_opcode, 0},
9868+
9869+/* unit stride */
9870+/* xstores */
9871+{"vsd", "Xhwacha", "#d,s", MATCH_VSD, MASK_VSD, match_opcode, 0},
9872+{"vsw", "Xhwacha", "#d,s", MATCH_VSW, MASK_VSW, match_opcode, 0},
9873+{"vsh", "Xhwacha", "#d,s", MATCH_VSH, MASK_VSH, match_opcode, 0},
9874+{"vsb", "Xhwacha", "#d,s", MATCH_VSB, MASK_VSB, match_opcode, 0},
9875+/* fstores */
9876+{"vfsd", "Xhwacha", "#D,s", MATCH_VFSD, MASK_VFSD, match_opcode, 0},
9877+{"vfsw", "Xhwacha", "#D,s", MATCH_VFSW, MASK_VFSW, match_opcode, 0},
9878+
9879+/* stride */
9880+/* xstores */
9881+{"vsstd", "Xhwacha", "#d,s,t", MATCH_VSSTD, MASK_VSSTD, match_opcode, 0},
9882+{"vsstw", "Xhwacha", "#d,s,t", MATCH_VSSTW, MASK_VSSTW, match_opcode, 0},
9883+{"vssth", "Xhwacha", "#d,s,t", MATCH_VSSTH, MASK_VSSTH, match_opcode, 0},
9884+{"vsstb", "Xhwacha", "#d,s,t", MATCH_VSSTB, MASK_VSSTB, match_opcode, 0},
9885+/* fstores */
9886+{"vfsstd", "Xhwacha", "#D,s,t", MATCH_VFSSTD, MASK_VFSSTD, match_opcode, 0},
9887+{"vfsstw", "Xhwacha", "#D,s,t", MATCH_VFSSTW, MASK_VFSSTW, match_opcode, 0},
9888+
9889+/* segment */
9890+/* xstores */
9891+{"vssegd", "Xhwacha", "#d,s,#n", MATCH_VSSEGD, MASK_VSSEGD, match_opcode, 0},
9892+{"vssegw", "Xhwacha", "#d,s,#n", MATCH_VSSEGW, MASK_VSSEGW, match_opcode, 0},
9893+{"vssegh", "Xhwacha", "#d,s,#n", MATCH_VSSEGH, MASK_VSSEGH, match_opcode, 0},
9894+{"vssegb", "Xhwacha", "#d,s,#n", MATCH_VSSEGB, MASK_VSSEGB, match_opcode, 0},
9895+/* fstores */
9896+{"vfssegd", "Xhwacha", "#D,s,#n", MATCH_VFSSEGD, MASK_VFSSEGD, match_opcode, 0},
9897+{"vfssegw", "Xhwacha", "#D,s,#n", MATCH_VFSSEGW, MASK_VFSSEGW, match_opcode, 0},
9898+
9899+/* stride segment */
9900+/* xsegstores */
9901+{"vssegstd", "Xhwacha", "#d,s,t,#n", MATCH_VSSEGSTD, MASK_VSSEGSTD, match_opcode, 0},
9902+{"vssegstw", "Xhwacha", "#d,s,t,#n", MATCH_VSSEGSTW, MASK_VSSEGSTW, match_opcode, 0},
9903+{"vssegsth", "Xhwacha", "#d,s,t,#n", MATCH_VSSEGSTH, MASK_VSSEGSTH, match_opcode, 0},
9904+{"vssegstb", "Xhwacha", "#d,s,t,#n", MATCH_VSSEGSTB, MASK_VSSEGSTB, match_opcode, 0},
9905+/* fsegstores */
9906+{"vfssegstd", "Xhwacha", "#D,s,t,#n", MATCH_VFSSEGSTD, MASK_VFSSEGSTD, match_opcode, 0},
9907+{"vfssegstw", "Xhwacha", "#D,s,t,#n", MATCH_VFSSEGSTW, MASK_VFSSEGSTW, match_opcode, 0},
9908+
9909+{"vsetcfg", "Xhwacha", "s", MATCH_VSETCFG, MASK_VSETCFG | MASK_IMM, match_opcode, 0},
9910+{"vsetcfg", "Xhwacha", "#g,#f", MATCH_VSETCFG, MASK_VSETCFG | MASK_RS1, match_opcode, 0},
9911+{"vsetcfg", "Xhwacha", "s,#g,#f", MATCH_VSETCFG, MASK_VSETCFG, match_opcode, 0},
9912+{"vsetucfg", "Xhwacha", "d,u", MATCH_LUI, MASK_LUI, match_opcode, INSN_ALIAS | WR_xd},
9913+{"vsetvl", "Xhwacha", "d,s", MATCH_VSETVL, MASK_VSETVL, match_opcode, 0},
9914+{"vgetcfg", "Xhwacha", "d", MATCH_VGETCFG, MASK_VGETCFG, match_opcode, 0},
9915+{"vgetvl", "Xhwacha", "d", MATCH_VGETVL, MASK_VGETVL, match_opcode, 0},
9916+
9917+{"vmvv", "Xhwacha", "#d,#s", MATCH_VMVV, MASK_VMVV, match_opcode, 0},
9918+{"vmsv", "Xhwacha", "#d,s", MATCH_VMSV, MASK_VMSV, match_opcode, 0},
9919+{"vfmvv", "Xhwacha", "#D,#S", MATCH_VFMVV, MASK_VFMVV, match_opcode, 0},
9920+{"vfmsv.d", "Xhwacha", "#D,s", MATCH_VFMSV_D, MASK_VFMSV_D, match_opcode, 0},
9921+{"vfmsv.s", "Xhwacha", "#D,s", MATCH_VFMSV_S, MASK_VFMSV_S, match_opcode, 0},
9922+
9923+{"vf", "Xhwacha", "q(s)", MATCH_VF, MASK_VF, match_opcode, 0},
9924+{"vf", "Xhwacha", "A,s", 0, (int) M_VF, match_never, INSN_MACRO },
9925+
9926+{"vxcptcause", "Xhwacha", "d", MATCH_VXCPTCAUSE, MASK_VXCPTCAUSE, match_opcode, 0},
9927+{"vxcptaux", "Xhwacha", "d", MATCH_VXCPTAUX, MASK_VXCPTAUX, match_opcode, 0},
9928+
9929+{"vxcptsave", "Xhwacha", "s", MATCH_VXCPTSAVE, MASK_VXCPTSAVE, match_opcode, 0},
9930+{"vxcptrestore", "Xhwacha", "s", MATCH_VXCPTRESTORE, MASK_VXCPTRESTORE, match_opcode, 0},
9931+{"vxcptkill", "Xhwacha", "", MATCH_VXCPTKILL, MASK_VXCPTKILL, match_opcode, 0},
9932+
9933+{"vxcptevac", "Xhwacha", "s", MATCH_VXCPTEVAC, MASK_VXCPTEVAC, match_opcode, 0},
Patrick Georgiaf473ed2015-07-17 23:35:54 +02009934+{"vxcpthold", "Xhwacha", "s", MATCH_VXCPTHOLD, MASK_VXCPTHOLD, match_opcode, 0},
Patrick Georgif0bbc952015-03-07 10:57:25 +01009935+{"venqcmd", "Xhwacha", "s,t", MATCH_VENQCMD, MASK_VENQCMD, match_opcode, 0},
9936+{"venqimm1", "Xhwacha", "s,t", MATCH_VENQIMM1, MASK_VENQIMM1, match_opcode, 0},
9937+{"venqimm2", "Xhwacha", "s,t", MATCH_VENQIMM2, MASK_VENQIMM2, match_opcode, 0},
9938+{"venqcnt", "Xhwacha", "s,t", MATCH_VENQCNT, MASK_VENQCNT, match_opcode, 0},
9939+};
9940+
9941+#define RISCV_NUM_OPCODES \
9942+ ((sizeof riscv_builtin_opcodes) / (sizeof (riscv_builtin_opcodes[0])))
9943+const int bfd_riscv_num_builtin_opcodes = RISCV_NUM_OPCODES;
9944+
9945+/* const removed from the following to allow for dynamic extensions to the
9946+ * built-in instruction set. */
9947+struct riscv_opcode *riscv_opcodes =
9948+ (struct riscv_opcode *) riscv_builtin_opcodes;
9949+int bfd_riscv_num_opcodes = RISCV_NUM_OPCODES;
9950+#undef RISCV_NUM_OPCODES
Patrick Georgiaf473ed2015-07-17 23:35:54 +02009951--- original-binutils/bfd/archures.c
9952+++ binutils-2.25/bfd/archures.c
9953@@ -597,6 +597,7 @@ extern const bfd_arch_info_type bfd_pj_a
9954 extern const bfd_arch_info_type bfd_plugin_arch;
9955 extern const bfd_arch_info_type bfd_powerpc_archs[];
9956 #define bfd_powerpc_arch bfd_powerpc_archs[0]
9957+extern const bfd_arch_info_type bfd_riscv_arch;
9958 extern const bfd_arch_info_type bfd_rs6000_arch;
9959 extern const bfd_arch_info_type bfd_rl78_arch;
9960 extern const bfd_arch_info_type bfd_rx_arch;
9961@@ -683,6 +684,7 @@ static const bfd_arch_info_type * const
9962 &bfd_or1k_arch,
9963 &bfd_pdp11_arch,
9964 &bfd_powerpc_arch,
9965+ &bfd_riscv_arch,
9966 &bfd_rs6000_arch,
9967 &bfd_rl78_arch,
9968 &bfd_rx_arch,
9969--- original-binutils/bfd/bfd-in2.h
9970+++ binutils-2.25/bfd/bfd-in2.h
9971@@ -2043,6 +2043,9 @@ enum bfd_architecture
9972 #define bfd_mach_ppc_e6500 5007
9973 #define bfd_mach_ppc_titan 83
9974 #define bfd_mach_ppc_vle 84
9975+ bfd_arch_riscv, /* RISC-V */
9976+#define bfd_mach_riscv32 132
9977+#define bfd_mach_riscv64 164
9978 bfd_arch_rs6000, /* IBM RS/6000 */
9979 #define bfd_mach_rs6k 6000
9980 #define bfd_mach_rs6k_rs1 6001
9981@@ -5531,6 +5534,43 @@ relative offset from _GLOBAL_OFFSET_TABL
9982 value in a word. The relocation is relative offset from */
9983 BFD_RELOC_MICROBLAZE_32_GOTOFF,
9984
9985+/* RISC-V relocations */
9986+ BFD_RELOC_RISCV_HI20,
9987+ BFD_RELOC_RISCV_PCREL_HI20,
9988+ BFD_RELOC_RISCV_PCREL_LO12_I,
9989+ BFD_RELOC_RISCV_PCREL_LO12_S,
9990+ BFD_RELOC_RISCV_LO12_I,
9991+ BFD_RELOC_RISCV_LO12_S,
9992+ BFD_RELOC_RISCV_GPREL12_I,
9993+ BFD_RELOC_RISCV_GPREL12_S,
9994+ BFD_RELOC_RISCV_TPREL_HI20,
9995+ BFD_RELOC_RISCV_TPREL_LO12_I,
9996+ BFD_RELOC_RISCV_TPREL_LO12_S,
9997+ BFD_RELOC_RISCV_TPREL_ADD,
9998+ BFD_RELOC_RISCV_CALL,
9999+ BFD_RELOC_RISCV_CALL_PLT,
10000+ BFD_RELOC_RISCV_ADD8,
10001+ BFD_RELOC_RISCV_ADD16,
10002+ BFD_RELOC_RISCV_ADD32,
10003+ BFD_RELOC_RISCV_ADD64,
10004+ BFD_RELOC_RISCV_SUB8,
10005+ BFD_RELOC_RISCV_SUB16,
10006+ BFD_RELOC_RISCV_SUB32,
10007+ BFD_RELOC_RISCV_SUB64,
10008+ BFD_RELOC_RISCV_GOT_HI20,
10009+ BFD_RELOC_RISCV_TLS_GOT_HI20,
10010+ BFD_RELOC_RISCV_TLS_GD_HI20,
10011+ BFD_RELOC_RISCV_JMP,
10012+ BFD_RELOC_RISCV_TLS_DTPMOD32,
10013+ BFD_RELOC_RISCV_TLS_DTPREL32,
10014+ BFD_RELOC_RISCV_TLS_DTPMOD64,
10015+ BFD_RELOC_RISCV_TLS_DTPREL64,
10016+ BFD_RELOC_RISCV_TLS_TPREL32,
10017+ BFD_RELOC_RISCV_TLS_TPREL64,
10018+ BFD_RELOC_RISCV_ALIGN,
10019+ BFD_RELOC_RISCV_RVC_BRANCH,
10020+ BFD_RELOC_RISCV_RVC_JUMP,
10021+
10022 /* This is used to tell the dynamic linker to copy the value out of
10023 the dynamic object into the runtime process image. */
10024 BFD_RELOC_MICROBLAZE_COPY,
10025--- original-binutils/bfd/config.bfd
10026+++ binutils-2.25/bfd/config.bfd
10027@@ -119,6 +119,7 @@ or1k*|or1knd*) targ_archs=bfd_or1k_arch
10028 pdp11*) targ_archs=bfd_pdp11_arch ;;
10029 pj*) targ_archs="bfd_pj_arch bfd_i386_arch";;
10030 powerpc*) targ_archs="bfd_rs6000_arch bfd_powerpc_arch" ;;
10031+riscv*) targ_archs=bfd_riscv_arch ;;
10032 rs6000) targ_archs="bfd_rs6000_arch bfd_powerpc_arch" ;;
10033 s390*) targ_archs=bfd_s390_arch ;;
10034 sh*) targ_archs=bfd_sh_arch ;;
10035@@ -1319,6 +1320,14 @@ case "${targ}" in
10036 targ_defvec=rl78_elf32_vec
10037 ;;
10038
10039+#ifdef BFD64
10040+ riscv*-*-*)
10041+ targ_defvec=riscv_elf64_vec
10042+ targ_selvecs="riscv_elf32_vec riscv_elf64_vec"
10043+ want64=true
10044+ ;;
10045+#endif
10046+
10047 rx-*-elf)
10048 targ_defvec=rx_elf32_le_vec
10049 targ_selvecs="rx_elf32_be_vec rx_elf32_le_vec rx_elf32_be_ns_vec"
10050--- original-binutils/bfd/configure
10051+++ binutils-2.25/bfd/configure
10052@@ -15506,6 +15506,8 @@ do
10053 powerpc_pei_vec) tb="$tb pei-ppc.lo peigen.lo cofflink.lo" ;;
10054 powerpc_pei_le_vec) tb="$tb pei-ppc.lo peigen.lo cofflink.lo" ;;
10055 powerpc_xcoff_vec) tb="$tb coff-rs6000.lo xcofflink.lo" ;;
10056+ riscv_elf32_vec) tb="$tb elf32-riscv.lo elfxx-riscv.lo elf32.lo $elf" ;;
10057+ riscv_elf64_vec) tb="$tb elf64-riscv.lo elf64.lo elfxx-riscv.lo elf32.lo $elf"; target_size=64 ;;
10058 rl78_elf32_vec) tb="$tb elf32-rl78.lo elf32.lo $elf" ;;
10059 rs6000_xcoff64_vec) tb="$tb coff64-rs6000.lo xcofflink.lo aix5ppc-core.lo"; target_size=64 ;;
10060 rs6000_xcoff64_aix_vec) tb="$tb coff64-rs6000.lo xcofflink.lo aix5ppc-core.lo"; target_size=64 ;;
10061--- original-binutils/bfd/configure.ac
10062+++ binutils-2.25/bfd/configure.ac
10063@@ -907,6 +907,8 @@ do
10064 powerpc_pei_vec) tb="$tb pei-ppc.lo peigen.lo cofflink.lo" ;;
10065 powerpc_pei_le_vec) tb="$tb pei-ppc.lo peigen.lo cofflink.lo" ;;
10066 powerpc_xcoff_vec) tb="$tb coff-rs6000.lo xcofflink.lo" ;;
10067+ riscv_elf32_vec) tb="$tb elf32-riscv.lo elfxx-riscv.lo elf32.lo $elf" ;;
10068+ riscv_elf64_vec) tb="$tb elf64-riscv.lo elf64.lo elfxx-riscv.lo elf32.lo $elf"; target_size=64 ;;
10069 rl78_elf32_vec) tb="$tb elf32-rl78.lo elf32.lo $elf" ;;
10070 rs6000_xcoff64_vec) tb="$tb coff64-rs6000.lo xcofflink.lo aix5ppc-core.lo"; target_size=64 ;;
10071 rs6000_xcoff64_aix_vec) tb="$tb coff64-rs6000.lo xcofflink.lo aix5ppc-core.lo"; target_size=64 ;;
10072--- original-binutils/bfd/elf-bfd.h
10073+++ binutils-2.25/bfd/elf-bfd.h
10074@@ -433,6 +433,7 @@ enum elf_target_id
10075 XGATE_ELF_DATA,
10076 TILEGX_ELF_DATA,
10077 TILEPRO_ELF_DATA,
10078+ RISCV_ELF_DATA,
10079 GENERIC_ELF_DATA
10080 };
10081
10082--- original-binutils/bfd/Makefile.am
10083+++ binutils-2.25/bfd/Makefile.am
10084@@ -931,6 +931,18 @@ elf64-ia64.c : elfnn-ia64.c
10085 sed -e s/NN/64/g < $(srcdir)/elfnn-ia64.c > elf64-ia64.new
10086 mv -f elf64-ia64.new elf64-ia64.c
10087
10088+elf32-riscv.c : elfnn-riscv.c
10089+ rm -f elf32-riscv.c
10090+ echo "#line 1 \"$(srcdir)/elfnn-riscv.c\"" > elf32-riscv.new
10091+ sed -e s/NN/32/g < $(srcdir)/elfnn-riscv.c >> elf32-riscv.new
10092+ mv -f elf32-riscv.new elf32-riscv.c
10093+
10094+elf64-riscv.c : elfnn-riscv.c
10095+ rm -f elf64-riscv.c
10096+ echo "#line 1 \"$(srcdir)/elfnn-riscv.c\"" > elf64-riscv.new
10097+ sed -e s/NN/64/g < $(srcdir)/elfnn-riscv.c >> elf64-riscv.new
10098+ mv -f elf64-riscv.new elf64-riscv.c
10099+
10100 peigen.c : peXXigen.c
10101 rm -f peigen.c
10102 sed -e s/XX/pe/g < $(srcdir)/peXXigen.c > peigen.new
10103--- original-binutils/bfd/Makefile.in
10104+++ binutils-2.25/bfd/Makefile.in
10105@@ -2009,6 +2009,18 @@ elf64-ia64.c : elfnn-ia64.c
10106 sed -e s/NN/64/g < $(srcdir)/elfnn-ia64.c > elf64-ia64.new
10107 mv -f elf64-ia64.new elf64-ia64.c
10108
10109+elf32-riscv.c : elfnn-riscv.c
10110+ rm -f elf32-riscv.c
10111+ echo "#line 1 \"$(srcdir)/elfnn-riscv.c\"" > elf32-riscv.new
10112+ sed -e s/NN/32/g < $(srcdir)/elfnn-riscv.c >> elf32-riscv.new
10113+ mv -f elf32-riscv.new elf32-riscv.c
10114+
10115+elf64-riscv.c : elfnn-riscv.c
10116+ rm -f elf64-riscv.c
10117+ echo "#line 1 \"$(srcdir)/elfnn-riscv.c\"" > elf64-riscv.new
10118+ sed -e s/NN/64/g < $(srcdir)/elfnn-riscv.c >> elf64-riscv.new
10119+ mv -f elf64-riscv.new elf64-riscv.c
10120+
10121 peigen.c : peXXigen.c
10122 rm -f peigen.c
10123 sed -e s/XX/pe/g < $(srcdir)/peXXigen.c > peigen.new
10124--- original-binutils/bfd/targets.c
10125+++ binutils-2.25/bfd/targets.c
10126@@ -784,6 +784,8 @@ extern const bfd_target powerpc_pe_le_ve
10127 extern const bfd_target powerpc_pei_vec;
10128 extern const bfd_target powerpc_pei_le_vec;
10129 extern const bfd_target powerpc_xcoff_vec;
10130+extern const bfd_target riscv_elf32_vec;
10131+extern const bfd_target riscv_elf64_vec;
10132 extern const bfd_target rl78_elf32_vec;
10133 extern const bfd_target rs6000_xcoff64_vec;
10134 extern const bfd_target rs6000_xcoff64_aix_vec;
10135--- original-binutils/binutils/readelf.c
10136+++ binutils-2.25/binutils/readelf.c
10137@@ -125,6 +125,7 @@
10138 #include "elf/metag.h"
10139 #include "elf/microblaze.h"
10140 #include "elf/mips.h"
10141+#include "elf/riscv.h"
10142 #include "elf/mmix.h"
10143 #include "elf/mn10200.h"
10144 #include "elf/mn10300.h"
10145@@ -720,6 +721,7 @@ guess_is_rela (unsigned int e_machine)
10146 case EM_OR1K:
10147 case EM_PPC64:
10148 case EM_PPC:
10149+ case EM_RISCV:
10150 case EM_RL78:
10151 case EM_RX:
10152 case EM_S390:
10153@@ -1252,6 +1254,10 @@ dump_relocations (FILE * file,
10154 rtype = elf_mips_reloc_type (type);
10155 break;
10156
10157+ case EM_RISCV:
10158+ rtype = elf_riscv_reloc_type (type);
10159+ break;
10160+
10161 case EM_ALPHA:
10162 rtype = elf_alpha_reloc_type (type);
10163 break;
10164@@ -2164,6 +2170,7 @@ get_machine_name (unsigned e_machine)
10165 case EM_CR16:
10166 case EM_MICROBLAZE:
10167 case EM_MICROBLAZE_OLD: return "Xilinx MicroBlaze";
10168+ case EM_RISCV: return "RISC-V";
10169 case EM_RL78: return "Renesas RL78";
10170 case EM_RX: return "Renesas RX";
10171 case EM_METAG: return "Imagination Technologies Meta processor architecture";
10172@@ -2951,6 +2958,18 @@ get_machine_flags (unsigned e_flags, uns
10173 decode_NDS32_machine_flags (e_flags, buf, sizeof buf);
10174 break;
10175
10176+ case EM_RISCV:
10177+ {
10178+ if (e_flags & EF_RISCV_RVC)
10179+ strcat (buf, ", RVC");
10180+
10181+ if (!EF_GET_RISCV_EXT (e_flags))
10182+ break;
10183+ strcat (buf, ", ");
10184+ strcat (buf, riscv_elf_flag_to_name (EF_GET_RISCV_EXT (e_flags)));
10185+ }
10186+ break;
10187+
10188 case EM_SH:
10189 switch ((e_flags & EF_SH_MACH_MASK))
10190 {
10191@@ -10789,6 +10808,8 @@ is_32bit_abs_reloc (unsigned int reloc_t
10192 return reloc_type == 1; /* R_PPC64_ADDR32. */
10193 case EM_PPC:
10194 return reloc_type == 1; /* R_PPC_ADDR32. */
10195+ case EM_RISCV:
10196+ return reloc_type == 1; /* R_RISCV_32. */
10197 case EM_RL78:
10198 return reloc_type == 1; /* R_RL78_DIR32. */
10199 case EM_RX:
10200@@ -10924,6 +10945,8 @@ is_64bit_abs_reloc (unsigned int reloc_t
10201 return reloc_type == 80; /* R_PARISC_DIR64. */
10202 case EM_PPC64:
10203 return reloc_type == 38; /* R_PPC64_ADDR64. */
10204+ case EM_RISCV:
10205+ return reloc_type == 2; /* R_RISCV_64. */
10206 case EM_SPARC32PLUS:
10207 case EM_SPARCV9:
10208 case EM_SPARC:
10209@@ -11072,6 +11095,7 @@ is_none_reloc (unsigned int reloc_type)
10210 case EM_ADAPTEVA_EPIPHANY:
10211 case EM_PPC: /* R_PPC_NONE. */
10212 case EM_PPC64: /* R_PPC64_NONE. */
10213+ case EM_RISCV: /* R_RISCV_NONE. */
10214 case EM_ARM: /* R_ARM_NONE. */
10215 case EM_IA_64: /* R_IA64_NONE. */
10216 case EM_SH: /* R_SH_NONE. */
10217--- original-binutils/config.sub
10218+++ binutils-2.25/config.sub
10219@@ -335,6 +335,9 @@ case $basic_machine in
10220 ms1)
10221 basic_machine=mt-unknown
10222 ;;
10223+ riscv)
10224+ basic_machine=riscv-ucb
10225+ ;;
10226
10227 strongarm | thumb | xscale)
10228 basic_machine=arm-unknown
10229--- original-binutils/gas/configure.ac
10230+++ binutils-2.25/gas/configure.ac
10231@@ -453,7 +453,7 @@ changequote([,])dnl
10232 AC_MSG_RESULT($enable_audio_ext)
10233 ;;
10234
10235- i386 | s390 | sparc)
10236+ i386 | riscv | s390 | sparc)
10237 if test $this_target = $target ; then
10238 AC_DEFINE_UNQUOTED(DEFAULT_ARCH, "${arch}", [Default architecture.])
10239 fi
10240--- original-binutils/gas/configure
10241+++ binutils-2.25/gas/configure
10242@@ -12402,7 +12402,7 @@ $as_echo "#define NDS32_DEFAULT_AUDIO_EXT 1" >>confdefs.h
10243 $as_echo "$enable_audio_ext" >&6; }
10244 ;;
10245
10246- i386 | s390 | sparc)
10247+ i386 | riscv | s390 | sparc)
10248 if test $this_target = $target ; then
10249
10250 cat >>confdefs.h <<_ACEOF
10251--- original-binutils/gas/configure.tgt
10252+++ binutils-2.25/gas/configure.tgt
10253@@ -86,6 +86,8 @@ case ${cpu} in
10254 pj*) cpu_type=pj endian=big ;;
10255 powerpc*le*) cpu_type=ppc endian=little ;;
10256 powerpc*) cpu_type=ppc endian=big ;;
10257+ riscv32*) cpu_type=riscv endian=little arch=riscv32 ;;
10258+ riscv*) cpu_type=riscv endian=little arch=riscv64 ;;
10259 rs6000*) cpu_type=ppc ;;
10260 rl78*) cpu_type=rl78 ;;
10261 rx) cpu_type=rx ;;
10262@@ -384,6 +385,8 @@ case ${generic_target} in
10263 ppc-*-kaos*) fmt=elf ;;
10264 ppc-*-lynxos*) fmt=elf em=lynx ;;
10265
10266+ riscv*-*-*) fmt=elf endian=little em=linux ;;
10267+
10268 s390-*-linux-*) fmt=elf em=linux ;;
10269 s390-*-tpf*) fmt=elf ;;
10270
10271@@ -489,7 +490,7 @@ case ${generic_target} in
10272 esac
10273
10274 case ${cpu_type} in
10275- aarch64 | alpha | arm | i386 | ia64 | microblaze | mips | ns32k | or1k | or1knd | pdp11 | ppc | sparc | z80 | z8k)
10276+ aarch64 | alpha | arm | i386 | ia64 | microblaze | mips | ns32k | or1k | or1knd | pdp11 | ppc | riscv | sparc | z80 | z8k)
10277 bfd_gas=yes
10278 ;;
10279 esac
10280--- original-binutils/gas/Makefile.am
10281+++ binutils-2.25/gas/Makefile.am
10282@@ -171,6 +171,7 @@ TARGET_CPU_CFILES = \
10283 config/tc-pdp11.c \
10284 config/tc-pj.c \
10285 config/tc-ppc.c \
10286+ config/tc-riscv.c \
10287 config/tc-rl78.c \
10288 config/tc-rx.c \
10289 config/tc-s390.c \
10290@@ -242,6 +243,7 @@ TARGET_CPU_HFILES = \
10291 config/tc-pdp11.h \
10292 config/tc-pj.h \
10293 config/tc-ppc.h \
10294+ config/tc-riscv.h \
10295 config/tc-rl78.h \
10296 config/tc-rx.h \
10297 config/tc-s390.h \
10298--- original-binutils/gas/Makefile.in
10299+++ binutils-2.25/gas/Makefile.in
10300@@ -440,6 +440,7 @@ TARGET_CPU_CFILES = \
10301 config/tc-pdp11.c \
10302 config/tc-pj.c \
10303 config/tc-ppc.c \
10304+ config/tc-riscv.c \
10305 config/tc-rl78.c \
10306 config/tc-rx.c \
10307 config/tc-s390.c \
10308@@ -511,6 +512,7 @@ TARGET_CPU_HFILES = \
10309 config/tc-pdp11.h \
10310 config/tc-pj.h \
10311 config/tc-ppc.h \
10312+ config/tc-riscv.h \
10313 config/tc-rl78.h \
10314 config/tc-rx.h \
10315 config/tc-s390.h \
10316@@ -866,6 +868,7 @@ distclean-compile:
10317 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tc-pdp11.Po@am__quote@
10318 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tc-pj.Po@am__quote@
10319 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tc-ppc.Po@am__quote@
10320+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tc-riscv.Po@am__quote@
10321 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tc-rl78.Po@am__quote@
10322 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tc-rx.Po@am__quote@
10323 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tc-s390.Po@am__quote@
10324@@ -1571,6 +1574,20 @@ tc-ppc.obj: config/tc-ppc.c
10325 @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
10326 @am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o tc-ppc.obj `if test -f 'config/tc-ppc.c'; then $(CYGPATH_W) 'config/tc-ppc.c'; else $(CYGPATH_W) '$(srcdir)/config/tc-ppc.c'; fi`
10327
10328+tc-riscv.o: config/tc-riscv.c
10329+@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT tc-riscv.o -MD -MP -MF $(DEPDIR)/tc-riscv.Tpo -c -o tc-riscv.o `test -f 'config/tc-riscv.c' || echo '$(srcdir)/'`config/tc-riscv.c
10330+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/tc-riscv.Tpo $(DEPDIR)/tc-riscv.Po
10331+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='config/tc-riscv.c' object='tc-riscv.o' libtool=no @AMDEPBACKSLASH@
10332+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
10333+@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o tc-riscv.o `test -f 'config/tc-riscv.c' || echo '$(srcdir)/'`config/tc-riscv.c
10334+
10335+tc-riscv.obj: config/tc-riscv.c
10336+@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT tc-riscv.obj -MD -MP -MF $(DEPDIR)/tc-riscv.Tpo -c -o tc-riscv.obj `if test -f 'config/tc-riscv.c'; then $(CYGPATH_W) 'config/tc-riscv.c'; else $(CYGPATH_W) '$(srcdir)/config/tc-riscv.c'; fi`
10337+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/tc-riscv.Tpo $(DEPDIR)/tc-riscv.Po
10338+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='config/tc-riscv.c' object='tc-riscv.obj' libtool=no @AMDEPBACKSLASH@
10339+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
10340+@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o tc-riscv.obj `if test -f 'config/tc-riscv.c'; then $(CYGPATH_W) 'config/tc-riscv.c'; else $(CYGPATH_W) '$(srcdir)/config/tc-riscv.c'; fi`
10341+
10342 tc-rl78.o: config/tc-rl78.c
10343 @am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT tc-rl78.o -MD -MP -MF $(DEPDIR)/tc-rl78.Tpo -c -o tc-rl78.o `test -f 'config/tc-rl78.c' || echo '$(srcdir)/'`config/tc-rl78.c
10344 @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/tc-rl78.Tpo $(DEPDIR)/tc-rl78.Po
10345--- original-binutils/include/dis-asm.h
10346+++ binutils-2.25/include/dis-asm.h
10347@@ -254,6 +254,7 @@ extern int print_insn_little_arm (bfd_vm
10348 extern int print_insn_little_mips (bfd_vma, disassemble_info *);
10349 extern int print_insn_little_nios2 (bfd_vma, disassemble_info *);
10350 extern int print_insn_little_powerpc (bfd_vma, disassemble_info *);
10351+extern int print_insn_riscv (bfd_vma, disassemble_info *);
10352 extern int print_insn_little_score (bfd_vma, disassemble_info *);
10353 extern int print_insn_lm32 (bfd_vma, disassemble_info *);
10354 extern int print_insn_m32c (bfd_vma, disassemble_info *);
10355@@ -313,6 +314,7 @@ extern void print_aarch64_disassembler_o
10356 extern void print_i386_disassembler_options (FILE *);
10357 extern void print_mips_disassembler_options (FILE *);
10358 extern void print_ppc_disassembler_options (FILE *);
10359+extern void print_riscv_disassembler_options (FILE *);
10360 extern void print_arm_disassembler_options (FILE *);
10361 extern void parse_arm_disassembler_option (char *);
10362 extern void print_s390_disassembler_options (FILE *);
10363--- original-binutils/include/elf/common.h
10364+++ binutils-2.25/include/elf/common.h
10365@@ -301,6 +301,7 @@
10366 #define EM_INTEL207 207 /* Reserved by Intel */
10367 #define EM_INTEL208 208 /* Reserved by Intel */
10368 #define EM_INTEL209 209 /* Reserved by Intel */
10369+#define EM_RISCV 243 /* Reserved by Intel */
10370
10371 /* If it is necessary to assign new unofficial EM_* values, please pick large
10372 random numbers (0x8523, 0xa7f2, etc.) to minimize the chances of collision
10373--- original-binutils/ld/configure.tgt
10374+++ binutils-2.25/ld/configure.tgt
10375@@ -604,6 +604,12 @@ powerpc-*-aix*) targ_emul=aixppc ;;
10376 powerpc-*-beos*) targ_emul=aixppc ;;
10377 powerpc-*-windiss*) targ_emul=elf32ppcwindiss ;;
10378 powerpc-*-lynxos*) targ_emul=ppclynx ;;
10379+riscv32*-*-*) targ_emul=elf32lriscv
10380+ targ_extra_emuls="elf64lriscv"
10381+ targ_extra_libpath=$targ_extra_emuls ;;
10382+riscv*-*-*) targ_emul=elf64lriscv
10383+ targ_extra_emuls="elf32lriscv"
10384+ targ_extra_libpath=$targ_extra_emuls ;;
10385 rs6000-*-aix[5-9]*) targ_emul=aix5rs6 ;;
10386 rs6000-*-aix*) targ_emul=aixrs6
10387 ;;
10388--- original-binutils/ld/Makefile.am
10389+++ binutils-2.25/ld/Makefile.am
10390@@ -258,6 +258,7 @@ ALL_EMULATION_SOURCES = \
10391 eelf32ppcsim.c \
10392 eelf32ppcvxworks.c \
10393 eelf32ppcwindiss.c \
10394+ eelf32lriscv.c \
10395 eelf32rl78.c \
10396 eelf32rx.c \
10397 eelf32tilegx.c \
10398@@ -464,6 +465,7 @@ ALL_64_EMULATION_SOURCES = \
10399 eelf64btsmip_fbsd.c \
10400 eelf64hppa.c \
10401 eelf64lppc.c \
10402+ eelf64lriscv.c \
10403 eelf64ltsmip.c \
10404 eelf64ltsmip_fbsd.c \
10405 eelf64mmix.c \
10406@@ -1104,6 +1106,11 @@ eelf32lppcsim.c: $(srcdir)/emulparams/el
10407 ldemul-list.h \
10408 $(ELF_DEPS) $(srcdir)/scripttempl/elf.sc ${GEN_DEPENDS}
10409
10410+eelf32lriscv.c: $(srcdir)/emulparams/elf32lriscv.sh \
10411+ $(srcdir)/emulparams/elf32lriscv-defs.sh $(ELF_DEPS) \
10412+ $(srcdir)/emultempl/riscvelf.em $(srcdir)/scripttempl/elf.sc \
10413+ ${GEN_DEPENDS}
10414+
10415 eelf32lsmip.c: $(srcdir)/emulparams/elf32lsmip.sh \
10416 $(srcdir)/emulparams/elf32lmip.sh $(srcdir)/emulparams/elf32bmip.sh \
10417 $(ELF_DEPS) $(srcdir)/emultempl/mipself.em $(srcdir)/scripttempl/elf.sc \
10418@@ -1861,6 +1868,12 @@ eelf64lppc.c: $(srcdir)/emulparams/elf64
10419 ldemul-list.h \
10420 $(ELF_DEPS) $(srcdir)/scripttempl/elf.sc ${GEN_DEPENDS}
10421
10422+eelf64lriscv.c: $(srcdir)/emulparams/elf64lriscv.sh \
10423+ $(srcdir)/emulparams/elf64lriscv-defs.sh \
10424+ $(srcdir)/emulparams/elf32lriscv-defs.sh $(ELF_DEPS) \
10425+ $(srcdir)/emultempl/riscvelf.em $(srcdir)/scripttempl/elf.sc \
10426+ ${GEN_DEPENDS}
10427+
10428 eelf64ltsmip.c: $(srcdir)/emulparams/elf64ltsmip.sh \
10429 $(srcdir)/emulparams/elf64btsmip.sh $(srcdir)/emulparams/elf64bmip-defs.sh \
10430 $(srcdir)/emulparams/elf32bmipn32-defs.sh $(ELF_DEPS) \
10431--- original-binutils/ld/Makefile.in
10432+++ binutils-2.25/ld/Makefile.in
10433@@ -546,6 +546,7 @@ ALL_EMULATION_SOURCES = \
10434 eelf32lppclinux.c \
10435 eelf32lppcnto.c \
10436 eelf32lppcsim.c \
10437+ eelf32lriscv.c \
10438 eelf32m32c.c \
10439 eelf32mb_linux.c \
10440 eelf32mbel_linux.c \
10441@@ -771,6 +772,7 @@ ALL_64_EMULATION_SOURCES = \
10442 eelf64btsmip_fbsd.c \
10443 eelf64hppa.c \
10444 eelf64lppc.c \
10445+ eelf64lriscv.c \
10446 eelf64ltsmip.c \
10447 eelf64ltsmip_fbsd.c \
10448 eelf64mmix.c \
10449@@ -1157,6 +1159,7 @@ distclean-compile:
10450 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf32lppclinux.Po@am__quote@
10451 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf32lppcnto.Po@am__quote@
10452 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf32lppcsim.Po@am__quote@
10453+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf32lriscv.Po@am__quote@
10454 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf32lr5900.Po@am__quote@
10455 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf32lr5900n32.Po@am__quote@
10456 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf32lsmip.Po@am__quote@
10457@@ -1211,6 +1214,7 @@ distclean-compile:
10458 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf64btsmip_fbsd.Po@am__quote@
10459 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf64hppa.Po@am__quote@
10460 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf64lppc.Po@am__quote@
10461+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf64lriscv.Po@am__quote@
10462 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf64ltsmip.Po@am__quote@
10463 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf64ltsmip_fbsd.Po@am__quote@
10464 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf64mmix.Po@am__quote@
10465@@ -2545,6 +2549,11 @@ eelf32lppcsim.c: $(srcdir)/emulparams/el
10466 ldemul-list.h \
10467 $(ELF_DEPS) $(srcdir)/scripttempl/elf.sc ${GEN_DEPENDS}
10468
10469+eelf32lriscv.c: $(srcdir)/emulparams/elf32lriscv.sh \
10470+ $(srcdir)/emulparams/elf32lriscv-defs.sh $(ELF_DEPS) \
10471+ $(srcdir)/emultempl/riscvelf.em $(srcdir)/scripttempl/elf.sc \
10472+ ${GEN_DEPENDS}
10473+
10474 eelf32lsmip.c: $(srcdir)/emulparams/elf32lsmip.sh \
10475 $(srcdir)/emulparams/elf32lmip.sh $(srcdir)/emulparams/elf32bmip.sh \
10476 $(ELF_DEPS) $(srcdir)/emultempl/mipself.em $(srcdir)/scripttempl/elf.sc \
10477@@ -3302,6 +3311,12 @@ eelf64lppc.c: $(srcdir)/emulparams/elf64
10478 ldemul-list.h \
10479 $(ELF_DEPS) $(srcdir)/scripttempl/elf.sc ${GEN_DEPENDS}
10480
10481+eelf64lriscv.c: $(srcdir)/emulparams/elf64lriscv.sh \
10482+ $(srcdir)/emulparams/elf64lriscv-defs.sh \
10483+ $(srcdir)/emulparams/elf32lriscv-defs.sh $(ELF_DEPS) \
10484+ $(srcdir)/emultempl/riscvelf.em $(srcdir)/scripttempl/elf.sc \
10485+ ${GEN_DEPENDS}
10486+
10487 eelf64ltsmip.c: $(srcdir)/emulparams/elf64ltsmip.sh \
10488 $(srcdir)/emulparams/elf64btsmip.sh $(srcdir)/emulparams/elf64bmip-defs.sh \
10489 $(srcdir)/emulparams/elf32bmipn32-defs.sh $(ELF_DEPS) \
10490--- original-binutils/opcodes/configure
10491+++ binutils-2.25/opcodes/configure
10492@@ -12590,6 +12590,7 @@ if test x${all_targets} = xfalse ; then
10493 bfd_powerpc_arch) ta="$ta ppc-dis.lo ppc-opc.lo" ;;
10494 bfd_powerpc_64_arch) ta="$ta ppc-dis.lo ppc-opc.lo" ;;
10495 bfd_pyramid_arch) ;;
10496+ bfd_riscv_arch) ta="$ta riscv-dis.lo riscv-opc.lo" ;;
10497 bfd_romp_arch) ;;
10498 bfd_rs6000_arch) ta="$ta ppc-dis.lo ppc-opc.lo" ;;
10499 bfd_rl78_arch) ta="$ta rl78-dis.lo rl78-decode.lo";;
10500--- original-binutils/opcodes/disassemble.c
10501+++ binutils-2.25/opcodes/disassemble.c
10502@@ -373,6 +373,11 @@ disassembler (abfd)
10503 disassemble = print_insn_little_powerpc;
10504 break;
10505 #endif
10506+#ifdef ARCH_riscv
10507+ case bfd_arch_riscv:
10508+ disassemble = print_insn_riscv;
10509+ break;
10510+#endif
10511 #ifdef ARCH_rs6000
10512 case bfd_arch_rs6000:
10513 if (bfd_get_mach (abfd) == bfd_mach_ppc_620)
10514@@ -545,6 +550,9 @@ disassembler_usage (stream)
10515 #ifdef ARCH_powerpc
10516 print_ppc_disassembler_options (stream);
10517 #endif
10518+#ifdef ARCH_riscv
10519+ print_riscv_disassembler_options (stream);
10520+#endif
10521 #ifdef ARCH_i386
10522 print_i386_disassembler_options (stream);
10523 #endif
10524--- original-binutils/bfd/Makefile.in 2014-10-14 00:32:02.000000000 -0700
10525+++ binutils-2.25/bfd/Makefile.in 2015-03-31 06:53:23.253426230 -0700
10526@@ -442,6 +442,7 @@
10527 cpu-pj.lo \
10528 cpu-plugin.lo \
10529 cpu-powerpc.lo \
10530+ cpu-riscv.lo \
10531 cpu-rs6000.lo \
10532 cpu-rl78.lo \
10533 cpu-rx.lo \
10534@@ -526,6 +527,7 @@
10535 cpu-pj.c \
10536 cpu-plugin.c \
10537 cpu-powerpc.c \
10538+ cpu-riscv.c \
10539 cpu-rs6000.c \
10540 cpu-rl78.c \
10541 cpu-rx.c \