OSDN Git Service

2009-11-30 David Edelsohn <edelsohn@gnu.org>
authordje <dje@138bc75d-0d04-0410-961f-82ee72b054a4>
Mon, 30 Nov 2009 23:34:33 +0000 (23:34 +0000)
committerdje <dje@138bc75d-0d04-0410-961f-82ee72b054a4>
Mon, 30 Nov 2009 23:34:33 +0000 (23:34 +0000)
        PR target/35484
        * src/powerpc/ffitarget.h (POWERPC64): Define for PPC64 Linux and
        AIX64.
        * src/powerpc/aix.S: Implement AIX64 version.
        * src/powerpc/aix_closure.S: Implement AIX64 version.
        (ffi_closure_ASM): Use extsb, lha and displament addresses.
        * src/powerpc/ffi_darwin.c (ffi_prep_args): Implement AIX64
        support.
        (ffi_prep_cif_machdep): Same.
        (ffi_call): Same.
        (ffi_closure_helper_DARWIN): Same.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@154855 138bc75d-0d04-0410-961f-82ee72b054a4

libffi/ChangeLog
libffi/src/powerpc/aix.S
libffi/src/powerpc/aix_closure.S
libffi/src/powerpc/ffi_darwin.c
libffi/src/powerpc/ffitarget.h

index 651a01e..c93d0b7 100644 (file)
@@ -1,3 +1,17 @@
+2009-11-30  David Edelsohn  <edelsohn@gnu.org>
+
+       PR target/35484
+       * src/powerpc/ffitarget.h (POWERPC64): Define for PPC64 Linux and
+       AIX64.
+       * src/powerpc/aix.S: Implement AIX64 version.
+       * src/powerpc/aix_closure.S: Implement AIX64 version.
+       (ffi_closure_ASM): Use extsb, lha and displament addresses.
+       * src/powerpc/ffi_darwin.c (ffi_prep_args): Implement AIX64
+       support.
+       (ffi_prep_cif_machdep): Same.
+       (ffi_call): Same.
+       (ffi_closure_helper_DARWIN): Same.
+
 2009-11-02  Andreas Tobler  <a.tobler@schweiz.org>
 
        PR libffi/41908
index 45502f7..7b73999 100644 (file)
@@ -1,5 +1,5 @@
 /* -----------------------------------------------------------------------
-   aix.S - Copyright (c) 2002 Free Software Foundation, Inc.
+   aix.S - Copyright (c) 2002,2009 Free Software Foundation, Inc.
    based on darwin.S by John Hornkvist
 
    PowerPC Assembly glue.
 #define L(x) x
        .file "aix.S"
        .toc
-       .csect .text[PR]
-       .align 2
-.globl ffi_prep_args
+
+       /* 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
+        */
 
 .csect .text[PR]
        .align 2
        .globl .ffi_call_AIX
 .csect ffi_call_AIX[DS]
 ffi_call_AIX:
+#ifdef __64BIT__
+       .llong .ffi_call_AIX, TOC[tc0], 0
+       .csect .text[PR]
+.ffi_call_AIX:
+       mr      r12,r8 // We only need r12 until the call, so it doesn't have to be saved...
+       /* Save the old stack pointer as AP.  */
+       mr      r8,r1
+
+       /* Allocate the stack space we need.  */
+       stdux   r1,r1,r4
+
+       /* Save registers we use.  */
+       mflr    r9
+
+       std     r28,-32(r8)
+       std     r29,-24(r8)
+       std     r30,-16(r8)
+       std     r31, -8(r8)
+
+       std     r9, 16(r8)
+       std     r2, 40(r1)
+
+       /* Save arguments over call...  */
+       mr      r31,r5  /* flags, */
+       mr      r30,r6  /* rvalue, */
+       mr      r29,r7  /* function address, */
+       mr      r28,r8  /* our AP. */
+
+       /* Call ffi_prep_args.  */
+       mr      r4,r1
+       li      r9,0
+
+       ld      r2,8(r12)
+       ld      r12,0(r12)
+       mtctr   r12 // r12 holds address of _ffi_prep_args
+       bctrl
+       ld      r2,40(r1)
+
+       /* Now do the call.  */
+       ld      r12,0(r29)
+       /* Set up cr1 with bits 4-7 of the flags.  */
+       mtcrf   0x40,r31
+       std     r2,40(r1)
+       mtctr   r12
+       ld      r2,8(r29)
+       /* 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)
+
+       /* Now, deal with the return value.  */
+       mtcrf   0x01,r31
+
+       bt      30,L(done_return_value)
+       bt      29,L(fp_return_value)
+       std     r3,0(r30)
+       bf      28,L(done_return_value)
+       std     r4,4(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)
+
+#else /* ! __64BIT__ */
+       
        .long .ffi_call_AIX, TOC[tc0], 0
        .csect .text[PR]
 .ffi_call_AIX:
