OSDN Git Service

* Makefile.am: Add SHmedia support. Fix a typo of SH support.
authorkkojima <kkojima@138bc75d-0d04-0410-961f-82ee72b054a4>
Fri, 13 Jun 2003 02:23:26 +0000 (02:23 +0000)
committerkkojima <kkojima@138bc75d-0d04-0410-961f-82ee72b054a4>
Fri, 13 Jun 2003 02:23:26 +0000 (02:23 +0000)
* Makefile.in: Regenerate.
* configure.in (sh64-*-linux*, sh5*-*-linux*): Add target.
* configure: Regenerate.
* include/ffi.h.in: Add SHmedia support.
* src/sh64/ffi.c: New file.
* src/sh64/sysv.S: New file.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@67869 138bc75d-0d04-0410-961f-82ee72b054a4

libffi/ChangeLog
libffi/Makefile.am
libffi/Makefile.in
libffi/configure
libffi/configure.in
libffi/include/ffi.h.in
libffi/src/sh64/ffi.c [new file with mode: 0644]
libffi/src/sh64/sysv.S [new file with mode: 0644]

index 5da773a..cbdc183 100644 (file)
@@ -1,3 +1,13 @@
+2003-06-13  Kaz Kojima  <kkojima@rr.iij4u.or.jp>
+
+       * Makefile.am: Add SHmedia support.  Fix a typo of SH support.
+       * Makefile.in: Regenerate.
+       * configure.in (sh64-*-linux*, sh5*-*-linux*): Add target.
+       * configure: Regenerate.
+       * include/ffi.h.in: Add SHmedia support.
+       * src/sh64/ffi.c: New file.
+       * src/sh64/sysv.S: New file.
+
 2003-05-16  Jakub Jelinek  <jakub@redhat.com>
 
        * configure.in (HAVE_RO_EH_FRAME): Check whether .eh_frame section
index 82381b8..d015026 100644 (file)
@@ -19,7 +19,8 @@ EXTRA_DIST = LICENSE ChangeLog.v1 src/mips/ffi.c src/mips/n32.S \
                src/powerpc/darwin_closure.S src/powerpc/aix_closure.S \
                src/arm/ffi.c src/arm/sysv.S \
                src/s390/ffi.c src/s390/sysv.S \
-               src/sh/ffi.c src/sh/sysv.S
+               src/sh/ffi.c src/sh/sysv.S \
+               src/sh64/ffi.c src/sh64/sysv.S
 
 VPATH = @srcdir@:@srcdir@/src:@srcdir@/src/@TARGETDIR@
 
@@ -102,6 +103,7 @@ TARGET_SRC_ARM =  src/arm/sysv.S src/arm/ffi.c
 TARGET_SRC_S390 =  src/s390/sysv.S src/s390/ffi.c
 TARGET_SRC_X86_64 = src/x86/ffi64.c src/x86/unix64.S src/x86/ffi.c src/x86/sysv.S
 TARGET_SRC_SH =  src/sh/sysv.S src/sh/ffi.c
+TARGET_SRC_SH64 =  src/sh64/sysv.S src/sh64/ffi.c
 
 ##libffi_la_SOURCES = src/debug.c src/prep_cif.c src/types.c $(TARGET_SRC_@TARGET@)
 ## Work around automake deficiency
@@ -169,7 +171,11 @@ libffi_convenience_la_SOURCES = $(libffi_la_common_SOURCES) $(TARGET_SRC_X86_64)
 endif
 if SH
 libffi_la_SOURCES = $(libffi_la_common_SOURCES) $(TARGET_SRC_SH)
-libfficonvenience_la_SOURCES = $(libffi_la_common_SOURCES) $(TARGET_SRC_SH)
+libffi_convenience_la_SOURCES = $(libffi_la_common_SOURCES) $(TARGET_SRC_SH)
+endif
+if SH64
+libffi_la_SOURCES = $(libffi_la_common_SOURCES) $(TARGET_SRC_SH64)
+libffi_convenience_la_SOURCES = $(libffi_la_common_SOURCES) $(TARGET_SRC_SH64)
 endif
 
 AM_CFLAGS = -fexceptions
index 08d8c73..4e4e461 100644 (file)
@@ -102,7 +102,8 @@ EXTRA_DIST = LICENSE ChangeLog.v1 src/mips/ffi.c src/mips/n32.S \
                src/powerpc/darwin_closure.S src/powerpc/aix_closure.S \
                src/arm/ffi.c src/arm/sysv.S \
                src/s390/ffi.c src/s390/sysv.S \
-               src/sh/ffi.c src/sh/sysv.S
+               src/sh/ffi.c src/sh/sysv.S \
+               src/sh64/ffi.c src/sh64/sysv.S
 
 
 VPATH = @srcdir@:@srcdir@/src:@srcdir@/src/@TARGETDIR@
@@ -181,6 +182,7 @@ TARGET_SRC_ARM = src/arm/sysv.S src/arm/ffi.c
 TARGET_SRC_S390 = src/s390/sysv.S src/s390/ffi.c
 TARGET_SRC_X86_64 = src/x86/ffi64.c src/x86/unix64.S src/x86/ffi.c src/x86/sysv.S
 TARGET_SRC_SH = src/sh/sysv.S src/sh/ffi.c
+TARGET_SRC_SH64 = src/sh64/sysv.S src/sh64/ffi.c
 
 libffi_la_common_SOURCES = src/debug.c src/prep_cif.c src/types.c \
                src/raw_api.c src/java_raw_api.c
@@ -201,6 +203,7 @@ libffi_la_common_SOURCES = src/debug.c src/prep_cif.c src/types.c \
 @S390_TRUE@libffi_la_SOURCES = @S390_TRUE@$(libffi_la_common_SOURCES) $(TARGET_SRC_S390)
 @X86_64_TRUE@libffi_la_SOURCES = @X86_64_TRUE@$(libffi_la_common_SOURCES) $(TARGET_SRC_X86_64)
 @SH_TRUE@libffi_la_SOURCES = @SH_TRUE@$(libffi_la_common_SOURCES) $(TARGET_SRC_SH)
