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]

Re: [PATCH] libffi support for CRIS


V tor, 26.10.2004 ob 04:27 je Hans-Peter Nilsson napisal(a):
> Over to the actual patch: Please use the "-p" diff option ("diff
> -up", not just "diff -u").  Sending the patch as an attachment
> (rather than in-body) made it harder to comment on each piece
> (to the crowd: comments on my choice of mailer to /dev/null).
OK. I will do it like that.

> Same comment applies as to boehm-gc, CRIS32 is a bit confusing.
> I'd rather just use the predefined __CRIS__ and __linux__ (eh,
> make that __gnu_linux__ ;-) and not define anything in
> configury.  Or maybe define CRIS_LINUX.
I choose CRIS_LINUX.

> I can't approve this as-is, as it touches target-independent
> libffi bits (which I anyway think should be handled with less
> #ifdefs).
I moved the stuff to target-depended part of libffi.

> > +++ gcc_cris/libffi/configure.ac	2004-10-25 12:58:24.102724416 +0200
> > @@ -68,6 +68,7 @@
> >  rs6000-*-aix*) TARGET=POWERPC_AIX; TARGETDIR=powerpc;;
> >  arm*-*-linux-*) TARGET=ARM; TARGETDIR=arm;;
> >  arm*-*-netbsdelf* | arm*-*-knetbsd*-gnu) TARGET=ARM; TARGETDIR=arm;;
> > +cris*-*-linux-*) TARGET=CRIS32; TARGETDIR=cris;;
> 
> Better use "cris-..." and even "cris-*-linux*".  The ARM port is
> not to be followed; it has other suffixes, the CRIS port in FSF
> just uses "cris".  (At present that is, "crisv32" coming, FWIW.)
Fixed.

> +++ gcc_cris/libffi/src/cris/ffi.c	2004-10-25 12:58:24.103724264 +0200
> > +/* -----------------------------------------------------------------------
> > +   ffi.c - Copyright (c) 1998 Cygnus Solutions
> > +           Copyright (c) 2004 Simon Posnjak
> 
> I doubt Cygnus Solutions should be credited here.
Yes, they should be be, because the file came from arm/ffi.c and was
adopted for cris. (The copyright headers are correct on all files)

> > +//  if (ecif->cif->rtype->type == FFI_TYPE_STRUCT ) {
> > +//    *(void **) argp = ecif->rvalue;
> > +//    argp += 4;
> > +//  }
> 
> No commented-out code please.  (Why is it there at all for this new code?
> Was arm/ffi.c copied here?)
Oops, missed that one.

> > +      /* Align if necessary */
> > +      if (((*p_arg)->alignment - 1) & (unsigned) argp)
> > +	{
> > +	  argp = (char *) ALIGN (argp, (*p_arg)->alignment);
> > +	}
> 
> Please explain why alignment can be necessary here.  Is it part
> of the libffi API?  Nothing needs more than byte-alignment in
> the CRIS ABI, but perhaps libffi supports structs with members
> with __attribute__ ((__align__ (N))) directives with N larger
> than normal alignment?
I can not, because it is not needed, so i removed it.

> (Also, coding standard nits: no braces for single statements.
> Comments are full sentences, with "." and two spaces after the
> ".".  Those two nits applies to all this code; I won't repeat
> those two.)
I did some reformatting so it should be better now.

