diff options
Diffstat (limited to 'gas/config')
-rw-r--r-- | gas/config/tc-riscv.c | 61 |
1 files changed, 47 insertions, 14 deletions
diff --git a/gas/config/tc-riscv.c b/gas/config/tc-riscv.c index 55799b1..322e0f0 100644 --- a/gas/config/tc-riscv.c +++ b/gas/config/tc-riscv.c @@ -89,6 +89,20 @@ struct riscv_csr_extra struct riscv_csr_extra *next; }; +/* This structure contains information about errors that occur within the + riscv_ip function */ +struct riscv_ip_error +{ + /* General error message */ + const char* msg; + + /* Statement that caused the error */ + char* statement; + + /* Missing extension that needs to be enabled */ + const char* missing_ext; +}; + #ifndef DEFAULT_ARCH #define DEFAULT_ARCH "riscv64" #endif @@ -2221,7 +2235,7 @@ riscv_is_priv_insn (insn_t insn) side effect, it sets the global variable imm_reloc to the type of relocation to do if one of the operands is an address expression. */ -static const char * +static struct riscv_ip_error riscv_ip (char *str, struct riscv_cl_insn *ip, expressionS *imm_expr, bfd_reloc_code_real_type *imm_reloc, htab_t hash) { @@ -2234,7 +2248,10 @@ riscv_ip (char *str, struct riscv_cl_insn *ip, expressionS *imm_expr, unsigned int regno; int argnum; const struct percent_op_match *p; - const char *error = "unrecognized opcode"; + struct riscv_ip_error error; + error.msg = "unrecognized opcode"; + error.statement = str; + error.missing_ext = NULL; /* Indicate we are assembling instruction with CSR. */ bool insn_with_csr = false; @@ -2257,10 +2274,15 @@ riscv_ip (char *str, struct riscv_cl_insn *ip, expressionS *imm_expr, continue; if (!riscv_multi_subset_supports (&riscv_rps_as, insn->insn_class)) - continue; + { + error.missing_ext = riscv_multi_subset_supports_ext (&riscv_rps_as, + insn->insn_class); + continue; + } /* Reset error message of the previous round. */ - error = _("illegal operands"); + error.msg = _("illegal operands"); + error.missing_ext = NULL; create_insn (ip, insn); argnum = 1; @@ -2310,14 +2332,14 @@ riscv_ip (char *str, struct riscv_cl_insn *ip, expressionS *imm_expr, && riscv_subset_supports (&riscv_rps_as, "zve32x") && !riscv_subset_supports (&riscv_rps_as, "zve64x")) { - error = _("illegal opcode for zve32x"); + error.msg = _("illegal opcode for zve32x"); break; } } if (*asarg != '\0') break; /* Successful assembly. */ - error = NULL; + error.msg = NULL; insn_with_csr = false; goto out; @@ -3253,11 +3275,16 @@ md_assemble (char *str) riscv_mapping_state (MAP_INSN, 0); - const char *error = riscv_ip (str, &insn, &imm_expr, &imm_reloc, op_hash); + const struct riscv_ip_error error = riscv_ip (str, &insn, &imm_expr, + &imm_reloc, op_hash); - if (error) + if (error.msg) { - as_bad ("%s `%s'", error, str); + if (error.missing_ext) + as_bad ("%s `%s', extension `%s' required", error.msg, + error.statement, error.missing_ext); + else + as_bad ("%s `%s'", error.msg, error.statement); return; } @@ -4266,17 +4293,23 @@ s_riscv_insn (int x ATTRIBUTE_UNUSED) riscv_mapping_state (MAP_INSN, 0); - const char *error = riscv_ip (str, &insn, &imm_expr, + struct riscv_ip_error error = riscv_ip (str, &insn, &imm_expr, &imm_reloc, insn_type_hash); - if (error) + if (error.msg) { char *save_in = input_line_pointer; - error = riscv_ip_hardcode (str, &insn, &imm_expr, error); + error.msg = riscv_ip_hardcode (str, &insn, &imm_expr, error.msg); input_line_pointer = save_in; } - if (error) - as_bad ("%s `%s'", error, str); + if (error.msg) + { + if (error.missing_ext) + as_bad ("%s `%s', extension `%s' required", error.msg, error.statement, + error.missing_ext); + else + as_bad ("%s `%s'", error.msg, error.statement); + } else { gas_assert (insn.insn_mo->pinfo != INSN_MACRO); |