+@SH64_TRUE@libffi_la_SOURCES = @SH64_TRUE@$(libffi_la_common_SOURCES) $(TARGET_SRC_SH64)
 @MIPS_GCC_TRUE@libffi_convenience_la_SOURCES = @MIPS_GCC_TRUE@$(libffi_la_common_SOURCES) $(TARGET_SRC_MIPS_GCC)
 @MIPS_LINUX_TRUE@libffi_convenience_la_SOURCES = @MIPS_LINUX_TRUE@$(libffi_la_common_SOURCES) $(TARGET_SRC_MIPS_LINUX)
 @MIPS_SGI_TRUE@libffi_convenience_la_SOURCES = @MIPS_SGI_TRUE@$(libffi_la_common_SOURCES) $(TARGET_SRC_MIPS_SGI)
@@ -216,7 +219,8 @@ libffi_la_common_SOURCES = src/debug.c src/prep_cif.c src/types.c \
 @ARM_TRUE@libffi_convenience_la_SOURCES = @ARM_TRUE@$(libffi_la_common_SOURCES) $(TARGET_SRC_ARM)
 @S390_TRUE@libffi_convenience_la_SOURCES = @S390_TRUE@$(libffi_la_common_SOURCES) $(TARGET_SRC_S390)
 @X86_64_TRUE@libffi_convenience_la_SOURCES = @X86_64_TRUE@$(libffi_la_common_SOURCES) $(TARGET_SRC_X86_64)
-@SH_TRUE@libfficonvenience_la_SOURCES = @SH_TRUE@$(libffi_la_common_SOURCES) $(TARGET_SRC_SH)
+@SH_TRUE@libffi_convenience_la_SOURCES = @SH_TRUE@$(libffi_la_common_SOURCES) $(TARGET_SRC_SH)
+@SH64_TRUE@libffi_convenience_la_SOURCES = @SH64_TRUE@$(libffi_la_common_SOURCES) $(TARGET_SRC_SH64)
 
 AM_CFLAGS = -fexceptions
 
@@ -270,6 +274,12 @@ libffi_convenience_la_LIBADD =
 @X86_64_TRUE@src/prep_cif.lo src/types.lo src/raw_api.lo \
 @X86_64_TRUE@src/java_raw_api.lo src/x86/ffi64.lo src/x86/unix64.lo \
 @X86_64_TRUE@src/x86/ffi.lo src/x86/sysv.lo
+@SH_TRUE@libffi_convenience_la_OBJECTS =  src/debug.lo src/prep_cif.lo \
+@SH_TRUE@src/types.lo src/raw_api.lo src/java_raw_api.lo src/sh/sysv.lo \
+@SH_TRUE@src/sh/ffi.lo
+@SH64_TRUE@libffi_convenience_la_OBJECTS =  src/debug.lo src/prep_cif.lo \
+@SH64_TRUE@src/types.lo src/raw_api.lo src/java_raw_api.lo \
+@SH64_TRUE@src/sh64/sysv.lo src/sh64/ffi.lo
 @SPARC_TRUE@libffi_convenience_la_OBJECTS =  src/debug.lo \
 @SPARC_TRUE@src/prep_cif.lo src/types.lo src/raw_api.lo \
 @SPARC_TRUE@src/java_raw_api.lo src/sparc/ffi.lo src/sparc/v8.lo \
@@ -294,6 +304,9 @@ libffi_la_LIBADD =
 @SH_TRUE@libffi_la_OBJECTS =  src/debug.lo src/prep_cif.lo src/types.lo \
 @SH_TRUE@src/raw_api.lo src/java_raw_api.lo src/sh/sysv.lo \
 @SH_TRUE@src/sh/ffi.lo
+@SH64_TRUE@libffi_la_OBJECTS =  src/debug.lo src/prep_cif.lo src/types.lo \
+@SH64_TRUE@src/raw_api.lo src/java_raw_api.lo src/sh64/sysv.lo \
+@SH64_TRUE@src/sh64/ffi.lo
 @IA64_TRUE@libffi_la_OBJECTS =  src/debug.lo src/prep_cif.lo \
 @IA64_TRUE@src/types.lo src/raw_api.lo src/java_raw_api.lo \
 @IA64_TRUE@src/ia64/ffi.lo src/ia64/unix.lo
index 9c2550d..8689a37 100755 (executable)
@@ -2480,6 +2480,7 @@ s390-*-linux-*) TARGET=S390; TARGETDIR=s390;;
 s390x-*-linux-*) TARGET=S390; TARGETDIR=s390;;
 x86_64-*-linux*) TARGET=X86_64; TARGETDIR=x86;;
 sh-*-linux* | sh[34]*-*-linux*) TARGET=SH; TARGETDIR=sh;;
+sh64-*-linux* | sh5*-*-linux*) TARGET=SH64; TARGETDIR=sh64;;
 esac
 
 if test $TARGETDIR = unknown; then
@@ -2631,6 +2632,14 @@ else
   SH_FALSE=
 fi
 
+if test x$TARGET = xSH64; then
+  SH64_TRUE=
+  SH64_FALSE='#'
+else
+  SH64_TRUE='#'
+  SH64_FALSE=
+fi
+
 if test x$TARGET = xMIPS_LINUX; then
   TARGET=MIPS
 fi
@@ -3938,6 +3947,8 @@ s%@X86_64_TRUE@%$X86_64_TRUE%g
 s%@X86_64_FALSE@%$X86_64_FALSE%g
 s%@SH_TRUE@%$SH_TRUE%g
 s%@SH_FALSE@%$SH_FALSE%g
