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]

Re: [RFC patch] libffi support for FreeBSD/PowerPC


Andreas Tobler wrote:
Hi all,

the attached patch brings libffi support for FreeBSD/PowerPC. In the core it is equal to the linux-ppc 32-bit port. But the thing which is different, is the FreeBSD/PowerPC port supports the final SYSV 4 ABI versus the draft one linux-ppc does. This means that small structures (smaller or equal 8 bytes) are passed in r3/r4 instead of memory as linux-ppc does.
I tested the patch on FreeBSD/PowerPC and linux-ppc 32-bit. No regressions. I do not have a 64-bit platform around. I'd appreciate if one could give it a short run. Although I do not expect any fall out.


I'd like to point to test results, but unfortunately the FreeBSD/PowerPC port does not yet support Altivec which prevents me from running a make -k check over the whole build. I need first to clean up/adjust the gcc testsuite to NOT test Altivec tests on FreeBSD/PowerPC. (Which is not that easy since we have tests which check Altivec directly.) GDB does it better ....

A suitable CL will follow. I smoked my fbsd machine just before writing the CL, with Altivec tests .....

Second try, added a CL and I also incorporated some feedback from dje. Less defines. Thanks David.


Andreas

2005-07-11 Andreas Tobler <a.tobler@schweiz.ch>

	* Makefile.am (nodist_libffi_la_SOURCES): Add POWERPC_FREEBSD.
	* Makefile.in: Regenerate.
	* configure.ac: Add POWERPC_FREEBSD rules.
	* configure: Regenerate.
	* src/powerpc/ffitarget.h: Add POWERPC_FREEBSD rules.
	(FFI_SYSV_TYPE_SMALL_STRUCT): Define.
	* src/powerpc/ffi.c: Add flags to handle small structure returns
	in ffi_call_SYSV.
	(ffi_prep_cif_machdep): Handle small structures for SYSV 4 ABI.
	Aka FFI_SYSV.
	(ffi_closure_helper_SYSV): Likewise.
	* src/powerpc/ppc_closure.S: Add return types for small structures.
	* src/powerpc/sysv.S: Add bits to handle small structures for
	final SYSV 4 ABI.
Index: Makefile.am
===================================================================
RCS file: /cvs/gcc/gcc/libffi/Makefile.am,v
retrieving revision 1.40
diff -u -r1.40 Makefile.am
--- Makefile.am	18 May 2005 01:49:29 -0000	1.40
+++ Makefile.am	11 Jul 2005 18:38:35 -0000
@@ -117,6 +117,9 @@
 if POWERPC_DARWIN
 nodist_libffi_la_SOURCES += src/powerpc/ffi_darwin.c src/powerpc/darwin.S src/powerpc/darwin_closure.S
 endif
+if POWERPC_FREEBSD
+nodist_libffi_la_SOURCES += src/powerpc/ffi.c src/powerpc/sysv.S src/powerpc/ppc_closure.S
+endif
 if ARM
 nodist_libffi_la_SOURCES += src/arm/sysv.S src/arm/ffi.c
 endif
Index: configure.ac
===================================================================
RCS file: /cvs/gcc/gcc/libffi/configure.ac,v
retrieving revision 1.15
diff -u -r1.15 configure.ac
--- configure.ac	14 Jun 2005 23:37:05 -0000	1.15
+++ configure.ac	11 Jul 2005 18:38:36 -0000
@@ -68,6 +68,7 @@
 powerpc-*-beos*) TARGET=POWERPC; TARGETDIR=powerpc;;
 powerpc-*-darwin*) TARGET=POWERPC_DARWIN; TARGETDIR=powerpc;;
 powerpc-*-aix*) TARGET=POWERPC_AIX; TARGETDIR=powerpc;;
