[RFC,2/4] RISC-V : Add support for rv64 arch using ilp32 abi

Message ID 20230519034835.664-3-shihua@iscas.ac.cn
State Accepted
Headers
Series RISC-V : Support ilp32 abi on rv64 isa |

Checks

Context Check Description
snail/binutils-gdb-check success Github commit url

Commit Message

Liao Shihua May 19, 2023, 3:48 a.m. UTC
  This patch add a new bfd_mach bfd_mach_riscv64x32 and a new e_flags X32.
bfd_mach_riscv64x32 has the same bits in a word/address and ARCH_SIZE with rv32, but use rv64's
PRSTATUS. X32 use the 6th bit of e_flags layout.
In addition, this patch replace xlen with abi_xlen in riscv_target_format().

Thanks for Jim Wilson's help.

bfd/ChangeLog:

        * archures.c: Add bfd_mach_riscv64x32.
        * bfd-in2.h (bfd_mach_riscv64x32): Likewise.
        * cpu-riscv.c:Likewise.
        * elfnn-riscv.c (ABI_X32_P): Add a flag when used x32.
        (perform_relocation): Check relocation. 
        (riscv_merge_arch_attr_info): Remove elf check when use x32.
        (_bfd_riscv_elf_merge_private_bfd_data):Allow linking X32 flag.
        (_bfd_riscv_relax_call):Check relocation. 
        (_bfd_riscv_relax_section):Check relocation. 
        (riscv_elf_object_p): Set bfd_default_set_arch_mach 
        is bfd_mach_riscv64x32 when use x32.

binutils/ChangeLog:

        * readelf.c (get_machine_flags): 

gas/ChangeLog:

        * config/tc-riscv.c (riscv_set_x32):Add X32 flag when use X32.
        (riscv_set_abi_by_arch):
        (riscv_target_format):init target_format by abi_xlen
        (md_begin):set mach.
        (s_riscv_attribute):Likewise

include/ChangeLog:

        * elf/riscv.h (EF_RISCV_X32):Add e_flags X32.

---
 bfd/archures.c        |  1 +
 bfd/bfd-in2.h         |  1 +
 bfd/cpu-riscv.c       |  2 ++
 bfd/elfnn-riscv.c     | 33 ++++++++++++++++++++++-----------
 binutils/readelf.c    |  3 +++
 gas/config/tc-riscv.c | 21 +++++++++++++++++----
 include/elf/riscv.h   |  3 +++
 7 files changed, 49 insertions(+), 15 deletions(-)
  

Comments

Jan Beulich May 19, 2023, 6:33 a.m. UTC | #1
On 19.05.2023 05:48, Liao Shihua wrote:
> This patch add a new bfd_mach bfd_mach_riscv64x32 and a new e_flags X32.
> bfd_mach_riscv64x32 has the same bits in a word/address and ARCH_SIZE
> with rv32, but use rv64's PRSTATUS. X32 use the 6th bit of e_flags layout.

And this has been added already to the official version of the spec? (A
reference might be good, maybe here or maybe in the cover letter.)

> --- a/bfd/elfnn-riscv.c
> +++ b/bfd/elfnn-riscv.c
> @@ -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;

While I'm not sure in how far libbfd, when built as a shared object, is
fully usable in multi-threaded programs, I don't think new code should
make the situation worse by adding new (non-const) static/global
variables. What's yet more odd about this variable is that ...

> @@ -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

... you use it in a pre-processor conditional here.

Jan
  
Liao Shihua May 19, 2023, 6:58 a.m. UTC | #2
Hello Jan,
&gt; And this has been added already to the official version of the spec? (A
&gt; reference might be good, maybe here or maybe in the cover letter.)
&gt; 

At the moment I have only initiated pr in psABI, but it is still under discussion.
You can see it in https://github.com/riscv-non-isa/riscv-elf-psabi-doc/pull/381


&gt; 
&gt; While I'm not sure in how far libbfd, when built as a shared object, is
&gt; fully usable in multi-threaded programs, I don't think new code should
&gt; make the situation worse by adding new (non-const) static/global
&gt; variables. What's yet more odd about this variable is that ...

&gt; 
&gt; ... you use it in a pre-processor conditional here.
&gt; 
&gt; Jan

Thank you for you advice, I will revise this part in the future.

Best Regards
Liao Shihua
  

Patch

diff --git a/bfd/archures.c b/bfd/archures.c
index 6fe8701b412..fb3554d253a 100644
--- a/bfd/archures.c
+++ b/bfd/archures.c
@@ -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.  *}
diff --git a/bfd/bfd-in2.h b/bfd/bfd-in2.h
index 7be18db20a8..c0615d3aeed 100644
--- a/bfd/bfd-in2.h
+++ b/bfd/bfd-in2.h
@@ -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.  */
diff --git a/bfd/cpu-riscv.c b/bfd/cpu-riscv.c
index a478797da69..38b7eb4a7b5 100644
--- a/bfd/cpu-riscv.c
+++ b/bfd/cpu-riscv.c
@@ -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)
 };
 
diff --git a/bfd/elfnn-riscv.c b/bfd/elfnn-riscv.c
index a23b91ac15c..f1f72e9bd35 100644
--- a/bfd/elfnn-riscv.c
+++ b/bfd/elfnn-riscv.c
@@ -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);
diff --git a/binutils/readelf.c b/binutils/readelf.c
index b872876a8b6..5e3378457c7 100644
--- a/binutils/readelf.c
+++ b/binutils/readelf.c
@@ -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:
diff --git a/gas/config/tc-riscv.c b/gas/config/tc-riscv.c
index 99903deccec..7c47530801e 100644
--- a/gas/config/tc-riscv.c
+++ b/gas/config/tc-riscv.c
@@ -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))
diff --git a/include/elf/riscv.h b/include/elf/riscv.h
index aabc71cf979..932ce42bf97 100644
--- a/include/elf/riscv.h
+++ b/include/elf/riscv.h
@@ -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.  */