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
This commit is contained in:
parent
17f35e2332
commit
5751cf6fef
@ -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
|
||||
|
@ -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
|
||||
|
@ -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) */
|
||||
|
@ -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;
|
||||
else
|
||||
*fpr_base++ = double_tmp;
|
||||
next_arg += 2;
|
||||
fparg_count++;
|
||||
double_tmp = ((double *)*p_argv)[1];
|
||||
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
|
||||
*(long double *) next_arg = *(long double *) *p_argv;
|
||||
next_arg += 2;
|
||||
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:
|
||||
|
@ -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
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user