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]

[m68k 04/13] libffi fixes and closure support


Hi,

The first part of this patch fixes numerous test suite failures,
especially return value handling was broken for various types.
The second part adds closure support.

One question here might be about frame information handling, older
assemblers don't support the cfi instructions, but I'd really like to
avoid having to hardcode this like other ports, as this is impossible to
maintain. Is there maybe a way to make this conditional?


2007-01-30  Roman Zippel <zippel@linux-m68k.org>

	* libffi/src/m68k/ffi.c (ffi_prep_args,ffi_prep_cif_machdep),
	  libffi/src/m68k/sysv.S (ffi_call_SYSV): fix numerous test
	  suite failures
	* libffi/src/m68k/ffi.c (ffi_prep_incoming_args_SYSV,
	  ffi_closure_SYSV_inner,ffi_prep_closure), libffi/src/m68k/sysv.S
	  (ffi_closure_SYSV,ffi_closure_struct_SYSV): New, add closure support

---
 libffi/src/m68k/ffi.c       |  214 ++++++++++++++++++++++++++++++++------------
 libffi/src/m68k/ffitarget.h |    3 
 libffi/src/m68k/sysv.S      |  126 +++++++++++++++++++++++--
 3 files changed, 273 insertions(+), 70 deletions(-)

Index: egcs/libffi/src/m68k/ffi.c
===================================================================
--- egcs.orig/libffi/src/m68k/ffi.c
+++ egcs/libffi/src/m68k/ffi.c
@@ -8,11 +8,24 @@
 #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.  */
 
