From 43135d3b15ce10a786704f9bb4736d834d6581a8 Mon Sep 17 00:00:00 2001 From: Jim Wilson Date: Thu, 30 Aug 2018 13:23:12 -0700 Subject: RISC-V: Allow instruction require more than one extension 2018-08-29 Kito Cheng gas/ * config/tc-riscv.c (riscv_subset_supports): New argument: xlen_required. (riscv_multi_subset_supports): New function, able to check more than one extension. (riscv_ip): Use riscv_multi_subset_supports instead of riscv_subset_supports. (riscv_set_arch): Update call-site for riscv_subset_supports. (riscv_after_parse_args): Likewise. include/ *opcode/riscv.h (MAX_SUBSET_NUM): New. (riscv_opcode): Add xlen_requirement field and change type of subset. opcodes/ * riscv-dis.c (riscv_disassemble_insn): Check XLEN by riscv_opcode.xlen_requirement. * riscv-opc.c (riscv_opcodes): Update for struct change. --- gas/ChangeLog | 11 +++++++++++ gas/config/tc-riscv.c | 32 +++++++++++++++++++++----------- 2 files changed, 32 insertions(+), 11 deletions(-) (limited to 'gas') diff --git a/gas/ChangeLog b/gas/ChangeLog index e880917..7607ab5 100644 --- a/gas/ChangeLog +++ b/gas/ChangeLog @@ -1,3 +1,14 @@ +2018-08-30 Kito Cheng + + * config/tc-riscv.c (riscv_subset_supports): New argument: + xlen_required. + (riscv_multi_subset_supports): New function, able to check more + than one extension. + (riscv_ip): Use riscv_multi_subset_supports instead of + riscv_subset_supports. + (riscv_set_arch): Update call-site for riscv_subset_supports. + (riscv_after_parse_args): Likewise. + 2018-08-30 H.J. Lu * testsuite/gas/elf/section14.d: Skip h8300 targets. diff --git a/gas/config/tc-riscv.c b/gas/config/tc-riscv.c index ee4b4f5..91b82ed 100644 --- a/gas/config/tc-riscv.c +++ b/gas/config/tc-riscv.c @@ -113,22 +113,32 @@ struct riscv_subset static struct riscv_subset *riscv_subsets; static bfd_boolean -riscv_subset_supports (const char *feature) +riscv_subset_supports (unsigned xlen_required, const char *feature) { struct riscv_subset *s; - char *p; - unsigned xlen_required = strtoul (feature, &p, 10); if (xlen_required && xlen != xlen_required) return FALSE; for (s = riscv_subsets; s != NULL; s = s->next) - if (strcasecmp (s->name, p) == 0) + if (strcasecmp (s->name, feature) == 0) return TRUE; return FALSE; } +static bfd_boolean +riscv_multi_subset_supports (unsigned xlen_required, const char *features[]) +{ + unsigned i = 0; + bfd_boolean supported = TRUE; + + for (;features[i]; ++i) + supported = supported && riscv_subset_supports (xlen_required, features[i]); + + return supported; +} + static void riscv_clear_subsets (void) { @@ -234,16 +244,16 @@ riscv_set_arch (const char *s) as_fatal ("-march=%s: unsupported ISA subset `%c'", s, *p); } - if (riscv_subset_supports ("e") && riscv_subset_supports ("f")) + if (riscv_subset_supports (0, "e") && riscv_subset_supports (0, "f")) as_fatal ("-march=%s: rv32e does not support the `f' extension", s); - if (riscv_subset_supports ("d") && !riscv_subset_supports ("f")) + if (riscv_subset_supports (0, "d") && !riscv_subset_supports (0, "f")) as_fatal ("-march=%s: `d' extension requires `f' extension", s); - if (riscv_subset_supports ("q") && !riscv_subset_supports ("d")) + if (riscv_subset_supports (0, "q") && !riscv_subset_supports (0, "d")) as_fatal ("-march=%s: `q' extension requires `d' extension", s); - if (riscv_subset_supports ("q") && xlen < 64) + if (riscv_subset_supports (0, "q") && xlen < 64) as_fatal ("-march=%s: rv32 does not support the `q' extension", s); free (extension); @@ -1480,7 +1490,7 @@ riscv_ip (char *str, struct riscv_cl_insn *ip, expressionS *imm_expr, argsStart = s; for ( ; insn && insn->name && strcmp (insn->name, str) == 0; insn++) { - if (!riscv_subset_supports (insn->subset)) + if (!riscv_multi_subset_supports (insn->xlen_requirement, insn->subset)) continue; create_insn (ip, insn); @@ -2297,14 +2307,14 @@ riscv_after_parse_args (void) /* Add the RVC extension, regardless of -march, to support .option rvc. */ riscv_set_rvc (FALSE); - if (riscv_subset_supports ("c")) + if (riscv_subset_supports (0, "c")) riscv_set_rvc (TRUE); else riscv_add_subset ("c"); /* Enable RVE if specified by the -march option. */ riscv_set_rve (FALSE); - if (riscv_subset_supports ("e")) + if (riscv_subset_supports (0, "e")) riscv_set_rve (TRUE); /* Infer ABI from ISA if not specified on command line. */ -- cgit v1.1