aboutsummaryrefslogtreecommitdiff
path: root/libffi/src/powerpc/ffi_darwin.c
diff options
context:
space:
mode:
Diffstat (limited to 'libffi/src/powerpc/ffi_darwin.c')
-rw-r--r--libffi/src/powerpc/ffi_darwin.c536
1 files changed, 262 insertions, 274 deletions
diff --git a/libffi/src/powerpc/ffi_darwin.c b/libffi/src/powerpc/ffi_darwin.c
index 3f705275c5f..73653cd43c6 100644
--- a/libffi/src/powerpc/ffi_darwin.c
+++ b/libffi/src/powerpc/ffi_darwin.c
@@ -1,7 +1,7 @@
/* -----------------------------------------------------------------------
ffi.c - Copyright (c) 1998 Geoffrey Keating
-
- PowerPC Foreign Function Interface
+
+ PowerPC Foreign Function Interface
Darwin ABI support (c) 2001 John Hornkvist
AIX ABI support (c) 2002 Free Software Foundation, Inc.
@@ -29,17 +29,17 @@
#include <ffi_common.h>
#include <stdlib.h>
-
+
extern void ffi_closure_ASM(void);
enum {
/* The assembly depends on these exact flags. */
- FLAG_RETURNS_NOTHING = 1 << (31-30), /* These go in cr7 */
+ FLAG_RETURNS_NOTHING = 1 << (31-30), /* These go in cr7 */
FLAG_RETURNS_FP = 1 << (31-29),
FLAG_RETURNS_64BITS = 1 << (31-28),
FLAG_ARG_NEEDS_COPY = 1 << (31- 7),
- FLAG_FP_ARGUMENTS = 1 << (31- 6), /* cr1.eq; specified by ABI */
+ FLAG_FP_ARGUMENTS = 1 << (31- 6), /* cr1.eq; specified by ABI */
FLAG_4_GPR_ARGUMENTS = 1 << (31- 5),
FLAG_RETVAL_REFERENCE = 1 << (31- 4)
};
@@ -58,7 +58,7 @@ enum { ASM_NEEDS_REGISTERS = 4 };
| Return address from ffi_call_DARWIN | higher addresses
|--------------------------------------------|
- | Previous backchain pointer 4 | stack pointer here
+ | Previous backchain pointer 4 | stack pointer here
|--------------------------------------------|<+ <<< on entry to
| Saved r28-r31 4*4 | | ffi_call_DARWIN
|--------------------------------------------| |
@@ -69,7 +69,7 @@ enum { ASM_NEEDS_REGISTERS = 4 };
| Reserved 2*4 | | grows |
|--------------------------------------------| | down V
| Space for callee's LR 4 | |
- |--------------------------------------------| | lower addresses
+ |--------------------------------------------| | lower addresses
| Saved CR 4 | |
|--------------------------------------------| | stack pointer here
| Current backchain pointer 4 |-/ during
@@ -81,8 +81,7 @@ enum { ASM_NEEDS_REGISTERS = 4 };
void ffi_prep_args(extended_cif *ecif, unsigned *const stack)
/*@=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. */
unsigned *const stacktop = stack + (ecif->cif->bytes / sizeof(unsigned));
@@ -94,23 +93,25 @@ void ffi_prep_args(extended_cif *ecif, unsigned *const stack)
/* '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;
- float float_tmp;
void **p_argv = ecif->avalue;
unsigned gprvalue;
ffi_type** ptr = ecif->cif->arg_types;
+ char *dest_cpy;
+ unsigned size_al = 0;
/* Check that everything starts aligned properly. */
FFI_ASSERT(((unsigned)(char *)stack & 0xF) == 0);
FFI_ASSERT(((unsigned)(char *)stacktop & 0xF) == 0);
FFI_ASSERT((bytes & 0xF) == 0);
- /* Deal with return values that are actually pass-by-reference. */
- // Rule:
- // Return values are referenced by r3, so r4 is the first parameter.
+ /* Deal with return values that are actually pass-by-reference.
+ Rule:
+ Return values are referenced by r3, so r4 is the first parameter. */
+
if (flags & FLAG_RETVAL_REFERENCE)
*next_arg++ = (unsigned)(char *)ecif->rvalue;
@@ -127,28 +128,28 @@ void ffi_prep_args(extended_cif *ecif, unsigned *const stack)
case FFI_TYPE_FLOAT:
double_tmp = *(float *)*p_argv;
if (fparg_count >= NUM_FPR_ARG_REGISTERS)
- *(double *)next_arg = double_tmp;
+ *(double *)next_arg = double_tmp;
else
- *fpr_base++ = double_tmp;
- next_arg++;
+ *fpr_base++ = double_tmp;
+ next_arg++;
fparg_count++;
FFI_ASSERT(flags & FLAG_FP_ARGUMENTS);
break;
case FFI_TYPE_DOUBLE:
double_tmp = *(double *)*p_argv;
if (fparg_count >= NUM_FPR_ARG_REGISTERS)
- *(double *)next_arg = double_tmp;
+ *(double *)next_arg = double_tmp;
else
- *fpr_base++ = double_tmp;
- next_arg += 2;
+ *fpr_base++ = double_tmp;
+ next_arg += 2;
fparg_count++;
FFI_ASSERT(flags & FLAG_FP_ARGUMENTS);
break;
case FFI_TYPE_UINT64:
case FFI_TYPE_SINT64:
- *(long long *)next_arg = *(long long *)*p_argv;
- next_arg+=2;
+ *(long long *)next_arg = *(long long *)*p_argv;
+ next_arg+=2;
break;
case FFI_TYPE_UINT8:
gprvalue = *(unsigned char *)*p_argv;
@@ -163,18 +164,31 @@ void ffi_prep_args(extended_cif *ecif, unsigned *const stack)
gprvalue = *(signed short *)*p_argv;
goto putgpr;
- case FFI_TYPE_STRUCT:
+ case FFI_TYPE_STRUCT:
#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
- case FFI_TYPE_LONGDOUBLE:
+ case FFI_TYPE_LONGDOUBLE:
#endif
-
- memcpy((char*)next_arg, (char *)*p_argv, (*ptr)->size);
- next_arg+=(((((*ptr)->size) + 3) & ~0x3)/4);
- break;
-
+ dest_cpy = (char *) next_arg;
+
+ /* Structures that match the basic modes (QI 1 byte, HI 2 bytes,
+ 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_UINT32:
+ case FFI_TYPE_UINT32:
case FFI_TYPE_SINT32:
case FFI_TYPE_POINTER:
gprvalue = *(unsigned *)*p_argv;
@@ -187,14 +201,13 @@ void ffi_prep_args(extended_cif *ecif, unsigned *const 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((unsigned *)fpr_base
// <= stacktop - ASM_NEEDS_REGISTERS - NUM_GPR_ARG_REGISTERS);
//FFI_ASSERT(flags & FLAG_4_GPR_ARGUMENTS || intarg_count <= 4);
}
-/* Perform machine dependent cif processing */
+/* Perform machine dependent cif processing. */
ffi_status ffi_prep_cif_machdep(ffi_cif *cif)
{
/* All this is for the DARWIN ABI. */
@@ -203,12 +216,12 @@ ffi_status ffi_prep_cif_machdep(ffi_cif *cif)
unsigned bytes;
int fparg_count = 0, intarg_count = 0;
unsigned flags = 0;
- unsigned struct_copy_size = 0;
+ unsigned size_al = 0;
/* All the machine-independent calculation of cif->bytes will be wrong.
Redo the calculation for DARWIN. */
- /* Space for the frame pointer, callee's LR, CR, etc, and for
+ /* Space for the frame pointer, callee's LR, CR, etc, and for
the asm's temp regs. */
bytes = (6 + ASM_NEEDS_REGISTERS) * sizeof(long);
@@ -281,7 +294,7 @@ ffi_status ffi_prep_cif_machdep(ffi_cif *cif)
on the stack. If they go on the stack, they must
be 8-byte-aligned. */
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 += 2;
break;
@@ -290,7 +303,13 @@ ffi_status ffi_prep_cif_machdep(ffi_cif *cif)
#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
case FFI_TYPE_LONGDOUBLE:
#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;
default:
@@ -303,9 +322,7 @@ ffi_status ffi_prep_cif_machdep(ffi_cif *cif)
if (fparg_count != 0)
flags |= FLAG_FP_ARGUMENTS;
- if (struct_copy_size != 0)
- flags |= FLAG_ARG_NEEDS_COPY;
-
+
/* Space for the FPR registers, if needed. */
if (fparg_count != 0)
bytes += NUM_FPR_ARG_REGISTERS * sizeof(double);
@@ -321,39 +338,39 @@ ffi_status ffi_prep_cif_machdep(ffi_cif *cif)
cif->flags = flags;
cif->bytes = bytes;
-
+
return FFI_OK;
}
/*@-declundef@*/
/*@-exportheader@*/
-extern void ffi_call_AIX(/*@out@*/ extended_cif *,
- unsigned, unsigned,
- /*@out@*/ unsigned *,
+extern void ffi_call_AIX(/*@out@*/ extended_cif *,
+ unsigned, unsigned,
+ /*@out@*/ unsigned *,
void (*fn)(),
void (*fn2)());
-extern void ffi_call_DARWIN(/*@out@*/ extended_cif *,
- unsigned, unsigned,
- /*@out@*/ unsigned *,
+extern void ffi_call_DARWIN(/*@out@*/ extended_cif *,
+ unsigned, unsigned,
+ /*@out@*/ unsigned *,
void (*fn)(),
void (*fn2)());
/*@=declundef@*/
/*@=exportheader@*/
-void ffi_call(/*@dependent@*/ ffi_cif *cif,
- void (*fn)(),
- /*@out@*/ void *rvalue,
+void ffi_call(/*@dependent@*/ ffi_cif *cif,
+ void (*fn)(),
+ /*@out@*/ void *rvalue,
/*@dependent@*/ void **avalue)
{
extended_cif ecif;
ecif.cif = cif;
ecif.avalue = avalue;
-
- /* If the return value is a struct and we don't have a return */
- /* value address then we need to make one */
- if ((rvalue == NULL) &&
+ /* If the return value is a struct and we don't have a return
+ value address then we need to make one. */
+
+ if ((rvalue == NULL) &&
(cif->rtype->type == FFI_TYPE_STRUCT))
{
/*@-sysunrecog@*/
@@ -362,18 +379,18 @@ void ffi_call(/*@dependent@*/ ffi_cif *cif,
}
else
ecif.rvalue = rvalue;
-
- switch (cif->abi)
+
+ switch (cif->abi)
{
case FFI_AIX:
/*@-usedef@*/
- ffi_call_AIX(&ecif, -cif->bytes,
+ ffi_call_AIX(&ecif, -cif->bytes,
cif->flags, ecif.rvalue, fn, ffi_prep_args);
/*@=usedef@*/
break;
case FFI_DARWIN:
/*@-usedef@*/
- ffi_call_DARWIN(&ecif, -cif->bytes,
+ ffi_call_DARWIN(&ecif, -cif->bytes,
cif->flags, ecif.rvalue, fn, ffi_prep_args);
/*@=usedef@*/
break;
@@ -385,9 +402,9 @@ void ffi_call(/*@dependent@*/ ffi_cif *cif,
static void flush_icache(char *);
static void flush_range(char *, int);
-
-/* The layout of a function descriptor. A C function pointer really */
-/* points to one of these. */
+
+/* The layout of a function descriptor. A C function pointer really
+ points to one of these. */
typedef struct aix_fd_struct {
void *code_pointer;
@@ -395,93 +412,93 @@ typedef struct aix_fd_struct {
} aix_fd;
/* here I'd like to add the stack frame layout we use in darwin_closure.S
- * and aix_clsoure.S
- *
-/* SP previous -> +---------------------------------------+ <--- child frame
- | back chain to caller 4 |
- +---------------------------------------+ 4
- | saved CR 4 |
- +---------------------------------------+ 8
- | saved LR 4 |
- +---------------------------------------+ 12
- | reserved for compilers 4 |
- +---------------------------------------+ 16
- | reserved for binders 4 |
- +---------------------------------------+ 20
- | saved TOC pointer 4 |
- +---------------------------------------+ 24
- | always reserved 8*4=32 (previous GPRs)|
- | according to the linkage convention |
- | from AIX |
- +---------------------------------------+ 56
- | our FPR area 13*8=104 |
- | f1 |
- | . |
- | f13 |
- +---------------------------------------+ 160
- | result area 8 |
- +---------------------------------------+ 168
- | alignement to the next multiple of 16 |
+ and aix_clsoure.S
+
+ SP previous -> +---------------------------------------+ <--- child frame
+ | back chain to caller 4 |
+ +---------------------------------------+ 4
+ | saved CR 4 |
+ +---------------------------------------+ 8
+ | saved LR 4 |
+ +---------------------------------------+ 12
+ | reserved for compilers 4 |
+ +---------------------------------------+ 16
+ | reserved for binders 4 |
+ +---------------------------------------+ 20
+ | saved TOC pointer 4 |
+ +---------------------------------------+ 24
+ | always reserved 8*4=32 (previous GPRs)|
+ | according to the linkage convention |
+ | from AIX |
+ +---------------------------------------+ 56
+ | our FPR area 13*8=104 |
+ | f1 |
+ | . |
+ | f13 |
+ +---------------------------------------+ 160
+ | result area 8 |
+ +---------------------------------------+ 168
+ | alignement to the next multiple of 16 |
SP current --> +---------------------------------------+ 176 <- parent frame
- | back chain to caller 4 |
- +---------------------------------------+ 180
- | saved CR 4 |
- +---------------------------------------+ 184
- | saved LR 4 |
- +---------------------------------------+ 188
- | reserved for compilers 4 |
- +---------------------------------------+ 192
- | reserved for binders 4 |
- +---------------------------------------+ 196
- | saved TOC pointer 4 |
- +---------------------------------------+ 200
- | always reserved 8*4=32 we store our |
- | GPRs here |
- | r3 |
- | . |
- | r10 |
- +---------------------------------------+ 232
- | PST area, overflow part |
- +---------------------------------------+ xxx
- | ???? |
- +---------------------------------------+ xxx
+ | back chain to caller 4 |
+ +---------------------------------------+ 180
+ | saved CR 4 |
+ +---------------------------------------+ 184
+ | saved LR 4 |
+ +---------------------------------------+ 188
+ | reserved for compilers 4 |
+ +---------------------------------------+ 192
+ | reserved for binders 4 |
+ +---------------------------------------+ 196
+ | saved TOC pointer 4 |
+ +---------------------------------------+ 200
+ | always reserved 8*4=32 we store our |
+ | GPRs here |
+ | r3 |
+ | . |
+ | r10 |
+ +---------------------------------------+ 232
+ | overflow part |
+ +---------------------------------------+ xxx
+ | ???? |
+ +---------------------------------------+ xxx
*/
ffi_status
-ffi_prep_closure (ffi_closure* closure,
- ffi_cif* cif,
- void (*fun)(ffi_cif*, void*, void**, void*),
- void *user_data)
+ffi_prep_closure (ffi_closure* closure,
+ ffi_cif* cif,
+ void (*fun)(ffi_cif*, void*, void**, void*),
+ void *user_data)
{
unsigned int *tramp;
struct ffi_aix_trampoline_struct *tramp_aix;
aix_fd *fd;
-
+
switch (cif->abi)
- {
+ {
case FFI_DARWIN:
FFI_ASSERT (cif->abi == FFI_DARWIN);
tramp = (unsigned int *) &closure->tramp[0];
- tramp[0] = 0x7c0802a6; /* mflr r0 */
- tramp[1] = 0x4800000d; /* bl 10 <trampoline_initial+0x10> */
- tramp[4] = 0x7d6802a6; /* mflr r11 */
- tramp[5] = 0x818b0000; /* lwz r12,0(r11) /* function address */
- tramp[6] = 0x7c0803a6; /* mtlr r0 */
- tramp[7] = 0x7d8903a6; /* mtctr r12 */
- tramp[8] = 0x816b0004; /* lwz r11,4(r11) /* static chain */
- tramp[9] = 0x4e800420; /* bctr */
- *(void **) &tramp[2] = (void *)ffi_closure_ASM; /* function */
- *(void **) &tramp[3] = (void *)closure; /* context */
+ tramp[0] = 0x7c0802a6; /* mflr r0 */
+ tramp[1] = 0x429f000d; /* bcl- 20,4*cr7+so,0x10 */
+ tramp[4] = 0x7d6802a6; /* mflr r11 */
+ tramp[5] = 0x818b0000; /* lwz r12,0(r11) function address */
+ tramp[6] = 0x7c0803a6; /* mtlr r0 */
+ tramp[7] = 0x7d8903a6; /* mtctr r12 */
+ tramp[8] = 0x816b0004; /* lwz r11,4(r11) static chain */
+ tramp[9] = 0x4e800420; /* bctr */
+ tramp[2] = (unsigned long) ffi_closure_ASM; /* function */
+ tramp[3] = (unsigned long) closure; /* context */
closure->cif = cif;
closure->fun = fun;
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);
-
+
break;
case FFI_AIX:
@@ -511,12 +528,12 @@ flush_icache(char *addr)
{
#ifndef _AIX
__asm__ volatile (
- "dcbf 0,%0;"
- "sync;"
- "icbi 0,%0;"
- "sync;"
- "isync;"
- : : "r"(addr) : "memory");
+ "dcbf 0,%0;"
+ "sync;"
+ "icbi 0,%0;"
+ "sync;"
+ "isync;"
+ : : "r"(addr) : "memory");
#endif
}
@@ -530,34 +547,38 @@ flush_range(char * addr1, int size)
flush_icache(addr1+size-1);
}
-int ffi_closure_helper_DARWIN (ffi_closure*, void*, unsigned long*,
- unsigned long*, unsigned long*);
+typedef union
+{
+ 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
- * entry, r11 holds the address of the closure.
- * After storing the registers that could possibly contain
- * parameters to be passed into the stack frame and setting
- * up space for a return value, ffi_closure_ASM invokes the
- * following helper function to do most of the work
- */
-
-int
-ffi_closure_helper_DARWIN (ffi_closure* closure, void * rvalue,
- unsigned long * pgr, unsigned long * pfr,
- unsigned long * pst)
+ entry, r11 holds the address of the closure.
+ After storing the registers that could possibly contain
+ parameters to be passed into the stack frame and setting
+ up space for a return value, ffi_closure_ASM invokes the
+ following helper function to do most of the work. */
+
+int ffi_closure_helper_DARWIN (ffi_closure* closure, void * rvalue,
+ unsigned long * pgr, ffi_dblfl * pfr)
{
- /* 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 */
- /* 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 */
+ /* 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
+ pfr is the pointer to where f1-f13 are stored in ffi_closure_ASM. */
+
void ** avalue;
ffi_type ** arg_types;
long i, avn;
- long nf; /* number of floating registers already used */
- long ng; /* number of general registers already used */
+ long nf; /* number of floating registers already used. */
+ long ng; /* number of general registers already used. */
ffi_cif * cif;
double temp;
+ unsigned size_al;
cif = closure->cif;
avalue = alloca(cif->nargs * sizeof(void *));
@@ -569,9 +590,9 @@ ffi_closure_helper_DARWIN (ffi_closure* closure, void * rvalue,
returns the data directly to the caller. */
if (cif->rtype->type == FFI_TYPE_STRUCT)
{
- rvalue = (void *)pgr;
- ng++;
+ rvalue = (void *) *pgr;
pgr++;
+ ng++;
}
i = 0;
@@ -582,125 +603,93 @@ ffi_closure_helper_DARWIN (ffi_closure* closure, void * rvalue,
while (i < avn)
{
switch (arg_types[i]->type)
- {
- case FFI_TYPE_SINT8:
- case FFI_TYPE_UINT8:
- /* there are 8 gpr registers used to pass values */
- if (ng < 8) {
- avalue[i] = (((char *)pgr)+3);
- ng++;
- pgr++;
- } else {
- avalue[i] = (((char *)pst)+3);
- pst++;
- }
- break;
-
- case FFI_TYPE_SINT16:
- case FFI_TYPE_UINT16:
- /* there are 8 gpr registers used to pass values */
- if (ng < 8) {
- avalue[i] = (((char *)pgr)+2);
- ng++;
- pgr++;
- } else {
- avalue[i] = (((char *)pst)+2);
- pst++;
- }
- break;
-
- case FFI_TYPE_SINT32:
- case FFI_TYPE_UINT32:
- case FFI_TYPE_POINTER:
- case FFI_TYPE_STRUCT:
- /* there are 8 gpr registers used to pass values */
- if (ng < 8) {
- avalue[i] = pgr;
- ng++;
- pgr++;
- } else {
- avalue[i] = pst;
- pst++;
- }
- break;
-
- case FFI_TYPE_SINT64:
- case FFI_TYPE_UINT64:
- /* long long ints are passed in two gpr's if available or in
- * the pst, one place is a bit odd, when a long long passes
- * the boundary between gpr and pst area we have to increment
- * the pst by one.
- */
- if (ng < 7) {
- avalue[i] = pgr;
- ng+=2;
- 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 ((ng > 7) && (nf < 13)) {
- pst++;
- }
- if (nf < 13) {
- temp = *(double*)pfr;
- *(float*)pfr = (float)temp;
- avalue[i] = pfr;
- nf++;
- pfr+=2;
- ng++;
- pgr++;
-
- } else {
- avalue[i] = pst;
- nf++;
- pst++;
- }
- break;
-
- case FFI_TYPE_DOUBLE:
- /* a double value consumes two GPRs
- *
- * there are 13 64bit floating point registers
- */
-
- if ((ng == 7) && (nf < 13)) {
- pst++; /* if only one gpr is left the double steals it */
- } else if ((ng > 7) && (nf < 13)) {
- pst+=2; /* a double consumes two GPRs in Darwin/AIX */
- }
- if (nf < 13) {
- avalue[i] = pfr;
- nf++;
- pfr+=2;
- ng+=2;
- pgr+=2;
-
- } else {
- avalue[i] = pst;
- nf++;
- pst+=2;
- }
- break;
-
- default:
- FFI_ASSERT(0);
-
- }
+ {
+ case FFI_TYPE_SINT8:
+ case FFI_TYPE_UINT8:
+ avalue[i] = (char *) pgr + 3;
+ ng++;
+ pgr++;
+ break;
+
+ case FFI_TYPE_SINT16:
+ case FFI_TYPE_UINT16:
+ avalue[i] = (char *) pgr + 2;
+ ng++;
+ pgr++;
+ break;
+ case FFI_TYPE_SINT32:
+ case FFI_TYPE_UINT32:
+ case FFI_TYPE_POINTER:
+ avalue[i] = pgr;
+ ng++;
+ pgr++;
+ break;
+
+ case FFI_TYPE_STRUCT:
+ /* 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)
+ size_al = ALIGN(arg_types[i]->size, 8);
+ if (size_al < 3 && cif->abi == FFI_DARWIN)
+ avalue[i] = (void*) pgr + 4 - size_al;
+ else
+ avalue[i] = (void*) pgr;
+ ng += (size_al + 3) / 4;
+ pgr += (size_al + 3) / 4;
+ break;
+
+ case FFI_TYPE_SINT64:
+ case FFI_TYPE_UINT64:
+ /* Long long ints are passed in two gpr's. */
+ avalue[i] = pgr;
+ ng += 2;
+ pgr += 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)
+ {
+ temp = pfr->d;
+ pfr->f = (float)temp;
+ avalue[i] = pfr;
+ pfr++;
+ }
+ else
+ {
+ avalue[i] = pgr;
+ }
+ nf++;
+ ng++;
+ pgr++;
+ break;
+
+ case FFI_TYPE_DOUBLE:
+ /* A double value consumes two GPRs.
+ There are 13 64bit floating point registers. */
+ if (nf < NUM_FPR_ARG_REGISTERS)
+ {
+ avalue[i] = pfr;
+ pfr++;
+ }
+ else
+ {
+ avalue[i] = pgr;
+ }
+ nf++;
+ ng += 2;
+ pgr += 2;
+ break;
+
+ default:
+ FFI_ASSERT(0);
+ }
i++;
}
@@ -708,5 +697,4 @@ ffi_closure_helper_DARWIN (ffi_closure* closure, void * rvalue,
/* Tell ffi_closure_ASM to perform return type promotions. */
return cif->rtype->type;
-
}