ffi.c (ffi_prep_incoming_args_SYSV, [...]): New, add closure support.
authorRoman Zippel <zippel@linux-m68k.org>
Thu, 10 May 2007 21:29:04 +0000 (21:29 +0000)
committerRoman Zippel <zippel@gcc.gnu.org>
Thu, 10 May 2007 21:29:04 +0000 (21:29 +0000)
* 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.

From-SVN: r124601

libffi/ChangeLog
libffi/src/m68k/ffi.c
libffi/src/m68k/ffitarget.h
libffi/src/m68k/sysv.S

index 7512e8124c1b7dc9dacc587f1a42563471314622..1f49a27e555ca2cfdd065c94db98be32c882a0de 100644 (file)
@@ -1,3 +1,11 @@
+2007-05-10  Roman Zippel <zippel@linux-m68k.org>
+
+       * 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 <zippel@linux-m68k.org>
 
        * configure.ac (HAVE_AS_CFI_PSEUDO_OP): New test.
index 5b9650e0ae5a56c5abcae5cfe7f2a3195eade577..600cf20527ff9d1c81fb5c9ad8010e8d82a88c03 100644 (file)
@@ -8,11 +8,18 @@
 #include <ffi_common.h>
 
 #include <stdlib.h>
+#include <unistd.h>
+#include <sys/syscall.h>
+#include <asm/cachectl.h>
 
 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;
+}
+
index aca7facc50a8db2c862e530d5d8e915679dd2b81..9a072db404fd07e5a0d4048d395f6329cfce6f9b 100644 (file)
@@ -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
index a3d9a4f7ff7a16110d46989488f62094ba8590ef..d2a4ff1c64a756686c0427ce936f9728aaf5b610 100644 (file)
@@ -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