|
|
|
@ -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)); |
|
|
|
} |
|
|
|
|