This is the mail archive of the libffi-discuss@sourceware.org mailing list for the libffi 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] 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
 

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