diff mbox

[PowerPC/RTEMS] Add 64-bit support using ELFv2 ABI

Message ID 20170725122521.10857-1-sebastian.huber@embedded-brains.de
State New
Headers show

Commit Message

Sebastian Huber July 25, 2017, 12:25 p.m. UTC
Add 64-bit support for RTEMS using the ELFv2 ABI with 64-bit long
double.

gcc/
	* config.gcc (powerpc-*-rtems*): Remove rs6000/eabi.h.  Add
	rs6000/biarch64.h.
	* config/rs6000/rtems.h (ASM_DECLARE_FUNCTION_SIZE): New macro.
	(ASM_OUTPUT_SPECIAL_POOL_ENTRY_P): Likewise.
	(CRT_CALL_STATIC_FUNCTION): Likewise.
	(ASM_DEFAULT_SPEC): New define.
	(ASM_SPEC32): Likewise.
	(ASM_SPEC64): Likewise.
	(ASM_SPEC_COMMON): Likewise.
	(ASM_SPEC): Likewise.
	(INVALID_64BIT): Likewise.
	(LINK_OS_DEFAULT_SPEC): Likewise.
	(LINK_OS_SPEC32): Likewise.
	(LINK_OS_SPEC64): Likewise.
	(POWERPC_LINUX): Likewise.
	(PTRDIFF_TYPE): Likewise.
	(RESTORE_FP_PREFIX): Likewise.
	(RESTORE_FP_SUFFIX): Likewise.
	(SAVE_FP_PREFIX): Likewise.
	(SAVE_FP_SUFFIX): Likewise.
	(SIZE_TYPE): Likewise.
	(SUBSUBTARGET_OVERRIDE_OPTIONS): Likewise.
	(TARGET_64BIT): Likewise.
	(TARGET_64BIT): Likewise.
	(TARGET_AIX): Likewise.
	(WCHAR_TYPE_SIZE): Likewise.
	(WCHAR_TYPE): Undefine.
	(TARGET_OS_CPP_BUILTINS): Add 64-bit PowerPC defines.
	(CPP_OS_DEFAULT_SPEC): Use previous CPP_OS_RTEMS_SPEC.
	(CPP_OS_RTEMS_SPEC): Delete.
	(SUBSUBTARGET_EXTRA_SPECS): Remove cpp_os_rtems.  Add
	asm_spec_common, asm_spec32, asm_spec64, link_os_spec32, and
	link_os_spec64.
	* config/rs6000/t-rtems: Add mcpu=e6500/m64 multilib.

libgcc/
	* config/rs6000/ibm-ldouble.c: Disable if defined __rtems__.
---
 gcc/config.gcc                     |   2 +-
 gcc/config/rs6000/rtems.h          | 197 ++++++++++++++++++++++++++++++++++---
 gcc/config/rs6000/t-rtems          |   5 +
 libgcc/config/rs6000/ibm-ldouble.c |   3 +-
 4 files changed, 189 insertions(+), 18 deletions(-)

Comments

Segher Boessenkool July 26, 2017, 5:56 p.m. UTC | #1
Hi!

On Tue, Jul 25, 2017 at 02:25:21PM +0200, Sebastian Huber wrote:
> Add 64-bit support for RTEMS using the ELFv2 ABI with 64-bit long
> double.
> 
> diff --git a/gcc/config.gcc b/gcc/config.gcc
> index 2ae0218b5fc..aab7f65c1df 100644
> --- a/gcc/config.gcc
> +++ b/gcc/config.gcc
> @@ -2424,7 +2424,7 @@ powerpc-*-rtems*spe*)
>  	tmake_file="${tmake_file} powerpcspe/t-fprules powerpcspe/t-rtems powerpcspe/t-ppccomm"
>  	;;
>  powerpc-*-rtems*)
> -	tm_file="${tm_file} dbxelf.h elfos.h freebsd-spec.h newlib-stdint.h rs6000/sysv4.h rs6000/eabi.h rs6000/rtems.h rtems.h"
> +	tm_file="rs6000/biarch64.h ${tm_file} dbxelf.h elfos.h freebsd-spec.h newlib-stdint.h rs6000/sysv4.h rs6000/rtems.h rtems.h"

This deletes eabi.h and I don't see you add all its definitions to
rtems.h directly (NAME__MAIN etc.)  Is this on purpose?


Segher
Sebastian Huber July 27, 2017, 5:28 a.m. UTC | #2
On 26/07/17 19:56, Segher Boessenkool wrote:

