diff --git a/opcodes/riscv-dis.c b/opcodes/riscv-dis.c index 2f01b149719..5bf83654e53 100644 --- a/opcodes/riscv-dis.c +++ b/opcodes/riscv-dis.c @@ -84,6 +84,12 @@ static bool is_numeric = false; /* Reset when either arch or option is changed. */ static bool is_init_csr = false; +/* Current privileged specification version. */ +static enum riscv_spec_class priv_spec = PRIV_SPEC_CLASS_NONE; + +/* If set, a custom privileged specification is specified. */ +static bool is_custom_priv_spec = false; + /* Initialization (for arch and options). */ @@ -102,14 +108,14 @@ static void init_riscv_dis_state_for_arch_and_options (void) { static bool init = false; - static enum riscv_spec_class prev_default_priv_spec; + static enum riscv_spec_class prev_priv_spec; if (!init) { set_default_riscv_dis_options (); build_riscv_opcodes_hash_table (); init = true; /* Save initial options. */ - prev_default_priv_spec = default_priv_spec; + prev_priv_spec = priv_spec; } riscv_gpr_names = is_numeric ? riscv_gpr_names_numeric : riscv_gpr_names_abi; riscv_fpr_names = is_numeric ? riscv_fpr_names_numeric : riscv_fpr_names_abi; @@ -117,10 +123,10 @@ init_riscv_dis_state_for_arch_and_options (void) if (riscv_subset_supports (&riscv_rps_dis, "zfinx")) riscv_fpr_names = riscv_gpr_names; /* Reset CSR hashtable if either `arch' or `priv-spec' option changes. */ - if (is_arch_changed || prev_default_priv_spec != default_priv_spec) + if (is_arch_changed || prev_priv_spec != priv_spec) is_init_csr = false; /* Save previous options and mark them "unchanged". */ - prev_default_priv_spec = default_priv_spec; + prev_priv_spec = priv_spec; is_arch_changed = false; } @@ -129,6 +135,7 @@ set_default_riscv_dis_options (void) { no_aliases = false; is_numeric = false; + is_custom_priv_spec = false; } /* Update current architecture string @@ -206,22 +213,13 @@ parse_riscv_dis_option (const char *option) value = equal + 1; if (strcmp (option, "priv-spec") == 0) { - enum riscv_spec_class priv_spec = PRIV_SPEC_CLASS_NONE; - const char *name = NULL; - - RISCV_GET_PRIV_SPEC_CLASS (value, priv_spec); - if (priv_spec == PRIV_SPEC_CLASS_NONE) + is_custom_priv_spec = true; + enum riscv_spec_class priv_spec_new = PRIV_SPEC_CLASS_NONE; + RISCV_GET_PRIV_SPEC_CLASS (value, priv_spec_new); + if (priv_spec_new == PRIV_SPEC_CLASS_NONE) opcodes_error_handler (_("unknown privileged spec set by %s=%s"), option, value); - else if (default_priv_spec == PRIV_SPEC_CLASS_NONE) - default_priv_spec = priv_spec; - else if (default_priv_spec != priv_spec) - { - RISCV_GET_PRIV_SPEC_NAME (name, default_priv_spec); - opcodes_error_handler (_("mis-matched privilege spec set by %s=%s, " - "the elf privilege attribute is %s"), - option, value, name); - } + priv_spec = priv_spec_new; } else { @@ -234,6 +232,7 @@ static void parse_riscv_dis_options (const char *opts_in) { char *opts = xstrdup (opts_in), *opt = opts, *opt_end = opts; + bool prev_is_custom_priv_spec = is_custom_priv_spec; set_default_riscv_dis_options (); @@ -245,6 +244,8 @@ parse_riscv_dis_options (const char *opts_in) } free (opts); + if (prev_is_custom_priv_spec && !is_custom_priv_spec) + priv_spec = default_priv_spec; } /* Print one argument from an array. */ @@ -610,15 +611,15 @@ print_insn_args (const char *oparg, insn_t l, bfd_vma pc, disassemble_info *info riscv_csr_hash[i] = NULL; /* Set to the newest privileged version. */ - if (default_priv_spec == PRIV_SPEC_CLASS_NONE) - default_priv_spec = PRIV_SPEC_CLASS_DRAFT - 1; + if (priv_spec == PRIV_SPEC_CLASS_NONE) + priv_spec = PRIV_SPEC_CLASS_DRAFT - 1; #define DECLARE_CSR(name, num, class, define_version, abort_version) \ if (riscv_csr_hash[num] == NULL \ && ((define_version == PRIV_SPEC_CLASS_NONE \ && abort_version == PRIV_SPEC_CLASS_NONE) \ - || (default_priv_spec >= define_version \ - && default_priv_spec < abort_version))) \ + || (priv_spec >= define_version \ + && priv_spec < abort_version))) \ riscv_csr_hash[num] = #name; #define DECLARE_CSR_ALIAS(name, num, class, define_version, abort_version) \ DECLARE_CSR (name, num, class, define_version, abort_version) @@ -1156,6 +1157,8 @@ riscv_get_disassembler (bfd *abfd) if (update_riscv_dis_default_arch (default_arch_next)) update_riscv_dis_current_arch (default_arch_next); + if (!is_custom_priv_spec) + priv_spec = default_priv_spec; init_riscv_dis_state_for_arch_and_options (); return print_insn_riscv; }