diff options
Diffstat (limited to 'libffi/src/powerpc/ffi.c')
-rw-r--r-- | libffi/src/powerpc/ffi.c | 312 |
1 files changed, 155 insertions, 157 deletions
diff --git a/libffi/src/powerpc/ffi.c b/libffi/src/powerpc/ffi.c index 29f7dba3827..c8d188777c8 100644 --- a/libffi/src/powerpc/ffi.c +++ b/libffi/src/powerpc/ffi.c @@ -1,9 +1,7 @@ /* ----------------------------------------------------------------------- ffi.c - Copyright (c) 1998 Geoffrey Keating - - PowerPC Foreign Function Interface - $Id: ffi.c,v 1.1.1.1 1998/11/29 16:48:16 green Exp $ + PowerPC Foreign Function Interface Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the @@ -67,7 +65,7 @@ enum { ASM_NEEDS_REGISTERS = 4 }; | Return address from ffi_call_SYSV 4bytes | 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_SYSV |--------------------------------------------| | @@ -84,7 +82,7 @@ enum { ASM_NEEDS_REGISTERS = 4 }; | Current backchain pointer 4 |-/ during |--------------------------------------------| <<< ffi_call_SYSV - */ +*/ /*@-exportheader@*/ void ffi_prep_args_SYSV(extended_cif *ecif, unsigned *const stack) @@ -92,7 +90,7 @@ void ffi_prep_args_SYSV(extended_cif *ecif, unsigned *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)); @@ -131,10 +129,10 @@ void ffi_prep_args_SYSV(extended_cif *ecif, unsigned *const stack) /* Deal with return values that are actually pass-by-reference. */ if (flags & FLAG_RETVAL_REFERENCE) - { - *gpr_base++ = (unsigned long)(char *)ecif->rvalue; - intarg_count++; - } + { + *gpr_base++ = (unsigned long)(char *)ecif->rvalue; + intarg_count++; + } /* Now for the arguments. */ p_argv = ecif->avalue; @@ -192,18 +190,18 @@ void ffi_prep_args_SYSV(extended_cif *ecif, unsigned *const stack) } else { - /* whoops: abi states only certain register pairs - * can be used for passing long long int - * specifically (r3,r4), (r5,r6), (r7,r8), - * (r9,r10) and if next arg is long long but - * not correct starting register of pair then skip - * until the proper starting register + /* whoops: abi states only certain register pairs + * can be used for passing long long int + * specifically (r3,r4), (r5,r6), (r7,r8), + * (r9,r10) and if next arg is long long but + * not correct starting register of pair then skip + * until the proper starting register */ - if (intarg_count%2 != 0) - { - intarg_count ++; - gpr_base++; - } + if (intarg_count%2 != 0) + { + intarg_count ++; + gpr_base++; + } *(long long *)gpr_base = *(long long *)*p_argv; gpr_base += 2; } @@ -217,7 +215,7 @@ void ffi_prep_args_SYSV(extended_cif *ecif, unsigned *const stack) struct_copy_size = ((*ptr)->size + 15) & ~0xF; copy_space -= struct_copy_size; memcpy(copy_space, (char *)*p_argv, (*ptr)->size); - + gprvalue = (unsigned long)copy_space; FFI_ASSERT(copy_space > (char *)next_arg); @@ -276,7 +274,7 @@ enum { ASM_NEEDS_REGISTERS64 = 4 }; |--------------------------------------------| | CR save area 8bytes | |--------------------------------------------| - | Previous backchain pointer 8 | stack pointer here + | Previous backchain pointer 8 | stack pointer here |--------------------------------------------|<+ <<< on entry to | Saved r28-r31 4*8 | | ffi_call_LINUX64 |--------------------------------------------| | @@ -299,7 +297,7 @@ enum { ASM_NEEDS_REGISTERS64 = 4 }; | Current backchain pointer 8 |-/ during |--------------------------------------------| <<< ffi_call_LINUX64 - */ +*/ /*@-exportheader@*/ void hidden ffi_prep_args64(extended_cif *ecif, unsigned long *const stack) @@ -314,7 +312,7 @@ void hidden ffi_prep_args64(extended_cif *ecif, unsigned long *const stack) /* 'next_arg' points at the space for gpr3, and grows upwards as we use GPR registers, then continues at rest. */ unsigned long *const gpr_base = stacktop - ASM_NEEDS_REGISTERS64 - - NUM_GPR_ARG_REGISTERS64; + - NUM_GPR_ARG_REGISTERS64; unsigned long *const gpr_end = gpr_base + NUM_GPR_ARG_REGISTERS64; unsigned long *const rest = stack + 6 + NUM_GPR_ARG_REGISTERS64; unsigned long *next_arg = gpr_base; @@ -434,7 +432,7 @@ void hidden ffi_prep_args64(extended_cif *ecif, unsigned long *const stack) case FFI_TYPE_SINT32: gprvalue = *(signed int *)*p_argv; goto putgpr; - + case FFI_TYPE_UINT64: case FFI_TYPE_SINT64: case FFI_TYPE_POINTER: @@ -466,7 +464,7 @@ ffi_status ffi_prep_cif_machdep(ffi_cif *cif) unsigned type = cif->rtype->type; if (cif->abi != FFI_LINUX64) - { + { /* All the machine-independent calculation of cif->bytes will be wrong. Redo the calculation for SYSV. */ @@ -497,10 +495,10 @@ ffi_status ffi_prep_cif_machdep(ffi_cif *cif) - 32-bit (or less) integer values are returned in gpr3; - Structures of size <= 4 bytes also returned in gpr3; - 64-bit integer values and structures between 5 and 8 bytes are returned - in gpr3 and gpr4; + in gpr3 and gpr4; - Single/double FP values are returned in fpr1; - Larger structures and long double (if not equivalent to double) values - are allocated space and a pointer is passed as the first argument. + are allocated space and a pointer is passed as the first argument. For LINUX64: - integer values in gpr3; - Structures/Unions by reference; @@ -674,31 +672,31 @@ ffi_status ffi_prep_cif_machdep(ffi_cif *cif) /*@-declundef@*/ /*@-exportheader@*/ -extern void ffi_call_SYSV(/*@out@*/ extended_cif *, - unsigned, unsigned, - /*@out@*/ unsigned *, +extern void ffi_call_SYSV(/*@out@*/ extended_cif *, + unsigned, unsigned, + /*@out@*/ unsigned *, void (*fn)()); -extern void hidden ffi_call_LINUX64(/*@out@*/ extended_cif *, +extern void hidden ffi_call_LINUX64(/*@out@*/ extended_cif *, unsigned long, unsigned long, - /*@out@*/ unsigned long *, + /*@out@*/ unsigned long *, void (*fn)()); /*@=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 ((rvalue == NULL) && (cif->rtype->type == FFI_TYPE_STRUCT)) { /*@-sysunrecog@*/ @@ -707,15 +705,15 @@ void ffi_call(/*@dependent@*/ ffi_cif *cif, } else ecif.rvalue = rvalue; - - - switch (cif->abi) + + + switch (cif->abi) { #ifndef POWERPC64 case FFI_SYSV: case FFI_GCC_SYSV: /*@-usedef@*/ - ffi_call_SYSV(&ecif, -cif->bytes, + ffi_call_SYSV(&ecif, -cif->bytes, cif->flags, ecif.rvalue, fn); /*@=usedef@*/ break; @@ -744,8 +742,8 @@ static void flush_icache(char * addr1, int size) int i; char * addr; for (i = 0; i < size; i += MIN_CACHE_LINE_SIZE) { - addr = addr1 + i; - __asm__ volatile ("icbi 0,%0;" "dcbf 0,%0;" : : "r"(addr) : "memory"); + addr = addr1 + i; + __asm__ volatile ("icbi 0,%0;" "dcbf 0,%0;" : : "r"(addr) : "memory"); } addr = addr1 + size - 1; __asm__ volatile ("icbi 0,%0;" "dcbf 0,%0;" "sync;" "isync;" : : "r"(addr) : "memory"); @@ -799,21 +797,21 @@ typedef union double d; } ffi_dblfl; -int ffi_closure_helper_SYSV (ffi_closure*, void*, unsigned long*, +int ffi_closure_helper_SYSV (ffi_closure*, void*, unsigned long*, ffi_dblfl*, unsigned long*); -/* Basically the trampoline invokes ffi_closure_SYSV, and on +/* Basically the trampoline invokes ffi_closure_SYSV, 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_SYSV invokes the + * up space for a return value, ffi_closure_SYSV invokes the * following helper function to do most of the work */ int -ffi_closure_helper_SYSV (ffi_closure* closure, void * rvalue, - unsigned long * pgr, ffi_dblfl * pfr, - unsigned long * pst) +ffi_closure_helper_SYSV (ffi_closure* closure, void * rvalue, + unsigned long * pgr, ffi_dblfl * pfr, + unsigned long * pst) { /* 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_SYSV */ @@ -825,8 +823,8 @@ ffi_closure_helper_SYSV (ffi_closure* closure, void * rvalue, long i, avn; long nf; /* number of floating registers already used */ long ng; /* number of general registers already used */ - ffi_cif * cif; - double temp; + ffi_cif * cif; + double temp; cif = closure->cif; avalue = alloca(cif->nargs * sizeof(void *)); @@ -846,7 +844,7 @@ ffi_closure_helper_SYSV (ffi_closure* closure, void * rvalue, i = 0; avn = cif->nargs; arg_types = cif->arg_types; - + /* Grab the addresses of the arguments from the stack frame. */ while (i < avn) { @@ -854,124 +852,124 @@ ffi_closure_helper_SYSV (ffi_closure* closure, void * rvalue, { 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++; - } + /* 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++; - } + /* 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: /* there are 8 gpr registers used to pass values */ - if (ng < 8) { - avalue[i] = pgr; - ng++; - pgr++; - } else { - avalue[i] = pst; - pst++; - } + if (ng < 8) { + avalue[i] = pgr; + ng++; + pgr++; + } else { + avalue[i] = pst; + pst++; + } break; case FFI_TYPE_STRUCT: - /* Structs are passed by reference. The address will appear in a + /* Structs are passed by reference. The address will appear in a gpr if it is one of the first 8 arguments. */ - if (ng < 8) { - avalue[i] = (void *) *pgr; - ng++; - pgr++; - } else { - avalue[i] = (void *) *pst; - pst++; - } + if (ng < 8) { + avalue[i] = (void *) *pgr; + ng++; + pgr++; + } else { + avalue[i] = (void *) *pst; + pst++; + } break; case FFI_TYPE_SINT64: case FFI_TYPE_UINT64: /* passing long long ints are complex, they must - * be passed in suitable register pairs such as - * (r3,r4) or (r5,r6) or (r6,r7), or (r7,r8) or (r9,r10) - * and if the entire pair aren't available then the outgoing - * parameter stack is used for both but an alignment of 8 - * must will be kept. So we must either look in pgr - * or pst to find the correct address for this type - * of parameter. - */ - if (ng < 7) { - if (ng & 0x01) { - /* skip r4, r6, r8 as starting points */ - ng++; - pgr++; - } - avalue[i] = pgr; - ng+=2; - pgr+=2; - } else { - if (((long)pst) & 4) pst++; - avalue[i] = pst; - pst+=2; - } - break; + * be passed in suitable register pairs such as + * (r3,r4) or (r5,r6) or (r6,r7), or (r7,r8) or (r9,r10) + * and if the entire pair aren't available then the outgoing + * parameter stack is used for both but an alignment of 8 + * must will be kept. So we must either look in pgr + * or pst to find the correct address for this type + * of parameter. + */ + if (ng < 7) { + if (ng & 0x01) { + /* skip r4, r6, r8 as starting points */ + ng++; + pgr++; + } + avalue[i] = pgr; + ng+=2; + pgr+=2; + } else { + if (((long)pst) & 4) pst++; + avalue[i] = pst; + pst+=2; + } + break; case FFI_TYPE_FLOAT: - /* unfortunately float values are stored as doubles - * in the ffi_closure_SYSV code (since we don't check - * the type in that routine). - */ - - /* there are 8 64bit floating point registers */ - - if (nf < 8) { - temp = pfr->d; - pfr->f = (float)temp; - avalue[i] = pfr; - nf++; - pfr++; - } else { + /* unfortunately float values are stored as doubles + * in the ffi_closure_SYSV code (since we don't check + * the type in that routine). + */ + + /* there are 8 64bit floating point registers */ + + if (nf < 8) { + temp = pfr->d; + pfr->f = (float)temp; + avalue[i] = pfr; + nf++; + pfr++; + } else { /* FIXME? here we are really changing the values - * stored in the original calling routines outgoing - * parameter stack. This is probably a really - * naughty thing to do but... - */ - avalue[i] = pst; - nf++; - pst+=1; - } + * stored in the original calling routines outgoing + * parameter stack. This is probably a really + * naughty thing to do but... + */ + avalue[i] = pst; + nf++; + pst+=1; + } break; case FFI_TYPE_DOUBLE: /* On the outgoing stack all values are aligned to 8 */ - /* there are 8 64bit floating point registers */ - - if (nf < 8) { - avalue[i] = pfr; - nf++; - pfr++; - } else { - if (((long)pst) & 4) pst++; - avalue[i] = pst; - nf++; - pst+=2; - } + /* there are 8 64bit floating point registers */ + + if (nf < 8) { + avalue[i] = pfr; + nf++; + pfr++; + } else { + if (((long)pst) & 4) pst++; + avalue[i] = pst; + nf++; + pst+=2; + } break; default: @@ -993,7 +991,7 @@ int hidden ffi_closure_helper_LINUX64 (ffi_closure*, void*, unsigned long*, ffi_dblfl*); int hidden -ffi_closure_helper_LINUX64 (ffi_closure *closure, void *rvalue, +ffi_closure_helper_LINUX64 (ffi_closure *closure, void *rvalue, unsigned long *pst, ffi_dblfl *pfr) { /* rvalue is the pointer to space for return value in closure assembly */ @@ -1004,7 +1002,7 @@ ffi_closure_helper_LINUX64 (ffi_closure *closure, void *rvalue, void **avalue; ffi_type **arg_types; long i, avn; - ffi_cif *cif; + ffi_cif *cif; ffi_dblfl *end_pfr = pfr + NUM_FPR_ARG_REGISTERS64; cif = closure->cif; @@ -1021,7 +1019,7 @@ ffi_closure_helper_LINUX64 (ffi_closure *closure, void *rvalue, i = 0; avn = cif->nargs; arg_types = cif->arg_types; - + /* Grab the addresses of the arguments from the stack frame. */ while (i < avn) { @@ -1032,7 +1030,7 @@ ffi_closure_helper_LINUX64 (ffi_closure *closure, void *rvalue, avalue[i] = (char *) pst + 7; pst++; break; - + case FFI_TYPE_SINT16: case FFI_TYPE_UINT16: avalue[i] = (char *) pst + 6; @@ -1064,13 +1062,13 @@ ffi_closure_helper_LINUX64 (ffi_closure *closure, void *rvalue, case FFI_TYPE_FLOAT: /* unfortunately float values are stored as doubles - * in the ffi_closure_LINUX64 code (since we don't check - * the type in that routine). - */ + * in the ffi_closure_LINUX64 code (since we don't check + * the type in that routine). + */ - /* there are 13 64bit floating point registers */ + /* there are 13 64bit floating point registers */ - if (pfr < end_pfr) + if (pfr < end_pfr) { double temp = pfr->d; pfr->f = (float) temp; @@ -1084,7 +1082,7 @@ ffi_closure_helper_LINUX64 (ffi_closure *closure, void *rvalue, case FFI_TYPE_DOUBLE: /* On the outgoing stack all values are aligned to 8 */ - /* there are 13 64bit floating point registers */ + /* there are 13 64bit floating point registers */ if (pfr < end_pfr) { |