> On Tue, Jul 25, 2017 at 02:25:21PM +0200, Sebastian Huber wrote:
>> Add 64-bit support for RTEMS using the ELFv2 ABI with 64-bit long
>> double.
>>
>> diff --git a/gcc/config.gcc b/gcc/config.gcc
>> index 2ae0218b5fc..aab7f65c1df 100644
>> --- a/gcc/config.gcc
>> +++ b/gcc/config.gcc
>> @@ -2424,7 +2424,7 @@ powerpc-*-rtems*spe*)
>>   	tmake_file="${tmake_file} powerpcspe/t-fprules powerpcspe/t-rtems powerpcspe/t-ppccomm"
>>   	;;
>>   powerpc-*-rtems*)
>> -	tm_file="${tm_file} dbxelf.h elfos.h freebsd-spec.h newlib-stdint.h rs6000/sysv4.h rs6000/eabi.h rs6000/rtems.h rtems.h"
>> +	tm_file="rs6000/biarch64.h ${tm_file} dbxelf.h elfos.h freebsd-spec.h newlib-stdint.h rs6000/sysv4.h rs6000/rtems.h rtems.h"
> This deletes eabi.h and I don't see you add all its definitions to
> rtems.h directly (NAME__MAIN etc.)  Is this on purpose?

Yes, I always wondered why GCC added the __eabi() call to main() out of 
thin air. In general, there is no main() function in RTEMS. Instead, you 
can statically configure initialization threads. We call __eabi() in the 
low-level startup code, e.g.

https://git.rtems.org/rtems/tree/c/src/lib/libbsp/powerpc/qoriq/start/start.S#n144
Segher Boessenkool July 27, 2017, 7:57 p.m. UTC | #3
On Thu, Jul 27, 2017 at 07:28:30AM +0200, Sebastian Huber wrote:
> >This deletes eabi.h and I don't see you add all its definitions to
> >rtems.h directly (NAME__MAIN etc.)  Is this on purpose?
> 
> Yes, I always wondered why GCC added the __eabi() call to main() out of 
> thin air. In general, there is no main() function in RTEMS. Instead, you 
> can statically configure initialization threads. We call __eabi() in the 
> low-level startup code, e.g.
> 
> https://git.rtems.org/rtems/tree/c/src/lib/libbsp/powerpc/qoriq/start/start.S#n144

Heh, I always thought the EABI must require it, but it seems to be a GCC
invention.

Patch looks fine to me then.  You can approve it yourself of course :-)


Segher
Sebastian Huber July 28, 2017, 8:29 a.m. UTC | #4
On 27/07/17 21:57, Segher Boessenkool wrote:

> On Thu, Jul 27, 2017 at 07:28:30AM +0200, Sebastian Huber wrote:
>>> This deletes eabi.h and I don't see you add all its definitions to
>>> rtems.h directly (NAME__MAIN etc.)  Is this on purpose?
>> Yes, I always wondered why GCC added the __eabi() call to main() out of
>> thin air. In general, there is no main() function in RTEMS. Instead, you
>> can statically configure initialization threads. We call __eabi() in the
>> low-level startup code, e.g.
>>
>> https://git.rtems.org/rtems/tree/c/src/lib/libbsp/powerpc/qoriq/start/start.S#n144
> Heh, I always thought the EABI must require it, but it seems to be a GCC
> invention.
>
> Patch looks fine to me then.  You can approve it yourself of course:-)

Thanks for your review, I checked it in in mainline and 7 branch.

Would you mind having a look at:

https://gcc.gnu.org/ml/gcc/2017-07/msg00196.html

Is the small data area no longer supported by GCC for 64-bit PowerPC?
Segher Boessenkool July 28, 2017, 5:36 p.m. UTC | #5
On Fri, Jul 28, 2017 at 10:29:21AM +0200, Sebastian Huber wrote:
> Would you mind having a look at:
> 
> https://gcc.gnu.org/ml/gcc/2017-07/msg00196.html
> 
> Is the small data area no longer supported by GCC for 64-bit PowerPC?

Yes, I'm looking at it, it takes a bit longer.

Currently we do not support sdata with ELFv2 in GCC; the question is
if we should.  Will let you know soon.


Segher
diff mbox

Patch

diff --git a/gcc/config.gcc b/gcc/config.gcc
index 2ae0218b5fc..aab7f65c1df 100644
--- a/gcc/config.gcc
+++ b/gcc/config.gcc
@@ -2424,7 +2424,7 @@  powerpc-*-rtems*spe*)
 	tmake_file="${tmake_file} powerpcspe/t-fprules powerpcspe/t-rtems powerpcspe/t-ppccomm"
 	;;
 powerpc-*-rtems*)