> > +++ gcc_cris/libffi/src/cris/ffitarget.h	2004-10-25 12:58:24.104724112 +0200
> > @@ -0,0 +1,47 @@
> > +/* -----------------------------------------------------------------*-C-*-
> > +   ffitarget.h - Copyright (c) 1996-2003  Red Hat, Inc.
> 
> Why is Red Hat mentioned here?  Copy-paste?
> Please resend with *at least* this fixed.
The file is exatcly the same as in arm/ffitarget.h. (s/ARM/CRIS/g)

> > +++ gcc_cris/libffi/src/cris/sysv.S	2004-10-25 12:58:24.105723960 +0200
> > @@ -0,0 +1,163 @@
> 
> There's a mix of TAB and spaces in this file.  Also, inconsistent
> formatting: I suggest you consistently drop the space after comma in "move
> X,Y".  Best to format it like the gcc output.  (Consistent with that,
> "move X,[Y+Z]", not "move X, [Y + Z]".  This is arguably a matter or taste
> but please be consistent within the file.)
OK. Done.

> > +ffi_call_SYSV:
> > +	;; save the regs to the stack
> > +	Push $srp
> > +	push $r6
> > +	push $r7
> > +	push $r8
> > +	push $r13
> > +	move.d $sp,$r8
> > +	move.d $sp,$r6
> 
> I don't understand the choice of call-saved registers here.  Better use
> $R0 and up, so they can be saved and restored with a single "MOVEM".
> Comments on register use would also be helpful.
Added some comments.

> > +	cmp.d $sp, $r6
> > +
> > +	bmi go_on_no_params_on_stack
> > +	nop
> > +
> > +        beq go_on_no_params_on_stack
> > +        nop
> > +
> > +	ba go_on
> > +	nop
> > +
> > +go_on_no_params_on_stack:
> > +	move.d $r6, $sp
> > +
> > +go_on:
> 
> Those branches look a bit strange.  The "beq" is redundant (copying over
> same contents), so just "bpl go_on" would have done it.  Also, because I
> prefer to use insns that relate to the compare, I'd use "bhs go_on"
> (branch-higher-same); "bmi" (branch-minus) is less understandable IMHO.
> (The stack-adjusting is a bit hard to follow as it is.)
You are correct. I cleaned it up.

> > +	cmpq FFI_TYPE_UINT64, $r13
> > +	beq return_double_or_longlong
> > +	nop
> > +
> > +	cmpq FFI_TYPE_SINT64, $r13
> > +	beq return_double_or_longlong
> > +	nop
> 
> All those delay-slots could have been filled with the following
> "CMPQ" with no loss in readbility (code-wise, just deleting the
> NOP).  Ok, maybe that's just me...
OK. Done.

> Hm, if the area ecif.rvalue points to is *always* at least 64
> bits long, there's no need for different epilogues.  You could
> remove all the above rval type compares and branches and just do
> this part:
It is not always 64 bits long. Only if return value is long long or double, all 
others are 32 bit. Or am I missing something?

> A bit too many ifdefs for my taste here.  I recognize there are
> several in the code as-is, but continuing that would have things
> worse. For this particular effect, wouldn't it just work with
> #ifdef __CRIS__
> #define initialize_aggregate initialize_aggregate_packed_struct
> #endif
> (perhaps in the initialize_aggregate body; after the header)?
> Hmm, I don't quite understand the code here, which may be my
> lack of libffi knowledge.  What does initialize_aggregate do
> that your initialize_aggregate_packed_struct wouldn't do?
> 
> But wait, how about wrapping the whole initialize_aggregate body
> after "cif->" lines up to including "cif->bytes = bytes;" in
> "#ifndef __CRIS__ / #endif" and let ffi_prep_cif_machdep do the
> structure handling?
I tried to clean it up the best I can.

		Regards Simon

diff -uNrp gcc/libffi/configure.ac gcc_cris/libffi/configure.ac
--- gcc/libffi/configure.ac     2004-10-13 19:20:23.000000000 +0200
+++ gcc_cris/libffi/configure.ac        2004-10-26 12:04:38.430195600 +0200
@@ -68,6 +68,7 @@ powerpc-*-aix*) TARGET=POWERPC_AIX; TARG
 rs6000-*-aix*) TARGET=POWERPC_AIX; TARGETDIR=powerpc;;
 arm*-*-linux-*) TARGET=ARM; TARGETDIR=arm;;
 arm*-*-netbsdelf* | arm*-*-knetbsd*-gnu) TARGET=ARM; TARGETDIR=arm;;
+cris-*-linux-*) TARGET=CRIS_LINUX; TARGETDIR=cris;;
 s390-*-linux-*) TARGET=S390; TARGETDIR=s390;;
 s390x-*-linux-*) TARGET=S390; TARGETDIR=s390;;
 x86_64-*-linux* | x86_64-*-freebsd* | x86_64-*-kfreebsd*-gnu) TARGET=X86_64; TARGETDIR=x86;;
@@ -95,6 +96,7 @@ AM_CONDITIONAL(POWERPC, test x$TARGET =
 AM_CONDITIONAL(POWERPC_AIX, test x$TARGET = xPOWERPC_AIX)
 AM_CONDITIONAL(POWERPC_DARWIN, test x$TARGET = xPOWERPC_DARWIN)
 AM_CONDITIONAL(ARM, test x$TARGET = xARM)
+AM_CONDITIONAL(CRIS_LINUX, test x$TARGET = xCRIS_LINUX)
 AM_CONDITIONAL(FRV, test x$TARGET = xFRV)
 AM_CONDITIONAL(S390, test x$TARGET = xS390)
 AM_CONDITIONAL(X86_64, test x$TARGET = xX86_64)
diff -uNrp gcc/libffi/Makefile.am gcc_cris/libffi/Makefile.am
--- gcc/libffi/Makefile.am	2004-10-13 19:20:21.000000000 +0200
+++ gcc_cris/libffi/Makefile.am	2004-10-26 12:04:38.000000000 +0200
@@ -7,6 +7,7 @@ SUBDIRS = include testsuite
 EXTRA_DIST = LICENSE ChangeLog.v1 \
 	src/alpha/ffi.c src/alpha/osf.S src/alpha/ffitarget.h \
 	src/arm/ffi.c src/arm/sysv.S src/arm/ffitarget.h \
+	src/cris/ffi.c src/cris/sysv.S src/cris/ffitarget.h \
 	src/mips/ffi.c src/mips/n32.S src/mips/o32.S \
 	src/mips/ffitarget.h \
 	src/m32r/ffi.c src/m32r/sysv.S src/m32r/ffitarget.h \
@@ -120,6 +121,9 @@ endif
 if ARM
 nodist_libffi_la_SOURCES += src/arm/sysv.S src/arm/ffi.c
 endif
+if CRIS_LINUX
+nodist_libffi_la_SOURCES += src/cris/sysv.S src/cris/ffi.c
+endif
 if FRV
 nodist_libffi_la_SOURCES += src/frv/eabi.S src/frv/ffi.c
 endif
diff -uNrp gcc/libffi/include/ffi_common.h gcc_cris/libffi/include/ffi_common.h
--- gcc/libffi/include/ffi_common.h	2004-08-30 17:43:02.000000000 +0200
+++ gcc_cris/libffi/include/ffi_common.h	2004-10-26 12:04:38.000000000 +0200
@@ -63,7 +63,14 @@ void ffi_type_test(/*@temp@*/ /*@out@*/ 
 #define ALIGN_DOWN(v, a) (((size_t) (v)) & -a)
 
 /* Perform machine dependent cif processing */
