diff options
Diffstat (limited to 'libffi/src/pa/ffi.c')
-rw-r--r-- | libffi/src/pa/ffi.c | 216 |
1 files changed, 59 insertions, 157 deletions
diff --git a/libffi/src/pa/ffi.c b/libffi/src/pa/ffi.c index 0da8184..95e6694 100644 --- a/libffi/src/pa/ffi.c +++ b/libffi/src/pa/ffi.c @@ -1,6 +1,5 @@ /* ----------------------------------------------------------------------- - ffi.c - (c) 2016 John David Anglin - (c) 2011 Anthony Green + ffi.c - (c) 2011 Anthony Green (c) 2008 Red Hat, Inc. (c) 2006 Free Software Foundation, Inc. (c) 2003-2004 Randolph Chung <tausq@debian.org> @@ -52,8 +51,7 @@ #define debug(lvl, x...) do { if (lvl <= DEBUG_LEVEL) { printf(x); } } while (0) -static inline int -ffi_struct_type (ffi_type *t) +static inline int ffi_struct_type(ffi_type *t) { size_t sz = t->size; @@ -141,8 +139,7 @@ ffi_struct_type (ffi_type *t) NOTE: We load floating point args in this function... that means we assume gcc will not mess with fp regs in here. */ -void -ffi_prep_args_pa32 (UINT32 *stack, extended_cif *ecif, unsigned bytes) +void ffi_prep_args_pa32(UINT32 *stack, extended_cif *ecif, unsigned bytes) { register unsigned int i; register ffi_type **p_arg; @@ -278,8 +275,7 @@ ffi_prep_args_pa32 (UINT32 *stack, extended_cif *ecif, unsigned bytes) return; } -static void -ffi_size_stack_pa32 (ffi_cif *cif) +static void ffi_size_stack_pa32(ffi_cif *cif) { ffi_type **ptr; int i; @@ -320,8 +316,7 @@ ffi_size_stack_pa32 (ffi_cif *cif) } /* Perform machine dependent cif processing. */ -ffi_status -ffi_prep_cif_machdep (ffi_cif *cif) +ffi_status ffi_prep_cif_machdep(ffi_cif *cif) { /* Set the return type flag */ switch (cif->rtype->type) @@ -374,13 +369,11 @@ ffi_prep_cif_machdep (ffi_cif *cif) return FFI_OK; } -extern void ffi_call_pa32 (void (*)(UINT32 *, extended_cif *, unsigned), - extended_cif *, unsigned, unsigned, unsigned *, - void (*fn)(void), void *closure); +extern void ffi_call_pa32(void (*)(UINT32 *, extended_cif *, unsigned), + extended_cif *, unsigned, unsigned, unsigned *, + void (*fn)(void)); -static void -ffi_call_int (ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue, - void *closure) +void ffi_call(ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue) { extended_cif ecif; @@ -408,8 +401,8 @@ ffi_call_int (ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue, { case FFI_PA32: debug(3, "Calling ffi_call_pa32: ecif=%p, bytes=%u, flags=%u, rvalue=%p, fn=%p\n", &ecif, cif->bytes, cif->flags, ecif.rvalue, (void *)fn); - ffi_call_pa32 (ffi_prep_args_pa32, &ecif, cif->bytes, - cif->flags, ecif.rvalue, fn, closure); + ffi_call_pa32(ffi_prep_args_pa32, &ecif, cif->bytes, + cif->flags, ecif.rvalue, fn); break; default: @@ -418,60 +411,35 @@ ffi_call_int (ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue, } } -void -ffi_call (ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue) -{ - ffi_call_int (cif, fn, rvalue, avalue, NULL); -} - -void -ffi_call_go (ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue, - void *closure) -{ - ffi_call_int (cif, fn, rvalue, avalue, closure); -} - #if FFI_CLOSURES /* This is more-or-less an inverse of ffi_call -- we have arguments on the stack, and we need to fill them into a cif structure and invoke the user function. This really ought to be in asm to make sure the compiler doesn't do things we don't expect. */ -ffi_status -ffi_closure_inner_pa32 (void *closure, UINT32 *stack, int closure_type) +ffi_status ffi_closure_inner_pa32(ffi_closure *closure, UINT32 *stack) { ffi_cif *cif; - void (*fun)(ffi_cif *,void *,void **,void *); - void *user_data; void **avalue; void *rvalue; - UINT32 ret[2]; /* function can return up to 64-bits in registers */ + /* Functions can return up to 64-bits in registers. Return address + must be double word aligned. */ + union { double rd; UINT32 ret[2]; } u; ffi_type **p_arg; char *tmp; int i, avn; unsigned int slot = FIRST_ARG_SLOT; register UINT32 r28 asm("r28"); + ffi_closure *c = (ffi_closure *)FFI_RESTORE_PTR (closure); - /* A non-zero closure type indicates a go closure. */ - if (closure_type) - { - cif = ((ffi_go_closure *)closure)->cif; - fun = ((ffi_go_closure *)closure)->fun; - user_data = closure; - } - else - { - cif = ((ffi_closure *)closure)->cif; - fun = ((ffi_closure *)closure)->fun; - user_data = ((ffi_closure *)closure)->user_data; - } + cif = closure->cif; /* If returning via structure, callee will write to our pointer. */ if (cif->flags == FFI_TYPE_STRUCT) rvalue = (void *)r28; else - rvalue = &ret[0]; + rvalue = &u; - avalue = (void **) alloca (cif->nargs * FFI_SIZEOF_ARG); + avalue = (void **)alloca(cif->nargs * FFI_SIZEOF_ARG); avn = cif->nargs; p_arg = cif->arg_types; @@ -564,35 +532,35 @@ ffi_closure_inner_pa32 (void *closure, UINT32 *stack, int closure_type) } /* Invoke the closure. */ - fun (cif, rvalue, avalue, user_data); + (c->fun) (cif, rvalue, avalue, c->user_data); - debug(3, "after calling function, ret[0] = %08x, ret[1] = %08x\n", ret[0], - ret[1]); + debug(3, "after calling function, ret[0] = %08x, ret[1] = %08x\n", u.ret[0], + u.ret[1]); /* Store the result using the lower 2 bytes of the flags. */ switch (cif->flags) { case FFI_TYPE_UINT8: - *(stack - FIRST_ARG_SLOT) = (UINT8)(ret[0] >> 24); + *(stack - FIRST_ARG_SLOT) = (UINT8)(u.ret[0] >> 24); break; case FFI_TYPE_SINT8: - *(stack - FIRST_ARG_SLOT) = (SINT8)(ret[0] >> 24); + *(stack - FIRST_ARG_SLOT) = (SINT8)(u.ret[0] >> 24); break; case FFI_TYPE_UINT16: - *(stack - FIRST_ARG_SLOT) = (UINT16)(ret[0] >> 16); + *(stack - FIRST_ARG_SLOT) = (UINT16)(u.ret[0] >> 16); break; case FFI_TYPE_SINT16: - *(stack - FIRST_ARG_SLOT) = (SINT16)(ret[0] >> 16); + *(stack - FIRST_ARG_SLOT) = (SINT16)(u.ret[0] >> 16); break; case FFI_TYPE_INT: case FFI_TYPE_SINT32: case FFI_TYPE_UINT32: - *(stack - FIRST_ARG_SLOT) = ret[0]; + *(stack - FIRST_ARG_SLOT) = u.ret[0]; break; case FFI_TYPE_SINT64: case FFI_TYPE_UINT64: - *(stack - FIRST_ARG_SLOT) = ret[0]; - *(stack - FIRST_ARG_SLOT - 1) = ret[1]; + *(stack - FIRST_ARG_SLOT) = u.ret[0]; + *(stack - FIRST_ARG_SLOT - 1) = u.ret[1]; break; case FFI_TYPE_DOUBLE: @@ -612,7 +580,7 @@ ffi_closure_inner_pa32 (void *closure, UINT32 *stack, int closure_type) case FFI_TYPE_SMALL_STRUCT4: tmp = (void*)(stack - FIRST_ARG_SLOT); tmp += 4 - cif->rtype->size; - memcpy((void*)tmp, &ret[0], cif->rtype->size); + memcpy((void*)tmp, &u, cif->rtype->size); break; case FFI_TYPE_SMALL_STRUCT5: @@ -633,7 +601,7 @@ ffi_closure_inner_pa32 (void *closure, UINT32 *stack, int closure_type) } memset (ret2, 0, sizeof (ret2)); - memcpy ((char *)ret2 + off, ret, 8 - off); + memcpy ((char *)ret2 + off, &u, 8 - off); *(stack - FIRST_ARG_SLOT) = ret2[0]; *(stack - FIRST_ARG_SLOT - 1) = ret2[1]; @@ -656,7 +624,6 @@ ffi_closure_inner_pa32 (void *closure, UINT32 *stack, int closure_type) cif specifies the argument and result types for fun. The cif must already be prep'ed. */ -extern void ffi_go_closure_pa32(void); extern void ffi_closure_pa32(void); ffi_status @@ -666,107 +633,42 @@ ffi_prep_closure_loc (ffi_closure* closure, void *user_data, void *codeloc) { - UINT32 *tramp = (UINT32 *)(closure->tramp); -#ifdef PA_HPUX - UINT32 *tmp; -#endif - - if (cif->abi != FFI_PA32) - return FFI_BAD_ABI; - - /* Make a small trampoline that will branch to our - handler function. Use PC-relative addressing. */ - -#ifdef PA_LINUX - tramp[0] = 0xeaa00000; /* b,l .+8,%r21 ; %r21 <- pc+8 */ - tramp[1] = 0xd6a01c1e; /* depi 0,31,2,%r21 ; mask priv bits */ - tramp[2] = 0x4aa10028; /* ldw 20(%r21),%r1 ; load plabel */ - tramp[3] = 0x36b53ff1; /* ldo -8(%r21),%r21 ; get closure addr */ - tramp[4] = 0x0c201096; /* ldw 0(%r1),%r22 ; address of handler */ - tramp[5] = 0xeac0c000; /* bv%r0(%r22) ; branch to handler */ - tramp[6] = 0x0c281093; /* ldw 4(%r1),%r19 ; GP of handler */ - tramp[7] = ((UINT32)(ffi_closure_pa32) & ~2); - - /* Flush d/icache -- have to flush up 2 two lines because of - alignment. */ - __asm__ volatile( - "fdc 0(%0)\n\t" - "fdc %1(%0)\n\t" - "fic 0(%%sr4, %0)\n\t" - "fic %1(%%sr4, %0)\n\t" - "sync\n\t" - "nop\n\t" - "nop\n\t" - "nop\n\t" - "nop\n\t" - "nop\n\t" - "nop\n\t" - "nop\n" - : - : "r"((unsigned long)tramp & ~31), - "r"(32 /* stride */) - : "memory"); -#endif + ffi_closure *c = (ffi_closure *)FFI_RESTORE_PTR (closure); -#ifdef PA_HPUX - tramp[0] = 0xeaa00000; /* b,l .+8,%r21 ; %r21 <- pc+8 */ - tramp[1] = 0xd6a01c1e; /* depi 0,31,2,%r21 ; mask priv bits */ - tramp[2] = 0x4aa10038; /* ldw 28(%r21),%r1 ; load plabel */ - tramp[3] = 0x36b53ff1; /* ldo -8(%r21),%r21 ; get closure addr */ - tramp[4] = 0x0c201096; /* ldw 0(%r1),%r22 ; address of handler */ - tramp[5] = 0x02c010b4; /* ldsid (%r22),%r20 ; load space id */ - tramp[6] = 0x00141820; /* mtsp %r20,%sr0 ; into %sr0 */ - tramp[7] = 0xe2c00000; /* be 0(%sr0,%r22) ; branch to handler */ - tramp[8] = 0x0c281093; /* ldw 4(%r1),%r19 ; GP of handler */ - tramp[9] = ((UINT32)(ffi_closure_pa32) & ~2); - - /* Flush d/icache -- have to flush three lines because of alignment. */ - __asm__ volatile( - "copy %1,%0\n\t" - "fdc,m %2(%0)\n\t" - "fdc,m %2(%0)\n\t" - "fdc,m %2(%0)\n\t" - "ldsid (%1),%0\n\t" - "mtsp %0,%%sr0\n\t" - "copy %1,%0\n\t" - "fic,m %2(%%sr0,%0)\n\t" - "fic,m %2(%%sr0,%0)\n\t" - "fic,m %2(%%sr0,%0)\n\t" - "sync\n\t" - "nop\n\t" - "nop\n\t" - "nop\n\t" - "nop\n\t" - "nop\n\t" - "nop\n\t" - "nop\n" - : "=&r" ((unsigned long)tmp) - : "r" ((unsigned long)tramp & ~31), - "r" (32/* stride */) - : "memory"); -#endif + /* The layout of a function descriptor. A function pointer with the PLABEL + bit set points to a function descriptor. */ + struct pa32_fd + { + UINT32 code_pointer; + UINT32 gp; + }; - closure->cif = cif; - closure->user_data = user_data; - closure->fun = fun; + struct ffi_pa32_trampoline_struct + { + UINT32 code_pointer; /* Pointer to ffi_closure_unix. */ + UINT32 fake_gp; /* Pointer to closure, installed as gp. */ + UINT32 real_gp; /* Real gp value. */ + }; - return FFI_OK; -} + struct ffi_pa32_trampoline_struct *tramp; + struct pa32_fd *fd; -#ifdef FFI_GO_CLOSURES -ffi_status -ffi_prep_go_closure (ffi_go_closure *closure, - ffi_cif *cif, - void (*fun)(ffi_cif *, void *, void **, void *)) -{ if (cif->abi != FFI_PA32) return FFI_BAD_ABI; - closure->tramp = &ffi_go_closure_pa32; - closure->cif = cif; - closure->fun = fun; + /* Get function descriptor address for ffi_closure_pa32. */ + fd = (struct pa32_fd *)((UINT32)ffi_closure_pa32 & ~3); + + /* Setup trampoline. */ + tramp = (struct ffi_pa32_trampoline_struct *)c->tramp; + tramp->code_pointer = fd->code_pointer; + tramp->fake_gp = (UINT32)codeloc & ~3; + tramp->real_gp = fd->gp; + + c->cif = cif; + c->user_data = user_data; + c->fun = fun; return FFI_OK; } -#endif /* FFI_GO_CLOSURES */ #endif |