This is the mail archive of the
libffi-discuss@sourceware.org
mailing list for the libffi project.
[PATCH] libffi-3.0.4: support for AIX 64bit
- From: Laurent Vivier <Laurent dot Vivier at bull dot net>
- To: libffi-discuss at sourceware dot org
- Date: Wed, 12 Mar 2008 18:27:18 +0100
- Subject: [PATCH] libffi-3.0.4: support for AIX 64bit
Hi,
This patch is an updated port to libffi-3.0.4 of the work I did on
GCC-4.2.0 libffi.
It has been tested with the libffi testsuite to have the same results as
libffi for AIX 32bit. It means nested structs and unwind are not
supported:
FAIL: libffi.call/nested_struct4.c execution test
FAIL: libffi.call/nested_struct5.c execution test
FAIL: libffi.call/nested_struct6.c execution test
FAIL: libffi.call/nested_struct4.c execution test
FAIL: libffi.call/nested_struct5.c execution test
FAIL: libffi.call/nested_struct6.c execution test
FAIL: libffi.call/nested_struct4.c execution test
FAIL: libffi.call/nested_struct5.c execution test
FAIL: libffi.call/nested_struct6.c execution test
FAIL: libffi.call/nested_struct4.c execution test
FAIL: libffi.call/nested_struct5.c execution test
FAIL: libffi.call/nested_struct6.c execution test
FAIL: libffi.call/nested_struct4.c execution test
FAIL: libffi.call/nested_struct5.c execution test
FAIL: libffi.call/nested_struct6.c execution test
FAIL: libffi.special/unwindtest.cc execution test
FAIL: libffi.special/unwindtest_ffi_call.cc execution test
FAIL: libffi.special/unwindtest.cc execution test
FAIL: libffi.special/unwindtest_ffi_call.cc execution test
FAIL: libffi.special/unwindtest.cc execution test
FAIL: libffi.special/unwindtest_ffi_call.cc execution test
FAIL: libffi.special/unwindtest.cc execution test
FAIL: libffi.special/unwindtest_ffi_call.cc execution test
=== libffi Summary ===
# of expected passes 1343
# of unexpected failures 23
# of unsupported tests 15
Of course, all comments are welcome,
Laurent
--
------------- Laurent.Vivier@bull.net --------------
"Software is hard" - Donald Knuth
Index: libffi-3.0.4-aix/src/powerpc/aix.S
===================================================================
--- libffi-3.0.4-aix.orig/src/powerpc/aix.S 2008-03-12 17:49:31.-1561489208 +0100
+++ libffi-3.0.4-aix/src/powerpc/aix.S 2008-03-12 18:00:18.-74312552 +0100
@@ -88,10 +88,140 @@
.toc
.csect .text[PR]
.align 2
-.globl ffi_prep_args
.csect .text[PR]
.align 2
+#ifdef __64BIT__
+ /* void ffi_call_AIX(extended_cif *ecif, unsigned long bytes,
+ * unsigned int flags, unsigned int *rvalue,
+ * void (*fn)(),
+ * void (*prep_args)(extended_cif*, unsigned *const));
+ * r3=ecif, r4=bytes, r5=flags, r6=rvalue, r7=fn, r8=prep_args
+ */
+
+ .globl ffi_call_AIX
+ .globl .ffi_call_AIX
+.csect ffi_call_AIX[DS]
+ffi_call_AIX:
+ .llong .ffi_call_AIX, TOC[tc0], 0
+ .csect .text[PR]
+.ffi_call_AIX:
+ // We only need r12 until the call, so it doesn't have to be saved...
+
+ mr r12,r8 /* r8 is prep_args() */
+
+ /* Save the old stack pointer as AP. */
+
+ mr r8,r1
+
+ /* Allocate the stack space we need. */
+
+ stdux r1,r1,r4 /* r4 is -cif->bytes */
+
+ /* Save registers we use. */
+
+ mflr r9 /* r9 becomes return address */
+
+ std r28,-32(r8)
+ std r29,-24(r8)
+ std r30,-16(r8)
+ std r31, -8(r8)
+
+ std r9, 16(r8) /* save return address */
+ std r2, 40(r1) /* save TOC pointer */
+
+ /* Save arguments over call... */
+ mr r31,r5 /* flags, */
+ mr r30,r6 /* rvalue, */
+ mr r29,r7 /* fn() */
+ mr r28,r8 /* our AP. */
+
+ /* Call ffi_prep_args. */
+ /* r3 is already &ecif */
+ mr r4,r1 /* r4 becomes stack pointer */
+ li r9,0
+
+ ld r2,8(r12) /* TOC of prep_args() */
+ ld r12,0(r12) /* trampoline */
+ mtctr r12 /* r12 holds address of prep_args() */
+ bctrl
+ ld r2,40(r1) /* restore TOC */
+
+ /* Now do the call. */
+
+ ld r12,0(r29) /* r29 is fn(), r12 its trampoline */
+ /* Set up cr1 with bits 4-7 of the flags. */
+ mtcrf 0x40,r31 /* r31 is cif->flags */
+ std r2,40(r1) /* save current TOC */
+ mtctr r12 /* load ctr with fn() pointer */
+ ld r2,8(r29) /* r2 is TOC of fn() */
+ /* Load all those argument registers. */
+ // We have set up a nice stack frame, just load it into registers.
+ ld r3, 40+(1*8)(r1)
+ ld r4, 40+(2*8)(r1)
+ ld r5, 40+(3*8)(r1)
+ ld r6, 40+(4*8)(r1)
+ nop
+ ld r7, 40+(5*8)(r1)
+ ld r8, 40+(6*8)(r1)
+ ld r9, 40+(7*8)(r1)
+ ld r10,40+(8*8)(r1)
+
+L1:
+ /* Load all the FP registers. */
+ bf 6,L2 // 2f + 0x18
+ lfd f1,-32-(13*8)(r28)
+ lfd f2,-32-(12*8)(r28)
+ lfd f3,-32-(11*8)(r28)
+ lfd f4,-32-(10*8)(r28)
+ nop
+ lfd f5,-32-(9*8)(r28)
+ lfd f6,-32-(8*8)(r28)
+ lfd f7,-32-(7*8)(r28)
+ lfd f8,-32-(6*8)(r28)
+ nop
+ lfd f9,-32-(5*8)(r28)
+ lfd f10,-32-(4*8)(r28)
+ lfd f11,-32-(3*8)(r28)
+ lfd f12,-32-(2*8)(r28)
+ nop
+ lfd f13,-32-(1*8)(r28)
+
+L2:
+ /* Make the call. */
+ bctrl
+ ld r2,40(r1) /* restore TOC */
+
+ /* Now, deal with the return value. */
+ mtcrf 0x1,r31
+
+ bt 30,L(done_return_value)
+ bt 29,L(fp_return_value)
+ std r3,0(r30)
+
+ /* Fall through... */
+
+L(done_return_value):
+ /* Restore the registers we used and return. */
+ ld r9, 16(r28)
+ ld r31, -8(r28)
+ mtlr r9
+ ld r30, -16(r28)
+ ld r29,-24(r28)
+ ld r28,-32(r28)
+ ld r1,0(r1)
+ blr
+
+L(fp_return_value):
+ bf 28,L(float_return_value)
+ stfd f1,0(r30)
+ b L(done_return_value)
+L(float_return_value):
+ stfs f1,0(r30)
+ b L(done_return_value)
+ .long 0
+ .byte 0,0,0,1,128,4,0,0
+#else /* ! __64BIT__ */
.globl ffi_call_AIX
.globl .ffi_call_AIX
.csect ffi_call_AIX[DS]
@@ -208,6 +338,7 @@
b L(done_return_value)
.long 0
.byte 0,0,0,1,128,4,0,0
+#endif /* ! __64BIT__ */
//END(ffi_call_AIX)
.csect .text[PR]
@@ -216,7 +347,11 @@
.globl .ffi_call_DARWIN
.csect ffi_call_DARWIN[DS]
ffi_call_DARWIN:
+#ifdef __64BIT__
+ .llong .ffi_call_DARWIN, TOC[tc0], 0
+#else
.long .ffi_call_DARWIN, TOC[tc0], 0
+#endif
.csect .text[PR]
.ffi_call_DARWIN:
blr
Index: libffi-3.0.4-aix/src/powerpc/aix_closure.S
===================================================================
--- libffi-3.0.4-aix.orig/src/powerpc/aix_closure.S 2008-03-12 17:49:31.1257795608 +0100
+++ libffi-3.0.4-aix/src/powerpc/aix_closure.S 2008-03-12 18:00:18.-1546150032 +0100
@@ -91,6 +91,174 @@
.csect .text[PR]
.align 2
+#ifdef __64BIT__
+ .globl ffi_closure_ASM
+ .globl .ffi_closure_ASM
+.csect ffi_closure_ASM[DS]
+
+
+ffi_closure_ASM:
+ .llong .ffi_closure_ASM, TOC[tc0], 0
+ .csect .text[PR]
+.ffi_closure_ASM:
+
+ mflr r0 /* extract return address */
+ std r0, 16(r1) /* save the return address */
+
+ /* 48 Bytes (Linkage Area) */
+ /* 64 Bytes (output params 8*8) */
+ /* 104 Bytes (13*8 from FPR) */
+ /* 32 Bytes (result) */
+ /* 248 Bytes */
+
+ stdu r1,-248(r1) /* skip over caller save area */
+
+ /* we want to build up an area for the parameters passed
+ * in registers (both floating point and integer) */
+
+ /* 256 bytes (callee stack frame aligned to 32
+ * 48 bytes (caller linkage area)
+ * 304 (start of caller parameter aligned to 8
+ */
+
+
+ /* we store gpr 3 to gpr 10 in the parents outgoing area */
+
+ std r3, (248+48+0*8)(r1)
+ std r4, (248+48+1*8)(r1)
+ std r5, (248+48+2*8)(r1)
+ std r6, (248+48+3*8)(r1)
+ std r7, (248+48+4*8)(r1)
+ std r8, (248+48+5*8)(r1)
+ std r9, (248+48+6*8)(r1)
+ std r10, (248+48+7*8)(r1)
+
+ /* next save fpr 1 to fpr 13 */
+
+ stfd f1, (112+0*8)(r1)
+ stfd f2, (112+1*8)(r1)
+ stfd f3, (112+2*8)(r1)
+ stfd f4, (112+3*8)(r1)
+ stfd f5, (112+4*8)(r1)
+ stfd f6, (112+5*8)(r1)
+ stfd f7, (112+6*8)(r1)
+ stfd f8, (112+7*8)(r1)
+ stfd f9, (112+8*8)(r1)
+ stfd f10, (112+9*8)(r1)
+ stfd f11, (112+10*8)(r1)
+ stfd f12, (112+11*8)(r1)
+ stfd f13, (112+12*8)(r1)
+
+ /* set up registers for the routine that actually does the work
+ * get the context pointer from the trampoline
+ */
+ mr r3,r11
+
+ /* now load up the pointer to the result storage
+ * current stack frame size - ((8 * 4) + saved registers)
+ */
+ addi r4,r1,216
+
+ /* now load up the pointer to the saved gpr registers */
+ addi r5,r1,248+48
+
+ /* now load up the pointer to the saved fpr registers */
+ addi r6,r1,112
+
+ /* make the call
+ * int ffi_closure_helper_DARWIN (ffi_closure* closure, void * rvalue,
+ * unsigned long * pgr, ffi_dblfl * pfr)
+ */
+
+ bl .ffi_closure_helper_DARWIN
+ nop
+
+ /* now r3 contains the return type */
+ /* so use it to look up in a table */
+ /* so we know how to deal with each type */
+
+ /* look up the proper starting point in table */
+ /* by using return type as offset */
+ addi r5,r1,216 /* get pointer to results area */
+ ld r4,LC..60(r2) /* get address of jump table */
+ sldi r3,r3,2 /* now multiply return type by 4 */
+ lwzx r3,r4,r3 /* get the contents of that table value */
+ add r3,r3,r4 /* add contents of table to table address */
+ mtctr r3
+ bctr /* jump to it */
+
+L..60:
+ .long L..44-L..60 /* FFI_TYPE_VOID */
+ .long L..50-L..60 /* FFI_TYPE_INT */
+ .long L..47-L..60 /* FFI_TYPE_FLOAT */
+ .long L..46-L..60 /* FFI_TYPE_DOUBLE */
+ .long L..62-L..60 /* FFI_TYPE_LONGDOUBLE */
+ .long L..56-L..60 /* FFI_TYPE_UINT8 */
+ .long L..55-L..60 /* FFI_TYPE_SINT8 */
+ .long L..58-L..60 /* FFI_TYPE_UINT16 */
+ .long L..57-L..60 /* FFI_TYPE_SINT16 */
+ .long L..50-L..60 /* FFI_TYPE_UINT32 */
+ .long L..50-L..60 /* FFI_TYPE_SINT32 */
+ .long L..48-L..60 /* FFI_TYPE_UINT64 */
+ .long L..48-L..60 /* FFI_TYPE_SINT64 */
+ .long L..44-L..60 /* FFI_TYPE_STRUCT */
+ .long L..48-L..60 /* FFI_TYPE_POINTER */
+
+
+/* case double */
+L..46:
+ lfd f1,0(r5)
+ b L..44
+
+/* case long double */
+L..62:
+ lfd f1,0(r5)
+ lfd f2,8(r5)
+ b L..44
+
+/* case float */
+L..47:
+ lfs f1,0(r5)
+ b L..44
+
+/* case long long */
+L..48:
+ ld r3,0(r5)
+ b L..44
+
+/* case int / int32 / uint32*/
+L..50:
+ lwz r3,4(r5)
+ b L..44
+
+/* case signed int8 */
+L..55:
+ lbz r3,7(r5)
+ extsb r3,r3
+ b L..44
+
+/* case unsigned int8 */
+L..56:
+ lbz r3,7(r5)
+ b L..44
+
+/* case signed int16 */
+L..57:
+ lha r3,6(r5)
+ b L..44
+
+/* case unsigned int16 */
+L..58:
+ lhz r3,6(r5)
+ b L..44
+
+/* case void / done */
+L..44:
+ addi r1,r1,248 /* restore stack pointer */
+ ld r0,16(r1) /* get return address */
+ mtlr r0 /* reset link register */
+ blr
+#else /* ! __64BIT__ */
.globl ffi_closure_ASM
.globl .ffi_closure_ASM
.csect ffi_closure_ASM[DS]
@@ -106,8 +274,8 @@
/* 24 Bytes (Linkage Area) */
/* 32 Bytes (params) */
/* 104 Bytes (13*8 from FPR) */
- /* 8 Bytes (result) */
- /* 168 Bytes */
+ /* 16 Bytes (result) */
+ /* 176 Bytes */
stwu r1,-176(r1) /* skip over caller save area
keep stack aligned to 16 */
@@ -243,5 +411,6 @@
lwz r0,8(r1) /* get return address */
mtlr r0 /* reset link register */
blr
+#endif /* __64BIT__ */
/* END(ffi_closure_ASM) */
Index: libffi-3.0.4-aix/src/powerpc/ffi_darwin.c
===================================================================
--- libffi-3.0.4-aix.orig/src/powerpc/ffi_darwin.c 2008-03-12 17:49:31.-217140872 +0100
+++ libffi-3.0.4-aix/src/powerpc/ffi_darwin.c 2008-03-12 18:00:18.1272677784 +0100
@@ -80,34 +80,37 @@
*/
-void ffi_prep_args(extended_cif *ecif, unsigned *const stack)
+void ffi_prep_args(extended_cif *ecif, unsigned long *const stack)
{
const unsigned bytes = ecif->cif->bytes;
const unsigned flags = ecif->cif->flags;
/* 'stacktop' points at the previous backchain pointer. */
- unsigned *const stacktop = stack + (bytes / sizeof(unsigned));
+ unsigned long *const stacktop = stack + (bytes / sizeof(unsigned long));
/* 'fpr_base' points at the space for fpr1, and grows upwards as
we use FPR registers. */
- double *fpr_base = (double*) (stacktop - ASM_NEEDS_REGISTERS) - NUM_FPR_ARG_REGISTERS;
+ double *fpr_base = (double*) (stacktop - ASM_NEEDS_REGISTERS) -
+ NUM_FPR_ARG_REGISTERS;
int fparg_count = 0;
/* 'next_arg' grows up as we put parameters in it. */
- unsigned *next_arg = stack + 6; /* 6 reserved positions. */
+ unsigned long *next_arg = stack + 6; /* 6 reserved positions. */
int i = ecif->cif->nargs;
+ ffi_abi abi = ecif->cif->abi;
double double_tmp;
void **p_argv = ecif->avalue;
- unsigned gprvalue;
+ unsigned long gprvalue;
ffi_type** ptr = ecif->cif->arg_types;
char *dest_cpy;
unsigned size_al = 0;
+
/* Check that everything starts aligned properly. */
- FFI_ASSERT(((unsigned)(char *)stack & 0xF) == 0);
- FFI_ASSERT(((unsigned)(char *)stacktop & 0xF) == 0);
+ FFI_ASSERT(((unsigned long)(char *)stack & 0xF) == 0);
+ FFI_ASSERT(((unsigned long)(char *)stacktop & 0xF) == 0);
FFI_ASSERT((bytes & 0xF) == 0);
/* Deal with return values that are actually pass-by-reference.
@@ -115,12 +118,10 @@
Return values are referenced by r3, so r4 is the first parameter. */
if (flags & FLAG_RETVAL_REFERENCE)
- *next_arg++ = (unsigned)(char *)ecif->rvalue;
+ *next_arg++ = (unsigned long)(char *)ecif->rvalue;/* this overwrites ecif */
/* Now for the arguments. */
- for (;
- i > 0;
- i--, ptr++, p_argv++)
+ for (; i > 0; i--, ptr++, p_argv++)
{
switch ((*ptr)->type)
{
@@ -140,11 +141,14 @@
case FFI_TYPE_DOUBLE:
double_tmp = *(double *)*p_argv;
- if (fparg_count >= NUM_FPR_ARG_REGISTERS)
- *(double *)next_arg = double_tmp;
- else
+ if (fparg_count < NUM_FPR_ARG_REGISTERS)
*fpr_base++ = double_tmp;
+ *(double *)next_arg = double_tmp;
+#if defined(POWERPC64)
+ next_arg++;
+#else
next_arg += 2;
+#endif
fparg_count++;
FFI_ASSERT(flags & FLAG_FP_ARGUMENTS);
break;
@@ -152,28 +156,45 @@
#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
case FFI_TYPE_LONGDOUBLE:
- double_tmp = ((double *)*p_argv)[0];
- if (fparg_count >= NUM_FPR_ARG_REGISTERS)
- *(double *)next_arg = double_tmp;
- else
- *fpr_base++ = double_tmp;
+#ifdef POWERPC64
+ if (fparg_count < NUM_FPR_ARG_REGISTERS) {
+ *(long double*)fpr_base = *(long double*)*p_argv;
+ fpr_base += 2;
+ } else
+ *(long double *)next_arg = *(long double*)*p_argv;
next_arg += 2;
- fparg_count++;
- double_tmp = ((double *)*p_argv)[1];
- if (fparg_count >= NUM_FPR_ARG_REGISTERS)
- *(double *)next_arg = double_tmp;
+ fparg_count += 2;
+#else
+ double_tmp = *(double *)*p_argv;
+ if (fparg_count < NUM_FPR_ARG_REGISTERS)
+ *fpr_base++ = double_tmp;
else
+ *(double *)next_arg = double_tmp;
+
+ double_tmp = ((double *)*p_argv)[1];
+ if (fparg_count < NUM_FPR_ARG_REGISTERS)
*fpr_base++ = double_tmp;
- next_arg += 2;
- fparg_count++;
+ else
+ *(double *)next_arg = double_tmp;
+ next_arg += 4;
+ fparg_count += 2;
+#endif
FFI_ASSERT(flags & FLAG_FP_ARGUMENTS);
break;
#endif
case FFI_TYPE_UINT64:
case FFI_TYPE_SINT64:
+#ifdef POWERPC64
+ gprvalue = *(long long *)*p_argv;
+ goto putgpr;
+#else
*(long long *)next_arg = *(long long *)*p_argv;
next_arg+=2;
+#endif
break;
+ case FFI_TYPE_POINTER:
+ gprvalue = *(unsigned long *)*p_argv;
+ goto putgpr;
case FFI_TYPE_UINT8:
gprvalue = *(unsigned char *)*p_argv;
goto putgpr;
@@ -188,6 +209,17 @@
goto putgpr;
case FFI_TYPE_STRUCT:
+#ifdef POWERPC64
+ dest_cpy = (char *) next_arg;
+ size_al = (*ptr)->size;
+ if ((*ptr)->elements[0]->type == 3)
+ size_al = ALIGN((*ptr)->size, 8);
+ if (size_al < 3 && abi == FFI_DARWIN)
+ dest_cpy += 4 - size_al;
+
+ memcpy((char *)dest_cpy, (char *)*p_argv, size_al);
+ next_arg += (size_al + 7) / 8;
+#else
dest_cpy = (char *) next_arg;
/* Structures that match the basic modes (QI 1 byte, HI 2 bytes,
@@ -199,17 +231,17 @@
Type 3 is defined in include/ffi.h. #define FFI_TYPE_DOUBLE 3. */
if ((*ptr)->elements[0]->type == 3)
size_al = ALIGN((*ptr)->size, 8);
- if (size_al < 3 && ecif->cif->abi == FFI_DARWIN)
+ if (size_al < 3 && abi == FFI_DARWIN)
dest_cpy += 4 - size_al;
memcpy((char *)dest_cpy, (char *)*p_argv, size_al);
next_arg += (size_al + 3) / 4;
+#endif
break;
case FFI_TYPE_INT:
case FFI_TYPE_UINT32:
case FFI_TYPE_SINT32:
- case FFI_TYPE_POINTER:
gprvalue = *(unsigned *)*p_argv;
putgpr:
*next_arg++ = gprvalue;
@@ -220,10 +252,10 @@
}
/* Check that we didn't overrun the stack... */
- //FFI_ASSERT(gpr_base <= stacktop - ASM_NEEDS_REGISTERS);
- //FFI_ASSERT((unsigned *)fpr_base
- // <= stacktop - ASM_NEEDS_REGISTERS - NUM_GPR_ARG_REGISTERS);
- //FFI_ASSERT(flags & FLAG_4_GPR_ARGUMENTS || intarg_count <= 4);
+ FFI_ASSERT(gpr_base <= stacktop - ASM_NEEDS_REGISTERS);
+ FFI_ASSERT((unsigned long*)fpr_base
+ <= stacktop - ASM_NEEDS_REGISTERS - NUM_GPR_ARG_REGISTERS);
+ FFI_ASSERT(flags & FLAG_4_GPR_ARGUMENTS || intarg_count <= 4);
}
/* Adjust the size of S to be correct for Darwin.
@@ -278,7 +310,6 @@
int fparg_count = 0, intarg_count = 0;
unsigned flags = 0;
unsigned size_al = 0;
-
/* All the machine-independent calculation of cif->bytes will be wrong.
All the calculation of structure sizes will also be wrong.
Redo the calculation for DARWIN. */
@@ -322,6 +353,9 @@
flags |= FLAG_RETURNS_FP;
break;
+#ifdef POWERPC64
+ case FFI_TYPE_POINTER:
+#endif
case FFI_TYPE_UINT64:
case FFI_TYPE_SINT64:
flags |= FLAG_RETURNS_64BITS;
@@ -391,7 +425,11 @@
Type 3 is defined in include/ffi.h. #define FFI_TYPE_DOUBLE 3. */
if ((*ptr)->elements[0]->type == 3)
size_al = ALIGN((*ptr)->size, 8);
+#ifdef POWERPC64
+ intarg_count += (size_al + 7) / 8;
+#else
intarg_count += (size_al + 3) / 4;
+#endif
break;
default:
@@ -410,13 +448,22 @@
bytes += NUM_FPR_ARG_REGISTERS * sizeof(double);
/* Stack space. */
+#ifdef POWERPC64
+ if ((intarg_count + fparg_count) > NUM_GPR_ARG_REGISTERS)
+ bytes += (intarg_count + fparg_count) * sizeof(long);
+#else
if ((intarg_count + 2 * fparg_count) > NUM_GPR_ARG_REGISTERS)
bytes += (intarg_count + 2 * fparg_count) * sizeof(long);
+#endif
else
bytes += NUM_GPR_ARG_REGISTERS * sizeof(long);
/* The stack space allocated needs to be a multiple of 16 bytes. */
+#ifdef POWERPC64
+ bytes = (bytes + 31) & ~0x1F;
+#else
bytes = (bytes + 15) & ~0xF;
+#endif
cif->flags = flags;
cif->bytes = bytes;
@@ -424,10 +471,10 @@
return FFI_OK;
}
-extern void ffi_call_AIX(extended_cif *, unsigned, unsigned, unsigned *,
- void (*fn)(), void (*fn2)());
-extern void ffi_call_DARWIN(extended_cif *, unsigned, unsigned, unsigned *,
- void (*fn)(), void (*fn2)());
+extern void ffi_call_AIX(extended_cif *, unsigned long, unsigned, unsigned *,
+ void (*fn)(), void (*fn2)(extended_cif*, unsigned long *const));
+extern void ffi_call_DARWIN(extended_cif *, unsigned long, unsigned, unsigned *,
+ void (*fn)(), void (*fn2)(extended_cif*, unsigned long *const));
void ffi_call(ffi_cif *cif, void (*fn)(), void *rvalue, void **avalue)
{
@@ -450,11 +497,11 @@
switch (cif->abi)
{
case FFI_AIX:
- ffi_call_AIX(&ecif, -cif->bytes, cif->flags, ecif.rvalue, fn,
+ ffi_call_AIX(&ecif, -(long)cif->bytes, cif->flags, ecif.rvalue, fn,
ffi_prep_args);
break;
case FFI_DARWIN:
- ffi_call_DARWIN(&ecif, -cif->bytes, cif->flags, ecif.rvalue, fn,
+ ffi_call_DARWIN(&ecif, -(long)cif->bytes, cif->flags, ecif.rvalue, fn,
ffi_prep_args);
break;
default:
@@ -650,7 +697,6 @@
ffi_cif * cif;
double temp;
unsigned size_al;
- union ldu temp_ld;
cif = closure->cif;
avalue = alloca(cif->nargs * sizeof(void *));
@@ -678,34 +724,56 @@
{
case FFI_TYPE_SINT8:
case FFI_TYPE_UINT8:
+#ifdef POWERPC64
+ avalue[i] = (char *) pgr + 7;
+#else
avalue[i] = (char *) pgr + 3;
+#endif
ng++;
pgr++;
break;
case FFI_TYPE_SINT16:
case FFI_TYPE_UINT16:
+#ifdef POWERPC64
+ avalue[i] = (char *) pgr + 6;
+#else
avalue[i] = (char *) pgr + 2;
+#endif
ng++;
pgr++;
break;
case FFI_TYPE_SINT32:
case FFI_TYPE_UINT32:
+#ifdef POWERPC64
+ avalue[i] = (char*)pgr + 4;
+#else
case FFI_TYPE_POINTER:
avalue[i] = pgr;
+#endif
ng++;
pgr++;
break;
case FFI_TYPE_STRUCT:
+#ifdef POWERPC64
+ size_al = arg_types[i]->size;
+ if (arg_types[i]->elements[0]->type == FFI_TYPE_DOUBLE)
+ size_al = ALIGN(arg_types[i]->size, 8);
+ if (size_al < 3 && cif->abi == FFI_DARWIN)
+ avalue[i] = (void*) pgr + 8 - size_al;
+ else
+ avalue[i] = (void*) pgr;
+ ng += (size_al + 7) / 8;
+ pgr += (size_al + 7) / 8;
+#else
/* Structures that match the basic modes (QI 1 byte, HI 2 bytes,
SI 4 bytes) are aligned as if they were those modes. */
size_al = arg_types[i]->size;
/* If the first member of the struct is a double, then align
- the struct to double-word.
- Type 3 is defined in include/ffi.h. #define FFI_TYPE_DOUBLE 3. */
- if (arg_types[i]->elements[0]->type == 3)
+ the struct to double-word. */
+ if (arg_types[i]->elements[0]->type == FFI_TYPE_DOUBLE)
size_al = ALIGN(arg_types[i]->size, 8);
if (size_al < 3 && cif->abi == FFI_DARWIN)
avalue[i] = (void*) pgr + 4 - size_al;
@@ -713,15 +781,24 @@
avalue[i] = (void*) pgr;
ng += (size_al + 3) / 4;
pgr += (size_al + 3) / 4;
+#endif
break;
case FFI_TYPE_SINT64:
case FFI_TYPE_UINT64:
+#ifdef POWERPC64
+ case FFI_TYPE_POINTER:
+ avalue[i] = pgr;
+ ng += 1;
+ pgr += 1;
+ break;
+#else
/* Long long ints are passed in two gpr's. */
avalue[i] = pgr;
ng += 2;
pgr += 2;
break;
+#endif
case FFI_TYPE_FLOAT:
/* A float value consumes a GPR.
@@ -743,7 +820,7 @@
break;
case FFI_TYPE_DOUBLE:
- /* A double value consumes two GPRs.
+ /* A double value consumes one or two GPRs.
There are 13 64bit floating point registers. */
if (nf < NUM_FPR_ARG_REGISTERS)
{
@@ -755,8 +832,13 @@
avalue[i] = pgr;
}
nf++;
+#if defined (POWERPC64)
+ ng++;
+ pgr++;
+#else
ng += 2;
pgr += 2;
+#endif
break;
#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
@@ -774,6 +856,7 @@
We use a union to pass the long double to avalue[i]. */
else if (nf == NUM_FPR_ARG_REGISTERS - 1)
{
+ union ldu temp_ld;
memcpy (&temp_ld.lb[0], pfr, sizeof(ldbits));
memcpy (&temp_ld.lb[1], pgr + 2, sizeof(ldbits));
avalue[i] = &temp_ld.ld;
Index: libffi-3.0.4-aix/src/powerpc/ffitarget.h
===================================================================
--- libffi-3.0.4-aix.orig/src/powerpc/ffitarget.h 2008-03-12 17:49:31.1127593464 +0100
+++ libffi-3.0.4-aix/src/powerpc/ffitarget.h 2008-03-12 18:00:18.-203747696 +0100
@@ -30,7 +30,11 @@
/* ---- System specific configurations ----------------------------------- */
-#if defined (POWERPC) && defined (__powerpc64__)
+#if defined (POWERPC) && defined (__powerpc64__) /* linux64 */
+#define POWERPC64
+#elif defined(POWERPC_DARWIN) && defined (__ppc64__) /* Darwin */
+#define POWERPC64
+#elif defined(POWERPC_AIX) && defined (__64BIT__) /* AIX */
#define POWERPC64
#endif