Commit 69b182fd by Andreas Tobler Committed by Andreas Tobler

types.c (double): Add AIX and Darwin to the right TYPEDEF.

2003-09-18  Andreas Tobler  <a.tobler@schweiz.ch>
	    David Edelsohn  <edelsohn@gnu.org>

	* src/types.c (double): Add AIX and Darwin to the right TYPEDEF.
	* src/powerpc/aix_closure.S: Remove the pointer to the outgoing
	parameter stack.
	* src/powerpc/darwin_closure.S: Likewise.
	* src/powerpc/ffi_darwin.c (ffi_prep_args): Handle structures
	according to the Darwin/AIX ABI.
	(ffi_prep_cif_machdep): Likewise.
	(ffi_closure_helper_DARWIN): Likewise.
	Remove the outgoing parameter stack logic. Simplify the evaluation
	of the different CASE types.
	(ffi_prep_clousure): Avoid the casts on lvalues. Change the branch
	statement in the trampoline code.

Co-Authored-By: David Edelsohn <edelsohn@gnu.org>

From-SVN: r71530
parent 85b22f78
2003-09-18 Andreas Tobler <a.tobler@schweiz.ch>
David Edelsohn <edelsohn@gnu.org>
* src/types.c (double): Add AIX and Darwin to the right TYPEDEF.
* src/powerpc/aix_closure.S: Remove the pointer to the outgoing
parameter stack.
* src/powerpc/darwin_closure.S: Likewise.
* src/powerpc/ffi_darwin.c (ffi_prep_args): Handle structures
according to the Darwin/AIX ABI.
(ffi_prep_cif_machdep): Likewise.
(ffi_closure_helper_DARWIN): Likewise.
Remove the outgoing parameter stack logic. Simplify the evaluation
of the different CASE types.
(ffi_prep_clousure): Avoid the casts on lvalues. Change the branch
statement in the trampoline code.
2003-09-18 Kaz Kojima <kkojima@gcc.gnu.org> 2003-09-18 Kaz Kojima <kkojima@gcc.gnu.org>
* src/sh/ffi.c (ffi_prep_args): Take account into the alignement * src/sh/ffi.c (ffi_prep_args): Take account into the alignement
......
...@@ -105,8 +105,8 @@ ffi_closure_ASM: ...@@ -105,8 +105,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) /* 8 Bytes (result) */
/* 168 Bytes */ /* 168 Bytes */
stwu r1,-176(r1) /* skip over caller save area stwu r1,-176(r1) /* skip over caller save area
...@@ -144,20 +144,16 @@ ffi_closure_ASM: ...@@ -144,20 +144,16 @@ ffi_closure_ASM:
/* set up registers for the routine that actually does the work */ /* set up registers for the routine that actually does the work */
/* get the context pointer from the trampoline */ /* get the context pointer from the trampoline */
mr r3,r11 mr r3,r11
/* now load up the pointer to the result storage */ /* now load up the pointer to the result storage */
addi r4,r1,160 addi r4,r1,160
/* now load up the pointer to the saved gpr registers */ /* now load up the pointer to the saved gpr registers */
addi r5,r1,200 addi r5,r1,200
/* now load up the pointer to the saved fpr registers */ /* now load up the pointer to the saved fpr registers */
addi r6,r1,56 addi r6,r1,56
/* now load up the pointer to the outgoing parameter */
/* stack in the previous frame */
addi r7,r1,232
/* make the call */ /* make the call */
bl .ffi_closure_helper_DARWIN bl .ffi_closure_helper_DARWIN
nop nop
......
...@@ -31,7 +31,7 @@ ...@@ -31,7 +31,7 @@
.text .text
.align 2 .align 2
.globl _ffi_closure_ASM .globl _ffi_closure_ASM
.text .text
.align 2 .align 2
_ffi_closure_ASM: _ffi_closure_ASM:
...@@ -44,13 +44,13 @@ LCFI0: ...@@ -44,13 +44,13 @@ LCFI0:
104 Bytes (13*8 from FPR) 104 Bytes (13*8 from FPR)
8 Bytes (result) 8 Bytes (result)
168 Bytes */ 168 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 */
LCFI1: LCFI1:
/* we want to build up an area for the parameters passed /* we want to build up an area for the parameters passed
in registers (both floating point and integer) */ in registers (both floating point and integer) */
/* we store gpr 3 to gpr 10 (aligned to 4) /* we store gpr 3 to gpr 10 (aligned to 4)
in the parents outgoing area */ in the parents outgoing area */
stw r3, 200(r1) stw r3, 200(r1)
...@@ -80,23 +80,19 @@ LCFI1: ...@@ -80,23 +80,19 @@ LCFI1:
/* set up registers for the routine that actually does the work */ /* set up registers for the routine that actually does the work */
/* get the context pointer from the trampoline */ /* get the context pointer from the trampoline */
mr r3,r11 mr r3,r11
/* now load up the pointer to the result storage */ /* now load up the pointer to the result storage */
addi r4,r1,160 addi r4,r1,160
/* now load up the pointer to the saved gpr registers */ /* now load up the pointer to the saved gpr registers */
addi r5,r1,200 addi r5,r1,200
/* now load up the pointer to the saved fpr registers */ /* now load up the pointer to the saved fpr registers */
addi r6,r1,56 addi r6,r1,56
/* now load up the pointer to the outgoing parameter
stack in the previous frame */
addi r7,r1,232
/* make the call */ /* make the call */
bl Lffi_closure_helper_DARWIN$stub bl Lffi_closure_helper_DARWIN$stub
/* now r3 contains the return type */ /* now r3 contains the return type */
/* so use it to look up in a table */ /* so use it to look up in a table */
/* so we know how to deal with each type */ /* so we know how to deal with each type */
...@@ -114,7 +110,7 @@ LFE1: ...@@ -114,7 +110,7 @@ LFE1:
/* Each of the ret_typeX code fragments has to be exactly 16 bytes long */ /* Each of the ret_typeX code fragments has to be exactly 16 bytes long */
/* (4 instructions). For cache effectiveness we align to a 16 byte boundary */ /* (4 instructions). For cache effectiveness we align to a 16 byte boundary */
/* first. */ /* first. */
.align 4 .align 4
nop nop
...@@ -234,7 +230,7 @@ Lfinish: ...@@ -234,7 +230,7 @@ Lfinish:
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
/* END(ffi_closure_ASM) */ /* END(ffi_closure_ASM) */
.data .data
......
...@@ -29,7 +29,7 @@ ...@@ -29,7 +29,7 @@
#include <ffi_common.h> #include <ffi_common.h>
#include <stdlib.h> #include <stdlib.h>
extern void ffi_closure_ASM(void); extern void ffi_closure_ASM(void);
enum { enum {
...@@ -81,8 +81,7 @@ enum { ASM_NEEDS_REGISTERS = 4 }; ...@@ -81,8 +81,7 @@ enum { ASM_NEEDS_REGISTERS = 4 };
void ffi_prep_args(extended_cif *ecif, unsigned *const stack) void ffi_prep_args(extended_cif *ecif, unsigned *const stack)
/*@=exportheader@*/ /*@=exportheader@*/
{ {
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 + (ecif->cif->bytes / sizeof(unsigned)); unsigned *const stacktop = stack + (ecif->cif->bytes / sizeof(unsigned));
...@@ -96,12 +95,13 @@ void ffi_prep_args(extended_cif *ecif, unsigned *const stack) ...@@ -96,12 +95,13 @@ void ffi_prep_args(extended_cif *ecif, unsigned *const stack)
/* '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 posistions. unsigned *next_arg = stack + 6; // 6 reserved posistions.
int i=ecif->cif->nargs; int i = ecif->cif->nargs;
double double_tmp; double double_tmp;
float float_tmp;
void **p_argv = ecif->avalue; void **p_argv = ecif->avalue;
unsigned gprvalue; unsigned gprvalue;
ffi_type** ptr = ecif->cif->arg_types; ffi_type** ptr = ecif->cif->arg_types;
char *dest_cpy;
unsigned size_al = 0;
/* Check that everything starts aligned properly. */ /* Check that everything starts aligned properly. */
FFI_ASSERT(((unsigned)(char *)stack & 0xF) == 0); FFI_ASSERT(((unsigned)(char *)stack & 0xF) == 0);
...@@ -163,16 +163,29 @@ void ffi_prep_args(extended_cif *ecif, unsigned *const stack) ...@@ -163,16 +163,29 @@ void ffi_prep_args(extended_cif *ecif, unsigned *const stack)
gprvalue = *(signed short *)*p_argv; gprvalue = *(signed short *)*p_argv;
goto putgpr; goto putgpr;
case FFI_TYPE_STRUCT: case FFI_TYPE_STRUCT:
#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE #if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
case FFI_TYPE_LONGDOUBLE: case FFI_TYPE_LONGDOUBLE:
#endif #endif
dest_cpy = (char *) next_arg;
memcpy((char*)next_arg, (char *)*p_argv, (*ptr)->size);
next_arg+=(((((*ptr)->size) + 3) & ~0x3)/4); /* Structures that match the basic modes (QI 1 byte, HI 2 bytes,
break; SI 4 bytes) are aligned as if they were those modes.
Structures with 3 byte in size are padded upwards. */
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)
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 + 3) / 4;
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:
...@@ -187,7 +200,6 @@ void ffi_prep_args(extended_cif *ecif, unsigned *const stack) ...@@ -187,7 +200,6 @@ void ffi_prep_args(extended_cif *ecif, unsigned *const stack)
} }
/* Check that we didn't overrun the stack... */ /* Check that we didn't overrun the stack... */
//FFI_ASSERT(copy_space >= (char *)next_arg);
//FFI_ASSERT(gpr_base <= stacktop - ASM_NEEDS_REGISTERS); //FFI_ASSERT(gpr_base <= stacktop - ASM_NEEDS_REGISTERS);
//FFI_ASSERT((unsigned *)fpr_base //FFI_ASSERT((unsigned *)fpr_base
// <= stacktop - ASM_NEEDS_REGISTERS - NUM_GPR_ARG_REGISTERS); // <= stacktop - ASM_NEEDS_REGISTERS - NUM_GPR_ARG_REGISTERS);
...@@ -203,7 +215,7 @@ ffi_status ffi_prep_cif_machdep(ffi_cif *cif) ...@@ -203,7 +215,7 @@ ffi_status ffi_prep_cif_machdep(ffi_cif *cif)
unsigned bytes; unsigned bytes;
int fparg_count = 0, intarg_count = 0; int fparg_count = 0, intarg_count = 0;
unsigned flags = 0; unsigned flags = 0;
unsigned struct_copy_size = 0; unsigned size_al = 0;
/* All the machine-independent calculation of cif->bytes will be wrong. /* All the machine-independent calculation of cif->bytes will be wrong.
Redo the calculation for DARWIN. */ Redo the calculation for DARWIN. */
...@@ -281,7 +293,7 @@ ffi_status ffi_prep_cif_machdep(ffi_cif *cif) ...@@ -281,7 +293,7 @@ ffi_status ffi_prep_cif_machdep(ffi_cif *cif)
on the stack. If they go on the stack, they must on the stack. If they go on the stack, they must
be 8-byte-aligned. */ be 8-byte-aligned. */
if (intarg_count == NUM_GPR_ARG_REGISTERS-1 if (intarg_count == NUM_GPR_ARG_REGISTERS-1
|| intarg_count >= NUM_GPR_ARG_REGISTERS && intarg_count%2 != 0) || (intarg_count >= NUM_GPR_ARG_REGISTERS && intarg_count%2 != 0))
intarg_count++; intarg_count++;
intarg_count += 2; intarg_count += 2;
break; break;
...@@ -290,7 +302,13 @@ ffi_status ffi_prep_cif_machdep(ffi_cif *cif) ...@@ -290,7 +302,13 @@ ffi_status ffi_prep_cif_machdep(ffi_cif *cif)
#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE #if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
case FFI_TYPE_LONGDOUBLE: case FFI_TYPE_LONGDOUBLE:
#endif #endif
intarg_count+=(((*ptr)->size + 3) & ~0x3)/4; 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)
size_al = ALIGN((*ptr)->size, 8);
intarg_count += (size_al + 3) / 4;
break; break;
default: default:
...@@ -303,9 +321,7 @@ ffi_status ffi_prep_cif_machdep(ffi_cif *cif) ...@@ -303,9 +321,7 @@ ffi_status ffi_prep_cif_machdep(ffi_cif *cif)
if (fparg_count != 0) if (fparg_count != 0)
flags |= FLAG_FP_ARGUMENTS; flags |= FLAG_FP_ARGUMENTS;
if (struct_copy_size != 0)
flags |= FLAG_ARG_NEEDS_COPY;
/* Space for the FPR registers, if needed. */ /* Space for the FPR registers, if needed. */
if (fparg_count != 0) if (fparg_count != 0)
bytes += NUM_FPR_ARG_REGISTERS * sizeof(double); bytes += NUM_FPR_ARG_REGISTERS * sizeof(double);
...@@ -321,7 +337,7 @@ ffi_status ffi_prep_cif_machdep(ffi_cif *cif) ...@@ -321,7 +337,7 @@ ffi_status ffi_prep_cif_machdep(ffi_cif *cif)
cif->flags = flags; cif->flags = flags;
cif->bytes = bytes; cif->bytes = bytes;
return FFI_OK; return FFI_OK;
} }
...@@ -349,7 +365,7 @@ void ffi_call(/*@dependent@*/ ffi_cif *cif, ...@@ -349,7 +365,7 @@ void ffi_call(/*@dependent@*/ ffi_cif *cif,
ecif.cif = cif; ecif.cif = cif;
ecif.avalue = avalue; ecif.avalue = avalue;
/* If the return value is a struct and we don't have a return */ /* If the return value is a struct and we don't have a return */
/* value address then we need to make one */ /* value address then we need to make one */
...@@ -362,7 +378,7 @@ void ffi_call(/*@dependent@*/ ffi_cif *cif, ...@@ -362,7 +378,7 @@ void ffi_call(/*@dependent@*/ ffi_cif *cif,
} }
else else
ecif.rvalue = rvalue; ecif.rvalue = rvalue;
switch (cif->abi) switch (cif->abi)
{ {
case FFI_AIX: case FFI_AIX:
...@@ -385,7 +401,7 @@ void ffi_call(/*@dependent@*/ ffi_cif *cif, ...@@ -385,7 +401,7 @@ void ffi_call(/*@dependent@*/ ffi_cif *cif,
static void flush_icache(char *); static void flush_icache(char *);
static void flush_range(char *, int); static void flush_range(char *, int);
/* The layout of a function descriptor. A C function pointer really */ /* The layout of a function descriptor. A C function pointer really */
/* points to one of these. */ /* points to one of these. */
...@@ -397,7 +413,7 @@ typedef struct aix_fd_struct { ...@@ -397,7 +413,7 @@ typedef struct aix_fd_struct {
/* here I'd like to add the stack frame layout we use in darwin_closure.S /* here I'd like to add the stack frame layout we use in darwin_closure.S
* and aix_clsoure.S * and aix_clsoure.S
* *
/* SP previous -> +---------------------------------------+ <--- child frame * SP previous -> +---------------------------------------+ <--- child frame
| back chain to caller 4 | | back chain to caller 4 |
+---------------------------------------+ 4 +---------------------------------------+ 4
| saved CR 4 | | saved CR 4 |
...@@ -441,7 +457,7 @@ SP current --> +---------------------------------------+ 176 <- parent frame ...@@ -441,7 +457,7 @@ SP current --> +---------------------------------------+ 176 <- parent frame
| . | | . |
| r10 | | r10 |
+---------------------------------------+ 232 +---------------------------------------+ 232
| PST area, overflow part | | overflow part |
+---------------------------------------+ xxx +---------------------------------------+ xxx
| ???? | | ???? |
+---------------------------------------+ xxx +---------------------------------------+ xxx
...@@ -456,7 +472,7 @@ ffi_prep_closure (ffi_closure* closure, ...@@ -456,7 +472,7 @@ ffi_prep_closure (ffi_closure* closure,
unsigned int *tramp; unsigned int *tramp;
struct ffi_aix_trampoline_struct *tramp_aix; struct ffi_aix_trampoline_struct *tramp_aix;
aix_fd *fd; aix_fd *fd;
switch (cif->abi) switch (cif->abi)
{ {
case FFI_DARWIN: case FFI_DARWIN:
...@@ -464,24 +480,24 @@ ffi_prep_closure (ffi_closure* closure, ...@@ -464,24 +480,24 @@ ffi_prep_closure (ffi_closure* closure,
FFI_ASSERT (cif->abi == FFI_DARWIN); FFI_ASSERT (cif->abi == FFI_DARWIN);
tramp = (unsigned int *) &closure->tramp[0]; tramp = (unsigned int *) &closure->tramp[0];
tramp[0] = 0x7c0802a6; /* mflr r0 */ tramp[0] = 0x7c0802a6; /* mflr r0 */
tramp[1] = 0x4800000d; /* bl 10 <trampoline_initial+0x10> */ tramp[1] = 0x429f000d; /* bcl- 20,4*cr7+so,0x10 */
tramp[4] = 0x7d6802a6; /* mflr r11 */ tramp[4] = 0x7d6802a6; /* mflr r11 */
tramp[5] = 0x818b0000; /* lwz r12,0(r11) /* function address */ tramp[5] = 0x818b0000; /* lwz r12,0(r11) function address */
tramp[6] = 0x7c0803a6; /* mtlr r0 */ tramp[6] = 0x7c0803a6; /* mtlr r0 */
tramp[7] = 0x7d8903a6; /* mtctr r12 */ tramp[7] = 0x7d8903a6; /* mtctr r12 */
tramp[8] = 0x816b0004; /* lwz r11,4(r11) /* static chain */ tramp[8] = 0x816b0004; /* lwz r11,4(r11) static chain */
tramp[9] = 0x4e800420; /* bctr */ tramp[9] = 0x4e800420; /* bctr */
*(void **) &tramp[2] = (void *)ffi_closure_ASM; /* function */ tramp[2] = (unsigned long) ffi_closure_ASM; /* function */
*(void **) &tramp[3] = (void *)closure; /* context */ tramp[3] = (unsigned long) closure; /* context */
closure->cif = cif; closure->cif = cif;
closure->fun = fun; closure->fun = fun;
closure->user_data = user_data; closure->user_data = user_data;
/* Flush the icache. Only necessary on Darwin */ /* Flush the icache. Only necessary on Darwin. */
flush_range(&closure->tramp[0],FFI_TRAMPOLINE_SIZE); flush_range(&closure->tramp[0],FFI_TRAMPOLINE_SIZE);
break; break;
case FFI_AIX: case FFI_AIX:
...@@ -530,8 +546,14 @@ flush_range(char * addr1, int size) ...@@ -530,8 +546,14 @@ flush_range(char * addr1, int size)
flush_icache(addr1+size-1); flush_icache(addr1+size-1);
} }
int ffi_closure_helper_DARWIN (ffi_closure*, void*, unsigned long*, typedef union
unsigned long*, unsigned long*); {
float f;
double d;
} ffi_dblfl;
int ffi_closure_helper_DARWIN (ffi_closure*, void*,
unsigned long*, ffi_dblfl*);
/* Basically the trampoline invokes ffi_closure_ASM, and on /* Basically the trampoline invokes ffi_closure_ASM, and on
* entry, r11 holds the address of the closure. * entry, r11 holds the address of the closure.
...@@ -541,15 +563,13 @@ int ffi_closure_helper_DARWIN (ffi_closure*, void*, unsigned long*, ...@@ -541,15 +563,13 @@ int ffi_closure_helper_DARWIN (ffi_closure*, void*, unsigned long*,
* following helper function to do most of the work * following helper function to do most of the work
*/ */
int int ffi_closure_helper_DARWIN (ffi_closure* closure, void * rvalue,
ffi_closure_helper_DARWIN (ffi_closure* closure, void * rvalue, unsigned long * pgr, ffi_dblfl * pfr)
unsigned long * pgr, unsigned long * pfr,
unsigned long * pst)
{ {
/* rvalue is the pointer to space for return value in closure assembly */ /* rvalue is the pointer to space for return value in closure assembly
/* pgr is the pointer to where r3-r10 are stored in ffi_closure_ASM */ pgr is the pointer to where r3-r10 are stored in ffi_closure_ASM
/* pfr is the pointer to where f1-f13 are stored in ffi_closure_ASM */ pfr is the pointer to where f1-f13 are stored in ffi_closure_ASM. */
/* pst is the pointer to outgoing parameter stack in original caller */
void ** avalue; void ** avalue;
ffi_type ** arg_types; ffi_type ** arg_types;
...@@ -558,6 +578,7 @@ ffi_closure_helper_DARWIN (ffi_closure* closure, void * rvalue, ...@@ -558,6 +578,7 @@ ffi_closure_helper_DARWIN (ffi_closure* closure, void * rvalue,
long ng; /* number of general registers already used */ long ng; /* number of general registers already used */
ffi_cif * cif; ffi_cif * cif;
double temp; double temp;
unsigned size_al;
cif = closure->cif; cif = closure->cif;
avalue = alloca(cif->nargs * sizeof(void *)); avalue = alloca(cif->nargs * sizeof(void *));
...@@ -569,9 +590,9 @@ ffi_closure_helper_DARWIN (ffi_closure* closure, void * rvalue, ...@@ -569,9 +590,9 @@ ffi_closure_helper_DARWIN (ffi_closure* closure, void * rvalue,
returns the data directly to the caller. */ returns the data directly to the caller. */
if (cif->rtype->type == FFI_TYPE_STRUCT) if (cif->rtype->type == FFI_TYPE_STRUCT)
{ {
rvalue = (void *)pgr; rvalue = (void *) *pgr;
ng++;
pgr++; pgr++;
ng++;
} }
i = 0; i = 0;
...@@ -582,125 +603,97 @@ ffi_closure_helper_DARWIN (ffi_closure* closure, void * rvalue, ...@@ -582,125 +603,97 @@ ffi_closure_helper_DARWIN (ffi_closure* closure, void * rvalue,
while (i < avn) while (i < avn)
{ {
switch (arg_types[i]->type) switch (arg_types[i]->type)
{ {
case FFI_TYPE_SINT8: case FFI_TYPE_SINT8:
case FFI_TYPE_UINT8: case FFI_TYPE_UINT8:
/* there are 8 gpr registers used to pass values */ avalue[i] = (char *) pgr + 3;
if (ng < 8) { ng++;
avalue[i] = (((char *)pgr)+3); pgr++;
ng++; break;
pgr++;
} else { case FFI_TYPE_SINT16:
avalue[i] = (((char *)pst)+3); case FFI_TYPE_UINT16:
pst++; avalue[i] = (char *) pgr + 2;
} ng++;
break; pgr++;
break;
case FFI_TYPE_SINT16:
case FFI_TYPE_UINT16: case FFI_TYPE_SINT32:
/* there are 8 gpr registers used to pass values */ case FFI_TYPE_UINT32:
if (ng < 8) { case FFI_TYPE_POINTER:
avalue[i] = (((char *)pgr)+2); avalue[i] = pgr;
ng++; ng++;
pgr++; pgr++;
} else { break;
avalue[i] = (((char *)pst)+2);
pst++; case FFI_TYPE_STRUCT:
} /* Structures that match the basic modes (QI 1 byte, HI 2 bytes,
break; SI 4 bytes) are aligned as if they were those modes. */
size_al = arg_types[i]->size;
case FFI_TYPE_SINT32: /* If the first member of the struct is a double, then align
case FFI_TYPE_UINT32: the struct to double-word.
case FFI_TYPE_POINTER: Type 3 is defined in include/ffi.h. #define FFI_TYPE_DOUBLE 3. */
case FFI_TYPE_STRUCT: if (arg_types[i]->elements[0]->type == 3)
/* there are 8 gpr registers used to pass values */ size_al = ALIGN(arg_types[i]->size, 8);
if (ng < 8) { if (size_al < 3 && cif->abi == FFI_DARWIN)
avalue[i] = pgr; avalue[i] = (void*) pgr + 4 - size_al;
ng++; else
pgr++; avalue[i] = (void*) pgr;
} else { ng += (size_al + 3) / 4;
avalue[i] = pst; pgr += (size_al + 3) / 4;
pst++; break;
}
break; case FFI_TYPE_SINT64:
case FFI_TYPE_UINT64:
case FFI_TYPE_SINT64: /* Long long ints are passed in two gpr's. */
case FFI_TYPE_UINT64: avalue[i] = pgr;
/* long long ints are passed in two gpr's if available or in ng += 2;
* the pst, one place is a bit odd, when a long long passes pgr += 2;
* the boundary between gpr and pst area we have to increment break;
* the pst by one.
*/ case FFI_TYPE_FLOAT:
if (ng < 7) { /* a float value consumes a GPR
avalue[i] = pgr; *
ng+=2; * here are 13 64bit floating point registers.
pgr+=2;
} else if (ng == 7) {
avalue[i] = pgr;
ng++;
pgr++;
pst++;
} else {
avalue[i] = pst;
pst+=2;
}
break;
case FFI_TYPE_FLOAT:
/* a float value consumes a GPR
*
* there are 13 64bit floating point registers
*/ */
if (nf < NUM_FPR_ARG_REGISTERS)
if ((ng > 7) && (nf < 13)) { {
pst++; temp = pfr->d;
} pfr->f = (float)temp;
if (nf < 13) { avalue[i] = pfr;
temp = *(double*)pfr; pfr++;
*(float*)pfr = (float)temp; }
avalue[i] = pfr; else
nf++; {
pfr+=2; avalue[i] = pgr;
ng++; }
pgr++; nf++;
ng++;
} else { pgr++;
avalue[i] = pst; break;
nf++;
pst++; case FFI_TYPE_DOUBLE:
}
break;
case FFI_TYPE_DOUBLE:
/* a double value consumes two GPRs /* a double value consumes two GPRs
* *
* there are 13 64bit floating point registers * There are 13 64bit floating point registers.
*/ */
if (nf < NUM_FPR_ARG_REGISTERS)
if ((ng == 7) && (nf < 13)) { {
pst++; /* if only one gpr is left the double steals it */ avalue[i] = pfr;
} else if ((ng > 7) && (nf < 13)) { pfr++;
pst+=2; /* a double consumes two GPRs in Darwin/AIX */ }
} else
if (nf < 13) { {
avalue[i] = pfr; avalue[i] = pgr;
nf++; }
pfr+=2; nf++;
ng+=2; ng += 2;
pgr+=2; pgr += 2;
break;
} else {
avalue[i] = pst;
nf++;
pst+=2;
}
break;
default: default:
FFI_ASSERT(0); FFI_ASSERT(0);
} }
i++; i++;
} }
...@@ -708,5 +701,4 @@ ffi_closure_helper_DARWIN (ffi_closure* closure, void * rvalue, ...@@ -708,5 +701,4 @@ ffi_closure_helper_DARWIN (ffi_closure* closure, void * rvalue,
/* Tell ffi_closure_ASM to perform return type promotions. */ /* Tell ffi_closure_ASM to perform return type promotions. */
return cif->rtype->type; return cif->rtype->type;
} }
...@@ -76,7 +76,7 @@ FFI_INTEGRAL_TYPEDEF(sint64, 8, 8, FFI_TYPE_SINT64); ...@@ -76,7 +76,7 @@ FFI_INTEGRAL_TYPEDEF(sint64, 8, 8, FFI_TYPE_SINT64);
FFI_INTEGRAL_TYPEDEF(double, 8, 4, FFI_TYPE_DOUBLE); FFI_INTEGRAL_TYPEDEF(double, 8, 4, FFI_TYPE_DOUBLE);
FFI_INTEGRAL_TYPEDEF(longdouble, 12, 4, FFI_TYPE_LONGDOUBLE); FFI_INTEGRAL_TYPEDEF(longdouble, 12, 4, FFI_TYPE_LONGDOUBLE);
#elif defined ARM || defined SH || defined POWERPC64 #elif defined ARM || defined SH || defined POWERPC64 || defined POWERPC_AIX || defined POWERPC_DARWIN
FFI_INTEGRAL_TYPEDEF(double, 8, 4, FFI_TYPE_DOUBLE); FFI_INTEGRAL_TYPEDEF(double, 8, 4, FFI_TYPE_DOUBLE);
FFI_INTEGRAL_TYPEDEF(longdouble, 8, 4, FFI_TYPE_LONGDOUBLE); FFI_INTEGRAL_TYPEDEF(longdouble, 8, 4, FFI_TYPE_LONGDOUBLE);
......
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