This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[patch] fix pr31937 soft-float for libffi ppc 32-bit


Hi all,
this patch adds soft float support for libffi-ppc 32-bit. Tested by Martin and me on a ppc-405 target. Libffi and libjava, on trunk.
No negative influence on real ppc with fpu.


This patch 'fixes' pr31937.

The patch itself makes sure not to store float/double in the asm part. Also, the patch 'changes' the ABI to store float as UINT32 and double as UINT64.

Ok for trunk?

Thanks,
Andreas

2007-11-06 Andreas Tobler <a.tobler@schweiz.org>

	PR libffi/31937
	* src/powerpc/ffi.c (enum): Add __NO_FPRS__, handle soft-float support.
	(ffi_prep_args_SYSV): Handle __NO_FPRS__.
	(ffi_prep_cif_machdep): Likewise.
	(ffi_closure_helper_SYSV): Likewise.
	* src/powerpc/ppc_closure.S: Make sure not to store float/double
	on SOFT_FLOAT archs.
Index: src/powerpc/ppc_closure.S
===================================================================
--- src/powerpc/ppc_closure.S	(revision 129874)
+++ src/powerpc/ppc_closure.S	(working copy)
@@ -28,6 +28,7 @@
 	stw   %r9, 40(%r1)
 	stw   %r10,44(%r1)
 
+#ifndef __NO_FPRS__
 	# next save fpr 1 to fpr 8 (aligned to 8)
 	stfd  %f1, 48(%r1)
 	stfd  %f2, 56(%r1)
@@ -37,6 +38,7 @@
 	stfd  %f6, 88(%r1)
 	stfd  %f7, 96(%r1)
 	stfd  %f8, 104(%r1)
+#endif
 
 	# set up registers for the routine that actually does the work
 	# get the context pointer from the trampoline
Index: src/powerpc/ffi.c
===================================================================
--- src/powerpc/ffi.c	(revision 129874)
+++ src/powerpc/ffi.c	(working copy)
@@ -51,7 +51,11 @@
 /* About the SYSV ABI.  */
 enum {
   NUM_GPR_ARG_REGISTERS = 8,
+#ifndef __NO_FPRS__
   NUM_FPR_ARG_REGISTERS = 8
+#else
+  NUM_FPR_ARG_REGISTERS = 0
+#endif
 };
 enum { ASM_NEEDS_REGISTERS = 4 };
 
@@ -117,7 +121,9 @@
 
   int i;
   ffi_type **ptr;
+#ifndef __NO_FPRS__
   double double_tmp;
+#endif
   union {
     void **v;
     char **c;
@@ -163,6 +169,7 @@
     {
       switch ((*ptr)->type)
 	{
+#ifndef __NO_FPRS__
 	case FFI_TYPE_FLOAT:
 	  double_tmp = **p_argv.f;
 	  if (fparg_count >= NUM_FPR_ARG_REGISTERS)
@@ -195,6 +202,7 @@
 	  fparg_count++;
 	  FFI_ASSERT (flags & FLAG_FP_ARGUMENTS);
 	  break;
+#endif
 
 #if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
 	case FFI_TYPE_LONGDOUBLE:
@@ -230,6 +238,9 @@
 
 	case FFI_TYPE_UINT64:
 	case FFI_TYPE_SINT64:
+#ifdef __NO_FPRS__
+	case FFI_TYPE_DOUBLE:
+#endif
 	  if (intarg_count == NUM_GPR_ARG_REGISTERS-1)
 	    intarg_count++;
 	  if (intarg_count >= NUM_GPR_ARG_REGISTERS)
@@ -292,6 +303,9 @@
 	case FFI_TYPE_UINT32:
 	case FFI_TYPE_SINT32:
 	case FFI_TYPE_POINTER:
+#ifdef __NO_FPRS__
+	case FFI_TYPE_FLOAT:
+#endif
 	  gprvalue = **p_argv.ui;
 
 	putgpr:
@@ -596,7 +610,9 @@
       flags |= FLAG_RETURNS_64BITS;
       /* Fall through.  */
     case FFI_TYPE_FLOAT:
+#ifndef __NO_FPRS__
       flags |= FLAG_RETURNS_FP;
+#endif
       break;
 
     case FFI_TYPE_UINT64:
@@ -658,6 +674,7 @@
       {
 	switch ((*ptr)->type)
 	  {
+#ifndef __NO_FPRS__
 	  case FFI_TYPE_FLOAT:
 	    fparg_count++;
 	    /* floating singles are not 8-aligned on stack */
@@ -680,8 +697,12 @@
 	      intarg_count++;
 	    break;
 
+#endif
 	  case FFI_TYPE_UINT64:
 	  case FFI_TYPE_SINT64:
+#ifdef __NO_FPRS__
+	  case FFI_TYPE_DOUBLE:
+#endif
 	    /* 'long long' arguments are passed as two words, but
 	       either both words must fit in registers or both go
 	       on the stack.  If they go on the stack, they must
@@ -922,7 +943,9 @@
   long             nf;   /* number of floating registers already used */
   long             ng;   /* number of general registers already used */
   ffi_cif *        cif;
+#ifndef __NO_FPRS__
   double           temp;
+#endif
   unsigned         size;
 
   cif = closure->cif;
@@ -994,6 +1017,9 @@
 	case FFI_TYPE_SINT32:
 	case FFI_TYPE_UINT32:
 	case FFI_TYPE_POINTER:
+#ifdef __NO_FPRS__
+	case FFI_TYPE_FLOAT:
+#endif
 	  /* there are 8 gpr registers used to pass values */
 	  if (ng < 8)
 	    {
@@ -1029,6 +1055,9 @@
 
 	case FFI_TYPE_SINT64:
 	case FFI_TYPE_UINT64:
+#ifdef __NO_FPRS__
+	case FFI_TYPE_DOUBLE:
+#endif
 	  /* passing long long ints are complex, they must
 	   * be passed in suitable register pairs such as
 	   * (r3,r4) or (r5,r6) or (r6,r7), or (r7,r8) or (r9,r10)
@@ -1059,6 +1088,7 @@
 	    }
 	  break;
 
+#ifndef __NO_FPRS__
 	case FFI_TYPE_FLOAT:
 	  /* unfortunately float values are stored as doubles
 	   * in the ffi_closure_SYSV code (since we don't check
@@ -1106,6 +1136,7 @@
 	    }
 	  break;
 
+#endif
 #if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
 	case FFI_TYPE_LONGDOUBLE:
 	  if (cif->abi != FFI_LINUX)
@@ -1149,7 +1180,21 @@
 	   && cif->abi != FFI_LINUX)
     return FFI_TYPE_STRUCT;
 #endif
+#ifdef __NO_FPRS__
+  switch (cif->rtype->type)
+    {
+    case FFI_TYPE_FLOAT:
+      return FFI_TYPE_UINT32;
+      break;
+    case FFI_TYPE_DOUBLE:
+      return FFI_TYPE_UINT64;
+      break;
+    default:
+      return cif->rtype->type;
+    }
+#else
   return cif->rtype->type;
+#endif
 }
 
 int FFI_HIDDEN ffi_closure_helper_LINUX64 (ffi_closure *, void *,

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]