-	tm_file="${tm_file} dbxelf.h elfos.h freebsd-spec.h newlib-stdint.h rs6000/sysv4.h rs6000/eabi.h rs6000/rtems.h rtems.h"
+	tm_file="rs6000/biarch64.h ${tm_file} dbxelf.h elfos.h freebsd-spec.h newlib-stdint.h rs6000/sysv4.h rs6000/rtems.h rtems.h"
 	extra_options="${extra_options} rs6000/sysv4.opt"
 	tmake_file="${tmake_file} rs6000/t-fprules rs6000/t-rtems rs6000/t-ppccomm"
 	;;
diff --git a/gcc/config/rs6000/rtems.h b/gcc/config/rs6000/rtems.h
index 1ab4e313fdb..8a62fdcbaf3 100644
--- a/gcc/config/rs6000/rtems.h
+++ b/gcc/config/rs6000/rtems.h
@@ -23,29 +23,163 @@ 
    see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
    <http://www.gnu.org/licenses/>.  */
 
-/* Specify predefined symbols in preprocessor.  */
+/* Copy and paste from linux64.h and freebsd64.h */
+#ifdef IN_LIBGCC2
+#undef TARGET_64BIT
+#ifdef __powerpc64__
+#define TARGET_64BIT 1
+#else
+#define TARGET_64BIT 0
+#endif
+#endif
+
+/* Copy and paste from linux64.h and freebsd64.h */
+#undef	TARGET_AIX
+#define	TARGET_AIX TARGET_64BIT
 
 #undef TARGET_OS_CPP_BUILTINS
-#define TARGET_OS_CPP_BUILTINS()          \
-  do                                      \
-    {                                     \
-      builtin_define_std ("PPC");         \
-      builtin_define ("__rtems__");       \
-      builtin_define ("__USE_INIT_FINI__"); \
-      builtin_assert ("system=rtems");    \
-      builtin_assert ("cpu=powerpc");     \
-      builtin_assert ("machine=powerpc"); \
-      TARGET_OS_SYSV_CPP_BUILTINS ();     \
-    }                                     \
+#define TARGET_OS_CPP_BUILTINS()			\
+  do							\
+    {							\
+      builtin_define ("__rtems__");			\
+      builtin_define ("__USE_INIT_FINI__");		\
+      builtin_assert ("system=rtems");			\
+      if (TARGET_64BIT)					\
+	{						\
+	  builtin_define ("__PPC__");			\
+	  builtin_define ("__PPC64__");			\
+	  builtin_define ("__powerpc64__");		\
+	  builtin_assert ("cpu=powerpc64");		\
+	  builtin_assert ("machine=powerpc64");		\
+	}						\
+      else						\
+	{						\
+	  builtin_define_std ("PPC");			\
+	  builtin_define_std ("powerpc");		\
+	  builtin_assert ("cpu=powerpc");		\
+	  builtin_assert ("machine=powerpc");		\
+	  TARGET_OS_SYSV_CPP_BUILTINS ();		\
+	}						\
+    }							\
+  while (0)
+
+/* Copy and paste from linux64.h and freebsd64.h */
+#define INVALID_64BIT "-m%s not supported in this configuration"
+
+/* A lot of copy and paste from linux64.h and freebsd64.h */
+#undef	SUBSUBTARGET_OVERRIDE_OPTIONS
+#define	SUBSUBTARGET_OVERRIDE_OPTIONS				\
+  do								\
+    {								\
+      if (rs6000_isa_flags & OPTION_MASK_64BIT)			\
+	{							\
+	  rs6000_elf_abi = 2;					\
+	  rs6000_current_abi = ABI_ELFv2;			\
+	  if (rs6000_isa_flags & OPTION_MASK_RELOCATABLE)	\
+	    {							\
+	      rs6000_isa_flags &= ~OPTION_MASK_RELOCATABLE;	\
+	      error (INVALID_64BIT, "relocatable");		\
+	    }							\
+	  if (rs6000_isa_flags & OPTION_MASK_EABI)		\
+	    {							\
+	      rs6000_isa_flags &= ~OPTION_MASK_EABI;		\
+	      error (INVALID_64BIT, "eabi");			\
+	    }							\
+	  if (TARGET_PROTOTYPE)					\
+	    {							\
+	      target_prototype = 0;				\
+	      error (INVALID_64BIT, "prototype");		\
+	    }							\
+	  if ((rs6000_isa_flags & OPTION_MASK_POWERPC64) == 0)	\
+	    {							\
+	      rs6000_isa_flags |= OPTION_MASK_POWERPC64;	\
+	      error ("-m64 requires a PowerPC64 cpu");		\
+	    }							\
+	}							\
+    }								\
   while (0)
 
 #undef TARGET_LIBGCC_SDATA_SECTION
 #define TARGET_LIBGCC_SDATA_SECTION ".sdata"
 
