Commit 5751cf6f by David Edelsohn Committed by David Edelsohn

re PR libffi/35484 (libffi doesn't support AIX 64bit)

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.

From-SVN: r154855
parent 17f35e23
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> 2009-11-02 Andreas Tobler <a.tobler@schweiz.org>
PR libffi/41908 PR libffi/41908
......
/* ----------------------------------------------------------------------- /* -----------------------------------------------------------------------
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 based on darwin.S by John Hornkvist
PowerPC Assembly glue. PowerPC Assembly glue.
...@@ -86,9 +86,13 @@ ...@@ -86,9 +86,13 @@
#define L(x) x #define L(x) x
.file "aix.S" .file "aix.S"
.toc .toc
.csect .text[PR]
.align 2 /* void ffi_call_AIX(extended_cif *ecif, unsigned long bytes,
.globl ffi_prep_args * 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] .csect .text[PR]
.align 2 .align 2
...@@ -96,10 +100,124 @@ ...@@ -96,10 +100,124 @@
.globl .ffi_call_AIX .globl .ffi_call_AIX
.csect ffi_call_AIX[DS] .csect ffi_call_AIX[DS]
ffi_call_AIX: 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 .long .ffi_call_AIX, TOC[tc0], 0
.csect .text[PR] .csect .text[PR]
.ffi_call_AIX: .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. */ /* Save the old stack pointer as AP. */
mr r8,r1 mr r8,r1
...@@ -142,15 +260,15 @@ ffi_call_AIX: ...@@ -142,15 +260,15 @@ ffi_call_AIX:
lwz r2,4(r29) lwz r2,4(r29)
/* Load all those argument registers. */ /* Load all those argument registers. */
// We have set up a nice stack frame, just load it into registers. // We have set up a nice stack frame, just load it into registers.
lwz r3, 20+(1*4)(r1) lwz r3, 20+(1*4)(r1)
lwz r4, 20+(2*4)(r1) lwz r4, 20+(2*4)(r1)
lwz r5, 20+(3*4)(r1) lwz r5, 20+(3*4)(r1)
lwz r6, 20+(4*4)(r1) lwz r6, 20+(4*4)(r1)
nop nop
lwz r7, 20+(5*4)(r1) lwz r7, 20+(5*4)(r1)
lwz r8, 20+(6*4)(r1) lwz r8, 20+(6*4)(r1)
lwz r9, 20+(7*4)(r1) lwz r9, 20+(7*4)(r1)
lwz r10,20+(8*4)(r1) lwz r10,20+(8*4)(r1)
L1: L1:
/* Load all the FP registers. */ /* Load all the FP registers. */
...@@ -165,17 +283,17 @@ L1: ...@@ -165,17 +283,17 @@ L1:
lfd f7,-16-(7*8)(r28) lfd f7,-16-(7*8)(r28)
lfd f8,-16-(6*8)(r28) lfd f8,-16-(6*8)(r28)
nop nop
lfd f9,-16-(5*8)(r28) lfd f9,-16-(5*8)(r28)
lfd f10,-16-(4*8)(r28) lfd f10,-16-(4*8)(r28)
lfd f11,-16-(3*8)(r28) lfd f11,-16-(3*8)(r28)
lfd f12,-16-(2*8)(r28) lfd f12,-16-(2*8)(r28)
nop nop
lfd f13,-16-(1*8)(r28) lfd f13,-16-(1*8)(r28)
L2: L2:
/* Make the call. */ /* Make the call. */
bctrl bctrl
lwz r2,20(r1) lwz r2,20(r1)
/* Now, deal with the return value. */ /* Now, deal with the return value. */
mtcrf 0x01,r31 mtcrf 0x01,r31
...@@ -190,8 +308,8 @@ L2: ...@@ -190,8 +308,8 @@ L2:
L(done_return_value): L(done_return_value):
/* Restore the registers we used and return. */ /* Restore the registers we used and return. */
lwz r9, 8(r28) lwz r9,8(r28)
lwz r31, -4(r28) lwz r31,-4(r28)
mtlr r9 mtlr r9
lwz r30, -8(r28) lwz r30, -8(r28)
lwz r29,-12(r28) lwz r29,-12(r28)
...@@ -206,6 +324,7 @@ L(fp_return_value): ...@@ -206,6 +324,7 @@ L(fp_return_value):
L(float_return_value): L(float_return_value):
stfs f1,0(r30) stfs f1,0(r30)
b L(done_return_value) b L(done_return_value)
#endif
.long 0 .long 0
.byte 0,0,0,1,128,4,0,0 .byte 0,0,0,1,128,4,0,0
//END(ffi_call_AIX) //END(ffi_call_AIX)
...@@ -216,7 +335,11 @@ L(float_return_value): ...@@ -216,7 +335,11 @@ L(float_return_value):
.globl .ffi_call_DARWIN .globl .ffi_call_DARWIN
.csect ffi_call_DARWIN[DS] .csect ffi_call_DARWIN[DS]
ffi_call_DARWIN: ffi_call_DARWIN:
#ifdef __64BIT__
.llong .ffi_call_DARWIN, TOC[tc0], 0
#else
.long .ffi_call_DARWIN, TOC[tc0], 0 .long .ffi_call_DARWIN, TOC[tc0], 0
#endif
.csect .text[PR] .csect .text[PR]
.ffi_call_DARWIN: .ffi_call_DARWIN:
blr blr
......
/* ----------------------------------------------------------------------- /* -----------------------------------------------------------------------
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 based on darwin_closure.S
PowerPC Assembly glue. PowerPC Assembly glue.
...@@ -94,8 +94,162 @@ LC..60: ...@@ -94,8 +94,162 @@ LC..60:
.globl ffi_closure_ASM .globl ffi_closure_ASM
.globl .ffi_closure_ASM .globl .ffi_closure_ASM
.csect ffi_closure_ASM[DS] .csect ffi_closure_ASM[DS]
ffi_closure_ASM: 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 .long .ffi_closure_ASM, TOC[tc0], 0
.csect .text[PR] .csect .text[PR]
.ffi_closure_ASM: .ffi_closure_ASM:
...@@ -106,8 +260,8 @@ ffi_closure_ASM: ...@@ -106,8 +260,8 @@ ffi_closure_ASM:
/* 24 Bytes (Linkage Area) */ /* 24 Bytes (Linkage Area) */
/* 32 Bytes (params) */ /* 32 Bytes (params) */
/* 104 Bytes (13*8 from FPR) */ /* 104 Bytes (13*8 from FPR) */
/* 8 Bytes (result) */ /* 16 Bytes (result) */
/* 168 Bytes */ /* 176 Bytes */
stwu r1,-176(r1) /* skip over caller save area stwu r1,-176(r1) /* skip over caller save area
keep stack aligned to 16 */ keep stack aligned to 16 */
...@@ -177,7 +331,7 @@ L..60: ...@@ -177,7 +331,7 @@ L..60:
.long L..50-L..60 /* FFI_TYPE_INT */ .long L..50-L..60 /* FFI_TYPE_INT */
.long L..47-L..60 /* FFI_TYPE_FLOAT */ .long L..47-L..60 /* FFI_TYPE_FLOAT */
.long L..46-L..60 /* FFI_TYPE_DOUBLE */ .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..56-L..60 /* FFI_TYPE_UINT8 */
.long L..55-L..60 /* FFI_TYPE_SINT8 */ .long L..55-L..60 /* FFI_TYPE_SINT8 */
.long L..58-L..60 /* FFI_TYPE_UINT16 */ .long L..58-L..60 /* FFI_TYPE_UINT16 */
...@@ -190,6 +344,12 @@ L..60: ...@@ -190,6 +344,12 @@ L..60:
.long L..50-L..60 /* FFI_TYPE_POINTER */ .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 */ /* case double */
L..46: L..46:
lfd f1,0(r5) lfd f1,0(r5)
...@@ -211,31 +371,25 @@ L..50: ...@@ -211,31 +371,25 @@ L..50:
lwz r3,0(r5) lwz r3,0(r5)
b L..44 b L..44
/* case signed int8 */ /* case signed int8 */
L..55: L..55:
addi r5,r5,3 lbz r3,3(r5)
lbz r3,0(r5) extsb r3,r3
slwi r3,r3,24
srawi r3,r3,24
b L..44 b L..44
/* case unsigned int8 */ /* case unsigned int8 */
L..56: L..56:
addi r5,r5,3 lbz r3,3(r5)
lbz r3,0(r5)
b L..44 b L..44
/* case signed int16 */ /* case signed int16 */
L..57: L..57:
addi r5,r5,2 lha r3,2(r5)
lhz r3,0(r5)
extsh r3,r3
b L..44 b L..44
/* case unsigned int16 */ /* case unsigned int16 */
L..58: L..58:
addi r5,r5,2 lhz r3,2(r5)
lhz r3,0(r5)
/* case void / done */ /* case void / done */
L..44: L..44:
...@@ -243,5 +397,5 @@ L..44: ...@@ -243,5 +397,5 @@ L..44:
lwz r0,8(r1) /* get return address */ lwz r0,8(r1) /* get return address */
mtlr r0 /* reset link register */ mtlr r0 /* reset link register */
blr blr
#endif
/* END(ffi_closure_ASM) */ /* END(ffi_closure_ASM) */
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
Copyright (C) 1998 Geoffrey Keating Copyright (C) 1998 Geoffrey Keating
Copyright (C) 2001 John Hornkvist 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. FFI support for Darwin and AIX.
...@@ -80,27 +80,28 @@ enum { ASM_NEEDS_REGISTERS = 4 }; ...@@ -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 bytes = ecif->cif->bytes;
const unsigned flags = ecif->cif->flags; const unsigned flags = ecif->cif->flags;
/* 'stacktop' points at the previous backchain pointer. */ /* '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 /* 'fpr_base' points at the space for fpr1, and grows upwards as
we use FPR registers. */ 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; int fparg_count = 0;
/* 'next_arg' grows up as we put parameters in it. */ /* '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; double double_tmp;
void **p_argv = ecif->avalue; void **p_argv = ecif->avalue;
unsigned gprvalue; unsigned long gprvalue;
ffi_type** ptr = ecif->cif->arg_types; ffi_type** ptr = ecif->cif->arg_types;
char *dest_cpy; char *dest_cpy;
unsigned size_al = 0; unsigned size_al = 0;
...@@ -115,12 +116,10 @@ void ffi_prep_args(extended_cif *ecif, unsigned *const stack) ...@@ -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. */ Return values are referenced by r3, so r4 is the first parameter. */
if (flags & FLAG_RETVAL_REFERENCE) if (flags & FLAG_RETVAL_REFERENCE)
*next_arg++ = (unsigned)(char *)ecif->rvalue; *next_arg++ = (unsigned long)(char *)ecif->rvalue;
/* Now for the arguments. */ /* Now for the arguments. */
for (; for (i = ecif->cif->nargs; i > 0; i--, ptr++, p_argv++)
i > 0;
i--, ptr++, p_argv++)
{ {
switch ((*ptr)->type) switch ((*ptr)->type)
{ {
...@@ -133,7 +132,11 @@ void ffi_prep_args(extended_cif *ecif, unsigned *const stack) ...@@ -133,7 +132,11 @@ void ffi_prep_args(extended_cif *ecif, unsigned *const stack)
*(double *)next_arg = double_tmp; *(double *)next_arg = double_tmp;
else else
*fpr_base++ = double_tmp; *fpr_base++ = double_tmp;
#ifdef POWERPC64
next_arg++; next_arg++;
#else
next_arg += 2;
#endif
fparg_count++; fparg_count++;
FFI_ASSERT(flags & FLAG_FP_ARGUMENTS); FFI_ASSERT(flags & FLAG_FP_ARGUMENTS);
break; break;
...@@ -152,42 +155,69 @@ void ffi_prep_args(extended_cif *ecif, unsigned *const stack) ...@@ -152,42 +155,69 @@ void ffi_prep_args(extended_cif *ecif, unsigned *const stack)
#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE #if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
case FFI_TYPE_LONGDOUBLE: case FFI_TYPE_LONGDOUBLE:
double_tmp = ((double *)*p_argv)[0]; #ifdef POWERPC64
if (fparg_count >= NUM_FPR_ARG_REGISTERS) if (fparg_count < NUM_FPR_ARG_REGISTERS)
*(double *)next_arg = double_tmp; *((long double *) fpr_base)++ = *(long double *) *p_argv;
else else
*fpr_base++ = double_tmp; *(long double *) next_arg = *(long double *) *p_argv;
next_arg += 2; next_arg += 2;
fparg_count++; fparg_count += 2;
double_tmp = ((double *)*p_argv)[1]; #else
if (fparg_count >= NUM_FPR_ARG_REGISTERS) double_tmp = *((double *) *p_argv);
*(double *)next_arg = double_tmp; if (fparg_count < NUM_FPR_ARG_REGISTERS)
*fpr_base++ = double_tmp;
else else
*(double *) next_arg = double_tmp;
double_tmp = ((double *) *p_argv)[1];
if (fparg_count < NUM_FPR_ARG_REGISTERS)
*fpr_base++ = double_tmp; *fpr_base++ = double_tmp;
else
*(double *) next_arg = double_tmp;
next_arg += 2; next_arg += 2;
fparg_count++; fparg_count++;
#endif
FFI_ASSERT(flags & FLAG_FP_ARGUMENTS); FFI_ASSERT(flags & FLAG_FP_ARGUMENTS);
break; break;
#endif #endif
case FFI_TYPE_UINT64: case FFI_TYPE_UINT64:
case FFI_TYPE_SINT64: 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; next_arg+=2;
#endif
break; break;
case FFI_TYPE_POINTER:
gprvalue = *(unsigned long *) *p_argv;
goto putgpr;
case FFI_TYPE_UINT8: case FFI_TYPE_UINT8:
gprvalue = *(unsigned char *)*p_argv; gprvalue = *(unsigned char *) *p_argv;
goto putgpr; goto putgpr;
case FFI_TYPE_SINT8: case FFI_TYPE_SINT8:
gprvalue = *(signed char *)*p_argv; gprvalue = *(signed char *) *p_argv;
goto putgpr; goto putgpr;
case FFI_TYPE_UINT16: case FFI_TYPE_UINT16:
gprvalue = *(unsigned short *)*p_argv; gprvalue = *(unsigned short *) *p_argv;
goto putgpr; goto putgpr;
case FFI_TYPE_SINT16: case FFI_TYPE_SINT16:
gprvalue = *(signed short *)*p_argv; gprvalue = *(signed short *) *p_argv;
goto putgpr; goto putgpr;
case FFI_TYPE_STRUCT: 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; dest_cpy = (char *) next_arg;
/* Structures that match the basic modes (QI 1 byte, HI 2 bytes, /* 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) ...@@ -204,12 +234,12 @@ void ffi_prep_args(extended_cif *ecif, unsigned *const stack)
memcpy((char *)dest_cpy, (char *)*p_argv, size_al); memcpy((char *)dest_cpy, (char *)*p_argv, size_al);
next_arg += (size_al + 3) / 4; next_arg += (size_al + 3) / 4;
#endif
break; break;
case FFI_TYPE_INT: case FFI_TYPE_INT:
case FFI_TYPE_UINT32: case FFI_TYPE_UINT32:
case FFI_TYPE_SINT32: case FFI_TYPE_SINT32:
case FFI_TYPE_POINTER:
gprvalue = *(unsigned *)*p_argv; gprvalue = *(unsigned *)*p_argv;
putgpr: putgpr:
*next_arg++ = gprvalue; *next_arg++ = gprvalue;
...@@ -324,6 +354,9 @@ ffi_status ffi_prep_cif_machdep(ffi_cif *cif) ...@@ -324,6 +354,9 @@ ffi_status ffi_prep_cif_machdep(ffi_cif *cif)
case FFI_TYPE_UINT64: case FFI_TYPE_UINT64:
case FFI_TYPE_SINT64: case FFI_TYPE_SINT64:
#ifdef POWERPC64
case FFI_TYPE_POINTER:
#endif
flags |= FLAG_RETURNS_64BITS; flags |= FLAG_RETURNS_64BITS;
break; break;
...@@ -387,11 +420,14 @@ ffi_status ffi_prep_cif_machdep(ffi_cif *cif) ...@@ -387,11 +420,14 @@ ffi_status ffi_prep_cif_machdep(ffi_cif *cif)
case FFI_TYPE_STRUCT: case FFI_TYPE_STRUCT:
size_al = (*ptr)->size; size_al = (*ptr)->size;
/* If the first member of the struct is a double, then align /* If the first member of the struct is a double, then align
the struct to double-word. the struct to double-word. */
Type 3 is defined in include/ffi.h. #define FFI_TYPE_DOUBLE 3. */ if ((*ptr)->elements[0]->type == FFI_TYPE_DOUBLE)
if ((*ptr)->elements[0]->type == 3)
size_al = ALIGN((*ptr)->size, 8); size_al = ALIGN((*ptr)->size, 8);
#ifdef POWERPC64
intarg_count += (size_al + 7) / 8;
#else
intarg_count += (size_al + 3) / 4; intarg_count += (size_al + 3) / 4;
#endif
break; break;
default: default:
...@@ -410,13 +446,22 @@ ffi_status ffi_prep_cif_machdep(ffi_cif *cif) ...@@ -410,13 +446,22 @@ ffi_status ffi_prep_cif_machdep(ffi_cif *cif)
bytes += NUM_FPR_ARG_REGISTERS * sizeof(double); bytes += NUM_FPR_ARG_REGISTERS * sizeof(double);
/* Stack space. */ /* 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) if ((intarg_count + 2 * fparg_count) > NUM_GPR_ARG_REGISTERS)
bytes += (intarg_count + 2 * fparg_count) * sizeof(long); bytes += (intarg_count + 2 * fparg_count) * sizeof(long);
#endif
else else
bytes += NUM_GPR_ARG_REGISTERS * sizeof(long); bytes += NUM_GPR_ARG_REGISTERS * sizeof(long);
/* The stack space allocated needs to be a multiple of 16 bytes. */ /* The stack space allocated needs to be a multiple of 16 bytes. */
#ifdef POWERPC64
bytes = (bytes + 31) & -0x1F;
#else
bytes = (bytes + 15) & ~0xF; bytes = (bytes + 15) & ~0xF;
#endif
cif->flags = flags; cif->flags = flags;
cif->bytes = bytes; cif->bytes = bytes;
...@@ -424,9 +469,9 @@ ffi_status ffi_prep_cif_machdep(ffi_cif *cif) ...@@ -424,9 +469,9 @@ ffi_status ffi_prep_cif_machdep(ffi_cif *cif)
return FFI_OK; 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)); 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 (*fn)(void), void (*fn2)(void));
void ffi_call(ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue) 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) ...@@ -450,11 +495,11 @@ void ffi_call(ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue)
switch (cif->abi) switch (cif->abi)
{ {
case FFI_AIX: 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); ffi_prep_args);
break; break;
case FFI_DARWIN: 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); ffi_prep_args);
break; break;
default: default:
...@@ -650,7 +695,6 @@ int ffi_closure_helper_DARWIN (ffi_closure* closure, void * rvalue, ...@@ -650,7 +695,6 @@ int ffi_closure_helper_DARWIN (ffi_closure* closure, void * rvalue,
ffi_cif * cif; ffi_cif * cif;
double temp; double temp;
unsigned size_al; unsigned size_al;
union ldu temp_ld;
cif = closure->cif; cif = closure->cif;
avalue = alloca(cif->nargs * sizeof(void *)); avalue = alloca(cif->nargs * sizeof(void *));
...@@ -678,34 +722,56 @@ int ffi_closure_helper_DARWIN (ffi_closure* closure, void * rvalue, ...@@ -678,34 +722,56 @@ int ffi_closure_helper_DARWIN (ffi_closure* closure, void * rvalue,
{ {
case FFI_TYPE_SINT8: case FFI_TYPE_SINT8:
case FFI_TYPE_UINT8: case FFI_TYPE_UINT8:
#ifdef POWERPC64
avalue[i] = (char *) pgr + 7;
#else
avalue[i] = (char *) pgr + 3; avalue[i] = (char *) pgr + 3;
#endif
ng++; ng++;
pgr++; pgr++;
break; break;
case FFI_TYPE_SINT16: case FFI_TYPE_SINT16:
case FFI_TYPE_UINT16: case FFI_TYPE_UINT16:
#ifdef POWERPC64
avalue[i] = (char *) pgr + 6;
#else
avalue[i] = (char *) pgr + 2; avalue[i] = (char *) pgr + 2;
#endif
ng++; ng++;
pgr++; pgr++;
break; break;
case FFI_TYPE_SINT32: case FFI_TYPE_SINT32:
case FFI_TYPE_UINT32: case FFI_TYPE_UINT32:
#ifdef POWERPC64
avalue[i] = (char *) pgr + 4;
#else
case FFI_TYPE_POINTER: case FFI_TYPE_POINTER:
avalue[i] = pgr; avalue[i] = pgr;
#endif
ng++; ng++;
pgr++; pgr++;
break; break;
case FFI_TYPE_STRUCT: 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, /* Structures that match the basic modes (QI 1 byte, HI 2 bytes,
SI 4 bytes) are aligned as if they were those modes. */ SI 4 bytes) are aligned as if they were those modes. */
size_al = arg_types[i]->size; size_al = arg_types[i]->size;
/* If the first member of the struct is a double, then align /* If the first member of the struct is a double, then align
the struct to double-word. 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 == FFI_TYPE_DOUBLE)
if (arg_types[i]->elements[0]->type == 3)
size_al = ALIGN(arg_types[i]->size, 8); size_al = ALIGN(arg_types[i]->size, 8);
if (size_al < 3 && cif->abi == FFI_DARWIN) if (size_al < 3 && cif->abi == FFI_DARWIN)
avalue[i] = (void*) pgr + 4 - size_al; avalue[i] = (void*) pgr + 4 - size_al;
...@@ -713,15 +779,24 @@ int ffi_closure_helper_DARWIN (ffi_closure* closure, void * rvalue, ...@@ -713,15 +779,24 @@ int ffi_closure_helper_DARWIN (ffi_closure* closure, void * rvalue,
avalue[i] = (void*) pgr; avalue[i] = (void*) pgr;
ng += (size_al + 3) / 4; ng += (size_al + 3) / 4;
pgr += (size_al + 3) / 4; pgr += (size_al + 3) / 4;
#endif
break; break;
case FFI_TYPE_SINT64: case FFI_TYPE_SINT64:
case FFI_TYPE_UINT64: 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. */ /* Long long ints are passed in two gpr's. */
avalue[i] = pgr; avalue[i] = pgr;
ng += 2; ng += 2;
pgr += 2; pgr += 2;
break; break;
#endif
case FFI_TYPE_FLOAT: case FFI_TYPE_FLOAT:
/* A float value consumes a GPR. /* A float value consumes a GPR.
...@@ -755,13 +830,32 @@ int ffi_closure_helper_DARWIN (ffi_closure* closure, void * rvalue, ...@@ -755,13 +830,32 @@ int ffi_closure_helper_DARWIN (ffi_closure* closure, void * rvalue,
avalue[i] = pgr; avalue[i] = pgr;
} }
nf++; nf++;
#ifdef POWERPC64
ng++;
pgr++;
#else
ng += 2; ng += 2;
pgr += 2; pgr += 2;
#endif
break; break;
#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE #if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
case FFI_TYPE_LONGDOUBLE: 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. /* A long double value consumes four GPRs and two FPRs.
There are 13 64bit floating point registers. */ There are 13 64bit floating point registers. */
if (nf < NUM_FPR_ARG_REGISTERS - 1) if (nf < NUM_FPR_ARG_REGISTERS - 1)
...@@ -774,6 +868,7 @@ int ffi_closure_helper_DARWIN (ffi_closure* closure, void * rvalue, ...@@ -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]. */ We use a union to pass the long double to avalue[i]. */
else if (nf == NUM_FPR_ARG_REGISTERS - 1) else if (nf == NUM_FPR_ARG_REGISTERS - 1)
{ {
union ldu temp_ld;
memcpy (&temp_ld.lb[0], pfr, sizeof(ldbits)); memcpy (&temp_ld.lb[0], pfr, sizeof(ldbits));
memcpy (&temp_ld.lb[1], pgr + 2, sizeof(ldbits)); memcpy (&temp_ld.lb[1], pgr + 2, sizeof(ldbits));
avalue[i] = &temp_ld.ld; avalue[i] = &temp_ld.ld;
...@@ -785,6 +880,7 @@ int ffi_closure_helper_DARWIN (ffi_closure* closure, void * rvalue, ...@@ -785,6 +880,7 @@ int ffi_closure_helper_DARWIN (ffi_closure* closure, void * rvalue,
nf += 2; nf += 2;
ng += 4; ng += 4;
pgr += 4; pgr += 4;
#endif /* POWERPC64 */
break; break;
#endif #endif
default: default:
......
...@@ -30,7 +30,11 @@ ...@@ -30,7 +30,11 @@
/* ---- System specific configurations ----------------------------------- */ /* ---- 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 #define POWERPC64
#endif #endif
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment