Xtensa support
authorAnthony Green <green@moxielogic.com>
Mon, 21 Jan 2013 12:07:38 +0000 (07:07 -0500)
committerAnthony Green <green@moxielogic.com>
Mon, 21 Jan 2013 12:07:38 +0000 (07:07 -0500)
ChangeLog
Makefile.am
Makefile.in
README
configure
configure.ac
doc/stamp-vti
src/prep_cif.c
src/xtensa/ffi.c [new file with mode: 0644]
src/xtensa/ffitarget.h [new file with mode: 0644]
src/xtensa/sysv.S [new file with mode: 0644]

index 3d451b9..0e2c331 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,16 @@
+2013-01-21  Chris Zankel   <chris@zankel.net>
+
+       * README: Add Xtensa support.
+       * Makefile.am: Likewise.
+       * configure.ac: Likewise.
+       * Makefile.in Regenerate.
+       * configure: Likewise.
+       * src/prep_cif.c: Handle Xtensa.
+       * src/xtensa: New directory.
+       * src/xtensa/ffi.c: New file.
+       * src/xtensa/ffitarget.h: Ditto.
+       * src/xtensa/sysv.S: Ditto.
+
 2013-01-11  Anthony Green  <green@moxielogic.com>
 
        * src/powerpc/ffi_darwin.c (ffi_prep_args): Replace // style
index f2373fa..571e677 100644 (file)
@@ -32,6 +32,7 @@ EXTRA_DIST = LICENSE ChangeLog.v1 ChangeLog.libgcj configure.host     \
        src/bfin/ffitarget.h src/bfin/sysv.S src/frv/eabi.S             \
        src/frv/ffitarget.h src/dlmalloc.c src/tile/ffi.c               \
        src/tile/ffitarget.h src/tile/tile.S libtool-version            \
+       src/xtensa/ffitarget.h src/xtensa/ffi.c src/xtensa/sysv.S       \
         ChangeLog.libffi m4/libtool.m4 m4/lt~obsolete.m4               \
         m4/ltoptions.m4 m4/ltsugar.m4 m4/ltversion.m4                  \
         m4/ltversion.m4 src/arm/gentramp.sh src/debug.c msvcc.sh       \
@@ -189,6 +190,9 @@ endif
 if TILE
 nodist_libffi_la_SOURCES += src/tile/tile.S src/tile/ffi.c
 endif
+if XTENSA
+nodist_libffi_la_SOURCES += src/xtensa/sysv.S src/xtensa/ffi.c
+endif
 
 libffi_convenience_la_SOURCES = $(libffi_la_SOURCES)
 nodist_libffi_convenience_la_SOURCES = $(nodist_libffi_la_SOURCES)
index 696c804..d457e1e 100644 (file)
@@ -81,6 +81,7 @@ target_triplet = @target@
 @PA_LINUX_TRUE@am__append_28 = src/pa/linux.S src/pa/ffi.c
 @PA_HPUX_TRUE@am__append_29 = src/pa/hpux32.S src/pa/ffi.c
 @TILE_TRUE@am__append_30 = src/tile/tile.S src/tile/ffi.c
+@XTENSA_TRUE@am__append_31 = src/xtensa/sysv.S src/xtensa/ffi.c
 subdir = .
 DIST_COMMON = README $(am__configure_deps) $(srcdir)/Makefile.am \
        $(srcdir)/Makefile.in $(srcdir)/doc/stamp-vti \
@@ -187,6 +188,7 @@ am_libffi_la_OBJECTS = src/prep_cif.lo src/types.lo src/raw_api.lo \
 @PA_LINUX_TRUE@am__objects_28 = src/pa/linux.lo src/pa/ffi.lo
 @PA_HPUX_TRUE@am__objects_29 = src/pa/hpux32.lo src/pa/ffi.lo
 @TILE_TRUE@am__objects_30 = src/tile/tile.lo src/tile/ffi.lo
+@XTENSA_TRUE@am__objects_31 = src/xtensa/sysv.lo src/xtensa/ffi.lo
 nodist_libffi_la_OBJECTS = $(am__objects_1) $(am__objects_2) \
        $(am__objects_3) $(am__objects_4) $(am__objects_5) \
        $(am__objects_6) $(am__objects_7) $(am__objects_8) \
@@ -197,17 +199,17 @@ nodist_libffi_la_OBJECTS = $(am__objects_1) $(am__objects_2) \
        $(am__objects_21) $(am__objects_22) $(am__objects_23) \
        $(am__objects_24) $(am__objects_25) $(am__objects_26) \
        $(am__objects_27) $(am__objects_28) $(am__objects_29) \
-       $(am__objects_30)
+       $(am__objects_30) $(am__objects_31)
 libffi_la_OBJECTS = $(am_libffi_la_OBJECTS) \
        $(nodist_libffi_la_OBJECTS)
 libffi_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \
        $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
        $(libffi_la_LDFLAGS) $(LDFLAGS) -o $@
 libffi_convenience_la_LIBADD =
-am__objects_31 = src/prep_cif.lo src/types.lo src/raw_api.lo \
+am__objects_32 = src/prep_cif.lo src/types.lo src/raw_api.lo \
        src/java_raw_api.lo src/closures.lo
-am_libffi_convenience_la_OBJECTS = $(am__objects_31)
-am__objects_32 = $(am__objects_1) $(am__objects_2) $(am__objects_3) \
+am_libffi_convenience_la_OBJECTS = $(am__objects_32)
+am__objects_33 = $(am__objects_1) $(am__objects_2) $(am__objects_3) \
        $(am__objects_4) $(am__objects_5) $(am__objects_6) \
        $(am__objects_7) $(am__objects_8) $(am__objects_9) \
        $(am__objects_10) $(am__objects_11) $(am__objects_12) \
@@ -216,8 +218,9 @@ am__objects_32 = $(am__objects_1) $(am__objects_2) $(am__objects_3) \
        $(am__objects_19) $(am__objects_20) $(am__objects_21) \
        $(am__objects_22) $(am__objects_23) $(am__objects_24) \
        $(am__objects_25) $(am__objects_26) $(am__objects_27) \
-       $(am__objects_28) $(am__objects_29) $(am__objects_30)
-nodist_libffi_convenience_la_OBJECTS = $(am__objects_32)
+       $(am__objects_28) $(am__objects_29) $(am__objects_30) \
+       $(am__objects_31)
+nodist_libffi_convenience_la_OBJECTS = $(am__objects_33)
 libffi_convenience_la_OBJECTS = $(am_libffi_convenience_la_OBJECTS) \
        $(nodist_libffi_convenience_la_OBJECTS)
 DEFAULT_INCLUDES = -I.@am__isrc@
@@ -480,6 +483,7 @@ EXTRA_DIST = LICENSE ChangeLog.v1 ChangeLog.libgcj configure.host   \
        src/bfin/ffitarget.h src/bfin/sysv.S src/frv/eabi.S             \
        src/frv/ffitarget.h src/dlmalloc.c src/tile/ffi.c               \
        src/tile/ffitarget.h src/tile/tile.S libtool-version            \
+       src/xtensa/ffitarget.h src/xtensa/ffi.c src/xtensa/sysv.S       \
         ChangeLog.libffi m4/libtool.m4 m4/lt~obsolete.m4               \
         m4/ltoptions.m4 m4/ltsugar.m4 m4/ltversion.m4                  \
         m4/ltversion.m4 src/arm/gentramp.sh src/debug.c msvcc.sh       \
@@ -546,7 +550,7 @@ nodist_libffi_la_SOURCES = $(am__append_1) $(am__append_2) \
        $(am__append_21) $(am__append_22) $(am__append_23) \
        $(am__append_24) $(am__append_25) $(am__append_26) \
        $(am__append_27) $(am__append_28) $(am__append_29) \
-       $(am__append_30)
+       $(am__append_30) $(am__append_31)
 libffi_convenience_la_SOURCES = $(libffi_la_SOURCES)
 nodist_libffi_convenience_la_SOURCES = $(nodist_libffi_la_SOURCES)
 LTLDFLAGS = $(shell $(SHELL) $(top_srcdir)/../libtool-ldflags $(LDFLAGS))
@@ -892,6 +896,16 @@ src/tile/tile.lo: src/tile/$(am__dirstamp) \
        src/tile/$(DEPDIR)/$(am__dirstamp)
 src/tile/ffi.lo: src/tile/$(am__dirstamp) \
        src/tile/$(DEPDIR)/$(am__dirstamp)
+src/xtensa/$(am__dirstamp):
+       @$(MKDIR_P) src/xtensa
+       @: > src/xtensa/$(am__dirstamp)
+src/xtensa/$(DEPDIR)/$(am__dirstamp):
+       @$(MKDIR_P) src/xtensa/$(DEPDIR)
+       @: > src/xtensa/$(DEPDIR)/$(am__dirstamp)
+src/xtensa/sysv.lo: src/xtensa/$(am__dirstamp) \
+       src/xtensa/$(DEPDIR)/$(am__dirstamp)
+src/xtensa/ffi.lo: src/xtensa/$(am__dirstamp) \
+       src/xtensa/$(DEPDIR)/$(am__dirstamp)
 libffi.la: $(libffi_la_OBJECTS) $(libffi_la_DEPENDENCIES) $(EXTRA_libffi_la_DEPENDENCIES) 
        $(libffi_la_LINK) -rpath $(toolexeclibdir) $(libffi_la_OBJECTS) $(libffi_la_LIBADD) $(LIBS)
 libffi_convenience.la: $(libffi_convenience_la_OBJECTS) $(libffi_convenience_la_DEPENDENCIES) $(EXTRA_libffi_convenience_la_DEPENDENCIES) 
@@ -939,6 +953,8 @@ mostlyclean-compile:
        -rm -f src/tile/*.lo
        -rm -f src/x86/*.$(OBJEXT)
        -rm -f src/x86/*.lo
+       -rm -f src/xtensa/*.$(OBJEXT)
+       -rm -f src/xtensa/*.lo
 
 distclean-compile:
        -rm -f *.tab.c
@@ -1006,6 +1022,8 @@ distclean-compile:
 @AMDEP_TRUE@@am__include@ @am__quote@src/x86/$(DEPDIR)/unix64.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@src/x86/$(DEPDIR)/win32.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@src/x86/$(DEPDIR)/win64.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/xtensa/$(DEPDIR)/ffi.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/xtensa/$(DEPDIR)/sysv.Plo@am__quote@
 
 .S.o:
 @am__fastdepCCAS_TRUE@ depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\
@@ -1080,6 +1098,7 @@ clean-libtool:
        -rm -rf src/sparc/.libs src/sparc/_libs
        -rm -rf src/tile/.libs src/tile/_libs
        -rm -rf src/x86/.libs src/x86/_libs
+       -rm -rf src/xtensa/.libs src/xtensa/_libs
 
 distclean-libtool:
        -rm -f libtool config.lt
@@ -1642,6 +1661,8 @@ distclean-generic:
        -rm -f src/tile/$(am__dirstamp)
        -rm -f src/x86/$(DEPDIR)/$(am__dirstamp)
        -rm -f src/x86/$(am__dirstamp)
+       -rm -f src/xtensa/$(DEPDIR)/$(am__dirstamp)
+       -rm -f src/xtensa/$(am__dirstamp)
 
 maintainer-clean-generic:
        @echo "This command is intended for maintainers to use"
@@ -1654,7 +1675,7 @@ clean-am: clean-aminfo clean-generic clean-libtool \
 
 distclean: distclean-recursive
        -rm -f $(am__CONFIG_DISTCLEAN_FILES)
-       -rm -rf src/$(DEPDIR) src/aarch64/$(DEPDIR) src/alpha/$(DEPDIR) src/arm/$(DEPDIR) src/avr32/$(DEPDIR) src/bfin/$(DEPDIR) src/cris/$(DEPDIR) src/frv/$(DEPDIR) src/ia64/$(DEPDIR) src/m32r/$(DEPDIR) src/m68k/$(DEPDIR) src/mips/$(DEPDIR) src/pa/$(DEPDIR) src/powerpc/$(DEPDIR) src/s390/$(DEPDIR) src/sh/$(DEPDIR) src/sh64/$(DEPDIR) src/sparc/$(DEPDIR) src/tile/$(DEPDIR) src/x86/$(DEPDIR)
+       -rm -rf src/$(DEPDIR) src/aarch64/$(DEPDIR) src/alpha/$(DEPDIR) src/arm/$(DEPDIR) src/avr32/$(DEPDIR) src/bfin/$(DEPDIR) src/cris/$(DEPDIR) src/frv/$(DEPDIR) src/ia64/$(DEPDIR) src/m32r/$(DEPDIR) src/m68k/$(DEPDIR) src/mips/$(DEPDIR) src/pa/$(DEPDIR) src/powerpc/$(DEPDIR) src/s390/$(DEPDIR) src/sh/$(DEPDIR) src/sh64/$(DEPDIR) src/sparc/$(DEPDIR) src/tile/$(DEPDIR) src/x86/$(DEPDIR) src/xtensa/$(DEPDIR)
        -rm -f Makefile
 distclean-am: clean-am distclean-compile distclean-generic \
        distclean-hdr distclean-libtool distclean-tags
@@ -1793,7 +1814,7 @@ installcheck-am:
 maintainer-clean: maintainer-clean-recursive
        -rm -f $(am__CONFIG_DISTCLEAN_FILES)
        -rm -rf $(top_srcdir)/autom4te.cache
-       -rm -rf src/$(DEPDIR) src/aarch64/$(DEPDIR) src/alpha/$(DEPDIR) src/arm/$(DEPDIR) src/avr32/$(DEPDIR) src/bfin/$(DEPDIR) src/cris/$(DEPDIR) src/frv/$(DEPDIR) src/ia64/$(DEPDIR) src/m32r/$(DEPDIR) src/m68k/$(DEPDIR) src/mips/$(DEPDIR) src/pa/$(DEPDIR) src/powerpc/$(DEPDIR) src/s390/$(DEPDIR) src/sh/$(DEPDIR) src/sh64/$(DEPDIR) src/sparc/$(DEPDIR) src/tile/$(DEPDIR) src/x86/$(DEPDIR)
+       -rm -rf src/$(DEPDIR) src/aarch64/$(DEPDIR) src/alpha/$(DEPDIR) src/arm/$(DEPDIR) src/avr32/$(DEPDIR) src/bfin/$(DEPDIR) src/cris/$(DEPDIR) src/frv/$(DEPDIR) src/ia64/$(DEPDIR) src/m32r/$(DEPDIR) src/m68k/$(DEPDIR) src/mips/$(DEPDIR) src/pa/$(DEPDIR) src/powerpc/$(DEPDIR) src/s390/$(DEPDIR) src/sh/$(DEPDIR) src/sh64/$(DEPDIR) src/sparc/$(DEPDIR) src/tile/$(DEPDIR) src/x86/$(DEPDIR) src/xtensa/$(DEPDIR)
        -rm -f Makefile
 maintainer-clean-am: distclean-am maintainer-clean-aminfo \
        maintainer-clean-generic maintainer-clean-vti
diff --git a/README b/README
index 1abad25..3684ed6 100644 (file)
--- a/README
+++ b/README
@@ -99,6 +99,7 @@ tested:
 | X86-64          | OpenBSD          | GCC                     |
 | X86-64          | Solaris          | Oracle Solaris Studio C |
 | X86-64          | Windows/MingW    | GCC                     |
+| Xtensa          | Linux            | GCC                     |
 |-----------------+------------------+-------------------------|
 
 Please send additional platform test results to
@@ -160,6 +161,7 @@ See the ChangeLog files for details.
        Add Blackfin support.
        Add TILE-Gx/TILEPro support.
        Add AArch64 support.
+       Add Xtensa support.
        Add support for PaX enabled kernels with MPROTECT.
        Add support for native vendor compilers on
          Solaris and AIX.
@@ -355,6 +357,7 @@ sparc               Anthony Green, Gordon Irlam
 tile-gx/tilepro Walter Lee
 x86            Anthony Green, Jon Beniston
 x86-64         Bo Thorsen
+xtensa         Chris Zankel
 
 Jesper Skov and Andrew Haley both did more than their fair share of
 stepping through the code and tracking down bugs.
index 41bde69..2af0ff1 100755 (executable)
--- a/configure
+++ b/configure
@@ -647,6 +647,8 @@ FFI_EXEC_TRAMPOLINE_TABLE_TRUE
 sys_symbol_underscore
 HAVE_LONG_DOUBLE
 ALLOCA
+XTENSA_FALSE
+XTENSA_TRUE
 TILE_FALSE
 TILE_TRUE
 PA64_HPUX_FALSE
@@ -13452,6 +13454,10 @@ case "$host" in
        fi
        ;;
 
+  xtensa*-*)
+       TARGET=XTENSA; TARGETDIR=xtensa
+       ;;
+
 esac
 
 
@@ -13701,6 +13707,14 @@ else
   TILE_FALSE=
 fi
 
+ if test x$TARGET = xXTENSA; then
+  XTENSA_TRUE=
+  XTENSA_FALSE='#'
+else
+  XTENSA_TRUE='#'
+  XTENSA_FALSE=
+fi
+
 
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ANSI C header files" >&5
 $as_echo_n "checking for ANSI C header files... " >&6; }
@@ -15071,6 +15085,10 @@ if test -z "${TILE_TRUE}" && test -z "${TILE_FALSE}"; then
   as_fn_error $? "conditional \"TILE\" was never defined.
 Usually this means the macro was only invoked conditionally." "$LINENO" 5
 fi
+if test -z "${XTENSA_TRUE}" && test -z "${XTENSA_FALSE}"; then
+  as_fn_error $? "conditional \"XTENSA\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
 
 if test -z "${FFI_EXEC_TRAMPOLINE_TABLE_TRUE}" && test -z "${FFI_EXEC_TRAMPOLINE_TABLE_FALSE}"; then
   as_fn_error $? "conditional \"FFI_EXEC_TRAMPOLINE_TABLE\" was never defined.
index 32ec7c5..db91985 100644 (file)
@@ -237,6 +237,10 @@ case "$host" in
        fi
        ;;
 
+  xtensa*-*)
+       TARGET=XTENSA; TARGETDIR=xtensa
+       ;;
+
 esac
 
 AC_SUBST(AM_RUNTESTFLAGS)
@@ -276,6 +280,7 @@ AM_CONDITIONAL(PA_LINUX, test x$TARGET = xPA_LINUX)
 AM_CONDITIONAL(PA_HPUX, test x$TARGET = xPA_HPUX)
 AM_CONDITIONAL(PA64_HPUX, test x$TARGET = xPA64_HPUX)
 AM_CONDITIONAL(TILE, test x$TARGET = xTILE)
+AM_CONDITIONAL(XTENSA, test x$TARGET = xXTENSA)
 
 AC_HEADER_STDC
 AC_CHECK_FUNCS(memcpy)
index 81d0b79..2abd242 100644 (file)
@@ -1,4 +1,4 @@
-@set UPDATED 14 February 2008
-@set UPDATED-MONTH February 2008
-@set EDITION 3.0.8
-@set VERSION 3.0.8
+@set UPDATED 23 December 2012
+@set UPDATED-MONTH December 2012
+@set EDITION 3.0.12-rc0
+@set VERSION 3.0.12-rc0
index 5d1924b..e8ec5cf 100644 (file)
@@ -143,6 +143,10 @@ ffi_status FFI_HIDDEN ffi_prep_cif_core(ffi_cif *cif, ffi_abi abi,
 #ifdef TILE
       && (cif->rtype->size > 10 * FFI_SIZEOF_ARG)
 #endif
+#ifdef XTENSA
+      && (cif->rtype->size > 16)
+#endif
+
      )
     bytes = STACK_ARG_SIZE(sizeof(void*));
 #endif
@@ -181,6 +185,10 @@ ffi_status FFI_HIDDEN ffi_prep_cif_core(ffi_cif *cif, ffi_abi abi,
              bytes = 10 * FFI_SIZEOF_ARG;
            }
 #endif
+#ifdef XTENSA
+         if (bytes <= 6*4 && bytes + STACK_ARG_SIZE((*ptr)->size) > 6*4)
+           bytes = 6*4;
+#endif
 
          bytes += STACK_ARG_SIZE((*ptr)->size);
        }
diff --git a/src/xtensa/ffi.c b/src/xtensa/ffi.c
new file mode 100644 (file)
index 0000000..fd94daf
--- /dev/null
@@ -0,0 +1,298 @@
+/* -----------------------------------------------------------------------
+   ffi.c - Copyright (c) 2013 Tensilica, Inc.
+
+   XTENSA 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 THE AUTHORS OR COPYRIGHT
+   HOLDERS 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>
+
+/*
+                                 |----------------------------------------|
+                                 |                                        |
+    on entry to ffi_call ---->   |----------------------------------------|
+                                 | caller stack frame for registers a0-a3 |
+                                 |----------------------------------------|
+                                 |                                        |
+                                 |         additional arguments           |
+    entry of the function --->   |----------------------------------------|
+                                 |    copy of function arguments a2-a7    |
+                                 | -  -  -  -  -  -  -  -  -  -  -  -  -  |
+                                 |                                        |
+
+    The area below the entry line becomes the new stack frame for the function.
+
+*/
+
+
+#define FFI_TYPE_STRUCT_REGS FFI_TYPE_LAST
+
+
+extern void ffi_call_SYSV(void *rvalue, unsigned rsize, unsigned flags,
+                         void(*fn)(void), unsigned nbytes, extended_cif*);
+extern void ffi_closure_SYSV(void) FFI_HIDDEN;
+
+ffi_status ffi_prep_cif_machdep(ffi_cif *cif)
+{
+  switch(cif->rtype->type) {
+    case FFI_TYPE_SINT8:
+    case FFI_TYPE_UINT8:
+    case FFI_TYPE_SINT16:
+    case FFI_TYPE_UINT16:
+      cif->flags = cif->rtype->type;
+      break;
+    case FFI_TYPE_VOID:
+    case FFI_TYPE_FLOAT:
+      cif->flags = FFI_TYPE_UINT32;
+      break;
+    case FFI_TYPE_DOUBLE:
+    case FFI_TYPE_UINT64:
+    case FFI_TYPE_SINT64:
+      cif->flags = FFI_TYPE_UINT64; // cif->rtype->type;
+      break;
+    case FFI_TYPE_STRUCT:
+      cif->flags = FFI_TYPE_STRUCT; //_REGS;
+      /* Up to 16 bytes are returned in registers */
+      if (cif->rtype->size > 4 * 4) {
+        /* returned structure is referenced by a register; use 8 bytes
+           (including 4 bytes for potential additional alignment) */
+        cif->flags = FFI_TYPE_STRUCT;  
+        cif->bytes += 8;
+      }
+      break;
+
+    default:
+      cif->flags = FFI_TYPE_UINT32;
+      break;
+  }
+
+  /* Round the stack up to a full 4 register frame, just in case
+     (we use this size in movsp). This way, it's also a  multiple of
+     8 bytes for 64-bit arguments.  */
+  cif->bytes = ALIGN(cif->bytes, 16);
+
+  return FFI_OK;
+}
+
+void ffi_prep_args(extended_cif *ecif, unsigned char* stack)
+{
+  unsigned int i;
+  unsigned long *addr;
+  ffi_type **ptr;
+
+  union {
+    void **v;
+    char **c;
+    signed char **sc;
+    unsigned char **uc;
+    signed short **ss;
+    unsigned short **us;
+    unsigned int **i;
+    long long **ll;
+    float **f;
+    double **d;
+  } p_argv;
+
+  /* Verify that everything is aligned up properly */
+  FFI_ASSERT (((unsigned long) stack & 0x7) == 0);
+
+  p_argv.v = ecif->avalue;
+  addr = (unsigned long*)stack;
+
+  /* structures with a size greater than 16 bytes are passed in memory */
+  if (ecif->cif->rtype->type == FFI_TYPE_STRUCT && ecif->cif->rtype->size > 16)
+  {
+    *addr++ = (unsigned long)ecif->rvalue;
+  }
+
+  for (i = ecif->cif->nargs, ptr = ecif->cif->arg_types;
+       i > 0;
+       i--, ptr++, p_argv.v++)
+  {
+    switch ((*ptr)->type)
+    {
+      case FFI_TYPE_SINT8:
+        *addr++ = **p_argv.sc;
+        break;
+      case FFI_TYPE_UINT8:
+        *addr++ = **p_argv.uc;
+        break;
+      case FFI_TYPE_SINT16:
+        *addr++ = **p_argv.ss;
+        break;
+      case FFI_TYPE_UINT16:
+        *addr++ = **p_argv.us;
+        break;
+      case FFI_TYPE_FLOAT:
+      case FFI_TYPE_INT:
+      case FFI_TYPE_UINT32:
+      case FFI_TYPE_SINT32:
+      case FFI_TYPE_POINTER:
+        *addr++ = **p_argv.i;
+        break;
+      case FFI_TYPE_DOUBLE:
+      case FFI_TYPE_UINT64:
+      case FFI_TYPE_SINT64:
+        if (((unsigned long)addr & 4) != 0)
+          addr++;
+        *(unsigned long long*)addr = **p_argv.ll;
+       addr += sizeof(unsigned long long) / sizeof (addr);
+        break;
+
+      case FFI_TYPE_STRUCT:
+      {
+        unsigned long offs;
+        unsigned long size;
+
+        if (((unsigned long)addr & 4) != 0 && (*ptr)->alignment > 4)
+          addr++;
+
+        offs = (unsigned long) addr - (unsigned long) stack;
+        size = (*ptr)->size;
+
+        /* Entire structure must fit the argument registers or referenced */
+        if (offs < FFI_REGISTER_NARGS * 4
+            && offs + size > FFI_REGISTER_NARGS * 4)
+          addr = (unsigned long*) (stack + FFI_REGISTER_NARGS * 4);
+
+        memcpy((char*) addr, *p_argv.c, size);
+        addr += (size + 3) / 4;
+        break;
+      }
+
+      default:
+        FFI_ASSERT(0);
+    }
+  }
+}
+
+
+void ffi_call(ffi_cif* cif, void(*fn)(void), void *rvalue, void **avalue)
+{
+  extended_cif ecif;
+  unsigned long rsize = cif->rtype->size;
+  int flags = cif->flags;
+  void *alloc = NULL;
+
+  ecif.cif = cif;
+  ecif.avalue = avalue;
+
+  /* Note that for structures that are returned in registers (size <= 16 bytes)
+     we allocate a temporary buffer and use memcpy to copy it to the final 
+     destination. The reason is that the target address might be misaligned or
+     the length not a multiple of 4 bytes. Handling all those cases would be
+     very complex.  */
+
+  if (flags == FFI_TYPE_STRUCT && (rsize <= 16 || rvalue == NULL))
+  {
+    alloc = alloca(ALIGN(rsize, 4));
+    ecif.rvalue = alloc;
+  }
+  else
+  {
+    ecif.rvalue = rvalue;
+  }
+
+  if (cif->abi != FFI_SYSV)
+    FFI_ASSERT(0);
+
+  ffi_call_SYSV (ecif.rvalue, rsize, cif->flags, fn, cif->bytes, &ecif);
+
+  if (alloc != NULL && rvalue != NULL)
+    memcpy(rvalue, alloc, rsize);
+}
+
+extern void ffi_trampoline();
+extern void ffi_cacheflush(void* start, void* end);
+
+ffi_status
+ffi_prep_closure_loc (ffi_closure* closure,
+                      ffi_cif* cif,
+                      void (*fun)(ffi_cif*, void*, void**, void*),
+                      void *user_data,
+                      void *codeloc)
+{
+  /* copye trampoline to stack and patch 'ffi_closure_SYSV' pointer */
+  memcpy(closure->tramp, ffi_trampoline, FFI_TRAMPOLINE_SIZE);
+  *(unsigned int*)(&closure->tramp[8]) = (unsigned int)ffi_closure_SYSV;
+
+  // Do we have this function?
+  // __builtin___clear_cache(closer->tramp, closer->tramp + FFI_TRAMPOLINE_SIZE)
+  ffi_cacheflush(closure->tramp, closure->tramp + FFI_TRAMPOLINE_SIZE);
+
+  closure->cif = cif;
+  closure->fun = fun;
+  closure->user_data = user_data;
+  return FFI_OK; 
+}
+
+
+long FFI_HIDDEN
+ffi_closure_SYSV_inner(ffi_closure *closure, void **values, void *rvalue)
+{
+  ffi_cif *cif;
+  ffi_type **arg_types;
+  void **avalue;
+  int i, areg;
+
+  cif = closure->cif;
+  if (cif->abi != FFI_SYSV)
+    return FFI_BAD_ABI;
+
+  areg = 0;
+
+  int rtype = cif->rtype->type;
+  if (rtype == FFI_TYPE_STRUCT && cif->rtype->size > 4 * 4)
+  {
+    rvalue = *values;
+    areg++;
+  }
+
+  cif = closure->cif; 
+  arg_types = cif->arg_types;
+  avalue = alloca(cif->nargs * sizeof(void *));
+
+  for (i = 0; i < cif->nargs; i++)
+  {
+    if (arg_types[i]->alignment == 8 && (areg & 1) != 0)
+      areg++;
+
+    // skip the entry 16,a1 framework, add 16 bytes (4 registers)
+    if (areg == FFI_REGISTER_NARGS)
+      areg += 4;
+
+    if (arg_types[i]->type == FFI_TYPE_STRUCT)
+    {
+      int numregs = ((arg_types[i]->size + 3) & ~3) / 4;
+      if (areg < FFI_REGISTER_NARGS && areg + numregs > FFI_REGISTER_NARGS)
+        areg = FFI_REGISTER_NARGS + 4;
+    }
+
+    avalue[i] = &values[areg];
+    areg += (arg_types[i]->size + 3) / 4;
+  }
+
+  (closure->fun)(cif, rvalue, avalue, closure->user_data);
+
+  return rtype;
+}
diff --git a/src/xtensa/ffitarget.h b/src/xtensa/ffitarget.h
new file mode 100644 (file)
index 0000000..0ba728b
--- /dev/null
@@ -0,0 +1,53 @@
+/* -----------------------------------------------------------------*-C-*-
+   ffitarget.h - Copyright (c) 2013 Tensilica, Inc.
+   Target configuration macros for XTENSA.
+
+   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 THE AUTHORS OR COPYRIGHT
+   HOLDERS 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_H
+#error "Please do not include ffitarget.h directly into your source.  Use ffi.h instead."
+#endif
+
+#ifndef LIBFFI_ASM
+typedef unsigned long  ffi_arg;
+typedef signed long    ffi_sarg;
+
+typedef enum ffi_abi {
+  FFI_FIRST_ABI = 0,
+  FFI_SYSV,
+  FFI_LAST_ABI,
+  FFI_DEFAULT_ABI = FFI_SYSV
+} ffi_abi;
+#endif
+
+#define FFI_REGISTER_NARGS     6
+
+/* ---- Definitions for closures ----------------------------------------- */
+
+#define FFI_CLOSURES 1
+#define FFI_NATIVE_RAW_API 0
+#define FFI_TRAMPOLINE_SIZE 24
+
+#endif
diff --git a/src/xtensa/sysv.S b/src/xtensa/sysv.S
new file mode 100644 (file)
index 0000000..64e6a09
--- /dev/null
@@ -0,0 +1,253 @@
+/* -----------------------------------------------------------------------
+   sysv.S - Copyright (c) 2013 Tensilica, Inc.
+   
+   XTENSA 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 THE AUTHORS OR COPYRIGHT
+   HOLDERS 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 <fficonfig.h>
+#include <ffi.h>
+
+#define ENTRY(name) .text; .globl name; .type  name,@function; .align 4; name:
+#define END(name) .size name , . - name
+
+/* Assert that the table below is in sync with ffi.h.  */
+
+#if       FFI_TYPE_UINT8 != 5          \
+        || FFI_TYPE_SINT8 != 6          \
+        || FFI_TYPE_UINT16 != 7         \
+        || FFI_TYPE_SINT16 != 8         \
+        || FFI_TYPE_UINT32 != 9         \
+        || FFI_TYPE_SINT32 != 10        \
+        || FFI_TYPE_UINT64 != 11
+#error "xtensa/sysv.S out of sync with ffi.h"
+#endif
+
+
+/* ffi_call_SYSV (rvalue, rbytes, flags, (*fnaddr)(), bytes, ecif)
+      void *rvalue;            a2
+      unsigned long rbytes;    a3
+      unsigned flags;          a4
+      void (*fnaddr)();        a5
+      unsigned long bytes;     a6
+      extended_cif* ecif)      a7
+*/
+
+ENTRY(ffi_call_SYSV)
+
+       entry   a1, 32              # 32 byte frame for using call8 below
+
+       mov     a10, a7             # a10(->arg0): ecif
+       sub     a11, a1, a6         # a11(->arg1): stack pointer
+       mov     a7, a1              # fp
+       movsp   a1, a11             # set new sp = old_sp - bytes
+
+       movi    a8, ffi_prep_args
+       callx8  a8                  # ffi_prep_args(ecif, stack)
+
+       # prepare to move stack pointer back up to 6 arguments
+       # note that 'bytes' is already aligned
+
+       movi    a10, 6*4 
+       sub     a11, a6, a10
+       movgez  a6, a10, a11
+       add     a6, a1, a6
+
+       
+       # we can pass up to 6 arguments in registers
+       # for simplicity, just load 6 arguments
+       # (the stack size is at least 32 bytes, so no risk to cross boundaries)
+
+       l32i    a10, a1, 0
+       l32i    a11, a1, 4
+       l32i    a12, a1, 8
+       l32i    a13, a1, 12
+       l32i    a14, a1, 16
+       l32i    a15, a1, 20
+
+       # move stack pointer
+
+       movsp   a1, a6
+
+       callx8  a5                  # (*fn)(args...)
+
+       # Handle return value(s)
+
+       beqz    a2, .Lexit
+
+       movi    a5, FFI_TYPE_STRUCT
+       bne     a4, a5, .Lstore
+       movi    a5, 16
+       blt     a5, a3, .Lexit
+
+       s32i    a10, a2, 0
+       blti    a3, 5, .Lexit
+       addi    a3, a3, -1
+       s32i    a11, a2, 4
+       blti    a3, 8, .Lexit
+       s32i    a12, a2, 8
+       blti    a3, 12, .Lexit
+       s32i    a13, a2, 12
+
+.Lexit:        retw
+
+.Lstore:
+       addi    a4, a4, -FFI_TYPE_UINT8
+       bgei    a4, 7, .Lexit   # should never happen
+       movi    a6, store_calls
+       add     a4, a4, a4
+       addx4   a6, a4, a6      # store_table + idx * 8
+       jx      a6
+
+       .align  8
+store_calls:
+       # UINT8
+       s8i     a10, a2, 0
+       retw
+
+       # SINT8
+       .align  8
+       s8i     a10, a2, 0
+       retw
+
+       # UINT16
+       .align  8
+       s16i    a10, a2, 0
+       retw
+
+       # SINT16
+       .align  8
+       s16i    a10, a2, 0
+       retw
+
+       # UINT32
+       .align  8
+       s32i    a10, a2, 0
+       retw
+
+       # SINT32
+       .align  8
+       s32i    a10, a2, 0
+       retw
+
+       # UINT64
+       .align  8
+       s32i    a10, a2, 0
+       s32i    a11, a2, 4
+       retw
+
+END(ffi_call_SYSV)
+
+
+/*
+ * void ffi_cacheflush (unsigned long start, unsigned long end)
+ */
+
+#define EXTRA_ARGS_SIZE        24
+
+ENTRY(ffi_cacheflush)
+
+       entry   a1, 16
+
+1:     dhwbi   a2, 0
+       ihi     a2, 0
+       addi    a2, a2, 4
+       blt     a2, a3, 1b
+
+       retw
+
+END(ffi_cacheflush)
+
+/* ffi_trampoline is copied to the stack */
+
+ENTRY(ffi_trampoline)
+
+       entry   a1, 16 + (FFI_REGISTER_NARGS * 4) + (4 * 4)   # [ 0]
+       j       2f                                # [ 3]
+       .align  4                                 # [ 6]
+1:     .long   0                                 # [ 8]
+2:     l32r    a15, 1b                           # [12]
+       _mov    a14, a0                           # [15]
+       callx0  a15                               # [18]
+                                                  # [21]
+END(ffi_trampoline)
+
+/*
+ * ffi_closure()
+ *
+ * a0:  closure + 21
+ * a14: return address (a0)
+ */
+
+ENTRY(ffi_closure_SYSV)
+
+       /* intentionally omitting entry here */
+
+       # restore return address (a0) and move pointer to closure to a10
+       addi    a10, a0, -21
+       mov     a0, a14
+
+       # allow up to 4 arguments as return values
+       addi    a11, a1, 4 * 4
+
+       # save up to 6 arguments to stack (allocated by entry below)
+       s32i    a2, a11,  0
+       s32i    a3, a11,  4
+       s32i    a4, a11,  8
+       s32i    a5, a11, 12
+       s32i    a6, a11, 16
+       s32i    a7, a11, 20
+
+       movi    a8, ffi_closure_SYSV_inner
+       mov     a12, a1
+       callx8  a8                      # .._inner(*closure, **avalue, *rvalue)
+
+       # load up to four return arguments
+       l32i    a2, a1,  0
+       l32i    a3, a1,  4
+       l32i    a4, a1,  8
+       l32i    a5, a1, 12
+
+       # (sign-)extend return value
+       movi    a11, FFI_TYPE_UINT8
+       bne     a10, a11, 1f
+       extui   a2, a2, 0, 8
+       retw
+
+1:     movi    a11, FFI_TYPE_SINT8
+       bne     a10, a11, 1f
+       sext    a2, a2, 7
+       retw
+
+1:     movi    a11, FFI_TYPE_UINT16
+       bne     a10, a11, 1f
+       extui   a2, a2, 0, 16
+       retw
+
+1:     movi    a11, FFI_TYPE_SINT16
+       bne     a10, a11, 1f
+       sext    a2, a2, 15
+
+1:     retw
+
+END(ffi_closure_SYSV)