-#undef CPP_OS_DEFAULT_SPEC
-#define CPP_OS_DEFAULT_SPEC "%(cpp_os_rtems)"
+/* Copy and paste from linux64.h and freebsd64.h */
+#undef	SIZE_TYPE
+#define	SIZE_TYPE (TARGET_64BIT ? "long unsigned int" : "unsigned int")
+
+/* Copy and paste from linux64.h and freebsd64.h */
+#undef	PTRDIFF_TYPE
+#define	PTRDIFF_TYPE (TARGET_64BIT ? "long int" : "int")
+
+/* Copy and paste from freebsd64.h */
+#undef WCHAR_TYPE
+
+/* Copy and paste from freebsd64.h */
+#undef  WCHAR_TYPE_SIZE
+#define WCHAR_TYPE_SIZE 32
+
+/* Copy and paste from linux64.h and freebsd64.h */
+#ifdef __powerpc64__
+#define CRT_CALL_STATIC_FUNCTION(SECTION_OP, FUNC)	\
+  asm (SECTION_OP "\n"					\
+"	bl " #FUNC "\n"					\
+"	nop\n"						\
+"	.previous");
+#endif
+
+/* This could be also POWERPC_FREEBSD.  It is related to the save/restore
+   defines below.  */
+#define POWERPC_LINUX
+
+/* Copy and paste from linux64.h and freebsd64.h */
+#undef  SAVE_FP_PREFIX
+#define SAVE_FP_PREFIX (TARGET_64BIT ? "._savef" : "_savefpr_")
+#undef  SAVE_FP_SUFFIX
+#define SAVE_FP_SUFFIX ""
+#undef  RESTORE_FP_PREFIX
+#define RESTORE_FP_PREFIX (TARGET_64BIT ? "._restf" : "_restfpr_")
+#undef  RESTORE_FP_SUFFIX
+#define RESTORE_FP_SUFFIX ""
 
-#define CPP_OS_RTEMS_SPEC "\
+/* Copy and paste from linux64.h and freebsd64.h */
+#undef	ASM_DECLARE_FUNCTION_SIZE
+#define	ASM_DECLARE_FUNCTION_SIZE(FILE, FNAME, DECL)			\
+  do									\
+    {									\
+      if (!flag_inhibit_size_directive)					\
+	{								\
+	  fputs ("\t.size\t", (FILE));					\
+	  if (TARGET_64BIT && DOT_SYMBOLS)				\
+	    putc ('.', (FILE));						\
+	  assemble_name ((FILE), (FNAME));				\
+	  fputs (",.-", (FILE));					\
+	  rs6000_output_function_entry (FILE, FNAME);			\
+	  putc ('\n', (FILE));						\
+	}								\
+    }									\
+  while (0)
+
+/* Copy and paste from linux64.h and freebsd64.h */
+#undef  ASM_OUTPUT_SPECIAL_POOL_ENTRY_P
+#define ASM_OUTPUT_SPECIAL_POOL_ENTRY_P(X, MODE)			\
+  (TARGET_TOC								\
+   && (GET_CODE (X) == SYMBOL_REF					\
+       || (GET_CODE (X) == CONST && GET_CODE (XEXP (X, 0)) == PLUS	\
+	   && GET_CODE (XEXP (XEXP (X, 0), 0)) == SYMBOL_REF)		\
+       || GET_CODE (X) == LABEL_REF					\
+       || (GET_CODE (X) == CONST_INT 					\
+	   && GET_MODE_BITSIZE (MODE) <= GET_MODE_BITSIZE (Pmode))	\
+       || (GET_CODE (X) == CONST_DOUBLE					\
+	   && ((TARGET_64BIT						\
+		&& (TARGET_MINIMAL_TOC					\
+		    || (SCALAR_FLOAT_MODE_P (GET_MODE (X))		\
+			&& ! TARGET_NO_FP_IN_TOC)))			\
+	       || (!TARGET_64BIT					\
+		   && !TARGET_NO_FP_IN_TOC				\
+		   && SCALAR_FLOAT_MODE_P (GET_MODE (X))		\
+		   && BITS_PER_WORD == HOST_BITS_PER_INT)))))
+
+#undef CPP_OS_DEFAULT_SPEC
+#define CPP_OS_DEFAULT_SPEC "\
 %{!mcpu*:  %{!Dppc*: %{!Dmpc*: -Dmpc750} } }\
 %{mcpu=403:  %{!Dppc*: %{!Dmpc*: -Dppc403}  } } \
 %{mcpu=505:  %{!Dppc*: %{!Dmpc*: -Dmpc505}  } } \