-       mr      r12,r8 // We only need r12 until the call, so it doesn't have to be saved...
+       mr      r12,r8 // We only need r12 until the call, so it doesn't have to be saved...
        /* Save the old stack pointer as AP.  */
        mr      r8,r1
 
@@ -142,15 +260,15 @@ ffi_call_AIX:
        lwz     r2,4(r29)
        /* Load all those argument registers.  */
        // We have set up a nice stack frame, just load it into registers.
-       lwz     r3, 20+(1*4)(r1)
-       lwz     r4, 20+(2*4)(r1)
-       lwz     r5, 20+(3*4)(r1)
-       lwz     r6, 20+(4*4)(r1)
+       lwz     r3, 20+(1*4)(r1)
+       lwz     r4, 20+(2*4)(r1)
+       lwz     r5, 20+(3*4)(r1)
+       lwz     r6, 20+(4*4)(r1)
        nop
-       lwz     r7, 20+(5*4)(r1)
-       lwz     r8, 20+(6*4)(r1)
-       lwz     r9, 20+(7*4)(r1)
-       lwz     r10,20+(8*4)(r1)
+       lwz     r7, 20+(5*4)(r1)
+       lwz     r8, 20+(6*4)(r1)
+       lwz     r9, 20+(7*4)(r1)
+       lwz     r10,20+(8*4)(r1)
 
 L1:
        /* Load all the FP registers.  */
@@ -165,17 +283,17 @@ L1:
        lfd     f7,-16-(7*8)(r28)
        lfd     f8,-16-(6*8)(r28)
        nop
-       lfd     f9,-16-(5*8)(r28)
-       lfd     f10,-16-(4*8)(r28)
-       lfd     f11,-16-(3*8)(r28)
-       lfd     f12,-16-(2*8)(r28)
+       lfd     f9,-16-(5*8)(r28)
+       lfd     f10,-16-(4*8)(r28)
+       lfd     f11,-16-(3*8)(r28)
+       lfd     f12,-16-(2*8)(r28)
        nop
-       lfd     f13,-16-(1*8)(r28)
+       lfd     f13,-16-(1*8)(r28)
 
 L2:
        /* Make the call.  */
        bctrl
-       lwz r2,20(r1)
+       lwz     r2,20(r1)
 
        /* Now, deal with the return value.  */
        mtcrf   0x01,r31
@@ -190,8 +308,8 @@ L2:
 
 L(done_return_value):
        /* Restore the registers we used and return.  */
-       lwz     r9,   8(r28)
-       lwz     r31,  -4(r28)
+       lwz     r9,8(r28)
+       lwz     r31,-4(r28)
        mtlr    r9
        lwz     r30, -8(r28)
        lwz     r29,-12(r28)
@@ -206,6 +324,7 @@ L(fp_return_value):
 L(float_return_value):
        stfs    f1,0(r30)
        b       L(done_return_value)
+#endif
        .long 0
        .byte 0,0,0,1,128,4,0,0
 //END(ffi_call_AIX)
@@ -216,7 +335,11 @@ L(float_return_value):
        .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 7bf5c65..e1a60b4 100644 (file)
@@ -1,5 +1,5 @@
 /* -----------------------------------------------------------------------
-   aix_closure.S - Copyright (c) 2002 2003 Free Software Foundation, Inc.
+   aix_closure.S - Copyright (c) 2002, 2003, 2009 Free Software Foundation, Inc.
    based on darwin_closure.S
 
    PowerPC Assembly glue.
@@ -94,8 +94,162 @@ LC..60:
        .globl ffi_closure_ASM
        .globl .ffi_closure_ASM
 .csect ffi_closure_ASM[DS]
-
 ffi_closure_ASM:
+#ifdef __64BIT__
+       .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 (params) */
+       /* 104 Bytes (13*8 from FPR) */
+       /* 32  Bytes (result) */
+       /* 248 Bytes */
+
+       stdu r1,-248(r1)        /* skip over caller save area
+                                  keep stack aligned to 16  */
+
+/* we want to build up an area for the parameters passed */
+/* in registers (both floating point and integer) */
+
+       /* we store gpr 3 to gpr 10 (aligned to 4)
+       in the parents outgoing area  */
+       std   r3, (304+0*8)(r1)
+       std   r4, (304+1*8)(r1)
+       std   r5, (304+2*8)(r1)
+       std   r6, (304+3*8)(r1)
+       std   r7, (304+4*8)(r1)
+       std   r8, (304+5*8)(r1)
+       std   r9, (304+6*8)(r1)
+       std   r10, (304+7*8)(r1)
+
+       /* next save fpr 1 to fpr 13 (aligned to 8) */
+       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 */
+       addi r4,r1,216
+
+       /* now load up the pointer to the saved gpr registers */
+       addi r5,r1,304
+
+       /* now load up the pointer to the saved fpr registers */
+       addi r6,r1,112
+
+       /* make the call */
+       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(2)         /* 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..51-L..60    /* FFI_TYPE_INT */
+       .long L..47-L..60    /* FFI_TYPE_FLOAT */
+       .long L..46-L..60    /* FFI_TYPE_DOUBLE */
+       .long L..45-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..51-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 long double */
+L..45:
+       lfd f1,0(r5)
+       lfd f2,8(r5)
+       b L..44
+
+/* case double */
+L..46:
+       lfd f1,0(r5)
+       b L..44
+
+/* case float */
+L..47:
+       lfs f1,0(r5)
+       b L..44
+
+/* case long long / pointer */
+L..48:
+       ld r3,0(r5)
+       b L..44
+
+/* case uint32 */
+L..50:
+       lwz r3,4(r5)
+       b L..44
+
+/* case int / sint32 */
+L..51:
+       lwa 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)
+
+/* 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__ */
+       
        .long .ffi_closure_ASM, TOC[tc0], 0
        .csect .text[PR]
 .ffi_closure_ASM:
