@@ -447,6 +447,7 @@ DESCRIPTION
. bfd_arch_riscv,
.#define bfd_mach_riscv32 132
.#define bfd_mach_riscv64 164
+.#define bfd_mach_riscv64x32 16432
. bfd_arch_rl78,
.#define bfd_mach_rl78 0x75
. bfd_arch_rx, {* Renesas RX. *}
@@ -1700,6 +1700,7 @@ enum bfd_architecture
bfd_arch_riscv,
#define bfd_mach_riscv32 132
#define bfd_mach_riscv64 164
+#define bfd_mach_riscv64x32 16432
bfd_arch_rl78,
#define bfd_mach_rl78 0x75
bfd_arch_rx, /* Renesas RX. */
@@ -86,6 +86,7 @@ riscv_scan (const struct bfd_arch_info *info, const char *string)
enum
{
I_riscv64,
+ I_riscv64x32,
I_riscv32
};
@@ -96,6 +97,7 @@ enum
static const bfd_arch_info_type arch_info_struct[] =
{
N (64, bfd_mach_riscv64, "riscv:rv64", false, NN (I_riscv64)),
+ N (32, bfd_mach_riscv64x32, "riscv:rv64", false, NN (I_riscv64x32)),
N (32, bfd_mach_riscv32, "riscv:rv32", false, NULL)
};
@@ -122,6 +122,11 @@
#define RISCV_ELF_WORD_BYTES (1 << RISCV_ELF_LOG_WORD_BYTES)
+#define ABI_X32_P(abfd) \
+ ((elf_elfheader (abfd)->e_flags & EF_RISCV_X32) != 0)
+
+static bool ABI_X32 = false;
+
/* The name of the dynamic interpreter. This is put in the .interp
section. */
@@ -1721,7 +1726,7 @@ perform_relocation (const reloc_howto_type *howto,
case R_RISCV_GOT_HI20:
case R_RISCV_TLS_GOT_HI20:
case R_RISCV_TLS_GD_HI20:
- if (ARCH_SIZE > 32 && !VALID_UTYPE_IMM (RISCV_CONST_HIGH_PART (value)))
+ if ((ARCH_SIZE > 32 || ABI_X32_P(input_bfd)) && !VALID_UTYPE_IMM (RISCV_CONST_HIGH_PART (value)))
return bfd_reloc_overflow;
value = ENCODE_UTYPE_IMM (RISCV_CONST_HIGH_PART (value));
break;
@@ -1744,7 +1749,7 @@ perform_relocation (const reloc_howto_type *howto,
case R_RISCV_CALL:
case R_RISCV_CALL_PLT:
- if (ARCH_SIZE > 32 && !VALID_UTYPE_IMM (RISCV_CONST_HIGH_PART (value)))
+ if ((ARCH_SIZE > 32 || ABI_X32_P(input_bfd))&& !VALID_UTYPE_IMM (RISCV_CONST_HIGH_PART (value)))
return bfd_reloc_overflow;
value = ENCODE_UTYPE_IMM (RISCV_CONST_HIGH_PART (value))
| (ENCODE_ITYPE_IMM (value) << 32);
@@ -3685,7 +3690,7 @@ riscv_merge_arch_attr_info (bfd *ibfd, char *in_arch, char *out_arch)
return NULL;
/* Checking XLEN. */
- if (xlen_out != xlen_in)
+ if (xlen_out != xlen_in && !ABI_X32_P(ibfd))
{
_bfd_error_handler
(_("error: %pB: ISA string of input (%s) doesn't match "
@@ -3705,7 +3710,7 @@ riscv_merge_arch_attr_info (bfd *ibfd, char *in_arch, char *out_arch)
if (!riscv_merge_multi_letter_ext (&in, &out))
return NULL;
- if (xlen_in != xlen_out)
+ if (xlen_in != xlen_out && !ABI_X32_P(ibfd))
{
_bfd_error_handler
(_("error: %pB: XLEN of input (%u) doesn't match "
@@ -3713,7 +3718,7 @@ riscv_merge_arch_attr_info (bfd *ibfd, char *in_arch, char *out_arch)
return NULL;
}
- if (xlen_in != ARCH_SIZE)
+ if (xlen_in != ARCH_SIZE && !ABI_X32_P(ibfd))
{
_bfd_error_handler
(_("error: %pB: unsupported XLEN (%u), you might be "
@@ -3721,7 +3726,7 @@ riscv_merge_arch_attr_info (bfd *ibfd, char *in_arch, char *out_arch)
return NULL;
}
- merged_arch_str = riscv_arch_str (ARCH_SIZE, &merged_subsets);
+ merged_arch_str = riscv_arch_str (xlen_in, &merged_subsets);
/* Release the subset lists. */
riscv_release_subset_list (&in_subsets);
@@ -3992,6 +3997,9 @@ _bfd_riscv_elf_merge_private_bfd_data (bfd *ibfd, struct bfd_link_info *info)
/* Allow linking TSO and non-TSO, and keep the TSO flag. */
elf_elfheader (obfd)->e_flags |= new_flags & EF_RISCV_TSO;
+ /* Allow linking X32 and non-X32, and keep the X32 flag. */
+ elf_elfheader (obfd)->e_flags |= new_flags & EF_RISCV_X32;
+
return true;
fail:
@@ -4431,7 +4439,7 @@ _bfd_riscv_relax_call (bfd *abfd, asection *sec, asection *sym_sec,
rvc = rvc && VALID_CJTYPE_IMM (foff);
/* C.J exists on RV32 and RV64, but C.JAL is RV32-only. */
- rvc = rvc && (rd == 0 || (rd == X_RA && ARCH_SIZE == 32));
+ rvc = rvc && (rd == 0 || (rd == X_RA && ARCH_SIZE == 32 && !ABI_X32_P(abfd)));
if (rvc)
{
@@ -5140,7 +5148,7 @@ _bfd_riscv_relax_section (bfd *abfd, asection *sec,
return ret;
}
-#if ARCH_SIZE == 32
+#if ARCH_SIZE == 32 && !ABI_X32
# define PRSTATUS_SIZE 204
# define PRSTATUS_OFFSET_PR_CURSIG 12
# define PRSTATUS_OFFSET_PR_PID 24
@@ -5310,9 +5318,12 @@ riscv_elf_grok_psinfo (bfd *abfd, Elf_Internal_Note *note)
static bool
riscv_elf_object_p (bfd *abfd)
{
- /* There are only two mach types in RISCV currently. */
- if (strcmp (abfd->xvec->name, "elf32-littleriscv") == 0
- || strcmp (abfd->xvec->name, "elf32-bigriscv") == 0)
+ ABI_X32 = ABI_X32_P(abfd);
+ /* There are only three mach types in RISCV currently. */
+ if (ABI_X32)
+ bfd_default_set_arch_mach (abfd, bfd_arch_riscv, bfd_mach_riscv64x32);
+ else if (strcmp (abfd->xvec->name, "elf32-littleriscv") == 0
+ || strcmp (abfd->xvec->name, "elf32-bigriscv") == 0)
bfd_default_set_arch_mach (abfd, bfd_arch_riscv, bfd_mach_riscv32);
else
bfd_default_set_arch_mach (abfd, bfd_arch_riscv, bfd_mach_riscv64);
@@ -4119,6 +4119,9 @@ get_machine_flags (Filedata * filedata, unsigned e_flags, unsigned e_machine)
if (e_flags & EF_RISCV_TSO)
strcat (buf, ", TSO");
+ if (e_flags & EF_RISCV_X32)
+ strcat (buf, ", X32");
+
switch (e_flags & EF_RISCV_FLOAT_ABI)
{
case EF_RISCV_FLOAT_ABI_SOFT:
@@ -278,6 +278,14 @@ riscv_set_tso (void)
elf_flags |= EF_RISCV_TSO;
}
+/* Turn on the x32 flag for elf_flags once we have enabled x32 model. */
+
+static void
+riscv_set_x32 (void)
+{
+ elf_flags |= EF_RISCV_X32;
+}
+
/* The linked list hanging off of .subsets_list records all enabled extensions,
which are parsed from the architecture string. The architecture string can
be set by the -march option, the elf architecture attributes, and the
@@ -405,6 +413,9 @@ riscv_set_abi_by_arch (void)
if (rve_abi)
elf_flags |= EF_RISCV_RVE;
+
+ if (abi_xlen == 32 && xlen == 64)
+ riscv_set_x32 ();
}
/* Handle of the OPCODE hash table. */
@@ -706,9 +717,9 @@ const char *
riscv_target_format (void)
{
if (target_big_endian)
- return xlen == 64 ? "elf64-bigriscv" : "elf32-bigriscv";
+ return abi_xlen == 64 ? "elf64-bigriscv" : "elf32-bigriscv";
else
- return xlen == 64 ? "elf64-littleriscv" : "elf32-littleriscv";
+ return abi_xlen == 64 ? "elf64-littleriscv" : "elf32-littleriscv";
}
/* Return the length of instruction INSN. */
@@ -1505,7 +1516,8 @@ init_opcode_hash (const struct riscv_opcode *opcodes,
void
md_begin (void)
{
- unsigned long mach = xlen == 64 ? bfd_mach_riscv64 : bfd_mach_riscv32;
+ unsigned long mach = xlen == 64 ?
+ (abi_xlen == 32 ? bfd_mach_riscv64x32 : bfd_mach_riscv64) : bfd_mach_riscv32;
if (! bfd_set_arch_mach (stdoutput, bfd_arch_riscv, mach))
as_warn (_("could not set architecture and machine"));
@@ -4912,7 +4924,8 @@ s_riscv_attribute (int ignored ATTRIBUTE_UNUSED)
if (old_xlen != xlen)
{
/* We must re-init bfd again if xlen is changed. */
- unsigned long mach = xlen == 64 ? bfd_mach_riscv64 : bfd_mach_riscv32;
+ unsigned long mach = xlen == 64 ? (abi_xlen == 32 ?
+ bfd_mach_riscv64x32 : bfd_mach_riscv64) : bfd_mach_riscv32;
bfd_find_target (riscv_target_format (), stdoutput);
if (! bfd_set_arch_mach (stdoutput, bfd_arch_riscv, mach))
@@ -124,6 +124,9 @@ END_RELOC_NUMBERS (R_RISCV_max)
/* File uses the TSO model. */
#define EF_RISCV_TSO 0x0010
+/* File uses the X32 model. */
+#define EF_RISCV_X32 0x0020
+
/* Additional section types. */
#define SHT_RISCV_ATTRIBUTES 0x70000003 /* Section holds attributes. */