+s%@SH64_TRUE@%$SH64_TRUE%g
+s%@SH64_FALSE@%$SH64_FALSE%g
 s%@CPP@%$CPP%g
 s%@ALLOCA@%$ALLOCA%g
 s%@TARGET@%$TARGET%g
index 0048439..25b0973 100644 (file)
@@ -75,6 +75,7 @@ s390-*-linux-*) TARGET=S390; TARGETDIR=s390;;
 s390x-*-linux-*) TARGET=S390; TARGETDIR=s390;;
 x86_64-*-linux*) TARGET=X86_64; TARGETDIR=x86;;
 sh-*-linux* | sh[[34]]*-*-linux*) TARGET=SH; TARGETDIR=sh;;
+sh64-*-linux* | sh5*-*-linux*) TARGET=SH64; TARGETDIR=sh64;;
 esac
 
 if test $TARGETDIR = unknown; then
@@ -97,6 +98,7 @@ AM_CONDITIONAL(ARM, test x$TARGET = xARM)
 AM_CONDITIONAL(S390, test x$TARGET = xS390)
 AM_CONDITIONAL(X86_64, test x$TARGET = xX86_64)
 AM_CONDITIONAL(SH, test x$TARGET = xSH)
+AM_CONDITIONAL(SH64, test x$TARGET = xSH64)
 
 if test x$TARGET = xMIPS_LINUX; then
   TARGET=MIPS