+powerpc-*-freebsd*) TARGET=POWERPC_FREEBSD; TARGETDIR=powerpc;;
 powerpc*-*-rtems*) TARGET=POWERPC; TARGETDIR=powerpc;;
 rs6000-*-aix*) TARGET=POWERPC_AIX; TARGETDIR=powerpc;;
 arm*-*-linux-*) TARGET=ARM; TARGETDIR=arm;;
@@ -101,6 +102,7 @@
 AM_CONDITIONAL(POWERPC, test x$TARGET = xPOWERPC)
 AM_CONDITIONAL(POWERPC_AIX, test x$TARGET = xPOWERPC_AIX)
 AM_CONDITIONAL(POWERPC_DARWIN, test x$TARGET = xPOWERPC_DARWIN)
+AM_CONDITIONAL(POWERPC_FREEBSD, test x$TARGET = xPOWERPC_FREEBSD)
 AM_CONDITIONAL(ARM, test x$TARGET = xARM)
 AM_CONDITIONAL(LIBFFI_CRIS, test x$TARGET = xLIBFFI_CRIS)
 AM_CONDITIONAL(FRV, test x$TARGET = xFRV)
Index: src/powerpc/ffitarget.h
===================================================================
RCS file: /cvs/gcc/gcc/libffi/src/powerpc/ffitarget.h,v
retrieving revision 1.2
diff -u -r1.2 ffitarget.h
--- src/powerpc/ffitarget.h	2 Sep 2004 21:07:21 -0000	1.2
+++ src/powerpc/ffitarget.h	11 Jul 2005 18:38:36 -0000
@@ -62,6 +62,13 @@
   FFI_DEFAULT_ABI = FFI_DARWIN,
 #endif
 
+#ifdef POWERPC_FREEBSD
+  FFI_SYSV,
+  FFI_GCC_SYSV,
+  FFI_LINUX64,
+  FFI_DEFAULT_ABI = FFI_SYSV,
+#endif
+
   FFI_LAST_ABI = FFI_DEFAULT_ABI + 1
 } ffi_abi;
 #endif
@@ -71,6 +78,8 @@
 #define FFI_CLOSURES 1
 #define FFI_NATIVE_RAW_API 0
 
+#define FFI_SYSV_TYPE_SMALL_STRUCT  (FFI_TYPE_LAST)
+
 #if defined(POWERPC64) || defined(POWERPC_AIX)
 #define FFI_TRAMPOLINE_SIZE 24
 #else /* POWERPC || POWERPC_AIX */
