From 124f60ab29f46aefdf892a4fcf981e4e292eb08c Mon Sep 17 00:00:00 2001 From: Bradley Smith Date: Sat, 26 Dec 2009 04:21:07 +0000 Subject: [PATCH] avr32 libffi port From-SVN: r155469 --- libffi/ChangeLog | 7 + libffi/Makefile.am | 4 + libffi/Makefile.in | 73 +++--- libffi/configure | 22 +- libffi/configure.ac | 5 + libffi/src/avr32/ffi.c | 421 +++++++++++++++++++++++++++++++++++ libffi/src/avr32/ffitarget.h | 50 +++++ libffi/src/avr32/sysv.S | 208 +++++++++++++++++ 8 files changed, 763 insertions(+), 27 deletions(-) create mode 100644 libffi/src/avr32/ffi.c create mode 100644 libffi/src/avr32/ffitarget.h create mode 100644 libffi/src/avr32/sysv.S diff --git a/libffi/ChangeLog b/libffi/ChangeLog index 276d738caa4..01052cd4fe0 100644 --- a/libffi/ChangeLog +++ b/libffi/ChangeLog @@ -1,3 +1,10 @@ +2009-12-25 Bradley Smith + + * configure.ac, Makefile.am, src/avr32/ffi.c, + src/avr32/ffitarget.h, + src/avr32/sysv.S: Add AVR32 port. + * configure, Makefile.in: Rebuilt. + 2009-12-21 Andreas Tobler * configure.ac: Make i?86 build on FreeBSD and OpenBSD. diff --git a/libffi/Makefile.am b/libffi/Makefile.am index 74d45d43e82..98b34acfa4a 100644 --- a/libffi/Makefile.am +++ b/libffi/Makefile.am @@ -8,6 +8,7 @@ SUBDIRS = include testsuite man EXTRA_DIST = LICENSE ChangeLog.v1 ChangeLog.libgcj configure.host \ src/alpha/ffi.c src/alpha/osf.S src/alpha/ffitarget.h \ src/arm/ffi.c src/arm/sysv.S src/arm/ffitarget.h \ + src/avr32/ffi.c src/avr32/sysv.S src/avr32/ffitarget.h \ src/cris/ffi.c src/cris/sysv.S src/cris/ffitarget.h \ src/ia64/ffi.c src/ia64/ffitarget.h src/ia64/ia64_flags.h \ src/ia64/unix.S \ @@ -132,6 +133,9 @@ endif if ARM nodist_libffi_la_SOURCES += src/arm/sysv.S src/arm/ffi.c endif +if AVR32 +nodist_libffi_la_SOURCES += src/avr32/sysv.S src/avr32/ffi.c +endif if LIBFFI_CRIS nodist_libffi_la_SOURCES += src/cris/sysv.S src/cris/ffi.c endif diff --git a/libffi/Makefile.in b/libffi/Makefile.in index 414a1f0654e..e5ef5413b5f 100644 --- a/libffi/Makefile.in +++ b/libffi/Makefile.in @@ -51,14 +51,15 @@ target_triplet = @target@ @POWERPC_DARWIN_TRUE@am__append_14 = src/powerpc/ffi_darwin.c src/powerpc/darwin.S src/powerpc/darwin_closure.S @POWERPC_FREEBSD_TRUE@am__append_15 = src/powerpc/ffi.c src/powerpc/sysv.S src/powerpc/ppc_closure.S @ARM_TRUE@am__append_16 = src/arm/sysv.S src/arm/ffi.c -@LIBFFI_CRIS_TRUE@am__append_17 = src/cris/sysv.S src/cris/ffi.c -@FRV_TRUE@am__append_18 = src/frv/eabi.S src/frv/ffi.c -@S390_TRUE@am__append_19 = src/s390/sysv.S src/s390/ffi.c -@X86_64_TRUE@am__append_20 = src/x86/ffi64.c src/x86/unix64.S src/x86/ffi.c src/x86/sysv.S -@SH_TRUE@am__append_21 = src/sh/sysv.S src/sh/ffi.c -@SH64_TRUE@am__append_22 = src/sh64/sysv.S src/sh64/ffi.c -@PA_LINUX_TRUE@am__append_23 = src/pa/linux.S src/pa/ffi.c -@PA_HPUX_TRUE@am__append_24 = src/pa/hpux32.S src/pa/ffi.c +@AVR32_TRUE@am__append_17 = src/avr32/sysv.S src/avr32/ffi.c +@LIBFFI_CRIS_TRUE@am__append_18 = src/cris/sysv.S src/cris/ffi.c +@FRV_TRUE@am__append_19 = src/frv/eabi.S src/frv/ffi.c +@S390_TRUE@am__append_20 = src/s390/sysv.S src/s390/ffi.c +@X86_64_TRUE@am__append_21 = src/x86/ffi64.c src/x86/unix64.S src/x86/ffi.c src/x86/sysv.S +@SH_TRUE@am__append_22 = src/sh/sysv.S src/sh/ffi.c +@SH64_TRUE@am__append_23 = src/sh64/sysv.S src/sh64/ffi.c +@PA_LINUX_TRUE@am__append_24 = src/pa/linux.S src/pa/ffi.c +@PA_HPUX_TRUE@am__append_25 = src/pa/hpux32.S src/pa/ffi.c subdir = . DIST_COMMON = README $(am__configure_deps) $(srcdir)/../compile \ $(srcdir)/../config.guess $(srcdir)/../config.sub \ @@ -139,15 +140,16 @@ am_libffi_la_OBJECTS = src/debug.lo src/prep_cif.lo src/types.lo \ @POWERPC_FREEBSD_TRUE@ src/powerpc/sysv.lo \ @POWERPC_FREEBSD_TRUE@ src/powerpc/ppc_closure.lo @ARM_TRUE@am__objects_16 = src/arm/sysv.lo src/arm/ffi.lo -@LIBFFI_CRIS_TRUE@am__objects_17 = src/cris/sysv.lo src/cris/ffi.lo -@FRV_TRUE@am__objects_18 = src/frv/eabi.lo src/frv/ffi.lo -@S390_TRUE@am__objects_19 = src/s390/sysv.lo src/s390/ffi.lo -@X86_64_TRUE@am__objects_20 = src/x86/ffi64.lo src/x86/unix64.lo \ +@AVR32_TRUE@am__objects_17 = src/avr32/sysv.lo src/avr32/ffi.lo +@LIBFFI_CRIS_TRUE@am__objects_18 = src/cris/sysv.lo src/cris/ffi.lo +@FRV_TRUE@am__objects_19 = src/frv/eabi.lo src/frv/ffi.lo +@S390_TRUE@am__objects_20 = src/s390/sysv.lo src/s390/ffi.lo +@X86_64_TRUE@am__objects_21 = src/x86/ffi64.lo src/x86/unix64.lo \ @X86_64_TRUE@ src/x86/ffi.lo src/x86/sysv.lo -@SH_TRUE@am__objects_21 = src/sh/sysv.lo src/sh/ffi.lo -@SH64_TRUE@am__objects_22 = src/sh64/sysv.lo src/sh64/ffi.lo -@PA_LINUX_TRUE@am__objects_23 = src/pa/linux.lo src/pa/ffi.lo -@PA_HPUX_TRUE@am__objects_24 = src/pa/hpux32.lo src/pa/ffi.lo +@SH_TRUE@am__objects_22 = src/sh/sysv.lo src/sh/ffi.lo +@SH64_TRUE@am__objects_23 = src/sh64/sysv.lo src/sh64/ffi.lo +@PA_LINUX_TRUE@am__objects_24 = src/pa/linux.lo src/pa/ffi.lo +@PA_HPUX_TRUE@am__objects_25 = src/pa/hpux32.lo src/pa/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) \ @@ -156,25 +158,26 @@ nodist_libffi_la_OBJECTS = $(am__objects_1) $(am__objects_2) \ $(am__objects_15) $(am__objects_16) $(am__objects_17) \ $(am__objects_18) $(am__objects_19) $(am__objects_20) \ $(am__objects_21) $(am__objects_22) $(am__objects_23) \ - $(am__objects_24) + $(am__objects_24) $(am__objects_25) 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_25 = src/debug.lo src/prep_cif.lo src/types.lo \ +am__objects_26 = src/debug.lo 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_25) -am__objects_26 = $(am__objects_1) $(am__objects_2) $(am__objects_3) \ +am_libffi_convenience_la_OBJECTS = $(am__objects_26) +am__objects_27 = $(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) \ $(am__objects_13) $(am__objects_14) $(am__objects_15) \ $(am__objects_16) $(am__objects_17) $(am__objects_18) \ $(am__objects_19) $(am__objects_20) $(am__objects_21) \ - $(am__objects_22) $(am__objects_23) $(am__objects_24) -nodist_libffi_convenience_la_OBJECTS = $(am__objects_26) + $(am__objects_22) $(am__objects_23) $(am__objects_24) \ + $(am__objects_25) +nodist_libffi_convenience_la_OBJECTS = $(am__objects_27) libffi_convenience_la_OBJECTS = $(am_libffi_convenience_la_OBJECTS) \ $(nodist_libffi_convenience_la_OBJECTS) DEFAULT_INCLUDES = -I.@am__isrc@ @@ -388,6 +391,7 @@ SUBDIRS = include testsuite man EXTRA_DIST = LICENSE ChangeLog.v1 ChangeLog.libgcj configure.host \ src/alpha/ffi.c src/alpha/osf.S src/alpha/ffitarget.h \ src/arm/ffi.c src/arm/sysv.S src/arm/ffitarget.h \ + src/avr32/ffi.c src/avr32/sysv.S src/avr32/ffitarget.h \ src/cris/ffi.c src/cris/sysv.S src/cris/ffitarget.h \ src/ia64/ffi.c src/ia64/ffitarget.h src/ia64/ia64_flags.h \ src/ia64/unix.S \ @@ -463,7 +467,7 @@ nodist_libffi_la_SOURCES = $(am__append_1) $(am__append_2) \ $(am__append_15) $(am__append_16) $(am__append_17) \ $(am__append_18) $(am__append_19) $(am__append_20) \ $(am__append_21) $(am__append_22) $(am__append_23) \ - $(am__append_24) + $(am__append_24) $(am__append_25) libffi_convenience_la_SOURCES = $(libffi_la_SOURCES) nodist_libffi_convenience_la_SOURCES = $(nodist_libffi_la_SOURCES) AM_CFLAGS = -Wall -g -fexceptions @@ -701,6 +705,16 @@ src/arm/sysv.lo: src/arm/$(am__dirstamp) \ src/arm/$(DEPDIR)/$(am__dirstamp) src/arm/ffi.lo: src/arm/$(am__dirstamp) \ src/arm/$(DEPDIR)/$(am__dirstamp) +src/avr32/$(am__dirstamp): + @$(MKDIR_P) src/avr32 + @: > src/avr32/$(am__dirstamp) +src/avr32/$(DEPDIR)/$(am__dirstamp): + @$(MKDIR_P) src/avr32/$(DEPDIR) + @: > src/avr32/$(DEPDIR)/$(am__dirstamp) +src/avr32/sysv.lo: src/avr32/$(am__dirstamp) \ + src/avr32/$(DEPDIR)/$(am__dirstamp) +src/avr32/ffi.lo: src/avr32/$(am__dirstamp) \ + src/avr32/$(DEPDIR)/$(am__dirstamp) src/cris/$(am__dirstamp): @$(MKDIR_P) src/cris @: > src/cris/$(am__dirstamp) @@ -778,6 +792,10 @@ mostlyclean-compile: -rm -f src/arm/ffi.lo -rm -f src/arm/sysv.$(OBJEXT) -rm -f src/arm/sysv.lo + -rm -f src/avr32/ffi.$(OBJEXT) + -rm -f src/avr32/ffi.lo + -rm -f src/avr32/sysv.$(OBJEXT) + -rm -f src/avr32/sysv.lo -rm -f src/closures.$(OBJEXT) -rm -f src/closures.lo -rm -f src/cris/ffi.$(OBJEXT) @@ -892,6 +910,8 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@src/alpha/$(DEPDIR)/osf.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/arm/$(DEPDIR)/ffi.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/arm/$(DEPDIR)/sysv.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@src/avr32/$(DEPDIR)/ffi.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@src/avr32/$(DEPDIR)/sysv.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/cris/$(DEPDIR)/ffi.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/cris/$(DEPDIR)/sysv.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/frv/$(DEPDIR)/eabi.Plo@am__quote@ @@ -993,6 +1013,7 @@ clean-libtool: -rm -rf src/.libs src/_libs -rm -rf src/alpha/.libs src/alpha/_libs -rm -rf src/arm/.libs src/arm/_libs + -rm -rf src/avr32/.libs src/avr32/_libs -rm -rf src/cris/.libs src/cris/_libs -rm -rf src/frv/.libs src/frv/_libs -rm -rf src/ia64/.libs src/ia64/_libs @@ -1371,6 +1392,8 @@ distclean-generic: -rm -f src/alpha/$(am__dirstamp) -rm -f src/arm/$(DEPDIR)/$(am__dirstamp) -rm -f src/arm/$(am__dirstamp) + -rm -f src/avr32/$(DEPDIR)/$(am__dirstamp) + -rm -f src/avr32/$(am__dirstamp) -rm -f src/cris/$(DEPDIR)/$(am__dirstamp) -rm -f src/cris/$(am__dirstamp) -rm -f src/frv/$(DEPDIR)/$(am__dirstamp) @@ -1408,7 +1431,7 @@ clean-am: clean-generic clean-libtool clean-noinstLTLIBRARIES \ distclean: distclean-multi distclean-recursive -rm -f $(am__CONFIG_DISTCLEAN_FILES) - -rm -rf src/$(DEPDIR) src/alpha/$(DEPDIR) src/arm/$(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/x86/$(DEPDIR) + -rm -rf src/$(DEPDIR) src/alpha/$(DEPDIR) src/arm/$(DEPDIR) src/avr32/$(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/x86/$(DEPDIR) -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-hdr distclean-libtool distclean-tags @@ -1456,7 +1479,7 @@ installcheck-am: maintainer-clean: maintainer-clean-multi 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/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/x86/$(DEPDIR) + -rm -rf src/$(DEPDIR) src/alpha/$(DEPDIR) src/arm/$(DEPDIR) src/avr32/$(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/x86/$(DEPDIR) -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic diff --git a/libffi/configure b/libffi/configure index cdefd57f215..f8456c9f4b7 100755 --- a/libffi/configure +++ b/libffi/configure @@ -628,6 +628,8 @@ FRV_FALSE FRV_TRUE LIBFFI_CRIS_FALSE LIBFFI_CRIS_TRUE +AVR32_FALSE +AVR32_TRUE ARM_FALSE ARM_TRUE POWERPC_FREEBSD_FALSE @@ -10771,7 +10773,7 @@ else lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 lt_status=$lt_dlunknown cat > conftest.$ac_ext <<_LT_EOF -#line 10774 "configure" +#line 10776 "configure" #include "confdefs.h" #if HAVE_DLFCN_H @@ -10877,7 +10879,7 @@ else lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 lt_status=$lt_dlunknown cat > conftest.$ac_ext <<_LT_EOF -#line 10880 "configure" +#line 10882 "configure" #include "confdefs.h" #if HAVE_DLFCN_H @@ -11329,6 +11331,10 @@ case "$host" in TARGET=X86_64; TARGETDIR=x86 ;; + avr32*-*-*) + TARGET=AVR32; TARGETDIR=avr32 + ;; + cris-*-*) TARGET=LIBFFI_CRIS; TARGETDIR=cris ;; @@ -11563,6 +11569,14 @@ else ARM_FALSE= fi + if test x$TARGET = xAVR32; then + AVR32_TRUE= + AVR32_FALSE='#' +else + AVR32_TRUE='#' + AVR32_FALSE= +fi + if test x$TARGET = xLIBFFI_CRIS; then LIBFFI_CRIS_TRUE= LIBFFI_CRIS_FALSE='#' @@ -12723,6 +12737,10 @@ if test -z "${ARM_TRUE}" && test -z "${ARM_FALSE}"; then as_fn_error "conditional \"ARM\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi +if test -z "${AVR32_TRUE}" && test -z "${AVR32_FALSE}"; then + as_fn_error "conditional \"AVR32\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi if test -z "${LIBFFI_CRIS_TRUE}" && test -z "${LIBFFI_CRIS_FALSE}"; then as_fn_error "conditional \"LIBFFI_CRIS\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 diff --git a/libffi/configure.ac b/libffi/configure.ac index 3c1b1bcee43..a1a016cf082 100644 --- a/libffi/configure.ac +++ b/libffi/configure.ac @@ -55,6 +55,10 @@ case "$host" in TARGET=X86_64; TARGETDIR=x86 ;; + avr32*-*-*) + TARGET=AVR32; TARGETDIR=avr32 + ;; + cris-*-*) TARGET=LIBFFI_CRIS; TARGETDIR=cris ;; @@ -177,6 +181,7 @@ AM_CONDITIONAL(POWERPC_AIX, test x$TARGET = xPOWERPC_AIX) AM_CONDITIONAL(POWERPC_DARWIN, test x$TARGET = xPOWERPC_DARWIN) AM_CONDITIONAL(POWERPC_FREEBSD, test x$TARGET = xPOWERPC_FREEBSD) AM_CONDITIONAL(ARM, test x$TARGET = xARM) +AM_CONDITIONAL(AVR32, test x$TARGET = xAVR32) AM_CONDITIONAL(LIBFFI_CRIS, test x$TARGET = xLIBFFI_CRIS) AM_CONDITIONAL(FRV, test x$TARGET = xFRV) AM_CONDITIONAL(S390, test x$TARGET = xS390) diff --git a/libffi/src/avr32/ffi.c b/libffi/src/avr32/ffi.c new file mode 100644 index 00000000000..39fba2b03b6 --- /dev/null +++ b/libffi/src/avr32/ffi.c @@ -0,0 +1,421 @@ +/* ----------------------------------------------------------------------- + ffi.c - Copyright (c) 2009 Bradley Smith + + AVR32 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 +#include + +#include +#include +#include +#include + +/* #define DEBUG */ + +extern void ffi_call_SYSV(void (*)(char *, extended_cif *), extended_cif *, + unsigned int, unsigned int, unsigned int*, unsigned int, + void (*fn)(void)); +extern void ffi_closure_SYSV (ffi_closure *); + +unsigned int pass_struct_on_stack(ffi_type *type) +{ + if(type->type != FFI_TYPE_STRUCT) + return 0; + + if(type->alignment < type->size && + !(type->size == 4 || type->size == 8) && + !(type->size == 8 && type->alignment >= 4)) + return 1; + + if(type->size == 3 || type->size == 5 || type->size == 6 || + type->size == 7) + return 1; + + return 0; +} + +/* ffi_prep_args is called by the assembly routine once stack space + * has been allocated for the function's arguments + * + * This is annoyingly complex since we need to keep track of used + * registers. + */ + +void ffi_prep_args(char *stack, extended_cif *ecif) +{ + unsigned int i; + void **p_argv; + ffi_type **p_arg; + char *reg_base = stack; + char *stack_base = stack + 20; + unsigned int stack_offset = 0; + unsigned int reg_mask = 0; + + p_argv = ecif->avalue; + + /* If cif->flags is struct then we know it's not passed in registers */ + if(ecif->cif->flags == FFI_TYPE_STRUCT) + { + *(void**)reg_base = ecif->rvalue; + reg_mask |= 1; + } + + for(i = 0, p_arg = ecif->cif->arg_types; i < ecif->cif->nargs; + i++, p_arg++) + { + size_t z = (*p_arg)->size; + int alignment = (*p_arg)->alignment; + int type = (*p_arg)->type; + char *addr = 0; + + if(z % 4 != 0) + z += (4 - z % 4); + + if(reg_mask != 0x1f) + { + if(pass_struct_on_stack(*p_arg)) + { + addr = stack_base + stack_offset; + stack_offset += z; + } + else if(z == sizeof(int)) + { + char index = 0; + + while((reg_mask >> index) & 1) + index++; + + addr = reg_base + (index * 4); + reg_mask |= (1 << index); + } + else if(z == 2 * sizeof(int)) + { + if(!((reg_mask >> 1) & 1)) + { + addr = reg_base + 4; + reg_mask |= (3 << 1); + } + else if(!((reg_mask >> 3) & 1)) + { + addr = reg_base + 12; + reg_mask |= (3 << 3); + } + } + } + + if(!addr) + { + addr = stack_base + stack_offset; + stack_offset += z; + } + + if(type == FFI_TYPE_STRUCT && (*p_arg)->elements[1] == NULL) + type = (*p_arg)->elements[0]->type; + + switch(type) + { + case FFI_TYPE_UINT8: + *(unsigned int *)addr = (unsigned int)*(UINT8 *)(*p_argv); + break; + case FFI_TYPE_SINT8: + *(signed int *)addr = (signed int)*(SINT8 *)(*p_argv); + break; + case FFI_TYPE_UINT16: + *(unsigned int *)addr = (unsigned int)*(UINT16 *)(*p_argv); + break; + case FFI_TYPE_SINT16: + *(signed int *)addr = (signed int)*(SINT16 *)(*p_argv); + break; + default: + memcpy(addr, *p_argv, z); + } + + p_argv++; + } + +#ifdef DEBUG + /* Debugging */ + for(i = 0; i < 5; i++) + { + if((reg_mask & (1 << i)) == 0) + printf("r%d: (unused)\n", 12 - i); + else + printf("r%d: 0x%08x\n", 12 - i, ((unsigned int*)reg_base)[i]); + } + + for(i = 0; i < stack_offset / 4; i++) + { + printf("sp+%d: 0x%08x\n", i*4, ((unsigned int*)stack_base)[i]); + } +#endif +} + +/* Perform machine dependent cif processing */ +ffi_status ffi_prep_cif_machdep(ffi_cif *cif) +{ + /* Round the stack up to a multiple of 8 bytes. This isn't needed + * everywhere, but it is on some platforms, and it doesn't harm + * anything when it isn't needed. */ + cif->bytes = (cif->bytes + 7) & ~7; + + /* Flag to indicate that he return value is in fact a struct */ + cif->rstruct_flag = 0; + + /* Set the return type flag */ + switch(cif->rtype->type) + { + case FFI_TYPE_SINT8: + case FFI_TYPE_UINT8: + cif->flags = (unsigned)FFI_TYPE_UINT8; + break; + case FFI_TYPE_SINT16: + case FFI_TYPE_UINT16: + cif->flags = (unsigned)FFI_TYPE_UINT16; + break; + case FFI_TYPE_FLOAT: + case FFI_TYPE_SINT32: + case FFI_TYPE_UINT32: + case FFI_TYPE_POINTER: + cif->flags = (unsigned)FFI_TYPE_UINT32; + break; + case FFI_TYPE_DOUBLE: + case FFI_TYPE_SINT64: + case FFI_TYPE_UINT64: + cif->flags = (unsigned)FFI_TYPE_UINT64; + break; + case FFI_TYPE_STRUCT: + cif->rstruct_flag = 1; + if(!pass_struct_on_stack(cif->rtype)) + { + if(cif->rtype->size <= 1) + cif->flags = (unsigned)FFI_TYPE_UINT8; + else if(cif->rtype->size <= 2) + cif->flags = (unsigned)FFI_TYPE_UINT16; + else if(cif->rtype->size <= 4) + cif->flags = (unsigned)FFI_TYPE_UINT32; + else if(cif->rtype->size <= 8) + cif->flags = (unsigned)FFI_TYPE_UINT64; + else + cif->flags = (unsigned)cif->rtype->type; + } + else + cif->flags = (unsigned)cif->rtype->type; + break; + default: + cif->flags = (unsigned)cif->rtype->type; + break; + } + + return FFI_OK; +} + +void ffi_call(ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue) +{ + extended_cif ecif; + + unsigned int size = 0, i = 0; + ffi_type **p_arg; + + ecif.cif = cif; + ecif.avalue = avalue; + + for(i = 0, p_arg = cif->arg_types; i < cif->nargs; i++, p_arg++) + size += (*p_arg)->size + (4 - (*p_arg)->size % 4); + + /* If the return value is a struct and we don't have a return value + * address then we need to make one */ + + /* If cif->flags is struct then it's not suitable for registers */ + if((rvalue == NULL) && (cif->flags == FFI_TYPE_STRUCT)) + ecif.rvalue = alloca(cif->rtype->size); + else + ecif.rvalue = rvalue; + + switch(cif->abi) + { + case FFI_SYSV: + ffi_call_SYSV(ffi_prep_args, &ecif, size, cif->flags, + ecif.rvalue, cif->rstruct_flag, fn); + break; + default: + FFI_ASSERT(0); + break; + } +} + +static void ffi_prep_incoming_args_SYSV(char *stack, void **rvalue, + void **avalue, ffi_cif *cif) +{ + register unsigned int i, reg_mask = 0; + register void **p_argv; + register ffi_type **p_arg; + register char *reg_base = stack; + register char *stack_base = stack + 20; + register unsigned int stack_offset = 0; + +#ifdef DEBUG + /* Debugging */ + for(i = 0; i < cif->nargs + 7; i++) + { + printf("sp+%d: 0x%08x\n", i*4, ((unsigned int*)stack)[i]); + } +#endif + + /* If cif->flags is struct then we know it's not passed in registers */ + if(cif->flags == FFI_TYPE_STRUCT) + { + *rvalue = *(void **)reg_base; + reg_mask |= 1; + } + + p_argv = avalue; + + for(i = 0, p_arg = cif->arg_types; i < cif->nargs; i++, p_arg++) + { + size_t z = (*p_arg)->size; + int alignment = (*p_arg)->alignment; + + *p_argv = 0; + + if(z % 4 != 0) + z += (4 - z % 4); + + if(reg_mask != 0x1f) + { + if(pass_struct_on_stack(*p_arg)) + { + *p_argv = (void*)stack_base + stack_offset; + stack_offset += z; + } + else if(z <= sizeof(int)) + { + char index = 0; + + while((reg_mask >> index) & 1) + index++; + + *p_argv = (void*)reg_base + (index * 4); + reg_mask |= (1 << index); + } + else if(z == 2 * sizeof(int)) + { + if(!((reg_mask >> 1) & 1)) + { + *p_argv = (void*)reg_base + 4; + reg_mask |= (3 << 1); + } + else if(!((reg_mask >> 3) & 1)) + { + *p_argv = (void*)reg_base + 12; + reg_mask |= (3 << 3); + } + } + } + + if(!*p_argv) + { + *p_argv = (void*)stack_base + stack_offset; + stack_offset += z; + } + + if((*p_arg)->type != FFI_TYPE_STRUCT || + (*p_arg)->elements[1] == NULL) + { + if(alignment == 1) + **(unsigned int**)p_argv <<= 24; + else if(alignment == 2) + **(unsigned int**)p_argv <<= 16; + } + + p_argv++; + } + +#ifdef DEBUG + /* Debugging */ + for(i = 0; i < cif->nargs; i++) + { + printf("sp+%d: 0x%08x\n", i*4, *(((unsigned int**)avalue)[i])); + } +#endif +} + +/* This function is jumped to by the trampoline */ + +unsigned int ffi_closure_SYSV_inner(ffi_closure *closure, void **respp, + void *args) +{ + ffi_cif *cif; + void **arg_area; + unsigned int i, size = 0; + ffi_type **p_arg; + + cif = closure->cif; + + for(i = 0, p_arg = cif->arg_types; i < cif->nargs; i++, p_arg++) + size += (*p_arg)->size + (4 - (*p_arg)->size % 4); + + arg_area = (void **)alloca(size); + + /* this call will initialize ARG_AREA, such that each element in that + * array points to the corresponding value on the stack; and if the + * function returns a structure, it will re-set RESP to point to the + * structure return address. */ + + ffi_prep_incoming_args_SYSV(args, respp, arg_area, cif); + + (closure->fun)(cif, *respp, arg_area, closure->user_data); + + return cif->flags; +} + +ffi_status ffi_prep_closure_loc(ffi_closure* closure, ffi_cif* cif, + void (*fun)(ffi_cif*, void*, void**, void*), void *user_data, + void *codeloc) +{ + FFI_ASSERT(cif->abi == FFI_SYSV); + + unsigned char *__tramp = (unsigned char*)(&closure->tramp[0]); + unsigned int __fun = (unsigned int)(&ffi_closure_SYSV); + unsigned int __ctx = (unsigned int)(codeloc); + unsigned int __rstruct_flag = (unsigned int)(cif->rstruct_flag); + unsigned int __inner = (unsigned int)(&ffi_closure_SYSV_inner); + *(unsigned int*) &__tramp[0] = 0xebcd1f00; /* pushm r8-r12 */ + *(unsigned int*) &__tramp[4] = 0xfefc0010; /* ld.w r12, pc[16] */ + *(unsigned int*) &__tramp[8] = 0xfefb0010; /* ld.w r11, pc[16] */ + *(unsigned int*) &__tramp[12] = 0xfefa0010; /* ld.w r10, pc[16] */ + *(unsigned int*) &__tramp[16] = 0xfeff0010; /* ld.w pc, pc[16] */ + *(unsigned int*) &__tramp[20] = __ctx; + *(unsigned int*) &__tramp[24] = __rstruct_flag; + *(unsigned int*) &__tramp[28] = __inner; + *(unsigned int*) &__tramp[32] = __fun; + syscall(__NR_cacheflush, 0, (&__tramp[0]), 36); + + closure->cif = cif; + closure->user_data = user_data; + closure->fun = fun; + + return FFI_OK; +} + diff --git a/libffi/src/avr32/ffitarget.h b/libffi/src/avr32/ffitarget.h new file mode 100644 index 00000000000..1c799b1de72 --- /dev/null +++ b/libffi/src/avr32/ffitarget.h @@ -0,0 +1,50 @@ +/* -----------------------------------------------------------------*-C-*- + ffitarget.h - Copyright (c) 2009 Bradley Smith + Target configuration macros for AVR32. + + 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_ASM +typedef unsigned long ffi_arg; +typedef signed long ffi_sarg; + +typedef enum ffi_abi { + FFI_FIRST_ABI = 0, + FFI_SYSV, + FFI_DEFAULT_ABI = FFI_SYSV, + FFI_LAST_ABI = FFI_DEFAULT_ABI + 1 +} ffi_abi; +#endif + +#define FFI_EXTRA_CIF_FIELDS unsigned int rstruct_flag + +/* Definitions for closures */ + +#define FFI_CLOSURES 1 +#define FFI_TRAMPOLINE_SIZE 36 +#define FFI_NATIVE_RAW_API 0 + +#endif diff --git a/libffi/src/avr32/sysv.S b/libffi/src/avr32/sysv.S new file mode 100644 index 00000000000..a984b3c88a3 --- /dev/null +++ b/libffi/src/avr32/sysv.S @@ -0,0 +1,208 @@ +/* ----------------------------------------------------------------------- + sysv.S - Copyright (c) 2009 Bradley Smith + + AVR32 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 +#include + + /* r12: ffi_prep_args + * r11: &ecif + * r10: size + * r9: cif->flags + * r8: ecif.rvalue + * sp+0: cif->rstruct_flag + * sp+4: fn */ + + .text + .align 1 + .globl ffi_call_SYSV + .type ffi_call_SYSV, @function +ffi_call_SYSV: + stm --sp, r0,r1,lr + stm --sp, r8-r12 + mov r0, sp + + /* Make room for all of the new args. */ + sub sp, r10 + /* Pad to make way for potential skipped registers */ + sub sp, 20 + + /* Call ffi_prep_args(stack, &ecif). */ + /* r11 already set */ + mov r1, r12 + mov r12, sp + icall r1 + + /* Save new argument size */ + mov r1, r12 + + /* Move first 5 parameters in registers. */ + ldm sp++, r8-r12 + + /* call (fn) (...). */ + ld.w r1, r0[36] + icall r1 + + /* Remove the space we pushed for the args. */ + mov sp, r0 + + /* Load r1 with the rstruct flag. */ + ld.w r1, sp[32] + + /* Load r9 with the return type code. */ + ld.w r9, sp[12] + + /* Load r8 with the return value pointer. */ + ld.w r8, sp[16] + + /* If the return value pointer is NULL, assume no return value. */ + cp.w r8, 0 + breq .Lend + + /* Check if return type is actually a struct */ + cp.w r1, 0 + breq 1f + + /* Return 8bit */ + cp.w r9, FFI_TYPE_UINT8 + breq .Lstore8 + + /* Return 16bit */ + cp.w r9, FFI_TYPE_UINT16 + breq .Lstore16 + +1: + /* Return 32bit */ + cp.w r9, FFI_TYPE_UINT32 + breq .Lstore32 + cp.w r9, FFI_TYPE_UINT16 + breq .Lstore32 + cp.w r9, FFI_TYPE_UINT8 + breq .Lstore32 + + /* Return 64bit */ + cp.w r9, FFI_TYPE_UINT64 + breq .Lstore64 + + /* Didn't match anything */ + bral .Lend + +.Lstore64: + st.w r8[0], r11 + st.w r8[4], r10 + bral .Lend + +.Lstore32: + st.w r8[0], r12 + bral .Lend + +.Lstore16: + st.h r8[0], r12 + bral .Lend + +.Lstore8: + st.b r8[0], r12 + bral .Lend + +.Lend: + sub sp, -20 + ldm sp++, r0,r1,pc + + .size ffi_call_SYSV, . - ffi_call_SYSV + + + /* r12: __ctx + * r11: __rstruct_flag + * r10: __inner */ + + .align 1 + .globl ffi_closure_SYSV + .type ffi_closure_SYSV, @function +ffi_closure_SYSV: + stm --sp, r0,lr + mov r0, r11 + mov r8, r10 + sub r10, sp, -8 + sub sp, 12 + st.w sp[8], sp + sub r11, sp, -8 + icall r8 + + /* Check if return type is actually a struct */ + cp.w r0, 0 + breq 1f + + /* Return 8bit */ + cp.w r12, FFI_TYPE_UINT8 + breq .Lget8 + + /* Return 16bit */ + cp.w r12, FFI_TYPE_UINT16 + breq .Lget16 + +1: + /* Return 32bit */ + cp.w r12, FFI_TYPE_UINT32 + breq .Lget32 + cp.w r12, FFI_TYPE_UINT16 + breq .Lget32 + cp.w r12, FFI_TYPE_UINT8 + breq .Lget32 + + /* Return 64bit */ + cp.w r12, FFI_TYPE_UINT64 + breq .Lget64 + + /* Didn't match anything */ + bral .Lclend + +.Lget64: + ld.w r11, sp[0] + ld.w r10, sp[4] + bral .Lclend + +.Lget32: + ld.w r12, sp[0] + bral .Lclend + +.Lget16: + ld.uh r12, sp[0] + bral .Lclend + +.Lget8: + ld.ub r12, sp[0] + bral .Lclend + +.Lclend: + sub sp, -12 + ldm sp++, r0,lr + sub sp, -20 + mov pc, lr + + .size ffi_closure_SYSV, . - ffi_closure_SYSV + +#if defined __ELF__ && defined __linux__ + .section .note.GNU-stack,"",@progbits +#endif