aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--bfd/elfnn-riscv.c27
-rw-r--r--bfd/elfxx-riscv.c69
-rw-r--r--bfd/elfxx-riscv.h8
-rw-r--r--gas/config/tc-riscv.c110
-rw-r--r--gas/testsuite/gas/riscv/mapping-04b.d4
-rw-r--r--gas/testsuite/gas/riscv/mapping-norelax-03b.d2
-rw-r--r--gas/testsuite/gas/riscv/mapping-norelax-04b.d4
-rw-r--r--opcodes/riscv-dis.c32
8 files changed, 133 insertions, 123 deletions
diff --git a/bfd/elfnn-riscv.c b/bfd/elfnn-riscv.c
index 2bae1e9..36cbf1e 100644
--- a/bfd/elfnn-riscv.c
+++ b/bfd/elfnn-riscv.c
@@ -3574,37 +3574,22 @@ riscv_merge_arch_attr_info (bfd *ibfd, char *in_arch, char *out_arch)
merged_subsets.head = NULL;
merged_subsets.tail = NULL;
- riscv_parse_subset_t rpe_in;
- riscv_parse_subset_t rpe_out;
-
- /* Only assembler needs to check the default version of ISA, so just set
- the rpe_in.get_default_version and rpe_out.get_default_version to NULL. */
- rpe_in.subset_list = &in_subsets;
- rpe_in.error_handler = _bfd_error_handler;
- rpe_in.xlen = &xlen_in;
- rpe_in.isa_spec = ISA_SPEC_CLASS_NONE;
- rpe_in.check_unknown_prefixed_ext = false;
-
- rpe_out.subset_list = &out_subsets;
- rpe_out.error_handler = _bfd_error_handler;
- rpe_out.xlen = &xlen_out;
- rpe_out.isa_spec = ISA_SPEC_CLASS_NONE;
- rpe_out.check_unknown_prefixed_ext = false;
+ riscv_parse_subset_t riscv_rps_ld_in =
+ {&in_subsets, _bfd_error_handler, &xlen_in, NULL, false};
+ riscv_parse_subset_t riscv_rps_ld_out =
+ {&out_subsets, _bfd_error_handler, &xlen_out, NULL, false};
if (in_arch == NULL && out_arch == NULL)
return NULL;
-
if (in_arch == NULL && out_arch != NULL)
return out_arch;
-
if (in_arch != NULL && out_arch == NULL)
return in_arch;
/* Parse subset from ISA string. */
- if (!riscv_parse_subset (&rpe_in, in_arch))
+ if (!riscv_parse_subset (&riscv_rps_ld_in, in_arch))
return NULL;
-
- if (!riscv_parse_subset (&rpe_out, out_arch))
+ if (!riscv_parse_subset (&riscv_rps_ld_out, out_arch))
return NULL;
/* Checking XLEN. */
diff --git a/bfd/elfxx-riscv.c b/bfd/elfxx-riscv.c
index 65bb1ca..3ffbaad 100644
--- a/bfd/elfxx-riscv.c
+++ b/bfd/elfxx-riscv.c
@@ -1418,12 +1418,14 @@ riscv_add_subset (riscv_subset_list_t *subset_list,
/* Get the default versions from the riscv_supported_*ext tables. */
static void
-riscv_get_default_ext_version (enum riscv_spec_class default_isa_spec,
+riscv_get_default_ext_version (enum riscv_spec_class *default_isa_spec,
const char *name,
int *major_version,
int *minor_version)
{
- if (name == NULL || default_isa_spec == ISA_SPEC_CLASS_NONE)
+ if (name == NULL
+ || default_isa_spec == NULL
+ || *default_isa_spec == ISA_SPEC_CLASS_NONE)
return;
struct riscv_supported_ext *table = NULL;
@@ -1445,7 +1447,7 @@ riscv_get_default_ext_version (enum riscv_spec_class default_isa_spec,
{
if (strcmp (table[i].name, name) == 0
&& (table[i].isa_spec_class == ISA_SPEC_CLASS_DRAFT
- || table[i].isa_spec_class == default_isa_spec))
+ || table[i].isa_spec_class == *default_isa_spec))
{
*major_version = table[i].major_version;
*minor_version = table[i].minor_version;
@@ -2095,3 +2097,64 @@ riscv_update_subset (riscv_parse_subset_t *rps,
riscv_parse_add_implicit_subsets (rps);
return riscv_parse_check_conflicts (rps);
}
+
+/* Check if the FEATURE subset is supported or not in the subset list.
+ Return true if it is supported; Otherwise, return false. */
+
+bool
+riscv_subset_supports (riscv_parse_subset_t *rps,
+ const char *feature)
+{
+ struct riscv_subset_t *subset;
+ return riscv_lookup_subset (rps->subset_list, feature, &subset);
+}
+
+/* Each instuction is belonged to an instruction class INSN_CLASS_*.
+ Call riscv_subset_supports to make sure if the instuction is valid. */
+
+bool
+riscv_multi_subset_supports (riscv_parse_subset_t *rps,
+ enum riscv_insn_class insn_class)
+{
+ switch (insn_class)
+ {
+ case INSN_CLASS_I:
+ return riscv_subset_supports (rps, "i");
+ case INSN_CLASS_ZICSR:
+ return riscv_subset_supports (rps, "zicsr");
+ case INSN_CLASS_ZIFENCEI:
+ return riscv_subset_supports (rps, "zifencei");
+ case INSN_CLASS_ZIHINTPAUSE:
+ return riscv_subset_supports (rps, "zihintpause");
+ case INSN_CLASS_M:
+ return riscv_subset_supports (rps, "m");
+ case INSN_CLASS_A:
+ return riscv_subset_supports (rps, "a");
+ case INSN_CLASS_F:
+ return riscv_subset_supports (rps, "f");
+ case INSN_CLASS_D:
+ return riscv_subset_supports (rps, "d");
+ case INSN_CLASS_Q:
+ return riscv_subset_supports (rps, "q");
+ case INSN_CLASS_C:
+ return riscv_subset_supports (rps, "c");
+ case INSN_CLASS_F_AND_C:
+ return (riscv_subset_supports (rps, "f")
+ && riscv_subset_supports (rps, "c"));
+ case INSN_CLASS_D_AND_C:
+ return (riscv_subset_supports (rps, "d")
+ && riscv_subset_supports (rps, "c"));
+ case INSN_CLASS_ZBA:
+ return riscv_subset_supports (rps, "zba");
+ case INSN_CLASS_ZBB:
+ return riscv_subset_supports (rps, "zbb");
+ case INSN_CLASS_ZBC:
+ return riscv_subset_supports (rps, "zbc");
+ case INSN_CLASS_ZBS:
+ return riscv_subset_supports (rps, "zbs");
+ default:
+ rps->error_handler
+ (_("internal: unreachable INSN_CLASS_*"));
+ return false;
+ }
+}
diff --git a/bfd/elfxx-riscv.h b/bfd/elfxx-riscv.h
index 17620fd..8de9adc 100644
--- a/bfd/elfxx-riscv.h
+++ b/bfd/elfxx-riscv.h
@@ -72,7 +72,7 @@ typedef struct
void (*error_handler) (const char *,
...) ATTRIBUTE_PRINTF_1;
unsigned *xlen;
- enum riscv_spec_class isa_spec;
+ enum riscv_spec_class *isa_spec;
bool check_unknown_prefixed_ext;
} riscv_parse_subset_t;
@@ -95,6 +95,12 @@ riscv_compare_subsets (const char *, const char *);
extern bool
riscv_update_subset (riscv_parse_subset_t *, const char *, bool);
+extern bool
+riscv_subset_supports (riscv_parse_subset_t *, const char *);
+
+extern bool
+riscv_multi_subset_supports (riscv_parse_subset_t *, enum riscv_insn_class);
+
extern void
bfd_elf32_riscv_set_data_segment_info (struct bfd_link_info *, int *);
extern void
diff --git a/gas/config/tc-riscv.c b/gas/config/tc-riscv.c
index 90d960a..8cea72a 100644
--- a/gas/config/tc-riscv.c
+++ b/gas/config/tc-riscv.c
@@ -234,77 +234,20 @@ riscv_set_rvc (bool rvc_value)
-march option, the elf architecture attributes, and the --with-arch
configure option. */
static riscv_subset_list_t riscv_subsets;
-
-/* Check if the FEATURE subset is supported or not in the subset list.
- Return true if it is supported; Otherwise, return false. */
-
-static bool
-riscv_subset_supports (const char *feature)
-{
- struct riscv_subset_t *subset;
- return riscv_lookup_subset (&riscv_subsets, feature, &subset);
-}
-
-/* Each instuction is belonged to an instruction class INSN_CLASS_*.
- Call riscv_subset_supports to make sure if the instuction is valid. */
-
-static bool
-riscv_multi_subset_supports (enum riscv_insn_class insn_class)
+static riscv_parse_subset_t riscv_rps_as =
{
- switch (insn_class)
- {
- case INSN_CLASS_I:
- return riscv_subset_supports ("i");
- case INSN_CLASS_ZICSR:
- return riscv_subset_supports ("zicsr");
- case INSN_CLASS_ZIFENCEI:
- return riscv_subset_supports ("zifencei");
- case INSN_CLASS_ZIHINTPAUSE:
- return riscv_subset_supports ("zihintpause");
- case INSN_CLASS_M:
- return riscv_subset_supports ("m");
- case INSN_CLASS_A:
- return riscv_subset_supports ("a");
- case INSN_CLASS_F:
- return riscv_subset_supports ("f");
- case INSN_CLASS_D:
- return riscv_subset_supports ("d");
- case INSN_CLASS_Q:
- return riscv_subset_supports ("q");
- case INSN_CLASS_C:
- return riscv_subset_supports ("c");
- case INSN_CLASS_F_AND_C:
- return (riscv_subset_supports ("f")
- && riscv_subset_supports ("c"));
- case INSN_CLASS_D_AND_C:
- return (riscv_subset_supports ("d")
- && riscv_subset_supports ("c"));
- case INSN_CLASS_ZBA:
- return riscv_subset_supports ("zba");
- case INSN_CLASS_ZBB:
- return riscv_subset_supports ("zbb");
- case INSN_CLASS_ZBC:
- return riscv_subset_supports ("zbc");
- case INSN_CLASS_ZBS:
- return riscv_subset_supports ("zbs");
- default:
- as_fatal ("internal: unreachable");
- return false;
- }
-}
+ &riscv_subsets, /* subset_list. */
+ as_bad, /* error_handler. */
+ &xlen, /* xlen. */
+ &default_isa_spec, /* isa_spec. */
+ true, /* check_unknown_prefixed_ext. */
+};
/* Set which ISA and extensions are available. */
static void
riscv_set_arch (const char *s)
{
- riscv_parse_subset_t rps;
- rps.subset_list = &riscv_subsets;
- rps.error_handler = as_bad;
- rps.xlen = &xlen;
- rps.isa_spec = default_isa_spec;
- rps.check_unknown_prefixed_ext = true;
-
if (s != NULL && strcmp (s, "") == 0)
{
as_bad (_("the architecture string of -march and elf architecture "
@@ -313,10 +256,10 @@ riscv_set_arch (const char *s)
}
riscv_release_subset_list (&riscv_subsets);
- riscv_parse_subset (&rps, s);
+ riscv_parse_subset (&riscv_rps_as, s);
riscv_set_rvc (false);
- if (riscv_subset_supports ("c"))
+ if (riscv_subset_supports (&riscv_rps_as, "c"))
riscv_set_rvc (true);
}
@@ -341,11 +284,11 @@ riscv_set_abi_by_arch (void)
{
if (!explicit_mabi)
{
- if (riscv_subset_supports ("q"))
+ if (riscv_subset_supports (&riscv_rps_as, "q"))
riscv_set_abi (xlen, FLOAT_ABI_QUAD, false);
- else if (riscv_subset_supports ("d"))
+ else if (riscv_subset_supports (&riscv_rps_as, "d"))
riscv_set_abi (xlen, FLOAT_ABI_DOUBLE, false);
- else if (riscv_subset_supports ("e"))
+ else if (riscv_subset_supports (&riscv_rps_as, "e"))
riscv_set_abi (xlen, FLOAT_ABI_SOFT, true);
else
riscv_set_abi (xlen, FLOAT_ABI_SOFT, false);
@@ -358,19 +301,19 @@ riscv_set_abi_by_arch (void)
else if (abi_xlen < xlen)
as_bad ("%d-bit ABI not yet supported on %d-bit ISA", abi_xlen, xlen);
- if (riscv_subset_supports ("e") && !rve_abi)
+ if (riscv_subset_supports (&riscv_rps_as, "e") && !rve_abi)
as_bad ("only the ilp32e ABI is supported for e extension");
if (float_abi == FLOAT_ABI_SINGLE
- && !riscv_subset_supports ("f"))
+ && !riscv_subset_supports (&riscv_rps_as, "f"))
as_bad ("ilp32f/lp64f ABI can't be used when f extension "
"isn't supported");
else if (float_abi == FLOAT_ABI_DOUBLE
- && !riscv_subset_supports ("d"))
+ && !riscv_subset_supports (&riscv_rps_as, "d"))
as_bad ("ilp32d/lp64d ABI can't be used when d extension "
"isn't supported");
else if (float_abi == FLOAT_ABI_QUAD
- && !riscv_subset_supports ("q"))
+ && !riscv_subset_supports (&riscv_rps_as, "q"))
as_bad ("ilp32q/lp64q ABI can't be used when q extension "
"isn't supported");
}
@@ -923,13 +866,13 @@ riscv_csr_address (const char *csr_name,
switch (csr_class)
{
case CSR_CLASS_I:
- result = riscv_subset_supports ("i");
+ result = riscv_subset_supports (&riscv_rps_as, "i");
break;
case CSR_CLASS_I_32:
- result = (xlen == 32 && riscv_subset_supports ("i"));
+ result = (xlen == 32 && riscv_subset_supports (&riscv_rps_as, "i"));
break;
case CSR_CLASS_F:
- result = riscv_subset_supports ("f");
+ result = riscv_subset_supports (&riscv_rps_as, "f");
need_check_version = false;
break;
case CSR_CLASS_DEBUG:
@@ -995,7 +938,7 @@ reg_lookup_internal (const char *s, enum reg_class class)
if (r == NULL || DECODE_REG_CLASS (r) != class)
return -1;
- if (riscv_subset_supports ("e")
+ if (riscv_subset_supports (&riscv_rps_as, "e")
&& class == RCLASS_GPR
&& DECODE_REG_NUM (r) > 15)
return -1;
@@ -2061,7 +2004,7 @@ riscv_ip (char *str, struct riscv_cl_insn *ip, expressionS *imm_expr,
if ((insn->xlen_requirement != 0) && (xlen != insn->xlen_requirement))
continue;
- if (!riscv_multi_subset_supports (insn->insn_class))
+ if (!riscv_multi_subset_supports (&riscv_rps_as, insn->insn_class))
continue;
create_insn (ip, insn);
@@ -3364,21 +3307,14 @@ s_riscv_option (int x ATTRIBUTE_UNUSED)
ch = *input_line_pointer;
*input_line_pointer = '\0';
- riscv_parse_subset_t rps;
- rps.subset_list = &riscv_subsets;
- rps.error_handler = as_bad;
- rps.xlen = &xlen;
- rps.isa_spec = default_isa_spec;
- rps.check_unknown_prefixed_ext = true;
-
if (strcmp (name, "rvc") == 0)
{
- riscv_update_subset (&rps, "c", false);
+ riscv_update_subset (&riscv_rps_as, "c", false);
riscv_set_rvc (true);
}
else if (strcmp (name, "norvc") == 0)
{
- riscv_update_subset (&rps, "c", true);
+ riscv_update_subset (&riscv_rps_as, "c", true);
riscv_set_rvc (false);
}
else if (strcmp (name, "pic") == 0)
diff --git a/gas/testsuite/gas/riscv/mapping-04b.d b/gas/testsuite/gas/riscv/mapping-04b.d
index 9735498..54bd0af 100644
--- a/gas/testsuite/gas/riscv/mapping-04b.d
+++ b/gas/testsuite/gas/riscv/mapping-04b.d
@@ -18,6 +18,6 @@ Disassembly of section .text:
[ ]+19:[ ]+20022002[ ]+.word[ ]+0x20022002
[ ]+1d:[ ]+2002[ ]+.short[ ]+0x2002
[ ]+1f:[ ]+00b585b3[ ]+add[ ]+a1,a1,a1
-[ ]+23:[ ]+0000[ ]+unimp
-[ ]+25:[ ]+0000[ ]+unimp
+[ ]+23:[ ]+0000[ ]+.2byte[ ]+0x0
+[ ]+25:[ ]+0000[ ]+.2byte[ ]+0x0
#...
diff --git a/gas/testsuite/gas/riscv/mapping-norelax-03b.d b/gas/testsuite/gas/riscv/mapping-norelax-03b.d
index ad88888..9e77735 100644
--- a/gas/testsuite/gas/riscv/mapping-norelax-03b.d
+++ b/gas/testsuite/gas/riscv/mapping-norelax-03b.d
@@ -17,7 +17,7 @@ Disassembly of section .text:
[ ]+18:[ ]+00000302[ ]+.word[ ]+0x00000302
[ ]+1c:[ ]+00[ ]+.byte[ ]+0x00
[ ]+1d:[ ]+00[ ]+.byte[ ]+0x00
-[ ]+1e:[ ]+0001[ ]+nop
+[ ]+1e:[ ]+0001[ ]+.2byte[ ]+0x1
[ ]+20:[ ]+00000005[ ]+.word[ ]+0x00000005
[ ]+24:[ ]+00000013[ ]+nop
[ ]+28:[ ]+00000013[ ]+nop
diff --git a/gas/testsuite/gas/riscv/mapping-norelax-04b.d b/gas/testsuite/gas/riscv/mapping-norelax-04b.d
index 824a898..be668f2 100644
--- a/gas/testsuite/gas/riscv/mapping-norelax-04b.d
+++ b/gas/testsuite/gas/riscv/mapping-norelax-04b.d
@@ -13,12 +13,12 @@ Disassembly of section .text:
[ ]+8:[ ]+00000001[ ]+.word[ ]+0x00000001
[ ]+c:[ ]+00[ ]+.byte[ ]+0x00
[ ]+d:[ ]+00[ ]+.byte[ ]+0x00
-[ ]+e:[ ]+0001[ ]+nop
+[ ]+e:[ ]+0001[ ]+.2byte[ ]+0x1
[ ]+10:[ ]+00a50533[ ]+add[ ]+a0,a0,a0
[ ]+14:[ ]+20022002[ ]+.word[ ]+0x20022002
[ ]+18:[ ]+20022002[ ]+.word[ ]+0x20022002
[ ]+1c:[ ]+2002[ ]+.short[ ]+0x2002
[ ]+1e:[ ]+00b585b3[ ]+add[ ]+a1,a1,a1
-[ ]+22:[ ]+0001[ ]+nop
+[ ]+22:[ ]+0001[ ]+.2byte[ ]+0x1
[ ]+24:[ ]+00000013[ ]+nop
#...
diff --git a/opcodes/riscv-dis.c b/opcodes/riscv-dis.c
index 1a09440..d097c16 100644
--- a/opcodes/riscv-dis.c
+++ b/opcodes/riscv-dis.c
@@ -27,13 +27,26 @@
#include "opintl.h"
#include "elf-bfd.h"
#include "elf/riscv.h"
-#include "cpu-riscv.h"
+#include "elfxx-riscv.h"
#include <stdint.h>
#include <ctype.h>
+static enum riscv_spec_class default_isa_spec = ISA_SPEC_CLASS_DRAFT - 1;
static enum riscv_spec_class default_priv_spec = PRIV_SPEC_CLASS_NONE;
+unsigned xlen = 0;
+
+static riscv_subset_list_t riscv_subsets;
+static riscv_parse_subset_t riscv_rps_dis =
+{
+ &riscv_subsets, /* subset_list. */
+ opcodes_error_handler,/* error_handler. */
+ &xlen, /* xlen. */
+ &default_isa_spec, /* isa_spec. */
+ false, /* check_unknown_prefixed_ext. */
+};
+
struct riscv_private_data
{
bfd_vma gp;
@@ -502,8 +515,6 @@ riscv_disassemble_insn (bfd_vma memaddr, insn_t word, disassemble_info *info)
op = riscv_hash[OP_HASH_IDX (word)];
if (op != NULL)
{
- unsigned xlen = 0;
-
/* If XLEN is not known, get its value from the ELF class. */
if (info->mach == bfd_mach_riscv64)
xlen = 64;
@@ -527,6 +538,9 @@ riscv_disassemble_insn (bfd_vma memaddr, insn_t word, disassemble_info *info)
if ((op->xlen_requirement != 0) && (op->xlen_requirement != xlen))
continue;
+ if (!riscv_multi_subset_supports (&riscv_rps_dis, op->insn_class))
+ continue;
+
/* It's a match. */
(*info->fprintf_func) (info->stream, "%s", op->name);
print_insn_args (op->args, word, memaddr, info);
@@ -852,11 +866,13 @@ print_insn_riscv (bfd_vma memaddr, struct disassemble_info *info)
disassembler_ftype
riscv_get_disassembler (bfd *abfd)
{
+ const char *default_arch = "rv64gc";
+
if (abfd)
{
const struct elf_backend_data *ebd = get_elf_backend_data (abfd);
if (ebd)
- {
+ {
const char *sec_name = ebd->obj_attrs_section;
if (bfd_get_section_by_name (abfd, sec_name) != NULL)
{
@@ -868,10 +884,14 @@ riscv_get_disassembler (bfd *abfd)
attr[Tag_b].i,
attr[Tag_c].i,
&default_priv_spec);
+ default_arch = attr[Tag_RISCV_arch].s;
}
- }
+ }
}
- return print_insn_riscv;
+
+ riscv_release_subset_list (&riscv_subsets);
+ riscv_parse_subset (&riscv_rps_dis, default_arch);
+ return print_insn_riscv;
}
/* Prevent use of the fake labels that are generated as part of the DWARF