From 6e94d4ca6390ea7cf723eae5516a10a67c5d2587 Mon Sep 17 00:00:00 2001 From: dje Date: Mon, 30 Nov 2009 23:34:33 +0000 Subject: [PATCH] 2009-11-30 David Edelsohn 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 | 14 +++ libffi/src/powerpc/aix.S | 165 ++++++++++++++++++++++++++++----- libffi/src/powerpc/aix_closure.S | 192 +++++++++++++++++++++++++++++++++++---- libffi/src/powerpc/ffi_darwin.c | 168 ++++++++++++++++++++++++++-------- libffi/src/powerpc/ffitarget.h | 6 +- 5 files changed, 468 insertions(+), 77 deletions(-) diff --git a/libffi/ChangeLog b/libffi/ChangeLog index 651a01e0b6e..c93d0b73574 100644 --- a/libffi/ChangeLog +++ b/libffi/ChangeLog @@ -1,3 +1,17 @@ +2009-11-30 David Edelsohn + + 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 PR libffi/41908 diff --git a/libffi/src/powerpc/aix.S b/libffi/src/powerpc/aix.S index 45502f7963e..7b73999f2a7 100644 --- a/libffi/src/powerpc/aix.S +++ b/libffi/src/powerpc/aix.S @@ -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. @@ -86,9 +86,13 @@ #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 @@ -96,10 +100,124 @@ .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 diff --git a/libffi/src/powerpc/aix_closure.S b/libffi/src/powerpc/aix_closure.S index 7bf5c656063..e1a60b46832 100644 --- a/libffi/src/powerpc/aix_closure.S +++ b/libffi/src/powerpc/aix_closure.S @@ -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) */ diff --git a/libffi/src/powerpc/ffi_darwin.c b/libffi/src/powerpc/ffi_darwin.c index 501035d75d0..fd2a3710434 100644 --- a/libffi/src/powerpc/ffi_darwin.c +++ b/libffi/src/powerpc/ffi_darwin.c @@ -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: diff --git a/libffi/src/powerpc/ffitarget.h b/libffi/src/powerpc/ffitarget.h index 269f573987c..b4f992e6df4 100644 --- a/libffi/src/powerpc/ffitarget.h +++ b/libffi/src/powerpc/ffitarget.h @@ -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__) /* AIX64 */ #define POWERPC64 #endif -- 2.11.0