-static void *
+void *
 ffi_prep_args (void *stack, extended_cif *ecif)
 {
   unsigned int i;
@@ -24,7 +37,7 @@ ffi_prep_args (void *stack, extended_cif
   argp = stack;
 
   if (ecif->cif->rtype->type == FFI_TYPE_STRUCT
-      && ecif->cif->rtype->size > 8)
+      && !ecif->cif->flags)
     struct_value_ptr = ecif->rvalue;
   else
     struct_value_ptr = NULL;
@@ -37,44 +50,47 @@ ffi_prep_args (void *stack, extended_cif
     {
       size_t z;
 
-      /* Align if necessary.  */
-      if (((*p_arg)->alignment - 1) & (unsigned) argp)
-	argp = (char *) ALIGN (argp, (*p_arg)->alignment);
-
-	  z = (*p_arg)->size;
-	  if (z < sizeof (int))
+      z = (*p_arg)->size;
+      if (z < sizeof (int))
+	{
+	  switch ((*p_arg)->type)
 	    {
-	      switch ((*p_arg)->type)
-		{
-		case FFI_TYPE_SINT8:
-		  *(signed int *) argp = (signed int) *(SINT8 *) *p_argv;
-		  break;
-
-		case FFI_TYPE_UINT8:
-		  *(unsigned int *) argp = (unsigned int) *(UINT8 *) *p_argv;
-		  break;
-
-		case FFI_TYPE_SINT16:
-		  *(signed int *) argp = (signed int) *(SINT16 *) *p_argv;
-		  break;
-
-		case FFI_TYPE_UINT16:
-		  *(unsigned int *) argp = (unsigned int) *(UINT16 *) *p_argv;
-		  break;
-
-		case FFI_TYPE_STRUCT:
-		  memcpy (argp + sizeof (int) - z, *p_argv, z);
-		  break;
-
-		default:
-		  FFI_ASSERT (0);
-		}
-	      z = sizeof (int);
+	    case FFI_TYPE_SINT8:
+	      *(signed int *) argp = (signed int) *(SINT8 *) *p_argv;
+	      break;
+
+	    case FFI_TYPE_UINT8:
+	      *(unsigned int *) argp = (unsigned int) *(UINT8 *) *p_argv;
+	      break;
+
+	    case FFI_TYPE_SINT16:
+	      *(signed int *) argp = (signed int) *(SINT16 *) *p_argv;
+	      break;
+
+	    case FFI_TYPE_UINT16:
+	      *(unsigned int *) argp = (unsigned int) *(UINT16 *) *p_argv;
+	      break;
+
+	    case FFI_TYPE_STRUCT:
+	      memcpy (argp + sizeof (int) - z, *p_argv, z);
+	      break;
+
+	    default:
+	      FFI_ASSERT (0);
 	    }
-	  else
-	    memcpy (argp, *p_argv, z);
-	  p_argv++;
-	  argp += z;
+	  z = sizeof (int);
+	}
+      else
+	{
+	  memcpy (argp, *p_argv, z);
+
+	  /* Align if necessary.  */
+	  if ((sizeof(int) - 1) & z)
+	    z = ALIGN(z, sizeof(int));
+	}
+
+      p_argv++;
+      argp += z;
     }
 
   return struct_value_ptr;
@@ -86,7 +102,8 @@ ffi_prep_args (void *stack, extended_cif
 #define CIF_FLAGS_DOUBLE	8
 #define CIF_FLAGS_LDOUBLE	16
 #define CIF_FLAGS_POINTER	32
-#define CIF_FLAGS_STRUCT	64
+#define CIF_FLAGS_STRUCT1	64
+#define CIF_FLAGS_STRUCT2	128
 
 /* Perform machine dependent cif processing */
 ffi_status
@@ -100,12 +117,24 @@ ffi_prep_cif_machdep (ffi_cif *cif)
       break;
 
     case FFI_TYPE_STRUCT:
-      if (cif->rtype->size > 4 && cif->rtype->size <= 8)
-	cif->flags = CIF_FLAGS_DINT;
-      else if (cif->rtype->size <= 4)
-	cif->flags = CIF_FLAGS_STRUCT;
-      else
-	cif->flags = 0;
+      switch (cif->rtype->size)
+	{
+	case 1:
+	  cif->flags = CIF_FLAGS_STRUCT1;
+	  break;
+	case 2:
+	  cif->flags = CIF_FLAGS_STRUCT2;
+	  break;
+	case 4:
+	  cif->flags = CIF_FLAGS_INT;
+	  break;
+	case 8:
+	  cif->flags = CIF_FLAGS_DINT;
+	  break;
+	default:
+	  cif->flags = 0;
+	  break;
+	}
       break;
 
     case FFI_TYPE_FLOAT:
@@ -137,11 +166,6 @@ ffi_prep_cif_machdep (ffi_cif *cif)
   return FFI_OK;
 }
 
-extern void ffi_call_SYSV (void *(*) (void *, extended_cif *), 
-			   extended_cif *, 
-			   unsigned, unsigned, unsigned,
-			   void *, void (*fn) ());
-
 void
 ffi_call (ffi_cif *cif, void (*fn) (), void *rvalue, void **avalue)
 {
@@ -149,7 +173,7 @@ ffi_call (ffi_cif *cif, void (*fn) (), v
 
   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.  */
 
@@ -159,13 +183,11 @@ ffi_call (ffi_cif *cif, void (*fn) (), v
     ecif.rvalue = alloca (cif->rtype->size);
   else
     ecif.rvalue = rvalue;
-    
-  
-  switch (cif->abi) 
+
+  switch (cif->abi)
     {
     case FFI_SYSV:
-      ffi_call_SYSV (ffi_prep_args, &ecif, cif->bytes, 
-		     cif->flags, cif->rtype->size * 8,
+      ffi_call_SYSV (&ecif, cif->bytes, cif->flags,
 		     ecif.rvalue, fn);
       break;
 
@@ -174,3 +196,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: egcs/libffi/src/m68k/ffitarget.h
===================================================================
--- egcs.orig/libffi/src/m68k/ffitarget.h
+++ egcs/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: egcs/libffi/src/m68k/sysv.S
===================================================================
--- egcs.orig/libffi/src/m68k/sysv.S
+++ egcs/libffi/src/m68k/sysv.S
@@ -12,36 +12,44 @@
 
 	.globl	ffi_call_SYSV
 	.type	ffi_call_SYSV,@function
+	.align	4
 
 ffi_call_SYSV:
+	.cfi_startproc
 	link	%fp,#0
+	.cfi_offset	14,-8
+	.cfi_def_cfa	14,8
 	move.l	%d2,-(%sp)
+	.cfi_offset	2,-12
 
 	| Make room for all of the new args.
-	sub.l	16(%fp),%sp
+	sub.l	12(%fp),%sp
 
 	| Call ffi_prep_args
-	move.l	12(%fp),-(%sp)
+	move.l	8(%fp),-(%sp)
 	pea	4(%sp)
-	move.l	8(%fp),%a0
-	jsr	(%a0)
+#if !defined __PIC__
+	jsr	ffi_prep_args
+#else
+	bsr.l	ffi_prep_args@PLTPC
+#endif
 	addq.l	#8,%sp	
 
 	| Pass pointer to struct value, if any
 	move.l	%a0,%a1
 
 	| Call the function
-	move.l	32(%fp),%a0
+	move.l	24(%fp),%a0
 	jsr	(%a0)
 
 	| Remove the space we pushed for the args
-	add.l	16(%fp),%sp
+	add.l	12(%fp),%sp
 
 	| Load the pointer to storage for the return value
-	move.l	28(%fp),%a1
+	move.l	20(%fp),%a1
 
 	| Load the return type code 
-	move.l	20(%fp),%d2
+	move.l	16(%fp),%d2
 
 	| If the return value pointer is NULL, assume no return value.
 	tst.l	%a1
@@ -79,19 +87,111 @@ retlongdouble:
 
 retpointer:
 	btst	#5,%d2
-	jbeq	retstruct
+	jbeq	retstruct1
 	move.l	%a0,(%a1)
 	jbra	epilogue
 
-retstruct:
+retstruct1:
 	btst	#6,%d2
+	jbeq	retstruct2
+	move.b	%d0,(%a1)
+	jbra	epilogue
+
+retstruct2:
+	btst	#7,%d2
 	jbeq	noretval
-	move.l	24(%fp),%d2
-	bfins	%d0,(%a1){#0,%d2}
+	move.w	%d0,(%a1)
 
 noretval:
 epilogue:
 	move.l	(%sp)+,%d2
-	unlk	%a6
+	unlk	%fp
 	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]