summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAnthony Green <green@moxielogic.com>2013-01-21 07:07:38 -0500
committerAnthony Green <green@moxielogic.com>2013-01-21 07:07:38 -0500
commit20cae32b152b43679ae65a85db9a1c6bb8a143dd (patch)
tree815bf275d334937c468fed76630e4ad907d791c9
parent9742f91782faef4a15941508a22c408fb7d1d227 (diff)
downloadlibffi-20cae32b152b43679ae65a85db9a1c6bb8a143dd.tar.gz
Xtensa support
-rw-r--r--ChangeLog13
-rw-r--r--Makefile.am4
-rw-r--r--Makefile.in39
-rw-r--r--README3
-rwxr-xr-xconfigure18
-rw-r--r--configure.ac5
-rw-r--r--doc/stamp-vti8
-rw-r--r--src/prep_cif.c8
-rw-r--r--src/xtensa/ffi.c298
-rw-r--r--src/xtensa/ffitarget.h53
-rw-r--r--src/xtensa/sysv.S253
11 files changed, 689 insertions, 13 deletions
diff --git a/ChangeLog b/ChangeLog
index 3d451b9..0e2c331 100644
--- 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
diff --git a/Makefile.am b/Makefile.am
index f2373fa..571e677 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -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)
diff --git a/Makefile.in b/Makefile.in
index 696c804..d457e1e 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -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
--- 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.
diff --git a/configure b/configure
index 41bde69..2af0ff1 100755
--- 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.
diff --git a/configure.ac b/configure.ac
index 32ec7c5..db91985 100644
--- a/configure.ac
+++ b/configure.ac
@@ -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)
diff --git a/doc/stamp-vti b/doc/stamp-vti
index 81d0b79..2abd242 100644
--- a/doc/stamp-vti
+++ b/doc/stamp-vti
@@ -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
diff --git a/src/prep_cif.c b/src/prep_cif.c
index 5d1924b..e8ec5cf 100644
--- a/src/prep_cif.c
+++ b/src/prep_cif.c
@@ -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
index 0000000..fd94daf
--- /dev/null
+++ b/src/xtensa/ffi.c
@@ -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
index 0000000..0ba728b
--- /dev/null
+++ b/src/xtensa/ffitarget.h
@@ -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
index 0000000..64e6a09
--- /dev/null
+++ b/src/xtensa/sysv.S
@@ -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)