+#ifdef __cris__
+ffi_status ffi_prep_cif_machdep (ffi_cif * cif,
+                      ffi_abi abi,
+                      unsigned int nargs,
+                      ffi_type * rtype, ffi_type ** atypes);
+#else
 ffi_status ffi_prep_cif_machdep(ffi_cif *cif);
+#endif
 
 /* Extended cif, used in callback from assembly routine */
 typedef struct
diff -uNrp gcc/libffi/src/cris/ffi.c gcc_cris/libffi/src/cris/ffi.c
--- gcc/libffi/src/cris/ffi.c	1970-01-01 01:00:00.000000000 +0100
+++ gcc_cris/libffi/src/cris/ffi.c	2004-10-26 12:30:15.674498944 +0200
@@ -0,0 +1,270 @@
+/* -----------------------------------------------------------------------
+   ffi.c - Copyright (c) 1998 Cygnus Solutions
+           Copyright (c) 2004 Simon Posnjak
+
+   CRIS Foreign Function Interface
+
+   Permission is hereby granted, free of charge, to any person obtaining
+   a copy of this software and associated documentation files (the
+   ``Software''), to deal in the Software without restriction, including
+   without limitation the rights to use, copy, modify, merge, publish,
+   distribute, sublicense, and/or sell copies of the Software, and to
+   permit persons to whom the Software is furnished to do so, subject to
+   the following conditions:
+
+   The above copyright notice and this permission notice shall be included
+   in all copies or substantial portions of the Software.
+
+   THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS
+   OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+   IN NO EVENT SHALL SIMON POSNJAK BE LIABLE FOR ANY CLAIM, DAMAGES OR
+   OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+   ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+   OTHER DEALINGS IN THE SOFTWARE.
+   ----------------------------------------------------------------------- */
+
+#include <ffi.h>
+#include <ffi_common.h>
+
+#define STACK_ARG_SIZE(x) ALIGN(x, FFI_SIZEOF_ARG)
+
+ffi_status
+initialize_aggregate_packed_struct (ffi_type * arg)
+{
+  ffi_type **ptr;
+
+  FFI_ASSERT (arg != NULL);
+
+  FFI_ASSERT (arg->elements != NULL);
+  FFI_ASSERT (arg->size == 0);
+  FFI_ASSERT (arg->alignment == 0);
+
+  ptr = &(arg->elements[0]);
+
+  while ((*ptr) != NULL)
+    {
+      if (((*ptr)->size == 0)
+	  && (initialize_aggregate_packed_struct ((*ptr)) != FFI_OK))
+	return FFI_BAD_TYPEDEF;
+
+      FFI_ASSERT (ffi_type_test ((*ptr)));
+
+      arg->size += (*ptr)->size;
+
+      arg->alignment = (arg->alignment > (*ptr)->alignment) ?
+	arg->alignment : (*ptr)->alignment;
+
+      ptr++;
+    }
+
+  if (arg->size == 0)
+    return FFI_BAD_TYPEDEF;
+  else
+    return FFI_OK;
+}
+
+int
+ffi_prep_args (char *stack, extended_cif * ecif)
+{
+  register unsigned int i;
+  register unsigned int struct_count = 0;
+  register void **p_argv;
+  register char *argp;
+  register ffi_type **p_arg;
+
+  argp = stack;
+
+  p_argv = ecif->avalue;
+
+  for (i = ecif->cif->nargs, p_arg = ecif->cif->arg_types;
+       (i != 0); i--, p_arg++)
+    {
+      size_t z;
+
+      switch ((*p_arg)->type)
+	{
+	case FFI_TYPE_STRUCT:
+	  {
+	    z = (*p_arg)->size;
+	    if (z <= 8)
+	      {
+		memcpy (argp, *p_argv, z);
+		z += (4 - (z % 4));
+	      }
+	    else
+	      {
+		unsigned int uiLocOnStack;
+
+		uiLocOnStack = 4 * ecif->cif->nargs + struct_count;
+		struct_count = struct_count + (*p_arg)->size;
+		*(unsigned int *) argp =
+		  (unsigned int) (UINT32 *) (stack + uiLocOnStack);
+		memcpy ((stack + uiLocOnStack), *p_argv, (*p_arg)->size);
+	      }
+	    break;
+	  }
+	default:
+	  z = (*p_arg)->size;
+	  if (z < sizeof (int))
+	    {
+	      z = sizeof (int);
+	      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;
+
+		default:
+		  FFI_ASSERT (0);
+		}
+	    }
+	  else if (z == sizeof (int))
+	    {
+	      *(unsigned int *) argp = (unsigned int) *(UINT32 *) (*p_argv);
+	    }
+	  else
+	    {
+	      memcpy (argp, *p_argv, z);
+	    }
+	  break;
+	}
+      p_argv++;
+      argp += z;
+    }
+
+  return (struct_count);
+}
+
+ffi_status
+ffi_prep_cif_machdep (ffi_cif * cif,
+		      ffi_abi abi,
+		      unsigned int nargs,
+		      ffi_type * rtype, ffi_type ** atypes)
+{
+  unsigned bytes = 0;
+  unsigned int i;
+  ffi_type **ptr;
+
+  FFI_ASSERT (cif != NULL);
+  FFI_ASSERT ((abi > FFI_FIRST_ABI) && (abi <= FFI_DEFAULT_ABI));
+
+  cif->abi = abi;
+  cif->arg_types = atypes;
+  cif->nargs = nargs;
+  cif->rtype = rtype;
+
+  cif->flags = 0;
+
+  if ((cif->rtype->size == 0)
+      && (initialize_aggregate (cif->rtype) != FFI_OK))
+    return FFI_BAD_TYPEDEF;
+
+  FFI_ASSERT_VALID_TYPE (cif->rtype);
+
+  for (ptr = cif->arg_types, i = cif->nargs; i > 0; i--, ptr++)
+    {
+      if ((*ptr)->type == FFI_TYPE_STRUCT)
+	{
+	  if (((*ptr)->size == 0)
+	      && (initialize_aggregate_packed_struct ((*ptr)) != FFI_OK))
+	    return FFI_BAD_TYPEDEF;
+	}
+      else
+	{
+	  if (((*ptr)->size == 0)
+	      && (initialize_aggregate ((*ptr)) != FFI_OK))
+	    return FFI_BAD_TYPEDEF;
+	}
+
+      FFI_ASSERT_VALID_TYPE (*ptr);
+
+      if (((*ptr)->alignment - 1) & bytes)
+	bytes = ALIGN (bytes, (*ptr)->alignment);
+      if ((*ptr)->type == FFI_TYPE_STRUCT)
+	{
+	  if ((*ptr)->size > 8)
+	    {
+	      bytes += (*ptr)->size;
+	      bytes += sizeof (void *);
+	    }
+	  else
+	    {
+	      if ((*ptr)->size > 4)
+		bytes += 8;
+	      else
+		bytes += 4;
+	    }
+	}
+      else
+	{
+	  bytes += STACK_ARG_SIZE ((*ptr)->size);
+	}
+    }
+
+  cif->bytes = bytes;
+
+  switch (cif->rtype->type)
+    {
+    case FFI_TYPE_VOID:
+    case FFI_TYPE_STRUCT:
+    case FFI_TYPE_FLOAT:
+    case FFI_TYPE_DOUBLE:
+    case FFI_TYPE_SINT64:
+    case FFI_TYPE_UINT64:
+      cif->flags = (unsigned) cif->rtype->type;
+      break;
+
+    default:
+      cif->flags = FFI_TYPE_INT;
+      break;
+    }
+
+  return FFI_OK;
+}
+
+
+extern void ffi_call_SYSV (void (*)(char *, extended_cif *),
+			   extended_cif *,
+			   unsigned, unsigned, unsigned *, void (*fn) ());
+
+void
+ffi_call (ffi_cif * cif, void (*fn) (), void *rvalue, void **avalue)
+{
+  extended_cif ecif;
+
+  ecif.cif = cif;
+  ecif.avalue = avalue;
+
+  if ((rvalue == NULL) && (cif->rtype->type == FFI_TYPE_STRUCT))
+    {
+      ecif.rvalue = alloca (cif->rtype->size);
+    }
+  else
+    ecif.rvalue = rvalue;
+
+  switch (cif->abi)
+    {
+    case FFI_SYSV:
+      ffi_call_SYSV (ffi_prep_args, &ecif, cif->bytes,
+		     cif->flags, ecif.rvalue, fn);
+      break;
+    default:
+      FFI_ASSERT (0);
+      break;
+    }
+}
diff -uNrp gcc/libffi/src/cris/ffitarget.h gcc_cris/libffi/src/cris/ffitarget.h
--- gcc/libffi/src/cris/ffitarget.h	1970-01-01 01:00:00.000000000 +0100
+++ gcc_cris/libffi/src/cris/ffitarget.h	2004-10-26 12:04:38.433195144 +0200
@@ -0,0 +1,47 @@
+/* -----------------------------------------------------------------*-C-*-
+   ffitarget.h - Copyright (c) 1996-2003  Red Hat, Inc.
+   Target configuration macros for CRIS.
+
+   Permission is hereby granted, free of charge, to any person obtaining
+   a copy of this software and associated documentation files (the
+   ``Software''), to deal in the Software without restriction, including
+   without limitation the rights to use, copy, modify, merge, publish,
+   distribute, sublicense, and/or sell copies of the Software, and to
+   permit persons to whom the Software is furnished to do so, subject to
+   the following conditions:
+
+   The above copyright notice and this permission notice shall be included
+   in all copies or substantial portions of the Software.
+
+   THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS
+   OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+   IN NO EVENT SHALL CYGNUS SOLUTIONS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+   OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+   ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+   OTHER DEALINGS IN THE SOFTWARE.
+
+   ----------------------------------------------------------------------- */
+
+#ifndef LIBFFI_TARGET_H
+#define LIBFFI_TARGET_H
+
+#ifndef LIBFFI_ASM
+typedef unsigned long          ffi_arg;
+typedef signed long            ffi_sarg;
+
+typedef enum ffi_abi {
+  FFI_FIRST_ABI = 0,
+  FFI_SYSV,
+  FFI_DEFAULT_ABI = FFI_SYSV,
+  FFI_LAST_ABI = FFI_DEFAULT_ABI + 1
+} ffi_abi;
+#endif
+
+/* ---- Definitions for closures ----------------------------------------- */
+
+#define FFI_CLOSURES 0
+#define FFI_NATIVE_RAW_API 0
+
+#endif
+
diff -uNrp gcc/libffi/src/cris/sysv.S gcc_cris/libffi/src/cris/sysv.S
--- gcc/libffi/src/cris/sysv.S	1970-01-01 01:00:00.000000000 +0100
+++ gcc_cris/libffi/src/cris/sysv.S	2004-10-26 12:22:22.577420632 +0200
@@ -0,0 +1,161 @@
+/* -----------------------------------------------------------------------
+   sysv.S - Copyright (c) 2004 Simon Posnjak
+
+   CRIS Foreign Function Interface
+
+   Permission is hereby granted, free of charge, to any person obtaining
+   a copy of this software and associated documentation files (the
+   ``Software''), to deal in the Software without restriction, including
+   without limitation the rights to use, copy, modify, merge, publish,
+   distribute, sublicense, and/or sell copies of the Software, and to
+   permit persons to whom the Software is furnished to do so, subject to
+   the following conditions:
+
+   The above copyright notice and this permission notice shall be included
+   in all copies or substantial portions of the Software.
+
+   THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS
+   OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+   IN NO EVENT SHALL SIMON POSNJAK BE LIABLE FOR ANY CLAIM, DAMAGES OR
+   OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+   ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+   OTHER DEALINGS IN THE SOFTWARE.
+   ----------------------------------------------------------------------- */
+
+#define LIBFFI_ASM
+#include <ffi.h>
+
+	.text
+
+	;; OK, when we get called we should have this (according to 
+	;; AXIS ETRAX 100LX Programmer's Manual chapter 6.3).  
+	;; 
+	;; R10:	 ffi_prep_args (func. pointer)
+	;; R11:  &ecif
+	;; R12:  cif->bytes
+	;; R13:  fig->flags
+	;; sp+0: ecif.rvalue
+	;; sp+4: fn (function pointer to the function that we need to call)
+
+	.globl  ffi_call_SYSV
+	.type   ffi_call_SYSV,@function
+
+ffi_call_SYSV:
+	;; Save the regs to the stack.  
+	push $srp
+	;; Used for stack pointer saving.  
+	push $r6
+	;; Used for function address pointer.  
+	push $r7
+	;; Used for stack pointer saving.  
+	push $r8
+	;; We save fig->flags to stack we will need them after we 
+	;; call The Function. 
+	push $r13
+	
+	;; Saving current stack pointer.  
+	move.d $sp,$r8
+	move.d $sp,$r6
+
+	;; Move address of ffi_prep_args to r13.  
+	move.d $r10,$r13
+
+	;; Make room on the stack for the args of fn.  
+	sub.d  $r12,$sp
+
+	;; Function void ffi_prep_args(char *stack, extended_cif *ecif) parameters are:
+	;; 	r10 <-- stack pointer
+	;; 	r11 <-- &ecif (already there)
+	move.d $sp,$r10
+
+	;; Call the function.  
+	jsr $r13
+
+	;; Save the size of the structures which are passed on stack.  
+	move.d $r10,$r7
+
+	;; Move first four args in to r10..r13.  
+	move.d [$sp+0],$r10
+	move.d [$sp+4],$r11
+	move.d [$sp+8],$r12
+	move.d [$sp+12],$r13
+
+	;; Adjust the stack and check if any parameters are given on stack.  
+	addq 16,$sp
+	sub.d $r7,$r6
+	cmp.d $sp,$r6
+
+	bpl go_on
+	nop
+
+go_on_no_params_on_stack:
+	move.d $r6,$sp
+
+go_on:
+	;; Discover if we need to put rval address in to r9.  
+	move.d [$r8+0],$r7
+	cmpq FFI_TYPE_STRUCT,$r7
+	bne call_now
+	nop
+
+	;; Move rval address to $r9.  
+	move.d [$r8+20],$r9
+
+call_now:
+	;; Move address of The Function in to r7.  
+	move.d [$r8+24],$r7
+
+	;; Call The Function.  
+	jsr $r7
+
+	;; Reset stack.  
+	move.d $r8,$sp
+
+	;; Load rval type (fig->flags) in to r13.  
+	pop $r13
+
+	;; Detect rval type.  
+	cmpq FFI_TYPE_VOID,$r13
+	beq epilogue
+
+	cmpq FFI_TYPE_STRUCT,$r13
+	beq epilogue
+
+	cmpq FFI_TYPE_DOUBLE,$r13
+	beq return_double_or_longlong
+
+	cmpq FFI_TYPE_UINT64,$r13
+	beq return_double_or_longlong
+
+	cmpq FFI_TYPE_SINT64,$r13
+	beq return_double_or_longlong
+	nop
+	
+	;; Just return the 32 bit value.  
+	ba return
+	nop
+	
+return_double_or_longlong:
+	;; Load half of the rval to r10 and the other half to r11.
+	move.d [$sp+16],$r13
+	move.d $r10,[$r13]
+	addq 4,$r13
+	move.d $r11,[$r13]
+	ba epilogue
+	nop	
+
+return:
+	;; Load the rval to r10.  
+	move.d [$sp+16],$r13
+	move.d $r10,[$r13]
+	ba epilogue
+	nop
+	
+epilogue:
+	pop $r8
+	pop $r7
+	pop $r6
+	Jump [$sp+]
+
+	.size   ffi_call_SYSV,.-ffi_call_SYSV
diff -uNrp gcc/libffi/src/prep_cif.c gcc_cris/libffi/src/prep_cif.c
--- gcc/libffi/src/prep_cif.c	2004-03-19 23:34:17.000000000 +0100
+++ gcc_cris/libffi/src/prep_cif.c	2004-10-26 12:04:38.000000000 +0200
@@ -25,7 +25,6 @@
 #include <ffi_common.h>
 #include <stdlib.h>
 
-
 /* Round up to FFI_SIZEOF_ARG. */
 
 #define STACK_ARG_SIZE(x) ALIGN(x, FFI_SIZEOF_ARG)
@@ -33,7 +32,7 @@
 /* Perform machine independent initialization of aggregate type
    specifications. */
 
-static ffi_status initialize_aggregate(/*@out@*/ ffi_type *arg)
+ffi_status initialize_aggregate(/*@out@*/ ffi_type *arg)
 {
   ffi_type **ptr; 
 
@@ -89,6 +88,9 @@ ffi_status ffi_prep_cif(/*@out@*/ /*@par
 			/*@dependent@*/ /*@out@*/ /*@partial@*/ ffi_type *rtype, 
 			/*@dependent@*/ ffi_type **atypes)
 {
+#ifdef __cris__
+  return ffi_prep_cif_machdep (cif, abi, nargs, rtype, atypes);
+#else
   unsigned bytes = 0;
   unsigned int i;
   ffi_type **ptr;
@@ -147,7 +149,7 @@ ffi_status ffi_prep_cif(/*@out@*/ /*@par
 	  /* Add any padding if necessary */
 	  if (((*ptr)->alignment - 1) & bytes)
 	    bytes = ALIGN(bytes, (*ptr)->alignment);
-	  
+
 	  bytes += STACK_ARG_SIZE((*ptr)->size);
 	}
 #endif
@@ -157,4 +159,5 @@ ffi_status ffi_prep_cif(/*@out@*/ /*@par
 
   /* Perform machine dependent cif processing */
   return ffi_prep_cif_machdep(cif);
+#endif
 }
diff -uNrp gcc/libffi/src/types.c gcc_cris/libffi/src/types.c
--- gcc/libffi/src/types.c	2004-10-13 19:20:24.000000000 +0200
+++ gcc_cris/libffi/src/types.c	2004-10-26 12:04:38.000000000 +0200
@@ -53,7 +53,7 @@ FFI_INTEGRAL_TYPEDEF(pointer, 4, 4, FFI_
 
 #endif
 
-#if defined X86 || defined ARM || defined M68K
+#if defined X86 || defined ARM || defined M68K || defined __cris__
 
 FFI_INTEGRAL_TYPEDEF(uint64, 8, 4, FFI_TYPE_UINT64);
 FFI_INTEGRAL_TYPEDEF(sint64, 8, 4, FFI_TYPE_SINT64);
@@ -80,7 +80,7 @@ FFI_INTEGRAL_TYPEDEF(double, 8, 4, FFI_T
 #endif
 FFI_INTEGRAL_TYPEDEF(longdouble, 12, 4, FFI_TYPE_LONGDOUBLE);
 
-#elif defined ARM || defined SH || defined POWERPC_AIX || defined M32R
+#elif defined ARM || defined SH || defined POWERPC_AIX || defined M32R || defined __cris__
 
 FFI_INTEGRAL_TYPEDEF(double, 8, 4, FFI_TYPE_DOUBLE);
 FFI_INTEGRAL_TYPEDEF(longdouble, 8, 4, FFI_TYPE_LONGDOUBLE);

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