diff options
-rw-r--r-- | bfd/elfnn-riscv.c | 27 | ||||
-rw-r--r-- | bfd/elfxx-riscv.c | 69 | ||||
-rw-r--r-- | bfd/elfxx-riscv.h | 8 | ||||
-rw-r--r-- | gas/config/tc-riscv.c | 110 | ||||
-rw-r--r-- | gas/testsuite/gas/riscv/mapping-04b.d | 4 | ||||
-rw-r--r-- | gas/testsuite/gas/riscv/mapping-norelax-03b.d | 2 | ||||
-rw-r--r-- | gas/testsuite/gas/riscv/mapping-norelax-04b.d | 4 | ||||
-rw-r--r-- | opcodes/riscv-dis.c | 32 |
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 |