This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[RFC patch] libffi support for FreeBSD/PowerPC
- From: Andreas Tobler <toa at pop dot agri dot ch>
- To: GCC Patches <gcc-patches at gcc dot gnu dot org>, Java Patches <java-patches at gcc dot gnu dot org>
- Date: Sat, 09 Jul 2005 23:49:42 +0200
- Subject: [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)