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]

[RFC patch] libffi support for FreeBSD/PowerPC


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

I'd appreciate some comments.

Thanks,
Andreas
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	9 Jul 2005 18:41:29 -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	9 Jul 2005 18:41:29 -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/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	9 Jul 2005 18:41:31 -0000
@@ -41,10 +41,20 @@
 
 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),
 
+  /* cr5 and cr6 bits are only used when the ABI follows the FFI_SYSV rules.  */
+  FLAG_SMALL_STRUCT_1	= 1 << (31-27), /* These go in cr6  */
+  FLAG_SMALL_STRUCT_2   = 1 << (31-26),
+  FLAG_SMALL_STRUCT_3   = 1 << (31-25),
+  FLAG_SMALL_STRUCT_5   = 1 << (31-24),
+
+  FLAG_SMALL_STRUCT_6	= 1 << (31-23),	/* These go in cr5  */
+  FLAG_SMALL_STRUCT_7	= 1 << (31-22),
+
   FLAG_ARG_NEEDS_COPY   = 1 << (31- 7),
   FLAG_FP_ARGUMENTS     = 1 << (31- 6), /* cr1.eq; specified by ABI */
   FLAG_4_GPR_ARGUMENTS  = 1 << (31- 5),
@@ -520,13 +530,47 @@
     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.  */
+	  if (cif->rtype->size <= 8)
+	    flags |= FLAG_RETURNS_SMST;
+
+	  if (cif->rtype->size == 1) {
+	    flags |= FLAG_SMALL_STRUCT_1;
 	    break;
-	  else if (cif->rtype->size <= 8)
-	    {
-	      flags |= FLAG_RETURNS_64BITS;
-	      break;
-	    }
+	  }
+	  if (cif->rtype->size == 2) {
+	    flags |= FLAG_SMALL_STRUCT_2;
+	    break;
+	  }
+	  if (cif->rtype->size == 3) {
+	    flags |= FLAG_SMALL_STRUCT_3;
+	    break;
+	  }
+	  /* A 4-byte struct is handled like an UINT32.  */
+	  if (cif->rtype->size == 4)
+	    break;
+
+	  if (cif->rtype->size == 5) {
+	    flags |= FLAG_SMALL_STRUCT_5;
+	    break;
+	  }
+
+	  if (cif->rtype->size == 6) {
+	    flags |= FLAG_SMALL_STRUCT_6;
+	    break;
+	  }
+	  if (cif->rtype->size == 7) {
+	    flags |= FLAG_SMALL_STRUCT_7;
+	    break;
+	  }
+	  /* If the struct is 8 byte in size it will be treated as two
+	     UINT32.  */
+	  else if (cif->rtype->size <= 8) {
+	    flags |= FLAG_RETURNS_64BITS;
+	    break;
+	  }
 	}
       /* else fall through.  */
 #if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
@@ -787,7 +831,6 @@
   /* Flush the icache.  */
   flush_icache(&closure->tramp[0],FFI_TRAMPOLINE_SIZE);
 #endif
-
   closure->cif = cif;
   closure->fun = fun;
   closure->user_data = user_data;
@@ -837,12 +880,17 @@
   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) && (cif->rtype->size <= 8))) {
+	rvalue = (void *) *pgr;
+	ng++;
+	pgr++;
+      }
     }
 
   i = 0;
@@ -986,9 +1034,28 @@
 
   (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) {
+    if (cif->rtype->size == 1)
+      return FFI_TYPE_SMST_1;
+    if (cif->rtype->size == 2)
+      return FFI_TYPE_SMST_2;
+    if (cif->rtype->size == 3)
+      return FFI_TYPE_SMST_3;
+    if (cif->rtype->size == 4)
+      return FFI_TYPE_UINT32;
+    if (cif->rtype->size == 5)
+      return FFI_TYPE_SMST_5;
+    if (cif->rtype->size == 6)
+      return FFI_TYPE_SMST_6;
+    if (cif->rtype->size == 7)
+      return FFI_TYPE_SMST_7;
+    if (cif->rtype->size == 8)
+      return FFI_TYPE_UINT64;
+  }
   return cif->rtype->type;
-
 }
 
 int hidden ffi_closure_helper_LINUX64 (ffi_closure*, void*, unsigned long*,
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	9 Jul 2005 18:41:31 -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,13 @@
 #define FFI_CLOSURES 1
 #define FFI_NATIVE_RAW_API 0
 
+#define FFI_TYPE_SMST_1  15
+#define FFI_TYPE_SMST_2  16
+#define FFI_TYPE_SMST_3  17
+#define FFI_TYPE_SMST_5  18
+#define FFI_TYPE_SMST_6  19
+#define FFI_TYPE_SMST_7  20
+
 #if defined(POWERPC64) || defined(POWERPC_AIX)
 #define FFI_TRAMPOLINE_SIZE 24
 #else /* POWERPC || POWERPC_AIX */
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	9 Jul 2005 18:41:31 -0000
@@ -190,6 +190,50 @@
 	nop
 	nop
 
+# The return types below are only used when the ABI type is FFI_SYSV.
+# case FFI_TYPE_SMST_1
+.Lret_type15:
+	lbz %r3,0(%r5)
+	b .Lfinish
+	nop
+	nop
+
+# case FFI_TYPE_SMST_2
+.Lret_type16:
+	lhz %r3,0(%r5)
+	b .Lfinish
+	nop
+	nop
+
+# case FFI_TYPE_SMST_3
+.Lret_type17:
+	lwz %r3,0(%r5)
+	srw %r3,%r3,2
+	b .Lfinish
+	nop
+
+
+# case FFI_TYPE_SMST_5
+.Lret_type18:
+	lbz %r3,0(%r5)
+	lwz %r4,1(%r5)
+	b .Lfinish
+	nop
+
+# case FFI_TYPE_SMST_6
+.Lret_type19:
+	lhz %r3,0(%r5)
+	lwz %r4,2(%r5)
+	b .Lfinish
+	nop
+	
+# case FFI_TYPE_SMST_7
+.Lret_type20:
+	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	9 Jul 2005 18:41:31 -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,45 @@
 L(float_return_value):
 	stfs	%f1,0(%r30)
 	b	L(done_return_value)
+
+L(small_struct_return_value):
+	mtcrf	0x02,%r31
+	bt-	27,L(smst_one_byte)
+	bt-	26,L(smst_two_byte)
+	bt-	25,L(smst_three_byte)
+	stw	%r3,0(%r30)
+	bt-	24,L(smst_five_byte)
+	mtcrf	0x04,%r31
+	bt-	23,L(smst_six_byte)
+	bt-	22,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]