@@ -106,8 +260,8 @@ ffi_closure_ASM:
        /* 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  */
@@ -177,7 +331,7 @@ L..60:
        .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..46-L..60    /* FFI_TYPE_LONGDOUBLE */
+       .long L..45-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 */
@@ -190,6 +344,12 @@ L..60:
        .long L..50-L..60    /* FFI_TYPE_POINTER */
 
 
+/* case long double */
+L..45:
+       lfd f1,0(r5)
+       lfd f2,8(r5)
+       b L..44
+
 /* case double */
 L..46:
        lfd f1,0(r5)
@@ -211,31 +371,25 @@ L..50:
        lwz r3,0(r5)
        b L..44
 
-/* case signed int8     */
+/* case signed int8 */
 L..55:
-       addi r5,r5,3
-       lbz r3,0(r5)
-       slwi r3,r3,24
-       srawi r3,r3,24
+       lbz r3,3(r5)
+       extsb r3,r3
        b L..44
 
-/* case unsigned int8   */
+/* case unsigned int8 */
 L..56:
-       addi r5,r5,3
-       lbz r3,0(r5)
+       lbz r3,3(r5)
        b L..44
 
 /* case signed int16 */
 L..57:
-       addi r5,r5,2
-       lhz r3,0(r5)
-       extsh r3,r3
+       lha r3,2(r5)
        b L..44
 
 /* case unsigned int16 */
 L..58:
-       addi r5,r5,2
-       lhz r3,0(r5)
+       lhz r3,2(r5)
 
 /* case void / done     */
 L..44:
@@ -243,5 +397,5 @@ L..44:
        lwz r0,8(r1)            /* get return address */
        mtlr r0                 /* reset link register */
        blr
-
+#endif
 /* END(ffi_closure_ASM) */
index 501035d..fd2a371 100644 (file)
@@ -3,7 +3,7 @@
 
    Copyright (C) 1998 Geoffrey Keating
    Copyright (C) 2001 John Hornkvist
-   Copyright (C) 2002, 2006, 2007 Free Software Foundation, Inc.
+   Copyright (C) 2002, 2006, 2007, 2009 Free Software Foundation, Inc.
 
    FFI support for Darwin and AIX.
    
@@ -80,27 +80,28 @@ enum { ASM_NEEDS_REGISTERS = 4 };
 
    */
 
-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 = (unsigned long *) stack + 6; /* 6 reserved positions.  */
 
-  int i = ecif->cif->nargs;
+  int i;
   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;
@@ -115,12 +116,10 @@ void ffi_prep_args(extended_cif *ecif, unsigned *const stack)
      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;
 
   /* Now for the arguments.  */