@@ -60,6 +194,37 @@ 
 %{mcpu=8540: %{!Dppc*: %{!Dmpc*: -Dppc8540}  } } \
 %{mcpu=e6500: -D__PPC_CPU_E6500__}"
 
+#undef	ASM_DEFAULT_SPEC
+#define	ASM_DEFAULT_SPEC "-mppc%{m64:64}"
+
+#undef	ASM_SPEC
+#define	ASM_SPEC "%{!m64:%(asm_spec32)}%{m64:%(asm_spec64)} %(asm_spec_common)"
+
+#define ASM_SPEC32 "-a32 \
+%{mrelocatable} %{mrelocatable-lib} %{" FPIE_OR_FPIC_SPEC ":-K PIC} \
+%{memb|msdata=eabi: -memb}"
+
+#define ASM_SPEC64 "-a64"
+
+#define ASM_SPEC_COMMON "%(asm_cpu) \
+%{,assembler|,assembler-with-cpp: %{mregnames} %{mno-regnames}}" \
+  ENDIAN_SELECT(" -mbig", " -mlittle", DEFAULT_ASM_ENDIAN)
+
+#undef  LINK_OS_DEFAULT_SPEC
+#define LINK_OS_DEFAULT_SPEC \
+"%{!m64:%(link_os_spec32)}%{m64:%(link_os_spec64)}"
+
+#define LINK_OS_SPEC32 ENDIAN_SELECT(" -m elf32ppc",		\
+				     " -m elf32lppc",		\
+				     " -m elf32ppc")
+#define LINK_OS_SPEC64 ENDIAN_SELECT(" -m elf64ppc",		\
+				     " -m elf64lppc",		\
+				     " -m elf64ppc")
+
 #undef  SUBSUBTARGET_EXTRA_SPECS
 #define SUBSUBTARGET_EXTRA_SPECS \
-  { "cpp_os_rtems",		CPP_OS_RTEMS_SPEC }
+  { "asm_spec_common",		ASM_SPEC_COMMON },			\
+  { "asm_spec32",		ASM_SPEC32 },				\
+  { "asm_spec64",		ASM_SPEC64 },				\
+  { "link_os_spec32",		LINK_OS_SPEC32 },			\
+  { "link_os_spec64",		LINK_OS_SPEC64 },
diff --git a/gcc/config/rs6000/t-rtems b/gcc/config/rs6000/t-rtems
index 8290f5c5bdd..e8878a92898 100644
--- a/gcc/config/rs6000/t-rtems
+++ b/gcc/config/rs6000/t-rtems
@@ -33,6 +33,9 @@  MULTILIB_DIRNAMES += m32
 MULTILIB_OPTIONS += msoft-float
 MULTILIB_DIRNAMES += nof
 
+MULTILIB_OPTIONS += m64
+MULTILIB_DIRNAMES += m64
+
 MULTILIB_OPTIONS += mno-altivec
 MULTILIB_DIRNAMES += noaltivec
 
@@ -72,3 +75,5 @@  MULTILIB_REQUIRED += mcpu=8540/msoft-float
 MULTILIB_REQUIRED += mcpu=860
 MULTILIB_REQUIRED += mcpu=e6500/m32
 MULTILIB_REQUIRED += mcpu=e6500/m32/msoft-float/mno-altivec
+MULTILIB_REQUIRED += mcpu=e6500/m64
+MULTILIB_REQUIRED += mcpu=e6500/m64/msoft-float/mno-altivec
diff --git a/libgcc/config/rs6000/ibm-ldouble.c b/libgcc/config/rs6000/ibm-ldouble.c
index 949b50c98ca..e99652e523f 100644
--- a/libgcc/config/rs6000/ibm-ldouble.c
+++ b/libgcc/config/rs6000/ibm-ldouble.c
@@ -45,7 +45,8 @@  see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
    This code currently assumes the most significant double is in
    the lower numbered register or lower addressed memory.  */
 
-#if defined (__MACH__) || defined (__powerpc__) || defined (_AIX)
+#if (defined (__MACH__) || defined (__powerpc__) || defined (_AIX)) \
+    && !defined (__rtems__)
 
 #define fabs(x) __builtin_fabs(x)
 #define isless(x, y) __builtin_isless (x, y)