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")
{
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. */
};
{
0, /* pic */
0, /* rvc */
+ 0, /* rve */
1, /* relax */
};
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;
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++)
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)
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);
}
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);
}
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
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;
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;
}
}
+ 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));
}