public inbox for libffi-discuss@sourceware.org
 help / color / mirror / Atom feed
From: Walter Lee <walt@tilera.com>
To: Walter Lee <walt@tilera.com>
Cc: <libffi-discuss@sourceware.org>
Subject: Re: [PATCH] new port for TILE-Gx/TILEPro
Date: Wed, 08 Aug 2012 18:46:00 -0000	[thread overview]
Message-ID: <5022B3D6.3040401@tilera.com> (raw)
In-Reply-To: <201207102148.q6ALmm6S019170@farm-0039.internal.tilera.com>

Ping?  Is there something else I need to do?

Thanks,

Walter

On 7/10/2012 5:48 PM, Walter Lee wrote:
> On behalf of Tilera Corporation, I would like to contribute libffi
> ports for the TILE-Gx and TILEPro architectures.  The ports have been
> in use for over two years, and they pass the test suite cleanly.  The
> ChangeLog entry and the patch are included below.  Please let me know
> if there is anything else I need to do.
>
> Thanks,
>
> Walter Lee
>
> 2012-07-10  Walter Lee  <walt@tilera.com>
>
> 	* Makefile.am: Add TILE-Gx/TILEPro support.
> 	* configure.ac: Likewise.
> 	* Makefile.in: Regenerate.
> 	* configure: Likewise.
> 	* src/prep_cif.c (ffi_prep_cif_core): Handle TILE-Gx/TILEPro.
> 	* src/tile: New directory.
> 	* src/tile/ffi.c: New file.
> 	* src/tile/ffitarget.h: Ditto.
> 	* src/tile/tile.S: Ditto.
>
> ----------------------------------------------------------------
>
> diff -ruP orig/libffi/Makefile.am libffi/Makefile.am
> --- orig/libffi/Makefile.am	2012-07-10 17:17:21.879017000 -0400
> +++ libffi/Makefile.am	2012-07-10 17:24:59.475868000 -0400
> @@ -29,11 +29,12 @@
>   	src/pa/ffi.c src/pa/linux.S src/pa/hpux32.S src/frv/ffi.c \
>   	src/bfin/ffi.c src/bfin/ffitarget.h src/bfin/sysv.S \
>   	src/frv/eabi.S src/frv/ffitarget.h src/dlmalloc.c \
> -	src/moxie/ffi.c src/moxie/eabi.S libtool-version \
> -	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 generate-ios-source-and-headers.py \
> +	src/moxie/ffi.c src/moxie/eabi.S src/tile/ffi.c \
> +	src/tile/tile.S libtool-version 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 \
> +	generate-ios-source-and-headers.py \
>   	generate-osx-source-and-headers.py \
>           libffi.xcodeproj/project.pbxproj \
>   	src/arm/trampoline.S
> @@ -187,6 +188,9 @@
>   if PA_HPUX
>   nodist_libffi_la_SOURCES += src/pa/hpux32.S src/pa/ffi.c
>   endif
> +if TILE
> +nodist_libffi_la_SOURCES += src/tile/tile.S src/tile/ffi.c
> +endif
>   
>   libffi_convenience_la_SOURCES = $(libffi_la_SOURCES)
>   nodist_libffi_convenience_la_SOURCES = $(nodist_libffi_la_SOURCES)
> diff -ruP orig/libffi/Makefile.in libffi/Makefile.in
> --- orig/libffi/Makefile.in	2012-07-10 17:17:21.881014000 -0400
> +++ libffi/Makefile.in	2012-07-10 17:31:20.642098000 -0400
> @@ -65,9 +65,10 @@
>   @SH64_TRUE@am__append_27 = src/sh64/sysv.S src/sh64/ffi.c
>   @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
>   # Build debug. Define FFI_DEBUG on the commandline so that, when building with
>   # MSVC, it can link against the debug CRT.
> -@FFI_DEBUG_TRUE@am__append_30 = -DFFI_DEBUG
> +@FFI_DEBUG_TRUE@am__append_31 = -DFFI_DEBUG
>   subdir = .
>   DIST_COMMON = README $(am__configure_deps) $(srcdir)/Makefile.am \
>   	$(srcdir)/Makefile.in $(srcdir)/doc/stamp-vti \
> @@ -156,6 +157,7 @@
>   @SH64_TRUE@am__objects_27 = src/sh64/sysv.lo src/sh64/ffi.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
>   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) \
> @@ -165,17 +167,18 @@
>   	$(am__objects_18) $(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_27) $(am__objects_28) $(am__objects_29) \
> +	$(am__objects_30)
>   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_30 = src/prep_cif.lo src/types.lo src/raw_api.lo \
> +am__objects_31 = 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_30)
> -am__objects_31 = $(am__objects_1) $(am__objects_2) $(am__objects_3) \
> +am_libffi_convenience_la_OBJECTS = $(am__objects_31)
> +am__objects_32 = $(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) \
> @@ -184,8 +187,8 @@
>   	$(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)
> -nodist_libffi_convenience_la_OBJECTS = $(am__objects_31)
> +	$(am__objects_28) $(am__objects_29) $(am__objects_30)
> +nodist_libffi_convenience_la_OBJECTS = $(am__objects_32)
>   libffi_convenience_la_OBJECTS = $(am_libffi_convenience_la_OBJECTS) \
>   	$(nodist_libffi_convenience_la_OBJECTS)
>   DEFAULT_INCLUDES = -I.@am__isrc@
> @@ -434,11 +437,12 @@
>   	src/pa/ffi.c src/pa/linux.S src/pa/hpux32.S src/frv/ffi.c \
>   	src/bfin/ffi.c src/bfin/ffitarget.h src/bfin/sysv.S \
>   	src/frv/eabi.S src/frv/ffitarget.h src/dlmalloc.c \
> -	src/moxie/ffi.c src/moxie/eabi.S libtool-version \
> -	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 generate-ios-source-and-headers.py \
> +	src/moxie/ffi.c src/moxie/eabi.S src/tile/ffi.c \
> +	src/tile/tile.S libtool-version 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 \
> +	generate-ios-source-and-headers.py \
>   	generate-osx-source-and-headers.py \
>           libffi.xcodeproj/project.pbxproj \
>   	src/arm/trampoline.S
> @@ -501,10 +505,11 @@
>   	$(am__append_18) $(am__append_19) $(am__append_20) \
>   	$(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_27) $(am__append_28) $(am__append_29) \
> +	$(am__append_30)
>   libffi_convenience_la_SOURCES = $(libffi_la_SOURCES)
>   nodist_libffi_convenience_la_SOURCES = $(nodist_libffi_la_SOURCES)
> -AM_CFLAGS = -g $(am__append_30)
> +AM_CFLAGS = -g $(am__append_31)
>   libffi_la_LDFLAGS = -version-info `grep -v '^\#' $(srcdir)/libtool-version` $(LTLDFLAGS) $(AM_LTLDFLAGS)
>   AM_CPPFLAGS = -I. -I$(top_srcdir)/include -Iinclude -I$(top_srcdir)/src -DFFI_BUILDING
>   AM_CCASFLAGS = $(AM_CPPFLAGS) -g
> @@ -834,6 +839,16 @@
>   src/pa/ffi.lo: src/pa/$(am__dirstamp) src/pa/$(DEPDIR)/$(am__dirstamp)
>   src/pa/hpux32.lo: src/pa/$(am__dirstamp) \
>   	src/pa/$(DEPDIR)/$(am__dirstamp)
> +src/tile/$(am__dirstamp):
> +	@$(MKDIR_P) src/tile
> +	@: > src/tile/$(am__dirstamp)
> +src/tile/$(DEPDIR)/$(am__dirstamp):
> +	@$(MKDIR_P) src/tile/$(DEPDIR)
> +	@: > src/tile/$(DEPDIR)/$(am__dirstamp)
> +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)
>   libffi.la: $(libffi_la_OBJECTS) $(libffi_la_DEPENDENCIES)
>   	$(libffi_la_LINK) -rpath $(libdir) $(libffi_la_OBJECTS) $(libffi_la_LIBADD) $(LIBS)
>   libffi_convenience.la: $(libffi_convenience_la_OBJECTS) $(libffi_convenience_la_DEPENDENCIES)
> @@ -943,6 +958,10 @@
>   	-rm -f src/sparc/v8.lo
>   	-rm -f src/sparc/v9.$(OBJEXT)
>   	-rm -f src/sparc/v9.lo
> +	-rm -f src/tile/ffi.$(OBJEXT)
> +	-rm -f src/tile/ffi.lo
> +	-rm -f src/tile/tile.$(OBJEXT)
> +	-rm -f src/tile/tile.lo
>   	-rm -f src/types.$(OBJEXT)
>   	-rm -f src/types.lo
>   	-rm -f src/x86/darwin.$(OBJEXT)
> @@ -1019,6 +1038,8 @@
>   @AMDEP_TRUE@@am__include@ @am__quote@src/sparc/$(DEPDIR)/ffi.Plo@am__quote@
>   @AMDEP_TRUE@@am__include@ @am__quote@src/sparc/$(DEPDIR)/v8.Plo@am__quote@
>   @AMDEP_TRUE@@am__include@ @am__quote@src/sparc/$(DEPDIR)/v9.Plo@am__quote@
> +@AMDEP_TRUE@@am__include@ @am__quote@src/tile/$(DEPDIR)/ffi.Plo@am__quote@
> +@AMDEP_TRUE@@am__include@ @am__quote@src/tile/$(DEPDIR)/tile.Plo@am__quote@
>   @AMDEP_TRUE@@am__include@ @am__quote@src/x86/$(DEPDIR)/darwin.Plo@am__quote@
>   @AMDEP_TRUE@@am__include@ @am__quote@src/x86/$(DEPDIR)/darwin64.Plo@am__quote@
>   @AMDEP_TRUE@@am__include@ @am__quote@src/x86/$(DEPDIR)/ffi.Plo@am__quote@
> @@ -1100,6 +1121,7 @@
>   	-rm -rf src/sh/.libs src/sh/_libs
>   	-rm -rf src/sh64/.libs src/sh64/_libs
>   	-rm -rf src/sparc/.libs src/sparc/_libs
> +	-rm -rf src/tile/.libs src/tile/_libs
>   	-rm -rf src/x86/.libs src/x86/_libs
>   
>   distclean-libtool:
> @@ -1669,6 +1691,8 @@
>   	-rm -f src/sh64/$(am__dirstamp)
>   	-rm -f src/sparc/$(DEPDIR)/$(am__dirstamp)
>   	-rm -f src/sparc/$(am__dirstamp)
> +	-rm -f src/tile/$(DEPDIR)/$(am__dirstamp)
> +	-rm -f src/tile/$(am__dirstamp)
>   	-rm -f src/x86/$(DEPDIR)/$(am__dirstamp)
>   	-rm -f src/x86/$(am__dirstamp)
>   
> @@ -1682,7 +1706,7 @@
>   
>   distclean: distclean-recursive
>   	-rm -f $(am__CONFIG_DISTCLEAN_FILES)
> -	-rm -rf src/$(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/moxie/$(DEPDIR) src/pa/$(DEPDIR) src/powerpc/$(DEPDIR) src/s390/$(DEPDIR) src/sh/$(DEPDIR) src/sh64/$(DEPDIR) src/sparc/$(DEPDIR) src/x86/$(DEPDIR)
> +	-rm -rf src/$(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/moxie/$(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 -f Makefile
>   distclean-am: clean-am distclean-compile distclean-generic \
>   	distclean-hdr distclean-libtool distclean-tags
> @@ -1802,7 +1826,7 @@
>   maintainer-clean: maintainer-clean-recursive
>   	-rm -f $(am__CONFIG_DISTCLEAN_FILES)
>   	-rm -rf $(top_srcdir)/autom4te.cache
> -	-rm -rf src/$(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/moxie/$(DEPDIR) src/pa/$(DEPDIR) src/powerpc/$(DEPDIR) src/s390/$(DEPDIR) src/sh/$(DEPDIR) src/sh64/$(DEPDIR) src/sparc/$(DEPDIR) src/x86/$(DEPDIR)
> +	-rm -rf src/$(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/moxie/$(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 -f Makefile
>   maintainer-clean-am: distclean-am maintainer-clean-aminfo \
>   	maintainer-clean-generic maintainer-clean-vti
> diff -ruP orig/libffi/configure libffi/configure
> --- orig/libffi/configure	2012-07-10 17:17:21.903030000 -0400
> +++ libffi/configure	2012-07-10 17:31:30.250259000 -0400
> @@ -627,6 +627,8 @@
>   sys_symbol_underscore
>   HAVE_LONG_DOUBLE
>   ALLOCA
> +TILE_FALSE
> +TILE_TRUE
>   PA64_HPUX_FALSE
>   PA64_HPUX_TRUE
>   PA_HPUX_FALSE
> @@ -13266,6 +13268,10 @@
>   	TARGET=SPARC; TARGETDIR=sparc
>   	;;
>   
> +  tile*-*)
> +	TARGET=TILE; TARGETDIR=tile
> +	;;
> +
>     x86_64-*-darwin*)
>   	TARGET=X86_DARWIN; TARGETDIR=x86
>   	;;
> @@ -13519,6 +13525,14 @@
>     PA64_HPUX_FALSE=
>   fi
>   
> + if test x$TARGET = xTILE; then
> +  TILE_TRUE=
> +  TILE_FALSE='#'
> +else
> +  TILE_TRUE='#'
> +  TILE_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; }
> @@ -14830,6 +14844,10 @@
>     as_fn_error $? "conditional \"PA64_HPUX\" was never defined.
>   Usually this means the macro was only invoked conditionally." "$LINENO" 5
>   fi
> +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 "${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 -ruP orig/libffi/configure.ac libffi/configure.ac
> --- orig/libffi/configure.ac	2012-07-10 17:17:21.904027000 -0400
> +++ libffi/configure.ac	2012-07-10 17:25:26.915450000 -0400
> @@ -187,6 +187,10 @@
>   	TARGET=SPARC; TARGETDIR=sparc
>   	;;
>   
> +  tile*-*)
> +	TARGET=TILE; TARGETDIR=tile
> +	;;
> +
>     x86_64-*-darwin*)
>   	TARGET=X86_DARWIN; TARGETDIR=x86
>   	;;
> @@ -244,6 +248,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)
>   
>   AC_HEADER_STDC
>   AC_CHECK_FUNCS(memcpy)
> diff -ruP orig/libffi/src/prep_cif.c libffi/src/prep_cif.c
> --- orig/libffi/src/prep_cif.c	2012-07-10 17:17:22.421038000 -0400
> +++ libffi/src/prep_cif.c	2012-07-10 17:26:05.208271000 -0400
> @@ -140,6 +140,9 @@
>   #ifdef SPARC
>         && (cif->abi != FFI_V9 || cif->rtype->size > 32)
>   #endif
> +#ifdef TILE
> +      && (cif->rtype->size > 10 * FFI_SIZEOF_ARG)
> +#endif
>        )
>       bytes = STACK_ARG_SIZE(sizeof(void*));
>   #endif
> @@ -169,6 +172,16 @@
>   	  if (((*ptr)->alignment - 1) & bytes)
>   	    bytes = ALIGN(bytes, (*ptr)->alignment);
>   
> +#ifdef TILE
> +	  if (bytes < 10 * FFI_SIZEOF_ARG &&
> +	      bytes + STACK_ARG_SIZE((*ptr)->size) > 10 * FFI_SIZEOF_ARG)
> +	    {
> +	      /* An argument is never split between the 10 parameter
> +		 registers and the stack. */
> +	      bytes = 10 * FFI_SIZEOF_ARG;
> +	    }
> +#endif
> +
>   	  bytes += STACK_ARG_SIZE((*ptr)->size);
>   	}
>   #endif
> diff -ruP orig/libffi/src/tile/ffi.c libffi/src/tile/ffi.c
> --- orig/libffi/src/tile/ffi.c	1969-12-31 19:00:00.000000000 -0500
> +++ libffi/src/tile/ffi.c	2012-07-10 17:26:05.232280000 -0400
> @@ -0,0 +1,355 @@
> +/* -----------------------------------------------------------------------
> +   ffi.c - Copyright (c) 2012 Tilera Corp.
> +
> +   TILE 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>
> +#include <stdlib.h>
> +#include <stdint.h>
> +#include <unistd.h>
> +#include <arch/abi.h>
> +#include <arch/icache.h>
> +#include <arch/opcode.h>
> +
> +
> +/* The first 10 registers are used to pass arguments and return values. */
> +#define NUM_ARG_REGS 10
> +
> +/* Performs a raw function call with the given NUM_ARG_REGS register arguments
> +   and the specified additional stack arguments (if any). */
> +extern void ffi_call_tile(ffi_sarg reg_args[NUM_ARG_REGS],
> +                          const ffi_sarg *stack_args,
> +                          size_t stack_args_bytes,
> +                          void (*fnaddr)(void))
> +  FFI_HIDDEN;
> +
> +/* This handles the raw call from the closure stub, cleaning up the
> +   parameters and delegating to ffi_closure_tile_inner. */
> +extern void ffi_closure_tile(void) FFI_HIDDEN;
> +
> +
> +ffi_status
> +ffi_prep_cif_machdep(ffi_cif *cif)
> +{
> +  /* We always allocate room for all registers. Even if we don't
> +     use them as parameters, they get returned in the same array
> +     as struct return values so we need to make room. */
> +  if (cif->bytes < NUM_ARG_REGS * FFI_SIZEOF_ARG)
> +    cif->bytes = NUM_ARG_REGS * FFI_SIZEOF_ARG;
> +
> +  if (cif->rtype->size > NUM_ARG_REGS * FFI_SIZEOF_ARG)
> +    cif->flags = FFI_TYPE_STRUCT;
> +  else
> +    cif->flags = FFI_TYPE_INT;
> +
> +  /* Nothing to do. */
> +  return FFI_OK;
> +}
> +
> +
> +static long
> +assign_to_ffi_arg(ffi_sarg *out, void *in, const ffi_type *type,
> +                  int write_to_reg)
> +{
> +  switch (type->type)
> +    {
> +    case FFI_TYPE_SINT8:
> +      *out = *(SINT8 *)in;
> +      return 1;
> +		
> +    case FFI_TYPE_UINT8:
> +      *out = *(UINT8 *)in;
> +      return 1;
> +		
> +    case FFI_TYPE_SINT16:
> +      *out = *(SINT16 *)in;
> +      return 1;
> +		
> +    case FFI_TYPE_UINT16:
> +      *out = *(UINT16 *)in;
> +      return 1;
> +		
> +    case FFI_TYPE_SINT32:
> +    case FFI_TYPE_UINT32:
> +#ifndef __LP64__
> +    case FFI_TYPE_POINTER:
> +#endif
> +      /* Note that even unsigned 32-bit quantities are sign extended
> +         on tilegx when stored in a register.  */
> +      *out = *(SINT32 *)in;
> +      return 1;
> +		
> +    case FFI_TYPE_FLOAT:
> +#ifdef __tilegx__
> +      if (write_to_reg)
> +        {
> +          /* Properly sign extend the value.  */
> +          union { float f; SINT32 s32; } val;
> +          val.f = *(float *)in;
> +          *out = val.s32;
> +        }
> +      else
> +#endif
> +        {
> +          *(float *)out = *(float *)in;
> +        }
> +      return 1;
> +
> +    case FFI_TYPE_SINT64:
> +    case FFI_TYPE_UINT64:
> +    case FFI_TYPE_DOUBLE:
> +#ifdef __LP64__
> +    case FFI_TYPE_POINTER:
> +#endif
> +      *(UINT64 *)out = *(UINT64 *)in;
> +      return sizeof(UINT64) / FFI_SIZEOF_ARG;
> +
> +    case FFI_TYPE_STRUCT:
> +      memcpy(out, in, type->size);
> +      return (type->size + FFI_SIZEOF_ARG - 1) / FFI_SIZEOF_ARG;
> +
> +    case FFI_TYPE_VOID:
> +      /* Must be a return type. Nothing to do. */
> +      return 0;
> +
> +    default:
> +      FFI_ASSERT(0);
> +      return -1;
> +    }
> +}
> +
> +
> +void
> +ffi_call(ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue)
> +{
> +  ffi_sarg * const arg_mem = alloca(cif->bytes);
> +  ffi_sarg * const reg_args = arg_mem;
> +  ffi_sarg * const stack_args = &reg_args[NUM_ARG_REGS];
> +  ffi_sarg *argp = arg_mem;
> +  ffi_type ** const arg_types = cif->arg_types;
> +  const long num_args = cif->nargs;
> +  long i;
> +
> +  if (cif->flags == FFI_TYPE_STRUCT)
> +    {
> +      /* Pass a hidden pointer to the return value. We make sure there
> +         is scratch space for the callee to store the return value even if
> +         our caller doesn't care about it. */
> +      *argp++ = (intptr_t)(rvalue ? rvalue : alloca(cif->rtype->size));
> +
> +      /* No more work needed to return anything. */
> +      rvalue = NULL;
> +    }
> +
> +  for (i = 0; i < num_args; i++)
> +    {
> +      ffi_type *type = arg_types[i];
> +      void * const arg_in = avalue[i];
> +      ptrdiff_t arg_word = argp - arg_mem;
> +
> +#ifndef __tilegx__
> +      /* Doubleword-aligned values are always in an even-number register
> +         pair, or doubleword-aligned stack slot if out of registers. */
> +      long align = arg_word & (type->alignment > FFI_SIZEOF_ARG);
> +      argp += align;
> +      arg_word += align;
> +#endif
> +
> +      if (type->type == FFI_TYPE_STRUCT)
> +        {
> +          const size_t arg_size_in_words =
> +            (type->size + FFI_SIZEOF_ARG - 1) / FFI_SIZEOF_ARG;
> +
> +          if (arg_word < NUM_ARG_REGS &&
> +              arg_word + arg_size_in_words > NUM_ARG_REGS)
> +            {
> +              /* Args are not allowed to span registers and the stack. */
> +              argp = stack_args;
> +            }
> +
> +          memcpy(argp, arg_in, type->size);
> +          argp += arg_size_in_words;
> +        }
> +      else
> +        {
> +          argp += assign_to_ffi_arg(argp, arg_in, arg_types[i], 1);
> +        }
> +    }
> +
> +  /* Actually do the call. */
> +  ffi_call_tile(reg_args, stack_args,
> +                cif->bytes - (NUM_ARG_REGS * FFI_SIZEOF_ARG), fn);
> +
> +  if (rvalue != NULL)
> +    assign_to_ffi_arg(rvalue, reg_args, cif->rtype, 0);
> +}
> +
> +
> +/* Template code for closure. */
> +extern const UINT64 ffi_template_tramp_tile[] FFI_HIDDEN;
> +
> +
> +ffi_status
> +ffi_prep_closure_loc (ffi_closure *closure,
> +		      ffi_cif *cif,
> +		      void (*fun)(ffi_cif*, void*, void**, void*),
> +		      void *user_data,
> +		      void *codeloc)
> +{
> +#ifdef __tilegx__
> +  /* TILE-Gx */
> +  SINT64 c;
> +  SINT64 h;
> +  int s;
> +  UINT64 *out;
> +
> +  if (cif->abi != FFI_UNIX)
> +    return FFI_BAD_ABI;
> +
> +  out = (UINT64 *)closure->tramp;
> +
> +  c = (intptr_t)closure;
> +  h = (intptr_t)ffi_closure_tile;
> +  s = 0;
> +
> +  /* Find the smallest shift count that doesn't lose information
> +     (i.e. no need to explicitly insert high bits of the address that
> +     are just the sign extension of the low bits). */
> +  while ((c >> s) != (SINT16)(c >> s) || (h >> s) != (SINT16)(h >> s))
> +    s += 16;
> +
> +#define OPS(a, b, shift) \
> +  (create_Imm16_X0((a) >> (shift)) | create_Imm16_X1((b) >> (shift)))
> +
> +  /* Emit the moveli. */
> +  *out++ = ffi_template_tramp_tile[0] | OPS(c, h, s);
> +  for (s -= 16; s >= 0; s -= 16)
> +    *out++ = ffi_template_tramp_tile[1] | OPS(c, h, s);
> +
> +#undef OPS
> +
> +  *out++ = ffi_template_tramp_tile[2];
> +
> +#else
> +  /* TILEPro */
> +  UINT64 *out;
> +  intptr_t delta;
> +
> +  if (cif->abi != FFI_UNIX)
> +    return FFI_BAD_ABI;
> +
> +  out = (UINT64 *)closure->tramp;
> +  delta = (intptr_t)ffi_closure_tile - (intptr_t)codeloc;
> +
> +  *out++ = ffi_template_tramp_tile[0] | create_JOffLong_X1(delta >> 3);
> +#endif
> +
> +  closure->cif = cif;
> +  closure->fun = fun;
> +  closure->user_data = user_data;
> +
> +  invalidate_icache(closure->tramp, (char *)out - closure->tramp,
> +                    getpagesize());
> +
> +  return FFI_OK;
> +}
> +
> +
> +/* This is called by the assembly wrapper for closures. This does
> +   all of the work. On entry reg_args[0] holds the values the registers
> +   had when the closure was invoked. On return reg_args[1] holds the register
> +   values to be returned to the caller (many of which may be garbage). */
> +void FFI_HIDDEN
> +ffi_closure_tile_inner(ffi_closure *closure,
> +                       ffi_sarg reg_args[2][NUM_ARG_REGS],
> +                       ffi_sarg *stack_args)
> +{
> +  ffi_cif * const cif = closure->cif;
> +  void ** const avalue = alloca(cif->nargs * sizeof(void *));
> +  void *rvalue;
> +  ffi_type ** const arg_types = cif->arg_types;
> +  ffi_sarg * const reg_args_in = reg_args[0];
> +  ffi_sarg * const reg_args_out = reg_args[1];
> +  ffi_sarg * argp;
> +  long i, arg_word, nargs = cif->nargs;
> +  /* Use a union to guarantee proper alignment for double. */
> +  union { ffi_sarg arg[NUM_ARG_REGS]; double d; UINT64 u64; } closure_ret;
> +
> +  /* Start out reading register arguments. */
> +  argp = reg_args_in;
> +
> +  /* Copy the caller's structure return address to that the closure
> +     returns the data directly to the caller.  */
> +  if (cif->flags == FFI_TYPE_STRUCT)
> +    {
> +      /* Return by reference via hidden pointer. */
> +      rvalue = (void *)(intptr_t)*argp++;
> +      arg_word = 1;
> +    }
> +  else
> +    {
> +      /* Return the value in registers. */
> +      rvalue = &closure_ret;
> +      arg_word = 0;
> +    }
> +
> +  /* Grab the addresses of the arguments. */
> +  for (i = 0; i < nargs; i++)
> +    {
> +      ffi_type * const type = arg_types[i];
> +      const size_t arg_size_in_words =
> +        (type->size + FFI_SIZEOF_ARG - 1) / FFI_SIZEOF_ARG;
> +
> +#ifndef __tilegx__
> +      /* Doubleword-aligned values are always in an even-number register
> +         pair, or doubleword-aligned stack slot if out of registers. */
> +      long align = arg_word & (type->alignment > FFI_SIZEOF_ARG);
> +      argp += align;
> +      arg_word += align;
> +#endif
> +
> +      if (arg_word == NUM_ARG_REGS ||
> +          (arg_word < NUM_ARG_REGS &&
> +           arg_word + arg_size_in_words > NUM_ARG_REGS))
> +        {
> +          /* Switch to reading arguments from the stack. */
> +          argp = stack_args;
> +          arg_word = NUM_ARG_REGS;
> +        }
> +
> +      avalue[i] = argp;
> +      argp += arg_size_in_words;
> +      arg_word += arg_size_in_words;
> +    }
> +
> +  /* Invoke the closure.  */
> +  closure->fun(cif, rvalue, avalue, closure->user_data);
> +
> +  if (cif->flags != FFI_TYPE_STRUCT)
> +    {
> +      /* Canonicalize for register representation. */
> +      assign_to_ffi_arg(reg_args_out, &closure_ret, cif->rtype, 1);
> +    }
> +}
> diff -ruP orig/libffi/src/tile/ffitarget.h libffi/src/tile/ffitarget.h
> --- orig/libffi/src/tile/ffitarget.h	1969-12-31 19:00:00.000000000 -0500
> +++ libffi/src/tile/ffitarget.h	2012-07-10 17:26:05.241297000 -0400
> @@ -0,0 +1,65 @@
> +/* -----------------------------------------------------------------*-C-*-
> +   ffitarget.h - Copyright (c) 2012 Tilera Corp.
> +   Target configuration macros for TILE.
> +
> +   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
> +
> +#include <arch/abi.h>
> +
> +typedef uint_reg_t ffi_arg;
> +typedef int_reg_t  ffi_sarg;
> +
> +typedef enum ffi_abi {
> +  FFI_FIRST_ABI = 0,
> +  FFI_UNIX,
> +  FFI_LAST_ABI,
> +  FFI_DEFAULT_ABI = FFI_UNIX
> +} ffi_abi;
> +#endif
> +
> +/* ---- Definitions for closures ----------------------------------------- */
> +#define FFI_CLOSURES 1
> +
> +#ifdef __tilegx__
> +/* We always pass 8-byte values, even in -m32 mode. */
> +# define FFI_SIZEOF_ARG 8
> +# ifdef __LP64__
> +#  define FFI_TRAMPOLINE_SIZE (8 * 5)  /* 5 bundles */
> +# else
> +#  define FFI_TRAMPOLINE_SIZE (8 * 3)  /* 3 bundles */
> +# endif
> +#else
> +# define FFI_SIZEOF_ARG 4
> +# define FFI_TRAMPOLINE_SIZE 8 /* 1 bundle */
> +#endif
> +#define FFI_NATIVE_RAW_API 0
> +
> +#endif
> diff -ruP orig/libffi/src/tile/tile.S libffi/src/tile/tile.S
> --- orig/libffi/src/tile/tile.S	1969-12-31 19:00:00.000000000 -0500
> +++ libffi/src/tile/tile.S	2012-07-10 17:26:05.246288000 -0400
> @@ -0,0 +1,360 @@
> +/* -----------------------------------------------------------------------
> +   tile.S - Copyright (c) 2011 Tilera Corp.
> +
> +   Tilera TILEPro and TILE-Gx 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>
> +
> +/* Number of bytes in a register. */
> +#define REG_SIZE FFI_SIZEOF_ARG
> +
> +/* Number of bytes in stack linkage area for backtracing.
> +
> +   A note about the ABI: on entry to a procedure, sp points to a stack
> +   slot where it must spill the return address if it's not a leaf.
> +   REG_SIZE bytes beyond that is a slot owned by the caller which
> +   contains the sp value that the caller had when it was originally
> +   entered (i.e. the caller's frame pointer). */
> +#define LINKAGE_SIZE (2 * REG_SIZE)
> +
> +/* The first 10 registers are used to pass arguments and return values. */
> +#define NUM_ARG_REGS 10
> +
> +#ifdef __tilegx__
> +#define SW st
> +#define LW ld
> +#define BGZT bgtzt
> +#else
> +#define SW sw
> +#define LW lw
> +#define BGZT bgzt
> +#endif
> +
> +
> +/* void ffi_call_tile (int_reg_t reg_args[NUM_ARG_REGS],
> +                       const int_reg_t *stack_args,
> +                       unsigned long stack_args_bytes,
> +                       void (*fnaddr)(void));
> +
> +        On entry, REG_ARGS contain the outgoing register values,
> +        and STACK_ARGS containts STACK_ARG_BYTES of additional values
> +        to be passed on the stack. If STACK_ARG_BYTES is zero, then
> +        STACK_ARGS is ignored.
> +
> +        When the invoked function returns, the values of r0-r9 are
> +        blindly stored back into REG_ARGS for the caller to examine. */
> +
> +        .section .text.ffi_call_tile, "ax", @progbits
> +        .align  8
> +        .globl  ffi_call_tile
> +        FFI_HIDDEN(ffi_call_tile)
> +ffi_call_tile:
> +
> +/* Incoming arguments. */
> +#define REG_ARGS                r0
> +#define INCOMING_STACK_ARGS     r1
> +#define STACK_ARG_BYTES         r2
> +#define ORIG_FNADDR             r3
> +
> +/* Temporary values. */
> +#define FRAME_SIZE              r10
> +#define TMP                     r11
> +#define TMP2                    r12
> +#define OUTGOING_STACK_ARGS     r13
> +#define REG_ADDR_PTR            r14
> +#define RETURN_REG_ADDR         r15
> +#define FNADDR                  r16
> +
> +        .cfi_startproc
> +        {
> +         /* Save return address. */
> +         SW     sp, lr
> +         .cfi_offset lr, 0
> +         /* Prepare to spill incoming r52. */
> +         addi   TMP, sp, -REG_SIZE
> +         /* Increase frame size to have room to spill r52 and REG_ARGS.
> +            The +7 is to round up mod 8. */
> +         addi   FRAME_SIZE, STACK_ARG_BYTES, \
> +                REG_SIZE + REG_SIZE + LINKAGE_SIZE + 7
> +        }
> +        {
> +         /* Round stack frame size to a multiple of 8 to satisfy ABI. */
> +         andi   FRAME_SIZE, FRAME_SIZE, -8
> +         /* Compute where to spill REG_ARGS value. */
> +         addi   TMP2, sp, -(REG_SIZE * 2)
> +        }
> +        {
> +         /* Spill incoming r52. */
> +         SW     TMP, r52
> +         .cfi_offset r52, -REG_SIZE
> +         /* Set up our frame pointer. */
> +         move   r52, sp
> +         .cfi_def_cfa_register r52
> +         /* Push stack frame. */
> +         sub    sp, sp, FRAME_SIZE
> +        }
> +        {
> +         /* Prepare to set up stack linkage. */
> +         addi   TMP, sp, REG_SIZE
> +         /* Prepare to memcpy stack args. */
> +         addi   OUTGOING_STACK_ARGS, sp, LINKAGE_SIZE
> +         /* Save REG_ARGS which we will need after we call the subroutine. */
> +         SW     TMP2, REG_ARGS
> +        }
> +        {
> +         /* Set up linkage info to hold incoming stack pointer. */
> +         SW     TMP, r52
> +        }
> +        {
> +         /* Skip stack args memcpy if we don't have any stack args (common). */
> +         blezt  STACK_ARG_BYTES, .Ldone_stack_args_memcpy
> +        }
> +
> +.Lmemcpy_stack_args:
> +        {
> +         /* Load incoming argument from stack_args. */
> +         LW     TMP, INCOMING_STACK_ARGS
> +         addi   INCOMING_STACK_ARGS, INCOMING_STACK_ARGS, REG_SIZE
> +        }
> +        {
> +         /* Store stack argument into outgoing stack argument area. */
> +         SW     OUTGOING_STACK_ARGS, TMP
> +         addi   OUTGOING_STACK_ARGS, OUTGOING_STACK_ARGS, REG_SIZE
> +         addi   STACK_ARG_BYTES, STACK_ARG_BYTES, -REG_SIZE
> +        }
> +        {
> +         BGZT   STACK_ARG_BYTES, .Lmemcpy_stack_args
> +        }
> +.Ldone_stack_args_memcpy:
> +
> +        {
> +         /* Copy aside ORIG_FNADDR so we can overwrite its register. */
> +         move   FNADDR, ORIG_FNADDR
> +         /* Prepare to load argument registers. */
> +         addi   REG_ADDR_PTR, r0, REG_SIZE
> +         /* Load outgoing r0. */
> +         LW     r0, r0
> +        }
> +
> +        /* Load up argument registers from the REG_ARGS array. */
> +#define LOAD_REG(REG, PTR) \
> +        { \
> +         LW     REG, PTR ; \
> +         addi   PTR, PTR, REG_SIZE \
> +        }
> +
> +        LOAD_REG(r1, REG_ADDR_PTR)
> +        LOAD_REG(r2, REG_ADDR_PTR)
> +        LOAD_REG(r3, REG_ADDR_PTR)
> +        LOAD_REG(r4, REG_ADDR_PTR)
> +        LOAD_REG(r5, REG_ADDR_PTR)
> +        LOAD_REG(r6, REG_ADDR_PTR)
> +        LOAD_REG(r7, REG_ADDR_PTR)
> +        LOAD_REG(r8, REG_ADDR_PTR)
> +        LOAD_REG(r9, REG_ADDR_PTR)
> +
> +        {
> +         /* Call the subroutine. */
> +         jalr   FNADDR
> +        }
> +
> +        {
> +         /* Restore original lr. */
> +         LW     lr, r52
> +         /* Prepare to recover ARGS, which we spilled earlier. */
> +         addi   TMP, r52, -(2 * REG_SIZE)
> +        }
> +        {
> +         /* Restore ARGS, so we can fill it in with the return regs r0-r9. */
> +         LW     RETURN_REG_ADDR, TMP
> +         /* Prepare to restore original r52. */
> +         addi   TMP, r52, -REG_SIZE
> +        }
> +
> +        {
> +         /* Pop stack frame. */
> +         move   sp, r52
> +         /* Restore original r52. */
> +         LW     r52, TMP
> +        }
> +
> +#define STORE_REG(REG, PTR) \
> +        { \
> +         SW     PTR, REG ; \
> +         addi   PTR, PTR, REG_SIZE \
> +        }
> +
> +        /* Return all register values by reference. */
> +        STORE_REG(r0, RETURN_REG_ADDR)
> +        STORE_REG(r1, RETURN_REG_ADDR)
> +        STORE_REG(r2, RETURN_REG_ADDR)
> +        STORE_REG(r3, RETURN_REG_ADDR)
> +        STORE_REG(r4, RETURN_REG_ADDR)
> +        STORE_REG(r5, RETURN_REG_ADDR)
> +        STORE_REG(r6, RETURN_REG_ADDR)
> +        STORE_REG(r7, RETURN_REG_ADDR)
> +        STORE_REG(r8, RETURN_REG_ADDR)
> +        STORE_REG(r9, RETURN_REG_ADDR)
> +
> +        {
> +         jrp    lr
> +        }
> +
> +        .cfi_endproc
> +        .size ffi_call_tile, .-ffi_call_tile
> +
> +/* ffi_closure_tile(...)
> +
> +   On entry, lr points to the closure plus 8 bytes, and r10
> +   contains the actual return address.
> +
> +   This function simply dumps all register parameters into a stack array
> +   and passes the closure, the registers array, and the stack arguments
> +   to C code that does all of the actual closure processing. */
> +
> +        .section .text.ffi_closure_tile, "ax", @progbits
> +        .align  8
> +        .globl  ffi_closure_tile
> +        FFI_HIDDEN(ffi_closure_tile)
> +
> +        .cfi_startproc
> +/* Room to spill all NUM_ARG_REGS incoming registers, plus frame linkage. */
> +#define CLOSURE_FRAME_SIZE (((NUM_ARG_REGS * REG_SIZE * 2 + LINKAGE_SIZE) + 7) & -8)
> +ffi_closure_tile:
> +        {
> +#ifdef __tilegx__
> +         st     sp, lr
> +         .cfi_offset lr, 0
> +#else
> +         /* Save return address (in r10 due to closure stub wrapper). */
> +         SW     sp, r10
> +         .cfi_return_column r10
> +         .cfi_offset r10, 0
> +#endif
> +         /* Compute address for stack frame linkage. */
> +         addli   r10, sp, -(CLOSURE_FRAME_SIZE - REG_SIZE)
> +        }
> +        {
> +         /* Save incoming stack pointer in linkage area. */
> +         SW     r10, sp
> +         .cfi_offset sp, -(CLOSURE_FRAME_SIZE - REG_SIZE)
> +         /* Push a new stack frame. */
> +         addli   sp, sp, -CLOSURE_FRAME_SIZE
> +         .cfi_adjust_cfa_offset CLOSURE_FRAME_SIZE
> +        }
> +
> +        {
> +         /* Create pointer to where to start spilling registers. */
> +         addi   r10, sp, LINKAGE_SIZE
> +        }
> +	
> +        /* Spill all the incoming registers. */
> +        STORE_REG(r0, r10)
> +        STORE_REG(r1, r10)
> +        STORE_REG(r2, r10)
> +        STORE_REG(r3, r10)
> +        STORE_REG(r4, r10)
> +        STORE_REG(r5, r10)
> +        STORE_REG(r6, r10)
> +        STORE_REG(r7, r10)
> +        STORE_REG(r8, r10)
> +        {
> +         /* Save r9. */
> +         SW     r10, r9
> +#ifdef __tilegx__
> +         /* Pointer to closure is passed in r11. */
> +         move  r0, r11
> +#else
> +         /* Compute pointer to the closure object. Because the closure
> +            starts with a "jal ffi_closure_tile", we can just take the
> +            value of lr (a phony return address pointing into the closure)
> +            and subtract 8. */
> +         addi   r0, lr, -8
> +#endif
> +         /* Compute a pointer to the register arguments we just spilled. */
> +         addi   r1, sp, LINKAGE_SIZE
> +        }
> +        {
> +         /* Compute a pointer to the extra stack arguments (if any). */
> +         addli   r2, sp, CLOSURE_FRAME_SIZE + LINKAGE_SIZE
> +         /* Call C code to deal with all of the grotty details. */
> +         jal    ffi_closure_tile_inner
> +        }
> +        {
> +         addli   r10, sp, CLOSURE_FRAME_SIZE
> +        }
> +        {
> +         /* Restore the return address. */
> +         LW     lr, r10
> +         /* Compute pointer to registers array. */
> +         addli   r10, sp, LINKAGE_SIZE + (NUM_ARG_REGS * REG_SIZE)
> +        }
> +        /* Return all the register values, which C code may have set. */
> +        LOAD_REG(r0, r10)
> +        LOAD_REG(r1, r10)
> +        LOAD_REG(r2, r10)
> +        LOAD_REG(r3, r10)
> +        LOAD_REG(r4, r10)
> +        LOAD_REG(r5, r10)
> +        LOAD_REG(r6, r10)
> +        LOAD_REG(r7, r10)
> +        LOAD_REG(r8, r10)
> +        LOAD_REG(r9, r10)
> +        {
> +         /* Pop the frame. */
> +         addli   sp, sp, CLOSURE_FRAME_SIZE
> +         jrp    lr
> +        }
> +
> +        .cfi_endproc
> +        .size   ffi_closure_tile, . - ffi_closure_tile
> +
> +
> +/* What follows are code template instructions that get copied to the
> +   closure trampoline by ffi_prep_closure_loc.  The zeroed operands
> +   get replaced by their proper values at runtime. */
> +
> +        .section .text.ffi_template_tramp_tile, "ax", @progbits
> +        .align  8
> +        .globl  ffi_template_tramp_tile
> +        FFI_HIDDEN(ffi_template_tramp_tile)
> +ffi_template_tramp_tile:
> +#ifdef __tilegx__
> +        {
> +          moveli r11, 0 /* backpatched to address of containing closure. */
> +          moveli r10, 0 /* backpatched to ffi_closure_tile. */
> +        }
> +        /* Note: the following bundle gets generated multiple times
> +           depending on the pointer value (esp. useful for -m32 mode). */
> +        { shl16insli r11, r11, 0 ; shl16insli r10, r10, 0 }
> +        { info 2+8 /* for backtracer: -> pc in lr, frame size 0 */ ; jr r10 }
> +#else
> +        /* 'jal .' yields a PC-relative offset of zero so we can OR in the
> +           right offset at runtime. */
> +        { move r10, lr ; jal . /* ffi_closure_tile */ }
> +#endif
> +
> +        .size   ffi_template_tramp_tile, . - ffi_template_tramp_tile


  reply	other threads:[~2012-08-08 18:46 UTC|newest]

Thread overview: 4+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2012-07-10 21:49 Walter Lee
2012-08-08 18:46 ` Walter Lee [this message]
2012-08-10 14:51   ` Anthony Green
2012-08-10 15:07     ` Walter Lee

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=5022B3D6.3040401@tilera.com \
    --to=walt@tilera.com \
    --cc=libffi-discuss@sourceware.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).