-  for (;
-       i > 0;
-       i--, ptr++, p_argv++)
+  for (i = ecif->cif->nargs; i > 0; i--, ptr++, p_argv++)
     {
       switch ((*ptr)->type)
        {
@@ -133,7 +132,11 @@ void ffi_prep_args(extended_cif *ecif, unsigned *const stack)
            *(double *)next_arg = double_tmp;
          else
            *fpr_base++ = double_tmp;
+#ifdef POWERPC64
          next_arg++;
+#else
+         next_arg += 2;
+#endif
          fparg_count++;
          FFI_ASSERT(flags & FLAG_FP_ARGUMENTS);
          break;
@@ -152,42 +155,69 @@ void ffi_prep_args(extended_cif *ecif, unsigned *const stack)
 #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;
+#ifdef POWERPC64
+         if (fparg_count < NUM_FPR_ARG_REGISTERS)
+           *((long double *) fpr_base)++ = *(long double *) *p_argv;
          else
-           *fpr_base++ = double_tmp;
+           *(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;
+         else
+           *(double *) next_arg = double_tmp;
          next_arg += 2;
          fparg_count++;
+#endif
          FFI_ASSERT(flags & FLAG_FP_ARGUMENTS);
          break;
 #endif
        case FFI_TYPE_UINT64:
        case FFI_TYPE_SINT64:
-         *(long long *)next_arg = *(long long *)*p_argv;
+#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;
+         gprvalue = *(unsigned char *) *p_argv;
          goto putgpr;
        case FFI_TYPE_SINT8:
-         gprvalue = *(signed char *)*p_argv;
+         gprvalue = *(signed char *) *p_argv;
          goto putgpr;
        case FFI_TYPE_UINT16:
-         gprvalue = *(unsigned short *)*p_argv;
+         gprvalue = *(unsigned short *) *p_argv;
          goto putgpr;
        case FFI_TYPE_SINT16:
-         gprvalue = *(signed short *)*p_argv;
+         gprvalue = *(signed short *) *p_argv;
          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 && ecif->cif->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,
@@ -204,12 +234,12 @@ void ffi_prep_args(extended_cif *ecif, unsigned *const stack)
 
          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;
@@ -324,6 +354,9 @@ ffi_status ffi_prep_cif_machdep(ffi_cif *cif)
 
     case FFI_TYPE_UINT64:
     case FFI_TYPE_SINT64:
+#ifdef POWERPC64
+    case FFI_TYPE_POINTER:
+#endif
       flags |= FLAG_RETURNS_64BITS;
       break;
 
@@ -387,11 +420,14 @@ ffi_status ffi_prep_cif_machdep(ffi_cif *cif)
        case FFI_TYPE_STRUCT:
          size_al = (*ptr)->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 ((*ptr)->elements[0]->type == 3)
+            the struct to double-word.  */
+         if ((*ptr)->elements[0]->type == FFI_TYPE_DOUBLE)
            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 +446,22 @@ ffi_status ffi_prep_cif_machdep(ffi_cif *cif)
     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,9 +469,9 @@ ffi_status ffi_prep_cif_machdep(ffi_cif *cif)
   return FFI_OK;
 }
 
-extern void ffi_call_AIX(extended_cif *, unsigned, unsigned, unsigned *,
+extern void ffi_call_AIX(extended_cif *, long, unsigned, unsigned *,
                         void (*fn)(void), void (*fn2)(void));
-extern void ffi_call_DARWIN(extended_cif *, unsigned, unsigned, unsigned *,
+extern void ffi_call_DARWIN(extended_cif *, long, unsigned, unsigned *,
                            void (*fn)(void), void (*fn2)(void));
 
 void ffi_call(ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue)
@@ -450,11 +495,11 @@ void ffi_call(ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue)
   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 +695,6 @@ int ffi_closure_helper_DARWIN (ffi_closure* closure, void * rvalue,
   ffi_cif *        cif;
   double           temp;
   unsigned         size_al;
-  union ldu        temp_ld;
 
   cif = closure->cif;
   avalue = alloca(cif->nargs * sizeof(void *));
@@ -678,34 +722,56 @@ int ffi_closure_helper_DARWIN (ffi_closure* closure, void * rvalue,
        {
        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 +779,24 @@ int ffi_closure_helper_DARWIN (ffi_closure* closure, void * rvalue,
            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++;
+         pgr++;
+         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.
@@ -755,13 +830,32 @@ int ffi_closure_helper_DARWIN (ffi_closure* closure, void * rvalue,
              avalue[i] = pgr;
            }
          nf++;
+#ifdef POWERPC64
+         ng++;
+         pgr++;
+#else
          ng += 2;
          pgr += 2;
+#endif
          break;
 
 #if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
 
        case FFI_TYPE_LONGDOUBLE:
+#ifdef POWERPC64
+         if (nf < NUM_FPR_ARG_REGISTERS)
+           {
+             avalue[i] = pfr;
+             pfr += 2;
+           }
+         else
+           {
+             avalue[i] = pgr;
+           }
+         nf += 2;
+         ng += 2;
+         pgr += 2;
+#else  /* POWERPC64 */
          /* A long double value consumes four GPRs and two FPRs.
             There are 13 64bit floating point registers.  */
          if (nf < NUM_FPR_ARG_REGISTERS - 1)
@@ -774,6 +868,7 @@ int ffi_closure_helper_DARWIN (ffi_closure* closure, void * rvalue,
             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;
@@ -785,6 +880,7 @@ int ffi_closure_helper_DARWIN (ffi_closure* closure, void * rvalue,
          nf += 2;
          ng += 4;
          pgr += 4;
+#endif  /* POWERPC64 */
          break;
 #endif
        default:
index 269f573..b4f992e 100644 (file)
 
 /* ---- 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__)     /* AIX64 */
 #define POWERPC64
 #endif