diff options
Diffstat (limited to 'gas/config/tc-riscv.c')
-rw-r--r-- | gas/config/tc-riscv.c | 66 |
1 files changed, 56 insertions, 10 deletions
diff --git a/gas/config/tc-riscv.c b/gas/config/tc-riscv.c index be32e6c..43ae21f 100644 --- a/gas/config/tc-riscv.c +++ b/gas/config/tc-riscv.c @@ -63,6 +63,7 @@ static const char default_arch[] = DEFAULT_ARCH; static unsigned xlen = 0; /* width of an x-register */ static unsigned abi_xlen = 0; /* width of a pointer in the ABI */ +static bfd_boolean rve_abi = FALSE; #define LOAD_ADDRESS_INSN (abi_xlen == 64 ? "ld" : "lw") #define ADD32_INSN (xlen == 64 ? "addiw" : "addi") @@ -75,6 +76,7 @@ struct riscv_set_options { int pic; /* Generate position-independent code. */ int rvc; /* Generate RVC code. */ + int rve; /* Generate RVE code. */ int relax; /* Emit relocs the linker is allowed to relax. */ }; @@ -82,6 +84,7 @@ static struct riscv_set_options riscv_opts = { 0, /* pic */ 0, /* rvc */ + 0, /* rve */ 1, /* relax */ }; @@ -94,6 +97,12 @@ riscv_set_rvc (bfd_boolean rvc_value) riscv_opts.rvc = rvc_value; } +static void +riscv_set_rve (bfd_boolean rve_value) +{ + riscv_opts.rve = rve_value; +} + struct riscv_subset { const char *name; @@ -171,6 +180,16 @@ riscv_set_arch (const char *s) case 'i': break; + case 'e': + p++; + riscv_add_subset ("e"); + riscv_add_subset ("i"); + + if (xlen > 32) + as_fatal ("-march=%s: rv%de is not a valid base ISA", s, xlen); + + break; + case 'g': p++; for ( ; *all_subsets != 'q'; all_subsets++) @@ -181,7 +200,7 @@ riscv_set_arch (const char *s) break; default: - as_fatal ("-march=%s: first ISA subset must be `i' or `g'", s); + as_fatal ("-march=%s: first ISA subset must be `e', `i' or `g'", s); } while (*p) @@ -215,6 +234,18 @@ 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")) + as_fatal ("-march=%s: rv32e does not support the `f' extension", s); + + if (riscv_subset_supports ("d") && !riscv_subset_supports ("f")) + as_fatal ("-march=%s: `d' extension requires `f' extension", s); + + if (riscv_subset_supports ("q") && !riscv_subset_supports ("d")) + as_fatal ("-march=%s: `q' extension requires `d' extension", s); + + if (riscv_subset_supports ("q") && xlen < 64) + as_fatal ("-march=%s: rv32 does not support the `q' extension", s); + free (extension); } @@ -546,6 +577,10 @@ reg_lookup_internal (const char *s, enum reg_class class) if (r == NULL || DECODE_REG_CLASS (r) != class) return -1; + + if (riscv_opts.rve && class == RCLASS_GPR && DECODE_REG_NUM (r) > 15) + return -1; + return DECODE_REG_NUM (r); } @@ -2165,10 +2200,11 @@ enum float_abi { static enum float_abi float_abi = FLOAT_ABI_DEFAULT; static void -riscv_set_abi (unsigned new_xlen, enum float_abi new_float_abi) +riscv_set_abi (unsigned new_xlen, enum float_abi new_float_abi, bfd_boolean rve) { abi_xlen = new_xlen; float_abi = new_float_abi; + rve_abi = rve; } int @@ -2190,21 +2226,23 @@ md_parse_option (int c, const char *arg) case OPTION_MABI: if (strcmp (arg, "ilp32") == 0) - riscv_set_abi (32, FLOAT_ABI_SOFT); + riscv_set_abi (32, FLOAT_ABI_SOFT, FALSE); + else if (strcmp (arg, "ilp32e") == 0) + riscv_set_abi (32, FLOAT_ABI_SOFT, TRUE); else if (strcmp (arg, "ilp32f") == 0) - riscv_set_abi (32, FLOAT_ABI_SINGLE); + riscv_set_abi (32, FLOAT_ABI_SINGLE, FALSE); else if (strcmp (arg, "ilp32d") == 0) - riscv_set_abi (32, FLOAT_ABI_DOUBLE); + riscv_set_abi (32, FLOAT_ABI_DOUBLE, FALSE); else if (strcmp (arg, "ilp32q") == 0) - riscv_set_abi (32, FLOAT_ABI_QUAD); + riscv_set_abi (32, FLOAT_ABI_QUAD, FALSE); else if (strcmp (arg, "lp64") == 0) - riscv_set_abi (64, FLOAT_ABI_SOFT); + riscv_set_abi (64, FLOAT_ABI_SOFT, FALSE); else if (strcmp (arg, "lp64f") == 0) - riscv_set_abi (64, FLOAT_ABI_SINGLE); + riscv_set_abi (64, FLOAT_ABI_SINGLE, FALSE); else if (strcmp (arg, "lp64d") == 0) - riscv_set_abi (64, FLOAT_ABI_DOUBLE); + riscv_set_abi (64, FLOAT_ABI_DOUBLE, FALSE); else if (strcmp (arg, "lp64q") == 0) - riscv_set_abi (64, FLOAT_ABI_QUAD); + riscv_set_abi (64, FLOAT_ABI_QUAD, FALSE); else return 0; break; @@ -2247,6 +2285,11 @@ riscv_after_parse_args (void) else riscv_add_subset ("c"); + /* Enable RVE if specified by the -march option. */ + riscv_set_rve (FALSE); + if (riscv_subset_supports ("e")) + riscv_set_rve (TRUE); + /* Infer ABI from ISA if not specified on command line. */ if (abi_xlen == 0) abi_xlen = xlen; @@ -2271,6 +2314,9 @@ riscv_after_parse_args (void) } } + if (rve_abi) + elf_flags |= EF_RISCV_RVE; + /* Insert float_abi into the EF_RISCV_FLOAT_ABI field of elf_flags. */ elf_flags |= float_abi * (EF_RISCV_FLOAT_ABI & ~(EF_RISCV_FLOAT_ABI << 1)); } |