index b37307c..fe32ea2 100644 (file)
@@ -302,6 +302,12 @@ typedef enum ffi_abi {
   FFI_DEFAULT_ABI = FFI_SYSV,
 #endif
 
+  /* ---- SuperH - SHmedia --------- */
+#ifdef SH64
+  FFI_SYSV,
+  FFI_DEFAULT_ABI = FFI_SYSV,
+#endif
+
   /* Leave this for debugging purposes */
   FFI_LAST_ABI
 
@@ -356,6 +362,10 @@ typedef struct {
 #endif
 #endif
 
+#ifdef SH64
+  long long flags2;
+#endif
+
 } ffi_cif;
 
 #if SIZEOF_ARG == 4
@@ -501,6 +511,12 @@ struct ffi_ia64_trampoline_struct {
 #define FFI_TRAMPOLINE_SIZE 16
 #define FFI_NATIVE_RAW_API 0
 
+#elif defined(SH64)
+
+#define FFI_CLOSURES 1
+#define FFI_TRAMPOLINE_SIZE 32
+#define FFI_NATIVE_RAW_API 0
+
 #elif defined(__x86_64__)
 
 #define FFI_CLOSURES 1
diff --git a/libffi/src/sh64/ffi.c b/libffi/src/sh64/ffi.c
new file mode 100644 (file)
index 0000000..7709603
--- /dev/null
@@ -0,0 +1,448 @@
+/* -----------------------------------------------------------------------
+   ffi.c - Copyright (c) 2003 Kaz Kojima
+   
+   SuperH SHmedia 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 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.
+   ----------------------------------------------------------------------- */
+
+#include <ffi.h>
+#include <ffi_common.h>
+
+#include <stdlib.h>
+
+#define NGREGARG 8
+#define NFREGARG 12
+
+/* If the structure has essentialy an unique element, return its type.  */
+static int
+simple_type (ffi_type *arg)
+{
+  if (arg->type != FFI_TYPE_STRUCT)
+    return arg->type;
+  else if (arg->elements[1])
+    return FFI_TYPE_STRUCT;
+
+  return simple_type (arg->elements[0]);
+}
+
+static int
+return_type (ffi_type *arg)
+{
+  unsigned short type;
+
+  if (arg->type != FFI_TYPE_STRUCT)
+    return arg->type;
+
+  type = simple_type (arg->elements[0]);
+  if (! arg->elements[1])
+    {
+      switch (type)
+       {
+       case FFI_TYPE_SINT8:
+       case FFI_TYPE_UINT8:
+       case FFI_TYPE_SINT16:
+       case FFI_TYPE_UINT16:
+       case FFI_TYPE_SINT32:
+       case FFI_TYPE_UINT32:
+       case FFI_TYPE_SINT64:
+       case FFI_TYPE_UINT64:
+         return FFI_TYPE_UINT64;
+
+       default:
+         return type;
+       }
+    }
+
+  /* gcc uses r2 if the result can be packed in on register.  */
+  if (arg->size <= sizeof (UINT64))
+    return FFI_TYPE_UINT64;
+
+  return FFI_TYPE_STRUCT;
+}
+
+/* ffi_prep_args is called by the assembly routine once stack space
+   has been allocated for the function's arguments */
+
+/*@-exportheader@*/
+void ffi_prep_args(char *stack, extended_cif *ecif)
+/*@=exportheader@*/
+{
+  register unsigned int i;
+  register unsigned int avn;
+  register void **p_argv;
+  register char *argp;
+  register ffi_type **p_arg;
+
+  argp = stack;
+
+  if (return_type (ecif->cif->rtype) == FFI_TYPE_STRUCT)
+    {
+      *(void **) argp = ecif->rvalue;
+      argp += sizeof (UINT64);
+    }
+
+  avn = ecif->cif->nargs;
+  p_argv = ecif->avalue;
+
+  for (i = 0, p_arg = ecif->cif->arg_types; i < avn; i++, p_arg++, p_argv++)
+    {
+      size_t z;
+
+      z = (*p_arg)->size;
+      if (z < sizeof (UINT32))
+       {
+         switch ((*p_arg)->type)
+           {
+           case FFI_TYPE_SINT8:
+             *(SINT64 *) argp = (SINT64) *(SINT8 *)(*p_argv);
+             break;
+  
+           case FFI_TYPE_UINT8:
+             *(UINT64 *) argp = (UINT64) *(UINT8 *)(*p_argv);
+             break;
+  
+           case FFI_TYPE_SINT16:
+             *(SINT64 *) argp = (SINT64) *(SINT16 *)(*p_argv);
+             break;
+  
+           case FFI_TYPE_UINT16:
+             *(UINT64 *) argp = (UINT64) *(UINT16 *)(*p_argv);
+             break;
+  
+           case FFI_TYPE_STRUCT:
+             *(UINT64 *) argp = (UINT64) *(UINT32 *)(*p_argv);
+             break;
+
+           default:
+             FFI_ASSERT(0);
+           }
+         argp += sizeof (UINT64);
+       }
+      else if (z == sizeof (UINT32))
+       {
+         *(UINT64 *) argp = (UINT64) *(UINT32 *) (*p_argv);
+         argp += sizeof (UINT64);
+       }
+      else if (z == sizeof (UINT64))
+       {
+         *(UINT64 *) argp = *(UINT64 *) (*p_argv);
+         argp += sizeof (UINT64);
+       }
+      else
+       {
+         int n = (z + sizeof (UINT64) - 1) / sizeof (UINT64);
+
+         memcpy (argp, *p_argv, z);
+         argp += n * sizeof (UINT64);
+       }
+    }
+
+  return;
+}
+
+/* Perform machine dependent cif processing */
+ffi_status ffi_prep_cif_machdep(ffi_cif *cif)
+{
+  int i, j;
+  int size, type;
+  int n, m;
+  int greg;
+  int freg;
+
+  greg = (return_type (cif->rtype) == FFI_TYPE_STRUCT ? 1 : 0);
+  freg = 0;
+  cif->flags2 = 0;
+
+  for (i = j = 0; i < cif->nargs; i++)
+    {
+      type = (cif->arg_types)[i]->type;
+      switch (type)
+       {
+       case FFI_TYPE_FLOAT:
+         greg++;
+         cif->bytes += sizeof (UINT64) - sizeof (float);
+         if (freg >= NFREGARG - 1)
+           continue;
+         freg++;
+         cif->flags2 += ((cif->arg_types)[i]->type) << (2 * j++);
+         break;
+
+       case FFI_TYPE_DOUBLE:
+         if (greg++ >= NGREGARG && (freg + 1) >= NFREGARG)
+           continue;
+         if ((freg + 1) < NFREGARG)
+           {
+             freg = (freg + 1) & ~1;
+             freg += 2;
+             cif->flags2 += ((cif->arg_types)[i]->type) << (2 * j++);
+           }
+         else
+           cif->flags2 += FFI_TYPE_INT << (2 * j++);
+         break;
+             
+       default:
+         size = (cif->arg_types)[i]->size;
+         if (size < sizeof (UINT64))
+           cif->bytes += sizeof (UINT64) - size;
+         n = (size + sizeof (UINT64) - 1) / sizeof (UINT64);
+         if (greg >= NGREGARG)
+           continue;
+         else if (greg + n - 1 >= NGREGARG)
+           greg = NGREGARG;
+         else
+           greg += n;
+         for (m = 0; m < n; m++)
+           cif->flags2 += FFI_TYPE_INT << (2 * j++);
+         break;
+       }
+    }
+
+  /* Set the return type flag */
+  switch (cif->rtype->type)
+    {
+    case FFI_TYPE_STRUCT:
+      cif->flags = return_type (cif->rtype);
+      break;
+
+    case FFI_TYPE_VOID:
+    case FFI_TYPE_FLOAT:
+    case FFI_TYPE_DOUBLE:
+    case FFI_TYPE_SINT64:
+    case FFI_TYPE_UINT64:
+      cif->flags = cif->rtype->type;
+      break;
+
+    default:
+      cif->flags = FFI_TYPE_INT;
+      break;
+    }
+
+  return FFI_OK;
+}
+
+/*@-declundef@*/
+/*@-exportheader@*/
+extern void ffi_call_SYSV(void (*)(char *, extended_cif *), 
+                         /*@out@*/ extended_cif *, 
+                         unsigned, unsigned, long long,
+                         /*@out@*/ unsigned *, 
+                         void (*fn)());
+/*@=declundef@*/
+/*@=exportheader@*/
+
+void ffi_call(/*@dependent@*/ ffi_cif *cif, 
+             void (*fn)(), 
+             /*@out@*/ void *rvalue, 
+             /*@dependent@*/ void **avalue)
+{
+  extended_cif ecif;
+
+  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                    */
+
+  if ((rvalue == NULL) && 
+      (cif->rtype->type == FFI_TYPE_STRUCT))
+    {
+      /*@-sysunrecog@*/
+      ecif.rvalue = alloca(cif->rtype->size);
+      /*@=sysunrecog@*/
+    }
+  else
+    ecif.rvalue = rvalue;
+
+  switch (cif->abi) 
+    {
+    case FFI_SYSV:
+      /*@-usedef@*/
+      ffi_call_SYSV(ffi_prep_args, &ecif, cif->bytes, 
+                   cif->flags, cif->flags2, ecif.rvalue, fn);
+      /*@=usedef@*/
+      break;
+    default:
+      FFI_ASSERT(0);
+      break;
+    }
+}
+
+extern void ffi_closure_SYSV (void);
+extern void __ic_invalidate (void *line);
+
+ffi_status
+ffi_prep_closure (ffi_closure *closure,
+                 ffi_cif *cif,
+                 void (*fun)(ffi_cif*, void*, void**, void*),
+                 void *user_data)
+{
+  unsigned int *tramp;
+
+  FFI_ASSERT (cif->abi == FFI_GCC_SYSV);
+
+  tramp = (unsigned int *) &closure->tramp[0];
+  /* Since ffi_closure is an aligned object, the ffi trampoline is
+     called as an SHcompact code.  Sigh.
+     SHcompact part:
+     mova @(1,pc),r0; add #1,r0; jmp @r0; nop;
+     SHmedia part:
+     movi fnaddr >> 16,r1; shori fnaddr,r1; ptabs/l r1,tr0
+     movi cxt >> 16,r1; shori cxt,r1; blink tr0,r63  */
+#ifdef __LITTLE_ENDIAN__
+  tramp[0] = 0x7001c701;
+  tramp[1] = 0x0009402b;
+#else
+  tramp[0] = 0xc7017001;
+  tramp[1] = 0x402b0009;
+#endif
+  tramp[2] = 0xcc000010 | (((UINT32) ffi_closure_SYSV) >> 16) << 10;
+  tramp[3] = 0xc8000010 | (((UINT32) ffi_closure_SYSV) & 0xffff) << 10;
+  tramp[4] = 0x6bf10600;
+  tramp[5] = 0xcc000010 | (((UINT32) closure) >> 16) << 10;
+  tramp[6] = 0xc8000010 | (((UINT32) closure) & 0xffff) << 10;
+  tramp[7] = 0x4401fff0;
+
+  closure->cif = cif;
+  closure->fun = fun;
+  closure->user_data = user_data;
+
+  /* Flush the icache.  */
+  asm volatile ("ocbwb %0,0; synco; icbi %0,0; synci" : : "r" (tramp));
+
+  return FFI_OK;
+}
+
+/* Basically the trampoline invokes ffi_closure_SYSV, and on 
+ * entry, r3 holds the address of the closure.
+ * After storing the registers that could possibly contain
+ * parameters to be passed into the stack frame and setting
+ * up space for a return value, ffi_closure_SYSV invokes the 
+ * following helper function to do most of the work.
+ */
+
+int
+ffi_closure_helper_SYSV (ffi_closure *closure, UINT64 *rvalue, 
+                        UINT64 *pgr, UINT64 *pfr, UINT64 *pst)
+{
+  void **avalue;
+  ffi_type **p_arg;
+  int i, avn;
+  int greg, freg;
+  ffi_cif *cif;
+
+  cif = closure->cif;
+  avalue = alloca (cif->nargs * sizeof (void *));
+
+  /* Copy the caller's structure return value address so that the closure
+     returns the data directly to the caller.  */
+  if (cif->rtype->type == FFI_TYPE_STRUCT)
+    {
+      rvalue = *pgr;
+      greg = 1;
+    }
+  else
+    greg = 0;
+
+  freg = 0;
+  cif = closure->cif;
+  avn = cif->nargs;
+
+  /* Grab the addresses of the arguments from the stack frame.  */
+  for (i = 0, p_arg = cif->arg_types; i < avn; i++, p_arg++)
+    {
+      size_t z;
+      void *p;
+
+      z = (*p_arg)->size;
+      if (z < sizeof (UINT32))
+       {
+         p = pgr + greg++;
+
+         switch ((*p_arg)->type)
+           {
+           case FFI_TYPE_SINT8:
+           case FFI_TYPE_UINT8:
+           case FFI_TYPE_SINT16:
+           case FFI_TYPE_UINT16:
+           case FFI_TYPE_STRUCT:
+#ifdef __LITTLE_ENDIAN__
+             avalue[i] = p;
+#else
+             avalue[i] = ((char *) p) + sizeof (UINT32) - z;
+#endif
+             break;
+
+           default:
+             FFI_ASSERT(0);
+           }
+       }
+      else if (z == sizeof (UINT32))
+       {
+         if ((*p_arg)->type == FFI_TYPE_FLOAT)
+           {
+             if (freg < NFREGARG - 1)
+#ifdef __LITTLE_ENDIAN__
+               avalue[i] = (UINT32 *) pfr + (1 ^ freg++);
+#else
+               avalue[i] = (UINT32 *) pfr + freg++;
+#endif
+             else
+#ifdef __LITTLE_ENDIAN__
+               avalue[i] = pgr + greg;
+#else
+               avalue[i] = (UINT32 *) (pgr + greg) + 1;
+#endif
+           }
+         else
+#ifdef __LITTLE_ENDIAN__
+           avalue[i] = pgr + greg;
+#else
+           avalue[i] = (UINT32 *) (pgr + greg) + 1;
+#endif
+         greg++;
+       }
+      else if ((*p_arg)->type == FFI_TYPE_DOUBLE)
+       {
+         if (freg + 1 >= NFREGARG)
+           avalue[i] = pgr + greg;
+         else
+           {
+             freg = (freg + 1) & ~1;
+             avalue[i] = pfr + (freg >> 1);
+             freg += 2;
+           }
+         greg++;
+       }
+      else
+       {
+         int n = (z + sizeof (UINT64) - 1) / sizeof (UINT64);
+
+         avalue[i] = pgr + greg;
+         greg += n;
+       }
+    }
+
+  (closure->fun) (cif, rvalue, avalue, closure->user_data);
+
+  /* Tell ffi_closure_SYSV how to perform return type promotions.  */
+  return cif->rtype->type;
+}
+
diff --git a/libffi/src/sh64/sysv.S b/libffi/src/sh64/sysv.S
new file mode 100644 (file)
index 0000000..e478ced
--- /dev/null
@@ -0,0 +1,483 @@
+/* -----------------------------------------------------------------------
+   sysv.S - Copyright (c) 2003 Kaz Kojima
+   
+   SuperH SHmedia 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 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.
+   ----------------------------------------------------------------------- */
+
+#define LIBFFI_ASM     
+#include <ffi.h>
+#ifdef HAVE_MACHINE_ASM_H
+#include <machine/asm.h>
+#else
+/* XXX these lose for some platforms, I'm sure. */
+#define CNAME(x) x
+#define ENTRY(x) .globl CNAME(x); .type CNAME(x),%function; CNAME(x):
+#endif
+
+#ifdef __LITTLE_ENDIAN__
+#define OFS_FLT        0
+#else
+#define OFS_FLT        4
+#endif
+
+       .section        .text..SHmedia32,"ax"
+
+       # r2:   ffi_prep_args
+       # r3:   &ecif
+       # r4:   bytes
+       # r5:   flags
+       # r6:   flags2
+       # r7:   rvalue
+       # r8:   fn
+
+       # This assumes we are using gas.
+       .align  5
+ENTRY(ffi_call_SYSV)
+       # Save registers
+.LFB1:
+       addi.l  r15, -48, r15
+.LCFI0:
+       st.q    r15, 40, r32
+       st.q    r15, 32, r31
+       st.q    r15, 24, r30
+       st.q    r15, 16, r29
+       st.q    r15, 8, r28
+       st.l    r15, 4, r18
+       st.l    r15, 0, r14
+       add.l   r15, r63, r14
+.LCFI1:
+#      add     r4, r63, r28
+       add     r5, r63, r29
+       add     r6, r63, r30
+       add     r7, r63, r31
+       add     r8, r63, r32
+
+       addi    r4, (64 + 7), r4
+       andi    r4, ~7, r4
+       sub.l   r15, r4, r15
+
+       ptabs/l r2, tr0
+       add     r15, r63, r2
+       blink   tr0, r18
+
+       addi    r15, 64, r22
+       movi    0, r0
+       movi    0, r1
+
+       pt/l    1f, tr1
+       bnei/l  r29, FFI_TYPE_STRUCT, tr1
+       ld.l    r15, 0, r19
+       addi    r15, 8, r15
+       addi    r0, 1, r0
+1:
+
+.L_pass:
+       andi    r30, 3, r20
+       shlri   r30, 2, r30
+
+       pt/l    .L_call_it, tr0
+       pt/l    .L_pass_i, tr1
+       pt/l    .L_pass_f, tr2
+
+       beqi/l  r20, FFI_TYPE_VOID, tr0
+       beqi/l  r20, FFI_TYPE_INT, tr1
+       beqi/l  r20, FFI_TYPE_FLOAT, tr2
+
+.L_pass_d:
+       addi    r0, 1, r0
+       addi    r1, 1, r1
+       andi    r1, ~1, r1
+
+       pt/l    3f, tr0
+       movi    12, r20
+       bge/l   r1, r20, tr0
+
+       pt/l    .L_pop_d, tr1
+       pt/l    2f, tr0
+       blink   tr1, r63
+2:
+       addi.l  r15, 8, r15
+3:
+       pt/l    .L_pass, tr0
+       addi    r1, 2, r1
+       blink   tr0, r63
+
+.L_pop_d:
+       pt/l    .L_pop_d_tbl, tr1
+       gettr   tr1, r20
+       shlli   r1, 2, r21
+       add     r20, r21, r20
+       ptabs/l r20, tr1
+       blink   tr1, r63
+
+.L_pop_d_tbl:
+       fld.d   r15, 0, dr0
+       blink   tr0, r63
+       fld.d   r15, 0, dr2
+       blink   tr0, r63
+       fld.d   r15, 0, dr4
+       blink   tr0, r63
+       fld.d   r15, 0, dr6
+       blink   tr0, r63
+       fld.d   r15, 0, dr8
+       blink   tr0, r63
+       fld.d   r15, 0, dr10
+       blink   tr0, r63
+
+.L_pass_f:
+       addi    r0, 1, r0
+       pt/l    3f, tr0
+       movi    12, r20
+       bge/l   r1, r20, tr0
+
+       pt/l    .L_pop_f, tr1
+       pt/l    2f, tr0
+       blink   tr1, r63
+2:
+       addi.l  r15, 8, r15
+3:
+       pt/l    .L_pass, tr0
+       addi    r1, 1, r1
+       blink   tr0, r63
+
+.L_pop_f:
+       pt/l    .L_pop_f_tbl, tr1
+       gettr   tr1, r20
+       shlli   r1, 3, r21
+       add     r20, r21, r20
+       ptabs/l r20, tr1
+       blink   tr1, r63
+
+.L_pop_f_tbl:
+       fld.s   r15, OFS_FLT, fr0
+       blink   tr0, r63
+       fld.s   r15, OFS_FLT, fr1
+       blink   tr0, r63
+       fld.s   r15, OFS_FLT, fr2
+       blink   tr0, r63
+       fld.s   r15, OFS_FLT, fr3
+       blink   tr0, r63
+       fld.s   r15, OFS_FLT, fr4
+       blink   tr0, r63
+       fld.s   r15, OFS_FLT, fr5
+       blink   tr0, r63
+       fld.s   r15, OFS_FLT, fr6
+       blink   tr0, r63
+       fld.s   r15, OFS_FLT, fr7
+       blink   tr0, r63
+       fld.s   r15, OFS_FLT, fr8
+       blink   tr0, r63
+       fld.s   r15, OFS_FLT, fr9
+       blink   tr0, r63
+       fld.s   r15, OFS_FLT, fr10
+       blink   tr0, r63
+       fld.s   r15, OFS_FLT, fr11
+       blink   tr0, r63
+
+.L_pass_i:
+       pt/l    3f, tr0
+       movi    8, r20
+       bge/l   r0, r20, tr0
+
+       pt/l    .L_pop_i, tr1
+       pt/l    2f, tr0
+       blink   tr1, r63
+2:
+       addi.l  r15, 8, r15
+3:
+       pt/l    .L_pass, tr0
+       addi    r0, 1, r0
+       blink   tr0, r63
+
+.L_pop_i:
+       pt/l    .L_pop_i_tbl, tr1
+       gettr   tr1, r20
+       shlli   r0, 3, r21
+       add     r20, r21, r20
+       ptabs/l r20, tr1
+       blink   tr1, r63
+
+.L_pop_i_tbl:
+       ld.q    r15, 0, r2
+       blink   tr0, r63
+       ld.q    r15, 0, r3
+       blink   tr0, r63
+       ld.q    r15, 0, r4
+       blink   tr0, r63
+       ld.q    r15, 0, r5
+       blink   tr0, r63
+       ld.q    r15, 0, r6
+       blink   tr0, r63
+       ld.q    r15, 0, r7
+       blink   tr0, r63
+       ld.q    r15, 0, r8
+       blink   tr0, r63
+       ld.q    r15, 0, r9
+       blink   tr0, r63
+
+.L_call_it:
+       # call function
+       pt/l    1f, tr1
+       bnei/l  r29, FFI_TYPE_STRUCT, tr1
+       add     r19, r63, r2
+1:
+       add     r22, r63, r15
+       ptabs/l r32, tr0
+       blink   tr0, r18
+
+       pt/l    .L_ret_i, tr0
+       pt/l    .L_ret_ll, tr1
+       pt/l    .L_ret_d, tr2
+       pt/l    .L_ret_f, tr3
+       pt/l    .L_epilogue, tr4
+
+       beqi/l  r29, FFI_TYPE_INT, tr0
+       beqi/l  r29, FFI_TYPE_SINT64, tr1
+       beqi/l  r29, FFI_TYPE_UINT64, tr1
+       beqi/l  r29, FFI_TYPE_DOUBLE, tr2
+       beqi/l  r29, FFI_TYPE_FLOAT, tr3
+       blink   tr4, r63
+
+.L_ret_d:
+       fst.d   r31, 0, dr0
+       blink   tr4, r63
+
+.L_ret_ll:
+       st.q    r31, 0, r2
+       blink   tr4, r63
+
+.L_ret_f:
+       fst.s   r31, OFS_FLT, fr0
+       blink   tr4, r63
+
+.L_ret_i:
+       st.l    r31, 0, r2
+       # Fall
+
+.L_epilogue:
+       # Remove the space we pushed for the args
+       add     r14, r63, r15
+
+       ld.l    r15, 0, r14
+       ld.l    r15, 4, r18
+       ld.q    r15, 8, r28
+       ld.q    r15, 16, r29
+       ld.q    r15, 24, r30
+       ld.q    r15, 32, r31
+       ld.q    r15, 40, r32
+       addi.l  r15, 48, r15
+       ptabs   r18, tr0
+       blink   tr0, r63
+
+.LFE1:
+.ffi_call_SYSV_end:
+       .size    CNAME(ffi_call_SYSV),.ffi_call_SYSV_end-CNAME(ffi_call_SYSV)
+
+       .align  5
+ENTRY(ffi_closure_SYSV)
+.LFB2:
+       addi.l  r15, -136, r15
+.LCFI2:
+       st.l    r15, 12, r18
+       st.l    r15, 8, r14
+       st.l    r15, 4, r12
+       add     r15, r63, r14
+.LCFI3:
+       /* Stack layout:        
+          ...
+          64 bytes (register parameters)
+          48 bytes (floating register parameters)
+           8 bytes (result)
+           4 bytes (r18)
+           4 bytes (r14)
+           4 bytes (r12)
+           4 bytes (for align)
+          <- new stack pointer
+       */
+       fst.d   r14, 24, dr0
+       fst.d   r14, 32, dr2
+       fst.d   r14, 40, dr4
+       fst.d   r14, 48, dr6
+       fst.d   r14, 56, dr8
+       fst.d   r14, 64, dr10
+       st.q    r14, 72, r2
+       st.q    r14, 80, r3
+       st.q    r14, 88, r4
+       st.q    r14, 96, r5
+       st.q    r14, 104, r6
+       st.q    r14, 112, r7
+       st.q    r14, 120, r8
+       st.q    r14, 128, r9
+
+       add     r1, r63, r2
+       addi    r14, 16, r3
+       addi    r14, 72, r4
+       addi    r14, 24, r5
+       addi    r14, 136, r6
+#ifdef PIC
+       movi    (((datalabel _GLOBAL_OFFSET_TABLE_-(.LPCS0-.)) >> 16) & 65535), r12
+        shori  ((datalabel _GLOBAL_OFFSET_TABLE_-(.LPCS0-.)) & 65535), r12
+.LPCS0:        ptrel/u r12, tr0
+       movi    ((ffi_closure_helper_SYSV@GOTPLT) & 65535), r1
+       gettr   tr0, r12
+       ldx.l   r1, r12, r1
+       ptabs   r1, tr0
+#else
+       pt/l    ffi_closure_helper_SYSV, tr0
+#endif
+       blink   tr0, r18
+
+       shlli   r2, 1, r1
+        movi    (((datalabel .L_table) >> 16) & 65535), r2
+        shori   ((datalabel .L_table) & 65535), r2
+        ldx.w   r2, r1, r1
+        add     r1, r2, r1
+       pt/l    .L_case_v, tr1
+        ptabs   r1, tr0
+        blink   tr0, r63
+
+        .align 2
+.L_table:
+       .word   .L_case_v - datalabel .L_table  /* FFI_TYPE_VOID */
+       .word   .L_case_i - datalabel .L_table  /* FFI_TYPE_INT */
+       .word   .L_case_f - datalabel .L_table  /* FFI_TYPE_FLOAT */
+       .word   .L_case_d - datalabel .L_table  /* FFI_TYPE_DOUBLE */
+       .word   .L_case_d - datalabel .L_table  /* FFI_TYPE_LONGDOUBLE */
+       .word   .L_case_uq - datalabel .L_table /* FFI_TYPE_UINT8 */
+       .word   .L_case_q - datalabel .L_table  /* FFI_TYPE_SINT8 */
+       .word   .L_case_uh - datalabel .L_table /* FFI_TYPE_UINT16 */
+       .word   .L_case_h - datalabel .L_table  /* FFI_TYPE_SINT16 */
+       .word   .L_case_i - datalabel .L_table  /* FFI_TYPE_UINT32 */
+       .word   .L_case_i - datalabel .L_table  /* FFI_TYPE_SINT32 */
+       .word   .L_case_ll - datalabel .L_table /* FFI_TYPE_UINT64 */
+       .word   .L_case_ll - datalabel .L_table /* FFI_TYPE_SINT64 */
+       .word   .L_case_v - datalabel .L_table  /* FFI_TYPE_STRUCT */
+       .word   .L_case_i - datalabel .L_table  /* FFI_TYPE_POINTER */
+
+        .align 2
+.L_case_d:
+       fld.d   r14, 16, dr0
+       blink   tr1, r63
+.L_case_f:
+       fld.s   r14, 16, fr0
+       blink   tr1, r63
+.L_case_ll:
+       ld.q    r14, 16, r2
+       blink   tr1, r63
+.L_case_i:
+       ld.l    r14, 16, r2
+       blink   tr1, r63
+.L_case_q:
+       ld.b    r14, 16, r2
+       blink   tr1, r63
+.L_case_uq:
+       ld.ub   r14, 16, r2
+       blink   tr1, r63
+.L_case_h:
+       ld.w    r14, 16, r2
+       blink   tr1, r63
+.L_case_uh:
+       ld.uw   r14, 16, r2
+       blink   tr1, r63
+.L_case_v:
+       add.l   r14, r63, r15
+       ld.l    r15, 4, r12
+       ld.l    r15, 8, r14
+       ld.l    r15, 12, r18
+       addi.l  r15, 136, r15
+       ptabs   r18, tr0
+       blink   tr0, r63
+
+.LFE2:
+.ffi_closure_SYSV_end:
+       .size    CNAME(ffi_closure_SYSV),.ffi_closure_SYSV_end-CNAME(ffi_closure_SYSV)
+
+       .section        ".eh_frame","aw",@progbits
+__FRAME_BEGIN__:
+       .4byte  .LECIE1-.LSCIE1 /* Length of Common Information Entry */
+.LSCIE1:
+       .4byte  0x0     /* CIE Identifier Tag */
+       .byte   0x1     /* CIE Version */
+       .ascii "zR\0"   /* CIE Augmentation */
+       .uleb128 0x1    /* CIE Code Alignment Factor */
+       .sleb128 -4     /* CIE Data Alignment Factor */
+       .byte   0x12    /* CIE RA Column */
+       .uleb128 0x1    /* Augmentation size */
+       .byte   0x1b    /* FDE Encoding (pcrel sdata4) */
+       .byte   0xc     /* DW_CFA_def_cfa */
+       .uleb128 0xf
+       .uleb128 0x0
+       .align  2
+.LECIE1:
+.LSFDE1:
+       .4byte  datalabel .LEFDE1-datalabel .LASFDE1    /* FDE Length */
+.LASFDE1:
+       .4byte  datalabel .LASFDE1-datalabel __FRAME_BEGIN__
+       .4byte  datalabel .LFB1-.               /* FDE initial location */
+       .4byte  datalabel .LFE1-datalabel .LFB1 /* FDE address range */
+       .byte   0x4     /* DW_CFA_advance_loc4 */
+       .4byte  datalabel .LCFI0-datalabel .LFB1
+       .byte   0xe     /* DW_CFA_def_cfa_offset */
+       .uleb128 0x30
+       .byte   0x4     /* DW_CFA_advance_loc4 */
+       .4byte  datalabel .LCFI1-datalabel .LCFI0
+       .byte   0x8e    /* DW_CFA_offset, column 0xe */
+       .uleb128 0xc
+       .byte   0x92    /* DW_CFA_offset, column 0x12 */
+       .uleb128 0xb
+       .byte   0x9c    /* DW_CFA_offset, column 0x1c */
+       .uleb128 0xa
+       .byte   0x9d    /* DW_CFA_offset, column 0x1d */
+       .uleb128 0x8
+       .byte   0x9e    /* DW_CFA_offset, column 0x1e */
+       .uleb128 0x6
+       .byte   0x9f    /* DW_CFA_offset, column 0x1f */
+       .uleb128 0x4
+       .byte   0xa0    /* DW_CFA_offset, column 0x20 */
+       .uleb128 0x2
+       .byte   0xd     /* DW_CFA_def_cfa_register */
+       .uleb128 0xe
+       .align  2
+.LEFDE1:
+
+.LSFDE3:
+       .4byte  datalabel .LEFDE3-datalabel .LASFDE3    /* FDE Length */
+.LASFDE3:
+       .4byte  datalabel .LASFDE3-datalabel __FRAME_BEGIN__
+       .4byte  datalabel .LFB2-.               /* FDE initial location */
+       .4byte  datalabel .LFE2-datalabel .LFB2 /* FDE address range */
+       .byte   0x4     /* DW_CFA_advance_loc4 */
+       .4byte  datalabel .LCFI2-datalabel .LFB2
+       .byte   0xe     /* DW_CFA_def_cfa_offset */
+       .uleb128 0x88
+       .byte   0x4     /* DW_CFA_advance_loc4 */
+       .4byte  datalabel .LCFI3-datalabel .LCFI2
+       .byte   0x8c    /* DW_CFA_offset, column 0xc */
+       .uleb128 0x21
+       .byte   0x8e    /* DW_CFA_offset, column 0xe */
+       .uleb128 0x20
+       .byte   0x92    /* DW_CFA_offset, column 0x12 */
+       .uleb128 0x1f
+       .byte   0xd     /* DW_CFA_def_cfa_register */
+       .uleb128 0xe
+       .align  2
+.LEFDE3: