diff --git a/libffi/ChangeLog b/libffi/ChangeLog index 7512e8124c1..1f49a27e555 100644 --- a/libffi/ChangeLog +++ b/libffi/ChangeLog @@ -1,3 +1,11 @@ +2007-05-10 Roman Zippel + + * src/m68k/ffi.c (ffi_prep_incoming_args_SYSV, + ffi_closure_SYSV_inner,ffi_prep_closure): New, add closure support. + * src/m68k/sysv.S(ffi_closure_SYSV,ffi_closure_struct_SYSV): Likewise. + * src/m68k/ffitarget.h (FFI_TRAMPOLINE_SIZE): Likewise. + (FFI_CLOSURES): Enable closure support. + 2007-05-10 Roman Zippel * configure.ac (HAVE_AS_CFI_PSEUDO_OP): New test. diff --git a/libffi/src/m68k/ffi.c b/libffi/src/m68k/ffi.c index 5b9650e0ae5..600cf20527f 100644 --- a/libffi/src/m68k/ffi.c +++ b/libffi/src/m68k/ffi.c @@ -8,11 +8,18 @@ #include #include +#include +#include +#include void ffi_call_SYSV (extended_cif *, unsigned, unsigned, void *, void (*fn) ()); void *ffi_prep_args (void *stack, extended_cif *ecif); +void ffi_closure_SYSV (ffi_closure *); +void ffi_closure_struct_SYSV (ffi_closure *); +unsigned int ffi_closure_SYSV_inner (ffi_closure *closure, + void *resp, void *args); /* ffi_prep_args is called by the assembly routine once stack space has been allocated for the function's arguments. */ @@ -188,3 +195,84 @@ ffi_call (ffi_cif *cif, void (*fn) (), void *rvalue, void **avalue) break; } } + +static void +ffi_prep_incoming_args_SYSV (char *stack, void **avalue, ffi_cif *cif) +{ + unsigned int i; + void **p_argv; + char *argp; + ffi_type **p_arg; + + argp = stack; + p_argv = avalue; + + for (i = cif->nargs, p_arg = cif->arg_types; (i != 0); i--, p_arg++) + { + size_t z; + + z = (*p_arg)->size; + if (z <= 4) + { + *p_argv = (void *) (argp + 4 - z); + + z = 4; + } + else + { + *p_argv = (void *) argp; + + /* Align if necessary */ + if ((sizeof(int) - 1) & z) + z = ALIGN(z, sizeof(int)); + } + + p_argv++; + argp += z; + } +} + +unsigned int +ffi_closure_SYSV_inner (ffi_closure *closure, void *resp, void *args) +{ + ffi_cif *cif; + void **arg_area; + + cif = closure->cif; + arg_area = (void**) alloca (cif->nargs * sizeof (void *)); + + ffi_prep_incoming_args_SYSV(args, arg_area, cif); + + (closure->fun) (cif, resp, arg_area, closure->user_data); + + return cif->flags; +} + +ffi_status +ffi_prep_closure_loc (ffi_closure* closure, + ffi_cif* cif, + void (*fun)(ffi_cif*,void*,void**,void*), + void *user_data, + void *codeloc) +{ + FFI_ASSERT (cif->abi == FFI_SYSV); + + *(unsigned short *)closure->tramp = 0x207c; + *(void **)(closure->tramp + 2) = codeloc; + *(unsigned short *)(closure->tramp + 6) = 0x4ef9; + if (cif->rtype->type == FFI_TYPE_STRUCT + && !cif->flags) + *(void **)(closure->tramp + 8) = ffi_closure_struct_SYSV; + else + *(void **)(closure->tramp + 8) = ffi_closure_SYSV; + + syscall(SYS_cacheflush, codeloc, FLUSH_SCOPE_LINE, + FLUSH_CACHE_BOTH, FFI_TRAMPOLINE_SIZE); + + closure->cif = cif; + closure->user_data = user_data; + closure->fun = fun; + + return FFI_OK; +} + diff --git a/libffi/src/m68k/ffitarget.h b/libffi/src/m68k/ffitarget.h index aca7facc50a..9a072db404f 100644 --- a/libffi/src/m68k/ffitarget.h +++ b/libffi/src/m68k/ffitarget.h @@ -40,7 +40,8 @@ typedef enum ffi_abi { /* ---- Definitions for closures ----------------------------------------- */ -#define FFI_CLOSURES 0 +#define FFI_CLOSURES 1 +#define FFI_TRAMPOLINE_SIZE 16 #define FFI_NATIVE_RAW_API 0 #endif diff --git a/libffi/src/m68k/sysv.S b/libffi/src/m68k/sysv.S index a3d9a4f7ff7..d2a4ff1c64a 100644 --- a/libffi/src/m68k/sysv.S +++ b/libffi/src/m68k/sysv.S @@ -121,3 +121,89 @@ epilogue: rts CFI_ENDPROC() .size ffi_call_SYSV,.-ffi_call_SYSV + + .globl ffi_closure_SYSV + .type ffi_closure_SYSV, @function + .align 4 + +ffi_closure_SYSV: + CFI_STARTPROC() + link %fp,#-12 + CFI_OFFSET(14,-8) + CFI_DEF_CFA(14,8) + move.l %sp,-12(%fp) + pea 8(%fp) + pea -12(%fp) + move.l %a0,-(%sp) +#if !defined __PIC__ + jsr ffi_closure_SYSV_inner +#else + bsr.l ffi_closure_SYSV_inner@PLTPC +#endif + + lsr.l #1,%d0 + jne 1f + jcc .Lcls_epilogue + move.l -12(%fp),%d0 +.Lcls_epilogue: + unlk %fp + rts +1: + lea -12(%fp),%a0 + lsr.l #2,%d0 + jne 1f + jcs .Lcls_ret_float + move.l (%a0)+,%d0 + move.l (%a0),%d1 + jra .Lcls_epilogue +.Lcls_ret_float: + fmove.s (%a0),%fp0 + jra .Lcls_epilogue +1: + lsr.l #2,%d0 + jne 1f + jcs .Lcls_ret_ldouble + fmove.d (%a0),%fp0 + jra .Lcls_epilogue +.Lcls_ret_ldouble: + fmove.x (%a0),%fp0 + jra .Lcls_epilogue +1: + lsr.l #2,%d0 + jne .Lcls_ret_struct2 + jcs .Lcls_ret_struct1 + move.l (%a0),%a0 + move.l %a0,%d0 + jra .Lcls_epilogue +.Lcls_ret_struct1: + move.b (%a0),%d0 + jra .Lcls_epilogue +.Lcls_ret_struct2: + move.w (%a0),%d0 + jra .Lcls_epilogue + CFI_ENDPROC() + + .size ffi_closure_SYSV,.-ffi_closure_SYSV + + .globl ffi_closure_struct_SYSV + .type ffi_closure_struct_SYSV, @function + .align 4 + +ffi_closure_struct_SYSV: + CFI_STARTPROC() + link %fp,#0 + CFI_OFFSET(14,-8) + CFI_DEF_CFA(14,8) + move.l %sp,-12(%fp) + pea 8(%fp) + move.l %a1,-(%sp) + move.l %a0,-(%sp) +#if !defined __PIC__ + jsr ffi_closure_SYSV_inner +#else + bsr.l ffi_closure_SYSV_inner@PLTPC +#endif + unlk %fp + rts + CFI_ENDPROC() + .size ffi_closure_struct_SYSV,.-ffi_closure_struct_SYSV