diff options
Diffstat (limited to 'libffi/src/powerpc/ffi_darwin.c')
-rw-r--r-- | libffi/src/powerpc/ffi_darwin.c | 536 |
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; - } |