This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[patch 3/3] libffi/m68k: add closure support


libffi/
2007-xx-xx  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.

---
 libffi/src/m68k/ffi.c       |   84 ++++++++++++++++++++++++++++++++++++++++++
 libffi/src/m68k/ffitarget.h |    3 +
 libffi/src/m68k/sysv.S      |   86 ++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 172 insertions(+), 1 deletion(-)

Index: gcc/libffi/src/m68k/ffi.c
===================================================================
--- gcc.orig/libffi/src/m68k/ffi.c
+++ gcc/libffi/src/m68k/ffi.c
@@ -8,6 +8,9 @@
 #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,
@@ -16,6 +16,10 @@ 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.  */
@@ -191,3 +195,83 @@ ffi_call (ffi_cif *cif, void (*fn) (), v
       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 (ffi_closure* closure,
+		  ffi_cif* cif,
+		  void (*fun)(ffi_cif*,void*,void**,void*),
+		  void *user_data)
+{
+  FFI_ASSERT (cif->abi == FFI_SYSV);
+
+  *(unsigned short *)closure->tramp = 0x207c;
+  *(void **)(closure->tramp + 2) = closure;
+  *(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, closure->tramp, FLUSH_SCOPE_LINE,
+	  FLUSH_CACHE_BOTH, FFI_TRAMPOLINE_SIZE);
+
+  closure->cif  = cif;
+  closure->user_data = user_data;
+  closure->fun  = fun;
+
+  return FFI_OK;
+}
+
Index: gcc/libffi/src/m68k/ffitarget.h
===================================================================
--- gcc.orig/libffi/src/m68k/ffitarget.h
+++ gcc/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
Index: gcc/libffi/src/m68k/sysv.S
===================================================================
--- gcc.orig/libffi/src/m68k/sysv.S
+++ gcc/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

--


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]