|
|
@ -62,9 +62,9 @@ struct riscv_cl_insn |
|
|
#endif |
|
|
#endif |
|
|
static const char default_arch[] = DEFAULT_ARCH; |
|
|
static const char default_arch[] = DEFAULT_ARCH; |
|
|
|
|
|
|
|
|
bfd_boolean rv64 = TRUE; /* RV64 (true) or RV32 (false) */ |
|
|
unsigned xlen = 0; /* width of an x-register */ |
|
|
#define LOAD_ADDRESS_INSN (rv64 ? "ld" : "lw") |
|
|
#define LOAD_ADDRESS_INSN (xlen == 64 ? "ld" : "lw") |
|
|
#define ADD32_INSN (rv64 ? "addiw" : "addi") |
|
|
#define ADD32_INSN (xlen == 64 ? "addiw" : "addi") |
|
|
|
|
|
|
|
|
unsigned elf_flags = 0; |
|
|
unsigned elf_flags = 0; |
|
|
|
|
|
|
|
|
@ -101,7 +101,7 @@ riscv_subset_supports(const char* feature) |
|
|
|
|
|
|
|
|
if ((rv64_insn = !strncmp(feature, "64", 2)) || !strncmp(feature, "32", 2)) |
|
|
if ((rv64_insn = !strncmp(feature, "64", 2)) || !strncmp(feature, "32", 2)) |
|
|
{ |
|
|
{ |
|
|
if (rv64 != rv64_insn) |
|
|
if ((xlen == 64) != rv64_insn) |
|
|
return 0; |
|
|
return 0; |
|
|
feature += 2; |
|
|
feature += 2; |
|
|
} |
|
|
} |
|
|
@ -157,12 +157,12 @@ riscv_set_arch (const char* arg) |
|
|
|
|
|
|
|
|
if (strncmp(arg, "RV32", 4) == 0) |
|
|
if (strncmp(arg, "RV32", 4) == 0) |
|
|
{ |
|
|
{ |
|
|
rv64 = FALSE; |
|
|
xlen = 32; |
|
|
arg += 4; |
|
|
arg += 4; |
|
|
} |
|
|
} |
|
|
else if (strncmp(arg, "RV64", 4) == 0) |
|
|
else if (strncmp(arg, "RV64", 4) == 0) |
|
|
{ |
|
|
{ |
|
|
rv64 = TRUE; |
|
|
xlen = 64; |
|
|
arg += 4; |
|
|
arg += 4; |
|
|
} |
|
|
} |
|
|
else if (strncmp(arg, "RV", 2) == 0) |
|
|
else if (strncmp(arg, "RV", 2) == 0) |
|
|
@ -304,12 +304,7 @@ static char *expr_end; |
|
|
const char * |
|
|
const char * |
|
|
riscv_target_format (void) |
|
|
riscv_target_format (void) |
|
|
{ |
|
|
{ |
|
|
if (strcmp (default_arch, "riscv32") == 0) |
|
|
return xlen == 64 ? "elf64-littleriscv" : "elf32-littleriscv"; |
|
|
rv64 = FALSE; |
|
|
|
|
|
else if (strcmp (default_arch, "riscv64") == 0) |
|
|
|
|
|
rv64 = TRUE; |
|
|
|
|
|
|
|
|
|
|
|
return rv64 ? "elf64-littleriscv" : "elf32-littleriscv"; |
|
|
|
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
/* Return the length of instruction INSN. */ |
|
|
/* Return the length of instruction INSN. */ |
|
|
@ -764,7 +759,7 @@ append_insn (struct riscv_cl_insn *ip, expressionS *address_expr, |
|
|
|
|
|
|
|
|
/* These relocations can have an addend that won't fit in
|
|
|
/* These relocations can have an addend that won't fit in
|
|
|
4 octets for 64bit assembly. */ |
|
|
4 octets for 64bit assembly. */ |
|
|
if (rv64 |
|
|
if (xlen == 64 |
|
|
&& ! howto->partial_inplace |
|
|
&& ! howto->partial_inplace |
|
|
&& (reloc_type == BFD_RELOC_32 |
|
|
&& (reloc_type == BFD_RELOC_32 |
|
|
|| reloc_type == BFD_RELOC_64 |
|
|
|| reloc_type == BFD_RELOC_64 |
|
|
@ -854,7 +849,7 @@ macro_build (expressionS *ep, const char *name, const char *fmt, ...) |
|
|
static void |
|
|
static void |
|
|
normalize_constant_expr (expressionS *ex) |
|
|
normalize_constant_expr (expressionS *ex) |
|
|
{ |
|
|
{ |
|
|
if (rv64) |
|
|
if (xlen > 32) |
|
|
return; |
|
|
return; |
|
|
if ((ex->X_op == O_constant || ex->X_op == O_symbol) |
|
|
if ((ex->X_op == O_constant || ex->X_op == O_symbol) |
|
|
&& IS_ZEXT_32BIT_NUM (ex->X_add_number)) |
|
|
&& IS_ZEXT_32BIT_NUM (ex->X_add_number)) |
|
|
@ -935,7 +930,7 @@ load_const (int reg, expressionS *ep) |
|
|
|
|
|
|
|
|
gas_assert (ep->X_op == O_constant); |
|
|
gas_assert (ep->X_op == O_constant); |
|
|
|
|
|
|
|
|
if (rv64 && !IS_SEXT_32BIT_NUM(ep->X_add_number)) |
|
|
if (xlen > 32 && !IS_SEXT_32BIT_NUM(ep->X_add_number)) |
|
|
{ |
|
|
{ |
|
|
/* Reduce to a signed 32-bit constant using SLLI and ADDI, which
|
|
|
/* Reduce to a signed 32-bit constant using SLLI and ADDI, which
|
|
|
is not optimal but also not so bad. */ |
|
|
is not optimal but also not so bad. */ |
|
|
@ -1609,7 +1604,7 @@ rvc_lui: |
|
|
case '>': /* shift amount, 0 - (XLEN-1) */ |
|
|
case '>': /* shift amount, 0 - (XLEN-1) */ |
|
|
my_getExpression (imm_expr, s); |
|
|
my_getExpression (imm_expr, s); |
|
|
check_absolute_expr (ip, imm_expr); |
|
|
check_absolute_expr (ip, imm_expr); |
|
|
if ((unsigned long) imm_expr->X_add_number > (rv64 ? 63 : 31)) |
|
|
if ((unsigned long) imm_expr->X_add_number >= xlen) |
|
|
as_warn (_("Improper shift amount (%lu)"), |
|
|
as_warn (_("Improper shift amount (%lu)"), |
|
|
(unsigned long) imm_expr->X_add_number); |
|
|
(unsigned long) imm_expr->X_add_number); |
|
|
INSERT_OPERAND (SHAMT, *ip, imm_expr->X_add_number); |
|
|
INSERT_OPERAND (SHAMT, *ip, imm_expr->X_add_number); |
|
|
@ -1911,11 +1906,11 @@ md_parse_option (int c, char *arg) |
|
|
break; |
|
|
break; |
|
|
|
|
|
|
|
|
case OPTION_M32: |
|
|
case OPTION_M32: |
|
|
rv64 = FALSE; |
|
|
xlen = 32; |
|
|
break; |
|
|
break; |
|
|
|
|
|
|
|
|
case OPTION_M64: |
|
|
case OPTION_M64: |
|
|
rv64 = TRUE; |
|
|
xlen = 64; |
|
|
break; |
|
|
break; |
|
|
|
|
|
|
|
|
case OPTION_MARCH: |
|
|
case OPTION_MARCH: |
|
|
@ -1942,6 +1937,16 @@ riscv_after_parse_args (void) |
|
|
if (riscv_subsets == NULL) |
|
|
if (riscv_subsets == NULL) |
|
|
riscv_set_arch ("RVIMAFDXcustom"); |
|
|
riscv_set_arch ("RVIMAFDXcustom"); |
|
|
|
|
|
|
|
|
|
|
|
if (xlen == 0) |
|
|
|
|
|
{ |
|
|
|
|
|
if (strcmp (default_arch, "riscv32") == 0) |
|
|
|
|
|
xlen = 32; |
|
|
|
|
|
else if (strcmp (default_arch, "riscv64") == 0) |
|
|
|
|
|
xlen = 64; |
|
|
|
|
|
else |
|
|
|
|
|
as_bad ("unknown default architecture `%s'", default_arch); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
if (riscv_opts.rvc) |
|
|
if (riscv_opts.rvc) |
|
|
elf_flags |= EF_RISCV_RVC; |
|
|
elf_flags |= EF_RISCV_RVC; |
|
|
} |
|
|
} |
|
|
|