Index: src/powerpc/ffi.c
===================================================================
RCS file: /cvs/gcc/gcc/libffi/src/powerpc/ffi.c,v
retrieving revision 1.12
diff -u -r1.12 ffi.c
--- src/powerpc/ffi.c	23 Feb 2005 14:05:12 -0000	1.12
+++ src/powerpc/ffi.c	11 Jul 2005 18:38:37 -0000
@@ -41,6 +41,7 @@
 
 enum {
   /* The assembly depends on these exact flags.  */
+  FLAG_RETURNS_SMST	= 1 << (31-31), /* Used for FFI_SYSV small structs.  */
   FLAG_RETURNS_NOTHING  = 1 << (31-30), /* These go in cr7 */
   FLAG_RETURNS_FP       = 1 << (31-29),
   FLAG_RETURNS_64BITS   = 1 << (31-28),
@@ -462,6 +463,7 @@
   unsigned flags = 0;
   unsigned struct_copy_size = 0;
   unsigned type = cif->rtype->type;
+  unsigned size = cif->rtype->size;
 
   if (cif->abi != FFI_LINUX64)
     {
@@ -520,13 +522,16 @@
     case FFI_TYPE_STRUCT:
       if (cif->abi != FFI_GCC_SYSV && cif->abi != FFI_LINUX64)
 	{
-	  if (cif->rtype->size <= 4)
+	  /* The final SYSV ABI says that structures smaller or equal 8 bytes
+	     are returned in r3/r4. The FFI_GCC_SYSV ABI instead returns them
+	     in memory.  */
+
+	  /* Treat structs with size <= 8 bytes.  */
+	  if (size <= 8) {
+	    flags |= FLAG_RETURNS_SMST;
+	    flags |= 1 << (31 - (FFI_SYSV_TYPE_SMALL_STRUCT + size));
 	    break;
-	  else if (cif->rtype->size <= 8)
-	    {
-	      flags |= FLAG_RETURNS_64BITS;
-	      break;
-	    }
+	  }
 	}
       /* else fall through.  */
 #if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
@@ -770,7 +775,7 @@
 #else
   unsigned int *tramp;
 
-  FFI_ASSERT (cif->abi == FFI_GCC_SYSV);
+  FFI_ASSERT (cif->abi == FFI_GCC_SYSV || cif->abi == FFI_SYSV);
 
   tramp = (unsigned int *) &closure->tramp[0];
   tramp[0] = 0x7c0802a6;  /*   mflr    r0 */
@@ -787,7 +792,6 @@
   /* Flush the icache.  */
   flush_icache(&closure->tramp[0],FFI_TRAMPOLINE_SIZE);
 #endif
-
   closure->cif = cif;
   closure->fun = fun;
   closure->user_data = user_data;
@@ -829,20 +833,27 @@
   long             ng;   /* number of general registers already used */
   ffi_cif *        cif;
   double           temp;
+  unsigned         size;
 
   cif = closure->cif;
   avalue = alloca(cif->nargs * sizeof(void *));
+  size = cif->rtype->size;
 
   nf = 0;
   ng = 0;
 
   /* Copy the caller's structure return value address so that the closure
-     returns the data directly to the caller.  */
+     returns the data directly to the caller.
+     For FFI_SYSV the result is passed in r3/r4 if the struct size is less
+     or equal 8 bytes.  */
+
   if (cif->rtype->type == FFI_TYPE_STRUCT)
     {
-      rvalue = (void *) *pgr;
-      ng++;
-      pgr++;
+      if (!((cif->abi == FFI_SYSV) && (size <= 8))) {
+	rvalue = (void *) *pgr;
+	ng++;
+	pgr++;
+      }
     }
 
   i = 0;
@@ -986,9 +997,18 @@
 
   (closure->fun) (cif, rvalue, avalue, closure->user_data);
 
-  /* Tell ffi_closure_SYSV how to perform return type promotions.  */
+  /* Tell ffi_closure_SYSV how to perform return type promotions.
+     Since the FFI_SYSV ABI returns the structures <= 8 bytes in r3/r4
+     we have to tell ffi_closure_SYSV how to treat them.  */
+  if (cif->abi == FFI_SYSV && cif->rtype->type == FFI_TYPE_STRUCT
+      && size <= 8)
+    {
+      if (size == 8)
+	return FFI_TYPE_UINT64;
+      
+      return FFI_SYSV_TYPE_SMALL_STRUCT + size;
+    }
   return cif->rtype->type;
-
 }
 
 int hidden ffi_closure_helper_LINUX64 (ffi_closure*, void*, unsigned long*,
Index: src/powerpc/ppc_closure.S
===================================================================
RCS file: /cvs/gcc/gcc/libffi/src/powerpc/ppc_closure.S,v
retrieving revision 1.10
diff -u -r1.10 ppc_closure.S
--- src/powerpc/ppc_closure.S	1 Jun 2005 00:33:09 -0000	1.10
+++ src/powerpc/ppc_closure.S	11 Jul 2005 18:38:37 -0000
@@ -190,6 +190,56 @@
 	nop
 	nop
 
+# The return types below are only used when the ABI type is FFI_SYSV.
+# case FFI_SYSV_TYPE_SMALL_STRUCT + 1. One byte struct.
+.Lret_type15:
+	lbz %r3,0(%r5)
+	b .Lfinish
+	nop
+	nop
+
+# case FFI_SYSV_TYPE_SMALL_STRUCT + 2. Two byte struct.
+.Lret_type16:
+	lhz %r3,0(%r5)
+	b .Lfinish
+	nop
+	nop
+
+# case FFI_SYSV_TYPE_SMALL_STRUCT + 3. Three byte struct.
+.Lret_type17:
+	lwz %r3,0(%r5)
+	srw %r3,%r3,2
+	b .Lfinish
+	nop
+
+# case FFI_SYSV_TYPE_SMALL_STRUCT + 4. Four byte struct.
+.Lret_type18:
+	lwz %r3,0(%r5)
+	b .Lfinish
+	nop
+	nop
+
+# case FFI_SYSV_TYPE_SMALL_STRUCT + 5. Five byte struct.
+.Lret_type19:
+	lbz %r3,0(%r5)
+	lwz %r4,1(%r5)
+	b .Lfinish
+	nop
+
+# case FFI_SYSV_TYPE_SMALL_STRUCT + 6. Six byte struct.
+.Lret_type20:
+	lhz %r3,0(%r5)
+	lwz %r4,2(%r5)
+	b .Lfinish
+	nop
+
+# case FFI_SYSV_TYPE_SMALL_STRUCT + 7. Seven byte struct.
+.Lret_type21:
+	lwz %r3,0(%r5)
+	srw %r3,%r3,2
+	lwz %r4,3(%r5)
+	b .Lfinish
+
 # case done
 .Lfinish:
 
Index: src/powerpc/sysv.S
===================================================================
RCS file: /cvs/gcc/gcc/libffi/src/powerpc/sysv.S,v
retrieving revision 1.7
diff -u -r1.7 sysv.S
--- src/powerpc/sysv.S	1 Jun 2005 00:33:09 -0000	1.7
+++ src/powerpc/sysv.S	11 Jul 2005 18:38:38 -0000
@@ -99,6 +99,7 @@
 
 	/* Now, deal with the return value.  */
 	mtcrf	0x01,%r31
+	bt-	31,L(small_struct_return_value)
 	bt-	30,L(done_return_value)
 	bt-	29,L(fp_return_value)
 	stw	%r3,0(%r30)
@@ -124,6 +125,46 @@
 L(float_return_value):
 	stfs	%f1,0(%r30)
 	b	L(done_return_value)
+
+L(small_struct_return_value):
+	mtcrf	0x10,%r31	/* cr3  */
+	bt-	15,L(smst_one_byte)
+	mtcrf	0x08,%r31	/* cr4  */
+	bt-	16,L(smst_two_byte)
+	bt-	17,L(smst_three_byte)
+	stw	%r3,0(%r30)
+	bt-	19,L(smst_five_byte)
+	mtcrf	0x04,%r31	/* cr5  */
+	bt-	20,L(smst_six_byte)
+	bt-	21,L(smst_seven_byte)
+	stw	%r4,4(%r30)
+	b       L(done_return_value)
+
+L(smst_one_byte):
+	stb	%r3,0(%r30)
+	b	L(done_return_value)
+L(smst_two_byte):
+	sth	%r3,0(%r30)
+	b	L(done_return_value)
+L(smst_three_byte):
+	slw     %r3,%r3,2
+	stw	%r3,0(%r30)
+	b	L(done_return_value)
+L(smst_five_byte):
+	stb	%r3,0(%r30)
+	stw	%r4,1(%r30)
+	b	L(done_return_value)
+L(smst_six_byte):
+	slw	%r3,%r3,1
+	stw	%r3,0(%r30)
+	stw	%r4,2(%r30)
+	b       L(done_return_value)
+L(smst_seven_byte):
+	slw     %r3,%r3,2
+	stw	%r3,0(%r30)
+	stw	%r4,3(%r30)
+	b       L(done_return_value)
+
 .LFE1:
 END(ffi_call_SYSV)
 

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